from django.contrib.auth.models import User from django.core.urlresolvers import reverse from django.shortcuts import render from django.utils.translation import ugettext as _ from django.views.decorators.csrf import csrf_exempt from django.http import HttpResponse from django.contrib.auth.decorators import login_required from django.db.models.signals import post_save from django.dispatch import receiver from django.db.utils import IntegrityError from django.conf import settings import json import requests import random import string import re from counter.models import Counter, Reset from bot.models import TelegramUser, TelegramUserCheck, TelegramUserChat, TelegramChat telegram_ips = ['149.154.167.' + str(i) for i in range(197, 234)] telegram_url = 'https://api.telegram.org/bot' + settings.BOT_TELEGRAM_KEY + '/' telegram_bot_id = settings.BOT_TELEGRAM_ID telegram_bot_name = settings.BOT_TELEGRAM_NAME @receiver(post_save, sender=Reset) def notify_telegram(sender, instance, created, **kwargs): if not settings.BOT_TELEGRAM_KEY or not settings.BOT_TELEGRAM_ID or not settings.BOT_TELEGRAM_NAME: return if created: chat_ids = [e.chat_id for e in TelegramChat.objects.filter(notify_only_members=False)] try: telegram_user = TelegramUser.objects.get(counter=instance.counter) chats = TelegramUserChat.objects.filter(telegram_user_id=telegram_user.telegram_user_id) chat_ids = chat_ids + [e.telegram_chat_id for e in chats] except TelegramUser.DoesNotExist: do_nothing = True if instance.who is None or instance.who == instance.counter: message = str(instance.counter) + ' has le seum: ' + instance.reason else: message = str(instance.who) + ' put le seum to ' + str(instance.counter) + ': ' + instance.reason for chat_id in set(chat_ids): requests.post(telegram_url + 'sendMessage', json={'chat_id': chat_id, 'text': message}) @login_required def link(request, verif_key): try: telegram_user_check = TelegramUserCheck.objects.get(verif_key=verif_key) the_counter = Counter.objects.get(user__id=request.user.id) TelegramUser.objects.create(counter=the_counter, telegram_user_id=telegram_user_check.telegram_user_id) TelegramUserCheck.objects.filter(telegram_user_id=telegram_user_check.telegram_user_id).delete() return HttpResponse('Your Telegram account has been linked!') except TelegramUserCheck.DoesNotExist: return HttpResponse(status=404) @csrf_exempt def webhook(request): ip = request.META.get('REMOTE_ADDR') # Uncomment the following two lines, and correctly configure the # reverse proxy to enable the security, or everyone will be able # to put le seum to everyone if not ip in telegram_ips: return HttpResponse(status=401) data = json.loads(request.body.decode('utf-8')) print(data) # We have different types of messages # - a simple text message from a person # - the bot joined/left a channel # - somebody joined/left a channel # The idea is to keep a list of all the telegram users in all channels # Then when a new seum is created, we look all the channels in which this user # is, and we send a message in those to notify everybody if not 'message' in data or not 'chat' in data['message']: return HttpResponse(201) # we should return something correct, or Telegram will try to send us the message again multiple times chat = data['message']['chat'] if chat['type'] != 'private': if 'new_chat_member' in data['message']: user_id = data['message']['new_chat_member']['id'] if user_id == telegram_bot_id: r = requests.get(telegram_url + 'getChatMembersCount?chat_id=' + str(chat['id'])).json() if r['result'] < 20: # when there are less than 20 people, we deactivate notify_only_members try: TelegramChat.objects.create(chat_id=chat['id'], notify_only_members=True) except IntegrityError as e: print(e) return HttpResponse('') requests.post(telegram_url + 'sendMessage', json={'chat_id': chat['id'], 'text': 'Hello everyone! Because of Telegram restrictions, I don\'t know who is here :( . Everybody, please say /seumhello, so I can see you\'re here!'}) else: TelegramChat.objects.create(chat_id=chat['id'], notify_only_members=False) requests.post(telegram_url + 'sendMessage', json={'chat_id': chat['id'], 'text': 'Hello everyone! I will notify you everytime a person in the world has the seum. I you prefer to be notified only when a member of this group has the seum, use the command /notify_every_seum_or_not'}) else: TelegramUserChat.objects.create(telegram_user_id=user_id, telegram_chat_id=chat['id']) return HttpResponse('') if 'left_chat_member' in data['message']: user_id = data['message']['left_chat_member']['id'] if user_id == telegram_bot_id: TelegramUserChat.objects.filter(telegram_chat_id=chat['id']).delete() TelegramChat.objects.filter(chat_id=chat['id']).delete() else: TelegramUserChat.objects.filter(telegram_user_id=user_id, telegram_chat_id=chat['id']).delete() return HttpResponse(200) if not 'message' in data or not 'from' in data['message'] or not 'id' in data['message']['from']: return HttpResponse(201) telegram_user_id = data['message']['from']['id'] if chat['type'] != 'private': # For each message we receive in a non private chat, we save that this user is in this chat try: TelegramUserChat.objects.create(telegram_user_id=telegram_user_id, telegram_chat_id=chat['id']) except: do_nothing = True text = data['message']['text'] if text == '/notify_every_seum_or_not' or text == '/notify_every_seum_or_not@' + telegram_bot_name: tchat = TelegramChat.objects.get(chat_id=chat['id']) tchat.notify_only_members = not tchat.notify_only_members if tchat.notify_only_members: requests.post(telegram_url + 'sendMessage', json={'chat_id': chat['id'], 'text': 'Ok, I will notify you only if someone in the group has the seum. But, because of Telegram restrictions, I don\'t know who is here :( . Everybody, please say /seumhello, so I can see you\'re here!'}) else: requests.post(telegram_url + 'sendMessage', json={'chat_id': chat['id'], 'text': 'Ok, so now I will notify you everytime a person in the world has the seum.'}) tchat.save() try: telegram_user = TelegramUser.objects.get(telegram_user_id=telegram_user_id) # in that cas we need to parse the message # and either create a new seum and reset a counter # either like some existing seum if text == '/seumunlink' or text == '/seumunlink@' + telegram_bot_name: TelegramUser.objects.filter(telegram_user_id=telegram_user_id).delete() requests.post(telegram_url + 'sendMessage', json={'chat_id': chat['id'], 'text': 'Your Telegram account has successfully been unlinked from your SeumBook account', 'reply_to_message_id': data['message']['message_id']}) return HttpResponse('') if text == '/seumhello' or text == '/seumhello@' + telegram_bot_name: requests.post(telegram_url + 'sendMessage', json={'chat_id': chat['id'], 'text': 'Hello ' + telegram_user.counter.name + ' :-)', 'reply_to_message_id': data['message']['message_id']}) return HttpResponse('') seum_cmd = r"^/seum((@" + telegram_bot_name + ")?) (.+)$" if re.match(seum_cmd, text) is not None: # it's a /seum cmd m = re.sub(seum_cmd, r"\3", text) maybe_counter = m.split(' ')[0] try: yes_counter = Counter.objects.get(trigramme=maybe_counter) seum_message = ' '.join(m.split(' ')[1:]) except Counter.DoesNotExist: yes_counter = telegram_user.counter seum_message = m reset = Reset(counter=yes_counter, who=telegram_user.counter, reason=seum_message) reset.save() except TelegramUser.DoesNotExist: print('in that case we send a link to the user') if chat['type'] == 'private' and chat['id'] == telegram_user_id: # We are in a private channel, we directly send the link verif_key = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(30)) requests.post(telegram_url + 'sendMessage', json={'chat_id': chat['id'], 'text': 'Open the following URL to link your Telegram account to your SeumBook account: ' + request.build_absolute_uri(reverse('tellink', args=[verif_key]))}) TelegramUserCheck.objects.create(telegram_user_id=telegram_user_id, verif_key=verif_key) else: print('bou') # We are not in a private channel, so we mention the user to talk with us requests.post(telegram_url + 'sendMessage', json={'chat_id': chat['id'], 'text': 'Your Telegram account isn\'t linked to a SeumBook account. Say hello to me in a private chat to link it :-)! https://telegram.me/' + telegram_bot_name + '?start=Hello', 'reply_to_message_id': data['message']['message_id']}) return HttpResponse('')