1use reqwest::Client;
42use serde::{Deserialize, Serialize};
43
44use crate::error::{Result, ImpossibleError, assert};
45use crate::{Code, Target};
46
47
48#[derive(Clone, Debug)]
52pub struct MiraiServer {
53 pub base_url: String
54}
55
56#[derive(Debug)]
60pub struct Session {
61 pub(crate) client: Client,
62 pub server: MiraiServer,
63 pub key: String,
64}
65
66#[derive(Deserialize)]
67pub(crate) struct CommonResponse {
68 pub code: Code,
69 pub msg: String,
70}
71
72#[derive(Deserialize)]
73pub struct AboutResponse {
74 pub code: Code,
75 pub data: AboutData,
76}
77
78#[derive(Deserialize)]
79pub struct AboutData {
80 pub version: String
81}
82
83impl MiraiServer {
84 pub fn new(base_url: &str) -> MiraiServer {
85 MiraiServer {
86 base_url: base_url.to_string()
87 }
88 }
89
90 pub fn url(&self, path: &str) -> String {
91 self.base_url.clone() + path
92 }
93
94 pub async fn about(&self) -> Result<AboutResponse> {
95 let resp: AboutResponse = reqwest::get(&self.url("/about"))
96 .await?
97 .json().await?;
98
99 Ok(resp)
100 }
101
102 pub async fn auth(&self, auth_key: &str) -> Result<Session> {
103 #[derive(Serialize)]
104 struct Request {
105 #[serde(rename = "authKey")]
106 auth_key: String
107 }
108
109 #[derive(Deserialize)]
110 struct Response {
111 code: Code,
112 session: Option<String>,
113 }
114
115 let client = Client::new();
116 let req = Request {
117 auth_key: auth_key.to_string()
118 };
119
120 let result: Response = client.post(&self.url("/auth"))
121 .json(&req).send().await?
122 .json().await?;
123
124 assert(result.code, "Auth")?;
125
126 Ok(Session {
127 client,
128 server: self.clone(),
129 key: result.session.ok_or(ImpossibleError("session is None".to_string()))?,
130 })
131 }
132
133 pub async fn run_command(&self, auth_key: &str, command: &str, args: &[&str]) -> Result<String> {
134 #[serde(rename_all = "camelCase")]
135 #[derive(Serialize)]
136 struct Request<'s> {
137 auth_key: &'s str,
138 name: &'s str,
139 args: &'s [&'s str],
140 }
141
142 let req = Request {
143 auth_key,
144 name: command,
145 args,
146 };
147
148 let client = Client::new();
149 let text = client.post(&self.url("/command/send"))
150 .json(&req).send().await?
151 .text().await?;
152
153 Ok(text)
154 }
155}
156
157impl Session {
158 pub fn url(&self, path: &str) -> String {
159 self.server.url(path)
160 }
161
162 pub async fn verify(&self, qq: Target) -> Result<()> {
163 #[derive(Serialize)]
164 struct Request {
165 #[serde(rename = "sessionKey")]
166 session_key: String,
167 qq: Target,
168 }
169
170 let req = Request {
171 session_key: self.key.clone(),
172 qq,
173 };
174
175 let result: CommonResponse = self.client.post(&self.url("/verify"))
176 .json(&req).send().await?
177 .json().await?;
178
179 assert(result.code, "Verify")
180 }
181
182 pub async fn release(&self, qq: Target) -> Result<()> {
183 #[derive(Serialize)]
184 struct Request {
185 #[serde(rename = "sessionKey")]
186 session_key: String,
187 qq: Target,
188 }
189
190 let req = Request {
191 session_key: self.key.clone(),
192 qq,
193 };
194
195 let resp: CommonResponse = self.client.post(&self.url("/release"))
196 .json(&req).send().await?
197 .json().await?;
198
199 assert(resp.code, "Release")
200 }
201}