Skip to content

Commit

Permalink
v0.2.6 Long-Lived Branch (#99)
Browse files Browse the repository at this point in the history
* bump manifest version

* View and Edit Queue (#100)

* just pushing what I have cause it's 4am and I have a headache

* address the suspended user issue

* single header

* make icon greyscale if paused

* add greyscale icon to makefile

* I really hate firefox v2 manifests

* some tweaks to popup

* add tweetdeck support

* fix the block on unblock copy/paste error again

* ugh

* fixed shit omg

* change scrollbar on chrome to be less hideous and change popup wording in menu
  • Loading branch information
kheina authored May 20, 2023
1 parent 3275407 commit d961ce6
Show file tree
Hide file tree
Showing 21 changed files with 626 additions and 170 deletions.
Binary file added assets/icon-128-greyscale.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ export const DefaultOptions = {
skipVerified: true,
skipAffiliated: true,
skip1Mplus: true,
skipFollowerCount: 1e6,
blockNftAvatars: false,
blockInterval: 15,
popupTimer: 30,

// this isn't set, but is used
// TODO: when migrating to firefox manifest v3, check to see if sets can be stored yet
Expand All @@ -32,6 +34,12 @@ export const Headers = [
"x-twitter-active-user",
"x-twitter-auth-type",
"x-twitter-client-language",
"sec-ch-ua",
"sec-ch-ua-mobile",
"sec-ch-ua-platform",
"sec-fetch-dest",
"sec-fetch-mode",
"sec-fetch-site",
];
export const ReasonBlueVerified = 0;
export const ReasonNftAvatar = 1;
Expand Down
4 changes: 3 additions & 1 deletion 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.5",
"version": "0.2.6",
"description": "Blocks all Twitter Blue verified users on twitter.com",
"icons": {
"128": "assets/icon-128.png"
Expand All @@ -25,6 +25,8 @@
"default_popup": "popup/index.html"
},
"permissions": [
"*://*.twitter.com/*",
"*://twitter.com/*",
"storage"
],
"content_scripts": [
Expand Down
14 changes: 12 additions & 2 deletions injected/inject.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
(function(xhr) {
const RequestRegex = /^https:\/\/(?:\w+\.)?twitter.com\/[\w\/\.\-\_\=]+\/(HomeLatestTimeline|HomeTimeline|UserTweets|timeline\/home\.json|TweetDetail|search\/typeahead\.json|search\/adaptive\.json)(?:$|\?)/;
const RequestRegex = /^https?:\/\/(?:\w+\.)?twitter.com\/[\w\/\.\-\_\=]+\/(HomeLatestTimeline|HomeTimeline|UserTweets|timeline\/home\.json|TweetDetail|search\/typeahead\.json|search\/adaptive\.json)(?:$|\?)/;

let XHR = XMLHttpRequest.prototype;
let open = XHR.open;
Expand All @@ -21,7 +21,17 @@
// determine if request is a timeline/tweet-returning request
const parsedUrl = RequestRegex.exec(this._url);
if(this._url && parsedUrl) {
document.dispatchEvent(new CustomEvent("blue-blocker-event", { detail: { url : this._url, parsedUrl, body: this.response, request: { headers: this._requestHeaders } } }));
document.dispatchEvent(new CustomEvent("blue-blocker-event", {
detail: {
parsedUrl,
url : this._url,
body: this.response,
request: {
headers: this._requestHeaders,
},
status: this.status,
},
}));
}
});
return send.apply(this, arguments);
Expand Down
4 changes: 4 additions & 0 deletions makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ firefox:
mv manifest.json chrome-manifest.json
mv firefox-manifest.json manifest.json
zip "blue-blocker-firefox-${VERSION}.zip" \
assets/icon-128-greyscale.png \
assets/icon-128.png \
assets/icon.png \
assets/error.png \
injected/* \
models/* \
parsers/* \
popup/* \
pages/* \
manifest.json \
LICENSE \
readme.md \
Expand All @@ -30,13 +32,15 @@ chrome:
# rm "blue-blocker-chrome-${VERSION}.zip"
# endif
zip "blue-blocker-chrome-${VERSION}.zip" \
assets/icon-128-greyscale.png \
assets/icon-128.png \
assets/icon.png \
assets/error.png \
injected/* \
models/* \
parsers/* \
popup/* \
pages/* \
manifest.json \
LICENSE \
readme.md \
Expand Down
2 changes: 1 addition & 1 deletion 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.5",
"version": "0.2.6",
"description": "Blocks all Twitter Blue verified users on twitter.com",
"icons": {
"128": "assets/icon-128.png"
Expand Down
2 changes: 1 addition & 1 deletion models/block_counter.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export class BlockCounter {
// try to access the critical point
await this.storage.set({ [criticalPointKey]: { refId: this._refId, time: (new Date()).valueOf() + interval * 1.5 } });
await new Promise(r => setTimeout(r, 10)); // wait a second to make sure any other sets have resolved
cpRefId = (await this.storage.get({ [criticalPointKey]: null }))[criticalPointKey].refId;
cpRefId = (await this.storage.get({ [criticalPointKey]: null }))[criticalPointKey]?.refId;
}
else {
// sleep for a little bit to let the other tab(s) release the critical point
Expand Down
2 changes: 1 addition & 1 deletion models/block_queue.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export class BlockQueue {
// try to access the critical point
await this.storage.set({ [criticalPointKey]: { refId: this._refId, time: (new Date()).valueOf() + interval * 1.5 } });
await new Promise(r => setTimeout(r, 10)); // wait a second to make sure any other sets have resolved
cpRefId = (await this.storage.get({ [criticalPointKey]: null }))[criticalPointKey].refId;
cpRefId = (await this.storage.get({ [criticalPointKey]: null }))[criticalPointKey]?.refId;
}
else {
// sleep for a little bit to let the other tab(s) release the critical point
Expand Down
2 changes: 1 addition & 1 deletion models/queue_consumer.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export class QueueConsumer {
// try to access the critical point
await this.storage.set({ [criticalPointKey]: { refId: this._refId, time: (new Date()).valueOf() + this._interval * 1.5 } });
await new Promise(r => setTimeout(r, 10)); // wait a second to make sure any other sets have resolved
cpRefId = (await this.storage.get({ [criticalPointKey]: null }))[criticalPointKey].refId;
cpRefId = (await this.storage.get({ [criticalPointKey]: null }))[criticalPointKey]?.refId;
}
else {
return false;
Expand Down
22 changes: 22 additions & 0 deletions pages/queue.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>Blue Blocker Queue</title>
<link href="./style.css" rel="stylesheet">
<link href="../assets/icon-128.png" rel="icon" type="image/png" sizes="128x128">
</head>
<!-- ♀ -->
<body>
<main>
<div class="inner">
<h1>Block Queue</h1>
<p class="subtitle">Users will not be added to the queue or blocked while this page is open</p>
<div id="block-queue">
loading...
</div>
</div>
</main>
</body>
<script src="./queue.js" type="module"></script>
</html>
81 changes: 81 additions & 0 deletions pages/queue.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { BlockQueue } from "../models/block_queue.js";
import { FormatLegacyName } from "../utilities.js";
import { api, logstr } from "../constants.js";

// Define constants that shouldn't be exported to the rest of the addon
const queue = new BlockQueue(api.storage.local);

// we need to obtain and hold on to the critical point as long as this tab is
// open so that any twitter tabs that are open are unable to block users
setInterval(async () => {
await queue.getCriticalPoint()
}, 500);

async function unqueueUser(user_id, safelist) {
// because this page holds onto the critical point, we can modify the queue
// without worrying about if it'll affect another tab
if (safelist) {
api.storage.sync.get({ unblocked: { } }).then(items => {
items.unblocked[String(user_id)] = null;
api.storage.sync.set(items);
});
}

const items = await api.storage.local.get({ BlockQueue: [] });

for (let i = 0; i < items.BlockQueue.length; i++) {
if (items.BlockQueue[i].user_id === user_id) {
items.BlockQueue.splice(i, 1);
break;
}
}

await api.storage.local.set(items);
}

// interval doesn't run immediately, so do that here
queue.getCriticalPoint()
.then(() => api.storage.local.get({ BlockQueue: [] }))
.then(items => {
const queueDiv = document.getElementById("block-queue");

if (items.BlockQueue.length === 0) {
queueDiv.textContent = "your block queue is empty";
return;
}

queueDiv.innerHTML = null;

items.BlockQueue.forEach(item => {
const { user, user_id } = item;
const div = document.createElement("div");

const p = document.createElement("p");
p.innerHTML = `${user.legacy.name} (<a href="https://twitter.com/${user.legacy.screen_name}" target="_blank">@${user.legacy.screen_name}</a>)`;
div.appendChild(p);

const remove = document.createElement("button");
remove.onclick = () => {
div.removeChild(remove);
unqueueUser(user_id, false).then(() => {
queueDiv.removeChild(div);
});
console.log(logstr, `removed ${FormatLegacyName(user)} from queue`);
};
remove.textContent = "remove";
div.appendChild(remove);

const never = document.createElement("button");
never.onclick = () => {
div.removeChild(never);
unqueueUser(user_id, true).then(() => {
queueDiv.removeChild(div);
});
console.log(logstr, `removed and safelisted ${FormatLegacyName(user)} from queue`);
};
never.textContent = "never block";
div.appendChild(never);

queueDiv.appendChild(div);
});
});
144 changes: 144 additions & 0 deletions pages/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
html {
--transition: ease;
--fadetime: 0.15s;
--interact: #1da1f2;
--bg0color: #000000;
--bg1color: #1e1f25;
--bg2color: #151416;
--bg3color: var(--bordercolor);
--blockquote: var(--bordercolor);
--textcolor: #DDD;
--bordercolor: #2D333A;
--linecolor: var(--bordercolor);
--borderhover: var(--interact);
--subtle: #EEEEEE80;
--shadowcolor: #00000080;
--activeshadowcolor: #000000B3;
--screen-cover: #00000080;
--border-size: 1px;
--border-radius: 3px;

background: var(--bg0color);
}
html * {
font-family: Bitstream Vera Sans, DejaVu Sans, Arial, Helvetica, sans-serif;
}
body {
background: var(--bg1color);
color: var(--textcolor);
}
html, body, main, h1, p {
margin: 0;
}

::-webkit-scrollbar {
width: 12px;
height:12px;
}
::-webkit-scrollbar-track {
background: var(--bg2color);
}
::-webkit-scrollbar-thumb {
background: #4D535A;
border-radius: 4px;
border: 2px solid var(--bg2color);
}
::-webkit-scrollbar-thumb:hover {
background: var(--interact);
}
::-webkit-scrollbar-corner {
background: var(--bg0color);
}

main {
color: var(--textcolor);
text-align: center;
width: 100%;
background: #1E1F25;
}
.inner {
padding: 25px;
}
.subtitle {
margin-bottom: 25px;
}


#block-queue {
bottom: 0;
display: inline-flex;
align-items: flex-start;
justify-content: center;
flex-direction: column;
}

#block-queue div {
display: flex;
justify-content: center;
align-items: center;
background: url('../assets/icon.png') var(--bg2color);
background-repeat: no-repeat;
background-size: 2.5em;
background-position-x: 1em;
background-position-y: center;
pointer-events: all;
padding: 1em 1.5em 1em 4.25em;
margin: 0 0 25px;
border: var(--border-size) solid var(--bordercolor);
border-radius: var(--border-radius);
color: var(--textcolor);
box-shadow: 0 2px 3px 1px var(--shadowcolor);
min-height: calc(2em + 4px);
}
#block-queue div:last-child {
margin-bottom: 0;
}
#block-queue div.error {
background: url('../assets/error.png') var(--bg1color);
background-repeat: no-repeat;
background-size: 2.5em;
background-position-x: 1em;
background-position-y: center;
}

#block-queue div a,
#block-queue div a:active,
#block-queue div a:focus {
color: var(--textcolor);
text-shadow: 0 2px 3px 1px var(--shadowcolor);
-webkit-transition: var(--transition) var(--fadetime);
-moz-transition: var(--transition) var(--fadetime);
-o-transition: var(--transition) var(--fadetime);
transition: var(--transition) var(--fadetime);
cursor: pointer;
}

#block-queue div a:hover {
text-shadow: 0 0 10px 3px var(--activeshadowcolor);
color: var(--interact);
}

#block-queue div button,
#block-queue div button:active,
#block-queue div button:focus {
margin-left: 1em;
font-size: 1em;
padding: 0.5em 1em;
color: var(--textcolor);
background: var(--bg1color);
box-shadow: 0 2px 3px 1px var(--shadowcolor);
border: var(--border-size) solid var(--bordercolor);
border-radius: var(--border-radius);
-webkit-transition: var(--transition) var(--fadetime);
-moz-transition: var(--transition) var(--fadetime);
-o-transition: var(--transition) var(--fadetime);
transition: var(--transition) var(--fadetime);
cursor: pointer;
}

#block-queue div button:hover {
box-shadow: 0 0 10px 3px var(--activeshadowcolor);
border-color: var(--interact);
color: var(--interact);
}

Loading

0 comments on commit d961ce6

Please sign in to comment.