@jant/core 0.5.4 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/bin/commands/telegram/register-webhooks.js +93 -0
  2. package/dist/app-CMSW_AYG.js +6 -0
  3. package/dist/{app-BtNdUAqz.js → app-DYQdDMs8.js} +2249 -387
  4. package/dist/client/.vite/manifest.json +3 -3
  5. package/dist/client/_assets/client-BRTh1ii1.js +274 -0
  6. package/dist/client/_assets/client-CO4b-RKd.css +2 -0
  7. package/dist/client/_assets/{client-auth-DJ_5wx9N.js → client-auth-CSNcTJwP.js} +81 -81
  8. package/dist/{env-CgaH9Mut.js → env-C7e2Nlnt.js} +30 -1
  9. package/dist/{export-CR9Megtb.js → export-Bbn86HmS.js} +1 -1
  10. package/dist/{github-sync-DYZq9rQp.js → github-sync-CBQPRZ8H.js} +1 -1
  11. package/dist/{github-sync-8Vv06aCr.js → github-sync-dXsiZa_e.js} +2 -2
  12. package/dist/index.js +4 -4
  13. package/dist/node.js +61 -5
  14. package/package.json +2 -1
  15. package/src/__tests__/helpers/app.ts +15 -2
  16. package/src/app.tsx +3 -0
  17. package/src/client/thread-context.ts +146 -2
  18. package/src/client/tiptap/__tests__/link-toolbar.test.ts +1 -1
  19. package/src/client/tiptap/bubble-menu.ts +1 -16
  20. package/src/client/tiptap/extensions.ts +2 -6
  21. package/src/client/tiptap/link-toolbar.ts +0 -21
  22. package/src/client/tiptap/toolbar-mode.ts +0 -43
  23. package/src/db/migrations/0022_old_gressill.sql +24 -0
  24. package/src/db/migrations/0023_broad_terror.sql +20 -0
  25. package/src/db/migrations/0024_red_the_twelve.sql +3 -0
  26. package/src/db/migrations/0025_exotic_wendell_rand.sql +1 -0
  27. package/src/db/migrations/meta/0022_snapshot.json +2267 -0
  28. package/src/db/migrations/meta/0023_snapshot.json +2396 -0
  29. package/src/db/migrations/meta/0024_snapshot.json +2417 -0
  30. package/src/db/migrations/meta/0025_snapshot.json +2424 -0
  31. package/src/db/migrations/meta/_journal.json +28 -0
  32. package/src/db/migrations/pg/0020_bizarre_smasher.sql +24 -0
  33. package/src/db/migrations/pg/0021_sharp_puppet_master.sql +20 -0
  34. package/src/db/migrations/pg/0022_blushing_blue_shield.sql +3 -0
  35. package/src/db/migrations/pg/0023_organic_zemo.sql +1 -0
  36. package/src/db/migrations/pg/meta/0020_snapshot.json +2904 -0
  37. package/src/db/migrations/pg/meta/0021_snapshot.json +3060 -0
  38. package/src/db/migrations/pg/meta/0022_snapshot.json +3078 -0
  39. package/src/db/migrations/pg/meta/0023_snapshot.json +3084 -0
  40. package/src/db/migrations/pg/meta/_journal.json +28 -0
  41. package/src/db/pg/schema.ts +82 -0
  42. package/src/db/schema.ts +90 -0
  43. package/src/i18n/coverage.generated.ts +2 -2
  44. package/src/i18n/locales/public/en.po +8 -0
  45. package/src/i18n/locales/public/zh-Hans.po +8 -0
  46. package/src/i18n/locales/public/zh-Hant.po +8 -0
  47. package/src/i18n/locales/settings/en.po +135 -0
  48. package/src/i18n/locales/settings/en.ts +1 -1
  49. package/src/i18n/locales/settings/zh-Hans.po +136 -1
  50. package/src/i18n/locales/settings/zh-Hans.ts +1 -1
  51. package/src/i18n/locales/settings/zh-Hant.po +136 -1
  52. package/src/i18n/locales/settings/zh-Hant.ts +1 -1
  53. package/src/lib/__tests__/image-dimensions.test.ts +314 -0
  54. package/src/lib/__tests__/telegram-entities.test.ts +180 -0
  55. package/src/lib/__tests__/telegram-pool-webhooks.test.ts +127 -0
  56. package/src/lib/env.ts +45 -0
  57. package/src/lib/ids.ts +3 -0
  58. package/src/lib/image-dimensions.ts +258 -0
  59. package/src/lib/telegram-entities.ts +240 -0
  60. package/src/lib/telegram-pool-webhooks.ts +86 -0
  61. package/src/lib/telegram-settings-status.tsx +109 -0
  62. package/src/lib/telegram.ts +363 -0
  63. package/src/node/runtime.ts +6 -0
  64. package/src/routes/api/__tests__/telegram.test.ts +612 -0
  65. package/src/routes/api/telegram.ts +782 -0
  66. package/src/routes/api/upload-multipart.ts +34 -12
  67. package/src/routes/api/upload.ts +23 -2
  68. package/src/routes/dash/settings.tsx +131 -1
  69. package/src/routes/pages/__tests__/post-page-title.test.ts +70 -0
  70. package/src/routes/pages/page.tsx +3 -2
  71. package/src/runtime/cloudflare.ts +20 -9
  72. package/src/runtime/node.ts +20 -9
  73. package/src/runtime/site.ts +2 -1
  74. package/src/services/__tests__/telegram.test.ts +148 -0
  75. package/src/services/index.ts +9 -0
  76. package/src/services/telegram.ts +613 -0
  77. package/src/services/upload-session.ts +39 -12
  78. package/src/styles/tokens.css +1 -0
  79. package/src/styles/ui.css +117 -38
  80. package/src/types/app-context.ts +6 -0
  81. package/src/types/bindings.ts +3 -0
  82. package/src/types/config.ts +40 -0
  83. package/src/ui/dash/settings/SettingsRootContent.tsx +48 -17
  84. package/src/ui/dash/settings/TelegramContent.tsx +549 -0
  85. package/src/ui/feed/ThreadPreview.tsx +90 -38
  86. package/src/ui/feed/__tests__/thread-preview.test.ts +66 -5
  87. package/src/ui/pages/PostPage.tsx +77 -15
  88. package/dist/app-DLINgGBd.js +0 -6
  89. package/dist/client/_assets/client-BErXNT6k.css +0 -2
  90. package/dist/client/_assets/client-CtAgWT8i.js +0 -274
@@ -141,6 +141,34 @@
141
141
  "when": 1777545080191,
142
142
  "tag": "0019_gray_natasha_romanoff",
143
143
  "breakpoints": true
144
+ },
145
+ {
146
+ "idx": 20,
147
+ "version": "7",
148
+ "when": 1778796689691,
149
+ "tag": "0020_bizarre_smasher",
150
+ "breakpoints": true
151
+ },
152
+ {
153
+ "idx": 21,
154
+ "version": "7",
155
+ "when": 1778971491254,
156
+ "tag": "0021_sharp_puppet_master",
157
+ "breakpoints": true
158
+ },
159
+ {
160
+ "idx": 22,
161
+ "version": "7",
162
+ "when": 1779056638164,
163
+ "tag": "0022_blushing_blue_shield",
164
+ "breakpoints": true
165
+ },
166
+ {
167
+ "idx": 23,
168
+ "version": "7",
169
+ "when": 1779059130438,
170
+ "tag": "0023_organic_zemo",
171
+ "breakpoints": true
144
172
  }
145
173
  ]
146
174
  }
@@ -825,6 +825,88 @@ export const githubAppInstallation = pgTable(
825
825
  ],
826
826
  );
827
827
 
828
+ // ---------------------------------------------------------------------------
829
+ // Telegram bindings (connect a Telegram account to post Notes via a bot)
830
+ // ---------------------------------------------------------------------------
831
+
832
+ export const telegramPendingBindings = pgTable(
833
+ "telegram_pending_binding",
834
+ {
835
+ id: text("id").primaryKey(),
836
+ siteId: text("site_id")
837
+ .notNull()
838
+ .references(() => sites.id, { onDelete: "cascade" }),
839
+ code: text("code").notNull(),
840
+ createdAt: integer("created_at").notNull(),
841
+ expiresAt: integer("expires_at").notNull(),
842
+ },
843
+ (table) => [
844
+ uniqueIndex("uq_telegram_pending_binding_site_id").on(table.siteId),
845
+ uniqueIndex("uq_telegram_pending_binding_code").on(table.code),
846
+ ],
847
+ );
848
+
849
+ export const telegramBindings = pgTable(
850
+ "telegram_binding",
851
+ {
852
+ id: text("id").primaryKey(),
853
+ siteId: text("site_id")
854
+ .notNull()
855
+ .references(() => sites.id, { onDelete: "cascade" }),
856
+ botId: text("bot_id").notNull(),
857
+ telegramUserId: text("telegram_user_id").notNull(),
858
+ telegramUsername: text("telegram_username"),
859
+ lastUpdateId: integer("last_update_id"),
860
+ boundAt: integer("bound_at").notNull(),
861
+ },
862
+ (table) => [
863
+ uniqueIndex("uq_telegram_binding_site_id").on(table.siteId),
864
+ uniqueIndex("uq_telegram_binding_bot_user").on(
865
+ table.botId,
866
+ table.telegramUserId,
867
+ ),
868
+ ],
869
+ );
870
+
871
+ /** Mirror of `telegram_media_group_item` in the SQLite schema. */
872
+ export const telegramMediaGroupItems = pgTable(
873
+ "telegram_media_group_item",
874
+ {
875
+ id: text("id").primaryKey(),
876
+ siteId: text("site_id")
877
+ .notNull()
878
+ .references(() => sites.id, { onDelete: "cascade" }),
879
+ botId: text("bot_id").notNull(),
880
+ telegramUserId: text("telegram_user_id").notNull(),
881
+ mediaGroupId: text("media_group_id").notNull(),
882
+ chatId: integer("chat_id").notNull(),
883
+ messageId: integer("message_id").notNull(),
884
+ updateId: integer("update_id").notNull(),
885
+ fileId: text("file_id").notNull(),
886
+ mediaKind: text("media_kind").notNull(),
887
+ mimeType: text("mime_type"),
888
+ originalName: text("original_name"),
889
+ captionMarkdown: text("caption_markdown"),
890
+ width: integer("width"),
891
+ height: integer("height"),
892
+ durationSeconds: integer("duration_seconds"),
893
+ /** Telegram `thumbnail.file_id` for videos / previewable documents. */
894
+ posterFileId: text("poster_file_id"),
895
+ createdAt: integer("created_at").notNull(),
896
+ },
897
+ (table) => [
898
+ index("idx_telegram_media_group_item_group").on(
899
+ table.botId,
900
+ table.mediaGroupId,
901
+ ),
902
+ uniqueIndex("uq_telegram_media_group_item_message").on(
903
+ table.botId,
904
+ table.mediaGroupId,
905
+ table.messageId,
906
+ ),
907
+ ],
908
+ );
909
+
828
910
  // ---------------------------------------------------------------------------
829
911
  // Rate Limit
830
912
  // ---------------------------------------------------------------------------
package/src/db/schema.ts CHANGED
@@ -775,6 +775,96 @@ export const githubAppInstallation = sqliteTable(
775
775
  ],
776
776
  );
777
777
 
778
+ // ---------------------------------------------------------------------------
779
+ // Telegram bindings (connect a Telegram account to post Notes via a bot)
780
+ // ---------------------------------------------------------------------------
781
+
782
+ export const telegramPendingBindings = sqliteTable(
783
+ "telegram_pending_binding",
784
+ {
785
+ id: text("id").primaryKey(),
786
+ siteId: text("site_id")
787
+ .notNull()
788
+ .references(() => sites.id, { onDelete: "cascade" }),
789
+ code: text("code").notNull(),
790
+ createdAt: integer("created_at").notNull(),
791
+ expiresAt: integer("expires_at").notNull(),
792
+ },
793
+ (table) => [
794
+ uniqueIndex("uq_telegram_pending_binding_site_id").on(table.siteId),
795
+ uniqueIndex("uq_telegram_pending_binding_code").on(table.code),
796
+ ],
797
+ );
798
+
799
+ export const telegramBindings = sqliteTable(
800
+ "telegram_binding",
801
+ {
802
+ id: text("id").primaryKey(),
803
+ siteId: text("site_id")
804
+ .notNull()
805
+ .references(() => sites.id, { onDelete: "cascade" }),
806
+ botId: text("bot_id").notNull(),
807
+ telegramUserId: text("telegram_user_id").notNull(),
808
+ telegramUsername: text("telegram_username"),
809
+ lastUpdateId: integer("last_update_id"),
810
+ boundAt: integer("bound_at").notNull(),
811
+ },
812
+ (table) => [
813
+ uniqueIndex("uq_telegram_binding_site_id").on(table.siteId),
814
+ uniqueIndex("uq_telegram_binding_bot_user").on(
815
+ table.botId,
816
+ table.telegramUserId,
817
+ ),
818
+ ],
819
+ );
820
+
821
+ /**
822
+ * Short-lived buffer for Telegram album (media_group_id) messages.
823
+ *
824
+ * Telegram splits an album into one webhook update per item, sharing a
825
+ * `media_group_id`. The webhook handler inserts one row per item, sleeps a
826
+ * short window for the rest of the group to arrive, then atomically claims
827
+ * the whole group with `DELETE ... RETURNING` to publish a single post with
828
+ * all attachments. Rows are deleted on flush, so the table stays small.
829
+ */
830
+ export const telegramMediaGroupItems = sqliteTable(
831
+ "telegram_media_group_item",
832
+ {
833
+ id: text("id").primaryKey(),
834
+ siteId: text("site_id")
835
+ .notNull()
836
+ .references(() => sites.id, { onDelete: "cascade" }),
837
+ botId: text("bot_id").notNull(),
838
+ telegramUserId: text("telegram_user_id").notNull(),
839
+ mediaGroupId: text("media_group_id").notNull(),
840
+ chatId: integer("chat_id").notNull(),
841
+ messageId: integer("message_id").notNull(),
842
+ updateId: integer("update_id").notNull(),
843
+ fileId: text("file_id").notNull(),
844
+ mediaKind: text("media_kind").notNull(),
845
+ mimeType: text("mime_type"),
846
+ originalName: text("original_name"),
847
+ captionMarkdown: text("caption_markdown"),
848
+ width: integer("width"),
849
+ height: integer("height"),
850
+ durationSeconds: integer("duration_seconds"),
851
+ /** Telegram `thumbnail.file_id` for videos / previewable documents. */
852
+ posterFileId: text("poster_file_id"),
853
+ createdAt: integer("created_at").notNull(),
854
+ },
855
+ (table) => [
856
+ index("idx_telegram_media_group_item_group").on(
857
+ table.botId,
858
+ table.mediaGroupId,
859
+ ),
860
+ uniqueIndex("uq_telegram_media_group_item_message").on(
861
+ table.botId,
862
+ table.mediaGroupId,
863
+ table.messageId,
864
+ ),
865
+ ],
866
+ );
867
+
778
868
  // =============================================================================
779
869
  // Rate Limit
780
870
  // =============================================================================
@@ -12,6 +12,6 @@ import type { Locale } from "./locales.js";
12
12
 
13
13
  export const SETTINGS_TRANSLATION_COVERAGE: Record<Locale, number> = {
14
14
  en: 1,
15
- "zh-Hans": 1,
16
- "zh-Hant": 1,
15
+ "zh-Hans": 0.9254658385093167,
16
+ "zh-Hant": 0.9254658385093167,
17
17
  } as const;
@@ -1773,13 +1773,21 @@ msgstr "Settings"
1773
1773
  msgid "Shared links"
1774
1774
  msgstr "Shared links"
1775
1775
 
1776
+ #. @context: Collapse expanded thread ancestor context in the feed
1777
+ #. @context: Collapse expanded thread ancestor context in the feed
1776
1778
  #. @context: Collapse reply context
1777
1779
  #: src/ui/compose/ComposeDialog.tsx
1780
+ #: src/ui/feed/ThreadPreview.tsx
1781
+ #: src/ui/pages/PostPage.tsx
1778
1782
  msgid "Show less"
1779
1783
  msgstr "Show less"
1780
1784
 
1785
+ #. @context: Expand faded thread ancestor context in the feed
1786
+ #. @context: Expand faded thread ancestor context in the feed
1781
1787
  #. @context: Expand reply context
1782
1788
  #: src/ui/compose/ComposeDialog.tsx
1789
+ #: src/ui/feed/ThreadPreview.tsx
1790
+ #: src/ui/pages/PostPage.tsx
1783
1791
  msgid "Show more"
1784
1792
  msgstr "Show more"
1785
1793
 
@@ -1770,13 +1770,21 @@ msgstr ""
1770
1770
  msgid "Shared links"
1771
1771
  msgstr ""
1772
1772
 
1773
+ #. @context: Collapse expanded thread ancestor context in the feed
1774
+ #. @context: Collapse expanded thread ancestor context in the feed
1773
1775
  #. @context: Collapse reply context
1774
1776
  #: src/ui/compose/ComposeDialog.tsx
1777
+ #: src/ui/feed/ThreadPreview.tsx
1778
+ #: src/ui/pages/PostPage.tsx
1775
1779
  msgid "Show less"
1776
1780
  msgstr ""
1777
1781
 
1782
+ #. @context: Expand faded thread ancestor context in the feed
1783
+ #. @context: Expand faded thread ancestor context in the feed
1778
1784
  #. @context: Expand reply context
1779
1785
  #: src/ui/compose/ComposeDialog.tsx
1786
+ #: src/ui/feed/ThreadPreview.tsx
1787
+ #: src/ui/pages/PostPage.tsx
1780
1788
  msgid "Show more"
1781
1789
  msgstr ""
1782
1790
 
@@ -1770,13 +1770,21 @@ msgstr ""
1770
1770
  msgid "Shared links"
1771
1771
  msgstr ""
1772
1772
 
1773
+ #. @context: Collapse expanded thread ancestor context in the feed
1774
+ #. @context: Collapse expanded thread ancestor context in the feed
1773
1775
  #. @context: Collapse reply context
1774
1776
  #: src/ui/compose/ComposeDialog.tsx
1777
+ #: src/ui/feed/ThreadPreview.tsx
1778
+ #: src/ui/pages/PostPage.tsx
1775
1779
  msgid "Show less"
1776
1780
  msgstr ""
1777
1781
 
1782
+ #. @context: Expand faded thread ancestor context in the feed
1783
+ #. @context: Expand faded thread ancestor context in the feed
1778
1784
  #. @context: Expand reply context
1779
1785
  #: src/ui/compose/ComposeDialog.tsx
1786
+ #: src/ui/feed/ThreadPreview.tsx
1787
+ #: src/ui/pages/PostPage.tsx
1780
1788
  msgid "Show more"
1781
1789
  msgstr ""
1782
1790
 
@@ -221,6 +221,11 @@ msgstr "Before deleting, download a site export. You won't be able to recover th
221
221
  msgid "Blog Avatar"
222
222
  msgstr "Blog Avatar"
223
223
 
224
+ #. @context: Label for the Telegram bot token input
225
+ #: src/ui/dash/settings/TelegramContent.tsx
226
+ msgid "Bot token"
227
+ msgstr "Bot token"
228
+
224
229
  #. @context: Section heading for built-in nav items
225
230
  #: src/ui/dash/appearance/NavigationContent.tsx
226
231
  msgid "Built-in links"
@@ -234,6 +239,8 @@ msgstr "Built-in links"
234
239
  #. @context: Button label to dismiss a dialog or action
235
240
  #. @context: Button label to dismiss a dialog or action
236
241
  #. @context: Button label to dismiss a dialog or action
242
+ #. @context: Button label to dismiss a dialog or action
243
+ #. @context: Button label to dismiss a dialog or action
237
244
  #. @context: Button to cancel form
238
245
  #. @context: Button to cancel settings changes
239
246
  #. @context: Button to cancel unsaved changes and revert to original values
@@ -250,6 +257,8 @@ msgstr "Built-in links"
250
257
  #: src/ui/dash/settings/GeneralContent.tsx
251
258
  #: src/ui/dash/settings/GitHubSyncContent.tsx
252
259
  #: src/ui/dash/settings/SessionsContent.tsx
260
+ #: src/ui/dash/settings/TelegramContent.tsx
261
+ #: src/ui/dash/settings/TelegramContent.tsx
253
262
  msgid "Cancel"
254
263
  msgstr "Cancel"
255
264
 
@@ -343,11 +352,31 @@ msgstr "Connect"
343
352
  msgid "Connect a GitHub repository to automatically back up your posts as Markdown files. Edits on GitHub sync back to your site."
344
353
  msgstr "Connect a GitHub repository to automatically back up your posts as Markdown files. Edits on GitHub sync back to your site."
345
354
 
355
+ #. @context: Intro text on the Telegram settings page when no bot is set up
356
+ #: src/ui/dash/settings/TelegramContent.tsx
357
+ msgid "Connect a Telegram bot, then anything you message it gets published as a note."
358
+ msgstr "Connect a Telegram bot, then anything you message it gets published as a note."
359
+
360
+ #. @context: Toggle that reveals manual Telegram binding instructions when the deep link can't be used
361
+ #: src/ui/dash/settings/TelegramContent.tsx
362
+ msgid "Connect manually"
363
+ msgstr "Connect manually"
364
+
365
+ #. @context: Heading on the Telegram settings page when ready to connect
366
+ #: src/ui/dash/settings/TelegramContent.tsx
367
+ msgid "Connect Telegram"
368
+ msgstr "Connect Telegram"
369
+
346
370
  #. @context: Heading for the GitHub App connect option on GitHub Sync setup
347
371
  #: src/ui/dash/settings/GitHubSyncContent.tsx
348
372
  msgid "Connect with GitHub App"
349
373
  msgstr "Connect with GitHub App"
350
374
 
375
+ #. @context: Status label when Telegram is connected, with the account name
376
+ #: src/ui/dash/settings/TelegramContent.tsx
377
+ msgid "Connected as {account}"
378
+ msgstr "Connected as {account}"
379
+
351
380
  #. @context: Status label when GitHub Sync is active using the GitHub App
352
381
  #: src/ui/dash/settings/GitHubSyncContent.tsx
353
382
  msgid "Connected via GitHub App"
@@ -369,12 +398,20 @@ msgid "Connecting…"
369
398
  msgstr "Connecting…"
370
399
 
371
400
  #. @context: Feedback after copying API token
401
+ #. @context: Feedback after copying to clipboard
372
402
  #: src/ui/dash/settings/ApiTokensContent.tsx
403
+ #: src/ui/dash/settings/TelegramContent.tsx
373
404
  msgid "Copied"
374
405
  msgstr "Copied"
375
406
 
376
407
  #. @context: Button to copy a URL to the clipboard
408
+ #. @context: Button to copy the Telegram binding code
409
+ #. @context: Button to copy the Telegram binding code
410
+ #. @context: Button to copy the Telegram binding code
377
411
  #: src/ui/dash/settings/GeneralContent.tsx
412
+ #: src/ui/dash/settings/TelegramContent.tsx
413
+ #: src/ui/dash/settings/TelegramContent.tsx
414
+ #: src/ui/dash/settings/TelegramContent.tsx
378
415
  msgid "Copy"
379
416
  msgstr "Copy"
380
417
 
@@ -410,6 +447,11 @@ msgstr "Couldn't delete. Try again in a moment."
410
447
  msgid "Couldn't save. Try again in a moment."
411
448
  msgstr "Couldn't save. Try again in a moment."
412
449
 
450
+ #. @context: Help text explaining where to get a Telegram bot token
451
+ #: src/ui/dash/settings/TelegramContent.tsx
452
+ msgid "Create a bot by messaging @BotFather on Telegram, then paste the token it gives you."
453
+ msgstr "Create a bot by messaging @BotFather on Telegram, then paste the token it gives you."
454
+
413
455
  #. @context: Link text pointing to GitHub's new repository page
414
456
  #: src/ui/dash/settings/GitHubSyncContent.tsx
415
457
  msgid "Create a new repository"
@@ -571,9 +613,11 @@ msgid "Destination"
571
613
  msgstr "Destination"
572
614
 
573
615
  #. @context: Button to disconnect GitHub repository on GitHub Sync settings
616
+ #. @context: Button to disconnect Telegram
574
617
  #. @context: Section heading for disconnect action on GitHub Sync settings
575
618
  #: src/ui/dash/settings/GitHubSyncContent.tsx
576
619
  #: src/ui/dash/settings/GitHubSyncContent.tsx
620
+ #: src/ui/dash/settings/TelegramContent.tsx
577
621
  msgid "Disconnect"
578
622
  msgstr "Disconnect"
579
623
 
@@ -582,6 +626,11 @@ msgstr "Disconnect"
582
626
  msgid "Disconnect from GitHub? The webhook will be removed. Your repository content will not be deleted."
583
627
  msgstr "Disconnect from GitHub? The webhook will be removed. Your repository content will not be deleted."
584
628
 
629
+ #. @context: Confirmation message when disconnecting Telegram
630
+ #: src/ui/dash/settings/TelegramContent.tsx
631
+ msgid "Disconnect Telegram? You can reconnect any time with a new binding code."
632
+ msgstr "Disconnect Telegram? You can reconnect any time with a new binding code."
633
+
585
634
  #. @context: Checkbox to show avatar in the site header
586
635
  #: src/ui/dash/settings/AvatarContent.tsx
587
636
  msgid "Display avatar in my site header"
@@ -732,6 +781,11 @@ msgstr "General"
732
781
  msgid "Generate Token"
733
782
  msgstr "Generate Token"
734
783
 
784
+ #. @context: Button to regenerate the Telegram binding code
785
+ #: src/ui/dash/settings/TelegramContent.tsx
786
+ msgid "Get a new code"
787
+ msgstr "Get a new code"
788
+
735
789
  #. @context: Breadcrumb label
736
790
  #. @context: Settings item — GitHub sync settings
737
791
  #. @context: Settings section heading for GitHub Sync setup
@@ -801,6 +855,11 @@ msgstr "Install GitHub App"
801
855
  msgid "Install the GitHub App to grant access without managing personal tokens. Permissions are scoped per repository and revocable from GitHub."
802
856
  msgstr "Install the GitHub App to grant access without managing personal tokens. Permissions are scoped per repository and revocable from GitHub."
803
857
 
858
+ #. @context: Settings group label for third-party integrations
859
+ #: src/ui/dash/settings/SettingsRootContent.tsx
860
+ msgid "Integrations"
861
+ msgstr "Integrations"
862
+
804
863
  #. @context: Nav item label field
805
864
  #: src/ui/dash/appearance/NavigationContent.tsx
806
865
  msgid "Label"
@@ -943,6 +1002,11 @@ msgstr "March 14"
943
1002
  msgid "Markdown supported"
944
1003
  msgstr "Markdown supported"
945
1004
 
1005
+ #. @context: Hint shown when Telegram is connected
1006
+ #: src/ui/dash/settings/TelegramContent.tsx
1007
+ msgid "Message the bot any text and it's published as a note."
1008
+ msgstr "Message the bot any text and it's published as a note."
1009
+
946
1010
  #. @context: Section label for nav items hidden under More dropdown
947
1011
  #: src/ui/dash/appearance/NavigationContent.tsx
948
1012
  msgid "More"
@@ -1056,11 +1120,31 @@ msgstr "Not synced yet"
1056
1120
  msgid "Note"
1057
1121
  msgstr "Note"
1058
1122
 
1123
+ #. @context: Caption inside the manual Telegram binding fallback. {linkOpen}/{linkClose} wrap the bot username as a t.me link — keep them around the @username token in translations.
1124
+ #: src/ui/dash/settings/TelegramContent.tsx
1125
+ msgid "Open {linkOpen}@{botUsername}{linkClose} and send:"
1126
+ msgstr "Open {linkOpen}@{botUsername}{linkClose} and send:"
1127
+
1128
+ #. @context: Button that opens the Telegram bot via a deep link
1129
+ #: src/ui/dash/settings/TelegramContent.tsx
1130
+ msgid "Open Telegram to connect"
1131
+ msgstr "Open Telegram to connect"
1132
+
1133
+ #. @context: Instructions on the Telegram settings page for connecting an account
1134
+ #: src/ui/dash/settings/TelegramContent.tsx
1135
+ msgid "Open the bot and send the binding code, then anything you message it becomes a note."
1136
+ msgstr "Open the bot and send the binding code, then anything you message it becomes a note."
1137
+
1059
1138
  #. @context: Settings item description for the hosted delete-site entry in the account menu
1060
1139
  #: src/ui/dash/settings/AccountMenuContent.tsx
1061
1140
  msgid "Open the hosted site controls in {providerLabel} to cancel billing or permanently delete this site."
1062
1141
  msgstr "Open the hosted site controls in {providerLabel} to cancel billing or permanently delete this site."
1063
1142
 
1143
+ #. @context: Separator between the QR code and the deep-link button on the Telegram connect page
1144
+ #: src/ui/dash/settings/TelegramContent.tsx
1145
+ msgid "or"
1146
+ msgstr "or"
1147
+
1064
1148
  #. @context: GitHub sync picker — placeholder text showing the expected input shape
1065
1149
  #: src/routes/dash/settings.tsx
1066
1150
  msgid "owner/repo"
@@ -1135,6 +1219,11 @@ msgstr "Pinned"
1135
1219
  msgid "Post"
1136
1220
  msgstr "Post"
1137
1221
 
1222
+ #. @context: Settings item description for Telegram integration
1223
+ #: src/ui/dash/settings/SettingsRootContent.tsx
1224
+ msgid "Post notes by messaging a Telegram bot"
1225
+ msgstr "Post notes by messaging a Telegram bot"
1226
+
1138
1227
  #. @context: GitHub sync picker — badge next to private repos
1139
1228
  #: src/routes/dash/settings.tsx
1140
1229
  msgid "Private"
@@ -1155,6 +1244,11 @@ msgstr "Published"
1155
1244
  msgid "Push all posts to GitHub right now instead of waiting for the next automatic sync."
1156
1245
  msgstr "Push all posts to GitHub right now instead of waiting for the next automatic sync."
1157
1246
 
1247
+ #. @context: Accessible label for the Telegram connect QR code
1248
+ #: src/ui/dash/settings/TelegramContent.tsx
1249
+ msgid "QR code linking to the Telegram bot"
1250
+ msgstr "QR code linking to the Telegram bot"
1251
+
1158
1252
  #. @context: Archive custom URL query params field
1159
1253
  #: src/routes/dash/custom-urls.tsx
1160
1254
  msgid "Query Parameters"
@@ -1204,6 +1298,16 @@ msgstr "Refresh repository list"
1204
1298
  msgid "Remove"
1205
1299
  msgstr "Remove"
1206
1300
 
1301
+ #. @context: Button to remove the saved Telegram bot token
1302
+ #: src/ui/dash/settings/TelegramContent.tsx
1303
+ msgid "Remove bot"
1304
+ msgstr "Remove bot"
1305
+
1306
+ #. @context: Confirmation message when removing the Telegram bot token
1307
+ #: src/ui/dash/settings/TelegramContent.tsx
1308
+ msgid "Remove the saved bot token? Its webhook is deleted and any connected account is disconnected."
1309
+ msgstr "Remove the saved bot token? Its webhook is deleted and any connected account is disconnected."
1310
+
1207
1311
  #. @context: Description for disconnect action on GitHub Sync settings
1208
1312
  #: src/ui/dash/settings/GitHubSyncContent.tsx
1209
1313
  msgid "Remove the webhook and stop syncing. Your repository content will not be deleted."
@@ -1261,6 +1365,11 @@ msgstr "Safe to leave this page — syncing continues in the background."
1261
1365
  msgid "Save"
1262
1366
  msgstr "Save"
1263
1367
 
1368
+ #. @context: Button to save the Telegram bot token
1369
+ #: src/ui/dash/settings/TelegramContent.tsx
1370
+ msgid "Save bot token"
1371
+ msgstr "Save bot token"
1372
+
1264
1373
  #. @context: Button to save custom CSS
1265
1374
  #: src/ui/dash/appearance/AdvancedContent.tsx
1266
1375
  msgid "Save CSS"
@@ -1406,6 +1515,11 @@ msgstr "Site-wide HTML for analytics and widgets"
1406
1515
  msgid "Soft color should still carry a clear reading rhythm."
1407
1516
  msgstr "Soft color should still carry a clear reading rhythm."
1408
1517
 
1518
+ #. @context: Description for the Telegram disconnect action
1519
+ #: src/ui/dash/settings/TelegramContent.tsx
1520
+ msgid "Stop accepting posts from Telegram. Your existing notes stay published."
1521
+ msgstr "Stop accepting posts from Telegram. Your existing notes stay published."
1522
+
1409
1523
  #. @context: Button to trigger a full content push to GitHub on GitHub Sync settings
1410
1524
  #: src/ui/dash/settings/GitHubSyncContent.tsx
1411
1525
  msgid "Sync Now"
@@ -1426,6 +1540,22 @@ msgstr "system"
1426
1540
  msgid "Target Slug"
1427
1541
  msgstr "Target Slug"
1428
1542
 
1543
+ #. @context: Breadcrumb label
1544
+ #. @context: Settings item — Telegram integration settings
1545
+ #. @context: Settings section heading for Telegram setup
1546
+ #. @context: Settings section heading for Telegram setup
1547
+ #: src/routes/dash/settings.tsx
1548
+ #: src/ui/dash/settings/SettingsRootContent.tsx
1549
+ #: src/ui/dash/settings/TelegramContent.tsx
1550
+ #: src/ui/dash/settings/TelegramContent.tsx
1551
+ msgid "Telegram"
1552
+ msgstr "Telegram"
1553
+
1554
+ #. @context: Error shown on the Telegram settings page when the bot can't be reached
1555
+ #: src/ui/dash/settings/TelegramContent.tsx
1556
+ msgid "Telegram is set up, but the bot couldn't be reached. Check the bot token and try again."
1557
+ msgstr "Telegram is set up, but the bot couldn't be reached. Check the bot token and try again."
1558
+
1429
1559
  #. @context: Error toast when selected font theme is not valid
1430
1560
  #: src/routes/dash/settings.tsx
1431
1561
  msgid "That font theme isn't available. Pick another one."
@@ -1635,3 +1765,8 @@ msgstr "We'll prefill the name {name}. The list refreshes on return."
1635
1765
  #: src/ui/dash/settings/AccountMenuContent.tsx
1636
1766
  msgid "When to use site export, database backups, and recovery drills."
1637
1767
  msgstr "When to use site export, database backups, and recovery drills."
1768
+
1769
+ #. @context: Fallback name when a connected Telegram account has no username
1770
+ #: src/ui/dash/settings/TelegramContent.tsx
1771
+ msgid "your Telegram account"
1772
+ msgstr "your Telegram account"