feat: Add daily rank tracking for Discord friends TUN-143
This commit is contained in:
parent
f9ce233099
commit
a697a6e636
@ -7,6 +7,8 @@ import utils
|
|||||||
|
|
||||||
import sentry_sdk
|
import sentry_sdk
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
|
||||||
sentry_sdk.init(
|
sentry_sdk.init(
|
||||||
dsn="https://272f1e4ecb3847ac8d24be796515e558@o4506942768021504.ingest.us.sentry.io/4506986058743808",
|
dsn="https://272f1e4ecb3847ac8d24be796515e558@o4506942768021504.ingest.us.sentry.io/4506986058743808",
|
||||||
)
|
)
|
||||||
@ -127,10 +129,36 @@ async def activate_friend(ctx, steam_id):
|
|||||||
async def heartbeat():
|
async def heartbeat():
|
||||||
utils.heartbeat()
|
utils.heartbeat()
|
||||||
|
|
||||||
|
@tasks.loop(hours=24)
|
||||||
|
async def check_rank_changes(channel):
|
||||||
|
logger.info("Checking for rank changes")
|
||||||
|
try:
|
||||||
|
data = await dota.check_rank_changes_for_discord()
|
||||||
|
if data:
|
||||||
|
logger.info(f"Sending rank changes: {data}")
|
||||||
|
await channel.send(content=data['content'], embeds=[discord.Embed.from_dict(embed) for embed in data['embeds']])
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error checking rank changes: {e}")
|
||||||
|
sentry_sdk.capture_exception(e)
|
||||||
|
|
||||||
@bot.event
|
@bot.event
|
||||||
async def on_ready():
|
async def on_ready():
|
||||||
channel = bot.get_channel(channel_id)
|
channel = bot.get_channel(channel_id)
|
||||||
send_message.start(channel)
|
send_message.start(channel)
|
||||||
heartbeat.start()
|
heartbeat.start()
|
||||||
|
|
||||||
|
# Start the rank check task and make it run at a specific time (e.g., noon)
|
||||||
|
check_rank_changes.start(channel)
|
||||||
|
|
||||||
|
# Calculate time until next noon
|
||||||
|
now = datetime.datetime.now()
|
||||||
|
target_time = now.replace(hour=21, minute=0, second=0, microsecond=0)
|
||||||
|
if now >= target_time:
|
||||||
|
target_time = target_time + datetime.timedelta(days=1)
|
||||||
|
|
||||||
|
# Adjust first run to happen at noon
|
||||||
|
seconds_until_target = (target_time - now).total_seconds()
|
||||||
|
check_rank_changes.change_interval(hours=24)
|
||||||
|
check_rank_changes.next_iteration = discord.utils.utcnow() + datetime.timedelta(seconds=seconds_until_target)
|
||||||
|
|
||||||
bot.run('MTE1MjE2NTc3NDMwNDIyMzI2Mg.GEi-17.VvuIkRy_cFD9XF6wtTagY95LKEbTxKaxy-FxGw') # 这里替换成你自己的 token
|
bot.run('MTE1MjE2NTc3NDMwNDIyMzI2Mg.GEi-17.VvuIkRy_cFD9XF6wtTagY95LKEbTxKaxy-FxGw') # 这里替换成你自己的 token
|
||||||
|
|||||||
52
dota.py
52
dota.py
@ -90,6 +90,7 @@ class Friend(BaseModel):
|
|||||||
steam_id = peewee.IntegerField(primary_key=True)
|
steam_id = peewee.IntegerField(primary_key=True)
|
||||||
name = peewee.CharField()
|
name = peewee.CharField()
|
||||||
active = peewee.BooleanField(default=True)
|
active = peewee.BooleanField(default=True)
|
||||||
|
rank_tier = peewee.IntegerField(null=True)
|
||||||
|
|
||||||
def get_recent_matches(self, limit=1):
|
def get_recent_matches(self, limit=1):
|
||||||
try:
|
try:
|
||||||
@ -98,6 +99,20 @@ class Friend(BaseModel):
|
|||||||
logger.error('fail to get player %s recent matches. error: %s' % (self.steam_id, e))
|
logger.error('fail to get player %s recent matches. error: %s' % (self.steam_id, e))
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
def update_rank_tier(self):
|
||||||
|
"""Update player's rank tier from OpenDota API"""
|
||||||
|
try:
|
||||||
|
player_info = player_client.get_players_by_account_id(self.steam_id)
|
||||||
|
if player_info and hasattr(player_info, 'rank_tier') and player_info.rank_tier:
|
||||||
|
old_rank_tier = self.rank_tier
|
||||||
|
self.rank_tier = player_info.rank_tier
|
||||||
|
self.save()
|
||||||
|
return old_rank_tier != self.rank_tier, old_rank_tier
|
||||||
|
return False, None
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f'Failed to update rank tier for player {self.steam_id}. Error: {e}')
|
||||||
|
return False, None
|
||||||
|
|
||||||
def serialize_recent_matches(self, limit=1):
|
def serialize_recent_matches(self, limit=1):
|
||||||
matches = self.get_recent_matches(limit=limit)
|
matches = self.get_recent_matches(limit=limit)
|
||||||
data = []
|
data = []
|
||||||
@ -369,3 +384,40 @@ async def serialize_match_for_discord(match_):
|
|||||||
}
|
}
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
async def check_rank_changes_for_discord():
|
||||||
|
"""Check for rank changes among all active friends and format for Discord"""
|
||||||
|
rank_changes = []
|
||||||
|
|
||||||
|
for friend in Friend.filter(active=True):
|
||||||
|
changed, old_rank_tier = friend.update_rank_tier()
|
||||||
|
if changed and friend.rank_tier is not None:
|
||||||
|
old_rank = utils.get_ranking(old_rank_tier) if old_rank_tier else "未校准"
|
||||||
|
new_rank = utils.get_ranking(friend.rank_tier)
|
||||||
|
rank_changes.append({
|
||||||
|
'name': friend.name,
|
||||||
|
'old_rank': old_rank,
|
||||||
|
'new_rank': new_rank,
|
||||||
|
'increased': friend.rank_tier > (old_rank_tier or 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
if not rank_changes:
|
||||||
|
return None
|
||||||
|
|
||||||
|
data = {
|
||||||
|
'content': '## 天梯更新',
|
||||||
|
'embeds': []
|
||||||
|
}
|
||||||
|
|
||||||
|
for change in rank_changes:
|
||||||
|
direction = "⬆️ 上升" if change['increased'] else "⬇️ 下降"
|
||||||
|
color = 6732650 if change['increased'] else 16724787 # Green if increased, red if decreased
|
||||||
|
|
||||||
|
data['embeds'].append({
|
||||||
|
'title': f"{change['name']} 的天梯等级变化",
|
||||||
|
'description': f"{direction}:{change['old_rank']} → {change['new_rank']}",
|
||||||
|
'color': color
|
||||||
|
})
|
||||||
|
|
||||||
|
return data
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user