feat(cli): add support for running import and API jobs

This commit is contained in:
Cory Dransfeldt 2025-06-08 15:47:09 -07:00
parent 75df36acc3
commit 8a12e83b13
No known key found for this signature in database
8 changed files with 272 additions and 65 deletions

159
cli/lib/jobs.js Normal file
View file

@ -0,0 +1,159 @@
import inquirer from 'inquirer';
import path from 'path';
import { fileURLToPath } from 'url';
import dotenv from 'dotenv';
import { loadConfig } from './config.js';
const config = await loadConfig();
const __dirname = path.dirname(fileURLToPath(import.meta.url));
dotenv.config({ path: path.resolve(__dirname, '..', '..', '.env') });
const JOBS = [{
name: '🎧 Update total plays',
type: 'curl',
urlEnvVar: 'TOTAL_PLAYS_WEBHOOK',
tokenEnvVar: 'DIRECTUS_API_TOKEN',
method: 'GET'
},
{
name: '🛠 Rebuild site',
type: 'curl',
urlEnvVar: 'SITE_REBUILD_WEBHOOK',
tokenEnvVar: 'DIRECTUS_API_TOKEN',
method: 'GET'
},
{
name: '💿 Scrobble listens from Navidrome',
type: 'curl',
apiUrl: `${config.globals.url}/api/scrobble.php`,
tokenEnvVar: 'NAVIDROME_SCROBBLE_TOKEN',
method: 'POST'
},
{
name: '🐘 Send posts to Mastodon',
type: 'curl',
apiUrl: `${config.globals.url}/api/mastodon.php`,
tokenEnvVar: 'MASTODON_SYNDICATION_TOKEN',
method: 'POST'
},
{
name: '🎤 Import artist from Navidrome',
type: 'curl',
apiUrl: `${config.globals.url}/api/artist-import.php`,
tokenEnvVar: 'ARTIST_IMPORT_TOKEN',
method: 'POST',
paramsPrompt: [{
type: 'input',
name: 'artistId',
message: 'Enter the Navidrome artist ID:',
validate: input => input ? true : 'Artist ID is required'
}]
},
{
name: '📖 Import book',
type: 'curl',
apiUrl: `${config.globals.url}/api/book-import.php`,
tokenEnvVar: 'BOOK_IMPORT_TOKEN',
method: 'POST',
paramsPrompt: [{
type: 'input',
name: 'isbn',
message: 'Enter the book\'s ISBN:',
validate: input => input ? true : 'ISBN is required'
}]
},
{
name: '📽 Import movie or show',
type: 'curl',
apiUrl: `${config.globals.url}/api/watching-import.php`,
tokenEnvVar: 'WATCHING_IMPORT_TOKEN',
method: 'POST',
tokenIncludeInParams: true,
paramsPrompt: [{
type: 'input',
name: 'tmdb_id',
message: 'Enter the TMDB ID:',
validate: (input) =>
/^\d+$/.test(input) ? true : 'Please enter a valid TMDB ID'
},
{
type: 'list',
name: 'media_type',
message: 'Is this a movie or a show?',
choices: ['movie', 'show']
}]
},
{
name: '📺 Import upcoming TV seasons',
type: 'curl',
apiUrl: `${config.globals.url}/api/seasons-import.php`,
tokenEnvVar: 'SEASONS_IMPORT_TOKEN',
method: 'POST'
}];
export const runJobsMenu = async () => {
const { selectedJob } = await inquirer.prompt([{
type: 'list',
name: 'selectedJob',
message: 'Select a job to run:',
choices: JOBS.map((job, index) => ({
name: job.name,
value: index
}))
}]);
const job = JOBS[selectedJob];
if (job.type === 'curl') {
let params = null;
if (job.paramsPrompt) {
const answers = await inquirer.prompt(job.paramsPrompt);
const token = process.env[job.tokenEnvVar];
params = { ...answers, ...(token ? { token } : {}) };
}
await runCurl({ ...job, params });
} else {
console.warn(`⚠️ Unsupported job type: ${job.type}`);
}
};
const runCurl = async ({
urlEnvVar,
apiUrl = "",
tokenEnvVar,
method = 'POST',
name,
params = null
}) => {
const url = process.env[urlEnvVar] || apiUrl;
const token = tokenEnvVar ? process.env[tokenEnvVar] : null;
if (!url) {
console.error(`❌ Missing URL for job. Check ${urlEnvVar} in your .env`);
return;
}
try {
const res = await fetch(url, {
method,
headers: {
'Content-Type': 'application/json',
...(token && { Authorization: `Bearer ${token}` })
},
...(params && { body: JSON.stringify(params) })
});
if (!res.ok) {
const errText = await res.text();
throw new Error(errText);
}
console.log(`${name} ran successfully.`);
} catch (err) {
console.error(`❌ Request failed: ${err.message}`);
}
};