discord.py - No DM sent to the user - python

I am making a discord.Client. I have a DM command that sends a DM to a specific user, but no message is sent to the user when the command is run, but a message is sent on the Context.channel.
Here is my code:
import discord, asyncio
app = discord.Client()
#app.event
async def on_message(message):
if message.content.startswith('!DM'):
usernotsending = []
content = message.content
msg = await message.channel.send('메시지를 보내고 있습니다!')
i = app.user
# 봇의 모든 유저를 for문으로 적용
for i in app.user:
try:
if i == app.user:
return
# 해당 유저의 DM을 염
await i.create_dm()
# 내용전송
await app.dmchannel.send(content)
# DiscordAPI 에서 오류가 발생했을경우
except discord.HTTPException:
# DM을 보내지 못한 유저 태그 list에 저장
usernotsending.append(f'{i.name}#{i.discriminator}')
messageing = """
아래 유저들에게 메시지를 전송하지 못했습니다!
직접 보내주시거나, 따로 전달을 해드려야됩니다!
"""
for msg in usernotsending:
# message 에 유저 태그 추가
messageing += msg
# 메시지 전송
await msg.edit(content=messageing)

Context is only part of a commands.Bot instance. Your code and your explanation don't seem to match. Assuming you want to DM the author:
import discord
app = discord.Client()
#app.event
async def on_message(message):
if message.content.startswith('!DM'):
try:
await message.author.send(...)
except discord.HTTPException:
...
If you want to DM everyone the bot can see:
import discord
app = discord.Client()
#app.event
async def on_message(message):
if message.content.startswith('!DM'):
for user in app.users:
try:
await user.send(...)
except discord.HTTPException:
...

Related

Warning discord.getaway "discord.gateway: Shard ID None heartbeat blocked for more than 10 seconds."

I tried to write a Discord bot that forwards messages from one server to another. But I get a warning that disconnects my connection to the discord gateway. I read that it is possible because of tyme.slep(), but without it, the connection is always interrupted. As I understand it, DDOS protection is activated due to a large number of requests.
import asyncio
import websocket
import json
from threading import Thread
import discord
import requests
from io import BytesIO
import time
from discord.ext import tasks
# Bot
bot_token = "anything"
user_token = "anything"
client = discord.Client(intents=discord.Intents.default())
# Channels list
f = open('channels.txt', 'r')
channels_file = f.read()
channels_array = channels_file.strip().split('\n')
# Connect func
def send_json_request(ws, request):
ws.send(json.dumps(request))
def receive_json_response(ws):
response = ws.recv()
if response:
return json.loads(response)
#WebSoket
def on_closed(ws):
ws.connect("wss://gateway.discord.gg/?v=6&encording=json")
ws = websocket.WebSocket(on_close=on_closed)
ws.connect("wss://gateway.discord.gg/?v=6&encording=json")
def receive_json_response(ws):
response = ws.recv()
if response:
return json.loads(response)
def get_attachment_media(media):
media_array = []
for i in media:
response = requests.get(i['url'])
im = BytesIO(response.content)
print(im)
media_array.append(discord.File(im))
return media_array
def get_channel(id):
for i in channels_array:
if i == id:
return True
return False
#Heartbeat
def heartbeat(interval):
print("Heartbeat begin")
while True:
time.sleep(interval)
heartbeatJSON = {
"op": 1,
"d": "null"
}
send_json_request(ws, heartbeatJSON)
print("Heartbeat sent")
#tasks.loop(seconds=0.5)
async def main():
channel = client.get_channel(anything)
event = receive_json_response(ws)
try:
if event['d']['author']['id'] == 'anything':
return
id_channel = event['d']['channel_id']
id_guild = event['d']['guild_id']
if get_channel(id_channel):
content = event['d']['content']
attachment_media = get_attachment_media(event['d']['attachments'])
await channel.send(content, files=attachment_media)
op_code = event('op')
if op_code == 11:
print('Heartbeat recieved')
except:
pass
#client.event
async def on_ready():
event = receive_json_response(ws)
heartbeat_interval = event['d']['heartbeat_interval'] / 1000
send_json_request(ws, {
"op": 2,
"d": {
"token": user_token,
"properties": {
"$os": 'linux',
"$browser": 'chrome',
"$device": 'pc'
}
}
})
main.start()
asyncio.run(heartbeat(heartbeat_interval))
client.run(bot_token)
I recommend you to check this answer and adjust it to your code.
However, if you are just trying to make your bot copy the contenet of the messages sent in one server and sending to another one, you can do it in a easier way using the on_message() event. This is the entire code, which should also prevent any warning (unless the bot tries to send too many messages in a short period of time):
import discord
intents = discord.Intents.default()
intents.message_content = True # You are missing the message_content intent! (needed to read the content of the guild's messages)
client = discord.Client(intents=intents)
TOKEN = "Your Token"
guild_id = 123456789 # The guild you want your bot to send the messages to
channel_id = 987654321 # The channel of the guild you want your bot to send the messages to
guild = None
channel = None
#client.event
async def on_ready():
global guild, channel, guild_id, channel_id
await client.wait_until_ready()
guild = client.get_guild(guild_id)
channel = guild.get_channel(channel_id)
print("Logged")
#client.event
async def on_message(message : discord.Message):
if message.author == client.user: # You don't want to send the own bot messages
return
if message.guild.id == guild_id: # You don't want to send the messages from the own guild your bot is sending the messages to
return
await channel.send(f"{message.author}: {message.content}") # Add attachments if you want
client.run(TOKEN)

I want to tag a person who clicks a button discord.py

components = [
[
Button(label="Open a ticket", style=2, custom_id="Open", emoji="📩")
]
]
await ctx.send(embed=embed, components=components )
while True:
interaction = await client.wait_for("button_click", check = lambda i: i.component.label.startswith("Open"))
overwrites = {
member_role: discord.PermissionOverwrite(view_channel=False),
ctx.author: discord.PermissionOverwrite(view_channel=True),
guild.me: discord.PermissionOverwrite(view_channel=True),
ticket_mod_role: discord.PermissionOverwrite(view_channel=True)
}
Embed = discord.Embed(
title="Ticket Created",
description=f"{THIS EMPTY SPACE} Your ticket is created",
)
await interaction.send(content = await interaction.send(embed=Embed), ephemeral=True)
ticket = await ticket_category.create_text_channel(
f"🎫│Ticket-{THIS EMPTY SPACE}", overwrites=overwrites
)
Embed = discord.Embed(
title="Ticket Created",
url="",
description=f"""{ctx.author.name} Wait our staff.""",
color=discord.Color.random()
)
Instead of ctx.author.name (ctx.author is a discord.member class)
Use ctx.author.mention
Docs:
https://discordpy.readthedocs.io/en/stable/api.html?highlight=mention#discord.Member.mention
i've resolved using the library of discord.py (interaction) instead of this i used the object (user.name)
import discord
from discord.ext import commands
from discord_buttons_plugin import *
intents = discord.Intents.default()
intents.members = True
client = commands.Bot(command_prefix='>', intents=intents)
buttons = ButtonsClient(client)
#client.event
async def on_ready():
print("Log : "+str(client.user))
#client.command()
#commands.has_permissions(administrator=True)
async def ticket(ctx):
em = discord.Embed(title="join us",description="To create a ticket react with",emoji={"id": None,"name": "📩","animated": False},color=discord.Color.from_rgb(0,255,0))
await buttons.send(embed=em,channel=ctx.channel.id,
components=[ActionRow([Button(style= ButtonType().Secondary,label = "Create ticket",custom_id = "test1")])])
#buttons.click
async def test1(ctx):
guild = ctx.guild
ch = await guild.create_text_channel(name=f'ticket-{ctx.member}')
await ch.set_permissions(ctx.guild.default_role,view_channel=False,send_messages=False)
await ch.set_permissions(ctx.member,view_channel=True,send_messages=True)
await ctx.reply(f"Ticket created {ch.mention}",flags=MessageFlags().EPHEMERAL)
client.run("token")

Can't for the life of me get button + role assignment to work - discord.py

I have been looking for help with this for a solid week now and tried a lot of things, but a lot of answers are outdated with the new Components update for discord.py
I referenced this video for this particular code: https://www.youtube.com/watch?v=1Ntw43Sg35k
This is in a cog if that matters. It worked ONCE but I didn't realize it and messed up the code so I lost it...
It pulls up the embed and even the buttons, but it does not assign the role and the component comes up with "This interaction failed".
enter image description here
Any help would be super appreciated!!
import os, json, asyncio, discord, discord.utils
from discord import Embed, Color
from discord.ext import commands
from discord_components import Button, ButtonStyle, Select, SelectOption, ComponentsBot, component
from discord_components.client import DiscordComponents
from discord_components.interaction import Interaction
from discord.utils import get
#----- Import -----#
client = discord.Client()
def get_prefix(client, message):
with open('prefixes.json','r') as f:
prefixes = json.load(f)
return prefixes[str(message.guild.id)]
client = commands.Bot(command_prefix = get_prefix,intents=discord.Intents.all(),case_sensitive=True,buttons = DiscordComponents(client))
#----- Class Code for f1r4 -----#
class f1r4(commands.Cog):
def __init__(self,client):
self.client = client
#client.command()
async def f1r4(self,ctx):
embed=discord.Embed(
title='Floor 1, Room 4',
url = '',
description = 'You decide that it\'s time to move on. Maybe, somewhere safer too...',
color=Color.green())
embed.set_thumbnail(url='')
embed.add_field(
name = 'North',
value = 'Insert an informative text dump here.',
inline = True)
embed.add_field(
name = 'South',
value = 'take two boogaloo',
inline = True)
embed.add_field(
name = 'East',
value = 'Boy howdy don\'t look at the actual descriptions lol',
inline = True)
msg = await ctx.send(embed=embed,
components=[[
Button(label = 'North'),
Button(label = 'South'),
Button(label = 'East')]])
def check(res):
return ctx.author == res.user and res.channel == ctx.channel
try:
res = await client.wait_for('buttonclick', check=check, timeout=30)
except asyncio.exceptions.TimeoutError:
tembed = discord.Embed(
title = 'Need More Time?',
descprtion = 'Try again once you\'ve had a chance to make your decision!',
color=Color.red())
await msg.edit(
embed=tembed,
components=[
Button(style=ButtonStyle.red,
label='Command Closed',
disabled=True)])
await asyncio.sleep(5)
await msg.delete()
return
if res.component.label == 'North':
member = ctx.author
mrole = discord.utils.find(lambda r:r.name == 'F1R1',ctx.message.guild.roles)
role = get(member.guild.roles, name='F1R1')
if mrole in member.roles:
await res.respond(content='You have a character in Room 1!')
await asyncio.sleep(3)
await msg.delete()
return
else:
await member.add_roles(role)
await asyncio.sleep(5)
await msg.delete()
return
else:
return
def setup(client):
client.add_cog(f1r4(client))
res = await client.wait_for('button_click', check=check, timeout=30) should be res = await self.client.wait_for('button_click', check=check, timeout=30).
There is also an typo on description for tembed.
Suggestions:
Don't import from discord_components.client. discord_components is supposed to export all required objects; using this breaks things if library decides to rename files.
buttons = DiscordComponents(client) should be DiscordComponents(client) in separate line.

Python code for Discord Bot using discord.py getting "using variable before assignment" error

I am new to both Python and Stack Exchange. When using this code, I receive the error, "Using variable 'status' before assignment [30,96]." It says that the variable status is unassigned in the await command in the loop, even though I assigned it above. If anyone could solve this, I would appreciate it. If any other info is needed, just ask and I can reply with it. Thanks.
import requests
from discord.ext import commands
from discord.ext import tasks
from itertools import cycle
client = commands.Bot(command_prefix = '.')
status = cycle(['Starting.', 'Starting..'])
serverOnePlayerCount = 0
serverTwoPlayerCount = 0
serverOneOnline = 'Offline'
serverTwoOnline = 'Offline'
#client.event
async def on_ready():
change_status.start()
print('Bot is ready.')
#client.command()
async def ping(ctx):
await ctx.send(f'Pong! {round(client.latency * 1000)}ms')
#tasks.loop(seconds=5)
async def change_status():
await client.change_presence(status=discord.Status.online, activity=discord.Game(name=next(status), type=3))
r1 = requests.get('https://api.minehut.com/server/5f0de3303c826f0051e583b1/')
json_data_1 = r1.json()
serverOneOnline = str(json_data_1["server"]["online"])
serverOnePlayerCount = str(json_data_1["server"]["playerCount"])
serverOneStatusMessage = 'Minecraft ----- Server 1 is {} ({}/10 players)'.format(serverOneOnline, serverOnePlayerCount)
r2 = requests.get('https://api.minehut.com/server/5f8242b2d74dc1006100293b/')
json_data_2 = r2.json()
serverTwoOnline = str(json_data_2["server"]["online"])
serverTwoPlayerCount = str(json_data_2["server"]["playerCount"])
serverTwoStatusMessage = 'Minecraft ----- Server 2 is {} ({}/10 players)'.format(serverTwoOnline, serverTwoPlayerCount)
status = cycle([serverOneStatusMessage, serverTwoStatusMessage])
client.run('token')

Python discord bot send to multiple channels problem

I've got a problem with sending a message to multiple channels. When I do the command, it sends just to the channel I wrote from for 8 times. Here is my code:
import discord
import config
client = discord.Client()
#client.event
async def on_message(message):
id = client.get_guild(config.ID)
channels = [647074685535649802, 636901028478058497, 690272147050070158, 694196995887202375, 690276595578962177, 654662320735387648, 650381379892412426, 641704849196711976]
valid_users = ["Resadesker#1103"]
if str(message.author) in valid_users:
for channelo in channels:
if message.content.find("$spam") != -1:
print(channelo)
channel = client.get_channel(channelo)
print(channel)
await message.channel.send(message.content[message.content.find(' '):])
client.run(config.TOKEN)
It looks like you are sending your response to the channel from message, try this:
#client.event
async def on_message(message):
id = client.get_guild(config.ID)
channels = [
647074685535649802,
636901028478058497,
690272147050070158,
694196995887202375,
690276595578962177,
654662320735387648,
650381379892412426,
641704849196711976,
]
valid_users = ["Resadesker#1103"]
if str(message.author) in valid_users:
for channelo in channels:
if message.content.find("$spam") != -1:
print(channelo)
channel = client.get_channel(channelo)
print(channel)
await channel.send(message.content[message.content.find(' '):])

Categories