Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug fix: 修正会错误地合并他人的游戏记录的问题 #121

Merged
merged 14 commits into from
Jul 30, 2024
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "psnine-enhanced-version",
"version": "1.0.26",
"version": "1.0.27",
"description": "数折价格走势图,显示人民币价格,奖杯统计和筛选,发帖字数统计和即时预览,楼主高亮,自动翻页,屏蔽黑名单用户发言,被@用户的发言内容显示等多项功能优化P9体验",
"main": "night-mode-css.js",
"scripts": {
Expand All @@ -22,4 +22,4 @@
"eslint-config-airbnb-base": "^14.2.1",
"eslint-plugin-import": "^2.22.1"
}
}
}
193 changes: 146 additions & 47 deletions psnineplus.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// ==UserScript==
// @name PSN中文网功能增强
// @namespace https://swsoyee.github.io
// @version 1.0.26
// @version 1.0.27
// @description 数折价格走势图,显示人民币价格,奖杯统计和筛选,发帖字数统计和即时预览,楼主高亮,自动翻页,屏蔽黑名单用户发言,被@用户的发言内容显示等多项功能优化P9体验
// eslint-disable-next-line max-len
// @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAMAAAAp4XiDAAAAMFBMVEVHcEw0mNs0mNs0mNs0mNs0mNs0mNs0mNs0mNs0mNs0mNs0mNs0mNs0mNs0mNs0mNuEOyNSAAAAD3RSTlMAQMAQ4PCApCBQcDBg0JD74B98AAABN0lEQVRIx+2WQRaDIAxECSACWLn/bdsCIkNQ2XXT2bTyHEx+glGIv4STU3KNRccp6dNh4qTM4VDLrGVRxbLGaa3ZQSVQulVJl5JFlh3cLdNyk/xe2IXz4DqYLhZ4mWtHd4/SLY/QQwKmWmGcmUfHb4O1mu8BIPGw4Hg1TEvySQGWoBcItgxndmsbhtJd6baukIKnt525W4anygNECVc1UD8uVbRNbumZNl6UmkagHeRJfX0BdM5NXgA+ZKESpiJ9tRFftZEvue2cS6cKOrGk/IOLTLUcaXuZHrZDq3FB2IonOBCHIy8Bs1Zzo1MxVH+m8fQ+nFeCQM3MWwEsWsy8e8Di7meA5Bb5MDYCt4SnUbP3lv1xOuWuOi3j5kJ5tPiZKahbi54anNRaaG7YElFKQBHR/9PjN3oD6fkt9WKF9rgAAAAASUVORK5CYII=
Expand Down Expand Up @@ -402,7 +402,7 @@
$('body,html').animate({
scrollTop: document.body.clientHeight,
},
500);
500);

Check failure on line 405 in psnineplus.js

View workflow job for this annotation

GitHub Actions / eslint

Expected indentation of 8 spaces but found 10
}).css({
cursor: 'pointer',
});
Expand Down Expand Up @@ -443,7 +443,7 @@
const tdElements = document.querySelectorAll('table.list > tbody > tr');

// 获取已保存的完成度
const personalGameCompletions = GM_getValue('personalGameCompletions', []);

Check failure on line 446 in psnineplus.js

View workflow job for this annotation

GitHub Actions / eslint

'GM_getValue' is not defined

// 根据已保存的完成度添加染色
tdElements.forEach((tr) => {
Expand Down Expand Up @@ -522,7 +522,7 @@
const progressPlatinumBG = (p) => `background-image: linear-gradient(90deg, rgba(200,240,255,0.6) ${p}%, rgba(200,255,250,0.15) ${p}%)`;
const progressPlatinumBGNight = (p) => `background-image: linear-gradient(90deg, rgba(200,240,255,0.15) ${p}%, rgba(200,255,250,0.05) ${p}%)`;

const personalGameCompletions = GM_getValue('personalGameCompletions', []);

Check failure on line 525 in psnineplus.js

View workflow job for this annotation

GitHub Actions / eslint

'GM_getValue' is not defined
const tdElements = document.querySelectorAll('table.list > tbody > tr');

tdElements.forEach((tr) => {
Expand Down Expand Up @@ -562,8 +562,8 @@
}`);

// 定义两个变量,用户设置的游戏约战监控列表,和当前存在的约战列表(缓存)
let userBattleMonitors = GM_getValue('userBattleMonitors', []);

Check failure on line 565 in psnineplus.js

View workflow job for this annotation

GitHub Actions / eslint

'GM_getValue' is not defined
let cacheBattleInfo = GM_getValue('cacheBattleInfo', {});

Check failure on line 566 in psnineplus.js

View workflow job for this annotation

GitHub Actions / eslint

'GM_getValue' is not defined

const updateTopMenuNotice = (lista, listb) => { // 定义函数:变更顶部菜单通知红点,多处执行
let count = 0;
Expand Down Expand Up @@ -600,7 +600,7 @@
result.push(gameID);
});
cacheBattleInfo = { list: result, lastUpdate: new Date().getTime() };
GM_setValue('cacheBattleInfo', cacheBattleInfo);

Check failure on line 603 in psnineplus.js

View workflow job for this annotation

GitHub Actions / eslint

'GM_setValue' is not defined
updateTopMenuNotice(userBattleMonitors, cacheBattleInfo.list);
}
},
Expand All @@ -609,12 +609,10 @@
};

// 页面加载时执行约战监测功能
if (cacheBattleInfo.lastUpdate && new Date().getTime() - cacheBattleInfo.lastUpdate < settings.BattleInfoUpdateInterval) {

Check failure on line 612 in psnineplus.js

View workflow job for this annotation

GitHub Actions / eslint

This line has a length of 126. Maximum allowed is 100
updateTopMenuNotice(userBattleMonitors, cacheBattleInfo.list);
console.log('use cached BattleRecuritInfo');
} else {
updateBattleRecuritInfo();
console.log('update BattleRecuritInfo');
}

// 在游戏的约战页面添加约战监控按钮
Expand Down Expand Up @@ -650,7 +648,7 @@
userBattleMonitors.push(gameID);
monitorBTN.textContent = '移除约战监控';
}
GM_setValue('userBattleMonitors', userBattleMonitors);

Check failure on line 651 in psnineplus.js

View workflow job for this annotation

GitHub Actions / eslint

'GM_setValue' is not defined
updateTopMenuNotice(userBattleMonitors, cacheBattleInfo.list);
});
}
Expand Down Expand Up @@ -718,55 +716,159 @@
);

/*
在 LocatStorage 中保存个人游戏完成度函数
添加于 /psnid\/[A-Za-z0-9_-]+\/?$/ 页面,以及该页自动翻页函数内部
*/
在 LocatStorage 中保存个人游戏完成度函数,为避免过多的页面重复请求,逻辑梳理如下:

场景:
1. 更新的奖杯一定在前,但用户可能会隐藏游戏或解除隐藏,导致内容不再确定。
2. 隐藏游戏条目不影响本地已有数据,也不要求本地数据作对应删除,但影响页码数和对应的更新记录
3. 由于设置为 Ajax 5 秒翻页,所以存在前几页数据已更新,后几页数据因为用户关闭页面而未更新的情况
4. 用户新开坑,可能导致页面数量增长,此时,最后几页也未记录更新时间,但实际是不需要更新的

简化:
1. 没有时间记录的页面,都需要更新,有时间记录的页面,从前往后更新,遇到无变化奖杯条目的就停止
2. 当用户进行异常操作时,需要自行通过翻页刷新数据
*/

// GM_setValue('personalGameCompletions', []);
// console.log(GM_getValue('personalGameCompletions', []));
// GM_setValue('personalGameCompletionsLastUpdate', []);

const parseCompletionPage = (content) => {
// 游戏进度信息
const tdElements = content.querySelectorAll('table.list tbody > tr');
const thisPageCompletions = Array.from(tdElements).map((tr) => {
const completionElement = tr.querySelector('div.progress > div');
const completion = completionElement ? parseFloat(completionElement.textContent) : 0;
const platinumElement = tr.querySelector('span.text-platinum');
const platinum = platinumElement ? platinumElement.textContent === '白1' : false;
const gameIDElement = tr.querySelector('a');
const gameID = gameIDElement.href.match(/\/psngame\/(\d+)/)[1];
return [gameID, completion, platinum];
});

const savePersonalGameCompletions = (configifneeded) => {
// if GM_setValue && GM_getValue is enabled
const thisFeatureEnabled = (configifneeded || true) && (typeof GM_setValue === 'function' && typeof GM_getValue === 'function');

if (thisFeatureEnabled) {
// 获得当前页的游戏完成度
const tdElements = document.querySelectorAll('table.list tbody > tr');
const personalGameCompletions = Array.from(tdElements).map((tr) => {
const completionElement = tr.querySelector('div.progress > div');
const completion = completionElement ? parseFloat(completionElement.textContent) : 0;
const platinumElement = tr.querySelector('span.text-platinum');
const platinum = platinumElement ? platinumElement.textContent === '白1' : false;
const gameIDElement = tr.querySelector('a');
const gameID = gameIDElement.href.match(/\/psngame\/(\d+)/)[1];
return [gameID, completion, platinum];
});
// 获得总页数和总条目数
let totalPages = 0; let
totalItems = 0;
const PaginationEle = content.querySelectorAll('.page > ul > li > a');
if (PaginationEle.length > 2) {
totalPages = parseInt(PaginationEle[PaginationEle.length - 2].innerText, 10);
totalItems = parseInt(PaginationEle[PaginationEle.length - 1].innerText, 10);
}

return { totalPages, totalItems, thisPageCompletions };
};

// 读取已保存的历史
const history = GM_getValue('personalGameCompletions', []);
const updateCompletions = (updateList) => {
const gameCompletionHistory = GM_getValue('personalGameCompletions', []);

Check failure on line 762 in psnineplus.js

View workflow job for this annotation

GitHub Actions / eslint

'GM_getValue' is not defined
let addCounts = 0;

// 用当前覆盖历史
personalGameCompletions.forEach((currentItem) => {
const index = history.findIndex((historyItem) => historyItem[0] === currentItem[0]);
if (index !== -1) {
history[index] = currentItem;
} else {
history.push(currentItem);
updateList.forEach((completion) => {
const index = gameCompletionHistory.findIndex((historyItem) => historyItem[0] === completion[0]);

Check failure on line 766 in psnineplus.js

View workflow job for this annotation

GitHub Actions / eslint

This line has a length of 105. Maximum allowed is 100
if (index !== -1) {
if (gameCompletionHistory[index][1] !== completion[1]) { addCounts += 1; }
gameCompletionHistory[index] = completion;
} else {
gameCompletionHistory.push(completion);
addCounts += 1;
}
});

GM_setValue('personalGameCompletions', gameCompletionHistory);
const totalRecords = gameCompletionHistory.length;
return { addCounts, totalRecords };
};

// 后台更新主函数
const loadGameCompletions = (userid, startPageID) => {
// console.log(`https://psnine.com/psnid/${userid}/psngame?page=${startPageID}`)
$.ajax({
type: 'GET',
url: `https://psnine.com/psnid/${userid}/psngame?page=${startPageID}`,
dataType: 'html',
async: true,
success: (data, status) => {
if (status === 'success') {
// 读取历史数据
const pagesUpdateTime = GM_getValue('personalGameCompletionsLastUpdate', []);
// 2024.07.30 bug fix: 错误地保存他人的游戏完成度 - 已经修复,但用户端的旧数据需要清除
if (Array.isArray(pagesUpdateTime) === false
|| pagesUpdateTime[0] === undefined
|| pagesUpdateTime[0] < 1722333600000 // 2024-07-30 18:00 GMT+0800
) {
GM_setValue('personalGameCompletions', []);
pagesUpdateTime = [];
}

// 读取当前页奖杯完成数据
const page = document.createElement('html');
page.innerHTML = data;
const o = parseCompletionPage(page);
const { thisPageCompletions } = o;
const totalPages = o.totalPages || pagesUpdateTime.length || 1;
const { addCounts } = updateCompletions(thisPageCompletions);

// 更新页面记录时间
pagesUpdateTime[startPageID - 1] = new Date().getTime();
GM_setValue('personalGameCompletionsLastUpdate', pagesUpdateTime);

// 根据规则计算下一页
if (addCounts === thisPageCompletions.length && startPageID < totalPages - 1) {
setTimeout(() => { loadGameCompletions(userid, startPageID + 1); }, 5000);
return true;
}
const fullfilledUpdateTime = pagesUpdateTime.concat(Array(totalPages - pagesUpdateTime.length).fill(0));
const nextIdx = fullfilledUpdateTime.findIndex((time) => time === undefined || time === 0 || time === null);
if (nextIdx !== -1) {
setTimeout(() => { loadGameCompletions(userid, nextIdx + 1); }, 5000);
return true;
}
return false;
}
});
return true;
},
error: (e) => { console.log('loadGameCompletions error', e); },
});
};

// 保存更新后的历史记录
GM_setValue('personalGameCompletions', history);
// console.log(GM_getValue('personalGameCompletions'))
return true;
// 获取个人 ID
const myHomePage = document.querySelectorAll('ul.r li.dropdown ul li a')[0].href;
const myUserId = myHomePage.match(/\/psnid\/([A-Za-z0-9_-]+)/)[1] || '*';
const myGamePageURLRegex = new RegExp(`psnid/${myUserId}/?(?:psngame(?:\\?page=(\\d+))?|$)`);
// match: https://psnine.com/psnid/kaikaiiiiiiiwu
// match: https://psnine.com/psnid/kaikaiiiiiiiwu/
// match: https://psnine.com/psnid/kaikaiiiiiiiwu/psngame
// match: https://psnine.com/psnid/kaikaiiiiiiiwu/psngame?page=2
// dismatch: https://psnine.com/psnid/kaikaiiiiiiiwu/comment

// 后台更新频次控制
const bgUpdateMyGameCompletion = () => {
const pagesUpdateTime = GM_getValue('personalGameCompletionsLastUpdate', []);
const now = new Date().getTime();
if (pagesUpdateTime[0] === undefined || now - pagesUpdateTime[0] > 60 * 60 * 1000) {
loadGameCompletions(myUserId, 1);
}
return false;
};

// 在个人页面或个人游戏列表页更新数据
if (
/psnid\/[A-Za-z0-9_-]+\/?$/.test(window.location.href) || /psnid\/[A-Za-z0-9_-]+\/psngame\/?/.test(window.location.href)
) {
savePersonalGameCompletions();
// 在用户浏览个人页面或个人游戏列表页时,无视 Interval 白嫖一次数据更新
if (myGamePageURLRegex.test(window.location.href)) {
const pagesUpdateTime = GM_getValue('personalGameCompletionsLastUpdate', []);
const pageid = parseInt(window.location.href.match(myGamePageURLRegex)[1], 10) || 1;

const { totalItems, thisPageCompletions } = parseCompletionPage(document);
const { totalRecords } = updateCompletions(thisPageCompletions);

pagesUpdateTime[pageid - 1] = new Date().getTime();
GM_setValue('personalGameCompletionsLastUpdate', pagesUpdateTime);
if (totalRecords < totalItems || totalItems === 0) {
const nextPageID = pageid === 1 ? 2 : 1;
loadGameCompletions(myUserId, nextPageID);
}
} else {
bgUpdateMyGameCompletion(); // 定时更新
}

/// /////////////////////////////////////////////////////////////////////////////

if (
/psnid\/[A-Za-z0-9_-]+\/?$/.test(window.location.href)
&& $('tbody').length > 2
Expand Down Expand Up @@ -799,9 +901,6 @@
$('tbody > tr:last').after(nextGameContent);
isbool2 = true;
gamePageIndex += 1;

// 同步更新个人游戏完成度
savePersonalGameCompletions();
} else {
$('#loadingMessage').text('没有更多游戏了...');
}
Expand Down Expand Up @@ -1128,7 +1227,7 @@
.append(`&nbsp;<a class="psnnode" id="hot" style="background-color: ${tagBackgroundColor === 'rgb(43, 43, 43)'
? 'rgb(125 69 67)' // 暗红色
: 'rgb(217, 83, 79)' // 鲜红色
};color: rgb(255, 255, 255);">🔥热门&nbsp;</a>`);
};color: rgb(255, 255, 255);">🔥热门&nbsp;</a>`);
}
});
};
Expand Down
Loading