mirror of
https://github.com/whekin/household-bot.git
synced 2026-03-31 22:54:02 +00:00
feat(onboarding): add mini app household join flow
This commit is contained in:
@@ -4,6 +4,8 @@ import { createDbClient, schema } from '@household/db'
|
||||
import {
|
||||
HOUSEHOLD_TOPIC_ROLES,
|
||||
type HouseholdConfigurationRepository,
|
||||
type HouseholdJoinTokenRecord,
|
||||
type HouseholdPendingMemberRecord,
|
||||
type HouseholdTelegramChatRecord,
|
||||
type HouseholdTopicBindingRecord,
|
||||
type HouseholdTopicRole,
|
||||
@@ -50,6 +52,38 @@ function toHouseholdTopicBindingRecord(row: {
|
||||
}
|
||||
}
|
||||
|
||||
function toHouseholdJoinTokenRecord(row: {
|
||||
householdId: string
|
||||
householdName: string
|
||||
token: string
|
||||
createdByTelegramUserId: string | null
|
||||
}): HouseholdJoinTokenRecord {
|
||||
return {
|
||||
householdId: row.householdId,
|
||||
householdName: row.householdName,
|
||||
token: row.token,
|
||||
createdByTelegramUserId: row.createdByTelegramUserId
|
||||
}
|
||||
}
|
||||
|
||||
function toHouseholdPendingMemberRecord(row: {
|
||||
householdId: string
|
||||
householdName: string
|
||||
telegramUserId: string
|
||||
displayName: string
|
||||
username: string | null
|
||||
languageCode: string | null
|
||||
}): HouseholdPendingMemberRecord {
|
||||
return {
|
||||
householdId: row.householdId,
|
||||
householdName: row.householdName,
|
||||
telegramUserId: row.telegramUserId,
|
||||
displayName: row.displayName,
|
||||
username: row.username,
|
||||
languageCode: row.languageCode
|
||||
}
|
||||
}
|
||||
|
||||
export function createDbHouseholdConfigurationRepository(databaseUrl: string): {
|
||||
repository: HouseholdConfigurationRepository
|
||||
close: () => Promise<void>
|
||||
@@ -261,6 +295,208 @@ export function createDbHouseholdConfigurationRepository(databaseUrl: string): {
|
||||
.orderBy(schema.householdTopicBindings.role)
|
||||
|
||||
return rows.map(toHouseholdTopicBindingRecord)
|
||||
},
|
||||
|
||||
async upsertHouseholdJoinToken(input) {
|
||||
const rows = await db
|
||||
.insert(schema.householdJoinTokens)
|
||||
.values({
|
||||
householdId: input.householdId,
|
||||
token: input.token,
|
||||
createdByTelegramUserId: input.createdByTelegramUserId ?? null
|
||||
})
|
||||
.onConflictDoUpdate({
|
||||
target: [schema.householdJoinTokens.householdId],
|
||||
set: {
|
||||
token: input.token,
|
||||
createdByTelegramUserId: input.createdByTelegramUserId ?? null,
|
||||
updatedAt: new Date()
|
||||
}
|
||||
})
|
||||
.returning({
|
||||
householdId: schema.householdJoinTokens.householdId,
|
||||
token: schema.householdJoinTokens.token,
|
||||
createdByTelegramUserId: schema.householdJoinTokens.createdByTelegramUserId
|
||||
})
|
||||
|
||||
const row = rows[0]
|
||||
if (!row) {
|
||||
throw new Error('Failed to save household join token')
|
||||
}
|
||||
|
||||
const householdRows = await db
|
||||
.select({
|
||||
householdId: schema.households.id,
|
||||
householdName: schema.households.name
|
||||
})
|
||||
.from(schema.households)
|
||||
.where(eq(schema.households.id, row.householdId))
|
||||
.limit(1)
|
||||
|
||||
const household = householdRows[0]
|
||||
if (!household) {
|
||||
throw new Error('Failed to resolve household for join token')
|
||||
}
|
||||
|
||||
return toHouseholdJoinTokenRecord({
|
||||
householdId: row.householdId,
|
||||
householdName: household.householdName,
|
||||
token: row.token,
|
||||
createdByTelegramUserId: row.createdByTelegramUserId
|
||||
})
|
||||
},
|
||||
|
||||
async getHouseholdJoinToken(householdId) {
|
||||
const rows = await db
|
||||
.select({
|
||||
householdId: schema.householdJoinTokens.householdId,
|
||||
householdName: schema.households.name,
|
||||
token: schema.householdJoinTokens.token,
|
||||
createdByTelegramUserId: schema.householdJoinTokens.createdByTelegramUserId
|
||||
})
|
||||
.from(schema.householdJoinTokens)
|
||||
.innerJoin(
|
||||
schema.households,
|
||||
eq(schema.householdJoinTokens.householdId, schema.households.id)
|
||||
)
|
||||
.where(eq(schema.householdJoinTokens.householdId, householdId))
|
||||
.limit(1)
|
||||
|
||||
const row = rows[0]
|
||||
return row ? toHouseholdJoinTokenRecord(row) : null
|
||||
},
|
||||
|
||||
async getHouseholdByJoinToken(token) {
|
||||
const rows = await db
|
||||
.select({
|
||||
householdId: schema.householdJoinTokens.householdId,
|
||||
householdName: schema.households.name,
|
||||
telegramChatId: schema.householdTelegramChats.telegramChatId,
|
||||
telegramChatType: schema.householdTelegramChats.telegramChatType,
|
||||
title: schema.householdTelegramChats.title
|
||||
})
|
||||
.from(schema.householdJoinTokens)
|
||||
.innerJoin(
|
||||
schema.households,
|
||||
eq(schema.householdJoinTokens.householdId, schema.households.id)
|
||||
)
|
||||
.innerJoin(
|
||||
schema.householdTelegramChats,
|
||||
eq(schema.householdJoinTokens.householdId, schema.householdTelegramChats.householdId)
|
||||
)
|
||||
.where(eq(schema.householdJoinTokens.token, token))
|
||||
.limit(1)
|
||||
|
||||
const row = rows[0]
|
||||
return row ? toHouseholdTelegramChatRecord(row) : null
|
||||
},
|
||||
|
||||
async upsertPendingHouseholdMember(input) {
|
||||
const rows = await db
|
||||
.insert(schema.householdPendingMembers)
|
||||
.values({
|
||||
householdId: input.householdId,
|
||||
telegramUserId: input.telegramUserId,
|
||||
displayName: input.displayName,
|
||||
username: input.username?.trim() || null,
|
||||
languageCode: input.languageCode?.trim() || null
|
||||
})
|
||||
.onConflictDoUpdate({
|
||||
target: [
|
||||
schema.householdPendingMembers.householdId,
|
||||
schema.householdPendingMembers.telegramUserId
|
||||
],
|
||||
set: {
|
||||
displayName: input.displayName,
|
||||
username: input.username?.trim() || null,
|
||||
languageCode: input.languageCode?.trim() || null,
|
||||
updatedAt: new Date()
|
||||
}
|
||||
})
|
||||
.returning({
|
||||
householdId: schema.householdPendingMembers.householdId,
|
||||
telegramUserId: schema.householdPendingMembers.telegramUserId,
|
||||
displayName: schema.householdPendingMembers.displayName,
|
||||
username: schema.householdPendingMembers.username,
|
||||
languageCode: schema.householdPendingMembers.languageCode
|
||||
})
|
||||
|
||||
const row = rows[0]
|
||||
if (!row) {
|
||||
throw new Error('Failed to save pending household member')
|
||||
}
|
||||
|
||||
const householdRows = await db
|
||||
.select({
|
||||
householdId: schema.households.id,
|
||||
householdName: schema.households.name
|
||||
})
|
||||
.from(schema.households)
|
||||
.where(eq(schema.households.id, row.householdId))
|
||||
.limit(1)
|
||||
|
||||
const household = householdRows[0]
|
||||
if (!household) {
|
||||
throw new Error('Failed to resolve household for pending member')
|
||||
}
|
||||
|
||||
return toHouseholdPendingMemberRecord({
|
||||
householdId: row.householdId,
|
||||
householdName: household.householdName,
|
||||
telegramUserId: row.telegramUserId,
|
||||
displayName: row.displayName,
|
||||
username: row.username,
|
||||
languageCode: row.languageCode
|
||||
})
|
||||
},
|
||||
|
||||
async getPendingHouseholdMember(householdId, telegramUserId) {
|
||||
const rows = await db
|
||||
.select({
|
||||
householdId: schema.householdPendingMembers.householdId,
|
||||
householdName: schema.households.name,
|
||||
telegramUserId: schema.householdPendingMembers.telegramUserId,
|
||||
displayName: schema.householdPendingMembers.displayName,
|
||||
username: schema.householdPendingMembers.username,
|
||||
languageCode: schema.householdPendingMembers.languageCode
|
||||
})
|
||||
.from(schema.householdPendingMembers)
|
||||
.innerJoin(
|
||||
schema.households,
|
||||
eq(schema.householdPendingMembers.householdId, schema.households.id)
|
||||
)
|
||||
.where(
|
||||
and(
|
||||
eq(schema.householdPendingMembers.householdId, householdId),
|
||||
eq(schema.householdPendingMembers.telegramUserId, telegramUserId)
|
||||
)
|
||||
)
|
||||
.limit(1)
|
||||
|
||||
const row = rows[0]
|
||||
return row ? toHouseholdPendingMemberRecord(row) : null
|
||||
},
|
||||
|
||||
async findPendingHouseholdMemberByTelegramUserId(telegramUserId) {
|
||||
const rows = await db
|
||||
.select({
|
||||
householdId: schema.householdPendingMembers.householdId,
|
||||
householdName: schema.households.name,
|
||||
telegramUserId: schema.householdPendingMembers.telegramUserId,
|
||||
displayName: schema.householdPendingMembers.displayName,
|
||||
username: schema.householdPendingMembers.username,
|
||||
languageCode: schema.householdPendingMembers.languageCode
|
||||
})
|
||||
.from(schema.householdPendingMembers)
|
||||
.innerJoin(
|
||||
schema.households,
|
||||
eq(schema.householdPendingMembers.householdId, schema.households.id)
|
||||
)
|
||||
.where(eq(schema.householdPendingMembers.telegramUserId, telegramUserId))
|
||||
.limit(1)
|
||||
|
||||
const row = rows[0]
|
||||
return row ? toHouseholdPendingMemberRecord(row) : null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user