So I made this discord bot and hosted it on Heroku. It fetches the latest tweet from a Twitter account and displays it in a specific channel on discord. It works fine most of the time but sometimes it happens that after a few hours, it fetches and displays the first tweet of the Twitter account again, even though there's no new tweet. I used asyncio.gather() to tackle this problem and it worked fine but it happened again today. I have been trying to solve this problem but to no avail. What do I do?
async def send_to_alert(embed):
await client.get_channel(alert_channel_id).send(content="#everyone", embed=embed)
return
async def send_to_all(embed):
await client.get_channel(all_channel_id).send(content="#everyone", embed=embed)
return
async def send_to_one(text):
await client.get_channel(all_channel_id).send(content=f"#everyone\n{text}")
return
#client.event
async def on_ready():
print('Logged in as ' + client.user.name)
print("Starting to fetch the last tweet from the " + USER_TO_SNITCH + " account")
last_tweet = '0'
while True:
current_last_tweet = \
api.user_timeline(screen_name=USER_TO_SNITCH, count=1, include_rts=False, tweet_mode='extended')[0]
if (int(current_last_tweet.id_str) > int(last_tweet)) and (
not current_last_tweet.full_text.startswith('RT')):
last_tweet = current_last_tweet.id_str
text = current_last_tweet.full_text
if "#chart" not in text and "#CHART" not in text and "#Chart" not in text:
if "#alert" in text or "#Alert" in text or "#ALERT" in text:
embed = alert_found(text)
# await send_to_alert(embed)
# await send_to_all(embed)
await asyncio.gather(send_to_alert(embed), send_to_all(embed))
else:
await asyncio.gather(send_to_one(current_last_tweet.full_text))
else:
media_link = current_last_tweet.extended_entities["media"][0]["media_url_https"]
text = current_last_tweet.full_text.split()
text.pop()
text = " ".join(text)
text = text.replace("#Charts", "").strip()
text = text.replace("#CHARTS", "").strip()
text = text.replace("#charts", "").strip()
text = text.replace("#chart", "").strip()
text = text.replace("#Chart", "").strip()
text = text.replace("#CHART", "").strip()
if text == "":
text = " "
media_embed = discord.Embed(color=0xffd500, description=f"**{text}**").set_image(url=media_link)
await asyncio.gather(client.get_channel(charts_channel_id).send(content="#everyone", embed=media_embed))
time.sleep(10)
client.run(DISCORD_BOT_TOKEN)
Related
when i write to the bot the name of the product i want to see the bot doesn't send me any message
def create_message_select_query(ans):
text = ""
for i in ans:
id = i[0]
name = i[1]
icon = i[2]
text += "id: ""<b>"+ str(id) +"</b> | " + "<b>"+ str(name) +"</b> | " + "<b>"+ str(icon)+"</b> | " "\n"
message = "<b>Received 📖 </b> Information about orders:\n\n"+text
return message
#client.on(events.NewMessage(pattern="(?i)/mostra"))
async def delete(event):
try:
sender = await event.get_sender()
SENDER = sender.id
name = re.match(" .*",event.message.text)
sql_command = "SELECT * FROM unitsprova WHERE name REGEXP (%s) Limit 1;"
ans = crsr.execute(sql_command, (name,))
conn.commit()
res = crsr.fetchall()
if ans < 1:
text = "Order with id {} is not present".format(name)
await client.send_message(SENDER, text, parse_mode='html')
else:
text = create_message_select_query(res)
await client.send_message(SENDER, text, parse_mode='html')
except Exception as e:
print(e)
await client.send_message(SENDER, "Something Wrong happened... Check your code!", parse_mode='html')
return
i tried this way also
sender = await event.get_sender()
SENDER = sender.id
list_of_words = event.message.text.split(" ")
name = list_of_words[ 1 ]`
but the bot only counts the first word I type and not the rest (and I need it to count all the words the user types)
I have a working script but when I changed the page.on in playwright it actually runs the network response a certain number of times as per the loop count. I have been trying to figure out why that happens.
For example at i=0 it gives one response.url print but at i=10 it prints response.url 10 times and then send 10 duplicate data to mongodb. I have no idea why this is happening. The link being sent based on the print are all the same.
Would be a great help if anyone can let me know what it is that I am doing wrong that is causing this issue.
Pls see sample code here.
#imports here
today = datetime.today().strftime("%m%d%Y")
filenamearr = []
mongousername = 'XXX'
mongopassword = 'XXXX'
client = MongoClient("mongodb+srv://%s:%s#XXXXX.XXXX.mongodb.net/?retryWrites=true&w=majority"%(mongousername,mongopassword))
db = client.DB1
logg = []
async def runbrowser(playwright,url):
async def handle_response(response,buttonnumber):
l = str(response.url)
para = 'param'
if para in l:
print(response.url)
textdata = await response.text()
subtask = asyncio.create_task(jsonparse(textdata))
done, pending = await asyncio.wait({subtask})
if subtask in done:
print("Success in Json parser")
result = await subtask
status = [buttonnumber,result]
logg.append(status)
print(status)
logdf = pd.DataFrame(logg)
logdf.columns = ['BUTTON','RESULT']
fname = 'XXXX' + today +".csv"
logdf.to_csv(fname,index=False)
async def jsonparse(textdata):
try:
#parsing happens here to output to MongoDB
return "Success"
except Exception as e:
print("Failled parsing")
return e
browser = await playwright.firefox.launch(
headless=True,
)
context = await browser.new_context(
locale='en-US',
ignore_https_errors = True,
)
page = await context.new_page()
await page.goto(url,timeout=0)
button = page.locator("xpath=//button[#event-list-item='']")
bcount = button.locator(":scope",has_text="Locator")
count = await bcount.count()
print(count)
for i in range(count):
print("\n\n\n\n\nSleeping 10 seconds before clicking button")
buttonnumber = i
await asyncio.sleep(10)
print("Clickking Button: ", i)
cbtn = bcount.nth(i)
await cbtn.hover()
await asyncio.sleep(4)
await cbtn.click()
if i==0:
print("i=0")
await page.reload(timeout=0)
retry = page.on("response",lambda response: handle_response(response,buttonnumber))
title = await page.title()
print(title)
print("Heading back to the main page.")
await page.go_back(timeout=0)
await page.reload()
await page.wait_for_timeout(5000)
await page.close()
print("Closing Tab")
await browser.close()
async def main():
tasks = []
async with async_playwright() as playwright:
url = 'https://samplelink.com'
tasks.append(asyncio.create_task(runbrowser(playwright,url)))
for t in asyncio.as_completed(tasks):
print(await t)
await asyncio.gather(*tasks)
asyncio.run(main())
I'm trying to make a bot that would autoreact, check the amount of reactions on the messages in a channel, make a link to the message and send it on a moderation channel if it got 2 or more reactions, then log it's jump url in bot's directory. I cant find a way to fetch all the messages with jump_url and reactions attributes. im feeling super lost so i'll put the code here
async def on_message(message):
if message.channel.id == 828579458167996420:
channel = client.get_channel(828579458167996420)
if message.attachments or "http" in message.content:
await message.add_reaction("<:MashaUpset:828589397074116709>")
x = int
messages = await channel.history(limit=21).flatten()
f = open("message log.txt","r")
readfile = f.read()
f.close()
if str(messages.jump_url) not in readfile:
if messages.reactions[0].count >= 2:
x = messages.reactions[0].count - 1
link = messages.jump_url
channel = client.get_channel(892065611876823100)
await channel.send("this post was liked "+ str(x) + " times! "+ str(link))
f = open("message log.txt", "a")
f.write("\n" + str(messages.jump_url))
f.close()
im a beginner, so sorry for the mess i've made
Edit: can't fetch jump_url, so instead fetching for message.id
Ok I found it. thx to Dominik for help
Changes I've done
I've separated the script into 2 parts, an on_message and a #tasks.loop
Added a for x loop
Added an await channel.fetch_message(x.id) in the loop
Fetched for message.id rather than jump_url
Added if statement to check if the message has reactions
#client.event
async def on_message(message):
if message.channel.id == 828579458167996420:
if message.attachments or "http" in message.content:
await message.add_reaction("<:MashaUpset:828589397074116709>")
#tasks.loop(minutes=2)
async def check():
channel = client.get_channel(828579458167996420)
messages = await channel.history(limit=30).flatten()
await asyncio.sleep(3)
f = open("message log.txt","r")
readfile = f.read()
f.close()
for message in messages:
channel = client.get_channel(828579458167996420)
message = await channel.fetch_message(message.id)
if str(message.id) not in readfile:
if message.reactions:
if message.reactions[0].count >= 2:
x = message.reactions[0].count - 1
link = message.jump_url
channel = client.get_channel(892065611876823100)
await channel.send("this post was liked "+ str(x) + " times! "+ str(link))
f = open("message log.txt", "a")
f.write("\n" + str(message.id))
f.close()
#check.before_loop
async def before():
await client.wait_until_ready()
check.start()
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'm creating a discord bot and tryying to save stats about every user and their messages sent but it's not working. This is what I have:
async def update_stats():
await client.wait_until_ready()
global messages, author
data = []
if author != 0:
try:
with open("stats.txt", "r") as f:
data = f.readlines()
for item in data:
author2, messages2 = item.split(":")
print(author2, messages2)
index = data.index(item)
if author == author2:
with open("stats.txt", "w") as f1:
data.pop(index)
novi_stat = f"""{author}:{int(messages) + int(messages2)}\n"""
data.insert(index, novi_stat)
str = ''.join(data)
f1.write(str)
else:
with open("stats.txt", "w") as f2:
data.append(f"""{author}:{messages}\n""")
str = ''.join(data)
f2.write(str)
await asyncio.sleep(5)
except Exception as e:
print(e)
await asyncio.sleep(5)
And this is the content of the text file it loads and is supposed to change when number of messages changes:
DrDEagle#4984:100
kreten:123
This is what I get when running the code:
DrDEagle#4984:100
kreten:123
:0
It is supposed to change the number from 100 to 101 if I send one message, but instead it writes a new line which doesn't even contain the right data, what am I doing wrong?
EDIT: After an hour of editing and rewriting the code, I did this and it works.
import discord
import random
import aiohttp
import asyncio
import json
import datetime
client = discord.Client()
sentdex_guild = client.get_guild(No, No!) # I didn't post the code...
author = ''
messages = 0
#client.event
async def on_message(message):
global author, messages
author = message.author.name
messages += 1
authorsInFile = []
f = open("stats.txt", 'r')
data = f.readlines()
for item in data:
author2, messages2 = item.split(":")
authorsInFile.append(author2)
print(author2, messages2)
if author in authorsInFile:
index = authorsInFile.index(author)
else:
pass
if author2 == author:
f1 = open("stats.txt", "w")
print(author)
data.pop(index)
novi_stat = f"""{author}:{int(messages2) + 1}\n"""
data.insert(index, novi_stat)
str = ''.join(data)
f1.write(str)
f1.close()
f.close()
else:
f2 = open("stats.txt", "w")
data.append(f"""{author}:{messages}\n""")
str = ''.join(data)
f2.write(str)
f2.close()
f.close()
await asyncio.sleep(5)
with open('log.txt', 'a') as f:
f.write(f"""{datetime.datetime.now()} | {message.author} je rekao: {message.content}\n""")
if message.content == "!bok":
await message.channel.send("Pozdrav!")
elif message.content == "!korisnici":
online = 0
idle = 0
offline = 0
for m in sentdex_guild.members:
if str(m.status) == "online":
online += 1
if str(m.status) == "offline":
offline += 1
else:
idle += 1
await message.channel.send(f"""Broj korisnika: {online+offline - 1}\nˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ\nOnline korisnika: {online - 1}\nOffline korisnika: {offline}\n^^^^^^^^^^^^^^^^^^^^^^^^""") # printa broj korisnika, ali ne broji sebe
elif message.content == "!ping":
latency = client.latency
await message.channel.send(f"""Moj ping iznosi {round(latency, 6)}ms""")
elif message.content == "!yacketty":
await message.channel.send("Dostupne komande su: !ping, !bok, !korisnici, !bitcoin...")
elif message.content == "!bitcoin":
url = 'https://api.coindesk.com/v1/bpi/currentprice/BTC.json'
async with aiohttp.ClientSession() as session: # Async HTTP request
raw_response = await session.get(url)
response = await raw_response.text()
response = json.loads(response)
await message.channel.send("Cijena bitcoina: $" + response['bpi']['USD']['rate'])
elif "!8ball" in message.content:
moguci_odgovori = [
'Nema jebene Å¡anse',
'Možda, ali samo možda',
'Ahhh, 50-50',
'Vrlo moguće',
'Apsolutno da'
]
await message.channel.send(random.choice(moguci_odgovori) + ", " + message.author.mention)
#client.event
async def welcome(member):
for channel in member.server.channels:
if str(channel) == "general":
await client.send_message(f"""{member.mention}, dobrodošao na server!""")
client.run("I'm not showing you this hehe")
I don't see anywhere that you set either author or messages. You have them set as globals, so I assume you're setting them before calling this function. If author is an empty string, and messages is 0, then the output you are getting is just what I would expect from your code.
Since there is not yet an author named "", it appends an entry for that author to the file that is the empty author name, a colon, and the 0 that is the value of message.
Note that your first if test would succeed and the if block entered in this proposed case, as "" != 0 is True.
Another observation...you're reading in multiple existing authors, but you seem to be only comparing the passed in author against the last author read in from the file. I'm assuming that's not what you want...you probably want to be comparing each author you read in against the passed in author in the loop that is processing each line of the file.