forked from projectmoon/tenebrous-dicebot
Convert project to workspace with Tonic for gRPC. (#84)
Convert project to workspace with Tonic for gRPC. This commit adds an RPC service to the dicebot, allowing external applications to control it. The project was converted to a cargo workspace to house the protobuf definitions in a common crate (tenebrous-rpc), so that clients and servers can make use of these protobuf definitions. Co-Authored-By: projectmoon <projectmoon@noreply.git.agnos.is> Co-Committed-By: projectmoon <projectmoon@noreply.git.agnos.is>
This commit is contained in:
parent
b4321721c4
commit
764426382a
|
@ -7,6 +7,7 @@ steps:
|
||||||
commands:
|
commands:
|
||||||
- apt-get update
|
- apt-get update
|
||||||
- apt-get install -y cmake
|
- apt-get install -y cmake
|
||||||
|
- rustup component add rustfmt
|
||||||
- cargo build --verbose --all
|
- cargo build --verbose --all
|
||||||
- cargo test --verbose --all
|
- cargo test --verbose --all
|
||||||
|
|
||||||
|
|
|
@ -101,6 +101,12 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anyhow"
|
||||||
|
version = "1.0.40"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "28b2cd92db5cbd74e8e5028f7e27dd7aa3090e89e4f2a197cc7c8dfb69c7063b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arrayref"
|
name = "arrayref"
|
||||||
version = "0.3.6"
|
version = "0.3.6"
|
||||||
|
@ -119,6 +125,27 @@ version = "1.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5f093eed78becd229346bf859eec0aa4dd7ddde0757287b2b4107a1f09c80002"
|
checksum = "5f093eed78becd229346bf859eec0aa4dd7ddde0757287b2b4107a1f09c80002"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "async-stream"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "171374e7e3b2504e0e5236e3b59260560f9fe94bfe9ac39ba5e4e929c5590625"
|
||||||
|
dependencies = [
|
||||||
|
"async-stream-impl",
|
||||||
|
"futures-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "async-stream-impl"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "648ed8c8d2ce5409ccd57453d9d1b214b342a0d69376a6feda1fd6cae3299308"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-trait"
|
name = "async-trait"
|
||||||
version = "0.1.50"
|
version = "0.1.50"
|
||||||
|
@ -529,6 +556,12 @@ version = "0.1.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
|
checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fixedbitset"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fnv"
|
name = "fnv"
|
||||||
version = "1.0.7"
|
version = "1.0.7"
|
||||||
|
@ -991,6 +1024,15 @@ version = "2.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "47be2f14c678be2fdcab04ab1171db51b2762ce6f0a8ee87c8dd4a04ed216135"
|
checksum = "47be2f14c678be2fdcab04ab1171db51b2762ce6f0a8ee87c8dd4a04ed216135"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itertools"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itertools"
|
name = "itertools"
|
||||||
version = "0.10.0"
|
version = "0.10.0"
|
||||||
|
@ -1263,6 +1305,12 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "multimap"
|
||||||
|
version = "0.8.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "native-tls"
|
name = "native-tls"
|
||||||
version = "0.2.7"
|
version = "0.2.7"
|
||||||
|
@ -1462,6 +1510,16 @@ version = "2.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "petgraph"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7"
|
||||||
|
dependencies = [
|
||||||
|
"fixedbitset",
|
||||||
|
"indexmap",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "phf"
|
name = "phf"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
|
@ -1618,6 +1676,57 @@ dependencies = [
|
||||||
"unicode-xid",
|
"unicode-xid",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "prost"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9e6984d2f1a23009bd270b8bb56d0926810a3d483f59c987d77969e9d8e840b2"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"prost-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "prost-build"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "32d3ebd75ac2679c2af3a92246639f9fcc8a442ee420719cc4fe195b98dd5fa3"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"heck",
|
||||||
|
"itertools 0.9.0",
|
||||||
|
"log",
|
||||||
|
"multimap",
|
||||||
|
"petgraph",
|
||||||
|
"prost",
|
||||||
|
"prost-types",
|
||||||
|
"tempfile",
|
||||||
|
"which",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "prost-derive"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "169a15f3008ecb5160cba7d37bcd690a7601b6d30cfb87a117d45e59d52af5d4"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"itertools 0.9.0",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "prost-types"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b518d7cdd93dab1d1122cf07fa9a60771836c668dde9d9e2a139f957f0d9f1bb"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"prost",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.9"
|
version = "1.0.9"
|
||||||
|
@ -2557,11 +2666,12 @@ dependencies = [
|
||||||
"futures",
|
"futures",
|
||||||
"html2text",
|
"html2text",
|
||||||
"indoc",
|
"indoc",
|
||||||
"itertools",
|
"itertools 0.10.0",
|
||||||
"log",
|
"log",
|
||||||
"matrix-sdk",
|
"matrix-sdk",
|
||||||
"nom 5.1.2",
|
"nom 5.1.2",
|
||||||
"phf",
|
"phf",
|
||||||
|
"prost",
|
||||||
"rand 0.8.3",
|
"rand 0.8.3",
|
||||||
"refinery",
|
"refinery",
|
||||||
"rust-argon2",
|
"rust-argon2",
|
||||||
|
@ -2569,13 +2679,25 @@ dependencies = [
|
||||||
"sqlx",
|
"sqlx",
|
||||||
"substring",
|
"substring",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
|
"tenebrous-rpc",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
"toml",
|
"toml",
|
||||||
|
"tonic",
|
||||||
|
"tonic-build",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tenebrous-rpc"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"prost",
|
||||||
|
"tonic",
|
||||||
|
"tonic-build",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.24"
|
version = "1.0.24"
|
||||||
|
@ -2743,6 +2865,73 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tonic"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2ac42cd97ac6bd2339af5bcabf105540e21e45636ec6fa6aae5e85d44db31be0"
|
||||||
|
dependencies = [
|
||||||
|
"async-stream",
|
||||||
|
"async-trait",
|
||||||
|
"base64",
|
||||||
|
"bytes",
|
||||||
|
"futures-core",
|
||||||
|
"futures-util",
|
||||||
|
"h2",
|
||||||
|
"http",
|
||||||
|
"http-body",
|
||||||
|
"hyper",
|
||||||
|
"percent-encoding",
|
||||||
|
"pin-project",
|
||||||
|
"prost",
|
||||||
|
"prost-derive",
|
||||||
|
"tokio",
|
||||||
|
"tokio-stream",
|
||||||
|
"tokio-util",
|
||||||
|
"tower",
|
||||||
|
"tower-service",
|
||||||
|
"tracing",
|
||||||
|
"tracing-futures",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tonic-build"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c695de27302f4697191dda1c7178131a8cb805463dda02864acb80fe1322fdcf"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"prost-build",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tower"
|
||||||
|
version = "0.4.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f60422bc7fefa2f3ec70359b8ff1caff59d785877eb70595904605bcc412470f"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
"futures-util",
|
||||||
|
"indexmap",
|
||||||
|
"pin-project",
|
||||||
|
"rand 0.8.3",
|
||||||
|
"slab",
|
||||||
|
"tokio",
|
||||||
|
"tokio-stream",
|
||||||
|
"tokio-util",
|
||||||
|
"tower-layer",
|
||||||
|
"tower-service",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tower-layer"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "343bc9466d3fe6b0f960ef45960509f84480bf4fd96f92901afe7ff3df9d3a62"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tower-service"
|
name = "tower-service"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
|
@ -2756,6 +2945,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "09adeb8c97449311ccd28a427f96fb563e7fd31aabf994189879d9da2394b89d"
|
checksum = "09adeb8c97449311ccd28a427f96fb563e7fd31aabf994189879d9da2394b89d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
|
"log",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"tracing-attributes",
|
"tracing-attributes",
|
||||||
"tracing-core",
|
"tracing-core",
|
||||||
|
@ -3055,6 +3245,16 @@ dependencies = [
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "which"
|
||||||
|
version = "4.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b55551e42cbdf2ce2bedd2203d0cc08dba002c27510f86dab6d0ce304cba3dfe"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "whoami"
|
name = "whoami"
|
||||||
version = "1.1.2"
|
version = "1.1.2"
|
||||||
|
|
51
Cargo.toml
51
Cargo.toml
|
@ -1,47 +1,6 @@
|
||||||
[package]
|
[workspace]
|
||||||
name = "tenebrous-dicebot"
|
|
||||||
version = "0.10.0"
|
|
||||||
authors = ["Taylor C. Richberger <taywee@gmx.com>", "projectmoon <projectmoon@agnos.is>"]
|
|
||||||
edition = "2018"
|
|
||||||
license = 'AGPL-3.0-or-later'
|
|
||||||
description = 'An async Matrix dice bot for role-playing games'
|
|
||||||
readme = 'README.md'
|
|
||||||
repository = 'https://git.agnos.is/projectmoon/matrix-dicebot'
|
|
||||||
keywords = ["games", "dice", "matrix", "bot"]
|
|
||||||
categories = ["games"]
|
|
||||||
|
|
||||||
[dependencies]
|
members = [
|
||||||
log = "0.4"
|
"dicebot",
|
||||||
tracing-subscriber = "0.2"
|
"rpc",
|
||||||
toml = "0.5"
|
]
|
||||||
nom = "5"
|
|
||||||
rand = "0.8"
|
|
||||||
rust-argon2 = "0.8"
|
|
||||||
thiserror = "1.0"
|
|
||||||
itertools = "0.10"
|
|
||||||
async-trait = "0.1"
|
|
||||||
url = "2.1"
|
|
||||||
dirs = "3.0"
|
|
||||||
indoc = "1.0"
|
|
||||||
combine = "4.5"
|
|
||||||
futures = "0.3"
|
|
||||||
html2text = "0.2"
|
|
||||||
phf = { version = "0.8", features = ["macros"] }
|
|
||||||
matrix-sdk = { git = "https://github.com/matrix-org/matrix-rust-sdk", branch = "master" }
|
|
||||||
refinery = { version = "0.5", features = ["rusqlite"]}
|
|
||||||
barrel = { version = "0.6", features = ["sqlite3"] }
|
|
||||||
tempfile = "3"
|
|
||||||
substring = "1.4"
|
|
||||||
fuse-rust = "0.2"
|
|
||||||
|
|
||||||
[dependencies.sqlx]
|
|
||||||
version = "0.5"
|
|
||||||
features = [ "offline", "sqlite", "runtime-tokio-native-tls" ]
|
|
||||||
|
|
||||||
[dependencies.serde]
|
|
||||||
version = "1"
|
|
||||||
features = ['derive']
|
|
||||||
|
|
||||||
[dependencies.tokio]
|
|
||||||
version = "1"
|
|
||||||
features = [ "full" ]
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
[package]
|
||||||
|
name = "tenebrous-dicebot"
|
||||||
|
version = "0.10.0"
|
||||||
|
authors = ["Taylor C. Richberger <taywee@gmx.com>", "projectmoon <projectmoon@agnos.is>"]
|
||||||
|
edition = "2018"
|
||||||
|
license = 'AGPL-3.0-or-later'
|
||||||
|
description = 'An async Matrix dice bot for role-playing games'
|
||||||
|
readme = 'README.md'
|
||||||
|
repository = 'https://git.agnos.is/projectmoon/matrix-dicebot'
|
||||||
|
keywords = ["games", "dice", "matrix", "bot"]
|
||||||
|
categories = ["games"]
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
tonic-build = "0.4"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
log = "0.4"
|
||||||
|
tracing-subscriber = "0.2"
|
||||||
|
toml = "0.5"
|
||||||
|
nom = "5"
|
||||||
|
rand = "0.8"
|
||||||
|
rust-argon2 = "0.8"
|
||||||
|
thiserror = "1.0"
|
||||||
|
itertools = "0.10"
|
||||||
|
async-trait = "0.1"
|
||||||
|
url = "2.1"
|
||||||
|
dirs = "3.0"
|
||||||
|
indoc = "1.0"
|
||||||
|
combine = "4.5"
|
||||||
|
futures = "0.3"
|
||||||
|
html2text = "0.2"
|
||||||
|
phf = { version = "0.8", features = ["macros"] }
|
||||||
|
matrix-sdk = { git = "https://github.com/matrix-org/matrix-rust-sdk", branch = "master" }
|
||||||
|
refinery = { version = "0.5", features = ["rusqlite"]}
|
||||||
|
barrel = { version = "0.6", features = ["sqlite3"] }
|
||||||
|
tempfile = "3"
|
||||||
|
substring = "1.4"
|
||||||
|
fuse-rust = "0.2"
|
||||||
|
tonic = "0.4"
|
||||||
|
prost = "0.7"
|
||||||
|
tenebrous-rpc = { path = "../rpc" }
|
||||||
|
|
||||||
|
[dependencies.sqlx]
|
||||||
|
version = "0.5"
|
||||||
|
features = [ "offline", "sqlite", "runtime-tokio-native-tls" ]
|
||||||
|
|
||||||
|
[dependencies.serde]
|
||||||
|
version = "1"
|
||||||
|
features = ['derive']
|
||||||
|
|
||||||
|
[dependencies.tokio]
|
||||||
|
version = "1"
|
||||||
|
features = [ "full" ]
|
|
@ -0,0 +1,35 @@
|
||||||
|
# Builder image with development dependencies.
|
||||||
|
FROM bougyman/voidlinux:glibc as builder
|
||||||
|
RUN xbps-install -Syu
|
||||||
|
RUN xbps-install -Sy base-devel rustup cargo cmake wget gnupg
|
||||||
|
RUN xbps-install -Sy openssl-devel libstdc++-devel
|
||||||
|
RUN rustup-init -qy
|
||||||
|
RUN rustup component add rustfmt # Needed for protobuf building.
|
||||||
|
|
||||||
|
# Install tini for signal processing and zombie killing
|
||||||
|
ENV TINI_VERSION v0.19.0
|
||||||
|
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /usr/local/bin/tini
|
||||||
|
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini.asc /tini.asc
|
||||||
|
RUN gpg --batch --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 595E85A6B1B4779EA4DAAEC70B588DFF0527A9B7 \
|
||||||
|
&& gpg --batch --verify /tini.asc /usr/local/bin/tini
|
||||||
|
RUN chmod +x /usr/local/bin/tini
|
||||||
|
|
||||||
|
# Build dicebot
|
||||||
|
RUN mkdir -p /root/src
|
||||||
|
WORKDIR /root/src
|
||||||
|
ADD . ./
|
||||||
|
RUN . /root/.cargo/env && cargo build --release
|
||||||
|
|
||||||
|
# Final image
|
||||||
|
FROM bougyman/voidlinux:tiny
|
||||||
|
RUN xbps-install -Sy ca-certificates libstdc++
|
||||||
|
COPY --from=builder \
|
||||||
|
/root/src/target/release/dicebot \
|
||||||
|
/usr/local/bin/
|
||||||
|
COPY --from=builder \
|
||||||
|
/usr/local/bin/tini \
|
||||||
|
/usr/local/bin/
|
||||||
|
|
||||||
|
ENV XDG_CACHE_HOME "/cache"
|
||||||
|
ENV DATABASE_PATH "/cache/bot-db"
|
||||||
|
ENTRYPOINT [ "/usr/local/bin/tini", "-v", "--", "/usr/local/bin/dicebot", "/config/dicebot-config.toml" ]
|
|
@ -1,21 +1,36 @@
|
||||||
//Needed for nested Result handling from tokio. Probably can go away after 1.47.0.
|
//Needed for nested Result handling from tokio. Probably can go away after 1.47.0.
|
||||||
#![type_length_limit = "7605144"]
|
#![type_length_limit = "7605144"]
|
||||||
|
use futures::try_join;
|
||||||
use log::error;
|
use log::error;
|
||||||
|
use matrix_sdk::Client;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
use tenebrous_dicebot::bot::DiceBot;
|
use tenebrous_dicebot::bot::DiceBot;
|
||||||
use tenebrous_dicebot::config::*;
|
use tenebrous_dicebot::config::*;
|
||||||
use tenebrous_dicebot::db::sqlite::Database;
|
use tenebrous_dicebot::db::sqlite::Database;
|
||||||
use tenebrous_dicebot::error::BotError;
|
use tenebrous_dicebot::error::BotError;
|
||||||
|
use tenebrous_dicebot::rpc;
|
||||||
use tenebrous_dicebot::state::DiceBotState;
|
use tenebrous_dicebot::state::DiceBotState;
|
||||||
use tracing_subscriber::filter::EnvFilter;
|
use tracing_subscriber::filter::EnvFilter;
|
||||||
|
|
||||||
|
/// Attempt to create config object and ddatabase connection pool from
|
||||||
|
/// the given config path. An error is returned if config creation or
|
||||||
|
/// database pool creation fails for some reason.
|
||||||
|
async fn init(config_path: &str) -> Result<(Arc<Config>, Database, Client), BotError> {
|
||||||
|
let cfg = read_config(config_path)?;
|
||||||
|
let cfg = Arc::new(cfg);
|
||||||
|
let sqlite_path = format!("{}/dicebot.sqlite", cfg.database_path());
|
||||||
|
let db = Database::new(&sqlite_path).await?;
|
||||||
|
let client = tenebrous_dicebot::matrix::create_client(&cfg)?;
|
||||||
|
Ok((cfg, db, client))
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() -> Result<(), BotError> {
|
||||||
let filter = if env::var("RUST_LOG").is_ok() {
|
let filter = if env::var("RUST_LOG").is_ok() {
|
||||||
EnvFilter::from_default_env()
|
EnvFilter::from_default_env()
|
||||||
} else {
|
} else {
|
||||||
EnvFilter::new("tenebrous_dicebot=info,dicebot=info,refinery=info")
|
EnvFilter::new("tonic=info,tenebrous_dicebot=info,dicebot=info,refinery=info")
|
||||||
};
|
};
|
||||||
|
|
||||||
tracing_subscriber::fmt().with_env_filter(filter).init();
|
tracing_subscriber::fmt().with_env_filter(filter).init();
|
||||||
|
@ -23,7 +38,9 @@ async fn main() {
|
||||||
match run().await {
|
match run().await {
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
Err(e) => error!("Error: {}", e),
|
Err(e) => error!("Error: {}", e),
|
||||||
};
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn run() -> Result<(), BotError> {
|
async fn run() -> Result<(), BotError> {
|
||||||
|
@ -32,12 +49,22 @@ async fn run() -> Result<(), BotError> {
|
||||||
.next()
|
.next()
|
||||||
.expect("Need a config as an argument");
|
.expect("Need a config as an argument");
|
||||||
|
|
||||||
let cfg = Arc::new(read_config(config_path)?);
|
let (cfg, db, client) = init(&config_path).await?;
|
||||||
let sqlite_path = format!("{}/dicebot.sqlite", cfg.database_path());
|
let grpc = rpc::serve_grpc(&cfg, &db, &client);
|
||||||
let db = Database::new(&sqlite_path).await?;
|
let bot = run_bot(&cfg, &db, &client);
|
||||||
|
|
||||||
|
match try_join!(bot, grpc) {
|
||||||
|
Ok(_) => (),
|
||||||
|
Err(e) => error!("Error: {}", e),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn run_bot(cfg: &Arc<Config>, db: &Database, client: &Client) -> Result<(), BotError> {
|
||||||
let state = Arc::new(RwLock::new(DiceBotState::new(&cfg)));
|
let state = Arc::new(RwLock::new(DiceBotState::new(&cfg)));
|
||||||
|
|
||||||
match DiceBot::new(&cfg, &state, &db) {
|
match DiceBot::new(cfg, &state, db, client) {
|
||||||
Ok(bot) => bot.run().await?,
|
Ok(bot) => bot.run().await?,
|
||||||
Err(e) => println!("Error connecting: {:?}", e),
|
Err(e) => println!("Error connecting: {:?}", e),
|
||||||
};
|
};
|
|
@ -0,0 +1,43 @@
|
||||||
|
use tenebrous_rpc::protos::dicebot::UserIdRequest;
|
||||||
|
use tenebrous_rpc::protos::dicebot::{dicebot_client::DicebotClient, GetVariableRequest};
|
||||||
|
use tonic::{metadata::MetadataValue, transport::Channel, Request};
|
||||||
|
|
||||||
|
async fn create_client(
|
||||||
|
shared_secret: &str,
|
||||||
|
) -> Result<DicebotClient<Channel>, Box<dyn std::error::Error>> {
|
||||||
|
let channel = Channel::from_static("http://0.0.0.0:9090")
|
||||||
|
.connect()
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let bearer = MetadataValue::from_str(&format!("Bearer {}", shared_secret))?;
|
||||||
|
|
||||||
|
let client = DicebotClient::with_interceptor(channel, move |mut req: Request<()>| {
|
||||||
|
req.metadata_mut().insert("authorization", bearer.clone());
|
||||||
|
Ok(req)
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(client)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
let mut client = create_client("example-key").await?;
|
||||||
|
|
||||||
|
// let request = tonic::Request::new(GetVariableRequest {
|
||||||
|
// user_id: "@projectmoon:agnos.is".into(),
|
||||||
|
// room_id: "!agICWvldGfuCywUVUM:agnos.is".into(),
|
||||||
|
// variable_name: "stuff".into(),
|
||||||
|
// });
|
||||||
|
|
||||||
|
// let response = client.get_variable(request).await?.into_inner();
|
||||||
|
|
||||||
|
let request = tonic::Request::new(UserIdRequest {
|
||||||
|
user_id: "@projectmoon:agnos.is".into(),
|
||||||
|
});
|
||||||
|
|
||||||
|
let response = client.rooms_for_user(request).await?.into_inner();
|
||||||
|
// println!("RESPONSE={:?}", response);
|
||||||
|
// println!("User friendly response is: {:?}", response.value);
|
||||||
|
println!("Rooms: {:?}", response.rooms);
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -4,13 +4,10 @@ use crate::db::sqlite::Database;
|
||||||
use crate::db::DbState;
|
use crate::db::DbState;
|
||||||
use crate::error::BotError;
|
use crate::error::BotError;
|
||||||
use crate::state::DiceBotState;
|
use crate::state::DiceBotState;
|
||||||
use dirs;
|
|
||||||
use log::info;
|
use log::info;
|
||||||
use matrix_sdk::{self, identifiers::EventId, room::Joined, Client, ClientConfig, SyncSettings};
|
use matrix_sdk::{self, identifiers::EventId, room::Joined, Client, SyncSettings};
|
||||||
use std::clone::Clone;
|
use std::clone::Clone;
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
use url::Url;
|
|
||||||
|
|
||||||
mod command_execution;
|
mod command_execution;
|
||||||
pub mod event_handlers;
|
pub mod event_handlers;
|
||||||
|
@ -35,22 +32,6 @@ pub struct DiceBot {
|
||||||
db: Database,
|
db: Database,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cache_dir() -> Result<PathBuf, BotError> {
|
|
||||||
let mut dir = dirs::cache_dir().ok_or(BotError::NoCacheDirectoryError)?;
|
|
||||||
dir.push("matrix-dicebot");
|
|
||||||
Ok(dir)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates the matrix client.
|
|
||||||
fn create_client(config: &Config) -> Result<Client, BotError> {
|
|
||||||
let cache_dir = cache_dir()?;
|
|
||||||
//let store = JsonStore::open(&cache_dir)?;
|
|
||||||
let client_config = ClientConfig::new().store_path(cache_dir);
|
|
||||||
let homeserver_url = Url::parse(&config.matrix_homeserver())?;
|
|
||||||
|
|
||||||
Ok(Client::new_with_config(homeserver_url, client_config)?)
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DiceBot {
|
impl DiceBot {
|
||||||
/// Create a new dicebot with the given configuration and state
|
/// Create a new dicebot with the given configuration and state
|
||||||
/// actor. This function returns a Result because it is possible
|
/// actor. This function returns a Result because it is possible
|
||||||
|
@ -60,9 +41,10 @@ impl DiceBot {
|
||||||
config: &Arc<Config>,
|
config: &Arc<Config>,
|
||||||
state: &Arc<RwLock<DiceBotState>>,
|
state: &Arc<RwLock<DiceBotState>>,
|
||||||
db: &Database,
|
db: &Database,
|
||||||
|
client: &Client,
|
||||||
) -> Result<Self, BotError> {
|
) -> Result<Self, BotError> {
|
||||||
Ok(DiceBot {
|
Ok(DiceBot {
|
||||||
client: create_client(&config)?,
|
client: client.clone(),
|
||||||
config: config.clone(),
|
config: config.clone(),
|
||||||
state: state.clone(),
|
state: state.clone(),
|
||||||
db: db.clone(),
|
db: db.clone(),
|
|
@ -4,10 +4,6 @@ use std::fs;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
/// Shortcut to defining db migration versions. Will probably
|
|
||||||
/// eventually be moved to a config file.
|
|
||||||
const MIGRATION_VERSION: u32 = 5;
|
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum ConfigError {
|
pub enum ConfigError {
|
||||||
#[error("i/o error: {0}")]
|
#[error("i/o error: {0}")]
|
||||||
|
@ -53,10 +49,19 @@ fn db_path_from_env() -> String {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The "bot" section of the config file, for bot settings.
|
/// The "bot" section of the config file, for bot settings.
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
|
||||||
struct BotConfig {
|
struct BotConfig {
|
||||||
/// How far back from current time should we process a message?
|
/// How far back from current time should we process a message?
|
||||||
oldest_message_age: Option<u64>,
|
oldest_message_age: Option<u64>,
|
||||||
|
|
||||||
|
/// What address and port to run the RPC service on. If not
|
||||||
|
/// specified, RPC will not be enabled.
|
||||||
|
rpc_addr: Option<String>,
|
||||||
|
|
||||||
|
/// The shared secret key between the bot and any RPC clients that
|
||||||
|
/// want to connect to it. The RPC server will reject any clients
|
||||||
|
/// that don't present the shared key.
|
||||||
|
rpc_key: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The "database" section of the config file.
|
/// The "database" section of the config file.
|
||||||
|
@ -84,6 +89,18 @@ impl BotConfig {
|
||||||
self.oldest_message_age
|
self.oldest_message_age
|
||||||
.unwrap_or(DEFAULT_OLDEST_MESSAGE_AGE)
|
.unwrap_or(DEFAULT_OLDEST_MESSAGE_AGE)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
#[must_use]
|
||||||
|
fn rpc_addr(&self) -> Option<String> {
|
||||||
|
self.rpc_addr.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
#[must_use]
|
||||||
|
fn rpc_key(&self) -> Option<String> {
|
||||||
|
self.rpc_key.clone()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents the toml config file for the dicebot. The sections of
|
/// Represents the toml config file for the dicebot. The sections of
|
||||||
|
@ -128,15 +145,6 @@ impl Config {
|
||||||
.unwrap_or_else(|| db_path_from_env())
|
.unwrap_or_else(|| db_path_from_env())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The current migration version we expect of the database. If
|
|
||||||
/// this number is higher than the one in the database, we will
|
|
||||||
/// execute migrations to update the data.
|
|
||||||
#[inline]
|
|
||||||
#[must_use]
|
|
||||||
pub fn migration_version(&self) -> u32 {
|
|
||||||
MIGRATION_VERSION
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Figure out the allowed oldest message age, in seconds. This will
|
/// Figure out the allowed oldest message age, in seconds. This will
|
||||||
/// be the defined oldest message age in the bot config, if the bot
|
/// be the defined oldest message age in the bot config, if the bot
|
||||||
/// configuration and associated "oldest_message_age" setting are
|
/// configuration and associated "oldest_message_age" setting are
|
||||||
|
@ -150,6 +158,18 @@ impl Config {
|
||||||
.map(|bc| bc.oldest_message_age())
|
.map(|bc| bc.oldest_message_age())
|
||||||
.unwrap_or(DEFAULT_OLDEST_MESSAGE_AGE)
|
.unwrap_or(DEFAULT_OLDEST_MESSAGE_AGE)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
#[must_use]
|
||||||
|
pub fn rpc_addr(&self) -> Option<String> {
|
||||||
|
self.bot.as_ref().and_then(|bc| bc.rpc_addr())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
#[must_use]
|
||||||
|
pub fn rpc_key(&self) -> Option<String> {
|
||||||
|
self.bot.as_ref().and_then(|bc| bc.rpc_key())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -169,6 +189,7 @@ mod tests {
|
||||||
}),
|
}),
|
||||||
bot: Some(BotConfig {
|
bot: Some(BotConfig {
|
||||||
oldest_message_age: None,
|
oldest_message_age: None,
|
||||||
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
|
use std::net::AddrParseError;
|
||||||
|
|
||||||
use crate::commands::CommandError;
|
use crate::commands::CommandError;
|
||||||
use crate::config::ConfigError;
|
use crate::config::ConfigError;
|
||||||
use crate::db::errors::DataError;
|
use crate::db::errors::DataError;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
use tonic::metadata::errors::InvalidMetadataValue;
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum BotError {
|
pub enum BotError {
|
||||||
|
@ -93,6 +96,15 @@ pub enum BotError {
|
||||||
|
|
||||||
#[error("room name or id does not exist")]
|
#[error("room name or id does not exist")]
|
||||||
RoomDoesNotExist,
|
RoomDoesNotExist,
|
||||||
|
|
||||||
|
#[error("tonic transport error: {0}")]
|
||||||
|
TonicTransportError(#[from] tonic::transport::Error),
|
||||||
|
|
||||||
|
#[error("address parsing error: {0}")]
|
||||||
|
AddressParseError(#[from] AddrParseError),
|
||||||
|
|
||||||
|
#[error("invalid metadata value: {0}")]
|
||||||
|
TonicInvalidMetadata(#[from] InvalidMetadataValue),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
|
@ -12,4 +12,5 @@ pub mod logic;
|
||||||
pub mod matrix;
|
pub mod matrix;
|
||||||
pub mod models;
|
pub mod models;
|
||||||
mod parser;
|
mod parser;
|
||||||
|
pub mod rpc;
|
||||||
pub mod state;
|
pub mod state;
|
|
@ -1,6 +1,8 @@
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use futures::stream::{self, StreamExt, TryStreamExt};
|
use futures::stream::{self, StreamExt, TryStreamExt};
|
||||||
use log::error;
|
use log::error;
|
||||||
use matrix_sdk::{events::room::message::NoticeMessageEventContent, room::Joined};
|
use matrix_sdk::{events::room::message::NoticeMessageEventContent, room::Joined, ClientConfig};
|
||||||
use matrix_sdk::{
|
use matrix_sdk::{
|
||||||
events::room::message::{InReplyTo, Relation},
|
events::room::message::{InReplyTo, Relation},
|
||||||
events::room::message::{MessageEventContent, MessageType},
|
events::room::message::{MessageEventContent, MessageType},
|
||||||
|
@ -9,6 +11,15 @@ use matrix_sdk::{
|
||||||
Error as MatrixError,
|
Error as MatrixError,
|
||||||
};
|
};
|
||||||
use matrix_sdk::{identifiers::RoomId, identifiers::UserId, Client};
|
use matrix_sdk::{identifiers::RoomId, identifiers::UserId, Client};
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
|
use crate::{config::Config, error::BotError};
|
||||||
|
|
||||||
|
fn cache_dir() -> Result<PathBuf, BotError> {
|
||||||
|
let mut dir = dirs::cache_dir().ok_or(BotError::NoCacheDirectoryError)?;
|
||||||
|
dir.push("matrix-dicebot");
|
||||||
|
Ok(dir)
|
||||||
|
}
|
||||||
|
|
||||||
/// Extracts more detailed error messages out of a matrix SDK error.
|
/// Extracts more detailed error messages out of a matrix SDK error.
|
||||||
fn extract_error_message(error: MatrixError) -> String {
|
fn extract_error_message(error: MatrixError) -> String {
|
||||||
|
@ -20,6 +31,15 @@ fn extract_error_message(error: MatrixError) -> String {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates the matrix client.
|
||||||
|
pub fn create_client(config: &Config) -> Result<Client, BotError> {
|
||||||
|
let cache_dir = cache_dir()?;
|
||||||
|
let client_config = ClientConfig::new().store_path(cache_dir);
|
||||||
|
let homeserver_url = Url::parse(&config.matrix_homeserver())?;
|
||||||
|
|
||||||
|
Ok(Client::new_with_config(homeserver_url, client_config)?)
|
||||||
|
}
|
||||||
|
|
||||||
/// Retrieve a list of users in a given room.
|
/// Retrieve a list of users in a given room.
|
||||||
pub async fn get_users_in_room(
|
pub async fn get_users_in_room(
|
||||||
client: &Client,
|
client: &Client,
|
|
@ -0,0 +1,50 @@
|
||||||
|
use crate::error::BotError;
|
||||||
|
use crate::{config::Config, db::sqlite::Database};
|
||||||
|
use log::{info, warn};
|
||||||
|
use matrix_sdk::Client;
|
||||||
|
use service::DicebotRpcService;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use tenebrous_rpc::protos::dicebot::dicebot_server::DicebotServer;
|
||||||
|
use tonic::{metadata::MetadataValue, transport::Server, Request, Status};
|
||||||
|
|
||||||
|
pub(crate) mod service;
|
||||||
|
|
||||||
|
pub async fn serve_grpc(
|
||||||
|
config: &Arc<Config>,
|
||||||
|
db: &Database,
|
||||||
|
client: &Client,
|
||||||
|
) -> Result<(), BotError> {
|
||||||
|
match config.rpc_addr().zip(config.rpc_key()) {
|
||||||
|
Some((addr, rpc_key)) => {
|
||||||
|
let expected_bearer = MetadataValue::from_str(&format!("Bearer {}", rpc_key))?;
|
||||||
|
let addr = addr.parse()?;
|
||||||
|
|
||||||
|
let rpc_service = DicebotRpcService {
|
||||||
|
db: db.clone(),
|
||||||
|
config: config.clone(),
|
||||||
|
client: client.clone(),
|
||||||
|
};
|
||||||
|
|
||||||
|
info!("Serving Dicebot gRPC service on {}", addr);
|
||||||
|
|
||||||
|
let interceptor = move |req: Request<()>| match req.metadata().get("authorization") {
|
||||||
|
Some(bearer) if bearer == expected_bearer => Ok(req),
|
||||||
|
_ => Err(Status::unauthenticated("No valid auth token")),
|
||||||
|
};
|
||||||
|
|
||||||
|
let server = DicebotServer::with_interceptor(rpc_service, interceptor);
|
||||||
|
|
||||||
|
Server::builder()
|
||||||
|
.add_service(server)
|
||||||
|
.serve(addr)
|
||||||
|
.await
|
||||||
|
.map_err(|e| e.into())
|
||||||
|
}
|
||||||
|
_ => noop().await,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn noop() -> Result<(), BotError> {
|
||||||
|
warn!("RPC address or shared secret not specified. Not enabling gRPC.");
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -0,0 +1,116 @@
|
||||||
|
use crate::db::{errors::DataError, Variables};
|
||||||
|
use crate::error::BotError;
|
||||||
|
use crate::matrix;
|
||||||
|
use crate::{config::Config, db::sqlite::Database};
|
||||||
|
use futures::stream;
|
||||||
|
use futures::{StreamExt, TryFutureExt, TryStreamExt};
|
||||||
|
use matrix_sdk::{identifiers::UserId, room::Joined, Client};
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use tenebrous_rpc::protos::dicebot::{
|
||||||
|
dicebot_server::Dicebot, rooms_list_reply::Room, GetAllVariablesReply, GetAllVariablesRequest,
|
||||||
|
RoomsListReply, SetVariableReply, SetVariableRequest, UserIdRequest,
|
||||||
|
};
|
||||||
|
use tenebrous_rpc::protos::dicebot::{GetVariableReply, GetVariableRequest};
|
||||||
|
use tonic::{Code, Request, Response, Status};
|
||||||
|
|
||||||
|
impl From<BotError> for Status {
|
||||||
|
fn from(error: BotError) -> Status {
|
||||||
|
Status::new(Code::Internal, error.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<DataError> for Status {
|
||||||
|
fn from(error: DataError) -> Status {
|
||||||
|
Status::new(Code::Internal, error.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub(super) struct DicebotRpcService {
|
||||||
|
pub(super) config: Arc<Config>,
|
||||||
|
pub(super) db: Database,
|
||||||
|
pub(super) client: Client,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tonic::async_trait]
|
||||||
|
impl Dicebot for DicebotRpcService {
|
||||||
|
async fn set_variable(
|
||||||
|
&self,
|
||||||
|
request: Request<SetVariableRequest>,
|
||||||
|
) -> Result<Response<SetVariableReply>, Status> {
|
||||||
|
let SetVariableRequest {
|
||||||
|
user_id,
|
||||||
|
room_id,
|
||||||
|
variable_name,
|
||||||
|
value,
|
||||||
|
} = request.into_inner();
|
||||||
|
|
||||||
|
self.db
|
||||||
|
.set_user_variable(&user_id, &room_id, &variable_name, value)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(Response::new(SetVariableReply { success: true }))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_variable(
|
||||||
|
&self,
|
||||||
|
request: Request<GetVariableRequest>,
|
||||||
|
) -> Result<Response<GetVariableReply>, Status> {
|
||||||
|
let request = request.into_inner();
|
||||||
|
let value = self
|
||||||
|
.db
|
||||||
|
.get_user_variable(&request.user_id, &request.room_id, &request.variable_name)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(Response::new(GetVariableReply { value }))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_all_variables(
|
||||||
|
&self,
|
||||||
|
request: Request<GetAllVariablesRequest>,
|
||||||
|
) -> Result<Response<GetAllVariablesReply>, Status> {
|
||||||
|
let request = request.into_inner();
|
||||||
|
let variables = self
|
||||||
|
.db
|
||||||
|
.get_user_variables(&request.user_id, &request.room_id)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(Response::new(GetAllVariablesReply { variables }))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn rooms_for_user(
|
||||||
|
&self,
|
||||||
|
request: Request<UserIdRequest>,
|
||||||
|
) -> Result<Response<RoomsListReply>, Status> {
|
||||||
|
let UserIdRequest { user_id } = request.into_inner();
|
||||||
|
let user_id = UserId::try_from(user_id).map_err(BotError::from)?;
|
||||||
|
|
||||||
|
let rooms_for_user = matrix::get_rooms_for_user(&self.client, &user_id)
|
||||||
|
.err_into::<BotError>()
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let mut rooms: Vec<Room> = stream::iter(rooms_for_user)
|
||||||
|
.filter_map(|room: Joined| async move {
|
||||||
|
let room: Result<Room, _> = room.display_name().await.map(|room_name| Room {
|
||||||
|
room_id: room.room_id().to_string(),
|
||||||
|
display_name: room_name,
|
||||||
|
});
|
||||||
|
|
||||||
|
Some(room)
|
||||||
|
})
|
||||||
|
.err_into::<BotError>()
|
||||||
|
.try_collect()
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let sort = |r1: &Room, r2: &Room| {
|
||||||
|
r1.display_name
|
||||||
|
.to_lowercase()
|
||||||
|
.cmp(&r2.display_name.to_lowercase())
|
||||||
|
};
|
||||||
|
|
||||||
|
rooms.sort_by(sort);
|
||||||
|
|
||||||
|
Ok(Response::new(RoomsListReply { rooms }))
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
[package]
|
||||||
|
name = "tenebrous-rpc"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["projectmoon <projectmoon@agnos.is>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
tonic-build = "0.4"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
tonic = "0.4"
|
||||||
|
prost = "0.7"
|
|
@ -0,0 +1,4 @@
|
||||||
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
tonic_build::compile_protos("protos/dicebot.proto")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
syntax = "proto3";
|
||||||
|
package dicebot;
|
||||||
|
|
||||||
|
service Dicebot {
|
||||||
|
rpc GetVariable(GetVariableRequest) returns (GetVariableReply);
|
||||||
|
rpc GetAllVariables(GetAllVariablesRequest) returns (GetAllVariablesReply);
|
||||||
|
rpc SetVariable(SetVariableRequest) returns (SetVariableReply);
|
||||||
|
rpc RoomsForUser(UserIdRequest) returns (RoomsListReply);
|
||||||
|
}
|
||||||
|
|
||||||
|
message GetVariableRequest {
|
||||||
|
string user_id = 1;
|
||||||
|
string room_id = 2;
|
||||||
|
string variable_name = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GetVariableReply {
|
||||||
|
int32 value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GetAllVariablesRequest {
|
||||||
|
string user_id = 1;
|
||||||
|
string room_id = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GetAllVariablesReply {
|
||||||
|
map<string, int32> variables = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SetVariableRequest {
|
||||||
|
string user_id = 1;
|
||||||
|
string room_id = 2;
|
||||||
|
string variable_name = 3;
|
||||||
|
int32 value = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SetVariableReply {
|
||||||
|
bool success = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UserIdRequest {
|
||||||
|
string user_id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RoomsListReply {
|
||||||
|
message Room {
|
||||||
|
string room_id = 1;
|
||||||
|
string display_name = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
repeated Room rooms = 1;
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
pub mod protos {
|
||||||
|
pub mod dicebot {
|
||||||
|
tonic::include_proto!("dicebot");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
fn main() {
|
||||||
|
println!("Hello, world!");
|
||||||
|
}
|
Loading…
Reference in New Issue