Ir para conteúdo
Propaganda

Posts Recomendados

  • Suporte

Eu tinha montado esse sistema um tempo, especificamente para atualizar, deletar e  adicionar arquivos, e tambem desligar/ligar/reniciar e
ver os logs do servidor caso nao tivesse em casa ou sem acesso a VPS
 

 

  • Like 5
  • Thanks 1
Link para o comentário
https://tibiadevs.com/forums/topic/1107-showoff-gerenciamento-otserv-pelo-discord/
Compartilhar em outros sites

Tópico Aprovado com Sucesso!
@JulianoZN
Excelente iniciativa! Esse sistema de gerenciamento remoto via Discord é prático, inteligente e extremamente útil pra quem trabalha com servidores 24/7, especialmente sem acesso direto à VPS. 💻📡

📌 Com ele, é possível:

  • Atualizar, deletar e adicionar arquivos

  • Ligar/desligar/reiniciar o servidor

  • Acompanhar logs como se estivesse em casa!

Além de funcional, é uma solução moderna e bem integrada com o cotidiano dos devs.
Parabéns pela ideia e obrigado por compartilhar com a comunidade! 🚀

  • Like 1
Link para o comentário
https://tibiadevs.com/forums/topic/1107-showoff-gerenciamento-otserv-pelo-discord/#findComment-5675
Compartilhar em outros sites

  • Administrador
4 horas atrás, JulianoZN disse:

Eu tinha montado esse sistema um tempo, especificamente para atualizar, deletar e  adicionar arquivos, e tambem desligar/ligar/reniciar e
ver os logs do servidor caso nao tivesse em casa ou sem acesso a VPS
 

 

gostei

  • Thanks 1
Link para o comentário
https://tibiadevs.com/forums/topic/1107-showoff-gerenciamento-otserv-pelo-discord/#findComment-5679
Compartilhar em outros sites

  • Suporte
10 horas atrás, Lindolfo disse:

seria possivel um botão de compilar a sources?

Sim, e possível

 

 image.png.8c4ed2a92c061997ec9222dd7dba5a3b.png

Link para o comentário
https://tibiadevs.com/forums/topic/1107-showoff-gerenciamento-otserv-pelo-discord/#findComment-5685
Compartilhar em outros sites

  • Suporte
40 minutos atrás, usariodenome disse:

are you gonna release it or you want to wait for me to release it for free?

Go ahead and release it, I don't care.
Like I said, I just put it together—I didn't make it from scratch.

Link para o comentário
https://tibiadevs.com/forums/topic/1107-showoff-gerenciamento-otserv-pelo-discord/#findComment-5690
Compartilhar em outros sites

so why not share it if you already wrote it why make others duplicate the code when everyone could benefit from this? why is everyone like this sell this module sell this discord bot in the end you make maybe 50$ from 1 user and nobody else buy this hsit for 2years xD

Link para o comentário
https://tibiadevs.com/forums/topic/1107-showoff-gerenciamento-otserv-pelo-discord/#findComment-5696
Compartilhar em outros sites

  • Suporte
54 minutos atrás, usariodenome disse:

so why not share it if you already wrote it why make others duplicate the code when everyone could benefit from this? why is everyone like this sell this module sell this discord bot in the end you make maybe 50$ from 1 user and nobody else buy this hsit for 2years xD

just to explain I never said I was going to sell this. I just put the pieces of the system together for myself and wanted to show it here. I didn’t invent everything from scratch — I simply took some existing tools and made them work for my needs.
Showing what I did doesn’t mean I’m selling it or that I’m obligated to share the code.
The tools are already available online on GitHub, so anyone can do the same thing — just adapt, edit, and adjust them to fit what you need.
Of course, if someone wants to buy it, I have no problem selling it

Link para o comentário
https://tibiadevs.com/forums/topic/1107-showoff-gerenciamento-otserv-pelo-discord/#findComment-5697
Compartilhar em outros sites

import discord
from discord.ext import commands
from discord import ButtonStyle
from discord.ui import Button, View
import subprocess
import psutil
import os

TOKEN = 'YOUR_BOT_TOKEN'
AUTHORIZED_ROLE_ID = 123456789012345678  # Replace with your role ID or None if using user ID
WORKING_DIR = '/home/youruser/tfs'  # Change to your compile folder

intents = discord.Intents.default()
bot = commands.Bot(command_prefix='!', intents=intents)

def run_cmd(command, cwd=WORKING_DIR):
    try:
        output = subprocess.check_output(command, shell=True, stderr=subprocess.STDOUT, cwd=cwd, timeout=60)
        return output.decode('utf-8')
    except subprocess.CalledProcessError as e:
        return f"[ERROR]\n{e.output.decode('utf-8')}"
    except Exception as e:
        return f"[EXCEPTION] {str(e)}"

def get_sysinfo():
    return (
        f"CPU Usage: {psutil.cpu_percent()}%\n"
        f"Memory: {psutil.virtual_memory().percent}%\n"
        f"Uptime: {int(psutil.boot_time())}"
    )

class AdminView(View):
    def __init__(self):
        super().__init__(timeout=None)
        self.add_item(Button(label="CMake", style=ButtonStyle.primary, custom_id="cmake"))
        self.add_item(Button(label="Make", style=ButtonStyle.primary, custom_id="make"))
        self.add_item(Button(label="Kill TFS", style=ButtonStyle.danger, custom_id="pkill"))
        self.add_item(Button(label="Sys Info", style=ButtonStyle.secondary, custom_id="sysinfo"))

    @discord.ui.button(label="CMake", style=ButtonStyle.primary, custom_id="cmake")
    async def cmake(self, interaction: discord.Interaction, _):
        if not await is_authorized(interaction): return
        out = run_cmd("cmake .")
        await interaction.response.send_message(f"```{out[:1900]}```", ephemeral=True)

    @discord.ui.button(label="Make", style=ButtonStyle.primary, custom_id="make")
    async def make(self, interaction: discord.Interaction, _):
        if not await is_authorized(interaction): return
        out = run_cmd("make -j$(nproc)")
        await interaction.response.send_message(f"```{out[:1900]}```", ephemeral=True)

    @discord.ui.button(label="Kill TFS", style=ButtonStyle.danger, custom_id="pkill")
    async def pkill(self, interaction: discord.Interaction, _):
        if not await is_authorized(interaction): return
        out = run_cmd("pkill tfs")
        await interaction.response.send_message(f"TFS killed.\n```{out}```", ephemeral=True)

    @discord.ui.button(label="Sys Info", style=ButtonStyle.secondary, custom_id="sysinfo")
    async def sysinfo(self, interaction: discord.Interaction, _):
        if not await is_authorized(interaction): return
        info = get_sysinfo()
        await interaction.response.send_message(f"```{info}```", ephemeral=True)

async def is_authorized(interaction):
    if AUTHORIZED_ROLE_ID:
        has_role = any(role.id == AUTHORIZED_ROLE_ID for role in interaction.user.roles)
        if not has_role:
            await interaction.response.send_message("Not authorized.", ephemeral=True)
            return False
    return True

@bot.command()
async def panel(ctx):
    """Send the admin panel with buttons"""
    if AUTHORIZED_ROLE_ID and not any(role.id == AUTHORIZED_ROLE_ID for role in ctx.author.roles):
        await ctx.send("Unauthorized.")
        return
    await ctx.send("Admin Panel", view=AdminView())

bot.run(TOKEN)

 

Link para o comentário
https://tibiadevs.com/forums/topic/1107-showoff-gerenciamento-otserv-pelo-discord/#findComment-5698
Compartilhar em outros sites

  • Suporte
10 horas atrás, usariodenome disse:
import discord
from discord.ext import commands
from discord import ButtonStyle
from discord.ui import Button, View
import subprocess
import psutil
import os

TOKEN = 'YOUR_BOT_TOKEN'
AUTHORIZED_ROLE_ID = 123456789012345678  # Replace with your role ID or None if using user ID
WORKING_DIR = '/home/youruser/tfs'  # Change to your compile folder

intents = discord.Intents.default()
bot = commands.Bot(command_prefix='!', intents=intents)

def run_cmd(command, cwd=WORKING_DIR):
    try:
        output = subprocess.check_output(command, shell=True, stderr=subprocess.STDOUT, cwd=cwd, timeout=60)
        return output.decode('utf-8')
    except subprocess.CalledProcessError as e:
        return f"[ERROR]\n{e.output.decode('utf-8')}"
    except Exception as e:
        return f"[EXCEPTION] {str(e)}"

def get_sysinfo():
    return (
        f"CPU Usage: {psutil.cpu_percent()}%\n"
        f"Memory: {psutil.virtual_memory().percent}%\n"
        f"Uptime: {int(psutil.boot_time())}"
    )

class AdminView(View):
    def __init__(self):
        super().__init__(timeout=None)
        self.add_item(Button(label="CMake", style=ButtonStyle.primary, custom_id="cmake"))
        self.add_item(Button(label="Make", style=ButtonStyle.primary, custom_id="make"))
        self.add_item(Button(label="Kill TFS", style=ButtonStyle.danger, custom_id="pkill"))
        self.add_item(Button(label="Sys Info", style=ButtonStyle.secondary, custom_id="sysinfo"))

    @discord.ui.button(label="CMake", style=ButtonStyle.primary, custom_id="cmake")
    async def cmake(self, interaction: discord.Interaction, _):
        if not await is_authorized(interaction): return
        out = run_cmd("cmake .")
        await interaction.response.send_message(f"```{out[:1900]}```", ephemeral=True)

    @discord.ui.button(label="Make", style=ButtonStyle.primary, custom_id="make")
    async def make(self, interaction: discord.Interaction, _):
        if not await is_authorized(interaction): return
        out = run_cmd("make -j$(nproc)")
        await interaction.response.send_message(f"```{out[:1900]}```", ephemeral=True)

    @discord.ui.button(label="Kill TFS", style=ButtonStyle.danger, custom_id="pkill")
    async def pkill(self, interaction: discord.Interaction, _):
        if not await is_authorized(interaction): return
        out = run_cmd("pkill tfs")
        await interaction.response.send_message(f"TFS killed.\n```{out}```", ephemeral=True)

    @discord.ui.button(label="Sys Info", style=ButtonStyle.secondary, custom_id="sysinfo")
    async def sysinfo(self, interaction: discord.Interaction, _):
        if not await is_authorized(interaction): return
        info = get_sysinfo()
        await interaction.response.send_message(f"```{info}```", ephemeral=True)

async def is_authorized(interaction):
    if AUTHORIZED_ROLE_ID:
        has_role = any(role.id == AUTHORIZED_ROLE_ID for role in interaction.user.roles)
        if not has_role:
            await interaction.response.send_message("Not authorized.", ephemeral=True)
            return False
    return True

@bot.command()
async def panel(ctx):
    """Send the admin panel with buttons"""
    if AUTHORIZED_ROLE_ID and not any(role.id == AUTHORIZED_ROLE_ID for role in ctx.author.roles):
        await ctx.send("Unauthorized.")
        return
    await ctx.send("Admin Panel", view=AdminView())

bot.run(TOKEN)

 

Weren't you supposed to be the badass? So where's the part that commits to the server? Edits server files? Deletes folders and files? Downloads the logs? And shuts down the server without causing a rollback?

What about the protection system for the command? Where’s that? And the one that only lets authorized people, handpicked by the owner, see the server, even with other admins? Where’s the part that lets you add more servers? The one that lets you add other types of bots? And the one that adds a website, where is it?

Link para o comentário
https://tibiadevs.com/forums/topic/1107-showoff-gerenciamento-otserv-pelo-discord/#findComment-5700
Compartilhar em outros sites

12 hours ago, JulianoZN said:

Weren't you supposed to be the badass? So where's the part that commits to the server? Edit server files? Deletes folders and files? Download the logs? And shuts down the server without causing a rollback?

What about the protection system for the command? Where's that? And the one that only lets authorized people, handpicked by the owner, see the server, even with other admins? Where's the part that lets you add more servers? The one that lets you add other types of bots? And the one that adds a website, where is it?

dude i got mobile client i can do /closeserver shutdown to restart server im not amateur like uu realize i have whole node js frontend website for my server on

This is the hidden content, please
  is admin panel on bottom i can do it via website instead of discord also i have linux apps on my phone called terminus it shows u cpu usage and everything u can login to ubuntu i use restarter file that backups sqls and have njs script to backup ssh into server to zip the sqls 🙂

 

  • Like 3
Link para o comentário
https://tibiadevs.com/forums/topic/1107-showoff-gerenciamento-otserv-pelo-discord/#findComment-5702
Compartilhar em outros sites

const { Client } = require('ssh2');
const fs = require('fs');
const path = require('path');

// Configuration
const remoteDir = '/home/ots/mysql_backup/';
const localDir = 'D:/backups/';
const zipFileName = `mysql_backup_${new Date().toISOString().replace(/[:T]/g, '-').slice(0, 19)}.zip`; // Format: mysql_backup_YYYY-MM-DD_HH-MM-SS.zip
const remoteZipFile = `/home/backups/${zipFileName}`; // Save ZIP in /home/ots

const conn = new Client();

conn.on('ready', () => {
    console.log('SSH Connection established.');

    // Step 1: Zip the directory on the remote server
    const zipCommand = `zip -r ${remoteZipFile} ${remoteDir}`;
    conn.exec(zipCommand, (err, stream) => {
        if (err) {
            console.error('Error executing zip command:', err);
            conn.end();
            return;
        }

        stream
            .on('close', (code, signal) => {
                if (code === 0) {
                    console.log(`Directory zipped successfully as ${zipFileName}.`);
                    downloadZipFile();
                } else {
                    console.error(`Zip command failed with code ${code} and signal ${signal}.`);
                    conn.end();
                }
            })
            .on('data', (data) => {
                console.log('STDOUT:', data.toString());
            })
            .stderr.on('data', (data) => {
                console.error('STDERR:', data.toString());
            });
    });

    // Step 2: Download the zipped file
    function downloadZipFile() {
        conn.sftp((err, sftp) => {
            if (err) {
                console.error('Error initiating SFTP:', err);
                conn.end();
                return;
            }

            const localFilePath = path.join(localDir, zipFileName);

            // Create local directory if it doesn't exist
            if (!fs.existsSync(localDir)) {
                fs.mkdirSync(localDir, { recursive: true });
            }

            const readStream = sftp.createReadStream(remoteZipFile);
            const writeStream = fs.createWriteStream(localFilePath);

            readStream.on('error', (err) => {
                console.error('Error reading remote file:', err);
                conn.end();
            });

            writeStream.on('error', (err) => {
                console.error('Error writing local file:', err);
                conn.end();
            });

            writeStream.on('close', () => {
                console.log(`File downloaded successfully to: ${localFilePath}`);
                cleanupRemoteZip();
            });

            readStream.pipe(writeStream);
        });
    }

    // Step 3: Clean up the zipped file on the remote server
    function cleanupRemoteZip() {
        conn.exec(`rm -f ${remoteZipFile}`, (err, stream) => {
            if (err) {
                console.error('Error deleting remote zip file:', err);
                conn.end();
                return;
            }

            stream
                .on('close', (code, signal) => {
                    if (code === 0) {
                        console.log(`Remote zip file ${zipFileName} deleted successfully.`);
                    } else {
                        console.error(`Failed to delete remote zip file with code ${code} and signal ${signal}.`);
                    }
                    conn.end();
                })
                .on('data', (data) => {
                    console.log('STDOUT:', data.toString());
                })
                .stderr.on('data', (data) => {
                    console.error('STDERR:', data.toString());
                });
        });
    }
}).connect({
    host: '',       // Replace with your remote host
    port: 22,                       // Default SSH port
    username: 'root',      // Replace with your username
    password: 'password for ur account here to backup your sql files if ur using restarter'       // Replace with your password
    // Or use privateKey for key-based authentication:
    // privateKey: fs.readFileSync('path/to/private/key')
});

// Handle errors
conn.on('error', (err) => {
    console.error('SSH Connection error:', err);
}).on('end', () => {
    console.log('Connection ended.');
}).on('close', () => {
    console.log('Connection closed.');
});

 

Link para o comentário
https://tibiadevs.com/forums/topic/1107-showoff-gerenciamento-otserv-pelo-discord/#findComment-5703
Compartilhar em outros sites

  • Suporte
8 minutos atrás, usariodenome disse:

dude i got mobile client i can do /closeserver shutdown to restart server im not amateur like uu realize i have whole node js frontend website for my server on

Hidden Content

  • Give reaction to this post to see the hidden content.

  is admin panel on bottom i can do it via website instead of discord also i have linux apps on my phone called terminus it shows u cpu usage and everything u can login to ubuntu i use restarter file that backups sqls and have njs script to backup ssh into server to zip the sqls 🙂

 

 

Bro, I’ve got all of that too — mobile client, auto-restart scripts, SSH access, panel, backups, you name it.

The only difference is, when I don’t feel like giving people full access, I can limit exactly what they can or can’t do through Discord or the site, which works as an API too.

Oh — and I can add new servers automatically via Discord, assign ownership, and manage them without ever touching the VPS manually.

So yeah, before flexing your tech setup, maybe make sure you actually know what the other person is running. 😉 Just saying.

Link para o comentário
https://tibiadevs.com/forums/topic/1107-showoff-gerenciamento-otserv-pelo-discord/#findComment-5704
Compartilhar em outros sites

  • Suporte
9 minutos atrás, usariodenome disse:
const { Client } = require('ssh2');
const fs = require('fs');
const path = require('path');

// Configuration
const remoteDir = '/home/ots/mysql_backup/';
const localDir = 'D:/backups/';
const zipFileName = `mysql_backup_${new Date().toISOString().replace(/[:T]/g, '-').slice(0, 19)}.zip`; // Format: mysql_backup_YYYY-MM-DD_HH-MM-SS.zip
const remoteZipFile = `/home/backups/${zipFileName}`; // Save ZIP in /home/ots

const conn = new Client();

conn.on('ready', () => {
    console.log('SSH Connection established.');

    // Step 1: Zip the directory on the remote server
    const zipCommand = `zip -r ${remoteZipFile} ${remoteDir}`;
    conn.exec(zipCommand, (err, stream) => {
        if (err) {
            console.error('Error executing zip command:', err);
            conn.end();
            return;
        }

        stream
            .on('close', (code, signal) => {
                if (code === 0) {
                    console.log(`Directory zipped successfully as ${zipFileName}.`);
                    downloadZipFile();
                } else {
                    console.error(`Zip command failed with code ${code} and signal ${signal}.`);
                    conn.end();
                }
            })
            .on('data', (data) => {
                console.log('STDOUT:', data.toString());
            })
            .stderr.on('data', (data) => {
                console.error('STDERR:', data.toString());
            });
    });

    // Step 2: Download the zipped file
    function downloadZipFile() {
        conn.sftp((err, sftp) => {
            if (err) {
                console.error('Error initiating SFTP:', err);
                conn.end();
                return;
            }

            const localFilePath = path.join(localDir, zipFileName);

            // Create local directory if it doesn't exist
            if (!fs.existsSync(localDir)) {
                fs.mkdirSync(localDir, { recursive: true });
            }

            const readStream = sftp.createReadStream(remoteZipFile);
            const writeStream = fs.createWriteStream(localFilePath);

            readStream.on('error', (err) => {
                console.error('Error reading remote file:', err);
                conn.end();
            });

            writeStream.on('error', (err) => {
                console.error('Error writing local file:', err);
                conn.end();
            });

            writeStream.on('close', () => {
                console.log(`File downloaded successfully to: ${localFilePath}`);
                cleanupRemoteZip();
            });

            readStream.pipe(writeStream);
        });
    }

    // Step 3: Clean up the zipped file on the remote server
    function cleanupRemoteZip() {
        conn.exec(`rm -f ${remoteZipFile}`, (err, stream) => {
            if (err) {
                console.error('Error deleting remote zip file:', err);
                conn.end();
                return;
            }

            stream
                .on('close', (code, signal) => {
                    if (code === 0) {
                        console.log(`Remote zip file ${zipFileName} deleted successfully.`);
                    } else {
                        console.error(`Failed to delete remote zip file with code ${code} and signal ${signal}.`);
                    }
                    conn.end();
                })
                .on('data', (data) => {
                    console.log('STDOUT:', data.toString());
                })
                .stderr.on('data', (data) => {
                    console.error('STDERR:', data.toString());
                });
        });
    }
}).connect({
    host: '',       // Replace with your remote host
    port: 22,                       // Default SSH port
    username: 'root',      // Replace with your username
    password: 'password for ur account here to backup your sql files if ur using restarter'       // Replace with your password
    // Or use privateKey for key-based authentication:
    // privateKey: fs.readFileSync('path/to/private/key')
});

// Handle errors
conn.on('error', (err) => {
    console.error('SSH Connection error:', err);
}).on('end', () => {
    console.log('Connection ended.');
}).on('close', () => {
    console.log('Connection closed.');
});

 

And what the hell is that about your script needing to SSH into the server just to backup's?

Bro… in 2025? Really?

Ever heard of local daemons, cron jobs, or remote API triggers? No need for a script to manually SSH like it's 2008.

But hey, if you like overcomplicating basic tasks, good for you. 💀

Link para o comentário
https://tibiadevs.com/forums/topic/1107-showoff-gerenciamento-otserv-pelo-discord/#findComment-5706
Compartilhar em outros sites

Agora, JulianoZN disse:

And what the hell is that about your script needing to SSH into the server just to backup's?

Bro… in 2025? Really?

Ever heard of local daemons, cron jobs, or remote API triggers? No need for a script to manually SSH like it's 2008.

But hey, if you like overcomplicating basic tasks, good for you. 💀

I need it on my harddrive not cloud. I also connect from phone the network is limited in my area but i pull 130mbp/s on 4g+ from my phone to pc. can stream in 4500mbps easily 6000 if no one else is using internet and on good weather hehe

Link para o comentário
https://tibiadevs.com/forums/topic/1107-showoff-gerenciamento-otserv-pelo-discord/#findComment-5707
Compartilhar em outros sites

  • Suporte
6 minutos atrás, usariodenome disse:

I need it on my harddrive not cloud.

Yeah, my script also works on my machine, no need for cloud or even touching the VPS.

For example, if I want an admin to only access specific files, the system (via the site or even Discord) only shows them what I allow – no remote access, no SSH, no drama.

But hey, if your definition of “security” is dragging entire server backups through SSH to your hard drive like it’s 2008~2009, that’s cool too. 🧠

Next time, before flexing something outdated, maybe take a peek outside the bubble.

Link para o comentário
https://tibiadevs.com/forums/topic/1107-showoff-gerenciamento-otserv-pelo-discord/#findComment-5708
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar Agora
×
  • Criar Novo...