wakitsu
Version:
Hobby project for managing anime watch list on Kitsu through CLI
127 lines • 4.17 kB
JavaScript
import { join, basename } from 'path';
export function parseWithZod(schema, data, failedSchemaName) {
const zodResp = schema.safeParse(data);
if (!zodResp.success) {
const errorMsgArray = [
`;r;Failed To Parse ;by;${failedSchemaName} ;r;Schema`,
...zodResp.error.issues.map((issue) => {
return `;y;${issue.path};x;: ${issue.message == 'Required' ? 'Missing or Undefined' : issue.message}`;
}),
];
return [errorMsgArray, null];
}
return [null, zodResp.data];
}
export async function tryCatchAsync(p) {
try {
const data = await p;
return {
success: true,
data,
};
}
catch (e) {
if (e instanceof Error) {
return {
success: false,
error: e,
};
}
return {
success: false,
error: Error('unknown error', { cause: e }),
};
}
}
export function fitStringEnd(str, maxLength) {
if (str.length > maxLength) {
throw Error(`cannot fit "${str}" inside a length of ${maxLength}`);
}
return `${str}${' '.repeat(maxLength - str.length)}`;
}
export function getColoredTimeWatchedStr(seconds) {
const { hours, days, months } = getTimeUnits(seconds);
const leftOverMinutes = (hours % 1) * 60;
const coloredMinutesLeft = `;y;${leftOverMinutes.toFixed(0)} ;g;Minutes`;
const coloredHours = `;y;${Math.floor(hours)} ;g;Hours`;
const coloredDays = `;y;${hours.toFixed(1)} ;g;Days`;
const coloredMonths = `;y;${months.toFixed(1)} ;g;Months`;
const allTimeStr = months >= 1 ? coloredMonths : days >= 1 ? coloredDays : coloredHours;
return {
allTimeStr,
hoursAndMinutesLeft: `${coloredHours};g;, ${coloredMinutesLeft}`,
};
}
export function getTimeUnits(seconds) {
const minutes = seconds / 60;
const hours = minutes / 60;
const days = hours / 24;
const months = days / 30;
return {
minutes,
hours,
days,
months,
};
}
export const toReadableBytes = createReadableBytesFunc();
export function createReadableBytesFunc() {
const m = new Map();
m.set('TB', 1_099_511_627_776);
m.set('GB', 1_073_741_824);
m.set('MB', 1_048_576);
m.set('KB', 1_024);
return function toMaxReadableBytes(bytes) {
for (const [strSize, byteSize] of m) {
if (bytes >= byteSize) {
return `${(bytes / byteSize).toFixed(2)} ${strSize}`;
}
}
throw Error(`cannot determine size of "${bytes}" bytes`);
};
}
export function parseFansubFilename(name) {
const fansubRegEx = /^\[([\w|\d|\s-]+)\]\s(.+)(\sS[0-9]{1,2})?\s([0-9]{2,4}|S([0-9]{2})E([0-9]{2,4})|[0-9]{2,4}v[0-9])(\s|\.)/gi;
const parts = fansubRegEx.exec(name);
if (!parts) {
const errorMessage = name.toLowerCase().includes('(batch)') || name.toLowerCase().includes('[batch]')
? 'This is a batch file, which means the season is over.'
: 'Try to find another fansub group.';
return [{ parseError: errorMessage, fileName: name }, null];
}
return [null, serializeFansubFilename(parts)];
}
function serializeFansubFilename(filenameParts) {
const [, fansub, title, seasonP, epNumP, seasonAlt, epNumAlt] = filenameParts;
let epNum = 0;
let paddedEpNum = '';
let season = '';
if (seasonAlt) {
epNum = Number(epNumAlt);
paddedEpNum = epNumAlt;
season = seasonAlt;
}
else {
epNum = Number(epNumP);
paddedEpNum = epNumP.includes('v') ? epNumP.split('v')[0] : epNumP;
season = seasonP;
}
const filenameData = {
fansub,
title: title[title.length - 1] == '-' ? title.substring(0, title.length - 2) : title,
epNum,
paddedEpNum,
season,
};
return filenameData;
}
export function wait(delay = 500) {
return new Promise((rs) => {
setTimeout(() => {
rs('');
}, delay);
});
}
export const pathJoin = join;
export const pathBasename = basename;
//# sourceMappingURL=utils.js.map