Index: channels/bookmarks.py ================================================================== --- channels/bookmarks.py +++ channels/bookmarks.py @@ -19,11 +19,10 @@ from config import * from uikit import * from channels import * -import favicon # The bookmarks tab is a core feature and built into the GtkBuilder # layout. Which is why it derives from GenericChannel, and requires @@ -100,12 +99,12 @@ # when bookmark is to be added for a selected stream entry def add(self, row): # normalize data (this row originated in a gtk+ widget) row["favourite"] = 1 - if row.get("favicon"): - row["favicon"] = favicon.file(row.get("homepage")) + #if row.get("favicon"): + # row["favicon"] = favicon.file(row.get("homepage")) if not row.get("listformat"): row["listformat"] = self.parent.channel().listformat # append to storage self.streams["favourite"].append(row) Index: channels/favicon.py ================================================================== --- channels/favicon.py +++ channels/favicon.py @@ -15,35 +15,35 @@ # # This module fetches a favicon for each station, or a small banner # or logo for some channel modules. It converts .ico image files and # sanitizes .png or .jpeg images even prior display. # -# It prepares cache files in ~/.config/streamtuner2/icons/ in agreement -# with the station list display logic. Either uses station "homepage" -# or "img" URLs from entry rows{}. +# It prepares cache files in ~/.config/streamtuner2/icons/ in silent +# agreement with the station list display logic. Either uses station +# row["homepage"] or row["img"] URLs from any entry. # # While it can often discover favicons directly from station homepages, -# it's often speedier to user the Google PNG conversion service. Both +# it's often speedier to use the Google PNG conversion service. Both # depend on a recent Pillow2 python module (superseding the PIL module). # Else may display images with fragments if converted from ICO files. # # Has recently been rewritten, is somewhat less entangled with other # modules now: # · GenericChannel presets row["favicon"] with cache image filename # in any case, uses row["homepage"] or row["img"] as template -# · the filename shortening functionality must be shared between +# · The filename shortening functionality must be shared between # favicon and genericchannel.prepare() code # · uikit.columns() merely checks row["favicon"] for file existence # on redraws # · main.play() only calls .update_playing() or .update_all() # · urllib is no longer required, uses the main ahttp/requests API -# · still might need unhtml() from channels/__init__ later +# · Still might need unhtml() from channels/__init__ later # · Reduce config options → move main favicon options here? import os, os.path -from compat2and3 import StringIO +from io import BytesIO import re from config import * import ahttp from PIL import Image from uikit import gtk @@ -144,11 +144,11 @@ if not pixstore: return # Unpack ListStore, pixbuf column no, preset rowno ls, pix_entry, i = pixstore - # Else rows-iteration rowno + # Else use row index from update_all-iteration if i is None: i = row_i # Existing "favicon" cache filename if row.get("favicon"): @@ -168,13 +168,13 @@ #--- somewhat unrelated --- # # Should become a distinct feature plugin. - It just depends on correct -# invocation order for plugins to work. +# invocation order for both plugins to interact. # Googling is often blocked anyway, because this is clearly a bot request. -# Tag requests with ?client=streamtuner2 purposefully still. +# And requests are tagged with ?client=streamtuner2 still purposefully. # def google_find_homepage(self, row): """ Searches for missing homepage URL via Google. """ if row.get("url") not in tried_urls: tried_urls.append(row.get("url")) @@ -231,26 +231,26 @@ # Convert accepted formats -- even PNG for filtering now if re.match(br'^(.PNG|GIF\d+|.{0,15}JFIF|\x00\x00\x01\x00|.{0,255}]+svg)', imgdata): try: # Read from byte/str - image = Image.open(StringIO(imgdata)) + image = Image.open(BytesIO(imgdata)) log.FAVICON_IMAGE_TO_PNG(image, resize) # Resize if resize and image.size[0] > resize: image.resize((resize, resize), Image.ANTIALIAS) # Convert to PNG via string buffer - out = StringIO() + out = BytesIO() image.save(out, "PNG", quality=98) imgdata = out.getvalue() except Exception as e: return log.ERR("favicon/logo conversion error:", e) and False else: - log.WARN("couldn't detect mime type") + log.WARN("Couldn't detect valig image type from its raw content") # PNG already? if re.match(b"^.(PNG)", imgdata): try: with open(fn, "wb") as f: @@ -261,11 +261,11 @@ # PNG via Google ico2png def fav_google_ico2png(url, fn): - log.FAVICON("google ico2png") + log.FAVICON("fav_google_ico2png()") # Download from service domain = re.sub("^\w+://|/.*$", "", url).lower() geturl = "http://www.google.com/s2/favicons?domain={}".format(domain) imgdata = ahttp.get(geturl, binary=1, timeout=2.5) @@ -286,11 +286,11 @@ # Check for img = html_link_icon(url) if not img: return False - # Fetc image, verify MIMEE type + # Fetch image, verify MIME type r = ahttp.get(img, binary=1, content=0, timeout=2.75) if not re.match('image/(png|jpe?g|png|ico|x-ico|vnd.microsoft.ico)', r.headers["content-type"], re.I): log.WARN("content-type wrong", r.headers) return False @@ -314,10 +314,11 @@ if name == pair.get("rel", "ignore") and pair.get("href"): href = pair["href"] # unhtml() break # Patch URL together (strip double proto/domain, or double slash) return re.sub("^(https?://\w[^/]+\w)?/?(https?://\w[^/]+\w)/?(/.+)$", "\g<2>\g<3>", url+href) + # (should rather split this up again, a few more special cases w/ non-root homepages)