source: deluge/ui/tracker_icons.py@ 7b72d7

2.0.x develop extjs4-port
Last change on this file since 7b72d7 was 7b72d7, checked in by Andrew Resch <andrewresch@gmail.com>, 16 years ago

Made TrackerIcons a component to prevent trying to get an icon multiple
times
Fixed showing the wrong tracker icon in the TorrentView when the icon
could not be retrieved from the tracker

  • Property mode set to 100644
File size: 6.0 KB
Line 
1#
2# tracker_icons.py
3#
4# Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com>
5#
6# Deluge is free software.
7#
8# You may redistribute it and/or modify it under the terms of the
9# GNU General Public License, as published by the Free Software
10# Foundation; either version 3 of the License, or (at your option)
11# any later version.
12#
13# deluge 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.
16# See the GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with deluge. If not, write to:
20# The Free Software Foundation, Inc.,
21# 51 Franklin Street, Fifth Floor
22# Boston, MA 02110-1301, USA.
23#
24
25
26
27import threading
28import gobject
29from urllib import urlopen
30from deluge.log import LOG as log
31from deluge.common import get_pixmap
32import os
33import deluge.configmanager
34import deluge.component as component
35
36#some servers don't have their favicon at the expected location
37RENAMES = {
38 "legaltorrents.com":"beta.legaltorrents.com",
39 "aelitis.com":"www.vuze.com"
40 }
41
42VALID_ICO_TYPES = ["octet-stream", "x-icon", "image/vnd.microsoft.icon", "vnd.microsoft.icon"]
43VALID_PNG_TYPES = ["octet-stream", "png"]
44
45def fetch_url(url, valid_subtypes=None):
46 """
47 returns: data or None
48 """
49 try:
50 url_file = urlopen(url)
51 data = url_file.read()
52
53 #validate:
54 if valid_subtypes and (url_file.info().getsubtype() not in valid_subtypes):
55 raise Exception("Unexpected type for %s : %s" % (url, url_file.info().getsubtype()))
56 if not data:
57 raise Exception("No data")
58 except Exception, e:
59 log.debug("%s %s" % (url, e))
60 return None
61
62 return data
63
64class TrackerIcons(component.Component):
65 def __init__(self):
66 component.Component.__init__(self, "TrackerIcons")
67 #set image cache dir
68 self.image_dir = os.path.join(deluge.configmanager.get_config_dir(), "icons")
69 if not os.path.exists(self.image_dir):
70 os.mkdir(self.image_dir)
71
72 #self.images : {tracker_host:filename}
73 self.images = {"DHT":get_pixmap("dht16.png" )}
74
75 #load image-names in cache-dir
76 for icon in os.listdir(self.image_dir):
77 if icon.endswith(".ico"):
78 self.images[icon[:-4]] = os.path.join(self.image_dir, icon)
79 if icon.endswith(".png"):
80 self.images[icon[:-4]] = os.path.join(self.image_dir, icon)
81
82 def _fetch_icon(self, tracker_host):
83 """
84 returns (ext, data)
85 """
86 host_name = RENAMES.get(tracker_host, tracker_host) #HACK!
87
88 ico = fetch_url("http://%s/favicon.ico" % host_name, VALID_ICO_TYPES)
89 if ico:
90 return ("ico", ico)
91
92 png = fetch_url("http://%s/favicon.png" % host_name, VALID_PNG_TYPES)
93 if png:
94 return ("png", png)
95
96 # FIXME: This should be cleaned up and not copy the top code
97
98 try:
99 html = urlopen("http://%s/" % (host_name,))
100 except Exception, e:
101 log.debug(e)
102 html = None
103
104 if html:
105 icon_path = ""
106 line = html.readline()
107 while line:
108 if '<link rel="icon"' in line or '<link rel="shortcut icon"' in line:
109 log.debug("line: %s", line)
110 icon_path = line[line.find("href"):].split("\"")[1]
111 break
112 line = html.readline()
113 if icon_path:
114 ico = fetch_url(("http://%s/" + icon_path) % host_name, VALID_ICO_TYPES)
115 if ico:
116 return ("ico", ico)
117 png = fetch_url(("http://%s/" + icon_path) % host_name, VALID_PNG_TYPES)
118 if png:
119 return ("png", png)
120
121 """
122 TODO: need a test-site first...
123 html = fetch_url("http://%s/" % (host_name,))
124 if html:
125 for line in html:
126 print line
127 """
128 return (None, None)
129
130 def _fetch_icon_thread(self, tracker_host, callback):
131 """
132 gets new icon from the internet.
133 used by get().
134 calls callback on sucess
135 assumes dicts,urllib and logging are threadsafe.
136 """
137
138 ext, icon_data = self._fetch_icon(tracker_host)
139
140 if icon_data:
141 filename = os.path.join(self.image_dir, "%s.%s" % (tracker_host, ext))
142 f = open(filename,"wb")
143 f.write(icon_data)
144 f.close()
145 else:
146 filename = None
147
148 self.images[tracker_host] = filename
149
150 if callback:
151 gobject.idle_add(callback, filename)
152
153 def get_async(self, tracker_host, callback):
154 if tracker_host in self.images:
155 callback(self.images[tracker_host])
156 elif "." in tracker_host:
157 #only find icon if there's a dot in the name.
158 self.images[tracker_host] = None
159 threading.Thread(target=self. _fetch_icon_thread,
160 args=(tracker_host, callback)).start()
161
162 def get(self, tracker_host):
163 """
164 returns None if the icon is not fetched(yet) or not fond.
165 """
166 if tracker_host in self.images:
167 return self.images[tracker_host]
168 else:
169 self.get_async(tracker_host, None)
170 return None
171
172if __name__ == "__main__":
173 import time
174 def del_old():
175 filename = os.path.join(deluge.configmanager.get_config_dir(),"legaltorrents.com.ico")
176 if os.path.exists(filename):
177 os.remove(filename)
178
179 def test_get():
180 del_old()
181 trackericons = TrackerIcons()
182 print trackericons.images
183 print trackericons.get("unknown2")
184 print trackericons.get("ntorrents.net")
185 print trackericons.get("google.com")
186 print trackericons.get("legaltorrents.com")
187 time.sleep(5.0)
188 print trackericons.get("legaltorrents.com")
189
190 test_get()
191 #test_async()
Note: See TracBrowser for help on using the repository browser.