From 00311227a8088d567a95eee2c8773e131e752517 Mon Sep 17 00:00:00 2001 From: Jonak-Adipta-Kalita Date: Tue, 30 Jul 2024 08:50:39 +0530 Subject: [PATCH 1/8] using C to generate ID, encrypting the posix timestamp into shorter alpha numeric string!! --- flomo/cli.py | 2 +- flomo/errors.py | 2 +- flomo/session_id.c | 41 +++++++++++++++++++++++++++++++++++++++++ flomo/tracker.py | 25 +++++++++++++++++-------- flomo/ui.py | 2 +- 5 files changed, 61 insertions(+), 11 deletions(-) create mode 100644 flomo/session_id.c diff --git a/flomo/cli.py b/flomo/cli.py index b02c729..9b576f3 100644 --- a/flomo/cli.py +++ b/flomo/cli.py @@ -132,7 +132,7 @@ def change(session_id: str, tag: str | None, name: str | None): """ try: db = tracker.Tracker() - db.update_session(int(session_id), tag, name) + db.update_session(session_id, tag, name) db.conn.close() except ( errors.DBFileNotFoundError, diff --git a/flomo/errors.py b/flomo/errors.py index 0884a48..fb3e6d7 100644 --- a/flomo/errors.py +++ b/flomo/errors.py @@ -19,5 +19,5 @@ def __init__(self): class NoSessionError(Exception): - def __init__(self, session_id: int): + def __init__(self, session_id: str): super().__init__(f"No session with ID {session_id} was found.") diff --git a/flomo/session_id.c b/flomo/session_id.c new file mode 100644 index 0000000..3874154 --- /dev/null +++ b/flomo/session_id.c @@ -0,0 +1,41 @@ +#include +#include +#include + +const char ALPHANUMERIC[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; +const int BASE = 62; + +char* encode_timestamp(unsigned long timestamp) { + char *encoded = (char*)malloc(12); + int index = 0; + + do { + int rem = timestamp % BASE; + encoded[index++] = ALPHANUMERIC[rem]; + timestamp /= BASE; + } while (timestamp > 0); + + for (int i = 0; i < index/2; i++) { + char temp = encoded[i]; + encoded[i] = encoded[index - i - 1]; + encoded[index - i - 1] = temp; + } + + encoded[index] = '\0'; + return encoded; +} + +unsigned long decode_timestamp(const char* encoded) { + unsigned long timestamp = 0; + size_t length = strlen(encoded); + + for (size_t i = 0; i < length; i++) { + char *ptr = strchr(ALPHANUMERIC, encoded[i]); + if (ptr) { + int index = ptr - ALPHANUMERIC; + timestamp = timestamp * BASE + index; + } + } + + return timestamp; +} diff --git a/flomo/tracker.py b/flomo/tracker.py index e0cc268..9c96e10 100644 --- a/flomo/tracker.py +++ b/flomo/tracker.py @@ -1,5 +1,6 @@ import datetime import sqlite3 +import ctypes from typing import Tuple import pandas @@ -29,9 +30,18 @@ def create_table(self): ) self.conn.commit() - def create_session(self, tag: str, name: str, start_time: datetime.datetime) -> int: - # TODO: Better way of generating session_id - session_id = int(start_time.timestamp() % 1000000) + def create_session(self, tag: str, name: str, start_time: datetime.datetime) -> str: + lib = ctypes.CDLL(helpers.get_path("session_id.so")) + + lib.encode_timestamp.argtypes = [ctypes.c_ulong] + lib.encode_timestamp.restype = ctypes.c_char_p + lib.decode_timestamp.argtypes = [ctypes.c_char_p] + lib.decode_timestamp.restype = ctypes.c_ulong + + _session_id: bytes = lib.encode_timestamp( + ctypes.c_ulong(int(start_time.timestamp())) + ) + session_id = _session_id.decode("utf-8") self.cursor.execute( "INSERT INTO sessions (id, date_time, tag, name) VALUES (?, ?, ?, ?)", (session_id, start_time.strftime("%Y-%m-%d %H:%M:%S"), tag, name), @@ -39,7 +49,7 @@ def create_session(self, tag: str, name: str, start_time: datetime.datetime) -> self.conn.commit() return session_id - def end_session(self, session_id: int, end_time: datetime.datetime): + def end_session(self, session_id: str, end_time: datetime.datetime): date_time = self.get_session(session_id)[1] total_time = end_time - datetime.datetime.strptime( date_time, "%Y-%m-%d %H:%M:%S" @@ -57,7 +67,7 @@ def get_sessions(self): self.cursor.execute("SELECT * FROM sessions") return self.cursor.fetchall() - def get_session(self, session_id: int): + def get_session(self, session_id: str): self.cursor.execute("SELECT * FROM sessions WHERE id = ?", (session_id,)) return self.cursor.fetchone() @@ -69,7 +79,6 @@ def delete_session(self, session_ids: Tuple[str] | Tuple): self.conn.commit() for session_id in session_ids: - session_id = int(session_id) if not self.get_session(session_id): raise errors.NoSessionError(session_id) @@ -81,7 +90,7 @@ def delete_session(self, session_ids: Tuple[str] | Tuple): ) self.conn.commit() - def update_session(self, session_id: int, tag: str | None, name: str | None): + def update_session(self, session_id: str, tag: str | None, name: str | None): if not self.get_session(session_id): raise errors.NoSessionError(session_id) @@ -98,7 +107,7 @@ def update_session(self, session_id: int, tag: str | None, name: str | None): self.conn.commit() -def end_session(session_id: int): +def end_session(session_id: str): db = Tracker() db.end_session(session_id, datetime.datetime.now()) db.conn.close() diff --git a/flomo/ui.py b/flomo/ui.py index 02f8dba..0b0a54d 100644 --- a/flomo/ui.py +++ b/flomo/ui.py @@ -79,7 +79,7 @@ def get_input(self): return self.terminal.inkey().lower() -def main(tag: str, name: str, session_id: int): +def main(tag: str, name: str, session_id: str): # TODO: Do something with the Terminal close issue try: while True: From 6e6992a30b59d0fe2098540baea7a00f3713535b Mon Sep 17 00:00:00 2001 From: Jonak-Adipta-Kalita Date: Tue, 30 Jul 2024 08:51:46 +0530 Subject: [PATCH 2/8] formatted the c code --- flomo/session_id.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/flomo/session_id.c b/flomo/session_id.c index 3874154..2f2b826 100644 --- a/flomo/session_id.c +++ b/flomo/session_id.c @@ -5,17 +5,20 @@ const char ALPHANUMERIC[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; const int BASE = 62; -char* encode_timestamp(unsigned long timestamp) { - char *encoded = (char*)malloc(12); +char *encode_timestamp(unsigned long timestamp) +{ + char *encoded = (char *)malloc(12); int index = 0; - do { + do + { int rem = timestamp % BASE; encoded[index++] = ALPHANUMERIC[rem]; timestamp /= BASE; } while (timestamp > 0); - for (int i = 0; i < index/2; i++) { + for (int i = 0; i < index / 2; i++) + { char temp = encoded[i]; encoded[i] = encoded[index - i - 1]; encoded[index - i - 1] = temp; @@ -25,13 +28,16 @@ char* encode_timestamp(unsigned long timestamp) { return encoded; } -unsigned long decode_timestamp(const char* encoded) { +unsigned long decode_timestamp(const char *encoded) +{ unsigned long timestamp = 0; size_t length = strlen(encoded); - for (size_t i = 0; i < length; i++) { + for (size_t i = 0; i < length; i++) + { char *ptr = strchr(ALPHANUMERIC, encoded[i]); - if (ptr) { + if (ptr) + { int index = ptr - ALPHANUMERIC; timestamp = timestamp * BASE + index; } From db4aa2663d1ed97b08f3ea855e42363608ebeb2a Mon Sep 17 00:00:00 2001 From: Jonak-Adipta-Kalita Date: Tue, 30 Jul 2024 09:10:20 +0530 Subject: [PATCH 3/8] better memory management! --- flomo/session_id.c | 18 ++++++++++++++---- flomo/tracker.py | 13 +++++++------ 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/flomo/session_id.c b/flomo/session_id.c index 2f2b826..1f6ed06 100644 --- a/flomo/session_id.c +++ b/flomo/session_id.c @@ -5,11 +5,16 @@ const char ALPHANUMERIC[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; const int BASE = 62; -char *encode_timestamp(unsigned long timestamp) +char *encode_timestamp(unsigned long long timestamp) { - char *encoded = (char *)malloc(12); + char *encoded = (char *)malloc((sizeof(timestamp) * CHAR_BIT + 5) / 6 + 1); int index = 0; + if (timestamp == 0) + { + encoded[index++] = ALPHANUMERIC[0]; + } + do { int rem = timestamp % BASE; @@ -28,9 +33,9 @@ char *encode_timestamp(unsigned long timestamp) return encoded; } -unsigned long decode_timestamp(const char *encoded) +unsigned long long decode_timestamp(const char *encoded) { - unsigned long timestamp = 0; + unsigned long long timestamp = 0; size_t length = strlen(encoded); for (size_t i = 0; i < length; i++) @@ -41,6 +46,11 @@ unsigned long decode_timestamp(const char *encoded) int index = ptr - ALPHANUMERIC; timestamp = timestamp * BASE + index; } + else + { + fprintf(stderr, "Error: Invalid character '%c' in encoded string.\n", encoded[i]); + return 0; + } } return timestamp; diff --git a/flomo/tracker.py b/flomo/tracker.py index 9c96e10..4c9cbb0 100644 --- a/flomo/tracker.py +++ b/flomo/tracker.py @@ -33,13 +33,13 @@ def create_table(self): def create_session(self, tag: str, name: str, start_time: datetime.datetime) -> str: lib = ctypes.CDLL(helpers.get_path("session_id.so")) - lib.encode_timestamp.argtypes = [ctypes.c_ulong] + lib.encode_timestamp.argtypes = [ctypes.c_ulonglong] lib.encode_timestamp.restype = ctypes.c_char_p lib.decode_timestamp.argtypes = [ctypes.c_char_p] - lib.decode_timestamp.restype = ctypes.c_ulong + lib.decode_timestamp.restype = ctypes.c_ulonglong _session_id: bytes = lib.encode_timestamp( - ctypes.c_ulong(int(start_time.timestamp())) + ctypes.c_ulonglong(int(start_time.timestamp())) ) session_id = _session_id.decode("utf-8") self.cursor.execute( @@ -73,9 +73,10 @@ def get_session(self, session_id: str): def delete_session(self, session_ids: Tuple[str] | Tuple): if len(session_ids) == 0: - self.cursor.execute( - "DELETE FROM sessions WHERE id = (SELECT MAX(id) FROM sessions)" - ) + # TODO: Fix the delete command as IDs are now alphanumeric + # self.cursor.execute( + # "DELETE FROM sessions WHERE id = (SELECT MAX(id) FROM sessions)" + # ) self.conn.commit() for session_id in session_ids: From 86efec5e96c28c13d01a3a0865625b82d56d5d16 Mon Sep 17 00:00:00 2001 From: Jonak-Adipta-Kalita Date: Tue, 30 Jul 2024 09:18:48 +0530 Subject: [PATCH 4/8] using the highest date_time value to delete the session! --- flomo/cli.py | 1 - flomo/tracker.py | 9 +++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/flomo/cli.py b/flomo/cli.py index 9b576f3..0db64c8 100644 --- a/flomo/cli.py +++ b/flomo/cli.py @@ -12,7 +12,6 @@ import flomo.tracker as tracker import flomo.ui as ui - class OrderCommands(click.Group): def list_commands(self, ctx: click.Context) -> list[str]: return list(self.commands) diff --git a/flomo/tracker.py b/flomo/tracker.py index 4c9cbb0..a1ef68c 100644 --- a/flomo/tracker.py +++ b/flomo/tracker.py @@ -9,6 +9,8 @@ import flomo.errors as errors import flomo.helpers as helpers +# Setup Dev & Prod Database Environments! + class Tracker: def __init__(self, initializing: bool = False): @@ -73,10 +75,9 @@ def get_session(self, session_id: str): def delete_session(self, session_ids: Tuple[str] | Tuple): if len(session_ids) == 0: - # TODO: Fix the delete command as IDs are now alphanumeric - # self.cursor.execute( - # "DELETE FROM sessions WHERE id = (SELECT MAX(id) FROM sessions)" - # ) + self.cursor.execute( + "DELETE FROM sessions WHERE date_time = (SELECT MAX(date_time) FROM sessions)" + ) self.conn.commit() for session_id in session_ids: From 4113ce603525b083dace58f690b9f9c5625b8599 Mon Sep 17 00:00:00 2001 From: Jonak-Adipta-Kalita Date: Tue, 30 Jul 2024 10:34:22 +0530 Subject: [PATCH 5/8] this an essential thingie --- flomo/tracker.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flomo/tracker.py b/flomo/tracker.py index a1ef68c..68c163e 100644 --- a/flomo/tracker.py +++ b/flomo/tracker.py @@ -9,7 +9,7 @@ import flomo.errors as errors import flomo.helpers as helpers -# Setup Dev & Prod Database Environments! +# TODO: Setup Dev & Prod Database Environments! class Tracker: From 28ae908bbdb4f89a3fb360ffdfc519ac857c439a Mon Sep 17 00:00:00 2001 From: Jonak-Adipta-Kalita Date: Tue, 30 Jul 2024 11:12:52 +0530 Subject: [PATCH 6/8] formatting --- flomo/cli.py | 3 ++- flomo/tracker.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/flomo/cli.py b/flomo/cli.py index 0db64c8..632d75f 100644 --- a/flomo/cli.py +++ b/flomo/cli.py @@ -12,6 +12,7 @@ import flomo.tracker as tracker import flomo.ui as ui + class OrderCommands(click.Group): def list_commands(self, ctx: click.Context) -> list[str]: return list(self.commands) @@ -115,7 +116,7 @@ def delete(session_ids: Tuple): except ( errors.DBFileNotFoundError, errors.NoSessionError, - errors.NoSessionsError + errors.NoSessionsError, ) as e: helpers.error_log(str(e)) print(e) diff --git a/flomo/tracker.py b/flomo/tracker.py index 68c163e..dc11585 100644 --- a/flomo/tracker.py +++ b/flomo/tracker.py @@ -1,6 +1,6 @@ +import ctypes import datetime import sqlite3 -import ctypes from typing import Tuple import pandas From 743cf775d1c5e3b54422997aa8610f7e5c513c3d Mon Sep 17 00:00:00 2001 From: Jonak-Adipta-Kalita Date: Tue, 30 Jul 2024 11:20:06 +0530 Subject: [PATCH 7/8] gotta build the c file to publish it! --- .github/workflows/publish.yml | 4 ++++ MANIFEST.in | 1 + 2 files changed, 5 insertions(+) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index a043e9d..0e9c7e6 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -13,13 +13,17 @@ jobs: uses: actions/setup-python@v2 with: python-version: "3.12.3" + - name: Install GCC + uses: egor-tensin/setup-gcc@v1.3 - name: Install dependencies run: | python -m pip install --upgrade pip pip install setuptools wheel twine + - name: Build and Publish env: TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }} run: | + gcc -fPIC -shared -o flomo\session_id.so flomo\session_id.c python setup.py sdist bdist_wheel twine upload dist/* diff --git a/MANIFEST.in b/MANIFEST.in index 945326a..8346f54 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,3 +1,4 @@ include docs/README.md include LICENSE include flomo/beep.mp3 +include flomo/session_id.so From 82c207bc3a18e3708ba7744b2cc9eeb188352e80 Mon Sep 17 00:00:00 2001 From: Jonak-Adipta-Kalita Date: Tue, 30 Jul 2024 17:28:03 +0530 Subject: [PATCH 8/8] random shits --- flomo/cli.py | 14 ++++++++++---- flomo/session_id.c | 1 + 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/flomo/cli.py b/flomo/cli.py index 632d75f..a81a4a6 100644 --- a/flomo/cli.py +++ b/flomo/cli.py @@ -1,5 +1,4 @@ import datetime -import gc import sys from typing import Tuple @@ -107,12 +106,19 @@ def delete(session_ids: Tuple): db = tracker.Tracker() if not db.get_sessions(): raise errors.NoSessionsError() - click.confirm("Are you sure you want to delete the session(s)?", abort=True) + session_1 = len(session_ids) == 1 + session_0 = len(session_ids) == 0 + click.confirm( + f"Are you sure you want to delete the {f'session{'' if session_1 else 's'}: {", ".join(session_ids)}' if not session_0 else 'last session'}?", + abort=True, + ) db.delete_session(session_ids) db.conn.close() - if len(session_ids) == 0: + if session_0: return print("Deleted the last session.") - print(f"Deleted session(s): {', '.join(map(str, session_ids))}") + print( + f"Deleted session{'' if session_1 else 's'}: {', '.join(map(str, session_ids))}" + ) except ( errors.DBFileNotFoundError, errors.NoSessionError, diff --git a/flomo/session_id.c b/flomo/session_id.c index 1f6ed06..04d02da 100644 --- a/flomo/session_id.c +++ b/flomo/session_id.c @@ -1,6 +1,7 @@ #include #include #include +#include const char ALPHANUMERIC[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; const int BASE = 62;