yoharnu / Goodreads Giveaway Script

// ==UserScript==
// @name         Goodreads Giveaway Script
// @namespace    yoharnuGoodreads
// @version      0.3
// @description  Automatically do every step of giveaway entry
// @author       yoharnu
// @match http*://www.goodreads.com/giveaway*
// @match http*://www.goodreads.com/book/show/*
// @downloadurl https://openuserjs.org/install/yoharnu/Goodreads_Giveaway_Script.user.js
// @copyright 2019, yoharnu (https://openuserjs.org/users/yoharnu)
// @license MIT
// @grant        none
// ==/UserScript==

(function () {
  'use strict';
  if (window.location.href.indexOf("goodreads.com/giveaway/show/") > -1) {
    var bookURL = document.getElementsByClassName('bookTitle')[0].getAttribute('href');
    window.location.href = bookURL;
  }
  else if (window.location.href.indexOf("goodreads.com/book/show/") > -1) {
    if (document.referrer.indexOf("goodreads.com/giveaway/show/") > -1) {
      var forms = document.getElementsByTagName('form');
      for (var i = 0; i < forms.length; i++) {
        var action = forms[i].getAttribute('action');
        console.log(action);
        if (action.indexOf("/review/destroy/") > -1) {
          forms[i].submit();
          break;
        }
      }
    }
  }
  else if (window.location.href.indexOf("/giveaway/enter_choose_address/") > -1) {
    let addresses = document.getElementsByClassName('addressSelect');
    if (addresses.length === 1) {
      let addressBlock = addresses[0];
      let link = addressBlock.getElementsByTagName('a')[0];
      link.click();
    }
  }
  else if (window.location.pathname === '/giveaway') {
    if (!window.location.search.includes('sort=ending_soon')) {
      window.location.search = '?sort=ending_soon';
    }

    let BookList = document.getElementsByClassName('BookListItem');

    for (let BookItem of BookList) {
      let entries = BookItem.getElementsByClassName('GiveawayMetadata__entryDataMobile--subdued')[0].innerHTML.split('<!--')[0].replaceAll(',', '');
      console.debug(entries + ' entries');
      if (entries.includes('k')) {
        entries = entries.split('k')[0];
        entries = parseFloat(entries) * 1000;
      }
      else {
        entries = parseInt(entries);
      }
      console.debug(entries + ' entries');

      let copies = BookItem.getElementsByClassName('GiveawayDetails__numCopiesAvailable')[0].children[0].innerHTML.split('<!--')[0];
      console.debug(copies + ' copies');

      let odds = copies / (entries + 1.0) * 100;
      console.debug('odds: ' + odds.toFixed(2) + '%');
      setTimeout(function () {
        copies = BookItem.getElementsByClassName('GiveawayDetails__numCopiesAvailable')[0].children[0];
        copies.innerHTML = copies.innerHTML + ' (' + odds.toFixed(2) + '%)';

        let description = BookItem.getElementsByClassName('Formatted')[0].innerHTML;
        if (description.toLowerCase().match(/\barc\b/) || description.toLowerCase().match(/\badvanced?\sreader\'?s?/)) {
          let entriesParent = BookItem.getElementsByClassName('GiveawayMetadata__entryData')[0].getElementsByTagName('ul')[0];
          let arcNode = document.createElement('li');
          arcNode.classList.add('GiveawayMetadata__entryData--subdued');
          arcNode.style.color = 'red';
          arcNode.style.fontWeight = 'bold';
          arcNode.innerHTML = 'ARC';
          entriesParent.appendChild(arcNode);
        }
      }, 2000);
    }

    const targetNode = document.getElementsByClassName('BookList')[0];
    const config = {
      attributes: true,
      childList: true,
      subtree: true
    };
    const callback = function (mutationsList, observer) {
      // Use traditional 'for loops' for IE 11
      for (const mutation of mutationsList) {
        if (mutation.type === 'childList') {
          // console.log('A child node has been added or removed.');
          for (const node of mutation.addedNodes) {
            if (node.classList) {
              if (node.classList.contains('BookListItem')) {
                let BookItem = node;
                let entries = BookItem.getElementsByClassName('GiveawayMetadata__entryDataMobile--subdued')[0].innerHTML.split('<!--')[0].replaceAll(',', '');
                console.debug(entries + ' entries');
                if (entries.includes('k')) {
                  entries = entries.split('k')[0];
                  entries = parseFloat(entries) * 1000;
                }
                else {
                  entries = parseInt(entries);
                }
                console.debug(entries + ' entries');

                let copies = BookItem.getElementsByClassName('GiveawayDetails__numCopiesAvailable')[0].children[0].innerHTML.split('&nbsp;')[0];
                console.debug(copies + ' copies');

                let odds = copies / (entries + 1.0) * 100;
                console.debug('odds: ' + odds.toFixed(2) + '%');
                copies = BookItem.getElementsByClassName('GiveawayDetails__numCopiesAvailable')[0].children[0];
                copies.innerHTML = copies.innerHTML + ' (' + odds.toFixed(2) + '%)';

                let description = BookItem.getElementsByClassName('Formatted')[0].innerHTML;
                if (description.toLowerCase().match(/\barc\b/) || description.toLowerCase().match(/\badvanced?\sreader\'?s?/)) {
                  let entriesParent = BookItem.getElementsByClassName('GiveawayMetadata__entryData')[0].getElementsByTagName('ul')[0];
                  let arcNode = document.createElement('li');
                  arcNode.classList.add('GiveawayMetadata__entryData--subdued');
                  arcNode.style.color = 'red';
                  arcNode.style.fontWeight = 'bold';
                  arcNode.innerHTML = 'ARC';
                  entriesParent.appendChild(arcNode);
                }
              }
            }
          }
        }
        else if (mutation.type === 'attributes') {
          console.log('The ' + mutation.attributeName + ' attribute was modified.');
        }
      }
    };
    const observer = new MutationObserver(callback);
    observer.observe(targetNode, config);
  }
  else {
    var termsCheckbox = document.getElementById('termsCheckBox');
    termsCheckbox.checked = true;
    document.entry_form.submit();
  }
})();