Invoke a bot message when the user has not specified a nickname - python-3.x

I want my bot to write
Error, you did not specify a nickname.
My code:
if message.content.startswith(prefix + 'kill'):
name = message.mentions[0]
randomgif = random.choice(["https://i.imgur.com/Pk6lOwI.gif","https://i.imgur.com/IRoF2pJ.gif","https://i.imgur.com/dV2N6KJ.gif","https://i.imgur.com/xyhP7Rz.gif","https://i.imgur.com/CzpHqFX.gif","https://i.imgur.com/iBsrA1c.gif","https://i.imgur.com/4jHevGp.gif","https://i.imgur.com/Oy2XGuL.gif","https://i.imgur.com/1uQwyli.gif","https://i.imgur.com/uCUf0V5.gif","https://i.imgur.com/xfubfyv.gif","https://i.imgur.com/8th0trO.gif","https://i.imgur.com/2jOXQcP.gif","https://i.imgur.com/2kCGfie.gif","https://i.imgur.com/TPV6Upz.gif","https://i.imgur.com/Bti43x8.gif"])
embed=discord.Embed(color=0x008C8C)
embed.set_author(name= message.author.display_name + " убил " + name.display_name, icon_url='https://pre00.deviantart.net/7e08/th/pre/f/2017/125/2/2/felix_argyle_by_aramisdraws-db8847i.png')
embed.set_image(url= randomgif)
await client.send_message(message.channel, embed=embed)

Member.nick is the server-specific nickname of a member. If there is no such name, it will be None.
import discord
from discord.ext import commands
import random
bot = commands.Bot(command_prefix=prefix)
#bot.command(pass_context=True)
async def kill(ctx, member: discord.Member):
if member.nick is None:
await bot.say("Error! You did not specify a nickname")
return
randomgif = random.choice(["https://i.imgur.com/Pk6lOwI.gif","https://i.imgur.com/IRoF2pJ.gif","https://i.imgur.com/dV2N6KJ.gif","https://i.imgur.com/xyhP7Rz.gif","https://i.imgur.com/CzpHqFX.gif","https://i.imgur.com/iBsrA1c.gif","https://i.imgur.com/4jHevGp.gif","https://i.imgur.com/Oy2XGuL.gif","https://i.imgur.com/1uQwyli.gif","https://i.imgur.com/uCUf0V5.gif","https://i.imgur.com/xfubfyv.gif","https://i.imgur.com/8th0trO.gif","https://i.imgur.com/2jOXQcP.gif","https://i.imgur.com/2kCGfie.gif","https://i.imgur.com/TPV6Upz.gif","https://i.imgur.com/Bti43x8.gif"])
embed=discord.Embed(color=0x008C8C)
embed.set_author(name= ctx.message.author.display_name + " убил " + member.display_name, icon_url='https://pre00.deviantart.net/7e08/th/pre/f/2017/125/2/2/felix_argyle_by_aramisdraws-db8847i.png')
embed.set_image(url= randomgif)
await bot.say(embed=embed)
If you're implementing commands, you should be using the discord.ext.commands module, that's what it's for.

Related

Discord bot stickers

Is there a way that I can get my discord bot to send stickers after somebody says a certain thing, I got normal messages and emojis to work while it replies but there is not much learning material to find out how to get stickers to work with discord.py.
This is my code :
import discord
from discord.ext import commands
bot = commands.Bot(command_prefix='.nerd ', description = 'nerd eyes')
#bot.event
async def on_ready():
guild_count = 0
for guild in bot.guilds:
print(f"- {guild.id} (name: {guild.name})")
guild_count = guild_count + 1
print('Nerdeyes has awoken in ' + str(guild_count) + " servers")
#bot.event
async def on_message(message):
if message.author == bot.user:
return
if message.content.startswith('nerd'):
msg = 'eyes'
await message.channel.send(msg)
if message.content.startswith('guy'):
msg = '<:guysusthink:873066296558882847>'
await message.channel.send(msg)
bot.run("TOKEN")
Stickers are a new Discord feature and haven't been added yet in Discord.py. You're gonna have to wait a bit until they release the new version.

Discord Poll Bot

Hi i am trying to make a poll bot but ive encountered a problem here is the code ignore the other commands other than + poll
import discord
import os
import requests
import json
import random
pollid = 0
emoji1 = '\N{THUMBS UP SIGN}'
emoji2 = '\N{THUMBS DOWN SIGN}'
client = discord.Client()
sad_words=["sad","depressed", "unhappy","angry","miserable","depressing"]
starter_encouragements = ["Cheer up", "hang in there.", "You are a great person / bot!"]
def get_quote():
response = requests.get("https://zenquotes.io/api/random")
json_data = json.loads(response.text)
quote = json_data[0]['q'] + " -" + json_data[0]['a']
return[quote]
from discord.utils import get
#client.event
async def on_ready():
print('We have logged in as {0.user}'.format(client))
#client.event
async def on_message(message):
global pollid
#if message.author == client.user:
# return
msg = message.content
if message.content.startswith('+encourage'):
quote=get_quote()
await message.channel.send(quote)
if any(word in msg for word in sad_words):
await message.channel.send(random.choice(starter_encouragements))
if message.content.startswith("+joke"):
from dadjokes import Dadjoke
dadjoke = Dadjoke()
await message.channel.send(dadjoke.joke)
if message.content.startswith("+poll"):
pollid = pollid+1
await message.channel.send(content = msg.split(' ', 1)[1] + ' (number of polls made ' + str(pollid) + ')')
if message.author == client.user:
await message.add_reaction(emoji1)
await message.add_reaction(emoji2)
reaction = get(message.reactions, emoji=emoji1)
#reaction2 = get(message.reactions, emoji=emoji2)
#if (reaction != None and reaction2 != None):
# totalcount = reaction.count + reaction2.count
#if totalcount>=2:
if (reaction != None and reaction.count != 1):
await message.channel.send('The outcome of the poll is yes'+ str(reaction.count))
# await message.channel.send('The outcome of the poll is no')
client.run(os.getenv('TOKEN'))
i am very new to python and the discord api for it ive been trying to set up a poll system where it has a timer on each poll that lasts 24 hrs and after 24 hrs it compares the amount of reactions on the message to see which side wins. Can someone help me with this. Thanks
I would not use on_message events for that but instead use a command.
You can do something like this:
import discord
from discord.ext import commands
#client.command()
async def poll(ctx, *, text: str):
poll = await ctx.send(f"{text}")
await poll.add_reaction("✅")
await poll.add_reaction("❌")
Here we have text as a str so you can add as many text as you want.
If you want to compare it after 24 hours you would also have to build in a cooldown saver if the bot restarts, otherwise we could go with await asyncio.sleep(TimeAmount)
If you want to check the result with a command we could go for this:
from discord.utils import get
import discord
from discord.ext import commands
#client.command()
async def results(ctx, channel: discord.TextChannel, msgID: int):
msg = await channel.fetch_message(msgID)
reaction = get(msg.reactions, emoji='✅')
count1 = reaction.count # Count the one reaction
reaction2 = get(msg.reactions, emoji="❌")
count2 = reaction2.count # Count the second reaction
await ctx.send(f"✅**: {count1 - 1}** and ❌**: {count2 - 1}**") # -1 is used to exclude the bot
The usage of the command would be: results #channel MSGID.
Be aware that fetch is an API call and could cause a ratelimit.

Discord.py grabbing twitch URL without an API

I have a discord bot.
What I want it to do is when the bot detects a user is streaming, print the URL of their stream into chat.
I'm having a problem trying to find out how to get the user's twitch channel url...
this is what I have
#client.event
async def on_member_update(before, after):
aname = after.display_name
aactivity = after.activity.type
mactivity = str(after.activities)
role = after.guild.get_role(736271867836498031)
channel = client.get_channel(736269005651836985)
memberinfo = after.activities.streaming.url
print(memberinfo)
if "Streaming name" in mactivity:
await after.add_roles(role)
await channel.send('{} has started streaming!'.format(after.display_name))
print(aname + " is streaming!")
else:
await after.remove_roles(role)
streamchannel = discord.Profile
await channel.send('{} is not streaming!'.format(after.display_name))
print(aname + " is not streaming.")
print('member updated status')
Is there something I'm missing? I don't know how at all to either find the URL of the streamer, or get it from their connect accounts.
Member objects have a Activity attribute. You can check if before.activity or after.activity is an instance of the Streaming class.
If so, the user either stopped or started streaming and we can send a message in channel:
from discord import Streaming
from discord.utils import get
#client.event
async def on_member_update(before, after):
if not before.activity.type == after.activity.type:
return
role = get(after.guild.roles, id=736271867836498031)
channel = get(after.guild.channels, id=736269005651836985)
if isinstance(after.activity, Streaming):
await after.add_roles(role)
await channel.send(f"{before.mention} is streaming on {activity.platform}: {activity.name}.\nJoin here: {activity.url}")
elif isinstance(before.activity, Streaming):
await after.remove_roles(role)
await channel.send(f'{after.mention} is no longer streaming!')
else:
return
Reference: discord.py documentation

How to loop a task in discord.py

I am experimenting with making my own little discord bot that can get information from Twitch, but I'm stumped on how to make the bot loop and check for a condition.
I want the bot to loop a section of code every few seconds that checks if the specified twitch channel is live.
Code
import discord
from discord.ext import commands, tasks
from twitch import TwitchClient
from pprint import pformat
client = TwitchClient(client_id='<twitch token>')
bot = commands.Bot(command_prefix='$')
#bot.event
async def on_ready():
print('We have logged in as {0.user}'.format(bot))
#bot.command()
async def info(ctx, username):
response = await ctx.send("Querying twitch database...")
try:
users = client.users.translate_usernames_to_ids(username)
for user in users:
print(user.id)
userid = user.id
twitchinfo = client.users.get_by_id(userid)
status = client.streams.get_stream_by_user(userid)
if status == None:
print("Not live")
livestat = twitchinfo.display_name + "is not live"
else:
livestat = twitchinfo.display_name + " is " + status.stream_type
responsemsg = pformat(twitchinfo) + "\n" + livestat
await response.edit(content=responsemsg)
except:
await response.edit(content="Invalid username")
bot.run("<discord token>")
I want the bot to run the following code every 10 seconds, for example:
status = client.streams.get_stream_by_user(<channel id>)
if status == None:
print("Not live")
livestat = twitchinfo.display_name + "is not live"
else:
livestat = twitchinfo.display_name + " is " + status.stream_type
I've tried using #tasks.loop(seconds=10) to try and make a custom async def repeat every 10 seconds but it didn't seem to work.
Any ideas?
The newer version of discord.py doesn't support client.command()
To achieve the same I used the following snippet
import discord
from discord.ext import tasks
client = discord.Client()
#tasks.loop(seconds = 10) # repeat after every 10 seconds
async def myLoop():
# work
myLoop.start()
client.run('<your token>')
This can be done like so:
async def my_task(ctx, username):
while True:
# do something
await asyncio.sleep(10)
#client.command()
async def info(ctx, username):
client.loop.create_task(my_task(ctx, username))
References:
asyncio.create_task()
asyncio.sleep()
This is the most proper way to implement background tasks.
from discord.ext import commands, tasks
bot = commands.Bot(...)
#bot.listen()
async def on_ready():
task_loop.start() # important to start the loop
#tasks.loop(seconds=10)
async def task_loop():
... # this code will be executed every 10 seconds after the bot is ready
Check this for more info
I struggled with this as well. The problem I ran into is that none of the examples online were complete. Here is one I came up with that uses #tasks.loop(seconds=10).
import discord
import os
from discord.ext import tasks
from dotenv import load_dotenv
intents = discord.Intents.all()
client = discord.Client(command_prefix="!", intents=intents)
load_dotenv()
token = os.getenv("DISCORD_TOKEN")
CHANNEL_ID = 1234
#client.event
async def on_ready():
print(f"We have logged in as {client.user}")
myloop.start()
#client.event
async def on_message(message):
if message.author == client.user:
return
if message.content.startswith("hi"):
await message.channel.send("Hello!")
#tasks.loop(seconds=10)
async def myloop():
channel = client.get_channel(CHANNEL_ID)
await channel.send("Message")
client.run(token)

Why has is_closed stopped working in the rewrite version?

I am new to the Discord python API. I am trying to run a method forever as long as the client is still open. I scheduled the method through Client.loop.create_task(), and am running while not client.is_closed. I added a debugging print statement, but the print statement is called 0 times.
I based the code on this post: Discord.py Schedule
import discord
from datetime import datetime
from datetime import timedelta
token = "TOKEN"
s_users = {}
timezon_offset = 5
inac_days = 0
inac_hours = 0
inac_minutes = 1
active_role = "Active"
inac_role = "Inactive"
client = discord.Client()
async def monitor():
for guild in client.guilds:
for user in guild.members:
s_users[user] = datetime(1,1,1)
#client.event
async def on_ready():
print('logged on as {0}'.format(client.user))
#client.event
async def on_message(message):
print('message logged from {0.author}: {0.content} at {0.created_at}'.format(message))
s_users[message.author] = message.created_at - timedelta(hours=timezon_offset)
async def task():
await client.wait_until_ready()
active = None
inactive = None
for guild in client.guilds:
for role in guild.roles:
if (role.name == active_role):
active = role
elif (role.name == inac_role):
inactive = role
while not client.is_closed:
print("here")
for user in s_users:
if datetime.now() - s_users[user] > timedelta(days=inac_days, hours=inac_hours, minutes=inac_minutes):
if not(inac_role in [role.name for role in user.roles]):
await user.remove_roles(active)
await user.add_roles(inactive)
print("gave user: " + user.name + " " + inac_role + " role")
if datetime.now() - s_users[user] <= timedelta(days=inac_days, hours=inac_hours, minutes=inac_minutes):
if not(active_role in [role.name for role in user.roles]):
await user.remove_roles(inactive)
await user.add_roles(active)
print("gave user: " + user.name + " " + active_role + " role")
client.loop.create_task(task())
client.run(token)
It should execute task(), which should run as long as the client is not closed. However, the print statement is executed 0 times.
In version 1.0.0, Client.is_closed was changed from a property to a method. See Property Changes in the Migration guide.
You'll need to add parentheses to call the method:
while not client.is_closed():
...

Resources