python

Создаем бота для Skype. Шаг за шагом, через REST API и на Python

  • понедельник, 3 апреля 2017 г. в 03:13:30
https://habrahabr.ru/post/325456/
  • Программирование
  • Python
  • API



Когда ищешь long-polling в Skype API

Год назад Microsoft представила платформу для создания ботов под Skype. Платформа предоставляет удобный формат сообщений, можно отправлять карточки с кнопками, как в телеграмме, одним словом, выглядит все очень круто.

Недавно мне потребовалось написать бота для Skype. И несмотря на то, что тема подымалась на хабре ( например), я столкнулся с некоторыми сложностями, мне очень не хватало step-by-step гайда по работе с REST API.

На самом деле, бот для скайпа пишется довольно быстро, если знать о подводных камнях и знать где смотреть документацию. Основная идея, которую мне пришлось усвоить: Нет веб поллинга. Если Телеграмм на выбор предоставляет лонг-поллинг и вебхуки, то скайп обходится только вебхуками. Из этого вытекают следующие проблемы – общение с серверами скайпа происходят только по https, и только при наличии валидного сертификата. Придется находить доменное имя, хостинг, заморачиваться с сертификатом.

Как это сделать?

Итак, с самого начала. Допустим, что у нас есть голый хостинг ( у меня это был Raspberry Pi, на котором я тестировал бота, но это может быть и сервер на амазоне, например ). Для начала, нужно получить доменное имя и сертификат на него. Бесплатные доменные имена можно получить например здесь. Далее нам нужно получить сертификат на это имя. Это легче всего сделать с помощью Let’s Encrypt. В процессе установки сертификата выбираем опцию standalone server – certbot запустит свой сервер, чтобы проверить, что именно вы владеете этим доменным именем перед тем как выдавать сертификат на него. После того, как у вас все получилось, у вас должны быть сертификаты в папке “/etc/letsencrypt/archive”.

Теперь, когда все подготовлено к работе, начнем писать бота.
1. Многое описано в этой статье, нам нужны два момента: Вот здесь создаем свое приложение, и здесь регистрируем бота. При регистрации нужно указать endpoint, куда Microsoft будет отсылать сообщения. Он указывается в таком же виде, как и пишется в браузере. После endpoint’a можно указать порт, тогда он будет выглядеть вот так: “https://endpoint_url:port” После регистрации нужно будет сгенерировать пароль, и это все, что нам нужно было получить на данный момент. На данный момент у нас должен быть: application_id ( с которым мы регистрировали бота ) и пароль ( который мы получили только что ).
2. Вы еще не забыли про вебхуки? Настала пора подымать сервер, для которого мы ранее получали сертификаты. На питоне для этого подойдет фласк. Первым делом, определим глобальные переменные ( не очень красивое решение, но очень простое ), и начнем в отдельном потоке автоматически получать и обновлять токен:
Посмотреть код
FLASK = Flask(__name__)
APP_ID = ''
PASSWORD = '' # секрет от бота
context =('fullchain.pem', 'privkey.pem') # относительные или абсолютные пути к файлам, которые сгенерировал certbot
TOKEN = {}
def get_token():
    global TOKEN
    url = 'https://login.microsoftonline.com/botframework.com/oauth2/v2.0/token'
    payload = {'grant_type': 'client_credentials',
               'client_id': APP_ID,
               'client_secret': PASSWORD,
               'scope': 'https://api.botframework.com/.default',
              }
    token = requests.post('https://login.microsoftonline.com/botframework.com/oauth2/v2.0/token', data=payload).content
    TOKEN = json.loads(str(token)[2:-1])
    return json.loads(str(token)[2:-1])
def send_token_to_connector(token):
    url = 'https://groupme.botframework.com/v3/conversations'
    headers = {'Authorization': 'Bearer ' + token}
    r = requests.post(url, headers=headers)
    return r
def get_and_verify_token():
    global TOKEN
    while True:
        get_token()
        send_token_to_connector(TOKEN['access_token'])
        time.sleep(TOKEN['expires_in']*0.9)


3. Напишем функцию-обработчик входящих сообщений:
Посмотреть код
@FLASK.route('/', methods=['GET', 'POST'])
def handle():
    data = request.get_json()
    talk_id = data['conversation']['id']
    msg = {
        "type": "message",
        "from": {
                "id": APP_ID,
                "name": "habraechobot"
            },
        "conversation": {
            "id": talk_id,
        },
        "text": data['text'],
    }
    url = data['serviceUrl'] + '/v3/conversations/{}/activities/'.format(data['conversation']['id'])
    headers = {'Authorization': 'Bearer ' + TOKEN['access_token'],
               'content-type': 'application/json; charset=utf8'}
    r = requests.post(url, headers=headers, data=json.dumps(msg))
    return 'success'


4. И, наконец, запустим сервер:
Посмотреть код
if __name__ == '__main__':
    thread = Thread( target=get_and_verify_token )
    thread.start()
    FLASK.run(host='0.0.0.0', port=8080, ssl_context=context)


Вот и все – полный код бота можно взять отсюда, надеюсь, моя статья была полезна и сэкономит кому-то время и силы.