Files
server-configs/vaultwarden_api.py
2026-02-13 22:24:27 +08:00

151 lines
4.6 KiB
Python

#!/usr/bin/env python3
"""
Vaultwarden API Wrapper
用于管理 bit.180356.xyz 的密码库
用法:
python3 vaultwarden_api.py list # 列出所有项目
python3 vaultwarden_api.py get <id> # 获取项目详情
python3 vaultwarden_api.py create <name> <username> <password> [notes] # 创建项目
python3 vaultwarden_api.py search <query> # 搜索项目
"""
import os
import json
import requests
import sys
import base64
# 配置
BASE_URL = "https://bit.180356.xyz"
EMAIL = "1803560007@qq.com" # 用户账号
CLIENT_ID = "user.447f249d-4b82-4ccf-83fa-df8f45e2413a"
CLIENT_SECRET = "NMdyXUfkZiTzdVUamQOYG0QcFDNzdJ"
class VaultwardenAPI:
def __init__(self):
self.token = None
self.device_id = "openclaw-" + str(hash(str(hash(str(hash(str()))))))[-8:]
def get_token(self):
"""获取访问令牌"""
url = f"{BASE_URL}/identity/connect/token"
data = {
"grant_type": "client_credentials",
"scope": "api",
"client_id": CLIENT_ID,
"client_secret": CLIENT_SECRET,
"device_identifier": self.device_id,
"device_type": "24",
"device_name": "openclaw"
}
response = requests.post(url, data=data)
if response.status_code == 200:
self.token = response.json().get("access_token")
return self.token
else:
print(f"获取令牌失败: {response.text}")
return None
def api_call(self, endpoint, method="GET", data=None):
"""API 调用"""
if not self.token:
self.get_token()
headers = {"Authorization": f"Bearer {self.token}"}
url = f"{BASE_URL}{endpoint}"
if method == "GET":
response = requests.get(url, headers=headers)
elif method == "POST":
headers["Content-Type"] = "application/json"
response = requests.post(url, headers=headers, json=data)
elif method == "DELETE":
response = requests.delete(url, headers=headers)
return response
def list_items(self):
"""列出所有项目 (ciphers)"""
response = self.api_call("/api/ciphers")
if response.status_code == 200:
return response.json().get("data", [])
return []
def get_item(self, item_id):
"""获取项目详情"""
response = self.api_call(f"/api/ciphers/{item_id}")
if response.status_code == 200:
return response.json()
return None
def create_item(self, name, username, password, notes="", folder_id=None):
"""创建新项目"""
data = {
"name": name,
"notes": notes,
"type": 1, # Login
"favorite": False,
"login": {
"username": username,
"password": password,
"totp": None
},
"fields": [],
"collectionIds": []
}
response = self.api_call("/api/ciphers", method="POST", data=data)
return response.status_code == 200
def search_items(self, query):
"""搜索项目"""
items = self.list_items()
return [item for item in items if query.lower() in item.get("name", "").lower()]
def main():
api = VaultwardenAPI()
if len(sys.argv) < 2:
print(__doc__)
return
command = sys.argv[1]
if command == "list":
items = api.list_items()
print(f"\n📋 项目列表 ({len(items)} 个):\n")
for item in items:
name = item.get("name", "Unknown")
item_id = item.get("id", "N/A")[:8]
print(f"{name} [{item_id}]")
elif command == "get" and len(sys.argv) > 2:
item = api.get_item(sys.argv[2])
if item:
print(f"\n📄 项目详情:\n")
print(json.dumps(item, indent=2, ensure_ascii=False))
elif command == "create" and len(sys.argv) > 4:
name = sys.argv[2]
username = sys.argv[3]
password = sys.argv[4]
notes = sys.argv[5] if len(sys.argv) > 5 else ""
success = api.create_item(name, username, password, notes)
if success:
print(f"\n✅ 创建成功: {name}")
else:
print(f"\n❌ 创建失败")
elif command == "search" and len(sys.argv) > 2:
results = api.search_items(sys.argv[2])
print(f"\n🔍 搜索结果 ({len(results)} 个):\n")
for item in results:
print(f"{item.get('name', 'Unknown')}")
if __name__ == "__main__":
main()