Search Function for folder with files - javascript

I'm coding a bot with Discord.js, and was wondering how to create a function for a play command.
!play
faded
I want the code to search through a set folder, located at ./MusicFiles and find the filename closest to the given argument after the command !play. How would I do this and how would I give the full name of the file so it can be used by the bot?

You can use the npm packages levenary and fs. levenary is a package that will calculate the Levenshtein Distance between two strings. For example:
levenary('cat', ['cow', 'dog', 'pig']);
//=> 'cow'
You can use this in combination with fs, a package with can return an array of all files within a directory.
const fs = require('fs');
const levenary = require('levenary')
const files = fs.readdirSync('./MusicFiles') // get every file in this directory
const songFile = levenary(args[0], files) // get the file

Related

Parse INI file in Node.js

I build a Node.js tool in order to change GCP config quickly. But I'm a bit stuck on the parsing of the config_nameOfConfig file.
It looks like this :
[core]
account = email#example.fr
project = project-example
disable_usage_reporting = False
[compute]
region = europe-west1-b
(This file is available in '/Users/nameOfUser/.config/gcloud')
And I want to convert it in an object like this :
const config = {
account:"email#example.fr",
project:"project-example",
disable_usage_reporting:false,
region:"europe-west1-b",
};
I get the content of this file with the fs.readFileSync function who converts it into a string.
An idea ?
This seems to be an ini file format. Unless you want to do the parsing yourself, you'd better just download a library to your project, for example:
npm install ini
Then in the code:
var ini = require('ini')
var fs = require('fs')
var config = ini.parse(fs.readFileSync('./config_nameOfConfig', 'utf-8'))
In config you should now have object containing the data in the file.
You can console.log(config) to see how it exactly looks like.

Dynamic command handler with shared and seperate commands

I am setting up a command handler for multiple channels (Twitch). At the moment I have all the commands divided in folders user specific and the generic ones. Accessing them by using a map(). I would like each user/channel to have access to only their folder and the generic one. The map key is name in a .js file.
So what would be the best way to do it? Ive tried mapping over the generic folder and the folder that matches the user name on login, but I am not aware of a way to change the "command" in client.commands.set(key, value) so it would be client.(nameChannel).set(key, value). Then I would be able to probably assign the default and user specific folder to the map.
Also fs.dirReadSync lists all of the .js files in a folder and sub folder. How do I access all of them at once in require? Wildcards don't seem to work so do I need to list them like shown below?
I want to be able to add more later and not hardcode them one-by-one if possible.
//hardcode example.
var moduleA = require( "./module-a.js" );
var moduleB = require( "../../module-b.js" );
var moduleC = require( "/my-library/module-c.js" );
The piece of code below is still a work in progress. What I like to achieve:
exclude channel specific commands from being called from other channels.
know if/what the standard or recommended approach is.
how to require() all .js from the readDir sync in one require.
client.commands = new Map();
//add commands property/method to client instance. A map to iterate over.
const commandFiles = fs.readdirSync("./commands").filter(file => file.endsWith(".js"));
//reads file system and filter .js files only. returns an array of those items.
for (const file of commandFiles) {
const command = require(`./commands/${file}`); //this only grabs the results in commands itself can't use wildcards..
//sets a new item in the collection.
//Key of map is command name.
client.commands.set(command.name, command);
}
//input validation etc here
//check command
try {
client.commands.get(commandFromMessage).execute(channel, commandFromMessage, argument);
} catch (error) {
console.error(error);
}
pastebin of the folder tree: https://pastebin.com/XNJt98Ha
You can set string names as your keys in regular objects.
const channelSpecificCommands = new Map();
const channelFolder= fs.readdirSync(`./commands/${channelSpecificDir}`);
for(const file in channelFolder) {
const commandFromFile = require(`./commands/{${channelSpecificDir}/${file}`)
channelSpecificCommands.set(commandFromFile.name, commandFromFile);
}
client[channelSpecificDir] = channelSpecificCommands;
For your second question - you should be using .json files instead of .js for this. You can load json files with JSON.parse(fs.readFileSync('myjsonfile.json', 'utf8')) to get the data without any issues that come with dynamic module resolution.

Simple node module command line example

I want to make a simple node module that can be run from the command line that I can input files into, then it might change every instance of 'red' to 'blue' for example and then save that as a new file. Is there a simple example out there somewhere that I can edit to fit my purposes? I've tried looking but couldn't find one that was sufficiently simple to understand how to modify it. Can anyone help?
A simple example of replace.js (both old and new files are supposed to be in UTF-8 encoding):
'use strict';
const fs = require('fs');
const oldFilePath = process.argv[2];
const newFilePath = process.argv[3];
const oldFileContent = fs.readFileSync(oldFilePath, 'utf8');
const newFileContent = oldFileContent.replace(/red/g, 'blue');
fs.writeFileSync(newFilePath, newFileContent);
How to call:
node replace.js test.txt new_test.txt
Documentation on used API:
process.argv
fs.readFileSync()
fs.writeFileSync()

How do I delete all files that match the basename in an array of globs?

I have an existing build task in my gulpfile, that transforms a collection of "source" files into "dist" files. I have an array of well-known filenames that tell my build task which files to operate on:
sourceFiles: [
"./js/source/hoobly.js",
"./js/source/hoo.js"
]
My build task produces the following files from this:
./js/dist/hoobly.js
./js/dist/hoobly.min.js
./js/dist/hoobly.js.map
./js/dist/hoobly.min.js.map
./js/dist/hoo.js
./js/dist/hoo.min.js
./js/dist/hoo.js.map
./js/dist/hoo.min.js.map
I now want to write a corresponding clean task that removes the files that get generated during my build task. Unfortunately I cannot just delete all the files in the ./js/dist/ directory, as this contains other files that are not generated by the build task in question, so I need to ensure that the files I delete match the "basename" of the orginal sourceFiles.
My question is: how do I go about using the sourceFiles array and "munging"* it so that I can end up calling something like:
gulp.src(sourceFiles)
.pipe(munge()) // I don't know what to do here!!
.pipe(del()); // does a `del ./js/dist/hoobly.*`
// and a `del ./js/dist/hoo.*`
(*Technical term, "munge"...)
Can you point me in the right direction? I've looked at various NPM packages (vinyl-paths, gulp-map-files, gulp-glob, ...) and I'm just getting more and more lost.
I'd change globs before passing them to gulp.src:
var sourceFiles = [
"./js/source/hoobly.js",
"./js/source/hoo.js"
];
var filesToDelete = sourceFiles.map(f=>f.replace("/source/", "/dist/").replace(".js", ".*"));
console.log(filesToDelete)
and omit that munge step:
gulp.src(filesToDelete).pipe(del())

How to zip a folder in node js application & after zip downloading start?

I tried with npm package adm-zip 0.4.4 because the latest one 0.4.7 doesn't work, adm-zip 0.4.4 works on Windows but not on Mac & Linux. Another problem is that I only want zip_folder to be zipped but it zipps the whole directory structure staring from folder_1. This is the code:
var zip = new admZip();
zip.addLocalFolder("./folder_1/folder_2/folder_3/**zip_folder**");
zip.writeZip("./folder_1/folder_2/folder_3/download_folder/zip_folder.zip");
All this happens on the server side. I have searched a lot and tried many npm packages to zip a folder or directory. Any suggestions or any other good approach to solve my problem?
You could also use node-archiver, which was very helpful when I was using it. First you need create an instance of the archiver as follows:
var fs = require('fs');
var archiver = require('archiver');
var archive = archiver.create('zip', {});
var output = fs.createWriteStream(__dirname + '/zip_folder.zip');
This way you tell the archiver to zip the files or folders based on the format you pass along with the method. In this case it's zip. In addition, we create a writeStream which will be piped to the archiver as its output. Also, we use the directory method to append a directory and its files, recursively, given its dirpath:
archive.pipe(output);
archive
.directory(__dirname + '/folder_1/folder_2/folder_3/download_folder/zip_folder')
.finalize();
At the end, we need to finalize the instance which prevents further appending to the archive structure.
Another option is to use the bulk method like so:
archive.bulk([{
expand: true, cwd: './folder_1/folder_2/folder_3/download_folder/zip_folder/',
src: ['**/*']
}]).finalize();
Update 1
A little explanation for the [**/*] syntax: This will recursively include all folders ** and files *.
Try to use the system's zip function:
var execFile = require('child_process').execFile;
execFile('zip', ['-r', '-j', zipName, path], function(err, stdout) {
if(err){
console.log(err);
throw err;
}
console.log('success');
});
Replace zipName and path with what you need.

Categories