762 lines
28 KiB
Bash
762 lines
28 KiB
Bash
#!/bin/bash
|
|
# =============================================================================
|
|
# photobooth-config.sh - Gestion rapide de la config photobooth-app
|
|
# =============================================================================
|
|
# Usage:
|
|
# bash photobooth-config.sh quality high|low|status
|
|
# bash photobooth-config.sh livestream on|off|status
|
|
# bash photobooth-config.sh frontpage manuel|direct|noprint|status
|
|
# bash photobooth-config.sh restart
|
|
# =============================================================================
|
|
|
|
set -uo pipefail
|
|
|
|
API_URL="http://127.0.0.1:8083"
|
|
API_USER="admin"
|
|
API_PASS="PhotoBooth2026!"
|
|
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
RED='\033[0;31m'
|
|
CYAN='\033[0;36m'
|
|
NC='\033[0m'
|
|
|
|
# --- Auth ---
|
|
get_token() {
|
|
curl -s -X POST "${API_URL}/api/admin/auth/token" \
|
|
-H "Content-Type: application/x-www-form-urlencoded" \
|
|
-d "grant_type=password&username=${API_USER}&password=${API_PASS}" \
|
|
| python3 -c 'import sys,json;print(json.load(sys.stdin)["access_token"])'
|
|
}
|
|
|
|
get_config() {
|
|
local token="$1"
|
|
curl -s "${API_URL}/api/admin/config/app" \
|
|
-H "Authorization: Bearer ${token}"
|
|
}
|
|
|
|
set_config() {
|
|
local token="$1"
|
|
local config="$2"
|
|
curl -s -X PATCH "${API_URL}/api/admin/config/app" \
|
|
-H "Authorization: Bearer ${token}" \
|
|
-H "Content-Type: application/json" \
|
|
-d "${config}" > /dev/null
|
|
}
|
|
|
|
# =============================================================================
|
|
# QUALITE
|
|
# =============================================================================
|
|
quality_status() {
|
|
local token
|
|
token=$(get_token)
|
|
local config
|
|
config=$(get_config "$token")
|
|
|
|
local capture_w quality
|
|
capture_w=$(echo "$config" | python3 -c 'import sys,json;c=json.load(sys.stdin);print(c["backends"]["group_backends"][0]["backend_config"]["CAPTURE_CAM_RESOLUTION_WIDTH"])')
|
|
quality=$(echo "$config" | python3 -c 'import sys,json;c=json.load(sys.stdin);print(c["backends"]["group_backends"][0]["backend_config"]["original_still_quality"])')
|
|
|
|
if [ "$capture_w" -ge 4000 ]; then
|
|
echo -e "Qualite: ${GREEN}HAUTE${NC} (${capture_w}px, quality ${quality})"
|
|
else
|
|
echo -e "Qualite: ${YELLOW}BASSE${NC} (${capture_w}px, quality ${quality})"
|
|
fi
|
|
}
|
|
|
|
quality_high() {
|
|
local token
|
|
token=$(get_token)
|
|
|
|
set_config "$token" '{
|
|
"backends": {
|
|
"group_backends": [{
|
|
"enabled": true,
|
|
"description": "pi camera module V3",
|
|
"backend_config": {
|
|
"orientation": "1: 0°",
|
|
"backend_type": "Picamera2",
|
|
"camera_num": 0,
|
|
"CAPTURE_CAM_RESOLUTION_WIDTH": 4608,
|
|
"CAPTURE_CAM_RESOLUTION_HEIGHT": 3072,
|
|
"PREVIEW_CAM_RESOLUTION_WIDTH": 2304,
|
|
"PREVIEW_CAM_RESOLUTION_HEIGHT": 1536,
|
|
"LIVEVIEW_RESOLUTION_WIDTH": 750,
|
|
"LIVEVIEW_RESOLUTION_HEIGHT": 500,
|
|
"framerate_still_mode": 20,
|
|
"framerate_video_mode": 25,
|
|
"frame_skip_count": 4,
|
|
"optimized_lowlight_short_exposure": false,
|
|
"videostream_quality": "MEDIUM",
|
|
"original_still_quality": 100
|
|
}
|
|
}]
|
|
},
|
|
"mediaprocessing": {
|
|
"full_still_length": 4608,
|
|
"preview_still_length": 2304,
|
|
"thumbnail_still_length": 960
|
|
}
|
|
}'
|
|
|
|
echo -e "${GREEN}Qualite HAUTE activee${NC} (4608x3072, quality 100)"
|
|
echo " -> systemctl --user restart photobooth-app"
|
|
}
|
|
|
|
quality_low() {
|
|
local token
|
|
token=$(get_token)
|
|
|
|
set_config "$token" '{
|
|
"backends": {
|
|
"group_backends": [{
|
|
"enabled": true,
|
|
"description": "pi camera module V3",
|
|
"backend_config": {
|
|
"orientation": "1: 0°",
|
|
"backend_type": "Picamera2",
|
|
"camera_num": 0,
|
|
"CAPTURE_CAM_RESOLUTION_WIDTH": 2304,
|
|
"CAPTURE_CAM_RESOLUTION_HEIGHT": 1536,
|
|
"PREVIEW_CAM_RESOLUTION_WIDTH": 1152,
|
|
"PREVIEW_CAM_RESOLUTION_HEIGHT": 768,
|
|
"LIVEVIEW_RESOLUTION_WIDTH": 750,
|
|
"LIVEVIEW_RESOLUTION_HEIGHT": 500,
|
|
"framerate_still_mode": 20,
|
|
"framerate_video_mode": 25,
|
|
"frame_skip_count": 4,
|
|
"optimized_lowlight_short_exposure": false,
|
|
"videostream_quality": "MEDIUM",
|
|
"original_still_quality": 90
|
|
}
|
|
}]
|
|
},
|
|
"mediaprocessing": {
|
|
"full_still_length": 2304,
|
|
"preview_still_length": 1200,
|
|
"thumbnail_still_length": 480
|
|
}
|
|
}'
|
|
|
|
echo -e "${YELLOW}Qualite BASSE activee${NC} (2304x1536, quality 90)"
|
|
echo " -> systemctl --user restart photobooth-app"
|
|
}
|
|
|
|
# =============================================================================
|
|
# LIVESTREAM
|
|
# =============================================================================
|
|
livestream_status() {
|
|
local token
|
|
token=$(get_token)
|
|
local config
|
|
config=$(get_config "$token")
|
|
|
|
local idle_stream
|
|
idle_stream=$(echo "$config" | python3 -c 'import sys,json;c=json.load(sys.stdin);print(c["uisettings"]["enable_livestream_when_idle"])')
|
|
|
|
if [ "$idle_stream" = "True" ]; then
|
|
echo -e "Livestream idle: ${GREEN}ACTIVE${NC}"
|
|
else
|
|
echo -e "Livestream idle: ${RED}DESACTIVE${NC}"
|
|
fi
|
|
}
|
|
|
|
livestream_on() {
|
|
local token
|
|
token=$(get_token)
|
|
|
|
set_config "$token" '{
|
|
"uisettings": {
|
|
"enable_livestream_when_idle": true
|
|
}
|
|
}'
|
|
|
|
echo -e "${GREEN}Livestream idle ACTIVE${NC}"
|
|
echo " Les visiteurs voient la camera en direct sur l'ecran d'accueil"
|
|
}
|
|
|
|
livestream_off() {
|
|
local token
|
|
token=$(get_token)
|
|
|
|
set_config "$token" '{
|
|
"uisettings": {
|
|
"enable_livestream_when_idle": false
|
|
}
|
|
}'
|
|
|
|
echo -e "${RED}Livestream idle DESACTIVE${NC}"
|
|
echo " L'ecran d'accueil affiche le slideshow"
|
|
}
|
|
|
|
# =============================================================================
|
|
# FRONTPAGE TEXT
|
|
# =============================================================================
|
|
frontpage_status() {
|
|
local token
|
|
token=$(get_token)
|
|
local config
|
|
config=$(get_config "$token")
|
|
|
|
local text
|
|
text=$(echo "$config" | python3 -c 'import sys,json;c=json.load(sys.stdin);t=c["uisettings"]["FRONTPAGE_TEXT"];print("impression" if "Impression" in t else "noprint" if "Appui long" not in t else "unknown")')
|
|
|
|
echo -e "Frontpage: ${CYAN}${text}${NC}"
|
|
}
|
|
|
|
# --- HTML templates ---
|
|
FRONTPAGE_MANUEL='<div> <div class="fixed-top-right q-mt-lg q-mr-lg" style="pointer-events: none; max-width: 400px;"> <div class="q-pa-md" style="background: rgba(226,235,242,0.85); border-radius: 12px; backdrop-filter: blur(4px); border: 2px solid #89a9c2;"> <div class="text-h3 text-weight-bold" style="color: #335e7e;">Bienvenue !</div> <div style="font-size: 1.3rem; line-height: 1.6; color: #335e7e; margin-top: 10px;"> <div>Appui court = Photo</div> <div>Appui long (3s) = Demande d'\''impression</div> </div> </div> </div> <div class="fixed-bottom-left q-mb-sm q-ml-lg" style="pointer-events: none;"> <div class="q-pa-sm" style="background: rgba(226,235,242,0.75); border-radius: 8px; border: 1px solid #89a9c2; white-space: nowrap;"> <span style="font-size: 0.85rem; color: #335e7e;"> Photomaton propos\u00e9 par Les Sapins Du Web. En l'\''utilisant, vous acceptez que les photos puissent etre utilis\u00e9es par Les Sapins Du Web et ses partenaires. </span> </div> </div> <div class="fixed-bottom-right q-mb-lg q-mr-lg" style="pointer-events: none;"> <img src="/userdata/LSDW/logo/logo.jpeg" alt="Les Sapins Du Web" style="width:180px; height:180px; border-radius: 12px; box-shadow: 2px 2px 10px rgba(0,0,0,0.5);"> </div></div>'
|
|
|
|
FRONTPAGE_DIRECT='<div> <div class="fixed-top-right q-mt-lg q-mr-lg" style="pointer-events: none; max-width: 400px;"> <div class="q-pa-md" style="background: rgba(226,235,242,0.85); border-radius: 12px; backdrop-filter: blur(4px); border: 2px solid #89a9c2;"> <div class="text-h3 text-weight-bold" style="color: #335e7e;">Bienvenue !</div> <div style="font-size: 1.3rem; line-height: 1.6; color: #335e7e; margin-top: 10px;"> <div>Appui court = Photo</div> <div>Appui long (3s) = Impression</div> </div> </div> </div> <div class="fixed-bottom-left q-mb-sm q-ml-lg" style="pointer-events: none;"> <div class="q-pa-sm" style="background: rgba(226,235,242,0.75); border-radius: 8px; border: 1px solid #89a9c2; white-space: nowrap;"> <span style="font-size: 0.85rem; color: #335e7e;"> Photomaton propos\u00e9 par Les Sapins Du Web. En l'\''utilisant, vous acceptez que les photos puissent etre utilis\u00e9es par Les Sapins Du Web et ses partenaires. </span> </div> </div> <div class="fixed-bottom-right q-mb-lg q-mr-lg" style="pointer-events: none;"> <img src="/userdata/LSDW/logo/logo.jpeg" alt="Les Sapins Du Web" style="width:180px; height:180px; border-radius: 12px; box-shadow: 2px 2px 10px rgba(0,0,0,0.5);"> </div></div>'
|
|
|
|
FRONTPAGE_NOPRINT='<div> <div class="fixed-top-right q-mt-lg q-mr-lg" style="pointer-events: none; max-width: 400px;"> <div class="q-pa-md" style="background: rgba(226,235,242,0.85); border-radius: 12px; backdrop-filter: blur(4px); border: 2px solid #89a9c2;"> <div class="text-h3 text-weight-bold" style="color: #335e7e;">Bienvenue !</div> <div style="font-size: 1.3rem; line-height: 1.6; color: #335e7e; margin-top: 10px;"> <div>Appuyez sur le bouton pour prendre une photo</div> </div> </div> </div> <div class="fixed-bottom-left q-mb-sm q-ml-lg" style="pointer-events: none;"> <div class="q-pa-sm" style="background: rgba(226,235,242,0.75); border-radius: 8px; border: 1px solid #89a9c2; white-space: nowrap;"> <span style="font-size: 0.85rem; color: #335e7e;"> Photomaton propos\u00e9 par Les Sapins Du Web. En l'\''utilisant, vous acceptez que les photos puissent etre utilis\u00e9es par Les Sapins Du Web et ses partenaires. </span> </div> </div> <div class="fixed-bottom-right q-mb-lg q-mr-lg" style="pointer-events: none;"> <img src="/userdata/LSDW/logo/logo.jpeg" alt="Les Sapins Du Web" style="width:180px; height:180px; border-radius: 12px; box-shadow: 2px 2px 10px rgba(0,0,0,0.5);"> </div></div>'
|
|
|
|
frontpage_set() {
|
|
local mode="$1"
|
|
local token
|
|
token=$(get_token)
|
|
|
|
local html=""
|
|
case "$mode" in
|
|
manuel)
|
|
html="$FRONTPAGE_MANUEL"
|
|
;;
|
|
direct)
|
|
html="$FRONTPAGE_DIRECT"
|
|
;;
|
|
noprint)
|
|
html="$FRONTPAGE_NOPRINT"
|
|
;;
|
|
esac
|
|
|
|
# Utiliser python3 pour construire le JSON proprement (gestion des quotes)
|
|
python3 -c "
|
|
import json, urllib.request
|
|
data = json.dumps({'uisettings': {'FRONTPAGE_TEXT': '''${html}'''}}).encode()
|
|
req = urllib.request.Request('${API_URL}/api/admin/config/app', data=data, method='PATCH')
|
|
req.add_header('Authorization', 'Bearer ${token}')
|
|
req.add_header('Content-Type', 'application/json')
|
|
urllib.request.urlopen(req)
|
|
"
|
|
|
|
case "$mode" in
|
|
manuel)
|
|
echo -e "${CYAN}Frontpage: MODE MANUEL${NC}"
|
|
echo " Appui court = Photo / Appui long = Demande d'impression"
|
|
;;
|
|
direct)
|
|
echo -e "${CYAN}Frontpage: MODE DIRECT${NC}"
|
|
echo " Appui court = Photo / Appui long = Impression"
|
|
;;
|
|
noprint)
|
|
echo -e "${CYAN}Frontpage: SANS IMPRESSION${NC}"
|
|
echo " Appuyez sur le bouton pour prendre une photo"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# =============================================================================
|
|
# ACTIONS IMAGE
|
|
# =============================================================================
|
|
ACTIONS_DIR="${HOME}/photobooth-data/actions-backups"
|
|
|
|
actions_init() {
|
|
mkdir -p "$ACTIONS_DIR"
|
|
}
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
DISPLAY_ACTIONS_PY="${SCRIPT_DIR}/display_actions.py"
|
|
|
|
actions_list() {
|
|
local token
|
|
token=$(get_token)
|
|
local config
|
|
config=$(get_config "$token")
|
|
|
|
echo "=== Actions image actuelles ==="
|
|
echo "$config" | python3 "$DISPLAY_ACTIONS_PY"
|
|
}
|
|
|
|
actions_backup() {
|
|
local name="$1"
|
|
actions_init
|
|
local token
|
|
token=$(get_token)
|
|
local config
|
|
config=$(get_config "$token")
|
|
|
|
local filepath="${ACTIONS_DIR}/${name}.json"
|
|
|
|
echo "$config" | python3 -c "
|
|
import sys, json
|
|
c = json.load(sys.stdin)
|
|
with open('${filepath}', 'w') as f:
|
|
json.dump(c['actions'], f, indent=2, ensure_ascii=False)
|
|
"
|
|
|
|
local count
|
|
count=$(python3 -c "import json;print(len(json.load(open('${filepath}'))['image']))")
|
|
echo -e "${GREEN}Backup sauvegarde: ${filepath}${NC}"
|
|
echo " ${count} action(s) image"
|
|
}
|
|
|
|
actions_restore() {
|
|
local name="$1"
|
|
actions_init
|
|
local filepath="${ACTIONS_DIR}/${name}.json"
|
|
|
|
if [ ! -f "$filepath" ]; then
|
|
echo -e "${RED}Backup introuvable: ${filepath}${NC}"
|
|
echo "Backups disponibles:"
|
|
actions_list_backups
|
|
return 1
|
|
fi
|
|
|
|
local token
|
|
token=$(get_token)
|
|
|
|
python3 -c "
|
|
import json, urllib.request
|
|
with open('${filepath}') as f:
|
|
actions = json.load(f)
|
|
data = json.dumps({'actions': actions}).encode()
|
|
req = urllib.request.Request('${API_URL}/api/admin/config/app', data=data, method='PATCH')
|
|
req.add_header('Authorization', 'Bearer ${token}')
|
|
req.add_header('Content-Type', 'application/json')
|
|
urllib.request.urlopen(req)
|
|
"
|
|
|
|
local count
|
|
count=$(python3 -c "import json;print(len(json.load(open('${filepath}'))['image']))")
|
|
echo -e "${GREEN}Backup restaure: ${name}${NC}"
|
|
echo " ${count} action(s) image chargees"
|
|
echo " -> systemctl --user restart photobooth-app"
|
|
}
|
|
|
|
actions_list_backups() {
|
|
actions_init
|
|
echo "=== Backups disponibles ==="
|
|
local found=false
|
|
for f in "${ACTIONS_DIR}"/*.json; do
|
|
if [ -f "$f" ]; then
|
|
found=true
|
|
local basename
|
|
basename=$(basename "$f" .json)
|
|
local count
|
|
count=$(python3 -c "import json;print(len(json.load(open('${f}'))['image']))" 2>/dev/null || echo "?")
|
|
local date
|
|
date=$(stat -c '%y' "$f" 2>/dev/null | cut -d. -f1)
|
|
echo " ${basename} (${count} actions, ${date})"
|
|
fi
|
|
done
|
|
if ! $found; then
|
|
echo " (aucun)"
|
|
fi
|
|
}
|
|
|
|
actions_show() {
|
|
local name="$1"
|
|
actions_init
|
|
local filepath="${ACTIONS_DIR}/${name}.json"
|
|
|
|
if [ ! -f "$filepath" ]; then
|
|
echo -e "${RED}Backup introuvable: ${filepath}${NC}"
|
|
return 1
|
|
fi
|
|
|
|
echo "=== Backup: ${name} ==="
|
|
python3 "$DISPLAY_ACTIONS_PY" --file "$filepath"
|
|
}
|
|
|
|
actions_move() {
|
|
local from="$1"
|
|
local to="$2"
|
|
local token
|
|
token=$(get_token)
|
|
local tmpfile
|
|
tmpfile=$(mktemp /tmp/photobooth-config-XXXXXX.json)
|
|
get_config "$token" > "$tmpfile"
|
|
|
|
python3 -c "
|
|
import json, urllib.request, sys
|
|
with open('${tmpfile}') as f:
|
|
config = json.load(f)
|
|
actions = config['actions']['image']
|
|
count = len(actions)
|
|
f, t = int('${from}'), int('${to}')
|
|
if f < 0 or f >= count or t < 0 or t >= count:
|
|
print(f'Erreur: index invalide (0-{count-1})')
|
|
sys.exit(1)
|
|
item = actions.pop(f)
|
|
actions.insert(t, item)
|
|
config['actions']['image'] = actions
|
|
data = json.dumps({'actions': config['actions']}).encode()
|
|
req = urllib.request.Request('${API_URL}/api/admin/config/app', data=data, method='PATCH')
|
|
req.add_header('Authorization', 'Bearer ${token}')
|
|
req.add_header('Content-Type', 'application/json')
|
|
urllib.request.urlopen(req)
|
|
print(f'Action [{f}] deplacee vers [{t}]')
|
|
for i, a in enumerate(actions):
|
|
marker = ' <--' if i == t else ''
|
|
print(f' [{i}] {a[\"name\"]}{marker}')
|
|
"
|
|
rm -f "$tmpfile"
|
|
}
|
|
|
|
actions_enable() {
|
|
local index="$1"
|
|
local token
|
|
token=$(get_token)
|
|
local tmpfile
|
|
tmpfile=$(mktemp /tmp/photobooth-config-XXXXXX.json)
|
|
get_config "$token" > "$tmpfile"
|
|
|
|
python3 -c "
|
|
import json, urllib.request, sys
|
|
with open('${tmpfile}') as f:
|
|
config = json.load(f)
|
|
actions = config['actions']['image']
|
|
idx = int('${index}')
|
|
if idx < 0 or idx >= len(actions):
|
|
print(f'Erreur: index invalide (0-{len(actions)-1})')
|
|
sys.exit(1)
|
|
actions[idx]['trigger']['ui_trigger']['show_button'] = True
|
|
data = json.dumps({'actions': config['actions']}).encode()
|
|
req = urllib.request.Request('${API_URL}/api/admin/config/app', data=data, method='PATCH')
|
|
req.add_header('Authorization', 'Bearer ${token}')
|
|
req.add_header('Content-Type', 'application/json')
|
|
urllib.request.urlopen(req)
|
|
print(f'Action [{idx}] {actions[idx][\"name\"]} : bouton VISIBLE')
|
|
"
|
|
rm -f "$tmpfile"
|
|
}
|
|
|
|
actions_disable() {
|
|
local index="$1"
|
|
local token
|
|
token=$(get_token)
|
|
local tmpfile
|
|
tmpfile=$(mktemp /tmp/photobooth-config-XXXXXX.json)
|
|
get_config "$token" > "$tmpfile"
|
|
|
|
python3 -c "
|
|
import json, urllib.request, sys
|
|
with open('${tmpfile}') as f:
|
|
config = json.load(f)
|
|
actions = config['actions']['image']
|
|
idx = int('${index}')
|
|
if idx < 0 or idx >= len(actions):
|
|
print(f'Erreur: index invalide (0-{len(actions)-1})')
|
|
sys.exit(1)
|
|
actions[idx]['trigger']['ui_trigger']['show_button'] = False
|
|
data = json.dumps({'actions': config['actions']}).encode()
|
|
req = urllib.request.Request('${API_URL}/api/admin/config/app', data=data, method='PATCH')
|
|
req.add_header('Authorization', 'Bearer ${token}')
|
|
req.add_header('Content-Type', 'application/json')
|
|
urllib.request.urlopen(req)
|
|
print(f'Action [{idx}] {actions[idx][\"name\"]} : bouton CACHE')
|
|
"
|
|
rm -f "$tmpfile"
|
|
}
|
|
|
|
actions_duplicate() {
|
|
local index="$1"
|
|
local token
|
|
token=$(get_token)
|
|
local tmpfile
|
|
tmpfile=$(mktemp /tmp/photobooth-config-XXXXXX.json)
|
|
get_config "$token" > "$tmpfile"
|
|
|
|
python3 -c "
|
|
import json, urllib.request, copy, sys
|
|
with open('${tmpfile}') as f:
|
|
config = json.load(f)
|
|
actions = config['actions']['image']
|
|
idx = int('${index}')
|
|
if idx < 0 or idx >= len(actions):
|
|
print(f'Erreur: index invalide (0-{len(actions)-1})')
|
|
sys.exit(1)
|
|
new_action = copy.deepcopy(actions[idx])
|
|
new_action['name'] = new_action['name'] + ' (copie)'
|
|
new_action['trigger']['ui_trigger']['show_button'] = False
|
|
actions.insert(idx + 1, new_action)
|
|
data = json.dumps({'actions': config['actions']}).encode()
|
|
req = urllib.request.Request('${API_URL}/api/admin/config/app', data=data, method='PATCH')
|
|
req.add_header('Authorization', 'Bearer ${token}')
|
|
req.add_header('Content-Type', 'application/json')
|
|
urllib.request.urlopen(req)
|
|
print(f'Action [{idx}] dupliquee vers [{idx+1}]')
|
|
for i, a in enumerate(actions):
|
|
marker = ' <-- copie' if i == idx + 1 else ''
|
|
print(f' [{i}] {a[\"name\"]}{marker}')
|
|
"
|
|
rm -f "$tmpfile"
|
|
}
|
|
|
|
actions_remove() {
|
|
local indices="$@"
|
|
local token
|
|
token=$(get_token)
|
|
local tmpfile
|
|
tmpfile=$(mktemp /tmp/photobooth-config-XXXXXX.json)
|
|
get_config "$token" > "$tmpfile"
|
|
|
|
python3 -c "
|
|
import json, urllib.request, sys
|
|
with open('${tmpfile}') as f:
|
|
config = json.load(f)
|
|
actions = config['actions']['image']
|
|
indices = sorted([int(x) for x in '${indices}'.split()], reverse=True)
|
|
|
|
for idx in indices:
|
|
if idx < 0 or idx >= len(actions):
|
|
print(f'Erreur: index {idx} invalide (0-{len(actions)-1})')
|
|
sys.exit(1)
|
|
|
|
removed = []
|
|
for idx in indices:
|
|
removed.append(f'[{idx}] {actions[idx][\"name\"]}')
|
|
actions.pop(idx)
|
|
|
|
data = json.dumps({'actions': config['actions']}).encode()
|
|
req = urllib.request.Request('${API_URL}/api/admin/config/app', data=data, method='PATCH')
|
|
req.add_header('Authorization', 'Bearer ${token}')
|
|
req.add_header('Content-Type', 'application/json')
|
|
urllib.request.urlopen(req)
|
|
|
|
print('Actions supprimees:')
|
|
for r in removed:
|
|
print(f' - {r}')
|
|
print()
|
|
print('Actions restantes:')
|
|
for i, a in enumerate(actions):
|
|
print(f' [{i}] {a[\"name\"]}')
|
|
print(f' Total: {len(actions)} action(s)')
|
|
"
|
|
rm -f "$tmpfile"
|
|
}
|
|
|
|
# =============================================================================
|
|
# RESTART
|
|
# =============================================================================
|
|
do_restart() {
|
|
echo "Redemarrage de photobooth-app..."
|
|
systemctl --user restart photobooth-app
|
|
sleep 3
|
|
if systemctl --user is-active photobooth-app &>/dev/null; then
|
|
echo -e "${GREEN}photobooth-app redemarre avec succes${NC}"
|
|
else
|
|
echo -e "${RED}ERREUR: photobooth-app n'a pas redemarre${NC}"
|
|
systemctl --user status photobooth-app
|
|
fi
|
|
}
|
|
|
|
# =============================================================================
|
|
# AIDE
|
|
# =============================================================================
|
|
show_help() {
|
|
cat << 'HELP'
|
|
===============================================================================
|
|
photobooth-config.sh - Gestion rapide de la config photobooth-app
|
|
===============================================================================
|
|
|
|
USAGE: photobooth-config.sh <commande> [arguments]
|
|
|
|
COMMANDES GENERALES:
|
|
status, s Afficher la config actuelle (qualite, livestream, frontpage)
|
|
restart, r Redemarrer photobooth-app
|
|
help, -h, --help Afficher cette aide
|
|
|
|
QUALITE D'IMAGE:
|
|
quality status Voir la qualite actuelle
|
|
quality high Haute qualite (4608x3072, JPEG 100%)
|
|
Meilleure qualite d'impression mais consomme plus de RAM
|
|
quality low Basse qualite (2304x1536, JPEG 90%)
|
|
Economise la RAM, suffisant pour impression Selphy
|
|
Note: necessite un restart apres changement
|
|
|
|
LIVESTREAM:
|
|
livestream status Voir si le livestream idle est actif
|
|
livestream on Activer le livestream sur l'ecran d'accueil
|
|
Les visiteurs voient la camera en direct
|
|
livestream off Desactiver le livestream idle
|
|
L'ecran d'accueil affiche le slideshow
|
|
|
|
TEXTE D'ACCUEIL (FRONTPAGE):
|
|
frontpage status Voir le mode actuel
|
|
frontpage manuel "Appui long (3s) = Demande d'impression"
|
|
Pour les events avec validation admin
|
|
frontpage direct "Appui long (3s) = Impression"
|
|
Pour les events avec impression automatique
|
|
frontpage noprint "Appuyez sur le bouton pour prendre une photo"
|
|
Pas de mention d'impression
|
|
|
|
ACTIONS IMAGE:
|
|
actions list Lister toutes les actions avec leurs parametres
|
|
L'index [0] = simple clic, [1] = double clic, etc.
|
|
actions backup <nom> Sauvegarder les actions actuelles
|
|
Ex: actions backup hopnbloc
|
|
actions restore <nom> Restaurer un backup d'actions
|
|
Ex: actions restore hopnbloc
|
|
Note: necessite un restart apres
|
|
actions backups Lister les backups disponibles
|
|
actions show <nom> Voir le contenu d'un backup
|
|
actions move <de> <vers> Deplacer une action dans la liste
|
|
Ex: actions move 3 0 (met l'action 3 en premier)
|
|
Important: l'ordre determine le bouton physique
|
|
[0] = simple clic
|
|
[1] = double clic
|
|
[2] = triple clic
|
|
[3] = quadruple clic
|
|
actions enable <index> Rendre le bouton visible sur l'ecran tactile
|
|
actions disable <index> Cacher le bouton de l'ecran tactile
|
|
actions dup <index> Dupliquer une action (copie inseree apres)
|
|
actions remove <i> [i...] Supprimer une ou plusieurs actions
|
|
Ex: actions remove 5 (supprime l'action 5)
|
|
Ex: actions remove 3 5 7 (supprime les actions 3, 5 et 7)
|
|
|
|
EXEMPLES:
|
|
|
|
# Preparer un event Hop'N Bloc
|
|
photobooth-config.sh actions backup config-avant
|
|
photobooth-config.sh actions restore hopnbloc
|
|
photobooth-config.sh frontpage manuel
|
|
photobooth-config.sh livestream on
|
|
photobooth-config.sh quality low
|
|
photobooth-config.sh restart
|
|
|
|
# Passer en haute qualite pour un event special
|
|
photobooth-config.sh quality high
|
|
photobooth-config.sh restart
|
|
|
|
# Apres l'event, tout remettre
|
|
photobooth-config.sh actions restore config-avant
|
|
photobooth-config.sh restart
|
|
|
|
===============================================================================
|
|
HELP
|
|
}
|
|
|
|
# =============================================================================
|
|
# MAIN
|
|
# =============================================================================
|
|
CMD="${1:-help}"
|
|
ARG="${2:-status}"
|
|
|
|
case "$CMD" in
|
|
quality|q)
|
|
case "$ARG" in
|
|
high|haute|hq) quality_high ;;
|
|
low|basse|lq) quality_low ;;
|
|
status|info) quality_status ;;
|
|
*) echo "Usage: $0 quality {high|low|status}" ;;
|
|
esac
|
|
;;
|
|
livestream|ls)
|
|
case "$ARG" in
|
|
on|true|1) livestream_on ;;
|
|
off|false|0) livestream_off ;;
|
|
status|info) livestream_status ;;
|
|
*) echo "Usage: $0 livestream {on|off|status}" ;;
|
|
esac
|
|
;;
|
|
frontpage|fp)
|
|
case "$ARG" in
|
|
manuel|manual) frontpage_set manuel ;;
|
|
direct) frontpage_set direct ;;
|
|
noprint|sans|off) frontpage_set noprint ;;
|
|
status|info) frontpage_status ;;
|
|
*) echo "Usage: $0 frontpage {manuel|direct|noprint|status}" ;;
|
|
esac
|
|
;;
|
|
actions|a)
|
|
case "$ARG" in
|
|
list|ls) actions_list ;;
|
|
backup|save)
|
|
if [ -z "${3:-}" ]; then
|
|
echo "Usage: $0 actions backup <nom>"
|
|
echo " Exemple: $0 actions backup hopnbloc"
|
|
exit 1
|
|
fi
|
|
actions_backup "$3"
|
|
;;
|
|
restore|load)
|
|
if [ -z "${3:-}" ]; then
|
|
echo "Usage: $0 actions restore <nom>"
|
|
actions_list_backups
|
|
exit 1
|
|
fi
|
|
actions_restore "$3"
|
|
;;
|
|
backups) actions_list_backups ;;
|
|
show)
|
|
if [ -z "${3:-}" ]; then
|
|
echo "Usage: $0 actions show <nom>"
|
|
actions_list_backups
|
|
exit 1
|
|
fi
|
|
actions_show "$3"
|
|
;;
|
|
move|mv)
|
|
if [ -z "${3:-}" ] || [ -z "${4:-}" ]; then
|
|
echo "Usage: $0 actions move <from> <to>"
|
|
echo " Exemple: $0 actions move 3 0 (deplace l'action 3 en position 0)"
|
|
exit 1
|
|
fi
|
|
actions_move "$3" "$4"
|
|
;;
|
|
enable|on)
|
|
if [ -z "${3:-}" ]; then
|
|
echo "Usage: $0 actions enable <index>"
|
|
actions_list
|
|
exit 1
|
|
fi
|
|
actions_enable "$3"
|
|
;;
|
|
disable|off)
|
|
if [ -z "${3:-}" ]; then
|
|
echo "Usage: $0 actions disable <index>"
|
|
actions_list
|
|
exit 1
|
|
fi
|
|
actions_disable "$3"
|
|
;;
|
|
dup|duplicate|copy)
|
|
if [ -z "${3:-}" ]; then
|
|
echo "Usage: $0 actions dup <index>"
|
|
actions_list
|
|
exit 1
|
|
fi
|
|
actions_duplicate "$3"
|
|
;;
|
|
remove|rm|del|delete)
|
|
if [ -z "${3:-}" ]; then
|
|
echo "Usage: $0 actions remove <index> [index...]"
|
|
echo " Exemple: $0 actions remove 5"
|
|
echo " Exemple: $0 actions remove 3 5 7"
|
|
actions_list
|
|
exit 1
|
|
fi
|
|
shift 2
|
|
actions_remove "$@"
|
|
;;
|
|
*) echo "Usage: $0 actions {list|backup|restore|backups|show|move|enable|disable|dup|remove}" ;;
|
|
esac
|
|
;;
|
|
restart|r)
|
|
do_restart
|
|
;;
|
|
status|s)
|
|
echo "=== Photobooth Config ==="
|
|
quality_status
|
|
livestream_status
|
|
frontpage_status
|
|
;;
|
|
help|-h|--help)
|
|
show_help
|
|
;;
|
|
*)
|
|
show_help
|
|
;;
|
|
esac
|