Skip to content

Commit

Permalink
feat: add QRCode functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
roziscoding committed Oct 21, 2022
1 parent 3ed5753 commit 1ae854b
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 35 deletions.
37 changes: 6 additions & 31 deletions api/qrcode.ts
Original file line number Diff line number Diff line change
@@ -1,42 +1,17 @@
import { promisify } from 'util'
import { QRCodeSegment, toDataURL } from 'qrcode'
import { VercelRequest, VercelResponse } from '@vercel/node'
import { Db, MongoClient } from 'mongodb'
import { config } from '../src/config'
import { UserRepository } from '../src/repositories/users'
import { getPixCodeForUser } from '../src/util/pixCode'
import { QRCodeSegment, toDataURL } from 'qrcode'
import { promisify } from 'util'
import { pngToJpeg } from '../src/util/image'

const createQrCode = promisify<string | QRCodeSegment[], string>(toDataURL)

let db: Db = null as any

export default async function (req: VercelRequest, res: VercelResponse) {
if (!db) {
db = await MongoClient.connect(config.database.uri, {
useNewUrlParser: true,
useUnifiedTopology: true
}).then((connection) => connection.db(config.database.dbName))
}

const telegramId = Number(req.query.telegramId)
const amount = req.query.value

if (isNaN(telegramId) || !amount || typeof amount !== 'string') {
return res.status(403).end()
}

const userRepository = new UserRepository(db)

const user = await userRepository.findByTelegramId(Number(req.query.telegramId))

if (!user) {
return res.status(401).end()
}
const pixCode = req.query.pixCode

const pixCode = getPixCodeForUser(user, amount)
if (!pixCode) return res.status(422).json({ message: 'missing pixCode param' })
if (Array.isArray(pixCode)) return res.status(422).json({ message: 'more than one pixCode provided' })

const buffer = await createQrCode([{ data: pixCode as string, mode: 'byte' }])
const buffer = await createQrCode([{ data: Buffer.from(pixCode), mode: 'byte' }])
.then((url) => url.split(',')[1])
.then((base64) => Buffer.from(base64!, 'base64'))
.then((buffer) => pngToJpeg(buffer))
Expand Down
6 changes: 4 additions & 2 deletions src/bot.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { ConversationFlavor, conversations as grammyConversations } from '@grammyjs/conversations'
import { FileAdapter } from '@grammyjs/storage-file'
import { ISession, MongoDBAdapter } from '@grammyjs/storage-mongodb'
import { Bot, Context, session, SessionFlavor } from 'grammy'
import { MongoClient } from 'mongodb'

import * as commands from './commands'
import { AppConfig } from './config'
import * as conversations from './conversations'
import * as handlers from './handlers'
import { qrCodeUrl, QRCodeUrlContext } from './util/qr-code-url'
import { ISession, MongoDBAdapter } from './util/storage-adapter'

export type AppSession = {
Expand All @@ -17,7 +17,7 @@ export type AppSession = {
query?: string
}

export type AppContext = Context & ConversationFlavor & SessionFlavor<AppSession>
export type AppContext = Context & ConversationFlavor & SessionFlavor<AppSession> & QRCodeUrlContext

async function getStorage(config: AppConfig) {
if (config.env !== 'production') return new FileAdapter<AppSession>({ dirName: 'sessions' })
Expand All @@ -35,6 +35,8 @@ async function getStorage(config: AppConfig) {
export async function getBot(config: AppConfig) {
const bot = new Bot<AppContext>(config.telegram.token)

bot.use(qrCodeUrl(config))

bot.use(
session({
getSessionKey: (ctx) => ctx.from?.id.toString(),
Expand Down
5 changes: 3 additions & 2 deletions src/handlers/registered.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { stripIndents } from 'common-tags'
import { Bot, InlineKeyboard } from 'grammy'
import { AppContext } from '../bot'
import { getPixCodeForUser } from '../util/pixCode'
import { getPixCodeForUser } from '../util/pix-code'
import { evaluateQuery } from '../util/query'

export function install(bot: Bot<AppContext>) {
Expand All @@ -21,6 +21,7 @@ export function install(bot: Bot<AppContext>) {
if (!amount) return ctx.answerInlineQuery([])

const pixCode = getPixCodeForUser(ctx.session, amount)
const qrCodeUrl = ctx.getQrCodeUrl(pixCode)

return ctx.answerInlineQuery([
{
Expand All @@ -29,7 +30,7 @@ export function install(bot: Bot<AppContext>) {
title: `Gerar código pix de R$ ${amount}`,
input_message_content: {
message_text: stripIndents`
Para me transferir R$ ${amount}, escaneie o QRCode ou utilize o código abaixo (clique no código para copiar):
Para me transferir R$ ${amount}, escaneie o <a href="${qrCodeUrl}">QRCode</a> ou utilize o código abaixo (clique no código para copiar):
<code>${pixCode}</code>
`,
Expand Down
11 changes: 11 additions & 0 deletions src/util/qr-code-url.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Context, MiddlewareFn } from 'grammy'
import { AppConfig } from '../config'

export type QRCodeUrlContext = Context & { getQrCodeUrl: (pixCode: string) => string }

export const qrCodeUrl =
(config: AppConfig): MiddlewareFn<QRCodeUrlContext> =>
(ctx, next) => {
ctx.getQrCodeUrl = (pixCode) => `${config.webhook.url}/api/qrcode?pixCode=${pixCode}`
return next()
}

0 comments on commit 1ae854b

Please sign in to comment.