From d60b29eb257b7935b8481505946eda4d4180da06 Mon Sep 17 00:00:00 2001 From: lucas Date: Sat, 25 Apr 2026 22:35:38 -0300 Subject: [PATCH 1/4] Upgrade mongoose version to 9.5.* --- bot/commands.ts | 62 ++++++++------- bot/messages.ts | 42 +++++----- bot/modules/block/commands.ts | 4 +- bot/modules/community/commands.ts | 16 ++-- bot/modules/community/messages.ts | 24 +++--- bot/modules/community/scenes.ts | 16 ++-- bot/modules/dispute/actions.ts | 6 +- bot/modules/dispute/commands.ts | 20 ++--- bot/modules/nostr/events.ts | 2 +- bot/modules/orders/commands.ts | 2 +- bot/modules/orders/messages.ts | 10 +-- bot/modules/orders/scenes.ts | 2 +- bot/modules/orders/takeOrder.ts | 4 +- bot/ordersActions.ts | 12 +-- bot/scenes.ts | 4 +- bot/start.ts | 36 ++++----- bot/validations.ts | 31 ++++---- db_connect.ts | 5 +- jobs/pending_payments.ts | 30 +++---- models/community.ts | 12 +-- models/order.ts | 2 +- models/user.ts | 4 +- package-lock.json | 127 ++++++++++++++---------------- package.json | 4 +- tsconfig.json | 1 + util/communityHelper.ts | 2 +- util/index.ts | 8 +- 27 files changed, 239 insertions(+), 249 deletions(-) diff --git a/bot/commands.ts b/bot/commands.ts index c64478b7..eb70d46f 100644 --- a/bot/commands.ts +++ b/bot/commands.ts @@ -1,3 +1,5 @@ +import mongoose from 'mongoose'; +const { ObjectId } = mongoose.Types; import { validateFiatSentOrder, validateReleaseOrder } from './validations'; import { createHoldInvoice, @@ -41,7 +43,7 @@ const setCooperativeCancelFlag = async ( const update = { [propName]: true }; return await Order.findOneAndUpdate( { - _id: orderId, + _id: new ObjectId(orderId), [propName]: { $ne: true }, status: { $in: ['ACTIVE', 'FIAT_SENT', 'DISPUTE'] }, }, @@ -62,7 +64,7 @@ const waitPayment = async ( // If there is not fiat amount the function don't do anything if (order.fiat_amount === undefined) { logger.debug( - `waitPayment: fiat_amount === undefined, User Id ${ctx.user.id} order Id: ${order.id}`, + `waitPayment: fiat_amount === undefined, User Id ${ctx.user._id.toString()} order Id: ${order._id.toString()}`, ); return; } @@ -87,7 +89,7 @@ const waitPayment = async ( // We create a hold invoice const description = i18nCtx.t('hold_invoice_memo', { botName: ctx.botInfo.username, - orderId: order._id, + orderId: order._id.toString(), fiatCode: order.fiat_code, fiatAmount: order.fiat_amount, }); @@ -137,7 +139,7 @@ const addInvoice = async ( if (!order) { const orderId = (ctx.update as any).callback_query.message.text; if (!orderId) return; - order = await Order.findOne({ _id: orderId }); + order = await Order.findOne({ _id: new ObjectId(orderId) }); if (!order) return; } @@ -146,7 +148,7 @@ const addInvoice = async ( return; } - const buyer = await User.findOne({ _id: order.buyer_id }); + const buyer = await User.findOne({ _id: new ObjectId(order.buyer_id!) }); if (buyer === null) throw new Error('buyer was not found'); if (order.fiat_amount === undefined) { @@ -175,7 +177,7 @@ const addInvoice = async ( return; } await order.save(); - const seller = await User.findOne({ _id: order.seller_id }); + const seller = await User.findOne({ _id: new ObjectId(order.seller_id!) }); if (seller === null) throw new Error('seller was not found'); if (buyer.lightning_address) { @@ -228,12 +230,12 @@ const rateUser = async ( const callerId = ctx.from?.id; if (!orderId) return; - const order = await Order.findOne({ _id: orderId }); + const order = await Order.findOne({ _id: new ObjectId(orderId) }); if (order === null) return; - const buyer = await User.findOne({ _id: order.buyer_id }); + const buyer = await User.findOne({ _id: new ObjectId(order.buyer_id!) }); if (buyer === null) throw new Error('buyer was not found'); - const seller = await User.findOne({ _id: order.seller_id }); + const seller = await User.findOne({ _id: new ObjectId(order.seller_id!) }); if (seller === null) throw new Error('seller was not found'); let targetUser = buyer; @@ -300,7 +302,7 @@ const cancelAddInvoice = async ( const orderId = !!ctx && (ctx.update as any).callback_query.message.text; if (!orderId) return; - order = await Order.findOne({ _id: orderId }); + order = await Order.findOne({ _id: new ObjectId(orderId) }); } } if (order === null) return; @@ -310,7 +312,7 @@ const cancelAddInvoice = async ( await cancelHoldInvoice({ hash: order.hash }); } - const user = await User.findOne({ _id: order.buyer_id }); + const user = await User.findOne({ _id: new ObjectId(order.buyer_id!) }); if (user == null) return; @@ -319,9 +321,9 @@ const cancelAddInvoice = async ( if (order.status !== 'WAITING_BUYER_INVOICE') return await messages.genericErrorMessage(ctx, user, i18nCtx); - const sellerUser = await User.findOne({ _id: order.seller_id }); + const sellerUser = await User.findOne({ _id: new ObjectId(order.seller_id!) }); if (sellerUser === null) throw new Error('sellerUser was not found'); - const buyerUser = await User.findOne({ _id: order.buyer_id }); + const buyerUser = await User.findOne({ _id: new ObjectId(order.buyer_id!) }); if (buyerUser === null) throw new Error('buyerUser was not found'); const sellerTgId = sellerUser.tg_id; // If order creator cancels it, it will not be republished @@ -413,11 +415,11 @@ const showHoldInvoice = async ( if (!order) { const orderId = (ctx.update as any).callback_query?.message?.text; if (!orderId) return; - order = await Order.findOne({ _id: orderId }); + order = await Order.findOne({ _id: new ObjectId(orderId) }); if (order === null || order === undefined) return; } - const user = await User.findOne({ _id: order.seller_id }); + const user = await User.findOne({ _id: new ObjectId(order.seller_id!) }); if (!user) return; if (order.status !== 'WAITING_PAYMENT') { @@ -507,7 +509,7 @@ const cancelShowHoldInvoice = async ( const orderId = !!ctx && (ctx.update as any).callback_query.message.text; if (!orderId) return; - order = await Order.findOne({ _id: orderId }); + order = await Order.findOne({ _id: new ObjectId(orderId) }); } } if (order === null) return; @@ -516,9 +518,9 @@ const cancelShowHoldInvoice = async ( if (order.hash) { await cancelHoldInvoice({ hash: order.hash }); } - const buyerUser = await User.findOne({ _id: order.buyer_id }); + const buyerUser = await User.findOne({ _id: new ObjectId(order.buyer_id!) }); if (buyerUser === null) throw new Error('buyerUser was not found'); - const sellerUser = await User.findOne({ _id: order.seller_id }); + const sellerUser = await User.findOne({ _id: new ObjectId(order.seller_id!) }); if (sellerUser === null) throw new Error('sellerUser was not found'); const i18nCtxSeller = await getUserI18nContext(sellerUser); @@ -646,12 +648,12 @@ const addInvoicePHI = async ( ) => { try { ctx.deleteMessage(); - const order = await Order.findOne({ _id: orderId }); + const order = await Order.findOne({ _id: new ObjectId(orderId) }); if (order === null) throw new Error('order was not found'); // only orders with status PAID_HOLD_INVOICE are released payments if (order.status !== 'PAID_HOLD_INVOICE') return; - const buyer = await User.findOne({ _id: order.buyer_id }); + const buyer = await User.findOne({ _id: new ObjectId(order.buyer_id!) }); if (buyer === null) return; if (order.amount === 0) { await messages.genericErrorMessage(bot, buyer, ctx.i18n); @@ -680,7 +682,7 @@ const cancelOrder = async ( if (!user) return; } if (user.banned) return await messages.bannedUserErrorMessage(ctx, user); - const order = await ordersActions.getOrder(ctx, user, orderId); + const order = await ordersActions.getOrder(ctx, user, new ObjectId(orderId) as any); if (!order) return; @@ -689,7 +691,7 @@ const cancelOrder = async ( if (order.hash) await cancelHoldInvoice({ hash: order.hash }); order.status = 'CANCELED'; - order.canceled_by = user._id; + order.canceled_by = user._id.toString(); await order.save(); OrderEvents.orderUpdated(order); // we sent a private message to the user @@ -737,16 +739,16 @@ const cancelOrder = async ( const initiatorUser = user; if (initiatorUser._id.toString() === order.buyer_id?.toString()) { - counterPartyUser = await User.findOne({ _id: order.seller_id }); + counterPartyUser = await User.findOne({ _id: new ObjectId(order.seller_id!) }); initiator = UserOrderRole.BUYER; } else { - counterPartyUser = await User.findOne({ _id: order.buyer_id }); + counterPartyUser = await User.findOne({ _id: new ObjectId(order.buyer_id!) }); initiator = UserOrderRole.SELLER; } if (counterPartyUser == null) throw new Error('counterPartyUser was not found'); - const updateOrder = await setCooperativeCancelFlag(order._id, initiator); + const updateOrder = await setCooperativeCancelFlag(new ObjectId(order._id) as any, initiator); // If the call returns null, the flag was already set (or order is missing), // so we treat it as a duplicate request. @@ -768,12 +770,12 @@ const cancelOrder = async ( if (updateOrder.hash) await cancelHoldInvoice({ hash: updateOrder.hash }); updateOrder.status = 'CANCELED'; - updateOrder.canceled_by = String(user._id); + updateOrder.canceled_by = user._id.toString(); await updateOrder.save(); let seller = initiatorUser; let i18nCtxSeller = ctx.i18n; - if (order.seller_id == counterPartyUser._id) { + if (order.seller_id?.toString() == counterPartyUser._id.toString()) { seller = counterPartyUser; i18nCtxSeller = i18nCtxCP; } @@ -830,7 +832,7 @@ const fiatSent = async ( if (!order) return; order.status = 'FIAT_SENT'; - const seller = await User.findOne({ _id: order.seller_id }); + const seller = await User.findOne({ _id: new ObjectId(order.seller_id!) }); if (seller === null) throw new Error('seller was not found'); await order.save(); // We sent messages to both parties @@ -868,7 +870,7 @@ const release = async ( const order = await validateReleaseOrder(ctx, user, orderId); if (!order) return; // We look for a dispute for this order - const dispute = await Dispute.findOne({ order_id: order._id }); + const dispute = await Dispute.findOne({ order_id: order._id.toString() }); if (dispute) { dispute.status = 'RELEASED'; @@ -900,7 +902,7 @@ const showQrCode = async ( if (!user) return; } if (user.banned) return await messages.bannedUserErrorMessage(ctx, user); - const order = await ordersActions.getOrder(ctx, user, orderId); + const order = await ordersActions.getOrder(ctx, user, new ObjectId(orderId) as any); if (!order) return; if (!order.hash) return; diff --git a/bot/messages.ts b/bot/messages.ts index 00011d13..418d539d 100644 --- a/bot/messages.ts +++ b/bot/messages.ts @@ -1,3 +1,5 @@ +import mongoose from 'mongoose'; +const { ObjectId } = mongoose.Types; import { TelegramError, Telegraf } from 'telegraf'; import { getCurrency, @@ -101,7 +103,7 @@ const invoicePaymentRequestMessage = async ( parse_mode: 'Markdown', }); - await ctx.telegram.sendMessage(user.tg_id, order._id, { + await ctx.telegram.sendMessage(user.tg_id, order._id.toString(), { reply_markup: { inline_keyboard: [ [ @@ -184,7 +186,7 @@ const pendingSellMessage = async ( await ctx.telegram.sendMessage( user.tg_id, - i18n.t('cancel_order_cmd', { orderId: order._id }), + i18n.t('cancel_order_cmd', { orderId: order._id.toString() }), { parse_mode: 'Markdown' }, ); @@ -221,7 +223,7 @@ const pendingBuyMessage = async ( ); await bot.telegram.sendMessage( user.tg_id, - i18n.t('cancel_order_cmd', { orderId: order._id }), + i18n.t('cancel_order_cmd', { orderId: order._id.toString() }), { parse_mode: 'MarkdownV2' }, ); } catch (error) { @@ -289,7 +291,7 @@ const expiredInvoiceOnPendingMessage = async ( await bot.telegram.sendMessage(user.tg_id, i18n.t('invoice_expired_long')); await bot.telegram.sendMessage( user.tg_id, - i18n.t('setinvoice_cmd_order', { orderId: order._id }), + i18n.t('setinvoice_cmd_order', { orderId: order._id.toString() }), { parse_mode: 'MarkdownV2' }, ); } catch (error) { @@ -447,7 +449,7 @@ const beginTakeBuyMessage = async ( }, ]); - await bot.telegram.sendMessage(seller.tg_id, order._id, { + await bot.telegram.sendMessage(seller.tg_id, order._id.toString(), { reply_markup: { inline_keyboard: [ [ @@ -552,7 +554,7 @@ const onGoingTakeBuyMessage = async ( days: ageInDays, }), ); - await bot.telegram.sendMessage(buyer.tg_id, order._id, { + await bot.telegram.sendMessage(buyer.tg_id, order._id.toString(), { reply_markup: { inline_keyboard: [ [{ text: i18nBuyer.t('continue'), callback_data: 'addInvoiceBtn' }], @@ -584,7 +586,7 @@ const beginTakeSellMessage = async ( ctx.i18n.t('you_took_someone_order', { expirationTime }), { parse_mode: 'MarkdownV2' }, ); - await bot.telegram.sendMessage(buyer.tg_id, order._id, { + await bot.telegram.sendMessage(buyer.tg_id, order._id.toString(), { reply_markup: { inline_keyboard: [ [ @@ -614,7 +616,7 @@ const onGoingTakeSellMessage = async ( await bot.telegram.sendMessage( buyerUser.tg_id, i18nBuyer.t('get_in_touch_with_seller', { - orderId: order.id, + orderId: order._id.toString(), currency: order.fiat_code, sellerUsername: sellerUser.username, fiatAmount: numberFormat(order.fiat_code, order.fiat_amount!), @@ -629,7 +631,7 @@ const onGoingTakeSellMessage = async ( await bot.telegram.sendMessage( sellerUser.tg_id, i18nSeller.t('buyer_took_your_order', { - orderId: order.id, + orderId: order._id.toString(), fiatAmount: order.fiat_amount, paymentMethod: order.payment_method, currency: order.fiat_code, @@ -650,7 +652,7 @@ const takeSellWaitingSellerToPayMessage = async ( try { await bot.telegram.sendMessage( buyerUser.tg_id, - ctx.i18n.t('waiting_seller_to_pay', { orderId: order._id }), + ctx.i18n.t('waiting_seller_to_pay', { orderId: order._id.toString() }), ); } catch (error) { logger.error(error); @@ -737,7 +739,7 @@ const publishBuyOrderMessage = async ( ) => { try { let publishMessage = `⚡️🍊⚡️\n${order.description}\n`; - publishMessage += `:${order._id}:`; + publishMessage += `:${order._id.toString()}:`; const channel = await getOrderChannel(order); if (channel === undefined) throw new Error('channel is undefined'); @@ -745,13 +747,13 @@ const publishBuyOrderMessage = async ( // Get the community language if available let communityI18n = i18n; if (order.community_id) { - const community = await Community.findOne({ _id: order.community_id }); + const community = await Community.findOne({ _id: new ObjectId(order.community_id!) }); if (community && community.language) { communityI18n = new I18n({ defaultLanguageOnMissing: true, - locale: community.language, + defaultLanguage: community.language, directory: 'locales', - }).createContext(community.language); + }).createContext(community.language, {}); } } @@ -790,7 +792,7 @@ const publishSellOrderMessage = async ( ) => { try { let publishMessage = `⚡️🍊⚡️\n${order.description}\n`; - publishMessage += `:${order._id}:`; + publishMessage += `:${order._id.toString()}:`; const channel = await getOrderChannel(order); if (channel === undefined) throw new Error('channel is undefined'); @@ -798,13 +800,13 @@ const publishSellOrderMessage = async ( let communityI18n = i18n; if (order.community_id) { - const community = await Community.findOne({ _id: order.community_id }); + const community = await Community.findOne({ _id: new ObjectId(order.community_id!) }); if (community && community.language) { communityI18n = new I18n({ defaultLanguageOnMissing: true, - locale: community.language, + defaultLanguage: community.language, directory: 'locales', - }).createContext(community.language); + }).createContext(community.language, {}); } } @@ -1079,7 +1081,7 @@ const addInvoiceMessage = async ( await bot.telegram.sendMessage( buyer.tg_id, ctx.i18n.t('get_in_touch_with_seller', { - orderId: order.id, + orderId: order._id.toString(), currency: order.fiat_code, sellerUsername: seller.username, fiatAmount: numberFormat(order.fiat_code, order.fiat_amount!), @@ -1108,7 +1110,7 @@ const sendBuyerInfo2SellerMessage = async ( seller.tg_id, i18n.t('get_in_touch_with_buyer', { currency: order.fiat_code, - orderId: order.id, + orderId: order._id.toString(), buyerUsername: buyer.username, fiatAmount: numberFormat(order.fiat_code, order.fiat_amount!), paymentMethod: order.payment_method, diff --git a/bot/modules/block/commands.ts b/bot/modules/block/commands.ts index 5afeeb44..800dd96c 100644 --- a/bot/modules/block/commands.ts +++ b/bot/modules/block/commands.ts @@ -24,8 +24,8 @@ const block = async (ctx: MainContext, usernameOrId: string): Promise => { const areExistingOrders = await Order.exists({ $or: [ - { seller_id: user.id, buyer_id: userToBlock.id }, - { seller_id: userToBlock.id, buyer_id: user.id }, + { seller_id: user._id.toString(), buyer_id: userToBlock._id.toString() }, + { seller_id: userToBlock._id.toString(), buyer_id: user._id.toString() }, ], status: { $nin: [ diff --git a/bot/modules/community/commands.ts b/bot/modules/community/commands.ts index 1170cbd1..a6afa21e 100644 --- a/bot/modules/community/commands.ts +++ b/bot/modules/community/commands.ts @@ -7,7 +7,7 @@ import { MainContext } from '../../start'; import { CommunityContext } from './communityContext'; import { Telegraf } from 'telegraf'; -async function getOrderCountByCommunity(): Promise { +async function getOrderCountByCommunity(): Promise> { const data = await Order.aggregate([ { $group: { _id: '$community_id', total: { $count: {} } } }, ]); @@ -25,7 +25,7 @@ async function findCommunities(currency: string) { const orderCount = await getOrderCountByCommunity(); return communities.map(comm => { const plainCommunity = comm.toObject(); - plainCommunity.orders = orderCount[comm.id] || 0; + plainCommunity.orders = orderCount[comm._id.toString()] || 0; return plainCommunity; }); } @@ -57,7 +57,7 @@ export const setComm = async (ctx: MainContext) => { return await ctx.reply(ctx.i18n.t('community_not_found')); } - user.default_community_id = community._id; + user.default_community_id = community._id.toString(); await user.save(); await ctx.reply(ctx.i18n.t('operation_successful')); @@ -69,7 +69,7 @@ export const setComm = async (ctx: MainContext) => { export const communityAdmin = async (ctx: CommunityContext) => { try { const [group] = (await validateParams(ctx, 2, '\\<_community_\\>'))!; - const creator_id = ctx.user.id; + const creator_id = ctx.user._id.toString(); const [community] = await Community.find({ group, creator_id }); if (!community) throw new Error('CommunityNotFound'); await ctx.scene.enter('COMMUNITY_ADMIN', { community }); @@ -89,7 +89,7 @@ export const myComms = async (ctx: MainContext) => { try { const { user } = ctx; - const communities = await Community.find({ creator_id: user._id }); + const communities = await Community.find({ creator_id: user._id.toString() }); if (!communities.length) return await ctx.reply(ctx.i18n.t('you_dont_have_communities')); @@ -146,7 +146,7 @@ export const updateCommunity = async ( if (!(await validateObjectId(ctx, id))) return; const community = await Community.findOne({ _id: id, - creator_id: user._id, + creator_id: user._id.toString(), }); if (!community) { @@ -221,7 +221,7 @@ export const deleteCommunity = async (ctx: CommunityContext) => { if (!(await validateObjectId(ctx, id))) return; const community = await Community.findOne({ _id: id, - creator_id: ctx.user._id, + creator_id: ctx.user._id.toString(), }); if (!community) { @@ -244,7 +244,7 @@ export const changeVisibility = async (ctx: CommunityContext) => { if (!(await validateObjectId(ctx, id))) return; const community = await Community.findOne({ _id: id, - creator_id: ctx.user._id, + creator_id: ctx.user._id.toString(), }); if (!community) { diff --git a/bot/modules/community/messages.ts b/bot/modules/community/messages.ts index 37be5e97..d8f35cab 100644 --- a/bot/modules/community/messages.ts +++ b/bot/modules/community/messages.ts @@ -131,7 +131,7 @@ export const listCommunitiesMessage = async ( try { let message = ''; communities.forEach(community => { - message += `ID: #${community.id}\n`; + message += `ID: #${community._id.toString()}\n`; message += ctx.i18n.t('name') + `: ${community.name}\n`; message += ctx.i18n.t('group') + `: ${community.group}\n`; community.order_channels.forEach(channel => { @@ -158,7 +158,7 @@ export const earningsMessage = async (ctx: MainContext) => { // We check if there is a payment scheduled for this community const isScheduled = await PendingPayment.findOne({ community_id: communityId, - attempts: { $lt: process.env.PAYMENT_ATTEMPTS }, + attempts: { $lt: Number(process.env.PAYMENT_ATTEMPTS) }, paid: false, }); if (isScheduled) @@ -169,17 +169,17 @@ export const earningsMessage = async (ctx: MainContext) => { const button = community.earnings > 0 ? { - reply_markup: { - inline_keyboard: [ - [ - { - text: ctx.i18n.t('withdraw_earnings'), - callback_data: `withdrawEarnings_${community._id}`, - }, - ], + reply_markup: { + inline_keyboard: [ + [ + { + text: ctx.i18n.t('withdraw_earnings'), + callback_data: `withdrawEarnings_${community._id}`, + }, ], - }, - } + ], + }, + } : undefined; await ctx.reply( ctx.i18n.t('current_earnings', { diff --git a/bot/modules/community/scenes.ts b/bot/modules/community/scenes.ts index b320a13d..6122eff1 100644 --- a/bot/modules/community/scenes.ts +++ b/bot/modules/community/scenes.ts @@ -81,7 +81,7 @@ export const communityWizard = new Scenes.WizardScene( fee, solvers, dispute_channel: disputeChannel, - creator_id: user._id, + creator_id: user._id.toString(), }); await community.save(); await ctx.reply( @@ -394,7 +394,7 @@ const createCommunitySteps = { const user = await User.findOne({ username }); if (user) { solvers.push({ - id: user._id, + id: user._id.toString(), username: user.username, } as IUsernameId); } @@ -745,7 +745,7 @@ export const updateSolversCommunityWizard = new Scenes.WizardScene( if (user == null) throw new Error('user not found'); if (user) { solvers.push({ - id: user._id, + id: user._id.toString(), username: user.username, } as IUsernameId); botUsers.push(username); @@ -945,8 +945,8 @@ export const addEarningsInvoiceWizard = new Scenes.WizardScene( return await ctx.reply(ctx.i18n.t('invoice_with_incorrect_amount')); const isScheduled = await PendingPayment.findOne({ - community_id: community._id, - attempts: { $lt: process.env.PAYMENT_ATTEMPTS }, + community_id: community._id.toString(), + attempts: { $lt: Number(process.env.PAYMENT_ATTEMPTS) }, paid: false, }); // We check if the payment is on flight @@ -957,12 +957,12 @@ export const addEarningsInvoiceWizard = new Scenes.WizardScene( const user = await User.findById(community.creator_id); if (user === null) throw new Error('user was not found'); - logger.debug(`Creating pending payment for community ${community.id}`); + logger.debug(`Creating pending payment for community ${community._id.toString()}`); const pp = new PendingPayment({ amount: community.earnings, payment_request: lnInvoice, - user_id: user.id, - community_id: community._id, + user_id: user._id.toString(), + community_id: community._id.toString(), description: `Retiro por admin @${user.username}`, hash: res.invoice.hash, }); diff --git a/bot/modules/dispute/actions.ts b/bot/modules/dispute/actions.ts index 7738fac3..37d15391 100644 --- a/bot/modules/dispute/actions.ts +++ b/bot/modules/dispute/actions.ts @@ -35,13 +35,13 @@ export const takeDispute = async (ctx: MainContext): Promise => { if (seller === null) throw new Error('seller not found'); const initiator = order.buyer_dispute ? 'buyer' : 'seller'; const buyerDisputes = await Dispute.countDocuments({ - $or: [{ buyer_id: buyer._id }, { seller_id: buyer._id }], + $or: [{ buyer_id: buyer._id.toString() }, { seller_id: buyer._id.toString() }], }); const sellerDisputes = await Dispute.countDocuments({ - $or: [{ buyer_id: seller._id }, { seller_id: seller._id }], + $or: [{ buyer_id: seller._id.toString() }, { seller_id: seller._id.toString() }], }); - dispute.solver_id = solver.id; + dispute.solver_id = solver._id.toString(); dispute.status = 'IN_PROGRESS'; await dispute.save(); await messages.disputeData( diff --git a/bot/modules/dispute/commands.ts b/bot/modules/dispute/commands.ts index 708419ee..9d87d1a1 100644 --- a/bot/modules/dispute/commands.ts +++ b/bot/modules/dispute/commands.ts @@ -35,7 +35,7 @@ export const handleDispute = async (ctx: MainContext, orderId: string) => { const seller = await User.findOne({ _id: order.seller_id }); if (seller === null) throw new Error('seller was not found'); let initiator: 'seller' | 'buyer' = 'seller'; - if (user._id == order.buyer_id) initiator = 'buyer'; + if (user._id.toString() == order.buyer_id) initiator = 'buyer'; order.previous_dispute_status = order.status; if (initiator === 'seller') order.seller_dispute = true; @@ -53,11 +53,11 @@ export const handleDispute = async (ctx: MainContext, orderId: string) => { // If a user disputes is equal to MAX_DISPUTES, we ban the user const buyerDisputes = (await Dispute.countDocuments({ - $or: [{ buyer_id: buyer._id }, { seller_id: buyer._id }], + $or: [{ buyer_id: buyer._id.toString() }, { seller_id: buyer._id.toString() }], })) + 1; const sellerDisputes = (await Dispute.countDocuments({ - $or: [{ buyer_id: seller._id }, { seller_id: seller._id }], + $or: [{ buyer_id: seller._id.toString() }, { seller_id: seller._id.toString() }], })) + 1; const maxDisputes = Number(process.env.MAX_DISPUTES); // if MAX_DISPUTES is not specified or can't be parsed as number, following @@ -74,18 +74,18 @@ export const handleDispute = async (ctx: MainContext, orderId: string) => { const dispute = new Dispute({ initiator, - seller_id: seller._id, - buyer_id: buyer._id, + seller_id: seller._id.toString(), + buyer_id: buyer._id.toString(), community_id: order.community_id, status: 'WAITING_FOR_SOLVER', - order_id: order._id, + order_id: order._id.toString(), }); await dispute.save(); // Send message to both users await messages.beginDispute(ctx, initiator, order, buyer, seller); // Show the dispute button to solvers await messages.takeDisputeButton(ctx, order); - logger.warning(`Order ${order.id}: User ${user.id} started a dispute!`); + logger.warning(`Order ${order._id.toString()}: User ${user._id.toString()} started a dispute!`); } catch (error) { logger.error(error); } @@ -164,13 +164,13 @@ const deleteDispute = async (ctx: MainContext) => { // We check if this dispute is from a community we validate that // the solver is running this command - if (dispute && dispute.solver_id != admin._id) { + if (dispute && dispute.solver_id != admin._id.toString()) { return await globalMessages.notAuthorized(ctx); } } - if (user._id == dispute.buyer_id) dispute.buyer_id = null; - if (user._id == dispute.seller_id) dispute.seller_id = null; + if (user._id.toString() == dispute.buyer_id) dispute.buyer_id = null; + if (user._id.toString() == dispute.seller_id) dispute.seller_id = null; await dispute.save(); await ctx.reply(ctx.i18n.t('operation_successful')); diff --git a/bot/modules/nostr/events.ts b/bot/modules/nostr/events.ts index 5f3674be..5563e479 100644 --- a/bot/modules/nostr/events.ts +++ b/bot/modules/nostr/events.ts @@ -38,7 +38,7 @@ const orderToTags = async (order: IOrder) => { const channel = removeAtSymbol(channelEnvVar); let source = `https://t.me/${channel}/${order.tg_channel_message1}`; const tags = []; - tags.push(['d', order.id]); + tags.push(['d', order._id.toString()]); tags.push(['k', order.type]); tags.push(['f', order.fiat_code]); tags.push(['s', toKebabCase(order.status)]); diff --git a/bot/modules/orders/commands.ts b/bot/modules/orders/commands.ts index 75a9d385..b2e69d6b 100644 --- a/bot/modules/orders/commands.ts +++ b/bot/modules/orders/commands.ts @@ -217,7 +217,7 @@ async function enterWizard( const isMaxPending = async (user: UserDocument) => { const pendingOrders = await Order.countDocuments({ - creator_id: user._id, + creator_id: user._id.toString(), status: 'PENDING', }); const maxPendingOrders = process.env.MAX_PENDING_ORDERS; diff --git a/bot/modules/orders/messages.ts b/bot/modules/orders/messages.ts index db849102..c38831a5 100644 --- a/bot/modules/orders/messages.ts +++ b/bot/modules/orders/messages.ts @@ -22,16 +22,16 @@ export const listOrdersResponse = async ( typeof order.fiat_amount !== 'undefined' ? sanitizeMD(order.fiat_amount) : [ - sanitizeMD(order.min_amount), - ' \\- ', - sanitizeMD(order.max_amount), - ].join(''); + sanitizeMD(order.min_amount), + ' \\- ', + sanitizeMD(order.max_amount), + ].join(''); if (typeof order.amount !== 'undefined') amount = String(order.amount); const timeToExpire = getTimeToExpirationOrder(order, i18n); const details = [ [''].join(''), - ['`Id `: ', '`', order.id, '`'].join(''), + ['`Id `: ', '`', order._id.toString(), '`'].join(''), ['`Status `: ', '`', status, '`'].join(''), ['`Sats amt`: ', '`', amount, '`'].join(''), ['`Fiat amt`: ', '`', fiatAmount, '`'].join(''), diff --git a/bot/modules/orders/scenes.ts b/bot/modules/orders/scenes.ts index e7db533e..83b50fc0 100644 --- a/bot/modules/orders/scenes.ts +++ b/bot/modules/orders/scenes.ts @@ -75,7 +75,7 @@ export const createOrder = new Scenes.WizardScene( paymentMethod, status: 'PENDING', priceMargin, - community_id: community && community.id, + community_id: community && community._id.toString(), }); if (order) { const publishFn = diff --git a/bot/modules/orders/takeOrder.ts b/bot/modules/orders/takeOrder.ts index 51b28d4b..98fae49f 100644 --- a/bot/modules/orders/takeOrder.ts +++ b/bot/modules/orders/takeOrder.ts @@ -80,7 +80,7 @@ export const takebuy = async ( ); order.status = 'WAITING_PAYMENT'; - order.seller_id = user._id; + order.seller_id = user._id.toString(); order.taken_at = new Date(Date.now()); order.random_image = randomImage; @@ -132,7 +132,7 @@ export const takesell = async ( return await messages.bannedUserErrorMessage(ctx, user); if (!(await validateTakeSellOrder(ctx, bot, user, order))) return; order.status = 'WAITING_BUYER_INVOICE'; - order.buyer_id = user._id; + order.buyer_id = user._id.toString(); order.taken_at = new Date(Date.now()); await order.save(); diff --git a/bot/ordersActions.ts b/bot/ordersActions.ts index aa71f919..c1422795 100644 --- a/bot/ordersActions.ts +++ b/bot/ordersActions.ts @@ -135,7 +135,7 @@ const createOrder = async ( bot_fee: isGoldenHoneyBadgerOrder ? 0 : botFee, is_golden_honey_badger: isGoldenHoneyBadgerOrder, community_fee: communityFee, - creator_id: user._id, + creator_id: user._id.toString(), type, status, fiat_code: fiatCode, @@ -164,12 +164,12 @@ const createOrder = async ( let order; if (type === 'sell') { order = new Order({ - seller_id: user._id, + seller_id: user._id.toString(), ...baseOrderData, }); } else { order = new Order({ - buyer_id: user._id, + buyer_id: user._id.toString(), ...baseOrderData, }); } @@ -309,7 +309,7 @@ const getOrder = async ( const where = { _id: orderId, - $or: [{ seller_id: user._id }, { buyer_id: user._id }], + $or: [{ seller_id: user._id.toString() }, { buyer_id: user._id.toString() }], }; const order = await Order.findOne(where).exec(); @@ -330,7 +330,7 @@ const getOrders = async (user: UserDocument, status?: string) => { const where: any = { $and: [ { - $or: [{ buyer_id: user._id }, { seller_id: user._id }], + $or: [{ buyer_id: user._id.toString() }, { seller_id: user._id.toString() }], }, ], }; @@ -377,7 +377,7 @@ const getNewRangeOrderPayload = async (order: IOrder) => { paymentMethod: order.payment_method, status: 'PENDING', priceMargin: order.price_margin, - range_parent_id: order._id, + range_parent_id: order._id.toString(), tgChatId: order.tg_chat_id, tgOrderMessage: order.tg_order_message, community_id: order.community_id, diff --git a/bot/scenes.ts b/bot/scenes.ts index 6db6e7b2..80814fc2 100644 --- a/bot/scenes.ts +++ b/bot/scenes.ts @@ -145,8 +145,8 @@ const addInvoicePHIWizard = new Scenes.WizardScene( return await messages.incorrectAmountInvoiceMessage(ctx); const isScheduled = await PendingPayment.findOne({ - order_id: order._id, - attempts: { $lt: process.env.PAYMENT_ATTEMPTS }, + order_id: order._id.toString(), + attempts: { $lt: Number(process.env.PAYMENT_ATTEMPTS) }, is_invoice_expired: false, }); // We check if the payment is on flight diff --git a/bot/start.ts b/bot/start.ts index 53e2b8f9..331bc330 100644 --- a/bot/start.ts +++ b/bot/start.ts @@ -3,7 +3,8 @@ import { Telegraf, session, Context, Telegram } from 'telegraf'; import { I18n, I18nContext } from '@grammyjs/i18n'; import { Message } from 'typegram'; import { UserDocument } from '../models/user'; -import { FilterQuery } from 'mongoose'; +import mongoose from 'mongoose'; +const { ObjectId } = mongoose.Types; import * as OrderEvents from './modules/events/orders'; import { limit } from '@grammyjs/ratelimiter'; import schedule from 'node-schedule'; @@ -99,7 +100,7 @@ const askForConfirmation = async (user: UserDocument, command: string) => { try { let orders: any[] = []; if (command === '/cancel') { - const where: FilterQuery = { + const where: any = { $and: [ { $or: [{ buyer_id: user._id }, { seller_id: user._id }] }, { @@ -114,12 +115,12 @@ const askForConfirmation = async (user: UserDocument, command: string) => { }; orders = await Order.find(where); } else if (command === '/fiatsent') { - const where: FilterQuery = { + const where: any = { $and: [{ buyer_id: user._id }, { status: 'ACTIVE' }], }; orders = await Order.find(where); } else if (command === '/release') { - const where: FilterQuery = { + const where: any = { $and: [ { seller_id: user._id }, { @@ -133,7 +134,7 @@ const askForConfirmation = async (user: UserDocument, command: string) => { }; orders = await Order.find(where); } else if (command === '/setinvoice') { - const where: FilterQuery = { + const where: any = { buyer_id: user._id, status: { $in: ['PAID_HOLD_INVOICE', 'WAITING_BUYER_INVOICE'] }, }; @@ -352,7 +353,7 @@ const initialize = ( order.is_frozen = true; order.status = 'FROZEN'; - order.action_by = ctx.admin._id; + order.action_by = ctx.admin._id.toString(); await order.save(); if (order.secret) await settleHoldInvoice({ secret: order.secret }); @@ -380,7 +381,7 @@ const initialize = ( if (order === null) return; // We look for a dispute for this order - const dispute = await Dispute.findOne({ order_id: order._id }); + const dispute = await Dispute.findOne({ order_id: order._id.toString() }); // We check if this is a solver, the order must be from the same community if (!ctx.admin.admin) { @@ -400,7 +401,7 @@ const initialize = ( // We check if this dispute is from a community we validate that // the solver is running this command - if (dispute && dispute.solver_id != ctx.admin._id) { + if (dispute && dispute.solver_id != ctx.admin._id.toString()) { logger.debug( `cancelorder ${order._id}: @${ctx.admin.username} is not the solver of this dispute`, ); @@ -418,7 +419,7 @@ const initialize = ( logger.info(`order ${order._id}: cancelled by admin`); order.status = 'CANCELED_BY_ADMIN'; - order.canceled_by = ctx.admin._id; + order.canceled_by = ctx.admin._id.toString(); await order.save(); order.status = 'CANCELED'; OrderEvents.orderUpdated(order); @@ -501,7 +502,7 @@ const initialize = ( } order.status = 'CANCELED'; - order.canceled_by = ctx.user.id; + order.canceled_by = ctx.user._id.toString(); await order.save(); OrderEvents.orderUpdated(order); // We delete the messages related to that order from the channel @@ -530,7 +531,7 @@ const initialize = ( } // We look for a dispute for this order - const dispute = await Dispute.findOne({ order_id: order._id }); + const dispute = await Dispute.findOne({ order_id: order._id.toString() }); // We check if this is a solver, the order must be from the same community if (!ctx.admin.admin) { @@ -544,7 +545,7 @@ const initialize = ( // We check if this dispute is from a community we validate that // the solver is running this command - if (dispute && dispute.solver_id != ctx.admin.id) { + if (dispute && dispute.solver_id != ctx.admin._id.toString()) { return await messages.notAuthorized(ctx); } } @@ -733,8 +734,8 @@ const initialize = ( ); if (community === null) throw Error('Community was not found in DB'); community.banned_users.push({ - id: user._id, - username: user.username, + id: user._id.toString(), + username: user.username || '', }); await community.save(); } else { @@ -777,8 +778,7 @@ const initialize = ( ); if (community === null) throw Error('Community was not found in DB'); community.banned_users = community.banned_users - .toObject() - .filter((el: IUsernameId) => el.id !== user.id.toString()); + .filter((el: IUsernameId) => el.id !== user._id.toString()); await community.save(); } else { return await ctx.reply(ctx.i18n.t('need_default_community')); @@ -1015,8 +1015,8 @@ const initialize = ( // We make sure the buyers invoice is not being paid const isPending = await PendingPayment.findOne({ - order_id: order._id, - attempts: { $lt: process.env.PAYMENT_ATTEMPTS }, + order_id: order._id.toString(), + attempts: { $lt: Number(process.env.PAYMENT_ATTEMPTS) }, }); if (isPending) return; diff --git a/bot/validations.ts b/bot/validations.ts index 7ee42bbb..05b63987 100644 --- a/bot/validations.ts +++ b/bot/validations.ts @@ -5,7 +5,8 @@ import { ctxUpdateAssertMsg, } from './start'; import { IUsernameId } from '../models/community'; -import { FilterQuery } from 'mongoose'; +import mongoose from 'mongoose'; +const { ObjectId } = mongoose.Types; import { UserDocument } from '../models/user'; import { IOrder } from '../models/order'; // @ts-ignore @@ -21,7 +22,7 @@ import { import { existLightningAddress } from '../lnurl/lnurl-pay'; import { logger } from '../logger'; -const { ObjectId } = require('mongoose').Types; +// Removed redundant ObjectId declaration const ctxUpdateMessageFromAssertMsg = 'ctx.update.message.from is not available'; @@ -44,7 +45,7 @@ const validateUser = async (ctx: MainContext, start: boolean) => { return false; } - let user = await User.findOne({ tg_id: tgUser.id }); + let user = await User.findOne({ tg_id: String(tgUser.id) }); if (!user && start) { user = new User({ @@ -111,7 +112,7 @@ const validateAdmin = async (ctx: MainContext, id?: string) => { let community = null; if (user.default_community_id) - community = await Community.findOne({ _id: user.default_community_id }); + community = await Community.findOne({ _id: new ObjectId(user.default_community_id) }); const isSolver = isDisputeSolver(community, user); @@ -519,10 +520,10 @@ const validateReleaseOrder = async ( orderId: string, ) => { try { - let where: FilterQuery = { + let where: any = { seller_id: user._id, status: 'WAITING_BUYER_INVOICE', - _id: orderId, + _id: new ObjectId(orderId), }; let order = await Order.findOne(where); if (order) { @@ -544,7 +545,7 @@ const validateReleaseOrder = async ( }; if (orderId) { - where._id = orderId; + where._id = new ObjectId(orderId); } order = await Order.findOne(where); @@ -568,9 +569,9 @@ const validateDisputeOrder = async ( try { const where = { $and: [ - { _id: orderId }, + { _id: new ObjectId(orderId) }, { $or: [{ status: 'ACTIVE' }, { status: 'FIAT_SENT' }] }, - { $or: [{ seller_id: user._id }, { buyer_id: user._id }] }, + { $or: [{ seller_id: user._id.toString() }, { buyer_id: user._id.toString() }] }, ], }; @@ -594,9 +595,9 @@ const validateFiatSentOrder = async ( orderId: string, ) => { try { - const where: FilterQuery = { + const where: any = { $and: [ - { buyer_id: user._id }, + { buyer_id: user._id.toString() }, { $or: [{ status: 'ACTIVE' }, { status: 'PAID_HOLD_INVOICE' }] }, ], }; @@ -631,7 +632,7 @@ const validateFiatSentOrder = async ( const validateSeller = async (ctx: MainContext, user: UserDocument) => { try { const where = { - seller_id: user._id, + seller_id: user._id.toString(), status: 'FIAT_SENT', }; @@ -697,7 +698,7 @@ const validateUserWaitingOrder = async ( ) => { try { // If is a seller - let where: FilterQuery = { + let where: any = { seller_id: user._id, status: 'WAITING_PAYMENT', }; @@ -730,10 +731,10 @@ const isBannedFromCommunity = async ( ) => { try { if (!communityId) return false; - const community = await Community.findOne({ _id: communityId }); + const community = await Community.findOne({ _id: new ObjectId(communityId) }); if (!community) return false; return community.banned_users.some( - (buser: IUsernameId) => buser.id == user._id, + (buser: IUsernameId) => buser.id == user._id.toString(), ); } catch (error) { logger.error(error); diff --git a/db_connect.ts b/db_connect.ts index b1b8dc32..bcb99089 100644 --- a/db_connect.ts +++ b/db_connect.ts @@ -15,10 +15,7 @@ if (!MONGO_URI) { } logger.info(`Connecting to MongoDB`); const connect = () => { - mongoose.connect(MONGO_URI, { - useNewUrlParser: true, - useUnifiedTopology: true, - } as ConnectOptions); + mongoose.connect(MONGO_URI, {} as ConnectOptions); return mongoose; }; diff --git a/jobs/pending_payments.ts b/jobs/pending_payments.ts index 951c38c7..1a34abf7 100644 --- a/jobs/pending_payments.ts +++ b/jobs/pending_payments.ts @@ -1,3 +1,5 @@ +import mongoose from 'mongoose'; +const { ObjectId } = mongoose.Types; import { PendingPayment, Order, User, Community } from '../models'; import * as messages from '../bot/messages'; import { logger } from '../logger'; @@ -8,18 +10,22 @@ import { getUserI18nContext } from '../util'; import { CommunityContext } from '../bot/modules/community/communityContext'; import { orderUpdated } from '../bot/modules/events/orders'; +function getPaymentAttempts(): number { + return Number(process.env.PAYMENT_ATTEMPTS) || 2; +} + export const attemptPendingPayments = async ( bot: Telegraf, ): Promise => { const pendingPayments = await PendingPayment.find({ paid: false, - attempts: { $lt: process.env.PAYMENT_ATTEMPTS }, + attempts: { $lt: getPaymentAttempts() }, is_invoice_expired: false, community_id: null, next_retry: { $lte: new Date() }, }); for (const pending of pendingPayments) { - const order = await Order.findOne({ _id: pending.order_id }); + const order = await Order.findOne({ _id: new ObjectId(pending.order_id) }); try { if (order === null) throw Error('Order was not found in DB'); pending.attempts++; @@ -54,7 +60,7 @@ export const attemptPendingPayments = async ( amount: pending.amount, request: pending.payment_request, }); - const buyerUser = await User.findOne({ _id: order.buyer_id }); + const buyerUser = await User.findOne({ _id: new ObjectId(order.buyer_id!) }); if (buyerUser === null) throw Error('buyerUser was not found in DB'); const i18nCtx: I18nContext = await getUserI18nContext(buyerUser); // If the buyer's invoice is expired we let it know and don't try to pay again @@ -78,7 +84,7 @@ export const attemptPendingPayments = async ( buyerUser.trades_completed++; await buyerUser.save(); // We add a new completed trade for the seller - const sellerUser = await User.findOne({ _id: order.seller_id }); + const sellerUser = await User.findOne({ _id: new ObjectId(order.seller_id!) }); if (sellerUser === null) throw Error('sellerUser was not found in DB'); sellerUser.trades_completed++; sellerUser.save(); @@ -124,10 +130,7 @@ export const attemptPendingPayments = async ( ); } - if ( - process.env.PAYMENT_ATTEMPTS !== undefined && - pending.attempts >= parseInt(process.env.PAYMENT_ATTEMPTS) - ) { + if (pending.attempts >= getPaymentAttempts()) { order.paid_hold_buyer_invoice_updated = false; await messages.toBuyerPendingPaymentFailedMessage( bot, @@ -162,7 +165,7 @@ export const attemptCommunitiesPendingPayments = async ( ): Promise => { const pendingPayments = await PendingPayment.find({ paid: false, - attempts: { $lt: process.env.PAYMENT_ATTEMPTS }, + attempts: { $lt: getPaymentAttempts() }, is_invoice_expired: false, community_id: { $ne: null }, next_retry: { $lte: new Date() }, @@ -191,7 +194,7 @@ export const attemptCommunitiesPendingPayments = async ( amount: pending.amount, request: pending.payment_request, }); - const user = await User.findById(pending.user_id); + const user = await User.findById(new ObjectId(pending.user_id)); if (user === null) throw Error('User was not found in DB'); const i18nCtx: I18nContext = await getUserI18nContext(user); // If the buyer's invoice is expired we let it know and don't try to pay again @@ -203,7 +206,7 @@ export const attemptCommunitiesPendingPayments = async ( ); } - const community = await Community.findById(pending.community_id); + const community = await Community.findById(new ObjectId(pending.community_id)); if (community === null) throw Error('Community was not found in DB'); if (!!payment && !!payment.confirmed_at) { pending.paid = true; @@ -238,10 +241,7 @@ export const attemptCommunitiesPendingPayments = async ( ); } - if ( - process.env.PAYMENT_ATTEMPTS !== undefined && - pending.attempts >= parseInt(process.env.PAYMENT_ATTEMPTS) - ) { + if (pending.attempts >= getPaymentAttempts()) { await bot.telegram.sendMessage( user.tg_id, i18nCtx.t('pending_payment_failed', { diff --git a/models/community.ts b/models/community.ts index 8b1b8bb2..506ff30b 100644 --- a/models/community.ts +++ b/models/community.ts @@ -11,7 +11,7 @@ const currencyLimits = (val: string): boolean => { return val.length > 0 && val.length <= CURRENCIES; }; -export interface IOrderChannel extends Document { +export interface IOrderChannel { name: string; type: string; } @@ -24,7 +24,7 @@ const OrderChannelSchema = new Schema({ }, }); -export interface IUsernameId extends Document { +export interface IUsernameId { id: string; username: string; } @@ -35,17 +35,17 @@ const usernameIdSchema = new Schema({ }); export interface ICommunity extends Document { - _id: string; + _id: mongoose.Types.ObjectId; name: string; creator_id: string; group: string; - order_channels: Types.DocumentArray; + order_channels: IOrderChannel[]; fee: number; earnings: number; orders_to_redeem: number; dispute_channel: string; - solvers: Types.DocumentArray; - banned_users: Types.DocumentArray; + solvers: IUsernameId[]; + banned_users: IUsernameId[]; public: boolean; currencies: Array; created_at: Date; diff --git a/models/order.ts b/models/order.ts index b82697d2..2d21a4ae 100644 --- a/models/order.ts +++ b/models/order.ts @@ -1,7 +1,7 @@ import mongoose, { Document, Schema } from 'mongoose'; export interface IOrder extends Document { - _id: string; + _id: mongoose.Types.ObjectId; description?: string; amount: number; max_amount: number; diff --git a/models/user.ts b/models/user.ts index 699091c8..f7c35311 100644 --- a/models/user.ts +++ b/models/user.ts @@ -5,8 +5,8 @@ interface UserReview { reviewed_at: Date; } -export interface UserDocument extends Document { - _id: string; +export interface UserDocument extends Omit { + _id: mongoose.Types.ObjectId; tg_id: string; username?: string; lang: string; diff --git a/package-lock.json b/package-lock.json index fc925f11..70ba9cd4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ "dotenv": "^10.0.0", "invoices": "2.0.6", "lightning": "10.25.0", - "mongoose": "^8.17.1", + "mongoose": "^9.5.0", "node-schedule": "^2.0.0", "nostr-tools": "^2.5.2", "qrcode": "^1.5.0", @@ -331,9 +331,9 @@ } }, "node_modules/@mongodb-js/saslprep": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.3.0.tgz", - "integrity": "sha512-zlayKCsIjYb7/IdfqxorK5+xUMyi4vOKcFy10wKJYc63NSdKI8mNME+uJqfatkPmOSMMUiojrL58IePKBm3gvQ==", + "version": "1.4.9", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.4.9.tgz", + "integrity": "sha512-RXSxsokhAF/4nWys8An8npsqOI33Ex1Hlzqjw2pZOO+GKtMAR2noGnUdsFiGwsaO/xXI+56mtjTmDA3JXJsvmA==", "license": "MIT", "dependencies": { "sparse-bitfield": "^3.0.3" @@ -684,9 +684,9 @@ "license": "MIT" }, "node_modules/@types/whatwg-url": { - "version": "11.0.5", - "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz", - "integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-13.0.0.tgz", + "integrity": "sha512-N8WXpbE6Wgri7KUSvrmQcqrMllKZ9uxkYWMt+mCSGwNc0Hsw9VQTW7ApqI4XNrx6/SaM2QQJCzMPDEXE058s+Q==", "license": "MIT", "dependencies": { "@types/webidl-conversions": "*" @@ -1441,12 +1441,12 @@ } }, "node_modules/bson": { - "version": "6.10.4", - "resolved": "https://registry.npmjs.org/bson/-/bson-6.10.4.tgz", - "integrity": "sha512-WIsKqkSC0ABoBJuT1LEX+2HEvNmNKKgnTAyd0fL8qzK4SH2i9NXg+t08YtdZp/V9IZ33cxe3iV4yM0qg8lMQng==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-7.2.0.tgz", + "integrity": "sha512-YCEo7KjMlbNlyHhz7zAZNDpIpQbd+wOEHJYezv0nMYTn4x31eIUM2yomNNubclAt63dObUzKHWsBLJ9QcZNSnQ==", "license": "Apache-2.0", "engines": { - "node": ">=16.20.1" + "node": ">=20.19.0" } }, "node_modules/buffer": { @@ -3695,13 +3695,10 @@ } }, "node_modules/ip-address": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", - "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", - "dependencies": { - "jsbn": "1.1.0", - "sprintf-js": "^1.1.3" - }, + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", + "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", + "license": "MIT", "engines": { "node": ">= 12" } @@ -4080,11 +4077,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/jsbn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", - "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==" - }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -4122,12 +4114,12 @@ "dev": true }, "node_modules/kareem": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz", - "integrity": "sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-3.3.0.tgz", + "integrity": "sha512-kpSuLD3/7RenBnjnJdOHXCKC8dTd1JzeOiJhN0necWWci6cC+qX+VuwPnMVgb+a4+KNJSfgqahpnfWaeDXCimw==", "license": "Apache-2.0", "engines": { - "node": ">=12.0.0" + "node": ">=18.0.0" } }, "node_modules/keyv": { @@ -4730,26 +4722,26 @@ "dev": true }, "node_modules/mongodb": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.18.0.tgz", - "integrity": "sha512-fO5ttN9VC8P0F5fqtQmclAkgXZxbIkYRTUi1j8JO6IYwvamkhtYDilJr35jOPELR49zqCJgXZWwCtW7B+TM8vQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-7.1.1.tgz", + "integrity": "sha512-067DXiMjcpYQl6bGjWQoTUEE9UoRViTtKFcoqX7z08I+iDZv/emH1g8XEFiO3qiDfXAheT5ozl1VffDTKhIW/w==", "license": "Apache-2.0", "dependencies": { - "@mongodb-js/saslprep": "^1.1.9", - "bson": "^6.10.4", - "mongodb-connection-string-url": "^3.0.0" + "@mongodb-js/saslprep": "^1.3.0", + "bson": "^7.1.1", + "mongodb-connection-string-url": "^7.0.0" }, "engines": { - "node": ">=16.20.1" + "node": ">=20.19.0" }, "peerDependencies": { - "@aws-sdk/credential-providers": "^3.188.0", - "@mongodb-js/zstd": "^1.1.0 || ^2.0.0", - "gcp-metadata": "^5.2.0", - "kerberos": "^2.0.1", - "mongodb-client-encryption": ">=6.0.0 <7", - "snappy": "^7.2.2", - "socks": "^2.7.1" + "@aws-sdk/credential-providers": "^3.806.0", + "@mongodb-js/zstd": "^7.0.0", + "gcp-metadata": "^7.0.1", + "kerberos": "^7.0.0", + "mongodb-client-encryption": ">=7.0.0 <7.1.0", + "snappy": "^7.3.2", + "socks": "^2.8.6" }, "peerDependenciesMeta": { "@aws-sdk/credential-providers": { @@ -4776,31 +4768,33 @@ } }, "node_modules/mongodb-connection-string-url": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.2.tgz", - "integrity": "sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-7.0.1.tgz", + "integrity": "sha512-h0AZ9A7IDVwwHyMxmdMXKy+9oNlF0zFoahHiX3vQ8e3KFcSP3VmsmfvtRSuLPxmyv2vjIDxqty8smTgie/SNRQ==", "license": "Apache-2.0", "dependencies": { - "@types/whatwg-url": "^11.0.2", - "whatwg-url": "^14.1.0 || ^13.0.0" + "@types/whatwg-url": "^13.0.0", + "whatwg-url": "^14.1.0" + }, + "engines": { + "node": ">=20.19.0" } }, "node_modules/mongoose": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.17.1.tgz", - "integrity": "sha512-aodS4cacux5caoxB5ErEwRmrafIUsVRJxHnvP7URnSUnTenr32j1qBVV+KjYxryyLSisQkxglAFF69TNLeZTLg==", + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-9.5.0.tgz", + "integrity": "sha512-B4blGFkFL1s0G24URuMvx0qTlx+gRVLmfO7WcSz8NcmW/XHEJ3G69capdyW1iRsGKiycp1tkwKHnxHbnwjwmPw==", "license": "MIT", "dependencies": { - "bson": "^6.10.4", - "kareem": "2.6.3", - "mongodb": "~6.18.0", + "kareem": "3.3.0", + "mongodb": "~7.1", "mpath": "0.9.0", - "mquery": "5.0.0", + "mquery": "6.0.0", "ms": "2.1.3", "sift": "17.1.3" }, "engines": { - "node": ">=16.20.1" + "node": ">=20.19.0" }, "funding": { "type": "opencollective", @@ -4816,15 +4810,12 @@ } }, "node_modules/mquery": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", - "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-6.0.0.tgz", + "integrity": "sha512-b2KQNsmgtkscfeDgkYMcWGn9vZI9YoXh802VDEwE6qc50zxBFQ0Oo8ROkawbPAsXCY1/Z1yp0MagqsZStPWJjw==", "license": "MIT", - "dependencies": { - "debug": "4.x" - }, "engines": { - "node": ">=14.0.0" + "node": ">=20.19.0" } }, "node_modules/ms": { @@ -6424,11 +6415,12 @@ } }, "node_modules/socks": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", - "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", + "version": "2.8.7", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", + "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", + "license": "MIT", "dependencies": { - "ip-address": "^9.0.5", + "ip-address": "^10.0.1", "smart-buffer": "^4.2.0" }, "engines": { @@ -6463,11 +6455,6 @@ "memory-pager": "^1.0.2" } }, - "node_modules/sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==" - }, "node_modules/stack-trace": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", diff --git a/package.json b/package.json index 4683c48c..dd874a18 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "dotenv": "^10.0.0", "invoices": "2.0.6", "lightning": "10.25.0", - "mongoose": "^8.17.1", + "mongoose": "^9.5.0", "node-schedule": "^2.0.0", "nostr-tools": "^2.5.2", "qrcode": "^1.5.0", @@ -69,4 +69,4 @@ "typegram": "^5.2.0", "typescript": "5.1.6" } -} +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index f1492da5..c37ea80d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,7 @@ { "compilerOptions": { "strict": true, + "skipLibCheck": true, "esModuleInterop": true, "resolveJsonModule": true, "downlevelIteration": true, diff --git a/util/communityHelper.ts b/util/communityHelper.ts index 76a18e4c..5379bd6c 100644 --- a/util/communityHelper.ts +++ b/util/communityHelper.ts @@ -29,7 +29,7 @@ export const getCommunityInfo = async ( const regex = new RegExp(`^@${chat.username}$`, 'i'); community = await Community.findOne({ group: regex }); if (community) { - communityId = community._id; + communityId = community._id.toString(); } } else if (user.default_community_id) { // Private chat with default community diff --git a/util/index.ts b/util/index.ts index dc00c832..7440c30e 100644 --- a/util/index.ts +++ b/util/index.ts @@ -37,7 +37,7 @@ const isIso4217 = (code: string): boolean => { const isOrderCreator = (user: UserDocument, order: IOrder) => { try { - return user._id == order.creator_id; + return user._id.toString() == order.creator_id; } catch (error) { logger.error(error); return false; @@ -88,8 +88,8 @@ const handleReputationItems = async ( const yesterday = new Date(Date.now() - 86400000).toISOString(); const orders = await Order.find({ status: 'SUCCESS', - seller_id: buyer._id, - buyer_id: seller._id, + seller_id: buyer._id.toString(), + buyer_id: seller._id.toString(), taken_at: { $gte: yesterday }, }); if (orders.length > 0) { @@ -454,7 +454,7 @@ const isDisputeSolver = (community: ICommunity | null, user: UserDocument) => { return false; } - return community.solvers.some(solver => solver.id == user._id); + return community.solvers.some(solver => solver.id == user._id.toString()); }; // Return the fee the bot will charge to the seller From 90d30b4a5ee450cc353a1abfc80c3a2dac9a996c Mon Sep 17 00:00:00 2001 From: lucas Date: Sun, 26 Apr 2026 22:23:17 -0300 Subject: [PATCH 2/4] Code formatting --- bot/commands.ts | 41 ++++++++++++++++++++++++------- bot/messages.ts | 8 ++++-- bot/modules/community/commands.ts | 4 ++- bot/modules/community/messages.ts | 20 +++++++-------- bot/modules/community/scenes.ts | 4 ++- bot/modules/dispute/actions.ts | 10 ++++++-- bot/modules/dispute/commands.ts | 14 ++++++++--- bot/modules/orders/messages.ts | 8 +++--- bot/ordersActions.ts | 10 ++++++-- bot/start.ts | 5 ++-- bot/validations.ts | 15 ++++++++--- jobs/pending_payments.ts | 12 ++++++--- 12 files changed, 109 insertions(+), 42 deletions(-) diff --git a/bot/commands.ts b/bot/commands.ts index eb70d46f..a7934c9f 100644 --- a/bot/commands.ts +++ b/bot/commands.ts @@ -321,9 +321,13 @@ const cancelAddInvoice = async ( if (order.status !== 'WAITING_BUYER_INVOICE') return await messages.genericErrorMessage(ctx, user, i18nCtx); - const sellerUser = await User.findOne({ _id: new ObjectId(order.seller_id!) }); + const sellerUser = await User.findOne({ + _id: new ObjectId(order.seller_id!), + }); if (sellerUser === null) throw new Error('sellerUser was not found'); - const buyerUser = await User.findOne({ _id: new ObjectId(order.buyer_id!) }); + const buyerUser = await User.findOne({ + _id: new ObjectId(order.buyer_id!), + }); if (buyerUser === null) throw new Error('buyerUser was not found'); const sellerTgId = sellerUser.tg_id; // If order creator cancels it, it will not be republished @@ -518,9 +522,13 @@ const cancelShowHoldInvoice = async ( if (order.hash) { await cancelHoldInvoice({ hash: order.hash }); } - const buyerUser = await User.findOne({ _id: new ObjectId(order.buyer_id!) }); + const buyerUser = await User.findOne({ + _id: new ObjectId(order.buyer_id!), + }); if (buyerUser === null) throw new Error('buyerUser was not found'); - const sellerUser = await User.findOne({ _id: new ObjectId(order.seller_id!) }); + const sellerUser = await User.findOne({ + _id: new ObjectId(order.seller_id!), + }); if (sellerUser === null) throw new Error('sellerUser was not found'); const i18nCtxSeller = await getUserI18nContext(sellerUser); @@ -682,7 +690,11 @@ const cancelOrder = async ( if (!user) return; } if (user.banned) return await messages.bannedUserErrorMessage(ctx, user); - const order = await ordersActions.getOrder(ctx, user, new ObjectId(orderId) as any); + const order = await ordersActions.getOrder( + ctx, + user, + new ObjectId(orderId) as any, + ); if (!order) return; @@ -739,16 +751,23 @@ const cancelOrder = async ( const initiatorUser = user; if (initiatorUser._id.toString() === order.buyer_id?.toString()) { - counterPartyUser = await User.findOne({ _id: new ObjectId(order.seller_id!) }); + counterPartyUser = await User.findOne({ + _id: new ObjectId(order.seller_id!), + }); initiator = UserOrderRole.BUYER; } else { - counterPartyUser = await User.findOne({ _id: new ObjectId(order.buyer_id!) }); + counterPartyUser = await User.findOne({ + _id: new ObjectId(order.buyer_id!), + }); initiator = UserOrderRole.SELLER; } if (counterPartyUser == null) throw new Error('counterPartyUser was not found'); - const updateOrder = await setCooperativeCancelFlag(new ObjectId(order._id) as any, initiator); + const updateOrder = await setCooperativeCancelFlag( + new ObjectId(order._id) as any, + initiator, + ); // If the call returns null, the flag was already set (or order is missing), // so we treat it as a duplicate request. @@ -902,7 +921,11 @@ const showQrCode = async ( if (!user) return; } if (user.banned) return await messages.bannedUserErrorMessage(ctx, user); - const order = await ordersActions.getOrder(ctx, user, new ObjectId(orderId) as any); + const order = await ordersActions.getOrder( + ctx, + user, + new ObjectId(orderId) as any, + ); if (!order) return; if (!order.hash) return; diff --git a/bot/messages.ts b/bot/messages.ts index 418d539d..b3fcf3ff 100644 --- a/bot/messages.ts +++ b/bot/messages.ts @@ -747,7 +747,9 @@ const publishBuyOrderMessage = async ( // Get the community language if available let communityI18n = i18n; if (order.community_id) { - const community = await Community.findOne({ _id: new ObjectId(order.community_id!) }); + const community = await Community.findOne({ + _id: new ObjectId(order.community_id!), + }); if (community && community.language) { communityI18n = new I18n({ defaultLanguageOnMissing: true, @@ -800,7 +802,9 @@ const publishSellOrderMessage = async ( let communityI18n = i18n; if (order.community_id) { - const community = await Community.findOne({ _id: new ObjectId(order.community_id!) }); + const community = await Community.findOne({ + _id: new ObjectId(order.community_id!), + }); if (community && community.language) { communityI18n = new I18n({ defaultLanguageOnMissing: true, diff --git a/bot/modules/community/commands.ts b/bot/modules/community/commands.ts index a6afa21e..786abb27 100644 --- a/bot/modules/community/commands.ts +++ b/bot/modules/community/commands.ts @@ -89,7 +89,9 @@ export const myComms = async (ctx: MainContext) => { try { const { user } = ctx; - const communities = await Community.find({ creator_id: user._id.toString() }); + const communities = await Community.find({ + creator_id: user._id.toString(), + }); if (!communities.length) return await ctx.reply(ctx.i18n.t('you_dont_have_communities')); diff --git a/bot/modules/community/messages.ts b/bot/modules/community/messages.ts index d8f35cab..27b61e7d 100644 --- a/bot/modules/community/messages.ts +++ b/bot/modules/community/messages.ts @@ -169,17 +169,17 @@ export const earningsMessage = async (ctx: MainContext) => { const button = community.earnings > 0 ? { - reply_markup: { - inline_keyboard: [ - [ - { - text: ctx.i18n.t('withdraw_earnings'), - callback_data: `withdrawEarnings_${community._id}`, - }, + reply_markup: { + inline_keyboard: [ + [ + { + text: ctx.i18n.t('withdraw_earnings'), + callback_data: `withdrawEarnings_${community._id}`, + }, + ], ], - ], - }, - } + }, + } : undefined; await ctx.reply( ctx.i18n.t('current_earnings', { diff --git a/bot/modules/community/scenes.ts b/bot/modules/community/scenes.ts index 6122eff1..3952a3b8 100644 --- a/bot/modules/community/scenes.ts +++ b/bot/modules/community/scenes.ts @@ -957,7 +957,9 @@ export const addEarningsInvoiceWizard = new Scenes.WizardScene( const user = await User.findById(community.creator_id); if (user === null) throw new Error('user was not found'); - logger.debug(`Creating pending payment for community ${community._id.toString()}`); + logger.debug( + `Creating pending payment for community ${community._id.toString()}`, + ); const pp = new PendingPayment({ amount: community.earnings, payment_request: lnInvoice, diff --git a/bot/modules/dispute/actions.ts b/bot/modules/dispute/actions.ts index 37d15391..4fb1511f 100644 --- a/bot/modules/dispute/actions.ts +++ b/bot/modules/dispute/actions.ts @@ -35,10 +35,16 @@ export const takeDispute = async (ctx: MainContext): Promise => { if (seller === null) throw new Error('seller not found'); const initiator = order.buyer_dispute ? 'buyer' : 'seller'; const buyerDisputes = await Dispute.countDocuments({ - $or: [{ buyer_id: buyer._id.toString() }, { seller_id: buyer._id.toString() }], + $or: [ + { buyer_id: buyer._id.toString() }, + { seller_id: buyer._id.toString() }, + ], }); const sellerDisputes = await Dispute.countDocuments({ - $or: [{ buyer_id: seller._id.toString() }, { seller_id: seller._id.toString() }], + $or: [ + { buyer_id: seller._id.toString() }, + { seller_id: seller._id.toString() }, + ], }); dispute.solver_id = solver._id.toString(); diff --git a/bot/modules/dispute/commands.ts b/bot/modules/dispute/commands.ts index 9d87d1a1..8d45ba96 100644 --- a/bot/modules/dispute/commands.ts +++ b/bot/modules/dispute/commands.ts @@ -53,11 +53,17 @@ export const handleDispute = async (ctx: MainContext, orderId: string) => { // If a user disputes is equal to MAX_DISPUTES, we ban the user const buyerDisputes = (await Dispute.countDocuments({ - $or: [{ buyer_id: buyer._id.toString() }, { seller_id: buyer._id.toString() }], + $or: [ + { buyer_id: buyer._id.toString() }, + { seller_id: buyer._id.toString() }, + ], })) + 1; const sellerDisputes = (await Dispute.countDocuments({ - $or: [{ buyer_id: seller._id.toString() }, { seller_id: seller._id.toString() }], + $or: [ + { buyer_id: seller._id.toString() }, + { seller_id: seller._id.toString() }, + ], })) + 1; const maxDisputes = Number(process.env.MAX_DISPUTES); // if MAX_DISPUTES is not specified or can't be parsed as number, following @@ -85,7 +91,9 @@ export const handleDispute = async (ctx: MainContext, orderId: string) => { await messages.beginDispute(ctx, initiator, order, buyer, seller); // Show the dispute button to solvers await messages.takeDisputeButton(ctx, order); - logger.warning(`Order ${order._id.toString()}: User ${user._id.toString()} started a dispute!`); + logger.warning( + `Order ${order._id.toString()}: User ${user._id.toString()} started a dispute!`, + ); } catch (error) { logger.error(error); } diff --git a/bot/modules/orders/messages.ts b/bot/modules/orders/messages.ts index c38831a5..c730f794 100644 --- a/bot/modules/orders/messages.ts +++ b/bot/modules/orders/messages.ts @@ -22,10 +22,10 @@ export const listOrdersResponse = async ( typeof order.fiat_amount !== 'undefined' ? sanitizeMD(order.fiat_amount) : [ - sanitizeMD(order.min_amount), - ' \\- ', - sanitizeMD(order.max_amount), - ].join(''); + sanitizeMD(order.min_amount), + ' \\- ', + sanitizeMD(order.max_amount), + ].join(''); if (typeof order.amount !== 'undefined') amount = String(order.amount); const timeToExpire = getTimeToExpirationOrder(order, i18n); diff --git a/bot/ordersActions.ts b/bot/ordersActions.ts index c1422795..cde22c2e 100644 --- a/bot/ordersActions.ts +++ b/bot/ordersActions.ts @@ -309,7 +309,10 @@ const getOrder = async ( const where = { _id: orderId, - $or: [{ seller_id: user._id.toString() }, { buyer_id: user._id.toString() }], + $or: [ + { seller_id: user._id.toString() }, + { buyer_id: user._id.toString() }, + ], }; const order = await Order.findOne(where).exec(); @@ -330,7 +333,10 @@ const getOrders = async (user: UserDocument, status?: string) => { const where: any = { $and: [ { - $or: [{ buyer_id: user._id.toString() }, { seller_id: user._id.toString() }], + $or: [ + { buyer_id: user._id.toString() }, + { seller_id: user._id.toString() }, + ], }, ], }; diff --git a/bot/start.ts b/bot/start.ts index 331bc330..bb8438cd 100644 --- a/bot/start.ts +++ b/bot/start.ts @@ -777,8 +777,9 @@ const initialize = ( ctx.admin.default_community_id, ); if (community === null) throw Error('Community was not found in DB'); - community.banned_users = community.banned_users - .filter((el: IUsernameId) => el.id !== user._id.toString()); + community.banned_users = community.banned_users.filter( + (el: IUsernameId) => el.id !== user._id.toString(), + ); await community.save(); } else { return await ctx.reply(ctx.i18n.t('need_default_community')); diff --git a/bot/validations.ts b/bot/validations.ts index 05b63987..36f490da 100644 --- a/bot/validations.ts +++ b/bot/validations.ts @@ -112,7 +112,9 @@ const validateAdmin = async (ctx: MainContext, id?: string) => { let community = null; if (user.default_community_id) - community = await Community.findOne({ _id: new ObjectId(user.default_community_id) }); + community = await Community.findOne({ + _id: new ObjectId(user.default_community_id), + }); const isSolver = isDisputeSolver(community, user); @@ -571,7 +573,12 @@ const validateDisputeOrder = async ( $and: [ { _id: new ObjectId(orderId) }, { $or: [{ status: 'ACTIVE' }, { status: 'FIAT_SENT' }] }, - { $or: [{ seller_id: user._id.toString() }, { buyer_id: user._id.toString() }] }, + { + $or: [ + { seller_id: user._id.toString() }, + { buyer_id: user._id.toString() }, + ], + }, ], }; @@ -731,7 +738,9 @@ const isBannedFromCommunity = async ( ) => { try { if (!communityId) return false; - const community = await Community.findOne({ _id: new ObjectId(communityId) }); + const community = await Community.findOne({ + _id: new ObjectId(communityId), + }); if (!community) return false; return community.banned_users.some( (buser: IUsernameId) => buser.id == user._id.toString(), diff --git a/jobs/pending_payments.ts b/jobs/pending_payments.ts index 1a34abf7..06002da5 100644 --- a/jobs/pending_payments.ts +++ b/jobs/pending_payments.ts @@ -60,7 +60,9 @@ export const attemptPendingPayments = async ( amount: pending.amount, request: pending.payment_request, }); - const buyerUser = await User.findOne({ _id: new ObjectId(order.buyer_id!) }); + const buyerUser = await User.findOne({ + _id: new ObjectId(order.buyer_id!), + }); if (buyerUser === null) throw Error('buyerUser was not found in DB'); const i18nCtx: I18nContext = await getUserI18nContext(buyerUser); // If the buyer's invoice is expired we let it know and don't try to pay again @@ -84,7 +86,9 @@ export const attemptPendingPayments = async ( buyerUser.trades_completed++; await buyerUser.save(); // We add a new completed trade for the seller - const sellerUser = await User.findOne({ _id: new ObjectId(order.seller_id!) }); + const sellerUser = await User.findOne({ + _id: new ObjectId(order.seller_id!), + }); if (sellerUser === null) throw Error('sellerUser was not found in DB'); sellerUser.trades_completed++; sellerUser.save(); @@ -206,7 +210,9 @@ export const attemptCommunitiesPendingPayments = async ( ); } - const community = await Community.findById(new ObjectId(pending.community_id)); + const community = await Community.findById( + new ObjectId(pending.community_id), + ); if (community === null) throw Error('Community was not found in DB'); if (!!payment && !!payment.confirmed_at) { pending.paid = true; From fe31341e3491a6bdeb7714b54f78e7ceff29dba2 Mon Sep 17 00:00:00 2001 From: lucas Date: Sun, 26 Apr 2026 22:30:35 -0300 Subject: [PATCH 3/4] Fix lint errors --- bot/commands.ts | 2 +- bot/messages.ts | 2 +- bot/start.ts | 4 ++-- bot/validations.ts | 3 +-- jobs/pending_payments.ts | 2 +- models/community.ts | 2 +- 6 files changed, 7 insertions(+), 8 deletions(-) diff --git a/bot/commands.ts b/bot/commands.ts index a7934c9f..62adf562 100644 --- a/bot/commands.ts +++ b/bot/commands.ts @@ -1,5 +1,4 @@ import mongoose from 'mongoose'; -const { ObjectId } = mongoose.Types; import { validateFiatSentOrder, validateReleaseOrder } from './validations'; import { createHoldInvoice, @@ -26,6 +25,7 @@ import { IOrder } from '../models/order'; import { UserDocument } from '../models/user'; import { HasTelegram, MainContext } from './start'; import { CommunityContext } from './modules/community/communityContext'; +const { ObjectId } = mongoose.Types; enum UserOrderRole { BUYER, diff --git a/bot/messages.ts b/bot/messages.ts index b3fcf3ff..0b42659a 100644 --- a/bot/messages.ts +++ b/bot/messages.ts @@ -1,5 +1,4 @@ import mongoose from 'mongoose'; -const { ObjectId } = mongoose.Types; import { TelegramError, Telegraf } from 'telegraf'; import { getCurrency, @@ -29,6 +28,7 @@ import { IFiat } from '../util/fiatModel'; import { CommunityContext } from './modules/community/communityContext'; import { imageCache } from '../util/imageCache'; import { ImageProcessingError } from '../util/errors'; +const { ObjectId } = mongoose.Types; const { I18n } = require('@grammyjs/i18n'); diff --git a/bot/start.ts b/bot/start.ts index bb8438cd..1bfee60a 100644 --- a/bot/start.ts +++ b/bot/start.ts @@ -3,8 +3,7 @@ import { Telegraf, session, Context, Telegram } from 'telegraf'; import { I18n, I18nContext } from '@grammyjs/i18n'; import { Message } from 'typegram'; import { UserDocument } from '../models/user'; -import mongoose from 'mongoose'; -const { ObjectId } = mongoose.Types; + import * as OrderEvents from './modules/events/orders'; import { limit } from '@grammyjs/ratelimiter'; import schedule from 'node-schedule'; @@ -79,6 +78,7 @@ import { IUsernameId } from '../models/community'; import { CommunityContext } from './modules/community/communityContext'; import { commandLogger } from './middleware/commandlogging'; + export interface MainContext extends Context { match: Array | null; i18n: I18nContext; diff --git a/bot/validations.ts b/bot/validations.ts index 36f490da..000e43dd 100644 --- a/bot/validations.ts +++ b/bot/validations.ts @@ -1,12 +1,10 @@ import { HasTelegram, MainContext, - OrderQuery, ctxUpdateAssertMsg, } from './start'; import { IUsernameId } from '../models/community'; import mongoose from 'mongoose'; -const { ObjectId } = mongoose.Types; import { UserDocument } from '../models/user'; import { IOrder } from '../models/order'; // @ts-ignore @@ -21,6 +19,7 @@ import { } from '../util'; import { existLightningAddress } from '../lnurl/lnurl-pay'; import { logger } from '../logger'; +const { ObjectId } = mongoose.Types; // Removed redundant ObjectId declaration diff --git a/jobs/pending_payments.ts b/jobs/pending_payments.ts index 06002da5..3859b5e2 100644 --- a/jobs/pending_payments.ts +++ b/jobs/pending_payments.ts @@ -1,5 +1,4 @@ import mongoose from 'mongoose'; -const { ObjectId } = mongoose.Types; import { PendingPayment, Order, User, Community } from '../models'; import * as messages from '../bot/messages'; import { logger } from '../logger'; @@ -9,6 +8,7 @@ import { payRequest, isPendingPayment } from '../ln'; import { getUserI18nContext } from '../util'; import { CommunityContext } from '../bot/modules/community/communityContext'; import { orderUpdated } from '../bot/modules/events/orders'; +const { ObjectId } = mongoose.Types; function getPaymentAttempts(): number { return Number(process.env.PAYMENT_ATTEMPTS) || 2; diff --git a/models/community.ts b/models/community.ts index 506ff30b..22cab4d3 100644 --- a/models/community.ts +++ b/models/community.ts @@ -1,4 +1,4 @@ -import mongoose, { Document, Schema, Types } from 'mongoose'; +import mongoose, { Document, Schema } from 'mongoose'; import { isValidLanguage, SUPPORTED_LANGUAGES } from '../util/languages'; const CURRENCIES: number = parseInt(process.env.COMMUNITY_CURRENCIES || '10'); From 403ba97ee728520820375b4ed9c2c7932d5bd6d2 Mon Sep 17 00:00:00 2001 From: lucas Date: Tue, 28 Apr 2026 23:40:17 -0300 Subject: [PATCH 4/4] Fix CI: In mongoose 9 when creating a new ObjectId from a string it should be a valid ObjectId, if not it creates an exception and makes isBannedFromCommunity to return false --- tests/bot/validation.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bot/validation.spec.ts b/tests/bot/validation.spec.ts index 63a5f3a6..83d3dbc4 100644 --- a/tests/bot/validation.spec.ts +++ b/tests/bot/validation.spec.ts @@ -1133,7 +1133,7 @@ describe('Validations', () => { it('should return true if user is banned', async () => { const user = { _id: 'userId' }; - const communityId = 'communityId'; + const communityId = new ObjectId().toString(); community.banned_users = [{ id: 'userId', username: 'username' }]; (Community.findOne as any).returns(community);