Skip to content

Commit 7cd9162

Browse files
authored
feat: wasabi vista user (#49)
* feat: wasabi vista user * chore: check code * fix: remove code from log * chore: updates
1 parent 6515f94 commit 7cd9162

5 files changed

Lines changed: 126 additions & 15 deletions

File tree

apps/web-app/server/services/telegram/wasabi-vista.ts

Lines changed: 50 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { repository } from '@roll-stack/database'
12
import { Bot } from 'grammy'
23

34
const logger = useLogger('telegram:wasabi-vista')
@@ -12,27 +13,50 @@ export async function useCreateWasabiVistaBot() {
1213
// const locale = ctx.message.from.language_code
1314

1415
if (ctx.hasCommand('start')) {
15-
// Welcome message with buttons
16-
await ctx.reply(
17-
`Ключ доступа: ${generateAccessCode()}`,
18-
// {
19-
// reply_markup: {
20-
// inline_keyboard: [
21-
// [{ text: dictionary(locale).bots.woodland.title, url: woodlandsBotUrl }],
22-
// [{ text: dictionary(locale).bots.subscribeToChannel, url: gameChannelUrl }],
23-
// [{ text: dictionary(locale).bots.chatgame.playingOnTwitch, url: twitchUrl }],
24-
// ],
25-
// },
26-
// },
27-
)
16+
// Not private chat?
17+
if (ctx.message.chat.type !== 'private') {
18+
await ctx.reply('Я пока не умею отвечать на групповые сообщения.')
19+
return
20+
}
2821

22+
// Find user
23+
const wasabiVistaUser = await repository.wasabiVista.findUserByTelegramId(ctx.message.from.id.toString())
24+
if (!wasabiVistaUser) {
25+
const accessKey = await generateAccessCode()
26+
27+
const createdUser = await repository.wasabiVista.createUser({
28+
telegramId: ctx.message.from.id.toString(),
29+
accessKey,
30+
firstName: ctx.message.from.first_name,
31+
lastName: ctx.message.from.last_name,
32+
username: ctx.message.from.username,
33+
})
34+
35+
logger.log('new user', createdUser.id, ctx.message.from.id, ctx.message.text)
36+
37+
await ctx.reply(`Ключ доступа: ${accessKey}`)
38+
39+
return
40+
}
41+
42+
if (!wasabiVistaUser.user) {
43+
await ctx.reply('Нет доступа. Используйте ранее полученный Ключ доступа. Или передайте его в службу поддержки.')
44+
return
45+
}
46+
47+
await ctx.reply('Вы уже авторизованы.')
2948
return
3049
}
3150

3251
logger.log(ctx.message.from.id, ctx.message.text)
3352
ctx.reply('Я пока не умею отвечать на сообщения.')
3453
})
3554

55+
// Somebody invited bot to a group
56+
bot.on('my_chat_member', async (ctx) => {
57+
logger.log(ctx.chat, ctx.chatMember, ctx.message)
58+
})
59+
3660
try {
3761
await bot.start()
3862
logger.info('Wasabi Vista bot started successfully')
@@ -54,6 +78,17 @@ export async function notifyWasabiVistaAdmin(message: string) {
5478
return useWasabiVistaBot().api.sendMessage(telegram.adminId, message)
5579
}
5680

57-
function generateAccessCode(): string {
58-
return getRandInteger(100000, 999999).toString()
81+
async function generateAccessCode(): Promise<string> {
82+
let selectedCode
83+
84+
// Code should be unique
85+
while (!selectedCode) {
86+
const code = getRandInteger(100000, 999999).toString()
87+
const wasabiVistaUser = await repository.wasabiVista.findUserByKey(code)
88+
if (!wasabiVistaUser) {
89+
selectedCode = code
90+
}
91+
}
92+
93+
return selectedCode
5994
}

packages/database/src/repository/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { Print } from './print'
1919
import { Product } from './product'
2020
import { Task } from './task'
2121
import { User } from './user'
22+
import { WasabiVista } from './wasabi-vista'
2223

2324
class Repository {
2425
readonly channel = Channel
@@ -41,6 +42,7 @@ class Repository {
4142
readonly product = Product
4243
readonly task = Task
4344
readonly user = User
45+
readonly wasabiVista = WasabiVista
4446

4547
async checkHealth(): Promise<boolean> {
4648
await useDatabase().query.users.findFirst()
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import type { WasabiVistaUserDraft } from '../types'
2+
import { eq, sql } from 'drizzle-orm'
3+
import { useDatabase } from '../database'
4+
import { wasabiVistaUsers } from '../tables'
5+
6+
export class WasabiVista {
7+
static async findUser(id: string) {
8+
return useDatabase().query.wasabiVistaUsers.findFirst({
9+
where: (users, { eq }) => eq(users.id, id),
10+
})
11+
}
12+
13+
static async findUserByKey(key: string) {
14+
return useDatabase().query.wasabiVistaUsers.findFirst({
15+
where: (users, { eq }) => eq(users.accessKey, key),
16+
})
17+
}
18+
19+
static async findUserByTelegramId(telegramId: string) {
20+
return useDatabase().query.wasabiVistaUsers.findFirst({
21+
where: (users, { eq }) => eq(users.telegramId, telegramId),
22+
with: {
23+
user: true,
24+
},
25+
})
26+
}
27+
28+
static async createUser(data: WasabiVistaUserDraft) {
29+
const [user] = await useDatabase().insert(wasabiVistaUsers).values(data).returning()
30+
return user
31+
}
32+
33+
static async updateUser(id: string, data: Partial<WasabiVistaUserDraft>) {
34+
const [user] = await useDatabase()
35+
.update(wasabiVistaUsers)
36+
.set({
37+
...data,
38+
updatedAt: sql`now()`,
39+
})
40+
.where(eq(wasabiVistaUsers.id, id))
41+
.returning()
42+
return user
43+
}
44+
45+
static async deleteUser(id: string) {
46+
return useDatabase().delete(wasabiVistaUsers).where(eq(wasabiVistaUsers.id, id))
47+
}
48+
}

packages/database/src/tables.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,21 @@ export const networkMetrics = pgTable('network_metrics', {
589589
averageCheck: numeric('average_check', { mode: 'number' }).notNull().default(0),
590590
})
591591

592+
export const wasabiVistaUsers = pgTable('wasabi_vista_users', {
593+
id: cuid2('id').defaultRandom().primaryKey(),
594+
createdAt: timestamp('created_at', { precision: 3, withTimezone: true, mode: 'string' }).notNull().defaultNow(),
595+
updatedAt: timestamp('updated_at', { precision: 3, withTimezone: true, mode: 'string' }).notNull().defaultNow(),
596+
accessKey: varchar('access_key').notNull().unique(),
597+
telegramId: varchar('telegram_id').notNull().unique(),
598+
firstName: varchar('first_name'),
599+
lastName: varchar('last_name'),
600+
username: varchar('username'),
601+
userId: cuid2('user_id').references(() => users.id, {
602+
onDelete: 'cascade',
603+
onUpdate: 'cascade',
604+
}),
605+
})
606+
592607
export const userRelations = relations(users, ({ many, one }) => ({
593608
chatMessages: many(chatMessages),
594609
chatMembers: many(chatMembers),
@@ -601,6 +616,7 @@ export const userRelations = relations(users, ({ many, one }) => ({
601616
}),
602617
postLikes: many(postLikes),
603618
postComments: many(postComments),
619+
wasabiVistaUsers: many(wasabiVistaUsers),
604620
}))
605621

606622
export const partnerRelations = relations(partners, ({ many, one }) => ({
@@ -943,3 +959,10 @@ export const clientReviewRelations = relations(clientReviews, ({ one }) => ({
943959
references: [kitchens.id],
944960
}),
945961
}))
962+
963+
export const wasabiVistaUserRelations = relations(wasabiVistaUsers, ({ one }) => ({
964+
user: one(users, {
965+
fields: [wasabiVistaUsers.userId],
966+
references: [users.id],
967+
}),
968+
}))

packages/database/src/types.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,3 +128,6 @@ export type ClientReviewDraft = InferInsertModel<typeof tables.clientReviews>
128128

129129
export type NetworkMetrics = InferSelectModel<typeof tables.networkMetrics>
130130
export type NetworkMetricsDraft = InferInsertModel<typeof tables.networkMetrics>
131+
132+
export type WasabiVistaUser = InferSelectModel<typeof tables.wasabiVistaUsers>
133+
export type WasabiVistaUserDraft = InferInsertModel<typeof tables.wasabiVistaUsers>

0 commit comments

Comments
 (0)