From 0cdc35946380d7ccb747e0b66959f06de57ea9e1 Mon Sep 17 00:00:00 2001
From: Remy Moll <me@moll.re>
Date: Tue, 12 Mar 2024 19:14:29 +0100
Subject: [PATCH] add day rating feature

---
 .vscode/launch.json          |  9 -----
 README.md                    |  6 +++-
 bot/commands/journal.py      | 67 ++++++++++++++++++++++++++----------
 bot/commands/memory.py       | 15 ++++----
 bot/cronjob/random_memory.py | 17 ++++-----
 bot/models.py                | 12 +++++--
 6 files changed, 80 insertions(+), 46 deletions(-)

diff --git a/.vscode/launch.json b/.vscode/launch.json
index bbcb7be..8167722 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -4,15 +4,6 @@
     // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
     "version": "0.2.0",
     "configurations": [
-
-        {
-            "name": "Python: Current File",
-            "type": "python",
-            "request": "launch",
-            "program": "${file}",
-            "console": "integratedTerminal",
-            "justMyCode": true
-        },
         {
             "name": "Python: Current project",
             "type": "python",
diff --git a/README.md b/README.md
index fa1518d..b27aabb 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,7 @@
 # journal-bot
 
-Sharing memories, the digital way...
\ No newline at end of file
+Sharing memories, the digital way...
+
+
+## Migration 10.03.24
+ALTER TABLE journalentry ADD COLUMN rating INTEGER;
\ No newline at end of file
diff --git a/bot/commands/journal.py b/bot/commands/journal.py
index 68b79bb..d47b00b 100644
--- a/bot/commands/journal.py
+++ b/bot/commands/journal.py
@@ -5,7 +5,7 @@ from telegram import InlineKeyboardButton, InlineKeyboardMarkup
 from telegram.constants import ParseMode
 import models
 
-ENTRY_OPTIONS, CONTENT_ENTRY = range(2)
+ENTRY_OPTIONS, CONTENT_ENTRY, DAY_RATING = range(3)
 BUTTON_COUNT = 5
 
 
@@ -26,6 +26,9 @@ class JournalHandler(BaseHandler):
                 CONTENT_ENTRY: [
                     MessageHandler(filters.ALL, self.content_save),
                     ],
+                DAY_RATING: [
+                    CallbackQueryHandler(self.day_rating_save),
+                    ],
             },
             fallbacks=[],
         )
@@ -41,21 +44,12 @@ class JournalHandler(BaseHandler):
 
         dates = [(datetime.datetime.now() - datetime.timedelta(days = i)).date() for i in range(BUTTON_COUNT + 2)][::-1]
         # since there are two buttons additional buttons, we need to have two more days
-        names = [d.strftime("%d.%m.") for d in dates]
+        names = get_names(dates)
         callbacks = [d.strftime("%d%m%Y") for d in dates]
-        names[-1] = "Today"
-        names[-2] = "Yesterday"
 
         options = [
-            [
-                InlineKeyboardButton(names[-1], callback_data=callbacks[-1])
-            ],
-            [
-                InlineKeyboardButton(names[-2], callback_data=callbacks[-2])
-            ],
-            [
-                InlineKeyboardButton(n, callback_data=c) for n,c in zip(names[:-2], callbacks[:-2])
-            ],
+                [InlineKeyboardButton(n, callback_data=c)] for n,c in zip(names[::-1], callbacks[::-1])
+        ] + [
             [
                 InlineKeyboardButton("<<", callback_data=BUTTON_COUNT + 2)
             ],
@@ -95,16 +89,16 @@ class JournalHandler(BaseHandler):
         delta = int(query.data)
 
         dates = [(datetime.datetime.now() - datetime.timedelta(days = i + delta)).date() for i in range(BUTTON_COUNT)][::-1]
-        names = [d.strftime("%d.%m.") for d in dates]
+        names = get_names(dates)
         callbacks = [d.strftime("%d%m%Y") for d in dates]
 
         options = [
             [
                 InlineKeyboardButton(">>", callback_data=delta - BUTTON_COUNT)
-            ],
-            [
-                InlineKeyboardButton(n, callback_data=c) for n,c in zip(names, callbacks)
-            ],
+            ]
+        ] + [
+            [InlineKeyboardButton(n, callback_data=c)] for n,c in zip(names[::-1], callbacks[::-1])
+        ] + [
             [
                 InlineKeyboardButton("<<", callback_data=delta + BUTTON_COUNT)
             ],
@@ -173,7 +167,23 @@ class JournalHandler(BaseHandler):
 
             self.current_model.save()
 
-        await update.message.reply_text(f"Saved entry ✅")
+        options = [
+            [InlineKeyboardButton(models.RATING_MAPPING[idx], callback_data=idx) for idx in [1,2,3,4,5]]
+        ]
+
+        await update.message.reply_text(f"Saved entry ✅. How was the day?", reply_markup=InlineKeyboardMarkup(options))
+
+        return DAY_RATING
+
+
+    async def day_rating_save(self, update, context):
+        query = update.callback_query
+        await query.answer()
+        rating = int(query.data)
+        with models.db:
+            self.current_model.rating = rating
+            self.current_model.save()
+        await query.edit_message_text(text="Rating saved ✅")
         return ConversationHandler.END
 
 
@@ -190,3 +200,22 @@ class JournalHandler(BaseHandler):
             self.current_model.delete_instance()
         context.chat_data["delete"] = False
         await update.message.reply_text(text="Entry deleted ✅")
+
+
+
+### HELPERS
+
+def get_names(dates: list):
+    names = []
+    for d in dates:
+        suffix = ""
+        if models.JournalEntry.get_or_none(date = d):
+            suffix = " ✅"
+        
+        if d == datetime.datetime.now().date():
+            names.append("Today" + suffix)
+        elif d == datetime.datetime.now().date() - datetime.timedelta(days = 1):
+            names.append("Yesterday" + suffix)
+        else:
+            names.append(d.strftime("%d.%m.") + suffix)
+    return names
diff --git a/bot/commands/memory.py b/bot/commands/memory.py
index 2bee0b3..5a25664 100644
--- a/bot/commands/memory.py
+++ b/bot/commands/memory.py
@@ -69,21 +69,22 @@ class MemoryHandler(BaseHandler):
         matching_models = context.chat_data["kept_matches"]
         chosen_match = matching_models[ind]
 
+        rating_string = f" ({models.RATING_MAPPING[chosen_match.rating]})" if chosen_match.rating else ""
+
+        message_text = f"On {chosen_match.date_pretty}{rating_string}, " \
+                f"{chosen_match.author} wrote: \n" \
+                f"{chosen_match.spoiler_text}"
+
         if chosen_match.media_path:
             # context.bot.sendPhoto()
             await update.effective_message.reply_photo(
                 photo = chosen_match.media_path,
-                caption=
-                    f"On {chosen_match.date_pretty}, "
-                    f"{chosen_match.author} wrote: \n"
-                    f"{chosen_match.spoiler_text}",
+                caption = message_text,
                 parse_mode=ParseMode.HTML
                 )
         else:
             await query.edit_message_text(
-                f"On {chosen_match.date_pretty}, "
-                f"{chosen_match.author} wrote: \n"
-                f"{chosen_match.spoiler_text}",
+                message_text,
                 parse_mode=ParseMode.HTML
             )
 
diff --git a/bot/cronjob/random_memory.py b/bot/cronjob/random_memory.py
index 43539aa..17589d3 100644
--- a/bot/cronjob/random_memory.py
+++ b/bot/cronjob/random_memory.py
@@ -42,23 +42,24 @@ class RandomMemoryJob():
 
         chat_id = os.getenv("CHAT_ID")
 
+        rating_string = f" ({models.RATING_MAPPING[chosen_entry.rating]})" if chosen_entry.rating else ""
+
+        message_text = f"On {chosen_entry.date_pretty}{rating_string}, " \
+                f"{chosen_entry.author} wrote: \n" \
+                f"{chosen_entry.spoiler_text}"
+
+
         if chosen_entry.media_path:
             await self.bot.send_photo(
                 chat_id = chat_id,
                 photo = chosen_entry.media_path,
-                caption =
-                    f"On {chosen_entry.date_pretty}, "
-                    f"{chosen_entry.author} wrote: \n"
-                    f"{chosen_entry.spoiler_text}",
+                caption = message_text,
                 parse_mode=ParseMode.HTML
                 )
         else:
             await self.bot.send_message(
                 chat_id = chat_id,
-                text =
-                    f"On {chosen_entry.date_pretty}, "
-                    f"{chosen_entry.author} wrote: \n"
-                    f"{chosen_entry.spoiler_text}",
+                text = message_text,
                 parse_mode=ParseMode.HTML
             )
 
diff --git a/bot/models.py b/bot/models.py
index b771058..2cd1313 100644
--- a/bot/models.py
+++ b/bot/models.py
@@ -10,6 +10,14 @@ ID_MAPPINGS = {
 }
 ID_MAPPINGS_REV = dict((v, k) for k, v in ID_MAPPINGS.items())
 
+RATING_MAPPING = {
+    1: "😵",
+    2: "☹️",
+    3: "😐",
+    4: "😃",
+    5: "🥰"
+}
+
 MEDIA_DIR = Path(os.getenv("MEDIA_DIR"))
 MEDIA_DIR.mkdir(parents=True, exist_ok=True)
 
@@ -28,7 +36,7 @@ class JournalEntry(BaseModel):
     text = TextField(null=True)
     media_path = TextField(null=True)
     last_shown = DateField(null=True)
-
+    rating = IntegerField(null=True) # mapped by RATING_MAPPING
     
     @property
     def media(self):
@@ -69,7 +77,7 @@ class JournalEntry(BaseModel):
             "("
             "(((?<=(\.|\!|\?)\s)[A-Z])|(^[A-Z]))" # beginning of a sentence
             "([^\.\!\?])+" # any character being part of a sentence
-            "((\:\))|😇|😈)" # the smiley
+            "((\:\))|😇|😈|[Ss]ex)" # the smiley
             "([^\.\!\?])*" # continuation of sentence
             "(\.|\!|\?|\,|$)" # end of the sentence
             ")"