-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.user.js
87 lines (68 loc) · 3.19 KB
/
main.user.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
// ==UserScript==
// @name twitter likes ratio
// @namespace szamanr
// @description shows the ratio of likes to views for each twitter post on the page
// @include https://twitter.com/*
// @include https://x.com/*
// @grant none
// @version 0.2
// @author szamanr
// @supportURL https://github.com/szamanr/twitter-likes-ratio
// @licence MIT
// ==/UserScript==
const parseNumber = (numberString) => {
let parsed;
if (numberString.slice(-1) === "K") { parsed = parseFloat(numberString.slice(0,-1)) * 1000; }
else if (numberString.slice(-1) === "M") { parsed = parseFloat(numberString.slice(0,-1)) * 1000_000; }
else parsed = parseFloat(numberString.replace(",",""));
return parsed || 0;
}
const main = () => {
const tweets = document.querySelectorAll("[data-testid=tweet]");
tweets.forEach(tweet => {
let views = Array.from(tweet.querySelectorAll("a")).filter(link=>link.getAttribute("href").includes("analytics"))[0]?.textContent;
const likes = tweet.querySelectorAll("[data-testid=like],[data-testid=unlike]")[0];
if (!views) {
views = Array.from(tweet.querySelectorAll("span")).find(el => el.textContent.includes("Views")).textContent.replace("Views", "").trim();
}
if (!views || !likes) { console.debug(tweet); return; }
const alreadyProcessed = likes.parentElement.textContent.includes("(");
if (alreadyProcessed) return;
const viewCount = parseNumber(views);
const likeCount = parseNumber(likes?.textContent);
const ratio = (likeCount / viewCount * 100).toFixed(1) + "%";
if (likeCount === 0) return;
const likeCountElement = likes.querySelector("[data-testid=app-text-transition-container]");
const likeContainer = likeCountElement?.parentElement;
if (!likeContainer) return;
const ratioElement = document.createElement("span")
const ratioContainer = document.createElement("span");
ratioElement.textContent = ` (${ratio})`;
ratioElement.style["font-size"] = "13px";
ratioElement.style["line-height"] = "16px";
ratioElement.style["color"] = window.getComputedStyle(likeCountElement).color;
ratioContainer.appendChild(ratioElement);
ratioElement.className = likeContainer.getAttribute("class");
likeContainer.style["flex-direction"] = "row";
likeContainer.style["align-items"] = "center";
likeContainer.appendChild(ratioContainer);
});
}
// If the script loads before the UI loads, the script's UI won't be added.
// Observe the DOM for changes and re-run `main` when it changes to ensure the script loads.
const addMutationObserver = () => {
// Select the node that will be observed for mutations
const targetNode = document.getElementsByTagName('body')[0];
// Options for the observer (which mutations to observe)
const config = { childList: true, subtree: true };
// Callback function to execute when mutations are observed
const callback = (mutationList, observer) => {
main();
};
// Create an observer instance linked to the callback function
const observer = new MutationObserver(callback);
// Start observing the target node for configured mutations
observer.observe(targetNode, config);
}
main();
addMutationObserver();