2
# -*- coding: utf-8 -*-
4
# Copyright (C) 2013 David Callé <davidc@framli.eu>
5
# This program is free software: you can redistribute it and/or modify it
6
# under the terms of the GNU General Public License version 3, as published
7
# by the Free Software Foundation.
9
# This program is distributed in the hope that it will be useful, but
10
# WITHOUT ANY WARRANTY; without even the implied warranties of
11
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
12
# PURPOSE. See the GNU General Public License for more details.
14
# You should have received a copy of the GNU General Public License along
15
# with this program. If not, see <http://www.gnu.org/licenses/>.
17
from gi.repository import Unity, UnityExtras
18
from gi.repository import Gio, GLib
24
APP_NAME = 'unity-scope-reddit'
25
LOCAL_PATH = '/usr/share/locale/'
26
gettext.bindtextdomain(APP_NAME, LOCAL_PATH)
27
gettext.textdomain(APP_NAME)
30
GROUP_NAME = 'com.canonical.Unity.Scope.Info.Reddit'
31
UNIQUE_PATH = '/com/canonical/unity/scope/info/reddit'
32
SEARCH_URI = 'https://reddit.com/'
33
SEARCH_HINT = _('Search Reddit')
34
NO_RESULTS_HINT = _('Sorry, there are no subreddits that match your search.')
35
PROVIDER_CREDITS = _('Powered by Reddit')
36
SVG_DIR = '/usr/share/icons/unity-icon-theme/places/svg/'
37
PROVIDER_ICON = SVG_DIR+'service-reddit.svg'
38
DEFAULT_RESULT_ICON = SVG_DIR+'result-info.svg'
39
DEFAULT_RESULT_MIMETYPE = 'text/html'
40
DEFAULT_RESULT_TYPE = Unity.ResultType.DEFAULT
45
'icon' :SVG_DIR+'group-installed.svg',
46
'renderer':Unity.CategoryRenderer.VERTICAL_TILE}
49
'icon' :SVG_DIR+'group-installed.svg',
50
'renderer':Unity.CategoryRenderer.VERTICAL_TILE}
51
c2 = {'id' :'controversial',
52
'name' :_('Controversial'),
53
'icon' :SVG_DIR+'group-installed.svg',
54
'renderer':Unity.CategoryRenderer.VERTICAL_TILE}
57
'icon' :SVG_DIR+'group-installed.svg',
58
'renderer':Unity.CategoryRenderer.VERTICAL_TILE}
65
'field':Unity.SchemaFieldType.OPTIONAL}
68
'field':Unity.SchemaFieldType.OPTIONAL}
69
EXTRA_METADATA = [m1, m2]
71
def search(search, filters):
73
Any search method returning results as a list of tuples.
74
Available tuple fields:
82
result_type (Unity ResultType)
83
extras metadata fields (variant)
88
search = urllib.parse.quote(search)
89
cats = ['hot', 'new', 'controversial', 'top']
91
uri = '%sr/%s/%s.json?limit=25' % (SEARCH_URI, search, cat)
95
response = urllib.request.urlopen(uri).read()
96
data = json.loads(response.decode('utf-8'))
97
except Exception as error:
103
if not data or not 'data' in data:
105
for d in data ['data']['children']:
106
if d['data']['over_18'] is True:
109
icon = d['data']['thumbnail']
110
results.append({'uri':'%s%s' % (SEARCH_URI, d['data']['permalink']),
111
'title':d['data']['title'],
113
'target':GLib.Variant('s', d['data']['url']),
114
'author':GLib.Variant('s', d['data']['author']),
115
'category':cats.index(cat)})
119
# Classes below this point establish communication
120
# with Unity, you probably shouldn't modify them.
123
class MySearch (Unity.ScopeSearchBase):
124
def __init__(self, search_context):
125
super (MySearch, self).__init__()
126
self.set_search_context (search_context)
130
Adds results to the model
133
result_set = self.search_context.result_set
134
for i in search(self.search_context.search_query,
135
self.search_context.filter_state):
136
if not 'uri' in i or not i['uri'] or i['uri'] == '':
138
if not 'icon' in i or not i['icon'] or i['icon'] == '':
139
i['icon'] = DEFAULT_RESULT_ICON
140
if not 'mimetype' in i or not i['mimetype'] or i['mimetype'] == '':
141
i['mimetype'] = DEFAULT_RESULT_MIMETYPE
142
if not 'result_type' in i or not i['result_type'] or i['result_type'] == '':
143
i['result_type'] = DEFAULT_RESULT_TYPE
144
if not 'category' in i or not i['category'] or i['category'] == '':
146
if not 'title' in i or not i['title']:
148
if not 'comment' in i or not i['comment']:
150
if not 'dnd_uri' in i or not i['dnd_uri'] or i['dnd_uri'] == '':
151
i['dnd_uri'] = i['uri']
155
for m in EXTRA_METADATA:
157
i['metadata'][e] = i[e]
158
i['metadata']['provider_credits'] = GLib.Variant('s', PROVIDER_CREDITS)
159
result = Unity.ScopeResult.create(str(i['uri']), str(i['icon']),
160
i['category'], i['result_type'],
161
str(i['mimetype']), str(i['title']),
162
str(i['comment']), str(i['dnd_uri']),
164
result_set.add_result(result)
165
except Exception as error:
168
class Scope (Unity.AbstractScope):
170
Unity.AbstractScope.__init__(self)
172
def do_get_search_hint (self):
175
def do_get_schema (self):
177
Adds specific metadata fields
179
schema = Unity.Schema.new ()
181
for m in EXTRA_METADATA:
182
schema.add_field(m['id'], m['type'], m['field'])
183
#FIXME should be REQUIRED for credits
184
schema.add_field('provider_credits', 's', Unity.SchemaFieldType.OPTIONAL)
187
def do_get_categories (self):
191
cs = Unity.CategorySet.new ()
194
cat = Unity.Category.new (c['id'], c['name'],
195
Gio.ThemedIcon.new(c['icon']),
200
def do_get_filters (self):
204
fs = Unity.FilterSet.new ()
209
def do_get_group_name (self):
212
def do_get_unique_name (self):
215
def do_create_search_for_query (self, search_context):
216
se = MySearch (search_context)