Skip to content

Commit

Permalink
Version 1.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
JungDev committed May 25, 2017
1 parent 3bae40d commit c840cee
Show file tree
Hide file tree
Showing 15 changed files with 276 additions and 86 deletions.
11 changes: 10 additions & 1 deletion HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,18 @@
History
-------
1.0.0 (2017-05-25)
++++++++++++++++++
* IMPORTANT: If you upgrade from a previous version, you MUST change how to include django_telegrambot.urls and settings.py.
* Added admin dashboard, available at /admin/django-telegrambot
* Added polling mode from management command (an easy to way to run bot in local machine, not recommended in production)
* More setting available
* Improved AppConfig
* Improved sample project

0.2.6 (2017-04-08)
++++++++++++++++++
* Improve module loading
* Improved module loading
* Added sample project

0.2.5 (2017-03-06)
Expand Down
73 changes: 65 additions & 8 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,75 @@ And set your bots::

#settings.py
#Django Telegram Bot settings
TELEGRAM_BOT_TOKENS = ('BOT_1_token','BOT_2_token',)
TELEGRAM_WEBHOOK_SITE = 'https://mysite.it'
TELEGRAM_WEBHOOK_BASE = '/baseurl'
#TELEGRAM_WEBHOOK_CERTIFICATE = 'cert.pem' #If your site use self-signed certificate, must be set with location of your public key certificate. (More info at https://core.telegram.org/bots/self-signed )

DJANGO_TELEGRAMBOT = {

Include in your urls.py the ``django_telegrambot.urls`` using the same value of ``TELEGRAM_WEBHOOK_BASE`` ::
'MODE' : 'WEBHOOK', #(Optional [str]) # The default value is WEBHOOK,
# otherwise you may use 'POLLING'
# NB: if use polling you must provide to run
# a management command that starts a worker

'WEBHOOK_SITE' : 'https://mywebsite.com',
'WEBHOOK_PREFIX' : '/prefix', # (Optional[str]) # If this value is specified,
# a prefix is added to webhook url

#'WEBHOOK_CERTIFICATE' : 'cert.pem', # If your site use self-signed
#certificate, must be set with location of your public key
#certificate.(More info at https://core.telegram.org/bots/self-signed )

'BOTS' : [
{
'TOKEN': '123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11', #Your bot token.

#'ALLOWED_UPDATES':(Optional[list[str]]), # List the types of
#updates you want your bot to receive. For example, specify
#``["message", "edited_channel_post", "callback_query"]`` to
#only receive updates of these types. See ``telegram.Update``
#for a complete list of available update types.
#Specify an empty list to receive all updates regardless of type
#(default). If not specified, the previous setting will be used.
#Please note that this parameter doesn't affect updates created
#before the call to the setWebhook, so unwanted updates may be
#received for a short period of time.

#'TIMEOUT':(Optional[int|float]), # If this value is specified,
#use it as the read timeout from the server

#'WEBHOOK_MAX_CONNECTIONS':(Optional[int]), # Maximum allowed number of
#simultaneous HTTPS connections to the webhook for update
#delivery, 1-100. Defaults to 40. Use lower values to limit the
#load on your bot's server, and higher values to increase your
#bot's throughput.

#'POLL_INTERVAL' : (Optional[float]), # Time to wait between polling updates from Telegram in
#seconds. Default is 0.0

#'POLL_CLEAN':(Optional[bool]), # Whether to clean any pending updates on Telegram servers before
#actually starting to poll. Default is False.

#'POLL_BOOTSTRAP_RETRIES':(Optional[int]), # Whether the bootstrapping phase of the `Updater`
#will retry on failures on the Telegram server.
#| < 0 - retry indefinitely
#| 0 - no retries (default)
#| > 0 - retry up to X times

#'POLL_READ_LATENCY':(Optional[float|int]), # Grace time in seconds for receiving the reply from
#server. Will be added to the `timeout` value and used as the read timeout from
#server (Default: 2).
},
#Other bots here with same structure.
],

}



Include in your urls.py the ``django_telegrambot.urls`` (NB: If you upgrade from a previous version, you MUST change how to include ``django_telegrambot.urls``. Never set prefix here!)::

#urls.py
urlpatterns = [
...
url(r'^baseurl/', include('django_telegrambot.urls')),
url(r'^', include('django_telegrambot.urls')),
...
]

Expand Down Expand Up @@ -85,7 +142,7 @@ Then use it in a project creating a module ``telegrambot.py`` in your app ::
def main():
logger.info("Loading handlers for telegram bot")

# Default dispatcher (this is related to the first bot in settings.TELEGRAM_BOT_TOKENS)
# Default dispatcher (this is related to the first bot in settings.DJANGO_TELEGRAMBOT['BOTS'])
dp = DjangoTelegramBot.dispatcher
# To get Dispatcher related to a specific bot
# dp = DjangoTelegramBot.getDispatcher('BOT_n_token') #get by bot token
Expand Down Expand Up @@ -148,7 +205,7 @@ There a sample application in `sampleproject` directory. Here is installation in
5. To test webhook locally install `ngrok` application and run command

./ngrok http 8000
And change TELEGRAM_WEBHOOK_SITE and ALLOWED_HOSTS in local_settings.py file
6. Change `WEBHOOK_SITE` and `ALLOWED_HOSTS` in local_settings.py file

Credits
---------
Expand Down
2 changes: 1 addition & 1 deletion django_telegrambot/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
__version__ = '0.2.7'
__version__ = '1.0.0'
default_app_config = 'django_telegrambot.apps.DjangoTelegramBot'
67 changes: 30 additions & 37 deletions django_telegrambot/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ class DjangoTelegramBot(AppConfig):
name = 'django_telegrambot'
verbose_name = 'Django TelegramBot'
ready_run = False
#_dispatcher = None
#_updater = None
bot_tokens = []
bot_usernames = []
dispatchers = []
Expand Down Expand Up @@ -127,57 +125,55 @@ def ready(self):
DjangoTelegramBot.ready_run = True

self.mode = WEBHOOK_MODE
if hasattr(settings, 'TELEGRAM_BOT_MODE'):
if settings.TELEGRAM_BOT_MODE == 'POLLING':
self.mode = POLLING_MODE
if settings.DJANGO_TELEGRAMBOT.get('MODE', 'WEBHOOK') == 'POLLING':
self.mode = POLLING_MODE

modes = ['WEBHOOK','POLLING']
logger.info('Django Telegram Bot <{} mode>'.format(modes[self.mode]))

if not hasattr(settings, 'TELEGRAM_BOT_TOKENS'):
logger.warn('Required TELEGRAM_BOT_TOKENS missing in settings')
return
tokens = settings.TELEGRAM_BOT_TOKENS
bots_list = settings.DJANGO_TELEGRAMBOT.get('BOTS', [])

if self.mode == WEBHOOK_MODE:
if not hasattr(settings, 'TELEGRAM_WEBHOOK_SITE'):
webhook_site = settings.DJANGO_TELEGRAMBOT.get('WEBHOOK_SITE', None)
if not webhook_site:
logger.warn('Required TELEGRAM_WEBHOOK_SITE missing in settings')
return
webhook_site = settings.TELEGRAM_WEBHOOK_SITE
if webhook_site.endswith("/"):
webhook_site = webhook_site[:-1]

webhook_base = ""
if hasattr(settings, 'TELEGRAM_WEBHOOK_BASE'):
logger.warn('Required TELEGRAM_WEBHOOK_BASE missing in settings')
webhook_base = settings.TELEGRAM_WEBHOOK_BASE
webhook_base = settings.DJANGO_TELEGRAMBOT.get('WEBHOOK_PREFIX','/')
if webhook_base.startswith("/"):
webhook_base = webhook_base[1:]
if webhook_base.endswith("/"):
webhook_base = webhook_base[:-1]

cert = settings.DJANGO_TELEGRAMBOT.get('WEBHOOK_CERTIFICATE', None)
certificate = None
if hasattr(settings, 'TELEGRAM_WEBHOOK_CERTIFICATE'):
cert = settings.TELEGRAM_WEBHOOK_CERTIFICATE
if os.path.exists(cert):
logger.info('TELEGRAM_WEBHOOK_CERTIFICATE found in {}'.format(cert))
certificate=open(cert, 'rb')
else:
logger.error('TELEGRAM_WEBHOOK_CERTIFICATE not found in {} '.format(cert))
if cert and os.path.exists(cert):
logger.info('WEBHOOK_CERTIFICATE found in {}'.format(cert))
certificate=open(cert, 'rb')
elif cert:
logger.error('WEBHOOK_CERTIFICATE not found in {} '.format(cert))

timeout = None
if hasattr(settings, 'TELEGRAM_WEBHOOK_TIMEOUT'):
timeout = settings.TELEGRAM_WEBHOOK_TIMEOUT
for b in bots_list:
token = b.get('TOKEN', None)
if not token:
break

max_connections = 40
if hasattr(settings, 'TELEGRAM_WEBHOOK_MAX_CONNECTIONS'):
max_connections = settings.TELEGRAM_WEBHOOK_MAX_CONNECTIONS
allowed_updates = b.get('ALLOWED_UPDATES', None)
timeout = b.get('TIMEOUT', None)

allowed_updates = None
if hasattr(settings, 'TELEGRAM_WEBHOOK_ALLOWED_UPDATES'):
allowed_updates = settings.TELEGRAM_WEBHOOK_ALLOWED_UPDATES

for token in tokens:
if self.mode == WEBHOOK_MODE:
bot = telegram.Bot(token=token)
DjangoTelegramBot.dispatchers.append(Dispatcher(bot, None, workers=0))
hookurl = '{}{}/{}/'.format(webhook_site, webhook_base, token)
hookurl = '{}/{}/{}/'.format(webhook_site, webhook_base, token)

max_connections = b.get('WEBHOOK_MAX_CONNECTIONS', 40)

setted = bot.setWebhook(hookurl, certificate=certificate, timeout=timeout, max_connections=max_connections, allowed_updates=allowed_updates)
webhook_info = bot.getWebhookInfo()
real_allowed = webhook_info.allowed_updates if webhook_info.allowed_updates else ["ALL"]

bot.more_info = webhook_info
logger.info('Telegram Bot <{}> setting webhook [ {} ] max connections:{} allowed updates:{} pending updates:{} : {}'.format(bot.username, webhook_info.url, webhook_info.max_connections, real_allowed, webhook_info.pending_update_count, setted))
else:
Expand Down Expand Up @@ -224,6 +220,3 @@ def module_exists(module_name, method_name, execute):
updater = DjangoTelegramBot.get_updater(bot_id=token)
logger.info('python manage.py botpolling --username={}'.format(updater.bot.username))




32 changes: 26 additions & 6 deletions django_telegrambot/management/commands/botpolling.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ def get_updater(self, username=None, token=None):

def handle(self, *args, **options):
from django.conf import settings
if not settings.TELEGRAM_BOT_MODE == 'POLLING':
self.stderr.write("Webhook mode active, change it in your settings if you want use polling update")
if settings.DJANGO_TELEGRAMBOT.get('MODE', 'WEBHOOK') == 'WEBHOOK':
self.stderr.write("Webhook mode active in settings.py, change in POLLING if you want use polling update")
return

updater = self.get_updater(username=options.get('username'), token=options.get('token'))
Expand All @@ -48,10 +48,30 @@ def handle(self, *args, **options):
console.setFormatter(logging.Formatter('%(name)s - %(levelname)s - %(message)s'))
logger.addHandler(console)

#wbinfo = updater.bot.getWebhookInfo()
#logger.warn(wbinfo)
#updater.bot.deleteWebhook() #not yet present in python-telegram-bot 5.3.1

bots_list = settings.DJANGO_TELEGRAMBOT.get('BOTS', [])
b = None
for bot_set in bots_list:
if bot_set.get('TOKEN', None) == updater.bot.token:
b = bot_set
break
if not b:
self.stderr.write("Cannot find bot settings")
return

allowed_updates = b.get('ALLOWED_UPDATES', None)
timeout = b.get('TIMEOUT', 10)
poll_interval = b.get('POLL_INTERVAL', 0.0)
clean = b.get('POLL_CLEAN', False)
bootstrap_retries = b.get('POLL_BOOTSTRAP_RETRIES', 0)
read_latency = b.get('POLL_READ_LATENCY', 2.)

self.stdout.write("Run polling...")
updater.start_polling()
updater.start_polling(poll_interval=poll_interval,
timeout=timeout,
clean=clean,
bootstrap_retries=bootstrap_retries,
read_latency=read_latency,
allowed_updates=allowed_updates)
self.stdout.write("the bot is started and runs until we press Ctrl-C on the command line.")
updater.idle()
2 changes: 1 addition & 1 deletion django_telegrambot/models.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
from django.db import models

# Create your models here.
# Create your models here.
13 changes: 5 additions & 8 deletions django_telegrambot/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,11 @@
from . import views
from django.conf import settings

if hasattr(settings, 'TELEGRAM_WEBHOOK_BASE'):
webhook_base = settings.TELEGRAM_WEBHOOK_BASE
if webhook_base.startswith("/"):
webhook_base = webhook_base[1:]
if not webhook_base.endswith("/"):
webhook_base += "/"
else:
webhook_base = ""
webhook_base = settings.DJANGO_TELEGRAMBOT.get('WEBHOOK_PREFIX','/')
if webhook_base.startswith("/"):
webhook_base = webhook_base[1:]
if not webhook_base.endswith("/"):
webhook_base += "/"

urlpatterns = [
url(r'admin/django-telegrambot/$', views.home, name='django-telegrambot'),
Expand Down
2 changes: 1 addition & 1 deletion django_telegrambot/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
@staff_member_required
def home(request):
bot_list = DjangoTelegramBot.bots
context = {'bot_list': bot_list, 'update_mode':settings.TELEGRAM_BOT_MODE}
context = {'bot_list': bot_list, 'update_mode':settings.DJANGO_TELEGRAMBOT.get('MODE', 'WEBHOOK')}
return render(request, 'django_telegrambot/index.html', context)


Expand Down
51 changes: 49 additions & 2 deletions docs/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,53 @@
Usage
========

To use django-telegrambot in a project::
To use django-telegrambot in a app, create a telegrambot.py module in your app as follow::

# Example code for telegrambot.py module
from telegram.ext import CommandHandler, MessageHandler, Filters
from django_telegrambot.apps import DjangoTelegramBot

import logging
logger = logging.getLogger(__name__)


# Define a few command handlers. These usually take the two arguments bot and
# update. Error handlers also receive the raised TelegramError object in error.
def start(bot, update):
bot.sendMessage(update.message.chat_id, text='Hi!')


def help(bot, update):
bot.sendMessage(update.message.chat_id, text='Help!')


def echo(bot, update):
bot.sendMessage(update.message.chat_id, text=update.message.text)


def error(bot, update, error):
logger.warn('Update "%s" caused error "%s"' % (update, error))


def main():
logger.info("Loading handlers for telegram bot")

# Default dispatcher (this is related to the first bot in settings.DJANGO_TELEGRAMBOT['BOTS'])
dp = DjangoTelegramBot.dispatcher
# To get Dispatcher related to a specific bot
# dp = DjangoTelegramBot.getDispatcher('BOT_n_token') #get by bot token
# dp = DjangoTelegramBot.getDispatcher('BOT_n_username') #get by bot username

# on different commands - answer in Telegram
dp.add_handler(CommandHandler("start", start))
dp.add_handler(CommandHandler("help", help))

# on noncommand i.e message - echo the message on Telegram
dp.add_handler(MessageHandler([Filters.text], echo))

# log all errors
dp.add_error_handler(error)

# log all errors
dp.addErrorHandler(error)

import django_telegrambot
Loading

0 comments on commit c840cee

Please sign in to comment.