检测其乐论坛福利放送版块的赠key剩余数量/时间
当前为
// ==UserScript== // @name Giveaway Left Check // @namespace Giveaway-Left-Check // @version 0.4 // @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/[email protected]/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 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) } } } function 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]+/)[0] 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) } } }) } function 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) } } }) } function 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) } } }) } function 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]+).*\)/)[1] 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) } } }) } function 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]+/)[0] 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) } } }) } function 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]) : 0 let fullLevel = response.responseText.match(/full_level.*?=.*?([\d]+)/) fullLevel = fullLevel ? parseInt(fullLevel[1]) : 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 (var 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) } } }) } function 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(function () { 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) } } }) } function 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) } } }) } function 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]+/)[0] 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) } } }) } function checkCubejoy (gameId, e) { GM_xmlhttpRequest({ method: 'get', url: 'https://cart.cubejoy.com/Handler/Data.ashx?type=GetModel¶m=' + gameId + '%7C1', timeout: 30 * 1000, responseType: 'json', 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 price = response.response.Data.s_price if (/^[\d]+$/.test(price)) { 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) } } }) } function 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)) const hour = parseInt(restSec / (60 * 60 * 1000) % 24) const min = parseInt(restSec / (60 * 1000) % 60) const sec = parseInt(restSec / 1000 % 60) return { time: `${day > 0 ? `${day} 天 ` : ''} ${hour}小时${min}分${sec}秒`, class: day > 0 ? 'lk-green' : (hour > 1 ? 'lk-yellow' : 'lk-red') } } function getClass (left) { const leftKey = parseInt(left) if (leftKey > 99) { return 'lk-green' } else if (leftKey > 0 && leftKey < 100) { return 'lk-yellow' } else { return 'lk-red' } } 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; } `) })()