diff --git a/lib/DDG/Spice/Hearthstone.pm b/lib/DDG/Spice/Hearthstone.pm new file mode 100644 index 0000000000..2b614998fd --- /dev/null +++ b/lib/DDG/Spice/Hearthstone.pm @@ -0,0 +1,51 @@ +package DDG::Spice::Hearthstone; +# ABSTRACT: Retrieve the card infos from Hearthstone game. + +use DDG::Spice; + +# Caching +spice is_cached => 1; +spice proxy_cache_valid => "200 4d"; + +# Metadata +name "Hearthstone Card Search"; +source "Bytevortex (Gamepedia Proxy)"; +icon_url "http://eu.battle.net/hearthstone/static/images/icons/favicon.ico"; +description "Get a preview of any Hearthstone card."; +primary_example_queries "hearthstone leeroy jenkins", "hearthstone leeroy", "leeroy hearthstone", "hearthstone mirror"; +category "entertainment"; +topics "gaming"; +code_url "https://github.com/duckduckgo/zeroclickinfo-spice/blob/master/lib/DDG/Spice/Hearthstone.pm"; +attribution github => ["https://github.com/Akryum", "Akryum"], + twitter => "Akryum"; + +# Triggers +triggers startend => "hearthstone"; + +# Target URL +spice to => 'http://bytevortex.net/hearthstone.php?search=$1'; + +# JS Callback +spice wrap_jsonp_callback => 1; + +# Keyword blacklist +my $keyword_guard = qr/game|instruction|stoves|warcraft|deck|forum|wiki|reddit/; + +# Handle statement +handle remainder => sub { + + # Guard against "no answer" + return unless $_; + + # Keyword Blacklist + return if (/$keyword_guard/); + + # Regex guard + # Allows string similar to any Hearthstone card name: multiple words separated by spaces, commas or dashes. + # The card name may also have dots, double dots, slashes or an exclamation mark (Those Blizzard devs). + return $_ if (/^([a-z0-9':!\/,.-]+\s*)+$/i); + + return; +}; + +1; diff --git a/share/spice/hearthstone/hearthstone.css b/share/spice/hearthstone/hearthstone.css new file mode 100644 index 0000000000..95bec727da --- /dev/null +++ b/share/spice/hearthstone/hearthstone.css @@ -0,0 +1,7 @@ +.zci--hearthstone b { + font-weight: normal; +} + +.zci--hearthstone i { + font-style: normal; +} \ No newline at end of file diff --git a/share/spice/hearthstone/hearthstone.handlebars b/share/spice/hearthstone/hearthstone.handlebars new file mode 100644 index 0000000000..9e631caafb --- /dev/null +++ b/share/spice/hearthstone/hearthstone.handlebars @@ -0,0 +1,5 @@ +
+ {{#if card_description}} +
{{{card_description}}}
+ {{/if}} +
diff --git a/share/spice/hearthstone/hearthstone.js b/share/spice/hearthstone/hearthstone.js new file mode 100644 index 0000000000..f941f2705c --- /dev/null +++ b/share/spice/hearthstone/hearthstone.js @@ -0,0 +1,107 @@ +(function(env) { + "use strict"; + + env.ddg_spice_hearthstone = function(api_result) { + + // Validate the response + if(!api_result || api_result.error || !api_result.Has_name || !api_result.page) { + return Spice.failed('hearthstone'); + } + + // Infobox Labels + var infoboxItems = { + Has_card_type: "Type", + Has_class: "Playable by", + Has_mana_cost: { + label: "Cost", + icon: "http://hydra-media.cursecdn.com/hearthstone.gamepedia.com/8/8b/Mana_icon.png" + }, + Has_attack: { + label: "Attack", + icon: "http://hydra-media.cursecdn.com/hearthstone.gamepedia.com/f/fe/Attack_icon.png" + }, + Has_health: { + label: "Health", + icon: "http://hydra-media.cursecdn.com/hearthstone.gamepedia.com/1/17/Health_icon.png" + }, + Has_rarity: "Rarity", + Is_part_of_set: "Set", + Is_collectible: "Collectible" + }; + + // Render the response + Spice.add({ + id: "hearthstone", + name: "Hearthstone", + data: api_result, + meta: { + sourceName: "Hearthstone Gamepedia Wiki", + sourceUrl: "http://hearthstone.gamepedia.com/" + api_result.page + }, + normalize: function(item) { + + // Infobox Heading + var infoboxData = [{ + heading: 'Card Details' + }]; + + // Is collectible + api_result.Is_collectible = (api_result.Is_collectible === "t" ? "Yes" : "No"); + + // Hero + if(api_result.Has_class === "Any") { + api_result.Has_class = "Any Hero"; + } + + // InfoBox data + $.each(infoboxItems, function(key, data) { + var label, + value; + if(api_result[key]) { + value = api_result[key]; + if(data.label) { + label = data.label; + } else { + label = data; + } + infoboxData.push({ + label: label, + value: value + }); + } + }); + + // Normalized data + var card = { + title: item.Has_name, + url: "http://hearthstone.gamepedia.com/" + item.page, + infoboxData: infoboxData + }; + + // Optionnal fields + // Image + if(item.image_url) { + card.image = item.image_url; + } + + // Description + if(item.Has_description) { + card.card_description = item.Has_description; + } + + // Flavor text + if(item.Has_flavor_text) { + card.subtitle = item.Has_flavor_text; + } + + return card; + }, + templates: { + group: 'info', + options: { + content: Spice.hearthstone.hearthstone + } + } + }); + }; +}(this)); \ No newline at end of file diff --git a/t/Hearthstone.t b/t/Hearthstone.t new file mode 100644 index 0000000000..da8cb7b4e0 --- /dev/null +++ b/t/Hearthstone.t @@ -0,0 +1,40 @@ +#!/usr/bin/env perl + +use strict; +use warnings; +use Test::More; +use DDG::Test::Spice; + +spice is_cached => 1; + +ddg_spice_test( + [qw( DDG::Spice::Hearthstone)], + 'hearthstone leeroy jenkins' => test_spice( + '/js/spice/hearthstone/leeroy%20jenkins', + call_type => 'include', + caller => 'DDG::Spice::Hearthstone' + ), + 'hearthstone leeroy' => test_spice( + '/js/spice/hearthstone/leeroy', + call_type => 'include', + caller => 'DDG::Spice::Hearthstone' + ), + 'leeroy hearthstone' => test_spice( + '/js/spice/hearthstone/leeroy', + call_type => 'include', + caller => 'DDG::Spice::Hearthstone' + ), + 'hearthstone mirror' => test_spice( + '/js/spice/hearthstone/mirror', + call_type => 'include', + caller => 'DDG::Spice::Hearthstone' + ), + 'hearthstone' => undef, + 'hearthstone heroes of warcraft' => undef, + 'hearthstone wood stoves' => undef, + 'hearthstone mage deck' => undef, + 'hearthstone tide_caller' => undef, + 'hearthstone tidecaller $' => undef +); + +done_testing;