您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds current pricing info from CheapShark for other stores to the Steam Store
- // ==UserScript==
- // @name CheapShark Steam Integration
- // @description Adds current pricing info from CheapShark for other stores to the Steam Store
- // @version 0.3.0
- // @author Phlebiac
- // @match https://store.steampowered.com/app/*
- // @connect www.cheapshark.com
- // @run-at document-end
- // @noframes
- // @license MIT; https://opensource.org/licenses/MIT
- // @namespace Phlebiac/CheapShark
- // @icon https://www.cheapshark.com/img/icons/round_114.png
- // @grant GM_addStyle
- // @grant GM_getValue
- // @grant GM_setValue
- // @grant GM_xmlhttpRequest
- // @grant unsafeWindow
- // ==/UserScript==
- ;(async () => {
- 'use strict'
- const BASE_URL = 'https://www.cheapshark.com';
- const API_URL = `${BASE_URL}/api/1.0/`;
- const METACRITIC_BASE = 'https://www.metacritic.com';
- let userPrefs = {
- open_in_new_tab: GM_getValue('open_in_new_tab', true),
- show_metacritic: GM_getValue('show_metacritic', true),
- store_info_cache: GM_getValue('store_info_cache', []),
- }
- const appId = getCurrentAppId();
- if (!appId) {
- return;
- }
- injectCSS();
- if (!userPrefs.store_info_cache.length) {
- log('Requesting store data...');
- GM_xmlhttpRequest({
- method: 'GET',
- url: `${API_URL}stores`,
- onload: buildStoreCache
- });
- } else {
- //log(`Using cache of ${userPrefs.store_info_cache.length} stores`);
- }
- GM_xmlhttpRequest({
- method: 'GET',
- url: `${API_URL}deals?steamAppID=${appId}&sortBy=Price`,
- onload: addDealsToStorePage
- })
- function getCurrentAppId() {
- const urlPath = window.location.pathname;
- const appId = urlPath.match(/\/app\/(\d+)/);
- if (appId === null) {
- log('Unable to get AppId from URL path:', urlPath);
- return false;
- }
- return appId[1];
- }
- function buildStoreCache(response) {
- if (response.status === 200) {
- try {
- var stores = JSON.parse(response.responseText);
- log(`Caching data for ${stores.length} stores`);
- stores.forEach(store => { userPrefs.store_info_cache[store.storeID] = store; });
- GM_setValue('store_info_cache', userPrefs.store_info_cache);
- } catch (err) {
- log('Unable to parse CheapShark response as JSON:', response);
- log('Javascript error:', err);
- }
- } else {
- log('Got unexpected HTTP code from CheapShark:', response.status);
- }
- }
- function addDealsToStorePage(response) {
- if (response.status === 200) {
- try {
- var deals = JSON.parse(response.responseText);
- //log(`Found ${deals.length} deals`);
- } catch (err) {
- log('Unable to parse CheapShark response as JSON:', response);
- log('Javascript error:', err);
- }
- } else {
- log('Got unexpected HTTP code from CheapShark:', response.status);
- }
- let target = document.querySelector('.game_purchase_action');
- if (target && deals.length > 0) {
- var bestDeal = deals[0];
- let node = Object.assign(document.createElement('span'), {
- className: 'cheapshark_deals_row btnv6_blue_hoverfade btn_medium'
- });
- if (userPrefs.show_metacritic && bestDeal.metacriticScore > 0) {
- node.appendChild(showMetaCritic(bestDeal));
- }
- node.appendChild(lowestPrice(bestDeal));
- if (deals.length > 1) {
- node.appendChild(listDeals(deals));
- }
- target.insertBefore(node, target.firstChild);
- target.insertBefore(preferencesDialog(), node);
- }
- }
- function showMetaCritic(deal) {
- let node = Object.assign(document.createElement('a'), {
- className: 'cheapshark_metacritic',
- href: `${METACRITIC_BASE}${deal.metacriticLink}`,
- title: 'View on MetaCritic',
- target: userPrefs.open_in_new_tab ? '_blank' : '_self'
- });
- node.appendChild(Object.assign(document.createElement('img'), {
- src: `${METACRITIC_BASE}/MC_favicon.png`,
- className: 'cheapshark_metacritic_img',
- height: 20
- }));
- node.appendChild(Object.assign(document.createElement('span'), {
- textContent: `${deal.metacriticScore}`,
- className: `cheapshark_metacritic_score`
- }));
- return node;
- }
- function lowestPrice(deal) {
- var store = userPrefs.store_info_cache[deal.storeID];
- let node = Object.assign(document.createElement('a'), {
- className: 'cheapshark_lowest',
- href: `${BASE_URL}/redirect?dealID=${deal.dealID}`,
- title: `$${deal.salePrice} on ${store.storeName}`,
- target: userPrefs.open_in_new_tab ? '_blank' : '_self'
- });
- node.appendChild(Object.assign(document.createElement('span'), {
- textContent: `Lowest: $${deal.salePrice}`,
- className: `cheapshark_lowest_price`,
- }));
- node.appendChild(Object.assign(document.createElement('img'), {
- src: `${BASE_URL}${store.images.icon}`,
- className: 'cheapshark_lowest_img'
- }));
- return node;
- }
- function listDeals(deals) {
- // Build out a menu option for each store deal
- let dealOptions = '';
- for (const deal of deals) {
- var store = userPrefs.store_info_cache[deal.storeID];
- dealOptions = `${dealOptions}
- <div class="cheapshark_deal_option queue_menu_option">
- <div class="cheapshark_valign queue_menu_option_label">
- <a href="${BASE_URL}/redirect?dealID=${deal.dealID}" class="option_title">
- <img class="cheapshark_valign" src="${BASE_URL}${store.images.icon}"> $${deal.salePrice} on ${store.storeName}
- </a>
- </div>
- </div>`;
- }
- return Object.assign(document.createElement('div'), {
- className: 'cheapshark_deals_dropdown queue_control_button queue_btn_menu',
- innerHTML: `
- <div class="queue_menu_arrow">
- <span><img src="https://store.cloudflare.steamstatic.com/public/images/v6/btn_arrow_down_padded.png"></span>
- </div>
- <div class="cheapshark_menu_flyout queue_menu_flyout">
- <div class="queue_flyout_content">${dealOptions}
- </div>
- </div>`
- });
- }
- function preferencesDialog() {
- const container = Object.assign(document.createElement('span'), {
- className: 'cheapshark_prefs_icon',
- title: 'Preferences for CheapShark Steam Integration',
- textContent: '⚙'
- })
- container.addEventListener('click', () => {
- const html = `
- <div class="cheapshark_prefs">
- <div class="newmodal_prompt_description">
- New preferences will only take effect after you refresh the page.
- </div>
- <blockquote>
- <div>
- <input type="checkbox" id="cheapshark_open_in_new_tab" ${ userPrefs.open_in_new_tab ? 'checked' : '' } />
- <label for="cheapshark_open_in_new_tab">Open links in a new tab</label>
- </div>
- <div>
- <input type="checkbox" id="cheapshark_show_metacritic" ${ userPrefs.show_metacritic ? 'checked' : '' } />
- <label for="cheapshark_show_metacritic">Show MetaCritic score and link</label>
- </div>
- </blockquote>
- </div>`
- unsafeWindow.ShowDialog('CheapShark on Steam Prefs', html);
- // Handle preferences changes
- const inputs = document.querySelectorAll('.cheapshark_prefs input');
- for (const input of inputs) {
- input.addEventListener('change', event => {
- const target = event.target;
- const prefName = target.id.replace('cheapshark_', '');
- switch (target.type) {
- case 'text':
- userPrefs[prefName] = target.value;
- GM_setValue(prefName, target.value);
- break;
- case 'checkbox':
- userPrefs[prefName] = target.checked;
- GM_setValue(prefName, target.checked);
- break;
- default:
- break;
- }
- })
- }
- })
- return container;
- }
- function injectCSS() {
- GM_addStyle(`
- .cheapshark_deals_row {
- border-style: solid;
- border-color: black;
- //padding: 0 0 2px 5px;
- padding: 5px 5px 5px 5px;
- background: #4d4b49;
- }
- .cheapshark_deals_row a:hover {
- color: white;
- }
- .cheapshark_metacritic {
- margin-right: 6px;
- }
- .cheapshark_metacritic_img {
- vertical-align: middle;
- margin-right: 4px;
- }
- .cheapshark_metacritic_score {
- font-size: 16px;
- vertical-align: middle;
- }
- .cheapshark_lowest {
- padding: 0 6px 0 6px;
- }
- .cheapshark_lowest_img {
- vertical-align: middle;
- }
- .cheapshark_lowest_price {
- font-size: 14px;
- vertical-align: middle;
- padding-right: 5px;
- }
- .cheapshark_deals_dropdown {
- //margin: -6px 0 -6px 0;
- }
- .cheapshark_menu_flyout {
- position: relative !important;
- width: unset !important;
- padding: 6px 6px;
- margin: -34px -6px -6px -240px;
- //position: absolute;
- //left: 0px;
- //margin-top: 5px;
- }
- .cheapshark_deal_option {
- padding: 2px !important;
- }
- .cheapshark_valign {
- vertical-align: middle;
- }
- .cheapshark_prefs_icon {
- font-size: 20px;
- padding: 0 2px;
- //vertical-align: top;
- cursor: pointer;
- }
- .cheapshark_prefs input[type="checkbox"], .cheapshark_prefs label {
- line-height: 20px;
- vertical-align: middle;
- display: inline-block;
- color: #66c0f4;
- cursor: pointer;
- }
- .cheapshark_prefs blockquote {
- margin: 15px 0 5px 10px;
- }`)
- }
- function log() {
- console.log('[CheapShark Steam Integration]', ...arguments)
- }
- })()