2 # -*- coding: utf-8 -*-
5 # gPodder - A media aggregator and podcast client
6 # Copyright (c) 2005-2010 Thomas Perl and the gPodder Team
8 # gPodder is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 3 of the License, or
11 # (at your option) any later version.
13 # gPodder is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with this program. If not, see <http://www.gnu.org/licenses/>.
23 # gpo - A better command-line interface to gPodder using the gPodder API
24 # by Thomas Perl <thp@gpodder.org>; 2009-05-07
28 Usage: gpo [COMMAND] [params...]
30 Subscription management
31 -----------------------
33 subscribe URL [TITLE] Subscribe to a new feed at URL (as TITLE)
34 rename URL TITLE Rename feed at URL to TITLE
35 unsubscribe URL Unsubscribe from feed at URL
37 info URL Show information about feed at URL
38 list List all subscribed podcasts
39 update Refresh all feeds (check for new episodes)
44 download [URL] Download all new (=pending) episodes; if
45 URL is an episode URL, download only one
46 episode; if it's a channel URL, download
47 all pending episodes from that channel
48 pending [URL] Show episodes that are marked as new; if
49 URL is given, show only pending downloads
50 from the channel at this URL
51 queue URL Add episode at URL to pending episodes
52 skip URL Remove episode at URL from pending episodes
54 details URL Show information about episode at URL
55 episodes [URL] Show a list of all episodes; if URL is given
56 it should be a channel URL and only episodes
57 from that channel will be displayed
59 delete URL Delete the downloaded episode at URL
61 Portable device synchronization
62 -------------------------------
64 device Show information about your device
65 sync Synchronize downloaded episodes to device
70 youtube resolve [URL] Resolve the YouTube URL to a download URL
71 youtube download [URL] Download a video from YouTube via its URL
79 gpodder_script
= sys
.argv
[0]
80 if os
.path
.islink(gpodder_script
):
81 gpodder_script
= os
.readlink(gpodder_script
)
82 gpodder_dir
= os
.path
.join(os
.path
.dirname(gpodder_script
), '..')
83 prefix
= os
.path
.abspath(os
.path
.normpath(gpodder_dir
))
85 src_dir
= os
.path
.join(prefix
, 'src')
86 data_dir
= os
.path
.join(prefix
, 'data')
88 if os
.path
.exists(src_dir
) and os
.path
.exists(data_dir
) and \
89 not prefix
.startswith('/usr'):
90 # Run gPodder from local source folder (not installed)
91 sys
.path
.insert(0, src_dir
)
97 # Use only the gPodder API here, so this serves both as an example
98 # and as a motivation to provide all functionality in the API :)
99 from gpodder
import api
103 class gPodderCli(object):
105 self
.client
= api
.PodcastClient()
107 # -------------------------------------------------------------------
109 def subscribe(self
, url
, title
=None):
110 if self
.client
.get_podcast(url
) is not None:
111 self
._info
(_('You are already subscribed to %s.' % url
))
114 if self
.client
.create_podcast(url
, title
) is None:
115 self
._error
(_('Cannot download feed for %s.') % url
)
120 self
._info
(_('Successfully added %s.' % url
))
123 def rename(self
, url
, title
):
124 podcast
= self
.client
.get_podcast(url
)
127 self
._error
(_('You are not subscribed to %s.') % url
)
129 old_title
= podcast
.title
130 podcast
.rename(title
)
132 self
._info
(_('Renamed %s to %s.') % (old_title
, title
))
136 def unsubscribe(self
, url
):
137 podcast
= self
.client
.get_podcast(url
)
140 self
._error
(_('You are not subscribed to %s.') % url
)
144 self
._error
(_('Unsubscribed from %s.') % url
)
149 podcast
= self
.client
.get_podcast(url
)
152 self
._error
(_('You are not subscribed to %s.') % url
)
154 title
, url
= podcast
.title
, podcast
.url
155 def status_str(episode
):
158 if episode
.is_downloaded
:
160 if episode
.is_deleted
:
165 episodes
= ('%3d. %s %s' % (i
+1, status_str(e
), e
.title
) for i
, e
in enumerate(podcast
.get_episodes()))
166 episodes
= '\n '.join(episodes
)
167 print >>sys
.stdout
, """
178 for podcast
in self
.client
.get_podcasts():
184 for podcast
in self
.client
.get_podcasts():
185 print 'Updating', podcast
.title
193 for podcast
in self
.client
.get_podcasts():
194 podcast_printed
= False
195 for episode
in podcast
.get_episodes():
197 if not podcast_printed
:
199 podcast_printed
= True
200 print ' ', episode
.title
203 print count
, 'episodes pending.'
208 for podcast
in self
.client
.get_podcasts():
209 podcast_printed
= False
210 for episode
in podcast
.get_episodes():
212 if not podcast_printed
:
214 podcast_printed
= True
215 print ' ', episode
.title
219 print count
, 'episodes downloaded.'
223 self
.client
.synchronize_device()
226 # -------------------------------------------------------------------
228 def _error(self
, *args
):
229 print >>sys
.stderr
, ' '.join(args
)
231 def _info(self
, *args
):
232 print >>sys
.stdout
, ' '.join(args
)
234 def _checkargs(self
, func
, command_line
):
235 args
, varargs
, keywords
, defaults
= inspect
.getargspec(func
)
236 args
.pop(0) # Remove "self" from args
237 defaults
= defaults
or ()
238 minarg
, maxarg
= len(args
)-len(defaults
), len(args
)
240 if len(command_line
) < minarg
or len(command_line
) > maxarg
:
241 self
._error
('Wrong argument count for %s.' % func
.__name
__)
244 return func(*command_line
)
247 def _parse(self
, command_line
):
251 command
= command_line
.pop(0)
252 if command
.startswith('_'):
253 self
._error
(_('This command is not available.'))
256 for name
, func
in inspect
.getmembers(self
):
257 if inspect
.ismethod(func
) and name
== command
:
258 return self
._checkargs
(func
, command_line
)
263 if __name__
== '__main__':
265 cli
._parse
(sys
.argv
[1:]) or sys
.stderr
.write(__doc__
)