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