From dc9106dfb3426482b298f05d27e5d6ba72053cb6 Mon Sep 17 00:00:00 2001 From: Hazelnoot Date: Tue, 29 Apr 2025 16:07:56 -0400 Subject: [PATCH] remove outdated packages from megalodon --- .../src/server/oauth/OAuth2ProviderService.ts | 2 +- packages/megalodon/package.json | 17 +- packages/megalodon/src/detector.ts | 8 - packages/megalodon/src/index.ts | 5 +- packages/megalodon/src/megalodon.ts | 20 - packages/megalodon/src/misskey.ts | 33 +- packages/megalodon/src/misskey/api_client.ts | 43 +- packages/megalodon/src/misskey/web_socket.ts | 413 ------------------ packages/megalodon/src/proxy_config.ts | 50 --- pnpm-lock.yaml | 101 +---- 10 files changed, 9 insertions(+), 683 deletions(-) delete mode 100644 packages/megalodon/src/misskey/web_socket.ts delete mode 100644 packages/megalodon/src/proxy_config.ts diff --git a/packages/backend/src/server/oauth/OAuth2ProviderService.ts b/packages/backend/src/server/oauth/OAuth2ProviderService.ts index b7e09633ed..a65acb7c9b 100644 --- a/packages/backend/src/server/oauth/OAuth2ProviderService.ts +++ b/packages/backend/src/server/oauth/OAuth2ProviderService.ts @@ -156,7 +156,7 @@ export class OAuth2ProviderService { const secret = String(body.client_secret); const code = body.code ? String(body.code) : ''; - // TODO fetch the access token directly + // TODO fetch the access token directly, then remove all oauth code from megalodon const client = this.mastodonClientService.getClient(request); const atData = await client.fetchAccessToken(clientId, secret, code); diff --git a/packages/megalodon/package.json b/packages/megalodon/package.json index 1ceb47759d..f10a9cf9dc 100644 --- a/packages/megalodon/package.json +++ b/packages/megalodon/package.json @@ -54,25 +54,13 @@ }, "homepage": "https://github.com/h3poteto/megalodon#readme", "dependencies": { - "@types/core-js": "^2.5.8", - "@types/form-data": "^2.5.0", "@types/jest": "^29.5.10", "@types/oauth": "^0.9.4", - "@types/object-assign-deep": "^0.4.3", - "@types/parse-link-header": "^2.0.3", - "@types/uuid": "^9.0.7", - "@types/ws": "^8.5.10", "axios": "1.7.4", "dayjs": "^1.11.10", "form-data": "4.0.2", - "https-proxy-agent": "^7.0.2", "oauth": "0.10.2", - "object-assign-deep": "^0.4.0", - "parse-link-header": "^2.0.0", - "socks-proxy-agent": "^8.0.2", - "typescript": "5.8.3", - "uuid": "11.1.0", - "ws": "8.17.1" + "typescript": "5.8.3" }, "devDependencies": { "@typescript-eslint/eslint-plugin": "8.31.0", @@ -80,8 +68,7 @@ "eslint": "9.25.1", "eslint-config-prettier": "^9.0.0", "jest": "29.7.0", - "jest-worker": "^29.7.0", - "lodash": "4.17.21", + "jest-worker": "29.7.0", "prettier": "3.5.3", "ts-jest": "^29.1.1" } diff --git a/packages/megalodon/src/detector.ts b/packages/megalodon/src/detector.ts index 31f34d72f7..ba95d96816 100644 --- a/packages/megalodon/src/detector.ts +++ b/packages/megalodon/src/detector.ts @@ -1,5 +1,4 @@ import axios, { AxiosRequestConfig } from 'axios' -import proxyAgent, { ProxyConfig } from './proxy_config' import { NodeinfoError } from './megalodon' const NODEINFO_10 = 'http://nodeinfo.diaspora.software/ns/schema/1.0' @@ -45,21 +44,14 @@ type Metadata = { * Now support Mastodon, Pleroma and Pixelfed. Throws an error when no known platform can be detected. * * @param url Base URL of SNS. - * @param proxyConfig Proxy setting, or set false if don't use proxy. * @return SNS name. */ export const detector = async ( url: string, - proxyConfig: ProxyConfig | false = false ): Promise<'mastodon' | 'pleroma' | 'misskey' | 'friendica'> => { let options: AxiosRequestConfig = { timeout: 20000 } - if (proxyConfig) { - options = Object.assign(options, { - httpsAgent: proxyAgent(proxyConfig) - }) - } const res = await axios.get(url + '/.well-known/nodeinfo', options) const link = res.data.links.find(l => l.rel === NODEINFO_20 || l.rel === NODEINFO_21) diff --git a/packages/megalodon/src/index.ts b/packages/megalodon/src/index.ts index 7a4f10ab02..50663c3ce5 100644 --- a/packages/megalodon/src/index.ts +++ b/packages/megalodon/src/index.ts @@ -1,8 +1,7 @@ import Response from './response' import OAuth from './oauth' import { isCancel, RequestCanceledError } from './cancel' -import { ProxyConfig } from './proxy_config' -import { MegalodonInterface, WebSocketInterface } from './megalodon' +import { MegalodonInterface } from './megalodon' import { detector } from './detector' import Misskey from './misskey' import Entity from './entity' @@ -16,10 +15,8 @@ export { OAuth, RequestCanceledError, isCancel, - ProxyConfig, detector, MegalodonInterface, - WebSocketInterface, NotificationType, FilterContext, Misskey, diff --git a/packages/megalodon/src/megalodon.ts b/packages/megalodon/src/megalodon.ts index 6032c351c9..4257e545df 100644 --- a/packages/megalodon/src/megalodon.ts +++ b/packages/megalodon/src/megalodon.ts @@ -2,16 +2,6 @@ import Response from './response' import OAuth from './oauth' import Entity from './entity' -export interface WebSocketInterface { - start(): void - stop(): void - // EventEmitter - on(event: string | symbol, listener: (...args: any[]) => void): this - once(event: string | symbol, listener: (...args: any[]) => void): this - removeListener(event: string | symbol, listener: (...args: any[]) => void): this - removeAllListeners(event?: string | symbol): this -} - export interface MegalodonInterface { /** * Cancel all requests in this instance. @@ -1361,16 +1351,6 @@ export interface MegalodonInterface { * @return Reaction. **/ getEmojiReaction(id: string, emoji: string): Promise> - - // ====================================== - // WebSocket - // ====================================== - userSocket(): WebSocketInterface - publicSocket(): WebSocketInterface - localSocket(): WebSocketInterface - tagSocket(tag: string): WebSocketInterface - listSocket(list_id: string): WebSocketInterface - directSocket(): WebSocketInterface } export class NoImplementedError extends Error { diff --git a/packages/megalodon/src/misskey.ts b/packages/megalodon/src/misskey.ts index eb1e5824b8..670b31e838 100644 --- a/packages/megalodon/src/misskey.ts +++ b/packages/megalodon/src/misskey.ts @@ -2,28 +2,24 @@ import FormData from 'form-data' import fs from 'fs'; import MisskeyAPI from './misskey/api_client' import { DEFAULT_UA } from './default' -import { ProxyConfig } from './proxy_config' import OAuth from './oauth' import Response from './response' -import { MegalodonInterface, WebSocketInterface, NoImplementedError, ArgumentError, UnexpectedError } from './megalodon' +import { MegalodonInterface, NoImplementedError, ArgumentError, UnexpectedError } from './megalodon' import { UnknownNotificationTypeError } from './notification' export default class Misskey implements MegalodonInterface { public client: MisskeyAPI.Interface public baseUrl: string - public proxyConfig: ProxyConfig | false /** * @param baseUrl hostname or base URL * @param accessToken access token from OAuth2 authorization * @param userAgent UserAgent is specified in header on request. - * @param proxyConfig Proxy setting, or set false if don't use proxy. */ constructor( baseUrl: string, accessToken: string | null = null, userAgent: string | null = DEFAULT_UA, - proxyConfig: ProxyConfig | false = false ) { let token: string = '' if (accessToken) { @@ -33,9 +29,8 @@ export default class Misskey implements MegalodonInterface { if (userAgent) { agent = userAgent } - this.client = new MisskeyAPI.Client(baseUrl, token, agent, proxyConfig) + this.client = new MisskeyAPI.Client(baseUrl, token, agent) this.baseUrl = baseUrl - this.proxyConfig = proxyConfig } public cancel(): void { @@ -2562,28 +2557,4 @@ export default class Misskey implements MegalodonInterface { reject(err) }) } - - public userSocket(): WebSocketInterface { - return this.client.socket('user') - } - - public publicSocket(): WebSocketInterface { - return this.client.socket('globalTimeline') - } - - public localSocket(): WebSocketInterface { - return this.client.socket('localTimeline') - } - - public tagSocket(_tag: string): WebSocketInterface { - throw new NoImplementedError('TODO: implement') - } - - public listSocket(list_id: string): WebSocketInterface { - return this.client.socket('list', list_id) - } - - public directSocket(): WebSocketInterface { - return this.client.socket('conversation') - } } diff --git a/packages/megalodon/src/misskey/api_client.ts b/packages/megalodon/src/misskey/api_client.ts index 4d97ae497c..17a59c7c76 100644 --- a/packages/megalodon/src/misskey/api_client.ts +++ b/packages/megalodon/src/misskey/api_client.ts @@ -3,11 +3,9 @@ import dayjs from 'dayjs' import FormData from 'form-data' import { DEFAULT_UA } from '../default' -import proxyAgent, { ProxyConfig } from '../proxy_config' import Response from '../response' import MisskeyEntity from './entity' import MegalodonEntity from '../entity' -import WebSocket from './web_socket' import MisskeyNotificationType from './notification' import * as NotificationType from '../notification' import { UnknownNotificationTypeError } from '../notification'; @@ -555,32 +553,28 @@ namespace MisskeyAPI { get(path: string, params?: any, headers?: { [key: string]: string }): Promise> post(path: string, params?: any, headers?: { [key: string]: string }): Promise> cancel(): void - socket(channel: 'user' | 'localTimeline' | 'hybridTimeline' | 'globalTimeline' | 'conversation' | 'list', listId?: string): WebSocket } /** * Misskey API client. * - * Usign axios for request, you will handle promises. + * Using axios for request, you will handle promises. */ export class Client implements Interface { private accessToken: string | null private baseUrl: string private userAgent: string private abortController: AbortController - private proxyConfig: ProxyConfig | false = false /** * @param baseUrl hostname or base URL * @param accessToken access token from OAuth2 authorization * @param userAgent UserAgent is specified in header on request. - * @param proxyConfig Proxy setting, or set false if don't use proxy. */ - constructor(baseUrl: string, accessToken: string | null, userAgent: string = DEFAULT_UA, proxyConfig: ProxyConfig | false = false) { + constructor(baseUrl: string, accessToken: string | null, userAgent: string = DEFAULT_UA) { this.accessToken = accessToken this.baseUrl = baseUrl this.userAgent = userAgent - this.proxyConfig = proxyConfig this.abortController = new AbortController() axios.defaults.signal = this.abortController.signal } @@ -595,12 +589,6 @@ namespace MisskeyAPI { maxContentLength: Infinity, maxBodyLength: Infinity } - if (this.proxyConfig) { - options = Object.assign(options, { - httpAgent: proxyAgent(this.proxyConfig), - httpsAgent: proxyAgent(this.proxyConfig) - }) - } return axios.get(this.baseUrl + path, options).then((resp: AxiosResponse) => { const res: Response = { data: resp.data, @@ -624,12 +612,6 @@ namespace MisskeyAPI { maxContentLength: Infinity, maxBodyLength: Infinity } - if (this.proxyConfig) { - options = Object.assign(options, { - httpAgent: proxyAgent(this.proxyConfig), - httpsAgent: proxyAgent(this.proxyConfig) - }) - } let bodyParams = params if (this.accessToken) { if (params instanceof FormData) { @@ -658,27 +640,6 @@ namespace MisskeyAPI { public cancel(): void { return this.abortController.abort() } - - /** - * Get connection and receive websocket connection for Misskey API. - * - * @param channel Channel name is user, localTimeline, hybridTimeline, globalTimeline, conversation or list. - * @param listId This parameter is required only list channel. - */ - public socket( - channel: 'user' | 'localTimeline' | 'hybridTimeline' | 'globalTimeline' | 'conversation' | 'list', - listId?: string - ): WebSocket { - if (!this.accessToken) { - throw new Error('accessToken is required') - } - const url = this.baseUrl + '/streaming' - const streaming = new WebSocket(url, channel, this.accessToken, listId, this.userAgent, this.proxyConfig) - process.nextTick(() => { - streaming.start() - }) - return streaming - } } } diff --git a/packages/megalodon/src/misskey/web_socket.ts b/packages/megalodon/src/misskey/web_socket.ts deleted file mode 100644 index 181fb1c903..0000000000 --- a/packages/megalodon/src/misskey/web_socket.ts +++ /dev/null @@ -1,413 +0,0 @@ -import WS from 'ws' -import dayjs, { Dayjs } from 'dayjs' -import { v4 as uuid } from 'uuid' -import { EventEmitter } from 'events' -import { WebSocketInterface } from '../megalodon' -import proxyAgent, { ProxyConfig } from '../proxy_config' -import MisskeyAPI from './api_client' -import { UnknownNotificationTypeError } from '../notification' - -/** - * WebSocket - * Misskey is not support http streaming. It supports websocket instead of streaming. - * So this class connect to Misskey server with WebSocket. - */ -export default class WebSocket extends EventEmitter implements WebSocketInterface { - public url: string - public channel: 'user' | 'localTimeline' | 'hybridTimeline' | 'globalTimeline' | 'conversation' | 'list' - public parser: Parser - public headers: { [key: string]: string } - public proxyConfig: ProxyConfig | false = false - public listId: string | null = null - private _accessToken: string - private _reconnectInterval: number - private _reconnectMaxAttempts: number - private _reconnectCurrentAttempts: number - private _connectionClosed: boolean - private _client: WS | null = null - private _channelID: string - private _pongReceivedTimestamp: Dayjs - private _heartbeatInterval: number = 60000 - private _pongWaiting: boolean = false - - /** - * @param url Full url of websocket: e.g. wss://misskey.io/streaming - * @param channel Channel name is user, localTimeline, hybridTimeline, globalTimeline, conversation or list. - * @param accessToken The access token. - * @param listId This parameter is required when you specify list as channel. - */ - constructor( - url: string, - channel: 'user' | 'localTimeline' | 'hybridTimeline' | 'globalTimeline' | 'conversation' | 'list', - accessToken: string, - listId: string | undefined, - userAgent: string, - proxyConfig: ProxyConfig | false = false - ) { - super() - this.url = url - this.parser = new Parser() - this.channel = channel - this.headers = { - 'User-Agent': userAgent - } - if (listId === undefined) { - this.listId = null - } else { - this.listId = listId - } - this.proxyConfig = proxyConfig - this._accessToken = accessToken - this._reconnectInterval = 10000 - this._reconnectMaxAttempts = Infinity - this._reconnectCurrentAttempts = 0 - this._connectionClosed = false - this._channelID = uuid() - this._pongReceivedTimestamp = dayjs() - } - - /** - * Start websocket connection. - */ - public start() { - this._connectionClosed = false - this._resetRetryParams() - this._startWebSocketConnection() - } - - /** - * Reset connection and start new websocket connection. - */ - private _startWebSocketConnection() { - this._resetConnection() - this._setupParser() - this._client = this._connect() - this._bindSocket(this._client) - } - - /** - * Stop current connection. - */ - public stop() { - this._connectionClosed = true - this._resetConnection() - this._resetRetryParams() - } - - /** - * Clean up current connection, and listeners. - */ - private _resetConnection() { - if (this._client) { - this._client.close(1000) - this._client.removeAllListeners() - this._client = null - } - - if (this.parser) { - this.parser.removeAllListeners() - } - } - - /** - * Resets the parameters used in reconnect. - */ - private _resetRetryParams() { - this._reconnectCurrentAttempts = 0 - } - - /** - * Connect to the endpoint. - */ - private _connect(): WS { - let options: WS.ClientOptions = { - headers: this.headers - } - if (this.proxyConfig) { - options = Object.assign(options, { - agent: proxyAgent(this.proxyConfig) - }) - } - const cli: WS = new WS(`${this.url}?i=${this._accessToken}`, options) - return cli - } - - /** - * Connect specified channels in websocket. - */ - private _channel() { - if (!this._client) { - return - } - switch (this.channel) { - case 'conversation': - this._client.send( - JSON.stringify({ - type: 'connect', - body: { - channel: 'main', - id: this._channelID - } - }) - ) - break - case 'user': - this._client.send( - JSON.stringify({ - type: 'connect', - body: { - channel: 'main', - id: this._channelID - } - }) - ) - this._client.send( - JSON.stringify({ - type: 'connect', - body: { - channel: 'homeTimeline', - id: this._channelID - } - }) - ) - break - case 'list': - this._client.send( - JSON.stringify({ - type: 'connect', - body: { - channel: 'userList', - id: this._channelID, - params: { - listId: this.listId - } - } - }) - ) - break - default: - this._client.send( - JSON.stringify({ - type: 'connect', - body: { - channel: this.channel, - id: this._channelID - } - }) - ) - break - } - } - - /** - * Reconnects to the same endpoint. - */ - - private _reconnect() { - setTimeout(() => { - // Skip reconnect when client is connecting. - // https://github.com/websockets/ws/blob/7.2.1/lib/websocket.js#L365 - if (this._client && this._client.readyState === WS.CONNECTING) { - return - } - - if (this._reconnectCurrentAttempts < this._reconnectMaxAttempts) { - this._reconnectCurrentAttempts++ - this._clearBinding() - if (this._client) { - // In reconnect, we want to close the connection immediately, - // because recoonect is necessary when some problems occur. - this._client.terminate() - } - // Call connect methods - console.log('Reconnecting') - this._client = this._connect() - this._bindSocket(this._client) - } - }, this._reconnectInterval) - } - - /** - * Clear binding event for websocket client. - */ - private _clearBinding() { - if (this._client) { - this._client.removeAllListeners('close') - this._client.removeAllListeners('pong') - this._client.removeAllListeners('open') - this._client.removeAllListeners('message') - this._client.removeAllListeners('error') - } - } - - /** - * Bind event for web socket client. - * @param client A WebSocket instance. - */ - private _bindSocket(client: WS) { - client.on('close', (code: number, _reason: Buffer) => { - if (code === 1000) { - this.emit('close', {}) - } else { - console.log(`Closed connection with ${code}`) - if (!this._connectionClosed) { - this._reconnect() - } - } - }) - client.on('pong', () => { - this._pongWaiting = false - this.emit('pong', {}) - this._pongReceivedTimestamp = dayjs() - // It is required to anonymous function since get this scope in checkAlive. - setTimeout(() => this._checkAlive(this._pongReceivedTimestamp), this._heartbeatInterval) - }) - client.on('open', () => { - this.emit('connect', {}) - this._channel() - // Call first ping event. - setTimeout(() => { - client.ping('') - }, 10000) - }) - client.on('message', (data: WS.Data, isBinary: boolean) => { - this.parser.parse(data, isBinary, this._channelID) - }) - client.on('error', (err: Error) => { - this.emit('error', err) - }) - } - - /** - * Set up parser when receive message. - */ - private _setupParser() { - this.parser.on('update', (note: MisskeyAPI.Entity.Note) => { - this.emit('update', MisskeyAPI.Converter.note(note)) - }) - this.parser.on('notification', (notification: MisskeyAPI.Entity.Notification) => { - const n = MisskeyAPI.Converter.notification(notification) - if (n instanceof UnknownNotificationTypeError) { - console.warn(`Unknown notification event has received: ${notification}`) - } else { - this.emit('notification', n) - } - }) - this.parser.on('conversation', (note: MisskeyAPI.Entity.Note) => { - this.emit('conversation', MisskeyAPI.Converter.noteToConversation(note)) - }) - this.parser.on('error', (err: Error) => { - this.emit('parser-error', err) - }) - } - - /** - * Call ping and wait to pong. - */ - private _checkAlive(timestamp: Dayjs) { - const now: Dayjs = dayjs() - // Block multiple calling, if multiple pong event occur. - // It the duration is less than interval, through ping. - if (now.diff(timestamp) > this._heartbeatInterval - 1000 && !this._connectionClosed) { - // Skip ping when client is connecting. - // https://github.com/websockets/ws/blob/7.2.1/lib/websocket.js#L289 - if (this._client && this._client.readyState !== WS.CONNECTING) { - this._pongWaiting = true - this._client.ping('') - setTimeout(() => { - if (this._pongWaiting) { - this._pongWaiting = false - this._reconnect() - } - }, 10000) - } - } - } -} - -/** - * Parser - * This class provides parser for websocket message. - */ -export class Parser extends EventEmitter { - /** - * @param message Message body of websocket. - * @param channelID Parse only messages which has same channelID. - */ - public parse(data: WS.Data, isBinary: boolean, channelID: string) { - const message = isBinary ? data : data.toString() - if (typeof message !== 'string') { - this.emit('heartbeat', {}) - return - } - - if (message === '') { - this.emit('heartbeat', {}) - return - } - - let obj: { - type: string - body: { - id: string - type: string - body: any - } - } - let body: { - id: string - type: string - body: any - } - - try { - obj = JSON.parse(message) - if (obj.type !== 'channel') { - return - } - if (!obj.body) { - return - } - body = obj.body - if (body.id !== channelID) { - return - } - } catch (err) { - this.emit('error', new Error(`Error parsing websocket reply: ${message}, error message: ${err}`)) - return - } - - switch (body.type) { - case 'note': - this.emit('update', body.body as MisskeyAPI.Entity.Note) - break - case 'notification': - this.emit('notification', body.body as MisskeyAPI.Entity.Notification) - break - case 'mention': { - const note = body.body as MisskeyAPI.Entity.Note - if (note.visibility === 'specified') { - this.emit('conversation', note) - } - break - } - // When renote and followed event, the same notification will be received. - case 'renote': - case 'followed': - case 'follow': - case 'unfollow': - case 'receiveFollowRequest': - case 'meUpdated': - case 'readAllNotifications': - case 'readAllUnreadSpecifiedNotes': - case 'readAllAntennas': - case 'readAllUnreadMentions': - case 'unreadNotification': - // Ignore these events - break - default: - this.emit('error', new Error(`Unknown event has received: ${JSON.stringify(body)}`)) - break - } - } -} diff --git a/packages/megalodon/src/proxy_config.ts b/packages/megalodon/src/proxy_config.ts deleted file mode 100644 index c9ae01b736..0000000000 --- a/packages/megalodon/src/proxy_config.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { HttpsProxyAgent } from 'https-proxy-agent' -import { SocksProxyAgent } from 'socks-proxy-agent' - -export type ProxyConfig = { - host: string - port: number - auth?: { - username: string - password: string - } - protocol: 'http' | 'https' | 'socks4' | 'socks4a' | 'socks5' | 'socks5h' | 'socks' -} - -class ProxyProtocolError extends Error {} - -const proxyAgent = (proxyConfig: ProxyConfig): HttpsProxyAgent<'http'> | HttpsProxyAgent<'https'> | SocksProxyAgent => { - switch (proxyConfig.protocol) { - case 'http': { - let url = new URL(`http://${proxyConfig.host}:${proxyConfig.port}`) - if (proxyConfig.auth) { - url = new URL(`http://${proxyConfig.auth.username}:${proxyConfig.auth.password}@${proxyConfig.host}:${proxyConfig.port}`) - } - const httpsAgent = new HttpsProxyAgent<'http'>(url) - return httpsAgent - } - case 'https': { - let url = new URL(`https://${proxyConfig.host}:${proxyConfig.port}`) - if (proxyConfig.auth) { - url = new URL(`https://${proxyConfig.auth.username}:${proxyConfig.auth.password}@${proxyConfig.host}:${proxyConfig.port}`) - } - const httpsAgent = new HttpsProxyAgent<'https'>(url) - return httpsAgent - } - case 'socks4': - case 'socks4a': - case 'socks5': - case 'socks5h': - case 'socks': { - let url = `socks://${proxyConfig.host}:${proxyConfig.port}` - if (proxyConfig.auth) { - url = `socks://${proxyConfig.auth.username}:${proxyConfig.auth.password}@${proxyConfig.host}:${proxyConfig.port}` - } - const socksAgent = new SocksProxyAgent(url) - return socksAgent - } - default: - throw new ProxyProtocolError('protocol is not accepted') - } -} -export default proxyAgent diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a99abba6e4..73ce445599 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1301,30 +1301,12 @@ importers: packages/megalodon: dependencies: - '@types/core-js': - specifier: ^2.5.8 - version: 2.5.8 - '@types/form-data': - specifier: ^2.5.0 - version: 2.5.2 '@types/jest': specifier: ^29.5.10 version: 29.5.12 '@types/oauth': specifier: ^0.9.4 version: 0.9.6 - '@types/object-assign-deep': - specifier: ^0.4.3 - version: 0.4.3 - '@types/parse-link-header': - specifier: ^2.0.3 - version: 2.0.3 - '@types/uuid': - specifier: ^9.0.7 - version: 9.0.8 - '@types/ws': - specifier: ^8.5.10 - version: 8.18.0 axios: specifier: 1.7.4 version: 1.7.4 @@ -1334,30 +1316,12 @@ importers: form-data: specifier: 4.0.2 version: 4.0.2 - https-proxy-agent: - specifier: ^7.0.2 - version: 7.0.2 oauth: specifier: 0.10.2 version: 0.10.2 - object-assign-deep: - specifier: ^0.4.0 - version: 0.4.0 - parse-link-header: - specifier: ^2.0.0 - version: 2.0.0 - socks-proxy-agent: - specifier: ^8.0.2 - version: 8.0.2 typescript: specifier: 5.8.3 version: 5.8.3 - uuid: - specifier: 11.1.0 - version: 11.1.0 - ws: - specifier: 8.17.1 - version: 8.17.1(bufferutil@4.0.9)(utf-8-validate@6.0.5) devDependencies: '@typescript-eslint/eslint-plugin': specifier: 8.31.0 @@ -1375,11 +1339,8 @@ importers: specifier: 29.7.0 version: 29.7.0(@types/node@22.15.2) jest-worker: - specifier: ^29.7.0 + specifier: 29.7.0 version: 29.7.0 - lodash: - specifier: 4.17.21 - version: 4.17.21 prettier: specifier: 3.5.3 version: 3.5.3 @@ -4200,9 +4161,6 @@ packages: '@types/cookiejar@2.1.5': resolution: {integrity: sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==} - '@types/core-js@2.5.8': - resolution: {integrity: sha512-VgnAj6tIAhJhZdJ8/IpxdatM8G4OD3VWGlp6xIxUGENZlpbob9Ty4VVdC1FIEp0aK6DBscDDjyzy5FB60TuNqg==} - '@types/debug@4.1.12': resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} @@ -4227,10 +4185,6 @@ packages: '@types/fluent-ffmpeg@2.1.27': resolution: {integrity: sha512-QiDWjihpUhriISNoBi2hJBRUUmoj/BMTYcfz+F+ZM9hHWBYABFAE6hjP/TbCZC0GWwlpa3FzvHH9RzFeRusZ7A==} - '@types/form-data@2.5.2': - resolution: {integrity: sha512-tfmcyHn1Pp9YHAO5r40+UuZUPAZbUEgqTel3EuEKpmF9hPkXgR4l41853raliXnb4gwyPNoQOfvgGGlHN5WSog==} - deprecated: This is a stub types definition. form-data provides its own type definitions, so you do not need this installed. - '@types/graceful-fs@4.1.6': resolution: {integrity: sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==} @@ -4333,12 +4287,6 @@ packages: '@types/oauth@0.9.6': resolution: {integrity: sha512-H9TRCVKBNOhZZmyHLqFt9drPM9l+ShWiqqJijU1B8P3DX3ub84NjxDuy+Hjrz+fEca5Kwip3qPMKNyiLgNJtIA==} - '@types/object-assign-deep@0.4.3': - resolution: {integrity: sha512-d9Gxaj5j1hzrxJ61EFEg13B4g4FgrT/DYtcDWFXPehR8DF2SUZbVMFtZIs8exkVRiqrqBpdTc/lUUZjncsPpMw==} - - '@types/parse-link-header@2.0.3': - resolution: {integrity: sha512-ffLAxD6Xqcf2gSbtEJehj8yJ5R/2OZqD4liodQvQQ+hhO4kg1mk9ToEZQPMtNTm/zIQj2GNleQbsjPp9+UQm4Q==} - '@types/pg-pool@2.0.6': resolution: {integrity: sha512-TaAUE5rq2VQYxab5Ts7WZhKNmuN78Q6PiFonTDdpbx8a1H0M1vhy3rhiMjl+e2iHmogyMw7jZF4FrE6eJUy5HQ==} @@ -4471,9 +4419,6 @@ packages: '@types/web-push@3.6.4': resolution: {integrity: sha512-GnJmSr40H3RAnj0s34FNTcJi1hmWFV5KXugE0mYWnYhgTAHLJ/dJKAwDmvPJYMke0RplY2XE9LnM4hqSqKIjhQ==} - '@types/ws@8.18.0': - resolution: {integrity: sha512-8svvI3hMyvN0kKCJMvTJP/x6Y/EoQbepff882wL+Sn5QsXb3etnamgrJq4isrBxSJj5L2AuXcI0+bgkoAXGUJw==} - '@types/ws@8.18.1': resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} @@ -8296,10 +8241,6 @@ packages: oauth@0.10.2: resolution: {integrity: sha512-JtFnB+8nxDEXgNyniwz573xxbKSOu3R8D40xQKqcjwJ2CDkYqUDI53o6IuzDJBx60Z8VKCm271+t8iFjakrl8Q==} - object-assign-deep@0.4.0: - resolution: {integrity: sha512-54Uvn3s+4A/cMWx9tlRez1qtc7pN7pbQ+Yi7mjLjcBpWLlP+XbSHiHbQW6CElDiV4OvuzqnMrBdkgxI1mT8V/Q==} - engines: {node: '>=6'} - object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -8459,9 +8400,6 @@ packages: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} - parse-link-header@2.0.0: - resolution: {integrity: sha512-xjU87V0VyHZybn2RrCX5TIFGxTVZE6zqqZWMPlIKiSKuWh/X5WZdt+w1Ki1nXB+8L/KtL+nZ4iq+sfI6MrhhMw==} - parse-ms@4.0.0: resolution: {integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==} engines: {node: '>=18'} @@ -10798,18 +10736,6 @@ packages: resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - ws@8.17.1: - resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - ws@8.18.1: resolution: {integrity: sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==} engines: {node: '>=10.0.0'} @@ -14414,8 +14340,6 @@ snapshots: '@types/cookiejar@2.1.5': {} - '@types/core-js@2.5.8': {} - '@types/debug@4.1.12': dependencies: '@types/ms': 0.7.34 @@ -14448,10 +14372,6 @@ snapshots: dependencies: '@types/node': 22.15.2 - '@types/form-data@2.5.2': - dependencies: - form-data: 4.0.2 - '@types/graceful-fs@4.1.6': dependencies: '@types/node': 22.15.2 @@ -14557,10 +14477,6 @@ snapshots: dependencies: '@types/node': 22.15.2 - '@types/object-assign-deep@0.4.3': {} - - '@types/parse-link-header@2.0.3': {} - '@types/pg-pool@2.0.6': dependencies: '@types/pg': 8.11.14 @@ -14692,10 +14608,6 @@ snapshots: dependencies: '@types/node': 22.15.2 - '@types/ws@8.18.0': - dependencies: - '@types/node': 22.15.2 - '@types/ws@8.18.1': dependencies: '@types/node': 22.15.2 @@ -19585,8 +19497,6 @@ snapshots: oauth@0.10.2: {} - object-assign-deep@0.4.0: {} - object-assign@4.1.1: {} object-inspect@1.12.3: {} @@ -19755,10 +19665,6 @@ snapshots: json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 - parse-link-header@2.0.0: - dependencies: - xtend: 4.0.2 - parse-ms@4.0.0: {} parse-srcset@1.0.2: {} @@ -22273,11 +22179,6 @@ snapshots: imurmurhash: 0.1.4 signal-exit: 3.0.7 - ws@8.17.1(bufferutil@4.0.9)(utf-8-validate@6.0.5): - optionalDependencies: - bufferutil: 4.0.9 - utf-8-validate: 6.0.5 - ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@6.0.5): optionalDependencies: bufferutil: 4.0.9