1 module SeekingWhirl; 2 import std.conv; 3 import std.json; 4 import std.net.curl; 5 /** 6 * DuckDuckGo API for D 7 * Authors: Azbuka-slovensko 8 * License: MIT 9 */ 10 class SeekingWhirl { 11 ///topic summary (can contain HTML) 12 string Abstract; 13 ///topic summary (w\o HTML) 14 string AbstractText; 15 ///name of source 16 string AbstractSource; 17 ///link to topic page 18 string AbstractURL; 19 ///link to Abstract's image 20 string Image; 21 ///Abstract's topic name 22 string Heading; 23 24 ///instant answer 25 string Answer; 26 ///instant answer type 27 string AnswerType; 28 29 ///dictionary Definition 30 string Definition; 31 ///name of Definition source 32 string DefinitionSource; 33 ///link to expanded page 34 string DefinitionURL; 35 36 ///icon asociated with topic 37 struct icon { 38 ///link to icon 39 string URL; 40 ///icon height 41 long Height; 42 ///icon width 43 long Width; 44 } 45 46 ///external links 47 struct result { 48 ///link to topic 49 string Result; 50 ///first url in Result 51 string FirstURL; 52 ///icon of topic 53 icon Icon; 54 ///text from firstURL 55 string Text; 56 } 57 58 ///array of internal links 59 result[] RelatedTopics; 60 ///array of external links 61 result[] Results; 62 63 ///response category 64 string Type; 65 ///!bang redirect 66 string Redirect; 67 68 69 /** 70 * Search 71 * Params: 72 * query = string to search 73 * appname = name of app 74 * no_redirect = true to skip HTTP redirects 75 * no_html = true to remove HTML from text 76 * skip_disambig = true to skip disambugation (D) Type 77 */ 78 this(string query, 79 string appname = "", 80 bool no_redirect = false, 81 bool no_html = false, 82 bool skip_disambig = false) { 83 string url = "http://api.duckduckgo.com/?q=" ~ query 84 ~ "&format=json"; 85 if(appname) 86 url ~= "&t=" ~ appname; 87 if(no_redirect) 88 url ~= "&no_redirect=1"; 89 if(no_html) 90 url ~= "&no_html=1"; 91 if(skip_disambig) 92 url ~= "&skip_disambig=1"; 93 94 JSONValue j = parseJSON(get(url)); 95 96 this.Abstract = j["Abstract"].str; 97 this.AbstractText = j["AbstractText"].str; 98 this.AbstractSource = j["AbstractSource"].str; 99 this.AbstractURL = j["AbstractURL"].str; 100 this.Image = j["Image"].str; 101 this.Heading = j["Heading"].str; 102 103 this.Answer = j["Answer"].str; 104 this.AnswerType = j["AnswerType"].str; 105 106 this.Definition = j["Definition"].str; 107 this.DefinitionSource = j["DefinitionSource"].str; 108 this.DefinitionURL = j["DefinitionURL"].str; 109 110 try { 111 for(ulong i = 0; i < j["RelatedTopics"].array.length; i++) { 112 this.RelatedTopics ~= result(j["RelatedTopics"][i]["Result"].str, 113 j["RelatedTopics"][i]["FirstURL"].str, 114 icon(j["RelatedTopics"][i]["Icon"]["URL"].str, 115 DDGNumber(j["RelatedTopics"][i]["Icon"]["Height"]), 116 DDGNumber(j["RelatedTopics"][i]["Icon"]["Width"]) 117 ), 118 j["RelatedTopics"][i]["Text"].str 119 ); 120 } 121 } catch { } 122 try { 123 for(ulong i = 0; i < j["Results"].array.length; i++) { 124 this.Results ~= result(j["Results"][i]["Result"].str, 125 j["Results"][i]["FirstURL"].str, 126 icon(j["Results"][i]["Icon"]["URL"].str, 127 DDGNumber(j["Results"][i]["Icon"]["Height"]), 128 DDGNumber(j["Results"][i]["Icon"]["Width"]) 129 ), 130 j["Results"][i]["Text"].str 131 ); 132 } 133 } catch { } 134 } 135 private long DDGNumber(JSONValue j) { 136 try { 137 return j.integer; 138 } catch { 139 return 0; 140 } 141 142 } 143 }