#!/usr/bin/env python3 """ Vaultwarden API Wrapper 用于管理 bit.180356.xyz 的密码库 用法: python3 vaultwarden_api.py list # 列出所有项目 python3 vaultwarden_api.py get # 获取项目详情 python3 vaultwarden_api.py create [notes] # 创建项目 python3 vaultwarden_api.py search # 搜索项目 """ 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()