|
|
@ -1,4 +1,5 @@ |
|
|
|
use std::collections::HashMap; |
|
|
|
use std::collections::HashMap; |
|
|
|
|
|
|
|
use std::path::Path; |
|
|
|
|
|
|
|
|
|
|
|
use reqwest::multipart::Form; |
|
|
|
use reqwest::multipart::Form; |
|
|
|
use reqwest::multipart::Part; |
|
|
|
use reqwest::multipart::Part; |
|
|
@ -9,6 +10,8 @@ use crate::config::JoplinConfig; |
|
|
|
use crate::storage::data::Data; |
|
|
|
use crate::storage::data::Data; |
|
|
|
use crate::storage::storage::Storage; |
|
|
|
use crate::storage::storage::Storage; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static INLINABLE: [&'static str; 4] = ["jpeg", "jpg", "png", "gif"]; |
|
|
|
|
|
|
|
|
|
|
|
/// This is the folder structured returned by Joplin. It is here so Reqwests can
|
|
|
|
/// This is the folder structured returned by Joplin. It is here so Reqwests can
|
|
|
|
/// unjson the data (there are more fields, but these are the only ones we need
|
|
|
|
/// unjson the data (there are more fields, but these are the only ones we need
|
|
|
|
/// right now).
|
|
|
|
/// right now).
|
|
|
@ -86,7 +89,12 @@ impl Joplin { |
|
|
|
fn add_resources_to_text(text: &mut String, resources: &Vec<Resource>) { |
|
|
|
fn add_resources_to_text(text: &mut String, resources: &Vec<Resource>) { |
|
|
|
resources.iter().for_each(|resource| { |
|
|
|
resources.iter().for_each(|resource| { |
|
|
|
let link = format!( |
|
|
|
let link = format!( |
|
|
|
"![{filename}](:/{resource})", |
|
|
|
"{inline}[{filename}](:/{resource})", |
|
|
|
|
|
|
|
inline = if Joplin::is_inlineable(&resource.filename) { |
|
|
|
|
|
|
|
"!" |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
"" |
|
|
|
|
|
|
|
}, |
|
|
|
filename = resource.filename, |
|
|
|
filename = resource.filename, |
|
|
|
resource = resource.id |
|
|
|
resource = resource.id |
|
|
|
); |
|
|
|
); |
|
|
@ -95,6 +103,16 @@ impl Joplin { |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn is_inlineable(filename: &String) -> bool { |
|
|
|
|
|
|
|
if let Some(extension) = Path::new(filename).extension() { |
|
|
|
|
|
|
|
INLINABLE |
|
|
|
|
|
|
|
.iter() |
|
|
|
|
|
|
|
.any(|ext| *ext == extension.to_str().unwrap_or("")) |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
false |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fn save_attachments(&self, record: &Data) -> Vec<Resource> { |
|
|
|
fn save_attachments(&self, record: &Data) -> Vec<Resource> { |
|
|
|
record |
|
|
|
record |
|
|
|
.attachments |
|
|
|
.attachments |
|
|
@ -123,10 +141,7 @@ impl Joplin { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fn upload_resource(&self, filename: String, content: Vec<u8>) -> String { |
|
|
|
fn upload_resource(&self, filename: String, content: Vec<u8>) -> String { |
|
|
|
let props = format!( |
|
|
|
let props = format!("{{\"title\": \"{filename}\"}}", filename = &filename); |
|
|
|
"{{\"title\": \"{filename}\", \"filename\": \"{filename}\"}}", |
|
|
|
|
|
|
|
filename = &filename, |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
let data_part = Part::bytes(content).file_name(filename); |
|
|
|
let data_part = Part::bytes(content).file_name(filename); |
|
|
|
let props_part = Part::text(props); |
|
|
|
let props_part = Part::text(props); |
|
|
|
let form = Form::new() |
|
|
|
let form = Form::new() |
|
|
|