mirror of
https://github.com/kirameki-cafe/Yumi.git
synced 2026-09-13 10:49:20 +00:00
Added VRChat commands
This commit is contained in:
@@ -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,302 @@
|
|||||||
|
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 user;
|
||||||
|
if (data.isMessage()) {
|
||||||
|
if (typeof args[1] === 'undefined')
|
||||||
|
return await sendHybridInteractionMessageResponse(data, {
|
||||||
|
embeds: [EMBEDS.NO_USER_MENTIONED(data)]
|
||||||
|
});
|
||||||
|
const [removed, ...newArgs] = args;
|
||||||
|
user = newArgs.join(' ');
|
||||||
|
} else if (data.isApplicationCommand()) user = data.getSlashCommand().options.get('user')?.value?.toString();
|
||||||
|
|
||||||
|
let result;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (user.startsWith('usr_')) result = await VRChatAPI.client!.UsersApi.getUser(user);
|
||||||
|
else {
|
||||||
|
let search_result = await VRChatAPI.client!.UsersApi.searchUsers(user, 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() === user.toLowerCase()) {
|
||||||
|
result = await VRChatAPI.client!.UsersApi.getUser(search_result.data[i].id);
|
||||||
|
foundExact = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!foundExact) result = await VRChatAPI.client!.UsersApi.getUser(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 (!result)
|
||||||
|
return await sendHybridInteractionMessageResponse(data, {
|
||||||
|
embeds: [EMBEDS.NO_USER_FOUND(data)]
|
||||||
|
});
|
||||||
|
|
||||||
|
if (data.isApplicationCommand()) {
|
||||||
|
await data.getSlashCommand().deferReply();
|
||||||
|
}
|
||||||
|
|
||||||
|
const embed = makeInfoEmbed({
|
||||||
|
icon: null,
|
||||||
|
title: `**${result.data.displayName}**`,
|
||||||
|
description: `**${
|
||||||
|
result.data.isFriend ? `${this.getState(result.data.status, result.data.state)}` : `⚪ Unknown`
|
||||||
|
}**\n\u200b`,
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: `${this.getTrustRankEmoji(result.data.tags)} ${this.getTrustRank(
|
||||||
|
result.data.tags
|
||||||
|
)}${this.getExtraRanks(result.data.tags)}`,
|
||||||
|
value: `\u200b`,
|
||||||
|
inline: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '✨ Status',
|
||||||
|
value: `${result.data.statusDescription || 'None'}\n\u200b`,
|
||||||
|
inline: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '🌏 Language',
|
||||||
|
value: `${this.listLanguages(result.data.tags)}\n\u200b`,
|
||||||
|
inline: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '✨ Bio',
|
||||||
|
value: `${result.data.bio}\n\u200b`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: `❤ Account Information`,
|
||||||
|
value: `Joined: <t:${Math.round(
|
||||||
|
new Date(result.data.date_joined).getTime() / 1000
|
||||||
|
)}:R>, <t:${Math.round(new Date(result.data.date_joined).getTime() / 1000)}:f>
|
||||||
|
Avatar Cloning: ${result.data.allowAvatarCopying ? 'Enabled' : 'Disabled'}
|
||||||
|
User ID: \`\`${result.data.id}\`\`\n`
|
||||||
|
}
|
||||||
|
],
|
||||||
|
user: data.getUser()
|
||||||
|
});
|
||||||
|
embed.setAuthor({
|
||||||
|
name: `VRChat Profile`,
|
||||||
|
url: `https://vrchat.com/home/user/${result.data.id}`,
|
||||||
|
iconURL:
|
||||||
|
'https://www.theladders.com/s3proxy/company-photo.theladders.com/68949/5721f0dd-d662-4b5e-9c0b-236b8a41b0d3.png'
|
||||||
|
});
|
||||||
|
|
||||||
|
let userMainImage;
|
||||||
|
|
||||||
|
if (result.data.userIcon) userMainImage = result.data.userIcon;
|
||||||
|
else if (result.data.currentAvatarImageUrl) userMainImage = result.data.currentAvatarImageUrl;
|
||||||
|
|
||||||
|
if (userMainImage)
|
||||||
|
embed.setThumbnail(
|
||||||
|
ImagePorxy.signImageProxyURL(userMainImage, 'resize:fill:150:150:0') ||
|
||||||
|
'https://osu.ppy.sh/images/layout/avatar-guest.png'
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result.data.profilePicOverride)
|
||||||
|
embed.setImage(
|
||||||
|
ImagePorxy.signImageProxyURL(result.data.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/${result.data.id}`)
|
||||||
|
.setStyle(ButtonStyle.Link)
|
||||||
|
]);
|
||||||
|
|
||||||
|
for (let link of result.data.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,255 @@
|
|||||||
|
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 world;
|
||||||
|
if (data.isMessage()) {
|
||||||
|
if (typeof args[1] === 'undefined')
|
||||||
|
return await sendHybridInteractionMessageResponse(data, {
|
||||||
|
embeds: [EMBEDS.NO_WORLD_MENTIONED(data)]
|
||||||
|
});
|
||||||
|
const [removed, ...newArgs] = args;
|
||||||
|
world = newArgs.join(' ');
|
||||||
|
} else if (data.isApplicationCommand()) world = data.getSlashCommand().options.get('world')?.value?.toString();
|
||||||
|
|
||||||
|
let result;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (world.startsWith('wrld_')) result = await VRChatAPI.client!.WorldsApi.getWorld(world);
|
||||||
|
else {
|
||||||
|
let search_result = await VRChatAPI.client!.WorldsApi.searchWorlds(
|
||||||
|
undefined,
|
||||||
|
VRChat.SortOption.Relevance,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
100,
|
||||||
|
undefined, //VRChat.OrderOption.Descending,
|
||||||
|
undefined,
|
||||||
|
world
|
||||||
|
);
|
||||||
|
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() === world.toLowerCase()) {
|
||||||
|
result = await VRChatAPI.client!.WorldsApi.getWorld(search_result.data[i].id);
|
||||||
|
foundExact = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!foundExact) result = await VRChatAPI.client!.WorldsApi.getWorld(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.client!.UsersApi.getUser(result.data.authorId);
|
||||||
|
|
||||||
|
const embed = makeInfoEmbed({
|
||||||
|
icon: null,
|
||||||
|
title: `**${result.data.name}**`,
|
||||||
|
description: `Created by **[${result.data.authorName}](https://vrchat.com/home/user/${author.data.id})**\n\u200b`,
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: '🌎 World Description',
|
||||||
|
value: `${result.data.description}\n\u200b`,
|
||||||
|
inline: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: `${this.getReleaseStatusEmoji(result.data)} Visiblity`,
|
||||||
|
value: `${this.getReleaseStatus(result.data)}\n\u200b`,
|
||||||
|
inline: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '✨ Visits',
|
||||||
|
value: `${this.numberWithCommas(result.data.visits)}\n\u200b`,
|
||||||
|
inline: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '💕 Favorites',
|
||||||
|
value: `${result.data.favorites ? this.numberWithCommas(result.data.favorites) : 0}\n\u200b`,
|
||||||
|
inline: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '👥 Players',
|
||||||
|
value: `${result.data.occupants ? this.numberWithCommas(result.data.occupants) : 0} ${
|
||||||
|
result.data.instances
|
||||||
|
? `(${this.numberWithCommas(
|
||||||
|
result.data.publicOccupants || 0
|
||||||
|
)} public, ${this.numberWithCommas(result.data.privateOccupants || 0)} private)`
|
||||||
|
: ''
|
||||||
|
}\n\u200b`,
|
||||||
|
inline: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '💖 Popularity',
|
||||||
|
value: `${this.numberWithCommas(result.data.popularity)}\n\u200b`,
|
||||||
|
inline: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '🔥 Heat',
|
||||||
|
value: `${result.data.heat}\n\u200b`,
|
||||||
|
inline: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '📥 Capacity',
|
||||||
|
value: `${result.data.capacity}\n\u200b`,
|
||||||
|
inline: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '📅 Last updated',
|
||||||
|
value: `<t:${Math.round(new Date(result.data.updated_at).getTime() / 1000)}:R>\n<t:${Math.round(
|
||||||
|
new Date(result.data.updated_at).getTime() / 1000
|
||||||
|
)}:f>\n\u200b`,
|
||||||
|
inline: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '📅 Created at',
|
||||||
|
value: `<t:${Math.round(new Date(result.data.created_at).getTime() / 1000)}:R>\n<t:${Math.round(
|
||||||
|
new Date(result.data.created_at).getTime() / 1000
|
||||||
|
)}:f>\n\u200b`,
|
||||||
|
inline: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: `❤ World Information`,
|
||||||
|
value: `World ID: \`\`${result.data.id}\`\`\nCreator ID: \`\`${result.data.authorId}\`\`\n`
|
||||||
|
}
|
||||||
|
],
|
||||||
|
user: data.getUser()
|
||||||
|
});
|
||||||
|
|
||||||
|
embed.setAuthor({
|
||||||
|
name: `VRChat World`,
|
||||||
|
url: `https://vrchat.com/home/world/${result.data.id}`,
|
||||||
|
iconURL:
|
||||||
|
'https://www.theladders.com/s3proxy/company-photo.theladders.com/68949/5721f0dd-d662-4b5e-9c0b-236b8a41b0d3.png'
|
||||||
|
});
|
||||||
|
|
||||||
|
let mainImage;
|
||||||
|
|
||||||
|
if (result.data.thumbnailImageUrl) mainImage = result.data.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.data.userIcon) userMainImage = author.data.userIcon;
|
||||||
|
else if (author.data.currentAvatarImageUrl) userMainImage = author.data.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.data.id}`)
|
||||||
|
.setStyle(ButtonStyle.Link),
|
||||||
|
new ButtonBuilder()
|
||||||
|
.setEmoji('🔗')
|
||||||
|
.setLabel(` ${author.data.displayName}'s Profile`)
|
||||||
|
.setURL(`https://vrchat.com/home/user/${author.data.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@ 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;
|
||||||
|
|||||||
@@ -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(),
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,15 @@ 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 {
|
||||||
@@ -76,6 +84,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 +109,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,53 @@
|
|||||||
|
import { Configuration, AuthenticationApi, UsersApi, WorldsApi } from 'vrchat';
|
||||||
|
import Environment from './Environment';
|
||||||
|
import Logger from '../libs/Logger';
|
||||||
|
|
||||||
|
import App from './App';
|
||||||
|
|
||||||
|
interface VRChatAPIs {
|
||||||
|
AuthenticationApi: AuthenticationApi;
|
||||||
|
UsersApi: UsersApi;
|
||||||
|
WorldsApi: WorldsApi;
|
||||||
|
}
|
||||||
|
|
||||||
|
class VRChatAPI {
|
||||||
|
public client: VRChatAPIs | null;
|
||||||
|
public configuration: Configuration | null;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.client = null;
|
||||||
|
this.configuration = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async init() {
|
||||||
|
this.configuration = new Configuration({
|
||||||
|
//username: Environment.get().VRC_USERNAME,
|
||||||
|
//;password: Environment.get().VRC_PASSWORD,
|
||||||
|
apiKey: Environment.get().VRC_API_KEY,
|
||||||
|
baseOptions: {
|
||||||
|
headers: {
|
||||||
|
'User-Agent': `Yumi/${App.version.replaceAll('/', '').replaceAll(' ', '-').replaceAll('--', '-')} ${
|
||||||
|
Environment.get().VRC_CONTACT_EMAIL
|
||||||
|
}`,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
Cookie: Environment.get().VRC_COOKIE || ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.client = {
|
||||||
|
AuthenticationApi: new AuthenticationApi(this.configuration),
|
||||||
|
UsersApi: new UsersApi(this.configuration),
|
||||||
|
WorldsApi: new 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
public end(): void {}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default new VRChatAPI();
|
||||||
@@ -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