dialog_ruby 0.1.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 (103) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/Gemfile +0 -0
  4. data/_dev/get_full_botapi.rb +59 -0
  5. data/_dev/inlinekb_pubsub.rb +69 -0
  6. data/_dev/main.rb +127 -0
  7. data/_dev/restriction.rb +32 -0
  8. data/_dev/ru.yml +79 -0
  9. data/_dev/sidekiq.rb +28 -0
  10. data/_dev/tdlib.rb +154 -0
  11. data/dialog.sh +51 -0
  12. data/dialog_ruby.gemspec +41 -0
  13. data/lib/architecture.md +22 -0
  14. data/lib/configuration.rb +117 -0
  15. data/lib/dialogStart.rb +189 -0
  16. data/lib/dialog_ruby.rb +59 -0
  17. data/lib/exec.sh +61 -0
  18. data/lib/exec_conf/cli_config +7 -0
  19. data/lib/exec_conf/dialog__sync.service +14 -0
  20. data/lib/exec_conf/dialog__sync.timer +11 -0
  21. data/lib/exec_conf/dialog_bot@.path +6 -0
  22. data/lib/exec_conf/dialog_bot@.service +18 -0
  23. data/lib/exec_conf/dialog_bot_dev@.path +6 -0
  24. data/lib/exec_conf/dialog_bot_dev_pre@.service +16 -0
  25. data/lib/exec_conf/dialog_bot_pre@.service +16 -0
  26. data/lib/exec_conf/dialog_redis@.service +14 -0
  27. data/lib/exec_conf/post-merge +5 -0
  28. data/lib/exec_conf/redis_global.conf +49 -0
  29. data/lib/exec_conf/redis_local.conf +4 -0
  30. data/lib/lang/global_ru.yml +29 -0
  31. data/lib/lib/dialect/canvas/canvas.rb +35 -0
  32. data/lib/lib/dialect/canvas/element/convert/SearchBaloo.rb +45 -0
  33. data/lib/lib/dialect/canvas/element/data/search.rb +34 -0
  34. data/lib/lib/dialect/canvas/element/send/Inline_query_result.rb +32 -0
  35. data/lib/lib/dialect/canvas/element/send/bot_message.rb +38 -0
  36. data/lib/lib/dialect/canvas/element/send/keyboards.rb +59 -0
  37. data/lib/lib/dialect/canvas/element/send/recognize.rb +51 -0
  38. data/lib/lib/dialect/canvas/element/send/restrict.rb +42 -0
  39. data/lib/lib/dialect/canvas/element/send/tdlib_chat.rb +33 -0
  40. data/lib/lib/dialect/canvas/element/send/tdlib_message.rb +38 -0
  41. data/lib/lib/dialect/canvas/mod/send/_Inline_query_result.rb +38 -0
  42. data/lib/lib/dialect/canvas/mod/send/_keyboards.rb +40 -0
  43. data/lib/lib/dialect/canvas/mod/send/func.rb +98 -0
  44. data/lib/lib/dialect/canvas/mod/send/general/_heads.rb +27 -0
  45. data/lib/lib/dialect/canvas/mod/send/general/chat.rb +38 -0
  46. data/lib/lib/dialect/canvas/mod/send/general/common.rb +32 -0
  47. data/lib/lib/dialect/canvas/mod/send/general/message.rb +37 -0
  48. data/lib/lib/dialect/canvas/mod/send/general/user.rb +36 -0
  49. data/lib/lib/dialect/canvas/mod/send/inline_query_result/common.rb +36 -0
  50. data/lib/lib/dialect/codegen/codegen.rb +74 -0
  51. data/lib/lib/dialect/codegen/erb/data/1.ModReceive2GetData.erb +27 -0
  52. data/lib/lib/dialect/codegen/erb/data/2.GetData2Elements.erb +27 -0
  53. data/lib/lib/dialect/codegen/erb/data/3.GenData2Dest.erb +34 -0
  54. data/lib/lib/dialect/codegen/erb/functional/1.Expect2Events.erb +37 -0
  55. data/lib/lib/dialect/codegen/erb/functional/2.1.Events2AppEvent.erb +26 -0
  56. data/lib/lib/dialect/codegen/erb/functional/2.2.1.Events2ModReceive.erb +73 -0
  57. data/lib/lib/dialect/codegen/erb/functional/2.2.2.ModReceive2AppEvent.erb +59 -0
  58. data/lib/lib/dialect/codegen/erb/functional/3.Appevent2EventBus.erb +35 -0
  59. data/lib/lib/dialect/codegen/erb/functional/4.1.AppEvent2Elements.erb +72 -0
  60. data/lib/lib/dialect/codegen/erb/functional/5.1.Element2ModElements.erb +70 -0
  61. data/lib/lib/dialect/codegen/erb/functional/5.2.Element2ModSend.erb +69 -0
  62. data/lib/lib/dialect/codegen/erb/functional/7.ElementChains.erb +91 -0
  63. data/lib/lib/dialect/codegen/repack/constructor/DockedGroupings2AppFunctions.rb +36 -0
  64. data/lib/lib/dialect/codegen/repack/constructor/Element2ModSend.rb +49 -0
  65. data/lib/lib/dialect/codegen/repack/constructor/ElementsInElements.rb +34 -0
  66. data/lib/lib/dialect/codegen/repack/functional/1.Expect2Events.rb +35 -0
  67. data/lib/lib/dialect/codegen/repack/functional/2.2.1.Events2ModReceive.rb +71 -0
  68. data/lib/lib/dialect/codegen/repack/functional/2.2.2.ModReceive2AppEvent.rb +45 -0
  69. data/lib/lib/dialect/codegen/repack/functional/5.1.Element2ModElements.rb +90 -0
  70. data/lib/lib/dialect/codegen/repack/functional/5.2.Element2ModSend.rb +60 -0
  71. data/lib/lib/dialect/codegen/repack/functional/7.ElementChains.rb +88 -0
  72. data/lib/lib/dialect/codegen/run.rb +79 -0
  73. data/lib/lib/metamess/_run.rb +162 -0
  74. data/lib/lib/metamess/content/content_o-command_f.rb +100 -0
  75. data/lib/lib/metamess/content/content_o-media_f.rb +149 -0
  76. data/lib/lib/metamess/content/content_o-simple_f.rb +35 -0
  77. data/lib/lib/metamess/content/content_o.rb +245 -0
  78. data/lib/lib/metamess/event/notify_o-chatmember_f.rb +124 -0
  79. data/lib/lib/metamess/event/notify_o-chattitle_f.rb +34 -0
  80. data/lib/lib/metamess/event/notify_o-create_f.rb +42 -0
  81. data/lib/lib/metamess/event/notify_o-migrate_f.rb +34 -0
  82. data/lib/lib/metamess/event/notify_o-pinned_f.rb +34 -0
  83. data/lib/lib/metamess/event/notify_o.rb +28 -0
  84. data/lib/lib/metamess/event_c.rb +26 -0
  85. data/lib/lib/metamess/func.rb +220 -0
  86. data/lib/lib/metamess/service/service_o-callback_f.rb +33 -0
  87. data/lib/lib/metamess/service/service_o-inline_f.rb +55 -0
  88. data/lib/lib/metamess/service/service_o.rb +26 -0
  89. data/lib/lib/naming.rb +130 -0
  90. data/lib/lib/storage/redis/redisPubSub.rb +51 -0
  91. data/lib/lib/storage/redis/rediscached.rb +97 -0
  92. data/lib/lib/tdlib/auth.rb +141 -0
  93. data/lib/lib/tdlib/func.rb +34 -0
  94. data/lib/lib/tdlib/init.rb +39 -0
  95. data/lib/lib/telegram/botapi.rb +71 -0
  96. data/lib/lib/telegram/infra_info.rb +50 -0
  97. data/lib/lib/telegram/wrappers.rb +41 -0
  98. data/lib/lib/tooling/lang.rb +24 -0
  99. data/lib/lib/tooling/log.rb +54 -0
  100. data/lib/lib/tooling/ruby.rb +25 -0
  101. data/lib/version.rb +3 -0
  102. data/logo.png +0 -0
  103. metadata +305 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: '0591c8831efddb65fe397568eb0327c8f57c17836f7509ae91251147a2113625'
4
+ data.tar.gz: 87e1b6ada747943e22e2f06d1c61cbdf993cb4863f98790b9d4b529808b15b97
5
+ SHA512:
6
+ metadata.gz: 647a9aed6209576da9db0a8299ae2f5e20a76a11f69b189ba92f9f0fee23ad7dd0c56a3cc2b3f7cfb6704a4c7f02a4ddd532877521cbc04ea3279b23e191cfaa
7
+ data.tar.gz: 241afa9492fc9bef33ff66f29eb61bb1bf497140f1990d892785df43e74dfe014f5326e04a69452be1217d39b8d7de2fee43c4e1f3181d20b9ff19ce4fa797a6
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ *.gem
data/Gemfile ADDED
File without changes
@@ -0,0 +1,59 @@
1
+ require 'oj'
2
+ require 'nokogiri'
3
+
4
+ html = File.read('./api.html')
5
+ doc = Nokogiri::HTML(html)
6
+
7
+ tables = {}
8
+ headers = {}
9
+ res = {}
10
+ trRunCount = 0
11
+ tablesHeader = {}
12
+
13
+ doc.xpath('//table/tbody/tr').each do |row|
14
+ pre = {}
15
+ tdNum = 1
16
+ row.xpath('td').each do |cell|
17
+ case cell.text
18
+ when 'Field', 'Parameters'
19
+ trRunCount = 1 if trRunCount > 1
20
+ tablesHeader = {} if trRunCount > 1
21
+ end
22
+
23
+ if trRunCount == 1
24
+ tablesHeader[tdNum] = cell.text.strip.to_sym
25
+ else
26
+ case tablesHeader[tdNum]
27
+ when :Type, :Field
28
+ pre[tablesHeader[tdNum]] = cell.text.to_sym
29
+ else
30
+ pre[tablesHeader[tdNum]] = cell.text
31
+ end
32
+ end
33
+
34
+ # p "# trRunCount::#{trRunCount}, tdNum::#{tdNum}, tablesHeader::#{tablesHeader}, pre::#{pre}"
35
+ tdNum = tdNum + 1
36
+ end
37
+ trRunCount += 1
38
+ # p "#pre::#{pre}"
39
+ tables[row.line.to_i] = pre
40
+ end
41
+
42
+
43
+ doc.xpath('//h4').each do |row|
44
+ headers[row.line] = row.text
45
+ end
46
+
47
+ headers.each do |row, content|
48
+ i = 6
49
+ while i < 12
50
+ if tables.has_key?(row+i)
51
+ res[content.to_sym] = tables[row+i]
52
+ break
53
+ else
54
+ i = i+1
55
+ end
56
+ end
57
+ end
58
+
59
+ pp res
@@ -0,0 +1,69 @@
1
+ ######## ####### ######## ####### ######## ########
2
+ ## / / / / License \ \ \ \
3
+ ## Copyleft culture, Copyright (C) is prohibited here
4
+ ## This work is licensed under a CC BY-SA 4.0
5
+ ## Creative Commons Attribution-ShareAlike 4.0 License
6
+ ## Refer to the http://creativecommons.org/licenses/by-sa/4.0/
7
+ ######## ####### ######## ####### ######## ########
8
+ ## / / / / Code Climate \ \ \ \
9
+ ## Language = ruby
10
+ ## Indent = space; 2 chars;
11
+ ######## ####### ######## ####### ######## ########
12
+
13
+ module Bot
14
+ class Interfaces
15
+
16
+ def smsgDefaults(args)
17
+ args[:smsg][:parse_mode] = 'HTML'
18
+ args[:smsg][:chat_id] = args[:mmsg][:chat_id]
19
+ end
20
+
21
+ def kbInlineUsingCallback(args)
22
+ args[:sess] = {}
23
+ args[:smsg] = {}
24
+ args[:tmp] = {}
25
+
26
+ smsgDefaults(args)
27
+
28
+ kbInlineUsingCallbackKB(args)
29
+ kbInlineUsingCallbackAnswer(args)
30
+ if ! args[:run][:answer].nil?
31
+ kbInlineUsingCallbackDeleteMessages(args)
32
+ # args[:run][:tryMethod] = args[:run][:answer][:data] # working without explicit tryMethod
33
+ Bot::Convey.new.tryMethodRun(args)
34
+ end
35
+ end
36
+
37
+
38
+ def kbInlineUsingCallbackKB args
39
+ args[:run][:text] = args[:run][:textWithKB]
40
+ args[:tmp][:answer] = Bot::Atom.new.sendSimpleMessage(args)
41
+ end
42
+
43
+ def kbInlineUsingCallbackAnswer args
44
+ args[:tmp][:subPostfix] = 'Service_Callback_Query'
45
+ args[:tmp][:redisChannelpostfix] = args[:tmp][:answer]['result']['message_id']
46
+ Bot::RedisQueue.new.subGetUnsub(args)
47
+ if ! args[:run][:answer].nil?
48
+ args[:sess][:op] = 'answerCallbackQuery'
49
+ args[:smsg][:callback_query_id] = args[:mmsg][:query_id]
50
+ args[:smsg][:text] = "#{args[:run][:textAferKBPush]} #{args[:run][:answer]['data']}"
51
+ smsgDefaults(args)
52
+ Bot::BotApi.new.apiAction(args)
53
+ end
54
+ end
55
+
56
+ def kbInlineUsingCallbackDeleteMessages args
57
+ args[:sess][:op] = 'deleteMessage'
58
+ smsgDefaults(args)
59
+ args[:smsg][:message_id] = args[:mmsg][:message_id]
60
+ Bot::BotApi.new.apiAction(args)
61
+ if (args[:mmsg][:chat_context] == Naming::ChatContext.Botman or args[:mmsg][:chat_context] == Naming::ChatContext.Fullman)
62
+ args[:smsg][:message_id] = args[:mmsg][:reply_to_message_id]
63
+ Bot::BotApi.new.apiAction(args)
64
+ end
65
+ end
66
+
67
+ end
68
+ end
69
+
data/_dev/main.rb ADDED
@@ -0,0 +1,127 @@
1
+ ######## ####### ######## ####### ######## ########
2
+ ## / / / / License \ \ \ \
3
+ ## Copyleft culture, Copyright (C) is prohibited here
4
+ ## This work is licensed under a CC BY-SA 4.0
5
+ ## Creative Commons Attribution-ShareAlike 4.0 License
6
+ ## Refer to the http://creativecommons.org/licenses/by-sa/4.0/
7
+ ######## ####### ######## ####### ######## ########
8
+ ## / / / / Code Climate \ \ \ \
9
+ ## Language = ruby
10
+ ## Indent = space; 2 chars;
11
+ ######## ####### ######## ####### ######## ########
12
+
13
+ module Bot
14
+ class ConveyMeta
15
+
16
+ def hello_private(args)
17
+ <<~HEREDOC
18
+ Приветствую!
19
+ Я - своего рода, проводник по платформе прототипирования коммуникационных сред Dialog.
20
+ Моей задачей является рассказать о том, какие возможности для такого прототипирования предоставляет вам Dialog.
21
+ HEREDOC
22
+ end
23
+
24
+ def runMetacommand__start_main(args)
25
+ case args[:mmsg][:chat_context]
26
+ when 'Private'
27
+ args[:run][:inline_keyboard] = [
28
+ [{text: 'Что такое "прототипирование коммуникационных сред"', callback_data: '_что такое прототипирование'}],
29
+ # [{text: 'Как Dialog помогает в этом?', callback_data: '_как Dialog помогает'}],
30
+ [{text: 'С чего мне начать ', callback_data: '_с чего начать'}],
31
+ [{text: 'Список интерфейсов', callback_data: '_интерфейсы'}],
32
+ ]
33
+
34
+ args[:run][:textWithKB] = "Основное меню" if args[:run][:textWithKB] == false
35
+ args[:run][:textWithKB] = hello_private(args) if args[:run][:textWithKB].nil?
36
+ args[:run][:text_parse_mode] = 'HTML'
37
+ args[:run][:text_disable_web_page_preview] = 1
38
+
39
+ answer = Bot::Interfaces.new.kbInlineUsingCallback(args)
40
+ else
41
+ args[:run][:text] = "Мы пока не добавили сценарий для команды start контекста #{args[:mmsg][:chat_context]}"
42
+ Bot::Atom.new.sendSimpleMessage(args)
43
+ end
44
+ end
45
+
46
+ ###
47
+
48
+ def what_is_prototyping(args)
49
+ <<~HEREDOC
50
+ <b>"Прототипирование коммуникационных сред"</b> - \n это короткое наименование трёх параллельных движений: \n
51
+ 1) <b>Я вижу, что есть среда/группа/комьюнити</b> - то есть люди, объединённые общим интересом и имеющие определённые направление и плотность движения;
52
+ 2) <b>Я выражаю свой интерес к "совместному"</b>, а для этого я должен научиться описывать как своё и средовое движения по-отдельности, так и создать прототип этого "совместного";
53
+ 3) <b>Я понимаю, что в результате возникнет новое "совместное"</b>, и я, в силу своих способностей, должен быть способен рассказать/нарисовать/описать нашу модель коммуникации и её "прототип".
54
+
55
+ Чем же отличается <b>"модель"</b> от <b>"прототипа"</b>?
56
+
57
+ Вот хороший ответ:
58
+ "<b>Model</b>:
59
+ 1. Not necessarily functional (don't need to work).
60
+ 2. Can be to any scale (usually smaller but can also be of the original size or bigger).
61
+ 3. Used for Display or/and [Visual] Demonstration of product.
62
+ 4. May consist of only the exterior of the object/product it replicates.
63
+ 5. Relatively cheap to manufacture.
64
+
65
+ <b>Prototype</b>:
66
+ 1. Is fully functional, but not fault-proof.
67
+ 2. Is an actual version of the intended product.
68
+ 3. Used for performance evaluation and further improvement of product.
69
+ 4. Contains complete interior and exterior.
70
+ 5. Is relatively expensive to produce.
71
+ 6. Often used as a technology demonstrator"
72
+
73
+ HEREDOC
74
+ end
75
+
76
+ def runMetacommand__what_is_prototyping(args)
77
+ args[:run][:text_parse_mode] = 'HTML'
78
+ args[:run][:text] = what_is_prototyping(args)
79
+ Bot::Atom.new.sendSimpleMessage(args)
80
+ args[:run][:textWithKB] = false
81
+ runMetacommand__start_main(args)
82
+ end
83
+ alias runMetacommand__chto_takoe_prototipirovanie runMetacommand__what_is_prototyping
84
+
85
+ ###
86
+
87
+ def firstStep(args)
88
+ <<~HEREDOC
89
+ Начнём с того, что обозначим 5 режимов работы (<b>"контекстов"</b>):
90
+ 1) <b>Private</b> - режим общения с ботом тет-а-тет
91
+ 2) <b>Noman</b> - бот добавлен в обычную группу, права бота - как у обычного пользователя
92
+ 3) <b>Botman</b> - бот добавлен в обычную группу, права бота - администратор
93
+ 4) <b>Climan</b> - бот добавлен в специальную группу, права бота - как у обычного пользователя
94
+ 5) <b>Fullman</b> - бот добавлен в специальную группу, права бота - администратор
95
+
96
+ <b>"Обычная"</b> и <b>"специальная"</b> группы отличаются тем, что обычную создана человеком, а "специальная" - машиной, т.е. специальным аккаунтом, настроенным на взаимодействие с ботом.
97
+ Права администратора дают боту возможность управлять коллективным взаимодействием согласно прописанным сценариям.
98
+
99
+
100
+ В добавление к стандартному символу "/", используемому перед командой боту (например, "/start"), мы ввели дополнительный символ "_" для удобства общения с Dialog-ботами - например, "_start". Так же, команды могут даны на русском языке, например "_старт".
101
+
102
+ В режиме <b>'private'</b> можно писать ботам:
103
+ Боту @DialogDemoBot - это production-демобот
104
+ Боту @DialogDemoDevBot - это демобот для разработки и отладки
105
+
106
+ В режиме <b>'Noman'</b> работает группа https://t.me/joinchat/CCfa_1HM1ORbycphoyqmMw
107
+ В режиме <b>'Botman'</b> работает группа https://t.me/joinchat/CCfa_0ndJfLFH6f_Ec8Oig
108
+ В режиме <b>'Fullman'</b> работает группа https://t.me/joinchat/FTAtQEdYpbxl0i46Atadgw
109
+
110
+ Канал https://t.me/joinchat/AAAAAEwvsUuDodkHj74iJQ работает в режиме тестирования возможностей Dialog в каналах.
111
+ HEREDOC
112
+ end
113
+
114
+ def runMetacommand__start_with(args)
115
+ args[:run][:text_parse_mode] = 'HTML'
116
+ args[:run][:text] = firstStep(args)
117
+ Bot::Atom.new.sendSimpleMessage(args)
118
+ args[:run][:textWithKB] = false
119
+ runMetacommand__start_main(args)
120
+ end
121
+ alias runMetacommand__s_chego_nachat runMetacommand__start_with
122
+
123
+
124
+
125
+ end
126
+ end
127
+
@@ -0,0 +1,32 @@
1
+ ######## ####### ######## ####### ######## ########
2
+ ## / / / / License \ \ \ \
3
+ ## Copyleft culture, Copyright (C) is prohibited here
4
+ ## This work is licensed under a CC BY-SA 4.0
5
+ ## Creative Commons Attribution-ShareAlike 4.0 License
6
+ ## Refer to the http://creativecommons.org/licenses/by-sa/4.0/
7
+ ######## ####### ######## ####### ######## ########
8
+ ## / / / / Code Climate \ \ \ \
9
+ ## Language = ruby
10
+ ## Indent = space; 2 chars;
11
+ ######## ####### ######## ####### ######## ########
12
+
13
+ module Bot
14
+ class Atom
15
+
16
+ def restrictChatMember(args)
17
+ args[:smsg] = {}
18
+ args[:sess][:op] = 'restrictChatMember'
19
+ args[:smsg][:chat_id] = args[:mmsg][:chat_id]
20
+ args[:smsg][:user_id] = args[:run][:user_id]
21
+ args[:smsg][:until_date] = (Time.now.to_i + 2678400)
22
+ args[:smsg][:can_send_messages] = 0
23
+ args[:smsg][:can_send_media_messages] = 0
24
+ args[:smsg][:can_send_other_messages] = 0
25
+ args[:smsg][:can_add_web_page_previews] = 0
26
+ Bot::BotApi.new.apiAction(args)
27
+ end
28
+
29
+ end
30
+ end
31
+ #
32
+
data/_dev/ru.yml ADDED
@@ -0,0 +1,79 @@
1
+ ru:
2
+ redmine_bots:
3
+ label:
4
+ slack: Slack
5
+ telegram: Telegram
6
+ settings:
7
+ slack_oauth_token: OAuth Access Token
8
+ slack_bot_oauth_token: Bot User OAuth Access Token
9
+ slack_client_id: Client ID
10
+ slack_client_secret: Client Secret
11
+ slack_verification_token: Verification Token
12
+ telegram:
13
+ phone_number: "Номер телефона"
14
+ phone_number_hint: "В формате: 78005553535"
15
+ phone_code: "Код телеграмма"
16
+ authorize_button_code: "Получить код авторизации"
17
+ authorize_client: "Авторизовать клиент Telegram"
18
+ authorize_hint: "Чтобы авторизировать Telegram, нажмите кнопку ниже. Текущая авторизация сбросится."
19
+ authorize_button: "Авторизовать"
20
+ plugin_link: "К настройкам плагина"
21
+ auth_step_1: "Получение кода авторизации"
22
+ auth_step_2: "Авторизация"
23
+ reset: "Сбросить кеш и авторизацию"
24
+ bot_init: Инициализировать бота
25
+ bot_deinit: Деинициализировать бота
26
+ get_updates_hint: bundle exec rake telegram_common:bot
27
+ web_hooks_warning: Нужен https протокол, чтобы настроить WebHooks
28
+ use_proxy: Использовать прокси
29
+ requirements:
30
+ title: Требования
31
+ telegram:
32
+ title: Требования
33
+ valid: ОК
34
+ description: Описание
35
+ no: Нет
36
+ yes: Да
37
+ rails_env: "Убедитесь, что ваш RAILS_ENV — production (сейчас: %{rails_env})"
38
+ redmine_host: "Убедитесь, что установлен правильный хост в настройках Redmine (сейчас: %{host})"
39
+ tdlib_installation: "Необходимо поместить libtdjson в директорию redmine_root/vendor или добавить в ldconfig. <a href='https://core.telegram.org/tdlib/docs/#building' target='_blank'>Инструкции по сборке</a>."
40
+ telegram:
41
+ bot:
42
+ start:
43
+ instruction_html: |
44
+ Чтобы связать аккаунты Redmine и Telegram, пожалуйста, введите команду /connect.
45
+ hello: Здравствуйте!
46
+ connect:
47
+ already_connected: Ваши аккаунты уже связаны
48
+ wait_for_email: Мы отправили подтверждение на адрес "%{email}". Пожалуйста, следуйте инструкциям из письма.
49
+ wrong_email: Неверный email-адрес. Пользователь с таким адресом не найден. Осталось %{attempts} попытки, после чего аккаунт будет заблокирован на час.
50
+ blocked: Ваш аккаунт заблокирован. Попробуйте через %{unblock} мин.
51
+ login_link: "Для привязки аккаунта к Redmine проследуйте по ссылке: %{link}"
52
+ group:
53
+ no_commands: "Нет команд для группового чата. В приватном чате доступны следующие команды:"
54
+ private_command: 'Данная команда обрабатывается в личных сообщениях.'
55
+ private:
56
+ group_command: 'Данная команда обрабатывается в групповых чатах.'
57
+ help:
58
+ start: "Начало работы с ботом"
59
+ connect: "Связывание аккаунтов Redmine и Telegram"
60
+ help: "Справка по командам"
61
+ token: Получить ссылку для аутентификации
62
+ login:
63
+ success: Аутентификация прошла успешно
64
+ errors:
65
+ not_logged: Вы не залогинены в Redmine
66
+ hash_invalid: Неверный Hash
67
+ hash_outdated: Истекло время ожидания
68
+ wrong_account: Неверный аккаунт Telegram
69
+ not_persisted: Не удалось сохранить данные о Telegram-аккаунте
70
+ invalid_token: Неверный token
71
+ follow_link: Пожалуйста, проследуйте по ссылке
72
+ send_to_telegram: Отправить ссылку в Telegram
73
+ widget_not_visible: если виджет недоступен
74
+ write_to_bot: "Пожалуйста, напишите команду /token боту @%{bot}, если не видно виджет"
75
+ slack:
76
+ commands:
77
+ connect: связывание аккаунтов Slack и Redmine
78
+ help: помощь по командам
79
+
data/_dev/sidekiq.rb ADDED
@@ -0,0 +1,28 @@
1
+ class TelegramHandlerWorker
2
+ include Sidekiq::Worker
3
+ sidekiq_options queue: :telegram
4
+
5
+ TYPES = %w(inline_query
6
+ chosen_inline_result
7
+ callback_query
8
+ edited_message
9
+ message
10
+ channel_post
11
+ edited_channel_post)
12
+
13
+ def perform(params)
14
+ update = Telegram::Bot::Types::Update.new(params)
15
+ message = TYPES.reduce(nil) { |m, t| m || update.public_send(t) }
16
+
17
+ if message.present?
18
+ RedmineBots::Telegram.update_manager.handle_message(message)
19
+ else
20
+ logger.fatal "Can't find message: #{params.to_json}"
21
+ end
22
+ end
23
+
24
+ def logger
25
+ @logger ||= Logger.new(Rails.root.join('log/redmine_bots',
26
+ 'telegram-handler.log'))
27
+ end
28
+ end
data/_dev/tdlib.rb ADDED
@@ -0,0 +1,154 @@
1
+ ## auth finish
2
+
3
+ when 'authorizationStateReady'
4
+ fetch_all_chats
5
+ return
6
+
7
+ def fetch_all_chats
8
+ offset_order = 2**63 - 1
9
+ offset_chat_id = 0
10
+ limit = 100
11
+
12
+ loop do
13
+ chat_ids = @client.fetch('@type' => 'getChats', 'offset_order' => offset_order, 'offset_chat_id' => offset_chat_id, 'limit' => limit).tap(&error_handler)['chat_ids']
14
+ break if chat_ids.empty?
15
+ last_chat = @client.fetch('@type' => 'getChat', 'chat_id' => chat_ids.last).tap(&error_handler)
16
+ offset_chat_id, offset_order = last_chat.values_at('id', 'order')
17
+ end
18
+ end
19
+
20
+ ## get_chat
21
+ @client.on_ready do |client|
22
+ client.fetch('@type' => 'getChat', 'chat_id' => id)
23
+
24
+ ## add_bot
25
+ @client.on_ready do |client|
26
+ chat = client.fetch('@type' => 'createPrivateChat', 'user_id' => bot_id)
27
+ client.fetch('@type' => 'sendBotStartMessage',
28
+ 'bot_user_id' => bot_id,
29
+ 'chat_id' => chat['id'])
30
+ end
31
+
32
+ ## create_chat
33
+ "chat_create_supergroup '#{chatname}' '#{args[:sess][:chatDesc]}'",
34
+ "chat_export_invite_link #{chatname}",
35
+ "chat_add_user #{chatname} @#{args[:mmsg][:username]}",
36
+ "chat_add_user #{chatname} @#{args[:globals][:botUsername]}",
37
+ "chat_change_role #{chatname} @#{args[:globals][:botUsername]} editor"
38
+
39
+ @client.on_ready(timeout: 5) do |client|
40
+ user_ids.each do |id|
41
+ client.fetch('@type' => 'getUser', 'user_id' => id)
42
+ end
43
+
44
+ sleep 1
45
+
46
+ chat = client.fetch('@type' => 'createNewBasicGroupChat',
47
+ 'title' => title,
48
+ 'user_ids' => user_ids)
49
+
50
+ sleep 1
51
+
52
+ client.fetch('@type' => 'toggleBasicGroupAdministrators',
53
+ 'basic_group_id' => chat.dig('type', 'basic_group_id'),
54
+ 'everyone_is_administrator' => false)
55
+ chat
56
+ end
57
+
58
+
59
+ ## get_user
60
+ @client.on_ready do |client|
61
+ client.fetch('@type' => 'getUser', 'user_id' => user_id)
62
+ end
63
+ end
64
+
65
+ ## rename_chat
66
+ @client.on_ready do |client|
67
+ client.fetch('@type' => 'setChatTitle',
68
+ 'chat_id' => chat_id,
69
+ 'title' => new_title)
70
+ end
71
+
72
+ ## get_chat
73
+ @client.on_ready do |client|
74
+ client.fetch('@type' => 'getChat', 'chat_id' => id)
75
+ end
76
+
77
+ ## toggle_chat_admin
78
+ status =
79
+ if admin
80
+ { '@type' => 'chatMemberStatusAdministrator',
81
+ 'can_change_info' => true,
82
+ 'can_edit_messages' => true,
83
+ 'can_delete_messages' => true,
84
+ 'can_invite_users' => true,
85
+ 'can_restrict_members' => true,
86
+ 'can_pin_messages' => true,
87
+ 'can_promote_members' => true }
88
+ else
89
+ { '@type' => 'chatMemberStatusMember' }
90
+ end
91
+ @client.on_ready do |client|
92
+ client.fetch('@type' => 'getUser', 'user_id' => user_id)
93
+ client.fetch('@type' => 'setChatMemberStatus',
94
+ 'chat_id' => chat_id,
95
+ 'user_id' => user_id,
96
+ 'status' => status)
97
+ end
98
+
99
+ ## delete_member
100
+ @client.fetch('@type' => 'setChatMemberStatus',
101
+ 'chat_id' => chat_id,
102
+ 'user_id' => user_id,
103
+ 'status' => { '@type' => 'chatMemberStatusLeft' })
104
+
105
+ ## close_chat
106
+ @client.on_ready do |client|
107
+ me = client.fetch('@type' => 'getMe')
108
+ bot_id = Setting.find_by(name: 'plugin_redmine_bots').value['telegram_bot_id'].to_i
109
+
110
+ chat = client.fetch('@type' => 'getChat', 'chat_id' => chat_id)
111
+
112
+ group_info = client.fetch('@type' => 'getBasicGroupFullInfo',
113
+ 'basic_group_id' => chat.dig('type', 'basic_group_id')
114
+ )
115
+ return if group_info['@type'] == 'error'
116
+
117
+ group_info['members'].map { |m| m['user_id'] }.each do |user_id|
118
+ delete_member(chat_id, user_id) unless user_id.in?([me['id'], bot_id])
119
+ end
120
+
121
+ delete_member(chat_id, me['id'])
122
+ delete_member(chat_id, bot_id)
123
+ end
124
+
125
+
126
+ ## get_chat_link
127
+ @client.on_ready do |client|
128
+ client.fetch('@type' => 'generateChatInviteLink', 'chat_id' => chat_id)
129
+ end
130
+
131
+
132
+ ## error handling
133
+ bot.api.send_message(message_params)
134
+ rescue BotKickedError
135
+ logger.warn("Bot was kicked from chat. Chat Id: #{chat_id}, params: #{params.inspect}")
136
+ rescue FloodError => e
137
+ logger.warn("Too many requests. Sleeping #{SLEEP_TIME} seconds...")
138
+ sleep SLEEP_TIME
139
+ (tries -= 1).zero? ? raise(e) : retry
140
+ end
141
+
142
+ SLEEP_TIME = 30
143
+
144
+ class BotKickedError
145
+ def self.===(e)
146
+ e.is_a?(Telegram::Bot::Exceptions::ResponseError) && e.message.include?('kicked')
147
+ end
148
+ end
149
+
150
+ class FloodError
151
+ def self.===(e)
152
+ e.is_a?(Telegram::Bot::Exceptions::ResponseError) && e.message.include?('Too Many Requests')
153
+ end
154
+ end