diff --git a/searx/engines/dailymotion.py b/searx/engines/dailymotion.py index a5bffa866..03b1dbb8b 100644 --- a/searx/engines/dailymotion.py +++ b/searx/engines/dailymotion.py @@ -6,12 +6,14 @@ # @using-api yes # @results JSON # @stable yes -# @parse url, title, thumbnail +# @parse url, title, thumbnail, publishedDate, embedded # # @todo set content-parameter with correct data from urllib import urlencode from json import loads +from cgi import escape +from datetime import datetime # engine dependent config categories = ['videos'] @@ -20,7 +22,9 @@ language_support = True # search-url # see http://www.dailymotion.com/doc/api/obj-video.html -search_url = 'https://api.dailymotion.com/videos?fields=title,description,duration,url,thumbnail_360_url&sort=relevance&limit=5&page={pageno}&{query}' # noqa +search_url = 'https://api.dailymotion.com/videos?fields=created_time,title,description,duration,url,thumbnail_360_url,id&sort=relevance&limit=5&page={pageno}&{query}' # noqa +embedded_url = '' # do search-request @@ -51,14 +55,17 @@ def response(resp): for res in search_res['list']: title = res['title'] url = res['url'] - #content = res['description'] - content = '' + content = escape(res['description']) thumbnail = res['thumbnail_360_url'] + publishedDate = datetime.fromtimestamp(res['created_time'], None) + embedded = embedded_url.format(videoid=res['id']) results.append({'template': 'videos.html', 'url': url, 'title': title, 'content': content, + 'publishedDate': publishedDate, + 'embedded': embedded, 'thumbnail': thumbnail}) # return results diff --git a/searx/engines/deezer.py b/searx/engines/deezer.py new file mode 100644 index 000000000..6c26b6aeb --- /dev/null +++ b/searx/engines/deezer.py @@ -0,0 +1,62 @@ +## Deezer (Music) +# +# @website https://deezer.com +# @provide-api yes (http://developers.deezer.com/api/) +# +# @using-api yes +# @results JSON +# @stable yes +# @parse url, title, content, embedded + +from json import loads +from urllib import urlencode + +# engine dependent config +categories = ['music'] +paging = True + +# search-url +url = 'http://api.deezer.com/' +search_url = url + 'search?{query}&index={offset}' + +embedded_url = '' + + +# do search-request +def request(query, params): + offset = (params['pageno'] - 1) * 25 + + params['url'] = search_url.format(query=urlencode({'q': query}), + offset=offset) + + return params + + +# get response from search-request +def response(resp): + results = [] + + search_res = loads(resp.text) + + # parse results + for result in search_res.get('data', []): + if result['type'] == 'track': + print result + title = result['title'] + url = result['link'] + content = result['artist']['name'] +\ + " • " +\ + result['album']['title'] +\ + " • " + result['title'] + embedded = embedded_url.format(audioid=result['id']) + + # append result + results.append({'url': url, + 'title': title, + 'embedded': embedded, + 'content': content}) + + # return results + return results diff --git a/searx/engines/soundcloud.py b/searx/engines/soundcloud.py index 164a569a3..44374af6f 100644 --- a/searx/engines/soundcloud.py +++ b/searx/engines/soundcloud.py @@ -6,10 +6,11 @@ # @using-api yes # @results JSON # @stable yes -# @parse url, title, content +# @parse url, title, content, publishedDate, embedded from json import loads -from urllib import urlencode +from urllib import urlencode, quote_plus +from dateutil import parser # engine dependent config categories = ['music'] @@ -27,6 +28,10 @@ search_url = url + 'search?{query}'\ '&linked_partitioning=1'\ '&client_id={client_id}' # noqa +embedded_url = '' + # do search-request def request(query, params): @@ -50,10 +55,15 @@ def response(resp): if result['kind'] in ('track', 'playlist'): title = result['title'] content = result['description'] + publishedDate = parser.parse(result['last_modified']) + uri = quote_plus(result['uri']) + embedded = embedded_url.format(uri=uri) # append result results.append({'url': result['permalink_url'], 'title': title, + 'publishedDate': publishedDate, + 'embedded': embedded, 'content': content}) # return results diff --git a/searx/engines/vimeo.py b/searx/engines/vimeo.py index c66c4148a..fd945b319 100644 --- a/searx/engines/vimeo.py +++ b/searx/engines/vimeo.py @@ -7,7 +7,7 @@ # @using-api no (TODO, rewrite to api) # @results HTML (using search portal) # @stable no (HTML can change) -# @parse url, title, publishedDate, thumbnail +# @parse url, title, publishedDate, thumbnail, embedded # # @todo rewrite to api # @todo set content-parameter with correct data @@ -33,6 +33,10 @@ title_xpath = './a/div[@class="data"]/p[@class="title"]/text()' results_xpath = '//div[@id="browse_content"]/ol/li' publishedDate_xpath = './/p[@class="meta"]//attribute::datetime' +embedded_url = '' + # do search-request def request(query, params): @@ -56,11 +60,13 @@ def response(resp): # parse results for result in dom.xpath(results_xpath): - url = base_url + result.xpath(url_xpath)[0] + videoid = result.xpath(url_xpath)[0] + url = base_url + videoid title = p.unescape(extract_text(result.xpath(title_xpath))) thumbnail = extract_text(result.xpath(content_xpath)[0]) publishedDate = parser.parse(extract_text( result.xpath(publishedDate_xpath)[0])) + embedded = embedded_url.format(videoid=videoid) # append result results.append({'url': url, @@ -68,6 +74,7 @@ def response(resp): 'content': '', 'template': 'videos.html', 'publishedDate': publishedDate, + 'embedded': embedded, 'thumbnail': thumbnail}) # return results diff --git a/searx/engines/youtube.py b/searx/engines/youtube.py index 973e799f8..59f07c574 100644 --- a/searx/engines/youtube.py +++ b/searx/engines/youtube.py @@ -6,7 +6,7 @@ # @using-api yes # @results JSON # @stable yes -# @parse url, title, content, publishedDate, thumbnail +# @parse url, title, content, publishedDate, thumbnail, embedded from json import loads from urllib import urlencode @@ -19,7 +19,11 @@ language_support = True # search-url base_url = 'https://gdata.youtube.com/feeds/api/videos' -search_url = base_url + '?alt=json&{query}&start-index={index}&max-results=5' # noqa +search_url = base_url + '?alt=json&{query}&start-index={index}&max-results=5' + +embedded_url = '' # do search-request @@ -60,6 +64,8 @@ def response(resp): if url.endswith('&'): url = url[:-1] + videoid = url[32:] + title = result['title']['$t'] content = '' thumbnail = '' @@ -72,12 +78,15 @@ def response(resp): content = result['content']['$t'] + embedded = embedded_url.format(videoid=videoid) + # append result results.append({'url': url, 'title': title, 'content': content, 'template': 'videos.html', 'publishedDate': publishedDate, + 'embedded': embedded, 'thumbnail': thumbnail}) # return results diff --git a/searx/settings.yml b/searx/settings.yml index e30c52256..70c56fccd 100644 --- a/searx/settings.yml +++ b/searx/settings.yml @@ -35,6 +35,10 @@ engines: engine : currency_convert categories : general shortcut : cc + + - name : deezer + engine : deezer + shortcut : dz - name : deviantart engine : deviantart diff --git a/searx/static/themes/oscar/js/searx.min.js b/searx/static/themes/oscar/js/searx.min.js index 34a44f51b..c2006d27d 100644 --- a/searx/static/themes/oscar/js/searx.min.js +++ b/searx/static/themes/oscar/js/searx.min.js @@ -1,2 +1,2 @@ -/*! oscar/searx.min.js | 19-12-2014 | https://github.com/asciimoo/searx */ -requirejs.config({baseUrl:"./static/themes/oscar/js",paths:{app:"../app"}}),searx.autocompleter&&(searx.searchResults=new Bloodhound({datumTokenizer:Bloodhound.tokenizers.obj.whitespace("value"),queryTokenizer:Bloodhound.tokenizers.whitespace,remote:"/autocompleter?q=%QUERY"}),searx.searchResults.initialize()),$(document).ready(function(){searx.autocompleter&&$("#q").typeahead(null,{name:"search-results",displayKey:function(a){return a},source:searx.searchResults.ttAdapter()})}),$(document).ready(function(){$("#q.autofocus").focus(),$(".select-all-on-click").click(function(){$(this).select()}),$(".btn-collapse").click(function(){var a=$(this).data("btn-text-collapsed"),b=$(this).data("btn-text-not-collapsed");""!==a&&""!==b&&(new_html=$(this).hasClass("collapsed")?$(this).html().replace(a,b):$(this).html().replace(b,a),$(this).html(new_html))}),$(".btn-toggle .btn").click(function(){var a="btn-"+$(this).data("btn-class"),b=$(this).data("btn-label-default"),c=$(this).data("btn-label-toggled");""!==c&&(new_html=$(this).hasClass("btn-default")?$(this).html().replace(b,c):$(this).html().replace(c,b),$(this).html(new_html)),$(this).toggleClass(a),$(this).toggleClass("btn-default")}),$(".btn-sm").dblclick(function(){var a="btn-"+$(this).data("btn-class");$(this).hasClass("btn-default")?($(".btn-sm > input").attr("checked","checked"),$(".btn-sm > input").prop("checked",!0),$(".btn-sm").addClass(a),$(".btn-sm").addClass("active"),$(".btn-sm").removeClass("btn-default")):($(".btn-sm > input").attr("checked",""),$(".btn-sm > input").removeAttr("checked"),$(".btn-sm > input").checked=!1,$(".btn-sm").removeClass(a),$(".btn-sm").removeClass("active"),$(".btn-sm").addClass("btn-default"))})}),$(document).ready(function(){$(".searx_overpass_request").on("click",function(a){var b="https://overpass-api.de/api/interpreter?data=",c=b+"[out:json][timeout:25];(",d=");out meta;",e=$(this).data("osm-id"),f=$(this).data("osm-type"),g=$(this).data("result-table"),h="#"+$(this).data("result-table-loadicon"),i=["addr:city","addr:country","addr:housenumber","addr:postcode","addr:street"];if(e&&f&&g){g="#"+g;var j=null;switch(f){case"node":j=c+"node("+e+");"+d;break;case"way":j=c+"way("+e+");"+d;break;case"relation":j=c+"relation("+e+");"+d}if(j){$.ajax(j).done(function(a){if(a&&a.elements&&a.elements[0]){var b=a.elements[0],c=$(g).html();for(var d in b.tags)if(null===b.tags.name||-1==i.indexOf(d)){switch(c+="
could not load data!
')})}}$(this).off(a)}),$(".searx_init_map").on("click",function(a){var b=$(this).data("leaflet-target"),c=$(this).data("map-lon"),d=$(this).data("map-lat"),e=$(this).data("map-zoom"),f=$(this).data("map-boundingbox"),g=$(this).data("map-geojson");require(["leaflet-0.7.3.min"],function(){f&&(southWest=L.latLng(f[0],f[2]),northEast=L.latLng(f[1],f[3]),map_bounds=L.latLngBounds(southWest,northEast)),L.Icon.Default.imagePath="./static/oscar/img/map";{var a=L.map(b),h="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",i='Map data © OpenStreetMap contributors',j=new L.TileLayer(h,{minZoom:1,maxZoom:19,attribution:i}),k="http://otile{s}.mqcdn.com/tiles/1.0.0/map/{z}/{x}/{y}.jpg",l='Map data © OpenStreetMap contributors | Tiles Courtesy of MapQuest ',m=new L.TileLayer(k,{minZoom:1,maxZoom:18,subdomains:"1234",attribution:l}),n="http://otile{s}.mqcdn.com/tiles/1.0.0/sat/{z}/{x}/{y}.jpg",o='Map data © OpenStreetMap contributors | Tiles Courtesy of MapQuest | Portions Courtesy NASA/JPL-Caltech and U.S. Depart. of Agriculture, Farm Service Agency';new L.TileLayer(n,{minZoom:1,maxZoom:11,subdomains:"1234",attribution:o})}map_bounds?setTimeout(function(){a.fitBounds(map_bounds,{maxZoom:17})},0):c&&d&&(e?a.setView(new L.LatLng(d,c),e):a.setView(new L.LatLng(d,c),8)),a.addLayer(m);var p={"OSM Mapnik":j,MapQuest:m};L.control.layers(p).addTo(a),g&&L.geoJson(g).addTo(a)}),$(this).off(a)})}); +/*! oscar/searx.min.js | 04-01-2015 | https://github.com/asciimoo/searx */ +requirejs.config({baseUrl:"./static/themes/oscar/js",paths:{app:"../app"}}),searx.autocompleter&&(searx.searchResults=new Bloodhound({datumTokenizer:Bloodhound.tokenizers.obj.whitespace("value"),queryTokenizer:Bloodhound.tokenizers.whitespace,remote:"/autocompleter?q=%QUERY"}),searx.searchResults.initialize()),$(document).ready(function(){searx.autocompleter&&$("#q").typeahead(null,{name:"search-results",displayKey:function(a){return a},source:searx.searchResults.ttAdapter()})}),$(document).ready(function(){$("#q.autofocus").focus(),$(".select-all-on-click").click(function(){$(this).select()}),$(".btn-collapse").click(function(){var a=$(this).data("btn-text-collapsed"),b=$(this).data("btn-text-not-collapsed");""!==a&&""!==b&&(new_html=$(this).hasClass("collapsed")?$(this).html().replace(a,b):$(this).html().replace(b,a),$(this).html(new_html))}),$(".btn-toggle .btn").click(function(){var a="btn-"+$(this).data("btn-class"),b=$(this).data("btn-label-default"),c=$(this).data("btn-label-toggled");""!==c&&(new_html=$(this).hasClass("btn-default")?$(this).html().replace(b,c):$(this).html().replace(c,b),$(this).html(new_html)),$(this).toggleClass(a),$(this).toggleClass("btn-default")}),$(".media-loader").click(function(){var a=$(this).data("target"),b=$(a+" > iframe"),c=b.attr("src");(void 0===c||c===!1)&&b.attr("src",b.data("src"))}),$(".btn-sm").dblclick(function(){var a="btn-"+$(this).data("btn-class");$(this).hasClass("btn-default")?($(".btn-sm > input").attr("checked","checked"),$(".btn-sm > input").prop("checked",!0),$(".btn-sm").addClass(a),$(".btn-sm").addClass("active"),$(".btn-sm").removeClass("btn-default")):($(".btn-sm > input").attr("checked",""),$(".btn-sm > input").removeAttr("checked"),$(".btn-sm > input").checked=!1,$(".btn-sm").removeClass(a),$(".btn-sm").removeClass("active"),$(".btn-sm").addClass("btn-default"))})}),$(document).ready(function(){$(".searx_overpass_request").on("click",function(a){var b="https://overpass-api.de/api/interpreter?data=",c=b+"[out:json][timeout:25];(",d=");out meta;",e=$(this).data("osm-id"),f=$(this).data("osm-type"),g=$(this).data("result-table"),h="#"+$(this).data("result-table-loadicon"),i=["addr:city","addr:country","addr:housenumber","addr:postcode","addr:street"];if(e&&f&&g){g="#"+g;var j=null;switch(f){case"node":j=c+"node("+e+");"+d;break;case"way":j=c+"way("+e+");"+d;break;case"relation":j=c+"relation("+e+");"+d}if(j){$.ajax(j).done(function(a){if(a&&a.elements&&a.elements[0]){var b=a.elements[0],c=$(g).html();for(var d in b.tags)if(null===b.tags.name||-1==i.indexOf(d)){switch(c+="could not load data!
')})}}$(this).off(a)}),$(".searx_init_map").on("click",function(a){var b=$(this).data("leaflet-target"),c=$(this).data("map-lon"),d=$(this).data("map-lat"),e=$(this).data("map-zoom"),f=$(this).data("map-boundingbox"),g=$(this).data("map-geojson");require(["leaflet-0.7.3.min"],function(){f&&(southWest=L.latLng(f[0],f[2]),northEast=L.latLng(f[1],f[3]),map_bounds=L.latLngBounds(southWest,northEast)),L.Icon.Default.imagePath="./static/themes/oscar/img/map";{var a=L.map(b),h="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",i='Map data © OpenStreetMap contributors',j=new L.TileLayer(h,{minZoom:1,maxZoom:19,attribution:i}),k="http://otile{s}.mqcdn.com/tiles/1.0.0/map/{z}/{x}/{y}.jpg",l='Map data © OpenStreetMap contributors | Tiles Courtesy of MapQuest ',m=new L.TileLayer(k,{minZoom:1,maxZoom:18,subdomains:"1234",attribution:l}),n="http://otile{s}.mqcdn.com/tiles/1.0.0/sat/{z}/{x}/{y}.jpg",o='Map data © OpenStreetMap contributors | Tiles Courtesy of MapQuest | Portions Courtesy NASA/JPL-Caltech and U.S. Depart. of Agriculture, Farm Service Agency';new L.TileLayer(n,{minZoom:1,maxZoom:11,subdomains:"1234",attribution:o})}map_bounds?setTimeout(function(){a.fitBounds(map_bounds,{maxZoom:17})},0):c&&d&&(e?a.setView(new L.LatLng(d,c),e):a.setView(new L.LatLng(d,c),8)),a.addLayer(m);var p={"OSM Mapnik":j,MapQuest:m};L.control.layers(p).addTo(a),g&&L.geoJson(g).addTo(a)}),$(this).off(a)})}); \ No newline at end of file diff --git a/searx/static/themes/oscar/js/searx_src/element_modifiers.js b/searx/static/themes/oscar/js/searx_src/element_modifiers.js index dd45b77e0..00c7f09a6 100644 --- a/searx/static/themes/oscar/js/searx_src/element_modifiers.js +++ b/searx/static/themes/oscar/js/searx_src/element_modifiers.js @@ -63,6 +63,18 @@ $(document).ready(function(){ $(this).toggleClass(btnClass); $(this).toggleClass('btn-default'); }); + + /** + * change text during btn-toggle click if possible + */ + $('.media-loader').click(function() { + var target = $(this).data('target'); + var iframe_load = $(target + ' > iframe'); + var srctest = iframe_load.attr('src'); + if(srctest === undefined || srctest === false){ + iframe_load.attr('src', iframe_load.data('src')); + } + }); /** * Select or deselect every categories on double clic diff --git a/searx/templates/oscar/result_templates/default.html b/searx/templates/oscar/result_templates/default.html index 6ab26132e..3e58588cc 100644 --- a/searx/templates/oscar/result_templates/default.html +++ b/searx/templates/oscar/result_templates/default.html @@ -5,8 +5,20 @@ {% if result.publishedDate %}{% endif %} {{ icon('link') }} {{ _('cached') }} +{% if result.embedded %} + • {{ icon('music') }} {{ _('show media') }} +{% endif %} + {% if result.content %}{{ result.content|safe }}
{% endif %} +{% if result.embedded %} +