Skip to content

Commit 6f97a46

Browse files
Merge pull request #118 from madeofpendletonwool/0.4.1
0.4.1 - Version Bump
2 parents 52bbfdb + 044856a commit 6f97a46

6 files changed

Lines changed: 195 additions & 20 deletions

File tree

api_functions/functions.py

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,32 +13,28 @@ def generate_session_token():
1313

1414

1515
def call_clean_expired_sessions(url, headers):
16-
# print(f'in clean expired call {headers}')
16+
# print('clean expired call {headers}')
1717
response = requests.post(url + "/clean_expired_sessions/", headers=headers)
1818
if response.status_code == 200:
19-
print('Response good!')
20-
# print(response.json())
19+
print(response.json())
2120
else:
2221
print("Error calling clean_expired_sessions:", response.status_code)
2322

2423

2524
def call_verify_key(url, headers):
2625
response = requests.get(url + "/verify_key", headers=headers)
2726
if response.status_code == 200:
28-
print('Response good!')
2927
return {"status": "success"}
3028
else:
3129
print("Error calling verify_key:", response.status_code)
3230
return {"status": "error", "code": response.status_code}
3331

3432

3533
def call_get_key(url, username, password):
36-
print('test')
3734
from requests.auth import HTTPBasicAuth
3835
try:
3936
response = requests.get(url + "/get_key", auth=HTTPBasicAuth(username, password))
4037
if response.status_code == 200:
41-
print('Response good!')
4238
return response.json() # Assumes the API key is returned in JSON response
4339
else:
4440
print("Error calling verify_key:", response.status_code)
@@ -49,14 +45,12 @@ def call_get_key(url, username, password):
4945

5046

5147
def call_get_user(url, headers):
52-
print('test')
5348
from requests.auth import HTTPBasicAuth
5449
try:
5550
response = requests.get(url + "/get_user", headers=headers)
5651
print(f'Response status code: {response.status_code}')
5752
print(f'Response text: {response.text}') # Add this to debug the response content
5853
if response.status_code == 200:
59-
print('Response good!')
6054
return response.json() # Assumes the API key is returned in JSON response
6155
else:
6256
print("Error calling verify_key:", response.status_code)
@@ -180,6 +174,40 @@ def call_return_episodes(url, headers, user_id):
180174
print("Error details:", response.text)
181175
return None
182176

177+
def call_podcast_episodes(url, headers, user_id, podcast_id):
178+
data = {
179+
"user_id": str(user_id),
180+
"podcast_id": str(podcast_id)
181+
}
182+
response = requests.get(url + f"/podcast_episodes", headers=headers, data=data)
183+
if response.status_code == 200:
184+
episodes = response.json()["episodes"]
185+
if episodes:
186+
return episodes
187+
else:
188+
return None
189+
else:
190+
print("Error fetching episodes:", response.status_code)
191+
print("Error details:", response.text)
192+
return None
193+
194+
def call_get_podcast_id(url, headers, user_id, podcast_feed):
195+
data = {
196+
"user_id": str(user_id),
197+
"podcast_feed": str(podcast_feed)
198+
}
199+
response = requests.get(url + f"/podcast_episodes", headers=headers, data=data)
200+
if response.status_code == 200:
201+
episodes = response.json()["episodes"]
202+
if episodes:
203+
return episodes
204+
else:
205+
return None
206+
else:
207+
print("Error fetching episodes:", response.status_code)
208+
print("Error details:", response.text)
209+
return None
210+
183211

184212
def call_check_episode_playback(url, headers, user_id, episode_title, episode_url):
185213
payload = {
@@ -399,8 +427,10 @@ def call_get_user_episode_count(url, headers, user_id):
399427
response = requests.get(url + f"/get_user_episode_count?user_id={user_id}", headers=headers)
400428
if response.status_code == 200:
401429
episode_count = response.json()
430+
print(f'ya counts: {episode_count}')
402431
return episode_count
403432
else:
433+
print("error")
404434
print("Error getting user episode count:", response.status_code)
405435
return None
406436

@@ -582,8 +612,8 @@ def call_set_password(url, headers, user_id, salt, hash_pw):
582612

583613

584614
def call_set_email(url, headers, user_id, email):
585-
data = {"user_id": self.user_id, "new_email": self.email}
586-
response = requests.put(app_api.url + "/user/set_email", headers=app_api.headers, json=data)
615+
data = {"user_id": user_id, "new_email": email}
616+
response = requests.put(url + "/user/set_email", headers=headers, json=data)
587617
if response.status_code != 200:
588618
print("Error updating email:", response.status_code)
589619

clients/clientapi.py

Lines changed: 61 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,59 @@ async def api_return_episodes(user_id: int, cnx=Depends(get_database_connection)
469469
detail="You can only return episodes of your own!")
470470

471471

472+
class PodcastData(BaseModel):
473+
podcast_id: int
474+
user_id: int
475+
@app.post("/api/data/podcast_episodes")
476+
async def api_podcast_episodes(data: PodcastData, cnx=Depends(get_database_connection), api_key: str = Depends(get_api_key_from_header)):
477+
is_valid_key = database_functions.functions.verify_api_key(cnx, api_key)
478+
if not is_valid_key:
479+
raise HTTPException(status_code=403,
480+
detail="Your API key is either invalid or does not have correct permission")
481+
482+
# Check if the provided API key is the web key
483+
is_web_key = api_key == base_webkey.web_key
484+
485+
key_id = database_functions.functions.id_from_api_key(cnx, api_key)
486+
487+
# Allow the action if the API key belongs to the user, or it's the web API key
488+
if key_id == data.user_id or is_web_key:
489+
episodes = database_functions.functions.return_podcast_episodes(database_type, cnx, data.user_id, data.podcast_id)
490+
if episodes is None:
491+
episodes = [] # Return an empty list instead of raising an exception
492+
return {"episodes": episodes}
493+
else:
494+
raise HTTPException(status_code=403,
495+
detail="You can only return episodes of your own!")
496+
497+
class PodcastIDData(BaseModel):
498+
podcast_feed: str
499+
user_id: int
500+
@app.get("/api/data/get_podcast_id")
501+
async def api_podcast_id(data: PodcastData, cnx=Depends(get_database_connection),
502+
api_key: str = Depends(get_api_key_from_header)):
503+
is_valid_key = database_functions.functions.verify_api_key(cnx, api_key)
504+
if not is_valid_key:
505+
raise HTTPException(status_code=403,
506+
detail="Your API key is either invalid or does not have correct permission")
507+
508+
# Check if the provided API key is the web key
509+
is_web_key = api_key == base_webkey.web_key
510+
511+
key_id = database_functions.functions.id_from_api_key(cnx, api_key)
512+
513+
# Allow the action if the API key belongs to the user, or it's the web API key
514+
if key_id == user_id or is_web_key:
515+
episodes = database_functions.functions.get_podcast_id(database_type, cnx, data.user_id, data.podcast_feed)
516+
if episodes is None:
517+
episodes = [] # Return an empty list instead of raising an exception
518+
return {"episodes": episodes}
519+
else:
520+
raise HTTPException(status_code=403,
521+
detail="You can only return pocast ids of your own podcasts!")
522+
523+
524+
472525
@app.post("/api/data/check_episode_playback")
473526
async def api_check_episode_playback(
474527
user_id: int = Form(...),
@@ -858,6 +911,7 @@ async def api_get_user_episode_count(user_id: int, cnx=Depends(get_database_conn
858911
is_valid_key = database_functions.functions.verify_api_key(cnx, api_key)
859912

860913
if not is_valid_key:
914+
logging.error(f"not valid key")
861915
raise HTTPException(status_code=403,
862916
detail="Your API key is either invalid or does not have correct permission")
863917

@@ -870,11 +924,13 @@ async def api_get_user_episode_count(user_id: int, cnx=Depends(get_database_conn
870924
if user_id != user_id_from_api_key:
871925
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN,
872926
detail="You are not authorized to access these user details")
873-
episode_count = database_functions.functions.get_user_episode_count(cnx, user_id)
874-
if episode_count:
875-
return episode_count
876-
else:
877-
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User not found")
927+
episode_count = database_functions.functions.get_user_episode_count(cnx, user_id)
928+
if episode_count:
929+
print(episode_count)
930+
logging.error(f"here's count: {episode_count}")
931+
return episode_count
932+
else:
933+
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User not found")
878934

879935

880936
@app.get("/api/data/get_user_info")

clients/linux-app/api_functions/functions.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,40 @@ def call_return_episodes(url, headers, user_id):
180180
print("Error details:", response.text)
181181
return None
182182

183+
def call_podcast_episodes(url, headers, user_id, podcast_id):
184+
data = {
185+
"user_id": str(user_id),
186+
"podcast_id": str(podcast_id)
187+
}
188+
response = requests.get(url + f"/podcast_episodes", headers=headers, data=data)
189+
if response.status_code == 200:
190+
episodes = response.json()["episodes"]
191+
if episodes:
192+
return episodes
193+
else:
194+
return None
195+
else:
196+
print("Error fetching episodes:", response.status_code)
197+
print("Error details:", response.text)
198+
return None
199+
200+
def call_get_podcast_id(url, headers, user_id, podcast_feed):
201+
data = {
202+
"user_id": str(user_id),
203+
"podcast_feed": str(podcast_feed)
204+
}
205+
response = requests.get(url + f"/podcast_episodes", headers=headers, data=data)
206+
if response.status_code == 200:
207+
episodes = response.json()["episodes"]
208+
if episodes:
209+
return episodes
210+
else:
211+
return None
212+
else:
213+
print("Error fetching episodes:", response.status_code)
214+
print("Error details:", response.text)
215+
return None
216+
183217

184218
def call_check_episode_playback(url, headers, user_id, episode_title, episode_url):
185219
payload = {
@@ -399,8 +433,10 @@ def call_get_user_episode_count(url, headers, user_id):
399433
response = requests.get(url + f"/get_user_episode_count?user_id={user_id}", headers=headers)
400434
if response.status_code == 200:
401435
episode_count = response.json()
436+
print(f'ya counts: {episode_count}')
402437
return episode_count
403438
else:
439+
print("error")
404440
print("Error getting user episode count:", response.status_code)
405441
return None
406442

clients/linux-app/pinepods.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1513,8 +1513,7 @@ def view_pop(e):
15131513
page.go(top_view.route)
15141514

15151515
def open_poddisplay(e):
1516-
pr_instance.touch_stack()
1517-
page.update()
1516+
print('open poddisplay')
15181517
page.go("/poddisplay")
15191518

15201519
def open_settings(e):
@@ -3353,6 +3352,8 @@ def stop_monitoring(self):
33533352
active_user.user_id, clicked_podcast.name)
33543353
# Creating attributes for page layout
33553354
# First Podcast Info
3355+
pr_instance.touch_stack()
3356+
page.update()
33563357
display_pod_art_no = secrets.SystemRandom().randint(1, 12)
33573358
display_pod_art_fallback = os.path.join('/pinepods', "images", "logo_random", f"{display_pod_art_no}.jpeg")
33583359
display_pod_art_url = clicked_podcast.artwork if clicked_podcast.artwork else display_pod_art_fallback
@@ -3888,7 +3889,6 @@ def map_search_result(result, source):
38883889

38893890
user_ep_count = api_functions.functions.call_get_user_episode_count(app_api.url, app_api.headers,
38903891
active_user.user_id)
3891-
38923892
user_title = ft.Text(f"Stats for {active_user.fullname}:", size=20, weight="bold")
38933893
date_display = ft.Text(f'{active_user.username} created on {stats_created_date}', size=16)
38943894
pods_played_display = ft.Text(f'{stats_pods_played} Podcasts listened to', size=16)

completed_todos.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
This is the list of previous todos that are now completed
44

5+
Version 0.4.1
6+
7+
- [x] Fixed issue where get_user_episode_count wasn't displaying episode numbers. There was a syntax error in the api call
8+
- [x] Added /api/data/podcast_episodes and /api/data/get_podcast_id api calls. These are needed for Pinepods Firewood
9+
10+
511
Version 0.4
612

713
- [x] Unlock api creation for standard users - The API has been completely re-written to follow along the permissions that users actually have. Meaning users can easily request their own api keys and sign into the client with admin consent

database_functions/functions.py

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,53 @@ def return_episodes(database_type, cnx, user_id):
301301

302302
return rows
303303

304+
def return_podcast_episodes(database_type, cnx, user_id, podcast_id):
305+
if database_type == "postgresql":
306+
cursor = cnx.cursor(cursor_factory=RealDictCursor)
307+
else: # Assuming MariaDB/MySQL if not PostgreSQL
308+
cursor = cnx.cursor(dictionary=True)
309+
310+
query = (f"SELECT Podcasts.PodcastID, Podcasts.PodcastName, Episodes.EpisodeID, Episodes.EpisodeTitle, Episodes.EpisodePubDate, "
311+
f"Episodes.EpisodeDescription, Episodes.EpisodeArtwork, Episodes.EpisodeURL, Episodes.EpisodeDuration, "
312+
f"UserEpisodeHistory.ListenDuration "
313+
f"FROM Episodes "
314+
f"INNER JOIN Podcasts ON Episodes.PodcastID = Podcasts.PodcastID "
315+
f"LEFT JOIN UserEpisodeHistory ON Episodes.EpisodeID = UserEpisodeHistory.EpisodeID AND UserEpisodeHistory.UserID = %s "
316+
f"WHERE Podcasts.PodcastID = %s "
317+
f"AND Podcasts.UserID = %s "
318+
f"ORDER BY Episodes.EpisodePubDate DESC")
319+
320+
cursor.execute(query, (user_id, podcast_id, user_id))
321+
rows = cursor.fetchall()
322+
323+
cursor.close()
324+
325+
if not rows:
326+
return None
327+
328+
return rows
329+
330+
def get_podcast_id(database_type, cnx, user_id, podcast_feed):
331+
if database_type == "postgresql":
332+
cursor = cnx.cursor(cursor_factory=RealDictCursor)
333+
else: # Assuming MariaDB/MySQL if not PostgreSQL
334+
cursor = cnx.cursor(dictionary=True)
335+
336+
# Adjusted query to select only the PodcastID based on FeedURL and UserID
337+
query = (f"SELECT PodcastID "
338+
f"FROM Podcasts "
339+
f"WHERE FeedURL = %s AND UserID = %s")
340+
341+
cursor.execute(query, (podcast_feed, user_id))
342+
row = cursor.fetchone() # Fetching only one row as we expect a single result
343+
344+
cursor.close()
345+
346+
if not row:
347+
return None
348+
349+
return row['PodcastID'] # Assuming the column name is 'PodcastID'
350+
304351

305352
def delete_podcast(cnx, url, title, user_id):
306353
cursor = cnx.cursor()
@@ -376,7 +423,7 @@ def return_pods(database_type, cnx, user_id):
376423
else: # Assuming MariaDB/MySQL if not PostgreSQL
377424
cursor = cnx.cursor(dictionary=True)
378425

379-
query = ("SELECT PodcastName, ArtworkURL, Description, EpisodeCount, WebsiteURL, FeedURL, Author, Categories "
426+
query = ("SELECT PodcastID, PodcastName, ArtworkURL, Description, EpisodeCount, WebsiteURL, FeedURL, Author, Categories "
380427
"FROM Podcasts "
381428
"WHERE UserID = %s")
382429

@@ -2475,4 +2522,4 @@ def restore_server(cnx, database_pass, server_restore_data):
24752522
if process.returncode != 0:
24762523
raise Exception(f"Restoration failed with error: {stderr.decode()}")
24772524

2478-
return "Restoration completed successfully!"
2525+
return "Restoration completed successfully!"

0 commit comments

Comments
 (0)