from interactions import slash_command, SlashContext, Client, slash_option, OptionType, auto_defer, Embed, check, Task, DateTrigger, listen from requests import get, post from datetime import datetime, timedelta, date from re import findall from os import environ bot = Client(token=environ["BOT_TOKEN"]) is_recurring = True owner_username = "alyssile" officer_role_suffix = "Officer" # add IDs for guilds you want the bot to register commands in guilds = [353071720342487040, 1038346577267392582] role_housel = 1149914848428294315 role_weekly = 1149914607822061599 role_tribal = 1149914662197010522 role_grandc = 1149914810486632488 role_jumboc = 1149929534129459290 role_fashio = 1212403886263115786 # role_testing = 873495029883236392 # TODO async def check_officer(ctx: SlashContext): return ctx.author.username == owner_username or any(role.name[-len(officer_role_suffix):] == officer_role_suffix for role in ctx.author.roles) #@slash_command(name="xivtimers", description="Show current timers", scopes=guilds) #@slash_option(name="clear", description="Clears the previous message from the channel", required=False, opt_type=OptionType.BOOLEAN) #@slash_option(name="recur", description="Sets up the command to refresh the embed automatically each time one of the timers expires", required=False, opt_type=OptionType.BOOLEAN) #@check(check=check_officer) #@auto_defer() #async def xivtimers_cmd(ctx: SlashContext, clear: bool=False, recur: bool=False): # global is_recurring # if is_recurring: # await ctx.send(f"There's already a recurring channel update task running... check with {owner_username}", delete_after=10, ephemeral=True) # return # await xivtimers(ctx.channel_id, clear, recur) async def xivtimers(channel_id, clear: bool=False, recur: bool=False, mention: str=""): global is_recurring channel = bot.get_channel(channel_id) now = datetime.now() data = get("https://www.xenoveritas.org/static/ffxiv/timers.json").json() embed = Embed(title="Timers", color="#eb144c") timers = {} maintenance = False #print('data["timers"]', data["timers"]) for timer in data["timers"]: if not any(label in timer for label in ["start", "end", "end_label"]): print(timer) continue if timer.get('end',0) and (now-timedelta(hours=6)).timestamp() > int(timer.get('end',0)/1000): continue end_label = timer.get("endLabel", f"") ts = datetime.fromtimestamp(int(timer.get('start',0)/1000)) if "')[1].split("<")[0] else: name = timer["name"] if "all worlds maintenance" in name.lower() and now > ts and now < datetime.fromtimestamp(int(timer.get('end',0)/1000)): maintenance = True timers["Maintenance complete"] = datetime.fromtimestamp(int(timer.get('end',0)/1000)) if now < ts: timers[name] = ts embed.add_field(name=name, value=f"Start{'s' if now.timestamp() < int(timer.get('start',0)/1000) else 'ed'} , {'runs' if 'endLabel' in timer else 'ends'} {end_label}") if maintenance: embed.title = "Timers (Maintenance)" def generate_field(name: str, hour: int, role: int=None, day: int=None): nonlocal timers, now if (day is not None and now.weekday() == day) and now.hour >= hour: _now = now + timedelta(1) elif now.hour >= hour: _now = now + timedelta(1) else: _now = now reset = datetime.combine(_now, datetime.min.time())+timedelta(hours=hour) if day is not None: reset += timedelta((day-_now.weekday())%7) timers[f"<@&{role}>"] = reset return {"name": name, "value": f"", "inline": True} # embed.add_field(name="Patch 6.5", value=f"") if not maintenance: housing_start_date = datetime(2022,5,27,1,0) if now.hour >= 1: _now = now+timedelta(1) else: _now = now mod = (_now - housing_start_date).days % 9 house_reset = datetime.combine(_now, datetime.min.time())+timedelta(abs(mod-5 if mod <= 5 else mod-9))+timedelta(hours=1) timers[f"<@&{role_housel}>"] = house_reset embed.add_field(name="Housing " + ("Results ending" if mod > 5 else "Lottery ending"), value=f"", inline=True) embed.add_field(**generate_field("Weekly Reset", 19, day=1, role=role_weekly)) embed.add_field(**generate_field("Fashion Report Judging", 19, day=4, role=role_fashio)) embed.add_field(**generate_field("Tribal/Duty Reset", 1, role=role_tribal)) embed.add_field(**generate_field("Grand Company Reset", 6, role=role_grandc)) embed.add_field(**generate_field("Jumbo Cactpot", 19, day=5, role=role_jumboc)) #print("\n".join(f"{t:%Y/%m/%d %H:%M:%S}" for t in timers.values())) async for message in channel.history(limit=2 if not is_recurring else 1): print(message) if message.author == bot.user.id: await message.delete() # timers[f"<@&{role_testing}>"] = datetime.now()+timedelta(seconds=20) # TODO _mention = mention mention, earliest = min(timers.items(), key=lambda x: x[1]) embed.add_field(name="Refreshing", value=f"", inline=True) await channel.send(content=_mention, embed=embed) print(f"Setting up timer at {earliest:%Y/%m/%d %H:%M:%S} in {channel_id}") @Task.create(DateTrigger(earliest)) async def recurring(): await xivtimers(channel_id, clear, recur, mention=mention) recurring.start() @listen() async def on_startup(): print("Bot started") await xivtimers(1063529561486270494, True, True) await (bot.get_channel("1127730623818256384")).send("xivtimers restarted") # channel = bot.get_channel("1127730623818256384") # await channel.send("Bot restarted, please run `/xivtimers clear:True recur:True` in <#1063529561486270494> (<@133057442425602048>)") bot.start()