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.
Related
im making user market command thing
im trying to make cooltime so that i can prevant spam
so how do i get last message from ctx.author in DM channel
im using cogs
Get the channel via
channel = ctx.author.dm_channel
Like documented here.
This will return an discord.DMChannel object of which you can get the history
lastMessage = await channel.history(limit=1).flatten()[0]
In total the call could look something like this
channel = ctx.author.dm_channel
if channel != None:
messages = await channel.history(limit=1).flatten()
if len(messages) != 0:
lastMessage = messages[0]
# lastMessage will be the last message in the channel
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
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).
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).
When trying to save my list of reactionrole objects with pickle it gives me the error Command raised an exception: TypeError: cannot pickle 'TaskStepMethWrapper' object.
I have not tried anything because I'm not sure what TaskStepMethWrapper is. Here's my code:
#client.command()
async def reactionadd(ctx):
# await ctx.send('Please give me the ID of the message you want to have a reactionrole on.')
# msgid_var = await client.wait_for('message')
await ctx.send('Please react with the emoji you want the reactionrole to use.')
emoji_var = await client.wait_for('reaction_add')
# await ctx.send('Please give me the ID of the role you want the reactionrole to give.')
# roleid_var = await client.wait_for('message')
if not os.path.isfile('reactionrole.obj'):
rrf = open('reactionrole.obj', 'xb')
rrf.close()
rrf = open('reactionrole.obj', 'rb+')
if os.stat('reactionrole.obj').st_size == 0:
rrobj = []
else:
rrobj = pickle.load(rrf)
emoji_var = emoji_var[0]
rrobj.append(reactionrole(749316751212150965, emoji_var, 749317419255857232))
pickle.dump(rrobj, rrf)
rrf.close()
class reactionrole:
def __init__(self, msgid, emoji, roleid):
self.msgid = msgid
self.emoji = emoji
self.roleid = roleid
SO, how to fix this error? should I go on with pickle or use another serialization technique? I could write to and parse a text file myself if needed.
Turns out emoji_var[0] is an object. Simply using str() to turn it into a string fixed this.