Skip to content

Commit

Permalink
Merge pull request #3 from HackerspaceKRK/feature/better-ux
Browse files Browse the repository at this point in the history
Feature/better ux
  • Loading branch information
alufers authored Dec 5, 2023
2 parents 47fbf1b + 95116e2 commit 4fba8f0
Show file tree
Hide file tree
Showing 3 changed files with 211 additions and 70 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM python:3-buster
FROM python:3-bookworm

WORKDIR /app

Expand Down
277 changes: 209 additions & 68 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,73 +2,214 @@
import logging
from pprint import pprint
from functools import wraps
from typing import Optional, Union
from phabricator import Phabricator
from telegram import ParseMode
from telegram.ext import Updater, CommandHandler

from telegram import (
Message,
Update,
ForceReply,
InlineKeyboardMarkup,
InlineKeyboardButton,
)
from telegram.ext import (
Application,
ApplicationBuilder,
Updater,
CommandHandler,
CallbackContext,
CallbackQueryHandler,
MessageHandler,
filters,
)
from telegram.constants import ParseMode

import json
import config


def create_task(title, description):
transactions = [
{'type': 'title', 'value': title},
{'type': 'description', 'value': description},
]

# @TODO support exceptions/errors/blah :P

phab = Phabricator(host=config.PHABRICATOR_URL_API, token=config.PHABRICATOR_TOKEN)
result = phab.maniphest.edit(transactions=transactions)
return result


def handler_add_task(update, context):
if update.message.chat and update.message.chat.title != config.TELEGRAM_CHAT_NAME:
update.message.reply_text('Niedozwolona grupa czatu!')
return

if len(context.args) < 3:
update.message.reply_text('Podaj, proszę, tytuł jako argument')
return

msg_text = update.message.text_markdown.lstrip('/add\\_task').strip() # need to work on this, because context.args doesn't indicate new lines
first_newline = msg_text.find('\n')

title = ''
description = ''

if first_newline == -1:
title = msg_text.capitalize()
else:
title = msg_text[:first_newline].capitalize()
description = msg_text[first_newline + 1:].strip()
description += '\n\n'

description += ' *Dodane przez:* {} '.format(update.message.from_user.name)
description += '\nlink do wiadomości: {} '.format(update.message.link)

result = create_task(title=title, description=description)
task_id = result.object['id']

url = '{}T{}'.format(config.PHABRICATOR_URL, task_id)
reply = '*T{}: {}* ({})'.format(task_id, title, url)

update.message.reply_text(reply, parse_mode=ParseMode.MARKDOWN)


def error_callback(update, context):
pprint(context.error)


if __name__ == '__main__':
logging.basicConfig(level=logging.DEBUG)

telegram_updater = Updater(config.TELEGRAM_TOKEN)
telegram_dispatcher = telegram_updater.dispatcher

telegram_dispatcher.add_handler(CommandHandler('add_task', handler_add_task, pass_args=True))

telegram_dispatcher.add_error_handler(error_callback)

telegram_updater.start_polling()
telegram_updater.idle()
import random
import string
import re


def create_task(title: str, description: str):
transactions = [
{"type": "title", "value": title},
{"type": "description", "value": description},
]

phab = Phabricator(host=config.PHABRICATOR_URL_API, token=config.PHABRICATOR_TOKEN)
result = phab.maniphest.edit(transactions=transactions)
return result


def extract_title_and_description(
update: Union[str, "Update"]
) -> (Optional[str], Optional[str]):
msg_text = re.sub(
r"^\s*\/add_task(@\w+)?\s*", "", update.message.text, flags=re.IGNORECASE
)

first_newline = msg_text.find("\n")

title = ""
description = None

if first_newline == -1:
title = msg_text.capitalize().strip()
else:
title = msg_text[:first_newline].capitalize()
# extract the description from text_markdown separately,
# because Phabricator supports markdown in the description, but not in the title
msg_text_markdown = update.message.text_markdown
first_newline = msg_text_markdown.find("\n")
description = msg_text_markdown[first_newline:].strip()
description += "\n\n"
if not title:
return None, None

return title, description


message_ids_waiting_for_reply: dict[int, Message] = {}


def gen_id() -> str:
return "".join(random.choice(string.ascii_lowercase) for i in range(15))


tasks_awaiting_confirmation: dict[str, dict] = {}


async def handler_add_task(update: Union[str, "Update"], context: CallbackContext):
global message_ids_waiting_for_reply
if update.message.chat and update.message.chat.title != config.TELEGRAM_CHAT_NAME:
await update.message.reply_text("Niedozwolona grupa czatu!")
return

title, description = extract_title_and_description(update)
print([title, description])
if not title:
reply_msg = await update.message.reply_text(
"Proszę podaj tytuł (oraz opcjonalnie opis w nowej linii):",
reply_markup=ForceReply(
selective=True,
input_field_placeholder="Tytuł zadania i opcjonalny opis w nowej linii",
),
)
message_ids_waiting_for_reply[reply_msg.message_id] = reply_msg
return
if not description:
description = ""

description += "*Dodane przez:* {} ".format(update.message.from_user.name)
description += "\nlink do wiadomości: {} ".format(update.message.link)

confirmation_id = gen_id()
tasks_awaiting_confirmation[confirmation_id] = {
"title": title,
"description": description,
}

await update.message.reply_markdown(
"""Podgląd zadania:
*Tytuł:* {}
*Opis:*
{}
Czy chcesz dodać zadanie?""".format(
title, description
),
reply_markup=InlineKeyboardMarkup(
[
[
InlineKeyboardButton(
"✅ Dodaj zadanie",
# callback_data=json.dumps({
# "action": "add_task",
# "title": title,
# "description": description,
# }),
callback_data="ok " + confirmation_id,
),
InlineKeyboardButton(
"❌ Anuluj", callback_data="cancel " + confirmation_id
),
]
]
),
)


async def callback_query_handler(update: Update, context: CallbackContext):
data = update.callback_query.data
op, confirmation_id = data.split(" ", 1)
if op == "ok":
if confirmation_id not in tasks_awaiting_confirmation:
return
task = tasks_awaiting_confirmation.pop(confirmation_id)
result = None
try:
result = create_task(title=task["title"], description=task["description"])
except Exception as e:
await update.callback_query.edit_message_text(
"Wystąpił błąd podczas dodawania zadania: {}".format(e)
)
# print error and traceback
logging.exception("Error while creating task", exc_info=e)
return
task_id = result.object["id"]

url = "{}T{}".format(config.PHABRICATOR_URL, task_id)
reply = "*T{}: {}* ({})".format(task_id, task["title"], url)

await update.callback_query.edit_message_text(
reply, parse_mode=ParseMode.MARKDOWN
)
await update.callback_query.edit_message_reply_markup(
InlineKeyboardMarkup(
[[InlineKeyboardButton("🔗 T{}".format(task_id), url=url)]]
)
)
elif op == "cancel":
if confirmation_id not in tasks_awaiting_confirmation:
return
tasks_awaiting_confirmation.pop(confirmation_id)
await update.callback_query.edit_message_text("Anulowano dodawanie zadania")
else:
await update.callback_query.edit_message_text(
"Nieznana operacja: {}".format(op)
)


async def message_handler(update: Union[str, "Update"], context: CallbackContext):
if (
update.message.reply_to_message
and update.message.reply_to_message.message_id in message_ids_waiting_for_reply
):
# delete the message from the chat
await update.message.reply_to_message.delete()
message_ids_waiting_for_reply.pop(update.message.reply_to_message.message_id)
await handler_add_task(update, context)
return


def error_callback(update, context: CallbackContext):
pprint(context.error)


async def post_init(application: Application) -> None:
await application.bot.set_my_commands(
[("add_task", "Dodaj zadanie do Phabricatora")]
)


if __name__ == "__main__":
# logging.basicConfig(level=logging.DEBUG)

app = ApplicationBuilder().token(config.TELEGRAM_TOKEN).post_init(post_init).build()

app.add_handler(CommandHandler("add_task", handler_add_task))
app.add_handler(MessageHandler(filters.TEXT, message_handler, True))
app.add_handler(CallbackQueryHandler(callback_query_handler))
app.add_error_handler(error_callback)

app.run_polling()
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ decorator==4.4.2
idna==2.10
phabricator==0.8.0
pycparser==2.20
python-telegram-bot==13.0
python-telegram-bot==20.7
pytz==2020.4
requests==2.25.0
six==1.15.0
Expand Down

0 comments on commit 4fba8f0

Please sign in to comment.