├── README.md ├── assets └── javascripts │ └── discourse │ └── templates │ └── connectors │ └── user-custom-preferences │ └── telegram-chat-id-preferences.hbs ├── config ├── locales │ ├── client.de.yml │ ├── client.en.yml │ ├── client.es.yml │ ├── client.it.yml │ ├── client.nb_NO.yml │ ├── client.pl_PL.yml │ ├── client.ru.yml │ ├── client.zh_CN.yml │ ├── client.zh_HK.yml │ ├── server.de.yml │ ├── server.en.yml │ ├── server.es.yml │ ├── server.it.yml │ ├── server.nb_NO.yml │ ├── server.pl_PL.yml │ ├── server.ru.yml │ ├── server.zh_CN.yml │ └── server.zh_HK.yml └── settings.yml ├── plugin.rb └── services └── discourse_telegram_notifications └── telegram-notifier.rb /README.md: -------------------------------------------------------------------------------- 1 | # discourse-telegram-notifications 2 | A plugin for Discourse which allows users to receive their notifications by telegram message 3 | 4 | # Getting setup 5 | 1. Install the plugin using the instructions here: [How to install a plugin](https://meta.discourse.org/t/install-a-plugin/19157) 6 | 2. Create a telegram by talking to the [BotFather](https://telegram.me/botfather) (instructions [here](https://core.telegram.org/bots#6-botfather) 7 | 3. Paste the "token" into the site setting "telegram access token" 8 | 4. Tick "telegram notifications enabled" 9 | 10 | I strongly recommend you use the `/setjoingroups` command to disable the bot being used for group chats. It is not designed for it, and risks leaking information that users are not supposed to be able to access (e.g. you don't want private messages being sent to a group chat). 11 | 12 | You can set the name/picture/description of your bot using the instructions [here](https://core.telegram.org/bots#botfather-commands) 13 | 14 | # For users to receive notifications 15 | 1. Send a message to the bot, you'll recieve a message back that looks like 16 | ``` 17 | To get notifications for Discourse, enter the 'Chat ID' 1234567 in your user preferences 18 | ``` 19 | 2. Visit your user preferences, and paste the number in the `Telegram Notifications` box 20 | 3. You should now receive notifications by telegram message! 21 | -------------------------------------------------------------------------------- /assets/javascripts/discourse/templates/connectors/user-custom-preferences/telegram-chat-id-preferences.hbs: -------------------------------------------------------------------------------- 1 |
%{post_excerpt}27 | group_mentioned: |- 28 | 💬 @%{username} hat dich 29 | in %{topic} erwähnt 30 |
%{post_excerpt}31 | quoted: |- 32 | 💬 @%{username} hat dich 33 | in %{topic} zitiert 34 |
%{post_excerpt}35 | replied: |- 36 | ↩️ @%{username} hat dir in %{topic} 37 | geantwortet 38 |
%{post_excerpt}39 | posted: |- 40 | 💬 @%{username} hat in %{topic} 41 | geantwortet 42 |
%{post_excerpt}43 | private_message: |- 44 | ✉️ @%{username} hat dir eine Private Nachricht 45 | gesendet %{topic} 46 |
%{post_excerpt}47 | linked: |- 48 | 🔗 @%{username} hat dich in 49 | %{topic} verlinkt 50 |
%{post_excerpt}51 | watching_first_post: |- 52 | 💬 @%{username} hat in %{topic} 53 | geantwortet 54 |
%{post_excerpt}55 | # Discourse Follow Plugin 56 | following_replied: |- 57 | ↩️👥 @%{username} hat in %{topic} 58 | geantwortet 59 |
%{post_excerpt}60 | following_posted: |- 61 | 💬👥 @%{username} hat in %{topic} 62 | geantwortet 63 |
%{post_excerpt}64 | -------------------------------------------------------------------------------- /config/locales/server.en.yml: -------------------------------------------------------------------------------- 1 | en: 2 | site_settings: 3 | telegram_notifications_enabled: Enable telegram notifications? 4 | telegram_access_token: Obtain your bot's access token from the telegram botfather 5 | telegram_enabled_notification_types: Limit notifications sent to Telegram by this selection of types 6 | discourse_telegram_notifications: 7 | initial-contact: "To get notifications for %{site_title}, enter the 'Chat ID' %{chat_id} in your user preferences" 8 | known-user: |- 9 | Hi %{username}, I'll message you when you have new notifications on %{site_title}. 10 | Replying to a notification will post a reply on %{site_title}. 11 | To disable, visit your user preferences. 12 | view_online: "View online" 13 | like: "❤️ Like" 14 | unlike: "❤️ Unlike" 15 | already-liked: "You already liked that post" 16 | like-failed: "Liking that post failed" 17 | like-success: "Like successful" 18 | unlike-failed: "Unliking that post failed" 19 | unlike-success: "Unlike successful" 20 | reply-error: "❌ An error occured while processing your reply" 21 | reply-failed: "❌ Reply failed: \n\n %{errors}" 22 | reply-success: "✅ Reply successful - view it here" 23 | message: 24 | mentioned: |- 25 | 💬 @%{username} mentioned you 26 | in %{topic} 27 | 28 |
%{post_excerpt}29 | group_mentioned: |- 30 | 💬 @%{username} mentioned you 31 | in %{topic} 32 | 33 |
%{post_excerpt}34 | quoted: |- 35 | 💬 @%{username} quoted you 36 | in %{topic} 37 | 38 |
%{post_excerpt}39 | replied: |- 40 | ↩️ @%{username} replied to you 41 | in %{topic} 42 | 43 |
%{post_excerpt}44 | posted: |- 45 | 💬 @%{username} posted 46 | in %{topic} 47 | 48 |
%{post_excerpt}49 | private_message: |- 50 | ✉️ @%{username} sent you a private message 51 | in %{topic} 52 | 53 |
%{post_excerpt}54 | linked: |- 55 | 🔗 @%{username} linked to your post 56 | from %{topic} 57 | 58 |
%{post_excerpt}59 | watching_first_post: |- 60 | 💬 @%{username} posted 61 | in %{topic} 62 | 63 |
%{post_excerpt}64 | # Discourse Follow Plugin 65 | following_replied: |- 66 | ↩️👥 @%{username} replied 67 | in %{topic} 68 | 69 |
%{post_excerpt}70 | following_posted: |- 71 | 💬👥 @%{username} posted 72 | in %{topic} 73 | 74 |
%{post_excerpt}75 | -------------------------------------------------------------------------------- /config/locales/server.es.yml: -------------------------------------------------------------------------------- 1 | es: 2 | site_settings: 3 | telegram_notifications_enabled: ¿Activar notificaciones de Telegram? 4 | telegram_access_token: Obtén el token de acceso del botfather de Telegram 5 | discourse_telegram_notifications: 6 | initial-contact: "Para recibir notificaciones de %{site_title}, introduce el siguiente código: %{chat_id} en tus preferencias de la comunidad" 7 | known-user: |- 8 | ¡Hola %{username}! Soy el bot de %{site_title}, te enviaré mensajes cuando tengas nuevas notificaciones. 9 | Puedes responder directamente desde esta ventana. Simplemente al contestar a una notificación aquí, se publicará automáticamente en %{site_title}. 10 | Puedes desativar notificaciones desde las preferencias de tu usuario en %{site_title}. 11 | view_online: "Ver en la web" 12 | like: "❤️ Me gusta" 13 | unlike: "❤️ No me gusta" 14 | already-liked: "Ya habías marcado que te gusta" 15 | like-failed: "Fallo al hacer me gusta" 16 | like-success: "¡Bien!" 17 | unlike-failed: "Fallo al quitar el me gusta" 18 | unlike-success: "Quitaste el me gusta de forma correcta" 19 | reply-error: "❌ Ocurrió un error al enviar tu respuesta" 20 | reply-failed: "❌ Fallo al responder: \n\n %{errors}" 21 | reply-success: "✅ Respuesta enviada correctamente, puedes verla aquí" 22 | message: 23 | mentioned: |- 24 | 💬 @%{username} te ha mencionado 25 | en %{topic} 26 | 27 |
%{post_excerpt}28 | group_mentioned: |- 29 | 💬 @%{username} te ha mencionado 30 | en %{topic} 31 | 32 |
%{post_excerpt}33 | quoted: |- 34 | 💬 @%{username} te ha citado 35 | en %{topic} 36 | 37 |
%{post_excerpt}38 | replied: |- 39 | ↩️ @%{username} te ha contestado 40 | en %{topic} 41 | 42 |
%{post_excerpt}43 | posted: |- 44 | 💬 @%{username} ha publicado 45 | en %{topic} 46 | 47 |
%{post_excerpt}48 | private_message: |- 49 | ✉️ @%{username} te ha enviado un mensaje privado 50 | en %{topic} 51 | 52 |
%{post_excerpt}53 | linked: |- 54 | 🔗 @%{username} ha enlazado tu hilo 55 | desde %{topic} 56 | 57 |
%{post_excerpt}58 | 59 | watching_first_post: |- 60 | 💬 @%{username} ha publicado 61 | en %{topic} 62 | 63 |
%{post_excerpt}64 | # Discourse Follow Plugin 65 | following_replied: |- 66 | ↩️👥 @%{username} ha respondido 67 | en %{topic} 68 | 69 |
%{post_excerpt}70 | following_posted: |- 71 | 💬👥 @%{username} publicó 72 | en %{topic} 73 | 74 |
%{post_excerpt}75 | -------------------------------------------------------------------------------- /config/locales/server.it.yml: -------------------------------------------------------------------------------- 1 | it: 2 | site_settings: 3 | telegram_notifications_enabled: Abilitare le notifiche da telegram? 4 | telegram_access_token: Ottieni il token per l'accesso del tuo bot da botfather di telegram 5 | discourse_telegram_notifications: 6 | initial-contact: "Per ricevere notifiche da %{site_title}, inserisci lo 'Chat ID' %{chat_id} nelle tue preferenze utente" 7 | known-user: |- 8 | Ciao %{username}, ti invierò un messaggio quando riceverai nuove notifiche da %{site_title}. 9 | Rispondere a una notifica pubblicherà una risposta anche su %{site_title}. 10 | Per disabilitare le notifiche, visita le tue preferenze utente. 11 | view_online: " Visualizza in linea" 12 | like: "❤️ Mi piace" 13 | unlike: "❤️ Rimuovi mi piace" 14 | already-liked: "Hai già messo mi piace a questo messaggio" 15 | like-failed: "Fallimento nel mettere mi piace" 16 | like-success: "Messo mi piace con successo" 17 | unlike-failed: "Fallimento nel rimuovere mi piace" 18 | unlike-success: "Rimosso mi piace con successo" 19 | reply-error: "❌ Si è verificato un errore durante l'elaborazione della risposta" 20 | reply-failed: "❌ Risposta fallita: \n\n %{errors}" 21 | reply-success: "✅ Risposta inviata con successo - visualizzala qui" 22 | message: 23 | mentioned: |- 24 | 💬 @%{username} ti ha menzionato 25 | in %{topic} 26 | 27 |
%{post_excerpt}28 | group_mentioned: |- 29 | 💬 @%{username} ti ha menzionato 30 | in %{topic} 31 | 32 |
%{post_excerpt}33 | quoted: |- 34 | 💬 @%{username} ti ha citato 35 | in %{topic} 36 | 37 |
%{post_excerpt}38 | replied: |- 39 | ↩️ @%{username} ti ha risposto 40 | in %{topic} 41 | 42 |
%{post_excerpt}43 | posted: |- 44 | 💬 @%{username} ha postato 45 | in %{topic} 46 | 47 |
%{post_excerpt}48 | private_message: |- 49 | ✉️ @%{username} ti ha inviato un messaggio privato 50 | in %{topic} 51 | 52 |
%{post_excerpt}53 | linked: |- 54 | 🔗 @%{username} ha creato un collegamento al tuo messaggio 55 | da %{topic} 56 | 57 |
%{post_excerpt}58 | watching_first_post: |- 59 | 💬 @%{username} ha postato 60 | in %{topic} 61 | 62 |
%{post_excerpt}63 | # Discourse Follow Plugin 64 | following_replied: |- 65 | ↩️👥 @%{username} ha risposto 66 | in %{topic} 67 | 68 |
%{post_excerpt}69 | following_posted: |- 70 | 💬👥 @%{username} ha postato 71 | in %{topic} 72 | 73 |
%{post_excerpt}74 | -------------------------------------------------------------------------------- /config/locales/server.nb_NO.yml: -------------------------------------------------------------------------------- 1 | nb_NO: 2 | site_settings: 3 | telegram_notifications_enabled: Aktivere Telegram-varsler? 4 | telegram_access_token: Skaff botens *access token* fra Telegram BotFather 5 | telegram_enabled_notification_types: Begrens varsel-typene som sendes til Telegram her 6 | discourse_telegram_notifications: 7 | initial-contact: "For å aktivere varsler fra %{site_title}, legg inn 'Chat ID' %{chat_id} i bruker-innstillingene dine på %{site_title}. Du må mest sannsynlig skrolle ned litt." 8 | known-user: |- 9 | Hei %{username}! Jeg kommer til å sende deg meldinger når du har nye varsler på %{site_title}. 10 | Dersom du svarer på meldinga, vil det postes et svar på %{site_title}. 11 | For å deaktivere, går du til bruker-innstillingene dine på %{site_title}, og tømmer boksen hvor du la inn 'Chat ID'. 12 | view_online: "Til forumet" 13 | like: "❤️ Liker" 14 | unlike: "💔 Ta bort at du liker" 15 | already-liked: "Du har allerede likt den posten." 16 | like-failed: "❌ Det funka visst ikke å like posten." 17 | like-success: "✅ Du har likt posten." 18 | unlike-failed: "❌ Det funka visst ikke å ta bort at du liker den posten." 19 | unlike-success: "✅ Du har tatt bort at du liker posten." 20 | reply-error: "❌ Det skjedde en feil med sendinga av svaret ditt." 21 | reply-failed: "❌ Svar feilet: \n\n %{errors}" 22 | reply-success: "✅ Svar lyktes! Se på det her." 23 | message: 24 | mentioned: |- 25 | 💬 @%{username} nevnte deg 26 | i %{topic}. 27 | 28 |
%{post_excerpt}29 | group_mentioned: |- 30 | 💬 @%{username} nevnte deg 31 | i %{topic}. 32 | 33 |
%{post_excerpt}34 | quoted: |- 35 | 💬 @%{username} siterte deg 36 | i %{topic}. 37 | 38 |
%{post_excerpt}39 | replied: |- 40 | ↩️ @%{username} svarte deg 41 | i %{topic}. 42 | 43 |
%{post_excerpt}44 | posted: |- 45 | 💬 @%{username} la ut noe 46 | i %{topic}. 47 | 48 |
%{post_excerpt}49 | private_message: |- 50 | ✉️ @%{username} har sendt deg en personlig melding 51 | i %{topic}. 52 | 53 |
%{post_excerpt}54 | linked: |- 55 | 🔗 @%{username} lenka til innlegget ditt 56 | fra %{topic}. 57 | 58 |
%{post_excerpt}59 | watching_first_post: |- 60 | 💬 @%{username} la ut noe 61 | i %{topic}. 62 | 63 |
%{post_excerpt}64 | # Discourse Follow Plugin 65 | following_replied: |- 66 | ↩️👥 @%{username} svarte noen 67 | i %{topic}. 68 | 69 |
%{post_excerpt}70 | following_posted: |- 71 | 💬👥 @%{username} skrev noe 72 | i %{topic}. 73 | 74 |
%{post_excerpt}75 | -------------------------------------------------------------------------------- /config/locales/server.pl_PL.yml: -------------------------------------------------------------------------------- 1 | pl_PL: 2 | site_settings: 3 | telegram_notifications_enabled: Włączone powiadomienia z telegramu? 4 | telegram_access_token: Uzyskaj token dostępu do swojego bota 5 | discourse_telegram_notifications: 6 | initial-contact: "Aby otrzymywać powiadomienia %{site_title}, wprowadź 'Chat ID' %{chat_id} w preferencjach użytkownika." 7 | known-user: |- 8 | Witaj %{username}, wyślemy ci wiadomość o nowych powiadomieniach na %{site_title}. 9 | Odpowiadając na powiadomienie opublikuję odpowiedź na %{site_title}. 10 | Aby wyłączyć, odwiedź ustawienia użytkownika. 11 | view_online: "Zobacz online" 12 | like: "Lajkuj" 13 | unlike: "Wycofaj lajka" 14 | already-liked: "Właśnie zalajkowałeś ten post" 15 | like-failed: "Nie udało się zalajkować" 16 | like-success: "Pomyślnie zalajkowano wpis" 17 | unlike-failed: "Nie udało się zaprzestać lajkować ;)" 18 | unlike-success: "Pomyślnie wycofano lajka" 19 | reply-error: "❌ Błąd podczas przetwarzania odpowiedzi." 20 | reply-failed: "❌ Odpowiedź nie powiodła się: \n\n %{errors}" 21 | reply-success: "✅ Pomyślnie odpowiedziano - wyświetl to here" 22 | message: 23 | mentioned: |- 24 | 💬 @%{username} wspomina o Tobie w 25 | %{topic} 26 | 27 |
%{post_excerpt}28 | group_mentioned: |- 29 | 💬 @%{username} wspomina o Tobie w %{topic} 30 | 31 |
%{post_excerpt}32 | quoted: |- 33 | 💬 @%{username} cytuje Ciebie w %{topic} 34 | 35 |
%{post_excerpt}36 | replied: |- 37 | ↩️ @%{username} odpowiada tobie w %{topic} 38 | 39 |
%{post_excerpt}40 | posted: |- 41 | 💬 @%{username} napisał 42 | w %{topic} 43 | 44 |
%{post_excerpt}45 | private_message: |- 46 | ✉️ @%{username} wysłał Tobie prywatną wiadomość 47 | in %{topic} 48 | 49 |
%{post_excerpt}50 | linked: |- 51 | 🔗 @%{username} wysłał odnośnik do Twojego postu z %{topic} 52 | 53 |
%{post_excerpt}54 | following_replied: |- 55 | ↩️ Obserwowany @%{username} odpowiedział w %{topic} 56 | 57 |
%{post_excerpt}58 | following_posted: |- 59 | ↩️ Obserwowany @%{username} utworzył nowy temat: %{topic} 60 | 61 |
%{post_excerpt}62 | -------------------------------------------------------------------------------- /config/locales/server.ru.yml: -------------------------------------------------------------------------------- 1 | ru: 2 | site_settings: 3 | telegram_notifications_enabled: "Включить уведомления в Telegram?" 4 | telegram_access_token: "Получите токен доступа для вашего бота у @BotFather в Telegram" 5 | telegram_enabled_notification_types: "Ограничить уведомления в Telegram по типам" 6 | discourse_telegram_notifications: 7 | initial-contact: "Чтобы получать уведомления от %{site_title}, введите 'Chat ID' %{chat_id} в настройках вашего профиля" 8 | known-user: |- 9 | Привет, %{username}! Я буду присылать уведомления о новых событиях на %{site_title}. 10 | Ответив здесь, вы опубликуете сообщение в теме на %{site_title}. 11 | Чтобы отключить уведомления, измените настройки профиля. 12 | view_online: "Посмотреть на сайте" 13 | like: "❤️ Нравится" 14 | unlike: "❤️ Убрать лайк" 15 | already-liked: "Вы уже лайкнули этот пост" 16 | like-failed: "Ошибка при добавлении лайка" 17 | like-success: "Лайк успешно поставлен" 18 | unlike-failed: "Ошибка при удалении лайка" 19 | unlike-success: "Лайк успешно убран" 20 | reply-error: "❌ Ошибка при обработке вашего ответа" 21 | reply-failed: "❌ Ошибка отправки ответа: \n\n %{errors}" 22 | reply-success: "✅ Ответ успешно отправлен — посмотреть здесь" 23 | message: 24 | mentioned: |- 25 | 💬 @%{username} упомянул(а) вас 26 | в %{topic} 27 | 28 |
%{post_excerpt}29 | group_mentioned: |- 30 | 💬 @%{username} упомянул(а) вашу группу 31 | в %{topic} 32 | 33 |
%{post_excerpt}34 | quoted: |- 35 | 💬 @%{username} процитировал(а) вас 36 | в %{topic} 37 | 38 |
%{post_excerpt}39 | replied: |- 40 | ↩️ @%{username} ответил(а) вам 41 | в %{topic} 42 | 43 |
%{post_excerpt}44 | posted: |- 45 | 💬 @%{username} написал(а) 46 | в %{topic} 47 | 48 |
%{post_excerpt}49 | private_message: |- 50 | ✉️ @%{username} отправил(а) вам личное сообщение 51 | в %{topic} 52 | 53 |
%{post_excerpt}54 | linked: |- 55 | 🔗 @%{username} сослался(ась) на ваш пост 56 | в %{topic} 57 | 58 |
%{post_excerpt}59 | watching_first_post: |- 60 | 💬 @%{username} опубликовал(а) пост 61 | в %{topic} 62 | 63 |
%{post_excerpt}64 | # Discourse Follow Plugin 65 | following_replied: |- 66 | ↩️👥 @%{username} ответил(а) 67 | в %{topic} 68 | 69 |
%{post_excerpt}70 | following_posted: |- 71 | 💬👥 @%{username} написал(а) 72 | в %{topic} 73 | 74 |
%{post_excerpt}-------------------------------------------------------------------------------- /config/locales/server.zh_CN.yml: -------------------------------------------------------------------------------- 1 | zh_CN: 2 | site_settings: 3 | telegram_notifications_enabled: 启用 telegram 通知? 4 | telegram_access_token: 从 Telegram 官方机器人 BotFather 得到的你自己的机器人的 Token,看起来像 110201543:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw 5 | discourse_telegram_notifications: 6 | initial-contact: "要在 %{site_title} 启用通知,请进入论坛的偏好设置 > 个人资料,输入 'Chat ID':%{chat_id}" 7 | known-user: |- 8 | Hi %{username}, 当你在 %{site_title} 上有新的通知时,我会给你留言。 9 | 你可以直接回复通知,就可以在 %{site_title} 上发布回复。 10 | 要禁用通知,请访问你的偏好设置。 11 | view_online: "在线查看" 12 | like: "❤️ 点赞" 13 | unlike: "❤️ 取消点赞" 14 | already-liked: "你已经赞过这个帖子" 15 | like-failed: "点赞失败" 16 | like-success: "点赞成功" 17 | unlike-failed: "取消点赞失败" 18 | unlike-success: "取消点赞成功" 19 | reply-error: "❌ 在处理你的回复时发生了一个错误" 20 | reply-failed: "❌ 回复失败: \n\n %{errors}" 21 | reply-success: "✅ 回复成功 - 在线查看" 22 | message: 23 | mentioned: |- 24 | 💬 @%{username} 提及 你 25 | 在 %{topic} 26 |
%{post_excerpt}27 | group_mentioned: |- 28 | 💬 @%{username} 提及 你 29 | 在 %{topic} 30 |
%{post_excerpt}31 | quoted: |- 32 | 💬 @%{username} 引用 你 33 | 在 %{topic} 34 |
%{post_excerpt}35 | replied: |- 36 | ↩️ @%{username} 回复 给你 37 | 在 %{topic} 38 |
%{post_excerpt}39 | posted: |- 40 | 💬 @%{username} 发布 41 | 在 %{topic} 42 |
%{post_excerpt}43 | private_message: |- 44 | ✉️ @%{username} 发给你 一条私信 45 | 在 %{topic} 46 |
%{post_excerpt}47 | linked: |- 48 | 🔗 @%{username} 链接 你的帖子 49 | 从 %{topic} 50 |
%{post_excerpt}51 | -------------------------------------------------------------------------------- /config/locales/server.zh_HK.yml: -------------------------------------------------------------------------------- 1 | zh_HK: 2 | site_settings: 3 | telegram_notifications_enabled: 啓用 Telegram 通知? 4 | telegram_access_token: 使用 Telegram 的 BotFather 獲得你的 Bot Access Token 5 | discourse_telegram_notifications: 6 | initial-contact: "如要獲得來自 %{site_title} 的通知,請先在你的用戶偏好中輸入 'Chat ID' %{chat_id}" 7 | known-user: |- 8 | 你好 %{username},每當你有新通知時,我會發送訊息給你。 9 | 回覆此通知會在 %{site_title} 發佈回覆。 10 | 如要停用此功能,請在你的用戶偏好中設定。 11 | view_online: "線上檢視" 12 | like: "❤️ 讚好" 13 | unlike: "❤️ 取消讚好" 14 | already-liked: "你已經讚好了該帖" 15 | like-failed: "讚好不成功" 16 | like-success: "成功讚好" 17 | unlike-failed: "取消讚好不成功" 18 | unlike-success: "成功取消讚好" 19 | reply-error: "❌ 處理你的回覆時發生錯誤" 20 | reply-failed: "❌ 回覆不成功:\n\n %{errors}" 21 | reply-success: "✅ 成功回覆,可以瀏覽:here" 22 | message: 23 | mentioned: |- 24 | 💬 在 %{topic} 25 | @%{username} 提及了你 26 | 27 |
%{post_excerpt}28 | group_mentioned: |- 29 | 💬 在 %{topic} 30 | @%{username} 提及了你 31 | 32 |
%{post_excerpt}33 | quoted: |- 34 | 💬 在 %{topic} 35 | @%{username} 引用了你 36 | 37 |
%{post_excerpt}38 | replied: |- 39 | ↩️ 在 %{topic} 40 | @%{username} 回覆了你 41 | 42 |
%{post_excerpt}43 | posted: |- 44 | 💬 @%{username} 發佈了 45 | %{topic} 46 | 47 |
%{post_excerpt}48 | private_message: |- 49 | ✉️ 在 %{topic} 50 | @%{username} 發送了私人訊息給你 51 | 52 |
%{post_excerpt}53 | linked: |- 54 | 🔗 在 %{topic} 55 | @%{username} 鏈接了你的帖子 56 | 57 |
%{post_excerpt}58 | watching_first_post: |- 59 | 💬 @%{username} 發佈了 60 | %{topic} 61 | 62 |
%{post_excerpt}63 | # Discourse Follow Plugin 64 | following_replied: |- 65 | ↩️👥 在 %{topic} 66 | @%{username} 有新回覆 67 | 68 |
%{post_excerpt}69 | following_posted: |- 70 | 💬👥 @%{username} 發佈了 71 | %{topic} 72 | 73 |
%{post_excerpt}74 | -------------------------------------------------------------------------------- /config/settings.yml: -------------------------------------------------------------------------------- 1 | plugins: 2 | telegram_notifications_enabled: 3 | default: false 4 | telegram_access_token: 5 | default: '' 6 | telegram_secret: 7 | default: '' 8 | hidden: true 9 | telegram_enabled_notification_types: 10 | type: list 11 | default: mentioned|replied|quoted|posted|linked|private_message|group_mentioned|watching_first_post|event_reminder|event_invitation|following_replied|following_posted 12 | client: false 13 | -------------------------------------------------------------------------------- /plugin.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # name: discourse-telegram-notifications 4 | # about: A plugin which posts all user notifications to a telegram message 5 | # version: 0.1 6 | # authors: David Taylor 7 | # url: https://github.com/davidtaylorhq/discourse-telegram-notifications 8 | 9 | require 'cgi' 10 | 11 | enabled_site_setting :telegram_notifications_enabled 12 | 13 | after_initialize do 14 | 15 | module ::DiscourseTelegramNotifications 16 | PLUGIN_NAME ||= "discourse_telegram_notifications".freeze 17 | 18 | autoload :TelegramNotifier, "#{Rails.root}/plugins/discourse-telegram-notifications/services/discourse_telegram_notifications/telegram-notifier" 19 | 20 | class Engine < ::Rails::Engine 21 | engine_name PLUGIN_NAME 22 | isolate_namespace DiscourseTelegramNotifications 23 | end 24 | end 25 | 26 | DiscourseTelegramNotifications::Engine.routes.draw do 27 | post "/hook/:key" => "telegram#hook" 28 | end 29 | 30 | Discourse::Application.routes.append do 31 | mount ::DiscourseTelegramNotifications::Engine, at: "/telegram" 32 | end 33 | 34 | class DiscourseTelegramNotifications::TelegramController < ::ApplicationController 35 | requires_plugin DiscourseTelegramNotifications::PLUGIN_NAME 36 | 37 | skip_before_action :check_xhr, :preload_json, :verify_authenticity_token, :redirect_to_login_if_required 38 | 39 | def hook 40 | if not SiteSetting.telegram_notifications_enabled 41 | render status: 404 42 | end 43 | 44 | if not (defined? params['key'] && (params['key'] == SiteSetting.telegram_secret)) 45 | Rails.logger.error("Telegram hook called with incorrect key") 46 | render status: 403 47 | return 48 | end 49 | 50 | # If it's a new message (telegram also sends hooks for other reasons that we don't care about) 51 | if params.key?('message') 52 | 53 | chat_id = params['message']['chat']['id'] 54 | 55 | known_user = false 56 | 57 | begin 58 | user_custom_field = UserCustomField.find_by(name: "telegram_chat_id", value: chat_id) 59 | user = User.find(user_custom_field.user_id) 60 | message_text = I18n.t( 61 | "discourse_telegram_notifications.known-user", 62 | site_title: CGI::escapeHTML(SiteSetting.title), 63 | username: user.username 64 | ) 65 | known_user = true 66 | rescue Discourse::NotFound, NoMethodError 67 | message_text = I18n.t( 68 | "discourse_telegram_notifications.initial-contact", 69 | site_title: CGI::escapeHTML(SiteSetting.title), 70 | chat_id: chat_id, 71 | ) 72 | end 73 | 74 | if known_user && params['message'].key?('reply_to_message') 75 | 76 | begin 77 | reply_to_message_id = params['message']['reply_to_message']['message_id'] 78 | post_id = PluginStore.get("telegram-notifications", "message_#{reply_to_message_id}") 79 | reply_to = Post.find(post_id) 80 | found_post = true 81 | rescue ActiveRecord::RecordNotFound 82 | found_post = false 83 | end 84 | 85 | if found_post 86 | 87 | new_post = { 88 | raw: params['message']['text'], 89 | topic_id: reply_to.topic_id, 90 | reply_to_post_number: reply_to.post_number, 91 | } 92 | 93 | manager = NewPostManager.new(user, new_post) 94 | result = manager.perform 95 | 96 | if result.errors.any? 97 | errors = result.errors.full_messages.join("\n") 98 | 99 | message_text = I18n.t( 100 | "discourse_telegram_notifications.reply-failed", 101 | errors: errors 102 | ) 103 | else 104 | message_text = I18n.t( 105 | "discourse_telegram_notifications.reply-success", 106 | post_url: result.post.full_url 107 | ) 108 | end 109 | else 110 | message_text = I18n.t("discourse_telegram_notifications.reply-error") 111 | end 112 | 113 | end 114 | 115 | message = { 116 | chat_id: chat_id, 117 | text: message_text, 118 | parse_mode: "html", 119 | disable_web_page_preview: true, 120 | } 121 | 122 | DiscourseTelegramNotifications::TelegramNotifier.sendMessage(message) 123 | elsif params.key?('callback_query') 124 | chat_id = params['callback_query']['message']['chat']['id'] 125 | user_id = UserCustomField.where(name: "telegram_chat_id", value: chat_id).first.user_id 126 | user = User.find(user_id) 127 | 128 | data = params['callback_query']['data'].split(":") 129 | 130 | post = Post.find(data[1]) 131 | 132 | string = I18n.t("discourse_telegram_notifications.error-unknown-action") 133 | 134 | if data[0] == "like" 135 | begin 136 | PostActionCreator.create(user, post, :like) 137 | string = I18n.t("discourse_telegram_notifications.like-success") 138 | rescue PostAction::AlreadyActed 139 | string = I18n.t("discourse_telegram_notifications.already-liked") 140 | rescue Discourse::InvalidAccess 141 | string = I18n.t("discourse_telegram_notifications.like-fail") 142 | end 143 | 144 | DiscourseTelegramNotifications::TelegramNotifier.answerCallback(params['callback_query']['id'], string) 145 | elsif data[0] == 'unlike' 146 | 147 | begin 148 | guardian = Guardian.new(user) 149 | post_action_type_id = PostActionType.types[:like] 150 | post_action = user.post_actions.find_by(post_id: post.id, post_action_type_id: post_action_type_id, deleted_at: nil) 151 | raise Discourse::NotFound if post_action.blank? 152 | guardian.ensure_can_delete!(post_action) 153 | PostAction.remove_act(user, post, post_action_type_id) 154 | 155 | string = I18n.t("discourse_telegram_notifications.unlike-success") 156 | rescue Discourse::NotFound, Discourse::InvalidAccess 157 | string = I18n.t("discourse_telegram_notifications.unlike-failed") 158 | end 159 | 160 | end 161 | 162 | DiscourseTelegramNotifications::TelegramNotifier.answerCallback(params['callback_query']['id'], string) 163 | 164 | message = { 165 | chat_id: chat_id, 166 | message_id: params['callback_query']['message']['message_id'], 167 | reply_markup: DiscourseTelegramNotifications::TelegramNotifier.generateReplyMarkup(post, user) 168 | } 169 | 170 | DiscourseTelegramNotifications::TelegramNotifier.editKeyboard(message) 171 | end 172 | 173 | # Always give telegram a success message, otherwise we'll stop receiving webhooks 174 | data = { 175 | success: true 176 | } 177 | render json: data 178 | end 179 | 180 | end 181 | DiscoursePluginRegistry.serialized_current_user_fields << "telegram_chat_id" 182 | 183 | User.register_custom_field_type('telegram_chat_id', :text) 184 | register_editable_user_custom_field :telegram_chat_id 185 | 186 | DiscourseEvent.on(:post_notification_alert) do |user, payload| 187 | if SiteSetting.telegram_notifications_enabled? 188 | Jobs.enqueue(:send_telegram_notifications, user_id: user.id, payload: payload) 189 | end 190 | end 191 | 192 | DiscourseEvent.on(:site_setting_changed) do |name, old, new| 193 | if (name == :telegram_notifications_enabled) || (name == :telegram_access_token) 194 | Jobs.enqueue(:setup_telegram_webhook) 195 | end 196 | end 197 | 198 | require_dependency "jobs/base" 199 | module ::Jobs 200 | class SendTelegramNotifications < ::Jobs::Base 201 | def execute(args) 202 | return if !SiteSetting.telegram_notifications_enabled? 203 | 204 | payload = args[:payload] 205 | 206 | return unless SiteSetting.telegram_enabled_notification_types.split("|").include?(Notification.types[payload[:notification_type]].to_s) 207 | 208 | user = User.find(args[:user_id]) 209 | 210 | chat_id = user.custom_fields["telegram_chat_id"] 211 | 212 | if (not chat_id.present?) || (chat_id.length < 1) 213 | return 214 | end 215 | 216 | post = Post.where(post_number: payload[:post_number], topic_id: payload[:topic_id]).first 217 | 218 | message_text = I18n.t( 219 | "discourse_telegram_notifications.message.#{Notification.types[payload[:notification_type]]}", 220 | site_title: CGI::escapeHTML(SiteSetting.title), 221 | site_url: Discourse.base_url, 222 | post_url: Discourse.base_url + payload[:post_url], 223 | post_excerpt: CGI::escapeHTML(payload[:excerpt]), 224 | topic: CGI::escapeHTML(payload[:topic_title]), 225 | username: CGI::escapeHTML(payload[:username]), 226 | user_url: Discourse.base_url + "/u/" + payload[:username] 227 | ) 228 | 229 | message = { 230 | chat_id: chat_id, 231 | text: message_text, 232 | parse_mode: "html", 233 | disable_web_page_preview: true, 234 | reply_markup: DiscourseTelegramNotifications::TelegramNotifier.generateReplyMarkup(post, user), 235 | } 236 | 237 | response = DiscourseTelegramNotifications::TelegramNotifier.sendMessage(message) 238 | 239 | if response 240 | message_id = response['result']['message_id'] 241 | 242 | PluginStore.set("telegram-notifications", "message_#{message_id}", post.id) 243 | end 244 | 245 | end 246 | end 247 | 248 | class SetupTelegramWebhook < ::Jobs::Base 249 | def execute(args) 250 | return if !SiteSetting.telegram_notifications_enabled? 251 | 252 | SiteSetting.telegram_secret = SecureRandom.hex 253 | 254 | DiscourseTelegramNotifications::TelegramNotifier.setupWebhook(SiteSetting.telegram_secret) 255 | 256 | end 257 | end 258 | 259 | end 260 | end 261 | -------------------------------------------------------------------------------- /services/discourse_telegram_notifications/telegram-notifier.rb: -------------------------------------------------------------------------------- 1 | require 'json' 2 | require 'net/http' 3 | 4 | module DiscourseTelegramNotifications 5 | class TelegramNotifier 6 | def self.sendMessage(message) 7 | return self.doRequest('sendMessage', message) 8 | end 9 | 10 | def self.answerCallback(callback_id, text) 11 | message = { 12 | callback_query_id: callback_id, 13 | text: text 14 | } 15 | 16 | return self.doRequest('answerCallbackQuery', message) 17 | end 18 | 19 | def self.setupWebhook(key) 20 | message = { 21 | url: Discourse.base_url+'/telegram/hook/'+SiteSetting.telegram_secret, 22 | } 23 | 24 | return self.doRequest('setWebhook', message) 25 | end 26 | 27 | def self.editKeyboard(message) 28 | return self.doRequest('editMessageReplyMarkup', message) 29 | end 30 | 31 | def self.doRequest(methodName, message) 32 | http = Net::HTTP.new("api.telegram.org", 443) 33 | http.use_ssl = true 34 | 35 | access_token = SiteSetting.telegram_access_token 36 | 37 | uri = URI("https://api.telegram.org/bot#{access_token}/#{methodName}") 38 | 39 | req = Net::HTTP::Post.new(uri, 'Content-Type' =>'application/json') 40 | req.body = message.to_json 41 | response = http.request(req) 42 | 43 | responseData = JSON.parse(response.body) 44 | 45 | if not responseData['ok'] == true 46 | Rails.logger.error("Failed to send Telegram message. Message data= "+req.body.to_json+ " response="+response.body.to_json) 47 | return false 48 | end 49 | 50 | return responseData 51 | end 52 | 53 | def self.generateReplyMarkup(post, user) 54 | likes = UserAction.where(action_type: UserAction::LIKE, user_id: user.id, target_post_id: post.id).count 55 | 56 | if likes > 0 57 | likeButtonText = I18n.t("discourse_telegram_notifications.unlike") 58 | likeButtonAction = "unlike:#{post.id}" 59 | else 60 | likeButtonText = I18n.t("discourse_telegram_notifications.like") 61 | likeButtonAction = "like:#{post.id}" 62 | end 63 | post_url = "#{Discourse.base_url}#{post.url(opts={without_slug: true})}" 64 | { 65 | inline_keyboard:[ 66 | [ 67 | {text: likeButtonText, callback_data:likeButtonAction}, 68 | {text: I18n.t("discourse_telegram_notifications.view_online"), url:post_url}, 69 | ] 70 | ] 71 | } 72 | end 73 | 74 | end 75 | end 76 | --------------------------------------------------------------------------------