So I made a giveaway command in a cog, and for some weird reason it's not working. I'm not getting any errors or anything. Since it's "interactive", the first two questions work fine but once it asks for the prize, it just freezes and doesn't do anything after that. My friend is also working on a different bot and gave me his code which worked perfectly on his end, but not on mine. Here is my code:
import discord
from discord.ext import commands
from discord.ext.commands import BucketType, cooldown, CommandOnCooldown
import random
import json
import datetime
import asyncio
class Giveaway(commands.Cog):
"""Giveaway commands. You must have manage message permissions to use these"""
def __init__(self, bot):
self.bot = bot
# Helper functions
def convert(self, time):
pos = ["s", "m", "h", "d"]
time_dict = {"s": 1, "m": 60, "h": 3600, "d": 2600*24}
unit = time[-1]
if unit not in pos:
return -1
try:
val = int(time[:-1])
except:
return -2
return val * time_dict[unit]
# Bot Events
# Bot Commands
#commands.command()
#commands.has_permissions(kick_members=True)
async def giveaway(self, ctx, host: discord.Member):
await ctx.send("Let's start with this giveaway! Answer these questions within 15 seconds!")
questions = ["Which channel should it be hosted in?",
"What should be the duration of the giveaway? (s|m|h|d)",
"What is the prize of the giveaway?"]
answers = [f"{ctx.channel.mention}"]
def check(m):
return m.author == ctx.author and m.channel == ctx.channel
for i in questions:
await ctx.send(i)
try:
msg = await self.bot.wait_for('message', timeout=15.0, check=check)
except asyncio.TimeoutError:
await ctx.send('You didn\'t answer in time, please be quicker next time!')
return
else:
answers.append(msg.content)
try:
c_id = int(answers[0][2:-1])
except:
await ctx.send(f"You didn't mention a channel properly smh")
return
channel = self.bot.get_channel(c_id)
time = convert(answers[2])
prize = answers[3]
await ctx.send(f"The giveaway for {prize} will be in {channel.mention} and will last {answers[2]}!! Hosted by {host.mention}")
embed = discord.Embed(title="Giveaway!", description=f"{prize}", color=discord.Colour.dark_purple())
embed.add_field(name="Hosted by:", value=f"{host}")
embed.set_footer(text=f"Ends {answers[2]} from now!")
my_msg = await channel.send(embed=embed)
await my_msg.add_reaction("🎉")
await asyncio.sleep(time)
new_msg = await channel.fetch_message(my_msg.id)
users = await new_msg.reactions[0].users().flatten()
users.pop(users.index(self.bot.user))
winner = random.choice(users)
await channel.send(f"Congratulations! {winner.mention} won the prize: {prize} from {host.mention}!!")
def setup(bot):
bot.add_cog(Giveaway(bot))
Please let me know what I should do to fix it!!
Related
I was trying to make a embed command with time limit, só i started doing it, and at my first try to make it timed it didn't work.
So i searched here, found one sample and tried to do like it (as you can see at my code below), but it didn't work too.
Then i tried to copy that code and pasted at my bot.
Guess...it didn't work -_-, now i'm here, asking gods to help.
client.command(aliases=["createEmbed", "embedCreate"])
async def embed(ctx,):
Questions = ["Titulo?", "Cor? (Hex sem #)", "Descrição?"]
Responses = []
def check(m):
return m.author == ctx.author and m.channel == ctx.channel
#try:
await ctx.send(Questions[0])
title = await client.wait_for('message',timeout=2.0,check=check)
#except asyncio.TimeoutError(*title):
#await ctx.send("Demorou muito")
#return
#else:
Responses.append(title.content)
await ctx.send(Questions[1])
cor = await client.wait_for('message',timeout=25.0,check=check)
Responses.append(cor.content)
await ctx.send(Questions[2])
descrição = await client.wait_for('message',timeout=25.0,check=check)
Responses.append(descrição.content)
cor2 = Responses[1]
corHex = int(cor2, 16)
embedVar = discord.Embed(title=Responses[0], description=Responses[2], color=corHex)
await ctx.send(embed=embedVar)
At my code you can see the piece with #, that is the piece that i tried to test the time command.
If i remove the time command, it works.
It is better to loop through questions and get the date after that make the embed. Below is an example of how to get the Title and Description. You can modify it how you like
#client.command(aliases=["createEmbed", "embedCreate"])
async def embed(ctx):
questions = ["Title?", "Description?"]
responses = []
def check(m):
return m.author == ctx.author and m.channel == ctx.channel
for question in questions:
try:
await ctx.send(question)
message = await client.wait_for('message', timeout=15, check=check)
except asyncio.TimeoutError:
await ctx.send("Timeout")
return
else:
responses.append(message.content)
embedVar = discord.Embed(title=responses[0], description=responses[1])
await ctx.send(embed=embedVar)
I made a discord bot that shows you gifs when you type a certain command but the problem is that it works fine in the first half but takes a long time to show the gifs when not used.
Basically it doesn't show the gifs instantly when not used.
Here's the code that I've written:
#client.command()
async def gif(ctx, *, q = 'dance'):
api_key = 'Some Key here'
api_instanc = giphy_client.DefaultApi()
try:
api_responce = api_instanc.gifs_search_get(api_key, q, limit = 7,rating = 'r')
lst = list(api_responce.data)
giff = random.choice(lst)
emb = discord.Embed(title = f"Requested by {ctx.author} " + q )
emb.set_image(url= f'https://media.giphy.com/media/{giff.id}/giphy.gif')
await ctx.channel.send(embed = emb)
except ApiException as e:
await ctx.channel.send("API EXCEPTION")
It doesn't show any errors but doesn't work after the long time.
Any re-write of the code with aiohttp will be appreciated because I am learning that.
I think the module you are using is not asynchronous which leads to blocking read more.
Default in the command is search = None you can use that with an if statement to check.
After that is the request for the api to get the image.
Here is the code edited to use aiohttp
# import aiohttp
# import random
#bot.command()
async def giphy(ctx, search: str = None):
api_key = ""
embed = discord.Embed(title=f"Requested by {ctx.author}")
async with aiohttp.ClientSession() as session:
# search
if search:
embed.description = search
async with session.get(f'http://api.giphy.com/v1/gifs/search?q={search}&api_key={api_key}&limit=10') as response:
data = await response.json()
gif_choice = random.randint(0, 9)
embed.set_image(url=data['data'][gif_choice]['images']['original']['url'])
# radnom
else:
async with session.get(f'http://api.giphy.com/v1/gifs/random?api_key={api_key}&limit=10') as response:
data = await response.json()
embed.set_image(url=data['data']['images']['original']['url'])
await ctx.send(embed=embed)
I'm making a discord bot and a problem that has come up for me is that the bot won't reply to the user, here is the code
#Code Imports
import discord
import random
from discord import message
from discord import channel
from discord.embeds import Embed
from discord.ext import commands
from discord.ext.commands.bot import Bot
from discord.message import Message
from apikeys import *
from discord import guild
from discord import emoji
from discord import *
from discord import ContentFilter
from discord import channel
from discord import client
#intents
intents=discord.Intents.default()
intents.members=True
#prefix
client=commands.Bot(command_prefix='!',intents=intents)
#Start
#client.event
async def on_ready():
for emoji in client.emojis:
print("Name:", emoji.name + ",", "ID:", emoji.id)
print('Bot is Online {0.user}'.format(client))
print("--------------------------------------------------------------------------------------------------------------------------------------------------------")
client.remove_command('help')
#Commands
#client.command()
async def work(ctx):
await ctx.send('use !war to get up the war menu')
emojigood = '\N{THUMBS UP SIGN}'
emojibad="\N{THUMBS DOWN SIGN}"
#client.command()
async def help(ctx):
embed=discord.Embed(title='Help', description='!war is currently under testing please do not complain about it', color=0x00000)
await ctx.send(embed=embed)
#client.command()
async def war(ctx):
embed = discord.Embed(title='War', description='You are starting a war, do you want to continue?', color=0x00000)
msg = await ctx.send(embed=embed)
await msg.add_reaction(emojigood)
await msg.add_reaction(emojibad)
def check(r, user):
return (r.emoji == emojigood or r.emoji == emojibad) and r.message == msg
#Checks whether the message is the same, and the emoji is one of the accepted ones, and returns either True or False
r, user = await client.wait_for('reaction_add',timeout=10 ,check=check)
#this is equivalent to a event listener within your command, it will stop there until a reaction that meets the requirements has been found
#(This won't block other commands and functions)
if r.emoji == emojigood:
embed = discord.Embed(title='War', description='Please now choose a country', color=0x00000)
await ctx.send(embed=embed)
prefix = "!" #insert your prefix
async def on_message(message):
if message.author == client.user:
return
if message.content == f'{prefix}war': #dont need to use this string, just illustrating the point
await message.channel.send("What country do you want to start a war with?")
def check(msg):
return msg.author == message.author and len(msg.role_mentions) > 0
msg = await client.wait_for('message', check=check)
role = msg.role_mentions[0]
channel = client.get_channel(849230881994047508)
await channel.send(f"{role.mention} {message.author} has declared war on you.")
client.run(token)
What's meant to happen:
Bot: Which role would you like to start a war with
User:#something
Bot:Send information to UN, 'War on #something'
I don't know how to make it see the role mention
You have a couple of issues, the way to make the code you're using function decently is to replace message.content with message.clean_content, however, 1. That will react to any message starting with # or a mention, which is probably not what you want, and 2. any message not beginning with the mention wouldn't work.
You say in your description that you're looking for role mentions, which is a different attribute, and you're looking to send a message, and wait for a response, so here's a piece of sample code that would solve those issues, assuming I'm interpreting your question correctly:
def check(msg):
return msg.author == message.author and len(msg.role_mentions) > 0
msg = await client.wait_for('message', check=check)
role = msg.role_mentions[0]
channel = client.get_channel(ID of the channel)
await channel.send(f"{role.mention} {message.author} has declared war on you."
If I misinterpreted any of what you wanted or you're not sure how some of it works, shoot me a comment and I'll do my best to explain!
Docs reference for slightly more complex objects used:
role_mentions,
wait_for(),
how are you doing today i sure hope your doing great im sorry for the spam on other account i apologize. ok so my problem is that i switched from client to bot basically bot = commands.Bot i tried renaming all the commmands to bot.event or bot.command can someone pls help me pls i would appreciate it thank you here is the code :)
#bot.command()
async def ping(ctx):
await ctx.send(f'Pong!\n`{round(client.latency*1000)}ms`')
#bot.command(aliases=['8ball'])
async def _8ball(ctx, *, question):
responses = [ "It is certain.",
"As I see it, yes",
"Ask again later.",
"Better not tell you now.",
"Cannot predict now.",
"Concentrate and ask again.",
"Don't count it",
"It is certain.",
"It is decidedly so.",
"Most likely.",
"My reply is no."
"My sources say no.",
"Outlook not so good.",
"Outlook good.",
"Reply hazy, try again.",
"Signs point to yes.",
"Very doubtful.",
"Without a doubt.",
"Yes.",
"Yes – definitely.",
"You may rely on it." ]
await ctx.send(f'Question: {question}\nAnswer: {random.choice(responses)}')
#commands.has_permissions(ban_members=True)
#bot.command()
async def kick(ctx, user: discord.Member, *, reason="No reason provided"):
await user.ban(reason=reason)
kick = discord.Embed(title=f":boom: Kicked {user.name}!", description=f"Reason: {reason}\nBy: {ctx.author.mention}")
await ctx.message.delete()
await ctx.channel.send(embed=kick)
await user.send(embed=kick)
#commands.has_permissions(ban_members=True)
#bot.command()
async def ban(ctx, user: discord.Member, *, reason="No reason provided"):
await user.ban(reason=reason)
ban = discord.Embed(title=f":boom: Banned {user.name}!", description=f"Reason: {reason}\nBy: {ctx.author.mention}")
await ctx.message.delete()
await ctx.channel.send(embed=ban)
await user.send(embed=ban)
#bot.command()
async def unban(ctx, *, member):
banned_users = await ctx.guild.bans()
member_name, member_discriminator = member.split('#')
for ban_entry in banned_users:
user = ban_entry.user
if (user.name, user.discriminator) == (member_name, member_discriminator):
await ctx.guild.unban(user)
await ctx.channel.send(f"Unbanned: {user.mention}")
#bot.command(pass_context = True)
async def mute(ctx, user_id, userName: discord.User):
if ctx.message.author.server_permissions.administrator:
user = ctx.message.author
role = discord.utils.get(user.server.roles, name="Muted")
#bot.command()
async def serverinfo(ctx):
name = str(ctx.guild.name)
description = str(ctx.guild.description)
owner = str(ctx.guild.owner)
id = str(ctx.guild.id)
region = str(ctx.guild.region)
memberCount = str(ctx.guild.member_count)
icon = str(ctx.guild.icon_url)
embed = discord.Embed(
title=name + " Server Information",
description=description,
color=discord.Color.blue()
)
embed.set_thumbnail(url=icon)
embed.add_field(name="Owner", value=owner, inline=True)
embed.add_field(name="Server ID", value=id, inline=True)
embed.add_field(name="Region", value=region, inline=True)
embed.add_field(name="Member Count", value=memberCount, inline=True)
await ctx.send(embed=embed)
await client.add_roles(user, role)
#bot.command()
async def setdelay(ctx, seconds: int):
await ctx.channel.edit(slowmode_delay=seconds)
await ctx.send(f"Set the slowmode delay in this channel to {seconds} seconds!")
#bot.command()
async def afk(ctx, mins):
current_nick = ctx.author.nick
await ctx.send(f"{ctx.author.mention} has gone afk for {mins} minutes.")
await ctx.author.edit(nick=f"{ctx.author.name} [AFK]")
counter = 0
while counter <= int(mins):
counter += 1
await asyncio.sleep(60)
if counter == int(mins):
await ctx.author.edit(nick=current_nick)
await ctx.send(f"{ctx.author.mention} is no longer AFK")
break
def setup(bot):
bot.add_cog(Afk(bot))
def user_is_me(ctx):
return ctx.message.author.id == "Your ID"
def convert(time):
pos = ["s","m","h","d"]
time_dict = {"s" : 1, "m" : 60, "h" : 3600, "d": 3600*24}
unit = time[-1]
if unit not in pos:
return -1
try:
val = int(time[:-1])
except:
return -2
return val * time_dict[unit]
#bot.command()
#commands.has_permissions(kick_members=True)
async def giveaway(ctx):
await ctx.send("Let's start with this giveaway! Answer these questions within 15 seconds!")
questions = ["Which channel should it be hosted in?", "What should be the duration of the giveaway? (s|m|h|d)", "What is the prize of the giveaway?"]
answers = []
def check(m):
return m.author == ctx.author and m.channel == ctx.channel
for i in questions:
await ctx.send(i)
try:
msg = await bot.wait_for('messsage', timeout=15.0, check=check)
except asyncio.TimeoutError:
await ctx.send('You didn\'t answer in time, please be quicker next time!')
return
else:
answers.append(msg.content)
try:
c_id = int(answers[0][2:-1])
except:
await ctx.send(f"You didn't mention a channel properly. Do it like this {ctx.channel.mention} next time.")
return
channel = bot.get_channel(c_id)
time = convert(answers[1])
if time == -1:
await ctx.send(f"You didn't answer with a proper unit. Use (s|m|h|d) next time!")
return
elif time == -2:
await ctx.send(f"The time just be an integer. Please enter an integer next time.")
return
prize = answers[2]
await ctx.send(f"The giveaway will be in {channel.mention} and will last {answers[1]} seconds!")
embed = discord.embed(title = "Giveaway!", description = f"{prize}", color = ctx.author.color)
embed.add_field(name = "Hosted by:", value = ctx.author.mention)
embed.set_footer(text = f"Ends {answers[1]} from now!")
my_msg = await channel.send(embed = embed)
await my_msg.add_reaction("🎉")
await asyncio.sleep(time)
new_msg = await channel.fetch_message(my_msg.id)
users = await new_msg.reactions[0].users().flatten()
users.pop(users.index(bot.user))
winner = random.choice(users)
await channel.send(f"Congratulations! {winner.mention} won the prize: {prize}!")
#bot.command()
#commands.has_permissions(kick_members=True)
async def reroll(ctx, channel : discord.TextChannel, id_ : int):
try:
new_msg = await channel.fetch_message(id_)
except:
await ctx.send("The ID that was entered was incorrect, make sure you have entered the correct giveaway message ID.")
users = await new_msg.reactions[0].users().flatten()
users.pop(users.index(bot.user))
winner = random.choice(users)
await channel.send(f"Congratulations the new winner is: {winner.mention} for the giveaway rerolled!")
if you want me to answer anything to help you solve it feel free to comment thank you so much have a great day!
It seems like you copied most of the code from the internet and bashed it together to create a bot or a cog (based on your question I would guess a bot).
Assuming this is a snippet of your main bot file and not a cog there are a couple of things that could be different:
Put your utility functions in one place (peferably after your import statatements). It's good practise overall and makes more readeable code.
Unless you have a cog class in the same file as your bot instance (which is bad practise) you shouldn't need this:
def setup(bot):
bot.add_cog(Afk(bot))
If there is a cog class named Afk you should move it into a separate file (putting the cog class into the main bot file defeats the purpose of the cog)
In your mute command you have pass_context = True. This is from the old version of discord.py and is no longer needed.
I can't tell you much more since there's no point in trying to debug your code since you didn't give us any errors or stacktrace to work with.
It is very exhausting, so you can just leave client in every command, just write this client = commands.Bot(command_prefix = 'your prefix') it is the same bot, but it just has a different name.
If you meant that, because i didn't really understand what you need
i have a problem with my discord bot, whenever i run the code below using apraw to get the titles of the recent submissions on a subreddit the bot doesn't appear online anymore but still returns the titles in CMD :
Bot is not online when i execute this but still asks for subreddit name & prints the titles of the new posts of the subreddit in CMD:
import asyncio
import apraw
from discord.ext import commands
bot = commands.Bot(command_prefix = '?')
#bot.event
async def on_ready():
print('Bot is ready')
await bot.change_presence(status=discord.Status.online, activity=discord.Game('?'))
#bot.command()
async def online (ctx):
await ctx.send('Bot is online !')
reddit = apraw.Reddit(client_id = "CLIENT_ID",
client_secret = "CLIENT_SECRET",
password = "PASSWORD",
user_agent = "pythonpraw",
username = "LittleBigOwl")
#bot.event
async def scan_posts():
xsub = str(input('Enter subreddit name : '))
subreddit = await reddit.subreddit(xsub)
async for submission in subreddit.new.stream():
print(submission.title)
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(scan_posts())
bot.run('TOKEN')
But is online when i execute this but obviously doesn't ask for sub name... :
import asyncio
import apraw
from discord.ext import commands
bot = commands.Bot(command_prefix = '?')
#bot.event
async def on_ready():
print('Bot is ready')
await bot.change_presence(status=discord.Status.online, activity=discord.Game('?'))
#bot.command()
async def online (ctx):
await ctx.send('Bot is online !')
bot.run('TOKEN')
So reddit is the problem here. But what exaclty do i ahve to change in order to make my bot apear online whilst still being able to retreive the titles of new submissions on a given subreddit? The code doesn't return any error:/
the #bot.event that you put above async def scan_posts(): should be changed to #bot.command(). It triggers by itself because you have this in your code:
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(scan_posts())
this is what causes the scan_posts to run automatically. You should remove this as you want scan_posts to be a bot command and not something that happens automatically. The bot also doesn't come online because of this code. What this does is check if this file has been run and then runs scan_posts. The rest of the code won't be triggered.
Also, you shouldn't change presence in on_ready as Discord has a high chance to completely disconnect you during the on_ready event and there is nothing you can do to prevent it. Instead you can use the activity and status kwargs in commands.Bot like:
bot = commands.Bot(command_prefix = '?', status=discord.Status.online, activity=discord.Game('?'))