Newer
Older
use crate::{app_state::AppState, model::Article};
use chrono::{Datelike, FixedOffset, TimeZone, Utc};
use sitemap::{
reader::{SiteMapEntity, SiteMapReader},
structs::UrlEntry,
writer::SiteMapWriter,
};
use std::{
fs::{create_dir, create_dir_all, remove_dir_all, remove_file, rename, File},
io::Write,
path::PathBuf,
};
enum UpdateSitemapMode {
CreateUrl,
DeleteUrl,
}
pub fn create_static_view(app_state: &AppState, article: &Article) -> Result<(), String> {
let view_path = app_state
.env
.public_dir
.join(&article.category)
.join("view");
if !view_path.exists() {
if let Err(e) = create_dir(&view_path) {
return Err(format!("Couldn't create directory {:?}: {}", view_path, e));
}
}
let d_path = article.metadata.static_resource_path.as_ref().unwrap();
if let Err(e) = create_dir_all(&d_path) {
return Err(format!("Error creating directory {:?} : {}", d_path, e));
}
let art_img_def = String::new();
let mut art_image_uri = article
.images
.iter()
.next()
.unwrap_or(&art_img_def)
.to_owned();
if !art_image_uri.is_empty() {
art_image_uri = format!("/assets/images/{}", art_image_uri);
}
let art_json = serde_json::to_string(&article).unwrap();
let (locale, title, subtitle, description) = {
(
&article.locale,
&article.title,
&article.subtitle,
&article.metadata.description,
)
};
<head>
<meta charset='UTF-8'>
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<meta name='author' content='Kuadrado Software' />
<meta name='image' content='{art_image_uri}'/>
<meta name='description' content='{description}'>
<link href='/style/style.css' rel='stylesheet' />
</head>
<body>
<main data='{art_json}'></main>
<h1 style='visibility:hidden;'>{title}</h1>
<h2 style='visibility:hidden;'>{subtitle}</h2>
<script type='text/javascript' src='/article-view.js'></script>
let f_path = d_path.join("index.html");
match File::create(&f_path) {
Ok(mut f) => {
if let Err(e) = f.write_all(html.as_bytes()) {
return Err(format!("Error writing to {:?} : {}", f_path, e));
}
if let Err(e) = update_sitemap(
app_state,
&article.metadata.view_uri,
UpdateSitemapMode::CreateUrl,
) {
return Err(e);
};
Ok(())
}
Err(e) => Err(format!("Error creating {:?} : {}", f_path, e)),
}
}
pub fn delete_static_view(
app_state: &AppState,
path: &Option<PathBuf>,
uri: &Option<String>,
) -> Result<(), String> {
if let Some(path) = path {
if path.exists() {
if let Err(e) = remove_dir_all(path) {
return Err(format!("Error deleting static view at {:?} : {}", path, e));
if let Err(e) = update_sitemap(app_state, uri, UpdateSitemapMode::DeleteUrl) {
return Err(e);
};
Ok(())
}
fn init_sitemap(sitemap_path: &PathBuf) -> Result<(), String> {
File::create(sitemap_path).expect("Couldn't create sitemap");
let sm = File::open(sitemap_path).unwrap();
let writer = SiteMapWriter::new(&sm);
match writer.start_urlset() {
Ok(url_w) => {
if let Err(e) = url_w.end() {
return Err(format!("Couldn't write new sitemap closing tags. {}", e));
}
Ok(())
}
Err(e) => Err(format!("Couldn't create new sitemap urlset. {}", e)),
}
}
fn update_sitemap(
app_state: &AppState,
uri: &Option<String>,
mode: UpdateSitemapMode,
) -> Result<(), String> {
if uri.is_none() {
return Ok(());
}
let sitemap_name = match std::env::var("CONTEXT") {
Ok(value) => {
if value.eq("testing") {
String::from("test_sitemap.xml")
} else {
};
let standard_dir_pth = app_state.env.public_dir.join("standard");
let uri = uri.as_ref().unwrap().to_owned();
let sitemap_path = standard_dir_pth.join(&sitemap_name);
if !sitemap_path.exists() {
if let Err(e) = init_sitemap(&sitemap_path) {
return Err(e);
}
}
let sitemap = File::open(&sitemap_path).expect("Couldn't open file sitemap.xml");
let mut urls = Vec::new();
for entity in SiteMapReader::new(sitemap) {
if let SiteMapEntity::Url(url_entry) = entity {
urls.push(url_entry.loc.get_url().unwrap().to_string());
}
}
let updated_sitemap = File::create(standard_dir_pth.join("tmp_sitemap.xml"))
.expect("Couldn't create temporary sitemap");
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
let mut url_writer = writer
.start_urlset()
.expect("Unable to write sitemap urlset");
match mode {
UpdateSitemapMode::CreateUrl => {
urls.push(uri);
}
UpdateSitemapMode::DeleteUrl => {
let mut updated_urls = Vec::new();
for u in urls {
if !u.eq(&uri) {
updated_urls.push(u);
}
}
urls = updated_urls;
}
}
let now = Utc::today().naive_utc();
for u in urls {
url_writer
.url(
UrlEntry::builder()
.loc(u)
.lastmod(
FixedOffset::west(0)
.ymd(now.year(), now.month(), now.day())
.and_hms(0, 0, 0),
)
.build()
.unwrap(),
)
.expect("Unable to write url");
}
url_writer
.end()
.expect("Unable to write sitemap closing tags");
if let Err(e) = remove_file(standard_dir_pth.join(&sitemap_name)) {
return Err(format!("Error updating sitemap.xml {}", e));
};
if let Err(e) = rename(
standard_dir_pth.join("tmp_sitemap.xml"),
standard_dir_pth.join(&sitemap_name),
) {
return Err(format!("Error updating sitemap.xml {}", e));
};