feat(nowlist): Task profile migration.
This commit is contained in:
@@ -29,19 +29,7 @@ class NowDoingChannel(Channel):
|
|||||||
|
|
||||||
async def on_connection(self, websocket, event):
|
async def on_connection(self, websocket, event):
|
||||||
await super().on_connection(websocket, event)
|
await super().on_connection(websocket, event)
|
||||||
for task in self.cog.tasks.values():
|
await self.reload_tasklist(websocket=websocket)
|
||||||
await self.send_set(*self.task_args(task), websocket=websocket)
|
|
||||||
|
|
||||||
async def send_test_set(self):
|
|
||||||
tasks = [
|
|
||||||
(0, 'Tester0', "Testing Tasklist", True),
|
|
||||||
(1, 'Tester1', "Getting Confused", False),
|
|
||||||
(2, "Tester2", "Generating Bugs", True),
|
|
||||||
(3, "Tester3", "Fixing Bugs", False),
|
|
||||||
(4, "Tester4", "Pushing the red button", False),
|
|
||||||
]
|
|
||||||
for task in tasks:
|
|
||||||
await self.send_set(*task)
|
|
||||||
|
|
||||||
def task_args(self, task: NowListData.Task):
|
def task_args(self, task: NowListData.Task):
|
||||||
return (
|
return (
|
||||||
@@ -52,6 +40,14 @@ class NowDoingChannel(Channel):
|
|||||||
task.done_at.isoformat() if task.done_at else None,
|
task.done_at.isoformat() if task.done_at else None,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
async def reload_tasklist(self, websocket=None):
|
||||||
|
"""
|
||||||
|
Clear tasklist and re-send current tasks.
|
||||||
|
"""
|
||||||
|
await self.send_clear(websocket=websocket)
|
||||||
|
for task in self.cog.tasks.values():
|
||||||
|
await self.send_set(*self.task_args(task), websocket=websocket)
|
||||||
|
|
||||||
async def send_set(self, userid, name, task, start_at, end_at, websocket=None):
|
async def send_set(self, userid, name, task, start_at, end_at, websocket=None):
|
||||||
await self.send_event({
|
await self.send_event({
|
||||||
'type': "DO",
|
'type': "DO",
|
||||||
@@ -65,22 +61,22 @@ class NowDoingChannel(Channel):
|
|||||||
}
|
}
|
||||||
}, websocket=websocket)
|
}, websocket=websocket)
|
||||||
|
|
||||||
async def send_del(self, userid):
|
async def send_del(self, userid, websocket=None):
|
||||||
await self.send_event({
|
await self.send_event({
|
||||||
'type': "DO",
|
'type': "DO",
|
||||||
'method': "delTask",
|
'method': "delTask",
|
||||||
'args': {
|
'args': {
|
||||||
'userid': userid,
|
'userid': userid,
|
||||||
}
|
}
|
||||||
})
|
}, websocket=websocket)
|
||||||
|
|
||||||
async def send_clear(self):
|
async def send_clear(self, websocket=None):
|
||||||
await self.send_event({
|
await self.send_event({
|
||||||
'type': "DO",
|
'type': "DO",
|
||||||
'method': "clearTasks",
|
'method': "clearTasks",
|
||||||
'args': {
|
'args': {
|
||||||
}
|
}
|
||||||
})
|
}, websocket=websocket)
|
||||||
|
|
||||||
|
|
||||||
class NowDoingCog(LionCog):
|
class NowDoingCog(LionCog):
|
||||||
@@ -98,17 +94,81 @@ class NowDoingCog(LionCog):
|
|||||||
|
|
||||||
async def cog_load(self):
|
async def cog_load(self):
|
||||||
await self.data.init()
|
await self.data.init()
|
||||||
|
|
||||||
await self.load_tasks()
|
await self.load_tasks()
|
||||||
|
|
||||||
|
self.bot.get_cog('ProfileCog').add_profile_migrator(self.migrate_profiles, name='task-migrator')
|
||||||
|
|
||||||
self._load_twitch_methods(self.crocbot)
|
self._load_twitch_methods(self.crocbot)
|
||||||
self.loaded.set()
|
self.loaded.set()
|
||||||
|
|
||||||
async def cog_unload(self):
|
async def cog_unload(self):
|
||||||
self.loaded.clear()
|
self.loaded.clear()
|
||||||
self.tasks.clear()
|
self.tasks.clear()
|
||||||
|
if profiles := self.bot.get_cog('ProfileCog'):
|
||||||
|
profiles.del_profile_migrator('task-migrator')
|
||||||
self._unload_twitch_methods(self.crocbot)
|
self._unload_twitch_methods(self.crocbot)
|
||||||
|
|
||||||
|
async def migrate_profiles(self, source_profile: UserProfile, target_profile: UserProfile):
|
||||||
|
"""
|
||||||
|
Move current source task to target profile if there's room for it, otherwise annihilate
|
||||||
|
"""
|
||||||
|
await self.load_tasks()
|
||||||
|
source_task = self.tasks.pop(source_profile.profileid, None)
|
||||||
|
|
||||||
|
results = ["(Tasklist)"]
|
||||||
|
|
||||||
|
if source_task:
|
||||||
|
target_task = self.tasks.get(target_profile.profileid, None)
|
||||||
|
if target_task and (target_task.is_done or target_task.started_at < source_task.started_at):
|
||||||
|
# If target is done, remove it so we can overwrite
|
||||||
|
results.append("Removed older task from target profile.")
|
||||||
|
await target_task.delete()
|
||||||
|
target_task = None
|
||||||
|
|
||||||
|
if not target_task:
|
||||||
|
# Update source task with new profile id
|
||||||
|
await source_task.update(userid=target_profile.profileid)
|
||||||
|
target_task = source_task
|
||||||
|
await self.channel.send_set(*self.channel.task_args(target_task))
|
||||||
|
results.append("Migrated 1 currently running task from source profile.")
|
||||||
|
else:
|
||||||
|
# If there is a target task we can't overwrite, just delete the source task
|
||||||
|
await source_task.delete()
|
||||||
|
results.append("Ignoring and removing older task from source profile.")
|
||||||
|
|
||||||
|
self.tasks.pop(source_profile.profileid, None)
|
||||||
|
await self.channel.send_del(source_profile.profileid)
|
||||||
|
else:
|
||||||
|
results.append("No running task in source profile, nothing to migrate!")
|
||||||
|
|
||||||
|
return ' '.join(results)
|
||||||
|
|
||||||
|
async def user_profile_migration(self):
|
||||||
|
"""
|
||||||
|
Manual single-use migration method from the old userid format to the new profileid format.
|
||||||
|
"""
|
||||||
|
await self.load_tasks()
|
||||||
|
for userid, task in self.tasks.items():
|
||||||
|
userid = int(userid)
|
||||||
|
if userid > 100:
|
||||||
|
# Assume it is a twitch userid
|
||||||
|
profile = await UserProfile.fetch_from_twitchid(self.bot, userid)
|
||||||
|
|
||||||
|
if not profile:
|
||||||
|
# Create a new profile with this twitch user
|
||||||
|
users = await self.crocbot.fetch_users(ids=[userid])
|
||||||
|
if not users:
|
||||||
|
continue
|
||||||
|
user = users[0]
|
||||||
|
profile = await UserProfile.create_from_twitch(self.bot, user)
|
||||||
|
|
||||||
|
if not await self.data.Task.fetch(profile.profileid):
|
||||||
|
await task.update(userid=profile.profileid)
|
||||||
|
else:
|
||||||
|
await task.delete()
|
||||||
|
await self.load_tasks()
|
||||||
|
await self.channel.reload_tasklist()
|
||||||
|
|
||||||
async def cog_check(self, ctx):
|
async def cog_check(self, ctx):
|
||||||
if not self.loaded.is_set():
|
if not self.loaded.is_set():
|
||||||
await ctx.reply("Tasklists are still loading! Please wait a moment~")
|
await ctx.reply("Tasklists are still loading! Please wait a moment~")
|
||||||
@@ -127,7 +187,9 @@ class NowDoingCog(LionCog):
|
|||||||
# await self.channel.send_test_set()
|
# await self.channel.send_test_set()
|
||||||
# await ctx.send(f"Hello {ctx.author.name}! This command does something, we aren't sure what yet.")
|
# await ctx.send(f"Hello {ctx.author.name}! This command does something, we aren't sure what yet.")
|
||||||
# await ctx.send(str(list(self.tasks.items())[0]))
|
# await ctx.send(str(list(self.tasks.items())[0]))
|
||||||
|
await self.user_profile_migration()
|
||||||
await ctx.send(str(ctx.author.id))
|
await ctx.send(str(ctx.author.id))
|
||||||
|
await ctx.reply("Userid -> profile migration done.")
|
||||||
else:
|
else:
|
||||||
await ctx.send(f"Hello {ctx.author.name}! I don't think you have permission to test that.")
|
await ctx.send(f"Hello {ctx.author.name}! I don't think you have permission to test that.")
|
||||||
|
|
||||||
@@ -200,7 +262,7 @@ class NowDoingCog(LionCog):
|
|||||||
)
|
)
|
||||||
self.tasks[task.userid] = task
|
self.tasks[task.userid] = task
|
||||||
await self.channel.send_set(*self.channel.task_args(task))
|
await self.channel.send_set(*self.channel.task_args(task))
|
||||||
await ctx.send(f"Next task set, good luck!" + ' ' + prefix)
|
await ctx.send("Next task set, good luck!" + ' ' + prefix)
|
||||||
elif task:
|
elif task:
|
||||||
if task.is_done:
|
if task.is_done:
|
||||||
done_ago = strfdelta(utc_now() - task.done_at)
|
done_ago = strfdelta(utc_now() - task.done_at)
|
||||||
@@ -267,9 +329,22 @@ class NowDoingCog(LionCog):
|
|||||||
profile = await self.bot.get_cog('ProfileCog').fetch_profile_discord(ctx.author)
|
profile = await self.bot.get_cog('ProfileCog').fetch_profile_discord(ctx.author)
|
||||||
await self.done(ctx, profile)
|
await self.done(ctx, profile)
|
||||||
|
|
||||||
@commands.command()
|
@commands.command(
|
||||||
async def clear(self, ctx: commands.Context):
|
name='clear',
|
||||||
userid = int(ctx.author.id)
|
)
|
||||||
|
async def twi_clear(self, ctx: commands.Context):
|
||||||
|
profile = await self.bot.get_cog('ProfileCog').fetch_profile_twitch(ctx.author)
|
||||||
|
await self.clear(ctx, profile)
|
||||||
|
|
||||||
|
@cmds.hybrid_command(
|
||||||
|
name='clear',
|
||||||
|
)
|
||||||
|
async def disc_clear(self, ctx: LionContext):
|
||||||
|
profile = await self.bot.get_cog('ProfileCog').fetch_profile_discord(ctx.author)
|
||||||
|
await self.clear(ctx, profile)
|
||||||
|
|
||||||
|
async def clear(self, ctx: commands.Context | LionContext, profile):
|
||||||
|
userid = profile.profileid
|
||||||
if task := self.tasks.pop(userid, None):
|
if task := self.tasks.pop(userid, None):
|
||||||
await task.delete()
|
await task.delete()
|
||||||
await self.channel.send_del(userid)
|
await self.channel.send_del(userid)
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ class ProfileCog(LionCog):
|
|||||||
results.append(f"Migrated {len(twitch_rows)} attached twitch account(s).")
|
results.append(f"Migrated {len(twitch_rows)} attached twitch account(s).")
|
||||||
|
|
||||||
# And then mark the old profile as migrated
|
# And then mark the old profile as migrated
|
||||||
await source_profile.update(migrated=target_profile.profileid)
|
await source_profile.profile_row.update(migrated=target_profile.profileid)
|
||||||
results.append("Marking old profile as migrated.. finished!")
|
results.append("Marking old profile as migrated.. finished!")
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user