amoorion 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- amoorion-0.3.0/LICENSE +21 -0
- amoorion-0.3.0/PKG-INFO +122 -0
- amoorion-0.3.0/README.md +102 -0
- amoorion-0.3.0/pyproject.toml +127 -0
- amoorion-0.3.0/pyproject.toml.orig +111 -0
- amoorion-0.3.0/src/amoorion/__init__.py +12 -0
- amoorion-0.3.0/src/amoorion/api/__init__.py +5 -0
- amoorion-0.3.0/src/amoorion/api/__main__.py +5 -0
- amoorion-0.3.0/src/amoorion/api/base.py +87 -0
- amoorion-0.3.0/src/amoorion/cli/__init__.py +5 -0
- amoorion-0.3.0/src/amoorion/cli/__main__.py +5 -0
- amoorion-0.3.0/src/amoorion/cli/base.py +140 -0
- amoorion-0.3.0/src/amoorion/cli/guide.py +141 -0
- amoorion-0.3.0/src/amoorion/core.py +86 -0
- amoorion-0.3.0/src/amoorion/daemon/__init__.py +5 -0
- amoorion-0.3.0/src/amoorion/daemon/__main__.py +5 -0
- amoorion-0.3.0/src/amoorion/daemon/base.py +62 -0
- amoorion-0.3.0/src/amoorion/hooks/__init__.py +5 -0
- amoorion-0.3.0/src/amoorion/hooks/base.py +72 -0
- amoorion-0.3.0/src/amoorion/inbox/__init__.py +5 -0
- amoorion-0.3.0/src/amoorion/inbox/base.py +81 -0
- amoorion-0.3.0/src/amoorion/mcp/__init__.py +5 -0
- amoorion-0.3.0/src/amoorion/mcp/__main__.py +5 -0
- amoorion-0.3.0/src/amoorion/mcp/base.py +62 -0
- amoorion-0.3.0/src/amoorion/methods/__init__.py +27 -0
- amoorion-0.3.0/src/amoorion/methods/base.py +175 -0
- amoorion-0.3.0/src/amoorion/models/__init__.py +5 -0
- amoorion-0.3.0/src/amoorion/models/base.py +45 -0
- amoorion-0.3.0/src/amoorion/plugins/__init__.py +16 -0
- amoorion-0.3.0/src/amoorion/plugins/base.py +83 -0
- amoorion-0.3.0/src/amoorion/plugins/dryrun/__init__.py +5 -0
- amoorion-0.3.0/src/amoorion/plugins/dryrun/base.py +38 -0
- amoorion-0.3.0/src/amoorion/plugins/http.py +57 -0
- amoorion-0.3.0/src/amoorion/vault/__init__.py +9 -0
- amoorion-0.3.0/src/amoorion/vault/base.py +69 -0
- amoorion-0.3.0/src/amoorion/vault/bw_cli.py +90 -0
- amoorion-0.3.0/src/amoorion/vault/default.py +28 -0
- amoorion-0.3.0/src/amoorion/vault/http_vault.py +55 -0
- amoorion-0.3.0/src/amoorion/vault/kpxc_db_file.py +59 -0
amoorion-0.3.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Sett Sarverott
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
amoorion-0.3.0/PKG-INFO
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: amoorion
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Universal tool for administration of chatting and communication platforms
|
|
5
|
+
Author: Sett Sarverott
|
|
6
|
+
Author-email: Sett Sarverott <sett@sarverott.com>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Requires-Dist: fastapi>=0.162.0
|
|
10
|
+
Requires-Dist: mcp[cli]>=2.3.0
|
|
11
|
+
Requires-Dist: pydantic>=2.14.1
|
|
12
|
+
Requires-Dist: python-dotenv>=1.2.4
|
|
13
|
+
Requires-Dist: requests>=2.34.2
|
|
14
|
+
Requires-Dist: rich>=15.0.0
|
|
15
|
+
Requires-Dist: uvicorn>=0.54.0
|
|
16
|
+
Requires-Dist: pykeepass>=4.2.0 ; extra == 'keepassxc'
|
|
17
|
+
Requires-Python: >=3.12
|
|
18
|
+
Provides-Extra: keepassxc
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
21
|
+
# amoorion
|
|
22
|
+
Universal tool for administration of chatting and communication platforms
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## **EARLY STAGE OF PROJECT**
|
|
27
|
+
|
|
28
|
+
The core works end to end, with plugins for Bluesky, Mastodon, X, Tumblr,
|
|
29
|
+
Blogger, Facebook, Discord (bot or webhook), Telegram and Matrix, tested
|
|
30
|
+
only against fakes of their APIs so far, not yet against real accounts. `dryrun` sends nothing, for trying.
|
|
31
|
+
Plan: [docs/devlog/VISION.md](docs/devlog/VISION.md).
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## What it will do
|
|
36
|
+
|
|
37
|
+
Write once, post everywhere, read and answer from one place, and link it
|
|
38
|
+
with the services around it.
|
|
39
|
+
|
|
40
|
+
#### Publication platforms
|
|
41
|
+
- twitter (x.com) posting by api
|
|
42
|
+
- bluesky posting
|
|
43
|
+
- tumblr posting by api
|
|
44
|
+
- blogger posting by mail
|
|
45
|
+
- facebook posting
|
|
46
|
+
- mastodon posting
|
|
47
|
+
|
|
48
|
+
#### Communication platforms
|
|
49
|
+
- discord
|
|
50
|
+
- telegram
|
|
51
|
+
- matrix
|
|
52
|
+
- ~whatsapp~
|
|
53
|
+
- ~signal~
|
|
54
|
+
|
|
55
|
+
#### Additional functionality
|
|
56
|
+
- email client
|
|
57
|
+
- ~rss feed receiver~
|
|
58
|
+
- ~phone manage by adb~
|
|
59
|
+
- webhooks - standard linkings with services like gitlab, github, discord etc.
|
|
60
|
+
- ntfy notifications
|
|
61
|
+
- nats.io
|
|
62
|
+
|
|
63
|
+
## How it is built
|
|
64
|
+
|
|
65
|
+
One core (model, view, controller) and namespaces on it: **plugins** (one
|
|
66
|
+
per platform), **methods** (what amoorion can do), and the faces that expose
|
|
67
|
+
the methods: **CLI**, **HTTP API**, **MCP** server for AI agents, and a
|
|
68
|
+
**daemon** for long-running services. Secrets come only from a **vault**
|
|
69
|
+
(Bitwarden / Vaultwarden, HashiCorp Vault / OpenBao, or a KeePassXC file);
|
|
70
|
+
`.env` holds just the link to it. Each platform is its own package in
|
|
71
|
+
`packages/` (a uv workspace). Details: [docs/structure.md](docs/structure.md), writing a plugin:
|
|
72
|
+
[docs/plugins.md](docs/plugins.md).
|
|
73
|
+
|
|
74
|
+
## Usage
|
|
75
|
+
|
|
76
|
+
```sh
|
|
77
|
+
uv sync
|
|
78
|
+
cp example.env .env # the link to the vault
|
|
79
|
+
|
|
80
|
+
uv run amoorion # asks step by step what to do (or: amoorion -i)
|
|
81
|
+
uv run amoorion plugins # platforms and what they can do
|
|
82
|
+
uv run amoorion accounts # which have their secrets in the vault
|
|
83
|
+
uv run amoorion publish --text "hello" --to dryrun bluesky
|
|
84
|
+
uv run amoorion --json read --platform bluesky
|
|
85
|
+
uv run amoorion reply --platform bluesky --to "at://…" --text "thanks"
|
|
86
|
+
uv run amoorion inbox # everything read or received so far
|
|
87
|
+
uv run task help # help of every command
|
|
88
|
+
|
|
89
|
+
uv run amoorion api # HTTP API on 127.0.0.1:8000
|
|
90
|
+
uv run amoorion mcp # MCP server (stdio) for agents
|
|
91
|
+
uv run amoorion daemon # long-running services
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
The API needs the secret `api/token` in the vault (sent as `Authorization:
|
|
95
|
+
Bearer`), and every hook its own secret; without them they refuse calls.
|
|
96
|
+
Where each backend keeps a secret: [docs/structure.md](docs/structure.md#vault).
|
|
97
|
+
Each platform's secrets are listed in its package's README, e.g.
|
|
98
|
+
[packages/amoorion-bluesky](packages/amoorion-bluesky/README.md).
|
|
99
|
+
|
|
100
|
+
Run locally first; a Dockerfile and compose come next (phase 6 of the plan).
|
|
101
|
+
|
|
102
|
+
## Development
|
|
103
|
+
|
|
104
|
+
```sh
|
|
105
|
+
uv run task init # tools, git hooks, .env, then check
|
|
106
|
+
uv run task check # tests, YAML, commit messages, docs (= CI)
|
|
107
|
+
uv run task docs:build # the docs site into docs/_build/html
|
|
108
|
+
uv run task plugin:new -- <platform> <Class> "<description>" # a new platform
|
|
109
|
+
uv run task test:live -- bluesky mastodon # one real test post on each platform named
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Examples of usage: Jupyter notebooks in [examples/](examples/)
|
|
113
|
+
(`uv run task examples:build` makes marimo notebooks and pages of them). The docs
|
|
114
|
+
(this README, the guides, the plan and an API reference generated from the
|
|
115
|
+
code) are built by Sphinx from [docs/](docs/) for Read the Docs.
|
|
116
|
+
Plan and open questions: [docs/devlog/](docs/devlog/). Guide for agents and
|
|
117
|
+
contributors: [AGENTS.md](AGENTS.md).
|
|
118
|
+
|
|
119
|
+
## License
|
|
120
|
+
|
|
121
|
+
Free, under the MIT License, © 2024–present Sett Sarverott:
|
|
122
|
+
[LICENSE](LICENSE), https://sett.mit-license.org
|
amoorion-0.3.0/README.md
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# amoorion
|
|
2
|
+
Universal tool for administration of chatting and communication platforms
|
|
3
|
+
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## **EARLY STAGE OF PROJECT**
|
|
7
|
+
|
|
8
|
+
The core works end to end, with plugins for Bluesky, Mastodon, X, Tumblr,
|
|
9
|
+
Blogger, Facebook, Discord (bot or webhook), Telegram and Matrix, tested
|
|
10
|
+
only against fakes of their APIs so far, not yet against real accounts. `dryrun` sends nothing, for trying.
|
|
11
|
+
Plan: [docs/devlog/VISION.md](docs/devlog/VISION.md).
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## What it will do
|
|
16
|
+
|
|
17
|
+
Write once, post everywhere, read and answer from one place, and link it
|
|
18
|
+
with the services around it.
|
|
19
|
+
|
|
20
|
+
#### Publication platforms
|
|
21
|
+
- twitter (x.com) posting by api
|
|
22
|
+
- bluesky posting
|
|
23
|
+
- tumblr posting by api
|
|
24
|
+
- blogger posting by mail
|
|
25
|
+
- facebook posting
|
|
26
|
+
- mastodon posting
|
|
27
|
+
|
|
28
|
+
#### Communication platforms
|
|
29
|
+
- discord
|
|
30
|
+
- telegram
|
|
31
|
+
- matrix
|
|
32
|
+
- ~whatsapp~
|
|
33
|
+
- ~signal~
|
|
34
|
+
|
|
35
|
+
#### Additional functionality
|
|
36
|
+
- email client
|
|
37
|
+
- ~rss feed receiver~
|
|
38
|
+
- ~phone manage by adb~
|
|
39
|
+
- webhooks - standard linkings with services like gitlab, github, discord etc.
|
|
40
|
+
- ntfy notifications
|
|
41
|
+
- nats.io
|
|
42
|
+
|
|
43
|
+
## How it is built
|
|
44
|
+
|
|
45
|
+
One core (model, view, controller) and namespaces on it: **plugins** (one
|
|
46
|
+
per platform), **methods** (what amoorion can do), and the faces that expose
|
|
47
|
+
the methods: **CLI**, **HTTP API**, **MCP** server for AI agents, and a
|
|
48
|
+
**daemon** for long-running services. Secrets come only from a **vault**
|
|
49
|
+
(Bitwarden / Vaultwarden, HashiCorp Vault / OpenBao, or a KeePassXC file);
|
|
50
|
+
`.env` holds just the link to it. Each platform is its own package in
|
|
51
|
+
`packages/` (a uv workspace). Details: [docs/structure.md](docs/structure.md), writing a plugin:
|
|
52
|
+
[docs/plugins.md](docs/plugins.md).
|
|
53
|
+
|
|
54
|
+
## Usage
|
|
55
|
+
|
|
56
|
+
```sh
|
|
57
|
+
uv sync
|
|
58
|
+
cp example.env .env # the link to the vault
|
|
59
|
+
|
|
60
|
+
uv run amoorion # asks step by step what to do (or: amoorion -i)
|
|
61
|
+
uv run amoorion plugins # platforms and what they can do
|
|
62
|
+
uv run amoorion accounts # which have their secrets in the vault
|
|
63
|
+
uv run amoorion publish --text "hello" --to dryrun bluesky
|
|
64
|
+
uv run amoorion --json read --platform bluesky
|
|
65
|
+
uv run amoorion reply --platform bluesky --to "at://…" --text "thanks"
|
|
66
|
+
uv run amoorion inbox # everything read or received so far
|
|
67
|
+
uv run task help # help of every command
|
|
68
|
+
|
|
69
|
+
uv run amoorion api # HTTP API on 127.0.0.1:8000
|
|
70
|
+
uv run amoorion mcp # MCP server (stdio) for agents
|
|
71
|
+
uv run amoorion daemon # long-running services
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
The API needs the secret `api/token` in the vault (sent as `Authorization:
|
|
75
|
+
Bearer`), and every hook its own secret; without them they refuse calls.
|
|
76
|
+
Where each backend keeps a secret: [docs/structure.md](docs/structure.md#vault).
|
|
77
|
+
Each platform's secrets are listed in its package's README, e.g.
|
|
78
|
+
[packages/amoorion-bluesky](packages/amoorion-bluesky/README.md).
|
|
79
|
+
|
|
80
|
+
Run locally first; a Dockerfile and compose come next (phase 6 of the plan).
|
|
81
|
+
|
|
82
|
+
## Development
|
|
83
|
+
|
|
84
|
+
```sh
|
|
85
|
+
uv run task init # tools, git hooks, .env, then check
|
|
86
|
+
uv run task check # tests, YAML, commit messages, docs (= CI)
|
|
87
|
+
uv run task docs:build # the docs site into docs/_build/html
|
|
88
|
+
uv run task plugin:new -- <platform> <Class> "<description>" # a new platform
|
|
89
|
+
uv run task test:live -- bluesky mastodon # one real test post on each platform named
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Examples of usage: Jupyter notebooks in [examples/](examples/)
|
|
93
|
+
(`uv run task examples:build` makes marimo notebooks and pages of them). The docs
|
|
94
|
+
(this README, the guides, the plan and an API reference generated from the
|
|
95
|
+
code) are built by Sphinx from [docs/](docs/) for Read the Docs.
|
|
96
|
+
Plan and open questions: [docs/devlog/](docs/devlog/). Guide for agents and
|
|
97
|
+
contributors: [AGENTS.md](AGENTS.md).
|
|
98
|
+
|
|
99
|
+
## License
|
|
100
|
+
|
|
101
|
+
Free, under the MIT License, © 2024–present Sett Sarverott:
|
|
102
|
+
[LICENSE](LICENSE), https://sett.mit-license.org
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "amoorion"
|
|
3
|
+
version = "0.3.0"
|
|
4
|
+
description = "Universal tool for administration of chatting and communication platforms"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
license-files = ["LICENSE"]
|
|
8
|
+
requires-python = ">=3.12"
|
|
9
|
+
dependencies = [
|
|
10
|
+
"fastapi>=0.162.0",
|
|
11
|
+
"mcp[cli]>=2.3.0",
|
|
12
|
+
"pydantic>=2.14.1",
|
|
13
|
+
"python-dotenv>=1.2.4",
|
|
14
|
+
"requests>=2.34.2",
|
|
15
|
+
"rich>=15.0.0",
|
|
16
|
+
"uvicorn>=0.54.0",
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
[[project.authors]]
|
|
20
|
+
name = "Sett Sarverott"
|
|
21
|
+
email = "sett@sarverott.com"
|
|
22
|
+
|
|
23
|
+
[project.scripts]
|
|
24
|
+
amoorion = "amoorion:main"
|
|
25
|
+
|
|
26
|
+
[project.entry-points."amoorion.plugins"]
|
|
27
|
+
dryrun = "amoorion.plugins.dryrun:DryRun"
|
|
28
|
+
|
|
29
|
+
[project.optional-dependencies]
|
|
30
|
+
keepassxc = ["pykeepass>=4.2.0"]
|
|
31
|
+
|
|
32
|
+
[build-system]
|
|
33
|
+
requires = ["uv_build>=0.12.20,<0.13.0"]
|
|
34
|
+
build-backend = "uv_build"
|
|
35
|
+
|
|
36
|
+
[dependency-groups]
|
|
37
|
+
dev = [
|
|
38
|
+
"amoorion-blogger",
|
|
39
|
+
"amoorion-bluesky",
|
|
40
|
+
"amoorion-dev",
|
|
41
|
+
"amoorion-discord",
|
|
42
|
+
"amoorion-facebook",
|
|
43
|
+
"amoorion-mastodon",
|
|
44
|
+
"amoorion-matrix",
|
|
45
|
+
"amoorion-telegram",
|
|
46
|
+
"amoorion-tumblr",
|
|
47
|
+
"amoorion-x",
|
|
48
|
+
"commitizen>=4.19.3",
|
|
49
|
+
"go-task-bin>=3.54.0",
|
|
50
|
+
"httpx>=0.28.1",
|
|
51
|
+
"ipykernel>=7.4.0",
|
|
52
|
+
"lefthook>=2.2.2",
|
|
53
|
+
"nbclient>=0.11.0",
|
|
54
|
+
"nbformat>=5.11.1",
|
|
55
|
+
"pykeepass>=4.2.0",
|
|
56
|
+
"pytest>=9.1.1",
|
|
57
|
+
"yamllint>=1.38.0",
|
|
58
|
+
]
|
|
59
|
+
examples = ["marimo>=0.25.2"]
|
|
60
|
+
|
|
61
|
+
[tool.commitizen]
|
|
62
|
+
name = "cz_conventional_commits"
|
|
63
|
+
version_provider = "uv"
|
|
64
|
+
tag_format = "v$version"
|
|
65
|
+
major_version_zero = true
|
|
66
|
+
version_files = [
|
|
67
|
+
"packages/amoorion-blogger/pyproject.toml:^version",
|
|
68
|
+
"packages/amoorion-bluesky/pyproject.toml:^version",
|
|
69
|
+
"packages/amoorion-discord/pyproject.toml:^version",
|
|
70
|
+
"packages/amoorion-facebook/pyproject.toml:^version",
|
|
71
|
+
"packages/amoorion-mastodon/pyproject.toml:^version",
|
|
72
|
+
"packages/amoorion-matrix/pyproject.toml:^version",
|
|
73
|
+
"packages/amoorion-telegram/pyproject.toml:^version",
|
|
74
|
+
"packages/amoorion-tumblr/pyproject.toml:^version",
|
|
75
|
+
"packages/amoorion-x/pyproject.toml:^version",
|
|
76
|
+
]
|
|
77
|
+
pre_bump_hooks = ["uv lock"]
|
|
78
|
+
|
|
79
|
+
[tool.pytest.ini_options]
|
|
80
|
+
testpaths = [
|
|
81
|
+
"tests",
|
|
82
|
+
"packages",
|
|
83
|
+
"tools",
|
|
84
|
+
]
|
|
85
|
+
addopts = [
|
|
86
|
+
"--import-mode=importlib",
|
|
87
|
+
"-m",
|
|
88
|
+
"not live",
|
|
89
|
+
]
|
|
90
|
+
markers = ["live: posts on a real platform account (task test:live -- <platform>…)"]
|
|
91
|
+
|
|
92
|
+
[tool.uv.workspace]
|
|
93
|
+
members = [
|
|
94
|
+
"packages/*",
|
|
95
|
+
"tools/*",
|
|
96
|
+
"docs",
|
|
97
|
+
]
|
|
98
|
+
|
|
99
|
+
[tool.uv.sources.amoorion-bluesky]
|
|
100
|
+
workspace = true
|
|
101
|
+
|
|
102
|
+
[tool.uv.sources.amoorion-mastodon]
|
|
103
|
+
workspace = true
|
|
104
|
+
|
|
105
|
+
[tool.uv.sources.amoorion-x]
|
|
106
|
+
workspace = true
|
|
107
|
+
|
|
108
|
+
[tool.uv.sources.amoorion-tumblr]
|
|
109
|
+
workspace = true
|
|
110
|
+
|
|
111
|
+
[tool.uv.sources.amoorion-blogger]
|
|
112
|
+
workspace = true
|
|
113
|
+
|
|
114
|
+
[tool.uv.sources.amoorion-facebook]
|
|
115
|
+
workspace = true
|
|
116
|
+
|
|
117
|
+
[tool.uv.sources.amoorion-discord]
|
|
118
|
+
workspace = true
|
|
119
|
+
|
|
120
|
+
[tool.uv.sources.amoorion-telegram]
|
|
121
|
+
workspace = true
|
|
122
|
+
|
|
123
|
+
[tool.uv.sources.amoorion-matrix]
|
|
124
|
+
workspace = true
|
|
125
|
+
|
|
126
|
+
[tool.uv.sources.amoorion-dev]
|
|
127
|
+
workspace = true
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "amoorion"
|
|
3
|
+
version = "0.3.0"
|
|
4
|
+
description = "Universal tool for administration of chatting and communication platforms"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
license-files = ["LICENSE"]
|
|
8
|
+
authors = [
|
|
9
|
+
{ name = "Sett Sarverott", email = "sett@sarverott.com" }
|
|
10
|
+
]
|
|
11
|
+
requires-python = ">=3.12"
|
|
12
|
+
dependencies = [
|
|
13
|
+
"fastapi>=0.162.0",
|
|
14
|
+
"mcp[cli]>=2.3.0",
|
|
15
|
+
"pydantic>=2.14.1",
|
|
16
|
+
"python-dotenv>=1.2.4",
|
|
17
|
+
"requests>=2.34.2",
|
|
18
|
+
"rich>=15.0.0",
|
|
19
|
+
"uvicorn>=0.54.0",
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
[project.scripts]
|
|
23
|
+
amoorion = "amoorion:main"
|
|
24
|
+
|
|
25
|
+
# Platform plugins, found through this group; the packages in packages/ add theirs the same way.
|
|
26
|
+
[project.entry-points."amoorion.plugins"]
|
|
27
|
+
dryrun = "amoorion.plugins.dryrun:DryRun"
|
|
28
|
+
|
|
29
|
+
[project.optional-dependencies]
|
|
30
|
+
keepassxc = [
|
|
31
|
+
"pykeepass>=4.2.0",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
[build-system]
|
|
35
|
+
requires = ["uv_build>=0.12.20,<0.13.0"]
|
|
36
|
+
build-backend = "uv_build"
|
|
37
|
+
|
|
38
|
+
[dependency-groups]
|
|
39
|
+
dev = [
|
|
40
|
+
"amoorion-blogger",
|
|
41
|
+
"amoorion-bluesky",
|
|
42
|
+
"amoorion-dev",
|
|
43
|
+
"amoorion-discord",
|
|
44
|
+
"amoorion-facebook",
|
|
45
|
+
"amoorion-mastodon",
|
|
46
|
+
"amoorion-matrix",
|
|
47
|
+
"amoorion-telegram",
|
|
48
|
+
"amoorion-tumblr",
|
|
49
|
+
"amoorion-x",
|
|
50
|
+
"commitizen>=4.19.3",
|
|
51
|
+
"go-task-bin>=3.54.0",
|
|
52
|
+
"httpx>=0.28.1",
|
|
53
|
+
"ipykernel>=7.4.0",
|
|
54
|
+
"lefthook>=2.2.2",
|
|
55
|
+
"nbclient>=0.11.0",
|
|
56
|
+
"nbformat>=5.11.1",
|
|
57
|
+
"pykeepass>=4.2.0",
|
|
58
|
+
"pytest>=9.1.1",
|
|
59
|
+
"yamllint>=1.38.0",
|
|
60
|
+
]
|
|
61
|
+
examples = [
|
|
62
|
+
"marimo>=0.25.2",
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
[tool.commitizen]
|
|
66
|
+
name = "cz_conventional_commits"
|
|
67
|
+
version_provider = "uv"
|
|
68
|
+
tag_format = "v$version"
|
|
69
|
+
# CHANGELOG.md is written by `amoorion-dev version final`, not on every bump.
|
|
70
|
+
major_version_zero = true
|
|
71
|
+
# Every package of the workspace is released with the same version.
|
|
72
|
+
version_files = [
|
|
73
|
+
"packages/amoorion-blogger/pyproject.toml:^version",
|
|
74
|
+
"packages/amoorion-bluesky/pyproject.toml:^version",
|
|
75
|
+
"packages/amoorion-discord/pyproject.toml:^version",
|
|
76
|
+
"packages/amoorion-facebook/pyproject.toml:^version",
|
|
77
|
+
"packages/amoorion-mastodon/pyproject.toml:^version",
|
|
78
|
+
"packages/amoorion-matrix/pyproject.toml:^version",
|
|
79
|
+
"packages/amoorion-telegram/pyproject.toml:^version",
|
|
80
|
+
"packages/amoorion-tumblr/pyproject.toml:^version",
|
|
81
|
+
"packages/amoorion-x/pyproject.toml:^version",
|
|
82
|
+
]
|
|
83
|
+
# uv.lock records the packages' versions too.
|
|
84
|
+
pre_bump_hooks = ["uv lock"]
|
|
85
|
+
|
|
86
|
+
[tool.pytest.ini_options]
|
|
87
|
+
testpaths = ["tests", "packages", "tools"]
|
|
88
|
+
# Test modules of several packages may share a name. Live tests post for
|
|
89
|
+
# real: left out unless asked for (task test:live).
|
|
90
|
+
addopts = ["--import-mode=importlib", "-m", "not live"]
|
|
91
|
+
markers = ["live: posts on a real platform account (task test:live -- <platform>…)"]
|
|
92
|
+
|
|
93
|
+
# Platform plugins, one package each (decision Q10).
|
|
94
|
+
[tool.uv.workspace]
|
|
95
|
+
members = [
|
|
96
|
+
"packages/*",
|
|
97
|
+
"tools/*",
|
|
98
|
+
"docs",
|
|
99
|
+
]
|
|
100
|
+
|
|
101
|
+
[tool.uv.sources]
|
|
102
|
+
amoorion-bluesky = { workspace = true }
|
|
103
|
+
amoorion-mastodon = { workspace = true }
|
|
104
|
+
amoorion-x = { workspace = true }
|
|
105
|
+
amoorion-tumblr = { workspace = true }
|
|
106
|
+
amoorion-blogger = { workspace = true }
|
|
107
|
+
amoorion-facebook = { workspace = true }
|
|
108
|
+
amoorion-discord = { workspace = true }
|
|
109
|
+
amoorion-telegram = { workspace = true }
|
|
110
|
+
amoorion-matrix = { workspace = true }
|
|
111
|
+
amoorion-dev = { workspace = true }
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"""amoorion: administration of chatting and communication platforms."""
|
|
2
|
+
|
|
3
|
+
from importlib.metadata import version
|
|
4
|
+
|
|
5
|
+
# From the installed package, so the docs, the API and `--version` never lag behind pyproject.toml.
|
|
6
|
+
__version__ = version("amoorion")
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def main() -> int:
|
|
10
|
+
from amoorion.cli import main
|
|
11
|
+
|
|
12
|
+
return main()
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"""API: `POST /methods/<name>` with the method's params as the body,
|
|
2
|
+
`POST /hooks/<name>` for incoming webhooks (kept in the inbox), `GET /` for
|
|
3
|
+
what is there.
|
|
4
|
+
|
|
5
|
+
Method calls need `Authorization: Bearer <api/token from the vault>`; without
|
|
6
|
+
that secret in the vault every method call is refused. Hooks verify
|
|
7
|
+
themselves (see amoorion.hooks).
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import argparse
|
|
11
|
+
import hmac
|
|
12
|
+
from typing import Annotated, Any
|
|
13
|
+
|
|
14
|
+
from fastapi import Depends, FastAPI, HTTPException, Request
|
|
15
|
+
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
|
|
16
|
+
|
|
17
|
+
from amoorion import __version__
|
|
18
|
+
from amoorion.core import AmoorionError, JsonView
|
|
19
|
+
from amoorion.hooks import HOOKS, Forbidden
|
|
20
|
+
from amoorion.inbox import Inbox
|
|
21
|
+
from amoorion.methods import METHODS, Method
|
|
22
|
+
from amoorion.vault import Vault, open_vault
|
|
23
|
+
|
|
24
|
+
bearer = HTTPBearer(auto_error=False)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def create_app(vault: Vault | None = None, inbox: Inbox | None = None) -> FastAPI:
|
|
28
|
+
vault = vault or open_vault()
|
|
29
|
+
inbox = inbox or Inbox()
|
|
30
|
+
app = FastAPI(title="amoorion", version=__version__)
|
|
31
|
+
|
|
32
|
+
def authorized(credentials: Annotated[HTTPAuthorizationCredentials | None, Depends(bearer)]) -> None:
|
|
33
|
+
try:
|
|
34
|
+
token = vault.get("api/token")
|
|
35
|
+
except AmoorionError:
|
|
36
|
+
raise HTTPException(503, "no api/token in the vault: method calls are off") from None
|
|
37
|
+
if credentials is None or not hmac.compare_digest(credentials.credentials.encode(), token.encode()):
|
|
38
|
+
raise HTTPException(401, "wrong or missing bearer token")
|
|
39
|
+
|
|
40
|
+
@app.get("/")
|
|
41
|
+
def index() -> dict[str, Any]:
|
|
42
|
+
return {"name": "amoorion", "version": __version__, "methods": METHODS.names(), "hooks": HOOKS.names()}
|
|
43
|
+
|
|
44
|
+
def add_method(method: type[Method]) -> None:
|
|
45
|
+
Params = method.Params
|
|
46
|
+
|
|
47
|
+
def call(params: Params) -> Any: # type: ignore[valid-type]
|
|
48
|
+
try:
|
|
49
|
+
return JsonView().render(method(vault, inbox=inbox).run(params))
|
|
50
|
+
except AmoorionError as error:
|
|
51
|
+
raise HTTPException(400, str(error)) from None
|
|
52
|
+
|
|
53
|
+
app.post(
|
|
54
|
+
f"/methods/{method.name}",
|
|
55
|
+
summary=method.description,
|
|
56
|
+
dependencies=[Depends(authorized)],
|
|
57
|
+
name=method.name,
|
|
58
|
+
)(call)
|
|
59
|
+
|
|
60
|
+
for name in METHODS.names():
|
|
61
|
+
add_method(METHODS.get(name))
|
|
62
|
+
|
|
63
|
+
@app.post("/hooks/{name}")
|
|
64
|
+
async def hook(name: str, request: Request) -> Any:
|
|
65
|
+
if name not in HOOKS:
|
|
66
|
+
raise HTTPException(404, f"no hook named {name!r}")
|
|
67
|
+
body = await request.body()
|
|
68
|
+
try:
|
|
69
|
+
payload = await request.json()
|
|
70
|
+
except ValueError:
|
|
71
|
+
raise HTTPException(400, "body is not JSON") from None
|
|
72
|
+
try:
|
|
73
|
+
message = HOOKS.get(name)(vault).handle(body, request.headers, payload)
|
|
74
|
+
except Forbidden as error:
|
|
75
|
+
raise HTTPException(403, str(error)) from None
|
|
76
|
+
except AmoorionError as error:
|
|
77
|
+
raise HTTPException(400, str(error)) from None
|
|
78
|
+
[kept] = inbox.keep([message])
|
|
79
|
+
return JsonView().render(kept)
|
|
80
|
+
|
|
81
|
+
return app
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def serve(args: argparse.Namespace) -> None:
|
|
85
|
+
import uvicorn
|
|
86
|
+
|
|
87
|
+
uvicorn.run(create_app(), host=args.host, port=args.port)
|