diff --git a/html/src/app.js b/html/src/app.js index 2dff62ed..a10c695f 100644 --- a/html/src/app.js +++ b/html/src/app.js @@ -52,6 +52,7 @@ import _memos from './classes/memos.js'; import _languages from './classes/languages.js'; import _groups from './classes/groups.js'; import _vrcRegistry from './classes/vrcRegistry.js'; +import _restoreFriendOrder from './classes/restoreFriendOrder.js'; // API classes import _config from './classes/API/config.js'; @@ -116,7 +117,8 @@ speechSynthesis.getVoices(); config: new _config($app, API, $t), languages: new _languages($app, API, $t), groups: new _groups($app, API, $t), - vrcRegistry: new _vrcRegistry($app, API, $t) + vrcRegistry: new _vrcRegistry($app, API, $t), + restoreFriendOrder: new _restoreFriendOrder($app, API, $t) }; await configRepository.init(); @@ -570,6 +572,7 @@ speechSynthesis.getVoices(); $previousLocation: '', $customTag: '', $customTagColour: '', + $friendNumber: 0, // ...json }; @@ -4144,7 +4147,7 @@ speechSynthesis.getVoices(); $app.data.friends = new Map(); $app.data.pendingActiveFriends = new Set(); - $app.data.friendsNo = 0; + $app.data.friendNumber = 0; $app.data.isFriendsGroupMe = true; $app.data.isVIPFriends = true; $app.data.isOnlineFriends = true; @@ -4251,7 +4254,7 @@ speechSynthesis.getVoices(); API.$on('LOGIN', function () { $app.friends.clear(); $app.pendingActiveFriends.clear(); - $app.friendsNo = 0; + $app.friendNumber = 0; $app.isVIPFriends = true; $app.isOnlineFriends = true; $app.isActiveFriends = true; @@ -4342,40 +4345,6 @@ speechSynthesis.getVoices(); this.deleteFriend(id); } } - - this.saveFriendOrder(); - }; - - $app.methods.saveFriendOrder = async function () { - var currentTime = Date.now(); - var lastStoreTime = await configRepository.getString( - `VRCX_lastStoreTime_${API.currentUser.id}`, - '' - ); - // store once every week - if (lastStoreTime && currentTime - lastStoreTime < 604800000) { - return; - } - var storedData = {}; - try { - var data = await configRepository.getString( - `VRCX_friendOrder_${API.currentUser.id}` - ); - if (data) { - var storedData = JSON.parse(data); - } - } catch (err) { - console.error(err); - } - storedData[currentTime] = Array.from(this.friends.keys()); - await configRepository.setString( - `VRCX_friendOrder_${API.currentUser.id}`, - JSON.stringify(storedData) - ); - await configRepository.setString( - `VRCX_lastStoreTime_${API.currentUser.id}`, - currentTime - ); }; $app.methods.addFriend = function (id, state) { @@ -4395,7 +4364,6 @@ speechSynthesis.getVoices(); isVIP, ref, name, - no: ++this.friendsNo, memo: '', pendingOffline: false, pendingOfflineTime: '', @@ -7088,7 +7056,8 @@ speechSynthesis.getVoices(); var row = { userId: ref.id, displayName: ref.displayName, - trustLevel: ref.$trustLevel + trustLevel: ref.$trustLevel, + friendNumber: 0 }; this.friendLog.set(friend.id, row); sqlValues.unshift(row); @@ -7110,6 +7079,11 @@ speechSynthesis.getVoices(); }; $app.methods.getFriendLog = async function (currentUser) { + this.friendNumber = await configRepository.getInt( + `VRCX_friendNumber_${currentUser.id}`, + 0 + ); + var friendLogCurrentArray = await database.getFriendLogCurrent(); for (var friend of friendLogCurrentArray) { this.friendLog.set(friend.userId, friend); @@ -7118,7 +7092,9 @@ speechSynthesis.getVoices(); this.friendLogTable.data = await database.getFriendLogHistory(); this.refreshFriends(currentUser, true); await API.refreshFriends(); + await this.tryRestoreFriendNumber(); this.friendLogInitStatus = true; + // check for friend/name/rank change AFTER friendLogInitStatus is set for (var friend of friendLogCurrentArray) { var ref = API.cachedUsers.get(friend.userId); @@ -7154,12 +7130,21 @@ speechSynthesis.getVoices(); userId: id }).then((args) => { if (args.json.isFriend && !this.friendLog.has(id)) { + if (this.friendNumber === 0) { + this.friendNumber = this.friends.size; + } + ref.$friendNumber = ++this.friendNumber; + configRepository.setInt( + `VRCX_friendNumber_${API.currentUser.id}`, + this.friendNumber + ); this.addFriend(id, ref.state); var friendLogHistory = { created_at: new Date().toJSON(), type: 'Friend', userId: id, - displayName: ref.displayName + displayName: ref.displayName, + friendNumber: ref.$friendNumber }; this.friendLogTable.data.push(friendLogHistory); database.addFriendLogHistory(friendLogHistory); @@ -7167,7 +7152,8 @@ speechSynthesis.getVoices(); var friendLogCurrent = { userId: id, displayName: ref.displayName, - trustLevel: ref.$trustLevel + trustLevel: ref.$trustLevel, + friendNumber: ref.$friendNumber }; this.friendLog.set(id, friendLogCurrent); database.setFriendLogCurrent(friendLogCurrent); @@ -7255,7 +7241,8 @@ speechSynthesis.getVoices(); type: 'DisplayName', userId: ref.id, displayName: ref.displayName, - previousDisplayName: ctx.displayName + previousDisplayName: ctx.displayName, + friendNumber: ref.$friendNumber }; this.friendLogTable.data.push(friendLogHistoryDisplayName); database.addFriendLogHistory(friendLogHistoryDisplayName); @@ -7263,7 +7250,8 @@ speechSynthesis.getVoices(); var friendLogCurrent = { userId: ref.id, displayName: ref.displayName, - trustLevel: ref.$trustLevel + trustLevel: ref.$trustLevel, + friendNumber: ref.$friendNumber }; this.friendLog.set(ref.id, friendLogCurrent); database.setFriendLogCurrent(friendLogCurrent); @@ -7286,7 +7274,8 @@ speechSynthesis.getVoices(); var friendLogCurrent3 = { userId: ref.id, displayName: ref.displayName, - trustLevel: ref.$trustLevel + trustLevel: ref.$trustLevel, + friendNumber: ref.$friendNumber }; this.friendLog.set(ref.id, friendLogCurrent3); database.setFriendLogCurrent(friendLogCurrent3); @@ -7298,7 +7287,8 @@ speechSynthesis.getVoices(); userId: ref.id, displayName: ref.displayName, trustLevel: ref.$trustLevel, - previousTrustLevel: ctx.trustLevel + previousTrustLevel: ctx.trustLevel, + friendNumber: ref.$friendNumber }; this.friendLogTable.data.push(friendLogHistoryTrustLevel); database.addFriendLogHistory(friendLogHistoryTrustLevel); @@ -7306,7 +7296,8 @@ speechSynthesis.getVoices(); var friendLogCurrent2 = { userId: ref.id, displayName: ref.displayName, - trustLevel: ref.$trustLevel + trustLevel: ref.$trustLevel, + friendNumber: ref.$friendNumber }; this.friendLog.set(ref.id, friendLogCurrent2); database.setFriendLogCurrent(friendLogCurrent2); @@ -7314,6 +7305,9 @@ speechSynthesis.getVoices(); this.updateSharedFeed(true); } ctx.trustLevel = ref.$trustLevel; + if (ctx.friendNumber) { + ref.$friendNumber = ctx.friendNumber; + } }; $app.methods.deleteFriendLog = function (row) { @@ -7787,7 +7781,7 @@ speechSynthesis.getVoices(); stripe: true, size: 'mini', defaultSort: { - prop: '$friendNum', + prop: '$friendNumber', order: 'descending' } }, @@ -14828,7 +14822,7 @@ speechSynthesis.getVoices(); this.stringComparer ); } - if (!match && filters.includes('Rank') && ctx.ref.$friendNum) { + if (!match && filters.includes('Rank')) { match = String(ctx.ref.$trustLevel) .toUpperCase() .includes(query.toUpperCase()); @@ -14837,7 +14831,6 @@ speechSynthesis.getVoices(); continue; } } - ctx.ref.$friendNum = ctx.no; results.push(ctx.ref); } this.getAllUserStats(); @@ -19429,7 +19422,7 @@ speechSynthesis.getVoices(); ); $app.methods.updateDatabaseVersion = async function () { - var databaseVersion = 10; + var databaseVersion = 11; if (this.databaseVersion < databaseVersion) { if (this.databaseVersion) { var msgBox = this.$message({ @@ -19448,11 +19441,11 @@ speechSynthesis.getVoices(); await database.fixNegativeGPS(); // fix GPS being a negative value due to VRCX bug with traveling await database.fixBrokenLeaveEntries(); // fix user instance timer being higher than current user location timer await database.fixBrokenGroupInvites(); // fix notification v2 in wrong table - await database.updateTableForGroupNames(); // alter tables to include group name await database.fixBrokenNotifications(); // fix notifications being null await database.fixBrokenGroupChange(); // fix spam group left & name change await database.fixCancelFriendRequestTypo(); // fix CancelFriendRequst typo await database.fixBrokenGameLogDisplayNames(); // fix gameLog display names "DisplayName (userId)" + await database.upgradeDatabaseVersion(); // update database version await database.vacuum(); // succ await configRepository.setInt( 'VRCX_databaseVersion', diff --git a/html/src/classes/restoreFriendOrder.js b/html/src/classes/restoreFriendOrder.js new file mode 100644 index 00000000..75989e1a --- /dev/null +++ b/html/src/classes/restoreFriendOrder.js @@ -0,0 +1,280 @@ +import * as workerTimers from 'worker-timers'; +import configRepository from '../repository/config.js'; +import database from '../repository/database.js'; +import { baseClass, $app, API, $t, $utils } from './baseClass.js'; + +export default class extends baseClass { + constructor(_app, _API, _t) { + super(_app, _API, _t); + } + + init() {} + + _data = {}; + + _methods = { + async tryRestoreFriendNumber() { + var lastUpdate = await configRepository.getString( + `VRCX_lastStoreTime_${API.currentUser.id}` + ); + if (lastUpdate == -1) { + // this means the backup was already applied + return; + } + var status = false; + this.friendNumber = 0; + try { + if (lastUpdate) { + // backup ready to try apply + status = await this.restoreFriendNumber(); + } + // needs to be in reverse because we don't know the starting number + this.applyFriendLogFriendOrderInReverse(); + } catch (err) { + console.error(err); + } + if (status) { + this.$message({ + message: 'Friend order restored from backup', + type: 'success', + duration: 0, + showClose: true + }); + } else if (this.friendLogTable.data.length > 0) { + this.$message({ + message: + 'No backup found, friend order partially restored from friendLog', + type: 'success', + duration: 0, + showClose: true + }); + } + await configRepository.setString( + `VRCX_lastStoreTime_${API.currentUser.id}`, + -1 + ); + }, + + async restoreFriendNumber() { + var storedData = null; + try { + var data = await configRepository.getString( + `VRCX_friendOrder_${API.currentUser.id}` + ); + if (data) { + var storedData = JSON.parse(data); + } + } catch (err) { + console.error(err); + } + if (!storedData || storedData.length === 0) { + var message = 'whomp whomp, no friend order backup found'; + console.error(message); + return false; + } + + var friendLogTable = this.getFriendLogFriendOrder(); + + // for storedData + var machList = []; + for (var i = 0; i < Object.keys(storedData).length; i++) { + var key = Object.keys(storedData)[i]; + var value = storedData[key]; + var item = this.parseFriendOrderBackup( + friendLogTable, + key, + value + ); + machList.push(item); + } + machList.sort((a, b) => b.matches - a.matches); + console.log( + `friendLog: ${friendLogTable.length} friendOrderBackups:`, + machList + ); + + var bestBackup = machList[0]; + if (!bestBackup?.isValid) { + var message = 'whomp whomp, no valid backup found'; + console.error(message); + return false; + } + + this.applyFriendOrderBackup(bestBackup.table); + this.applyFriendLogFriendOrder(); + await configRepository.setInt( + `VRCX_friendNumber_${API.currentUser.id}`, + this.friendNumber + ); + return true; + }, + + getFriendLogFriendOrder() { + var friendLogTable = []; + for (var i = 0; i < this.friendLogTable.data.length; i++) { + var ref = this.friendLogTable.data[i]; + if (ref.type !== 'Friend') { + continue; + } + if ( + friendLogTable.findIndex((x) => x.id === ref.userId) !== -1 + ) { + // console.log( + // 'ignoring duplicate friend', + // ref.displayName, + // ref.created_at + // ); + continue; + } + friendLogTable.push({ + id: ref.userId, + displayName: ref.displayName, + created_at: ref.created_at + }); + } + var compareByCreatedAt = function (a, b) { + var A = a.created_at; + var B = b.created_at; + if (A < B) { + return -1; + } + if (A > B) { + return 1; + } + return 0; + }; + friendLogTable.sort(compareByCreatedAt); + return friendLogTable; + }, + + applyFriendLogFriendOrder() { + var friendLogTable = this.getFriendLogFriendOrder(); + if (this.friendNumber === 0) { + console.log( + 'No backup applied, applying friend log in reverse' + ); + // this means no FriendOrderBackup was applied + // will need to apply in reverse order instead + return; + } + for (var friendLog of friendLogTable) { + var ref = this.friendLog.get(friendLog.id); + if (!ref || ref.friendNumber) { + continue; + } + ref.friendNumber = ++this.friendNumber; + this.friendLog.set(ref.userId, ref); + database.setFriendLogCurrent(ref); + var friendRef = this.friends.get(friendLog.id); + if (friendRef?.ref) { + friendRef.ref.$friendNumber = ref.friendNumber; + } + } + }, + + applyFriendLogFriendOrderInReverse() { + this.friendNumber = this.friends.size + 1; + var friendLogTable = this.getFriendLogFriendOrder(); + for (var i = friendLogTable.length - 1; i > -1; i--) { + var friendLog = friendLogTable[i]; + var ref = this.friendLog.get(friendLog.id); + if (!ref) { + continue; + } + if (ref.friendNumber) { + break; + } + ref.friendNumber = --this.friendNumber; + this.friendLog.set(ref.userId, ref); + database.setFriendLogCurrent(ref); + var friendRef = this.friends.get(friendLog.id); + if (friendRef?.ref) { + friendRef.ref.$friendNumber = ref.friendNumber; + } + } + console.log('Applied friend order from friendLog'); + }, + + parseFriendOrderBackup(friendLogTable, created_at, backupUserIds) { + var backupTable = []; + for (var i = 0; i < backupUserIds.length; i++) { + var userId = backupUserIds[i]; + var ctx = this.friends.get(userId); + if (ctx) { + backupTable.push({ + id: ctx.id, + displayName: ctx.name + }); + } + } + + // var compareTable = []; + // compare 2 tables, find max amount of id's in same order + var maxMatches = 0; + var currentMatches = 0; + var backupIndex = 0; + for (var i = 0; i < friendLogTable.length; i++) { + var isMatch = false; + var ref = friendLogTable[i]; + if (backupIndex <= 0) { + backupIndex = backupTable.findIndex((x) => x.id === ref.id); + if (backupIndex !== -1) { + currentMatches = 1; + } + } else if (backupTable[backupIndex].id === ref.id) { + currentMatches++; + isMatch = true; + } else { + var backupIndex = backupTable.findIndex( + (x) => x.id === ref.id + ); + if (backupIndex !== -1) { + currentMatches = 1; + } + } + if (backupIndex === backupTable.length - 1) { + backupIndex = 0; + } else { + backupIndex++; + } + if (currentMatches > maxMatches) { + maxMatches = currentMatches; + } + // compareTable.push({ + // id: ref.id, + // displayName: ref.displayName, + // match: isMatch + // }); + } + + var lerp = (a, b, alpha) => { + return a + alpha * (b - a); + }; + return { + matches: parseFloat(`${maxMatches}.${created_at}`), + table: backupUserIds, + isValid: maxMatches > lerp(4, 10, backupTable.length / 1000) // pls no collisions + }; + }, + + applyFriendOrderBackup(userIdOrder) { + for (var i = 0; i < userIdOrder.length; i++) { + var userId = userIdOrder[i]; + var ctx = this.friends.get(userId); + var ref = ctx?.ref; + if (!ref || ref.$friendNumber) { + continue; + } + var friendLogCurrent = { + userId, + displayName: ref.displayName, + trustLevel: ref.$trustLevel, + friendNumber: i + 1 + }; + this.friendLog.set(userId, friendLogCurrent); + database.setFriendLogCurrent(friendLogCurrent); + this.friendNumber = i + 1; + } + } + }; +} diff --git a/html/src/mixins/dialogs/userDialog.pug b/html/src/mixins/dialogs/userDialog.pug index 94e8ea32..a4826936 100644 --- a/html/src/mixins/dialogs/userDialog.pug +++ b/html/src/mixins/dialogs/userDialog.pug @@ -46,7 +46,7 @@ mixin userDialog() span(style="display:block;text-align:center;font-family:monospace") {{ API.currentUser.username | textToHex }} div(style="margin-top:5px") el-tag.name(type="info" effect="plain" size="mini" :class="userDialog.ref.$trustClass" v-text="userDialog.ref.$trustLevel" style="margin-right:5px;margin-top:5px") - el-tag.x-tag-friend(v-if="userDialog.isFriend && userDialog.friend" type="info" effect="plain" size="mini" style="margin-right:5px;margin-top:5px") {{ $t('dialog.user.tags.friend_no', { number: userDialog.friend.no }) }} + el-tag.x-tag-friend(v-if="userDialog.isFriend && userDialog.friend" type="info" effect="plain" size="mini" style="margin-right:5px;margin-top:5px") {{ $t('dialog.user.tags.friend_no', { number: userDialog.ref.$friendNumber ? userDialog.ref.$friendNumber : "?" }) }} el-tag.x-tag-troll(v-if="userDialog.ref.$isTroll" type="info" effect="plain" size="mini" style="margin-right:5px;margin-top:5px") Nuisance el-tag.x-tag-troll(v-if="userDialog.ref.$isProbableTroll" type="info" effect="plain" size="mini" style="margin-right:5px;margin-top:5px") Almost Nuisance el-tag.x-tag-vip(v-if="userDialog.ref.$isModerator" type="info" effect="plain" size="mini" style="margin-right:5px;margin-top:5px") {{ $t('dialog.user.tags.vrchat_team') }} diff --git a/html/src/mixins/tabs/friendsList.pug b/html/src/mixins/tabs/friendsList.pug index d06989db..22e46b34 100644 --- a/html/src/mixins/tabs/friendsList.pug +++ b/html/src/mixins/tabs/friendsList.pug @@ -33,7 +33,7 @@ mixin friendsListTab() template(v-once #default="scope") el-button(type="text" size="mini" @click.stop) el-checkbox(v-model="scope.row.$selected" @change="friendsListBulkUnfriendForceUpdate++") - el-table-column(:label="$t('table.friendList.no')" width="70" prop="$friendNum" sortable="custom") + el-table-column(:label="$t('table.friendList.no')" width="70" prop="$friendNumber" sortable="custom") el-table-column(:label="$t('table.friendList.avatar')" width="70" prop="photo") template(v-once #default="scope") el-popover(placement="right" height="500px" trigger="hover") diff --git a/html/src/repository/database.js b/html/src/repository/database.js index 1891d46d..1205c2aa 100644 --- a/html/src/repository/database.js +++ b/html/src/repository/database.js @@ -28,10 +28,10 @@ class Database { `CREATE TABLE IF NOT EXISTS ${Database.userPrefix}_feed_online_offline (id INTEGER PRIMARY KEY, created_at TEXT, user_id TEXT, display_name TEXT, type TEXT, location TEXT, world_name TEXT, time INTEGER, group_name TEXT)` ); await sqliteService.executeNonQuery( - `CREATE TABLE IF NOT EXISTS ${Database.userPrefix}_friend_log_current (user_id TEXT PRIMARY KEY, display_name TEXT, trust_level TEXT)` + `CREATE TABLE IF NOT EXISTS ${Database.userPrefix}_friend_log_current (user_id TEXT PRIMARY KEY, display_name TEXT, trust_level TEXT, friend_number INTEGER)` ); await sqliteService.executeNonQuery( - `CREATE TABLE IF NOT EXISTS ${Database.userPrefix}_friend_log_history (id INTEGER PRIMARY KEY, created_at TEXT, type TEXT, user_id TEXT, display_name TEXT, previous_display_name TEXT, trust_level TEXT, previous_trust_level TEXT)` + `CREATE TABLE IF NOT EXISTS ${Database.userPrefix}_friend_log_history (id INTEGER PRIMARY KEY, created_at TEXT, type TEXT, user_id TEXT, display_name TEXT, previous_display_name TEXT, trust_level TEXT, previous_trust_level TEXT, friend_number INTEGER)` ); await sqliteService.executeNonQuery( `CREATE TABLE IF NOT EXISTS ${Database.userPrefix}_notifications (id TEXT PRIMARY KEY, created_at TEXT, type TEXT, sender_user_id TEXT, sender_username TEXT, receiver_user_id TEXT, message TEXT, world_id TEXT, world_name TEXT, image_url TEXT, invite_message TEXT, request_message TEXT, response_message TEXT, expired INTEGER)` @@ -326,7 +326,8 @@ class Database { var row = { userId: dbRow[0], displayName: dbRow[1], - trustLevel: dbRow[2] + trustLevel: dbRow[2], + friendNumber: dbRow[3] }; friendLogCurrent.unshift(row); }, `SELECT * FROM ${Database.userPrefix}_friend_log_current`); @@ -335,11 +336,12 @@ class Database { setFriendLogCurrent(entry) { sqliteService.executeNonQuery( - `INSERT OR REPLACE INTO ${Database.userPrefix}_friend_log_current (user_id, display_name, trust_level) VALUES (@user_id, @display_name, @trust_level)`, + `INSERT OR REPLACE INTO ${Database.userPrefix}_friend_log_current (user_id, display_name, trust_level, friend_number) VALUES (@user_id, @display_name, @trust_level, @friend_number)`, { '@user_id': entry.userId, '@display_name': entry.displayName, - '@trust_level': entry.trustLevel + '@trust_level': entry.trustLevel, + '@friend_number': entry.friendNumber } ); } @@ -359,11 +361,11 @@ class Database { field[item] = ''; } } - sqlValues += `('${field.userId}', '${field.displayName}', '${field.trustLevel}'), `; + sqlValues += `('${field.userId}', '${field.displayName}', '${field.trustLevel}', ${line.friendNumber}), `; } sqlValues = sqlValues.slice(0, -2); sqliteService.executeNonQuery( - `INSERT OR REPLACE INTO ${Database.userPrefix}_friend_log_current (user_id, display_name, trust_level) VALUES ${sqlValues}` + `INSERT OR REPLACE INTO ${Database.userPrefix}_friend_log_current (user_id, display_name, trust_level, friend_number) VALUES ${sqlValues}` ); } @@ -384,7 +386,8 @@ class Database { created_at: dbRow[1], type: dbRow[2], userId: dbRow[3], - displayName: dbRow[4] + displayName: dbRow[4], + friendNumber: dbRow[8] }; if (row.type === 'DisplayName') { row.previousDisplayName = dbRow[5]; @@ -399,7 +402,7 @@ class Database { addFriendLogHistory(entry) { sqliteService.executeNonQuery( - `INSERT OR IGNORE INTO ${Database.userPrefix}_friend_log_history (created_at, type, user_id, display_name, previous_display_name, trust_level, previous_trust_level) VALUES (@created_at, @type, @user_id, @display_name, @previous_display_name, @trust_level, @previous_trust_level)`, + `INSERT OR IGNORE INTO ${Database.userPrefix}_friend_log_history (created_at, type, user_id, display_name, previous_display_name, trust_level, previous_trust_level, friend_number) VALUES (@created_at, @type, @user_id, @display_name, @previous_display_name, @trust_level, @previous_trust_level, @friend_number)`, { '@created_at': entry.created_at, '@type': entry.type, @@ -407,7 +410,8 @@ class Database { '@display_name': entry.displayName, '@previous_display_name': entry.previousDisplayName, '@trust_level': entry.trustLevel, - '@previous_trust_level': entry.previousTrustLevel + '@previous_trust_level': entry.previousTrustLevel, + '@friend_number': entry.friendNumber } ); } @@ -424,7 +428,8 @@ class Database { 'displayName', 'previousDisplayName', 'trustLevel', - 'previousTrustLevel' + 'previousTrustLevel', + 'friendNumber' ]; for (var i = 0; i < inputData.length; ++i) { var line = inputData[i]; @@ -449,7 +454,7 @@ class Database { // sqlValues `('${line.created_at}', '${line.type}', '${line.userId}', '${line.displayName}', '${line.previousDisplayName}', '${line.trustLevel}', '${line.previousTrustLevel}'), ` } sqliteService.executeNonQuery( - `INSERT OR IGNORE INTO ${Database.userPrefix}_friend_log_history (created_at, type, user_id, display_name, previous_display_name, trust_level, previous_trust_level) VALUES ${sqlValues}` + `INSERT OR IGNORE INTO ${Database.userPrefix}_friend_log_history (created_at, type, user_id, display_name, previous_display_name, trust_level, previous_trust_level, friend_number) VALUES ${sqlValues}` ); } @@ -2596,6 +2601,36 @@ class Database { ); } + async upgradeDatabaseVersion() { + // var version = 0; + // await sqliteService.execute((dbRow) => { + // version = dbRow[0]; + // }, 'PRAGMA user_version'); + // if (version === 0) { + await this.updateTableForGroupNames(); + await this.addFriendLogFriendNumber(); + // } + // await sqliteService.executeNonQuery('PRAGMA user_version = 1'); + } + + async addFriendLogFriendNumber() { + var tables = []; + await sqliteService.execute((dbRow) => { + tables.push(dbRow[0]); + }, `SELECT name FROM sqlite_schema WHERE type='table' AND name LIKE '%_friend_log_current' OR name LIKE '%_friend_log_history'`); + for (var tableName of tables) { + try { + await sqliteService.executeNonQuery( + `ALTER TABLE ${tableName} ADD friend_number INTEGER DEFAULT 0` + ); + } catch (e) { + if (e.indexOf('duplicate column name') === -1) { + console.error(e); + } + } + } + } + async updateTableForGroupNames() { var tables = []; await sqliteService.execute((dbRow) => { @@ -2604,28 +2639,22 @@ class Database { for (var tableName of tables) { try { await sqliteService.executeNonQuery( - `SELECT group_name FROM ${tableName} LIMIT 1` - ); - } catch (e) { - if (e.indexOf('no such column') === -1) { - throw e; - } - sqliteService.executeNonQuery( `ALTER TABLE ${tableName} ADD group_name TEXT DEFAULT ''` ); + } catch (e) { + if (e.indexOf('duplicate column name') === -1) { + console.error(e); + } } } // Fix gamelog_location column typo try { - await sqliteService.executeNonQuery( - `SELECT groupName FROM gamelog_location LIMIT 1` - ); await sqliteService.executeNonQuery( `ALTER TABLE gamelog_location DROP COLUMN groupName` ); } catch (e) { if (e.indexOf('no such column') === -1) { - throw e; + console.error(e); } } }