Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,9 @@ output/*/index.html

# Sphinx
docs/_build

# virtualvenv
venv

# PyCharm
.idea
11 changes: 8 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,20 @@ python:


env:
- DJANGO_VERSION=2.0
- DJANGO_VERSION=1.11
- DJANGO_VERSION=1.10
- DJANGO_VERSION=1.9
- DJANGO_VERSION=1.8

matrix:
exclude:
- python: "2.7"
env: DJANGO_VERSION=2.0

before_install:
- pip install coveralls

# command to install dependencies, e.g. pip install -r requirements.txt --use-mirrors
install:
install:
- pip install -q Django==$DJANGO_VERSION
- pip install -r requirements/test.txt

Expand Down
6 changes: 3 additions & 3 deletions requirements/base.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
django>=1.8.0
djangorestframework==3.3.2
python-telegram-bot==5.3.0
django>=1.10.0
djangorestframework>=3.8
python-telegram-bot>=10.0
14 changes: 8 additions & 6 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,25 +45,27 @@
],
include_package_data=True,
install_requires=[
'django>=1.8.0',
'python-telegram-bot==5.3.0',
'djangorestframework==3.3.2',
'django>=1.10.0',
'python-telegram-bot==7.0.1',
'djangorestframework>=3.8',
],
license="BSD",
zip_safe=False,
keywords='django-telegram-bot',
classifiers=[
'Development Status :: 3 - Alpha',
'Framework :: Django',
'Framework :: Django :: 1.8',
'Framework :: Django :: 1.9',
'Framework :: Django :: 1.10',
'Framework :: Django :: 1.11',
'Framework :: Django :: 2.0',
'Intended Audience :: Developers',
'License :: OSI Approved :: BSD License',
'Natural Language :: English',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
],
)
8 changes: 5 additions & 3 deletions telegrambot/bot_views/decorators.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from functools import wraps
from telegrambot.models import Chat, Bot
from django.core.urlresolvers import reverse

try:
from django.urls import reverse
except ImportError:
from django.core.urlresolvers import reverse

def login_required(view_func):
"""
Expand All @@ -18,4 +20,4 @@ def wrapper(bot, update, **kwargs):
bot_model = Bot.objects.get(token=bot.token)
kwargs['link'] = reverse('telegrambot:auth', kwargs={'bot': bot_model.user_api.username})
return login_command_view(bot, update, **kwargs)
return wrapper
return wrapper
8 changes: 7 additions & 1 deletion telegrambot/bot_views/generic/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,20 @@ def handle(self, bot, update, **kwargs):
if text:
if not PY3:
text = text.encode('utf-8')
bot.send_message(chat_id=update.message.chat_id, text=text, reply_markup=keyboard, parse_mode=ParseMode.MARKDOWN)
try:
bot.send_message(chat_id=update.message.chat_id, text=text, reply_markup=keyboard, parse_mode=ParseMode.MARKDOWN)
except AttributeError:
self.handle_callback_query(bot, update, **kwargs)
else:
logger.info("No text response for update %s" % str(update))
except:
exc_info = sys.exc_info()
traceback.print_exception(*exc_info)
raise

def handle_callback_query(self, bot, update, **kwargs):
raise NotImplementedError('Implement this to handle callback queries, which are received when an InlineKeyboard is clicked')

@classmethod
def as_command_view(cls, **initkwargs):
def view(bot, update, **kwargs):
Expand Down
7 changes: 5 additions & 2 deletions telegrambot/bot_views/generic/compound.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@ class ListDetailCommandView(TemplateCommandView):
@classmethod
def as_command_view(cls, **initkwargs):
def view(bot, update, **kwargs):
command_args = update.message.text.split(' ')
try:
command_args = update.message.text.split(' ')
except AttributeError:
command_args = update.callback_query.data.split(' ')
if len(command_args) > 1:
self = cls.detail_view_class(command_args[1])
else:
self = cls.list_view_class()
return self.handle(bot, update, **kwargs)
return view
return view
3 changes: 1 addition & 2 deletions telegrambot/bot_views/generic/responses.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ def render(self):
logger.debug("Template not found: %s" % self.template_name)
return None
# TODO: Avoid using a null HttRequest to context processors
ctx = RequestContext(HttpRequest(), self.ctx)
return template.render(ctx)
return template.render(self.ctx)

class TextResponse(TemplateResponse):

Expand Down
17 changes: 8 additions & 9 deletions telegrambot/bot_views/login.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
from django.conf import settings
from telegrambot.bot_views.generic import TemplateCommandView
from telegrambot.models import Bot

class LoginBotView(TemplateCommandView):
template_text = "telegrambot/messages/login_required.txt"

def generate_link(self, bot, link):

from django.contrib.sites.models import Site
current_site = Site.objects.get_current()
return 'https://%s%s' % (current_site.domain, link)

domain = settings.TELEGRAM_BOT_SITE_DOMAIN
return 'https://%s%s' % (domain, link)

def get_bot(self, bot):
return Bot.objects.get(token=bot.token)

def get_context(self, bot, update, **kwargs):

context = {'bot': self.get_bot(bot),
'link': self.generate_link(bot, kwargs['link'])}
return context
return context
22 changes: 16 additions & 6 deletions telegrambot/handlers/resolver.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,28 @@
from django.core.urlresolvers import RegexURLResolver
from django.core.urlresolvers import Resolver404
try:
from django.urls import URLResolver
from django.urls.resolvers import RegexPattern
from django.urls.exceptions import Resolver404
except ImportError:
from django.core.urlresolvers import RegexURLResolver, Resolver404

class HandlerNotFound(Exception):
pass


class HandlerResolver(object):

def __init__(self, conf):
self.resolver = RegexURLResolver(r'^', conf)

try:
self.resolver = RegexURLResolver(r'^', conf)
except NameError:
self.resolver = URLResolver(RegexPattern(r'^'), conf)

def resolve(self, update):
try:
resolver_match = self.resolver.resolve(update.message.text)
return resolver_match
except AttributeError:
resolver_match = self.resolver.resolve(update.callback_query.data)
return resolver_match
except Resolver404:
raise HandlerNotFound("No handler configured for %s" % update.message.text)
raise HandlerNotFound("No handler configured for %s" % update.message.text)
38 changes: 20 additions & 18 deletions telegrambot/models/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
from telegram import Bot as BotAPI
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.core.urlresolvers import reverse
try:
from django.urls import reverse
except ImportError:
from django.core.urlresolvers import reverse
import logging
from telegrambot.models import User
from telegrambot.handlers import HandlerResolver
Expand All @@ -18,30 +21,30 @@
@python_2_unicode_compatible
class Bot(models.Model):
token = models.CharField(_('Token'), max_length=100, db_index=True)
user_api = models.OneToOneField(User, verbose_name=_("Bot User"), related_name='bot',
user_api = models.OneToOneField(User, verbose_name=_("Bot User"), related_name='bot',
on_delete=models.CASCADE, blank=True, null=True)
ssl_certificate = models.FileField(_("SSL certificate"), upload_to='telegrambot/ssl/',
ssl_certificate = models.FileField(_("SSL certificate"), upload_to='telegrambot/ssl/',
blank=True, null=True)
https_port = models.PositiveIntegerField(_('Webhook HTTPS port'), blank=True,
null=True, default=None,
help_text=_('Leave empty if the bot webhook is published at the standard HTTPS port (443).'))
enabled = models.BooleanField(_('Enable'), default=True)
created = models.DateTimeField(_('Date Created'), auto_now_add=True)
modified = models.DateTimeField(_('Date Modified'), auto_now=True)
modified = models.DateTimeField(_('Date Modified'), auto_now=True)

class Meta:
verbose_name = _('Bot')
verbose_name_plural = _('Bots')
verbose_name_plural = _('Bots')

def __init__(self, *args, **kwargs):
super(Bot, self).__init__(*args, **kwargs)
self._bot = None
if self.token:
self._bot = BotAPI(self.token)

def __str__(self):
return "%s" % (self.user_api.first_name or self.token if self.user_api else self.token)

def handle(self, update):
handlerconf = settings.TELEGRAM_BOT_HANDLERS_CONF
resolver = HandlerResolver(handlerconf)
Expand All @@ -54,8 +57,8 @@ def handle(self, update):
callback(self, update, **callback_kwargs)

def send_message(self, chat_id, text, parse_mode=None, disable_web_page_preview=None, **kwargs):
self._bot.sendMessage(chat_id=chat_id, text=text, parse_mode=parse_mode,
disable_web_page_preview=disable_web_page_preview, **kwargs)
self._bot.sendMessage(chat_id=chat_id, text=text, parse_mode=parse_mode,
disable_web_page_preview=disable_web_page_preview, **kwargs)

@receiver(post_save, sender=Bot)
def set_api(sender, instance, **kwargs):
Expand All @@ -66,21 +69,20 @@ def set_api(sender, instance, **kwargs):
url = None
cert = None
if instance.enabled:
webhook = reverse('telegrambot:webhook', kwargs={'token': instance.token})
from django.contrib.sites.models import Site
current_site = Site.objects.get_current()
webhook = reverse('telegrambot:webhook', kwargs={'token': instance.token})
domain = settings.TELEGRAM_BOT_SITE_DOMAIN
if instance.https_port is None:
url = 'https://' + current_site.domain + webhook
url = 'https://' + domain + webhook
else:
url = 'https://' + current_site.domain + ':' + str(instance.https_port) + webhook
url = 'https://' + domain + ':' + str(instance.https_port) + webhook
if instance.ssl_certificate:
instance.ssl_certificate.open()
cert = instance.ssl_certificate

instance._bot.setWebhook(webhook_url=url,
instance._bot.setWebhook(webhook_url=url,
certificate=cert)
logger.info("Success: Webhook url %s for bot %s set" % (url, str(instance)))

# complete Bot instance with api data
if not instance.user_api:
bot_api = instance._bot.getMe()
Expand Down
8 changes: 4 additions & 4 deletions telegrambot/models/telegram_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ def is_authenticated(self):
class Message(models.Model):

message_id = models.BigIntegerField(_('Id'), primary_key=True)
from_user = models.ForeignKey(User, related_name='messages', verbose_name=_("User"))
from_user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='messages', verbose_name=_("User"))
date = models.DateTimeField(_('Date'))
chat = models.ForeignKey(Chat, related_name='messages', verbose_name=_("Chat"))
forward_from = models.ForeignKey(User, null=True, blank=True, related_name='forwarded_from',
chat = models.ForeignKey(Chat, on_delete=models.CASCADE, related_name='messages', verbose_name=_("Chat"))
forward_from = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True, related_name='forwarded_from',
verbose_name=_("Forward from"))
text = models.TextField(null=True, blank=True, verbose_name=_("Text"))
# TODO: complete fields with all message fields
Expand All @@ -74,7 +74,7 @@ def __str__(self):
class Update(models.Model):

update_id = models.BigIntegerField(_('Id'), primary_key=True)
message = models.ForeignKey(Message, null=True, blank=True, verbose_name=_('Message'),
message = models.ForeignKey(Message, on_delete=models.CASCADE, null=True, blank=True, verbose_name=_('Message'),
related_name="updates")

class Meta:
Expand Down
6 changes: 3 additions & 3 deletions telegrambot/templatetags/telegrambot_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
@register.filter(name='keyboard_field')
def keyboard_field(value, args=None):
"""
Format keyboard /command field.
Format keyboard /command field.
"""
qs = QueryDict(args)
per_line = qs.get('per_line', 1)
Expand All @@ -16,5 +16,5 @@ def keyboard_field(value, args=None):
grouped = group(value, int(per_line))
new_list = []
for line in grouped:
new_list.append([convert(e) for e in line])
return str(new_list).encode('utf-8')
new_list.append([convert(e) for e in line])
return new_list
5 changes: 3 additions & 2 deletions telegrambot/test/factories/telegram_lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class UserLibFactory(Factory):
class Meta:
model = telegram.User
id = Sequence(lambda n: n+1)
is_bot = False
first_name = Sequence(lambda n: 'first_name_%d' % n)
last_name = Sequence(lambda n: 'last_name_%d' % n)
username = Sequence(lambda n: 'username_%d' % n)
Expand All @@ -30,10 +31,10 @@ class Meta:
from_user = SubFactory(UserLibFactory)
date = timezone.now()
chat = SubFactory(ChatLibFactory)
text = FuzzyText()
text = FuzzyText()

class UpdateLibFactory(Factory):
class Meta:
model = telegram.Update
update_id = Sequence(lambda n: n+1)
message = SubFactory(MessageLibFactory)
message = SubFactory(MessageLibFactory)
Loading