feat(bot.py, dota.py, utils.py): 增加查询某人战绩的命令
增加查询某人战绩的命令 Signed-off-by: Ching <loooching@gmail.com>
This commit is contained in:
parent
233fa91b5b
commit
cd1fc45044
@ -40,6 +40,18 @@ async def send_message(channel):
|
||||
logger.info(f"sending match {match_['match_id']}, {data}")
|
||||
await channel.send(content=data['content'], embeds=[discord.Embed.from_dict(embed) for embed in data['embeds']])
|
||||
|
||||
@bot.command(description="获取最近战绩", name='recent_matches') # this decorator makes a slash command
|
||||
async def get_friends_recent_matches(ctx, name, match_count=5): # a slash command will be created with the name "ping"
|
||||
logger.info(f"get_friends_recent_matches {name} {match_count}")
|
||||
friends = dota.Friend.filter(name=name)
|
||||
match_count = int(match_count)
|
||||
if friends.count() == 0:
|
||||
await ctx.respond(content=f'找不到 {name} 的信息')
|
||||
return
|
||||
data = dota.Friend.serialize_recent_matches_for_discord(friends, match_count)
|
||||
await ctx.respond(content=data['content'], embeds=[discord.Embed.from_dict(embed) for embed in data['embeds']])
|
||||
|
||||
|
||||
@tasks.loop(minutes=1)
|
||||
async def heartbeat():
|
||||
utils.heartbeat()
|
||||
|
||||
81
dota.py
81
dota.py
@ -75,13 +75,77 @@ class Friend(BaseModel):
|
||||
steam_id = peewee.IntegerField(primary_key=True)
|
||||
name = peewee.CharField()
|
||||
|
||||
def get_recent_matches(self):
|
||||
def get_recent_matches(self, limit=1):
|
||||
try:
|
||||
return player_client.get_players_by_account_id_select_matches(self.steam_id, limit=1)
|
||||
return player_client.get_players_by_account_id_select_matches(self.steam_id, limit=limit)
|
||||
except:
|
||||
logger.error('fail to get player %s recent matches' % self.steam_id)
|
||||
return []
|
||||
|
||||
def serialize_recent_matches(self, limit=1):
|
||||
matches = self.get_recent_matches(limit=limit)
|
||||
data = []
|
||||
for match_ in matches:
|
||||
data.append({
|
||||
'match_id': match_.match_id,
|
||||
'win': match_.radiant_win == (match_.player_slot < 128),
|
||||
'is_radiant': match_.player_slot < 128,
|
||||
'kills': match_.kills,
|
||||
'deaths': match_.deaths,
|
||||
'assists': match_.assists,
|
||||
'party_size': match_.party_size,
|
||||
'start_time': match_.start_time,
|
||||
'duration': match_.duration,
|
||||
'average_rank': utils.get_ranking(match_.average_rank),
|
||||
'hero_id': match_.hero_id,
|
||||
})
|
||||
return data
|
||||
|
||||
@classmethod
|
||||
def serialize_recent_matches_for_discord(cls, friends, limit=5):
|
||||
# {
|
||||
# "content": "## 水哥的战报\n",
|
||||
# "embeds": [
|
||||
# {
|
||||
# "description": "3黑 00:34:23",
|
||||
# "fields": [],
|
||||
# "title": "2 杀 5 死 3 助 ",
|
||||
# "color": 6732650,
|
||||
# "url": "https://www.opendota.com/matches/7335993790",
|
||||
# "timestamp": "2023-09-12T16:00:00.000Z"
|
||||
# }
|
||||
# ],
|
||||
# }
|
||||
matches = []
|
||||
if limit > 10:
|
||||
limit = 10
|
||||
for friend in friends:
|
||||
matches.extend(friend.serialize_recent_matches(limit=limit))
|
||||
# sort matches by start_time from latest to oldest
|
||||
matches.sort(key=lambda x: x['start_time'], reverse=True)
|
||||
name = friends[0].name
|
||||
data = {
|
||||
'content': f'## {name}的战报',
|
||||
'embeds': [],
|
||||
}
|
||||
for match_ in matches[:limit]:
|
||||
duration = '%d:%02d:%02d' % utils.convert_seconds_to_hms(match_['duration'])
|
||||
if match_['party_size'] > 1:
|
||||
summary = f"{match_['party_size']}黑 {duration}"
|
||||
else:
|
||||
summary = f"单排 {duration}"
|
||||
start_time = datetime.datetime.fromtimestamp(match_['start_time']).strftime('%Y-%m-%dT%H:%M:%S.000+08:00')
|
||||
hero_name = Hero.get(hero_id=match_['hero_id']).localized_name
|
||||
data['embeds'].append({
|
||||
'title': f"{hero_name} {match_['kills']} 杀 {match_['deaths']} 死 {match_['assists']} 助 ",
|
||||
'description': summary + '\n' + match_['average_rank'],
|
||||
'color': 6732650 if match_['win'] else 16724787, # 66bb6a or FF3333
|
||||
'fields': [],
|
||||
'timestamp': start_time,
|
||||
'url': f"https://www.opendota.com/matches/{match_['match_id']}",
|
||||
})
|
||||
return data
|
||||
|
||||
|
||||
def get_friends_recent_matches():
|
||||
matches = []
|
||||
@ -98,17 +162,6 @@ def get_friends_recent_matches():
|
||||
matches.append(match_obj.serialize_match())
|
||||
return matches
|
||||
|
||||
def shorten_digits(num):
|
||||
# if num like 12345, return 1.2w
|
||||
# if num like 1234, return 1.2k
|
||||
# if num < 1000, return num
|
||||
# if result ends with 0, remove it
|
||||
if num >= 10000:
|
||||
return '%.1fw' % (num / 10000)
|
||||
elif num >= 1000:
|
||||
return '%.1fk' % (num / 1000)
|
||||
else:
|
||||
return str(num)
|
||||
|
||||
def serialize_match_for_discord(match_):
|
||||
# {
|
||||
@ -171,7 +224,7 @@ def serialize_match_for_discord(match_):
|
||||
dire_highest_damage_idx = 0
|
||||
|
||||
for player in match_['players']:
|
||||
desc = f"{player['nickname'] or player['personaname']}(Lv.**{player['level']}** {player['hero']}): **{player['kills']}** 杀 **{player['deaths']}** 死 **{player['assists']}** 助 | **{shorten_digits(player['total_gold'])}** 经济 | **{shorten_digits(player['hero_damage'])}** 伤害 "
|
||||
desc = f"{player['nickname'] or player['personaname']}(Lv.**{player['level']}** {player['hero']}): **{player['kills']}** 杀 **{player['deaths']}** 死 **{player['assists']}** 助 | **{utils.shorten_digits(player['total_gold'])}** 经济 | **{utils.shorten_digits(player['hero_damage'])}** 伤害 "
|
||||
|
||||
if player['is_radiant']:
|
||||
radiant.append(desc)
|
||||
|
||||
36
utils.py
36
utils.py
@ -30,3 +30,39 @@ def heartbeat():
|
||||
except:
|
||||
logger.error('fail to heartbeat, resp status: %s' % resp.status_code)
|
||||
pass
|
||||
|
||||
|
||||
def get_ranking(ranking_int):
|
||||
# (10-15: Herald, 20-25: Guardian, 30-35: Crusader, 40-45: Archon, 50-55: Legend, 60-65: Ancient, 70-75: Divine, 80-85: Immortal).
|
||||
stars = ranking_int % 10
|
||||
if ranking_int < 20:
|
||||
return '先锋 %s' % stars
|
||||
elif ranking_int < 30:
|
||||
return '卫士 %s' % stars
|
||||
elif ranking_int < 40:
|
||||
return '中军 %s' % stars
|
||||
elif ranking_int < 50:
|
||||
return '统帅 %s' % stars
|
||||
elif ranking_int < 60:
|
||||
return '传奇 %s' % stars
|
||||
elif ranking_int < 70:
|
||||
return '万古流芳 %s' % stars
|
||||
elif ranking_int < 80:
|
||||
return '超凡入圣 %s' % stars
|
||||
elif ranking_int < 90:
|
||||
return '不朽 %s' % stars
|
||||
else:
|
||||
return 'Unknown %s' % stars
|
||||
|
||||
|
||||
def shorten_digits(num):
|
||||
# if num like 12345, return 1.2w
|
||||
# if num like 1234, return 1.2k
|
||||
# if num < 1000, return num
|
||||
# if result ends with 0, remove it
|
||||
if num >= 10000:
|
||||
return '%.1fw' % (num / 10000)
|
||||
elif num >= 1000:
|
||||
return '%.1fk' % (num / 1000)
|
||||
else:
|
||||
return str(num)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user