Geen omschrijving

telegram.py 9.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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. import json
  13. import requests
  14. import random
  15. import string
  16. import re
  17. from counter.models import Counter, Reset
  18. from bot.models import TelegramUser, TelegramUserCheck, TelegramUserChat, TelegramChat
  19. telegram_ips = ['149.154.167.' + str(i) for i in range(197, 234)]
  20. telegram_url = 'https://api.telegram.org/bot' + settings.BOT_TELEGRAM_KEY + '/'
  21. telegram_bot_id = settings.BOT_TELEGRAM_ID
  22. telegram_bot_name = settings.BOT_TELEGRAM_NAME
  23. @receiver(post_save, sender=Reset)
  24. def notify_telegram(sender, instance, created, **kwargs):
  25. if not settings.BOT_TELEGRAM_KEY or not settings.telegram_bot_id or not settings.telegram_bot_name:
  26. return
  27. if created:
  28. chat_ids = [e.chat_id for e in TelegramChat.objects.filter(notify_only_members=False)]
  29. try:
  30. telegram_user = TelegramUser.objects.get(counter=instance.counter)
  31. chats = TelegramUserChat.objects.filter(telegram_user_id=telegram_user.telegram_user_id)
  32. chat_ids = chat_ids + [e.telegram_chat_id for e in chats]
  33. except TelegramUser.DoesNotExist:
  34. do_nothing = True
  35. if instance.who is None or instance.who == instance.counter:
  36. message = str(instance.counter) + ' has le seum: ' + instance.reason
  37. else:
  38. message = str(instance.who) + ' put le seum to ' + str(instance.counter) + ': ' + instance.reason
  39. for chat_id in set(chat_ids):
  40. requests.post(telegram_url + 'sendMessage', json={'chat_id': chat_id, 'text': message})
  41. @login_required
  42. def link(request, verif_key):
  43. try:
  44. telegram_user_check = TelegramUserCheck.objects.get(verif_key=verif_key)
  45. the_counter = Counter.objects.get(user__id=request.user.id)
  46. TelegramUser.objects.create(counter=the_counter, telegram_user_id=telegram_user_check.telegram_user_id)
  47. TelegramUserCheck.objects.filter(telegram_user_id=telegram_user_check.telegram_user_id).delete()
  48. return HttpResponse('Your Telegram account has been linked!')
  49. except TelegramUserCheck.DoesNotExist:
  50. return HttpResponse(status=404)
  51. @csrf_exempt
  52. def webhook(request):
  53. ip = request.META.get('REMOTE_ADDR')
  54. # Uncomment the following two lines, and correctly configure the
  55. # reverse proxy to enable the security, or everyone will be able
  56. # to put le seum to everyone
  57. if not ip in telegram_ips:
  58. return HttpResponse(status=401)
  59. data = json.loads(request.body.decode('utf-8'))
  60. print(data)
  61. # We have different types of messages
  62. # - a simple text message from a person
  63. # - the bot joined/left a channel
  64. # - somebody joined/left a channel
  65. # The idea is to keep a list of all the telegram users in all channels
  66. # Then when a new seum is created, we look all the channels in which this user
  67. # is, and we send a message in those to notify everybody
  68. if not 'message' in data or not 'chat' in data['message']:
  69. return HttpResponse(201) # we should return something correct, or Telegram will try to send us the message again multiple times
  70. chat = data['message']['chat']
  71. if chat['type'] != 'private':
  72. if 'new_chat_member' in data['message']:
  73. user_id = data['message']['new_chat_member']['id']
  74. if user_id == telegram_bot_id:
  75. r = requests.get(telegram_url + 'getChatMembersCount?chat_id=' + str(chat['id'])).json()
  76. if r['result'] < 20: # when there are less than 20 people, we deactivate notify_only_members
  77. try:
  78. TelegramChat.objects.create(chat_id=chat['id'], notify_only_members=True)
  79. except IntegrityError as e:
  80. print(e)
  81. return HttpResponse('')
  82. 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!'})
  83. else:
  84. TelegramChat.objects.create(chat_id=chat['id'], notify_only_members=False)
  85. 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'})
  86. else:
  87. TelegramUserChat.objects.create(telegram_user_id=user_id, telegram_chat_id=chat['id'])
  88. return HttpResponse('')
  89. if 'left_chat_member' in data['message']:
  90. user_id = data['message']['left_chat_member']['id']
  91. if user_id == telegram_bot_id:
  92. TelegramUserChat.objects.filter(telegram_chat_id=chat['id']).delete()
  93. TelegramChat.objects.filter(chat_id=chat['id']).delete()
  94. else:
  95. TelegramUserChat.objects.filter(telegram_user_id=user_id, telegram_chat_id=chat['id']).delete()
  96. return HttpResponse(200)
  97. if not 'message' in data or not 'from' in data['message'] or not 'id' in data['message']['from']:
  98. return HttpResponse(201)
  99. telegram_user_id = data['message']['from']['id']
  100. if chat['type'] != 'private':
  101. # For each message we receive in a non private chat, we save that this user is in this chat
  102. try:
  103. TelegramUserChat.objects.create(telegram_user_id=telegram_user_id, telegram_chat_id=chat['id'])
  104. except:
  105. do_nothing = True
  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. reset = Reset(counter=yes_counter, who=telegram_user.counter, reason=seum_message)
  139. reset.save()
  140. except TelegramUser.DoesNotExist:
  141. print('in that case we send a link to the user')
  142. if chat['type'] == 'private' and chat['id'] == telegram_user_id:
  143. # We are in a private channel, we directly send the link
  144. verif_key = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(30))
  145. 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]))})
  146. TelegramUserCheck.objects.create(telegram_user_id=telegram_user_id, verif_key=verif_key)
  147. else:
  148. print('bou')
  149. # We are not in a private channel, so we mention the user to talk with us
  150. 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']})
  151. return HttpResponse('')