From 7c4ec48f4c45114665aa29aba69d4f97dcaa4fea Mon Sep 17 00:00:00 2001 From: missytake Date: Sun, 10 Dec 2023 11:58:42 +0100 Subject: [PATCH] allow storing files via attachments --- src/remember_remember_bot/commands.py | 32 ++++++++++++++++++++++++++- src/remember_remember_bot/loop.py | 7 +++++- src/remember_remember_bot/util.py | 13 +++++++++-- tests/conftest.py | 32 +++++++++++++++++++++++++++ tests/test_commands.py | 19 ++++++++++++++++ 5 files changed, 99 insertions(+), 4 deletions(-) create mode 100644 tests/test_commands.py diff --git a/src/remember_remember_bot/commands.py b/src/remember_remember_bot/commands.py index c80b098..ba1651c 100644 --- a/src/remember_remember_bot/commands.py +++ b/src/remember_remember_bot/commands.py @@ -1,3 +1,5 @@ +import os + import deltachat from remember_remember_bot.util import ( chat_is_active, @@ -8,12 +10,23 @@ from remember_remember_bot.util import ( def setup(email: str, password: str, db: str, debug: bool) -> deltachat.Account: + """Set up the Delta Chat account of the bot. + + :param email: the email account for the bot, e.g. bot@example.org + :param password: the password for the email account + :param db: the path to the database + :param debug: whether to show low-level deltachat FFI events + :return: a configured and running Delta Chat account object + """ + ac = deltachat.account.Account(db_path=db) + ac.set_config("delete_server_after", "2") ac.run_account(email, password, show_ffi=debug) return ac def remind_chat(chat: deltachat.Chat): + """Remind a chat from the last sent file, with all lines which fit today's date.""" messages = [msg.text for msg in chat.get_messages()] if chat_is_active(messages): file_path = get_file_path(messages) @@ -35,9 +48,26 @@ def activate_chat(msg: deltachat.Message): ) msg.mark_seen() return + if msg.chat.get_ephemeral_timer(): + msg.chat.set_ephemeral_timer(0) reply(msg.chat, f"I will send you daily reminders from the file {file_path}.") msg.chat.set_ephemeral_timer(60 * 60 * 24) - remind_chat(msg.get_sender_contact()) + remind_chat(msg.get_sender_contact().create_chat()) + + +def store_file(msg: deltachat.Message): + """Store a received file and reply without timer to the chat where it was stored""" + timer = msg.chat.get_ephemeral_timer() + if timer: + msg.chat.set_ephemeral_timer(0) + new_filename = "./files/" + str(msg.chat.id) + "/" + msg.filename.split("/")[-1] + with open(msg.filename, "r") as read_file: + os.makedirs(os.path.dirname(new_filename), exist_ok=True) + with open(new_filename, "w+") as write_file: + write_file.write(read_file.read()) + reply(msg.chat, f"Thanks, I stored the file at {new_filename}", quote=msg) + if timer: + msg.chat.set_ephemeral_timer(timer) def reply( diff --git a/src/remember_remember_bot/loop.py b/src/remember_remember_bot/loop.py index 150c1f8..8d6d290 100644 --- a/src/remember_remember_bot/loop.py +++ b/src/remember_remember_bot/loop.py @@ -2,7 +2,7 @@ import time import deltachat -from remember_remember_bot.commands import remind_chat, activate_chat, reply +from remember_remember_bot.commands import remind_chat, activate_chat, reply, store_file from remember_remember_bot.util import check_new_day, update_day @@ -25,4 +25,9 @@ def handle_incoming_message(msg: deltachat.Message): elif "/stop" in msg.text: msg.chat.set_ephemeral_timer(0) reply(msg.chat, "I will stop sending you messages now.", quote=msg) + elif "/file" in msg.text: + if msg.filename: + store_file(msg) + else: + activate_chat(msg) msg.mark_seen() diff --git a/src/remember_remember_bot/util.py b/src/remember_remember_bot/util.py index 6e4bdda..dd7700e 100644 --- a/src/remember_remember_bot/util.py +++ b/src/remember_remember_bot/util.py @@ -39,10 +39,19 @@ def get_file_path(messages: [str]) -> str: :param messages: the text of all messages with the user :return: the file path with their reminders """ + # :TODO SECURITY ISSUE - right now, this allows anyone to read any arbitrary file on the bot's machine. + # at least the parts which are formatted as expected, tbh. + file_path = None for message_text in messages: - if "file" in message_text: - file_path = message_text.split("file ", 1)[1] + if "Thanks, I stored the file at" in message_text: + file_path = message_text.split("file at ", 1)[1] + if message_text.startswith("/file"): + try: + file_path = message_text.split("file ", 1)[1] + except IndexError as e: + print("Can't split the message:", message_text) + print(e) if not get_lines_from_file(file_path) == [f"File not found: {file_path}"]: return file_path diff --git a/tests/conftest.py b/tests/conftest.py index 39b2b59..0a597d7 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,4 +1,8 @@ +import os + +import deltachat import pytest +import requests @pytest.fixture @@ -8,3 +12,31 @@ def tmp_file_path(request, tmpdir): with open(path, "w+", encoding="utf-8") as f: f.write("test") return path + + +@pytest.fixture +def chat(tmpdir): + token = os.getenv("DCC_NEW_TMP_EMAIL", "https://nine.testrun.org/cgi-bin/newemail.py") + + # create bot account from token + result = requests.post(token) + addr = result.json()['email'] + password = result.json()['password'] + bot = deltachat.Account(str(tmpdir) + "/db.sqlite") + bot.run_account(addr=addr, password=password, show_ffi=True) + # :TODO how to start the loop? In a subthread? + + # create chat partner from token + result = requests.post(token) + addr = result.json()['email'] + password = result.json()['password'] + user = deltachat.Account(str(tmpdir) + "/db.sqlite") + user.run_account(addr=addr, password=password, show_ffi=False) + + # initiate a chat between them + yield user.create_chat(bot.get_config('addr')) + # return the chat object + bot.shutdown() + user.shutdown() + bot.wait_shutdown() + user.wait_shutdown() diff --git a/tests/test_commands.py b/tests/test_commands.py new file mode 100644 index 0000000..d1a3fa2 --- /dev/null +++ b/tests/test_commands.py @@ -0,0 +1,19 @@ +import time + +import deltachat + +from remember_remember_bot.commands import store_file, reply +from remember_remember_bot.util import get_file_path, get_lines_from_file + + +def test_store_file(tmp_path, chat: deltachat.Chat): + chat.set_ephemeral_timer(1) + reply(chat, "/file", attachment=str(tmp_path)) + last_message = chat.get_messages()[-1] + store_file(last_message) + time.sleep(1) + messages = chat.get_messages() + new_file_path = get_file_path([msg.text for msg in messages]) + assert new_file_path + assert get_lines_from_file(new_file_path) == ["test"] + assert chat.get_ephemeral_timer() == 1