"""Splitwise Python SDK
Splitwise Python SDK provides a simple interface to access splitwise APIs
Typical usage:
>>> s = Splitwise("consumer_key", "consumer_secret")
>>> s.setAccessToken(access_token)
>>> s.getCurrentUser().getId()
78322
>>> expense = Expense()
>>> expense.setGroupId("19433671")
>>> expense.setSplitEqually()
>>> expense.setCost("10")
>>> created_expense, errors = s.createExpense(expense)
>>> created_expense.getId()
897763
"""
import json
import io
from splitwise.user import User, Friend, CurrentUser
from splitwise.currency import Currency
from splitwise.group import Group
from splitwise.category import Category
from splitwise.expense import Expense
from splitwise.comment import Comment
from splitwise.notification import Notification
from splitwise.error import SplitwiseError
from requests_oauthlib import OAuth1, OAuth2Session, OAuth2
from requests import Request, sessions
from splitwise.exception import (SplitwiseException,
SplitwiseUnauthorizedException,
SplitwiseBadRequestException,
SplitwiseNotAllowedException,
SplitwiseNotFoundException
)
from .__version__ import __version__ # noqa: F401
try:
from urlparse import parse_qs # Python 2.x
from urllib import urlencode
except ImportError: # Python 3
from urllib.parse import parse_qs, urlencode
[docs]class Splitwise(object):
""" The Splitwise class that provides all the functionality.
Attributes:
consumer_key(str): Consumer Key provided by Splitwise.
consumer_secret(str): Consumer Secret provided by Splitwise.
auth(:obj:`requests.AuthBase`, optional): A request.AuthBase object that defines an auth.
"""
SPLITWISE_BASE_URL = "https://secure.splitwise.com/"
SPLITWISE_VERSION = "v3.0"
OAUTH_BASE_URL = "https://www.splitwise.com/"
# URLs to make the request
REQUEST_TOKEN_URL = SPLITWISE_BASE_URL+"api/" + \
SPLITWISE_VERSION+"/get_request_token"
ACCESS_TOKEN_URL = SPLITWISE_BASE_URL+"api/" + \
SPLITWISE_VERSION+"/get_access_token"
AUTHORIZE_URL = SPLITWISE_BASE_URL + \
"authorize"
OAUTH_AUTHORIZE_URL = OAUTH_BASE_URL + "oauth/" \
"authorize"
OAUTH2_TOKEN_URL = OAUTH_BASE_URL + "oauth/" \
"token"
GET_CURRENT_USER_URL = SPLITWISE_BASE_URL + \
"api/"+SPLITWISE_VERSION+"/get_current_user"
GET_USER_URL = SPLITWISE_BASE_URL + \
"api/"+SPLITWISE_VERSION+"/get_user"
UPDATE_USER_URL = SPLITWISE_BASE_URL + \
"api/"+SPLITWISE_VERSION+"/update_user"
GET_FRIENDS_URL = SPLITWISE_BASE_URL + \
"api/"+SPLITWISE_VERSION+"/get_friends"
GET_GROUPS_URL = SPLITWISE_BASE_URL + \
"api/"+SPLITWISE_VERSION+"/get_groups"
GET_GROUP_URL = SPLITWISE_BASE_URL + \
"api/"+SPLITWISE_VERSION+"/get_group"
GET_CURRENCY_URL = SPLITWISE_BASE_URL + \
"api/"+SPLITWISE_VERSION+"/get_currencies"
GET_CATEGORY_URL = SPLITWISE_BASE_URL + \
"api/"+SPLITWISE_VERSION+"/get_categories"
GET_EXPENSES_URL = SPLITWISE_BASE_URL + \
"api/"+SPLITWISE_VERSION+"/get_expenses"
GET_EXPENSE_URL = SPLITWISE_BASE_URL + \
"api/"+SPLITWISE_VERSION+"/get_expense"
CREATE_EXPENSE_URL = SPLITWISE_BASE_URL + \
"api/"+SPLITWISE_VERSION+"/create_expense"
UPDATE_EXPENSE_URL = SPLITWISE_BASE_URL + \
"api/" + SPLITWISE_VERSION + "/update_expense"
DELETE_EXPENSE_URL = SPLITWISE_BASE_URL + \
"api/"+SPLITWISE_VERSION+"/delete_expense"
CREATE_GROUP_URL = SPLITWISE_BASE_URL + \
"api/"+SPLITWISE_VERSION+"/create_group"
ADD_USER_TO_GROUP_URL = SPLITWISE_BASE_URL + \
"api/"+SPLITWISE_VERSION+"/add_user_to_group"
DELETE_GROUP_URL = SPLITWISE_BASE_URL + \
"api/"+SPLITWISE_VERSION+"/delete_group"
GET_COMMENTS_URL = SPLITWISE_BASE_URL + \
"api/"+SPLITWISE_VERSION+"/get_comments"
CREATE_COMMENT_URL = SPLITWISE_BASE_URL + \
"api/"+SPLITWISE_VERSION+"/create_comment"
GET_NOTIFICATIONS_URL = SPLITWISE_BASE_URL + \
"api/"+SPLITWISE_VERSION+"/get_notifications"
debug = False
def __init__(self, consumer_key, consumer_secret, access_token=None, oauth2_access_token=None, api_key=None):
"""
Args:
consumer_key(str): Consumer Key provided by Spliwise
consumer_secret(str): Consumer Secret provided by Splitwise
access_token(:obj:`dict`, optional): Access Token is a combination of
oauth_token and oauth_token_secret
oauth2_access_token(:obj:`dict`, optional): OAuth2 Access Token is a combination of
access_token and token_type
api_key(str, optional): API key provided by Splitwise
"""
self.consumer_key = consumer_key
self.consumer_secret = consumer_secret
self.auth = None
self.api_key = api_key
# If access token is present then set the Access token
if access_token:
self.setAccessToken(access_token)
if oauth2_access_token:
self.setOAuth2AccessToken(oauth2_access_token)
[docs] def getOAuth2AuthorizeURL(self, redirect_uri, state=None):
""" Provides the Authorize URL for end user's authentication
Returns:
tuple: tuple containing:
auth_url(str): URL that user should be redirected to for authorization
oauth_token_secret(str): Token secret that should be saved to redeem token
"""
oauth = OAuth2Session(self.consumer_key, redirect_uri=redirect_uri, state=state)
authorization_url, state = oauth.authorization_url(Splitwise.OAUTH_AUTHORIZE_URL)
return authorization_url, state
[docs] def getAuthorizeURL(self):
""" Provides the Authorize URL for end user's authentication
Returns:
tuple: tuple containing:
auth_url(str): URL that user should be redirected to for authorization
oauth_token_secret(str): Token secret that should be saved to redeem token
"""
oauth1 = OAuth1(
self.consumer_key,
client_secret=self.consumer_secret
)
content = self.__makeRequest(Splitwise.REQUEST_TOKEN_URL, method='POST', auth=oauth1)
credentials = parse_qs(content)
return "%s?oauth_token=%s" % (
Splitwise.AUTHORIZE_URL, credentials.get('oauth_token')[0]
), credentials.get('oauth_token_secret')[0]
[docs] def getOAuth2AccessToken(self, code, redirect_uri):
""" Provides the OAuth1.0 access token
Args:
code(str): code from the query param after redirect
redirect_uri(str): Redirect uri specified while getting code
Returns:
dict: dict containing:
access_token(str): The OAuth 2.0 token
token_type(str): The OAuth 2.0 token type
"""
data = "client_id=%s&client_secret=%s&grant_type=authorization_code&code=%s&redirect_uri=%s" % (
self.consumer_key, self.consumer_secret, code, redirect_uri)
content = self.__makeRequest(Splitwise.OAUTH2_TOKEN_URL, 'POST', data=data)
if content == "false":
return None
content = json.loads(content)
return content
[docs] def getAccessToken(self, oauth_token, oauth_token_secret, oauth_verifier):
""" Provides the OAuth1.0 access token
Args:
oauth_token(str): The OAuth 1.0 token got from the redirect URL
oauth_token_secret(str): The OAuth 1.0 token secret got while generating the auth URL
oauth_verifier(str): The OAuth 1.0 token verifier got from the redirect URL
Returns:
dict: dict containing:
oauth_token(str): The OAuth 1.0 token
oauth_token_secret(str): The OAuth 1.0 token secret
"""
oauth1 = OAuth1(
self.consumer_key,
client_secret=self.consumer_secret,
resource_owner_key=oauth_token,
resource_owner_secret=oauth_token_secret,
verifier=oauth_verifier
)
try:
content = self.__makeRequest(Splitwise.ACCESS_TOKEN_URL, 'POST', auth=oauth1)
except SplitwiseUnauthorizedException as e:
e.setMessage("Your oauth token could be expired or check your consumer id and secret")
raise
credentials = parse_qs(content)
return {
"oauth_token": credentials.get("oauth_token")[0],
"oauth_token_secret": credentials.get("oauth_token_secret")[0],
}
[docs] def setAccessToken(self, access_token):
""" Sets the OAuth1.0 access token, this should be done to make any authorized calls
Args:
access_token(:obj:`dict`): dict containing
oauth_token(str): The OAuth 1.0 token
oauth_token_secret(str): The OAuth 1.0 token secret
"""
oauth1 = OAuth1(self.consumer_key,
client_secret=self.consumer_secret,
resource_owner_key=access_token['oauth_token'],
resource_owner_secret=access_token['oauth_token_secret'])
self.auth = oauth1
[docs] def setOAuth2AccessToken(self, access_token):
""" Sets the OAuth2.0 access token, this should be done to make any authorized calls
Args:
access_token(:obj:`dict`): dict containing
access_token(str): The OAuth 2.0 token
token_type(str): The OAuth 2.0 token type
"""
oauth2 = OAuth2(self.consumer_key,
token=access_token)
self.auth = oauth2
def __makeRequest(self, url, method="GET", data=None, auth=None, files=None):
headers = {}
if auth is None:
if self.auth:
auth = self.auth
elif self.api_key:
headers = {'Authorization': 'Bearer {}'.format(self.api_key)}
data = Splitwise.__handleUppercaseBoolean(data)
requestObj = Request(method=method, url=url, headers=headers, data=data, auth=auth, files=files)
prep_req = requestObj.prepare()
with sessions.Session() as session:
response = session.send(prep_req)
content = self.__handleResponse(response)
return content
def __handleResponse(self, response):
if response.status_code == 200:
if (response.content and hasattr(response.content, "decode")):
return response.content.decode("utf-8")
return response.content
if response.status_code == 401:
raise SplitwiseUnauthorizedException("Please check your token or consumer id and secret", response=response)
if response.status_code == 403:
raise SplitwiseNotAllowedException("You are not allowed to perform this operation", response=response)
if response.status_code == 400:
raise SplitwiseBadRequestException("Please check your request", response=response)
if response.status_code == 404:
raise SplitwiseNotFoundException("Required resource is not found", response)
raise SplitwiseException("Unknown error happened", response)
def __prepareOptionsUrl(self, options={}):
return "?"+urlencode(options)
[docs] def getCurrentUser(self):
""" Gets the current authorized user's data
Returns:
:obj:`splitwise.user.CurrentUser`: CurrentUser object containing user data
"""
content = self.__makeRequest(Splitwise.GET_CURRENT_USER_URL)
content = json.loads(content)
return CurrentUser(content["user"])
[docs] def getUser(self, id):
""" Gets the friends user's data given the ids
Args:
id (long): ID of the user whose information is needed
Returns:
:obj:`splitwise.user.User`: User object containing user data
"""
try:
content = self.__makeRequest(Splitwise.GET_USER_URL + "/"+str(id))
except SplitwiseNotAllowedException as e:
e.setMessage("You are not allowed to fetch user with id %d" % id)
raise
except SplitwiseNotFoundException as e:
e.setMessage("User with id %d does not exist" % id)
raise
content = json.loads(content)
return User(content["user"])
[docs] def updateUser(self, user):
""" Updates the user.
Args:
:obj:`splitwise.user.CurrentUser`: User object with atleast id set
Returns:
tuple: tuple containing:
user(:obj:`splitwise.user.CurrentUser`): Object with User detail
errors(:obj:`splitwise.error.SplitwiseError`): Object representing errors
"""
if user.getId() is None:
raise SplitwiseBadRequestException("User ID is required to update user")
user_data = user.__dict__
try:
content = self.__makeRequest(Splitwise.UPDATE_USER_URL, 'POST', user_data)
except SplitwiseNotAllowedException as e:
e.setMessage("You are not allowed to access user with id %d" % user.getId())
raise
except SplitwiseNotFoundException as e:
e.setMessage("User with id %d does not exist" % user.getId())
raise
content = json.loads(content)
user = None
errors = None
if "user" in content:
if content["user"] is not None:
user = CurrentUser(content["user"])
if "errors" in content:
if len(content['errors']) != 0:
errors = SplitwiseError(content["errors"])
return user, errors
[docs] def getFriends(self):
""" Gets the list of users friends.
Returns:
:obj:`list` of :obj:`splitwise.user.Friend`: List of Friends
"""
content = self.__makeRequest(Splitwise.GET_FRIENDS_URL)
content = json.loads(content)
friends = []
if "friends" in content:
for f in content["friends"]:
friends.append(Friend(f))
return friends
[docs] def getGroups(self):
""" Gets the list of groups a user is part of.
Returns:
:obj:`list` of :obj:`splitwise.group.Group`: List of Groups
"""
content = self.__makeRequest(Splitwise.GET_GROUPS_URL)
content = json.loads(content)
groups = []
if "groups" in content:
for g in content["groups"]:
groups.append(Group(g))
return groups
[docs] def getCurrencies(self):
""" Gets the list of curriencies in Splitwise.
Returns:
:obj:`list` of :obj:`splitwise.currency.Currency`: List of Currency
"""
content = self.__makeRequest(Splitwise.GET_CURRENCY_URL)
content = json.loads(content)
currencies = []
if "currencies" in content:
for c in content["currencies"]:
currencies.append(Currency(c))
return currencies
[docs] def getCategories(self):
""" Gets the list of categories in Splitwise.
Returns:
:obj:`list` of :obj:`splitwise.category.Category`: List of Category
"""
content = self.__makeRequest(Splitwise.GET_CATEGORY_URL)
content = json.loads(content)
categories = []
if "categories" in content:
for c in content["categories"]:
categories.append(Category(c))
return categories
[docs] def getGroup(self, id=0):
""" Gets the detail of particular group a user is part of.
Args:
id(long, optional): ID of the group. Default value is 0, and means non-group expenses
Returns:
:obj:`splitwise.group.Group`: Object representing a group
"""
try:
content = self.__makeRequest(Splitwise.GET_GROUP_URL+"/"+str(id))
except SplitwiseNotAllowedException as e:
e.setMessage("You are not allowed to fetch group with id %d" % id)
raise
except SplitwiseNotFoundException as e:
e.setMessage("Group with id %d does not exist" % id)
raise
content = json.loads(content)
group = None
if "group" in content:
group = Group(content["group"])
return group
[docs] def getExpenses(self,
offset=None,
limit=None,
group_id=None,
friend_id=None,
dated_after=None,
dated_before=None,
updated_after=None,
updated_before=None,
visible=None
):
""" Gets the list of expenses given parameters.
Args:
offset(int, optional): Number of expenses to be skipped
limit(int, optional): Number of expenses to be returned
group_id(long, optional): GroupID of the expenses
friend_id(long, optional): ID of the friend for which expenses are required
dated_after(str, optional): ISO 8601 Date time. Return expenses later that this date
dated_before(str, optional): ISO 8601 Date time. Return expenses earlier than this date
updated_after(str, optional): ISO 8601 Date time. Return expenses updated after this date
updated_before(str, optional): ISO 8601 Date time. Return expenses updated before this date
visible(bool, optional): Boolean to show only not deleted expenses
Returns:
:obj:`list` of :obj:`splitwise.expense.Expense`: List of Expense
"""
options = {}
# Copy of the locals is created as if I directly work on
# locals and create variables in the loop a dictionary changed
# error is thrown. Refer to bug #2 on Github
localCopy = dict(locals())
params = localCopy.keys()
for param in params:
if param != 'self' and param != 'options' and localCopy.get(param) is not None:
paramVal = localCopy.get(param)
options[param] = paramVal
if isinstance(paramVal, bool):
options[param] = str(paramVal).lower()
url = Splitwise.GET_EXPENSES_URL
url += self.__prepareOptionsUrl(options)
content = self.__makeRequest(url)
content = json.loads(content)
expenses = []
if "expenses" in content:
for e in content["expenses"]:
expenses.append(Expense(e))
return expenses
[docs] def getExpense(self, id):
""" Gets the detail of the expense given the expense id.
Args:
id(long, optional): ID of the expense.
Returns:
:obj:`splitwise.expense.Expense`: Object representing an expense
"""
content = self.__makeRequest(Splitwise.GET_EXPENSE_URL+"/"+str(id))
content = json.loads(content)
expense = None
if "expense" in content:
expense = Expense(content["expense"])
return expense
[docs] def createExpense(self, expense):
""" Creates a new expense.
Args:
expense(:obj:`splitwise.expense.Expense`): Splitwise Expense Object.
Returns:
tuple: tuple containing:
expense(:obj:`splitwise.expense.Expense`): Object with Expense detail
errors(:obj:`splitwise.error.SplitwiseError`): Object representing errors
"""
# Get the expense Dict
expense_data = expense.__dict__
# Get users and store in a separate var
expense_users = expense.getUsers()
if expense_users:
# Delete users from original dict as we
# need to put like users_1_
del expense_data['users']
# Add user values to expense_data
Splitwise.setUserArray(expense_users, expense_data)
category = expense.getCategory()
if category:
expense_data["category_id"] = category.getId()
del expense_data["category"]
receipt = expense.getReceiptPath()
files = None
if receipt:
files = {"receipt": io.open(receipt, "rb")}
del expense_data["receiptPath"]
content = self.__makeRequest(
Splitwise.CREATE_EXPENSE_URL, "POST", expense_data, files=files)
content = json.loads(content)
expense = None
errors = None
if files:
files["receipt"].close()
if 'expenses' in content:
if len(content['expenses']) > 0:
expense = Expense(content["expenses"][0])
if 'errors' in content:
if len(content['errors']) != 0:
errors = SplitwiseError(content['errors'])
return expense, errors
[docs] def updateExpense(self, expense):
""" Updates an existing expense.
Args:
expense(:obj:`splitwise.expense.Expense`): Splitwise Expense Object.
expense id must be set. Include only the fields that should be updated. null fields are ignored
Returns:
tuple: tuple containing:
expense(:obj:`splitwise.expense.Expense`): Object with Expense detail
errors(:obj:`splitwise.error.SplitwiseError`): Object representing errors
"""
expense_id = expense.id
if expense_id is None:
raise SplitwiseBadRequestException("Incorrect query parameters sent. Expense Id cannot be null")
# Get the expense Dict
expense_data = expense.__dict__
del expense_data['id']
# Get users and store in a separate var
expense_users = expense.getUsers()
if expense_users:
# Delete users from original dict as we
# need to put like users_1_
del expense_data['users']
# Add user values to expense_data
Splitwise.setUserArray(expense_users, expense_data)
category = expense.getCategory()
if category:
expense_data["category_id"] = category.getId()
del expense_data["category"]
receipt = expense.getReceiptPath()
files = None
if receipt:
files = {"receipt": io.open(receipt, "rb")}
del expense_data["receiptPath"]
expense_data.pop("created_by", None)
expense_data.pop("repayments", None)
expense_data.pop("next_repeat", None)
expense_data.pop("comments_count", None)
expense_data.pop("updated_by", None)
expense_data.pop("transaction_confirmed", None)
expense_data.pop("deleted_at", None)
expense_data.pop("friendship_id", None)
expense_data.pop("expense_bundle_id", None)
expense_data.pop("updated_at", None)
expense_data.pop("deleted_by", None)
expense_data.pop("created_at", None)
content = self.__makeRequest(
Splitwise.UPDATE_EXPENSE_URL+"/"+str(expense_id), "POST", expense_data, files=files)
content = json.loads(content)
expense = None
errors = None
if files:
files["receipt"].close()
if 'expenses' in content:
if len(content['expenses']) > 0:
expense = Expense(content["expenses"][0])
if 'errors' in content:
if len(content['errors']) != 0:
errors = SplitwiseError(content['errors'])
return expense, errors
[docs] def deleteExpense(self, id):
""" Deletes the expense with given id.
Args:
id(long): ID of the expense to be deleted.
Returns:
tuple: tuple containing:
success(bool): True if group deleted, False otherwise
errors(:obj:`splitwise.error.SplitwiseError`): Object representing errors
"""
errors = None
success = False
try:
content = self.__makeRequest(
Splitwise.DELETE_EXPENSE_URL+"/"+str(id), "POST")
except SplitwiseNotAllowedException as e:
e.setMessage("You are not allowed to access expense with id %d" % id)
raise
except SplitwiseNotFoundException as e:
e.setMessage("Expense with id %d does not exist" % id)
raise
content = json.loads(content)
if 'success' in content:
success = content["success"]
if 'errors' in content:
if len(content['errors']) != 0:
errors = SplitwiseError(content['errors'])
return success, errors
[docs] def createGroup(self, group):
""" Creates a new Group.
Args:
group(:obj:`splitwise.group.Group`): Splitwise Group Object.
Returns:
tuple: tuple containing:
group(:obj:`splitwise.group.Group`): Object with Group detail
errors(:obj:`splitwise.error.SplitwiseError`): Object representing errors
"""
# create group
group_info = group.__dict__
if "members" in group_info:
group_members = group.getMembers()
del group_info["members"]
Splitwise.setUserArray(group_members, group_info)
content = self.__makeRequest(
Splitwise.CREATE_GROUP_URL, "POST", group_info)
content = json.loads(content)
group_detail = None
errors = None
if "group" in content:
group_detail = Group(content["group"])
if "errors" in content["group"]:
if len(content["group"]['errors']) != 0:
errors = SplitwiseError(content["group"]["errors"])
return group_detail, errors
[docs] def addUserToGroup(self, user, group_id):
""" Adds a user to the group.
Args:
user(:obj:`splitwise.user.User`): User to be added
group_id(long): ID of the group
Returns:
tuple: tuple containing:
success(bool): True if group deleted, False otherwise
user(:obj:`splitwise.user.Friend`): Object representing added user details
errors(:obj:`splitwise.error.SplitwiseError`): Object representing errors
"""
# Get the user data
request_data = user.__dict__
request_data["group_id"] = group_id
if "id" in request_data:
request_data["user_id"] = request_data["id"]
del request_data["id"]
try:
content = self.__makeRequest(
Splitwise.ADD_USER_TO_GROUP_URL, "POST", request_data)
except SplitwiseNotAllowedException as e:
e.setMessage("You are not allowed to access group with id %d" % group_id)
raise
except SplitwiseNotFoundException as e:
e.setMessage("Group with id %d does not exist" % group_id)
raise
content = json.loads(content)
errors = None
success = False
user = None
if 'success' in content:
success = content["success"]
if 'errors' in content:
if len(content['errors']) != 0:
errors = SplitwiseError(content['errors'])
if 'user' in content:
if content['user'] is not None:
user = Friend(content['user'])
return success, user, errors
[docs] def deleteGroup(self, id):
""" Deletes the group with given id.
Args:
id(long): ID of the group to be deleted.
Returns:
tuple: tuple containing:
success(bool): True if group deleted, False otherwise
errors(:obj:`splitwise.error.SplitwiseError`): Object representing errors
"""
errors = None
success = False
try:
content = self.__makeRequest(
Splitwise.DELETE_GROUP_URL+"/"+str(id), "POST")
except SplitwiseNotAllowedException as e:
e.setMessage("You are not allowed to access group with id %d" % id)
raise
except SplitwiseNotFoundException as e:
e.setMessage("Group with id %d does not exist" % id)
raise
content = json.loads(content)
if 'success' in content:
success = content["success"]
if 'errors' in content:
if len(content['errors']) != 0:
errors = SplitwiseError(content['errors'])
return success, errors
@staticmethod
def __handleUppercaseBoolean(data):
# convert the uppercase True/False to lower
# Splitwise server considers False as true value
try:
if data is not None:
for key, val in data.items():
if isinstance(val, bool):
data[key] = str(val).lower()
except Exception:
pass
return data
@staticmethod
def setUserArray(users, user_array):
for count, user in enumerate(users):
user_dict = user.__dict__
for key in user_dict:
if key == "id":
gen_key = "user_id"
elif key == "picture":
continue
else:
gen_key = key
user_array["users__" +
str(count) + "__" + gen_key] = user_dict[key]
# TODO: Implement optional args
[docs] def getNotifications(self, updated_since=None, limit=None):
"""
Get notifications.
Args:
updated_since(string): Optional. ISO8601 Timestamp.
limit(long): Optional. Defaults to 0
Returns:
:obj:`splitwise.notification.Notifications`: Object representing Notifications
"""
try:
content = self.__makeRequest(Splitwise.GET_NOTIFICATIONS_URL)
except SplitwiseNotAllowedException as e:
e.setMessage("You are not allowed to fetch notifications")
raise
content = json.loads(content)
notifications = []
if "notifications" in content:
for n in content["notifications"]:
notifications.append(Notification(n))
return notifications