Convert project to workspace with Tonic for gRPC. (#84)
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
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