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

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())
}
}