diff --git a/zefie_wtvp_minisrv/includes/WTVNews.js b/zefie_wtvp_minisrv/includes/WTVNews.js
index 7583fa23..77f85230 100644
--- a/zefie_wtvp_minisrv/includes/WTVNews.js
+++ b/zefie_wtvp_minisrv/includes/WTVNews.js
@@ -100,32 +100,37 @@ class WTVNews {
});
}
- getArticle(articleID) {
+ getArticle(articleID, get_next_last = true) {
var articleID = parseInt(articleID);
return new Promise((resolve, reject) => {
var promises = [];
this.client.article(articleID).then((data) => {
- // ask server for next article
- promises.push(new Promise((resolve, reject) => {
- this.client.next().then((res) => {
- data.next_article = res.article.articleNumber;
- resolve(data.next_article);
- }).catch((e) => {
- console.log(e);
- data.next_article = null;
- resolve(data.next_article);
- })
- }));
+ if (get_next_last) {
+ // ask server for next article
+ promises.push(new Promise((resolve, reject) => {
+ this.client.next().then((res) => {
+ data.next_article = res.article.articleNumber;
+ resolve(data.next_article);
+ }).catch((e) => {
+ console.log(e);
+ data.next_article = null;
+ resolve(data.next_article);
+ })
+ }));
- // ask server for previous article
- promises.push(new Promise((resolve, reject) => {
- this.client.last().then((res) => {
- data.prev_article = res.article.articleNumber;
- // do it again
- this.client.article(data.prev_article).then(() => {
- this.client.last().then((res) => {
- data.prev_article = res.article.articleNumber;
- resolve(data.prev_article);
+ // ask server for previous article
+ promises.push(new Promise((resolve, reject) => {
+ this.client.last().then((res) => {
+ data.prev_article = res.article.articleNumber;
+ // do it again
+ this.client.article(data.prev_article).then(() => {
+ this.client.last().then((res) => {
+ data.prev_article = res.article.articleNumber;
+ resolve(data.prev_article);
+ }).catch(() => {
+ data.prev_article = null;
+ resolve(data.prev_article);
+ });
}).catch(() => {
data.prev_article = null;
resolve(data.prev_article);
@@ -133,16 +138,15 @@ class WTVNews {
}).catch(() => {
data.prev_article = null;
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);
- });
+ }
}).catch((e) => {
reject(`Error reading article ID ${articleID}`);
console.error(" * WTVNews Error:", "Command: article", "args:", articleID, "Error:", e);
diff --git a/zefie_wtvp_minisrv/includes/WTVNewsServer.js b/zefie_wtvp_minisrv/includes/WTVNewsServer.js
index a5780653..4d3a0545 100644
--- a/zefie_wtvp_minisrv/includes/WTVNewsServer.js
+++ b/zefie_wtvp_minisrv/includes/WTVNewsServer.js
@@ -15,32 +15,7 @@ class WTVNewsServer {
const { WTVShared } = require("./WTVShared.js");
this.wtvshared = new WTVShared(minisrv_config);
const nntp_server = require('nntp-server');
- var nntp_commands = {
- ...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);
-
+ const nntp_statuses = require('nntp-server/lib/status');
this.username == username || null;
this.password == password || null;
this.using_auth = using_auth;
@@ -53,10 +28,52 @@ class WTVNewsServer {
// nntp-server module overrides
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,
_authenticate: function (session) {
- // authenticte
+ // authenticate
if (session.authinfo_user == self.username && session.authinfo_pass == self.password) return Promise.resolve(true);
return Promise.resolve(false);
},
@@ -89,12 +106,10 @@ class WTVNewsServer {
_getArticle: function (session, message_id) {
// getArticle
return new Promise((resolve, reject) => {
- self.getArticle(session.group.name, message_id).then((res) => {
- resolve(res);
- }).catch((e) => {
- console.log(" * WTVNewsServer Error:", e);
- reject(e);
- });
+ var res = self.getArticle(session.group.name, message_id);
+ console.log(res);
+ if (!res.messageId) reject(res);
+ else resolve(res)
});
},
@@ -137,23 +152,28 @@ class WTVNewsServer {
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) {
if (!this.fs.existsSync(getGroupPath(group))) return this.fs.mkdirSync(getGroupPath(group));
return true;
}
getArticle(group, article) {
- return new Promise((resolve, reject) => {
- const g = this.getArticlePath(group, article);
- if (!this.fs.existsSync(g)) return false;
- try {
- var data = JSON.parse(this.fs.readFileSync(g));
- resolve(data);
- } catch (e) {
- console.log(" * WTVNewsServer Error:", e);
- reject(e)
- }
- });
+ const g = this.getArticlePath(group, article);
+ if (!this.fs.existsSync(g)) return false;
+ try {
+ var data = JSON.parse(this.fs.readFileSync(g));
+ data.index = data.articleNumber;
+ return data
+ } catch (e) {
+ console.log(" * WTVNewsServer Error:", e);
+ }
+ return null;
}
selectGroup(group) {
@@ -180,6 +200,55 @@ class WTVNewsServer {
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) {
var g = this.getGroupPath(group);
var out = {
diff --git a/zefie_wtvp_minisrv/sync_nntp.js b/zefie_wtvp_minisrv/sync_nntp.js
index a547b564..bf549144 100644
--- a/zefie_wtvp_minisrv/sync_nntp.js
+++ b/zefie_wtvp_minisrv/sync_nntp.js
@@ -7,6 +7,7 @@ const groups_to_sync = [
const fs = require('fs');
const path = require('path');
+const crypto = require('crypto');
var classPath = __dirname + "/includes/";
const { WTVShared } = require(classPath + "WTVShared.js");
const wtvshared = new WTVShared(); // creates minisrv_config
@@ -58,14 +59,9 @@ function createGroup(group) {
function createArticle(group, articleNumber, article) {
var g = getGroupPath(group);
var file = g + path.sep + articleNumber + ".newz";
- if (fs.existsSync(file)) return "exists";
+ if (verifyMessage(group, articleNumber, article)) return "exists";
else {
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));
return file;
} 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) {
var g = getGroupPath(group);
try {
@@ -108,7 +116,7 @@ wtvnews.connectUsenet().then((res) => {
deleteMissing(group, res.group.articleNumbers)
res.group.articleNumbers.forEach((article) => {
promises.push(new Promise((resolve, reject) => {
- wtvnews.getArticle(article).then((message) => {
+ wtvnews.getArticle(article, false).then((message) => {
res = createArticle(group, article, message);
if (res) {
if (res == "exists") {
diff --git a/zefie_wtvp_minisrv/zefie_wtvp_minisrv.njsproj b/zefie_wtvp_minisrv/zefie_wtvp_minisrv.njsproj
index 686289d6..01e555d3 100644
--- a/zefie_wtvp_minisrv/zefie_wtvp_minisrv.njsproj
+++ b/zefie_wtvp_minisrv/zefie_wtvp_minisrv.njsproj
@@ -1103,6 +1103,7 @@
+