1 module telega.telegram.inline;
2 
3 import std.typecons : Nullable;
4 import std.meta : AliasSeq;
5 import telega.botapi : BotApi, TelegramMethod, HTTPMethod;
6 import telega.telegram.basic : ParseMode, InlineKeyboardMarkup, InputMessageContent, User, Location;
7 import telega.serialization : JsonableAlgebraicProxy;
8 
9 struct InlineQuery
10 {
11     string id;
12     User from;
13     Nullable!Location location;
14     string query;
15     string offset;
16 }
17 
18 alias InlineQueryResultStructs = AliasSeq!(
19     InlineQueryResultArticle, InlineQueryResultPhoto, InlineQueryResultGif, InlineQueryResultMpeg4Gif,
20     InlineQueryResultVideo, InlineQueryResultAudio, InlineQueryResultVoice, InlineQueryResultDocument,
21     InlineQueryResultLocation, InlineQueryResultVenue, InlineQueryResultContact, InlineQueryResultGame,
22     InlineQueryResultCachedPhoto, InlineQueryResultCachedGif, InlineQueryResultCachedMpeg4Gif,
23     InlineQueryResultCachedSticker, InlineQueryResultCachedDocument, InlineQueryResultCachedVideo,
24     InlineQueryResultCachedVoice, InlineQueryResultCachedAudio
25 );
26 
27 alias InlineQueryResult = JsonableAlgebraicProxy!InlineQueryResultStructs;
28 
29 mixin template InlineQueryFields()
30 {
31     Nullable!InlineKeyboardMarkup reply_markup;
32     Nullable!InputMessageContent  input_message_content;
33 }
34 
35 struct InlineQueryResultArticle
36 {
37     string type = "article";
38     string id;
39     string title;
40     Nullable!string url;
41     Nullable!bool hide_url;
42     Nullable!string description;
43     Nullable!string thumb_url;
44     Nullable!uint thumb_width;
45     Nullable!uint thumb_height;
46 
47     Nullable!InlineKeyboardMarkup reply_markup;
48     InputMessageContent  input_message_content; // can't be nullable
49 }
50 
51 struct InlineQueryResultPhoto
52 {
53     string type = "photo";
54     string id;
55     string photo_url;
56     string thumb_url;
57     Nullable!uint photo_width;
58     Nullable!uint photo_height;
59     Nullable!string title;
60     Nullable!string description;
61     Nullable!string caption;
62     Nullable!ParseMode parse_mode;
63 
64     mixin InlineQueryFields;
65 }
66 
67 struct InlineQueryResultGif
68 {
69     string type = "gif";
70     string id;
71     string gif_url;
72     Nullable!uint gif_width;
73     Nullable!uint gif_height;
74     Nullable!uint gif_duration;
75     Nullable!string thumb_url;
76     Nullable!string title;
77     Nullable!string caption;
78     Nullable!ParseMode parse_mode;
79 
80     mixin InlineQueryFields;
81 }
82 
83 struct InlineQueryResultMpeg4Gif
84 {
85     string type ="mpeg4_gif";
86     string id;
87     string mpeg4_url;
88     Nullable!uint mpeg4_width;
89     Nullable!uint mpeg4_height;
90     Nullable!uint mpeg4_duration;
91     Nullable!string thumb_url;
92     Nullable!string title;
93     Nullable!string caption;
94     Nullable!ParseMode parse_mode;
95 
96     mixin InlineQueryFields;
97 }
98 
99 struct InlineQueryResultVideo
100 {
101     string type ="video";
102     string id;
103     string video_url;
104     string mime_type;
105     string thumb_url;
106     string title;
107     Nullable!string caption;
108     Nullable!ParseMode parse_mode;
109     Nullable!uint video_width;
110     Nullable!uint video_height;
111     Nullable!uint video_duration;
112     Nullable!string description;
113 
114     mixin InlineQueryFields;
115 }
116 
117 struct InlineQueryResultAudio
118 {
119     string    type = "audio";
120     string    id;
121     string    audio_url;
122     string    title;
123     Nullable!string    caption;
124     Nullable!ParseMode parse_mode;
125     Nullable!string    performer;
126     Nullable!uint      audio_duration;
127 
128     mixin InlineQueryFields;
129 }
130 
131 struct InlineQueryResultVoice
132 {
133     string    type = "voice";
134     string    id;
135     string    voice_url;
136     string    title;
137     Nullable!string    caption;
138     Nullable!ParseMode parse_mode;
139     Nullable!uint      voice_duration;
140 
141     mixin InlineQueryFields;
142 }
143 
144 struct InlineQueryResultDocument
145 {
146     string    type = "document";
147     string    id;
148     string    title;
149     Nullable!string    caption;
150     Nullable!ParseMode parse_mode;
151     Nullable!string    document_url;
152     Nullable!string    mime_type;
153     Nullable!string    description;
154     Nullable!string    thumb_url;
155     Nullable!uint      thumb_width;
156     Nullable!uint      thumb_height;
157 
158     mixin InlineQueryFields;
159 }
160 
161 struct InlineQueryResultLocation
162 {
163     string type = "location";
164     string id;
165     float latitude;
166     float longitude;
167     string title;
168     Nullable!uint live_period;
169     Nullable!string thumb_url;
170     Nullable!uint thumb_width;
171     Nullable!uint thumb_height;
172 
173     mixin InlineQueryFields;
174 }
175 
176 struct InlineQueryResultVenue
177 {
178     string type = "venue";
179     string id;
180     float latitude;
181     float longitude;
182     string title;
183     string address;
184     Nullable!string foursquare_id;
185     Nullable!string foursquare_type;
186     Nullable!string thumb_url;
187     Nullable!uint thumb_width;
188     Nullable!uint thumb_height;
189 
190     mixin InlineQueryFields;
191 }
192 
193 struct InlineQueryResultContact
194 {
195     string type = "contact";
196     string id;
197     string phone_number;
198     string first_name;
199     Nullable!string last_name;
200     Nullable!string vcard;
201     Nullable!string thumb_url;
202     Nullable!uint thumb_width;
203     Nullable!uint thumb_height;
204 
205     mixin InlineQueryFields;
206 }
207 
208 struct InlineQueryResultGame
209 {
210     string type = "game";
211     string id;
212     string game_short_name;
213     Nullable!InlineKeyboardMarkup reply_markup;
214 }
215 
216 
217 struct InlineQueryResultCachedPhoto
218 {
219     string type = "photo";
220     string id;
221     string photo_file_id;
222     Nullable!string title;
223     Nullable!string description;
224     Nullable!string caption;
225     Nullable!ParseMode parse_mode;
226 
227     mixin InlineQueryFields;
228 }
229 
230 struct InlineQueryResultCachedGif
231 {
232     string type = "gif";
233     string id;
234     string gif_file_id;
235     Nullable!string title;
236     Nullable!string caption;
237     Nullable!ParseMode parse_mode;
238 
239     mixin InlineQueryFields;
240 }
241 
242 struct InlineQueryResultCachedMpeg4Gif
243 {
244     string type = "mpeg4_gif";
245     string id;
246     string mpeg4_file_id;
247     Nullable!string title;
248     Nullable!string caption;
249     Nullable!ParseMode parse_mode;
250 
251     mixin InlineQueryFields;
252 }
253 
254 struct InlineQueryResultCachedSticker
255 {
256     string type = "sticker";
257     string id;
258     string sticker_file_id;
259 
260     mixin InlineQueryFields;
261 }
262 
263 struct InlineQueryResultCachedDocument
264 {
265     string type = "document";
266     string    id;
267     string    title;
268     string    document_file_id;
269     Nullable!string    description;
270     Nullable!string    caption;
271     Nullable!ParseMode parse_mode;
272 
273     mixin InlineQueryFields;
274 }
275 
276 struct InlineQueryResultCachedVideo
277 {
278     string type = "video";
279     string    id;
280     string    video_file_id;
281     string    title;
282     Nullable!string    description;
283     Nullable!string    caption;
284     Nullable!ParseMode parse_mode;
285 
286     mixin InlineQueryFields;
287 }
288 
289 struct InlineQueryResultCachedVoice
290 {
291     string type = "voice";
292     string    id;
293     string    voice_file_id;
294     string    title;
295     Nullable!string    caption;
296     Nullable!ParseMode parse_mode;
297 
298     mixin InlineQueryFields;
299 }
300 
301 
302 struct InlineQueryResultCachedAudio
303 {
304     string type = "audio";
305     string    id;
306     string    audio_file_id;
307     Nullable!string    caption;
308     Nullable!ParseMode parse_mode;
309 
310     mixin InlineQueryFields;
311 }
312 
313 // methods
314 
315 struct AnswerInlineQueryMethod
316 {
317     mixin TelegramMethod!"/answerInlineQuery";
318 
319     string              inline_query_id;
320     InlineQueryResult[] results;
321     uint                cache_time;
322     bool                is_personal;
323     string              next_offset;
324     string              switch_pm_text;
325     string              switch_pm_parameter;
326 }
327 
328 bool answerInlineQuery(BotApi api, ref AnswerInlineQueryMethod m)
329 {
330     return api.callMethod!bool(m);
331 }
332 
333 bool answerInlineQuery(BotApi api, string inlineQueryId, InlineQueryResult[] results)
334 {
335     AnswerInlineQueryMethod m = {
336         inline_query_id : inlineQueryId,
337         results : results
338     };
339 
340     return api.answerInlineQuery(m);
341 }
342 
343 unittest
344 {
345     class BotApiMock : BotApi
346     {
347         this(string token)
348         {
349             super(token);
350         }
351 
352         T callMethod(T, M)(M method)
353         {
354             T result;
355 
356             logDiagnostic("[%d] Requesting %s", requestCounter, method.name);
357 
358             return result;
359         }
360     }
361 
362     auto api = new BotApiMock(null);
363 
364     InlineQueryResult[] iqr = new InlineQueryResult[20];
365 
366     iqr[0] = InlineQueryResultArticle();
367     iqr[1] = InlineQueryResultPhoto();
368     iqr[2] = InlineQueryResultGif();
369     iqr[3] = InlineQueryResultMpeg4Gif();
370     iqr[4] = InlineQueryResultVideo();
371     iqr[5] = InlineQueryResultAudio();
372     iqr[6] = InlineQueryResultVoice();
373     iqr[7] = InlineQueryResultDocument();
374     iqr[8] = InlineQueryResultLocation();
375     iqr[9] = InlineQueryResultVenue();
376     iqr[10] = InlineQueryResultContact();
377     iqr[11] = InlineQueryResultGame();
378     iqr[12] = InlineQueryResultCachedPhoto();
379     iqr[13] = InlineQueryResultCachedGif();
380     iqr[14] = InlineQueryResultCachedMpeg4Gif();
381     iqr[15] = InlineQueryResultCachedSticker();
382     iqr[16] = InlineQueryResultCachedDocument();
383     iqr[17] = InlineQueryResultCachedVideo();
384     iqr[18] = InlineQueryResultCachedVoice();
385     iqr[19] = InlineQueryResultCachedAudio();
386 
387     api.answerInlineQuery("answer-inline-query", iqr);
388 }