-
Notifications
You must be signed in to change notification settings - Fork 0
/
bot.py
195 lines (157 loc) · 6.97 KB
/
bot.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
from mongo_client_wrapper import MongoClientWrapper
import telepot
from telepot.loop import MessageLoop
import time
from telepot.delegate import (per_chat_id_except, per_chat_id_in, create_open, pave_event_space, call)
from constants_and_messages import *
from telepot.namedtuple import ReplyKeyboardMarkup, KeyboardButton
from format_functions import format_leaderboard
from custom_threads import custom_thread
from directories_manager import create_directory
import sys
SetProxy = telepot.api.set_proxy("http://181.129.160.50:39460")
TOKEN = '809107388:AAHoSNRNDziBc1Ffs-cw-D0g8aetlh8DMpk'
MONGO = 'mongodb://localhost:27017/' #default mongo addr
OWNER_ID = 130042164
class GatherValidateChatHandler(telepot.helper.ChatHandler):
EMOTIONS_KEYBOARD = ReplyKeyboardMarkup(
keyboard=[[KeyboardButton(text=emotion) for emotion in list(BUTTONS_TO_EMOTIONS.keys())[:3]],
[KeyboardButton(text=emotion) for emotion in list(BUTTONS_TO_EMOTIONS.keys())[3:7]],
[KeyboardButton(text=emotion) for emotion in list(BUTTONS_TO_EMOTIONS.keys())[7:]]]
)
ALLOWED_COMMANDS = ['/start', '/help'] + list(BUTTONS_TO_EMOTIONS.keys()) + MAIN_MENU_BUTTONS
def __init__(self, seed_tuple, mongo, **kwargs):
self._mongo = mongo
self._mode = "audio_records"
self._id_for_classification = None
super(GatherValidateChatHandler, self).__init__(seed_tuple, **kwargs)
def on_chat_message(self, msg):
print('msg!', msg)
content_type, chat_type, chat_id = telepot.glance(msg)
if content_type == 'voice':
self._handle_audio_message(msg)
elif content_type == 'text' and msg['text'] in self.ALLOWED_COMMANDS:
self._handle_text_command(msg)
else:
self.sender.sendMessage(UNSUPPORTED_MESSAGE_ERROR_MESSAGE, reply_markup=MAIN_MENU)
self.sender.sendMessage(MAIN_MENU_INSTRUCTION_MESSAGE, reply_markup=MAIN_MENU)
def _handle_audio_message(self, msg):
print('Duration: ', msg['voice']['duration'])
if msg['voice']['duration'] >= MIN_ALLOWED_VOICE_DURATION: #right voice
self._mongo.add_audio_sample(msg)
self.sender.sendMessage(AUDIO_RECEIVED_MESSAGE, reply_markup=MAIN_MENU)
else: #too short voice
self.sender.sendMessage(WRONG_DURATION_ERROR_MESSAGE, reply_markup=MAIN_MENU)
def _handle_text_command(self, msg):
if msg['text'] == MAIN_MENU_BUTTONS[0]:
self._handle_validation(msg)
elif msg['text'] in BUTTONS_TO_EMOTIONS.keys():
self._handle_vote(msg)
elif msg['text'] == '/start':
self._handle_start(msg)
elif msg['text'] == '/help':
self._handle_help(msg)
elif msg['text'] in MAIN_MENU_BUTTONS[1:-1]:
self._handle_leaderboard(msg)
elif msg['text'] == MAIN_MENU_BUTTONS[-1]:
self._handle_help(msg)
def _handle_help(self, msg):
self.sender.sendMessage(HELP_MESSAGE, reply_markup=MAIN_MENU, parse_mode='Markdown')
def _handle_leaderboard(self, msg):
print('leaderboard')
if msg['text'] == MAIN_MENU_BUTTONS[1]:
action = 'vote'
else:
action = 'audio'
leaders, user_info = self._mongo.get_users_entries_leaderboard(action, msg)
self.sender.sendMessage(format_leaderboard(action, leaders, user_info), reply_markup=MAIN_MENU, parse_mode='Markdown')
def _handle_validation(self, msg):
self._id_for_classification = self._mongo.choose_id_for_validation()
if self._id_for_classification is not None:
self.sender.sendMessage(VALIDATION_INSTRUCTION_MESSAGE, reply_markup=None)
self.sender.sendVoice(self._id_for_classification, reply_markup=self.EMOTIONS_KEYBOARD)
else:
self.sender.sendMessage(ALL_VALIDATED_MESSAGE, reply_markup=MAIN_MENU)
def _handle_vote(self, msg):
self._mongo.add_vote(self._id_for_classification, BUTTONS_TO_EMOTIONS[msg['text']], msg)
self.sender.sendMessage(VOTE_RECEIVED, reply_markup=MAIN_MENU)
def _handle_start(self, msg):
self.sender.sendMessage(WELCOME_MESSAGE.format(msg['from']['username']), reply_markup=MAIN_MENU)
self._mongo.add_user(msg)
def on_callback_query(self, msg):
query_id, from_id, query_data = telepot.glance(msg, flavor='callback_query')
print(query_data)
class OwnerHandler(GatherValidateChatHandler):
def __init__(self, seed_tuple, mongo, **kwargs):
super(OwnerHandler, self).__init__(seed_tuple, mongo, **kwargs)
self._announce_mode = False
def handle_get_users_command(original_function):
def new_function(self, msg):
content_type, chat_type, chat_id = telepot.glance(msg)
if content_type == 'text' and msg['text'] == '/get_users':
self.get_users(msg['text'])
else:
original_function(self, msg)
return new_function
def handle_get_total_stats_command(original_function):
def new_function(self, msg):
content_type, chat_type, chat_id = telepot.glance(msg)
if content_type == 'text' and msg['text'] == '/get_total_stats':
self.get_total_stats(msg['text'])
else:
original_function(self, msg)
return new_function
def get_users(self, text):
usernames = self._mongo.get_all_users()
self.sender.sendMessage('\n'.join(usernames) + '\nTotal: ' + str(len(usernames)))
def get_total_stats(self, text):
total_stats = self._mongo.get_total_stats()
self.sender.sendMessage('\n'.join(['Total ' + key + ': ' + str(stat) for key, stat in total_stats.items()]))
@handle_get_users_command
@handle_get_total_stats_command
def on_chat_message(self, msg):
super(OwnerHandler, self).on_chat_message(msg)
class GatherValidateBot(telepot.DelegatorBot):
FILES_DIRECTORY = 'raw_audio'
def __init__(self, token, owner_id):
# create folder for audio storage
create_directory(self.FILES_DIRECTORY)
self._mongo = MongoClientWrapper(MONGO)
super(GatherValidateBot, self).__init__(token, [
# Handler for the chat actions
pave_event_space()(per_chat_id_except([owner_id]), create_open, GatherValidateChatHandler, self._mongo,
timeout=1000000),
pave_event_space()(
per_chat_id_in([owner_id]), create_open, OwnerHandler, self._mongo, timeout=1000000),
# download voice file
(self._is_voice, custom_thread(call(self._download_and_store))),
# announce to all users
(self._is_announce, custom_thread(call(self._announce)))
])
def _is_voice(self, msg):
content_type, chat_type, chat_id = telepot.glance(msg)
if content_type != 'voice':
return None
else:
return [] #hashable!
def _is_announce(self, msg):
content_type, chat_type, chat_id = telepot.glance(msg)
if msg['from']['id'] == OWNER_ID and content_type == 'text' and msg['text'].split(' ', 1)[0] == '/announce':
return []
else:
return None
def _announce(self, seed_tuple):
msg = seed_tuple[1]
text = msg['text'].split(' ', 1)[1]
user_ids = self._mongo.get_all_user_ids()
print('user_ids', user_ids)
for user_id in user_ids:
self.sendMessage(user_id, text)
def _download_and_store(self, seed_tuple):
self.download_file(seed_tuple[1]['voice']['file_id'], './' + self.FILES_DIRECTORY + '/' +
seed_tuple[1]['voice']['file_id'] + '.ogg')
bot = GatherValidateBot(TOKEN, OWNER_ID)
MessageLoop(bot).run_as_thread()
print ('BotHosting: I am listening ...')
while 1:
time.sleep(4)