-
Notifications
You must be signed in to change notification settings - Fork 1
/
discord_bot.py
278 lines (233 loc) · 9.23 KB
/
discord_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
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
import requests
import gspread
import json
from oauth2client.service_account import ServiceAccountCredentials
import os
from dotenv import load_dotenv
import discord
from discord.ext import commands, tasks
import urllib
import io
import aiohttp
# These are the PRs we have taken care
prs_taken_care = []
prs_ids_file = open('pr_ids.txt', 'r')
prs_taken_care = prs_ids_file.read().split("\n")
prs_ids_file.close()
# Repos list
repos_list = []
repos_file = open('repos.txt', 'r')
repos_list = repos_file.read().split("\n")
repos_list = [x.lower() for x in repos_list]
repos_file.close()
# Bot's announcement channel
discord_channel_id = 1050055499485286450
temp_channel = 1049971925792870470
# Role to mention, when a PR with no points label or badly formatted points label is found
organizing_team_role_id = "<@&900360254624239666>"
# Stuff for google spreadsheets
scope = [
'https://www.googleapis.com/auth/drive',
'https://www.googleapis.com/auth/drive.file',
'https://www.googleapis.com/auth/spreadsheets'
]
file_name = 'client_key.json'
creds = ServiceAccountCredentials.from_json_keyfile_name(file_name,scope)
client_gs = gspread.authorize(creds)
sheet = client_gs.open('CODEPEAK 23 SCORING').sheet1
load_dotenv()
# Discord bot
client = commands.Bot(command_prefix=".", intents=discord.Intents.all())
token = os.getenv('TOKEN')
github_token = os.getenv('GITHUB_TOKEN')
image_url = os.getenv('IMAGE_URL')
@client.event
async def on_ready():
await client.change_presence(activity=discord.Game(name="codepeak.tech"))
await check.start()
print("Logged in as a bot {0.user}".format(client))
# Command to test if the bot is up
@client.command()
async def test(ctx):
await ctx.reply("Up")
@client.command()
async def award(ctx, username, points, link):
my_roles = ctx.author.roles
found_mentor = False
for role in my_roles:
if role.name == 'Mentor':
found_mentor = True
break
if not found_mentor:
return
try:
points = int(points)
except Exception:
await ctx.reply("Invalid points")
return
column = sheet.col_values(1)
column = [x.lower() for x in column]
if (username.lower() in column):
i = column.index(username.lower())+1
row = sheet.row_values(i)
currentPoints = int(row[1])
l = len(row)
sheet.update_cell(i, l+1, points)
sheet.update_cell(i, l+2, link)
currentPoints += points
sheet.update_cell(i, 2, currentPoints)
await ctx.reply(username + " has been awarded " + str(points) + " points! Making their total: " + str(currentPoints))
else:
i = len(column) + 1
sheet.update_cell(i, 1, username)
sheet.update_cell(i, 2, points)
sheet.update_cell(i, 3, points)
sheet.update_cell(i, 4, link)
await ctx.reply(username + " has been awarded " + str(points) + " points! Making their total: " + str(points))
@tasks.loop(seconds=3*60)
async def check():
await findNewContributions()
# To announce that we have got a badly formatted points label
async def announce_badly_formatted_points_label(pr_link):
global client
global temp_channel
global organizing_team_role_id
message = organizing_team_role_id + ", found a PR with `CodePeak 22` label, but with a badly formatted points label.\n"+pr_link
await client.get_channel(temp_channel).send(message)
# To announce that we have got a PR with CodePeak 22 label but no points label
async def announce_no_points_label(pr_link):
global client
global temp_channel
global organizing_team_role_id
message = organizing_team_role_id + ", found a PR with `CodePeak 22` label, but with no points label.\n"+pr_link
await client.get_channel(temp_channel).send(message)
async def new_announce_points_awarded(handle, points, total, link, avatar_link):
global client
global discord_channel_id
global temp_channel
global image_url
await client.get_channel(temp_channel).send("4")
repo = link.split('/')[-3]
prnumber = link.split('/')[-1]
change_url = image_url + "points/?username="
change_url += urllib.parse.quote(handle, safe='()*!\'')
change_url += "&points="
change_url += urllib.parse.quote(points, safe='()*!\'')
change_url += "&totalpoints="
change_url += urllib.parse.quote(total, safe='()*!\'')
change_url += "&repo="
change_url += urllib.parse.quote(repo, safe='()*!\'')
change_url += "&prnumber="
change_url += urllib.parse.quote(prnumber, safe='()*!\'')
change_url += "&url="
change_url += urllib.parse.quote(avatar_link, safe='()*!\'')
async with aiohttp.ClientSession() as session:
await client.get_channel(temp_channel).send("5")
async with session.get(change_url) as resp:
await client.get_channel(temp_channel).send("6")
img = await resp.read()
with io.BytesIO(img) as file:
await client.get_channel(temp_channel).send("7")
await client.get_channel(discord_channel_id).send(file=discord.File(file, "points.png"))
await client.get_channel(temp_channel).send("8")
# To awards points, i.e., update points in google spreadsheet
async def award_points(handle, points, link, id, avatar_url):
global client
global temp_channel
await client.get_channel(temp_channel).send("1")
try:
column = sheet.col_values(1)
column = [x.lower() for x in column]
if (handle.lower() in column):
i = column.index(handle.lower())+1
row = sheet.row_values(i)
currentPoints = int(row[1])
l = len(row)
sheet.update_cell(i, l+1, points)
sheet.update_cell(i, l+2, link)
currentPoints += points
sheet.update_cell(i, 2, currentPoints)
await new_announce_points_awarded(handle, str(points), str(currentPoints), link, avatar_url)
else:
i = len(column) + 1
sheet.update_cell(i, 1, handle)
sheet.update_cell(i, 2, points)
sheet.update_cell(i, 3, points)
sheet.update_cell(i, 4, link)
await new_announce_points_awarded(handle, str(points), str(points), link, avatar_url)
await client.get_channel(temp_channel).send("2")
prs_taken_care.append(id)
set_pr_ids()
await client.get_channel(temp_channel).send("3")
except Exception as e:
print(e)
print("Rated limited ig")
def set_pr_ids():
global prs_taken_care
prs_ids_file = open('pr_ids.txt', 'w')
prs_ids_file.write("\n".join(prs_taken_care))
prs_ids_file.close()
# To find new contributions
async def findNewContributions():
global prs_taken_care
global repos_list
global github_token
print("Attempting to find some.")
headers = {'Authorization': 'Bearer ' + github_token}
url = 'https://api.github.com/search/issues?q=label%3Aissue%3A1'
req = requests.get(url, headers=headers)
data = json.loads(req.text)
for i in data['items']:
repo_name = i['repository_url'].split("/")[-1]
if not repo_name.lower() in repos_list:
continue
if not str(i['id']) in prs_taken_care:
handle = i['user']['login']
link = i['html_url']
points = 1
await award_points(handle, points, link, str(i['id']), i['user']['avatar_url'])
url = 'https://api.github.com/search/issues?q=label%3Aissue%3A3'
req = requests.get(url, headers=headers)
data = json.loads(req.text)
for i in data['items']:
repo_name = i['repository_url'].split("/")[-1]
if not repo_name.lower() in repos_list:
continue
if not str(i['id']) in prs_taken_care:
handle = i['user']['login']
link = i['html_url']
points = 3
await award_points(handle, points, link, str(i['id']), i['user']['avatar_url'])
url = 'https://api.github.com/search/issues?q=is%3Apr+is%3Amerged+label%3A%22codepeak+22%22'
req = requests.get(url, headers=headers)
data = json.loads(req.text)
for i in data['items']:
repo_name = i['repository_url'].split("/")[-1]
if not repo_name.lower() in repos_list:
continue
if not str(i['id']) in prs_taken_care:
handle = i['user']['login']
link = i['html_url']
points = -1
badly_formatted = False
for label in i['labels']:
name = label['name'].lower()
if "points:" in name:
args = name.split('points:')
if len(args) != 2:
await announce_badly_formatted_points_label(link)
badly_formatted = True
break
try:
points = int(args[1])
except Exception:
await announce_badly_formatted_points_label(link)
badly_formatted = True
break
if badly_formatted:
continue
if points == -1:
await announce_no_points_label(link)
continue
await award_points(handle, points, link, str(i['id']), i['user']['avatar_url'])
client.run(token)