kopia lustrzana https://github.com/lartsch/FediAct
another big update (utilize background script, remove redirect page, introduce ext. follow indicator)
rodzic
3bd824a931
commit
968b462bab
|
@ -1 +1,2 @@
|
|||
*.zip
|
||||
NOTES.md
|
||||
|
|
|
@ -10,8 +10,13 @@
|
|||
"run_at": "document_start"
|
||||
}
|
||||
],
|
||||
"background": {
|
||||
"scripts": ["src/background.js"],
|
||||
"persistent": false
|
||||
},
|
||||
"permissions": [
|
||||
"storage",
|
||||
"alarms",
|
||||
"https://*/*",
|
||||
"http://*/*"
|
||||
],
|
||||
|
|
|
@ -10,8 +10,13 @@
|
|||
"run_at": "document_start"
|
||||
}
|
||||
],
|
||||
"background": {
|
||||
"service_worker": "src/background.js",
|
||||
"persistent": false
|
||||
},
|
||||
"permissions": [
|
||||
"storage"
|
||||
"storage",
|
||||
"alarms"
|
||||
],
|
||||
"host_permissions": [
|
||||
"https://*/*",
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
var browser, chrome, settings;
|
||||
var enableConsoleLog = true;
|
||||
var logPrepend = "[FediFollow]";
|
||||
|
||||
var tokenRegex = /"access_token":".*?",/gm;
|
||||
|
||||
// required settings keys with defauls
|
||||
var settingsDefaults = {
|
||||
fedifollow_homeinstance: null,
|
||||
fedifollow_showfollows: true
|
||||
}
|
||||
|
||||
// create alarm every 3 minutes
|
||||
chrome.alarms.create('refresh', { periodInMinutes: 1 });
|
||||
|
||||
function onError(error){
|
||||
console.error(`${logPrepend} Error: ${error}`);
|
||||
}
|
||||
|
||||
// wrapper to prepend to log messages
|
||||
function log(text) {
|
||||
if (enableConsoleLog) {
|
||||
console.log(logPrepend + ' ' + text)
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchBearerToken() {
|
||||
var url = "https://" + settings.fedifollow_homeinstance;
|
||||
var res = await fetch(url);
|
||||
var text = await res.text();
|
||||
if (text) {
|
||||
// dom parser is not available in background workers, so we use regex to parse the html....
|
||||
// for some reason, regex groups do not seem to work in chrome background workers... the following is ugly but should work fine
|
||||
var content = text.match(tokenRegex)[0];
|
||||
if (content) {
|
||||
var indexOne = content.search(/"access_token":"/);
|
||||
var indexTwo = content.search(/",/);
|
||||
if (indexOne > -1 && indexTwo > -1) {
|
||||
indexOne = indexOne + 16
|
||||
var token = content.substring(indexOne, indexTwo);
|
||||
console.log(token)
|
||||
if (token.length > 16) {
|
||||
settings.fedifollow_token = token;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// reset token for inject.js to know
|
||||
settings.fedifollow_token = null;
|
||||
log("Token could not be found.");
|
||||
}
|
||||
|
||||
async function fetchFollows() {
|
||||
var url = "https://" + settings.fedifollow_homeinstance + "/settings/exports/follows.csv";
|
||||
var res = await fetch(url);
|
||||
var text = await res.text();
|
||||
if (text) {
|
||||
var content = text.substring(text.indexOf("\n") + 1);
|
||||
var lines = content.split("\n");
|
||||
var follows = [];
|
||||
for (var line of lines) {
|
||||
follows.push(line.split(",")[0]);
|
||||
}
|
||||
settings.fedifollow_follows = follows;
|
||||
return;
|
||||
}
|
||||
log("Could not get follow list.");
|
||||
}
|
||||
|
||||
async function run() {
|
||||
settings = await (browser || chrome).storage.local.get(settingsDefaults);
|
||||
if (settings.fedifollow_homeinstance) {
|
||||
await fetchBearerToken();
|
||||
if (settings.fedifollow_showfollows) {
|
||||
await fetchFollows();
|
||||
} else {
|
||||
log("External follow indication not enabled.")
|
||||
}
|
||||
} else {
|
||||
log("Home instance not set");
|
||||
}
|
||||
await (browser || chrome).storage.local.set(settings);
|
||||
}
|
||||
|
||||
chrome.runtime.onInstalled.addListener(run);
|
||||
chrome.alarms.onAlarm.addListener(run);
|
269
src/inject.js
269
src/inject.js
|
@ -8,7 +8,7 @@ const domainRegex = /^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$/;
|
|||
const profileRegex = /^(?:https?:\/\/(www\.)?.*\..*?\/)((?<handle>@\w+(?:@([\w-]+\.)+?\w+)?)|explore)\/?$/;
|
||||
const tootsRegex = /^(?:https?:\/\/(www\.)?.*\..*?)(\/explore|\/public|\/public\/local|\d+)$/;
|
||||
const tootRegex = /^(?:https?:\/\/(www\.)?.*\..*?\/)(?<handle>@\w+(?:@([\w-]+\.)+?\w+)?)\/\d+\/?$/;
|
||||
const handleExtractRegex = /^.*(?<handle>@\w+)@(?<handledomain>([\w-]+\.)+?\w+)\/?$/;
|
||||
const handleExtractRegex = /^.*@(?<handle>\w+)@(?<handledomain>([\w-]+\.)+?\w+)\/?$/;
|
||||
const enableConsoleLog = true;
|
||||
const logPrepend = "[FediFollow]";
|
||||
const maxElementWaitFactor = 200; // x 100ms for total time
|
||||
|
@ -28,11 +28,15 @@ var settingsDefaults = {
|
|||
fedifollow_whitelist: null,
|
||||
fedifollow_blacklist: null,
|
||||
fedifollow_target: "_self",
|
||||
fedifollow_autoaction: true
|
||||
fedifollow_autoaction: true,
|
||||
fedifollow_token: null,
|
||||
fedifollow_follows: null,
|
||||
fedifollow_showfollows: true,
|
||||
fedifollow_redirects: true
|
||||
}
|
||||
|
||||
// fix for cross-browser storage api compatibility and other public vars
|
||||
var browser, chrome, instanceUri, fediParamValue, fediParamActionValue, settings;
|
||||
var browser, chrome, settings;
|
||||
|
||||
// wrappers to prepend to log messages
|
||||
function log(text) {
|
||||
|
@ -133,20 +137,14 @@ var getUrlParameter = function getUrlParameter(sParam) {
|
|||
return false;
|
||||
};
|
||||
|
||||
function redirectToHomeInstance(searchString, action) {
|
||||
// build url
|
||||
var url = "https://" + settings.fedifollow_homeinstance + "/?" + fediParamName + "=" + encodeURIComponent(searchString);
|
||||
if (action) {
|
||||
// add action parameter if set
|
||||
url = url + "&" + fediParamActionName + "=" + action;
|
||||
}
|
||||
log("Redirecting to " + url);
|
||||
// alert if set
|
||||
function redirectTo(url) {
|
||||
if (settings.fedifollow_redirects) {
|
||||
if (settings.fedifollow_alert) {
|
||||
alert("Redirecting to "+url);
|
||||
alert("Redirecting...")
|
||||
}
|
||||
// open window according to settings
|
||||
// open the url in same/new tab
|
||||
var win = window.open(url, settings.fedifollow_target);
|
||||
log("Redirected to " + url)
|
||||
// focus the new tab if open was successfull
|
||||
if (win) {
|
||||
win.focus();
|
||||
|
@ -154,43 +152,87 @@ function redirectToHomeInstance(searchString, action) {
|
|||
// otherwise notify user...
|
||||
log('Could not open new window. Please allow popups for this website.');
|
||||
}
|
||||
} else {
|
||||
log("Redirects disabled.")
|
||||
}
|
||||
}
|
||||
|
||||
// process fedifollow redirects to the home instance
|
||||
async function processHomeInstance() {
|
||||
// first we need the api token
|
||||
waitForEl(0, tokenPaths, function(found){
|
||||
if (found) {
|
||||
// then we wait for the appHolder
|
||||
waitForEl(0, appHolderPaths, async function(holder) {
|
||||
if (holder) {
|
||||
// hide the app holder
|
||||
$(holder).hide();
|
||||
// append our notification div
|
||||
$('body').append('<div style="position: absolute; display: block; margin-left: 30px; margin-top: 30px; font-size: 18px; font-weight: bold" id="fedifollow"></div>');
|
||||
// extract the token
|
||||
var token = JSON.parse($(found).text()).meta.access_token;
|
||||
if (token) {
|
||||
// update notification div
|
||||
$('div#fedifollow').html("<p>Resolving search...</p>");
|
||||
var requestUrl = location.protocol + '//' + location.hostname + searchApi + "/?q="+fediParamValue+"&resolve=true&limit=10";
|
||||
var headers = {"Authorization":"Bearer "+token,};
|
||||
async function followHomeInstance(id, headers, unfollow) {
|
||||
// if auto actions are enbaled...
|
||||
if (settings.fedifollow_autoaction) {
|
||||
// build follow post request
|
||||
var requestUrl = 'https://' + settings.fedifollow_homeinstance + "/api/v1/accounts/" + id + "/";
|
||||
if (unfollow) {
|
||||
requestUrl = requestUrl + "unfollow";
|
||||
} else {
|
||||
requestUrl = requestUrl + "follow";
|
||||
}
|
||||
var responseFollow = await makeRequest("POST",requestUrl,headers);
|
||||
// check if it worked (it is ignored if the user was already followed)
|
||||
if (responseFollow) {
|
||||
responseFollow = JSON.parse(responseFollow);
|
||||
if (!responseFollow.following && !responseFollow.requested) {
|
||||
log("Follow failed.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log("Auto-action disabled.")
|
||||
}
|
||||
}
|
||||
|
||||
async function boostHomeInstance(id, headers) {
|
||||
// if auto actions are enbaled...
|
||||
if (settings.fedifollow_autoaction) {
|
||||
// build follow post request
|
||||
var requestUrl = 'https://' + settings.fedifollow_homeinstance + "/api/v1/statuses/" + id + "/reblog";
|
||||
var responseBoost = await makeRequest("POST",requestUrl,headers);
|
||||
// check if it worked (it is ignored if the user was already followed)
|
||||
if (responseBoost) {
|
||||
responseBoost = JSON.parse(responseBoost);
|
||||
if (!responseBoost.reblogged) {
|
||||
log("Boost failed.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log("Auto-action disabled.")
|
||||
}
|
||||
}
|
||||
|
||||
async function favouriteHomeInstance(id, headers) {
|
||||
// if auto actions are enbaled...
|
||||
if (settings.fedifollow_autoaction) {
|
||||
// build follow post request
|
||||
var requestUrl = 'https://' + settings.fedifollow_homeinstance + "/api/v1/statuses/" + id + "/favourite";
|
||||
var responseFav = await makeRequest("POST",requestUrl,headers);
|
||||
// check if it worked (it is ignored if the user was already followed)
|
||||
if (responseFav) {
|
||||
responseFav = JSON.parse(responseFav);
|
||||
if (!responseFav.favourited) {
|
||||
log("Favourite failed.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log("Auto-action disabled.")
|
||||
}
|
||||
}
|
||||
|
||||
// resolve content uri on home instance
|
||||
async function resolveHomeInstance(searchstring, action, unfollow) {
|
||||
var requestUrl = 'https://' + settings.fedifollow_homeinstance + searchApi + "/?q="+encodeURIComponent(searchstring)+"&resolve=true&limit=10";
|
||||
var headers = {"Authorization":"Bearer " + settings.fedifollow_token,};
|
||||
// api request: search endpoint, resolve search string locally (best support for edge cases (for ex. where subdomain does not equal the handle domain) and prevents uncached profile issue)
|
||||
var response = await makeRequest("GET", requestUrl, headers);
|
||||
if (response) {
|
||||
response = JSON.parse(response);
|
||||
// decode for additional checks
|
||||
var decodedParam = decodeURIComponent(fediParamValue);
|
||||
// if we got no data (failed resolve) we can at least try to resolve a user by swapping the domain in case we got a domain in the handle
|
||||
// this does not work for resolving post IDs so we check against the handle regex
|
||||
if (!response.accounts.length && !response.statuses.length && handleExtractRegex.test(decodedParam)) {
|
||||
if (!response.accounts.length && !response.statuses.length && handleExtractRegex.test(searchstring)) {
|
||||
// get matches
|
||||
var matches = decodedParam.match(handleExtractRegex);
|
||||
var matches = searchstring.match(handleExtractRegex);
|
||||
if (matches.groups.handle && matches.groups.handledomain) {
|
||||
// we got handle + handledomain, so try to put the handle domain as host for this fallback (not guaranteed to resolve)
|
||||
$('div#fedifollow').append("<p>Failed, trying domain swap...</p>");
|
||||
var searchstring = encodeURIComponent("https://" + matches.groups.handledomain + "/" + matches.groups.handle);
|
||||
var requestUrl = location.protocol + '//' + location.hostname + searchApi + "/?q="+searchstring+"&resolve=true&limit=10";
|
||||
var searchstring = "https://" + matches.groups.handledomain + "/@" + matches.groups.handle;
|
||||
var requestUrl = 'https://' + settings.fedifollow_homeinstance + searchApi + "/?q="+encodeURIComponent(searchstring)+"&resolve=true&limit=10";
|
||||
// update response var
|
||||
response = await makeRequest("GET", requestUrl, headers);
|
||||
response = JSON.parse(response);
|
||||
|
@ -201,26 +243,9 @@ async function processHomeInstance() {
|
|||
// if we got an account but no statuses, redirect to profile (first result)
|
||||
if (response.accounts.length && !response.statuses.length) {
|
||||
// build redirect url
|
||||
var redirect = location.protocol + "//" + location.hostname + "/@" + response.accounts[0].acct;
|
||||
$('div#fedifollow').append("<p>Success!</p>");
|
||||
// if auto actions are enbaled...
|
||||
if (settings.fedifollow_autoaction) {
|
||||
$('div#fedifollow').append("<p>Attempting auto-follow...</p>");
|
||||
// build follow post request
|
||||
var requestUrl = location.protocol + "//" + location.hostname + "/api/v1/accounts/" + response.accounts[0].id + "/follow";
|
||||
var responseFollow = await makeRequest("POST",requestUrl,headers);
|
||||
// check if it worked (it is ignored if the user was already followed)
|
||||
if (responseFollow) {
|
||||
responseFollow = JSON.parse(responseFollow);
|
||||
if (responseFollow.following || responseFollow.requested) {
|
||||
$('div#fedifollow').append("<p>Success!</p>");
|
||||
} else {
|
||||
$('div#fedifollow').append("<p>Failed.</p>");
|
||||
}
|
||||
}
|
||||
}
|
||||
var redirect = 'https://' + settings.fedifollow_homeinstance + "/@" + response.accounts[0].acct;
|
||||
await followHomeInstance(response.accounts[0].id, headers, unfollow);
|
||||
} else if (!response.accounts.length && response.statuses.length) {
|
||||
$('div#fedifollow').append("<p>Success!</p>");
|
||||
// if statuses but no accounts, redirect to status (first result)
|
||||
var status = response.statuses[0];
|
||||
var statusData = {
|
||||
|
@ -228,68 +253,23 @@ async function processHomeInstance() {
|
|||
"account": status.account.acct
|
||||
}
|
||||
// build redirect url
|
||||
var redirect = location.protocol + "//" + location.hostname + "/@" + statusData.account + "/" + statusData.id;
|
||||
// if autoactions enabled and fediParamValue is okay...
|
||||
if (settings.fedifollow_autoaction && (fediParamActionValue == "boost" || fediParamActionValue == "favourite")) {
|
||||
$('div#fedifollow').append("<p>Attempting auto-" + fediParamActionValue + "...</p>");
|
||||
// build favourite/boost post request
|
||||
var actionRequest = location.protocol + "//" + location.hostname + "/api/v1/statuses/" + statusData.id + "/";
|
||||
if (fediParamActionValue == "boost") {
|
||||
actionRequest = actionRequest + "reblog";
|
||||
} else {
|
||||
actionRequest = actionRequest + "favourite";
|
||||
}
|
||||
var actionResponse = await makeRequest("POST", actionRequest, headers);
|
||||
// check if it worked (it is ignored if the post was already fav'ed / boosted)
|
||||
if (actionResponse) {
|
||||
actionResponse = JSON.parse(actionResponse);
|
||||
if (actionResponse.reblogged || actionResponse.favourited) {
|
||||
$('div#fedifollow').append("<p>Success!<p>");
|
||||
} else {
|
||||
$('div#fedifollow').append("<p>Failed.<p>");
|
||||
}
|
||||
}
|
||||
var redirect = 'https://' + settings.fedifollow_homeinstance + "/@" + statusData.account + "/" + statusData.id;
|
||||
// perform action if set
|
||||
if (action == "boost") {
|
||||
await boostHomeInstance(statusData.id, headers)
|
||||
} else if (action == "favourite") {
|
||||
await favouriteHomeInstance(statusData.id, headers)
|
||||
}
|
||||
}
|
||||
// if we got a redirect url...
|
||||
if (redirect) {
|
||||
$('div#fedifollow').append("<p>Redirecting...</p>");
|
||||
// open the url in current tab
|
||||
var win = window.open(redirect, "_self");
|
||||
log("Redirected to " + redirect)
|
||||
// focus the new tab if open was successfull
|
||||
if (win) {
|
||||
win.focus();
|
||||
return true;
|
||||
} else {
|
||||
// otherwise notify user...
|
||||
log('Could not open new window. Please allow popups for this website.');
|
||||
$('div#fedifollow').text('Could not open new window. Please allow popups for this website.');
|
||||
}
|
||||
redirectTo(redirect);
|
||||
} else {
|
||||
log("Could not resolve a match for this search...");
|
||||
$('div#fedifollow').text("Could not resolve a match for this search....")
|
||||
}
|
||||
} else {
|
||||
log("API call failed...")
|
||||
$('div#fedifollow').text("API call failed...")
|
||||
}
|
||||
} else {
|
||||
log("Could not extract API token.")
|
||||
$('div#fedifollow').text("Could not get API token...");
|
||||
}
|
||||
// show app holder after 1.5s (in case we did not redirect)
|
||||
setTimeout(function(){
|
||||
$(holder).show()
|
||||
}, 1500);
|
||||
} else {
|
||||
log("Could not find app holder element.")
|
||||
}
|
||||
});
|
||||
} else {
|
||||
log("Could not find API token.")
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// process any toots found on supported sites
|
||||
|
@ -320,7 +300,7 @@ async function processToots() {
|
|||
// first check if there is an <a> sibling with the actual post URL (easiest and fastest)
|
||||
if ($(this).siblings("a.status__relative-time").attr("href")) {
|
||||
var redirected = true;
|
||||
redirectToHomeInstance((this).siblings("a.status__relative-time").attr("href"), action);
|
||||
resolveHomeInstance((this).siblings("a.status__relative-time").attr("href"), action, null);
|
||||
} else if ($(e.target).closest("div.status").attr("data-id")) {
|
||||
// no? then check if there is a closest div.status with the ID in data-id attribute
|
||||
closestTootId = $(e.target).closest("div.status").attr("data-id").replace(/[^0-9]/gi,'');
|
||||
|
@ -354,7 +334,7 @@ async function processToots() {
|
|||
var postUri = JSON.parse(response).url.replace("/activity/","").replace("/activity","");
|
||||
if (postUri) {
|
||||
// redirect to home instance
|
||||
redirectToHomeInstance(postUri, action);
|
||||
resolveHomeInstance(postUri, action, null);
|
||||
} else {
|
||||
log("Could not find post url.")
|
||||
}
|
||||
|
@ -378,18 +358,9 @@ function processFollow() {
|
|||
// check if this is a profile url
|
||||
if (profileRegex.test(window.location.href.split("?")[0])) {
|
||||
// wait until follow button appears (document is already ready, but most content is loaded afterwards)
|
||||
waitForEl(0, followButtonPaths, function(found) {
|
||||
waitForEl(0, followButtonPaths, async function(found) {
|
||||
if (found) {
|
||||
// setup the button click listener
|
||||
$(found).click(async function(e) {
|
||||
// prevent default action and other handlers
|
||||
e.preventDefault();
|
||||
e.stopImmediatePropagation();
|
||||
// backup the button text
|
||||
var originaltext = $(found).html();
|
||||
var handleEl;
|
||||
var handleDomain;
|
||||
var handle;
|
||||
var unfollow, handleEl, handleDomain, handle;
|
||||
// dirty fix for some v3 instance views
|
||||
if (~window.location.href.indexOf("/explore")) {
|
||||
var temp = $(e.target).closest("div.account-card").find("div.display-name > span");
|
||||
|
@ -413,9 +384,17 @@ function processFollow() {
|
|||
}
|
||||
// if extraction worked...
|
||||
if (handleDomain && handle) {
|
||||
if (settings.fedifollow_showfollows) {
|
||||
if (settings.fedifollow_follows) {
|
||||
if ($.inArray(handle + "@" + handleDomain, settings.fedifollow_follows) > -1) {
|
||||
$(found).text("Unfollow");
|
||||
unfollow = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// make request to the external instances search endpoint to make sure we get the correct url for the searchstring
|
||||
// (for ex. another external instance, also instance domain can differ from handle domain)
|
||||
var requestUrl = location.protocol + "//" + location.hostname + searchApi + "/?q=" + encodeURIComponent(handle+"@"+handleDomain) + "&resolve=false&limit=10";
|
||||
var requestUrl = location.protocol + "//" + location.hostname + searchApi + "/?q=" + encodeURIComponent("@"+handle+"@"+handleDomain) + "&resolve=false&limit=10";
|
||||
var response = await makeRequest("GET", requestUrl, null);
|
||||
var result;
|
||||
if (response) {
|
||||
|
@ -430,15 +409,22 @@ function processFollow() {
|
|||
result = url.protocol + "//" + url.hostname;
|
||||
}
|
||||
}
|
||||
// setup the button click listener
|
||||
$(found).click(async function(e) {
|
||||
// prevent default action and other handlers
|
||||
e.preventDefault();
|
||||
e.stopImmediatePropagation();
|
||||
// backup the button text
|
||||
var originaltext = $(found).html();
|
||||
// replace the button text to indicate redirection
|
||||
$(found).text("Redirecting...");
|
||||
// if we could resolve the user domain...
|
||||
if (result) {
|
||||
// add the handle
|
||||
var redirectUrl = result + "/" + handle;
|
||||
var redirectUrl = result + "/@" + handle;
|
||||
// timeout 1000ms to make it possible to notice the redirection indication
|
||||
setTimeout(function() {
|
||||
redirectToHomeInstance(redirectUrl, null);
|
||||
resolveHomeInstance(redirectUrl, null, unfollow);
|
||||
// restore original button text
|
||||
$(found).html(originaltext);
|
||||
}, 1000);
|
||||
|
@ -447,19 +433,19 @@ function processFollow() {
|
|||
var rawRedirect = window.location.href;
|
||||
// dirty fix for some v3 views
|
||||
if (~rawRedirect.indexOf("/explore")) {
|
||||
rawRedirect = "https://" + handleDomain + "/" + handle;
|
||||
rawRedirect = "https://" + handleDomain + "/@" + handle;
|
||||
}
|
||||
// timeout 1000ms to make it possible to notice the redirection indication
|
||||
setTimeout(function() {
|
||||
redirectToHomeInstance(rawRedirect, null);
|
||||
resolveHomeInstance(rawRedirect, null, unfollow);
|
||||
// restore original button text
|
||||
$(found).html(originaltext);
|
||||
}, 1000);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
log("Could not extract user handle.")
|
||||
}
|
||||
});
|
||||
} else {
|
||||
log("Could not find any follow button.");
|
||||
}
|
||||
|
@ -491,6 +477,11 @@ function checkSettings() {
|
|||
log("Mastodon home instance is not set.");
|
||||
return false;
|
||||
}
|
||||
// no token for api available (see background.js)
|
||||
if (!settings.fedifollow_token) {
|
||||
log("No API token available. Are you logged in to your home instance?");
|
||||
return false;
|
||||
}
|
||||
// if the value looks like a domain...
|
||||
if (!(domainRegex.test(settings.fedifollow_homeinstance))) {
|
||||
log("Instance setting is not a valid domain name.");
|
||||
|
@ -522,17 +513,9 @@ function checkSettings() {
|
|||
async function checkSite(callback) {
|
||||
// is this site on our home instance?
|
||||
if (location.hostname == settings.fedifollow_homeinstance) {
|
||||
// do we have a fedifollow param?
|
||||
fediParamValue = getUrlParameter(fediParamName);
|
||||
fediParamActionValue = getUrlParameter(fediParamActionName);
|
||||
if (fediParamValue) {
|
||||
// if so, run home mode
|
||||
return "home";
|
||||
} else {
|
||||
log("Current site is your home instance.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// are we in whitelist mode?
|
||||
if (settings.fedifollow_mode == "whitelist") {
|
||||
// if so, check if site is NOT in whitelist
|
||||
|
@ -554,10 +537,8 @@ async function checkSite(callback) {
|
|||
if (response) {
|
||||
var uri = JSON.parse(response).uri;
|
||||
if (uri) {
|
||||
// update global var
|
||||
instanceUri = uri;
|
||||
// run external mode
|
||||
return "external";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
log("Does not look like a Mastodon instance.");
|
||||
|
@ -572,14 +553,10 @@ async function run() {
|
|||
// validate settings
|
||||
if (checkSettings()) {
|
||||
// check site (if and which scripts should run)
|
||||
var mode = await checkSite();
|
||||
// run or exit
|
||||
if (mode == "external") {
|
||||
if (await checkSite()) {
|
||||
processFollow();
|
||||
processToots();
|
||||
urlChangeLoop();
|
||||
} else if (mode == "home") {
|
||||
processHomeInstance();
|
||||
} else {
|
||||
log("Will not process this site.")
|
||||
}
|
||||
|
|
|
@ -5,34 +5,48 @@
|
|||
.hide {
|
||||
display: none;
|
||||
}
|
||||
label.pad {
|
||||
margin-bottom: 4px;
|
||||
display: block;
|
||||
}
|
||||
p {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<body style="min-width: 300px">
|
||||
<div id="mhi-wrapper">
|
||||
<div id="mhi-containers">
|
||||
<form id="fedifollow-settings">
|
||||
<label for="homeinstance">Home instance (make sure you are logged in):</label><br>
|
||||
<p><b>General</b></p>
|
||||
<label class="pad" for="homeinstance">Home instance (make sure you are logged in):</label>
|
||||
<input type="text" id="homeinstance" name="homeinstance" placeholder="mastodon.social"><br>
|
||||
<label for="alert">Alert on redirect:</label><br>
|
||||
<input type="checkbox" id="alert" name="alert"><br>
|
||||
<label for="alert">Auto-action:</label><br>
|
||||
<input type="checkbox" id="autoaction" name="autoaction"><br>
|
||||
<label for="target">Open in:</label><br>
|
||||
<select name="target" id="target" selected="_blank">
|
||||
<p><b>Redirect settings</b></p>
|
||||
<input type="checkbox" id="redirects" name="redirects">
|
||||
<label for="redirects">Enable</label><br>
|
||||
<input type="checkbox" id="alert" name="alert">
|
||||
<label for="alert">Alert on redirect</label><br>
|
||||
<label style="padding-right: 5px" for="target">Open in</label>
|
||||
<select style="margin-top: 5px;" name="target" id="target" selected="_blank">
|
||||
<option id="target_blank" value="_blank">New tab</option>
|
||||
<option id="target_self" value="_self">Same tab</option>
|
||||
</select><br>
|
||||
<label for="mode">Mode:</label><br>
|
||||
<p><b>Other</b></p>
|
||||
<input type="checkbox" id="autoaction" name="autoaction">
|
||||
<label for="alert">Auto-action</label><br>
|
||||
<input type="checkbox" id="showfollows" name="showfollows">
|
||||
<label for="alert">Show external follows</label><br>
|
||||
<p><b>Mode</b></p>
|
||||
<select name="mode" id="mode" selected="blacklist">
|
||||
<option id="blacklist" value="blacklist">All (with blacklist)</option>
|
||||
<option id="whitelist" value="whitelist">Whitelist</option>
|
||||
</select><br>
|
||||
<div class="hide" id="blacklist_input">
|
||||
<label for="blacklist_content">Blacklist (one per line):</label><br>
|
||||
<label for="blacklist_content">Blacklist:</label><br>
|
||||
<textarea id="blacklist_content" name="blacklist_content" placeholder="mastodon.social infosec.exchange"></textarea><br>
|
||||
</div>
|
||||
<div class="hide" id="whitelist_input">
|
||||
<label for="whitelist_content">Whitelist (one per line):</label><br>
|
||||
<label for="whitelist_content">Whitelist:</label><br>
|
||||
<textarea id="whitelist_content" name="whitelist_content" placeholder="mastodon.social infosec.exchange"></textarea><br>
|
||||
</div><br>
|
||||
<input type="submit" value="Submit">
|
||||
|
|
12
src/popup.js
12
src/popup.js
|
@ -1,5 +1,5 @@
|
|||
|
||||
// settings keys with defauls
|
||||
// required settings keys with defauls
|
||||
var settings = {
|
||||
fedifollow_homeinstance: null,
|
||||
fedifollow_alert: false,
|
||||
|
@ -7,14 +7,16 @@ var settings = {
|
|||
fedifollow_whitelist: null,
|
||||
fedifollow_blacklist: null,
|
||||
fedifollow_target: "_self",
|
||||
fedifollow_autoaction: true
|
||||
fedifollow_autoaction: true,
|
||||
fedifollow_showfollows: true,
|
||||
fedifollow_redirects: true
|
||||
}
|
||||
|
||||
// fix for cross-browser storage api compatibility
|
||||
var browser, chrome;
|
||||
|
||||
function onError(error){
|
||||
console.error(`[FediFollow] Error: ${error}`)
|
||||
console.error(`[FediFollow] Error: ${error}`);
|
||||
}
|
||||
|
||||
// this performs loading the settings into the popup, reacting to changes and saving changes
|
||||
|
@ -36,6 +38,8 @@ function popupTasks(settings) {
|
|||
settings.fedifollow_blacklist = $("textarea#blacklist_content").val();
|
||||
settings.fedifollow_target = $("select#target").val();
|
||||
settings.fedifollow_autoaction = $("input#autoaction").is(':checked');
|
||||
settings.fedifollow_showfollows = $("input#showfollows").is(':checked');
|
||||
settings.fedifollow_redirects = $("input#redirects").is(':checked');
|
||||
// write to storage
|
||||
const waitForSaved = (browser || chrome).storage.local.set(settings);
|
||||
// show saved indicator after successful save
|
||||
|
@ -51,6 +55,8 @@ function popupTasks(settings) {
|
|||
$("select#target").val(settings.fedifollow_target);
|
||||
$("input#alert").prop('checked', settings.fedifollow_alert);
|
||||
$("input#autoaction").prop('checked', settings.fedifollow_autoaction);
|
||||
$("input#showfollows").prop('checked', settings.fedifollow_showfollows);
|
||||
$("input#redirects").prop('checked', settings.fedifollow_redirects);
|
||||
// both containers are hidden by default
|
||||
if ($("select#mode").val() == "whitelist") {
|
||||
$("div#whitelist_input").show();
|
||||
|
|
Ładowanie…
Reference in New Issue