forked from snxraven/p2ns
Global Paste Feed
This commit is contained in:
@@ -141,7 +141,7 @@ curl -sS "https://peer.paste/api/pastes/${PASTE_ID}/raw" | jq .
|
||||
- Attachment cap:
|
||||
- max attachments processed: `16`
|
||||
- max total attachment bytes: `64MB`
|
||||
- Burn-after-first-read pastes are intentionally excluded from recent active lists.
|
||||
- The realtime sidebar lists **all active pastes** in the replicated database (every peer), not only local ones. Burn-after-read pastes are excluded from that feed.
|
||||
- Cleanup task runs hourly and removes expired/consumed entries.
|
||||
- Paste data is replicated via HyperDB.
|
||||
|
||||
|
||||
@@ -322,7 +322,11 @@ function toPublicPaste(paste, includeOwner = false) {
|
||||
expiresInMs: Math.max(0, paste.expiresAt - t),
|
||||
isExpired: paste.expiresAt <= t
|
||||
};
|
||||
if (includeOwner) out.ownerPeerId = paste.ownerPeerId || '';
|
||||
if (includeOwner) {
|
||||
out.ownerPeerId = paste.ownerPeerId || '';
|
||||
const localPeer = sdk.state.localPeerId || '';
|
||||
if (localPeer) out.isMine = (paste.ownerPeerId || '') === localPeer;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -553,7 +557,7 @@ async function listPastes(req, res, ownerOnly = false) {
|
||||
items.sort((a, b) => b.createdAt - a.createdAt);
|
||||
const total = items.length;
|
||||
const page = items.slice(offset, offset + limit);
|
||||
const pastes = page.map((p) => toPublicPaste(p, ownerOnly));
|
||||
const pastes = page.map((p) => toPublicPaste(p, true));
|
||||
|
||||
return sdk.router.json(res, {
|
||||
count: pastes.length,
|
||||
@@ -1357,12 +1361,17 @@ function buildOpenApi(baseUrl) {
|
||||
};
|
||||
}
|
||||
|
||||
async function getRecentPastesPage(ownerOnly = true, offset = 0, limit = DEFAULT_PAGE_SIZE) {
|
||||
async function getRecentPastesPage(ownerOnly = false, offset = 0, limit = DEFAULT_PAGE_SIZE) {
|
||||
return withPeerPasteContext(async () => {
|
||||
try {
|
||||
await sdk.db.update();
|
||||
} catch (err) {
|
||||
sdk.log.debug('peer.paste', `db.update before recent list: ${err.message}`);
|
||||
}
|
||||
const { rows: all, timedOut } = await safeFindPastes({
|
||||
includeExpired: false,
|
||||
maxEntries: MAX_LIST_SCAN,
|
||||
context: 'getRecentPastesPage'
|
||||
context: ownerOnly ? 'getRecentPastesPage(mine)' : 'getRecentPastesPage(all)'
|
||||
});
|
||||
const ownerPeerId = sdk.state.localPeerId || '';
|
||||
let items = all.filter((p) => !p.destroyOnRead);
|
||||
@@ -1383,7 +1392,7 @@ async function getRecentPastesPage(ownerOnly = true, offset = 0, limit = DEFAULT
|
||||
|
||||
async function broadcastRecentPastesUpdate() {
|
||||
try {
|
||||
const page = await getRecentPastesPage(true, 0, DEFAULT_PAGE_SIZE);
|
||||
const page = await getRecentPastesPage(false, 0, DEFAULT_PAGE_SIZE);
|
||||
sdk.websocket.broadcast({
|
||||
type: 'pastes-updated',
|
||||
data: page
|
||||
@@ -1402,7 +1411,7 @@ function setupWebSocketHandlers() {
|
||||
sdk.websocket.on('connection', async (ws) => {
|
||||
return withPeerPasteContext(async () => {
|
||||
try {
|
||||
const initial = await getRecentPastesPage(true, 0, DEFAULT_PAGE_SIZE);
|
||||
const initial = await getRecentPastesPage(false, 0, DEFAULT_PAGE_SIZE);
|
||||
sdk.websocket.send(ws, { type: 'init', data: initial });
|
||||
} catch (err) {
|
||||
sdk.websocket.send(ws, { type: 'error', error: err.message });
|
||||
@@ -1417,7 +1426,7 @@ function setupWebSocketHandlers() {
|
||||
if (message.type === 'request-pastes') {
|
||||
const offset = Math.max(0, Number(message.offset) || 0);
|
||||
const limit = Math.max(1, Math.min(100, Number(message.limit) || DEFAULT_PAGE_SIZE));
|
||||
const page = await getRecentPastesPage(true, offset, limit);
|
||||
const page = await getRecentPastesPage(false, offset, limit);
|
||||
sdk.websocket.send(ws, { type: 'pastes-page', data: page, requestId: message.requestId || null });
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -214,13 +214,17 @@ function renderRecentList() {
|
||||
}
|
||||
list.innerHTML = rows.map((p) => {
|
||||
const idLabel = p.id.length > 14 ? `${p.id.slice(0, 12)}…` : p.id;
|
||||
const owner = p.ownerPeerId || '';
|
||||
const ownerLabel = owner.length > 10 ? `${owner.slice(0, 8)}…` : owner;
|
||||
const isMine = !!p.isMine;
|
||||
return `
|
||||
<article class="paste-item">
|
||||
<article class="paste-item${isMine ? ' paste-item-mine' : ''}">
|
||||
<div class="paste-title" title="${escapeHtml(p.id)}">${escapeHtml(idLabel)}</div>
|
||||
<div class="paste-meta">
|
||||
<span>${msToHuman(p.expiresInMs)}</span>
|
||||
<span>${p.readCount}${p.maxReads ? `/${p.maxReads}` : ''} reads</span>
|
||||
<span>${escapeHtml(p.format || 'text')}</span>
|
||||
${owner ? `<span class="paste-owner" title="${escapeHtml(owner)}">${isMine ? 'you' : escapeHtml(ownerLabel)}</span>` : ''}
|
||||
</div>
|
||||
<div class="paste-actions">
|
||||
<a href="/p/${p.id}" target="_blank" rel="noopener">Open</a>
|
||||
|
||||
@@ -569,6 +569,15 @@ button:hover,
|
||||
border-color: rgba(99, 102, 241, 0.35);
|
||||
}
|
||||
|
||||
.paste-item-mine {
|
||||
border-color: rgba(99, 102, 241, 0.4);
|
||||
}
|
||||
|
||||
.paste-owner {
|
||||
font-family: var(--font-mono);
|
||||
color: var(--text-tertiary);
|
||||
}
|
||||
|
||||
.paste-title {
|
||||
color: var(--text);
|
||||
font-weight: 600;
|
||||
|
||||
Reference in New Issue
Block a user