add dynamic config commands

This commit is contained in:
2026-05-22 18:11:08 +01:00
parent 1bf8e41e0c
commit c3b05c6bcb
8 changed files with 110 additions and 19 deletions

View File

@@ -30,3 +30,7 @@ font = "./res/curie.bdf"
text_filters = [ "lowercase" ]
text_offset = [45, 4]
text_fill = [255, 255, 255] # your template image must have alpha channel to use alpha
[[image]]
output = "out/iloveseason.gif"
command = [ "python", "./res/iloveseason.py" ]

View File

@@ -12,7 +12,7 @@ such as nginx or caddy.
1. install requirements: `pip install -r requirements.txt`
2. run: `python main/src.py [-c config-file] [-L]`.
## docker
### docker
a [dockerfile](./Dockerfile) and [compose file](./compose.yaml) have been provided.
keep in mind the commands will run in the docker container, too.
@@ -37,6 +37,36 @@ RUN apt-get update && apt-get install blahblahblah
CMD [ "python", "-u", "./src/main.py", "-c", "/config.toml" ]
```
## writing commands
### basic
basic commands return just text.
the text can end in 0 or 1 newlines but not multiple,
else it will be interpreted as a dynamic config command.
### dynamic config commands
any config can be dynamically set by preceeding the text to be printed
with TOML config:
```
template = "pat/to/templat.gif"
font = "fonts/custom_font.bdf"
text_offset = [20, 4]
hello world
```
if you do not want to print any text,
simply leave an extra blank/empty line
(the text ends in two newlines)
or a space character:
```
template = "pat/to/templat.gif"
```
## config
the provided [example config file](./config.toml) lists all the options that can be used.

BIN
res/autumn.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

42
res/iloveseason.py Executable file
View File

@@ -0,0 +1,42 @@
#!/usr/bin/env python3
#
# Akbar Rahman <hi@alv.cx>
#
import sys
from datetime import datetime as dt
def get_args():
""" Get command line arguments """
import argparse
parser = argparse.ArgumentParser()
return parser.parse_args()
def main(args):
""" Entry point for script """
now = dt.now()
template = ""
if now.month in [3, 4, 5]:
template = './res/spring.gif'
if now.month in [6, 7, 8]:
template = './res/summer.gif'
if now.month in [9, 10, 11]:
template = './res/autumn.gif'
if now.month in [12, 1, 2]:
template = './res/winter.gif'
print(f'template = "{template}"')
print()
return 0
if __name__ == '__main__':
try:
sys.exit(main(get_args()))
except KeyboardInterrupt:
sys.exit(0)

BIN
res/spring.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
res/summer.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

BIN
res/winter.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -3,6 +3,7 @@
# Akbar Rahman <hi@alv.cx>
#
import json
import sys
import subprocess
import time
@@ -22,22 +23,36 @@ def get_args():
def generate(config):
if config.get('template'):
img = Image.open(config['template'])
else:
img = Image.new(mode="RGBA", size = config['size'])
draw = ImageDraw.Draw(img)
with open(config['font'], "rb") as fp:
font = BdfFontFile.BdfFontFile(fp).to_imagefont()
process = subprocess.run(config['command'], stdout=subprocess.PIPE, shell=False)
if process.returncode != config.get('return_code', 0):
# process did not run succesfully.
# do not risk displaying that to user
return
cmd_output = process.stdout.decode('utf-8').split('\n')
print(f"{cmd_output=}")
dynamic_config = {}
if len(cmd_output) > 2:
dynamic_config = tomllib.loads('\n'.join(cmd_output[:-2]))
text = cmd_output[-2]
else:
text = cmd_output[0]
print(f"{dynamic_config=}")
for key, val in dynamic_config.items():
config[key] = val
if config.get('template'):
img = Image.open(config['template'])
else:
img = Image.new(mode="RGBA", size = config['size'])
print(f"{text=}")
if text:
draw = ImageDraw.Draw(img)
with open(config['font'], "rb") as fp:
font = BdfFontFile.BdfFontFile(fp).to_imagefont()
text = process.stdout.decode('utf-8').split('\n')[0]
for filter in config.get('text_filters', []):
if filter == "lowercase":
text = text.lower()