diff --git a/.eslintrc.json b/.eslintrc.json index ba4de9c..42ebb05 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -10,9 +10,6 @@ "rules": { "no-await-in-loop": "warn", "no-compare-neg-zero": "error", - "no-extra-parens": ["warn", "all", { - "nestedBinaryExpressions": false - }], "no-template-curly-in-string": "error", "no-unsafe-negation": "error", "valid-jsdoc": ["error", { @@ -95,7 +92,7 @@ "func-names": "error", "func-name-matching": "error", "func-style": ["error", "declaration", { "allowArrowFunctions": true }], - "indent": ["error", 2, { "SwitchCase": 1 }], + "indent": ["error", 2, { "SwitchCase": 1, "offsetTernaryExpressions": true }], "key-spacing": "error", "keyword-spacing": "error", "max-depth": "error", @@ -117,7 +114,6 @@ "nonblock-statement-body-position": "error", "object-curly-spacing": ["error", "always"], "operator-assignment": "error", - "operator-linebreak": ["error", "after"], "padded-blocks": ["error", "never"], "quote-props": ["error", "as-needed"], "quotes": ["error", "single", { "avoidEscape": true, "allowTemplateLiterals": true }], diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..07d56b5 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +ko_fi: skick \ No newline at end of file diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml deleted file mode 100644 index dc777c5..0000000 --- a/.github/workflows/lint.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: Lint - -on: [push, pull_request] - -jobs: - eslint: - name: Lint - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 - - - uses: actions/setup-node@v1 - with: - node-version: 13.x - - - name: npm install, build, and lint - run: | - npm install - npm run build --if-present - npm run-script lint - npm run-script lint:typings diff --git a/.github/workflows/node_ci.yml b/.github/workflows/node_ci.yml deleted file mode 100644 index 2ac388c..0000000 --- a/.github/workflows/node_ci.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: Node.js CI - -on: [push] - -jobs: - build: - - runs-on: ubuntu-latest - - strategy: - matrix: - node-version: [8.x, 10.x, 12.x] - - steps: - - uses: actions/checkout@v2 - - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 - with: - node-version: ${{ matrix.node-version }} - - - run: npm install - - run: npm run build --if-present - - run: npm test - env: - CI: true diff --git a/.github/workflows/publish_npm.yml b/.github/workflows/publish_npm.yml new file mode 100644 index 0000000..154cc8b --- /dev/null +++ b/.github/workflows/publish_npm.yml @@ -0,0 +1,31 @@ +name: Publish @distube/ytdl-core +on: + push: + tags: + - '*' +jobs: + publish: + name: Build & Publish + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install Node.js + uses: actions/setup-node@v3 + with: + node-version: 18 + registry-url: "https://registry.npmjs.org" + + - name: Install dependencies + run: npm i + + - name: Publish + run: npm publish + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }} + + - name: Deprecate older versions + run: npm deprecate @distube/ytdl-core@"< ${{ github.ref_name }}" "This version is deprecated, please upgrade to the latest version." + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }} diff --git a/.gitignore b/.gitignore index c838784..4294cfe 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ node_modules coverage .nyc_output test.js -package-lock.json \ No newline at end of file +package-lock.json +dumps \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..54e8251 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,10 @@ +{ + "semi": true, + "trailingComma": "all", + "printWidth": 120, + "endOfLine": "lf", + "quoteProps": "as-needed", + "arrowParens": "avoid", + "tabWidth": 2, + "singleQuote": true +} diff --git a/lib/main.js b/lib/main.js index a3cb8e3..2f73a21 100644 --- a/lib/main.js +++ b/lib/main.js @@ -1,10 +1,9 @@ const PARSE_ITEM = require('./parseItem.js'); const { request } = require('undici'); const UTIL = require('./util.js'); -const QS = require('querystring'); -const BASE_SEARCH_URL = 'https://www.youtube.com/results?'; -const BASE_API_URL = 'https://www.youtube.com/youtubei/v1/search?key='; +const BASE_SEARCH_URL = 'https://www.youtube.com/results'; +const BASE_API_URL = 'https://www.youtube.com/youtubei/v1/search'; const CACHE = new Map(); // Save api key and client version for safeSearch @@ -16,7 +15,7 @@ const saveCache = (parsed, opts) => { }; // eslint-disable-next-line complexity -const main = module.exports = async (searchString, options, rt = 3) => { +const main = (module.exports = async (searchString, options, rt = 3) => { if (rt === 2) { CACHE.delete('apiKey'); CACHE.delete('clientVersion'); @@ -26,29 +25,43 @@ const main = module.exports = async (searchString, options, rt = 3) => { // Set default values const opts = UTIL.checkArgs(searchString, options); - const ref = BASE_SEARCH_URL + QS.encode(opts.query); let parsed = {}; if (!opts.safeSearch || !CACHE.has('apiKey') || !CACHE.has('clientVersion') || !CACHE.has('playlistParams')) { - const body = await request(ref, opts.requestOptions).then(r => r.body.text()); + const body = await request(BASE_SEARCH_URL, Object.assign({}, opts.requestOptions, { query: opts.query })).then(r => + r.body.text(), + ); parsed = UTIL.parseBody(body, opts); let plParams = UTIL.betweenFromRight(body, `"params":"`, '"}},"tooltip":"Search for Playlist"'); if (plParams) CACHE.set('playlistParams', plParams); saveCache(parsed, opts); } if (opts.type === 'playlist') { - let params = 'EgIQAw%253D%253D'; - if (CACHE.has('playlistParams')) params = CACHE.get('playlistParams'); - parsed.json = await UTIL.doPost(BASE_API_URL + parsed.apiKey, opts, { - context: parsed.context, - params, - query: searchString, - }).catch(() => null); + const params = CACHE.has('playlistParams') ? CACHE.get('playlistParams') : 'EgIQAw%253D%253D'; + parsed.json = await UTIL.doPost( + BASE_API_URL, + Object.assign({}, opts.requestOptions, { + query: { key: parsed.apiKey, prettyPrint: false }, + }), + { + context: parsed.context, + params, + query: searchString, + }, + ); if (!parsed.json) throw new Error('Cannot searching for Playlist!'); } else if (opts.safeSearch || !parsed.json) { try { if (!parsed.apiKey || !parsed.context.client.clientVersion) throw new Error('Missing api key'); - const context = parsed.context; - parsed.json = await UTIL.doPost(BASE_API_URL + parsed.apiKey, opts, { context, query: searchString }); + parsed.json = await UTIL.doPost( + BASE_API_URL, + Object.assign({}, opts.requestOptions, { + query: { key: parsed.apiKey, prettyPrint: false }, + }), + { + context: parsed.context, + query: searchString, + }, + ); } catch (e) { if (rt === 1) throw e; } @@ -67,7 +80,8 @@ const main = module.exports = async (searchString, options, rt = 3) => { ); // Parse items - resp.items = rawItems.map(a => PARSE_ITEM(a, resp)) + resp.items = rawItems + .map(a => PARSE_ITEM(a, resp)) .filter(r => r && r.type === opts.type) .filter((_, index) => index < opts.limit); @@ -93,7 +107,7 @@ const main = module.exports = async (searchString, options, rt = 3) => { UTIL.logger(parsed); throw new Error(e); } -}; +}); const parsePage2 = async (apiKey, token, context, opts) => { const json = await UTIL.doPost(BASE_API_URL + apiKey, opts.requestOptions, { context, continuation: token }); @@ -105,7 +119,8 @@ const parsePage2 = async (apiKey, token, context, opts) => { const { rawItems, continuation } = UTIL.parsePage2Wrapper( json.onResponseReceivedCommands[0].appendContinuationItemsAction.continuationItems, ); - const parsedItems = rawItems.map(PARSE_ITEM) + const parsedItems = rawItems + .map(PARSE_ITEM) .filter(r => r && r.type === opts.type) .filter((_, index) => index < opts.limit); diff --git a/lib/util.js b/lib/util.js index c64ee61..7daf9e8 100644 --- a/lib/util.js +++ b/lib/util.js @@ -44,7 +44,7 @@ exports.parseBody = (body, options = {}) => { return { json, apiKey, context }; }; -const buildPostContext = exports.buildPostContext = (clientVersion, options = {}) => { +const buildPostContext = (exports.buildPostContext = (clientVersion, options = {}) => { // Make deep copy and set clientVersion const context = clone(DEFAULT_CONTEXT); context.client.clientVersion = clientVersion; @@ -54,13 +54,13 @@ const buildPostContext = exports.buildPostContext = (clientVersion, options = {} if (options.utcOffsetMinutes) context.client.utcOffsetMinutes = options.utcOffsetMinutes; if (options.safeSearch) context.user.enableSafetyMode = true; return context; -}; +}); // Parsing utility -const parseText = exports.parseText = txt => - typeof txt === 'object' ? txt.simpleText || (Array.isArray(txt.runs) ? txt.runs.map(a => a.text).join('') : '') : ''; +const parseText = (exports.parseText = txt => + typeof txt === 'object' ? txt.simpleText || (Array.isArray(txt.runs) ? txt.runs.map(a => a.text).join('') : '') : ''); -exports.parseIntegerFromText = x => typeof x === 'string' ? Number(x) : Number(parseText(x).replace(/\D+/g, '')); +exports.parseIntegerFromText = x => (typeof x === 'string' ? Number(x) : Number(parseText(x).replace(/\D+/g, ''))); // Request Utility exports.doPost = (url, opts, payload) => { diff --git a/package.json b/package.json index 7988561..2e5b973 100644 --- a/package.json +++ b/package.json @@ -29,13 +29,14 @@ "lint:fix": "eslint --fix ./" }, "dependencies": { - "undici": "^5.25.2" + "undici": "^5.27.2" }, "devDependencies": { - "eslint": "^8.49.0" + "eslint": "^8.54.0" }, "engines": { "node": ">=8" }, - "homepage": "https://github.com/distubejs/ytsr#readme" + "homepage": "https://github.com/distubejs/ytsr#readme", + "funding": "https://github.com/distubejs/ytsr?sponsor=1" }