Isolate official account RPC capabilities from API key device driver
This commit is contained in:
@@ -4,7 +4,6 @@ from pigway_frame_flow.models import Device, GalleryImage
|
||||
|
||||
|
||||
class FrameDeviceDriver(Protocol):
|
||||
def widgets(self): ...
|
||||
def invalidate(self) -> None: ...
|
||||
def device(self, refresh: bool = False) -> Device: ...
|
||||
def get_current_image(self) -> int | None: ...
|
||||
|
||||
@@ -8,9 +8,8 @@ from pigway_frame_flow.models import (
|
||||
|
||||
|
||||
class KokonnaDriver:
|
||||
def __init__(self, client, device_id, sanitize=lambda v: v, widgets=None):
|
||||
def __init__(self, client, device_id, sanitize=lambda v: v):
|
||||
self.client, self.device_id, self.sanitize = client, device_id, sanitize
|
||||
self.widget_reader = widgets
|
||||
self.cached: Device | None = None
|
||||
self.cached_at = 0.0
|
||||
|
||||
@@ -63,9 +62,6 @@ class KokonnaDriver:
|
||||
self.cached_at = time.monotonic()
|
||||
return result
|
||||
|
||||
def widgets(self):
|
||||
return self.widget_reader.read()
|
||||
|
||||
def get_current_image(self):
|
||||
return self.device().current_content.id
|
||||
|
||||
|
||||
@@ -1,862 +0,0 @@
|
||||
{
|
||||
"observed_at": "2026-10-02",
|
||||
"transport": "https://robot.galaxyguide.cn/api/rpc",
|
||||
"method": "appFrame.getFrameCovers",
|
||||
"catalog": [
|
||||
{
|
||||
"id": 188,
|
||||
"name": "大字体日历",
|
||||
"tags": [
|
||||
"Weather",
|
||||
"feature",
|
||||
"Calendar"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": [
|
||||
"城市"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 183,
|
||||
"name": "天气日历-黑",
|
||||
"tags": [
|
||||
"Weather",
|
||||
"feature",
|
||||
"Calendar"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": [
|
||||
"城市"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 182,
|
||||
"name": "天气日历-白",
|
||||
"tags": [
|
||||
"Weather",
|
||||
"feature",
|
||||
"Calendar"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": [
|
||||
"城市"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 190,
|
||||
"name": "文学金句2",
|
||||
"tags": [
|
||||
"DailyRandom",
|
||||
"Calendar",
|
||||
"feature"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": []
|
||||
},
|
||||
{
|
||||
"id": 30,
|
||||
"name": "文学金句",
|
||||
"tags": [
|
||||
"DailyRandom",
|
||||
"Calendar",
|
||||
"feature"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": []
|
||||
},
|
||||
{
|
||||
"id": 191,
|
||||
"name": "名人名言",
|
||||
"tags": [
|
||||
"DailyRandom",
|
||||
"Calendar",
|
||||
"feature",
|
||||
"Lunar"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": []
|
||||
},
|
||||
{
|
||||
"id": 29,
|
||||
"name": "古诗词名句",
|
||||
"tags": [
|
||||
"DailyRandom",
|
||||
"Calendar",
|
||||
"feature",
|
||||
"Lunar"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": []
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "电影台词",
|
||||
"tags": [
|
||||
"Weather",
|
||||
"Calendar",
|
||||
"DailyRandom"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": [
|
||||
"所在城市"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 13,
|
||||
"name": "一周天气",
|
||||
"tags": [
|
||||
"Weather",
|
||||
"feature",
|
||||
"Calendar",
|
||||
"DailyRandom"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": [
|
||||
"城市"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 27,
|
||||
"name": "世界名画推荐",
|
||||
"tags": [
|
||||
"DailyRandom",
|
||||
"Calendar",
|
||||
"feature"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": []
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"name": "项目倒计时",
|
||||
"tags": [
|
||||
"Countdown"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": [
|
||||
"项目名称",
|
||||
"截止时间"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"name": "结婚纪念日",
|
||||
"tags": [
|
||||
"Stopwatch"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": [
|
||||
"新郎姓名",
|
||||
"新娘姓名",
|
||||
"结婚日期"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 28,
|
||||
"name": "乐器知识",
|
||||
"tags": [
|
||||
"DailyRandom",
|
||||
"Calendar",
|
||||
"feature"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": []
|
||||
},
|
||||
{
|
||||
"id": 193,
|
||||
"name": "作品名称和描述",
|
||||
"tags": [
|
||||
"DailyRandom"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": []
|
||||
},
|
||||
{
|
||||
"id": 192,
|
||||
"name": "作品名称",
|
||||
"tags": [
|
||||
"DailyRandom"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": []
|
||||
},
|
||||
{
|
||||
"id": 31,
|
||||
"name": "旅行目的地推荐",
|
||||
"tags": [
|
||||
"DailyRandom",
|
||||
"Calendar",
|
||||
"Weather"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": [
|
||||
"城市"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 32,
|
||||
"name": "动物科普",
|
||||
"tags": [
|
||||
"DailyRandom",
|
||||
"Calendar"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": []
|
||||
},
|
||||
{
|
||||
"id": 33,
|
||||
"name": "植物科普",
|
||||
"tags": [
|
||||
"DailyRandom",
|
||||
"Calendar",
|
||||
"feature"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": []
|
||||
},
|
||||
{
|
||||
"id": 42,
|
||||
"name": "海洋生物科普",
|
||||
"tags": [
|
||||
"DailyRandom",
|
||||
"Calendar",
|
||||
"feature"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": []
|
||||
},
|
||||
{
|
||||
"id": 43,
|
||||
"name": "昆虫科普",
|
||||
"tags": [
|
||||
"DailyRandom",
|
||||
"Calendar",
|
||||
"feature"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": []
|
||||
},
|
||||
{
|
||||
"id": 36,
|
||||
"name": "佛经片段",
|
||||
"tags": [
|
||||
"DailyRandom",
|
||||
"Calendar",
|
||||
"feature",
|
||||
"Lunar"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": []
|
||||
},
|
||||
{
|
||||
"id": 44,
|
||||
"name": "美食推荐",
|
||||
"tags": [
|
||||
"DailyRandom",
|
||||
"Calendar",
|
||||
"feature",
|
||||
"Lunar"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": []
|
||||
},
|
||||
{
|
||||
"id": 45,
|
||||
"name": "博物馆文物推荐",
|
||||
"tags": [
|
||||
"DailyRandom",
|
||||
"Calendar",
|
||||
"feature"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": []
|
||||
},
|
||||
{
|
||||
"id": 46,
|
||||
"name": "职场毒鸡汤",
|
||||
"tags": [
|
||||
"DailyRandom",
|
||||
"Calendar",
|
||||
"feature",
|
||||
"Lunar"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": []
|
||||
},
|
||||
{
|
||||
"id": 37,
|
||||
"name": "每日学单词",
|
||||
"tags": [
|
||||
"DailyRandom",
|
||||
"Calendar",
|
||||
"feature"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": []
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"name": "生活建议",
|
||||
"tags": [
|
||||
"Weather",
|
||||
"Calendar",
|
||||
"feature"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": [
|
||||
"城市"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 34,
|
||||
"name": "历史上的今天",
|
||||
"tags": [
|
||||
"DailyRandom",
|
||||
"Calendar",
|
||||
"feature"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": []
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"name": "冷知识",
|
||||
"tags": [
|
||||
"Weather",
|
||||
"Calendar",
|
||||
"DailyRandom"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": [
|
||||
"所在城市"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"name": "心灵鸡汤",
|
||||
"tags": [
|
||||
"feature",
|
||||
"Weather",
|
||||
"Calendar",
|
||||
"DailyRandom"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": [
|
||||
"所在城市"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 189,
|
||||
"name": "待办和天气",
|
||||
"tags": [
|
||||
"feature",
|
||||
"DailyRandom",
|
||||
"Weather"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": [
|
||||
"所在城市",
|
||||
"待办事项"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 24,
|
||||
"name": "待办事项",
|
||||
"tags": [
|
||||
"feature",
|
||||
"DailyRandom",
|
||||
"Weather"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": [
|
||||
"所在城市",
|
||||
"待办事项"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 39,
|
||||
"name": "情侣间的365件事",
|
||||
"tags": [
|
||||
"Calendar",
|
||||
"feature",
|
||||
"Lunar"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": []
|
||||
},
|
||||
{
|
||||
"id": 25,
|
||||
"name": "星座今日运势",
|
||||
"tags": [
|
||||
"feature",
|
||||
"DailyRandom",
|
||||
"Calendar"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": [
|
||||
"生日"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 26,
|
||||
"name": "生肖今日运势",
|
||||
"tags": [
|
||||
"feature",
|
||||
"DailyRandom",
|
||||
"Lunar",
|
||||
"Calendar"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": [
|
||||
"生日"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 16,
|
||||
"name": "娱乐新闻",
|
||||
"tags": [
|
||||
"feature",
|
||||
"DailyRandom",
|
||||
"Calendar"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": []
|
||||
},
|
||||
{
|
||||
"id": 21,
|
||||
"name": "政治新闻",
|
||||
"tags": [
|
||||
"feature",
|
||||
"DailyRandom",
|
||||
"Calendar"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": []
|
||||
},
|
||||
{
|
||||
"id": 12,
|
||||
"name": "科技新闻",
|
||||
"tags": [
|
||||
"feature",
|
||||
"DailyRandom",
|
||||
"Calendar"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": []
|
||||
},
|
||||
{
|
||||
"id": 15,
|
||||
"name": "财经新闻",
|
||||
"tags": [
|
||||
"feature",
|
||||
"DailyRandom",
|
||||
"Calendar"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": []
|
||||
},
|
||||
{
|
||||
"id": 48,
|
||||
"name": "简约月历3",
|
||||
"tags": [
|
||||
"Calendar"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": []
|
||||
},
|
||||
{
|
||||
"id": 47,
|
||||
"name": "简约月历2",
|
||||
"tags": [
|
||||
"Calendar"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": []
|
||||
},
|
||||
{
|
||||
"id": 41,
|
||||
"name": "简约月历1",
|
||||
"tags": [
|
||||
"Calendar",
|
||||
"feature"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": []
|
||||
},
|
||||
{
|
||||
"id": 23,
|
||||
"name": "黄历",
|
||||
"tags": [
|
||||
"feature",
|
||||
"DailyRandom",
|
||||
"Lunar"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": []
|
||||
},
|
||||
{
|
||||
"id": 19,
|
||||
"name": "农历阳历",
|
||||
"tags": [
|
||||
"Lunar",
|
||||
"Calendar"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": []
|
||||
},
|
||||
{
|
||||
"id": 18,
|
||||
"name": "简约日历3",
|
||||
"tags": [
|
||||
"Calendar",
|
||||
"feature"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": []
|
||||
},
|
||||
{
|
||||
"id": 22,
|
||||
"name": "简约日历2",
|
||||
"tags": [
|
||||
"Calendar"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": []
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "简约日历1",
|
||||
"tags": [
|
||||
"Calendar"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": []
|
||||
},
|
||||
{
|
||||
"id": 54,
|
||||
"name": "极简日历5",
|
||||
"tags": [
|
||||
"Calendar"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": []
|
||||
},
|
||||
{
|
||||
"id": 40,
|
||||
"name": "极简日历4",
|
||||
"tags": [
|
||||
"Calendar"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": []
|
||||
},
|
||||
{
|
||||
"id": 53,
|
||||
"name": "KoKonna极简日历",
|
||||
"tags": [
|
||||
"Calendar"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": []
|
||||
},
|
||||
{
|
||||
"id": 20,
|
||||
"name": "极简日历3",
|
||||
"tags": [
|
||||
"Calendar",
|
||||
"feature"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": []
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "极简日历2",
|
||||
"tags": [
|
||||
"Calendar"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": []
|
||||
},
|
||||
{
|
||||
"id": 14,
|
||||
"name": "极简日历1",
|
||||
"tags": [
|
||||
"Calendar"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": []
|
||||
},
|
||||
{
|
||||
"id": 228,
|
||||
"name": "月历卡片",
|
||||
"tags": [
|
||||
"Weather",
|
||||
"Calendar"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": [
|
||||
"城市"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 209,
|
||||
"name": "卡片天气日历15",
|
||||
"tags": [
|
||||
"feature",
|
||||
"Weather"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": [
|
||||
"所在城市"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 208,
|
||||
"name": "卡片天气日历14",
|
||||
"tags": [
|
||||
"feature",
|
||||
"Weather"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": [
|
||||
"所在城市"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 207,
|
||||
"name": "卡片天气日历13",
|
||||
"tags": [
|
||||
"feature",
|
||||
"Weather"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": [
|
||||
"所在城市"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 206,
|
||||
"name": "卡片天气日历12",
|
||||
"tags": [
|
||||
"feature",
|
||||
"Weather"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": [
|
||||
"所在城市"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 205,
|
||||
"name": "卡片天气日历11",
|
||||
"tags": [
|
||||
"feature",
|
||||
"Weather"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": [
|
||||
"所在城市"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 204,
|
||||
"name": "卡片天气日历10",
|
||||
"tags": [
|
||||
"feature",
|
||||
"Weather"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": [
|
||||
"所在城市"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 203,
|
||||
"name": "卡片天气日历9",
|
||||
"tags": [
|
||||
"feature",
|
||||
"Weather"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": [
|
||||
"所在城市"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 202,
|
||||
"name": "卡片天气日历8",
|
||||
"tags": [
|
||||
"feature",
|
||||
"Weather"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": [
|
||||
"所在城市"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 201,
|
||||
"name": "卡片天气日历7",
|
||||
"tags": [
|
||||
"feature",
|
||||
"Weather"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": [
|
||||
"所在城市"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 200,
|
||||
"name": "卡片天气日历6",
|
||||
"tags": [
|
||||
"feature",
|
||||
"Weather"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": [
|
||||
"所在城市"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 199,
|
||||
"name": "卡片天气日历5",
|
||||
"tags": [
|
||||
"feature",
|
||||
"Weather"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": [
|
||||
"所在城市"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 198,
|
||||
"name": "卡片天气日历4",
|
||||
"tags": [
|
||||
"feature",
|
||||
"Weather"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": [
|
||||
"所在城市"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 197,
|
||||
"name": "卡片天气日历3",
|
||||
"tags": [
|
||||
"feature",
|
||||
"Weather"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": [
|
||||
"所在城市"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 196,
|
||||
"name": "卡片天气日历2",
|
||||
"tags": [
|
||||
"feature",
|
||||
"Weather"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": [
|
||||
"所在城市"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 195,
|
||||
"name": "卡片天气日历1",
|
||||
"tags": [
|
||||
"feature",
|
||||
"Weather"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": [
|
||||
"所在城市"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 57,
|
||||
"name": "自定义二维码",
|
||||
"tags": [
|
||||
"DailyRandom"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": [
|
||||
"二维码内容",
|
||||
"备注"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 56,
|
||||
"name": "画框分享二维码",
|
||||
"tags": [
|
||||
"DailyRandom"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": []
|
||||
},
|
||||
{
|
||||
"id": 55,
|
||||
"name": "画框状态",
|
||||
"tags": [
|
||||
"DailyRandom"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": []
|
||||
},
|
||||
{
|
||||
"id": 52,
|
||||
"name": "黑色艺术字贴纸2",
|
||||
"tags": [
|
||||
"DailyRandom",
|
||||
"feature"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": [
|
||||
"内容"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 50,
|
||||
"name": "黑色艺术字贴纸",
|
||||
"tags": [
|
||||
"DailyRandom",
|
||||
"feature"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": [
|
||||
"内容"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 49,
|
||||
"name": "白色艺术字贴纸",
|
||||
"tags": [
|
||||
"DailyRandom",
|
||||
"feature"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": [
|
||||
"内容"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 17,
|
||||
"name": "红色艺术字贴纸",
|
||||
"tags": [
|
||||
"DailyRandom",
|
||||
"feature"
|
||||
],
|
||||
"type": null,
|
||||
"arg_keys": [
|
||||
"内容"
|
||||
]
|
||||
}
|
||||
],
|
||||
"notes": "Observed directory only; no user tokens, device IDs, photos or configuration values retained."
|
||||
}
|
||||
@@ -1,118 +1,5 @@
|
||||
"""Read-only official widget RPC; separate from the device OpenAPI credential."""
|
||||
"""Compatibility import; official capabilities live outside device drivers."""
|
||||
|
||||
import json
|
||||
import time
|
||||
from pathlib import Path
|
||||
from pigway_frame_flow.integrations.kokonna_official.widgets import WidgetReader
|
||||
|
||||
import requests
|
||||
|
||||
from pigway_frame_flow.errors import ErrorCode as E
|
||||
from pigway_frame_flow.errors import FlowError
|
||||
from pigway_frame_flow.models import Widget, WidgetState
|
||||
|
||||
|
||||
class WidgetReader:
|
||||
def __init__(self, token="", robot_id=None, mock=False):
|
||||
self._token = token
|
||||
self._robot_id = robot_id
|
||||
self.mock = mock
|
||||
self._cached = None
|
||||
self._cached_at = 0.0
|
||||
|
||||
def read(self) -> WidgetState:
|
||||
if self._cached is not None and time.monotonic() - self._cached_at < 60:
|
||||
return self._cached
|
||||
snapshot = json.loads(
|
||||
Path(__file__).with_name("widget_catalog.json").read_text()
|
||||
)
|
||||
catalog = [
|
||||
Widget(**{k: row[k] for k in ("id", "name", "tags", "arg_keys")})
|
||||
for row in snapshot["catalog"]
|
||||
]
|
||||
if self.mock:
|
||||
return WidgetState(
|
||||
source="mock",
|
||||
configured=True,
|
||||
catalog=catalog,
|
||||
current=catalog[0],
|
||||
current_verified=True,
|
||||
)
|
||||
if not self._token or self._robot_id is None:
|
||||
return WidgetState(
|
||||
source="snapshot",
|
||||
configured=False,
|
||||
catalog=catalog,
|
||||
observed_at=snapshot["observed_at"],
|
||||
status="AUTH_REQUIRED",
|
||||
)
|
||||
try:
|
||||
response = requests.post(
|
||||
"https://robot.galaxyguide.cn/api/rpc",
|
||||
headers={"Authorization": f"Bearer {self._token}"},
|
||||
json={
|
||||
"jsonrpc": "2.0",
|
||||
"method": "appFrame.getFrameCovers",
|
||||
"params": {"robotId": self._robot_id},
|
||||
"id": int(time.time() * 1000),
|
||||
},
|
||||
timeout=15,
|
||||
allow_redirects=False,
|
||||
)
|
||||
if response.status_code in (401, 403):
|
||||
raise FlowError(E.UNAUTHORIZED, "Official widget session expired", 401)
|
||||
response.raise_for_status()
|
||||
payload = response.json()
|
||||
if payload.get("error"):
|
||||
raise FlowError(
|
||||
E.CLOUD_UNAVAILABLE, "Official widget query rejected", 502
|
||||
)
|
||||
data = payload["result"]
|
||||
rows = data["rows"]
|
||||
catalog = [
|
||||
Widget(
|
||||
id=row["id"],
|
||||
name=row["name"],
|
||||
tags=row.get("tags") or [],
|
||||
arg_keys=list((row.get("args") or {}).keys())
|
||||
if isinstance(row.get("args"), dict)
|
||||
else [],
|
||||
)
|
||||
for row in rows
|
||||
]
|
||||
selected = data.get("frameCoverRobot") or {}
|
||||
cover = selected.get("frameCover") or {}
|
||||
current_id = cover.get("id", selected.get("coverId"))
|
||||
current = next((row for row in catalog if row.id == current_id), None)
|
||||
robot = data.get("robot") or {}
|
||||
no_widget = (
|
||||
"frameCoverRobot" in data
|
||||
and data["frameCoverRobot"] is None
|
||||
and "frameCoverRobotId" in robot
|
||||
and robot["frameCoverRobotId"] is None
|
||||
)
|
||||
result = WidgetState(
|
||||
source="live",
|
||||
configured=True,
|
||||
catalog=catalog,
|
||||
current=current,
|
||||
current_verified=current is not None or no_widget,
|
||||
status="OK"
|
||||
if current
|
||||
else "NO_WIDGET"
|
||||
if no_widget
|
||||
else "CURRENT_UNVERIFIED",
|
||||
)
|
||||
except FlowError:
|
||||
raise
|
||||
except (
|
||||
requests.RequestException,
|
||||
ValueError,
|
||||
KeyError,
|
||||
TypeError,
|
||||
AttributeError,
|
||||
):
|
||||
raise FlowError(
|
||||
E.CLOUD_UNAVAILABLE, "Official widget query unavailable", 502
|
||||
) from None
|
||||
self._cached, self._cached_at = result, time.monotonic()
|
||||
return result
|
||||
__all__ = ["WidgetReader"]
|
||||
|
||||
Reference in New Issue
Block a user