gogo-dl
Version:
<h1 align="center">gogo-dl</h1> <p align="center"> <b> Powerful, lightweight, user-friendly tool for downloading anime.</b> </p>
426 lines (425 loc) • 22.9 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.driver = void 0;
var prompts = require("prompts");
var chalk = require("chalk");
var dl_1 = require("../commands/dl");
var watch_1 = require("../commands/watch");
var watchList_1 = require("../commands/watchList");
var Anime_1 = require("../models/Anime");
var Gogoanime_1 = __importDefault(require("../sites/Gogoanime"));
var got_1 = __importDefault(require("got"));
var _9anime_1 = __importDefault(require("../sites/9anime"));
var utils_1 = require("../utils/utils");
var cli_spinners_1 = __importDefault(require("cli-spinners"));
var loadingSpinner = require('loading-spinner');
var SUPPORTED_SITES = ['Gogoanime', '9anime'];
var t_site = new Map();
t_site.set("Gogoanime", new Gogoanime_1.default());
t_site.set("9anime", new _9anime_1.default());
exports.driver = {
mapIDToList: function (ani) {
return __awaiter(this, void 0, void 0, function () {
var id, date, url, site_key, response, res, sites, _i, _a, site_1, slug_keys, ind_subs, _b, slug_keys_1, key, e_1;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
id = ani.id;
date = Date.parse(ani.start_date);
url = "https://api.malsync.moe/mal/anime/" + id;
site_key = 'Sites';
if (Date.now() - date.valueOf() > 1209600000) {
url = "https://raw.githubusercontent.com/MALSync/MAL-Sync-Backup/master/data/myanimelist/anime/" + id + ".json";
site_key = 'Pages';
}
_c.label = 1;
case 1:
_c.trys.push([1, 3, , 4]);
return [4 /*yield*/, got_1.default(url)];
case 2:
response = _c.sent();
if (response.statusCode === 200 && response.body !== 'Not found in the fire') {
res = JSON.parse(response.body);
if (res[site_key] !== undefined) {
sites = new Map();
for (_i = 0, _a = Object.keys(res[site_key]); _i < _a.length; _i++) {
site_1 = _a[_i];
slug_keys = Object.keys(res[site_key][site_1]);
ind_subs = { dub: undefined, sub: undefined, uncen: undefined };
if (site_1 === 'Gogoanime') {
for (_b = 0, slug_keys_1 = slug_keys; _b < slug_keys_1.length; _b++) {
key = slug_keys_1[_b];
if (key.toLowerCase().endsWith('-uncensored')) {
ind_subs.uncen = res[site_key][site_1][key]['url'];
}
else if (key.toLowerCase().endsWith('-dub')) {
ind_subs.dub = res[site_key][site_1][key]['url'];
}
else {
ind_subs.sub = res[site_key][site_1][key]['url'];
}
}
}
else {
if (slug_keys.length == 2) {
if (res[site_key][site_1][slug_keys[0]]['url'].toLowerCase().lastIndexOf('dub') > res[site_key][site_1][slug_keys[1]]['url'].toLowerCase().lastIndexOf('dub')) {
ind_subs.dub = res[site_key][site_1][slug_keys[0]]['url'];
ind_subs.sub = res[site_key][site_1][slug_keys[1]]['url'];
}
else {
ind_subs.dub = res[site_key][site_1][slug_keys[1]]['url'];
ind_subs.sub = res[site_key][site_1][slug_keys[0]]['url'];
}
}
else
ind_subs.sub = res[site_key][site_1][slug_keys[0]]['url'];
}
sites.set(site_1, ind_subs);
}
return [2 /*return*/, sites];
}
else
return [2 /*return*/, new Map()];
}
else
return [2 /*return*/, new Map()];
return [3 /*break*/, 4];
case 3:
e_1 = _c.sent();
return [2 /*return*/, new Map()];
case 4: return [2 /*return*/];
}
});
});
},
askForShow: function (title, cmd, player) {
return __awaiter(this, void 0, void 0, function () {
var style, options, choices, i, _i, _a, anime, opts, intersected, watch_lists, _b, watch_lists_1, anime, opts, i, response;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
style = cli_spinners_1.default.bouncingBar;
loadingSpinner.setSequence(style.frames);
process.stdout.write(chalk.gray('fetching from MAL '));
loadingSpinner.start(style.interval, { clearLine: true });
options = [];
choices = {
type: 'select',
name: 'value',
message: 'Pick a show',
choices: [],
initial: 0,
};
if (!(cmd !== 'list' && cmd !== 'remove')) return [3 /*break*/, 6];
i = 0;
_i = 0;
return [4 /*yield*/, utils_1.utils.getMal().search(title, { limit: 100, offset: 0 })];
case 1:
_a = _c.sent();
_c.label = 2;
case 2:
if (!(_i < _a.length)) return [3 /*break*/, 5];
anime = _a[_i];
if (i >= 10)
return [3 /*break*/, 5];
return [4 /*yield*/, this.mapIDToList(anime.node)];
case 3:
opts = _c.sent();
if (opts.size > 0) {
intersected = Array.from(opts.keys()).filter(function (value) { return SUPPORTED_SITES.includes(value); });
if (intersected.length > 0 && anime.node.start_season !== undefined && anime.node.start_season.year !== undefined) {
options.push(new Anime_1.Anime(anime.node.title, opts, "", anime.node.start_season.year, anime.node.id));
i += 1;
}
}
_c.label = 4;
case 4:
_i++;
return [3 /*break*/, 2];
case 5:
if (options.length === 0) {
console.log(chalk.redBright('no results found for search term ') + chalk.yellow("" + title));
process.exit(0);
}
return [3 /*break*/, 12];
case 6: return [4 /*yield*/, utils_1.utils.getMal().get_watch_list({ status: "watching" /* watching */ })];
case 7:
watch_lists = _c.sent();
_b = 0, watch_lists_1 = watch_lists;
_c.label = 8;
case 8:
if (!(_b < watch_lists_1.length)) return [3 /*break*/, 11];
anime = watch_lists_1[_b];
return [4 /*yield*/, this.mapIDToList(anime.node)];
case 9:
opts = _c.sent();
if (opts.size > 0) {
options.push(new Anime_1.Anime(anime.node.title, opts, "", anime.node.start_season.year, anime.node.id));
}
_c.label = 10;
case 10:
_b++;
return [3 /*break*/, 8];
case 11:
if (cmd === 'list')
cmd = title;
_c.label = 12;
case 12:
for (i = 0; i < options.length; i++) {
// @ts-ignore
choices.choices.push({ title: options[i].name, description: '' + options[i].released, value: i });
}
loadingSpinner.stop();
console.log();
return [4 /*yield*/, prompts(choices)];
case 13:
response = _c.sent();
if (!(response.value === undefined)) return [3 /*break*/, 14];
process.exit(0);
return [3 /*break*/, 20];
case 14:
if (!(cmd === 'add')) return [3 /*break*/, 16];
return [4 /*yield*/, watchList_1.watchList.newShow(options[response.value].id)];
case 15:
_c.sent();
return [3 /*break*/, 20];
case 16:
if (!(cmd === 'remove')) return [3 /*break*/, 18];
return [4 /*yield*/, watchList_1.watchList.removeShow(options[response.value].id)];
case 17:
_c.sent();
return [3 /*break*/, 20];
case 18: return [4 /*yield*/, exports.driver.execute(options[response.value], cmd, player)];
case 19:
_c.sent();
_c.label = 20;
case 20: return [2 /*return*/];
}
});
});
},
execute: function (anime, type, player) {
var _a, _b;
return __awaiter(this, void 0, void 0, function () {
var rangeNum, intersected, meta, default_src, watch_type, options, response, options, range, rangeStr;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
intersected = Array.from(anime.href.keys()).filter(function (value) { return SUPPORTED_SITES.includes(value); }).sort();
default_src = intersected[0];
if (intersected.includes('Gogoanime'))
default_src = 'Gogoanime';
watch_type = '';
if (!(anime.href.get(default_src).dub !== undefined || anime.href.get(default_src).uncen !== undefined)) return [3 /*break*/, 2];
options = {
type: 'select',
name: 'value',
message: 'Pick an option',
choices: [
{ title: 'Subbed', value: 'sub' },
],
initial: 0
};
if (anime.href.get(default_src).dub !== undefined) { // @ts-ignore
(_a = options.choices) === null || _a === void 0 ? void 0 : _a.push({ title: 'Dubbed', value: 'dub' });
}
if (anime.href.get(default_src).uncen !== undefined) { // @ts-ignore
(_b = options.choices) === null || _b === void 0 ? void 0 : _b.push({ title: 'Uncensored', value: 'uncen' });
}
return [4 /*yield*/, prompts(options)];
case 1:
response = _c.sent();
if (response.value === 'uncen')
watch_type = 'uncen';
else if (response.value === 'dub')
watch_type = 'dub';
else
watch_type = 'sub';
return [3 /*break*/, 3];
case 2:
watch_type = 'sub';
_c.label = 3;
case 3:
if (!(watch_type === 'uncen')) return [3 /*break*/, 5];
return [4 /*yield*/, t_site.get(default_src).getMetaData(anime.href.get(default_src).uncen)];
case 4:
meta = _c.sent();
return [3 /*break*/, 9];
case 5:
if (!(watch_type === 'dub')) return [3 /*break*/, 7];
return [4 /*yield*/, t_site.get(default_src).getMetaData(anime.href.get(default_src).dub)];
case 6:
meta = _c.sent();
return [3 /*break*/, 9];
case 7: return [4 /*yield*/, t_site.get(default_src).getMetaData(anime.href.get(default_src).sub)];
case 8:
meta = _c.sent();
_c.label = 9;
case 9:
if (!(meta.lastEpisode !== 1)) return [3 /*break*/, 11];
console.log("\nThere are " + chalk.magenta(meta.lastEpisode) + " episodes");
options = {
type: 'text',
name: 'value',
message: "Episode range [1-" + meta.lastEpisode + "]"
};
return [4 /*yield*/, prompts(options)];
case 10:
range = _c.sent();
rangeStr = range.value;
if (rangeStr !== undefined && rangeStr !== null && rangeStr.trim().length > 0)
rangeNum = this.getRangeFromString(rangeStr);
else {
process.exit(0);
}
if (rangeNum.lower > rangeNum.upper) {
rangeNum = { lower: rangeNum.upper, upper: rangeNum.lower };
}
return [3 /*break*/, 12];
case 11:
if (meta.lastEpisode > 0) {
rangeNum = { lower: 1, upper: 1 };
}
else {
console.log(chalk.redBright('no episodes available'));
process.exit(0);
}
_c.label = 12;
case 12:
if (!(type === 'dl')) return [3 /*break*/, 14];
return [4 /*yield*/, dl_1.dl.download(anime, rangeNum.lower, rangeNum.upper, watch_type)];
case 13:
_c.sent();
return [3 /*break*/, 16];
case 14:
if (!(type === 'watch')) return [3 /*break*/, 16];
return [4 /*yield*/, watch_1.watch.watch(anime, rangeNum.lower, rangeNum.upper, player, watch_type)];
case 15:
_c.sent();
_c.label = 16;
case 16: return [2 /*return*/];
}
});
});
},
getRangeFromString: function (range) {
var ind = range.indexOf('-');
var lower;
var upper;
if (ind === undefined || ind === -1) {
lower = parseInt(range.trim());
upper = parseInt(range.trim());
}
else {
lower = parseInt(range.substring(0, ind).trim());
upper = parseInt(range.substring(ind + 1).trim());
}
return { lower: lower, upper: upper };
},
getOptimizedPlayer: function (anime, ep, type) {
return __awaiter(this, void 0, void 0, function () {
var temp, src, back_up, _i, _a, server;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
if (!(anime.href.get('Gogoanime') !== undefined)) return [3 /*break*/, 8];
temp = void 0;
src = '';
back_up = '';
_i = 0, _a = ['vidcdn', 'anime', 'xstreamcdn', 'streamtape'];
_b.label = 1;
case 1:
if (!(_i < _a.length)) return [3 /*break*/, 4];
server = _a[_i];
if (!(src === '' || src.endsWith('.m3u8'))) return [3 /*break*/, 3];
return [4 /*yield*/, this.getUrl(anime, ep, type, "Gogoanime", server)];
case 2:
temp = (_b.sent());
if (temp !== undefined) {
back_up = temp;
if (!temp.endsWith('.m3u8')) {
src = temp;
}
}
_b.label = 3;
case 3:
_i++;
return [3 /*break*/, 1];
case 4:
if (!(src !== '')) return [3 /*break*/, 5];
return [2 /*return*/, src];
case 5:
if (!(anime.href.get('9anime') !== undefined)) return [3 /*break*/, 7];
return [4 /*yield*/, this.getUrl(anime, ep, type, "9anime", '')];
case 6:
temp = (_b.sent());
if (temp !== undefined)
return [2 /*return*/, temp];
_b.label = 7;
case 7: return [2 /*return*/, back_up];
case 8: return [2 /*return*/];
}
});
});
},
getUrl: function (anime, ep, type, src, server) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!(type === 'uncen' && anime.href.get(src).uncen !== undefined)) return [3 /*break*/, 2];
return [4 /*yield*/, t_site.get(src).getVideoSrc(anime.href.get(src).uncen, ep, server)];
case 1: return [2 /*return*/, _a.sent()];
case 2:
if (!(type === 'dub' && anime.href.get(src).dub !== undefined)) return [3 /*break*/, 4];
return [4 /*yield*/, t_site.get(src).getVideoSrc(anime.href.get(src).dub, ep, server)];
case 3: return [2 /*return*/, _a.sent()];
case 4:
if (!(type === 'sub')) return [3 /*break*/, 6];
return [4 /*yield*/, t_site.get(src).getVideoSrc(anime.href.get(src).sub, ep, server)];
case 5: return [2 /*return*/, _a.sent()];
case 6: return [2 /*return*/, undefined];
}
});
});
}
};