diff --git a/.env-sample b/.env-sample index 604ff56f..747df517 100644 --- a/.env-sample +++ b/.env-sample @@ -72,6 +72,9 @@ PAYMENT_ATTEMPTS=2 # Here will go the disputes from non community orders DISPUTE_CHANNEL='@p2plnbotDispute' +# Counterparty requirements limits +MAX_COUNTERPARTY_AGE_REQUIREMENT=30 +MAX_COUNTERPARTY_ORDERS_REQUIREMENT=10 # time-to-live for communities in days, communities without successful orders on this time are deleted COMMUNITY_TTL=31 diff --git a/bot/messages.ts b/bot/messages.ts index 17354be0..6c6fb359 100644 --- a/bot/messages.ts +++ b/bot/messages.ts @@ -975,6 +975,20 @@ const userTakerIsBlockedByUserOrder = async ( } }; +const notMeetingRequirementsMessage = async ( + ctx: MainContext, + user: UserDocument, +) => { + try { + await ctx.telegram.sendMessage( + user.tg_id, + ctx.i18n.t('not_meeting_requirements'), + ); + } catch (error) { + logger.error(error); + } +}; + const fiatSentMessages = async ( ctx: MainContext, buyer: UserDocument, @@ -2224,4 +2238,5 @@ export { userTakerIsBlockedByUserOrder, userOrderIsBlockedByUserTaker, showQRCodeMessage, + notMeetingRequirementsMessage, }; diff --git a/bot/middleware/stage.ts b/bot/middleware/stage.ts index 424eda3a..dd3a1dd7 100644 --- a/bot/middleware/stage.ts +++ b/bot/middleware/stage.ts @@ -27,6 +27,7 @@ export const stageMiddleware = () => { addInvoicePHIWizard, OrdersModule.Scenes.createOrder, UserModule.Scenes.Settings, + UserModule.Scenes.Requirements, ]; scenes.forEach(addGenericCommands); const stage = new Scenes.Stage(scenes, { diff --git a/bot/modules/orders/takeOrder.ts b/bot/modules/orders/takeOrder.ts index ad574b32..2ffe83cc 100644 --- a/bot/modules/orders/takeOrder.ts +++ b/bot/modules/orders/takeOrder.ts @@ -1,7 +1,11 @@ import { logger } from '../../../logger'; import { Block, Order, User } from '../../../models'; import { UserDocument } from '../../../models/user'; -import { deleteOrderFromChannel, generateRandomImage } from '../../../util'; +import { + deleteOrderFromChannel, + generateRandomImage, + getUserAge, +} from '../../../util'; import * as messages from '../../messages'; import { HasTelegram, MainContext } from '../../start'; import { @@ -73,6 +77,8 @@ export const takebuy = async ( if (await isBannedFromCommunity(user, order.community_id)) return await messages.bannedUserErrorMessage(ctx, user); + if (!(await meetsCounterpartyRequirements(ctx, user, userOffer))) return; + if (!(await validateTakeBuyOrder(ctx, bot, user, order))) return; const { randomImage } = generateRandomImage(user._id.toString()); @@ -127,6 +133,9 @@ export const takesell = async ( // We verify if the user is not banned on this community if (await isBannedFromCommunity(user, order.community_id)) return await messages.bannedUserErrorMessage(ctx, user); + + if (!(await meetsCounterpartyRequirements(ctx, user, seller))) return; + if (!(await validateTakeSellOrder(ctx, bot, user, order))) return; order.status = 'WAITING_BUYER_INVOICE'; order.buyer_id = user._id; @@ -168,3 +177,31 @@ const checkBlockingStatus = async ( return false; }; + +const meetsCounterpartyRequirements = async ( + ctx: MainContext, + user: UserDocument, + orderCreator: UserDocument, +) => { + if (!orderCreator.counterparty_requirements) return true; + + const { min_days_using_bot, min_completed_orders } = + orderCreator.counterparty_requirements; + + if (min_days_using_bot > 0) { + const ageInDays = getUserAge(user); + if (ageInDays < min_days_using_bot) { + await messages.notMeetingRequirementsMessage(ctx, user); + return false; + } + } + + if (min_completed_orders > 0) { + if (user.trades_completed < min_completed_orders) { + await messages.notMeetingRequirementsMessage(ctx, user); + return false; + } + } + + return true; +}; diff --git a/bot/modules/user/index.ts b/bot/modules/user/index.ts index 7bd67240..db1fed07 100644 --- a/bot/modules/user/index.ts +++ b/bot/modules/user/index.ts @@ -13,6 +13,14 @@ export const configure = (bot: Telegraf) => { ctx.reply(err.message); } }); + bot.command('/requirements', userMiddleware, async ctx => { + try { + const { user } = ctx; + await ctx.scene.enter(Scenes.Requirements.id, { user }); + } catch (err: any) { + ctx.reply(err.message); + } + }); }; export { Scenes }; diff --git a/bot/modules/user/scenes/index.ts b/bot/modules/user/scenes/index.ts index a414202d..30450e60 100644 --- a/bot/modules/user/scenes/index.ts +++ b/bot/modules/user/scenes/index.ts @@ -1,3 +1,4 @@ import Settings from './settings'; +import Requirements from './requirements'; -export default { Settings }; +export default { Settings, Requirements }; diff --git a/bot/modules/user/scenes/requirements.ts b/bot/modules/user/scenes/requirements.ts new file mode 100644 index 00000000..809a6341 --- /dev/null +++ b/bot/modules/user/scenes/requirements.ts @@ -0,0 +1,214 @@ +import { Scenes } from 'telegraf'; +import { + CommunityContext, + CommunityWizardState, +} from '../../community/communityContext'; +import { Message } from 'telegraf/typings/core/types/typegram'; +import { logger } from '../../../../logger'; + +function make() { + const resetMessage = async (ctx: CommunityContext, next: () => void) => { + const state = ctx.scene.state as CommunityWizardState; + delete state.feedback; + delete state.error; + next(); + }; + async function mainData(ctx: CommunityContext) { + const state = ctx.scene.state as CommunityWizardState; + const { user } = state; + return { + min_days_using_bot: + user.counterparty_requirements?.min_days_using_bot || 0, + min_completed_orders: + user.counterparty_requirements?.min_completed_orders || 0, + }; + } + async function updateMessage(ctx: CommunityContext) { + try { + const state = ctx.scene.state as CommunityWizardState; + ctx.i18n.locale(state.language); + const { message, error } = state; + + if (message === undefined) throw new Error('message is undefined'); + + const errorText = (error => { + if (!error) return; + return '⚠️ ERROR\n' + ctx.i18n.t(error.i18n, error); + })(error); + const feedbackText = (feedback => { + if (!feedback) return; + if (typeof feedback === 'string') return feedback; + return ctx.i18n.t(feedback.i18n, feedback); + })(state.feedback); + const extras = [errorText, feedbackText].filter(e => e); + + const main = ctx.i18n.t('user_requirements', await mainData(ctx)); + const str = [main, ...extras].filter(e => e).join('\n'); + + const messageChanged = str !== message.text; + if (!messageChanged) return; + + const msg = await ctx.telegram.editMessageText( + message.chat.id, + message.message_id, + undefined, + str, + { + parse_mode: 'HTML', + link_preview_options: { is_disabled: true }, + } as any, + ); + state.message = msg as Message.TextMessage; + state.message.text = str; + } catch (err) { + logger.error(err); + } + } + async function initHandler(ctx: CommunityContext) { + try { + const state = ctx.scene.state as CommunityWizardState; + const { user } = state; + state.language = user.lang || ctx.from?.language_code; + const str = ctx.i18n.t('user_requirements', await mainData(ctx)); + const msg = await ctx.reply(str, { parse_mode: 'HTML' }); + state.message = msg; + state.message.text = str; + } catch (err) { + logger.error(err); + } + } + const scene = new Scenes.WizardScene( + 'USER_COUNTERPARTY_REQUIREMENTS', + async (ctx: CommunityContext) => { + const state = ctx.scene.state as CommunityWizardState; + ctx.user = state.user; + if (!state.message) return initHandler(ctx); + await ctx.deleteMessage(); + state.error = { + i18n: 'generic_error', + }; + await updateMessage(ctx); + }, + ); + + scene.command( + 'counterpartyage', + resetMessage, + async (ctx: CommunityContext) => { + try { + await ctx.deleteMessage(); + const state = ctx.scene.state as CommunityWizardState; + if (ctx.message === undefined || !('text' in ctx.message)) + throw new Error('ctx.message is undefined'); + const [, days] = ctx.message.text.trim().split(' '); + const min_days = parseInt(days); + if (isNaN(min_days) || min_days < 0) throw new Error('NotValidNumber'); + const user = state.user; + const maxAge = parseInt( + process.env.MAX_COUNTERPARTY_AGE_REQUIREMENT || '30', + ); + if (min_days > maxAge) { + state.error = { + i18n: 'invalid_range', + command: '/counterpartyage', + max: maxAge, + }; + return await updateMessage(ctx); + } + if (!user.counterparty_requirements) { + user.counterparty_requirements = { + min_days_using_bot: 0, + min_completed_orders: 0, + }; + } + user.counterparty_requirements.min_days_using_bot = min_days; + await user.save(); + state.feedback = { + i18n: 'counterpartyage_updated', + days: min_days, + }; + await updateMessage(ctx); + } catch (err) { + const state = ctx.scene.state as CommunityWizardState; + state.error = { + i18n: 'invalid_number', + }; + await updateMessage(ctx); + } + }, + ); + + scene.command( + 'counterpartyorders', + resetMessage, + async (ctx: CommunityContext) => { + try { + await ctx.deleteMessage(); + const state = ctx.scene.state as CommunityWizardState; + if (ctx.message === undefined || !('text' in ctx.message)) + throw new Error('ctx.message is undefined'); + const [, orders] = ctx.message.text.trim().split(' '); + const min_orders = parseInt(orders); + if (isNaN(min_orders) || min_orders < 0) + throw new Error('NotValidNumber'); + const user = state.user; + const maxOrders = parseInt( + process.env.MAX_COUNTERPARTY_ORDERS_REQUIREMENT || '10', + ); + if (min_orders > maxOrders) { + state.error = { + i18n: 'invalid_range', + command: '/counterpartyorders', + max: maxOrders, + }; + return await updateMessage(ctx); + } + if (!user.counterparty_requirements) { + user.counterparty_requirements = { + min_days_using_bot: 0, + min_completed_orders: 0, + }; + } + user.counterparty_requirements.min_completed_orders = min_orders; + await user.save(); + state.feedback = { + i18n: 'counterpartyorders_updated', + orders: min_orders, + }; + await updateMessage(ctx); + } catch (err) { + const state = ctx.scene.state as CommunityWizardState; + state.error = { + i18n: 'invalid_number', + }; + await updateMessage(ctx); + } + }, + ); + + scene.command('reset', resetMessage, async (ctx: CommunityContext) => { + try { + await ctx.deleteMessage(); + const state = ctx.scene.state as CommunityWizardState; + const user = state.user; + user.counterparty_requirements = { + min_days_using_bot: 0, + min_completed_orders: 0, + }; + await user.save(); + state.feedback = { + i18n: 'requirements_reset', + }; + await updateMessage(ctx); + } catch (err) { + (ctx.scene.state as CommunityWizardState).error = { + i18n: 'generic_error', + }; + await updateMessage(ctx); + } + }); + + return scene; +} + +export default make(); diff --git a/locales/de.yaml b/locales/de.yaml index 8aa1b665..24fb6e0a 100644 --- a/locales/de.yaml +++ b/locales/de.yaml @@ -251,6 +251,7 @@ help: | /setaddress <_lightning Adresse / off_> - Ermöglicht es dem Käufer, eine statische Zahlungsadresse (Lightning-Adresse) einzurichten, _off_ zum Deaktivieren /setlang - Ermöglicht dem Benutzer, die Sprache zu ändern /settings - Zeigt die aktuellen Einstellungen des Benutzers an + /requirements - Den Assistenten für Anforderungen an den Vertragspartner aufrufen /listorders - Benutze diesen Befehl, um alle deine ausstehenden Transaktionen aufzulisten /listcurrencies - Listet alle FIAT Währungen auf, die wir verwenden können /fiatsent <_order id_> - Der Käufer teilt mit, dass er dem Verkäufer das FIAT-Geld geschickt hat @@ -707,3 +708,20 @@ unblock_failed: "Fehler beim Freigeben des Benutzers" check_solvers: Ihre Community ${communityName} hat keine Solver. Bitte fügen Sie innerhalb von ${remainingDays} Tagen mindestens einen hinzu, um zu verhindern, dass die Community deaktiviert wird. check_solvers_last_warning: Ihre Community ${communityName} hat keine Solver. Bitte fügen Sie noch heute mindestens einen hinzu, um zu verhindern, dass die Community deaktiviert wird. image_processing_error: Wir hatten einen Fehler beim Verarbeiten des Bildes, bitte warten Sie ein paar Minuten und versuchen Sie es erneut. + +user_requirements: | + Anforderungen an den Vertragspartner + Erforderliches Alter des Vertragspartners: ${min_days_using_bot} Tage Bot-Nutzung. + Abgeschlossene Aufträge: ${min_completed_orders} + + # HILFE + /counterpartyage <tage> - Legt das Mindestalter (in Tagen) fest, das der Vertragspartner haben muss, um deine Aufträge anzunehmen. + /counterpartyorders <aufträge> - Legt die Mindestanzahl abgeschlossener Aufträge für den Vertragspartner fest, damit dieser deine Aufträge annehmen kann. + /reset - Setzt diese Konfiguration auf die Standardwerte zurück + /exit - Um diesen Assistenten zu verlassen +counterpartyage_updated: Altersanforderung des Vertragspartners auf ${days} Tage aktualisiert. +counterpartyorders_updated: Anforderung für abgeschlossene Aufträge des Vertragspartners auf ${orders} aktualisiert. +requirements_reset: Anforderungen an den Vertragspartner wurden auf Standardwerte zurückgesetzt. +not_meeting_requirements: Du erfüllst nicht die Anforderungen des Vertragspartners, um diesen Auftrag anzunehmen. +invalid_number: Ungültige Nummer. +invalid_range: Ungültiger Wert für den Parameter ${command}, bitte wählen Sie eine Zahl im Bereich [0 - ${max}] diff --git a/locales/en.yaml b/locales/en.yaml index c12c9407..d18190d8 100644 --- a/locales/en.yaml +++ b/locales/en.yaml @@ -254,6 +254,7 @@ help: | /setaddress <_lightning address / off_> - Allows the buyer to establish a static payment address (lightning address), _off_ to deactivate /setlang - Allows the user to change the language /settings - Displays the user's current settings + /requirements - Enter Counterparty Requirements Wizard /listorders - Use this command to list all your pending transactions /listcurrencies - Lists all the currencies we can use to without indicatin the amount in sats. /fiatsent <_order id_> - Buyer informs that he has already sent FIAT money to seller @@ -712,3 +713,20 @@ unblock_failed: "Error unblocking the user" check_solvers: Your community ${communityName} does not have any solvers. Please add at least one within ${remainingDays} days to prevent the community from being disabled. check_solvers_last_warning: Your community ${communityName} does not have any solvers. Please add at least one today to prevent the community from being disabled. image_processing_error: We had an error processing the image, please wait a few minutes and try again + +user_requirements: | + Counterparty Requirements + Required counterparty age: ${min_days_using_bot} days using the bot. + Completed orders: ${min_completed_orders} + + # HELP + /counterpartyage <days> - Sets the minimum age (in days) required for the counterparty to take your orders. + /counterpartyorders <orders> - Sets the minimum number of completed orders required for the counterparty to take your orders. + /reset - Returns this configuration to default values + /exit - To exit this wizard +counterpartyage_updated: Counterparty age requirement updated to ${days} days. +counterpartyorders_updated: Counterparty completed orders requirement updated to ${orders}. +requirements_reset: Counterparty requirements have been reset to default. +not_meeting_requirements: You do not meet the counterparty requirements to take this order. +invalid_number: Invalid number. +invalid_range: Invalid value for parameter ${command}, please choose a number in the range [0 - ${max}] diff --git a/locales/es.yaml b/locales/es.yaml index b77314c4..dabdc092 100644 --- a/locales/es.yaml +++ b/locales/es.yaml @@ -251,6 +251,7 @@ help: | /setaddress <_lightning address / off_> - Permite al comprador indicar una dirección de pago estática (lightning address), _off_ para desactivarla /setlang - Le permite al usuario cambiar el idioma /settings - Muestra la configuración actual del usuario + /requirements - Entrar al asistente de requisitos de contraparte /listorders - El usuario puede listar sus órdenes no finalizadas /listcurrencies - Lista las monedas que podemos utilizar sin indicar el monto en satoshis /fiatsent <_id orden_> - El comprador indica que ya ha enviado el dinero Fiat al vendedor @@ -709,3 +710,20 @@ unblock_failed: "Error al desbloquear al usuario" image_processing_error: Hemos tenido un error procesando la imagen, por favor espera unos minutos y vuelve a intentarlo. check_solvers: Tu comunidad ${communityName} no tiene ningún solucionador. Agregue al menos uno dentro de ${remainingDays} días para evitar que se deshabilite la comunidad. check_solvers_last_warning: Tu comunidad ${communityName} no tiene ningún solucionador. Agregue al menos uno hoy para evitar que la comunidad quede inhabilitada. + +user_requirements: | + Requisitos de la contraparte + antiguedad de usuario requerida: ${min_days_using_bot} dias usando el bot. + ordenes completadas: ${min_completed_orders} + + # AYUDA + /counterpartyage <dias> - Setea el requisito de antiguedad minima (en días) requeridos para la contraparte para tomar tus ordenes. + /counterpartyorders <ordenes> - Setea el requisito minimo de ordenes completadas por la contraparte para que puedan tomar tus ordenes. + /reset - vuelve esta configuracion al valor por defecto + /exit - para salir de este asistente +counterpartyage_updated: Requisito de antigüedad de la contraparte actualizado a ${days} días. +counterpartyorders_updated: Requisito de órdenes completadas de la contraparte actualizado a ${orders}. +requirements_reset: Los requisitos de la contraparte se han vuelto al valor por defecto. +not_meeting_requirements: No cumples con los requisitos de la contraparte para tomar esta orden. +invalid_number: Número inválido. +invalid_range: Valor inválido para el parámetro ${command}, por favor elija un número en el rango [0 - ${max}] diff --git a/locales/fa.yaml b/locales/fa.yaml index 824acd93..059935ad 100644 --- a/locales/fa.yaml +++ b/locales/fa.yaml @@ -283,6 +283,9 @@ help: | /settings تنظیمات کنونی کاربر را نمایش می‌دهد. + + /requirements + ورود به راهنمای الزامات طرف مقابل /listorders از این دستور برای مشاهده لیستی از تمامی سفارش‌ها فعال خود استفاده کنید. @@ -806,3 +809,20 @@ unblock_failed: "خطا در رفع مسدودیت کاربر" check_solvers: اجتماع شما ${communityName} هیچ داوری ندارد. لطفاً برای جلوگیری از غیرفعال شدن اجتماع، تا ${remainingDays} روز آینده حداقل یک داور به آن اضافه کنید. check_solvers_last_warning: اجتماع شما ${communityName} هیچ داوری ندارد. برای جلوگیری از غیرفعال شدن اجتماع، امروز حداقل یک داور به آن اضافه کنید. image_processing_error: هنگام پردازش تصویر با خطایی مواجه شدیم، لطفاً چند دقیقه صبر کرده و دوباره امتحان کنید. + +user_requirements: | + الزامات طرف مقابل + سابقه مورد نیاز برای طرف مقابل: ${min_days_using_bot} روز استفاده از ربات. + تعداد سفارش‌های تکمیل شده: ${min_completed_orders} + + # راهنما + /counterpartyage <روز> - حداقل سابقه مورد نیاز (به روز) برای طرف مقابل جهت پذیرش سفارش‌های شما را تنظیم می‌کند. + /counterpartyorders <سفارش> - حداقل تعداد سفارش‌های تکمیل شده توسط طرف مقابل برای پذیرش سفارش‌های شما را تنظیم می‌کند. + /reset - این تنظیمات را به مقادیر پیش‌فرض باز می‌گرداند. + /exit - خروج از این راهنما +counterpartyage_updated: الزامات سابقه طرف مقابل به ${days} روز به‌روزرسانی شد. +counterpartyorders_updated: الزامات سفارش‌های تکمیل شده طرف مقابل به ${orders} عدد به‌روزرسانی شد. +requirements_reset: الزامات طرف مقابل به مقادیر پیش‌فرض بازگردانده شد. +not_meeting_requirements: شما واجد الزامات طرف مقابل برای پذیرش این سفارش نیستید. +invalid_number: عدد نامعتبر است. +invalid_range: مقدار نامعتبر برای پارامتر ${command}، لطفاً عددی در محدوده [0 - ${max}] انتخاب کنید. diff --git a/locales/fr.yaml b/locales/fr.yaml index 38a4fad0..df81d00e 100644 --- a/locales/fr.yaml +++ b/locales/fr.yaml @@ -253,6 +253,7 @@ help: | /setaddress <_addresse lightning / off_> - Permet à l'acheteur de définir une adresse de paiement statique (adresse lightning), _off_ pour désactiver /setlang - Change la langue de l'interface /settings - Affiche tes réglages actuels + /requirements - Entrer dans l'assistant des exigences de la contrepartie /listorders - Utilise cette commande pour afficher toutes tes offres en attente /listcurrencies - Lister les devises que nous pouvons utiliser sans spécifier le montant en satoshi. /fiatsent <_order id_> - L'acheteur informe qu'il a déjà envoyé de l'argent FIAT au vendeur @@ -706,3 +707,20 @@ unblock_failed: "Erreur lors du déblocage de l'utilisateur" check_solvers: Votre communauté ${communityName} ne possède aucun solveur. Veuillez en ajouter au moins un dans les ${remainingDays} jours pour éviter que la communauté ne soit désactivée. check_solvers_last_warning: Votre communauté ${communityName} ne possède aucun solveur. Veuillez en ajouter au moins un aujourd'hui pour éviter que la communauté ne soit désactivée. image_processing_error: Nous avons eu une erreur lors du traitement de l'image, veuillez attendre quelques minutes et réessayer. + +user_requirements: | + Exigences de la contrepartie + Âge de la contrepartie requis : ${min_days_using_bot} jours d'utilisation du bot. + Ordres complétés : ${min_completed_orders} + + # AIDE + /counterpartyage <jours> - Définit l'âge minimum (en jours) requis pour la contrepartie pour prendre vos ordres. + /counterpartyorders <ordres> - Définit le nombre minimum d'ordres complétés par la contrepartie pour qu'ils puissent prendre vos ordres. + /reset - Réinitialise cette configuration aux valeurs par défaut + /exit - Pour quitter cet assistant +counterpartyage_updated: Exigence d'âge de la contrepartie mise à jour à ${days} jours. +counterpartyorders_updated: Exigence d'ordres complétés de la contrepartie mise à jour à ${orders}. +requirements_reset: Les exigences de la contrepartie ont été réinitialisées par défaut. +not_meeting_requirements: Vous ne remplissez pas les exigences de la contrepartie pour prendre cet ordre. +invalid_number: Nombre invalide. +invalid_range: Valeur invalide pour le paramètre ${command}, veuillez choisir un nombre dans la plage [0 - ${max}] diff --git a/locales/it.yaml b/locales/it.yaml index 2a0efcd5..a4829c80 100644 --- a/locales/it.yaml +++ b/locales/it.yaml @@ -251,6 +251,7 @@ help: | /setaddress <_lightning address / off_> - Consente all'acquirente di indicare un indirizzo di pagamento statico (lightning address), _off_ per disattivarlo /setlang - Consente all'utente di cambiare lingua /settings - Visualizza le impostazioni correnti dell'utente + /requirements - Entra nella procedura guidata per i requisiti della controparte /listorders - Utilizzare questo comando per verificare tutte le transazioni in sospeso /listcurrencies - Elenca tutte le valute che si possono usare senza indicare l'importo in sats. /fiatsent <_order id_> - L'acquirente informa che ha inviato FIAT al venditore @@ -704,3 +705,20 @@ unblock_failed: "Errore nello sbloccare l'utente" check_solvers: La tua community ${communityName} non ha risolutori. Aggiungine almeno uno entro ${remainingDays} giorni per evitare che la community venga disabilitata. check_solvers_last_warning: La tua community ${communityName} non ha risolutori. Per favore aggiungine almeno uno oggi per evitare che la community venga disabilitata. image_processing_error: Abbiamo avuto un errore nel processare l'immagine, per favore attendi qualche minuto e prova di nuovo. + +user_requirements: | + Requisiti della controparte + anzianità utente richiesta: ${min_days_using_bot} giorni di utilizzo del bot. + ordini completati: ${min_completed_orders} + + # AIUTO + /counterpartyage <giorni> - Imposta il requisito di anzianità minima (in giorni) richiesto per la controparte per accettare i tuoi ordini. + /counterpartyorders <ordini> - Imposta il requisito minimo di ordini completati dalla controparte affinché possa accettare i tuoi ordini. + /reset - riporta questa configurazione al valore predefinito + /exit - per uscire da questa procedura guidata +counterpartyage_updated: Requisito di anzianità della controparte aggiornato a ${days} giorni. +counterpartyorders_updated: Requisito di ordini completati della controparte aggiornato a ${orders}. +requirements_reset: I requisiti della controparte sono stati riportati ai valori predefiniti. +not_meeting_requirements: Non soddisfi i requisiti della controparte per accettare questo ordine. +invalid_number: Numero non valido. +invalid_range: Valore non valido per il parametro ${command}, scegli un numero compreso tra [0 - ${max}] diff --git a/locales/ko.yaml b/locales/ko.yaml index d2c15154..c8c34886 100644 --- a/locales/ko.yaml +++ b/locales/ko.yaml @@ -252,6 +252,7 @@ help: | /setaddress <_라이트닝 주소 / off_> - 구매자가 정적인 결제 주소 (라이트닝 주소)를 설정할 수 있게 해 줍니다. 주소 대신 _off_를 넣으면 비활성화됩니다. /setlang - 사용자 언어를 변경합니다. /settings - 사용자의 현재 설정을 표시합니다. + /requirements - 거래 상대방 요구 사항 마법사 시작 /listorders - 대기 중인 결제 내역들을 모두 보려면 이 명령어를 사용하세요. /listcurrencies - 사용 가능한 모든 법정화폐 종류를 나열합니다. (sat 단위 제외) /fiatsent <_주문 id_> - 구매자가 판매자에게 법정화폐의 지불을 마쳤다고 알려주는 명령어입니다. @@ -704,3 +705,20 @@ unblock_failed: "사용자 차단 해제 중 오류 발생" check_solvers: ${communityName} 커뮤니티에 해결사가 없습니다. 커뮤니티가 비활성화되는 것을 방지하려면 ${remainingDays}일 이내에 하나 이상 추가하세요. check_solvers_last_warning: ${communityName} 커뮤니티에 해결사가 없습니다. 커뮤니티가 비활성화되는 것을 방지하려면 오늘 하나 이상 추가하세요. image_processing_error: 이미지 처리에 오류가 발생했습니다. 몇 분 후에 다시 시도해 주세요. + +user_requirements: | + 거래 상대방 요구 사항 + 필요한 상대방 가입 기간: 봇 사용 기간 ${min_days_using_bot}일. + 완료된 주문: ${min_completed_orders}개 + + # 도움말 + /counterpartyage <일> - 거래 상대방이 귀하의 주문을 수락하기 위해 필요한 최소 가입 기간(일)을 설정합니다. + /counterpartyorders <주문> - 거래 상대방이 귀하의 주문을 수락하기 위해 필요한 최소 완료 주문 수를 설정합니다. + /reset - 이 구성을 기본값으로 되돌립니다. + /exit - 이 마법사를 종료합니다. +counterpartyage_updated: 거래 상대방 가입 기간 요구 사항이 ${days}일로 업데이트되었습니다. +counterpartyorders_updated: 거래 상대방 완료 주문 수 요구 사항이 ${orders}개로 업데이트되었습니다. +requirements_reset: 거래 상대방 요구 사항이 기본값으로 재설정되었습니다. +not_meeting_requirements: 귀하는 이 주문을 수락하기 위한 거래 상대방 요구 사항을 충족하지 않습니다. +invalid_number: 유효하지 않은 숫자입니다. +invalid_range: ${command} 매개변수가 잘못되었습니다. [0 - ${max}] 사이의 숫자를 선택해 주세요. diff --git a/locales/pt.yaml b/locales/pt.yaml index c4c9c1a8..bd48524e 100644 --- a/locales/pt.yaml +++ b/locales/pt.yaml @@ -252,6 +252,7 @@ help: | /setaddress - Permite que o comprador indique um endereço de pagamento estático (lightning address), off para desativá-lo /setlang - Permite que o usuário altere o idioma /settings - Exibe as configurações atuais do usuário + /requirements - Entrar no assistente de requisitos da contraparte /listorders - O usuário pode listar seus pedidos inacabados /listcurrencies - Lista as moedas que podemos usar sem indicar o valor em satoshis /fiatsent - O comprador indica que já enviou o dinheiro Fiat para o vendedor @@ -706,3 +707,20 @@ unblock_failed: "Erro ao desbloquear o usuário" check_solvers: Sua comunidade ${communityName} não possui solucionadores. Adicione pelo menos um dentro de ${remainingDays} dias para evitar que a comunidade seja desativada. check_solvers_last_warning: Sua comunidade ${communityName} não possui solucionadores. Adicione pelo menos um hoje para evitar que a comunidade seja desativada. image_processing_error: Tivemos um erro ao processar a imagem, por favor aguarde alguns minutos e tente novamente. + +user_requirements: | + Requisitos da contraparte + antiguidade de usuário requerida: ${min_days_using_bot} dias usando o bot. + ordens concluídas: ${min_completed_orders} + + # AJUDA + /counterpartyage <dias> - Define o requisito de antiguidade mínima (em dias) exigido para a contraparte para aceitar suas ordens. + /counterpartyorders <ordens> - Define o requisito mínimo de ordens concluídas pela contraparte para que possam aceitar suas ordens. + /reset - volta esta configuração ao valor padrão + /exit - para sair deste assistente +counterpartyage_updated: Requisito de antiguidade da contraparte atualizado para ${days} dias. +counterpartyorders_updated: Requisito de ordens concluídas da contraparte atualizado para ${orders}. +requirements_reset: Os requisitos da contraparte foram redefinidos para o padrão. +not_meeting_requirements: Você não cumpre os requisitos da contraparte para aceitar esta ordem. +invalid_number: Número inválido. +invalid_range: Valor inválido para o parâmetro ${command}, por favor escolha um número no intervalo [0 - ${max}] diff --git a/locales/ru.yaml b/locales/ru.yaml index 9404f3d8..dcd8df30 100644 --- a/locales/ru.yaml +++ b/locales/ru.yaml @@ -250,6 +250,7 @@ help: | /setaddress <_lightning address / off_> - Позволяет покупателю указать статический платежный адрес (lightning address), _off_ - отключить /setlang - Позволяет пользователю изменить язык /settings - Отображает текущие настройки пользователя + /requirements - Вход в мастер требований к контрагенту /listorders - Пользователь может перечислить свои незавершенные заявки /listcurrencies - Перечислите валюты, которые мы можем использовать без указания суммы в сатоши /fiatsent <_order id_> - Покупатель указывает, что уже отправил фиатные деньги продавцу @@ -707,3 +708,20 @@ unblock_failed: "Ошибка при разблокировке пользова check_solvers: В вашем сообществе ${communityName} нет решателей. Добавьте хотя бы одно в течение ${remainingDays} дн., чтобы сообщество не было отключено. check_solvers_last_warning: В вашем сообществе ${communityName} нет решателей. Пожалуйста, добавьте хотя бы один сегодня, чтобы предотвратить отключение сообщества. image_processing_error: У нас возникла ошибка при обработке изображения, пожалуйста, подождите несколько минут и попробуйте снова. + +user_requirements: | + Требования к контрагенту + Требуемый возраст контрагента: ${min_days_using_bot} дней использования бота. + Выполнено ордеров: ${min_completed_orders} + + # ПОМОЩЬ + /counterpartyage <дней> - Устанавливает минимальный возраст (в днях), необходимый контрагенту для принятия ваших ордеров. + /counterpartyorders <ордеров> - Устанавливает минимальное количество выполненных ордеров контрагентом, чтобы он мог принимать ваши ордера. + /reset - Сбрасывает эти настройки до значений по умолчанию + /exit - Выйти из этого мастера +counterpartyage_updated: Требование к возрасту контрагента обновлено до ${days} дней. +counterpartyorders_updated: Требование к выполненным ордерам контрагента обновлено до ${orders}. +requirements_reset: Требования к контрагенту сброшены до значений по умолчанию. +not_meeting_requirements: Вы не соответствуете требованиям контрагента для принятия этого ордера. +invalid_number: Неверное число. +invalid_range: Недопустимое значение для параметра ${command}, пожалуйста, выберите число в диапазоне [0 - ${max}] diff --git a/locales/uk.yaml b/locales/uk.yaml index c3fcccc8..9039c3fb 100644 --- a/locales/uk.yaml +++ b/locales/uk.yaml @@ -250,6 +250,7 @@ help: | /setaddress <_lightning address / off_> - Дозволяє покупцеві вказати статичну платіжну адресу (lightning address), _off_ - відключено /setlang - Дозволяє користувачеві змінювати мову /settings - відображає поточні налаштування користувача + /requirements - Вхід до майстра вимог до контрагента /listorders - Використовуйте цю команду, щоб переглянути всі Ваші транзакції, що очікують на розгляд. /listcurrencies - Перелічує всі валюти, які ми можемо використовувати, не вказуючи суми в сатоші /fiatsent <_order id_> - Покупець повідомляє, що вже відправив фіатні гроші продавцю @@ -703,3 +704,20 @@ unblock_failed: "Помилка при розблокуванні користу check_solvers: У вашій спільноті ${communityName} немає розв’язувачів. Додайте принаймні одну протягом ${remainingDays} днів, щоб запобігти вимкненню спільноти. check_solvers_last_warning: У вашій спільноті ${communityName} немає розв’язувачів. Будь ласка, додайте принаймні одну сьогодні, щоб запобігти вимкненню спільноти. image_processing_error: У нас виникла помилка при обробці зображення, будь ласка, почекайте кілька хвилин і спробуйте знову. + +user_requirements: | + Вимоги до контрагента + Необхідний вік контрагента: ${min_days_using_bot} днів використання бота. + Виконано ордерів: ${min_completed_orders} + + # ДОПОМОГА + /counterpartyage <днів> - Встановлює мінімальний вік (у днях), необхідний контрагенту для прийняття ваших ордерів. + /counterpartyorders <ордерів> - Встановлює мінімальну кількість виконаних ордерів контрагентом, щоб він міг приймати ваші ордери. + /reset - Скидає ці налаштування до значень за замовчуванням + /exit - Вийти з цього майстра +counterpartyage_updated: Вимога до віку контрагента оновлена до ${days} днів. +counterpartyorders_updated: Вимога до виконаних ордерів контрагента оновлена до ${orders}. +requirements_reset: Вимоги до контрагента скинуті до значень за замовчуванням. +not_meeting_requirements: Ви не відповідаєте вимогам контрагента для прийняття цього ордера. +invalid_number: Невірне число. +invalid_range: Неприпустиме значення для параметра ${command}, будь ласка, виберіть число в діапазоні [0 - ${max}] diff --git a/models/user.ts b/models/user.ts index 699091c8..51c167a7 100644 --- a/models/user.ts +++ b/models/user.ts @@ -25,6 +25,10 @@ export interface UserDocument extends Document { disputes: number; created_at: Date; default_community_id?: string; + counterparty_requirements: { + min_days_using_bot: number; + min_completed_orders: number; + }; } const UserReviewSchema = new Schema({ @@ -51,6 +55,10 @@ const UserSchema = new Schema({ disputes: { type: Number, min: 0, default: 0 }, created_at: { type: Date, default: Date.now }, default_community_id: { type: String }, + counterparty_requirements: { + min_days_using_bot: { type: Number, min: 0, default: 0 }, + min_completed_orders: { type: Number, min: 0, default: 0 }, + }, }); export default mongoose.model('User', UserSchema);