News for hackers. Stuff that matters.
Re:Show HN: I wrote a bookmarklet to know any Twitter poll r... by vicke4 on Monday August 31, 2020 @01:19PM (#24333639)
More readable version of the code:

( function () {

    // Exiting if the webpage is not Twitter or a valid tweet
    if (window.location.origin !== 'https://twitter.com' || window.location.pathname.split('/').length !== 4) return alert('This is not a valid Twitter poll!');

    alert("Please wait this can take up to 30 seconds. Select OK or close to get started. If this is a valid poll, you will get the result when it is ready...:)");

    // This string will hold our poll result
    let result = '';
    // This boolean denotes if our job is done and if true, doesn't execute the addEventListener anymore.
    let processDone = false;
    let oldXHROpen = window.XMLHttpRequest.prototype.open;
    const startTime = Date.now();

    window.XMLHttpRequest.prototype.open = function () {
      if (processDone) {
        return oldXHROpen.apply(this, arguments);
      }

      // onLoad event handler to intercept the Twitter API response to read the poll results.
      function listenEvent() {
        try {
          if (this.responseURL.includes('poll')) {
            // JSON from the Twitter API response
            // On a poll page every 30 seconds, Twitter hits the API to retrieve the latest poll results
            const pollResultJson = JSON.parse(this.responseText);
            const pollBindingValues = pollResultJson.card.binding_values;
            const resultObj = Object.keys(pollBindingValues).reduce(function (accum, key) {
              if (key.includes('_label')) {
                const label = pollBindingValues[key].string_value;
                const choiceNumber = key.replace(/\D/g, '');
                const voteCount = pollBindingValues[`choice${choiceNumber}_count`].string_value;

                accum.choiceVoteCountMap[label] = +voteCount;
                accum.noOfVotes += +voteCount;
              }

              return accum;
            }, { noOfVotes: 0, choiceVoteCountMap: {} });

            const { choiceVoteCountMap, noOfVotes } = resultObj;
            Object.keys(choiceVoteCountMap).forEach(function (label) {
              result += `${label}: ${((choiceVoteCountMap[label] / noOfVotes) * 100).toFixed(2)}%\n`
            })
          }
        } catch (e) {
          processDone = true;
          // For error reporting. Incase if the bookmarklet fails to work in future, people will be able to report...:)
          if (window.confirm("Something went wrong. Could you please report the issue?")) {
            window.open("https://www.syncwithtech.org/twitter-poll-result-wo-voting/", "_blank");
          }

          this.removeEventListener('load', listenEvent);
        }
      }

      this.addEventListener('load', listenEvent);

      // If result holds proper string, we need to stop listening to the event
      if (result) {
        processDone = true;
        alert(result);

        this.removeEventListener('load', listenEvent);
      }

      // If the page is a proper tweet and doesn't have a poll, we must stop listening to the load event. It happens after 40 seconds.
      if (Date.now() - startTime > 40000 && !processDone) {
        processDone = true;

        // To get feedback if it's actually a poll and the script fails to detect it
        if (window.confirm("Seems like it is not a valid Twitter poll. Press OK to report the issue if it is a valid poll and the bookmarklet failed to detect it.")) {
          window.open("https://www.syncwithtech.org/twitter-poll-result-wo-voting/", "_blank");
        }

        this.removeEventListener('load', listenEvent);
      }

      return oldXHROpen.apply(this, arguments);
    }
  }
)();

There are no comments on this comment yet.