[gwibber] update to 875bzr, BigWhales DM fixes, fix digg, fix kitchen unicode patch, fix glib usage, right-cli

Tom Callaway spot at fedoraproject.org
Thu Oct 7 17:17:46 UTC 2010


commit dea46f9c3deb7536cbb95ec0f617f7b468b743ee
Author: Tom "spot" Callaway <tcallawa at redhat.com>
Date:   Thu Oct 7 13:17:46 2010 -0400

    update to 875bzr, BigWhales DM fixes, fix digg, fix kitchen unicode patch, fix glib usage, right-click closes streams now

 .gitignore                                       |    1 +
 gwibber-867bzr-gowalla.patch                     |    2 +-
 gwibber-875bzr-BigWhale-dm-fixes.patch           |  135 +++
 gwibber-875bzr-digg-fix.patch                    |   23 +
 gwibber-875bzr-glib-fix.patch                    |   12 +
 gwibber-875bzr-kitchen-utf8.patch                |  982 ++++++++++++++++++++++
 gwibber-875bzr-right-click-to-close-stream.patch |   30 +
 gwibber.spec                                     |   60 +-
 sources                                          |    2 +-
 9 files changed, 1231 insertions(+), 16 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 3275499..a92c17b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,4 @@ gwibber-pre3-738bzr.tar.gz
 /gwibber-838bzr.tar.gz
 /gwibber-847bzr.tar.gz
 /gwibber-867bzr.tar.gz
+/gwibber-875bzr.tar.gz
diff --git a/gwibber-867bzr-gowalla.patch b/gwibber-867bzr-gowalla.patch
index 978dbae..fbbe5b5 100644
--- a/gwibber-867bzr-gowalla.patch
+++ b/gwibber-867bzr-gowalla.patch
@@ -160,7 +160,7 @@ diff -up gwibber-867bzr/gwibber/microblog/gowalla.py.NEW gwibber-867bzr/gwibber/
 +            text += data["message"] + "\n"
 +        else:
 +            text= "Checked in off the grid"
-+            shouttext= "<table><tr><td><img src='http://gowalla.com/favicon.ico'/></td><td>Checked in off the grid"
++            messagetext= "<table><tr><td><img src='http://gowalla.com/favicon.ico'/></td><td>Checked in off the grid"
 +
 +    m["text"] = text
 +    m["content"] = messagetext + "</td></tr></table>"
diff --git a/gwibber-875bzr-BigWhale-dm-fixes.patch b/gwibber-875bzr-BigWhale-dm-fixes.patch
new file mode 100644
index 0000000..569094b
--- /dev/null
+++ b/gwibber-875bzr-BigWhale-dm-fixes.patch
@@ -0,0 +1,135 @@
+diff -up gwibber-875bzr/gwibber/client.py.dm gwibber-875bzr/gwibber/client.py
+--- gwibber-875bzr/gwibber/client.py.dm	2010-10-07 10:22:55.595095848 -0400
++++ gwibber-875bzr/gwibber/client.py	2010-10-07 10:23:23.022095848 -0400
+@@ -450,6 +450,9 @@ class GwibberClient(gtk.Window):
+     def perform_action(mi, act, widget, msg): act(widget, self, msg)
+ 
+     for a in actions.MENU_ITEMS:
++      if a.action.__self__.__name__ == "private" and msg["sender"]["is_me"]:
++        continue
++
+       if a.include(self, msg):
+         image = gtk.image_new_from_icon_name(a.icon, gtk.ICON_SIZE_MENU)
+         mi = gtk.ImageMenuItem()
+diff -up gwibber-875bzr/gwibber/microblog/identica.py.dm gwibber-875bzr/gwibber/microblog/identica.py
+--- gwibber-875bzr/gwibber/microblog/identica.py.dm	2010-10-07 10:23:54.622095850 -0400
++++ gwibber-875bzr/gwibber/microblog/identica.py	2010-10-07 10:24:20.236095867 -0400
+@@ -174,7 +174,9 @@ class Client:
+     return self._get("statuses/mentions.json", count=count, since_id=since)
+ 
+   def private(self, count=util.COUNT, since=None):
+-    return self._get("direct_messages.json", "private", count=count, since_id=since)
++    private = self._get("direct_messages.json", "private", count=count, since_id=since)
++    private_sent = self._get("direct_messages/sent.json", "private", count=count, since_id=since)
++    return private + private_sent
+ 
+   def public(self):
+     return self._get("statuses/public_timeline.json")
+diff -up gwibber-875bzr/gwibber/microblog/twitter.py.dm gwibber-875bzr/gwibber/microblog/twitter.py
+--- gwibber-875bzr/gwibber/microblog/twitter.py.dm	2010-10-07 10:24:51.997095781 -0400
++++ gwibber-875bzr/gwibber/microblog/twitter.py	2010-10-07 10:25:06.213095760 -0400
+@@ -232,7 +232,9 @@ class Client:
+     return self._get("statuses/mentions.json", count=count, since_id=since)
+ 
+   def private(self, count=util.COUNT, since=None):
+-    return self._get("direct_messages.json", "private", count=count, since_id=since)
++    private = self._get("direct_messages.json", "private", count=count, since_id=since)
++    private_sent = self._get("direct_messages/sent.json", "private", count=count, since_id=since)
++    return private + private_sent
+ 
+   def public(self):
+     return self._get("statuses/public_timeline.json")
+diff -up gwibber-875bzr/ui/templates/base.mako.dm gwibber-875bzr/ui/templates/base.mako
+--- gwibber-875bzr/ui/templates/base.mako.dm	2010-10-07 10:26:56.291095849 -0400
++++ gwibber-875bzr/ui/templates/base.mako	2010-10-07 10:36:00.756095811 -0400
+@@ -56,11 +56,33 @@
+ </%def>
+ 
+ <%def name="image(data)">
+-  % if "sender" in data:
+-    % if "image" in data["sender"]:
+-      <a href="${profile_url(data)}">
+-        <div class="imgbox" title="${data["sender"].get("nick", "")}" style="background-image: url(${data["sender"]["image"]});"></div>
++  % if data.get("private", 0):
++    % if "recipient" in data:
++      % if data['recipient'].get("is_me", 0):
++        % if "sender" in data:
++          % if "image" in data["sender"]:
++            <a href="${profile_url(data)}">
++              <div class="imgbox" title="${data["sender"].get("nick", "")}" style="background-image: url(${data["sender"]["image"]});">
++              <div class="imgbox" title="${data["recipient"].get("nick", "")}" style="margin: 25px 0px 0px 25px; width: 25px; height: 25px; background-image: url(${data["recipient"]["image"]});"></div></div>
++            </a>
++          % endif
++        % endif
++      % else:
++        % if "image" in data["recipient"]:
++            <a href="${profile_url(data)}">
++              <div class="imgbox" title="${data["sender"].get("nick", "")}" style="background-image: url(${data["sender"]["image"]});">
++              <div class="imgbox" title="${data["recipient"].get("nick", "")}" style="margin: 25px 0px 0px 25px; width: 25px; height: 25px; background-image: url(${data["recipient"]["image"]});"></div></div>
++            </a>
++        % endif
++      % endif
++    % endif
++  % else:
++    % if "sender" in data:
++      % if "image" in data["sender"]:
++        <a href="${profile_url(data)}">
++          <div class="imgbox" title="${data["sender"].get("nick", "")}" style="background-image: url(${data["sender"]["image"]});"></div>
+       </a>
++      % endif
+     % endif
+   % endif
+ </%def>
+@@ -125,9 +147,33 @@
+ <%def name="sender(data)" filter="trim">
+   % if "sender" in data:
+     % if preferences["show_fullname"]:
+-      ${data['sender'].get("name", 0) or data["sender"].get("nick", "")}
++      % if data.get("private", 0):
++        % if "recipient" in data:
++          % if data['recipient'].get("is_me", 0):
++            ${data['sender'].get("name", 0) or data["sender"].get("nick", "")}
++          % else:
++           ${data['recipient'].get("name", 0) or data["recipient"].get("nick", "")}
++          % endif
++        % else:
++          ${data['sender'].get("name", 0) or data["sender"].get("nick", "")}
++        % endif
++      % else:
++        ${data['sender'].get("name", 0) or data["sender"].get("nick", "")}
++      % endif
+     % else:
+-      ${data['sender'].get("nick", 0) or data["sender"].get("name", "")}
++      % if data.get("private", 0):
++        % if "recipient" in data:
++          % if data['recipient'].get("is_me", 0):
++            ${data['sender'].get("nick", 0) or data["sender"].get("name", "")}
++          % else:
++            ${data['recipient'].get("nick", 0) or data["recipient"].get("name", "")}
++          % endif
++        % else:
++          ${data['sender'].get("nick", 0) or data["sender"].get("name", "")}
++        % endif
++      % else:
++        ${data['sender'].get("nick", 0) or data["sender"].get("name", "")}
++      % endif
+     % endif
+   % endif
+ </%def>
+@@ -144,7 +190,15 @@
+   % endif
+ 
+   % if data.get("private", 0):
+-    <img src="${resources.get_ui_asset('icons/streams/16x16/private.png')}" />
++    % if "recipient" in data:
++      % if data['recipient'].get("is_me", 0):
++        <img src="${resources.get_ui_asset('icons/streams/16x16/private.png')}" />
++      % else:
++        <img src="${resources.get_ui_asset('icons/streams/16x16/sent.png')}" />
++      % endif
++    % else:
++      <img src="${resources.get_ui_asset('icons/streams/16x16/private.png')}" />
++    % endif
+   % endif
+   </span>
+ </%def>
diff --git a/gwibber-875bzr-digg-fix.patch b/gwibber-875bzr-digg-fix.patch
new file mode 100644
index 0000000..ad8fab3
--- /dev/null
+++ b/gwibber-875bzr-digg-fix.patch
@@ -0,0 +1,23 @@
+diff -up gwibber-875bzr/gwibber/microblog/digg.py.BAD gwibber-875bzr/gwibber/microblog/digg.py
+--- gwibber-875bzr/gwibber/microblog/digg.py.BAD	2010-10-07 09:27:12.934095847 -0400
++++ gwibber-875bzr/gwibber/microblog/digg.py	2010-10-07 09:28:36.399095852 -0400
+@@ -65,10 +65,15 @@ class Client:
+   def _get(self, path, parse="story", post=False, single=False, **args):
+     url = "/".join((URL_PREFIX, path)) + "?appkey=http://gwibber.com&type=json"
+     
+-    data = network.Download(url, util.compact(args) or None, post).get_json()["stories"]
+-    if single: return [getattr(self, "_%s" % parse)(data)]
+-    if parse: return [getattr(self, "_%s" % parse)(m) for m in data]
+-    else: return []
++    data = network.Download(url, util.compact(args) or None, post).get_json()
++    if "stories" in data:
++        if single: return [getattr(self, "_%s" % parse)(data["stories"])]
++        if parse: return [getattr(self, "_%s" % parse)(m) for m in data["stories"]]
++        else: return []
++    else:
++        if ("status" in data) and ("message" in data):
++            print "Digg: got message with status %s and message %s" % (data["status"], data["message"])
++        return []
+ 
+   def __call__(self, opname, **args):
+     return getattr(self, opname)(**args)
diff --git a/gwibber-875bzr-glib-fix.patch b/gwibber-875bzr-glib-fix.patch
new file mode 100644
index 0000000..d5b0973
--- /dev/null
+++ b/gwibber-875bzr-glib-fix.patch
@@ -0,0 +1,12 @@
+diff -up gwibber-875bzr/gwibber/microblog/util/__init__.py.BAD gwibber-875bzr/gwibber/microblog/util/__init__.py
+--- gwibber-875bzr/gwibber/microblog/util/__init__.py.BAD	2010-10-07 09:49:18.414095850 -0400
++++ gwibber-875bzr/gwibber/microblog/util/__init__.py	2010-10-07 09:49:23.123095884 -0400
+@@ -1,7 +1,7 @@
+ 
+ import os, locale, re, mx.DateTime, cgi
+ import log, resources
+-import dbus
++import dbus, glib
+ from const import *
+ 
+ # Try to import * from custom, install custom.py to include packaging 
diff --git a/gwibber-875bzr-kitchen-utf8.patch b/gwibber-875bzr-kitchen-utf8.patch
new file mode 100644
index 0000000..86e35dc
--- /dev/null
+++ b/gwibber-875bzr-kitchen-utf8.patch
@@ -0,0 +1,982 @@
+diff -up gwibber-875bzr/gwibber/microblog/brightkite.py.kitchen gwibber-875bzr/gwibber/microblog/brightkite.py
+--- gwibber-875bzr/gwibber/microblog/brightkite.py.kitchen	2010-10-06 15:00:44.000000000 -0400
++++ gwibber-875bzr/gwibber/microblog/brightkite.py	2010-10-07 10:47:45.296095849 -0400
+@@ -8,6 +8,7 @@ SegPhault (Ryan Paul) - 10/19/2008
+ from . import support
+ import urllib2, urllib, base64, re, simplejson
+ from xml.dom import minidom
++from kitchen.text.converters import to_unicode
+ 
+ PROTOCOL_INFO = {
+   "name": "BrightKite",
+@@ -34,62 +35,62 @@ class Message:
+   def __init__(self, client, data):
+     self.client = client
+     self.account = client.account
+-    self.service = client.account["service"]
+-    self.username = client.account["username"]
++    self.service = to_unicode(client.account["service"])
++    self.username = to_unicode(client.account["username"])
+ 
+-    self.sender = data["creator"]["fullname"]
+-    self.sender_nick = data["creator"]["login"]
+-    self.sender_id = data["creator"]["login"]
+-    self.image = data["creator"]["small_avatar_url"]
++    self.sender = to_unicode(data["creator"]["fullname"])
++    self.sender_nick = to_unicode(data["creator"]["login"])
++    self.sender_id = to_unicode(data["creator"]["login"])
++    self.image = to_unicode(data["creator"]["small_avatar_url"])
+     
+     self.time = support.parse_time(data["created_at"])
+-    self.text = data["body"] or ""
+-    self.bgcolor = "message_color"
+-    self.id = data["id"]
++    self.text = to_unicode(data["body"]) or u""
++    self.bgcolor = u"message_color"
++    self.id = to_unicode(data["id"])
+     
+-    self.url = "http://brightkite.com/objects/%s" % data["id"]
+-    self.profile_url = "http://brightkite.com/people/%s" % self.sender_nick
++    self.url = to_unicode("http://brightkite.com/objects/%s" % data["id"])
++    self.profile_url = to_unicode("http://brightkite.com/people/%s" % self.sender_nick)
+     
+-    self.html_string = '<span class="text">%s</span>' % \
++    self.html_string = to_unicode('<span class="text">%s</span>' % \
+       NICK_PARSE.sub('@<a class="inlinenick" href="http://brightkite.com/people/\\1">\\1</a>',
+-        support.linkify(self.text))
++        support.linkify(self.text)))
+     
+     self.is_reply = ("@%s" % self.username) in self.text
+     self.can_thread = data["comments_count"] > 0
+ 
+     # Geolocation
+-    self.location_lon = data["place"]["longitude"]
+-    self.location_lat = data["place"]["latitude"]
+-    self.location_id = data["place"]["id"]
+-    self.location_name = data["place"]["name"]
+-    self.location_fullname = data["place"]["display_location"]
++    self.location_lon = to_unicode(data["place"]["longitude"])
++    self.location_lat = to_unicode(data["place"]["latitude"])
++    self.location_id = to_unicode(data["place"]["id"])
++    self.location_name = to_unicode(data["place"]["name"])
++    self.location_fullname = to_unicode(data["place"]["display_location"])
+     self.geo_position = (self.location_lat, self.location_lon)
+ 
+     if "photo" in data:
+-      self.thumbnails = [{"src": data["photo"], "href": data["photo"]}]
++      self.thumbnails = [{"src": to_unicode(data["photo"]), "href": to_unicode(data["photo"])}]
+ 
+ class Comment:
+   def __init__(self, client, data):
+     self.client = client
+     self.account = client.account
+-    self.service = client.account["service"]
+-    self.username = client.account["username"]
++    self.service = to_unicode(client.account["service"])
++    self.username = to_unicode(client.account["username"])
+ 
+-    self.sender = data["user"]["fullname"]
+-    self.sender_nick = data["user"]["login"]
+-    self.sender_id = data["user"]["login"]
+-    self.image = data["user"]["small_avatar_url"]
++    self.sender = to_unicode(data["user"]["fullname"])
++    self.sender_nick = to_unicode(data["user"]["login"])
++    self.sender_id = to_unicode(data["user"]["login"])
++    self.image = to_unicode(data["user"]["small_avatar_url"])
+     
+     self.time = support.parse_time(data["created_at"])
+-    self.text = data["comment"]
+-    self.bgcolor = "message_color"
++    self.text = to_unicode(data["comment"])
++    self.bgcolor = u"message_color"
+     
+-    self.url = "http://brightkite.com/objects/%s" % data["place_object"]["id"]
+-    self.profile_url = "http://brightkite.com/people/%s" % self.sender_nick
++    self.url = to_unicode("http://brightkite.com/objects/%s" % data["place_object"]["id"])
++    self.profile_url = to_unicode("http://brightkite.com/people/%s" % self.sender_nick)
+     
+-    self.html_string = '<span class="text">%s</span>' % \
++    self.html_string = to_unicode('<span class="text">%s</span>' % \
+       NICK_PARSE.sub('@<a class="inlinenick" href="http://brightkite.com/people/\\1">\\1</a>',
+-        support.linkify(self.text))
++        support.linkify(self.text)))
+     
+     self.is_reply = ("@%s" % self.username) in self.text
+ 
+@@ -97,26 +98,26 @@ class FriendPosition:
+   def __init__(self, client, data):
+     self.client = client
+     self.account = client.account
+-    self.service = client.account["service"]
+-    self.username = client.account["username"]
+-    self.sender = data["fullname"]
+-    self.sender_nick = data["login"]
++    self.service = to_unicode(client.account["service"])
++    self.username = to_unicode(client.account["username"])
++    self.sender = to_unicode(data["fullname"])
++    self.sender_nick = to_unicode(data["login"])
+     self.sender_id = self.sender_nick
+     self.time = support.parse_time(data["last_checked_in"])
+-    self.text = data["place"]["display_location"]
+-    self.image = data["small_avatar_url"]
+-    self.image_small = data["smaller_avatar_url"]
+-    self.bgcolor = "message_color"
+-    self.url = "http://brightkite.com" # TODO
+-    self.profile_url = "http://brightkite.com" # TODO
++    self.text = to_unicode(data["place"]["display_location"])
++    self.image = to_unicode(data["small_avatar_url"])
++    self.image_small = to_unicode(data["smaller_avatar_url"])
++    self.bgcolor = u"message_color"
++    self.url = u"http://brightkite.com" # TODO
++    self.profile_url = u"http://brightkite.com" # TODO
+     self.is_reply = False
+ 
+     # Geolocation
+-    self.location_lon = data["place"]["longitude"]
+-    self.location_lat = data["place"]["latitude"]
+-    self.location_id = data["place"]["id"]
+-    self.location_name = data["place"]["name"]
+-    self.location_fullname = data["place"]["display_location"]
++    self.location_lon = to_unicode(data["place"]["longitude"])
++    self.location_lat = to_unicode(data["place"]["latitude"])
++    self.location_id = to_unicode(data["place"]["id"])
++    self.location_name = to_unicode(data["place"]["name"])
++    self.location_fullname = to_unicode(data["place"]["display_location"])
+ 
+ class Client:
+   def __init__(self, acct):
+diff -up gwibber-875bzr/gwibber/microblog/buzz.py.kitchen gwibber-875bzr/gwibber/microblog/buzz.py
+--- gwibber-875bzr/gwibber/microblog/buzz.py.kitchen	2010-10-06 15:00:44.000000000 -0400
++++ gwibber-875bzr/gwibber/microblog/buzz.py	2010-10-07 10:47:45.298095849 -0400
+@@ -1,5 +1,6 @@
+ import network, util, json
+ from oauth import oauth
++from kitchen.text.converters import to_unicode
+ 
+ PROTOCOL_INFO = {
+   "name": "Buzz",
+@@ -41,32 +42,32 @@ class Client:
+ 
+   def _actor(self, user):
+     return {
+-        "name": user["name"],
+-        "nick": user["id"],
+-        "id": user["id"],
+-        "image": user.get("thumbnailUrl", "https://mail.google.com/mail/images/blue_ghost.jpg?sz=45"),
+-        "url": user.get("profileUrl", None),
++        "name": to_unicode(user["name"]),
++        "nick": to_unicode(user["id"]),
++        "id": to_unicode(user["id"]),
++        "image": to_unicode(user.get("thumbnailUrl", "https://mail.google.com/mail/images/blue_ghost.jpg?sz=45")),
++        "url": to_unicode(user.get("profileUrl", None)),
+         "is_me": user["id"] == self.account["user_id"],
+     }
+ 
+   def _message(self, data):
+     m = {
+         "mid": data["id"],
+-        "service": "buzz",
+-        "account": self.account["id"],
++        "service": u"buzz",
++        "account": to_unicode(self.account["id"]),
+         "time": util.parsetime(data["published"]),
+-        "url": data.get("links", {})["alternate"][0].get("href", ""),
+-        "source": data.get("source", {}).get("title", None),
++        "url": to_unicode(data.get("links", {})["alternate"][0].get("href", "")),
++        "source": to_unicode(data.get("source", {}).get("title", None)),
+         "sender": self._actor(data["actor"]),
+     }
+ 
+-    m["text"] = data["object"]["content"]
++    m["text"] = to_unicode(data["object"]["content"])
+ 
+     if data.get("source", {}).get("title", 0) == "Twitter":
+       m["text"] = m["text"].split(">:", 1)[1].strip()
+     
+-    m["html"] = m["text"]
+-    m["content"] = m["text"]
++    m["html"] = to_unicode(m["text"])
++    m["content"] = to_unicode(m["text"])
+ 
+     if data.get("geocode", 0):
+       m["location"] = {
+@@ -75,24 +76,24 @@ class Client:
+       }
+ 
+       if data.get("address", 0):
+-        m["location"]["address"] = data["address"]
++        m["location"]["address"] = to_unicode(data["address"])
+ 
+     m["images"] = []
+     for a in data["object"].get("attachments", []):
+       if a["type"] == "photo":
+         m["images"].append({
+-          "src": a["links"]["preview"][0]["href"],
+-          "url": a["links"]["enclosure"][0]["href"]
++          "src": to_unicode(a["links"]["preview"][0]["href"]),
++          "url": to_unicode(a["links"]["enclosure"][0]["href"])
+         })
+ 
+       if a["type"] == "video":
+         m["images"].append({
+-          "src": a["links"]["preview"][0]["href"],
+-          "url": a["links"]["alternate"][0]["href"],
++          "src": to_unicode(a["links"]["preview"][0]["href"]),
++          "url": to_unicode(a["links"]["alternate"][0]["href"]),
+         })
+ 
+       if a["type"] == "article":
+-        m["content"] += "<p><b><a href=\"%s\">%s</a></b></p>" % (a["links"]["alternate"][0]["href"], a["title"])
++        m["content"] += to_unicode("<p><b><a href=\"%s\">%s</a></b></p>" % (a["links"]["alternate"][0]["href"], a["title"]))
+ 
+     return m
+ 
+diff -up gwibber-875bzr/gwibber/microblog/digg.py.kitchen gwibber-875bzr/gwibber/microblog/digg.py
+--- gwibber-875bzr/gwibber/microblog/digg.py.kitchen	2010-10-07 10:47:45.289095849 -0400
++++ gwibber-875bzr/gwibber/microblog/digg.py	2010-10-07 10:47:45.299095849 -0400
+@@ -1,5 +1,6 @@
+ import network, util
+ from gettext import lgettext as _
++from kitchen.text.converters import to_unicode
+ 
+ PROTOCOL_INFO = {
+   "name": "Digg",
+@@ -32,33 +33,33 @@ class Client:
+   def _story(self, data):
+     m = {}; 
+     m["mid"] = str(data["id"])
+-    m["service"] = "digg"
+-    m["account"] = self.account["id"]
++    m["service"] = u"digg"
++    m["account"] = to_unicode(self.account["id"])
+     m["time"] = data["submit_date"]
+ 
+-    m["text"] = data["title"] + "\n" + data["description"]
+-    m["content"] = "<b>%(title)s</b><br />%(description)s" % data
+-    m["html"] = "<b>%(title)s</b><br />%(description)s" % data
++    m["text"] = to_unicode(data["title"]) + u"\n" + to_unicode(data["description"])
++    m["content"] = to_unicode("<b>%(title)s</b><br />%(description)s" % data)
++    m["html"] = to_unicode("<b>%(title)s</b><br />%(description)s" % data)
+     user = data["friends"]["users"][0]
+ 
+     m["sender"] = {}
+-    m["sender"]["nick"] = user["name"]
+-    m["sender"]["id"] = user["name"]
+-    m["sender"]["image"] = user["icon"]
+-    m["sender"]["url"] = "http://digg.com/users/%s" % user["name"]
++    m["sender"]["nick"] = to_unicode(user["name"])
++    m["sender"]["id"] = to_unicode(user["name"])
++    m["sender"]["image"] = to_unicode(user["icon"])
++    m["sender"]["url"] = to_unicode("http://digg.com/users/%s" % user["name"])
+     m["sender"]["is_me"] = user["name"] == self.account["username"]
+-    if user.get("fullname", 0): m["sender"]["name"] = user["fullname"]
++    if user.get("fullname", 0): m["sender"]["name"] = to_unicode(user["fullname"])
+     
+-    m["url"] = data["link"]
++    m["url"] = to_unicode(data["link"])
+     m["likes"] = {"count": data["diggs"]}
+ 
+-    m["html"] = util.linkify(m["text"],
++    m["html"] = to_unicode(util.linkify(m["text"],
+       ((util.PARSE_HASH, '#<a class="hash" href="%s#search?q=\\1">\\1</a>' % URL_PREFIX),
+-      (util.PARSE_NICK, '@<a class="nick" href="%s/\\1">\\1</a>' % URL_PREFIX)))
++      (util.PARSE_NICK, '@<a class="nick" href="%s/\\1">\\1</a>' % URL_PREFIX))))
+ 
+-    m["content"] = util.linkify(m["text"],
++    m["content"] = to_unicode(util.linkify(m["text"],
+       ((util.PARSE_HASH, '#<a class="hash" href="gwibber:/tag?acct=%s&query=\\1">\\1</a>' % m["account"]),
+-      (util.PARSE_NICK, '@<a class="nick" href="gwibber:/user?acct=%s&name=\\1">\\1</a>' % m["account"])))
++      (util.PARSE_NICK, '@<a class="nick" href="gwibber:/user?acct=%s&name=\\1">\\1</a>' % m["account"]))))
+ 
+     return m
+ 
+diff -up gwibber-875bzr/gwibber/microblog/dispatcher.py.kitchen gwibber-875bzr/gwibber/microblog/dispatcher.py
+--- gwibber-875bzr/gwibber/microblog/dispatcher.py.kitchen	2010-10-07 10:47:45.249095849 -0400
++++ gwibber-875bzr/gwibber/microblog/dispatcher.py	2010-10-07 10:47:45.301095849 -0400
+@@ -8,6 +8,7 @@ import qaiku, friendfeed, digg, buzz, pi
+ import foursquare, gowalla
+ import sqlite3, mx.DateTime, re, uuid
+ import urlshorter, storage, network, util, config
++from kitchen.text.converters import to_unicode
+ 
+ from util import log
+ from util import resources
+@@ -86,9 +87,9 @@ def perform_operation((account, opname, 
+     if message_data is not None:
+       for m in message_data:
+         if "mid" in m:
+-          m["id"] = uuid.uuid1().hex
+-          m["operation"] = opname
+-          m["stream"] = stream
++          m["id"] = to_unicode(uuid.uuid1().hex)
++          m["operation"] = to_unicode(opname)
++          m["stream"] = to_unicode(stream)
+           m["transient"] = transient
+           m["rtl"] = util.isRTL(re.sub(text_cleaner, "", m["text"].decode('utf-8')))
+ 
+diff -up gwibber-875bzr/gwibber/microblog/facebook.py.kitchen gwibber-875bzr/gwibber/microblog/facebook.py
+--- gwibber-875bzr/gwibber/microblog/facebook.py.kitchen	2010-10-06 15:00:44.000000000 -0400
++++ gwibber-875bzr/gwibber/microblog/facebook.py	2010-10-07 10:47:45.303095849 -0400
+@@ -6,6 +6,7 @@ import hashlib, mx.DateTime, time
+ from os.path import join, getmtime, exists
+ from gettext import lgettext as _
+ from util.const import *
++from kitchen.text.converters import to_unicode
+ # Try to import * from custom, install custom.py to include packaging 
+ # customizations like distro API keys, etc
+ try:
+@@ -91,36 +92,36 @@ class Client:
+ 
+   def _sender(self, user):
+     sender = {
+-      "name": user["name"],
++      "name": to_unicode(user["name"]),
+       "id": str(user["id"]),
+       "is_me": str(user["id"]) == self.user_id,
+-      "url": user["url"],
+-      "image": user["pic_square"],
++      "url": to_unicode(user["url"]),
++      "image": to_unicode(user["pic_square"]),
+     }
+     
+     if user["url"] and not "?" in user["url"]:
+-      sender["nick"] = user["url"].rsplit("/", 1)[-1]
++      sender["nick"] = to_unicode(user["url"].rsplit("/", 1)[-1])
+     return sender
+   
+   def _message(self, data, profiles):
+     m = {}
+-    m["mid"] = str(data["post_id"])
+-    m["service"] = "facebook"
++    m["mid"] = to_unicode(data["post_id"])
++    m["service"] = u"facebook"
+     m["account"] = self.account["id"]
+     m["time"] = int(mx.DateTime.DateTimeFrom(int(data['created_time'])).gmtime())
+-    m["url"] = data["permalink"]
++    m["url"] = to_unicode(data["permalink"])
+ 
+     if data.get("attribution", 0):
+-      m["source"] = util.strip_urls(data["attribution"]).replace("via ", "")
++      m["source"] = to_unicode(util.strip_urls(data["attribution"]).replace("via ", ""))
+     
+     if data.get("message", "").strip():
+-      m["text"] = data["message"]
+-      m["html"] = util.linkify(data["message"])
+-      m["content"] = m["html"]
++      m["text"] = to_unicode(data["message"])
++      m["html"] = to_unicode(util.linkify(data["message"]))
++      m["content"] = to_unicode(m["html"])
+     else:
+-      m["text"] = ""
+-      m["html"] = ""
+-      m["content"] = ""
++      m["text"] = u""
++      m["html"] = u""
++      m["content"] = u""
+ 
+     if data.get("actor_id", 0) in profiles:
+       m["sender"] = self._sender(profiles[data["actor_id"]])
+@@ -131,8 +132,8 @@ class Client:
+ 
+     if data.get("likes", {}).get("count", None):
+       m["likes"] = {
+-        "count": data["likes"]["count"],
+-        "url": data["likes"]["href"],
++        "count": to_unicode(data["likes"]["count"]),
++        "url": to_unicode(data["likes"]["href"]),
+       }
+ 
+     if data.get("comments", 0):
+@@ -140,100 +141,100 @@ class Client:
+       for item in data["comments"]["comment_list"]:
+         if item["fromid"] in profiles:
+           m["comments"].append({
+-            "text": item["text"],
++            "text": to_unicode(item["text"]),
+             "time": int(mx.DateTime.DateTimeFrom(int(item["time"])).gmtime()),
+             "sender": self._sender(profiles[item["fromid"]]),
+           })
+ 
+     if data.get("attachment", 0):
+       if data["attachment"].get("name", 0):
+-        m["content"] += "<p><b>%s</b></p>" % data["attachment"]["name"]
++        m["content"] += to_unicode("<p><b>%s</b></p>" % data["attachment"]["name"])
+ 
+       if data["attachment"].get("description", 0):
+-        m["content"] += "<p>%s</p>" % data["attachment"]["description"]
++        m["content"] += to_unicode("<p>%s</p>" % data["attachment"]["description"])
+ 
+       m["images"] = []
+       for a in data["attachment"].get("media", []):
+         if a["type"] in ["photo", "video", "link"]:
+           if a.get("src", 0):
+             if a["src"].startswith("/"):
+-              a["src"] = "http://facebook.com" + a["src"]
+-            m["images"].append({"src": a["src"], "url": a["href"]})
++              a["src"] = u"http://facebook.com" + to_unicode(a["src"])
++            m["images"].append({"src": a["src"], "url": to_unicode(a["href"])})
+ 
+     return m
+ 
+   def _comment(self, data, profiles):
+     user = profiles[data["fromid"]]
+     return {
+-      "mid": str(data["id"]),
+-      "service": "facebook",
++      "mid": to_unicode(data["id"]),
++      "service": u"facebook",
+       "account": self.account["id"],
+       "time": int(mx.DateTime.DateTimeFrom(int(data['time'])).gmtime()),
+-      "text": "@%s: %s" % (self.account["username"], data["text"]),
+-      "content": "@%s: %s" % (self.account["username"], data["text"]),
+-      "html": "@%s: %s" % (self.account["username"], data["text"]),
++      "text": to_unicode("@%s: %s" % (self.account["username"], data["text"])),
++      "content": to_unicode("@%s: %s" % (self.account["username"], data["text"])),
++      "html": to_unicode("@%s: %s" % (self.account["username"], data["text"])),
+       "reply": {
+         "id": data["post_id"],
+-        "nick": self.account["username"],
+-        "url": POST_URL % (self.user_id, data["object_id"]),
++        "nick": to_unicode(self.account["username"]),
++        "url": to_unicode(POST_URL % (self.user_id, data["object_id"])),
+       },
+       "sender": {
+-        "nick": user["username"] or str(user["uid"]),
+-        "name": user["name"],
++        "nick": to_unicode(user["username"]) or to_unicode(user["uid"]),
++        "name": to_unicode(user["name"]),
+         "id": str(user["uid"]),
+-        "url": user["profile_url"],
+-        "image": user["pic_square"],
++        "url": to_unicode(user["profile_url"]),
++        "image": to_unicode(user["pic_square"]),
+       }
+     }
+ 
+   def _image(self, data, profiles):
+     user = profiles[int(data["owner"])]
+     return {
+-      "mid": str(data["object_id"]),
+-      "service": "facebook",
++      "mid": to_unicode(data["object_id"]),
++      "service": u"facebook",
+       "account": self.account["id"],
+       "time": int(mx.DateTime.DateTimeFrom(int(data['created'])).gmtime()),
+-      "content": data["caption"],
+-      "text": data["caption"],
+-      "html": data["caption"],
++      "content": to_unicode(data["caption"]),
++      "text": to_unicode(data["caption"]),
++      "html": to_unicode(data["caption"]),
+       "images": [{
+-        "full": data["src_big"],
+-        "src": data["src_big"],
+-        "thumb": data["src_small"],
+-        "url": data["link"],
++        "full": to_unicode(data["src_big"]),
++        "src": to_unicode(data["src_big"]),
++        "thumb": to_unicode(data["src_small"]),
++        "url": to_unicode(data["link"]),
+       }],
+       "sender": {
+-        "nick": user["username"] or str(user["uid"]),
+-        "name": user["name"],
++        "nick": to_unicode(user["username"]) or to_unicode(user["uid"]),
++        "name": to_unicode(user["name"]),
+         "id": str(user["uid"]),
+-        "url": user["profile_url"],
+-        "image": user["pic_square"],
++        "url": to_unicode(user["profile_url"]),
++        "image": to_unicode(user["pic_square"]),
+       }
+     }
+ 
+   def _list(self, data, user):
+     return {
+         "mid": data["value"],
+-        "service": "facebook",
++        "service": u"facebook",
+         "account": self.account["id"],
+         "time": 0,
+-        "text": "",
+-        "html": "",
+-        "content": "",
+-        "url": "#", # http://www.facebook.com/friends/?filter=flp_%s" % data["flid"],
+-        "name": data["name"],
+-        "nick": data["name"],
+-        "key": data["filter_key"],
+-        "full": "",
+-        "type": data["type"],
+-        "kind": "list",
+-        "fbstreamicon": data["icon_url"],
++        "text": u"",
++        "html": u"",
++        "content": u"",
++        "url": u"#", # http://www.facebook.com/friends/?filter=flp_%s" % data["flid"],
++        "name": to_unicode(data["name"]),
++        "nick": to_unicode(data["name"]),
++        "key": to_unicode(data["filter_key"]),
++        "full": u"",
++        "type": to_unicode(data["type"]),
++        "kind": u"list",
++        "fbstreamicon": to_unicode(data["icon_url"]),
+         "sender": {
+-          "nick": user["username"] or str(user["uid"]),
+-          "name": user["name"],
++          "nick": to_unicode(user["username"]) or to_unicode(user["uid"]),
++          "name": to_unicode(user["name"]),
+           "id": str(user["uid"]),
+-          "url": user["profile_url"],
+-          "image": user["pic_square"],
++          "url": to_unicode(user["profile_url"]),
++          "image": to_unicode(user["pic_square"]),
+         }
+     }
+ 
+diff -up gwibber-875bzr/gwibber/microblog/gowalla.py.kitchen gwibber-875bzr/gwibber/microblog/gowalla.py
+--- gwibber-875bzr/gwibber/microblog/gowalla.py.kitchen	2010-10-07 10:47:45.250095849 -0400
++++ gwibber-875bzr/gwibber/microblog/gowalla.py	2010-10-07 10:47:45.304095849 -0400
+@@ -26,6 +26,7 @@ import network, json, util, htmllib, re
+ from util import log
+ from util import exceptions
+ from gettext import lgettext as _
++from kitchen.text.converters import to_unicode
+ log.logger.name = "Gowalla"
+ 
+ PROTOCOL_INFO = {
+@@ -60,47 +61,47 @@ class Client:
+   def _message(self, data):
+ 
+     m = {}; 
+-    m["mid"] = str(data["user"]["first_name"]) + str(data["user"]["last_name"])
+-    m["service"] = "gowalla"
++    m["mid"] = to_unicode(str(data["user"]["first_name"]) + str(data["user"]["last_name"]))
++    m["service"] = u"gowalla"
+     m["account"] = self.account["id"]
+     m["time"] = util.parsetime(data["created_at"])
+ 
+-    messagetext = ""
+-    text = ""
++    messagetext = u""
++    text = u""
+     if data.has_key("spot"):
+         if data.has_key("message"):
+             messagetext += data["message"] + "<br/><br/>"
+             text += data["message"] + "\n"
+-	m["url"] = "<a href='http://gowalla.com%s'>" % data["spot"]["url"]
+-	m["url"] = "http://gowalla.com%s" % data["spot"]["url"]
+-        img = "<table><tr><td><img src='%s'/></td><td>" % data["spot"]["image_url"]
+-        messagetext += img + "Checked in at <a href='" + m["url"] + "'>" + data["spot"]["name"] + "</a>"
+-	text += "Checked in at " + data["spot"]["name"]
++	m["url"] = to_unicode("<a href='http://gowalla.com%s'>" % data["spot"]["url"])
++	m["url"] = to_unicode("http://gowalla.com%s" % data["spot"]["url"])
++        img = to_unicode("<table><tr><td><img src='%s'/></td><td>" % data["spot"]["image_url"])
++        messagetext += img + "Checked in at <a href='" + m["url"] + "'>" + to_unicode(data["spot"]["name"]) + "</a>"
++	text += u"Checked in at " + to_unicode(data["spot"]["name"])
+     else:
+         if data.has_key("message"):
+-            messagetext += data["message"] + "<br/><br/>"
+-            text += data["message"] + "\n"
++            messagetext += to_unicode(data["message"]) + u"<br/><br/>"
++            text += to_unicode(data["message"]) + u"\n"
+         else:
+-            text= "Checked in off the grid"
+-            messagetext= "<table><tr><td><img src='http://gowalla.com/favicon.ico'/></td><td>Checked in off the grid"
++            text= u"Checked in off the grid"
++            messagetext= u"<table><tr><td><img src='http://gowalla.com/favicon.ico'/></td><td>Checked in off the grid"
+ 
+     m["text"] = text
+-    m["content"] = messagetext + "</td></tr></table>"
+-    m["html"] = messagetext + "</td></tr></table>"
++    m["content"] = messagetext + u"</td></tr></table>"
++    m["html"] = messagetext + u"</td></tr></table>"
+ 
+     m["sender"] = {}
+-    m["sender"]["image"] = data["user"]["image_url"]
+-    m["sender"]["url"] = "http://gowalla.com%s" % data["user"]["url"]
+-    fullname = ""
++    m["sender"]["image"] = to_unicode(data["user"]["image_url"])
++    m["sender"]["url"] = to_unicode("http://gowalla.com%s" % data["user"]["url"])
++    fullname = u""
+     if data["user"].has_key("first_name"):
+-        fullname += data["user"]["first_name"] + " "
++        fullname += to_unicode(data["user"]["first_name"]) + u" "
+     if data["user"].has_key("last_name"):
+-        fullname += data["user"]["last_name"]
++        fullname += to_unicode(data["user"]["last_name"])
+ 
+     m["sender"]["name"] = fullname
+     m["sender"]["nick"] = fullname
+         
+-    m["source"] = "<a href='http://gowalla.com/'>Gowalla</a>"
++    m["source"] = u"<a href='http://gowalla.com/'>Gowalla</a>"
+ 
+     return m
+ 
+diff -up gwibber-875bzr/gwibber/microblog/identica.py.kitchen gwibber-875bzr/gwibber/microblog/identica.py
+--- gwibber-875bzr/gwibber/microblog/identica.py.kitchen	2010-10-07 10:47:45.164095849 -0400
++++ gwibber-875bzr/gwibber/microblog/identica.py	2010-10-07 10:47:45.305095849 -0400
+@@ -2,6 +2,7 @@ import re, network, util
+ from util import log
+ from util import exceptions
+ from gettext import lgettext as _
++from kitchen.text.converters import to_unicode
+ log.logger.name = "Identi.ca"
+ 
+ PROTOCOL_INFO = {
+@@ -54,27 +55,27 @@ class Client:
+     m = {}
+     try:
+       m["mid"] = str(data["id"])
+-      m["service"] = "identica"
++      m["service"] = u"identica"
+       m["account"] = self.account["id"]
+       m["time"] = util.parsetime(data["created_at"])
+-      m["source"] = data.get("source", False)
+-      m["text"] = data["text"]
++      m["source"] = to_unicode(data.get("source", False))
++      m["text"] = to_unicode(data["text"])
+       m["to_me"] = ("@%s" % self.account["username"]) in data["text"]
+   
+-      m["html"] = util.linkify(m["text"],
++      m["html"] = to_unicode(util.linkify(m["text"],
+         ((util.PARSE_HASH, '#<a class="hash" href="%s#search?q=\\1">\\1</a>' % URL_PREFIX),
+-        (util.PARSE_NICK, '@<a class="nick" href="%s/\\1">\\1</a>' % URL_PREFIX)))
++        (util.PARSE_NICK, '@<a class="nick" href="%s/\\1">\\1</a>' % URL_PREFIX))))
+   
+-      m["content"] = util.linkify(m["text"],
++      m["content"] = to_unicode(util.linkify(m["text"],
+         ((util.PARSE_HASH, '#<a class="hash" href="gwibber:/tag?acct=%s&query=\\1">\\1</a>' % m["account"]),
+-        (util.PARSE_NICK, '@<a class="nick" href="gwibber:/user?acct=%s&name=\\1">\\1</a>' % m["account"])))
++        (util.PARSE_NICK, '@<a class="nick" href="gwibber:/user?acct=%s&name=\\1">\\1</a>' % m["account"]))))
+ 
+       images = []
+       if data.get("attachments", 0):
+         for a in data["attachments"]:
+           mime = a.get("mimetype", "")
+           if mime and mime.startswith("image") and a.get("url", 0):
+-            images.append({"src": a["url"], "url": a["url"]})
++            images.append({"src": to_unicode(a["url"]), "url": to_unicode(a["url"])})
+ 
+       images.extend(util.imgpreview(m["text"]))
+ 
+@@ -91,33 +92,33 @@ class Client:
+     if data.get("in_reply_to_status_id", 0) and data.get("in_reply_to_screen_name", 0):
+       m["reply"] = {}
+       m["reply"]["id"] = data["in_reply_to_status_id"]
+-      m["reply"]["nick"] = data["in_reply_to_screen_name"]
+-      m["reply"]["url"] = "/".join((URL_PREFIX, "notice", str(m["reply"]["id"])))
++      m["reply"]["nick"] = to_unicode(data["in_reply_to_screen_name"])
++      m["reply"]["url"] = to_unicode("/".join((URL_PREFIX, "notice", str(m["reply"]["id"]))))
+ 
+     user = data.get("user", data.get("sender", 0))
+     
+     m["sender"] = {}
+-    m["sender"]["name"] = user["name"]
+-    m["sender"]["nick"] = user["screen_name"]
++    m["sender"]["name"] = to_unicode(user["name"])
++    m["sender"]["nick"] = to_unicode(user["screen_name"])
+     m["sender"]["id"] = user["id"]
+-    m["sender"]["location"] = user["location"]
++    m["sender"]["location"] = to_unicode(user["location"])
+     m["sender"]["followers"] = user["followers_count"]
+-    m["sender"]["image"] = user["profile_image_url"]
+-    m["sender"]["url"] = "/".join((URL_PREFIX, m["sender"]["nick"]))
++    m["sender"]["image"] = to_unicode(user["profile_image_url"])
++    m["sender"]["url"] = to_unicode("/".join((URL_PREFIX, m["sender"]["nick"])))
+     m["sender"]["is_me"] = m["sender"]["nick"] == self.account["username"]
+-    m["url"] = "/".join((URL_PREFIX, "notice", m["mid"]))
++    m["url"] = to_unicode("/".join((URL_PREFIX, "notice", m["mid"])))
+     return m
+ 
+   def _private(self, data):
+     m = self._message(data)
+     m["private"] = True
+     m["recipient"] = {}
+-    m["recipient"]["name"] = data["recipient"]["name"]
+-    m["recipient"]["nick"] = data["recipient"]["screen_name"]
++    m["recipient"]["name"] = to_unicode(data["recipient"]["name"])
++    m["recipient"]["nick"] = to_unicode(data["recipient"]["screen_name"])
+     m["recipient"]["id"] = data["recipient"]["id"]
+-    m["recipient"]["image"] = data["recipient"]["profile_image_url"]
+-    m["recipient"]["location"] = data["recipient"]["location"]
+-    m["recipient"]["url"] = "/".join((URL_PREFIX, m["recipient"]["nick"]))
++    m["recipient"]["image"] = to_unicode(data["recipient"]["profile_image_url"])
++    m["recipient"]["location"] = to_unicode(data["recipient"]["location"])
++    m["recipient"]["url"] = to_unicode("/".join((URL_PREFIX, m["recipient"]["nick"])))
+     m["recipient"]["is_me"] = m["recipient"]["nick"].lower() == self.account["username"].lower()
+     return m
+ 
+@@ -127,14 +128,14 @@ class Client:
+     if data["to_user_id"]:
+       m["reply"] = {}
+       m["reply"]["id"] = data["to_user_id"]
+-      m["reply"]["nick"] = data["to_user"]
++      m["reply"]["nick"] = to_unicode(data["to_user"])
+ 
+     m["sender"] = {}
+-    m["sender"]["nick"] = data["from_user"]
++    m["sender"]["nick"] = to_unicode(data["from_user"])
+     m["sender"]["id"] = data["from_user_id"]
+-    m["sender"]["image"] = data["profile_image_url"]
+-    m["sender"]["url"] = "/".join((URL_PREFIX, m["sender"]["nick"]))
+-    m["url"] = "/".join((URL_PREFIX, "notice", str(m["mid"])))
++    m["sender"]["image"] = to_unicode(data["profile_image_url"])
++    m["sender"]["url"] = to_unicode("/".join((URL_PREFIX, m["sender"]["nick"])))
++    m["url"] = to_unicode("/".join((URL_PREFIX, "notice", str(m["mid"]))))
+     return m
+ 
+   def _get(self, path, parse="message", post=False, single=False, **args):
+diff -up gwibber-875bzr/gwibber/microblog/statusnet.py.kitchen gwibber-875bzr/gwibber/microblog/statusnet.py
+--- gwibber-875bzr/gwibber/microblog/statusnet.py.kitchen	2010-10-06 15:00:44.000000000 -0400
++++ gwibber-875bzr/gwibber/microblog/statusnet.py	2010-10-07 10:49:47.151095848 -0400
+@@ -2,6 +2,7 @@ import re, network, util
+ from util import log
+ from util import exceptions
+ from gettext import lgettext as _
++from kitchen.text.converters import to_unicode
+ log.logger.name = "StatusNet"
+ 
+ PROTOCOL_INFO = {
+@@ -56,27 +57,27 @@ class Client:
+     m = {}
+     try:
+       m["mid"] = str(data["id"])
+-      m["service"] = "statusnet"
++      m["service"] = u"statusnet"
+       m["account"] = self.account["id"]
+       m["time"] = util.parsetime(data["created_at"])
+-      m["source"] = data.get("source", False)
+-      m["text"] = data["text"]
++      m["source"] = to_unicode(data.get("source", False))
++      m["text"] = to_unicode(data["text"])
+       m["to_me"] = ("@%s" % self.account["username"]) in data["text"]
+ 
+-      m["html"] = util.linkify(m["text"],
++      m["html"] = to_unicode(util.linkify(m["text"],
+         ((util.PARSE_HASH, '#<a class="hash" href="%s#search?q=\\1">\\1</a>' % self.url_prefix),
+-        (util.PARSE_NICK, '@<a class="nick" href="%s/\\1">\\1</a>' % self.url_prefix)))
++        (util.PARSE_NICK, '@<a class="nick" href="%s/\\1">\\1</a>' % self.url_prefix))))
+ 
+-      m["content"] = util.linkify(m["text"],
++      m["content"] = to_unicode(util.linkify(m["text"],
+         ((util.PARSE_HASH, '#<a class="hash" href="gwibber:/tag?acct=%s&query=\\1">\\1</a>' % m["account"]),
+-        (util.PARSE_NICK, '@<a class="nick" href="gwibber:/user?acct=%s&name=\\1">\\1</a>' % m["account"])))
++        (util.PARSE_NICK, '@<a class="nick" href="gwibber:/user?acct=%s&name=\\1">\\1</a>' % m["account"]))))
+ 
+       images = []
+       if data.get("attachments", 0):
+         for a in data["attachments"]:
+           mime = a.get("mimetype", "")
+           if mime and mime.startswith("image") and a.get("url", 0):
+-            images.append({"src": a["url"], "url": a["url"]})
++            images.append({"src": to_unicode(a["url"]), "url": to_unicode(a["url"])})
+ 
+       images.extend(util.imgpreview(m["text"]))
+   
+@@ -93,33 +94,33 @@ class Client:
+     if data.get("in_reply_to_status_id", 0) and data.get("in_reply_to_screen_name", 0):
+       m["reply"] = {}
+       m["reply"]["id"] = data["in_reply_to_status_id"]
+-      m["reply"]["nick"] = data["in_reply_to_screen_name"]
+-      m["reply"]["url"] = "/".join((self.url_prefix, "notice", str(m["reply"]["id"])))
++      m["reply"]["nick"] = to_unicode(data["in_reply_to_screen_name"])
++      m["reply"]["url"] = to_unicode("/".join((self.url_prefix, "notice", str(m["reply"]["id"]))))
+ 
+     user = data.get("user", data.get("sender", 0))
+     
+     m["sender"] = {}
+-    m["sender"]["name"] = user["name"]
+-    m["sender"]["nick"] = user["screen_name"]
++    m["sender"]["name"] = to_unicode(user["name"])
++    m["sender"]["nick"] = to_unicode(user["screen_name"])
+     m["sender"]["id"] = user["id"]
+-    m["sender"]["location"] = user["location"]
++    m["sender"]["location"] = to_unicode(user["location"])
+     m["sender"]["followers"] = user["followers_count"]
+-    m["sender"]["image"] = user["profile_image_url"]
+-    m["sender"]["url"] = "/".join((self.url_prefix, m["sender"]["nick"]))
++    m["sender"]["image"] = to_unicode(user["profile_image_url"])
++    m["sender"]["url"] = to_unicode("/".join((self.url_prefix, m["sender"]["nick"])))
+     m["sender"]["is_me"] = m["sender"]["nick"] == self.account["username"]
+-    m["url"] = "/".join((self.url_prefix, "notice", m["mid"]))
++    m["url"] = to_unicode("/".join((self.url_prefix, "notice", m["mid"])))
+     return m
+ 
+   def _private(self, data):
+     m = self._message(data)
+     m["private"] = True
+     m["recipient"] = {}
+-    m["recipient"]["name"] = data["recipient"]["name"]
+-    m["recipient"]["nick"] = data["recipient"]["screen_name"]
++    m["recipient"]["name"] = to_unicode(data["recipient"]["name"])
++    m["recipient"]["nick"] = to_unicode(data["recipient"]["screen_name"])
+     m["recipient"]["id"] = data["recipient"]["id"]
+-    m["recipient"]["image"] = data["recipient"]["profile_image_url"]
+-    m["recipient"]["location"] = data["recipient"]["location"]
+-    m["recipient"]["url"] = "/".join((self.url_prefix, m["recipient"]["nick"]))
++    m["recipient"]["image"] = to_unicode(data["recipient"]["profile_image_url"])
++    m["recipient"]["location"] = to_unicode(data["recipient"]["location"])
++    m["recipient"]["url"] = to_unicode("/".join((self.url_prefix, m["recipient"]["nick"])))
+     m["recipient"]["is_me"] = m["recipient"]["nick"].lower() == self.account["username"].lower()
+     return m
+ 
+@@ -132,11 +133,11 @@ class Client:
+       m["reply"]["nick"] = data["to_user"]
+ 
+     m["sender"] = {}
+-    m["sender"]["nick"] = data["from_user"]
++    m["sender"]["nick"] = to_unicode(data["from_user"])
+     m["sender"]["id"] = data["from_user_id"]
+-    m["sender"]["image"] = data["profile_image_url"]
+-    m["sender"]["url"] = "/".join((self.url_prefix, m["sender"]["nick"]))
+-    m["url"] = "/".join((self.url_prefix, "notice", str(m["mid"])))
++    m["sender"]["image"] = to_unicode(data["profile_image_url"])
++    m["sender"]["url"] = to_unicode("/".join((self.url_prefix, m["sender"]["nick"])))
++    m["url"] = to_unicode("/".join((self.url_prefix, "notice", str(m["mid"]))))
+     return m
+ 
+   def _get(self, path, parse="message", post=False, single=False, **args):
+diff -up gwibber-875bzr/gwibber/microblog/twitter.py.kitchen gwibber-875bzr/gwibber/microblog/twitter.py
+--- gwibber-875bzr/gwibber/microblog/twitter.py.kitchen	2010-10-07 10:47:45.166095849 -0400
++++ gwibber-875bzr/gwibber/microblog/twitter.py	2010-10-07 10:47:45.309095849 -0400
+@@ -3,6 +3,7 @@ import gnomekeyring
+ from oauth import oauth
+ from util import log, exceptions
+ from gettext import lgettext as _
++from kitchen.text.converters import to_unicode
+ log.logger.name = "Twitter"
+ 
+ PROTOCOL_INFO = {
+@@ -72,19 +73,19 @@ class Client:
+     m = {}; 
+     try:
+       m["mid"] = str(data["id"])
+-      m["service"] = "twitter"
++      m["service"] = u"twitter"
+       m["account"] = self.account["id"]
+       m["time"] = util.parsetime(data["created_at"])
+-      m["text"] = unescape(data["text"])
++      m["text"] = to_unicode(unescape(data["text"]))
+       m["to_me"] = ("@%s" % self.account["username"]) in data["text"]
+ 
+-      m["html"] = util.linkify(data["text"],
++      m["html"] = to_unicode(util.linkify(data["text"],
+         ((util.PARSE_HASH, '#<a class="hash" href="%s#search?q=\\1">\\1</a>' % URL_PREFIX),
+-        (util.PARSE_NICK, '@<a class="nick" href="%s/\\1">\\1</a>' % URL_PREFIX)), escape=False)
++        (util.PARSE_NICK, '@<a class="nick" href="%s/\\1">\\1</a>' % URL_PREFIX)), escape=False))
+ 
+-      m["content"] = util.linkify(data["text"],
++      m["content"] = to_unicode(util.linkify(data["text"],
+         ((util.PARSE_HASH, '#<a class="hash" href="gwibber:/tag?acct=%s&query=\\1">\\1</a>' % m["account"]),
+-        (util.PARSE_NICK, '@<a class="nick" href="gwibber:/user?acct=%s&name=\\1">\\1</a>' % m["account"])), escape=False)
++        (util.PARSE_NICK, '@<a class="nick" href="gwibber:/user?acct=%s&name=\\1">\\1</a>' % m["account"])), escape=False))
+ 
+       images = util.imgpreview(m["text"])
+       if images:
+@@ -96,13 +97,13 @@ class Client:
+ 
+   def _user(self, user):
+     return {
+-        "name": user["name"],
+-        "nick": user["screen_name"],
++        "name": to_unicode(user["name"]),
++        "nick": to_unicode(user["screen_name"]),
+         "id": user["id"],
+-        "location": user["location"],
++        "location": to_unicode(user["location"]),
+         "followers": user.get("followers", None),
+-        "image": user["profile_image_url"],
+-        "url": "/".join((URL_PREFIX, user["screen_name"])),
++        "image": to_unicode(user["profile_image_url"]),
++        "url": to_unicode("/".join((URL_PREFIX, user["screen_name"]))),
+         "is_me": user["screen_name"] == self.account["username"],
+     }
+     
+@@ -116,11 +117,11 @@ class Client:
+     if "in_reply_to_status_id" in data and data["in_reply_to_status_id"]:
+       m["reply"] = {}
+       m["reply"]["id"] = data["in_reply_to_status_id"]
+-      m["reply"]["nick"] = data["in_reply_to_screen_name"]
+-      m["reply"]["url"] = "/".join((URL_PREFIX, m["reply"]["nick"], "statuses", str(m["reply"]["id"])))
++      m["reply"]["nick"] = to_unicode(data["in_reply_to_screen_name"])
++      m["reply"]["url"] = to_unicode("/".join((URL_PREFIX, m["reply"]["nick"], "statuses", str(m["reply"]["id"]))))
+ 
+     m["sender"] = self._user(data["user"] if "user" in data else data["sender"])
+-    m["url"] = "/".join((m["sender"]["url"], "statuses", str(m["mid"])))
++    m["url"] = to_unicode("/".join((m["sender"]["url"], "statuses", str(m["mid"]))))
+ 
+     return m
+ 
+@@ -129,12 +130,12 @@ class Client:
+     m["private"] = True
+     
+     m["recipient"] = {}
+-    m["recipient"]["name"] = data["recipient"]["name"]
+-    m["recipient"]["nick"] = data["recipient"]["screen_name"]
++    m["recipient"]["name"] = to_unicode(data["recipient"]["name"])
++    m["recipient"]["nick"] = to_unicode(data["recipient"]["screen_name"])
+     m["recipient"]["id"] = data["recipient"]["id"]
+-    m["recipient"]["image"] = data["recipient"]["profile_image_url"]
+-    m["recipient"]["location"] = data["recipient"]["location"]
+-    m["recipient"]["url"] = "/".join((URL_PREFIX, m["recipient"]["nick"]))
++    m["recipient"]["image"] = to_unicode(data["recipient"]["profile_image_url"])
++    m["recipient"]["location"] = to_unicode(data["recipient"]["location"])
++    m["recipient"]["url"] = to_unicode("/".join((URL_PREFIX, m["recipient"]["nick"])))
+     m["recipient"]["is_me"] = m["recipient"]["nick"] == self.account["username"]
+ 
+     return m
+@@ -145,37 +146,37 @@ class Client:
+     if data["to_user_id"]:
+       m["reply"] = {}
+       m["reply"]["id"] = data["to_user_id"]
+-      m["reply"]["nick"] = data["to_user"]
++      m["reply"]["nick"] = to_unicode(data["to_user"])
+ 
+     m["sender"] = {}
+-    m["sender"]["nick"] = data["from_user"]
++    m["sender"]["nick"] = to_unicode(data["from_user"])
+     m["sender"]["id"] = data["from_user_id"]
+-    m["sender"]["image"] = data["profile_image_url"]
+-    m["sender"]["url"] = "/".join((URL_PREFIX, m["sender"]["nick"]))
++    m["sender"]["image"] = to_unicode(data["profile_image_url"])
++    m["sender"]["url"] = to_unicode("/".join((URL_PREFIX, m["sender"]["nick"])))
+     m["sender"]["is_me"] = m["sender"]["nick"] == self.account["username"]
+-    m["url"] = "/".join((m["sender"]["url"], "statuses", str(m["mid"])))
++    m["url"] = to_unicode("/".join((m["sender"]["url"], "statuses", str(m["mid"]))))
+     return m
+ 
+   def _list(self, data):
+     return {
+         "mid": data["id"],
+-        "service": "twitter",
++        "service": u"twitter",
+         "account": self.account["id"],
+         "time": 0,
+-        "text": data["description"],
+-        "html": data["description"],
+-        "content": data["description"],
+-        "url": "/".join((URL_PREFIX, data["uri"])),
+-        "sender": self._user(data["user"]),
+-        "name": data["name"],
+-        "nick": data["slug"],
++        "text": to_unicode(data["description"]),
++        "html": to_unicode(data["description"]),
++        "content": to_unicode(data["description"]),
++        "url": to_unicode("/".join((URL_PREFIX, data["uri"]))),
++        "sender": to_unicode(self._user(data["user"])),
++        "name": to_unicode(data["name"]),
++        "nick": to_unicode(data["slug"]),
+         "key": data["slug"],
+-        "full": data["full_name"],
+-        "uri": data["uri"],
++        "full": to_unicode(data["full_name"]),
++        "uri": to_unicode(data["uri"]),
+         "mode": data["mode"],
+         "members": data["member_count"],
+         "followers": data["subscriber_count"],
+-        "kind": "list",
++        "kind": u"list",
+     }
+ 
+   def _get(self, path, parse="message", post=False, single=False, **args):
diff --git a/gwibber-875bzr-right-click-to-close-stream.patch b/gwibber-875bzr-right-click-to-close-stream.patch
new file mode 100644
index 0000000..7e00dcf
--- /dev/null
+++ b/gwibber-875bzr-right-click-to-close-stream.patch
@@ -0,0 +1,30 @@
+diff -up gwibber-875bzr/ui/templates/navigation.mako.TEST gwibber-875bzr/ui/templates/navigation.mako
+--- gwibber-875bzr/ui/templates/navigation.mako.TEST	2010-10-06 15:00:44.000000000 -0400
++++ gwibber-875bzr/ui/templates/navigation.mako	2010-10-07 12:29:33.481095835 -0400
+@@ -75,10 +75,23 @@ def active(item):
+             return false;
+         });
+ 
+-        $(".compact .stream").click(function() {
+-            selectstream($(this));
+-            document.location = generateStreamURL($(this));
++        $(".compact .stream").mousedown(function(event) {
++            switch (event.which) {
++              case 1:
++              selectstream($(this));
++              document.location = generateStreamURL($(this));
++              break;
++              case 2:
++              alert("     @..@  \n      (\\--/) \n   (.>__<.)\n   ^^^  ^^^\n\nRIBBIT!");
++              break;
++              case 3:
++              document.location = "gwibber:/close?transient=" + $(this).attr("transient");
++              return false;
++              break;
++              default:
++            }
+         });
++
+       });
+     </script>
+ 
diff --git a/gwibber.spec b/gwibber.spec
index 8e5af94..61f083b 100644
--- a/gwibber.spec
+++ b/gwibber.spec
@@ -1,11 +1,11 @@
  %{!?python_sitelib: %define python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")}
 
 %global basever 2.33.0
-%global bzr_rev 867
+%global bzr_rev 875
 
 Name:           gwibber
 Version:        %{basever}
-Release:        7.%{bzr_rev}bzr%{?dist}
+Release:        11.%{bzr_rev}bzr%{?dist}
 Epoch:          1
 Summary:        An open source microblogging client for GNOME developed with Python and GTK
 Group:          Applications/Internet
@@ -19,16 +19,27 @@ URL:            https://launchpad.net/gwibber
 Source0:	gwibber-%{bzr_rev}bzr.tar.gz
 BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 
+# BigWhale's DM fixes
+Patch0:		gwibber-875bzr-BigWhale-dm-fixes.patch
+
 # Fix situation where pango_overlay can be undefined
 # https://bugs.launchpad.net/gwibber/+bug/577050
-Patch0:		gwibber-865bzr-undefined.patch
+Patch1:		gwibber-865bzr-undefined.patch
 
 # Disable libproxy support
 # It doesn't work for some unknown reason.
 Patch2:		gwibber-pre3-no-libproxy.patch
 
-# Turn off Position printing debug. Noise noise noise!
-Patch3:		gwibber-794bzr-no-Position-printing.patch
+# Handle \x00 if it shows up in our content string
+# bz 630944 & 620170
+# https://bugs.launchpad.net/gwibber/+bug/647049
+Patch3:        gwibber-867bzr-handle-x00-in-content.patch
+
+# You have to import glib to use it. ;)
+#   File "/usr/lib/python2.7/site-packages/gwibber/microblog/util/__init__.py", line 162, in notify
+#     except glib.GError as e:
+# NameError: global name 'glib' is not defined
+Patch4:        gwibber-875bzr-glib-fix.patch
 
 # Oauth bits
 Patch6:		gwibber-832bzr-twitter-oauth.patch
@@ -44,13 +55,15 @@ Patch10:	gwibber-867bzr-minimize-chars.patch
 # bz635345 bz623754
 Patch11:	gwibber-867bzr-missing-mark.patch
 
+# Fix digg
+# Taken from https://code.launchpad.net/~roignac/gwibber/Bug352226-digg-internal-errors
+Patch12:	gwibber-875bzr-digg-fix.patch
+
 # Use kitchen to force all strings generated by microblog inputs to unicode
-Patch12:	gwibber-867bzr-kitchen-utf8.patch
+Patch13:	gwibber-875bzr-kitchen-utf8.patch
 
-# Handle \x00 if it shows up in our content string
-# bz 630944 & 620170
-# https://bugs.launchpad.net/gwibber/+bug/647049
-Patch13:	gwibber-867bzr-handle-x00-in-content.patch
+# Right click on a stream in the navigation bar to close it.
+Patch14:	gwibber-875bzr-right-click-to-close-stream.patch
 
 Requires:	libsoup, python-pycurl
 Requires:	python 
@@ -81,9 +94,13 @@ and GTK. It supports Twitter, Jaiku, Identi.ca, Facebook, and Digg.
 
 %prep
 %setup -q -n gwibber-%{bzr_rev}bzr
-%patch0 -p1 -b .undefined
+
+%patch0 -p1 -b .dm
+%patch1 -p1 -b .undefined
 %patch2 -p1 -b .no-libproxy
-%patch3 -p1 -b .no-position-printing
+%patch3 -p1 -b .x00
+%patch4 -p1 -b .glibfix
+
 %patch6 -p1 -b .oauth
 
 %patch7 -p1 -b .gowalla
@@ -91,9 +108,10 @@ and GTK. It supports Twitter, Jaiku, Identi.ca, Facebook, and Digg.
 
 %patch10 -p1 -b .minimize
 
-%patch12 -p1 -b .kitchen
+%patch12 -p1 -b .diggfix
+%patch13 -p1 -b .kitchen
 
-# %%patch13 -p1 -b .x00
+%patch14 -p1 -b .right-click
 
 # sed -i -e '/^#! \?\//, 1d' $(find %{name} | grep "\.py$")
 
@@ -137,6 +155,20 @@ rm -rf %{buildroot}
 %{_datadir}/indicators/messages/applications/gwibber
 
 %changelog
+* Thu Oct  7 2010 Tom "spot" Callaway <tcallawa at redhat.com> - 1:2.33.0-11.875bzr
+- right click on a stream in the navigation bar and it closes
+- RIBBIT!
+
+* Thu Oct  7 2010 Tom "spot" Callaway <tcallawa at redhat.com> - 1:2.33.0-10.875bzr
+- fix place where glib was being used without being imported
+- apply BigWhale's DM fixes
+
+* Thu Oct  7 2010 Tom "spot" Callaway <tcallawa at redhat.com> - 1:2.33.0-9.875bzr
+- fix digg, apply kitchen changes to digg too
+
+* Wed Oct  6 2010 Tom "spot" Callaway <tcallawa at redhat.com> - 1:2.33.0-8.875bzr
+- sync to bzr875
+
 * Sat Sep 25 2010 Tom "spot" Callaway <tcallawa at redhat.com> - 1:2.33.0-7.867bzr
 - enable toshio's improved character minimization code
 
diff --git a/sources b/sources
index 75c06b3..98bed6e 100644
--- a/sources
+++ b/sources
@@ -1 +1 @@
-869d7b4909a2f88f532608bdbdf648ce  gwibber-867bzr.tar.gz
+b8cb372a52e7207c9d103387fd08d19b  gwibber-875bzr.tar.gz


More information about the scm-commits mailing list