Add webhook examples

This commit is contained in:
Sergio Conde Gómez 2015-10-06 12:06:23 +02:00
parent 117c5a1141
commit d6552eb4c6
4 changed files with 304 additions and 0 deletions

View File

@ -0,0 +1,36 @@
# Webhook examples using pyTelegramBotAPI
There are 3 examples in this directory using different libraries:
* **Python (CPython):** *webhook_cpython_echo_bot.py*
* **Pros:**
* Official python libraries, it works out of the box (doesn't require to
install anything).
* Works with Python 2 and Python 3 (need to be converted with 2to3).
* **Cons:**
* Ugly code.
* Many things to handle yourself, this can lead to errors.
* Not powerful, do the trick but the performance is low.
* **CherryPy (3.8.0):** *webhook_cherrypy_echo_bot.py*
* **Pros:**
* It's a web application framework, cleaner code, uses objects for defining
the web application.
* Very good performance.
* The project seems to be active, latest version is recent.
* Works with Python 2 and Python 3.
* **Cons:**
* Some things are not very intuitive, reading the doc is a must.
* **Flask (0.10.1):** *webhook_flask_echo_bot.py*
* **Pros:**
* It's a web application framework, cleaner code, uses decorator which can
be nice.
* Good performance.
* It's intuitive if you know how web application works.
* **Cons:**
* The project seems not to be very active, latest version dates 2013.
* They don't recommend to use it with Python 3, but may work.
* May be a oversized for just handling webhook petitions.
*Latest update of this document: 2015-10-06*

View File

@ -0,0 +1,85 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# This is a simple echo bot using decorators and webhook with CherryPy
# It echoes any incoming text messages and does not use the polling method.
import cherrypy
import telebot
import logging
API_TOKEN = '<api_token>'
WEBHOOK_HOST = '<ip/host where the bot is running>'
WEBHOOK_PORT = 8443 # 443, 80, 88 or 8443 (port need to be 'open')
WEBHOOK_LISTEN = '0.0.0.0' # In some VPS you may need to put here the IP addr
WEBHOOK_SSL_CERT = './webhook_cert.pem' # Path to the ssl certificate
WEBHOOK_SSL_PRIV = './webhook_pkey.pem' # Path to the ssl private key
# Quick'n'dirty SSL certificate generation:
#
# openssl genrsa -out webhook_pkey.pem 2048
# openssl req -new -x509 -days 3650 -key webhook_pkey.pem -out webhook_cert.pem
#
# When asked for "Common Name (e.g. server FQDN or YOUR name)" you should reply
# with the same value in you put in WEBHOOK_HOST
WEBHOOK_URL_BASE = "https://%s:%s" % (WEBHOOK_HOST, WEBHOOK_PORT)
WEBHOOK_URL_PATH = "/%s/" % (API_TOKEN)
logger = telebot.logger
telebot.logger.setLevel(logging.INFO)
bot = telebot.TeleBot(API_TOKEN)
# WebhookServer, process webhook calls
class WebhookServer(object):
@cherrypy.expose
def index(self):
if 'content-length' in cherrypy.request.headers and \
'content-type' in cherrypy.request.headers and \
cherrypy.request.headers['content-type'] == 'application/json':
length = int(cherrypy.request.headers['content-length'])
json_string = cherrypy.request.body.read(length)
update = telebot.types.Update.de_json(json_string)
bot.process_new_messages([update.message])
return ''
else:
raise cherrypy.HTTPError(403)
# Handle '/start' and '/help'
@bot.message_handler(commands=['help', 'start'])
def send_welcome(message):
bot.reply_to(message,
("Hi there, I am EchoBot.\n"
"I am here to echo your kind words back to you."))
# Handle all other messages
@bot.message_handler(func=lambda message: True, content_types=['text'])
def echo_message(message):
bot.reply_to(message, message.text)
# Remove webhook, it fails sometimes the set if there is a previous webhook
bot.remove_webhook()
# Set webhook
bot.set_webhook(url=WEBHOOK_URL_BASE+WEBHOOK_URL_PATH,
certificate=open(WEBHOOK_SSL_CERT, 'r'))
# Start cherrypy server
cherrypy.config.update({
'server.socket_host': WEBHOOK_LISTEN,
'server.socket_port': WEBHOOK_PORT,
'server.ssl_module': 'builtin',
'server.ssl_certificate': WEBHOOK_SSL_CERT,
'server.ssl_private_key': WEBHOOK_SSL_PRIV
})
cherrypy.quickstart(WebhookServer(), WEBHOOK_URL_PATH, {'/': {}})

View File

@ -0,0 +1,99 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# This is a simple echo bot using decorators and webhook with BaseHTTPServer
# It echoes any incoming text messages and does not use the polling method.
import BaseHTTPServer
import ssl
import telebot
import logging
API_TOKEN = '<api_token>'
WEBHOOK_HOST = '<ip/host where the bot is running>'
WEBHOOK_PORT = 8443 # 443, 80, 88 or 8443 (port need to be 'open')
WEBHOOK_LISTEN = '0.0.0.0' # In some VPS you may need to put here the IP addr
WEBHOOK_SSL_CERT = './webhook_cert.pem' # Path to the ssl certificate
WEBHOOK_SSL_PRIV = './webhook_pkey.pem' # Path to the ssl private key
# Quick'n'dirty SSL certificate generation:
#
# openssl genrsa -out webhook_pkey.pem 2048
# openssl req -new -x509 -days 3650 -key webhook_pkey.pem -out webhook_cert.pem
#
# When asked for "Common Name (e.g. server FQDN or YOUR name)" you should reply
# with the same value in you put in WEBHOOK_HOST
WEBHOOK_URL_BASE = "https://%s:%s" % (WEBHOOK_HOST, WEBHOOK_PORT)
WEBHOOK_URL_PATH = "/%s/" % (API_TOKEN)
logger = telebot.logger
telebot.logger.setLevel(logging.INFO)
bot = telebot.TeleBot(API_TOKEN)
# WebhookHandler, process webhook calls
class WebhookHandler(BaseHTTPServer.BaseHTTPRequestHandler):
server_version = "WebhookHandler/1.0"
def do_HEAD(self):
self.send_response(200)
self.end_headers()
def do_GET(self):
self.send_response(200)
self.end_headers()
def do_POST(self):
if self.path == WEBHOOK_URL_PATH and \
'content-type' in self.headers and \
'content-length' in self.headers and \
self.headers['content-type'] == 'application/json':
json_string = self.rfile.read(int(self.headers['content-length']))
self.send_response(200)
self.end_headers()
update = telebot.types.Update.de_json(json_string)
bot.process_new_messages([update.message])
else:
self.send_error(403)
self.end_headers()
# Handle '/start' and '/help'
@bot.message_handler(commands=['help', 'start'])
def send_welcome(message):
bot.reply_to(message,
("Hi there, I am EchoBot.\n"
"I am here to echo your kind words back to you."))
# Handle all other messages
@bot.message_handler(func=lambda message: True, content_types=['text'])
def echo_message(message):
bot.reply_to(message, message.text)
# Remove webhook, it fails sometimes the set if there is a previous webhook
bot.remove_webhook()
# Set webhook
bot.set_webhook(url=WEBHOOK_URL_BASE+WEBHOOK_URL_PATH,
certificate=open(WEBHOOK_SSL_CERT, 'r'))
# Start server
httpd = BaseHTTPServer.HTTPServer((WEBHOOK_LISTEN, WEBHOOK_PORT),
WebhookHandler)
httpd.socket = ssl.wrap_socket(httpd.socket,
certfile=WEBHOOK_SSL_CERT,
keyfile=WEBHOOK_SSL_PRIV,
server_side=True)
httpd.serve_forever()

View File

@ -0,0 +1,84 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# This is a simple echo bot using decorators and webhook with flask
# It echoes any incoming text messages and does not use the polling method.
import flask
import telebot
import logging
API_TOKEN = '<api_token>'
WEBHOOK_HOST = '<ip/host where the bot is running>'
WEBHOOK_PORT = 8443 # 443, 80, 88 or 8443 (port need to be 'open')
WEBHOOK_LISTEN = '0.0.0.0' # In some VPS you may need to put here the IP addr
WEBHOOK_SSL_CERT = './webhook_cert.pem' # Path to the ssl certificate
WEBHOOK_SSL_PRIV = './webhook_pkey.pem' # Path to the ssl private key
# Quick'n'dirty SSL certificate generation:
#
# openssl genrsa -out webhook_pkey.pem 2048
# openssl req -new -x509 -days 3650 -key webhook_pkey.pem -out webhook_cert.pem
#
# When asked for "Common Name (e.g. server FQDN or YOUR name)" you should reply
# with the same value in you put in WEBHOOK_HOST
WEBHOOK_URL_BASE = "https://%s:%s" % (WEBHOOK_HOST, WEBHOOK_PORT)
WEBHOOK_URL_PATH = "/%s/" % (API_TOKEN)
logger = telebot.logger
telebot.logger.setLevel(logging.INFO)
bot = telebot.TeleBot(API_TOKEN)
app = flask.Flask(__name__)
# Empty webserver index, return nothing, just http 200
@app.route('/', methods=['GET', 'HEAD'])
def index():
return ''
# Process webhook calls
@app.route(WEBHOOK_URL_PATH, methods=['POST'])
def webhook():
if flask.request.headers.get('content-type') == 'application/json':
json_string = flask.request.get_data()
update = telebot.types.Update.de_json(json_string)
bot.process_new_messages([update.message])
return ''
else:
flask.abort(403)
# Handle '/start' and '/help'
@bot.message_handler(commands=['help', 'start'])
def send_welcome(message):
bot.reply_to(message,
("Hi there, I am EchoBot.\n"
"I am here to echo your kind words back to you."))
# Handle all other messages
@bot.message_handler(func=lambda message: True, content_types=['text'])
def echo_message(message):
bot.reply_to(message, message.text)
# Remove webhook, it fails sometimes the set if there is a previous webhook
bot.remove_webhook()
# Set webhook
bot.set_webhook(url=WEBHOOK_URL_BASE+WEBHOOK_URL_PATH,
certificate=open(WEBHOOK_SSL_CERT, 'r'))
# Start flask server
app.run(host=WEBHOOK_LISTEN,
port=WEBHOOK_PORT,
ssl_context=(WEBHOOK_SSL_CERT, WEBHOOK_SSL_PRIV),
debug=True)