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
|
from os import environ
import argparse
import discord
import sqlite3
import time
ap = argparse.ArgumentParser()
ap.add_argument('database', help='the file with the database')
a = ap.parse_args()
if 'TOKEN' not in environ:
print('please set an environment variable TOKEN with the bot token')
exit(1)
token = environ['TOKEN']
dbcon = sqlite3.connect(a.database)
cur = dbcon.cursor()
rows = cur.execute('''
SELECT entry_1, entry_2, poll_number, expires, channel_id, message_id
FROM polls
WHERE voters_1 IS NULL
ORDER BY expires
''').fetchall()
s = discord.session(token)
def get_all_voters(s, channel, message, answer):
endpoint_base = f'/channels/{channel}/polls/{message}/answers/{answer}?limit=100'
users = discord.get(s, endpoint_base)['users']
if len(users) < 100:
return users
while True:
new_users = discord.get(s, endpoint_base + f'&after={users[-1]['id']}')['users']
users += new_users
if len(new_users) < 100:
return users
for row in rows:
expires = row[3]
sleep_for = expires - time.time()
if sleep_for > 0:
time.sleep(sleep_for)
result = None
time_to_sleep = 1
while True:
result = discord.get(s, f'/channels/{row[4]}/messages/{row[5]}')
if result['poll']['results']['is_finalized']:
break
time.sleep(time_to_sleep)
time_to_sleep *= 2
answer_list_1 = list(filter(lambda x: x['poll_media']['text'] == row[0], result['poll']['answers']))
answer_list_2 = list(filter(lambda x: x['poll_media']['text'] == row[1], result['poll']['answers']))
if len(answer_list_1) != 1 or len(answer_list_2) != 1:
exit(1)
the_time = time.time()
voters_1 = get_all_voters(s, row[4], row[5], answer_list_1[0]['answer_id'])
voters_2 = get_all_voters(s, row[4], row[5], answer_list_2[0]['answer_id'])
cur.executemany('INSERT OR REPLACE INTO users VALUES(?, ?, ?, ?)',
list(map(lambda x: (x['id'], x['global_name'], x['avatar'], the_time), voters_1 + voters_2)))
cur.execute('''
UPDATE polls
SET voters_1 = ?, voters_2 = ?
WHERE poll_number = ?
LIMIT 1
''', (
','.join(map(lambda x: x['id'], voters_1)),
','.join(map(lambda x: x['id'], voters_2)),
row[2]
))
cur.executemany('''
UPDATE entries
SET status = ?
WHERE name = ?
LIMIT 1
''', [
(0 if len(voters_1) >= len(voters_2) else 2, row[0]),
(0 if len(voters_2) >= len(voters_1) else 2, row[1])
])
dbcon.commit()
|