rainlink-nico
Version:
A rainlink plugin that allows you to play music on apple
197 lines (196 loc) • 7.72 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 __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.RainlinkPlugin = void 0;
const rainlink_1 = require("rainlink");
const rainlink_2 = require("rainlink");
const rainlink_3 = require("rainlink");
const rainlink_4 = require("rainlink");
const NicoResolver_1 = __importDefault(require("./NicoResolver"));
const NicoSearch_js_1 = __importDefault(require("./NicoSearch.js"));
const REGEX = RegExp(
// https://github.com/ytdl-org/youtube-dl/blob/a8035827177d6b59aca03bd717acb6a9bdd75ada/youtube_dl/extractor/niconico.py#L162
'https?://(?:www\\.|secure\\.|sp\\.)?nicovideo\\.jp/watch/(?<id>(?:[a-z]{2})?[0-9]+)');
class RainlinkPlugin extends rainlink_4.SourceRainlinkPlugin {
/**
* Initialize the plugin.
* @param nicoOptions Options for run plugin
*/
constructor(nicoOptions) {
super();
this.options = nicoOptions;
this.methods = {
track: this.getTrack.bind(this),
};
this.rainlink = null;
}
/**
* Source identify of the plugin
* @returns string
*/
sourceIdentify() {
return 'nv';
}
/**
* Source name of the plugin
* @returns string
*/
sourceName() {
return 'nicovideo';
}
/**
* Type of the plugin
* @returns RainlinkPluginType
*/
type() {
return rainlink_1.RainlinkPluginType.SourceResolver;
}
/**
* load the plugin
* @param rainlink The rainlink class
*/
load(rainlink) {
this.rainlink = rainlink;
this._search = rainlink.search.bind(rainlink);
rainlink.search = this.search.bind(this);
}
/**
* Unload the plugin
* @param rainlink The rainlink class
*/
unload(rainlink) {
this.rainlink = rainlink;
rainlink.search = rainlink.search.bind(rainlink);
}
/** Name function for getting plugin name */
name() {
return 'rainlink-nico';
}
search(query, options) {
return __awaiter(this, void 0, void 0, function* () {
const res = yield this._search(query, options);
if (!this.directSearchChecker(query))
return res;
if (res.tracks.length == 0)
return this.searchDirect(query, options);
else
return res;
});
}
/**
* Directly search from plugin
* @param query URI or track name query
* @param options search option like RainlinkSearchOptions
* @returns RainlinkSearchResult
*/
searchDirect(query, options) {
return __awaiter(this, void 0, void 0, function* () {
var _a;
if (!this.rainlink || !this._search)
throw new Error('rainlink-nico is not loaded yet.');
if (!query)
throw new Error('Query is required');
const [, id] = REGEX.exec(query) || [];
const isUrl = /^https?:\/\//.test(query);
if (id) {
this.debug(`Start search from ${this.sourceName()} plugin`);
const _function = this.methods.track;
const result = yield _function(id, options === null || options === void 0 ? void 0 : options.requester);
const loadType = result ? rainlink_2.RainlinkSearchResultType.TRACK : rainlink_2.RainlinkSearchResultType.SEARCH;
const playlistName = (_a = result.name) !== null && _a !== void 0 ? _a : undefined;
const tracks = result.tracks.filter(this.filterNullOrUndefined);
return this.buildSearch(playlistName, tracks && tracks.length !== 0 ? tracks : [], loadType);
}
else if ((options === null || options === void 0 ? void 0 : options.engine) === this.sourceName() && !isUrl) {
const result = yield this.searchTrack(query, options === null || options === void 0 ? void 0 : options.requester);
return this.buildSearch(undefined, result.tracks, rainlink_2.RainlinkSearchResultType.SEARCH);
}
else
return this.buildSearch(undefined, [], rainlink_2.RainlinkSearchResultType.SEARCH);
});
}
buildSearch(playlistName, tracks = [], type) {
return {
playlistName,
tracks,
type: type !== null && type !== void 0 ? type : rainlink_2.RainlinkSearchResultType.TRACK,
};
}
searchTrack(query, requester) {
return __awaiter(this, void 0, void 0, function* () {
try {
const { data } = yield (0, NicoSearch_js_1.default)({
q: query,
targets: ['tagsExact'],
fields: ['contentId'],
sort: '-viewCounter',
limit: 10,
});
const res = [];
for (let i = 0; i < data.length; i++) {
const element = data[i];
const nico = new NicoResolver_1.default(`https://www.nicovideo.jp/watch/${element.contentId}`);
const info = yield nico.getVideoInfo();
res.push(info);
}
return {
tracks: res.map(track => this.buildrainlinkTrack(track, requester)),
};
}
catch (e) {
throw new Error(e);
}
});
}
getTrack(id, requester) {
return __awaiter(this, void 0, void 0, function* () {
try {
const niconico = new NicoResolver_1.default(`https://www.nicovideo.jp/watch/${id}`);
const info = yield niconico.getVideoInfo();
return { tracks: [this.buildrainlinkTrack(info, requester)] };
}
catch (e) {
throw new Error(e);
}
});
}
filterNullOrUndefined(obj) {
return obj !== undefined && obj !== null;
}
buildrainlinkTrack(nicoTrack, requester) {
return new rainlink_3.RainlinkTrack({
encoded: '',
info: {
sourceName: this.sourceName(),
identifier: nicoTrack.id,
isSeekable: true,
author: nicoTrack.owner ? nicoTrack.owner.nickname : 'Unknown',
length: nicoTrack.duration * 1000,
isStream: false,
position: 0,
title: nicoTrack.title,
uri: `https://www.nicovideo.jp/watch/${nicoTrack.id}`,
artworkUrl: nicoTrack.thumbnail ? nicoTrack.thumbnail.url : '',
isrc: null
},
pluginInfo: {
name: 'rainlink.mod@nico',
},
}, requester);
}
debug(logs) {
this.rainlink ? this.rainlink.emit(rainlink_1.RainlinkEvents.Debug, `[Rainlink Nico Plugin]: ${logs}`) : true;
}
}
exports.RainlinkPlugin = RainlinkPlugin;