Files
strfry/src/apps/web/static/oddbean.js
2024-08-29 14:08:43 -04:00

240 lines
6.8 KiB
JavaScript

const bech32Ctx = genBech32('bech32');
function encodeBech32(prefix, inp) {
return bech32Ctx.encode(prefix, bech32Ctx.toWords(base16.decode(inp.toUpperCase())));
}
function decodeBech32(inp) {
return base16.encode(bech32Ctx.fromWords(bech32Ctx.decode(inp).words)).toLowerCase();
}
document.addEventListener('alpine:init', () => {
Alpine.data('obLogin', () => ({
loggedIn: false,
pubkey: '',
username: '',
init() {
let storage = JSON.parse(window.localStorage.getItem('auth') || '{}');
if (storage.pubkey) {
this.loggedIn = true;
this.pubkey = storage.pubkey;
this.username = storage.username;
}
},
async login() {
if (!window.nostr) {
window.location = "/login";
return;
}
let pubkey = await nostr.getPublicKey();
let response = await fetch(`/u/${pubkey}/metadata.json`);
let json = await response.json();
console.log(json);
let username = json.name;
if (username === undefined) username = pubkey.substr(0, 8) + '...';
if (username.length > 25) username = username.substr(0, 25) + '...';
this.pubkey = pubkey;
this.username = username;
window.localStorage.setItem('auth', JSON.stringify({ pubkey, username, }));
this.loggedIn = true;
},
myProfile() {
return `/u/${encodeBech32('npub', this.pubkey)}`;
},
logout() {
window.localStorage.setItem('auth', '{}');
this.loggedIn = false;
},
}));
Alpine.data('newPost', () => ({
init() {
},
async submit() {
this.$refs.msg.innerText = '';
let ev = {
created_at: Math.floor(((new Date()) - 0) / 1000),
kind: 1,
tags: [['t', 'oddbean']],
content: this.$refs.post.value,
};
ev = await window.nostr.signEvent(ev);
let resp = await fetch("/submit-post", {
method: "post",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(ev),
});
let json = await resp.json();
if (json.message === 'ok' && json.written === true) {
window.location = `/e/${json.event}`
} else {
this.$refs.msg.innerText = `Sending note failed: ${json.message}`;
console.error(json);
}
},
}));
Alpine.data('newReply', (note) => ({
async init() {
let resp = await fetch(`/e/${note}/raw.json`);
this.repliedTo = await resp.json();
},
async submit() {
this.$refs.msg.innerText = '';
let ev = {
created_at: Math.floor(((new Date()) - 0) / 1000),
kind: 1,
tags: [],
content: this.$refs.post.value,
};
{
// e tags
let rootId;
for (let t of this.repliedTo.tags) {
if (t[0] === 'e' && t[3] === 'root') {
rootId = t[1];
break;
}
}
if (!rootId) {
for (let t of this.repliedTo.tags) {
if (t[0] === 'e') {
rootId = t[1];
break;
}
}
}
if (rootId) {
ev.tags.push(['e', rootId, '', 'root']);
ev.tags.push(['e', this.repliedTo.id, '', 'reply']);
} else {
ev.tags.push(['e', this.repliedTo.id, '', 'root']);
}
// p tags
let seenPTags = {};
for (let t of this.repliedTo.tags) {
if (t[0] === 'p' && !seenPTags[t[1]]) {
ev.tags.push(['p', t[1]]);
seenPTags[t[1]] = true;
}
}
if (!seenPTags[this.repliedTo.pubkey]) {
ev.tags.push(['p', this.repliedTo.pubkey]);
}
}
ev = await window.nostr.signEvent(ev);
let resp = await fetch("/submit-post", {
method: "post",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(ev),
});
let json = await resp.json();
if (json.message === 'ok' && json.written === true) {
window.location = `/e/${json.event}`
} else {
this.$refs.msg.innerText = `Sending note failed: ${json.message}`;
console.error(json);
}
},
}))
});
document.addEventListener("click", async (e) => {
let parent = e.target.closest(".vote-context");
if (!parent) return;
let which = e.target.className;
if (which.length !== 1) return;
let note = parent.getAttribute('data-note');
e.target.className = 'loading';
e.target.innerText = '↻';
if (which === 'f') return; // not impl
try {
let ev = {
created_at: Math.floor(((new Date()) - 0) / 1000),
kind: 7,
tags: [],
content: which === 'u' ? '+' : '-',
};
{
let response = await fetch(`/e/${note}/raw.json`);
let liked = await response.json();
//for (let tag of liked.tags) {
// if (tag.length >= 2 && (tag[0] === 'e' || tag[0] === 'p')) ev.tags.push(tag);
//}
ev.tags.push(['e', liked.id]);
//ev.tags.push(['p', liked.pubkey]);
}
ev = await window.nostr.signEvent(ev);
let response = await fetch("/submit-post", {
method: "post",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(ev),
});
let json = await response.json();
if (json.message === 'ok' && json.written === true) {
e.target.className = 'success';
e.target.innerText = '✔';
} else {
throw(Error(`Sending reaction note failed: ${json.message}`));
console.error(json);
}
} catch(err) {
console.error(err);
e.target.className = 'error';
e.target.innerText = '✘';
}
});