2022-02-26 09:35:58 +00:00
import typing as t
from requests import Session
from . models import BasePipedModel
from . models . comments import Comments
2022-02-26 18:02:26 +00:00
from . models . videos import Video
2022-02-28 08:24:59 +00:00
from . models . channels import NextPageChannel , Channel
2022-02-26 09:35:58 +00:00
2022-02-26 18:02:26 +00:00
_MDL = t . TypeVar ( ' _MDL ' , bound = t . Type [ BasePipedModel ] )
2022-02-26 09:35:58 +00:00
2022-02-27 17:20:42 +00:00
class APIError ( Exception ) : """ Raised when an API call fails """
2022-02-26 09:35:58 +00:00
class PipedClient :
"""
An API client for [ Piped ] ( https : / / piped . kavin . rocks ) .
2022-02-27 17:20:42 +00:00
See also [ Piped API docs ] ( https : / / piped - docs . kavin . rocks / docs )
2022-02-26 09:35:58 +00:00
"""
def __init__ ( self , base_api_url : str = ' https://pipedapi.kavin.rocks ' , session : t . Type [ Session ] = Session ( ) ) - > None :
"""
### Parameters:
- ` base_api_url ` - The base URL to the instance ' s API. Trailing slashes will be stripped.
- ` session ` - A class / subclass of ` requests . Session ` to use for all requests .
For example , you could use [ requests - cache ] ( https : / / pypi . org / project / requests - cache / ) to make all requests cacheable .
"""
self . base_api_url = base_api_url . strip ( " / " )
self . session = session
2022-02-28 08:24:59 +00:00
def _get_json ( self , uri : str , as_model : t . Optional [ _MDL ] = None , * * kwargs ) - > t . Union [ _MDL , t . Dict [ str , t . Any ] , t . List [ t . Any ] ] :
2022-02-26 09:35:58 +00:00
"""
Obtains JSON data from specific URI of the Piped API .
### Parameters:
- ` uri ` - The URI to get JSON data from
- ` as_model ` - The ` BasePipedModel ` to load the JSON data into . If this is ` None ` , the JSON data is returned as a ` dict ` .
- ` * * kwargs ` - Additional keyword arguments to pass to ` requests . Session . get `
"""
2022-02-27 17:21:46 +00:00
json : t . Union [ dict , list ] = self . session . get ( f " { self . base_api_url } { uri } " , * * kwargs ) . json ( )
2022-02-27 17:20:42 +00:00
2022-02-27 17:21:46 +00:00
if isinstance ( json , dict ) and json . get ( ' error ' , None ) is not None :
2022-02-27 17:20:42 +00:00
raise APIError ( f " Error: { json [ ' error ' ] } " )
2022-02-26 09:35:58 +00:00
if as_model is not None :
return as_model ( json )
return json
2022-02-28 08:24:59 +00:00
def get_video ( self , video_id : str , * * kwargs ) - > Video :
2022-02-26 09:35:58 +00:00
"""
2022-02-28 08:24:59 +00:00
Gets information about a specific video .
2022-02-26 09:35:58 +00:00
### Parameters:
2022-02-28 08:24:59 +00:00
- ` video_id ` - The ID of the video to get information for
2022-02-27 17:08:39 +00:00
- ` * * kwargs ` - Additional keyword arguments to pass to ` requests . Session . get `
2022-02-28 08:24:59 +00:00
[ Piped Documentation ] ( https : / / piped - docs . kavin . rocks / docs / api - documentation / #streamsvideoid)
"""
2022-02-26 18:02:26 +00:00
2022-02-28 08:24:59 +00:00
return self . _get_json ( f " /streams/ { video_id } " , Video , * * kwargs )
2022-02-26 18:02:26 +00:00
2022-02-28 08:24:59 +00:00
def get_comments ( self , video_id : str , nextpage : t . Optional [ t . Dict [ str , t . Optional [ str ] ] ] = None , * * kwargs ) - > Comments :
2022-02-26 18:02:26 +00:00
"""
2022-02-28 08:24:59 +00:00
Gets a list of comments for a specific video .
2022-02-26 18:02:26 +00:00
### Parameters:
2022-02-28 08:24:59 +00:00
- ` video_id ` - The ID of the video to get comments for
- ` nextpage ` - Nextpage data , obtained from ` . models . comments . Comments . nextpage ` property . If this is ` None ` , the first page of comments is returned .
There are often 20 comments per page .
2022-02-27 17:08:39 +00:00
- ` * * kwargs ` - Additional keyword arguments to pass to ` requests . Session . get `
2022-02-28 08:24:59 +00:00
[ Piped Documentation ] ( https : / / piped - docs . kavin . rocks / docs / api - documentation / #commentsvideoid)
2022-02-26 18:02:26 +00:00
"""
2022-02-28 08:24:59 +00:00
if nextpage is not None :
kwargs . update ( { ' params ' : { ' nextpage ' : nextpage } } )
return self . _get_json ( f " /nextpage/comments/ { video_id } " , Comments , * * kwargs )
return self . _get_json ( f " /comments/ { video_id } " , Comments , * * kwargs )
2022-02-27 07:40:58 +00:00
2022-02-27 17:08:39 +00:00
def get_trending ( self , country_code : str = ' US ' , * * kwargs ) - > t . List [ Video . RelatedStream ] :
2022-02-27 07:40:58 +00:00
"""
Obtains trending videos for a specific country . If there are no trending videos ( or ` country_code ` is invalid ) ,
an empty list is returned .
### Parameters:
- ` country_code ` - The country code ( [ ISO 3166 - 1 alpha - 2 ] ( https : / / en . wikipedia . org / wiki / ISO_3166 - 1 _alpha - 2 #Officially_assigned_code_elements)) to get trending videos for. This is automatically capitalized by this package,
since Piped for some reason doesn ' t accept lowercase country codes. Note: countries such as China or North Korea don ' t have trending videos , so they will always return an empty list .
2022-02-27 17:08:39 +00:00
- ` * * kwargs ` - Additional keyword arguments to pass to ` requests . Session . get `
2022-02-28 08:24:59 +00:00
[ Piped Documentation ] ( https : / / piped - docs . kavin . rocks / docs / api - documentation / #trending)
2022-02-27 17:08:39 +00:00
"""
2022-02-28 08:24:59 +00:00
kwargs . update ( { ' params ' : { ' region ' : country_code . upper ( ) } } )
2022-02-27 17:08:39 +00:00
2022-02-28 08:24:59 +00:00
return [ Video . RelatedStream ( trending_video ) for trending_video in self . _get_json ( f " /trending " , * * kwargs ) ]
2022-02-27 17:08:39 +00:00
2022-02-28 08:24:59 +00:00
def get_channel_by_id ( self , channel_id : str , nextpage : t . Optional [ t . Dict [ str , t . Optional [ str ] ] ] = None , * * kwargs ) - > t . Union [ NextPageChannel , Channel ] :
2022-02-27 17:08:39 +00:00
"""
2022-02-27 17:20:42 +00:00
Gets information about a specific channel by its ID .
2022-02-27 17:08:39 +00:00
### Parameters:
- ` channel_id ` - The ID of the channel to get information for
- ` * * kwargs ` - Additional keyword arguments to pass to ` requests . Session . get `
2022-02-28 08:24:59 +00:00
[ Piped Documentation ] ( https : / / piped - docs . kavin . rocks / docs / api - documentation / #channelchannelid)
2022-02-27 07:40:58 +00:00
"""
2022-02-28 08:24:59 +00:00
if nextpage is not None :
kwargs . update ( { ' params ' : { ' nextpage ' : nextpage } } )
return self . _get_json ( f " /nextpage/channel/ { channel_id } " , NextPageChannel , * * kwargs )
2022-02-27 17:20:42 +00:00
return self . _get_json ( f " /channel/ { channel_id } " , Channel , * * kwargs )
def get_channel_by_name ( self , channel_name : str , * * kwargs ) - > Channel :
"""
Gets information about a specific channel by its name .
### Parameters:
- ` channel_name ` - The name of the channel to get information for
- ` * * kwargs ` - Additional keyword arguments to pass to ` requests . Session . get `
2022-02-28 08:24:59 +00:00
[ Piped Documentation ] ( https : / / piped - docs . kavin . rocks / docs / api - documentation / #cname)
2022-02-27 17:20:42 +00:00
"""
return self . _get_json ( f " /c/ { channel_name } " , Channel , * * kwargs )
2022-02-28 08:24:59 +00:00
def get_search_suggestions ( self , search_query : str , * * kwargs ) - > t . List [ str ] :
"""
Obtains search suggestions for a query .
### Parameters:
- ` search_query ` - The query to get search suggestions for
- ` * * kwargs ` - Additional keyword arguments to pass to ` requests . Session . get `
[ Piped Documentation ] ( https : / / piped - docs . kavin . rocks / docs / api - documentation / #suggestions)
"""
kwargs . update ( { ' params ' : { ' query ' : search_query } } )
return self . _get_json ( f " /suggestions " , * * kwargs )