From 86b857b8d4f6440c4b4f7ec10075e512fb8f6455 Mon Sep 17 00:00:00 2001 From: ekzyis Date: Mon, 3 Jun 2024 11:26:19 -0500 Subject: [PATCH] Allow SN users to edit special items forever (#1204) * Allow SN users to edit special items * Refactor item edit validation * Create object for user IDs * Remove anon from SN_USER_IDS * Fix isMine and myBio checks * Don't update author * remove anon from trust graph --------- Co-authored-by: keyan --- api/resolvers/image.js | 4 +-- api/resolvers/item.js | 44 ++++++++++++++++++++---------- api/resolvers/rewards.js | 4 +-- api/resolvers/upload.js | 4 +-- api/resolvers/user.js | 6 ++-- api/resolvers/wallet.js | 6 ++-- components/client-notifications.js | 4 +-- components/comment.js | 6 ++-- components/hat.js | 6 ++-- components/item-info.js | 4 +-- components/item.js | 8 +++--- components/nav/common.js | 4 +-- lib/constants.js | 19 ++++++++----- lib/webPush.js | 4 +-- worker/deleteUnusedImages.js | 4 +-- worker/trust.js | 4 +-- 16 files changed, 75 insertions(+), 56 deletions(-) diff --git a/api/resolvers/image.js b/api/resolvers/image.js index d27a3eb5..c8382edc 100644 --- a/api/resolvers/image.js +++ b/api/resolvers/image.js @@ -1,4 +1,4 @@ -import { ANON_USER_ID, AWS_S3_URL_REGEXP } from '@/lib/constants' +import { USER_ID, AWS_S3_URL_REGEXP } from '@/lib/constants' import { msatsToSats } from '@/lib/format' export default { @@ -17,7 +17,7 @@ export function uploadIdsFromText (text, { models }) { export async function imageFeesInfo (s3Keys, { models, me }) { // returns info object in this format: // { bytes24h: int, bytesUnpaid: int, nUnpaid: int, imageFeeMsats: BigInt } - const [info] = await models.$queryRawUnsafe('SELECT * FROM image_fees_info($1::INTEGER, $2::INTEGER[])', me ? me.id : ANON_USER_ID, s3Keys) + const [info] = await models.$queryRawUnsafe('SELECT * FROM image_fees_info($1::INTEGER, $2::INTEGER[])', me ? me.id : USER_ID.anon, s3Keys) const imageFee = msatsToSats(info.imageFeeMsats) const totalFeesMsats = info.nUnpaid * Number(info.imageFeeMsats) const totalFees = msatsToSats(totalFeesMsats) diff --git a/api/resolvers/item.js b/api/resolvers/item.js index f4a97c12..ac67353a 100644 --- a/api/resolvers/item.js +++ b/api/resolvers/item.js @@ -8,8 +8,8 @@ import domino from 'domino' import { ITEM_SPAM_INTERVAL, ITEM_FILTER_THRESHOLD, COMMENT_DEPTH_LIMIT, COMMENT_TYPE_QUERY, - ANON_USER_ID, ANON_ITEM_SPAM_INTERVAL, POLL_COST, - ITEM_ALLOW_EDITS, GLOBAL_SEED, ANON_FEE_MULTIPLIER, NOFOLLOW_LIMIT, UNKNOWN_LINK_REL + USER_ID, ANON_ITEM_SPAM_INTERVAL, POLL_COST, + ITEM_ALLOW_EDITS, GLOBAL_SEED, ANON_FEE_MULTIPLIER, NOFOLLOW_LIMIT, UNKNOWN_LINK_REL, SN_USER_IDS } from '@/lib/constants' import { msatsToSats } from '@/lib/format' import { parse } from 'tldts' @@ -876,7 +876,7 @@ export default { models.$queryRaw` SELECT item_act(${Number(id)}::INTEGER, - ${me?.id || ANON_USER_ID}::INTEGER, ${act}::"ItemActType", ${Number(sats)}::INTEGER)`, + ${me?.id || USER_ID.anon}::INTEGER, ${act}::"ItemActType", ${Number(sats)}::INTEGER)`, { models, lnd, me, hash, hmac, fee: sats } ) } @@ -1157,7 +1157,7 @@ export default { return parent.otsHash }, deleteScheduledAt: async (item, args, { me, models }) => { - const meId = me?.id ?? ANON_USER_ID + const meId = me?.id ?? USER_ID.anon if (meId !== item.userId) { // Only query for deleteScheduledAt for your own items to keep DB queries minimized return null @@ -1166,8 +1166,8 @@ export default { return deleteJobs[0]?.startafter ?? null }, reminderScheduledAt: async (item, args, { me, models }) => { - const meId = me?.id ?? ANON_USER_ID - if (meId !== item.userId || meId === ANON_USER_ID) { + const meId = me?.id ?? USER_ID.anon + if (meId !== item.userId || meId === USER_ID.anon) { // don't show reminders on an item if it isn't yours // don't support reminders for ANON return null @@ -1227,10 +1227,21 @@ export const createMentions = async (item, models) => { export const updateItem = async (parent, { sub: subName, forward, options, ...item }, { me, models, lnd, hash, hmac }) => { // update iff this item belongs to me const old = await models.item.findUnique({ where: { id: Number(item.id) }, include: { sub: true } }) - if (Number(old.userId) !== Number(me?.id)) { + + // author can always edit their own item + const mid = Number(me?.id) + const isMine = Number(old.userId) === mid + + // allow admins to edit special items + const allowEdit = ITEM_ALLOW_EDITS.includes(old.id) + const adminEdit = SN_USER_IDS.includes(mid) && allowEdit + + if (!isMine && !adminEdit) { throw new GraphQLError('item does not belong to you', { extensions: { code: 'FORBIDDEN' } }) } - if (subName && old.subName !== subName) { + + const differentSub = subName && old.subName !== subName + if (differentSub) { const sub = await models.sub.findUnique({ where: { name: subName } }) if (old.freebie) { if (!sub.allowFreebies) { @@ -1244,10 +1255,13 @@ export const updateItem = async (parent, { sub: subName, forward, options, ...it // in case they lied about their existing boost await ssValidate(advSchema, { boost: item.boost }, { models, me, existingBoost: old.boost }) - // prevent update if it's not explicitly allowed, not their bio, not their job and older than 10 minutes const user = await models.user.findUnique({ where: { id: me.id } }) - if (!ITEM_ALLOW_EDITS.includes(old.id) && user.bioId !== old.id && - !isJob(item) && Date.now() > new Date(old.createdAt).getTime() + 10 * 60000) { + + // prevent update if it's not explicitly allowed, not their bio, not their job and older than 10 minutes + const myBio = user.bioId === old.id + const timer = Date.now() < new Date(old.createdAt).getTime() + 10 * 60_000 + + if (!allowEdit && !myBio && !timer) { throw new GraphQLError('item can no longer be editted', { extensions: { code: 'BAD_INPUT' } }) } @@ -1266,7 +1280,7 @@ export const updateItem = async (parent, { sub: subName, forward, options, ...it } } - item = { subName, userId: me.id, ...item } + item = { subName, userId: old.userId, ...item } const fwdUsers = await getForwardUsers(models, forward) const uploadIds = uploadIdsFromText(item.text, { models }) @@ -1303,7 +1317,7 @@ export const createItem = async (parent, { forward, options, ...item }, { me, mo item.subName = item.sub delete item.sub - item.userId = me ? Number(me.id) : ANON_USER_ID + item.userId = me ? Number(me.id) : USER_ID.anon const fwdUsers = await getForwardUsers(models, forward) if (item.url && !isJob(item)) { @@ -1367,7 +1381,7 @@ const enqueueDeletionJob = async (item, models) => { } const deleteReminderAndJob = async ({ me, item, models }) => { - if (me?.id && me.id !== ANON_USER_ID) { + if (me?.id && me.id !== USER_ID.anon) { await models.$transaction([ models.$queryRawUnsafe(` DELETE FROM pgboss.job @@ -1389,7 +1403,7 @@ const deleteReminderAndJob = async ({ me, item, models }) => { const createReminderAndJob = async ({ me, item, models }) => { // disallow anon to use reminder - if (!me || me.id === ANON_USER_ID) { + if (!me || me.id === USER_ID.anon) { return } const reminderCommand = getReminderCommand(item.text) diff --git a/api/resolvers/rewards.js b/api/resolvers/rewards.js index 8d701010..a16d10e2 100644 --- a/api/resolvers/rewards.js +++ b/api/resolvers/rewards.js @@ -1,7 +1,7 @@ import { GraphQLError } from 'graphql' import { amountSchema, ssValidate } from '@/lib/validate' import serialize from './serial' -import { ANON_USER_ID } from '@/lib/constants' +import { USER_ID } from '@/lib/constants' import { getItem } from './item' import { topUsers } from './user' @@ -165,7 +165,7 @@ export default { await ssValidate(amountSchema, { amount: sats }) await serialize( - models.$queryRaw`SELECT donate(${sats}::INTEGER, ${me?.id || ANON_USER_ID}::INTEGER)`, + models.$queryRaw`SELECT donate(${sats}::INTEGER, ${me?.id || USER_ID.anon}::INTEGER)`, { models, lnd, me, hash, hmac, fee: sats } ) diff --git a/api/resolvers/upload.js b/api/resolvers/upload.js index 4aecaabb..fc2699ef 100644 --- a/api/resolvers/upload.js +++ b/api/resolvers/upload.js @@ -1,5 +1,5 @@ import { GraphQLError } from 'graphql' -import { ANON_USER_ID, IMAGE_PIXELS_MAX, UPLOAD_SIZE_MAX, UPLOAD_SIZE_MAX_AVATAR, UPLOAD_TYPES_ALLOW } from '@/lib/constants' +import { USER_ID, IMAGE_PIXELS_MAX, UPLOAD_SIZE_MAX, UPLOAD_SIZE_MAX_AVATAR, UPLOAD_TYPES_ALLOW } from '@/lib/constants' import { createPresignedPost } from '@/api/s3' export default { @@ -26,7 +26,7 @@ export default { size, width, height, - userId: me?.id || ANON_USER_ID, + userId: me?.id || USER_ID.anon, paid: false } diff --git a/api/resolvers/user.js b/api/resolvers/user.js index 632dc1af..0dccafb1 100644 --- a/api/resolvers/user.js +++ b/api/resolvers/user.js @@ -5,7 +5,7 @@ import { decodeCursor, LIMIT, nextCursorEncoded } from '@/lib/cursor' import { msatsToSats } from '@/lib/format' import { bioSchema, emailSchema, settingsSchema, ssValidate, userSchema } from '@/lib/validate' import { getItem, updateItem, filterClause, createItem, whereClause, muteClause } from './item' -import { ANON_USER_ID, DELETE_USER_ID, RESERVED_MAX_USER_ID, SN_NO_REWARDS_IDS } from '@/lib/constants' +import { USER_ID, RESERVED_MAX_USER_ID, SN_NO_REWARDS_IDS } from '@/lib/constants' import { viewGroup } from './growth' import { timeUnitForRange, whenRange } from '@/lib/time' import assertApiKeyNotPermitted from './apiKey' @@ -217,7 +217,7 @@ export default { SELECT name FROM users WHERE ( - id > ${RESERVED_MAX_USER_ID} OR id IN (${ANON_USER_ID}, ${DELETE_USER_ID}) + id > ${RESERVED_MAX_USER_ID} OR id IN (${USER_ID.anon}, ${USER_ID.delete}) ) AND SIMILARITY(name, ${q}) > 0.1 ORDER BY SIMILARITY(name, ${q}) DESC @@ -518,7 +518,7 @@ export default { return await models.$queryRaw` SELECT * FROM users - WHERE (id > ${RESERVED_MAX_USER_ID} OR id IN (${ANON_USER_ID}, ${DELETE_USER_ID})) + WHERE (id > ${RESERVED_MAX_USER_ID} OR id IN (${USER_ID.anon}, ${USER_ID.delete})) AND SIMILARITY(name, ${q}) > ${Number(similarity) || 0.1} ORDER BY SIMILARITY(name, ${q}) DESC LIMIT ${Number(limit) || 5}` }, userStatsActions: async (parent, { when, from, to }, { me, models }) => { diff --git a/api/resolvers/wallet.js b/api/resolvers/wallet.js index 7780b28f..153bf3ce 100644 --- a/api/resolvers/wallet.js +++ b/api/resolvers/wallet.js @@ -7,7 +7,7 @@ import { SELECT } from './item' import { lnAddrOptions } from '@/lib/lnurl' import { msatsToSats, msatsToSatsDecimal, ensureB64 } from '@/lib/format' import { CLNAutowithdrawSchema, LNDAutowithdrawSchema, amountSchema, lnAddrAutowithdrawSchema, lnAddrSchema, ssValidate, withdrawlSchema } from '@/lib/validate' -import { ANON_BALANCE_LIMIT_MSATS, ANON_INV_PENDING_LIMIT, ANON_USER_ID, BALANCE_LIMIT_MSATS, INVOICE_RETENTION_DAYS, INV_PENDING_LIMIT, USER_IDS_BALANCE_NO_LIMIT, Wallet } from '@/lib/constants' +import { ANON_BALANCE_LIMIT_MSATS, ANON_INV_PENDING_LIMIT, USER_ID, BALANCE_LIMIT_MSATS, INVOICE_RETENTION_DAYS, INV_PENDING_LIMIT, USER_IDS_BALANCE_NO_LIMIT, Wallet } from '@/lib/constants' import { datePivot } from '@/lib/time' import assertGofacYourself from './ofac' import assertApiKeyNotPermitted from './apiKey' @@ -28,7 +28,7 @@ export async function getInvoice (parent, { id }, { me, models, lnd }) { throw new GraphQLError('invoice not found', { extensions: { code: 'BAD_INPUT' } }) } - if (inv.user.id === ANON_USER_ID) { + if (inv.user.id === USER_ID.anon) { return inv } if (!me) { @@ -339,7 +339,7 @@ export default { expirePivot = { seconds: Math.min(expireSecs, 180) } invLimit = ANON_INV_PENDING_LIMIT balanceLimit = ANON_BALANCE_LIMIT_MSATS - id = ANON_USER_ID + id = USER_ID.anon } const user = await models.user.findUnique({ where: { id } }) diff --git a/components/client-notifications.js b/components/client-notifications.js index a806253a..b81ffe5a 100644 --- a/components/client-notifications.js +++ b/components/client-notifications.js @@ -2,7 +2,7 @@ import { useApolloClient } from '@apollo/client' import { useMe } from './me' import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react' import { datePivot, timeSince } from '@/lib/time' -import { ANON_USER_ID, JIT_INVOICE_TIMEOUT_MS } from '@/lib/constants' +import { USER_ID, JIT_INVOICE_TIMEOUT_MS } from '@/lib/constants' import { HAS_NOTIFICATIONS } from '@/fragments/notifications' import Item from './item' import { RootProvider } from './root' @@ -25,7 +25,7 @@ export function ClientNotificationProvider ({ children }) { const me = useMe() // anons don't have access to /notifications // but we'll store client notifications anyway for simplicity's sake - const storageKey = `client-notifications:${me?.id || ANON_USER_ID}` + const storageKey = `client-notifications:${me?.id || USER_ID.anon}` useEffect(() => { const loaded = loadNotifications(storageKey, client) diff --git a/components/comment.js b/components/comment.js index ac362e6b..7cd079f8 100644 --- a/components/comment.js +++ b/components/comment.js @@ -9,7 +9,7 @@ import Eye from '@/svgs/eye-fill.svg' import EyeClose from '@/svgs/eye-close-line.svg' import { useRouter } from 'next/router' import CommentEdit from './comment-edit' -import { ANON_USER_ID, COMMENT_DEPTH_LIMIT, UNKNOWN_LINK_REL } from '@/lib/constants' +import { USER_ID, COMMENT_DEPTH_LIMIT, UNKNOWN_LINK_REL } from '@/lib/constants' import PayBounty from './pay-bounty' import BountyIcon from '@/svgs/bounty-bag.svg' import ActionTooltip from './action-tooltip' @@ -128,9 +128,9 @@ export default function Comment ({ const bottomedOut = depth === COMMENT_DEPTH_LIMIT // Don't show OP badge when anon user comments on anon user posts - const op = root.user.name === item.user.name && Number(item.user.id) !== ANON_USER_ID + const op = root.user.name === item.user.name && Number(item.user.id) !== USER_ID.anon ? 'OP' - : root.forwards?.some(f => f.user.name === item.user.name) && Number(item.user.id) !== ANON_USER_ID + : root.forwards?.some(f => f.user.name === item.user.name) && Number(item.user.id) !== USER_ID.anon ? 'fwd' : null const bountyPaid = root.bountyPaidTo?.includes(Number(item.id)) diff --git a/components/hat.js b/components/hat.js index 8db6f250..1fc14e40 100644 --- a/components/hat.js +++ b/components/hat.js @@ -4,11 +4,11 @@ import Tooltip from 'react-bootstrap/Tooltip' import CowboyHatIcon from '@/svgs/cowboy.svg' import AnonIcon from '@/svgs/spy-fill.svg' import { numWithUnits } from '@/lib/format' -import { AD_USER_ID, ANON_USER_ID } from '@/lib/constants' +import { USER_ID } from '@/lib/constants' export default function Hat ({ user, badge, className = 'ms-1', height = 16, width = 16 }) { - if (!user || Number(user.id) === AD_USER_ID) return null - if (Number(user.id) === ANON_USER_ID) { + if (!user || Number(user.id) === USER_ID.ad) return null + if (Number(user.id) === USER_ID.anon) { return ( {badge diff --git a/components/item-info.js b/components/item-info.js index 430edac4..5167dc41 100644 --- a/components/item-info.js +++ b/components/item-info.js @@ -15,7 +15,7 @@ import BookmarkDropdownItem from './bookmark' import SubscribeDropdownItem from './subscribe' import { CopyLinkDropdownItem, CrosspostDropdownItem } from './share' import Hat from './hat' -import { AD_USER_ID } from '@/lib/constants' +import { USER_ID } from '@/lib/constants' import ActionDropdown from './action-dropdown' import MuteDropdownItem from './mute' import { DropdownItemUpVote } from './upvote' @@ -58,7 +58,7 @@ export default function ItemInfo ({ return (
- {!(item.position && (pinnable || !item.subName)) && !(!item.parentId && Number(item.user?.id) === AD_USER_ID) && + {!(item.position && (pinnable || !item.subName)) && !(!item.parentId && Number(item.user?.id) === USER_ID.ad) && <> : item.meDontLikeSats > item.meSats ? - : Number(item.user?.id) === AD_USER_ID + : Number(item.user?.id) === USER_ID.ad ? : }
@@ -99,7 +99,7 @@ export default function Item ({ item, rank, belowTitle, right, full, children, s full={full} item={item} onQuoteReply={onQuoteReply} pinnable={pinnable} - extraBadges={Number(item?.user?.id) === AD_USER_ID && AD} + extraBadges={Number(item?.user?.id) === USER_ID.ad && AD} /> {belowTitle}
@@ -130,7 +130,7 @@ export function ItemSummary ({ item }) { item={item} showUser={false} showActionDropdown={false} - extraBadges={item.title && Number(item?.user?.id) === AD_USER_ID && AD} + extraBadges={item.title && Number(item?.user?.id) === USER_ID.ad && AD} /> ) diff --git a/components/nav/common.js b/components/nav/common.js index 8be6dfa6..5116658d 100644 --- a/components/nav/common.js +++ b/components/nav/common.js @@ -6,7 +6,7 @@ import BackArrow from '../../svgs/arrow-left-line.svg' import { useCallback, useEffect, useState } from 'react' import Price from '../price' import SubSelect from '../sub-select' -import { ANON_USER_ID, BALANCE_LIMIT_MSATS, Wallet } from '../../lib/constants' +import { USER_ID, BALANCE_LIMIT_MSATS, Wallet } from '../../lib/constants' import Head from 'next/head' import NoteIcon from '../../svgs/notification-4-fill.svg' import { useMe } from '../me' @@ -307,7 +307,7 @@ export function AnonDropdown ({ path }) { - @anon + @anon diff --git a/lib/constants.js b/lib/constants.js index 6e640ecb..6b13cd72 100644 --- a/lib/constants.js +++ b/lib/constants.js @@ -36,8 +36,16 @@ export const ITEM_SPAM_INTERVAL = '10m' export const ANON_ITEM_SPAM_INTERVAL = '0' export const INV_PENDING_LIMIT = 100 export const BALANCE_LIMIT_MSATS = 100000000 // 100k sat -export const SN_USER_IDS = [616, 6030, 4502, 27] -export const SN_NO_REWARDS_IDS = [27, 4502] +export const USER_ID = { + k00b: 616, + ek: 6030, + sn: 4502, + anon: 27, + ad: 9, + delete: 106 +} +export const SN_USER_IDS = [USER_ID.k00b, USER_ID.ek, USER_ID.sn] +export const SN_NO_REWARDS_IDS = [USER_ID.anon, USER_ID.sn] export const ANON_INV_PENDING_LIMIT = 1000 export const ANON_BALANCE_LIMIT_MSATS = 0 // disable export const MAX_POLL_NUM_CHOICES = 10 @@ -54,17 +62,14 @@ export const ITEM_TYPES_USER = ['all', 'posts', 'comments', 'bounties', 'links', export const ITEM_TYPES = ['all', 'posts', 'comments', 'bounties', 'links', 'discussions', 'polls', 'freebies', 'bios', 'jobs'] export const ITEM_TYPES_UNIVERSAL = ['all', 'posts', 'comments', 'freebies'] export const OLD_ITEM_DAYS = 3 -export const ANON_USER_ID = 27 -export const DELETE_USER_ID = 106 -export const AD_USER_ID = 9 export const ANON_FEE_MULTIPLIER = 100 export const SSR = typeof window === 'undefined' export const MAX_FORWARDS = 5 export const LNURLP_COMMENT_MAX_LENGTH = 1000 export const RESERVED_MAX_USER_ID = 615 -export const GLOBAL_SEED = 616 +export const GLOBAL_SEED = USER_ID.k00b export const FREEBIE_BASE_COST_THRESHOLD = 10 -export const USER_IDS_BALANCE_NO_LIMIT = [...SN_USER_IDS, AD_USER_ID] +export const USER_IDS_BALANCE_NO_LIMIT = [...SN_USER_IDS, USER_ID.anon, USER_ID.ad] // WIP ultimately subject to this list: https://ofac.treasury.gov/sanctions-programs-and-country-information // From lawyers: north korea, cuba, iran, ukraine, syria diff --git a/lib/webPush.js b/lib/webPush.js index edbb919d..0b4344cb 100644 --- a/lib/webPush.js +++ b/lib/webPush.js @@ -1,6 +1,6 @@ import webPush from 'web-push' import removeMd from 'remove-markdown' -import { ANON_USER_ID, COMMENT_DEPTH_LIMIT, FOUND_BLURBS, LOST_BLURBS } from './constants' +import { USER_ID, COMMENT_DEPTH_LIMIT, FOUND_BLURBS, LOST_BLURBS } from './constants' import { msatsToSats, numWithUnits } from './format' import models from '@/api/models' import { isMuted } from '@/lib/user' @@ -179,7 +179,7 @@ export const notifyTerritorySubscribers = async ({ models, item }) => { export const notifyItemParents = async ({ models, item, me }) => { try { - const user = await models.user.findUnique({ where: { id: me?.id || ANON_USER_ID } }) + const user = await models.user.findUnique({ where: { id: me?.id || USER_ID.anon } }) const parents = await models.$queryRawUnsafe( 'SELECT DISTINCT p."userId" FROM "Item" i JOIN "Item" p ON p.path @> i.path WHERE i.id = $1 and p."userId" <> $2 ' + 'AND NOT EXISTS (SELECT 1 FROM "Mute" m WHERE m."muterId" = p."userId" AND m."mutedId" = $2)', diff --git a/worker/deleteUnusedImages.js b/worker/deleteUnusedImages.js index 19133c8c..13563d59 100644 --- a/worker/deleteUnusedImages.js +++ b/worker/deleteUnusedImages.js @@ -1,5 +1,5 @@ import { deleteObjects } from '@/api/s3' -import { ANON_USER_ID } from '@/lib/constants' +import { USER_ID } from '@/lib/constants' export async function deleteUnusedImages ({ models }) { // delete all images in database and S3 which weren't paid in the last 24 hours @@ -14,7 +14,7 @@ export async function deleteUnusedImages ({ models }) { AND NOT EXISTS (SELECT * FROM users WHERE "photoId" = "Upload".id) AND NOT EXISTS (SELECT * FROM "Item" WHERE "uploadId" = "Upload".id) )) - AND created_at < date_trunc('hour', now() - CASE WHEN "userId" = ${ANON_USER_ID} THEN interval '1 hour' ELSE interval '24 hours' END)` + AND created_at < date_trunc('hour', now() - CASE WHEN "userId" = ${USER_ID.anon} THEN interval '1 hour' ELSE interval '24 hours' END)` const s3Keys = unpaidImages.map(({ id }) => id) if (s3Keys.length === 0) { diff --git a/worker/trust.js b/worker/trust.js index 44c85f3d..51fa83c8 100644 --- a/worker/trust.js +++ b/worker/trust.js @@ -1,5 +1,5 @@ import * as math from 'mathjs' -import { ANON_USER_ID, SN_USER_IDS } from '@/lib/constants.js' +import { USER_ID, SN_USER_IDS } from '@/lib/constants.js' export async function trust ({ boss, models }) { try { @@ -127,7 +127,7 @@ async function getGraph (models) { FROM "ItemAct" JOIN "Item" ON "Item".id = "ItemAct"."itemId" AND "ItemAct".act IN ('FEE', 'TIP', 'DONT_LIKE_THIS') AND "Item"."parentId" IS NULL AND NOT "Item".bio AND "Item"."userId" <> "ItemAct"."userId" - JOIN users ON "ItemAct"."userId" = users.id AND users.id <> ${ANON_USER_ID} + JOIN users ON "ItemAct"."userId" = users.id AND users.id <> ${USER_ID.anon} GROUP BY user_id, name, item_id, user_at, against HAVING CASE WHEN "ItemAct".act = 'DONT_LIKE_THIS' THEN sum("ItemAct".msats) > ${AGAINST_MSAT_MIN}