display phash as hex
This commit is contained in:
parent
c745ed8901
commit
d3f3a9aa0f
291
script.js
291
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);
|
||||
|
|
Loading…
Reference in New Issue