How to send json formatted messages to Slack through Cloud functions? - python

I am trying to send a json formatted message to Slack through a Cloud function using slack_sdk, if I send it like this (not formatted) it works.
client = WebClient(token='xoxb-25.......')
try:
response = client.chat_postMessage(channel='#random', text=DICTIONARY)
I found the documentation on Slack that chat_postMessage supports sending json formats by setting the HTTP headers:
Content-type: application/json
Authorization: Bearer xoxb-25xxxxxxx-xxxx
How would that work applied in my code above? I want to send a big python dictionary and would like to receive it formatted in the Slack channel. I tried adding it in multiple ways and deployment fails.
This is the documentation: https://api.slack.com/web

Bit late, but I hope this can help others who stumble upon this issue in the future.
I think that you've misunderstood the documentation. The JSON support allows for accepting POST message bodies in JSON format, as only application/x-www-form-urlencoded format was supported earlier. Read more here.
To answer your question, you can try to send the dictionary by formatting it or in a code block as Slack API supports markdown.
Reference- Slack Text Formatting.
Sample Code-
from slack_sdk import WebClient
import json
client = WebClient(token="xoxb........-")
json_message = {
"title": "Tom Sawyer",
"author": "Twain, Mark",
"year_written": 1862,
"edition": "Random House",
"price": 7.75
}
# format and send as a text block
formatted_text = f"```{json.dumps(json_message, indent = 2)}```"
client.chat_postMessage(channel = "#general", text = formatted_text)
# format and send as a code block
formatted_code_block = json.dumps(json_message, indent = 2)
client.chat_postMessage(channel = "#general", text = formatted_code_block)
Output-

Related

How to forward webhook data from JIRA using Google Cloud Functions?

I want to make a simple middle-man script which receives data from a JIRA webhook and then parses it and sends it over (to Discord, but that's not important).
From the looks of it, Cloud Functions was a perfect match, so I made a short script which just forwards the request json to a message on Discord to see what data it sends.
import requests
import json
def forward(request):
data = request.json
#tried:
#data = request.get_json()
#data = request.data
#data = request.values
url = 'discord webhook receiver url'
myobj = {'content': str(data)}
requests.post(url, data = myobj)
return '', 200
Set up the webhook on the JIRA side and it kinda works, but not really. First of all it doesn't trigger on some events, like adding a comment or editing a task, only for important(?) events, like adding a new task.
And secondly, it doesn't even send the right looking data for it. This is all i'm getting
{'timestamp': 1609851709546, 'webhookEvent': 'issuelink_created', 'issueLink': {'id': 10016, 'sourceIssueId': 10007, 'destinationIssueId': 10022, 'issueLinkType': {'id': 10004, 'name': 'jira_subtask_link', 'outwardName': 'jira_subtask_outward', 'inwardName': 'jira_subtask_inward', 'style': 'jira_subtask', 'isSubTaskLinkType': True, 'isSystemLinkType': True}, 'sequence': 12, 'systemLink': True}}
And I know those 2 things are wrong because while testing it I've also set up another webhook for Pipedream, where it reacts to all changes, and the data contains names of issues, avatars, links. Everything that's needed for what I'm trying to do. And there aren't any differences between those 2 webhook settings, I have them both with all events selected.
So I've been at it for 2 days now with no breakthrough. Maybe I'm misunderstanding how webhooks work, or maybe cloud functions isn't the service to use for this. So while the question is how to do it in cloud functions, I'm also open to alternatives. (not the ones which do the formatting for you, as that's why I started making this in the first place)
Apparently Jira sends 2 requests on webhook trigger and the one containing all the useful info was just over the limit to be put into a Discord message so it never sent it.
That's what I get for using it for logging.
If anyone is also on the same dumbass path, then what I did to find that out is to save all the request data into a hastebin and send the link to it, like so.
#pack it all into a hastebin
everything = str(request.headers) + "\n" + str(request.data) + "\n" + str(request.args) + "\n" + str(request.form) + "\n" + str(request.method) + "\n" + str(request.remote_addr)
req = requests.post('https://hastebin.com/documents', data=everything)
#send the link id to discord
myobj = {'content': req.text}
x = requests.post(url, data = myobj)
All that's left is to parse and format the json.

What is the format for adding a compliance standard to an existing policy with the Prisma Cloud API?

I'm having trouble adding a Compliance Standard to an existing Policy via the Pal Alto Prisma Cloud API.
Everytime I send the request, I'm returned with a 500 Server Error (and, unfortunately, the API documentation is super unhelpful with this). I'm not sure if I'm sending the right information to add a compliance standard as the API documentation doesn't show what info needs to be sent. If I leave out required fields (name, policyType, and severity), I'm returned a 400 error (bad request, which makes sense). But I can't figure out why I keep getting the 500 Server Error.
In essence, my code looks like:
import requests
url = https://api2.redlock.io/policy/{policy_id}
header = {'Content-Type': 'application/json', 'x-redlock-auth': 'token'}
payload = {
'name': 'policy_name',
'policyType': 'policy_type',
'severity': 'policy_severity',
'complianceMetadata': [
{
'standardName': 'standard_name',
'requirementId': 'requirement_ID',
'sectionId': 'section_id'
}
]
}
response = requests.request('PUT', url, json=payload, header=header)
The response should be a 200 with the policy's metadata returned in JSON format with the new compliance standard.
For those using the RedLock API, I managed to figure it out.
Though non-descriptive, 500 errors generally mean the JSON being sent to the server is incorrect. In this case, the payload was incorrect.
The correct JSON for updating a policy's compliance standard is:
req_header = {'Content-Type':'application/json','x-redlock-auth':jwt_token}
# This is a small function to get a policy by ID
policy = get_redlock_policy_by_ID(req_header, 'policy_ID')
new_standard = {
"standardName":"std-name",
"requirementId":"1.1",
"sectionId":"1.1.1",
"customAssigned":true,
"complianceId":"comp-id",
"requirementName":"req-name"
}
policy['complianceMetadata'].append(new_standard)
requests.put('{}/policy/{}'.format(REDLOCK_API_URL, policy['policyId']), json=policy, headers=req_header)

Azure IoTHub DeviceMessage and route filter

I use python and paho.mqtt for sending messages to cloud
I set up endpoint and route. When I set query string to true, everything works fine
messageDict = {}
systemPropertiesDict = {"contentType": "application/json", "contentEncoding": "utf-8", "iothub-message-source": "deviceMessages", "iothub-enqueuedtime": "2017-05-08T18:55:31.8514657Z"}
messageDict = {"systemProperties": systemPropertiesDict}
messageDict["appProperties"] = {}
body = '{id:1}'
messageDict["body"] = body
root = {"message":messageDict}
msg = json.dumps(root, indent=2).encode('utf-8')
print("Message to send", msg)
self.client.publish(topicName, msg)
But if I set the query string to $body.id = 1, then I don't receive any messages.
Any ideas, guys?
The route not working because the content encoding type is not set. All the "systemProperties" in your code actually as message body not system properties. Content encoding type set by this method doesn't take effect.
Add "$.ct=application%2Fjson&$.ce=utf-8" to the topic. Then it will look like this:
devices/{yourDeviceId}/messages/events/$.ct=application%2Fjson&$.ce=utf-8
But to make the route query works on your message you need use this query string: $body.message.body.id = 1
Two edits to make:
First, change body = '{id:1}' to body = {"id":1} to make the id as a string.
Second, change topicName value to this one:
devices/{yourDeviceId}/messages/events/$.ct=application%2Fjson&$.ce=utf-8
If possible, it is suggesting to use Azure IoT SDK for Python to communicate with Azure IoT Hub.
If you are using a third-party library (like paho-mqtt) you have to specify the content type and the encoding of the message.
IoT Hub route messages with content type "application/json" and content encoding: "utf-8" or "utf-16" or "utf-32".
Using MQTT protocol you can set this info with $.ct and $.ce.
topic example:
devices/{MY_DEVICE_ID}/messages/events/%24.ct=application%2fjson&%24.ce=utf-8
URL encoding of
devices/{MY_DEVICE_ID}/messages/events/$.ct=application/json&$.ce=utf-8
Here you could found more info:
https://azure.microsoft.com/it-it/blog/iot-hub-message-routing-now-with-routing-on-message-body/

Blockchain info wallet check payment

i am trying to create bill for payment and send to my customer via telegram bot:
i am using blockchain API V2-https://blockchain.info/api/api receive .my code is:
xpub='***'
keyk='02e57f1***'
url='https://api.blockchain.info/v2/receive?xpub='+str(xpub)+'&callback=https%3A%2F%2Fdoors03.ru&key='+keyk
x=requests.get(url)
r=x.json()
r=r['address']
r -is an adress wich was made.
i am sending it to my costumer(by the way is there any way to send adress with exact sum for pay ) . After i want to check is payment was recieved:
data={ "Content-Type": "text/plain","key":keyk,"addr":r,"callback":"https%3A%2F%2Fdoors03.ru","onNotification":"KEEP", "op":"RECEIVE"}
r = requests.post(url, data=data)
and this is the response - u'{\n "message" : "Internal handlers error"\n}'
what i am doing wrong ? how to check payments ? how to send address with exact sum of btc or ethereum ?
Sorry, i don't have enough reputation to post a comment, so this is
the only option i have. #egorkh have you solved this problem? Maybe
you have received explanation from blockchain.info support? I have
sent them a question about that, but they are answering for too long.
UPDATE: Finally, i have found solution.
In my case, reason of "Internal handlers error" message is in a wrong interpretation of their API.
As they haven't implemented balance_update request in their java-api, i did it on my own and i did it in wrong way.
I have put this parameters:
{"key":keyk,"addr":r,"callback":"https%3A%2F%2Fdoors03.ru","onNotification":"KEEP", "op":"RECEIVE"}
as post parameters, like in other methods they have provided in api. In those methods parameters are URLEncoded like you did with callback link. But...
In this HTML request they must be sent as plain text in json format without any special encoding, like that:
Map<String, String> params = new HashMap<String, String>();
params.put("addr", address);
params.put("callback", callbackUrl);
params.put("key", apiCode);
params.put("onNotification", keepOnNotification? "KEEP" : "DELETE");
params.put("confs", Integer.toString(confirmationCount));
params.put("op", StringUtils.isBlank(operationType) ? "ALL" : operationType);
//parse parameters map to json string(that's optional: you can write it directly as string)
String body = new Gson().toJson(params);
if (requestMethod.equals("POST")) {
byte[] postBytes = body.getBytes("UTF-8");
conn.setDoOutput(true);
conn.setRequestProperty("Content-Type", "text/plain");
conn.setRequestProperty("Content-Length", String.valueOf(postBytes.length));
conn.getOutputStream().write(postBytes);
conn.getOutputStream().close();
}
The main reason of your error may be that you put "Content-Type": "text/plain" in data object (, and maybe encoded callback url) .

Creating POST request in python, need to send data as multipart/form-data?

I'm in the process of writing a very simple Python application for a friend that will query a service and get some data in return. I can manage the GET requests easily enough, but I'm having trouble with the POST requests. Just to get my feet wet, I've only slightly modified their example JSON data, but when I send it, I get an error. Here's the code (with identifying information changed):
import urllib.request
import json
def WebServiceClass(Object):
def __init__(self, user, password, host):
self.user = user
self.password = password
self.host = host
self.url = "https://{}/urldata/".format(self.host)
mgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()
mgr.add_password(None, "https://{}".format(self.host), self.user, self.password)
self.opener = urllib.request.build_opener(urllib.request.HTTPDigestAuthHandler(mgr))
username = "myusername"
password = "mypassword"
service_host = "thisisthehostinfo"
web_service_object = WebServiceClass(username, password, service_host)
user_query = {"searchFields":
{
"First Name": "firstname",
"Last Name": "lastname"
},
"returnFields":["Entity ID","First Name","Last Name"]
}
user_query = json.dumps(user_query)
user_query = user_query.encode("ascii")
the_url = web_service_object.url + "modules/Users/search"
try:
user_data = web_service_object.opener.open(the_url, user_query)
user_data.read()
except urllib.error.HTTPError as e:
print(e.code)
print(e.read())
I got the class data from their API documentation.
As I said, I can do GET requests fine, but this POST request gives me a 500 error with the following text:
Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported
In researching this error, my assumption has become that the above error means I need to submit the data as multipart/form-data. Whether or not that assumption is correct is something I would like to test, but stock Python doesn't appear to have any easy way to create multipart/form-data - there are modules out there, but all of them appear to take a file and convert it to multipart/form-data, whereas I just want to convert this simple JSON data to test.
This leads me to two questions: does it seem as though I'm correct in my assumption that I need multipart/form-data to get this to work correctly? And if so, do I need to put my JSON data into a text file and use one of those modules out there to turn it into multipart, or is there some way to do it without creating a file?
Maybe you want to try the requests lib, You can pass a files param, then requests will send a multipart/form-data POST instead of an application/x-www-form-urlencoded POST. You are not limited to using actual files in that dictionary, however:
import requests
response = requests.post('http://httpbin.org/post', files=dict(foo='bar'))
print response.status_code
If you want to know more about the requests lib, and specially in sending multipart forms take a look at this:
http://docs.python-requests.org/en/master/
and
http://docs.python-requests.org/en/master/user/advanced/?highlight=Multipart-Encoded%20Files

Categories

Resources