move replicated README info and point to duckduckgo readme

master
Dylan Lloyd 2013-06-24 19:39:01 -04:00
parent 95282fdf0d
commit 37443d3040
1 changed files with 5 additions and 143 deletions

148
README.md
View File

@ -1,150 +1,12 @@
DuckDuckHack Goodies
====
This documentation walks you through the process of writing a DuckDuckHack Goodie plugin.
Before reading this section, make sure you've read the [DuckDuckHack Intro Site](http://duckduckhack.com) and the [DuckDuckHack Developer's Overview](https://github.com/duckduckgo/duckduckgo/blob/master/README.md). If you're here to brush up on Goodie info, scroll down. If you're here to learn how to write Goodie Plugins, check out the [Goodies Overview](https://github.com/duckduckgo/duckduckgo#goodies-overview).
### Example
Goodies are DuckDuckGo plugins that work with pure [Perl](https://en.wikipedia.org/wiki/Perl).
![morse code example](https://s3.amazonaws.com/ddg-assets/docs/goodie_example.png)
## Writing test files
We recommend starting at the [DuckDuckHack Intro Site](http://duckduckhack.com). If you've read that, but are still looking for more detail, checkout the [DuckDuckHack Goodie Overview](https://github.com/duckduckgo/duckduckgo/blob/master/README.md).
Every goodie includes a test file in the `t` directory. For example, the **RouterPasswords** goodie uses the the test file `t/RouterPasswords.t`. This test file includes sample queries and answers, and is run automatically before every release to ensure that all goodies are triggering properly with correct answers. The test file is a Perl program that uses the Perl packages `DDG::Test::Goodie` and `Test::More` to function. Here's an annotated excerpt from `t/RouterPasswords.t` that you can use as a base:
### Writing a Goodie
```perl
#!/usr/bin/env perl
use strict;
use warnings;
# These modules are necessary for the functions we'll be running.
use Test::More;
use DDG::Test::Goodie;
# These zci attributes aren't necessary, but if you specify them inside your
# goodie, you'll need to add matching values here to check against.
zci answer_type => 'password';
zci is_cached => 1;
ddg_goodie_test(
[
# This is the name of the goodie that will be loaded to test.
'DDG::Goodie::RouterPasswords'
],
# This is a sample query, just like the user will enter into the DuckDuckGo
# search box.
'Belkin f5d6130' =>
test_zci(
# The first argument to test_zci is the plain text (default)
# returned from a goodie. If your goodie also returns an HTML
# version, you can pass that along explicitly as the second
# argument. If your goodie is random, you can use regexs instead of
# strings to match against.
'Default login for the BELKIN F5D6130: Username: (none) Password: password',
html => 'Default login for the BELKIN F5D6130:<br><i>Username</i>: (none)<br><i>Password</i>: password'
),
# You should include more test cases here. Try to think of ways that your
# plugin might break, and add them here to ensure they won't. Here are a
# few others that were thought of for this goodie.
);
# This function call is expected by Test::More. It makes sure the program
# doesn't exit before all the tests are run.
done_testing;
```
## Advanced Goodies
These advanced handle techniques are specific to Goodie plugins:
**Returning HTML**. &nbsp;Goodies return text instant answers by default, but can return simple HTML as well. In that case, simply attach the html version to the end of the return statement.
```perl
return $text, html => $html;
```
**Other zci keywords**. &nbsp;The Chars example sets the **is_cached** zci keyword. You can find other settable attributes in the [object documentation](https://metacpan.org/module/WWW::DuckDuckGo::ZeroClickInfo). For example, the [GoldenRatio Goodie](https://github.com/duckduckgo/zeroclickinfo-goodies/blob/master/lib/DDG/Goodie/GoldenRatio.pm) sets the **answer_type** variable, which gets returned in the API.
```perl
zci answer_type => "golden_ratio";
```
## Location API
Sometimes, a plugin needs the user's location. This is where the Location API comes in. An example is the [Is it snowing?](https://github.com/duckduckgo/zeroclickinfo-spice/blob/master/lib/DDG/Spice/Snow.pm) plugin:
```perl
# Phoenixville, Pennsylvania, United States
my $location = join(", ", $loc->city, $loc->region_name, $loc->country_name);
```
When testing on `duckpan`, the plugin will always point you to "Phoenixville, Pennsylvania, United States," but don't worry, because it will show the real location once it's live.
It isn't limited to just the city, the state, and the country. [Location.pm](https://github.com/duckduckgo/duckduckgo/blob/master/lib/DDG/Location.pm#L6) lists all the things that you can possibly use:
```perl
my @geo_ip_record_attrs = qw( country_code country_code3 country_name region
region_name city postal_code latitude longitude time_zone area_code
continent_code metro_code );
```
Sample contents of `$loc`:
```perl
longitude => -75.5385
country_name => United States
area_code => 610
region_name => Pennsylvania
country_code => US
region => PA
continent_code => NA
city => Phoenixville
postal_code => 19460
latitude => 40.1246
time_zone => America/New_York
metro_code => 504
country_code3 => USA
```
## Testing the Location API
To write a test for a location aware Goodie, you'll need to pass `ddg_goodie_test` an extra parameter, a `DDG::Request` object, with the location specified. To do this, you'll need to `use DDG::Test::Location` and `use DDG::Request`. Here is a working annotated example excerpted from `t/Helpline.t`.
Note that only a small set of locations are available to be simulated for testing. They are defined in [DDG::Test::Location.pm](https://github.com/duckduckgo/duckduckgo/blob/master/lib/DDG/Test/Location.pm#L18).
```perl
#!/usr/bin/env perl
use strict;
use warnings;
use Test::More;
use DDG::Test::Spice;
# These two modules are only necessary when testing with the Location API.
use DDG::Test::Location;
use DDG::Request;
ddg_spice_test(
[qw( DDG::Spice::Snow )],
# This optional argument to ddg_goodie_test is a DDG::Request object.
# The object constructor takes two arguments of its own:
# the query (usually specified in the test_zci),
# and a location object - created by test_location (with a country code).
DDG::Request->new(
query_raw => "is it snowing?",
location => test_location("de")
) => test_spice(
'/js/spice/snow/'
.'M%C3%B6nchengladbach%2C%20%20Nordrhein-Westfalen%2C%20%20Germany',
call_type => 'include',
caller => 'DDG::Spice::Snow',
),
# The DDG::Request is used in place of a query string, and isn't necessary
# to be used with every test passed to ddg_spice_test.
'is it snowing in new york?' => test_spice(
'/js/spice/snow/new%20york',
call_type => 'include',
caller => 'DDG::Spice::Snow',
)
);
done_testing;
```
If you're ready to start writing a Goodie, go to the [Goodies Overview](https://github.com/duckduckgo/duckduckgo#goodies-overview).