Telegram Bot profile with calendar - python-3.x

I am writing a bot profile. After the answer, the following question should be asked. In one of the steps you need to select a date. I use a ready-made calendar. But after choosing a date, the next question is not asked, but the script does not crash, only waits for input and throws the Exception defined in the code below. How to fix that would bring up the next question "What is your name?". Thank. Here is the part of the code that includes the previous calendar question and the next question:
def process_Personenanzahl_step(message):
try:
chat_id = message.chat.id
user = user_dict[chat_id]
user.carModel = message.text
markup = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True)
itembtn1 = types.KeyboardButton('1')
itembtn2 = types.KeyboardButton('2')
itembtn3 = types.KeyboardButton('3')
itembtn4 = types.KeyboardButton('4')
itembtn5 = types.KeyboardButton('5')
markup.add(itembtn1, itembtn2, itembtn3, itembtn4, itembtn5)
msg = bot.send_message(chat_id, 'Qun', reply_markup=markup)
bot.register_next_step_handler(msg, check_calendar_messages)
except Exception as e:
bot.reply_to(message, 'ooops!!')
calendar_1 = CallbackData("calendar_1", "action", "year", "month", "day")
def check_calendar_messages(message):
now = datetime.datetime.now() # Get the current date
bot.send_message(
message.chat.id,
"Selected date",
reply_markup=telebot_calendar.create_calendar(
name=calendar_1.prefix,
year=now.year,
month=now.month, # Specify the NAME of your calendar
),
)
#bot.callback_query_handler(func=lambda call: call.data.startswith(calendar_1.prefix))
def callback_inline(call: object) -> object:
# At this point, we are sure that this calendar is ours. So we cut the line by the separator of our calendar
name, action, year, month, day = call.data.split(calendar_1.sep)
# Processing the calendar. Get either the date or None if the buttons are of a different type
date = telebot_calendar.calendar_query_handler(
bot=bot, call=call, name=name, action=action, year=year, month=month, day=day
)
# There are additional steps. Let's say if the date DAY is selected, you can execute your code. I sent a message.
if action == "DAY":
msg = bot.send_message(
chat_id=call.from_user.id,
text=f"You have chosen {date.strftime('%d.%m.%Y')}",
reply_markup=ReplyKeyboardRemove(),
)
print(f"{calendar_1}: Day: {date.strftime('%d.%m.%Y')}")
bot.register_next_step_handler(msg, process_fullname_step)
def process_fullname_step(message):
try:
chat_id = message.chat.id
user_dict[chat_id] = User(message.text)
markup = types.ReplyKeyboardRemove(selective=False)
msg = bot.send_message(chat_id, 'What is your name?', reply_markup=markup)
bot.register_next_step_handler(msg, process_fullname_step)
except Exception as e:
bot.reply_to(message, 'ooops!!')

Related

Save all data in database with one query in Django

I'm a new Django programmer. I write a API call with rest_framework in Django. when call this API, my program connect to KUCOIN and get list of all cryptocurrency. I want save symbol and name this cryptocurrencies in database. For save data to database, I use 'for loop' and in every for loop iteration, I query to database and save data. my code :
for currencie in currencies:
name = currencie['name']
symbol = currencie['symbol']
active = (False, True)[symbol.endswith('USDT')]
oms = 'kucoin'
try:
obj = Instrument.objects.get(symbol=symbol, oms=oms)
setattr(obj, 'name', name)
setattr(obj, 'active', active)
obj.save()
except Instrument.DoesNotExist:
obj = Instrument(name=name, symbol=symbol,
active=active, oms=oms)
obj.save()
query to database in every for loop iteration have problem ,How can I solve this problem?
Exist any way in Django to save data in database in with one query.
All my code:
class getKucoinInstrument(APIView):
def post(self, request):
try:
person = Client.objects.filter(data_provider=True).first()
person_data = ClientSerializer(person, many=False).data
api_key = person_data['api_key']
api_secret = person_data['secret_key']
api_passphrase = person_data['api_passphrase']
client = kucoin_client(api_key, api_secret, api_passphrase)
currencies = client.get_symbols()
for currencie in currencies:
name = currencie['name']
symbol = currencie['symbol']
active = (False, True)[symbol.endswith('USDT')]
oms = 'kucoin'
try:
obj = Instrument.objects.get(symbol=symbol, oms=oms)
setattr(obj, 'name', name)
setattr(obj, 'active', active)
obj.save()
except Instrument.DoesNotExist:
obj = Instrument(name=name, symbol=symbol,
active=active, oms=oms)
obj.save()
return Response({'response': 'Instruments get from kucoin'}, status=status.HTTP_200_OK)
except Exception as e:
print(e)
return Response({'response': 'Internal server error'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
Thank you for you help.
Yes! Take a look at bulk_create() documentation. https://docs.djangoproject.com/en/4.0/ref/models/querysets/#bulk-create
If you have a db that supports ignore_conflicts parameter (all do, except Oracle), you can do this:
new_currencies = []
for currencie in currencies:
name = currencie['name']
symbol = currencie['symbol']
active = (False, True)[symbol.endswith('USDT')]
oms = 'kucoin'
new_currencies.append(Instrument(name=name, symbol=symbol,
active=active, oms=oms))
Instrument.objects.bulk_create(new_currencies, ignore_conflicts=True)
1-liner:
Instrument.objects.bulk_create(
[
Instrument(
name=currencie['name'], symbol=currencie['symbol'],
active=currencie['symbol'].endswith('USDT'), oms='kucoin'
)
for currencie in currencies
],
ignore_conflicts=True
)

How do I make a snipe command that shows the timestamp in the footer

I am able to get the time in UTC using the 'pytz' library and 'datetime' library, but I need it in local time of the user. Say you run the snipe command from the USA, you should get your local time, and if I run it from say Italy, I should get Italy's time. I hope I made it clear.
x = message = {}
y = author = {}
z = author_avatar = {}
time = {}
#client.event
async def on_message_delete(msg):
UTC = pytz.utc
datetime_utc = datetime.now(UTC)
if msg.author.bot == False:
x[msg.channel.id] = msg.content
y[msg.channel.id] = msg.author
time[msg.channel.id] = datetime_utc.strftime('%H:%M UTC')
if msg.author == client.user:
x[msg.channel.id] = msg.content
y[msg.channel.id] = msg.author
time[msg.channel.id] = datetime_utc.strftime('%H:%M UTC')
#client.command(name = 'snipe')
async def snipe(ctx):
try:
em = discord.Embed(description = f" {x[ctx.channel.id]}" ,color = random.choice(colors_for_embeds1), timestamp = datetime.now())
em.set_author(name = y[ctx.channel.id] ,icon_url = (y[ctx.channel.id]).author.url)
em.set_footer(text = f"at {time[ctx.channel.id]}")
await ctx.send(embed = em)
except:
await ctx.send("There is nothing to snipe!")
This is how the command works. The deleted message gets added to a dictionary with the channel ID as the key, the author id gets saved in a dictionary with the channel ID.
I hope this answers your question.
UTC time updates for your location, so for you, it would show your time (example: Today at 8:00 AM) then for someone else that is somewhere else in the world would show (Today at 9:00 AM).
I don't know if I answered this well or not, or if you understood it.
But hope answers your question! :D
your bot has no way of knowing the timezone of the people running the command. The timestamp on discord embeds always show the time in the local format for the people who see the embed, so different people will see different times depending on their timezones.
A solution would be to record the user timezone with a different command and save it to a database.
Then on your command parse the time into the footer for the timezone you want.

How can I return a string from a Google BigQuery row iterator object?

My task is to write a Python script that can take results from BigQuery and email them out. I've written a code that can successfully send an email, but I am having trouble including the results of the BigQuery script in the actual email. The query results are correct, but the actual object I am returning from the query (results) always returns as a Nonetype.
For example, the email should look like this:
Hello,
You have the following issues that have been "open" for more than 7 days:
-List issues here from bigquery code
Thanks.
The code reads in contacts from a contacts.txt file, and it reads in the email message template from a message.txt file. I tried to make the bigquery object into a string, but it still results in an error.
from google.cloud import bigquery
import warnings
warnings.filterwarnings("ignore", "Your application has authenticated using end user credentials")
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from string import Template
def query_emailtest():
client = bigquery.Client(project=("analytics-merch-svcs-thd"))
query_job = client.query("""
select dept, project_name, reset, tier, project_status, IssueStatus, division, store_number, top_category,
DATE_DIFF(CURRENT_DATE(), in_review, DAY) as days_in_review
from `analytics-merch-svcs-thd.MPC.RESET_DETAILS`
where in_review IS NOT NULL
AND IssueStatus = "In Review"
AND DATE_DIFF(CURRENT_DATE(), in_review, DAY) > 7
AND ready_for_execution IS NULL
AND project_status = "Active"
AND program_name <> "Capital"
AND program_name <> "SSI - Capital"
LIMIT 50
""")
results = query_job.result() # Waits for job to complete.
return results #THIS IS A NONETYPE
def get_queryresults(results): #created new method to put query results into a for loop and store it in a variable
for i,row in enumerate(results,1):
bq_data = (i , '. ' + str(row.dept) + " " + row.project_name + ", Reset #: " + str(row.reset) + ", Store #: " + str(row.store_number) + ", " + row.IssueStatus + " for " + str(row.days_in_review)+ " days")
print (bq_data)
def get_contacts(filename):
names = []
emails = []
with open(filename, mode='r', encoding='utf-8') as contacts_file:
for a_contact in contacts_file:
names.append(a_contact.split()[0])
emails.append(a_contact.split()[1])
return names, emails
def read_template(filename):
with open(filename, 'r', encoding='utf-8') as template_file:
template_file_content = template_file.read()
return Template(template_file_content)
names, emails = get_contacts('mycontacts.txt') # read contacts
message_template = read_template('message.txt')
results = query_emailtest()
bq_results = get_queryresults(query_emailtest())
import smtplib
# set up the SMTP server
s = smtplib.SMTP(host='smtp-mail.outlook.com', port=587)
s.starttls()
s.login('email', 'password')
# For each contact, send the email:
for name, email in zip(names, emails):
msg = MIMEMultipart() # create a message
# bq_data = get_queryresults(query_emailtest())
# add in the actual person name to the message template
message = message_template.substitute(PERSON_NAME=name.title())
message = message_template.substitute(QUERY_RESULTS=bq_results) #SUBSTITUTE QUERY RESULTS IN MESSAGE TEMPLATE. This is where I am having trouble because the Row Iterator object results in Nonetype.
# setup the parameters of the message
msg['From']='email'
msg['To']='email'
msg['Subject']="This is TEST"
# body = str(get_queryresults(query_emailtest())) #get query results from method to put into message body
# add in the message body
# body = MIMEText(body)
#msg.attach(body)
msg.attach(MIMEText(message, 'plain'))
# query_emailtest()
# get_queryresults(query_emailtest())
# send the message via the server set up earlier.
s.send_message(msg)
del msg
Message template:
Dear ${PERSON_NAME},
Hope you are doing well. Please find the following alert for Issues that have been "In Review" for greater than 7 days.
${QUERY_RESULTS}
If you would like more information, please visit this link that contains a complete dashboard view of the alert.
ISE Services
The BQ result() function returns a generator, so I think you need to change your return to yield from.
I'm far from a python expert, but the following pared-down code worked for me.
from google.cloud import bigquery
import warnings
warnings.filterwarnings("ignore", "Your application has authenticated using end user credentials")
def query_emailtest():
client = bigquery.Client(project=("my_project"))
query_job = client.query("""
select field1, field2 from `my_dataset.my_table` limit 5
""")
results = query_job.result()
yield from results # NOTE THE CHANGE HERE
results = query_emailtest()
for row in results:
print(row.field1, row.field2)

How to call a function every interval time Odoo 11

i know we can create automatic action using cron in odoo
but I want something a different
in the mass mailing of odoo i want to add a repetion option of mail mass mailings
Example in the Form view_mail_mass_mailing_form > Options page
I added a repetition selection field,
I added this because I want each mass mail alone
class MailMassMailing(models.Model):
_inherit = 'mail.mass_mailing'
recurrence_mail = fields.Selection([
('daily', 'Day'),
('weekly', 'Weeks'),
('monthly', 'Months'),
], string='Recurring')
I want this mass mailng to send each (days or weeks or months)
how to call a function with interval date,
how to call a function every (days or weeks or months)
The sending of this mass mailing is revived from the date of creation
Just extend Mass Mailing model with a new date field and implement a model method to use for a daily running ir.cron.
from odoo import api, fields, models
class MailMassMailing(models.Model):
_inherit = 'mail.mass_mailing'
recurrence_mail = fields.Selection([
('daily', 'Day'),
('weekly', 'Weeks'),
('monthly', 'Months'),
], string='Recurring')
last_sent_on = fields.Date()
#api.model
def run_send_recurring(self):
""" Resend mass mailing with recurring interval"""
domain = [('recurrence_mail', '!=', False)]
# TODO monthly should be solved in another way, but that
# is not needed for this example
deltas = {'daily': 1, 'weekly': 7, 'monthly': 30}
today = fields.Date.today()
for mass_mail in self.search(domain):
# never sent? go send it
if not mass_mail.last_sent_on:
# send the way you want
# or get delta between today and last_sent_on
last_dt = fields.Date.from_string(mass_mail.last_sent_on)
if (today - last_dt).days >= deltas[mass_mail.recurrence_mail]:
# send the way you want
Thank you #CZoellner for your help
I found the solution with your idea
# Solution ############### .py
#api.model
def run_send_recurring(self):
""" Resend mass mailing with recurring interval"""
date_format = '%Y-%m-%d'
domain = [('recurrence_mail', '!=', False),('state','=','done')]
deltas = {'daily': 1, 'weekly': 7, 'monthly': 30}
logger.info("______deltas________: %s ",deltas)
today = fields.Date.today()
logger.info("______today________: %s ",today)
for mass_mail in self.search(domain):
logger.info("______mass_mail________: %s ",mass_mail)
# never sent? go send it
if not mass_mail.last_sent_on:
self.put_in_queue()
joining_date = mass_mail.last_sent_on
current_date = (datetime.today()).strftime(date_format)
print('joining_date',joining_date)
d1 = datetime.strptime(joining_date, date_format).date()
logger.info("______1 day________: %s ",d1)
d2 = datetime.strptime(current_date, date_format).date()
logger.info("______2 day________: %s ",d2)
logger.info("______deltas[mass_mail.recurrence_mail]________: %s ",deltas[mass_mail.recurrence_mail])
r = relativedelta(d1,d2)
logger.info("______r day________: %s ",r.days)
if (r ,'>=' , deltas[mass_mail.recurrence_mail]):
mass_mail.put_in_queue()

python3 programme raising TypeError: 'dict' object is not callable [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 5 years ago.
Improve this question
I basically tried to write a programme which will send mails to a list of users.i ran the programme below and it is telling me that TypeError: 'dict' object is not callable. I cant understand what is wrong here and how to fix it.I know it's a long code but any kind of help would be appreciated. I may have made some silly mistakes but i cant reach it.
import datetime
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
host = "smtp.gmail.com"
port = 587
username = "testmail3018"
password = "******" #not disclosing the password
from_email = username
to_mail_list = ["testmail3018#gmail.com",
"rasel_cse07#gmail.com"]#to_email always have to be a list
#not using this list anymore in this programme
class MessageUser():
User_Details = []
Messages = []
Email_Message = []
base_message = """Hi {name}!
Thank you for the purchase on {date}.
We hope you are exicted about using it. Just as a
reminder the purcase total was ${total}.
Have a great time!
from Pritom_Mazhi
"""
def add_user(self, name, amount, email=None):
name = name[0].upper() + name[1:].lower() #Capitalizing the first
letter of all names - formatted name
amount = "%.2f" %(amount) #formatted amount
detail = {
"name" : name,
"amount" : amount,
}
today = datetime.date.today()
date_text =
'{tday.day}/{tday.month}/{tday.year}'.format(tday=today)
#formatted date
detail["date"] = date_text
if email is not None:
detail["email"] = email
self.User_Details.append(detail)
def get_details(self):
return self.User_Details
def make_message(self):
if len(self.User_Details) > 0:
for detail in self.get_details(): #for detail in
self.User_Details
name = detail["name"]
amount = detail["amount"]
date = detail["date"]
#email = detail["email"]
message = self.base_message
formatted_message = message.format(
name = name,
total = amount,
date = date
)
user_email = detail.get("email")
if user_email:
user_data = {
"email" : user_email,
"message" : formatted_message
}
self.Email_Message.append(user_data)
else:
self.Messages.append(formatted_message)
return self.Messages
else:
return []
def send_email(self):
self.make_message()
if len(self.Email_Message) > 0:
for item in self.Email_Message:
user_email = item("email")
user_message = item("message")
try:
gmail_connection = smtplib.SMTP(host, port)
gmail_connection.ehlo()
gmail_connection.starttls()
gmail_connection.login(username, password)
the_message = MIMEMultipart("alternative")
the_message["Subject"] = "hi there! trying to send
some billing messages or messages like that"
the_message["From"] = from_email
the_message["To"] = user_email
part1 = MIMEText(user_message, 'plain')
the_message.attach(part1)
gmail_connection.sendmail(from_email, [user_email],
the_message.as_string())
#to_email always have to be a list
gmail_connection.quit()
except smtplib.SMTPException:
print("error sending mails or messages")
#return False - could be used here instead of using
below but while iterating this wouldn't be good
return True
return False
obj = MessageUser()
obj.add_user("Pritom", 123.32, email='testmail3018#gmail.com')
obj.add_user("jon Snow", 94.23, email='testmail3018#gmail.com')
obj.add_user("Sean", 93.23, email='testmail3018#gmail.com')
obj.add_user("Emilee", 193.23, email='testmail3018#gmail.com')
obj.add_user("Marie", 13.23, email='testmail3018#gmail.com')
obj.get_details()
obj.send_email()
the output is in attached screenshot.
the terminal is showing error as follows:
Traceback (most recent call last):
File "day_12.py", line 118, in
obj.send_email()
File "day_12.py", line 78, in send_email
user_email = item("email")
TypeError: 'dict' object is not callable
in python, in order to access values in a dict, you have two ways:
dict['key']
dict.get('key')
dict('key') will not work.

Resources