formatting message from sns publish to https endpoints - python

I am publishing messages to a sns_topic and am suing boto3.
I am using https endpoint as protocol. The output message received to the endpoint are included with "/". I tried a way to escape that by doing this
def sns_publish(message, sns_event):
try:
topic_arn = get_topic_arn(sns_event)
customer_id = str(message['customer_id'])
message = json.dumps({"default":json.dumps(message)})
sns_client.publish(TopicArn=topic_arn,
Message=message,
MessageStructure='json',
MessageAttributes={
'customer_id': {
'DataType': 'String',
'StringValue': customer_id
}})
except Exception as e:
logging.exception("SNSPublishError: {}".format(e))
output received to https endpoint is below:
"Message": "{\"id\": \"WT3375104\", \"bill_to_nbr_x\": \"7159\", \"file_nbr_x\": \"3375104\"}"
I followed the boto3 documentation and gave Message and MessageStructure attributes as shown above in the code, how can I remove those "/" from JSON output

it's aws feature to present sent data in such format, so to parse it use json module:
import json
mess = {"Message": "{\"id\": \"WT3375104\", \"bill_to_nbr_x\": \"7159\", \"file_nbr_x\": \"3375104\"}"}
print(json.loads(mess['Message']))

Have you tried using raw message delivery? This should result in the message not looking like an SNS message, which means the message doesn't need to be escaped because it's not included in another JSON object.

Related

Is there a way to decode the string returned from AWS lambda to meta's whatsapp business api?

I am trying to setup a webhook in AWS Lambda (using API Gateway) for Meta's WhatsApp Business API. They have the following guidelines:
Whenever your endpoint receives a verification request, it must:
Verify that the hub.verify_token value matches the string you set in the Verify Token field when you configure Webhooks in your App Dashboard (you haven't set up this token string yet). Respond with the hub.challenge value."
I have setup all the query strings it needs in the API gateway. Here is what my lambda handler looks like:
def lambda_handler(event, context):
response = {
"status": 400,
"body" : "failed"
}
print(str(event))
print("Received context" + str(context))
if(len(event) != 0 and (event['hub.verify_token'] == "some value")):
response['status'] = 200
response['body'] = event['hub.challenge']
return event['hub.challenge']
#print(response)
#returnResponse = re.findall('[0-9]+', event['hub.challenge'])
#return returnResponse[0]
else:
return(response)
the event looks like:
{
"hub.mode" : "some value",
"hub.verify_token": "some value",
"hub.challenge": "1158201444"
}
The response in AWS console looks like "1158201444" but on meta's end, the response looks like "\"1158201444\"" and the webhook confirmation fails in Meta's dashboard.
How can remove the extra characters and decode the string? I have already tried regex and still getting the extra characters (\"\").
So what worked for me is was that I passed hub.challenge as a integer format instead of string. I just converted it to an integer before returning it.

Sending request to reCAPTCHA Enterprise API fails

I am trying to create ReCaptcha assessment using their REST API in my backend server.
From reading the documentation, I understand that the request body contains an instance of Assesment, but when I try to send a request, I receive the following error:
TypeError: Object of type Assessment is not JSON serializable
My code:
import requests
from google.cloud import recaptchaenterprise_v1
from google.cloud.recaptchaenterprise_v1 import Assessment
def create_assessment(project_id: str, recaptcha_site_key: str, token: str, recaptcha_action: str, apiKey:str):
# Create event object
event = recaptchaenterprise_v1.Event()
event.site_key = recaptcha_site_key
event.token = token
# Create assesment object
assessment = recaptchaenterprise_v1.Assessment()
assessment.event = event
# Set project name
project_name = "projects/"+project_id
response = requests.post(url="https://recaptchaenterprise.googleapis.com/v1/"+project_name+"/assessments?key="+apiKey, json=assessment)
return response
I tried to convert the assesment to JSON using dumps(), but I had no success.
I've also tried to write it as "skinny JSON" like so:
assessment = {
'event': {
'token': token,
'siteKey': recaptcha_site_key,
'expectedAction': 'LOGIN'
}
}
Even though I receive status code 200, it indicates that my request is MALFORMED, probably because I don't include some recaptchaenterprise_v1 objects that should be on the assesment.
Try to use the CreateAssessmentRequest to create the request instead, like so:
client = recaptchaenterprise_v1.RecaptchaEnterpriseServiceClient()
project_name = "projects/"+project_id
# Build the assessment request.
request = recaptchaenterprise_v1.CreateAssessmentRequest()
request.assessment = assessment
request.parent = project_name
response = client.create_assessment(request)
You can find a more complete code sample in GCP's documentation.

Youtube Python API LiveChatMessages insert ERROR_UNSPECIFIED

I'm working on writing a python script that utilizes the Youtube Live API. I can read messages using the liveChatMessages().list() method, but am getting a strange error about an invalid argument when I attempt to create a message with liveChatMessages().insert().
The below is the source code responsible for sending messages:
def send_message(self, message):
body = {
'snippet': {
'liveChatId': self.stream_id,
'type': 'textMessageEvent',
'textMessageDetails': {
'messageText': message
}
}
}
self.youtube.liveChatMessages().insert(part='snippet', body=body).execute()
The following is the errror that I'm getting
googleapiclient.errors.HttpError: <HttpError 400 when requesting https://youtube.googleapis.com/youtube/v3/liveChat/messages?part=snippet&alt=json returned "Request contains an invalid argument.". Details: "[{'domain': 'youtube.api.v3.LiveChatMessageInsertResponse.Error', 'reason': 'ERROR_UNSPECIFIED'}]">
I have been following the API documentation found at https://developers.google.com/youtube/v3/live/docs/liveChatMessages/insert and https://developers.google.com/resources/api-libraries/documentation/youtube/v3/python/latest/youtube_v3.liveChatMessages.html#insert
I've had this same problem with Dart instead of Python:
await youTubeApi!.liveChatMessages.insert(
LiveChatMessage(
snippet: LiveChatMessageSnippet(
liveChatId: chatId,
type: "textMessageEvent",
textMessageDetails: LiveChatTextMessageDetails(messageText: message)))
Resulting in the "400 Request contains an invalid argument" error.
The solution was simple: I forgot to activate the YouTube channel of the account. Check whether you can write into the chat manually.

HTTPERROR 400 Removing a message label gmail api python

I'm using this slice of code to try to remove the label "INBOX" from a message, but i'm getting error "no label to remove or specify"
message = service.users().messages().modify(userId='me', id=id, body='INBOX').execute();
I think your body is wrong the body is a json object probably something like this
msg_labels = {'removeLabelIds': ['INBOX'], 'addLabelIds': []}
message = service.users().messages().modify(userId=user_id, id=msg_id,
body=msg_labels).execute()
You might want to check the documented example my python is very basic messages.modify python

Amazon SNS with Python

Trying to get started with Amazon SNS. API is very simple REST. I seem to be hung up on the signature part of the call. The API example is:
http://sns.us-east-1.amazonaws.com/
?Subject=My%20first%20message
&TopicArn=arn%3Aaws%3Asns%3Aus-east-1%3A698519295917%3AMy-Topic
&Message=Hello%20world%21
&Action=Publish
&SignatureVersion=2
&SignatureMethod=HmacSHA256
&Timestamp=2010-03-31T12%3A00%3A00.000Z
&AWSAccessKeyId=AKIAJHS4T6XPF7XIURNA
&Signature=9GZysQ4Jpnz%2BHklqM7VFTvEcjR2LIUtn6jW47054xxE%3D
I've been following the API docs for signatures, so I'm trying:
from time import strftime,gmtime,time
import urllib2
import hmac
import hashlib
import base64
import string
def publichSNSMsg(Subject,TopicArn,Message,AWSAccessKeyId,privatekey):
#http://docs.amazonwebservices.com/AWSSimpleQueueService/2008-01-01/SQSDeveloperGuide/
amzsnshost = 'sns.us-east-1.amazonaws.com'
values = {'Subject' : Subject,
'TopicArn' : TopicArn,
'Message' :Message,
'Timestamp' : strftime("%Y-%m-%dT%H:%M:%S.000Z", gmtime(time())),
'AWSAccessKeyId' : AWSAccessKeyId,
'Action' : 'Publish',
'SignatureVersion' : '2',
'SignatureMethod' : 'HmacSHA256',
}
amazquote=lambda v: urllib2.quote(v).replace('%7E','~')
cannqs=string.join(["%s=%s"%(amazquote(key),amazquote(values[key])) for key in sorted(values.keys(),key=str.lower)],'&')
string_to_sign=string.join(["GET",amzsnshost,"/",cannqs],'\n')
sig=base64.encodestring(hmac.new(privatekey,string_to_sign,hashlib.sha1).digest())
querystring = "%s&Signature=%s"%(cannqs,amazquote(sig))
url="http://%s/?%s"%(amzsnshost,querystring)
try:
return urllib2.urlopen(url).read()
except urllib2.HTTPError, exception:
return "Error %s (%s):\n%s"%(exception.code,exception.msg,exception.read())
And getting back:
<ErrorResponse xmlns="http://sns.amazonaws.com/doc/2010-03-31/">
<Error>
<Type>Sender</Type>
<Code>SignatureDoesNotMatch</Code>
<Message>The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.</Message>
</Error>
<RequestId>8d6e5a41-dafb-11df-ac33-f981dc4e6c50</RequestId>
</ErrorResponse>
Any ideas?
Aw, it was simple!
Keys in the query string were supposed to be byte-order sorted, not case-insensitive sorted (that was for version 1 signatures).
Slightly updated (and now correct) code is available on gist.
I found this example so useful that I rewrote it in C#. Since AWS does not have a WP7 library for SNS, perhaps this will be of help to someone: https://gist.github.com/2705156
I would suggest you to use boto3 for SNS. The documentation can be found at http://boto3.readthedocs.io/en/latest/reference/services/sns.html. The following code snippet can be used for fetching signature as JSON.
import boto3
from django.views.decorators.csrf import csrf_exempt
topic_arn = <your topic>
client = boto3.client('sns',region_name="us-west-2")
#Call this to publish
def sns_publish(arg1,arg2):
response = client.publish(
TopicArn=topic_arn,
Message=arg2,
Subject=arg2
)
#Function to subscribe to topic
#csrf_exempt
def sns_parse(request):
print request.body.decode('utf-8')
if request.method == "POST":
response = json.loads(request.body.decode('utf-8'))
type = response.get('Type')
if type == 'Subscription':
print(type)
return("Subscription URL: "+<Url obtained>)
elif type == 'Notification':
return HttpResponse(type.get('Signature'))
else:
return HttpResponse('Not a POST object')
This is just a template code though, but yeah, boto3 is indeed helpful.

Categories