Açıklama Yok

telegram.py 9.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  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.167.' + str(i) for i in range(197, 234)]
  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 = request.META.get('REMOTE_ADDR')
  55. # Uncomment the following two lines, and correctly configure the
  56. # reverse proxy to enable the security, or everyone will be able
  57. # to put le seum to everyone
  58. if not ip in telegram_ips:
  59. return HttpResponse(status=401)
  60. data = json.loads(request.body.decode('utf-8'))
  61. print(data)
  62. # We have different types of messages
  63. # - a simple text message from a person
  64. # - the bot joined/left a channel
  65. # - somebody joined/left a channel
  66. # The idea is to keep a list of all the telegram users in all channels
  67. # Then when a new seum is created, we look all the channels in which this user
  68. # is, and we send a message in those to notify everybody
  69. if not 'message' in data or not 'chat' in data['message']:
  70. return HttpResponse(201) # we should return something correct, or Telegram will try to send us the message again multiple times
  71. chat = data['message']['chat']
  72. if chat['type'] != 'private':
  73. if 'new_chat_member' in data['message']:
  74. user_id = data['message']['new_chat_member']['id']
  75. if user_id == telegram_bot_id:
  76. r = requests.get(telegram_url + 'getChatMembersCount?chat_id=' + str(chat['id'])).json()
  77. if r['result'] < 20: # when there are less than 20 people, we deactivate notify_only_members
  78. try:
  79. TelegramChat.objects.create(chat_id=chat['id'], notify_only_members=True)
  80. except IntegrityError as e:
  81. print(e)
  82. return HttpResponse('')
  83. 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!'})
  84. else:
  85. TelegramChat.objects.create(chat_id=chat['id'], notify_only_members=False)
  86. 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'})
  87. else:
  88. TelegramUserChat.objects.create(telegram_user_id=user_id, telegram_chat_id=chat['id'])
  89. return HttpResponse('')
  90. if 'left_chat_member' in data['message']:
  91. user_id = data['message']['left_chat_member']['id']
  92. if user_id == telegram_bot_id:
  93. TelegramUserChat.objects.filter(telegram_chat_id=chat['id']).delete()
  94. TelegramChat.objects.filter(chat_id=chat['id']).delete()
  95. else:
  96. TelegramUserChat.objects.filter(telegram_user_id=user_id, telegram_chat_id=chat['id']).delete()
  97. return HttpResponse(200)
  98. if not 'message' in data or not 'from' in data['message'] or not 'id' in data['message']['from']:
  99. return HttpResponse(201)
  100. telegram_user_id = data['message']['from']['id']
  101. if chat['type'] != 'private':
  102. # For each message we receive in a non private chat, we save that this user is in this chat
  103. try:
  104. TelegramUserChat.objects.create(telegram_user_id=telegram_user_id, telegram_chat_id=chat['id'])
  105. except:
  106. do_nothing = True
  107. if not 'text' in data['message']:
  108. return HttpResponse(201)
  109. text = data['message']['text']
  110. if text == '/notify_every_seum_or_not' or text == '/notify_every_seum_or_not@' + telegram_bot_name:
  111. tchat = TelegramChat.objects.get(chat_id=chat['id'])
  112. tchat.notify_only_members = not tchat.notify_only_members
  113. if tchat.notify_only_members:
  114. 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!'})
  115. else:
  116. 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.'})
  117. tchat.save()
  118. try:
  119. telegram_user = TelegramUser.objects.get(telegram_user_id=telegram_user_id)
  120. # in that cas we need to parse the message
  121. # and either create a new seum and reset a counter
  122. # either like some existing seum
  123. if text == '/seumunlink' or text == '/seumunlink@' + telegram_bot_name:
  124. TelegramUser.objects.filter(telegram_user_id=telegram_user_id).delete()
  125. 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']})
  126. return HttpResponse('')
  127. if text == '/seumhello' or text == '/seumhello@' + telegram_bot_name:
  128. requests.post(telegram_url + 'sendMessage', json={'chat_id': chat['id'], 'text': 'Hello ' + telegram_user.counter.name + ' :-)', 'reply_to_message_id': data['message']['message_id']})
  129. return HttpResponse('')
  130. seum_cmd = r"^/seum((@" + telegram_bot_name + ")?) (.+)$"
  131. if re.match(seum_cmd, text) is not None:
  132. # it's a /seum cmd
  133. m = re.sub(seum_cmd, r"\3", text)
  134. maybe_counter = m.split(' ')[0]
  135. try:
  136. yes_counter = Counter.objects.get(trigramme=maybe_counter)
  137. seum_message = ' '.join(m.split(' ')[1:])
  138. except Counter.DoesNotExist:
  139. yes_counter = telegram_user.counter
  140. seum_message = m
  141. perform_reset(telegram_user.counter, yes_counter, seum_message)
  142. except TelegramUser.DoesNotExist:
  143. print('in that case we send a link to the user')
  144. if chat['type'] == 'private' and chat['id'] == telegram_user_id:
  145. # We are in a private channel, we directly send the link
  146. verif_key = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(30))
  147. 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]))})
  148. TelegramUserCheck.objects.create(telegram_user_id=telegram_user_id, verif_key=verif_key)
  149. else:
  150. print('bou')
  151. # We are not in a private channel, so we mention the user to talk with us
  152. 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']})
  153. return HttpResponse('')