sunng / ExaileDoubanCovers (http://classicning.com/)
Exaile plugin which retrieves album covers from douban.com
$ hg clone http://bitbucket.org/sunng/exailedoubancovers/
| commit 4: | d13005d965df |
| parent 3: | d1e7c8385508 |
| branch: | default |
| tags: | tip |
Changed (Δ8.0 KB):
PLUGININFO (2 lines added, 2 lines removed)
__init__.py (9 lines added, 2 lines removed)
doubanprefs.py (37 lines added, 0 lines removed)
doubanprefs_pane.glade (80 lines added, 0 lines removed)
doubanprefs_pane.ui (81 lines added, 0 lines removed)
doubanquery.py (7 lines added, 4 lines removed)
1 |
Version='0.0. |
|
1 |
Version='0.0.2' |
|
2 |
2 |
Authors=['Sun Ning <classicning@gmail.com>'] |
3 |
Name= |
|
3 |
Name=_('Douban Covers') |
|
4 |
4 |
Description='Load album cover from http://www.douban.com/music/' |
5 |
5 |
| … | … | @@ -24,10 +24,11 @@ import hashlib |
24 |
24 |
import time |
25 |
25 |
import os |
26 |
26 |
from xl.cover import * |
27 |
from xl import event, common |
|
27 |
from xl import event, common, settings |
|
28 |
28 |
import logging |
29 |
29 |
|
30 |
30 |
import doubanquery |
31 |
import doubanprefs |
|
31 |
32 |
|
32 |
33 |
logger = logging.getLogger(__name__) |
33 |
34 |
|
| … | … | @@ -44,6 +45,9 @@ def _enable(eventname, exaile, nothing): |
44 |
45 |
exaile.covers.add_search_method( |
45 |
46 |
DoubanCoverSearch() |
46 |
47 |
) |
48 |
||
49 |
def get_prefs_pane(): |
|
50 |
return doubanprefs |
|
47 |
51 |
|
48 |
52 |
class DoubanCoverSearch(CoverSearchMethod): |
49 |
53 |
""" |
| … | … | @@ -64,8 +68,11 @@ class DoubanCoverSearch(CoverSearchMetho |
64 |
68 |
if waittime > 0: time.sleep(waittime) |
65 |
69 |
self.starttime = time.time() |
66 |
70 |
|
71 |
apikey = settings.get_option('plugin/doubancovers/api_key', None) |
|
72 |
logger.info(apikey) |
|
73 |
||
67 |
74 |
try: |
68 |
cover_urls = list(doubanquery.search(search |
|
75 |
cover_urls = list(doubanquery.search(search, apikey)) |
|
69 |
76 |
logger.info(cover_urls or "no url from douban") |
70 |
77 |
if len(cover_urls) == 0: |
71 |
78 |
raise NoCoverFoundException() |
Up to file-list doubanprefs.py:
1 |
#! /usr/bin/env python |
|
2 |
# |
|
3 |
# |
|
4 |
# Sun Ning(classicning@gmail.com, http://www.classicning.com) |
|
5 |
# |
|
6 |
# This program is free software; you can redistribute it and/or modify |
|
7 |
# it under the terms of the GNU General Public License as published by |
|
8 |
# the Free Software Foundation; either version 1, or (at your option) |
|
9 |
# any later version. |
|
10 |
# |
|
11 |
# This program is distributed in the hope that it will be useful, |
|
12 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
14 |
# GNU General Public License for more details. |
|
15 |
# |
|
16 |
# You should have received a copy of the GNU General Public License |
|
17 |
# along with this program; if not, write to the Free Software |
|
18 |
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|
19 |
||
20 |
||
21 |
import os |
|
22 |
from xlgui.prefs import widgets |
|
23 |
from xl.nls import gettext as _ |
|
24 |
from xl import xdg |
|
25 |
import logging |
|
26 |
||
27 |
logger = logging.getLogger(__name__) |
|
28 |
||
29 |
name = _('Douban Covers') |
|
30 |
basedir = os.path.dirname(os.path.realpath(__file__)) |
|
31 |
glade = os.path.join(basedir, 'doubanprefs_pane.glade') |
|
32 |
||
33 |
||
34 |
class DoubanAPIKeyPreference(widgets.PrefsItem): |
|
35 |
default = '' |
|
36 |
name = 'plugin/doubancovers/api_key' |
|
37 |
Up to file-list doubanprefs_pane.glade:
1 |
<?xml version="1.0"?> |
|
2 |
<glade-interface> |
|
3 |
<!-- interface-requires gtk+ 2.16 --> |
|
4 |
<!-- interface-naming-policy project-wide --> |
|
5 |
<widget class="GtkWindow" id="prefs_window"> |
|
6 |
<child> |
|
7 |
<widget class="GtkVBox" id="prefs_pane"> |
|
8 |
<property name="visible">True</property> |
|
9 |
<property name="border_width">3</property> |
|
10 |
<property name="orientation">vertical</property> |
|
11 |
<property name="spacing">3</property> |
|
12 |
<child> |
|
13 |
<widget class="GtkLabel" id="label2"> |
|
14 |
<property name="visible">True</property> |
|
15 |
<property name="xalign">0</property> |
|
16 |
<property name="yalign">0</property> |
|
17 |
<property name="label" translatable="yes">Your are suggested to use an api key to search and fetch |
|
18 |
album covers. However it is totally optional if your request |
|
19 |
frequency is limited to 10 times per minute.</property> |
|
20 |
</widget> |
|
21 |
<packing> |
|
22 |
<property name="expand">False</property> |
|
23 |
<property name="position">0</property> |
|
24 |
</packing> |
|
25 |
</child> |
|
26 |
<child> |
|
27 |
<widget class="GtkTable" id="table1"> |
|
28 |
<property name="visible">True</property> |
|
29 |
<property name="n_columns">2</property> |
|
30 |
<property name="column_spacing">5</property> |
|
31 |
<child> |
|
32 |
<widget class="GtkLabel" id="label1"> |
|
33 |
<property name="visible">True</property> |
|
34 |
<property name="xalign">0</property> |
|
35 |
<property name="yalign">0.4699999988079071</property> |
|
36 |
<property name="label" translatable="yes">Douban API Key: </property> |
|
37 |
</widget> |
|
38 |
<packing> |
|
39 |
<property name="x_options">GTK_FILL</property> |
|
40 |
<property name="y_options"></property> |
|
41 |
</packing> |
|
42 |
</child> |
|
43 |
<child> |
|
44 |
<widget class="GtkEntry" id="plugin/doubancovers/api_key"> |
|
45 |
<property name="visible">True</property> |
|
46 |
<property name="can_focus">True</property> |
|
47 |
<property name="invisible_char">●</property> |
|
48 |
</widget> |
|
49 |
<packing> |
|
50 |
<property name="left_attach">1</property> |
|
51 |
<property name="right_attach">2</property> |
|
52 |
<property name="y_options">GTK_FILL</property> |
|
53 |
</packing> |
|
54 |
</child> |
|
55 |
</widget> |
|
56 |
<packing> |
|
57 |
<property name="position">1</property> |
|
58 |
</packing> |
|
59 |
</child> |
|
60 |
<child> |
|
61 |
<widget class="GtkLinkButton" id="linkbutton1"> |
|
62 |
<property name="label" translatable="yes">Get You Own Douban API Key</property> |
|
63 |
<property name="visible">True</property> |
|
64 |
<property name="can_focus">True</property> |
|
65 |
<property name="receives_default">True</property> |
|
66 |
<property name="relief">none</property> |
|
67 |
<property name="image_position">bottom</property> |
|
68 |
<property name="uri">http://www.douban.com/service/apikey/apply</property> |
|
69 |
</widget> |
|
70 |
<packing> |
|
71 |
<property name="expand">False</property> |
|
72 |
<property name="fill">False</property> |
|
73 |
<property name="padding">5</property> |
|
74 |
<property name="position">2</property> |
|
75 |
</packing> |
|
76 |
</child> |
|
77 |
</widget> |
|
78 |
</child> |
|
79 |
</widget> |
|
80 |
</glade-interface> |
Up to file-list doubanprefs_pane.ui:
1 |
<?xml version="1.0"?> |
|
2 |
<interface> |
|
3 |
<requires lib="gtk+" version="2.16"/> |
|
4 |
<!-- interface-naming-policy toplevel-contextual --> |
|
5 |
<object class="GtkWindow" id="prefs_window"> |
|
6 |
<child> |
|
7 |
<object class="GtkVBox" id="prefs_pane"> |
|
8 |
<property name="visible">True</property> |
|
9 |
<property name="border_width">3</property> |
|
10 |
<property name="orientation">vertical</property> |
|
11 |
<property name="spacing">3</property> |
|
12 |
<child> |
|
13 |
<object class="GtkLabel" id="label2"> |
|
14 |
<property name="visible">True</property> |
|
15 |
<property name="xalign">0</property> |
|
16 |
<property name="yalign">0</property> |
|
17 |
<property name="label" translatable="yes">Your are suggested to use an api key to search and fetch |
|
18 |
album covers. However it is totally optional if your request |
|
19 |
frequency is limited to 10 times per minute.</property> |
|
20 |
</object> |
|
21 |
<packing> |
|
22 |
<property name="expand">False</property> |
|
23 |
<property name="position">0</property> |
|
24 |
</packing> |
|
25 |
</child> |
|
26 |
<child> |
|
27 |
<object class="GtkTable" id="table1"> |
|
28 |
<property name="visible">True</property> |
|
29 |
<property name="n_columns">2</property> |
|
30 |
<property name="n_rows">1</property> |
|
31 |
<property name="column_spacing">5</property> |
|
32 |
<child> |
|
33 |
<object class="GtkLabel" id="label1"> |
|
34 |
<property name="visible">True</property> |
|
35 |
<property name="xalign">0</property> |
|
36 |
<property name="yalign">0.4699999988079071</property> |
|
37 |
<property name="label" translatable="yes">Douban API Key: </property> |
|
38 |
</object> |
|
39 |
<packing> |
|
40 |
<property name="x_options">GTK_FILL</property> |
|
41 |
<property name="y_options"></property> |
|
42 |
</packing> |
|
43 |
</child> |
|
44 |
<child> |
|
45 |
<object class="GtkEntry" id="plugin/doubancovers/api_key"> |
|
46 |
<property name="visible">True</property> |
|
47 |
<property name="can_focus">True</property> |
|
48 |
<property name="invisible_char">●</property> |
|
49 |
</object> |
|
50 |
<packing> |
|
51 |
<property name="left_attach">1</property> |
|
52 |
<property name="right_attach">2</property> |
|
53 |
<property name="y_options">GTK_FILL</property> |
|
54 |
</packing> |
|
55 |
</child> |
|
56 |
</object> |
|
57 |
<packing> |
|
58 |
<property name="position">1</property> |
|
59 |
</packing> |
|
60 |
</child> |
|
61 |
<child> |
|
62 |
<object class="GtkLinkButton" id="linkbutton1"> |
|
63 |
<property name="label" translatable="yes">Get You Own Douban API Key</property> |
|
64 |
<property name="visible">True</property> |
|
65 |
<property name="can_focus">True</property> |
|
66 |
<property name="receives_default">True</property> |
|
67 |
<property name="relief">none</property> |
|
68 |
<property name="image_position">bottom</property> |
|
69 |
<property name="uri">http://www.douban.com/service/apikey/apply</property> |
|
70 |
</object> |
|
71 |
<packing> |
|
72 |
<property name="expand">False</property> |
|
73 |
<property name="fill">False</property> |
|
74 |
<property name="padding">5</property> |
|
75 |
<property name="position">2</property> |
|
76 |
</packing> |
|
77 |
</child> |
|
78 |
</object> |
|
79 |
</child> |
|
80 |
</object> |
|
81 |
</interface> |
Up to file-list doubanquery.py:
| … | … | @@ -27,11 +27,14 @@ reload(sys) |
27 |
27 |
sys.setdefaultencoding("utf-8") |
28 |
28 |
logger = logging.getLogger(__name__) |
29 |
29 |
|
30 |
apikey="0de816503ce01deb29b842f0b6a059c1" |
|
31 |
urltemplate="http://api.douban.com/music/subjects?q=%s&max-results=5&apikey=%s&alt=json"; |
|
32 |
def search(key |
|
30 |
def search(key, apikey=None): |
|
33 |
31 |
quoted = urllib.quote(key.encode("utf8")) |
34 |
|
|
32 |
urltemplate="http://api.douban.com/music/subjects?q=%s&max-results=5&alt=json" |
|
33 |
query = urltemplate %(quoted) |
|
34 |
||
35 |
if apikey: |
|
36 |
urltemplate += ("&api_key=%s" % apikey) |
|
37 |
||
35 |
38 |
h = urllib.urlopen(query) |
36 |
39 |
data = h.read() |
37 |
40 |
