source: trunk/Update Podcasts/update_podcasts.py @ 489

Last change on this file since 489 was 489, checked in by Nicholas Riley, 11 years ago

iPod touch/iPhone podcast updater, now complete.

File size: 3.3 KB
Line 
1#!/usr/bin/python
2# -*- coding: utf-8 -*-
3
4from appscript import *
5from aem import AEEnum
6from itertools import izip
7import htmlentitydefs
8import re
9import time
10
11# based on <http://sebsauvage.net/python/snyppets/>
12RE_ENTITY_CHR = re.compile(u'&(%s);' % u'|'.join(htmlentitydefs.name2codepoint))
13RE_ENTITY_DEC = re.compile(u'&#(\d+);')
14RE_ENTITY_HEX = re.compile(u'&#x(\w+);')
15def decode_entities(s):
16    def entity2char(m):
17        entity = m.group(1)
18        if entity in htmlentitydefs.name2codepoint:
19            return unichr(htmlentitydefs.name2codepoint[entity])
20        return u' ' # Unknown entity: We replace with a space.
21    replaced = 0
22    s, n = RE_ENTITY_CHR.subn(entity2char, s)
23    replaced += n
24    s, n = RE_ENTITY_DEC.subn(lambda x: unichr(int(x.group(1))), s)
25    replaced += n
26    s, n = RE_ENTITY_HEX.subn(lambda x: unichr(int(x.group(1),16)), s)
27    replaced += n
28    return s, replaced
29
30OPEN_P = r'<[Pp][^>]*>'
31RE_OPEN_P = re.compile(OPEN_P)
32RE_MATCHED_P = re.compile(OPEN_P + r'(?!<[Pp])(.*)</[Pp]>')
33RE_TOO_MANY_CR = re.compile(r'\s*\n\s*\n\s*\n+', re.U)
34RE_TAG = re.compile(r'<[^>]*>')
35RE_WHITESPACE = re.compile(r'\s+', re.U)
36RE_LEADING_WHITESPACE = re.compile(r'^\s+(.*)', re.U)
37RE_TRAILING_WHITESPACE = re.compile(r'(.*)\s+$', re.U)
38
39def html_to_text(s):
40    s, replaced = decode_entities(s)
41    s = s.replace('\r\n', '\n')
42    s = s.replace('\r', '\n')
43    if replaced > 0 or RE_TAG.search(s): # HTML
44        s = RE_WHITESPACE.sub(' ', s)
45        s = RE_MATCHED_P.sub(r'\1\n\n', s)
46        s = RE_OPEN_P.sub(r'\n\n', s)
47        s = RE_TAG.sub('', s)
48        s = RE_TOO_MANY_CR.sub(r'\n\n', s)
49    s = RE_LEADING_WHITESPACE.sub(r'\1', s)
50    s = RE_TRAILING_WHITESPACE.sub(r'\1', s)
51    return s
52
53def podcasts_to_lyrics(iTunes):
54    podcasts = iTunes.tracks[its.podcast == True]
55
56    ids = podcasts.id()
57    descs = podcasts.description()
58    longdescs = podcasts.long_description()
59    lyricses = podcasts.lyrics()
60
61    for id_, desc, longdesc, lyrics in izip(ids, descs, longdescs, lyricses):
62        if lyrics == k.missing_value: # video
63            continue
64
65        if longdesc == k.missing_value:
66            if desc == k.missing_value:
67                continue
68            longdesc = desc
69        else:
70            longdesc = html_to_text(longdesc)
71
72        if lyrics == longdesc:
73            continue
74
75        iTunes.tracks[its.id == id_].lyrics.set(longdesc)
76
77def iTunes_main_pane():
78    return app(u'System Events').application_processes[u'iTunes'].windows[u'iTunes'].splitter_groups[1].scroll_areas[1]
79
80def wait_for_podcast_update(iTunes):
81    # show 'Podcasts'
82    iTunes.playlists[its.special_kind == AEEnum('kSpP')].reveal()
83    podcast_status = iTunes_main_pane().outlines[1].rows.static_texts[1].value
84    while u'queued for download' in podcast_status.get():
85        time.sleep(0.5)
86
87def wait_for_iPod_update(iTunes):
88    # show iPod
89    iTunes.sources[its.kind == AEEnum('kPod')].sources[1].library_playlists[1].reveal()
90    sync_enabled = iTunes_main_pane().buttons[u'Sync'].enabled
91    while sync_enabled.get() == False:
92        time.sleep(0.5)
93
94if __name__ == '__main__':
95    iTunes = app('iTunes')
96    iTunes.updateAllPodcasts() # start downloading
97    iTunes.update() # sync iPod
98    wait_for_iPod_update(iTunes)
99    iTunes.updateAllPodcasts()
100    wait_for_podcast_update(iTunes)
101    podcasts_to_lyrics(iTunes)
102    iTunes.update()
Note: See TracBrowser for help on using the repository browser.