#!/usr/bin/env -S node --experimental-fetch const fs = require('fs'); const JSDOM = require('jsdom').JSDOM; const ConfigParser = require("./Lib/config-ini-parser").ConfigIniParser; const BlogURL = 'https://listed.to/@u8'; // Full base URL of the Listed blog (any server) const SiteName = 'sitoctt'; //const DefaultMode = 'Include' // 'Include' or 'Exclude' | Not implemented const PostsFileDate = true; // Append dates (YYYY-MM-DD) to posts file names const Replacements = { // Format: { ReplaceWithString: [ToFindString] } "## [:HNotesRefsHTML:]": "

🏷️ Note e Riferimenti

", "", "## ": "

", "### ": "

", "#### ": "

", "##### ": "

", "###### ": "
", "": ["
", "", "", "", "", ""], // staticoso TODO: Fix the handling of headings to remove this crap above... }; const MetadataBlockSelect = '.MetadataBlock, .MetadataBlock + :Where(Div, Pre, Code)'; const ExtractCodeBlockSelect = '.ExtractCodeBlock, .ExtractCodeBlock + :Where(Div, Pre, Code)'; const TryReadFileSync = Path => { if (fs.existsSync(Path)) { return fs.readFileSync(Path, 'utf8'); }; }; const TryMkdirSync = Path => { if (!fs.existsSync(Path)) { return fs.mkdirSync(Path, {recursive: true}); }; }; const GetPath = URL => { if (URL.startsWith('http://') || URL.startsWith('https://')) { URL = URL.split('/').slice(3).join('/'); }; return URL; }; const GetFragHTML = Frag => { let Dom = new JSDOM(''); Dom.window.document.body.appendChild(Frag); return Dom.window.document.body.innerHTML; }; const CheckDoDownsync = File => { let DoDownsync = true; const TryFile = TryReadFileSync(File); if (TryFile) { const Lines = TryFile.trim().toLowerCase().split('\n'); for (let i=0; i {return i != ''}); if (Tokens[1] == '%' && Tokens[2] == 'downsync' && [':', '='].includes(Tokens[3]) && ['false', 'disabled', 'off', 'no'].includes(Tokens[4])) { DoDownsync = false; break; }; }; }; }; return DoDownsync; }; const GetLinkElem = Dom => { let Elem; Elem = Dom.querySelector(`.Mirror-${SiteName}`); if (!Elem) { Elem = Dom.querySelector(`.Mirror-${SiteName}-Include`); }; return Elem; }; const ParseMeta = Raw => { let Mid = {"Meta": "", "Macros": ""}; let Data = {"Meta": {}, "Macros": {}}; const Lines = Raw.trim().split('\n'); for (let i=0; i { let Str = ''; const Types = ['Meta', 'Macros']; for (let i=0; i { let LinkElem, ContentDom; let Post = {"Meta": {}, "Macros": {}}; Post.Meta.Title = PostSrc.title; Post.Meta.CreatedOn = PostSrc.created_at.split('T')[0]; Post.Content = PostSrc.rendered_text; console.log(`[I] => [${Post.Meta.CreatedOn}] ${Post.Meta.Title}`); ContentDom = JSDOM.fragment(Post.Content); LinkElem = GetLinkElem(ContentDom); if (!LinkElem) { // Post content has no mirror-flagging element, skip it // TODO: Exclusion mode instead of inclusion? Aka automatically handle posts without the element // TODO: Check flagging via MetadataBlock? console.log(`[I] : No mirror flag in source body; Skipping!`); return; }; const LinkPath = GetPath(JSDOM.fragment(LinkElem.outerHTML).querySelector('[href]').href); /* // Get post categories Post.Categories = ''; const Classes = LinkElem.classList; for (let i=0; i { console.log('[I] Downloading...'); fetch(`${BlogURL}/all`).then(Response => Response.text()).then(Data => { console.log('[I] Parsing...'); const Elem = JSDOM.fragment(Data).querySelector('script[data-component-name="AuthorAll"]'); const Posts = JSON.parse(Elem.childNodes[0].data).posts; for (let i=0; i