-
Notifications
You must be signed in to change notification settings - Fork 34
Providers
Providers are really simple JSON objects that tell to helios where and how to find sources.
Please note that for legal reasons, I won't discuss, develop nor distribute any providers connecting to illegal sources. So there is no need to ask me. While I can partake in general discussions regarding provider development, I won't do so for illegal sources specific problems.
If you want to create a new provider, here is the Provider interface (you need some HTML/JavaScript background): Provider Interface
Let's see an example:
{
"my_first_provider": {
"name": "MyProvider1",
"enabled": true,
"enabled_in_list": true,
"languages": ["en"],
"base_url": "https://www.my-provider.com/search/",
"response_type": "text",
"movie": {
"query": "{query}/Movies/1/",
"keywords": "{title} {year}"
},
"episode": {
"query": "{query}/TV/1/",
"keywords": "{title} {episodeCode}"
},
"anime": {
"query": "{query}/Anime/1/",
"keywords": "{title} {episode}"
},
"html_parser": {
"row": "doc.querySelectorAll('tbody > tr')",
"title": "row.querySelector('a:nth-child(2)').innerHTML",
"peers": "row.querySelector('.leeches').innerHTML",
"seeds": "row.querySelector('.seeds').innerHTML",
"size": "row.querySelector('tbody > tr .size').textContent.split('B')[0] + 'B'",
"url": "'https://www.my-provider.com/'+ row.querySelector('a:nth-child(2)').getAttribute('href')"
},
"source_is_in_sub_page": true,
"title_replacement": {
"'s": "s",
"\"": ""
}
},
"my_second_provider": {
"name": "MyProvider2",
"enabled": true,
"enabled_in_list": true,
"languages": [
"en"
],
"base_url": "https://my-provider2.org/api",
"response_type": "json",
"time_to_wait_between_each_request_ms": 300,
"time_to_wait_on_too_many_request_ms": 5000,
"token": {
"query": "?get_token=get_token",
"token_validity_time_ms": 840000,
"token_format": {
"token": "token"
}
},
"movie": {
"query": "?mode=search&search_imdb={query}&category=movies&token={token}",
"keywords": "{imdbId}"
},
"episode": {
"query": "?mode=search&search_string={query}&category=tv&token={token}",
"keywords": "{title} {episodeCode}"
},
"json_format": {
"results": "torrent_results",
"url": "download",
"title": "title",
"seeds": "seeders",
"peers": "leechers",
"size": "size"
},
"title_replacement": {
"'s": "s",
"\"": ""
}
}
}
Here we have 2 providers my_first_provider and my_second_provider. The first one will parse html pages while the second will use a JSON API
Let's say we want to look for the movie "Helios Movie" aired on 2010. Here are the steps helios is gonna do to search for this query:
- Replace
{title} {year}
byHelios Movie 2010
(bellow all available variables) - Replace
{query}/Movies/1/
byHelios%20Movie%202010/Movies/1/
- Call this url
https://www.my-provider.com/search/Helios%20Movie%202010/Movies/1/
If the url returns a 200 response, helios will parse the HTML received using html_parser
property. It will:
- Execute
doc.querySelectorAll('tbody > tr')
wheredoc
is the HTML document received - For each returned row it will try to find all the other properties:
2.1. Get the title fromrow.querySelector('a:nth-child(2)').innerHTML
2.2. Get the peers fromrow.querySelector('.leeches').innerHTML
2.3. Get the seeds fromrow.querySelector('.seeds').innerHTML
2.4. Get the size fromrow.querySelector('tbody > tr .size').textContent.split('B')[0] + 'B'
(If the size is a number it will be converted automatically)
2.5. This provider hassource_is_in_sub_page = true
which means the url we're gonna get is not the torrent url but a page where the magnet url will be find inside the source code. We get this sub page url like this fromrow.querySelector('a:nth-child(2)').getAttribute('href')
.
Ok we saw how to search for a movie, it's basically the same for a TV show. {episodeCode}
will look like sXXeYY
where XX
is the season number and YY
is the episode number.
Dealing with JSON API is better than parsing HTML. Let's search for the same movie "Helios Movie 2010" with the IMDb id: "tt99999"
This API needs a token for every request, first helios will retrieve this token because it is dynamic and it doesn't last forever.
helios will call "https://my-provider2.org/api?get_token=get_token". It expects a JSON response like that:
{
"token":"MyToKeN"
}
Once the token is retrieved, it will be stored for "840000" ms, after that another token will be asked before new requests.
Let's search. Here the keywords are not title+year but imdbId. Searching by imdbId will provide accurate results.
helios will proceed the same for all the replacements and finally it will call the URL: "https://my-provider2.org/api?mode=search&search_imdb=tt99999&category=movies&token=MyToKeN"
The expected result for this request will look like this:
{
"torrent_results": [
{
"url":"magnet:XXXXX",
"title":"Helios Movie 2010 By YYY",
"seeds":100,
"peers": 90,
"size":10000
},
{
"url":"magnet:XXXXX",
"title":"Helios Movie 2010 By ZZZ",
"seeds":55,
"peers": 20,
"size":90000
},
....
]
}
Here is the provider for Legit Torrent (a torrent tracker for only legal torrents)
{
"legittorrents": {
"name": "Legit Torrents",
"enabled": true,
"enabled_in_list": false,
"languages": [
"en"
],
"base_url": "http://www.legittorrents.info/index.php?page=torrents&active=1",
"response_type": "text",
"movie": {
"query": "&search={query}&category=1",
"keywords": "{title} "
},
"html_parser": {
"row": "doc.querySelectorAll('#bodyarea tr table:nth-child(3) table.lista tr')",
"title": "row.querySelector('td:nth-child(2) a').textContent",
"peers": "row.querySelector('td:nth-child(6)').textContent",
"seeds": "row.querySelector('td:nth-child(5)').textContent",
"size": null,
"url": "'http://www.legittorrents.info/'+ row.querySelector('td:nth-child(3) a').getAttribute('href')"
},
"source_is_in_sub_page": false
}
}
This is the list of all variable that can be added.
- title: Helios Movie
- titleFirstLetter: W
- imdbId
- year
- episodeCode (i.e. s02e06)
- season (i.e. 02)
- episode (i.e. 06)
- query
- token For the title you can choose the title in the language you want. By default "title" will be replaced by the original title. If you want the french title, use "title.fr"