mirror of
https://codeberg.org/postscriptum/snac2nex.git
synced 2026-03-31 21:25:28 +00:00
implement deleted posts cleanup, extend sync response features
This commit is contained in:
parent
e85a4bb7d0
commit
499a78004a
7 changed files with 160 additions and 36 deletions
102
src/nex.rs
102
src/nex.rs
|
|
@ -1,14 +1,18 @@
|
|||
mod attachment;
|
||||
pub mod response;
|
||||
pub mod source;
|
||||
|
||||
use anyhow::{Result, bail};
|
||||
use attachment::Attachment;
|
||||
use chrono::{DateTime, Utc};
|
||||
use std::{collections::HashMap, fs, path::PathBuf, str::FromStr};
|
||||
|
||||
pub enum Source {
|
||||
Url(String),
|
||||
File(PathBuf),
|
||||
}
|
||||
use response::{Clean, Sync, change::Change};
|
||||
use source::Source;
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
fs,
|
||||
path::PathBuf,
|
||||
str::FromStr,
|
||||
};
|
||||
|
||||
pub struct Nex {
|
||||
attachment: Attachment,
|
||||
|
|
@ -66,19 +70,38 @@ impl Nex {
|
|||
attachments: Option<Vec<(String, String, Source)>>,
|
||||
tags: Option<Vec<String>>,
|
||||
(published, updated): (DateTime<Utc>, Option<DateTime<Utc>>),
|
||||
) -> Result<usize> {
|
||||
) -> Result<Sync> {
|
||||
// collect existing entries to ignore on cleanup
|
||||
let mut i = Vec::with_capacity(10); // includes est. attachments len
|
||||
|
||||
// prepare destination
|
||||
let mut p = PathBuf::from(self.users.get(name).unwrap());
|
||||
let root = PathBuf::from(self.users.get(name).unwrap());
|
||||
let mut p = PathBuf::from(&root);
|
||||
i.push(root);
|
||||
|
||||
p.push(published.format("%Y").to_string());
|
||||
i.push(p.clone());
|
||||
|
||||
p.push(published.format("%m").to_string());
|
||||
i.push(p.clone());
|
||||
|
||||
p.push(published.format("%d").to_string());
|
||||
i.push(p.clone());
|
||||
|
||||
fs::create_dir_all(&p)?;
|
||||
|
||||
// init shared post ID once
|
||||
let id = published.format(&self.filename).to_string();
|
||||
|
||||
// init post filepath
|
||||
let mut f = PathBuf::from(&p);
|
||||
f.push(&id);
|
||||
|
||||
// init storage directory for the post state file and attachments
|
||||
// * by the current implementation, its name starts with dot
|
||||
// as usually hidden but accessible (in servers like Nexy)
|
||||
let mut d = PathBuf::from(&p);
|
||||
d.push(format!(".{}", published.format(&self.filename)));
|
||||
d.push(format!(".{id}"));
|
||||
fs::create_dir_all(&d)?;
|
||||
|
||||
// create system meta file to track post time updated
|
||||
|
|
@ -89,10 +112,13 @@ impl Nex {
|
|||
{
|
||||
fs::remove_dir_all(&d)?;
|
||||
fs::create_dir_all(&d)?;
|
||||
fs::write(s, updated.unwrap_or(published).to_string())?
|
||||
fs::write(&s, updated.unwrap_or(published).to_string())?
|
||||
} else {
|
||||
println!("\t\t\tpost is up to date.");
|
||||
return Ok(0);
|
||||
i.extend([d, f, p, s]); // move all paths processed to cleanup ignore
|
||||
return Ok(Sync {
|
||||
change: Change::Ignored,
|
||||
keep: i,
|
||||
});
|
||||
}
|
||||
|
||||
// format content pattern
|
||||
|
|
@ -112,7 +138,7 @@ impl Nex {
|
|||
.map(|a| {
|
||||
let mut b = Vec::with_capacity(a.len());
|
||||
b.push("\n".to_string());
|
||||
for (i, (name, media_type, source)) in a.into_iter().enumerate() {
|
||||
for (n, (name, media_type, source)) in a.into_iter().enumerate() {
|
||||
let mut t = Vec::with_capacity(3);
|
||||
t.push(format!(
|
||||
"=> {}",
|
||||
|
|
@ -122,7 +148,7 @@ impl Nex {
|
|||
let mut to = PathBuf::from(&d);
|
||||
let f = format!(
|
||||
"{}{}",
|
||||
i + 1,
|
||||
n + 1,
|
||||
from.extension()
|
||||
.map(|e| format!(".{}", e.to_string_lossy()))
|
||||
.unwrap_or_default(),
|
||||
|
|
@ -131,6 +157,7 @@ impl Nex {
|
|||
if !to.exists() {
|
||||
self.attachment.sync(&from, &to).unwrap()
|
||||
}
|
||||
i.push(to);
|
||||
format!("{}/{f}", d.file_name().unwrap().to_string_lossy())
|
||||
}
|
||||
}
|
||||
|
|
@ -161,17 +188,46 @@ impl Nex {
|
|||
.unwrap_or_default(),
|
||||
);
|
||||
|
||||
// save post file
|
||||
p.push(published.format(&self.filename).to_string());
|
||||
let f = p.to_string_lossy();
|
||||
if fs::exists(&p)? {
|
||||
println!("\t\t\tpost file `{f}` update with new content.")
|
||||
// save post file, set its change status
|
||||
let change = if fs::exists(&f)? {
|
||||
Change::Updated
|
||||
} else {
|
||||
println!("\t\t\tcreate new post file `{f}`.")
|
||||
}
|
||||
fs::write(&p, c)?;
|
||||
Change::Created
|
||||
};
|
||||
fs::write(&f, c)?;
|
||||
|
||||
Ok(1)
|
||||
// move all paths processed to cleanup ignore
|
||||
i.extend([d, f, p, s]);
|
||||
|
||||
Ok(Sync { change, keep: i })
|
||||
}
|
||||
|
||||
pub fn clean(&self, name: &str, ignore: HashSet<PathBuf>) -> Result<Clean> {
|
||||
let mut r = Clean::default();
|
||||
for entry in
|
||||
walkdir::WalkDir::new(PathBuf::from(self.users.get(name).unwrap())).follow_links(false)
|
||||
{
|
||||
let e = entry?;
|
||||
let p = e.path();
|
||||
let s = p.to_string_lossy();
|
||||
println!("check `{s}`...");
|
||||
if ignore.contains(p) {
|
||||
continue;
|
||||
}
|
||||
let m = fs::metadata(p)?;
|
||||
if m.is_file() {
|
||||
fs::remove_file(p)?;
|
||||
r.files += 1;
|
||||
println!("\t\t\tdelete file `{s}`");
|
||||
} else if m.is_dir() {
|
||||
fs::remove_dir_all(p)?;
|
||||
r.directories += 1;
|
||||
println!("\t\t\tdelete directory `{s}`");
|
||||
} else {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
Ok(r)
|
||||
}
|
||||
|
||||
pub fn is_attachments_disabled(&self) -> bool {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue