Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // ==UserScript==
- // @name jetriBetter
- // @namespace jetriBetter
- // @match https://hololive.jetri.co/*
- // @run-at document-start
- // @grant none
- // @version 1.0
- // @author トワ…
- // @description Uses the APIs from holodex for the holotools website
- // ==/UserScript==
- "use strict";
- // Emits 2 event types on `document`, where the event's `detail` property holds the jetri-fied API response:
- // "jetri-live": /v1/live
- // "jetri-channels": /v1/channels (`total` and `count` properties are always 1)
- const jetriLiveFromHolodex = (x) => ({
- id: x.id,
- yt_video_key: x.id,
- bb_video_id: null,
- title: x.title,
- thumbnail: null,
- status: x.status,
- live_schedule: x.start_scheduled,
- live_start: x.start_actual ?? null,
- live_end: null,
- live_viewers: x.live_viewers ?? null,
- channel: {
- id: x.channel.id,
- yt_channel_id: x.channel.id,
- bb_space_id: null,
- name: x.channel.name,
- photo: x.channel.photo,
- published_at: null, // unused
- twitter_link: null, // unused
- view_count: 0,
- subscriber_count: 0,
- video_count: 0,
- },
- });
- const jetriChannelFromHolodex = (x, i) => ({
- id: x.id,
- yt_channel_id: x.id,
- bb_space_id: null,
- name: x.name,
- description: "",
- photo: x.photo,
- published_at: i, // used only for sorting
- twitter_link: x.twitter,
- view_count: 0,
- subscriber_count: x.subscriber_count,
- video_count: x.video_count,
- video_original: x.video_count,
- });
- const handleLive = ({ target }) => {
- const streams = [];
- for (const stream of JSON.parse(target.responseText)) {
- const isYoutubeStream = stream.placeholderType !== "external-stream"
- && (stream.status === "live" || stream.status === "upcoming");
- if (isYoutubeStream) {
- streams.push(jetriLiveFromHolodex(stream));
- }
- }
- const result = streams.reduce((a, stream) => {
- a[stream.status].push(stream);
- return a;
- }, {
- live: [],
- upcoming: [],
- ended: [],
- cached: true,
- });
- Object.defineProperty(target, "responseText", {
- value: JSON.stringify(result),
- writable: true,
- enumerable: true,
- configrable: true,
- });
- return result;
- };
- const handleChannels = ({ target }) => {
- const channels = JSON.parse(target.responseText).map(jetriChannelFromHolodex);
- Object.defineProperty(target, "responseText", {
- value: JSON.stringify({
- count: 1,
- total: 1,
- channels,
- }),
- writable: true,
- enumerable: true,
- configrable: true,
- });
- return channels;
- };
- const makeLoadHandler = (wrapper, name) => (fn) => (event) => {
- if (event.target.readyState === 4) {
- const detail = wrapper(event);
- document.dispatchEvent(new CustomEvent(name, { detail }));
- }
- fn.call(event.target, event);
- };
- const onreadystatechangeDescriptor =
- Object.getOwnPropertyDescriptor(XMLHttpRequest.prototype, "onreadystatechange");
- const hijackReadystatechange = (xhr, wrapper) => void Object
- .defineProperty(xhr, "onreadystatechange", {
- get() {
- return onreadystatechangeDescriptor.get.call(this);
- },
- set(fn) {
- onreadystatechangeDescriptor.set.call(this, wrapper(fn));
- },
- enumerable: true,
- configrable: true,
- });
- const origOpen = XMLHttpRequest.prototype.open;
- const holodexLiveApiUrl =
- "https://holodex.net/api/v2/live?type=placeholder%2Cstream&org=Hololive";
- const holodexChannelsApiUrl =
- "https://holodex.net/api/v2/channels?limit=100&offset=0&type=vtuber&org=Hololive&sort=suborg&order=asc";
- Object.defineProperty(XMLHttpRequest.prototype, "open", {
- value: function open(method, url) {
- if (method.toUpperCase() === "GET") {
- const _url = new URL(url, "https://api.holotools.app/");
- if (_url.pathname === "/v1/live") {
- hijackReadystatechange(this, makeLoadHandler(handleLive, "jetri-live"));
- return origOpen.call(this, "GET", holodexLiveApiUrl);
- } else if (_url.pathname === "/v1/channels") {
- hijackReadystatechange(this, makeLoadHandler(handleChannels, "jetri-channels"));
- return origOpen.call(this, "GET", holodexChannelsApiUrl);
- }
- }
- return origOpen.apply(this, arguments);
- },
- writable: true,
- configrable: true,
- });
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement