howto assets

This commit is contained in:
lovebird 2025-03-23 11:36:45 +01:00
parent 3c98cdebb9
commit 511f9c9add
5 changed files with 65 additions and 5 deletions

View File

@ -23,7 +23,7 @@
"format": "unix-time"
}
],
"default": "2025-03-23T09:17:59.161Z"
"default": "2025-03-23T10:33:15.959Z"
},
"description": {
"type": "string",

File diff suppressed because one or more lines are too long

View File

@ -1,7 +1,6 @@
import { sync as read } from "@polymech/fs/read"
import { sync as exists } from "@polymech/fs/exists"
import { run, OptionsSchema, IKBotTask } from "@polymech/kbot-d";
import { createMarkdownComponent } from "@/base/index.js";
import { filters } from "@/model/howto.js";
export interface Props extends IKBotTask {

View File

@ -42,6 +42,7 @@ const content = async (str: string) => {
);
return ret;
};
const component = async (str: string) =>
await createMarkdownComponent(await content(str));

View File

@ -1,7 +1,10 @@
import * as path from 'path'
import { findUp } from 'find-up'
import { execFileSync, execFile } from "child_process";
import { sync as read } from '@polymech/fs/read'
import { sync as exists } from '@polymech/fs/exists'
import { sync as mkdir } from '@polymech/fs/dir'
import { sync as rm } from '@polymech/fs/remove'
import type { Loader, LoaderContext } from 'astro/loaders'
import { sanitizeFilename } from "@polymech/fs/utils"
@ -32,7 +35,8 @@ export const ITEM_TYPE = 'howto'
//export const load = () => get(`${HOWTO_ROOT()}/${HOWTO_GLOB}`, HOWTO_ROOT(), ITEM_TYPE)
export const item_path = (item: any) => `${HOWTO_ROOT()}/${item.data.slug}`
const blacklist = ['precious-plastic', 'fair-enough', 'mad-plastic-labs', 'the-flipflopi', 'easymoulds', 'plasticpreneur', 'sustainable-design-studio'];
const blacklist = [];
const blacklist_mafia = ['precious-plastic', 'fair-enough', 'mad-plastic-labs', 'the-flipflopi', 'easymoulds', 'plasticpreneur', 'sustainable-design-studio'];
const download = async (url, outputPath) => {
const stream = createWriteStream(outputPath);
@ -42,6 +46,7 @@ const download = async (url, outputPath) => {
stream.on('error', reject);
});
}
export const asset_local_abs = async (item: IHowto, asset: Image) => {
const sanitizedFilename = sanitizeFilename(asset.name)
const asset_path = path.join(HOWTO_ROOT(), item.slug, sanitizedFilename)
@ -50,6 +55,60 @@ export const asset_local_abs = async (item: IHowto, asset: Image) => {
}
return false
}
export const downloadFiles = async (dst: string, howto: IHowto) => {
const asset_root = path.join(HOWTO_ROOT(), howto.slug)
return await pMap(howto.files, async (i) => {
const sanitizedFilename = sanitizeFilename(i.name).toLowerCase()
const asset_path = path.join(HOWTO_ROOT(), howto.slug, sanitizedFilename)
if (!exists(asset_path)) {
try {
await download(i.downloadUrl, asset_path)
} catch (e) {
console.error('error download step file', e);
}
} else {
const parts = path.parse(asset_path);
const zipout = path.join(asset_root, 'files')
if (parts.ext === '.rar' || parts.ext === '.zip') {
console.info(`Extracting RAR file ${i.name} to ${zipout}`);
try {
if (!exists(asset_path)) {
console.error(`File does not exist: ${asset_path}`);
return;
}
if (exists(zipout)) {
//console.info(`Removing existing directory: ${zipout}`);
// rm(zipout);
console.info(`already extracted: ${zipout}`)
return
}
return new Promise<boolean>((resolve, reject) => {
const timeout = setTimeout(() => {
child.kill()
console.error("Extraction timed out after 15 seconds")
resolve(false);
}, 15000);
const child = execFile("7z", ["e", "" + asset_path, "-o" + zipout], (err, stdout) => {
clearTimeout(timeout)
if (err) {
console.error(err.message);
return resolve(false)
}
console.info(`Extracted rar to ${zipout}`)
return resolve(true)
});
});
} catch (e) {
console.error("Error during RAR extraction", e);
}
}
}
}, { concurrency: 1 })
}
export const asset_local_rel = async (item: IHowto, asset: Image) => {
const sanitizedFilename = sanitizeFilename(asset.name).toLowerCase()
const asset_path = path.join(HOWTO_ROOT(), item.slug, sanitizedFilename)
@ -68,7 +127,6 @@ export const howtos = async () => {
let howtos = data.v3_howtos as any[]
howtos = howtos.filter((h) => h.moderation == 'accepted');
const tags = data.v3_tags;
howtos.forEach((howto: IHowto) => {
const howtoTags: any = [];
for (const ht in howto.tags) {
@ -126,6 +184,8 @@ const onItem = async (store: any, ctx: LoaderContext) => {
item.steps.forEach((step) => {
step.images = step.images.filter((image) => asset_local_abs(item, image))
})
item.files = await downloadFiles(item.slug, item)
return item
}