{"action":"created","comment":{"url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/pulls/comments/26454272","id":26454272,"diff_hunk":"@@ -23,25 +23,48 @@ attribution web     => ['robert.io',                 'Robert Picard'],\n             github  => ['http://github.com/rpicard', 'Robert Picard'],\n             twitter => ['http://twitter.com/__rlp',  'Robert Picard'];\n \n+\n handle remainder => sub {\n-    return unless $_ =~ /^(?<com>encode|decode|)\\s*(?<str>.*)$/i;\n+    my ($command, $input) = query_components($_);\n+    return unless $input;\n \n-    my ($command, $in_str) = (lc($+{'com'}) || 'encode', $+{'str'});\n+    my $output = perform_conversion($command, $input);\n+    \n+    my $operation = 'Base64 ' . $command;\n+    my $text_output = $operation . 'd: ' . $output;\n+    return $text_output,\n+      structured_answer => {\n+        input     => [html_enc($input)],\n+        operation => $operation,\n+        result    => $output,\n+      };\n+};\n \n-    return unless $in_str;\n \n-    my $out_str = ($command eq 'decode') ? decode(\"UTF-8\", decode_base64($in_str)) : encode_base64(encode(\"UTF-8\", $in_str));\n-    chomp $out_str;\n+# Parse the query into its two components:\n+# an optional command (encode or decode), \n+# and an input string.\n+sub query_components {\n+    my $query = shift;\n+    $query =~ /^(?<command>encode|decode|)\\s*(?<input>.*)$/i;\n+    my $command = lc($+{'command'}) || 'encode';\n+    return ($command, $+{'input'});\n+}\n \n-    return unless $out_str;\n-    my $what = 'Base64 ' . $command;\n \n-    return ucfirst($what) . 'd: ' . $out_str,\n-      structured_answer => {\n-        input     => [html_enc($in_str)],\n-        operation => $what,\n-        result    => $out_str,\n-      };\n-};\n+sub perform_conversion {\n+    my $command = shift;\n+    my $input = shift;\n+    \n+    if ($command eq 'decode') {\n+        return trim(decode(\"UTF-8\", decode_base64($input)));\n+    } else {\n+        return trim(encode_base64(encode(\"UTF-8\", $input)));\n+    }\n+}\n+\n+\n+# Trim whitespace from the beginning and end of a string.\n+sub trim { my $s = shift; $s =~ s/^\\s+|\\s+$//g; return $s };","path":"lib/DDG/Goodie/Base64.pm","position":69,"original_position":69,"commit_id":"ac3b198746c0817462f2e9c72455ddf4698653db","original_commit_id":"ac3b198746c0817462f2e9c72455ddf4698653db","user":{"login":"mintsoft","id":978048,"avatar_url":"https://avatars.githubusercontent.com/u/978048?v=3","gravatar_id":"","url":"https://api.github.com/users/mintsoft","html_url":"https://github.com/mintsoft","followers_url":"https://api.github.com/users/mintsoft/followers","following_url":"https://api.github.com/users/mintsoft/following{/other_user}","gists_url":"https://api.github.com/users/mintsoft/gists{/gist_id}","starred_url":"https://api.github.com/users/mintsoft/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mintsoft/subscriptions","organizations_url":"https://api.github.com/users/mintsoft/orgs","repos_url":"https://api.github.com/users/mintsoft/repos","events_url":"https://api.github.com/users/mintsoft/events{/privacy}","received_events_url":"https://api.github.com/users/mintsoft/received_events","type":"User","site_admin":false},"body":"Good point @moollaza I was just thinking that we could do with a standard way of doing it in the docs etc","created_at":"2015-03-15T23:57:14Z","updated_at":"2015-03-15T23:57:14Z","html_url":"https://github.com/duckduckgo/zeroclickinfo-goodies/pull/1059#discussion_r26454272","pull_request_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/pulls/1059","_links":{"self":{"href":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/pulls/comments/26454272"},"html":{"href":"https://github.com/duckduckgo/zeroclickinfo-goodies/pull/1059#discussion_r26454272"},"pull_request":{"href":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/pulls/1059"}}},"pull_request":{"url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/pulls/1059","id":31194572,"html_url":"https://github.com/duckduckgo/zeroclickinfo-goodies/pull/1059","diff_url":"https://github.com/duckduckgo/zeroclickinfo-goodies/pull/1059.diff","patch_url":"https://github.com/duckduckgo/zeroclickinfo-goodies/pull/1059.patch","issue_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/issues/1059","number":1059,"state":"open","locked":false,"title":"Base64 Fix","user":{"login":"dogweather","id":150670,"avatar_url":"https://avatars.githubusercontent.com/u/150670?v=3","gravatar_id":"","url":"https://api.github.com/users/dogweather","html_url":"https://github.com/dogweather","followers_url":"https://api.github.com/users/dogweather/followers","following_url":"https://api.github.com/users/dogweather/following{/other_user}","gists_url":"https://api.github.com/users/dogweather/gists{/gist_id}","starred_url":"https://api.github.com/users/dogweather/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dogweather/subscriptions","organizations_url":"https://api.github.com/users/dogweather/orgs","repos_url":"https://api.github.com/users/dogweather/repos","events_url":"https://api.github.com/users/dogweather/events{/privacy}","received_events_url":"https://api.github.com/users/dogweather/received_events","type":"User","site_admin":false},"body":"This is a fix for Issue #1051.","created_at":"2015-03-15T03:17:05Z","updated_at":"2015-03-15T23:57:14Z","closed_at":null,"merged_at":null,"merge_commit_sha":"e02d4372a28aa5ae37cccd5651a4cf8f60fe8ba6","assignee":{"login":"mintsoft","id":978048,"avatar_url":"https://avatars.githubusercontent.com/u/978048?v=3","gravatar_id":"","url":"https://api.github.com/users/mintsoft","html_url":"https://github.com/mintsoft","followers_url":"https://api.github.com/users/mintsoft/followers","following_url":"https://api.github.com/users/mintsoft/following{/other_user}","gists_url":"https://api.github.com/users/mintsoft/gists{/gist_id}","starred_url":"https://api.github.com/users/mintsoft/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mintsoft/subscriptions","organizations_url":"https://api.github.com/users/mintsoft/orgs","repos_url":"https://api.github.com/users/mintsoft/repos","events_url":"https://api.github.com/users/mintsoft/events{/privacy}","received_events_url":"https://api.github.com/users/mintsoft/received_events","type":"User","site_admin":false},"milestone":null,"commits_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/pulls/1059/commits","review_comments_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/pulls/1059/comments","review_comment_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/pulls/comments{/number}","comments_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/issues/1059/comments","statuses_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/statuses/ac3b198746c0817462f2e9c72455ddf4698653db","head":{"label":"dogweather:base64-fix","ref":"base64-fix","sha":"ac3b198746c0817462f2e9c72455ddf4698653db","user":{"login":"dogweather","id":150670,"avatar_url":"https://avatars.githubusercontent.com/u/150670?v=3","gravatar_id":"","url":"https://api.github.com/users/dogweather","html_url":"https://github.com/dogweather","followers_url":"https://api.github.com/users/dogweather/followers","following_url":"https://api.github.com/users/dogweather/following{/other_user}","gists_url":"https://api.github.com/users/dogweather/gists{/gist_id}","starred_url":"https://api.github.com/users/dogweather/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dogweather/subscriptions","organizations_url":"https://api.github.com/users/dogweather/orgs","repos_url":"https://api.github.com/users/dogweather/repos","events_url":"https://api.github.com/users/dogweather/events{/privacy}","received_events_url":"https://api.github.com/users/dogweather/received_events","type":"User","site_admin":false},"repo":{"id":32201180,"name":"zeroclickinfo-goodies","full_name":"dogweather/zeroclickinfo-goodies","owner":{"login":"dogweather","id":150670,"avatar_url":"https://avatars.githubusercontent.com/u/150670?v=3","gravatar_id":"","url":"https://api.github.com/users/dogweather","html_url":"https://github.com/dogweather","followers_url":"https://api.github.com/users/dogweather/followers","following_url":"https://api.github.com/users/dogweather/following{/other_user}","gists_url":"https://api.github.com/users/dogweather/gists{/gist_id}","starred_url":"https://api.github.com/users/dogweather/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dogweather/subscriptions","organizations_url":"https://api.github.com/users/dogweather/orgs","repos_url":"https://api.github.com/users/dogweather/repos","events_url":"https://api.github.com/users/dogweather/events{/privacy}","received_events_url":"https://api.github.com/users/dogweather/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/dogweather/zeroclickinfo-goodies","description":"DuckDuckGo instant answer plugins based on Perl functions","fork":true,"url":"https://api.github.com/repos/dogweather/zeroclickinfo-goodies","forks_url":"https://api.github.com/repos/dogweather/zeroclickinfo-goodies/forks","keys_url":"https://api.github.com/repos/dogweather/zeroclickinfo-goodies/keys{/key_id}","collaborators_url":"https://api.github.com/repos/dogweather/zeroclickinfo-goodies/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/dogweather/zeroclickinfo-goodies/teams","hooks_url":"https://api.github.com/repos/dogweather/zeroclickinfo-goodies/hooks","issue_events_url":"https://api.github.com/repos/dogweather/zeroclickinfo-goodies/issues/events{/number}","events_url":"https://api.github.com/repos/dogweather/zeroclickinfo-goodies/events","assignees_url":"https://api.github.com/repos/dogweather/zeroclickinfo-goodies/assignees{/user}","branches_url":"https://api.github.com/repos/dogweather/zeroclickinfo-goodies/branches{/branch}","tags_url":"https://api.github.com/repos/dogweather/zeroclickinfo-goodies/tags","blobs_url":"https://api.github.com/repos/dogweather/zeroclickinfo-goodies/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/dogweather/zeroclickinfo-goodies/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/dogweather/zeroclickinfo-goodies/git/refs{/sha}","trees_url":"https://api.github.com/repos/dogweather/zeroclickinfo-goodies/git/trees{/sha}","statuses_url":"https://api.github.com/repos/dogweather/zeroclickinfo-goodies/statuses/{sha}","languages_url":"https://api.github.com/repos/dogweather/zeroclickinfo-goodies/languages","stargazers_url":"https://api.github.com/repos/dogweather/zeroclickinfo-goodies/stargazers","contributors_url":"https://api.github.com/repos/dogweather/zeroclickinfo-goodies/contributors","subscribers_url":"https://api.github.com/repos/dogweather/zeroclickinfo-goodies/subscribers","subscription_url":"https://api.github.com/repos/dogweather/zeroclickinfo-goodies/subscription","commits_url":"https://api.github.com/repos/dogweather/zeroclickinfo-goodies/commits{/sha}","git_commits_url":"https://api.github.com/repos/dogweather/zeroclickinfo-goodies/git/commits{/sha}","comments_url":"https://api.github.com/repos/dogweather/zeroclickinfo-goodies/comments{/number}","issue_comment_url":"https://api.github.com/repos/dogweather/zeroclickinfo-goodies/issues/comments{/number}","contents_url":"https://api.github.com/repos/dogweather/zeroclickinfo-goodies/contents/{+path}","compare_url":"https://api.github.com/repos/dogweather/zeroclickinfo-goodies/compare/{base}...{head}","merges_url":"https://api.github.com/repos/dogweather/zeroclickinfo-goodies/merges","archive_url":"https://api.github.com/repos/dogweather/zeroclickinfo-goodies/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/dogweather/zeroclickinfo-goodies/downloads","issues_url":"https://api.github.com/repos/dogweather/zeroclickinfo-goodies/issues{/number}","pulls_url":"https://api.github.com/repos/dogweather/zeroclickinfo-goodies/pulls{/number}","milestones_url":"https://api.github.com/repos/dogweather/zeroclickinfo-goodies/milestones{/number}","notifications_url":"https://api.github.com/repos/dogweather/zeroclickinfo-goodies/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/dogweather/zeroclickinfo-goodies/labels{/name}","releases_url":"https://api.github.com/repos/dogweather/zeroclickinfo-goodies/releases{/id}","created_at":"2015-03-14T07:43:16Z","updated_at":"2015-03-14T07:43:19Z","pushed_at":"2015-03-15T05:05:22Z","git_url":"git://github.com/dogweather/zeroclickinfo-goodies.git","ssh_url":"git@github.com:dogweather/zeroclickinfo-goodies.git","clone_url":"https://github.com/dogweather/zeroclickinfo-goodies.git","svn_url":"https://github.com/dogweather/zeroclickinfo-goodies","homepage":"http://duckduckhack.com/","size":26184,"stargazers_count":0,"watchers_count":0,"language":"Perl","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"duckduckgo:master","ref":"master","sha":"f761f030c7e5431d22f6bfa6b2466d9e05a8f624","user":{"login":"duckduckgo","id":342708,"avatar_url":"https://avatars.githubusercontent.com/u/342708?v=3","gravatar_id":"","url":"https://api.github.com/users/duckduckgo","html_url":"https://github.com/duckduckgo","followers_url":"https://api.github.com/users/duckduckgo/followers","following_url":"https://api.github.com/users/duckduckgo/following{/other_user}","gists_url":"https://api.github.com/users/duckduckgo/gists{/gist_id}","starred_url":"https://api.github.com/users/duckduckgo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/duckduckgo/subscriptions","organizations_url":"https://api.github.com/users/duckduckgo/orgs","repos_url":"https://api.github.com/users/duckduckgo/repos","events_url":"https://api.github.com/users/duckduckgo/events{/privacy}","received_events_url":"https://api.github.com/users/duckduckgo/received_events","type":"Organization","site_admin":false},"repo":{"id":2164979,"name":"zeroclickinfo-goodies","full_name":"duckduckgo/zeroclickinfo-goodies","owner":{"login":"duckduckgo","id":342708,"avatar_url":"https://avatars.githubusercontent.com/u/342708?v=3","gravatar_id":"","url":"https://api.github.com/users/duckduckgo","html_url":"https://github.com/duckduckgo","followers_url":"https://api.github.com/users/duckduckgo/followers","following_url":"https://api.github.com/users/duckduckgo/following{/other_user}","gists_url":"https://api.github.com/users/duckduckgo/gists{/gist_id}","starred_url":"https://api.github.com/users/duckduckgo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/duckduckgo/subscriptions","organizations_url":"https://api.github.com/users/duckduckgo/orgs","repos_url":"https://api.github.com/users/duckduckgo/repos","events_url":"https://api.github.com/users/duckduckgo/events{/privacy}","received_events_url":"https://api.github.com/users/duckduckgo/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/duckduckgo/zeroclickinfo-goodies","description":"DuckDuckGo instant answer plugins based on Perl functions","fork":false,"url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies","forks_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/forks","keys_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/keys{/key_id}","collaborators_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/teams","hooks_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/hooks","issue_events_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/issues/events{/number}","events_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/events","assignees_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/assignees{/user}","branches_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/branches{/branch}","tags_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/tags","blobs_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/git/refs{/sha}","trees_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/git/trees{/sha}","statuses_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/statuses/{sha}","languages_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/languages","stargazers_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/stargazers","contributors_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/contributors","subscribers_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/subscribers","subscription_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/subscription","commits_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/commits{/sha}","git_commits_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/git/commits{/sha}","comments_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/comments{/number}","issue_comment_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/issues/comments{/number}","contents_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/contents/{+path}","compare_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/compare/{base}...{head}","merges_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/merges","archive_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/downloads","issues_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/issues{/number}","pulls_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/pulls{/number}","milestones_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/milestones{/number}","notifications_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/labels{/name}","releases_url":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/releases{/id}","created_at":"2011-08-06T13:26:05Z","updated_at":"2015-03-15T20:58:01Z","pushed_at":"2015-03-15T00:27:40Z","git_url":"git://github.com/duckduckgo/zeroclickinfo-goodies.git","ssh_url":"git@github.com:duckduckgo/zeroclickinfo-goodies.git","clone_url":"https://github.com/duckduckgo/zeroclickinfo-goodies.git","svn_url":"https://github.com/duckduckgo/zeroclickinfo-goodies","homepage":"http://duckduckhack.com/","size":26184,"stargazers_count":253,"watchers_count":253,"language":"Perl","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":757,"mirror_url":null,"open_issues_count":92,"forks":757,"open_issues":92,"watchers":253,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/pulls/1059"},"html":{"href":"https://github.com/duckduckgo/zeroclickinfo-goodies/pull/1059"},"issue":{"href":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/issues/1059"},"comments":{"href":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/issues/1059/comments"},"review_comments":{"href":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/pulls/1059/comments"},"review_comment":{"href":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/pulls/1059/commits"},"statuses":{"href":"https://api.github.com/repos/duckduckgo/zeroclickinfo-goodies/statuses/ac3b198746c0817462f2e9c72455ddf4698653db"}}}}