Hey so this code works completely fine but my problem is that it gets info of all the servers that the bot is in.
#commands.Cog.listener()
async def on_user_update(self, before, after):
logs = self.bot.get_channel(810977833823240262)
embed = discord.Embed(colour=0x7289da)
embed.description = f"{after.name} has changed his avatar"
if before.avatar_url != after.avatar_url:
embed.add_field(name="New avatar")
embed.set_image(url=after.avatar_url)
if before.name != after.name:
embed.add_field(name="Previous name",value=before.name,inline=False)
embed.add_field(name="New name ",value=after.name,inline=False)
if before.status != after.status:
embed.add_field(name="Previous Status",value=before.status,inline=False)
embed.add_field(name="New Status ",value=after.status,inline=False)
await logs.send(embed=embed)
This code is for logs so I want it to have different logs for each server. For example, I don't want to show a server that I'm not in if I changed avatar or anything.
Any help is appreciated
You can simply check if you have any mutual guilds with the user that updated it's info
#commands.Cog.listener()
async def on_user_update(self, before, after):
my_id = YOUR_ID_HERE # Obviously put your ID here
mutual_guilds = [g for g in self.bot.guilds if g.get_member(my_id) and g.get_member(after.id)]
if mutual_guilds: # Checking if the list is not empty
# The user is in one of your guilds
logs = self.bot.get_channel(810977833823240262)
embed = discord.Embed(colour=0x7289da)
embed.description = f"{after.name} has changed his avatar"
if before.avatar_url != after.avatar_url:
embed.add_field(name="New avatar")
embed.set_image(url=after.avatar_url)
if before.name != after.name:
embed.add_field(name="Previous name",value=before.name,inline=False)
embed.add_field(name="New name ",value=after.name,inline=False)
if before.status != after.status:
embed.add_field(name="Previous Status",value=before.status,inline=False)
embed.add_field(name="New Status ",value=after.status,inline=False)
await logs.send(embed=embed)
To explain a bit more the list comprehension:
mutual_guilds = []
for g in self.bot.guilds: # Looping though every guild
if g.get_member(my_id) and g.get_member(after.id): # Checking if both you and the user are in the guild
mutual_guilds.append(g)
Related
I am currently working on a system that deletes a channel when the user leaves. This system works by, when a user asks for it, a command is used to create the channel and the member id and channel id are stored in mongodb, as shown in the picture below:
My current code for this is:
#commands.Cog.listener()
async def on_member_remove(self, member):
channelfind = cluster["Channels"]["info"]
if member.guild.id == testid:
joinedat = diskord.utils.utcnow() - member.joined_at
time = humanize.precisedelta(joinedat, format="%0.0f")
embed = diskord.Embed(title="\u200b", color=0xfc8eac)
embed: Embed = diskord.Embed(
description= f'**{member.mention} left the server**\n:timer: **Joined:**\n{time} ago',
color=0xfc8eac
)
embed.set_author(name=member, icon_url=member.avatar.url)
embed.set_thumbnail(url=member.avatar.url)
embed.timestamp = datetime.datetime.utcnow()
embed.set_footer(text=f'ID: {member.id} \u200b ')
memberid = channelfind.find_one({"member_id": member.id})
if memberid is not None:
log = testlog
await self.bot.get_channel(log).send(embed=embed)
else:
pass
However, I am not sure how I can find the channel_id that is with the member_id of the user who has left
Any help would be appreciated thank you!
.find_one() returns a dictionary representing the document. So, you can do
memberid = channelfind.find_one({"member_id": member.id})
print(memberid['channel_id'])
to get the channel_id.
For my problem I ended up using the discom pip library, but if there is any other way to do what I want, I would be happy for the suggestions.
I want to find out what are the datetimes when a user joined a specific discord group.
I managed to get all the IDs of the users from a group, but the documentation is so poor for this library, that I'm having trouble getting the username and datetime joined. I see, that it should be possible, but I can't figure it quite out.
The code I have for the IDs is:
import discum
bot = discum.Client(token="token")
def close_after_fetching(resp, guild_id):
if bot.gateway.finishedMemberFetching(guild_id):
lenmembersfetched = len(bot.gateway.session.guild(guild_id).members)
print(str(lenmembersfetched)+' members fetched')
bot.gateway.removeCommand({'function': close_after_fetching, 'params' :{'guild_id': guild_id}})
bot.gateway.close()
def get_members(guild_id, channel_id):
bot.gateway.fetchMembers(guild_id, channel_id, wait=1)
bot.gateway.command({'function': close_after_fetching, 'params': {'guild_id': guild_id}})
bot.gateway.run()
bot.gateway.resetSession()
return bot.gateway.session.guild(guild_id).members
members = get_members('guild_id', 'channel_id')
membersList = []
for memberID in members:
membersList.append(memberID)
print(memberID)
I end up with a list of all the member IDs, but I need more.
Also, I have a suspicion, that the member list is not complete. Could that be true?
I understand, that this library is not widely used, but any help (especially other solutions) would be much appreciated.
SOLUTION
I ended up using a discord bot to get the list. It is much easier and much more documented.I still used python, but with discord library. 'access_token' is my discord bot token and the answer is put into a .txt file, because it could be to large for discord message.
import discord
import os
from io import BytesIO
import datetime
access_token= os.environ["ACCESS_TOKEN"]
intents = discord.Intents.default()
intents.members = True
client = discord.Client(intents=intents)
#client.event
async def on_ready():
print('We have logged in as {0.user}'.format(client))
#client.event
async def on_message(message):
if message.author == client.user:
return
if message.content.startswith('!members'):
userrole = message.author.top_role.name
if userrole == "Admin" or userrole == "Moderators":
memberList = ""
username = ''
dateJoined = ''
guilds = client.guilds
for guild in guilds:
members = guild.members
for member in members:
if member.bot == False:
username = member.name
dateJoined = member.joined_at.strftime("%d-%m-%Y %H:%M:%S")
memberList = memberList + username + "," + dateJoined + "\n"
as_bytes = map(str.encode, memberList)
content = b"".join(as_bytes)
await message.reply("Member List", file=discord.File(BytesIO(content), "members.txt"))
client.run(access_token)
I'm new to python and i'm making discord bot. So here i have twitch notification function, but when someone is live bot just starts spamming, i think because idk how to get content out of an embed. please help me. the code:
import os
import json
import discord
import requests
from discord.ext import tasks, commands
from discord.utils import get
intents = discord.Intents.all()
bot = commands.Bot(command_prefix='$', intents=intents)
TOKEN = os.getenv('token')
# Authentication with Twitch API.
client_id = os.getenv('client_id')
client_secret = os.getenv('Dweller_token')
body = {
'client_id': client_id,
'client_secret': client_secret,
"grant_type": 'client_credentials'
}
r = requests.post('https://id.twitch.tv/oauth2/token', body)
keys = r.json()
headers = {
'Client-ID': client_id,
'Authorization': 'Bearer ' + keys['access_token']
}
'''user_info = twitch.get_users(logins=['turb4ik'])
user_id = user_info['data'][0]['id']
print(user_info)'''
# Returns true if online, false if not.
def checkuser(streamer_name):
stream = requests.get('https://api.twitch.tv/helix/streams?user_login=' + streamer_name, headers=headers)
stream_data = stream.json()
if len(stream_data['data']) == 1:
return True, stream_data
else:
return False, stream_data
# Executes when bot is started
#bot.event
async def on_ready():
# Defines a loop that will run every 10 seconds (checks for live users every 10 seconds).
#tasks.loop(seconds=10)
async def live_notifs_loop():
# username = stream_data['data'][0]['user_name']
# stream_title = stream_data['data'][0]['title']
# game_being_played = stream_data['data'][0]['game_name']
# Opens and reads the json file
with open('streamers.json', 'r') as file:
streamers = json.loads(file.read())
# Makes sure the json isn't empty before continuing.
if streamers is not None:
# Gets the guild, 'twitch streams' channel, and streaming role.
guild = bot.get_guild(690995360411156531)
channel = bot.get_channel(798127930295058442)
role = get(guild.roles, id=835581408272580649)
# Loops through the json and gets the key,value which in this case is the user_id and twitch_name of
# every item in the json.
for user_id, twitch_name in streamers.items():
print("checking" + " " + str(twitch_name))
# Takes the given twitch_name and checks it using the checkuser function to see if they're live.
# Returns either true or false.
status, stream_data = checkuser(twitch_name)
# Gets the user using the collected user_id in the json
user = bot.get_user(int(user_id))
# Makes sure they're live
if status is True:
# Checks to see if the live message has already been sent.
async for message in channel.history(limit=200):
print("yes")
twitch_embed = discord.Embed(
title=f":red_circle: **LIVE**\n{user.name} is now streaming on Twitch! \n \n {stream_data['data'][0]['title']}",
color=0xac1efb,
url=f'\nhttps://www.twitch.tv/{twitch_name}'
)
twitch_embed.add_field(
name = '**Game**',
value = stream_data['data'][0]['game_name'],
inline = True
)
twitch_embed.add_field(
name = '**Viewers**',
value = stream_data['data'][0]['viewer_count'],
inline = True
)
twitch_embed.set_author(
name = str(twitch_name),
icon_url = stream_data['data'][0]['thumbnail_url']
)
twitch_embed.set_image(url = f'https://www.twitch.tv/{twitch_name}')
print("yes2")
try:
embed_title = twitch_embed.title
embed_description = twitch_embed.description
except Exception as e:
break
print("yes3")
# If it has, break the loop (do nothing).
if embed_title == True:
break
# If it hasn't, assign them the streaming role and send the message.
else:
# Gets all the members in your guild.
async for member in guild.fetch_members(limit=None):
# If one of the id's of the members in your guild matches the one from the json and
# they're live, give them the streaming role.
if member.id == int(user_id):
await member.add_roles(role)
# Sends the live notification to the 'twitch streams' channel then breaks the loop.
await channel.send(
content = f"Hey #everyone! {user.name} is now streaming on Twitch! Go check it out: https://www.twitch.tv/{twitch_name}", embed=twitch_embed)
print(f"{user} started streaming. Sending a notification.")
break
# If they aren't live do this:
else:
# Gets all the members in your guild.
async for member in guild.fetch_members(limit=None):
# If one of the id's of the members in your guild matches the one from the json and they're not
# live, remove the streaming role.
if member.id == int(user_id):
await member.remove_roles(role)
# Checks to see if the live notification was sent.
async for message in channel.history(limit=200):
try:
embed_title = message.embeds[0].title
embed_description = message.embeds[0].description
except Exception as e:
break
# If it was, delete it.
if user.mention in embed_title and "is now playing" in embed_title:
print(f"{user} stopped streaming. Removing the notification.")
await message.delete()
# Start your loop.
live_notifs_loop.start()
# Command to add Twitch usernames to the json.
#bot.command(name='addtwitch', help='Adds your Twitch to the live notifs.', pass_context=True)
async def add_twitch(ctx, twitch_name):
# Opens and reads the json file.
with open('streamers.json', 'r') as file:
streamers = json.loads(file.read())
# Gets the users id that called the command.
user_id = ctx.author.id
# Assigns their given twitch_name to their discord id and adds it to the streamers.json.
streamers[user_id] = twitch_name
# Adds the changes we made to the json file.
with open('streamers.json', 'w') as file:
file.write(json.dumps(streamers))
# Tells the user it worked.
await ctx.send(f"Added {twitch_name} for {ctx.author} to the notifications list.")
print('Server Running')
bot.run(TOKEN)
Just for others context, he had shown me the error on discord, so I am answering him through this question!
So mate, I found the error.
The line 106 in your code is:
await message.channel.send(msg)
Now this msg variable send all the details but we just want the content of it and not anything else.
So change that to:
await message.channel.send(msg.content)
Thank You! :D
I'm sorry, but i couldn't frame the question properly. Currently when someone uses my "meme" command in one server, it shows the memes however if someone from another server uses the same command,my bot skips the meme it has already shown. I'm new to programming,can someone tell me how to resolve the issue and explain what they did?Thank you!
#client.command()
async def meme(ctx, typememe="hot"):
if typememe == "hot":
y = next(hot_memes)
x = y.url
z = y.title
votes = y.score
comments = y.num_comments
embed = discord.Embed(
colour=discord.Colour.blue(),
title=z,
url=x
)
embed.set_image(
url=x)
embed.set_footer(
text=f"Upvotes:{votes}"
)
await ctx.send(embed=embed)
elif typememe == "controversial":
y = next(controversial_memes)
x = y.url
z = y.title
votes = y.score
comments = y.num_comments
embed = discord.Embed(
colour=discord.Colour.blue(),
title=z,
url=x
)
embed.set_image(
url=x)
embed.set_footer(
text=f"Upvotes:{votes}"
)
await ctx.send(embed=embed)
What I would do is have a dictionary that stores the guild id and the times the meme command was called, something like {GUILD_ID,4} where 4 is the times "meme" was called, we'll call this the memestorage. After that, every time the meme command is called you can check if it in memestorage's keys with memestorage.keys() and if it isn't add it with memestorage[ctx.message.guild] = 0. Finally, add one to the integer that is at the ctx.message.guild in memestorage and get the meme at that index + 1. All of this together may look something like:
memestorage = {}
memeiter = [meme1,meme2,meme3,meme4]
#client.command()
async def meme(ctx):
guild = ctx.message.guild
if guild not in memestorage.keys():
memestorage[guild] = 0
memestorage[guild] += 1
if memestorage[guild] >= len(memeiter):
memestorage[guild] = 1
pickedmeme = memeiter[memestorage[guild]+1]
With this, you could also save the memestorage dict in a json file so you can store the data even when the bot goes offline.
I use :
import discord
I need to get from each voice channel amount all users and then get their names (usernames). How to do it?
You need to access the voice channel object. I recommend you use the voice channel's id. The command could look as follows:
#client.command(pass_context = True)
async def vcmembers(ctx, voice_channel_id):
#First getting the voice channel object
voice_channel = discord.utils.get(ctx.message.server.channels, id = voice_channel_id)
if not voice_channel:
return await client.say("That is not a valid voice channel.")
members = voice_channel.voice_members
member_names = '\n'.join([x.name for x in members])
embed = discord.Embed(title = "{} member(s) in {}".format(len(members), voice_channel.name),
description = member_names,
color=discord.Color.blue())
return await client.say(embed = embed)
And would work like this:
Where the number at the end is the channel id. If you don't know how to get the channel id, right click the channel and click Copy ID.
If you can't see the Copy ID, turn on Developer Mode in your Settings > Appearance > Developer Mode
You can also get all the members of a voice channel like this (updated for discord.py versions 1.0.0+):
#client.command(brief="returns a list of the people in the voice channels in the server",)
async def vcmembers(ctx):
#First getting the voice channels
voice_channel_list = ctx.guild.voice_channels
#getting the members in the voice channel
for voice_channels in voice_channel_list:
#list the members if there are any in the voice channel
if len(voice_channels.members) != 0:
if len(voice_channels.members) == 1:
await ctx.send("{} member in {}".format(len(voice_channels.members), voice_channels.name))
else:
await ctx.send("{} members in {}".format(len(voice_channels.members), voice_channels.name))
for members in voice_channels.members:
#if user does not have a nickname in the guild, send thier discord name. Otherwise, send thier guild nickname
if members.nick == None:
await ctx.send(members.name)
else:
await ctx.send(members.nick)