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

Merge branch 'ddfilelister_loadable_module_support' into 'master'

ddfilelister: Now supports being used as a loadable module for Scan Dirs and List Files (applicable for Synchronet 3.20+)

See merge request !260
parents d1d49e99 cc2a757a
No related branches found
No related tags found
2 merge requests!463MRC mods by Codefenix (2024-10-20),!260ddfilelister: Now supports being used as a loadable module for Scan Dirs and List Files (applicable for Synchronet 3.20+)
Pipeline #3868 passed
...@@ -58,6 +58,9 @@ ...@@ -58,6 +58,9 @@
* scrolls through the file list/search results. Also, * scrolls through the file list/search results. Also,
* used lfexpand() to ensure the extended description has * used lfexpand() to ensure the extended description has
* CRLF endings, useful for splitting it into multiple lines properly. * CRLF endings, useful for splitting it into multiple lines properly.
* 2023-02-25 Eric Oulashin Version 2.09
* Now supports being used as a loadable module for
* Scan Dirs and List Files
*/ */
"use strict"; "use strict";
...@@ -84,39 +87,42 @@ else ...@@ -84,39 +87,42 @@ else
} }
// If the user's terminal doesn't support ANSI, then just call the standard Synchronet /*
// file list function and exit now Configured in SCFG->System->Loadable Modules:
if (!console.term_supports(USER_ANSI)) Scan Dirs: User scans one or more directories for (e.g. new) files
{ List Files: User lists files within a file directory
bbs.list_files(); View File Info: User views detailed information on files in a directory
exit();
}
This addresses/fixes feature request #521 for Nightfox
Will need to document the mode argument bit values on the wiki, but
it's the usual suspects: FL_* for scandirs and listfiles and FI_* for
fileinfo. The scandirs_mod will be passed an extra bool (0/1) arg that
indicates whether or not the user is scanning *all* directories.
*/
// This script requires Synchronet version 3.19 or higher. // This script requires Synchronet version 3.19 or newer.
// If the Synchronet version is below the minimum, then just call the standard // If the Synchronet version is below the minimum, then exit.
// Synchronet file list and exit.
if (system.version_num < 31900) if (system.version_num < 31900)
{ {
if (user.is_sysop) if (user.is_sysop)
{ {
var message = "\x01n\x01h\x01y\x01i* Warning:\x01n\x01h\x01w Digital Distortion File Lister " var message = "\x01n\x01h\x01y\x01i* Warning:\x01n\x01h\x01w Digital Distortion File Lister "
+ "requires version \x01g3.19\x01w or\r\n" + "requires version \x01g3.19\x01w or\r\n"
+ "higher of Synchronet. This BBS is using version \x01g" + system.version + "newer of Synchronet. This BBS is using version \x01g" + system.version
+ "\x01w.\x01n"; + "\x01w.\x01n";
console.crlf(); console.crlf();
console.print(message); console.print(message);
console.crlf(); console.crlf();
console.pause(); console.pause();
} }
bbs.list_files();
exit(); exit();
} }
// Lister version information // Lister version information
var LISTER_VERSION = "2.08"; var LISTER_VERSION = "2.09";
var LISTER_DATE = "2023-01-18"; var LISTER_DATE = "2023-02-25";
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
...@@ -194,13 +200,21 @@ var FILE_MOVE = 6; // Sysop action ...@@ -194,13 +200,21 @@ var FILE_MOVE = 6; // Sysop action
var FILE_DELETE = 7; // Sysop action var FILE_DELETE = 7; // Sysop action
// Search/list modes // Search/list modes
var MODE_LIST_CURDIR = 1; var MODE_LIST_DIR = 1;
var MODE_SEARCH_FILENAME = 2; var MODE_SEARCH_FILENAME = 2;
var MODE_SEARCH_DESCRIPTION = 3; var MODE_SEARCH_DESCRIPTION = 3;
var MODE_NEW_FILE_SEARCH = 4; var MODE_NEW_FILE_SEARCH = 4;
// Sort orders (not included in FileBase.SORT)
var SORT_FL_ULTIME = 50; // Sort by upload time
var SORT_FL_DLTIME = 51; // Sort by download time
// The searc/list mode for the current run // The searc/list mode for the current run
var gScriptMode = MODE_LIST_CURDIR; // Default var gScriptMode = MODE_LIST_DIR; // Default
var gListBehavior = FL_NONE; // From sbbsdefs.js
// The directory internal code to list
var gDirCode = bbs.curdir_code;
...@@ -222,17 +236,38 @@ var gPauseAfterViewingFile = true; ...@@ -222,17 +236,38 @@ var gPauseAfterViewingFile = true;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Script execution code // Script execution code
// The filename pattern to match
var gFilespec = "*";
// The sort order to use for the file list // The sort order to use for the file list
var gFileSortOrder = FileBase.SORT.NATURAL; // Natural sort order, same as DATE_A (import date ascending) var gFileSortOrder = FileBase.SORT.NATURAL; // Natural sort order, same as DATE_A (import date ascending)
var gSearchVerbose = false; var gSearchVerbose = false;
// When called as a lodable module, one of the options is to scan all dirs
var gScanAllDirs = false;
// Read the configuration file and set the settings // Read the configuration file and set the settings
readConfigFile(); readConfigFile();
// Parse command-line arguments (which sets program options) // Parse command-line arguments (which sets program options)
parseArgs(argv); parseArgs(argv);
// If the user's terminal doesn't support ANSI, then just call the standard Synchronet
// file list function and exit now
if (!console.term_supports(USER_ANSI))
{
var exitCode = 0;
if (gScriptMode == MODE_SEARCH_FILENAME || gScriptMode == MODE_SEARCH_DESCRIPTION || gScriptMode == MODE_NEW_FILE_SEARCH)
{
//if (user.is_sysop) console.print("\x01n\r\nScan dirs\r\n"); // Temporary
bbs.scan_dirs(gListBehavior, gScanAllDirs);
}
else
exitCode = bbs.list_files(gDirCode, gFilespec, gListBehavior);
exit(exitCode);
}
// This array will contain file metadata objects // This array will contain file metadata objects
var gFileList = []; var gFileList = [];
...@@ -249,8 +284,13 @@ if (gFileList.length == 0) ...@@ -249,8 +284,13 @@ if (gFileList.length == 0)
{ {
console.crlf(); console.crlf();
console.print("\x01n\x01c"); console.print("\x01n\x01c");
if (gScriptMode == MODE_LIST_CURDIR) if (gScriptMode == MODE_LIST_DIR)
console.print("There are no files in the current directory."); {
if (gFilespec == "*" || gFilespec == "*.*")
console.print("There are no files in the directory.");
else
console.print("No files in the directory were found matching " + gFilespec);
}
else else
console.print("No files were found."); console.print("No files were found.");
console.print("\x01n"); console.print("\x01n");
...@@ -262,6 +302,7 @@ if (gFileList.length == 0) ...@@ -262,6 +302,7 @@ if (gFileList.length == 0)
// Clear the screen and display the header lines // Clear the screen and display the header lines
console.clear("\x01n"); console.clear("\x01n");
if ((gListBehavior & FL_NO_HDR) != FL_NO_HDR)
displayFileLibAndDirHeader(); displayFileLibAndDirHeader();
// Construct and display the menu/command bar at the bottom of the screen // Construct and display the menu/command bar at the bottom of the screen
var fileMenuBar = new DDFileMenuBar({ x: 1, y: console.screen_rows }); var fileMenuBar = new DDFileMenuBar({ x: 1, y: console.screen_rows });
...@@ -321,6 +362,8 @@ while (continueDoingFileList) ...@@ -321,6 +362,8 @@ while (continueDoingFileList)
if (actionRetObj.exitNow) if (actionRetObj.exitNow)
continueDoingFileList = false; continueDoingFileList = false;
else else
{
if ((gListBehavior & FL_NO_HDR) != FL_NO_HDR)
{ {
if (actionRetObj.reDrawHeaderTextOnly) if (actionRetObj.reDrawHeaderTextOnly)
{ {
...@@ -333,6 +376,7 @@ while (continueDoingFileList) ...@@ -333,6 +376,7 @@ while (continueDoingFileList)
console.gotoxy(1, 1); console.gotoxy(1, 1);
displayFileLibAndDirHeader(); displayFileLibAndDirHeader();
} }
}
if (actionRetObj.reDrawCmdBar) // Could call fileMenuBar.constructPromptText(); if needed if (actionRetObj.reDrawCmdBar) // Could call fileMenuBar.constructPromptText(); if needed
fileMenuBar.writePromptLine(); fileMenuBar.writePromptLine();
var redrewPartOfFileListMenu = false; var redrewPartOfFileListMenu = false;
...@@ -537,8 +581,7 @@ function showFileInfo(pFileList, pFileListMenu) ...@@ -537,8 +581,7 @@ function showFileInfo(pFileList, pFileListMenu)
// extended information. Get a metadata object with extended information so we // extended information. Get a metadata object with extended information so we
// can display the extended description. // can display the extended description.
// The metadata object in pFileList should have a dirCode added by this script. // The metadata object in pFileList should have a dirCode added by this script.
// If not, assume the user's current directory. var dirCode = gDirCode;
var dirCode = bbs.curdir_code;
if (pFileList[pFileListMenu.selectedItemIdx].hasOwnProperty("dirCode")) if (pFileList[pFileListMenu.selectedItemIdx].hasOwnProperty("dirCode"))
dirCode = pFileList[pFileListMenu.selectedItemIdx].dirCode; dirCode = pFileList[pFileListMenu.selectedItemIdx].dirCode;
var fileMetadata = null; var fileMetadata = null;
...@@ -558,7 +601,7 @@ function showFileInfo(pFileList, pFileListMenu) ...@@ -558,7 +601,7 @@ function showFileInfo(pFileList, pFileListMenu)
// Note: File size can also be retrieved by calling a FileBase's get_size(fileMetadata.name) // Note: File size can also be retrieved by calling a FileBase's get_size(fileMetadata.name)
// TODO: Shouldn't need the max length here // TODO: Shouldn't need the max length here
fileInfoStr += "Size: " + gColors.fileSize + getFileSizeStr(fileMetadata.size, 99999) + "\x01n\x01w\r\n"; fileInfoStr += "Size: " + gColors.fileSize + getFileSizeStr(fileMetadata.size, 99999) + "\x01n\x01w\r\n";
fileInfoStr += "Timestamp: " + gColors.fileTimestamp + strftime("%Y-%m-%d %H:%M:%S", fileMetadata.time) + "\x01n\x01w\r\n" fileInfoStr += "Timestamp: " + gColors.fileTimestamp + strftime("%Y-%m-%d %H:%M:%S", fileMetadata.time) + "\x01n\x01w\r\n";
fileInfoStr += "\r\n"; fileInfoStr += "\r\n";
// File library/directory information // File library/directory information
...@@ -993,15 +1036,15 @@ function displayHelpScreen() ...@@ -993,15 +1036,15 @@ function displayHelpScreen()
console.crlf(); console.crlf();
// If listing files in a directory, display information about the current file directory. // If listing files in a directory, display information about the current file directory.
if (gScriptMode == MODE_LIST_CURDIR) if (gScriptMode == MODE_LIST_DIR)
{ {
var libIdx = file_area.dir[bbs.curdir_code].lib_index; var libIdx = file_area.dir[gDirCode].lib_index;
var dirIdx = file_area.dir[bbs.curdir_code].index; var dirIdx = file_area.dir[gDirCode].index;
console.print("\x01n\x01cCurrent file library: \x01g" + file_area.lib_list[libIdx].description); console.print("\x01n\x01cCurrent file library: \x01g" + file_area.lib_list[libIdx].description);
console.crlf(); console.crlf();
console.print("\x01cCurrent file directory: \x01g" + file_area.dir[bbs.curdir_code].description); console.print("\x01cCurrent file directory: \x01g" + file_area.dir[gDirCode].description);
console.crlf(); console.crlf();
console.print("\x01cThere are \x01g" + file_area.dir[bbs.curdir_code].files + " \x01cfiles in this directory."); console.print("\x01cThere are \x01g" + file_area.dir[gDirCode].files + " \x01cfiles in this directory.");
} }
else if (gScriptMode == MODE_SEARCH_FILENAME) else if (gScriptMode == MODE_SEARCH_FILENAME)
console.print("\x01n\x01cCurrently performing a filename search"); console.print("\x01n\x01cCurrently performing a filename search");
...@@ -1167,7 +1210,7 @@ function chooseFilebaseAndMoveFileToOtherFilebase(pFileList, pFileListMenu) ...@@ -1167,7 +1210,7 @@ function chooseFilebaseAndMoveFileToOtherFilebase(pFileList, pFileListMenu)
// If we're listing files in the user's current directory, then remove // If we're listing files in the user's current directory, then remove
// the file info object from the file list array. Otherwise, update // the file info object from the file list array. Otherwise, update
// the metadata object in the list. // the metadata object in the list.
if (gScriptMode == MODE_LIST_CURDIR) if (gScriptMode == MODE_LIST_DIR)
{ {
pFileList.splice(fileIdx, 1); pFileList.splice(fileIdx, 1);
// Subtract 1 from the remaining indexes in the fileIndexes array // Subtract 1 from the remaining indexes in the fileIndexes array
...@@ -1207,7 +1250,7 @@ function chooseFilebaseAndMoveFileToOtherFilebase(pFileList, pFileListMenu) ...@@ -1207,7 +1250,7 @@ function chooseFilebaseAndMoveFileToOtherFilebase(pFileList, pFileListMenu)
// set allSameDir to false so the header lines will now say "various". // set allSameDir to false so the header lines will now say "various".
// However, if not all files were in the same directory, check to see if they // However, if not all files were in the same directory, check to see if they
// are now, and if so, we'll need to re-draw the header lines. // are now, and if so, we'll need to re-draw the header lines.
if (gScriptMode != MODE_LIST_CURDIR && typeof(pFileList.allSameDir) == "boolean") if (gScriptMode != MODE_LIST_DIR && typeof(pFileList.allSameDir) == "boolean")
{ {
if (pFileList.allSameDir) if (pFileList.allSameDir)
{ {
...@@ -1235,7 +1278,7 @@ function chooseFilebaseAndMoveFileToOtherFilebase(pFileList, pFileListMenu) ...@@ -1235,7 +1278,7 @@ function chooseFilebaseAndMoveFileToOtherFilebase(pFileList, pFileListMenu)
} }
// After moving the files, if there are no more files (in the directory or otherwise), // After moving the files, if there are no more files (in the directory or otherwise),
// say so and exit now. // say so and exit now.
if (gScriptMode == MODE_LIST_CURDIR && file_area.dir[bbs.curdir_code].files == 0) if (gScriptMode == MODE_LIST_DIR && file_area.dir[gDirCode].files == 0)
{ {
displayMsg("There are no more files in the directory.", false); displayMsg("There are no more files in the directory.", false);
retObj.exitNow = true; retObj.exitNow = true;
...@@ -1354,7 +1397,7 @@ function confirmAndRemoveFilesFromFilebase(pFileList, pFileListMenu) ...@@ -1354,7 +1397,7 @@ function confirmAndRemoveFilesFromFilebase(pFileList, pFileListMenu)
} }
if (removeFileSucceeded) if (removeFileSucceeded)
{ {
if (gScriptMode == MODE_LIST_CURDIR) if (gScriptMode == MODE_LIST_DIR)
numFilesRemaining = filebase.files; numFilesRemaining = filebase.files;
} }
filebase.close(); filebase.close();
...@@ -1430,7 +1473,7 @@ function confirmAndRemoveFilesFromFilebase(pFileList, pFileListMenu) ...@@ -1430,7 +1473,7 @@ function confirmAndRemoveFilesFromFilebase(pFileList, pFileListMenu)
} }
else else
{ {
if (gScriptMode == MODE_LIST_CURDIR) if (gScriptMode == MODE_LIST_DIR)
displayMsg("The directory now has no files.", false, true); displayMsg("The directory now has no files.", false, true);
else else
displayMsg("There are no more files to show.", false, true); displayMsg("There are no more files to show.", false, true);
...@@ -1994,6 +2037,10 @@ function doFrameInputLoop(pFrame, pScrollbar, pFrameContentStr, pAdditionalQuitK ...@@ -1994,6 +2037,10 @@ function doFrameInputLoop(pFrame, pScrollbar, pFrameContentStr, pAdditionalQuitK
// pDirCodeOverride: Optional string: If this is valid, this will be used for the library & directory name // pDirCodeOverride: Optional string: If this is valid, this will be used for the library & directory name
function displayFileLibAndDirHeader(pTextOnly, pDirCodeOverride) function displayFileLibAndDirHeader(pTextOnly, pDirCodeOverride)
{ {
// If the behavior flags include no header, then just return immediately
if ((gListBehavior & FL_NO_HDR) == FL_NO_HDR)
return;
var textOnly = (typeof(pTextOnly) === "boolean" ? pTextOnly : false); var textOnly = (typeof(pTextOnly) === "boolean" ? pTextOnly : false);
// Determine if this is the first time this function has been called. If so, // Determine if this is the first time this function has been called. If so,
...@@ -2013,8 +2060,8 @@ function displayFileLibAndDirHeader(pTextOnly, pDirCodeOverride) ...@@ -2013,8 +2060,8 @@ function displayFileLibAndDirHeader(pTextOnly, pDirCodeOverride)
var libDesc = ""; var libDesc = "";
var dirDesc = ""; var dirDesc = "";
var dirCode = ""; var dirCode = "";
if (gScriptMode == MODE_LIST_CURDIR) if (gScriptMode == MODE_LIST_DIR)
dirCode = bbs.curdir_code; dirCode = gDirCode;
else if (typeof(gFileList.allSameDir) === "boolean" && gFileList.allSameDir && gFileList.length > 0) else if (typeof(gFileList.allSameDir) === "boolean" && gFileList.allSameDir && gFileList.length > 0)
dirCode = gFileList[0].dirCode; dirCode = gFileList[0].dirCode;
if (dirCode.length > 0) if (dirCode.length > 0)
...@@ -2182,11 +2229,14 @@ function createFileListMenu(pQuitKeys) ...@@ -2182,11 +2229,14 @@ function createFileListMenu(pQuitKeys)
// like a bit of a hack, but it works. // like a bit of a hack, but it works.
var allSameDir = (typeof(gFileList.allSameDir) === "boolean" ? gFileList.allSameDir : false); var allSameDir = (typeof(gFileList.allSameDir) === "boolean" ? gFileList.allSameDir : false);
if (isDoingFileSearch() && !allSameDir && gFileList[pIdx].dirCode != this.lastFileDirCode) if (isDoingFileSearch() && !allSameDir && gFileList[pIdx].dirCode != this.lastFileDirCode)
{
if ((gListBehavior & FL_NO_HDR) != FL_NO_HDR)
{ {
var originalCurPos = console.getxy(); var originalCurPos = console.getxy();
displayFileLibAndDirHeader(true, gFileList[pIdx].dirCode); displayFileLibAndDirHeader(true, gFileList[pIdx].dirCode);
console.gotoxy(originalCurPos); console.gotoxy(originalCurPos);
} }
}
this.lastFileDirCode = gFileList[pIdx].dirCode; this.lastFileDirCode = gFileList[pIdx].dirCode;
var menuItemObj = this.MakeItemWithRetval(pIdx); var menuItemObj = this.MakeItemWithRetval(pIdx);
...@@ -2945,6 +2995,10 @@ function readConfigFile() ...@@ -2945,6 +2995,10 @@ function readConfigFile()
gFileSortOrder = FileBase.SORT.DATE_A; gFileSortOrder = FileBase.SORT.DATE_A;
else if (valueUpper == "DATE_D") else if (valueUpper == "DATE_D")
gFileSortOrder = FileBase.SORT.DATE_D; gFileSortOrder = FileBase.SORT.DATE_D;
else if (valueUpper == "ULTIME")
gFileSortOrder = SORT_FL_ULTIME;
else if (valueUpper == "DLTIME")
gFileSortOrder = SORT_FL_DLTIME;
else // Default else // Default
gFileSortOrder = FileBase.SORT.NATURAL; gFileSortOrder = FileBase.SORT.NATURAL;
} }
...@@ -3131,41 +3185,50 @@ function shortenFilename(pFilename, pMaxLen, pFillWidth) ...@@ -3131,41 +3185,50 @@ function shortenFilename(pFilename, pMaxLen, pFillWidth)
// value will be a boolean. Otherwise, the value will be a string. // value will be a boolean. Otherwise, the value will be a string.
// //
// Parameters: // Parameters:
// pArgArr: An array of strings containing values in the format -arg=val // argv: An array of strings containing values in the format -arg=val
function parseArgs(pArgArr) //
// Return value: Boolean: Whether or not this script was run as a loadable
// module (depending on the arguments used).
function parseArgs(argv)
{ {
// Default program options // Default program options
gScriptMode = MODE_LIST_CURDIR; gScriptMode = MODE_LIST_DIR;
// Sanity checking for pArgArr - Make sure it's an array // Sanity checking for argv - Make sure it's an array
if ((typeof(pArgArr) != "object") || (typeof(pArgArr.length) != "number")) if ((typeof(argv) != "object") || (typeof(argv.length) != "number"))
return; return false;
// Go through pArgArr looking for strings in the format -arg=val and parse them // This script accepts arguments in -arg=val format; See if there are any of those.
// If so, process arguments with that assumption; otherwise, we'll check for args
// passed when Synchronet runs this as a loadable module.
var scriptRanAsLoadableModule = false;
var anySettingEqualsVal = false;
for (var i = 0; i < argv.length && !anySettingEqualsVal; ++i)
anySettingEqualsVal = (typeof(argv[i]) === "string" && argv[i].length > 0 && argv[i].charAt(0) == "-" && argv[i].indexOf("=") > 1);
if (anySettingEqualsVal)
{
// Go through argv looking for strings in the format -arg=val and parse them
// into objects in the argVals array. // into objects in the argVals array.
var equalsIdx = 0; var equalsIdx = 0;
var argName = ""; var argName = "";
var argVal = ""; var argVal = "";
var argValUpper = ""; // For case-insensitive matching var argValUpper = ""; // For case-insensitive matching
for (var i = 0; i < pArgArr.length; ++i) for (var i = 0; i < argv.length; ++i)
{ {
// We're looking for strings that start with "-", except strings that are // We're looking for strings that start with "-", except strings that are
// only "-". // only "-".
if ((typeof(pArgArr[i]) != "string") || (pArgArr[i].length == 0) || if (typeof(argv[i]) !== "string" || argv[i].length == 0 || argv[i].charAt(0) != "-" || argv[i] == "-")
(pArgArr[i].charAt(0) != "-") || (pArgArr[i] == "-"))
{
continue; continue;
}
// Look for an = and if found, split the string on the = // Look for an = and if found, split the string on the =
equalsIdx = pArgArr[i].indexOf("="); equalsIdx = argv[i].indexOf("=");
// If a = is found, then split on it and add the argument name & value // If a = is found, then split on it and add the argument name & value
// to the array. Otherwise (if the = is not found), then treat the // to the array. Otherwise (if the = is not found), then treat the
// argument as a boolean and set it to true (to enable an option). // argument as a boolean and set it to true (to enable an option).
if (equalsIdx > -1) if (equalsIdx > -1)
{ {
argName = pArgArr[i].substring(1, equalsIdx).toUpperCase(); argName = argv[i].substring(1, equalsIdx).toUpperCase();
argVal = pArgArr[i].substr(equalsIdx+1); argVal = argv[i].substr(equalsIdx+1);
argValUpper = argVal.toUpperCase(); argValUpper = argVal.toUpperCase();
if (argName === "MODE") if (argName === "MODE")
{ {
...@@ -3176,14 +3239,85 @@ function parseArgs(pArgArr) ...@@ -3176,14 +3239,85 @@ function parseArgs(pArgArr)
else if (argValUpper === "NEW_FILE_SEARCH") else if (argValUpper === "NEW_FILE_SEARCH")
gScriptMode = MODE_NEW_FILE_SEARCH; gScriptMode = MODE_NEW_FILE_SEARCH;
else if (argValUpper === "LIST_CURDIR") else if (argValUpper === "LIST_CURDIR")
gScriptMode = MODE_LIST_CURDIR; gScriptMode = MODE_LIST_DIR;
}
} }
// Nothing to do if an = was not found
} }
else // An equals sign (=) was not found. Add as a boolean set to true to enable the option. }
else
{ {
// Nothing to be done here for this script // Check for arguments as if this was run by Synchronet as a loadable module
// (for either Scan Dirs or List Files)
/*
// bbs.list_files() & bbs.scan_dirs()
//********************************************
var FL_NONE =0; // No special behavior
var FL_ULTIME =(1<<0); // List files by upload time
var FL_DLTIME =(1<<1); // List files by download time
var FL_NO_HDR =(1<<2); // Don't list directory header
var FL_FINDDESC =(1<<3); // Find text in description
var FL_EXFIND =(1<<4); // Find text in description - extended info
var FL_VIEW =(1<<5); // View ZIP/ARC/GIF etc. info
*/
// There must be either 2 or 3 arguments
if (argv.length < 2)
return false;
// The 2nd argument is the mode/behavior bits in either case
var FLBehavior = parseInt(argv[1]);
if (isNaN(FLBehavior))
return false;
else
gListBehavior = FLBehavior;
scriptRanAsLoadableModule = true;
// Default gScriptmode to MODE_LIST_DIR; for FLBehavior as FL_NONE, no special behavior
gScriptMode = MODE_LIST_DIR;
// 2 args - Scanning/searching
if (argv.length == 2)
{
// - 0: Bool (scanning all directories): 0/1
// - 1: FL_ mode value
gScanAllDirs = (argv[0] == "1");
if ((FLBehavior & FL_ULTIME) == FL_ULTIME)
gScriptMode = MODE_NEW_FILE_SEARCH;
else if ((FLBehavior & FL_FINDDESC) == FL_FINDDESC || (FLBehavior & FL_EXFIND) == FL_EXFIND)
gScriptMode = MODE_SEARCH_DESCRIPTION;
if ((FLBehavior & FL_VIEW) == FL_VIEW)
{
// View ZIP/ARC/GIF etc. info
// TODO: Not sure what to do with this
} }
} }
// 3 args - Listing
else if (argv.length >= 3) //==3
{
// - 0: Directory internal code
// - 1: FL_ mode value
// - 2: Filespec (i.e., *, *.zip, etc.)
if (!file_area.dir.hasOwnProperty(argv[0]))
return false;
gDirCode = argv[0];
gFilespec = argv[2];
if ((FLBehavior & FL_VIEW) == FL_VIEW)
{
// View ZIP/ARC/GIF etc. info
// TODO: Not sure what to do with this
}
}
// Options that apply to both searching and listing
if ((FLBehavior & FL_ULTIME) == FL_ULTIME)
gFileSortOrder = SORT_FL_ULTIME;
else if ((FLBehavior & FL_DLTIME) == FL_DLTIME)
gFileSortOrder = SORT_FL_DLTIME;
}
return scriptRanAsLoadableModule;
} }
// Populates the file list (gFileList). // Populates the file list (gFileList).
...@@ -3205,19 +3339,19 @@ function populateFileList(pSearchMode) ...@@ -3205,19 +3339,19 @@ function populateFileList(pSearchMode)
var allSameDir = true; var allSameDir = true;
// Do the things for list or search, depending on the specified mode // Do the things for list or search, depending on the specified mode
if (pSearchMode == MODE_LIST_CURDIR) // This is the default if (pSearchMode == MODE_LIST_DIR) // This is the default
{ {
var filebase = new FileBase(bbs.curdir_code); var filebase = new FileBase(gDirCode);
if (filebase.open()) if (filebase.open())
{ {
// If there are no files in the filebase, then say so and exit now. // If there are no files in the filebase, then say so and exit now.
if (filebase.files == 0) if (filebase.files == 0)
{ {
filebase.close(); filebase.close();
var libIdx = file_area.dir[bbs.curdir_code].lib_index; var libIdx = file_area.dir[gDirCode].lib_index;
console.crlf(); console.crlf();
console.print("\x01n\x01cThere are no files in \x01h" + file_area.lib_list[libIdx].description + "\x01n\x01c - \x01h" + console.print("\x01n\x01cThere are no files in \x01h" + file_area.lib_list[libIdx].description + "\x01n\x01c - \x01h" +
file_area.dir[bbs.curdir_code].description + "\x01n"); file_area.dir[gDirCode].description + "\x01n");
console.crlf(); console.crlf();
console.pause(); console.pause();
retObj.exitNow = true; retObj.exitNow = true;
...@@ -3227,7 +3361,16 @@ function populateFileList(pSearchMode) ...@@ -3227,7 +3361,16 @@ function populateFileList(pSearchMode)
// Get a list of file data // Get a list of file data
var fileDetail = (extendedDescEnabled() ? FileBase.DETAIL.EXTENDED : FileBase.DETAIL.NORM); var fileDetail = (extendedDescEnabled() ? FileBase.DETAIL.EXTENDED : FileBase.DETAIL.NORM);
gFileList = filebase.get_list("*", fileDetail, 0, true, gFileSortOrder); if (gFileSortOrder == SORT_FL_ULTIME || gFileSortOrder == SORT_FL_DLTIME)
{
gFileList = filebase.get_list(gFilespec, fileDetail, 0, true, FileBase.SORT.NATURAL);
if (gFileSortOrder == SORT_FL_ULTIME)
gFileList.sort(fileInfoSortULTime);
else if (gFileSortOrder == SORT_FL_DLTIME)
gFileList.sort(fileInfoSortDLTime);
}
else
gFileList = filebase.get_list(gFilespec, fileDetail, 0, true, gFileSortOrder);
filebase.close(); filebase.close();
// Add a dirCode property to the file metadata objects (for consistency, // Add a dirCode property to the file metadata objects (for consistency,
// as file search results may contain files from multiple directories). // as file search results may contain files from multiple directories).
...@@ -3235,7 +3378,7 @@ function populateFileList(pSearchMode) ...@@ -3235,7 +3378,7 @@ function populateFileList(pSearchMode)
// from the end. // from the end.
for (var i = 0; i < gFileList.length; ++i) for (var i = 0; i < gFileList.length; ++i)
{ {
gFileList[i].dirCode = bbs.curdir_code; gFileList[i].dirCode = gDirCode;
if (gFileList[i].hasOwnProperty("extdesc") && /\r\n$/.test(gFileList[i].extdesc)) if (gFileList[i].hasOwnProperty("extdesc") && /\r\n$/.test(gFileList[i].extdesc))
{ {
gFileList[i].extdesc = gFileList[i].extdesc.substr(0, gFileList[i].extdesc.length-2); gFileList[i].extdesc = gFileList[i].extdesc.substr(0, gFileList[i].extdesc.length-2);
...@@ -3247,7 +3390,7 @@ function populateFileList(pSearchMode) ...@@ -3247,7 +3390,7 @@ function populateFileList(pSearchMode)
else else
{ {
console.crlf(); console.crlf();
console.print("\x01n\x01h\x01yUnable to open \x01w" + file_area.dir[bbs.curdir_code].description + "\x01n"); console.print("\x01n\x01h\x01yUnable to open \x01w" + file_area.dir[gDirCode].description + "\x01n");
console.crlf(); console.crlf();
console.pause(); console.pause();
retObj.exitNow = true; retObj.exitNow = true;
...@@ -3259,12 +3402,18 @@ function populateFileList(pSearchMode) ...@@ -3259,12 +3402,18 @@ function populateFileList(pSearchMode)
{ {
var lastDirCode = ""; var lastDirCode = "";
// Prompt the user for directory, library, or all // If not searching all already, prompt the user for directory, library, or all
var validInputOptions = "DLA";
var userInputDLA = "";
if (gScanAllDirs)
userInputDLA = "A";
else
{
console.print("\x01n"); console.print("\x01n");
console.crlf(); console.crlf();
console.mnemonics(bbs.text(DirLibOrAll)); console.mnemonics(bbs.text(DirLibOrAll));
var validInputOptions = "DLA"; userInputDLA = console.getkeys(validInputOptions, -1, K_UPPER);
var userInputDLA = console.getkeys(validInputOptions, -1, K_UPPER); }
var userFilespec = ""; var userFilespec = "";
if (userInputDLA.length > 0 && validInputOptions.indexOf(userInputDLA) > -1) if (userInputDLA.length > 0 && validInputOptions.indexOf(userInputDLA) > -1)
{ {
...@@ -3286,14 +3435,20 @@ function populateFileList(pSearchMode) ...@@ -3286,14 +3435,20 @@ function populateFileList(pSearchMode)
{ {
var lastDirCode = ""; var lastDirCode = "";
// Prompt the user for directory, library, or all // If not saerching all already, prompt the user for directory, library, or all
var validInputOptions = "DLA";
var userInputDLA = "";
if (gScanAllDirs)
userInputDLA = "A";
else
{
console.print("\x01n"); console.print("\x01n");
console.crlf(); console.crlf();
//console.print("\r\n\x01c\x01hFind Text in File Descriptions (no wildcards)\x01n\r\n"); //console.print("\r\n\x01c\x01hFind Text in File Descriptions (no wildcards)\x01n\r\n");
console.mnemonics(bbs.text(DirLibOrAll)); console.mnemonics(bbs.text(DirLibOrAll));
console.print("\x01n"); console.print("\x01n");
var validInputOptions = "DLA"; userInputDLA = console.getkeys(validInputOptions, -1, K_UPPER);
var userInputDLA = console.getkeys(validInputOptions, -1, K_UPPER); }
var searchDescription = ""; var searchDescription = "";
if (userInputDLA.length > 0 && validInputOptions.indexOf(userInputDLA) > -1) if (userInputDLA.length > 0 && validInputOptions.indexOf(userInputDLA) > -1)
{ {
...@@ -3344,14 +3499,20 @@ function populateFileList(pSearchMode) ...@@ -3344,14 +3499,20 @@ function populateFileList(pSearchMode)
between successive sessions. between successive sessions.
*/ */
// Prompt the user for directory, library, or all // If not searching all dirs already, prompt the user for directory, library, or all
var userInputDLA = "";
if (gScanAllDirs)
userInputDLA = "A";
else
{
console.print("\x01n"); console.print("\x01n");
console.crlf(); console.crlf();
console.mnemonics(bbs.text(DirLibOrAll)); console.mnemonics(bbs.text(DirLibOrAll));
var validInputOptions = "DLA"; var validInputOptions = "DLA";
var userInputDLA = console.getkeys(validInputOptions, -1, K_UPPER); userInputDLA = console.getkeys(validInputOptions, -1, K_UPPER);
console.print("\x01n"); console.print("\x01n");
console.crlf(); console.crlf();
}
if (userInputDLA == "D" || userInputDLA == "L" || userInputDLA == "A") if (userInputDLA == "D" || userInputDLA == "L" || userInputDLA == "A")
{ {
console.print("\x01n\x01cSearching for files uploaded after \x01h" + system.timestr(bbs.new_file_time) + "\x01n"); console.print("\x01n\x01cSearching for files uploaded after \x01h" + system.timestr(bbs.new_file_time) + "\x01n");
...@@ -3375,7 +3536,7 @@ function populateFileList(pSearchMode) ...@@ -3375,7 +3536,7 @@ function populateFileList(pSearchMode)
return retObj; return retObj;
} }
if (pSearchMode != MODE_LIST_CURDIR) if (pSearchMode != MODE_LIST_DIR)
gFileList.allSameDir = allSameDir; gFileList.allSameDir = allSameDir;
if (dirErrors.length > 0) if (dirErrors.length > 0)
...@@ -3448,7 +3609,17 @@ function searchDirWithFilespec(pDirCode, pFilespec) ...@@ -3448,7 +3609,17 @@ function searchDirWithFilespec(pDirCode, pFilespec)
if (filebase.open()) if (filebase.open())
{ {
var fileDetail = (extendedDescEnabled() ? FileBase.DETAIL.EXTENDED : FileBase.DETAIL.NORM); var fileDetail = (extendedDescEnabled() ? FileBase.DETAIL.EXTENDED : FileBase.DETAIL.NORM);
var fileList = filebase.get_list(pFilespec, fileDetail, 0, true, gFileSortOrder); var fileList;
if (gFileSortOrder == SORT_FL_ULTIME || gFileSortOrder == SORT_FL_DLTIME)
{
fileList = filebase.get_list(pFilespec, fileDetail, 0, true, FileBase.SORT.NATURAL);
if (gFileSortOrder == SORT_FL_ULTIME)
fileList.sort(fileInfoSortULTime);
else if (gFileSortOrder == SORT_FL_DLTIME)
fileList.sort(fileInfoSortDLTime);
}
else
fileList = filebase.get_list(pFilespec, fileDetail, 0, true, gFileSortOrder);
retObj.foundFiles = (fileList.length > 0); retObj.foundFiles = (fileList.length > 0);
filebase.close(); filebase.close();
for (var i = 0; i < fileList.length; ++i) for (var i = 0; i < fileList.length; ++i)
...@@ -3491,7 +3662,18 @@ function searchDirWithDescUpper(pDirCode, pDescUpper) ...@@ -3491,7 +3662,18 @@ function searchDirWithDescUpper(pDirCode, pDescUpper)
var filebase = new FileBase(pDirCode); var filebase = new FileBase(pDirCode);
if (filebase.open()) if (filebase.open())
{ {
var fileList = filebase.get_list("*", FileBase.DETAIL.EXTENDED, 0, true, gFileSortOrder); //var fileList = filebase.get_list(gFilespec, FileBase.DETAIL.EXTENDED, 0, true, gFileSortOrder);
var fileList;
if (gFileSortOrder == SORT_FL_ULTIME || gFileSortOrder == SORT_FL_DLTIME)
{
fileList = filebase.get_list(gFilespec, FileBase.DETAIL.EXTENDED, 0, true, FileBase.SORT.NATURAL);
if (gFileSortOrder == SORT_FL_ULTIME)
fileList.sort(fileInfoSortULTime);
else if (gFileSortOrder == SORT_FL_DLTIME)
fileList.sort(fileInfoSortDLTime);
}
else
fileList = filebase.get_list(gFilespec, FileBase.DETAIL.EXTENDED, 0, true, gFileSortOrder);
filebase.close(); filebase.close();
for (var i = 0; i < fileList.length; ++i) for (var i = 0; i < fileList.length; ++i)
{ {
...@@ -3550,7 +3732,17 @@ function searchDirNewFiles(pDirCode, pSinceTime) ...@@ -3550,7 +3732,17 @@ function searchDirNewFiles(pDirCode, pSinceTime)
if (filebase.open()) if (filebase.open())
{ {
var fileDetail = (extendedDescEnabled() ? FileBase.DETAIL.EXTENDED : FileBase.DETAIL.NORM); var fileDetail = (extendedDescEnabled() ? FileBase.DETAIL.EXTENDED : FileBase.DETAIL.NORM);
var fileList = filebase.get_list("*", fileDetail, 0, true, gFileSortOrder); var fileList;
if (gFileSortOrder == SORT_FL_ULTIME || gFileSortOrder == SORT_FL_DLTIME)
{
fileList = filebase.get_list(gFilespec, fileDetail, 0, true, FileBase.SORT.NATURAL);
if (gFileSortOrder == SORT_FL_ULTIME)
fileList.sort(fileInfoSortULTime);
else if (gFileSortOrder == SORT_FL_DLTIME)
fileList.sort(fileInfoSortDLTime);
}
else
fileList = filebase.get_list(gFilespec, fileDetail, 0, true, gFileSortOrder);
filebase.close(); filebase.close();
for (var i = 0; i < fileList.length; ++i) for (var i = 0; i < fileList.length; ++i)
{ {
...@@ -3610,7 +3802,7 @@ function searchDirGroupOrAll(pSearchOption, pDirSearchFn) ...@@ -3610,7 +3802,7 @@ function searchDirGroupOrAll(pSearchOption, pDirSearchFn)
if (searchOptionUpper == "D") if (searchOptionUpper == "D")
{ {
// Current directory // Current directory
var searchRetObj = pDirSearchFn(bbs.curdir_code); var searchRetObj = pDirSearchFn(gDirCode);
retObj.allSameDir = true; retObj.allSameDir = true;
for (var i = 0; i < searchRetObj.dirErrors.length; ++i) for (var i = 0; i < searchRetObj.dirErrors.length; ++i)
retObj.errors.push(searchRetObj.dirErrors[i]); retObj.errors.push(searchRetObj.dirErrors[i]);
...@@ -3618,7 +3810,7 @@ function searchDirGroupOrAll(pSearchOption, pDirSearchFn) ...@@ -3618,7 +3810,7 @@ function searchDirGroupOrAll(pSearchOption, pDirSearchFn)
else if (searchOptionUpper == "L") else if (searchOptionUpper == "L")
{ {
// Current file library // Current file library
var libIdx = file_area.dir[bbs.curdir_code].lib_index; var libIdx = file_area.dir[gDirCode].lib_index;
for (var dirIdx = 0; dirIdx < file_area.lib_list[libIdx].dir_list.length; ++dirIdx) for (var dirIdx = 0; dirIdx < file_area.lib_list[libIdx].dir_list.length; ++dirIdx)
{ {
if (file_area.lib_list[libIdx].dir_list[dirIdx].can_access) // And can_download? if (file_area.lib_list[libIdx].dir_list[dirIdx].can_access) // And can_download?
...@@ -3670,7 +3862,8 @@ function searchDirGroupOrAll(pSearchOption, pDirSearchFn) ...@@ -3670,7 +3862,8 @@ function searchDirGroupOrAll(pSearchOption, pDirSearchFn)
} }
else else
{ {
retObj.errors.push("Invalid search option" + (pSearchOption.length > 0 ? ": " + pSearchOption : "")); //retObj.errors.push("Invalid search option" + (pSearchOption.length > 0 ? ": " + pSearchOption : ""));
retObj.errors.push("Aborted");
} }
return retObj; return retObj;
...@@ -3868,3 +4061,42 @@ function isDoingFileSearch() ...@@ -3868,3 +4061,42 @@ function isDoingFileSearch()
{ {
return (gScriptMode == MODE_SEARCH_FILENAME || gScriptMode == MODE_SEARCH_DESCRIPTION || gScriptMode == MODE_NEW_FILE_SEARCH); return (gScriptMode == MODE_SEARCH_FILENAME || gScriptMode == MODE_SEARCH_DESCRIPTION || gScriptMode == MODE_NEW_FILE_SEARCH);
} }
// Custom file info sort function for upload time
function fileInfoSortULTime(pA, pB)
{
if (pA.hasOwnProperty("added") && pB.hasOwnProperty("added"))
{
if (pA.added < pB.added)
return -1;
else if (pA.added > pB.added)
return 1;
else
return 0;
}
else
{
if (pA.time < pB.time)
return -1;
else if (pA.time > pB.time)
return 1;
else
return 0;
}
}
// Custom file info sort function for download time
function fileInfoSortDLTime(pA, pB)
{
if (pA.hasOwnProperty("last_downloaded") && pB.hasOwnProperty("last_downloaded"))
{
if (pA.last_downloaded < pB.last_downloaded)
return -1;
else if (pA.last_downloaded > pB.last_downloaded)
return 1;
else
return 0;
}
else
return 0;
}
Digital Distortion File Lister Digital Distortion File Lister
Version 2.08 Version 2.09
Release date: 2023-01-18 Release date: 2023-02-25
by by
Eric Oulashin Eric Oulashin
Sysop of Digital Distortion Sysop of Digital Distortion
BBS internet address: digitaldistortionbbs.com BBS internet address: digitaldistortionbbs.com
Alternate address: digdist.bbsindex.com Alternate address: digdist.synchro.net
Email: eric.oulashin@gmail.com Email: eric.oulashin@gmail.com
...@@ -19,6 +19,7 @@ Contents ...@@ -19,6 +19,7 @@ Contents
1. Disclaimer 1. Disclaimer
2. Introduction 2. Introduction
3. Installation & Setup 3. Installation & Setup
- Loadable Module setup
- Command shell setup - Command shell setup
- Background: Running JavaScript scripts in Synchronet - Background: Running JavaScript scripts in Synchronet
4. Configuration file & color/text theme configuration file 4. Configuration file & color/text theme configuration file
...@@ -105,17 +106,42 @@ where the .js script is located. So, if you desire, you could place ...@@ -105,17 +106,42 @@ where the .js script is located. So, if you desire, you could place
ddfilelister.js in sbbs/exec and the .cfg file sin your sbbs/ctrl directory, ddfilelister.js in sbbs/exec and the .cfg file sin your sbbs/ctrl directory,
for example. for example.
One way to install ddfilelister.js is to run it directly from your command
shell. Also, as of Synchronet 3.20 (built on February 25, 2023 and newer),
there are a couple of loadable module options in SCFG for file operations;
ddfilelister.js can be used as a loadable module for Scan Dirs and List Files.
The advantage of having ddfilelister.js set up as a loadable module is that
ddfilelister.js will be used from standard command shells and using the standard
file list/search commands/functions.
Loadable Module setup
---------------------
Note: This only works in Synchronet 3.20 (built from February 25, 2020) and
newer.
As a loadable module, ddfilelister.js works for the Scan Dirs and List Files
options. These options are available in SCFG > System > Loadable Modules.
If you have ddfilelister.js in your mods directory or other standard directory,
you can specify the settings as follows:
Scan Dirs ddfilelister.js
List Files ddfilelister.js
If you keep ddfilelister.js in sbbs/xtrn/ddfilelister, you can specify it as
follows:
Scan Dirs ../xtrn/ddfilelister/ddfilelister.js
List Files ../xtrn/ddfilelister/ddfilelister.js
Command shell setup Command shell setup
------------------- -------------------
Running the file lister involves simply having the BBS run a command to run To running the file lister in a command shell, you simply need to add a command
ddfilelister.js. No command-line parameters are required. The command to run to your command shell run ddfilelister.js. To list the files in the user's
ddfilelister.js can be placed in a command shell for a command key, or in current file directory, no command-line parameters are required. The command to
run ddfilelister.js can be placed in a command shell for a command key, or in
SCFG > External Programs > Online Programs (Doors) in one of your program SCFG > External Programs > Online Programs (Doors) in one of your program
groups, and then you could have your command shell run the lister via the groups, and then you could have your command shell run the lister via the
internal program code you configured in SCFG. internal program code you configured in SCFG.
Installing into a command shell is described in section 3, "Installation &
Setup".
Background: Running JavaScript scripts in Synchronet Background: Running JavaScript scripts in Synchronet
---------------------------------------------------- ----------------------------------------------------
......
...@@ -5,6 +5,8 @@ Revision History (change log) ...@@ -5,6 +5,8 @@ Revision History (change log)
============================= =============================
Version Date Description Version Date Description
------- ---- ----------- ------- ---- -----------
2.09 2023-02-25 Now supports being used as a loadable module for Scan Dirs
and List Files (applicable for Synchronet 3.20+)
2.08 2023-01-18 When doing a file search in multiple directories, the 2.08 2023-01-18 When doing a file search in multiple directories, the
file library & directory is now shown in the header as file library & directory is now shown in the header as
the user scrolls through the file list/search results. the user scrolls through the file list/search results.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment