Skip to content

Commit 047b838

Browse files
authored
Merge pull request #2 from thenamesweretakenalready/api-token-validation
Api token validation + other stuff
2 parents 7f2adc5 + f2f4bf5 commit 047b838

File tree

5 files changed

+111
-43
lines changed

5 files changed

+111
-43
lines changed

README.md

Lines changed: 62 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,16 @@ while also maintaining a readable codebase.
1010

1111
You can install jokeapi through [pip](https://pypi.org/project/pip/) by using `pip install jokeapi`
1212

13-
So far there are no build from source instructions.
14-
1513
---
1614

1715
# get_joke
1816

1917
The wrapper is structured in such a way that the end-user should only ever have to
20-
interact with one function. This function is `get_joke()`
18+
interact with one function. This function is `get_joke()`.
19+
20+
Please note that urllib3, the core dependency of this wrapper automatically abides by
21+
`Retry-After` headers, which means you may have to wait a long time for a joke if you
22+
have made a lot of requests recently
2123

2224
---
2325

@@ -29,7 +31,8 @@ interact with one function. This function is `get_joke()`
2931
from jokeapi import Jokes # Import the Jokes class
3032

3133
j = Jokes() # Initialise the class
32-
j.get_joke() # Retrieve a random joke
34+
joke = j.get_joke(type="single", response_format="txt") # Retrieve a random joke
35+
print(joke)
3336
```
3437

3538
### Parameters
@@ -129,15 +132,66 @@ If left blank it will default to `None`
129132

130133
The range in which the selected joke should fall. ID's are decided by the order in which jokes are submitted.
131134
The argument passes should be in form of list or tuple, and should not exceed length of 2 items. First item
132-
should be minimum 0.
135+
should be minimum 0. Maximum value can be determined [here](https://sv443.net/jokeapi/v2/info)
133136

134137
If left blank it will default to the maximum range.
135138

136139

137140
#### Example
138141

139142
```python
140-
joke = get_joke(id_range=[10,100]) # Will return a joke with the ID between 10 and 100
143+
joke = get_joke(id_range=[10,100]) # Will return a joke with the ID between 10 and 100.
144+
```
145+
146+
---
147+
148+
### auth_token
149+
150+
A string token provided by the api owner. Using it will mean you are whitelisted by the api and can make
151+
more requests than normal users. Defaults to None
152+
153+
154+
#### Example
155+
156+
```python
157+
joke = get_joke(auth_token="aaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbb") # Will send the token to the api in a header.
158+
```
159+
160+
---
161+
162+
### user_agent
163+
164+
A string sent the the api that tells the api what browser you are (pretending to be). The default user agent
165+
is Mozilla Firefox from Windows 10 and should work fine, but the functionality is provided in case you wish
166+
to change it
167+
168+
169+
#### Example
170+
171+
```python
172+
joke = get_joke(user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:77.0) Gecko/20100101 Firefox/77.0")
173+
# This is in fact the default user agent, and tells the API that we are visitng the page from a Firefox 77.0
174+
# browser using Windows 10 64bit.
175+
```
176+
177+
---
178+
179+
### return_headers
180+
181+
A boolean value (True or False) that tells the wrapper if you wish to receive headers in the return from the function.
182+
Defaults to False.
183+
184+
185+
#### Example
186+
187+
```python
188+
response = get_joke(return_headers=True)
189+
joke = response[0]
190+
headers = response[1]
191+
# The function returns the joke and then the headers using the "return x, y" syntax, so you can index it like a list or tuple.
192+
193+
print(f"Joke: {joke}")
194+
print(f"Headers: {headers}")
141195
```
142196

143197
---
@@ -151,7 +205,7 @@ Depending on what format is chosen different things will be returned.
151205

152206
A succesful API call will return:
153207

154-
```python
208+
```json
155209
{
156210
"category": "Miscellaneous",
157211
"type": "twopart",
@@ -228,16 +282,14 @@ He keeps dropping the database.
228282

229283
The wrapper can raise multiple different errors depending on what you did wrong.
230284

231-
### ValueErrors will always be raised with expected errors.
232-
233285
The errors are descriptive enough that you should be able to solve them with the information provided in the error message.
234286
If not, feel free to ask me through one of the channels provided below.
235287

236288
---
237289

238290
Developer contact:
239291

240-
[Discord](https://discord.gg/mB989eP)
292+
![Discord](https://discord.com/assets/07dca80a102d4149e9736d4b162cff6f.ico)[**Discord**](https://discord.gg/mB989eP)
241293

242294
[Issue Tracker](https://github.com/thenamesweretakenalready/Sv443s-JokeAPI-Python-Wrapper/issues)
243295

jokeapi/main.py

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import urllib3
22
import urllib
3-
import json
3+
import simplejson as json
4+
import re
45

56

67
class Jokes:
@@ -131,26 +132,39 @@ def build_request(
131132
return r
132133

133134
def send_request(self, request, response_format, return_headers, auth_token, user_agent):
135+
returns = []
136+
134137
if auth_token:
135138
r = self.http.request('GET', request, headers={'Authorization': str(
136139
auth_token), 'user-agent': str(user_agent)})
137140
else:
138141
r = self.http.request('GET', request, headers={'user-agent': str(user_agent)})
139142

140-
if return_headers:
141-
if response_format == "json":
142-
return r.data, r.headers
143-
elif response_format == "xml":
144-
return r.data, r.headers
145-
else:
146-
return r.data, r.headers
143+
data = r.data
144+
145+
if response_format == "json":
146+
try:
147+
data = json.loads(data)
148+
except:
149+
print(data)
150+
raise
147151
else:
148-
if response_format == "json":
149-
return r.data
150-
elif response_format == "xml":
151-
return r.data
152-
else:
153-
return r.data
152+
data = str(data)[2:-1].replace(r'\n', '\n').replace('\\', '')
153+
if len(' '.join(re.split("error", data.lower().replace("\n", "NEWLINECHAR"))[0:][1:]).replace(
154+
'<', '').replace('/', '').replace(' ', '').replace(':', '').replace('>', '').replace('NEWLINECHAR', '\n')) == 4:
155+
return [Exception(f"API returned an error. Full response: \n\n {data}")]
156+
157+
headers = str(r.headers).replace(r'\n', '').replace(
158+
'\n', '').replace(r'\\', '').replace(r"\'", '')[15:-1]
159+
160+
returns.append(data)
161+
if return_headers:
162+
returns.append(headers)
163+
164+
if auth_token:
165+
returns.append({"Token-Valid": bool(int(re.split(r"Token-Valid", headers)[1][4]))})
166+
167+
return returns
154168

155169
def get_joke(
156170
self,

requirements.txt

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,3 @@
1-
attrs==19.3.0
2-
coverage==5.0.3
3-
entrypoints==0.3
4-
flake8==3.7.9
5-
mccabe==0.6.1
6-
more-itertools==8.2.0
7-
packaging==20.1
8-
pluggy==0.13.1
9-
py==1.8.1
10-
pycodestyle==2.5.0
11-
pyflakes==2.1.1
12-
pyparsing==2.4.6
13-
pytest==5.3.5
14-
pytest-cov==2.8.1
15-
six==1.14.0
16-
wcwidth==0.1.8
171
urllib3==1.25.8
18-
python-dotenv
2+
simplejson==3.17.0
3+
python-dotenv==0.13.0

setup.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@
66
setuptools.setup(
77
name="jokeapi",
88
packages=["jokeapi"],
9-
version="0.2.1",
9+
version="0.2.3",
1010
license="GNU General Public License v3 (GPLv3)",
1111
description="An API Wrapper for Sv443's JokeAPI",
1212
long_description=long_description,
1313
long_description_content_type="text/markdown",
1414
author="thenamesweretakenalready",
1515
author_email="[email protected]",
1616
url="""https://github.com/thenamesweretakenalready/Sv443s-JokeAPI-Python-Wrapper""",
17-
download_url="https://github.com/user/Sv443s-JokeAPI-Python-Wrapper/archive/v0.1.5.tar.gz",
17+
download_url="https://github.com/user/Sv443s-JokeAPI-Python-Wrapper/archive/v0.2.3.tar.gz",
1818
keywords=["api wrapper", "wrapper", "api", "jokes", "python", "joke api"],
1919
install_requires=setuptools.find_packages(),
2020
classifiers=[

test_main.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from os import getenv
22
from jokeapi import Jokes
33
from dotenv import load_dotenv
4+
import time
45
load_dotenv()
56

67
j = Jokes()
@@ -12,69 +13,83 @@
1213
j.get_joke()
1314
except Exception as e:
1415
errors.append({'Error in': 'blank joke get', 'Error': e})
16+
time.sleep(2)
1517

1618
"""Testing auth tokens"""
1719
try:
1820
j.get_joke(auth_token=token)
1921
except Exception as e:
2022
auth_token = None
2123
errors.append({'Error in': 'auth usage', 'Error': e})
24+
time.sleep(2)
2225

2326
"""Testing for errors in categories"""
2427
try:
2528
j.get_joke(category=["programming"], auth_token=token)
2629
except Exception as e:
2730
errors.append({'Error in': 'category programming', 'Error': e})
31+
time.sleep(2)
2832
try:
2933
j.get_joke(category=["miscellaneous"], auth_token=token)
3034
except Exception as e:
3135
errors.append({'Error in': 'category miscellaneous', 'Error': e})
36+
time.sleep(2)
3237
try:
3338
j.get_joke(category=["dark"], auth_token=token)
3439
except Exception as e:
3540
errors.append({'Error in': 'category dark', 'Error': e})
41+
time.sleep(2)
3642

3743
"""Testing for errors in blacklist"""
3844
try:
3945
j.get_joke(blacklist=["nsfw"], auth_token=token)
4046
except Exception as e:
4147
errors.append({'Error in': 'blacklist nsfw', 'Error': e})
48+
time.sleep(2)
4249
try:
4350
j.get_joke(blacklist=["religious"], auth_token=token)
4451
except Exception as e:
4552
errors.append({'Error in': 'blacklist religious', 'Error': e})
53+
time.sleep(2)
4654
try:
4755
j.get_joke(blacklist=["political"], auth_token=token)
4856
except Exception as e:
4957
errors.append({'Error in': 'blacklist political', 'Error': e})
58+
time.sleep(2)
5059
try:
5160
j.get_joke(blacklist=["racist"], auth_token=token)
5261
except Exception as e:
5362
errors.append({'Error in': 'blacklist political', 'Error': e})
63+
time.sleep(2)
5464
try:
5565
j.get_joke(blacklist=["sexist"], auth_token=token)
5666
except Exception as e:
5767
errors.append({'Error in': 'blacklist sexist', 'Error': e})
68+
time.sleep(2)
5869

5970
"""Testing for errors in response_format"""
6071
try:
6172
j.get_joke(response_format="xml", auth_token=token)
6273
except Exception as e:
6374
errors.append({'Error in': 'response_format xml', 'Error': e})
75+
time.sleep(2)
6476
try:
6577
j.get_joke(response_format="yaml", auth_token=token)
6678
except Exception as e:
6779
errors.append({'Error in': 'response_format yaml', 'Error': e})
80+
time.sleep(2)
6881

6982
"""Testing for errors in type"""
7083
try:
7184
j.get_joke(type="single", auth_token=token)
7285
except Exception as e:
7386
errors.append({'Error in': 'type single', 'Error': e})
87+
time.sleep(2)
7488
try:
7589
j.get_joke(type="twopart", auth_token=token)
7690
except Exception as e:
7791
errors.append({'Error in': 'type double', 'Error': e})
92+
time.sleep(2)
7893

7994
"""Testing for errors in search_string"""
8095
try:
@@ -83,12 +98,14 @@
8398
# it probably doesn't exist in a joke.
8499
except Exception as e:
85100
errors.append({'Error in': 'search_string', 'Error': e})
101+
time.sleep(2)
86102

87103
"""Testing for errors in id_range"""
88104
try:
89105
j.get_joke(id_range=[30, 151], auth_token=token)
90106
except Exception as e:
91107
errors.append({'Error in': 'id_range', 'Error': e})
108+
time.sleep(2)
92109

93110
if len(errors):
94111
for e in errors:

0 commit comments

Comments
 (0)