Release 202506141856
This commit is contained in:
@@ -5,7 +5,7 @@ import { LOGS_UI_URL } from 'astro:env/server'
|
||||
|
||||
import { SUPPORT_EMAIL } from '../constants/project'
|
||||
import BaseLayout from '../layouts/BaseLayout.astro'
|
||||
import { DEPLOYMENT_MODE } from '../lib/envVariables'
|
||||
import { DEPLOYMENT_MODE } from '../lib/client/envVariables'
|
||||
import { zodParseQueryParamsStoringErrors } from '../lib/parseUrlFilters'
|
||||
|
||||
type Props = {
|
||||
|
||||
@@ -165,7 +165,7 @@ The trust score represents how reliable and trustworthy a service is, based on o
|
||||
|
||||
##### Overall Score
|
||||
|
||||
The overall score is calculated as `(privacy * 0.6) + (trust * 0.4)` and provides a combined measure of privacy and trust.
|
||||
The overall score is calculated as `(privacy * 0.6) + (trust * 0.4)` truncated. This provides a combined measure of privacy and trust.
|
||||
|
||||
#### Terms of Service Reviews
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import { makeUserWithKarmaUnlocks } from '../../lib/karmaUnlocks'
|
||||
import { prisma } from '../../lib/prisma'
|
||||
import { makeLoginUrl } from '../../lib/redirectUrls'
|
||||
import { formatDateShort } from '../../lib/timeAgo'
|
||||
import { urlDomain } from '../../lib/urls'
|
||||
|
||||
const userId = Astro.locals.user?.id
|
||||
if (!userId) {
|
||||
@@ -423,7 +424,7 @@ if (!user) return Astro.rewrite('/404')
|
||||
rel="noopener noreferrer"
|
||||
class="text-blue-400 hover:underline"
|
||||
>
|
||||
{user.verifiedLink}
|
||||
{urlDomain(user.verifiedLink)}
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
@@ -857,12 +858,7 @@ if (!user) return Astro.rewrite('/404')
|
||||
</span>
|
||||
</td>
|
||||
<td class="px-4 py-3 text-center">
|
||||
<span
|
||||
class={cn(
|
||||
'border-night-500/20 bg-night-800/10 inline-flex items-center rounded-full border px-2 py-0.5 text-xs',
|
||||
statusInfo.iconClass
|
||||
)}
|
||||
>
|
||||
<span class="border-night-500/20 bg-night-800/10 inline-flex items-center rounded-full border px-2 py-0.5 text-xs">
|
||||
<Icon name={statusInfo.icon} class="mr-1 size-3" />
|
||||
{statusInfo.label}
|
||||
</span>
|
||||
|
||||
@@ -271,7 +271,6 @@ if (toggleResult?.error) {
|
||||
label: type.label,
|
||||
value: type.value,
|
||||
icon: type.icon,
|
||||
noTransitionPersist: false,
|
||||
}))}
|
||||
cardSize="sm"
|
||||
required
|
||||
@@ -306,8 +305,8 @@ if (toggleResult?.error) {
|
||||
label="Status"
|
||||
error={createInputErrors.isActive}
|
||||
options={[
|
||||
{ label: 'Active', value: 'true', noTransitionPersist: true },
|
||||
{ label: 'Inactive', value: 'false', noTransitionPersist: true },
|
||||
{ label: 'Active', value: 'true' },
|
||||
{ label: 'Inactive', value: 'false' },
|
||||
]}
|
||||
selectedValue={newAnnouncement.isActive ? 'true' : 'false'}
|
||||
cardSize="sm"
|
||||
@@ -628,7 +627,6 @@ if (toggleResult?.error) {
|
||||
label: type.label,
|
||||
value: type.value,
|
||||
icon: type.icon,
|
||||
noTransitionPersist: true,
|
||||
}))}
|
||||
cardSize="sm"
|
||||
required
|
||||
@@ -661,8 +659,8 @@ if (toggleResult?.error) {
|
||||
name="isActive"
|
||||
label="Status"
|
||||
options={[
|
||||
{ label: 'Active', value: 'true', noTransitionPersist: true },
|
||||
{ label: 'Inactive', value: 'false', noTransitionPersist: true },
|
||||
{ label: 'Active', value: 'true' },
|
||||
{ label: 'Inactive', value: 'false' },
|
||||
]}
|
||||
selectedValue={announcement.isActive ? 'true' : 'false'}
|
||||
cardSize="sm"
|
||||
|
||||
@@ -35,7 +35,7 @@ import {
|
||||
verificationStepStatuses,
|
||||
} from '../../../../constants/verificationStepStatus'
|
||||
import BaseLayout from '../../../../layouts/BaseLayout.astro'
|
||||
import { DEPLOYMENT_MODE } from '../../../../lib/envVariables'
|
||||
import { DEPLOYMENT_MODE } from '../../../../lib/client/envVariables'
|
||||
import { listFiles } from '../../../../lib/fileStorage'
|
||||
import { makeAdminApiCallInfo } from '../../../../lib/makeAdminApiCallInfo'
|
||||
import { pluralize } from '../../../../lib/pluralize'
|
||||
@@ -441,7 +441,6 @@ const apiCalls = await Astro.locals.banners.try(
|
||||
value: kycLevel.id.toString(),
|
||||
icon: kycLevel.icon,
|
||||
description: kycLevel.description,
|
||||
noTransitionPersist: true,
|
||||
}))}
|
||||
selectedValue={service.kycLevel.toString()}
|
||||
iconSize="md"
|
||||
@@ -458,7 +457,6 @@ const apiCalls = await Astro.locals.banners.try(
|
||||
value: clarification.value,
|
||||
icon: clarification.icon,
|
||||
description: clarification.description,
|
||||
noTransitionPersist: true,
|
||||
}))}
|
||||
selectedValue={service.kycLevelClarification}
|
||||
iconSize="sm"
|
||||
@@ -475,7 +473,6 @@ const apiCalls = await Astro.locals.banners.try(
|
||||
icon: status.icon,
|
||||
iconClass: status.classNames.icon,
|
||||
description: status.description,
|
||||
noTransitionPersist: true,
|
||||
}))}
|
||||
selectedValue={service.verificationStatus}
|
||||
error={serviceInputErrors.verificationStatus}
|
||||
@@ -491,7 +488,6 @@ const apiCalls = await Astro.locals.banners.try(
|
||||
label: currency.name,
|
||||
value: currency.id,
|
||||
icon: currency.icon,
|
||||
noTransitionPersist: true,
|
||||
}))}
|
||||
selectedValue={service.acceptedCurrencies}
|
||||
error={serviceInputErrors.acceptedCurrencies}
|
||||
@@ -532,7 +528,6 @@ const apiCalls = await Astro.locals.banners.try(
|
||||
icon: visibility.icon,
|
||||
iconClass: visibility.iconClass,
|
||||
description: visibility.description,
|
||||
noTransitionPersist: true,
|
||||
}))}
|
||||
selectedValue={service.serviceVisibility}
|
||||
error={serviceInputErrors.serviceVisibility}
|
||||
|
||||
@@ -230,26 +230,22 @@ if (!user) return Astro.rewrite('/404')
|
||||
label: 'Admin',
|
||||
value: 'admin',
|
||||
icon: 'ri:shield-star-fill',
|
||||
noTransitionPersist: true,
|
||||
},
|
||||
{
|
||||
label: 'Moderator',
|
||||
value: 'moderator',
|
||||
icon: 'ri:graduation-cap-fill',
|
||||
noTransitionPersist: true,
|
||||
},
|
||||
{
|
||||
label: 'Spammer',
|
||||
value: 'spammer',
|
||||
icon: 'ri:alert-fill',
|
||||
noTransitionPersist: true,
|
||||
},
|
||||
{
|
||||
label: 'Verified',
|
||||
value: 'verified',
|
||||
icon: 'ri:verified-badge-fill',
|
||||
disabled: true,
|
||||
noTransitionPersist: true,
|
||||
},
|
||||
]}
|
||||
selectedValue={[
|
||||
@@ -434,7 +430,6 @@ if (!user) return Astro.rewrite('/404')
|
||||
label: role.label,
|
||||
value: role.value,
|
||||
icon: role.icon,
|
||||
noTransitionPersist: true,
|
||||
}))}
|
||||
required
|
||||
cardSize="sm"
|
||||
|
||||
@@ -52,6 +52,7 @@ type ServiceResponse = {
|
||||
description: string
|
||||
}
|
||||
verifiedAt: Date | null
|
||||
approvedAt: Date | null
|
||||
kycLevel: 0 | 1 | 2 | 3 | 4
|
||||
kycLevelInfo: {
|
||||
value: 0 | 1 | 2 | 3 | 4
|
||||
@@ -145,7 +146,8 @@ curl -X QUERY https://kycnot.me/api/v1/service/get \
|
||||
"labelShort": "Verified",
|
||||
"description": "Thoroughly tested and verified by the team. But things might change, this is not a guarantee."
|
||||
},
|
||||
"verifiedAt": "2025-01-20T07:12:29.393Z",
|
||||
"verifiedAt": "2025-06-14T11:02:39.294Z",
|
||||
"approvedAt": "2025-05-31T19:09:18.043Z",
|
||||
"kycLevel": 0,
|
||||
"kycLevelInfo": {
|
||||
"value": 0,
|
||||
@@ -163,7 +165,7 @@ curl -X QUERY https://kycnot.me/api/v1/service/get \
|
||||
"slug": "exchange"
|
||||
}
|
||||
],
|
||||
"listedAt": "2025-05-31T19:09:18.043Z",
|
||||
"listedAt": "2025-04-20T07:12:29.393Z",
|
||||
"serviceUrls": [
|
||||
"https://example.com",
|
||||
"http://c9ikae0fdidzh1ufrzp022e5uqfvz6ofxlkycz59cvo6fdxjgx7ekl9e.onion"
|
||||
|
||||
@@ -45,7 +45,6 @@ const [services, [dbEvents, totalEvents]] = await Astro.locals.banners.tryMany([
|
||||
async () =>
|
||||
prisma.service.findMany({
|
||||
where: {
|
||||
listedAt: { lte: new Date() },
|
||||
serviceVisibility: { in: ['PUBLIC', 'ARCHIVED'] },
|
||||
},
|
||||
select: {
|
||||
@@ -72,7 +71,6 @@ const [services, [dbEvents, totalEvents]] = await Astro.locals.banners.tryMany([
|
||||
},
|
||||
service: {
|
||||
slug: params.service ?? undefined,
|
||||
listedAt: params.service ? undefined : { lte: new Date() },
|
||||
serviceVisibility: {
|
||||
in: params.service ? ['PUBLIC', 'ARCHIVED', 'UNLISTED'] : ['PUBLIC', 'ARCHIVED'],
|
||||
},
|
||||
|
||||
@@ -219,7 +219,6 @@ const servicesQMatch = filters.q ? await findServicesBySimilarity(filters.q) : n
|
||||
|
||||
const where = {
|
||||
id: servicesQMatch ? { in: servicesQMatch.map(({ id }) => id) } : undefined,
|
||||
listedAt: { lte: new Date() },
|
||||
categories: filters.categories.length ? { some: { slug: { in: filters.categories } } } : undefined,
|
||||
verificationStatus: {
|
||||
in: includeScams ? uniq([...filters.verification, 'VERIFICATION_FAILED'] as const) : filters.verification,
|
||||
@@ -317,7 +316,6 @@ const [categories, [services, totalServices], countCommunityOnly, attributes] =
|
||||
services: {
|
||||
where: {
|
||||
serviceVisibility: { in: ['PUBLIC', 'ARCHIVED'] },
|
||||
listedAt: { lte: new Date() },
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -70,7 +70,6 @@ const [service, dbNotificationPreferences] = await Astro.locals.banners.tryMany(
|
||||
where: {
|
||||
slug,
|
||||
serviceVisibility: { in: ['PUBLIC', 'UNLISTED', 'ARCHIVED'] },
|
||||
listedAt: { lte: new Date() },
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
@@ -93,6 +92,7 @@ const [service, dbNotificationPreferences] = await Astro.locals.banners.tryMany(
|
||||
referral: true,
|
||||
imageUrl: true,
|
||||
listedAt: true,
|
||||
approvedAt: true,
|
||||
createdAt: true,
|
||||
acceptedCurrencies: true,
|
||||
tosReview: true,
|
||||
@@ -100,7 +100,7 @@ const [service, dbNotificationPreferences] = await Astro.locals.banners.tryMany(
|
||||
userSentiment: true,
|
||||
userSentimentAt: true,
|
||||
averageUserRating: true,
|
||||
isRecentlyListed: true,
|
||||
isRecentlyApproved: true,
|
||||
contactMethods: {
|
||||
select: {
|
||||
value: true,
|
||||
@@ -230,7 +230,6 @@ if (!service) {
|
||||
where: {
|
||||
previousSlugs: { has: slug },
|
||||
serviceVisibility: { in: ['PUBLIC', 'UNLISTED', 'ARCHIVED'] },
|
||||
listedAt: { lte: new Date() },
|
||||
},
|
||||
select: { slug: true },
|
||||
})
|
||||
@@ -1005,15 +1004,23 @@ const activeEventToShow =
|
||||
attribute.typeInfo.classNames.text
|
||||
)}
|
||||
>
|
||||
<Icon
|
||||
name={attribute.categoryInfo.icon}
|
||||
class={cn('mr-2 size-4 flex-shrink-0', attribute.typeInfo.classNames.icon)}
|
||||
/>
|
||||
<span>{attribute.title}</span>
|
||||
<span class="mr-auto ml-1">{attribute.title}</span>
|
||||
<>
|
||||
{weights.map((w) => (
|
||||
<span
|
||||
class={cn(
|
||||
'ml-2 text-center text-sm',
|
||||
w.value === 0 ? 'text-current/30' : 'text-current/60'
|
||||
)}
|
||||
>
|
||||
{formatNumber(w.value, w.formatOptions)}
|
||||
</span>
|
||||
))}
|
||||
</>
|
||||
<Icon
|
||||
name="ri:arrow-down-s-line"
|
||||
class={cn(
|
||||
'ml-auto size-5 group-open/attribute:rotate-180',
|
||||
'ml-1 size-5 group-open/attribute:rotate-180',
|
||||
attribute.typeInfo.classNames.icon
|
||||
)}
|
||||
/>
|
||||
@@ -1080,19 +1087,16 @@ const activeEventToShow =
|
||||
baseScoreType.classNames.text
|
||||
)}
|
||||
>
|
||||
<Icon
|
||||
name={baseScoreType.icon}
|
||||
class={cn('mr-2 size-4 flex-shrink-0', baseScoreType.classNames.icon)}
|
||||
/>
|
||||
<span class="font-title">{baseScoreType.label}</span>
|
||||
<span class={cn('mr-1 ml-auto', baseScoreType.classNames.icon)}>+50</span>
|
||||
<span class="font-title mr-auto ml-1">{baseScoreType.label}</span>
|
||||
<span class="mr-2 text-current/60">+50</span>
|
||||
<span class="mr-1 text-current/60">+50</span>
|
||||
</li>
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
|
||||
<p class="text-day-400 mt-3 text-center text-xs">
|
||||
<span class="hover:text-day-200 transition-colors">Overall = 60% Privacy + 40% Trust (Rounded)</span>
|
||||
<span class="hover:text-day-200 transition-colors">Overall = 60% Privacy + 40% Trust (Truncated)</span>
|
||||
</p>
|
||||
<div class="xs:gap-x-6 mt-2 flex flex-wrap justify-center gap-x-4 gap-y-2 text-xs">
|
||||
<a
|
||||
|
||||
@@ -25,6 +25,7 @@ import { makeUserWithKarmaUnlocks } from '../../lib/karmaUnlocks'
|
||||
import { prisma } from '../../lib/prisma'
|
||||
import { KYCNOTME_SCHEMA_MINI } from '../../lib/schema'
|
||||
import { formatDateShort } from '../../lib/timeAgo'
|
||||
import { urlDomain } from '../../lib/urls'
|
||||
|
||||
import type { ProfilePage, WithContext } from 'schema-dts'
|
||||
|
||||
@@ -96,9 +97,6 @@ const user = await Astro.locals.banners.try('user', async () => {
|
||||
},
|
||||
where: {
|
||||
service: {
|
||||
listedAt: {
|
||||
lte: new Date(),
|
||||
},
|
||||
serviceVisibility: {
|
||||
in: ['PUBLIC', 'ARCHIVED'],
|
||||
},
|
||||
@@ -511,7 +509,7 @@ const isCurrentUser = !!Astro.locals.user && user.id === Astro.locals.user.id
|
||||
rel="noopener noreferrer"
|
||||
class="text-blue-400 hover:underline"
|
||||
>
|
||||
{user.verifiedLink}
|
||||
{urlDomain(user.verifiedLink)}
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
@@ -975,12 +973,7 @@ const isCurrentUser = !!Astro.locals.user && user.id === Astro.locals.user.id
|
||||
</span>
|
||||
</td>
|
||||
<td class="px-4 py-3 text-center">
|
||||
<span
|
||||
class={cn(
|
||||
'border-night-500/20 bg-night-800/10 inline-flex items-center rounded-full border px-2 py-0.5 text-xs',
|
||||
statusInfo.iconClass
|
||||
)}
|
||||
>
|
||||
<span class="border-night-500/20 bg-night-800/10 inline-flex items-center rounded-full border px-2 py-0.5 text-xs">
|
||||
<Icon name={statusInfo.icon} class="mr-1 size-3" />
|
||||
{statusInfo.label}
|
||||
</span>
|
||||
|
||||
Reference in New Issue
Block a user