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,
}
}
}