use std::collections::HashMap;
use steamid::SteamID;
use crate::{error::SteamError, SteamClient};
#[derive(Debug, Clone)]
pub struct ChatRoomGroup {
pub chat_group_id: String,
pub chat_group_name: String,
pub steamid_owner: SteamID,
pub tagline: String,
pub avatar_url: Option<String>,
pub appid: Option<u32>,
pub default_chat_id: String,
pub active_member_count: u32,
pub active_voice_member_count: u32,
pub chat_rooms: Vec<ChatRoom>,
pub members: Vec<ChatRoomMember>,
pub roles: Vec<ChatRole>,
}
#[derive(Debug, Clone)]
pub struct ChatRoom {
pub chat_id: String,
pub chat_name: String,
pub voice_allowed: bool,
pub members_in_voice: Vec<SteamID>,
pub time_last_message: u32,
pub sort_order: u32,
pub last_message: String,
pub steamid_last_message: Option<SteamID>,
}
#[derive(Debug, Clone)]
pub struct ChatRoomMember {
pub steamid: SteamID,
pub state: u32,
pub rank: u32,
pub time_kick_expire: Option<u32>,
pub role_ids: Vec<String>,
}
#[derive(Debug, Clone)]
pub struct ChatRole {
pub role_id: String,
pub name: String,
pub ordinal: u32,
}
#[derive(Debug, Clone, Default)]
pub struct RolePermissions {
pub can_create_rename_delete_channel: bool,
pub can_kick: bool,
pub can_ban: bool,
pub can_invite: bool,
pub can_change_tagline_avatar_name: bool,
pub can_chat: bool,
pub can_view_history: bool,
pub can_change_group_roles: bool,
pub can_change_user_roles: bool,
pub can_mention_all: bool,
pub can_set_watching_broadcast: bool,
}
#[derive(Debug, Clone)]
pub struct ChatRoomMessage {
pub sender: SteamID,
pub message: String,
pub server_timestamp: u32,
pub ordinal: u32,
pub deleted: bool,
}
#[derive(Debug, Clone)]
pub struct ChatRoomBan {
pub steamid: SteamID,
pub steamid_actor: SteamID,
pub time_banned: u32,
pub ban_reason: String,
}
#[derive(Debug, Clone)]
pub struct InviteLinkInfo {
pub invite_code: String,
pub steamid_sender: SteamID,
pub time_expires: Option<u32>,
pub group_summary: Option<ChatRoomGroup>,
pub banned: bool,
pub time_kick_expire: Option<u32>,
pub chat_id: Option<String>,
}
impl SteamClient {
pub async fn create_chat_room_group(&mut self, name: &str, invitees: Vec<SteamID>) -> Result<ChatRoomGroup, SteamError> {
if !self.is_logged_in() {
return Err(SteamError::NotLoggedOn);
}
let msg = steam_protos::CChatRoomCreateChatRoomGroupRequest {
name: Some(name.to_string()),
steamid_invitees: invitees.iter().map(|s| s.steam_id64()).collect(),
..Default::default()
};
self.send_service_method("ChatRoom.CreateChatRoomGroup#1", &msg).await?;
Ok(ChatRoomGroup {
chat_group_id: String::new(),
chat_group_name: name.to_string(),
steamid_owner: self.steam_id.unwrap_or_default(),
tagline: String::new(),
avatar_url: None,
appid: None,
default_chat_id: String::new(),
active_member_count: 0,
active_voice_member_count: 0,
chat_rooms: Vec::new(),
members: Vec::new(),
roles: Vec::new(),
})
}
pub async fn save_chat_room_group(&mut self, group_id: SteamID, name: &str) -> Result<(), SteamError> {
if !self.is_logged_in() {
return Err(SteamError::NotLoggedOn);
}
let msg = steam_protos::CChatRoomSaveChatRoomGroupRequest { chat_group_id: Some(group_id.steam_id64()), name: Some(name.to_string()) };
self.send_service_method("ChatRoom.SaveChatRoomGroup#1", &msg).await
}
pub async fn get_chat_room_groups(&mut self) -> Result<HashMap<String, ChatRoomGroup>, SteamError> {
if !self.is_logged_in() {
return Err(SteamError::NotLoggedOn);
}
let msg = steam_protos::CChatRoomGetMyChatRoomGroupsRequest {};
self.send_service_method("ChatRoom.GetMyChatRoomGroups#1", &msg).await?;
Ok(HashMap::new())
}
pub async fn set_session_active_chat_groups(&mut self, group_ids: Vec<SteamID>) -> Result<HashMap<String, ChatRoomGroup>, SteamError> {
if !self.is_logged_in() {
return Err(SteamError::NotLoggedOn);
}
let chat_group_ids: Vec<u64> = group_ids.iter().map(|s| s.steam_id64()).collect();
let msg = steam_protos::CChatRoomSetSessionActiveChatRoomGroupsRequest { chat_group_ids: chat_group_ids.clone(), chat_groups_data_requested: chat_group_ids, ..Default::default() };
self.send_service_method("ChatRoom.SetSessionActiveChatRoomGroups#1", &msg).await?;
Ok(HashMap::new())
}
pub async fn get_chat_invite_link_info(&mut self, link_url: &str) -> Result<InviteLinkInfo, SteamError> {
if !self.is_logged_in() {
return Err(SteamError::NotLoggedOn);
}
let invite_code = link_url.split("/chat/").last().ok_or_else(|| SteamError::Other("Invalid invite link".into()))?.trim_end_matches('/');
let msg = steam_protos::CChatRoomGetInviteLinkInfoRequest { invite_code: Some(invite_code.to_string()) };
self.send_service_method("ChatRoom.GetInviteLinkInfo#1", &msg).await?;
Ok(InviteLinkInfo {
invite_code: invite_code.to_string(),
steamid_sender: SteamID::new(),
time_expires: None,
group_summary: None,
banned: false,
time_kick_expire: None,
chat_id: None,
})
}
pub async fn join_chat_room_group(&mut self, group_id: SteamID, invite_code: Option<&str>) -> Result<ChatRoomGroup, SteamError> {
if !self.is_logged_in() {
return Err(SteamError::NotLoggedOn);
}
let msg = steam_protos::CChatRoomJoinChatRoomGroupRequest {
chat_group_id: Some(group_id.steam_id64()),
invite_code: invite_code.map(|s| s.to_string()),
..Default::default()
};
self.send_service_method("ChatRoom.JoinChatRoomGroup#1", &msg).await?;
Ok(ChatRoomGroup {
chat_group_id: group_id.to_string(),
chat_group_name: String::new(),
steamid_owner: SteamID::new(),
tagline: String::new(),
avatar_url: None,
appid: None,
default_chat_id: String::new(),
active_member_count: 0,
active_voice_member_count: 0,
chat_rooms: Vec::new(),
members: Vec::new(),
roles: Vec::new(),
})
}
pub async fn leave_chat_room_group(&mut self, group_id: SteamID) -> Result<(), SteamError> {
if !self.is_logged_in() {
return Err(SteamError::NotLoggedOn);
}
let msg = steam_protos::CChatRoomLeaveChatRoomGroupRequest { chat_group_id: Some(group_id.steam_id64()) };
self.send_service_method("ChatRoom.LeaveChatRoomGroup#1", &msg).await
}
pub async fn create_chat_room_invite_link(&mut self, group_id: SteamID, seconds_valid: Option<u32>, voice_chat_id: Option<String>) -> Result<String, SteamError> {
if !self.is_logged_in() {
return Err(SteamError::NotLoggedOn);
}
let msg = steam_protos::CChatRoomCreateInviteLinkRequest {
chat_group_id: Some(group_id.steam_id64()),
seconds_valid: Some(seconds_valid.unwrap_or(3600)),
chat_id: voice_chat_id.and_then(|id| id.parse().ok()),
};
let response: steam_protos::CChatRoomCreateInviteLinkResponse = self.send_service_method_and_wait("ChatRoom.CreateInviteLink#1", &msg).await?;
Ok(response.invite_code.unwrap_or_default())
}
pub async fn get_group_invite_links(&mut self, group_id: SteamID) -> Result<Vec<InviteLinkInfo>, SteamError> {
if !self.is_logged_in() {
return Err(SteamError::NotLoggedOn);
}
let msg = steam_protos::CChatRoomGetInviteLinksForGroupRequest { chat_group_id: Some(group_id.steam_id64()) };
let response: steam_protos::CChatRoomGetInviteLinksForGroupResponse = self.send_service_method_and_wait("ChatRoom.GetInviteLinksForGroup#1", &msg).await?;
let links = response
.invite_links
.into_iter()
.map(|link| InviteLinkInfo {
invite_code: link.invite_code.unwrap_or_default(),
steamid_sender: SteamID::from_steam_id64(link.steamid_creator.unwrap_or(0)),
time_expires: link.time_expires,
group_summary: None,
banned: false,
time_kick_expire: None,
chat_id: link.chat_id.map(|id| id.to_string()),
})
.collect();
Ok(links)
}
pub async fn delete_invite_link(&mut self, group_id: SteamID, invite_code: &str) -> Result<(), SteamError> {
if !self.is_logged_in() {
return Err(SteamError::NotLoggedOn);
}
let msg = steam_protos::CChatRoomDeleteInviteLinkRequest { chat_group_id: Some(group_id.steam_id64()), invite_code: Some(invite_code.to_string()) };
self.send_service_method("ChatRoom.DeleteInviteLink#1", &msg).await
}
pub async fn send_chat_room_message(&mut self, group_id: SteamID, chat_id: u64, message: &str) -> Result<(), SteamError> {
if !self.is_logged_in() {
return Err(SteamError::NotLoggedOn);
}
let msg = steam_protos::CChatRoomSendChatMessageRequest {
chat_group_id: Some(group_id.steam_id64()),
chat_id: Some(chat_id),
message: Some(message.to_string()),
..Default::default()
};
self.send_service_method("ChatRoom.SendChatMessage#1", &msg).await
}
pub async fn create_chat_room(&mut self, group_id: SteamID, name: &str, allow_voice: bool) -> Result<ChatRoom, SteamError> {
if !self.is_logged_in() {
return Err(SteamError::NotLoggedOn);
}
let msg = steam_protos::CChatRoomCreateChatRoomRequest { chat_group_id: Some(group_id.steam_id64()), name: Some(name.to_string()), allow_voice: Some(allow_voice) };
let response: steam_protos::CChatRoomCreateChatRoomResponse = self.send_service_method_and_wait("ChatRoom.CreateChatRoom#1", &msg).await?;
let room = response.chat_room.ok_or_else(|| SteamError::Other("No chat room returned".into()))?;
Ok(ChatRoom {
chat_id: room.chat_id.unwrap_or(0).to_string(),
chat_name: room.chat_name.unwrap_or_default(),
voice_allowed: room.voice_allowed.unwrap_or(false),
members_in_voice: room.members_in_voice.into_iter().map(SteamID::from_individual_account_id).collect(),
time_last_message: room.time_last_message.unwrap_or(0),
sort_order: room.sort_order.unwrap_or(0),
last_message: room.last_message.unwrap_or_default(),
steamid_last_message: room.accountid_last_message.map(SteamID::from_individual_account_id),
})
}
pub async fn rename_chat_room(&mut self, group_id: SteamID, chat_id: u64, name: &str) -> Result<(), SteamError> {
if !self.is_logged_in() {
return Err(SteamError::NotLoggedOn);
}
let msg = steam_protos::CChatRoomRenameChatRoomRequest { chat_group_id: Some(group_id.steam_id64()), chat_id: Some(chat_id), name: Some(name.to_string()) };
self.send_service_method("ChatRoom.RenameChatRoom#1", &msg).await
}
pub async fn delete_chat_room(&mut self, group_id: SteamID, chat_id: u64) -> Result<(), SteamError> {
if !self.is_logged_in() {
return Err(SteamError::NotLoggedOn);
}
let msg = steam_protos::CChatRoomDeleteChatRoomRequest { chat_group_id: Some(group_id.steam_id64()), chat_id: Some(chat_id) };
self.send_service_method("ChatRoom.DeleteChatRoom#1", &msg).await
}
pub async fn get_chat_room_message_history(&mut self, group_id: SteamID, chat_id: u64, last_time: u32, last_ordinal: u32, max_count: u32) -> Result<Vec<ChatRoomMessage>, SteamError> {
if !self.is_logged_in() {
return Err(SteamError::NotLoggedOn);
}
let msg = steam_protos::CChatRoomGetMessageHistoryRequest {
chat_group_id: Some(group_id.steam_id64()),
chat_id: Some(chat_id),
last_time: Some(last_time),
last_ordinal: Some(last_ordinal),
max_count: Some(max_count),
..Default::default()
};
self.send_service_method("ChatRoom.GetMessageHistory#1", &msg).await?;
Ok(Vec::new())
}
pub async fn ack_chat_message(&mut self, group_id: SteamID, chat_id: u64, timestamp: u32) -> Result<(), SteamError> {
if !self.is_logged_in() {
return Err(SteamError::NotLoggedOn);
}
let msg = steam_protos::CChatRoomAckChatMessageNotification { chat_group_id: Some(group_id.steam_id64()), chat_id: Some(chat_id), timestamp: Some(timestamp) };
self.send_service_method("ChatRoom.AckChatMessage#1", &msg).await
}
pub async fn delete_chat_messages(&mut self, group_id: SteamID, chat_id: u64, messages: Vec<(u32, u32)>) -> Result<(), SteamError> {
if !self.is_logged_in() {
return Err(SteamError::NotLoggedOn);
}
let proto_messages = messages.into_iter().map(|(ts, ord)| steam_protos::CChatRoomMessage { server_timestamp: Some(ts), ordinal: Some(ord) }).collect();
let msg = steam_protos::CChatRoomDeleteChatMessagesRequest { chat_group_id: Some(group_id.steam_id64()), chat_id: Some(chat_id), messages: proto_messages };
self.send_service_method("ChatRoom.DeleteChatMessages#1", &msg).await
}
pub async fn get_clan_chat_group_info(&mut self, clan_id: SteamID) -> Result<ChatRoomGroup, SteamError> {
if !self.is_logged_in() {
return Err(SteamError::NotLoggedOn);
}
let msg = steam_protos::CClanChatRoomsGetClanChatRoomInfoRequest { steamid: Some(clan_id.steam_id64()), autocreate: Some(true) };
let response: steam_protos::CClanChatRoomsGetClanChatRoomInfoResponse = self.send_service_method_and_wait("ClanChatRooms.GetClanChatRoomInfo#1", &msg).await?;
let summary = response.chat_group_summary.unwrap_or_default();
Ok(ChatRoomGroup {
chat_group_id: summary.chat_group_id.unwrap_or(0).to_string(),
chat_group_name: summary.chat_group_name.unwrap_or_default(),
steamid_owner: SteamID::from_steam_id64(summary.steamid_owner.unwrap_or(0)),
tagline: summary.chat_group_tagline.unwrap_or_default(),
avatar_url: None, appid: summary.appid,
default_chat_id: summary.default_chat_id.unwrap_or(0).to_string(),
active_member_count: summary.active_member_count.unwrap_or(0),
active_voice_member_count: summary.active_voice_member_count.unwrap_or(0),
chat_rooms: Vec::new(), members: Vec::new(),
roles: Vec::new(),
})
}
pub async fn kick_chat_room_member(&mut self, group_id: SteamID, steamid: SteamID, expiry: Option<u32>) -> Result<(), SteamError> {
if !self.is_logged_in() {
return Err(SteamError::NotLoggedOn);
}
let msg = steam_protos::CChatRoomKickUserRequest {
chat_group_id: Some(group_id.steam_id64()),
steamid: Some(steamid.steam_id64()),
expiration: expiry.map(|e| e as i32),
};
self.send_service_method("ChatRoom.KickUser#1", &msg).await
}
pub async fn ban_chat_room_member(&mut self, group_id: SteamID, steamid: SteamID, _expiry: Option<u32>) -> Result<(), SteamError> {
if !self.is_logged_in() {
return Err(SteamError::NotLoggedOn);
}
let msg = steam_protos::CChatRoomSetUserBanStateRequest { chat_group_id: Some(group_id.steam_id64()), steamid: Some(steamid.steam_id64()), ban_state: Some(true) };
self.send_service_method("ChatRoom.SetUserBanState#1", &msg).await
}
pub async fn unban_chat_room_member(&mut self, group_id: SteamID, steamid: SteamID) -> Result<(), SteamError> {
if !self.is_logged_in() {
return Err(SteamError::NotLoggedOn);
}
let msg = steam_protos::CChatRoomSetUserBanStateRequest { chat_group_id: Some(group_id.steam_id64()), steamid: Some(steamid.steam_id64()), ban_state: Some(false) };
self.send_service_method("ChatRoom.SetUserBanState#1", &msg).await
}
pub async fn get_group_ban_list(&mut self, group_id: SteamID) -> Result<Vec<ChatRoomBan>, SteamError> {
if !self.is_logged_in() {
return Err(SteamError::NotLoggedOn);
}
let msg = steam_protos::CChatRoomGetBanListRequest { chat_group_id: Some(group_id.steam_id64()) };
let response: steam_protos::CChatRoomGetBanListResponse = self.send_service_method_and_wait("ChatRoom.GetBanList#1", &msg).await?;
let bans = response
.bans
.into_iter()
.map(|ban| ChatRoomBan {
steamid: SteamID::from_steam_id64(ban.steamid.unwrap_or(0)),
steamid_actor: SteamID::from_steam_id64(ban.steamid_actor.unwrap_or(0)),
time_banned: ban.time_banned.unwrap_or(0),
ban_reason: ban.ban_reason.unwrap_or_default(),
})
.collect();
Ok(bans)
}
pub async fn set_group_user_role_state(&mut self, group_id: SteamID, steamid: SteamID, role_id: &str, role_state: bool) -> Result<(), SteamError> {
if !self.is_logged_in() {
return Err(SteamError::NotLoggedOn);
}
if role_state {
let msg = steam_protos::CChatRoomAddRoleToUserRequest {
chat_group_id: Some(group_id.steam_id64()),
role_id: Some(role_id.parse().unwrap_or(0)),
steamid: Some(steamid.steam_id64()),
};
self.send_service_method("ChatRoom.AddRoleToUser#1", &msg).await
} else {
let msg = steam_protos::CChatRoomDeleteRoleFromUserRequest {
chat_group_id: Some(group_id.steam_id64()),
role_id: Some(role_id.parse().unwrap_or(0)),
steamid: Some(steamid.steam_id64()),
};
self.send_service_method("ChatRoom.DeleteRoleFromUser#1", &msg).await
}
}
pub async fn invite_to_chat_room_group(&mut self, group_id: SteamID, steamid: SteamID) -> Result<(), SteamError> {
if !self.is_logged_in() {
return Err(SteamError::NotLoggedOn);
}
let msg = steam_protos::CChatRoomInviteFriendToChatRoomGroupRequest { chat_group_id: Some(group_id.steam_id64()), steamid: Some(steamid.steam_id64()), ..Default::default() };
self.send_service_method("ChatRoom.InviteFriendToChatRoomGroup#1", &msg).await
}
}