sunng / ExaileDoubanCovers (http://classicning.com/)

Exaile plugin which retrieves album covers from douban.com

commit 4: d13005d965df
parent 3: d1e7c8385508
branch: default
tags: tip
v0.2.0: add preference dialog
Ning Sun / sunng
4 months ago

Changed (Δ8.0 KB):

raw changeset »

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)

Up to file-list PLUGININFO:

1
Version='0.0.1'
1
Version='0.0.2'
2
2
Authors=['Sun Ning <classicning@gmail.com>']
3
Name='Douban Covers'
3
Name=_('Douban Covers')
4
4
Description='Load album cover from http://www.douban.com/music/'
5
5

Up to file-list __init__.py:

@@ -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
	query = urltemplate %(quoted, apikey)
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