You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
159 lines
3.5 KiB
Rust
159 lines
3.5 KiB
Rust
use serde::{Deserialize, Serialize};
|
|
use serde_json::Value;
|
|
use serde_repr::*;
|
|
use std::convert::TryFrom;
|
|
use std::num::ParseIntError;
|
|
use std::str::FromStr;
|
|
|
|
#[repr(u16)]
|
|
#[derive(Serialize_repr, Deserialize_repr, Copy, Ord, PartialOrd, Eq, PartialEq, Debug, Clone)]
|
|
pub enum GatewayOpcode {
|
|
Dispatch = 0,
|
|
Heartbeat = 1,
|
|
Identify = 2,
|
|
StatusUpdate = 3,
|
|
VoiceStateUpdate = 4,
|
|
Resume = 6,
|
|
Reconnect = 7,
|
|
RequestGuildMembers = 8,
|
|
InvalidSession = 9,
|
|
Hello = 10,
|
|
HeartbeatAck = 11,
|
|
|
|
UnknownError = 4000,
|
|
UnknownOpcode = 4001,
|
|
DecodeError = 4002,
|
|
NotAuthenticated = 4003,
|
|
AuthenticationFailed = 4004,
|
|
InvalidSeq = 4007,
|
|
RateLimited = 4008,
|
|
SessionTimeout = 4009,
|
|
InvalidShard = 4010,
|
|
ShardingRequired = 4011,
|
|
}
|
|
|
|
impl GatewayOpcode {
|
|
#[inline]
|
|
fn is_err(&self) -> bool {
|
|
return (*self as u16) >= 4000;
|
|
}
|
|
|
|
#[inline]
|
|
fn is_ok(&self) -> bool {
|
|
return (*self as u16) < 4000;
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Deserialize, Serialize)]
|
|
pub struct GatewayEvent {
|
|
#[serde(rename = "op")]
|
|
pub opcode: GatewayOpcode,
|
|
#[serde(rename = "d")]
|
|
pub data: Value,
|
|
#[serde(rename = "s")]
|
|
pub sequence_num: Option<u64>,
|
|
#[serde(rename = "t")]
|
|
pub event_name: Option<String>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Deserialize, Serialize)]
|
|
pub struct Identify {
|
|
pub token: String,
|
|
pub properties: IdentifyProperties,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Deserialize, Serialize)]
|
|
pub struct IdentifyProperties {
|
|
#[serde(rename = "$os")]
|
|
pub os: String,
|
|
#[serde(rename = "$browser")]
|
|
pub browser: String,
|
|
#[serde(rename = "$device")]
|
|
pub device: String,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Deserialize, Serialize)]
|
|
pub struct Ready {
|
|
#[serde(rename = "v")]
|
|
protocol_version: u32,
|
|
user: (),
|
|
private_channels: Vec<()>,
|
|
guilds: Vec<UnavailableGuild>,
|
|
session_id: String,
|
|
shared: Option<(u32, u32)>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, Deserialize, Serialize)]
|
|
pub struct UnavailableGuild {
|
|
id: Snowflake,
|
|
available: bool,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Deserialize, Serialize)]
|
|
pub struct Resume {
|
|
token: String,
|
|
session_id: String,
|
|
seq: u64,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Deserialize, Serialize)]
|
|
pub struct GatewayBot {
|
|
pub url: String,
|
|
shards: u32,
|
|
session_start_limit: SessionStartLimit,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, Deserialize, Serialize)]
|
|
pub struct SessionStartLimit {
|
|
total: u64,
|
|
remaining: u64,
|
|
reset_after: u64,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Deserialize, Serialize)]
|
|
pub struct RateLimitNotice {
|
|
pub global: bool,
|
|
message: String,
|
|
pub retry_after: u64,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Serialize, Deserialize)]
|
|
#[serde(try_from = "String", into = "String")]
|
|
pub struct Snowflake(u64);
|
|
|
|
impl Into<String> for Snowflake {
|
|
fn into(self) -> String {
|
|
self.0.to_string()
|
|
}
|
|
}
|
|
|
|
impl TryFrom<String> for Snowflake {
|
|
type Error = ParseIntError;
|
|
|
|
fn try_from(from: String) -> Result<Snowflake, ParseIntError> {
|
|
Ok(Snowflake(u64::from_str(&from)?))
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test {
|
|
use crate::discord::dto::{GatewayOpcode, Snowflake};
|
|
|
|
#[test]
|
|
fn snowflake() {
|
|
assert_eq!(
|
|
Ok(Snowflake(4)),
|
|
serde_json::from_str("\"4\"").map_err(|_| ())
|
|
);
|
|
assert_eq!(
|
|
Ok("\"4\"".to_string()),
|
|
serde_json::to_string(&Snowflake(4)).map_err(|_| ())
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn opcode() {
|
|
assert!(GatewayOpcode::SessionTimeout.is_err())
|
|
}
|
|
}
|