yosup/web/js/event.js
2022-12-20 18:47:33 -08:00

171 lines
4 KiB
JavaScript

/* EVENT */
/* event_refs_pubkey checks if the event (ev) is directed at the public key
* (pubkey) by checking its type, tags, and key.
*/
function event_refs_pubkey(ev, pubkey) {
if (!(ev.kind === 1 || ev.kind === 42))
return false
if (ev.pubkey === pubkey)
return false
for (const tag of ev.tags) {
if (tag.length >= 2 && tag[0] === "p" && tag[1] === pubkey)
return true
}
return false
}
function event_calculate_pow(ev) {
const id_bits = leading_zero_bits(ev.id)
for (const tag of ev.tags) {
if (tag.length >= 3 && tag[0] === "nonce") {
const target = +tag[2]
if (isNaN(target))
return 0
// if our nonce target is smaller than the difficulty,
// then we use the nonce target as the actual difficulty
return min(target, id_bits)
}
}
// not a valid pow if we don't have a difficulty target
return 0
}
/* event_can_reply returns a boolean value based on if you can "reply" to the
* event in the manner of a chat.
*/
function event_can_reply(ev) {
return ev.kind === KIND_NOTE || ev.kind === 42
}
/* event_is_timeline returns a boolean based on if the event should be rendered
* in a GUI
*/
function event_is_timeline(ev) {
return ev.kind === KIND_NOTE || ev.kind === 42 || ev.kind === 6
}
function event_get_tag_refs(tags) {
let ids = []
let pubkeys = []
let root, reply
for (const tag of tags) {
if (tag.length >= 4 && tag[0] == "e") {
ids.push(tag[1])
if (tag[3] === "root") {
root = tag[1]
} else if (tag[3] === "reply") {
reply = tag[1]
}
} else if (tag.length >= 2 && tag[0] == "e") {
ids.push(tag[1])
} else if (tag.length >= 2 && tag[0] == "p") {
pubkeys.push(tag[1])
}
}
if (!(root && reply) && ids.length > 0) {
if (ids.length === 1)
return {root: ids[0], reply: ids[0], pubkeys}
else if (ids.length >= 2)
return {root: ids[0], reply: ids[1], pubkeys}
return {pubkeys}
}
return {root, reply, pubkeys}
}
function event_is_spam(ev, contacts, pow) {
if (contacts.friend_of_friends.has(ev.pubkey))
return true
return ev.pow >= pow
}
function event_cmp_created(a={}, b={}) {
if (a.created_at > b.created_at)
return 1;
if (a.created_at < b.created_at)
return -1;
return 0;
}
/* event_refs_event checks if event A references event B in its tags.
*/
function event_refs_event(a, b) {
for (const tag of a.tags) {
if (tag.length >= 2 && tag[0] === "e" && tag[1] == b.id)
return true;
}
return false;
}
function event_get_last_tags(ev) {
let o = {};
for (const tag of ev.tags) {
if (tag.length >= 2 && (tag[0] === "e" || tag[0] === "p"))
o[tag[0]] = tag[1];
}
return o;
}
/* event_get_reacted_to returns the reacted to event & pubkey (e, p). Returns
* undefined if invalid or incomplete.
*/
function event_parse_reaction(ev) {
if (!is_valid_reaction_content(ev.content) || ev.kind != KIND_REACTION) {
return;
}
const o = event_get_last_tags(ev);
if (o["e"]) {
return o;
}
}
async function model_save_events(model) {
function _events_save(ev, resolve, reject) {
const db = ev.target.result;
let tx = db.transaction("events", "readwrite");
let store = tx.objectStore("events");
for (const evid in model.all_events) {
store.put(model.all_events[evid]);
}
tx.oncomplete = (ev) => {
db.close();
resolve();
log_debug("saved events!");
};
tx.onerror = (ev) => {
db.close();
log_error("failed to save events");
reject(ev);
};
}
return dbcall(_events_save);
}
async function model_load_events(model, fn) {
function _events_load(ev, resolve, reject) {
const db = ev.target.result;
const tx = db.transaction("events", "readonly");
const store = tx.objectStore("events");
const cursor = store.openCursor();
cursor.onsuccess = (ev) => {
var cursor = ev.target.result;
if (cursor) {
fn(cursor.value);
cursor.continue();
} else {
db.close();
resolve();
log_debug("Successfully loaded events");
}
}
cursor.onerror = (ev) => {
db.close();
reject(ev);
log_error("Could not load events.");
};
}
return dbcall(_events_load);
}