Skip to content
Snippets Groups Projects
Commit b0a76216 authored by echicken's avatar echicken :chicken:
Browse files

listSubs doesn't need to return that much detail. New stuff will be exported...

listSubs doesn't need to return that much detail. New stuff will be exported as part of 'forum' object, for use with require().
parent 417cbeb4
No related branches found
No related tags found
1 merge request!463MRC mods by Codefenix (2024-10-20)
...@@ -13,7 +13,8 @@ function listGroups() { ...@@ -13,7 +13,8 @@ function listGroups() {
index: grp.index, index: grp.index,
name: grp.name, name: grp.name,
description: grp.description, description: grp.description,
sub_count: grp.sub_list.length sub_count: grp.sub_list.length,
// unread: is_user() ? getGroupUnreadCount(grp.index) : null,
}); });
}); });
return response; return response;
...@@ -21,36 +22,39 @@ function listGroups() { ...@@ -21,36 +22,39 @@ function listGroups() {
// Returns an array of objects of "useful" information about subs // Returns an array of objects of "useful" information about subs
function listSubs(group) { function listSubs(group) {
return msg_area.grp_list[group].sub_list.map(function (sub) { return msg_area.grp_list[group].sub_list.map(function (e) {
return { const mb = new MsgBase(e.code);
index: sub.index, if (!mb.open()) throw new Error(mb.error);
code: sub.code, const ret = {
grp_index: sub.grp_index, index: e.index,
grp_name: sub.grp_name, code: e.code,
name: sub.name, grp_index: e.grp_index,
description: sub.description, grp_name: e.grp_name,
qwk_name: sub.qwk_name, name: e.name,
qwk_conf: sub.qwk_conf, description: e.description,
qwk_tagline: sub.qwknet_tagline, can_post: e.can_post,
newsgroup: sub.newsgroup, is_operator: e.is_operator,
ars: sub.ars, is_moderated: e.is_moderated,
read_ars: sub.read_ars, scan_ptr: e.scan_ptr,
can_read: sub.can_read, scan_cfg: e.scan_cfg,
post_ars: sub.post_ars, // unread: is_user() ? getSubUnreadCount(mb) : null,
can_post: sub.can_post, // newest: getNewestMessageInSub(mb),
operator_ars: sub.operator_ars,
is_operator: sub.is_operator,
moderated_ars: sub.moderated_ars,
is_moderated: sub.is_moderated,
scan_ptr: sub.scan_ptr,
scan_cfg: sub.scan_cfg,
}; };
mb.close();
return ret;
}); });
} }
function getNewestMessageInSub(sub) { function getNewestMessageInSub(sub) {
const mb = new MsgBase(sub.code);
if (!mb.open()) return; var mb;
if (sub instanceof MsgBase) {
mb = sub;
} else {
mb = new MsgBase(sub.code);
if (!mb.open()) throw new Error(mb.error);
}
var h; var h;
var ret; var ret;
for (var m = mb.last_msg; m >= mb.first_msg; m--) { for (var m = mb.last_msg; m >= mb.first_msg; m--) {
...@@ -59,12 +63,15 @@ function getNewestMessageInSub(sub) { ...@@ -59,12 +63,15 @@ function getNewestMessageInSub(sub) {
ret = { ret = {
from: h.from, from: h.from,
subject: h.subject, subject: h.subject,
date: h.when_written_time, // should just be a timestamp; all date formatting should be client-side in forum.xjs date: h.when_written_time,
}; };
break; break;
} }
mb.close();
if (!(sub instanceof MsgBase)) mb.close();
return ret; return ret;
} }
function getNewestMessagePerSub(grp) { function getNewestMessagePerSub(grp) {
...@@ -78,32 +85,34 @@ function getNewestMessagePerSub(grp) { ...@@ -78,32 +85,34 @@ function getNewestMessagePerSub(grp) {
} }
function getSubUnreadCount(sub) { function getSubUnreadCount(sub) {
var ret = { var ret = {
scanned: 0, scanned: 0,
total: 0, total: 0,
}; };
if (msg_area.sub[sub] === undefined) return ret;
try { var mb;
var sy = msg_area.sub[sub].scan_cfg&SCAN_CFG_YONLY; if (sub instanceof MsgBase) {
var sn = msg_area.sub[sub].scan_cfg&SCAN_CFG_NEW; mb = sub;
var msgBase = new MsgBase(sub); } else {
msgBase.open(); if (msg_area.sub[sub] === undefined) return ret;
for (var m = msg_area.sub[sub].scan_ptr + 1; m <= msgBase.last_msg; m++) { mb = new MsgBase(sub);
var h = msgBase.get_msg_header(m); if (!mb.open()) throw new Error(mb.error);
if (h === null || h.attr&MSG_DELETE || h.attr&MSG_NODISP) continue; }
if ((sy && (h.to_ext === user.number || h.to === user.alias || h.to === user.name)) || sn) ret.scanned++;
ret.total++; var sy = msg_area.sub[mb.cfg.code].scan_cfg&SCAN_CFG_YONLY;
ret.newest = { var sn = msg_area.sub[mb.cfg.code].scan_cfg&SCAN_CFG_NEW;
from: h.from, for (var m = msg_area.sub[mb.cfg.code].scan_ptr + 1; m <= mb.last_msg; m++) {
subject: h.subject, var h = mb.get_msg_header(m);
date: h.when_written_time if (h === null || h.attr&MSG_DELETE || h.attr&MSG_NODISP) continue;
}; if ((sy && (h.to_ext === user.number || h.to === user.alias || h.to === user.name)) || sn) ret.scanned++;
} ret.total++;
msgBase.close();
} catch (err) {
log(LOG_ERR, err);
} }
if (!(sub instanceof MsgBase)) mb.close();
return ret; return ret;
} }
function getSubUnreadCounts(group) { function getSubUnreadCounts(group) {
...@@ -202,11 +211,6 @@ function listThreads(sub, count, after) { ...@@ -202,11 +211,6 @@ function listThreads(sub, count, after) {
var thread; var thread;
var stop = Math.min(threads.order.length, offset + count); var stop = Math.min(threads.order.length, offset + count);
var ret = { total: threads.order.length, threads : [] }; var ret = { total: threads.order.length, threads : [] };
if (sub.scan_cfg&SCAN_CFG_NEW) {
ret.scan_cfg = 'new';
} else if (sub.scan_cfg&SCAN_CFG_YONLY) {
ret.scan_cfg = 'you_only';
}
for (var n = offset; n < stop; n++) { for (var n = offset; n < stop; n++) {
thread = threads.thread[threads.order[n]]; thread = threads.thread[threads.order[n]];
msgs = Object.keys(thread.messages); msgs = Object.keys(thread.messages);
...@@ -216,6 +220,7 @@ function listThreads(sub, count, after) { ...@@ -216,6 +220,7 @@ function listThreads(sub, count, after) {
first: thread.messages[msgs[0]], first: thread.messages[msgs[0]],
last: thread.messages[msgs[msgs.length - 1]], last: thread.messages[msgs[msgs.length - 1]],
messages: msgs.length, messages: msgs.length,
sub: sub,
unread: is_user() ? getUnreadInThread(sub, thread) : 0, unread: is_user() ? getUnreadInThread(sub, thread) : 0,
votes: getThreadVoteTotals(thread), votes: getThreadVoteTotals(thread),
}); });
...@@ -1072,7 +1077,7 @@ function getMessageThreads(sub, max) { ...@@ -1072,7 +1077,7 @@ function getMessageThreads(sub, max) {
} }
function getMessageThread(sub, thread, count, after) { function getMessageThread(sub, thread, count, after, reload) {
thread = parseInt(thread, 10); thread = parseInt(thread, 10);
if (isNaN(thread)) return []; if (isNaN(thread)) return [];
...@@ -1084,7 +1089,15 @@ function getMessageThread(sub, thread, count, after) { ...@@ -1084,7 +1089,15 @@ function getMessageThread(sub, thread, count, after) {
var m; // Current message var m; // Current message
var r = 0; // Messages returned var r = 0; // Messages returned
var n = 0; // Index into t.messages var n = 0; // Index into t.messages
if (after) n = mkeys.indexOf(after) + 1; if (after) {
var i = mkeys.indexOf(after);
if (reload) {
if (i >= 0) count += i + 1;
} else {
if (i < 0) return [];
n = i + 1;
}
}
const msgBase = new MsgBase(sub); const msgBase = new MsgBase(sub);
...@@ -1111,15 +1124,154 @@ function getMessageThread(sub, thread, count, after) { ...@@ -1111,15 +1124,154 @@ function getMessageThread(sub, thread, count, after) {
} }
function isValidRequest() { function cleanSubject(subject) {
if (Request.has_param('group')) { return subject.replace(/^(re:\s*)*/ig, '');
const grp = Request.get_param('group');
if (msg_area.grp_list[grp] === undefined) return false;
if (!user.compare_ars(msg_area.grp_list[grp].ars)) return false;
}
if (Request.has_param('sub')) {
const sub = Request.get_param('sub');
if (msg_area.sub[sub] === undefined) return false;
}
return true;
} }
var forum = {
getThreadList: function getThreadList(sub) {
const threads = {};
const subjects = {}; // Map of "clean" subjects to threads
const messages = {}; // Map of messsage numbers to threads
function addThread(h, s) {
threads[h.thread_id] = {
first_message: {
from: h.from,
from_net_addr: h.from_net_addr,
from_net_type: h.from_net_type,
tags: h.tags,
to: h.to,
to_net_addr: h.to_net_addr,
to_net_type: h.to_net_type,
subject: h.subject,
when_written_time: h.when_written_time,
},
messages: 1,
votes: {
parent: {
up: h.upvotes,
down: h.downvotes,
},
total: {
up: h.upvotes,
down: h.downvotes,
}
}
};
subjects[s] = h.thread_id;
messages[h.thread_id] = h.thread_id;
}
function addToThread(t, h, s, m) {
threads[t].messages++;
threads[t].last_message = {
from: h.from,
when_written_time: h.when_written_time,
};
threads[t].votes.total.up += h.upvotes;
threads[t].votes.total.down += h.downvotes;
if (subjects[s] === undefined) subjects[s] = t;
messages[m] = t;
}
const mb = new MsgBase(sub);
if (!mb.open()) return threads;
const headers = mb.get_all_msg_headers();
mb.close();
var s; // "clean" subject of current message
for (var h in headers) {
if (headers[h] === null) continue; // Unnecessary? Does get_all_message_headers exclude empty slots?
if (headers[h].attr&MSG_DELETE) continue;
s = cleanSubject(headers[h].subject);
// If we don't yet have a thread for this message's thread_id:
if (threads[headers[h].thread_id] === undefined) {
// If this message's thread_id points to a message that belongs to another thread:
if (messages[headers[h].thread_id] !== undefined) {
// The record in messages[] for that message tells us which thread it belongs to
addToThread(messages[headers[h].thread_id], headers[h], s, h);
// If this message's "clean" subject has been seen before:
} else if (subjects[s] !== undefined) {
// The record in subjects[] for this subject tells us which thread shares this subject
addToThread(subjects[s], headers[h], s, h);
// This is the first message in a new thread
} else {
addThread(headers[h], s);
}
// We have a thread for this message's thread_id:
} else {
addToThread(headers[h].thread_id, headers[h], s, h);
}
}
return threads;
},
getThread: function getThread(sub, id, onMessage) {
id = parseInt(id, 10);
if (isNaN(id) || id < 0) return;
const mb = new MsgBase(sub);
if (!mb.open()) return;
if (id < mb.first_msg || id > mb.last_msg) {
mb.close();
return;
}
var b;
var s;
const subjects = [];
const messages = [];
const headers = mb.get_all_msg_headers();
for (var h in headers) {
if (headers[h] === null) continue; // Unnecessary? Does get_all_message_headers exclude empty slots?
if (headers[h].attr&MSG_DELETE) continue;
s = cleanSubject(headers[h].subject);
if (headers[h].thread_id !== id && messages.indexOf(headers[h].thread_id) < 0 && subjects.indexOf(s) < 0) continue;
messages.push(parseInt(h, 10));
if (subjects.indexOf(s) < 0) subjects.push(s);
b = mb.get_msg_body(parseInt(h, 10));
if (b === null) continue; // Not sure if this is a holdover from early vote msg days. Is body ever null on a real message?
onMessage({
body: b, // Do we use formatMessage here, or let the browser handle that? Leaning toward client-side formatting.
from: headers[h].from,
from_net_addr: headers[h].from_net_addr,
from_net_type: headers[h].from_net_type,
number: parseInt(h, 10),
subject: headers[h].subject,
tags: headers[h].tags,
thread_id: headers[h].thread_id, // for debug; remove this line at some point
thread_back: headers[h].thread_back,
thread_next: headers[h].thread_next,
thread_first: headers[h].thread_first,
to: headers[h].to,
to_net_addr: headers[h].to_net_addr,
to_net_type: headers[h].to_net_type,
votes: {
up: headers[h].upvotes,
down: headers[h].downvotes,
},
when_written_time: headers[h].when_written_time,
});
}
mb.close();
}
};
forum;
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment