Rename the project to Echo (was fedserv)

Rebrand the daemon and workspace: the binary is now `echo`, every crate
is `echo-*` (`echo-api` and the module crates), Rust imports use
`echo_*`, the gRPC proto is `proto/echo.proto` with package `echo.v1`,
and the log filter, gossip peer-name default, and on-disk store default
(`echo.db.jsonl`) follow. Docs updated throughout. No behaviour change;
crate directories and the config schema are untouched.
This commit is contained in:
Jean Chevronnet 2026-07-14 15:24:41 +00:00
parent e7037572e5
commit 993f5b2eea
No known key found for this signature in database
159 changed files with 660 additions and 660 deletions

308
Cargo.lock generated
View file

@ -288,6 +288,160 @@ version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
[[package]]
name = "echo"
version = "0.0.1"
dependencies = [
"anyhow",
"argon2",
"axum",
"axum-server",
"base64",
"echo-api",
"echo-botserv",
"echo-chanfix",
"echo-chanserv",
"echo-diceserv",
"echo-example",
"echo-groupserv",
"echo-helpserv",
"echo-hostserv",
"echo-infoserv",
"echo-inspircd",
"echo-memoserv",
"echo-nickserv",
"echo-operserv",
"echo-reportserv",
"echo-statserv",
"hmac",
"pbkdf2",
"prost",
"regex",
"rustls-pemfile",
"serde",
"serde_json",
"sha2",
"subtle",
"tokio",
"tokio-rustls",
"tokio-stream",
"toml",
"tonic",
"tonic-build",
"tracing",
"tracing-subscriber",
]
[[package]]
name = "echo-api"
version = "0.0.1"
[[package]]
name = "echo-botserv"
version = "0.0.1"
dependencies = [
"echo-api",
]
[[package]]
name = "echo-chanfix"
version = "0.0.1"
dependencies = [
"echo-api",
]
[[package]]
name = "echo-chanserv"
version = "0.0.1"
dependencies = [
"echo-api",
]
[[package]]
name = "echo-diceserv"
version = "0.0.1"
dependencies = [
"echo-api",
"rand",
]
[[package]]
name = "echo-example"
version = "0.0.1"
dependencies = [
"echo-api",
]
[[package]]
name = "echo-groupserv"
version = "0.0.1"
dependencies = [
"echo-api",
]
[[package]]
name = "echo-helpserv"
version = "0.0.1"
dependencies = [
"echo-api",
]
[[package]]
name = "echo-hostserv"
version = "0.0.1"
dependencies = [
"echo-api",
]
[[package]]
name = "echo-infoserv"
version = "0.0.1"
dependencies = [
"echo-api",
]
[[package]]
name = "echo-inspircd"
version = "0.0.1"
dependencies = [
"echo-api",
]
[[package]]
name = "echo-memoserv"
version = "0.0.1"
dependencies = [
"echo-api",
]
[[package]]
name = "echo-nickserv"
version = "0.0.1"
dependencies = [
"echo-api",
]
[[package]]
name = "echo-operserv"
version = "0.0.1"
dependencies = [
"echo-api",
]
[[package]]
name = "echo-reportserv"
version = "0.0.1"
dependencies = [
"echo-api",
]
[[package]]
name = "echo-statserv"
version = "0.0.1"
dependencies = [
"echo-api",
]
[[package]]
name = "either"
version = "1.16.0"
@ -316,160 +470,6 @@ version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6"
[[package]]
name = "fedserv"
version = "0.0.1"
dependencies = [
"anyhow",
"argon2",
"axum",
"axum-server",
"base64",
"fedserv-api",
"fedserv-botserv",
"fedserv-chanfix",
"fedserv-chanserv",
"fedserv-diceserv",
"fedserv-example",
"fedserv-groupserv",
"fedserv-helpserv",
"fedserv-hostserv",
"fedserv-infoserv",
"fedserv-inspircd",
"fedserv-memoserv",
"fedserv-nickserv",
"fedserv-operserv",
"fedserv-reportserv",
"fedserv-statserv",
"hmac",
"pbkdf2",
"prost",
"regex",
"rustls-pemfile",
"serde",
"serde_json",
"sha2",
"subtle",
"tokio",
"tokio-rustls",
"tokio-stream",
"toml",
"tonic",
"tonic-build",
"tracing",
"tracing-subscriber",
]
[[package]]
name = "fedserv-api"
version = "0.0.1"
[[package]]
name = "fedserv-botserv"
version = "0.0.1"
dependencies = [
"fedserv-api",
]
[[package]]
name = "fedserv-chanfix"
version = "0.0.1"
dependencies = [
"fedserv-api",
]
[[package]]
name = "fedserv-chanserv"
version = "0.0.1"
dependencies = [
"fedserv-api",
]
[[package]]
name = "fedserv-diceserv"
version = "0.0.1"
dependencies = [
"fedserv-api",
"rand",
]
[[package]]
name = "fedserv-example"
version = "0.0.1"
dependencies = [
"fedserv-api",
]
[[package]]
name = "fedserv-groupserv"
version = "0.0.1"
dependencies = [
"fedserv-api",
]
[[package]]
name = "fedserv-helpserv"
version = "0.0.1"
dependencies = [
"fedserv-api",
]
[[package]]
name = "fedserv-hostserv"
version = "0.0.1"
dependencies = [
"fedserv-api",
]
[[package]]
name = "fedserv-infoserv"
version = "0.0.1"
dependencies = [
"fedserv-api",
]
[[package]]
name = "fedserv-inspircd"
version = "0.0.1"
dependencies = [
"fedserv-api",
]
[[package]]
name = "fedserv-memoserv"
version = "0.0.1"
dependencies = [
"fedserv-api",
]
[[package]]
name = "fedserv-nickserv"
version = "0.0.1"
dependencies = [
"fedserv-api",
]
[[package]]
name = "fedserv-operserv"
version = "0.0.1"
dependencies = [
"fedserv-api",
]
[[package]]
name = "fedserv-reportserv"
version = "0.0.1"
dependencies = [
"fedserv-api",
]
[[package]]
name = "fedserv-statserv"
version = "0.0.1"
dependencies = [
"fedserv-api",
]
[[package]]
name = "find-msvc-tools"
version = "0.1.9"

View file

@ -21,28 +21,28 @@ members = [
]
[package]
name = "fedserv"
name = "echo"
version = "0.0.1"
edition = "2021"
description = "Federated IRC services daemon (protocol-agnostic core, InspIRCd link first)"
[dependencies]
fedserv-api = { path = "api" }
fedserv-inspircd = { path = "modules/protocol/inspircd" }
fedserv-chanserv = { path = "modules/chanserv" }
fedserv-nickserv = { path = "modules/nickserv" }
fedserv-example = { path = "modules/example" }
fedserv-botserv = { path = "modules/botserv" }
fedserv-memoserv = { path = "modules/memoserv" }
fedserv-statserv = { path = "modules/statserv" }
fedserv-hostserv = { path = "modules/hostserv" }
fedserv-operserv = { path = "modules/operserv" }
fedserv-diceserv = { path = "modules/diceserv" }
fedserv-infoserv = { path = "modules/infoserv" }
fedserv-reportserv = { path = "modules/reportserv" }
fedserv-groupserv = { path = "modules/groupserv" }
fedserv-chanfix = { path = "modules/chanfix" }
fedserv-helpserv = { path = "modules/helpserv" }
echo-api = { path = "api" }
echo-inspircd = { path = "modules/protocol/inspircd" }
echo-chanserv = { path = "modules/chanserv" }
echo-nickserv = { path = "modules/nickserv" }
echo-example = { path = "modules/example" }
echo-botserv = { path = "modules/botserv" }
echo-memoserv = { path = "modules/memoserv" }
echo-statserv = { path = "modules/statserv" }
echo-hostserv = { path = "modules/hostserv" }
echo-operserv = { path = "modules/operserv" }
echo-diceserv = { path = "modules/diceserv" }
echo-infoserv = { path = "modules/infoserv" }
echo-reportserv = { path = "modules/reportserv" }
echo-groupserv = { path = "modules/groupserv" }
echo-chanfix = { path = "modules/chanfix" }
echo-helpserv = { path = "modules/helpserv" }
tokio = { version = "1", features = ["net", "io-util", "rt-multi-thread", "macros", "time", "sync", "process"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"

View file

@ -1,10 +1,10 @@
# Writing a module
fedserv is a small core plus a set of module crates. A module depends on one
crate — `fedserv-api` — and nothing else: not the engine, not the storage, not
Echo is a small core plus a set of module crates. A module depends on one
crate — `echo-api` — and nothing else: not the engine, not the storage, not
the network code. That crate carries the traits a module implements and the
normalized vocabulary the engine speaks. If your module compiles against
`fedserv-api`, the core can run it.
`echo-api`, the core can run it.
There are two kinds of module.
@ -21,18 +21,18 @@ minimal service to copy from; `modules/protocol/inspircd/` is the reference prot
```toml
# modules/mymod/Cargo.toml
[package]
name = "fedserv-mymod"
name = "echo-mymod"
version = "0.0.1"
edition = "2021"
[dependencies]
fedserv-api = { path = "../../api" }
echo-api = { path = "../../api" }
```
**2. The service.** A plain struct implementing `Service`:
```rust
use fedserv_api::{NetView, Sender, Service, ServiceCtx, Store};
use echo_api::{NetView, Sender, Service, ServiceCtx, Store};
pub struct MyServ {
pub uid: String, // assigned by the daemon
@ -79,14 +79,14 @@ an IRC-originated one does — you do not write any replication code.
members = [..., "modules/mymod"]
[dependencies]
fedserv-mymod = { path = "modules/mymod" }
echo-mymod = { path = "modules/mymod" }
```
Construct it in `src/main.rs` alongside the others, behind its config name:
```rust
if enabled("mymod") {
services.push(Box::new(fedserv_mymod::MyServ {
services.push(Box::new(echo_mymod::MyServ {
uid: format!("{}AAAAAD", cfg.server.sid), // a stable, unique suffix
}));
}

View file

@ -1,4 +1,4 @@
# fedserv
# Echo
A federated IRC services daemon in Rust. Protocol-agnostic core, InspIRCd link first.
@ -8,9 +8,9 @@ derived from any project's source.
## Design
The core lives in `src/`. The pluggable parts are separate crates in a Cargo
workspace, each depending only on the `fedserv-api` SDK crate.
workspace, each depending only on the `echo-api` SDK crate.
- **`api/`** (`fedserv-api`) the module SDK: the `Service`, `Protocol`, `Store`
- **`api/`** (`echo-api`) the module SDK: the `Service`, `Protocol`, `Store`
and `NetView` traits a module implements or is handed, plus the normalized
`NetEvent`/`NetAction` vocabulary and the read views. It has no storage or
runtime dependencies, so a third-party module builds against it alone.
@ -21,8 +21,8 @@ workspace, each depending only on the `fedserv-api` SDK crate.
stay out of a module's reach.
- **`src/gossip.rs`** node-to-node replication over the logs.
- **`modules/`** the loadable modules, each its own crate depending only on the
`fedserv-api` SDK:
- **`modules/protocol/inspircd/`** (`fedserv-inspircd`) the ircd link layer. A
`echo-api` SDK:
- **`modules/protocol/inspircd/`** (`echo-inspircd`) the ircd link layer. A
`Protocol` impl maps raw server-to-server lines to and from the normalized
model, so the engine never touches a raw line and a new ircd is one new crate
under `modules/protocol/`.
@ -57,7 +57,7 @@ grows. An account registered on any node works on all of them.
## Directory API (gRPC)
**`src/grpc.rs`** exposes the account/channel directory over gRPC (see
`proto/fedserv.proto`) so a website can mirror it without touching IRC: a
`proto/echo.proto`) so a website can mirror it without touching IRC: a
one-shot `Snapshot` for the initial load, then `Subscribe` for a live stream of
every change from that point on. It subscribes to the same committed-entry
channel gossip does, so a change reaches a subscriber in the same push, no
@ -77,7 +77,7 @@ calls do not re-check the account's own password (an admin-level override, the
same trust model a JSON-RPC integration to another services package would
use) — `Register` and `Authenticate` are the two exceptions, since the
password is the actual input there. A write committed this way replicates to
every other fedserv node exactly like an IRC-originated one does — gossip
every other Echo node exactly like an IRC-originated one does — gossip
doesn't know or care where it came from.
## Config

View file

@ -1,5 +1,5 @@
[package]
name = "fedserv-api"
name = "echo-api"
version = "0.0.1"
edition = "2021"
description = "Stable module SDK: the traits and vocabulary a service or protocol module builds against."

View file

@ -1,10 +1,10 @@
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Server only: the Rust side never needs to dial itself as a gRPC client.
// Django (or any other consumer) generates its own stub from proto/fedserv.proto.
// Django (or any other consumer) generates its own stub from proto/echo.proto.
tonic_build::configure()
.build_server(true)
.build_client(false)
.compile_protos(&["proto/fedserv.proto"], &["proto"])?;
println!("cargo:rerun-if-changed=proto/fedserv.proto");
.compile_protos(&["proto/echo.proto"], &["proto"])?;
println!("cargo:rerun-if-changed=proto/echo.proto");
Ok(())
}

View file

@ -26,7 +26,7 @@ protocol = 1206 # InspIRCd link protocol version (1206 = insp4, 1205
# name = "other-node" # TLS name to expect; must match the peer certificate
# Directory replication (gRPC) — lets a website mirror the account/channel
# directory (identity + metadata only, never credentials; see proto/fedserv.proto).
# directory (identity + metadata only, never credentials; see proto/echo.proto).
# Omit this section to run without it.
# [grpc]
# bind = "127.0.0.1:50051" # a private network hop is the expected deployment
@ -76,12 +76,12 @@ protocol = 1206 # InspIRCd link protocol version (1206 = insp4, 1205
# [session]
# default_limit = 3
# Account authority. Omit this section (the default) and fedserv owns accounts
# Account authority. Omit this section (the default) and Echo owns accounts
# itself: NickServ REGISTER / IDENTIFY / SET PASSWORD all work standalone, no
# external service needed. Set external = true to hand identity to an outside
# authority (e.g. your website): IRC can then only IDENTIFY — REGISTER, DROP,
# SET PASSWORD/EMAIL, RESETPASS, CONFIRM, CERT and GROUP are refused, and the
# authority pushes accounts in via the gRPC Accounts API (see [grpc]). fedserv
# authority pushes accounts in via the gRPC Accounts API (see [grpc]). Echo
# still owns all channel/vhost/ban data, keyed by the account name.
# [auth]
# external = true

View file

@ -1,8 +1,8 @@
[package]
name = "fedserv-botserv"
name = "echo-botserv"
version = "0.0.1"
edition = "2021"
description = "BotServ: registers and manages service bots that sit in channels."
[dependencies]
fedserv-api = { path = "../../api" }
echo-api = { path = "../../api" }

View file

@ -1,4 +1,4 @@
use fedserv_api::{Priv, Sender, ServiceCtx, Store};
use echo_api::{Priv, Sender, ServiceCtx, Store};
// ASSIGN <#channel> <bot> / UNASSIGN <#channel>: put a bot in a channel (or take
// it out). Channel founder only (or a services admin).

View file

@ -1,4 +1,4 @@
use fedserv_api::{ChanError, Sender, ServiceCtx, Store};
use echo_api::{ChanError, Sender, ServiceCtx, Store};
// BADWORDS <#channel> ADD <regex> | DEL <regex> | LIST | CLEAR: manage the
// channel's badword patterns. Each entry is a regular expression, so a channel

View file

@ -1,4 +1,4 @@
use fedserv_api::{ChanError, Priv, Sender, ServiceCtx, Store};
use echo_api::{ChanError, Priv, Sender, ServiceCtx, Store};
// BOT ADD <nick> <user> <host> [gecos] | BOT DEL <nick> | BOT LIST — manage the
// bot registry. Administering bots is oper-only (Priv::Admin).

View file

@ -1,4 +1,4 @@
use fedserv_api::{Sender, ServiceCtx, Store};
use echo_api::{Sender, ServiceCtx, Store};
// COPY <#source> <#dest>: copy a channel's bot configuration — kickers,
// badwords, greet and nobot — onto another. Requires founder-or-admin on both.

View file

@ -1,4 +1,4 @@
use fedserv_api::{Sender, ServiceCtx, Store};
use echo_api::{Sender, ServiceCtx, Store};
// INFO <bot> — describe a bot and list the channels it serves.
// INFO <#channel> — show which bot (if any) is assigned to a channel.

View file

@ -1,4 +1,4 @@
use fedserv_api::{Kicker, Sender, ServiceCtx, Store};
use echo_api::{Kicker, Sender, ServiceCtx, Store};
// KICK <#channel> <type> {ON|OFF} [params]: configure the bot's kickers.
// Types: CAPS [min [percent]], BOLDS, COLORS, UNDERLINES, REVERSES, ITALICS,

View file

@ -2,7 +2,7 @@
//! and (in later slices) run fantasy commands. `lib.rs` holds the dispatcher;
//! each command lives in its own file, matching NickServ/ChanServ.
use fedserv_api::{NetView, Priv, Sender, Service, ServiceCtx, Store};
use echo_api::{NetView, Priv, Sender, Service, ServiceCtx, Store};
#[path = "bot.rs"]
mod bot;

View file

@ -1,4 +1,4 @@
use fedserv_api::{NetView, Priv, Sender, ServiceCtx, Store};
use echo_api::{NetView, Priv, Sender, ServiceCtx, Store};
// SAY <#channel> <text> — make the channel's assigned bot say something.
// ACT <#channel> <text> — the same, as a CTCP ACTION (/me).

View file

@ -1,4 +1,4 @@
use fedserv_api::{parse_duration, ChanSetting, Priv, Sender, ServiceCtx, Store};
use echo_api::{parse_duration, ChanSetting, Priv, Sender, ServiceCtx, Store};
// SET <#channel> <option> <value>: per-channel bot options (founder-or-admin) —
// GREET <on|off>, BANEXPIRE <duration|off>, NOBOT <on|off>. Also

View file

@ -1,4 +1,4 @@
use fedserv_api::{ChanError, Sender, ServiceCtx, Store};
use echo_api::{ChanError, Sender, ServiceCtx, Store};
// TRIGGER <#channel> ADD <regex>|<response> | DEL <num> | LIST | CLEAR: manage
// the channel's auto-responses. When a line matches <regex>, the assigned bot

View file

@ -1,8 +1,8 @@
[package]
name = "fedserv-chanfix"
name = "echo-chanfix"
version = "0.0.1"
edition = "2021"
description = "ChanFix: reop opless unregistered channels from accumulated op-time scores."
[dependencies]
fedserv-api = { path = "../../api" }
echo-api = { path = "../../api" }

View file

@ -1,4 +1,4 @@
use fedserv_api::{NetView, Sender, ServiceCtx, Store};
use echo_api::{NetView, Sender, ServiceCtx, Store};
// A channel with this many ops isn't opless and needs no fix.
const OP_THRESHOLD: usize = 3;

View file

@ -6,7 +6,7 @@
//! SCORES <#channel> shows the standings; CHANFIX <#channel> performs the fix.
//! `lib.rs` holds the dispatcher; each command lives in its own file.
use fedserv_api::{NetView, Sender, Service, ServiceCtx, Store};
use echo_api::{NetView, Sender, Service, ServiceCtx, Store};
#[path = "scores.rs"]
mod scores;

View file

@ -1,4 +1,4 @@
use fedserv_api::{NetView, Sender, ServiceCtx};
use echo_api::{NetView, Sender, ServiceCtx};
// SCORES <#channel>: show the op-time standings ChanFix would reop from.
pub fn handle(me: &str, from: &Sender, chan: Option<&str>, ctx: &mut ServiceCtx, net: &dyn NetView) {

View file

@ -1,8 +1,8 @@
[package]
name = "fedserv-chanserv"
name = "echo-chanserv"
version = "0.0.1"
edition = "2021"
description = "ChanServ channel-registration service module for fedserv."
description = "ChanServ channel-registration service module for echo."
[dependencies]
fedserv-api = { path = "../../api" }
echo-api = { path = "../../api" }

View file

@ -1,5 +1,5 @@
use fedserv_api::Store;
use fedserv_api::{Sender, ServiceCtx};
use echo_api::Store;
use echo_api::{Sender, ServiceCtx};
// ACCESS <#channel> LIST | ADD <account> <op|voice> | DEL <account>
pub fn handle(me: &str, from: &Sender, args: &[&str], ctx: &mut ServiceCtx, db: &mut dyn Store) {

View file

@ -1,5 +1,5 @@
use fedserv_api::Store;
use fedserv_api::{Sender, ServiceCtx};
use echo_api::Store;
use echo_api::{Sender, ServiceCtx};
// AKICK <#channel> ADD <mask> [reason] | DEL <mask> | LIST
// Masks are nick!user@host globs; matching users are banned and kicked on join.

View file

@ -1,6 +1,6 @@
use fedserv_api::Store;
use fedserv_api::{Sender, ServiceCtx};
use fedserv_api::NetView;
use echo_api::Store;
use echo_api::{Sender, ServiceCtx};
use echo_api::NetView;
// BAN <#channel> <nick> [reason]: ban *!*@host and kick the user.
pub fn handle(me: &str, from: &Sender, args: &[&str], ctx: &mut ServiceCtx, net: &dyn NetView, db: &dyn Store) {

View file

@ -1,5 +1,5 @@
use fedserv_api::Store;
use fedserv_api::{Sender, ServiceCtx};
use echo_api::Store;
use echo_api::{Sender, ServiceCtx};
// CLONE <source> <target>: copy a channel's settings (mode lock, access,
// auto-kick, description, entry message) into another. Founder of both.

View file

@ -1,6 +1,6 @@
use fedserv_api::Store;
use fedserv_api::{Sender, ServiceCtx};
use fedserv_api::NetView;
use echo_api::Store;
use echo_api::{Sender, ServiceCtx};
use echo_api::NetView;
// ENFORCE <#channel>: re-apply the channel's settings to everyone present —
// the mode lock, access status modes, and the auto-kick list.

View file

@ -1,5 +1,5 @@
use fedserv_api::Store;
use fedserv_api::{Sender, ServiceCtx};
use echo_api::Store;
use echo_api::{Sender, ServiceCtx};
// ENTRYMSG <#channel> [CLEAR | <text>]: message noticed to users as they join.
// With no argument, show the current message.

View file

@ -1,4 +1,4 @@
use fedserv_api::{apply_flags, Sender, ServiceCtx, Store, ACCESS_FLAGS};
use echo_api::{apply_flags, Sender, ServiceCtx, Store, ACCESS_FLAGS};
// FLAGS <#channel> [account [+/-flags]]: the granular access model. With no
// account, list the access entries and their flags; with an account, show or

View file

@ -1,6 +1,6 @@
use fedserv_api::Store;
use fedserv_api::{Sender, ServiceCtx};
use fedserv_api::NetView;
use echo_api::Store;
use echo_api::{Sender, ServiceCtx};
use echo_api::NetView;
// GETKEY <#channel>: report the channel key (+k), for ops who need to let
// someone in.

View file

@ -1,6 +1,6 @@
use fedserv_api::Store;
use fedserv_api::{Sender, ServiceCtx};
use fedserv_api::NetView;
use echo_api::Store;
use echo_api::{Sender, ServiceCtx};
use echo_api::NetView;
// INVITE <#channel> [nick]: invite a user (self if no nick) into the channel.
pub fn handle(me: &str, from: &Sender, args: &[&str], ctx: &mut ServiceCtx, net: &dyn NetView, db: &dyn Store) {

View file

@ -1,6 +1,6 @@
use fedserv_api::Store;
use fedserv_api::{Sender, ServiceCtx};
use fedserv_api::NetView;
use echo_api::Store;
use echo_api::{Sender, ServiceCtx};
use echo_api::NetView;
// KICK <#channel> <nick> [reason]: kick a user.
pub fn handle(me: &str, from: &Sender, args: &[&str], ctx: &mut ServiceCtx, net: &dyn NetView, db: &dyn Store) {

View file

@ -1,6 +1,6 @@
use fedserv_api::{ChanError, ChannelView, Priv, Store};
use fedserv_api::{Sender, Service, ServiceCtx};
use fedserv_api::NetView;
use echo_api::{ChanError, ChannelView, Priv, Store};
use echo_api::{Sender, Service, ServiceCtx};
use echo_api::NetView;
#[path = "mode.rs"]
mod mode;
@ -109,7 +109,7 @@ impl Service for ChanServ {
if !info.desc.is_empty() {
ctx.notice(me, from.uid, format!(" Description: {}", info.desc));
}
ctx.notice(me, from.uid, format!(" Registered : {}", fedserv_api::human_time(info.ts)));
ctx.notice(me, from.uid, format!(" Registered : {}", echo_api::human_time(info.ts)));
if let Some(s) = db.channel_suspension(chan) {
ctx.notice(me, from.uid, format!(" Suspended : by \x02{}\x02{}", s.by, s.reason));
}

View file

@ -1,5 +1,5 @@
use fedserv_api::Store;
use fedserv_api::{Sender, ServiceCtx};
use echo_api::Store;
use echo_api::{Sender, ServiceCtx};
// LIST: show all registered channels.
pub fn handle(me: &str, from: &Sender, _args: &[&str], ctx: &mut ServiceCtx, db: &dyn Store) {

View file

@ -1,5 +1,5 @@
use fedserv_api::Store;
use fedserv_api::{Sender, ServiceCtx};
use echo_api::Store;
use echo_api::{Sender, ServiceCtx};
// MODE <#channel> <modes>: the founder sets channel modes via ChanServ.
pub fn handle(me: &str, from: &Sender, args: &[&str], ctx: &mut ServiceCtx, db: &mut dyn Store) {

View file

@ -1,4 +1,4 @@
use fedserv_api::{Priv, Sender, ServiceCtx, Store};
use echo_api::{Priv, Sender, ServiceCtx, Store};
// NOEXPIRE <#channel> {ON|OFF}: pin a channel so inactivity-expiry never drops
// it (or lift the pin). Oper-only (Priv::Admin).

View file

@ -1,6 +1,6 @@
use fedserv_api::Store;
use fedserv_api::{Sender, ServiceCtx};
use fedserv_api::NetView;
use echo_api::Store;
use echo_api::{Sender, ServiceCtx};
use echo_api::NetView;
// OP/DEOP/VOICE/DEVOICE <#channel> [nick]: set a status mode on a user (self if
// no nick given). `mode` is the mode to apply, e.g. "+o".

View file

@ -1,5 +1,5 @@
use fedserv_api::{Sender, ServiceCtx};
use fedserv_api::NetView;
use echo_api::{Sender, ServiceCtx};
use echo_api::NetView;
// SEEN <nick>: when a nick was last seen, and doing what.
pub fn handle(me: &str, from: &Sender, args: &[&str], ctx: &mut ServiceCtx, net: &dyn NetView) {
@ -12,7 +12,7 @@ pub fn handle(me: &str, from: &Sender, args: &[&str], ctx: &mut ServiceCtx, net:
return;
}
match net.last_seen(nick) {
Some(s) => ctx.notice(me, from.uid, format!("\x02{}\x02 was last seen {} ({}).", s.nick, fedserv_api::human_time(s.ts), s.what)),
Some(s) => ctx.notice(me, from.uid, format!("\x02{}\x02 was last seen {} ({}).", s.nick, echo_api::human_time(s.ts), s.what)),
None => ctx.notice(me, from.uid, format!("I have no record of \x02{nick}\x02.")),
}
}

View file

@ -1,4 +1,4 @@
use fedserv_api::{ChanSetting, Sender, ServiceCtx, Store};
use echo_api::{ChanSetting, Sender, ServiceCtx, Store};
// SET <#channel> FOUNDER <account> | DESC <text>: founder-only channel settings.
pub fn handle(me: &str, from: &Sender, args: &[&str], ctx: &mut ServiceCtx, db: &mut dyn Store) {

View file

@ -1,6 +1,6 @@
use fedserv_api::Store;
use fedserv_api::{Sender, ServiceCtx};
use fedserv_api::NetView;
use echo_api::Store;
use echo_api::{Sender, ServiceCtx};
use echo_api::NetView;
// STATUS <#channel> [nick]: show a user's access level (self if no nick).
pub fn handle(me: &str, from: &Sender, args: &[&str], ctx: &mut ServiceCtx, net: &dyn NetView, db: &dyn Store) {

View file

@ -1,4 +1,4 @@
use fedserv_api::{parse_duration, NetView, Priv, Sender, ServiceCtx, Store};
use echo_api::{parse_duration, NetView, Priv, Sender, ServiceCtx, Store};
use std::time::{SystemTime, UNIX_EPOCH};
// SUSPEND <#channel> [+expiry] [reason] / UNSUSPEND <#channel>: freeze or unfreeze

View file

@ -1,5 +1,5 @@
use fedserv_api::Store;
use fedserv_api::{Sender, ServiceCtx};
use echo_api::Store;
use echo_api::{Sender, ServiceCtx};
// TOPIC <#channel> <text>: set the channel topic (empty clears it).
pub fn handle(me: &str, from: &Sender, args: &[&str], ctx: &mut ServiceCtx, db: &dyn Store) {

View file

@ -1,6 +1,6 @@
use fedserv_api::Store;
use fedserv_api::{Sender, ServiceCtx};
use fedserv_api::NetView;
use echo_api::Store;
use echo_api::{Sender, ServiceCtx};
use echo_api::NetView;
// UNBAN <#channel> [nick]: remove the *!*@host ban of a user (self if no nick).
pub fn handle(me: &str, from: &Sender, args: &[&str], ctx: &mut ServiceCtx, net: &dyn NetView, db: &dyn Store) {

View file

@ -1,5 +1,5 @@
use fedserv_api::Store;
use fedserv_api::{Sender, ServiceCtx};
use echo_api::Store;
use echo_api::{Sender, ServiceCtx};
// AOP/SOP/VOP <#channel> ADD <account> | DEL <account> | LIST — tiered
// shortcuts over the access list. `level` is the access level they map to

View file

@ -1,9 +1,9 @@
[package]
name = "fedserv-diceserv"
name = "echo-diceserv"
version = "0.0.1"
edition = "2021"
description = "DiceServ: a dice-roll and math-expression service for tabletop games over IRC."
[dependencies]
fedserv-api = { path = "../../api" }
echo-api = { path = "../../api" }
rand = "0.8"

View file

@ -6,7 +6,7 @@
//! `lib.rs` holds the dispatcher; the command lives in roll.rs and the
//! expression evaluator in expr.rs.
use fedserv_api::{NetView, Sender, Service, ServiceCtx, Store};
use echo_api::{NetView, Sender, Service, ServiceCtx, Store};
#[path = "expr.rs"]
mod expr;

View file

@ -1,4 +1,4 @@
use fedserv_api::{Sender, ServiceCtx};
use echo_api::{Sender, ServiceCtx};
use super::expr;

View file

@ -1,8 +1,8 @@
[package]
name = "fedserv-example"
name = "echo-example"
version = "0.0.1"
edition = "2021"
description = "A minimal example service module: the template a new pseudo-client is copied from."
[dependencies]
fedserv-api = { path = "../../api" }
echo-api = { path = "../../api" }

View file

@ -1,6 +1,6 @@
//! A minimal example service module — the smallest complete `Service`, meant to
//! be copied when writing a new pseudo-client. It depends on nothing but the
//! `fedserv-api` SDK crate, reads through the `Store`/`NetView` traits, and
//! `echo-api` SDK crate, reads through the `Store`/`NetView` traits, and
//! answers users by pushing notices onto the `ServiceCtx`. It never mutates the
//! store, so it is safe to enable anywhere.
//!
@ -8,7 +8,7 @@
//! real module, replace the commands below with your own and register the struct
//! in the daemon's `main.rs` (see MODULES.md).
use fedserv_api::{human_time, NetView, Sender, Service, ServiceCtx, Store};
use echo_api::{human_time, NetView, Sender, Service, ServiceCtx, Store};
// A service is a plain struct. It is introduced to the network at burst and then
// receives the commands users message it. `uid` is assigned by the daemon.

View file

@ -1,8 +1,8 @@
[package]
name = "fedserv-groupserv"
name = "echo-groupserv"
version = "0.0.1"
edition = "2021"
description = "GroupServ: user groups (!name) whose members can be granted channel access together."
[dependencies]
fedserv-api = { path = "../../api" }
echo-api = { path = "../../api" }

View file

@ -1,4 +1,4 @@
use fedserv_api::{Sender, ServiceCtx, Store};
use echo_api::{Sender, ServiceCtx, Store};
// ADD <!group> <account>: add a plain member (no flags). Needs founder or `f`.
pub fn handle(me: &str, from: &Sender, name: Option<&str>, target: Option<&str>, ctx: &mut ServiceCtx, db: &mut dyn Store) {

View file

@ -1,4 +1,4 @@
use fedserv_api::{Sender, ServiceCtx, Store};
use echo_api::{Sender, ServiceCtx, Store};
// DEL <!group> <account>: remove a member. Needs founder or the `f` flag.
pub fn handle(me: &str, from: &Sender, name: Option<&str>, target: Option<&str>, ctx: &mut ServiceCtx, db: &mut dyn Store) {

View file

@ -1,4 +1,4 @@
use fedserv_api::{Sender, ServiceCtx, Store};
use echo_api::{Sender, ServiceCtx, Store};
// DROP <!group>: delete a group. Founder only.
pub fn handle(me: &str, from: &Sender, name: Option<&str>, ctx: &mut ServiceCtx, db: &mut dyn Store) {

View file

@ -1,4 +1,4 @@
use fedserv_api::{apply_flags, Sender, ServiceCtx, Store, GROUP_FLAGS};
use echo_api::{apply_flags, Sender, ServiceCtx, Store, GROUP_FLAGS};
// FLAGS <!group> [account [+/-flags]]: list, show, or change group-access flags.
// Listing/showing is open; changing needs the founder or the `f` flag.

View file

@ -1,4 +1,4 @@
use fedserv_api::{Sender, ServiceCtx, Store};
use echo_api::{Sender, ServiceCtx, Store};
// INFO <!group>: show a group's founder and member count.
pub fn handle(me: &str, from: &Sender, name: Option<&str>, ctx: &mut ServiceCtx, db: &mut dyn Store) {

View file

@ -8,7 +8,7 @@
//! `lib.rs` holds the dispatcher and the two shared guards; each command lives
//! in its own file.
use fedserv_api::{NetView, Sender, Service, ServiceCtx, Store};
use echo_api::{NetView, Sender, Service, ServiceCtx, Store};
#[path = "register.rs"]
mod register;
@ -68,7 +68,7 @@ fn account<'a>(me: &str, from: &'a Sender, ctx: &mut ServiceCtx) -> Option<&'a s
}
// Whether `who` may manage `group` (founder, or holds the F/f flag).
fn can_manage(group: &fedserv_api::GroupView, who: &str) -> bool {
fn can_manage(group: &echo_api::GroupView, who: &str) -> bool {
group.founder.eq_ignore_ascii_case(who)
|| group.members.iter().any(|m| m.account.eq_ignore_ascii_case(who) && (m.flags.contains('F') || m.flags.contains('f')))
}

View file

@ -1,4 +1,4 @@
use fedserv_api::{Sender, ServiceCtx, Store};
use echo_api::{Sender, ServiceCtx, Store};
// LIST: operators see every group; others see the ones they belong to.
pub fn handle(me: &str, from: &Sender, ctx: &mut ServiceCtx, db: &mut dyn Store) {

View file

@ -1,4 +1,4 @@
use fedserv_api::{Sender, ServiceCtx, Store};
use echo_api::{Sender, ServiceCtx, Store};
// REGISTER <!group>: create a group with you as its founder.
pub fn handle(me: &str, from: &Sender, name: Option<&str>, ctx: &mut ServiceCtx, db: &mut dyn Store) {
@ -14,7 +14,7 @@ pub fn handle(me: &str, from: &Sender, name: Option<&str>, ctx: &mut ServiceCtx,
let acc = acc.to_string();
match db.group_register(name, &acc) {
Ok(()) => ctx.notice(me, from.uid, format!("Group \x02{name}\x02 registered — you're the founder.")),
Err(fedserv_api::ChanError::Exists) => ctx.notice(me, from.uid, format!("\x02{name}\x02 is already registered.")),
Err(echo_api::ChanError::Exists) => ctx.notice(me, from.uid, format!("\x02{name}\x02 is already registered.")),
Err(_) => ctx.notice(me, from.uid, "Sorry, that didn't work. Please try again in a moment."),
}
}

View file

@ -1,8 +1,8 @@
[package]
name = "fedserv-helpserv"
name = "echo-helpserv"
version = "0.0.1"
edition = "2021"
description = "HelpServ: a help-desk queue — users ask, operators take and answer."
[dependencies]
fedserv-api = { path = "../../api" }
echo-api = { path = "../../api" }

View file

@ -1,4 +1,4 @@
use fedserv_api::{Sender, ServiceCtx, Store};
use echo_api::{Sender, ServiceCtx, Store};
// CANCEL: withdraw your own newest open ticket.
pub fn handle(me: &str, from: &Sender, ctx: &mut ServiceCtx, db: &mut dyn Store) {

View file

@ -1,4 +1,4 @@
use fedserv_api::{Sender, ServiceCtx, Store};
use echo_api::{Sender, ServiceCtx, Store};
// CLOSE <id> (aka RESOLVE): resolve a ticket.
pub fn handle(me: &str, from: &Sender, id: Option<&str>, ctx: &mut ServiceCtx, db: &mut dyn Store) {

View file

@ -7,7 +7,7 @@
//! `lib.rs` holds the dispatcher and the shared guard/claim helpers; each
//! command lives in its own file.
use fedserv_api::{NetView, Sender, Service, ServiceCtx, Store};
use echo_api::{NetView, Sender, Service, ServiceCtx, Store};
#[path = "request.rs"]
mod request;

View file

@ -1,4 +1,4 @@
use fedserv_api::{Sender, ServiceCtx, Store};
use echo_api::{Sender, ServiceCtx, Store};
// LIST [ALL]: operators list the open queue (or every ticket with ALL).
pub fn handle(me: &str, from: &Sender, arg: Option<&str>, ctx: &mut ServiceCtx, db: &mut dyn Store) {

View file

@ -1,4 +1,4 @@
use fedserv_api::{Sender, ServiceCtx, Store};
use echo_api::{Sender, ServiceCtx, Store};
// NEXT: claim the oldest unassigned ticket.
pub fn handle(me: &str, from: &Sender, ctx: &mut ServiceCtx, db: &mut dyn Store) {

View file

@ -1,4 +1,4 @@
use fedserv_api::{Sender, ServiceCtx, Store};
use echo_api::{Sender, ServiceCtx, Store};
// REQUEST <message> (aka HELPME): open a help-desk ticket for the staff.
pub fn handle(me: &str, from: &Sender, rest: &[&str], ctx: &mut ServiceCtx, db: &mut dyn Store) {

View file

@ -1,4 +1,4 @@
use fedserv_api::{Sender, ServiceCtx, Store};
use echo_api::{Sender, ServiceCtx, Store};
// TAKE <id> (aka ASSIGN): claim a specific ticket.
pub fn handle(me: &str, from: &Sender, id: Option<&str>, ctx: &mut ServiceCtx, db: &mut dyn Store) {

View file

@ -1,4 +1,4 @@
use fedserv_api::{human_time, Sender, ServiceCtx, Store};
use echo_api::{human_time, Sender, ServiceCtx, Store};
// VIEW <id> (aka READ): operators read a ticket in full.
pub fn handle(me: &str, from: &Sender, id: Option<&str>, ctx: &mut ServiceCtx, db: &mut dyn Store) {

View file

@ -1,8 +1,8 @@
[package]
name = "fedserv-hostserv"
name = "echo-hostserv"
version = "0.0.1"
edition = "2021"
description = "HostServ: assign and apply virtual hosts (vhosts)."
[dependencies]
fedserv-api = { path = "../../api" }
echo-api = { path = "../../api" }

View file

@ -1,4 +1,4 @@
use fedserv_api::{NetView, Sender, ServiceCtx, Store};
use echo_api::{NetView, Sender, ServiceCtx, Store};
// ACTIVATE <account> / REJECT <account>: approve a pending vhost request (setting
// and applying it) or turn it down. Operators only.

View file

@ -1,4 +1,4 @@
use fedserv_api::{Sender, ServiceCtx, Store};
use echo_api::{Sender, ServiceCtx, Store};
// DEFAULT: give yourself the auto-vhost from the network template, with your
// account name substituted for $account.

View file

@ -1,4 +1,4 @@
use fedserv_api::{NetView, Sender, ServiceCtx, Store};
use echo_api::{NetView, Sender, ServiceCtx, Store};
// DEL <account>: remove an account's vhost, restoring the normal host on any
// online sessions. Operators only.

View file

@ -1,4 +1,4 @@
use fedserv_api::{Sender, ServiceCtx, Store};
use echo_api::{Sender, ServiceCtx, Store};
// FORBID <pattern>: block user-requested vhosts matching this regex (operators),
// e.g. (?i)(oper|admin|staff|services) to stop impersonation.

View file

@ -3,7 +3,7 @@
//! with SET/DEL and review with LIST. `lib.rs` holds the dispatcher; each
//! command lives in its own file.
use fedserv_api::{NetView, Priv, Sender, Service, ServiceCtx, Store};
use echo_api::{NetView, Priv, Sender, Service, ServiceCtx, Store};
#[path = "on.rs"]
mod on;

View file

@ -1,4 +1,4 @@
use fedserv_api::{Sender, ServiceCtx, Store};
use echo_api::{Sender, ServiceCtx, Store};
// LIST: every account with an assigned vhost. Operators only.
pub fn handle(me: &str, from: &Sender, ctx: &mut ServiceCtx, db: &dyn Store) {

View file

@ -1,4 +1,4 @@
use fedserv_api::{NetView, Sender, ServiceCtx, Store};
use echo_api::{NetView, Sender, ServiceCtx, Store};
// OFF: restore your normal host for this session (the vhost stays assigned and
// re-applies next time you identify).

View file

@ -1,4 +1,4 @@
use fedserv_api::{Sender, ServiceCtx, Store};
use echo_api::{Sender, ServiceCtx, Store};
// OFFER <host>: add a vhost to the self-serve menu (operators).
pub fn add(me: &str, from: &Sender, args: &[&str], ctx: &mut ServiceCtx, db: &mut dyn Store) {

View file

@ -1,4 +1,4 @@
use fedserv_api::{Sender, ServiceCtx, Store};
use echo_api::{Sender, ServiceCtx, Store};
// ON: activate the vhost assigned to your account.
pub fn handle(me: &str, from: &Sender, ctx: &mut ServiceCtx, db: &dyn Store) {

View file

@ -1,4 +1,4 @@
use fedserv_api::{Sender, ServiceCtx, Store};
use echo_api::{Sender, ServiceCtx, Store};
// REQUEST <host>: ask for a vhost, to be approved by an operator.
pub fn handle(me: &str, from: &Sender, args: &[&str], ctx: &mut ServiceCtx, db: &mut dyn Store) {

View file

@ -1,4 +1,4 @@
use fedserv_api::{parse_duration, NetView, Sender, ServiceCtx, Store};
use echo_api::{parse_duration, NetView, Sender, ServiceCtx, Store};
// SET <account> <host> [duration]: assign a vhost to an account, applying it at
// once to online sessions. An optional duration (e.g. 30d) makes it temporary.

View file

@ -1,4 +1,4 @@
use fedserv_api::{Sender, ServiceCtx, Store};
use echo_api::{Sender, ServiceCtx, Store};
// TAKE <number>: assign yourself the vhost offered at that position on the menu.
pub fn handle(me: &str, from: &Sender, args: &[&str], ctx: &mut ServiceCtx, db: &mut dyn Store) {

View file

@ -1,4 +1,4 @@
use fedserv_api::{Sender, ServiceCtx, Store};
use echo_api::{Sender, ServiceCtx, Store};
// TEMPLATE [<pattern>]: show the auto-vhost template, or (operators) set it.
// Use $account for the requester's sanitised account name, e.g.

View file

@ -1,4 +1,4 @@
use fedserv_api::{Sender, ServiceCtx, Store};
use echo_api::{Sender, ServiceCtx, Store};
// WAITING: pending vhost requests awaiting approval. Operators only.
pub fn handle(me: &str, from: &Sender, ctx: &mut ServiceCtx, db: &dyn Store) {

View file

@ -1,8 +1,8 @@
[package]
name = "fedserv-infoserv"
name = "echo-infoserv"
version = "0.0.1"
edition = "2021"
description = "InfoServ: network information bulletins shown on connect (public) and on oper login."
[dependencies]
fedserv-api = { path = "../../api" }
echo-api = { path = "../../api" }

View file

@ -1,4 +1,4 @@
use fedserv_api::{Priv, Sender, ServiceCtx, Store};
use echo_api::{Priv, Sender, ServiceCtx, Store};
// DEL/ODEL <number>: remove a bulletin by its listed position. Admin only.
pub fn handle(me: &str, from: &Sender, kind: &str, num: Option<&str>, ctx: &mut ServiceCtx, db: &mut dyn Store) {

View file

@ -9,7 +9,7 @@
//! and any operator may OLIST. `lib.rs` holds the dispatcher; each command
//! (parameterised by bulletin kind) lives in its own file.
use fedserv_api::{NetView, Sender, Service, ServiceCtx, Store};
use echo_api::{NetView, Sender, Service, ServiceCtx, Store};
#[path = "post.rs"]
mod post;

View file

@ -1,4 +1,4 @@
use fedserv_api::{Sender, ServiceCtx, Store};
use echo_api::{Sender, ServiceCtx, Store};
// LIST/OLIST: show the bulletins of a kind. Public is open; oper is oper-only.
pub fn handle(me: &str, from: &Sender, kind: &str, oper_only: bool, ctx: &mut ServiceCtx, db: &mut dyn Store) {

View file

@ -1,4 +1,4 @@
use fedserv_api::{Priv, Sender, ServiceCtx, Store};
use echo_api::{Priv, Sender, ServiceCtx, Store};
// POST/OPOST <message>: add a bulletin (public or oper). Admin only.
pub fn handle(me: &str, from: &Sender, kind: &str, rest: &[&str], ctx: &mut ServiceCtx, db: &mut dyn Store) {

View file

@ -1,8 +1,8 @@
[package]
name = "fedserv-memoserv"
name = "echo-memoserv"
version = "0.0.1"
edition = "2021"
description = "MemoServ: deliver messages to registered users, online or not."
[dependencies]
fedserv-api = { path = "../../api" }
echo-api = { path = "../../api" }

View file

@ -1,4 +1,4 @@
use fedserv_api::{Sender, ServiceCtx, Store};
use echo_api::{Sender, ServiceCtx, Store};
// DEL <num>|ALL: remove a memo (or the whole mailbox).
pub fn handle(me: &str, from: &Sender, account: &str, args: &[&str], ctx: &mut ServiceCtx, db: &mut dyn Store) {

View file

@ -4,7 +4,7 @@
//! account data. `lib.rs` holds the dispatcher; each command lives in its own
//! file, matching NickServ/ChanServ.
use fedserv_api::{NetView, Sender, Service, ServiceCtx, Store};
use echo_api::{NetView, Sender, Service, ServiceCtx, Store};
#[path = "send.rs"]
mod send;

View file

@ -1,4 +1,4 @@
use fedserv_api::{human_time, Sender, ServiceCtx, Store};
use echo_api::{human_time, Sender, ServiceCtx, Store};
// LIST: show every memo with a one-line preview; \x02*\x02 marks unread.
pub fn handle(me: &str, from: &Sender, account: &str, ctx: &mut ServiceCtx, db: &dyn Store) {

View file

@ -1,4 +1,4 @@
use fedserv_api::{human_time, MemoView, Sender, ServiceCtx, Store};
use echo_api::{human_time, MemoView, Sender, ServiceCtx, Store};
// READ <num>|NEW|ALL: display memos and mark them read.
pub fn handle(me: &str, from: &Sender, account: &str, args: &[&str], ctx: &mut ServiceCtx, db: &mut dyn Store) {

View file

@ -1,4 +1,4 @@
use fedserv_api::{Sender, ServiceCtx, Store};
use echo_api::{Sender, ServiceCtx, Store};
// A full mailbox rejects new memos, so nobody can be flooded.
const MAX_MEMOS: usize = 30;

View file

@ -1,8 +1,8 @@
[package]
name = "fedserv-nickserv"
name = "echo-nickserv"
version = "0.0.1"
edition = "2021"
description = "NickServ account-registration service module for fedserv."
description = "NickServ account-registration service module for echo."
[dependencies]
fedserv-api = { path = "../../api" }
echo-api = { path = "../../api" }

View file

@ -1,5 +1,5 @@
use fedserv_api::Store;
use fedserv_api::{Sender, ServiceCtx};
use echo_api::Store;
use echo_api::{Sender, ServiceCtx};
// A sane cap so a runaway list can't bloat an account or flood a user on identify.
const MAX_AJOIN: usize = 25;

View file

@ -1,5 +1,5 @@
use fedserv_api::Store;
use fedserv_api::{Sender, ServiceCtx};
use echo_api::Store;
use echo_api::{Sender, ServiceCtx};
// ALIST: list the channels the sender's account founds or has access on.
pub fn handle(me: &str, from: &Sender, ctx: &mut ServiceCtx, db: &dyn Store) {

View file

@ -1,5 +1,5 @@
use fedserv_api::{CertError, Store};
use fedserv_api::{Sender, ServiceCtx};
use echo_api::{CertError, Store};
use echo_api::{Sender, ServiceCtx};
// CERT ADD|DEL|LIST <password> [fingerprint]: manage the TLS certificate
// fingerprints that may log in to your account via SASL EXTERNAL. Each

View file

@ -1,5 +1,5 @@
use fedserv_api::{CodeKind, Store};
use fedserv_api::{Sender, ServiceCtx};
use echo_api::{CodeKind, Store};
use echo_api::{Sender, ServiceCtx};
// CONFIRM <code>: confirm your account's email with the code you were emailed.
pub fn handle(me: &str, from: &Sender, args: &[&str], ctx: &mut ServiceCtx, db: &mut dyn Store) {

View file

@ -1,6 +1,6 @@
use fedserv_api::Store;
use fedserv_api::{Sender, ServiceCtx};
use fedserv_api::NetView;
use echo_api::Store;
use echo_api::{Sender, ServiceCtx};
use echo_api::NetView;
// DROP <password>: delete your account. Re-authenticates as confirmation, releases
// and drops the channels you found, and logs you out.

Some files were not shown because too many files have changed in this diff Show more