diff options
Diffstat (limited to 'callback.py')
-rw-r--r-- | callback.py | 266 |
1 files changed, 266 insertions, 0 deletions
diff --git a/callback.py b/callback.py new file mode 100644 index 0000000..8c80028 --- /dev/null +++ b/callback.py | |||
@@ -0,0 +1,266 @@ | |||
1 | import io | ||
2 | from foursquare.poi import OSM_ENDPOINT | ||
3 | from foursquare.poi import query_poi | ||
4 | from dbstore.dbm_store import get_loc | ||
5 | from toot import mastodon_client | ||
6 | from command import * | ||
7 | from telegram import __version__ as TG_VER | ||
8 | from typing import cast, List | ||
9 | from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update, ReplyKeyboardMarkup, KeyboardButton | ||
10 | from telegram.ext import Application, CallbackQueryHandler, CommandHandler, ContextTypes, MessageHandler, filters, \ | ||
11 | ConversationHandler, CallbackContext | ||
12 | from telegram.constants import ParseMode, ChatAction | ||
13 | from telegram.error import BadRequest | ||
14 | from telegram import InlineKeyboardButton, InlineKeyboardMarkup, ReplyKeyboardRemove | ||
15 | |||
16 | |||
17 | async def callback_skip_media(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: | ||
18 | query = update.callback_query | ||
19 | await query.answer() | ||
20 | |||
21 | await query.delete_message() | ||
22 | await query.message.reply_text(text=PROMPT_DONE, reply_markup=MAIN_MENU) | ||
23 | |||
24 | return ConversationHandler.END | ||
25 | |||
26 | |||
27 | async def callback_location_sharing(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: | ||
28 | if update.message.venue is not None: | ||
29 | fsq_id = update.message.venue.foursquare_id | ||
30 | title = update.message.venue.title | ||
31 | context.user_data["fsq_id"] = fsq_id | ||
32 | context.user_data["title"] = title | ||
33 | context.user_data["latitude"] = update.message.venue.location.latitude | ||
34 | context.user_data["longitude"] = update.message.venue.location.longitude | ||
35 | |||
36 | poi = get_loc(context.user_data["fsq_id"]) | ||
37 | media_id = [] | ||
38 | content = f"I'm at {poi['name']} in {poi['locality']}, {poi['region']}, {poi['osm_url']}" | ||
39 | status = mastodon_client.status_post( | ||
40 | content, | ||
41 | visibility="private", | ||
42 | media_ids=media_id) | ||
43 | |||
44 | context.user_data["status_id"] = status["id"] | ||
45 | context.user_data["status_content"] = content | ||
46 | |||
47 | print("status_id", context.user_data["status_id"]) | ||
48 | |||
49 | await update.message.reply_text( | ||
50 | text=f"Selected place: {poi['name']}, \nPosted to Mastodon: {status['url']}", | ||
51 | parse_mode=ParseMode.MARKDOWN, | ||
52 | ) | ||
53 | |||
54 | prompt_attach_comment_msg = await update.message.reply_text(PROMPT_ADD_COMMENT, reply_markup=INLINE_SKIP_MENU) | ||
55 | context.user_data[PROMPT_ADD_COMMENT] = prompt_attach_comment_msg.message_id | ||
56 | |||
57 | return ADD_COMMENT | ||
58 | else: | ||
59 | context.user_data["latitude"] = update.message.location.latitude | ||
60 | context.user_data["longitude"] = update.message.location.longitude | ||
61 | |||
62 | await update.message.reply_text("Searching...", reply_markup=ReplyKeyboardRemove()) | ||
63 | prompt_msg = await update.message.reply_text(PROMPT_LOCATION_KEYWORD, reply_markup=INLINE_SKIP_MENU) | ||
64 | |||
65 | context.user_data[PROMPT_LOCATION_KEYWORD] = prompt_msg.message_id | ||
66 | return LOCATION_SEARCH_KEYWORD | ||
67 | |||
68 | |||
69 | async def callback_manual_location(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: | ||
70 | loc = update.effective_message.text | ||
71 | osm_url = OSM_ENDPOINT.format(context.user_data["latitude"], context.user_data["longitude"]) | ||
72 | media_id = [] | ||
73 | content = f"I'm at {loc}, {osm_url}" | ||
74 | status = mastodon_client.status_post( | ||
75 | content, | ||
76 | visibility="private", | ||
77 | media_ids=media_id) | ||
78 | |||
79 | context.user_data["status_id"] = status["id"] | ||
80 | context.user_data["status_content"] = content | ||
81 | |||
82 | print("status_id", context.user_data["status_id"]) | ||
83 | |||
84 | await update.message.reply_text( | ||
85 | text=f"Manually selected place: {loc}, \nPosted to Mastodon: {status['url']}", | ||
86 | parse_mode=ParseMode.MARKDOWN, | ||
87 | ) | ||
88 | |||
89 | prompt_attach_comment_msg = await update.message.reply_text(PROMPT_ADD_COMMENT, reply_markup=INLINE_SKIP_MENU) | ||
90 | context.user_data[PROMPT_ADD_COMMENT] = prompt_attach_comment_msg.message_id | ||
91 | |||
92 | return ADD_COMMENT | ||
93 | |||
94 | |||
95 | async def callback_location_confirmation(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: | ||
96 | query = update.callback_query | ||
97 | await query.answer() | ||
98 | context.user_data["fsq_id"] = query.data | ||
99 | |||
100 | await query.delete_message() | ||
101 | |||
102 | poi = get_loc(context.user_data["fsq_id"]) | ||
103 | media_id = [] | ||
104 | content = f"I'm at {poi['name']} in {poi['locality']}, {poi['region']}, {poi['osm_url']}" | ||
105 | status = mastodon_client.status_post( | ||
106 | content, | ||
107 | visibility="private", | ||
108 | media_ids=media_id) | ||
109 | |||
110 | context.user_data["status_id"] = status["id"] | ||
111 | context.user_data["status_content"] = content | ||
112 | |||
113 | print("status_id", context.user_data["status_id"]) | ||
114 | |||
115 | await query.message.reply_text( | ||
116 | text=f"Selected place: {poi['name']}, `{query.data}`\nPosted to Mastodon: {status['url']}", | ||
117 | parse_mode=ParseMode.MARKDOWN, | ||
118 | ) | ||
119 | |||
120 | prompt_attach_comment_msg = await query.message.reply_text(PROMPT_ADD_COMMENT, reply_markup=INLINE_SKIP_MENU) | ||
121 | context.user_data[PROMPT_ADD_COMMENT] = prompt_attach_comment_msg.message_id | ||
122 | |||
123 | return ADD_COMMENT | ||
124 | |||
125 | |||
126 | async def callback_location_keyword_search(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: | ||
127 | await context.bot.delete_message(update.effective_chat.id, context.user_data[PROMPT_LOCATION_KEYWORD]) | ||
128 | |||
129 | location_search = update.effective_message.text | ||
130 | latitude = context.user_data["latitude"] | ||
131 | longitude = context.user_data["longitude"] | ||
132 | |||
133 | keyboard = [] | ||
134 | poi_result = query_poi(location_search, latitude, longitude) | ||
135 | if len(poi_result) == 0: | ||
136 | poi_result = query_poi("", latitude, longitude) | ||
137 | |||
138 | for poi in poi_result: | ||
139 | keyboard.append([ | ||
140 | InlineKeyboardButton(poi["name"], callback_data=poi["fsq_id"]), | ||
141 | ]) | ||
142 | |||
143 | if len(keyboard) == 0: | ||
144 | await update.message.reply_text(PROMPT_NO_NEARBY_POI) | ||
145 | return LOCATION_CONFIRMATION | ||
146 | else: | ||
147 | reply_markup = InlineKeyboardMarkup(keyboard) | ||
148 | context.user_data["location_search"] = location_search | ||
149 | await update.message.reply_text(PROMPT_CHOOSE_POI_FROM_LIST, reply_markup=reply_markup) | ||
150 | |||
151 | return LOCATION_CONFIRMATION | ||
152 | |||
153 | |||
154 | async def callback_skip_location_keyword(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: | ||
155 | query = update.callback_query | ||
156 | await query.answer() | ||
157 | |||
158 | await query.message.delete() | ||
159 | latitude = context.user_data["latitude"] | ||
160 | longitude = context.user_data["longitude"] | ||
161 | |||
162 | keyboard = [] | ||
163 | |||
164 | for poi in query_poi("", latitude, longitude): | ||
165 | keyboard.append([ | ||
166 | InlineKeyboardButton(poi["name"], callback_data=poi["fsq_id"]), | ||
167 | ]) | ||
168 | |||
169 | reply_markup = InlineKeyboardMarkup(keyboard) | ||
170 | await query.message.reply_text(PROMPT_CHOOSE_POI_FROM_LIST, reply_markup=reply_markup) | ||
171 | |||
172 | return LOCATION_CONFIRMATION | ||
173 | |||
174 | |||
175 | async def callback_add_comment(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: | ||
176 | await context.bot.delete_message(update.effective_chat.id, context.user_data[PROMPT_ADD_COMMENT]) | ||
177 | comment = update.effective_message.text | ||
178 | |||
179 | mastodon_client.status_update( | ||
180 | status=f"{comment} " + context.user_data["status_content"], | ||
181 | id=context.user_data["status_id"]) | ||
182 | |||
183 | context.user_data["status_content"] = f"{comment} " + context.user_data["status_content"] | ||
184 | prompt_attach_photo_msg = await update.message.reply_text(PROMPT_ADD_MEDIA, reply_markup=INLINE_SKIP_MENU) | ||
185 | context.user_data[PROMPT_ADD_MEDIA] = prompt_attach_photo_msg.message_id | ||
186 | |||
187 | return ADD_MEDIA | ||
188 | |||
189 | |||
190 | async def callback_skip_comment(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: | ||
191 | await context.bot.delete_message(update.effective_chat.id, context.user_data[PROMPT_ADD_COMMENT]) | ||
192 | prompt_attach_photo_msg = await update.message.reply_text(PROMPT_ADD_MEDIA, reply_markup=INLINE_SKIP_MENU) | ||
193 | context.user_data[PROMPT_ADD_MEDIA] = prompt_attach_photo_msg.message_id | ||
194 | return ADD_MEDIA | ||
195 | |||
196 | |||
197 | async def process_media_group(context: CallbackContext): | ||
198 | context.job.data = cast(List[MsgDict], context.job.data) | ||
199 | |||
200 | media_id = [] | ||
201 | chat_id = context.job.data[0].get("chat_id") | ||
202 | for msg_dict in context.job.data: | ||
203 | if len(media_id) >= 4: | ||
204 | await context.bot.send_message(chat_id=chat_id, text=PROMPT_MAX_PHOTO_REACHED, reply_markup=MAIN_MENU) | ||
205 | return | ||
206 | |||
207 | file = await context.bot.get_file(msg_dict.get("media_id")) | ||
208 | img = io.BytesIO() | ||
209 | await file.download_to_memory(img) | ||
210 | |||
211 | img.seek(0) | ||
212 | |||
213 | media = mastodon_client.media_post(img.read(), mime_type="image/jpeg") | ||
214 | media_id.append(media["id"]) | ||
215 | |||
216 | mastodon_client.status_update( | ||
217 | status=msg_dict.get("content"), | ||
218 | id=msg_dict.get("status_id"), | ||
219 | media_ids=media_id) | ||
220 | |||
221 | await context.bot.send_message(chat_id=chat_id, text=PROMPT_DONE, reply_markup=MAIN_MENU) | ||
222 | |||
223 | |||
224 | async def callback_add_media(update: Update, context: CallbackContext): | ||
225 | await update.message.reply_chat_action(ChatAction.TYPING) | ||
226 | |||
227 | try: | ||
228 | await context.bot.delete_message(chat_id=update.message.chat_id, | ||
229 | message_id=context.user_data[PROMPT_ADD_MEDIA]) | ||
230 | except BadRequest as e: | ||
231 | if "not found" in str(e.message): | ||
232 | pass | ||
233 | |||
234 | status_id = context.user_data["status_id"] | ||
235 | status_content = context.user_data["status_content"] | ||
236 | |||
237 | message = update.effective_message | ||
238 | context.user_data["media"] = [] | ||
239 | if message.media_group_id: | ||
240 | media_id = message.photo[-1].file_id if message.photo else message.effective_attachment.file_id | ||
241 | msg_dict = { | ||
242 | "media_id": media_id, | ||
243 | "caption": message.caption_html, | ||
244 | "status_id": status_id, | ||
245 | "content": status_content, | ||
246 | "chat_id": message.chat_id, | ||
247 | } | ||
248 | jobs = context.job_queue.get_jobs_by_name(str(message.media_group_id)) | ||
249 | if jobs: | ||
250 | jobs[0].data.append(msg_dict) | ||
251 | else: | ||
252 | context.job_queue.run_once(callback=process_media_group, when=MEDIA_GROUP_TIMEOUT, | ||
253 | data=[msg_dict], name=str(message.media_group_id)) | ||
254 | else: | ||
255 | file = await update.message.effective_attachment[-1].get_file() | ||
256 | img = io.BytesIO() | ||
257 | await file.download_to_memory(img) | ||
258 | img.seek(0) | ||
259 | |||
260 | media = mastodon_client.media_post(img.read(), mime_type="image/jpeg") | ||
261 | mastodon_client.status_update( | ||
262 | status=status_content, | ||
263 | id=status_id, | ||
264 | media_ids=media["id"]) | ||
265 | |||
266 | await update.message.reply_text(text=PROMPT_DONE, reply_markup=MAIN_MENU) | ||