@ -0,0 +1,91 @@ | |||
import { IMovieSearchInfo } from "@autoplex-api/torrent-search"; | |||
import { jsonRequest } from "../../util"; | |||
import Provider, { MediaType } from "../Provider"; | |||
import { ISearchResult, ITokenResponse } from "./schema"; | |||
/** | |||
* The Base URL for the API | |||
*/ | |||
const URL_BASE = "https://torrentapi.org/pubapi_v2.php?app_id=autoplex"; | |||
/** | |||
* How frequently to re-authenticate | |||
*/ | |||
const AUTH_FREQUENCY = 1000*60*15; // 15 minutes | |||
export default class Rarbg extends Provider | |||
{ | |||
/** | |||
* The name of the provider | |||
*/ | |||
public readonly NAME = "RARBG"; | |||
/** | |||
* Indicate the content that the provider provides | |||
*/ | |||
public readonly PROVIDES = MediaType.Movies | MediaType.TvShows; | |||
/** | |||
* Throttle requests; | |||
*/ | |||
protected readonly THROTTLE = 1500; | |||
/** | |||
* Since the API is sereverly broken, we need a bunch of retries | |||
*/ | |||
protected readonly SEARCH_RETRIES = 30; | |||
/** | |||
* Store the time when the API needs to re-authenticate | |||
*/ | |||
protected nextAuthenticationTime: number = 0; | |||
/** | |||
* The authentication token | |||
*/ | |||
protected token!: string; | |||
/** | |||
* Indicate if the API is currently authenticated | |||
*/ | |||
protected async isAuthenticated() { | |||
return Date.now() < this.nextAuthenticationTime; | |||
} | |||
/** | |||
* Authenticate the RARBG context | |||
*/ | |||
protected async authenticate() { | |||
let now = Date.now(); | |||
let [status, response] = await jsonRequest<ITokenResponse>(`${URL_BASE}&get_token=get_token`); | |||
if (status !== 200) { | |||
return false; | |||
} | |||
this.nextAuthenticationTime = now + AUTH_FREQUENCY; | |||
this.token = response.token; | |||
return true; | |||
} | |||
/** | |||
* Search for a movie | |||
*/ | |||
public async searchMovieImdb(imdbId: string, movie: IMovieSearchInfo) { | |||
let [_, response] = await jsonRequest<ISearchResult>( | |||
`${URL_BASE}&token=${this.token}` | |||
+ `&mode=search&search_imdb=${imdbId}` | |||
+ "&format=json_extended&limit=100" | |||
); | |||
if (response.error_code !== undefined) { | |||
if (response.error_code === 10) { | |||
return []; // Successful search, no results found | |||
} | |||
throw new Error("No results found"); // API most likely broke, we need to retry. | |||
} | |||
if (response.torrent_results === undefined) { | |||
throw new Error("Torrents should be defined here"); | |||
} | |||
return response.torrent_results.map(result => this.createTorrent( | |||
movie, result.title, result.size, result.seeders, result.download | |||
)); | |||
} | |||
} |
@ -0,0 +1,52 @@ | |||
export enum Category { | |||
MOVIES_XVID = 14, | |||
MOVIES_XVID_720 = 48, | |||
MOVIES_X264 = 17, | |||
MOVIES_X264_1080 = 44, | |||
MOVIES_X264_720 = 45, | |||
MOVIES_X264_3D = 47, | |||
MOVIES_X264_4K = 50, | |||
MOVIES_X265_4K = 51, | |||
MOVIES_X265_4K_HDR = 52, | |||
MOVIES_FULL_BD = 42, | |||
MOVIES_BD_REMUX = 46, | |||
TV_EPISODES = 18, | |||
TV_HD_EPISODES = 41, | |||
TV_UHD_EPISODES = 49 | |||
} | |||
export enum ErrorCode { | |||
NoTokenSet = 1, | |||
InvalidToken = 4, | |||
InvalidImdb = 9, | |||
ImdbNotFound = 10, | |||
NoResultsFound = 20, | |||
Error = 22 | |||
} | |||
export interface ITokenResponse { | |||
token: string | |||
} | |||
export interface ISearchResult { | |||
error ?: string, | |||
error_code ?: number, | |||
torrent_results?: IResult[] | |||
} | |||
export interface IResult { | |||
title : string, | |||
category : string, | |||
download : string, | |||
seeders : number, | |||
leechers : number, | |||
size : number, | |||
pubdate : string, | |||
ranked : number, | |||
info_page : string, | |||
episode_info: { | |||
imdb : string|null, | |||
tvdb : string|null, | |||
themoviedb: string|null, | |||
} | |||
} |
@ -1,36 +1,32 @@ | |||
import { IMovieSearchInfo } from "@autoplex-api/torrent-search"; | |||
import Provider, { MediaType } from "../Provider"; | |||
import Torrent from "../../Torrent"; | |||
import { search, Sort } from "./search"; | |||
/** | |||
* Throttle the torrent search | |||
*/ | |||
const THROTTLE_SEARCH = 3000; | |||
import { search } from "./search"; | |||
import { Sort } from "./schema"; | |||
export default class TorrentGalaxy extends Provider | |||
{ | |||
/** | |||
* The torrent provider name | |||
*/ | |||
public readonly NAME = "Torrent Galaxy"; | |||
/** | |||
* Indicate that this provider provides movies | |||
*/ | |||
public readonly PROVIDES = MediaType.Movies; | |||
/** | |||
* Throttle the requests | |||
*/ | |||
protected readonly THROTTLE = 3000; | |||
/** | |||
* Search for a movie | |||
*/ | |||
public async searchMovie(movie: IMovieSearchInfo) { | |||
if (movie.imdbId === null) { | |||
return []; | |||
} | |||
await this.lock(); | |||
let torrents = await search(movie.imdbId, undefined, Sort.Seeders); | |||
this.unlock(THROTTLE_SEARCH); | |||
return torrents.torrents.map(torrent => new Torrent( | |||
movie, | |||
torrent.name, | |||
torrent.size, | |||
torrent.seeders, | |||
torrent.magnet | |||
public async searchMovieImdb(imdbId: string, movie: IMovieSearchInfo) { | |||
let torrents = await search(imdbId, undefined, Sort.Seeders); | |||
return torrents.torrents.map(torrent => this.createTorrent( | |||
movie, torrent.name, torrent.size,torrent.seeders, torrent.magnet | |||
)); | |||
} | |||
} |
@ -0,0 +1,89 @@ | |||
export enum LanguageId { | |||
AllLanguages = 0, | |||
English = 1, | |||
French = 2, | |||
German = 3, | |||
Italian = 4, | |||
Japanese = 5, | |||
Spanish = 6, | |||
Russian = 7, | |||
Hindi = 8, | |||
OtherMultiple = 9, | |||
Korean = 10, | |||
Danish = 11, | |||
Norwegian = 12, | |||
Dutch = 13, | |||
Chinese = 14, | |||
Portuguese = 15, | |||
Bengali = 16, | |||
Polish = 17, | |||
Turkish = 18, | |||
Telugu = 19, | |||
Urdu = 20, | |||
Arabic = 21, | |||
Swedish = 22, | |||
Romanian = 23, | |||
Thai = 24 | |||
} | |||
export enum Language { | |||
AllLanguages ="AllLanguages", | |||
English ="English", | |||
French ="French", | |||
German ="German", | |||
Italian ="Italian", | |||
Japanese ="Japanese", | |||
Spanish ="Spanish", | |||
Russian ="Russian", | |||
Hindi ="Hindi", | |||
OtherMultiple ="OtherMultiple", | |||
Korean ="Korean", | |||
Danish ="Danish", | |||
Norwegian ="Norwegian", | |||
Dutch ="Dutch", | |||
Chinese ="Chinese", | |||
Portuguese ="Portuguese", | |||
Bengali ="Bengali", | |||
Polish ="Polish", | |||
Turkish ="Turkish", | |||
Telugu ="Telugu", | |||
Urdu ="Urdu", | |||
Arabic ="Arabic", | |||
Swedish ="Swedish", | |||
Romanian ="Romanian", | |||
Thai ="Thai" | |||
} | |||
export enum Category { | |||
Documentaries = 9, | |||
MoviesHD = 42, | |||
MoviesSD = 1, | |||
Movies4K = 3, | |||
MoviesPacks = 4, | |||
TVEpisodesHD = 41, | |||
TVEPisodesSD = 5, | |||
TVPacks = 6, | |||
TVSports = 7 | |||
} | |||
export enum Sort { | |||
Date = "id", | |||
Name = "name", | |||
Size = "size", | |||
Seeders = "seeders" | |||
} | |||
export enum SortOrder { | |||
Asc = "asc", | |||
Desc = "desc", | |||
} | |||
export interface ITorrentGalaxyTorrent { | |||
category: number, | |||
language: Language, | |||
name : string, | |||
magnet : string, | |||
size : number, | |||
seeders : number, | |||
leechers: number | |||
} |