Skip to content

Commit 4ca2851

Browse files
committed
Initial Commit
0 parents  commit 4ca2851

File tree

5 files changed

+281
-0
lines changed

5 files changed

+281
-0
lines changed

.gitignore

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
yarn-debug.log*
6+
yarn-error.log*
7+
8+
# Runtime data
9+
pids
10+
*.pid
11+
*.seed
12+
*.pid.lock
13+
14+
# Directory for instrumented libs generated by jscoverage/JSCover
15+
lib-cov
16+
17+
# Coverage directory used by tools like istanbul
18+
coverage
19+
20+
# nyc test coverage
21+
.nyc_output
22+
23+
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
24+
.grunt
25+
26+
# Bower dependency directory (https://bower.io/)
27+
bower_components
28+
29+
# node-waf configuration
30+
.lock-wscript
31+
32+
# Compiled binary addons (http://nodejs.org/api/addons.html)
33+
build/Release
34+
35+
# Dependency directories
36+
node_modules/
37+
jspm_packages/
38+
39+
# Typescript v1 declaration files
40+
typings/
41+
42+
# Optional npm cache directory
43+
.npm
44+
45+
# Optional eslint cache
46+
.eslintcache
47+
48+
# Optional REPL history
49+
.node_repl_history
50+
51+
# Output of 'npm pack'
52+
*.tgz
53+
54+
# Yarn Integrity file
55+
.yarn-integrity
56+
57+
# dotenv environment variables file
58+
.env

LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2017 Mike Kokkolios
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# subs4free
2+
Search for Greek & English movies' subtitles
3+
4+
## Installation
5+
* `npm install subs4free`
6+
7+
## Usage
8+
```javascript
9+
const subs4free = require('subs4free')
10+
11+
// Get subs and movies list by search query
12+
subs4free.getSubs('cars', function(err, results) {
13+
console.log(results)
14+
})
15+
16+
/*
17+
{ movies_count: 4,
18+
subs_count: 24,
19+
langs: [ 'en', 'el' ],
20+
movies:
21+
[ { id: 'md48bc7ac4d', title: 'Cars 3' },
22+
{ id: 'md5f94634e5', title: 'Cars 2' },
23+
{ id: 'm4ca2388654', title: 'Gifted Hands: The Ben Carson Story' },
24+
{ id: 'm6c3966eb63', title: 'Cars' } ],
25+
subs:
26+
[ { lang: 'en',
27+
name: 'Cars 3 2017 720p-1080p BluRay X264-AMIABLE',
28+
uploader: 'MiKiE',
29+
downloads: '176',
30+
link: 'http://www.subs4free.com/download-s27033ffda0.html' },
31+
{ lang: 'en',
32+
name: 'Cars 3 2017 720p-1080p BluRay x264 DTS-HDChina',
33+
uploader: 'MiKiE',
34+
downloads: '119',
35+
link: 'http://www.subs4free.com/download-s51ca3797e6.html' } ...etc
36+
]
37+
}
38+
*/
39+
40+
// Get subs list by movie id
41+
subs4free.getSubsById('mca769ae54a', function(err, results) {
42+
console.log(results)
43+
})
44+
45+
/*
46+
{ subs_count: 20,
47+
langs: [ 'el', 'en' ],
48+
subs:
49+
[ { lang: 'el',
50+
name: 'Rango 2011 PROPER 1080p BluRay x264-HDEX & VeDeTT & NERDHD',
51+
uploader: 'punked666',
52+
downloads: '2972',
53+
link: 'http://www.subs4free.com/download-s748ec6c440.html' },
54+
{ lang: 'el',
55+
name: 'Rango 2011 PROPER 720p BluRay x264-HDEX & VeDeTT & WiKi',
56+
uploader: 'punked666',
57+
downloads: '5980',
58+
link: 'http://www.subs4free.com/download-s1bf1bc78b1.html' } ...etc
59+
]
60+
}
61+
*/
62+
```
63+
64+
## Packages
65+
* [request](https://github.com/request/request)
66+
* [cheerio](https://github.com/cheeriojs/cheerio)
67+
* [iconv-lite](https://github.com/ashtuchkin/iconv-lite)
68+
69+
## License
70+
This project is licensed under The MIT License (MIT). Which means that you can use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the software. But you always need to state that Mike Kokkolios is the original author of this template.
71+
72+
Project is developed and maintained by [Mike Kokkolios](https://www.linkedin.com/in/michael-kokkolios).

index.js

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// Dependencies
2+
const request = require('request')
3+
const cheerio = require('cheerio')
4+
const iconv = require('iconv-lite')
5+
6+
// Greek Encoding
7+
const encoding = 'iso-8859-7'
8+
9+
// Base URL
10+
const URL = 'http://www.subs4free.com'
11+
12+
// Search by query
13+
let getSubs = (query, cb) => {
14+
let searchURL = `${URL}/search_report.php?search=${query}`
15+
request(searchURL, (err, res, body) => {
16+
if (!err && res.statusCode == 200) {
17+
let $ = cheerio.load(body)
18+
19+
// Movies List [{id, title}]
20+
let movies = []
21+
$('select.style10 option').each(function() {
22+
let id = $(this).val().split('-').pop().split('.')[0]
23+
let title = $(this).text()
24+
let info = {id, title}
25+
movies.push(info)
26+
})
27+
movies.shift()
28+
29+
// Subtitles List [{lang, name, uploader, downloads, link}]
30+
let subs = []
31+
$('.page_header table tr:nth-child(2) td table').each(function() {
32+
let lang = $(this).find('tr').first().find('td').eq(1).find('img').attr('src') != undefined ? $(this).find('tr').first().find('td').eq(1).find('img').attr('src').split('/').pop().split('.')[0] : ''
33+
let name = $(this).find('tr').first().find('td').eq(2).find('b').text().trim() != '' ? $(this).find('tr').first().find('td').eq(2).find('b').text().trim() : ''
34+
let uploader = $(this).find('tr').eq(1).find('td').first().find('table tr td b').text().trim() != '' ? $(this).find('tr').eq(1).find('td').first().find('table tr td b').text().trim() : ''
35+
let downloads = $(this).find('tr').eq(1).find('td:nth-child(2) b').text().trim() != '' ? $(this).find('tr').eq(1).find('td:nth-child(2) b').text().trim() : ''
36+
let link = $(this).find('tr').first().find('td').eq(3).find('a').attr('href') != undefined ? URL + $(this).find('tr').first().find('td').eq(3).find('a').attr('href') : ''
37+
38+
if (lang != '' && name != '' && uploader != '' && downloads != '' && link != '') {
39+
let sub = {lang, name, uploader, downloads, link}
40+
subs.push(sub)
41+
}
42+
})
43+
44+
// Languages [lang, lang...]
45+
let langs = Array.from(new Set(subs.map(x => x.lang)))
46+
47+
if (movies.length > 0 && subs.length > 0) {
48+
// Results callback
49+
cb(null, {movies_count: movies.length, subs_count: subs.length, langs, movies, subs})
50+
} else {
51+
// No movies found callback
52+
cb(null, {movies: 'No movies or subtitles were found'})
53+
}
54+
} else {
55+
// Error callback
56+
cb(err)
57+
}
58+
})
59+
}
60+
61+
// Search by movie id
62+
let getSubsById = (movie_id, cb) => {
63+
let searchURL = `${URL}/movie-${movie_id}.html`
64+
request({url: searchURL, encoding: null}, (err, res, body) => {
65+
if (!err && res.statusCode == 200) {
66+
body = iconv.decode(body, encoding)
67+
let $ = cheerio.load(body)
68+
69+
// Subtitles List [{lang, name, uploader, downloads, link}]
70+
let subs = []
71+
$('#subsTR table tr:nth-child(2) td table').each(function() {
72+
let lang = $(this).find('tr').first().find('td').eq(1).find('img').attr('src') != undefined ? $(this).find('tr').first().find('td').eq(1).find('img').attr('src').split('/').pop().split('.')[0] : ''
73+
let name = $(this).find('tr').first().find('td').eq(2).find('b').text().trim() != '' ? $(this).find('tr').first().find('td').eq(2).find('b').text().trim() : ''
74+
let uploader = $(this).find('tr').eq(1).find('td').first().find('table tr td b').text().trim() != '' ? $(this).find('tr').eq(1).find('td').first().find('table tr td b').text().trim() : ''
75+
let downloads = $(this).find('tr').eq(1).find('td:nth-child(2) b').text().trim() != '' ? $(this).find('tr').eq(1).find('td:nth-child(2) b').text().trim() : ''
76+
let link = $(this).find('tr').first().find('td').eq(3).find('a').attr('href') != undefined ? URL + $(this).find('tr').first().find('td').eq(3).find('a').attr('href') : ''
77+
78+
if (lang != '' && name != '' && uploader != '' && downloads != '' && link != '') {
79+
let sub = {lang, name, uploader, downloads, link}
80+
subs.push(sub)
81+
}
82+
})
83+
84+
// Languages [lang, lang...]
85+
let langs = Array.from(new Set(subs.map(x => x.lang)))
86+
87+
if (subs.length > 0) {
88+
// Results callback
89+
cb(null, {subs_count: subs.length, langs, subs: subs})
90+
} else {
91+
// No subtitles found callback
92+
cb(null, {subs: 'No subtitles were found'})
93+
}
94+
} else {
95+
// Error callback
96+
cb(err)
97+
}
98+
})
99+
}
100+
101+
// Export Functions
102+
module.exports = {getSubs, getSubsById}

package.json

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"name": "subs4free",
3+
"version": "0.0.1",
4+
"description": "A Subs4Free API for searching for movies' subtitles",
5+
"main": "index.js",
6+
"scripts": {
7+
"test": "echo \"Error: no test specified\" && exit 1"
8+
},
9+
"repository": {
10+
"type": "git",
11+
"url": "git+https://github.com/mikekok/subs4free.git"
12+
},
13+
"keywords": [
14+
"subs4free",
15+
"greek",
16+
"subs",
17+
"subtitles",
18+
"greek subs",
19+
"subs api"
20+
],
21+
"author": "Mike Kokkolios <[email protected]>",
22+
"license": "MIT",
23+
"dependencies": {
24+
"cheerio": "^1.0.0-rc.2",
25+
"iconv-lite": "^0.4.19",
26+
"request": "^2.83.0"
27+
}
28+
}

0 commit comments

Comments
 (0)