first commit
This commit is contained in:
@@ -0,0 +1,761 @@
|
||||
#!/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
|
||||
Reference in New Issue
Block a user