mirror of
https://github.com/kirameki-cafe/Yumi.git
synced 2026-09-13 18:59:19 +00:00
@@ -32,7 +32,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
language: [ 'typescript' ]
|
language: [ 'javascript' ]
|
||||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||||
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
|
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
"typescript": "^5.0.4",
|
"typescript": "^5.0.4",
|
||||||
"utf-8-validate": "^6.0.3",
|
"utf-8-validate": "^6.0.3",
|
||||||
"validator": "^13.9.0",
|
"validator": "^13.9.0",
|
||||||
|
"vrchat": "^1.11.1",
|
||||||
"winston": "^3.8.2",
|
"winston": "^3.8.2",
|
||||||
"zlib-sync": "^0.1.8"
|
"zlib-sync": "^0.1.8"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,300 @@
|
|||||||
|
import { Message, ActionRowBuilder, ButtonBuilder, CommandInteraction, BaseInteraction, ButtonStyle } from 'discord.js';
|
||||||
|
|
||||||
|
import Prisma from '../../providers/Prisma';
|
||||||
|
import VRChatAPI from '../../providers/VRChatAPI';
|
||||||
|
import validator from 'validator';
|
||||||
|
import DiscordModule, { HybridInteractionMessage } from '../../utils/DiscordModule';
|
||||||
|
import { makeInfoEmbed, makeErrorEmbed, sendHybridInteractionMessageResponse } from '../../utils/DiscordMessage';
|
||||||
|
import Environment from '../../providers/Environment';
|
||||||
|
import ImagePorxy from '../../libs/ImageProxy';
|
||||||
|
|
||||||
|
const EMBEDS = {
|
||||||
|
NO_USER_FOUND: (data: HybridInteractionMessage) => {
|
||||||
|
return makeErrorEmbed({
|
||||||
|
title: `That user doesn't exists on VRChat`,
|
||||||
|
user: data.getUser()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
NO_USER_MENTIONED: (data: HybridInteractionMessage) => {
|
||||||
|
return makeErrorEmbed({
|
||||||
|
title: `No VRChat username or user id provided`,
|
||||||
|
user: data.getUser()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
ERROR: (data: HybridInteractionMessage) => {
|
||||||
|
return makeErrorEmbed({
|
||||||
|
title: `Something went wrong while connecting to VRChat`,
|
||||||
|
user: data.getUser()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class VRChatUser {
|
||||||
|
public static async run(data: HybridInteractionMessage, args: any) {
|
||||||
|
let query;
|
||||||
|
if (data.isMessage()) {
|
||||||
|
if (typeof args[1] === 'undefined')
|
||||||
|
return await sendHybridInteractionMessageResponse(data, {
|
||||||
|
embeds: [EMBEDS.NO_USER_MENTIONED(data)]
|
||||||
|
});
|
||||||
|
const [removed, ...newArgs] = args;
|
||||||
|
query = newArgs.join(' ');
|
||||||
|
} else if (data.isApplicationCommand()) query = data.getSlashCommand().options.get('user')?.value?.toString();
|
||||||
|
|
||||||
|
let user;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (query.startsWith('usr_')) user = await VRChatAPI.getCachedUserById(query);
|
||||||
|
else {
|
||||||
|
let search_result = await VRChatAPI.client!.UsersApi.searchUsers(query, undefined, 100);
|
||||||
|
if (search_result.data.length === 0)
|
||||||
|
return await sendHybridInteractionMessageResponse(data, {
|
||||||
|
embeds: [EMBEDS.NO_USER_FOUND(data)]
|
||||||
|
});
|
||||||
|
|
||||||
|
let foundExact = false;
|
||||||
|
for (let i = 0; i < search_result.data.length; i++) {
|
||||||
|
if (search_result.data[i].displayName.toLowerCase() === query.toLowerCase()) {
|
||||||
|
user = await VRChatAPI.getCachedUserById(search_result.data[i].id);
|
||||||
|
foundExact = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!foundExact) user = await VRChatAPI.getCachedUserById(search_result.data[0].id);
|
||||||
|
}
|
||||||
|
} catch (err: any) {
|
||||||
|
// If 404
|
||||||
|
if (err.response?.status === 404)
|
||||||
|
return await sendHybridInteractionMessageResponse(data, {
|
||||||
|
embeds: [EMBEDS.NO_USER_FOUND(data)]
|
||||||
|
});
|
||||||
|
else
|
||||||
|
return await sendHybridInteractionMessageResponse(data, {
|
||||||
|
embeds: [EMBEDS.ERROR(data)]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!user)
|
||||||
|
return await sendHybridInteractionMessageResponse(data, {
|
||||||
|
embeds: [EMBEDS.NO_USER_FOUND(data)]
|
||||||
|
});
|
||||||
|
|
||||||
|
if (data.isApplicationCommand()) {
|
||||||
|
await data.getSlashCommand().deferReply();
|
||||||
|
}
|
||||||
|
|
||||||
|
const embed = makeInfoEmbed({
|
||||||
|
icon: null,
|
||||||
|
title: `**${user.displayName}**`,
|
||||||
|
description: `**${user.isFriend ? `${this.getState(user.status, user.state)}` : `⚪ Unknown`}**\n\u200b`,
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: `${this.getTrustRankEmoji(user.tags)} ${this.getTrustRank(user.tags)}${this.getExtraRanks(
|
||||||
|
user.tags
|
||||||
|
)}`,
|
||||||
|
value: `\u200b`,
|
||||||
|
inline: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '✨ Status',
|
||||||
|
value: `${user.statusDescription || 'None'}\n\u200b`,
|
||||||
|
inline: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '🌏 Language',
|
||||||
|
value: `${this.listLanguages(user.tags)}\n\u200b`,
|
||||||
|
inline: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '✨ Bio',
|
||||||
|
value: `${user.bio}\n\u200b`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: `❤ Account Information`,
|
||||||
|
value: `Joined: <t:${Math.round(new Date(user.date_joined).getTime() / 1000)}:R>, <t:${Math.round(
|
||||||
|
new Date(user.date_joined).getTime() / 1000
|
||||||
|
)}:f>
|
||||||
|
Avatar Cloning: ${user.allowAvatarCopying ? 'Enabled' : 'Disabled'}
|
||||||
|
User ID: \`\`${user.id}\`\`\n`
|
||||||
|
}
|
||||||
|
],
|
||||||
|
user: data.getUser()
|
||||||
|
});
|
||||||
|
embed.setAuthor({
|
||||||
|
name: `VRChat Profile`,
|
||||||
|
url: `https://vrchat.com/home/user/${user.id}`,
|
||||||
|
iconURL:
|
||||||
|
'https://www.theladders.com/s3proxy/company-photo.theladders.com/68949/5721f0dd-d662-4b5e-9c0b-236b8a41b0d3.png'
|
||||||
|
});
|
||||||
|
|
||||||
|
let userMainImage;
|
||||||
|
|
||||||
|
if (user.userIcon) userMainImage = user.userIcon;
|
||||||
|
else if (user.currentAvatarImageUrl) userMainImage = user.currentAvatarImageUrl;
|
||||||
|
|
||||||
|
if (userMainImage)
|
||||||
|
embed.setThumbnail(
|
||||||
|
ImagePorxy.signImageProxyURL(userMainImage, 'resize:fill:150:150:0') ||
|
||||||
|
'https://osu.ppy.sh/images/layout/avatar-guest.png'
|
||||||
|
);
|
||||||
|
|
||||||
|
if (user.profilePicOverride)
|
||||||
|
embed.setImage(
|
||||||
|
ImagePorxy.signImageProxyURL(user.profilePicOverride, 'resize:fill:960:540:0') ||
|
||||||
|
'https://osu.ppy.sh/images/layout/avatar-guest.png'
|
||||||
|
);
|
||||||
|
|
||||||
|
const row = new ActionRowBuilder<ButtonBuilder>().addComponents([
|
||||||
|
new ButtonBuilder()
|
||||||
|
.setEmoji('🔗')
|
||||||
|
.setLabel(' Open Profile')
|
||||||
|
.setURL(`https://vrchat.com/home/user/${user.id}`)
|
||||||
|
.setStyle(ButtonStyle.Link)
|
||||||
|
]);
|
||||||
|
|
||||||
|
for (let link of user.bioLinks) {
|
||||||
|
this.parseBioLink(row, link);
|
||||||
|
}
|
||||||
|
|
||||||
|
return await sendHybridInteractionMessageResponse(data, {
|
||||||
|
embeds: [embed],
|
||||||
|
components: [row]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
private static getState(status: string, state: string) {
|
||||||
|
if (state === 'offline') return '⚪ Offline';
|
||||||
|
else if (state === 'active') return '🟡 Active (Web/API)';
|
||||||
|
|
||||||
|
switch (status) {
|
||||||
|
case 'join me':
|
||||||
|
return '🔵 Join Me';
|
||||||
|
case 'active':
|
||||||
|
return '🟢 Online';
|
||||||
|
case 'ask me':
|
||||||
|
return '🟠 Ask Me';
|
||||||
|
case 'busy':
|
||||||
|
return '🔴 Do Not Disturb';
|
||||||
|
case 'offline':
|
||||||
|
return '⚪ Offline';
|
||||||
|
default:
|
||||||
|
return '⚪ Unknown';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static getTrustRank(tags: string[]) {
|
||||||
|
/*
|
||||||
|
Trusted user - system_trust_veteran
|
||||||
|
Known user - system_trust_trusted
|
||||||
|
User - system_trust_known
|
||||||
|
New user - system_trust_basic
|
||||||
|
Visitor - (No above tags) (or system_no_captcha?)
|
||||||
|
*/
|
||||||
|
if (tags.includes('system_trust_veteran')) return 'Trusted User';
|
||||||
|
if (tags.includes('system_trust_trusted')) return 'Known User';
|
||||||
|
if (tags.includes('system_trust_known')) return 'User';
|
||||||
|
if (tags.includes('system_trust_basic')) return 'New User';
|
||||||
|
return 'Visitor';
|
||||||
|
}
|
||||||
|
|
||||||
|
private static getExtraRanks(tags: string[]) {
|
||||||
|
let ranks = '';
|
||||||
|
if (tags.includes('system_probable_troll')) ranks += ' [Nuisance]';
|
||||||
|
if (tags.includes('admin_moderator') || tags.includes('admin_scripting_access')) ranks += ' [VRChat Team]';
|
||||||
|
|
||||||
|
return ranks;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static getTrustRankEmoji(tags: string[]) {
|
||||||
|
if (tags.includes('system_probable_troll')) return '🚩';
|
||||||
|
if (tags.includes('admin_moderator') || tags.includes('admin_scripting_access')) return '❤️';
|
||||||
|
|
||||||
|
if (tags.includes('system_trust_veteran')) return '💜';
|
||||||
|
if (tags.includes('system_trust_trusted')) return '🧡';
|
||||||
|
if (tags.includes('system_trust_known')) return '💚';
|
||||||
|
if (tags.includes('system_trust_basic')) return '💙';
|
||||||
|
return '🤍';
|
||||||
|
}
|
||||||
|
|
||||||
|
private static remapLanguageToISO3166(language: string) {
|
||||||
|
const map: any = {
|
||||||
|
eng: 'en',
|
||||||
|
kor: 'ko',
|
||||||
|
rus: 'ru',
|
||||||
|
spa: 'es',
|
||||||
|
por: 'pt',
|
||||||
|
zho: 'zh',
|
||||||
|
deu: 'de',
|
||||||
|
jpn: 'ja',
|
||||||
|
fra: 'fr',
|
||||||
|
swe: 'sv',
|
||||||
|
nld: 'nl',
|
||||||
|
pol: 'pl',
|
||||||
|
dan: 'da',
|
||||||
|
nor: 'no',
|
||||||
|
ita: 'it',
|
||||||
|
tha: 'th',
|
||||||
|
fin: 'fi',
|
||||||
|
hun: 'hu',
|
||||||
|
ces: 'cs',
|
||||||
|
tur: 'tr',
|
||||||
|
ara: 'ar',
|
||||||
|
ron: 'ro',
|
||||||
|
vie: 'vi',
|
||||||
|
ukr: 'uk'
|
||||||
|
};
|
||||||
|
return map[language] || language;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static listLanguages(tags: string[]) {
|
||||||
|
const languages = tags.filter((tag) => tag.startsWith('language_'));
|
||||||
|
const languagesWithoutPrefix = languages.map((language) => language.replace('language_', ''));
|
||||||
|
|
||||||
|
let finalLang = [];
|
||||||
|
for (let lang of languagesWithoutPrefix) {
|
||||||
|
//finalLang.push(`${countryCodeEmoji(this.remapLanguageToISO3166(lang))} ${lang}`);
|
||||||
|
finalLang.push(`${lang}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return finalLang.join(', ');
|
||||||
|
}
|
||||||
|
|
||||||
|
private static parseBioLink(row: any, link: string) {
|
||||||
|
const links: any = {
|
||||||
|
'twitter.com': { emoji: '🐦', label: 'Twitter' },
|
||||||
|
'youtube.com': { emoji: '📺', label: 'YouTube' },
|
||||||
|
'twitch.tv': { emoji: '📺', label: 'Twitch' },
|
||||||
|
'instagram.com': { emoji: '📷', label: 'Instagram' },
|
||||||
|
'facebook.com': { emoji: '📷', label: 'Facebook' },
|
||||||
|
'discord.gg': { emoji: '📢', label: 'Discord' },
|
||||||
|
'discord.com': { emoji: '📢', label: 'Discord' },
|
||||||
|
'reddit.com': { emoji: '📰', label: 'Reddit' },
|
||||||
|
'github.com': { emoji: '📦', label: 'GitHub' },
|
||||||
|
'steamcommunity.com': { emoji: '🎮', label: 'Steam' },
|
||||||
|
'tiktok.com': { emoji: '🎮', label: 'TikTok' },
|
||||||
|
'patreon.com': { emoji: '💰', label: 'Patreon' },
|
||||||
|
'ko-fi.com': { emoji: '☕', label: 'Ko-Fi' },
|
||||||
|
'paypal.me': { emoji: '💳', label: 'PayPal' },
|
||||||
|
'paypal.com': { emoji: '💳', label: 'PayPal' }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check if valid url using validator
|
||||||
|
if (!validator.isURL(link)) return;
|
||||||
|
|
||||||
|
const domain = new URL(link).hostname.toLowerCase();
|
||||||
|
|
||||||
|
if (links[domain]) {
|
||||||
|
row.addComponents([
|
||||||
|
new ButtonBuilder()
|
||||||
|
.setEmoji(links[domain].emoji)
|
||||||
|
.setLabel(` ${links[domain].label}`)
|
||||||
|
.setStyle(ButtonStyle.Link)
|
||||||
|
.setURL(link)
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
row.addComponents([
|
||||||
|
new ButtonBuilder().setEmoji('🔗').setLabel(' Bio Link').setURL(link).setStyle(ButtonStyle.Link)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,259 @@
|
|||||||
|
import { Message, ActionRowBuilder, ButtonBuilder, CommandInteraction, BaseInteraction, ButtonStyle } from 'discord.js';
|
||||||
|
|
||||||
|
import Prisma from '../../providers/Prisma';
|
||||||
|
import VRChatAPI from '../../providers/VRChatAPI';
|
||||||
|
import validator from 'validator';
|
||||||
|
import DiscordModule, { HybridInteractionMessage } from '../../utils/DiscordModule';
|
||||||
|
import { makeInfoEmbed, makeErrorEmbed, sendHybridInteractionMessageResponse } from '../../utils/DiscordMessage';
|
||||||
|
import Environment from '../../providers/Environment';
|
||||||
|
import ImagePorxy from '../../libs/ImageProxy';
|
||||||
|
import * as VRChat from 'vrchat';
|
||||||
|
|
||||||
|
const EMBEDS = {
|
||||||
|
NO_WORLD_FOUND: (data: HybridInteractionMessage) => {
|
||||||
|
return makeErrorEmbed({
|
||||||
|
title: `That world doesn't exists on VRChat`,
|
||||||
|
user: data.getUser()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
NO_WORLD_MENTIONED: (data: HybridInteractionMessage) => {
|
||||||
|
return makeErrorEmbed({
|
||||||
|
title: `No VRChat world name or world id provided`,
|
||||||
|
user: data.getUser()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
NOT_INITIALIZED: (data: HybridInteractionMessage) => {
|
||||||
|
return makeErrorEmbed({
|
||||||
|
title: `VRChat feature is disabled`,
|
||||||
|
user: data.getUser()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
ERROR: (data: HybridInteractionMessage) => {
|
||||||
|
return makeErrorEmbed({
|
||||||
|
title: `Something went wrong while connecting to VRChat`,
|
||||||
|
user: data.getUser()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class VRChatWorld {
|
||||||
|
public static async run(data: HybridInteractionMessage, args: any) {
|
||||||
|
let query;
|
||||||
|
if (data.isMessage()) {
|
||||||
|
if (typeof args[1] === 'undefined')
|
||||||
|
return await sendHybridInteractionMessageResponse(data, {
|
||||||
|
embeds: [EMBEDS.NO_WORLD_MENTIONED(data)]
|
||||||
|
});
|
||||||
|
const [removed, ...newArgs] = args;
|
||||||
|
query = newArgs.join(' ');
|
||||||
|
} else if (data.isApplicationCommand()) query = data.getSlashCommand().options.get('world')?.value?.toString();
|
||||||
|
|
||||||
|
let result;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (query.startsWith('wrld_')) result = await VRChatAPI.getCachedWorldById(query);
|
||||||
|
else {
|
||||||
|
let search_result = await VRChatAPI.client!.WorldsApi.searchWorlds(
|
||||||
|
undefined,
|
||||||
|
VRChat.SortOption.Relevance,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
100,
|
||||||
|
undefined, //VRChat.OrderOption.Descending,
|
||||||
|
undefined,
|
||||||
|
query
|
||||||
|
);
|
||||||
|
if (search_result.data.length === 0)
|
||||||
|
return await sendHybridInteractionMessageResponse(data, {
|
||||||
|
embeds: [EMBEDS.NO_WORLD_FOUND(data)]
|
||||||
|
});
|
||||||
|
|
||||||
|
let foundExact = false;
|
||||||
|
for (let i = 0; i < search_result.data.length; i++) {
|
||||||
|
if (search_result.data[i].name.toLowerCase() === query.toLowerCase()) {
|
||||||
|
result = await VRChatAPI.getCachedWorldById(search_result.data[i].id);
|
||||||
|
foundExact = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!foundExact) result = await VRChatAPI.getCachedWorldById(search_result.data[0].id);
|
||||||
|
}
|
||||||
|
} catch (err: any) {
|
||||||
|
if (err.response?.status === 404)
|
||||||
|
return await sendHybridInteractionMessageResponse(data, {
|
||||||
|
embeds: [EMBEDS.NO_WORLD_FOUND(data)]
|
||||||
|
});
|
||||||
|
else
|
||||||
|
return await sendHybridInteractionMessageResponse(data, {
|
||||||
|
embeds: [EMBEDS.ERROR(data)]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result)
|
||||||
|
return await sendHybridInteractionMessageResponse(data, {
|
||||||
|
embeds: [EMBEDS.NO_WORLD_FOUND(data)]
|
||||||
|
});
|
||||||
|
|
||||||
|
if (data.isApplicationCommand()) {
|
||||||
|
await data.getSlashCommand().deferReply();
|
||||||
|
}
|
||||||
|
|
||||||
|
let author = await VRChatAPI.getCachedUserById(result.authorId);
|
||||||
|
if (!author)
|
||||||
|
return await sendHybridInteractionMessageResponse(data, {
|
||||||
|
embeds: [EMBEDS.ERROR(data)]
|
||||||
|
});
|
||||||
|
|
||||||
|
const embed = makeInfoEmbed({
|
||||||
|
icon: null,
|
||||||
|
title: `**${result.name}**`,
|
||||||
|
description: `Created by **[${result.authorName}](https://vrchat.com/home/user/${author.id})**\n\u200b`,
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: '🌎 World Description',
|
||||||
|
value: `${result.description}\n\u200b`,
|
||||||
|
inline: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: `${this.getReleaseStatusEmoji(result)} Visiblity`,
|
||||||
|
value: `${this.getReleaseStatus(result)}\n\u200b`,
|
||||||
|
inline: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '✨ Visits',
|
||||||
|
value: `${this.numberWithCommas(result.visits)}\n\u200b`,
|
||||||
|
inline: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '💕 Favorites',
|
||||||
|
value: `${result.favorites ? this.numberWithCommas(result.favorites) : 0}\n\u200b`,
|
||||||
|
inline: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '👥 Players',
|
||||||
|
value: `${result.occupants ? this.numberWithCommas(result.occupants) : 0} ${
|
||||||
|
result.instances
|
||||||
|
? `(${this.numberWithCommas(result.publicOccupants || 0)} public, ${this.numberWithCommas(
|
||||||
|
result.privateOccupants || 0
|
||||||
|
)} private)`
|
||||||
|
: ''
|
||||||
|
}\n\u200b`,
|
||||||
|
inline: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '💖 Popularity',
|
||||||
|
value: `${this.numberWithCommas(result.popularity)}\n\u200b`,
|
||||||
|
inline: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '🔥 Heat',
|
||||||
|
value: `${result.heat}\n\u200b`,
|
||||||
|
inline: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '📥 Capacity',
|
||||||
|
value: `${result.capacity}\n\u200b`,
|
||||||
|
inline: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '📅 Last updated',
|
||||||
|
value: `<t:${Math.round(new Date(result.updated_at).getTime() / 1000)}:R>\n<t:${Math.round(
|
||||||
|
new Date(result.updated_at).getTime() / 1000
|
||||||
|
)}:f>\n\u200b`,
|
||||||
|
inline: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '📅 Created at',
|
||||||
|
value: `<t:${Math.round(new Date(result.created_at).getTime() / 1000)}:R>\n<t:${Math.round(
|
||||||
|
new Date(result.created_at).getTime() / 1000
|
||||||
|
)}:f>\n\u200b`,
|
||||||
|
inline: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: `❤ World Information`,
|
||||||
|
value: `World ID: \`\`${result.id}\`\`\nCreator ID: \`\`${result.authorId}\`\`\n`
|
||||||
|
}
|
||||||
|
],
|
||||||
|
user: data.getUser()
|
||||||
|
});
|
||||||
|
|
||||||
|
embed.setAuthor({
|
||||||
|
name: `VRChat World`,
|
||||||
|
url: `https://vrchat.com/home/world/${result.id}`,
|
||||||
|
iconURL:
|
||||||
|
'https://www.theladders.com/s3proxy/company-photo.theladders.com/68949/5721f0dd-d662-4b5e-9c0b-236b8a41b0d3.png'
|
||||||
|
});
|
||||||
|
|
||||||
|
let mainImage;
|
||||||
|
|
||||||
|
if (result.thumbnailImageUrl) mainImage = result.thumbnailImageUrl;
|
||||||
|
|
||||||
|
if (mainImage)
|
||||||
|
embed.setImage(
|
||||||
|
ImagePorxy.signImageProxyURL(mainImage, 'resize:fill:960:540:0') ||
|
||||||
|
'https://osu.ppy.sh/images/layout/avatar-guest.png'
|
||||||
|
);
|
||||||
|
|
||||||
|
let userMainImage;
|
||||||
|
|
||||||
|
if (author.userIcon) userMainImage = author.userIcon;
|
||||||
|
else if (author.currentAvatarImageUrl) userMainImage = author.currentAvatarImageUrl;
|
||||||
|
|
||||||
|
if (userMainImage)
|
||||||
|
embed.setThumbnail(
|
||||||
|
ImagePorxy.signImageProxyURL(userMainImage, 'resize:fill:150:150:0') ||
|
||||||
|
'https://osu.ppy.sh/images/layout/avatar-guest.png'
|
||||||
|
);
|
||||||
|
|
||||||
|
const row = new ActionRowBuilder<ButtonBuilder>().addComponents([
|
||||||
|
new ButtonBuilder()
|
||||||
|
.setEmoji('🔗')
|
||||||
|
.setLabel(' Open World')
|
||||||
|
.setURL(`https://vrchat.com/home/world/${result.id}`)
|
||||||
|
.setStyle(ButtonStyle.Link),
|
||||||
|
new ButtonBuilder()
|
||||||
|
.setEmoji('🔗')
|
||||||
|
.setLabel(` ${author.displayName}'s Profile`)
|
||||||
|
.setURL(`https://vrchat.com/home/user/${author.id}`)
|
||||||
|
.setStyle(ButtonStyle.Link)
|
||||||
|
]);
|
||||||
|
|
||||||
|
return await sendHybridInteractionMessageResponse(data, {
|
||||||
|
embeds: [embed],
|
||||||
|
components: [row]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static numberWithCommas(x: Number) {
|
||||||
|
try {
|
||||||
|
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
||||||
|
} catch (err) {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static getReleaseStatusEmoji(world: any) {
|
||||||
|
switch (world.releaseStatus) {
|
||||||
|
case 'public':
|
||||||
|
if (world.tags.includes('system_labs')) return '🧪';
|
||||||
|
else return '🌎';
|
||||||
|
case 'private':
|
||||||
|
return '🔒';
|
||||||
|
default:
|
||||||
|
return '🌎';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static getReleaseStatus(world: any) {
|
||||||
|
switch (world.releaseStatus) {
|
||||||
|
case 'public':
|
||||||
|
if (world.tags.includes('system_labs')) return 'Labs';
|
||||||
|
else return 'Public';
|
||||||
|
case 'private':
|
||||||
|
return 'Private';
|
||||||
|
default:
|
||||||
|
return world.releaseStatus;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
import { Message, ActionRowBuilder, ButtonBuilder, CommandInteraction, BaseInteraction, ButtonStyle } from 'discord.js';
|
||||||
|
import validator from 'validator';
|
||||||
|
import { createHmac } from 'crypto';
|
||||||
|
import countryLookup from 'country-code-lookup';
|
||||||
|
import { countryCodeEmoji } from 'country-code-emoji';
|
||||||
|
|
||||||
|
import Prisma from '../../providers/Prisma';
|
||||||
|
import VRChatAPI from '../../providers/VRChatAPI';
|
||||||
|
|
||||||
|
import DiscordModule, { HybridInteractionMessage } from '../../utils/DiscordModule';
|
||||||
|
import { makeInfoEmbed, makeErrorEmbed, sendHybridInteractionMessageResponse } from '../../utils/DiscordMessage';
|
||||||
|
import Environment from '../../providers/Environment';
|
||||||
|
|
||||||
|
import VRChatUser from './User';
|
||||||
|
import VRChatWorld from './World';
|
||||||
|
|
||||||
|
const EMBEDS = {
|
||||||
|
VRChat_INFO: (data: HybridInteractionMessage) => {
|
||||||
|
return makeInfoEmbed({
|
||||||
|
title: 'VRChat',
|
||||||
|
description: `[VRChat](https://hello.vrchat.com/) is an online virtual world platform created by Graham Gaylor and Jesse Joudrey and operated by VRChat, Inc. The platform allows users to interact with others with user-created 3D avatars and worlds.`,
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'What can I do?',
|
||||||
|
value: 'You can view users stats and information'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Available arguments',
|
||||||
|
value: '``user``'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
user: data.getUser()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
NOT_INITIALIZED: (data: HybridInteractionMessage) => {
|
||||||
|
return makeErrorEmbed({
|
||||||
|
title: `VRChat feature is disabled`,
|
||||||
|
user: data.getUser()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
ERROR: (data: HybridInteractionMessage) => {
|
||||||
|
return makeErrorEmbed({
|
||||||
|
title: `Something went wrong while connecting to VRChat`,
|
||||||
|
user: data.getUser()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class VRChat extends DiscordModule {
|
||||||
|
public id = 'Discord_VRChat';
|
||||||
|
public commands = ['vrchat', 'vrc'];
|
||||||
|
public commandInteractionName = 'vrchat';
|
||||||
|
|
||||||
|
async GuildOnModuleCommand(args: any, message: Message) {
|
||||||
|
await this.run(new HybridInteractionMessage(message), args);
|
||||||
|
}
|
||||||
|
|
||||||
|
async GuildModuleCommandInteractionCreate(interaction: CommandInteraction) {
|
||||||
|
await this.run(new HybridInteractionMessage(interaction), interaction.options);
|
||||||
|
}
|
||||||
|
|
||||||
|
async run(data: HybridInteractionMessage, args: any) {
|
||||||
|
const Guild = await Prisma.client.guild.findFirst({ where: { id: data.getGuild()!.id } });
|
||||||
|
if (!Guild) return;
|
||||||
|
|
||||||
|
if (!VRChatAPI.client)
|
||||||
|
return await sendHybridInteractionMessageResponse(data, {
|
||||||
|
embeds: [EMBEDS.NOT_INITIALIZED(data)]
|
||||||
|
});
|
||||||
|
|
||||||
|
let query;
|
||||||
|
|
||||||
|
if (data.isMessage()) {
|
||||||
|
if (args.length === 0) {
|
||||||
|
return await sendHybridInteractionMessageResponse(data, {
|
||||||
|
embeds: [EMBEDS.VRChat_INFO(data)]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
query = args[0].toLowerCase();
|
||||||
|
} else if (data.isApplicationCommand()) {
|
||||||
|
query = args.getSubcommand();
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (query) {
|
||||||
|
case 'user':
|
||||||
|
case 'u':
|
||||||
|
return await VRChatUser.run(data, args);
|
||||||
|
case 'world':
|
||||||
|
case 'w':
|
||||||
|
return await VRChatWorld.run(data, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private numberWithCommas(x: Number) {
|
||||||
|
try {
|
||||||
|
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
||||||
|
} catch (err) {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
-1
@@ -1,14 +1,19 @@
|
|||||||
|
import path from 'path';
|
||||||
|
import dotenv from 'dotenv';
|
||||||
|
dotenv.config({ path: path.resolve(__dirname, '../.env') });
|
||||||
|
|
||||||
import App from './providers/App';
|
import App from './providers/App';
|
||||||
import NativeException from './exception/NativeException';
|
import NativeException from './exception/NativeException';
|
||||||
|
|
||||||
NativeException.process();
|
NativeException.process();
|
||||||
|
|
||||||
App.loadConfig();
|
|
||||||
App.loadENV();
|
App.loadENV();
|
||||||
|
App.loadConfig();
|
||||||
App.loadPrisma();
|
App.loadPrisma();
|
||||||
App.loadLocale();
|
App.loadLocale();
|
||||||
App.loadDiscord();
|
App.loadDiscord();
|
||||||
App.load_osu();
|
App.load_osu();
|
||||||
|
App.loadVRChat();
|
||||||
App.loadExpress();
|
App.loadExpress();
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import { createHmac } from 'crypto';
|
||||||
|
import Environment from '../providers/Environment';
|
||||||
|
|
||||||
|
export default class ImagePorxy {
|
||||||
|
public static signImageProxyURL(url: string, modifiers: string | undefined = undefined) {
|
||||||
|
const urlSafeBase64 = (string: Buffer) => {
|
||||||
|
return Buffer.from(string).toString('base64').replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
|
||||||
|
};
|
||||||
|
|
||||||
|
const hexDecode = (hex: string) => Buffer.from(hex, 'hex');
|
||||||
|
|
||||||
|
const sign = (salt: string, target: string, secret: string) => {
|
||||||
|
const hmac = createHmac('sha256', hexDecode(secret));
|
||||||
|
hmac.update(hexDecode(salt));
|
||||||
|
hmac.update(target);
|
||||||
|
return urlSafeBase64(hmac.digest());
|
||||||
|
};
|
||||||
|
|
||||||
|
let path;
|
||||||
|
if (modifiers) path = `/${modifiers}/plain/${url}`;
|
||||||
|
else path = `/plain/${url}`;
|
||||||
|
|
||||||
|
const signature = sign(Environment.get().IMGPROXY_SALT, path, Environment.get().IMGPROXY_KEY);
|
||||||
|
const result = `${Environment.get().IMGPROXY_HOST}${signature}${path}`;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ import Configuration from './Configuration';
|
|||||||
import Prisma from './Prisma';
|
import Prisma from './Prisma';
|
||||||
import Discord from './Discord';
|
import Discord from './Discord';
|
||||||
import osu from './osuAPI';
|
import osu from './osuAPI';
|
||||||
|
import VRChat from './VRChatAPI';
|
||||||
import Express from './Express';
|
import Express from './Express';
|
||||||
|
|
||||||
import Logger from '../libs/Logger';
|
import Logger from '../libs/Logger';
|
||||||
@@ -38,6 +39,11 @@ class App {
|
|||||||
Locale.init();
|
Locale.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public loadVRChat(): void {
|
||||||
|
Logger.log('info', 'Loading VRChat');
|
||||||
|
VRChat.init();
|
||||||
|
}
|
||||||
|
|
||||||
public load_osu(): void {
|
public load_osu(): void {
|
||||||
if (!Environment.get().OSU_API_KEY) {
|
if (!Environment.get().OSU_API_KEY) {
|
||||||
Logger.log('warn', 'OSU_API_KEY is not defined in .env, osu! features will be disabled');
|
Logger.log('warn', 'OSU_API_KEY is not defined in .env, osu! features will be disabled');
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import Discord_Say from '../discord/Say';
|
|||||||
import Discord_InteractionManager from '../discord/InteractionManager';
|
import Discord_InteractionManager from '../discord/InteractionManager';
|
||||||
import Discord_MembershipScreening from '../discord/MembershipScreening';
|
import Discord_MembershipScreening from '../discord/MembershipScreening';
|
||||||
import Discord_osu from '../discord/osu';
|
import Discord_osu from '../discord/osu';
|
||||||
|
import Discord_VRChat from '../discord/VRChat';
|
||||||
import Discord_UserInfo from '../discord/UserInfo';
|
import Discord_UserInfo from '../discord/UserInfo';
|
||||||
import Discord_Stats from '../discord/Stats';
|
import Discord_Stats from '../discord/Stats';
|
||||||
import Discord_Support from '../discord/Support';
|
import Discord_Support from '../discord/Support';
|
||||||
@@ -78,6 +79,7 @@ class Discord {
|
|||||||
new Discord_Say(),
|
new Discord_Say(),
|
||||||
new Discord_InteractionManager(),
|
new Discord_InteractionManager(),
|
||||||
new Discord_osu(),
|
new Discord_osu(),
|
||||||
|
new Discord_VRChat(),
|
||||||
new Discord_Settings(),
|
new Discord_Settings(),
|
||||||
new Discord_Support(),
|
new Discord_Support(),
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,19 @@
|
|||||||
import * as path from 'path';
|
|
||||||
import * as dotenv from 'dotenv';
|
|
||||||
import validator from 'validator';
|
import validator from 'validator';
|
||||||
|
|
||||||
import Logger from '../libs/Logger';
|
import Logger from '../libs/Logger';
|
||||||
|
|
||||||
const requiredENV = ['NODE_ENV', 'DATABASE_URL', 'DISCORD_TOKEN', 'PRIVATE_BOT'];
|
const requiredENV = [
|
||||||
|
'NODE_ENV',
|
||||||
|
'DATABASE_URL',
|
||||||
|
'DISCORD_TOKEN',
|
||||||
|
'PRIVATE_BOT',
|
||||||
|
'IMGPROXY_HOST',
|
||||||
|
'IMGPROXY_KEY',
|
||||||
|
'IMGPROXY_SALT'
|
||||||
|
];
|
||||||
|
|
||||||
class Environment {
|
class Environment {
|
||||||
public init(): void {
|
public init(): void {
|
||||||
dotenv.config({ path: path.resolve(__dirname, '../../.env') });
|
|
||||||
|
|
||||||
for (let param of requiredENV) {
|
for (let param of requiredENV) {
|
||||||
if (this.isUndefinedOrEmpty(process.env[param])) throw new Error(`.env ${param} is undefined`);
|
if (this.isUndefinedOrEmpty(process.env[param])) throw new Error(`.env ${param} is undefined`);
|
||||||
}
|
}
|
||||||
@@ -76,6 +80,14 @@ class Environment {
|
|||||||
const SPOTIFY_REFRESH_TOKEN = process.env.SPOTIFY_REFRESH_TOKEN;
|
const SPOTIFY_REFRESH_TOKEN = process.env.SPOTIFY_REFRESH_TOKEN;
|
||||||
const SPOTIFY_CLIENT_MARKET = process.env.SPOTIFY_CLIENT_MARKET;
|
const SPOTIFY_CLIENT_MARKET = process.env.SPOTIFY_CLIENT_MARKET;
|
||||||
|
|
||||||
|
const VRC_CONTACT_EMAIL = process.env.VRC_CONTACT_EMAIL;
|
||||||
|
const VRC_API_KEY = process.env.VRC_API_KEY;
|
||||||
|
const VRC_COOKIE = process.env.VRC_COOKIE;
|
||||||
|
|
||||||
|
const IMGPROXY_HOST = process.env.IMGPROXY_HOST;
|
||||||
|
const IMGPROXY_KEY = process.env.IMGPROXY_KEY;
|
||||||
|
const IMGPROXY_SALT = process.env.IMGPROXY_SALT;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
NODE_ENV,
|
NODE_ENV,
|
||||||
|
|
||||||
@@ -93,7 +105,15 @@ class Environment {
|
|||||||
SPOTIFY_CLIENT_ID,
|
SPOTIFY_CLIENT_ID,
|
||||||
SPOTIFY_CLIENT_SECRET,
|
SPOTIFY_CLIENT_SECRET,
|
||||||
SPOTIFY_REFRESH_TOKEN,
|
SPOTIFY_REFRESH_TOKEN,
|
||||||
SPOTIFY_CLIENT_MARKET
|
SPOTIFY_CLIENT_MARKET,
|
||||||
|
|
||||||
|
VRC_CONTACT_EMAIL,
|
||||||
|
VRC_API_KEY,
|
||||||
|
VRC_COOKIE,
|
||||||
|
|
||||||
|
IMGPROXY_HOST,
|
||||||
|
IMGPROXY_KEY,
|
||||||
|
IMGPROXY_SALT
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,151 @@
|
|||||||
|
import * as VRChat from 'vrchat';
|
||||||
|
import Environment from './Environment';
|
||||||
|
import Logger from '../libs/Logger';
|
||||||
|
import App from './App';
|
||||||
|
|
||||||
|
const VRC_CACHE_DURATION = 5 * 60 * 1000; // 5 minutes
|
||||||
|
|
||||||
|
interface VRChatAPIs {
|
||||||
|
AuthenticationApi: VRChat.AuthenticationApi;
|
||||||
|
UsersApi: VRChat.UsersApi;
|
||||||
|
WorldsApi: VRChat.WorldsApi;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface UserCache {
|
||||||
|
user: VRChat.User;
|
||||||
|
expires: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface WorldCache {
|
||||||
|
world: VRChat.World;
|
||||||
|
expires: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Cache {
|
||||||
|
Users: { [key: string]: UserCache };
|
||||||
|
Worlds: { [key: string]: WorldCache };
|
||||||
|
}
|
||||||
|
|
||||||
|
class VRChatAPI {
|
||||||
|
public client: VRChatAPIs | null;
|
||||||
|
public configuration: VRChat.Configuration | null;
|
||||||
|
private cache: Cache;
|
||||||
|
private useragent: string | null = null;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.cache = {
|
||||||
|
Users: {},
|
||||||
|
Worlds: {}
|
||||||
|
};
|
||||||
|
this.client = null;
|
||||||
|
this.configuration = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async init() {
|
||||||
|
this.useragent = `Yumi/${App.version.replaceAll('/', '').replaceAll(' ', '-').replaceAll('--', '-')} ${
|
||||||
|
Environment.get().VRC_CONTACT_EMAIL
|
||||||
|
}`;
|
||||||
|
Logger.debug(`[VRChat] Using user agent ${this.useragent}`);
|
||||||
|
this.configuration = new VRChat.Configuration({
|
||||||
|
//username: Environment.get().VRC_USERNAME,
|
||||||
|
//;password: Environment.get().VRC_PASSWORD,
|
||||||
|
apiKey: Environment.get().VRC_API_KEY,
|
||||||
|
baseOptions: {
|
||||||
|
headers: {
|
||||||
|
'User-Agent': this.useragent,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
Cookie: Environment.get().VRC_COOKIE || ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.client = {
|
||||||
|
AuthenticationApi: new VRChat.AuthenticationApi(this.configuration),
|
||||||
|
UsersApi: new VRChat.UsersApi(this.configuration),
|
||||||
|
WorldsApi: new VRChat.WorldsApi(this.configuration)
|
||||||
|
};
|
||||||
|
|
||||||
|
Logger.info('Logging in to VRChat');
|
||||||
|
let res = await this.client.AuthenticationApi.getCurrentUser();
|
||||||
|
|
||||||
|
Logger.info('Logged in to VRChat as ' + res.data.displayName);
|
||||||
|
|
||||||
|
setInterval(() => {
|
||||||
|
for (let key in this.cache.Users) {
|
||||||
|
if (this.cache.Users[key].expires < new Date()) {
|
||||||
|
Logger.debug('[VRChat] [Cache] Removing user ' + key + ' from cache');
|
||||||
|
delete this.cache.Users[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let key in this.cache.Worlds) {
|
||||||
|
if (this.cache.Worlds[key].expires < new Date()) {
|
||||||
|
Logger.debug('[VRChat] [Cache] Removing world ' + key + ' from cache');
|
||||||
|
delete this.cache.Worlds[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, VRC_CACHE_DURATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getCachedUserById(id: string) {
|
||||||
|
if (typeof this.cache.Users[id] !== 'undefined') {
|
||||||
|
Logger.debug('[VRChat] [Cache] Cache hit for user ' + id);
|
||||||
|
if (this.cache.Users[id].expires > new Date()) {
|
||||||
|
return this.cache.Users[id].user;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.debug('[VRChat] [Cache] Cache miss for ' + id);
|
||||||
|
let user;
|
||||||
|
try {
|
||||||
|
user = await this.client!.UsersApi.getUser(id);
|
||||||
|
} catch (err: any) {
|
||||||
|
if (err.response?.status === 404) return null;
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.debug('[VRChat] [Cache] Caching user ' + id);
|
||||||
|
this.cache.Users[id] = {
|
||||||
|
user: user.data,
|
||||||
|
expires: new Date(Date.now() + VRC_CACHE_DURATION)
|
||||||
|
};
|
||||||
|
return user.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getCachedWorldById(id: string) {
|
||||||
|
if (typeof this.cache.Worlds[id] !== 'undefined') {
|
||||||
|
Logger.debug('[VRChat] [Cache] Cache hit for world ' + id);
|
||||||
|
if (this.cache.Worlds[id].expires > new Date()) {
|
||||||
|
return this.cache.Worlds[id].world;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.debug('[VRChat] [Cache] Cache miss for ' + id);
|
||||||
|
let world;
|
||||||
|
try {
|
||||||
|
world = await this.client!.WorldsApi.getWorld(id);
|
||||||
|
} catch (err: any) {
|
||||||
|
if (err.response?.status === 404) return null;
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!world) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.debug('[VRChat] [Cache] Caching world ' + id);
|
||||||
|
this.cache.Worlds[id] = {
|
||||||
|
world: world.data,
|
||||||
|
expires: new Date(Date.now() + VRC_CACHE_DURATION)
|
||||||
|
};
|
||||||
|
|
||||||
|
return world.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public end(): void {}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default new VRChatAPI();
|
||||||
@@ -58,6 +58,22 @@ export const GLOBAL_COMMANDS: Object[] = [
|
|||||||
.setName('beatmap')
|
.setName('beatmap')
|
||||||
.setDescription('Get beatmap information on osu!')
|
.setDescription('Get beatmap information on osu!')
|
||||||
.addStringOption((user) => user.setName('beatmap').setDescription('Beatmap id').setRequired(true))
|
.addStringOption((user) => user.setName('beatmap').setDescription('Beatmap id').setRequired(true))
|
||||||
|
),
|
||||||
|
|
||||||
|
new SlashCommandBuilder()
|
||||||
|
.setName('vrchat')
|
||||||
|
.setDescription('Interact with the VRChat')
|
||||||
|
.addSubcommand((user) =>
|
||||||
|
user
|
||||||
|
.setName('user')
|
||||||
|
.setDescription('Get user information on VRChat')
|
||||||
|
.addStringOption((user) => user.setName('user').setDescription('Username or User id').setRequired(true))
|
||||||
|
)
|
||||||
|
.addSubcommand((world) =>
|
||||||
|
world
|
||||||
|
.setName('world')
|
||||||
|
.setDescription('Get world information on VRChat')
|
||||||
|
.addStringOption((user) => user.setName('world').setDescription('World id').setRequired(true))
|
||||||
)
|
)
|
||||||
];
|
];
|
||||||
export const GUILD_COMMANDS: Object[] = [];
|
export const GUILD_COMMANDS: Object[] = [];
|
||||||
|
|||||||
@@ -339,6 +339,11 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz#9aa30c04db212a9a0649d6ae6fd50accc40748a1"
|
resolved "https://registry.yarnpkg.com/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz#9aa30c04db212a9a0649d6ae6fd50accc40748a1"
|
||||||
integrity sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==
|
integrity sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==
|
||||||
|
|
||||||
|
"@types/tough-cookie@^4.0.1":
|
||||||
|
version "4.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.2.tgz#6286b4c7228d58ab7866d19716f3696e03a09397"
|
||||||
|
integrity sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==
|
||||||
|
|
||||||
"@types/validator@^13.7.15":
|
"@types/validator@^13.7.15":
|
||||||
version "13.7.15"
|
version "13.7.15"
|
||||||
resolved "https://registry.yarnpkg.com/@types/validator/-/validator-13.7.15.tgz#408c99d1b5f0eecc78109c11f896f72d1f026a10"
|
resolved "https://registry.yarnpkg.com/@types/validator/-/validator-13.7.15.tgz#408c99d1b5f0eecc78109c11f896f72d1f026a10"
|
||||||
@@ -434,6 +439,21 @@ asynckit@^0.4.0:
|
|||||||
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
|
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
|
||||||
integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
|
integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
|
||||||
|
|
||||||
|
axios-cookiejar-support@^1.0.1:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/axios-cookiejar-support/-/axios-cookiejar-support-1.0.1.tgz#7b32af7d932508546c68b1fc5ba8f562884162e1"
|
||||||
|
integrity sha512-IZJxnAJ99XxiLqNeMOqrPbfR7fRyIfaoSLdPUf4AMQEGkH8URs0ghJK/xtqBsD+KsSr3pKl4DEQjCn834pHMig==
|
||||||
|
dependencies:
|
||||||
|
is-redirect "^1.0.0"
|
||||||
|
pify "^5.0.0"
|
||||||
|
|
||||||
|
axios@^0.26.1:
|
||||||
|
version "0.26.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/axios/-/axios-0.26.1.tgz#1ede41c51fcf51bbbd6fd43669caaa4f0495aaa9"
|
||||||
|
integrity sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==
|
||||||
|
dependencies:
|
||||||
|
follow-redirects "^1.14.8"
|
||||||
|
|
||||||
balanced-match@^1.0.0:
|
balanced-match@^1.0.0:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
|
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
|
||||||
@@ -922,6 +942,11 @@ fn.name@1.x.x:
|
|||||||
resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc"
|
resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc"
|
||||||
integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==
|
integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==
|
||||||
|
|
||||||
|
follow-redirects@^1.14.8:
|
||||||
|
version "1.15.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13"
|
||||||
|
integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==
|
||||||
|
|
||||||
form-data@^3.0.0:
|
form-data@^3.0.0:
|
||||||
version "3.0.1"
|
version "3.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f"
|
resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f"
|
||||||
@@ -1135,6 +1160,11 @@ is-number@^7.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
|
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
|
||||||
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
|
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
|
||||||
|
|
||||||
|
is-redirect@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24"
|
||||||
|
integrity sha512-cr/SlUEe5zOGmzvj9bUyC4LVvkNVAXu4GytXLNMr1pny+a65MpQ9IJzFHD5vi7FyJgb4qt27+eS3TuQnqB+RQw==
|
||||||
|
|
||||||
is-stream@^2.0.0:
|
is-stream@^2.0.0:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077"
|
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077"
|
||||||
@@ -1451,6 +1481,11 @@ picomatch@^2.0.4, picomatch@^2.2.1:
|
|||||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
|
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
|
||||||
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
|
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
|
||||||
|
|
||||||
|
pify@^5.0.0:
|
||||||
|
version "5.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/pify/-/pify-5.0.0.tgz#1f5eca3f5e87ebec28cc6d54a0e4aaf00acc127f"
|
||||||
|
integrity sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==
|
||||||
|
|
||||||
ping@^0.4.4:
|
ping@^0.4.4:
|
||||||
version "0.4.4"
|
version "0.4.4"
|
||||||
resolved "https://registry.yarnpkg.com/ping/-/ping-0.4.4.tgz#f70c5c8ad7b476d903100c9d45ecd52cf83e1de3"
|
resolved "https://registry.yarnpkg.com/ping/-/ping-0.4.4.tgz#f70c5c8ad7b476d903100c9d45ecd52cf83e1de3"
|
||||||
@@ -1493,6 +1528,16 @@ proxy-addr@~2.0.7:
|
|||||||
forwarded "0.2.0"
|
forwarded "0.2.0"
|
||||||
ipaddr.js "1.9.1"
|
ipaddr.js "1.9.1"
|
||||||
|
|
||||||
|
psl@^1.1.33:
|
||||||
|
version "1.9.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7"
|
||||||
|
integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==
|
||||||
|
|
||||||
|
punycode@^2.1.1:
|
||||||
|
version "2.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f"
|
||||||
|
integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==
|
||||||
|
|
||||||
qs@6.11.0, qs@^6.9.4:
|
qs@6.11.0, qs@^6.9.4:
|
||||||
version "6.11.0"
|
version "6.11.0"
|
||||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a"
|
resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a"
|
||||||
@@ -1500,6 +1545,11 @@ qs@6.11.0, qs@^6.9.4:
|
|||||||
dependencies:
|
dependencies:
|
||||||
side-channel "^1.0.4"
|
side-channel "^1.0.4"
|
||||||
|
|
||||||
|
querystringify@^2.1.1:
|
||||||
|
version "2.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6"
|
||||||
|
integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==
|
||||||
|
|
||||||
range-parser@~1.2.1:
|
range-parser@~1.2.1:
|
||||||
version "1.2.1"
|
version "1.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
|
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
|
||||||
@@ -1566,6 +1616,11 @@ require-directory@^2.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
|
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
|
||||||
integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==
|
integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==
|
||||||
|
|
||||||
|
requires-port@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
|
||||||
|
integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==
|
||||||
|
|
||||||
resolve@^1.0.0:
|
resolve@^1.0.0:
|
||||||
version "1.22.1"
|
version "1.22.1"
|
||||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177"
|
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177"
|
||||||
@@ -1848,6 +1903,16 @@ token-types@^5.0.1:
|
|||||||
"@tokenizer/token" "^0.3.0"
|
"@tokenizer/token" "^0.3.0"
|
||||||
ieee754 "^1.2.1"
|
ieee754 "^1.2.1"
|
||||||
|
|
||||||
|
tough-cookie@^4.0.0:
|
||||||
|
version "4.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.2.tgz#e53e84b85f24e0b65dd526f46628db6c85f6b874"
|
||||||
|
integrity sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==
|
||||||
|
dependencies:
|
||||||
|
psl "^1.1.33"
|
||||||
|
punycode "^2.1.1"
|
||||||
|
universalify "^0.2.0"
|
||||||
|
url-parse "^1.5.3"
|
||||||
|
|
||||||
tr46@~0.0.3:
|
tr46@~0.0.3:
|
||||||
version "0.0.3"
|
version "0.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
|
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
|
||||||
@@ -1943,6 +2008,11 @@ undici@^5.21.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
busboy "^1.6.0"
|
busboy "^1.6.0"
|
||||||
|
|
||||||
|
universalify@^0.2.0:
|
||||||
|
version "0.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0"
|
||||||
|
integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==
|
||||||
|
|
||||||
unpipe@1.0.0, unpipe@~1.0.0:
|
unpipe@1.0.0, unpipe@~1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
|
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
|
||||||
@@ -1953,6 +2023,14 @@ untildify@^4.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b"
|
resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b"
|
||||||
integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==
|
integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==
|
||||||
|
|
||||||
|
url-parse@^1.5.3:
|
||||||
|
version "1.5.10"
|
||||||
|
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1"
|
||||||
|
integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==
|
||||||
|
dependencies:
|
||||||
|
querystringify "^2.1.1"
|
||||||
|
requires-port "^1.0.0"
|
||||||
|
|
||||||
utf-8-validate@^6.0.3:
|
utf-8-validate@^6.0.3:
|
||||||
version "6.0.3"
|
version "6.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-6.0.3.tgz#7d8c936d854e86b24d1d655f138ee27d2636d777"
|
resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-6.0.3.tgz#7d8c936d854e86b24d1d655f138ee27d2636d777"
|
||||||
@@ -1985,6 +2063,16 @@ vary@^1, vary@~1.1.2:
|
|||||||
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
|
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
|
||||||
integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==
|
integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==
|
||||||
|
|
||||||
|
vrchat@^1.11.1:
|
||||||
|
version "1.11.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/vrchat/-/vrchat-1.11.1.tgz#acf37426f717c9cfb60d37ef50131b0c94704c0c"
|
||||||
|
integrity sha512-zQ+wXN3fnf5y7oVbRQw99JKx8DIQ2xfLxSpR8Yw0SQBOHfgXLrdOQw9MofoHQbW1Rqmj+LnvRiNh9bZM/ffEcw==
|
||||||
|
dependencies:
|
||||||
|
"@types/tough-cookie" "^4.0.1"
|
||||||
|
axios "^0.26.1"
|
||||||
|
axios-cookiejar-support "^1.0.1"
|
||||||
|
tough-cookie "^4.0.0"
|
||||||
|
|
||||||
webidl-conversions@^3.0.0:
|
webidl-conversions@^3.0.0:
|
||||||
version "3.0.1"
|
version "3.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
|
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
|
||||||
|
|||||||
Reference in New Issue
Block a user