summaryrefslogtreecommitdiffstats
path: root/girok/commands/task/callbacks.py
blob: 364062a39108e0cb96a91c24d2168705bd0c9350 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import re
from datetime import datetime
from typing import Optional

import typer

from girok.commands.task.utils import decode_date_format, decode_time_format
from girok.constants import REPETITION_TYPE, TASK_PRIORITY


def allow_empty_category_callback(ctx: typer.Context, param: typer.CallbackParam, value: str):
    if value is None:
        return None

    if value == "/":
        return value.rstrip("/")

    if not re.match("^([a-zA-Z0-9]+/)*[a-zA-Z0-9]+/?$", value):
        raise typer.BadParameter("[Invalid category path] Category path must be in 'xx/yy/zz format.'")

    if value.endswith("/"):
        value = value[:-1]

    if value == "none":
        raise typer.BadParameter("Sorry, 'none' is a reserved category name.")
    return value


def not_allow_empty_category_callback(ctx: typer.Context, param: typer.CallbackParam, value: str):
    if value is None:
        return None

    if not re.match("^([a-zA-Z0-9]+/)*[a-zA-Z0-9]+/?$", value):
        raise typer.BadParameter("[Invalid category path] Category path must be in 'xx/yy/zz format.'")

    if value.endswith("/"):
        value = value[:-1]

    if value == "none":
        raise typer.BadParameter("Sorry, 'none' is a reserved category name.")
    return value


def datetime_callback(ctx: typer.Context, param: typer.CallbackParam, value: str):
    if value is None:
        return None
    """
    Check if
    1. xxx
    2. xxx@yyy
    """
    if "@" not in value:
        valid, iso_date_str = decode_date_format(value)
        if not valid:
            raise typer.BadParameter("Invalid date format")
        return iso_date_str, None
    else:
        date_items = value.split("@")
        if len(date_items) != 2:
            raise typer.BadParameter("Invalid date format")
        date_str, time_str = date_items

        # Validate date
        valid, iso_date_str = decode_date_format(date_str)
        if not valid:
            raise typer.BadParameter("Invalid date format")

        # Validate time
        valid, iso_time_str = decode_time_format(time_str)
        if not valid:
            raise typer.BadParameter("Invalid time format")

        return iso_date_str, iso_time_str


def tags_callback(ctx: typer.Context, param: typer.CallbackParam, value: Optional[str]):
    if value is None:
        return None
    is_matched = bool(re.match("^[^,]+(,[^,]+)*$", value))
    if not is_matched:
        raise typer.BadParameter("Invalid tags format. You must specify tags separated by comma such as 'A,B,C'")
    return value


def priority_callback(ctx: typer.Context, param: typer.CallbackParam, value: str):
    if value is None:
        return None

    if value not in TASK_PRIORITY:
        raise typer.BadParameter("Priority must be one of 'low', 'medium', 'high'")

    return TASK_PRIORITY[value]


def date_callback(ctx: typer.Context, param: typer.CallbackParam, value: str):
    if value is None:
        return None

    valid, iso_date_str = decode_date_format(value)
    if not valid:
        raise typer.BadParameter("Invalid date format")
    return iso_date_str


def valid_integer_callback(ctx: typer.Context, param: typer.CallbackParam, value: int):
    if value is None:
        return None

    if value <= 0:
        raise typer.BadParameter("The time window must be a positive integer")

    return value