Added support for Qaiku
authorRyan Paul <segphault@arstechnica.com>
Sun, 21 Jun 2009 01:28:19 +0000 (18:28 -0700)
committerRyan Paul <segphault@arstechnica.com>
Sun, 21 Jun 2009 01:28:19 +0000 (18:28 -0700)
gwibber/microblog/__init__.py
gwibber/microblog/qaiku.py [new file with mode: 0644]
ui/preferences.glade

index e83b567..574c6de 100644 (file)
@@ -3,7 +3,7 @@ import operator, traceback
 from . import can
 from . import twitter, jaiku, identica, laconica, pownce, friendfeed
 from . import digg, flickr, brightkite, rss, pingfm, facebook
-from . import greader
+from . import greader, qaiku
 
 # i18n magic
 import gettext
@@ -24,6 +24,7 @@ PROTOCOLS = {
   "pingfm": pingfm,
   "greader": greader,
   "brightkite": brightkite,
+  "qaiku": qaiku,
 }
 
 def supports(a, feature):
diff --git a/gwibber/microblog/qaiku.py b/gwibber/microblog/qaiku.py
new file mode 100644 (file)
index 0000000..45cc084
--- /dev/null
@@ -0,0 +1,149 @@
+"""
+
+Qaiku interface for Gwibber
+SegPhault (Ryan
+
+"""
+
+
+from . import can, support
+import urllib2, urllib, re, simplejson, base64
+from gettext import lgettext as _
+
+PROTOCOL_INFO = {
+  "name": "Qaiku",
+  "version": 0.1,
+  
+  "config": [
+    "private:password",
+    "username",
+    "message_color",
+    "comment_color",
+    "receive_enabled",
+    "send_enabled"
+  ],
+
+  "features": [
+    can.SEND,
+    can.RECEIVE,
+    can.SEARCH,
+    can.REPLY,
+    #can.RESPONSES,
+    can.DELETE,
+    can.THREAD,
+    can.THREAD_REPLY,
+    can.USER_MESSAGES,
+  ],
+}
+
+NICK_PARSE = re.compile("\B@([A-Za-z0-9_]+|@[A-Za-z0-9_]$)")
+HASH_PARSE = re.compile("\B#([A-Za-z0-9_\-]+|@[A-Za-z0-9_\-]$)")
+
+class Message:
+  def __init__(self, client, data):
+    self.client = client
+    self.account = client.account
+    self.protocol = client.account["protocol"]
+    self.username = client.account["username"]
+    self.id = data["id"] or ''
+    self.time = support.parse_time(data["created_at"])
+    self.is_private  = False
+
+    user = data["user"]
+    #self.reply_nick = data["in_reply_to_user_id"]
+    self.reply_url = "http://qaiku.com/home/%s/show/%s" % (user["screen_name"], data["id"])
+    self.reply_id = data["in_reply_to_status_id"]
+    self.bgcolor = "comment_color" if self.reply_id else "message_color"
+
+    self.sender = user["name"]
+    self.sender_nick = user["screen_name"]
+    self.sender_id = user["id"]
+    self.sender_location = user["location"]
+    self.sender_followers_count = user["followers_count"]
+    self.image = user["profile_image_url"]
+    self.url = "http://qaiku.com/home/%s/show/%s" % (user["screen_name"], data["id"])
+    self.profile_url = "gwibber:user/%s/%s" % (self.account.id, user["screen_name"])
+    self.external_profile_url = user["url"]
+
+    self.text = data["text"]
+    self.html_string = '<span class="text">%s</span>' % \
+        HASH_PARSE.sub('#<a class="inlinehash" href="gwibber:tag/\\1">\\1</a>',
+        NICK_PARSE.sub('@<a class="inlinenick" href="gwibber:user/'+self.account.id+'/\\1">\\1</a>',
+        support.linkify(self.text)))
+    self.is_reply = re.compile("@%s[\W]+|@%s$" % (self.username, self.username)).search(self.text)
+    self.can_thread = True
+
+class Client:
+  def __init__(self, acct):
+    self.account = acct
+
+  def send_enabled(self):
+    return self.account["send_enabled"] and \
+      self.account["username"] != None and \
+      self.account["private:password"] != None
+
+  def receive_enabled(self):
+    return self.account["receive_enabled"] and \
+      self.account["username"] != None and \
+      self.account["private:password"] != None
+
+  def get_auth(self):
+    return "Basic %s" % base64.encodestring(
+      ("%s:%s" % (self.account["username"], self.account["private:password"]))).strip()
+
+  def connect(self, url, data = None):
+    return urllib2.urlopen(urllib2.Request("http://www.qaiku.com/api" + url,
+      data, headers = {"Authorization": self.get_auth()}))
+
+  def get_messages(self):
+    return simplejson.load(self.connect("/statuses/friends_timeline.json"))
+
+  def get_user_messages(self, screen_name):
+    return simplejson.load(self.connect("/statuses/user_timeline.json" +'?'+
+        urllib.urlencode({"screen_name": screen_name})))
+
+  def get_search_data(self, query):
+    return simplejson.load(self.connect("/search.json?" +
+        urllib.urlencode({"q": query})))
+
+  def get_thread_data(self, msg):
+    return simplejson.load(self.connect(
+      "/statuses/replies/%s.json" % msg.reply_id or msg.id))
+
+  def get_message_data(self, id):
+    return simplejson.load(self.connect(
+      "/statuses/show/%s.json" % id))
+
+  def get_thread(self, msg):
+    yield Message(self, self.get_message_data(msg.reply_id or msg.id))
+    for data in self.get_thread_data(msg):
+      yield Message(self, data)
+
+  def search(self, query):
+    for data in self.get_search_data(query):
+      if data["user"]:
+        yield Message(self, data)
+
+  def receive(self):
+    for data in self.get_messages():
+      if data["user"]:
+        yield Message(self, data)
+
+  def user_messages(self, screen_name):
+    for data in self.get_user_messages(screen_name):
+      yield Message(self, data)
+
+  def delete(self, message):
+    return simplejson.load(self.connect(
+      "/statuses/destroy/%s.json" % message.id, {}))
+  
+  def send(self, message):
+    data = simplejson.load(self.connect("/statuses/update.json",
+      urllib.urlencode({"status":message})))
+    return Message(self, data)
+
+  def send_thread(self, message, target):
+    data = simplejson.load(self.connect("/statuses/update.json",
+      urllib.urlencode({"status":message, "in_reply_to_status_id": target.id})))
+    return Message(self, data)
+
index 7fe3f00..5f36924 100644 (file)
@@ -4379,4 +4379,285 @@ a Gwibber login code from Facebook.</property>
       </widget>
     </child>
   </widget>
+  <widget class="GtkDialog" id="dialog_qaiku">
+    <property name="border_width">5</property>
+    <property name="window_position">center-on-parent</property>
+    <property name="type_hint">dialog</property>
+    <child internal-child="vbox">
+      <widget class="GtkVBox" id="dialog-vbox20">
+        <property name="visible">True</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">2</property>
+        <child>
+          <widget class="GtkVBox" id="vbox10">
+            <property name="visible">True</property>
+            <property name="orientation">vertical</property>
+            <property name="spacing">10</property>
+            <child>
+              <widget class="GtkFrame" id="frameAccount3">
+                <property name="visible">True</property>
+                <property name="label_xalign">0</property>
+                <property name="shadow_type">none</property>
+                <child>
+                  <widget class="GtkAlignment" id="alignment14">
+                    <property name="visible">True</property>
+                    <property name="top_padding">10</property>
+                    <property name="left_padding">12</property>
+                    <child>
+                      <widget class="GtkTable" id="table5">
+                        <property name="visible">True</property>
+                        <property name="n_rows">2</property>
+                        <property name="n_columns">2</property>
+                        <property name="column_spacing">5</property>
+                        <property name="row_spacing">5</property>
+                        <child>
+                          <widget class="GtkEntry" id="qaiku_password">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="visibility">False</property>
+                            <property name="invisible_char">&#x2022;</property>
+                          </widget>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">1</property>
+                            <property name="bottom_attach">2</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <widget class="GtkEntry" id="qaiku_username">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="invisible_char">&#x2022;</property>
+                          </widget>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <widget class="GtkLabel" id="label25">
+                            <property name="visible">True</property>
+                            <property name="label" translatable="yes">API key:</property>
+                          </widget>
+                          <packing>
+                            <property name="top_attach">1</property>
+                            <property name="bottom_attach">2</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <widget class="GtkLabel" id="label26">
+                            <property name="visible">True</property>
+                            <property name="label" translatable="yes">Username:</property>
+                          </widget>
+                        </child>
+                      </widget>
+                    </child>
+                  </widget>
+                </child>
+                <child>
+                  <widget class="GtkLabel" id="label28">
+                    <property name="visible">True</property>
+                    <property name="label" translatable="yes">&lt;b&gt;Account Information&lt;/b&gt;</property>
+                    <property name="use_markup">True</property>
+                  </widget>
+                  <packing>
+                    <property name="type">label_item</property>
+                  </packing>
+                </child>
+              </widget>
+              <packing>
+                <property name="expand">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <widget class="GtkFrame" id="frameStatus3">
+                <property name="visible">True</property>
+                <property name="label_xalign">0</property>
+                <property name="shadow_type">none</property>
+                <child>
+                  <widget class="GtkAlignment" id="alignment15">
+                    <property name="visible">True</property>
+                    <property name="top_padding">10</property>
+                    <property name="left_padding">12</property>
+                    <child>
+                      <widget class="GtkVBox" id="vbox11">
+                        <property name="visible">True</property>
+                        <property name="orientation">vertical</property>
+                        <child>
+                          <widget class="GtkCheckButton" id="qaiku_receive_enabled">
+                            <property name="label" translatable="yes">_Receive Messages</property>
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">False</property>
+                            <property name="use_underline">True</property>
+                            <property name="draw_indicator">True</property>
+                          </widget>
+                          <packing>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <widget class="GtkCheckButton" id="qaiku_send_enabled">
+                            <property name="label" translatable="yes">_Send Messages</property>
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">False</property>
+                            <property name="use_underline">True</property>
+                            <property name="draw_indicator">True</property>
+                          </widget>
+                          <packing>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                      </widget>
+                    </child>
+                  </widget>
+                </child>
+                <child>
+                  <widget class="GtkLabel" id="label29">
+                    <property name="visible">True</property>
+                    <property name="label" translatable="yes">&lt;b&gt;Account Status&lt;/b&gt;</property>
+                    <property name="use_markup">True</property>
+                  </widget>
+                  <packing>
+                    <property name="type">label_item</property>
+                  </packing>
+                </child>
+              </widget>
+              <packing>
+                <property name="expand">False</property>
+                <property name="position">3</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkFrame" id="frameAppearance3">
+                <property name="visible">True</property>
+                <property name="label_xalign">0</property>
+                <property name="shadow_type">none</property>
+                <child>
+                  <widget class="GtkAlignment" id="alignment16">
+                    <property name="visible">True</property>
+                    <property name="top_padding">10</property>
+                    <property name="left_padding">12</property>
+                    <child>
+                      <widget class="GtkTable" id="table13">
+                        <property name="visible">True</property>
+                        <property name="n_rows">2</property>
+                        <property name="n_columns">2</property>
+                        <child>
+                          <widget class="GtkLabel" id="label30">
+                            <property name="visible">True</property>
+                            <property name="label" translatable="yes">Message Color:</property>
+                          </widget>
+                        </child>
+                        <child>
+                          <widget class="GtkLabel" id="label62">
+                            <property name="visible">True</property>
+                            <property name="label" translatable="yes">Comment Color:</property>
+                          </widget>
+                          <packing>
+                            <property name="top_attach">1</property>
+                            <property name="bottom_attach">2</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <widget class="GtkColorButton" id="qaiku_message_color">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">True</property>
+                            <property name="color">#000000000000</property>
+                          </widget>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <widget class="GtkColorButton" id="qaiku_comment_color">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">True</property>
+                            <property name="color">#000000000000</property>
+                          </widget>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">1</property>
+                            <property name="bottom_attach">2</property>
+                          </packing>
+                        </child>
+                      </widget>
+                    </child>
+                  </widget>
+                </child>
+                <child>
+                  <widget class="GtkLabel" id="label31">
+                    <property name="visible">True</property>
+                    <property name="label" translatable="yes">&lt;b&gt;Appearance&lt;/b&gt;</property>
+                    <property name="use_markup">True</property>
+                  </widget>
+                  <packing>
+                    <property name="type">label_item</property>
+                  </packing>
+                </child>
+              </widget>
+              <packing>
+                <property name="expand">False</property>
+                <property name="position">4</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child internal-child="action_area">
+          <widget class="GtkHButtonBox" id="dialog-action_area20">
+            <property name="visible">True</property>
+            <child>
+              <widget class="GtkButton" id="qaiku_btndelete">
+                <property name="label">gtk-delete</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+              </widget>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkButton" id="qaiku_btnclose">
+                <property name="label">gtk-close</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+              </widget>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+      </widget>
+    </child>
+  </widget>
 </glade-interface>