Skip to content

Commit

Permalink
Merge pull request #65 from Jonak-Adipta-Kalita/main
Browse files Browse the repository at this point in the history
random shits, important tho!
  • Loading branch information
Jonak-Adipta-Kalita authored Jul 29, 2024
2 parents 3a2789e + 761eb71 commit 45f57a5
Show file tree
Hide file tree
Showing 8 changed files with 180 additions and 56 deletions.
2 changes: 1 addition & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
include README.md
include docs/README.md
include LICENSE
include flomo/beep.mp3
18 changes: 12 additions & 6 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,15 +93,21 @@ flomo s -t work -n "math"

```
flomo --help
Usage: flomo [OPTIONS] COMMAND [ARGS]...
Usage: flomo [OPTIONS] COMMAND [ARGS]...
A Flowmodoro CLI for productivity enthusiasts.
Options:
--help Show this message and exit.
Commands:
start (s) Start a Flowmodoro session.
Options:
--help Show this message and exit.
Commands:
init (i) Initialize the required files for Flomo.
start (s) Start a Flowmodoro session.
tracking (t) Show the tracking history.
delete (d) Delete sessions.
change (ch) Change session data.
config (cf) Print config file path
error (er) Show the error log.
```

#### Pro Tip for Linux Users
Expand Down
105 changes: 89 additions & 16 deletions flomo/cli.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import datetime
import gc
import sys
from typing import Tuple

import click
import click_aliases
Expand All @@ -9,9 +12,6 @@
import flomo.tracker as tracker
import flomo.ui as ui

# TODO: Ability for users to see message.log file.
# TODO: Change Config data from a Command


class OrderCommands(click.Group):
def list_commands(self, ctx: click.Context) -> list[str]:
Expand Down Expand Up @@ -73,9 +73,12 @@ def start(tag: str, name: str):
errors.DBFileNotFoundError,
errors.NoConfigError,
errors.InvalidConfigKeyError,
Exception,
) as e:
# TODO: print(e) isnt printing anything
helpers.error_log(f"{datetime.datetime.now()} - Error: {e}")
print(e)
finally:
sys.exit()


@flomo.command(aliases=["t"])
Expand All @@ -90,26 +93,32 @@ def tracking():
errors.NoSessionsError,
errors.NoSessionError,
) as e:
helpers.message_log(str(e))
helpers.error_log(str(e))
print(e)


# TODO: delete multiple sessions at once
@flomo.command(aliases=["d"])
@click.argument("session_id")
def delete(session_id: str):
@click.argument("session_ids", nargs=-1)
def delete(session_ids: Tuple):
"""
Delete a session.
Delete sessions.
"""
try:
db = tracker.Tracker()
db.delete_session(int(session_id))
if not db.get_sessions():
raise errors.NoSessionsError()
click.confirm("Are you sure you want to delete the session(s)?", abort=True)
db.delete_session(session_ids)
db.conn.close()
if len(session_ids) == 0:
return print("Deleted the last session.")
print(f"Deleted session(s): {', '.join(map(str, session_ids))}")
except (
errors.DBFileNotFoundError,
errors.NoSessionError,
errors.NoSessionsError
) as e:
helpers.message_log(str(e))
helpers.error_log(str(e))
print(e)


Expand All @@ -129,21 +138,85 @@ def change(session_id: str, tag: str | None, name: str | None):
errors.DBFileNotFoundError,
errors.NoSessionError,
) as e:
helpers.message_log(str(e))
helpers.error_log(str(e))
print(e)


@flomo.command(aliases=["cf"])
def config():
@click.option(
"-n", "--notif", help="Set notification priority to 'off', 'normal', or 'high'."
)
@click.option("-tc", "--tag-color", help="Set or delete tag colors. (tag_name, color)")
@click.option("-ds", "--default-session", help="Set default session data. (tag, Name)")
def config(notif: str, tag_color: str, default_session: str):
"""
Print config file path
Change the config values or get the config file path.
"""
try:
print(helpers.get_path("config.json", True))
print(f"File Path: {helpers.get_path("config.json", True)}")
conf_ = conf.Config()

if notif:
notif = notif.lower()
if notif.lower() in ["off", "normal", "high"]:
conf_.set_config(conf.NOTIFICATION_PRIORITY, notif)
print(f"Notification Priority set to {notif}")
else:
raise click.BadOptionUsage("notif", "Invalid input")

if tag_color:
tag_color = tag_color.lower()
tc = tag_color.split(" ")
if len(tc) == 2:
if not tc[1]:
raise click.BadOptionUsage("tag-color", "Invalid input")
conf_.set_config(conf.TAG_COLORS, tag_color, nested_value=True)
print(f"Tag {tc[0]}'s color set to '{tc[1]}'")
elif len(tc) == 1:
tag_colors = conf_.get_config(conf.TAG_COLORS)
if not tc[0] in list(tag_colors.keys()):
raise click.BadOptionUsage("tag-color", "Invalid input")
conf_.delete_tag_color(tc[0])
print(f"Deleted color for tag '{tc[0]}'")
else:
raise click.BadOptionUsage("tag-color", "Invalid input")

if default_session:
ds = default_session.split(" ")
ds[0] = ds[0].lower()
if len(ds) == 2 and ds[0] and ds[1]:
conf_.set_config(
conf.DEFAULT_SESSION_DATA, " ".join(ds), nested_value=True
)
print(f"Default Session Data set to Tag: {ds[0]} and Name: {ds[1]}")
else:
raise click.BadOptionUsage("default-session", "Invalid input")
except errors.NoConfigError as e:
helpers.message_log(str(e))
helpers.error_log(str(e))
print(e)


@flomo.command(aliases=["er"])
@click.option("-c", "--clear", is_flag=True, help="Clear the error log.")
def error(clear: bool):
"""
Show the error log.
"""
try:
path = helpers.get_path("error.log", True)
print(f"File Path: {path}")
if clear:
with open(path, "w") as f:
f.write("")
return print("Message log cleared.")

with open(path, "r") as f:
if not f.read():
return print("No errors found till now.")
print(f.read())
except FileNotFoundError:
print("No errors found till now.")


if __name__ == "__main__":
flomo()
66 changes: 49 additions & 17 deletions flomo/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,16 @@
import flomo.helpers as helpers

default_session_data = {
"tag": "Work",
"tag": "work",
"name": "Working",
}

tag_colors = {"Work": "red", "Study": "blue", "Exercise": "green"}
tag_colors = {"work": "red", "study": "blue", "exercise": "green"}


DEFAULT_SESSION_DATA = "default_session_data"
NOTIFICATION_PRIORITY = "notification_priority"
TAG_COLORS = "tag_colors"


class Config:
Expand All @@ -28,25 +33,25 @@ def _config_file_exists(self):

def _get_missing_keys(self):
if not os.path.exists(self.path):
return ["default_session_data", "notification_priority", "tag_colors"]
return [DEFAULT_SESSION_DATA, NOTIFICATION_PRIORITY, TAG_COLORS]

with open(self.path, "r") as f:
data = json.load(f)
missing_keys = []

if (
"default_session_data" not in data
or data["default_session_data"].keys() != default_session_data.keys()
DEFAULT_SESSION_DATA not in data
or data[DEFAULT_SESSION_DATA].keys() != default_session_data.keys()
):
missing_keys.append("default_session_data")
missing_keys.append(DEFAULT_SESSION_DATA)

if "notification_priority" not in data or data[
"notification_priority"
if NOTIFICATION_PRIORITY not in data or data[
NOTIFICATION_PRIORITY
].lower() not in ["off", "normal", "high"]:
missing_keys.append("notification_priority")
missing_keys.append(NOTIFICATION_PRIORITY)

if "tag_colors" not in data:
missing_keys.append("tag_colors")
if TAG_COLORS not in data:
missing_keys.append(TAG_COLORS)

return missing_keys

Expand All @@ -62,18 +67,19 @@ def create_config(self):
with open(self.path, "r+") as f:
data = json.load(f)
for missing_key in missing_keys:
if missing_key == "default_session_data":
if missing_key == DEFAULT_SESSION_DATA:
data[missing_key] = default_session_data
if missing_key == "notification_priority":
if missing_key == NOTIFICATION_PRIORITY:
data[missing_key] = "normal"
if missing_key == "tag_colors":
if missing_key == TAG_COLORS:
data[missing_key] = tag_colors

f.seek(0)
f.truncate(0)
json.dump(data, f, indent=4)

def get_config(self, key: str):
if key == "default_session_data" and not self._config_file_exists()[0]:
if key == DEFAULT_SESSION_DATA and not self._config_file_exists()[0]:
return default_session_data

try:
Expand All @@ -83,10 +89,36 @@ def get_config(self, key: str):
except KeyError:
raise errors.InvalidConfigKeyError(key)

def set_config(self, key: str, value: str, nested_value: bool = False):
with open(self.path, "r+") as f:
data = json.load(f)
if nested_value:
if key == DEFAULT_SESSION_DATA:
tag, name = value.split(" ")
data[key]["tag"] = tag
data[key]["name"] = name
elif key == TAG_COLORS:
key_, value_ = value.split(" ")
data[key][key_] = value_
else:
data[key] = value
f.seek(0)
f.truncate(0)
json.dump(data, f, indent=4)

def delete_tag_color(self, tag_name: str):
with open(self.path, "r+") as f:
data = json.load(f)
key = [k for k, v in data[TAG_COLORS].items() if k.lower() == tag_name][0]
del data[TAG_COLORS][key]
f.seek(0)
f.truncate(0)
json.dump(data, f, indent=4)


def get_default_session_data():
try:
conf = Config(get_default_session_data=True).get_config("default_session_data")
conf = Config(get_default_session_data=True).get_config(DEFAULT_SESSION_DATA)
return conf["tag"], conf["name"]
except errors.InvalidConfigKeyError:
except (errors.InvalidConfigKeyError, KeyError):
return default_session_data["tag"], default_session_data["name"]
8 changes: 4 additions & 4 deletions flomo/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def play_sound():
path = get_path("beep.mp3")
conf = config.Config()

notification_priority = str(conf.get_config("notification_priority"))
notification_priority = str(conf.get_config(config.NOTIFICATION_PRIORITY))

if notification_priority.lower() == "off":
return
Expand All @@ -60,11 +60,11 @@ def play_sound():
pass # Error is already getting logged from ui.py


def message_log(message: str):
path = get_path("message.log", in_data=True)
def error_log(error: str):
path = get_path("error.log", in_data=True)

with open(path, "a") as f:
f.write(message + "\n")
f.write(error + "\n")


def format_time(seconds: int) -> str:
Expand Down
24 changes: 20 additions & 4 deletions flomo/tracker.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import datetime
import sqlite3
from typing import Tuple

import pandas
import tabulate
Expand Down Expand Up @@ -29,6 +30,7 @@ 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)
self.cursor.execute(
"INSERT INTO sessions (id, date_time, tag, name) VALUES (?, ?, ?, ?)",
Expand Down Expand Up @@ -59,10 +61,24 @@ def get_session(self, session_id: int):
self.cursor.execute("SELECT * FROM sessions WHERE id = ?", (session_id,))
return self.cursor.fetchone()

def delete_session(self, session_id: int):
if not self.get_session(session_id):
raise errors.NoSessionError(session_id)
self.cursor.execute("DELETE FROM sessions WHERE id = ?", (session_id,))
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)"
)
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)

self.cursor.execute(
"DELETE FROM sessions WHERE id IN ({seq})".format(
seq=",".join(["?"] * len(session_ids))
),
session_ids,
)
self.conn.commit()

def update_session(self, session_id: int, tag: str | None, name: str | None):
Expand Down
Loading

0 comments on commit 45f57a5

Please sign in to comment.