mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-04-20 07:13:51 +02:00
1123 lines
43 KiB
JavaScript
1123 lines
43 KiB
JavaScript
import * as workerTimers from 'worker-timers';
|
|
import gameLogService from '../service/gamelog.js';
|
|
import configRepository from '../repository/config.js';
|
|
import { baseClass, $app, API, $t, $utils } from './baseClass.js';
|
|
|
|
export default class extends baseClass {
|
|
constructor(_app, _API, _t) {
|
|
super(_app, _API, _t);
|
|
}
|
|
|
|
_data = {
|
|
gameLogTable: {
|
|
data: [],
|
|
loading: false,
|
|
search: '',
|
|
filter: [],
|
|
tableProps: {
|
|
stripe: true,
|
|
size: 'mini',
|
|
defaultSort: {
|
|
prop: 'created_at',
|
|
order: 'descending'
|
|
}
|
|
},
|
|
pageSize: 15,
|
|
paginationProps: {
|
|
small: true,
|
|
layout: 'sizes,prev,pager,next,total',
|
|
pageSizes: [10, 15, 25, 50, 100]
|
|
}
|
|
},
|
|
gameLogSessionTable: [],
|
|
gameLogApiLoggingEnabled: false,
|
|
lastVideoUrl: '',
|
|
lastResourceloadUrl: ''
|
|
};
|
|
|
|
_methods = {
|
|
addGameLogEntry(gameLog, location) {
|
|
if (this.gameLogDisabled) {
|
|
return;
|
|
}
|
|
var userId = gameLog.userId;
|
|
if (!userId && gameLog.displayName) {
|
|
for (var ref of API.cachedUsers.values()) {
|
|
if (ref.displayName === gameLog.displayName) {
|
|
userId = ref.id;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
switch (gameLog.type) {
|
|
case 'location-destination':
|
|
if (this.isGameRunning) {
|
|
// needs to be added before OnPlayerLeft entries from LocationReset
|
|
this.addGameLog({
|
|
created_at: gameLog.dt,
|
|
type: 'LocationDestination',
|
|
location: gameLog.location
|
|
});
|
|
this.lastLocationReset(gameLog.dt);
|
|
this.lastLocation.location = 'traveling';
|
|
this.lastLocationDestination = gameLog.location;
|
|
this.lastLocationDestinationTime = Date.parse(
|
|
gameLog.dt
|
|
);
|
|
this.removeQueuedInstance(gameLog.location);
|
|
this.updateCurrentUserLocation();
|
|
this.clearNowPlaying();
|
|
this.updateCurrentInstanceWorld();
|
|
this.applyUserDialogLocation();
|
|
this.applyWorldDialogInstances();
|
|
this.applyGroupDialogInstances();
|
|
}
|
|
break;
|
|
case 'location':
|
|
this.addInstanceJoinHistory(
|
|
this.lastLocation.location,
|
|
gameLog.dt
|
|
);
|
|
var worldName = this.replaceBioSymbols(gameLog.worldName);
|
|
if (this.isGameRunning) {
|
|
this.lastLocationReset(gameLog.dt);
|
|
this.clearNowPlaying();
|
|
this.lastLocation = {
|
|
date: Date.parse(gameLog.dt),
|
|
location: gameLog.location,
|
|
name: worldName,
|
|
playerList: new Map(),
|
|
friendList: new Map()
|
|
};
|
|
this.removeQueuedInstance(gameLog.location);
|
|
this.updateCurrentUserLocation();
|
|
this.updateVRLastLocation();
|
|
this.updateCurrentInstanceWorld();
|
|
this.applyUserDialogLocation();
|
|
this.applyWorldDialogInstances();
|
|
this.applyGroupDialogInstances();
|
|
}
|
|
this.addInstanceJoinHistory(gameLog.location, gameLog.dt);
|
|
var L = $utils.parseLocation(gameLog.location);
|
|
var entry = {
|
|
created_at: gameLog.dt,
|
|
type: 'Location',
|
|
location: gameLog.location,
|
|
worldId: L.worldId,
|
|
worldName,
|
|
groupName: '',
|
|
time: 0
|
|
};
|
|
this.getGroupName(gameLog.location).then((groupName) => {
|
|
entry.groupName = groupName;
|
|
});
|
|
this.addGamelogLocationToDatabase(entry);
|
|
break;
|
|
case 'player-joined':
|
|
var joinTime = Date.parse(gameLog.dt);
|
|
var userMap = {
|
|
displayName: gameLog.displayName,
|
|
userId,
|
|
joinTime,
|
|
lastAvatar: ''
|
|
};
|
|
this.lastLocation.playerList.set(
|
|
gameLog.displayName,
|
|
userMap
|
|
);
|
|
if (userId) {
|
|
var ref = API.cachedUsers.get(userId);
|
|
if (userId === API.currentUser.id) {
|
|
// skip
|
|
} else if (this.friends.has(userId)) {
|
|
this.lastLocation.friendList.set(
|
|
gameLog.displayName,
|
|
userMap
|
|
);
|
|
if (
|
|
ref.location !== this.lastLocation.location &&
|
|
ref.travelingToLocation !==
|
|
this.lastLocation.location
|
|
) {
|
|
// fix $location_at with private
|
|
ref.$location_at = joinTime;
|
|
}
|
|
} else if (typeof ref !== 'undefined') {
|
|
// set $location_at to join time if user isn't a friend
|
|
ref.$location_at = joinTime;
|
|
} else {
|
|
if (this.debugGameLog || this.debugWebRequests) {
|
|
console.log(
|
|
'Fetching user from gameLog:',
|
|
userId
|
|
);
|
|
}
|
|
API.getUser({ userId });
|
|
}
|
|
} else {
|
|
// TODO: remove this
|
|
// try fetch userId from previous encounter using database
|
|
database
|
|
.getUserIdFromDisplayName(gameLog.displayName)
|
|
.then((oldUserId) => {
|
|
if (this.isGameRunning) {
|
|
if (oldUserId) {
|
|
API.getUser({ userId: oldUserId });
|
|
} else if (
|
|
Date.now() - joinTime <
|
|
5 * 1000
|
|
) {
|
|
workerTimers.setTimeout(
|
|
() =>
|
|
this.silentSearchUser(
|
|
gameLog.displayName
|
|
),
|
|
10 * 1000
|
|
);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
this.updateVRLastLocation();
|
|
this.getCurrentInstanceUserList();
|
|
var entry = {
|
|
created_at: gameLog.dt,
|
|
type: 'OnPlayerJoined',
|
|
displayName: gameLog.displayName,
|
|
location,
|
|
userId,
|
|
time: 0
|
|
};
|
|
database.addGamelogJoinLeaveToDatabase(entry);
|
|
break;
|
|
case 'player-left':
|
|
var ref = this.lastLocation.playerList.get(
|
|
gameLog.displayName
|
|
);
|
|
if (typeof ref === 'undefined') {
|
|
break;
|
|
}
|
|
var time = Date.now() - ref.joinTime;
|
|
this.lastLocation.playerList.delete(gameLog.displayName);
|
|
this.lastLocation.friendList.delete(gameLog.displayName);
|
|
this.photonLobbyAvatars.delete(userId);
|
|
this.updateVRLastLocation();
|
|
this.getCurrentInstanceUserList();
|
|
var entry = {
|
|
created_at: gameLog.dt,
|
|
type: 'OnPlayerLeft',
|
|
displayName: gameLog.displayName,
|
|
location,
|
|
userId,
|
|
time
|
|
};
|
|
database.addGamelogJoinLeaveToDatabase(entry);
|
|
break;
|
|
case 'portal-spawn':
|
|
if (this.ipcEnabled && this.isGameRunning) {
|
|
break;
|
|
}
|
|
var entry = {
|
|
created_at: gameLog.dt,
|
|
type: 'PortalSpawn',
|
|
location,
|
|
displayName: '',
|
|
userId: '',
|
|
instanceId: '',
|
|
worldName: ''
|
|
};
|
|
database.addGamelogPortalSpawnToDatabase(entry);
|
|
break;
|
|
case 'video-play':
|
|
gameLog.videoUrl = decodeURI(gameLog.videoUrl);
|
|
if (this.lastVideoUrl === gameLog.videoUrl) {
|
|
break;
|
|
}
|
|
this.lastVideoUrl = gameLog.videoUrl;
|
|
this.addGameLogVideo(gameLog, location, userId);
|
|
break;
|
|
case 'video-sync':
|
|
var timestamp = gameLog.timestamp.replace(/,/g, '');
|
|
if (this.nowPlaying.playing) {
|
|
this.nowPlaying.offset = parseInt(timestamp, 10);
|
|
}
|
|
break;
|
|
case 'resource-load-string':
|
|
case 'resource-load-image':
|
|
if (
|
|
!this.logResourceLoad ||
|
|
this.lastResourceloadUrl === gameLog.resourceUrl
|
|
) {
|
|
break;
|
|
}
|
|
this.lastResourceloadUrl = gameLog.resourceUrl;
|
|
var entry = {
|
|
created_at: gameLog.dt,
|
|
type:
|
|
gameLog.type === 'resource-load-string'
|
|
? 'StringLoad'
|
|
: 'ImageLoad',
|
|
resourceUrl: gameLog.resourceUrl,
|
|
location
|
|
};
|
|
database.addGamelogResourceLoadToDatabase(entry);
|
|
break;
|
|
case 'screenshot':
|
|
// var entry = {
|
|
// created_at: gameLog.dt,
|
|
// type: 'Event',
|
|
// data: `Screenshot Processed: ${gameLog.screenshotPath.replace(
|
|
// /^.*[\\/]/,
|
|
// ''
|
|
// )}`
|
|
// };
|
|
// database.addGamelogEventToDatabase(entry);
|
|
|
|
this.processScreenshot(gameLog.screenshotPath);
|
|
break;
|
|
case 'api-request':
|
|
var bias = Date.parse(gameLog.dt) + 60 * 1000;
|
|
if (
|
|
!this.isGameRunning ||
|
|
this.lastLocation.location === '' ||
|
|
this.lastLocation.location === 'traveling' ||
|
|
bias < Date.now()
|
|
) {
|
|
break;
|
|
}
|
|
var userId = '';
|
|
try {
|
|
var url = new URL(gameLog.url);
|
|
var urlParams = new URLSearchParams(gameLog.url);
|
|
if (url.pathname.substring(0, 13) === '/api/1/users/') {
|
|
var pathArray = url.pathname.split('/');
|
|
userId = pathArray[4];
|
|
} else if (urlParams.has('userId')) {
|
|
userId = urlParams.get('userId');
|
|
}
|
|
} catch (err) {
|
|
console.error(err);
|
|
}
|
|
if (!userId) {
|
|
break;
|
|
}
|
|
this.gameLogApiLoggingEnabled = true;
|
|
if (
|
|
API.cachedUsers.has(userId) ||
|
|
API.cachedPlayerModerationsUserIds.has(userId)
|
|
) {
|
|
break;
|
|
}
|
|
if (this.debugGameLog || this.debugWebRequests) {
|
|
console.log('Fetching user from gameLog:', userId);
|
|
}
|
|
API.getUser({ userId });
|
|
break;
|
|
case 'avatar-change':
|
|
var ref = this.lastLocation.playerList.get(
|
|
gameLog.displayName
|
|
);
|
|
if (
|
|
this.photonLoggingEnabled ||
|
|
typeof ref === 'undefined' ||
|
|
ref.lastAvatar === gameLog.avatarName
|
|
) {
|
|
break;
|
|
}
|
|
if (!ref.lastAvatar) {
|
|
ref.lastAvatar = gameLog.avatarName;
|
|
this.lastLocation.playerList.set(
|
|
gameLog.displayName,
|
|
ref
|
|
);
|
|
break;
|
|
}
|
|
ref.lastAvatar = gameLog.avatarName;
|
|
this.lastLocation.playerList.set(gameLog.displayName, ref);
|
|
var entry = {
|
|
created_at: gameLog.dt,
|
|
type: 'AvatarChange',
|
|
userId,
|
|
name: gameLog.avatarName,
|
|
displayName: gameLog.displayName
|
|
};
|
|
break;
|
|
case 'vrcx':
|
|
// VideoPlay(PyPyDance) "https://jd.pypy.moe/api/v1/videos/jr1NX4Jo8GE.mp4",0.1001,239.606,"0905 : [J-POP] 【まなこ】金曜日のおはよう 踊ってみた (vernities)"
|
|
var type = gameLog.data.substr(
|
|
0,
|
|
gameLog.data.indexOf(' ')
|
|
);
|
|
if (type === 'VideoPlay(PyPyDance)') {
|
|
this.addGameLogPyPyDance(gameLog, location);
|
|
} else if (type === 'VideoPlay(VRDancing)') {
|
|
this.addGameLogVRDancing(gameLog, location);
|
|
} else if (type === 'VideoPlay(ZuwaZuwaDance)') {
|
|
this.addGameLogZuwaZuwaDance(gameLog, location);
|
|
} else if (type === 'LSMedia') {
|
|
this.addGameLogLSMedia(gameLog, location);
|
|
} else if (type === 'Movie&Chill') {
|
|
this.addGameLogMovieAndChill(gameLog, location);
|
|
}
|
|
break;
|
|
case 'photon-id':
|
|
if (!this.isGameRunning || !this.friendLogInitStatus) {
|
|
break;
|
|
}
|
|
var photonId = parseInt(gameLog.photonId, 10);
|
|
var ref = this.photonLobby.get(photonId);
|
|
if (typeof ref === 'undefined') {
|
|
for (var ctx of API.cachedUsers.values()) {
|
|
if (ctx.displayName === gameLog.displayName) {
|
|
this.photonLobby.set(photonId, ctx);
|
|
this.photonLobbyCurrent.set(photonId, ctx);
|
|
break;
|
|
}
|
|
}
|
|
var ctx = {
|
|
displayName: gameLog.displayName
|
|
};
|
|
this.photonLobby.set(photonId, ctx);
|
|
this.photonLobbyCurrent.set(photonId, ctx);
|
|
this.getCurrentInstanceUserList();
|
|
}
|
|
break;
|
|
case 'notification':
|
|
// var entry = {
|
|
// created_at: gameLog.dt,
|
|
// type: 'Notification',
|
|
// data: gameLog.json
|
|
// };
|
|
break;
|
|
case 'event':
|
|
var entry = {
|
|
created_at: gameLog.dt,
|
|
type: 'Event',
|
|
data: gameLog.event
|
|
};
|
|
database.addGamelogEventToDatabase(entry);
|
|
break;
|
|
case 'vrc-quit':
|
|
if (!this.isGameRunning) {
|
|
break;
|
|
}
|
|
if (this.vrcQuitFix) {
|
|
var bias = Date.parse(gameLog.dt) + 3000;
|
|
if (bias < Date.now()) {
|
|
console.log(
|
|
'QuitFix: Bias too low, not killing VRC'
|
|
);
|
|
break;
|
|
}
|
|
AppApi.QuitGame().then((processCount) => {
|
|
if (processCount > 1) {
|
|
console.log(
|
|
'QuitFix: More than 1 process running, not killing VRC'
|
|
);
|
|
} else if (processCount === 1) {
|
|
console.log('QuitFix: Killed VRC');
|
|
} else {
|
|
console.log(
|
|
'QuitFix: Nothing to kill, no VRC process running'
|
|
);
|
|
}
|
|
});
|
|
}
|
|
break;
|
|
case 'openvr-init':
|
|
this.isGameNoVR = false;
|
|
configRepository.setBool('isGameNoVR', this.isGameNoVR);
|
|
this.updateOpenVR();
|
|
break;
|
|
case 'desktop-mode':
|
|
this.isGameNoVR = true;
|
|
configRepository.setBool('isGameNoVR', this.isGameNoVR);
|
|
this.updateOpenVR();
|
|
break;
|
|
case 'udon-exception':
|
|
if (this.udonExceptionLogging) {
|
|
console.log('UdonException', gameLog.data);
|
|
}
|
|
// var entry = {
|
|
// created_at: gameLog.dt,
|
|
// type: 'Event',
|
|
// data: gameLog.data
|
|
// };
|
|
// database.addGamelogEventToDatabase(entry);
|
|
break;
|
|
}
|
|
if (entry) {
|
|
// add tag colour
|
|
if (entry.userId) {
|
|
var tagRef = this.customUserTags.get(entry.userId);
|
|
if (typeof tagRef !== 'undefined') {
|
|
entry.tagColour = tagRef.colour;
|
|
}
|
|
}
|
|
this.queueGameLogNoty(entry);
|
|
this.addGameLog(entry);
|
|
}
|
|
},
|
|
|
|
addGameLog(entry) {
|
|
this.gameLogSessionTable.push(entry);
|
|
this.updateSharedFeed(false);
|
|
if (entry.type === 'VideoPlay') {
|
|
// event time can be before last gameLog entry
|
|
this.updateSharedFeed(true);
|
|
}
|
|
if (
|
|
entry.type === 'LocationDestination' ||
|
|
entry.type === 'AvatarChange' ||
|
|
entry.type === 'ChatBoxMessage' ||
|
|
(entry.userId === API.currentUser.id &&
|
|
(entry.type === 'OnPlayerJoined' ||
|
|
entry.type === 'OnPlayerLeft'))
|
|
) {
|
|
return;
|
|
}
|
|
if (
|
|
this.gameLogTable.filter.length > 0 &&
|
|
!this.gameLogTable.filter.includes(entry.type)
|
|
) {
|
|
return;
|
|
}
|
|
if (!this.gameLogSearch(entry)) {
|
|
return;
|
|
}
|
|
this.gameLogTable.data.push(entry);
|
|
this.sweepGameLog();
|
|
this.notifyMenu('gameLog');
|
|
},
|
|
|
|
async addGamelogLocationToDatabase(input) {
|
|
var groupName = await this.getGroupName(input.location);
|
|
var entry = {
|
|
...input,
|
|
groupName
|
|
};
|
|
database.addGamelogLocationToDatabase(entry);
|
|
},
|
|
|
|
async addGameLogVideo(gameLog, location, userId) {
|
|
var videoUrl = gameLog.videoUrl;
|
|
var youtubeVideoId = '';
|
|
var videoId = '';
|
|
var videoName = '';
|
|
var videoLength = '';
|
|
var displayName = '';
|
|
var videoPos = 8; // video loading delay
|
|
if (typeof gameLog.displayName !== 'undefined') {
|
|
displayName = gameLog.displayName;
|
|
}
|
|
if (typeof gameLog.videoPos !== 'undefined') {
|
|
videoPos = gameLog.videoPos;
|
|
}
|
|
if (!this.isRpcWorld(location) || gameLog.videoId === 'YouTube') {
|
|
// skip PyPyDance and VRDancing videos
|
|
try {
|
|
var url = new URL(videoUrl);
|
|
if (
|
|
url.origin === 'https://t-ne.x0.to' ||
|
|
url.origin === 'https://nextnex.com' ||
|
|
url.origin === 'https://r.0cm.org'
|
|
) {
|
|
url = new URL(url.searchParams.get('url'));
|
|
}
|
|
if (videoUrl.startsWith('https://u2b.cx/')) {
|
|
url = new URL(videoUrl.substring(15));
|
|
}
|
|
var id1 = url.pathname;
|
|
var id2 = url.searchParams.get('v');
|
|
if (id1 && id1.length === 12) {
|
|
// https://youtu.be/
|
|
youtubeVideoId = id1.substring(1, 12);
|
|
}
|
|
if (id1 && id1.length === 19) {
|
|
// https://www.youtube.com/shorts/
|
|
youtubeVideoId = id1.substring(8, 19);
|
|
}
|
|
if (id2 && id2.length === 11) {
|
|
// https://www.youtube.com/watch?v=
|
|
// https://music.youtube.com/watch?v=
|
|
youtubeVideoId = id2;
|
|
}
|
|
if (this.youTubeApi && youtubeVideoId) {
|
|
var data =
|
|
await this.lookupYouTubeVideo(youtubeVideoId);
|
|
if (data || data.pageInfo.totalResults !== 0) {
|
|
videoId = 'YouTube';
|
|
videoName = data.items[0].snippet.title;
|
|
videoLength = this.convertYoutubeTime(
|
|
data.items[0].contentDetails.duration
|
|
);
|
|
}
|
|
}
|
|
} catch {
|
|
console.error(`Invalid URL: ${url}`);
|
|
}
|
|
var entry = {
|
|
created_at: gameLog.dt,
|
|
type: 'VideoPlay',
|
|
videoUrl,
|
|
videoId,
|
|
videoName,
|
|
videoLength,
|
|
location,
|
|
displayName,
|
|
userId,
|
|
videoPos
|
|
};
|
|
this.setNowPlaying(entry);
|
|
}
|
|
},
|
|
|
|
addGameLogPyPyDance(gameLog, location) {
|
|
var data =
|
|
/VideoPlay\(PyPyDance\) "(.+?)",([\d.]+),([\d.]+),"(.*)"/g.exec(
|
|
gameLog.data
|
|
);
|
|
if (!data) {
|
|
console.error('failed to parse', gameLog.data);
|
|
return;
|
|
}
|
|
var videoUrl = data[1];
|
|
var videoPos = Number(data[2]);
|
|
var videoLength = Number(data[3]);
|
|
var title = data[4];
|
|
var bracketArray = title.split('(');
|
|
var text1 = bracketArray.pop();
|
|
var displayName = text1.slice(0, -1);
|
|
var text2 = bracketArray.join('(');
|
|
if (text2 === 'Custom URL') {
|
|
var videoId = 'YouTube';
|
|
} else {
|
|
var videoId = text2.substr(0, text2.indexOf(':') - 1);
|
|
text2 = text2.substr(text2.indexOf(':') + 2);
|
|
}
|
|
var videoName = text2.slice(0, -1);
|
|
if (displayName === 'Random') {
|
|
displayName = '';
|
|
}
|
|
if (videoUrl === this.nowPlaying.url) {
|
|
var entry = {
|
|
created_at: gameLog.dt,
|
|
videoUrl,
|
|
videoLength,
|
|
videoPos
|
|
};
|
|
this.setNowPlaying(entry);
|
|
return;
|
|
}
|
|
var userId = '';
|
|
if (displayName) {
|
|
for (var ref of API.cachedUsers.values()) {
|
|
if (ref.displayName === displayName) {
|
|
userId = ref.id;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (videoId === 'YouTube') {
|
|
var entry = {
|
|
dt: gameLog.dt,
|
|
videoUrl,
|
|
displayName,
|
|
videoPos,
|
|
videoId
|
|
};
|
|
this.addGameLogVideo(entry, location, userId);
|
|
} else {
|
|
var entry = {
|
|
created_at: gameLog.dt,
|
|
type: 'VideoPlay',
|
|
videoUrl,
|
|
videoId,
|
|
videoName,
|
|
videoLength,
|
|
location,
|
|
displayName,
|
|
userId,
|
|
videoPos
|
|
};
|
|
this.setNowPlaying(entry);
|
|
}
|
|
},
|
|
|
|
addGameLogVRDancing(gameLog, location) {
|
|
var data =
|
|
/VideoPlay\(VRDancing\) "(.+?)",([\d.]+),([\d.]+),(-?[\d.]+),"(.+?)","(.+?)"/g.exec(
|
|
gameLog.data
|
|
);
|
|
if (!data) {
|
|
console.error('failed to parse', gameLog.data);
|
|
return;
|
|
}
|
|
var videoUrl = data[1];
|
|
var videoPos = Number(data[2]);
|
|
var videoLength = Number(data[3]);
|
|
var videoId = Number(data[4]);
|
|
var displayName = data[5];
|
|
var videoName = data[6];
|
|
if (videoId === -1) {
|
|
videoId = 'YouTube';
|
|
}
|
|
if (parseInt(videoPos, 10) === parseInt(videoLength, 10)) {
|
|
// ummm okay
|
|
videoPos = 0;
|
|
}
|
|
if (videoUrl === this.nowPlaying.url) {
|
|
var entry = {
|
|
created_at: gameLog.dt,
|
|
videoUrl,
|
|
videoLength,
|
|
videoPos
|
|
};
|
|
this.setNowPlaying(entry);
|
|
return;
|
|
}
|
|
var userId = '';
|
|
if (displayName) {
|
|
for (var ref of API.cachedUsers.values()) {
|
|
if (ref.displayName === displayName) {
|
|
userId = ref.id;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (videoId === 'YouTube') {
|
|
var entry = {
|
|
dt: gameLog.dt,
|
|
videoUrl,
|
|
displayName,
|
|
videoPos,
|
|
videoId
|
|
};
|
|
this.addGameLogVideo(entry, location, userId);
|
|
} else {
|
|
var entry = {
|
|
created_at: gameLog.dt,
|
|
type: 'VideoPlay',
|
|
videoUrl,
|
|
videoId,
|
|
videoName,
|
|
videoLength,
|
|
location,
|
|
displayName,
|
|
userId,
|
|
videoPos
|
|
};
|
|
this.setNowPlaying(entry);
|
|
}
|
|
},
|
|
|
|
addGameLogZuwaZuwaDance(gameLog, location) {
|
|
var data =
|
|
/VideoPlay\(ZuwaZuwaDance\) "(.+?)",([\d.]+),([\d.]+),(-?[\d.]+),"(.+?)","(.+?)"/g.exec(
|
|
gameLog.data
|
|
);
|
|
if (!data) {
|
|
console.error('failed to parse', gameLog.data);
|
|
return;
|
|
}
|
|
var videoUrl = data[1];
|
|
var videoPos = Number(data[2]);
|
|
var videoLength = Number(data[3]);
|
|
var videoId = Number(data[4]);
|
|
var displayName = data[5];
|
|
var videoName = data[6];
|
|
if (displayName === 'Random') {
|
|
displayName = '';
|
|
}
|
|
if (videoId === 9999) {
|
|
videoId = 'YouTube';
|
|
}
|
|
if (videoUrl === this.nowPlaying.url) {
|
|
var entry = {
|
|
created_at: gameLog.dt,
|
|
videoUrl,
|
|
videoLength,
|
|
videoPos
|
|
};
|
|
this.setNowPlaying(entry);
|
|
return;
|
|
}
|
|
var userId = '';
|
|
if (displayName) {
|
|
for (var ref of API.cachedUsers.values()) {
|
|
if (ref.displayName === displayName) {
|
|
userId = ref.id;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (videoId === 'YouTube') {
|
|
var entry = {
|
|
dt: gameLog.dt,
|
|
videoUrl,
|
|
displayName,
|
|
videoPos,
|
|
videoId
|
|
};
|
|
this.addGameLogVideo(entry, location, userId);
|
|
} else {
|
|
var entry = {
|
|
created_at: gameLog.dt,
|
|
type: 'VideoPlay',
|
|
videoUrl,
|
|
videoId,
|
|
videoName,
|
|
videoLength,
|
|
location,
|
|
displayName,
|
|
userId,
|
|
videoPos
|
|
};
|
|
this.setNowPlaying(entry);
|
|
}
|
|
},
|
|
|
|
addGameLogLSMedia(gameLog, location) {
|
|
// [VRCX] LSMedia 0,4268.981,Natsumi-sama,,
|
|
// [VRCX] LSMedia 0,6298.292,Natsumi-sama,The Outfit (2022), 1080p
|
|
var data = /LSMedia ([\d.]+),([\d.]+),(.+?),(.+?),(?=[^,]*$)/g.exec(
|
|
gameLog.data
|
|
);
|
|
if (!data) {
|
|
return;
|
|
}
|
|
var videoPos = Number(data[1]);
|
|
var videoLength = Number(data[2]);
|
|
var displayName = data[3];
|
|
var videoName = this.replaceBioSymbols(data[4]);
|
|
var videoUrl = videoName;
|
|
var videoId = 'LSMedia';
|
|
if (videoUrl === this.nowPlaying.url) {
|
|
var entry = {
|
|
created_at: gameLog.dt,
|
|
videoUrl,
|
|
videoLength,
|
|
videoPos
|
|
};
|
|
this.setNowPlaying(entry);
|
|
return;
|
|
}
|
|
var userId = '';
|
|
if (displayName) {
|
|
for (var ref of API.cachedUsers.values()) {
|
|
if (ref.displayName === displayName) {
|
|
userId = ref.id;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
var entry = {
|
|
created_at: gameLog.dt,
|
|
type: 'VideoPlay',
|
|
videoUrl,
|
|
videoId,
|
|
videoName,
|
|
videoLength,
|
|
location,
|
|
displayName,
|
|
userId,
|
|
videoPos
|
|
};
|
|
this.setNowPlaying(entry);
|
|
},
|
|
|
|
addGameLogMovieAndChill(gameLog, location) {
|
|
// [VRCX] Movie&Chill CurrentTime,Length,PlayerName,MovieName
|
|
var data = /Movie&Chill ([\d.]+),([\d.]+),(.+?),(.*)/g.exec(
|
|
gameLog.data
|
|
);
|
|
if (!data) {
|
|
return;
|
|
}
|
|
var videoPos = Number(data[1]);
|
|
var videoLength = Number(data[2]);
|
|
var displayName = data[3];
|
|
var videoName = data[4];
|
|
var videoUrl = videoName;
|
|
var videoId = 'Movie&Chill';
|
|
if (!videoName) {
|
|
return;
|
|
}
|
|
if (videoUrl === this.nowPlaying.url) {
|
|
var entry = {
|
|
created_at: gameLog.dt,
|
|
videoUrl,
|
|
videoLength,
|
|
videoPos
|
|
};
|
|
this.setNowPlaying(entry);
|
|
return;
|
|
}
|
|
var userId = '';
|
|
if (displayName) {
|
|
for (var ref of API.cachedUsers.values()) {
|
|
if (ref.displayName === displayName) {
|
|
userId = ref.id;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
var entry = {
|
|
created_at: gameLog.dt,
|
|
type: 'VideoPlay',
|
|
videoUrl,
|
|
videoId,
|
|
videoName,
|
|
videoLength,
|
|
location,
|
|
displayName,
|
|
userId,
|
|
videoPos
|
|
};
|
|
this.setNowPlaying(entry);
|
|
},
|
|
|
|
async gameLogTableLookup() {
|
|
await configRepository.setString(
|
|
'VRCX_gameLogTableFilters',
|
|
JSON.stringify(this.gameLogTable.filter)
|
|
);
|
|
this.gameLogTable.loading = true;
|
|
this.gameLogTable.data = await database.lookupGameLogDatabase(
|
|
this.gameLogTable.search,
|
|
this.gameLogTable.filter
|
|
);
|
|
this.gameLogTable.loading = false;
|
|
},
|
|
|
|
sweepGameLog() {
|
|
var { data } = this.gameLogTable;
|
|
var j = data.length;
|
|
if (j > this.maxTableSize) {
|
|
data.splice(0, j - this.maxTableSize);
|
|
}
|
|
|
|
var date = new Date();
|
|
date.setDate(date.getDate() - 1); // 24 hour limit
|
|
var limit = date.toJSON();
|
|
var i = 0;
|
|
var k = this.gameLogSessionTable.length;
|
|
while (i < k && this.gameLogSessionTable[i].created_at < limit) {
|
|
++i;
|
|
}
|
|
if (i === k) {
|
|
this.gameLogSessionTable = [];
|
|
} else if (i) {
|
|
this.gameLogSessionTable.splice(0, i);
|
|
}
|
|
},
|
|
|
|
// async resetGameLog() {
|
|
// await gameLogService.reset();
|
|
// this.gameLogTable.data = [];
|
|
// this.lastLocationReset();
|
|
// },
|
|
|
|
// async refreshEntireGameLog() {
|
|
// await gameLogService.setDateTill('1970-01-01');
|
|
// await database.initTables();
|
|
// await this.resetGameLog();
|
|
// var location = '';
|
|
// for (var gameLog of await gameLogService.getAll()) {
|
|
// if (gameLog.type === 'location') {
|
|
// location = gameLog.location;
|
|
// }
|
|
// this.addGameLogEntry(gameLog, location);
|
|
// }
|
|
// this.getGameLogTable();
|
|
// },
|
|
|
|
async getGameLogTable() {
|
|
await database.initTables();
|
|
this.gameLogSessionTable = await database.getGamelogDatabase();
|
|
var dateTill = await database.getLastDateGameLogDatabase();
|
|
this.updateGameLog(dateTill);
|
|
},
|
|
|
|
async updateGameLog(dateTill) {
|
|
await gameLogService.setDateTill(dateTill);
|
|
await gameLogService.reset();
|
|
await new Promise((resolve) => {
|
|
workerTimers.setTimeout(resolve, 10000);
|
|
});
|
|
var location = '';
|
|
for (var gameLog of await gameLogService.getAll()) {
|
|
if (gameLog.type === 'location') {
|
|
location = gameLog.location;
|
|
}
|
|
this.addGameLogEntry(gameLog, location);
|
|
}
|
|
},
|
|
|
|
addGameLogEvent(json) {
|
|
var rawLogs = JSON.parse(json);
|
|
var gameLog = gameLogService.parseRawGameLog(
|
|
rawLogs[1],
|
|
rawLogs[2],
|
|
rawLogs.slice(3)
|
|
);
|
|
if (
|
|
this.debugGameLog &&
|
|
gameLog.type !== 'photon-id' &&
|
|
gameLog.type !== 'api-request' &&
|
|
gameLog.type !== 'udon-exception'
|
|
) {
|
|
console.log('gameLog:', gameLog);
|
|
}
|
|
this.addGameLogEntry(gameLog, this.lastLocation.location);
|
|
},
|
|
|
|
deleteGameLogEntryPrompt(row) {
|
|
this.$confirm('Continue? Delete Log', 'Confirm', {
|
|
confirmButtonText: 'Confirm',
|
|
cancelButtonText: 'Cancel',
|
|
type: 'info',
|
|
callback: (action) => {
|
|
if (action === 'confirm') {
|
|
this.deleteGameLogEntry(row);
|
|
}
|
|
}
|
|
});
|
|
},
|
|
|
|
deleteGameLogEntry(row) {
|
|
$app.removeFromArray(this.gameLogTable.data, row);
|
|
database.deleteGameLogEntry(row);
|
|
console.log(row);
|
|
database.getGamelogDatabase().then((data) => {
|
|
this.gameLogSessionTable = data;
|
|
this.updateSharedFeed(true);
|
|
});
|
|
},
|
|
|
|
gameLogSearch(row) {
|
|
var value = this.gameLogTable.search.toUpperCase();
|
|
if (!value) {
|
|
return true;
|
|
}
|
|
if (
|
|
value.startsWith('wrld_') &&
|
|
String(row.location).toUpperCase().includes(value)
|
|
) {
|
|
return true;
|
|
}
|
|
switch (row.type) {
|
|
case 'Location':
|
|
if (String(row.worldName).toUpperCase().includes(value)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
case 'OnPlayerJoined':
|
|
if (String(row.displayName).toUpperCase().includes(value)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
case 'OnPlayerLeft':
|
|
if (String(row.displayName).toUpperCase().includes(value)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
case 'PortalSpawn':
|
|
if (String(row.displayName).toUpperCase().includes(value)) {
|
|
return true;
|
|
}
|
|
if (String(row.worldName).toUpperCase().includes(value)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
case 'Event':
|
|
if (String(row.data).toUpperCase().includes(value)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
case 'External':
|
|
if (String(row.message).toUpperCase().includes(value)) {
|
|
return true;
|
|
}
|
|
if (String(row.displayName).toUpperCase().includes(value)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
case 'VideoPlay':
|
|
if (String(row.displayName).toUpperCase().includes(value)) {
|
|
return true;
|
|
}
|
|
if (String(row.videoName).toUpperCase().includes(value)) {
|
|
return true;
|
|
}
|
|
if (String(row.videoUrl).toUpperCase().includes(value)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
case 'StringLoad':
|
|
case 'ImageLoad':
|
|
if (String(row.resourceUrl).toUpperCase().includes(value)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
},
|
|
|
|
gameLogIsFriend(row) {
|
|
if (typeof row.isFriend !== 'undefined') {
|
|
return row.isFriend;
|
|
}
|
|
if (!row.userId) {
|
|
return false;
|
|
}
|
|
row.isFriend = this.friends.has(row.userId);
|
|
return row.isFriend;
|
|
},
|
|
|
|
gameLogIsFavorite(row) {
|
|
if (typeof row.isFavorite !== 'undefined') {
|
|
return row.isFavorite;
|
|
}
|
|
if (!row.userId) {
|
|
return false;
|
|
}
|
|
row.isFavorite = this.localFavoriteFriends.has(row.userId);
|
|
return row.isFavorite;
|
|
},
|
|
|
|
async disableGameLogDialog() {
|
|
if (this.isGameRunning) {
|
|
this.$message({
|
|
message:
|
|
'VRChat needs to be closed before this option can be changed',
|
|
type: 'error'
|
|
});
|
|
this.gameLogDisabled = !this.gameLogDisabled;
|
|
return;
|
|
}
|
|
if (this.gameLogDisabled) {
|
|
this.$confirm('Continue? Disable GameLog', 'Confirm', {
|
|
confirmButtonText: 'Confirm',
|
|
cancelButtonText: 'Cancel',
|
|
type: 'info',
|
|
callback: async (action) => {
|
|
if (action !== 'confirm') {
|
|
this.gameLogDisabled = !this.gameLogDisabled;
|
|
await configRepository.setBool(
|
|
'VRCX_gameLogDisabled',
|
|
this.gameLogDisabled
|
|
);
|
|
}
|
|
}
|
|
});
|
|
} else {
|
|
await configRepository.setBool(
|
|
'VRCX_gameLogDisabled',
|
|
this.gameLogDisabled
|
|
);
|
|
}
|
|
}
|
|
};
|
|
}
|