Implemented saving a frame to the message base and frame_import

This commit is contained in:
Deon George 2024-12-04 10:13:28 +11:00
parent f7a581fa30
commit da51bd3d0b
5 changed files with 183 additions and 250 deletions

View File

@ -143,19 +143,27 @@ function MsgArea() {
// Get all frames that are tagged
Object.defineProperty(this,'frames',{
get: function() {
if (! this.managed)
var msgbase;
var regex = false;
if (this.code === FRAMES_MSG_BASE) {
msgbase = this.msgbase;
} else if (this.managed) {
msgbase = new MsgAreas().getArea(FRAMES_MSG_BASE).msgbase;
regex = this.page_prefix_regex;
} else
return undefined;
var msgbase = new MsgAreas().getArea(FRAMES_MSG_BASE).msgbase;
var frames = [];
var regex = this.page_prefix_regex;
try {
if (msgbase.open()) {
var headers = msgbase.get_all_msg_headers(false,false) || [];
for (var i in headers) {
if ((! (headers[i].attr&MSG_DELETE)) && headers[i].tags && regex.test(headers[i].tags))
if ((! (headers[i].attr&MSG_DELETE)) && headers[i].tags && ((! regex) || regex.test(headers[i].tags)))
frames.push(headers[i]);
}
@ -208,7 +216,8 @@ function MsgArea() {
}
});
Object.defineProperty(this,'last_tagged',{
// Retrieve the last tagged frame
Object.defineProperty(this,'last_tagged_message',{
get: function() {
var last_tag = this.frames.sort(function(a,b) {
if (a.when_imported_time === b.when_imported_time)
@ -217,6 +226,9 @@ function MsgArea() {
return (a.when_imported_time > b.when_imported_time);
}).pop();
if (last_tag === undefined)
return undefined;
var msgbase = new MsgAreas().getArea(FRAMES_MSG_BASE).msgbase;
try {
@ -230,7 +242,7 @@ function MsgArea() {
}
} catch (e) {
log(LOG_ERROR,this.code+' cannot be opened (last_tagged):'+e.message);
log(LOG_ERROR,this.code+' cannot be opened (last_tagged_message):'+e.message);
return undefined;
}
@ -248,7 +260,7 @@ function MsgArea() {
}
} catch (e) {
log(LOG_ERROR,this.code+' cannot be opened (last_tagged):'+e.message);
log(LOG_ERROR,this.code+' cannot be opened (last_tagged_message_base):'+e.message);
return undefined;
}
@ -257,7 +269,7 @@ function MsgArea() {
}
})
// Is this area defined for videotex messages
// Is this area defined for ansitex messages
Object.defineProperty(this,'managed',{
get: function() {
return (this.zone_id !== undefined) && (this.area_id !== undefined);
@ -365,7 +377,7 @@ function MsgArea() {
return undefined;
var msgbase = this.msgbase;
var last_tag = this.last_tagged;
var last_tag = this.last_tagged_message;
var msgs = [];
try {
@ -401,6 +413,40 @@ function MsgArea() {
}
});
// Get frame content
MsgArea.prototype.getContent = function(id) {
// @todo If this is for a echomail/netmail content, then we need to switch message bases
if (this.code !== FRAMES_MSG_BASE)
return undefined;
var msgbase = this.msgbase;
try {
if (msgbase.open()) {
var content = JSON.parse(LZString.decompressFromBase64(msgbase.get_msg_body(false,id,false,false,true,true)));
msgbase.close();
var i;
for (var i=0; i<content.length; i++) {
// Echomail tag line
if (content[i] === '---' || content[i].substring(0,4) === '--- ')
break;
}
content.length = i;
} else {
writeln('*** NOPE WONT OPEN msgbase:'+JSON.stringify(msgbase));
}
} catch (e) {
log(LOG_ERROR,this.code+' cannot be opened (frames):'+e.message);
return undefined;
}
return content;
};
// @todo review
/**
* Unread messages [1..]

View File

@ -77,7 +77,7 @@
*/
load('ansitex/load/windows.js'); // Our supporting window class
require('ansitex/load/msgbases.js','PAGE_LENGTH'); // To read/write to message bases
load('ansitex/load/msgbases.js'); // To read/write to message bases
require('sbbsdefs.js','SS_USERON'); // Need for our ANSI colors eg: BG_*
/**
@ -144,7 +144,7 @@ function Page(debug) {
// isPublic is TRUE - can be viewed by users (if logged in)
key: [], // Key actions
raw: undefined, // Page raw content
raw: {}, // Page raw content for each session type
};
this.__defaults__ = {
@ -424,8 +424,14 @@ function Page(debug) {
this.__window__.provider.__properties__.content = provider;
});
Page.prototype.__defineGetter__('raw',function() {
return this.__properties__.raw;
Object.defineProperty(this,'raw',{
get: function() {
return this.__properties__.raw
},
set: function(value) {
this.__properties__.raw[SESSION_EXT] = value;
}
});
Page.prototype.__defineSetter__('showHeader',function(bool) {
@ -885,6 +891,21 @@ function Page(debug) {
}
}
Page.prototype.file_content = function(filename) {
log(LOG_DEBUG,'|-- Importing frame content: ['+filename+']');
var f = new File(filename);
if (! f.exists || ! f.open('rb',true)) {
log(LOG_ERROR,'|? File doesnt exist: ['+filename+']');
return false;
}
var content = f.read();
f.close();
return content;
};
/**
* Load a specific page
*
@ -901,7 +922,7 @@ function Page(debug) {
return true;
// Fall back to loading from msgbase
return FRAMES_MSG_BASE ? this.load(page) : false;
return FRAMES_MSG_BASE && this.load(page);
}
/**
@ -924,53 +945,52 @@ function Page(debug) {
* Load a frame from a file
*
* @param filename - Name of file to load page from (SBBS default dir is CTRL, so relative to it)
* @param width - Width to build window (not required for ANS)
* @param height - Height to build window (not required for ANS)
* @returns {boolean}
* @todo Dont allow load() to load a Viewdata frame for an ANSItex session and visa-versa.
*/
this.import = function(filename,ext,width,height) {
Page.prototype.import = function(filename) {
log(LOG_DEBUG,'|- Importing frame: ['+filename+']');
var f = new File(filename);
if (! f.exists || ! f.open('rb',true)) {
log(LOG_ERROR,'|? File doesnt exist: ['+filename+']');
return null;
return false;
}
var contents = f.read();
var contents = JSON.parse(f.read());
f.close();
// Load the page content
if (contents.version === 2)
contents.content = this.file_content(FRAMES_HOME+SESSION_EXT+'/'+this.name.toString()+'.'+CONTENT_EXT);
var valid_sauce = false;
if (contents.substr(-128, 7) === 'SAUCE00') {
ext = file_getext(filename).substr(1).toLowerCase();
var sauceless_size = ascii(contents.substr(-35,1));
if (contents.content.substr(-128, 7) === 'SAUCE00') {
var sauceless_size = ascii(contents.content.substr(-35,1));
sauceless_size <<= 8;
sauceless_size |= ascii(contents.substr(-36,1));
sauceless_size |= ascii(contents.content.substr(-36,1));
sauceless_size <<= 8;
sauceless_size |= ascii(contents.substr(-37,1));
sauceless_size |= ascii(contents.content.substr(-37,1));
sauceless_size <<= 8;
sauceless_size |= ascii(contents.substr(-38,1));
sauceless_size |= ascii(contents.content.substr(-38,1));
var data_type = ascii(contents.substr(-34,1));
var file_type = ascii(contents.substr(-33,1));
var data_type = ascii(contents.content.substr(-34,1));
var file_type = ascii(contents.content.substr(-33,1));
var tinfo1 = ascii(contents.substr(-31,1));
var tinfo1 = ascii(contents.content.substr(-31,1));
tinfo1 <<= 8;
tinfo1 |= ascii(contents.substr(-32,1));
tinfo1 |= ascii(contents.content.substr(-32,1));
var tinfo2 = ascii(contents.substr(-29,1));
var tinfo2 = ascii(contents.content.substr(-29,1));
tinfo2 <<= 8;
tinfo2 |= ascii(contents.substr(-30,1));
tinfo2 |= ascii(contents.content.substr(-30,1));
switch(data_type) {
case 1:
switch(file_type) {
// Plain ASCII
case 0:
ext = 'TXT';
var ext = 'TXT';
if (tinfo1)
width = tinfo1;
if (tinfo2)
@ -979,7 +999,7 @@ function Page(debug) {
// ANSI
case 1:
ext = 'ANS';
var ext = 'ANS';
if (tinfo1)
width = tinfo1;
if (tinfo2)
@ -988,7 +1008,7 @@ function Page(debug) {
// Source
case 7:
ext = 'TXT';
var ext = 'TXT';
break;
}
@ -996,7 +1016,7 @@ function Page(debug) {
break;
case 5:
ext = 'BIN';
var ext = 'BIN';
width = file_type * 2;
height = (sauceless_size / 2) / width;
valid_sauce = true;
@ -1004,69 +1024,35 @@ function Page(debug) {
}
if (valid_sauce)
contents = contents.substr(0, sauceless_size);
contents.content = contents.content.substr(0, sauceless_size);
}
return this.preload((['vtx','tex'].indexOf(ext) !== -1) ? JSON.parse(contents) : contents,ext,width,height);
return this.preload(contents,SESSION_EXT);
}
// Load a frame from a message base
this.load = function(page) {
var headers;
var mb = new MsgBase(FRAMES_MSG_BASE);
try {
if (mb.open()) {
headers = mb.get_all_msg_headers(false,false) || [];
} else {
log(LOG_ERROR,'! ['+FRAMES_MSG_BASE+'] cannot be opened ['+mb.error+']');
return false;
}
// @todo It appears if the message base doesnt exist, we dont error?
} catch (e) {
log(LOG_ERROR,'! ['+FRAMES_MSG_BASE+'] cannot be opened ['+e.message+']');
return false;
}
var msg;
// Find existing message with the page number
for (var x in headers) {
if ((!(headers[x].attr&MSG_DELETE)) && (headers[x].to === page.toString()) && (headers[x].from === SESSION_EXT)) {
msg = headers[x];
//break; @todo We'll take the last one that matches, if there are more than one.
// @todo In the case of frames coming via FTN packets, we are not currently deleting old entries
}
}
var page = this.name.toString();
var mb = new MsgAreas().getArea(FRAMES_MSG_BASE)
var msg = mb.frames
.sort(function(a,b) {
if (a.when_imported_time === b.when_imported_time)
return a.number < b.number
else
return (a.when_imported_time < b.when_imported_time); })
.filter(function(item) { return item.tags === page; }).pop();
if (msg === undefined) {
log(LOG_DEBUG,'|- Frame not found: ['+page.toString()+'] in ['+FRAMES_MSG_BASE+']');
return false;
} else {
log(LOG_DEBUG,'|- Loading frame: ['+page.toString()+'] from msgbase ['+msg.number+']');
log(LOG_DEBUG,'|- Loading frame: ['+page.toString()+'] from msgbase ['+msg.number+'] ['+SESSION_EXT+']');
var contents = mb.get_msg_body(false,msg.number,false,false,true,true).split("\r\n");
var contents = mb.getContent(msg.number);
contents.content = contents.content[SESSION_EXT];
var i;
for (var i=0; i<contents.length; i++) {
// Echomail tag line
if (contents[i] === '---' || contents[i].substring(0,4) === '--- ')
break;
}
contents.length = i;
try {
var result = JSON.parse(contents.join(''));
} catch(e) {
alert('Error ' + e + ' parsing JSON');
}
return this.preload(result,SESSION_EXT);
return this.preload(contents,SESSION_EXT);
}
return false;
@ -1109,7 +1095,7 @@ function Page(debug) {
* @param height
* @returns {boolean|null}
*/
this.preload = function(contents,ext,width,height) {
this.preload = function(contents,ext) {
switch (ext) {
// Messages
case 'txt':
@ -1117,7 +1103,7 @@ function Page(debug) {
var page = rawtoattrs(contents,this.width,this.__window__.body.y,this.__window__.body.x,debug);
this.__window__.body.__properties__.content = page.content;
this.__properties__.raw = contents;
return contents;
// ANSI files
case 'ans':
@ -1131,7 +1117,7 @@ function Page(debug) {
// Our fields are sorted in x descending order
this.input_fields = page.input_fields.sort(function(a,b) { return a.x < b.x ? 1 : -1; });
this.__properties__.raw = contents;
this.raw = contents;
break;
@ -1164,7 +1150,7 @@ function Page(debug) {
if (page.input_fields.length)
this.input_fields = page.input_fields.sort(function(a,b) { return a.x < b.x ? 1 : -1; });
this.__properties__.raw = base64_decode(contents[index]);
this.raw = base64_decode(contents[index]);
break;
@ -1249,21 +1235,7 @@ function Page(debug) {
break;
case 2:
// Load the page content
var content_file = FRAMES_HOME+SESSION_EXT+'/'+this.name.toString()+'.'+CONTENT_EXT;
log(LOG_DEBUG,'|-- Importing frame content: ['+content_file+']');
var f = new File(content_file);
if (! f.exists || ! f.open('rb',true)) {
log(LOG_ERROR,'|? File doesnt exist: ['+content_file+']');
this.get(new PageObject(FRAME_SYSTEM_ERROR));
break;
}
this.__properties__.raw = f.read();
f.close();
var page = rawtoattrs(this.__properties__.raw,this.width,this.__window__.body.y,this.__window__.body.x);
var page = rawtoattrs(contents.content,this.width,this.__window__.body.y,this.__window__.body.x);
this.__window__.body.__properties__.content = page.content;
this.dynamic_fields = page.dynamic_fields;
@ -1276,6 +1248,7 @@ function Page(debug) {
this.attrs = contents.attrs;
this.cost = contents.cost;
this.key = contents.key;
this.raw = contents.content;
break;
@ -1304,115 +1277,39 @@ function Page(debug) {
* Save the frame to the message base
*/
this.save = function() {
var mb = new MsgBase(FRAMES_MSG_BASE);
var headers;
var msgbase = new MsgAreas().getArea(FRAMES_MSG_BASE).msgbase;
try {
if (mb.open()) {
headers = mb.get_all_msg_headers(false,false) || [];
} else {
log(LOG_ERROR,FRAMES_MSG_BASE+' cannot be opened:'+mb.error);
return;
if (! msgbase.open()) {
log(LOG_ERROR,'! Message Base cannot be opened (save): ['+msgbase.error+']');
return false;
}
} catch (e) {
log(LOG_ERROR,FRAMES_MSG_BASE+' cannot be opened:'+e.message);
var hdr = {
to: this.name,
from: 'SYSTEM',
tags: this.name,
//date: msgs[x].date,
subject: 'Content',
};
return;
}
var page = {
'version': 2,
'attrs': p.attrs,
'cost': p.cost,
'key': p.key,
'content': p.raw,
};
// Build the save content
var content = {};
var body = LZString.compressToBase64(JSON.stringify(page));
for (var index in FRAME_SAVE_ATTRS) {
switch (FRAME_SAVE_ATTRS[index]) {
case 'cost':
content[FRAME_SAVE_ATTRS[index]] = this.cost;
break;
case 'dynamic_fields':
content[FRAME_SAVE_ATTRS[index]] = this.dynamic_fields;
break;
case 'frame':
content[FRAME_SAVE_ATTRS[index]] = this.name.frame;
break;
case 'index':
content[FRAME_SAVE_ATTRS[index]] = this.name.index;
break;
case 'input_fields':
content[FRAME_SAVE_ATTRS[index]] = this.input_fields;
break;
case 'isAccessible':
content[FRAME_SAVE_ATTRS[index]] = this.__properties__.isAccessible;
break;
case 'isPublic':
content[FRAME_SAVE_ATTRS[index]] = this.__properties__.isPublic;
break;
case 'key':
content[FRAME_SAVE_ATTRS[index]] = this.key;
break;
case 'type':
content[FRAME_SAVE_ATTRS[index]] = this.type;
break;
case 'version':
content[FRAME_SAVE_ATTRS[index]] = 1;
break;
case 'window':
content[FRAME_SAVE_ATTRS[index]] = this.__window__.body.__properties__.content;
break;
default:
log(LOG_ERROR,' ! NOTE Index ['+FRAME_SAVE_ATTRS[index]+'] has been ignored.');
continue;
}
log(LOG_DEBUG,' / Storing ['+FRAME_SAVE_ATTRS[index]+'] with value:'+content[FRAME_SAVE_ATTRS[index]]);
}
// Find existing message with the page number and delete it if defined
var msg;
for (var x in headers) {
if ((headers[x].tags === this.name.toString()) && (!(headers[x].attr&MSG_DELETE))) {
msg = headers[x];
break;
}
}
if (msg === undefined) {
log(LOG_DEBUG,' - Saving NEW frame: ['+this.name.toString()+'] to ['+FRAMES_MSG_BASE+']');
} else {
log(LOG_DEBUG,' - REPLACING frame: ['+this.name.toString()+'] at ['+msg.number+']');
if (! mb.remove_msg(msg.number))
log(LOG_ERROR,' ! Error removing frame: ['+this.name.toString()+'] to ['+msg.number+']');
}
log(LOG_DEBUG,'** Save frame with keys'+JSON.stringify(Object.keys(content)));
if (! mb.save_msg(
{
subject: this.name.toString(),
to: this.name.toString(),
from: SESSION_EXT,
tags: this.name.toString(),
},
JSON.stringify(content)
))
if (! msgbase.save_msg(hdr,body)) {
log(LOG_ERROR,' ! Error saving frame: ['+this.name.toString()+']');
}
mb.close();
msgbase.close();
// @todo Find old message and delete it?
return true;
}
this.scroll = function(x,y) {

View File

@ -8,7 +8,7 @@ if (argv.length !== 1) {
exit(1);
} else {
writeln('Showing frames:'+argv[0]);
writeln('Showing frame:'+argv[0]);
}
const SESSION_EXT = 'tex';

32
tools/frame_import.js Normal file
View File

@ -0,0 +1,32 @@
/**
* Load a frame, and store it in the message base
*/
load('ansitex/load/page.js');
load('ansitex/load/funcs.js');
load('lz-string.js');
/* parse command arguments */
if (argv.length !== 1) {
writeln('ERROR: Need a frame ID');
exit(1);
} else {
writeln('Importing frame:'+argv[0]);
}
var po = new PageObject(argv[0]);
// Load ANSItex frame
var SESSION_EXT = 'tex';
require('ansitex/load/session/ansitex.js','SESSION_ANSITEX');
var p = new Page();
p.get(po);
// Load Viewdata frame
var SESSION_EXT = 'vtx';
require('ansitex/load/session/viewdata.js','SESSION_VIEWDATA');
p.raw = p.file_content(FRAMES_HOME+SESSION_EXT+'/'+po.toString()+'.'+CONTENT_EXT);
p.save();

View File

@ -1,42 +0,0 @@
/**
* Load a frame, optionally with a new ANSI/BIN and load it into the msgbase.
*/
load('ansitex/load/funcs.js');
// Our page handler
load('ansitex/load/page.js');
/* parse command arguments */
if (argv.length !== 3) {
writeln('! ERROR: Need 3 arguments only');
exit(1);
}
var frame = argv.shift();
var index = argv.shift();
var file = argv.shift();
var ext = file_getext(file).substr(1).toLowerCase();
// Type of frame to load
switch (ext) {
case 'tex':
case 'ans':
require('ansitex/load/session/ansitex.js','SESSION_ANSITEX');
break;
case 'vtx':
case 'bin':
require('ansitex/load/session/viewdata.js','SESSION_VIEWDATA');
break;
}
var page = new Page();
if (page.get(new PageObject(frame,index))) {
page.import(file,ext);
page.save();
} else if (['vtx','tex'].indexOf(ext) !== -1) {
page.import(file,ext);
page.save();
}