use crate::capability::Protocol;
use crate::entity::{FileMeta, FriendInfo, GroupInfo, ImplStatus, MemberInfo};
use crate::id::{MessageId, Peer, Scene, Uin};
use crate::message::Message;
use serde_json::Value;
#[derive(Clone, Debug)]
#[non_exhaustive]
pub enum Event {
Message(Box<MessageEvent>),
Notice(Notice),
Request(Request),
Meta(Meta),
Raw(RawEvent),
}
#[derive(Clone, Debug)]
pub struct Anonymous {
pub id: i64,
pub name: String,
pub flag: String,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct MessageStyle {
pub bubble_id: Option<i64>,
pub pendant_id: Option<i64>,
pub pal_type: Option<i64>,
pub raw: Value,
}
#[derive(Clone, Debug)]
pub struct MessageEvent {
pub id: MessageId,
pub peer: Peer,
pub sender: Uin,
pub self_id: Uin,
pub time: i64,
pub content: Message,
pub is_self: bool,
pub group: Option<GroupInfo>,
pub member: Option<MemberInfo>,
pub friend: Option<FriendInfo>,
pub anonymous: Option<Anonymous>,
pub font: Option<i32>,
pub target_id: Option<Uin>,
pub message_style: Option<MessageStyle>,
pub raw: Value,
}
#[derive(Clone, Debug)]
pub struct NudgeDisplay {
pub action: String,
pub suffix: String,
pub action_img_url: Option<String>,
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum ReactionKind {
Face,
Emoji,
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum HonorKind {
Talkative,
Performer,
Emotion,
Unknown,
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum MemberDecreaseReason {
Leave,
Kick,
KickMe,
Disband,
Unknown,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct EmojiLike {
pub face_id: String,
pub count: Option<i64>,
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum OnlineFileDirection {
Send,
Receive,
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum FlashFilePhase {
Downloading,
Downloaded,
Uploading,
Uploaded,
Unknown,
}
#[derive(Clone, Debug)]
#[non_exhaustive]
pub enum Notice {
Recall { peer: Peer, id: MessageId, sender: Uin, operator: Uin, suffix: Option<String> },
MemberIncrease { group: Uin, user: Uin, operator: Option<Uin>, invitor: Option<Uin> },
MemberDecrease { group: Uin, user: Uin, operator: Option<Uin>, reason: MemberDecreaseReason },
AdminChange { group: Uin, user: Uin, operator: Option<Uin>, is_set: bool },
Mute { group: Uin, user: Uin, operator: Uin, duration: i32 },
WholeMute { group: Uin, operator: Uin, is_mute: bool },
GroupNameChange { group: Uin, new_name: String, operator: Uin },
LuckyKing { group: Uin, user: Uin, target: Uin },
Honor { group: Uin, user: Uin, honor: HonorKind },
GroupCardChange { group: Uin, user: Uin, old_card: String, new_card: String },
FriendNudge { user: Uin, is_self_send: bool, is_self_receive: bool, display: NudgeDisplay },
GroupNudge { group: Uin, sender: Uin, receiver: Uin, display: NudgeDisplay },
Reaction { group: Uin, user: Uin, seq: i64, face_id: String, kind: ReactionKind, is_add: bool, sub_type: Option<String>, count: Option<i64>, likes: Vec<EmojiLike> },
EssenceChange { group: Uin, seq: i64, sender: Option<Uin>, operator: Option<Uin>, is_set: bool },
GroupFileUpload { group: Uin, user: Uin, file: FileMeta },
FriendFileUpload { user: Uin, file: FileMeta, is_self: bool },
FriendAdd { user: Uin },
PeerPinChange { peer: Peer, is_pinned: bool },
BotOffline { reason: String, tag: Option<String> },
GroupDismiss { group: Uin, operator: Uin },
GroupTitleChange { group: Uin, user: Uin, title: String },
InputStatus { user: Uin, group: Option<Uin>, status_text: String, event_type: i64 },
ProfileLike { operator: Uin, operator_nick: String, times: i64 },
GrayTip { group: Option<Uin>, user: Option<Uin>, content: String },
PokeRecall { group: Option<Uin>, user: Uin },
OnlineFile { direction: OnlineFileDirection, user: Uin, group: Option<Uin> },
FlashFile { phase: FlashFilePhase, user: Uin, group: Option<Uin> },
Other { protocol: Protocol, kind: String, raw: Value },
}
#[derive(Clone, Debug)]
pub struct RequestToken(#[doc(hidden)] pub RequestTokenInner);
#[doc(hidden)]
#[derive(Clone, Debug)]
pub enum RequestTokenInner {
OneBotFlag(String),
MilkyFriend { initiator_uid: String, is_filtered: bool },
MilkyGroupNotification { notification_seq: i64, notification_type: String, group_id: Uin, is_filtered: bool },
MilkyInvitation { group_id: Uin, invitation_seq: i64 },
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum RequestState {
Pending,
Accepted,
Rejected,
Ignored,
Unknown,
}
#[derive(Clone, Debug)]
#[non_exhaustive]
pub enum Request {
Friend { initiator: Uin, initiator_uid: Option<String>, comment: String, via: String, source_group: Option<Uin>, target_user_id: Option<Uin>, state: RequestState, time: Option<i64>, is_filtered: bool, token: RequestToken },
GroupJoin { group: Uin, initiator: Uin, comment: String, invitor: Option<Uin>, is_filtered: bool, token: RequestToken },
GroupInvitedJoin { group: Uin, initiator: Uin, target: Uin, token: RequestToken },
GroupInvite { group: Uin, initiator: Uin, comment: String, source_group: Option<Uin>, token: RequestToken },
}
#[derive(Clone, Debug)]
#[non_exhaustive]
pub enum Meta {
Connect,
Disconnect { reason: Option<String> },
Ready { self_id: Uin, nickname: String },
Heartbeat { interval: i64, status: ImplStatus },
BotOnline { reason: Option<String> },
BotOffline,
}
#[derive(Clone, Debug)]
pub struct RawEvent {
pub protocol: Protocol,
pub kind: String,
pub raw: Value,
}
impl RequestToken {
pub fn onebot_flag(flag: impl Into<String>) -> Self {
RequestToken(RequestTokenInner::OneBotFlag(flag.into()))
}
}
impl Event {
pub fn peer(&self) -> Option<Peer> {
use Notice as N;
use Request as R;
match self {
Event::Message(m) => Some(m.peer),
Event::Notice(n) => match n {
N::Recall { peer, .. } => Some(*peer),
N::PeerPinChange { peer, .. } => Some(*peer),
N::MemberIncrease { group, .. }
| N::MemberDecrease { group, .. }
| N::AdminChange { group, .. }
| N::Mute { group, .. }
| N::WholeMute { group, .. }
| N::GroupNameChange { group, .. }
| N::Honor { group, .. }
| N::GroupCardChange { group, .. }
| N::GroupNudge { group, .. }
| N::Reaction { group, .. }
| N::EssenceChange { group, .. }
| N::GroupFileUpload { group, .. }
| N::GroupDismiss { group, .. }
| N::GroupTitleChange { group, .. }
| N::LuckyKing { group, .. } => Some(Peer::group(*group)),
N::FriendNudge { user, .. }
| N::FriendFileUpload { user, .. }
| N::FriendAdd { user } => Some(Peer::friend(*user)),
N::InputStatus { user, group, .. }
| N::PokeRecall { user, group, .. }
| N::OnlineFile { user, group, .. }
| N::FlashFile { user, group, .. }
| N::GrayTip { user: Some(user), group, .. } => Some(match group {
Some(g) => Peer::group(*g),
None => Peer::friend(*user),
}),
N::GrayTip { user: None, group: Some(g), .. } => Some(Peer::group(*g)),
N::GrayTip { user: None, group: None, .. }
| N::ProfileLike { .. }
| N::BotOffline { .. }
| N::Other { .. } => None,
},
Event::Request(r) => match r {
R::Friend { initiator, .. } => Some(Peer::friend(*initiator)),
R::GroupJoin { group, .. }
| R::GroupInvitedJoin { group, .. }
| R::GroupInvite { group, .. } => Some(Peer::group(*group)),
},
Event::Meta(_) | Event::Raw(_) => None,
}
}
pub fn group(&self) -> Option<Uin> {
self.peer().and_then(|p| match p.scene {
Scene::Group => Some(p.id),
_ => None,
})
}
pub fn sender(&self) -> Option<Uin> {
use Notice as N;
use Request as R;
match self {
Event::Message(m) => Some(m.sender),
Event::Notice(n) => match n {
N::Recall { sender, .. } => Some(*sender),
N::MemberIncrease { user, .. }
| N::MemberDecrease { user, .. }
| N::AdminChange { user, .. }
| N::Honor { user, .. }
| N::GroupCardChange { user, .. }
| N::Reaction { user, .. }
| N::GroupFileUpload { user, .. }
| N::GroupTitleChange { user, .. }
| N::InputStatus { user, .. }
| N::PokeRecall { user, .. }
| N::OnlineFile { user, .. }
| N::FlashFile { user, .. }
| N::LuckyKing { user, .. } => Some(*user),
N::Mute { operator, .. } | N::WholeMute { operator, .. }
| N::GroupNameChange { operator, .. }
| N::GroupDismiss { operator, .. }
| N::ProfileLike { operator, .. } => Some(*operator),
N::GroupNudge { sender, .. } => Some(*sender),
N::FriendNudge { user, .. } | N::FriendFileUpload { user, .. }
| N::FriendAdd { user } => Some(*user),
N::GrayTip { user, .. } => *user,
N::EssenceChange { .. } | N::PeerPinChange { .. }
| N::BotOffline { .. } | N::Other { .. } => None,
},
Event::Request(r) => match r {
R::Friend { initiator, .. } | R::GroupJoin { initiator, .. }
| R::GroupInvitedJoin { initiator, .. } | R::GroupInvite { initiator, .. } => Some(*initiator),
},
Event::Meta(_) | Event::Raw(_) => None,
}
}
}