mirror of
https://codeberg.org/postscriptum/snac2nex.git
synced 2026-03-31 21:25:28 +00:00
130 lines
4.4 KiB
Rust
130 lines
4.4 KiB
Rust
mod config;
|
|
mod nex;
|
|
mod response;
|
|
mod snac;
|
|
|
|
use anyhow::Result;
|
|
use nex::Nex;
|
|
use response::Response;
|
|
use snac::Snac;
|
|
|
|
fn main() -> Result<()> {
|
|
use clap::Parser;
|
|
use config::Config;
|
|
|
|
let c = Config::parse();
|
|
let n = Nex::init(
|
|
c.target,
|
|
c.format_filename,
|
|
c.format_updated,
|
|
c.format_content,
|
|
c.attachment,
|
|
!c.keep,
|
|
&c.user,
|
|
)?;
|
|
let s = Snac::init(c.source, c.user)?;
|
|
|
|
println!("export begin...");
|
|
let mut r = sync(&s, &n)?;
|
|
match c.rotate {
|
|
Some(t) => loop {
|
|
println!(
|
|
"queue completed:\n\tcreated: {}\n\tupdated: {}\n\tdeleted:\n\t\tfiles: {}\n\t\tdirectories: {}\n\tignored: {}\n\ttotal: {}\nawait {t} seconds to rotate...",
|
|
r.created, r.updated, r.deleted.files, r.deleted.directories, r.ignored, r.total
|
|
);
|
|
std::thread::sleep(std::time::Duration::from_secs(t));
|
|
r = sync(&s, &n)?;
|
|
},
|
|
None => println!(
|
|
"export completed:\n\tcreated: {}\n\tupdated: {}\n\tdeleted:\n\t\tfiles: {}\n\t\tdirectories: {}\n\tignored: {}\n\ttotal: {}",
|
|
r.created, r.updated, r.deleted.files, r.deleted.directories, r.ignored, r.total
|
|
),
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn sync(snac: &Snac, nex: &Nex) -> Result<Response> {
|
|
use std::collections::HashSet;
|
|
let mut r = Response::default();
|
|
for user in &snac.users {
|
|
println!("\tsync profile for `{}`...", user.name);
|
|
let mut keep = if nex.is_cleanup() {
|
|
Some(HashSet::with_capacity(100)) // @TODO estimated
|
|
} else {
|
|
None
|
|
};
|
|
for post in user.public()? {
|
|
r.total += 1;
|
|
// make sure post entry has expected content type
|
|
if !post.is_note() {
|
|
todo!()
|
|
}
|
|
// skip non authorized content
|
|
if let Some(content) = post.source_content {
|
|
println!("\t\tsync post `{}`...", post.id);
|
|
let response = nex.sync(
|
|
&user.name,
|
|
content,
|
|
post.url,
|
|
post.attachment.map(|a| {
|
|
use nex::source::Source;
|
|
let mut attachments = Vec::with_capacity(a.len());
|
|
for attachment in a {
|
|
attachments.push((
|
|
attachment.name,
|
|
attachment.media_type,
|
|
if nex.is_attachments_disabled() {
|
|
Source::Url(attachment.url)
|
|
} else {
|
|
Source::File(
|
|
user.file(attachment.url.split('/').next_back().unwrap())
|
|
.unwrap(),
|
|
)
|
|
},
|
|
))
|
|
}
|
|
attachments
|
|
}),
|
|
post.tag.map(|t| {
|
|
let mut tags = Vec::with_capacity(t.len());
|
|
for tag in t {
|
|
tags.push(tag.name)
|
|
}
|
|
tags
|
|
}),
|
|
(post.published, post.updated),
|
|
)?;
|
|
use nex::response::change::Change;
|
|
match response.change {
|
|
Change::Created => {
|
|
r.created += 1;
|
|
println!("\t\t\tcreate new post file.")
|
|
}
|
|
Change::Ignored => {
|
|
r.ignored += 1;
|
|
println!("\t\t\tpost file is up to date.")
|
|
}
|
|
Change::Updated => {
|
|
r.updated += 1;
|
|
println!("\t\t\tpost file update with new content.")
|
|
}
|
|
}
|
|
if let Some(ref mut k) = keep
|
|
&& let Some(r) = response.keep
|
|
{
|
|
for i in r {
|
|
k.insert(i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// cleanup removed post entries
|
|
if let Some(k) = keep {
|
|
let d = nex.clean(&user.name, k)?;
|
|
r.deleted.directories += d.directories;
|
|
r.deleted.files += d.files;
|
|
}
|
|
}
|
|
Ok(r)
|
|
}
|