Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

magic-judge-telegram-bot.py 8.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. import logging
  2. import json
  3. import oracle
  4. from telegram.ext import Updater, CommandHandler, InlineQueryHandler, CallbackQueryHandler, MessageHandler, Filters
  5. from telegram import InlineQueryResultArticle, InputTextMessageContent, InlineKeyboardButton, InlineKeyboardMarkup
  6. #logging.basicConfig(level=logging.DEBUG,
  7. # format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
  8. crData = {}
  9. with open('data/cr.json') as file:
  10. crData = json.load(file)
  11. crDataNames = crData['glossary'].keys()
  12. crDataNumbers = crData['sections'].keys()
  13. print('Registered {} CR glossary terms and {} CR sections'.format(len(crDataNames), len(crDataNumbers)))
  14. def format_card(card):
  15. mana = ''
  16. if 'manaCost' in card:
  17. mana = '\t' + card['manaCost']
  18. text = ''
  19. if 'text' in card:
  20. text = '\n' + card['text']
  21. footer = ''
  22. if "Creature" in card['type']:
  23. footer = '\n{}/{}'.format(card['power'], card['toughness'])
  24. if "Planeswalker" in card['type'] and 'loyalty' in card:
  25. footer = '\n{}'.format(card['loyalty'])
  26. return '<b>{}</b>{}\n<i>{}</i>{}{}'.format(
  27. card['name'],
  28. mana,
  29. card['type'],
  30. text,
  31. footer)
  32. def preview_card(card):
  33. mana = ''
  34. if 'manaCost' in card:
  35. mana = '\t' + card['manaCost']
  36. return '{}{}\n{}'.format(
  37. card['name'],
  38. mana,
  39. card['type'])
  40. def start_command(bot, update):
  41. commands = [
  42. '/o <card name or search strings> - oracle text for a card',
  43. '/q <question> - oracle text for cards mentioned in the question',
  44. '/cr <section> (coming soon)',
  45. '/ipg <section> (coming soon)',
  46. '/mtr <section> (coming soon)',
  47. ]
  48. update.message.reply_text('How can I help?\n{}'.format('\n'.join(commands)), quote = False)
  49. def oracle_command(bot, update, args):
  50. if not args:
  51. update.message.reply_text('I need some clues to search for, my master!', quote=False)
  52. return
  53. words = [word.casefold() for word in args]
  54. nameCandidates = oracle.get_matching_names(words)
  55. if not nameCandidates:
  56. update.message.reply_text('I searched very thoroughly, but returned empty-handed, my master!', quote=False)
  57. return
  58. if len(nameCandidates) > 20:
  59. update.message.reply_text('I need more specific clues, my master! This would return {} names'.format(len(nameCandidates)), quote=False)
  60. return
  61. if len(nameCandidates) > 1:
  62. reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton(name, callback_data=name)] for name in nameCandidates])
  63. update.message.reply_text('Which one?', reply_markup=reply_markup, quote=False)
  64. return
  65. reply = []
  66. for name in nameCandidates:
  67. for oracleName in oracle.get_oracle_names(name):
  68. reply.append(format_card(oracle.get_card(oracleName)))
  69. update.message.reply_text('\n'.join(reply), parse_mode='HTML', quote = False)
  70. def question_command(bot, update, args):
  71. text = ' '.join(args).casefold()
  72. names = oracle.get_names_in_text(text)
  73. reply = []
  74. for name in names:
  75. reply.append('"' + name + '":\n' + '\n'.join([format_card(oracle.get_card(oracleName)) for oracleName in oracle.get_oracle_names(name)]))
  76. if reply:
  77. update.message.reply_text('\n\n'.join(reply), parse_mode='HTML', quote = False)
  78. def inline_oracle(bot, update):
  79. query = update.inline_query.query.casefold()
  80. if not query:
  81. return
  82. if len(query) < 3:
  83. return
  84. words = query.split()
  85. nameCandidates = oracle.get_matching_names(words)
  86. if not nameCandidates:
  87. return
  88. results = list()
  89. for word in nameCandidates[:3]:
  90. for oracleName in oracle.get_oracle_names(word):
  91. card = oracle.get_card(oracleName)
  92. results.append(
  93. InlineQueryResultArticle(
  94. id=card['name'],
  95. title=word,
  96. description=preview_card(card),
  97. input_message_content=InputTextMessageContent(format_card(card), parse_mode='HTML')
  98. )
  99. )
  100. bot.answerInlineQuery(update.inline_query.id, results)
  101. def callback_name(bot, update):
  102. message_id = update.callback_query.message.message_id
  103. chat_id = update.callback_query.message.chat.id
  104. name = update.callback_query.data
  105. names = oracle.get_oracle_names(name)
  106. if not names:
  107. bot.answerCallbackQuery(update.callback_query.id)
  108. return
  109. bot.editMessageText(
  110. chat_id = chat_id,
  111. message_id = message_id,
  112. parse_mode = 'HTML',
  113. text = '\n'.join([format_card(oracle.get_card(oracleName)) for oracleName in names])
  114. )
  115. bot.answerCallbackQuery(update.callback_query.id)
  116. def text(bot, update):
  117. if update.message.chat.type != 'private':
  118. return
  119. text = update.message.text
  120. if len(text) < 30:
  121. oracle_command(bot, update, text.split())
  122. else:
  123. question(bot, update, text)
  124. def comp_rules_command(bot, update, args):
  125. if not args:
  126. update.message.reply_text('I need some clues to search for, my master!', quote=False)
  127. return
  128. words = [word.casefold() for word in args]
  129. if words[0][0].isdigit():
  130. lang = 'en'
  131. if len(words) > 1 and words[1] == 'ru':
  132. lang = 'ru'
  133. results = []
  134. other = []
  135. section = words[0].casefold()
  136. pos = len(section)
  137. for name in sorted([name for name in crDataNumbers if name.startswith(section)]):
  138. diff = name[pos:].strip('.')
  139. if len(diff) < 2 and (len(diff) == 0 or diff.isalpha()):
  140. results.append(name)
  141. elif not diff[-1:].isalpha():
  142. other.append(name)
  143. if not results:
  144. update.message.reply_text('This section doesn\'t exist, my master!', quote=False)
  145. return
  146. text = '\n'.join(['<b>{}</b> {}'.format(name, crData['sections'][name][lang]) for name in results])
  147. if other:
  148. text += '\n<i>(Subsections: {}-{})</i>'.format(other[0], other[-1])
  149. if len(text) > 4000:
  150. text = '<b>{}</b> {}\n<i>(See also: {}-{})</i>'.format(results[0], crData['sections'][results[0]][lang], results[1], results[-1])
  151. update.message.reply_text(text, parse_mode='HTML', quote = False)
  152. return
  153. nameCandidates = [name for name in crDataNames if all(word in name.casefold() for word in words)]
  154. term = ' '.join(words)
  155. if len(words) > 1:
  156. goodCandidates = [name for name in nameCandidates if term in name.casefold()]
  157. if goodCandidates:
  158. nameCandidates = goodCandidates
  159. bestCandidates = [name for name in nameCandidates if name.casefold().startswith(term)]
  160. if bestCandidates:
  161. nameCandidates = bestCandidates
  162. excellentCandidate = [name for name in nameCandidates if name.casefold() == term]
  163. if excellentCandidate:
  164. nameCandidates = excellentCandidate
  165. if not nameCandidates:
  166. update.message.reply_text('I searched very thoroughly, but returned empty-handed, my master!', quote=False)
  167. return
  168. if len(nameCandidates) > 20:
  169. update.message.reply_text('I need more specific clues, my master! This would return {} names'.format(len(nameCandidates)), quote=False)
  170. return
  171. text = '\n'.join(['<b>{}</b> {}'.format(name, crData['glossary'][name]) for name in sorted(nameCandidates)])
  172. update.message.reply_text(text, parse_mode='HTML', quote = False)
  173. def ask_command(bot, update, args):
  174. pass
  175. def dispatcher_setup(dispatcher):
  176. dispatcher.add_handler(CommandHandler('start', start_command))
  177. dispatcher.add_handler(CommandHandler('help', start_command))
  178. dispatcher.add_handler(CommandHandler('o', oracle_command, pass_args=True))
  179. dispatcher.add_handler(CommandHandler('q', question_command, pass_args=True))
  180. dispatcher.add_handler(CommandHandler('cr', comp_rules_command, pass_args=True))
  181. dispatcher.add_handler(CommandHandler('ask', ask_command, pass_args=True))
  182. dispatcher.add_handler(InlineQueryHandler(inline_oracle))
  183. dispatcher.add_handler(CallbackQueryHandler(callback_name))
  184. dispatcher.add_handler(MessageHandler(Filters.text, text))
  185. with open('config.json') as file:
  186. config = json.load(file)
  187. updater = Updater(config['token'])
  188. dispatcher_setup(updater.dispatcher)
  189. updater.start_polling()
  190. updater.idle()