-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcngal2steam.user.js
114 lines (101 loc) · 4.18 KB
/
cngal2steam.user.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
// ==UserScript==
// @name CnGal on Steam
// @namespace https://github.com/Vinfall/UserScripts
// @version 0.3.4
// @author Vinfall
// @match https://store.steampowered.com/app/*
// @icon https://www.cngal.org/favicon.ico
// @grant GM_xmlhttpRequest
// @license MIT
// @description Show CnGal link on Steam
// @description:zh-cn 在 Steam 商店页面显示 CnGal 链接
// @connect api.cngal.org
// @run-at document-end
// ==/UserScript==
/*
Doc: https://api.cngal.org/swagger/index.html
API: /api/storeinfo/GetAllGameStoreInfo
*/
(() => {
const appId = /app\/(\d+)\//.exec(location.href)?.pop();
const cacheTime = 3000; // in seconds, 5 minutes by default
const cacheKey = 'cngal_steam';
function makeRow(rowClass, subtitle, linkText, linkUrl) {
const row = document.createElement('div');
row.className = `dev_row ${rowClass}`;
const subtitleEl = document.createElement('div');
subtitleEl.className = 'subtitle column';
subtitleEl.textContent = subtitle;
let linkEl;
if (linkUrl) {
linkEl = document.createElement('a');
linkEl.className = 'date';
linkEl.textContent = linkText;
linkEl.href = linkUrl;
} else {
linkEl = document.createElement('div');
linkEl.className = 'date';
linkEl.textContent = linkText;
}
row.appendChild(subtitleEl);
row.appendChild(linkEl);
return row;
}
function fetchData() {
GM_xmlhttpRequest({
method: 'GET',
url: 'https://api.cngal.org/api/storeinfo/GetAllGameStoreInfo',
headers: {
accept: 'application/json',
},
// platformType only has "Steam", and API response only contains entries with a platform
// jq -r '.[].id' GetAllGameStoreInfo.json | wc -l
// jq -r '.[].platformType' GetAllGameStoreInfo.json | wc -l
onload: (response) => {
const result = JSON.parse(response.responseText);
const cacheData = {
data: result,
timestamp: Date.now(),
};
localStorage.setItem(cacheKey, JSON.stringify(cacheData));
processData(result);
},
onerror: (error) => {
console.error('Error fetching data from CnGal API:', error);
},
});
}
function processData(data) {
const item = data.find((game) => game.platformType === 'Steam' && game.link === appId);
// TODO: log appid & name, but only when it has "Visual Novel" or "Dating Sim" tag
if (!item) {
console.log('Game not listed on CnGal.');
return;
}
const cngalIdRow = makeRow('cngal_id', 'CnGal', item.id, `https://www.cngal.org/entries/index/${item.id}`);
const releaseDate = document.querySelector('.release_date');
const vndbIdRow = document.querySelector('.dev_row vndb_id');
// TODO: fix selector on cromite
// const releaseDateMobileLabels = document.querySelectorAll('.grid_label.grid_date');
// const releaseDateMobileContent =
// releaseDateMobileLabels.length > 0 ? releaseDateMobileLabels[0].nextElementSibling : null;
if (vndbIdRow) {
vndbIdRow.parentNode.insertBefore(cngalIdRow, vndbIdRow);
} else if (releaseDate) {
releaseDate.parentNode.insertBefore(cngalIdRow, releaseDate.nextSibling);
// } else if (releaseDateMobileContent) {
// releaseDateMobileContent.parentNode.insertBefore(cngalIdRow, releaseDateMobileContent.nextSibling);
} else {
const firstDevRow = document.querySelector('.glance_ctn_responsive_left .dev_row');
if (firstDevRow) {
firstDevRow.parentNode.insertBefore(cngalIdRow, firstDevRow);
}
}
}
const cachedData = JSON.parse(localStorage.getItem(cacheKey));
if (cachedData && Date.now() - cachedData.timestamp < cacheTime * 1000) {
processData(cachedData.data);
} else {
fetchData();
}
})();