Add first release

tests
Lars 2022-11-16 15:48:05 +01:00 zatwierdzone przez GitHub
rodzic adb3e3ba04
commit c99a5748cb
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
6 zmienionych plików z 230 dodań i 0 usunięć

BIN
icon/48.png 100644

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 2.0 KiB

144
inject.js 100644
Wyświetl plik

@ -0,0 +1,144 @@
// prep
var instance;
var showAlert;
var lastUrl = window.location.href;
var buttonPaths = ["div.account__header button.logo-button","div.public-account-header a.logo-button"];
// function to wait for given elements to appear - first found element gets returned
var waitForEl = function(selectors, callback) {
var match = false;
for (const selector of selectors) {
if ($(selector).length) {
match = true;
callback(selector);
}
}
if (!match) {
setTimeout(function() {
waitForEl(selectors, callback);
}, 100);
}
};
// regex match to extract @handle from any (as always, the regex was awful to build)
function extractHandle(url) {
if (!url) return null;
// regex with named match group
const match = url.match(/^(?:https?:\/\/(www\.)?.*\..*?\/)(?<handle>@\w+(?:@\w+\.\w+)?)(?:\/?.*|\z)$/);
// return the named match group
return match.groups.handle
}
// found no other way to close one kind of modal
// using .delete() will result in an an app error, .hide() does work but still blocks the interface, removing the class "-with-modals--active" also doesnt work
// so we use this function to simulate a click in the top left corner to close the modal
function click(x,y){
var ev = document.createEvent("MouseEvent");
var el = document.elementFromPoint(x,y);
ev.initMouseEvent(
"click",
true /* bubble */, true /* cancelable */,
window, null,
x, y, 0, 0, /* coordinates */
false, false, false, false, /* modifier keys */
0 /*left*/, null
);
el.dispatchEvent(ev);
}
// main function to listen for the follow button pressed and open a new tab with the home instance
function processButton() {
// is this site on our home instance?
if (!(document.domain == instance)) {
// wait for the DOM...
$(document).ready(function() {
// check if we are on a mastodon site with a handle in url
if (($("head").text().includes("mastodon") || $("head").text().includes("Mastodon") || $("div#mastodon").length) && window.location.href.includes("@")) {
for (const selector of buttonPaths) {
$(selector).attr("target","_self");
$(selector).attr("href","#");
}
// wait until follow button appears
waitForEl(buttonPaths, function(found) {
// grab the user handle
handle = extractHandle(window.location.href);
// if we got one...
if (!(handle == null) && (handle.match(/@/g) || []).length > 0) {
// setup the button click listener
$(found).click(function(e) {
e.preventDefault();
// wait until overlay apepars, then click in top left corner to close it (see comment above)
waitForEl(["div.modal-root div.modal-root__overlay"], function(foundoverlay) {
click(0,0);
});
// check the alert setting and show it if set
if (showAlert) {
alert("Redirecting to "+instance);
}
// backup the button text
var originaltext = $(found).text();
// replace the button text to indicate redirection
$(found).text("Redirecting...");
// timeout 1000ms to make it possible to notice the redirection indication
setTimeout(function() {
// build the new url from home instance, user handle and current domain name
// and open the url
if ((handle.match(/@/g) || []).length > 1)
var win = window.open('https://'+instance+'/'+handle, '_blank');
else {
var win = window.open('https://'+instance+'/'+handle+'@'+document.domain, '_blank');
}
// focus the new tab if open was successfull
if (win) {
win.focus();
} else {
// otherwise notify user...
console.log('Please allow popups for this website');
}
// restore original button text
$(found).text(originaltext)
}, 1000);
});
}
});
}
});
}
}
// for some reason, locationchange event did not work for me so lets use this ugly thing...
function urlChangeLoop() {
// run every 100ms, can probably be reduced
setTimeout(function() {
// compare last to current url
if (!(lastUrl == window.location.href)) {
// update lastUrl and run main script
lastUrl = window.location.href;
processButton();
}
// repeat
urlChangeLoop();
}, 300);
}
// get the extension setting for the users' Mastadon home instance
chrome.storage.local.get(['mastodonhomeinstance'], function(fetchedData) {
instance = fetchedData.mastodonhomeinstance;
// and alert setting
chrome.storage.local.get(['mastodonalert'], function(fetchedData) {
showAlert = fetchedData.mastodonalert;
// if the value is empty/null/undefined...
if (instance == null || !instance) {
console.log("Mastodon home instance is not set.");
} else {
// if the value looks like a domain...
if (/\w+\.\w+/.test(instance)) {
// ... run the actual script (once for the start and then in a loop depending on url changes)
processButton();
urlChangeLoop();
} else {
console.log("Instance setting is not a valid domain name.");
}
}
});
});

2
lib/jquery-3.6.1.min.js vendored 100644

File diff suppressed because one or more lines are too long

32
manifest.json 100644
Wyświetl plik

@ -0,0 +1,32 @@
{
"name": "FediFollow",
"version": "0.0.1",
"description": "Simplifies following Fediverse user on other instances than your own. You need to set your instance and need to be logged in to it. Built by: Github @lartsch, Fediverse lartsch@infosec.exchange",
"manifest_version": 2,
"content_scripts": [
{
"matches": ["*://*/*"],
"js": ["lib/jquery-3.6.1.min.js","inject.js"],
"run_at": "document_start"
}
],
"permissions": [
"https://*/*",
"http://*/*",
"tabs",
"storage"
],
"background":
{
"scripts": ["lib/jquery-3.6.1.min.js"]
},
"browser_action":
{
"default_popup": "popup.html",
"default_icon": "icon/48.png",
"default_title": "Home instance setting"
},
"icons": {
"48": "icon/48.png"
}
}

21
popup.html 100644
Wyświetl plik

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div id="mhi-wrapper">
<div id="mhi-containers">
<form id="homeinstance">
<label for="homeinstance">Mastodon home instance:</label><br>
<input type="text" id="homeinstance" name="homeinstance" placeholder="mastodon.social">
<label for="alert">Alert on redirect:</label><br>
<input type="checkbox" id="alert" name="alert"><br><br>
<input type="submit" value="Submit">
<span id="indicator" style="display:none">Settings saved!</span>
</form>
</div>
</div>
<script src="lib/jquery-3.6.1.min.js"></script>
<script src="popup.js"></script>
</body>
</html>

31
popup.js 100644
Wyświetl plik

@ -0,0 +1,31 @@
var currentVal_instance;
var currentVal_alert;
function popupTasks() {
$(document).ready(function() {
$("input#homeinstance").val(currentVal_instance);
if (currentVal_alert){
$("input#alert").prop('checked', true);
} else {
$("input#alert").prop('checked', false);
}
$("form#homeinstance").on('submit', function(e){
e.preventDefault();
var newVal_instance = $("input#homeinstance").val();
var newVal_alert = $("input#alert").is(':checked')
chrome.storage.local.set({mastodonhomeinstance: newVal_instance}, function() {
chrome.storage.local.set({mastodonalert: newVal_alert}, function() {
$("span#indicator").show();
});
});
});
});
}
chrome.storage.local.get(['mastodonhomeinstance'], function(fetchedData) {
currentVal_instance = fetchedData.mastodonhomeinstance;
chrome.storage.local.get(['mastodonalert'], function(fetchedData) {
currentVal_alert = fetchedData.mastodonalert;
popupTasks()
});
});