Skip to content

Commit

Permalink
Update for python-telegram-bot release v6.0.1, and more
Browse files Browse the repository at this point in the history
  • Loading branch information
JungDev committed May 25, 2017
1 parent 5ca49c0 commit 3bae40d
Show file tree
Hide file tree
Showing 9 changed files with 310 additions and 49 deletions.
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.6'
__version__ = '0.2.7'
default_app_config = 'django_telegrambot.apps.DjangoTelegramBot'
176 changes: 136 additions & 40 deletions django_telegrambot/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,53 @@
import telegram
from django.utils.module_loading import module_has_submodule
from telegram.ext import Dispatcher
from telegram.ext import Updater
import os.path

import logging

logger = logging.getLogger(__name__)

TELEGRAM_BOT_MODULE_NAME = 'telegrambot'
WEBHOOK_MODE, POLLING_MODE = range(2)

class classproperty(property):
def __get__(self, obj, objtype=None):
return super(classproperty, self).__get__(objtype)
def __set__(self, obj, value):
super(classproperty, self).__set__(type(obj), value)
def __delete__(self, obj):
super(classproperty, self).__delete__(type(obj))

class DjangoTelegramBot(AppConfig):
name = 'django_telegrambot'
verbose_name = 'Django TelegramBot'
ready_run = False
dispatcher = None
#_dispatcher = None
#_updater = None
bot_tokens = []
bot_usernames = []
dispatchers = []
bots = []
updaters = []
__used_tokens = set()

@classproperty
def dispatcher(cls):
#print("Getting value default dispatcher")
cls.__used_tokens.add(cls.bot_tokens[0])
return cls.dispatchers[0]

@classproperty
def updater(cls):
#print("Getting value default updater")
cls.__used_tokens.add(cls.bot_tokens[0])
return cls.updaters[0]

@classmethod
def getDispatcher(cls, bot_id=None, safe=True):
def get_dispatcher(cls, bot_id=None, safe=True):
if bot_id is None:
cls.__used_tokens.add(cls.bot_tokens[0])
return cls.dispatchers[0]
else:
try:
Expand All @@ -40,12 +65,22 @@ def getDispatcher(cls, bot_id=None, safe=True):
index = cls.bot_usernames.index(bot_id)
except ValueError:
return None
cls.__used_tokens.add(cls.bot_tokens[index])
return cls.dispatchers[index]


@classmethod
def getBot(cls, bot_id=None, safe=True):
def getDispatcher(cls, bot_id=None, safe=True):
return cls.get_dispatcher(bot_id, safe)


@classmethod
def get_bot(cls, bot_id=None, safe=True):
if bot_id is None:
return cls.bots[0]
if safe:
return cls.bots[0]
else:
return None
else:
try:
index = cls.bot_tokens.index(bot_id)
Expand All @@ -58,63 +93,113 @@ def getBot(cls, bot_id=None, safe=True):
return None
return cls.bots[index]


@classmethod
def getBot(cls, bot_id=None, safe=True):
return cls.get_bot(bot_id, safe)


@classmethod
def get_updater(cls, bot_id=None, safe=True):
if bot_id is None:
return cls.updaters[0]
else:
try:
index = cls.bot_tokens.index(bot_id)
except ValueError:
if not safe:
return None
try:
index = cls.bot_usernames.index(bot_id)
except ValueError:
return None
return cls.updaters[index]


@classmethod
def getUpdater(cls, id=None, safe=True):
return cls.get_updater(id, safe)


def ready(self):
if DjangoTelegramBot.ready_run:
return
DjangoTelegramBot.ready_run = True

self.mode = WEBHOOK_MODE
if hasattr(settings, 'TELEGRAM_BOT_MODE'):
if settings.TELEGRAM_BOT_MODE == '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

if not hasattr(settings, 'TELEGRAM_WEBHOOK_SITE'):
logger.warn('Required TELEGRAM_WEBHOOK_SITE missing in settings')
return
webhook_site = settings.TELEGRAM_WEBHOOK_SITE

if not hasattr(settings, 'TELEGRAM_WEBHOOK_BASE'):
logger.warn('Required TELEGRAM_WEBHOOK_BASE missing in settings')
return
webhook_base = settings.TELEGRAM_WEBHOOK_BASE

use_certificate = False
if hasattr(settings, 'TELEGRAM_WEBHOOK_CERTIFICATE'):
cert = settings.TELEGRAM_WEBHOOK_CERTIFICATE
if os.path.exists(cert):
use_certificate = True
logger.info('TELEGRAM_WEBHOOK_CERTIFICATE found in {}'.format(cert))
if self.mode == WEBHOOK_MODE:
if not hasattr(settings, 'TELEGRAM_WEBHOOK_SITE'):
logger.warn('Required TELEGRAM_WEBHOOK_SITE missing in settings')
return
webhook_site = settings.TELEGRAM_WEBHOOK_SITE

webhook_base = ""
if hasattr(settings, 'TELEGRAM_WEBHOOK_BASE'):
logger.warn('Required TELEGRAM_WEBHOOK_BASE missing in settings')
webhook_base = settings.TELEGRAM_WEBHOOK_BASE

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))

timeout = None
if hasattr(settings, 'TELEGRAM_WEBHOOK_TIMEOUT'):
timeout = settings.TELEGRAM_WEBHOOK_TIMEOUT

max_connections = 40
if hasattr(settings, 'TELEGRAM_WEBHOOK_MAX_CONNECTIONS'):
max_connections = settings.TELEGRAM_WEBHOOK_MAX_CONNECTIONS

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)
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:
logger.error('TELEGRAM_WEBHOOK_CERTIFICATE not found in {} '.format(cert))

for index, token in enumerate(tokens):
updater = Updater(token=token)
bot = updater.bot
bot.delete_webhook()
DjangoTelegramBot.updaters.append(updater)
DjangoTelegramBot.dispatchers.append(updater.dispatcher)
DjangoTelegramBot.__used_tokens.add(token)

bot = telegram.Bot(token=token)

DjangoTelegramBot.dispatchers.append(Dispatcher(bot, None, workers=0))
DjangoTelegramBot.bots.append(bot)
DjangoTelegramBot.bot_tokens.append(bot.token)
DjangoTelegramBot.bot_tokens.append(token)
DjangoTelegramBot.bot_usernames.append(bot.username)

hookurl = '{}{}/{}/'.format(webhook_site, webhook_base, token)
if use_certificate:
setted = bot.setWebhook(hookurl, certificate=open(cert, 'rb'))
else:
setted = bot.setWebhook(hookurl, certificate=None)

logger.info('Telegram Bot <{}> setting webhook [ {} ] : {}'.format(bot.username, hookurl, setted))

# per compatibilità salvo il primo bot nella proprietà DjangoTelegramBot.dispatcher
if index == 0:
DjangoTelegramBot.dispatcher = DjangoTelegramBot.dispatchers[0]
logger.debug('Telegram Bot <{}> set as default bot'.format(bot.username))
logger.debug('Telegram Bot <{}> set as default bot'.format(DjangoTelegramBot.bots[0].username))

def module_exists(module_name, method_name, execute):
try:
# m = __import__(module_name).telegrambot
m = importlib.import_module(module_name)
if execute and hasattr(m, method_name):
logger.debug('Run {}.main()'.format(module_name))
logger.debug('Run {}.{}()'.format(module_name,method_name))
getattr(m, method_name)()
else:
logger.debug('Run {}'.format(module_name))
Expand All @@ -131,3 +216,14 @@ def module_exists(module_name, method_name, execute):
module_name = '%s.%s' % (app_config.name, TELEGRAM_BOT_MODULE_NAME)
if module_exists(module_name, 'main', True):
logger.info('Loaded {}'.format(module_name))

num_bots=len(DjangoTelegramBot.__used_tokens)
if self.mode == POLLING_MODE and num_bots>0:
logger.info('Please manually start polling update for {0} bot{1}. Run command{1}:'.format(num_bots, 's' if num_bots>1 else ''))
for token in DjangoTelegramBot.__used_tokens:
updater = DjangoTelegramBot.get_updater(bot_id=token)
logger.info('python manage.py botpolling --username={}'.format(updater.bot.username))




Empty file.
Empty file.
57 changes: 57 additions & 0 deletions django_telegrambot/management/commands/botpolling.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import logging

from django.core.management.base import BaseCommand
#from telegram.ext import Updater

from django_telegrambot.apps import DjangoTelegramBot


class Command(BaseCommand):
help = "Run telegram bot in polling mode"
can_import_settings = True

def add_arguments(self, parser):
parser.add_argument('--username', '-i', help="Bot username", default=None)
parser.add_argument('--token', '-t', help="Bot token", default=None)
pass

def get_updater(self, username=None, token=None):
updater = None
if username is not None:
updater = DjangoTelegramBot.get_updater(bot_id=username)
if not updater:
self.stderr.write("Cannot find default bot with username {}".format(username))
elif token:
updater = DjangoTelegramBot.get_updater(bot_id=token)
if not updater:
self.stderr.write("Cannot find bot with token {}".format(token))
return updater

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")
return

updater = self.get_updater(username=options.get('username'), token=options.get('token'))
if not updater:
self.stderr.write("Bot not found")
return
# Enable Logging
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
level=logging.INFO)
logger = logging.getLogger("telegrambot")
logger.setLevel(logging.INFO)
console = logging.StreamHandler()
console.setLevel(logging.INFO)
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
self.stdout.write("Run polling...")
updater.start_polling()
self.stdout.write("the bot is started and runs until we press Ctrl-C on the command line.")
updater.idle()
88 changes: 88 additions & 0 deletions django_telegrambot/templates/django_telegrambot/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
{% extends "admin/index.html" %}
{% block extrastyle %}
{{ block.super }}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<style>
#django-telegrambot ul li {
list-style-type: none;
}
ul.nolist{
margin-left: 10px;
padding-left: 0;
}
.dodgerblue{
color: dodgerblue;
}
.botlist{
font-size: 1.5em;
}
#django-telegrambot li {font-size: 1.1em;}
</style>
{% endblock %}
{% block extrahead %}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/1.6.1/clipboard.min.js"></script>

<script src="https://use.fontawesome.com/c8dc42a356.js"></script>
<script>
$( document ).ready(function() {

var clipboard = new Clipboard('.btn');
clipboard.on('success', function(e) {
e.clearSelection();
});

clipboard.on('error', function(e) {
console.error('Action:', e.action);
console.error('Trigger:', e.trigger);
});
});
</script>
{% endblock %}
{% block breadcrumbs %}
<div class="breadcrumbs">
<a href="{% url 'admin:index' %}">Home</a> &rsaquo;
<a href="{% url 'django-telegrambot' %}">Django Telegrambot</a>
</div>
{% endblock %}
{% block content %}


{{ block.super }}
<div id = 'django-telegrambot' style = "float: left">
<h1><a href="https://github.com/JungDev/django-telegrambot#django-telegrambot">Django-TelegramBot</a></h1>
<p>
The full documentation is at <a href="https://django-telegrambot.readthedocs.org">https://django-telegrambot.readthedocs.org</a>.
</p>
<h3>Bot update mode: <b>{{update_mode}}</b></h3>
{% if update_mode == 'POLLING' %}<p>Please remember to start polling mode with commands:
<ul class="nolist">
{% for bot in bot_list %}
<li>
<kbd>$ python manage.py botpolling --username={{bot.username}}</kbd>
<button class="btn btn-default btn-xs" data-clipboard-text="python manage.py botpolling --username={{bot.username}}">
<i class="fa fa-clipboard" aria-hidden="true"></i>
</button>
</li>
{% endfor %}
</ul>
</p>
{% endif %}

{% if bot_list %}
<h3>Bot List:</h3>
<ul class="nolist botlist">
{% for bot in bot_list %}
<i class="fa fa-telegram dodgerblue" aria-hidden="true"></i>
<b>{{ bot.first_name}}</b>
<a class="btn btn-default btn-sm" href="https://t.me/{{ bot.username }}/?start=true" role="button" title="start a chat">@{{ bot.username}}</a>
<a class="btn btn-default btn-sm" href="https://t.me/{{ bot.username }}/?startgroup=true" role="button">Add to group/channel</a></li>
{% endfor %}
</ul>
{% else %}
<p>No bots are available. Please <a href="https://github.com/JungDev/django-telegrambot#configure-your-installation">configure it</a> in settings.py</p>
{% endif %}
</div>

{% endblock %}
Loading

0 comments on commit 3bae40d

Please sign in to comment.