mirror of
https://git.sr.ht/~tsileo/microblog.pub
synced 2024-12-22 05:04:27 +00:00
More work towards support moving/deleting instance
This commit is contained in:
parent
b03daf1274
commit
5f20eab3f1
7 changed files with 126 additions and 1 deletions
4
Makefile
4
Makefile
|
@ -17,3 +17,7 @@ update:
|
||||||
.PHONY: prune-old-data
|
.PHONY: prune-old-data
|
||||||
prune-old-data:
|
prune-old-data:
|
||||||
-docker run --volume `pwd`/data:/app/data --volume `pwd`/app/static:/app/app/static microblogpub/microblogpub inv prune-old-data
|
-docker run --volume `pwd`/data:/app/data --volume `pwd`/app/static:/app/app/static microblogpub/microblogpub inv 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)
|
||||||
|
|
|
@ -9,6 +9,7 @@ from loguru import logger
|
||||||
from markdown import markdown
|
from markdown import markdown
|
||||||
|
|
||||||
from app import config
|
from app import config
|
||||||
|
from app.config import ALSO_KNOWN_AS
|
||||||
from app.config import AP_CONTENT_TYPE # noqa: F401
|
from app.config import AP_CONTENT_TYPE # noqa: F401
|
||||||
from app.httpsig import auth
|
from app.httpsig import auth
|
||||||
from app.key import get_pubkey_as_pem
|
from app.key import get_pubkey_as_pem
|
||||||
|
@ -126,6 +127,9 @@ ME = {
|
||||||
"tag": _LOCAL_ACTOR_TAGS,
|
"tag": _LOCAL_ACTOR_TAGS,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ALSO_KNOWN_AS:
|
||||||
|
ME["alsoKnownAs"] = [ALSO_KNOWN_AS]
|
||||||
|
|
||||||
|
|
||||||
class NotAnObjectError(Exception):
|
class NotAnObjectError(Exception):
|
||||||
def __init__(self, url: str, resp: httpx.Response | None = None) -> None:
|
def __init__(self, url: str, resp: httpx.Response | None = None) -> None:
|
||||||
|
|
|
@ -87,6 +87,7 @@ class Config(pydantic.BaseModel):
|
||||||
blocked_servers: list[_BlockedServer] = []
|
blocked_servers: list[_BlockedServer] = []
|
||||||
custom_footer: str | None = None
|
custom_footer: str | None = None
|
||||||
emoji: str | None = None
|
emoji: str | None = None
|
||||||
|
also_known_as: str | None = None
|
||||||
|
|
||||||
inbox_retention_days: int = 15
|
inbox_retention_days: int = 15
|
||||||
|
|
||||||
|
@ -135,6 +136,7 @@ if CONFIG.privacy_replace:
|
||||||
PRIVACY_REPLACE = {pr.domain: pr.replace_by for pr in CONFIG.privacy_replace}
|
PRIVACY_REPLACE = {pr.domain: pr.replace_by for pr in CONFIG.privacy_replace}
|
||||||
|
|
||||||
BLOCKED_SERVERS = {blocked_server.hostname for blocked_server in CONFIG.blocked_servers}
|
BLOCKED_SERVERS = {blocked_server.hostname for blocked_server in CONFIG.blocked_servers}
|
||||||
|
ALSO_KNOWN_AS = CONFIG.also_known_as
|
||||||
|
|
||||||
INBOX_RETENTION_DAYS = CONFIG.inbox_retention_days
|
INBOX_RETENTION_DAYS = CONFIG.inbox_retention_days
|
||||||
CUSTOM_FOOTER = (
|
CUSTOM_FOOTER = (
|
||||||
|
|
|
@ -251,6 +251,7 @@ async def index(
|
||||||
page: int | None = None,
|
page: int | None = None,
|
||||||
) -> templates.TemplateResponse | ActivityPubResponse:
|
) -> templates.TemplateResponse | ActivityPubResponse:
|
||||||
if is_activitypub_requested(request):
|
if is_activitypub_requested(request):
|
||||||
|
|
||||||
return ActivityPubResponse(LOCAL_ACTOR.ap_actor)
|
return ActivityPubResponse(LOCAL_ACTOR.ap_actor)
|
||||||
|
|
||||||
page = page or 1
|
page = page or 1
|
||||||
|
|
|
@ -29,6 +29,7 @@ async def webfinger(
|
||||||
|
|
||||||
is_404 = False
|
is_404 = False
|
||||||
|
|
||||||
|
resp: httpx.Response | None = None
|
||||||
async with httpx.AsyncClient() as client:
|
async with httpx.AsyncClient() as client:
|
||||||
for i, proto in enumerate(protos):
|
for i, proto in enumerate(protos):
|
||||||
try:
|
try:
|
||||||
|
@ -59,7 +60,10 @@ async def webfinger(
|
||||||
if is_404:
|
if is_404:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
if resp:
|
||||||
return resp.json()
|
return resp.json()
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
async def get_remote_follow_template(resource: str) -> str | None:
|
async def get_remote_follow_template(resource: str) -> str | None:
|
||||||
|
|
|
@ -235,6 +235,42 @@ All the data generated by the server is located in the `data/` directory:
|
||||||
|
|
||||||
Restoring is as easy as adding your backed up `data/` directory into a fresh deployment.
|
Restoring is as easy as adding your backed up `data/` directory into a fresh deployment.
|
||||||
|
|
||||||
|
## Moving from another instance
|
||||||
|
|
||||||
|
If you want to move followers from your existing account, ensure it is supported in your software documentation.
|
||||||
|
|
||||||
|
For [Mastodon you can look at Moving or leaving accounts](https://docs.joinmastodon.org/user/moving/).
|
||||||
|
|
||||||
|
First you need to grab the "ActivityPub actor URL" for your existing account:
|
||||||
|
|
||||||
|
### Python edition
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# For a Python install
|
||||||
|
poetry run inv webfinger username@domain.tld
|
||||||
|
```
|
||||||
|
|
||||||
|
Edit the config.
|
||||||
|
|
||||||
|
### Docker edition
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# For a Docker install
|
||||||
|
make account=username@domain.tld webfinger
|
||||||
|
```
|
||||||
|
|
||||||
|
Edit the config.
|
||||||
|
|
||||||
|
#### Edit the config
|
||||||
|
|
||||||
|
And add a reference to your old/existing account in `profile.toml`:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
also_known_as = "my@old-account.com"
|
||||||
|
```
|
||||||
|
|
||||||
|
Restart the server, and you should be able to complete the move from your existing account.
|
||||||
|
|
||||||
## Tasks
|
## Tasks
|
||||||
|
|
||||||
### Pruning old data
|
### Pruning old data
|
||||||
|
@ -280,3 +316,48 @@ make prune-old-data
|
||||||
docker compose up -d
|
docker compose up -d
|
||||||
rm data/microblogpub.db.bak
|
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/)).
|
||||||
|
|
||||||
|
Execute the Move task:
|
||||||
|
|
||||||
|
#### Python edition
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# For a Python install
|
||||||
|
poetry run inv move username@domain.tld
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Docker edition
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# For a Docker install
|
||||||
|
make account=username@domain.tld move
|
||||||
|
```
|
||||||
|
|
||||||
|
### Deleting the instance
|
||||||
|
|
||||||
|
**This section is just a draft.**
|
||||||
|
|
||||||
|
You want to delete your instance, you can request other instances to delete your remote profile.
|
||||||
|
Once deleted, you won't be able to use your instance anymore.
|
||||||
|
|
||||||
|
#### Python edition
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# For a Python install
|
||||||
|
poetry run inv self-destruct
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Docker edition
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# For a Docker install
|
||||||
|
make self-destruct
|
||||||
|
```
|
||||||
|
|
29
tasks.py
29
tasks.py
|
@ -190,6 +190,35 @@ def prune_old_data(ctx):
|
||||||
asyncio.run(run_prune_old_data())
|
asyncio.run(run_prune_old_data())
|
||||||
|
|
||||||
|
|
||||||
|
@task
|
||||||
|
def webfinger(ctx, account):
|
||||||
|
# type: (Context, str) -> None
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
from loguru import logger
|
||||||
|
|
||||||
|
from app.source import _MENTION_REGEX
|
||||||
|
from app.webfinger import get_actor_url
|
||||||
|
|
||||||
|
logger.disable("app")
|
||||||
|
if not account.startswith("@"):
|
||||||
|
account = f"@{account}"
|
||||||
|
if not _MENTION_REGEX.match(account):
|
||||||
|
print(f"Invalid acccount {account}")
|
||||||
|
return
|
||||||
|
|
||||||
|
print(f"Resolving {account}")
|
||||||
|
try:
|
||||||
|
maybe_actor_url = asyncio.run(get_actor_url(account))
|
||||||
|
if maybe_actor_url:
|
||||||
|
print(f"SUCCESS: {maybe_actor_url}")
|
||||||
|
else:
|
||||||
|
print(f"ERROR: Failed to resolve {account}")
|
||||||
|
except Exception as exc:
|
||||||
|
print(f"ERROR: Failed to resolve {account}")
|
||||||
|
print("".join(traceback.format_exception(exc)))
|
||||||
|
|
||||||
|
|
||||||
@task
|
@task
|
||||||
def yunohost_config(
|
def yunohost_config(
|
||||||
ctx,
|
ctx,
|
||||||
|
|
Loading…
Reference in a new issue