-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgazelleApiLib.min.js
17 lines (17 loc) · 5.88 KB
/
gazelleApiLib.min.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// ==UserScript==
// ==UserLibrary==
// @name gazelleApiLib
// @namespace https://openuserjs.org/users/Anakunda
// @version 1.10
// @author Anakunda
// @license GPL-3.0-or-later
// @copyright 2021, Anakunda (https://openuserjs.org/users/Anakunda)
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_deleteValue
// @exclude *
// @require https://openuserjs.org/src/libs/Anakunda/libLocks.min.js
// ==/UserScript==
// ==/UserLibrary==
'use strict';const siteApiTimeframeStorageKey='AJAX time frame',ajaxRequestsCache=new Map;let ajaxApiKey,ajaxApiLogger,ajaxCache,ajaxLastCachedSuccess,gazelleApiMaxRetries=GM_getValue('gazelle_api_max_retries',100),gazelleApiFrameReserve=100,gazelleApiMutex=createMutex(),domStorageLimitReached=!1;if('function'==typeof GM_getValue)switch(document.domain){case'redacted.ch':ajaxApiKey=GM_getValue('redacted_api_key'),void 0===ajaxApiKey&&'function'==typeof GM_setValue&&GM_setValue('redacted_api_key','')}for(let key of['ajaxApiKey','ajax_api_key','apiKey','api_key'])!ajaxApiKey&&key in window.localStorage&&(ajaxApiKey=window.localStorage[key])&&'function'==typeof GM_setValue&&GM_setValue('api_key',ajaxApiKey);function setAjaxApiLogger(callback){ajaxApiLogger='function'==typeof callback?callback:void 0}function queryAjaxAPI(action,params,postData,useCache=0){if(!action)throw'Action is missing';if(params=new URLSearchParams(Object.assign({action:action},params||void 0)),useCache>=1&&!postData){if(ajaxRequestsCache.has(params.toString()))return ajaxRequestsCache.get(params.toString());if(useCache>=2){if(!ajaxCache&&'ajaxCache'in sessionStorage)try{ajaxCache=new Map(JSON.parse(sessionStorage.getItem('ajaxCache')))}catch(e){console.warn('AJAX static cache is invalid:',e)}if(ajaxCache||(ajaxCache=new Map),ajaxCache.has(params.toString()))return Promise.resolve(ajaxCache.get(params.toString()))}}const worker=new Promise((function(resolve,reject){let xhr=new XMLHttpRequest,retryCounter=0;const url='/ajax.php?'+params.toString();if(postData&&!(postData instanceof URLSearchParams))switch(typeof postData){case'object':postData=new URLSearchParams(postData);break;case'string':try{postData=new URLSearchParams(JSON.parse(postData))}catch(e){}}postData=postData instanceof URLSearchParams?postData.toString():void 0,function attempt(){gazelleApiMutex.lock((function(){gazelleApiMaxRetries>0&&retryCounter>gazelleApiMaxRetries&&reject(`Retry count exceeded limit (${gazelleApiMaxRetries})`);let apiTimeFrame,timeStamp=Date.now();if("AJAX time frame"in window.localStorage)try{apiTimeFrame=JSON.parse(window.localStorage["AJAX time frame"])}catch(e){apiTimeFrame={}}else apiTimeFrame={};!apiTimeFrame.timeLock||timeStamp>apiTimeFrame.timeLock?(apiTimeFrame.timeLock=timeStamp+1e4+gazelleApiFrameReserve,apiTimeFrame.requestCounter=1):++apiTimeFrame.requestCounter,window.localStorage["AJAX time frame"]=JSON.stringify(apiTimeFrame),gazelleApiMutex.unlock(),apiTimeFrame.requestCounter<=5?(xhr.open(postData?'POST':'GET',url,!0),xhr.setRequestHeader('Accept','application/json'),postData&&xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded; charset=utf-8'),ajaxApiKey&&xhr.setRequestHeader('Authorization',ajaxApiKey),xhr.setRequestHeader('X-Requested-With','XMLHttpRequest'),xhr.responseType='json',xhr.timeout=12e4,xhr.onload=function(){if(404==xhr.status)reject('not found');else if(429==xhr.status&&'rate limit exceeded'==xhr.response.error)console.debug(xhr.response.error+':','action='+action,apiTimeFrame,timeStamp,retryCounter),++retryCounter,setTimeout(attempt,apiTimeFrame.timeLock-timeStamp),'function'==typeof ajaxApiLogger&&ajaxApiLogger(action,apiTimeFrame,timeStamp);else if([500,502,504].includes(xhr.status))defaultErrorHandler(xhr),++retryCounter,attempt();else if(xhr.status<200||xhr.status>=400)reject(defaultErrorHandler(xhr));else if('success'==xhr.response.status){if(useCache>=2&&!domStorageLimitReached&&!postData){ajaxCache.set(params.toString(),xhr.response.response);const serialized=JSON.stringify(Array.from(ajaxCache));try{sessionStorage.setItem('ajaxCache',serialized),ajaxLastCachedSuccess=serialized}catch(e){console.warn(e,`(${serialized.length})`),(/\b(?:NS_ERROR_DOM_QUOTA_REACHED)\b/.test(e)||e instanceof DOMException&&'QuotaExceededError'==e.name)&&(domStorageLimitReached=!0,ajaxLastCachedSuccess&&(sessionStorage.setItem('ajaxCache',ajaxLastCachedSuccess),ajaxLastCachedSuccess=void 0))}}resolve(xhr.response.response)}else{if(console.debug(xhr.response.error+':','action='+action,apiTimeFrame,timeStamp,retryCounter),'rate limit exceeded'==xhr.response.error)return++retryCounter,setTimeout(attempt,apiTimeFrame.timeLock-timeStamp);console.warn('queryAjaxAPI.attempt(…):',xhr.response.status,xhr.response.error),reject(xhr.response.status+': '+xhr.response.error)}},xhr.onerror=function(){[500,502,504].includes(xhr.status)?(defaultErrorHandler(xhr),++retryCounter,attempt()):reject(defaultTimeoutHandler(xhr))},xhr.ontimeout=function(){defaultTimeoutHandler(xhr),//reject(defaultTimeoutHandler(xhr));
++retryCounter,attempt()},xhr.timeout=2e4,xhr.send(postData)):(setTimeout(attempt,apiTimeFrame.timeLock-timeStamp),'function'==typeof ajaxApiLogger&&ajaxApiLogger(action,apiTimeFrame,timeStamp),console.debug('AJAX API request quota exceeded: action='+action,apiTimeFrame,timeStamp,retryCounter))}))}()}));return useCache>=1&&!postData&&ajaxRequestsCache.set(params.toString(),worker),worker}const queryAjaxAPICached=(action,params,useStaticCache=!1)=>queryAjaxAPI(action,params,void 0,useStaticCache?2:1),ajaxGetArtist=artistName=>queryAjaxAPI('artist',{artistname:artistName}),ajaxGetRequest=id=>queryAjaxAPI('request',{id:id});function defaultErrorHandler(response){console.error('HTTP error:',response);let e='HTTP error '+response.status;return response.statusText&&(e+=' ('+response.statusText+')'),response.error&&(e+=' ('+response.error+')'),e}function defaultTimeoutHandler(response){console.error('HTTP timeout:',response);return'HTTP timeout'}