Accessing nested data in a supposed dict - python

Alright, I'm stumped. I have googled everything I can think of from nested Dicts, Dicts inside Lists inside Dicts, to JSON referencing and have no idea how to get to this data.
I have this AWS Lambda handler that is reading Slack events and simply reversing someone's message and then spitting it out back to Slack. However, the bot can respond to itself (creating an infinite loop). I thought I had this solved, however, that was for the legacy stuff. I am Python stupid, so how do reference this data?
Data (slack_body_dict print from below):
{'token': 'NgapUeqidaGeTf4ONWkUQQiP', 'team_id': 'T7BD9RY57', 'api_app_id': 'A01LZHA7R9U', 'event': {'client_msg_id': '383aeac2-a436-4bad-8e19-7fa68facf916', 'type': 'message', 'text': 'rip', 'user': 'U7D1RQ9MM', 'ts': '1612727797.024200', 'team': 'T7BD9RY57', 'blocks': [{'type': 'rich_text', 'block_id': 'gA7K', 'elements': [{'type': 'rich_text_section', 'elements': [{'type': 'text', 'text': 'rip'}]}]}], 'channel': 'D01MK0JSNDP', 'event_ts': '1612727797.024200', 'channel_type': 'im'}, 'type': 'event_callback', 'event_id': 'Ev01MN8LJ117', 'event_time': 1612727797, 'authorizations': [{'enterprise_id': None, 'team_id': 'T7BD9RY57', 'user_id': 'U01MW6UK55W', 'is_bot': True, 'is_enterprise_install': False}], 'is_ext_shared_channel': False, 'event_context': '1-message-T7BD9RY57-D01MK0JSNDP'}
There is an 'is_bot' there under 'authorizations' I want to check. I assume this will let the bot stop responding to itself. However, for the life of me, I cannot reference it. It seems to be nested in there.
I have tried the following:
def lambda_handler(api_event, api_context):
print(f"Received event:\n{api_event}\nWith context:\n{api_context}")
# Grab relevant information form the api_event
slack_body_raw = api_event.get('body')
slack_body_dict = json.loads(slack_body_raw)
request_headers = api_event["headers"]
print(f"!!!!!!!!!!!!!!!!!!!!!!!body_dict:\n{slack_body_dict}")
print(f"#######################is_bot:\n{slack_body_dict('is_bot')}")
print(f"#######################is_bot:\n{slack_body_dict("is_bot")}")
print(f"#######################is_bot:\n{slack_body_dict(['is_bot']}")
print(f"#######################is_bot:\n{slack_body_dict(["is_bot"]}")
print(f"#######################is_bot:\n{slack_body_dict['authorizations']['is_bot']}")
As you can see I have absolutely no clue how to get to that variable to tell if it is true or false. Every 'is_bot' print reference results in an error. Can someone tell me how to reference that variable or give me something to google? Appreciate it. Code is below in case it is relevant.
import json
import os
from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError
def is_challenge(slack_event_body: dict) -> bool:
"""Is the event a challenge from slack? If yes return the correct response to slack
Args:
slack_event_body (dict): The slack event JSON
Returns:
returns True if it is a slack challenge event returns False otherwise
"""
if "challenge" in slack_event_body:
LOGGER.info(f"Challenge Data: {slack_event_body['challenge']}")
return True
return False
def lambda_handler(api_event, api_context):
# Grab relevant information form the api_event
slack_body_raw = api_event.get('body')
slack_body_dict = json.loads(slack_body_raw)
request_headers = api_event["headers"]
# This is to appease the slack challenge gods
if is_challenge(slack_body_dict):
challenge_response_body = {
"challenge": slack_body_dict["challenge"]
}
return helpers.form_response(200, challenge_response_body)
# This parses the slack body dict to get the event JSON
slack_event_dict = slack_body_dict["event"]
# Build the slack client.
slack_client = WebClient(token=os.environ['BOT_TOKEN'])
# We need to discriminate between events generated by
# the users, which we want to process and handle,
# and those generated by the bot.
if slack_body_dict['is_bot']: #THIS IS GIVING ME THE ERROR. I WANT TO CHECK IF BOT HERE.
logging.warning("Ignore bot event")
else:
# Get the text of the message the user sent to the bot,
# and reverse it.
text = slack_event_dict["text"]
reversed_text = text[::-1]
# Get the ID of the channel where the message was posted.
channel_id = slack_event_dict["channel"]
try:
response = slack_client.chat_postMessage(
channel=channel_id,
text=reversed_text
)
except SlackApiError as e:
# You will get a SlackApiError if "ok" is False
assert e.response["error"] # str like 'invalid_auth', 'channel_not_found'

The structure of the data is:
{
"authorizations": [
{
"is_bot": true
}
]
}
So you would need to first index "authorizations", then to get the first item 0, and lastly "is_bot".
data["authorizations"][0]["is_bot"]
Alternativly, you could iterate over all the authorizations and check if any (or all) of them are marked as a bot like so:
any(auth["is_bot"] for auth in slack_body_dict["authorizations"])

Related

Hotbit cancel all orders request endpoint does not work | Python

I´ve tried to create a cancelAllOrder function for my Class.
When I use the cancel All button manually I get this result:
Endpoint: https://www.hotbit.io/v1/order/cancel_all?platform=web
The payload tab looks like this:
and the answer should looks like this: {Code: 1100, Msg: "all orders are sucessfully cancelled", Content: null}
I used this Information and turned it into this code:
def cancelAll0(self, market, order_ids):
payload = [{'market': market.replace('/', ''), 'order_id': o} for o in order_ids]
print(payload)
resp = self.session.post('https://www.hotbit.io/v1/order/cancel_all?platform=web', data=payload, headers=self.headers, cookies=self.cookies)
return resp.json()
Headers and Cookies should be good as everything else (like creating orders, requesting balance, etc.) works fine.
When I use it, I get this:
print(client.cancelAll0("ETH/USDT", order_ids=order_ids))
Output:
[{'market': 'ETHUSDT', 'order_id': 135217230000}, {'market': 'ETHUSDT', 'order_id': 135217120000}]
{'Code': 1201, 'Msg': "invalid character 'm' looking for beginning of value", 'Content': None}
As I get a response, just not the one I wanted, I think something is wrong with my payload. I checked the format of the Array but it should be correct.

How to take from key value and take from this value another value

How can i get needed value, because i send post request to other site and cant edit answer from site.
I have this dict from responded content:
{'username': 'DeadFinder', 'subscriptions': [{'subscription': 'default', 'expiry': '1635683460'}], 'ip': 'not at this life'}
How you can see in this dict there is a key subscriptions, i'm need value expiry(this is timestamp) but how can i get this value if when i'm trying to call this value i'm not see any results (code not gives needed value), maybe any variants how to get this value? I'm not finded anything like this.
Maybe my small part of code can smally help you but i doubt.
data1 = {f"hwid":"", "type":"login", "username": {username}, "pass": {password},
"sessionid":f"{response_cut2}", "name":"test_app", "ownerid":"5OLbm5S3fS"}
url1 = "nope"
response1 = requests.post(url1, data1)
data = response1.json()
#get = data.get('expiry')
file_write = open("test.txt", "w")
file_write.write(str(data))
file_write.close()
for key in data.keys():
if key == 'info':
print (data[key])
Are you trying to achieve this as result ?
data = {'username': 'DeadFinder', 'subscriptions': [{'subscription': 'default', 'expiry': '1635683460'}], 'ip': 'not at this life'}
print(data['subscriptions'][0]['expiry'])
# first get 'subscriptions' which returns an array,
# so use [0] to get this dict {'subscription': 'default', 'expiry': '1635683460'}
# then get 'expiry'
EDIT : In case subscriptions has multiple values then use for loop
subscriptions = data['subscriptions']
for subscription in subscriptions:
print(subscription['expiry'])
Output
1635683460

Did i migrate from the default code to my testing one properly?

I want to create develop a chatbot using Lex's interface, as a first step i found a ScheduleAppointment default bot so i decided to do adjustments to it. The default prompts in this bot are date, time and appointmenttype. As a first step i went to using blueprint lex-make-appointment-python https://console.aws.amazon.com/lambda/home?region=us-east-1#/create/new?bp=lex-make-appointment-python and had to change lots of the default stuff there, for example it has an exact appointment time and days etc while the version i want to work on before developing it any further in lambda is one that would take ANY TIME and ANY DAY for example i can't get an error if i ask to schedule an appointment tomorrow but if the bot asks for date and i put something like hfujdhfu or banana i should be asked what is the date? again.
All that being said and done this is my version of that code after adjusting it :
import json
import dateutil.parser
import datetime
import time
import os
import math
import random
import logging
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
""" --- Helpers to build responses which match the structure of the necessary dialog actions --- """
def elicit_slot(session_attributes, intent_name, slots, slot_to_elicit, message, response_card):
return {
'sessionAttributes': session_attributes,
'dialogAction': {
'type': 'ElicitSlot',
'intentName': intent_name,
'slots': slots,
'slotToElicit': slot_to_elicit,
'message': message,
'responseCard': response_card
}
}
def confirm_intent(session_attributes, intent_name, slots, message, response_card):
return {
'sessionAttributes': session_attributes,
'dialogAction': {
'type': 'ConfirmIntent',
'intentName': intent_name,
'slots': slots,
'message': message,
'responseCard': response_card
}
}
def close(session_attributes, fulfillment_state, message):
response = {
'sessionAttributes': session_attributes,
'dialogAction': {
'type': 'Close',
'fulfillmentState': fulfillment_state,
'message': message
}
}
return response
def delegate(session_attributes, slots):
return {
'sessionAttributes': session_attributes,
'dialogAction': {
'type': 'Delegate',
'slots': slots
}
}
def build_response_card(title, subtitle, options):
"""
Build a responseCard with a title, subtitle, and an optional set of options which should be displayed as buttons.
"""
buttons = None
if options is not None:
buttons = []
for i in range(min(5, len(options))):
buttons.append(options[i])
return {
'contentType': 'application/vnd.amazonaws.card.generic',
'version': 1,
'genericAttachments': [{
'title': title,
'subTitle': subtitle,
'buttons': buttons
}]
}
""" --- Helper Functions --- """
def parse_int(n):
try:
return int(n)
except ValueError:
return float('nan')
def try_ex(func):
"""
Call passed in function in try block. If KeyError is encountered return None.
This function is intended to be used to safely access dictionary.
Note that this function would have negative impact on performance.
"""
try:
return func()
except KeyError:
return None
def isvalid_date(date):
try:
dateutil.parser.parse(date)
return True
except ValueError:
return False
def build_time_output_string(appointment_time):
hour, minute = appointment_time.split(':') # no conversion to int in order to have original string form. for eg) 10:00 instead of 10:0
if int(hour) > 12:
return '{}:{} p.m.'.format((int(hour) - 12), minute)
elif int(hour) == 12:
return '12:{} p.m.'.format(minute)
elif int(hour) == 0:
return '12:{} a.m.'.format(minute)
return '{}:{} a.m.'.format(hour, minute)
def make_appointment(intent_request):
"""
Performs dialog management and fulfillment for booking a dentists appointment.
Beyond fulfillment, the implementation for this intent demonstrates the following:
1) Use of elicitSlot in slot validation and re-prompting
2) Use of confirmIntent to support the confirmation of inferred slot values, when confirmation is required
on the bot model and the inferred slot values fully specify the intent.
"""
appointment_type = intent_request['currentIntent']['slots']['AppointmentType']
date = intent_request['currentIntent']['slots']['Date']
appointment_time = intent_request['currentIntent']['slots']['Time']
source = intent_request['invocationSource']
output_session_attributes = intent_request['sessionAttributes'] if intent_request['sessionAttributes'] is not None else {}
booking_map = json.loads(try_ex(lambda: output_session_attributes['bookingMap']) or '{}')
if source == 'DialogCodeHook':
# Perform basic validation on the supplied input slots.
slots = intent_request['currentIntent']['slots']
if not appointment_type:
return elicit_slot(
output_session_attributes,
intent_request['currentIntent']['name'],
intent_request['currentIntent']['slots'],
'AppointmentType',
{'contentType': 'PlainText', 'content': 'What type of appointment would you like to schedule?'},
build_response_card(
'Specify Appointment Type', 'What type of appointment would you like to schedule?',
build_options('AppointmentType', appointment_type, date, None)
)
)
if appointment_type and not date:
return elicit_slot(
output_session_attributes,
intent_request['currentIntent']['name'],
intent_request['currentIntent']['slots'],
'Date',
{'contentType': 'PlainText', 'content': 'When would you like to schedule your {}?'.format(appointment_type)},
build_response_card(
'Specify Date',
'When would you like to schedule your {}?'.format(appointment_type),
build_options('Date', appointment_type, date, None)
)
)
)
message_content = 'What time on {} works for you? '.format(date)
if appointment_time:
output_session_attributes['formattedTime'] = build_time_output_string(appointment_time)
)
available_time_string = build_available_time_string(appointment_type_availabilities)
return elicit_slot(
output_session_attributes,
intent_request['currentIntent']['name'],
slots,
'Time',
{'contentType': 'PlainText', 'content': '{}{}'.format(message_content, available_time_string)},
build_response_card(
'Specify Time',
'What time works best for you?',
build_options('Time', appointment_type, date, booking_map)
)
)
return delegate(output_session_attributes, slots)
duration = get_duration(appointment_type)
""" --- Intents --- """
def dispatch(intent_request):
"""
Called when the user specifies an intent for this bot.
"""
logger.debug('dispatch userId={}, intentName={}'.format(intent_request['userId'], intent_request['currentIntent']['name']))
intent_name = intent_request['currentIntent']['name']
# Dispatch to your bot's intent handlers
if intent_name == 'MakeAppointment':
return make_appointment(intent_request)
raise Exception('Intent with name ' + intent_name + ' not supported')
""" --- Main handler --- """
def lambda_handler(event, context):
"""
Route the incoming request based on intent.
The JSON body of the request is provided in the event slot.
"""
# By default, treat the user request as coming from the America/New_York time zone.
os.environ['TZ'] = 'America/New_York'
time.tzset()
logger.debug('event.bot.name={}'.format(event['bot']['name']))
return dispatch(event)
There is ) at line 171 and line 175 without any ( which must be causing syntax error. many code lines are unreachable because you are coding return before them but those won't cause syntax error.
You can watch the logs on Cloudwatch.
The blueprint which you are using is very complex and not beginner friendly. You really should be using this blueprint for starting. That is my suggestion.
Also, since you are using response_card so please be aware that the response cards won't be shown in the Lex Console window. It will work in Facebook and Slack though.

Telegram bot API - Inline bot getting Error 400 while trying to answer inline query

I have a problem coding a bot in Python that works with the new inline mode.
The bot gets the query, and while trying to answer, it receives error 400.
Here is a sample of data sent by the bot at this time:
{
'inline_query_id': '287878416582808857',
'results': [
{
'type': 'article',
'title': 'Convertion',
'parse_mode': 'Markdown',
'id': '287878416582808857/0',
'message_text': 'blah blah'
}
]
}
I use requests library in to make requests, and here is the line that does it in the code:
requests.post(url = "https://api.telegram.org/bot%s%s" % (telegram_bot_token, "/answerInlineQuery"), data = myData)
With myData holding the data described in the sample.
Can you help me solve this, please?
I suspect it is because you haven't JSON-serialized the results parameter.
import json
results = [{'type': 'article',
'title': 'Convertion',
'parse_mode': 'Markdown',
'id': '287878416582808857/0',
'message_text': 'blah blah'}]
my_data = {
'inline_query_id': '287878416582808857',
'results': json.dumps(results),
}
requests.post(url="https://api.telegram.org/bot%s%s" % (telegram_bot_token, "/answerInlineQuery"),
params=my_data)
Note that I use params to supply the data.
I am getting the correct response after doing some POC. I am using java com.github.pengrad.
Below the code.
GetUpdatesResponse updatesResponse = bot.execute(new GetUpdates());
List updates = updatesResponse.updates();
for(Update update:updates){
InlineQuery inlineQuery = update.inlineQuery();
System.out.println(update);
System.out.println(inlineQuery);
System.out.println("----------------");
if(inlineQuery!=null) {
InlineQueryResult r1 = new InlineQueryResultPhoto("AgADBQADrqcxG5q8tQ0EKSz5JaZjzDWgvzIABL0Neit4ar9MsXYBAAEC", "https://api.telegram.org/file/bot230014106:AAGtWr8xUCqUy8HjSgSFrY3aCs4IZs00Omg/photo/file_1.jpg", "https://api.telegram.org/file/bot230014106:AAGtWr8xUCqUy8HjSgSFrY3aCs4IZs00Omg/photo/file_1.jpg");
BaseResponse baseResponse = bot.execute(new AnswerInlineQuery(inlineQuery.id(), r1)
.cacheTime(6000)
.isPersonal(true)
.nextOffset("offset")
.switchPmParameter("pmParam")
.switchPmText("pmText"));
System.out.println(baseResponse.isOk());
System.out.println(baseResponse.toString());
System.out.println(baseResponse.description());
}
}
Below the console output:
Update{update_id=465103212, message=null, edited_message=null, inline_query=InlineQuery{id='995145139265927135', from=User{id=231700283, first_name='Manabendra', last_name='Maji', username='null'}, location=null, query='hi', offset=''}, chosen_inline_result=null, callback_query=null}
InlineQuery{id='995145139265927135', from=User{id=231700283, first_name='Manabendra', last_name='Maji', username='null'}, location=null, query='hi', offset=''}
true
BaseResponse{ok=true, error_code=0, description='null'}
null
And I am getting proper response in my mobile telegram app also.

How to send multiple messages to mandrill

I have around 1000 unique mails with unique content. I want to bulk send them to mandril i.e. I dont want to make individual network calls for every message I am sending. The following document shows the api. But it does not define what I want to.
https://mandrillapp.com/api/docs/messages.python.html
What I want
mandrill_client = mandrill.Mandrill('YOUR_API_KEY')
messages ={ message1, message2 ....}
result = mandrill_client.messages.send(messages=messages, async=True, ip_pool='Main Pool', send_at='example send_at')
I could not find the above. But this is what I want.
Try this
message = {
#other details
'from_email': 'message.from_email#example.com',
'from_name': 'Example Name',
'to': [{'email': 'recipient.email#example.com',
'name': 'Recipient Name',
'type': 'to'},2nd reciepient,....],
}
result = mandrill_client.messages.send(messages=messages, async=True)

Categories

Resources