Skip to content
Snippets Groups Projects
Commit 08786fbe authored by Rob Swindell's avatar Rob Swindell :speech_balloon:
Browse files

Merge remote-tracking branch 'origin/master'

parents 30391a1f eb1f9dd3
No related branches found
No related tags found
1 merge request!463MRC mods by Codefenix (2024-10-20)
Showing
with 3579 additions and 496 deletions
; Options for Xtrn Menu Mod
; http://wiki.synchro.net/module:xtrnmenu
; Refer to the wiki for instructions on how to customize individual menus
[xtrnmenu]
; Uncomment if you wish to have the mod hand over section menus to xtrn_sec.js
;use_xtrn_sec = true
; Default sort, can be "name", "key", or false (no sort)
sort = false
; Enable multi-column display (when more than 10 external programs in a section)
multicolumn = true
; Clear the (remote) terminal screen before displaying the menu
clear_screen = true
; uncomment and modify any of the below to change the look of the external programs menu
; to remove titles or underline, set to the text ' '
;multicolumn_separator: " "
; set the singlecolumn margin to the number of lines of your footer, if you have one
;singlecolumn_margin=2
;header_fmt: \1n\1c\1h%s \1n\1cExternal Programs:\r\n\r\n
;titles: \1n\1cKey \1h\xb3\1n\1c Name \1n\1c
multicolumn_fmt: \1h\1c%3s \xb3 \1n\1c%-32.32s \1h
singlecolumn_fmt: \1h\1c%3s \xb3 \1n\1c%s \1h
;which: \r\n\1-\1cWhich or \1h~Q\1n\1cuit: \1h
;underline: \1c\1h\xc4\xc4\xc4\xc4\xc5\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4
; used by the lightbar
multicolumn_fmt_inverse: \1n\1w[\1y\1h%2s\1n\1w] \1n\1w\1h\x015%-32.32s \1n\1h
singlecolumn_fmt_inverse: \1n\1w[\1y\1h%2s\1n\1w] \1n\1w\1h\x015%s \1n\1h
; to enable cost display, use these instead
; Note: cost not supported in special menus
;titles: \1n\1cInput \1h\xb3\1n\1c Name Cost \1n\1c
;multicolumn_fmt: \1h\1c%3s \xb3 \1n\1c%-26.26s\1h %5u
;singlecolumn_fmt: \1h\1c%3s \xb3 \1n\1c%-26.26s\1h %5u
;multicolumn_fmt_inverse: \1h\1c%3s \xb3 \1n\x016\1w\1h%-26.26s\1n \1c%5u
;singlecolumn_fmt_inverse: \1h\1c%3s \xb3 \1n\x016\1w\1h%-26.26s\1n \1c%5u
; These are used for the special menus (most launched, etc.)
; It adds the "stats" field which is the number of launches, amount of time, etc.
multicolumn_fmt_special: \1h\1c%3s \xb3 \1m%-21.21s\1h \1m%-10s
singlecolumn_fmt_special: \1h\1c%3s \xb3 \1m%-21.21s\1h \1m%-10s
multicolumn_fmt_special: \1h\1c%3s \xb3 \1m%-21.21s\1h \1m%-10s
singlecolumn_fmt_special: \1h\1c%3s \xb3 \1m%-21.21s\1h \1m%-10s
; Override the message when there are no programs available
; (defaults to text.dat NoXtrnPrograms)
;no_programs_msg:
; Override the restricted user msg
; (defaults to text.dat R_ExternalPrograms)
;restricted_user_msg:
; JSON service powers special menus (most popular, recent, etc.)
; Add appropriate entry to json-service.ini and set host/port here
;json_enabled = true
;json_host = localhost
;json_port = 10088
; Exclude external codes or external sections from being tracked
; and showing up in special menus (most popular, recent, etc.)
blacklist_tracking_xtrncodes: bullshit,sbbslist,avatchoo
blacklist_tracking_xtrnsec: operator
; Formatting for the "return to previous menu" option
return_msg: "\xae Return to Previous Menu"
logoff_msg: "Logoff"
quit_msg: "Quit"
; Formatting for the "return to previous menu" option
return_msg: "\xae Return to Previous Menu"
logoff_msg: "Logoff"
quit_msg: "Quit"
return_multicolumn_fmt: \1h\1c%3s \xb3 \1n\1c%-32.32s \1h
return_singlecolumn_fmt: \1h\1c%3s \xb3 \1n\1c%s \1h
return_multicolumn_fmt_inverse: \1h\1c%3s \xb3 \1n\x016\1w\1h%-32.32s \1n\1h
return_singlecolumn_fmt_inverse: \1h\1c%3s \xb3 \1n\x016\1w\1h%s \1n\1h
return_multicolumn_special_fmt: \1h\1c%3s \xb3 \1m%-32.32s\1h
return_singlecolumn_special_fmt: \1h\1c%3s \xb3 \1m%s\1h
return_multicolumn_special_fmt_inverse: \1h\1c%3s \xb3 \x015\1w\1h%-32.32s\1n
return_singlecolumn_special_fmt_inverse: \1h\1c%3s \xb3 \x015\1w\1h%s\1n
; Change display of filearea command menu
;xfer_prompt: "\x01n\x01c\xfe \x01b\x01hFile \x01n\x01c\xfe \x01h"
;xfer_prompt2: " \x01n\x01c@DIR@: \x01n"
;command_prompt: "\r\n\x01gCommand: "
;view_prompt: "\r\n\x01c\x01hView File(s)\r\n"
;searchfname_prompt: "\r\n\x01c\x01hSearch for Filename(s)\r\n"
;remove_prompt: "\r\n\x01c\x01hRemove/Edit File(s)\r\n"
;finddesc_prompt: "\r\n\x01c\x01hFind Text in File Descriptions (no wildcards)\r\n"
;download:prompt: "\r\n\x01c\x01hDownload File(s)\r\n"
; Change display of search menu
entersearchterm: "\x01y\x01hEnter search term: "
searchresultheader: "\x01n\x01cSearch Results for \x01h%s"
searchagainmsg: "\x01n\x01mPress S to Search Again."
; Feedback Module
;feedback_subject: "Game Server Feedback\r\n"
;feedback_msg: Thank you for your Feedback, @SYSOP@ will get back to you ASAP!\r\n\r\n
; Favorites Module
;favorite_add_item: "Add Item"
;favorte_remove_item: "Remove Item"
;add_favorites_msg: "\x01c\x01hAdd Favorite"
;remove_favorites_msg: "\x01c\x01hRemove Favorite"
;favorites_inst: "\x01n\x01w\x01h\x012 [Up/Down/Home/End] to Navigate, [Enter] to Select, [Q] to Quit, [S] to Search "
;favorites_inst_rem: "\x01n\x01w\x01h\x012 [Up/Down/Home/End] to Navigate, [Enter] to Select, [Q] to Quit "
;favorite_add_search_prompt: "\x01c\x01hSearch (ESC to Cancel): \x01n"
; autocomplete (search) box on add favorite
; see cga_defs.js for color codes
; autocomplete input box
;favorite_add_search_fg=LIGHTGRAY
;favorite_add_search_bg=BG_BLACK
; autocomplete result box
;favorite_add_search_sfg=LIGHTGRAY
;favorite_add_search_sbg=BG_BLACK
; autocomplete highlighted row
;favorite_add_search_hsfg=WHITE
;favorite_add_search_hsbg=BG_MAGENTA
; scrolling menu on add favorite
; lightbar non-current item
;favorite_add_fg=LIGHTGRAY
;favorite_add_bg=BG_BLACK
; lightbar current item
;favorite_add_lfg=WHITE
;favorite_add_lbg=BG_MAGENTA
; tree heading
;favorite_add_cfg=WHITE
;favorite_add_cbg=BG_BLACK
\ No newline at end of file
......@@ -177,3 +177,5 @@
forum_extended_ascii=false
max_messages=0
nodelist_ibbs = true
darkmode_off=false
......@@ -26,6 +26,7 @@ var version_notice = "BinkIT/" + REVISION;
var semaphores = [];
// data/binkstats.ini
var stats = { inbound: { true: {}, false: {} }, callout: { true: {}, false: {} }, totals: {} };
var cfgfname;
function update_stats(stats, addr, bp, host)
{
......@@ -609,7 +610,7 @@ function callout(addr, scfg, locks, bicfg)
log(LOG_INFO, format("%s callout to %s started", bp.revision, addr));
if (bicfg === undefined)
bicfg = new BinkITCfg();
bicfg = new BinkITCfg(cfgfname);
bp.system_operator = bicfg.sysop;
bp.plain_auth_only = bicfg.plain_auth_only;
bp.crypt_support = bicfg.crypt_support;
......@@ -845,8 +846,8 @@ function run_outbound(ran)
var scfg_ob;
log(LOG_DEBUG, "Running outbound");
scfg = new SBBSEchoCfg();
bicfg = new BinkITCfg();
scfg = new SBBSEchoCfg(cfgfname);
bicfg = new BinkITCfg(cfgfname);
if (!scfg.is_flo) {
log(LOG_ERROR, "sbbsecho not configured for FLO-style mailers.");
......@@ -1011,8 +1012,8 @@ function run_inbound(sock)
log(LOG_INFO, bp.revision + " inbound connection from " +sock.remote_ip_address+":"+sock.remote_port);
bp.cb_data = {
binkitcfg:new BinkITCfg(),
binkit_scfg:new SBBSEchoCfg(),
binkitcfg:new BinkITCfg(cfgfname),
binkit_scfg:new SBBSEchoCfg(cfgfname),
binkit_file_actions:{},
binkit_flow_contents:{},
binkit_locks:locks
......@@ -1057,7 +1058,7 @@ function poll_node(addr_str, scfg, bicfg, myaddr)
var locks = [];
if (scfg === undefined)
scfg = new SBBSEchoCfg();
scfg = new SBBSEchoCfg(cfgfname);
if (myaddr === undefined)
myaddr = FIDO.parse_addr(system.fido_addr_list[0], 1, 'fidonet');
......@@ -1092,8 +1093,8 @@ function run_polls(ran)
var locks = [];
log(LOG_DEBUG, "Running polls");
scfg = new SBBSEchoCfg();
bicfg = new BinkITCfg();
scfg = new SBBSEchoCfg(cfgfname);
bicfg = new BinkITCfg(cfgfname);
myaddr = FIDO.parse_addr(system.fido_addr_list[0], 1, 'fidonet');
Object.keys(bicfg.node).forEach(function(addr_str) {
......@@ -1194,6 +1195,11 @@ if (system.fido_addr_list.length < 1) {
exit(1);
}
for (i = 0; i < argv.length; i++) {
if(file_getext(argv[i]) == ".ini")
cfgfname = argv[i];
}
// If we're running as a service, call run_inbound().
if (sock !== undefined && sock.descriptor !== -1)
run_inbound(sock);
......
......@@ -216,37 +216,37 @@ load('tree.js');
var Typeahead = function (options) {
var properties = {
'x' : 0,
'y' : 0,
'len' : console.screen_columns,
'height' : 0,
'prompt' : '',
'fg' : LIGHTGRAY,
'bg' : BG_BLUE,
'sfg' : LIGHTGRAY,
'sbg' : BG_BLUE,
'hsfg' : WHITE,
'hsbg' : BG_CYAN,
'cursor' : ascii(219),
'position' : 0,
'text' : '',
'datasources' : [],
'delay' : 1,
'minLength' : 1,
'lastKey' : system.timer,
'suggested' : false,
'attr' : console.attributes,
'focus' : true,
'maxResults': 0,
x: 0,
y: 0,
len: console.screen_columns,
height: 0,
prompt: '',
fg: LIGHTGRAY,
bg: BG_BLUE,
sfg: LIGHTGRAY,
sbg: BG_BLUE,
hsfg: WHITE,
hsbg: BG_CYAN,
cursor: ascii(219),
position: 0,
text: '',
datasources: [],
delay: 1,
minLength: 1,
lastKey: system.timer,
suggested: false,
attr: console.attributes,
focus: true,
maxResults: 0,
};
var display = {
'parentFrame' : undefined,
'frame' : undefined,
'inputFrame' : undefined,
'cursor' : undefined,
'treeFrame' : undefined,
'tree' : undefined
parentFrame: undefined,
frame: undefined,
inputFrame: undefined,
cursor: undefined,
treeFrame: undefined,
tree: undefined
};
function initSettings() {
......@@ -355,17 +355,15 @@ var Typeahead = function (options) {
display.treeFrame.invalidate();
}
if (suggestions.length < 1) {
display.tree = undefined;
return;
}
display.tree = new Tree(display.treeFrame);
display.tree.colors.fg = properties.sfg;
display.tree.colors.bg = properties.sbg;
display.tree.colors.lfg = properties.hsfg;
display.tree.colors.lbg = properties.hsbg;
if (suggestions.length < 1) {
display.tree.addItem('No results found');
} else {
display.tree.addItem('');
for (var n = 0; n < (properties.maxResults || suggestions.length); n++) {
if (typeof suggestions[n] === 'object' && typeof suggestions[n].text === 'string') {
......@@ -375,6 +373,7 @@ var Typeahead = function (options) {
display.tree.addItem(suggestions[n]);
}
}
}
display.tree.open();
......@@ -412,7 +411,8 @@ var Typeahead = function (options) {
break;
case KEY_UP:
case KEY_DOWN:
if (typeof display.tree !== 'undefined') {
//if (typeof display.tree !== 'undefined') {
if (display.tree.items.length > 1) {
display.tree.getcmd(key);
}
break;
......@@ -429,6 +429,7 @@ var Typeahead = function (options) {
properties.position = (properties.position >= properties.text.length) ? properties.text.length : properties.position + 1;
break;
case '\b':
case '\x08':
if (properties.position === 0) break;
properties.text = properties.text.split('');
properties.text.splice((properties.position - 1), 1);
......
......@@ -67,6 +67,12 @@ ExternalMenus.prototype.getOptions = function(menutype, menuid) {
if (this.options.singlecolumn_fmt === undefined)
this.options.singlecolumn_fmt = "\x01h\x01c%3u \xb3 \x01n\x01c%s\x01h ";
if (this.options.multicolumn_fmt_inverse === undefined)
this.options.multicolumn_fmt_inverse = system.text(XtrnProgLstFmt);
if (this.options.singlecolumn_fmt_inverse === undefined)
this.options.singlecolumn_fmt_inverse = "\x01h\x01c%3u \xb3 \x01n\x01c%s\x01h ";
if (this.options.singlecolumn_margin == undefined)
this.options.singlecolumn_margin = 7;
......@@ -120,6 +126,20 @@ ExternalMenus.prototype.getOptions = function(menutype, menuid) {
this.options.singlecolumn_fmt = "\x01h\x01c%3s \xb3 \x01n\x01c%s\x01h ";
}
if (typeof this.xtrn_custommenu_options.multicolumn_fmt_inverse !== "undefined") {
this.options.multicolumn_fmt_inverse = this.xtrn_custommenu_options.multicolumn_fmt_inverse;
} else {
// cannot default to xtrn_sec multicolumn_fmt due to use of %u instead of %s
this.options.multicolumn_fmt_inverse = "\x01h\x01c%3s \xb3 \x01n\x016\x01w\x01h%-32.32s \x01n\x01h";
}
if (typeof this.xtrn_custommenu_options.singlecolumn_fmt_inverse !== "undefined") {
this.options.singlecolumn_fmt_inverse = this.xtrn_custommenu_options.singlecolumn_fmt_inverse;
} else {
// cannot default to xtrn_sec multicolumn_fmt due to use of %u instead of %s
this.options.singlecolumn_fmt_inverse = "\x01h\x01c%3s \xb3 \x01n\x016\x01w\x01h%s \x01n\x01h";
}
this.options.header_fmt = (typeof this.xtrn_custommenu_options.header_fmt !== "undefined")
? this.xtrn_custommenu_options.header_fmt : this.options.header_fmt;
......@@ -148,12 +168,6 @@ ExternalMenus.prototype.getOptions = function(menutype, menuid) {
? this.xtrn_custommenu_options.singlecolumn_margin : this.options.singlecolumn_margin;
if (typeof bbs !== "undefined") {
this.options.singlecolumn_height = (typeof this.xtrn_custommenu_options.singlecolumn_height !== "undefined")
? this.xtrn_custommenu_options.singlecolumn_height : this.options.singlecolumn_height;
if (this.options.singlecolumn_height == undefined)
this.options.singlecolumn_height = console.screen_rows - this.options.singlecolumn_margin;
// override and turn off multicolumn if terminal width is less than 80
if (console.screen_columns < 80)
options.multicolumn = false;
......@@ -164,13 +178,25 @@ ExternalMenus.prototype.getOptions = function(menutype, menuid) {
// Allow overriding on a per-menu basis
var menuoptions = load({}, "modopts.js", "xtrnmenu:" + menuid);
if ((typeof menuid !== "undefined") && (menuoptions != null)) {
if ((typeof menuid !== "undefined") && (menuoptions !== null)) {
for (var m in menuoptions) {
this.options[m] = menuoptions[m];
}
}
}
this.options.json_enabled = (typeof this.xtrn_custommenu_options.json_enabled !== undefined)
? this.xtrn_custommenu_options.json_enabled : false;
this.options.json_host = (typeof this.xtrn_custommenu_options.json_host !== undefined)
? this.xtrn_custommenu_options.json_host : "localhost";
this.options.json_port = (typeof this.xtrn_custommenu_options.json_port !== undefined)
? this.xtrn_custommenu_options.json_port : 10088;
this.options.blacklist_tracking_xtrncodes = (typeof this.xtrn_custommenu_options.blacklist_tracking_xtrncodes !== undefined)
? this.xtrn_custommenu_options.blacklist_tracking_xtrncodes : "";
this.options.blacklist_tracking_xtrnsec = (typeof this.xtrn_custommenu_options.blacklist_tracking_xtrnsec !== undefined)
? this.xtrn_custommenu_options.blacklist_tracking_xtrnsec : "";
// these options only apply to terminals/consoles
// the intention is to obtain all the mod_opts options for xtrn_sec, and
......@@ -185,6 +211,8 @@ ExternalMenus.prototype.getOptions = function(menutype, menuid) {
this.options.custom_menu_program_not_found_msg = "Program %PROGRAMID% not found";
}
this.options.custom = this.xtrn_custommenu_options;
return this.options;
}
......@@ -216,20 +244,20 @@ ExternalMenus.prototype.getMenu = function(menuid) {
xtrn_area.sec_list.forEach(function (sec) {
if (sec.can_access) {
menuitems.push({
"input": i,
"target": sec.code,
"type": "xtrnmenu",
"title": sec.name,
"access_string": sec.ars
input: i,
target: sec.code,
type: "xtrnmenu",
title: sec.name,
access_string: sec.ars
});
i++;
}
});
menu = {
"id": "main",
"title": "Main Menu",
"items": menuitems
id: "main",
title: "Main Menu",
items: menuitems
};
}
return menu;
......@@ -244,12 +272,17 @@ ExternalMenus.prototype.getSectionMenu = function(menuid) {
}
var menuitems = [];
var menu, title;
var title;
xtrn_area.sec_list.some(function (sec) {
var menu = {
id: menuid,
title: null,
items: []
}
xtrn_area.sec_list.some(function (sec) {
if (sec.code.toLowerCase() == menuid.toLowerCase()) {
title = sec.name;
menu.title = sec.name;
if (!sec.can_access || sec.prog_list.length < 1) {
return false;
......@@ -258,22 +291,18 @@ ExternalMenus.prototype.getSectionMenu = function(menuid) {
var i = 1;
sec.prog_list.some(function (prog) {
menuitems.push({
'input' : i,
'target': prog.code,
'title': prog.name,
'type': 'xtrnprog',
'access_string': prog.ars,
'cost': prog.cost
input : i,
target: prog.code,
title: prog.name,
type: 'xtrnprog',
access_string: prog.ars,
cost: prog.cost
});
i++;
});
if (menuitems.length > 0) {
menu = {
'id': menuid,
'title': title,
'items': menuitems,
};
menu.items = menuitems;
}
return;
}
......@@ -412,3 +441,214 @@ ExternalMenus.prototype.sort_by_input = function(a, b) {
}
return 0;
}
// Handle json update
ExternalMenus.prototype.processUpdate = function(update) {
log(ERROR, "Unhandled JSON DB packet: " + JSON.stringify(update));
}
// Sort for special menus, by value numerically desc
ExternalMenus.prototype.sort_special = function(obj) {
var keys = [];
for(var key in obj) {
keys.push(key);
}
return keys.sort(function(a,b) { return obj[b]-obj[a]});
}
// return menu object for special menu (most recent, etc.)
ExternalMenus.prototype.getSpecial = function(menutype, title, itemcount) {
var options = this.getOptions('custommenu', menutype);
var menu;
var menuitems = [];
if (itemcount === undefined) {
itemcount = 0;
}
if (menutype === undefined) {
log(LOG_DEBUG, "xtrnmenulib: getSpecial called without menutype");
return false;
}
if (!this.options.json_enabled) {
log(LOG_DEBUG, "xtrnmenulib: Skipping " + menutype + " because JSON is not enabled");
return false;
}
try {
require("json-client.js", "JSONClient");
var jsonClient = new JSONClient(this.options.json_host, this.options.json_port);
jsonClient.callback = this.processUpdate;
} catch (e) {
writeln("NP" + e);
log(LOG_ERR, "xtrnmenulib: Could not initialize JSON database so special menu is now disabled: " + e);
return false;
}
var sortedItems = [];
var jsonData = [];
switch (menutype) {
// game keys sorted by most recent descending
case 'recentall':
jsonData = jsonClient.read("xtrnmenu", "launchstart", 1);
break;
case 'recentuser':
jsonData = jsonClient.read("xtrnmenu", "launchstart_user_" + user.alias, 1);
break;
case 'mostlaunchedall':
jsonData = jsonClient.read("xtrnmenu", "launchnum", 1);
break;
case 'mostlauncheduser':
jsonData = jsonClient.read("xtrnmenu", "launchnum_user_" + user.alias, 1);
break;
case 'longestrunall':
jsonData = jsonClient.read("xtrnmenu", "timeran", 1);
break;
case 'longestrunuser':
jsonData = jsonClient.read("xtrnmenu", "timeran_user_" + user.alias, 1);
break;
default:
log(LOG_ERR, "xtrnmenulib: Unknown special menu type: " + menutype);
return false;
}
if (!jsonData) {
jsonData = {};
}
sortedItems = this.sort_special(jsonData);
var i = 1;
for (var d=0; d<sortedItems.length; d++) {
var doorid = sortedItems[d];
for (var e in xtrn_area.prog) {
if (xtrn_area.prog[e].code.toLowerCase() == doorid.toLowerCase()) {
var stats;
switch (menutype) {
case 'longestrunall':
case 'longestrunuser':
var seconds = jsonData[doorid];
var hours = ~~(seconds/3600);
var mins = ~~((seconds % 3600) / 60);
var secs = ~~seconds % 60;
stats = ("00"+hours).slice(-2) + ":" + ("00"+mins).slice(-2) + ":" + ("00"+secs).slice(-2);
break;
case 'recentall':
case 'recentuser':
var elapsedtime = (time() - jsonData[doorid])*1000;
var msPerMin = 60000;
var msPerHour = msPerMin * 60;
var msPerDay = msPerHour * 24;
var msPerMon = msPerDay * 30;
var msPerYear = msPerDay * 365;
if (elapsedtime < msPerMin) {
stats = Math.round(elapsedtime/1000) + ' sec ago';
} else if (elapsedtime < msPerHour) {
stats = Math.round(elapsedtime/msPerMin) + ' min ago';
} else if (elapsedtime < msPerDay) {
var stat = Math.round(elapsedtime/msPerHour)
stats = Math.round(elapsedtime/msPerHour) + ' hr ago';
} else if (elapsedtime < msPerMon) {
stats = Math.round(elapsedtime/msPerDay) + ' day ago';
} else if (elapsedtime < msPerYear) {
stats = Math.round(elapsedtime/msPerMonth) + ' mon ago';
} else {
stats = Math.round(elapsedtime/msPerYear) + ' yr ago';
}
break;
default:
stats = jsonData[doorid].toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");;
break;
}
menuitems.push({
input: i,
target: xtrn_area.prog[e].code,
title: xtrn_area.prog[e].name,
type: 'xtrnprog',
access_string: xtrn_area.prog[e].ars,
cost: xtrn_area.prog[e].cost,
stats: stats,
});
i++;
break;
}
}
if ((itemcount > 0) && ((d + 1) >= itemcount)) {
break;
}
}
if (menuitems.length > 0) {
menu = {
id: menutype,
title: title,
items: menuitems,
};
}
return menu;
}
// return menu object for user's favorites
ExternalMenus.prototype.getFavorites = function(title, itemcount) {
var menu;
var menuitems = [];
if (itemcount === undefined) {
itemcount = 0;
}
if (!this.options.json_enabled) {
log(LOG_DEBUG, "xtrnmenulib: Skipping favorites because JSON is not enabled");
return false;
}
try {
require("json-client.js", "JSONClient");
var jsonClient = new JSONClient(this.options.json_host, this.options.json_port);
jsonClient.callback = this.processUpdate;
} catch (e) {
log(LOG_ERR, "xtrnmenulib: Could not initialize JSON database so favorites is now disabled: " + e);
return false;
}
var sortedItems = [];
var jsonData = jsonClient.read("xtrnmenu", "favorites_" + user.alias, 1);
if (!jsonData) {
jsonData = {};
}
var i = 1;
for (var d=0; d<jsonData.length; d++) {
for (var e in xtrn_area.prog) {
if (xtrn_area.prog[e].code.toLowerCase() == jsonData[d].toLowerCase()) {
var stats;
menuitems.push({
input: i,
target: xtrn_area.prog[e].code,
title: xtrn_area.prog[e].name,
type: 'xtrnprog',
access_string: xtrn_area.prog[e].ars,
cost: xtrn_area.prog[e].cost,
});
i++;
break;
}
}
if ((itemcount > 0) && ((d + 1) >= itemcount)) {
break;
}
}
menu = {
id: 'favorites',
title: title !== undefined ? title : 'Favorites',
items: menuitems,
};
return menu;
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
......@@ -8,4 +8,4 @@ vpath %.c ..
$(SCFG): $(OBJS) $(CRYPT_DEPS)
@echo Linking $@
${QUIET}$(CC) $(LDFLAGS) $(MT_LDFLAGS) -o$@ $(OBJS) $(SMBLIB_LIBS) $(ENCODE_LIBS) $(HASH_LIBS) $(UIFC-MT_LIBS) $(CIOLIB-MT_LIBS) $(XPDEV-MT_LIBS) $(CRYPT_LIBS)
${QUIET}$(CC) $(LDFLAGS) $(MT_LDFLAGS) -o$@ $(OBJS) $(SMBLIB_LIBS) $(ENCODE_LIBS) $(HASH_LIBS) $(UIFC-MT_LIBS) $(CIOLIB-MT_LIBS) $(CRYPT_LIBS) $(XPDEV-MT_LIBS)
......@@ -47,7 +47,20 @@
<ul class="nav navbar-nav">
<?xjs menu(getPageList(settings.web_pages)); ?>
</ul>
<ul class="nav navbar-nav navbar-right">
<?xjs if (!settings.darkmode_off) { ?>
<li class="nav-item dark-switch">
<div class="form-group">
<div class="checkbox checbox-switch darkswitchbox">
<label>
<input type="checkbox" id="darkSwitch" />Dark
<span></span>
</label>
</div>
</div>
</li>
<?xjs } ?>
<?xjs if (user.alias === settings.guest || user.number < 1) { ?>
<?xjs if (settings.user_registration) { ?>
<li>
......
......@@ -73,7 +73,7 @@ function scan() {
if (e.status != NODE_INUSE) {
return {
node: i + 1,
status: null,
status: locale.strings.sidebar_node_list.label_waiting_for_call,
action: null,
user: null,
connection: ''
......
......@@ -100,6 +100,7 @@ label_node_column = Node
label_send_telegram = Send a telegram
label_status_column = Status
label_status_web = browsing
label_waiting_for_call = Waiting for call
[sidebar_recent_visitors]
label_title = Recent Visitors
......
......@@ -20,6 +20,7 @@
<script id="fTelnetScript" src="<?xjs write(get_url()); ?>"></script>
<script>
window.addEventListener('load', (event) => {
var wsp = <?xjs write(settings.wsp || GetWebSocketServicePort()); ?>;
var wssp = <?xjs write(settings.wssp || GetWebSocketServicePort(true)); ?>;
var Options = new fTelnetOptions();
......@@ -44,6 +45,7 @@
fTelnet.Connect();
});
}
});
</script>
<?xjs } ?>
......
......@@ -43,6 +43,7 @@
<script id="fTelnetScript" src="<?xjs write(get_url()); ?>"></script>
<script type="text/javascript">
window.addEventListener('load', (event) => {
var wsp = <?xjs write(settings.wsp || GetWebSocketServicePort()); ?>;
var wssp = <?xjs write(settings.wssp || GetWebSocketServicePort(true)); ?>;
var Options = new fTelnetOptions();
......@@ -62,10 +63,11 @@
Options.ScreenRows = 25;
Options.SplashScreen = Options.SplashScreen = '<?xjs write(get_splash()); ?>';
Options.WebSocketUrlPath = '?Port=<?xjs write(GetRLoginPort()); ?>';
var fTelnet = new fTelnetClient('fTelnetContainer', Options);
window.fTelnet = new fTelnetClient('fTelnetContainer', Options);
fTelnet.OnConnectionClose = function () {
window.location.reload();
};
});
async function launchXtrn(code) {
await v4_get('./api/system.ssjs?call=set-xtrn-intent&code=' + code);
......
<!--HIDDEN:Games-->
<!--Games-->
<?xjs
/**
* Web Display for Custom External Program Menus
* by Michael Long mlong innerrealmbbs.us
*
* See wiki at http://wiki.synchro.net/module:xtrnmenumod
* See wiki at http://wiki.synchro.net/module:xtrnmenu
*/
load("ftelnethelper.js");
......@@ -33,8 +33,43 @@
<?xjs
var menuobj;
if ((Request.get_param('type') == 'xtrnmenu') && Request.has_param('target')) {
menuobj = ExternalMenus.getSectionMenu(Request.get_param('target'));
if (Request.get_param('type')) {
var target = Request.get_param('target');
switch (Request.get_param('type')) {
case 'custommenu':
if (target !== undefined) {
menuobj = ExternalMenus.getMenu(target);
}
break;
case 'xtrnmenu':
if (target !== undefined) {
menuobj = ExternalMenus.getSectionMenu(target);
}
break;
case 'recentall':
menuobj = ExternalMenus.getSpecial(Request.get_param('type'), "Most Recent - All", target);
break;
case 'recentuser':
menuobj = ExternalMenus.getSpecial(Request.get_param('type'), "Most Recent - Yours", target);
break;
case 'mostlaunchedall':
menuobj = ExternalMenus.getSpecial(Request.get_param('type'), "Most Launched - All", target);
break;
case 'mostlauncheduser':
menuobj = ExternalMenus.getSpecial(Request.get_param('type'), "Most Launched - Yours", target);
break;
case 'longestrunall':
menuobj = ExternalMenus.getSpecial(Request.get_param('type'), "Longest Run - All", target);
break;
case 'longestrunuser':
menuobj = ExternalMenus.getSpecial(Request.get_param('type'), "Longest Run - Yours", target);
break;
case 'favorites':
menuobj = ExternalMenus.getFavorites("Favorites", target);
break;
default:
break;
}
} else {
if (Request.has_param('target')) {
menuobj = ExternalMenus.getMenu(Request.get_param('target'));
......@@ -57,11 +92,27 @@
if (settings.xtrn_blacklist.indexOf(menuitem.target.toLowerCase()) > -1) {
return;
}
switch (menuitem.type) {
case 'custommenu':
case 'xtrnmenu':
case 'xtrnprog':
case 'favorites':
case 'recentall':
case 'recentuser':
case 'mostlaunchedall':
case 'mostlauncheduser':
case 'longestrunuser':
case 'longestrunall':
menuitems.push({
'itemtitle': menuitem.title,
'itemtype': menuitem.type,
'itemtarget': menuitem.target
'itemtarget': menuitem.target,
'stats': typeof menuitem.stats !== undefined ? menuitem.stats : null
});
break;
default:
break;
}
});
}
?>
......@@ -69,6 +120,7 @@
<script id="fTelnetScript" src="<?xjs write(get_url()); ?>"></script>
<script type="text/javascript">
window.addEventListener('load', (event) => {
var wsp = <?xjs write(settings.wsp || GetWebSocketServicePort()); ?>;
var wssp = <?xjs write(settings.wssp || GetWebSocketServicePort(true)); ?>;
var Options = new fTelnetOptions();
......@@ -88,10 +140,11 @@
Options.ScreenRows = 25;
Options.SplashScreen = Options.SplashScreen = '<?xjs write(get_splash()); ?>';
Options.WebSocketUrlPath = '?Port=<?xjs write(GetRLoginPort()); ?>';
var fTelnet = new fTelnetClient('fTelnetContainer', Options);
window.fTelnet = new fTelnetClient('fTelnetContainer', Options);
fTelnet.OnConnectionClose = function () {
window.location.reload();
};
});
async function launchXtrn() {
var code = event.srcElement.id;
......@@ -109,12 +162,19 @@
sessionStorage.setItem("mainmenu", currentTitle);
}
var div = $('#xtrn-list');
menuitems.forEach(function (menuitem) {
var a = document.createElement('a');
$(a).addClass("list-group-item");
$(a).addClass("striped");
a.text = menuitem.itemtitle;
if (typeof menuitem.stats !== "undefined") {
var badge = document.createElement('span');
$(badge).addClass('badge').text(menuitem.stats);
a.appendChild(badge);
}
if (menuitem.itemtype == "xtrnprog") {
a.href = "#fTelnet";
a.id = menuitem.itemtarget;
......
<!--Game Stats-->
<div class="list-group">
<h1>Game Stats</h1>
<?xjs
load('sbbsdefs.js');
load("xtrnmenulib.js");
var ExternalMenus = new ExternalMenus();
if (typeof settings.xtrn_blacklist === 'string') {
settings.xtrn_blacklist = settings.xtrn_blacklist.toLowerCase().split(',');
} else {
settings.xtrn_blacklist = [];
}
// Edit these lines as needed to adjust the page
gameStats("recentall", "Most Recent", 10);
gameStats("mostlaunchedall", "Top 15 Most Launched", 15);
gameStats("longestrunall", "Top 15 Longest Run", 15);
function gameStats(menutype, title, maxitems) {
var menuobj = ExternalMenus.getSpecial(menutype, title);
?>
<div class="row list-group-item" style="background-color: #993399; color: #FFF">
<div class="col-sm-12"><h3><?xjs write(title) ?></h3></div>
</div>
<?xjs
if ((typeof menuobj.items !== "undefined") || (menuobj.items.length > 0)) {
var i = 0;
menuobj.items.some(function (menuitem) {
if (menuitem.type != "xtrnprog") {
return;
}
if (settings.xtrn_blacklist.indexOf(menuitem.target.toLowerCase()) > -1) return;
if (++i > maxitems) return;
?>
<div class="row list-group-item striped">
<div class="col-sm-2"><span class="badge badge-inverse"><?xjs write(menuitem.stats) ?></span></div>
<div class="col-sm-10"><?xjs write(menuitem.title) ?></div>
</div>
<?xjs
});
}
}
?>
</div>
/* ---------------------------------------------------
Project : CSS Checkbox Switch
Author : Partha Kar (https://www.facebook.com/partha.creativemind)
Version : 1.0
Release Dtae : 15 November, 2017
---------------------------------------------------- */
.checkbox.checbox-switch {
padding-left: 0;
}
.checkbox.checbox-switch label,
.checkbox-inline.checbox-switch {
display: inline-block;
position: relative;
padding-left: 0;
}
.checkbox.checbox-switch label input,
.checkbox-inline.checbox-switch input {
display: none;
}
.checkbox.checbox-switch label span,
.checkbox-inline.checbox-switch span {
width: 35px;
border-radius: 20px;
height: 18px;
border: 1px solid #dbdbdb;
background-color: rgb(255, 255, 255);
border-color: rgb(223, 223, 223);
box-shadow: rgb(223, 223, 223) 0px 0px 0px 0px inset;
transition: border 0.4s ease 0s, box-shadow 0.4s ease 0s;
display: inline-block;
vertical-align: middle;
margin-right: 5px;
}
.checkbox.checbox-switch label span:before,
.checkbox-inline.checbox-switch span:before {
display: inline-block;
width: 16px;
height: 16px;
border-radius: 50%;
background: rgb(255,255,255);
content: " ";
top: 0;
position: relative;
left: 0;
transition: all 0.3s ease;
box-shadow: 0 1px 4px rgba(0,0,0,0.4);
}
.checkbox.checbox-switch label > input:checked + span:before,
.checkbox-inline.checbox-switch > input:checked + span:before {
left: 17px;
}
/* Switch Default */
.checkbox.checbox-switch label > input:checked + span,
.checkbox-inline.checbox-switch > input:checked + span {
background-color: rgb(180, 182, 183);
border-color: rgb(180, 182, 183);
box-shadow: rgb(180, 182, 183) 0px 0px 0px 8px inset;
transition: border 0.4s ease 0s, box-shadow 0.4s ease 0s, background-color 1.2s ease 0s;
}
.checkbox.checbox-switch label > input:checked:disabled + span,
.checkbox-inline.checbox-switch > input:checked:disabled + span {
background-color: rgb(220, 220, 220);
border-color: rgb(220, 220, 220);
box-shadow: rgb(220, 220, 220) 0px 0px 0px 8px inset;
transition: border 0.4s ease 0s, box-shadow 0.4s ease 0s, background-color 1.2s ease 0s;
}
.checkbox.checbox-switch label > input:disabled + span,
.checkbox-inline.checbox-switch > input:disabled + span {
background-color: rgb(232,235,238);
border-color: rgb(255,255,255);
}
.checkbox.checbox-switch label > input:disabled + span:before,
.checkbox-inline.checbox-switch > input:disabled + span:before {
background-color: rgb(248,249,250);
border-color: rgb(243, 243, 243);
box-shadow: 0 1px 4px rgba(0,0,0,0.1);
}
/* Switch Light */
.checkbox.checbox-switch.switch-light label > input:checked + span,
.checkbox-inline.checbox-switch.switch-light > input:checked + span {
background-color: rgb(248,249,250);
border-color: rgb(248,249,250);
box-shadow: rgb(248,249,250) 0px 0px 0px 8px inset;
transition: border 0.4s ease 0s, box-shadow 0.4s ease 0s, background-color 1.2s ease 0s;
}
/* Switch Dark */
.checkbox.checbox-switch.switch-dark label > input:checked + span,
.checkbox-inline.checbox-switch.switch-dark > input:checked + span {
background-color: rgb(52,58,64);
border-color: rgb(52,58,64);
box-shadow: rgb(52,58,64) 0px 0px 0px 8px inset;
transition: border 0.4s ease 0s, box-shadow 0.4s ease 0s, background-color 1.2s ease 0s;
}
.checkbox.checbox-switch.switch-dark label > input:checked:disabled + span,
.checkbox-inline.checbox-switch.switch-dark > input:checked:disabled + span {
background-color: rgb(100, 102, 104);
border-color: rgb(100, 102, 104);
box-shadow: rgb(100, 102, 104) 0px 0px 0px 8px inset;
transition: border 0.4s ease 0s, box-shadow 0.4s ease 0s, background-color 1.2s ease 0s;
}
/* Switch Success */
.checkbox.checbox-switch.switch-success label > input:checked + span,
.checkbox-inline.checbox-switch.switch-success > input:checked + span {
background-color: rgb(40, 167, 69);
border-color: rgb(40, 167, 69);
box-shadow: rgb(40, 167, 69) 0px 0px 0px 8px inset;
transition: border 0.4s ease 0s, box-shadow 0.4s ease 0s, background-color 1.2s ease 0s;
}
.checkbox.checbox-switch.switch-success label > input:checked:disabled + span,
.checkbox-inline.checbox-switch.switch-success > input:checked:disabled + span {
background-color: rgb(153, 217, 168);
border-color: rgb(153, 217, 168);
box-shadow: rgb(153, 217, 168) 0px 0px 0px 8px inset;
}
/* Switch Danger */
.checkbox.checbox-switch.switch-danger label > input:checked + span,
.checkbox-inline.checbox-switch.switch-danger > input:checked + span {
background-color: rgb(200, 35, 51);
border-color: rgb(200, 35, 51);
box-shadow: rgb(200, 35, 51) 0px 0px 0px 8px inset;
transition: border 0.4s ease 0s, box-shadow 0.4s ease 0s, background-color 1.2s ease 0s;
}
.checkbox.checbox-switch.switch-danger label > input:checked:disabled + span,
.checkbox-inline.checbox-switch.switch-danger > input:checked:disabled + span {
background-color: rgb(216, 119, 129);
border-color: rgb(216, 119, 129);
box-shadow: rgb(216, 119, 129) 0px 0px 0px 8px inset;
transition: border 0.4s ease 0s, box-shadow 0.4s ease 0s, background-color 1.2s ease 0s;
}
/* Switch Primary */
.checkbox.checbox-switch.switch-primary label > input:checked + span,
.checkbox-inline.checbox-switch.switch-primary > input:checked + span {
background-color: rgb(0, 105, 217);
border-color: rgb(0, 105, 217);
box-shadow: rgb(0, 105, 217) 0px 0px 0px 8px inset;
transition: border 0.4s ease 0s, box-shadow 0.4s ease 0s, background-color 1.2s ease 0s;
}
.checkbox.checbox-switch.switch-primary label > input:checked:disabled + span,
.checkbox-inline.checbox-switch.switch-primary > input:checked:disabled + span {
background-color: rgb(109, 163, 221);
border-color: rgb(109, 163, 221);
box-shadow: rgb(109, 163, 221) 0px 0px 0px 8px inset;
transition: border 0.4s ease 0s, box-shadow 0.4s ease 0s, background-color 1.2s ease 0s;
}
/* Switch Info */
.checkbox.checbox-switch.switch-info label > input:checked + span,
.checkbox-inline.checbox-switch.switch-info > input:checked + span {
background-color: rgb(23, 162, 184);
border-color: rgb(23, 162, 184);
box-shadow: rgb(23, 162, 184) 0px 0px 0px 8px inset;
transition: border 0.4s ease 0s, box-shadow 0.4s ease 0s, background-color 1.2s ease 0s;
}
.checkbox.checbox-switch.switch-info label > input:checked:disabled + span,
.checkbox-inline.checbox-switch.switch-info > input:checked:disabled + span {
background-color: rgb(102, 192, 206);
border-color: rgb(102, 192, 206);
box-shadow: rgb(102, 192, 206) 0px 0px 0px 8px inset;
transition: border 0.4s ease 0s, box-shadow 0.4s ease 0s, background-color 1.2s ease 0s;
}
/* Switch Warning */
.checkbox.checbox-switch.switch-warning label > input:checked + span,
.checkbox-inline.checbox-switch.switch-warning > input:checked + span {
background-color: rgb(255, 193, 7);
border-color: rgb(255, 193, 7);
box-shadow: rgb(255, 193, 7) 0px 0px 0px 8px inset;
transition: border 0.4s ease 0s, box-shadow 0.4s ease 0s, background-color 1.2s ease 0s;
}
.checkbox.checbox-switch.switch-warning label > input:checked:disabled + span,
.checkbox-inline.checbox-switch.switch-warning > input:checked:disabled + span {
background-color: rgb(226, 195, 102);
border-color: rgb(226, 195, 102);
box-shadow: rgb(226, 195, 102) 0px 0px 0px 8px inset;
transition: border 0.4s ease 0s, box-shadow 0.4s ease 0s, background-color 1.2s ease 0s;
}
......@@ -53,7 +53,77 @@ span.message-header.unread {
background-color: #FCF8E3;
}
/* You probably don't need to mess with rules below this line. */
/*** Dark mode ***/
/* default links, like the breadcrumbs */
.dark a {
color: #75b8f1;
}
/* background of the top bar */
.dark .navbar {
background-color: #333;
}
/* bbs name at top left */
.dark .navbar-brand {
color: #ccc;
}
.dark .navbar-brand:hover {
color: #fff;
}
/* hover for the top nav buttons */
.dark .navbar-default a:hover {
color: #8cc1ee !important;
color: #fff;
background-color: #444 !important;
}
/* the active top nav button when opened */
.dark .navbar-default .navbar-nav>.open>a,
.dark.navbar-default .navbar-nav>.open>a:focus,
.dark.navbar-default .navbar-nav>.open>a:hover {
background-color: #555;
color: #EEE;
}
/* dropdown menus */
.dark .dropdown-menu {
background-color: #333;
}
.dark .dropdown-menu li a {
color: #75b8f1;
}
/* background color of alternate rows in lists */
.dark .striped:nth-of-type(even), .dark .table-striped > tbody > tr:nth-child(odd) > td, .dark .table-striped > tbody > tr:nth-child(odd) > th {
background: #444;
}
/* this is the text and color for most items, including non-alternating rows */
.dark .list-group-item {
background-color: #555;
color: #EEE;
}
/* A link in a list when the mouse is hovering over it (mostly applies to the Forum) */
.dark a.list-group-item:hover, .dark a.list-group-item:active {
background-color: #888;
color: #222;
}
.dark li.list-group-item.mail:hover {
background-color: #888;
color: #FFF;
}
/* background color for the breadcrumb box */
.dark .breadcrumb {
background-color: #555;
}
/*** You probably don't need to mess with rules below this line. ***/
blockquote {
margin: .5em;
......@@ -180,3 +250,72 @@ animation: indicator-fade 3s ease 0s 1 alternate !important;
.breadcrumb li {
display: inline;
}
.dark {
background-color: #222 !important;
color: #eee;
}
.dark span.badge.ignored {
background-color: #aaa;
}
.dark .text-danger {
color: #ef1c18;
}
.dark .text-success {
color: #3eef41;
}
.dark a.btn, .dark .icon {
color: #000;
background-color: #ddd !important;
}
.dark .btn {
color: #000;
background-color: #ddd ;
}
.dark .btn-primary {
color: #FFF;
background-color: #337ab7;
}
.dark a.btn :hover, .dark .icon:hover {
color: #000;
background-color: #fff !important;
}
@media (max-width: 767px) {
.dark-switch {
padding: 10px 15px;
}
}
@media (min-width: 768px) {
.dark-switch {
padding: 0px;
}
}
.dark .modal-content {
background-color: #555 !important;
color: #FFF !important;
}
.darkswitchbox {
margin-block-start: 1em;
margin-block-end: 1em;
margin-inline-start: 0px;
margin-inline-end: 0px;
padding-inline-start: 40px;
}
.dark input,.dark select,.dark textarea {
color: #333;
background-color: #DDD;
}
......@@ -41,6 +41,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<style type="text/css">
.hidden { display:none; }
</style>
<script src="./js/jquery.min.js"></script>
<script type="text/javascript">
jQuery('html').addClass('hidden');
</script>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
......@@ -49,6 +56,9 @@
<link href="./bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link href="./css/offcanvas.css" rel="stylesheet">
<link href="./css/style.css" rel="stylesheet">
<?xjs if (!settings.darkmode_off) { ?>
<link href="./css/checkbox.css" rel="stylesheet">
<?xjs } ?>
<? if (file_exists(settings.web_root + 'css/custom.css')) { ?>
<link href="./css/custom.css" rel="stylesheet">
<? } ?>
......@@ -56,7 +66,6 @@
<body>
<script src="./js/jquery.min.js"></script>
<script src="./bootstrap/js/bootstrap.min.js"></script>
<script src="./js/common.js"></script>
......@@ -101,7 +110,6 @@
return false;
});
</script>
</body>
</html>
......@@ -91,6 +91,44 @@ function registerEventListener(scope, callback, params) {
};
}
document.addEventListener("DOMContentLoaded", function () {
// originally based on dark-mode-switch by Christian Oliff
var darkSwitch = document.getElementById("darkSwitch");
if (darkSwitch) {
initTheme();
darkSwitch.addEventListener("change", function (event) {
resetTheme();
});
function initTheme() {
var darkThemeSelected;
if (localStorage.getItem("darkSwitch") !== null) {
darkThemeSelected = localStorage.getItem("darkSwitch") === "dark";
} else {
darkThemeSelected = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
}
darkSwitch.checked = darkThemeSelected;
if (darkThemeSelected) {
jQuery("body").addClass("dark")
} else {
jQuery("body").removeClass("dark");
}
}
function resetTheme() {
if (darkSwitch.checked) {
jQuery("body").addClass("dark");
localStorage.setItem("darkSwitch", "dark");
} else {
jQuery("body").removeClass("dark");
localStorage.setItem("darkSwitch", "light");
}
}
}
jQuery('html').removeClass('hidden');
});
window.onload = function () {
$('#button-logout').click(logout);
......
<h4><?xjs write(locale.strings.sidebar_node_list.label_title); ?></h4>
<div id="sbbs-nodelist"></div>
<?xjs if (settings.nodelist_ibbs) { ?>
<div id="sbbsimsg-nodelist"></div>
<?xjs } ?>
<script type="text/javascript">
......@@ -10,30 +7,6 @@
const nch = '<?xjs write(settings.active_node_list ? locale.strings.sidebar_node_list.label_connection_column : locale.strings.sidebar_node_list.label_node_column) ?>';
const nll = <?xjs write(system.node_list.length); ?>;
var niu = 0;
var ns = 0;
function _sb_list_node(e) {
if (e.action === null || e.user === null) return;
$('#sbbs-nodelist-table').append(
'<tr>' +
'<th scope="row">' +
(anl ? e.connection : (typeof e.node == 'number' ? e.node + 1 : e.connection)) +
'</th>' +
'<td id="nodelist-' + e.node + '">' +
(e.user == '' ? e.status : ('<strong>' + e.user + '</strong> ' + e.action)) +
'</td>' +
'</tr>'
);
if (e.user != '' && <?xjs write(user.alias != settings.guest); ?>) {
$('#nodelist-' + e.node).attr('title', '<?xjs write(locale.strings.sidebar_node_list.label_send_telegram); ?>');
$('#nodelist-' + e.node).css('cursor', 'pointer');
$('#nodelist-' + e.node).click(function () {
sendTelegram(e.user);
});
}
if (typeof e.node == 'number' && e.user != '') niu++;
ns++;
}
function _sb_nodelist(evt) {
const data = JSON.parse(evt.data);
......@@ -49,31 +22,30 @@
'</table>'
);
niu = 0;
ns = 0;
if (!anl) {
const nodes = Array(nll);
data.forEach(function (e) {
if (typeof e.node == 'number') {
nodes[e.node] = e;
} else {
nodes.push(e); // Web user
}
});
for (var n = 0; n < nodes.length; n++) {
if (!nodes[n]) {
_sb_list_node({ node: n, user: '', status :'Waiting for call' });
} else {
_sb_list_node(nodes[n], n);
}
}
$('#sbbs-nodelist').parent().removeClass('hidden');
} else {
data.forEach(_sb_list_node);
var ns = data.reduce((a, c) => {
if (anl && (c.action === null || c.user === null)) return a;
$('#sbbs-nodelist-table').append(
'<tr>' +
'<th scope="row">' +
(anl ? c.connection : (typeof c.node == 'number' ? c.node : c.connection)) +
'</th>' +
`<td id="nodelist-${c.node}">` +
(c.user ? `<strong>${c.user}</strong> ${c.action}` : c.status) +
'</td>' +
'</tr>'
);
if (c.user && <?xjs write(user.alias != settings.guest); ?>) {
$(`#nodelist-${c.node}`).attr('title', '<?xjs write(locale.strings.sidebar_node_list.label_send_telegram); ?>');
$(`#nodelist-${c.node}`).css('cursor', 'pointer');
$(`#nodelist-${c.node}`).click(() => sendTelegram(c.user));
}
if (typeof c.node == 'number' && c.user != '') niu++;
return a + 1;
}, 0);
if (ns) {
$('#sbbs-nodelist').parent().removeClass('hidden');
$('#sbbs-nodelist').removeClass('hidden');
}
}
// Spans with these classes are used in the 'system stats' sidebar module.
// Update the nodes in use / available counters there.
$('#sidebar').find('.sb-nodes-in-use').text(niu);
......@@ -82,68 +54,4 @@
registerEventListener('nodelist', _sb_nodelist);
<?xjs if (settings.nodelist_ibbs) { ?>
function _send_ibbs_telegram(sys, host, user) {
async function send_ibbs_tg(evt) {
if (typeof evt !== 'undefined') evt.preventDefault();
await v4_post('./api/sbbsimsg.ssjs', {
call: 'send_telegram',
username: user,
host: host,
message: $('#telegram').val()
});
$('#popUpModal').modal('hide');
};
$('#popUpModalTitle').html('Send a telegram to ' + user + '@' + sys);
$('#popUpModalBody').html(
'<form id="ibbs-telegram-form">'
+ '<input type="text" class="form-control" placeholder="My message" name="telegram" id="telegram">'
+ '<input type="submit" value="submit" class="hidden">'
+ '</form>'
);
$('#popUpModalActionButton').show();
$('#ibbs-telegram-form').submit(send_ibbs_tg);
$('#popUpModalActionButton').click(send_ibbs_tg);
$('#popUpModal').modal('show');
}
registerEventListener('sbbsimsg', function (e) {
const data = JSON.parse(e.data);
var users = 0;
$('#sbbsimsg-nodelist').addClass('hidden');
$('#sbbsimsg-nodelist').html('<h4>Other Systems</h4>');
Object.keys(data).forEach(function (e, i) {
if (!data[e].users.length) return;
const id = 'sbbsimsg-nodelist-' + i;
$('#sbbsimsg-nodelist').append(
'<table id="' + id + '" class="table table-condensed table-responsive table-striped">'
+ '<tr><td><strong>' + e + '</strong></td></tr>'
+ '</table>'
);
data[e].users.forEach(function (ee, ii) {
const nid = id + '-' + ii;
$('#' + id).append(
'<tr>'
+ '<td id="' + nid + '">'
+ '<strong>' + ee.name + '</strong> ' + ee.action
+ '</td>'
+'</tr>'
);
if (<?xjs write(user.alias != settings.guest); ?>) {
$('#' + nid).click(function () {
_send_ibbs_telegram(e, data[e].host, ee.name);
});
$('#' + nid).attr('title', '<?xjs write(locale.strings.sidebar_node_list.label_send_telegram); ?>');
$('#' + nid).css('cursor', 'pointer');
}
});
users += data[e].users.length;
});
if (users) {
$('#sbbsimsg-nodelist').removeClass('hidden');
$('#sbbs-nodelist').parent().removeClass('hidden');
}
});
<?xjs } ?>
</script>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment