use std::fmt::{Display, Formatter, Result as FmtResult};
use serde_json::{
Error as JsonError,
value::RawValue,
};
use serde_repr::{Deserialize_repr, Serialize_repr};
use crate::{
guild::UnavailableGuild,
presence::{ClientActivity, ClientPresence},
Snowflake,
User
};
use crate::presence::Status;
pub trait SendablePacket {
fn to_json(self) -> Result<String, JsonError>;
fn bytes(self) -> Result<Vec<u8>, JsonError>;
}
#[derive(Serialize, Deserialize, Debug)]
pub struct GatewayBot {
pub url: String,
pub shards: usize,
pub session_start_limit: SessionStartLimit
}
#[derive(Serialize, Deserialize, Debug)]
pub struct SessionStartLimit {
pub total: i32,
pub remaining: i32,
pub reset_after: i32,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct ReceivePacket {
pub op: Opcodes,
pub d: Box<RawValue>,
pub s: Option<u64>,
pub t: Option<GatewayEvent>
}
#[derive(Serialize, Deserialize, Debug)]
pub struct SendPacket<T: SendablePacket> {
pub op: Opcodes,
pub d: T
}
#[derive(Serialize, Deserialize, Debug)]
pub struct GatewayBrokerMessage {
pub guild_id: Snowflake,
pub packet: Box<RawValue>,
}
impl GatewayBrokerMessage {
pub fn new<T: SendablePacket>(guild_id: Snowflake, packet: T) -> Result<Self, JsonError> {
let raw = RawValue::from_string(packet.to_json()?)?;
Ok(Self {
guild_id,
packet: raw,
})
}
pub fn as_bytes(&self) -> Result<Vec<u8>, JsonError> {
let json = serde_json::to_string(self)?;
Ok(json.as_bytes().to_vec())
}
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct IdentifyPacket {
pub token: String,
pub properties: IdentifyProperties,
#[serde(rename = "v")]
pub version: u8,
pub compress: bool,
pub large_threshold: i32,
pub shard: [usize; 2],
pub presence: Option<ClientPresence>
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct IdentifyProperties {
#[serde(rename = "$os")]
pub os: String,
#[serde(rename = "$browser")]
pub browser: String,
#[serde(rename = "$device")]
pub device: String
}
#[derive(Serialize, Deserialize, Debug)]
pub struct HelloPacket {
pub heartbeat_interval: u64,
pub _trace: Vec<String>
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct ResumeSessionPacket {
pub session_id: String,
pub seq: u64,
pub token: String
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct HeartbeatPacket {
pub seq: u64
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct RequestGuildMembers {
pub guild_id: Snowflake,
pub query: String,
pub limit: i32
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct UpdateVoiceState {
pub guild_id: Snowflake,
pub channel_id: Snowflake,
pub self_mute: bool,
pub self_deaf: bool
}
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
pub struct UpdateStatus {
pub since: Option<i32>,
pub game: Option<ClientActivity>,
pub status: Status,
pub afk: bool
}
impl UpdateStatus {
pub fn game(mut self, activity: ClientActivity) -> Self {
self.game = Some(activity);
self
}
pub fn status(mut self, status: Status) -> Self {
self.status = status;
self
}
pub fn afk(mut self, afk: bool) -> Self {
self.afk = afk;
self
}
}
impl SendablePacket for UpdateStatus {
fn to_json(self) -> Result<String, JsonError> {
serde_json::to_string(&SendPacket {
op: Opcodes::StatusUpdate,
d: self
})
}
fn bytes(self) -> Result<Vec<u8>, JsonError> {
let json = self.to_json()?;
Ok(json.as_bytes().to_vec())
}
}
impl SendablePacket for IdentifyPacket {
fn to_json(self) -> Result<String, JsonError> {
serde_json::to_string(&SendPacket {
op: Opcodes::Identify,
d: self
})
}
fn bytes(self) -> Result<Vec<u8>, JsonError> {
let json = self.to_json()?;
Ok(json.as_bytes().to_vec())
}
}
impl SendablePacket for UpdateVoiceState {
fn to_json(self) -> Result<String, JsonError> {
serde_json::to_string(&SendPacket {
op: Opcodes::VoiceStatusUpdate,
d: self,
})
}
fn bytes(self) -> Result<Vec<u8>, JsonError> {
let json = self.to_json()?;
Ok(json.as_bytes().to_vec())
}
}
impl SendablePacket for RequestGuildMembers {
fn to_json(self) -> Result<String, JsonError> {
serde_json::to_string(&SendPacket {
op: Opcodes::RequestGuildMembers,
d: self
})
}
fn bytes(self) -> Result<Vec<u8>, JsonError> {
let json = self.to_json()?;
Ok(json.as_bytes().to_vec())
}
}
impl SendablePacket for HeartbeatPacket {
fn to_json(self) -> Result<String, JsonError> {
serde_json::to_string(&SendPacket {
op: Opcodes::Heartbeat,
d: self
})
}
fn bytes(self) -> Result<Vec<u8>, JsonError> {
let json = self.to_json()?;
Ok(json.as_bytes().to_vec())
}
}
impl SendablePacket for ResumeSessionPacket {
fn to_json(self) -> Result<String, JsonError> {
serde_json::to_string(&SendPacket {
op: Opcodes::Resume,
d: self
})
}
fn bytes(self) -> Result<Vec<u8>, JsonError> {
let json = self.to_json()?;
Ok(json.as_bytes().to_vec())
}
}
#[derive(Deserialize, Serialize, Debug, Clone)]
pub struct ReadyPacket {
pub v: i32,
pub user: User,
pub private_channels: [String; 0],
pub guilds: Vec<UnavailableGuild>,
pub session_id: String,
pub _trace: Vec<String>,
#[serde(default)]
pub shard: [u64; 2]
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct ResumedPacket {
pub _trace: Vec<String>
}
#[derive(Debug, Deserialize, Serialize, Clone)]
#[allow(non_camel_case_types)]
pub enum GatewayEvent {
HELLO,
READY,
RESUMED,
INVALID_SESSION,
CHANNEL_CREATE,
CHANNEL_UPDATE,
CHANNEL_DELETE,
CHANNEL_PINS_UPDATE,
GUILD_CREATE,
GUILD_UPDATE,
GUILD_DELETE,
GUILD_BAN_ADD,
GUILD_BAN_REMOVE,
GUILD_EMOJIS_UPDATE,
GUILD_INTEGRATIONS_UPDATE,
GUILD_MEMBER_ADD,
GUILD_MEMBER_REMOVE,
GUILD_MEMBER_UPDATE,
GUILD_MEMBERS_CHUNK,
GUILD_ROLE_CREATE,
GUILD_ROLE_UPDATE,
GUILD_ROLE_DELETE,
MESSAGE_CREATE,
MESSAGE_UPDATE,
MESSAGE_DELETE,
MESSAGE_DELETE_BULK,
MESSAGE_REACTION_ADD,
MESSAGE_REACTION_REMOVE,
MESSAGE_REACTION_REMOVE_ALL,
PRESENCE_UPDATE,
PRESENCES_REPLACE,
TYPING_START,
USER_UPDATE,
VOICE_STATE_UPDATE,
VOICE_SERVER_UPDATE,
WEBHOOKS_UPDATE
}
impl Display for GatewayEvent {
fn fmt(&self, f: &mut Formatter) -> FmtResult {
write!(f, "{:?}", self)
}
}
#[derive(Serialize_repr, Deserialize_repr, Debug, Clone)]
#[repr(u8)]
pub enum Opcodes {
Dispatch,
Heartbeat,
Identify,
StatusUpdate,
VoiceStatusUpdate,
Resume = 6,
Reconnect,
RequestGuildMembers,
InvalidSession,
Hello,
HeartbeatAck
}
#[derive(Debug, Copy, Deserialize_repr, Clone)]
#[repr(u16)]
pub enum CloseCodes {
UnknownError = 4000,
UnknownOpcode,
DecodeError,
NotAuthenticated,
AuthenticationFailed,
AlreadyAuthenticated,
InvalidSeq,
Ratelimited,
SessionTimeout,
InvalidShard,
ShardingRequired,
}