'Context' object has no attribute 'reddit' Discord.PY - python

I'm trying to add a .reddit command to my bot. This is my code:
#client.command(name="random", aliases=["reddit"])
async def _random(ctx, subreddit: str = ""):
reddit = None
if reddit_app_id and reddit_app_secret:
reddit = praw.Reddit(client_id=reddit_app_id,client_secret=reddit_app_secret,user_agent="MASTERBOT:%s1.0" % reddit_app_id)
if reddit:
submissions = reddit.subreddit(subreddit).hot()
submission = next(x for x in submissions if not x.stickied)
await ctx.send(submissions.url)
I have everything imported, everything seemed fine until I got this error:
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: AttributeError: 'Command' object has no attribute 'randint'
As I understood, the program has no idea what a randint is. I checked if I've made a typo, but no. Everything seemed fine. I was getting an antoher error on the same command but I managed to fix it. But this one got me and I need your help.
These are the new errors:
AttributeError: 'coroutine' object has no attribute 'url'
.
RuntimeWarning: Enable tracemalloc to get the object allocation traceback

Do you have the command in a Cog (class)?
If you don't, then you should remove self, as it'll assume that that's the name of the context object.
#client.command(name="random", aliases=["reddit"])
async def _random( ctx, subreddit: str = ""):
reddit = None
if reddit_app_id and reddit_app_secret:
reddit = praw.Reddit(client_id=reddit_app_id,client_secret=reddit_app_secret,user_agent="MASTERBOT:%s1.0" % reddit_app_id)
if reddit:
chosen_subreddit = reddit_enabled_meme_subreddits[0]
if subreddit:
if subreddit in reddit_enabled_meme_subreddits:
chosen_subreddit = subreddit
submissions = reddit.subreddit(chosen_subreddit).hot()
post_to_pick = random.randint(1, 10)
for i in range(0, post_to_pick):
submission = next(x for x in submissions if not x.stickied)
await ctx.send(submission.url)
else:
await ctx.send("This is not working")
The issue is with the name of the command, random, as this is polluting the namespace of the random module. You're able to bypass this by renaming the command.
The async def random(.... is clashing with import random at the top of your code. You're able to set the name of the command with the name= keyword argument in the decorator. That's the name that people will be typing into discord.
Tried using your method of getting a random submission (minus the superfluous code, just the same logic), and it worked for me:
reddit = praw.Reddit(client_id="...", client_secret="...", user_agent="...")
#bot.command(name="reddit")
async def _reddit(ctx, subreddit: str = ""):
submissions = reddit.subreddit(subreddit).hot()
submission = next(x for x in submissions if not x.stickied)
await ctx.send(submission.url)
The only thing I can think of is making sure that you have the most up-to-date version of praw, and also if there's anything else in the command that you might be leaving out of the question, then that might be affecting it, although that's just speculation.
I'd say try making the command from the ground-up. Start off simple with something that works, and add to it line by line until something breaks. Then you'll know what's causing the RuntimeWarning and such.
Sorry for not having a clear-cut answer for this.

Related

Need to know timestamp of when Discord bot was last functioning

I am making a discord bot and I want for it to be able to take actions based on it being online.
However, I am running into the issue that I can't seem to figure out an easy way to know when the discord bot last went offline (which I need to know).
Currently I was trying to look into a way by using the activity of the bot in order to figure out when the bot goes offline since activities theoretically have timestamps from in the documentation. I don't know if this method would work this way but certainly I can't get it working and have the following trackback:
Traceback (most recent call last):
File "C:\Users\carol\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\client.py", line 409, in _run_event
await coro(*args, **kwargs)
File "C:\Users\carol\Code\Personal\visabot\visa_bot.py", line 128, in on_ready
success =await self.add_visa_after_offline()
File "C:\Users\carol\Code\Personal\visabot\visa_bot.py", line 103, in add_visa_after_offline
async for active in visabot.activity.timestamps:
AttributeError: 'NoneType' object has no attribute 'timestamps'
Here is the code for the specific function that errors:
async def add_visa_after_offline(self) -> bool:
guild = await self.get_guild()
visabot = await self.get_visabot_member()
async for active in visabot.activity.timestamps:
print(active)
And here is my intents:
client = MyClient(GUILD_ID, SPAM_CHANNEL, MAIN_CHANNEL,BOT_ID, intents=discord.Intents.all())
client.run(BOT_TOKEN)
After combing through the documentation I didn't see anything that looked like this did exactly. Please let me know if there is any specific functionality for this or if there is some easier alternative way to know when the bot last went offline.
IF AT ALL POSSIBLE, I want to avoid having any kind of database, even a super simple one. So simply combing through discord stuff to infer last went offline would be much superior to solutions that use a database.
I mostly thought it would be an intent problem so I tried to let it have all intents. It could also be a permissions token problem and there is some permission its lacking. Looking at them though I am not sure that there is.
Additionally, I know that the visabot object is definitely the bot since .name, .id, and other methods work properly. Also the activity on the robot is "Watching" which I know since I can see it watching in the discord app.
Thanks.
I solved it by getting lazy and instead storing a variable of "LAST_ACTION" since my bot performs actions periodically. This will be a pretty accurate time of when the bot was last functional.
Relevant features:
Used a Json file for storage. Don't know if it was very optimal but it worked.
def get_json_data(self) -> dict:
with open(self.tracker_file, 'r') as openfile:
data = json.load(openfile)
return data
def update_json(self, new_data: dict) -> bool:
data = self.get_json_data()
data.update(new_data)
with open(self.tracker_file, "w") as outfile:
json.dump(data, outfile)
For initializing the client object I added:
def __init__(self, data, *args, **kwargs):
super().__init__(*args, **kwargs)
...
...
...
self.tracker_file = "var_tracker.json"
if not os.path.exists(self.tracker_file):
now = get_now()
# this will make it not really function well if you need to use this the first time
init_data = {'LAST_TIME_OF_ACTION': str(now), 'ASSIGNED': []}
with open(self.tracker_file, 'w') as openfile:
json.dump(init_data, openfile)
data = self.get_json_data()
self.timestamp_before_online = data['LAST_TIME_OF_ACTION']
Then I made a function to reference the "self.timestamp_before_online" and get the timestamp since I have to convert from datetime to string to put in the json then back to datetime to use while coding. It was a little annoying to figure out though:
def get_now():
return datetime.datetime.now((datetime.timezone.utc))
def str_datetime_to_datetime_obj(str_datetime: str) -> datetime.datetime:
datetime_obj = datetime.datetime.strptime(str_datetime,
"%Y-%m-%d %H:%M:%S.%f%z")
return datetime_obj
def search_last_around(self) -> datetime.datetime:
last_around = str_datetime_to_datetime_obj(self.timestamp_before_online)
return last_around
Finally, I simply updated the json for the "LAST_TIME_OF_ACTION "as the last line in my task loop:
#tasks.loop(seconds=300)
async def purge_visas_background_task(self):
print("Attempting Purge at {}".format(get_now()))
success = await self.purge_all_overstayed_visa()
if success:
pass
else:
await self.send_to_spam('Purge has failed')
await self.report_error()
now = get_now()
self.update_json({'LAST_TIME_OF_ACTION': str(now)})
Not super elegant or compact but it works for my purposes so I thought I'd share it in case it helped anyone else.

python replit database throwing typeError

I was trying to make functions to save, get, and get all for the Replit Python database. It doesn't work and I can't find out why.
Get all function:
def loadAll(user):
if user in db.keys():
return db[user]
if user not in db.keys():
db[user] = {}
return db[user]
It throws an error at return db[user].
This is the code that fires the function (I'm using the discord.py commands extension.):
#bot.command(name = "getMyData")
async def getUserData(ctx):
await ctx.send(ctx.author)
await ctx.send(loadAll(ctx.author))
The error message says:
TypeError: quote_from_bytes() expected bytes
I solved it by changing the database key to not just be the user.
Replit Database doesn't support integers as keys. Stringify the key beforehand.

'NoneType' object has no attribute 'node' Lavalink

I'm trying to make a music bot in python, and I get this error:
AttributeError: 'NoneType' object has no attribute 'node'
I suspect that this part of the code is causing this problem:
#cog_ext.cog_slash(name="play", guild_ids=guild_ids, description="Play song")
async def play(self, ctx, *, query: str):
""" Searches and plays a song from a given query. """
# Get the player for this guild from cache.
player = self.bot.lavalink.player_manager.get(ctx.guild.id)
# Remove leading and trailing <>. <> may be used to suppress embedding links in Discord.
query = query.strip('<>')
# Check if the user input might be a URL. If it isn't, we can Lavalink do a YouTube search for it instead.
# SoundCloud searching is possible by prefixing "scsearch:" instead.
if not url_rx.match(query):
query = f'ytsearch:{query}'
# Get the results for the query from Lavalink.
results = await player.node.get_tracks(query)
# Results could be None if Lavalink returns an invalid response (non-JSON/non-200 (OK)).
# ALternatively, resullts['tracks'] could be an empty array if the query yielded no tracks.
if not results or not results['tracks']:
return await ctx.send('Nothing found!')
Let me know if anyone needs more code, I don't want to spam all the code if it is not needed

Sqlite3 Flask discord bot dashboard. TypeError: "NoneType object is not subscriptable

So, i'm making a discord bot dashboard and, in the guild settings, I want to show if a category if enabled or desabled. And I maked this code:
#app.route("/serveurs/<int:serveur_id>")
def serveur(serveur_id):
if 'token' not in session:
return redirect("https://discord.com/api/oauth2/authorize?client_id=787982190776287282&redirect_uri=https%3A%2F%2FMEE0-1.devteaming.repl.co%2Foauth%2Fdiscord&response_type=code&scope=identify%20guilds")
serveur_info = get_serveur_info(serveur_id)
if not serveur_info:
return redirect('/dashboard')
with sqlite3.connect("dashboard.sqlite3") as db:
cursor = db.cursor()
cursor.execute(f"SELECT * FROM dashboardconfig WHERE guilds_id = {serveur_info['id']}")
data = cursor.fetchone()
print(data)
mod = bool(data[2])
music = bool(data[2])
fun = bool(data[2])
return render_template("serveur.html", serveur=serveur_info, mod=mod, music=music, fun=fun)
When I restart the server and I go on the endpoint it raise me this error in the terminal:
TypeError: "NoneType object is not subscriptable"
I'm pretty sure the error is in the data variable but I don't know how fix it. If anyone can help me, thanks.
PS: I make all the functions, files etc... Don't worry ;).

AttributeError in MessageFwdHeader telethon library

I'm getting AttributeError in my code. How can I fix it please
from telethon import events
#client.on(events.NewMessage(func=lambda e: e.is_private))
async def _(event):
x = await event.get_reply_message()
if x is None:
return
send = event.raw_text
who = event.sender_id
if x.fwd_from:
user = x.fwd_from.sender_id.user_id
else:
return
Error:
Line 11: AttributeError: 'MessageFwdHeader' object has no attribute 'sender_id'
the AttributeError usually use a not existence attribute ,check the object Attribute.
According to this and this in the docs it is possible to get the original sender ID like: message.forward.sender_id. By the way the result will be None if the sender's profile was hidden or that was a channel repost.

Categories

Resources