I have two meme commands. They have two subreddits and that take random memes from that.
Here is my code
sreddits_list = ['dankruto', 'narutomemes']
#bot.command(aliases=['narutomeme', 'narmeme', 'nmeme'])
async def Nmeme(ctx):
subreddit = await reddit.subreddit(random.choice(sreddits_list))
all_subs = []
top = subreddit.top(limit = 50)
async for submission in top:
all_subs.append(submission)
random_subs = random.choice(all_subs)
name = random_subs.title
url = random_subs.url
em = discord.Embed(title = name, colour = discord.Colour.random(), timestamp = ctx.message.created_at, url = url)
em.set_image(url = url)
await ctx.send(embed = em)
#meme cmd
sreddits2_list = ['memes', 'dankmemes']
#bot.command(aliases=['Meme'])
async def meme(ctx):
subreddit = await reddit.subreddit(random.choice(sreddits2_list))
all_subs = []
top = subreddit.top(limit = 50)
async for submission in top:
all_subs.append(submission)
random_subs = random.choice(all_subs)
name = random_subs.title
url = random_subs.url
em = discord.Embed(title = name, colour = discord.Colour.random(), timestamp = ctx.message.created_at, url = url)
em.set_image(url = url)
await ctx.send(embed = em)
I used praw before this. But then someone told me to use asyncpraw. I tried and it was faster. But it's not enough.
Please tell me how do I make it faster?.
The problem is that the bot takes some time to respond and send the embed.
If you want to test the commands, then join the Discord Server and try the commands. (It's just a test server)
-meme
-nmeme
If the above link does not work then please use this one
https://discord.gg/RDtmjTz87H
The reason is praw and asyncpraw. As they are not made for getting posts, you shouldn't be using them. You can use RedditEasy which is 2x faster than praw in getting posts.
This is mostly regarding your bots latency(ping) and the place you are requesting it from. I also recommend you use the reddit api(json).
Related
Hi I'm trying to block a few subreddits in praw like FiftyFifty but I cant find the command for something like that this is also for a discord bot my code is here
#client.command()
async def r(ctx,subred = ""):
subreddit = reddit.subreddit(subred)
all_subs = []
top = subreddit.top(limit = 50)
for submission in top:
all_subs.append(submission)
random_sub = random.choice(all_subs)
name = random_sub.title
url = random_sub.url
if not submission.over_18:
em = discord.Embed(title = name)
em.set_image(url = url)
await ctx.send(embed = em)
else:
await ctx.send("NO")
This might be a possible solution
bannedSubreddits = ["FiftyFifty", "various", "other", "subreddits"] #Add as many subreddits as you'd like here or just add one
#client.command()
async def r(ctx,subred = ""):
subreddit = reddit.subreddit(subred)
for bannedSub in bannedSubreddits:
if subreddit == reddit.subreddit(bannedSub): #If a banned subreddit is detected, it sends what you wanted to send when you find an over 18 post
await ctx.send("NO")
return
all_subs = []
top = subreddit.top(limit = 50)
for submission in top:
all_subs.append(submission)
random_sub = random.choice(all_subs)
name = random_sub.title
url = random_sub.url
if not submission.over_18:
em = discord.Embed(title = name)
em.set_image(url = url)
await ctx.send(embed = em)
else:
await ctx.send("NO")
I have written the code to check if Twitch streamer is life, if so send a message, but i can't find a way to check if life notification(message and embed) is already send. So I tried different things of checking embed title: if discord.Embed(title=f":red_circle: **LIVE**\n{user.name} is now streaming on Twitch! \n \n {stream_data['data'][0]['title']}") == embed: and if discord.Embed(title=f":red_circle: **LIVE**\n{user.name} is now streaming on Twitch! \n \n {stream_data['data'][0]['title']}"):. But in the first case bot is spamming, in the second case bot doesn't activate else statement(which i need to send notification), so i am getting spammed or instead bot doesn't send anything at all. Please help me: I need balance, when streamer is live send ONE notification and then break(then check only if statement which must prevent bot from spamming. Here is the CODE. I recommend you taking a look between line 74 and 119. Especially line 99 with if statement.
import os
import json
import discord
import requests
from discord.ext import tasks, commands
from discord.utils import get
from server import ping
from Time import mytimemy
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(785523710362124298)
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) + " Current time: " + str(mytimemy()))
# 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):
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}')
embeds = message.embeds
for embed in embeds:
if discord.Embed(title=f":red_circle: **LIVE**\n{user.name} is now streaming on Twitch! \n \n {stream_data['data'][0]['title']}") == embed:
try:
embed_title = twitch_embed.title
embed_description = twitch_embed.description
except Exception as e:
break
print(f"Already sent for {user.name} at {mytimemy()}!") #just sending the time and name
break
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 str(user.name) in embed_title and "is now streaming" 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.")
ping()
print('Server Running')
bot.run(TOKEN)
It is very hard to explain and understand, but please help me. I need to check embed content while someone is streaming, so the embed and message are send one time per stream and NO spamming. And when stream goes off forget that embed content, so the embed can be send next time too. If u don't understand something, please ask. My discord just in case: Dweller_Igor#3291. Please someone EDIT the question, if it helps you better understand it.
MINIMAL REPRODUCIBLE EXAMPLE (embed, if-statement and else-statement):
if status is True:
# Checks to see if the live message has already been sent.
async for message in channel.history(limit=200):
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}')
embeds = message.embeds
for embed in embeds:
if discord.Embed(title=f":red_circle: **LIVE**\n{user.name} is now streaming on Twitch! \n \n {stream_data['data'][0]['title']}") == embed:
try:
embed_title = twitch_embed.title
embed_description = twitch_embed.description
except Exception as e:
break
print(f"Already sent for {user.name} at {mytimemy()}!") #just sending the time and name
break
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
await ctx.send(content = "some message", embed = embed)
It was a very stupid question at the time, and it still is to this day
So I have this code:
while True:
recent_post = api.user_timeline(screen_name = 'PartAlert', count = 1, since_id=recent_id, include_rts = True, tweet_mode='extended')
if recent_post:
last_post = recent_post[0].full_text
urls = re.findall('http[s]?://(?:[a-zA-Z]|[0-9]|[$-_#.&+]|[!*(),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', last_post)
if urls:
print(f"[{datetime.datetime.now()}] Link(s) Found:")
for x in range(len(urls)):
if urls[x][-1] == ':':
urls[x] = urls[x][:-1]
print(urls[x])
recent_id = recent_post[0].id
time.sleep(10)
which gets the twitter post of a specific user. What I want now is that the url variable will send to a discord channel but whatever I try it doesnt work. Any ideas?
Be sure to place the send_url method above the line in which you call send_url (or you could use classes, but that might require redesigning your bot).
To send messages to a channel, you can use:
channel_id = # some channel id here
message = # some message here
channel = client.get_channel(channel_id)
await channel.send(message)
You could also define send_url like so
async def send_url(channel_id, message):
channel = client.get_channel(channel_id)
await channel.send(message)
Just be sure to place it above the line in which you call the method.
So I have a meme command for my bot. I've been trying to figure out how to make it less likely to show the same meme twice (it keeps repeating them). Here is my code:
#client.event
async def on_message(message):
if message.content.startswith(".meme"):
subreddit = reddit.subreddit("cleanmemes")
all_subs = []
top = subreddit.top(limit = 75)
for submission in top:
all_subs.append(submission)
random_sub = random.choice(all_subs)
name = random_sub.title
url = random_sub.url
em = discord.Embed(title = name, color = 0xffff00)
em.set_image(url = url)
await message.channel.send(embed = em)
Im new to programming, any tips?
You can save the memes' urls in a json or txt file. Then, you can check the new url with the sent ones.
#client.event
async def on_message(message):
if message.content.startswith(".meme"):
subreddit = reddit.subreddit("cleanmemes")
all_subs = []
top = subreddit.top(limit = 75)
for submission in top:
all_subs.append(submission)
random_sub = random.choice(all_subs)
name = random_sub.title
url = random_sub.url
with open('urls.txt', 'r+') as file:
if url in file.read():
return
else:
file.write(f'{url}\n')
em = discord.Embed(title = name, color = 0xffff00)
em.set_image(url = url)
await message.channel.send(embed = em)
In this code, you must create a urls.txt file at first. Then, it will check the url's of the memes that you've sent before. If it has sent before, it'll return and won't send anything. If it doesn't, it will save it to that txt file and will send the meme.
Could you try storing a list of the memes that you've already sent (i.e. a list of URLs) and check whether the URL is in your list before sending the message?
Pseudo-code example, below.
# at the beginning of your code initialize an empty list of memes
sent_memes = []
# check if meme has been sent - skip if so
if url in sent_memes:
pass
else:
# send meme
sent_memes.append(url) # add url to list of sent_memes
This approach would ensure that you never send two of the same memes (unless they have different URLs).
This works and I have no issue with it. my bot is about 1100 lines of code so not that much. I have a standard meme command using PRAW. Is there any way to make its response time faster and not embedding it is not an option. My ms is average.
code:
#client.command(pass_context=True)
async def meme(ctx):
subreddit = reddit.subreddit("meme")
all_subs = []
top = subreddit.top(limit=50)
for submission in top:
all_subs.append(submission)
random_sub = random.choice(all_subs)
name = random_sub.title
url = random_sub.url
embed = discord.Embed(title = name)
embed.set_image(url=url)
await ctx.send(embed=embed)
You can store a meme and then send it later. By sending and then getting a meme, you do not have to wait to get a meme before sending one. Then you prepare for the next one.
#client.command(pass_context=True)
async def meme(ctx):
if not hasattr(client, 'nextMeme'):
client.nextMeme = getMeme()
name, url = client.nextMeme
embed = discord.Embed(title = name)
embed.set_image(url=url)
await ctx.send(embed=embed)
client.nextMeme = getMeme()
def getMeme():
subreddit = reddit.subreddit("meme")
top = subreddit.top(limit=50)
for submission in top:
all_subs.append(submission)
random_sub = random.choice(all_subs)
name = random_sub.title
url = random_sub.url
return name, url
I changed bot to client, if client does not work for you then replace it with bot.