/* eslint-disable new-cap */
// ==UserScript==
// @name Giveaway Left Check
// @namespace Giveaway-Left-Check
// @version 0.5
// @description 检测其乐论坛福利放送版块的赠key剩余数量/时间
// @author HCLonely
// @iconURL https://auto-task.hclonely.com/img/favicon.ico
// @homepage https://github.com/HCLonely/user.js
// @supportURL https://github.com/HCLonely/user.js/issues
// @include *://keylol.com/*
// @require https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.min.js
// @run-at document-end
// @grant GM_xmlhttpRequest
// @grant GM_addStyle
// @connect marvelousga.com
// @connect grabfreegame.com
// @connect bananagiveaway.com
// @connect gamehag.com
// @connect prys.revadike.com
// @connect takekey.ru
// @connect alienwarearena.com
// @connect giveaway.su
// @connect givekey.ru
// @connect store.cubejoy.com
// @connect cart.cubejoy.com
// @connect itch.io
// ==/UserScript==
(function () {
'use strict';
const getTime = (dateStr) => {
const endDate = new Date(dateStr).getTime();
const nowDate = new Date().getTime();
if (nowDate > endDate) return 0;
const restSec = endDate - nowDate;
const day = parseInt(restSec / (60 * 60 * 24 * 1000), 10);
const hour = parseInt(restSec / (60 * 60 * 1000) % 24, 10);
const min = parseInt(restSec / (60 * 1000) % 60, 10);
const sec = parseInt(restSec / 1000 % 60, 10);
return {
time: `${day > 0 ? `${day} 天 ` : ''} ${hour}小时${min}分${sec}秒`,
// eslint-disable-next-line no-nested-ternary
class: day > 0 ? 'lk-green' : (hour > 1 ? 'lk-yellow' : 'lk-red')
};
};
const getClass = (left) => {
const leftKey = parseInt(left, 10);
if (leftKey > 99) {
return 'lk-green';
} else if (leftKey > 0 && leftKey < 100) {
return 'lk-yellow';
}
return 'lk-red';
};
const checkMarvelousga = (id, e) => {
GM_xmlhttpRequest({
method: 'get',
url: 'https://marvelousga.com/',
timeout: 30 * 1000,
ontimeout: () => {
const thisEle = $(`a[href="${$(e).attr('href')}"]`);
if (!thisEle.next().hasClass('left-keys')) thisEle.after('<font class="left-keys lk-black" title="请求超时">timeout</font>');
},
onerror: (err) => {
const thisEle = $(`a[href="${$(e).attr('href')}"]`);
if (!thisEle.next().hasClass('left-keys')) thisEle.after('<font class="left-keys lk-black" title="请求失败">error</font>');
console.error(err);
},
onload: (response) => {
const thisEle = $(`a[href="${$(e).attr('href')}"]`);
try {
const a = $(`<div>${response.responseText}</div>`).find(`a[href*="${id}"]`);
if (a.length > 0) {
const [leftKey] = a.parent().children('small')
.text()
.trim()
.match(/[\d]+/);
if (!thisEle.next().hasClass('left-keys')) thisEle.after(`<font class="left-keys ${getClass(leftKey)}" title="剩余key数量">${leftKey}</font>`);
} else {
if (!thisEle.next().hasClass('left-keys')) thisEle.after(`<font class="left-keys ${getClass(0)}" title="剩余key数量">0</font>`);
}
} catch (err) {
if (!thisEle.next().hasClass('left-keys')) thisEle.after('<font class="left-keys lk-black" title="获取数据失败">error</font>');
console.error(err);
}
}
});
};
const checkGrabfreegame = (url, e) => {
GM_xmlhttpRequest({
method: 'get',
url,
timeout: 30 * 1000,
ontimeout: () => {
const thisEle = $(`a[href="${$(e).attr('href')}"]`);
if (!thisEle.next().hasClass('left-keys')) thisEle.after('<font class="left-keys lk-black" title="请求超时">timeout</font>');
},
onerror: (err) => {
const thisEle = $(`a[href="${$(e).attr('href')}"]`);
if (!thisEle.next().hasClass('left-keys')) thisEle.after('<font class="left-keys lk-black" title="请求失败">error</font>');
console.error(err);
},
onload: (response) => {
const thisEle = $(`a[href="${$(e).attr('href')}"]`);
try {
const counter = $(`<div>${response.responseText}</div>`).find('#giveaway .left>b');
if (counter.length > 0) {
const leftKey = counter.text().trim();
if (!thisEle.next().hasClass('left-keys')) thisEle.after(`<font class="left-keys ${getClass(leftKey)}" title="剩余key数量">${leftKey}</font>`);
} else {
if (!thisEle.next().hasClass('left-keys')) thisEle.after(`<font class="left-keys ${getClass(0)}" title="剩余key数量">0</font>`);
}
} catch (err) {
if (!thisEle.next().hasClass('left-keys')) thisEle.after('<font class="left-keys lk-black" title="获取数据失败">error</font>');
console.error(err);
}
}
});
};
const checkGamehag = (url, e) => {
GM_xmlhttpRequest({
method: 'get',
url,
timeout: 30 * 1000,
ontimeout: () => {
const thisEle = $(`a[href="${$(e).attr('href')}"]`);
if (!thisEle.next().hasClass('left-keys')) thisEle.after('<font class="left-keys lk-black" title="请求超时">timeout</font>');
},
onerror: (err) => {
const thisEle = $(`a[href="${$(e).attr('href')}"]`);
if (!thisEle.next().hasClass('left-keys')) thisEle.after('<font class="left-keys lk-black" title="请求失败">error</font>');
console.error(err);
},
onload: (response) => {
const thisEle = $(`a[href="${$(e).attr('href')}"]`);
try {
const counter = $(`<div>${response.responseText}</div>`).find('div.giveaway-counter')
.not(':contains("day")')
.find('.strong');
if (counter.length > 0) {
const leftKey = counter.text().trim();
if (!thisEle.next().hasClass('left-keys')) thisEle.after(`<font class="left-keys ${getClass(leftKey)}" title="剩余key数量">${leftKey}</font>`);
} else {
if (!thisEle.next().hasClass('left-keys')) thisEle.after(`<font class="left-keys ${getClass(0)}" title="剩余key数量">0</font>`);
}
} catch (err) {
if (!thisEle.next().hasClass('left-keys')) thisEle.after('<font class="left-keys lk-black" title="获取数据失败">error</font>');
console.error(err);
}
}
});
};
const checkPrys = (url, e) => {
GM_xmlhttpRequest({
method: 'get',
url,
timeout: 30 * 1000,
ontimeout: () => {
const thisEle = $(`a[href="${$(e).attr('href')}"]`);
if (!thisEle.next().hasClass('left-keys')) thisEle.after('<font class="left-keys lk-black" title="请求超时">timeout</font>');
},
onerror: (err) => {
const thisEle = $(`a[href="${$(e).attr('href')}"]`);
if (!thisEle.next().hasClass('left-keys')) thisEle.after('<font class="left-keys lk-black" title="请求失败">error</font>');
console.error(err);
},
onload: (response) => {
const thisEle = $(`a[href="${$(e).attr('href')}"]`);
try {
const counter = $(`<div>${response.responseText}</div>`).find('#header :contains("left")');
if (counter.length > 0) {
const [, leftKey] = counter.text().trim()
.match(/\(([\d]+).*\)/);
if (!thisEle.next().hasClass('left-keys')) thisEle.after(`<font class="left-keys ${getClass(leftKey)}" title="剩余key数量">${leftKey}</font>`);
} else {
if (!thisEle.next().hasClass('left-keys')) thisEle.after(`<font class="left-keys ${getClass(0)}" title="剩余key数量">0</font>`);
}
} catch (err) {
if (!thisEle.next().hasClass('left-keys')) thisEle.after('<font class="left-keys lk-black" title="获取数据失败">error</font>');
console.error(err);
}
}
});
};
const checkTakekey = (url, e) => {
GM_xmlhttpRequest({
method: 'get',
url,
timeout: 30 * 1000,
ontimeout: () => {
const thisEle = $(`a[href="${$(e).attr('href')}"]`);
if (!thisEle.next().hasClass('left-keys')) thisEle.after('<font class="left-keys lk-black" title="请求超时">timeout</font>');
},
onerror: (err) => {
const thisEle = $(`a[href="${$(e).attr('href')}"]`);
if (!thisEle.next().hasClass('left-keys')) thisEle.after('<font class="left-keys lk-black" title="请求失败">error</font>');
console.error(err);
},
onload: (response) => {
const thisEle = $(`a[href="${$(e).attr('href')}"]`);
try {
const counter = $(`<div>${response.responseText}</div>`).find('span.text-muted:contains("Left")');
if (counter.length > 0) {
const [leftKey] = counter.text().trim()
.match(/[\d]+/);
if (!thisEle.next().hasClass('left-keys')) thisEle.after(`<font class="left-keys ${getClass(leftKey)}" title="剩余key数量">${leftKey}</font>`);
} else {
if (!thisEle.next().hasClass('left-keys')) thisEle.after(`<font class="left-keys ${getClass(0)}" title="剩余key数量">0</font>`);
}
} catch (err) {
if (!thisEle.next().hasClass('left-keys')) thisEle.after('<font class="left-keys lk-black" title="获取数据失败">error</font>');
console.error(err);
}
}
});
};
const checkAlienwarearena = (url, e) => {
GM_xmlhttpRequest({
method: 'get',
url,
timeout: 30 * 1000,
ontimeout: () => {
const thisEle = $(`a[href="${$(e).attr('href')}"]`);
if (!thisEle.next().hasClass('left-keys')) thisEle.after('<font class="left-keys lk-black" title="请求超时">timeout</font>');
},
onerror: (err) => {
const thisEle = $(`a[href="${$(e).attr('href')}"]`);
if (!thisEle.next().hasClass('left-keys')) thisEle.after('<font class="left-keys lk-black" title="请求失败">error</font>');
console.error(err);
},
onload: (response) => {
const thisEle = $(`a[href="${$(e).attr('href')}"]`);
try {
let userCountry = response.responseText.match(/user_country.*?=.*?"([\w]+)"/);
userCountry = userCountry ? userCountry[1] : '';
let prestigeLevel = response.responseText.match(/prestige_level.*?=.*?([\d]+)/);
prestigeLevel = prestigeLevel ? parseInt(prestigeLevel[1], 10) : 0;
let fullLevel = response.responseText.match(/full_level.*?=.*?([\d]+)/);
fullLevel = fullLevel ? parseInt(fullLevel[1], 10) : 0;
let countryKeys = response.responseText.match(/countryKeys.*?=.*?(\{.+\});/);
if (countryKeys) {
countryKeys = JSON.parse(countryKeys[1]);
} else {
return;
}
const keyType = prestigeLevel ? 'prestige' : 'normal';
let userCountryKeys = countryKeys[userCountry][keyType];
let lowestLevelWithKeys;
let highestKeysForUser;
let keysForUser = false;
for (const level in userCountryKeys) {
if (userCountryKeys[level] > 0) {
if (!lowestLevelWithKeys) { lowestLevelWithKeys = level; }
if (fullLevel >= level) {
if (!highestKeysForUser || userCountryKeys[level] > highestKeysForUser) { highestKeysForUser = userCountryKeys[level]; }
}
}
}
if (!highestKeysForUser && keyType === 'prestige') {
userCountryKeys = countryKeys[userCountry].normal;
for (const level in userCountryKeys) {
if (userCountryKeys[level] > 0) {
if (!lowestLevelWithKeys) { lowestLevelWithKeys = level; }
if (fullLevel >= level) {
if (!highestKeysForUser || userCountryKeys[level] > highestKeysForUser) { highestKeysForUser = userCountryKeys[level]; }
}
}
}
}
if (highestKeysForUser) {
if (!thisEle.next().hasClass('left-keys')) thisEle.after(`<font class="left-keys ${getClass(highestKeysForUser)}" title="剩余key数量">${highestKeysForUser}</font>`);
keysForUser = true;
}
if (!keysForUser) {
if (lowestLevelWithKeys) {
if (!thisEle.next().hasClass('left-keys')) thisEle.after('<font class="left-keys lk-red" title="等级不足">等级不足</font>');
} else {
if (!thisEle.next().hasClass('left-keys')) thisEle.after('<font class="left-keys lk-red" title="剩余key数量">0</font>');
}
}
} catch (err) {
if (!thisEle.next().hasClass('left-keys')) thisEle.after('<font class="left-keys lk-black" title="获取数据失败">error</font>');
console.error(err);
}
}
});
};
const checkItch = (url, e) => {
GM_xmlhttpRequest({
method: 'get',
url,
timeout: 30 * 1000,
ontimeout: () => {
const thisEle = $(`a[href="${$(e).attr('href')}"]`);
if (!thisEle.next().hasClass('left-keys')) thisEle.after('<font class="left-keys lk-black" title="请求超时">timeout</font>');
},
onerror: (err) => {
const thisEle = $(`a[href="${$(e).attr('href')}"]`);
if (!thisEle.next().hasClass('left-keys')) thisEle.after('<font class="left-keys lk-black" title="请求失败">error</font>');
console.error(err);
},
onload: (response) => {
const thisEle = $(`a[href="${$(e).attr('href')}"]`);
try {
const counter = $(`<div>${response.responseText}</div>`).find('.promotion_dates .date_format');
if (counter.length > 0) {
const endTime = `${counter.attr('title').trim()}Z`;
const time = getTime(endTime);
if (time !== 0) {
if (!thisEle.next().hasClass('left-keys')) thisEle.after(`<font data-time="${endTime}" class="left-keys ${time.class}" title="剩余时间">${time.time}</font>`);
setInterval(() => {
const leftTimeEle = $(`font[data-time="${endTime}"]`);
const leftTime = getTime(endTime);
if (leftTime !== 0) {
if (!leftTimeEle.hasClass(leftTime.class)) leftTimeEle.attr('class', `left-keys ${leftTime.class}`);
leftTimeEle.text(leftTime.time);
} else {
leftTimeEle.attr('class', 'left-keys lk-red').attr('title', '活动已结束')
.text('end');
}
}, 500);
} else {
if (!thisEle.next().hasClass('left-keys')) thisEle.after('<font class="left-keys lk-red" title="活动已结束">end</font>');
}
} else {
if (!thisEle.next().hasClass('left-keys')) thisEle.after('<font class="left-keys lk-red" title="活动已结束">end</font>');
}
} catch (err) {
if (!thisEle.next().hasClass('left-keys')) thisEle.after('<font class="left-keys lk-black" title="获取数据失败">error</font>');
console.error(err);
}
}
});
};
const checkGiveawaysu = (url, e) => {
GM_xmlhttpRequest({
method: 'get',
url,
timeout: 30 * 1000,
ontimeout: () => {
const thisEle = $(`a[href="${$(e).attr('href')}"]`);
if (!thisEle.next().hasClass('left-keys')) thisEle.after('<font class="left-keys lk-black" title="请求超时">timeout</font>');
},
onerror: (err) => {
const thisEle = $(`a[href="${$(e).attr('href')}"]`);
if (!thisEle.next().hasClass('left-keys')) thisEle.after('<font class="left-keys lk-black" title="请求失败">error</font>');
console.error(err);
},
onload: (response) => {
const thisEle = $(`a[href="${$(e).attr('href')}"]`);
try {
const counter = $(`<div>${response.responseText}</div>`).find('div.giveaway-ended');
if (counter.length > 0) {
if (!thisEle.next().hasClass('left-keys')) thisEle.after(`<font class="left-keys ${getClass(0)}" title="已结束">End</font>`);
} else {
if (!thisEle.next().hasClass('left-keys')) thisEle.after(`<font class="left-keys ${getClass(100)}" title="进行中">Active</font>`);
}
} catch (err) {
if (!thisEle.next().hasClass('left-keys')) thisEle.after('<font class="left-keys lk-black" title="获取数据失败">error</font>');
console.error(err);
}
}
});
};
const checkGivekey = (url, e) => {
GM_xmlhttpRequest({
method: 'get',
url,
timeout: 30 * 1000,
ontimeout: () => {
const thisEle = $(`a[href="${$(e).attr('href')}"]`);
if (!thisEle.next().hasClass('left-keys')) thisEle.after('<font class="left-keys lk-black" title="请求超时">timeout</font>');
},
onerror: (err) => {
const thisEle = $(`a[href="${$(e).attr('href')}"]`);
if (!thisEle.next().hasClass('left-keys')) thisEle.after('<font class="left-keys lk-black" title="请求失败">error</font>');
console.error(err);
},
onload: (response) => {
const thisEle = $(`a[href="${$(e).attr('href')}"]`);
try {
const counter = $(`<div>${response.responseText}</div>`).find('#keys_count');
if (counter.length > 0) {
const [leftKey] = counter.text().trim()
.match(/[\d]+/);
if (!thisEle.next().hasClass('left-keys')) thisEle.after(`<font class="left-keys ${getClass(leftKey)}" title="剩余key数量">${leftKey}</font>`);
} else {
if (!thisEle.next().hasClass('left-keys')) thisEle.after(`<font class="left-keys ${getClass(0)}" title="剩余key数量">0</font>`);
}
} catch (err) {
if (!thisEle.next().hasClass('left-keys')) thisEle.after('<font class="left-keys lk-black" title="获取数据失败">error</font>');
console.error(err);
}
}
});
};
const checkCubejoy = (gameId, e) => {
GM_xmlhttpRequest({
method: 'get',
url: `https://store.cubejoy.com/html/en/store/goodsdetail/detail${gameId}.html`,
timeout: 30 * 1000,
ontimeout: () => {
const thisEle = $(`a[href="${$(e).attr('href')}"]`);
if (!thisEle.next().hasClass('left-keys')) thisEle.after('<font class="left-keys lk-black" title="请求超时">timeout</font>');
},
onerror: (err) => {
const thisEle = $(`a[href="${$(e).attr('href')}"]`);
if (!thisEle.next().hasClass('left-keys')) thisEle.after('<font class="left-keys lk-black" title="请求失败">error</font>');
console.error(err);
},
onload: (response) => {
const thisEle = $(`a[href="${$(e).attr('href')}"]`);
try {
let price = response.responseText.match(/<span class="gameoriginal">[\D]*?([\d.]+)/)?.[1] || '';
if (!price && response.responseText.includes('免费游戏</span>')) {
price = '0';
}
if (/^[\d.]+$/.test(price)) {
price = parseInt(price, 10);
if (price === 0) {
if (!thisEle.next().hasClass('left-keys')) thisEle.after(`<font class="left-keys ${getClass(100)}" title="游戏价格">¥ 0.00</font>`);
} else if (price > 0) {
if (!thisEle.next().hasClass('left-keys')) thisEle.after(`<font class="left-keys ${getClass(0)}" title="游戏价格">¥ ${price / 100}</font>`);
}
} else {
if (!thisEle.next().hasClass('left-keys')) thisEle.after('<font class="left-keys lk-black" title="获取游戏价格失败">error</font>');
}
} catch (err) {
if (!thisEle.next().hasClass('left-keys')) thisEle.after('<font class="left-keys lk-black" title="获取数据失败">error</font>');
console.error(err);
}
}
});
};
const leftTitle = $('.subforum_left_title_left_up a').eq(3);
const leftTitleHref = leftTitle.length > 0 ? leftTitle.attr('href') : '';
if ((leftTitleHref.includes('f319-1') || (leftTitleHref.includes('page=1') && leftTitleHref.includes('fid=319'))) && leftTitle.text() === '福利放送') {
const marvelousgaLinks = $('a[href*="marvelousga.com/giveaway/"]');
const grabfreegameLinks = $('a[href*="grabfreegame.com/giveaway/"],a[href*="bananagiveaway.com/giveaway/"]');
const gamehagLinks = $('a[href*="gamehag.com/giveaway/"]');
const prysLinks = $('a[href*="prys.revadike.com/giveaway/?id="]');
const takekeyLinks = $('a[href*="takekey.ru/distribution/"]');
const alienwarearenaLinks = $('a[href*="alienwarearena.com/ucf/show/"]');
const itchLinks = $('a[href*="itch.io/s/"]');
const giveawaysuLinks = $('a[href*="giveaway.su/giveaway/view/"]');
const givekeyLinks = $('a[href*="givekey.ru/giveaway/"]');
const cubejoyLinks = $('a[href*="store.cubejoy.com/html/en/store/goodsdetail/detail"],a[href*="cart.cubejoy.com/shop/xnEdition.html?pid="]');
if (marvelousgaLinks.length > 0) {
for (const e of marvelousgaLinks) {
const test = $(e).attr('href')
.match(/https?:\/\/marvelousga\.com\/giveaway\/(.+)/);
const id = test ? test[1] : false;
if (id) checkMarvelousga(id, e);
}
}
if (grabfreegameLinks.length > 0) {
for (const e of grabfreegameLinks) {
const link = $(e).attr('href');
if (/^https?:\/\/www\.(grabfreegame|bananagiveaway)\.com\/giveaway\/.*/.test(link)) checkGrabfreegame(link, e);
}
}
if (gamehagLinks.length > 0) {
for (const e of gamehagLinks) {
const link = $(e).attr('href');
if (/^https?:\/\/.*?gamehag\.com\/giveaway\/[\d]+.*?/.test(link)) checkGamehag(link, e);
}
}
if (prysLinks.length > 0) {
for (const e of prysLinks) {
const link = $(e).attr('href');
if (/^https?:\/\/prys\.revadike\.com\/giveaway\/\?id=[\d]+/.test(link)) checkPrys(link, e);
}
}
if (takekeyLinks.length > 0) {
for (const e of takekeyLinks) {
const link = $(e).attr('href');
if (/^https?:\/\/takekey\.ru\/distribution\/[\d]+/.test(link)) checkTakekey(link, e);
}
}
if (alienwarearenaLinks.length > 0) {
for (const e of alienwarearenaLinks) {
const link = $(e).attr('href');
if (/^https?:\/\/.*?\.alienwarearena\.com\/ucf\/show\/[\d]+.*?/.test(link)) checkAlienwarearena(link, e);
}
}
if (itchLinks.length > 0) {
for (const e of itchLinks) {
const link = $(e).attr('href');
if (/^https?:\/\/itch\.io\/s\/[\d]+?\/.*/.test(link)) checkItch(link, e);
}
}
if (giveawaysuLinks.length > 0) {
for (const e of giveawaysuLinks) {
const link = $(e).attr('href');
if (/^https?:\/\/giveaway\.su\/giveaway\/view\/[\d]+/.test(link)) checkGiveawaysu(link, e);
}
}
if (givekeyLinks.length > 0) {
for (const e of givekeyLinks) {
const link = $(e).attr('href');
if (/^https?:\/\/givekey\.ru\/giveaway\/[\d]+/.test(link)) checkGivekey(link, e);
}
}
if (cubejoyLinks.length > 0) {
for (const e of cubejoyLinks) {
const link = $(e).attr('href');
const gameId = link.match(/goodsdetail\/detail([\d]+?)\.html/) || link.match(/xnEdition\.html\?pid=([\d]+)/);
if (gameId && gameId[1]) checkCubejoy(gameId[1], e);
}
}
}
GM_addStyle(`
.left-keys{
color: #fff;
border-radius: 10px;
padding: 0 5px;
margin-left: 5px;
}
.lk-green{
background-color: #5cb85c;
}
.lk-yellow{
background-color: #f0ad4e;
}
.lk-red{
background-color: #d9534f;
}
.lk-black{
background-color: #000;
}
`);
}());