mirror of
https://github.com/pimalaya/himalaya.git
synced 2026-06-17 21:37:55 +08:00
refactor: clean serializers
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
use anyhow::{anyhow, bail, Result};
|
||||
use clap::Parser;
|
||||
use io_jmap::{
|
||||
rfc8620::coroutines::blob_download::{JmapBlobDownload, JmapBlobDownloadResult},
|
||||
rfc8620::types::session::capabilities,
|
||||
rfc8620::{
|
||||
coroutines::blob_download::{JmapBlobDownload, JmapBlobDownloadResult},
|
||||
types::session::capabilities::{self, MAIL},
|
||||
},
|
||||
rfc8621::coroutines::email_get::{JmapEmailGet, JmapEmailGetResult},
|
||||
};
|
||||
use io_stream::runtimes::std::handle;
|
||||
@@ -52,7 +54,7 @@ impl ExportEmailCommand {
|
||||
let account_id = jmap
|
||||
.session
|
||||
.primary_accounts
|
||||
.get(capabilities::MAIL)
|
||||
.get(MAIL)
|
||||
.map(|s| s.as_str())
|
||||
.unwrap_or("");
|
||||
let blob_id = emails
|
||||
|
||||
@@ -6,10 +6,14 @@ use std::{
|
||||
use anyhow::{bail, Result};
|
||||
use clap::Parser;
|
||||
use io_jmap::{
|
||||
rfc8620::coroutines::blob_upload::{JmapBlobUpload, JmapBlobUploadResult},
|
||||
rfc8620::types::session::capabilities,
|
||||
rfc8621::coroutines::email_import::{JmapEmailImport, JmapEmailImportResult},
|
||||
rfc8621::types::email::EmailImport,
|
||||
rfc8620::{
|
||||
coroutines::blob_upload::{JmapBlobUpload, JmapBlobUploadResult},
|
||||
types::session::capabilities::{self, MAIL},
|
||||
},
|
||||
rfc8621::{
|
||||
coroutines::email_import::{JmapEmailImport, JmapEmailImportResult},
|
||||
types::email::EmailImport,
|
||||
},
|
||||
};
|
||||
use io_stream::runtimes::std::handle;
|
||||
use pimalaya_toolbox::terminal::printer::{Message, Printer};
|
||||
@@ -64,7 +68,7 @@ impl ImportEmailCommand {
|
||||
let account_id = jmap
|
||||
.session
|
||||
.primary_accounts
|
||||
.get(capabilities::MAIL)
|
||||
.get(MAIL)
|
||||
.map(|s| s.as_str())
|
||||
.unwrap_or("");
|
||||
let url: Url = jmap
|
||||
|
||||
+18
-1
@@ -4,6 +4,7 @@ use io_jmap::rfc8621::coroutines::email_parse::{JmapEmailParse, JmapEmailParseRe
|
||||
use io_stream::runtimes::std::handle;
|
||||
use log::warn;
|
||||
use pimalaya_toolbox::terminal::printer::Printer;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::jmap::account::JmapAccount;
|
||||
|
||||
@@ -49,13 +50,15 @@ impl ParseEmailCommand {
|
||||
warn!("blob `{id}` not valid MIME message, ignoring it");
|
||||
}
|
||||
|
||||
let mut bodies = Vec::new();
|
||||
|
||||
for (_blob_id, email) in parsed {
|
||||
if let Some(body_values) = &email.body_values {
|
||||
if let Some(text_parts) = &email.text_body {
|
||||
for part in text_parts {
|
||||
if let Some(part_id) = &part.part_id {
|
||||
if let Some(body_value) = body_values.get(part_id) {
|
||||
printer.out(&body_value.value)?;
|
||||
bodies.push(body_value.value.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -63,6 +66,20 @@ impl ParseEmailCommand {
|
||||
}
|
||||
}
|
||||
|
||||
printer.out(ParsedBodies { bodies })
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct ParsedBodies {
|
||||
bodies: Vec<String>,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for ParsedBodies {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
for body in &self.bodies {
|
||||
write!(f, "{body}")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,7 +171,6 @@ impl JmapEmailQueryCommand {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct EmailsTable {
|
||||
#[serde(skip)]
|
||||
pub preset: String,
|
||||
|
||||
@@ -58,7 +58,6 @@ impl GetIdentityCommand {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct IdentitiesTable {
|
||||
#[serde(skip)]
|
||||
pub preset: String,
|
||||
|
||||
@@ -118,7 +118,6 @@ impl JmapMailboxQueryCommand {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Serialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct MailboxesTable {
|
||||
#[serde(skip)]
|
||||
pub preset: String,
|
||||
|
||||
+23
-16
@@ -7,11 +7,12 @@ use anyhow::{bail, Context, Result};
|
||||
use clap::Parser;
|
||||
use io_jmap::rfc8620::{
|
||||
coroutines::send::{JmapRequest, JmapSend, JmapSendResult},
|
||||
types::session::capabilities,
|
||||
types::session::capabilities::{CORE, MAIL},
|
||||
};
|
||||
use io_stream::runtimes::std::handle;
|
||||
use pimalaya_toolbox::terminal::printer::Printer;
|
||||
use serde::Serialize;
|
||||
use serde_json::Value;
|
||||
|
||||
use crate::jmap::account::JmapAccount;
|
||||
|
||||
@@ -53,50 +54,52 @@ impl QueryCommand {
|
||||
self.method_calls.join(" ")
|
||||
};
|
||||
|
||||
let calls_value: serde_json::Value =
|
||||
let calls_value: Value =
|
||||
serde_json::from_str(&raw).context("METHOD_CALLS is not valid JSON")?;
|
||||
|
||||
let serde_json::Value::Array(calls_arr) = calls_value else {
|
||||
let Value::Array(calls_arr) = calls_value else {
|
||||
bail!("METHOD_CALLS must be a JSON array");
|
||||
};
|
||||
|
||||
let account_id = jmap
|
||||
.session
|
||||
.primary_accounts
|
||||
.get(capabilities::MAIL)
|
||||
.get(MAIL)
|
||||
.cloned()
|
||||
.unwrap_or_default();
|
||||
|
||||
// Parse and inject accountId into each call's args.
|
||||
let mut method_calls = Vec::with_capacity(calls_arr.len());
|
||||
for (i, call) in calls_arr.into_iter().enumerate() {
|
||||
let serde_json::Value::Array(mut tuple) = call else {
|
||||
let Value::Array(mut tuple) = call else {
|
||||
bail!("method call #{i} must be a JSON array [name, args, callId]");
|
||||
};
|
||||
|
||||
if tuple.len() != 3 {
|
||||
bail!("method call #{i} must have exactly 3 elements [name, args, callId]");
|
||||
}
|
||||
|
||||
let call_id = match tuple.remove(2) {
|
||||
serde_json::Value::String(s) => s,
|
||||
Value::String(s) => s,
|
||||
v => bail!("method call #{i} callId must be a string, got {v}"),
|
||||
};
|
||||
|
||||
let mut args = tuple.remove(1);
|
||||
let name = match tuple.remove(0) {
|
||||
serde_json::Value::String(s) => s,
|
||||
Value::String(s) => s,
|
||||
v => bail!("method call #{i} name must be a string, got {v}"),
|
||||
};
|
||||
|
||||
// Inject accountId if the args object doesn't already have it.
|
||||
if let serde_json::Value::Object(ref mut map) = args {
|
||||
if let Value::Object(ref mut map) = args {
|
||||
map.entry("accountId")
|
||||
.or_insert_with(|| serde_json::Value::String(account_id.clone()));
|
||||
.or_insert_with(|| Value::String(account_id.clone()));
|
||||
}
|
||||
|
||||
method_calls.push((name, args, call_id));
|
||||
}
|
||||
|
||||
let mut using = vec![
|
||||
capabilities::CORE.to_string(),
|
||||
capabilities::MAIL.to_string(),
|
||||
];
|
||||
let mut using = vec![CORE.to_string(), MAIL.to_string()];
|
||||
for extra in self.using {
|
||||
if !using.contains(&extra) {
|
||||
using.push(extra);
|
||||
@@ -122,17 +125,21 @@ impl QueryCommand {
|
||||
}
|
||||
};
|
||||
|
||||
printer.out(RawResponse(response.method_responses))
|
||||
printer.out(RawResponse {
|
||||
method_responses: response.method_responses,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Wraps the raw method_responses for display.
|
||||
#[derive(Serialize)]
|
||||
struct RawResponse(Vec<(String, serde_json::Value, String)>);
|
||||
struct RawResponse {
|
||||
method_responses: Vec<(String, Value, String)>,
|
||||
}
|
||||
|
||||
impl fmt::Display for RawResponse {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match serde_json::to_string_pretty(&self.0) {
|
||||
match serde_json::to_string_pretty(&self.method_responses) {
|
||||
Ok(s) => write!(f, "{s}"),
|
||||
Err(e) => write!(f, "<serialization error: {e}>"),
|
||||
}
|
||||
|
||||
@@ -108,7 +108,6 @@ impl QuerySubmissionCommand {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct SubmissionsTable {
|
||||
#[serde(skip)]
|
||||
pub preset: String,
|
||||
|
||||
@@ -53,7 +53,6 @@ impl GetThreadCommand {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct ThreadsTable {
|
||||
#[serde(skip)]
|
||||
pub preset: String,
|
||||
|
||||
Reference in New Issue
Block a user