Skip to content

Commit

Permalink
v0.2.1 Long-Lived Branch (#20)
Browse files Browse the repository at this point in the history
* update manifest versions

* store block queue in local storage

* move class into shared and init in browser scripts

* fix zero follower accounts not being blocker with 1mskip option

* add block counter to popup menu

* remove storage polling in favor of onChanged.addListener. also add queued value
  • Loading branch information
kheina authored Apr 29, 2023
1 parent 0d66294 commit 40752b4
Show file tree
Hide file tree
Showing 10 changed files with 185 additions and 23 deletions.
17 changes: 16 additions & 1 deletion chrome/options.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DefaultOptions } from '../shared.js';
import { DefaultOptions, commafy } from '../shared.js';

// restore state from storage
document.addEventListener("DOMContentLoaded", () => {
Expand All @@ -12,6 +12,21 @@ document.addEventListener("DOMContentLoaded", () => {
});
});

// set the block value immediately
chrome.storage.local.get({ BlockCounter: 0, BlockQueue: 0 }).then(items => {
document.getElementById("blocked-users-count").innerText = commafy(items.BlockCounter);
document.getElementById("blocked-user-queue-length").innerText = commafy(items.BlockQueue.length);
});
chrome.storage.local.onChanged.addListener(items => {
if (items.hasOwnProperty('BlockCounter')) {
document.getElementById("blocked-users-count").innerText = commafy(items.BlockCounter.newValue);
}
if (items.hasOwnProperty('BlockQueue')) {
document.getElementById("blocked-user-queue-length").innerText = commafy(items.BlockQueue.newValue.length);
}
// if we want to add other values, add them here
});

document.getElementById("block-following").addEventListener("input", () => {
chrome.storage.sync.set({
blockFollowing: document.getElementById("block-following").checked,
Expand Down
1 change: 1 addition & 0 deletions chrome/popup.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
</head>
<body>
<h2><img src="../assets/icon.png" alt="🅱️">lue Blocker</h2>
<p class="blocked-users-count">blocked <span id="blocked-users-count"></span> users so far! (<span id="blocked-user-queue-length"></span> queued)</p>
<div class="option">
<input type="checkbox" id="block-following">
<label ref="label" for="block-following" >
Expand Down
5 changes: 4 additions & 1 deletion chrome/script.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { ClearCache, DefaultOptions, SetOptions, HandleInstructionsResponse, HandleHomeTimeline } from '../shared.js';
import { ClearCache, DefaultOptions, BlockCounter, BlockQueue, SetBlockCounter, SetBlockQueue, SetOptions, HandleInstructionsResponse, HandleHomeTimeline } from '../shared.js';
SetBlockQueue(new BlockQueue(chrome.storage.local));
SetBlockCounter(new BlockCounter(chrome.storage.local));


document.addEventListener("blue-blocker-event", function (e) {
ClearCache();
Expand Down
8 changes: 5 additions & 3 deletions firefox-manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"manifest_version": 2,
"name": "Blue Blocker",
"version": "0.2",
"version": "0.2.1",
"description": "Blocks all Twitter Blue verified users on twitter.com",
"icons": {
"128": "assets/icon-128.png"
Expand All @@ -10,7 +10,7 @@
"firefox/script.js",
"shared.js",
"inject.js"
],
],
"browser_action": {
"browser_style": true,
"default_icon": {
Expand All @@ -28,7 +28,9 @@
"*://*.twitter.com/*",
"*://twitter.com/*"
],
"js": ["firefox/main.js"]
"js": [
"firefox/main.js"
]
}
],
"browser_specific_settings": {
Expand Down
17 changes: 16 additions & 1 deletion firefox/options.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DefaultOptions } from '../shared.js';
import { DefaultOptions, commafy } from '../shared.js';

// restore state from storage
document.addEventListener("DOMContentLoaded", () => {
Expand All @@ -12,6 +12,21 @@ document.addEventListener("DOMContentLoaded", () => {
});
});

// set the block value immediately
browser.storage.local.get({ BlockCounter: 0, BlockQueue: 0 }).then(items => {
document.getElementById("blocked-users-count").innerText = commafy(items.BlockCounter);
document.getElementById("blocked-user-queue-length").innerText = commafy(items.BlockQueue.length);
});
browser.storage.local.onChanged.addListener(items => {
if (items.hasOwnProperty('BlockCounter')) {
document.getElementById("blocked-users-count").innerText = commafy(items.BlockCounter.newValue);
}
if (items.hasOwnProperty('BlockQueue')) {
document.getElementById("blocked-user-queue-length").innerText = commafy(items.BlockQueue.newValue.length);
}
// if we want to add other values, add them here
});

document.getElementById("block-following").addEventListener("input", () => {
browser.storage.sync.set({
blockFollowing: document.getElementById("block-following").checked,
Expand Down
1 change: 1 addition & 0 deletions firefox/popup.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
</head>
<body>
<h2><img src="../assets/icon.png" alt="🅱️">lue Blocker</h2>
<p class="blocked-users-count">blocked <span id="blocked-users-count"></span> users so far! (<span id="blocked-user-queue-length"></span> queued)</p>
<div class="option">
<input type="checkbox" id="block-following">
<label ref="label" for="block-following" >
Expand Down
5 changes: 4 additions & 1 deletion firefox/script.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { ClearCache, DefaultOptions, SetOptions, HandleInstructionsResponse, HandleHomeTimeline } from '../shared.js';
import { ClearCache, DefaultOptions, BlockCounter, BlockQueue, SetBlockCounter, SetBlockQueue, SetOptions, HandleInstructionsResponse, HandleHomeTimeline } from '../shared.js';
SetBlockQueue(new BlockQueue(browser.storage.local));
SetBlockCounter(new BlockCounter(browser.storage.local));


document.addEventListener("blue-blocker-event", function (e) {
ClearCache();
Expand Down
6 changes: 4 additions & 2 deletions manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"manifest_version": 3,
"name": "Blue Blocker",
"version": "0.2",
"version": "0.2.1",
"description": "Blocks all Twitter Blue verified users on twitter.com",
"icons": {
"128": "assets/icon-128.png"
Expand Down Expand Up @@ -32,7 +32,9 @@
"*://*.twitter.com/*",
"*://twitter.com/*"
],
"js": ["chrome/main.js"]
"js": [
"chrome/main.js"
]
}
]
}
136 changes: 124 additions & 12 deletions shared.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,17 @@ export const Headers = [
"x-twitter-client-language",
];

// 64bit refid
const MaxId = 0xffffffffffffffff;
const RefId = () => Math.round(Math.random() * MaxId);

export function commafy(x)
{ // from https://stackoverflow.com/a/2901298
let parts = x.toString().split('.');
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
return parts.join('.');
}

var options = { };
export function SetOptions(items) {
options = items;
Expand All @@ -80,7 +91,103 @@ const ReasonMap = {
[ReasonNftAvatar]: "NFT avatar",
};

const BlockQueue = [];
export class BlockQueue {
// queue must be defined with push and shift functions
constructor(storage) {
this.storage = storage;
this.queue = [];
this.timeout = null;
}
async sync() {
// sync simply adds the in-memory queue to the stored queue
const items = await this.storage.get({ BlockQueue: [] });
items.BlockQueue.push(...this.queue);
await this.storage.set(items);
this.queue.length = 0;
this.timeout = null;
}
async push(item) {
this.queue.push(item);
if (this.timeout) {
clearTimeout(this.timeout);
}
this.timeout = setTimeout(() => this.sync(), 100);
}
async shift() {
// shift halts any modifications to the local storage queue, removes an item, and saves it, and restarts sync
if (this.timeout) {
clearTimeout(this.timeout);
}
const items = await this.storage.get({ BlockQueue: [] });
const item = items.BlockQueue.shift();
if (item !== undefined) {
await this.storage.set(items);
}
this.timeout = setTimeout(() => this.sync(), 100);
return item;
}
}

var queue = null;
export function SetBlockQueue(q) {
queue = q;
}

export class BlockCounter {
// this class provides functionality to update and maintain a counter on badge text in an accurate way via async functions
constructor(storage) {
this.storage = storage;
this.value = 0;
this.timeout = null;

// we need to make sure the critical point is empty on launch. this has a very low chance of causing conflict between tabs, but
// prevents the possibility of a bunch of bugs caused by issues in retrieving the critical point. ideally we wouldn't have this
this.releaseCriticalPoint();
}
async getCriticalPoint() {
const key = "blockCounterCriticalPoint";
const refId = RefId();
let value = null;
do {
value = (await this.storage.get({ [key]: null }))[key];
if (!value) {
// try to access the critical point
await this.storage.set({ [key]: refId });
value = (await this.storage.get({ [key]: null }))[key];
}
else {
// sleep for a little bit to let the other tab(s) release the critical point
await new Promise(r => setTimeout(r, 50));
}
} while (value !== refId)
}
async releaseCriticalPoint() {
// this should only be called AFTER getCriticalPoint
const key = "blockCounterCriticalPoint";
await this.storage.set({ [key]: null });
}
async sync() {
await this.getCriticalPoint();
const items = await this.storage.get({ BlockCounter: 0 });
items.BlockCounter += this.value;
this.value = 0;
await this.storage.set(items);
this.releaseCriticalPoint();
}
async increment(value = 1) {
this.value += value;
if (this.timeout) {
clearTimeout(this.timeout);
}
this.timeout = setTimeout(() => this.sync(), 100);
}
}

var blockCounter = null;
export function SetBlockCounter(t) {
blockCounter = t;
}

const BlockCache = new Set();
let BlockInterval = undefined;

Expand All @@ -93,22 +200,24 @@ function QueueBlockUser(user, user_id, headers, reason) {
return;
}
BlockCache.add(user_id);
BlockQueue.push({user, user_id, headers, reason});
queue.push({user, user_id, headers, reason});
console.log(`queued ${user.legacy.name} (@${user.legacy.screen_name}) for a block due to ${ReasonMap[reason]}.`);

if (BlockInterval === undefined) {
BlockInterval = setInterval(CheckBlockQueue, 5000);
}
}

function CheckBlockQueue() {
if (BlockQueue.length === 0) {
clearInterval(BlockInterval);
BlockInterval = undefined;
return;
}
const {user, user_id, headers, reason} = BlockQueue.shift();
BlockUser(user, user_id, headers, reason);
queue.shift().then(item => {
if (item === undefined) {
clearInterval(BlockInterval);
BlockInterval = undefined;
return;
}
const {user, user_id, headers, reason} = item;
BlockUser(user, user_id, headers, reason);
});
}

function BlockUser(user, user_id, headers, reason, attempt=1) {
Expand All @@ -117,7 +226,10 @@ function BlockUser(user, user_id, headers, reason, attempt=1) {

const ajax = new XMLHttpRequest();

ajax.addEventListener('load', event => console.log(`blocked ${user.legacy.name} (@${user.legacy.screen_name}) due to ${ReasonMap[reason]}.`), false);
ajax.addEventListener('load', event => {
blockCounter.increment();
console.log(`blocked ${user.legacy.name} (@${user.legacy.screen_name}) due to ${ReasonMap[reason]}.`);
}, false);
ajax.addEventListener('error', error => {
console.error('error:', error);

Expand Down Expand Up @@ -167,7 +279,7 @@ export function BlockBlueVerified(user, headers) {
}
else if (
// verified by follower count
options.skip1Mplus && (user.legacy.followers_count > 1000000 || !user.legacy.followers_count)
options.skip1Mplus && user.legacy.followers_count > 1000000
) {
console.log(`did not block Twitter Blue verified user ${user.legacy.name} (@${user.legacy.screen_name}) because they have over a million followers and Elon is an idiot.`);
}
Expand Down
12 changes: 10 additions & 2 deletions style.css
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@ html, body {
}

body {
width: 20em;
width: 25em;
margin: 25px;
padding: 0;
}

/* popup title */
h2 {
margin-top: 0;
margin: 0;
text-align: center;
}
/* Blue Blocker logo in the popup title */
Expand Down Expand Up @@ -137,3 +137,11 @@ input:checked + label div.checkmark div, label.checked div.checkmark div {
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}

.blocked-users-count {
text-align: center;
color: var(--subtle);
font-size: 0.9em;
margin-top: 0;
margin-bottom: 2em;
}

0 comments on commit 40752b4

Please sign in to comment.