implement nntp NEXT and LAST

This commit is contained in:
zefie
2022-10-12 14:35:52 -04:00
parent 976c79c92a
commit 575054a4d4
4 changed files with 162 additions and 80 deletions

View File

@@ -100,32 +100,37 @@ class WTVNews {
}); });
} }
getArticle(articleID) { getArticle(articleID, get_next_last = true) {
var articleID = parseInt(articleID); var articleID = parseInt(articleID);
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
var promises = []; var promises = [];
this.client.article(articleID).then((data) => { this.client.article(articleID).then((data) => {
// ask server for next article if (get_next_last) {
promises.push(new Promise((resolve, reject) => { // ask server for next article
this.client.next().then((res) => { promises.push(new Promise((resolve, reject) => {
data.next_article = res.article.articleNumber; this.client.next().then((res) => {
resolve(data.next_article); data.next_article = res.article.articleNumber;
}).catch((e) => { resolve(data.next_article);
console.log(e); }).catch((e) => {
data.next_article = null; console.log(e);
resolve(data.next_article); data.next_article = null;
}) resolve(data.next_article);
})); })
}));
// ask server for previous article // ask server for previous article
promises.push(new Promise((resolve, reject) => { promises.push(new Promise((resolve, reject) => {
this.client.last().then((res) => { this.client.last().then((res) => {
data.prev_article = res.article.articleNumber; data.prev_article = res.article.articleNumber;
// do it again // do it again
this.client.article(data.prev_article).then(() => { this.client.article(data.prev_article).then(() => {
this.client.last().then((res) => { this.client.last().then((res) => {
data.prev_article = res.article.articleNumber; data.prev_article = res.article.articleNumber;
resolve(data.prev_article); resolve(data.prev_article);
}).catch(() => {
data.prev_article = null;
resolve(data.prev_article);
});
}).catch(() => { }).catch(() => {
data.prev_article = null; data.prev_article = null;
resolve(data.prev_article); resolve(data.prev_article);
@@ -133,16 +138,15 @@ class WTVNews {
}).catch(() => { }).catch(() => {
data.prev_article = null; data.prev_article = null;
resolve(data.prev_article); resolve(data.prev_article);
}); })
}).catch(() => { }));
data.prev_article = null;
resolve(data.prev_article);
})
}));
Promise.all(promises).then(() => { Promise.all(promises).then(() => {
resolve(data);
});
} else {
resolve(data); resolve(data);
}); }
}).catch((e) => { }).catch((e) => {
reject(`Error reading article ID ${articleID}`); reject(`Error reading article ID ${articleID}`);
console.error(" * WTVNews Error:", "Command: article", "args:", articleID, "Error:", e); console.error(" * WTVNews Error:", "Command: article", "args:", articleID, "Error:", e);

View File

@@ -15,32 +15,7 @@ class WTVNewsServer {
const { WTVShared } = require("./WTVShared.js"); const { WTVShared } = require("./WTVShared.js");
this.wtvshared = new WTVShared(minisrv_config); this.wtvshared = new WTVShared(minisrv_config);
const nntp_server = require('nntp-server'); const nntp_server = require('nntp-server');
var nntp_commands = { const nntp_statuses = require('nntp-server/lib/status');
...nntp_server.commands,
"LAST": {
head: 'LAST',
validate: /^LAST( [^\s]+)$/i,
// All supported params are defined in separate files
run() {
console.log('hi');
throw new Error('method LAST is not implemented');
}
},
"NEXT": {
head: 'NEXT',
validate: /^NEXT( [^\s]+)$/i,
// All supported params are defined in separate files
run() {
console.log('hi');
throw new Error('method NEXT is not implemented');
}
}
}
console.log(nntp_commands);
this.username == username || null; this.username == username || null;
this.password == password || null; this.password == password || null;
this.using_auth = using_auth; this.using_auth = using_auth;
@@ -53,10 +28,52 @@ class WTVNewsServer {
// nntp-server module overrides // nntp-server module overrides
var self = this; var self = this;
var nntp_commands = {
...nntp_server.commands,
"LAST": {
head: 'LAST',
validate: /^LAST$/i,
// All supported params are defined in separate files
run: function (session) {
try {
if (!session.group.name) return nntp_statuses._412_GRP_NOT_SLCTD;
if (!session.group.current_article) return nntp_statuses._420_ARTICLE_NOT_SLCTD;
if (!self.articleExists(session.group.name, session.group.current_article)) return nntp_statuses._420_ARTICLE_NOT_SLCTD;
var res = self.getLastArticle(session.group.name, session.group.current_article);
if (!res) return nntp_statuses._422_NO_LAST_ARTICLE;
var last = `${nntp_statuses._223_ARTICLE_EXISTS} ${res.articleNumber} ${res.message_id}`
return last
} catch (e) {
console.log(e);
}
}
},
"NEXT": {
head: 'NEXT',
validate: /^NEXT$/i,
// All supported params are defined in separate files
run: function (session) {
try {
if (!session.group.name) return nntp_statuses._412_GRP_NOT_SLCTD;
if (!session.group.current_article) return nntp_statuses._420_ARTICLE_NOT_SLCTD;
if (!self.articleExists(session.group.name, session.group.current_article)) return nntp_statuses._420_ARTICLE_NOT_SLCTD;
var res = self.getNextArticle(session.group.name, session.group.current_article);
if (!res) return nntp_statuses._421_NO_NEXT_ARTICLE;
var next = `${nntp_statuses._223_ARTICLE_EXISTS} ${res.articleNumber} ${res.message_id}`
return next
} catch (e) {
console.log(e);
}
}
}
}
nntp_server.prototype = { nntp_server.prototype = {
...nntp_server.prototype, ...nntp_server.prototype,
_authenticate: function (session) { _authenticate: function (session) {
// authenticte // authenticate
if (session.authinfo_user == self.username && session.authinfo_pass == self.password) return Promise.resolve(true); if (session.authinfo_user == self.username && session.authinfo_pass == self.password) return Promise.resolve(true);
return Promise.resolve(false); return Promise.resolve(false);
}, },
@@ -89,12 +106,10 @@ class WTVNewsServer {
_getArticle: function (session, message_id) { _getArticle: function (session, message_id) {
// getArticle // getArticle
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
self.getArticle(session.group.name, message_id).then((res) => { var res = self.getArticle(session.group.name, message_id);
resolve(res); console.log(res);
}).catch((e) => { if (!res.messageId) reject(res);
console.log(" * WTVNewsServer Error:", e); else resolve(res)
reject(e);
});
}); });
}, },
@@ -137,23 +152,28 @@ class WTVNewsServer {
return this.getGroupPath(group) + this.path.sep + article + ".newz"; return this.getGroupPath(group) + this.path.sep + article + ".newz";
} }
articleExists(group, article) {
const g = this.getArticlePath(group, article);
if (this.fs.existsSync(g)) return true;
return false;
}
createGroup(group) { createGroup(group) {
if (!this.fs.existsSync(getGroupPath(group))) return this.fs.mkdirSync(getGroupPath(group)); if (!this.fs.existsSync(getGroupPath(group))) return this.fs.mkdirSync(getGroupPath(group));
return true; return true;
} }
getArticle(group, article) { getArticle(group, article) {
return new Promise((resolve, reject) => { const g = this.getArticlePath(group, article);
const g = this.getArticlePath(group, article); if (!this.fs.existsSync(g)) return false;
if (!this.fs.existsSync(g)) return false; try {
try { var data = JSON.parse(this.fs.readFileSync(g));
var data = JSON.parse(this.fs.readFileSync(g)); data.index = data.articleNumber;
resolve(data); return data
} catch (e) { } catch (e) {
console.log(" * WTVNewsServer Error:", e); console.log(" * WTVNewsServer Error:", e);
reject(e) }
} return null;
});
} }
selectGroup(group) { selectGroup(group) {
@@ -180,6 +200,55 @@ class WTVNewsServer {
return out; return out;
} }
getLastArticle(group, current) {
var g = this.getGroupPath(group);
var res = null;
try {
this.fs.readdirSync(g).forEach(file => {
var articleNumber = parseInt(file.split('.')[0]);
if (articleNumber > current) return false;
res = articleNumber;
return false;
});
} catch (e) {
console.log(e);
return e;
}
if (res) {
if (res == current) return null;
var message = this.getArticle(group, res);
if (message.messageId) {
res = { "articleNumber": res, "message_id": message.messageId };
}
}
return res;
}
getNextArticle(group, current) {
var g = this.getGroupPath(group);
var res = null;
try {
this.fs.readdirSync(g).forEach(file => {
var articleNumber = parseInt(file.split('.')[0]);
if (articleNumber <= current) return;
res = articleNumber;
return false;
});
} catch (e) {
console.log(e);
return e;
}
if (res) {
if (res == current) return null;
var message = this.getArticle(group, res);
if (message.messageId) {
res = { "articleNumber": res, "message_id": message.messageId };
}
}
return res;
}
listGroup(group, start, end) { listGroup(group, start, end) {
var g = this.getGroupPath(group); var g = this.getGroupPath(group);
var out = { var out = {

View File

@@ -7,6 +7,7 @@ const groups_to_sync = [
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const crypto = require('crypto');
var classPath = __dirname + "/includes/"; var classPath = __dirname + "/includes/";
const { WTVShared } = require(classPath + "WTVShared.js"); const { WTVShared } = require(classPath + "WTVShared.js");
const wtvshared = new WTVShared(); // creates minisrv_config const wtvshared = new WTVShared(); // creates minisrv_config
@@ -58,14 +59,9 @@ function createGroup(group) {
function createArticle(group, articleNumber, article) { function createArticle(group, articleNumber, article) {
var g = getGroupPath(group); var g = getGroupPath(group);
var file = g + path.sep + articleNumber + ".newz"; var file = g + path.sep + articleNumber + ".newz";
if (fs.existsSync(file)) return "exists"; if (verifyMessage(group, articleNumber, article)) return "exists";
else { else {
try { try {
article.article.index = article.article.articleNumber;
delete article.article.articleNumber;
article.article['message-id'] = article.article.messageId;
delete article.article.messageId;
fs.writeFileSync(file, JSON.stringify(article.article)); fs.writeFileSync(file, JSON.stringify(article.article));
return file; return file;
} catch (e) { } catch (e) {
@@ -74,6 +70,18 @@ function createArticle(group, articleNumber, article) {
} }
} }
function verifyMessage(group, articleNumber, article) {
var g = getGroupPath(group);
var file = g + path.sep + articleNumber + ".newz";
if (!fs.existsSync(file)) return false;
var old_data = fs.readFileSync(file);
var new_data = JSON.stringify(article.article);
var old_data_hash = crypto.createHash('md5').update(old_data).digest("hex");
var new_data_hash = crypto.createHash('md5').update(new_data).digest("hex");
return (old_data_hash === new_data_hash);
}
function deleteMissing(group, articles) { function deleteMissing(group, articles) {
var g = getGroupPath(group); var g = getGroupPath(group);
try { try {
@@ -108,7 +116,7 @@ wtvnews.connectUsenet().then((res) => {
deleteMissing(group, res.group.articleNumbers) deleteMissing(group, res.group.articleNumbers)
res.group.articleNumbers.forEach((article) => { res.group.articleNumbers.forEach((article) => {
promises.push(new Promise((resolve, reject) => { promises.push(new Promise((resolve, reject) => {
wtvnews.getArticle(article).then((message) => { wtvnews.getArticle(article, false).then((message) => {
res = createArticle(group, article, message); res = createArticle(group, article, message);
if (res) { if (res) {
if (res == "exists") { if (res == "exists") {

View File

@@ -1103,6 +1103,7 @@
<Content Include="SharedROMCache\up-arrows.swf" /> <Content Include="SharedROMCache\up-arrows.swf" />
<Content Include="SharedROMCache\UsingWebTVBanner.gif" /> <Content Include="SharedROMCache\UsingWebTVBanner.gif" />
<Content Include="SharedROMCache\WebTVLogoJewel.gif" /> <Content Include="SharedROMCache\WebTVLogoJewel.gif" />
<Content Include="sync_nntp.js" />
<Content Include="test.js" /> <Content Include="test.js" />
<Content Include="includes\WTVAdmin.js" /> <Content Include="includes\WTVAdmin.js" />
<Content Include="includes\WTVBGMusic.js"> <Content Include="includes\WTVBGMusic.js">