1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
use chrono::Utc;
use std::collections::HashMap;
use crate::{TwitterAPI, FRAGMENT};
use percent_encoding::utf8_percent_encode;
impl TwitterAPI {
pub fn encode(target: &str) -> percent_encoding::PercentEncode {
utf8_percent_encode(&target, &FRAGMENT)
}
pub(crate) fn create_oauth_header(
&self,
endpoint: &str,
params: &HashMap<&str, &str>,
) -> String {
let oauth_nonce: &str = &format!("nonce{}", Utc::now().timestamp());
let oauth_signature_method: &str = "HMAC-SHA1";
let oauth_timestamp: &str = &format!("{}", Utc::now().timestamp());
let oauth_version: &str = "1.0";
let mut map: HashMap<&str, &str> = maplit::hashmap! {
"oauth_nonce" => oauth_nonce,
"oauth_version" => oauth_version,
"oauth_timestamp" => oauth_timestamp,
"oauth_consumer_key" => &self.api_key,
"oauth_token" => &self.access_token,
"oauth_signature_method" => oauth_signature_method,
};
for (k, v) in params {
map.insert(k, v);
}
let oauth_signature: &str = &self.create_oauth_signature("POST", &endpoint, &map);
format!(
"OAuth oauth_consumer_key=\"{}\", oauth_nonce=\"{}\", oauth_signature=\"{}\", oauth_signature_method=\"{}\", oauth_timestamp=\"{}\", oauth_token=\"{}\", oauth_version=\"{}\"",
Self::encode(&self.api_key),
Self::encode(oauth_nonce),
Self::encode(oauth_signature),
Self::encode(oauth_signature_method),
Self::encode(oauth_timestamp),
Self::encode(&self.access_token),
Self::encode(oauth_version),
)
}
pub(crate) fn create_oauth_signature(
&self,
http_method: &str,
endpoint: &str,
params: &HashMap<&str, &str>,
) -> String {
let cs_encoded = Self::encode(&self.api_secret_key);
let ts_encoded = Self::encode(&self.access_token_secret);
let key: String = format!("{}&{}", cs_encoded, ts_encoded);
let mut params: Vec<(&str, &str)> = params.iter().map(|(&k, &v)| (k, v)).collect();
params.sort();
let param = params
.into_iter()
.map(|(k, v)| format!("{}={}", Self::encode(k), Self::encode(v)))
.collect::<Vec<String>>()
.join("&");
let data = format!(
"{}&{}&{}",
Self::encode(http_method),
Self::encode(endpoint),
Self::encode(¶m)
);
let hash = hmacsha1::hmac_sha1(key.as_bytes(), data.as_bytes());
base64::encode(&hash)
}
}