Skip to content

Commit

Permalink
feat: follow spot via inline button (#122)
Browse files Browse the repository at this point in the history
* feat: follow spot via inline button

* feat: follow spot via inline button

* applying recommendations

* fix: codefactor

* fix: always shows manual reactions

* removed trailing whitespace

* test: give priority to delete anonymous comment instead of follow one

---------

Co-authored-by: Neos <[email protected]>
Co-authored-by: Stefano Borzì <[email protected]>
  • Loading branch information
3 people authored Oct 31, 2023
1 parent df9a904 commit b005aed
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 9 deletions.
7 changes: 7 additions & 0 deletions data/db/meme_db_init.sql
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,10 @@ CREATE TABLE IF NOT EXISTS user_report
message_date TIMESTAMP NOT NULL,
PRIMARY KEY (user_id, target_username, message_date)
);
-----
CREATE TABLE IF NOT EXISTS user_follow
(
user_id BIGINT NOT NULL,
message_id BIGINT NOT NULL,
private_message_id BIGINT NOT NULL
);
4 changes: 4 additions & 0 deletions modules/handlers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
from .spot import spot_conv_handler
from .start import start_cmd
from .stats import stats_callback, stats_cmd
from .follow_spot import follow_spot_callback
from .follow_comment import follow_spot_comment


def add_commands(updater: Updater):
Expand Down Expand Up @@ -90,6 +92,7 @@ def add_handlers(disp: Dispatcher):
# Callback handlers
disp.add_handler(CallbackQueryHandler(meme_callback, pattern=r"^meme_\.*"))
disp.add_handler(CallbackQueryHandler(stats_callback, pattern=r"^stats_\.*"))
disp.add_handler(CallbackQueryHandler(follow_spot_callback, pattern=r"^follow_\.*"))

if Config.meme_get('comments'):
disp.add_handler(
Expand All @@ -100,6 +103,7 @@ def add_handlers(disp: Dispatcher):
anonymous_comment_msg,
run_async=True))

disp.add_handler(MessageHandler(Filters.reply & Filters.chat_type.groups, follow_spot_comment, run_async=True))

def add_jobs(disp: Dispatcher):
"""Adds all the jobs to be scheduled to the dispatcher
Expand Down
34 changes: 34 additions & 0 deletions modules/handlers/follow_comment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"""Detect Comment on a post in the comment group"""
from telegram import Update
from telegram.ext import CallbackContext
from modules.data import Config
from modules.utils import EventInfo
from modules.data.db_manager import DbManager


def follow_spot_comment(update: Update, context: CallbackContext):
"""Handles a new comment on a post in the comment group.
Checks if someone is following the post, and sends them an update in case.
Args:
update: update event
context: context passed by the handler
"""
info = EventInfo.from_message(update, context)

if info.chat_id == Config.meme_get('channel_group_id'):
# Get the spot's message_id
reply_to_message_id = info.message.message_thread_id
# Get a list of users who are following the spot
result = DbManager.select_from(
table_name = "user_follow",
select = "user_id, private_message_id",
where = "message_id = %s",
where_args = (reply_to_message_id, )
)

# Send them an update about the new comment
for user in result:
# Avoid sending if it's made by the same user
if not user['user_id'] == info.message.from_user.id:
info.message.copy(chat_id=user['user_id'], reply_to_message_id=user['private_message_id'])
84 changes: 84 additions & 0 deletions modules/handlers/follow_spot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
"Handles callback when the 'Follow Spot' button is clicked."
import logging
from telegram import Update
from telegram.ext import CallbackContext
from telegram.error import Unauthorized
from telegram import InlineKeyboardButton, InlineKeyboardMarkup
from modules.utils import EventInfo
from modules.data import Config
from modules.data.db_manager import DbManager


logger = logging.getLogger(__name__)

def follow_spot_callback(update: Update, context: CallbackContext) -> int:
"""Handles the follow callback.
Args:
update: update event
context: context passed by the handler
Returns:
next state of the conversation
"""
info = EventInfo.from_callback(update, context)
message_id = info.message.reply_to_message.message_id if Config.meme_get('comments') else info.message_id

# Check if user is already following this spot
result = DbManager.select_from(
table_name = "user_follow",
select = "private_message_id",
where = "user_id = %s and message_id = %s",
where_args = (info.user_id, message_id)
)

if len(result) > 0:
answer_text = "Non stai più seguendo questo spot."
# Forget the stored data
DbManager.delete_from(
table_name="user_follow",
where="user_id = %s and message_id = %s",
where_args=(info.user_id, message_id)
)

info.bot.send_message(
chat_id = info.user_id,
text = answer_text,
reply_to_message_id = result[0]['private_message_id'],
disable_notification = True
)
else:
post_url = f"https://t.me/c/{str(info.chat_id).replace('-100', '')}/{info.message_id}"
answer_text = "Stai seguendo questo spot."
try:
# Forward the spot in user's conversation with the bot, so that
# future comments will be sent in response to this forwarded message.
private_message = info.bot.copy_message(
chat_id = info.user_id,
from_chat_id = info.chat_id,
message_id = message_id,
disable_notification = True,
reply_markup = InlineKeyboardMarkup([
[InlineKeyboardButton("💬 Visualizza thread", url = post_url)]
])
)

# Add an explanation to why the message was forwarded?
info.bot.send_message(
chat_id = info.user_id,
text = answer_text,
reply_to_message_id = private_message.message_id
)
except Unauthorized:
info.answer_callback_query(text=f"Assicurati di aver avviato la chat con {Config.settings_get('bot_tag')}")
return -1

# Remember the user_id and message_id
DbManager.insert_into(
table_name="user_follow",
columns=("user_id", "message_id", "private_message_id"),
values=(info.user_id, message_id, private_message.message_id)
)

info.answer_callback_query(text=answer_text)
return -1
1 change: 1 addition & 0 deletions modules/handlers/stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,4 @@ def close_callback(_: None) -> None:
text and replyMarkup that make up the reply
"""
return None
# endregion
21 changes: 12 additions & 9 deletions modules/utils/keyboard_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,22 +156,25 @@ def get_vote_kb(published_post: Optional[PublishedPost] = None) -> Optional[Inli
new inline keyboard
"""
keyboard = []
for row in ROWS: # for each ROW or the keyboard...
new_row = []
for reaction_id in row: # ... add all the reactions for that row
n_votes = "0" if published_post is None else published_post.get_votes(vote=reaction_id)
new_row.append(InlineKeyboardButton(f"{REACTION[reaction_id]} {n_votes}",
callback_data=f"meme_vote,{reaction_id}"))
keyboard.append(new_row)

# the last button in the last row will be the report button
if Config.meme_get('manual_reactions', default = False):
for row in ROWS: # for each ROW or the keyboard...
new_row = []
for reaction_id in row: # ... add all the reactions for that row
n_votes = "0" if published_post is None else published_post.get_votes(vote=reaction_id)
new_row.append(InlineKeyboardButton(f"{REACTION[reaction_id]} {n_votes}",
callback_data=f"meme_vote,{reaction_id}"))
keyboard.append(new_row)

# the last buttons in the last rows will be the report button and the follow button
report_button = InlineKeyboardButton("🚩 Report", callback_data="meme_report_spot")
follow_button = InlineKeyboardButton("👁 Follow", callback_data="follow_spot")
if Config.meme_get('report'):
if len(keyboard) > 0:
keyboard[-1].append(report_button)
else:
keyboard.append([report_button])

keyboard.append([follow_button])
return InlineKeyboardMarkup(keyboard) if keyboard else None


Expand Down

0 comments on commit b005aed

Please sign in to comment.