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