mirror of
https://git.pleroma.social/pleroma/relay.git
synced 2024-11-09 18:08:00 +00:00
Compare commits
7 commits
65b6c0a5ad
...
dec7c6a674
Author | SHA1 | Date | |
---|---|---|---|
dec7c6a674 | |||
b1a2989ba7 | |||
fd0b9fb723 | |||
ffed955ab3 | |||
71de40dfca | |||
7064adb000 | |||
437075e512 |
|
@ -5,7 +5,7 @@ ENV DOCKER_RUNNING=true
|
||||||
|
|
||||||
# setup various container properties
|
# setup various container properties
|
||||||
VOLUME ["/data"]
|
VOLUME ["/data"]
|
||||||
CMD ["python3", "-m", "relay"]
|
CMD ["python3", "-m", "relay", "run"]
|
||||||
EXPOSE 8080/tcp
|
EXPOSE 8080/tcp
|
||||||
WORKDIR /opt/activityrelay
|
WORKDIR /opt/activityrelay
|
||||||
|
|
||||||
|
|
17
relay/dev.py → dev.py
Normal file → Executable file
17
relay/dev.py → dev.py
Normal file → Executable file
|
@ -1,3 +1,4 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
import click
|
import click
|
||||||
import platform
|
import platform
|
||||||
import shutil
|
import shutil
|
||||||
|
@ -7,12 +8,10 @@ import time
|
||||||
|
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from relay import __version__, logger as logging
|
||||||
from tempfile import TemporaryDirectory
|
from tempfile import TemporaryDirectory
|
||||||
from typing import Sequence
|
from typing import Sequence
|
||||||
|
|
||||||
from . import __version__
|
|
||||||
from . import logger as logging
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from watchdog.observers import Observer
|
from watchdog.observers import Observer
|
||||||
from watchdog.events import PatternMatchingEventHandler
|
from watchdog.events import PatternMatchingEventHandler
|
||||||
|
@ -22,8 +21,7 @@ except ImportError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
SCRIPT = Path(__file__).parent
|
REPO = Path(__file__).parent
|
||||||
REPO = SCRIPT.parent
|
|
||||||
IGNORE_EXT = {
|
IGNORE_EXT = {
|
||||||
'.py',
|
'.py',
|
||||||
'.pyc'
|
'.pyc'
|
||||||
|
@ -58,8 +56,8 @@ def cli_lint(path: Path, strict: bool, watch: bool) -> None:
|
||||||
handle_run_watcher([sys.executable, "-m", "relay.dev", "lint", str(path)], wait = True)
|
handle_run_watcher([sys.executable, "-m", "relay.dev", "lint", str(path)], wait = True)
|
||||||
return
|
return
|
||||||
|
|
||||||
flake8 = [sys.executable, '-m', 'flake8', str(path)]
|
flake8 = [sys.executable, '-m', 'flake8', "dev.py", str(path)]
|
||||||
mypy = [sys.executable, '-m', 'mypy', str(path)]
|
mypy = [sys.executable, '-m', 'mypy', "dev.py", str(path)]
|
||||||
|
|
||||||
if strict:
|
if strict:
|
||||||
mypy.append('--strict')
|
mypy.append('--strict')
|
||||||
|
@ -108,7 +106,7 @@ def cli_build():
|
||||||
cmd.append('--console')
|
cmd.append('--console')
|
||||||
|
|
||||||
# putting the spec path on a different drive than the source dir breaks
|
# putting the spec path on a different drive than the source dir breaks
|
||||||
if str(SCRIPT)[0] == tmp[0]:
|
if str(REPO)[0] == tmp[0]:
|
||||||
cmd.extend(['--specpath', tmp])
|
cmd.extend(['--specpath', tmp])
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
@ -136,7 +134,7 @@ def handle_run_watcher(*commands: Sequence[str], wait: bool = False):
|
||||||
handler.run_procs()
|
handler.run_procs()
|
||||||
|
|
||||||
watcher = Observer()
|
watcher = Observer()
|
||||||
watcher.schedule(handler, str(SCRIPT), recursive=True)
|
watcher.schedule(handler, str(REPO), recursive=True)
|
||||||
watcher.start()
|
watcher.start()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -151,7 +149,6 @@ def handle_run_watcher(*commands: Sequence[str], wait: bool = False):
|
||||||
watcher.join()
|
watcher.join()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class WatchHandler(PatternMatchingEventHandler):
|
class WatchHandler(PatternMatchingEventHandler):
|
||||||
patterns = ['*.py']
|
patterns = ['*.py']
|
||||||
|
|
23
docker.sh
23
docker.sh
|
@ -2,9 +2,21 @@
|
||||||
|
|
||||||
case $1 in
|
case $1 in
|
||||||
install)
|
install)
|
||||||
|
if [[ -z ${2#$} ]]; then
|
||||||
|
host=127.0.0.1
|
||||||
|
else
|
||||||
|
host=$2
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z ${3#$} ]]; then
|
||||||
|
port=8080
|
||||||
|
else
|
||||||
|
port=$3
|
||||||
|
fi
|
||||||
|
|
||||||
docker build -f Dockerfile -t activityrelay . && \
|
docker build -f Dockerfile -t activityrelay . && \
|
||||||
docker volume create activityrelay-data && \
|
docker volume create activityrelay-data && \
|
||||||
docker run -it -p 8080:8080 -v activityrelay-data:/data --name activityrelay activityrelay
|
docker run -it -p target=8080,published=${host}:${port} -v activityrelay-data:/data --name activityrelay activityrelay
|
||||||
;;
|
;;
|
||||||
|
|
||||||
uninstall)
|
uninstall)
|
||||||
|
@ -22,6 +34,10 @@ case $1 in
|
||||||
docker stop activityrelay
|
docker stop activityrelay
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
restart)
|
||||||
|
docker restart activityrelay
|
||||||
|
;;
|
||||||
|
|
||||||
manage)
|
manage)
|
||||||
shift
|
shift
|
||||||
docker exec -it activityrelay python3 -m relay "$@"
|
docker exec -it activityrelay python3 -m relay "$@"
|
||||||
|
@ -61,10 +77,7 @@ case $1 in
|
||||||
printf "$COLS" "- edit" "Edit the relay's config in \$EDITOR"
|
printf "$COLS" "- edit" "Edit the relay's config in \$EDITOR"
|
||||||
printf "$COLS" "- shell" "Drop into a bash shell on the running container"
|
printf "$COLS" "- shell" "Drop into a bash shell on the running container"
|
||||||
printf "$COLS" "- rescue" "Drop into a bash shell on a temp container with the data volume mounted"
|
printf "$COLS" "- rescue" "Drop into a bash shell on a temp container with the data volume mounted"
|
||||||
printf "$COLS" "- install" "Build the image, create a new container and volume, and run relay setup"
|
printf "$COLS" "- install [address] [port]" "Build the image, create a new container and volume, and run relay setup"
|
||||||
printf "$COLS" "- uninstall" "Delete the relay image, container, and volume"
|
printf "$COLS" "- uninstall" "Delete the relay image, container, and volume"
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "Note: This script may not work. It is recommended to manually install and manage the container if you know what you're doing."
|
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
|
@ -154,6 +154,8 @@ When enabled, instances that try to follow the relay will have to be manually ap
|
||||||
|
|
||||||
Maximum level of messages to log.
|
Maximum level of messages to log.
|
||||||
|
|
||||||
|
Note: Changing this setting via CLI does not actually take effect until restart.
|
||||||
|
|
||||||
Valid values: `DEBUG`, `VERBOSE`, `INFO`, `WARNING`, `ERROR`, `CRITICAL`
|
Valid values: `DEBUG`, `VERBOSE`, `INFO`, `WARNING`, `ERROR`, `CRITICAL`
|
||||||
|
|
||||||
log-level: INFO
|
log-level: INFO
|
||||||
|
|
|
@ -13,9 +13,9 @@ the [official pipx docs](https://pypa.github.io/pipx/installation/) for more in-
|
||||||
|
|
||||||
python3 -m pip install pipx
|
python3 -m pip install pipx
|
||||||
|
|
||||||
Now simply install ActivityRelay directly from git
|
Now simply install ActivityRelay from pypi
|
||||||
|
|
||||||
pipx install git+https://git.pleroma.social/pleroma/relay@0.3.0
|
pipx install activityrelay
|
||||||
|
|
||||||
Or from a cloned git repo.
|
Or from a cloned git repo.
|
||||||
|
|
||||||
|
@ -36,10 +36,9 @@ be installed via [pyenv](https://github.com/pyenv/pyenv).
|
||||||
|
|
||||||
## Pip
|
## Pip
|
||||||
|
|
||||||
The instructions for installation via pip are very similar to pipx. Installation can be done from
|
The instructions for installation via pip are very similar to pipx
|
||||||
git
|
|
||||||
|
|
||||||
python3 -m pip install git+https://git.pleroma.social/pleroma/relay@0.3.0
|
python3 -m pip install activityrelay
|
||||||
|
|
||||||
or a cloned git repo.
|
or a cloned git repo.
|
||||||
|
|
||||||
|
@ -58,10 +57,11 @@ And start the relay when finished
|
||||||
|
|
||||||
Installation and management via Docker can be handled with the `docker.sh` script. To install
|
Installation and management via Docker can be handled with the `docker.sh` script. To install
|
||||||
ActivityRelay, run the install command. Once the image is built and the container is created,
|
ActivityRelay, run the install command. Once the image is built and the container is created,
|
||||||
your will be asked to fill out some config options for your relay.
|
you will be asked to fill out some config options for your relay. An address and port can be
|
||||||
|
specified to change what the relay listens on.
|
||||||
|
|
||||||
./docker.sh install
|
./docker.sh install 0.0.0.0 6942
|
||||||
|
|
||||||
Finally start it up. It will be listening on TCP port 8080.
|
Finally start it up. It will be listening on TCP localhost:8080 by default.
|
||||||
|
|
||||||
./docker.sh start
|
./docker.sh start
|
||||||
|
|
|
@ -55,7 +55,7 @@ class Application(web.Application):
|
||||||
DEFAULT: Application | None = None
|
DEFAULT: Application | None = None
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, cfgpath: str | None, dev: bool = False):
|
def __init__(self, cfgpath: Path | None, dev: bool = False):
|
||||||
web.Application.__init__(self,
|
web.Application.__init__(self,
|
||||||
middlewares = [
|
middlewares = [
|
||||||
handle_api_path,
|
handle_api_path,
|
||||||
|
|
|
@ -33,7 +33,7 @@ else:
|
||||||
DOCKER_VALUES = {
|
DOCKER_VALUES = {
|
||||||
'listen': '0.0.0.0',
|
'listen': '0.0.0.0',
|
||||||
'port': 8080,
|
'port': 8080,
|
||||||
'sq_path': '/data/relay.jsonld'
|
'sq_path': '/data/relay.sqlite3'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ class Config:
|
||||||
rd_prefix: str = 'activityrelay'
|
rd_prefix: str = 'activityrelay'
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, path: str | None = None, load: bool = False):
|
def __init__(self, path: Path | None = None, load: bool = False):
|
||||||
self.path = Config.get_config_dir(path)
|
self.path = Config.get_config_dir(path)
|
||||||
self.reset()
|
self.reset()
|
||||||
|
|
||||||
|
@ -92,9 +92,12 @@ class Config:
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_config_dir(path: str | None = None) -> Path:
|
def get_config_dir(path: Path | str | None = None) -> Path:
|
||||||
if path:
|
if isinstance(path, str):
|
||||||
return Path(path).expanduser().resolve()
|
path = Path(path)
|
||||||
|
|
||||||
|
if path is not None:
|
||||||
|
return path.expanduser().resolve()
|
||||||
|
|
||||||
paths = (
|
paths = (
|
||||||
Path("relay.yaml").resolve(),
|
Path("relay.yaml").resolve(),
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import Crypto
|
|
||||||
import aputils
|
import aputils
|
||||||
import asyncio
|
import asyncio
|
||||||
import click
|
import click
|
||||||
|
import json
|
||||||
import os
|
import os
|
||||||
import platform
|
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
@ -32,31 +31,44 @@ def check_alphanumeric(text: str) -> str:
|
||||||
return text
|
return text
|
||||||
|
|
||||||
|
|
||||||
@click.group('cli', context_settings={'show_default': True}, invoke_without_command=True)
|
@click.group('cli', context_settings = {'show_default': True})
|
||||||
@click.option('--config', '-c', help='path to the relay\'s config')
|
@click.option('--config', '-c', type = Path, help = 'path to the relay\'s config')
|
||||||
@click.version_option(version=__version__, prog_name='ActivityRelay')
|
@click.version_option(version = __version__, prog_name = 'ActivityRelay')
|
||||||
@click.pass_context
|
@click.pass_context
|
||||||
def cli(ctx: click.Context, config: str | None) -> None:
|
def cli(ctx: click.Context, config: Path | None) -> None:
|
||||||
|
if IS_DOCKER:
|
||||||
|
config = Path("/data/relay.yaml")
|
||||||
|
|
||||||
|
# The database was named "relay.jsonld" even though it's an sqlite file. Fix it.
|
||||||
|
db = Path('/data/relay.sqlite3')
|
||||||
|
wrongdb = Path('/data/relay.jsonld')
|
||||||
|
|
||||||
|
if wrongdb.exists() and not db.exists():
|
||||||
|
try:
|
||||||
|
with wrongdb.open('rb') as fd:
|
||||||
|
json.load(fd)
|
||||||
|
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
wrongdb.rename(db)
|
||||||
|
|
||||||
ctx.obj = Application(config)
|
ctx.obj = Application(config)
|
||||||
|
|
||||||
if not ctx.invoked_subcommand:
|
|
||||||
if ctx.obj.config.domain.endswith('example.com'):
|
|
||||||
cli_setup.callback() # type: ignore
|
|
||||||
|
|
||||||
else:
|
|
||||||
click.echo(
|
|
||||||
'[DEPRECATED] Running the relay without the "run" command will be removed in the ' +
|
|
||||||
'future.'
|
|
||||||
)
|
|
||||||
|
|
||||||
cli_run.callback() # type: ignore
|
|
||||||
|
|
||||||
|
|
||||||
@cli.command('setup')
|
@cli.command('setup')
|
||||||
|
@click.option('--skip-questions', '-s', is_flag = True, help = 'Just setup the database')
|
||||||
@click.pass_context
|
@click.pass_context
|
||||||
def cli_setup(ctx: click.Context) -> None:
|
def cli_setup(ctx: click.Context, skip_questions: bool) -> None:
|
||||||
'Generate a new config and create the database'
|
'Generate a new config and create the database'
|
||||||
|
|
||||||
|
if ctx.obj.signer is not None:
|
||||||
|
if not click.prompt('The database is already setup. Are you sure you want to continue?'):
|
||||||
|
return
|
||||||
|
|
||||||
|
if skip_questions and ctx.obj.config.domain.endswith('example.com'):
|
||||||
|
click.echo('You cannot skip the questions if the relay is not configured yet')
|
||||||
|
return
|
||||||
|
|
||||||
|
if not skip_questions:
|
||||||
while True:
|
while True:
|
||||||
ctx.obj.config.domain = click.prompt(
|
ctx.obj.config.domain = click.prompt(
|
||||||
'What domain will the relay be hosted on?',
|
'What domain will the relay be hosted on?',
|
||||||
|
@ -86,7 +98,7 @@ def cli_setup(ctx: click.Context) -> None:
|
||||||
type = click.Choice(['postgres', 'sqlite'], case_sensitive = False)
|
type = click.Choice(['postgres', 'sqlite'], case_sensitive = False)
|
||||||
)
|
)
|
||||||
|
|
||||||
if ctx.obj.config.db_type == 'sqlite':
|
if ctx.obj.config.db_type == 'sqlite' and not IS_DOCKER:
|
||||||
ctx.obj.config.sq_path = click.prompt(
|
ctx.obj.config.sq_path = click.prompt(
|
||||||
'Where should the database be stored?',
|
'Where should the database be stored?',
|
||||||
default = ctx.obj.config.sq_path
|
default = ctx.obj.config.sq_path
|
||||||
|
@ -174,7 +186,11 @@ def cli_setup(ctx: click.Context) -> None:
|
||||||
for key, value in config.items():
|
for key, value in config.items():
|
||||||
conn.put_config(key, value)
|
conn.put_config(key, value)
|
||||||
|
|
||||||
if not IS_DOCKER and click.confirm('Relay all setup! Would you like to run it now?'):
|
if IS_DOCKER:
|
||||||
|
click.echo("Relay all setup! Start the container to run the relay.")
|
||||||
|
return
|
||||||
|
|
||||||
|
if click.confirm('Relay all setup! Would you like to run it now?'):
|
||||||
cli_run.callback() # type: ignore
|
cli_run.callback() # type: ignore
|
||||||
|
|
||||||
|
|
||||||
|
@ -184,28 +200,13 @@ def cli_setup(ctx: click.Context) -> None:
|
||||||
def cli_run(ctx: click.Context, dev: bool = False) -> None:
|
def cli_run(ctx: click.Context, dev: bool = False) -> None:
|
||||||
'Run the relay'
|
'Run the relay'
|
||||||
|
|
||||||
if ctx.obj.config.domain.endswith('example.com') or not ctx.obj.signer:
|
if ctx.obj.config.domain.endswith('example.com') or ctx.obj.signer is None:
|
||||||
click.echo(
|
if not IS_DOCKER:
|
||||||
'Relay is not set up. Please edit your relay config or run "activityrelay setup".'
|
click.echo('Relay is not set up. Please run "activityrelay setup".')
|
||||||
)
|
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
vers_split = platform.python_version().split('.')
|
cli_setup.callback() # type: ignore
|
||||||
pip_command = 'pip3 uninstall pycrypto && pip3 install pycryptodome'
|
|
||||||
|
|
||||||
if Crypto.__version__ == '2.6.1':
|
|
||||||
if int(vers_split[1]) > 7:
|
|
||||||
click.echo(
|
|
||||||
'Error: PyCrypto is broken on Python 3.8+. Please replace it with pycryptodome ' +
|
|
||||||
'before running again. Exiting...'
|
|
||||||
)
|
|
||||||
|
|
||||||
click.echo(pip_command)
|
|
||||||
return
|
|
||||||
|
|
||||||
click.echo('Warning: PyCrypto is old and should be replaced with pycryptodome')
|
|
||||||
click.echo(pip_command)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
ctx.obj['dev'] = dev
|
ctx.obj['dev'] = dev
|
||||||
|
|
Loading…
Reference in a new issue