From d3f3a9aa0fe95380e1e5cb4d29f604946e55bb61 Mon Sep 17 00:00:00 2001 From: towards-a-new-leftypol Date: Thu, 24 Aug 2023 18:07:37 -0400 Subject: [PATCH] display phash as hex --- script.js | 291 +++++++++++++++++------------------------------------- style.css | 3 +- 2 files changed, 91 insertions(+), 203 deletions(-) diff --git a/script.js b/script.js index cad0ad1..d125c38 100644 --- a/script.js +++ b/script.js @@ -124,13 +124,6 @@ function match(re) { } } -/* -var ROUTES = RoutePart([ - [match(/^s$/), new RoutePart([], handleSearch)], - [match(/^[a-f0-9]{40}$/), new RoutePart([], handleInfo)] -], loadTop); -*/ - var ROUTES = RoutePart( [ [ match(/^spam_post$/) @@ -147,24 +140,6 @@ var ROUTES = RoutePart( , handlePageRoot ); -/* -var ROUTES = RoutePart( - [ - [ match(/^static$/) - , new RoutePart( - [ - [ match(/^index\.html$/) - , new RoutePart([], handlePageRoot) - ] - ] - , null - ) - ] - ] - , null -); -*/ - /** * Functions */ @@ -214,48 +189,53 @@ function get(url, xhr_req_follower, headers) { }); } -var HexArray = "0123456789abcdef"; +// 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; +} -function bytesToHex(uint8arr) { - var hex_encoded = ""; +function hexArrayFromBuffer(buffer) { + // Create a Uint8Array view to access the bytes + const uint8Array = new Uint8Array(buffer); - for (var i=0; i < uint8arr.length; i++) { - var j = uint8arr[i] & 0xFF; - hex_encoded += HexArray[j >>> 4]; - hex_encoded += HexArray[j & 0x0F]; + // Convert each byte to its hexadecimal representation + const hexArray = Array.from(uint8Array, byte => byte.toString(16).padStart(2, '0')); + + return uint8Array; +} + +function bufferToHex(buffer) { + // Join the hexadecimal values into a single string + return hexArray(buffer).join(''); +} + +function hammingDistance(buffer1, buffer2) { + if (buffer1.byteLength !== buffer2.byteLength) { + throw new Error("Buffer lengths must be equal"); + } + + const view1 = new DataView(buffer1); + const view2 = new DataView(buffer2); + + 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 hex_encoded; + return distance; } -var ESC_STR = '$ESCAPE_PIPE_SYMBOL'; - -function splitRawRow(raw_row) { - return raw_row - .replace('\\|', ESC_STR) - .split('|') - .map(function(s) { - return s.replace(ESC_STR, '|') - .trim(); - }) -} - -function parseTable(results) { - var raw_rows = results.split('\n').slice(0, -1); - var headers = splitRawRow(raw_rows[0]); - - return raw_rows.slice(2, -1) - .map(splitRawRow) - .map(function(row) { - return row.reduce(function(acc, val, i) { - acc[headers[i]] = val; - return acc; - }, - {}); - }) -} - - function parseFilePath(s) { return JSON.parse(s); } @@ -385,43 +365,16 @@ function keepElements(elem_selectors) { } } -function ensureElementExist(selector) { - var document_root = document.querySelector('main'); - var elem = document_root.querySelector(selector); - - if (!elem) { - document_root.appendChild(global_elements[selector]); - } - -} - function loadJwt() { cancelGlobalEvts(); } -function loadTop() { - //TODO: dispatch changeurl event - cancelGlobalEvts(); - ensureElementExist('style.loading'); - pageInfoText.innerText = 'Loading Top 100...'; - get('/cgi-bin/top_100', cancel) - .then(function(response) { - CurrentScore = currentScore(); - console.log("Current score:", CurrentScore); - - var document_root = document.querySelector('main'); - var t = parseTable(response); - console.log(t); - keepElements(['style', '.info']); - pageInfoText.innerText = 'Top 100'; - document_root.appendChild(assembleTable(t)); - }) - .catch(caught.bind(this, "Failed to load top 100: ")); -} - function caught(m, e) { console.error(m); console.error(e); + for (var property in e) { + console.error(property + ": " + e[property]); + } alert(new Error(m + e.message)); }; @@ -430,13 +383,13 @@ function mkSpamImgElement(img_description) { var mime = img_description.mimetype; var thumb_url; - if (!img_description.thumbnail) { + if (mime == "audio/mpeg") { thumb_url = `/bin/?path=${GlobalVars.settings.audio_mpeg_thumbnail_path}&mimetype=image/jpeg` } else { thumb_url = `/bin/?path=${GlobalVars.settings.content_directory}/${img_description.md5_hash}_thumbnail.jpg&mimetype=image/jpeg` } - var image_url = `/bin/?path=${GlobalVars.settings.content_directory}/${img_description.md5_hash}&mimetype=${mime}` + var image_url = `/bin/?path=${GlobalVars.settings.content_directory}/${img_description.md5_hash}.attachment&mimetype=${mime}` img_elem.setAttribute('src', thumb_url); img_elem.setAttribute('decoding', 'async'); img_elem.setAttribute('loading', 'lazy'); @@ -485,9 +438,45 @@ function renderPostElem(post) { function renderKnownSpamAttachments(attachments) { var container = div(); container.classList.add('attachment'); + attachments.forEach(function(a) { container.appendChild(mkSpamImgElement(a)); }); + + 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; +} + +function renderAttachmentReason(attachment) { + var container = div(); + + container.classList.add('attachment-reason'); + container.appendChild(mkSpamImgElement(attachment)); + + var things = { + 'mimetype': attachment['mimetype'], + 'time stamp': attachment['time_stamp'], + 'md5': attachment['md5_hash'], + 'phash raw': BigInt(attachment['phash']).toString(2), + 'phash (hex)': hexArrayFromBuffer(unpackBytes(BigInt(attachment['phash']))), + //'distance': hammingDistance(unpackBytes(BigInt(attachment['phash'])), unpackBytes(BigInt(attachment['phash']))), + 'distance': hammingDistance(unpackBytes(BigInt(attachment['phash'])), unpackBytes(BigInt(0))), + }; + + + container.appendChild(renderThings(things)); return container; } @@ -501,12 +490,10 @@ function renderReasons(post) { reasonDetailsContainer.className = 'reason-details'; if (reasonDetails.frequent_attachment_details) { - var attachmentList = ul(); - reasonDetails.frequent_attachment_details.forEach(function (attachment) { - attachmentList.appendChild(li(text(attachment.filename))); - }); reasonDetailsContainer.appendChild(h4(text('Previously posted matching attachments:'))); - reasonDetailsContainer.appendChild(div(attachmentList)); + reasonDetails.frequent_attachment_details.forEach(function (attachment) { + reasonDetailsContainer.appendChild(renderAttachmentReason(attachment)); + }); } if (reasonDetails.frequent_text_details) { @@ -562,14 +549,14 @@ function renderOverviewPost(post) { var postContainer = renderPostElem(post); postContainer.appendChild(h3(text('Reasons:'))); postContainer.appendChild(div(renderReasonsUl(post))); + postContainer.classList.add('post--overview'); return postContainer; } function loadKnownSpamPosts() { - pageInfoText.innerText = 'Loading known spam post'; + pageInfoText.innerText = 'Loading all known spam posts...'; cancelGlobalEvts(); - //var url = GlobalVars.settings.postgrest_url + '/known_spam_post?select=*,known_spam_attachments(*)' var url = GlobalVars.settings.postgrest_url + '/known_spam_post?select=*,known_spam_post_attachment(*)' var headers = { 'Authorization': 'Bearer ' + GlobalVars.settings.jwt @@ -578,8 +565,7 @@ function loadKnownSpamPosts() { get(url, cancel, headers) .then(function(response) { var json = JSON.parse(response); - console.log("results for", url, json); - //console.log("have known spam images:", json); + console.log("results for", url, response); pageInfoText.innerText = 'Have these known spam posts:'; var mainElem = document.querySelector('main'); mainElem.innerHTML = ''; @@ -597,88 +583,6 @@ function loadKnownSpamPosts() { .catch(caught.bind(this, "Failed to load known spam posts. Reason:")); } -function loadInfo(info_hash) { - var preLoad_executed = false; - var page = document.createElement('div'); - - function preLoad() { - if (preLoad_executed) { - return; - } - - preLoad_executed = true; - keepElements(['style', '.info']); - pageInfoText.innerText = info_hash; - document.querySelector('main').appendChild(page); - } - - ensureElementExist('style.loading'); - pageInfoText.innerText = 'Loading info for ' + info_hash; - - cancelGlobalEvts(); - - get('/cgi-bin/files?i=' + info_hash, cancel) - .then(function(response) { - preLoad(); - var files = parseTable(response); - console.log(files); - var h = document.createElement('h2'); - h.innerText = 'Contents'; - page.appendChild(h); - var t = renderTree(files); - page.appendChild(t); - }) - .catch(caught.bind(this, "Failed to info details. Reason:")); - - get('/cgi-bin/info?i=' + info_hash, cancel) - .then(function(response) { - preLoad(); - var info = parseTable(response)[0]; - pageInfoText.innerText = info.name; - var first_seen = new Date(info.added.split('.')[0]+'Z'); - var mlink = magnet(info); - mlink.innerText = mlink.href; - - var last_seen = new Date(Math.min( - invertScore(Number(info.score)) * 1000, - new Date().getTime()) - ); - - prepend(page, div(text('First Indexed: ' + first_seen))); - prepend(page, div(text('Approximately last seen: ' + last_seen))); - var filecount = div(text('Files: ')); - filecount.appendChild(bold(text(info.filecount))) - prepend(page, filecount); - var total_size = div(text('Total Size: ')); - total_size.appendChild(bold(text(info.total_size))) - prepend(page, total_size); - prepend(page, div(mlink)); - }) - .catch(caught.bind(this, "Failed to load file list. Details:")); -} - -function loadResults(search_query) { - var encoder = new TextEncoder(); - var hex = bytesToHex(encoder.encode(search_query)); - console.log(hex); - cancelGlobalEvts(); - ensureElementExist('style.loading'); - pageInfoText.innerText = 'Loading results for "' + search_query + '"...'; - get('/cgi-bin/search?q=' + hex, cancel) - .then(function(response) { - CurrentScore = currentScore(); - console.log("Current score:", CurrentScore); - - var t = assembleTable(parseTable(response)); - var document_root = document.querySelector('main'); - - keepElements(['style', '.info']) - pageInfoText.innerText = 'Results for "' + search_query + '"'; - document_root.appendChild(t); - }) - .catch(caught.bind(this, "Failed to results: ")); -} - function changeUrl(path, search_query, push_state) { var event = new CustomEvent( 'urlchange', @@ -694,7 +598,7 @@ function changeUrl(path, search_query, push_state) { } function handlePageRoot(_, query_params) { - console.log("handlePageRoot", query_params); + console.log("handlePageRoot", JSON.stringify(query_params)); return loadKnownSpamPosts(); } @@ -759,23 +663,6 @@ function showSpamPost(path_data, _) { } -function handleSearch(_, query_params) { - var search_query = query_params.q; - - if (!search_query) { - console.log("nothing to query"); - return; - } else { - console.log(search_query); - loadResults(search_query); - } -} - -function handleInfo(parts, query_params) { - console.log('info request', parts, query_params); - loadInfo(parts[0]); -} - function onUrlChange(e) { var path = e.detail.path.split('/').filter(function(s){ return s.length; }); console.log(e, e.detail, path); diff --git a/style.css b/style.css index a4c588d..1b09b4b 100644 --- a/style.css +++ b/style.css @@ -14,7 +14,7 @@ header { padding: 1em; } -.post:hover { +.post--overview:hover { background-color: #FFEEEE; } @@ -24,6 +24,7 @@ header { } .post--body_container, +.attachment-reason, .attachment { display: flow-root; }