use serde_json::{json, Value};
use crate::error::ImError;
use crate::outbound::registry::{
build_creator_member_users, require_str, OutboundCommand, OutboundRegistration,
};
use super::helpers::{do_search_body, require_str_array};
macro_rules! misc_cmd {
($cmd_struct:ident, $reg:ident, $name:literal, $is_read:literal, $build:expr) => {
struct $cmd_struct;
impl OutboundCommand for $cmd_struct {
fn name(&self) -> &'static str {
$name
}
fn build(&self, args: &Value) -> Result<(&'static str, Value), ImError> {
let f: fn(&Value, &'static str) -> Result<(&'static str, Value), ImError> = $build;
f(args, $name)
}
fn is_read(&self) -> bool {
$is_read
}
}
inventory::submit! {
OutboundRegistration {
name: $name,
command: &$cmd_struct,
}
}
};
}
mod search;
misc_cmd!(
ListUsersCommand,
LIST_USERS_REG,
"im_list_users",
true,
|args, cmd| {
let channel_id = require_str(args, "channel_id", cmd)?;
Ok(("users/list", json!({ "channelId": channel_id })))
}
);
misc_cmd!(
GetUserStatusesCommand,
GET_USER_STATUSES_REG,
"im_get_user_statuses",
true,
|args, cmd| {
let user_ids = require_str_array(args, "user_ids", cmd)?;
Ok(("users/status/ids", json!({ "userIds": user_ids })))
}
);
misc_cmd!(
UserCandidatesCommand,
USER_CANDIDATES_REG,
"im_user_candidates",
true,
|args, cmd| {
let user_ids: Vec<String> = match args.get("user_ids") {
None => Vec::new(),
Some(Value::Array(items)) => items
.iter()
.map(|item| {
item.as_str()
.filter(|id| !id.is_empty())
.map(str::to_string)
.ok_or_else(|| ImError::Parse(format!("{cmd}: user_ids 含空值")))
})
.collect::<Result<Vec<_>, _>>()?,
Some(_) => return Err(ImError::Parse(format!("{cmd}: user_ids 必须为字符串数组"))),
};
let keyword = args.get("keyword").and_then(Value::as_str).unwrap_or("");
let limit = args
.get("limit")
.and_then(Value::as_u64)
.map(|value| value.clamp(1, 100))
.unwrap_or(50);
Ok((
"users/candidates",
json!({ "userIds": user_ids, "keyword": keyword, "limit": limit }),
))
}
);
misc_cmd!(
TeamUpsertCommand,
TEAM_UPSERT_REG,
"im_team_upsert",
false,
|args, cmd| {
let display_name = require_str(args, "display_name", cmd)?;
let self_id = require_str(args, "self_id", cmd)?;
let team_id = args.get("team_id").and_then(Value::as_str).unwrap_or("");
let (users, user_ids) = build_creator_member_users(args, cmd)?;
let team = json!({
"teamId": team_id,
"displayName": display_name,
"orient": "",
"type": "P",
"picturetype": "USER",
"picture": { "userIds": user_ids },
"users": users,
"forceCreate": true,
"owner": { "id": self_id, "teamId": team_id, "role": "CREATOR" },
});
Ok(("teams/upsert", team))
}
);
misc_cmd!(
TeamMemberAddCommand,
TEAM_MEMBER_ADD_REG,
"im_team_member_add",
false,
|args, cmd| {
let event = args
.get("event")
.filter(|v| v.is_object())
.cloned()
.ok_or_else(|| {
ImError::Parse(format!("{cmd}: 缺/坏 event(ChannelMemberEvent 对象)"))
})?;
Ok(("teams/member/add", event))
}
);
misc_cmd!(
TeamQuitCommand,
TEAM_QUIT_REG,
"im_team_quit",
false,
|args, cmd| {
let user_id = require_str(args, "user_id", cmd)?;
let team_id = require_str(args, "team_id", cmd)?;
Ok((
"teams/member/quit",
json!({ "userId": user_id, "teamId": team_id }),
))
}
);
misc_cmd!(
GetAllModulesCommand,
GET_ALL_MODULES_REG,
"im_get_all_modules",
true,
|_args, _cmd| { Ok(("modules/getAll", json!({}))) }
);
misc_cmd!(
LoadSendNotificationsCommand,
LOAD_SEND_NOTIFICATIONS_REG,
"im_load_send_notifications",
true,
|args, cmd| {
let page = args
.get("page")
.and_then(Value::as_i64)
.ok_or_else(|| ImError::Parse(format!("{cmd}: 缺/坏 page(int ≥1)")))?;
let size = args
.get("size")
.and_then(Value::as_i64)
.ok_or_else(|| ImError::Parse(format!("{cmd}: 缺/坏 size(int ≥1)")))?;
let mut b = json!({ "page": page, "size": size });
if let Some(state) = args.get("state").and_then(Value::as_str) {
b["state"] = json!(state);
}
Ok(("notification/loadSend", b))
}
);
misc_cmd!(
LoadTargetNotificationsCommand,
LOAD_TARGET_NOTIFICATIONS_REG,
"im_load_target_notifications",
true,
|args, _cmd| {
let page = args.get("page").and_then(Value::as_i64).unwrap_or(0);
let size = args.get("size").and_then(Value::as_i64).unwrap_or(10);
Ok((
"notification/loadTarget",
json!({ "page": page, "size": size }),
))
}
);
#[cfg(test)]
#[path = "core_tests.rs"]
mod tests;