postiz/libraries/nestjs-libraries/src/integrations/social.abstract.ts

110 lines
2.6 KiB
TypeScript

import { timer } from '@gitroom/helpers/utils/timer';
import pThrottle from 'p-throttle';
export class RefreshToken {
constructor(
public identifier: string,
public json: string,
public body: BodyInit,
public message = ''
) {}
}
export class BadBody {
constructor(
public identifier: string,
public json: string,
public body: BodyInit,
public message = ''
) {}
}
export class NotEnoughScopes {
constructor(public message = 'Not enough scopes') {}
}
const pThrottleInstance = pThrottle({
limit: 1,
interval: 5000,
});
export abstract class SocialAbstract {
private fetchInstance = pThrottleInstance(
(url: RequestInfo, options?: RequestInit) => fetch(url, options)
);
public handleErrors(
body: string
): { type: 'refresh-token' | 'bad-body'; value: string } | undefined {
return { type: 'bad-body', value: 'bad request' };
}
async fetch(
url: string,
options: RequestInit = {},
identifier = '',
totalRetries = 0
): Promise<Response> {
const request = await this.fetchInstance(url, options);
if (request.status === 200 || request.status === 201) {
return request;
}
if (totalRetries > 2) {
console.log('bad body retries');
throw new BadBody(identifier, '{}', options.body || '{}');
}
let json = '{}';
try {
json = await request.text();
console.log(json);
} catch (err) {
json = '{}';
}
if (json.includes('rate_limit_exceeded') || json.includes('Rate limit')) {
await timer(5000);
console.log('rate limit trying again');
return this.fetch(url, options, identifier, totalRetries + 1);
}
const handleError = this.handleErrors(json || '{}') || {
type: 'bad-body',
value: '',
};
if (request.status === 401 || handleError?.type === 'refresh-token') {
console.log('refresh token');
throw new RefreshToken(
identifier,
json,
options.body!,
handleError?.value
);
}
throw new BadBody(identifier, json, options.body!, handleError?.value);
}
checkScopes(required: string[], got: string | string[]) {
if (Array.isArray(got)) {
if (!required.every((scope) => got.includes(scope))) {
throw new NotEnoughScopes();
}
return true;
}
const newGot = decodeURIComponent(got);
const splitType = newGot.indexOf(',') > -1 ? ',' : ' ';
const gotArray = newGot.split(splitType);
if (!required.every((scope) => gotArray.includes(scope))) {
throw new NotEnoughScopes();
}
return true;
}
}