Sin descripción

telegram.py 9.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. from django.contrib.auth.models import User
  2. from django.core.urlresolvers import reverse
  3. from django.shortcuts import render
  4. from django.utils.translation import ugettext as _
  5. from django.views.decorators.csrf import csrf_exempt
  6. from django.http import HttpResponse
  7. from django.contrib.auth.decorators import login_required
  8. from django.db.models.signals import post_save
  9. from django.dispatch import receiver
  10. from django.db.utils import IntegrityError
  11. from django.conf import settings
  12. from counter.views.counter import perform_reset
  13. import json
  14. import requests
  15. import random
  16. import string
  17. import re
  18. from counter.models import Counter, Reset
  19. from bot.models import TelegramUser, TelegramUserCheck, TelegramUserChat, TelegramChat
  20. telegram_ips = ['149.154.' + str(i) + '.' for i in range(160, 176)] + ['91.108.' + str(i) + '.' for i in range(4, 8)]
  21. telegram_url = 'https://api.telegram.org/bot' + settings.BOT_TELEGRAM_KEY + '/'
  22. telegram_bot_id = settings.BOT_TELEGRAM_ID
  23. telegram_bot_name = settings.BOT_TELEGRAM_NAME
  24. @receiver(post_save, sender=Reset)
  25. def notify_telegram(sender, instance, created, **kwargs):
  26. if not settings.BOT_TELEGRAM_KEY or not settings.BOT_TELEGRAM_ID or not settings.BOT_TELEGRAM_NAME:
  27. return
  28. if created:
  29. chat_ids = [e.chat_id for e in TelegramChat.objects.filter(notify_only_members=False)]
  30. try:
  31. telegram_user = TelegramUser.objects.get(counter=instance.counter)
  32. chats = TelegramUserChat.objects.filter(telegram_user_id=telegram_user.telegram_user_id)
  33. chat_ids = chat_ids + [e.telegram_chat_id for e in chats]
  34. except TelegramUser.DoesNotExist:
  35. do_nothing = True
  36. if instance.who is None or instance.who == instance.counter:
  37. message = str(instance.counter) + ' a le seum: ' + instance.reason
  38. else:
  39. message = str(instance.who) + ' a foutu le seum à ' + str(instance.counter) + ': ' + instance.reason
  40. for chat_id in set(chat_ids):
  41. requests.post(telegram_url + 'sendMessage', json={'chat_id': chat_id, 'text': message})
  42. @login_required
  43. def link(request, verif_key):
  44. try:
  45. telegram_user_check = TelegramUserCheck.objects.get(verif_key=verif_key)
  46. the_counter = Counter.objects.get(user__id=request.user.id)
  47. TelegramUser.objects.create(counter=the_counter, telegram_user_id=telegram_user_check.telegram_user_id)
  48. TelegramUserCheck.objects.filter(telegram_user_id=telegram_user_check.telegram_user_id).delete()
  49. return HttpResponse('Your Telegram account has been linked!')
  50. except TelegramUserCheck.DoesNotExist:
  51. return HttpResponse(status=404)
  52. @csrf_exempt
  53. def webhook(request):
  54. ip = re.sub(r"\.([^.]+)$", '.', request.META.get('REMOTE_ADDR'))
  55. if not ip in telegram_ips:
  56. return HttpResponse(status=401)
  57. data = json.loads(request.body.decode('utf-8'))
  58. print(data)
  59. # We have different types of messages
  60. # - a simple text message from a person
  61. # - the bot joined/left a channel
  62. # - somebody joined/left a channel
  63. # The idea is to keep a list of all the telegram users in all channels
  64. # Then when a new seum is created, we look all the channels in which this user
  65. # is, and we send a message in those to notify everybody
  66. if not 'message' in data or not 'chat' in data['message']:
  67. return HttpResponse(201) # we should return something correct, or Telegram will try to send us the message again multiple times
  68. chat = data['message']['chat']
  69. if chat['type'] != 'private':
  70. if 'new_chat_member' in data['message']:
  71. user_id = data['message']['new_chat_member']['id']
  72. if user_id == telegram_bot_id:
  73. r = requests.get(telegram_url + 'getChatMembersCount?chat_id=' + str(chat['id'])).json()
  74. if r['result'] < 20: # when there are less than 20 people, we deactivate notify_only_members
  75. try:
  76. TelegramChat.objects.create(chat_id=chat['id'], notify_only_members=True)
  77. except IntegrityError as e:
  78. print(e)
  79. return HttpResponse('')
  80. 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!'})
  81. else:
  82. TelegramChat.objects.create(chat_id=chat['id'], notify_only_members=False)
  83. 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'})
  84. else:
  85. TelegramUserChat.objects.create(telegram_user_id=user_id, telegram_chat_id=chat['id'])
  86. return HttpResponse('')
  87. if 'left_chat_member' in data['message']:
  88. user_id = data['message']['left_chat_member']['id']
  89. if user_id == telegram_bot_id:
  90. TelegramUserChat.objects.filter(telegram_chat_id=chat['id']).delete()
  91. TelegramChat.objects.filter(chat_id=chat['id']).delete()
  92. else:
  93. TelegramUserChat.objects.filter(telegram_user_id=user_id, telegram_chat_id=chat['id']).delete()
  94. return HttpResponse(200)
  95. if not 'message' in data or not 'from' in data['message'] or not 'id' in data['message']['from']:
  96. return HttpResponse(201)
  97. telegram_user_id = data['message']['from']['id']
  98. if chat['type'] != 'private':
  99. # For each message we receive in a non private chat, we save that this user is in this chat
  100. try:
  101. TelegramUserChat.objects.create(telegram_user_id=telegram_user_id, telegram_chat_id=chat['id'])
  102. except:
  103. do_nothing = True
  104. if not 'text' in data['message']:
  105. return HttpResponse(201)
  106. text = data['message']['text']
  107. if text == '/notify_every_seum_or_not' or text == '/notify_every_seum_or_not@' + telegram_bot_name:
  108. tchat = TelegramChat.objects.get(chat_id=chat['id'])
  109. tchat.notify_only_members = not tchat.notify_only_members
  110. if tchat.notify_only_members:
  111. 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!'})
  112. else:
  113. 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.'})
  114. tchat.save()
  115. try:
  116. telegram_user = TelegramUser.objects.get(telegram_user_id=telegram_user_id)
  117. # in that cas we need to parse the message
  118. # and either create a new seum and reset a counter
  119. # either like some existing seum
  120. if text == '/seumunlink' or text == '/seumunlink@' + telegram_bot_name:
  121. TelegramUser.objects.filter(telegram_user_id=telegram_user_id).delete()
  122. 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']})
  123. return HttpResponse('')
  124. if text == '/seumhello' or text == '/seumhello@' + telegram_bot_name:
  125. requests.post(telegram_url + 'sendMessage', json={'chat_id': chat['id'], 'text': 'Hello ' + telegram_user.counter.name + ' :-)', 'reply_to_message_id': data['message']['message_id']})
  126. return HttpResponse('')
  127. seum_cmd = r"^/seum((@" + telegram_bot_name + ")?) (.+)$"
  128. if re.match(seum_cmd, text) is not None:
  129. # it's a /seum cmd
  130. m = re.sub(seum_cmd, r"\3", text)
  131. maybe_counter = m.split(' ')[0]
  132. try:
  133. yes_counter = Counter.objects.get(trigramme=maybe_counter)
  134. seum_message = ' '.join(m.split(' ')[1:])
  135. except Counter.DoesNotExist:
  136. yes_counter = telegram_user.counter
  137. seum_message = m
  138. perform_reset(telegram_user.counter, yes_counter, seum_message)
  139. except TelegramUser.DoesNotExist:
  140. print('in that case we send a link to the user')
  141. if chat['type'] == 'private' and chat['id'] == telegram_user_id:
  142. # We are in a private channel, we directly send the link
  143. verif_key = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(30))
  144. 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]))})
  145. TelegramUserCheck.objects.create(telegram_user_id=telegram_user_id, verif_key=verif_key)
  146. else:
  147. print('bou')
  148. # We are not in a private channel, so we mention the user to talk with us
  149. 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']})
  150. return HttpResponse('')