127 lines
4.4 KiB
JavaScript
127 lines
4.4 KiB
JavaScript
require("dotenv").config();
|
|
var Discord = require("discord.js");
|
|
var vrchat = require("vrchat");
|
|
var exithook = require("async-exit-hook");
|
|
|
|
var client = new Discord.Client({intents: 32767});
|
|
var vrc = {
|
|
configuration: {
|
|
username: process.env.VRC_USERNAME,
|
|
password: process.env.VRC_PASSWORD
|
|
}
|
|
};
|
|
vrc.authenticationApi = new vrchat.AuthenticationApi(vrc.configuration);
|
|
vrc.usersApi = new vrchat.UsersApi(vrc.configuration);
|
|
vrc.friendsApi = new vrchat.FriendsApi(vrc.configuration);
|
|
vrc.worldsApi = new vrchat.WorldsApi(vrc.configuration);
|
|
var VRCAT = "959236139913445376";
|
|
var SUBCH_PFX = '┗';
|
|
var status2icon = {
|
|
"join me": '🔵',
|
|
"active": '🟢',
|
|
"ask me": '🟠',
|
|
"busy": '🔴',
|
|
"offline": '⚫'
|
|
}
|
|
var selfUserId;
|
|
|
|
client.login(process.env.TOKEN).then(() => {
|
|
console.log("discord login", client.user.tag);
|
|
}).catch(error => {
|
|
console.log("discord login fail", error.stack)
|
|
});
|
|
|
|
client.once("ready", async () => {
|
|
var vrcat = client.channels.resolve(VRCAT);
|
|
if (!vrcat) return console.log("category not found");
|
|
for (let child of vrcat.children.values()) await child.delete();
|
|
exithook(async cb => {
|
|
console.log("discord cleanup");
|
|
for (let child of vrcat.children.values()) await child.delete();
|
|
client.destroy();
|
|
console.log("discord destroyed");
|
|
cb();
|
|
});
|
|
try {
|
|
var logindata = await vrc.authenticationApi.getCurrentUser().then(res => res.data);
|
|
} catch (error) {
|
|
console.log("vrc login fail:", JSON.stringify(error.response.data));
|
|
vrcat.createChannel("login failure", {type: "GUILD_VOICE"}).catch(()=>{});
|
|
}
|
|
if (!logindata) return;
|
|
console.log("vrc login", logindata.username);
|
|
selfUserId = logindata.id;
|
|
exithook(cb => {
|
|
console.log("vrc logout");
|
|
vrc.authenticationApi.logout().then(res => {
|
|
console.log("vrc", res.data);
|
|
cb();
|
|
});
|
|
});
|
|
do {
|
|
try {
|
|
await syncStat();
|
|
} catch (error) {
|
|
console.log("syncStat", error.message);
|
|
if (error.response?.status == 401 /* && error.response.data.message == "\"Missing Credentials\"" /* todo? */) {
|
|
console.log(error.response.data);
|
|
try {
|
|
var logindata = await vrc.authenticationApi.getCurrentUser().then(res => res.data);
|
|
console.log("vrc relogin", logindata.username);
|
|
selfUserId = logindata.id;
|
|
} catch (error) {
|
|
console.log("relogin fail", error.message, logindata);
|
|
vrcat.createChannel("login failure", {type: "GUILD_VOICE"}).catch(()=>{});
|
|
await new Promise(r => setTimeout(r, 1000*60*60));
|
|
}
|
|
} else {
|
|
vrcat.createChannel(error.response?.status?.toString() || error.message, {type: "GUILD_VOICE"}).catch(()=>{});
|
|
}
|
|
}
|
|
await new Promise(r => setTimeout(r, 1000*60*5));
|
|
} while (true);
|
|
});
|
|
|
|
async function syncStat() {
|
|
var friendsOnline = await vrc.friendsApi.getFriends(0, 50, false).then(x => x.data);
|
|
friendsOnline = friendsOnline.filter(x => x.location);
|
|
var selfUser = await vrc.usersApi.getUser(selfUserId).then(res => res.data);
|
|
if (selfUser.state == "online") friendsOnline.unshift(selfUser);
|
|
//console.debug(friendsOnline.map(m => m.displayName));
|
|
for (let fren of friendsOnline) {
|
|
try {
|
|
let vcnam = `${status2icon[fren.status]} ${fren.displayName}`.substring(0,100);
|
|
let subvcnam = `${SUBCH_PFX} ${await getWorldNameForId(fren.location.split(':')[0])}`.substring(0,100);
|
|
let vc = client.channels.resolve(VRCAT).children.find(vc => vc.vrcuid == fren.id);
|
|
if (vc) {
|
|
if (vc.name != vcnam) await vc.setName(vcnam);
|
|
if (vc.subvc && vc.subvc.name != subvcnam) await vc.subvc.setName(subvcnam);
|
|
} else {
|
|
vc = await client.channels.resolve(VRCAT).createChannel(vcnam, {type: "GUILD_VOICE"});
|
|
vc.subvc = await client.channels.resolve(VRCAT).createChannel(subvcnam, {type: "GUILD_VOICE"});
|
|
vc.vrcuid = fren.id;
|
|
}
|
|
} catch(error) {
|
|
console.log(`fren ${fren.username} brok:`, error);
|
|
}
|
|
}
|
|
for (let vc of client.channels.resolve(VRCAT).children.values()) {
|
|
if (vc.vrcuid && !friendsOnline.some(fren => fren.id == vc.vrcuid)) {
|
|
await vc.delete();
|
|
await vc.subvc?.delete();
|
|
}
|
|
}
|
|
}
|
|
|
|
var worldnamecache = {};
|
|
async function getWorldNameForId(worldId) {
|
|
if (!worldId || worldId == "offline") return;
|
|
if (worldId == "private") return "Private World";
|
|
return worldnamecache[worldId] = worldnamecache[worldId] || (await vrc.worldsApi.getWorld(worldId)).data.name;
|
|
}
|
|
|
|
|
|
global.client = client;
|
|
global.vrc = vrc;
|
|
global.syncStat = syncStat;
|