upstream: integrar Oasis 1.3.1
Base del merge a tres bandas: git 0.9.5 de epsylon, esta rama y el src de la
APK oficial 1.3.1 (la variante movil: OASIS_MOBILE, regex sin \p{}, audio y
video de Android). Corre en el mismo nodejs-mobile 18.20.4 que ya usabamos.
Se conserva de la rama: Karvan, identidades y multicuenta, topbar y barra
inferior, borrado de EXIF sin sharp, filtro hot del foro, RTC sin STUN y los
modulos apagados en movil (wallet, banking, torrents).
Se toma de upstream lo que ya hace de serie: respuesta citada en chats, ssb-lan
en movil, configuracion en ~/.ssb/oasis (sobrevive a reinstalar el backend).
El asistente de bienvenida deja elegir workflow tambien en movil.
This commit is contained in:
parent
8d838dd8b1
commit
c332afd6ea
265 changed files with 80970 additions and 29167 deletions
|
|
@ -2,6 +2,9 @@ const pull = require('../server/node_modules/pull-stream');
|
|||
const moment = require('../server/node_modules/moment');
|
||||
const { getConfig } = require('../configs/config-manager.js');
|
||||
const { buildValidatedTombstoneSet } = require('./tombstone_validator');
|
||||
const { readTyped, CONTENT_TYPES } = require('./typed_log');
|
||||
const longText = require('../backend/long_text');
|
||||
const { versionGroups, versionEntry } = require('../backend/dedupe');
|
||||
const logLimit = getConfig().ssbLogStream?.limit || 1000;
|
||||
|
||||
module.exports = ({ cooler, padsModel, tribeCrypto, tribesModel }) => {
|
||||
|
|
@ -39,8 +42,8 @@ module.exports = ({ cooler, padsModel, tribeCrypto, tribesModel }) => {
|
|||
const searchableTypes = [
|
||||
'post', 'about', 'curriculum', 'tribe', 'transfer', 'feed',
|
||||
'votes', 'report', 'task', 'event', 'bookmark', 'document',
|
||||
'image', 'audio', 'video', 'torrent', 'market', 'bankWallet', 'bankClaim',
|
||||
'project', 'job', 'housing', 'industry', 'industryBlueprint', 'forum', 'vote', 'contact', 'pub', 'map', 'shop', 'shopProduct', 'chat', 'pad', 'poll'
|
||||
'image', 'audio', 'video', 'torrent', 'file', 'market', 'bankWallet', 'bankClaim',
|
||||
'project', 'job', 'housing', 'industry', 'industryBlueprint', 'forum', 'vote', 'contact', 'pub', 'map', 'shop', 'shopProduct', 'chat', 'pad', 'room', 'poll', 'schoolCourse', 'wikiPage', 'emergency', 'mailingList', 'logisticsRoute', 'podcast', 'podcastEpisode', 'campaign'
|
||||
];
|
||||
|
||||
const getRelevantFields = (type, content) => {
|
||||
|
|
@ -66,6 +69,7 @@ module.exports = ({ cooler, padsModel, tribeCrypto, tribesModel }) => {
|
|||
case 'document':
|
||||
return [content?.url, content?.title, content?.description, ...(content?.tags || []), content?.key];
|
||||
case 'torrent':
|
||||
case 'file':
|
||||
return [content?.title, content?.description, ...(content?.tags || []), content?.url];
|
||||
case 'market':
|
||||
return [content?.item_type, content?.title, content?.description, content?.price, ...(content?.tags || []), content?.status, content?.item_status, content?.deadline, content?.includesShipping, content?.seller, content?.image, content?.auctions_poll, content?.stock];
|
||||
|
|
@ -83,6 +87,8 @@ module.exports = ({ cooler, padsModel, tribeCrypto, tribesModel }) => {
|
|||
return [content?.address];
|
||||
case 'bankClaim':
|
||||
return [content?.amount, content?.epochId, content?.allocationId, content?.txid];
|
||||
case 'schoolCourse':
|
||||
return [content?.title, content?.description, ...(content?.tags || []), content?.price, content?.status, content?.visibility];
|
||||
case 'project':
|
||||
return [content?.title, content?.status, content?.progress, content?.goal, content?.pledged, content?.deadline, (content?.followers || []).length, (content?.backers || []).length, (content?.milestones || []).length, content?.bounty, content?.bountyAmount, content?.bounty_currency, content?.activity?.kind, content?.activityActor];
|
||||
case 'poll':
|
||||
|
|
@ -115,6 +121,22 @@ module.exports = ({ cooler, padsModel, tribeCrypto, tribesModel }) => {
|
|||
return [content?.title, content?.description, content?.category, ...(content?.tags || []), content?.status, content?.author];
|
||||
case 'pad':
|
||||
return [content?.title, content?.status, content?.deadline, ...(content?.tags || []), content?.author];
|
||||
case 'room':
|
||||
return content?.encrypted === true ? [] : [content?.title, content?.description, content?.status, ...(content?.tags || []), content?.author];
|
||||
case 'wikiPage':
|
||||
return [content?.title, content?.body, content?.slug, ...(content?.tags || []), ...(content?.aliases || []), content?.author];
|
||||
case 'emergency':
|
||||
return [content?.title, content?.text, content?.category, content?.status, ...(content?.tags || []), content?.author];
|
||||
case 'mailingList':
|
||||
return [content?.title, content?.description, content?.listType, content?.status, ...(content?.tags || []), content?.author];
|
||||
case 'logisticsRoute':
|
||||
return [content?.title, content?.description, content?.origin, content?.destination, content?.kind, content?.mode, ...(content?.tags || []), content?.author];
|
||||
case 'podcast':
|
||||
return [content?.title, content?.description, content?.category, ...(content?.tags || []), content?.author];
|
||||
case 'podcastEpisode':
|
||||
return [content?.title, content?.description, ...(content?.tags || []), content?.author];
|
||||
case 'campaign':
|
||||
return [content?.title, content?.text, content?.category, content?.status, ...(content?.tags || []), content?.author];
|
||||
case 'gameScore':
|
||||
return [content?.game, content?.player];
|
||||
default:
|
||||
|
|
@ -144,6 +166,7 @@ module.exports = ({ cooler, padsModel, tribeCrypto, tribesModel }) => {
|
|||
if (t === 'audio') return `audio:${c.url || `${author}|${norm(c.title)}|${norm(c.description)}` || msg.key}`;
|
||||
if (t === 'video') return `video:${c.url || `${author}|${norm(c.title)}|${norm(c.description)}` || msg.key}`;
|
||||
if (t === 'torrent') return `torrent:${c.url || `${author}|${norm(c.title)}|${norm(c.description)}` || msg.key}`;
|
||||
if (t === 'file') return `file:${c.url || `${author}|${norm(c.title)}|${norm(c.description)}` || msg.key}`;
|
||||
if (t === 'bookmark') return `bookmark:${author}|${c.url || norm(c.description) || msg.key}`;
|
||||
|
||||
if (t === 'tribe') {
|
||||
|
|
@ -228,6 +251,9 @@ module.exports = ({ cooler, padsModel, tribeCrypto, tribesModel }) => {
|
|||
].join('|');
|
||||
}
|
||||
|
||||
if (t === 'schoolCourse') {
|
||||
return ['schoolCourse', author, norm(c.title), norm(c.createdAt)].join('|');
|
||||
}
|
||||
if (t === 'project') {
|
||||
return [
|
||||
'project',
|
||||
|
|
@ -288,6 +314,30 @@ module.exports = ({ cooler, padsModel, tribeCrypto, tribesModel }) => {
|
|||
return ['pad', author, norm(c.title), norm(c.deadline)].join('|');
|
||||
}
|
||||
|
||||
if (t === 'room') {
|
||||
return ['room', author, norm(c.rid || c.title), norm(c.createdAt)].join('|');
|
||||
}
|
||||
|
||||
if (t === 'wikiPage') {
|
||||
return ['wikiPage', norm(c.tribeId), norm(c.slug)].join('|');
|
||||
}
|
||||
|
||||
if (t === 'emergency') {
|
||||
return ['emergency', author, norm(c.title), norm(c.createdAt)].join('|');
|
||||
}
|
||||
|
||||
if (t === 'mailingList') {
|
||||
return ['mailingList', author, norm(c.createdAt)].join('|');
|
||||
}
|
||||
|
||||
if (t === 'logisticsRoute') {
|
||||
return ['logisticsRoute', author, norm(c.createdAt)].join('|');
|
||||
}
|
||||
|
||||
if (t === 'podcast' || t === 'podcastEpisode' || t === 'campaign') {
|
||||
return [t, author, norm(c.createdAt)].join('|');
|
||||
}
|
||||
|
||||
return `${t}:${msg.key}`;
|
||||
};
|
||||
|
||||
|
|
@ -303,20 +353,14 @@ module.exports = ({ cooler, padsModel, tribeCrypto, tribesModel }) => {
|
|||
return Array.from(map.values());
|
||||
};
|
||||
|
||||
const search = async ({ query, types = [], resultsPerPage = "10" }) => {
|
||||
const search = async ({ query, types = [] }) => {
|
||||
const ssbClient = await openSsb();
|
||||
const viewerId = ssbClient.id;
|
||||
const queryLower = String(query || '').toLowerCase();
|
||||
|
||||
const messages = await new Promise((res, rej) => {
|
||||
pull(
|
||||
ssbClient.createLogStream({ limit: logLimit }),
|
||||
pull.collect((err, msgs) => err ? rej(err) : res(msgs))
|
||||
);
|
||||
});
|
||||
const messages = await readTyped(ssbClient, CONTENT_TYPES, { limit: logLimit, withWindow: true });
|
||||
|
||||
const tombstoned = buildValidatedTombstoneSet(messages);
|
||||
const replacesMap = new Map();
|
||||
const latestByKey = new Map();
|
||||
|
||||
for (const msg of messages) {
|
||||
|
|
@ -324,23 +368,12 @@ module.exports = ({ cooler, padsModel, tribeCrypto, tribesModel }) => {
|
|||
const c = msg?.value?.content;
|
||||
const t = c?.type;
|
||||
if (!t || !searchableTypes.includes(t)) continue;
|
||||
if (tombstoned.has(k)) continue;
|
||||
if (c.replaces) replacesMap.set(c.replaces, k);
|
||||
latestByKey.set(k, msg);
|
||||
}
|
||||
|
||||
for (const [oldId, newId] of Array.from(replacesMap.entries())) {
|
||||
const orig = latestByKey.get(oldId);
|
||||
const repl = latestByKey.get(newId);
|
||||
if (!orig) { replacesMap.delete(oldId); continue; }
|
||||
if (!repl || String(repl?.value?.author) !== String(orig?.value?.author)) {
|
||||
replacesMap.delete(oldId);
|
||||
latestByKey.delete(newId);
|
||||
}
|
||||
}
|
||||
|
||||
for (const oldId of replacesMap.keys()) {
|
||||
latestByKey.delete(oldId);
|
||||
const vg = versionGroups(Array.from(latestByKey.values()).map(versionEntry));
|
||||
for (const k of Array.from(latestByKey.keys())) {
|
||||
if (!vg.roots.has(vg.rootOf(k)) || vg.tipOf(k) !== k || tombstoned.has(k)) latestByKey.delete(k);
|
||||
}
|
||||
|
||||
const viewerTribeIds = new Set();
|
||||
|
|
@ -376,6 +409,14 @@ module.exports = ({ cooler, padsModel, tribeCrypto, tribesModel }) => {
|
|||
}
|
||||
}
|
||||
|
||||
const chunkLookup = longText.lookupIn(longText.indexChunks(messages));
|
||||
for (const [k, msg] of Array.from(latestByKey.entries())) {
|
||||
const c = msg?.value?.content;
|
||||
if ((c?.type === 'post' || c?.type === 'forum') && longText.hasChunks(c)) {
|
||||
latestByKey.set(k, { ...msg, value: { ...msg.value, content: longText.resolveField(c, 'text', msg.value.author, chunkLookup) } });
|
||||
}
|
||||
}
|
||||
|
||||
if (padsModel) {
|
||||
for (const msg of latestByKey.values()) {
|
||||
const c = msg?.value?.content;
|
||||
|
|
@ -422,11 +463,6 @@ module.exports = ({ cooler, padsModel, tribeCrypto, tribesModel }) => {
|
|||
return acc;
|
||||
}, {});
|
||||
|
||||
if (resultsPerPage !== "all") {
|
||||
const limit = parseInt(resultsPerPage, 10);
|
||||
for (const key in grouped) grouped[key] = grouped[key].slice(0, limit);
|
||||
}
|
||||
|
||||
return grouped;
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue