Merge lp:~verterok/ubuntu-scopes/themoviedb-fix-results-and-previews into lp:~submarine/ubuntu-scopes/themoviedb

Proposed by Guillermo Gonzalez
Status: Rejected
Rejected by: Guillermo Gonzalez
Proposed branch: lp:~verterok/ubuntu-scopes/themoviedb-fix-results-and-previews
Merge into: lp:~submarine/ubuntu-scopes/themoviedb
Diff against target: 380 lines (+193/-40)
3 files modified
data/themoviedb.scope.in (+2/-1)
po/unity-scope-themoviedb.pot (+47/-7)
src/unity_themoviedb_daemon.py (+144/-32)
To merge this branch: bzr merge lp:~verterok/ubuntu-scopes/themoviedb-fix-results-and-previews
Reviewer Review Type Date Requested Status
Submarine Pending
Review via email: mp+184587@code.launchpad.net

Commit message

Fix ScopeResults build (preserve metadata) and also add movie and person previews.

Description of the change

This branch change the way ScopeResults are create, stop using ScopeResult.create and use result_set.add(**result), and also adds movie and person previews.

To post a comment you must log in.
7. By Guillermo Gonzalez

add people_id to OptionalMetadata and fix EXTRA_METADATA reference

Unmerged revisions

7. By Guillermo Gonzalez

add people_id to OptionalMetadata and fix EXTRA_METADATA reference

6. By Guillermo Gonzalez

add first version of person preview

5. By Guillermo Gonzalez

- fix results building
- add custom movie preview, with extra data (not part of the result)
- added Master key to themoviedb.scope.in

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'data/themoviedb.scope.in'
2--- data/themoviedb.scope.in 2013-03-08 14:50:12 +0000
3+++ data/themoviedb.scope.in 2013-09-09 14:43:25 +0000
4@@ -4,10 +4,11 @@
5 Icon=
6 _Keywords=themoviedb;movie;db;actor;cinema;
7 RequiredMetadata=
8-OptionalMetadata=
9+OptionalMetadata=movie_id[s];people_id[s];
10 Loader=/usr/lib/ubuntu-scopes/themoviedb/unity_themoviedb_daemon.py
11 RemoteContent=true
12 Type=reference
13+Master=reference
14 _Name=themoviedb.org
15 _Description=Find themoviedb.org items
16 _SearchHint=Search themoviedb.org
17
18=== modified file 'po/unity-scope-themoviedb.pot'
19--- po/unity-scope-themoviedb.pot 2013-03-08 14:50:12 +0000
20+++ po/unity-scope-themoviedb.pot 2013-09-09 14:43:25 +0000
21@@ -8,7 +8,7 @@
22 msgstr ""
23 "Project-Id-Version: PACKAGE VERSION\n"
24 "Report-Msgid-Bugs-To: \n"
25-"POT-Creation-Date: 2013-03-08 15:49+0100\n"
26+"POT-Creation-Date: 2013-09-09 11:37-0300\n"
27 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
28 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
29 "Language-Team: LANGUAGE <LL@li.org>\n"
30@@ -17,30 +17,70 @@
31 "Content-Type: text/plain; charset=CHARSET\n"
32 "Content-Transfer-Encoding: 8bit\n"
33
34-#: ../src/unity_themoviedb_daemon.py:35 ../data/themoviedb.scope.in.h:4
35+#: ../src/unity_themoviedb_daemon.py:38 ../data/themoviedb.scope.in.h:4
36 msgid "Search themoviedb.org"
37 msgstr ""
38
39-#: ../src/unity_themoviedb_daemon.py:36
40+#: ../src/unity_themoviedb_daemon.py:39
41 msgid "Sorry, there are no movies or people that match your search."
42 msgstr ""
43
44-#: ../src/unity_themoviedb_daemon.py:37
45+#: ../src/unity_themoviedb_daemon.py:40
46 msgid "Powered by themoviedb.org"
47 msgstr ""
48
49-#: ../src/unity_themoviedb_daemon.py:45
50+#: ../src/unity_themoviedb_daemon.py:48
51 msgid "Global"
52 msgstr ""
53
54-#: ../src/unity_themoviedb_daemon.py:49
55+#: ../src/unity_themoviedb_daemon.py:52
56 msgid "Movies"
57 msgstr ""
58
59-#: ../src/unity_themoviedb_daemon.py:53
60+#: ../src/unity_themoviedb_daemon.py:56
61 msgid "People"
62 msgstr ""
63
64+#: ../src/unity_themoviedb_daemon.py:234
65+msgid "Release date"
66+msgstr ""
67+
68+#: ../src/unity_themoviedb_daemon.py:236
69+msgid "Status"
70+msgstr ""
71+
72+#: ../src/unity_themoviedb_daemon.py:237
73+msgid "Genres"
74+msgstr ""
75+
76+#: ../src/unity_themoviedb_daemon.py:238
77+msgid "Runtime"
78+msgstr ""
79+
80+#: ../src/unity_themoviedb_daemon.py:239
81+msgid "Description"
82+msgstr ""
83+
84+#: ../src/unity_themoviedb_daemon.py:242 ../src/unity_themoviedb_daemon.py:299
85+msgid "The Movie DB"
86+msgstr ""
87+
88+#: ../src/unity_themoviedb_daemon.py:279
89+msgid "Homepage"
90+msgstr ""
91+
92+#: ../src/unity_themoviedb_daemon.py:280
93+msgid "Place of birth"
94+msgstr ""
95+
96+#: ../src/unity_themoviedb_daemon.py:281
97+msgid "Also known as"
98+msgstr ""
99+
100+#: ../src/unity_themoviedb_daemon.py:282
101+msgid "Popularity"
102+msgstr ""
103+
104 #: ../data/themoviedb.scope.in.h:1
105 msgid "themoviedb;movie;db;actor;cinema;"
106 msgstr ""
107
108=== modified file 'src/unity_themoviedb_daemon.py'
109--- src/unity_themoviedb_daemon.py 2013-03-08 14:49:44 +0000
110+++ src/unity_themoviedb_daemon.py 2013-09-09 14:43:25 +0000
111@@ -2,25 +2,27 @@
112 # -*- coding: utf-8 -*-
113
114 # Copyright (C) 2013 David Callé <davidc@framli.eu>
115-# This program is free software: you can redistribute it and/or modify it
116-# under the terms of the GNU General Public License version 3, as published
117+# This program is free software: you can redistribute it and/or modify it
118+# under the terms of the GNU General Public License version 3, as published
119 # by the Free Software Foundation.
120-#
121-# This program is distributed in the hope that it will be useful, but
122-# WITHOUT ANY WARRANTY; without even the implied warranties of
123-# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
124+#
125+# This program is distributed in the hope that it will be useful, but
126+# WITHOUT ANY WARRANTY; without even the implied warranties of
127+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
128 # PURPOSE. See the GNU General Public License for more details.
129-#
130-# You should have received a copy of the GNU General Public License along
131+#
132+# You should have received a copy of the GNU General Public License along
133 # with this program. If not, see <http://www.gnu.org/licenses/>.
134
135-from gi.repository import Unity, UnityExtras
136-from gi.repository import Gio, GLib
137+import os
138 import urllib.parse
139 import urllib.request
140 import json
141 import gettext
142
143+from gi.repository import Unity
144+from gi.repository import Gio, GLib
145+
146 APP_NAME = 'unity-scope-themoviedb'
147 LOCAL_PATH = '/usr/share/locale/'
148 gettext.bindtextdomain(APP_NAME, LOCAL_PATH)
149@@ -31,6 +33,7 @@
150 UNIQUE_PATH = '/com/canonical/unity/scope/reference/themoviedb'
151 CONFIG_URI = 'https://api.themoviedb.org/3/'
152 SEARCH_URI = 'https://api.themoviedb.org/3/'
153+MOVIE_URI = 'https://api.themoviedb.org/3/movie'
154 API_KEY = 'bbfb28cb1b07e184a58554a6641c75c4'
155 SEARCH_HINT = _('Search themoviedb.org')
156 NO_RESULTS_HINT = _('Sorry, there are no movies or people that match your search.')
157@@ -45,11 +48,11 @@
158 'name' :_('Global'),
159 'icon' :SVG_DIR+'group-installed.svg',
160 'renderer':Unity.CategoryRenderer.VERTICAL_TILE}
161-c2 = {'id' :'movies',
162+c2 = {'id' :'movies',
163 'name' :_('Movies'),
164 'icon' :SVG_DIR+'group-installed.svg',
165 'renderer':Unity.CategoryRenderer.VERTICAL_TILE}
166-c3 = {'id' :'people',
167+c3 = {'id' :'people',
168 'name' :_('People'),
169 'icon' :SVG_DIR+'group-installed.svg',
170 'renderer':Unity.CategoryRenderer.VERTICAL_TILE}
171@@ -57,25 +60,23 @@
172
173 FILTERS = []
174
175-m1 = {'id' :'published',
176+m1 = {'id' :'movie_id',
177 'type' :'s',
178 'field':Unity.SchemaFieldType.OPTIONAL}
179-m2 = {'id' :'author',
180+m2 = {'id' :'people_id',
181 'type' :'s',
182 'field':Unity.SchemaFieldType.OPTIONAL}
183 EXTRA_METADATA = [m1, m2]
184
185 def configuration():
186- print(CONFIG_URI)
187 uri = '%sconfiguration?api_key=%s' % (CONFIG_URI, API_KEY)
188- print(uri)
189 header = {"Accept": "application/json"}
190 r = urllib.request.Request(uri, headers=header)
191 try:
192 response = urllib.request.urlopen(r).read()
193 data = json.loads(response.decode('utf-8'))
194 except Exception as error:
195- print(error)
196+ print("[themoviedb] Configuration Error:", error)
197 data = None
198 if not data:
199 return None
200@@ -106,14 +107,13 @@
201 search = urllib.parse.quote(search)
202 for cat in ['movie', 'person']:
203 uri = '%ssearch/%s?api_key=%s&query=%s' % (SEARCH_URI, cat, API_KEY, search)
204- print(uri)
205 header = {"Accept": "application/json"}
206 r = urllib.request.Request(uri, headers=header)
207 try:
208 response = urllib.request.urlopen(r).read()
209 data = json.loads(response.decode('utf-8'))
210 except Exception as error:
211- print(error)
212+ print("[themoviedb] Search error: ", error)
213 data = None
214 if not data and CONFIG:
215 return results
216@@ -140,10 +140,15 @@
217 title = r['name']
218 category = 1
219 uri = 'https://www.themoviedb.org/%s/%i' % (cat, r['id'])
220- results.append({'uri':uri,
221- 'icon':icon,
222- 'title':title,
223- 'category':category})
224+ result = {'uri':uri,
225+ 'icon':icon,
226+ 'title':title,
227+ 'category':category}
228+ if category == 1:
229+ result['people_id'] = r['id']
230+ else:
231+ result['movie_id'] = r['id']
232+ results.append(result)
233 return results
234
235
236@@ -187,14 +192,115 @@
237 if m['id'] == e:
238 i['metadata'][e] = i[e]
239 i['metadata']['provider_credits'] = GLib.Variant('s', PROVIDER_CREDITS)
240- result = Unity.ScopeResult.create(str(i['uri']), str(i['icon']),
241- i['category'], i['result_type'],
242- str(i['mimetype']), str(i['title']),
243- str(i['comment']), str(i['dnd_uri']),
244- i['metadata'])
245- result_set.add_result(result)
246- except Exception as error:
247- print (error)
248+ result_set.add_result(**i)
249+ except Exception as error:
250+ print("[themoviedb] Error: ", error)
251+
252+
253+class Preview(Unity.ResultPreviewer):
254+
255+ def _get_movie_preview(self):
256+ """Build a movie preview."""
257+ # it's a movie, let gat more data
258+ movie_id = self.result.metadata['movie_id']
259+ uri = '%smovie/%s?api_key=%s&append_to_response=trailers' % (SEARCH_URI, movie_id, API_KEY)
260+ header = {"Accept": "application/json"}
261+ r = urllib.request.Request(uri, headers=header)
262+ try:
263+ response = urllib.request.urlopen(r).read()
264+ data = json.loads(response.decode('utf-8'))
265+ except Exception as error:
266+ print("[themoviedb] Search error: ", error)
267+ data = None
268+ else:
269+ tagline = data['tagline']
270+ status = data['status']
271+ release_date = data['release_date']
272+ title = data['title']
273+ overview = data['overview']
274+ genres = ', '.join(g['name'] for g in data['genres'])
275+ runtime = data['runtime']
276+ # trailers
277+ trailer = {}
278+ yt = data['trailers'].get('youtube')
279+ if yt:
280+ for t in yt:
281+ if 'trailer' in t['name'].lower():
282+ trailer = t.copy()
283+ trailer['uri'] = "https://www.youtube.com/watch?v=%s" % t['source']
284+ break
285+ preview = Unity.GenericPreview.new(title, tagline, None)
286+ if status == "Released":
287+ preview.add_info(Unity.InfoHint.new("release_date", _("Release date"), None, release_date))
288+ else:
289+ preview.add_info(Unity.InfoHint.new("status", _("Status"), None, status))
290+ preview.add_info(Unity.InfoHint.new("genres", _("Genres"), None, genres))
291+ preview.add_info(Unity.InfoHint.new("runtime", _("Runtime"), None, "%s min." % (runtime,)))
292+ preview.add_info(Unity.InfoHint.new("_description_", _("Description"), None, overview))
293+ preview.props.image_source_uri = self.result.icon_hint
294+ icon = Gio.FileIcon.new (Gio.file_new_for_path(PROVIDER_ICON))
295+ view_action = Unity.PreviewAction.new("view", _("The Movie DB"), icon)
296+ preview.add_action(view_action)
297+ if trailer:
298+ trailer_icon = os.path.join(SVG_DIR, 'group-videos.svg')
299+ icon = Gio.FileIcon.new(Gio.file_new_for_path(trailer_icon))
300+ view_action = Unity.PreviewAction.with_uri(trailer['uri'], "View trailer", icon)
301+ preview.add_action(view_action)
302+
303+ return preview
304+
305+ def _get_person_preview(self):
306+ """Build a person preview."""
307+ people_id = self.result.metadata['people_id']
308+ uri = '%sperson/%s?api_key=%s&append_to_response=trailers' % (SEARCH_URI, people_id, API_KEY)
309+ header = {"Accept": "application/json"}
310+ r = urllib.request.Request(uri, headers=header)
311+ try:
312+ response = urllib.request.urlopen(r).read()
313+ data = json.loads(response.decode('utf-8'))
314+ except Exception as error:
315+ print("[themoviedb] Preview error: ", error)
316+ data = None
317+ else:
318+ birthday = data['birthday']
319+ deathday = data['deathday']
320+ homepage = data['homepage']
321+ name = data['name']
322+ place_of_birth = data['place_of_birth']
323+ popularity = data['popularity']
324+ biography = data['biography']
325+ also_known_as = ';'.join(data['also_known_as'])
326+ if deathday:
327+ comment = birthday + "/" + deathday
328+ else:
329+ comment = birthday
330+ preview = Unity.GenericPreview.new(name, comment, None)
331+ if homepage:
332+ preview.add_info(Unity.InfoHint.new("homepage", _("Homepage"), None, homepage))
333+ preview.add_info(Unity.InfoHint.new("place_of_birth", _("Place of birth"), None, place_of_birth))
334+ preview.add_info(Unity.InfoHint.new("also_known_as", _("Also known as"), None, also_known_as))
335+ preview.add_info(Unity.InfoHint.new("popularity", _("Popularity"), None, popularity))
336+ return preview
337+
338+ def do_run(self):
339+ preview = None
340+ if 'movie_id' in self.result.metadata:
341+ preview = self._get_movie_preview()
342+ else:
343+ preview = self._get_person_preview()
344+ if preview is None:
345+ # if we are here, the custom preview didn't worked. try to do our best
346+ title = self.result.title.strip()
347+ description = self.result.comment.strip()
348+ preview = Unity.GenericPreview.new(title, description, None)
349+ image = self.result.icon_hint
350+ preview.props.image_source_uri = image
351+ icon = Gio.FileIcon.new (Gio.file_new_for_path(PROVIDER_ICON))
352+ view_action = Unity.PreviewAction.new("view", _("The Movie DB"),
353+ icon)
354+ preview.add_action(view_action)
355+ return preview
356+
357
358 class Scope (Unity.AbstractScope):
359 def __init__(self):
360@@ -234,7 +340,7 @@
361 '''
362 fs = Unity.FilterSet.new ()
363 # if FILTERS:
364-#
365+#
366 return fs
367
368 def do_get_group_name (self):
369@@ -247,5 +353,11 @@
370 se = MySearch (search_context)
371 return se
372
373+ def do_create_previewer(self, result, metadata):
374+ rp = Preview()
375+ rp.set_scope_result(result)
376+ rp.set_search_metadata(metadata)
377+ return rp
378+
379 def load_scope():
380 return Scope()

Subscribers

People subscribed via source and target branches

to all changes: