import { decode } from './lib/base64.js'
import { cachekv } from './lib/cachekv.js'
import { human } from './lib/human.js'
import { vb } from './lib/vb.js'
import { an } from 'https://esm.sh/gh/evbogue/anproto@ddc040c/an.js'
let db
let hashLog = []
let openedLog = []
let newMessages = false
let sort = true
export const apds = {}
apds.start = async (appId) => {
db = await cachekv(appId)
setInterval(async () => {
if (newMessages) {
await db.put('hashlog', JSON.stringify(hashLog))
await db.put('openedlog', JSON.stringify(openedLog))
newMessages = false
}
}, 1000)
const getHashLog = await db.get('hashlog')
const getOpenedLog = await db.get('openedlog')
if (getHashLog) {
hashLog = JSON.parse(getHashLog)
}
if (getOpenedLog) {
openedLog = JSON.parse(getOpenedLog)
}
setInterval(async () => {
if (sort) {
const newArray = []
await Promise.all(hashLog.map(async (hash) => {
try {
const obj = {
hash,
sig: await apds.get(hash)
}
obj.author = obj.sig.substring(0, 44)
obj.opened = await apds.open(obj.sig)
obj.text = await apds.get(obj.opened.substring(13))
obj.ts = obj.opened.substring(0, 13)
newArray.push(obj)
} catch (err) { /*console.log(err)*/ }
}))
const newLog = []
await newArray.sort((a,b) => a.ts - b.ts)
await newArray.forEach(msg => {
newLog.push(msg.hash)
})
hashLog = newLog
openedLog = newArray
newMessages = true
sort = false
}
}, 20000)
}
apds.generate = async () => {
const genkey = await an.gen()
return genkey
}
apds.keypair = async () => {
const keypair = await db.get('keypair')
if (keypair) {
return keypair
}
}
apds.pubkey = async () => {
const keypair = await apds.keypair()
if (keypair) {
return keypair.substring(0, 44)
}
}
apds.privkey = async () => {
const keypair = await apds.keypair()
if (keypair) {
return keypair.substring(44)
}
}
apds.deletekey = async () => {
db.rm('keypair')
}
apds.clear = async () => {
db.clear()
}
apds.hash = async (data) => { return await an.hash(data) }
apds.sign = async (data) => {
const hash = await apds.make(data)
const sig = await an.sign(hash, await apds.keypair())
await apds.add(sig)
const protocolMsg = await apds.make(sig)
db.put('previous', protocolMsg)
return protocolMsg
}
apds.open = async (msg) => {
try {
if (msg.endsWith('==')) {
return await an.open(msg)
} //else {
//console.log('NOT A VALID SIGNATURE ' + msg)
//}
} catch (err) {
//console.log('Not a valid ANProto message')
}
}
import { yaml } from './lib/yaml.js'
apds.parseYaml = async (doc) => {
return await yaml.parse(doc)
}
apds.createYaml = async (obj, content) => {
return await yaml.create(obj, content)
}
apds.compose = async (content, prev) => {
let obj = {}
if (prev) { obj = prev }
const name = await db.get('name')
const image = await db.get('image')
const previous = await db.get('previous')
if (name) { obj.name = name}
if (image) { obj.image = image}
if (previous) { obj.previous = previous}
if (Object.keys(obj).length > 0) {
const yaml = await apds.createYaml(obj, content)
return await apds.sign(yaml)
} else {
return await apds.sign(content)
}
}
apds.make = async (data) => {
const hash = await apds.hash(data)
await db.put(hash, data)
return hash
}
apds.get = async (hash) => {
const blob = await db.get(hash)
return blob
}
apds.put = async (key, value) => {
await db.put(key, value)
}
apds.rm = async (key) => {
await db.rm(key)
}
apds.add = async (msg) => {
const opened = await apds.open(msg)
if (opened) {
const hash = await apds.make(msg)
if (!hashLog.includes(hash)) {
hashLog.push(hash)
const obj = {
hash,
sig: msg
}
obj.author = obj.sig.substring(0, 44)
obj.opened = opened
obj.text = await apds.get(obj.opened.substring(13))
obj.ts = obj.opened.substring(0, 13)
openedLog.push(obj)
newMessages = true
sort = true
return true
}
}
}
apds.getHashLog = async () => { return hashLog }
apds.getOpenedLog = async () => { return openedLog }
apds.query = async (query) => {
if (openedLog[0] && !query) { return openedLog }
if (openedLog[0] && query.startsWith('?')) {
const search = query.substring(1).replace(/%20/g, ' ').toUpperCase()
const result = openedLog.filter(msg => msg.text && msg.text.toUpperCase().includes(search))
return result
} else if (openedLog[0]) {
const result = openedLog.filter(msg => msg.author == query || msg.hash == query)
return result
}
}
apds.getPubkeys = async () => {
const arr = await apds.query()
const newSet = new Set()
for (const msg of arr) {
newSet.add(msg.author)
}
const newArr = [...newSet]
return newArr
}
apds.getLatest = async (pubkey) => {
const q = openedLog.filter(msg => msg.author === pubkey)
return q[q.length -1]
}
apds.human = async (ts) => {
return await human(new Date(parseInt(ts)))
}
apds.visual = async (pubkey) => {
return vb(decode(pubkey), 256)
}