• A class is a body of code that defines the attributes (properties) and behaviors (methods) required to accurately model something you need for your program.
  • __init__ is a reseved method in python classes known as a constructor.
  • If a class method name starts with (but doesn’t end with) two underscores __, it’s private.

Read More

We will create a new models package which contains chat module. The app will have below structure

app/
    __init__.py/
    handlers/
        __init__.py/
        base.py/
        bot.py/
    models/
        __init__.py/
        chat.py/
static/
    images/
        favicon.ico/
app.yaml/
main.py/

chat.py

import logging
import urllib
import urllib2

TOKEN = 'xxxxxx:YOUR_TELEGRAM_BOT_TOKEN'
BASE_URL = 'https://api.telegram.org/bot' + TOKEN


class Handler(object):
    def __init__(self, body):
        self.body = body

    def __get_message(self):
        if self.body:
            if 'message' in self.body:
                message = self.body['message']
            elif 'edited_message' in self.body:
                message = self.body['edited_message']
            return message
        return None

    def __get_default_reply(self, message=None):
        global reply_method
        reply_method = 'sendMessage'
        message_id = message['message_id']
        chat_id = message['chat']['id']
        msg = 'I understand only text and sticker messages'
        return urllib.urlencode({
            'chat_id': str(chat_id),
            'text': msg.encode('utf-8'),
            'reply_to_message_id': str(message_id),
        })

    def __get_text_reply(self, message=None):
        global reply_method
        reply_method = 'sendMessage'
        message_id = message['message_id']
        chat_id = message['chat']['id']
        first_name = message['from']['first_name']
        msg = 'Yo {} I got your message'.format(first_name)
        return urllib.urlencode({
            'chat_id': str(chat_id),
            'text': msg.encode('utf-8'),
            'reply_to_message_id': str(message_id),
        })

    def __get_sticker_reply(self, message=None):
        global reply_method
        reply_method = 'sendSticker'
        chat_id = message['chat']['id']
        file_id = message['sticker']['file_id']
        return urllib.urlencode({
            'chat_id': str(chat_id),
            'sticker': file_id.encode('utf-8'),
        })

    def __get_reply(self):
        message = self.__get_message()
        if message:
            if 'sticker' in message:
                return self.__get_sticker_reply(message)
            elif 'text' in message:
                return self.__get_text_reply(message)
            else:
                return self.__get_default_reply(message)
        return None

    def send_reply(self):
        global reply_method
        data = self.__get_reply()
        if data:
            requestUrl = '{}/{}'.format(BASE_URL, reply_method)
            resp = urllib2.urlopen(requestUrl, data).read()
            logging.info('Reply is sent with response: {0}'.format(resp))
        else:
            logging.info('Send reply fail')
            resp = None

Update bot.py

import webapp2
import urllib
import urllib2
import json
import logging

from google.appengine.api import urlfetch

import app.models.chat as chat

TOKEN = 'xxxxxx:YOUR_TELEGRAM_BOT_TOKEN'
BASE_URL = 'https://api.telegram.org/bot' + TOKEN


class SetWebhookHandler(webapp2.RequestHandler):
    def get(self):
        urlfetch.set_default_fetch_deadline(60)
        url = self.request.get('url')
        if url:
            requestUrl = '{}/{}'.format(BASE_URL, 'setWebhook')
            requestParam = urllib.urlencode({'url': url})
            response = urllib2.urlopen(requestUrl, requestParam)
            self.response.write(json.dumps(json.load(response)))
        else:
            self.response.write('Invalid webhook URL: {}<br>'.format(url))


class GetWebhookHandler(webapp2.RequestHandler):
    def get(self):
        urlfetch.set_default_fetch_deadline(60)
        requestUrl = '{}/{}'.format(BASE_URL, 'getWebhookInfo')
        response = urllib2.urlopen(requestUrl)
        self.response.write(json.dumps(json.load(response)))


class WebhookHandler(webapp2.RequestHandler):
    def post(self):
        urlfetch.set_default_fetch_deadline(60)
        body = json.loads(self.request.body)
        if body:
            logging.info('Update body: {}'.format(body))
            chat_handler = chat.Handler(body)
            chat_handler.send_reply()
        else:
            logging.info('Telegram update body is Invalid')