-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwebhook-server.py
executable file
·84 lines (69 loc) · 2.64 KB
/
webhook-server.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#!/usr/bin/env python3
# coding: utf-8
from functools import cache
import json
import logging
import os
from typing import Annotated
from fastapi import Depends, FastAPI, HTTPException
import uvicorn
import dotenv
import importlib
tuya_qr_sharing = importlib.import_module("tuya-qr-sharing")
app = FastAPI()
logger = logging.getLogger('uvicorn.error')
dotenv_file = dotenv.find_dotenv(usecwd=True) or dotenv.find_dotenv()
dotenv.load_dotenv(dotenv_file)
@cache
def get_config():
logger.info(f"Configuration read from {dotenv_file}")
scenes = dict(json.loads(os.getenv("webhook_server_scenes")))
scene_info = "Scenes:\n"
need_save = False
skip = []
for name, definition in scenes.items():
scene_info += f" {name}\n"
if not 'home_id' in definition:
scene_info += " Missing home_id - ignoring\n"
skip.append(name)
continue
if not 'scene_id' in definition:
scene_info += " Missing scene_id - ignoring\n"
skip.append(name)
continue
if not 'key' in definition:
scene_info += " Setting key\n"
definition['key'] = os.urandom(32).hex()
need_save = True
logger.info(scene_info)
if need_save:
dotenv.set_key(dotenv_file, "webhook_server_scenes", json.dumps(scenes, indent=2))
logger.info("Configuration saved.")
return { k: v for k, v in scenes.items() if k not in skip }
@cache
def make_client():
client = tuya_qr_sharing.TuyaQrSharing(dotenv_file)
if (result := client.connect()) != tuya_qr_sharing.EXIT_OK:
raise HTTPException(status_code=500, detail="Failed to connect to Tuya")
return client
def get_client():
client = make_client()
client.reload_token_info()
return client
ConfigDep = Annotated[dict, Depends(get_config)]
ClientDep = Annotated[tuya_qr_sharing.TuyaQrSharing, Depends(get_client)]
@app.get("/activate/{scene_id}")
async def activate(scene_id: str, key: str, config: ConfigDep, client: ClientDep):
if scene_id not in config:
raise HTTPException(status_code=404, detail="Scene not found")
scene = config[scene_id]
if key != scene['key']:
raise HTTPException(status_code=401, detail="Invalid key")
if (result := client.activate(scene['home_id'], scene['scene_id'])) != tuya_qr_sharing.EXIT_OK:
raise HTTPException(status_code=500, detail=f"Failed to activate scene {scene_id} ({result})")
return {"message": f"Scene {scene_id} activated successfully"}
if __name__ == "__main__":
bind_host = os.getenv("webhook_server_host", "::")
bind_port = int(os.getenv("webhook_server_port", "8000"))
root_path = os.getenv("webhook_server_root_path", "")
uvicorn.run(app, host=bind_host, port=bind_port, log_level="info", root_path=root_path)