mirror of
https://github.com/Permissionless-Software-Foundation/psf-memo-db.git
synced 2026-09-21 16:52:02 -07:00
Adding endpoint for most recent posts
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
Utility: read all follows from the Memo indexer LevelDB and print to the terminal.
|
||||
|
||||
Run from the psf-memo-db repo root:
|
||||
node util/follow/get_follows.js
|
||||
*/
|
||||
|
||||
import level from 'level'
|
||||
import * as url from 'url'
|
||||
|
||||
const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
|
||||
|
||||
const followsDb = level(`${__dirname}/../../leveldb/current/follows`, {
|
||||
valueEncoding: 'json'
|
||||
})
|
||||
|
||||
async function getFollows () {
|
||||
try {
|
||||
let count = 0
|
||||
|
||||
for await (const [key, follow] of followsDb.iterator()) {
|
||||
count++
|
||||
console.log(`${key} = ${JSON.stringify(follow, null, 2)}`)
|
||||
}
|
||||
|
||||
console.log(`\nTotal follows: ${count}`)
|
||||
await followsDb.close()
|
||||
} catch (err) {
|
||||
console.error('Error reading follows:', err.message)
|
||||
try {
|
||||
await followsDb.close()
|
||||
} catch (closeErr) {
|
||||
// ignore close errors after read failure
|
||||
}
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
getFollows()
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
Utility: read all likes from the Memo indexer LevelDB and print to the terminal.
|
||||
|
||||
Run from the psf-memo-db repo root:
|
||||
node util/like/get_likes.js
|
||||
*/
|
||||
|
||||
import level from 'level'
|
||||
import * as url from 'url'
|
||||
|
||||
const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
|
||||
|
||||
const likesDb = level(`${__dirname}/../../leveldb/current/likes`, {
|
||||
valueEncoding: 'json'
|
||||
})
|
||||
|
||||
async function getLikes () {
|
||||
try {
|
||||
let count = 0
|
||||
|
||||
for await (const [txid, like] of likesDb.iterator()) {
|
||||
count++
|
||||
console.log(`${txid} = ${JSON.stringify(like, null, 2)}`)
|
||||
}
|
||||
|
||||
console.log(`\nTotal likes: ${count}`)
|
||||
await likesDb.close()
|
||||
} catch (err) {
|
||||
console.error('Error reading likes:', err.message)
|
||||
try {
|
||||
await likesDb.close()
|
||||
} catch (closeErr) {
|
||||
// ignore close errors after read failure
|
||||
}
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
getLikes()
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
Utility: read all names from the Memo indexer LevelDB and print to the terminal.
|
||||
|
||||
Run from the psf-memo-db repo root:
|
||||
node util/name/get_names.js
|
||||
*/
|
||||
|
||||
import level from 'level'
|
||||
import * as url from 'url'
|
||||
|
||||
const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
|
||||
|
||||
const namesDb = level(`${__dirname}/../../leveldb/current/names`, {
|
||||
valueEncoding: 'json'
|
||||
})
|
||||
|
||||
async function getNames () {
|
||||
try {
|
||||
let count = 0
|
||||
|
||||
for await (const [addr, name] of namesDb.iterator()) {
|
||||
count++
|
||||
console.log(`${addr} = ${JSON.stringify(name, null, 2)}`)
|
||||
}
|
||||
|
||||
console.log(`\nTotal names: ${count}`)
|
||||
await namesDb.close()
|
||||
} catch (err) {
|
||||
console.error('Error reading names:', err.message)
|
||||
try {
|
||||
await namesDb.close()
|
||||
} catch (closeErr) {
|
||||
// ignore close errors after read failure
|
||||
}
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
getNames()
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
Utility: read all postChildren from the Memo indexer LevelDB and print to the terminal.
|
||||
|
||||
Run from the psf-memo-db repo root:
|
||||
node util/postchild/get_post_children.js
|
||||
*/
|
||||
|
||||
import level from 'level'
|
||||
import * as url from 'url'
|
||||
|
||||
const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
|
||||
|
||||
const postChildrenDb = level(`${__dirname}/../../leveldb/current/postChildren`, {
|
||||
valueEncoding: 'json'
|
||||
})
|
||||
|
||||
async function getPostChildren () {
|
||||
try {
|
||||
let count = 0
|
||||
|
||||
for await (const [txid, child] of postChildrenDb.iterator()) {
|
||||
count++
|
||||
console.log(`${txid} = ${JSON.stringify(child, null, 2)}`)
|
||||
}
|
||||
|
||||
console.log(`\nTotal post children: ${count}`)
|
||||
await postChildrenDb.close()
|
||||
} catch (err) {
|
||||
console.error('Error reading postChildren:', err.message)
|
||||
try {
|
||||
await postChildrenDb.close()
|
||||
} catch (closeErr) {
|
||||
// ignore close errors after read failure
|
||||
}
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
getPostChildren()
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
Utility: read all postParents from the Memo indexer LevelDB and print to the terminal.
|
||||
|
||||
Run from the psf-memo-db repo root:
|
||||
node util/postparent/get_post_parents.js
|
||||
*/
|
||||
|
||||
import level from 'level'
|
||||
import * as url from 'url'
|
||||
|
||||
const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
|
||||
|
||||
const postParentsDb = level(`${__dirname}/../../leveldb/current/postParents`, {
|
||||
valueEncoding: 'json'
|
||||
})
|
||||
|
||||
async function getPostParents () {
|
||||
try {
|
||||
let count = 0
|
||||
|
||||
for await (const [txid, parent] of postParentsDb.iterator()) {
|
||||
count++
|
||||
console.log(`${txid} = ${JSON.stringify(parent, null, 2)}`)
|
||||
}
|
||||
|
||||
console.log(`\nTotal post parents: ${count}`)
|
||||
await postParentsDb.close()
|
||||
} catch (err) {
|
||||
console.error('Error reading postParents:', err.message)
|
||||
try {
|
||||
await postParentsDb.close()
|
||||
} catch (closeErr) {
|
||||
// ignore close errors after read failure
|
||||
}
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
getPostParents()
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
Utility: read all profilePics from the Memo indexer LevelDB and print to the terminal.
|
||||
|
||||
Run from the psf-memo-db repo root:
|
||||
node util/profilepic/get_profile_pics.js
|
||||
*/
|
||||
|
||||
import level from 'level'
|
||||
import * as url from 'url'
|
||||
|
||||
const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
|
||||
|
||||
const profilePicsDb = level(`${__dirname}/../../leveldb/current/profilePics`, {
|
||||
valueEncoding: 'json'
|
||||
})
|
||||
|
||||
async function getProfilePics () {
|
||||
try {
|
||||
let count = 0
|
||||
|
||||
for await (const [addr, profilePic] of profilePicsDb.iterator()) {
|
||||
count++
|
||||
console.log(`${addr} = ${JSON.stringify(profilePic, null, 2)}`)
|
||||
}
|
||||
|
||||
console.log(`\nTotal profile pics: ${count}`)
|
||||
await profilePicsDb.close()
|
||||
} catch (err) {
|
||||
console.error('Error reading profilePics:', err.message)
|
||||
try {
|
||||
await profilePicsDb.close()
|
||||
} catch (closeErr) {
|
||||
// ignore close errors after read failure
|
||||
}
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
getProfilePics()
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
Utility: backfill profile `seen` timestamps from on-chain block header times.
|
||||
|
||||
Reads each profile's txid, looks up blockHeight in ptxs, fetches block header
|
||||
time via BCH RPC, and writes seen = block.time * 1000 (Unix ms).
|
||||
|
||||
Run from the psf-memo-db repo root (memo-db must be stopped to avoid lock conflicts):
|
||||
node util/profiles/backfill_seen.js
|
||||
|
||||
Environment (same as psf-memo-indexer):
|
||||
RPC_IP, RPC_PORT, RPC_USER, RPC_PASS
|
||||
*/
|
||||
|
||||
import 'dotenv/config'
|
||||
import level from 'level'
|
||||
import * as url from 'url'
|
||||
|
||||
const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
|
||||
|
||||
const rpcIp = process.env.RPC_IP || '172.17.0.1'
|
||||
const rpcPort = process.env.RPC_PORT || '8332'
|
||||
const rpcUser = process.env.RPC_USER || 'bitcoin'
|
||||
const rpcPass = process.env.RPC_PASS || 'password'
|
||||
|
||||
const profilesDb = level(`${__dirname}/../../leveldb/current/profiles`, {
|
||||
valueEncoding: 'json'
|
||||
})
|
||||
|
||||
const ptxsDb = level(`${__dirname}/../../leveldb/current/ptxs`, {
|
||||
valueEncoding: 'json'
|
||||
})
|
||||
|
||||
const blockTimeCache = new Map()
|
||||
|
||||
async function rpcCall (method, params = []) {
|
||||
const response = await fetch(`http://${rpcIp}:${rpcPort}/`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Basic ${Buffer.from(`${rpcUser}:${rpcPass}`).toString('base64')}`
|
||||
},
|
||||
body: JSON.stringify({
|
||||
jsonrpc: '1.0',
|
||||
id: method,
|
||||
method,
|
||||
params
|
||||
})
|
||||
})
|
||||
|
||||
const body = await response.json()
|
||||
if (body.error) {
|
||||
throw new Error(body.error.message || `RPC ${method} failed`)
|
||||
}
|
||||
return body.result
|
||||
}
|
||||
|
||||
async function getBlockTimeMs (blockHeight) {
|
||||
if (blockTimeCache.has(blockHeight)) {
|
||||
return blockTimeCache.get(blockHeight)
|
||||
}
|
||||
|
||||
const hash = await rpcCall('getblockhash', [blockHeight])
|
||||
const header = await rpcCall('getblockheader', [hash, true])
|
||||
const seen = header.time * 1000
|
||||
blockTimeCache.set(blockHeight, seen)
|
||||
return seen
|
||||
}
|
||||
|
||||
async function backfillProfiles () {
|
||||
let updated = 0
|
||||
let skipped = 0
|
||||
let errors = 0
|
||||
|
||||
try {
|
||||
for await (const [addr, profile] of profilesDb.iterator()) {
|
||||
try {
|
||||
if (!profile.txid) {
|
||||
skipped++
|
||||
continue
|
||||
}
|
||||
|
||||
const ptx = await ptxsDb.get(profile.txid)
|
||||
if (!ptx || ptx.blockHeight === undefined) {
|
||||
console.warn(`No ptx blockHeight for ${addr} txid ${profile.txid}`)
|
||||
skipped++
|
||||
continue
|
||||
}
|
||||
|
||||
const seen = await getBlockTimeMs(ptx.blockHeight)
|
||||
if (profile.seen === seen) {
|
||||
skipped++
|
||||
continue
|
||||
}
|
||||
|
||||
await profilesDb.put(addr, { ...profile, seen })
|
||||
updated++
|
||||
console.log(`${addr}: seen ${profile.seen} -> ${seen} (block ${ptx.blockHeight})`)
|
||||
} catch (err) {
|
||||
errors++
|
||||
console.error(`Error updating ${addr}:`, err.message)
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`\nBackfill complete. Updated: ${updated}, skipped: ${skipped}, errors: ${errors}`)
|
||||
} finally {
|
||||
await profilesDb.close()
|
||||
await ptxsDb.close()
|
||||
}
|
||||
}
|
||||
|
||||
backfillProfiles().catch((err) => {
|
||||
console.error('Backfill failed:', err.message)
|
||||
process.exit(1)
|
||||
})
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
Utility: read all ptxs (processed transactions) from the Memo indexer LevelDB and print to the terminal.
|
||||
|
||||
Run from the psf-memo-db repo root:
|
||||
node util/ptx/get_ptxs.js
|
||||
*/
|
||||
|
||||
import level from 'level'
|
||||
import * as url from 'url'
|
||||
|
||||
const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
|
||||
|
||||
const ptxsDb = level(`${__dirname}/../../leveldb/current/ptxs`, {
|
||||
valueEncoding: 'json'
|
||||
})
|
||||
|
||||
async function getPtxs () {
|
||||
try {
|
||||
let count = 0
|
||||
|
||||
for await (const [txid, ptx] of ptxsDb.iterator()) {
|
||||
count++
|
||||
console.log(`${txid} = ${JSON.stringify(ptx, null, 2)}`)
|
||||
}
|
||||
|
||||
console.log(`\nTotal ptxs: ${count}`)
|
||||
await ptxsDb.close()
|
||||
} catch (err) {
|
||||
console.error('Error reading ptxs:', err.message)
|
||||
try {
|
||||
await ptxsDb.close()
|
||||
} catch (closeErr) {
|
||||
// ignore close errors after read failure
|
||||
}
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
getPtxs()
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
Utility: read all rooms from the Memo indexer LevelDB and print to the terminal.
|
||||
|
||||
Run from the psf-memo-db repo root:
|
||||
node util/room/get_rooms.js
|
||||
*/
|
||||
|
||||
import level from 'level'
|
||||
import * as url from 'url'
|
||||
|
||||
const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
|
||||
|
||||
const roomsDb = level(`${__dirname}/../../leveldb/current/rooms`, {
|
||||
valueEncoding: 'json'
|
||||
})
|
||||
|
||||
async function getRooms () {
|
||||
try {
|
||||
let count = 0
|
||||
|
||||
for await (const [key, room] of roomsDb.iterator()) {
|
||||
count++
|
||||
console.log(`${key} = ${JSON.stringify(room, null, 2)}`)
|
||||
}
|
||||
|
||||
console.log(`\nTotal rooms: ${count}`)
|
||||
await roomsDb.close()
|
||||
} catch (err) {
|
||||
console.error('Error reading rooms:', err.message)
|
||||
try {
|
||||
await roomsDb.close()
|
||||
} catch (closeErr) {
|
||||
// ignore close errors after read failure
|
||||
}
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
getRooms()
|
||||
Reference in New Issue
Block a user