Role gets removed after assigning - python-3.x

so I have an bot, written and based on Discord.py,
and I am encountering an very strange issue, I have my bot hosted on CentOs 6, 64 bit, and installed with python 3.6.3.
I am starting the bot through cd'ing it to the main folder and use python3.6 main.py.
See this code snippet:
#bot.command(aliases=["pokemon", "Pokemon", "POKEMON", "PoGo", "POGO", "PokeMonGo", "Pokémon GO"], pass_context=True)
async def pokemongo(ctx):
gotrole = discord.utils.get(ctx.message.server.roles, name="1")
pogorole = discord.utils.get(ctx.message.server.roles, name="Pokémon GO")
if gotrole in ctx.message.author.roles:
await bot.say("You already have a role! Contact support if you want to change!")
return
else:
await bot.add_roles(ctx.message.author, pogorole)
time.sleep(2)
await bot.add_roles(ctx.message.author, gotrole)
await bot.say("Got you the role, Pokémon GO!")
That should totally work, what happens is that the user gets the role Pokemon GO and then the role 1, and then weirdly, the role Pokemon GO gets deleted, sometimes it does happens, sometimes it doesn't, and it's nothing to do with roles, permissions, the code between or below. This snippet is used for various other roles too, using the same template just differing in the commands name (async def) and the roles variable (pogorole in this case)
The weird part its completely random, and actually done by the bot, and not someone else, see the imported libraries below
import discord
from discord.ext import commands
from discord.utils import get
import os
import random
import sys
import asyncio
import aiohttp
import time
import psutil
And an other example of another snippet of code, using the same template:
#bot.command(pass_context=True)
async def fortnite(ctx):
gotrole = discord.utils.get(ctx.message.server.roles, name="1")
fortniterole = discord.utils.get(ctx.message.server.roles, name="Fortnite")
if gotrole in ctx.message.author.roles:
await bot.say("You already have a role! Contact support if you want to change!")
return
else:
await bot.add_roles(ctx.message.author, fortniterole)
time.sleep(2)
await bot.add_roles(ctx.message.author, gotrole)
await bot.say("Got you the role, fortnite!")
It does not error out and the role 1 does not change or gets removed from the user, its just the game role that randomly does, it doesn't have anything to do with internet or something similiar
I really hope there is an explanation to this, and would really love to hear some!
Cheers, Deadly

Try to add all roles at once.
await bot.add_roles(ctx.message.author, fortniterole, gotrole)
Or try to use asyncio.sleep instead of time.sleep. time.sleep is blocking bot entirely, since it is not async
await bot.add_roles(ctx.message.author, fortniterole)
await asyncio.sleep(2)
await bot.add_roles(ctx.message.author, gotrole)

Related

How do i make a discord bot receive text after a command

I want to become a fake discord bot, so i can use: !!send or something like that.
I have the token ready and i tried some repl.it templates but i have no idea of what to do.
here is the code i tried:
import discord
import os
import time
import discord.ext
from discord.utils import get
from discord.ext import commands, tasks
from discord.ext.commands import has_permissions, CheckFailure, check
os.environ["TOKEN"] = "no-token-for-you-to-see-here"
#^ basic imports for other features of discord.py and python ^
client = discord.Client()
client = commands.Bot(command_prefix = '!!') #put your own prefix here
#client.event
async def on_ready():
print("bot online") #will print "bot online" in the console when the bot is online
#client.command(pass_context=True)
async def send(ctx,*,message):
await client.say(message)
client.run(os.getenv("TOKEN")) #get your bot token and create a key named `TOKEN` to the secrets panel then paste your bot token as the value.
#to keep your bot from shutting down use https://uptimerobot.com then create a https:// monitor and put the link to the website that appewars when you run this repl in the monitor and it will keep your bot alive by pinging the flask server
#enjoy!
It was online, but the command didn't work.
The command send should be
#client.command()
async def send(ctx, *, message: str):
await ctx.send(message)
Also, you're defining two client(s). You need only one.
client = commands.Bot(command_prefix = '!!')
You're also importing some useless modules that you don't need right now.
Your final code should look like this:
import discord
from discord.ext import commands
client = commands.Bot(command_prefix="!!")
#client.event
async def on_ready():
print("The bot is online")
#client.command()
async def send(ctx, *, message: str):
await ctx.send(message)
client.run("token-of-the-bot")
Please tell me if it works or not. Have a great day :)

Discord.py API get user data from IP

I've been looking into the Discord API source code and I was wondering if you could get a user's data. Not just returning their username. There is nothing that I could find in the API's docks.
This is the furthest I got:
data = await discord.client.Client.fetch_user_profile(discord.client.Client.fetch_user_profile, id)
But I keep on getting the error:
CommandInvokeError: Command raised an exception: AttributeError: 'function' object has no attribute '_connection'
Caused by a what I think may be a function and a variable having the same name. Are there any ways to fix this, or any other methods to get a users data that works. Preferably without having to change the source code. Thanks for any help in advance.
And just in case you need it, here is the entirety of my code:
#import libarys
import discord
from discord.ext import commands
import os
#setup bot
bot = commands.Bot(command_prefix='&', owner_id=MyID, case_insensitive=True)
#bot.event
async def on_ready():
await bot.change_presence(activity=discord.Activity(type=discord.ActivityType.watching, name='for &help'))
print(f'\n\nLogged in as: {bot.user} - {bot.user.id}\nVersion: {discord.__version__}\n')
#find user data command
#bot.command()
async def find(ctx, id: int):
member = await ctx.guild.fetch_member(id)
data = await discord.client.Client.fetch_user_profile(discord.client.Client.fetch_user_profile, id)
print(member, data)
#connect bot
bot.run(os.environ.get('TOKEN'), bot=True, reconnect=True)
EDIT: This code is just a mock up to get a working concept, I don't care to make it more refined yet.
This is a really bad code, I don't even know how you came up with that code. You're not supposed to refer to the class itself but to the instance, your code fixed
#bot.command()
async def find(ctx, id: int):
member = await ctx.guild.fetch_member(id)
data = await bot.fetch_user_profile(id)
print(member, data)
Also note that the fetch_user_profile method it's deprecated since version 1.7 and bot accounts cannot use this endpoint
Reference:
Client.fetch_user_profile

Add a reaction to a ctx.send message in discord.py

I am making a poll command, the bot will send a ctx message and will say the poll question. I want to make it so when the poll message is sent, the bot adds two reaction, a thumbs up and a thumbs down. I have tried several different ways but non of them work. Here is the code from my latest try (everything is already imported)
reactions = ["👍", "👎"]
#bot.command(pass_context=True)
async def poll(self, ctx, message,*, question):
poll_msg = f"Poll: {question} -{ctx.author}"
reply = await self.bot.say(poll_msg)
for emoji_id in reactions:
emoji = get(ctx.server.emojis, name=emoji_id)
await message.add_reaction(reply, emoji or emoji_id)
The code is all over the place because I tried putting different solutions together to see if it would work but it doesn't work at all.
It looks like you're operating from some old examples. You should read the official documentation to find examples of the modern interfaces.
from discord.ext import commands
from discord.utils import get
bot = commands.Bot("!")
reactions = ["👍", "👎"]
#bot.command()
async def poll(ctx, *, question):
m = await ctx.send(f"Poll: {question} -{ctx.author}")
for name in reactions:
emoji = get(ctx.guild.emojis, name=name)
await m.add_reaction(emoji or name)

Discord.py User nickname changing

I have been trying to make myself a bot for my ArmA 3 unit, and upon doing so I have tried to create an Enlisting command, which changes the users existing Nickname within the server to the one that they enlist with (Their ArmA soldier name). But I am having some trouble figuring out how to do this. I'll leave my code down below for you to look at and hopefully figure out a solution :
import discord
from discord.ext.commands import Bot
from discord.ext import commands
import asyncio
Client = discord.Client()
client = commands.Bot(command_prefix = "+.")
#client.event
async def on_ready():
print("ToLate Special Operations Reporting For Duty")
await client.change_presence(game=discord.Game(name="By Slay > $enlist", type=3))
print("For more information: Please contact Slay on twitter #OverflowEIP")
#client.event
async def on_message(message):
if message.content.upper().startswith('+.ENLIST'):
client.change_nickname(message.content.replace('changeNick', ''))
client.run('token')
change_nickname is a coroutine, so you have to await it. You're also not really using commands properly. You should be defining separate coroutines for each command and decorating them with the client.command decorator. (You also don't need Client, commands.Bot is a subclass of discord.Client)
from discord.ext.commands import Bot
from discord.utils import get
client = commands.Bot(command_prefix = "+.")
#client.event
async def on_ready():
print("ToLate Special Operations Reporting For Duty")
await client.change_presence(game=discord.Game(name="By Slay > $enlist", type=3))
print("For more information: Please contact Slay on twitter #OverflowEIP")
#client.command(pass_context=True)
async def enlist(ctx, *, nickname):
await client.change_nickname(ctx.message.author, nickname)
role = get(ctx.message.server.roles, name='ARMA_ROLE') # Replace ARMA_ROLE as appropriate
if role: # If get could find the role
await client.add_role(ctx.message.author, role)
client.run('token')
enlist(ctx, *, nickname) means we accept commands like
+.enlist apple
+.enlist bag cat
+.enlist "dog eat"
and will assign those users (the person who called the command) the nicknames
apple
bag cat
"dog eat"

discord.py module how do i remove the command text afterwards?

from discord.ext.commands import Bot
import secrets
from time import sleep
discordBot = Bot(command_prefix = ".")
listStrings = ['add a reaction', 'adnd']
#discordBot.event
async def on_read():
print('Client logged in')
#discordBot.command()
async def s(*args):
return await discordBot.say (" ".join(args))
#discordBot.command()
async def close():
quit()
discordBot.run(secrets.token)
I wanted to say ".s (text)" and that the bot says the text(works already) but deletes your message, how can i do this? i got the part working of on_message:
#discordbot.event
async def on_message(message):
await discordBot.delete_message(message)
What is the best way to do this? Thanks in advance.
I'm sorry you haven't got an answer for 26 days. If you are still looking for an answer, I hope I can provide some help. So I ran your code, and the bot ran the command, my message deleted, then the bot's message also deleted. One way to fix this is to provide an if statement which means the bot only deletes the message if the author is not a bot.
#test_bot.event
async def on_message(message):
if not (message.author).bot:
await test_bot.delete_message(message)
await test_bot.process_commands(message)
Another way to remove only messages that are the commands is to use another if statement. The following code is specific, so you only delete commands, not just all user's messages if they aren't a bot. The following code uses message.content which returns the message as a string.
#test_bot.event
async def on_message(message):
if message.content.startswith('.s'):
await test_bot.delete_message(message)
await test_bot.process_commands(message)

Resources