20:fc0904a91aea default tip
Anton Shestakov <engored@ya.ru>, Sat, 29 Nov 2014 13:29:52 +0800
find-closest: something about ok and fail

previous change 16:2a4c890a667a

youtube-watch/watch.py

Permissions: -rw-r--r--

Other formats: Feeds:
import subprocess
import sys
from argparse import ArgumentParser, FileType
from calendar import timegm
from contextlib import contextmanager
from operator import itemgetter
from time import localtime, sleep, strftime
import feedparser
def user_entries(user):
url = 'https://gdata.youtube.com/feeds/api/users/%s/uploads?v=2' % user
feed = feedparser.parse(url)
return feed['entries']
def prepare_entries(entries, limit=None):
entries = sorted(entries, key=itemgetter('published_parsed'))
if limit is not None:
entries = entries[-limit:]
return entries
def formatter(template, entries):
for entry in entries:
entry['link'] = entry['link'].replace('&feature=youtube_gdata', '')
entry['published_nice'] = strftime('%Y-%m-%d %H:%M:%S', localtime(timegm(entry['published_parsed'])))
print template.format(**entry)
def get_template(candidate):
if candidate is None:
return templates['default']
elif candidate in templates:
return templates[candidate]
else:
return candidate.decode('utf-8')
templates = {
'default': u'{link:<43} | {published_nice:<19} | {author:<25} | {title}',
'long': u'{title}\nBy {author} ({link})'
}
@contextmanager
def activity_status(msg):
sys.stderr.write(msg)
sys.stderr.flush()
yield
sys.stderr.write('\r' + ' ' * len(msg) + '\r')
sys.stderr.flush()
def fetch_entries(users, delay=0):
entries = []
for user in users:
if delay:
msg = 'Sleeping for %s' % delay
with activity_status(msg):
sleep(delay)
msg = 'Fetching entries for %s' % user
with activity_status(msg):
entries += user_entries(user)
return entries
def download(entries):
if entries:
subprocess.call(['cclive', '--continue', '--timestamp', '--stream', 'best'] + [entry['link'] for entry in entries])
def identify(entry):
return entry['id'].rpartition(':')[2]
def main():
parser = ArgumentParser()
parser.add_argument('-U', '--user', action='append', dest='users', help='author of uploads', metavar='USER [+]')
parser.add_argument('-F', '--input-file', type=FileType('r'), help='file with users')
parser.add_argument('-T', '--template', help='template for python .format()')
parser.add_argument('-l', '--limit', type=int, help='limit number of initial videos')
parser.add_argument('-f', '--follow', action='store_true', help='continuous mode')
parser.add_argument('-d', '--delay', type=int, help='delay for continuous mode', default=60)
parser.add_argument('-D', '--download', action='store_true', help='download each video')
args = parser.parse_args()
template = get_template(args.template)
users = args.users or []
if args.input_file is not None:
users += args.input_file.read().splitlines()
entries = fetch_entries(users)
earlier = {identify(entry) for entry in entries}
entries = prepare_entries(entries, args.limit)
formatter(template, entries)
if args.download:
download(entries)
if not args.follow:
return
try:
while True:
entries = fetch_entries(users, args.delay)
new_entries = [entry for entry in entries if identify(entry) not in earlier]
earlier |= {identify(entry) for entry in new_entries}
new_entries = prepare_entries(new_entries)
formatter(template, new_entries)
if args.download:
download(new_entries)
except KeyboardInterrupt:
print
if __name__ == '__main__':
main()