hosting a discord bot on cPanel - node.js

I have a problem that when I want to turn on my discord bot on my server that uses cPanel, I can't get it to work from the node.js control panel without putting the shell command node index.js into the package.json file and using the run script function of the panel. the problem with this is that the only way to stop the bot is to use the eval command on discord, since I don't have proper terminal access.

In addition to what #Verdigris answered above, you can use Glitch too, just make sure to use Runtime Bot so you can keep your Discord bot up 24/7.
Important: code to add on your main node.js file:
const http = require('http');
const express = require('express');
const app = express();
app.get("/", (request, response) => {
console.log(Date.now() + "Ping Received");
response.sendStatus(200);
});
app.listen(process.env.PORT);
setInterval(() => {
http.get(`http://${process.env.PROJECT_DOMAIN}.glitch.me/`);
}, 280000);
And as always, cheers.

On cPanel you will never have full terminal access, so what I suggest you do is just keep the NPM start script, then create a command for the bot that issues the process.exit() function. This function essentially stops the entire NodeJS Process. If you are looking for an alternative that provides full terminal access I recommend buying a cheap VPS from a decent provider such as OVH.

If your cPanel account has a in-browser terminal, you can enter the virtual environment by pasting the command that appears at the top of the Node.js control panel into there. It is something like:
source ~/nodevenv/<name_of_node_application>/10/bin/activate && cd ~/<path_to_node_application>
You will then have access to node and npm, and can then start your discord bot like you normally would like:
node <name_of_node_application> &
and kill it by running kill -TERM with node's pid, from ps -ax.
However, you can't reliably use the Node.js panel to stop a daemon script, as described here:
cpanel node.js Can't acquire lock for app: app

Related

Github Cli Command does not work with express js

In my backend express server , I am trying to execute a github cli command using execSync. But it hungs up there. The command is following:
`
execSsnc("gh auth login --web")
`
In the same machine, when I use terminal to execute the same command, it works fine. In fact, I have tried a executing this line of code in a simple nodejs project and this too works fine. But whenever I use this in my express server, it hungs up there. I have tried using spawn, exec, spawnSync too but no luck so far.
Also when I use execSync("gh auth status") this gives error saying there is no github hosts currently. But in the machine, when I run this command from the terminal, it says that I am already logged it using Personal Access Token. Thus I found that running the login command from the express server is the main issue. Is there any way out?
First, check if setting GH_DEBUG to 1 or api generates any verbose log which might shed some light to the issue.
const env = {
'env': {
'GH_DEBUG': 'api',
...process.env
}
}
exec('gh auth login --web', env, function (error, stdout, stderr){
console.log(stdout, stderr, error);
});
Second, check with another exec who you are when executed from Express.js, and compare it to your command-line environment (where it does work)
Using gh auth login --token < aTokenFile (passing the token as stdin to your execSync call) might be a better alternative than --web.
Note that execSync create a new shell and executes gh command in this shell.
Depending on the OS, the shell used by execSync might be different than the shell used in your terminal (bash/sh) or miss some env variables that are available in your terminal. This might explain why "gh auth status" execution shows different results.
Try to verify if the environment variables is your Express app are different than environment variables in your terminal

node-cron only working with an active session

I have a simple node-cron schedule that calls a function:
cron.schedule('00 00 00 * * *', () => {
console.log('update movies', new Date().toISOString());
updateMovies();
});
When I log in to my server using PuTTy or use the droplet console in Digital Ocean and then run the updateMovies.mjs file node server/updateMovies.mjs and wait for the time that the cron-job should run, everything works as expected.
But when I close PuTTy or the droplet console in Digital Ocean, then nothing happens when the cron-job should run. So the server seems to lose the cron-job when I close the session.
Short answer
You need to run the app in the background
nohup node server/updateMovies.mjs >/dev/null 2>&1
Long answer
Run your app directly in the shell is just for demos or academic purposes. On an enterprise environment you should a live process like a server which runs independently of the shell user.
Foreground and background processes
Processes that require a user to start them or to interact with them are called foreground processes
Processes that are run independently of a user are referred to as background processes.
How run background process (Linux)
No body uses windows for an modern deployments, so in Linux the usual strategy is to use nohup
server.js
var express = require('express');
var app = express();
app.get('/', function(req, res) {
res.type('text/plain');
res.send('Hell , its about time!!');
});
app.listen(process.env.PORT || 8080);
nohup node server.js >/dev/null 2>&1
If you login to the server using some shell client, and run only node server.js it will start but if you close the shell window, the process will ends.
How run background process with nodejs and PM2
pm2 server.js
More details here:
https://pm2.keymetrics.io/docs/usage/quick-start/
Best way : Docker
You need to dockerize your app and it will run everywhere with this command:
docker run -d my_app_nodejs ....

starting, stopping and restarting windows services using node js

Can someone explain how I can start or stop a windows service using a node program? Not a NodeJS service running on Windows, but specifically a Windows service itself, and that too, using NODEJS. There are lots of articles as to how to kill or start a NodeJS service, but not of what I am in need of here. There is an article though on StackOverflow in the following link:
Node js start and stop windows services
But I am either not doing it right because I have not understood it the way it should be or it doesn't do what I need it to do. Please help me out. Don't know why, but there are just almost no articles online about this.
USE os-services module
npm install os-service
It is loaded using the require() function:
var service = require ("os-service");
A program can then be added, removed and run as a service:
service.add ("my-service");
service.remove ("my-service");
service.run (function () {
// Stop request received (i.e. a kill signal on Linux or from the
// Service Control Manager on Windows), so let's stop!
service.stop ();
});
Use bat file to stop and start node server or user nodemon package.
And use windows task scheduler
#echo off
cd "D:\sam\Projects\NodeSchedule // path of node project i.e. index.js
taskkill /IM node.exe -F
start /min cmd /C "node index.js"
goto :EOF

child_process.fork not starting an express server inside of packaged electron app

I have an electron app where I need not only to run the interface to the user but also start an express server that will serve files for people connected through the network.
I have everything working if I start both electron and the express server normally, but I'm pretty confident that I will need the server running in a different thread to avoid slugish interface and even problems with the server.
For that matter I tried to run my express server using the child_process.fork and it worked when I use npm start, but when I use electron-builder to create an .exe, the installed program doesn't start the express server.
I tried to run my server right away using:
require('child_process').fork('app/server/mainServer.js')
I tried several changes, prefixing the file with __dirname, process.resourcesPath and even hard coding the generated file path; changing the fork options to pass cwd: __dirname, detached: true and stdio: 'ignore'; and even tried using spawn with process.execPath, which will also work with npm start but won't when packaged (it keeps opening new instances of my app, seems obvious after you do hehe)
Note: If I don't fork and require the server script right away, using require('server/mainServer.js') it works on the packaged app, so the problem most like isn't the express itself.
Note 2: I have asar: false to solve other problems, so this is not the problem solver here.
I put up a small git project to show my problem:
https://github.com/victorivens05/electron-fork-error
Any help will be highly appreciated.
With the great help from Samuel Attard (https://github.com/MarshallOfSound) I was able to solve the problem (he solved for me actually)
As he said:
the default electron app will launch the first file path provided to it
so `electron path/to/thing` will work
in a packaged state, that launch logic is not present
it will always run the app you have packaged regardless of the CLI args passed to it
you need to handle the argument manually yourself
and launch that JS file if it's passed in as the 1st argument
The first argument to fork simply calls `process.execPath` with the first
argument being the path provided afaik
The issue is that when packaged Electron apps don't automatically run the
path provided to them
they run the app that is packaged within them
In other words. fork is actually spawn being executed with process.execPath and passing the fork's first argument as the second for spawn.
What happens in a packaged app is that the process.execPath isn't electron but the packaged app itself. So if you try to spawn, the app will be open over and over again.
So, what Samuel suggest was implemented like this:
if (process.argv[1] === '--start-server') {
require('./server/mainServer.js')
return
}
require('./local/mainLocal.js')
require('child_process').spawn(process.execPath, ['--start-server'])
That way, the first time the packaged app will be executed, the process.argv[1] will be empty, so the server won't start. It will then execute the electron part (mainLocal in my case) and start the app over, but this time passing the argv. Next time the app starts, it will start the server and stop the execution, so the app won't open again because spawn is never reached.
Huge thanks to Samuel.

Flow of Work Working With Node.JS HTTP server

Learning Node.JS at the moment.
Everything is going fine, just that i have a little challenge with the flow of work.
So i create an HTTP server that listens at a particular port. For example
var http = require("http");
http.createServer(function(request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello World");
response.end();
}).listen(8888);
It works fine. Only problem is that when i edit the file that has the above code, and try to start the node process again by typing node server.js i get the following error:
Error: EADDRINUSE, Address already in use.
So i learnt I need to kill the node process using ps before the changes can be reflected and before i can restart.
But this looks like a pain. Do i need to kill the node process anytime i make changes to the server i am writing?
I am sure there is a better way. Any help?
During development I tend to just run node from the command line in a terminal window. When I'm finished with the testing I just Ctrl-C to interrupt the current process which kills node and then press arrow-up enter to restart the process.
my solution is as simple as
npm install dev -g
node-dev app.js
node-dev is the same as 'node' but automatically reruns app.js everytime any file in application dir (or subdir) is changed. it means restarting when static files are changed, too, but should be acceptable for development mode
There isn't any easy way. Authors of node do not like hot-reloading idea, so this is the way it works.
You can hack it if you put your server in a module, require it from the main script, fs.watchFile the .js for changes and then manually stop it as a reaction to a file change, manually deleting it from the module cache (require.cache if I am not mistaken), and require it again.
Or run it in child process and kill and respawn it after a file change (that is, doing automatically what you now do by hand).
You can use something like nodemon (video tutorial about it here) or node-supervisor so that the server auto-restarts when editing files.
If you want to manually do this, then just interrupt the process (CTRL+C) and re-run last command (node server.js).

Resources