Skip to content
This repository has been archived by the owner on Jun 12, 2021. It is now read-only.

Commit

Permalink
Merge pull request #4 from cgomesu/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
cgomesu committed Sep 24, 2020
2 parents 2a4bb0c + b0f2ee5 commit d7b8e03
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 77 deletions.
53 changes: 27 additions & 26 deletions youtube4tvh/lib/youtubehandler.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/python3
# Purpose: Save a Youtube live-stream to an M3U playlist
# Author: cgomesu
# Date: September 14th, 2020
# Date: September 24th, 2020
# Disclaimer: Use at your own discretion.
# Be mindful of the API daily quota.
# The author does not provide any sort warranty whatsoever.
Expand All @@ -22,14 +22,6 @@ class YoutubeHandlerNoAPI:
'viewer_digits': re.compile(r'\d*'),
}

@staticmethod
def write_debug(filename='debug.txt', content=None):
content = 'NA' if not content else content.encode('utf-8')
if not isinstance(content, str):
content = str(content)
with open(filename, 'w') as f:
f.write(content)

def __init__(self, channelid, channelname, channellogo):
self.channelname = channelname
self.channelid = channelid
Expand Down Expand Up @@ -102,14 +94,20 @@ def find_chinfo(self):
# extract info from the FIRST search result
data_item = data_list['contents'][section_index]['itemSectionRenderer']
self.channelid = data_item['contents'][item_index]['channelRenderer']['channelId']
self.channellogo = 'https:{}'.format(
data_item['contents'][item_index]['channelRenderer']['thumbnail']['thumbnails'][0]['url'])
# get thumbnail with highest quality
highest_width, thumb_index = -1, 0
if 'thumbnails' in data_item['contents'][item_index]['channelRenderer']['thumbnail'].keys():
for k, thumb in enumerate(data_item['contents'][item_index]['channelRenderer']['thumbnail']['thumbnails']):
current_width = thumb['width']
if current_width > highest_width:
highest_width, thumb_index = current_width, k
data_item_thumb = data_item['contents'][item_index]['channelRenderer']['thumbnail']['thumbnails'][thumb_index]
self.channellogo = data_item_thumb['url'] if 'https' in data_item_thumb['url'] else 'https:{}'.format(
data_item_thumb['url']
)
return self.channelid, self.channellogo
except Exception as err:
print('There was an error while parsing the request: {}'.format(err))
# save req to a file for debugging
self.write_debug(filename='debug_{}.txt'.format(self.channelname.replace(' ', '_')),
content=req.text)
return None, None

def find_stream(self):
Expand Down Expand Up @@ -150,23 +148,27 @@ def find_stream(self):
data = json.loads(find_data[0])
data_tabs = data['contents']['twoColumnBrowseResultsRenderer']['tabs']
data_videos = {}
for index, tab in enumerate(data_tabs):
if 'Videos' in tab['tabRenderer']['title']:
data_videos = data_tabs[index]
break
for i, tab in enumerate(data_tabs):
if 'tabRenderer' in tab.keys():
tab_title = tab['tabRenderer']['title']
if 'Videos' in tab_title:
data_videos = data_tabs[i]
break
if not data_videos:
raise Exception('Videos section not found in get request.')
data_videos_list = data_videos['tabRenderer']['content']['sectionListRenderer']
data_videos_item = data_videos_list['contents'][0]['itemSectionRenderer']
data_videos_item_video = data_videos_item['contents'][0]['gridRenderer']['items']
# TODO: make sure the video is a livestream and not a VOD
# selection method for channels with multiple livestreams
# select livestream with the highest number of viewers
highest_viewers, highest_index = -1, 0
for index, item in enumerate(data_videos_item_video):
if 'viewCountText' in item['gridVideoRenderer'].keys():
found_live = False
for j, item in enumerate(data_videos_item_video):
# video has a view counter and is not a VOD
if 'viewCountText' in item['gridVideoRenderer'].keys() \
and 'publishedTimeText' not in item['gridVideoRenderer'].keys():
found_live = True
# extract only digits from viewers count
current_index = index
viewer_digits = re.match(
self.regex_dict['viewer_digits'],
item['gridVideoRenderer']['viewCountText']['runs'][0]['text'].replace(',', '')
Expand All @@ -177,7 +179,9 @@ def find_stream(self):
# assume 0 viewer if unable to find digits
current_viewers = int(viewer_digits.group()) if viewer_digits.group() else 0
if current_viewers > highest_viewers:
highest_viewers, highest_index = current_viewers, current_index
highest_viewers, highest_index = current_viewers, j
if not found_live:
raise Exception('Unable to find a livestream for this channel right now.')
data_videos_item_video = data_videos_item_video[highest_index]['gridVideoRenderer']
# extract livestream URL from the video with the highest number of viewers or the first found (default)
video = {
Expand All @@ -194,9 +198,6 @@ def find_stream(self):
return video
except Exception as err:
print('There was an error while trying to retrieve the videoId from the live-stream: {}'.format(err))
# save req to a file for debugging
self.write_debug(filename='debug_{}.txt'.format(self.channelname.replace(' ', '_')),
content=req.text)
return None


Expand Down
4 changes: 2 additions & 2 deletions youtube4tvh/main.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/python3
# Purpose: Save a Youtube live-stream to an M3U playlist
# Author: cgomesu
# Date: September 14th, 2020
# Date: September 24th, 2020
# Disclaimer: Use at your own discretion.
# Be mindful of the API daily quota.
# The author does not provide any sort warranty whatsoever.
Expand Down Expand Up @@ -169,7 +169,7 @@ def update_stream():
print('[INFO] Updating channel: {}...'.format(channel))
print('##############################################')
args_cli['channelname'], args_cli['channelid'], args_cli['channellogo'] = channel, '', ''
# TODO: improve the way errors are handled (retry then change request method)
# TODO: improve the way errors are handled (e.g., try with /channelid/live)
try:
add_stream()
except Exception:
Expand Down
Loading

0 comments on commit d7b8e03

Please sign in to comment.