mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-04-26 18:23:47 +02:00
474 lines
18 KiB
JavaScript
474 lines
18 KiB
JavaScript
import { reactive, ref } from 'vue';
|
|
import { defineStore } from 'pinia';
|
|
import { useI18n } from 'vue-i18n';
|
|
|
|
import {
|
|
getGroupName,
|
|
getLaunchURL,
|
|
isRealInstance,
|
|
isRpcWorld,
|
|
parseLocation
|
|
} from '../../shared/utils';
|
|
import {
|
|
getPlatformLabel,
|
|
getRpcWorldConfig,
|
|
getStatusInfo,
|
|
isPopcornPalaceWorld
|
|
} from '../../shared/utils/discordPresence';
|
|
import {
|
|
ActivityType,
|
|
StatusDisplayType
|
|
} from '../../shared/constants/discord';
|
|
import { queryRequest } from '../../api';
|
|
import { useGameLogStore } from '../gameLog';
|
|
import { useGameStore } from '../game';
|
|
import { useLocationStore } from '../location';
|
|
import { useUpdateLoopStore } from '../updateLoop';
|
|
import { useUserStore } from '../user';
|
|
|
|
import configRepository from '../../services/config';
|
|
|
|
export const useDiscordPresenceSettingsStore = defineStore(
|
|
'DiscordPresenceSettings',
|
|
() => {
|
|
const locationStore = useLocationStore();
|
|
const gameStore = useGameStore();
|
|
const gameLogStore = useGameLogStore();
|
|
const userStore = useUserStore();
|
|
const updateLoopStore = useUpdateLoopStore();
|
|
const { t } = useI18n();
|
|
|
|
const state = reactive({
|
|
isDiscordActive: false,
|
|
lastLocationDetails: {
|
|
tag: '',
|
|
instanceName: '',
|
|
accessType: '',
|
|
worldId: '',
|
|
worldName: '',
|
|
thumbnailImageUrl: '',
|
|
worldCapacity: 0,
|
|
joinUrl: '',
|
|
worldLink: '',
|
|
accessName: '',
|
|
groupAccessType: '',
|
|
groupAccessName: ''
|
|
}
|
|
});
|
|
|
|
const discordActive = ref(false);
|
|
const discordInstance = ref(true);
|
|
const discordHideInvite = ref(true);
|
|
const discordJoinButton = ref(false);
|
|
const discordHideImage = ref(false);
|
|
const discordShowPlatform = ref(true);
|
|
const discordWorldIntegration = ref(true);
|
|
const discordWorldNameAsDiscordStatus = ref(false);
|
|
|
|
/**
|
|
*
|
|
*/
|
|
function setDiscordActive() {
|
|
discordActive.value = !discordActive.value;
|
|
configRepository.setBool('discordActive', discordActive.value);
|
|
}
|
|
/**
|
|
*
|
|
*/
|
|
function setDiscordInstance() {
|
|
discordInstance.value = !discordInstance.value;
|
|
configRepository.setBool('discordInstance', discordInstance.value);
|
|
}
|
|
/**
|
|
*
|
|
*/
|
|
function setDiscordHideInvite() {
|
|
discordHideInvite.value = !discordHideInvite.value;
|
|
configRepository.setBool(
|
|
'discordHideInvite',
|
|
discordHideInvite.value
|
|
);
|
|
}
|
|
/**
|
|
*
|
|
*/
|
|
function setDiscordJoinButton() {
|
|
discordJoinButton.value = !discordJoinButton.value;
|
|
configRepository.setBool(
|
|
'discordJoinButton',
|
|
discordJoinButton.value
|
|
);
|
|
}
|
|
/**
|
|
*
|
|
*/
|
|
function setDiscordHideImage() {
|
|
discordHideImage.value = !discordHideImage.value;
|
|
configRepository.setBool(
|
|
'discordHideImage',
|
|
discordHideImage.value
|
|
);
|
|
}
|
|
/**
|
|
*
|
|
*/
|
|
function setDiscordShowPlatform() {
|
|
discordShowPlatform.value = !discordShowPlatform.value;
|
|
configRepository.setBool(
|
|
'discordShowPlatform',
|
|
discordShowPlatform.value
|
|
);
|
|
}
|
|
/**
|
|
*
|
|
*/
|
|
function setDiscordWorldIntegration() {
|
|
discordWorldIntegration.value = !discordWorldIntegration.value;
|
|
configRepository.setBool(
|
|
'discordWorldIntegration',
|
|
discordWorldIntegration.value
|
|
);
|
|
}
|
|
/**
|
|
*
|
|
*/
|
|
function setDiscordWorldNameAsDiscordStatus() {
|
|
discordWorldNameAsDiscordStatus.value =
|
|
!discordWorldNameAsDiscordStatus.value;
|
|
configRepository.setBool(
|
|
'discordWorldNameAsDiscordStatus',
|
|
discordWorldNameAsDiscordStatus.value
|
|
);
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
async function initDiscordPresenceSettings() {
|
|
const [
|
|
discordActiveConfig,
|
|
discordInstanceConfig,
|
|
discordHideInviteConfig,
|
|
discordJoinButtonConfig,
|
|
discordHideImageConfig,
|
|
discordShowPlatformConfig,
|
|
discordWorldIntegrationConfig,
|
|
discordWorldNameAsDiscordStatusConfig
|
|
] = await Promise.all([
|
|
configRepository.getBool('discordActive', false),
|
|
configRepository.getBool('discordInstance', true),
|
|
configRepository.getBool('discordHideInvite', true),
|
|
configRepository.getBool('discordJoinButton', false),
|
|
configRepository.getBool('discordHideImage', false),
|
|
configRepository.getBool('discordShowPlatform', true),
|
|
configRepository.getBool('discordWorldIntegration', true),
|
|
configRepository.getBool(
|
|
'discordWorldNameAsDiscordStatus',
|
|
false
|
|
)
|
|
]);
|
|
|
|
discordActive.value = discordActiveConfig;
|
|
discordInstance.value = discordInstanceConfig;
|
|
discordHideInvite.value = discordHideInviteConfig;
|
|
discordJoinButton.value = discordJoinButtonConfig;
|
|
discordHideImage.value = discordHideImageConfig;
|
|
discordShowPlatform.value = discordShowPlatformConfig;
|
|
discordWorldIntegration.value = discordWorldIntegrationConfig;
|
|
discordWorldNameAsDiscordStatus.value =
|
|
discordWorldNameAsDiscordStatusConfig;
|
|
}
|
|
|
|
initDiscordPresenceSettings();
|
|
|
|
/**
|
|
*
|
|
*/
|
|
async function updateDiscord() {
|
|
let currentLocation = locationStore.lastLocation.location;
|
|
let startTime = locationStore.lastLocation.date;
|
|
if (locationStore.lastLocation.location === 'traveling') {
|
|
currentLocation = locationStore.lastLocationDestination;
|
|
startTime = locationStore.lastLocationDestinationTime;
|
|
}
|
|
if (!currentLocation) {
|
|
// game log disabled, use API location
|
|
currentLocation = userStore.currentUser.$locationTag;
|
|
startTime = userStore.currentUser.$location_at;
|
|
if (userStore.currentUser.$travelingToLocation) {
|
|
currentLocation =
|
|
userStore.currentUser.$travelingToLocation;
|
|
}
|
|
}
|
|
if (!discordActive.value || !isRealInstance(currentLocation)) {
|
|
setIsDiscordActive(false);
|
|
return;
|
|
}
|
|
if (currentLocation !== state.lastLocationDetails.tag) {
|
|
const L = parseLocation(currentLocation);
|
|
state.lastLocationDetails = {
|
|
tag: L.tag,
|
|
instanceName: L.instanceName,
|
|
accessType: L.accessType,
|
|
worldId: L.worldId,
|
|
worldName: '',
|
|
thumbnailImageUrl: '',
|
|
worldCapacity: 0,
|
|
joinUrl: '',
|
|
worldLink: '',
|
|
accessName: '',
|
|
groupAccessType: '',
|
|
groupAccessName: ''
|
|
};
|
|
try {
|
|
const args = await queryRequest.fetch('world.location', {
|
|
worldId: L.worldId
|
|
});
|
|
state.lastLocationDetails.worldName = args.ref.name;
|
|
state.lastLocationDetails.thumbnailImageUrl =
|
|
args.ref.thumbnailImageUrl;
|
|
state.lastLocationDetails.worldCapacity = args.ref.capacity;
|
|
if (args.ref.releaseStatus === 'public') {
|
|
state.lastLocationDetails.worldLink = `https://vrchat.com/home/world/${L.worldId}`;
|
|
}
|
|
} catch (e) {
|
|
console.error(
|
|
`Failed to get world details for ${L.worldId}`,
|
|
e
|
|
);
|
|
}
|
|
|
|
let platform = '';
|
|
if (discordShowPlatform.value) {
|
|
platform = getPlatformLabel(
|
|
userStore.currentUser.presence.platform,
|
|
gameStore.isGameRunning,
|
|
gameStore.isGameNoVR,
|
|
t
|
|
);
|
|
}
|
|
state.lastLocationDetails.groupAccessType = L.groupAccessType;
|
|
if (L.groupAccessType) {
|
|
if (L.groupAccessType === 'public') {
|
|
state.lastLocationDetails.groupAccessName = t(
|
|
'dialog.new_instance.group_access_type_public'
|
|
);
|
|
} else if (L.groupAccessType === 'plus') {
|
|
state.lastLocationDetails.groupAccessName = t(
|
|
'dialog.new_instance.group_access_type_plus'
|
|
);
|
|
}
|
|
}
|
|
switch (L.accessType) {
|
|
case 'public':
|
|
state.lastLocationDetails.joinUrl = getLaunchURL(L);
|
|
state.lastLocationDetails.accessName = `${t('dialog.new_instance.access_type_public')} #${L.instanceName}${platform}`;
|
|
break;
|
|
case 'invite+':
|
|
state.lastLocationDetails.accessName = `${t('dialog.new_instance.access_type_invite_plus')} #${L.instanceName}${platform}`;
|
|
break;
|
|
case 'invite':
|
|
state.lastLocationDetails.accessName = `${t('dialog.new_instance.access_type_invite')} #${L.instanceName}${platform}`;
|
|
break;
|
|
case 'friends':
|
|
state.lastLocationDetails.accessName = `${t('dialog.new_instance.access_type_friend')} #${L.instanceName}${platform}`;
|
|
break;
|
|
case 'friends+':
|
|
state.lastLocationDetails.accessName = `${t('dialog.new_instance.access_type_friend_plus')} #${L.instanceName}${platform}`;
|
|
break;
|
|
case 'group':
|
|
state.lastLocationDetails.accessName = `${t('dialog.new_instance.access_type_group')} #${L.instanceName}${platform}`;
|
|
try {
|
|
const groupName = await getGroupName(L.groupId);
|
|
if (groupName) {
|
|
state.lastLocationDetails.accessName = `${t('dialog.new_instance.access_type_group')}${state.lastLocationDetails.groupAccessName}(${groupName}) #${L.instanceName}${platform}`;
|
|
}
|
|
} catch (e) {
|
|
console.error(
|
|
`Failed to get group name for ${L.groupId}`,
|
|
e
|
|
);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
setIsDiscordActive(true);
|
|
let hidePrivate = false;
|
|
if (
|
|
discordHideInvite.value &&
|
|
(state.lastLocationDetails.accessType === 'invite' ||
|
|
state.lastLocationDetails.accessType === 'invite+' ||
|
|
state.lastLocationDetails.groupAccessType === 'members')
|
|
) {
|
|
hidePrivate = true;
|
|
}
|
|
const statusInfo = getStatusInfo(
|
|
userStore.currentUser.status,
|
|
discordHideInvite.value,
|
|
t
|
|
);
|
|
const { statusName, statusImage } = statusInfo;
|
|
if (statusInfo.hidePrivate) {
|
|
hidePrivate = true;
|
|
}
|
|
let details = state.lastLocationDetails.worldName;
|
|
let stateText = state.lastLocationDetails.accessName;
|
|
let endTime = 0;
|
|
let activityType = ActivityType.Playing;
|
|
let statusDisplayType = discordWorldNameAsDiscordStatus.value
|
|
? StatusDisplayType.Details
|
|
: StatusDisplayType.Name;
|
|
let appId = '883308884863901717';
|
|
let bigIcon = 'vrchat';
|
|
let detailsUrl = state.lastLocationDetails.worldLink;
|
|
let poweredBy = t(
|
|
'view.settings.discord_presence.rpc.powered_by_vrcx'
|
|
);
|
|
|
|
let partyId = `${state.lastLocationDetails.worldId}:${state.lastLocationDetails.instanceName}`;
|
|
let partySize = locationStore.lastLocation.playerList.size;
|
|
let partyMaxSize = state.lastLocationDetails.worldCapacity;
|
|
if (partySize > partyMaxSize) {
|
|
partyMaxSize = partySize;
|
|
}
|
|
if (partySize === 0) {
|
|
partyMaxSize = 0;
|
|
}
|
|
if (!discordInstance.value) {
|
|
partySize = 0;
|
|
partyMaxSize = 0;
|
|
stateText = '';
|
|
}
|
|
let buttonText = 'Join';
|
|
let buttonUrl = state.lastLocationDetails.joinUrl;
|
|
if (!discordJoinButton.value) {
|
|
buttonText = '';
|
|
buttonUrl = '';
|
|
}
|
|
|
|
const rpcConfig =
|
|
isRpcWorld(state.lastLocationDetails.tag) &&
|
|
discordWorldIntegration.value
|
|
? getRpcWorldConfig(state.lastLocationDetails.worldId)
|
|
: null;
|
|
|
|
if (rpcConfig) {
|
|
activityType = rpcConfig.activityType;
|
|
statusDisplayType = rpcConfig.statusDisplayType;
|
|
appId = rpcConfig.appId;
|
|
bigIcon = rpcConfig.bigIcon;
|
|
if (
|
|
isPopcornPalaceWorld(state.lastLocationDetails.worldId) &&
|
|
!discordHideImage.value &&
|
|
gameLogStore.nowPlaying.thumbnailUrl
|
|
) {
|
|
bigIcon = gameLogStore.nowPlaying.thumbnailUrl;
|
|
}
|
|
if (gameLogStore.nowPlaying.name) {
|
|
details = gameLogStore.nowPlaying.name;
|
|
}
|
|
if (gameLogStore.nowPlaying.playing) {
|
|
startTime = gameLogStore.nowPlaying.startTime * 1000;
|
|
endTime =
|
|
(gameLogStore.nowPlaying.startTime +
|
|
gameLogStore.nowPlaying.length) *
|
|
1000;
|
|
}
|
|
} else if (
|
|
!discordHideImage.value &&
|
|
state.lastLocationDetails.thumbnailImageUrl
|
|
) {
|
|
bigIcon = state.lastLocationDetails.thumbnailImageUrl;
|
|
}
|
|
|
|
if (hidePrivate) {
|
|
partyId = '';
|
|
partySize = 0;
|
|
partyMaxSize = 0;
|
|
buttonText = '';
|
|
buttonUrl = '';
|
|
detailsUrl = '';
|
|
details = t('view.settings.discord_presence.rpc.private_world');
|
|
stateText = '';
|
|
startTime = 0;
|
|
endTime = 0;
|
|
appId = '883308884863901717'; // default VRChat app id
|
|
bigIcon = 'vrchat';
|
|
activityType = ActivityType.Playing;
|
|
statusDisplayType = StatusDisplayType.Name;
|
|
}
|
|
if (details.length < 2) {
|
|
// 글자 수가 짧으면 업데이트가 안된다..
|
|
details += '\uFFA0'.repeat(2 - details.length);
|
|
}
|
|
Discord.SetAssets(
|
|
details, // main text
|
|
stateText, // secondary text
|
|
detailsUrl, // details url
|
|
|
|
bigIcon, // big icon
|
|
poweredBy, // big icon hover text
|
|
|
|
statusImage, // small icon
|
|
statusName, // small icon hover text
|
|
|
|
startTime,
|
|
endTime,
|
|
|
|
partyId, // party id
|
|
partySize, // party size
|
|
partyMaxSize, // party max size
|
|
buttonText, // button text
|
|
buttonUrl, // button url
|
|
appId, // app id
|
|
activityType, // activity type
|
|
statusDisplayType // status display type
|
|
);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param active
|
|
*/
|
|
async function setIsDiscordActive(active) {
|
|
if (active !== state.isDiscordActive) {
|
|
state.isDiscordActive = await Discord.SetActive(active);
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param configLabel
|
|
*/
|
|
async function saveDiscordOption(configLabel = '') {
|
|
state.lastLocationDetails.tag = '';
|
|
updateLoopStore.setNextDiscordUpdate(3);
|
|
updateDiscord();
|
|
}
|
|
|
|
return {
|
|
state,
|
|
|
|
discordActive,
|
|
discordInstance,
|
|
discordHideInvite,
|
|
discordJoinButton,
|
|
discordHideImage,
|
|
discordShowPlatform,
|
|
discordWorldIntegration,
|
|
discordWorldNameAsDiscordStatus,
|
|
|
|
setDiscordActive,
|
|
setDiscordInstance,
|
|
setDiscordHideInvite,
|
|
setDiscordJoinButton,
|
|
setDiscordHideImage,
|
|
setDiscordShowPlatform,
|
|
setDiscordWorldIntegration,
|
|
setDiscordWorldNameAsDiscordStatus,
|
|
updateDiscord,
|
|
saveDiscordOption
|
|
};
|
|
}
|
|
);
|