Skip to content

Commit

Permalink
Merge pull request #28 from fixstars/use-users.conversations
Browse files Browse the repository at this point in the history
conversations.list -> users.conversations
  • Loading branch information
vorj authored Aug 7, 2023
2 parents 005bc99 + e0bf446 commit 182f2c6
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 59 deletions.
48 changes: 37 additions & 11 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ failure = "0.1.1"
log = "0.4"
env_logger = "0.9.0"
chrono = "0.4.6"
serde = { version = "1.0.175", features = ["derive"] }
[dependencies.reqwest]
version = "0.11.11"
features = ["blocking"]
features = ["blocking", "json"]
15 changes: 5 additions & 10 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ use crate::runtime_error::{as_str, Result, RuntimeError};
mod slack;
use crate::slack::{
add_reaction, channel_type, conversations_history, post_ephemeral_attachments, post_message,
post_message_to_thread, public_channel_list, rtm_connect, try_connect_to_slack_com, users_list,
ChannelType,
post_message_to_thread, rtm_connect, try_connect_to_slack_com, users_list,
users_public_channel_list, ChannelType,
};

mod linux_user_manage;
Expand Down Expand Up @@ -140,15 +140,10 @@ fn rtm_setup(
/// `channel_names` で与えられたチャンネルが、公開チャンネルとして存在するか確認する
fn check_channels(api_token: &str, channel_names: &[String]) -> Result<Vec<String>> {
// 公開チャンネルの一覧を取得
let public_channels = public_channel_list(api_token)?
let public_channels = users_public_channel_list(api_token, None)?
.into_iter()
.map(|v| {
Ok((
as_str(&v["name"])?.to_string(),
as_str(&v["id"])?.to_string(),
))
})
.collect::<Result<HashMap<_, _>>>()?;
.map(|v| (v.name, v.id))
.collect::<HashMap<_, _>>();
channel_names
.iter()
.map(|c| {
Expand Down
132 changes: 95 additions & 37 deletions src/slack.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use log::{debug, warn};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

use crate::runtime_error::{as_array, Result, RuntimeError};
Expand Down Expand Up @@ -100,6 +101,7 @@ pub fn rtm_connect(api_token: &str) -> Result<serde_json::Value> {
.parse()?)
}

#[derive(Clone, Copy, Debug)]
pub enum ChannelType {
PublicChannel,
PrivateChannel,
Expand Down Expand Up @@ -219,63 +221,119 @@ pub fn conversations_history(
.clone())
}

fn get_conversations_list(
#[derive(Serialize, Deserialize, Debug)]
struct Cursor {
next_cursor: String,
}
#[derive(Serialize, Debug)]
struct UsersConversationsParams<'a> {
token: &'a str,
cursor: Option<&'a str>,
exclude_archive: Option<bool>,
limit: Option<u16>,
team_id: Option<&'a str>,
types: Option<&'a str>,
user: Option<&'a str>,
}
impl<'a> UsersConversationsParams<'a> {
fn new(token: &'a str) -> Self {
UsersConversationsParams {
token,
cursor: None,
exclude_archive: None,
limit: None,
team_id: None,
types: None,
user: None,
}
}
}
#[derive(Deserialize, Debug)]
pub struct Channel {
pub id: String,
pub name: String,
}
#[derive(Deserialize, Debug)]
#[serde(untagged)]
enum UsersConversationsResponse {
Ok {
ok: bool,
channels: Vec<Channel>,
response_metadata: Cursor,
},
Err {
ok: bool,
error: String,
},
}

fn get_users_conversations(
api_token: &str,
cursor: Option<String>,
exclude_archive: Option<bool>,
types: Option<Vec<ChannelType>>,
) -> Result<(Vec<serde_json::Value>, Option<String>)> {
let types_: String;
types: Option<&[ChannelType]>,
user: Option<&str>,
) -> Result<(Vec<Channel>, Option<String>)> {
let s;
let form_params = {
let mut params = HashMap::new();
params.insert("token", api_token);
if let Some(ref c) = cursor {
params.insert("cursor", c);
}
if let Some(e) = exclude_archive {
params.insert("exclude_archive", if e { "true" } else { "false" });
}
params.insert("limit", "200");
let mut p = UsersConversationsParams::new(api_token);
p.cursor = cursor.as_deref();
p.exclude_archive = exclude_archive;
p.limit = Some(200);
if let Some(t) = types {
let mut ts = Vec::<&str>::new();
for x in t {
ts.push(get_channel_type_name_for_slack_api(x))
}
types_ = (&ts.join(",")).to_string();
params.insert("types", &types_);
let v = t
.iter()
.copied()
.map(get_channel_type_name_for_slack_api)
.collect::<Vec<_>>();
s = v.join(",");
p.types = Some(&s);
}
params
p.user = user;
p
};
let response = reqwest::blocking::Client::new()
.post("https://slack.com/api/conversations.list")
let response: UsersConversationsResponse = reqwest::blocking::Client::new()
.get("https://slack.com/api/users.conversations")
.header(
reqwest::header::CONTENT_TYPE,
"application/x-www-form-urlencoded; charset=utf-8",
)
.form(&form_params)
.query(&form_params)
.send()?
.text()?
.parse::<serde_json::Value>()?;
debug!("{}", serde_json::to_string_pretty(&response)?);
Ok((
as_array(&response["channels"])?.clone(),
response["response_metadata"]["next_cursor"]
.as_str()
.and_then(|s| if s.is_empty() { None } else { Some(s) })
.map(std::string::ToString::to_string),
))
.json()?;
match response {
UsersConversationsResponse::Ok {
ok,
channels,
response_metadata,
} => {
debug_assert!(ok);
let next_cursor = response_metadata.next_cursor;
if next_cursor.is_empty() {
Ok((channels, None))
} else {
Ok((channels, Some(next_cursor)))
}
}
UsersConversationsResponse::Err { ok, error } => {
debug_assert!(!ok);
let m = format!("API error: users.conversations failed \"{error}\"");
Err(RuntimeError::new(m).into())
}
}
}

/// 全てのpublic channelを取得
pub fn public_channel_list(api_token: &str) -> Result<Vec<serde_json::Value>> {
/// ユーザーが属している全てのpublic channelを取得
pub fn users_public_channel_list(api_token: &str, user: Option<&str>) -> Result<Vec<Channel>> {
let mut list = Vec::new();
let mut cursor = None;
loop {
let (mut ret, next_cursor) = get_conversations_list(
let (mut ret, next_cursor) = get_users_conversations(
api_token,
cursor,
Some(true),
Some(vec![ChannelType::PublicChannel]),
Some(&[ChannelType::PublicChannel]),
user,
)?;
list.append(&mut ret);
if next_cursor.is_some() {
Expand Down

0 comments on commit 182f2c6

Please sign in to comment.