4
4
from datetime import timedelta , datetime , timezone
5
5
from pprint import pprint
6
6
7
+ import click
8
+
7
9
import aw_client
8
10
from aw_core import Event
9
11
12
+ now = datetime .now (timezone .utc )
13
+ td1day = timedelta (days = 1 )
14
+ td1yr = timedelta (days = 365 )
15
+
10
16
11
17
def _valid_date (s ):
12
18
# https://stackoverflow.com/questions/25470844/specify-format-for-input-arguments-argparse-python
@@ -17,110 +23,104 @@ def _valid_date(s):
17
23
raise argparse .ArgumentTypeError (msg )
18
24
19
25
20
- def main ():
21
- now = datetime .now (timezone .utc )
22
- td1day = timedelta (days = 1 )
23
- td1yr = timedelta (days = 365 )
24
-
25
- parser = argparse .ArgumentParser (
26
- prog = "aw-cli" , description = "A CLI utility for interacting with ActivityWatch."
27
- )
28
- parser .set_defaults (which = "none" )
29
- parser .add_argument (
30
- "--host" ,
31
- default = "127.0.0.1:5600" ,
32
- help = "Host to use, in the format HOSTNAME[:PORT]" ,
33
- )
34
- parser .add_argument (
35
- "--testing" , action = "store_true" , help = "Set to use testing ports by default"
36
- )
37
-
38
- subparsers = parser .add_subparsers (help = "sub-command help" )
39
-
40
- parser_heartbeat = subparsers .add_parser (
41
- "heartbeat" , help = "Send a heartbeat to the server"
42
- )
43
- parser_heartbeat .set_defaults (which = "heartbeat" )
44
- parser_heartbeat .add_argument ("--pulsetime" , default = 60 , help = "Pulsetime to use" )
45
- parser_heartbeat .add_argument ("bucket" , help = "bucketname to send heartbeat to" )
46
- parser_heartbeat .add_argument (
47
- "data" , default = "{}" , help = "JSON data to send in heartbeat"
48
- )
49
-
50
- parser_buckets = subparsers .add_parser ("buckets" , help = "List all buckets" )
51
- parser_buckets .set_defaults (which = "buckets" )
52
-
53
- parser_buckets = subparsers .add_parser ("events" , help = "Query events from bucket" )
54
- parser_buckets .set_defaults (which = "events" )
55
- parser_buckets .add_argument ("bucket" )
56
-
57
- parser_query = subparsers .add_parser ("query" , help = "Query events from bucket" )
58
- parser_query .set_defaults (which = "query" )
59
- parser_query .add_argument ("path" )
60
- parser_query .add_argument ("--name" )
61
- parser_query .add_argument ("--cache" , action = "store_true" )
62
- parser_query .add_argument (
63
- "--json" , action = "store_true" , help = "Output resulting JSON"
26
+ @click .group (
27
+ help = "CLI utility for aw-client to aid in interacting with the ActivityWatch server"
28
+ )
29
+ @click .option ("--testing" , is_flag = True , help = "Set to use testing ports by default" )
30
+ @click .option (
31
+ "--host" ,
32
+ default = "127.0.0.1" ,
33
+ help = "Address of host" ,
34
+ )
35
+ @click .option (
36
+ "--port" ,
37
+ default = 5600 ,
38
+ help = "Port to use" ,
39
+ )
40
+ @click .pass_context
41
+ def main (ctx , testing : bool , host : str , port : int ):
42
+ ctx .testing = testing
43
+ ctx .client = aw_client .ActivityWatchClient (
44
+ host = host ,
45
+ port = port if port != 5600 else (5666 if testing else 5600 ),
64
46
)
65
- parser_query .add_argument ("--start" , default = now - td1day , type = _valid_date )
66
- parser_query .add_argument ("--end" , default = now + 10 * td1yr , type = _valid_date )
67
47
68
- args = parser .parse_args ()
69
- # print("Args: {}".format(args))
70
48
71
- client = aw_client .ActivityWatchClient (
72
- host = args .host .split (":" )[0 ],
73
- port = int (
74
- (args .host .split (":" )[1 :] + [5600 if not args .testing else 5666 ]).pop ()
75
- ),
76
- )
77
-
78
- if args .which == "heartbeat" :
79
- e = Event (duration = 0 , data = json .loads (args .data ), timestamp = now )
80
- print (e )
81
- client .heartbeat (args .bucket , e , args .pulsetime )
82
- elif args .which == "buckets" :
83
- buckets = client .get_buckets ()
84
- print ("Buckets:" )
85
- for bucket in buckets :
86
- print (" - {}" .format (bucket ))
87
- elif args .which == "events" :
88
- events = client .get_events (args .bucket )
89
- print ("events:" )
90
- for e in events :
91
- print (
92
- " - {} ({}) {}" .format (
93
- e .timestamp .replace (tzinfo = None , microsecond = 0 ),
94
- str (e .duration ).split ("." )[0 ],
95
- e .data ,
96
- )
49
+ @main .command (help = "Send a heartbeat to bucket with ID `bucket_id` with JSON `data`" )
50
+ @click .argument ("bucket_id" )
51
+ @click .argument ("data" )
52
+ @click .option ("--pulsetime" , default = 60 , help = "pulsetime to use for merging heartbeats" )
53
+ @click .pass_context
54
+ def heartbeat (ctx , bucket_id : str , data : str , pulsetime : int ):
55
+ now = datetime .now (timezone .utc )
56
+ e = Event (duration = 0 , data = json .loads (data ), timestamp = now )
57
+ print (e )
58
+ ctx .client .heartbeat (bucket_id , e , pulsetime )
59
+
60
+
61
+ @main .command (help = "List all buckets" )
62
+ @click .pass_context
63
+ def buckets (ctx ):
64
+ buckets = ctx .client .get_buckets ()
65
+ print ("Buckets:" )
66
+ for bucket in buckets :
67
+ print (" - {}" .format (bucket ))
68
+
69
+
70
+ @main .command (help = "Query events from bucket with ID `bucket_id`" )
71
+ @click .argument ("bucket_id" )
72
+ @click .pass_context
73
+ def events (ctx , bucket_id : str ):
74
+ events = ctx .client .get_events (bucket_id )
75
+ print ("events:" )
76
+ for e in events :
77
+ print (
78
+ " - {} ({}) {}" .format (
79
+ e .timestamp .replace (tzinfo = None , microsecond = 0 ),
80
+ str (e .duration ).split ("." )[0 ],
81
+ e .data ,
97
82
)
98
- elif args .which == "query" :
99
- with open (args .path ) as f :
100
- query = f .read ()
101
- result = client .query (
102
- query , args .start , args .end , cache = args .cache , name = args .name
103
83
)
104
- if args .json :
105
- print (json .dumps (result ))
106
- else :
107
- for period in result :
108
- print ("Showing 10 out of {} events:" .format (len (period )))
109
- for event in period [:10 ]:
110
- event .pop ("id" )
111
- event .pop ("timestamp" )
112
- print (
113
- " - Duration: {} \t Data: {}" .format (
114
- str (timedelta (seconds = event ["duration" ])).split ("." )[0 ],
115
- event ["data" ],
116
- )
117
- )
84
+
85
+
86
+ @main .command (help = "Run a query in file at `path` on the server" )
87
+ @click .argument ("path" )
88
+ @click .option ("--name" )
89
+ @click .option ("--cache" , is_flag = True )
90
+ @click .option ("--json" , is_flag = True )
91
+ @click .option ("--start" , default = now - td1day , type = click .DateTime ())
92
+ @click .option ("--stop" , default = now + td1yr , type = click .DateTime ())
93
+ @click .pass_context
94
+ def query (
95
+ ctx ,
96
+ path : str ,
97
+ cache : bool ,
98
+ _json : bool ,
99
+ start : datetime ,
100
+ stop : datetime ,
101
+ name : str = None ,
102
+ ):
103
+ with open (path ) as f :
104
+ query = f .read ()
105
+ result = ctx .client .query (query , [(start , stop )], cache = cache , name = name )
106
+ if _json :
107
+ print (json .dumps (result ))
108
+ else :
109
+ for period in result :
110
+ print ("Showing 10 out of {} events:" .format (len (period )))
111
+ for event in period [:10 ]:
112
+ event .pop ("id" )
113
+ event .pop ("timestamp" )
118
114
print (
119
- "Total duration:\t " ,
120
- timedelta (seconds = sum (e ["duration" ] for e in period )),
115
+ " - Duration: {} \t Data: {}" .format (
116
+ str (timedelta (seconds = event ["duration" ])).split ("." )[0 ],
117
+ event ["data" ],
118
+ )
121
119
)
122
- else :
123
- parser .print_help ()
120
+ print (
121
+ "Total duration:\t " ,
122
+ timedelta (seconds = sum (e ["duration" ] for e in period )),
123
+ )
124
124
125
125
126
126
if __name__ == "__main__" :
0 commit comments