sonarr-pogdesign-importer
Version:
Import tv series from pogdesign and/or trakt into sonarr
191 lines (152 loc) • 6.51 kB
text/typescript
import { IConfig, IScraper } from './interfaces/config';
import PogDesign from './scrapers/pogdesign';
import { IItem } from './interfaces/scraper';
import { ISeries } from './interfaces/sonarr';
import SonarrApi from './sonarrapi';
import * as moment from 'moment';
import Trakt from './scrapers/trakt';
class App {
private readonly config: IConfig;
private readonly sonarrApi: SonarrApi;
constructor(config: IConfig) {
this.config = config;
this.sonarrApi = new SonarrApi(config);
}
private async scrape() {
let result: IItem[] = [];
for (const scraper of this.config.scrapers) {
try {
console.log(`${scraper.type} started`);
const items = await this.getItems(scraper);
if (items && items.length) {
result = result.concat(items);
}
console.log(`${scraper.type} finished successfully with ${items.length} series`);
} catch (exception) {
console.log(`Skipping... ${exception}`);
}
console.log();
console.log();
}
return result;
}
private async getItems(scraper: IScraper) {
switch (scraper.type.toLocaleLowerCase()) {
case 'trakt':
const trakt = new Trakt(scraper, this.config.verbose);
return trakt.process();
case 'pogdesign':
const pogdesign = new PogDesign(scraper, this.config.verbose);
return pogdesign.process();
default:
throw `'${scraper.type}' is not a valid type`;
}
}
private async lookupItems(items: IItem[]) {
let result: ISeries[] = [];
for (const item of items) {
if (result.some(r => r.tvdbId === item.tvdbId || r.title.toLocaleLowerCase() === item.title.toLocaleLowerCase())) {
continue;
}
const res = await this.sonarrApi.lookupSeries(item.title);
if (!res.ok) {
console.log(`Sonarr responded with ${res.status}: ${await res.text()}`);
continue;
}
const series: ISeries[] = await res.json();
const thisYear = parseInt(moment().format('YYYY'));
for (const serie of series) {
if ((item.tvdbId === serie.tvdbId) || (!item.tvdbId && serie.year >= thisYear)) {
if (!result.some(r => r.tvdbId === serie.tvdbId)) {
serie.profileId = this.config.sonarr.profileId;
serie.rootFolderPath = this.config.sonarr.path;
serie.seasonFolder = this.config.sonarr.useSeasonFolder;
result.push(serie);
}
break;
}
}
}
return result;
}
private async lookupLocal(series: ISeries[]) {
const res = await this.sonarrApi.getSeries();
if (!res.ok) {
console.log(`Sonarr responded with ${res.status}: ${await res.text()}`);
return series;
}
const localSeries: ISeries[] = await res.json();
const result = series.filter(item => !localSeries || !localSeries.length || !localSeries.some(local => local.tvdbId === item.tvdbId));
return result;
}
async process() {
if (this.config.verbose) { console.log('Scraping started'); }
const scrapeItems = await this.scrape();
const scrapedItems = await this.lookupItems(scrapeItems);
console.log();
if (scrapedItems.length > 0) {
let items = await this.lookupLocal(scrapedItems);
if (this.config.verbose && scrapedItems.length > items.length) { console.log(`${scrapedItems.length - items.length}/${scrapedItems.length} series already exists in Sonarr.`); }
if (!items.length) {
console.log('\nNothing new to add to Sonarr');
process.exit(0);
} else if (this.config.verbose) {
console.log(`${items.length} new series are ready to be imported into Sonarr.`);
}
if (this.config.genresIgnored && this.config.genresIgnored.length) {
if (this.config.verbose) { console.log(); }
items = this.filterCategories(items);
}
if (this.config.verbose) { console.log(); }
await this.addSeries(items);
} else {
console.log('\nNothing new to add to Sonarr');
}
}
private async addSeries(items: ISeries[]) {
let notAdded: number = 0;
for (const item of items) {
console.log(`\t${item.title}`);
if (!this.config.test) {
const res = await this.sonarrApi.addSeries(item);
if (!res.ok) {
if (this.config.verbose || res.status !== 400) {
notAdded++;
console.log(`Sonarr responded with ${res.status}: ${await res.text()}`);
}
continue;
}
const json = await res.json();
if (this.config.verbose) {
console.log(JSON.stringify(json, null, 2));
}
}
}
console.log();
const totalImported = items.length - notAdded;
if (totalImported) {
console.log(`${totalImported} series were successfully imported to Sonarr`);
} else if (notAdded) {
console.log('Something went wrong when adding. Please try again with verbose.')
}
}
private filterCategories(items: ISeries[]) {
const genres = this.config.genresIgnored.map(genre => genre.toLocaleLowerCase());
const result = items.filter(item => {
const itemGenres = item.genres.map(genre => genre.toLocaleLowerCase());
const isOk = !genres.filter(genre => {
return itemGenres.indexOf(genre) !== -1;
}).length;
if (!isOk && this.config.verbose) {
console.log(`${item.title} skipped because the genres do not match.`);
}
return isOk;
});
console.log();
if (this.config.verbose) {
console.log(`${items.length - result.length} series were skipped.`);
}
return result;
}
}
export default App;