enigma-bbs/misc/menu_template.in.hjson

4370 lines
147 KiB
Plaintext

{
/*
./\/\.' 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: 1
action: @menu:messageArea
}
]
}
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
}
]
}
}
}
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"
}
]
}
}
}
}
}
}