diff options
-rw-r--r-- | bot.py | 4 | ||||
-rw-r--r-- | callback.py | 177 |
2 files changed, 91 insertions, 90 deletions
@@ -17,7 +17,7 @@ from callback import ( | |||
17 | callback_manual_location, | 17 | callback_manual_location, |
18 | callback_location_confirmation, | 18 | callback_location_confirmation, |
19 | callback_location_keyword_search, | 19 | callback_location_keyword_search, |
20 | callback_skip_location_keyword, | 20 | callback_skip_location_keyword_search, |
21 | callback_add_comment, | 21 | callback_add_comment, |
22 | callback_skip_comment, | 22 | callback_skip_comment, |
23 | callback_add_media | 23 | callback_add_media |
@@ -56,7 +56,7 @@ def main() -> None: | |||
56 | ], | 56 | ], |
57 | LOCATION_SEARCH_KEYWORD: [ | 57 | LOCATION_SEARCH_KEYWORD: [ |
58 | MessageHandler(filters.TEXT & ~filters.COMMAND, callback_location_keyword_search), | 58 | MessageHandler(filters.TEXT & ~filters.COMMAND, callback_location_keyword_search), |
59 | CallbackQueryHandler(callback_skip_location_keyword), | 59 | CallbackQueryHandler(callback_skip_location_keyword_search), |
60 | ], | 60 | ], |
61 | LOCATION_CONFIRMATION: [ | 61 | LOCATION_CONFIRMATION: [ |
62 | CallbackQueryHandler(callback_location_confirmation), | 62 | CallbackQueryHandler(callback_location_confirmation), |
diff --git a/callback.py b/callback.py index 9b82d78..38b0456 100644 --- a/callback.py +++ b/callback.py | |||
@@ -27,6 +27,37 @@ def generate_toot_text(poi_name, poi_locality, poi_region, poi_lat, poi_lon): | |||
27 | return f"I'm at {poi_name}, {osm_url}" | 27 | return f"I'm at {poi_name}, {osm_url}" |
28 | 28 | ||
29 | 29 | ||
30 | async def get_img_file_bytes(telegram_media_file): | ||
31 | img = io.BytesIO() | ||
32 | await telegram_media_file.download_to_memory(img) | ||
33 | img.seek(0) | ||
34 | |||
35 | return img.read() | ||
36 | |||
37 | |||
38 | async def process_media_group(context: CallbackContext): | ||
39 | context.job.data = cast(List[MsgDict], context.job.data) | ||
40 | |||
41 | media_id = [] | ||
42 | chat_id = context.job.data[0].get("chat_id") | ||
43 | for msg_dict in context.job.data: | ||
44 | if len(media_id) >= 4: | ||
45 | await context.bot.send_message(chat_id=chat_id, text=PROMPT_MAX_PHOTO_REACHED, reply_markup=MAIN_MENU) | ||
46 | return | ||
47 | |||
48 | file = await context.bot.get_file(msg_dict.get("media_id")) | ||
49 | img = await get_img_file_bytes(file) | ||
50 | media = mastodon_client.media_post(img, mime_type="image/jpeg") | ||
51 | media_id.append(media["id"]) | ||
52 | |||
53 | mastodon_client.status_update( | ||
54 | status=msg_dict.get("content"), | ||
55 | id=msg_dict.get("status_id"), | ||
56 | media_ids=media_id) | ||
57 | |||
58 | await context.bot.send_message(chat_id=chat_id, text=PROMPT_DONE, reply_markup=MAIN_MENU) | ||
59 | |||
60 | |||
30 | async def callback_location_sharing(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: | 61 | async def callback_location_sharing(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: |
31 | if update.message.venue is not None: | 62 | if update.message.venue is not None: |
32 | context.user_data["fsq_id"] = update.message.venue.foursquare_id | 63 | context.user_data["fsq_id"] = update.message.venue.foursquare_id |
@@ -59,27 +90,32 @@ async def callback_location_sharing(update: Update, context: ContextTypes.DEFAUL | |||
59 | return LOCATION_SEARCH_KEYWORD | 90 | return LOCATION_SEARCH_KEYWORD |
60 | 91 | ||
61 | 92 | ||
62 | async def callback_location_keyword_search(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: | 93 | async def _process_location_search(keyword, lat, lon) -> list: |
63 | await context.bot.delete_message(update.effective_chat.id, context.user_data.get(PROMPT_LOCATION_KEYWORD)) | 94 | keyboard = [] |
95 | poi_result = [] | ||
64 | 96 | ||
65 | location_search_keyword = update.effective_message.text | 97 | if keyword: |
66 | latitude = context.user_data.get("latitude") | 98 | poi_result = query_poi(keyword, lat, lon) |
67 | longitude = context.user_data.get("longitude") | ||
68 | 99 | ||
69 | keyboard = [] | ||
70 | poi_result = query_poi(location_search_keyword, latitude, longitude) | ||
71 | if len(poi_result) == 0: | 100 | if len(poi_result) == 0: |
72 | poi_result = query_poi("", latitude, longitude) | 101 | poi_result = query_poi("", lat, lon) |
73 | 102 | ||
74 | for poi in poi_result: | 103 | for poi in poi_result: |
75 | keyboard.append([ | 104 | keyboard.append([ |
76 | InlineKeyboardButton(poi["name"], callback_data=poi["fsq_id"]), | 105 | InlineKeyboardButton(poi["name"], callback_data=poi["fsq_id"]), |
77 | ]) | 106 | ]) |
107 | return keyboard | ||
108 | |||
109 | |||
110 | async def callback_location_keyword_search(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: | ||
111 | await context.bot.delete_message(update.effective_chat.id, context.user_data.get(PROMPT_LOCATION_KEYWORD)) | ||
112 | key = update.effective_message.text | ||
113 | |||
114 | keyboard = await _process_location_search(key, context.user_data.get("latitude"), context.user_data.get("longitude")) | ||
78 | 115 | ||
79 | if len(keyboard) == 0: | 116 | if len(keyboard) == 0: |
80 | msg = await update.message.reply_text(PROMPT_WAIT_LOCATION_CONFIRMATION_NO_NEARBY_POI) | 117 | msg = await update.message.reply_text(PROMPT_WAIT_LOCATION_CONFIRMATION_NO_NEARBY_POI) |
81 | else: | 118 | else: |
82 | context.user_data["location_search"] = location_search_keyword | ||
83 | msg = await update.message.reply_text(PROMPT_WAIT_LOCATION_CONFIRMATION, | 119 | msg = await update.message.reply_text(PROMPT_WAIT_LOCATION_CONFIRMATION, |
84 | reply_markup=InlineKeyboardMarkup(keyboard)) | 120 | reply_markup=InlineKeyboardMarkup(keyboard)) |
85 | 121 | ||
@@ -87,121 +123,89 @@ async def callback_location_keyword_search(update: Update, context: ContextTypes | |||
87 | return LOCATION_CONFIRMATION | 123 | return LOCATION_CONFIRMATION |
88 | 124 | ||
89 | 125 | ||
90 | async def callback_skip_location_keyword(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: | 126 | async def callback_skip_location_keyword_search(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: |
91 | query = update.callback_query | 127 | query = update.callback_query |
92 | await query.answer() | 128 | await query.answer() |
93 | |||
94 | await query.message.delete() | 129 | await query.message.delete() |
95 | latitude = context.user_data.get("latitude") | ||
96 | longitude = context.user_data.get("longitude") | ||
97 | |||
98 | keyboard = [] | ||
99 | |||
100 | for poi in query_poi("", latitude, longitude): | ||
101 | keyboard.append([ | ||
102 | InlineKeyboardButton(poi["name"], callback_data=poi["fsq_id"]), | ||
103 | ]) | ||
104 | 130 | ||
131 | keyboard = await _process_location_search("", context.user_data.get("latitude"), context.user_data.get("longitude")) | ||
105 | await query.message.reply_text(PROMPT_WAIT_LOCATION_CONFIRMATION, reply_markup=InlineKeyboardMarkup(keyboard)) | 132 | await query.message.reply_text(PROMPT_WAIT_LOCATION_CONFIRMATION, reply_markup=InlineKeyboardMarkup(keyboard)) |
106 | 133 | ||
107 | return LOCATION_CONFIRMATION | 134 | return LOCATION_CONFIRMATION |
108 | 135 | ||
109 | 136 | ||
110 | async def callback_location_confirmation(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: | 137 | async def _process_location_selection(context: ContextTypes.DEFAULT_TYPE) -> int: |
111 | query = update.callback_query | 138 | poi_name = context.user_data.get("poi_name") |
112 | await query.answer() | 139 | if context.user_data.get("fsq_id") is not None: |
113 | 140 | poi = get_loc(context.user_data.get("fsq_id")) | |
114 | context.user_data["fsq_id"] = query.data | 141 | content = generate_toot_text(poi["name"], poi["locality"], poi["region"], poi["latitude"], poi["longitude"]) |
115 | await query.delete_message() | 142 | else: |
143 | content = generate_toot_text(poi_name, "", "", context.user_data.get("latitude"), context.user_data.get("longitude")) | ||
116 | 144 | ||
117 | poi = get_loc(context.user_data.get("fsq_id")) | ||
118 | content = generate_toot_text(poi["name"], poi["locality"], poi["region"], poi["latitude"], poi["longitude"]) | ||
119 | status = mastodon_client.status_post(content, visibility=DEFAULT_TOOT_VISIBILITY, media_ids=[]) | 145 | status = mastodon_client.status_post(content, visibility=DEFAULT_TOOT_VISIBILITY, media_ids=[]) |
120 | 146 | ||
121 | context.user_data[KEY_TOOT_STATUS_ID] = status["id"] | 147 | context.user_data[KEY_TOOT_STATUS_ID] = status["id"] |
122 | context.user_data[KEY_TOOT_STATUS_CONTENT] = content | 148 | context.user_data[KEY_TOOT_STATUS_CONTENT] = content |
123 | 149 | ||
124 | await query.message.reply_text( | 150 | await context.bot.send_message(chat_id=context.user_data.get("chat_id"), |
125 | text=f"Selected place: {poi['name']}, `{query.data}`\nPosted to Mastodon: {status['url']}", | 151 | text=f"Selected place: {poi_name}, \nPosted to Mastodon: {status['url']}", |
126 | parse_mode=ParseMode.MARKDOWN, | 152 | parse_mode=ParseMode.MARKDOWN) |
127 | ) | 153 | |
154 | msg = await context.bot.send_message(chat_id=context.user_data.get("chat_id"), | ||
155 | text=PROMPT_ADD_COMMENT, | ||
156 | reply_markup=INLINE_SKIP_MENU) | ||
128 | 157 | ||
129 | msg = await query.message.reply_text(PROMPT_ADD_COMMENT, reply_markup=INLINE_SKIP_MENU) | ||
130 | context.user_data[PROMPT_ADD_COMMENT] = msg.message_id | 158 | context.user_data[PROMPT_ADD_COMMENT] = msg.message_id |
131 | 159 | ||
132 | return ADD_COMMENT | 160 | return ADD_COMMENT |
133 | 161 | ||
134 | 162 | ||
135 | async def callback_manual_location(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: | 163 | async def callback_location_confirmation(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: |
136 | manual_poi_name = update.effective_message.text | 164 | query = update.callback_query |
137 | content = generate_toot_text(manual_poi_name, "", "", context.user_data.get("latitude"), | 165 | await query.answer() |
138 | context.user_data.get("longitude")) | 166 | context.user_data["fsq_id"] = query.data |
139 | status = mastodon_client.status_post(content, visibility=DEFAULT_TOOT_VISIBILITY, media_ids=[]) | 167 | await query.delete_message() |
140 | 168 | ||
141 | context.user_data[KEY_TOOT_STATUS_ID] = status["id"] | 169 | context.user_data["chat_id"] = update.effective_chat.id |
142 | context.user_data[KEY_TOOT_STATUS_CONTENT] = content | ||
143 | 170 | ||
144 | await update.message.reply_text( | 171 | return await _process_location_selection(context) |
145 | text=f"Manually selected place: {manual_poi_name}, \nPosted to Mastodon: {status['url']}", | ||
146 | parse_mode=ParseMode.MARKDOWN, | ||
147 | ) | ||
148 | 172 | ||
149 | msg = await update.message.reply_text(PROMPT_ADD_COMMENT, reply_markup=INLINE_SKIP_MENU) | ||
150 | context.user_data[PROMPT_ADD_COMMENT] = msg.message_id | ||
151 | 173 | ||
152 | return ADD_COMMENT | 174 | async def callback_manual_location(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: |
175 | context.user_data["poi_name"] = update.effective_message.text | ||
176 | context.user_data["chat_id"] = update.effective_chat.id | ||
177 | |||
178 | return await _process_location_selection(context) | ||
179 | |||
180 | |||
181 | async def _process_comment(context: ContextTypes.DEFAULT_TYPE) -> int: | ||
182 | msg = await context.bot.send_message(chat_id=context.user_data.get("chat_id"), | ||
183 | text=PROMPT_ADD_MEDIA, | ||
184 | reply_markup=INLINE_SKIP_MENU) | ||
185 | context.user_data[PROMPT_ADD_MEDIA] = msg.message_id | ||
186 | return ADD_MEDIA | ||
153 | 187 | ||
154 | 188 | ||
155 | async def callback_add_comment(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: | 189 | async def callback_add_comment(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: |
190 | context.user_data["chat_id"] = update.effective_chat.id | ||
156 | await context.bot.delete_message(update.effective_chat.id, context.user_data.get(PROMPT_ADD_COMMENT)) | 191 | await context.bot.delete_message(update.effective_chat.id, context.user_data.get(PROMPT_ADD_COMMENT)) |
157 | comment = update.effective_message.text | ||
158 | 192 | ||
193 | comment = update.effective_message.text | ||
159 | mastodon_client.status_update(id=context.user_data.get(KEY_TOOT_STATUS_ID), | 194 | mastodon_client.status_update(id=context.user_data.get(KEY_TOOT_STATUS_ID), |
160 | status=f"{comment} " + context.user_data.get(KEY_TOOT_STATUS_CONTENT)) | 195 | status=f"{comment} " + context.user_data.get(KEY_TOOT_STATUS_CONTENT)) |
161 | |||
162 | context.user_data[KEY_TOOT_STATUS_CONTENT] = f"{comment} " + context.user_data.get(KEY_TOOT_STATUS_CONTENT) | 196 | context.user_data[KEY_TOOT_STATUS_CONTENT] = f"{comment} " + context.user_data.get(KEY_TOOT_STATUS_CONTENT) |
163 | prompt_attach_photo_msg = await update.message.reply_text(PROMPT_ADD_MEDIA, reply_markup=INLINE_SKIP_MENU) | ||
164 | context.user_data[PROMPT_ADD_MEDIA] = prompt_attach_photo_msg.message_id | ||
165 | 197 | ||
166 | return ADD_MEDIA | 198 | return await _process_comment(context) |
167 | 199 | ||
168 | 200 | ||
169 | async def callback_skip_comment(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: | 201 | async def callback_skip_comment(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: |
202 | context.user_data["chat_id"] = update.effective_chat.id | ||
170 | await context.bot.delete_message(update.effective_chat.id, context.user_data.get(PROMPT_ADD_COMMENT)) | 203 | await context.bot.delete_message(update.effective_chat.id, context.user_data.get(PROMPT_ADD_COMMENT)) |
171 | prompt_attach_photo_msg = await context.bot.send_message(chat_id=update.effective_chat.id, | ||
172 | text=PROMPT_ADD_MEDIA, | ||
173 | reply_markup=INLINE_SKIP_MENU) | ||
174 | context.user_data[PROMPT_ADD_MEDIA] = prompt_attach_photo_msg.message_id | ||
175 | return ADD_MEDIA | ||
176 | |||
177 | 204 | ||
178 | async def callback_add_media(update: Update, context: CallbackContext): | 205 | return await _process_comment(context) |
179 | async def process_media_group(context: CallbackContext): | ||
180 | context.job.data = cast(List[MsgDict], context.job.data) | ||
181 | |||
182 | _media_id = [] | ||
183 | chat_id = context.job.data[0].get("chat_id") | ||
184 | for _msg_dict in context.job.data: | ||
185 | if len(_media_id) >= 4: | ||
186 | await context.bot.send_message(chat_id=chat_id, text=PROMPT_MAX_PHOTO_REACHED, reply_markup=MAIN_MENU) | ||
187 | return | ||
188 | |||
189 | _file = await context.bot.get_file(_msg_dict.get("media_id")) | ||
190 | _img = io.BytesIO() | ||
191 | await _file.download_to_memory(_img) | ||
192 | |||
193 | _img.seek(0) | ||
194 | 206 | ||
195 | _media = mastodon_client.media_post(_img.read(), mime_type="image/jpeg") | ||
196 | _media_id.append(_media["id"]) | ||
197 | |||
198 | mastodon_client.status_update( | ||
199 | status=_msg_dict.get("content"), | ||
200 | id=_msg_dict.get("status_id"), | ||
201 | media_ids=_media_id) | ||
202 | |||
203 | await context.bot.send_message(chat_id=chat_id, text=PROMPT_DONE, reply_markup=MAIN_MENU) | ||
204 | 207 | ||
208 | async def callback_add_media(update: Update, context: CallbackContext): | ||
205 | await update.message.reply_chat_action(ChatAction.TYPING) | 209 | await update.message.reply_chat_action(ChatAction.TYPING) |
206 | 210 | ||
207 | try: | 211 | try: |
@@ -233,11 +237,8 @@ async def callback_add_media(update: Update, context: CallbackContext): | |||
233 | data=[msg_dict], name=str(message.media_group_id)) | 237 | data=[msg_dict], name=str(message.media_group_id)) |
234 | else: | 238 | else: |
235 | file = await update.message.effective_attachment[-1].get_file() | 239 | file = await update.message.effective_attachment[-1].get_file() |
236 | img = io.BytesIO() | 240 | img = await get_img_file_bytes(file) |
237 | await file.download_to_memory(img) | 241 | media = mastodon_client.media_post(img, mime_type="image/jpeg") |
238 | img.seek(0) | ||
239 | |||
240 | media = mastodon_client.media_post(img.read(), mime_type="image/jpeg") | ||
241 | mastodon_client.status_update(status=status_content, id=status_id, media_ids=media["id"]) | 242 | mastodon_client.status_update(status=status_content, id=status_id, media_ids=media["id"]) |
242 | 243 | ||
243 | await update.message.reply_text(text=PROMPT_DONE, reply_markup=MAIN_MENU) | 244 | await update.message.reply_text(text=PROMPT_DONE, reply_markup=MAIN_MENU) |