kodilist
Version:
CLI tool for generating Kodi playlists based on filename-embedded tags.
193 lines (190 loc) • 6.52 kB
text/typescript
import chalk from "chalk";
import recursive from "recursive-readdir";
import fs from "fs";
import {
ConfigFile,
writePlaylistsAlphabet,
writePlaylistsNew,
writePlaylistsSearchTerms,
simplifyName
} from ".";
/**
* An OperationSet contains a function for each action the user can take,
* nested nicely to represent possible paths. The first term passed on the
* command line can be any of the top-level values; the second term passed can
* be any values nested beneath that.
*/
export interface OperationSet {
[key: string]: any;
generate: () => void;
list: {
people: () => void;
directories: () => void;
tags: () => void;
sources: () => void;
ignores: () => void;
};
delete: {
person: () => void;
ignore: () => void;
directory: () => void;
tag: () => void;
source: () => void;
};
ignore: () => void;
add: {
person: () => void;
tag: () => void;
source: () => void;
directory: () => void;
};
}
/**
* Produces an OperationSet object that can be used to easily match the command
* line input to the desired function. The first term passed to kodilist selects
* a top-level key in the OperationSet. If the first term matched a function,
* all further terms become its arguments; if the first term matched an object,
* the second term selects a function and terms 3+ become its arguments.
*
* For example, `$ kodilist add source bbc.co.uk` matches
* `['add']['source']['bbc.co.uk']()`.
*
* Arguments do not need to be directly passed to the matched function; the
* full string is passed in when `Operations()` is invoked and each function
* selects the portion it needs.
*/
export default function Operations(
config: ConfigFile,
paramSet: string[]
): OperationSet {
const param = paramSet
.slice(2)
.join(" ")
.toLowerCase();
return {
generate: async function() {
const files: any[] = [];
for (let dirName of config.directories) {
const currentDirFiles = await recursive(dirName, config.ignoreList);
currentDirFiles.forEach(filename =>
files.push({
filename,
simpleName: simplifyName(filename),
mtime: fs.statSync(filename).mtimeMs
})
);
}
files.sort((a, b) => (a.simpleName < b.simpleName ? -1 : 1));
writePlaylistsSearchTerms(config, files);
writePlaylistsNew(config, files);
writePlaylistsAlphabet(config, files);
},
list: {
people: () => config.searchTerms.people.forEach(s => console.log(s)),
directories: () => config.directories.forEach(s => console.log(s)),
tags: () => config.searchTerms.tags.forEach(s => console.log(s)),
sources: () => config.searchTerms.sources.forEach(s => console.log(s)),
ignores: () => config.ignoreList.forEach(s => console.log(s))
},
delete: {
person: function() {
const index = config.searchTerms.people.indexOf(param);
if (index === -1) {
console.log(`${chalk.red(param)} wasn't in list of people`);
return;
}
config.searchTerms.people.splice(index, 1);
config.save();
console.log(`Stopped tracking ${chalk.green(param)}`);
},
directory: function() {
const index = config.directories.indexOf(param);
if (index === -1) {
console.log(`${chalk.red(param)} wasn't in list of directories`);
return;
}
config.directories.splice(index, 1);
config.save();
console.log(`Stopped tracking ${chalk.green(param)}`);
},
tag: function() {
const index = config.searchTerms.tags.indexOf(param);
if (index === -1) {
console.log(`${chalk.red(param)} wasn't in list of tags`);
return;
}
config.searchTerms.tags.splice(index, 1);
config.save();
console.log(`Stopped tracking ${chalk.green(param)}`);
},
source: function() {
const index = config.searchTerms.sources.indexOf(param);
if (index === -1) {
console.log(`${chalk.red(param)} wasn't in list of sources`);
return;
}
config.searchTerms.sources.splice(index, 1);
config.save();
console.log(`Stopped tracking ${chalk.green(param)}`);
},
ignore: function() {
const index = config.ignoreList.indexOf(param);
if (index === -1) {
console.log(`${chalk.red(param)} wasn't on ignore list`);
return;
}
config.ignoreList.splice(index, 1);
config.save();
console.log(`Stopped ignoring ${chalk.green(param)}`);
}
},
ignore: function() {
const toIgnore = paramSet.slice(1).join(" ");
if (config.ignoreList.includes(toIgnore)) {
console.log(`Already ignoring ${chalk.blue(toIgnore)}`);
} else {
config.ignoreList.push(toIgnore);
console.log(`Now ignoring ${chalk.green(toIgnore)}`);
}
config.save();
},
add: {
person: function(): void {
if (config.searchTerms.people.includes(param)) {
console.log("Already tracking", chalk.blue(param));
} else {
config.searchTerms.people.push(param);
config.save();
console.log("Now tracking", chalk.blue(param));
}
},
tag: function(): void {
if (config.searchTerms.tags.includes(param)) {
console.log("Already tracking", chalk.blue(param));
} else {
config.searchTerms.tags.push(param);
config.save();
console.log("Now tracking", chalk.blue(param));
}
},
source: function(): void {
if (config.searchTerms.sources.includes(param)) {
console.log("Already tracking", chalk.blue(param));
} else {
config.searchTerms.sources.push(param);
config.save();
console.log("Now tracking", chalk.blue(param));
}
},
directory: function(): void {
if (config.directories.includes(paramSet[2])) {
console.log("Already tracking", chalk.blue(paramSet[2]));
} else {
config.directories.push(paramSet[2]);
config.save();
console.log("Now tracking", chalk.blue(paramSet[2]));
}
}
}
};
}