From a9fb6f252553ae49a2ba372434073824babe31e4 Mon Sep 17 00:00:00 2001 From: clarkzjw Date: Thu, 23 Feb 2023 21:46:27 -0800 Subject: bot: support changing default toot visibility --- bot.py | 22 +++++++++++++++++++--- callback.py | 21 ++++++++++----------- command.py | 32 +++++++++++++++++++++++++++++--- config.py | 2 +- dbstore/peewee_store.py | 34 ++++++++++++++++++++++++++++++---- prompt/string.py | 5 ++--- 6 files changed, 91 insertions(+), 25 deletions(-) diff --git a/bot.py b/bot.py index aea62af..1d59f9e 100644 --- a/bot.py +++ b/bot.py @@ -42,6 +42,7 @@ from command import ( help_command, tos_command, toggle_visibility_command, + callback_toggle_visibility, logout_command, list_command ) @@ -55,7 +56,8 @@ from config import ( ADD_COMMENT, BOT_TOKEN, BOT_SCOPE, - MAIN_MENU + MAIN_MENU, + WAIT_VISIBILITY ) from prompt.string import PROMPT_CHOOSE_ACTION @@ -161,13 +163,27 @@ async def main() -> None: # register handlers application.add_handler(CommandHandler("tos", tos_command)) - application.add_handler(CommandHandler("vis", toggle_visibility_command)) + visibility_conversation_handler = ConversationHandler( + entry_points=[ + CommandHandler("vis", toggle_visibility_command) + ], + states={ + WAIT_VISIBILITY: [ + CallbackQueryHandler(callback_toggle_visibility) + ]}, + fallbacks=[CommandHandler("cancel", cancel_command)], + per_message=False, + allow_reentry=True, + ) + application.add_handler(CommandHandler("logout", logout_command)) application.add_handler(CommandHandler("list", list_command)) application.add_handler(CommandHandler("Help", help_command)) - application.add_handler(checkin_handler) application.add_handler(TypeHandler(type=FediLoginCallbackUpdate, callback=process_oauth_login_callback)) + application.add_handler(visibility_conversation_handler, 2) + application.add_handler(checkin_handler, 1) + # Pass webhook settings to telegram await application.bot.set_webhook(url=f"{BOT_DOMAIN}{TELEGRAM_WEBHOOK_URL}") diff --git a/callback.py b/callback.py index 1abef5e..cb6a8d3 100644 --- a/callback.py +++ b/callback.py @@ -60,7 +60,7 @@ async def process_media_group(context: CallbackContext): with db.connection_context(): u = User.get(User.telegram_user_id == context.user_data["user_id"]) - content_type = "text/markdown" if u.home_instance_type == "pleroma" else "text/plain" + content_type = "text/markdown" if u.home_instance_type == "pleroma" else None for media_dict in context.job.data: if len(media_id) >= 4: @@ -124,11 +124,11 @@ async def callback_location_sharing(update: Update, context: ContextTypes.DEFAUL poi = query_poi_by_fsq_id(context.user_data.get("fsq_id")) content = generate_toot_text(poi["name"], poi["locality"], poi["region"], poi["latitude"], poi["longitude"]) - with db.connection_context(): - u = User.get(User.telegram_user_id == update.effective_user.id) - content_type = "text/markdown" if u.home_instance_type == "pleroma" else "text/plain" + u = get_user_by_id(str(update.effective_user.id)) + content_type = "text/markdown" if u["home_instance_type"] == "pleroma" else None + status = get_mastodon_client(update.effective_user.id).status_post(content, - visibility=TOOT_VISIBILITY_PRIVATE, + visibility=u["tool_visibility"], content_type=content_type, media_ids=[]) @@ -208,12 +208,11 @@ async def _process_location_selection(context: ContextTypes.DEFAULT_TYPE) -> int content = generate_toot_text(poi_name, "", "", context.user_data.get("latitude"), context.user_data.get("longitude")) - with db.connection_context(): - u = User.get(User.telegram_user_id == context.user_data["user_id"]) - content_type = "text/markdown" if u.home_instance_type == "pleroma" else "text/plain" + u = get_user_by_id(context.user_data["user_id"]) + content_type = "text/markdown" if u["home_instance_type"] == "pleroma" else None status = get_mastodon_client(context.user_data["user_id"]).status_post(content, - visibility=TOOT_VISIBILITY_PRIVATE, + visibility=u["toot_visibility"], content_type=content_type, media_ids=[]) @@ -268,7 +267,7 @@ async def callback_add_comment(update: Update, context: ContextTypes.DEFAULT_TYP with db.connection_context(): u = User.get(User.telegram_user_id == context.user_data["user_id"]) - content_type = "text/markdown" if u.home_instance_type == "pleroma" else "text/plain" + content_type = "text/markdown" if u.home_instance_type == "pleroma" else None comment = update.effective_message.text get_mastodon_client(update.effective_user.id).status_update(id=context.user_data.get(KEY_TOOT_STATUS_ID), @@ -329,7 +328,7 @@ async def callback_add_media(update: Update, context: CallbackContext): with db.connection_context(): u = User.get(User.telegram_user_id == context.user_data["user_id"]) - content_type = "text/markdown" if u.home_instance_type == "pleroma" else "text/plain" + content_type = "text/markdown" if u.home_instance_type == "pleroma" else None mastodon_client.status_update(status=status_content, id=status_id, diff --git a/command.py b/command.py index b12483a..f124e2a 100644 --- a/command.py +++ b/command.py @@ -2,7 +2,9 @@ from telegram import Update from telegram.constants import ParseMode from telegram.error import BadRequest from telegram.ext import ContextTypes, ConversationHandler -from dbstore.peewee_store import get_user_access_key, get_user_home_instance, delete_user_by_id +from dbstore.peewee_store import get_user_access_key, get_user_home_instance, delete_user_by_id, update_user_visibility +from dbstore.peewee_store import get_user_by_id +from dbstore.peewee_store import TOOT_VISIBILITY_PRIVATE, TOOT_VISIBILITY_UNLISTED, TOOT_VISIBILITY_PUBLIC from config import * @@ -50,8 +52,32 @@ async def logout_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> await update.message.reply_text(PROMPT_LOGOUT_SUCCESS, parse_mode=ParseMode.HTML, reply_markup=LOGIN_MENU) -async def toggle_visibility_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: - await update.message.reply_text(PROMPT_TOGGLE_VIS, parse_mode=ParseMode.HTML, reply_markup=MAIN_MENU) +async def toggle_visibility_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: + visibility_menu = InlineKeyboardMarkup([ + [InlineKeyboardButton("Private", callback_data=TOOT_VISIBILITY_PRIVATE)], + [InlineKeyboardButton("Unlisted", callback_data=TOOT_VISIBILITY_UNLISTED)], + [InlineKeyboardButton("Public", callback_data=TOOT_VISIBILITY_PUBLIC)] + ]) + + user = get_user_by_id(str(update.effective_user.id)) + await update.message.reply_text(PROMPT_TOGGLE_VIS.format(user["toot_visibility"]), + parse_mode=ParseMode.HTML, + reply_markup=visibility_menu) + return WAIT_VISIBILITY + + +async def callback_toggle_visibility(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: + query = update.callback_query + await query.answer() + + if query.data not in [TOOT_VISIBILITY_PRIVATE, TOOT_VISIBILITY_UNLISTED, TOOT_VISIBILITY_PUBLIC]: + await query.edit_message_text(text="Invalid visibility", + reply_markup=MAIN_MENU) + return ConversationHandler.END + + update_user_visibility(str(update.effective_user.id), query.data) + await query.edit_message_text(text=f"Default visibility changed to {query.data}") + return ConversationHandler.END async def cancel_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: diff --git a/config.py b/config.py index 9b52205..0fae9b1 100644 --- a/config.py +++ b/config.py @@ -12,7 +12,7 @@ ENCRYPT_KEY = config["DEFAULT"]["ENCRYPT_KEY"] MEDIA_GROUP_TIMEOUT = 3 -FEDI_LOGIN, WAIT_LOCATION, LOCATION_SEARCH_KEYWORD, LOCATION_CONFIRMATION, ADD_MEDIA, ADD_COMMENT = range(6) +FEDI_LOGIN, WAIT_VISIBILITY, WAIT_LOCATION, LOCATION_SEARCH_KEYWORD, LOCATION_CONFIRMATION, ADD_MEDIA, ADD_COMMENT = range(7) MAIN_MENU = ReplyKeyboardMarkup([ [KeyboardButton(text="Check-in here", request_location=True)], diff --git a/dbstore/peewee_store.py b/dbstore/peewee_store.py index f10627b..c8d9c22 100644 --- a/dbstore/peewee_store.py +++ b/dbstore/peewee_store.py @@ -25,6 +25,31 @@ class User(BaseModel): toot_visibility = CharField(max_length=128, default=TOOT_VISIBILITY_PRIVATE) +def update_user_visibility(telegram_user_id: str, visibility: str) -> int: + with db.connection_context(): + return User.update(toot_visibility=visibility).where( + User.telegram_user_id == telegram_user_id + ).execute() + + +def get_user_by_id(telegram_user_id: str) -> dict: + with db.connection_context(): + try: + user = User.get(User.telegram_user_id == telegram_user_id) + return { + "telegram_user_id": user.telegram_user_id, + "access_key": user.access_key, + "home_instance": user.home_instance, + "home_instance_type": user.home_instance_type, + "state": user.state, + "client_id": user.client_id, + "client_secret": user.client_secret, + "toot_visibility": user.toot_visibility, + } + except DoesNotExist: + return {} + + def get_user_by_state(state: str) -> dict: with db.connection_context(): try: @@ -33,6 +58,7 @@ def get_user_by_state(state: str) -> dict: "telegram_user_id": user.telegram_user_id, "access_key": user.access_key, "home_instance": user.home_instance, + "home_instance_type": user.home_instance_type, "state": user.state, "client_id": user.client_id, "client_secret": user.client_secret, @@ -78,10 +104,6 @@ class Location(BaseModel): longitude = CharField(max_length=128) -with db.connection_context(): - db.create_tables([User, Location]) - - def get_poi_by_fsq_id(fsq_id) -> dict: with db.connection_context(): try: @@ -107,3 +129,7 @@ def create_or_update_poi(poi: dict) -> int: latitude=poi["latitude"], longitude=poi["longitude"], ).on_conflict_replace().execute() + + +with db.connection_context(): + db.create_tables([User, Location]) diff --git a/prompt/string.py b/prompt/string.py index b7aeff1..2fe13f6 100644 --- a/prompt/string.py +++ b/prompt/string.py @@ -34,8 +34,7 @@ PROMPT_HELP = "Available commands:" \ "You can use this command to login to multiple Fediverse accounts" \ "\n`/list` - list current linked Fediverse accounts" \ "\n`/logout [number]` - logout from specified Fediverse account, default logout from all" \ - "\n`/vis public|private|unlisted [number]` - " \ - "toggle visibility of your checkins on specified instances, default=private" \ + "\n`/vis` - toggle visibility of your checkins on specified instances, default=private" \ "\n`/tos` - show ToS message" \ "\n`/cancel` - cancel current operation during checkins" @@ -43,6 +42,6 @@ PROMPT_LIST = "You are linked with the following Fediverse accounts:" PROMPT_LIST_NO_RESULT = "You are not linked with any Fediverse account yet. \n\n Input /login to login." PROMPT_LOGOUT = "Choose Fediverse account to logout" PROMPT_LOGOUT_SUCCESS = "Successfully logged out from Fediverse account" -PROMPT_TOGGLE_VIS = "Choose visibility of your checkins on Fediverse" +PROMPT_TOGGLE_VIS = "Change default toot visibility of your checkins on Fediverse.\nCurrent: {}" CALLBACK_SKIP = "Skip" -- cgit v1.2.3