From 1e03fe47cdbbf76c8e44d338de8c2e870a89d6bd Mon Sep 17 00:00:00 2001 From: Bryan Ashby Date: Wed, 3 Jun 2020 22:10:02 -0600 Subject: [PATCH 01/22] ArakNet mention --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e2b6310e..4137ae0d 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ See [the issue tracker](https://github.com/NuSkooler/enigma-bbs/issues) for more * Use [the issue tracker](https://github.com/NuSkooler/enigma-bbs/issues) * **Discussion on a ENiGMA BBS!** (see Boards below) * IRC: **#enigma-bbs** on **chat.freenode.net** ([webchat](https://webchat.freenode.net/?channels=enigma-bbs)) -* FSX_ENG on [fsxNet](http://bbs.geek.nz/#fsxNet) available on many boards +* FSX_ENG on [fsxNet](http://bbs.geek.nz/#fsxNet) or ARK_ENIG on [ArakNet](https://www.araknet.xyz/) available on many fine boards * Email: bryan -at- l33t.codes * [Facebook ENiGMA½ group](https://www.facebook.com/groups/enigmabbs/) From b7251dad996691934fcaa622b7f379fc7f7768d7 Mon Sep 17 00:00:00 2001 From: wts42 Date: Sat, 13 Jun 2020 14:07:19 +0200 Subject: [PATCH 02/22] Fixed broken links in documentation. --- docs/configuration/archivers.md | 6 +++--- docs/configuration/colour-codes.md | 7 +++---- docs/filebase/tic-support.md | 2 +- docs/filebase/uploads.md | 3 +-- docs/filebase/web-access.md | 10 +++++----- docs/installation/manual.md | 20 ++++++++++---------- docs/installation/production.md | 6 +++--- docs/installation/rpi.md | 6 +++--- docs/installation/testing.md | 12 ++++++------ docs/installation/windows.md | 18 +++++++++--------- docs/messageareas/bso-import-export.md | 2 +- docs/servers/web-server.md | 2 +- 12 files changed, 46 insertions(+), 48 deletions(-) diff --git a/docs/configuration/archivers.md b/docs/configuration/archivers.md index 3f5d941e..c11b2747 100644 --- a/docs/configuration/archivers.md +++ b/docs/configuration/archivers.md @@ -24,12 +24,12 @@ The following archivers are pre-configured in ENiGMA½ as of this writing. Remem #### Lha * Formats: LHA files such as .lzh. * Key: `Lha` -* Homepage/package: `lhasa` on most UNIX-like environments. See also https://fragglet.github.io/lhasa/ and http://www2m.biglobe.ne.jp/~dolphin/lha/lha-unix.htm +* Homepage/package: `lhasa` on most UNIX-like environments. See also https://fragglet.github.io/lhasa/ and https://web.archive.org/web/20191023045303/http://www2m.biglobe.ne.jp/~dolphin/lha/lha-unix.htm #### Lzx * Formats: Amiga LZX * Key: `Lzx` -* Homepage/package: `unlzx` under most UNIX-like platforms ([Debian/Ubuntu](https://launchpad.net/~rzr/+archive/ubuntu/ppa/+build/2486127), [RedHat](https://fedora.pkgs.org/28/rpm-sphere/unlzx-1.1-4.1.x86_64.rpm.html), [Source](http://xavprods.free.fr/lzx/)) +* Homepage/package: `unlzx` under most UNIX-like platforms ([Debian/Ubuntu](https://launchpad.net/~rzr/+archive/ubuntu/ppa/+build/2486127), [RedHat](https://fedora.pkgs.org/32/rpm-sphere-x86_64/unlzx-1.1-4.1.x86_64.rpm.html), [Source](http://xavprods.free.fr/lzx/)) #### Arj * Formats: .arj @@ -85,4 +85,4 @@ zip: { handler: 7Zip /* points to a defined archiver */ desc: "ZIP Archive" } -``` \ No newline at end of file +``` diff --git a/docs/configuration/colour-codes.md b/docs/configuration/colour-codes.md index 9ad9abdd..57d04ee5 100644 --- a/docs/configuration/colour-codes.md +++ b/docs/configuration/colour-codes.md @@ -2,8 +2,8 @@ layout: page title: Colour Codes --- -ENiGMA½ supports Renegade-style pipe colour codes for formatting strings. You'll see them used in [`config.hjson`](config-hjson), -[`prompt.hjson`](prompt-hjson), [`menu.hjson`](menu-hjson), and can also be used in places like the oneliner, rumour mod, +ENiGMA½ supports Renegade-style pipe colour codes for formatting strings. You'll see them used in [`config.hjson`](config-hjson.md), +[`prompt.hjson`](prompt-hjson.md), [`menu.hjson`](menu-hjson.md), and can also be used in places like the oneliner, rumour mod, full screen editor etc. ## Usage @@ -18,8 +18,7 @@ For example: ## Colour Code Reference -:warning: Colour codes |24 to |31 are considered "blinking" or "iCE" colour codes. On terminals that support them they'll +:warning: Colour codes |24 to |31 are considered "blinking" or "iCE" colour codes. On terminals that support them they'll be shown as the correct colours - for terminals that don't, or are that are set to "blinking" mode - they'll blink! ![Regegade style colour codes](../assets/images/colour-codes.png "Colour Codes") - diff --git a/docs/filebase/tic-support.md b/docs/filebase/tic-support.md index 4c128bab..0970ef5e 100644 --- a/docs/filebase/tic-support.md +++ b/docs/filebase/tic-support.md @@ -6,7 +6,7 @@ title: TIC Support ENiGMA½ supports FidoNet-Style TIC file attachments by mapping TIC areas to local file areas. Under a given node defined in the `ftn_bso` config section in `config.hjson` (see -[BSO Import/Export](../messageareas/bso-import-export)), TIC configuration may be supplied: +[BSO Import/Export](../messageareas/bso-import-export.md)), TIC configuration may be supplied: ```hjson { diff --git a/docs/filebase/uploads.md b/docs/filebase/uploads.md index 795c0781..b6bceef2 100644 --- a/docs/filebase/uploads.md +++ b/docs/filebase/uploads.md @@ -21,5 +21,4 @@ uploads: { :information_source: Remember that uploads in a particular area are stored **using the first storage tag defined in that area.** -:information_source: Any ACS checks are allowed. See [ACS](/docs/acs.md) - +:information_source: Any ACS checks are allowed. See [ACS](../configuration/acs.md) diff --git a/docs/filebase/web-access.md b/docs/filebase/web-access.md index 714a801e..e0b9bd26 100644 --- a/docs/filebase/web-access.md +++ b/docs/filebase/web-access.md @@ -2,10 +2,10 @@ layout: page title: Web Access --- -Temporary web HTTP(S) URLs can be used to download files using the built in web server. Temporary links -expire after `fileBase::web::expireMinutes` (default 24 hours). The full URL given to users is built -using `contentServers::web::domain` and will default to HTTPS (https://) if enabled with a fallback to -HTTP. The end result is users are given a temporary web link that may look something like this: +Temporary web HTTP(S) URLs can be used to download files using the built in web server. Temporary links +expire after `fileBase::web::expireMinutes` (default 24 hours). The full URL given to users is built +using `contentServers::web::domain` and will default to HTTPS (https://) if enabled with a fallback to +HTTP. The end result is users are given a temporary web link that may look something like this: `https://xibalba.l33t.codes:44512/f/h7JK` -See [Web Server](web_server.md) for more information. \ No newline at end of file +See [Web Server](../servers/web-server.md) for more information. diff --git a/docs/installation/manual.md b/docs/installation/manual.md index 0a8a8f1d..0965a870 100644 --- a/docs/installation/manual.md +++ b/docs/installation/manual.md @@ -2,22 +2,22 @@ layout: page title: Manual Installation --- -For Linux environments it's recommended you run the [install script](install-script.md). If you like to +For Linux environments it's recommended you run the [install script](install-script.md). If you like to do things manually, read on... ## Prerequisites * [Node.js](https://nodejs.org/) version **v10.x LTS or higher** (Note that 8.x LTS *probably* works but is unsupported). - * :information_source: It is **highly** recommended to use [nvm](https://github.com/creationix/nvm) to manage your + * :information_source: It is **highly** recommended to use [nvm](https://github.com/creationix/nvm) to manage your Node.js installation if you're on a Linux/Unix environment. - + * [Python](https://www.python.org/downloads/) 2.7.x for compiling Node.js packages with native extensions. -* A compiler such as Clang or GCC for Linux/UNIX systems or a recent copy of Visual Studio -([Visual Studio Express](https://www.visualstudio.com/en-us/products/visual-studio-express-vs.aspx) editions +* A compiler such as Clang or GCC for Linux/UNIX systems or a recent copy of Visual Studio +([Visual Studio Express](https://www.visualstudio.com/en-us/products/visual-studio-express-vs.aspx) editions are OK) for Windows users. Note that you **should only need the Visual C++ component**. * [git](https://git-scm.com/downloads) to check out the ENiGMA source code. - + ## Node.js ### With NVM Node Version Manager (NVM) is an excellent way to install and manage Node.js versions on most UNIX-like environments. [Get the latest version here](https://github.com/creationix/nvm). The nvm install may look _something_ like this: @@ -38,7 +38,7 @@ If the above steps completed without errors, you should now have `nvm`, `node`, For Windows nvm-like systems exist ([nvm-windows](https://github.com/coreybutler/nvm-windows), ...) or [just download the installer](https://nodejs.org/en/download/). - + ## ENiGMA BBS ```bash git clone https://github.com/NuSkooler/enigma-bbs.git @@ -57,9 +57,9 @@ ENiGMA BBS makes use of a few packages for archive and legacy protocol support. |------------|-----------------------------------|--------------------------------------------|---------------------------------------------------|------------------------------------------------------------------| | arj | Unpacking arj archives | `arj` | n/a, binaries [here](http://arj.sourceforge.net/) | [ARJ](http://arj.sourceforge.net/) | | 7zip | Unpacking zip, rar, archives | `p7zip-full` | `p7zip-full` | [7-zip](http://www.7-zip.org/) | -| lha | Unpacking lha archives | `lhasa` | n/a, source [here](http://www2m.biglobe.ne.jp/~dolphin/lha/lha.htm) | Unknown | +| lha | Unpacking lha archives | `lhasa` | n/a, source [here](https://web.archive.org/web/20200301124852/http://www2m.biglobe.ne.jp/~dolphin/lha/lha.htm) | Unknown | | Rar | Unpacking rar archives | `unrar` | n/a, binaries [here](https://www.rarlab.com/download.htm) | Unknown | -| lrzsz | sz/rz: X/Y/Z protocol support | `lrzsz` | `lrzsz` | Unknown | +| lrzsz | sz/rz: X/Y/Z protocol support | `lrzsz` | `lrzsz` | Unknown | | sexyz | SexyZ protocol support | [sexyz](https://l33t.codes/outgoing/sexyz) | [sexyz](https://l33t.codes/outgoing/sexyz) | Available with [Synchronet](http://wiki.synchro.net/install:win) | | exiftool | [ExifTool](https://www.sno.phy.queensu.ca/~phil/exiftool/) | libimage-exiftool-perl | perl-Image-ExifTool | Unknown | xdms | Unpack/view Amiga DMS | [xdms](http://manpages.ubuntu.com/manpages/trusty/man1/xdms.1.html) | xdms | Unknown @@ -67,7 +67,7 @@ ENiGMA BBS makes use of a few packages for archive and legacy protocol support. ## Config Files You'll need a basic configuration to get started. The main system configuration is handled via `config/config.hjson`. This is an [HJSON](http://hjson.org/) file (compiliant JSON is also OK). See [Configuration](../configuration/) for more information. -Use `oputil.js` to generate your **initial** configuration: +Use `oputil.js` to generate your **initial** configuration: ```bash ./oputil.js config new diff --git a/docs/installation/production.md b/docs/installation/production.md index 53641d41..df4dfe7b 100644 --- a/docs/installation/production.md +++ b/docs/installation/production.md @@ -2,11 +2,11 @@ layout: page title: Production Installation --- -If you've become convinced you would like a "production" BBS running ENiGMA½ a more advanced installation -may be in order. +If you've become convinced you would like a "production" BBS running ENiGMA½ a more advanced installation +may be in order. [PM2](https://github.com/Unitech/pm2) is an excellent choice for managing your running ENiGMA½ instances if -you've installed via the [install script](install-script) or [manual installation](manual) method. +you've installed via the [install script](install-script.md) or [manual installation](manual.md) method. Additionally, it is suggested that you run as a specific more locked down user (e.g. 'enigma'). If you're running ENiGMA via Docker, then process management is already handled for you! diff --git a/docs/installation/rpi.md b/docs/installation/rpi.md index fb8ff235..17fd6b5d 100644 --- a/docs/installation/rpi.md +++ b/docs/installation/rpi.md @@ -3,7 +3,7 @@ layout: page title: Raspberry Pi --- -All Raspberry Pi models work great with ENiGMA½! Keep in mind compiling the dependencies with +All Raspberry Pi models work great with ENiGMA½! Keep in mind compiling the dependencies with `npm install` will take some time and *may* appear to hang. It's still working - just be patient and let it complete. @@ -19,9 +19,9 @@ to get it written to an SD card. 3. Expand the filesystem to use the entire SD card (option 7, option A1) 3. Update & upgrade all packages: `apt-get update && apt-get upgrade` - + 4. Install required packages: `sudo apt install lrzsz p7zip-full` -5. Follow the [installation instructions](/installation) to install ENiGMA½. +5. Follow the [installation instructions](../installation/) to install ENiGMA½. 6. Profit! diff --git a/docs/installation/testing.md b/docs/installation/testing.md index 576b28fd..b3d1cf50 100644 --- a/docs/installation/testing.md +++ b/docs/installation/testing.md @@ -1,16 +1,16 @@ --- layout: page -title: Testing Your Installation +title: Testing Your Installation --- -Once you've completed your chosen installation method, it's time to test! +Once you've completed your chosen installation method, it's time to test! -_Note that if you've used the [Docker](docker) installation method, you've already done this._ +_Note that if you've used the [Docker](docker.md) installation method, you've already done this._ ```bash ./main.js ``` -If everything went OK: +If everything went OK: ```bash ENiGMA½ Copyright (c) 2014-2020, Bryan Ashby @@ -33,7 +33,7 @@ To shut down the server, press Ctrl-C. ## Points of Interest * The default port for Telnet is 8888 and 8889 for SSH. - * Note that on *nix systems port such as telnet/23 are privileged (e.g. require root). See + * Note that on *nix systems port such as telnet/23 are privileged (e.g. require root). See [this SO article](http://stackoverflow.com/questions/16573668/best-practices-when-running-node-js-with-port-80-ubuntu-linode) for some tips on using these ports on your system if desired. * The first user you create when logging in will be automatically be added to the `sysops` group. @@ -44,6 +44,6 @@ If you don't have any telnet software, these are compatible with ENiGMA½: * [SyncTERM](http://syncterm.bbsdev.net/) * [EtherTerm](https://github.com/M-griffin/EtherTerm) * [NetRunner](http://mysticbbs.com/downloads.html) -* [MagiTerm](https://magickabbs.com/index.php/magiterm/) +* [MagiTerm](https://web.archive.org/web/20190330170733/https://magickabbs.com/index.php/2018/01/) * [VTX](https://github.com/codewar65/VTX_ClientServer) (Browser based) * [fTelnet](https://www.ftelnet.ca/) (Browser based) diff --git a/docs/installation/windows.md b/docs/installation/windows.md index a9fcf060..f2d9300e 100644 --- a/docs/installation/windows.md +++ b/docs/installation/windows.md @@ -22,7 +22,7 @@ ENiGMA½ will run on both 32bit and 64bit Windows. If you want to run 16bit door npm-windows-upgrade ``` - Note: Do not run `npm i -g npm`. Instead use `npm-windows-upgrade` to update npm going forward. + Note: Do not run `npm i -g npm`. Instead use `npm-windows-upgrade` to update npm going forward. Also if you run the NodeJS installer, it will replace the node version. 2. Install [windows-build-tools for npm](https://www.npmjs.com/package/windows-build-tools) @@ -30,7 +30,7 @@ ENiGMA½ will run on both 32bit and 64bit Windows. If you want to run 16bit door ```Powershell npm install --global --production windows-build-tools ``` - + 2. Install [7zip](https://www.7-zip.org/download.html). @@ -41,19 +41,19 @@ ENiGMA½ will run on both 32bit and 64bit Windows. If you want to run 16bit door 4. Click `New` and paste the path to 7zip 5. Close your console window and reopen. You can type `7z` to make sure it's working. -(Please see [Archivers](/docs/archivers.md) for additional archive utilities!) +(Please see [Archivers](../configuration/archivers.md) for additional archive utilities!) -3. Install [Git](https://git-scm.com/downloads) and optionally [TortoiseGit](https://tortoisegit.org/download/). +3. Install [Git](https://git-scm.com/downloads) and optionally [TortoiseGit](https://tortoisegit.org/download/). -4. Clone ENiGMA½ - browse to the directory you want and run +4. Clone ENiGMA½ - browse to the directory you want and run ```Powershell git clone "https://github.com/NuSkooler/enigma-bbs.git" ``` Optionally use the TortoiseGit by right clicking the directory and selecting `Git Clone`. - + 5. Install ENiGMA½. - 1. In the enigma directory run + 1. In the enigma directory run ```Powershell npm install ``` @@ -66,6 +66,6 @@ ENiGMA½ will run on both 32bit and 64bit Windows. If you want to run 16bit door ```Powershell node .\main.js ``` - -6. Look at [Production Installation](/installation/production) for maintaining ENiGMA½ when you are ready to go live. + +6. Look at [Production Installation](production.md) for maintaining ENiGMA½ when you are ready to go live. diff --git a/docs/messageareas/bso-import-export.md b/docs/messageareas/bso-import-export.md index 6fc6298e..a7c49c10 100644 --- a/docs/messageareas/bso-import-export.md +++ b/docs/messageareas/bso-import-export.md @@ -30,7 +30,7 @@ A node entry starts with a [FTN address](http://ftsc.org/docs/old/fsp-1028.001) | `packetType` | :-1: | `2`, `2.2`, or `2+`. Defaults to `2+` for modern mailer compatiability. | | `packetPassword` | :-1: | Optional password for the packet | | `encoding` | :-1: | Encoding to use for message bodies; Defaults to `utf-8`. | -| `archiveType` | :-1: | Specifies the archive type (by extension or MIME type) for ArcMail bundles. This should be `zip` (or `application/zip`) for most setups. Other valid examples include `arc`, `arj`, `lhz`, `pak`, `sqz`, or `zoo`. See [Archivers](docs/configuration/archivers.md) for more information. | +| `archiveType` | :-1: | Specifies the archive type (by extension or MIME type) for ArcMail bundles. This should be `zip` (or `application/zip`) for most setups. Other valid examples include `arc`, `arj`, `lhz`, `pak`, `sqz`, or `zoo`. See [Archivers](../configuration/archivers.md) for more information. | **Example**: ```hjson diff --git a/docs/servers/web-server.md b/docs/servers/web-server.md index 5675c4c6..fd9ac1b9 100644 --- a/docs/servers/web-server.md +++ b/docs/servers/web-server.md @@ -2,7 +2,7 @@ layout: page title: Web Server --- -ENiGMA½ comes with a built in *content server* for supporting both HTTP and HTTPS. Currently the [File Bases](file_base.md) registers routes for file downloads, password reset email links are handled via the server, and static files can also be served for your BBS. Other features will likely come in the future or you can easily write your own! +ENiGMA½ comes with a built in *content server* for supporting both HTTP and HTTPS. Currently the [File Bases](../modding/file-base-web-download-manager.md) registers routes for file downloads, password reset email links are handled via the server, and static files can also be served for your BBS. Other features will likely come in the future or you can easily write your own! # Configuration By default the web server is not enabled. To enable it, you will need to at a minimum configure two keys in the `contentServers.web` section of `config.hjson`: From 9aa783d262645037f7fdda7f0cfd97f363b1e89b Mon Sep 17 00:00:00 2001 From: wts42 Date: Sat, 13 Jun 2020 15:06:38 +0200 Subject: [PATCH 03/22] Minor fixes on the links. They should all point to the correct page now. --- docs/index.md | 10 +++++----- docs/modding/local-doors.md | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/index.md b/docs/index.md index b19f1b7d..edeab5a6 100644 --- a/docs/index.md +++ b/docs/index.md @@ -10,8 +10,8 @@ ENiGMA½ is a modern BBS software with a nostalgic flair! ## Features Available Now * Multi platform: Anywhere [Node.js](https://nodejs.org/) runs likely works (known to work under Linux, FreeBSD, OpenBSD, OS X and Windows) * Unlimited multi node support (for all those BBS "callers"!) - * **Highly** customizable via [HJSON](http://hjson.org/) based configuration, menus, and themes in addition to JavaScript based [mods](docs/mods.md) - * [MCI support](docs/mci.md) for lightbars, toggles, input areas, and so on plus many other other bells and whistles + * **Highly** customizable via [HJSON](http://hjson.org/) based configuration, menus, and themes in addition to JavaScript based [mods](modding/) + * [MCI support](art/mci.md) for lightbars, toggles, input areas, and so on plus many other other bells and whistles * Telnet, **SSH**, and both secure and non-secure [WebSocket](https://en.wikipedia.org/wiki/WebSocket) access built in! Additional servers are easy to implement * [CP437](http://www.ascii-codes.com/) and UTF-8 output * [SyncTerm](http://syncterm.bbsdev.net/) style font and baud emulation support. Display PC/DOS and Amiga style artwork as it's intended! In general, ANSI-BBS / [cterm.txt](http://cvs.synchro.net/cgi-bin/viewcvs.cgi/*checkout*/src/conio/cterm.txt?content-type=text%2Fplain&revision=HEAD) / [bansi.txt](http://www.bbsdocumentary.com/library/PROGRAMS/GRAPHICS/ANSI/bansi.txt) are followed for expected BBS behavior @@ -19,9 +19,9 @@ ENiGMA½ is a modern BBS software with a nostalgic flair! * Renegade style pipe color codes * [SQLite](http://sqlite.org/) storage of users, message areas, and so on * Strong [PBKDF2](https://en.wikipedia.org/wiki/PBKDF2) backed password encryption - * [Door support](docs/doors.md) including common dropfile formats for legacy DOS doors. Built in [BBSLink](http://bbslink.net/), [DoorParty](http://forums.throwbackbbs.com/), [Exodus](https://oddnetwork.org/exodus/) and [CombatNet](http://combatnet.us/) support! + * [Door support](modding/local-doors.md) including common dropfile formats for legacy DOS doors. Built in [BBSLink](http://bbslink.net/), [DoorParty](http://forums.throwbackbbs.com/), [Exodus](https://oddnetwork.org/exodus/) and [CombatNet](http://combatnet.us/) support! * [Bunyan](https://github.com/trentm/node-bunyan) logging - * [Message networks](docs/msg_networks.md) with FidoNet Type Network (FTN) + BinkleyTerm Style Outbound (BSO) message import/export - * [Gazelle](https://github.com/WhatCD/Gazelle) inspired File Bases including fast fully indexed full text search (FTS), #tags, and HTTP(S) temporary download URLs using a built in [web server](docs/web_server.md). Legacy X/Y/Z modem also supported! + * [Message networks](messageareas/message_networks.md) with FidoNet Type Network (FTN) + BinkleyTerm Style Outbound (BSO) message import/export + * [Gazelle](https://github.com/WhatCD/Gazelle) inspired File Bases including fast fully indexed full text search (FTS), #tags, and HTTP(S) temporary download URLs using a built in [web server](servers/web-server.md). Legacy X/Y/Z modem also supported! * Upload processor supporting [FILE_ID.DIZ](https://en.wikipedia.org/wiki/FILE_ID.DIZ) and [NFO](https://en.wikipedia.org/wiki/.nfo) extraction, year estimation, and more! * ANSI support in the Full Screen Editor (FSE), file descriptions, and so on diff --git a/docs/modding/local-doors.md b/docs/modding/local-doors.md index 2a4a1338..3e3e59ad 100644 --- a/docs/modding/local-doors.md +++ b/docs/modding/local-doors.md @@ -28,9 +28,9 @@ Dropfile types specified by `dropFileType`: | Value | Description | |-------|-------------| -| `DOOR` | [DOOR.SYS](http://goldfndr.home.mindspring.com/dropfile/doorsys.htm) +| `DOOR` | [DOOR.SYS](https://web.archive.org/web/20160325192739/http://goldfndr.home.mindspring.com/dropfile/doorsys.htm) | `DOOR32` | [DOOR32.SYS](https://raw.githubusercontent.com/NuSkooler/ansi-bbs/master/docs/dropfile_formats/door32_sys.txt) -| `DORINFO` | [DORINFOx.DEF](http://goldfndr.home.mindspring.com/dropfile/dorinfo.htm) +| `DORINFO` | [DORINFOx.DEF](https://web.archive.org/web/20160321190038/http://goldfndr.home.mindspring.com/dropfile/dorinfo.htm) #### Argument Variables The following variables may be used in `args` entries: From dd08cd68e74c69c078074a5472adf2c8dde9dd02 Mon Sep 17 00:00:00 2001 From: Bryan Ashby Date: Mon, 15 Jun 2020 19:28:32 -0600 Subject: [PATCH 04/22] Add PV[name,value] ACS check --- WHATSNEW.md | 1 + core/acs_parser.js | 8 ++++++++ docs/configuration/acs.md | 3 ++- misc/acs_parser.pegjs | 8 ++++++++ 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/WHATSNEW.md b/WHATSNEW.md index e587adf8..13462252 100644 --- a/WHATSNEW.md +++ b/WHATSNEW.md @@ -3,6 +3,7 @@ This document attempts to track **major** changes and additions in ENiGMA½. For ## 0.0.12-beta * The `master` branch has become mainline. What this means to users is `git pull` will always give you the latest and greatest. Make sure to read [Updating](/docs/admin/updating.md) and keep an eye on `WHATSNEW.md` (this file) and [UPGRADE](UPGRADE.md)! See also [ticket #276](https://github.com/NuSkooler/enigma-bbs/issues/276). +* New `PV` ACS check for arbitrary user properties. See [ACS](/docs/configuration/acs.md) for details. ## 0.0.11-beta * Upgraded from `alpha` to `beta` -- The software is far along and mature enough at this point! diff --git a/core/acs_parser.js b/core/acs_parser.js index f903d6f1..9d645a2f 100644 --- a/core/acs_parser.js +++ b/core/acs_parser.js @@ -1055,6 +1055,14 @@ function peg$parse(input, options) { } const points = user.getPropertyAsNumber(UserProps.AchievementTotalPoints) || 0; return !isNan(value) && points >= value; + }, + PV : function userPropValue() { + if (!user || !Array.isArray(value) || value.length !== 2) { + return false; + } + const [propName, propValue] = value; + const actualPropValue = user.getProperty(propName); + return actualPropValue === propValue; } }[acsCode](value); } catch (e) { diff --git a/docs/configuration/acs.md b/docs/configuration/acs.md index dd57ce22..decb3267 100644 --- a/docs/configuration/acs.md +++ b/docs/configuration/acs.md @@ -39,9 +39,10 @@ The following are ACS codes available as of this writing: | APachievementPoints | User has >= _achievementPoints_ achievement points | | AFauthFactor | User's current *Authentication Factor* is >= _authFactor_. Authentication factor 1 refers to username + password (or PubKey) while factor 2 refers to 2FA such as One-Time-Password authentication. | | ARauthFactorReq | Current user **requires** an Authentication Factor >= _authFactorReq_ | +| PV[_name,_value_] | Checks that the property by _name_ for the current user is exactly _value_. This ACS allows arbitrary user property values to be checked. For example, `PV[message_conf,local]` checks that the user is currently in the "local" message conference. ## ACS Strings -ACS strings are one or more ACS codes in addition to some basic language semantics. +ACS strings are one or more ACS codes in addition to some basic language semantics. The following logical operators are supported: * `!` NOT diff --git a/misc/acs_parser.pegjs b/misc/acs_parser.pegjs index 25e5853a..5ac55f30 100644 --- a/misc/acs_parser.pegjs +++ b/misc/acs_parser.pegjs @@ -211,6 +211,14 @@ } const points = user.getPropertyAsNumber(UserProps.AchievementTotalPoints) || 0; return !isNan(value) && points >= value; + }, + PV : function userPropValue() { + if (!user || !Array.isArray(value) || value.length !== 2) { + return false; + } + const [propName, propValue] = value; + const actualPropValue = user.getProperty(propName); + return actualPropValue === propValue; } }[acsCode](value); } catch (e) { From c59386cfda00bec6c30e8b71da5392420ce91ba2 Mon Sep 17 00:00:00 2001 From: wts42 Date: Tue, 16 Jun 2020 16:30:37 +0200 Subject: [PATCH 05/22] Changed link to MagiTerm by suggestion of NuSkooler. --- docs/installation/testing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation/testing.md b/docs/installation/testing.md index b3d1cf50..2e5dbea1 100644 --- a/docs/installation/testing.md +++ b/docs/installation/testing.md @@ -44,6 +44,6 @@ If you don't have any telnet software, these are compatible with ENiGMA½: * [SyncTERM](http://syncterm.bbsdev.net/) * [EtherTerm](https://github.com/M-griffin/EtherTerm) * [NetRunner](http://mysticbbs.com/downloads.html) -* [MagiTerm](https://web.archive.org/web/20190330170733/https://magickabbs.com/index.php/2018/01/) +* [MagiTerm](https://magickabbs.com/utils/) * [VTX](https://github.com/codewar65/VTX_ClientServer) (Browser based) * [fTelnet](https://www.ftelnet.ca/) (Browser based) From 5ab927d2f52a40185a9127ad5962da320108122f Mon Sep 17 00:00:00 2001 From: Bryan Ashby Date: Mon, 29 Jun 2020 22:26:35 -0600 Subject: [PATCH 06/22] Better getConfigPath() --- core/config_util.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/config_util.js b/core/config_util.js index 63e46f62..714055dd 100644 --- a/core/config_util.js +++ b/core/config_util.js @@ -9,9 +9,9 @@ const paths = require('path'); exports.getConfigPath = getConfigPath; function getConfigPath(filePath) { - // |filePath| is assumed to be in the config path if it's only a file name - if('.' === paths.dirname(filePath)) { - filePath = paths.join(Config().paths.config, filePath); + if (paths.isAbsolute(filePath)) { + return filePath; } - return filePath; + + return paths.join(Config().paths.config, filePath); } From 0b78b42f2fd7e883f94206e71e2e27138e279c23 Mon Sep 17 00:00:00 2001 From: Bryan Ashby Date: Mon, 29 Jun 2020 22:27:13 -0600 Subject: [PATCH 07/22] Fix DoesNotExist error --- core/menu_util.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/menu_util.js b/core/menu_util.js index 923d907d..0943fe22 100644 --- a/core/menu_util.js +++ b/core/menu_util.js @@ -37,7 +37,7 @@ function getMenuConfig(client, name, cb) { menuConfig.promptConfig = client.currentTheme.prompts[menuConfig.prompt]; return callback(null, menuConfig); } - return callback(Error.DoesNotExist(`No prompt entry for "${menuConfig.prompt}"`)); + return callback(Errors.DoesNotExist(`No prompt entry for "${menuConfig.prompt}"`)); } return callback(null, menuConfig); } From b36191392923384f473b4fd89be79cce676424af Mon Sep 17 00:00:00 2001 From: Bryan Ashby Date: Mon, 29 Jun 2020 22:27:31 -0600 Subject: [PATCH 08/22] Fix getConfigPath() --- core/oputil/oputil_common.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/oputil/oputil_common.js b/core/oputil/oputil_common.js index ae63fa2a..ff6e348b 100644 --- a/core/oputil/oputil_common.js +++ b/core/oputil/oputil_common.js @@ -64,7 +64,7 @@ function getDefaultConfigPath() { } function getConfigPath() { - const baseConfigPath = argv.config ? argv.config : config.getDefaultPath(); + const baseConfigPath = argv.config ? argv.config : config.Config.getDefaultPath(); return baseConfigPath + 'config.hjson'; } From 72564b7db6d2b704932b233354c4f46827e1e690 Mon Sep 17 00:00:00 2001 From: Bryan Ashby Date: Mon, 29 Jun 2020 22:59:27 -0600 Subject: [PATCH 09/22] Fix theme getter --- core/user_config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/user_config.js b/core/user_config.js index ca3b20ff..4ccd7017 100644 --- a/core/user_config.js +++ b/core/user_config.js @@ -171,7 +171,7 @@ exports.getModule = class UserConfigModule extends MenuModule { }, function prepareAvailableThemes(callback) { self.availThemeInfo = _.sortBy([...theme.getAvailableThemes()].map(entry => { - const theme = entry[1]; + const theme = entry[1].get(); return { themeId : theme.info.themeId, name : theme.info.name, From c849a1dc6d7265a5183c1bc33a51bfb2d2dbac48 Mon Sep 17 00:00:00 2001 From: Bryan Ashby Date: Sun, 5 Jul 2020 14:05:45 -0600 Subject: [PATCH 10/22] Update Node version in template --- .github/ISSUE_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index a8e6a08e..b6d1464a 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -3,7 +3,7 @@ For :bug: bug reports, please fill out the information below plus any additional **Short problem description** **Environment** -- [ ] I am using Node.js v10.x LTS or higher +- [ ] I am using Node.js v12.x LTS or higher - [ ] `npm install` or `yarn` reports success - Actual Node.js version (`node --version`): - Operating system (`uname -a` on *nix systems): From 35ef2db4463733c6b087a2e64d45a92af107f07b Mon Sep 17 00:00:00 2001 From: Bryan Ashby Date: Sun, 5 Jul 2020 14:06:10 -0600 Subject: [PATCH 11/22] Fix theme reload bug --- core/theme.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/theme.js b/core/theme.js index db9561f1..f763614d 100644 --- a/core/theme.js +++ b/core/theme.js @@ -121,7 +121,7 @@ exports.ThemeManager = class ThemeManager { onReload : err => { if (!err) { // this particular theme has changed - this._themeLoaded(themeId, err => { + this._themeLoaded(themeId, themeConfig, err => { if (!err) { Events.emit( Events.getSystemEvents().ThemeChanged, From 965e845834b04c8ad7b68ba4c482af27cf40147e Mon Sep 17 00:00:00 2001 From: Bryan Ashby Date: Sun, 5 Jul 2020 14:06:34 -0600 Subject: [PATCH 12/22] Major work on breaking up menus --- art/themes/luciano_blocktronics/theme.hjson | 70 +- core/oputil/oputil_config.js | 52 +- misc/config_template.in.hjson | 8 +- misc/menu_template.in.hjson | 4421 ------------------- misc/menu_templates/doors.in.hjson | 132 + misc/menu_templates/file_base.in.hjson | 918 ++++ misc/menu_templates/login.in.hjson | 607 +++ misc/menu_templates/main.in.hjson | 1024 +++++ misc/menu_templates/message_base.in.hjson | 816 ++++ misc/menu_templates/new_user.in.hjson | 362 ++ misc/menu_templates/private_mail.in.hjson | 197 + misc/prompt_template.in.hjson | 152 +- 12 files changed, 4147 insertions(+), 4612 deletions(-) delete mode 100644 misc/menu_template.in.hjson create mode 100644 misc/menu_templates/doors.in.hjson create mode 100644 misc/menu_templates/file_base.in.hjson create mode 100644 misc/menu_templates/login.in.hjson create mode 100644 misc/menu_templates/main.in.hjson create mode 100644 misc/menu_templates/message_base.in.hjson create mode 100644 misc/menu_templates/new_user.in.hjson create mode 100644 misc/menu_templates/private_mail.in.hjson diff --git a/art/themes/luciano_blocktronics/theme.hjson b/art/themes/luciano_blocktronics/theme.hjson index d812a9c3..4045a549 100644 --- a/art/themes/luciano_blocktronics/theme.hjson +++ b/art/themes/luciano_blocktronics/theme.hjson @@ -4,6 +4,11 @@ author: Luciano Ayres group: blocktronics enabled: true + + // + // Also check out Luciano's ANSIGARDEN: + // http://www.ansigarden.com/ + // } customization: { @@ -32,7 +37,7 @@ ET2: { width: 23 } ET5: { width: 23 } ET6: { width: 23 } - + ET7: { width: 23 } ET8: { width: 23 } ET9: { width: 23 } @@ -43,14 +48,14 @@ } } } - + newUserApplicationSsh: { mci: { ET1: { width: 23 } ET2: { width: 23 } ET5: { width: 23 } ET6: { width: 23 } - + ET7: { width: 23 } ET8: { width: 23 } ET9: { width: 23 } @@ -97,7 +102,7 @@ } TM2: { focusTextStyle: first lower - } + } } } 1: { @@ -227,7 +232,7 @@ } TM2: { focusTextStyle: first lower - } + } } } 1: { @@ -241,8 +246,8 @@ } } - messageAreaMessageList: { - config: { + messageBaseMessageList: { + config: { dateTimeFormat: ddd MMM Do allViewsInfoFormat10: "|00|15{msgNumSelected:>4.4} |08/ |15{msgNumTotal:<4.4}" } @@ -256,7 +261,7 @@ } } - messageAreaChangeCurrentConference: { + messageBaseChangeCurrentConference: { mci: { VM1: { width: 26 @@ -267,7 +272,7 @@ } } - messageAreaChangeCurrentArea: { + messageBaseChangeCurrentArea: { mci: { VM1: { width: 26 @@ -278,7 +283,7 @@ } } - messageAreaSetNewScanDate: { + messageBaseSetNewScanDate: { mci: { SM2: { width: 54 @@ -299,7 +304,7 @@ } } - mailMenuCreateMessage: { + privateMailMenuCreateMessage: { 0: { mci: { TL1: { width: 19, textOverflow: "..." } @@ -314,7 +319,7 @@ } } - mailMenuInbox: { + privateMailMenuInbox: { config: { dateTimeFormat: ddd MMM Do allViewsInfoFormat10: "|00|15{msgNumSelected:>4.4} |08/ |15{msgNumTotal:<4.4}" @@ -344,7 +349,7 @@ TM2: { focusTextStyle: upper items: [ "yes", "no" ] - } + } } } 1: { @@ -375,7 +380,7 @@ TL6: { width: 28 } TL7: { width: 28 } TL8: { width: 28 } - TL9: { width: 28 } + TL9: { width: 28 } } }, 1: { @@ -500,7 +505,7 @@ } } - messageAreaSearchMessageList: { + messageBaseSearchMessageList: { config: { allViewsInfoFormat10: "|00|15{msgNumSelected:>4.4} |08/ |15{msgNumTotal:<4.4}" // Fri Sep 25th @@ -516,7 +521,7 @@ } } - messageAreaMyMessagesList: { + messageBaseMyMessagesList: { config: { // Fri Sep 25th dateTimeFormat: ddd MMM Do @@ -531,22 +536,23 @@ } } + // The 'msg_list' module looks for this entry by default messageAreaViewPost: { 0: { mci: { - TL1: { + TL1: { width: 19 - textOverflow: ... + textOverflow: ... } TL2: { width: 19 textOverflow: ... } - TL3: { + TL3: { width: 19 textOverflow: ... } - TL5: { + TL5: { width: 19 textOverflow: ... } @@ -566,7 +572,7 @@ } } - messageAreaNewPost: { + messageBaseNewPost: { 0: { mci: { TL1: { width: 19, textOverflow: "..." } @@ -582,7 +588,7 @@ } } - messageAreaReplyPost: { + messageBaseReplyPost: { 0: { mci: { TL1: { width: 19, textOverflow: "..." } @@ -664,7 +670,7 @@ } newScanMessageList: { - config: { + config: { dateTimeFormat: ddd MMM Do allViewsInfoFormat10: "|00|15{msgNumSelected:>4.4} |08/ |15{msgNumTotal:<4.4}" } @@ -693,7 +699,7 @@ config: { hashTagsSep: "|08, |07" browseInfoFormat10: "|00|10{fileName:<.44} |08- |03{byteSize!sizeWithoutAbbr} |11{byteSize!sizeAbbr} |08- |03uploaded |11{uploadTimestamp}" - browseInfoFormat11: "|00|15{areaName}" + browseInfoFormat11: "|00|15{areaName}" browseInfoFormat12: "|00|07{hashTags}" browseInfoFormat13: "|00|07{estReleaseYear}" browseInfoFormat14: "|00|07{dlCount}" @@ -706,7 +712,7 @@ isQueuedIndicator: "|00|10YES" isNotQueuedIndicator: "|00|07no" - + userRatingTicked: "|00|15*" userRatingUnticked: "|00|07-" @@ -749,7 +755,7 @@ TL13: { width: 21 } TL14: { width: 21 } TL15: { width: 21 } - TL16: { width: 21 } + TL16: { width: 21 } TL17: { width: 73 } } @@ -793,7 +799,7 @@ config: { hashTagsSep: "|08, |07" browseInfoFormat10: "|00|10{fileName:<44} |08- |03{byteSize!sizeWithoutAbbr} |11{byteSize!sizeAbbr} |08- |03uploaded |11{uploadTimestamp}" - browseInfoFormat11: "|00|15{areaName}" + browseInfoFormat11: "|00|15{areaName}" browseInfoFormat12: "|00|07{hashTags}" browseInfoFormat13: "|00|07{estReleaseYear}" browseInfoFormat14: "|00|07{dlCount}" @@ -806,7 +812,7 @@ isQueuedIndicator: "|00|10YES" isNotQueuedIndicator: "|00|07no" - + userRatingTicked: "|00|15*" userRatingUnticked: "|00|07-" @@ -849,7 +855,7 @@ TL13: { width: 21 } TL14: { width: 21 } TL15: { width: 21 } - TL16: { width: 21 } + TL16: { width: 21 } TL17: { width: 73 } } @@ -901,7 +907,7 @@ } } } - } + } fileBaseSearch: { mci: { @@ -977,7 +983,7 @@ } } - fileAreaFilterEditor: { + fileBaseFilterEditor: { mci: { ET1: { width: 26 @@ -1086,7 +1092,7 @@ mci: { TL1: { width: 48 } TL2: { width: 48 } - TL3: { width: 48 } + TL3: { width: 48 } MT4: { height: 6 width: 68 diff --git a/core/oputil/oputil_config.js b/core/oputil/oputil_config.js index 4548a910..28c065d4 100644 --- a/core/oputil/oputil_config.js +++ b/core/oputil/oputil_config.js @@ -227,29 +227,47 @@ function buildNewConfig() { if(err) { return; } - const bn = sanatizeFilename(config.general.boardName) + const boardName = sanatizeFilename(config.general.boardName) .replace(/[^a-z0-9_-]/ig, '_') .replace(/_+/g, '_') .toLowerCase(); - const menuFile = `${bn}-menu.hjson`; - copyFileSyncSilent( - paths.join(__dirname, '../../misc/menu_template.in.hjson'), - paths.join(__dirname, '../../config/', menuFile), - fs.constants.COPYFILE_EXCL - ); + const menuFile = `menus/${boardName}-main.hjson`; - const promptFile = `${bn}-prompt.hjson`; - copyFileSyncSilent( - paths.join(__dirname, '../../misc/prompt_template.in.hjson'), - paths.join(__dirname, '../../config/', promptFile), - fs.constants.COPYFILE_EXCL - ); + const mainTemplate = hjson.rt.parse(fs.readFileSync(paths.join(__dirname, '../../misc/menu_templates/main.in.hjson'), 'utf8')); - config.general.menuFile = menuFile; - config.general.promptFile = promptFile; + const includeFiles = [ + 'message_base.in.hjson', + 'private_mail.in.hjson', + 'login.in.hjson', + 'new_user.in.hjson', + 'doors.in.hjson', + 'file_base.in.hjson', + ]; - if(writeConfig(config, configPath)) { - console.info('Configuration generated'); + includeFiles.forEach(incFile => { + const outName = `${boardName}-${incFile.replace('.in', '')}`; + copyFileSyncSilent( + paths.join(__dirname, '../../misc/menu_templates', incFile), + paths.join(__dirname, '../../config/menus', outName), + fs.constants.COPYFILE_EXCL + ); + }); + + mainTemplate.includes = includeFiles.map(incFile => { + return `${boardName}-${incFile.replace('.in', '')}`; + }); + + if (writeConfig( + mainTemplate, + paths.join(__dirname, '../../config/menus', `${boardName}-main.hjson`))) + { + config.general.menuFile = menuFile; + + if(writeConfig(config, configPath)) { + console.info('Configuration generated'); + } else { + console.error('Failed writing configuration'); + } } else { console.error('Failed writing configuration'); } diff --git a/misc/config_template.in.hjson b/misc/config_template.in.hjson index abcdc09a..1db5406d 100644 --- a/misc/config_template.in.hjson +++ b/misc/config_template.in.hjson @@ -369,7 +369,7 @@ storageTags: { // // Example storage tag: "super_l33t_warez": - // super_l33t_warez: "/path/to/super/l33t/warez" + // super_l33t_warez: /path/to/super/l33t/warez // } @@ -377,10 +377,10 @@ // // Example area with the areaTag of "an_example_area": // an_example_area: { - // name: "Example File Area" - // desc: "It's just an example, yo!" + // name: Example File Area + // desc: It's just an example, yo! // storageTags: [ - // "super_l33t_warez" + // super_l33t_warez // ] // } // diff --git a/misc/menu_template.in.hjson b/misc/menu_template.in.hjson deleted file mode 100644 index 57a3f761..00000000 --- a/misc/menu_template.in.hjson +++ /dev/null @@ -1,4421 +0,0 @@ -{ - /* - ./\/\.' ENiGMA½ Menu Configuration -/--/-------- - -- - - - _____________________ _____ ____________________ __________\_ / - \__ ____/\_ ____ \ /____/ / _____ __ \ / ______/ // /___jp! - // __|___// | \// |// | \// | | \// \ /___ /_____ - /____ _____| __________ ___|__| ____| \ / _____ \ - ---- \______\ -- |______\ ------ /______/ ---- |______\ - |______\ /__/ // ___/ - /__ _\ - <*> ENiGMA½ // HTTPS://GITHUB.COM/NUSKOOLER/ENIGMA-BBS <*> /__/ - - *-----------------------------------------------------------------------------* - - General Information - ------------------------------- - - - This configuration is in HJSON (http://hjson.org/) format. Strict to-spec - JSON is also perfectly valid. Use 'hjson' from npm to convert to/from JSON. - - See http://hjson.org/ for more information and syntax. - - Various editors and IDEs such as Sublime Text 3, Visual Studio Code, and so - on have syntax highlighting for the HJSON format which are highly recommended. - - ------------------------------- -- - - - Menu Configuration - ------------------------------- - - - ENiGMA½ makes no assumptions about specific menu types (main, doors, etc.), - but instead allows full customization of all menus throughout the system. - Some menus such as a main menu are considered "standard" while others are - backed by a specific module. SysOps can tweak various settings about these - modules (look & feel, keyboard interation, and so on) or even fully replace - the module with something else. - - This file starts out as an example setup. Look at the examples, change - settings, menu ordering/flow, add/remove menus, implement ACS control, - etc.! - - Remember you can *live edit* this file. That is, make a change and save - while you're logged into the system and it will take effect on the next - menu change or screen refresh. - - Please see RTFM ...er, uh... see the documentation for more information, and - don't be shy to ask for help: - - BBS : Xibalba @ xibalba.l33t.codes - FTN : BBS Discussion on fsxNet - IRC : #enigma-bbs / FreeNode - Email : bryan@l33t.codes - */ - menus: { - // - // Send telnet connections to matrix where users can login, apply, etc. - // - telnetConnected: { - art: CONNECT - next: matrix - config: { nextTimeout: 1500 } - } - - // - // SSH connections are pre-authenticated via the SSH server itself. - // Jump directly to either the 2FA/OTP auth or the login sequence - // depending on user ACS. - // - sshConnected: { - art: CONNECT - next: [ - { - acs: AR2 - next: loginTwoFactorAuthOTPLoop - } - { - next: fullLoginSequenceLoginArt - } - ] - config: { nextTimeout: 1500 } - } - - // - // Another SSH specialization: If the user logs in with a new user - // name (e.g. "new", "apply", ...) they will be directed to the - // application process. - // - sshConnectedNewUser: { - art: CONNECT - next: newUserApplicationPreSsh - config: { nextTimeout: 1500 } - } - - // Ye ol' standard matrix - matrix: { - art: matrix - form: { - 0: { - VM: { - mci: { - VM1: { - submit: true - focus: true - argName: navSelect - items: [ - { - text: login - data: login - } - { - text: apply - data: apply - } - - // - // To enable the forgot password option, you'll need to have - // the web server & email configured. Once that is in place, - // uncomment the section below. - // - // See docs for more information - // - /* - { - text: forgot pass - data: forgot - } - */ - { - text: log off - data: logoff - } - ] - } - } - submit: { - *: [ - { - value: { navSelect: "login" } - action: @menu:login - } - { - value: { navSelect: "apply" } - action: @menu:newUserApplicationPre - } - { - value: { navSelect: "forgot" } - action: @menu:forgotPassword - } - { - value: { navSelect: "logoff" } - action: @menu:logoff - } - ] - } - } - } - } - } - - login: { - art: USERLOG - next: [ - { - // - // Users with 2FA/OTP enabled *must* go through - // an additional OTP authentication step - // - acs: AR2 - next: loginTwoFactorAuthOTPLoop - } - { - // ...everyone else can carry on as per usual - next: fullLoginSequenceLoginArt - } - ] - config: { - tooNodeMenu: loginAttemptTooNode - inactive: loginAttemptAccountInactive - disabled: loginAttemptAccountDisabled - locked: loginAttemptAccountLocked - } - form: { - 0: { - mci: { - ET1: { - maxLength: @config:users.usernameMax - argName: username - focus: true - } - ET2: { - password: true - maxLength: @config:users.passwordMax - argName: password - submit: true - } - } - submit: { - *: [ - { - value: { password: null } - action: @systemMethod:login - } - ] - } - actionKeys: [ - { - keys: [ "escape" ] - action: @systemMethod:prevMenu - } - ] - } - } - } - - loginAttemptTooNode: { - art: TOONODE - config: { - cls: true - nextTimeout: 2000 - } - next: logoff - } - - loginAttemptAccountLocked: { - art: ACCOUNTLOCKED - config: { - cls: true - nextTimeout: 2000 - } - next: logoff - } - - loginAttemptAccountDisabled: { - art: ACCOUNTDISABLED - config: { - cls: true - nextTimeout: 2000 - } - next: logoff - } - - loginAttemptAccountInactive: { - art: ACCOUNTINACTIVE - config: { - cls: true - nextTimeout: 2000 - } - next: logoff - } - - // - // Empty menu to catch us in a 2FA/OTP auth loop - // until the user either authenticates successfully - // or the system boots them. - // - loginTwoFactorAuthOTPLoop: { - next: loginTwoFactorAuthOTP - } - - loginTwoFactorAuthOTP: { - art: 2FAOTP - next: fullLoginSequenceLoginArt - form: { - 0: { - mci: { - ET1: { - argName: token - focus: true - submit: true - } - } - submit: { - *: [ - { - value: { token: null } - action: @systemMethod:login2FA_OTP - } - ] - } - actionKeys: [ - { - // no turning back at this point... - keys: [ "escape" ] - action: @systemMethod:logoff - } - ] - } - } - } - - forgotPassword: { - desc: Forgot password - prompt: forgotPasswordPrompt - submit: [ - { - value: { username: null } - action: @systemMethod:sendForgotPasswordEmail - extraArgs: { next: "forgotPasswordSubmitted" } - } - ] - } - - forgotPasswordSubmitted: { - desc: Forgot password - art: FORGOTPWSENT - config: { - cls: true - pause: true - } - next: @systemMethod:logoff - } - - // :TODO: Prompt Yes/No for logoff confirm - fullLogoffSequence: { - desc: Logging Off - prompt: logoffConfirmation - submit: [ - { - value: { promptValue: 0 } - action: @menu:fullLogoffSequencePreAd - } - { - value: { promptValue: 1 } - action: @systemMethod:prevMenu - } - ] - } - - fullLogoffSequencePreAd: { - art: PRELOGAD - desc: Logging Off - next: fullLogoffSequenceRandomBoardAd - config: { - cls: true - nextTimeout: 1500 - } - } - - fullLogoffSequenceRandomBoardAd: { - art: OTHRBBS - desc: Logging Off - next: logoff - config: { - baudRate: 57600 - pause: true - cls: true - } - } - - logoff: { - art: LOGOFF - desc: Logging Off - next: @systemMethod:logoff - } - - // A quick preamble - defaults to warning about broken terminals - newUserApplicationPre: { - art: NEWUSER1 - next: newUserApplication - desc: Applying - config: { - pause: true - cls: true - menuFlags: [ "noHistory" ] - } - } - - newUserApplication: { - module: nua - art: NUA - next: [ - { - // Initial SysOp does not send feedback to themselves - acs: ID1 - next: fullLoginSequenceLoginArt - } - { - // ...everyone else does - next: newUserFeedbackToSysOpPreamble - } - ] - form: { - 0: { - mci: { - ET1: { - focus: true - argName: username - maxLength: @config:users.usernameMax - validate: @systemMethod:validateUserNameAvail - } - ET2: { - argName: realName - maxLength: @config:users.realNameMax - validate: @systemMethod:validateNonEmpty - } - MET3: { - argName: birthdate - maskPattern: "####/##/##" - validate: @systemMethod:validateBirthdate - } - ME4: { - argName: sex - maskPattern: A - textStyle: upper - validate: @systemMethod:validateNonEmpty - } - ET5: { - argName: location - maxLength: @config:users.locationMax - validate: @systemMethod:validateNonEmpty - } - ET6: { - argName: affils - maxLength: @config:users.affilsMax - } - ET7: { - argName: email - maxLength: @config:users.emailMax - validate: @systemMethod:validateEmailAvail - } - ET8: { - argName: web - maxLength: @config:users.webMax - } - ET9: { - argName: password - password: true - maxLength: @config:users.passwordMax - validate: @systemMethod:validatePasswordSpec - } - ET10: { - argName: passwordConfirm - password: true - maxLength: @config:users.passwordMax - validate: @method:validatePassConfirmMatch - } - TM12: { - argName: submission - items: [ "apply", "cancel" ] - submit: true - } - } - - submit: { - *: [ - { - value: { "submission" : 0 } - action: @method:submitApplication - extraArgs: { - inactive: userNeedsActivated - error: newUserCreateError - } - } - { - value: { "submission" : 1 } - action: @systemMethod:prevMenu - } - ] - } - - actionKeys: [ - { - keys: [ "escape" ] - action: @systemMethod:prevMenu - } - ] - } - } - } - - // A quick preamble - defaults to warning about broken terminals (SSH version) - newUserApplicationPreSsh: { - art: NEWUSER1 - next: newUserApplicationSsh - desc: Applying - config: { - pause: true - cls: true - menuFlags: [ "noHistory" ] - } - } - - // - // SSH specialization of NUA - // Canceling this form logs off vs falling back to matrix - // - newUserApplicationSsh: { - module: nua - art: NUA - fallback: logoff - next: newUserFeedbackToSysOpPreamble - form: { - 0: { - mci: { - ET1: { - focus: true - argName: username - maxLength: @config:users.usernameMax - validate: @systemMethod:validateUserNameAvail - } - ET2: { - argName: realName - maxLength: @config:users.realNameMax - validate: @systemMethod:validateNonEmpty - } - MET3: { - argName: birthdate - maskPattern: "####/##/##" - validate: @systemMethod:validateBirthdate - } - ME4: { - argName: sex - maskPattern: A - textStyle: upper - validate: @systemMethod:validateNonEmpty - } - ET5: { - argName: location - maxLength: @config:users.locationMax - validate: @systemMethod:validateNonEmpty - } - ET6: { - argName: affils - maxLength: @config:users.affilsMax - } - ET7: { - argName: email - maxLength: @config:users.emailMax - validate: @systemMethod:validateEmailAvail - } - ET8: { - argName: web - maxLength: @config:users.webMax - } - ET9: { - argName: password - password: true - maxLength: @config:users.passwordMax - validate: @systemMethod:validatePasswordSpec - } - ET10: { - argName: passwordConfirm - password: true - maxLength: @config:users.passwordMax - validate: @method:validatePassConfirmMatch - } - TM12: { - argName: submission - items: [ "apply", "cancel" ] - submit: true - } - } - - submit: { - *: [ - { - value: { "submission" : 0 } - action: @method:submitApplication - extraArgs: { - inactive: userNeedsActivated - error: newUserCreateError - } - } - { - value: { "submission" : 1 } - action: @systemMethod:logoff - } - ] - } - - actionKeys: [ - { - keys: [ "escape" ] - action: @systemMethod:logoff - } - ] - } - } - } - - newUserFeedbackToSysOpPreamble: { - art: LETTER - config: { pause: true } - next: newUserFeedbackToSysOp - } - - newUserFeedbackToSysOp: { - desc: Feedback to SysOp - module: msg_area_post_fse - next: [ - { - acs: AS2 - next: fullLoginSequenceLoginArt - } - { - next: newUserInactiveDone - } - ] - config: { - art: { - header: MSGEHDR - body: MSGBODY - footerEditor: MSGEFTR - footerEditorMenu: MSGEMFT - help: MSGEHLP - }, - editorMode: edit - editorType: email - messageAreaTag: private_mail - toUserId: 1 /* always to +op */ - } - form: { - 0: { - mci: { - TL1: { - argName: from - } - ET2: { - argName: to - focus: true - text: @sysStat:sysop_username - maxLength: 36 - // :TODO: readOnly: true - } - ET3: { - argName: subject - maxLength: 72 - submit: true - text: New user feedback - validate: @systemMethod:validateMessageSubject - } - } - submit: { - 3: [ - { - value: { subject: null } - action: @method:headerSubmit - } - ] - } - } - 1: { - mci: { - MT1: { - width: 79 - argName: message - mode: edit - } - } - - submit: { - *: [ { value: "message", action: "@method:editModeEscPressed" } ] - } - actionKeys: [ - { - keys: [ "escape" ] - viewId: 1 - } - ] - }, - 2: { - TLTL: { - mci: { - TL1: { - width: 5 - } - TL2: { - width: 4 - } - } - } - } - 3: { - HM: { - mci: { - HM1: { - // :TODO: clear - items: [ "save", "help" ] - } - } - submit: { - *: [ - { - value: { 1: 0 } - action: @method:editModeMenuSave - } - { - value: { 1: 1 } - action: @method:editModeMenuHelp - } - ] - } - actionKeys: [ - { - keys: [ "escape" ] - action: @method:editModeEscPressed - } - { - keys: [ "?" ] - action: @method:editModeMenuHelp - } - ] - } - } - } - } - - newUserInactiveDone: { - desc: Finished with NUA - art: DONE - config: { pause: true } - next: @menu:logoff - } - - fullLoginSequenceLoginArt: { - desc: Logging In - art: WELCOME - config: { pause: true } - next: fullLoginSequenceLastCallers - } - - fullLoginSequenceLastCallers: { - desc: Last Callers - module: last_callers - art: LASTCALL - config: { - pause: true - font: cp437 - } - next: fullLoginSequenceWhosOnline - } - fullLoginSequenceWhosOnline: { - desc: Who's Online - module: whos_online - art: WHOSON - config: { pause: true } - next: fullLoginSequenceOnelinerz - } - - fullLoginSequenceOnelinerz: { - desc: Viewing Onelinerz - module: onelinerz - next: [ - { - // calls >= 2 - acs: NC2 - next: fullLoginSequenceNewScanConfirm - } - { - // new users - skip new scan - next: fullLoginSequenceUserStats - } - ] - config: { - cls: true - art: { - view: ONELINER - add: ONEADD - } - } - form: { - 0: { - mci: { - VM1: { - focus: false - height: 10 - } - TM2: { - argName: addOrExit - items: [ "yeah!", "nah" ] - "hotKeys" : { "Y" : 0, "N" : 1, "Q" : 1 } - submit: true - focus: true - } - } - submit: { - *: [ - { - value: { addOrExit: 0 } - action: @method:viewAddScreen - } - { - value: { addOrExit: null } - action: @systemMethod:nextMenu - } - ] - } - actionKeys: [ - { - keys: [ "escape" ] - action: @systemMethod:nextMenu - } - ] - }, - 1: { - mci: { - ET1: { - focus: true - maxLength: 70 - argName: oneliner - } - TL2: { - width: 60 - } - TM3: { - argName: addOrCancel - items: [ "add", "cancel" ] - "hotKeys" : { "A" : 0, "C" : 1, "Q" : 1 } - submit: true - } - } - - submit: { - *: [ - { - value: { addOrCancel: 0 } - action: @method:addEntry - } - { - value: { addOrCancel: 1 } - action: @method:cancelAdd - } - ] - } - actionKeys: [ - { - keys: [ "escape" ] - action: @method:cancelAdd - } - ] - } - } - } - - fullLoginSequenceNewScanConfirm: { - desc: Logging In - prompt: loginGlobalNewScan - submit: [ - { - value: { promptValue: 0 } - action: @menu:fullLoginSequenceNewScan - } - { - value: { promptValue: 1 } - action: @menu:fullLoginSequenceUserStats - } - ] - } - - fullLoginSequenceNewScan: { - desc: Performing New Scan - module: new_scan - art: NEWSCAN - next: fullLoginSequenceSysStats - config: { - messageListMenu: newScanMessageList - } - } - - fullLoginSequenceSysStats: { - desc: System Stats - art: SYSSTAT - config: { pause: true } - next: fullLoginSequenceUserStats - } - fullLoginSequenceUserStats: { - desc: User Stats - art: STATUS - config: { pause: true } - next: mainMenu - } - - newScanMessageList: { - desc: New Messages - module: msg_list - art: NEWMSGS - config: { - menuViewPost: messageAreaViewPost - } - form: { - 0: { - mci: { - VM1: { - focus: true - submit: true - argName: message - } - TL6: { - // theme me! - } - } - submit: { - *: [ - { - value: { message: null } - action: @method:selectMessage - } - ] - } - actionKeys: [ - { - keys: [ "escape", "q", "shift + q" ] - action: @systemMethod:prevMenu - } - { - keys: [ "x", "shift + x" ] - action: @method:fullExit - } - { - keys: [ "m", "shift + m" ] - action: @method:markAllRead - } - ] - } - } - } - - newScanFileBaseList: { - module: file_area_list - desc: New Files - config: { - art: { - browse: FNEWBRWSE - details: FDETAIL - detailsGeneral: FDETGEN - detailsNfo: FDETNFO - detailsFileList: FDETLST - help: FBHELP - } - } - form: { - 0: { - mci: { - MT1: { - mode: preview - ansiView: true - } - - HM2: { - focus: true - submit: true - argName: navSelect - items: [ - "prev", "next", "details", "toggle queue", "rate", "help", "quit" - ] - focusItemIndex: 1 - } - } - - submit: { - *: [ - { - value: { navSelect: 0 } - action: @method:prevFile - } - { - value: { navSelect: 1 } - action: @method:nextFile - } - { - value: { navSelect: 2 } - action: @method:viewDetails - } - { - value: { navSelect: 3 } - action: @method:toggleQueue - } - { - value: { navSelect: 4 } - action: @menu:fileBaseGetRatingForSelectedEntry - } - { - value: { navSelect: 5 } - action: @method:displayHelp - } - { - value: { navSelect: 6 } - action: @systemMethod:prevMenu - } - ] - } - - actionKeys: [ - { - keys: [ "w", "shift + w" ] - action: @method:showWebDownloadLink - } - { - keys: [ "escape", "q", "shift + q" ] - action: @systemMethod:prevMenu - } - { - keys: [ "t", "shift + t" ] - action: @method:toggleQueue - } - { - keys: [ "v", "shift + v" ] - action: @method:viewDetails - } - { - keys: [ "r", "shift + r" ] - action: @menu:fileBaseGetRatingForSelectedEntry - } - { - keys: [ "?" ] - action: @method:displayHelp - } - ] - } - - 1: { - mci: { - HM1: { - focus: true - submit: true - argName: navSelect - items: [ - "general", "nfo/readme", "file listing" - ] - } - } - - actionKeys: [ - { - keys: [ "escape", "q", "shift + q" ] - action: @method:detailsQuit - } - ] - } - - 2: { - // details - general - mci: {} - } - - 3: { - // details - nfo/readme - mci: { - MT1: { - mode: preview - } - } - } - - 4: { - // details - file listing - mci: { - VM1: { - - } - } - } - } - } - - /////////////////////////////////////////////////////////////////////// - // Main Menu - /////////////////////////////////////////////////////////////////////// - mainMenu: { - art: MMENU - desc: Main Menu - prompt: menuCommand - config: { - font: cp437 - interrupt: realtime - } - submit: [ - { - value: { command: "MSG" } - action: @menu:nodeMessage - } - { - value: { command: "G" } - action: @menu:fullLogoffSequence - } - { - value: { command: "D" } - action: @menu:doorMenu - } - { - value: { command: "F" } - action: @menu:fileBase - } - { - value: { command: "U" } - action: @menu:mainMenuUserList - } - { - value: { command: "L" } - action: @menu:mainMenuLastCallers - } - { - value: { command: "W" } - action: @menu:mainMenuWhosOnline - } - { - value: { command: "Y" } - action: @menu:mainMenuUserStats - } - { - value: { command: "M" } - action: @menu:messageArea - } - { - value: { command: "E" } - action: @menu:mailMenu - } - { - value: { command: "C" } - action: @menu:mainMenuUserConfig - } - { - value: { command: "S" } - action: @menu:mainMenuSystemStats - } - { - value: { command: "!" } - action: @menu:mainMenuGlobalNewScan - } - { - value: { command: "K" } - action: @menu:mainMenuFeedbackToSysOp - } - { - value: { command: "O" } - action: @menu:mainMenuOnelinerz - } - { - value: { command: "R" } - action: @menu:mainMenuRumorz - } - { - value: { command: "BBS"} - action: @menu:bbsList - } - { - value: { command: "UA" } - action: @menu:mainMenuUserAchievementsEarned - } - { - value: { command: "MRC" } - action: @menu:mrc - } - { - value: { command: "2FA" } - action: [ - { - // - // For security reasons, only allow 2FA/OTP to be - // configured over already secure (SSL, wss://, ...) - // connections. Not doing so risks leaking secrets! - // - acs: SC - action: @menu:userTwoFactorAuthOTPConfig - } - { - action: @menu:userTwoFactorAuthOTPSecConnRequired - } - ] - } - { - value: 1 - action: @menu:mainMenu - } - ] - } - - mainMenuUserAchievementsEarned: { - desc: Achievements - module: user_achievements_earned - art: USERACHIEV - form: { - 0: { - mci: { - VM1: { - focus: true - } - } - actionKeys: [ - { - keys: [ "escape", "q", "shift + q" ] - action: @systemMethod:prevMenu - } - ] - } - } - } - - mrc: { - desc: MRC Chat - module: mrc - art: MRC - config: { - cls: true - - // max lines kept in scrollback buffer - maxScrollbackLines: 500 - } - form: { - 0: { - mci: { - MT1: { - mode: preview - autoScroll: true - } - ET2: { - argName: inputArea - submit: true - focus: true - } - } - actionKeys: [ - { - keys: [ "escape" ] - action: @systemMethod:prevMenu - } - { - keys: [ "down arrow", "up arrow", "page up", "page down" ] - action: @method:movementKeyPressed - } - ] - submit: { - *: [ - { - value: { inputArea: null } - action: @method:sendChatMessage - } - ] - } - } - } - } - - userTwoFactorAuthOTPConfig: { - desc: 2FA/OTP Config - module: user_2fa_otp_config - art: 2FACONFSCR - form: { - 0: { - mci: { - TM1: { - argName: enableToggle - focus: true - items: [ - // order is important here: - "disable" - "enable/reset" - ] - } - SM2: { - argName: otpType - items: [ - // order is important here: - "Time-Based - TOTP" - "HMAC-Based - HOTP" - "Google Authenticator" - ] - } - TM3: { - argName: submit - items: [ - "save" - "cancel" - ] - submit: true - } - } - - submit: { - *: [ - { - value: { submit: 0 } - action: @method:saveChanges - } - { - value: { submit: 1 } - action: @systemMethod:prevMenu - } - ] - } - - actionKeys: [ - { - keys: [ "escape" ] - action: @systemMethod:prevMenu - } - { - keys: [ "q", "shift + q" ] - action: @method:showQRCode - } - { - keys: [ "s", "shift + s" ] - action: @method:showSecret - } - { - keys: [ "b", "shift + b" ] - action: @method:showBackupCodes - } - { - keys: [ "n", "shift + n" ] - action: @method:generateNewBackupCodes - } - ] - } - } - } - - userTwoFactorAuthOTPSecConnRequired: { - desc: Insecure Warning - art: 2FAOTPSECREQ - config: { - cls: true - pause: true - } - } - - userTwoFactorAuthOTPConfigShowDetails: { - desc: 2FA/OTP Details - module: show_art - config: { - pause: true - method: extraArgs - } - } - - nodeMessage: { - desc: Node Messaging - module: node_msg - art: NODEMSG - config: { - cls: true - art: { - header: NODEMSGHDR - footer: NODEMSGFTR - } - } - form: { - 0: { - mci: { - SM1: { - argName: node - } - ET2: { - argName: message - submit: true - } - } - actionKeys: [ - { - keys: [ "escape" ] - action: @systemMethod:prevMenu - } - ] - submit: { - *: [ - { - value: { message: null } - action: @method:sendMessage - } - ] - } - } - } - } - - mainMenuLastCallers: { - desc: Last Callers - module: last_callers - art: LASTCALL - config: { pause: true } - } - - mainMenuWhosOnline: { - desc: Who's Online - module: whos_online - art: WHOSON - config: { pause: true } - } - - mainMenuUserStats: { - desc: User Stats - art: STATUS - config: { pause: true } - } - - mainMenuSystemStats: { - desc: System Stats - art: SYSSTAT - config: { pause: true } - } - - mainMenuUserList: { - desc: User Listing - module: user_list - art: USERLST - form: { - 0: { - mci: { - VM1: { - focus: true - submit: true - } - } - actionKeys: [ - { - keys: [ "escape", "q", "shift + q" ] - action: @systemMethod:prevMenu - } - ] - } - } - } - - mainMenuUserConfig: { - module: user_config - art: CONFSCR - form: { - 0: { - mci: { - ET1: { - argName: realName - maxLength: @config:users.realNameMax - validate: @systemMethod:validateNonEmpty - focus: true - } - ME2: { - argName: birthdate - maskPattern: "####/##/##" - } - ME3: { - argName: sex - maskPattern: A - textStyle: upper - validate: @systemMethod:validateNonEmpty - } - ET4: { - argName: location - maxLength: @config:users.locationMax - validate: @systemMethod:validateNonEmpty - } - ET5: { - argName: affils - maxLength: @config:users.affilsMax - } - ET6: { - argName: email - maxLength: @config:users.emailMax - validate: @method:validateEmailAvail - } - ET7: { - argName: web - maxLength: @config:users.webMax - } - ME8: { - maskPattern: "##" - argName: termHeight - validate: @systemMethod:validateNonEmpty - } - SM9: { - argName: theme - } - ET10: { - argName: password - maxLength: @config:users.passwordMax - password: true - validate: @method:validatePassword - } - ET11: { - argName: passwordConfirm - maxLength: @config:users.passwordMax - password: true - validate: @method:validatePassConfirmMatch - } - TM25: { - argName: submission - items: [ "save", "cancel" ] - submit: true - } - } - - submit: { - *: [ - { - value: { submission: 0 } - action: @method:saveChanges - } - { - value: { submission: 1 } - action: @systemMethod:prevMenu - } - ] - } - - actionKeys: [ - { - keys: [ "escape" ] - action: @systemMethod:prevMenu - } - ] - } - } - } - - mainMenuGlobalNewScan: { - desc: Performing New Scan - module: new_scan - art: NEWSCAN - config: { - messageListMenu: newScanMessageList - } - } - - mainMenuFeedbackToSysOp: { - desc: Feedback to SysOp - module: msg_area_post_fse - config: { - art: { - header: MSGEHDR - body: MSGBODY - footerEditor: MSGEFTR - footerEditorMenu: MSGEMFT - help: MSGEHLP - }, - editorMode: edit - editorType: email - messageAreaTag: private_mail - toUserId: 1 /* always to +op */ - } - form: { - 0: { - mci: { - TL1: { - argName: from - } - ET2: { - argName: to - focus: true - text: @sysStat:sysop_username - maxLength: 36 - // :TODO: readOnly: true - } - ET3: { - argName: subject - maxLength: 72 - submit: true - validate: @systemMethod:validateMessageSubject - } - } - submit: { - 3: [ - { - value: { subject: null } - action: @method:headerSubmit - } - ] - } - actionKeys: [ - { - keys: [ "escape" ] - action: @systemMethod:prevMenu - } - ] - } - 1: { - mci: { - MT1: { - width: 79 - argName: message - mode: edit - } - } - - submit: { - *: [ { value: "message", action: "@method:editModeEscPressed" } ] - } - actionKeys: [ - { - keys: [ "escape" ] - viewId: 1 - } - ] - }, - 2: { - TLTL: { - mci: { - TL1: { - width: 5 - } - TL2: { - width: 4 - } - } - } - } - 3: { - HM: { - mci: { - HM1: { - // :TODO: clear - items: [ "save", "discard", "help" ] - } - } - submit: { - *: [ - { - value: { 1: 0 } - action: @method:editModeMenuSave - } - { - value: { 1: 1 } - action: @systemMethod:prevMenu - } - { - value: { 1: 2 } - action: @method:editModeMenuHelp - } - ] - } - actionKeys: [ - { - keys: [ "escape" ] - action: @method:editModeEscPressed - } - { - keys: [ "?" ] - action: @method:editModeMenuHelp - } - ] - } - } - } - } - - mainMenuOnelinerz: { - desc: Viewing Onelinerz - module: onelinerz - config: { - cls: true - art: { - view: ONELINER - add: ONEADD - } - } - form: { - 0: { - mci: { - VM1: { - focus: false - height: 10 - } - TM2: { - argName: addOrExit - items: [ "yeah!", "nah" ] - "hotKeys" : { "Y" : 0, "N" : 1, "Q" : 1 } - submit: true - focus: true - } - } - submit: { - *: [ - { - value: { addOrExit: 0 } - action: @method:viewAddScreen - } - { - value: { addOrExit: null } - action: @systemMethod:nextMenu - } - ] - } - actionKeys: [ - { - keys: [ "escape" ] - action: @systemMethod:nextMenu - } - ] - }, - 1: { - mci: { - ET1: { - focus: true - maxLength: 70 - argName: oneliner - } - TL2: { - width: 60 - } - TM3: { - argName: addOrCancel - items: [ "add", "cancel" ] - "hotKeys" : { "A" : 0, "C" : 1, "Q" : 1 } - submit: true - } - } - - submit: { - *: [ - { - value: { addOrCancel: 0 } - action: @method:addEntry - } - { - value: { addOrCancel: 1 } - action: @method:cancelAdd - } - ] - } - actionKeys: [ - { - keys: [ "escape" ] - action: @method:cancelAdd - } - ] - } - } - } - - mainMenuRumorz: { - desc: Rumorz - module: rumorz - config: { - cls: true - art: { - entries: RUMORS - add: RUMORADD - } - } - form: { - 0: { - mci: { - VM1: { - focus: false - height: 10 - } - TM2: { - argName: addOrExit - items: [ "yeah!", "nah" ] - "hotKeys" : { "Y" : 0, "N" : 1, "Q" : 1 } - submit: true - focus: true - } - } - submit: { - *: [ - { - value: { addOrExit: 0 } - action: @method:viewAddScreen - } - { - value: { addOrExit: null } - action: @systemMethod:nextMenu - } - ] - } - actionKeys: [ - { - keys: [ "escape" ] - action: @systemMethod:nextMenu - } - ] - }, - 1: { - mci: { - ET1: { - focus: true - maxLength: 70 - argName: rumor - } - TL2: { - width: 60 - } - TM3: { - argName: addOrCancel - items: [ "add", "cancel" ] - "hotKeys" : { "A" : 0, "C" : 1, "Q" : 1 } - submit: true - } - } - - submit: { - *: [ - { - value: { addOrCancel: 0 } - action: @method:addEntry - } - { - value: { addOrCancel: 1 } - action: @method:cancelAdd - } - ] - } - actionKeys: [ - { - keys: [ "escape" ] - action: @method:cancelAdd - } - ] - } - } - } - - bbsList: { - desc: Viewing BBS List - module: bbs_list - config: { - cls: true - art: { - entries: BBSLIST - add: BBSADD - } - } - - form: { - 0: { - mci: { - VM1: { maxLength: 32 } - TL2: { maxLength: 32 } - TL3: { maxLength: 32 } - TL4: { maxLength: 32 } - TL5: { maxLength: 32 } - TL6: { maxLength: 32 } - TL7: { maxLength: 32 } - TL8: { maxLength: 32 } - TL9: { maxLength: 32 } - } - actionKeys: [ - { - keys: [ "a" ] - action: @method:addBBS - } - { - // :TODO: add delete key - keys: [ "d" ] - action: @method:deleteBBS - } - { - keys: [ "q", "escape" ] - action: @systemMethod:prevMenu - } - ] - } - 1: { - mci: { - ET1: { - argName: name - maxLength: 32 - validate: @systemMethod:validateNonEmpty - } - ET2: { - argName: sysop - maxLength: 32 - validate: @systemMethod:validateNonEmpty - } - ET3: { - argName: telnet - maxLength: 32 - validate: @systemMethod:validateNonEmpty - } - ET4: { - argName: www - maxLength: 32 - } - ET5: { - argName: location - maxLength: 32 - } - ET6: { - argName: software - maxLength: 32 - } - ET7: { - argName: notes - maxLength: 32 - } - TM17: { - argName: submission - items: [ "save", "cancel" ] - submit: true - } - } - - actionKeys: [ - { - keys: [ "escape" ] - action: @method:cancelSubmit - } - ] - - submit: { - *: [ - { - value: { "submission" : 0 } - action: @method:submitBBS - } - { - value: { "submission" : 1 } - action: @method:cancelSubmit - } - ] - } - } - } - } - - /////////////////////////////////////////////////////////////////////// - // Doors Menu - /////////////////////////////////////////////////////////////////////// - doorMenu: { - desc: Doors Menu - art: DOORMNU - prompt: menuCommand - config: { - interrupt: realtime - } - submit: [ - { - value: { command: "G" } - action: @menu:logoff - } - { - value: { command: "Q" } - action: @systemMethod:prevMenu - } - // - // The system supports many ways of launching doors including - // modules for DoorParty!, BBSLink, etc. - // - // Below are some examples. See the documentation for more info. - // - { - value: { command: "ABRACADABRA" } - action: @menu:doorAbracadabraExample - } - { - value: { command: "TWBBSLINK" } - action: @menu:doorTradeWars2002BBSLinkExample - } - { - value: { command: "DP" } - action: @menu:doorPartyExample - } - { - value: { command: "CN" } - action: @menu:doorCombatNetExample - } - { - value: { command: "EXODUS" } - action: @menu:doorExodusCataclysm - } - ] - } - - // - // Local Door Example via abracadabra module - // - // This example assumes launch_door.sh (which is passed args) - // launches the door. - // - doorAbracadabraExample: { - desc: Abracadabra Example - module: abracadabra - config: { - name: Example Door - dropFileType: DORINFO - cmd: /home/enigma/DOS/scripts/launch_door.sh - args: [ - "{node}", - "{dropFile}", - "{srvPort}", - ], - nodeMax: 1 - tooManyArt: DOORMANY - io: socket - } - } - - // - // BBSLink Example (TradeWars 2000) - // - // Register @ https://bbslink.net/ - // - doorTradeWars2002BBSLinkExample: { - desc: Playing TW 2002 (BBSLink) - module: bbs_link - config: { - sysCode: XXXXXXXX - authCode: XXXXXXXX - schemeCode: XXXXXXXX - door: tw - } - } - - // - // DoorParty! Example - // - // Register @ http://throwbackbbs.com/ - // - doorPartyExample: { - desc: Using DoorParty! - module: door_party - config: { - username: XXXXXXXX - password: XXXXXXXX - bbsTag: XX - } - } - - // - // CombatNet Example - // - // Register @ http://combatnet.us/ - // - doorCombatNetExample: { - desc: Using CombatNet - module: combatnet - config: { - bbsTag: CBNxxx - password: XXXXXXXXX - } - } - - // - // Exodus Example (cataclysm) - // Register @ https://oddnetwork.org/exodus/ - // - doorExodusCataclysm: { - desc: Cataclysm - module: exodus - config: { - rejectUnauthorized: false - board: XXX - key: XXXXXXXX - door: cataclysm - } - } - - /////////////////////////////////////////////////////////////////////// - // Message Area Menu - /////////////////////////////////////////////////////////////////////// - messageArea: { - art: MSGMNU - desc: Message Area - prompt: messageMenuCommand - config: { - interrupt: realtime - } - submit: [ - { - value: { command: "P" } - action: @menu:messageAreaNewPost - } - { - value: { command: "J" } - action: @menu:messageAreaChangeCurrentConference - } - { - value: { command: "C" } - action: @menu:messageAreaChangeCurrentArea - } - { - value: { command: "L" } - action: @menu:messageAreaMessageList - } - { - value: { command: "Q" } - action: @systemMethod:prevMenu - } - { - value: { command: "G" } - action: @menu:fullLogoffSequence - } - { - value: { command: "<" } - action: @systemMethod:prevConf - } - { - value: { command: ">" } - action: @systemMethod:nextConf - } - { - value: { command: "[" } - action: @systemMethod:prevArea - } - { - value: { command: "]" } - action: @systemMethod:nextArea - } - { - value: { command: "D" } - action: @menu:messageAreaSetNewScanDate - } - { - value: { command: "S" } - action: @menu:messageSearch - } - { - value: { command: "M" } - action: @menu:myMessages - } - { - value: { command: "A" } - action: @menu:editAutoSignature - } - { - value: 1 - action: @menu:messageArea - } - ] - } - - editAutoSignature: { - desc: Auto Sig Editor - module: autosig_edit - art: autosig - form: { - 0: { - mci: { - MT1: { - argName: signature - tabSwitchesView: true - } - BT2: { - text: save - argName: save - submit: true - } - } - submit: { - *: [ - { - value: { save: null } - action: @method:saveChanges - } - ] - } - - actionKeys: [ - { - keys: [ "escape" ] - action: @systemMethod:prevMenu - } - ] - } - } - } - - messageSearch: { - desc: Message Search - module: message_base_search - art: MSEARCH - config: { - messageListMenu: messageAreaSearchMessageList - } - form: { - 0: { - mci: { - ET1: { - focus: true - argName: searchTerms - } - BT2: { - argName: search - text: search - submit: true - } - SM3: { - argName: confTag - } - SM4: { - argName: areaTag - } - ET5: { - argName: toUserName - maxLength: @config:users.usernameMax - } - ET6: { - argName: fromUserName - maxLength: @config:users.usernameMax - } - BT7: { - argName: advancedSearch - text: advanced search - submit: true - } - } - - submit: { - *: [ - { - value: { search: null } - action: @method:search - } - { - value: { advancedSearch: null } - action: @method:search - } - ] - } - - actionKeys: [ - { - keys: [ "escape" ] - action: @systemMethod:prevMenu - } - ] - } - } - } - - messageAreaSearchMessageList: { - desc: Message Search - module: msg_list - art: MSRCHLST - config: { - menuViewPost: messageAreaViewPost - } - form: { - 0: { - mci: { - VM1: { - focus: true - submit: true - argName: message - } - TL6: { - // theme me! - } - } - submit: { - *: [ - { - value: { message: null } - action: @method:selectMessage - } - ] - } - actionKeys: [ - { - keys: [ "escape", "q", "shift + q" ] - action: @systemMethod:prevMenu - } - ] - } - } - } - - myMessages: { - desc: Personal Messages - module: my_messages - config: { - messageListMenu: messageAreaMyMessagesList - } - } - - messageAreaMyMessagesList: { - desc: Personal Messages - module: msg_list - art: MYMSGLST - config: { - menuViewPost: messageAreaViewPost - } - form: { - 0: { - mci: { - VM1: { - focus: true - submit: true - argName: message - } - } - submit: { - *: [ - { - value: { message: null } - action: @method:selectMessage - } - ] - } - actionKeys: [ - { - keys: [ "escape", "q", "shift + q" ] - action: @systemMethod:prevMenu - } - ] - } - } - } - - messageSearchNoResults: { - desc: Message Search - art: MSRCNORES - config: { - pause: true - } - } - - messageAreaChangeCurrentConference: { - art: CCHANGE - module: msg_conf_list - form: { - 0: { - mci: { - VM1: { - focus: true - submit: true - argName: conf - } - } - submit: { - *: [ - { - value: { conf: null } - action: @method:changeConference - } - ] - } - actionKeys: [ - { - keys: [ "escape", "q", "shift + q" ] - action: @systemMethod:prevMenu - } - ] - } - } - } - - messageAreaSetNewScanDate: { - module: set_newscan_date - desc: Message Base - art: SETMNSDATE - config: { - target: message - scanDateFormat: YYYYMMDD - } - form: { - 0: { - mci: { - ME1: { - focus: true - submit: true - argName: scanDate - maskPattern: "####/##/##" - } - SM2: { - argName: targetSelection - submit: false - } - } - submit: { - *: [ - { - value: { scanDate: null } - action: @method:scanDateSubmit - } - ] - } - actionKeys: [ - { - keys: [ "escape", "q", "shift + q" ] - action: @systemMethod:prevMenu - } - ] - } - } - } - - changeMessageConfPreArt: { - module: show_art - config: { - method: messageConf - key: confTag - pause: true - cls: true - menuFlags: [ "popParent", "noHistory" ] - } - } - - messageAreaChangeCurrentArea: { - // :TODO: rename this art to ACHANGE - art: CHANGE - module: msg_area_list - form: { - 0: { - mci: { - VM1: { - focus: true - submit: true - argName: area - } - } - submit: { - *: [ - { - value: { area: null } - action: @method:changeArea - } - ] - } - actionKeys: [ - { - keys: [ "escape", "q", "shift + q" ] - action: @systemMethod:prevMenu - } - ] - } - } - } - - changeMessageAreaPreArt: { - module: show_art - config: { - method: messageArea - key: areaTag - pause: true - cls: true - menuFlags: [ "popParent", "noHistory" ] - } - } - - messageAreaMessageList: { - module: msg_list - art: MSGLIST - config: { - menuViewPost: messageAreaViewPost - } - form: { - 0: { - mci: { - VM1: { - focus: true - submit: true - argName: message - } - } - submit: { - *: [ - { - value: { message: null } - action: @method:selectMessage - } - ] - } - actionKeys: [ - { - keys: [ "escape", "q", "shift + q" ] - action: @systemMethod:prevMenu - } - ] - } - } - } - - messageAreaViewPost: { - module: msg_area_view_fse - config: { - art: { - header: MSGVHDR - body: MSGBODY - footerView: MSGVFTR - help: MSGVHLP - }, - editorMode: view - editorType: area - } - form: { - 0: { - mci: { - // :TODO: ensure this block isn't even req. for theme to apply... - } - } - 1: { - mci: { - MT1: { - width: 79 - mode: preview - } - } - submit: { - *: [ - { - value: message - action: @method:editModeEscPressed - } - ] - } - actionKeys: [ - { - keys: [ "escape" ] - viewId: 1 - } - ] - } - 2: { - TLTL: { - mci: { - TL1: { width: 5 } - TL2: { width: 4 } - } - } - } - 4: { - mci: { - HM1: { - // :TODO: (#)Jump/(L)Index (msg list)/Last - items: [ "prev", "next", "reply", "quit", "help" ] - focusItemIndex: 1 - } - } - submit: { - *: [ - { - value: { 1: 0 } - action: @method:prevMessage - } - { - value: { 1: 1 } - action: @method:nextMessage - } - { - value: { 1: 2 } - action: @method:replyMessage - extraArgs: { - menu: messageAreaReplyPost - } - } - { - value: { 1: 3 } - action: @systemMethod:prevMenu - } - { - value: { 1: 4 } - action: @method:viewModeMenuHelp - } - ] - } - actionKeys: [ - { - keys: [ "p", "shift + p" ] - action: @method:prevMessage - } - { - keys: [ "n", "shift + n" ] - action: @method:nextMessage - } - { - keys: [ "r", "shift + r" ] - action: @method:replyMessage - extraArgs: { - menu: messageAreaReplyPost - } - } - { - keys: [ "escape", "q", "shift + q" ] - action: @systemMethod:prevMenu - } - { - keys: [ "?" ] - action: @method:viewModeMenuHelp - } - { - keys: [ "down arrow", "up arrow", "page up", "page down" ] - action: @method:movementKeyPressed - } - ] - } - } - } - - messageAreaReplyPost: { - module: msg_area_post_fse - config: { - art: { - header: MSGEHDR - body: MSGBODY - quote: MSGQUOT - footerEditor: MSGEFTR - footerEditorMenu: MSGEMFT - help: MSGEHLP - } - editorMode: edit - editorType: area - } - form: { - 0: { - mci: { - // :TODO: use appropriate system properties for max lengths - TL1: { - argName: from - } - ET2: { - argName: to - focus: true - validate: @systemMethod:validateNonEmpty - maxLength: 36 - } - ET3: { - argName: subject - maxLength: 72 - submit: true - validate: @systemMethod:validateNonEmpty - } - TL4: { - // :TODO: this is for RE: line (NYI) - //width: 27 - //textOverflow: ... - } - } - submit: { - 3: [ - { - value: { subject: null } - action: @method:headerSubmit - } - ] - } - actionKeys: [ - { - keys: [ "escape" ] - action: @systemMethod:prevMenu - } - ] - } - 1: { - mci: { - MT1: { - width: 79 - height: 14 - argName: message - mode: edit - } - } - submit: { - *: [ { "value": "message", "action": "@method:editModeEscPressed" } ] - } - actionKeys: [ - { - keys: [ "escape" ], - viewId: 1 - } - ] - } - - 3: { - mci: { - HM1: { - items: [ "save", "discard", "quote", "help" ] - } - } - - submit: { - *: [ - { - value: { 1: 0 } - action: @method:editModeMenuSave - } - { - value: { 1: 1 } - action: @systemMethod:prevMenu - } - { - value: { 1: 2 }, - action: @method:editModeMenuQuote - } - { - value: { 1: 3 } - action: @method:editModeMenuHelp - } - ] - } - - actionKeys: [ - { - keys: [ "escape" ] - action: @method:editModeEscPressed - } - { - keys: [ "s", "shift + s" ] - action: @method:editModeMenuSave - } - { - keys: [ "d", "shift + d" ] - action: @systemMethod:prevMenu - } - { - keys: [ "q", "shift + q" ] - action: @method:editModeMenuQuote - } - { - keys: [ "?" ] - action: @method:editModeMenuHelp - } - ] - } - - // Quote builder - 5: { - mci: { - MT1: { - width: 79 - height: 7 - } - VM3: { - width: 79 - height: 4 - argName: quote - } - } - - submit: { - *: [ - { - value: { quote: null } - action: @method:appendQuoteEntry - } - ] - } - - actionKeys: [ - { - keys: [ "escape" ] - action: @method:quoteBuilderEscPressed - } - ] - } - } - } - // :TODO: messageAreaSelect (change msg areas -> call @systemMethod -> fallback to menu - messageAreaNewPost: { - desc: Posting message, - module: msg_area_post_fse - config: { - art: { - header: MSGEHDR - body: MSGBODY - footerEditor: MSGEFTR - footerEditorMenu: MSGEMFT - help: MSGEHLP - } - editorMode: edit - editorType: area - } - form: { - 0: { - mci: { - TL1: { - argName: from - } - ET2: { - argName: to - focus: true - text: All - validate: @systemMethod:validateNonEmpty - maxLength: 36 - } - ET3: { - argName: subject - maxLength: 72 - submit: true - validate: @systemMethod:validateNonEmpty - // :TODO: Validate -> close/cancel if empty - } - } - submit: { - 3: [ - { - value: { subject: null } - action: @method:headerSubmit - } - ] - } - - actionKeys: [ - { - keys: [ "escape" ] - action: @systemMethod:prevMenu - } - ] - } - - 1: { - "mci" : { - MT1: { - width: 79 - argName: message - mode: edit - } - } - - submit: { - *: [ { "value": "message", "action": "@method:editModeEscPressed" } ] - } - actionKeys: [ - { - keys: [ "escape" ] - viewId: 1 - } - ] - } - 2: { - TLTL: { - mci: { - TL1: { width: 5 } - TL2: { width: 4 } - } - } - } - 3: { - HM: { - mci: { - HM1: { - // :TODO: clear - "items" : [ "save", "discard", "help" ] - } - } - submit: { - *: [ - { - value: { 1: 0 } - action: @method:editModeMenuSave - } - { - value: { 1: 1 } - action: @systemMethod:prevMenu - } - { - value: { 1: 2 } - action: @method:editModeMenuHelp - } - ] - } - actionKeys: [ - { - keys: [ "escape" ] - action: @method:editModeEscPressed - } - { - keys: [ "?" ] - action: @method:editModeMenuHelp - } - ] - // :TODO: something like the following for overriding keymap - // this should only override specified entries. others will default - /* - "keyMap" : { - "accept" : [ "return" ] - } - */ - } - } - } - } - - - // - // User to User mail aka Email Menu - // - mailMenu: { - art: MAILMNU - desc: Mail Menu - prompt: menuCommand - config: { - interrupt: realtime - } - submit: [ - { - value: { command: "C" } - action: @menu:mailMenuCreateMessage - } - { - value: { command: "I" } - action: @menu:mailMenuInbox - } - { - value: { command: "Q" } - action: @systemMethod:prevMenu - } - { - value: { command: "G" } - action: @menu:fullLogoffSequence - } - { - value: 1 - action: @menu:mailMenu - } - ] - } - - mailMenuCreateMessage: { - desc: Mailing Someone - module: msg_area_post_fse - config: { - art: { - header: MSGEHDR - body: MSGBODY - footerEditor: MSGEFTR - footerEditorMenu: MSGEMFT - help: MSGEHLP - }, - editorMode: edit - editorType: email - messageAreaTag: private_mail - } - form: { - 0: { - mci: { - TL1: { - argName: from - } - ET2: { - argName: to - focus: true - validate: @systemMethod:validateGeneralMailAddressedTo - maxLength: 36 - } - ET3: { - argName: subject - maxLength: 72 - submit: true - validate: @systemMethod:validateMessageSubject - } - } - submit: { - 3: [ - { - value: { subject: null } - action: @method:headerSubmit - } - ] - } - actionKeys: [ - { - keys: [ "escape" ] - action: @systemMethod:prevMenu - } - ] - } - 1: { - mci: { - MT1: { - width: 79 - argName: message - mode: edit - } - } - - submit: { - *: [ { value: "message", action: "@method:editModeEscPressed" } ] - } - actionKeys: [ - { - keys: [ "escape" ] - viewId: 1 - } - ] - }, - 2: { - TLTL: { - mci: { - TL1: { - width: 5 - } - TL2: { - width: 4 - } - } - } - } - 3: { - HM: { - mci: { - HM1: { - // :TODO: clear - items: [ "save", "discard", "help" ] - } - } - submit: { - *: [ - { - value: { 1: 0 } - action: @method:editModeMenuSave - } - { - value: { 1: 1 } - action: @systemMethod:prevMenu - } - { - value: { 1: 2 } - action: @method:editModeMenuHelp - } - ] - } - actionKeys: [ - { - keys: [ "escape" ] - action: @method:editModeEscPressed - } - { - keys: [ "?" ] - action: @method:editModeMenuHelp - } - ] - } - } - } - } - - mailMenuInbox: { - module: msg_list - art: PRVMSGLIST - config: { - menuViewPost: messageAreaViewPost - messageAreaTag: private_mail - } - form: { - 0: { // main list - mci: { - VM1: { - focus: true - submit: true - argName: message - } - } - submit: { - *: [ - { - value: { message: null } - action: @method:selectMessage - } - ] - } - actionKeys: [ - { - keys: [ "escape", "q", "shift + q" ] - action: @systemMethod:prevMenu - } - { - keys: [ "delete", "d", "shift + d" ] - action: @method:deleteSelected - } - ] - } - 1: { // delete prompt form - submit: { - *: [ - { - value: { promptValue: 0 } - action: @method:deleteMessageYes - } - { - value: { promptValue: 1 } - action: @method:deleteMessageNo - } - ] - } - } - } - } - - //////////////////////////////////////////////////////////////////////// - // File Base - //////////////////////////////////////////////////////////////////////// - - fileBase: { - desc: File Base - art: FMENU - prompt: fileMenuCommand - config: { - interrupt: realtime - } - submit: [ - { - value: { menuOption: "L" } - action: @menu:fileBaseListEntries - } - { - value: { menuOption: "B" } - action: @menu:fileBaseBrowseByAreaSelect - } - { - value: { menuOption: "F" } - action: @menu:fileAreaFilterEditor - } - { - value: { menuOption: "Q" } - action: @systemMethod:prevMenu - } - { - value: { menuOption: "G" } - action: @menu:fullLogoffSequence - } - { - value: { menuOption: "D" } - action: @menu:fileBaseDownloadManager - } - { - value: { menuOption: "W" } - action: @menu:fileBaseWebDownloadManager - } - { - value: { menuOption: "U" } - action: @menu:fileBaseUploadFiles - } - { - value: { menuOption: "S" } - action: @menu:fileBaseSearch - } - { - value: { menuOption: "P" } - action: @menu:fileBaseSetNewScanDate - } - { - value: { menuOption: "E" } - action: @menu:fileBaseExportListFilter - } - ] - } - - fileBaseExportListFilter: { - module: file_base_search - art: FBLISTEXPSEARCH - config: { - fileBaseListEntriesMenu: fileBaseExportList - } - form: { - 0: { - mci: { - ET1: { - focus: true - argName: searchTerms - } - BT2: { - argName: search - text: search - submit: true - } - ET3: { - maxLength: 64 - argName: tags - } - SM4: { - maxLength: 64 - argName: areaIndex - } - SM5: { - items: [ - "upload date", - "uploaded by", - "downloads", - "rating", - "estimated year", - "size", - "filename" - ] - argName: sortByIndex - } - SM6: { - items: [ - "decending", - "ascending" - ] - argName: orderByIndex - } - BT7: { - argName: advancedSearch - text: advanced search - submit: true - } - } - - submit: { - *: [ - { - value: { search: null } - action: @method:search - } - { - value: { advancedSearch: null } - action: @method:search - } - ] - } - - actionKeys: [ - { - keys: [ "escape" ] - action: @systemMethod:prevMenu - } - ] - } - } - } - - fileBaseExportList: { - module: file_base_user_list_export - art: FBLISTEXP - config: { - pause: true - templates: { - entry: file_list_entry.asc - } - } - form: { - 0: { - mci: { - TL1: { } - TL2: { } - } - } - } - } - - fileBaseExportListNoResults: { - desc: Browsing Files - art: FBNORES - config: { - pause: true - menuFlags: [ "noHistory", "popParent" ] - } - } - - fileBaseSetNewScanDate: { - module: set_newscan_date - desc: File Base - art: SETFNSDATE - config: { - target: file - scanDateFormat: YYYYMMDD - } - form: { - 0: { - mci: { - ME1: { - focus: true - submit: true - argName: scanDate - maskPattern: "####/##/##" - } - } - submit: { - *: [ - { - value: { scanDate: null } - action: @method:scanDateSubmit - } - ] - } - actionKeys: [ - { - keys: [ "escape", "q", "shift + q" ] - action: @systemMethod:prevMenu - } - ] - } - } - } - - fileBaseListEntries: { - module: file_area_list - desc: Browsing Files - config: { - art: { - browse: FBRWSE - details: FDETAIL - detailsGeneral: FDETGEN - detailsNfo: FDETNFO - detailsFileList: FDETLST - help: FBHELP - } - } - form: { - 0: { - mci: { - MT1: { - mode: preview - } - - HM2: { - focus: true - submit: true - argName: navSelect - items: [ - "prev", "next", "details", "toggle queue", "rate", "change filter", "help", "quit" - ] - focusItemIndex: 1 - } - } - - submit: { - *: [ - { - value: { navSelect: 0 } - action: @method:prevFile - } - { - value: { navSelect: 1 } - action: @method:nextFile - } - { - value: { navSelect: 2 } - action: @method:viewDetails - } - { - value: { navSelect: 3 } - action: @method:toggleQueue - } - { - value: { navSelect: 4 } - action: @menu:fileBaseGetRatingForSelectedEntry - } - { - value: { navSelect: 5 } - action: @menu:fileAreaFilterEditor - } - { - value: { navSelect: 6 } - action: @method:displayHelp - } - { - value: { navSelect: 7 } - action: @systemMethod:prevMenu - } - ] - } - - actionKeys: [ - { - keys: [ "w", "shift + w" ] - action: @method:showWebDownloadLink - } - { - keys: [ "escape", "q", "shift + q" ] - action: @systemMethod:prevMenu - } - { - keys: [ "t", "shift + t" ] - action: @method:toggleQueue - } - { - keys: [ "f", "shift + f" ] - action: @menu:fileAreaFilterEditor - } - { - keys: [ "v", "shift + v" ] - action: @method:viewDetails - } - { - keys: [ "r", "shift + r" ] - action: @menu:fileBaseGetRatingForSelectedEntry - } - { - keys: [ "?" ] - action: @method:displayHelp - } - ] - } - - 1: { - mci: { - HM1: { - focus: true - submit: true - argName: navSelect - items: [ - "general", "nfo/readme", "file listing" - ] - } - } - - actionKeys: [ - { - keys: [ "escape", "q", "shift + q" ] - action: @method:detailsQuit - } - ] - } - - 2: { - // details - general - mci: {} - } - - 3: { - // details - nfo/readme - mci: { - MT1: { - mode: preview - } - } - } - - 4: { - // details - file listing - mci: { - VM1: { - - } - } - } - } - } - - fileBaseBrowseByAreaSelect: { - desc: Browsing File Areas - module: file_base_area_select - art: FAREASEL - form: { - 0: { - mci: { - VM1: { - focus: true - argName: areaTag - } - } - - submit: { - *: [ - { - value: { areaTag: null } - action: @method:selectArea - } - ] - } - - actionKeys: [ - { - keys: [ "escape", "q", "shift + q" ] - action: @systemMethod:prevMenu - } - ] - } - } - } - - fileBaseGetRatingForSelectedEntry: { - desc: Rating a File - prompt: fileBaseRateEntryPrompt - config: { - cls: true - } - submit: [ - // :TODO: handle esc/q - { - // pass data back to caller - value: { rating: null } - action: @systemMethod:prevMenu - } - ] - } - - fileBaseListEntriesNoResults: { - desc: Browsing Files - art: FBNORES - config: { - pause: true - menuFlags: [ "noHistory", "popParent" ] - } - } - - fileBaseSearch: { - module: file_base_search - desc: Searching Files - art: FSEARCH - form: { - 0: { - mci: { - ET1: { - focus: true - argName: searchTerms - } - BT2: { - argName: search - text: search - submit: true - } - ET3: { - maxLength: 64 - argName: tags - } - SM4: { - maxLength: 64 - argName: areaIndex - } - SM5: { - items: [ - "upload date", - "uploaded by", - "downloads", - "rating", - "estimated year", - "size", - "filename", - ] - argName: sortByIndex - } - SM6: { - items: [ - "decending", - "ascending" - ] - argName: orderByIndex - } - BT7: { - argName: advancedSearch - text: advanced search - submit: true - } - } - - submit: { - *: [ - { - value: { search: null } - action: @method:search - } - { - value: { advancedSearch: null } - action: @method:search - } - ] - } - - actionKeys: [ - { - keys: [ "escape" ] - action: @systemMethod:prevMenu - } - ] - } - } - } - - fileAreaFilterEditor: { - desc: File Filter Editor - module: file_area_filter_edit - art: FFILEDT - form: { - 0: { - mci: { - ET1: { - argName: searchTerms - } - ET2: { - maxLength: 64 - argName: tags - } - SM3: { - maxLength: 64 - argName: areaIndex - } - SM4: { - items: [ - "upload date", - "uploaded by", - "downloads", - "rating", - "estimated year", - "size", - ] - argName: sortByIndex - } - SM5: { - items: [ - "decending", - "ascending" - ] - argName: orderByIndex - } - ET6: { - maxLength: 64 - argName: name - validate: @systemMethod:validateNonEmpty - } - HM7: { - focus: true - items: [ - "prev", "next", "make active", "save", "new", "delete" - ] - argName: navSelect - focusItemIndex: 1 - } - } - - submit: { - *: [ - { - value: { navSelect: 0 } - action: @method:prevFilter - } - { - value: { navSelect: 1 } - action: @method:nextFilter - } - { - value: { navSelect: 2 } - action: @method:makeFilterActive - } - { - value: { navSelect: 3 } - action: @method:saveFilter - } - { - value: { navSelect: 4 } - action: @method:newFilter - } - { - value: { navSelect: 5 } - action: @method:deleteFilter - } - ] - } - - actionKeys: [ - { - keys: [ "escape" ] - action: @systemMethod:prevMenu - } - ] - } - } - } - - fileBaseDownloadManager: { - desc: Download Manager - module: file_base_download_manager - config: { - art: { - queueManager: FDLMGR - /* - NYI - details: FDLDET - */ - } - emptyQueueMenu: fileBaseDownloadManagerEmptyQueue - } - form: { - 0: { - mci: { - VM1: { - argName: queueItem - } - HM2: { - focus: true - items: [ "download all", "quit" ] - argName: navSelect - } - } - - submit: { - *: [ - { - value: { navSelect: 0 } - action: @method:downloadAll - } - { - value: { navSelect: 1 } - action: @systemMethod:prevMenu - } - ] - } - - actionKeys: [ - { - keys: [ "a", "shift + a" ] - action: @method:downloadAll - } - { - keys: [ "delete", "r", "shift + r" ] - action: @method:removeItem - } - { - keys: [ "c", "shift + c" ] - action: @method:clearQueue - } - { - keys: [ "escape", "q", "shift + q" ] - action: @systemMethod:prevMenu - } - ] - } - } - } - - fileBaseWebDownloadManager: { - desc: Web D/L Manager - module: file_base_web_download_manager - config: { - art: { - queueManager: FWDLMGR - batchList: BATDLINF - } - emptyQueueMenu: fileBaseDownloadManagerEmptyQueue - } - form: { - 0: { - mci: { - VM1: { - argName: queueItem - } - HM2: { - focus: true - items: [ "get batch link", "quit", "help" ] - argName: navSelect - } - } - - submit: { - *: [ - { - value: { navSelect: 0 } - action: @method:getBatchLink - } - { - value: { navSelect: 1 } - action: @systemMethod:prevMenu - } - ] - } - - actionKeys: [ - { - keys: [ "b", "shift + b" ] - action: @method:getBatchLink - } - { - keys: [ "delete", "r", "shift + r" ] - action: @method:removeItem - } - { - keys: [ "c", "shift + c" ] - action: @method:clearQueue - } - { - keys: [ "escape", "q", "shift + q" ] - action: @systemMethod:prevMenu - } - ] - } - } - } - - fileBaseDownloadManagerEmptyQueue: { - desc: Empty Download Queue - art: FEMPTYQ - config: { - pause: true - menuFlags: [ "noHistory", "popParent" ] - } - } - - fileTransferProtocolSelection: { - desc: Protocol selection - module: file_transfer_protocol_select - art: FPROSEL - form: { - 0: { - mci: { - VM1: { - focus: true - argName: protocol - } - } - - submit: { - *: [ - { - value: { protocol: null } - action: @method:selectProtocol - } - ] - } - - actionKeys: [ - { - keys: [ "escape" ] - action: @systemMethod:prevMenu - } - ] - } - } - } - - fileBaseUploadFiles: { - desc: Uploading - module: upload - config: { - interrupt: never - art: { - options: ULOPTS - fileDetails: ULDETAIL - processing: ULCHECK - dupes: ULDUPES - } - } - - form: { - // options - 0: { - mci: { - SM1: { - argName: areaSelect - focus: true - } - TM2: { - argName: uploadType - items: [ "blind", "supply filename" ] - } - ET3: { - argName: fileName - maxLength: 255 - validate: @method:validateNonBlindFileName - } - HM4: { - argName: navSelect - items: [ "continue", "cancel" ] - submit: true - } - } - - submit: { - *: [ - { - value: { navSelect: 0 } - action: @method:optionsNavContinue - } - { - value: { navSelect: 1 } - action: @systemMethod:prevMenu - } - ] - } - - "actionKeys" : [ - { - "keys" : [ "escape" ], - action: @systemMethod:prevMenu - } - ] - } - - 1: { - mci: { } - } - - // file details entry - 2: { - mci: { - MT1: { - argName: shortDesc - tabSwitchesView: true - focus: true - } - - ET2: { - argName: tags - } - - ME3: { - argName: estYear - maskPattern: "####" - } - - BT4: { - argName: continue - text: continue - submit: true - } - } - - submit: { - *: [ - { - value: { continue: null } - action: @method:fileDetailsContinue - } - ] - } - } - - // dupes - 3: { - mci: { - VM1: { - /* - Use 'dupeInfoFormat' to custom format: - - areaDesc - areaName - areaTag - desc - descLong - fileId - fileName - fileSha256 - storageTag - uploadTimestamp - - */ - - mode: preview - } - } - } - } - } - - fileBaseNoUploadAreasAvail: { - desc: File Base - art: ULNOAREA - config: { - pause: true - menuFlags: [ "noHistory", "popParent" ] - } - } - - sendFilesToUser: { - desc: Downloading - module: file_transfer - config: { - // defaults - generally use extraArgs - protocol: zmodem8kSexyz - direction: send - } - } - - recvFilesFromUser: { - desc: Uploading - module: file_transfer - config: { - // defaults - generally use extraArgs - protocol: zmodem8kSexyz - direction: recv - } - } - - - //////////////////////////////////////////////////////////////////////// - // Required entries - //////////////////////////////////////////////////////////////////////// - idleLogoff: { - art: IDLELOG - next: @systemMethod:logoff - } - //////////////////////////////////////////////////////////////////////// - // Demo Section - // :TODO: This entire section needs updated!!! - //////////////////////////////////////////////////////////////////////// - "demoMain" : { - "art" : "demo_selection_vm.ans", - "form" : { - "0" : { - "VM" : { - "mci" : { - "VM1" : { - "items" : [ - "Single Line Text Editing Views", - "Spinner & Toggle Views", - "Mask Edit Views", - "Multi Line Text Editor", - "Vertical Menu Views", - "Horizontal Menu Views", - "Art Display", - "Full Screen Editor" - ], - "height" : 10, - "itemSpacing" : 1, - "justify" : "center", - "focusTextStyle" : "small i" - } - }, - "submit" : { - "*" : [ - { - "value" : { "1" : 0 }, - "action" : "@menu:demoEditTextView" - }, - { - "value" : { "1" : 1 }, - "action" : "@menu:demoSpinAndToggleView" - }, - { - "value" : { "1" : 2 }, - "action" : "@menu:demoMaskEditView" - }, - { - "value" : { "1" : 3 }, - "action" : "@menu:demoMultiLineEditTextView" - }, - { - "value" : { "1" : 4 }, - "action" : "@menu:demoVerticalMenuView" - }, - { - "value" : { "1" : 5 }, - "action" : "@menu:demoHorizontalMenuView" - }, - { - "value" : { "1" : 6 }, - "action" : "@menu:demoArtDisplay" - }, - { - "value" : { "1" : 7 }, - "action" : "@menu:demoFullScreenEditor" - } - ] - } - } - } - } - }, - "demoEditTextView" : { - "art" : "demo_edit_text_view1.ans", - "form" : { - "0" : { - "BTETETETET" : { - "mci" : { - "ET1" : { - "width" : 20, - "maxLength" : 20 - }, - "ET2" : { - "width" : 20, - "maxLength" : 40, - "textOverflow" : "..." - }, - "ET3" : { - "width" : 20, - "fillChar" : "-", - "styleSGR1" : "|00|36", - "maxLength" : 20 - }, - "ET4" : { - "width" : 20, - "maxLength" : 20, - "password" : true - }, - "BT5" : { - "width" : 8, - "text" : "< Back" - } - }, - "submit" : { - "*" : [ - { - "value" : 5, - "action" : "@menu:demoMain" - } - ] - }, - "actionKeys" : [ - { - "keys" : [ "escape" ], - "viewId" : 5 - } - ] - } - } - } - }, - "demoSpinAndToggleView" : { - "art" : "demo_spin_and_toggle.ans", - "form" : { - "0" : { - "BTSMSMTM" : { - "mci" : { - "SM1" : { - "items" : [ "Henry Morgan", "François l'Ollonais", "Roche Braziliano", "Black Bart", "Blackbeard" ] - }, - "SM2" : { - "items" : [ "Razor 1911", "DrinkOrDie", "TRSI" ] - }, - "TM3" : { - "items" : [ "Yarly", "Nowaii" ], - "styleSGR1" : "|00|30|01", - "hotKeys" : { "Y" : 0, "N" : 1 } - }, - "BT8" : { - "text" : "< Back" - } - }, - "submit" : { - "*" : [ - { - "value" : 8, - "action" : "@menu:demoMain" - } - ] - }, - "actionKeys" : [ - { - "keys" : [ "escape" ], - "viewId" : 8 - } - ] - } - } - } - }, - "demoMaskEditView" : { - "art" : "demo_mask_edit_text_view1.ans", - "form" : { - "0" : { - "BTMEME" : { - "mci" : { - "ME1" : { - "maskPattern" : "##/##/##", - "styleSGR1" : "|00|30|01", - //"styleSGR2" : "|00|45|01", - "styleSGR3" : "|00|30|35", - "fillChar" : "#" - }, - "BT5" : { - "text" : "< Back" - } - }, - "submit" : { - "*" : [ - { - "value" : 5, - "action" : "@menu:demoMain" - } - ] - }, - "actionKeys" : [ - { - "keys" : [ "escape" ], - "viewId" : 5 - } - ] - } - } - } - }, - "demoMultiLineEditTextView" : { - "art" : "demo_multi_line_edit_text_view1.ans", - "form" : { - "0" : { - "BTMT" : { - "mci" : { - "MT1" : { - "width" : 70, - "height" : 17, - //"text" : "@art:demo_multi_line_edit_text_view_text.txt", - // "text" : "@systemMethod:textFromFile" - text: "Hints:\n\t* Insert / CTRL-V toggles overtype mode\n\t* CTRL-Y deletes the current line\n\t* Try Page Up / Page Down\n\t* Home goes to the start of line text\n\t* End goes to the end of a line\n\n\nTab handling:\n-------------------------------------------------\n\tA\tB\tC\tD\tE\tF\nA\tB\tC\tD\tE\tF\tG\tH\n\tA\tB\tC\tD\tE\tF\nA\tB\tC\tD\tE\tF\tG\tH\nA0\tBB\t1\tCCC\t2\tDDD\t3EEEE\nW\t\tX\t\tY\t\tZ\n\nAn excerpt from A Clockwork Orange:\n\"What sloochatted then, of course, was that my cellmates woke up and started joining in, tolchocking a bit wild in the near-dark, and the shoom seemed to wake up the whole tier, so that you could slooshy a lot of creeching and banging about with tin mugs on the wall, as though all the plennies in all the cells thought a big break was about to commence, O my brothers.\n", - "focus" : true - }, - "BT5" : { - "text" : "< Back" - } - }, - "submit" : { - "*" : [ - { - "value" : 5, - "action" : "@menu:demoMain" - } - ] - }, - "actionKeys" : [ - { - "keys" : [ "escape" ], - "viewId" : 5 - } - ] - } - } - } - }, - "demoHorizontalMenuView" : { - "art" : "demo_horizontal_menu_view1.ans", - "form" : { - "0" : { - "BTHMHM" : { - "mci" : { - "HM1" : { - "items" : [ "One", "Two", "Three" ], - "hotKeys" : { "1" : 0, "2" : 1, "3" : 2 } - }, - "HM2" : { - "items" : [ "Uno", "Dos", "Tres" ], - "hotKeys" : { "U" : 0, "D" : 1, "T" : 2 } - }, - "BT5" : { - "text" : "< Back" - } - }, - "submit" : { - "*" : [ - { - "value" : 5, - "action" : "@menu:demoMain" - } - ] - }, - "actionKeys" : [ - { - "keys" : [ "escape" ], - "viewId" : 5 - } - ] - } - } - } - }, - "demoVerticalMenuView" : { - "art" : "demo_vertical_menu_view1.ans", - "form" : { - "0" : { - "BTVM" : { - "mci" : { - "VM1" : { - "items" : [ - "|33Oblivion/2", - "|33iNiQUiTY", - "|33ViSiON/X" - ], - "focusItems" : [ - "|33Oblivion|01/|00|332", - "|01|33i|00|33N|01i|00|33QU|01i|00|33TY", - "|33ViSiON/X" - ] - // - // :TODO: how to do the following: - // 1) Supply a view a string for a standard vs focused item - // "items" : [...], "focusItems" : [ ... ] ? - // "draw" : "@method:drawItemX", then items: [...] - }, - "BT5" : { - "text" : "< Back" - } - }, - "submit" : { - "*" : [ - { - "value" : 5, - "action" : "@menu:demoMain" - } - ] - }, - "actionKeys" : [ - { - "keys" : [ "escape" ], - "viewId" : 5 - } - ] - } - } - } - - }, - "demoArtDisplay" : { - "art" : "demo_selection_vm.ans", - "form" : { - "0" : { - "VM" : { - "mci" : { - "VM1" : { - "items" : [ - "Defaults - DOS ANSI", - "bw_mindgames.ans - DOS", - "test.ans - DOS", - "Defaults - Amiga", - "Pause at Term Height" - ], - // :TODO: justify not working?? - "focusTextStyle" : "small i" - } - }, - "submit" : { - "*" : [ - { - "value" : { "1" : 0 }, - "action" : "@menu:demoDefaultsDosAnsi" - }, - { - "value" : { "1" : 1 }, - "action" : "@menu:demoDefaultsDosAnsi_bw_mindgames" - }, - { - "value" : { "1" : 2 }, - "action" : "@menu:demoDefaultsDosAnsi_test" - } - ] - } - } - } - } - }, - "demoDefaultsDosAnsi" : { - "art" : "DM-ENIG2.ANS" - }, - "demoDefaultsDosAnsi_bw_mindgames" : { - "art" : "bw_mindgames.ans" - }, - "demoDefaultsDosAnsi_test" : { - "art" : "test.ans" - }, - "demoFullScreenEditor" : { - "module" : "fse", - "config" : { - "editorType" : "netMail", - "art" : { - "header" : "demo_fse_netmail_header.ans", - "body" : "demo_fse_netmail_body.ans", - "footerEditor" : "demo_fse_netmail_footer_edit.ans", - "footerEditorMenu" : "demo_fse_netmail_footer_edit_menu.ans", - "footerView" : "demo_fse_netmail_footer_view.ans", - "help" : "demo_fse_netmail_help.ans" - } - }, - "form" : { - "0" : { - "ETETET" : { - "mci" : { - "ET1" : { - // :TODO: from/to may be set by args - // :TODO: focus may change dep on view vs edit - "width" : 36, - "focus" : true, - "argName" : "to" - }, - "ET2" : { - "width" : 36, - "argName" : "from" - }, - "ET3" : { - "width" : 65, - "maxLength" : 72, - "submit" : [ "enter" ], - "argName" : "subject" - } - }, - "submit" : { - "3" : [ - { - "value" : { "subject" : null }, - "action" : "@method:headerSubmit" - } - ] - } - } - }, - "1" : { - "MT" : { - "mci" : { - "MT1" : { - "width" : 79, - "height" : 17, - "text" : "", // :TODO: should not be req. - "argName" : "message" - } - }, - "submit" : { - "*" : [ - { - "value" : "message", - "action" : "@method:editModeEscPressed" - } - ] - }, - "actionKeys" : [ - { - "keys" : [ "escape" ], - "viewId" : 1 - } - ] - } - }, - "2" : { - "TLTL" : { - "mci" : { - "TL1" : { - "width" : 5 - }, - "TL2" : { - "width" : 4 - } - } - } - }, - "3" : { - "HM" : { - "mci" : { - "HM1" : { - // :TODO: Continue, Save, Discard, Clear, Quote, Help - "items" : [ "Save", "Discard", "Quote", "Help" ] - } - }, - "submit" : { - "*" : [ - { - "value" : { "1" : 0 }, - "action" : "@method:editModeMenuSave" - }, - { - "value" : { "1" : 1 }, - "action" : "@menu:demoMain" - }, - { - "value" : { "1" : 2 }, - "action" : "@method:editModeMenuQuote" - }, - { - "value" : { "1" : 3 }, - "action" : "@method:editModeMenuHelp" - }, - { - "value" : 1, - "action" : "@method:editModeEscPressed" - } - ] - }, - "actionKeys" : [ // :TODO: Need better name - { - "keys" : [ "escape" ], - "action" : "@method:editModeEscPressed" - } - ] - } - } - } - } - } -} diff --git a/misc/menu_templates/doors.in.hjson b/misc/menu_templates/doors.in.hjson new file mode 100644 index 00000000..c26ee114 --- /dev/null +++ b/misc/menu_templates/doors.in.hjson @@ -0,0 +1,132 @@ +{ + menus: { + doorsMainMenu: { + desc: Doors Menu + art: DOORMNU + prompt: menuCommand + config: { + interrupt: realtime + } + submit: [ + { + value: { command: "G" } + action: @menu:fullLogoffSequence + } + { + value: { command: "Q" } + action: @systemMethod:prevMenu + } + // + // The system supports many ways of launching doors including + // modules for DoorParty!, BBSLink, etc. + // + // Below are some examples. See the documentation for more info. + // + { + value: { command: "ABRACADABRA" } + action: @menu:doorAbracadabraExample + } + { + value: { command: "TWBBSLINK" } + action: @menu:doorTradeWars2002BBSLinkExample + } + { + value: { command: "DP" } + action: @menu:doorPartyExample + } + { + value: { command: "CN" } + action: @menu:doorCombatNetExample + } + { + value: { command: "EXODUS" } + action: @menu:doorExodusCataclysm + } + ] + } + + // + // Local Door Example via abracadabra module + // + // This example assumes launch_door.sh (which is passed args) + // launches the door. + // + doorAbracadabraExample: { + desc: Abracadabra Example + module: abracadabra + config: { + name: Example Door + dropFileType: DORINFO + cmd: /home/enigma/DOS/scripts/launch_door.sh + args: [ + "{node}", + "{dropFile}", + "{srvPort}", + ], + nodeMax: 1 + tooManyArt: DOORMANY + io: socket + } + } + + // + // BBSLink Example (TradeWars 2000) + // + // Register @ https://bbslink.net/ + // + doorTradeWars2002BBSLinkExample: { + desc: Playing TW 2002 (BBSLink) + module: bbs_link + config: { + sysCode: XXXXXXXX + authCode: XXXXXXXX + schemeCode: XXXXXXXX + door: tw + } + } + + // + // DoorParty! Example + // + // Register @ http://throwbackbbs.com/ + // + doorPartyExample: { + desc: Using DoorParty! + module: door_party + config: { + username: XXXXXXXX + password: XXXXXXXX + bbsTag: XX + } + } + + // + // CombatNet Example + // + // Register @ http://combatnet.us/ + // + doorCombatNetExample: { + desc: Using CombatNet + module: combatnet + config: { + bbsTag: CBNxxx + password: XXXXXXXXX + } + } + + // + // Exodus Example (cataclysm) + // Register @ https://oddnetwork.org/exodus/ + // + doorExodusCataclysm: { + desc: Cataclysm + module: exodus + config: { + rejectUnauthorized: false + board: XXX + key: XXXXXXXX + door: cataclysm + } + } + } +} \ No newline at end of file diff --git a/misc/menu_templates/file_base.in.hjson b/misc/menu_templates/file_base.in.hjson new file mode 100644 index 00000000..572abf97 --- /dev/null +++ b/misc/menu_templates/file_base.in.hjson @@ -0,0 +1,918 @@ +{ + menus: { + fileBaseMainMenu: { + desc: File Base + art: FMENU + prompt: fileMenuCommand + config: { + interrupt: realtime + } + submit: [ + { + value: { menuOption: "L" } + action: @menu:fileBaseListEntries + } + { + value: { menuOption: "B" } + action: @menu:fileBaseBrowseByAreaSelect + } + { + value: { menuOption: "F" } + action: @menu:fileBaseFilterEditor + } + { + value: { menuOption: "Q" } + action: @systemMethod:prevMenu + } + { + value: { menuOption: "G" } + action: @menu:fullLogoffSequence + } + { + value: { menuOption: "D" } + action: @menu:fileBaseDownloadManager + } + { + value: { menuOption: "W" } + action: @menu:fileBaseWebDownloadManager + } + { + value: { menuOption: "U" } + action: @menu:fileBaseUploadFiles + } + { + value: { menuOption: "S" } + action: @menu:fileBaseSearch + } + { + value: { menuOption: "P" } + action: @menu:fileBaseSetNewScanDate + } + { + value: { menuOption: "E" } + action: @menu:fileBaseExportListFilter + } + ] + } + + fileBaseListEntries: { + module: file_area_list + desc: Browsing Files + config: { + art: { + browse: FBRWSE + details: FDETAIL + detailsGeneral: FDETGEN + detailsNfo: FDETNFO + detailsFileList: FDETLST + help: FBHELP + } + } + form: { + 0: { + mci: { + MT1: { + mode: preview + } + + HM2: { + focus: true + submit: true + argName: navSelect + items: [ + "prev", "next", "details", "toggle queue", "rate", "change filter", "help", "quit" + ] + focusItemIndex: 1 + } + } + + submit: { + *: [ + { + value: { navSelect: 0 } + action: @method:prevFile + } + { + value: { navSelect: 1 } + action: @method:nextFile + } + { + value: { navSelect: 2 } + action: @method:viewDetails + } + { + value: { navSelect: 3 } + action: @method:toggleQueue + } + { + value: { navSelect: 4 } + action: @menu:fileBaseGetRatingForSelectedEntry + } + { + value: { navSelect: 5 } + action: @menu:fileBaseFilterEditor + } + { + value: { navSelect: 6 } + action: @method:displayHelp + } + { + value: { navSelect: 7 } + action: @systemMethod:prevMenu + } + ] + } + + actionKeys: [ + { + keys: [ "w", "shift + w" ] + action: @method:showWebDownloadLink + } + { + keys: [ "escape", "q", "shift + q" ] + action: @systemMethod:prevMenu + } + { + keys: [ "t", "shift + t" ] + action: @method:toggleQueue + } + { + keys: [ "f", "shift + f" ] + action: @menu:fileBaseFilterEditor + } + { + keys: [ "v", "shift + v" ] + action: @method:viewDetails + } + { + keys: [ "r", "shift + r" ] + action: @menu:fileBaseGetRatingForSelectedEntry + } + { + keys: [ "?" ] + action: @method:displayHelp + } + ] + } + + 1: { + mci: { + HM1: { + focus: true + submit: true + argName: navSelect + items: [ + "general", "nfo/readme", "file listing" + ] + } + } + + actionKeys: [ + { + keys: [ "escape", "q", "shift + q" ] + action: @method:detailsQuit + } + ] + } + + 2: { + // details - general + mci: {} + } + + 3: { + // details - nfo/readme + mci: { + MT1: { + mode: preview + } + } + } + + 4: { + // details - file listing + mci: { + VM1: { + + } + } + } + } + } + + fileBaseBrowseByAreaSelect: { + desc: Browsing File Areas + module: file_base_area_select + art: FAREASEL + form: { + 0: { + mci: { + VM1: { + focus: true + argName: areaTag + } + } + + submit: { + *: [ + { + value: { areaTag: null } + action: @method:selectArea + } + ] + } + + actionKeys: @reference:common.quitToPrev + } + } + } + + fileBaseFilterEditor: { + desc: File Filter Editor + module: file_area_filter_edit + art: FFILEDT + form: { + 0: { + mci: { + ET1: { + argName: searchTerms + } + ET2: { + maxLength: 64 + argName: tags + } + SM3: { + maxLength: 64 + argName: areaIndex + } + SM4: { + items: [ + "upload date", + "uploaded by", + "downloads", + "rating", + "estimated year", + "size", + ] + argName: sortByIndex + } + SM5: { + items: [ + "decending", + "ascending" + ] + argName: orderByIndex + } + ET6: { + maxLength: 64 + argName: name + validate: @systemMethod:validateNonEmpty + } + HM7: { + focus: true + items: [ + "prev", "next", "make active", "save", "new", "delete" + ] + argName: navSelect + focusItemIndex: 1 + } + } + + submit: { + *: [ + { + value: { navSelect: 0 } + action: @method:prevFilter + } + { + value: { navSelect: 1 } + action: @method:nextFilter + } + { + value: { navSelect: 2 } + action: @method:makeFilterActive + } + { + value: { navSelect: 3 } + action: @method:saveFilter + } + { + value: { navSelect: 4 } + action: @method:newFilter + } + { + value: { navSelect: 5 } + action: @method:deleteFilter + } + ] + } + + actionKeys: [ + { + keys: [ "escape" ] + action: @systemMethod:prevMenu + } + ] + } + } + } + + fileBaseDownloadManager: { + desc: Download Manager + module: file_base_download_manager + config: { + art: { + queueManager: FDLMGR + /* + NYI + details: FDLDET + */ + } + emptyQueueMenu: fileBaseDownloadManagerEmptyQueue + } + form: { + 0: { + mci: { + VM1: { + argName: queueItem + } + HM2: { + focus: true + items: [ "download all", "quit" ] + argName: navSelect + } + } + + submit: { + *: [ + { + value: { navSelect: 0 } + action: @method:downloadAll + } + { + value: { navSelect: 1 } + action: @systemMethod:prevMenu + } + ] + } + + actionKeys: [ + { + keys: [ "a", "shift + a" ] + action: @method:downloadAll + } + { + keys: [ "delete", "r", "shift + r" ] + action: @method:removeItem + } + { + keys: [ "c", "shift + c" ] + action: @method:clearQueue + } + { + keys: [ "escape", "q", "shift + q" ] + action: @systemMethod:prevMenu + } + ] + } + } + } + + fileBaseDownloadManagerEmptyQueue: { + desc: Empty Download Queue + art: FEMPTYQ + config: { + pause: true + menuFlags: [ "noHistory", "popParent" ] + } + } + + fileBaseWebDownloadManager: { + desc: Web D/L Manager + module: file_base_web_download_manager + config: { + art: { + queueManager: FWDLMGR + batchList: BATDLINF + } + emptyQueueMenu: fileBaseDownloadManagerEmptyQueue + } + form: { + 0: { + mci: { + VM1: { + argName: queueItem + } + HM2: { + focus: true + items: [ "get batch link", "quit", "help" ] + argName: navSelect + } + } + + submit: { + *: [ + { + value: { navSelect: 0 } + action: @method:getBatchLink + } + { + value: { navSelect: 1 } + action: @systemMethod:prevMenu + } + ] + } + + actionKeys: [ + { + keys: [ "b", "shift + b" ] + action: @method:getBatchLink + } + { + keys: [ "delete", "r", "shift + r" ] + action: @method:removeItem + } + { + keys: [ "c", "shift + c" ] + action: @method:clearQueue + } + { + keys: [ "escape", "q", "shift + q" ] + action: @systemMethod:prevMenu + } + ] + } + } + } + + fileBaseUploadFiles: { + desc: Uploading + module: upload + config: { + interrupt: never + art: { + options: ULOPTS + fileDetails: ULDETAIL + processing: ULCHECK + dupes: ULDUPES + } + } + + form: { + // options + 0: { + mci: { + SM1: { + argName: areaSelect + focus: true + } + TM2: { + argName: uploadType + items: [ "blind", "supply filename" ] + } + ET3: { + argName: fileName + maxLength: 255 + validate: @method:validateNonBlindFileName + } + HM4: { + argName: navSelect + items: [ "continue", "cancel" ] + submit: true + } + } + + submit: { + *: [ + { + value: { navSelect: 0 } + action: @method:optionsNavContinue + } + { + value: { navSelect: 1 } + action: @systemMethod:prevMenu + } + ] + } + + "actionKeys" : [ + { + "keys" : [ "escape" ], + action: @systemMethod:prevMenu + } + ] + } + + 1: { + mci: { } + } + + // file details entry + 2: { + mci: { + MT1: { + argName: shortDesc + tabSwitchesView: true + focus: true + } + + ET2: { + argName: tags + } + + ME3: { + argName: estYear + maskPattern: "####" + } + + BT4: { + argName: continue + text: continue + submit: true + } + } + + submit: { + *: [ + { + value: { continue: null } + action: @method:fileDetailsContinue + } + ] + } + } + + // dupes + 3: { + mci: { + VM1: { + /* + Use 'dupeInfoFormat' to custom format: + + areaDesc + areaName + areaTag + desc + descLong + fileId + fileName + fileSha256 + storageTag + uploadTimestamp + + */ + + mode: preview + } + } + } + } + } + + fileBaseSearch: { + module: file_base_search + desc: Searching Files + art: FSEARCH + form: { + 0: { + mci: { + ET1: { + focus: true + argName: searchTerms + } + BT2: { + argName: search + text: search + submit: true + } + ET3: { + maxLength: 64 + argName: tags + } + SM4: { + maxLength: 64 + argName: areaIndex + } + SM5: { + items: [ + "upload date", + "uploaded by", + "downloads", + "rating", + "estimated year", + "size", + "filename", + ] + argName: sortByIndex + } + SM6: { + items: [ + "decending", + "ascending" + ] + argName: orderByIndex + } + BT7: { + argName: advancedSearch + text: advanced search + submit: true + } + } + + submit: { + *: [ + { + value: { search: null } + action: @method:search + } + { + value: { advancedSearch: null } + action: @method:search + } + ] + } + + actionKeys: [ + { + keys: [ "escape" ] + action: @systemMethod:prevMenu + } + ] + } + } + } + + fileBaseSetNewScanDate: { + module: set_newscan_date + desc: File Base + art: SETFNSDATE + config: { + target: file + scanDateFormat: YYYYMMDD + } + form: { + 0: { + mci: { + ME1: { + focus: true + submit: true + argName: scanDate + maskPattern: "####/##/##" + } + } + submit: { + *: [ + { + value: { scanDate: null } + action: @method:scanDateSubmit + } + ] + } + actionKeys: @reference:common.quitToPrev + } + } + } + + fileBaseExportListFilter: { + module: file_base_search + art: FBLISTEXPSEARCH + config: { + fileBaseListEntriesMenu: fileBaseExportList + } + form: { + 0: { + mci: { + ET1: { + focus: true + argName: searchTerms + } + BT2: { + argName: search + text: search + submit: true + } + ET3: { + maxLength: 64 + argName: tags + } + SM4: { + maxLength: 64 + argName: areaIndex + } + SM5: { + items: [ + "upload date", + "uploaded by", + "downloads", + "rating", + "estimated year", + "size", + "filename" + ] + argName: sortByIndex + } + SM6: { + items: [ + "decending", + "ascending" + ] + argName: orderByIndex + } + BT7: { + argName: advancedSearch + text: advanced search + submit: true + } + } + + submit: { + *: [ + { + value: { search: null } + action: @method:search + } + { + value: { advancedSearch: null } + action: @method:search + } + ] + } + + actionKeys: [ + { + keys: [ "escape" ] + action: @systemMethod:prevMenu + } + ] + } + } + } + + fileBaseExportList: { + module: file_base_user_list_export + art: FBLISTEXP + config: { + pause: true + templates: { + entry: file_list_entry.asc + } + } + form: { + 0: { + mci: { + TL1: { } + TL2: { } + } + } + } + } + + fileBaseExportListNoResults: { + desc: Browsing Files + art: FBNORES + config: { + pause: true + menuFlags: [ "noHistory", "popParent" ] + } + } + + // Referenced by various menus + fileBaseGetRatingForSelectedEntry: { + desc: Rating a File + prompt: fileBaseRateEntryPrompt + config: { + cls: true + } + submit: [ + // :TODO: handle esc/q + { + // pass data back to caller + value: { rating: null } + action: @systemMethod:prevMenu + } + ] + } + + // default menu entry used by the 'file_area_list' module + // when there are no search results for the provided criteria + fileBaseListEntriesNoResults: { + desc: Browsing Files + art: FBNORES + config: { + pause: true + menuFlags: [ "noHistory", "popParent" ] + } + } + + // default menu entry used by the 'file_base_download_manager' module + // for protocol selection + fileTransferProtocolSelection: { + desc: Protocol selection + module: file_transfer_protocol_select + art: FPROSEL + form: { + 0: { + mci: { + VM1: { + focus: true + argName: protocol + } + } + + submit: { + *: [ + { + value: { protocol: null } + action: @method:selectProtocol + } + ] + } + + actionKeys: [ + { + keys: [ "escape" ] + action: @systemMethod:prevMenu + } + ] + } + } + } + + // default menu entry used by the 'upload' module for when + // no areas are available for the user to upload to + fileBaseNoUploadAreasAvail: { + desc: File Base + art: ULNOAREA + config: { + pause: true + menuFlags: [ "noHistory", "popParent" ] + } + } + + // default menu entry used by the 'file_transfer_protocol_select' module + // when performing user downloads + sendFilesToUser: { + desc: Downloading + module: file_transfer + config: { + // defaults - generally use extraArgs + protocol: zmodem8kSexyz + direction: send + } + } + + // default menu entry used by the 'file_transfer_protocol_select' module + // when performing user uploads + recvFilesFromUser: { + desc: Uploading + module: file_transfer + config: { + // defaults - generally use extraArgs + protocol: zmodem8kSexyz + direction: recv + } + } + } + + prompts: { + fileMenuCommand: { + art: FILPMPT + mci: { + TL1: {} + ET2: { + argName: menuOption + width: 20 + maxLength: 20 + textStyle: upper + focus: true + } + } + } + + fileBaseRateEntryPrompt: { + art: RATEFILE + mci: { + SM1: { + argName: rating + items: [ "-----", "*----", "**---", "***--", "****-", "*****" ] + } + } + + actionKeys: [ + { + keys: [ "escape" ] + action: @systemMethod:prevMenu + } + ] + } + + fileBaseTagEntryPrompt: { + art: TAGFILE + mci: { + ET1: { + argName: tags + } + } + } + } +} \ No newline at end of file diff --git a/misc/menu_templates/login.in.hjson b/misc/menu_templates/login.in.hjson new file mode 100644 index 00000000..bcee88e2 --- /dev/null +++ b/misc/menu_templates/login.in.hjson @@ -0,0 +1,607 @@ +{ + menus: { + // + // Send telnet connections to matrix where users can login, apply, etc. + // + telnetConnected: { + art: CONNECT + next: matrix + config: { nextTimeout: 1500 } + } + + // + // SSH connections are pre-authenticated via the SSH server itself. + // Jump directly to either the 2FA/OTP auth or the login sequence + // depending on user ACS. + // + sshConnected: { + art: CONNECT + next: [ + { + acs: AR2 + next: loginTwoFactorAuthOTPLoop + } + { + next: fullLoginSequenceLoginArt + } + ] + config: { nextTimeout: 1500 } + } + + // + // Another SSH specialization: If the user logs in with a new user + // name (e.g. "new", "apply", ...) they will be directed to the + // application process. + // + sshConnectedNewUser: { + art: CONNECT + next: newUserApplicationPreSsh + config: { nextTimeout: 1500 } + } + + // Ye ol' standard matrix + matrix: { + art: matrix + form: { + 0: { + VM: { + mci: { + VM1: { + submit: true + focus: true + argName: navSelect + items: [ + { + text: login + data: login + } + { + text: apply + data: apply + } + + // + // To enable the forgot password option, you'll need to have + // the web server & email configured. Once that is in place, + // uncomment the section below. + // + // See docs for more information + // + /* + { + text: forgot pass + data: forgot + } + */ + { + text: log off + data: logoff + } + ] + } + } + submit: { + *: [ + { + value: { navSelect: "login" } + action: @menu:login + } + { + value: { navSelect: "apply" } + action: @menu:newUserApplicationPre + } + { + value: { navSelect: "forgot" } + action: @menu:forgotPassword + } + { + value: { navSelect: "logoff" } + action: @menu:logoff + } + ] + } + } + } + } + } + + login: { + art: USERLOG + next: [ + { + // + // Users with 2FA/OTP enabled *must* go through + // an additional OTP authentication step + // + acs: AR2 + next: loginTwoFactorAuthOTPLoop + } + { + // ...everyone else can carry on as per usual + next: fullLoginSequenceLoginArt + } + ] + config: { + tooNodeMenu: loginAttemptTooNode + inactive: loginAttemptAccountInactive + disabled: loginAttemptAccountDisabled + locked: loginAttemptAccountLocked + } + form: { + 0: { + mci: { + ET1: { + maxLength: @config:users.usernameMax + argName: username + focus: true + } + ET2: { + password: true + maxLength: @config:users.passwordMax + argName: password + submit: true + } + } + submit: { + *: [ + { + value: { password: null } + action: @systemMethod:login + } + ] + } + actionKeys: @reference:common.escToPrev + } + } + } + + loginAttemptTooNode: { + art: TOONODE + config: { + cls: true + nextTimeout: 2000 + } + next: logoff + } + + loginAttemptAccountLocked: { + art: ACCOUNTLOCKED + config: { + cls: true + nextTimeout: 2000 + } + next: logoff + } + + loginAttemptAccountDisabled: { + art: ACCOUNTDISABLED + config: { + cls: true + nextTimeout: 2000 + } + next: logoff + } + + loginAttemptAccountInactive: { + art: ACCOUNTINACTIVE + config: { + cls: true + nextTimeout: 2000 + } + next: logoff + } + + forgotPassword: { + desc: Forgot password + prompt: forgotPasswordPrompt + submit: [ + { + value: { username: null } + action: @systemMethod:sendForgotPasswordEmail + extraArgs: { next: "forgotPasswordSubmitted" } + } + ] + } + + forgotPasswordSubmitted: { + desc: Forgot password + art: FORGOTPWSENT + config: { + cls: true + pause: true + } + next: @systemMethod:logoff + } + + fullLoginSequenceLoginArt: { + desc: Logging In + art: WELCOME + config: { pause: true } + next: fullLoginSequenceLastCallers + } + + fullLoginSequenceLastCallers: { + desc: Last Callers + module: last_callers + art: LASTCALL + config: { + pause: true + font: cp437 + } + next: fullLoginSequenceWhosOnline + } + + fullLoginSequenceWhosOnline: { + desc: Who's Online + module: whos_online + art: WHOSON + config: { pause: true } + next: fullLoginSequenceOnelinerz + } + + fullLoginSequenceOnelinerz: { + desc: Viewing Onelinerz + module: onelinerz + next: [ + { + // calls >= 2 + acs: NC2 + next: fullLoginSequenceNewScanConfirm + } + { + // new users - skip new scan + next: fullLoginSequenceUserStats + } + ] + config: { + cls: true + art: { + view: ONELINER + add: ONEADD + } + } + form: { + 0: { + mci: { + VM1: { + focus: false + height: 10 + } + TM2: { + argName: addOrExit + items: [ "yeah!", "nah" ] + "hotKeys" : { "Y" : 0, "N" : 1, "Q" : 1 } + submit: true + focus: true + } + } + submit: { + *: [ + { + value: { addOrExit: 0 } + action: @method:viewAddScreen + } + { + value: { addOrExit: null } + action: @systemMethod:nextMenu + } + ] + } + actionKeys: [ + { + keys: [ "escape" ] + action: @systemMethod:nextMenu + } + ] + }, + 1: { + mci: { + ET1: { + focus: true + maxLength: 70 + argName: oneliner + } + TL2: { + width: 60 + } + TM3: { + argName: addOrCancel + items: [ "add", "cancel" ] + "hotKeys" : { "A" : 0, "C" : 1, "Q" : 1 } + submit: true + } + } + + submit: { + *: [ + { + value: { addOrCancel: 0 } + action: @method:addEntry + } + { + value: { addOrCancel: 1 } + action: @method:cancelAdd + } + ] + } + actionKeys: [ + { + keys: [ "escape" ] + action: @method:cancelAdd + } + ] + } + } + } + + fullLoginSequenceNewScanConfirm: { + desc: Logging In + prompt: loginGlobalNewScan + submit: [ + { + value: { promptValue: 0 } + action: @menu:fullLoginSequenceNewScan + } + { + value: { promptValue: 1 } + action: @menu:fullLoginSequenceUserStats + } + ] + } + + fullLoginSequenceNewScan: { + desc: Performing New Scan + module: new_scan + art: NEWSCAN + next: fullLoginSequenceSysStats + config: { + messageListMenu: newScanMessageList + } + } + + newScanMessageList: { + desc: New Messages + module: msg_list + art: NEWMSGS + config: { + menuViewPost: messageBaseViewPost + } + form: { + 0: { + mci: { + VM1: { + focus: true + submit: true + argName: message + } + TL6: { } + } + submit: { + *: [ + { + value: { message: null } + action: @method:selectMessage + } + ] + } + actionKeys: [ + { + keys: [ "escape", "q", "shift + q" ] + action: @systemMethod:prevMenu + } + { + keys: [ "x", "shift + x" ] + action: @method:fullExit + } + { + keys: [ "m", "shift + m" ] + action: @method:markAllRead + } + ] + } + } + } + + newScanFileBaseList: { + module: file_area_list + desc: New Files + config: { + art: { + browse: FNEWBRWSE + details: FDETAIL + detailsGeneral: FDETGEN + detailsNfo: FDETNFO + detailsFileList: FDETLST + help: FBHELP + } + } + form: { + 0: { + mci: { + MT1: { + mode: preview + ansiView: true + } + + HM2: { + focus: true + submit: true + argName: navSelect + items: [ + "prev", "next", "details", "toggle queue", "rate", "help", "quit" + ] + focusItemIndex: 1 + } + } + + submit: { + *: [ + { + value: { navSelect: 0 } + action: @method:prevFile + } + { + value: { navSelect: 1 } + action: @method:nextFile + } + { + value: { navSelect: 2 } + action: @method:viewDetails + } + { + value: { navSelect: 3 } + action: @method:toggleQueue + } + { + value: { navSelect: 4 } + action: @menu:fileBaseGetRatingForSelectedEntry + } + { + value: { navSelect: 5 } + action: @method:displayHelp + } + { + value: { navSelect: 6 } + action: @systemMethod:prevMenu + } + ] + } + + actionKeys: [ + { + keys: [ "w", "shift + w" ] + action: @method:showWebDownloadLink + } + { + keys: [ "escape", "q", "shift + q" ] + action: @systemMethod:prevMenu + } + { + keys: [ "t", "shift + t" ] + action: @method:toggleQueue + } + { + keys: [ "v", "shift + v" ] + action: @method:viewDetails + } + { + keys: [ "r", "shift + r" ] + action: @menu:fileBaseGetRatingForSelectedEntry + } + { + keys: [ "?" ] + action: @method:displayHelp + } + ] + } + + 1: { + mci: { + HM1: { + focus: true + submit: true + argName: navSelect + items: [ + "general", "nfo/readme", "file listing" + ] + } + } + + actionKeys: @reference:common.quitToPrev + } + + 2: { + // details - general + mci: { } + } + + 3: { + // details - nfo/readme + mci: { + MT1: { + mode: preview + } + } + } + + 4: { + // details - file listing + mci: { + VM1: { } + } + } + } + } + + fullLoginSequenceSysStats: { + desc: System Stats + art: SYSSTAT + config: { pause: true } + next: fullLoginSequenceUserStats + } + + fullLoginSequenceUserStats: { + desc: User Stats + art: STATUS + config: { pause: true } + next: mainMenu + } + + // + // Empty menu to catch us in a 2FA/OTP auth loop + // until the user either authenticates successfully + // or the system boots them. + // + loginTwoFactorAuthOTPLoop: { + next: loginTwoFactorAuthOTP + } + + loginTwoFactorAuthOTP: { + art: 2FAOTP + next: fullLoginSequenceLoginArt + form: { + 0: { + mci: { + ET1: { + argName: token + focus: true + submit: true + } + } + submit: { + *: [ + { + value: { token: null } + action: @systemMethod:login2FA_OTP + } + ] + } + actionKeys: [ + { + // no turning back at this point... + keys: [ "escape" ] + action: @systemMethod:logoff + } + ] + } + } + } + + } + + prompts: { + loginGlobalNewScan: { + art: GNSPMPT + mci: { + TM1: { + argName: promptValue + items: [ "yes", "no" ] + focus: true + hotKeys: { Y: 0, N: 1 } + hotKeySubmit: true + } + } + } + + } +} \ No newline at end of file diff --git a/misc/menu_templates/main.in.hjson b/misc/menu_templates/main.in.hjson new file mode 100644 index 00000000..ac4b1771 --- /dev/null +++ b/misc/menu_templates/main.in.hjson @@ -0,0 +1,1024 @@ +{ + /* + ./\/\.' ENiGMA½ Menu Configuration -/--/-------- - -- - + + _____________________ _____ ____________________ __________\_ / + \__ ____/\_ ____ \ /____/ / _____ __ \ / ______/ // /___jp! + // __|___// | \// |// | \// | | \// \ /___ /_____ + /____ _____| __________ ___|__| ____| \ / _____ \ + ---- \______\ -- |______\ ------ /______/ ---- |______\ - |______\ /__/ // ___/ + /__ _\ + <*> ENiGMA½ // HTTPS://GITHUB.COM/NUSKOOLER/ENIGMA-BBS <*> /__/ + + *-----------------------------------------------------------------------------* + + General Information + ------------------------------- - - + This configuration is in HJSON (http://hjson.org/) format. Strict to-spec + JSON is also perfectly valid. Use 'hjson' from npm to convert to/from JSON. + + See http://hjson.org/ for more information and syntax. + + Various editors and IDEs such as Sublime Text 3, Visual Studio Code, and so + on have syntax highlighting for the HJSON format which are highly recommended. + + ------------------------------- -- - - + Menu Configuration + ------------------------------- - - + ENiGMA½ makes no assumptions about specific menu types (main, doors, etc.), + but instead allows full customization of all menus throughout the system. + Some menus such as a main menu are considered "standard" while others are + backed by a specific module. SysOps can tweak various settings about these + modules (look & feel, keyboard interation, and so on) or even fully replace + the module with something else. + + This file starts out as an example setup. Look at the examples, change + settings, menu ordering/flow, add/remove menus, implement ACS control, + etc.! + + Remember you can *live edit* this file. That is, make a change and save + while you're logged into the system and it will take effect on the next + menu change or screen refresh. + + Please see RTFM ...er, uh... see the documentation for more information, and + don't be shy to ask for help: + + BBS : Xibalba @ xibalba.l33t.codes + FTN : BBS Discussion on fsxNet + IRC : #enigma-bbs / FreeNode + Email : bryan@l33t.codes + */ + + // You may include as many additional fragments as you like here. + includes: [ + XXXXXXXX + ] + + // This section creates common fragments to use as @reference + common: { + escToPrev: [ + { + keys: [ "escape" ] + action: @systemMethod:prevMenu + } + ] + + quitToPrev: [ + { + keys: [ "escape", "q", "shift + q" ] + action: @systemMethod:prevMenu + } + ] + } + + menus: { + /////////////////////////////////////////////////////////////////////// + // Main Menu + /////////////////////////////////////////////////////////////////////// + mainMenu: { + art: MMENU + desc: Main Menu + prompt: menuCommand + config: { + font: cp437 + interrupt: realtime + } + submit: [ + { + value: { command: "MSG" } + action: @menu:nodeMessage + } + { + value: { command: "G" } + action: @menu:fullLogoffSequence + } + { + value: { command: "D" } + action: @menu:doorsMainMenu + } + { + value: { command: "F" } + action: @menu:fileBaseMainMenu + } + { + value: { command: "U" } + action: @menu:mainMenuUserList + } + { + value: { command: "L" } + action: @menu:mainMenuLastCallers + } + { + value: { command: "W" } + action: @menu:mainMenuWhosOnline + } + { + value: { command: "Y" } + action: @menu:mainMenuUserStats + } + { + value: { command: "M" } + action: @menu:messageBaseMainMenu + } + { + value: { command: "E" } + action: @menu:privateMailMenu + } + { + value: { command: "C" } + action: @menu:mainMenuUserConfig + } + { + value: { command: "S" } + action: @menu:mainMenuSystemStats + } + { + value: { command: "!" } + action: @menu:mainMenuGlobalNewScan + } + { + value: { command: "K" } + action: @menu:mainMenuFeedbackToSysOp + } + { + value: { command: "O" } + action: @menu:mainMenuOnelinerz + } + { + value: { command: "R" } + action: @menu:mainMenuRumorz + } + { + value: { command: "BBS"} + action: @menu:bbsList + } + { + value: { command: "UA" } + action: @menu:mainMenuUserAchievementsEarned + } + { + value: { command: "MRC" } + action: @menu:mrc + } + { + value: { command: "2FA" } + action: [ + { + // + // For security reasons, only allow 2FA/OTP to be + // configured over already secure (SSL, wss://, ...) + // connections. Not doing so risks leaking secrets! + // + acs: SC + action: @menu:userTwoFactorAuthOTPConfig + } + { + action: @menu:userTwoFactorAuthOTPSecConnRequired + } + ] + } + { + value: 1 + action: @menu:mainMenu + } + ] + } + + mainMenuUserAchievementsEarned: { + desc: Achievements + module: user_achievements_earned + art: USERACHIEV + form: { + 0: { + mci: { + VM1: { + focus: true + } + } + actionKeys: @reference:common.quitToPrev + } + } + } + + mrc: { + desc: MRC Chat + module: mrc + art: MRC + config: { + cls: true + + // max lines kept in scrollback buffer + maxScrollbackLines: 500 + } + form: { + 0: { + mci: { + MT1: { + mode: preview + autoScroll: true + } + ET2: { + argName: inputArea + submit: true + focus: true + } + } + actionKeys: [ + { + keys: [ "escape" ] + action: @systemMethod:prevMenu + } + { + keys: [ "down arrow", "up arrow", "page up", "page down" ] + action: @method:movementKeyPressed + } + ] + submit: { + *: [ + { + value: { inputArea: null } + action: @method:sendChatMessage + } + ] + } + } + } + } + + userTwoFactorAuthOTPConfig: { + desc: 2FA/OTP Config + module: user_2fa_otp_config + art: 2FACONFSCR + form: { + 0: { + mci: { + TM1: { + argName: enableToggle + focus: true + items: [ + // order is important here: + "disable" + "enable/reset" + ] + } + SM2: { + argName: otpType + items: [ + // order is important here: + "Time-Based - TOTP" + "HMAC-Based - HOTP" + "Google Authenticator" + ] + } + TM3: { + argName: submit + items: [ + "save" + "cancel" + ] + submit: true + } + } + + submit: { + *: [ + { + value: { submit: 0 } + action: @method:saveChanges + } + { + value: { submit: 1 } + action: @systemMethod:prevMenu + } + ] + } + + actionKeys: [ + { + keys: [ "escape" ] + action: @systemMethod:prevMenu + } + { + keys: [ "q", "shift + q" ] + action: @method:showQRCode + } + { + keys: [ "s", "shift + s" ] + action: @method:showSecret + } + { + keys: [ "b", "shift + b" ] + action: @method:showBackupCodes + } + { + keys: [ "n", "shift + n" ] + action: @method:generateNewBackupCodes + } + ] + } + } + } + + userTwoFactorAuthOTPSecConnRequired: { + desc: Insecure Warning + art: 2FAOTPSECREQ + config: { + cls: true + pause: true + } + } + + userTwoFactorAuthOTPConfigShowDetails: { + desc: 2FA/OTP Details + module: show_art + config: { + pause: true + method: extraArgs + } + } + + nodeMessage: { + desc: Node Messaging + module: node_msg + art: NODEMSG + config: { + cls: true + art: { + header: NODEMSGHDR + footer: NODEMSGFTR + } + } + form: { + 0: { + mci: { + SM1: { + argName: node + } + ET2: { + argName: message + submit: true + } + } + actionKeys: [ + { + keys: [ "escape" ] + action: @systemMethod:prevMenu + } + ] + submit: { + *: [ + { + value: { message: null } + action: @method:sendMessage + } + ] + } + } + } + } + + mainMenuLastCallers: { + desc: Last Callers + module: last_callers + art: LASTCALL + config: { pause: true } + } + + mainMenuWhosOnline: { + desc: Who's Online + module: whos_online + art: WHOSON + config: { pause: true } + } + + mainMenuUserStats: { + desc: User Stats + art: STATUS + config: { pause: true } + } + + mainMenuSystemStats: { + desc: System Stats + art: SYSSTAT + config: { pause: true } + } + + mainMenuUserList: { + desc: User Listing + module: user_list + art: USERLST + form: { + 0: { + mci: { + VM1: { + focus: true + submit: true + } + } + actionKeys: @reference:common.quitToPrev + } + } + } + + mainMenuUserConfig: { + module: user_config + art: CONFSCR + form: { + 0: { + mci: { + ET1: { + argName: realName + maxLength: @config:users.realNameMax + validate: @systemMethod:validateNonEmpty + focus: true + } + ME2: { + argName: birthdate + maskPattern: "####/##/##" + } + ME3: { + argName: sex + maskPattern: A + textStyle: upper + validate: @systemMethod:validateNonEmpty + } + ET4: { + argName: location + maxLength: @config:users.locationMax + validate: @systemMethod:validateNonEmpty + } + ET5: { + argName: affils + maxLength: @config:users.affilsMax + } + ET6: { + argName: email + maxLength: @config:users.emailMax + validate: @method:validateEmailAvail + } + ET7: { + argName: web + maxLength: @config:users.webMax + } + ME8: { + maskPattern: "##" + argName: termHeight + validate: @systemMethod:validateNonEmpty + } + SM9: { + argName: theme + } + ET10: { + argName: password + maxLength: @config:users.passwordMax + password: true + validate: @method:validatePassword + } + ET11: { + argName: passwordConfirm + maxLength: @config:users.passwordMax + password: true + validate: @method:validatePassConfirmMatch + } + TM25: { + argName: submission + items: [ "save", "cancel" ] + submit: true + } + } + + submit: { + *: [ + { + value: { submission: 0 } + action: @method:saveChanges + } + { + value: { submission: 1 } + action: @systemMethod:prevMenu + } + ] + } + + actionKeys: [ + { + keys: [ "escape" ] + action: @systemMethod:prevMenu + } + ] + } + } + } + + mainMenuGlobalNewScan: { + desc: Performing New Scan + module: new_scan + art: NEWSCAN + config: { + messageListMenu: newScanMessageList + } + } + + mainMenuFeedbackToSysOp: { + desc: Feedback to SysOp + module: msg_area_post_fse + config: { + art: { + header: MSGEHDR + body: MSGBODY + footerEditor: MSGEFTR + footerEditorMenu: MSGEMFT + help: MSGEHLP + }, + editorMode: edit + editorType: email + messageAreaTag: private_mail + toUserId: 1 /* always to +op */ + } + form: { + 0: { + mci: { + TL1: { + argName: from + } + ET2: { + argName: to + focus: true + text: @sysStat:sysop_username + maxLength: 36 + // :TODO: readOnly: true + } + ET3: { + argName: subject + maxLength: 72 + submit: true + validate: @systemMethod:validateMessageSubject + } + } + submit: { + 3: [ + { + value: { subject: null } + action: @method:headerSubmit + } + ] + } + actionKeys: [ + { + keys: [ "escape" ] + action: @systemMethod:prevMenu + } + ] + } + 1: { + mci: { + MT1: { + width: 79 + argName: message + mode: edit + } + } + + submit: { + *: [ { value: "message", action: "@method:editModeEscPressed" } ] + } + actionKeys: [ + { + keys: [ "escape" ] + viewId: 1 + } + ] + }, + 2: { + TLTL: { + mci: { + TL1: { + width: 5 + } + TL2: { + width: 4 + } + } + } + } + 3: { + HM: { + mci: { + HM1: { + // :TODO: clear + items: [ "save", "discard", "help" ] + } + } + submit: { + *: [ + { + value: { 1: 0 } + action: @method:editModeMenuSave + } + { + value: { 1: 1 } + action: @systemMethod:prevMenu + } + { + value: { 1: 2 } + action: @method:editModeMenuHelp + } + ] + } + actionKeys: [ + { + keys: [ "escape" ] + action: @method:editModeEscPressed + } + { + keys: [ "?" ] + action: @method:editModeMenuHelp + } + ] + } + } + } + } + + mainMenuOnelinerz: { + desc: Viewing Onelinerz + module: onelinerz + config: { + cls: true + art: { + view: ONELINER + add: ONEADD + } + } + form: { + 0: { + mci: { + VM1: { + focus: false + height: 10 + } + TM2: { + argName: addOrExit + items: [ "yeah!", "nah" ] + "hotKeys" : { "Y" : 0, "N" : 1, "Q" : 1 } + submit: true + focus: true + } + } + submit: { + *: [ + { + value: { addOrExit: 0 } + action: @method:viewAddScreen + } + { + value: { addOrExit: null } + action: @systemMethod:nextMenu + } + ] + } + actionKeys: [ + { + keys: [ "escape" ] + action: @systemMethod:nextMenu + } + ] + }, + 1: { + mci: { + ET1: { + focus: true + maxLength: 70 + argName: oneliner + } + TL2: { + width: 60 + } + TM3: { + argName: addOrCancel + items: [ "add", "cancel" ] + "hotKeys" : { "A" : 0, "C" : 1, "Q" : 1 } + submit: true + } + } + + submit: { + *: [ + { + value: { addOrCancel: 0 } + action: @method:addEntry + } + { + value: { addOrCancel: 1 } + action: @method:cancelAdd + } + ] + } + actionKeys: [ + { + keys: [ "escape" ] + action: @method:cancelAdd + } + ] + } + } + } + + mainMenuRumorz: { + desc: Rumorz + module: rumorz + config: { + cls: true + art: { + entries: RUMORS + add: RUMORADD + } + } + form: { + 0: { + mci: { + VM1: { + focus: false + height: 10 + } + TM2: { + argName: addOrExit + items: [ "yeah!", "nah" ] + "hotKeys" : { "Y" : 0, "N" : 1, "Q" : 1 } + submit: true + focus: true + } + } + submit: { + *: [ + { + value: { addOrExit: 0 } + action: @method:viewAddScreen + } + { + value: { addOrExit: null } + action: @systemMethod:nextMenu + } + ] + } + actionKeys: [ + { + keys: [ "escape" ] + action: @systemMethod:nextMenu + } + ] + }, + 1: { + mci: { + ET1: { + focus: true + maxLength: 70 + argName: rumor + } + TL2: { + width: 60 + } + TM3: { + argName: addOrCancel + items: [ "add", "cancel" ] + "hotKeys" : { "A" : 0, "C" : 1, "Q" : 1 } + submit: true + } + } + + submit: { + *: [ + { + value: { addOrCancel: 0 } + action: @method:addEntry + } + { + value: { addOrCancel: 1 } + action: @method:cancelAdd + } + ] + } + actionKeys: [ + { + keys: [ "escape" ] + action: @method:cancelAdd + } + ] + } + } + } + + bbsList: { + desc: Viewing BBS List + module: bbs_list + config: { + cls: true + art: { + entries: BBSLIST + add: BBSADD + } + } + + form: { + 0: { + mci: { + VM1: { maxLength: 32 } + TL2: { maxLength: 32 } + TL3: { maxLength: 32 } + TL4: { maxLength: 32 } + TL5: { maxLength: 32 } + TL6: { maxLength: 32 } + TL7: { maxLength: 32 } + TL8: { maxLength: 32 } + TL9: { maxLength: 32 } + } + actionKeys: [ + { + keys: [ "a" ] + action: @method:addBBS + } + { + // :TODO: add delete key + keys: [ "d" ] + action: @method:deleteBBS + } + { + keys: [ "q", "escape" ] + action: @systemMethod:prevMenu + } + ] + } + 1: { + mci: { + ET1: { + argName: name + maxLength: 32 + validate: @systemMethod:validateNonEmpty + } + ET2: { + argName: sysop + maxLength: 32 + validate: @systemMethod:validateNonEmpty + } + ET3: { + argName: telnet + maxLength: 32 + validate: @systemMethod:validateNonEmpty + } + ET4: { + argName: www + maxLength: 32 + } + ET5: { + argName: location + maxLength: 32 + } + ET6: { + argName: software + maxLength: 32 + } + ET7: { + argName: notes + maxLength: 32 + } + TM17: { + argName: submission + items: [ "save", "cancel" ] + submit: true + } + } + + actionKeys: [ + { + keys: [ "escape" ] + action: @method:cancelSubmit + } + ] + + submit: { + *: [ + { + value: { "submission" : 0 } + action: @method:submitBBS + } + { + value: { "submission" : 1 } + action: @method:cancelSubmit + } + ] + } + } + } + } + + fullLogoffSequence: { + desc: Logging Off + prompt: logoffConfirmation + submit: [ + { + value: { promptValue: 0 } + action: @menu:fullLogoffSequencePreAd + } + { + value: { promptValue: 1 } + action: @systemMethod:prevMenu + } + ] + } + + fullLogoffSequencePreAd: { + art: PRELOGAD + desc: Logging Off + next: fullLogoffSequenceRandomBoardAd + config: { + cls: true + nextTimeout: 1500 + } + } + + fullLogoffSequenceRandomBoardAd: { + art: OTHRBBS + desc: Logging Off + next: logoff + config: { + baudRate: 57600 + pause: true + cls: true + } + } + + logoff: { + art: LOGOFF + desc: Logging Off + next: @systemMethod:logoff + } + + //////////////////////////////////////////////////////////////////////// + // These entries are required by the system and must exist. + // You can still modify/theme them, however. + //////////////////////////////////////////////////////////////////////// + idleLogoff: { + art: IDLELOG + next: @systemMethod:logoff + } + } + + prompts: { + menuCommand: { + art: MNUPRMT + mci: { + TL1: { } + ET2: { + argName: command + width: 20 + maxLength: 20 + submit: true + textStyle: upper + focus: true + } + } + } + + logoffConfirmation: { + art: LOGPMPT + mci: { + TM1: { + argName: promptValue + items: [ "yes", "no" ] + focus: true + hotKeys: { Y: 0, N: 1 } + hotKeySubmit: true + } + } + } + + forgotPasswordPrompt: { + art: FORGOTPW + mci: { + ET1: { + argName: username + maxLength: @config:users.usernameMax + width: 32 + focus: true + } + } + actionKeys: [ + { + keys: [ "escape" ] + action: @systemMethod:prevMenu + } + ] + } + + //////////////////////////////////////////////////////////////////////// + // These entries are required by the system and must exist. + // You can still modify/theme them, however. + //////////////////////////////////////////////////////////////////////// + pause: { + art: pause + config: { + trailingLF: no + } + } + } +} diff --git a/misc/menu_templates/message_base.in.hjson b/misc/menu_templates/message_base.in.hjson new file mode 100644 index 00000000..a7bcac65 --- /dev/null +++ b/misc/menu_templates/message_base.in.hjson @@ -0,0 +1,816 @@ +{ + menus: { + messageBaseMainMenu: { + art: MSGMNU + desc: Message Area + prompt: messageBaseMenuPrompt + config: { + interrupt: realtime + } + submit: [ + { + value: { command: "P" } + action: @menu:messageBaseNewPost + } + { + value: { command: "J" } + action: @menu:messageBaseChangeCurrentConference + } + { + value: { command: "C" } + action: @menu:messageBaseChangeCurrentArea + } + { + value: { command: "L" } + action: @menu:messageBaseMessageList + } + { + value: { command: "<" } + action: @systemMethod:prevConf + } + { + value: { command: ">" } + action: @systemMethod:nextConf + } + { + value: { command: "[" } + action: @systemMethod:prevArea + } + { + value: { command: "]" } + action: @systemMethod:nextArea + } + { + value: { command: "D" } + action: @menu:messageBaseSetNewScanDate + } + { + value: { command: "S" } + action: @menu:messageBaseSearch + } + { + value: { command: "M" } + action: @menu:messageBaseMyMessages + } + { + value: { command: "A" } + action: @menu:editAutoSignature + } + { + value: { command: "Q" } + action: @systemMethod:prevMenu + } + { + value: { command: "G" } + action: @menu:fullLogoffSequence + } + ] + } + + messageBaseNewPost: { + desc: Posting message, + module: msg_area_post_fse + config: { + art: { + header: MSGEHDR + body: MSGBODY + footerEditor: MSGEFTR + footerEditorMenu: MSGEMFT + help: MSGEHLP + } + editorMode: edit + editorType: area + } + form: { + 0: { + mci: { + TL1: { + argName: from + } + ET2: { + argName: to + focus: true + text: All + validate: @systemMethod:validateNonEmpty + maxLength: 36 + } + ET3: { + argName: subject + maxLength: 72 + submit: true + validate: @systemMethod:validateNonEmpty + } + } + submit: { + 3: [ + { + value: { subject: null } + action: @method:headerSubmit + } + ] + } + + actionKeys: [ + { + keys: [ "escape" ] + action: @systemMethod:prevMenu + } + ] + } + + 1: { + "mci" : { + MT1: { + width: 79 + argName: message + mode: edit + } + } + + submit: { + *: [ { "value": "message", "action": "@method:editModeEscPressed" } ] + } + actionKeys: [ + { + keys: [ "escape" ] + viewId: 1 + } + ] + } + 2: { + TLTL: { + mci: { + TL1: { width: 5 } + TL2: { width: 4 } + } + } + } + 3: { + HM: { + mci: { + HM1: { + "items" : [ "save", "discard", "help" ] + } + } + submit: { + *: [ + { + value: { 1: 0 } + action: @method:editModeMenuSave + } + { + value: { 1: 1 } + action: @systemMethod:prevMenu + } + { + value: { 1: 2 } + action: @method:editModeMenuHelp + } + ] + } + actionKeys: [ + { + keys: [ "escape" ] + action: @method:editModeEscPressed + } + { + keys: [ "?" ] + action: @method:editModeMenuHelp + } + ] + } + } + } + } + + messageBaseChangeCurrentConference: { + art: CCHANGE + module: msg_conf_list + form: { + 0: { + mci: { + VM1: { + focus: true + submit: true + argName: conf + } + } + submit: { + *: [ + { + value: { conf: null } + action: @method:changeConference + } + ] + } + actionKeys: @reference:common.quitToPrev + } + } + } + + messageBaseChangeCurrentArea: { + art: CHANGE + module: msg_area_list + form: { + 0: { + mci: { + VM1: { + focus: true + submit: true + argName: area + } + } + submit: { + *: [ + { + value: { area: null } + action: @method:changeArea + } + ] + } + actionKeys: @reference:common.quitToPrev + } + } + } + + messageBaseMessageList: { + module: msg_list + art: MSGLIST + config: { + menuViewPost: messageAreaViewPost + } + form: { + 0: { + mci: { + VM1: { + focus: true + submit: true + argName: message + } + } + submit: { + *: [ + { + value: { message: null } + action: @method:selectMessage + } + ] + } + actionKeys: @reference:common.quitToPrev + } + } + } + + messageBaseSetNewScanDate: { + module: set_newscan_date + desc: Message Base + art: SETMNSDATE + config: { + target: message + scanDateFormat: YYYYMMDD + } + form: { + 0: { + mci: { + ME1: { + focus: true + submit: true + argName: scanDate + maskPattern: "####/##/##" + } + SM2: { + argName: targetSelection + submit: false + } + } + submit: { + *: [ + { + value: { scanDate: null } + action: @method:scanDateSubmit + } + ] + } + actionKeys: @reference:common.quitToPrev + } + } + } + + messageBaseSearch: { + desc: Message Search + module: message_base_search + art: MSEARCH + config: { + messageListMenu: messageBaseSearchResultsMessageList + } + form: { + 0: { + mci: { + ET1: { + focus: true + argName: searchTerms + } + BT2: { + argName: search + text: search + submit: true + } + SM3: { + argName: confTag + } + SM4: { + argName: areaTag + } + ET5: { + argName: toUserName + maxLength: @config:users.usernameMax + } + ET6: { + argName: fromUserName + maxLength: @config:users.usernameMax + } + BT7: { + argName: advancedSearch + text: advanced search + submit: true + } + } + + submit: { + *: [ + { + value: { search: null } + action: @method:search + } + { + value: { advancedSearch: null } + action: @method:search + } + ] + } + + actionKeys: [ + { + keys: [ "escape" ] + action: @systemMethod:prevMenu + } + ] + } + } + } + + messageBaseSearchResultsMessageList: { + desc: Message Search + module: msg_list + art: MSRCHLST + config: { + menuViewPost: messageAreaViewPost + } + form: { + 0: { + mci: { + VM1: { + focus: true + submit: true + argName: message + } + TL6: { + // theme me! + } + } + submit: { + *: [ + { + value: { message: null } + action: @method:selectMessage + } + ] + } + actionKeys: @reference:common.quitToPrev + } + } + } + + // The message_base_search module looks for this entry by default + messageSearchNoResults: { + desc: Message Search + art: MSRCNORES + config: { + pause: true + } + } + + messageBaseMyMessages: { + desc: Personal Messages + module: my_messages + config: { + messageListMenu: messageBaseMyMessagesList + } + } + + messageBaseMyMessagesList: { + desc: Personal Messages + module: msg_list + art: MYMSGLST + config: { + menuViewPost: messageAreaViewPost + } + form: { + 0: { + mci: { + VM1: { + focus: true + submit: true + argName: message + } + } + submit: { + *: [ + { + value: { message: null } + action: @method:selectMessage + } + ] + } + actionKeys: @reference:common.quitToPrev + } + } + } + + editAutoSignature: { + desc: Auto Sig Editor + module: autosig_edit + art: autosig + form: { + 0: { + mci: { + MT1: { + argName: signature + tabSwitchesView: true + } + BT2: { + text: save + argName: save + submit: true + } + } + submit: { + *: [ + { + value: { save: null } + action: @method:saveChanges + } + ] + } + + actionKeys: [ + { + keys: [ "escape" ] + action: @systemMethod:prevMenu + } + ] + } + } + } + + messageAreaViewPost: { + module: msg_area_view_fse + config: { + art: { + header: MSGVHDR + body: MSGBODY + footerView: MSGVFTR + help: MSGVHLP + }, + editorMode: view + editorType: area + } + form: { + 0: { + mci: { + // :TODO: ensure this block isn't even req. for theme to apply... + } + } + 1: { + mci: { + MT1: { + width: 79 + mode: preview + } + } + submit: { + *: [ + { + value: message + action: @method:editModeEscPressed + } + ] + } + actionKeys: [ + { + keys: [ "escape" ] + viewId: 1 + } + ] + } + 2: { + TLTL: { + mci: { + TL1: { width: 5 } + TL2: { width: 4 } + } + } + } + 4: { + mci: { + HM1: { + // :TODO: (#)Jump/(L)Index (msg list)/Last + items: [ "prev", "next", "reply", "quit", "help" ] + focusItemIndex: 1 + } + } + submit: { + *: [ + { + value: { 1: 0 } + action: @method:prevMessage + } + { + value: { 1: 1 } + action: @method:nextMessage + } + { + value: { 1: 2 } + action: @method:replyMessage + extraArgs: { + menu: messageAreaReplyPost + } + } + { + value: { 1: 3 } + action: @systemMethod:prevMenu + } + { + value: { 1: 4 } + action: @method:viewModeMenuHelp + } + ] + } + actionKeys: [ + { + keys: [ "p", "shift + p" ] + action: @method:prevMessage + } + { + keys: [ "n", "shift + n" ] + action: @method:nextMessage + } + { + keys: [ "r", "shift + r" ] + action: @method:replyMessage + extraArgs: { + menu: messageAreaReplyPost + } + } + { + keys: [ "escape", "q", "shift + q" ] + action: @systemMethod:prevMenu + } + { + keys: [ "?" ] + action: @method:viewModeMenuHelp + } + { + keys: [ "down arrow", "up arrow", "page up", "page down" ] + action: @method:movementKeyPressed + } + ] + } + } + } + + messageAreaReplyPost: { + module: msg_area_post_fse + config: { + art: { + header: MSGEHDR + body: MSGBODY + quote: MSGQUOT + footerEditor: MSGEFTR + footerEditorMenu: MSGEMFT + help: MSGEHLP + } + editorMode: edit + editorType: area + } + form: { + 0: { + mci: { + // :TODO: use appropriate system properties for max lengths + TL1: { + argName: from + } + ET2: { + argName: to + focus: true + validate: @systemMethod:validateNonEmpty + maxLength: 36 + } + ET3: { + argName: subject + maxLength: 72 + submit: true + validate: @systemMethod:validateNonEmpty + } + TL4: { + // :TODO: this is for RE: line (NYI) + //width: 27 + //textOverflow: ... + } + } + submit: { + 3: [ + { + value: { subject: null } + action: @method:headerSubmit + } + ] + } + actionKeys: [ + { + keys: [ "escape" ] + action: @systemMethod:prevMenu + } + ] + } + 1: { + mci: { + MT1: { + width: 79 + height: 14 + argName: message + mode: edit + } + } + submit: { + *: [ { "value": "message", "action": "@method:editModeEscPressed" } ] + } + actionKeys: [ + { + keys: [ "escape" ], + viewId: 1 + } + ] + } + + 3: { + mci: { + HM1: { + items: [ "save", "discard", "quote", "help" ] + } + } + + submit: { + *: [ + { + value: { 1: 0 } + action: @method:editModeMenuSave + } + { + value: { 1: 1 } + action: @systemMethod:prevMenu + } + { + value: { 1: 2 }, + action: @method:editModeMenuQuote + } + { + value: { 1: 3 } + action: @method:editModeMenuHelp + } + ] + } + + actionKeys: [ + { + keys: [ "escape" ] + action: @method:editModeEscPressed + } + { + keys: [ "s", "shift + s" ] + action: @method:editModeMenuSave + } + { + keys: [ "d", "shift + d" ] + action: @systemMethod:prevMenu + } + { + keys: [ "q", "shift + q" ] + action: @method:editModeMenuQuote + } + { + keys: [ "?" ] + action: @method:editModeMenuHelp + } + ] + } + + // Quote builder + 5: { + mci: { + MT1: { + width: 79 + height: 7 + } + VM3: { + width: 79 + height: 4 + argName: quote + } + } + + submit: { + *: [ + { + value: { quote: null } + action: @method:appendQuoteEntry + } + ] + } + + actionKeys: [ + { + keys: [ "escape" ] + action: @method:quoteBuilderEscPressed + } + ] + } + } + } + + // + // The 'msg_conf_list' module defaults to looking for + // a menu entry of 'changeConfPreArtMenu'. If found, + // this menu will be executed upon changing message + // conferences using the conference tag as an art spec. + // + changeMessageConfPreArt: { + module: show_art + config: { + method: messageConf + key: confTag + pause: true + cls: true + menuFlags: [ "popParent", "noHistory" ] + } + } + + // + // The 'msg_area_list' module defaults to looking for + // a menu entry of 'changeMessageAreaPreArt'. If found, + // this menu will be executed upon changing message + // areas using the area tag as an art spec. + // + changeMessageAreaPreArt: { + module: show_art + config: { + method: messageArea + key: areaTag + pause: true + cls: true + menuFlags: [ "popParent", "noHistory" ] + } + } + } + + prompts: { + messageBaseMenuPrompt: { + art: MSGPMPT + mci: { + //TL1: {} + ET2: { + argName: command + width: 20 + maxLength: 20 + submit: true + textStyle: upper + focus: true + } + } + }, + + // default prompt entry used by the 'msg_lsit' module + deleteMessageFromListPrompt: { + art: MSGDELPMPT + mci: { + TM1: { + argName: promptValue + items: [ "yes", "no" ] + focus: true + hotKeys: { Y: 0, N: 1 } + hotKeySubmit: true + } + } + } + } +} \ No newline at end of file diff --git a/misc/menu_templates/new_user.in.hjson b/misc/menu_templates/new_user.in.hjson new file mode 100644 index 00000000..084e3788 --- /dev/null +++ b/misc/menu_templates/new_user.in.hjson @@ -0,0 +1,362 @@ +{ + menus: { + // A quick preamble - defaults to warning about broken terminals + newUserApplicationPre: { + art: NEWUSER1 + next: newUserApplication + desc: Applying + config: { + pause: true + cls: true + menuFlags: [ "noHistory" ] + } + } + + newUserApplication: { + module: nua + art: NUA + next: [ + { + // Initial SysOp does not send feedback to themselves + acs: ID1 + next: fullLoginSequenceLoginArt + } + { + // ...everyone else does + next: newUserFeedbackToSysOpPreamble + } + ] + form: { + 0: { + mci: { + ET1: { + focus: true + argName: username + maxLength: @config:users.usernameMax + validate: @systemMethod:validateUserNameAvail + } + ET2: { + argName: realName + maxLength: @config:users.realNameMax + validate: @systemMethod:validateNonEmpty + } + MET3: { + argName: birthdate + maskPattern: "####/##/##" + validate: @systemMethod:validateBirthdate + } + ME4: { + argName: sex + maskPattern: A + textStyle: upper + validate: @systemMethod:validateNonEmpty + } + ET5: { + argName: location + maxLength: @config:users.locationMax + validate: @systemMethod:validateNonEmpty + } + ET6: { + argName: affils + maxLength: @config:users.affilsMax + } + ET7: { + argName: email + maxLength: @config:users.emailMax + validate: @systemMethod:validateEmailAvail + } + ET8: { + argName: web + maxLength: @config:users.webMax + } + ET9: { + argName: password + password: true + maxLength: @config:users.passwordMax + validate: @systemMethod:validatePasswordSpec + } + ET10: { + argName: passwordConfirm + password: true + maxLength: @config:users.passwordMax + validate: @method:validatePassConfirmMatch + } + TM12: { + argName: submission + items: [ "apply", "cancel" ] + submit: true + } + } + + submit: { + *: [ + { + value: { "submission" : 0 } + action: @method:submitApplication + extraArgs: { + inactive: userNeedsActivated + error: newUserCreateError + } + } + { + value: { "submission" : 1 } + action: @systemMethod:prevMenu + } + ] + } + + actionKeys: @reference:common.escToPrev + } + } + } + + // A quick preamble - defaults to warning about broken terminals (SSH version) + newUserApplicationPreSsh: { + art: NEWUSER1 + next: newUserApplicationSsh + desc: Applying + config: { + pause: true + cls: true + menuFlags: [ "noHistory" ] + } + } + + // + // SSH specialization of NUA + // Canceling this form logs off vs falling back to matrix + // + newUserApplicationSsh: { + module: nua + art: NUA + fallback: logoff + next: newUserFeedbackToSysOpPreamble + form: { + 0: { + mci: { + ET1: { + focus: true + argName: username + maxLength: @config:users.usernameMax + validate: @systemMethod:validateUserNameAvail + } + ET2: { + argName: realName + maxLength: @config:users.realNameMax + validate: @systemMethod:validateNonEmpty + } + MET3: { + argName: birthdate + maskPattern: "####/##/##" + validate: @systemMethod:validateBirthdate + } + ME4: { + argName: sex + maskPattern: A + textStyle: upper + validate: @systemMethod:validateNonEmpty + } + ET5: { + argName: location + maxLength: @config:users.locationMax + validate: @systemMethod:validateNonEmpty + } + ET6: { + argName: affils + maxLength: @config:users.affilsMax + } + ET7: { + argName: email + maxLength: @config:users.emailMax + validate: @systemMethod:validateEmailAvail + } + ET8: { + argName: web + maxLength: @config:users.webMax + } + ET9: { + argName: password + password: true + maxLength: @config:users.passwordMax + validate: @systemMethod:validatePasswordSpec + } + ET10: { + argName: passwordConfirm + password: true + maxLength: @config:users.passwordMax + validate: @method:validatePassConfirmMatch + } + TM12: { + argName: submission + items: [ "apply", "cancel" ] + submit: true + } + } + + submit: { + *: [ + { + value: { "submission" : 0 } + action: @method:submitApplication + extraArgs: { + inactive: userNeedsActivated + error: newUserCreateError + } + } + { + value: { "submission" : 1 } + action: @systemMethod:logoff + } + ] + } + + actionKeys: [ + { + keys: [ "escape" ] + action: @systemMethod:logoff + } + ] + } + } + } + + newUserFeedbackToSysOpPreamble: { + art: LETTER + config: { pause: true } + next: newUserFeedbackToSysOp + } + + newUserFeedbackToSysOp: { + desc: Feedback to SysOp + module: msg_area_post_fse + next: [ + { + acs: AS2 + next: fullLoginSequenceLoginArt + } + { + next: newUserInactiveDone + } + ] + config: { + art: { + header: MSGEHDR + body: MSGBODY + footerEditor: MSGEFTR + footerEditorMenu: MSGEMFT + help: MSGEHLP + }, + editorMode: edit + editorType: email + messageAreaTag: private_mail + toUserId: 1 /* always to +op */ + } + form: { + 0: { + mci: { + TL1: { + argName: from + } + ET2: { + argName: to + focus: true + text: @sysStat:sysop_username + maxLength: 36 + // :TODO: readOnly: true + } + ET3: { + argName: subject + maxLength: 72 + submit: true + text: New user feedback + validate: @systemMethod:validateMessageSubject + } + } + submit: { + 3: [ + { + value: { subject: null } + action: @method:headerSubmit + } + ] + } + } + 1: { + mci: { + MT1: { + width: 79 + argName: message + mode: edit + } + } + + submit: { + *: [ + { + value: message + action: @method:editModeEscPressed + } + ] + } + actionKeys: [ + { + keys: [ "escape" ] + viewId: 1 + } + ] + }, + 2: { + TLTL: { + mci: { + TL1: { + width: 5 + } + TL2: { + width: 4 + } + } + } + } + 3: { + HM: { + mci: { + HM1: { + // :TODO: clear + items: [ "save", "help" ] + } + } + submit: { + *: [ + { + value: { 1: 0 } + action: @method:editModeMenuSave + } + { + value: { 1: 1 } + action: @method:editModeMenuHelp + } + ] + } + actionKeys: [ + { + keys: [ "escape" ] + action: @method:editModeEscPressed + } + { + keys: [ "?" ] + action: @method:editModeMenuHelp + } + ] + } + } + } + } + + newUserInactiveDone: { + desc: Finished with NUA + art: DONE + config: { pause: true } + next: @menu:logoff + } + } +} \ No newline at end of file diff --git a/misc/menu_templates/private_mail.in.hjson b/misc/menu_templates/private_mail.in.hjson new file mode 100644 index 00000000..eeefb25d --- /dev/null +++ b/misc/menu_templates/private_mail.in.hjson @@ -0,0 +1,197 @@ +{ + menus: { + privateMailMenu: { + art: MAILMNU + desc: Private Mail + prompt: menuCommand + config: { + interrupt: realtime + } + submit: [ + { + value: { command: "C" } + action: @menu:privateMailMenuCreateMessage + } + { + value: { command: "I" } + action: @menu:privateMailMenuInbox + } + { + value: { command: "Q" } + action: @systemMethod:prevMenu + } + { + value: { command: "G" } + action: @menu:fullLogoffSequence + } + ] + } + + privateMailMenuCreateMessage: { + desc: Mailing Someone + module: msg_area_post_fse + config: { + art: { + header: MSGEHDR + body: MSGBODY + footerEditor: MSGEFTR + footerEditorMenu: MSGEMFT + help: MSGEHLP + }, + editorMode: edit + editorType: email + messageAreaTag: private_mail + } + form: { + 0: { + mci: { + TL1: { + argName: from + } + ET2: { + argName: to + focus: true + validate: @systemMethod:validateGeneralMailAddressedTo + maxLength: 36 + } + ET3: { + argName: subject + maxLength: 72 + submit: true + validate: @systemMethod:validateMessageSubject + } + } + submit: { + 3: [ + { + value: { subject: null } + action: @method:headerSubmit + } + ] + } + actionKeys: @reference: common.escToPrev + } + 1: { + mci: { + MT1: { + width: 79 + argName: message + mode: edit + } + } + + submit: { + *: [ { value: "message", action: "@method:editModeEscPressed" } ] + } + actionKeys: [ + { + keys: [ "escape" ] + viewId: 1 + } + ] + }, + 2: { + TLTL: { + mci: { + TL1: { + width: 5 + } + TL2: { + width: 4 + } + } + } + } + 3: { + HM: { + mci: { + HM1: { + // :TODO: clear + items: [ "save", "discard", "help" ] + } + } + submit: { + *: [ + { + value: { 1: 0 } + action: @method:editModeMenuSave + } + { + value: { 1: 1 } + action: @systemMethod:prevMenu + } + { + value: { 1: 2 } + action: @method:editModeMenuHelp + } + ] + } + actionKeys: [ + { + keys: [ "escape" ] + action: @method:editModeEscPressed + } + { + keys: [ "?" ] + action: @method:editModeMenuHelp + } + ] + } + } + } + } + + privateMailMenuInbox: { + module: msg_list + art: PRVMSGLIST + config: { + menuViewPost: messageAreaViewPost + messageAreaTag: private_mail + } + form: { + 0: { // main list + mci: { + VM1: { + focus: true + submit: true + argName: message + } + } + submit: { + *: [ + { + value: { message: null } + action: @method:selectMessage + } + ] + } + actionKeys: [ + { + keys: [ "escape", "q", "shift + q" ] + action: @systemMethod:prevMenu + } + { + keys: [ "delete", "d", "shift + d" ] + action: @method:deleteSelected + } + ] + } + 1: { // delete prompt form + submit: { + *: [ + { + value: { promptValue: 0 } + action: @method:deleteMessageYes + } + { + value: { promptValue: 1 } + action: @method:deleteMessageNo + } + ] + } + } + } + } + + } +} \ No newline at end of file diff --git a/misc/prompt_template.in.hjson b/misc/prompt_template.in.hjson index e5a50630..4e451a1f 100644 --- a/misc/prompt_template.in.hjson +++ b/misc/prompt_template.in.hjson @@ -1,6 +1,6 @@ { /* - ./\/\.' ENiGMA½ Prompt Configuration -/--/-------- - -- - + ./\/\.' ENiGMA½ Prompt Configuration -/--/-------- - -- - _____________________ _____ ____________________ __________\_ / \__ ____/\_ ____ \ /____/ / _____ __ \ / ______/ // /___jp! @@ -12,22 +12,23 @@ ------------------------------------------------------------------------------- - This configuration is in HJSON (http://hjson.org/) format. Strict to-spec + This configuration is in HJSON (http://hjson.org/) format. Strict to-spec JSON is also perfectly valid. Use 'hjson' from npm to convert to/from JSON. - + See http://hjson.org/ for more information and syntax. - If you haven't yet, copy the conents of this file to something like - sick_board_prompt.hjson. Point to it via config.hjson using the + If you haven't yet, copy the conents of this file to something like + sick_board_prompt.hjson. Point to it via config.hjson using the 'general.promptFile' key: - - general: { promptFile: "sick_board_prompt.hjson" } - + + general: { promptFile: "sick_board_prompt.hjson" } + */ // :TODO: this entire file needs cleaned up a LOT // :TODO: Convert all of this to HJSON prompts: { + /* userCredentials: { "art" : "usercred", "mci" : { @@ -58,20 +59,9 @@ } } }, + */ - logoffConfirmation: { - art: LOGPMPT - mci: { - TM1: { - argName: promptValue - items: [ "yes", "no" ] - focus: true - hotKeys: { Y: 0, N: 1 } - hotKeySubmit: true - } - } - } - + /* loginSequenceFlavorSelect: { art: LOGINSEL mci: { @@ -85,66 +75,8 @@ } } } + */ - loginGlobalNewScan: { - art: GNSPMPT - mci: { - TM1: { - argName: promptValue - items: [ "yes", "no" ] - focus: true - hotKeys: { Y: 0, N: 1 } - hotKeySubmit: true - } - } - } - - menuCommand: { - art: MNUPRMT - mci: { - TL1: { - // theme me! - } - ET2: { - argName: command - width: 20 - maxLength: 20 - submit: true - textStyle: upper - focus: true - } - } - }, - - messageMenuCommand: { - art: MSGPMPT - mci: { - TL1: { - // theme me! - } - ET2: { - argName: command - width: 20 - maxLength: 20 - submit: true - textStyle: upper - focus: true - } - } - }, - - deleteMessageFromListPrompt: { - art: MSGDELPMPT - mci: { - TM1: { - argName: promptValue - items: [ "yes", "no" ] - focus: true - hotKeys: { Y: 0, N: 1 } - hotKeySubmit: true - } - } - } "newAreaPostPrompt" : { "art" : "message_area_new_post", @@ -160,70 +92,14 @@ } }, - forgotPasswordPrompt: { - art: FORGOTPW - mci: { - ET1: { - argName: username - maxLength: @config:users.usernameMax - width: 32 - focus: true - } - } - actionKeys: [ - { - keys: [ "escape" ] - action: @systemMethod:prevMenu - } - ] - } - /////////////////////////////////////////////////////////////////////// // File Base Related /////////////////////////////////////////////////////////////////////// - fileMenuCommand: { - art: FILPMPT - mci: { - TL1: {} - ET2: { - argName: menuOption - width: 20 - maxLength: 20 - textStyle: upper - focus: true - } - } - } - fileBaseRateEntryPrompt: { - art: RATEFILE - mci: { - SM1: { - argName: rating - items: [ "-----", "*----", "**---", "***--", "****-", "*****" ] - } - } - - actionKeys: [ - { - keys: [ "escape" ] - action: @systemMethod:prevMenu - } - ] - } - - fileBaseTagEntryPrompt: { - art: TAGFILE - mci: { - ET1: { - argName: tags - } - } - } /////////////////////////////////////////////////////////////////////// // Standard / Required - // + // // Prompts in this section are considered "standard" and are required // to be present // @@ -271,7 +147,7 @@ /* see notes in menu_module.js also ...how to allow for this to come from the theme first??? - same as custom vc drawing/etc.? ... + same as custom vc drawing/etc.? ... { "theme" : { From ef826687b1e11b798651d83d7222ffea5f534703 Mon Sep 17 00:00:00 2001 From: Bryan Ashby Date: Sun, 5 Jul 2020 17:50:48 -0600 Subject: [PATCH 13/22] my @menu actionKey doesn't work #290 --- core/msg_list.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/core/msg_list.js b/core/msg_list.js index 380fc5e4..73ab4850 100644 --- a/core/msg_list.js +++ b/core/msg_list.js @@ -60,13 +60,14 @@ exports.getModule = class MessageListModule extends MessageAreaConfTempSwitcher( this.menuMethods = { selectMessage : (formData, extraArgs, cb) => { if(MciViewIds.allViews.msgList === formData.submitId) { - this.initialFocusIndex = formData.value.message; + this.initialFocusIndex = formData.value.messageIndex || + formData.value.message; // older deprecated arg name const modOpts = { extraArgs : { - messageAreaTag : this.getSelectedAreaTag(formData.value.message), + messageAreaTag : this.getSelectedAreaTag(this.initialFocusIndex), messageList : this.config.messageList, - messageIndex : formData.value.message, + messageIndex : this.initialFocusIndex, lastMessageNextExit : true, } }; @@ -107,7 +108,8 @@ exports.getModule = class MessageListModule extends MessageAreaConfTempSwitcher( if(MciViewIds.allViews.msgList != formData.submitId) { return cb(null); } - const messageIndex = _.get(formData, 'value.message'); + const messageIndex = formData.value.messageIndex || + formData.value.message; // older, deprecated arg name return this.promptDeleteMessageConfirm(messageIndex, cb); }, deleteMessageYes : (formData, extraArgs, cb) => { From f5f8b08a27e5cc8871c4e32aac85377144251c90 Mon Sep 17 00:00:00 2001 From: Bryan Ashby Date: Mon, 6 Jul 2020 17:55:53 -0600 Subject: [PATCH 14/22] argName: message -> messageIndex --- WHATSNEW.md | 1 + misc/menu_templates/login.in.hjson | 2 +- misc/menu_templates/message_base.in.hjson | 6 +++--- misc/menu_templates/private_mail.in.hjson | 4 ++-- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/WHATSNEW.md b/WHATSNEW.md index 5d204610..f1eed328 100644 --- a/WHATSNEW.md +++ b/WHATSNEW.md @@ -7,6 +7,7 @@ This document attempts to track **major** changes and additions in ENiGMA½. For * A full configuration revamp has taken place. Configuration files such as `config.hjson`, `menu.hjson`, and `theme.hjson` can now utilize includes via the `includes` directive, reference 'self' sections using `@reference:` and import environment variables with `@environment`. * An explicit prompt file previously specified by `general.promptFile` in `config.hjson` is no longer necessary. Instead, this now simply part of the `prompts` section in `menu.hjson`. The default setup still creates a separate prompt HJSON file, but it is `includes`ed in `menu.hjson`. * New `PV` ACS check for arbitrary user properties. See [ACS](/docs/configuration/acs.md) for details. +* The `message` arg used by `msg_list` has been deprecated. Please starting using `messageIndex` for this purpose. Support for `message` will be removed in the future. ## 0.0.11-beta * Upgraded from `alpha` to `beta` -- The software is far along and mature enough at this point! diff --git a/misc/menu_templates/login.in.hjson b/misc/menu_templates/login.in.hjson index bcee88e2..d16ace0c 100644 --- a/misc/menu_templates/login.in.hjson +++ b/misc/menu_templates/login.in.hjson @@ -372,7 +372,7 @@ VM1: { focus: true submit: true - argName: message + argName: messageIndex } TL6: { } } diff --git a/misc/menu_templates/message_base.in.hjson b/misc/menu_templates/message_base.in.hjson index a7bcac65..e5bfb822 100644 --- a/misc/menu_templates/message_base.in.hjson +++ b/misc/menu_templates/message_base.in.hjson @@ -245,7 +245,7 @@ VM1: { focus: true submit: true - argName: message + argName: messageIndex } } submit: { @@ -372,7 +372,7 @@ VM1: { focus: true submit: true - argName: message + argName: messageIndex } TL6: { // theme me! @@ -421,7 +421,7 @@ VM1: { focus: true submit: true - argName: message + argName: messageIndex } } submit: { diff --git a/misc/menu_templates/private_mail.in.hjson b/misc/menu_templates/private_mail.in.hjson index eeefb25d..0ebd2fa9 100644 --- a/misc/menu_templates/private_mail.in.hjson +++ b/misc/menu_templates/private_mail.in.hjson @@ -145,7 +145,7 @@ module: msg_list art: PRVMSGLIST config: { - menuViewPost: messageAreaViewPost + menuViewPost: messageBaseViewPost messageAreaTag: private_mail } form: { @@ -154,7 +154,7 @@ VM1: { focus: true submit: true - argName: message + argName: messageIndex } } submit: { From 51f3b0ffcea5e675a355fc0288275332860d6122 Mon Sep 17 00:00:00 2001 From: Bryan Ashby Date: Mon, 6 Jul 2020 17:59:34 -0600 Subject: [PATCH 15/22] Minor --- misc/menu_templates/main.in.hjson | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/misc/menu_templates/main.in.hjson b/misc/menu_templates/main.in.hjson index ac4b1771..c601fed1 100644 --- a/misc/menu_templates/main.in.hjson +++ b/misc/menu_templates/main.in.hjson @@ -72,9 +72,6 @@ } menus: { - /////////////////////////////////////////////////////////////////////// - // Main Menu - /////////////////////////////////////////////////////////////////////// mainMenu: { art: MMENU desc: Main Menu @@ -84,10 +81,6 @@ interrupt: realtime } submit: [ - { - value: { command: "MSG" } - action: @menu:nodeMessage - } { value: { command: "G" } action: @menu:fullLogoffSequence @@ -178,8 +171,8 @@ ] } { - value: 1 - action: @menu:mainMenu + value: { command: "MSG" } + action: @menu:nodeMessage } ] } From 189c42ebea3b10fe836263cab001b807e3c5863b Mon Sep 17 00:00:00 2001 From: Bryan Ashby Date: Mon, 6 Jul 2020 18:16:53 -0600 Subject: [PATCH 16/22] Doc updates --- UPGRADE.md | 25 +--- docs/configuration/creating-config.md | 2 +- docs/configuration/directory-structure.md | 8 +- docs/configuration/menu-hjson.md | 4 +- misc/prompt_template.in.hjson | 170 ---------------------- 5 files changed, 16 insertions(+), 193 deletions(-) delete mode 100644 misc/prompt_template.in.hjson diff --git a/UPGRADE.md b/UPGRADE.md index 3898a320..0bedeb2e 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -2,29 +2,17 @@ This document covers basic upgrade notes for major ENiGMA½ version updates. # Before Upgrading -* Always back up your system! +* Always back up your system! (See [Administration](/docs/admin/administration.md)) * Seriously, always back up your system! -* At least back up the `db` directory and your `menu.hjson` (or renamed equivalent) # General Notes ## Configuration File Updates -In general, look at the `menu_template.in.hjson`, and `config_template.in.hjson` as well as the default `luciano_blocktronics/theme.hjson` files when you update. These files may come with new sections you wish to merge into your system! +In general, look at template menu files in `misc/menu_templates`, and `config_template.in.hjson` as well as the default `luciano_blocktronics/theme.hjson` files when you update. These files may come with new sections you wish to merge into your system! -### menu.hjson -Upgrades often come with changes to the default `menu_template.in.hjson`. It is wise to use a *different* file name for your BBS's version of this file and point to it via `config.hjson`. For example: - -```hjson -general: { - menuFile: my_bbs.hjson -} -``` - -After updating code, use a program such as DiffMerge to merge in updates to -`my_bbs.hjson` from the shipping `menu.hjson`. - -### theme.hjson -Any custom themes you have created may now be missing features as well. Take a look at the default `luciano_blocktronics/theme.hjson` file. You can use missing sections in your `theme.hjson` (which will generally correspond to sections you've also merged in to your `menu.hjson`). +### Menus & Theme Updates +Upgrades often come with changes to the default menu templates found in `misc/menu_tempaltes`. You can use these as references for changes and additions to the default menu sets. This also applies to the default `luciano_blocktronics` theme and it's `theme.hjson` file. +See [Updating](/docs/admin/updating.md) for details on menu files/etc. # Upgrading the Code Upgrading from GitHub is easy: @@ -33,7 +21,7 @@ Upgrading from GitHub is easy: cd /path/to/enigma-bbs git pull rm -rf npm_modules # do this any time you update Node.js itself -npm install +npm install # or simply 'yarn' ``` # Problems @@ -42,6 +30,7 @@ Report your issue on Xibalba BBS, hop in #enigma-bbs on FreeNode and chat, or # 0.0.11-beta to 0.0.12-beta * Be aware that `master` is now mainline! This means all `git pull`'s will yield the latest version. See [WHATSNEW](WHATSNEW.md) for more information. +* There is no longer a `prompt.hjson` file. Prompts are simply part of the menu set in the `prompts` section. # 0.0.10-alpha to 0.0.11-beta * Node.js 12.x LTS is now in use. Follow standard Node.js upgrade procedures (e.g.: `nvm install 12 && nvm use 12`). diff --git a/docs/configuration/creating-config.md b/docs/configuration/creating-config.md index 068ad5fa..432752b5 100644 --- a/docs/configuration/creating-config.md +++ b/docs/configuration/creating-config.md @@ -10,5 +10,5 @@ Your initial configuration skeleton can be created using the `oputil.js` command ./oputil.js config new ``` -You will be asked a series of questions to create an initial configuration, which will be saved to `/enigma-bbs-install-path/config/config.hjson`. This will also produce `config/-menu.hjson` and `config/-prompt.hjson` files (where `` is replaced by the name you provided in the steps above). See [Menu HJSON](menu-hjson.md) for more information. +You will be asked a series of questions to create an initial configuration, which will be saved to `/enigma-bbs-install-path/config/config.hjson`. This will also produce menu files under `config/menus/`. See [Menu HJSON](menu-hjson.md) for more information. diff --git a/docs/configuration/directory-structure.md b/docs/configuration/directory-structure.md index d968df17..e139be80 100644 --- a/docs/configuration/directory-structure.md +++ b/docs/configuration/directory-structure.md @@ -2,14 +2,16 @@ layout: page title: Directory Structure --- -All paths mentioned here are relative to the ENiGMA½ checkout directory. +All paths mentioned here are relative to the ENiGMA½ checkout directory. | Directory | Description | |---------------------|-----------------------------------------------------------------------------------------------------------| | `/art/general` | Non-theme art - welcome ANSI, logoff ANSI, etc. See [General Art]({{ site.baseurl }}{% link art/general.md %}). | `/art/themes` | Theme art. Themes should be in their own subdirectory and contain a theme.hjson. See [Themes]({{ site.baseurl }}{% link art/themes.md %}). -| `/config` | config.hjson, [menu.hjson]({{ site.baseurl }}{% link configuration/menu-hjson.md %}) and prompt.hjson storage. Also default path for SSL certs and public/private keys -| `/db` | All ENiGMA½ databases in Sqlite3 format +| `/config` | [config.hjson](config-hjson.md) system configuration. +| `/config/menus` | [menu.hjson](menu-hjson.md)storage. +| `/config/security` | D path for SSL certs and public/private keys. +| `/db` | All ENiGMA½ databases in Sqlite3 format. | `/docs` | These docs ;-) | `/dropfiles` | Dropfiles created for [local doors]({{ site.baseurl }}{% link modding/local-doors.md %}) | `/logs` | Logs. See [Monitoring Logs]({{ site.baseurl }}{% link troubleshooting/monitoring-logs.md %}) diff --git a/docs/configuration/menu-hjson.md b/docs/configuration/menu-hjson.md index d8d21af8..898fc315 100644 --- a/docs/configuration/menu-hjson.md +++ b/docs/configuration/menu-hjson.md @@ -3,7 +3,7 @@ layout: page title: Menu HSJON --- ## Menu HJSON -The core of a ENiGMA½ based BBS is `menu.hjson`. Note that when `menu.hjson` is referenced, we're actually talking about `config/yourboardname-menu.hjson` or similar. This file determines the menus (or screens) a user can see, the order they come in and how they interact with each other, ACS configuration, etc. Like all configuration within ENiGMA½, menu configuration is done in [HJSON](https://hjson.org/) format. See [HJSON General Information](hjson.md) for more information. +The core of a ENiGMA½ based BBS is `menu.hjson`. Note that when `menu.hjson` is referenced, we're actually talking about `config/menus/yourboardname-*.hjson`. These files determines the menus (or screens) a user can see, the order they come in and how they interact with each other, ACS configuration, etc. Like all configuration within ENiGMA½, menu configuration is done in [HJSON](https://hjson.org/) format. See [HJSON General Information](hjson.md) for more information. Entries in `menu.hjson` are often referred to as *blocks* or *sections*. Each entry defines a menu. A menu in this sense is something the user can see or visit. Examples include but are not limited to: @@ -13,6 +13,8 @@ Entries in `menu.hjson` are often referred to as *blocks* or *sections*. Each en Menu entries live under the `menus` section of `menu.hjson`. The *key* for a menu is it's name that can be referenced by other menus and areas of the system. +:information_source: Remember that the top level menu may include additional files using the `includes` directive. See [Configuration Files](config-files.md) for more information on this. + ## Common Menu Entry Members Below is a table of **common** menu entry members. These members apply to most entries, though entries that are backed by a specialized module (ie: `module: bbs_list`) may differ. See documentation for the module in question for particulars. diff --git a/misc/prompt_template.in.hjson b/misc/prompt_template.in.hjson deleted file mode 100644 index 4e451a1f..00000000 --- a/misc/prompt_template.in.hjson +++ /dev/null @@ -1,170 +0,0 @@ -{ - /* - ./\/\.' ENiGMA½ Prompt Configuration -/--/-------- - -- - - - _____________________ _____ ____________________ __________\_ / - \__ ____/\_ ____ \ /____/ / _____ __ \ / ______/ // /___jp! - // __|___// | \// |// | \// | | \// \ /___ /_____ - /____ _____| __________ ___|__| ____| \ / _____ \ - ---- \______\ -- |______\ ------ /______/ ---- |______\ - |______\ /__/ // ___/ - /__ _\ - <*> ENiGMA½ // HTTPS://GITHUB.COM/NUSKOOLER/ENIGMA-BBS <*> /__/ - - ------------------------------------------------------------------------------- - - This configuration is in HJSON (http://hjson.org/) format. Strict to-spec - JSON is also perfectly valid. Use 'hjson' from npm to convert to/from JSON. - - See http://hjson.org/ for more information and syntax. - - - If you haven't yet, copy the conents of this file to something like - sick_board_prompt.hjson. Point to it via config.hjson using the - 'general.promptFile' key: - - general: { promptFile: "sick_board_prompt.hjson" } - - */ - // :TODO: this entire file needs cleaned up a LOT - // :TODO: Convert all of this to HJSON - prompts: { - /* - userCredentials: { - "art" : "usercred", - "mci" : { - "ET1" : { - "argName" : "username", - "maxLength" : "@config:users.usernameMax" - }, - "ET2" : { - "submit" : true, - "argName" : "password", - "password" : true, - "maxLength" : "@config:users.passwordMax" - } - } - }, - "userLoginCredentials" : { - "art" : "USRCRED", - "mci" : { - "ET1" : { - "argName" : "username", - "maxLength" : "@config:users.usernameMax" - }, - "ET2" : { - "submit" : true, - "argName" : "password", - "password" : true, - "maxLength" : "@config:users.passwordMax" - } - } - }, - */ - - /* - loginSequenceFlavorSelect: { - art: LOGINSEL - mci: { - TM1: { - argName: promptValue - items: [ "yes", "no" ] - focus: true - focusItemIndex: 1 - hotKeys: { Y: 0, N: 1 } - hotKeySubmit: true - } - } - } - */ - - - "newAreaPostPrompt" : { - "art" : "message_area_new_post", - "mci" : { - "ET1" : { - "argName" : "to", - "width" : 20 - }, - "ET2" : { - "argName" : "subject", - "width" : 20 - } - } - }, - - /////////////////////////////////////////////////////////////////////// - // File Base Related - /////////////////////////////////////////////////////////////////////// - - - /////////////////////////////////////////////////////////////////////// - // Standard / Required - // - // Prompts in this section are considered "standard" and are required - // to be present - // - /////////////////////////////////////////////////////////////////////// - pause: { - // - // Any menu 'pause' will use this prompt - // - art: pause - config: { - trailingLF: no - } - /* - "mci" : { - // :TODO: Need special pause for a key MCI - // e.g. %PA -> themed prompt - } - - ...or maybe pause should just be special: - { - ... - "pause" true - // uses theme pause which can be art/inline/etc. - - } - - ... better, a special prompt - - GetKeyView - * echoKey : false - - */ - } - /*, - "standard" : { - // any menu 'pause' will display this, pause for a key, then erase and move on - "pause" : { - "art" : "pause" - // :TODO: support mci mappings - } - }, - "custom" : { - - }*/ - /* - see notes in menu_module.js also - ...how to allow for this to come from the theme first??? - same as custom vc drawing/etc.? ... - - { - "theme" : { - "inlineArt" : { - "something" : "%MC and |01Pipe codes here" - } - } - } - - "pause" : { - "art" : "@inline:simplePrompt", - // support pipe codes & MCI - "simplePrompt" : "--------/ Pause /----------------", - "mci" : { - - } - } - */ - } -} From 99df4f284f737bc9bc6c5fc6c8262eb83a4057f4 Mon Sep 17 00:00:00 2001 From: Bryan Ashby Date: Mon, 6 Jul 2020 18:36:21 -0600 Subject: [PATCH 17/22] Doc updates on prompts --- WHATSNEW.md | 2 +- docs/configuration/menu-hjson.md | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/WHATSNEW.md b/WHATSNEW.md index f1eed328..acef4338 100644 --- a/WHATSNEW.md +++ b/WHATSNEW.md @@ -5,7 +5,7 @@ This document attempts to track **major** changes and additions in ENiGMA½. For * The `master` branch has become mainline. What this means to users is `git pull` will always give you the latest and greatest. Make sure to read [Updating](/docs/admin/updating.md) and keep an eye on `WHATSNEW.md` (this file) and [UPGRADE](UPGRADE.md)! See also [ticket #276](https://github.com/NuSkooler/enigma-bbs/issues/276). * The default configuration has been moved to [config_default.js](/core/config_default.js). * A full configuration revamp has taken place. Configuration files such as `config.hjson`, `menu.hjson`, and `theme.hjson` can now utilize includes via the `includes` directive, reference 'self' sections using `@reference:` and import environment variables with `@environment`. -* An explicit prompt file previously specified by `general.promptFile` in `config.hjson` is no longer necessary. Instead, this now simply part of the `prompts` section in `menu.hjson`. The default setup still creates a separate prompt HJSON file, but it is `includes`ed in `menu.hjson`. +* An explicit prompt file previously specified by `general.promptFile` in `config.hjson` is no longer necessary. Instead, this now simply part of the `prompts` section in `menu.hjson`. The default setup still creates a separate prompt HJSON file, but it is `includes`ed in `menu.hjson`. With the removal of prompts the `PromptsChanged` event will no longer be fired. * New `PV` ACS check for arbitrary user properties. See [ACS](/docs/configuration/acs.md) for details. * The `message` arg used by `msg_list` has been deprecated. Please starting using `messageIndex` for this purpose. Support for `message` will be removed in the future. diff --git a/docs/configuration/menu-hjson.md b/docs/configuration/menu-hjson.md index 898fc315..886fba7f 100644 --- a/docs/configuration/menu-hjson.md +++ b/docs/configuration/menu-hjson.md @@ -186,7 +186,9 @@ In the above entry, you'll notice `form`. This defines a form(s) object. In this * Upon submit, the first match will be executed. For example, if the user selects "login", the first entry with a value of `{ matrixSubmit: 0 }` will match (due to 0 being the first index in the list and `matrixSubmit` being the arg name in question) causing `action` of `@menu:login` to be executed (go to `login` menu). ## Prompts -TODO: describe the "prompts" section, default setup, etc. +Prompts are found in the `prompts` section of menu files. Prompts allow for quick user input and shorthand form requirements for menus. Additionally, prompts are often used for for multiple menus. Consider a pause prompt or menu command input for example. + +TODO: additional prompt docs ## ACS Checks Menu modules can check user ACS in order to restrict areas and perform flow control. See [ACS](acs.md) for available ACS syntax. From 9d8b43b605c8f3d89bb5f98f3468f99b4719b33b Mon Sep 17 00:00:00 2001 From: Bryan Ashby Date: Mon, 6 Jul 2020 18:49:21 -0600 Subject: [PATCH 18/22] Formatting --- misc/menu_templates/main.in.hjson | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/misc/menu_templates/main.in.hjson b/misc/menu_templates/main.in.hjson index c601fed1..cacb18ee 100644 --- a/misc/menu_templates/main.in.hjson +++ b/misc/menu_templates/main.in.hjson @@ -517,11 +517,11 @@ module: msg_area_post_fse config: { art: { - header: MSGEHDR - body: MSGBODY - footerEditor: MSGEFTR - footerEditorMenu: MSGEMFT - help: MSGEHLP + header: MSGEHDR + body: MSGBODY + footerEditor: MSGEFTR + footerEditorMenu: MSGEMFT + help: MSGEHLP }, editorMode: edit editorType: email From c91ae50c6bee76bb79911de6399b9f49c4a2cbfd Mon Sep 17 00:00:00 2001 From: Bryan Ashby Date: Mon, 6 Jul 2020 19:13:22 -0600 Subject: [PATCH 19/22] Fix oputil --- core/config.js | 13 +++++++++---- core/config_loader.js | 4 ++++ core/oputil/oputil_common.js | 2 +- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/core/config.js b/core/config.js index 791845b8..788514ae 100644 --- a/core/config.js +++ b/core/config.js @@ -12,7 +12,12 @@ exports.Config = class Config extends ConfigLoader { super(options); } - static create(baseConfigPath, cb) { + static create(baseConfigPath, options, cb) { + if (!cb && _.isFunction(options)) { + cb = options; + options = {}; + } + const replacePaths = [ 'loginServers.ssh.algorithms.kex', 'loginServers.ssh.algorithms.cipher', @@ -24,7 +29,7 @@ exports.Config = class Config extends ConfigLoader { 'args', 'sendArgs', 'recvArgs', 'recvArgsNonBatch', ]; - const options = { + const configOptions = Object.assign({}, options, { defaultConfig : DefaultConfig, defaultsCustomizer : (defaultVal, configVal, key, path) => { if (Array.isArray(defaultVal) && Array.isArray(configVal)) { @@ -43,9 +48,9 @@ exports.Config = class Config extends ConfigLoader { Events.emit(Events.getSystemEvents().ConfigChanged); } }, - }; + }); - systemConfigInstance = new Config(options); + systemConfigInstance = new Config(configOptions); systemConfigInstance.init(baseConfigPath, err => { if (err) { console.stdout(`Configuration ${baseConfigPath} error: ${err.message}`); // eslint-disable-line no-console diff --git a/core/config_loader.js b/core/config_loader.js index 768cbe1d..29c2ab58 100644 --- a/core/config_loader.js +++ b/core/config_loader.js @@ -13,12 +13,14 @@ module.exports = class ConfigLoader { defaultConfig = {}, defaultsCustomizer = null, onReload = null, + keepWsc = false, } = { hotReload : true, defaultConfig : {}, defaultsCustomizer : null, onReload : null, + keepWsc : false, } ) { @@ -28,6 +30,7 @@ module.exports = class ConfigLoader { this.defaultConfig = defaultConfig; this.defaultsCustomizer = defaultsCustomizer; this.onReload = onReload; + this.keepWsc = keepWsc; } init(baseConfigPath, cb) { @@ -176,6 +179,7 @@ module.exports = class ConfigLoader { const options = { filePath, hotReload : this.hotReload, + keepWsc : this.keepWsc, callback : this._configFileChanged.bind(this), }; diff --git a/core/oputil/oputil_common.js b/core/oputil/oputil_common.js index ff6e348b..72b6f14b 100644 --- a/core/oputil/oputil_common.js +++ b/core/oputil/oputil_common.js @@ -71,7 +71,7 @@ function getConfigPath() { function initConfig(cb) { const configPath = getConfigPath(); - config.init(configPath, { keepWsc : true, hotReload : false }, cb); + config.Config.create(configPath, { keepWsc : true, hotReload : false }, cb); } function initConfigAndDatabases(cb) { From f4ccc998f52f94be96648276dca00ff310738254 Mon Sep 17 00:00:00 2001 From: Bryan Ashby Date: Mon, 6 Jul 2020 19:23:13 -0600 Subject: [PATCH 20/22] Fix theme slightly --- art/themes/luciano_blocktronics/theme.hjson | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/art/themes/luciano_blocktronics/theme.hjson b/art/themes/luciano_blocktronics/theme.hjson index 4045a549..f5dbbe30 100644 --- a/art/themes/luciano_blocktronics/theme.hjson +++ b/art/themes/luciano_blocktronics/theme.hjson @@ -255,8 +255,8 @@ VM1: { height: 14 width: 70 - itemFormat: "|00|15{msgNum:>4} |03{subject:<28.27} |11{fromUserName:<20.20} |03{ts} |15{newIndicator}" - focusItemFormat: "|00|19|15{msgNum:>4} {subject:<28.27} {fromUserName:<20.20} {ts} {newIndicator}" + itemFormat: "|00|15{msgNum:>4} |03{subject:<28.27} |11{fromUserName:<20.20} |03{ts:<15.16} |15{newIndicator}" + focusItemFormat: "|00|19|15{msgNum:>4} {subject:<28.27} {fromUserName:<20.20} {ts:<15.16} {newIndicator}" } } } From 60a1f14f6ef0d290872c41319e9caf7c1ff864b5 Mon Sep 17 00:00:00 2001 From: Bryan Ashby Date: Mon, 6 Jul 2020 21:02:18 -0600 Subject: [PATCH 21/22] Better 'config new' and fix a couple menu refs --- core/msg_list.js | 9 +++--- core/oputil/oputil_config.js | 34 +++++++++++------------ misc/menu_templates/login.in.hjson | 4 +-- misc/menu_templates/main.in.hjson | 2 +- misc/menu_templates/message_base.in.hjson | 4 +-- misc/menu_templates/private_mail.in.hjson | 4 +-- 6 files changed, 29 insertions(+), 28 deletions(-) diff --git a/core/msg_list.js b/core/msg_list.js index 73ab4850..8b91585b 100644 --- a/core/msg_list.js +++ b/core/msg_list.js @@ -60,8 +60,8 @@ exports.getModule = class MessageListModule extends MessageAreaConfTempSwitcher( this.menuMethods = { selectMessage : (formData, extraArgs, cb) => { if(MciViewIds.allViews.msgList === formData.submitId) { - this.initialFocusIndex = formData.value.messageIndex || - formData.value.message; // older deprecated arg name + // 'messageIndex' or older deprecated 'message' member + this.initialFocusIndex = _.get(formData, 'value.messageIndex', formData.value.message); const modOpts = { extraArgs : { @@ -108,8 +108,9 @@ exports.getModule = class MessageListModule extends MessageAreaConfTempSwitcher( if(MciViewIds.allViews.msgList != formData.submitId) { return cb(null); } - const messageIndex = formData.value.messageIndex || - formData.value.message; // older, deprecated arg name + + // newer 'messageIndex' or older deprecated value + const messageIndex = _.get(formData, 'value.messageIndex', formData.value.message); return this.promptDeleteMessageConfirm(messageIndex, cb); }, deleteMessageYes : (formData, extraArgs, cb) => { diff --git a/core/oputil/oputil_config.js b/core/oputil/oputil_config.js index 28c065d4..b1490c28 100644 --- a/core/oputil/oputil_config.js +++ b/core/oputil/oputil_config.js @@ -231,11 +231,8 @@ function buildNewConfig() { .replace(/[^a-z0-9_-]/ig, '_') .replace(/_+/g, '_') .toLowerCase(); - const menuFile = `menus/${boardName}-main.hjson`; - const mainTemplate = hjson.rt.parse(fs.readFileSync(paths.join(__dirname, '../../misc/menu_templates/main.in.hjson'), 'utf8')); - - const includeFiles = [ + const includeFilesIn = [ 'message_base.in.hjson', 'private_mail.in.hjson', 'login.in.hjson', @@ -244,8 +241,11 @@ function buildNewConfig() { 'file_base.in.hjson', ]; - includeFiles.forEach(incFile => { + let includeFiles = []; + includeFilesIn.forEach(incFile => { const outName = `${boardName}-${incFile.replace('.in', '')}`; + includeFiles.push(outName); + copyFileSyncSilent( paths.join(__dirname, '../../misc/menu_templates', incFile), paths.join(__dirname, '../../config/menus', outName), @@ -253,21 +253,21 @@ function buildNewConfig() { ); }); - mainTemplate.includes = includeFiles.map(incFile => { - return `${boardName}-${incFile.replace('.in', '')}`; - }); + // We really only need includes to be replaced + const mainTemplate = fs.readFileSync(paths.join(__dirname, '../../misc/menu_templates/main.in.hjson'), 'utf8') + .replace(/%INCLUDE_FILES%/g, includeFiles.join('\n\t\t')); // cheesy, but works! - if (writeConfig( + const menuFile = `${boardName}-main.hjson`; + fs.writeFileSync( + paths.join(__dirname, '../../config/menus', menuFile), mainTemplate, - paths.join(__dirname, '../../config/menus', `${boardName}-main.hjson`))) - { - config.general.menuFile = menuFile; + 'utf8' + ); - if(writeConfig(config, configPath)) { - console.info('Configuration generated'); - } else { - console.error('Failed writing configuration'); - } + config.general.menuFile = paths.join(__dirname, '../../config/menus/', menuFile); + + if(writeConfig(config, configPath)) { + console.info('Configuration generated'); } else { console.error('Failed writing configuration'); } diff --git a/misc/menu_templates/login.in.hjson b/misc/menu_templates/login.in.hjson index d16ace0c..c3fc5340 100644 --- a/misc/menu_templates/login.in.hjson +++ b/misc/menu_templates/login.in.hjson @@ -364,7 +364,7 @@ module: msg_list art: NEWMSGS config: { - menuViewPost: messageBaseViewPost + menuViewPost: messageAreaViewPost } form: { 0: { @@ -379,7 +379,7 @@ submit: { *: [ { - value: { message: null } + value: { messageIndex: null } action: @method:selectMessage } ] diff --git a/misc/menu_templates/main.in.hjson b/misc/menu_templates/main.in.hjson index cacb18ee..f2caef56 100644 --- a/misc/menu_templates/main.in.hjson +++ b/misc/menu_templates/main.in.hjson @@ -51,7 +51,7 @@ // You may include as many additional fragments as you like here. includes: [ - XXXXXXXX + %INCLUDE_FILES% ] // This section creates common fragments to use as @reference diff --git a/misc/menu_templates/message_base.in.hjson b/misc/menu_templates/message_base.in.hjson index e5bfb822..fd4adf97 100644 --- a/misc/menu_templates/message_base.in.hjson +++ b/misc/menu_templates/message_base.in.hjson @@ -381,7 +381,7 @@ submit: { *: [ { - value: { message: null } + value: { messageIndex: null } action: @method:selectMessage } ] @@ -427,7 +427,7 @@ submit: { *: [ { - value: { message: null } + value: { messageIndex: null } action: @method:selectMessage } ] diff --git a/misc/menu_templates/private_mail.in.hjson b/misc/menu_templates/private_mail.in.hjson index 0ebd2fa9..ebf4d104 100644 --- a/misc/menu_templates/private_mail.in.hjson +++ b/misc/menu_templates/private_mail.in.hjson @@ -145,7 +145,7 @@ module: msg_list art: PRVMSGLIST config: { - menuViewPost: messageBaseViewPost + menuViewPost: messageAreaViewPost messageAreaTag: private_mail } form: { @@ -160,7 +160,7 @@ submit: { *: [ { - value: { message: null } + value: { messageIndex: null } action: @method:selectMessage } ] From 992ee6056e78e75e0a190f714d5551a31501dfbd Mon Sep 17 00:00:00 2001 From: Bryan Ashby Date: Mon, 6 Jul 2020 21:14:31 -0600 Subject: [PATCH 22/22] Log if a variable isn't found --- core/config_loader.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/config_loader.js b/core/config_loader.js index 29c2ab58..47b3d4d4 100644 --- a/core/config_loader.js +++ b/core/config_loader.js @@ -161,7 +161,8 @@ module.exports = class ConfigLoader { let value = process.env[varName]; if (!value) { - return; + // console is about as good as we can do here + return console.info(`WARNING: environment variable "${varName}" from spec "${spec}" not found!`); } if ('array' === array) {