Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions apps/atrium-telegram/app/components/StaffBlock.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<template>
<div class="max-w-full overflow-x-scroll overflow-y-hidden snap-x hide-scroll">
<div class="w-max flex flex-row flex-wrap gap-3.5">
<div class="w-max flex flex-row flex-wrap gap-1">
<div
v-for="user in allUsers"
:key="user.id"
class="w-14 flex flex-col gap-1 justify-start items-center scroll-ml-6 snap-start motion-preset-slide-right"
class="w-18 flex flex-col gap-1 justify-start items-center scroll-ml-6 snap-start motion-preset-slide-right"
@click="handleClick(user.id)"
>
<div class="relative">
Expand All @@ -26,7 +26,11 @@
</div>
</div>

<p class="text-xs/3 text-muted text-center">
<p class="text-xs/3 font-bold text-center line-clamp-2">
{{ user.name }}
</p>

<p class="text-xs/3 text-muted text-center line-clamp-2">
{{ user.isOnline ? 'Онлайн' : useTimeAgoIntl(new Date(user.onlineAt ?? '')) }}
</p>
</div>
Expand Down
6 changes: 5 additions & 1 deletion apps/atrium-telegram/app/pages/startapp.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<UIcon name="i-lucide-loader" class="animate-spin" />
<UIcon name="i-lucide-loader" class="size-8 text-primary animate-spin" />
</template>

<script setup lang="ts">
Expand All @@ -21,6 +21,10 @@ if (tgWebAppStartParam?.length && tgWebAppStartParam.includes(separator)) {
if (key === 'epic') {
await navigateTo(`/epic/${value}`)
}

if (key === 'flow') {
await navigateTo(`/flow/${value}`)
}
} else {
await navigateTo('/')
}
Expand Down
21 changes: 19 additions & 2 deletions apps/web-app/server/tasks/ai/daily-report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,30 @@ export default defineTask({

// Flow item
const date = format(new Date(), 'd MMMM', { locale: ru })
await repository.flow.createItem({
const flowItem = await repository.flow.createItem({
type: 'daily_task_report',
title: `Задачи ${date}`,
description: finalMessage,
})
Comment on lines +58 to 62

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Guard against missing flowItem.id to avoid sending broken links.

If createItem fails or returns no id, the URL becomes ...startapp=flowzzzzzundefined. Bail out early.

       const flowItem = await repository.flow.createItem({
         type: 'daily_task_report',
         title: `Задачи ${date}`,
         description: finalMessage,
       })
+
+      if (!flowItem?.id) {
+        logger.warn('daily-report: flow item was not created or has no id; skipping Telegram post')
+        return { result: true }
+      }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const flowItem = await repository.flow.createItem({
type: 'daily_task_report',
title: `Задачи ${date}`,
description: finalMessage,
})
const flowItem = await repository.flow.createItem({
type: 'daily_task_report',
title: `Задачи ${date}`,
description: finalMessage,
})
if (!flowItem?.id) {
logger.warn('daily-report: flow item was not created or has no id; skipping Telegram post')
return { result: true }
}
🤖 Prompt for AI Agents
In apps/web-app/server/tasks/ai/daily-report.ts around lines 58 to 62, the code
assumes repository.flow.createItem returns an object with id and will build a
URL using flowItem.id; add a guard to check that flowItem exists and has a
truthy id before proceeding to build or send any links — if missing, log an
error/warning and return early (or throw) to avoid producing a URL containing
"undefined". Ensure any callers handle this early exit and include a clear log
message with the failed response details for debugging.


await useAtriumBot().api.sendMessage(telegram.teamGroupId, finalMessage)
const separator = 'zzzzz'
const startAppData = `flow${separator}${flowItem?.id}`

Comment on lines +64 to +66

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Encode and centralize startapp payload.

  • URL-encode the payload to be safe.
  • Reuse a shared TG_STARTAPP_SEPARATOR constant across server and client.
-      const separator = 'zzzzz'
-      const startAppData = `flow${separator}${flowItem?.id}`
+      const separator = 'zzzzz' // TODO: import from shared constants
+      const startAppData = `flow${separator}${flowItem.id}`
+      const startAppParam = encodeURIComponent(startAppData)

Verification helper:


🏁 Script executed:

#!/bin/bash
# Check all usages of the separator and startapp param construction.
rg -nP "zzzzz|startapp=" -C2

Length of output: 2436


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== apps/web-app/server/tasks/ai/daily-report.ts ==="
nl -ba apps/web-app/server/tasks/ai/daily-report.ts | sed -n '1,220p' || true

echo
echo "=== apps/web-app/server/api/beacon/epic/comment.post.ts ==="
nl -ba apps/web-app/server/api/beacon/epic/comment.post.ts | sed -n '1,220p' || true

echo
echo "=== apps/atrium-telegram/app/pages/startapp.vue ==="
nl -ba apps/atrium-telegram/app/pages/startapp.vue | sed -n '1,240p' || true

echo
echo "=== apps/storefront-telegram/app/pages/startapp.vue ==="
nl -ba apps/storefront-telegram/app/pages/startapp.vue | sed -n '1,240p' || true

Length of output: 389


Centralize TG_STARTAPP_SEPARATOR and URL‑encode startapp payload

Local 'zzzzz' separator found in:

  • apps/web-app/server/tasks/ai/daily-report.ts
  • apps/web-app/server/api/beacon/epic/comment.post.ts
  • apps/atrium-telegram/app/pages/startapp.vue
  • apps/storefront-telegram/app/pages/startapp.vue

Actions:

  • Export a single TG_STARTAPP_SEPARATOR from a shared module and import it in all server/client files (replace each local "zzzzz").
  • Encode the payload on the server: const startAppParam = encodeURIComponent(startAppData); use ?startapp=${startAppParam} in URLs.
  • Decode on the client before parsing: const startAppData = decodeURIComponent(tgWebAppStartParam as string || ''); then split by TG_STARTAPP_SEPARATOR.
  • Do not remove optional chaining (e.g., flowItem?.id) unless you verify the value is always present.
🤖 Prompt for AI Agents
In apps/web-app/server/tasks/ai/daily-report.ts around lines 64-66, replace the
local separator ('zzzzz') with a shared constant exported from a common module
(e.g., TG_STARTAPP_SEPARATOR) and import it here and in the other listed files;
when building the startapp payload, URL-encode it on the server (use
encodeURIComponent) and use ?startapp=<encoded> in generated URLs; on the client
decode with decodeURIComponent before parsing (then split by
TG_STARTAPP_SEPARATOR) and keep optional chaining (e.g., flowItem?.id) as-is
unless you can guarantee the value is present.

// Get first words
const messageIntro = finalMessage.split(' ').slice(0, 40).join(' ')
const preparedMessage = `${messageIntro}...\n\nПродолжение внутри Атриума? 🙃`

await useAtriumBot().api.sendMessage(telegram.teamGroupId, preparedMessage, {
link_preview_options: {
is_disabled: true,
},
reply_markup: {
inline_keyboard: [[{
text: '👉 Открыть Атриум',
url: `https://t.me/sushi_atrium_bot/app?startapp=${startAppData}`,
}]],
},
})
} catch (error) {
errorResolver(error)
}
Expand Down