import fs from 'fs'; import path from 'path'; import FormData from 'form-data'; import dotenv from 'dotenv'; dotenv.config(); const instance = process.env.NEXTCLOUD_INSTANCE; const username = process.env.NEXTCLOUD_LOGIN; const appPassword = process.env.NEXTCLOUD_PASSWORD; const __dirname = import.meta.dirname; const authHeader = "Basic " + Buffer.from(`${username}:${appPassword}`).toString("base64"); function dir_project(after) { return path.join(__dirname, after) } function readDir(path, options) { return new Promise((res, rej) => { fs.readdir(path, options, (err, files) => { if (err) rej(err) else res(files) }); }) } function readFile(path, options) { return new Promise((res, rej) => { fs.readFile(path, options, (err, data) => { if (err) rej(err) else res(data) }); }) } function writeFile(path, data, options) { return new Promise((res, rej) => { fs.writeFile(path, data, options, (err, data) => { if (err) rej(err) else res(data) }); }) } function randomItem(array) { return array[Math.floor((Math.random() * array.length))]; } async function updateTheming(object) { let kvPairs = Object.entries(object) for (const [setting, value] of kvPairs) { await fetch(`https://${instance}/apps/theming/ajax/updateStylesheet`, { method: "POST", headers: { "Accept": "application/json", "Content-Type": "application/json", "Authorization": authHeader, "OCS-APIRequest": "true" }, body: JSON.stringify({ setting, value }) }); } } async function uploadImage({ image, filename, contentType }) { const imageBuffer = await readFile(dir_project(image)) const form = new FormData(); form.append('key', 'background'); form.append('image', imageBuffer, { filename, contentType }); const response = await fetch(`https://${instance}/apps/theming/ajax/uploadImage`, { method: "POST", headers: { "Accept": "application/json", "Authorization": authHeader, "OCS-APIRequest": "true", ...form.getHeaders() }, body: form.getBuffer() }); return await response.text() } function convertTheme(theme = "") { let themeData = theme.split("\n"); return { theme: { name: themeData[0], slogan: themeData[1], primary_color: themeData[5] }, background: { image: themeData[2], filename: themeData[3], contentType: themeData[4], } } } async function getTodaysTheme() { const directory = await readDir(dir_project("/themes/")); const lastTheme = await readFile(dir_project("last_theme.txt"), { encoding: "utf-8" }); let themeFileName = lastTheme if (process.argv[2]) { themeFileName = process.argv[2] } else { let i = 50 while (themeFileName == lastTheme) { themeFileName = randomItem(directory); if (i < 0) break i-- } } await writeFile(dir_project("last_theme.txt"), themeFileName, { encoding: "utf-8" }) const themeFile = await readFile(dir_project("/themes/" + themeFileName), { encoding: "utf-8" }); const parsedTheme = convertTheme(themeFile); return parsedTheme } async function updateNextcloud() { const todaysTheme = await getTodaysTheme(); await updateTheming(todaysTheme.theme); await uploadImage(todaysTheme.background); } updateNextcloud()