Skip to content
This repository has been archived by the owner on Oct 21, 2023. It is now read-only.

Commit

Permalink
feat: group mute
Browse files Browse the repository at this point in the history
See #17
  • Loading branch information
BlueGlassBlock committed Mar 19, 2023
1 parent ab8f357 commit 2dcd9ad
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 8 deletions.
1 change: 1 addition & 0 deletions news/+group-mute.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
支持处理全体禁言和群员禁言事件。
23 changes: 22 additions & 1 deletion python/ichika/core/events/__init__.pyi
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
from dataclasses import dataclass
from datetime import datetime
from datetime import datetime, timedelta
from typing import Literal

from graia.amnesia.message import MessageChain

from ichika.core import Group

from . import structs as structs
from .structs import FriendInfo, MemberInfo, MessageSource

Expand Down Expand Up @@ -77,5 +80,23 @@ class GroupDisband:
class FriendDeleted:
friend_uin: int

@internal_repr
class GroupMute:
group: Group
operator: MemberInfo
status: bool

@internal_repr
class MemberMute:
operator: MemberInfo
target: MemberInfo
duration: timedelta | Literal[False]

@internal_repr
class BotMute:
group: Group
operator: MemberInfo
duration: timedelta | Literal[False]

@internal_repr
class UnknownEvent: ...
66 changes: 62 additions & 4 deletions src/events/converter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,19 @@ use ricq::handler::QEvent;
use super::structs::{FriendInfo, MemberInfo, MessageSource};
use super::{
BotLeaveGroup,
BotMute,
FriendDeleted,
FriendMessage,
FriendNudge,
FriendRecallMessage,
GroupDisband,
GroupMessage,
GroupMute,
GroupNudge,
GroupRecallMessage,
LoginEvent,
MemberLeaveGroup,
MemberMute,
NewFriend,
NewMember,
TempMessage,
Expand All @@ -24,8 +27,8 @@ use super::{
use crate::client::cache;
use crate::exc::MapPyErr;
use crate::message::convert::{serialize_as_py_chain, serialize_audio};
use crate::utils::{datetime_from_ts, py_none, py_try, AsPython};
use crate::{call_static_py, PyRet};
use crate::utils::{datetime_from_ts, py_none, py_try, timedelta_from_secs, AsPython};
use crate::PyRet;

pub async fn convert(event: QEvent) -> PyRet {
match event {
Expand All @@ -44,6 +47,7 @@ pub async fn convert(event: QEvent) -> PyRet {
QEvent::GroupLeave(event) => Ok(handle_group_leave(event).await),
QEvent::GroupDisband(event) => Ok(handle_group_disband(event)),
QEvent::DeleteFriend(event) => Ok(handle_friend_delete(event)),
QEvent::GroupMute(event) => handle_mute(event).await,
unknown => Ok(UnknownEvent { inner: unknown }.obj()),
}
}
Expand Down Expand Up @@ -91,7 +95,7 @@ async fn handle_group_recall(event: rce::GroupMessageRecallEvent) -> PyRet {
.fetch_member(event.group_code, event.operator_uin)
.await
.py_res()?;
let time = py_try(|py| Ok(call_static_py!(datetime_from_ts, py, (event.time))?.into_py(py)))?;
let time = py_try(|py| Ok(datetime_from_ts(py, event.time)?.into_py(py)))?;
Ok(GroupRecallMessage {
time,
author: MemberInfo::new(&author, (*group_info).clone()),
Expand Down Expand Up @@ -149,7 +153,7 @@ async fn handle_friend_recall(event: rce::FriendMessageRecallEvent) -> PyRet {
.ok_or_else(|| {
PyValueError::new_err(format!("Unable to find friend {}", event.friend_uin))
})?;
let time = py_try(|py| Ok(call_static_py!(datetime_from_ts, py, (event.time))?.into_py(py)))?;
let time = py_try(|py| Ok(datetime_from_ts(py, event.time)?.into_py(py)))?;
Ok(FriendRecallMessage {
time,
author: FriendInfo {
Expand Down Expand Up @@ -296,3 +300,57 @@ fn handle_friend_delete(event: rce::DeleteFriendEvent) -> PyObject {
}
.obj()
}

async fn handle_mute(event: rce::GroupMuteEvent) -> PyRet {
let uin = event.client.uin().await;
let mut cache = cache(event.client).await;
let event = event.inner;
let group = cache
.fetch_group(event.group_code)
.await
.py_res()?
.as_ref()
.clone();
let operator = cache
.fetch_member(event.group_code, event.operator_uin)
.await
.py_res()?;
let operator = MemberInfo::new(&operator, group.clone());

if event.target_uin == 0 {
return Ok(GroupMute {
group,
operator,
status: event.duration.as_secs() == 0,
}
.obj());
}
let duration = event.duration.as_secs();
let duration = py_try(|py| {
Ok(if duration != 0 {
timedelta_from_secs(py, duration)?.into_py(py)
} else {
false.into_py(py)
})
})?;
if event.target_uin == uin {
Ok(BotMute {
group,
operator,
duration,
}
.obj())
} else {
let target = cache
.fetch_member(event.group_code, event.target_uin)
.await
.py_res()?;
let target = MemberInfo::new(&target, group.clone());
Ok(MemberMute {
operator,
target,
duration,
}
.obj())
}
}
25 changes: 25 additions & 0 deletions src/events/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub mod structs;
use structs::MessageSource;

use self::structs::{FriendInfo, MemberInfo};
use crate::client::group::Group;
use crate::utils::py_try;

#[pyclass(get_all)]
Expand Down Expand Up @@ -110,6 +111,30 @@ pub struct FriendDeleted {
friend_uin: i64,
}

#[pyclass(get_all)]
#[derive(PyRepr, Clone)]
pub struct MemberMute {
target: MemberInfo,
operator: MemberInfo,
duration: PyObject, // datetime.timedelta | Literal[False]
}

#[pyclass(get_all)]
#[derive(PyRepr, Clone)]
pub struct BotMute {
group: Group,
operator: MemberInfo,
duration: PyObject, // datetime.timedelta | Literal[False]
}

#[pyclass(get_all)]
#[derive(PyRepr, Clone)]
pub struct GroupMute {
group: Group,
operator: MemberInfo,
status: bool,
}

#[pyclass]
#[derive(PyRepr, Clone)]
pub struct UnknownEvent {
Expand Down
3 changes: 1 addition & 2 deletions src/events/structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use pyo3::prelude::*;
use pyo3::types::PyTuple;
use pyo3_repr::PyRepr;

use crate::call_static_py;
use crate::client::group::{Group, Member};
use crate::utils::datetime_from_ts;
#[pyclass(get_all)]
Expand All @@ -18,7 +17,7 @@ impl MessageSource {
Ok(Self {
seqs: PyTuple::new(py, seqs).into_py(py),
rands: PyTuple::new(py, rands).into_py(py),
time: call_static_py!(datetime_from_ts, py, (time))?.into(),
time: datetime_from_ts(py, time)?.into_py(py),
})
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ fn register_event_module(py: Python, parent: &PyModule) -> PyResult<()> {
crate::events::BotLeaveGroup,
crate::events::GroupDisband,
crate::events::FriendDeleted,
crate::events::GroupMute,
crate::events::MemberMute,
crate::events::BotMute,
crate::events::UnknownEvent
);
parent.add_submodule(m)?;
Expand Down
17 changes: 16 additions & 1 deletion src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,10 +163,25 @@ macro_rules! call_static_py {
}

static_py_fn!(
datetime_from_ts,
_datetime_from_ts,
__DT_CELL,
"datetime",
["datetime", "fromtimestamp"]
);

pub fn datetime_from_ts(py: Python<'_>, time: impl IntoPy<PyObject>) -> PyResult<&PyAny> {
call_static_py!(_datetime_from_ts, py, (time))
}

static_py_fn!(
_timedelta_from_secs,
__TDELTA_CELL,
"datetime",
["timedelta"]
);

pub fn timedelta_from_secs(py: Python<'_>, delta: impl IntoPy<PyObject>) -> PyResult<&PyAny> {
_timedelta_from_secs(py).call((), kwargs!(py, "seconds" => delta.into_py(py)))
}

static_py_fn!(partial, __PARTIAL_CELL, "functools", ["partial"]);

0 comments on commit 2dcd9ad

Please sign in to comment.