How to get event subject and content from Microsoft Graph API? - python

I'm sending a GET request to /users/{id}/calendar/calendarView?startDateTime={start_datetime}&endDateTime={end_datetime} in order to get events of a user and after that I'm filtering the event subject and content.
What happens is that in the majority of times the subject in the JSON response is just the name of the event organizer and the content is just a blank HTML instead of the values that can be seen in the calendar normally.
I tried finding another fields in the JSON that could provide the correct information but there aren't any.
It looks like some people also had the same problem (here and here), but no solution was found or the one given is not what I need.
The following code is what I'm using:
graph_client = OAuth2Session(token=token)
headers = {
'Prefer' : 'outlook.timezone="America/Manaus"'
}
response = graph_client.get(f'{self.graph_url}/users/{room}/calendar/calendarView?startDateTime={start_datetime}&endDateTime={end_datetime}',
headers=headers)
print(response.json()['value'])

Related

Spotipy - 401 token error "no token proviced" with .search function

I have a list of dictionaries that contain album information which I'm trying to use to search within Spotify and then add to users' saved albums. I tried following the examples given in the spotipy documentation, however, I'm getting an issue when using the search function via spotipy.
SCOPE = 'user-library-modify'
sp = spotipy.Spotify(auth_manager=SpotifyOAuth(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI, scope=SCOPE))
for album in newMusic:
albumName = album["Title"]
artistName = f"{album['Last Name']}+{album[' First Name']}"
getRecord = sp.search(q = f"artist:{artistName}&album:{albumName}", type='album')
print(getRecord)
I provided the redirect url when prompted after running, but this results in a 401 response for each album result as such:
{
"error": {
"status": 401,
"message": "No token provided"
}
}
I have the .cache file with the access and refresh tokens but it still says no token is provided. I thought maybe I was entering the query incorrectly, but I don't see anything wrong. This is how an example end url looks:
https://api.spotify.com/v1/search?query=artist:band+name&album:album+name&type=album&offset=0&limit=10
What am I doing wrong here? How can I get my access code recognized?
Found the issue; the query entry format was wrong. I found this answer to a past question that explains my problem: Using python to get a track from the spotify API by using search Endpoint
The artist, album, etc. do not need to be declared separately (e.g. "artist: _", "album: _"). They should just be combined together like:
https://api.spotify.com/v1/search?query=first+name+last+name+album+title&type=album&offset=0&limit=10
Weirdly, this contradicts what is in the Spotify API documentation where an example query value is given as such:
Example value:
"remaster%20track:Doxy+artist:Miles%20Davis"
https://developer.spotify.com/documentation/web-api/reference/#/operations/search

Reading a single user entry from REST GET if one can only GET a full user list

I use software that only lets me fetch information on all users, while my project requires me to get only one specific user. I only need his ID and I'm going to find it out by his e-mail (because it's unique).
The program creates an user (via POST) and stores his data (like email) in variables, then reads a provided list of devices that will be assigned to said user. To do this, the program has to:
Fetch all users (why software author didn't allow to fetch a single user is beyond me)
Filter users so it finds my newly created user <- here's my issue
Fetch all devices...
Filter devices...
Finally create a permission relationship between found user and device IDs
This is what I came up with so far:
inputText = self.imeiInput.GetValue().splitlines() # reads input and creates a list
url = "https://example.com/api/users/"
userList = requests.get(url, auth=(login, password)).content
foundUser = re.findall(givenMail, str(userList)) # givenMail provided by function argument
print(userList)
print(foundUser) # prints only searched mail
for imei in inputText:
self.TrackerAssign(imei, foundUser) # do your stuff
But it only confirms that there indeed is my email in the userbase, there's no other info (like ID I'm interested in). Here's a sample userList output (except that originally it's all in one line):
b'[{
"id":1,
"attributes": {
...
},
"name":"username",
"login":"",
"email":"test#example.com",
"phone":"999999999",...
},
{
"id":2,
"attributes": {
...
},
"name":"username2",
"login":"",
"email":"test2#exmaple.com",
"phone":"888888888",...
},
...]'
Then there's also a question how to only read the desired ID. Sorry if this is confusing, I barely know what I'm doing myself.
From your example it seems like you get a JSON response from the endpoint. This is great, because this JSON can be parsed to a list/dictionary!
Your approach can look something like this. In broad terms, this is a possible strategy:
Get all users from the users endpoint.
Parse the response JSON to a list of dictionaries.
Loop over all users, breaking the loop when you find your user.
Do something with the ID of the user that you found in your search.
response = requests.get(url, auth=(login, password)) # receive a Response instance
user_list = response.json() # parse the body to a dictionary
for user in user_list:
# Compare the email of this user with the target, using get to catch users with no email specified.
if user.get("email") == given_mail:
desired_user = user
break # if we find the correct user, we exit the loop
else:
# If we never find the desired user, we raise an exception.
raise ValueError("There is no user with email %s", given_email")
print(f"The ID of the user I am looking for is {desired_user["id"]}.")

Google DialogFlow: Usage of Session Entity

I am very newbie with the Google DialogFlow, As I am exploring with the Api.ai. I got to know about the userEntity(V1) or SessionEntity(V2).
I have created the session entity using fulfilment with the below code:
import requests
REQUIRED_SCOPES = 'https://www.googleapis.com/auth/dialogflow'
access_token = generate_access_token()
url = 'https://dialogflow.googleapis.com/v2/'+ session_id +'/entityTypes'
headers = {'Authorization': 'Bearer '+ access_token,'Content-Type': 'application/json'}
entity_data = json.dumps({"entityOverrideMode": "ENTITY_OVERRIDE_MODE_OVERRIDE", "entities": [{"synonyms":["sugarcane", "sugar"],"value": "sweet"}], "value": str(session_id)+'fruit'})
response = requests.post(url,headers=headers,data=entity_data)
It creates the sessionEntity with success and also able to list the entity from the session.
It's working while I tried from the same page of console with TryMe-Intents.
But while I tried using simulator or mobile to pass some phrases for my Intent I am not getting the newly created entity to map with the matching phrases.
For Example, I want Sugarcane, at this point, I suppose to get sugarcane as mapped with the entity with the current session for followup intents.
But it was not happening, don't know if I am missing anything. Let me know if anything is wrong or missing.
Suggestions are always welcome.
Reference Links which I have referred to achieve:
https://cloud.google.com/dialogflow-enterprise/docs/reference/rest/v2/projects.agent.sessions.entityTypes/create
https://cloud.google.com/dialogflow-enterprise/docs/entities-session

Calendar info using confluence API

I have a Confluence page which has a Calendar inside it (please check photo below).
Calendar
I am trying to pull information from this calendar, like how many events in each day. nothing more.
i used a code from stackoverflow that reads Confluence page using API. but the json response does not contain any data about the calendar inside the page.
`import requests
import json
from requests.auth import HTTPDigestAuth
confluence_host = "https://confluence.tools.mycompany.com"
url = confluence_host + '/rest/api/content/'
page_id = "36013799"
page = requests.get(url=url + page_id,
params={'expand': 'body.storage'},
auth=('my_user', 'my_password') ).json()`
Even if i write, html = page['body']['storage']['value'] and check its output, it only gives this:
name="calendar" ac:schema-version="1" ac:macro-id="99a26d73-abaa-45a1-92cc-0edafec567f5">72da4ae5-4888-46dd-9078-0299b51ab815,743a55b4-7b3b-4e00-b102-90d95916de8d
Is there any way to get the calendar info ?
Thanks
You are using Team Calendar in your page and Team Calendar is a plugin in your page. Technically, /rest/api/content only gives you the content of the page not the Content of the Plugins. As far as I know, Team Calendar doesn't have Public Rest API as you can see on CONFSERVER-51323 but you can get the data that you want from the database instead of REST API since Team Calendar has already creates couple of AO Tables in your database.
I found it easiest to get the subscribe link to the calendar then use an iCalendar library to parse the data. Make sure the subscribe button gives you a link with a {guid}.ics and not undefined.ics - To solve that I had to go to the calendars link in the main confluence space and then select it from the dropdown. You may have to create an empty calendar so you can select a cal.
I was able by looking at the GET and PUT, there is a rest API used by the javascript plugin (rest/calendar-services/1.0/calendar/events.json):
you need to find out your: subCalendarId='yourID'
urlC = 'https://yourconfluence.com/rest/calendar-services/1.0/calendar/events.json?subCalendarId=40xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx&userTimeZoneId=America%2FMexico_City&start=2018-11-28T00%3A00%3A00Z&end=2018-11-28T00%3A00%3A00Z'
r = requests.get(urlC, auth=("myuser", "mypass"), timeout=15)
that will return all the records on that period:
a = r.json()
a.keys()
[u'events', u'success']
a['success']
True
type(a['events'])
list
len(a['events'])
61
Use the following data in a PUT to add new events:
data = {
"subCalendarId": "xxx-xxx-xxx",
"eventType": "custom",
"customEventTypeId": "xxx-xxx-xxx",
"what": "My Test",
"person": "xxxxxxxxxxxxxxxxx",
"startDate": "28-Nov-2018",
"startTime": "15:00",
"endDate": "28-Nov-2018",
"endTime": "16:00",
"allDayEvent": "false",
"editAllInRecurrenceSeries": "true",
"where": "Some Place",
"description": "My testing Case",
"userTimeZoneId": "America/Mexico_City",}
urlC = 'https://yourconfluence.com/rest/calendar-services/1.0/calendar/events.json'
r = requests.put(urlC, auth=('username', 'pass'), data=data, timeout=15)
that will return a 'success': true with the new entry:
u'{"success":true,"subCalendar":{"reminderMe":false,........}}
After going through the developer console in chrome, After analyzing the format of the payload and required authentication details I found solution for this,
My problem statement was little different I have to add the event to confluence calendar, Both adding event and extracting event will follow the same process.
There are few cookies which are required for authentication like JSESSIONID and seraphConfluence Which will be stored in the application -> cookies in chrome developer tool.
and also we require the subCalenderid and Id Type which can be taken from the application-> local storage in in chrome developer tool.
and also , The confluence will send request using 'application/x-www-form-urlencoded' as Content-Type, So in the data we should have it in encoded format,
For this we can use below code to convert to that format
import urllib
urllib.parse.quote_plus('May 4, 2022')
output:
'May+4%2C+2022'
And also date and type should be in the MMM D, YYYY and h:MM A format you can use arrow python package to do the work
arrow.utcnow.format(MMM D, YYYY)
output
May 4, 2022
Below there is a string from the request payload in chrome when it send put request when we click add event , if we analyse the string we can see that we have
confirmRemoveInvalidUsers=false&childSubCalendarId=&customEventTypeId=asdfghjk-asdf-asdf-asfg-sdfghjssdfgh&eventType=custom&isSingleJiraDate=false&originalSubCalendarId=&originalStartDate=&originalEventType=&originalCustomEventTypeId=&recurrenceId=&subCalendarId=asdfghjk-asdf-asdf-asdg-asdfghjkl&uid=&what=test&startDate=May+4%2C+2022&startTime=&endDate=May+4%2C+2022&endTime=&allDayEvent=true&rruleStr=&until=&editAllInRecurrenceSeries=true&where=&url=&description=&userTimeZoneId=America%2FNew_York
After analysing it we can come to conclution we have to replace start date,enddate , start and end time, what , where , subcalendar id and type and other fields with our code and send the request.
Below is the code which will do that
def addEventtoCalender():
reqUrl = 'https://confluence.yourdomain.com/rest/calendar-services/1.0/calendar/events.json'
authDetails = getConfluenceAuthenticationDetails()
what=urllib.parse.quote_plus('WHAT field data')
startDate = urllib.parse.quote_plus(arrow.utcnow().format('MMM D, YYYY'))
startTime=urllib.parse.quote_plus(arrow.utcnow().format('h:MM A'))
endDate=urllib.parse.quote_plus(arrow.utcnow().format('MMM D, YYYY'))
endTime=urllib.parse.quote_plus(arrow.utcnow().shift(hours=+1).format('h:MM A'))
where=urllib.parse.quote_plus('WHERE field data')
url=urllib.parse.quote_plus('https://yoururl.com')
description=urllib.parse.quote_plus('test test test')
customEventTypeId = authDetails['CONFLUENCE_CUSTOM_EVENT_TYPE_ID'] #subcalender type
subCalendarId = authDetails['CONFLUENCE_SUBCALENDAR_ID']
seraphConfluence = authDetails['CONFLUENCE_SERAPH_CONFLUENCE']
JSESSIONID = authDetails['CONFLUENCE_JSESSION_ID']
data = f'confirmRemoveInvalidUsers=false&childSubCalendarId=&customEventTypeId={customEventTypeId}&eventType=custom&isSingleJiraDate=false&originalSubCalendarId=&originalStartDate=&originalEventType=&originalCustomEventTypeId=&recurrenceId=&subCalendarId={subCalendarId}&uid=&what={what}&startDate={startDate}&startTime={startTime}&endDate={endDate}&endTime={endTime}&allDayEvent=false&rruleStr=&until=&editAllInRecurrenceSeries=true&where={where}&url={url}&description={description}&userTimeZoneId=America%2FNew_York'
headers = {
'Content-Type': 'application/x-www-form-urlencoded',
'Cookie': f'seraph.confluence={seraphConfluence}; JSESSIONID={JSESSIONID}'
}
res = requests.put(url=reqUrl,data=data,headers=headers,verify=False)
Above code will replicate the whole process of adding event to calendar. You can use the same approach to replicate getting all event between particular dates.

Read facebook messages using python sdk

I'm trying to read facebook conversations of a page using a python script. With this code
import facebook
at = "page access token"
pid = "page id"
api = facebook.GraphAPI( at )
p = api.get_object( 'me/conversations')
print p
I get a dictionary containing the following
{'paging': {'next': 'https://graph.facebook.com/v2.5/1745249635693902/conversations?access_token=<my_access_token>&limit=25&until=1454344040&__paging_token=<my_access_token>', 'previous': 'https://graph.facebook.com/v2.5/1745249635693902/conversations?access_token=<my_access_token>&limit=25&since=1454344040&__paging_token=<my_access_token>'}, 'data': [{'link': '/Python-1745249635693902/manager/messages/?mercurythreadid=user%3A100000386799941&threadid=mid.1454344039847%3A2e3ac25e0302042916&folder=inbox', 'id': 't_mid.1454344039847:2e3ac25e0302042916', 'updated_time': '2016-02-01T16:27:20+0000'}]}
What are those fields? How can I get the text of the message?
Edit: I tried asking for the "messages" field by adding
msg = api.get_object( p['data'][0]['id']+'/messages')
print msg
but it just returns the same fields. I've searched in the API docs for a while, but I didn't find anything helpful. Is it even possible to read the message content of a facebook page's conversation using python?
I managed to find the answer myself; the question was not well posed and did not match what I was exactly looking for.
I wanted to get the content of the messages of facebook conversations of a page. Following the facebook graph API documentation, this can be achieved by asking for the conversations ({page-id}/conversations), then the messages in said conversations ({conversation-id}/messages, https://developers.facebook.com/docs/graph-api/reference/v2.5/conversation/messages), and finally asking for the message itself should return a dict with all the fields, content included (/{message-id}, https://developers.facebook.com/docs/graph-api/reference/v2.5/message).
At least this is how I believed it should have been; however the last request returned only the fields 'created_time' and 'id'.
What I was really trying to ask was a way to fetch the 'message' (content) field. I was assuming the function graph.get_object() from the official python facebook sdk should have returned all the fields in any case, since it has only one documented argument (http://facebook-sdk.readthedocs.org/en/latest/api.html) - the graph path for the requested object, and adding additional field request is not allowed.
The answer I was looking for was in this other question, Request fields in Python Facebook SDK.
Apparently, it's possible to ask for specific fields ( that are not returned otherwise ) by passing an **args dict with such fields along with the path requested.
In a GET request to the Facebook graph that would be the equivalent of adding
?fields=<requested fieds>
to the object path.
This is the working code:
#!/usr/bin/env python
import facebook
at = <my access token>
pid = <my page id>
api = facebook.GraphAPI( at )
args = {'fields' : 'message'} #requested fields
conv = api.get_object( 'me/conversations')
msg = api.get_object( conv['data'][0]['id']+'/messages')
for el in msg['data']:
content = api.get_object( el['id'], **args) #adding the field request
print content

Categories