{ /* ./\/\.' 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 // :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 // :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 } 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 } 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 } 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" } ] } } } } } }