Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // ==UserScript==
- // @name wykop tag followers
- // @namespace https://wykop.pl
- // @version 0.1
- // @description add follower count to tags autocomplete
- // @author 4:19am
- // @match https://wykop.pl/*
- // @grant none
- // ==/UserScript==
- let interceptors = [];
- /*
- * Add a interceptor.
- */
- const addInterceptor = (interceptor) => {
- interceptors.push(interceptor);
- };
- /*
- * Clear interceptors
- */
- const clearInterceptors = () => {
- interceptors = [];
- };
- /*
- * XML HTPP requests can be intercepted with interceptors.
- * Takes a regex to match against requests made and a callback to process the response.
- */
- const createXmlHttpOverride = (
- open
- ) => {
- return function (
- method,
- url,
- async,
- username,
- password
- ) {
- this.addEventListener(
- "readystatechange",
- function () {
- if (this.readyState === 4) {
- // Override `onreadystatechange` handler, there's no where else this can go.
- // Basically replace the client's with our override for interception.
- this.onreadystatechange = (function (
- originalOnreadystatechange
- ) {
- return function (ev) {
- // Only intercept JSON requests.
- const contentType = this.getResponseHeader("content-type");
- if (!contentType || !contentType.includes("application/json")) {
- return (
- originalOnreadystatechange &&
- originalOnreadystatechange.call(this, ev)
- );
- }
- // Read data from response.
- (async function () {
- let success = false;
- let data;
- try {
- data =
- this.responseType === "blob"
- ? JSON.parse(await this.response.text())
- : JSON.parse(this.responseText);
- success = true;
- } catch (e) {
- console.error("Unable to parse response.");
- }
- if (!success) {
- return (
- originalOnreadystatechange &&
- originalOnreadystatechange.call(this, ev)
- );
- }
- for (const i in interceptors) {
- const { regex, override, callback } = interceptors[i];
- // Override.
- const match = url.indexOf(regex) !== -1;
- if (match) {
- if (override) {
- try {
- data = await callback(data, this);
- } catch (e) {
- return (
- originalOnreadystatechange &&
- originalOnreadystatechange.call(this, ev)
- );
- }
- }
- }
- }
- // Override the response text.
- Object.defineProperty(this, "responseText", {
- get() {
- return JSON.stringify(data);
- },
- });
- // Tell the client callback that we're done.
- return (
- originalOnreadystatechange &&
- originalOnreadystatechange.call(this, ev)
- );
- }.call(this));
- };
- })(this.onreadystatechange);
- }
- },
- false
- );
- open.call(this, method, url, async, username, password);
- };
- };
- const sleep = (ms) => new Promise((res) => setTimeout(res, ms));
- const tagAutocompletionLimit = 5; // to jest obecny limit wykopu (tj ilosci wyswietlanych podpowiedzi). moj skrypt go nie zmienia (narazie), ta zmienna tylko okresla do ilu tagow ma wyciagac liczbe obserwujacych
- async function tagsAutocompleteOptionInjector (tagsDict) {
- let container = document.querySelector('section.inline-autocomplete');
- let tries = 0;
- while (container === null && tries !== false) {
- tries += 1;
- container = document.querySelector('section.inline-autocomplete');
- if (tries > 60) {
- tries = false;
- }
- if (tries > 40) {
- await sleep(50);
- }
- }
- tries = 0;
- while (container.matches('.waiting') || container.matches('.pending') || tries !== false) {
- tries += 1;
- container = document.querySelector('section.inline-autocomplete');
- if (tries > 100) {
- tries = false;
- }
- if (tries > 80) {
- await sleep(50);
- }
- }
- if (container === null) {
- return false;
- }
- container.querySelectorAll('span').forEach(
- function (span)
- {
- var followers = tagsDict[span.innerText];
- if (followers) {
- span.innerText += ' (' + followers + ' obs.)';
- }
- }
- );
- }
- async function getTagsFollowers (tags, token) {
- const responses = await Promise.all(
- tags.map(async tag => {
- const res = await fetch(`https://wykop.pl/api/v3/tags/${tag}`,
- {
- headers: {
- 'authorization': 'Bearer ' + token
- }
- }
- );
- return res.json();
- })
- );
- return responses;
- }
- async function tagsAutocompleteRequestHandler(data, originalRequest) {
- data.data.splice(tagAutocompletionLimit, 5).reverse();
- let tags = data.data;
- tags = tags.map(x => x.name);
- const responses = await getTagsFollowers(tags, window.localStorage.getItem("token"));
- let tagsWithFollowers = responses.map(x => ({"name": x.data.name, "followers": x.data.followers}) );
- let tagsDict = Object.fromEntries(responses.map(x => ['#' + x.data.name, x.data.followers]));
- tagsAutocompleteOptionInjector(tagsDict);
- return {"data": tagsWithFollowers};
- }
- const main = () => {
- addInterceptor({
- regex: "wykop.pl/api/v3/tags/autocomplete",
- callback: tagsAutocompleteRequestHandler,
- override: true
- });
- XMLHttpRequest.prototype.open = createXmlHttpOverride(
- XMLHttpRequest.prototype.open
- );
- };
- main();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement