~sdague/onehundredscopes/unity-lens-pidgin

« back to all changes in this revision

Viewing changes to src/unity-lens-pidgin

  • Committer: Sean Dague
  • Date: 2012-05-06 15:39:22 UTC
  • Revision ID: sean@dague.net-20120506153922-8o6ca4wz49sdso7r
initial dump of pidgin lens. This only currently can search online buddies,
still can't yet open the conversation

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#! /usr/bin/python
 
2
 
 
3
#    Copyright (c) 2011 David Calle <davidc@framli.eu>
 
4
 
 
5
#    This program is free software: you can redistribute it and/or modify
 
6
#    it under the terms of the GNU General Public License as published by
 
7
#    the Free Software Foundation, either version 3 of the License, or
 
8
#    (at your option) any later version.
 
9
 
 
10
#    This program is distributed in the hope that it will be useful,
 
11
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
#    GNU General Public License for more details.
 
14
 
 
15
#    You should have received a copy of the GNU General Public License
 
16
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
17
 
 
18
import sys
 
19
import os
 
20
import glob
 
21
from gi.repository import GLib, GObject, Gio
 
22
from gi.repository import Dee
 
23
from gi.repository import Unity
 
24
import dbus
 
25
import urllib2
 
26
import simplejson
 
27
import locale
 
28
import datetime
 
29
import pprint
 
30
import xml.etree.ElementTree
 
31
 
 
32
BUS_NAME = "net.launchpad.lens.pidgin"
 
33
 
 
34
class Daemon:
 
35
 
 
36
    def __init__ (self):
 
37
        self.error_connect = False
 
38
        self._pidgin = Pidgin()
 
39
 
 
40
        # The path for the Lens *must* also match the one in our .lens file
 
41
        self._lens = Unity.Lens.new ("/net/launchpad/lens/pidgin", "pidgin")
 
42
        self._scope = Unity.Scope.new ("/net/launchpad/lens/pidgin/main")
 
43
        self._scope.search_in_global = True
 
44
 
 
45
        self._lens.props.search_hint = "Search Pidgin"
 
46
        self._lens.props.visible = True;
 
47
        self._lens.props.search_in_global = True;
 
48
        self._lens.props.sources_display_name = ("Pidgin Configs")
 
49
 
 
50
 
 
51
        self._lens.add_local_scope (self._scope);
 
52
        self._scope.connect("search-changed", self.on_search_changed)
 
53
        svg_dir = "/usr/share/icons/unity-icon-theme/places/svg/"
 
54
 
 
55
        # Populate categories
 
56
        cats = []
 
57
        cats.append (Unity.Category.new ("Online Buddies",
 
58
                                         Gio.ThemedIcon.new(svg_dir+"group-installed.svg"),
 
59
                                         Unity.CategoryRenderer.VERTICAL_TILE))
 
60
        self._lens.props.categories = cats
 
61
 
 
62
        locale.setlocale(locale.LC_MESSAGES, '')
 
63
        loc = locale.getlocale(locale.LC_MESSAGES)[0].split("_")[0]
 
64
 
 
65
        self._lens.export ();
 
66
        self._scope.export ();
 
67
 
 
68
 
 
69
    def on_search_changed (self, scope, search, search_type, *_):
 
70
        #        if search_type is Unity.SearchType.DEFAULT:
 
71
        search_string = search.props.search_string.strip()
 
72
        print "Search changed to \"%s\"" % search_string
 
73
        model = search.props.results_model
 
74
        model.clear()
 
75
        self.update_results_model(model, search_string)
 
76
        search.set_reply_hint ("no-results-hint", GLib.Variant.new_string("Sorry, there are no articles that match your search."))
 
77
        search.finished()
 
78
 
 
79
    def update_results_model (self, model, search):
 
80
        if search == '':
 
81
            return
 
82
 
 
83
        buddies = self._pidgin.search(search)
 
84
 
 
85
        for buddy in buddies:
 
86
            model.append("file://%s" % buddy["icon"],
 
87
                         "file://%s" % buddy["icon"],
 
88
                         0,
 
89
                         "text/html",
 
90
                         buddy["alias"],
 
91
                         "Buddy Name",
 
92
                         "file://%s" % buddy["icon"],
 
93
                         )
 
94
 
 
95
    def _search_pidgin(self,  name):
 
96
 
 
97
        buddies = []
 
98
        for account in self._purple.PurpleAccountsGetAllActive():
 
99
            buddylist = self._purple.PurpleFindBuddies(account, '')
 
100
            for buddyid in buddylist:
 
101
                buddy =  {}
 
102
                buddy["name"] = self._purple.PurpleBuddyGetName(buddyid)
 
103
                buddy["online"] = self._purple.PurpleBuddyIsOnline(buddyid)
 
104
                buddy["icon"] = self._purple.PurpleBuddyGetIcon(buddyid)
 
105
                buddy["alias"] = self._purple.PurpleBuddyGetAlias(buddyid)
 
106
                if buddy["online"] != 0:
 
107
                    buddies.append(buddy)
 
108
 
 
109
        pprint.pprint(buddies)
 
110
 
 
111
class Pidgin:
 
112
 
 
113
    def __init__(self):
 
114
        self._parse_blist()
 
115
        self._bus = dbus.SessionBus()
 
116
        obj = self._bus.get_object("im.pidgin.purple.PurpleService", "/im/pidgin/purple/PurpleObject")
 
117
        self._purple = dbus.Interface(obj, "im.pidgin.purple.PurpleInterface")
 
118
 
 
119
    def _gather_buddies(self):
 
120
        self._buddies = []
 
121
        for account in self._purple.PurpleAccountsGetAllActive():
 
122
            accountname = self._purple.PurpleAccountGetUsername(account)
 
123
            buddylist = self._purple.PurpleFindBuddies(account, '')
 
124
            for buddyid in buddylist:
 
125
                buddy =  {}
 
126
                buddy["account"] = accountname
 
127
                buddy["name"] = self._purple.PurpleBuddyGetName(buddyid)
 
128
                buddy["online"] = self._purple.PurpleBuddyIsOnline(buddyid)
 
129
                buddy["alias"] = self._purple.PurpleBuddyGetAlias(buddyid)
 
130
                if buddy["online"] != 0:
 
131
                    self._buddies.append(buddy)
 
132
 
 
133
        return self._buddies
 
134
 
 
135
    def _parse_blist(self):
 
136
        self._cache = {}
 
137
        fp = open("/home/sdague/.purple/blist.xml")
 
138
        element = xml.etree.ElementTree.parse(fp).getroot()
 
139
        buddies = element.findall("blist/group/contact/buddy")
 
140
        for buddy in buddies:
 
141
            account = buddy.attrib["account"]
 
142
            if not account in self._cache:
 
143
                self._cache[account] = {}
 
144
 
 
145
            name = buddy.getchildren()[0].text
 
146
            if not name in self._cache[account]:
 
147
                self._cache[account][name] = {}
 
148
 
 
149
            for elem in buddy.getchildren():
 
150
                if elem.tag == "alias":
 
151
                    self._cache[account][name]["alias"] = elem.text
 
152
                if elem.tag == "setting" and elem.attrib["name"] == "buddy_icon":
 
153
                    self._cache[account][name]["icon"] = elem.text
 
154
 
 
155
        pprint.pprint(self._cache)
 
156
        fp.close()
 
157
 
 
158
    def _icon_for_buddy(self, buddy):
 
159
        if "icon" in self._cache[buddy["account"]][buddy["name"]]:
 
160
            icon = self._cache[buddy["account"]][buddy["name"]]["icon"]
 
161
            return "%s/.purple/icons/%s" % (os.environ["HOME"], icon)
 
162
        else:
 
163
            return "%s/.purple/icons/%s" % (os.environ["HOME"], "")
 
164
 
 
165
    def search(self,  string):
 
166
        buddies = self._gather_buddies()
 
167
        results = []
 
168
        for buddy in buddies:
 
169
            if ((buddy["name"].lower().find(string) >=0) or
 
170
                (buddy["alias"].lower().find(string) >=0) ):
 
171
 
 
172
                buddy["icon"] = self._icon_for_buddy(buddy)
 
173
                results.append(buddy)
 
174
        return results
 
175
 
 
176
 
 
177
 
 
178
if __name__ == "__main__":
 
179
    session_bus_connection = Gio.bus_get_sync (Gio.BusType.SESSION, None)
 
180
    session_bus = Gio.DBusProxy.new_sync (session_bus_connection, 0, None,
 
181
                                          'org.freedesktop.DBus',
 
182
                                          '/org/freedesktop/DBus',
 
183
                                          'org.freedesktop.DBus', None)
 
184
    result = session_bus.call_sync('RequestName',
 
185
                                   GLib.Variant ("(su)", (BUS_NAME, 0x4)),
 
186
                                   0, -1, None)
 
187
 
 
188
    # Unpack variant response with signature "(u)". 1 means we got it.
 
189
    result = result.unpack()[0]
 
190
 
 
191
    if result != 1 :
 
192
        print >> sys.stderr, "Failed to own name %s. Bailing out." % BUS_NAME
 
193
        raise SystemExit (1)
 
194
 
 
195
    daemon = Daemon()
 
196
    GObject.MainLoop().run()