Skip to content

Commit

Permalink
feat!: telegram profile
Browse files Browse the repository at this point in the history
  • Loading branch information
hmbanan666 committed Dec 13, 2024
1 parent c814c30 commit 4f93f21
Show file tree
Hide file tree
Showing 13 changed files with 199 additions and 4 deletions.
1 change: 1 addition & 0 deletions apps/telegram-game/auto-imports.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ declare global {
const useRoute: typeof import('vue-router')['useRoute']
const useRouter: typeof import('vue-router')['useRouter']
const useSlots: typeof import('vue')['useSlots']
const useTelegramProfile: typeof import('./src/composables/useTelegramProfile')['useTelegramProfile']
const useTemplateRef: typeof import('vue')['useTemplateRef']
const viteConfig: typeof import('./vite.config')['default']
const watch: typeof import('vue')['watch']
Expand Down
1 change: 1 addition & 0 deletions apps/telegram-game/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@

<script setup lang="ts">
useBackButton()
useTelegramProfile()
</script>
10 changes: 6 additions & 4 deletions apps/telegram-game/src/components/Game.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,33 @@
<div>Энергия: ??</div>

<div class="opacity-15">
{{ gameClient.websocketService.socket.status.value }} {{ roomConnected }}
{{ game.websocketService.socket.status }} {{ roomConnected }}
</div>
</div>
</div>
</div>
</template>

<script setup lang="ts">
import type { BaseGameAddon } from '@chat-game/game'
import { initData } from '@telegram-apps/sdk-vue'
import { gameClient, roomConnected } from '../utils/gameClient'
const data = initData.user()
const router = useRouter()
const canvas = ref<HTMLElement>()
const game = ref<BaseGameAddon>(gameClient)
const isOpened = ref(false)
onMounted(async () => {
if (!data?.id) {
return
}
await gameClient.init(data.id.toString())
canvas.value?.appendChild(gameClient.app.canvas)
await game.value.init(data.id.toString())
canvas.value?.appendChild(game.value.app.canvas)
return () => gameClient.destroy()
return () => game.value.destroy()
})
watch(router.currentRoute, (value) => {
Expand Down
28 changes: 28 additions & 0 deletions apps/telegram-game/src/composables/useTelegramProfile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { initData } from '@telegram-apps/sdk-vue'
import { useFetch } from '@vueuse/core'

export function useTelegramProfile() {
const user = initData.user()

const { data } = useFetch(`https://chatgame.space/api/telegram/${user?.id}`, {
async onFetchError(ctx) {
if (ctx?.data?.statusCode === 404 && user?.id) {
await fetch('https://chatgame.space/api/telegram/profile', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer 123`,
},
body: JSON.stringify({
telegramId: user.id,
username: user?.username,
}),
})
}

return ctx
},
}).get().json()

return { profile: data }
}
2 changes: 2 additions & 0 deletions apps/telegram-game/src/views/InventoryView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
</div>

<div class="grid grid-cols-4 gap-2">
{{ profile }}
<div v-for="item in items" :key="item.id" class="tg-section-bg aspect-square p-2 rounded-md">
<div>Вещь</div>
</div>
Expand All @@ -24,6 +25,7 @@
import { initData } from '@telegram-apps/sdk-vue'
const data = initData.user()
const { profile } = useTelegramProfile()
const items = [
{
Expand Down
3 changes: 3 additions & 0 deletions apps/website/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ export default defineNuxtConfig({
ssr: false,
cors: true,
},
'/api/**': {
cors: true,
},
},
devtools: { enabled: true },
devServer: {
Expand Down
16 changes: 16 additions & 0 deletions apps/website/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ model Profile {
storytellerPoints Int @default(0) @map("storyteller_points")
collectorPoints Int @default(0) @map("collector_points")
activeEditionId String @map("active_edition_id")
telegramProfileId String? @unique @map("telegram_profile_id")
telegramProfile TelegramProfile? @relation(fields: [telegramProfileId], references: [id])
posts Post[]
quests Quest[]
questEditions QuestEdition[]
Expand All @@ -38,6 +40,20 @@ model Profile {
@@map("profile")
}

model TelegramProfile {
id String @id
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @default(now()) @map("updated_at")
telegramId String @map("telegram_id")
level Int @default(1)
coins Int @default(0)
energy Int @default(0)
username String?
profile Profile?
@@map("telegram_profile")
}

model Payment {
id String @id
createdAt DateTime @default(now()) @map("created_at")
Expand Down
21 changes: 21 additions & 0 deletions apps/website/server/api/telegram/[telegramId].get.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export default defineEventHandler(async (event) => {
try {
const telegramId = getRouterParam(event, 'telegramId')

const profile = await prisma.telegramProfile.findFirst({
where: { telegramId },
include: {
profile: true,
},
})
if (!profile) {
throw createError({
status: 404,
})
}

return profile
} catch (error) {
throw errorResolver(error)
}
})
18 changes: 18 additions & 0 deletions apps/website/server/api/telegram/profile/[id].get.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export default defineEventHandler(async (event) => {
try {
const id = getRouterParam(event, 'id')

const profile = await prisma.telegramProfile.findFirst({
where: { id },
})
if (!profile) {
throw createError({
status: 404,
})
}

return profile
} catch (error) {
throw errorResolver(error)
}
})
27 changes: 27 additions & 0 deletions apps/website/server/api/telegram/profile/index.post.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { DBRepository } from '../../../utils/repository'

export default defineEventHandler(async (event) => {
try {
const body = await readBody(event)

if (!body.telegramId) {
throw createError({
statusCode: 400,
message: 'You must provide telegramId',
})
}

const repository = new DBRepository()
const profile = await repository.findOrCreateTelegramProfile({
telegramId: body.telegramId,
username: body.username,
})

return {
ok: true,
result: profile,
}
} catch (error) {
throw errorResolver(error)
}
})
17 changes: 17 additions & 0 deletions apps/website/server/utils/error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { H3Error } from 'h3'

const logger = useLogger('error')

export function errorResolver(exception: unknown) {
if (exception instanceof H3Error) {
throw exception
}

// Ok, something intereresting happened
logger.error(exception)

return createError({
statusCode: 500,
statusMessage: 'Internal server error',
})
}
47 changes: 47 additions & 0 deletions apps/website/server/utils/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type {
Profile,
ProfileWithTokens,
QuestEdition,
TelegramProfile,
TwitchAccessToken,
TwitchToken,
} from '@chat-game/types'
Expand Down Expand Up @@ -107,6 +108,52 @@ export class DBRepository {
return profile
}

async findOrCreateTelegramProfile({ telegramId, username }: { telegramId: string, username?: string }) {
const profile = await prisma.telegramProfile.findFirst({
where: { telegramId },
})
if (!profile) {
const telegramProfileId = createId()
const profileId = createId()
const editionId = createId()

const createdProfile: TelegramProfile = await prisma.telegramProfile.create({
data: {
id: telegramProfileId,
telegramId,
username,
energy: 10,
},
})

const mainProfile = await this.findOrCreateProfile({
userId: profileId,
userName: `tg_${telegramId}`,
})

// Telegramo
const edition = await prisma.characterEdition.create({
data: {
id: editionId,
profileId: mainProfile.id,
characterId: 'c3hrpu39wodc2nlv6pmgmm2k',
},
})

await prisma.profile.update({
where: { id: mainProfile.id },
data: {
telegramProfileId,
activeEditionId: edition.id,
},
})

return createdProfile
}

return profile
}

async findCharacterByEditionId(editionId: string): Promise<CharacterEditionWithCharacter> {
const char = await prisma.characterEdition.findFirst({
where: { id: editionId },
Expand Down
12 changes: 12 additions & 0 deletions packages/types/src/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export interface Profile {
createdAt: Date
updatedAt: Date
twitchId: string
telegramProfileId: string | null
userName: string
isStreamer: boolean
coupons: number
Expand Down Expand Up @@ -42,6 +43,17 @@ export interface ProfileCreateResponse {
result: Profile
}

export interface TelegramProfile {
id: string
createdAt: Date
updatedAt: Date
telegramId: string
username: string | null
level: number
coins: number
energy: number
}

export interface TokenCreateRequest {
data: {
code: string
Expand Down

0 comments on commit 4f93f21

Please sign in to comment.