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 thumb_url;
186     Nullable!uint thumb_width;
187     Nullable!uint thumb_height;
188 
189     mixin InlineQueryFields;
190 }
191 
192 struct InlineQueryResultContact
193 {
194     string type = "contact";
195     string id;
196     string phone_number;
197     string first_name;
198     Nullable!string last_name;
199     Nullable!string thumb_url;
200     Nullable!uint thumb_width;
201     Nullable!uint thumb_height;
202 
203     mixin InlineQueryFields;
204 }
205 
206 struct InlineQueryResultGame
207 {
208     string type = "game";
209     string id;
210     string game_short_name;
211     Nullable!InlineKeyboardMarkup reply_markup;
212 }
213 
214 
215 struct InlineQueryResultCachedPhoto
216 {
217     string type = "photo";
218     string id;
219     string photo_file_id;
220     Nullable!string title;
221     Nullable!string description;
222     Nullable!string caption;
223     Nullable!ParseMode parse_mode;
224 
225     mixin InlineQueryFields;
226 }
227 
228 struct InlineQueryResultCachedGif
229 {
230     string type = "gif";
231     string id;
232     string gif_file_id;
233     Nullable!string title;
234     Nullable!string caption;
235     Nullable!ParseMode parse_mode;
236 
237     mixin InlineQueryFields;
238 }
239 
240 struct InlineQueryResultCachedMpeg4Gif
241 {
242     string type = "mpeg4_gif";
243     string id;
244     string mpeg4_file_id;
245     Nullable!string title;
246     Nullable!string caption;
247     Nullable!ParseMode parse_mode;
248 
249     mixin InlineQueryFields;
250 }
251 
252 struct InlineQueryResultCachedSticker
253 {
254     string type = "sticker";
255     string id;
256     string sticker_file_id;
257 
258     mixin InlineQueryFields;
259 }
260 
261 struct InlineQueryResultCachedDocument
262 {
263     string type = "document";
264     string    id;
265     string    title;
266     string    document_file_id;
267     Nullable!string    description;
268     Nullable!string    caption;
269     Nullable!ParseMode parse_mode;
270 
271     mixin InlineQueryFields;
272 }
273 
274 struct InlineQueryResultCachedVideo
275 {
276     string type = "video";
277     string    id;
278     string    video_file_id;
279     string    title;
280     Nullable!string    description;
281     Nullable!string    caption;
282     Nullable!ParseMode parse_mode;
283 
284     mixin InlineQueryFields;
285 }
286 
287 struct InlineQueryResultCachedVoice
288 {
289     string type = "voice";
290     string    id;
291     string    voice_file_id;
292     string    title;
293     Nullable!string    caption;
294     Nullable!ParseMode parse_mode;
295 
296     mixin InlineQueryFields;
297 }
298 
299 
300 struct InlineQueryResultCachedAudio
301 {
302     string type = "audio";
303     string    id;
304     string    audio_file_id;
305     Nullable!string    caption;
306     Nullable!ParseMode parse_mode;
307 
308     mixin InlineQueryFields;
309 }
310 
311 // methods
312 
313 struct AnswerInlineQueryMethod
314 {
315     mixin TelegramMethod!"/answerInlineQuery";
316 
317     string              inline_query_id;
318     InlineQueryResult[] results;
319     uint                cache_time;
320     bool                is_personal;
321     string              next_offset;
322     string              switch_pm_text;
323     string              switch_pm_parameter;
324 }
325 
326 bool answerInlineQuery(BotApi api, ref AnswerInlineQueryMethod m)
327 {
328     return api.callMethod!bool(m);
329 }
330 
331 bool answerInlineQuery(BotApi api, string inlineQueryId, InlineQueryResult[] results)
332 {
333     AnswerInlineQueryMethod m = {
334         inline_query_id : inlineQueryId,
335         results : results
336     };
337 
338     return api.answerInlineQuery(m);
339 }
340 
341 unittest
342 {
343     class BotApiMock : BotApi
344     {
345         this(string token)
346         {
347             super(token);
348         }
349 
350         T callMethod(T, M)(M method)
351         {
352             T result;
353 
354             logDiagnostic("[%d] Requesting %s", requestCounter, method.name);
355 
356             return result;
357         }
358     }
359 
360     auto api = new BotApiMock(null);
361 
362     InlineQueryResult[] iqr = new InlineQueryResult[20];
363 
364     iqr[0] = InlineQueryResultArticle();
365     iqr[1] = InlineQueryResultPhoto();
366     iqr[2] = InlineQueryResultGif();
367     iqr[3] = InlineQueryResultMpeg4Gif();
368     iqr[4] = InlineQueryResultVideo();
369     iqr[5] = InlineQueryResultAudio();
370     iqr[6] = InlineQueryResultVoice();
371     iqr[7] = InlineQueryResultDocument();
372     iqr[8] = InlineQueryResultLocation();
373     iqr[9] = InlineQueryResultVenue();
374     iqr[10] = InlineQueryResultContact();
375     iqr[11] = InlineQueryResultGame();
376     iqr[12] = InlineQueryResultCachedPhoto();
377     iqr[13] = InlineQueryResultCachedGif();
378     iqr[14] = InlineQueryResultCachedMpeg4Gif();
379     iqr[15] = InlineQueryResultCachedSticker();
380     iqr[16] = InlineQueryResultCachedDocument();
381     iqr[17] = InlineQueryResultCachedVideo();
382     iqr[18] = InlineQueryResultCachedVoice();
383     iqr[19] = InlineQueryResultCachedAudio();
384 
385     api.answerInlineQuery("answer-inline-query", iqr);
386 }