bot.get_all_channels() gets ignored discord.py - discord.py

When obtaining all channels to send a message to all, the bot ignores the command. Here's my code.
async def lockdown(ctx):
allchannels = bot.get_all_channels()
overwrite = channel.overwrites_for(ctx.guild.default_role)
locked = overwrite.send_messages = False
await locked.send(allchannels, 'This server has been locked down.')

Try printing allchannel, you'll see where you did an error.
You can't use bot.get_all_channels() in this way that's all

Related

How do you send a private message on_ready aka on a #client.event. Discord.py

I had multiple attempts.
# One of the attempts
ch = client.get_user(USERID)
await ch.send("IDK")
#Another
client = discord.Client()
#client.event
async def on_ready():
user = "#name"
user = discord.Member
await user.send(user, "here")
#Another
client = discord.Client()
#client.event
async def on_ready():
user = discord.utils.get(client.get_all_members(), id='USERID')
if user is not None:
await client.send(user, "A message for you")
else:
await client.send(user, "A message for you")
#Another
#client.event
async def on_ready():
ch = client.get_all_members()
await ch.send("Hello")
# Another
ch = client.start_private_message(USERID)
await ch.send("IDK")
As you can see I messed with the variables because I noticed that you can send a message by channel like this
channel = client.get_channel(CHANNELID)
await channel.send("Something)
But that doesn't work with get_user. Thanks in advance also sorry how bad my post/code is.
Allow me to inform you on what is wrong with the pieces of code you have provided.
await client.send(user, "A message for you") is older syntax, and has not been used since the v1.0 migration.
client.get_all_members() shouldn't be used in this case, as you are only getting all the members the bot shares a server with rather than a single user.
client.start_private_message(USERID) does not exist as far as I have read, and therefore we can assume that this wouldn't work.
My recommendation would be to use one of the two methods I will detail.
The first method would be to use client.fetch_user(), which sends a request to the Discord API instead of its internal cache (as the second method will). The only problem you will face with this method is if you retrieve too many users in a small amount of time, which will get you ratelimited. Other than that, I recommend this method.
The second method is to get a server through client.get_guild() and getting your user through there via guild.get_member(). This method will require the user to be in its cache, however, so this shouldn't be your go-to method in my opinion.
Do view both of these methods in the code below.
#client.event
async def on_ready():
# Method 1: Using fetch
user = await client.fetch_user(USER_ID)
await user.send("A message!")
# Method 2: Using 'get'
guild = client.get_guild(GUILD_ID)
user = guild.get_member(USER_ID)
await user.send("A message!")
Other Links:
Send DM to specific User ID - Stackoverflow
DM a specific user - Stackoverflow
Sending DM through python console (Fetch user) - Stackoverflow
DPY v1.0 Migration - Discord.py Documentation

Grabbing new channel ID from json file in background task

I have a background task that send a message in a channel that the channel ID is stored in JSON. In the even that channel gets deleted, a new channel ID replaces the old channel ID in the JSON file. I'm getting discord.errors.NotFound: 404 Not Found (error code: 10003): Unknown Channel when the background task sends again. I tried to put the piece of code chanid = get_general() outside of the background task code in hopes that it pulls in the new channel ID in the loop but I feel like I a missing something here.
try:
with open("channels.json", 'r') as fp:
channels = json.load(fp)
except Exception:
channels = {}
def save_channels():
with open("channels.json", "w+") as fp:
json.dump(channels, fp, indent=4)
def get_general():
return channels.get("general", 0)
chanid = get_general()
async def hello_loop():
await client.wait_until_ready()
chan = client.get_channel(chanid)
while not client.is_closed():
msg= 'hello'
msgsend = await chan.send(msg)
client.loop.create_task(hello_loop())
What I need is, on chance that a delete channel command is used, I remove the current general channel ID inside of delete channel command and replace it with the cloned channel ID. I also stop the background task, and reset it within the same command. It works the way I want it, but maybe there is a better way of approaching it?

How to change channel permissions without having a message sent first?

I have a program that changes what channel members can see at certain times of the day. To do this, I can either change the roles that every member has, or change the permissions of each channel. However, I have looked all over the web and all of the ways for either method require a message to be sent so that the data from that message can be read and put into the function, such as:
#client.command()
async def perm(ctx):
await ctx.channel.set_permissions(ctx.guild.default_role, send_messages=False
Change the permissions of a discord text channel with discord.py
or
async def addrole(ctx):
member = ctx.message.author
role = get(member.server.roles, name="Test")
await bot.add_roles(member, role)
Discord.py | add role to someone
My current program looks like this:
import discord
client = discord.Client()
import datetime
async def live_day(schedule):
current_place = "the void"
while True:
current_time = str((datetime.datetime.now() -datetime.timedelta(hours=7)).time())
int_time = int(current_time[:2] + current_time[3:5])
for x in range(len(schedule)):
try:
start_time = schedule[x][1]
end_time = schedule[x + 1][1]
except IndexError:
end_time = 2400
if current_place != schedule[x][0] and int_time >= start_time and int_time < end_time:
current_place = schedule[x][0]
#Change the channel permissions of the current place to allow viewing
#Change the channel permissions of the last channel to disallow viewing
#client.event
async def on_ready():
print("{0.user} has arrived for duty".format(client))
client.loop.create_task(live_day([
("Home", 0),
("Work", 900),
("Home", 1700),
("Nightclub", 2000),
("Home", 2200),
]))
client.run(my_secret)
Never mind the badly written code, how would I do this or where should I go to figure this out? Any help is appreciated. Thanks!
Edit: I could get the channels individually by using this,
channel1=client.get_channel(channelid)
discord.py, send message by channel id without on_message() event?
but then I can't use this for more than one server. How can I get channels by name?
Note on on_ready():
This function is not guaranteed to be the first event called. Likewise, this function is not guaranteed to only be called once. This library implements reconnection logic and thus will end up calling this event whenever a RESUME request fails.
Using this function may crash the bot.
Instead create background tasks and use wait_until_ready().
You can find examples in https://github.com/Rapptz/discord.py/blob/v1.7.3/examples/background_task.py
If you want to change only one channel's permissions (per guild) this might fit your needs:
#changing "Home" channel visibility, every day at 5 pm.
#client.event
async def on_ready():
while True:
await asyncio.sleep(1)
current_time = datetime.datetime.now()
five_pm = current_time.replace(hour=17, minute=0, second=0)
if current_time == five_pm:
for guild in client.guilds: #looping through all the guilds your bot is in
channel = discord.utils.get(client.get_all_channels(), name="Home") #getting channel by name by using "discord.utils"
await channel.set_permissions(guild.default_role, view_channel=True) #changing permissions
By using the on_ready() event you can loop through the time check without sending any message.
Remember to import discord.utils.

Discord.py logging messages

I've got this code, which when I type !snapshot should log the last 100 messages in the channel, and make them into a text file:
snapshot_channel = (my snapshot channel ID)
#commands.has_permissions(administrator=True)
#bot.command()
async def snapshot(ctx):
channel = bot.get_channel(snapshot_channel)
await ctx.message.delete()
messages = message in ctx.history(limit=100)
numbers = "\n".join(
f"{message.author}: {message.clean_content}" for message in messages
)
f = BytesIO(bytes(numbers, encoding="utf-8"))
file = discord.File(fp=f, filename="snapshot.txt")
await channel.send("Snapshot requested has completed.")
await channel.send(file=file)
I've got BytesIO imported, and it works fine for a different command which purges messages and logs them, but this code which should just make a log and then send it in the channel doesn't work. Please can you send me what it should look like for it to work. Thanks!
TextChannel.history is an async generator, you're not using it properly
messages = await ctx.channel.history(limit=100).flatten()
numbers = "\n".join([f"{message.author}: {message.clean_content}" for message in messages])
Another option would be
numbers = ""
async for message in ctx.channel.history(limit=100):
numbers += f"{message.author}: {message.clean_content}"

cant set overwrites when creating category

I've watched a youtube tutorial about creating channels with overwrites but I still don't get why this code doesn't work
varCategory = await message.guild.create_category(name=args[1], overwrites={overwrite(message.guild.default_role,view_channel=False,send_messages=False)}, reason=None, position=0)
I get the error init() takes 1 positional argument but 2 were given
view_channel is from the old async version. Now you can just set it with read_messages or send_messages, which would both prevent a user from messaging in a channel.
Here I have corrected your code and tested it, you can also choose if the author of the command should have access to the channel.
guild = ctx.guild
member = ctx.author
overwrites = {
guild.default_role: discord.PermissionOverwrite(read_messages=False),
member: discord.PermissionOverwrite(read_messages=False)
}
channel = await guild.create_text_channel(args=[1], overwrites=overwrites)

Resources