Add prettier as linter
This commit is contained in:
commit
2eadb53b8f
|
@ -4,13 +4,14 @@ jobs:
|
|||
tests:
|
||||
strategy:
|
||||
matrix:
|
||||
node: ['16', '14', '12']
|
||||
node: ["16", "14", "12"]
|
||||
name: Run NPM Stuff
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: ${{matrix.node}}
|
||||
- run: npm install
|
||||
- run: npm test
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: ${{matrix.node}}
|
||||
- run: npm install
|
||||
- run: npm run lint
|
||||
- run: npm run test
|
||||
|
|
54
index.js
54
index.js
|
@ -1,16 +1,16 @@
|
|||
#!/usr/bin/env node
|
||||
import ytdl from 'ytdl-core';
|
||||
import getArtistTitle from 'get-artist-title'
|
||||
import {parse} from './src/parser.js'
|
||||
import {generate} from './src/cue.js'
|
||||
import minimist from 'minimist'
|
||||
import exit from 'process'
|
||||
import ytdl from "ytdl-core";
|
||||
import getArtistTitle from "get-artist-title";
|
||||
import { parse } from "./src/parser.js";
|
||||
import { generate } from "./src/cue.js";
|
||||
import minimist from "minimist";
|
||||
import exit from "process";
|
||||
|
||||
let argv = minimist(process.argv.slice(2), {
|
||||
string: 'audio-file'
|
||||
string: "audio-file",
|
||||
});
|
||||
|
||||
if (argv._.length <1 || argv.help ){
|
||||
if (argv._.length < 1 || argv.help) {
|
||||
console.log(`Usage
|
||||
$ youtube-cue [--audio-file audio.m4a] <youtube_url> [output_file]
|
||||
|
||||
|
@ -36,32 +36,38 @@ if (argv._.length <1 || argv.help ){
|
|||
$ youtube-cue --audio-file audio.m4a "https://www.youtube.com/watch?v=THzUassmQwE"
|
||||
"T A Y L O R S W I F T – Folklore [Full album].cue" saved
|
||||
$ youtube-cue "https://youtu.be/THzUassmQwE" folklore.cue
|
||||
folklore.cue saved`)
|
||||
folklore.cue saved`);
|
||||
} else {
|
||||
let url = argv._[0]
|
||||
let url = argv._[0];
|
||||
|
||||
ytdl.getInfo(url).then(info=>{
|
||||
let audioFile = argv['audio-file']? argv['audio-file'] : `${info.videoDetails.title}.m4a`
|
||||
ytdl.getInfo(url).then((info) => {
|
||||
let audioFile = argv["audio-file"]
|
||||
? argv["audio-file"]
|
||||
: `${info.videoDetails.title}.m4a`;
|
||||
|
||||
let output_file = argv._[1]? argv._[1] : `${info.videoDetails.title}.cue`
|
||||
let output_file = argv._[1] ? argv._[1] : `${info.videoDetails.title}.cue`;
|
||||
|
||||
let forceTimestamps = argv['timestamps']? argv['timestamps'] : false;
|
||||
let forceTimestamps = argv["timestamps"] ? argv["timestamps"] : false;
|
||||
|
||||
let forceDurations = argv['durations']? argv['durations'] : false;
|
||||
let forceDurations = argv["durations"] ? argv["durations"] : false;
|
||||
|
||||
if (forceTimestamps && forceDurations) {
|
||||
console.error("You can't pass both --timestamps and durations");
|
||||
exit(1)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
let res = getArtistTitle(info.videoDetails.title,{
|
||||
let res = getArtistTitle(info.videoDetails.title, {
|
||||
defaultArtist: "Unknown Artist",
|
||||
defaultTitle: info.videoDetails.title
|
||||
defaultTitle: info.videoDetails.title,
|
||||
});
|
||||
let [artist, album] = res
|
||||
artist = (info.videoDetails.media ? info.videoDetails.media.artist : artist)
|
||||
let tracks = parse(info.videoDetails.description, {artist, forceTimestamps, forceDurations})
|
||||
generate({tracks, artist, audioFile, album}, output_file)
|
||||
console.log(`"${output_file}" saved`)
|
||||
})
|
||||
let [artist, album] = res;
|
||||
artist = info.videoDetails.media ? info.videoDetails.media.artist : artist;
|
||||
let tracks = parse(info.videoDetails.description, {
|
||||
artist,
|
||||
forceTimestamps,
|
||||
forceDurations,
|
||||
});
|
||||
generate({ tracks, artist, audioFile, album }, output_file);
|
||||
console.log(`"${output_file}" saved`);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
{
|
||||
"name": "youtube-cue",
|
||||
"version": "1.0.5",
|
||||
"version": "1.0.6",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"version": "1.0.5",
|
||||
"version": "1.0.6",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"console-log-level": "^1.4.1",
|
||||
|
@ -17,7 +17,8 @@
|
|||
"youtube-cue": "index.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"mocha": "^9.0.0"
|
||||
"mocha": "^9.0.0",
|
||||
"prettier": "^2.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@ungap/promise-all-settled": {
|
||||
|
@ -796,6 +797,18 @@
|
|||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/prettier": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.2.tgz",
|
||||
"integrity": "sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"prettier": "bin-prettier.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/randombytes": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||
|
@ -1716,6 +1729,12 @@
|
|||
"integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==",
|
||||
"dev": true
|
||||
},
|
||||
"prettier": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.2.tgz",
|
||||
"integrity": "sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ==",
|
||||
"dev": true
|
||||
},
|
||||
"randombytes": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||
|
|
|
@ -4,13 +4,15 @@
|
|||
"description": "Generates Cue sheet from Youtube URL",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "mocha"
|
||||
"test": "mocha",
|
||||
"lint": "prettier --check *.js src/*.js test/*.js"
|
||||
},
|
||||
"bin": "index.js",
|
||||
"author": "Nemo <npm@captnemo.in>",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"mocha": "^9.0.0"
|
||||
"mocha": "^9.0.0",
|
||||
"prettier": "^2.3.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"console-log-level": "^1.4.1",
|
||||
|
|
13
src/cue.js
13
src/cue.js
|
@ -1,21 +1,24 @@
|
|||
import fs from 'fs';
|
||||
import fs from "fs";
|
||||
|
||||
// https://en.wikipedia.org/wiki/Cue_sheet_(computing)
|
||||
export function generate(data, outputFile) {
|
||||
try {
|
||||
fs.truncateSync(outputFile)
|
||||
fs.truncateSync(outputFile);
|
||||
} catch {}
|
||||
fs.appendFileSync(outputFile, `REM Generated using youtube-cue\n`);
|
||||
fs.appendFileSync(outputFile, `PERFORMER "${data.artist}"\n`);
|
||||
fs.appendFileSync(outputFile, `TITLE "${data.album}"\n`);
|
||||
fs.appendFileSync(outputFile, `FILE "${data.audioFile}" M4A\n`);
|
||||
for(var i in data.tracks) {
|
||||
for (var i in data.tracks) {
|
||||
let song = data.tracks[i];
|
||||
let minutes = (song.start.hh * 60) + (song.start.mm)
|
||||
let minutes = song.start.hh * 60 + song.start.mm;
|
||||
fs.appendFileSync(outputFile, ` TRACK ${song.track} AUDIO\n`);
|
||||
fs.appendFileSync(outputFile, ` TITLE "${song.title}"\n`);
|
||||
fs.appendFileSync(outputFile, ` PERFORMER "${song.artist}"\n`);
|
||||
// Cue File is always MINUTES:SECONDS:FRAME, where FRAME is 00
|
||||
fs.appendFileSync(outputFile, ` INDEX 01 ${minutes}:${song.start.ss}:00\n`);
|
||||
fs.appendFileSync(
|
||||
outputFile,
|
||||
` INDEX 01 ${minutes}:${song.start.ss}:00\n`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,8 @@
|
|||
*
|
||||
* It is suggested to check their lengths and pick one to parse as the Track Title
|
||||
*/
|
||||
const TS_REGEX = /^((?<trackl>\d{1,3})\.)? *(?<text_1>.*?) *[\(\[]?(?<start_ts>((?<start_hh>\d{1,2}):)?(?<start_mm>\d{1,2}):(?<start_ss>\d{1,2})) *-? *[\)\]]?(?<end_ts>(?<end_hh>\d{1,2}:)?(?<end_mm>\d{1,2}):(?<end_ss>\d{1,2}))? *((?<trackr>\d{1,3})\.)? *(?<text_2>.*?)$/;
|
||||
const TS_REGEX =
|
||||
/^((?<trackl>\d{1,3})\.)? *(?<text_1>.*?) *[\(\[]?(?<start_ts>((?<start_hh>\d{1,2}):)?(?<start_mm>\d{1,2}):(?<start_ss>\d{1,2})) *-? *[\)\]]?(?<end_ts>(?<end_hh>\d{1,2}:)?(?<end_mm>\d{1,2}):(?<end_ss>\d{1,2}))? *((?<trackr>\d{1,3})\.)? *(?<text_2>.*?)$/;
|
||||
import getArtistTitle from "get-artist-title";
|
||||
var _options = {};
|
||||
|
||||
|
@ -30,12 +31,12 @@ function convertTime(h, m, s) {
|
|||
}
|
||||
|
||||
// Only picks out lines which have a timestamp in them
|
||||
var filterTimestamp = function(line) {
|
||||
var filterTimestamp = function (line) {
|
||||
return TS_REGEX.test(line);
|
||||
};
|
||||
|
||||
// Parse each line as per the regex
|
||||
var firstPass = function(line) {
|
||||
var firstPass = function (line) {
|
||||
let matches = line.match(TS_REGEX);
|
||||
let track = matches.groups["trackl"]
|
||||
? +matches.groups["trackl"]
|
||||
|
@ -71,7 +72,7 @@ var firstPass = function(line) {
|
|||
};
|
||||
|
||||
// Add a calc attribute with total seconds
|
||||
var calcTimestamp = function(obj) {
|
||||
var calcTimestamp = function (obj) {
|
||||
if (obj.end) {
|
||||
obj.end.calc = convertTime(obj.end.hh, obj.end.mm, obj.end.ss);
|
||||
}
|
||||
|
@ -80,7 +81,7 @@ var calcTimestamp = function(obj) {
|
|||
};
|
||||
|
||||
// Pick the longer "text" from left or right side.
|
||||
var parseTitle = function(obj) {
|
||||
var parseTitle = function (obj) {
|
||||
obj.title =
|
||||
obj._.left_text.length > obj._.right_text.length
|
||||
? obj._.left_text
|
||||
|
@ -89,7 +90,7 @@ var parseTitle = function(obj) {
|
|||
};
|
||||
|
||||
// Parse the text as the title/artist
|
||||
var parseArtist = function(obj) {
|
||||
var parseArtist = function (obj) {
|
||||
let [artist, title] = getArtistTitle(obj.title, {
|
||||
defaultArtist: _options.artist,
|
||||
defaultTitle: obj.title,
|
||||
|
@ -100,7 +101,7 @@ var parseArtist = function(obj) {
|
|||
};
|
||||
|
||||
// If track numbers are not present, add them accordingly
|
||||
var addTrack = function(obj, index) {
|
||||
var addTrack = function (obj, index) {
|
||||
if (obj.track == null) {
|
||||
obj.track = index + 1;
|
||||
}
|
||||
|
@ -108,7 +109,7 @@ var addTrack = function(obj, index) {
|
|||
};
|
||||
|
||||
// Add "end" timestamps as next start timestamps
|
||||
var addEnd = function(obj, index, arr) {
|
||||
var addEnd = function (obj, index, arr) {
|
||||
if (!obj.end) {
|
||||
if (arr.length != index + 1) {
|
||||
let next = arr[index + 1];
|
||||
|
@ -119,7 +120,7 @@ var addEnd = function(obj, index, arr) {
|
|||
return obj;
|
||||
};
|
||||
|
||||
var timeToObject = function(obj) {
|
||||
var timeToObject = function (obj) {
|
||||
let d = new Date(obj.calc * 1000).toISOString();
|
||||
obj.hh = +d.substr(11, 2);
|
||||
obj.mm = +d.substr(14, 2);
|
||||
|
@ -131,7 +132,7 @@ var timeToObject = function(obj) {
|
|||
// Instead of timestamps, some tracklists use durations
|
||||
// If durations are provided, use them to re-calculate
|
||||
// the starting and ending timestamps
|
||||
var fixDurations = function(list) {
|
||||
var fixDurations = function (list) {
|
||||
for (let i in list) {
|
||||
if (i == 0) {
|
||||
// Set the first one to start of track.
|
||||
|
@ -167,7 +168,7 @@ export function parse(
|
|||
if (!options.forceTimestamps) {
|
||||
// If our timestamps are not in increasing order
|
||||
// Assume that we've been given a duration list instead
|
||||
if (result[0].start.calc!=0) {
|
||||
if (result[0].start.calc != 0) {
|
||||
result.forEach((current, index, list) => {
|
||||
if (index > 0) {
|
||||
let previous = list[index - 1];
|
||||
|
@ -183,9 +184,5 @@ export function parse(
|
|||
}
|
||||
}
|
||||
|
||||
return result
|
||||
.map(parseTitle)
|
||||
.map(parseArtist)
|
||||
.map(addTrack)
|
||||
.map(addEnd);
|
||||
return result.map(parseTitle).map(parseArtist).map(addTrack).map(addEnd);
|
||||
}
|
||||
|
|
|
@ -24,21 +24,21 @@ Hello World 48:20
|
|||
|
||||
const TEXT_WITH_ARTIST = "12:23 Rolling Stones - Hello World";
|
||||
|
||||
describe("Parser", function() {
|
||||
describe("Parser", function () {
|
||||
var big_result;
|
||||
before(function() {
|
||||
before(function () {
|
||||
big_result = parse(TEXT);
|
||||
});
|
||||
it("should find all timestamps", function() {
|
||||
it("should find all timestamps", function () {
|
||||
assert.equal(big_result.length, 15);
|
||||
});
|
||||
|
||||
it("should find artist names", function() {
|
||||
it("should find artist names", function () {
|
||||
let result = parse(TEXT_WITH_ARTIST);
|
||||
assert.equal(result[0].artist, "Rolling Stones");
|
||||
});
|
||||
|
||||
it("should find track numbers", function() {
|
||||
it("should find track numbers", function () {
|
||||
assert.equal(big_result[3].track, 1);
|
||||
assert.equal(big_result[4].track, 2);
|
||||
assert.equal(big_result[5].track, 3);
|
||||
|
@ -51,7 +51,7 @@ describe("Parser", function() {
|
|||
assert.equal(big_result[12].track, 10);
|
||||
});
|
||||
|
||||
it("should ensure ending timestamps for all", function() {
|
||||
it("should ensure ending timestamps for all", function () {
|
||||
assert.deepEqual(big_result[13].end, {
|
||||
calc: 3023,
|
||||
hh: 0,
|
||||
|
@ -63,8 +63,9 @@ describe("Parser", function() {
|
|||
assert.deepEqual(big_result[14].end, null);
|
||||
});
|
||||
|
||||
it("should parse timestamps with square brackets", function() {
|
||||
let result = parse(`[00:00:00] 1. Steve Kroeger x Skye Holland - Through The Dark
|
||||
it("should parse timestamps with square brackets", function () {
|
||||
let result =
|
||||
parse(`[00:00:00] 1. Steve Kroeger x Skye Holland - Through The Dark
|
||||
[00:02:53] 2. Gabri Ponte x Jerome - Lonely `);
|
||||
assert.deepEqual(result[0], {
|
||||
artist: "Steve Kroeger x Skye Holland",
|
||||
|
@ -79,7 +80,7 @@ describe("Parser", function() {
|
|||
});
|
||||
});
|
||||
|
||||
it("should parse durations when given", function() {
|
||||
it("should parse durations when given", function () {
|
||||
let result = parse(`1. Artist - Title 6:19
|
||||
2. Another Artist - Another Title 6:59
|
||||
3. Yet Another Artist - Yet another title 5:12`);
|
||||
|
@ -113,7 +114,7 @@ describe("Parser", function() {
|
|||
});
|
||||
});
|
||||
|
||||
it("should parse as timestamps if first timestamp is 00:00", function() {
|
||||
it("should parse as timestamps if first timestamp is 00:00", function () {
|
||||
let result = parse(`1. Artist - Title 00:00
|
||||
2. Another Artist - Another Title 01:00
|
||||
3. Yet Another Artist - Yet another title 02:00`);
|
||||
|
@ -140,11 +141,14 @@ describe("Parser", function() {
|
|||
track: 3,
|
||||
end: null,
|
||||
start: { ts: "00:02:00", hh: 0, mm: 2, ss: 0, calc: 120 },
|
||||
_: { left_text: "Yet Another Artist - Yet another title", right_text: "" },
|
||||
_: {
|
||||
left_text: "Yet Another Artist - Yet another title",
|
||||
right_text: "",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("should parse durations as timestamps when forced", function() {
|
||||
it("should parse durations as timestamps when forced", function () {
|
||||
let result = parse(
|
||||
`1. Artist - Title 5:00
|
||||
2. Another Artist - Another Title 4:20`,
|
||||
|
@ -166,7 +170,7 @@ describe("Parser", function() {
|
|||
});
|
||||
});
|
||||
|
||||
it("should parse timestamps as durations when forced", function() {
|
||||
it("should parse timestamps as durations when forced", function () {
|
||||
let result = parse(
|
||||
`1. Artist - Title 1:00
|
||||
2. Another Artist - Another Title 1:15`,
|
||||
|
@ -214,7 +218,7 @@ describe("Parser", function() {
|
|||
});
|
||||
});
|
||||
|
||||
it("should parse taylor swift", function() {
|
||||
it("should parse taylor swift", function () {
|
||||
let result = parse(`0:00 the 1
|
||||
3:29 cardigan
|
||||
9:30 the last great american dynasty
|
||||
|
|
Loading…
Reference in New Issue