-
Notifications
You must be signed in to change notification settings - Fork 1
/
petfinder.py
167 lines (143 loc) · 6.1 KB
/
petfinder.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
import requests
import urllib.parse
from Dog import Dog
from credentials import pf_client_id
from credentials import pf_client_secret
from random import randint
class PetFinderClient:
def __init__(self):
self.api_key = self._get_token()
# Function that will return object(s) of Dog class
def get_dogs_by_breed(self, breed="German Shepherd Dog", zipcode="94065"):
""" Find dogs by breed sorted by distance to the specified zip code
returns list of objects of type Dog
"""
data = self._get_dogs_json_by_breed(breed, zipcode)
dogs = []
for el in data:
dog = _convert_to_dog(el)
if dog.photo_thumbnail is not None:
dogs.append(dog)
return dogs
def get_dogs(self, zipcode="94063"):
""" Find dogs of any breed sorted by distance to the specified zip code.
returns list of objects of type Dog
"""
data = self._get_dogs_json(zipcode)
dogs = []
for el in data:
dog = _convert_to_dog(el)
if dog.photo_thumbnail is not None:
dogs.append(dog)
return dogs
def get_dog_by_id(self, id="43736184"):
""" Find a dog by its PetFinder id.
returns one object of type Dog
"""
data = self._get_dog_json_by_id(id)
return _convert_to_dog(data)
# Functions that makes calls to PetFinder API
def _get_token(self):
""" Fetch access token from PetFinder api """
url = "https://api.petfinder.com/v2/oauth2/token"
body = {"grant_type": "client_credentials",
"client_id": pf_client_id,
"client_secret": pf_client_secret}
r = requests.post(url, data=body)
data = r.json()
api_key = data['access_token']
return "Bearer " + api_key
def _make_api_call(self, url):
""" Make GET Http request to PetFinder API with specified url and return uncleaned data """
headers = {'Authorization': self.api_key}
r = requests.get(url, headers=headers)
if r.status_code == 200:
return r.json()
# api key expired, get a new key
self.api_key = self._get_token()
print("Api key expired")
headers = {'Authorization': self.api_key}
r = requests.get(url, headers=headers)
return r.json()
def _get_dogs_json_by_breed(self, breed, zipcode):
""" Returns full dogs info of the specified breed near zipcode """
# Replace space symbols with %20
breed = urllib.parse.quote(breed)
url = "https://api.petfinder.com/v2/animals?type=dog&breed=%s&location=%s&distance=500&sort=distance&status=adoptable" % (
breed, zipcode)
data = self._make_api_call(url)
if 'animals' in data:
return data['animals']
return []
def _get_dogs_json(self, zipcode):
""" Return full info for all type of dogs near zipcode """
url = "https://api.petfinder.com/v2/animals?type=dog&location=%s&distance=10&sort=distance&status=adoptable" % (
zipcode)
data = self._make_api_call(url)
if 'pagination' in data:
total_pages = data['pagination']['total_pages']
random_page = randint(1, total_pages)
random_url = "https://api.petfinder.com/v2/animals?type=dog&location=%s&distance=10&sort=distance&status=adoptable&page=%d" % (
zipcode, random_page)
data = self._make_api_call(random_url)
if 'animals' in data:
return data['animals']
return []
def _get_dog_json_by_id(self, id):
""" Return full info for a single dog based on its id in PetFinder API """
url = "https://api.petfinder.com/v2/animals/%s" % id
data = self._make_api_call(url)
if 'animal' in data:
return data['animal']
print("No such animal")
return []
# Functions defined below this point should not be used directly in the other parts of the app
# Convert dictionary returned from PetFinder API to Dog object
def _convert_to_dog(element):
""" Convert information about one dog (returned from API call) to the object of type Dog """
# Check if photo is available (sometimes there is no picture of a dog)
photo_thumbnail = None
if len(element["photos"]) > 0:
photo_thumbnail = element["photos"][0]["large"]
address_line1 = ""
if element["contact"]["address"]["address1"] is not None:
address_line1 = element["contact"]["address"]["address1"]
address_line2 = ""
if element["contact"]["address"]["address2"] is not None:
address_line2 = element["contact"]["address"]["address2"]
address = address_line1 + " " + address_line2 + " " + \
element["contact"]["address"]["city"] + " " + element["contact"]["address"]["state"] + \
" " + element["contact"]["address"]["postcode"]
name = element["name"]
if len(name) > 22:
name = name[:21]
return Dog(element["id"],
element["organization_id"],
element["breeds"]["primary"],
element["breeds"]["secondary"],
element["age"],
element["gender"],
element["attributes"]["spayed_neutered"],
name,
photo_thumbnail,
element["contact"]["email"],
element["contact"]["phone"],
element["contact"]["address"]["city"],
element["photos"],
element["environment"],
element["description"],
address,
)
# Testing
# Uncomment one print statement at a time
# Find a dog by its PetFinder id
# You can specify id
# print(get_dog_by_id(45000754))
# Find dogs by breed sorted by distance to the specified zip code
# You can specify breed or/and zipcode
# print(get_dogs_by_breed("french bulldog", 94065))
# print(get_dogs_by_breed("Smooth Fox Terrier", 94065))
# print(get_dogs_by_breed("terrier", 94065))
# Find dogs of any breed sorted by distance to the specified zip code
# You can specify zipcode or leave the default
# print(get_dogs(94063))