import 'dotenv/config'; import vrchat from "vrchat"; import globalAxios from "axios"; import { CookieJar } from "tough-cookie"; import FileCookieStore from 'tough-cookie-file-store'; globalAxios.defaults.jar = new CookieJar(new FileCookieStore("./cookies.json")); import {Bot, RichText} from "@skyware/bot"; var bot = new Bot({ emitEvents: false }); await bot.login({ identifier: process.env.BSKY_DID, password: process.env.BSKY_PW }); var conversation = await bot.getConversationForMembers([process.env.BSKY_ADMIN_DID]); //await conversation.sendMessage({text: "bot start"}); var vrc_conf = new vrchat.Configuration({ username: process.env.VRC_USR, password: process.env.VRC_PW, baseOptions: {headers: {"User-Agent": "fishcat"}} }); var vrc_auth_api = new vrchat.AuthenticationApi(vrc_conf); //var vrc_users_api = new vrchat.UsersApi(vrc_conf); var vrc_friends_api = new vrchat.FriendsApi(vrc_conf); //var vrc_worlds_api = new vrchat.WorldsApi(vrc_conf); var vrc_user; async function get_current_user_or_login() { var res = await vrc_auth_api.getCurrentUser(); console.debug(res); vrc_user = res.data; if (vrc_user.requiresTwoFactorAuth) { if (vrc_user.requiresTwoFactorAuth[0] == "emailOtp") { await prompt2fa(); await get_current_user_or_login(); } else { throw new Error("unsupported 2fa"); } } } async function prompt2fa() { console.log("prompt 2fa"); await conversation.sendMessage({text: "2fa required"}); do { await new Promise(r => setTimeout(r, 5000)); var {messages} = await conversation.getMessages(); var lastmsg = messages[0]; if (lastmsg.senderDid != process.env.BSKY_ADMIN_DID) continue; var code = lastmsg.text.match(/\d{6}/)?.[0]; if (!code) { await conversation.sendMessage({text: "invalid"}); continue; } var res = await vrc_auth_api.verify2FAEmailCode({code}); console.debug(res); await conversation.sendMessage({text: "ok"}); } while (!code) } //await get_current_user_or_login(); var last_online; async function check_friends() { await get_current_user_or_login(); var online = await vrc_friends_api.getFriends(0, 50, false).then(res => res.data); online = online.filter(user => user.location && user.location != "offline"); if (vrc_user.state == "online") online.unshift(vrc_user); console.debug("online", online); if (last_online) { var went_online = []; var went_offline = []; for (let user of online) { let last_user = last_online.find(u => u.id == user.id); if (!last_user) { // user went online went_online.push(user); } } for (let last_user of last_online) { let now_user = online.find(u => u.id == last_user.id); if (!now_user) { // user went offline went_offline.push(last_user); } } } if (!last_online || went_online?.length || went_offline?.length) { let priv = online.filter(user => user.location == "private"); let notpriv = online.filter(user => user.location != "private"); let text = new RichText(); if (notpriv.length) { text.addText("Online: ") for (let u of notpriv) { text.addLink(u.displayName, `https://vrchat.com/home/user/${u.id}`); text.addText(", "); } } if (priv.length) { text.addText("\n\nPrivate: "); for (let u of priv) { text.addLink(u.displayName, `https://vrchat.com/home/user/${u.id}`); text.addText(", "); } } let post = await bot.post({text}); console.log("posted", post.uri); } last_online = online; } while (true) { try { await check_friends(); } catch (error) { console.error(error.stack); } await new Promise(r => setTimeout(r, 1000*60*5)); }