您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Create a ShoeBot !specials list
// ==UserScript== // @name getSpecialsSSG // @namespace none // @version 2021.09.26.2340 // @description Create a ShoeBot !specials list // @author MagentaRV // @match http://www.ddo.com/en/news/ddo-chronicle-issue-* // @match https://www.ddo.com/en/news/ddo-chronicle-issue-* // @match http://www.lotro.com/en/game/articles/lotro-beacon-issue-* // @match https://www.lotro.com/en/game/articles/lotro-beacon-issue-* // @grant none // ==/UserScript== ( function() { // objOptions = { trim: 'false/start/end/true', // nbsp: 'false/replacement/true', b: 'false/replacement/true', // i: 'false/replacement/true', u: 'false/replacement/true', // span: 'false/replacement/true', a: 'false/replacement/true' } function parseHTMLtoDiscord( htmlString, objOptions = {} ) { var rxpA = new RegExp( '<a href="((?:https?|mailto):(?:\/\/)?(?:[^"]*?))"(?:.*?)>(.*?)<\/a>', 'g' ); var rxpB = new RegExp( '<\/?(b|strong)(?:.*?)>', 'gi' ); var rxpI = new RegExp( '<\/?(i|emphasis)(?:.*?)>', 'gi' ); var rxpSpan = new RegExp( '<\/?span(?:.*?)>', 'gi' ); var rxpU = new RegExp( '<\/?u(?:.*?)>', 'gi' ); switch ( objOptions.trim ) {// Options are false to skip, start, end, or -default- both case false: break; case 'start': htmlString = htmlString.trimStart(); break; case 'end': htmlString = htmlString.trimEnd(); break; default: htmlString = htmlString.trim(); } switch ( objOptions.nbsp ) {// Options are false to skip, text to replace with, or -default- a plain space case false: break; default: htmlString = htmlString.replace( / /g, ( typeof objOptions.nbsp === 'string' ? objOptions.nbsp : ' ' ) ); } switch ( objOptions.b ) {// Options are false to skip, text to replace bold tag with, or -default- ** case false: break; default: htmlString = htmlString.replace( rxpB, ( typeof objOptions.b === 'string' ? objOptions.b : '**' ) ); } switch ( objOptions.i ) {// Options are false to skip, text to replace italic tag with, or -default- * case false: break; default: htmlString = htmlString.replace( rxpI, ( typeof objOptions.i === 'string' ? objOptions.i : '*' ) ); } switch ( objOptions.u ) {// Options are false to skip, text to replace underline tag with, or -default- __ case false: break; default: htmlString = htmlString.replace( rxpU, ( typeof objOptions.u === 'string' ? objOptions.u : '__' ) ); } switch ( objOptions.span ) {// Options are false to skip, text to replace span tag with, or -default- strip the span case false: break; default: htmlString = htmlString.replace( rxpSpan, ( typeof objOptions.span === 'string' ? objOptions.span : '' ) ); } switch ( objOptions.a ) {// Options are false to skip, text to replace anchor tag with, or -default- [link text](<link href>) case false: break; default: htmlString = htmlString.replace( rxpA, ( typeof objOptions.a === 'string' ? objOptions.a : '[$2](<$1>)' ) ); } return htmlString; } // Define which game we're parsing data for var strGame = document.URL.replace( /https?:\/\/(?:www\.)?/i, '' ); strGame = strGame.slice( 0, strGame.indexOf( '.' ) ).toLowerCase(); // Initialize variables var now = new Date( document.querySelector( 'time.submitted.pretty' ).title ), today = now, published = now, aWeekFromNow = new Date( now.getFullYear(), String( now.getMonth() ).padStart( 2, '0' ), String( now.getDate() + 7 ).padStart( 2, '0' ) ), author = '', sSotW = document.querySelectorAll( 'p.rtecenter a img' ), IMGsS = sSotW[ sSotW.length - 1 ].src, SSdesc = parseHTMLtoDiscord( sSotW[ sSotW.length - 1 ].closest( 'p' ).nextElementSibling.childNodes[ 0 ].innerHTML, { trim: false } ), InTheNews = [], freebieLinks = {}, rowFreebie = [], arrSalesFree = [], strSaleName = '', strSalePercent = '', arrSalesVal = [], arrSaleDates = [], objSaleDates = {}, arrBonusDays = [], objBonusDays = {}, arrBonusDaysVal = [], strWeeklyCoupon = '', arrWeeklyCoupon = [], arrFreebieDates = [], objFreebieDates = {}, strFreebieCode = '', strFreebieName = '', strFreebieLink = '', intFreebieQuantity = 0, strFreebieWeek = ''; if ( strGame === 'ddo' ) { var chronicleSections = []; // Create an object of possible freebies links freebieLinks = { 'unknown': 'https://ddowiki.com/index.php?title=Special:Search&go=Go&search=', }; } else { var beaconSections = []; // Create an object of possible freebies links freebieLinks = { 'unknown': 'https://lotro-wiki.com/index.php?title=Special:Search&go=Go&search=', '+5% Attack Damage x25 (90 minutes)': 'https://lotro-wiki.com/index.php/LOTRO_Store#Damage', '+5 Hope Boost': 'https://lotro-wiki.com/index.php/LOTRO_Store#Hope', '+20% Mount Speed (90 minute) boost': 'https://lotro-wiki.com/index.php/Item:%2B20%25_Mount_Speed_%2890_Min%29', '100% XP Boost (1 hour)': 'https://lotro-wiki.com/index.php/Item:Tome_of_Extraordinary_Experience_%28100%29', // '100% Mark Acquisition (90 minute) boost': '',// NO LINK 'Dye: Crimson': 'https://lotro-wiki.com/index.php/Item:Crimson_Dye', 'Dye: Ered Luin Blue': 'https://lotro-wiki.com/index.php/Item:Ered_Luin_Blue_Dye', 'Landscape Soldier Token': 'https://lotro-wiki.com/index.php/Item:Landscape_Soldier_Token', 'Morale Bubble Potion': 'https://lotro-wiki.com/index.php/Item:Morale_Bubble_Potion', 'Rejuvenation Potion x5': 'https://lotro-wiki.com/index.php/Item:Rejuvenation_Potion', 'Skill and Slayer Deed Boost': 'https://lotro-wiki.com/index.php/Item:Slayer_and_Skill_Deed_Boost_%2890_min%29', 'Slayer Deed Accelerator (60 minutes)': '', 'Universal Ingredient Pack': 'https://lotro-wiki.com/index.php/Item:Universal_Ingredient_Pack', 'Universal Solvent': 'https://lotro-wiki.com/index.php/Item:Universal_Solvent' } } function parseDates( dateString ) { let startDate = dateString.slice( ( dateString.indexOf( ', ' ) === -1 ? ( dateString.indexOf( 'Now' ) === -1 ? dateString.indexOf( ' through ' ) : 0 ) : dateString.indexOf( ', ' ) + 2 ), dateString.indexOf( ' through ' ) ).trim(); if ( startDate.match( /now/i ) ) { startDate = startDate.toLowerCase(); } if ( startDate.indexOf( 'starting ' ) !== -1 ) { let arrDate = startDate.match( /starting (\d?\d):\d\d ([AP])M Eastern \((-[45]) GMT\) on (January|February|March|April|May|June|July|August|September|October|November|December) (\d?\d)(?:st|nd|rd|th) and running/ ); startDate = arrDate[ 4 ] + ' ' + arrDate[ 5 ].padStart( 2, '0' ) + ', ' + ( new Date( now ) ).getFullYear() + ' ' + ( ( parseInt( arrDate[ 1 ] ) + ( arrDate[ 2 ] === 'A' ? 0 : 12 ) ) % 24 ) + ':00:00'; startDate = ( new Date( startDate ) ); } startDate = ( startDate === 'now' || startDate === '' ? now : ( startDate instanceof Date && !isNaN( startDate.valueOf() ) ? startDate.valueOf() : startDate + ', ' + ( new Date() ).getFullYear() ) ); let endDate = dateString.match( /(January|February|March|April|May|June|July|August|September|October|November|December) (\d?\d)(?:st|nd|rd|th)/ ); if ( !endDate ) { endDate = aWeekFromNow.valueOf(); } else { endDate = endDate[ 1 ] + ' ' + endDate[ 2 ].replace( /(st|nd|rd|th)[\.!:]/, '' ).padStart( 2, '0' ) + ', ' + ( new Date() ).getFullYear(); } return [ new Date( startDate ), new Date( endDate ) ]; } // Populate variables depending on which game if ( strGame === 'ddo' ) { chronicleSections = document.getElementsByTagName( 'h1' ); InTheNews = chronicleSections[ ( chronicleSections.length - 1 ) ].nextElementSibling.nextElementSibling.children; } else { author = document.querySelector( 'span.news.author' ).innerText.replace( 'By ', '' ); beaconSections = document.getElementsByTagName( 'h3' ); InTheNews = beaconSections[ ( beaconSections.length - 1 ) ].nextSibling.nextSibling.children; } arrBonusDays = Array.from( InTheNews ).splice( 0, ( Array.from( InTheNews ).length - 2 ) ); arrBonusDays.forEach( ( bonusDay, i ) => { bonusDay = parseHTMLtoDiscord( bonusDay.children[ 0 ].innerHTML ); let strMatchStart = bonusDay.match( new RegExp( '(Bonus Days brings? you )' ) ); strMatchStart = ( strMatchStart ? strMatchStart[ 0 ] : '' ); let intBonusDayStart = bonusDay.indexOf( strMatchStart ); let thisBD = bonusDay.slice( ( intBonusDayStart === -1 ? 0 : intBonusDayStart ), bonusDay.indexOf( ', ' ) ).replace( strMatchStart, '' ); if ( thisBD.indexOf( ' through ' ) !== -1 ) { thisBD = thisBD.slice( 0, thisBD.indexOf( ' through ' ) ); } if ( bonusDay.lastIndexOf( '!' ) === bonusDay.length ) { thisBD += '!'; } else { thisBD += bonusDay.slice( bonusDay.lastIndexOf( '!' ) ); } let arrBonusDates = parseDates( bonusDay ); let objBonusDates = { start: arrBonusDates[ 0 ], end: arrBonusDates[ 1 ] }; if ( intBonusDayStart !== -1 ) { objBonusDays[ i ] = { name: thisBD, dates: objBonusDates }; } } ); arrSalesFree = InTheNews[ ( InTheNews.length - 2 ) ]; strSaleName = parseHTMLtoDiscord( arrSalesFree.children[ 0 ].children[ 0 ].innerHTML ); strSalePercent = arrSalesFree.children[ 0 ].innerText.replace( strSaleName, '' ).match( /(\d+%)/ )[ 1 ]; arrSalesVal = Array.from( arrSalesFree.children[ 1 ].children ); arrSalesVal.forEach( ( item, i ) => { arrSalesVal[ i ] = item.innerText; } ); let tmpSale = arrSalesVal.pop(); arrSaleDates = parseDates( tmpSale ); objSaleDates = { start: arrSaleDates[ 0 ], end: arrSaleDates[ 1 ] }; rowFreebie = parseHTMLtoDiscord( InTheNews[ ( InTheNews.length - 1 ) ].children[ 0 ].innerHTML ); strFreebieName = rowFreebie.replace( /\*\*/g, '' ).trim().slice( 0, strFreebieName.indexOf( ' with the Coupon Code' ) ); strFreebieName = strFreebieName.slice( strFreebieName.indexOf( ' gets you a free ' ) ).replace( ' gets you a free ', '' ); intFreebieQuantity = ( strFreebieName.match( / x([\d]+)/ ) ? parseInt( strFreebieName.match( / x([\d]+)/ )[ 1 ] ) : 1 ); strFreebieLink = ( Object.keys( freebieLinks ).indexOf( strFreebieName.replace( / x([\d]+)/, '' ) ) === -1 ? freebieLinks.unknown + encodeURI( strFreebieName.replace( ' x' + intFreebieQuantity, '' ) ) : freebieLinks[ strFreebieName.replace( / x([\d]+)/, '' ) ] ); strFreebieCode = '**' + rowFreebie.slice( rowFreebie.indexOf( 'Coupon Code ' ), rowFreebie.indexOf( ', now through ' ) ).replace( 'Coupon Code ', '' ) + '**'; if ( strFreebieCode === '****' ) { strFreebieCode = rowFreebie.slice( rowFreebie.indexOf( 'Coupon Code ' ), rowFreebie.indexOf( ', now through ' ) ).replace( 'Coupon Code ', '' ); } arrFreebieDates = parseDates( rowFreebie ); objFreebieDates = { start: arrFreebieDates[ 0 ], end: arrFreebieDates[ 1 ] }; strFreebieWeek = objFreebieDates.start.toLocaleDateString( 'en-US', { month: 'short', day: '2-digit' } ) + ' - ' + objFreebieDates.end.toLocaleDateString( 'en-US', { month: 'short', day: '2-digit' } ); // Hand validate all components and make any needed adjustments /* Do the thing. */ // Create our object var objSpecials = { URI: document.URL, image: document.getElementsByClassName( 'news content' )[ 0 ].querySelector( 'img' ).getAttribute( 'src' ).replace( 'https://', 'http://' ), author: ( strGame === 'ddo' ? '*unknown*' : author ), pubDate: published, sSotW: { img: IMGsS, desc: SSdesc }, bonusDays: objBonusDays, freebie: { dates: objFreebieDates, code: strFreebieCode, item: { name: strFreebieName, link: strFreebieLink }, quantity: intFreebieQuantity, week: strFreebieWeek }, sales: { name: strSaleName, dates: objSaleDates, percent: strSalePercent, value: arrSalesVal } } console.log( '%o', objSpecials ); console.info( '%s', JSON.stringify( objSpecials ) ); } )();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址