How do I create a timestamp in an embed with pycord? - discord

I would like my sent msg log which is an embedded msg to have a timestamp, so it would have a footing like bot_name • Today at 10:48 PM
Here is my current code,
#bot.event
async def on_message(ctx):
if ctx.author.bot: return
else:
log_msg = bot.get_channel(1023451687857442828)
embed = discord.Embed(
title = "Sent Message",
description = f"""This message was sent by{ctx.author.mention}, in {ctx.channel}\n**Message:** "{ctx.content}" """,
color = discord.Colour.green(),
)
embed.set_author(name=ctx.author)
embed.set_footer(text="bot_name")
await log_msg.send(embed=embed)```

You could do the following:
(remaining of your code)
now = datetime.now() # Gets your current time as a datetime object
embed.set_footer(text=f'bot_name • Today at {now.strftime("%H:%M")}') # Set your embed footer with the formatted time
await log_msg.send(embed=embed) # Sends your footer (already present in your original code)
If you don't have it imported already, you'll have to import datetime from datetime, or import datetime and do datetime.datetime.now() instead of just datetime.now()

You can use ctx.message.created_at to add a timestamp. That would look like this in the context of your code:
#bot.event
async def on_message(ctx):
if ctx.author.bot: return
else:
log_msg = bot.get_channel(1023451687857442828)
embed = discord.Embed(
title = "Sent Message",
description = f"""This message was sent by{ctx.author.mention}, in {ctx.channel}\n**Message:** "{ctx.content}" """,
color = discord.Colour.green(),
# message created at code below
timestamp = ctx.message.created_at
)
embed.set_author(name=ctx.author)
embed.set_footer(text="bot_name")
await log_msg.send(embed=embed)
Hope this helps

Related

Other commands are delayed when a command error occurs in discord py

#bot.command()
async def timer(ctx,minutes:int):
import datetime
start_time = datetime.datetime.now()
end_time = start_time + datetime.timedelta(minutes=minutes)
previous_time = datetime.datetime.now()
message = await ctx.channel.send('start timer!')
try:
while datetime.datetime.now() <= end_time:
current_time = datetime.datetime.now()
if current_time.minute != previous_time.minute:
previous_time = current_time
diff = end_time - datetime.datetime.now()
diff_seconds = diff.seconds
end_time_formatted = end_time.strftime('%I:%M:%S %p')
await message.edit(
content=f'> timer\n```⏰end time:{end_time_formatted}\n⏰{diff_seconds // 60}minute {diff_seconds%60}second left```'
)
except:
await ctx.channel.send('timer reset')
await message.edit(content='> time out!')
await ctx.channel.send('on time now')
The current timer is using message deletion because there is no other way to end it. However, when deleting the message, an error message appears after a one-minute interval. However, other commands are not available until error message appears.
i looking for way to solve it.

Stop 2 consecutive uses discord.py

I am making a discord bot in which an auction could take place.So I want someone to bid only once unless someone bids after him/her.
`async def bid(ctx):
embed1=discord.Embed(description= f'Bid has been placed by {ctx.author}', title='bid placed')
await ctx.send(embed=embed1)
`
That's what I have so far made.
You could put the author id in a variable:
bidderid = 0 #this will reset whenever your bot restarts
#client.command()
async def bid(ctx):
global bidderid
if ctx.author.id != bidderid: #if it is not the same bidder
bidderid = ctx.author.id
embed1=discord.Embed(description= f'Bid has been placed by {ctx.author}', title='bid placed')
await ctx.send(embed=embed1)
else: #if it is the same bidder
await ctx.send('You cannot bid twice in a row!') #replace with whatever message
note: It doesn't have to be the id, you could store ctx.author instead, idea is the same

How do i make my discord.py bot go through a text file and if a user says a word in that file it will delete that message + how to make uptime command

I want my discord.py bot to go through a text file and if a user says a word in that file it will delete that message
elif msg.content == '***':
await msg.channel.send("Dont curse")
await msg.delete()
that is my code but i want to replace *** with a text document
And also another question i have some issues with an uptime command
async def on_ready():
print("Bot is running")
activity = discord.Game(name="!test", type=3)
await client.change_presence(status=discord.Status.idle, activity=activity)
channel = client.get_channel(944665750453497886)
myid = '<#516236429689618467>'
await channel.send("I am online "+myid)
#Uptime code starts
global startdate
startdate = datetime.now()
#client.command()
async def uptime(ctx):
now = datetime.now()
uptime = startdate - now
uptime = uptime.strftime('%d/%h/%M')
await ctx.send(f'Uptime: {uptime}')

AttributeError: 'Context' object has no attribute 'guild_icon'

I am trying to set up a command to print the information of the server the bot is in. The code below gives the error AttributeError: 'Context' object has no attribute 'guild_icon'
#commands.command()
async def serverinfo(self,ctx):
name = str(ctx.guild.name)
description = str(ctx.guild.description)
owner = str(ctx.guild.owner)
id = str(ctx.guild.id)
region = str(ctx.guild.region)
memberCount = str(ctx.guild.member_count)
embed = discord.Embed(
title=name + " Server Information",
description=description,
color=discord.Color.blue()
)
embed.set_thumbnail(ctx.guild_icon)
embed.add_field(name="Owner", value=owner, inline=True)
embed.add_field(name="Server ID", value=id, inline=True)
embed.add_field(name="Region", value=region, inline=True)
embed.add_field(name="Member Count", value=memberCount, inline=True)
await ctx.send(embed=embed)
When trying to find the solution I tried to change the code to be
#commands.command()
async def serverinfo(self,ctx):
name = str(ctx.guild.name)
description = str(ctx.guild.description)
owner = str(ctx.guild.owner)
id = str(ctx.guild.id)
region = str(ctx.guild.region)
memberCount = str(ctx.guild.member_count)
embed = discord.Embed(
title=name + " Server Information",
description=description,
color=discord.Color.blue()
)
embed.set_thumbnail(ctx.guild.icon)
embed.add_field(name="Owner", value=owner, inline=True)
embed.add_field(name="Server ID", value=id, inline=True)
embed.add_field(name="Region", value=region, inline=True)
embed.add_field(name="Member Count", value=memberCount, inline=True)
await ctx.send(embed=embed)
But then I get the error discord.ext.commands.errors.CommandInvokeError: Command raised an exception: TypeError: set_thumbnail() takes 1 positional argument but 2 were given
Could someone tell me what I have done wrong and point me in the right direction?
Problem 1
ctx.guild_icon does not exist, you fix this in your second code by using ctx.guild.icon
Problem 2
discord.Embed.set_thumbnail takes in a named argument for the image.
In fact, it doesn't take in an image at all, but rather a url
Solution
To solve your issue, you should use the following:
embed.set_thumbnail(url=ctx.guild.icon.url)
More info
discord.ext.commands.Context
discord.Embed.set_thumbnail

cron job throwing DeadlineExceededError

I am currently working on a google cloud project in free trial mode. I have cron job to fetch the data from a data vendor and store it in the data store. I wrote the code to fetch the data couple of weeks ago and it was all working fine but all of sudden , i started receiving error "DeadlineExceededError: The overall deadline for responding to the HTTP request was exceeded" for last two days. I believe cron job is supposed to timeout only after 60 minutes any idea why i am getting the error?.
cron task
def run():
try:
config = cron.config
actual_data_source = config['xxx']['xxxx']
original_data_source = actual_data_source
company_list = cron.rest_client.load(config, "companies", '')
if not company_list:
logging.info("Company list is empty")
return "Ok"
for row in company_list:
company_repository.save(row,original_data_source, actual_data_source)
return "OK"
Repository code
def save( dto, org_ds , act_dp):
try:
key = 'FIN/%s' % (dto['ticker'])
company = CompanyInfo(id=key)
company.stock_code = key
company.ticker = dto['ticker']
company.name = dto['name']
company.original_data_source = org_ds
company.actual_data_provider = act_dp
company.put()
return company
except Exception:
logging.exception("company_repository: error occurred saving the company
record ")
raise
RestClient
def load(config, resource, filter):
try:
username = config['xxxx']['xxxx']
password = config['xxxx']['xxxx']
headers = {"Authorization": "Basic %s" % base64.b64encode(username + ":"
+ password)}
if filter:
from_date = filter['from']
to_date = filter['to']
ticker = filter['ticker']
start_date = datetime.strptime(from_date, '%Y%m%d').strftime("%Y-%m-%d")
end_date = datetime.strptime(to_date, '%Y%m%d').strftime("%Y-%m-%d")
current_page = 1
data = []
while True:
if (filter):
url = config['xxxx']["endpoints"][resource] % (ticker, current_page, start_date, end_date)
else:
url = config['xxxx']["endpoints"][resource] % (current_page)
response = urlfetch.fetch(
url=url,
deadline=60,
method=urlfetch.GET,
headers=headers,
follow_redirects=False,
)
if response.status_code != 200:
logging.error("xxxx GET received status code %d!" % (response.status_code))
logging.error("error happend for url: %s with headers %s", url, headers)
return 'Sorry, xxxx API request failed', 500
db = json.loads(response.content)
if not db['data']:
break
data.extend(db['data'])
if db['total_pages'] == current_page:
break
current_page += 1
return data
except Exception:
logging.exception("Error occured with xxxx API request")
raise
I'm guessing this is the same question as this, but now with more code:
DeadlineExceededError: The overall deadline for responding to the HTTP request was exceeded
I modified your code to write to the database after each urlfetch. If there are more pages, then it relaunches itself in a deferred task, which should be well before the 10 minute timeout.
Uncaught exceptions in a deferred task cause it to retry, so be mindful of that.
It was unclear to me how actual_data_source & original_data_source worked, but I think you should be able to modify that part.
crontask
def run(current_page=0):
try:
config = cron.config
actual_data_source = config['xxx']['xxxx']
original_data_source = actual_data_source
data, more = cron.rest_client.load(config, "companies", '', current_page)
for row in data:
company_repository.save(row, original_data_source, actual_data_source)
# fetch the rest
if more:
deferred.defer(run, current_page + 1)
except Exception as e:
logging.exception("run() experienced an error: %s" % e)
RestClient
def load(config, resource, filter, current_page):
try:
username = config['xxxx']['xxxx']
password = config['xxxx']['xxxx']
headers = {"Authorization": "Basic %s" % base64.b64encode(username + ":"
+ password)}
if filter:
from_date = filter['from']
to_date = filter['to']
ticker = filter['ticker']
start_date = datetime.strptime(from_date, '%Y%m%d').strftime("%Y-%m-%d")
end_date = datetime.strptime(to_date, '%Y%m%d').strftime("%Y-%m-%d")
url = config['xxxx']["endpoints"][resource] % (ticker, current_page, start_date, end_date)
else:
url = config['xxxx']["endpoints"][resource] % (current_page)
response = urlfetch.fetch(
url=url,
deadline=60,
method=urlfetch.GET,
headers=headers,
follow_redirects=False,
)
if response.status_code != 200:
logging.error("xxxx GET received status code %d!" % (response.status_code))
logging.error("error happend for url: %s with headers %s", url, headers)
return [], False
db = json.loads(response.content)
return db['data'], (db['total_pages'] != current_page)
except Exception as e:
logging.exception("Error occured with xxxx API request: %s" % e)
return [], False
I would prefer to write this as a comment, but I need more reputation to do that.
What happens when you run the actual data fetch directly instead of
through the cron job?
Have you tried measuring a time delta from the start to the end of
the job?
Has the number of companies being retrieved increased dramatically?
You appear to be doing some form of stock quote aggregation - is it
possible that the provider has started blocking you?

Resources