Push data to Campaign Monitor using Python - 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)

Related

How can I have only one api value?

everyone
I started programming in python yesterday to create a project. This consists of taking data from an API using the "Requests" library
So far I had no trouble getting familiar with the library, but I can't get results for what I'm specifically looking for.
My idea is just to get the name of the account.
Here the code
import requests
user = 'example'
payload = {'data': 'username'}
r = requests.get('https://api.imvu.com/user/user-'+user, params=payload)
json = r.json()
print(json)
My idea is that, within all the data that can be obtained, only obtain the name of the account. just the name
The code works perfectly, but it throws me all the account data.
For example:
{
"https://api.imvu.com/user/user-x?data=created": {
"data": {
"created": "2020-11-30T17:56:31Z",
"registered": "x",
"gender": "f",
"display_name": "‏‏‎ ‎",
"age": "None",
"country": "None",
"state": "None",
"avatar_image": "x",
"avatar_portrait_image": "https://......",
"is_vip": false,
"is_ap": true,
"is_creator": false,
"is_adult": true,
"is_ageverified": true,
"is_staff": false,
"is_greeter": false,
"greeter_score": 0,
"badge_level": 0,
"username": "=== ONLY THIS I NEED ==="
}
}
}
As you can see, I only need one thing from all that data.
Sorry for bothering and I hope I can learn from your answers. Thanks so much for reading
Unless API allows you to specify exactly what data to return (some does) then you got no control about the API behavior nor what data (and how) given endpoint returns. Publicly exposed API is all you can have in hand and sometimes you may get tons of useless data and there's basically nothing you can do about that.
To get specific item from json, you can simply make few changes in your code.
r = requests.get('https://api.imvu.com/user/user-'+user, params=payload)
json = r.json()
username = json["https://api.imvu.com/user/user-x?data=created"]["data"]["username"]
print(username)
you might check whether there is an alternative REST method that only provides you with the username.
The REST response you cannot modify as it is sent from the server, so you need to parse the response e.g. like here
Extract value from json response python?
python

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:

Message Attachments missing when posting message to Slack App Home channel

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.

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.
:)

Syncano v4 Error: "You do not have permission to perform this action"

Using the Syncano v4 Python Library, I attempted to do the following:
book_class = instance.classes.create(
name='book',
schema='[{"name": "title", "type": "string"}, {"name": "author", "type": "string"}]’
)
And received this error:
syncano.exceptions.SyncanoRequestError: 403 You do not have permission to perform this action.
I'm currently using the instance API key - what am I doing wrong?
403 in the response usually means you are trying to access an endpoint with either non-existing key or wrong type of key.
In this case - you cannot create classes using instance api key - using your account key is necessary. If you don't have it, you can always check it in the dashboard, or just use https://api.syncano.io/v1/account/auth/ endpoint to log in (or use api explorer: http://docs.syncano.com/v0.1/docs/account-log-in, account key will be in the response, once you pass your credentials).
Once you have your account key, you should use it to connect to your syncano instance:
import syncano
from syncano.models.base import Class
connection = syncano.connect(api_key="ACCOUNT_KEY")
book_class = Class.please.create(
instance_name='INSTANCE_NAME',
name='books',
schema=[
{"name": "title", "type": "string"},
{"name": "author", "type": "string"}
])
If account key and instance name are correct this code should work fine.
You have to use the account key to create new classes. You can also use the Syncano GUI to make them. More info is on that here. Hope that helps

Categories

Resources