-
Notifications
You must be signed in to change notification settings - Fork 0
/
voteBot_responses.py
336 lines (270 loc) · 13.7 KB
/
voteBot_responses.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
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
import bot_memory
import utils
from utils import BOT_CHAR
from info import VERSION
from datetime import datetime, timedelta
winner_list = []
vote_active = False
date1_string = ""
date2_string = ""
def get_vote_active():
return vote_active
def prep_author_and_content(message):
assert message.content[0] == BOT_CHAR
author = message.author
words = message.content.split()
command = words[0].lower()[1::]
content = message.content[len(command) + 2::]
return author, content
async def default(message, client):
return ["unknown command. Try !help"], False, None
async def greet(message, client):
author, _ = prep_author_and_content(message)
nick = author.nick
if nick is None:
nick = author.name
return [f"""beep beep boop {author.id} (this is bot language for "hello {nick}.")"""], False, None
async def version(message, client):
return [f"""VoteBot Version: {VERSION}."""], False, None
def suggestion_key_to_txt(key):
msg = ""
for char in key:
msg += char
return msg
async def suggest(message, client):
author, content = prep_author_and_content(message)
print(f"content: {content}")
key = tuple(utils.remove_empty_lines(content))
print(f"key: {key}")
nick = author.nick
if nick is None:
nick = author.name
print(f"author: {author}, ID: {author.id}, NICK: {nick}")
msg = f"Suggestion:\n{suggestion_key_to_txt(key)}\n suggested by {nick}."
return [msg], False, utils.PAPER_VOTING_CHANNEL_ID
async def vote(message, client):
global winner_list
global vote_active
await message.add_reaction("🤖")
vote_active = True
print("Lets vote")
(vote_winner, vote_info) = await utils.get_winner(client)
if vote_winner is None:
return [f"No options"], False, None
winner_list.append(vote_winner.id)
content = vote_winner.content.partition("Suggestion:")[-1][1::] #remove first word
print(f"winner content: {content}")
return [f"Winner with acceptance value {vote_info} is:\n{utils.untuple_str(content)}\n"
f"\n"
f"✅: to set it for the upcoming meeting.\n"
f"⏩: to see the runner-up."], False, None
def increase_date():
upcoming_date = bot_memory.get_info(info_key=bot_memory.NEXT_DATE)
print(f"extracted previously next_date, now upcoming_date: {upcoming_date}")
bot_memory.set_info(info_key=bot_memory.UPCOMING_DATE, info_value=upcoming_date)
print(f"change date")
if upcoming_date == "N/A":
bot_memory.set_info(info_key=bot_memory.NEXT_DATE, info_value="N/A")
else:
next_date = datetime.strptime(upcoming_date, "%Y/%m/%d") + timedelta(days=7)
bot_memory.set_info(info_key=bot_memory.NEXT_DATE, info_value=next_date.strftime("%Y/%m/%d"))
async def responsibility_note(user):
global CLIENT
paper = bot_memory.get_info(info_key=bot_memory.UPCOMING_PAPER)
text = f"You made \n{paper}\n the paper for the upcoming meeting. " \
f"Please feel responsible to update the website " \
f"https://ai.dmi.unibas.ch/research/reading_group.html\n" \
f"or to delegate it."
print(f"send {text}\n to {user.name} / {user.id}")
await user.send(text)
async def dictate(message, client):
author, content = prep_author_and_content(message)
bot_memory.set_info(info_key=bot_memory.UPCOMING_PAPER, info_value=content)
increase_date()
await responsibility_note(author)
return [meeting_announcment(), vote_announcement()], False, utils.MEETING_CHANNEL_ID
async def accept_by_rank(rank, channel):
global winner_list
global vote_active
if not vote_active:
print("outside of voting phase")
return [""], False, None
vote_active = False
final_winner = winner_list[rank-1]
final_winner_message = await channel.fetch_message(final_winner)
final_content = final_winner_message.content.partition("Suggestion:")[-1][1::] #remove first word
winner_list = []
await final_winner_message.delete()
increase_date()
bot_memory.set_info(info_key=bot_memory.UPCOMING_PAPER, info_value=final_content)
print("done accept_by_rank")
upcoming_date = bot_memory.get_info(info_key=bot_memory.NEXT_DATE)
return [f"{utils.untuple_str(final_content)}\n\nwas accepted as winner for the meeting on {upcoming_date}."], False, None
async def deny(message, client):
global winner_list
global vote_active
if not vote_active:
print("outside of voting phase")
return [""], False, None
print("Lets vote again")
(vote_winner, vote_info) = await utils.get_winner(client, winner_list)
if vote_winner is None:
return [f"No further options"], False, None
content = vote_winner.content.partition("Suggestion:")[-1][1::] #remove first word
print(f"the new winner is...\n{utils.untuple_str(content)}\n\n{vote_info}")
winner_list.append(vote_winner.id)
print(f"Winner list: {winner_list}")
return [f"Winner #{len(winner_list)} with acceptance value {vote_info} is:\n{utils.untuple_str(content)}"], False, None
async def show_admins(message, client):
return ["admins DB:\n" + str(bot_memory.get_admins_table())], False, None
async def show_db(message, client):
bi = await bot_info(message, client)
sa = await show_admins(message, client)
return [bi[0][0]] + \
[
sa[0][0],
], False, None
async def bot_info(message, client):
upcoming_date = bot_memory.get_info(info_key=bot_memory.UPCOMING_DATE)
paper = bot_memory.get_info(info_key=bot_memory.UPCOMING_PAPER)
next_date = bot_memory.get_info(info_key=bot_memory.NEXT_DATE)
return [f"The date of the upcoming meeting: {upcoming_date}.\n" \
f"We will discuss the paper:\n{paper}\n" \
f"\n" \
f"The date of the next meeting: {next_date}.\n"], False, None
def meeting_announcment():
upcoming_date = bot_memory.get_info(info_key=bot_memory.UPCOMING_DATE)
paper = bot_memory.get_info(info_key=bot_memory.UPCOMING_PAPER)
return f"For the upcoming meeting on {upcoming_date} we read:\n" \
f"\n{paper}\n"
def vote_announcement():
next_date = bot_memory.get_info(info_key=bot_memory.NEXT_DATE)
return f"-----------------------------------------\n" + \
f"The date of the next meeting: {next_date}.\n" + \
f"Tell me with 🇯/🇸 reactions whether you will 🇯oin or 🇸kip the next meeting "\
"so I can consider your votes accordingly."
def new_meeting_announcment():
global date1_string
global date2_string
return f"For the next meeting on {date1_string} we have the vote on {date2_string}."
async def set_upcoming_date(message, client):
author, content = prep_author_and_content(message)
bot_memory.set_info(info_key=bot_memory.UPCOMING_DATE, info_value=content)
await message.add_reaction("✅")
return [], False, None
async def set_next_date(message, client):
author, content = prep_author_and_content(message)
bot_memory.set_info(info_key=bot_memory.NEXT_DATE, info_value=content)
await message.add_reaction("✅")
return [], False, None
async def admin_set_upcoming_paper(message, client):
author, content = prep_author_and_content(message)
bot_memory.set_info(info_key=bot_memory.UPCOMING_PAPER, info_value=content)
await message.add_reaction("✅")
return [], False, None
async def announce_new_meeting(message, client):
author, content = prep_author_and_content(message)
global date1_string
global date2_string
try:
date1_string = content.split()[0]
date1 = datetime.strptime(date1_string, "%Y/%m/%d")
date2_string = content.split()[1]
date2 = datetime.strptime(date2_string, "%Y/%m/%d")
bot_memory.set_info(info_key=bot_memory.NEXT_DATE, info_value=date1_string)
bot_memory.set_info(info_key=bot_memory.UPCOMING_DATE, info_value="N/A")
return [new_meeting_announcment(), vote_announcement()], False, utils.MEETING_CHANNEL_ID
except Exception as e:
await message.add_reaction("❌")
return [], False, None
async def echo(message, client):
author, content = prep_author_and_content(message)
channel_ID_str = content.split()[0]
channel_ID = int(channel_ID_str)
return [content[len(channel_ID_str)::]], False, channel_ID
async def echo_user(message, client):
author, content = prep_author_and_content(message)
user_ID_str = content.split()[0]
user_ID = int(user_ID_str)
user = await client.fetch_user(user_ID)
await user.send(content[len(user_ID_str)::])
return [], False, None
async def add_admin(message, client):
author, content = prep_author_and_content(message)
bot_memory.update_admins(content, add=True)
await message.add_reaction("✅")
return [], False, None
async def remove_admin(message, client):
author, content = prep_author_and_content(message)
bot_memory.update_admins(content, add=False)
await message.add_reaction("✅")
return [], False, None
async def admin_announce_meeting(message, client):
return [meeting_announcment(), vote_announcement()], False, utils.MEETING_CHANNEL_ID
responses_dict = {
"info": [bot_info, f"I tell you this weeks paper, meeting date "
f"and the date for the meeting corresponding to the upcoming vote."],
"suggest": [suggest, f"'{BOT_CHAR}suggest [string]' to add a suggestion.\n"
"Type for example "
f"```{BOT_CHAR}suggest Patrik Haslum and Hector Geffner.\n Heuristic Planning with Time and "
"Resources.\n In Proc. ECP 2001, pp. 121-132. "
"https://www.ida.liu.se/divisions/aiics/publications/ECP-2001-Heuristic-Planning-Time.pdf``` "
"to suggest this paper for a future meeting.\n"
"No need to follow a specific format."],
"set_next_date": [set_next_date, f"set a date for the next meeting with the format %Y/%m/%d"],
"set_upcoming_date": [set_upcoming_date, f"set a date for the upcoming meeting with the format %Y/%m/%d"],
"vote": [vote, "Returns a paper based on the user reactions to the suggestions and their claims to join/skip."],
"v": [vote, f"shorthand for {BOT_CHAR}vote"],
"dictate": [dictate, f"'{BOT_CHAR}dictate [string]' to bypass suggesting and voting. "
"The next meeting will be announced with the set string as paper. "
"Keep your anti-pitchfork-spray at hand when using this command. "],
"announce_new_meeting": [announce_new_meeting, f"'{BOT_CHAR}announce_new_meeting [date1] [date2]' to announce"
" that a new meeting will happen at date1 and the paper will be"
" decided on date2. Date format %Y/%m/%d"],
# admin commands
"admin_add_admin": [add_admin, f"add an admin with '{BOT_CHAR}admin_add_admin [user_ID]'"],
"admin_remove_admin": [remove_admin, f"remove an admin with '{BOT_CHAR}admin_remove_admin [user_ID]'"],
"admin_show_admins": [show_admins, f"list all admins"],
"admin_hi": [greet, f"greeting each other"],
"admin_version": [version, f"check the version"],
"admin_set_upcoming_paper": [admin_set_upcoming_paper, f"set the upcoming paper for the meeting"],
"admin_announce_meeting": [admin_announce_meeting, f"announce a meeting with the current next/upcoming date and paper"],
"admin_show_db": [show_db, f"show all tables from the DB"],
"admin_echo": [echo, f"Let the VoteBot say something '{BOT_CHAR}admin_echo [channel_ID] [string]'"],
"admin_echo_user": [echo_user, f"Let the VoteBot say something '{BOT_CHAR}admin_echo [user_ID] [string]'"],
}
help_msg = "I am the VoteBot you can suggest papers to me. Everyone can react with emojis to the suggestions. " \
"You can tell me if you plan to join or skip the next meeting. " \
"I can choose a paper based on the user reactions to the suggestions and their claims to join/skip.\n" \
"Reactions:\n" \
"👍: I am looking forward to discuss this paper.\n" \
"👎: I want you to discuss this paper without me.\n" \
"⭐: I want you to wait for me to discuss this paper (please do not overuse).\n" \
"How can I help you? I know these commands:\n"
def get_help_msg(admin):
msg = ""
for key in responses_dict:
if (key[0:5] == "admin") == admin:
msg += "\n```" + BOT_CHAR + str(key) + "```" + "\t" + responses_dict[key][1] + "\n"
post_msg = "\nYou can interact with me in a private chat, too."
return [help_msg, msg, post_msg]
async def bot_help(message, client):
msg = get_help_msg(False)
return msg, False, None
async def admin_help(message, client):
msg = get_help_msg(True)
return msg, False, None
responses_dict.update({"help": [bot_help, "get a help message."]})
responses_dict.update({"admin_help": [admin_help, "get a help message for admins."]})
async def handle_responses(message_content, message, is_private, client):
author = message.author
if not message_content[0] == BOT_CHAR:
return []
words = message_content.split()
command = words[0].lower()[1::]
if command[0:5] == "admin" and (author.id,) not in bot_memory.get_admins_table():
return ["This command is only for admins."], False, None
response_function = responses_dict.get(command, [default, "default response function"])[0]
if is_private and response_function in [suggest, set_next_date, set_upcoming_date, vote, dictate] and (author.id,) not in bot_memory.get_admins_table():
return ["This command is only usable in the public channels."]
return await response_function(message, client) # expect list of strings and one bool and maybe channel_id