Download:
child 16:2a4c890a667a
parent 14:26228d16d36a
15:0a64b0583576
Anton Shestakov <engored@ya.ru>, Thu, 25 Sep 2014 14:35:55 +0900
Youtube-watch script.

1 files changed, 103 insertions(+), 0 deletions(-) [+]
youtube-watch/watch.py file | annotate | diff | comparison | revisions
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/youtube-watch/watch.py Thu Sep 25 14:35:55 2014 +0900
@@ -0,0 +1,103 @@
+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 formatter(template, limit, entries):
+ entries = sorted(entries, key=itemgetter('published_parsed'))
+
+ if limit is not None:
+ entries = entries[-limit:]
+
+ 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 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)
+ 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)
+
+ formatter(template, args.limit, entries)
+
+ if not args.follow:
+ return
+
+ earlier = None
+
+ try:
+ while True:
+ if earlier is not None:
+ new_entries = [entry for entry in entries if entry['published_parsed'] > earlier]
+ formatter(template, None, new_entries)
+ earlier = max([entry['published_parsed'] for entry in entries])
+ entries = fetch_entries(users, args.delay)
+ except KeyboardInterrupt:
+ print
+
+
+if __name__ == '__main__':
+ main()