-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathleaderboard.py
153 lines (122 loc) · 5.6 KB
/
leaderboard.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
import discord
from discord.ext import commands, tasks
import aiohttp
import asyncio
from datetime import datetime, timedelta
from io import StringIO
LOGIN_ENDPOINT = '/api/login'
GET_LOGS_ENDPOINT = '/api/get_historical_logs'
with open('creds.txt', 'r') as f:
USERNAME, PASSWORD = f.read().split('\n')
RESET_ON_DAYS = [1, 16]
EMBED_ICON = 'https://media.discordapp.net/attachments/729998051288285256/791030109628399647/MiP_-5ea_400x400.png'
def next_update():
now = datetime.now() - timedelta(hours=1)
if now.day > 16 or (now.day == 16 and now.hour >= 12):
exec_at = (now.replace(day=1) + timedelta(days=32)).replace(day=1,hour=12,minute=0,second=0)
elif now.day == 1 and now.hour < 12:
exec_at = now.replace(day=1,hour=12,minute=0,second=0)
else:
exec_at = now.replace(day=16,hour=12,minute=0,second=0)
return exec_at
def last_update():
dt = next_update()
dt -= timedelta(days=15)
if dt.day != 1: dt = dt.replace(day=16)
return dt
class LeaderboardInstance:
@classmethod
async def create(cls, bot, url, guild_id, channel_id, name, content, show_full_results=True):
self = LeaderboardInstance()
self.bot = bot
self.name = name
self.url = url
self.guild = self.bot.get_guild(guild_id)
self.channel = self.guild.get_channel(channel_id)
self.content = content
self.show_full_results = show_full_results
return self
async def print(self):
# Get logs
jar = aiohttp.CookieJar(unsafe=True)
async with aiohttp.ClientSession(cookie_jar=jar) as session:
# Login
payload = {'username': USERNAME, 'password': PASSWORD}
await session.post(self.url+LOGIN_ENDPOINT, json=payload)
# Get logs
payload = {'limit': 999999, 'log_type': 'KILL', 'from': str(last_update())}
async with session.post(self.url+GET_LOGS_ENDPOINT, json=payload) as res:
logs = (await res.json())['result']
# Parse logs
data = dict()
for log in logs:
killer = log['player_name']
victim = log['player2_name']
try: data[killer][0] += 1
except KeyError: data[killer] = [1, 0, {"None": 0}]
try: data[victim][1] += 1
except KeyError: data[victim] = [0, 1, {"None": 0}]
# Parse weapon used
weapon = log['content'].split(' with ')[-1]
if weapon == "None": weapon = "Tank/Arty"
try: data[killer][2][weapon] += 1
except KeyError: data[killer][2][weapon] = 1
# Order logs
data = dict(sorted(data.items(), key=lambda item: item[1][0]*1000-item[1][1], reverse=True))
# Turn into file
output = "RANK NAME KILLS DEATHS K/D WEAPON"
for i, (name, (kills, deaths, weapons)) in enumerate(data.items()):
kd = round(kills/deaths, 2) if deaths else 0.00
weapon = max(weapons, key=weapons.get)
output += "\n#{: <5} {: <25} {: <6} {: <6} {: <6} {}({})".format(i+1, name, kills, deaths, kd, weapon, weapons[weapon])
f = StringIO(output)
f.seek(0)
# Send results over discord
embed = discord.Embed(title=f"🏆 Leaderboard from {last_update().strftime('%b %d')} to {next_update().strftime('%b %d')} 🏆", color=discord.Color.gold())
embed.set_author(icon_url=EMBED_ICON, name=self.name)
for i, (name, (kills, deaths, weapons)) in enumerate(data.items()):
i += 1
if i > 15: break
elif i == 1: rank = "🥇"
elif i == 2: rank = "🥈"
elif i == 3: rank = "🥉"
else: rank = "#"+str(i)
if i <= 6: rank = '_ _\n' + rank
kd = round(kills/deaths, 2) if deaths else 0.00
weapon = max(weapons, key=weapons.get)
embed.add_field(name=f"{rank} {name}", value=f"Kills: {str(kills)}\nDeaths: {str(deaths)}\nK/D Ratio: {str(kd)}\nWeapon: {weapon}({str(weapons[weapon])})")
await self.channel.send(content=self.content, embed=embed)
if self.show_full_results: await self.channel.send(file=discord.File(f, "full_results.txt"))
class leaderboard(commands.Cog):
def __init__(self, bot):
self.bot = bot
@commands.Cog.listener()
async def on_ready(self):
leaderboards = [
#('http://62.171.172.221:8040', 618763306726981652, 666991815978909697, '[WTH] Public Server 1 & 2', '', False),
('http://62.171.172.221:8040', 695232527123742742, 790967581396828190, '[WTH] Public Server 1 & 2', '<@!425249228185534485>', True)
]
self.leaderboards = []
for leaderboard in leaderboards:
inst = await LeaderboardInstance.create(self.bot, *leaderboard)
self.leaderboards.append(inst)
self.print_leaderboard.start()
@tasks.loop(hours=24)
async def print_leaderboard(self):
if datetime.now().day not in RESET_ON_DAYS:
return
for lb in self.leaderboards:
try: await lb.print()
except Exception as e: print('Failed to print leaderboard %s: %s: %s' % (lb.name, e.__class__.__name__, e))
@print_leaderboard.before_loop
async def queue_start_task(self):
delay = -1
while delay < 0:
exec_at = next_update()
delay = (exec_at - datetime.now()).total_seconds()
if delay < 0: await asyncio.sleep(3600)
print(str(exec_at))
print(delay)
await asyncio.sleep(delay)
async def setup(bot):
await bot.add_cog(leaderboard(bot))