2022-12-02 21:45:34 +00:00
// =-=-=-=-==-=-=-=-==-=-=-=-==-=-=
// =-=-=-=-=-= CONSTANTS =-==-=-=-=
// =-=-=-=-==-=-=-=-==-=-=-=-==-=-=
2022-12-19 15:04:23 +00:00
const followButtonPaths = [ "div.account__header button.logo-button" , "div.public-account-header a.logo-button" , "div.account-card a.logo-button" , "div.directory-card a.icon-button" , "div.directory__card a.icon-button" , "div.detailed-status a.logo-button" , "button.remote-button" , "div.account__header button.button--follow" ]
2022-12-13 13:30:24 +00:00
const profileNamePaths = [ "div.account__header__tabs__name small" , "div.public-account-header__tabs__name small" , "div.detailed-status span.display-name__account" , "div.display-name > span" , "a.user-screen-name" , "div.profile-info-panel small" ]
2022-12-09 14:27:57 +00:00
const domainRegex = /^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$/
const handleExtractUrlRegex = /^(?<domain>https?:\/\/(?:\.?[a-z0-9-]+)+(?:\.[a-z]+){1})?\/?@(?<handle>\w+)(?:@(?<handledomain>(?:[\w-]+\.)+?\w+))?(?:\/(?<tootid>\d+))?\/?$/
const handleExtractUriRegex = /^(?<domain>https?:\/\/(?:\.?[a-z0-9-]+)+(?:\.[a-z]+){1})(?:\/users\/)(?<handle>\w+)(?:(?:\/statuses\/)(?<tootid>\d+))?\/?$/
2022-12-21 13:47:07 +00:00
const enableConsoleLog = false
2022-12-09 14:27:57 +00:00
const logPrepend = "[FediAct]"
const instanceApi = "/api/v1/instance"
const statusApi = "/api/v1/statuses"
const searchApi = "/api/v2/search"
const accountsApi = "/api/v1/accounts"
2022-12-15 12:29:04 +00:00
const mutesApi = "/api/v1/mutes"
const blocksApi = "/api/v1/blocks"
2022-12-15 11:51:15 +00:00
const domainBlocksApi = "/api/v1/domain_blocks"
2022-12-14 13:13:27 +00:00
const pollsApi = "/api/v1/polls"
2022-12-29 15:10:59 +00:00
const apiDelay = 600
2022-12-08 14:23:58 +00:00
const maxTootCache = 200
2022-12-18 23:33:04 +00:00
const modalHtml = '<div class="fediactmodal"><div class="fediactmodalinner"><ul class="fediactmodallist"></ul></div></div>'
2022-12-29 15:10:59 +00:00
const maxAsyncRequests = 10
2022-11-18 13:20:22 +00:00
// settings keys with defauls
2022-12-02 21:45:34 +00:00
var settings = { }
const settingsDefaults = {
2022-12-06 11:04:25 +00:00
fediact _homeinstance : null ,
fediact _alert : false ,
fediact _mode : "blacklist" ,
fediact _whitelist : null ,
fediact _blacklist : null ,
fediact _target : "_self" ,
fediact _autoaction : true ,
fediact _token : null ,
fediact _redirects : true ,
2022-12-10 15:01:38 +00:00
fediact _enabledelay : true ,
fediact _hidemuted : false ,
2022-12-15 00:23:31 +00:00
fediact _runifloggedin : false ,
2022-12-15 12:29:04 +00:00
fediact _mutes : [ ] ,
fediact _blocks : [ ] ,
2022-12-10 15:37:06 +00:00
fediact _domainblocks : [ ]
2022-11-18 13:20:22 +00:00
}
2022-12-18 18:02:35 +00:00
const tmpSettings = {
fedireply : undefined ,
lasthomerequest : undefined ,
whitelist : undefined ,
blacklist : undefined ,
exturi : undefined ,
tokenheader : undefined ,
processed : [ ] ,
processedFollow : [ ] ,
isProcessing : [ ]
}
2022-11-18 13:20:22 +00:00
2022-12-03 01:09:23 +00:00
// fix for cross-browser storage api compatibility and other global vars
2022-12-18 18:02:35 +00:00
var browser , chrome
2022-12-02 21:45:34 +00:00
2022-12-10 13:11:05 +00:00
2022-12-02 21:45:34 +00:00
// =-=-=-=-==-=-=-=-==-=-=-=-=-
// =-=-=-=-=-= UTILS =-==-=-=-=
// =-=-=-=-==-=-=-=-==-=-=-=-=-
2022-11-18 14:13:31 +00:00
2022-11-18 13:20:22 +00:00
// wrappers to prepend to log messages
function log ( text ) {
if ( enableConsoleLog ) {
console . log ( logPrepend + ' ' + text )
}
}
2022-12-03 01:09:23 +00:00
// Custom solution for detecting inserted nodes
// Works in combination with nodeinserted.css (fixes Firefox blocking addon-inserted <style> elements for sites with CSP)
2022-12-07 18:49:07 +00:00
// Is more reliable/practicable in certain situations than mutationobserver, who will ignore any node that was inserted with its parent node at once
2022-12-02 21:45:34 +00:00
( function ( $ ) {
$ . fn . DOMNodeAppear = function ( callback , selector ) {
if ( ! selector ) {
return false
}
2022-12-10 13:09:08 +00:00
// catch all animationstart events
2022-12-02 21:45:34 +00:00
$ ( document ) . on ( 'animationstart webkitAnimationStart oanimationstart MSAnimationStart' , function ( e ) {
2022-12-10 13:09:08 +00:00
// check if the animatonname equals our animation and if the element is one of our selectors
2022-12-02 21:45:34 +00:00
if ( e . originalEvent . animationName == 'nodeInserted' && $ ( e . target ) . is ( selector ) ) {
if ( typeof callback == 'function' ) {
2022-12-10 13:09:08 +00:00
// return the complete object in the callback
2022-12-09 14:32:23 +00:00
callback ( e )
2022-12-02 21:45:34 +00:00
}
}
2022-12-09 14:32:23 +00:00
} )
}
jQuery . fn . onAppear = jQuery . fn . DOMNodeAppear
} ) ( jQuery )
2022-11-18 13:20:22 +00:00
2022-12-14 10:44:01 +00:00
// for checking if logged in on an external instance
function isLoggedIn ( ) {
return new Promise ( function ( resolve ) {
if ( $ ( document ) . find ( "script#initial-state" ) . length ) {
var initialState = $ ( document ) . find ( "script#initial-state" ) . first ( )
var stateJson = JSON . parse ( $ ( initialState ) . text ( ) )
if ( stateJson . meta . access _token ) {
resolve ( true )
}
} else {
$ ( document ) . DOMNodeAppear ( function ( e ) {
var initialState = $ ( e . target )
var stateJson = JSON . parse ( $ ( initialState ) . text ( ) )
if ( stateJson . meta . access _token ) {
resolve ( true )
}
} , "script#initial-state" )
}
resolve ( false )
} )
}
2022-12-04 16:56:42 +00:00
// extract given url parameter value
var getUrlParameter = function getUrlParameter ( sParam ) {
var sPageURL = window . location . search . substring ( 1 ) ,
2022-12-09 14:32:23 +00:00
sURLVariables = sPageURL . split ( '&' ) , sParameterName , i
2022-12-04 16:56:42 +00:00
for ( i = 0 ; i < sURLVariables . length ; i ++ ) {
2022-12-09 14:32:23 +00:00
sParameterName = sURLVariables [ i ] . split ( '=' )
2022-12-04 16:56:42 +00:00
if ( sParameterName [ 0 ] === sParam ) {
2022-12-09 14:32:23 +00:00
return sParameterName [ 1 ] === undefined ? true : decodeURIComponent ( sParameterName [ 1 ] )
2022-12-04 16:56:42 +00:00
}
}
2022-12-09 14:32:23 +00:00
return false
}
2022-12-04 16:56:42 +00:00
2022-12-29 15:10:59 +00:00
const asyncLimit = ( fn , n ) => {
let pendingPromises = [ ]
return async function ( ... args ) {
while ( pendingPromises . length >= n ) {
await Promise . race ( pendingPromises ) . catch ( ( ) => { } )
}
const p = fn . apply ( this , args )
pendingPromises . push ( p )
await p . catch ( ( ) => { } )
pendingPromises = pendingPromises . filter ( pending => pending !== p )
return p
}
}
2022-11-21 22:47:32 +00:00
// promisified xhr for api calls
2022-12-25 19:21:48 +00:00
function makeRequest ( method , url , extraheaders , jsonbody ) {
2022-12-21 13:47:07 +00:00
return new Promise ( async function ( resolve ) {
2022-12-29 15:10:59 +00:00
// get current time
var currenttime = Date . now ( )
2022-12-25 19:21:48 +00:00
// try to prevent error 429 too many request by delaying home instance requests
if ( ~ url . indexOf ( settings . fediact _homeinstance ) && settings . fediact _enabledelay ) {
// get difference of current time and time of last request
var difference = currenttime - tmpSettings . lasthomerequest
// if difference is smaller than our set api delay value...
if ( difference < apiDelay ) {
// ... then wait the time required to reach the api delay value...
await new Promise ( resolve => {
setTimeout ( function ( ) {
resolve ( )
} , apiDelay - difference )
} )
}
// TODO: move this to the top? or get new Date.now() here?
2022-12-29 10:22:35 +00:00
tmpSettings . lasthomerequest = Date . now ( )
2022-12-25 19:21:48 +00:00
}
2022-12-21 13:47:07 +00:00
try {
await chrome . runtime . sendMessage ( { requestdata : [ method , url , extraheaders , jsonbody ] } , function ( response ) {
if ( response ) {
resolve ( response )
} else {
resolve ( false )
}
} )
} catch ( e ) {
// if we encounter an error here, it is likely since the extension context got invalidated, so reload the page
log ( e )
log ( "Reloading page, extension likely got updated or reloaded." )
location . reload ( )
2022-12-14 13:13:27 +00:00
}
2022-12-21 13:47:07 +00:00
} )
2022-11-21 22:47:32 +00:00
}
2022-12-29 15:10:59 +00:00
// wrap so there are never more than 10 concurrent requests
const requestAsyncLimited = asyncLimit ( makeRequest , maxAsyncRequests )
2022-12-03 01:09:23 +00:00
// Escape characters used for regex
2022-12-02 21:45:34 +00:00
function escapeRegExp ( string ) {
return string . replace ( /[.*+?^${}()|[\]\\]/g , '\\$&' ) ; // $& means the whole matched string
}
2022-12-03 01:09:23 +00:00
// Replace all occurrences of a substring
2022-12-02 21:45:34 +00:00
function replaceAll ( str , find , replace ) {
2022-12-09 14:32:23 +00:00
return str . replace ( new RegExp ( escapeRegExp ( find ) , 'g' ) , replace )
2022-12-02 21:45:34 +00:00
}
2022-12-03 01:09:23 +00:00
// handles redirects to home instance
2022-11-26 01:40:41 +00:00
function redirectTo ( url ) {
2022-12-10 13:09:08 +00:00
// check if redirects are enabled at all
2022-12-06 11:04:25 +00:00
if ( settings . fediact _redirects ) {
2022-12-29 15:47:09 +00:00
if ( settings . fediact _target == "_self" ) {
/* If browser back button was used, flush cache */
( function ( ) {
window . onpageshow = function ( event ) {
if ( event . persisted ) {
window . location . reload ( ) ;
}
} ;
} ) ( )
}
2022-12-14 22:55:27 +00:00
// check if alert before redirect is enabled and show the prompt if so
2022-12-06 11:04:25 +00:00
if ( settings . fediact _alert ) {
2022-12-14 22:55:27 +00:00
if ( ! confirm ( "Redirecting to " + url ) ) {
return
}
2022-11-26 01:40:41 +00:00
}
// open the url in same/new tab
2022-12-09 14:32:23 +00:00
var win = window . open ( url , settings . fediact _target )
2022-11-26 01:40:41 +00:00
log ( "Redirected to " + url )
// focus the new tab if open was successfull
if ( win ) {
2022-12-09 14:32:23 +00:00
win . focus ( )
2022-11-26 01:40:41 +00:00
} else {
// otherwise notify user...
2022-12-09 14:32:23 +00:00
log ( 'Could not open new window. Please allow popups for this website.' )
2022-11-26 01:40:41 +00:00
}
} else {
log ( "Redirects disabled." )
2022-11-22 19:12:23 +00:00
}
2022-11-26 01:40:41 +00:00
}
2022-12-02 21:45:34 +00:00
// =-=-=-=-==-=-=-=-==-=-=-=-==-=-=
// =-=-=-=-= INTERACTIONS =-=-=-=-=
// =-=-=-=-==-=-=-=-==-=-=-=-==-=-=
2022-12-20 22:58:46 +00:00
async function executeAction ( data , action , polldata ) {
2022-12-15 12:29:04 +00:00
var requestUrl , condition , jsonbody , after
2022-12-15 11:51:15 +00:00
var method = "POST"
2022-12-10 15:01:38 +00:00
switch ( action ) {
2022-12-20 22:58:46 +00:00
case 'copy' :
// special action. only copy to clipboard and return
navigator . clipboard . writeText ( data )
2022-12-25 19:21:48 +00:00
return true
2022-12-15 11:51:15 +00:00
case 'domainblock' :
2022-12-20 22:58:46 +00:00
requestUrl = 'https://' + settings . fediact _homeinstance + domainBlocksApi + "?domain=" + data
2022-12-15 11:51:15 +00:00
condition = function ( response ) { if ( response ) { return true } }
2022-12-25 19:21:48 +00:00
after = async function ( ) { await updateMutedBlocked ( ) }
2022-12-15 11:51:15 +00:00
break
case 'domainunblock' :
2022-12-20 22:58:46 +00:00
requestUrl = 'https://' + settings . fediact _homeinstance + domainBlocksApi + "?domain=" + data
2022-12-15 11:51:15 +00:00
condition = function ( response ) { if ( response ) { return true } }
method = "DELETE"
2022-12-25 19:21:48 +00:00
after = async function ( ) { await updateMutedBlocked ( ) }
2022-12-15 11:51:15 +00:00
break
case 'mute' :
2022-12-20 22:58:46 +00:00
requestUrl = 'https://' + settings . fediact _homeinstance + accountsApi + "/" + data + "/mute"
2022-12-15 11:51:15 +00:00
condition = function ( response ) { return response . muting }
2022-12-25 19:21:48 +00:00
after = async function ( ) { await updateMutedBlocked ( ) }
2022-12-15 11:51:15 +00:00
break
case 'unmute' :
2022-12-20 22:58:46 +00:00
requestUrl = 'https://' + settings . fediact _homeinstance + accountsApi + "/" + data + "/unmute"
2022-12-15 11:51:15 +00:00
condition = function ( response ) { return ! response . muting }
2022-12-25 19:21:48 +00:00
after = async function ( ) { await updateMutedBlocked ( ) }
2022-12-15 11:51:15 +00:00
break
case 'block' :
2022-12-20 22:58:46 +00:00
requestUrl = 'https://' + settings . fediact _homeinstance + accountsApi + "/" + data + "/block"
2022-12-15 11:51:15 +00:00
condition = function ( response ) { return response . blocking }
2022-12-25 19:21:48 +00:00
after = async function ( ) { await updateMutedBlocked ( ) }
2022-12-15 11:51:15 +00:00
break
case 'unblock' :
2022-12-20 22:58:46 +00:00
requestUrl = 'https://' + settings . fediact _homeinstance + accountsApi + "/" + data + "/unblock"
2022-12-15 11:51:15 +00:00
condition = function ( response ) { return ! response . blocking }
2022-12-25 19:21:48 +00:00
after = async function ( ) { await updateMutedBlocked ( ) }
2022-12-15 11:51:15 +00:00
break
2022-12-14 13:13:27 +00:00
case 'vote' :
2022-12-20 22:58:46 +00:00
requestUrl = 'https://' + settings . fediact _homeinstance + pollsApi + "/" + data + "/votes"
2022-12-14 13:13:27 +00:00
condition = function ( response ) { return response . voted }
jsonbody = polldata
break
2022-12-10 15:01:38 +00:00
case 'follow' :
2022-12-20 22:58:46 +00:00
requestUrl = 'https://' + settings . fediact _homeinstance + accountsApi + "/" + data + "/follow"
2022-12-10 15:01:38 +00:00
condition = function ( response ) { return response . following || response . requested }
break
case 'boost' :
2022-12-20 22:58:46 +00:00
requestUrl = 'https://' + settings . fediact _homeinstance + statusApi + "/" + data + "/reblog"
2022-12-10 15:01:38 +00:00
condition = function ( response ) { return response . reblogged }
break
case 'favourite' :
2022-12-20 22:58:46 +00:00
requestUrl = 'https://' + settings . fediact _homeinstance + statusApi + "/" + data + "/favourite"
2022-12-10 15:01:38 +00:00
condition = function ( response ) { return response . favourited }
break
case 'bookmark' :
2022-12-20 22:58:46 +00:00
requestUrl = 'https://' + settings . fediact _homeinstance + statusApi + "/" + data + "/bookmark"
2022-12-10 15:01:38 +00:00
condition = function ( response ) { return response . bookmarked }
break
case 'unfollow' :
2022-12-20 22:58:46 +00:00
requestUrl = 'https://' + settings . fediact _homeinstance + accountsApi + "/" + data + "/unfollow"
2022-12-10 15:01:38 +00:00
condition = function ( response ) { return ! response . following && ! response . requested }
break
case 'unboost' :
2022-12-20 22:58:46 +00:00
requestUrl = 'https://' + settings . fediact _homeinstance + statusApi + "/" + data + "/unreblog"
2022-12-10 15:01:38 +00:00
condition = function ( response ) { return ! response . reblogged }
break
case 'unfavourite' :
2022-12-20 22:58:46 +00:00
requestUrl = 'https://' + settings . fediact _homeinstance + statusApi + "/" + data + "/unfavourite"
2022-12-10 15:01:38 +00:00
condition = function ( response ) { return ! response . favourited }
break
case 'unbookmark' :
2022-12-20 22:58:46 +00:00
requestUrl = 'https://' + settings . fediact _homeinstance + statusApi + "/" + data + "/unbookmark"
2022-12-10 15:01:38 +00:00
condition = function ( response ) { return ! response . bookmarked }
break
default :
2022-12-25 19:21:48 +00:00
log ( "No valid action specified." )
return
2022-12-10 15:01:38 +00:00
}
if ( requestUrl ) {
2022-12-29 15:10:59 +00:00
var response = await requestAsyncLimited ( method , requestUrl , tmpSettings . tokenheader , jsonbody )
2022-12-10 15:01:38 +00:00
if ( response ) {
// convert to json object
response = JSON . parse ( response )
if ( condition ( response ) ) {
2022-12-15 12:29:04 +00:00
if ( after !== undefined ) {
2022-12-25 19:21:48 +00:00
await after ( )
2022-12-15 12:29:04 +00:00
}
2022-12-10 15:01:38 +00:00
return true
2022-12-04 16:30:47 +00:00
}
}
}
2022-12-10 15:01:38 +00:00
log ( action + " action failed." )
2022-12-04 16:30:47 +00:00
}
2022-12-10 13:09:08 +00:00
// allows to check if user is following one or multiple user IDs on the home instance
2022-12-02 21:45:34 +00:00
async function isFollowingHomeInstance ( ids ) {
2022-12-06 11:04:25 +00:00
var requestUrl = 'https://' + settings . fediact _homeinstance + accountsApi + "/relationships?"
2022-12-10 13:09:08 +00:00
// build the request url with one or multiple IDs
2022-12-02 21:45:34 +00:00
for ( const id of ids ) {
// trailing & is no issue
requestUrl += "id[]=" + id . toString ( ) + "&"
}
2022-12-10 13:09:08 +00:00
// make the request
2022-12-29 15:10:59 +00:00
var responseFollowing = await requestAsyncLimited ( "GET" , requestUrl , tmpSettings . tokenheader , null )
2022-12-10 13:09:08 +00:00
// fill response array according to id amount with false
2022-12-09 14:32:23 +00:00
const follows = Array ( ids . length ) . fill ( false )
2022-12-10 13:09:08 +00:00
// parse the response
2022-12-02 21:45:34 +00:00
if ( responseFollowing ) {
2022-12-09 14:32:23 +00:00
responseFollowing = JSON . parse ( responseFollowing )
2022-12-10 13:09:08 +00:00
// iterate over ids and accounts in response
2022-12-02 21:45:34 +00:00
for ( var i = 0 ; i < ids . length ; i ++ ) {
for ( account of responseFollowing ) {
2022-12-10 13:09:08 +00:00
// check if the current account matches the id at the current index
2022-12-02 21:45:34 +00:00
if ( account . id == ids [ i ] ) {
2022-12-11 11:44:01 +00:00
if ( account . following || account . requested ) {
2022-12-10 13:09:08 +00:00
// update the response array at the given index with true if the account is already followed
2022-12-02 21:45:34 +00:00
follows [ i ] = true
}
}
}
}
}
return follows
}
2022-12-15 12:29:04 +00:00
// clear handle for comparison with mutes/blocks
function clearHandle ( handle ) {
2022-12-10 15:01:38 +00:00
// remove leading @
2022-12-11 20:05:30 +00:00
if ( handle . startsWith ( "@" ) ) {
handle = handle . slice ( 1 )
}
2022-12-10 15:01:38 +00:00
// add local uri if handle has no domain already
if ( handle . split ( "@" ) . length - 1 == 0 ) {
2022-12-18 18:02:35 +00:00
handle = handle + "@" + tmpSettings . exturi
2022-12-10 15:01:38 +00:00
}
2022-12-15 12:29:04 +00:00
return handle
}
function isBlocked ( handle ) {
handle = clearHandle ( handle )
if ( settings . fediact _blocks . includes ( handle ) ) {
2022-12-10 15:01:38 +00:00
return true
}
}
2022-12-15 12:29:04 +00:00
// check if handle is muted
function isMuted ( handle ) {
handle = clearHandle ( handle )
if ( settings . fediact _mutes . includes ( handle ) ) {
return true
}
}
// check if handle is domain blocked
function isDomainBlocked ( handle ) {
handle = clearHandle ( handle )
if ( settings . fediact _domainblocks . includes ( handle . split ( "@" ) [ 1 ] ) ) {
return true
}
}
//execute the above 3 functions on a handle
function checkAllMutedBlocked ( handle ) {
if ( isMuted ( handle ) || isBlocked ( handle ) || isDomainBlocked ( handle ) ) {
return true
}
}
2022-12-02 21:45:34 +00:00
// =-=-=-=-==-=-=-=-==-=-=-=-==-=-=
// =-=-=-=-=-= RESOLVING =-=-==-=-=
// =-=-=-=-==-=-=-=-==-=-=-=-==-=-=
2022-12-10 13:09:08 +00:00
// Return the user id on the users home instance
2022-12-02 21:45:34 +00:00
async function resolveHandleToHome ( handle ) {
2022-12-15 09:39:43 +00:00
var requestUrl = 'https://' + settings . fediact _homeinstance + accountsApi + "/search?q=" + handle + "&resolve=true&limit=1&exclude_unreviewed=false"
2022-12-29 15:10:59 +00:00
var searchResponse = await requestAsyncLimited ( "GET" , requestUrl , tmpSettings . tokenheader , null )
2022-12-02 21:45:34 +00:00
if ( searchResponse ) {
searchResponse = JSON . parse ( searchResponse )
if ( searchResponse [ 0 ] . id ) {
2022-12-10 13:09:08 +00:00
// return the first account result
2022-12-02 21:45:34 +00:00
return [ searchResponse [ 0 ] . id , searchResponse [ 0 ] . acct ]
}
}
return false
}
2022-12-10 13:09:08 +00:00
// resolve a toot to the users home instance
2022-12-05 11:07:07 +00:00
async function resolveTootToHome ( searchstring ) {
2022-12-15 09:39:43 +00:00
var requestUrl = 'https://' + settings . fediact _homeinstance + searchApi + "/?q=" + searchstring + "&resolve=true&limit=1&exclude_unreviewed=false"
2022-12-29 15:10:59 +00:00
var response = await requestAsyncLimited ( "GET" , requestUrl , tmpSettings . tokenheader , null )
2022-12-05 11:07:07 +00:00
if ( response ) {
2022-12-09 14:32:23 +00:00
response = JSON . parse ( response )
2022-12-10 13:09:08 +00:00
// do we have a status as result?
2022-12-05 11:07:07 +00:00
if ( ! response . accounts . length && response . statuses . length ) {
2022-12-09 14:32:23 +00:00
var status = response . statuses [ 0 ]
2022-12-14 13:13:27 +00:00
if ( status . poll ) {
2022-12-15 11:51:15 +00:00
return [ [ status . account . acct , status . id , status . reblogged , status . favourited , status . bookmarked , status . account . id ] , [ status . poll . id , status . poll . voted ] ]
2022-12-14 13:13:27 +00:00
} else {
// return the required status data
2022-12-15 11:51:15 +00:00
return [ [ status . account . acct , status . id , status . reblogged , status . favourited , status . bookmarked , status . account . id ] , [ false , false ] ]
2022-12-14 13:13:27 +00:00
}
2022-12-05 11:07:07 +00:00
} else {
2022-12-14 13:13:27 +00:00
return [ false , false ]
2022-12-05 11:07:07 +00:00
}
} else {
2022-12-14 13:13:27 +00:00
return [ false , false ]
2022-12-05 11:07:07 +00:00
}
}
2022-12-07 18:49:07 +00:00
// Get a toot's (external) home instance url by using the 302 redirect feature of mastodon
// we send a message with the toot url to the background script, which will perform the HEAD request
// since XMLHttpRequest/fetch do not allow access to the location header
// TODO: FALLBACK IF 302 IS NOT SUPPORTED
2022-12-02 21:45:34 +00:00
function resolveTootToExternalHome ( tooturl ) {
2022-12-07 18:49:07 +00:00
// TODO: check if a delay is necessary here too
2022-12-02 21:45:34 +00:00
if ( tooturl ) {
2022-12-08 14:23:58 +00:00
return new Promise ( async function ( resolve ) {
2022-12-08 10:08:14 +00:00
try {
2022-12-21 13:47:07 +00:00
await chrome . runtime . sendMessage ( { externaltoot : tooturl } , function ( response ) {
2022-12-08 10:08:14 +00:00
if ( response ) {
2022-12-09 14:32:23 +00:00
resolve ( response )
2022-12-08 10:08:14 +00:00
} else {
2022-12-09 14:32:23 +00:00
resolve ( false )
2022-12-08 10:08:14 +00:00
}
2022-12-09 14:32:23 +00:00
} )
2022-12-08 10:08:14 +00:00
} catch ( e ) {
2022-12-10 13:09:08 +00:00
// if we encounter an error here, it is likely since the extension context got invalidated, so reload the page
2022-12-08 15:07:37 +00:00
log ( e )
2022-12-10 13:09:08 +00:00
log ( "Reloading page, extension likely got updated or reloaded." )
2022-12-08 15:07:37 +00:00
location . reload ( )
2022-12-08 10:08:14 +00:00
}
2022-12-09 14:32:23 +00:00
} )
2022-12-02 21:45:34 +00:00
} else {
return false
}
}
2022-12-10 13:11:05 +00:00
2022-12-02 21:45:34 +00:00
// =-=-=-=-==-=-=-=-==-=-=-=-==-=-=-=
// =-=-=-=-= SITE PROCESSING =-==-=-=
// =-=-=-=-==-=-=-=-==-=-=-=-==-=-=-=
2022-12-10 13:09:08 +00:00
// custom implementation for allowing to toggle inline css
2022-12-02 21:45:34 +00:00
function toggleInlineCss ( el , styles , toggleclass ) {
2022-12-10 13:09:08 +00:00
// toggle the active class (specified) on the element (specified), then check the current state
2022-12-09 14:32:23 +00:00
var active = $ ( el ) . toggleClass ( toggleclass ) . hasClass ( toggleclass )
2022-12-10 13:09:08 +00:00
// we can have multiple styles as input, so loop through them
2022-12-02 21:45:34 +00:00
for ( var style of styles ) {
2022-12-10 13:09:08 +00:00
// if the element now has the active class...
2022-12-02 21:45:34 +00:00
if ( active ) {
2022-12-10 13:09:08 +00:00
// set the third value as style (first value / 0 is style itself)
2022-12-02 21:45:34 +00:00
$ ( el ) . css ( style [ 0 ] , style [ 2 ] )
} else {
2022-12-10 13:09:08 +00:00
// otherwise, if the second value is "!remove"...
2022-12-02 21:45:34 +00:00
if ( style [ 1 ] == "!remove" ) {
2022-12-10 13:09:08 +00:00
// remove the inline css by regex replacing
2022-12-02 21:45:34 +00:00
var newinline = replaceAll ( $ ( el ) . attr ( 'style' ) , style [ 0 ] + ": " + style [ 2 ] + ";" , "" )
$ ( el ) . attr ( 'style' , newinline )
} else {
2022-12-10 13:09:08 +00:00
// otherwise set the second value as style
2022-12-02 21:45:34 +00:00
$ ( el ) . css ( style [ 0 ] , style [ 1 ] )
}
}
}
}
2022-12-10 13:09:08 +00:00
// check if an toot identifier is already in the "processed" array
2022-12-08 14:23:58 +00:00
function isInProcessedToots ( id ) {
2022-12-10 13:09:08 +00:00
// iterate array
2022-12-18 18:02:35 +00:00
for ( var i = 0 ; i < tmpSettings . processed . length ; i ++ ) {
2022-12-10 13:09:08 +00:00
// if the the first value of the nested array at the current index matches the id we look for...
2022-12-18 18:02:35 +00:00
if ( tmpSettings . processed [ i ] [ 0 ] == id ) {
2022-12-10 13:09:08 +00:00
// return the index
2022-12-08 14:23:58 +00:00
return i
}
}
2022-12-10 13:09:08 +00:00
// if none was found...
2022-12-08 14:23:58 +00:00
return false
}
2022-12-10 13:09:08 +00:00
// add a toot to the "processed" array
2022-12-08 14:23:58 +00:00
function addToProcessedToots ( toot ) {
2022-12-10 13:09:08 +00:00
// push the array first
2022-12-18 18:02:35 +00:00
tmpSettings . processed . push ( toot )
2022-12-10 13:09:08 +00:00
// check the difference of the max elements to cache and the current length of the processed array
2022-12-18 18:02:35 +00:00
var diff = tmpSettings . processed . length - maxTootCache
2022-12-10 13:09:08 +00:00
// if diff is greater than 0...
2022-12-08 14:23:58 +00:00
if ( diff > 0 ) {
2022-12-10 13:09:08 +00:00
// remove the first diff items from it
2022-12-18 18:02:35 +00:00
tmpSettings . processed = tmpSettings . processed . splice ( 0 , diff )
2022-12-08 14:23:58 +00:00
}
2022-12-18 18:02:35 +00:00
return tmpSettings . processed . length - 1
2022-12-08 14:23:58 +00:00
}
2022-12-25 19:21:48 +00:00
function updateMutedBlocked ( ) {
return new Promise ( async function ( resolve ) {
2022-12-21 13:47:07 +00:00
try {
2022-12-25 19:21:48 +00:00
await chrome . runtime . sendMessage ( { updatemutedblocked : true } , async function ( response ) {
2022-12-21 13:47:07 +00:00
if ( response ) {
2022-12-25 19:21:48 +00:00
if ( ! await getSettings ( ) ) {
// but reload if settings are invalid
location . reload ( )
} else {
resolve ( true )
}
2022-12-21 13:47:07 +00:00
} else {
resolve ( false )
}
} )
} catch ( e ) {
// if we encounter an error here, it is likely since the extension context got invalidated, so reload the page
log ( e )
log ( "Reloading page, extension likely got updated or reloaded." )
location . reload ( )
}
} )
2022-12-15 12:29:04 +00:00
}
2022-12-15 11:51:15 +00:00
function showModal ( settings ) {
// [ [action,tootdata],[action,tootdata] ]
var baseEl = $ ( modalHtml )
var appendTo = $ ( baseEl ) . find ( "ul" )
for ( const entry of settings ) {
2022-12-22 00:16:52 +00:00
var append = "<li class='fediactmodalitem'><a class='fediactmodallink' fediactaction='" + entry [ 0 ] + "' fediactdata='" + entry [ 1 ] + "'><span>" + entry [ 2 ] + "</span></a></li>"
2022-12-15 11:51:15 +00:00
$ ( appendTo ) . append ( $ ( append ) )
}
$ ( "body" ) . append ( $ ( baseEl ) )
2022-12-20 23:10:33 +00:00
async function handleModalEvent ( e ) {
2022-12-19 10:34:02 +00:00
if ( e . originalEvent . isTrusted ) {
2022-12-25 19:21:48 +00:00
if ( $ ( e . target ) . is ( ".fediactmodal li, .fediactmodal li *" ) ) {
if ( ! $ ( e . target ) . is ( ".fediactmodal li a" ) ) {
if ( $ ( e . target ) . find ( "a" ) . length ) {
e . target = $ ( e . target ) . find ( "a" )
} else {
e . target = $ ( e . target ) . closest ( "a" )
}
2022-12-19 10:34:02 +00:00
}
var action = $ ( e . target ) . attr ( "fediactaction" )
2022-12-20 22:58:46 +00:00
var data = $ ( e . target ) . attr ( "fediactdata" )
2022-12-25 19:21:48 +00:00
var done = await executeAction ( data , action , null )
2022-12-19 10:34:02 +00:00
if ( done ) {
2022-12-22 00:16:52 +00:00
$ ( e . target ) . addClass ( "activated" )
$ ( e . target ) . append ( "<span>Done!</span>" )
$ ( baseEl ) . css ( "animation" , "fadeOut .2s .7s forwards" )
$ ( baseEl ) . find ( ".fediactmodalinner" ) . css ( "animation" , "scaleInFade .2s .7s forwards reverse" )
2022-12-20 23:10:33 +00:00
await new Promise ( resolve => {
setTimeout ( function ( ) {
resolve ( )
} , 1000 )
} )
2022-12-19 10:34:02 +00:00
$ ( baseEl ) . remove ( )
2022-12-20 23:10:33 +00:00
$ ( "body" ) . off ( "click" , handleModalEvent )
2022-12-19 10:34:02 +00:00
} else {
2022-12-22 00:25:17 +00:00
$ ( e . target ) . css ( "--confirmation" , "red" )
$ ( e . target ) . addClass ( "activated" )
2022-12-22 00:16:52 +00:00
$ ( e . target ) . append ( "<span>Failed</span>" )
$ ( baseEl ) . css ( "animation" , "fadeOut .2s .7s forwards" )
$ ( baseEl ) . find ( ".fediactmodalinner" ) . css ( "animation" , "scaleInFade .2s .7s forwards reverse" )
2022-12-20 23:10:33 +00:00
await new Promise ( resolve => {
setTimeout ( function ( ) {
resolve ( )
} , 1000 )
} )
$ ( baseEl ) . remove ( )
$ ( "body" ) . off ( "click" , handleModalEvent )
2022-12-19 10:34:02 +00:00
}
2022-12-25 19:21:48 +00:00
} else if ( $ ( e . target ) . is ( ".fediactmodalinner" ) ) {
$ . noop ( )
2022-12-19 10:34:02 +00:00
} else {
2022-12-15 11:51:15 +00:00
$ ( baseEl ) . remove ( )
2022-12-20 12:55:42 +00:00
$ ( "body" ) . off ( "click" , handleModalEvent )
2022-12-15 11:51:15 +00:00
}
}
2022-12-20 12:55:42 +00:00
}
$ ( "body" ) . on ( "click" , handleModalEvent )
2022-12-15 11:51:15 +00:00
}
2022-12-19 11:24:36 +00:00
function addFediElements ( ) {
2022-12-20 12:55:42 +00:00
if ( ! $ ( ".fediacticon" ) . length ) {
$ ( "body" ) . append ( "<div class='fediacticon'></div>" )
$ ( "body" ) . append ( "<div class='fediactsettings_onsite'><div class='fediactsettings_onsite_inner'><a href='https://" + settings . fediact _homeinstance + "' target='" + settings . fediact _target + "'>Go home</a></div></div>" )
function fediSettingsHandler ( e ) {
2022-12-21 13:47:07 +00:00
try {
if ( e . originalEvent . isTrusted ) {
if ( $ ( e . target ) . is ( "div.fediacticon" ) ) {
$ ( "div.fediacticon" ) . hide ( )
$ ( "div.fediactsettings_onsite" ) . show ( )
} else {
$ ( "div.fediactsettings_onsite" ) . hide ( )
$ ( "div.fediacticon" ) . show ( )
}
2022-12-20 12:55:42 +00:00
}
2022-12-21 13:47:07 +00:00
} catch {
$ . noop ( )
2022-12-20 12:55:42 +00:00
}
}
$ ( "body" ) . on ( "click" , fediSettingsHandler )
2022-12-19 11:24:36 +00:00
}
}
2022-12-07 18:49:07 +00:00
// trigger the reply button click - will only run when we are on a home instance url with fedireply parameter
2022-12-04 16:56:42 +00:00
async function processReply ( ) {
2022-12-10 13:09:08 +00:00
// wait for the detailed status action bar to appear
2022-12-04 16:56:42 +00:00
$ ( document ) . DOMNodeAppear ( function ( e ) {
2022-12-10 13:09:08 +00:00
// find the reply button and click it
2022-12-04 17:22:38 +00:00
$ ( e . target ) . find ( "button:has(i.fa-reply), button:has(i.fa-reply-all)" ) . click ( )
2022-12-04 16:56:42 +00:00
} , "div.detailed-status__action-bar" )
}
2022-11-21 22:47:32 +00:00
// process any toots found on supported sites
async function processToots ( ) {
2022-12-09 14:27:57 +00:00
// determine action when a button is clicked (except reply, which will always redirect)
2022-12-02 21:45:34 +00:00
function getTootAction ( e ) {
2022-12-09 17:07:13 +00:00
// set to false initially
2022-12-02 21:45:34 +00:00
var action = false
2022-12-09 17:07:13 +00:00
// check if the clicked element has a retweet icon
2022-12-02 21:45:34 +00:00
if ( $ ( e . currentTarget ) . children ( "i.fa-retweet" ) . length ) {
2022-12-09 17:07:13 +00:00
// if so, check if the retweet icon has the fediactive class (for all other buttons it will be the button element itself)
2022-12-02 21:45:34 +00:00
if ( $ ( e . currentTarget ) . children ( "i.fa-retweet" ) . hasClass ( "fediactive" ) ) {
2022-12-09 17:07:13 +00:00
// yep, has the class - so this action should be unboost
2022-12-09 14:32:23 +00:00
action = "unboost"
2022-12-02 21:45:34 +00:00
} else {
2022-12-09 17:07:13 +00:00
// nope, so it will be a boost
2022-12-09 14:32:23 +00:00
action = "boost"
2022-12-02 21:45:34 +00:00
}
2022-12-09 17:07:13 +00:00
// repeat for favourite and bookmark
2022-12-02 21:45:34 +00:00
} else if ( $ ( e . currentTarget ) . children ( "i.fa-star" ) . length ) {
if ( $ ( e . currentTarget ) . hasClass ( "fediactive" ) ) {
2022-12-09 14:32:23 +00:00
action = "unfavourite"
2022-12-02 21:45:34 +00:00
} else {
2022-12-09 14:32:23 +00:00
action = "favourite"
2022-12-02 21:45:34 +00:00
}
2022-12-04 16:30:47 +00:00
} else if ( $ ( e . currentTarget ) . children ( "i.fa-bookmark" ) . length ) {
if ( $ ( e . currentTarget ) . hasClass ( "fediactive" ) ) {
2022-12-09 14:32:23 +00:00
action = "unbookmark"
2022-12-04 16:30:47 +00:00
} else {
2022-12-09 14:32:23 +00:00
action = "bookmark"
2022-12-04 16:30:47 +00:00
}
2022-12-10 13:09:08 +00:00
// should rarely reach this point, but some v3 instances include the action in the href only, so we have this as a fallback
// (v3 public view does NOT have a bookmark button)
2022-12-02 21:45:34 +00:00
} else if ( $ ( e . currentTarget ) . attr ( "href" ) ) {
2022-12-10 13:09:08 +00:00
// does the href include "type=reblog"?
2022-12-02 21:45:34 +00:00
if ( ~ $ ( e . currentTarget ) . attr ( "href" ) . indexOf ( "type=reblog" ) ) {
2022-12-10 13:09:08 +00:00
// if so, do as above...
2022-12-02 21:45:34 +00:00
if ( $ ( e . currentTarget ) . hasClass ( "fediactive" ) ) {
2022-12-09 14:32:23 +00:00
action = "unboost"
2022-12-02 21:45:34 +00:00
} else {
2022-12-09 14:32:23 +00:00
action = "boost"
2022-12-02 21:45:34 +00:00
}
2022-12-10 13:09:08 +00:00
// repeat for favourite
2022-12-02 21:45:34 +00:00
} else if ( ~ $ ( e . currentTarget ) . attr ( "href" ) . indexOf ( "type=favourite" ) ) {
if ( $ ( e . currentTarget ) . hasClass ( "fediactive" ) ) {
2022-12-09 14:32:23 +00:00
action = "unfavourite"
2022-12-02 21:45:34 +00:00
} else {
2022-12-09 14:32:23 +00:00
action = "favourite"
2022-12-02 21:45:34 +00:00
}
}
}
return action
}
2022-12-09 14:27:57 +00:00
// some toots contain an href which can be an already resolved external link or an internal reference
function tootHrefCheck ( temp ) {
2022-12-09 17:07:13 +00:00
// is it a full url?
2022-12-09 14:27:57 +00:00
if ( temp . startsWith ( "http" ) ) {
2022-12-09 17:07:13 +00:00
// yes, create a new URL() to access its parts
2022-12-09 14:27:57 +00:00
var tempUrl = new URL ( temp )
2022-12-09 17:07:13 +00:00
// is the hostname of the URL the same as the current instance hostname?
2022-12-09 14:27:57 +00:00
if ( location . hostname == tempUrl . hostname ) {
2022-12-09 17:07:13 +00:00
// yes, so its a local toot id
2022-12-09 14:27:57 +00:00
temp = temp . split ( "/" )
2022-12-09 17:07:13 +00:00
// handle trailing / case
2022-12-09 14:27:57 +00:00
var tempLast = temp . pop ( ) || temp . pop ( )
return [ false , tempLast ]
} else {
// return full URL, since this is already a resolved link to the toot's home instance
return [ true , temp ]
}
} else {
2022-12-09 17:07:13 +00:00
// no, so it must be a local toot id as well
2022-12-09 14:27:57 +00:00
temp = temp . split ( "/" )
var tempLast = temp . pop ( ) || temp . pop ( )
return [ false , tempLast ]
}
}
// get only the toot author handle
function getTootAuthor ( el ) {
2022-12-09 17:07:13 +00:00
// find the element containing the display name and return text if found
2022-12-02 21:45:34 +00:00
if ( $ ( el ) . find ( "span.display-name__account" ) . length ) {
2022-12-09 14:27:57 +00:00
return $ ( el ) . find ( "span.display-name__account" ) . first ( ) . text ( ) . trim ( )
2022-12-02 21:45:34 +00:00
}
2022-12-09 14:27:57 +00:00
}
// check elements that can contain the local toot id and return it if found
function getTootInternalId ( el ) {
2022-12-09 17:07:13 +00:00
// detailed status wrapper - get id from current document url
2022-12-02 21:45:34 +00:00
if ( $ ( el ) . is ( ".detailed-status__wrapper" ) ) {
2022-12-07 18:49:07 +00:00
// we will use the last part of the URL path - this should be more universal than always selecting the fifth "/" slice
var temp = window . location . href . split ( "?" ) [ 0 ] . split ( "/" )
2022-12-09 14:27:57 +00:00
return ( temp . pop ( ) || temp . pop ( ) )
2022-12-09 17:07:13 +00:00
// otherwise check if current element has data-id attribute
2022-12-02 21:45:34 +00:00
} else if ( $ ( el ) . attr ( "data-id" ) ) {
2022-12-09 14:27:57 +00:00
// split by "-" to respect some ids startin with "f-"
2022-12-09 14:32:23 +00:00
return $ ( el ) . attr ( "data-id" ) . split ( "-" ) . slice ( - 1 ) [ 0 ]
2022-12-09 17:07:13 +00:00
// otherwise do the same for any closest article or div with the data-id attribute
2022-12-02 21:45:34 +00:00
} else if ( $ ( el ) . closest ( "article[data-id], div[data-id]" ) . length ) {
2022-12-09 14:32:23 +00:00
return $ ( el ) . closest ( "article[data-id], div[data-id]" ) . first ( ) . attr ( "data-id" ) . split ( "-" ) . slice ( - 1 ) [ 0 ]
2022-12-14 10:44:01 +00:00
} else if ( $ ( el ) . find ( "a.icon-button:has(i.fa-star), a.detailed-status__link:has(i.fa-star)" ) . length ) {
var hrefEl = $ ( el ) . find ( "a.icon-button:has(i.fa-star), a.detailed-status__link:has(i.fa-star)" ) . first ( )
if ( $ ( hrefEl ) . attr ( "href" ) ) {
var hrefAttr = $ ( hrefEl ) . attr ( "href" )
if ( ~ hrefAttr . indexOf ( "interact/" ) ) {
var splitted = hrefAttr . split ( "?" ) [ 0 ] . split ( "/" )
var lastpart = splitted . pop ( ) || splitted . pop ( )
return lastpart
}
}
2022-12-09 14:27:57 +00:00
}
}
// check elements that can contain an href (either resolved external link or internal reference)
function getTootExtIntHref ( el ) {
2022-12-09 17:07:13 +00:00
// for each element possibly containing an href, check if its and external fully resolved href or an internal reference and return the first found
2022-12-09 14:27:57 +00:00
if ( $ ( el ) . find ( "a.status__relative-time" ) . length ) {
return tootHrefCheck ( $ ( el ) . find ( "a.status__relative-time" ) . first ( ) . attr ( "href" ) . split ( "?" ) [ 0 ] )
} else if ( $ ( el ) . find ( "a.detailed-status__datetime" ) . length ) {
return tootHrefCheck ( $ ( el ) . find ( "a.detailed-status__datetime" ) . first ( ) . attr ( "href" ) . split ( "?" ) [ 0 ] )
2022-12-02 21:45:34 +00:00
} else if ( $ ( el ) . find ( "a.modal-button" ) . length ) {
2022-12-09 14:27:57 +00:00
return tootHrefCheck ( $ ( el ) . find ( "a.modal-button" ) . first ( ) . attr ( "href" ) . split ( "?" ) [ 0 ] )
2022-12-02 21:45:34 +00:00
}
2022-12-14 10:44:01 +00:00
return [ false , undefined ]
2022-12-02 21:45:34 +00:00
}
2022-12-10 15:01:38 +00:00
// check toot author, mentions and toot prepend mentions for applying mutes
function processMutes ( el , tootAuthor ) {
if ( settings . fediact _hidemuted ) {
var hrefs = [ ]
if ( $ ( el ) . siblings ( ".status__prepend" ) . length ) {
var prepended = $ ( el ) . siblings ( ".status__prepend" ) . first ( )
2022-12-11 11:19:46 +00:00
if ( $ ( prepended ) . find ( "a" ) . attr ( "href" ) ) {
hrefs . push ( $ ( prepended ) . find ( "a" ) . attr ( "href" ) . split ( "?" ) [ 0 ] )
}
2022-12-10 15:01:38 +00:00
}
// build array of mentions in @user@domain.com format
// NOTE: this will fail if ax external user handle uses another subdomain than hostname, but FediAct was not designed for that - this is best effort
$ ( el ) . find ( "span.h-card" ) . each ( function ( ) {
hrefs . push ( $ ( this ) . find ( "a" ) . attr ( "href" ) . split ( "?" ) [ 0 ] )
} )
var processedHrefs = [ ]
2022-12-14 10:44:01 +00:00
for ( var href of hrefs ) {
2022-12-10 15:01:38 +00:00
var splitted = href . split ( "/" )
var lastpart = splitted . pop ( ) || splitted . pop ( )
lastpart = lastpart . slice ( 1 )
if ( href . startsWith ( "http" ) ) {
var url = new URL ( href )
2022-12-18 18:02:35 +00:00
if ( url . hostname != tmpSettings . exturi && url . hostname != location . hostname ) {
2022-12-10 15:01:38 +00:00
// external handle
processedHrefs . push ( lastpart + "@" + url . hostname )
} else {
2022-12-18 18:02:35 +00:00
processedHrefs . push ( lastpart + "@" + tmpSettings . exturi )
2022-12-10 15:01:38 +00:00
}
} else {
2022-12-18 18:02:35 +00:00
processedHrefs . push ( lastpart + "@" + tmpSettings . exturi )
2022-12-10 15:01:38 +00:00
}
}
2022-12-15 12:29:04 +00:00
if ( processedHrefs . some ( r => checkAllMutedBlocked ( r ) ) || checkAllMutedBlocked ( tootAuthor ) ) {
2022-12-10 15:01:38 +00:00
$ ( el ) . hide ( )
if ( prepended ) {
$ ( prepended ) . hide ( )
}
return true
}
}
}
2022-12-09 14:27:57 +00:00
// main function to process each detected toot element
2022-12-02 21:45:34 +00:00
async function process ( el ) {
2022-12-19 11:24:36 +00:00
addFediElements ( )
2022-12-09 14:27:57 +00:00
// extra step for detailed status elements to select the correct parent
2022-12-14 10:44:01 +00:00
if ( $ ( el ) . is ( "div.detailed-status" ) && $ ( el ) . closest ( "div.focusable" ) . length ) {
2022-12-29 11:40:21 +00:00
var isDetailed = true
2022-12-07 18:49:07 +00:00
el = $ ( el ) . closest ( "div.focusable" )
}
2022-12-09 17:07:13 +00:00
// get toot data
2022-12-09 14:27:57 +00:00
var tootAuthor = getTootAuthor ( $ ( el ) )
2022-12-10 15:01:38 +00:00
// check if mutes apply and return if so
if ( processMutes ( el , tootAuthor ) ) {
return
}
2022-12-09 14:27:57 +00:00
var tootInternalId = getTootInternalId ( $ ( el ) )
var [ tootHrefIsExt , tootHrefOrId ] = getTootExtIntHref ( $ ( el ) )
2022-12-09 17:07:13 +00:00
// we will always need an internal reference to the toot, be it an actual internal toot id or the href of a toot already resolved to its home
// tootInternalId will be preferred if both are set
2022-12-09 14:27:57 +00:00
var internalIdentifier = tootInternalId || tootHrefOrId
2022-12-09 17:07:13 +00:00
// do we have one of those?
2022-12-09 14:27:57 +00:00
if ( internalIdentifier ) {
var homeResolveStrings = [ ]
2022-12-21 13:47:07 +00:00
var hasHiddenPoll = false
2022-12-09 14:27:57 +00:00
// check if id is already cached
var cacheIndex = isInProcessedToots ( internalIdentifier )
2022-12-07 18:49:07 +00:00
// get all button elements of this toot
2022-12-14 19:06:44 +00:00
var favButton = $ ( el ) . find ( "button:has(i.fa-star)" ) . first ( )
if ( ! $ ( favButton ) . length ) {
favButton = $ ( el ) . find ( "a.icon-button:has(i.fa-star), a.detailed-status__link:has(i.fa-star)" )
}
2022-12-29 11:40:21 +00:00
if ( isDetailed ) {
$ ( "<div class='detailed-status__button fediactprocessingdetailed'><span class='fediactprocessing'></span></div>" ) . insertAfter ( $ ( favButton ) . parent ( ) )
} else {
$ ( "<span class='fediactprocessing'></span>" ) . insertAfter ( $ ( favButton ) )
}
2022-12-14 19:06:44 +00:00
var boostButton = $ ( el ) . find ( "button:has(i.fa-retweet)" ) . first ( )
if ( ! $ ( boostButton ) . length ) {
boostButton = $ ( el ) . find ( "a.icon-button:has(i.fa-retweet), a.detailed-status__link:has(i.fa-retweet)" )
}
2022-12-07 18:49:07 +00:00
var bookmarkButton = $ ( el ) . find ( "button:has(i.fa-bookmark)" ) . first ( )
var replyButton = $ ( el ) . find ( "button:has(i.fa-reply), button:has(i.fa-reply-all), a.icon-button:has(i.fa-reply), a.icon-button:has(i.fa-reply-all)" ) . first ( )
2022-12-21 13:47:07 +00:00
var spoilerButton = $ ( el ) . find ( 'button[class*="show-more"]' ) . first ( )
2022-12-14 13:13:27 +00:00
var voteButton = $ ( el ) . find ( "div.poll button" ) . first ( )
2022-12-21 13:47:07 +00:00
if ( $ ( spoilerButton ) . length ) {
$ ( spoilerButton ) . click ( )
if ( $ ( el ) . find ( "div.poll" ) . length ) {
hasHiddenPoll = true
}
$ ( spoilerButton ) . click ( )
}
2022-12-18 23:52:01 +00:00
var moreButton = $ ( el ) . find ( "button:has(i.fa-ellipsis-h,i.fa-ellipsis-fw,i.fa-ellipsis-v)" ) . first ( )
2022-12-15 00:23:31 +00:00
// handles process when a vote button is clicked
2022-12-14 13:13:27 +00:00
async function pollAction ( id , redirect , e ) {
if ( settings . fediact _autoaction ) {
var pollData = {
choices : [ ]
}
var pollDiv = $ ( e . currentTarget ) . closest ( "div.poll" )
var listEls = $ ( pollDiv ) . find ( "li" )
for ( var i = 0 ; i < listEls . length ; i ++ ) {
if ( $ ( listEls [ i ] ) . find ( "span.active" ) . length ) {
pollData . choices . push ( String ( i ) )
}
}
var result = await executeAction ( id , "vote" , pollData )
if ( result ) {
$ ( e . currentTarget ) . hide ( )
2022-12-18 23:33:04 +00:00
$ ( pollDiv ) . find ( "ul" ) . replaceWith ( "<p class='fediactvoted'><a href='" + redirect + "' target='" + settings . fediact _target + "'>View the results</a> on your home instance.<p>" )
2022-12-14 13:13:27 +00:00
if ( cacheIndex ) {
2022-12-18 18:02:35 +00:00
tmpSettings . processed [ cacheIndex ] [ 10 ] = true
tmpSettings . processed [ cacheIndex ] [ 11 ] = true
2022-12-14 13:13:27 +00:00
}
}
return result
}
}
// handles process when a toot button is clicked
async function tootAction ( id , e ) {
2022-12-10 15:01:38 +00:00
if ( settings . fediact _autoaction ) {
// determine the action to perform
var action = getTootAction ( e )
if ( action ) {
// resolve url on home instance to get local toot/author identifiers and toot status
2022-12-14 13:13:27 +00:00
var actionExecuted = await executeAction ( id , action , null )
2022-12-10 15:01:38 +00:00
if ( actionExecuted ) {
2022-12-15 00:23:31 +00:00
if ( cacheIndex ) {
2022-12-29 15:47:09 +00:00
console . log ( cacheIndex )
console . log ( tmpSettings . processed [ cacheIndex ] )
console . log ( tmpSettings . processed )
2022-12-15 00:23:31 +00:00
// set interacted to true
2022-12-18 18:02:35 +00:00
tmpSettings . processed [ cacheIndex ] [ 11 ] = true
2022-12-15 00:23:31 +00:00
}
2022-12-10 15:01:38 +00:00
// if the action was successfully executed, update the element styles
if ( action == "boost" || action == "unboost" ) {
// toggle inline css styles
2022-12-12 09:25:42 +00:00
toggleInlineCss ( $ ( e . currentTarget ) , [ [ "color" , "!remove" , "rgb(140, 141, 255)" ] ] , "fediactive" )
toggleInlineCss ( $ ( e . currentTarget ) . find ( "i" ) , [ [ "transition-duration" , "!remove" , "0.9s" ] , [ "background-position" , "!remove" , "0px 100%" ] ] , "fediactive" )
2022-12-10 15:01:38 +00:00
// update element in cache if exists
if ( cacheIndex ) {
2022-12-18 18:02:35 +00:00
tmpSettings . processed [ cacheIndex ] [ 3 ] = ! tmpSettings . processed [ cacheIndex ] [ 3 ]
2022-12-10 15:01:38 +00:00
}
// same for favourite, bookmarked....
} else if ( action == "favourite" || action == "unfavourite" ) {
toggleInlineCss ( $ ( e . currentTarget ) , [ [ "color" , "!remove" , "rgb(202, 143, 4)" ] ] , "fediactive" )
2022-12-12 09:25:42 +00:00
toggleInlineCss ( $ ( e . currentTarget ) . find ( "i" ) , [ [ "animation" , "spring-rotate-out 1s linear" , "spring-rotate-in 1s linear" ] ] , "fediactive" )
2022-12-10 15:01:38 +00:00
if ( cacheIndex ) {
2022-12-18 18:02:35 +00:00
tmpSettings . processed [ cacheIndex ] [ 4 ] = ! tmpSettings . processed [ cacheIndex ] [ 4 ]
2022-12-10 15:01:38 +00:00
}
} else {
toggleInlineCss ( $ ( e . currentTarget ) , [ [ "color" , "!remove" , "rgb(255, 80, 80)" ] ] , "fediactive" )
if ( cacheIndex ) {
2022-12-18 18:02:35 +00:00
tmpSettings . processed [ cacheIndex ] [ 5 ] = ! tmpSettings . processed [ cacheIndex ] [ 5 ]
2022-12-10 15:01:38 +00:00
}
2022-12-14 01:14:26 +00:00
}
2022-12-10 15:01:38 +00:00
return true
2022-12-08 14:23:58 +00:00
} else {
2022-12-10 15:01:38 +00:00
log ( "Could not execute action on home instance." )
}
2022-12-08 14:23:58 +00:00
} else {
2022-12-10 15:01:38 +00:00
log ( "Could not determine action." )
2022-12-08 14:23:58 +00:00
}
} else {
2022-12-10 15:01:38 +00:00
log ( "Auto-action disabled." )
return true
2022-12-08 14:23:58 +00:00
}
}
2022-12-09 17:07:13 +00:00
// handles initialization of element styles
2022-12-08 14:23:58 +00:00
function initStyles ( tootdata ) {
2022-12-09 17:07:13 +00:00
// always remove any existing "Unresolved" indicator from the element first
2022-12-29 11:40:21 +00:00
$ ( el ) . find ( ".fediactunresolveddetailed, .fediactunresolved" ) . remove ( )
$ ( el ) . find ( ".fediactprocessingdetailed, .fediactprocessing" ) . remove ( )
2022-12-09 17:07:13 +00:00
// is the toot unresolved?
2022-12-08 15:07:37 +00:00
if ( ! tootdata [ 1 ] ) {
2022-12-09 17:07:13 +00:00
// yes, then add the Unresolved indicator
2022-12-29 11:40:21 +00:00
if ( isDetailed ) {
$ ( "<div class='detailed-status__button fediactunresolveddetailed'><span class='fediactunresolved'>X</span></div>" ) . insertAfter ( $ ( favButton ) . parent ( ) )
} else {
$ ( "<span class='fediactunresolved'>X</span>" ) . insertAfter ( $ ( favButton ) )
}
2022-12-08 15:07:37 +00:00
} else {
2022-12-15 00:23:31 +00:00
// otherwise start processing button styles (if enabled OR if the toot was already interacted with, to restore the state while still on the same page)
2022-12-09 17:07:13 +00:00
// first enable the bookmark button (is disabled on external instances)
2022-12-08 15:07:37 +00:00
$ ( bookmarkButton ) . removeClass ( "disabled" ) . removeAttr ( "disabled" )
2022-12-15 11:51:15 +00:00
$ ( moreButton ) . removeClass ( "disabled" ) . removeAttr ( "disabled" )
2022-12-21 13:47:07 +00:00
// special care for polls that are hidden behind a CW
if ( tootdata [ 13 ] ) {
// click initially to show content
$ ( spoilerButton ) . click ( )
$ ( spoilerButton ) . find ( "span" ) . text ( "Show less" )
// set voteButton
voteButton = $ ( el ) . find ( "div.poll button" ) . first ( )
// set handling for all new clicks
$ ( spoilerButton ) . on ( "click" , function ( e ) {
// prevent default etc.
e . preventDefault ( )
e . stopImmediatePropagation ( )
var spanText = $ ( spoilerButton ) . find ( "span" )
if ( $ ( spanText ) . text ( ) == "Show less" ) {
$ ( spanText ) . text ( "Show more" )
} else {
$ ( spanText ) . text ( "Show less" )
}
// toggle the css manually to hide/show the content/poll
toggleInlineCss ( $ ( el ) . find ( "div.poll" ) . first ( ) , [ [ "display" , "block" , "none" ] ] , "fedihideshow" )
toggleInlineCss ( $ ( el ) . find ( "div.status__content__text" ) . first ( ) , [ [ "display" , "block" , "none" ] ] , "fedihideshow" )
} )
// click again so it is hidden by default, like usually
$ ( spoilerButton ) . click ( )
}
2022-12-14 13:13:27 +00:00
$ ( voteButton ) . removeAttr ( "disabled" )
2022-12-18 22:03:26 +00:00
// set the toot buttons to active, depending on the state of the resolved toot and if the element already has the active class
if ( tootdata [ 4 ] ) {
if ( ! $ ( favButton ) . hasClass ( "fediactive" ) ) {
toggleInlineCss ( $ ( favButton ) , [ [ "color" , "!remove" , "rgb(202, 143, 4)" ] ] , "fediactive" )
toggleInlineCss ( $ ( favButton ) . find ( "i" ) , [ [ "animation" , "spring-rotate-out 1s linear" , "spring-rotate-in 1s linear" ] ] , "fediactive" )
2022-12-08 15:07:37 +00:00
}
2022-12-18 22:03:26 +00:00
}
// repeat for other buttons
if ( tootdata [ 3 ] ) {
if ( ! $ ( boostButton ) . find ( "i.fediactive" ) . length ) {
toggleInlineCss ( $ ( boostButton ) , [ [ "color" , "!remove" , "rgb(140, 141, 255)" ] ] , "fediactive" )
toggleInlineCss ( $ ( boostButton ) . find ( "i" ) , [ [ "transition-duration" , "!remove" , "0.9s" ] , [ "background-position" , "!remove" , "0px 100%" ] ] , "fediactive" )
2022-12-15 00:23:31 +00:00
}
2022-12-18 22:03:26 +00:00
}
if ( tootdata [ 5 ] ) {
if ( ! $ ( bookmarkButton ) . hasClass ( "fediactive" ) ) {
toggleInlineCss ( $ ( bookmarkButton ) , [ [ "color" , "!remove" , "rgb(255, 80, 80)" ] ] , "fediactive" )
2022-12-08 15:07:37 +00:00
}
2022-12-14 13:13:27 +00:00
}
2022-12-18 22:03:26 +00:00
if ( tootdata [ 10 ] ) {
$ ( voteButton ) . hide ( )
2022-12-18 23:33:04 +00:00
$ ( voteButton ) . closest ( "div.poll" ) . find ( "ul" ) . replaceWith ( "<p class='fediactvoted'><a href='" + tootdata [ 7 ] + "' target='" + settings . fediact _target + "'>View the results</a> on your home instance.<p>" )
2022-12-18 22:03:26 +00:00
}
2022-12-07 18:49:07 +00:00
}
}
2022-12-09 17:07:13 +00:00
// handles binding of clicks events for all buttons of a toot
2022-12-08 14:23:58 +00:00
function clickBinder ( tootdata ) {
2022-12-18 22:03:26 +00:00
var domainsplit = tootdata [ 1 ] . split ( "@" )
var domain = domainsplit . pop ( ) || domainsplit . pop ( )
2022-12-09 17:07:13 +00:00
// reply button is simple, it will always redirect to the homeinstance with the fedireply parameter set
2022-12-07 18:49:07 +00:00
$ ( replyButton ) . on ( "click" , function ( e ) {
2022-12-09 17:07:13 +00:00
// prevent default and immediate propagation
2022-12-09 14:32:23 +00:00
e . preventDefault ( )
e . stopImmediatePropagation ( )
2022-12-19 10:34:02 +00:00
if ( e . originalEvent . isTrusted ) {
// redirect to the resolved URL + fedireply parameter (so the extension can handle it after redirect)
redirectTo ( tootdata [ 7 ] + "?fedireply" )
}
2022-12-15 11:51:15 +00:00
} )
$ ( moreButton ) . on ( "click" , function ( e ) {
// prevent default and immediate propagation
e . preventDefault ( )
e . stopImmediatePropagation ( )
2022-12-19 10:34:02 +00:00
if ( e . originalEvent . isTrusted ) {
var modalLinks = [ ]
if ( isBlocked ( tootdata [ 1 ] ) ) {
2022-12-20 22:58:46 +00:00
modalLinks . push ( [ "unblock" , tootdata [ 6 ] , "Unblock user" ] )
2022-12-19 10:34:02 +00:00
} else {
2022-12-20 22:58:46 +00:00
modalLinks . push ( [ "block" , tootdata [ 6 ] , "Block user" ] )
2022-12-19 10:34:02 +00:00
}
if ( isMuted ( tootdata [ 1 ] ) ) {
2022-12-20 22:58:46 +00:00
modalLinks . push ( [ "unmute" , tootdata [ 6 ] , "Unmute user" ] )
2022-12-19 10:34:02 +00:00
} else {
2022-12-20 22:58:46 +00:00
modalLinks . push ( [ "mute" , tootdata [ 6 ] , "Mute user" ] )
2022-12-19 10:34:02 +00:00
}
if ( isDomainBlocked ( tootdata [ 1 ] ) ) {
2022-12-20 22:58:46 +00:00
modalLinks . push ( [ "domainunblock" , domain , "Unblock domain" ] )
2022-12-19 10:34:02 +00:00
} else {
2022-12-20 22:58:46 +00:00
modalLinks . push ( [ "domainblock" , domain , "Block domain" ] )
2022-12-19 10:34:02 +00:00
}
2022-12-20 22:58:46 +00:00
modalLinks . push ( [ "copy" , tootdata [ 12 ] , "Copy URL" ] )
modalLinks . push ( [ "copy" , tootdata [ 7 ] , "Copy home URL" ] )
2022-12-19 10:34:02 +00:00
showModal ( modalLinks )
2022-12-15 12:29:04 +00:00
}
2022-12-07 18:49:07 +00:00
} )
2022-12-09 17:07:13 +00:00
// for all other buttons...
2022-12-14 13:13:27 +00:00
$ ( [ favButton , boostButton , bookmarkButton , voteButton ] ) . each ( function ( ) {
if ( $ ( voteButton ) . length ) {
if ( $ ( voteButton ) . get ( 0 ) . isEqualNode ( $ ( this ) . get ( 0 ) ) ) {
var isVote = true
}
}
2022-12-09 17:07:13 +00:00
// these behave differently with single / double click
// we use a custom solution for handling dblclick since the default event does not work here
// init function global vars required for single/double click handling
2022-12-09 14:32:23 +00:00
var clicks = 0
var timer
2022-12-07 18:49:07 +00:00
$ ( this ) . on ( "click" , async function ( e ) {
// prevent default and immediate propagation
2022-12-09 14:32:23 +00:00
e . preventDefault ( )
e . stopImmediatePropagation ( )
2022-12-19 10:34:02 +00:00
if ( e . originalEvent . isTrusted ) {
// increase click counter
clicks ++
// this will always run, but see below for double click handling
if ( clicks == 1 ) {
timer = setTimeout ( async function ( ) {
if ( isVote && ! tootdata [ 10 ] ) {
var actionExecuted = pollAction ( tootdata [ 9 ] , tootdata [ 7 ] , e )
} else {
// execute action on click and get result (fail/success)
var actionExecuted = await tootAction ( tootdata [ 2 ] , e )
}
if ( ! actionExecuted ) {
log ( "Action failed." )
}
// reset clicks
clicks = 0
} , 350 )
} else {
// if we get here, the element was clicked twice before the above timeout was over, so this is a double click
// reset the above timeout so it wont execute
clearTimeout ( timer )
if ( isVote ) {
2022-12-15 11:51:15 +00:00
var actionExecuted = pollAction ( tootdata [ 9 ] , tootdata [ 7 ] , e )
2022-12-14 13:13:27 +00:00
} else {
// execute action on click and get result (fail/success)
var actionExecuted = await tootAction ( tootdata [ 2 ] , e )
}
2022-12-05 11:07:07 +00:00
if ( ! actionExecuted ) {
log ( "Action failed." )
2022-12-19 10:34:02 +00:00
} else {
// redirect to home instance with the resolved toot url
redirectTo ( tootdata [ 7 ] )
2022-12-04 16:30:47 +00:00
}
2022-12-09 17:07:13 +00:00
// reset clicks
2022-12-09 14:32:23 +00:00
clicks = 0
2022-12-14 13:13:27 +00:00
}
2022-12-07 18:49:07 +00:00
}
} ) . on ( "dblclick" , function ( e ) {
// default dblclick event must be prevented
2022-12-09 14:32:23 +00:00
e . preventDefault ( )
e . stopImmediatePropagation ( )
} )
} )
2022-12-07 18:49:07 +00:00
}
2022-12-09 14:27:57 +00:00
// if element is not in cache, resolve it
2022-12-08 14:23:58 +00:00
if ( ! cacheIndex ) {
2022-12-09 17:07:13 +00:00
// always add the already resolved external toot href first, if it was set
2022-12-09 14:27:57 +00:00
if ( tootHrefIsExt ) {
homeResolveStrings . push ( tootHrefOrId )
}
2022-12-09 17:07:13 +00:00
// we can only process internalTootIds if we also have a user handle
2022-12-09 14:27:57 +00:00
if ( tootAuthor ) {
2022-12-07 18:49:07 +00:00
// get handle/handledomain without @
2022-12-09 14:27:57 +00:00
var matches = tootAuthor . match ( handleExtractUrlRegex )
var [ isExternalHandle , extHomeResolved ] = [ false , false ]
2022-12-07 18:49:07 +00:00
// if we have a handledomain...
if ( matches . groups . handledomain ) {
// check if the current hostname includes that handle domain...
2022-12-09 14:27:57 +00:00
if ( ! ( ~ location . hostname . indexOf ( matches . groups . handledomain ) ) ) {
isExternalHandle = true
}
}
// add ids
var internalTootIds = [ tootInternalId ]
if ( ! tootHrefIsExt ) {
internalTootIds . push ( tootHrefOrId )
}
// filter duplicates and undefined values (shorter than checking with if clauses when adding...)
internalTootIds = internalTootIds . filter ( ( element , index ) => {
return ( element !== undefined && internalTootIds . indexOf ( element ) == index )
} )
// loop through internal ids (will be only 1 normally, but we want to maximize our chances for resolving later on)
for ( var internalTootId of internalTootIds ) {
// if its not an external handle...
if ( ! isExternalHandle ) {
// add resolve strings for both formats on the current external instance
homeResolveStrings . push ( location . protocol + "//" + location . hostname + "/users/" + matches . groups . handle + "/statuses/" + internalTootId )
homeResolveStrings . push ( location . protocol + "//" + location . hostname + "/@" + matches . groups . handle + "/" + internalTootId )
// otherwise, start external resolve process if not done already for one of the internalTootIds
} else if ( ! extHomeResolved ) {
var extResolveString = location . protocol + '//' + location . hostname + "/" + tootAuthor + "/" + internalTootId
var resolveTootHome = await resolveTootToExternalHome ( extResolveString )
2022-12-07 18:49:07 +00:00
if ( resolveTootHome ) {
2022-12-09 14:27:57 +00:00
// update var so next tootid will not be resolved externally, if any more
extHomeResolved = true
// always push the originally returned url
homeResolveStrings . push ( resolveTootHome )
// if it matches the URI format, also add the @ format
if ( handleExtractUriRegex . test ( resolveTootHome ) ) {
var tmpmatches = resolveTootHome . match ( handleExtractUriRegex )
if ( tmpmatches . groups . handle && tmpmatches . groups . tootid && tmpmatches . groups . domain ) {
homeResolveStrings . push ( tmpmatches . groups . domain + "/@" + tmpmatches . groups . handle + "/" + tmpmatches . groups . tootid )
}
// otherwise, if it matches the @ format, also add the URI format
} else if ( handleExtractUrlRegex . test ( resolveTootHome ) ) {
var tmpmatches = resolveTootHome . match ( handleExtractUrlRegex )
if ( tmpmatches . groups . handle && tmpmatches . groups . tootid && tmpmatches . groups . domain ) {
homeResolveStrings . push ( tmpmatches . groups . domain + "/users/" + tmpmatches . groups . handle + "/statuses/" + tmpmatches . groups . tootid )
2022-12-07 18:49:07 +00:00
}
}
}
2022-12-09 15:34:38 +00:00
// always add fallback to current external instance URL (for external handles, there is no /users/... format)
homeResolveStrings . push ( location . protocol + "//" + location . hostname + "/" + tootAuthor + "/" + internalTootId )
2022-12-07 18:49:07 +00:00
}
}
}
2022-12-09 17:14:48 +00:00
// if we have any resolve strings to resolve on our home instance...
2022-12-09 14:27:57 +00:00
if ( homeResolveStrings . length ) {
2022-12-09 17:14:48 +00:00
// filter duplicates
2022-12-09 14:27:57 +00:00
homeResolveStrings = homeResolveStrings . filter ( ( element , index ) => {
return ( homeResolveStrings . indexOf ( element ) == index )
} )
2022-12-09 17:14:48 +00:00
// initialize with false
2022-12-09 14:27:57 +00:00
var resolvedToHomeInstance = false
2022-12-09 17:14:48 +00:00
// for each resolve string...
2022-12-09 14:27:57 +00:00
for ( var homeResolveString of homeResolveStrings ) {
2022-12-09 17:14:48 +00:00
// run only if not already resolved
2022-12-09 14:27:57 +00:00
if ( ! resolvedToHomeInstance ) {
// resolve toot on actual home instance
2022-12-15 11:51:15 +00:00
var [ resolvedToot , poll ] = await resolveTootToHome ( homeResolveString ) // [status.account.acct, status.id, status.reblogged, status.favourited, status.bookmarked, status.account.id], [pollid/false, voted]
2022-12-09 14:27:57 +00:00
if ( resolvedToot ) {
2022-12-09 17:14:48 +00:00
// if successful, set condition to true (so it will not be resolved twice)
2022-12-09 14:27:57 +00:00
resolvedToHomeInstance = true
// set the redirect to home instance URL in @ format
var redirectUrl = 'https://' + settings . fediact _homeinstance + "/@" + resolvedToot [ 0 ] + "/" + resolvedToot [ 1 ]
2022-12-09 17:14:48 +00:00
// prepare the cache entry / toot data entry
2022-12-21 13:47:07 +00:00
var fullEntry = [ internalIdentifier , ... resolvedToot , redirectUrl , true , ... poll , false , homeResolveString , hasHiddenPoll ]
// 0: internal identifier; 1: toot home acct / false 2: toot home id 3: toot reblogged 4: toot favourited 5: toot bookmarked 6: home account id
// 7: redirect url 8: ??? crap! 9: poll id / false 10: poll voted 11: interacted 12: original URL that was resolved 13: has hidden poll?
2022-12-09 14:27:57 +00:00
}
}
}
2022-12-09 17:14:48 +00:00
// was any resolve successful?
2022-12-09 14:27:57 +00:00
if ( resolvedToHomeInstance ) {
2022-12-09 17:14:48 +00:00
// yes, so add to processed toots with the full toot data entry
2022-12-14 01:14:26 +00:00
cacheIndex = addToProcessedToots ( fullEntry )
2022-12-09 17:14:48 +00:00
// ... and init styles
2022-12-08 14:23:58 +00:00
initStyles ( fullEntry )
2022-12-14 01:14:26 +00:00
// continue with click handling...
clickBinder ( fullEntry )
2022-12-07 18:49:07 +00:00
} else {
2022-12-09 17:14:48 +00:00
// no, but we will still add the toot to cache as unresolved
2022-12-09 14:27:57 +00:00
log ( "Failed to resolve: " + homeResolveStrings )
2022-12-14 01:14:26 +00:00
cacheIndex = addToProcessedToots ( [ internalIdentifier , false ] )
2022-12-09 14:27:57 +00:00
initStyles ( [ internalIdentifier , false ] )
2022-12-07 18:49:07 +00:00
}
} else {
2022-12-09 17:14:48 +00:00
// no resolve possible without any resolve strings, but we will still add the toot to cache as unresolved
2022-12-07 18:49:07 +00:00
log ( "Could not identify a post URI for home resolving." )
2022-12-14 01:14:26 +00:00
cacheIndex = addToProcessedToots ( [ internalIdentifier , false ] )
2022-12-09 14:27:57 +00:00
initStyles ( [ internalIdentifier , false ] )
2022-12-02 21:45:34 +00:00
}
2022-11-21 22:47:32 +00:00
} else {
2022-12-09 17:14:48 +00:00
// the toot is already in cache, so grab it
2022-12-18 18:02:35 +00:00
var toot = tmpSettings . processed [ cacheIndex ]
2022-12-09 17:14:48 +00:00
// init stylings
2022-12-08 14:23:58 +00:00
initStyles ( toot )
2022-12-09 17:14:48 +00:00
// if it is NOT unresolved, bind click handlers again
2022-12-08 15:07:37 +00:00
if ( toot [ 1 ] ) {
clickBinder ( toot )
}
2022-11-21 22:47:32 +00:00
}
2022-12-02 21:45:34 +00:00
} else {
log ( "Could not get toot data." )
}
}
2022-12-07 18:49:07 +00:00
// One DOMNodeAppear to rule them all
$ ( document ) . DOMNodeAppear ( async function ( e ) {
2022-12-18 18:02:35 +00:00
if ( ! tmpSettings . isProcessing . includes ( $ ( e . target ) . get ( 0 ) ) ) {
tmpSettings . isProcessing . push ( $ ( e . target ) . get ( 0 ) )
2022-12-11 14:55:09 +00:00
process ( $ ( e . target ) )
}
2022-12-09 14:32:23 +00:00
} , "div.status, div.detailed-status" )
2022-12-11 14:55:09 +00:00
// try to find all existing elements (fixes some elements not being detected by DOMNodeAppear in rare cases, esp. v3)
$ ( document ) . find ( "div.status, div.detailed-status" ) . each ( function ( ) {
2022-12-18 18:02:35 +00:00
if ( ! tmpSettings . isProcessing . includes ( $ ( this ) . get ( 0 ) ) ) {
tmpSettings . isProcessing . push ( $ ( this ) . get ( 0 ) )
2022-12-11 14:55:09 +00:00
process ( $ ( this ) )
}
} )
2022-11-21 22:47:32 +00:00
}
2022-11-18 13:20:22 +00:00
2022-12-19 11:24:36 +00:00
// main function to process profile views / follow buttons
async function processProfile ( ) {
2022-12-02 21:45:34 +00:00
// for mastodon v3 - v4 does not show follow buttons / account cards on /explore
async function process ( el ) {
2022-12-19 11:24:36 +00:00
addFediElements ( )
2022-12-19 15:04:23 +00:00
var fullHandle , icon
2022-12-11 11:44:01 +00:00
var action = "follow"
2022-12-18 23:52:01 +00:00
var moreButton = $ ( el ) . siblings ( "button:has(i.fa-ellipsis-fw,i.fa-ellipsis-v,i.fa-ellipsis-h)" )
2022-12-08 10:08:14 +00:00
// wrapper for follow/unfollow action
2022-12-08 15:07:37 +00:00
async function execFollow ( id ) {
2022-12-10 15:01:38 +00:00
if ( settings . fediact _autoaction ) {
// execute action and save result
2022-12-14 13:13:27 +00:00
var response = await executeAction ( id , action , null )
2022-12-10 15:01:38 +00:00
// if action was successful, update button text and action value according to performed action
if ( action == "follow" && response ) {
2022-12-19 15:04:23 +00:00
if ( $ ( icon ) . length ) {
$ ( icon ) . removeClass ( "fa-user-plus" ) . addClass ( "fa-user" )
$ ( el ) . append ( "-" )
$ ( el ) . attr ( "title" , "Unfollow" )
} else {
$ ( el ) . text ( "Unfollow" )
}
2022-12-10 15:01:38 +00:00
action = "unfollow"
return true
// repeat for unfollow action
} else if ( action == "unfollow" && response ) {
2022-12-19 15:04:23 +00:00
if ( $ ( icon ) . length ) {
$ ( icon ) . removeClass ( "fa-user" ) . addClass ( "fa-user-plus" )
2022-12-20 22:58:46 +00:00
$ ( el ) . contents ( ) . filter ( ( _ , node ) => node . nodeType === 3 ) . remove ( )
2022-12-19 15:04:23 +00:00
$ ( el ) . attr ( "title" , "Follow" )
} else {
$ ( el ) . text ( "Follow" )
}
2022-12-10 15:01:38 +00:00
action = "follow"
return true
}
} else {
log ( "Auto-action disabled." )
2022-12-10 13:09:08 +00:00
return true
2022-12-08 10:08:14 +00:00
}
}
2022-12-02 21:45:34 +00:00
// for mastodon v3 explore page
if ( $ ( el ) . closest ( "div.account-card" ) . length ) {
fullHandle = $ ( el ) . closest ( "div.account-card" ) . find ( "div.display-name > span" ) . text ( ) . trim ( )
2022-12-19 15:04:23 +00:00
} else if ( $ ( el ) . closest ( "div.directory__card" ) . length ) {
fullHandle = $ ( el ) . closest ( "div.directory__card" ) . find ( "div.display-name > span" ) . text ( ) . trim ( )
icon = $ ( el ) . find ( "i" ) . first ( )
2022-12-02 21:45:34 +00:00
} else {
// for all other pages, where only one of the selection elements is present
for ( const selector of profileNamePaths ) {
if ( $ ( selector ) . length ) {
fullHandle = $ ( selector ) . text ( ) . trim ( )
2022-12-13 13:30:24 +00:00
if ( fullHandle . split ( "@" ) . length - 1 == 1 ) {
2022-12-18 18:02:35 +00:00
fullHandle = fullHandle + "@" + tmpSettings . exturi
2022-12-13 13:30:24 +00:00
}
2022-12-02 21:45:34 +00:00
break
2022-11-26 01:40:41 +00:00
}
2022-12-02 21:45:34 +00:00
}
}
2022-12-09 17:14:48 +00:00
// do we have a full handle?
2022-12-02 21:45:34 +00:00
if ( fullHandle ) {
2022-12-18 18:02:35 +00:00
if ( ! tmpSettings . processedFollow . includes ( fullHandle ) ) {
2022-12-24 03:26:58 +00:00
$ ( "<span class='fediactprocessing'></span>" ) . insertBefore ( $ ( el ) )
2022-12-11 14:55:09 +00:00
// yes, so resolve it to a user id on our homeinstance
var resolvedHandle = await resolveHandleToHome ( fullHandle )
if ( resolvedHandle ) {
2022-12-18 18:02:35 +00:00
tmpSettings . processedFollow . push ( fullHandle )
2022-12-18 23:55:29 +00:00
if ( $ ( moreButton ) . length ) {
$ ( moreButton ) . removeClass ( "disabled" ) . removeAttr ( "disabled" )
}
2022-12-18 22:03:26 +00:00
var domainsplit = fullHandle . split ( "@" )
var domain = domainsplit . pop ( ) || domainsplit . pop ( )
2022-12-20 22:58:46 +00:00
var redirectUrl = 'https://' + settings . fediact _homeinstance + '/@' + resolvedHandle [ 1 ]
2022-12-11 14:55:09 +00:00
// successfully resolved
2022-12-18 22:03:26 +00:00
// ... then check if user is already following
var isFollowing = await isFollowingHomeInstance ( [ resolvedHandle [ 0 ] ] )
// update button text and action if already following
if ( isFollowing [ 0 ] ) {
2022-12-19 15:04:23 +00:00
if ( $ ( icon ) . length ) {
$ ( icon ) . removeClass ( "fa-user-plus" ) . addClass ( "fa-user" )
$ ( el ) . append ( "-" )
$ ( el ) . attr ( "title" , "Unfollow" )
} else {
$ ( el ) . text ( "Unfollow" )
}
2022-12-18 22:03:26 +00:00
action = "unfollow"
2022-12-02 21:45:34 +00:00
}
2022-12-18 22:03:26 +00:00
$ ( moreButton ) . on ( "click" , function ( e ) {
// prevent default and immediate propagation
e . preventDefault ( )
e . stopImmediatePropagation ( )
2022-12-19 10:34:02 +00:00
if ( e . originalEvent . isTrusted ) {
var modalLinks = [ ]
if ( isBlocked ( fullHandle ) ) {
2022-12-20 22:58:46 +00:00
modalLinks . push ( [ "unblock" , resolvedHandle [ 0 ] , "Unblock user" ] )
2022-12-19 10:34:02 +00:00
} else {
2022-12-20 22:58:46 +00:00
modalLinks . push ( [ "block" , resolvedHandle [ 0 ] , "Block user" ] )
2022-12-19 10:34:02 +00:00
}
if ( isMuted ( fullHandle ) ) {
2022-12-20 22:58:46 +00:00
modalLinks . push ( [ "unmute" , resolvedHandle [ 0 ] , "Unmute user" ] )
2022-12-19 10:34:02 +00:00
} else {
2022-12-20 22:58:46 +00:00
modalLinks . push ( [ "mute" , resolvedHandle [ 0 ] , "Mute user" ] )
2022-12-19 10:34:02 +00:00
}
if ( isDomainBlocked ( fullHandle ) ) {
2022-12-20 22:58:46 +00:00
modalLinks . push ( [ "domainunblock" , domain , "Unblock domain" ] )
2022-12-19 10:34:02 +00:00
} else {
2022-12-20 22:58:46 +00:00
modalLinks . push ( [ "domainblock" , domain , "Block domain" ] )
2022-12-19 10:34:02 +00:00
}
2022-12-20 22:58:46 +00:00
modalLinks . push ( [ "copy" , redirectUrl , "Copy home URL" ] )
2022-12-19 10:34:02 +00:00
showModal ( modalLinks )
2022-12-18 22:03:26 +00:00
}
} )
2022-12-11 14:55:09 +00:00
// single and double click handling (see toot processing for explanation, is the same basically)
var clicks = 0
var timer
$ ( el ) . on ( "click" , async function ( e ) {
// prevent default and immediate propagation
e . preventDefault ( )
e . stopImmediatePropagation ( )
2022-12-19 10:34:02 +00:00
if ( e . originalEvent . isTrusted ) {
clicks ++
if ( clicks == 1 ) {
timer = setTimeout ( async function ( ) {
execFollow ( resolvedHandle [ 0 ] )
clicks = 0
} , 350 )
2022-12-11 14:55:09 +00:00
} else {
2022-12-19 10:34:02 +00:00
clearTimeout ( timer )
var done = await execFollow ( resolvedHandle [ 0 ] )
if ( done ) {
2022-12-19 15:04:23 +00:00
if ( $ ( icon ) . length ) {
var classes = $ ( icon ) . attr ( "class" )
$ ( icon ) . removeClass ( "fa-user" ) . removeClass ( "fa-user-plus" ) . addClass ( "fa-arrow-right" )
} else {
var saveText = $ ( el ) . text ( )
$ ( el ) . text ( "Redirecting..." )
}
2022-12-19 10:34:02 +00:00
setTimeout ( function ( ) {
redirectTo ( redirectUrl )
2022-12-19 15:04:23 +00:00
if ( $ ( icon ) . length ) {
$ ( icon ) . attr ( "class" , classes )
} else {
$ ( el ) . text ( saveText )
}
2022-12-19 10:34:02 +00:00
} , 1000 )
} else {
log ( "Action failed." )
}
clicks = 0
2022-12-11 14:55:09 +00:00
}
2022-11-22 10:00:02 +00:00
}
2022-12-11 14:55:09 +00:00
} ) . on ( "dblclick" , function ( e ) {
e . preventDefault ( )
e . stopImmediatePropagation ( )
} )
} else {
log ( "Could not resolve user home ID." )
}
2022-12-18 23:33:04 +00:00
$ ( el ) . siblings ( ".fediactprocessing" ) . remove ( )
2022-11-21 22:47:32 +00:00
}
2022-12-02 21:45:34 +00:00
}
}
2022-12-08 10:08:14 +00:00
// create css selector from selector array
2022-12-07 21:17:49 +00:00
var allFollowPaths = followButtonPaths . join ( "," )
2022-12-08 10:08:14 +00:00
// one domnodeappear to rule them all
2022-12-07 21:17:49 +00:00
$ ( document ) . DOMNodeAppear ( async function ( e ) {
2022-12-18 18:02:35 +00:00
if ( ! tmpSettings . isProcessing . includes ( $ ( e . target ) . get ( 0 ) ) ) {
tmpSettings . isProcessing . push ( $ ( e . target ) . get ( 0 ) )
2022-12-11 14:55:09 +00:00
process ( $ ( e . target ) )
}
2022-12-07 21:17:49 +00:00
} , allFollowPaths )
2022-12-11 14:55:09 +00:00
// try to find all existing elements (fixes some elements not being detected by DOMNodeAppear in rare cases, esp. v3)
$ ( document ) . find ( allFollowPaths ) . each ( function ( ) {
2022-12-18 18:02:35 +00:00
if ( ! tmpSettings . isProcessing . includes ( $ ( this ) . get ( 0 ) ) ) {
tmpSettings . isProcessing . push ( $ ( this ) . get ( 0 ) )
2022-12-11 14:55:09 +00:00
process ( $ ( this ) )
}
} )
2022-11-21 22:47:32 +00:00
}
2022-12-10 13:11:05 +00:00
2022-12-02 21:45:34 +00:00
// =-=-=-=-==-=-=-=-==-=-=-=-==-=-=-=
// =-=-=-=-=-= SETUP / RUN =-==-=-=-=
// =-=-=-=-==-=-=-=-==-=-=-=-==-=-=-=
// process white/blacklist from ext settings
function processDomainList ( newLineList ) {
// split by new line
2022-12-09 14:32:23 +00:00
var arrayFromList = newLineList . split ( /\r?\n/ )
2022-12-02 21:45:34 +00:00
// array to put checked domains into
2022-12-09 14:32:23 +00:00
var cleanedArray = [ ]
2022-12-02 21:45:34 +00:00
for ( var domain of arrayFromList ) {
// remove whitespace
2022-12-09 14:32:23 +00:00
domain = domain . trim ( )
2022-12-08 14:23:58 +00:00
if ( domain . length ) {
if ( domainRegex . test ( domain ) ) {
cleanedArray . push ( domain )
} else {
log ( "Removed invalid domain " + domain + " from blacklist/whitelist." )
}
2022-12-02 21:45:34 +00:00
}
}
// return newly created set (remvoes duplicates)
2022-12-12 09:40:41 +00:00
return [ ... new Set ( cleanedArray ) ]
2022-12-02 21:45:34 +00:00
}
2022-11-21 22:47:32 +00:00
function checkSettings ( ) {
// if the home instance is undefined/null/empty
2022-12-06 11:04:25 +00:00
if ( settings . fediact _homeinstance == null || ! settings . fediact _homeinstance ) {
2022-12-09 14:32:23 +00:00
log ( "Mastodon home instance is not set." )
return false
2022-11-21 22:47:32 +00:00
}
2022-11-26 01:40:41 +00:00
// no token for api available (see background.js)
2022-12-06 11:04:25 +00:00
if ( ! settings . fediact _token ) {
2022-12-09 14:32:23 +00:00
log ( "No API token available. Are you logged in to your home instance? If yes, wait for 1-2 minutes and reload page." )
return false
2022-12-02 21:45:34 +00:00
} else {
2022-12-18 18:02:35 +00:00
tmpSettings . tokenheader = { "Authorization" : "Bearer " + settings . fediact _token , }
2022-11-26 01:40:41 +00:00
}
2022-11-21 22:47:32 +00:00
// if the value looks like a domain...
2022-12-06 11:04:25 +00:00
if ( ! ( domainRegex . test ( settings . fediact _homeinstance ) ) ) {
2022-12-09 14:32:23 +00:00
log ( "Instance setting is not a valid domain name." )
return false
2022-11-21 22:47:32 +00:00
}
2022-12-06 11:04:25 +00:00
if ( settings . fediact _mode == "whitelist" ) {
2022-11-21 22:47:32 +00:00
// if in whitelist mode and the cleaned whitelist is empty, return false
2022-12-18 18:02:35 +00:00
tmpSettings . whitelist = processDomainList ( settings . fediact _whitelist )
if ( tmpSettings . whitelist . length < 1 ) {
2022-11-21 22:47:32 +00:00
log ( "Whitelist is empty or invalid." )
2022-12-09 14:32:23 +00:00
return false
2022-11-18 13:20:22 +00:00
}
2022-11-21 22:47:32 +00:00
} else {
// also process the blacklist if in blacklist mode, but an empty blacklist is OK so we do not return false
2022-12-18 18:02:35 +00:00
tmpSettings . blacklist = processDomainList ( settings . fediact _blacklist )
2022-11-21 22:47:32 +00:00
}
2022-12-09 14:32:23 +00:00
return true
2022-11-21 22:47:32 +00:00
}
// test if the current site should be processed or not
// this will also be the function for whitelist/blacklist feature
2022-12-02 21:45:34 +00:00
async function checkSite ( ) {
2022-11-21 22:47:32 +00:00
// is this site on our home instance?
2022-12-06 11:04:25 +00:00
if ( location . hostname == settings . fediact _homeinstance ) {
2022-12-18 18:02:35 +00:00
tmpSettings . fedireply = getUrlParameter ( "fedireply" )
if ( ! tmpSettings . fedireply ) {
2022-12-09 14:32:23 +00:00
log ( "Current site is your home instance." )
return false
2022-12-04 16:56:42 +00:00
}
2022-11-21 22:47:32 +00:00
}
// are we in whitelist mode?
2022-12-06 11:04:25 +00:00
if ( settings . fediact _mode == "whitelist" ) {
2022-11-21 22:47:32 +00:00
// if so, check if site is NOT in whitelist
2022-12-18 18:02:35 +00:00
if ( $ . inArray ( location . hostname , tmpSettings . whitelist ) < 0 ) {
2022-12-09 14:32:23 +00:00
log ( "Current site is not in whitelist." )
return false
2022-11-21 22:47:32 +00:00
}
} else {
// otherwise we are in blacklist mode, so check if site is on blacklist
2022-12-18 18:02:35 +00:00
if ( $ . inArray ( location . hostname , tmpSettings . blacklist ) > - 1 ) {
2022-12-09 14:32:23 +00:00
log ( "Current site is in blacklist." )
return false
2022-11-21 22:47:32 +00:00
}
}
// last check - and probably the most accurate to determine if it actually is mastadon
2022-12-09 14:32:23 +00:00
var requestUrl = location . protocol + '//' + location . hostname + instanceApi
2022-11-21 22:47:32 +00:00
// call instance api to confirm its mastodon and get normalized handle uri
2022-12-29 15:10:59 +00:00
var response = await requestAsyncLimited ( "GET" , requestUrl , null , null )
2022-12-21 13:47:07 +00:00
// todo: add basic check for "mastodon" string in response
2022-11-21 22:47:32 +00:00
if ( response ) {
2022-12-09 14:32:23 +00:00
var uri = JSON . parse ( response ) . uri
2022-11-21 22:47:32 +00:00
if ( uri ) {
2022-12-13 13:30:24 +00:00
if ( uri . startsWith ( "http" ) ) {
uri = new URL ( uri )
2022-12-18 18:02:35 +00:00
tmpSettings . exturi = uri . hostname
2022-12-13 13:30:24 +00:00
} else {
2022-12-18 18:02:35 +00:00
tmpSettings . exturi = uri
2022-12-13 13:30:24 +00:00
}
2022-12-15 00:30:40 +00:00
// at this point, we know that it's mastodon and the background processor should start running
if ( ! backgroundProcessor ( ) ) {
2022-12-29 10:11:29 +00:00
log ( "Could not start background processor." )
2022-12-15 00:30:40 +00:00
return false
}
// if option is enabled, check if logged in on that instance and stop
2022-12-18 18:02:35 +00:00
if ( ! settings . fediact _runifloggedin && ! tmpSettings . fedireply ) {
2022-12-15 00:23:31 +00:00
if ( await isLoggedIn ( ) ) {
log ( "Already logged in to this external instance." )
return false
}
2022-12-14 10:44:01 +00:00
}
2022-12-15 00:23:31 +00:00
} else {
return false
2022-11-18 13:20:22 +00:00
}
2022-12-15 00:23:31 +00:00
} else {
return false
2022-11-18 13:20:22 +00:00
}
2022-12-15 00:23:31 +00:00
return true
2022-11-21 22:47:32 +00:00
}
2022-11-18 13:20:22 +00:00
2022-12-08 14:23:58 +00:00
async function backgroundProcessor ( ) {
2022-12-08 10:08:14 +00:00
// wait for any url change messages from background script
2022-12-11 11:19:46 +00:00
chrome . runtime . onMessage . addListener ( async function ( request , sender , sendResponse ) {
2022-12-08 14:23:58 +00:00
if ( request . urlchanged ) {
2022-12-07 18:49:07 +00:00
// reset already processed elements
2022-12-18 18:02:35 +00:00
tmpSettings . processed = [ ]
tmpSettings . processedFollow = [ ]
tmpSettings . isProcessing = [ ]
2022-12-20 12:55:42 +00:00
$ ( ".fediacticon" ) . remove ( )
$ ( ".fediactsettings_onsite" ) . remove ( )
2022-12-21 13:47:07 +00:00
try {
$ ( "body" ) . off ( "click" , fediSettingsHandler )
} catch {
$ . noop ( )
}
2022-12-11 11:19:46 +00:00
// rerun getSettings to keep mutes/blocks up to date while not reloading the page
if ( ! await getSettings ( ) ) {
// but reload if settings are invalid
location . reload ( )
}
2022-12-08 14:23:58 +00:00
}
2022-12-11 11:19:46 +00:00
// if the settings were updated, we do a page reload
2022-12-08 14:23:58 +00:00
if ( request . updatedfedisettings ) {
location . reload ( )
}
} )
2022-12-08 10:08:14 +00:00
// send message to initialize onUpdated listener in background script (this way it gets the tabid and we do not need to bind the listener for ALL sites)
try {
2022-12-08 14:23:58 +00:00
await chrome . runtime . sendMessage ( { running : true } )
2022-12-08 10:08:14 +00:00
return true
} catch ( e ) {
log ( e )
}
return false
2022-12-07 18:49:07 +00:00
}
2022-12-11 11:19:46 +00:00
function getSettings ( ) {
// get setting
return new Promise ( async function ( resolve ) {
try {
settings = await ( browser || chrome ) . storage . local . get ( settingsDefaults )
} catch ( e ) {
log ( e )
resolve ( false )
2022-12-25 19:21:48 +00:00
return
2022-12-11 11:19:46 +00:00
}
if ( settings ) {
// validate settings
if ( checkSettings ( ) ) {
resolve ( true )
} else {
resolve ( false )
}
} else {
resolve ( false )
}
} )
}
2022-11-21 22:47:32 +00:00
// run wrapper
async function run ( ) {
2022-12-11 11:19:46 +00:00
// validate settings
if ( await getSettings ( ) ) {
// check site (if and which scripts should run)
if ( await checkSite ( ) ) {
2022-12-18 18:02:35 +00:00
if ( tmpSettings . fedireply ) {
2022-12-11 11:19:46 +00:00
processReply ( )
} else {
2022-12-19 11:24:36 +00:00
processProfile ( )
2022-12-15 00:30:40 +00:00
processToots ( )
2022-11-21 22:47:32 +00:00
}
2022-12-11 11:19:46 +00:00
} else {
log ( "Will not process this site." )
2022-11-21 22:47:32 +00:00
}
} else {
log ( "Could not load settings." )
}
2022-11-18 13:20:22 +00:00
}
2022-12-08 10:08:14 +00:00
run ( )