1import re 2from .pafy import call_gdata 3from .playlist import Playlist 4from .backend_shared import pyver 5 6 7def get_channel(channel_url, basic=False, gdata=False, 8 size=False, callback=None): 9 """Return a Channel object 10 11 The returned Pafy and Playlist objects are initialised using the arguments 12 to get_channel() in the manner documented for pafy.new() 13 14 """ 15 16 return Channel.from_url(channel_url, basic, gdata, size, callback) 17 18 19class Channel(object): 20 def __init__(self, channel_url, basic, gdata, size, callback): 21 22 self._channel_url = channel_url 23 self._channel_id = None 24 self._title = None 25 self._description = None 26 self._logo = None 27 self._subscriberCount = None 28 self._uploads = None 29 self._basic = basic 30 self._gdata = gdata 31 self._size = size 32 self._callback = callback 33 self._playlists = None 34 self._subscriptions = None 35 self._have_basic = False 36 37 @classmethod 38 def from_dict(cls, ch, basic, gdata, size, callback): 39 t = cls(ch['id'], basic, gdata, size, callback) 40 t._channel_id = ch['id'] 41 t._title = ch['title'] 42 t._description = ch['description'] 43 t._logo = ch['logo'] 44 t._subscriberCount = ch['subscriberCount'] 45 t._uploads = ch['uploads'] 46 t._have_basic = True 47 48 return t 49 50 @classmethod 51 def from_url(cls, url, basic, gdata, size, callback): 52 t = cls(url, basic, gdata, size, callback) 53 t._fetch_basic() 54 return t 55 56 @property 57 def channel_id(self): 58 if not self._have_basic: 59 self._fetch_basic() 60 return self._channel_id 61 62 @property 63 def title(self): 64 if not self._have_basic: 65 self._fetch_basic() 66 return self._title 67 68 @property 69 def description(self): 70 if not self._have_basic: 71 self._fetch_basic() 72 return self._description 73 74 @property 75 def logo(self): 76 if not self._have_basic: 77 self._fetch_basic() 78 return self._logo 79 80 @property 81 def subscriberCount(self): 82 if not self._have_basic: 83 self._fetch_basic() 84 return self._subscriberCount 85 86 @property 87 def uploads(self): 88 if not self._uploads: 89 self._fetch_basic() 90 if type(self._uploads) != Playlist: 91 self._uploads = Playlist.from_url(self._uploads, self._basic, 92 self._gdata, self._size, 93 self._callback) 94 95 return self._uploads 96 97 @property 98 def playlists(self): 99 if self._playlists is not None: 100 for playlist in self._playlists: 101 yield playlist 102 return 103 104 playlists = [] 105 106 query = {'part': 'snippet,contentDetails', 107 'maxResults': 50, 108 'channelId': self.channel_id} 109 110 while True: 111 playlistList = call_gdata('playlists', query) 112 113 for pl in playlistList['items']: 114 try: 115 thumbnail = pl['snippet']['thumbnails']['standard']['url'] 116 except KeyError: 117 thumbnail = None 118 pl_data = dict( 119 id=pl['id'], 120 title=pl['snippet']['title'], 121 author=pl['snippet']['channelTitle'], 122 description=pl['snippet']['description'], 123 thumbnail=thumbnail, 124 len=pl['contentDetails']['itemCount'] 125 ) 126 127 pl_obj = Playlist.from_dict(pl_data, self._basic, self._gdata, 128 self._size, self._callback) 129 playlists.append(pl_obj) 130 if self._callback: 131 self._callback("Added playlist: %s" % pl_data['title']) 132 yield pl_obj 133 134 if not playlistList.get('nextPageToken'): 135 break 136 query['pageToken'] = playlistList['nextPageToken'] 137 138 self._playlists = playlists 139 140 @property 141 def subscriptions(self): 142 if self._subscriptions is not None: 143 for sub in self._subscriptions: 144 yield sub 145 return 146 147 subscriptions = [] 148 query = {'part': 'snippet', 149 'maxResults': 50, 150 'channelId': self.channel_id} 151 152 while True: 153 subs_data = call_gdata('subscriptions', query) 154 sub_ids = [] 155 156 for sub in subs_data['items']: 157 sub_ids.append(sub['snippet']['resourceId']['channelId']) 158 159 query2 = {'part': 'snippet, contentDetails, statistics', 160 'id': ','.join(sub_ids), 161 'maxResults': 50} 162 163 data = call_gdata('channels', query2) 164 165 for ch in data['items']: 166 channel_data = dict( 167 id=ch['id'], 168 title=ch['snippet']['title'], 169 description=ch['snippet']['description'], 170 logo=ch['snippet']['thumbnails']['default']['url'], 171 subscriberCount=ch['statistics']['subscriberCount'], 172 uploads=ch['contentDetails']['relatedPlaylists']['uploads'] 173 ) 174 sub_obj = Channel.from_dict(channel_data, self._basic, 175 self._gdata, self._size, 176 self._callback) 177 subscriptions.append(sub_obj) 178 yield sub_obj 179 180 if not subs_data.get('nextPageToken'): 181 break 182 query['pageToken'] = subs_data['nextPageToken'] 183 184 self._subscriptions = subscriptions 185 186 def __repr__(self): 187 if not self._have_basic: 188 self._fetch_basic() 189 190 info = [("Type", "Channel"), 191 ("Title", self.title), 192 ("Description", self.description), 193 ("SubscriberCount", self.subscriberCount)] 194 195 nfo = "\n".join(["%s: %s" % i for i in info]) 196 197 return nfo.encode("utf8", "replace") if pyver == 2 else nfo 198 199 def _fetch_basic(self): 200 query = None 201 chanR = re.compile('.+channel\/([^\/]+)$') 202 userR = re.compile('.+user\/([^\/]+)$') 203 channel_id = None 204 channel_url = self._channel_url 205 if chanR.match(channel_url): 206 channel_id = chanR.search(channel_url).group(1) 207 elif userR.match(channel_url): 208 username = userR.search(channel_url).group(1) 209 query = {'part': 'snippet, contentDetails, statistics', 210 'forUsername': username} 211 elif len(channel_url) == 24 and channel_url[:2] == 'UC': 212 channel_id = channel_url 213 else: 214 username = channel_url 215 query = {'part': 'snippet, contentDetails, statistics', 216 'forUsername': username} 217 218 if query is None: 219 query = {'part': 'snippet, contentDetails, statistics', 220 'id': channel_id} 221 allinfo = call_gdata('channels', query) 222 223 try: 224 ch = allinfo['items'][0] 225 except IndexError: 226 err = "Unrecognized channel id, url or name : %s" 227 raise ValueError(err % channel_url) 228 229 self._channel_id = ch['id'] 230 self._title = ch['snippet']['title'] 231 self._description = ch['snippet']['description'] 232 self._logo = ch['snippet']['thumbnails']['default']['url'] 233 self._subscriberCount = ch['statistics']['subscriberCount'] 234 self._uploads = ch['contentDetails']['relatedPlaylists']['uploads'] 235 self._have_basic = True 236