2023-08-24 22:07:37 +00:00
function prepend ( elem , children ) {
var child = elem . firstChild ;
if ( child ) {
elem . insertBefore ( children , child ) ;
} else {
elem . appendChild ( children ) ;
}
}
function _log ( ) {
for ( var arg of arguments ) {
2023-08-24 22:07:37 +00:00
if ( arg == null ) {
continue ;
}
2023-08-24 22:07:37 +00:00
var pre = document . createElement ( 'pre' ) ;
pre . appendChild ( text ( arg . toString ( ) ) ) ;
document . body . appendChild ( pre ) ;
try {
prepend ( document . body , pre ) ;
} catch ( e ) {
var pre = document . createElement ( 'pre' ) ;
pre . appendChild ( text ( e . toString ( ) ) ) ;
document . body . appendChild ( pre ) ;
}
}
}
/ *
var console = {
log : _log ,
error : _log
} ;
* /
var global _elements ;
var GlobalElemSelectors =
[ 'style'
, 'style.loading'
, '.info'
]
var GlobalVars = { } ;
var pageInfoText ;
var GlobalCancellableEvents = [ ] ;
var cancel = GlobalCancellableEvents . push . bind ( GlobalCancellableEvents ) ;
/ * *
* Router
* /
// [ fpart : next ], content
function RoutePart ( fparts , content ) {
return {
fparts ,
content
}
}
function iter ( iarray ) {
var i = 0 ;
return function ( f , g ) {
console . log ( i , iarray . length , iarray ) ;
if ( i < iarray . length ) {
console . log ( "calling" , f , "with" , iarray [ i ] ) ;
f ( iarray [ i ++ ] ) ;
} else {
console . log ( "calling" , g ) ;
g ( ) ;
}
}
}
function resolvePath ( routes , path , query _params ) {
console . log ( "resolvePath:" , arguments ) ;
var next = iter ( path ) ;
function goRoute ( path _data , route _part , path _part ) {
var found = false ;
console . log ( "Route part:" , route _part ) ;
console . log ( "Route part fparts:" , route _part . fparts ) ;
for ( var [ fpart , next _route _part ] of route _part . fparts ) {
var parsed _part = fpart ( path _part ) ;
if ( parsed _part ) {
console . log ( "parsed part:" , parsed _part ) ;
path _data . push ( parsed _part ) ;
next (
goRoute . bind ( this , path _data , next _route _part ) ,
resolve . bind ( this , path _data , next _route _part )
) ;
found = true ;
}
}
if ( ! found ) {
throw new Error ( "404 " + path _data . join ( '/' ) + '/' + path _part ) ;
}
}
function resolve ( path _data , route _part ) {
console . log ( 'calling content' ) ;
2023-08-24 22:07:37 +00:00
console . log ( path _data , route _part , query _params ) ;
2023-08-24 22:07:37 +00:00
route _part . content ( path _data , query _params ) ;
}
var p = [ ] ;
next ( goRoute . bind ( this , p , routes ) , resolve . bind ( this , p , routes ) ) ;
}
function match ( re ) {
return function ( s ) {
if ( re . test ( s ) ) {
return s ;
}
}
}
2023-08-24 22:07:37 +00:00
var ROUTES = RoutePart (
[
[ match ( /^spam_post$/ )
, new RoutePart (
[
[ match ( /^[0-9]+$/ )
, new RoutePart ( [ ] , showSpamPost )
]
]
, null
)
]
]
, handlePageRoot
) ;
2023-08-24 22:07:37 +00:00
/ * *
* Pagination
* /
function createPagination ( start _page _num , url , name , page _size , renderContent ) {
const numDisplayedPages = 5 ; // Specify the number of numbered links to display
// Helper function to update the URL with the new page number
function updatePageNumberInURL ( pageNum ) {
2023-08-24 22:07:37 +00:00
const url = new URL ( window . location . href ) ;
const query _params = url . searchParams ;
console . log ( "updatePageNumberInURL" , query _params . constructor . name ) ;
query _params . set ( replaceAll ( name , ' ' , '_' ) , pageNum ) ;
console . log ( "Hello World 1" ) ;
changeUrl ( "/" , query _params , true ) ;
2023-08-24 22:07:37 +00:00
}
function createPaginationControls ( page _num , dataset _size ) {
2023-08-24 22:07:37 +00:00
const container = document . createElement ( 'nav' ) ;
2023-08-24 22:07:37 +00:00
container . classList . add ( 'pagination' ) ;
// Calculate the total number of pages
const total _pages = Math . ceil ( dataset _size / page _size ) ;
console . log ( 'page_num:' , page _num , 'page_size:' , page _size , 'dataset_size:' , dataset _size , 'total_pages:' , total _pages ) ;
function createNumberedLink ( pageNum ) {
const link = document . createElement ( 'a' ) ;
link . addEventListener ( 'click' , function ( e ) {
//loadNthPage(url, pageNum - 1, page_size)
e . preventDefault ( ) ;
updatePageNumberInURL ( pageNum - 1 ) ;
} ) ;
link . appendChild ( text ( pageNum ) ) ;
if ( pageNum - 1 === page _num ) {
link . classList . add ( 'active' ) ; // Apply CSS class for active page
} else {
link . setAttribute ( 'href' , '#' ) ;
}
return link ;
}
// Add Previous link if applicable
if ( page _num > 0 ) {
const prev _link = document . createElement ( 'a' ) ;
prev _link . setAttribute ( 'href' , '#' ) ;
prev _link . addEventListener ( 'click' , function ( e ) {
e . preventDefault ( ) ;
//loadNthPage(url, page_num - 1, page_size)
updatePageNumberInURL ( page _num - 1 ) ;
} ) ;
prev _link . appendChild ( text ( 'Previous' ) ) ;
container . appendChild ( prev _link ) ;
}
// Add numbered links
const firstDisplayedPage = Math . max ( 1 , page _num - Math . floor ( numDisplayedPages / 2 ) ) ;
const lastDisplayedPage = Math . min ( total _pages , firstDisplayedPage + numDisplayedPages - 1 ) ;
if ( firstDisplayedPage > 1 ) {
container . appendChild ( createNumberedLink ( 1 ) ) ;
if ( firstDisplayedPage > 2 ) {
container . appendChild ( text ( '...' ) ) ;
}
}
for ( let i = firstDisplayedPage ; i <= lastDisplayedPage ; i ++ ) {
container . appendChild ( createNumberedLink ( i ) ) ;
}
if ( lastDisplayedPage < total _pages ) {
if ( lastDisplayedPage < total _pages - 1 ) {
container . appendChild ( text ( '...' ) ) ;
}
container . appendChild ( createNumberedLink ( total _pages ) ) ;
}
// Add Next link if applicable
if ( page _num < total _pages - 1 ) {
const next _link = document . createElement ( 'a' ) ;
next _link . setAttribute ( 'href' , '#' ) ;
next _link . addEventListener ( 'click' , function ( e ) {
//loadNthPage(url, page_num + 1, page_size)
e . preventDefault ( ) ;
updatePageNumberInURL ( page _num + 1 ) ;
} ) ;
next _link . appendChild ( text ( 'Next' ) ) ;
container . appendChild ( next _link ) ;
}
return container ;
}
function loadNthPage ( url , page _num ) {
// Calculate the range of results based on the current page
const start = page _num * page _size ;
const end = start + page _size - 1 ;
var headers = {
'Authorization' : 'Bearer ' + GlobalVars . settings . jwt ,
//'Prefer': 'count=estimated',
'Prefer' : 'count=exact' ,
'Range-Unit' : 'items' ,
'Range' : ` ${ start } - ${ end } `
} ;
pageInfoText . innerText = ` Loading page ${ page _num } of ${ name } ` ;
cancelGlobalEvts ( ) ;
return get ( url , cancel , headers )
. then ( function ( response ) {
// Retrieve the range and total number of results from the HTTP headers
const rangeHeader = response . getResponseHeader ( 'Content-Range' ) ;
const [ start , end , total _results ] = parseRangeHeader ( rangeHeader ) ;
const json = JSON . parse ( response . responseText ) ;
const controlsA = createPaginationControls ( page _num , total _results ) ;
const controlsB = createPaginationControls ( page _num , total _results ) ;
renderContent ( json , controlsA , controlsB ) ;
2023-08-24 22:07:37 +00:00
pageInfoText . innerText = ` ${ name } page ${ page _num + 1 } / ${ Math . ceil ( total _results / page _size ) } ` ;
2023-08-24 22:07:37 +00:00
} )
. catch ( caught . bind ( this , ` Failed to load ${ url } page ${ page _num } . Reason: ` ) ) ;
}
loadNthPage ( url , start _page _num ) ;
}
// Helper function to parse the Content-Range header
function parseRangeHeader ( rangeHeader ) {
const match = rangeHeader . match ( /(\d+)-(\d+)\/(\d+)/ ) ;
if ( match ) {
const start = parseInt ( match [ 1 ] ) ;
const end = parseInt ( match [ 2 ] ) ;
const totalResults = parseInt ( match [ 3 ] ) ;
return [ start , end , totalResults ] ;
}
return [ 0 , 0 , 0 ] ; // Default values if the header is not available or not in the expected format
}
2023-08-24 22:07:37 +00:00
/ * *
* Functions
* /
function resolveResponse ( resolve , reject ) {
return function ( e ) {
var status = e . target . getResponseHeader ( "Status" ) ;
if ( status != null ) {
var status _code = Number ( status . split ( " " ) [ 0 ] ) ;
if ( status _code >= 200 && status _code < 300 ) {
resolve ( e . target . responseText ) ;
} else {
reject ( new Error ( 'API responded with ' + status ) ) ;
}
} else {
if ( e . target . status >= 200 && e . target . status < 300 ) {
2023-08-24 22:07:37 +00:00
return resolve ( e . target ) ;
2023-08-24 22:07:37 +00:00
} else {
reject ( new Error ( 'API responded with ' + e . target . status ) ) ;
}
}
}
}
function cancelGlobalEvts ( ) {
while ( GlobalCancellableEvents . length ) {
GlobalCancellableEvents . pop ( ) . abort ( ) ;
}
}
function get ( url , xhr _req _follower , headers ) {
return new Promise ( function ( resolve , reject ) {
var req = new XMLHttpRequest ( ) ;
xhr _req _follower ( req ) ;
req . onload = resolveResponse ( resolve , reject ) ;
req . onerror = reject ;
req . open ( 'GET' , url ) ;
if ( headers ) {
Object . entries ( headers )
. forEach ( function ( [ header _name , header _value ] ) {
req . setRequestHeader ( header _name , header _value ) ;
} ) ;
}
req . send ( ) ;
} ) ;
}
2023-08-24 22:07:37 +00:00
// Given a BigInt that is packed bytes, unpack the bytes into an ArrayBuffer
function unpackBytes ( bigint ) {
const buffer = new ArrayBuffer ( 8 ) ;
const view = new DataView ( buffer ) ;
view . setBigInt64 ( 0 , bigint ) ;
return buffer ;
}
2023-08-24 22:07:37 +00:00
2023-08-24 22:07:37 +00:00
function bufferToHex ( buffer ) {
2023-08-24 22:07:37 +00:00
// Create a Uint8Array view to access the bytes
const uint8Array = new Uint8Array ( buffer ) ;
2023-08-24 22:07:37 +00:00
2023-08-24 22:07:37 +00:00
// Convert each byte to its hexadecimal representation
const hexArray = Array . from ( uint8Array , byte => byte . toString ( 16 ) . padStart ( 2 , '0' ) ) ;
2023-08-24 22:07:37 +00:00
2023-08-24 22:07:37 +00:00
// Join the hexadecimal values into a single string
2023-08-24 22:07:37 +00:00
return hexArray . join ( '' ) ;
2023-08-24 22:07:37 +00:00
}
2023-08-24 22:07:37 +00:00
function hammingDistance ( buffer1 , buffer2 ) {
if ( buffer1 . byteLength !== buffer2 . byteLength ) {
throw new Error ( "Buffer lengths must be equal" ) ;
}
2023-08-24 22:07:37 +00:00
2023-08-24 22:07:37 +00:00
const view1 = new DataView ( buffer1 ) ;
const view2 = new DataView ( buffer2 ) ;
2023-08-24 22:07:37 +00:00
2023-08-24 22:07:37 +00:00
let distance = 0 ;
for ( let i = 0 ; i < buffer1 . byteLength ; i ++ ) {
const byte1 = view1 . getUint8 ( i ) ;
const byte2 = view2 . getUint8 ( i ) ;
let xor = byte1 ^ byte2 ;
while ( xor !== 0 ) {
distance ++ ;
xor &= xor - 1 ;
}
}
return distance ;
}
2023-08-24 22:07:37 +00:00
function parseFilePath ( s ) {
return JSON . parse ( s ) ;
}
function FileSize ( s ) {
this . filesize = s ;
}
function tree ( rows ) {
var c = { } ;
for ( var row of rows ) {
var path = parseFilePath ( row . path ) ;
var tree = c ;
var previous = c ;
var filename = 'NOPATH' ;
for ( var p of path ) {
previous = tree ;
if ( p in tree ) {
tree = tree [ p ] ;
} else {
var newtree = { } ;
tree [ p ] = newtree ;
tree = newtree ;
}
filename = p ;
}
previous [ filename ] = new FileSize ( row . filesize ) ;
}
console . log ( c ) ;
return c ;
}
function renderTree ( rows ) {
var list _elem = ul ( ) ;
function draw ( list _elem , t ) {
Object . entries ( t )
. forEach ( function ( [ key , val ] ) {
if ( val instanceof FileSize ) {
var contents = div ( span ( text ( key ) ) ) ;
contents . appendChild ( italic ( text ( val . filesize ) ) ) ;
list _elem . appendChild ( contents ) ;
} else {
var new _list = ul ( ) ;
var elem = li ( text ( key ) ) ;
elem . appendChild ( new _list ) ;
list _elem . appendChild ( elem ) ;
draw ( new _list , val ) ;
}
} ) ;
}
draw ( list _elem , tree ( rows ) ) ;
return list _elem ;
}
function assembleTable ( rows ) {
var t = document . createElement ( 'table' ) ;
rows . forEach ( function ( r ) {
var row = t . insertRow ( ) ;
TableHeadings . forEach ( function ( header ) {
var cell = row . insertCell ( ) ;
cell . appendChild ( header [ 1 ] ( r ) ) ;
} ) ;
} ) ;
var thead = t . createTHead ( ) . insertRow ( ) ;
TableHeadingNames . forEach ( function ( header ) {
var th = document . createElement ( 'th' ) ;
th . appendChild ( text ( header ) ) ;
thead . appendChild ( th ) ;
} ) ;
var countElem = div ( text ( rows . length + ' rows' ) )
var wrapper = div ( ) ;
wrapper . appendChild ( t ) ;
wrapper . appendChild ( countElem ) ;
return wrapper ;
}
function text ( s ) {
return document . createTextNode ( s ) ;
}
function _mkelem ( etype , child ) {
var elem = document . createElement ( etype ) ;
if ( child ) {
elem . appendChild ( child ) ;
}
return elem ;
}
2023-08-24 22:07:37 +00:00
var h3 = _mkelem . bind ( this , 'h3' ) ;
2023-08-24 22:07:37 +00:00
var h4 = _mkelem . bind ( this , 'h4' ) ;
2023-08-24 22:07:37 +00:00
var div = _mkelem . bind ( this , 'div' ) ;
var li = _mkelem . bind ( this , 'li' ) ;
var span = _mkelem . bind ( this , 'span' ) ;
2023-08-24 22:07:37 +00:00
var italic = _mkelem . bind ( this , 'i' ) ;
2023-08-24 22:07:37 +00:00
var bold = _mkelem . bind ( this , 'b' ) ;
var ul = _mkelem . bind ( this , 'ul' ) ;
2023-08-24 22:07:37 +00:00
function keepElements ( elem _selectors ) {
var document _root = document . querySelector ( 'main' ) ;
document _root . innerHTML = '' ;
for ( var i = 0 ; i < elem _selectors . length ; i ++ ) {
var sel = elem _selectors [ i ] ;
var elem = global _elements [ sel ] ;
document _root . appendChild ( elem ) ;
}
}
function caught ( m , e ) {
console . error ( m ) ;
console . error ( e ) ;
2023-08-24 22:07:37 +00:00
for ( var property in e ) {
console . error ( property + ": " + e [ property ] ) ;
}
2023-08-24 22:07:37 +00:00
alert ( new Error ( m + e . message ) ) ;
} ;
function mkSpamImgElement ( img _description ) {
var img _elem = document . createElement ( 'img' ) ;
var mime = img _description . mimetype ;
2023-08-24 22:07:37 +00:00
var thumb _url ;
2023-08-24 22:07:37 +00:00
2023-08-24 22:07:37 +00:00
if ( mime == "audio/mpeg" ) {
2023-08-24 22:07:37 +00:00
thumb _url = ` /bin/?path= ${ GlobalVars . settings . audio _mpeg _thumbnail _path } &mimetype=image/jpeg `
} else {
2023-08-24 22:07:37 +00:00
thumb _url = ` /bin/?path= ${ GlobalVars . settings . content _directory } / ${ img _description . md5 _hash } _thumbnail.jpg&mimetype=image/jpeg `
2023-08-24 22:07:37 +00:00
}
2023-08-24 22:07:37 +00:00
2023-08-24 22:07:37 +00:00
var image _url = ` /bin/?path= ${ GlobalVars . settings . content _directory } / ${ img _description . md5 _hash } .attachment&mimetype= ${ mime } `
2023-08-24 22:07:37 +00:00
img _elem . setAttribute ( 'src' , thumb _url ) ;
img _elem . setAttribute ( 'decoding' , 'async' ) ;
img _elem . setAttribute ( 'loading' , 'lazy' ) ;
var a _elem = document . createElement ( 'a' ) ;
a _elem . setAttribute ( 'href' , image _url ) ;
a _elem . appendChild ( img _elem ) ;
2023-08-24 22:07:37 +00:00
2023-08-24 22:07:37 +00:00
var img _container _elem = div ( a _elem ) ;
img _container _elem . classList . add ( 'post--image_container' ) ;
2023-08-24 22:07:37 +00:00
return img _container _elem ;
}
2023-08-24 22:07:37 +00:00
function renderNav ( ) {
var nav = document . createElement ( 'nav' ) ;
var a _elem = _mkelem ( 'a' , text ( 'All Known Spam Posts' ) ) ;
2023-08-24 22:07:37 +00:00
a _elem . addEventListener ( 'click' , function ( e ) {
e . preventDefault ( ) ;
2023-08-24 22:07:37 +00:00
changeUrl ( '/' , new URLSearchParams ( ) , true ) ;
2023-08-24 22:07:37 +00:00
} ) ;
a _elem . setAttribute ( 'href' , '#' ) ;
nav . appendChild ( a _elem ) ;
return nav
}
2023-08-24 22:07:37 +00:00
function renderPostElem ( post ) {
var postContainer = div ( ) ;
2023-08-24 22:07:37 +00:00
postContainer . classList . add ( 'post' ) ;
2023-08-24 22:07:37 +00:00
var postElem = div ( ) ;
postElem . classList . add ( 'post--body_container' ) ;
postContainer . appendChild ( postElem ) ;
var bodyTextElem = div ( ) ;
bodyTextElem . classList . add ( 'post--body' ) ;
bodyTextElem . innerText = post . body ;
2023-08-24 22:07:37 +00:00
if ( post . known _spam _post _attachment ) {
post . known _spam _post _attachment . forEach ( function ( attachment ) {
postElem . appendChild ( mkSpamImgElement ( attachment ) ) ;
} ) ;
}
2023-08-24 22:07:37 +00:00
postElem . appendChild ( bodyTextElem ) ;
return postContainer ;
}
2023-08-24 22:07:37 +00:00
function renderKnownSpamAttachments ( attachments ) {
var container = div ( ) ;
container . classList . add ( 'attachment' ) ;
2023-08-24 22:07:37 +00:00
2023-08-24 22:07:37 +00:00
attachments . forEach ( function ( a ) {
container . appendChild ( mkSpamImgElement ( a ) ) ;
} ) ;
2023-08-24 22:07:37 +00:00
return container ;
}
function renderThings ( things _map ) {
var container = div ( ) ;
for ( const [ key , value ] of Object . entries ( things _map ) ) {
var entry = div ( ) ;
entry . appendChild ( span ( bold ( text ( key + ": " ) ) ) ) ;
entry . appendChild ( span ( text ( value ) ) ) ;
container . appendChild ( entry ) ;
}
return container ;
}
2023-08-24 22:07:37 +00:00
function renderAttachmentReason ( attachment , known _spam _post _attachments ) {
let container = div ( ) ;
2023-08-24 22:07:37 +00:00
container . classList . add ( 'attachment-reason' ) ;
container . appendChild ( mkSpamImgElement ( attachment ) ) ;
2023-08-24 22:07:37 +00:00
let phash _buffer = unpackBytes ( BigInt ( attachment [ 'phash' ] ) ) ;
let distance = ( 64 - Math . min ( ... known _spam _post _attachments . map ( function ( known _attachment ) {
let known _buffer = unpackBytes ( BigInt ( known _attachment [ 'phash' ] ) ) ;
let distance = hammingDistance ( known _buffer , phash _buffer ) ;
return distance ;
} ) ) ) / 64 ;
let things = {
2023-08-24 22:07:37 +00:00
'mimetype' : attachment [ 'mimetype' ] ,
'time stamp' : attachment [ 'time_stamp' ] ,
'md5' : attachment [ 'md5_hash' ] ,
2023-08-24 22:07:37 +00:00
'phash (hex)' : bufferToHex ( phash _buffer ) ,
'match' : ` ${ Math . round ( distance * 100 * 10 ) / 10 } % `
2023-08-24 22:07:37 +00:00
} ;
container . appendChild ( renderThings ( things ) ) ;
2023-08-24 22:07:37 +00:00
return container ;
}
function renderReasons ( post ) {
var container = div ( h3 ( text ( 'Reasons for being considered spam:' ) ) ) ;
container . appendChild ( renderReasonsUl ( post ) ) ;
var reasonDetails = post . reason _details ;
if ( reasonDetails ) {
var reasonDetailsContainer = div ( ) ;
reasonDetailsContainer . className = 'reason-details' ;
if ( reasonDetails . frequent _attachment _details ) {
2023-08-24 22:07:37 +00:00
reasonDetailsContainer . appendChild ( h4 ( text ( 'Previously posted matching attachments:' ) ) ) ;
2023-08-24 22:07:37 +00:00
reasonDetails . frequent _attachment _details . forEach ( function ( attachment ) {
2023-08-24 22:07:37 +00:00
reasonDetailsContainer . appendChild (
renderAttachmentReason ( attachment , post . known _spam _post _attachment )
) ;
2023-08-24 22:07:37 +00:00
} ) ;
}
if ( reasonDetails . frequent _text _details ) {
var textPosts = div ( ) ;
reasonDetails . frequent _text _details . forEach ( function ( post ) {
textPosts . appendChild ( renderPostElem ( post ) ) ;
} ) ;
reasonDetailsContainer . appendChild ( h4 ( text ( 'Previously posted matching text:' ) ) ) ;
reasonDetailsContainer . appendChild ( textPosts ) ;
}
container . appendChild ( h3 ( text ( 'Reason Details:' ) ) ) ;
container . appendChild ( reasonDetailsContainer ) ;
}
return container ;
}
2023-08-24 22:07:37 +00:00
var REASONS = {
RECENTLY _POSTED _ATTACHMENT _ABOVE _RATE : 1 << 0 ,
LEXICAL _ANALYSIS _SHOWS _NONSENSE : 1 << 1 ,
SEGMENTED _AVG _ENTROPY _TOO _HIGH : 1 << 2 ,
TEXT _MATCHES _KNOWN _SPAM : 1 << 3 ,
RECENTLY _POSTED _TEXT _ABOVE _RATE : 1 << 4 ,
TEXT _IS _URL : 1 << 5 ,
TEXT _IS _ONE _LONG _WORD : 1 << 6 ,
TEXT _IS _RANDOM _WORDS : 1 << 7
} ;
function reasonsFromBitmap ( n ) {
var reasons = new Set ( ) ;
for ( const [ reason , bit ] of Object . entries ( REASONS ) ) {
if ( n & bit ) {
reasons . add ( reason ) ;
}
}
return reasons ;
}
2023-08-24 22:07:37 +00:00
function renderReasonsUl ( post ) {
2023-08-24 22:07:37 +00:00
var reasons = ul ( ) ;
reasonsFromBitmap ( post . reason ) . forEach ( function ( r ) {
reasons . appendChild ( li ( text ( r ) ) ) ;
} ) ;
2023-08-24 22:07:37 +00:00
return reasons ;
}
function renderOverviewPost ( post ) {
var postContainer = renderPostElem ( post ) ;
2023-08-24 22:07:37 +00:00
postContainer . appendChild ( h3 ( text ( 'Reasons:' ) ) ) ;
2023-08-24 22:07:37 +00:00
postContainer . appendChild ( div ( renderReasonsUl ( post ) ) ) ;
2023-08-24 22:07:37 +00:00
postContainer . classList . add ( 'post--overview' ) ;
2023-08-24 22:07:37 +00:00
return postContainer ;
}
2023-08-24 22:07:37 +00:00
function replaceAll ( input , find , replace ) {
var regex = new RegExp ( find , "g" ) ;
return input . replace ( regex , replace ) ;
}
2023-08-24 22:07:37 +00:00
function loadKnownSpamPosts ( params ) {
2023-08-24 22:07:37 +00:00
console . log ( "loadKnownSpamPosts" ) ;
2023-08-24 22:07:37 +00:00
2023-08-24 22:07:37 +00:00
const pageName = "known spam posts" ;
2023-08-24 22:07:37 +00:00
console . log ( "HELLO WORLD 1" ) ;
2023-08-24 22:07:37 +00:00
var url = GlobalVars . settings . postgrest _url + '/known_spam_post?select=*,known_spam_post_attachment(*,phash::text)'
2023-08-24 22:07:37 +00:00
2023-08-24 22:07:37 +00:00
const pageNum = Number ( params . get ( replaceAll ( pageName , ' ' , '_' ) ) || 0 ) ;
2023-08-24 22:07:37 +00:00
2023-08-24 22:07:37 +00:00
function renderContent ( json , controlsA , controlsB ) {
var mainElem = document . querySelector ( 'main' ) ;
mainElem . innerHTML = '' ;
mainElem . appendChild ( controlsA ) ;
2023-08-24 22:07:37 +00:00
2023-08-24 22:07:37 +00:00
json . forEach ( function ( post ) {
var postElem = renderOverviewPost ( post ) ;
2023-08-24 22:07:37 +00:00
2023-08-24 22:07:37 +00:00
postElem . addEventListener ( 'click' , function ( ) {
2023-08-24 22:07:37 +00:00
changeUrl ( '/spam_post/' + post . text _post _id , new URLSearchParams ( ) , true ) ;
2023-08-24 22:07:37 +00:00
} ) ;
2023-08-24 22:07:37 +00:00
mainElem . appendChild ( postElem ) ;
} ) ;
mainElem . appendChild ( controlsB ) ;
}
createPagination ( pageNum , url , pageName , 25 , renderContent ) ;
2023-08-24 22:07:37 +00:00
}
2023-08-24 22:07:37 +00:00
function changeUrl ( path , search _query , push _state ) {
2023-08-24 22:07:37 +00:00
console . log ( 'changeURL' ) ;
2023-08-24 22:07:37 +00:00
var event = new CustomEvent (
'urlchange' ,
{
detail : {
path : path ,
2023-08-24 22:07:37 +00:00
query : search _query ,
push _state : push _state ,
2023-08-24 22:07:37 +00:00
}
} ) ;
window . dispatchEvent ( event ) ;
}
function handlePageRoot ( _ , query _params ) {
2023-08-24 22:07:37 +00:00
console . log ( "handlePageRoot" , JSON . stringify ( query _params ) ) ;
2023-08-24 22:07:37 +00:00
return loadKnownSpamPosts ( query _params ) ;
2023-08-24 22:07:37 +00:00
}
2023-08-24 22:07:37 +00:00
function showSpamPost ( path _data , _ ) {
console . log ( path _data ) ;
var post _id = path _data [ 1 ] ;
pageInfoText . innerText = 'Loading known spam post ' + post _id ;
var url =
GlobalVars . settings . postgrest _url
+ '/known_spam_post?text_post_id=eq.' + post _id
2023-08-24 22:07:37 +00:00
+ '&select=*,known_spam_post_attachment(*,phash::text)' ; // Have to load the phash as text here because javascripts json parser won't use BigInt when appropriate because javascript Numbers are based on floats and we're dealing with a 64bit signed int.
2023-08-24 22:07:37 +00:00
var headers = {
'Authorization' : 'Bearer ' + GlobalVars . settings . jwt
} ;
var postSectionElem = document . createElement ( 'section' ) ;
var mainElem = document . querySelector ( 'main' ) ;
mainElem . innerHTML = '' ;
2023-08-24 22:07:37 +00:00
mainElem . appendChild ( renderNav ( ) ) ;
2023-08-24 22:07:37 +00:00
mainElem . appendChild ( postSectionElem ) ;
var h2 = document . createElement ( 'h2' ) ;
h2 . innerText = 'Known Spam Attachments' ;
mainElem . appendChild ( postSectionElem ) ;
mainElem . appendChild ( h2 ) ;
var knownSpamAttachmentsSectionElem = document . createElement ( 'section' ) ;
mainElem . append ( knownSpamAttachmentsSectionElem ) ;
2023-08-24 22:07:37 +00:00
var reasonsSectionElem = document . createElement ( 'section' ) ;
mainElem . appendChild ( reasonsSectionElem ) ;
2023-08-24 22:07:37 +00:00
get ( url , cancel , headers )
. then ( function ( response ) {
2023-08-24 22:07:37 +00:00
var json = JSON . parse ( response . responseText ) ;
2023-08-24 22:07:37 +00:00
console . log ( json ) ;
pageInfoText . innerText = 'Known Spam Post' ;
json . forEach ( function ( p ) {
var postElem = renderPostElem ( p ) ;
postSectionElem . appendChild ( postElem ) ;
2023-08-24 22:07:37 +00:00
reasonsSectionElem . appendChild ( renderReasons ( p ) )
2023-08-24 22:07:37 +00:00
} ) ;
} )
. catch ( caught . bind ( this , "Failed to load known spam post. Reason:" ) ) ;
url =
GlobalVars . settings . postgrest _url
+ '/known_spam_attachments?post_id=eq.' + post _id ;
get ( url , cancel , headers )
. then ( function ( response ) {
2023-08-24 22:07:37 +00:00
var json = JSON . parse ( response . responseText ) ;
2023-08-24 22:07:37 +00:00
console . log ( "known spam attachments:" , json ) ;
2023-08-24 22:07:37 +00:00
knownSpamAttachmentsSectionElem
. appendChild ( renderKnownSpamAttachments ( json ) ) ;
2023-08-24 22:07:37 +00:00
} )
. catch ( caught . bind ( this , "Failed to load known spam attachments. Reason:" ) ) ;
}
2023-08-24 22:07:37 +00:00
function onUrlChange ( e ) {
2023-08-24 22:07:37 +00:00
console . log ( 'Hello World 2' ) ;
2023-08-24 22:07:37 +00:00
var path = e . detail . path . split ( '/' ) . filter ( function ( s ) { return s . length ; } ) ;
console . log ( e , e . detail , path ) ;
2023-08-24 22:07:37 +00:00
if ( e . detail . push _state ) {
2023-08-24 22:07:37 +00:00
var search _query = e . detail . query ;
search _query . set ( '__path' , e . detail . path ) ;
console . log ( "onUrlChange push_state search_query:" , search _query , typeof search _query ) ;
2023-08-24 22:07:37 +00:00
window . history . pushState ( null , "" ,
window . location . origin + window . location . pathname + '?' + search _query . toString ( ) ) ;
}
2023-08-24 22:07:37 +00:00
resolvePath ( ROUTES , path , e . detail . query ) ;
}
function aClickNav ( e ) {
e . preventDefault ( ) ;
e . stopPropagation ( ) ;
console . log ( this , this . href ) ;
window . history . pushState ( null , "" , this . href ) ;
onRealUrlChange ( ) ;
}
function bindEventHandlers ( ) {
window . addEventListener ( 'urlchange' , onUrlChange ) ;
window . addEventListener ( 'popstate' , onRealUrlChange ) ;
2023-08-24 22:07:37 +00:00
function on _pushstate ( e ) {
for ( var i = 0 ; i < 10 ; i ++ ) {
console . log ( "pushstate" , e ) ;
}
}
window . addEventListener ( 'pushstate' , on _pushstate ) ;
2023-08-24 22:07:37 +00:00
}
function gatherElements ( ) {
global _elements = { } ;
var qs ;
for ( var i = 0 ; i < GlobalElemSelectors . length ; i ++ ) {
var sel = GlobalElemSelectors [ i ] ;
var elem = document . querySelector ( sel ) ;
global _elements [ sel ] = elem ;
}
}
function onRealUrlChange ( ) {
2023-08-24 22:07:37 +00:00
const url = new URL ( window . location . href ) ;
const query _params = url . searchParams ;
2023-08-24 22:07:37 +00:00
2023-08-24 22:07:37 +00:00
const path = query _params . get ( '__path' ) || '/' ;
2023-08-24 22:07:37 +00:00
2023-08-24 22:07:37 +00:00
changeUrl ( path , query _params ) ;
}
function initPageInfoText ( ) {
pageInfoText = document . createElement ( 'div' ) ;
pageInfoText . className = 'info' ;
prepend ( document . querySelector ( '.info-container' ) , pageInfoText ) ;
}
function getSettings ( ) {
cancelGlobalEvts ( ) ;
pageInfoText . innerText = 'Loading settings' ;
return get ( '/static/settings.json' , cancel )
. then ( function ( response ) {
2023-08-24 22:07:37 +00:00
var result = JSON . parse ( response . responseText ) ;
2023-08-24 22:07:37 +00:00
console . log ( "settings response:" , result ) ;
GlobalVars . settings = result ;
pageInfoText . innerText = 'Have settings.' ;
} )
. catch ( caught . bind ( this , "Failed to load JWT: " ) ) ;
}
/ * *
* Init
* /
initPageInfoText ( ) ;
// gatherElements();
bindEventHandlers ( ) ;
// searchInputHandler();
getSettings ( )
. then ( onRealUrlChange ) ;