Message Attachments missing when posting message to Slack App Home channel - python

I've built a Workspace App for Slack, which now comes with a channel (under the Apps header), where a user can send messages to the app itself. This triggers a
message.app_home event, that my backend receives. I want to respond to that message, using chat.postMessage, but only the message text appears in the response. None of the attachments I send along appear in the channel. Returning this structure as part of a JSON response to a Slash Command request works correctly.
Here are the attachments structure I sending along:
(
{
"title": "Create a space, optionally setting its name and adding other users",
"text": "`/luffa create [space name] [teammates]`\nExample: `/luffa create Marketing Campaign 2018 #john #kate`",
"color": SLACK_COLOR,
},
{
"title": "Start a new meeting, optionally strating it in the space matching the provided name",
"text": "`/luffa start [space name]`\nExample: `/luffa start Marketing Campaign 2018`",
"color": SLACK_COLOR,
},
{
"title": "Search Luffa",
"text": "`/luffa search [query]`\nExample: `/luffa search interviews before:Yesterday `",
"color": SLACK_COLOR,
},
{
"text": "There is more help available in our Help Center: https://help.okluffa.com/",
},
)
I am using the slackclient Python library to wrap my calls to the Slack API.
There is no error message returned and the structure seems to be correct based on the documentation. Is there something missing there?

Something small to check - try removing the extra commas on each last value in your attachments structure, as those are causing validation errors when plugged into the Slack message tester here:

The issue turned out that the data structure I was passing to slackclient 1.2.1 was a tuple of objects. The library will only serialize as JSON list or dict objects. (See slackrequest.py, line 94, if isinstance(v, (list, dict)):). Passing a tuple, or any other iterable for that matter, will not be serialized correctly and the Slack API will disregard the attachments. That was not an issue with a JSON response to a request, since Python's JSON serializer converts all iterables to a JSON array.
I solved the issue by passing in a list to the slackclient method.

Related

Amazon Seller Central SP API ERROR - 'code': 'InvalidInput', 'message': 'Invalid request parameters', 'details': ''

Updating inventory in the seller central, using their API, suddenly stopped working for Japan and Australia.
I was told by the account holder that Amazon's response to this problem was to just look at the documentation which doesn't help at all since the documentation hasn't changed. The request body that is failing is ...
{
"feedType": "POST_FLAT_FILE_INVLOADER_DATA",
"inputFeedDocumentId": "[actual document id returned by AWS when document was uploaded]",
"path": "/feeds/2021-06-30/feeds",
"marketplaceIds": ["A39IBJ37TRP1C6"],
"MarketplaceIds": ["A39IBJ37TRP1C6"]
}
After editing the python-amazon-sp-api library so the request would match the documentation exactly I sent the following request.
{
"feedType": "POST_FLAT_FILE_INVLOADER_DATA",
"inputFeedDocumentId": "[actual document id returned by AWS when document was uploaded]",
"marketplaceIds": ["A39IBJ37TRP1C6"]}'
}
The response document for both requests is
"errors": [
{
"code": "InvalidInput",
"message": "Invalid request parameters",
"details": ""
}
]
}
This response is pretty useless since the details are empty.
The documentation does say to send the file with content type text/tab-separated-values; charset=iso-8859-1 but when I did that they return an internal error, try again. This problem doesn't happen when I send content type text/tsv. Feeds for other countries are still working with this code, but this isn't working with Japan or Australia and Amazon support on this issue is useless! Is there any work-around to get this feed to be accepted by Amazon?

Push data to Campaign Monitor using Python

Campaign Monitor is a service where we can send emails to a set of subscribers. We can create multiple lists within Campaign Monitor and add the required users to these lists as subscribers(to whom we can send personalised emails). So, here I am trying to send a set of customers' details like their name, emails, total_bookings, and first_booking to the campaign monitor's list using the API in Python so that I can send emails to this set of users.
More details on campaign monitor: https://www.campaignmonitor.com/api/v3-3/subscribers/
I am new to using Campaign Monitor. I have searched documentation, a lot of posts and blogs for examples on how to push data with multiple custom fields to Campaign Monitor using Python. By default, a list in Campaign Monitor will have a name and an email that can be added, but I want to add other details for each subscriber(here I want to add total_bookings and first_booking data) and Campaign Monitor provides custom fields to achieve this.
For instance:
I have my data stored in a redshift table named customer_details with the fields name, email, total_bookings, first_booking. I was able to retrieve this data from redshift table using Python with the following code.
# Get the data from the above table:
cursor = connection.cursor()
cursor.execute("select * from customer_details")
creator_details = cursor.fetchall()
# Now I have the data as a list of sets in creator_details
Now I want to push this data to a list in the Campaign Monitor using API like request.put('https://api.createsend.com/api/../.../..'). But I am not sure on how to do this. Can someone please help me here.
400 indicated invalid parameters
we can first see the request is POST not PUT
so first change requests.put to requests.post
the next thing is that all the variables need to be sent either as www-formdata or as json body data not sure which
and lastly you almost certainly cannot verify with basic auth ... but maybe
something like the following
some_variables = some_values
...
header = {"Authorization": f"Bearer {MY_API_KEY}"}
data = {"email":customer_email,"CustomFields":[{"key":"total_bookings","value":customer_details2}]}
url = f'https://api.createsend.com/api/v3.3/subscribers/{my_list_id}.json'
res = requests.post(url,json=data,headers=header)
print(res.status_code)
try:
print(res.json())
except:
print(res.content)
after looking more into the API docs it looks like this is the expected request
{
"EmailAddress": "subscriber#example.com",
"Name": "New Subscriber",
"MobileNumber": "+5012398752",
"CustomFields": [
{
"Key": "website",
"Value": "http://example.com"
},
{
"Key": "interests",
"Value": "magic"
},
{
"Key": "interests",
"Value": "romantic walks"
}
],
"Resubscribe": true,
"RestartSubscriptionBasedAutoresponders": true,
"ConsentToTrack":"Yes"
}
which we can see has "EmailAddress" not "email" so you would need to do
data = {"EmailAddress":customer_email,"CustomFields":[{"key":"total_bookings","value":customer_details2}]}
Im not sure if all of the fields are required or not ... so you may also need to provide "Name","MobileNumber",Resubscribe",etc
and looking at "Getting Started" it looks like the publish a python package to make interfacing simpler
http://campaignmonitor.github.io/createsend-python/
which makes it as easy as
import createsend
cli = createsend.CreateSend({"api_key":MY_API_KEY})
cli.subscriber.add(list_id,"user#email.com","John Doe",custom_fields,True,"No")
(which I found here https://github.com/campaignmonitor/createsend-python/blob/master/test/test_subscriber.py#L70)

Creating a Pull Request in Azure Devops (using REST API) doesn't link work items

I'm trying to automate some post-release processes for creating Pull Requests (release branch -> master) after a release. While I'm able to automate the PR creation, and it links the commits, it does not link the work items.
Note: I'm using Python for this, using the (officially supported) azure-devops module from PyPi (https://pypi.org/project/azure-devops/). It is a thin wrapper around the REST API, and I've read the REST API documentation itself to see if there are any other options (haven't found any so far). Here's my code:
def create_pull_request(self, repo_id, source_branch, target_branch, title, description):
pull_request = {
"title": title,
"description": description,
"sourceRefName": "refs/heads/" + source_branch,
"targetRefName": "refs/heads/" + target_branch,
}
response = self._git_client.create_pull_request(pull_request, repository_id=repo_id)
Here's my function for connection to the git client:
def __init__(self, personal_access_token=None, organization_url=None):
# Create a connection to the org
credentials = BasicAuthentication('', personal_access_token)
self._connection = azure.devops.connection.Connection(base_url=organization_url,
creds=credentials)
# Get a client (the "core" client provides access to projects, teams, etc)
self._git_client = self._connection.clients.get_git_client()
I've also tried pulling the individual commits to see if I can find the work items associated with them and attached them to the pull request after creation, but those responses are coming back with the work items empty.
Is there some other way I can accomplish this?
A couple of ideas to get your work items linked:
First, your pull_request should probably include:
pull_request = {
"title": title,
"description": description,
"sourceRefName": "refs/heads/" + source_branch,
"targetRefName": "refs/heads/" + target_branch,
"workItemRefs": # collection of work item refs
}
workItemRefs is documented in the REST API docs at https://learn.microsoft.com/en-us/rest/api/azure/devops/git/pull%20requests/create?view=azure-devops-rest-6.0 . What you need to put in there is probably a matter of some experimentation.
Second, as an alternative, your commits could be created in the form:
git commit -m "My commit message #workitemid1 #workitemid2, etc."
Then, when the PR is created, it will automatically link those work items in the commits it finds in the PR.
We cannot add work item link via the Pull Request Create API and Pull Request Update API. I found a feature request, you could follow the ticket to get the latest news.
As a work item, we could link work item to pull request via this REST API Work Items - Update
Steps:
Get pull request field artifactId via below API:
GET https://dev.azure.com/{organization}/{project}/_apis/git/repositories/{repositoryId}/pullrequests/{pullRequestId}?api-version=6.0
Link work item to Pull Request:
Request URL:
PATCH https://dev.azure.com/{organization}/{project}/_apis/wit/workitems/{work item ID}?api-version=5.1
Request Body:
[ {
"op": "add",
"path": "/relations/-",
"value": {
"rel": "ArtifactLink",
"url": "{This url is artifactId}",
"attributes": {
"name": "pull request"
}
}
} ]
Result:
Update1
Is there somewhere that I could find the work items associated with the commits
We could list the work items associated via the commit ID.
Request URL:
POST https://dev.azure.com/{Org name}/_apis/wit/artifactUriQuery?api-version=5.0-preview
Request Body:
{
"artifactUris": [
"vstfs:///Git/Commit/{Project ID}%2F{Repo ID}%2F{Commit ID}"
]
}
Result:

How to build Python Lambda for Alexa skill with sequence of statements?

I am building Alexa skill for my application. When your ask's 'what is my account status?' this intent return sequence of statements related to user's account. API gives following response
response = [{
..
text: 'Total orders are 41, Delivered 28'
..
},
{
..
text: 'Today orders are 12, Delivered 2'
..
},
{}]
How to build response sequence based on API response?
With this intent, I get the response from API with set statements Alexa should prompt each statement one by one. If the user said 'next' in between any of the statement while Alexa prompting then it goes to next statement in the response array.
First when user says "what is my account status?" your intent will be called and you will get response in a list where in the first call you will display 0th item.
API Result:
response = [{
..
text: 'Total orders are 41, Delivered 28'
..
},
{
..
text: 'Today orders are 12, Delivered 2'
..
},
{}]
You need to store information in Session attributes, like intent name, index which you displayed (0 in case of first call) etc.
Now you need to setup one more intent which will be triggered on keywords like next. In the code you will check values of session attributes and make your response according to the values. For example you would want to check previous intent name, previous index. If all is fine you will modify the session attributes and respond to user.
Hope it helps.
Since you mentioned Python, I would suggest to take a look at Flask-ask, which provides you with two main responses type: statement and question.
As sid8491 mentioned, you will need to store info in sessions to keep track of which response (from json) needs to be returned. You can use redis for this purpose, using this python library.
Assuming the json response is stored in db (or somewhere), and can be accessed in a list, let's say your interaction model looks something like this:
{
"languageModel": {
"intents": [
{
"name": "NextIntent",
"samples": ["next", "tell me more"]
},
{
"name": "StopIntent",
"samples": ["stop"]
},
{
"name": "StatusIntent",
"samples": ["what is my account status"]
}
],
"invocationName": "orders"
}
}
You can use following steps (using redis and flask-ask for this example):
on 'StatusIntent', store session and return first response:
redis.set("session_key", 0)
return statement(response[0]) # assuming responses are stored in a list
on 'NextIntent', get value stored in session, if present return next response
value = redis.get("session_key")
if not value: # session is expired
return statement("I don't understand")
redis.set("session_key", int(value)+1)
return statement(response[int(value)+1])
on 'StopIntent', remove "session_key" from redis
redis.delete("session_key")
return statement("Ok. I am here if you need me.")
It's not the actual code but simply intended to give you an idea. Hope it helps.
:)

400 Error while trying to POST to JIRA issue

I am trying to set the 'transition' property in a JIRA issue from whatever it is, to completed(which according to the doc is 10000). According to the documentation, this error is 'If there is no transition specified.'
Also I have used ?expand=transitions.fields to verify that 10000 is for complete.
using these docs
https://docs.atlassian.com/jira/REST/latest/#api/2/issue-doTransition
https://jira.atlassian.com/plugins/servlet/restbrowser#/resource/api-2-issue-issueidorkey-transitions/POST
Here is my request
url = 'http://MYURL/rest/api/2/issue/ISSUE-ID/transitions'
payload1 = open('data3.json', 'r').read()
payload = json.loads(payload1)
textFile = requests.post(url, auth=('username', 'password'), json=payload)
The contents on my data3.json file are
{
"transition": 10000
}
edit: I also changed my JSON to this and I get a 500 error
{
"transition": {
"id": "10000"
}
}
The error I get
{"errorMessages":["Can not instantiate value of type [simple type,classcom.atlassian.jira.rest.v2.issue.TransitionBean] from JSON integral number;no single-int-arg constructor/factory method (through reference chain:com.atlassian.jira.rest.v2.issue.IssueUpdateBean[\"transition\"])"]}400
I'm pretty confident that my issue is in my json file since I have used GET in the code above this snippit multiple times, but I could be wrong.
Possible cause - https://jira.atlassian.com/browse/JRA-32132
I believe the issue I was having was a process flow one. I cannot jump right from my issue being opened, to 'completed'. However, I can go from the issue being created to 'Done'.
{
"transition": {
"name": "Done",
"id": "151"
}
}
As this does what I need, I will use it. If I find how to make ticket complete I will post back.
Also, I think the fact we customize our JIRA lead to my getting 'Completed' as a valid transition even though it wasn't.
Yes, you're right that the JSON is wrong, it's not even a valid json since the value is not a number, string, object, or array. The doc says:
The fields that can be set on transtion, in either the fields
parameter or the update parameter can be determined using the
/rest/api/2/issue/{issueIdOrKey}/transitions?expand=transitions.fields
resource.
So you need to do a get request on /rest/api/2/issue/{issueIdOrKey}/transitions?expand=transitions.fields to get the list of possible values and then set that in the json
{
"transition": {
"id" : "an_id_from_response"
}
}

Categories

Resources