From b7e5b87b01dba96a9091e7682429f180aee79724 Mon Sep 17 00:00:00 2001 From: simon renlund Date: Thu, 25 Jan 2024 19:04:03 +0200 Subject: [PATCH] Add export command --- backend/.env.template | 1 + backend/src/config.ts | 2 ++ backend/src/index.ts | 37 +++++++++++++++++++++++++++++++------ backend/src/transactions.ts | 5 +++++ 4 files changed, 39 insertions(+), 6 deletions(-) diff --git a/backend/.env.template b/backend/.env.template index 41fb430..4af10ad 100644 --- a/backend/.env.template +++ b/backend/.env.template @@ -1,5 +1,6 @@ BOT_TOKEN="" CHAT_ID="" +ADMIN_CHAT_ID="" PGDATABASE="spiken" PGHOST="localhost" PGUSER="spiken" diff --git a/backend/src/config.ts b/backend/src/config.ts index 48892b7..0c12d1c 100644 --- a/backend/src/config.ts +++ b/backend/src/config.ts @@ -4,9 +4,11 @@ import 'dotenv/config' const processEnvSchema = z.object({ BOT_TOKEN: z.string(), CHAT_ID: z.string().transform((val) => Number(val)), + ADMIN_CHAT_ID: z.string().transform((val) => Number(val)), }) const typedProcessEnv = processEnvSchema.parse(process.env) export const config = { botToken: typedProcessEnv.BOT_TOKEN, chatId: typedProcessEnv.CHAT_ID, + adminChatId: typedProcessEnv.ADMIN_CHAT_ID, } diff --git a/backend/src/index.ts b/backend/src/index.ts index 012c0ef..ae861f1 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -1,11 +1,15 @@ import { Context, Telegraf } from 'telegraf' import { config } from './config.js' -import { getBalanceForMember, purchaseItemForMember } from './transactions.js' +import { + exportTransactions, + getBalanceForMember, + purchaseItemForMember, +} from './transactions.js' import { Message, Update } from '@telegraf/types' /* Toiveiden tynnyri: -- Admin interface, lägg till/ta bort produkter, csv transaction dump, lägg till/ta bort saldo +- Admin interface, lägg till/ta bort produkter, lägg till/ta bort saldo - Skamlistan, posta alla med negativt i chatten med en @ - En 'vapaa myynti' command med description och summa - "Undo" funktionalitet @@ -24,7 +28,7 @@ bot.use(async (ctx, next) => { if (!ctx.from) { return } - if (!(await isChatMember(ctx.from.id))) { + if (!(await isChatMember(ctx.from.id, config.chatId))) { return ctx.reply('sii dej i reven!') } await next() @@ -110,6 +114,27 @@ bot.command('start', async (ctx) => { return ctx.reply(info_message) }) +bot.command('exportera', async (ctx) => { + if (!(await isChatMember(ctx.from.id, config.adminChatId))) { + return ctx.reply('sii dej i reven, pleb!') + } + const res = await exportTransactions() + const headers = res.fields.map((field) => field.name) + const rows = res.rows.map((row) => { + return headers + .map((header) => { + return (String(row[header]) ?? '').replace(',', '') + }) + .join(', ') + }) + const csv = `${headers.join(', ')} + ${rows.join('\n')}` + ctx.replyWithDocument({ + source: Buffer.from(csv, 'utf-8'), + filename: `spiken-dump-${new Date().toISOString()}.csv`, + }) +}) + bot.telegram.setMyCommands([ ...commands.map(({ command, description, priceCents }) => ({ command, @@ -118,7 +143,7 @@ bot.telegram.setMyCommands([ ).toFixed(2)}€`, })), { command: 'saldo', description: 'Kontrollera saldo' }, - { command: 'info', description: 'Visar information om bottens användning'} + { command: 'info', description: 'Visar information om bottens användning' }, ]) bot.launch() @@ -127,10 +152,10 @@ bot.launch() process.once('SIGINT', () => bot.stop('SIGINT')) process.once('SIGTERM', () => bot.stop('SIGTERM')) -const isChatMember = async (userId: number) => { +const isChatMember = async (userId: number, chatId: number) => { const acceptedStatuses = ['creator', 'administrator', 'member', 'owner'] try { - const member = await bot.telegram.getChatMember(config.chatId, userId) + const member = await bot.telegram.getChatMember(chatId, userId) return acceptedStatuses.includes(member.status) } catch (e) { console.log('Error checking group membership:', e) diff --git a/backend/src/transactions.ts b/backend/src/transactions.ts index c9998b0..a2c6a5e 100644 --- a/backend/src/transactions.ts +++ b/backend/src/transactions.ts @@ -42,6 +42,11 @@ export const getBalanceForMember = async (userId: number) => { } } +export const exportTransactions = async () => { + const res = await pool.query(`SELECT * FROM transactions`) + return res +} + const BalanceResponseSchema = z .array( z.object({