~davidc3/onehundredscopes/opt-wikipedia

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#! /usr/bin/python

#    Copyright (c) 2011 David Calle <davidc@framli.eu>

#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.

#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.

#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.

import sys
import os
from gi.repository import GLib, GObject, Gio
from gi.repository import Dee
from gi.repository import Unity
import urllib2
import re
from xml.dom.minidom import parseString
import locale
import datetime
import random

BUS_NAME = "net.launchpad.lens.wikipedia"

class Daemon:

    def __init__ (self):
        self._lens = Unity.Lens.new ("/net/launchpad/lens/wikipedia", "wikipedia")
        self._scope = Unity.Scope.new ("/net/launchpad/lens/wikipedia/main")
        self._lens.props.search_hint = "Search Wikipedia"
        self._lens.props.visible = True;

        self._lens.add_local_scope (self._scope);
        self._scope.connect("search-changed", self.on_search_changed)
        self._scope.connect ("activate-uri", self.on_activate_uri);
        svg_dir = "/usr/share/icons/unity-icon-theme/places/svg/"
        cats = []
        cats.append (Unity.Category.new ("Articles",
                                         Gio.ThemedIcon.new(svg_dir+"group-installed.svg"),
                                         Unity.CategoryRenderer.HORIZONTAL_TILE))
        self._lens.props.categories = cats
        locale.setlocale(locale.LC_MESSAGES, '')
        loc = locale.getlocale(locale.LC_MESSAGES)[0].split("_")[0]
        self.wiki = ["http://%s.wikipedia.org" % (loc)]
        self._lens.export ();
        self._scope.export ();

    def on_search_changed (self, scope, search, search_type, *_):
        if search_type is Unity.SearchType.DEFAULT:
            search_string = search.props.search_string.strip ()
            print "Search changed to \"%s\"" % search_string
            model = search.props.results_model
            model.clear ()
            self.update_results_model(model, search_string)
            search.set_reply_hint ("no-results-hint", GLib.Variant.new_string("Sorry, there are no articles that match your search."))
        search.finished ()
        
    def update_results_model (self, model, search):
        if search == '':
            search = str(datetime.datetime.now().strftime("%B %d"))
        for site in self.wiki:
            for i in self.wikipedia_query(search, site):
                try:
                    image = i.childNodes[0].attributes["source"].value
                    text = i.childNodes[1].firstChild.data
                    comment = i.childNodes[2].firstChild.data
                    image = re.sub("/\d{1,3}px-", "/96px-", image)
                except:
					#the below line can safely be uncommented when CardView layout learns to respect not-square (in this case circlular) icons
                    #image = "http://upload.wikimedia.org/wikipedia/commons/6/63/Wikipedia-logo.png"
                    #make the thumnails for the artciles without custom thumnails have a square icon, so CardView layout won't draw ugly black outline around those, will become obsolete when CardView layot learns to respect not-square (in this case circlular) icons
                    image = "/opt/extras.ubuntu.com/unity-lens-wikipedia/media/wiki_blank-"+str(random.randint(0,1))+".png"
                    text = i.childNodes[0].firstChild.data
                    comment = i.childNodes[1].firstChild.data
                try:
                    if comment.endswith(":"):
                        comment = "may refer to several subjects..."
                    comment = comment.replace ("()", "")
                except:
                    pass

                model.append("%s/wiki/%s" % (site, text),
                            image,
                            0,
                            "text/html",
                            text,
                            comment,
                            "%s/wiki/%s" % (site, text))

    def wikipedia_query(self,search, site):
        try:
            search = search.replace(" ", "|")
            url = ("%s/w/api.php?action=opensearch&limit=25&format=xml&search=%s" % (site, search))
            results = parseString(urllib2.urlopen(url).read())
            items = results.getElementsByTagName('Item')
            print "Searching Wikipedia: "+url
            return items
        except (IOError, KeyError, urllib2.URLError, urllib2.HTTPError):
            print "Error : Unable to search Wikipedia"
            return []

    def on_activate_uri (self, scope, uri):
#        GLib.spawn_command_line_async('notify-send -i "%s" "%s" "%s"' % ('applications-graphics',notification_title, notification_text))
        print Unity.ActivationResponse(Unity.HandledType.HIDE_DASH, '')
#        return Unity.ActivationResponse(Unity.HandledType.HIDE_DASH,'')

if __name__ == "__main__":
    session_bus_connection = Gio.bus_get_sync (Gio.BusType.SESSION, None)
    session_bus = Gio.DBusProxy.new_sync (session_bus_connection, 0, None,
                                          'org.freedesktop.DBus',
                                          '/org/freedesktop/DBus',
                                          'org.freedesktop.DBus', None)
    result = session_bus.call_sync('RequestName',
                                   GLib.Variant ("(su)", (BUS_NAME, 0x4)),
                                   0, -1, None)
                                   
    result = result.unpack()[0]
    
    if result != 1 :
        print >> sys.stderr, "Failed to own name %s. Bailing out." % BUS_NAME
        raise SystemExit (1)
    
    daemon = Daemon()
    GObject.MainLoop().run()