Twitch Drop bot

Twitch Auto Claim, Drop, change channel and auto track progress

2023-05-17 या दिनांकाला. सर्वात नवीन आवृत्ती पाहा.

// ==UserScript==
// @name         Twitch Drop bot
// @namespace    http://tampermonkey.net/
// @version      1.1
// @description  Twitch Auto Claim, Drop, change channel and auto track progress
// @author       gig4d3v
// @match        https://www.twitch.tv/*
// @icon         https://www.google.com/s2/favicons?domain=mozilla.org
// @grant        none
// @license      GPLv3
// ==/UserScript==

const claimBonusButton = '[aria-label="Claim Bonus"]';
const twitchLogo = '[aria-label="Twitch Home"]';
const dropNumber = 1;

var allStreamersNickames = [
  "GENERAL",
  "TWITCHRIVALS",
  "BUDDHA",
  "MENDO",
  "COCONUTB",
  "EROBB221",
  "DHALUCARD",
  "WILLJUM",
  "HJUNE",
  "DISGUISEDTOAST",
  "JLTOMY",
  "KROLAY",
  "PANPOTS",
  "ISVOLCANO",
  "POW3R",
  "KESI__",
  "WELYN",
  "ZCHUM",
];

var timeCheck = 1;
var tempCurrentStreamer = "";
var tempStreamerList = [];

const config = { attributes: true, childList: true, subtree: true };

const notification = document.createElement("div");
notification.style.cssText =
  "position:fixed;top:10px;right:10px;background:#f2f2f2;padding:10px;border:1px solid #ccc;border-radius:4px;z-index:9999;font-family:Arial;font-size:14px;display:flex;justify-content:center;align-items:center;color:black;";

const notificationText = document.createElement("p");
notificationText.innerText = "This is a notification!";
notificationText.style.cssText = "margin:0; color:black;";

const closeNotificationButton = document.createElement("button");
closeNotificationButton.innerText = "X";
closeNotificationButton.style.cssText =
  "width:30px;text-align:center;margin-left:10px;border:none;background:#ccc;padding:5px;border-radius:4px;cursor:pointer;";
closeNotificationButton.addEventListener("click", function () {
  notification.remove();
});
closeNotificationButton.addEventListener("mouseover", function () {
  closeNotificationButton.style.background = "#aaa";
});
closeNotificationButton.addEventListener("mouseout", function () {
  closeNotificationButton.style.background = "#ccc";
});
notification.appendChild(notificationText);
notification.appendChild(closeNotificationButton);

var nextStreamerButton = document.createElement("button");
nextStreamerButton.innerText = "Next Streamer";
nextStreamerButton.style.cssText =
  "position:fixed;bottom:10px;left:10px;border:none;background:#9147ff;padding:5px;border-radius:4px;cursor:pointer;color:#efeff1;height:57px;font-family:Roobert,Inter,Helvetica Neue,Helvetica,Arial,sans-serif;font-weight:600";
nextStreamerButton.addEventListener("click", function () {
  selectNextStreamer();
  var currentStreamer = JSON.parse(localStorage.getItem("currentStreamer"));
  awokeNotification("Switched to " + currentStreamer, 3000);
  setTimeout(function () {
    notification.remove();
  }, 3000);
});

var changeStreamersButton = document.createElement("button");
changeStreamersButton.innerText = "Change Streamers";
changeStreamersButton.style.cssText =
  "position:fixed;bottom:10px;left:120px;border:none;background:#9147ff;padding:5px;border-radius:4px;cursor:pointer;color:#efeff1;height:57px;font-family:Roobert,Inter,Helvetica Neue,Helvetica,Arial,sans-serif;font-weight:600";
changeStreamersButton.addEventListener("click", function () {
  localStorage.setItem("streamerList", JSON.stringify([]));
  localStorage.setItem("currentStreamer", JSON.stringify(""));
  chooseStreamersNotification();
});

var statsBar = document.getElementById("statsBar");
statsBar = document.createElement("div");
statsBar.id = "statsBar";

statsBar.style.cssText =
  "display:flex;flex-direction:row;justify-content:center;align-items:center;padding: 10px 0;background:#18181B;box-shadow:0 1px 2px rgba(0,0,0,.9),0 0px 2px rgba(0,0,0,.9);";

function getClaimButton() {
  var xpathExpression = "//div[text()='Claim Now']";
  var result = document.evaluate(
    xpathExpression,
    document,
    null,
    XPathResult.ANY_TYPE,
    null
  );
  var divElement = result.iterateNext();
  var grandparentElement = null;

  if (divElement) {
    var parentElement = divElement.parentNode;
    grandparentElement = parentElement.parentNode;
  }

  return grandparentElement;
}

function isOnline() {
  var xpathExpression = "//p[text()='Offline']";
  var result = document.evaluate(
    xpathExpression,
    document,
    null,
    XPathResult.FIRST_ORDERED_NODE_TYPE,
    null
  );
  var element = result.singleNodeValue;

  if (!element) return true;
  return false;
}

function selectNextStreamer() {
  var streamerList = JSON.parse(localStorage.getItem("streamerList"));
  var currentStreamer = JSON.parse(localStorage.getItem("currentStreamer"));
  var index;
  for (var i = 0; i < streamerList.length; i++) {
    if (streamerList[i][0] == currentStreamer) {
      index = i;
      break;
    }
  }

  var nextStreamer = streamerList[index + 1];
  if (nextStreamer == undefined) {
    nextStreamer = streamerList[0];
  }
  awokeNotification("Switched to " + nextStreamer[0], 3000);
  currentStreamer = nextStreamer[0];
  localStorage.setItem("currentStreamer", JSON.stringify(currentStreamer));
  if (JSON.parse(localStorage.getItem("streamerList")).length === 0) {
    chooseStreamersNotification();
  }
}

function updateStreamerList() {
  var attributeValue =
    "DropsCampaignInProgressDescription-two-channels-hint-text";
  var attributeValue2 =
    "DropsCampaignInProgressDescription-multi-channels-hint-text";

  [attributeValue, attributeValue2].forEach(function (attributeValue) {
    var elements = document.querySelectorAll(
      "[data-test-selector='" + attributeValue + "']"
    );
    var rivalsGeneral = document.querySelector("div.inventory-campaign-info");
    var flag = false;
    if (rivalsGeneral !== null && flag === false) {
      flag = true;
      elements = Array.prototype.slice.call(elements);
      elements.push(rivalsGeneral);
    }

    elements.forEach(function (element) {
      var streamerName = element.innerText;
      if (element == rivalsGeneral) streamerName = "/general";
      var allItems = 0;
      var obtaind = 0;
      var pElement = element;
      while (pElement.querySelector("div.inventory-campaign-info") === null) {
        pElement = pElement.parentNode;
      }
      pElement = pElement.children[1].children[0];
      var progress = null;
      var isLocked = true;
      for (var i = 0; i < pElement.children.length; i++) {
        var child = pElement.children[i];
        // if child has any children
        if (child.children.length > 0) {
          for (var j = 0; j < child.children.length; j++) {
            if (j === 0) {
              var img =
                child.children[j].children[0].children[0].children[0]
                  .children[0].children[0];
              // get opacity of image
              var opacity = window
                .getComputedStyle(img)
                .getPropertyValue("opacity");
              isLocked = opacity === "0.2";
              isLocked =
                child.children[j].children[0].children[0].children[0]
                  .children[1] !== undefined;
            } else if (j === 1) {
              if (child.children[j].querySelector("[aria-valuenow]") !== null) {
                progress = child.children[j]
                  .querySelector("[aria-valuenow]")
                  .getAttribute("aria-valuenow");
              } else {
                progress = null;
              }
            }
          }

          if (isLocked === false && progress === "0") {
            obtaind++;
            allItems++;
          } else if (isLocked || progress !== "0") {
            allItems++;
          }
        }
      }

      var streamerList = JSON.parse(localStorage.getItem("streamerList"));

      streamerList.forEach(function (streamer) {
        console.log(streamer);
        if (streamer[0] === streamerName.split("/")[1]) {
          streamer[1] = obtaind + "/" + allItems;
        }
        if (streamer[0] === "general" && streamerName === "/general") {
          streamer[1] = 5 + "/" + 5;
        }
      });

      localStorage.setItem("streamerList", JSON.stringify(streamerList));
    });
  });
}

function setCurrentStreamerOffline() {
  var currentStreamer = JSON.parse(localStorage.getItem("currentStreamer"));
  var streamerList = JSON.parse(localStorage.getItem("streamerList"));
  streamerList.forEach(function (streamer) {
    if (streamer[0] === currentStreamer) {
      streamer[2] = "offline";
    }
  });
  localStorage.setItem("streamerList", JSON.stringify(streamerList));
}
function setCurrentStreamerOnline() {
  var currentStreamer = JSON.parse(localStorage.getItem("currentStreamer"));
  var streamerList = JSON.parse(localStorage.getItem("streamerList"));
  streamerList.forEach(function (streamer) {
    if (streamer[0] === currentStreamer) {
      streamer[2] = "online";
    }
  });
  localStorage.setItem("streamerList", JSON.stringify(streamerList));
}

function awokeNotification(data, time) {
  console.log("awokeNotification: ", data);
  if (data == "[object HTMLDivElement]") {
    notificationText.parentNode.appendChild(data);
  } else {
    notificationText.innerText = data;
  }

  document.body.appendChild(notification);
  setTimeout(function () {
    notification.remove();
  }, time);
}
function selectStreamer(streamerName) {
  localStorage.setItem("currentStreamer", JSON.stringify(streamerName));
}

function chooseStreamersNotification() {
  var chooseStreamersNotificationContainer = document.createElement("div");
  chooseStreamersNotificationContainer.style.cssText =
    "position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.5);display:flex;justify-content:center;align-items:center;z-index:9999999999; flex-direction:column; color:white; font-size:20px; font-weight:bold; padding:20px; box-sizing:border-box;";
  var innerContainer = document.createElement("div");
  innerContainer.style.cssText =
    "background-color:#18181B; padding:20px; box-sizing:border-box; border-radius:10px; display:flex; flex-direction:column; justify-content:center; align-items:left; width: 400px;";

  allStreamersNickames.forEach((element) => {
    element = element.toLowerCase();
    var checkbox = document.createElement("input");
    checkbox.type = "checkbox";
    checkbox.name = "name";
    checkbox.value = "value";
    checkbox.id = element;
    checkbox.checked = false;
    checkbox.style.cssText = "margin:0 10px";
    var label = document.createElement("label");
    label.htmlFor = element;
    label.appendChild(document.createTextNode(element));
    label.style.cssText = "margin:0 10px";
    var group = document.createElement("div");
    group.style.cssText = "display:flex;";
    group.appendChild(checkbox);
    group.appendChild(label);
    innerContainer.appendChild(group);
  });
  chooseStreamersNotificationContainer.appendChild(innerContainer);

  var readyButton = document.createElement("button");
  readyButton.innerText = "Ready";
  readyButton.id = "readyButton";
  readyButton.style.cssText =
    "margin:0 10px; padding:10px; background-color:purple; color:white; border:none; border-radius:5px;margin-top:40px;width: 400px; text-align:center;";
  chooseStreamersNotificationContainer.appendChild(readyButton);
  awokeNotification(chooseStreamersNotificationContainer, 99999);
  document.querySelector("#readyButton").addEventListener("click", function () {
    var streamerList = [];
    var checkboxes = chooseStreamersNotificationContainer.querySelectorAll(
      "input[type=checkbox]:checked"
    );
    for (var i = 0; i < checkboxes.length; i++) {
      streamerList.push([checkboxes[i].id, "not started yet", "on/off-line"]);
    }
    chooseStreamersNotificationContainer.remove();
    localStorage.setItem("streamerList", JSON.stringify(streamerList));
  });
}

function refreshStatBar() {
  var streamerList = JSON.parse(localStorage.getItem("streamerList"));
  var currentStreamer = JSON.parse(localStorage.getItem("currentStreamer"));
  statsBar.innerHTML = "";
  streamerList.forEach(function (streamer) {
    var streamerNameOrginal = streamer[0];
    var streamerName = streamer[0];
    var streamerDrops = streamer[1];
    var streamerStatus = streamer[2];
    var streamerElement = document.createElement("a");
    streamerElement.href = "https://www.twitch.tv/" + streamerNameOrginal;
    streamerElement.style.cssText =
      "display:flex;flex-direction:column;justify-content:center;align-items:center;margin:0 10px;text-decoration:none;color:#d1d1d1;";
    var streamerNameElement = document.createElement("div");
    streamerNameElement.style.cssText =
      "font-weight:bold;" +
      (streamer[0] == currentStreamer ? "color:purple;" : "color:#d1d1d1;");
    streamerNameElement.innerText = streamerName;
    var streamerDropsElement = document.createElement("div");
    streamerDropsElement.innerText = streamerDrops;
    var streamerStatusElement = document.createElement("div");
    streamerStatusElement.innerText = streamerStatus;
    streamerElement.appendChild(streamerNameElement);
    streamerElement.appendChild(streamerDropsElement);
    streamerElement.appendChild(streamerStatusElement);
    streamerElement.addEventListener("mouseover", function () {
      closeNotificationButton.style.background = "#a9a9a9";
    });
    streamerElement.addEventListener("mouseout", function () {
      closeNotificationButton.style.background = "transparent";
    });
    streamerElement.addEventListener("click", function () {
      selectStreamer(streamerName);
      awokeNotification("Streamer changed to " + streamerName, 2000);
      refreshStatBar();
    });

    statsBar.appendChild(streamerElement);
  });
}

if (window.location.pathname === "/drops/inventory") {
  let checkChanges = (mutationsList) => {
    window.addEventListener("storage", (e) => {
      if (e.key === "streamerList" || e.key === "currentStreamer") {
        console.log("refreshing stats bar from inventory page");
        refreshStatBar();
      }
    });

    function initializeLocalStorage() {
      var currentStreamer = localStorage.getItem("currentStreamer");
      var streamerList = localStorage.getItem("streamerList");

      if (!currentStreamer || !streamerList) {
        localStorage.setItem(
          "currentStreamer",
          JSON.stringify(tempCurrentStreamer)
        );
        localStorage.setItem("streamerList", JSON.stringify(tempStreamerList));
      }
    }

    initializeLocalStorage();

    for (const mutation of mutationsList) {
      var currentStreamer = JSON.parse(localStorage.getItem("currentStreamer"));
      var claimDropButton = getClaimButton();
      if (claimDropButton !== null) {
        var streamerDropsLeft = 0;
        claimDropButton.click();
        awokeNotification(
          `Congratulations, you have received a gift from ${currentStreamer} (${streamerDropsLeft} left) !`,
          3000
        );
        return true;
      }
      updateStreamerList();
      var streamerList = JSON.parse(localStorage.getItem("streamerList"));
      streamerList.forEach(function (streamer) {
        if (streamer[0] === currentStreamer) {
          if (streamer[1] === "0/0") {
            selectNextStreamer();
          }
        }
      });
    }
  };
  let verifyChanges = new MutationObserver(checkChanges);
  verifyChanges.observe(document.body, config);
  setInterval(function () {
    window.location.reload();
  }, timeCheck * 60000);
} else {
  window.addEventListener("storage", (e) => {
    if (e.key === "streamerList" || e.key === "currentStreamer") {
      console.log("refreshing stat bar from stream");
      refreshStatBar();
    }
  });
  function initializeLocalStorage() {
    var currentStreamer = localStorage.getItem("currentStreamer");
    var streamerList = localStorage.getItem("streamerList");

    if (!currentStreamer || !streamerList) {
      localStorage.setItem(
        "currentStreamer",
        JSON.stringify(tempCurrentStreamer)
      );
      localStorage.setItem("streamerList", JSON.stringify(tempStreamerList));
    }
  }
  initializeLocalStorage();
  document.body.appendChild(nextStreamerButton);
  document.body.appendChild(statsBar);
  document.body.appendChild(changeStreamersButton);

  if (
    JSON.parse(localStorage.getItem("streamerList")).length === 0 &&
    JSON.parse(localStorage.getItem("currentStreamer")).length === 0
  ) {
    chooseStreamersNotification();
  }
  setInterval(function () {
    var currentStreamer = JSON.parse(localStorage.getItem("currentStreamer"));
    var streamerList = JSON.parse(localStorage.getItem("streamerList"));
    if (window.location.pathname === "/" + "general") {
      console.log("redirecting to " + currentStreamer);
      var randomStreamer =
        allStreamersNickames[
          Math.floor(Math.random() * allStreamersNickames.length)
        ].toLowerCase();
      selectStreamer(randomStreamer);
      localStorage.setItem("currentStreamer", JSON.stringify(randomStreamer));
      window.location.pathname = "/" + randomStreamer;
    }
    if (window.location.pathname != "/" + currentStreamer) {
      console.log("redirecting to " + currentStreamer);
      window.location.pathname = "/" + currentStreamer;
    }

    streamerList.forEach((streamer) => {
      if (streamer[1].split("/")[0] == streamer[1].split("/")[1]) {
        console.log("streamer " + streamer[0] + " has completed all drops");
        awokeNotification(
          "Streamer " + streamer[0] + " has completed all drops",
          3000
        );
        selectNextStreamer();
        localStorage.setItem(
          "currentStreamer",
          JSON.stringify(currentStreamer)
        );
      }
    });

    var onlineStatus = isOnline() ? "online" : "offline";
    if (onlineStatus === "offline") {
      setCurrentStreamerOffline();
      selectNextStreamer();
      currentStreamer = JSON.parse(localStorage.getItem("currentStreamer"));
      console.log("streamer is offline redirecting to" + currentStreamer);
    } else {
      setCurrentStreamerOnline();
    }
    refreshStatBar();
    if (document.querySelector(claimBonusButton) !== null) {
      document.querySelector(claimBonusButton).click();
    }
  }, 1000);
}