diff --git a/Makefile b/Makefile index de85ec5..9671a4c 100644 --- a/Makefile +++ b/Makefile @@ -21,3 +21,7 @@ prune-old-data: .PHONY: webfinger webfinger: -docker run --volume `pwd`/data:/app/data --volume `pwd`/app/static:/app/app/static microblogpub/microblogpub inv webfinger $(account) + +.PHONY: move-to +move-to: + -docker run --volume `pwd`/data:/app/data --volume `pwd`/app/static:/app/app/static microblogpub/microblogpub inv move-to $(account) diff --git a/docs/user_guide.md b/docs/user_guide.md index 1b300bc..da1c472 100644 --- a/docs/user_guide.md +++ b/docs/user_guide.md @@ -319,8 +319,6 @@ rm data/microblogpub.db.bak ### Moving to another instance -**This section is just a draft.** - If you want to migrate to another instance, you have the ability to move your existing followers to your new account. Your new account should reference the existing one, refer to your software configuration (for example [Moving or leaving accounts from the Mastodon doc](https://docs.joinmastodon.org/user/moving/)). @@ -331,14 +329,14 @@ Execute the Move task: ```bash # For a Python install -poetry run inv move username@domain.tld +poetry run inv move-to username@domain.tld ``` #### Docker edition ```bash # For a Docker install -make account=username@domain.tld move +make account=username@domain.tld move-to ``` ### Deleting the instance diff --git a/tasks.py b/tasks.py index 8f6f209..512240e 100644 --- a/tasks.py +++ b/tasks.py @@ -219,6 +219,58 @@ def webfinger(ctx, account): print("".join(traceback.format_exception(exc))) +@task +def move_to(ctx, moved_to): + # type: (Context, str) -> None + import traceback + + from loguru import logger + + from app.actor import LOCAL_ACTOR + from app.actor import fetch_actor + from app.boxes import send_move + from app.database import async_session + from app.source import _MENTION_REGEX + from app.webfinger import get_actor_url + + logger.disable("app") + + if not moved_to.startswith("@"): + moved_to = f"@{moved_to}" + if not _MENTION_REGEX.match(moved_to): + print(f"Invalid acccount {moved_to}") + return + + async def _send_move(): + print(f"Initiating move to {moved_to}") + async with async_session() as db_session: + try: + moved_to_actor_id = await get_actor_url(moved_to) + except Exception as exc: + print(f"ERROR: Failed to resolve {moved_to}") + print("".join(traceback.format_exception(exc))) + return + + if not moved_to_actor_id: + print("ERROR: Failed to resolve {moved_to}") + return + + new_actor = await fetch_actor(db_session, moved_to_actor_id) + + if LOCAL_ACTOR.ap_id not in new_actor.ap_actor.get("alsoKnownAs", []): + print( + f"{new_actor.handle}/{moved_to_actor_id} is missing " + f"{LOCAL_ACTOR.ap_id} in alsoKnownAs" + ) + return + + await send_move(db_session, moved_to) + + print("Done") + + asyncio.run(_send_move()) + + @task def yunohost_config( ctx,