Run bash through discord api - python

I want to make a bot that runs bash commands through the discord api with a checker against a file called admin.json that would run through discord's API running bash commands on my vps server so I don't have to logon each time through ssh. I want to do this over discord specifically.
I tried researching LIKE EVERYWHERE..
https://discordpy.readthedocs.io/en/latest/api.html#discord.MessageType
This was the closet I have gotten to about what I need: To return the message.content identifier. I want to be able to access my vps server over discord so I don't have to login each time through ssh.
import discord
import sys
import os
import json
import subprocess
import asyncio
from discord.ext import commands
t = "<token here>"
with open("admin.json", "r") as admin:
admin = json.load(admin)
client = commands.Bot(command_prefix='-')
#client.event
async def on_ready():
print('Bash bot is online')
#client.command()
async def on_message(ctx, arg1):
if str(ctx.author.id) in(admin):
command = ctx.message.content #this for some reason fails
cmd = subprocess.getoutput(command)
await ctx.send(command)
print(str(ctx.message.content)) #even this one fails :(
else:
pass
await ctx.send("You don't have permission to use this command!" + "\n" + "<" + "#" + str(ctx.author.id) + ">")
client.run(t, bot=True)```
Should be able to run with any args so if there is a space between a bash command it shouldn't break the bot like:
```wget https://google.com``` <- Should not break the discord bot
My most common error message:
```File "bot.py", line 23, in run
print(message.content)
AttributeError: 'str' object has no attribute 'content'

You can make a check to handle checking the ids. I'm not sure where your problem with ctx.message is coming from, I suspect you had some code that is assigning to it.
with open("admin.json", "r") as admin:
admin = [int(x) for x in json.load(admin)]
def is_any_user(ids):
def predicate(ctx):
return ctx.message.author.id in ids
return commands.check(predicate)
#is_any_user(admin)
#client.command(name="run")
async def run_command(ctx, *, command_string):
output = subprocess.getoutput(command_string)
await ctx.send(output)
#run_command.error
async def run_error(ctx, error):
if isinstance(error, commands.CheckFailure):
await ctx.send(f"You don't have permission, {ctx.author.mention}")
else:
raise error

Related

Discord.py client.run and bot.run in one code

Not sure that I need to use the both runs at the same time, but:
from multiprocessing.dummy.connection import Client
from telnetlib import DM
from typing_extensions import Required
import discord
from discord.utils import get
from discord.ext import commands
from dislash import InteractionClient, Option, OptionType
from dislash.interactions import *
client = discord.Client()
from message import *
#client.event
async def on_message(message):
if message.author == client.user:
return
User_id = message.author.id
if message.channel.id == 1009530463108476968:
NewMessage = message.content.split(' ', 1)[0]
LimitLenght = len(NewMessage) + 11
if len(message.clean_content) >= LimitLenght:
await message.delete()
await message.author.send("Hello, " + f"<#{User_id}>" + "\nPlease, don't send any messages that break the **Counting-game** rules!\nIt's forbidden to post a comment that is longer than 10 characters.")
# More code
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
bot = commands.Bot(command_prefix="!")
inter_client = InteractionClient(bot)
#inter_client.slash_command(name="help", description="Shows the help-menu")
async def help(ctx):
embedVar = discord.Embed(title="Test project", description="*The blue text is clickable.*\n⠀", color=0x0000ff)
embedVar.add_field(name="Rules", value='To see rules write **/Rules**\n⠀', inline=False)
await ctx.reply(embed=embedVar, delete_after=180)
bot.run('ToKeN')
client.run('ToKeN')
If you run this code and comment the "bot.run('ToKeN')", the first part of the code will work (def on_message), however the command '/help' will not work. If you change it (comment 'client.run('ToKeN')'), the command '/help' will work, but def on_message not.
What are the possible solutions? Thanks.
The .runs block each other and prevent from running. You shouldn't be using a client and a bot anyway. Use one commands.Bot instead. It subclasses a Client and it should be able to do everything you can do with the client.
bot = commands.Bot(command_prefix="!")
inter_client = InteractionClient(bot)
#bot.event
async def on_message(message):
...
#inter_client.slash_command(name="help", description="Shows the help-menu")
async def help(ctx):
...
bot.run(token)

Discordpy Slash command don't update afer restarting bot

I'm having a problem that after restarting the bot, the slash commands doesn't update, it stays the one I've made first, this is my simple code:
import discord
from discord.ext import commands
from discord_slash import cog_ext, SlashContext
class Slash(commands.Cog):
def __init__(self, bot):
self.bot = bot
#cog_ext.cog_slash(name="Soporte",description="Comando para ver las opciones de soporte")
async def _support(self, ctx: SlashContext):
await ctx.channel.send("✈️ Telegram: #Isaac_Sanz\n💬 Discord: ElmerKao_#0058 \n🌐 Página Web: https://nakiri.x10.mx/")
def setup(bot):
bot.add_cog(Slash(bot))
Here is a prove that everything is running as it should be:
But when I enter discord to run the command it only shows the test one I did before:
Could someone explain what is happening and any solution?
Found the issue, seems that you need to load the cogs before the something like this:
cogs = ["cogs.roles","cogs.users","cogs.moderation","cogs.ticket-es","cogs.ticket-en"]
bot = ComponentsBot("!", help_command=None,intents=intents)
#BOT STARTUP
#bot.event
#When bot starts
async def on_ready():
print('Bot {0.user} funcionando perfectamente'.format(bot))
print("-----------------------------------------")
print("ID: " + str(bot.user.id))
print("Version de Discord: " + str(discord.__version__))
print(f'Actualmente en {len(bot.guilds)} servidores!')
for server in bot.guilds:
print(server.name)
print("-----------------------------------------")
#COGS
#This loads the cogs like in line 16
print("Cargando cogs . . .")
for cog in cogs:
try:
bot.load_extension(cog)
print(cog + " ha sido cargada.")
except Exception as e:
print(e)
print("\n")
Here is how it should look like:
Here is the link of the question where I found the answer:
Link
They're sort of in the middle of adding slash commands to discord.py but you can see a few examples in https://gist.github.com/Rapptz/c4324f17a80c94776832430007ad40e6 You seem to be using discord_slash, which I have not used.
I'm not quite sure how to do it in cogs, because I have mine in groups but basically what I'm doing is a combination of #bot.tree.command() in the main bot file and a few groups in separate files.
So here's my main file
import discord
import simplegeneralgroup
from config import TOKEN
MY_GUILD = discord.Object(id=1234567890)
class MyBot(discord.ext.commands.Bot):
async def on_ready(self):
await self.tree.sync(guild=MY_GUILD)
bot: discord.ext.commands.Bot = MyBot
#bot.tree.command(guild=MY_GUILD)
async def slash(interaction: discord.Interaction, number: int, string: str):
await interaction.response.send_message(f'Modify {number=} {string=}', ephemeral=True)
bot.tree.add_command(simplegeneralgroup.Generalgroup(bot), guild=MY_GUILD)
if __name__ == "__main__":
bot.run(TOKEN)
and then the simplegeneralgroup file
import discord
from discord import app_commands as apc
class Generalgroup(apc.Group):
"""Manage general commands"""
def __init__(self, bot: discord.ext.commands.Bot):
super().__init__()
self.bot = bot
#apc.command()
async def hello(self, interaction: discord.Interaction):
await interaction.response.send_message('Hello')
#apc.command()
async def version(self, interaction: discord.Interaction):
"""tells you what version of the bot software is running."""
await interaction.response.send_message('This is an untested test version')
There should be three commands: /slash, which will prompt the user for a number and string, /generalgroup hello, and /generalgroup version
The main documentation for this stuff is https://discordpy.readthedocs.io/en/master/interactions/api.html?highlight=dropdown#decorators but the main "how to" is that you've gotta make a "tree", attach commands to that tree, and sync your tree for the commands to show up. discord.ext.Bot makes its own tree, which is why I'm using that instead of client, which I think doesn't make a tree by default.
If you specify the guilds, the commands sync takes place instantly, but if you don't specify the guild, I think it takes an hour to update or something like that, so specify the guild until you're ready for deployment.

How to stop repetitive messages, and the token is changed, but it doesn't run

I started learning python today and made a Discord bot. I have a few problems:
If message.author == was used in the on_message, but the bot continued to reply to itself.
Afterwards, a new bot was created with a new token and the code didn't work.
I searched a lot on this site and Google. I didn't find any solution. It's okay to modify my code. Everything is from the internet, so it can be a mess. Please help me.
import discord
import asyncio
from discord.ext import commands
client = discord.Client()
bot = commands.Bot(command_prefix="!")
#bot.event
async def on_ready():
print('Loggend in Bot: ', bot.user.name)
print('Bot id: ', bot.user.id)
print('connection was succesful!')
print('=' * 30)
#client.event
async def on_message(message) :
if on_message.content.startswith('!의뢰'):
msg = on_message.channel.content[3:]
embed = discord.Embed(title = "브리핑", description = msg, color = 0x62c1cc)
embed.set_thumbnail(url="https://i.imgur.com/UDJYlV3.png")
embed.set_footer(text="C0de")
await on_message.channel.send("새로운 의뢰가 들어왔습니다", embed=embed)
await client.process_commands(message)
client.run("My bot's token.")
Your code was messy, but it should work now. I included comments to let you know how everything works. I think the good starting point to making your own bot is reading documentation. Especially Quickstart that shows you a simple example with explanation.
Write !example or hello to see how it works.
import discord
import asyncio
from discord.ext import commands
# you created 'client' and 'bot' and used them randomly. Create one and use it for everything:
client = commands.Bot(command_prefix="!") # you can change commands prefix here
#client.event
async def on_ready(): # this will run everytime bot is started
print('Logged as:', client.user)
print('ID:', client.user.id)
print('=' * 30)
#client.event
async def on_message(message):
if message.author == client.user:
return
if message.content.startswith('hello'): # you can change what your bot should react to
await message.channel.send("Hello! (This is not a command. It will run everytime a user sends a message and it starts with `hello`).")
await client.process_commands(message)
#client.command()
async def example(ctx): # you can run this command by sending command name and prefix before it, (e.g. !example)
await ctx.send("Hey! This is an example command.")
client.run("YOUR TOKEN HERE")

Unittest or Pytest for Discord Bot

Writing Unittests/Pytests
I have a discord bot and I'm trying to write tests for it. I tried a library called distest and it worked well for certain things but not all..
I have a second bot that sends a message and checks the response, but it's just not working with Unittests or Pytest.
Here's an example of one of my tests,
it's checking for the reply "Pong!" if "ping" was sent.
I run my bot that needs to be tested before calling the script with pytest
from discord.ext import commands
from dotenv import load_dotenv
import os
import pytest
TOKEN = "bot token of tester bot"
bot = commands.Bot(command_prefix='?/')
bot.run(TOKEN)
target_id = "ID of bot to be tested"
channel_id = "ID of channel of where it will be tested"
async def test_ping():
correct_response = 'Pong!'
channel = await bot.fetch_channel(channel_id)
await channel.send("ping")
def check(m):
return m.content == correct_response and m.author.id == target_id
response = await bot.wait_for('message', check=check)
assert (response.content == correct_response)
Pytests is stuck on collecting and when I tried Unittests it just hung and did nothing
You did try to register the ping command after running the bot. bot.run(TOKEN) must be end of the code. Also you must put a decorator to resgistering command. So the code will be this:
from discord.ext import commands
from dotenv import load_dotenv
import os
import pytest
TOKEN = "bot token of tester bot"
bot = commands.Bot(command_prefix='?/')
target_id = "ID of bot to be tested"
channel_id = "ID of channel of where it will be tested"
#bot.command(name="ping") #if name did not entered, function name will be the command name
async def test_ping(ctx): #Every command takes context object as first parameter
correct_response = 'Pong!'
channel = await bot.fetch_channel(channel_id)
await channel.send("ping")
def check(m):
return m.content == correct_response and m.author.id == target_id
response = await bot.wait_for('message', check=check)
assert (response.content == correct_response)
bot.run(TOKEN)
Basicly context object:
await ctx.send("message") #sends message to command's invoked channel.
ctx.guild #returns server if not channel is a DM channel
ctx.channel #returns channel
ctx.author #returns message's author
ctx.message #returns message
ctx.message.content #returns the messsge's content

I am hosting a discord.py bot on Heroku Git and it wont go online on the discord server even though I turned it on in the website

My code is and my main problem is that when I turn the worker on in Heroku it is not online in discord. I know this may seem like a duplicate but the answers to the other questions are not working for me. :
import discord, os, time
from dotenv import load_dotenv
from discord.ext import tasks, commands
TOKEN = 'xxxxxxxxxxxxxxxxxxxx'
client = discord.Client()
#client.event
async def on_ready():
print(f"RoleCheck has connected to {client.guilds[0].name}")
global channel
channel = client.guilds[0].get_channel(xxxxxxxxxxxxxxxxxx)
#client.event
async def on_member_update(before, after):
newRole = next(role for role in after.roles if role not in before.roles)
if newRole.name == "1":
print(f"IGN:{after.nick} \nDiscord:{after.name}")
global msg
msg = await channel.send(f"IGN:{after.nick} \nDiscord:{after.name}")
#client.event
async def on_message(message):
if message.content.startswith("!comment"):
_content = "Comment: " + msg.content + '\n' + message.content[8:]
await msg.edit(content=_content)
elif message.content.startswith("!help"):
await channel.send("---RoleCheck--- \n!comment - will add a comment on the last message with whatever you write after\n !help = will show the help screen\n Made with python and the discord.py API by xxxxxxxx")
client.run(TOKEN)
Procflile:
worker: python bot.py
requirements.txt:
discord.py==1.4.1
OP was missing an import in their requirements.txt. Heroku logs are very helpful in determining the cause of your error. If you are using the Heroku CLI you can check your logs using heroku logs, alternatively you can check your logs on the website by clicking on your app > More > View logs.

Categories