-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbot.py
193 lines (166 loc) · 6.67 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
import os
import discord
import gspread
from dotenv import load_dotenv
from oauth2client.service_account import ServiceAccountCredentials
from discord.ext import commands
from datetime import datetime
import json
load_dotenv()
TOKEN = os.getenv("TOKEN")
scope = [
"https://spreadsheets.google.com/feeds",
"https://www.googleapis.com/auth/drive",
]
creds = ServiceAccountCredentials.from_json_keyfile_name("credentials.json", scope)
client = gspread.authorize(creds)
sheet = client.open("curriculum tracker")
intents = discord.Intents.default()
intents.message_content = True
bot = commands.Bot(command_prefix="!", intents=intents)
TASK_DEADLINES = {
"Task 00 Codeforces": None,
"Task 01 Git": 5,
"Task 02 Web Dev basics": 10,
"Task 03 Build a Simple Shell": 12,
"Task 04 NOT A SRS DOC": 3,
"Task 05 WIREFRAME THE SKELETON": 5,
"Task 06 Figma Design Task": 7,
"Task 07 Frontend Development": 12,
"Task 08 Backend Development": 12,
"Task 09 Flutter Development": 10,
}
@bot.event
async def on_ready():
print(f"Logged in as {bot.user}")
@bot.command(name="taskstatusgroup1")
async def taskstatus_group1(ctx):
await fetch_tasks_for_group(ctx, "GROUP1")
@bot.command(name="taskstatusgroup2")
async def taskstatus_group2(ctx):
await fetch_tasks_for_group(ctx, "GROUP2")
@bot.command(name="taskstatusgroup3")
async def taskstatus_group3(ctx):
await fetch_tasks_for_group(ctx, "GROUP3")
@bot.command(name="taskstatusgroup4")
async def taskstatus_group4(ctx):
await fetch_tasks_for_group(ctx, "GROUP4")
@bot.command(name="curriculumdeadlines")
async def curriculum_deadlines(ctx):
embed = discord.Embed(
title="📌 Curriculum Deadlines",
description="Here are the task deadlines for the curriculum:",
color=discord.Color.orange()
)
for task, days in TASK_DEADLINES.items():
if days is None:
deadline = "Until objectives are met"
else:
deadline = f"{days} days"
embed.add_field(name=task, value=deadline, inline=False)
embed.set_footer(text="")
await ctx.send(embed=embed)
async def fetch_tasks_for_group(ctx, group_name):
try:
available_sheets = [ws.title for ws in sheet.worksheets()]
if group_name not in available_sheets:
await ctx.send(
f"Error: Sheet '{group_name}' not found!\nAvailable sheets: {', '.join(available_sheets)}"
)
return
worksheet = sheet.worksheet(group_name)
data = worksheet.get_all_values()
mentee_tasks = {}
last_mentee = None
for row in data[1:]:
if not any(row):
continue
mentee, task, state, start_date, end_date, *_ = row
if mentee.strip():
last_mentee = mentee.strip()
if last_mentee not in mentee_tasks:
mentee_tasks[last_mentee] = []
if last_mentee is None:
continue
days_taken = ""
date_format = "%d/%m/%Y"
if state.strip().lower() == "done" and start_date and end_date:
try:
start = datetime.strptime(start_date, date_format)
end = datetime.strptime(end_date, date_format)
days_taken = f" ({(end - start).days} days)"
except ValueError:
pass
mentee_tasks[last_mentee].append(
f"✅️ **{task}** - time taken: {start_date} - {end_date}{days_taken}"
)
elif state.strip().lower() == "in progress" and start_date:
try:
start = datetime.strptime(start_date, date_format)
today_date = datetime.today()
days = f" ({(today_date - start).days} days)"
except ValueError:
days= ""
mentee_tasks[last_mentee].append(f"🟠 **{task}** -In Progress, start date: {start_date}")
embed = discord.Embed(
title=f"Tasks from {group_name}", color=discord.Color.orange()
)
embed.set_footer(text="Curriculum Tracker Bot")
if not mentee_tasks:
embed.description = "No tasks found"
else:
for mentee, tasks in mentee_tasks.items():
embed.add_field(
name=f"__**{mentee}**__", value="\n".join(tasks), inline=False
)
await ctx.send(embed=embed)
except Exception as e:
await ctx.send(f"Error fetching data from {group_name}: {e}")
@bot.command(name="leaderboard")
async def leaderboard(ctx):
group_names = ["GROUP1", "GROUP2", "GROUP3", "GROUP4"]
date_format = "%d/%m/%Y"
task_leaderboard = {}
for group_name in group_names:
try:
worksheet = sheet.worksheet(group_name)
data = worksheet.get_all_values()
last_mentee = None
for row in data[1:]:
if not any(row):
continue
mentee, task, state, start_date, end_date, *_ = row
if mentee.strip():
last_mentee = mentee.strip()
if last_mentee is None or not task:
continue
if state.strip().lower() == "done" and start_date and end_date:
try:
start = datetime.strptime(start_date, date_format)
end = datetime.strptime(end_date, date_format)
days_taken = (end - start).days
if days_taken < 0:
continue
if task not in task_leaderboard:
task_leaderboard[task] = []
task_leaderboard[task].append((last_mentee, days_taken))
except ValueError:
continue
except Exception as e:
await ctx.send(f"Error processing {group_name}: {e}")
continue
if not task_leaderboard:
await ctx.send("No task-wise data found.")
return
embed = discord.Embed(
title="📊 Task-wise Leaderboard",
description="Top performers per task (based on completion time)",
color=discord.Color.purple()
)
for task, mentees in task_leaderboard.items():
mentees_sorted = sorted(mentees, key=lambda x: x[1])[:3] # Top 3
value = "\n".join([f"#{i+1} **{name}** - {days} days" for i, (name, days) in enumerate(mentees_sorted)])
embed.add_field(name=f"🏁 {task}", value=value, inline=False)
embed.set_footer(text="Based on 'Done' tasks across all groups.")
await ctx.send(embed=embed)
bot.run(TOKEN)