Parcourir la source

First version of bot

Taddeus Kroes il y a 9 ans
commit
cc8c0e4f32
5 fichiers modifiés avec 180 ajouts et 0 suppressions
  1. 3 0
      .gitignore
  2. 2 0
      README.md
  3. 104 0
      bot.py
  4. 12 0
      talk.py
  5. 59 0
      translate.py

+ 3 - 0
.gitignore

@@ -0,0 +1,3 @@
+config.py
+*.pyc
+*.swp

+ 2 - 0
README.md

@@ -0,0 +1,2 @@
+A simple telegram bot that translates text into R2D2 sound using
+http://www.r2d2translator.com/.

+ 104 - 0
bot.py

@@ -0,0 +1,104 @@
+#!/usr/bin/env python
+import os
+import logging
+from tempfile import mkstemp
+from telegram.ext import Updater, CommandHandler, MessageHandler, Filters, \
+        InlineQueryHandler
+from telegram import InlineQueryResultVoice, InlineQueryResultAudio
+from telegram.ext.dispatcher import run_async
+from translate import get_audio_url, get_audio
+from config import token
+
+
+logging.basicConfig(
+        format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
+        level=logging.INFO)
+logger = logging.getLogger(__name__)
+
+
+@run_async
+def onstart(bot, update):
+    logger.info('start command from %s' % update.message.from_user.first_name)
+    bot.send_message(chat_id=update.message.chat_id, text='Hello! I\'m R2D2.')
+    onhelp(bot, update)
+
+
+@run_async
+def onhelp(bot, update):
+    logger.info('help command from %s' % update.message.from_user.first_name)
+    bot.send_message(chat_id=update.message.chat_id, text='''
+Type "@artoobot <message>" to get inline voice.
+Commands:
+/help Show this help message.
+/say <message> Reply with a translated message (use to get voice next to \
+original text.)
+'''.strip())
+
+
+def reply_audio(bot, chat_id, text, reply_id):
+    fd, path = mkstemp()
+    f = os.fdopen(fd, 'w+b')
+    f.write(get_audio(text))
+    f.flush()
+    f.seek(0)
+    bot.send_voice(chat_id=chat_id, voice=f, reply_to_message_id=reply_id)
+    f.close()
+    os.unlink(path)
+
+
+@run_async
+def onsay(bot, update, args):
+    m = update.message
+    text = ' '.join(args)
+    logger.info('say command from %s: %s' % (m.from_user.first_name, text))
+    reply_audio(bot, m.chat_id, text, m.message_id)
+
+
+@run_async
+def onmessage(bot, update, reply=False):
+    m = update.message
+    logger.info('message from %s: %s' % (m.from_user.first_name, m.text))
+    reply_audio(bot, m.chat_id, m.text, None)
+
+
+@run_async
+def oninline(bot, update):
+    q = update.inline_query.query
+    logger.info('inline query from %s: %s' %
+                update.message.from_user.first_name, q)
+    if not q:
+        return
+    url = get_audio_url(q)
+    results = [
+        InlineQueryResultAudio(id='audio_%s' % q, audio_url=url,
+                               title='Audio (download button, shows text)'),
+        InlineQueryResultVoice(id='voice_%s' % q, voice_url=url,
+                               title='Voice (play button, no text)')
+    ]
+    bot.answer_inline_query(update.inline_query.id, results)
+
+
+@run_async
+def onunknown(bot, update):
+    logger.info('unknown command from %s' %
+                update.message.from_user.first_name)
+    bot.send_message(chat_id=update.message.chat_id,
+                     text='Sorry, I didn\'t understand that command.')
+
+
+def onerror(bot, update, error):
+    logger.warn('Update "%s" caused error "%s"' % (update, error))
+
+
+if __name__ == '__main__':
+    updater = Updater(token=token)
+    dp = updater.dispatcher
+    dp.add_handler(CommandHandler('start', onstart))
+    dp.add_handler(CommandHandler('help', onhelp))
+    dp.add_handler(CommandHandler('say', onsay, pass_args=True))
+    dp.add_handler(InlineQueryHandler(oninline))
+    dp.add_handler(MessageHandler([Filters.command], onunknown))
+    dp.add_handler(MessageHandler([Filters.text], onmessage))
+    dp.add_error_handler(onerror)
+    updater.start_polling()
+    updater.idle()

+ 12 - 0
talk.py

@@ -0,0 +1,12 @@
+#!/usr/bin/env python
+import sys
+from translate import request_audio, read_request
+
+
+if __name__ == '__main__':
+    if len(sys.argv) < 2:
+        print >>sys.stderr, 'Usage: python %s MESSAGE' % sys.argv[0]
+        sys.exit(1)
+
+    message = ' '.join(sys.argv[1:])
+    sys.stdout.write(read_request(request_audio(message)))

+ 59 - 0
translate.py

@@ -0,0 +1,59 @@
+import requests
+
+
+translate_url = 'http://www.r2d2translator.com/composeSongD2R2.php'
+file_url = 'http://www.r2d2translator.com/audio/%s.MP3'
+
+
+class ReqError(RuntimeError):
+    pass
+
+
+def encode(msg):
+    e = ''
+    for i, c in enumerate(msg):
+        if i:
+            e += '!'
+        if c == ' ':
+            e += 'silence'
+        else:
+            e += str(1 + (ord(c) + 60) % 80)
+    return e
+
+
+def get_audio_url(msg):
+    enc = encode(msg)
+    vol = '!'.join('1' * len(enc))
+    req = requests.post(translate_url, data={'volumes': vol, 'sons': enc})
+    if req.status_code != 200:
+        raise ReqError()
+    res = req.text
+    if not res.startswith(' &cle='):
+        raise ReqError()
+    fileid = res[6:]
+    return file_url % fileid
+
+
+def request_audio(msg):
+    req = requests.get(get_audio_url(msg), stream=True)
+    if req.status_code != 200:
+        raise ReqError()
+    return req
+
+
+def read_request(req):
+    return req.raw.read(decode_content=False)
+
+
+def save_request(req, path):
+    with file(path, 'wb') as f:
+        for chunk in req.iter_content(1024):
+            f.write(chunk)
+
+
+def get_audio(msg):
+    return read_request(request_audio(msg))
+
+
+def save_audio(msg, path):
+    save_request(request_audio(msg), path)