Clocking in and out is boring. Why dont you automate it? This python module will do it for you in no time!
- Automatically perform clock in/out operations from your favourite time tracking app.
- Run hooks right after clocking in/out.
- Provides a plugin-driven architecture that makes it easy to add support for any time tracking app and any notification service.
- Out of the box support for Woffu.
- Out of the box support for Telegram notifications after clocking in/out.
- Download the latest release
- Install the module
pip install -e clocking_assistant-X.Y.Z.tar.gz
- Create the configuration file in
/srv/clocking_assistant/config.json. This will vary depending of the service you use to clock in. You should look for you tracking service in drivers, but overall it will look somewhat like this:{ "driver": { "name": "driver name", "credentials": { "api-key": "secret-key" }, "options": { ... } }, } - Setup a cron job to clock in and out whenever you like:
crontab -e # Cron file 0 9 * * * python -m clocking_assistant clock-in 0 14 * * * python -m clocking_assistant clock-out
If the configuration file does not exist, an error will be raised and the application will exit.
| Argument | Description | Default Value |
|---|---|---|
--config |
File used to configure the program | /srv/clocking_assistant/config.json. |
[operation] |
Required positional argument. Must be either clock-in or clock-out. Specifies the operation to be performed by the module. |
Here's a list of currently supported time tracking services:
- Automatically skip non working days, such as weekends, national and regional holidays and requested PTO.
- Human-like behaviour (see
humanizeflag).
Sample configuration:
{
"driver": {
"name": "woffu",
"credentials": {
"username": "<woffu username>",
"password": "<woffu password>",
},
"options": {
"humanize": true
}
}
}| Name | Description | Default Value |
|---|---|---|
humanize |
Adds a random delay (between 0 and 120 seconds) whenever the scripts is about to clock in or out. This way we ensure clocking hours are always slightly different, but your cron job should take this delay into account! | false |
This module offers support for running hooks after clocking in/out.
Telegram notifications are supported out of the box, but there's room for more integrations through the plugins architecture ;)
To receive a message via Telegram bot anytime the module clocks you in or out, simply set up the telegram hook in your configuration file:
{
"username": "<YOUR WOFFU USERNAME>",
"password": "<YOUR WOFFU PASSWORD>",
"hooks": [
{
"name": "telegram",
"args": {
"api_key": "<TELEGRAM BOT KEY>"
}
}
]
}You may also customize the notification message by specifying it in the args section:
{
...
"hooks": [
{
"name": "telegram",
"args": {
"api_key": "<TELEGRAM BOT KEY>",
"message": "Custom message"
}
}
]
}Don't forget to text your bot before you run the script for the first time!
You may add your own time trackers and hooks!
Plugins are loaded from /srv/clocking_assistant/plugins, and their data is stored under
/srv/clocking_assistant/plugins/data/${plugin_name} by default. This is customizable by plugins and plugins_data (respectively) keys within the configuration file:
{
...
"plugins": "/etc/clocking-assistant/plugins",
"plugins_data": "/var/clocking-assistant/plugins"
}Have in mind that any feature that allows running arbitrary code is somewhat a risk. Only use plugins you trust!
To make a new hook, you just need to create a Python script with a class extending HookHandlerBase, set the hook name associated to this handler and implement the run method. For instance, let's write a very simple discord plugin that will be executed whenever the hook 'discord' is defined:
from clocking_assistant import HookDefinition, HookHandlerBase
class DiscordHandler(HookHandlerBase):
def __init__(self, cache_dir: str) -> None:
super().__init__('discord', cache_dir)
def run(self, hook: HookDefinition):
key = hook.args['api-key']
message = hook.args['message']
# Actually do something...Now you'd only need to place the script under the plugins folder and add the custom hook to the configuration file!
{
...
"hooks": [
{
"name": "discord",
"args": {
"api-key": "hello",
"message": "there"
}
}
]
}If your time tracking service of choice is not supported, you may just support it yourself.
You will need to create a Python script with a class extending ClockingServiceBase, set the plugin name associated to this service and implement the clock_in, clock_out and is_working_day methods. Here's some boilerplate code:
from clocking_assistant import ClockingServiceBase
class MyTrackerService(ClockingServiceBase):
def __init__(self, data_dir: str, credentials: Dict[str, str], options: Dict[str, Any]) -> None:
super().__init__("myTracker", data_dir, credentials, options)
def is_working_day(self) -> bool:
# Check whether today is a working day
working_day = ...
return working_day
def clock_in(self):
api_key = self.credentials['api-key']
opt = self.options['some-option']
# Actually clock in
def clock_out(self):
api_key = self.credentials['api-key']
opt = self.options['some-option']
# Actually clock outNow you'd only need to place the script under the plugins folder and select your custom driver in the configuration file!
{
"driver": {
{
"name": "myTracker",
"credentials": {
"api-key": "secret-key",
},
"options": {
"some-option": "some value"
}
}
}
}