fix
This commit is contained in:
@@ -36,7 +36,7 @@ class Settings(BaseSettings):
|
|||||||
default_video_codec: str = "libx264"
|
default_video_codec: str = "libx264"
|
||||||
default_audio_codec: str = "aac"
|
default_audio_codec: str = "aac"
|
||||||
# cloud flare
|
# cloud flare
|
||||||
cloudflare_api_key: str = "dlGquMNiAX-S7SV9pXne7YGfdH_fEgq3TfIGgNcQ"
|
cloudflare_api_key: str = "hAiXy3jB-Lt5q-XiIV588lyvyH1c8FJaG3oieqeT"
|
||||||
cloudflare_url: str = "https://api.cloudflare.com/client/v4/"
|
cloudflare_url: str = "https://api.cloudflare.com/client/v4/"
|
||||||
cloudflare_account_id: str = "67720b647ff2b55cf37ba3ef9e677083"
|
cloudflare_account_id: str = "67720b647ff2b55cf37ba3ef9e677083"
|
||||||
cloudflare_kv_id: str = "995d7eff088547d7a7d8fea53e56115b"
|
cloudflare_kv_id: str = "995d7eff088547d7a7d8fea53e56115b"
|
||||||
|
|||||||
@@ -12,73 +12,315 @@ class Kv:
|
|||||||
self.cf_account_id = settings.cloudflare_account_id
|
self.cf_account_id = settings.cloudflare_account_id
|
||||||
self.cf_kv_api_token = settings.cloudflare_api_key
|
self.cf_kv_api_token = settings.cloudflare_api_key
|
||||||
self.cf_kv_id = settings.cloudflare_kv_id
|
self.cf_kv_id = settings.cloudflare_kv_id
|
||||||
|
self.base_url = f"https://api.cloudflare.com/client/v4/accounts/{self.cf_account_id}/storage/kv/namespaces/{self.cf_kv_id}"
|
||||||
def gets(self, keys: list[str]):
|
self.headers = {"Authorization": f"Bearer {self.cf_kv_api_token}"}
|
||||||
|
|
||||||
|
def get(self, key: str, default=None):
|
||||||
|
"""
|
||||||
|
获取单个键的值
|
||||||
|
|
||||||
|
Args:
|
||||||
|
key: 要获取的键
|
||||||
|
default: 如果键不存在时返回的默认值
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
键对应的值,如果不存在则返回default
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
with httpx.Client() as client:
|
with httpx.Client() as client:
|
||||||
response = client.post(
|
response = client.get(
|
||||||
f"https://api.cloudflare.com/client/v4/accounts/{self.cf_account_id}/storage/kv/namespaces/{self.cf_kv_id}/bulk/get",
|
f"{self.base_url}/values/{key}",
|
||||||
headers={"Authorization": f"Bearer {self.cf_kv_api_token}"},
|
headers=self.headers
|
||||||
json={
|
|
||||||
"keys": keys,
|
|
||||||
"type": "json"
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
if response.status_code == 404:
|
||||||
|
return default
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
|
return response.text
|
||||||
except httpx.RequestError as e:
|
except httpx.RequestError as e:
|
||||||
logger.error(f"An error occurred while put kv to cloudflare")
|
logger.error(f"An error occurred while getting key '{key}' from cloudflare: {e}")
|
||||||
raise e
|
raise e
|
||||||
except httpx.HTTPStatusError as e:
|
except httpx.HTTPStatusError as e:
|
||||||
logger.error(f"HTTP error occurred while get kv from cloudflare {str(e)}")
|
if e.response.status_code == 404:
|
||||||
|
return default
|
||||||
|
logger.error(f"HTTP error occurred while getting key '{key}' from cloudflare: {e}")
|
||||||
raise e
|
raise e
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"An unexpected error occurred: {str(e)}")
|
logger.error(f"An unexpected error occurred while getting key '{key}': {e}")
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
def sets(self, caches: Dict[str, str]):
|
def set(self, key: str, value: str):
|
||||||
|
"""
|
||||||
|
设置单个键值对
|
||||||
|
|
||||||
|
Args:
|
||||||
|
key: 键名
|
||||||
|
value: 值
|
||||||
|
expiration_ttl: TTL过期时间(秒)
|
||||||
|
expiration: 绝对过期时间(Unix时间戳)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
操作结果
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
with httpx.Client() as client:
|
with httpx.Client() as client:
|
||||||
|
params = {}
|
||||||
|
|
||||||
response = client.put(
|
response = client.put(
|
||||||
f"https://api.cloudflare.com/client/v4/accounts/{self.cf_account_id}/storage/kv/namespaces/{self.cf_kv_id}/bulk",
|
f"{self.base_url}/values/{key}",
|
||||||
headers={"Authorization": f"Bearer {self.cf_kv_api_token}"},
|
headers=self.headers,
|
||||||
json=[
|
params=params,
|
||||||
{
|
content=value
|
||||||
"based64": False,
|
|
||||||
"key": key,
|
|
||||||
"value": value,
|
|
||||||
}
|
|
||||||
for (key, value) in caches.items()
|
|
||||||
]
|
|
||||||
)
|
)
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
|
return response.json() if response.text else {"success": True}
|
||||||
except httpx.RequestError as e:
|
except httpx.RequestError as e:
|
||||||
logger.error(f"An error occurred while put kv to cloudflare")
|
logger.error(f"An error occurred while setting key '{key}' to cloudflare: {e}")
|
||||||
raise e
|
raise e
|
||||||
except httpx.HTTPStatusError as e:
|
except httpx.HTTPStatusError as e:
|
||||||
logger.error(f"HTTP error occurred while get kv from cloudflare {str(e)}")
|
logger.error(f"HTTP error occurred while setting key '{key}' to cloudflare: {e}")
|
||||||
raise e
|
raise e
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"An unexpected error occurred: {str(e)}")
|
logger.error(f"An unexpected error occurred while setting key '{key}': {e}")
|
||||||
|
raise e
|
||||||
|
|
||||||
|
def remove(self, key: str):
|
||||||
|
"""
|
||||||
|
删除单个键
|
||||||
|
|
||||||
|
Args:
|
||||||
|
key: 要删除的键名
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
操作结果
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
with httpx.Client() as client:
|
||||||
|
response = client.delete(
|
||||||
|
f"{self.base_url}/values/{key}",
|
||||||
|
headers=self.headers
|
||||||
|
)
|
||||||
|
if response.status_code == 404:
|
||||||
|
return {"success": True, "message": "Key not found"}
|
||||||
|
response.raise_for_status()
|
||||||
|
return response.json() if response.text else {"success": True}
|
||||||
|
except httpx.RequestError as e:
|
||||||
|
logger.error(f"An error occurred while removing key '{key}' from cloudflare: {e}")
|
||||||
|
raise e
|
||||||
|
except httpx.HTTPStatusError as e:
|
||||||
|
if e.response.status_code == 404:
|
||||||
|
return {"success": True, "message": "Key not found"}
|
||||||
|
logger.error(f"HTTP error occurred while removing key '{key}' from cloudflare: {e}")
|
||||||
|
raise e
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"An unexpected error occurred while removing key '{key}': {e}")
|
||||||
|
raise e
|
||||||
|
|
||||||
|
def sets(self, caches: Dict[str, str]):
|
||||||
|
"""
|
||||||
|
批量设置多个键值对
|
||||||
|
|
||||||
|
Args:
|
||||||
|
caches: 包含键值对的字典
|
||||||
|
expiration_ttl: TTL过期时间(秒)
|
||||||
|
expiration: 绝对过期时间(Unix时间戳)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
操作结果
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
with httpx.Client() as client:
|
||||||
|
bulk_data = []
|
||||||
|
for key, value in caches.items():
|
||||||
|
item = {
|
||||||
|
"base64": False,
|
||||||
|
"key": key,
|
||||||
|
"value": value,
|
||||||
|
}
|
||||||
|
bulk_data.append(item)
|
||||||
|
|
||||||
|
response = client.put(
|
||||||
|
f"{self.base_url}/bulk",
|
||||||
|
headers=self.headers,
|
||||||
|
json=bulk_data
|
||||||
|
)
|
||||||
|
response.raise_for_status()
|
||||||
|
return response.json()
|
||||||
|
except httpx.RequestError as e:
|
||||||
|
logger.error(f"An error occurred while bulk setting keys to cloudflare: {e}")
|
||||||
|
raise e
|
||||||
|
except httpx.HTTPStatusError as e:
|
||||||
|
logger.error(f"HTTP error occurred while bulk setting keys to cloudflare: {e}")
|
||||||
|
raise e
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"An unexpected error occurred while bulk setting keys: {e}")
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
def remove(self, keys: list[str]):
|
def removes(self, keys: list[str]):
|
||||||
with httpx.Client() as client:
|
"""
|
||||||
try:
|
批量删除多个键
|
||||||
|
|
||||||
|
Args:
|
||||||
|
keys: 要删除的键列表
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
操作结果
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
with httpx.Client() as client:
|
||||||
response = client.post(
|
response = client.post(
|
||||||
f"https://api.cloudflare.com/client/v4/accounts/{self.cf_account_id}/storage/kv/namespaces/{self.cf_kv_id}/bulk/delete",
|
f"{self.base_url}/bulk/delete",
|
||||||
headers={"Authorization": f"Bearer {self.cf_kv_api_token}"},
|
headers=self.headers,
|
||||||
json=keys
|
json=keys
|
||||||
)
|
)
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
except httpx.RequestError as e:
|
return response.json()
|
||||||
logger.error(f"An error occurred while put kv to cloudflare")
|
except httpx.RequestError as e:
|
||||||
raise e
|
logger.error(f"An error occurred while bulk removing keys from cloudflare: {e}")
|
||||||
except httpx.HTTPStatusError as e:
|
raise e
|
||||||
logger.error(f"HTTP error occurred while get kv from cloudflare {str(e)}")
|
except httpx.HTTPStatusError as e:
|
||||||
raise e
|
logger.error(f"HTTP error occurred while bulk removing keys from cloudflare: {e}")
|
||||||
except Exception as e:
|
raise e
|
||||||
logger.error(f"An unexpected error occurred: {str(e)}")
|
except Exception as e:
|
||||||
raise e
|
logger.error(f"An unexpected error occurred while bulk removing keys: {e}")
|
||||||
|
raise e
|
||||||
|
|
||||||
|
def exists(self, key: str) -> bool:
|
||||||
|
"""
|
||||||
|
检查键是否存在
|
||||||
|
|
||||||
|
Args:
|
||||||
|
key: 要检查的键名
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
如果键存在返回True,否则返回False
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
with httpx.Client() as client:
|
||||||
|
response = client.get(
|
||||||
|
f"{self.base_url}/values/{key}",
|
||||||
|
headers=self.headers
|
||||||
|
)
|
||||||
|
return response.status_code == 200
|
||||||
|
except httpx.HTTPStatusError as e:
|
||||||
|
if e.response.status_code == 404:
|
||||||
|
return False
|
||||||
|
raise e
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def list_keys(self, prefix: str = None, limit: int = 1000, cursor: str = None):
|
||||||
|
"""
|
||||||
|
列出KV存储中的键
|
||||||
|
|
||||||
|
Args:
|
||||||
|
prefix: 键名前缀过滤
|
||||||
|
limit: 返回的最大键数量(默认1000)
|
||||||
|
cursor: 分页游标
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
包含键列表和分页信息的字典
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
with httpx.Client() as client:
|
||||||
|
params = {"limit": limit}
|
||||||
|
if prefix:
|
||||||
|
params["prefix"] = prefix
|
||||||
|
if cursor:
|
||||||
|
params["cursor"] = cursor
|
||||||
|
|
||||||
|
response = client.get(
|
||||||
|
f"{self.base_url}/keys",
|
||||||
|
headers=self.headers,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
|
response.raise_for_status()
|
||||||
|
return response.json()
|
||||||
|
except httpx.RequestError as e:
|
||||||
|
logger.error(f"An error occurred while listing keys from cloudflare: {e}")
|
||||||
|
raise e
|
||||||
|
except httpx.HTTPStatusError as e:
|
||||||
|
logger.error(f"HTTP error occurred while listing keys from cloudflare: {e}")
|
||||||
|
raise e
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"An unexpected error occurred while listing keys: {e}")
|
||||||
|
raise e
|
||||||
|
|
||||||
|
def get_metadata(self, key: str):
|
||||||
|
"""
|
||||||
|
获取键的元数据
|
||||||
|
|
||||||
|
Args:
|
||||||
|
key: 键名
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
键的元数据信息
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
with httpx.Client() as client:
|
||||||
|
response = client.get(
|
||||||
|
f"{self.base_url}/metadata/{key}",
|
||||||
|
headers=self.headers
|
||||||
|
)
|
||||||
|
if response.status_code == 404:
|
||||||
|
return None
|
||||||
|
response.raise_for_status()
|
||||||
|
return response.json()
|
||||||
|
except httpx.RequestError as e:
|
||||||
|
logger.error(f"An error occurred while getting metadata for key '{key}' from cloudflare: {e}")
|
||||||
|
raise e
|
||||||
|
except httpx.HTTPStatusError as e:
|
||||||
|
if e.response.status_code == 404:
|
||||||
|
return None
|
||||||
|
logger.error(f"HTTP error occurred while getting metadata for key '{key}' from cloudflare: {e}")
|
||||||
|
raise e
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"An unexpected error occurred while getting metadata for key '{key}': {e}")
|
||||||
|
raise e
|
||||||
|
|
||||||
|
def clear_all(self, prefix: str = None):
|
||||||
|
"""
|
||||||
|
清空所有键(危险操作!)
|
||||||
|
|
||||||
|
Args:
|
||||||
|
prefix: 如果提供,只删除指定前缀的键
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
操作结果
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# 首先获取所有键
|
||||||
|
all_keys = []
|
||||||
|
cursor = None
|
||||||
|
|
||||||
|
while True:
|
||||||
|
result = self.list_keys(prefix=prefix, limit=1000, cursor=cursor)
|
||||||
|
keys_data = result.get("result", [])
|
||||||
|
|
||||||
|
if not keys_data:
|
||||||
|
break
|
||||||
|
|
||||||
|
# 提取键名
|
||||||
|
for key_info in keys_data:
|
||||||
|
if isinstance(key_info, dict):
|
||||||
|
all_keys.append(key_info.get("name"))
|
||||||
|
else:
|
||||||
|
all_keys.append(str(key_info))
|
||||||
|
|
||||||
|
# 检查是否有更多数据
|
||||||
|
result_info = result.get("result_info", {})
|
||||||
|
cursor = result_info.get("cursor")
|
||||||
|
if not cursor:
|
||||||
|
break
|
||||||
|
|
||||||
|
# 批量删除
|
||||||
|
if all_keys:
|
||||||
|
return self.removes(all_keys)
|
||||||
|
else:
|
||||||
|
return {"success": True, "message": "No keys to delete"}
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"An error occurred while clearing keys: {e}")
|
||||||
|
raise e
|
||||||
|
|
||||||
|
|
||||||
kv = Kv()
|
kv = Kv()
|
||||||
Reference in New Issue
Block a user