Model euphoria api
This commit is contained in:
parent
03dfe10f3e
commit
de7815f653
9 changed files with 702 additions and 1 deletions
|
|
@ -6,11 +6,13 @@ edition = "2021"
|
|||
[dependencies]
|
||||
anyhow = "1.0.57"
|
||||
async-trait = "0.1.56"
|
||||
chrono = "0.4.19"
|
||||
chrono = { version = "0.4.19", features = ["serde"] }
|
||||
crossterm = "0.23.2"
|
||||
directories = "4.0.1"
|
||||
edit = "0.1.4"
|
||||
parking_lot = "0.12.1"
|
||||
rusqlite = "0.27.0"
|
||||
serde = { version = "1.0.137", features = ["derive"] }
|
||||
serde_json = "1.0.81"
|
||||
tokio = { version = "1.19.2", features = ["full"] }
|
||||
toss = { git = "https://github.com/Garmelon/toss.git", rev = "761519c1a7cdc950eab70fd6539c71bf22919a50" }
|
||||
|
|
|
|||
12
cove-tui/src/euph.rs
Normal file
12
cove-tui/src/euph.rs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
mod api;
|
||||
|
||||
use std::convert::Infallible;
|
||||
|
||||
use tokio::sync::{mpsc, oneshot};
|
||||
|
||||
enum Request {}
|
||||
|
||||
pub struct EuphRoom {
|
||||
canary: oneshot::Sender<Infallible>,
|
||||
tx: mpsc::Sender<Request>,
|
||||
}
|
||||
24
cove-tui/src/euph/api.rs
Normal file
24
cove-tui/src/euph/api.rs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
//! Models the euphoria API at <http://api.euphoria.io/>.
|
||||
|
||||
mod events;
|
||||
mod room_cmds;
|
||||
mod session_cmds;
|
||||
mod types;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
|
||||
pub use events::*;
|
||||
pub use room_cmds::*;
|
||||
pub use session_cmds::*;
|
||||
pub use types::*;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Packet {
|
||||
pub id: Option<String>,
|
||||
pub r#type: PacketType,
|
||||
pub data: Option<Value>,
|
||||
pub error: Option<String>,
|
||||
pub throttled: Option<bool>,
|
||||
pub throttled_reason: Option<String>,
|
||||
}
|
||||
170
cove-tui/src/euph/api/events.rs
Normal file
170
cove-tui/src/euph/api/events.rs
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
//! Asynchronous events.
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::{AuthOption, Message, PersonalAccountView, SessionView, Snowflake, Time, UserId};
|
||||
|
||||
/// Indicates that access to a room is denied.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct BounceEvent {
|
||||
/// The reason why access was denied.
|
||||
pub reason: Option<String>,
|
||||
/// Authentication options that may be used.
|
||||
pub auth_options: Option<Vec<AuthOption>>,
|
||||
/// Internal use only.
|
||||
pub agent_id: Option<UserId>,
|
||||
/// Internal use only.
|
||||
pub ip: Option<String>,
|
||||
}
|
||||
|
||||
/// Indicates that the session is being closed. The client will subsequently be
|
||||
/// disconnected.
|
||||
///
|
||||
/// If the disconnect reason is `authentication changed`, the client should
|
||||
/// immediately reconnect.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct DisconnectEvent {
|
||||
/// The reason for disconnection.
|
||||
pub reason: String,
|
||||
}
|
||||
|
||||
/// Sent by the server to the client when a session is started.
|
||||
///
|
||||
/// It includes information about the client's authentication and associated
|
||||
/// identity.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct HelloEvent {
|
||||
/// The id of the agent or account logged into this session.
|
||||
pub id: UserId,
|
||||
/// Details about the user's account, if the session is logged in.
|
||||
pub account: Option<PersonalAccountView>,
|
||||
/// Details about the session.
|
||||
pub session: SessionView,
|
||||
/// If true, then the account has an explicit access grant to the current
|
||||
/// room.
|
||||
pub account_has_access: Option<bool>,
|
||||
/// Whether the account's email address has been verified.
|
||||
pub account_email_verified: Option<bool>,
|
||||
/// If true, the session is connected to a private room.
|
||||
pub room_is_private: bool,
|
||||
/// The version of the code being run and served by the server.
|
||||
pub version: String,
|
||||
}
|
||||
|
||||
/// Indicates a session just joined the room.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct JoinEvent(pub SessionView);
|
||||
|
||||
/// Sent to all sessions of an agent when that agent is logged in (except for
|
||||
/// the session that issued the login command).
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct LoginEvent {
|
||||
pub account_id: Snowflake,
|
||||
}
|
||||
|
||||
/// Sent to all sessions of an agent when that agent is logged out (except for
|
||||
/// the session that issued the logout command).
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct LogoutEvent;
|
||||
|
||||
/// Indicates some server-side event that impacts the presence of sessions in a
|
||||
/// room.
|
||||
///
|
||||
/// If the network event type is `partition`, then this should be treated as a
|
||||
/// [`PartEvent`] for all sessions connected to the same server id/era combo.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct NetworkEvent {
|
||||
/// The type of network event; for now, always `partition`.
|
||||
pub r#type: String,
|
||||
/// The id of the affected server.
|
||||
pub server_id: String,
|
||||
/// The era of the affected server.
|
||||
pub server_era: String,
|
||||
}
|
||||
|
||||
/// Announces a nick change by another session in the room.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct NickEvent {
|
||||
/// The id of the session this name applies to.
|
||||
pub session_id: String,
|
||||
/// The id of the agent or account logged into the session.
|
||||
pub id: UserId,
|
||||
/// The previous name associated with the session.
|
||||
pub from: String,
|
||||
/// The name associated with the session henceforth.
|
||||
pub to: String,
|
||||
}
|
||||
|
||||
/// Indicates that a message in the room has been modified or deleted.
|
||||
///
|
||||
/// If the client offers a user interface and the indicated message is currently
|
||||
/// displayed, it should update its display accordingly.
|
||||
///
|
||||
/// The event packet includes a snapshot of the message post-edit.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct EditMessageEvent {
|
||||
/// The id of the edit.
|
||||
pub edit_id: Snowflake,
|
||||
/// The snapshot of the message post-edit.
|
||||
#[serde(flatten)]
|
||||
pub message: Message,
|
||||
}
|
||||
|
||||
/// Indicates a session just disconnected from the room.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct PartEvent(pub SessionView);
|
||||
|
||||
/// Represents a server-to-client ping.
|
||||
///
|
||||
/// The client should send back a ping-reply with the same value for the time
|
||||
/// field as soon as possible (or risk disconnection).
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct PingEvent {
|
||||
/// A unix timestamp according to the server's clock.
|
||||
pub time: Time,
|
||||
/// The expected time of the next ping event, according to the server's
|
||||
/// clock.
|
||||
pub next: Time,
|
||||
}
|
||||
|
||||
/// Informs the client that another user wants to chat with them privately.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct PmInitiateEvent {
|
||||
/// The id of the user inviting the client to chat privately.
|
||||
pub from: UserId,
|
||||
/// The nick of the inviting user.
|
||||
pub from_nick: String,
|
||||
/// The room where the invitation was sent from.
|
||||
pub from_room: String,
|
||||
/// The private chat can be accessed at `/room/pm:<pm_id>`.
|
||||
pub pm_id: Snowflake,
|
||||
}
|
||||
|
||||
/// Indicates a message received by the room from another session.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct SendEvent(pub Message);
|
||||
|
||||
/// Indicates that a session has successfully joined a room.
|
||||
///
|
||||
/// It also offers a snapshot of the room’s state and recent history.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct SnapshotEvent {
|
||||
/// The id of the agent or account logged into this session.
|
||||
pub identity: UserId,
|
||||
/// The globally unique id of this session.
|
||||
pub session_id: String,
|
||||
/// The server’s version identifier.
|
||||
pub version: String,
|
||||
/// The list of all other sessions joined to the room (excluding this
|
||||
/// session).
|
||||
pub listing: Vec<SessionView>,
|
||||
/// The most recent messages posted to the room (currently up to 100).
|
||||
pub log: Vec<Message>,
|
||||
/// The acting nick of the session; if omitted, client set nick before
|
||||
/// speaking.
|
||||
pub nick: Option<String>,
|
||||
/// If given, this room is for private chat with the given nick.
|
||||
pub pm_with_nick: Option<String>,
|
||||
/// If given, this room is for private chat with the given user.
|
||||
pub pm_with_user_id: Option<String>,
|
||||
}
|
||||
116
cove-tui/src/euph/api/room_cmds.rs
Normal file
116
cove-tui/src/euph/api/room_cmds.rs
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
//! Chat room commands.
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::{Message, SessionView, Snowflake, UserId};
|
||||
|
||||
/// Retrieve the full content of a single message in the room.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct GetMessage {
|
||||
/// The id of the message to retrieve.
|
||||
pub id: Snowflake,
|
||||
}
|
||||
|
||||
/// The message retrieved by [`GetMessage`].
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct GetMessageReply(pub Message);
|
||||
|
||||
/// Request messages from the room's message log.
|
||||
///
|
||||
/// This can be used to supplement the log provided by snapshot-event (for
|
||||
/// example, when scrolling back further in history).
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Log {
|
||||
/// Maximum number of messages to return (up to 1000).
|
||||
pub n: usize,
|
||||
/// Return messages prior to this snowflake.
|
||||
pub before: Option<Snowflake>,
|
||||
}
|
||||
|
||||
/// List of messages from the room's message log.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct LogReply {
|
||||
/// List of messages returned.
|
||||
pub log: Vec<Message>,
|
||||
/// Messages prior to this snowflake were returned.
|
||||
pub before: Option<Snowflake>,
|
||||
}
|
||||
|
||||
/// Set the name you present to the room.
|
||||
///
|
||||
/// This name applies to all messages sent during this session, until the nick
|
||||
/// command is called again.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Nick {
|
||||
/// The requested name (maximum length 36 bytes).
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
/// Confirms the [`Nick`] command.
|
||||
///
|
||||
/// Returns the session's former and new names (the server may modify the
|
||||
/// requested nick).
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct NickReply {
|
||||
/// The id of the session this name applies to.
|
||||
pub session_id: String,
|
||||
/// The id of the agent or account logged into the session.
|
||||
pub id: UserId,
|
||||
/// The previous name associated with the session.
|
||||
pub from: String,
|
||||
/// The name associated with the session henceforth.
|
||||
pub to: String,
|
||||
}
|
||||
|
||||
/// Constructs a virtual room for private messaging between the client and the
|
||||
/// given [`UserId`].
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct PmInitiate {
|
||||
/// The id of the user to invite to chat privately.
|
||||
pub user_id: UserId,
|
||||
}
|
||||
|
||||
/// Provides the PMID for the requested private messaging room.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct PmInitiateReply {
|
||||
/// The private chat can be accessed at `/room/pm:<pm_id>`.
|
||||
pub pm_id: Snowflake,
|
||||
/// The nickname of the recipient of the invitation.
|
||||
pub to_nick: String,
|
||||
}
|
||||
|
||||
/// Send a message to a room.
|
||||
///
|
||||
/// The session must be successfully joined with the room. This message will be
|
||||
/// broadcast to all sessions joined with the room.
|
||||
///
|
||||
/// If the room is private, then the message content will be encrypted before it
|
||||
/// is stored and broadcast to the rest of the room.
|
||||
///
|
||||
/// The caller of this command will not receive the corresponding
|
||||
/// [`SendEvent`](super::SendEvent), but will receive the same information in
|
||||
/// the [`SendReply`].
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Send {
|
||||
/// The content of the message (client-defined).
|
||||
pub content: String,
|
||||
/// The id of the parent message, if any.
|
||||
pub parent: Option<Snowflake>,
|
||||
}
|
||||
|
||||
/// The message that was sent.
|
||||
///
|
||||
/// this includes the message id, which was populated by the server.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct SendReply(pub Message);
|
||||
|
||||
/// Request a list of sessions currently joined in the room.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Who;
|
||||
|
||||
/// Lists the sessions currently joined in the room.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct WhoReply {
|
||||
/// A list of session views.
|
||||
listing: Vec<SessionView>,
|
||||
}
|
||||
43
cove-tui/src/euph/api/session_cmds.rs
Normal file
43
cove-tui/src/euph/api/session_cmds.rs
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
//! Session commands.
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::{AuthOption, Time};
|
||||
|
||||
/// Attempt to join a private room.
|
||||
///
|
||||
/// This should be sent in response to a bounce event at the beginning of a
|
||||
/// session.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Auth {
|
||||
/// The method of authentication.
|
||||
pub r#type: AuthOption,
|
||||
/// Use this field for [`AuthOption::Passcode`] authentication.
|
||||
pub passcode: Option<String>,
|
||||
}
|
||||
|
||||
/// Reports whether the [`Auth`] command succeeded.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct AuthReply {
|
||||
/// True if authentication succeeded.
|
||||
pub success: bool,
|
||||
/// If [`Self::success`] was false, the reason for failure.
|
||||
pub reason: Option<String>,
|
||||
}
|
||||
|
||||
/// Initiate a client-to-server ping.
|
||||
///
|
||||
/// The server will send back a [`PingReply`] with the same timestamp as soon as
|
||||
/// possible.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Ping {
|
||||
/// An arbitrary value, intended to be a unix timestamp.
|
||||
pub time: Time,
|
||||
}
|
||||
|
||||
/// Response to a [`Ping`] command or [`PingEvent`](super::PingEvent).
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct PingReply {
|
||||
/// The timestamp of the ping being replied to.
|
||||
pub time: Option<Time>,
|
||||
}
|
||||
330
cove-tui/src/euph/api/types.rs
Normal file
330
cove-tui/src/euph/api/types.rs
Normal file
|
|
@ -0,0 +1,330 @@
|
|||
//! Field types.
|
||||
|
||||
// Serde's derive macros generate this warning and I can't turn it off locally,
|
||||
// so I'm turning it off for the entire module.
|
||||
#![allow(clippy::use_self)]
|
||||
|
||||
use std::fmt;
|
||||
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{de, ser, Deserialize, Serialize};
|
||||
|
||||
/// Describes an account and its preferred name.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct AccountView {
|
||||
/// The id of the account.
|
||||
pub id: Snowflake,
|
||||
/// The name that the holder of the account goes by.
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
/// Mode of authentication.
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub enum AuthOption {
|
||||
/// Authentication with a passcode, where a key is derived from the passcode
|
||||
/// to unlock an access grant.
|
||||
Passcode,
|
||||
}
|
||||
|
||||
/// A node in a room's log.
|
||||
///
|
||||
/// It corresponds to a chat message, or a post, or any broadcasted event in a
|
||||
/// room that should appear in the log.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Message {
|
||||
/// The id of the message (unique within a room).
|
||||
pub id: Snowflake,
|
||||
/// The id of the message's parent, or null if top-level.
|
||||
pub parent: Option<Snowflake>,
|
||||
/// The edit id of the most recent edit of this message, or null if it's
|
||||
/// never been edited.
|
||||
pub previous_edit_id: Option<Snowflake>,
|
||||
/// The unix timestamp of when the message was posted.
|
||||
pub time: Time,
|
||||
/// The view of the sender's session.
|
||||
pub sender: SessionView,
|
||||
/// The content of the message (client-defined).
|
||||
pub content: String,
|
||||
/// The id of the key that encrypts the message in storage.
|
||||
pub encryption_key_id: Option<String>,
|
||||
/// The unix timestamp of when the message was last edited.
|
||||
pub edited: Option<Time>,
|
||||
/// The unix timestamp of when the message was deleted.
|
||||
pub deleted: Option<Time>,
|
||||
/// If true, then the full content of this message is not included (see
|
||||
/// [`GetMessage`](super::GetMessage) to obtain the message with full
|
||||
/// content).
|
||||
pub truncated: Option<bool>,
|
||||
}
|
||||
|
||||
/// The type of a packet.
|
||||
///
|
||||
/// Not all of these types have their corresponding data modeled as a struct.
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub enum PacketType {
|
||||
// Asynchronous events
|
||||
/// See [`BounceEvent`](super::BounceEvent).
|
||||
BounceEvent,
|
||||
/// See [`DisconnectEvent`](super::DisconnectEvent).
|
||||
DisconnectEvent,
|
||||
/// See [`HelloEvent`](super::HelloEvent).
|
||||
HelloEvent,
|
||||
/// See [`JoinEvent`](super::JoinEvent).
|
||||
JoinEvent,
|
||||
/// See [`LoginEvent`](super::LoginEvent).
|
||||
LoginEvent,
|
||||
/// See [`LogoutEvent`](super::LogoutEvent).
|
||||
LogoutEvent,
|
||||
/// See [`NetworkEvent`](super::NetworkEvent).
|
||||
NetworkEvent,
|
||||
/// See [`NickEvent`](super::NickEvent).
|
||||
NickEvent,
|
||||
/// See [`EditMessageEvent`](super::EditMessageEvent).
|
||||
EditMessageEvent,
|
||||
/// See [`PartEvent`](super::PartEvent).
|
||||
PartEvent,
|
||||
/// See [`PingEvent`](super::PingEvent).
|
||||
PingEvent,
|
||||
/// See [`PmInitiateEvent`](super::PmInitiateEvent).
|
||||
PmInitiateEvent,
|
||||
/// See [`SendEvent`](super::SendEvent).
|
||||
SendEvent,
|
||||
/// See [`SnapshotEvent`](super::SnapshotEvent).
|
||||
SnapshotEvent,
|
||||
|
||||
// Session commands
|
||||
/// See [`Auth`](super::Auth).
|
||||
Auth,
|
||||
/// See [`AuthReply`](super::AuthReply).
|
||||
AuthReply,
|
||||
/// See [`Ping`](super::Ping).
|
||||
Ping,
|
||||
/// See [`PingReply`](super::PingReply).
|
||||
PingReply,
|
||||
|
||||
// Chat room commands
|
||||
/// See [`GetMessage`](super::GetMessage).
|
||||
GetMessage,
|
||||
/// See [`GetMessageReply`](super::GetMessageReply).
|
||||
GetMessageReply,
|
||||
/// See [`Log`](super::Log).
|
||||
Log,
|
||||
/// See [`LogReply`](super::LogReply).
|
||||
LogReply,
|
||||
/// See [`Nick`](super::Nick).
|
||||
Nick,
|
||||
/// See [`NickReply`](super::NickReply).
|
||||
NickReply,
|
||||
/// See [`PmInitiate`](super::PmInitiate).
|
||||
PmInitiate,
|
||||
/// See [`PmInitiateReply`](super::PmInitiateReply).
|
||||
PmInitiateReply,
|
||||
/// See [`Send`](super::Send).
|
||||
Send,
|
||||
/// See [`SendReply`](super::SendReply).
|
||||
SendReply,
|
||||
/// See [`Who`](super::Who).
|
||||
Who,
|
||||
/// See [`WhoReply`](super::WhoReply).
|
||||
WhoReply,
|
||||
|
||||
// Account commands
|
||||
/// Not implemented.
|
||||
ChangeEmail,
|
||||
/// Not implemented.
|
||||
ChangeEmailReply,
|
||||
/// Not implemented.
|
||||
ChangeName,
|
||||
/// Not implemented.
|
||||
ChangeNameReply,
|
||||
/// Not implemented.
|
||||
ChangePassword,
|
||||
/// Not implemented.
|
||||
ChangePasswordReply,
|
||||
/// Not implemented.
|
||||
Login,
|
||||
/// Not implemented.
|
||||
LoginReply,
|
||||
/// Not implemented.
|
||||
Logout,
|
||||
/// Not implemented.
|
||||
LogoutReply,
|
||||
/// Not implemented.
|
||||
RegisterAccount,
|
||||
/// Not implemented.
|
||||
RegisterAccountReply,
|
||||
/// Not implemented.
|
||||
ResendVerificationEmail,
|
||||
/// Not implemented.
|
||||
ResendVerificationEmailReply,
|
||||
/// Not implemented.
|
||||
ResetPassword,
|
||||
/// Not implemented.
|
||||
ResetPasswordReply,
|
||||
|
||||
// Room host commands
|
||||
/// Not implemented.
|
||||
Ban,
|
||||
/// Not implemented.
|
||||
BanReply,
|
||||
/// Not implemented.
|
||||
EditMessage,
|
||||
/// Not implemented.
|
||||
EditMessageReply,
|
||||
/// Not implemented.
|
||||
GrantAccess,
|
||||
/// Not implemented.
|
||||
GrantAccessReply,
|
||||
/// Not implemented.
|
||||
GrantManager,
|
||||
/// Not implemented.
|
||||
GrantManagerReply,
|
||||
/// Not implemented.
|
||||
RevokeAccess,
|
||||
/// Not implemented.
|
||||
RevokeAccessReply,
|
||||
/// Not implemented.
|
||||
RevokeManager,
|
||||
/// Not implemented.
|
||||
RevokeManagerReply,
|
||||
/// Not implemented.
|
||||
Unban,
|
||||
/// Not implemented.
|
||||
UnbanReply,
|
||||
|
||||
// Staff commands
|
||||
/// Not implemented.
|
||||
StaffCreateRoom,
|
||||
/// Not implemented.
|
||||
StaffCreateRoomReply,
|
||||
/// Not implemented.
|
||||
StaffEnrollOtp,
|
||||
/// Not implemented.
|
||||
StaffEnrollOtpReply,
|
||||
/// Not implemented.
|
||||
StaffGrantManager,
|
||||
/// Not implemented.
|
||||
StaffGrantManagerReply,
|
||||
/// Not implemented.
|
||||
StaffInvade,
|
||||
/// Not implemented.
|
||||
StaffInvadeReply,
|
||||
/// Not implemented.
|
||||
StaffLockRoom,
|
||||
/// Not implemented.
|
||||
StaffLockRoomReply,
|
||||
/// Not implemented.
|
||||
StaffRevokeAccess,
|
||||
/// Not implemented.
|
||||
StaffRevokeAccessReply,
|
||||
/// Not implemented.
|
||||
StaffValidateOtp,
|
||||
/// Not implemented.
|
||||
StaffValidateOtpReply,
|
||||
/// Not implemented.
|
||||
UnlockStaffCapability,
|
||||
/// Not implemented.
|
||||
UnlockStaffCapabilityReply,
|
||||
}
|
||||
|
||||
/// Describes an account to its owner.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct PersonalAccountView {
|
||||
/// The id of the account.
|
||||
pub id: Snowflake,
|
||||
/// The name that the holder of the account goes by.
|
||||
pub name: String,
|
||||
/// The account's email address.
|
||||
pub email: String,
|
||||
}
|
||||
|
||||
/// Describes a session and its identity.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct SessionView {
|
||||
/// The id of an agent or account (or bot).
|
||||
pub id: UserId,
|
||||
/// The name-in-use at the time this view was captured.
|
||||
pub name: String,
|
||||
/// The id of the server that captured this view.
|
||||
pub server_id: String,
|
||||
/// The era of the server that captured this view.
|
||||
pub server_era: String,
|
||||
/// Id of the session, unique across all sessions globally.
|
||||
pub session_id: String,
|
||||
/// If true, this session belongs to a member of staff.
|
||||
pub is_staff: Option<bool>,
|
||||
/// If true, this session belongs to a manager of the room.
|
||||
pub is_manager: Option<bool>,
|
||||
/// For hosts and staff, the virtual address of the client.
|
||||
pub client_address: Option<String>,
|
||||
/// For staff, the real address of the client.
|
||||
pub real_client_address: Option<String>,
|
||||
}
|
||||
|
||||
/// A 13-character string, usually used as aunique identifier for some type of object.
|
||||
///
|
||||
/// It is the base-36 encoding of an unsigned, 64-bit integer.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Snowflake(pub u64);
|
||||
|
||||
impl Serialize for Snowflake {
|
||||
fn serialize<S: ser::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
// Convert u64 to base36 string
|
||||
let mut n = self.0;
|
||||
let mut result = String::with_capacity(13);
|
||||
for _ in 0..13 {
|
||||
let c = char::from_digit((n % 36) as u32, 36).unwrap();
|
||||
result.insert(0, c);
|
||||
n /= 36;
|
||||
}
|
||||
result.serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
struct SnowflakeVisitor;
|
||||
|
||||
impl<'de> de::Visitor<'de> for SnowflakeVisitor {
|
||||
type Value = Snowflake;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(formatter, "a base36 string of length 13")
|
||||
}
|
||||
|
||||
fn visit_str<E: de::Error>(self, v: &str) -> Result<Self::Value, E> {
|
||||
// Convert base36 string to u64
|
||||
if v.len() != 13 {
|
||||
return Err(E::invalid_length(v.len(), &self));
|
||||
}
|
||||
let mut n = 0;
|
||||
for c in v.chars() {
|
||||
let digit = c
|
||||
.to_digit(36)
|
||||
.ok_or_else(|| E::invalid_value(de::Unexpected::Str(v), &self))?;
|
||||
n = n * 36 + digit as u64;
|
||||
}
|
||||
Ok(Snowflake(n))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Snowflake {
|
||||
fn deserialize<D: de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||
deserializer.deserialize_str(SnowflakeVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
/// Time is specified as a signed 64-bit integer, giving the number of seconds
|
||||
/// since the Unix Epoch.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Time(#[serde(with = "chrono::serde::ts_seconds")] pub DateTime<Utc>);
|
||||
|
||||
/// Identifies a user.
|
||||
///
|
||||
/// The prefix of this value (up to the colon) indicates a type of session,
|
||||
/// while the suffix is a unique value for that type of session.
|
||||
///
|
||||
/// It is possible for this value to have no prefix and colon, and there is no
|
||||
/// fixed format for the unique value.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct UserId(pub String);
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
#![warn(clippy::use_self)]
|
||||
|
||||
mod chat;
|
||||
mod euph;
|
||||
mod log;
|
||||
mod store;
|
||||
mod ui;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue