New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

yifysubtitles

Package Overview
Dependencies
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

yifysubtitles - npm Package Compare versions

Comparing version 2.1.3 to 2.1.4

10

examples/test.js

@@ -1,2 +0,2 @@

const yifysubtitles = require('../index');
const yifysubtitles = require('..');

@@ -6,5 +6,5 @@ console.log('dirname', __dirname);

yifysubtitles('tt1156398', {langs: ['fr', 'en', 'zh'], path: '/tmp'})
.then(res => {
console.log('res', res);
})
.catch(err => console.log(err));
.then(res => {
console.log('res', res);
})
.catch(error => console.log(error));

@@ -12,90 +12,125 @@ const fs = require('fs');

const apiUri = 'http://api.yifysubtitles.com/subs';
const uri = 'http://www.yifysubtitles.com/movie-imdb';
const downloadUri = 'http://yifysubtitles.com';
// Down const apiUri = 'http://api.yifysubtitles.com/subs';
const uri = 'https://www.yifysubtitles.com/movie-imdb';
const downloadUri = 'https://yifysubtitles.com';
const langK = Object.keys(langsFormat);
const langV = langK.map(i => langsFormat[i]);
const formatLangLong = lang => (langV[langK.indexOf(lang)]);
const formatLangShort = lang => (langK[langV.indexOf(lang)]);
const formatLangLong = lang => langV[langK.indexOf(lang)];
const formatLangShort = lang => langK[langV.indexOf(lang)];
// Since yifysubtitle api is not working anymore we scrape the site instead
const scrape = imdbId => {
return got(`${uri}/${imdbId}`)
.then(res => cheerio.load(res.body))
.then($ => {
return $('tbody tr').map((i, el) => {
const $el = $(el);
return {
rating: $el.find('.rating-cell').text(),
language: $el.find('.flag-cell .sub-lang').text().toLowerCase(),
url: $el.find('.download-cell a').attr('href').replace('subtitles/', 'subtitle/') + '.zip'
};
}).get();
})
return got(`${uri}/${imdbId}`)
.then(res => cheerio.load(res.body))
.then($ => {
return $('tbody tr')
.map((i, el) => {
const $el = $(el);
return {
rating: $el.find('.rating-cell').text(),
language: $el
.find('.flag-cell .sub-lang')
.text()
.toLowerCase(),
url:
$el
.find('.download-cell a')
.attr('href')
.replace('subtitles/', 'subtitle/') + '.zip'
};
})
.get();
});
};
const langFilter = (subs, langs) => {
const data = langs.reduce((acc, l) => {
const lang = subs.filter(s => s.language === l).sort((a, b) => b.rating - a.rating);
if (lang.length) {
acc[l] = lang[0];
}
return acc;
}, {});
return data
const data = langs.reduce((acc, l) => {
const lang = subs
.filter(s => s.language === l)
.sort((a, b) => b.rating - a.rating);
if (lang.length > 0) {
acc[l] = lang[0];
}
return acc;
}, {});
return data;
};
const downloadFormat = format => (lang, url, link) => {
let writed = '';
let fullPath = '';
let writed = '';
let fullPath = '';
return got.stream(downloadUri + url)
.pipe(unzipper())
.pipe(streamz(entry => {
const parsedPath = path.parse(entry.path);
if (parsedPath.dir === '' && parsedPath.ext === '.srt') {
writed = format === 'srt' ? entry.path : entry.path.replace('srt', 'vtt');
fullPath = path.join(link, writed);
return format === 'srt'
? entry.pipe(fs.createWriteStream(fullPath))
: entry.pipe(srt2vtt()).pipe(fs.createWriteStream(fullPath));
}
entry.autodrain();
}))
.promise()
.then(() => ({lang: lang, langShort: formatLangShort(lang), path: fullPath, fileName: writed}));
return got
.stream(downloadUri + url)
.pipe(unzipper())
.pipe(
streamz(entry => {
const parsedPath = path.parse(entry.path);
// Add Language to subtitle name and deete spaces
const escapedLang = lang.replace('/', '-');
entry.path = entry.path
.replace(/\s+/g, '.')
.replace(parsedPath.ext, `_${escapedLang}_${parsedPath.ext}`);
if (parsedPath.dir === '' && parsedPath.ext === '.srt') {
writed =
format === 'srt' ? entry.path : entry.path.replace('srt', 'vtt');
fullPath = path.join(link, writed);
return format === 'srt' ?
entry.pipe(fs.createWriteStream(fullPath)) :
entry.pipe(srt2vtt()).pipe(fs.createWriteStream(fullPath));
}
entry.autodrain();
})
)
.promise()
.then(() => ({
lang,
langShort: formatLangShort(lang),
path: fullPath,
fileName: writed
}));
};
const downloads = (res, opts) => {
const download = downloadFormat(opts.format);
const {concurrency, path} = opts;
const download = downloadFormat(opts.format);
const {concurrency, path} = opts;
return pMap(Object.keys(res), lang => download(lang, res[lang].url, path), concurrency);
return pMap(
Object.keys(res),
lang => download(lang, res[lang].url, path),
concurrency
);
};
const runConditional = (imdbId, opts, res) => {
return Promise.resolve(langFilter(res, opts.langs.map(formatLangLong)))
.then(res => downloads(res, opts));
return Promise.resolve(
langFilter(res, opts.langs.map(formatLangLong))
).then(res => downloads(res, opts));
};
const yifysubtitles = (imdbId, opts) => {
opts = Object.assign({
path: __dirname,
langs: ['en'],
concurrency: Infinity,
format: 'vtt'
}, opts);
opts = Object.assign(
{
path: __dirname,
langs: ['en'],
concurrency: Infinity,
format: 'vtt'
},
opts
);
if (opts.langs.constructor !== Array) {
throw new TypeError('Expected `langs` to be an array');
} else if (opts.langs.some(lang => langK.indexOf(lang) === -1)) {
throw new TypeError(`Expected \`langs\` members to be in ${langK}`);
}
if (opts.langs.constructor !== Array) {
throw new TypeError('Expected `langs` to be an array');
} else if (opts.langs.some(lang => langK.indexOf(lang) === -1)) {
throw new TypeError(`Expected \`langs\` members to be in ${langK}`);
}
return scrape(imdbId)
.then(res => res.length ? runConditional(imdbId, opts, res) : []);
return scrape(imdbId).then(res =>
(res.length > 0) ? runConditional(imdbId, opts, res) : []
);
};
module.exports = yifysubtitles;
{
"name": "yifysubtitles",
"version": "2.1.3",
"version": "2.1.4",
"description": "A simple wrapper to download subtitles from the yifysubtitles website.",

@@ -8,11 +8,12 @@ "license": "MIT",

"type": "git",
"url": "https://github.com/MRdotB/yifysubtitles"
"url": "https://github.com/mrdotb/yifysubtitles"
},
"author": {
"name": "mrdotb",
"email": "baptiste.chaleil@gmail.com"
"email": "mrdotb@protonmail.com"
},
"main": "index.js",
"scripts": {
"test": "ava"
"test": "ava",
"lint": "xo --fix"
},

@@ -23,2 +24,5 @@ "ava": {

},
"xo": {
"space": true
},
"dependencies": {

@@ -35,2 +39,3 @@ "cheerio": "^1.0.0-rc.2",

"ava": "^0.25.0",
"xo": "^0.24.0",
"pify": "^4.0.0"

@@ -37,0 +42,0 @@ },

import test from 'ava';
import got from 'got';
test(`http://yifysubtitles.com should be alive`, async t => {
const res = await got(`http://yifysubtitles.com`);
test('http://yifysubtitles.com should be alive', async t => {
const res = await got('http://yifysubtitles.com');
t.is(res.statusCode, 200);
t.is(res.statusCode, 200);
});

@@ -7,55 +7,55 @@ import fs from 'fs';

import yifysubtitles from '../';
import yifysubtitles from '..';
const downloadDir = path.join(__dirname, 'tmp');
test.before('setup: create tmp dir', async t => {
await pify(fs.mkdir)(downloadDir);
test.before('setup: create tmp dir', async () => {
await pify(fs.mkdir)(downloadDir);
});
test('with imdbid not in api', async t => {
const subtitles = await yifysubtitles('tt1234567', {path: downloadDir, langs: ['fr', 'en', 'nl']});
const subtitles = await yifysubtitles('tt1234567', {path: downloadDir, langs: ['fr', 'en', 'nl']});
t.is(subtitles.length, 0);
t.is(subtitles.length, 0);
});
test('opts.langs bad args', t => {
t.throws(() => yifysubtitles('tt1156398', {langs: 'lol string'}));
t.throws(() => yifysubtitles('tt1156398', {langs: ['zz']}));
t.throws(() => yifysubtitles('tt1156398', {langs: 'lol string'}));
t.throws(() => yifysubtitles('tt1156398', {langs: ['zz']}));
});
test('download zombieland subtitles in fr, en, nl + transform in vtt', async t => {
const subtitles = await yifysubtitles('tt1156398', {path: downloadDir, langs: ['fr', 'en', 'nl']});
const subtitles = await yifysubtitles('tt1156398', {path: downloadDir, langs: ['fr', 'en', 'nl']});
t.is(subtitles.length, 3, 'results length should be 3');
subtitles.forEach(subtitle => t.regex(subtitle.path, /(\.vtt)$/, 'extension should be vtt'));
t.is(subtitles.length, 3, 'results length should be 3');
subtitles.forEach(subtitle => t.regex(subtitle.path, /(\.vtt)$/, 'extension should be vtt'));
const paths = subtitles.map(subtitle => subtitle.path);
await pMap(paths, path => t.notThrows(pify(fs.access)(path), 'file should exist'));
await pMap(paths, path => pify(fs.unlink)(path));
const paths = subtitles.map(subtitle => subtitle.path);
await pMap(paths, path => t.notThrows(pify(fs.access)(path), 'file should exist'));
await pMap(paths, path => pify(fs.unlink)(path));
});
test('download zombieland subtitles in fr, en, nl', async t => {
const subtitles = await yifysubtitles('tt1156398', {path: downloadDir, langs: ['fr', 'en', 'nl'], format: 'srt'});
const subtitles = await yifysubtitles('tt1156398', {path: downloadDir, langs: ['fr', 'en', 'nl'], format: 'srt'});
t.is(subtitles.length, 3, 'results length should be 3');
subtitles.forEach(subtitle => t.regex(subtitle.path, /(\.srt)$/, 'extension should be srt'));
t.is(subtitles.length, 3, 'results length should be 3');
subtitles.forEach(subtitle => t.regex(subtitle.path, /(\.srt)$/, 'extension should be srt'));
const paths = subtitles.map(subtitle => subtitle.path);
await pMap(paths, path => t.notThrows(pify(fs.access)(path), 'file should exist'));
await pMap(paths, path => pify(fs.unlink)(path));
const paths = subtitles.map(subtitle => subtitle.path);
await pMap(paths, path => t.notThrows(pify(fs.access)(path), 'file should exist'));
await pMap(paths, path => pify(fs.unlink)(path));
});
test('download rango subtitles in ir', async t => {
const subtitles = await yifysubtitles('tt1192628', {path: downloadDir, langs: ['ir']});
const subtitles = await yifysubtitles('tt1192628', {path: downloadDir, langs: ['ir']});
t.is(subtitles.length, 1, 'results length should be 1');
t.is(subtitles.length, 1, 'results length should be 1');
const paths = subtitles.map(subtitle => subtitle.path);
await pMap(paths, path => t.notThrows(pify(fs.access)(path), 'file should exist'));
await pMap(paths, path => pify(fs.unlink)(path));
const paths = subtitles.map(subtitle => subtitle.path);
await pMap(paths, path => t.notThrows(pify(fs.access)(path), 'file should exist'));
await pMap(paths, path => pify(fs.unlink)(path));
});
test.after.always('cleanup: delete tmp dir', async t => {
await pify(fs.rmdir)(downloadDir);
test.after.always('cleanup: delete tmp dir', async () => {
await pify(fs.rmdir)(downloadDir);
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc