initial: 七牛云上传 OpenClaw Skill
功能特性: - 支持 /upload, /u 命令上传文件到七牛云 - 支持 /qiniu-config 配置管理 - 支持飞书卡片交互 - 支持指定上传路径和存储桶 - 自动刷新 CDN 缓存 - 支持文件覆盖上传 包含组件: - OpenClaw 处理器 (openclaw-processor.js) - 独立监听器 (scripts/feishu-listener.js) - 核心上传脚本 (scripts/upload-to-qiniu.js) - 部署脚本 (deploy.sh) - 完整文档 部署方式: 1. 复制 skill 到 ~/.openclaw/workspace/skills/ 2. 配置 ~/.openclaw/credentials/qiniu-config.json 3. 重启 OpenClaw Gateway
This commit is contained in:
166
scripts/update-bucket-setting.js
Normal file
166
scripts/update-bucket-setting.js
Normal file
@@ -0,0 +1,166 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* 七牛云存储桶设置更新脚本
|
||||
*
|
||||
* 用途:更新存储桶的防覆盖等设置
|
||||
*
|
||||
* 用法:
|
||||
* node update-bucket-setting.js <bucket-name> <setting> <value>
|
||||
*
|
||||
* 示例:
|
||||
* node update-bucket-setting.js mybucket noOverwrite 0 # 允许覆盖
|
||||
* node update-bucket-setting.js mybucket noOverwrite 1 # 禁止覆盖
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const crypto = require('crypto');
|
||||
const https = require('https');
|
||||
const http = require('http');
|
||||
|
||||
const DEFAULT_CONFIG_PATH = path.join(process.env.HOME || process.env.USERPROFILE, '.openclaw/credentials/qiniu-config.json');
|
||||
|
||||
function loadConfig() {
|
||||
if (!fs.existsSync(DEFAULT_CONFIG_PATH)) {
|
||||
throw new Error(`配置文件不存在:${DEFAULT_CONFIG_PATH}`);
|
||||
}
|
||||
return JSON.parse(fs.readFileSync(DEFAULT_CONFIG_PATH, 'utf-8'));
|
||||
}
|
||||
|
||||
function hmacSha1(data, secret) {
|
||||
return crypto.createHmac('sha1', secret).update(data).digest();
|
||||
}
|
||||
|
||||
function urlSafeBase64(data) {
|
||||
return Buffer.from(data).toString('base64')
|
||||
.replace(/\+/g, '-')
|
||||
.replace(/\//g, '_');
|
||||
}
|
||||
|
||||
function generateAccessToken(accessKey, secretKey, method, path, body = '') {
|
||||
const host = 'api.qiniu.com';
|
||||
const contentType = 'application/json';
|
||||
|
||||
const signData = `${method} ${path}\nHost: ${host}\nContent-Type: ${contentType}\n\n${body}`;
|
||||
const signature = hmacSha1(signData, secretKey);
|
||||
const encodedSign = urlSafeBase64(signature);
|
||||
|
||||
return `Qiniu ${accessKey}:${encodedSign}`;
|
||||
}
|
||||
|
||||
function httpRequest(url, options, body = null) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const protocol = url.startsWith('https') ? https : http;
|
||||
|
||||
const req = protocol.request(url, options, (res) => {
|
||||
let data = '';
|
||||
res.on('data', chunk => data += chunk);
|
||||
res.on('end', () => {
|
||||
try {
|
||||
const json = JSON.parse(data);
|
||||
resolve({ status: res.statusCode, data: json });
|
||||
} catch (e) {
|
||||
resolve({ status: res.statusCode, data: data });
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
req.on('error', reject);
|
||||
|
||||
if (body) {
|
||||
req.write(body);
|
||||
}
|
||||
|
||||
req.end();
|
||||
});
|
||||
}
|
||||
|
||||
async function updateBucketSetting(bucketName, setting, value) {
|
||||
const config = loadConfig();
|
||||
const bucketConfig = config.buckets['default'];
|
||||
|
||||
if (!bucketConfig) {
|
||||
throw new Error(`默认存储桶配置不存在`);
|
||||
}
|
||||
|
||||
const { accessKey, secretKey, bucket } = bucketConfig;
|
||||
|
||||
console.log('🔄 更新存储桶设置...\n');
|
||||
console.log(`存储桶:${bucket}`);
|
||||
console.log(`设置项:${setting}`);
|
||||
console.log(`值:${value}`);
|
||||
console.log('');
|
||||
|
||||
// 七牛云存储桶设置 API
|
||||
// 文档:https://developer.qiniu.com/kodo/api/1313/bucket-settings-update
|
||||
const updateUrl = `https://api.qiniu.com/buckets/${bucket}/settings`;
|
||||
|
||||
const body = JSON.stringify({
|
||||
[setting]: value === '1' || value === 'true' ? 1 : 0
|
||||
});
|
||||
|
||||
const accessToken = generateAccessToken(accessKey, secretKey, 'PUT', `/buckets/${bucket}/settings`, body);
|
||||
|
||||
const options = {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Host': 'api.qiniu.com',
|
||||
'Content-Type': 'application/json',
|
||||
'Content-Length': body.length,
|
||||
'Authorization': accessToken
|
||||
}
|
||||
};
|
||||
|
||||
console.log('📤 发送更新请求...');
|
||||
const result = await httpRequest(updateUrl, options, body);
|
||||
|
||||
if (result.status !== 200) {
|
||||
console.error('❌ 更新失败:', result.data);
|
||||
console.log('\n可能原因:');
|
||||
console.log('1. AccessKey/SecretKey 权限不足,需要存储桶管理权限');
|
||||
console.log('2. 存储桶名称不正确');
|
||||
console.log('3. 设置项不支持通过 API 修改');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('✅ 设置已更新成功!\n');
|
||||
console.log('提示:设置可能需要几分钟生效,请稍后重试上传。');
|
||||
}
|
||||
|
||||
function printUsage() {
|
||||
console.log(`
|
||||
用法:node update-bucket-setting.js <bucket-name> <setting> <value>
|
||||
|
||||
设置项:
|
||||
noOverwrite - 防覆盖设置 (0=允许覆盖,1=禁止覆盖)
|
||||
|
||||
示例:
|
||||
node update-bucket-setting.js mybucket noOverwrite 0 # 允许覆盖
|
||||
node update-bucket-setting.js mybucket noOverwrite 1 # 禁止覆盖
|
||||
`);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const args = process.argv.slice(2);
|
||||
|
||||
if (args.length < 3) {
|
||||
printUsage();
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const [bucketName, setting, value] = args;
|
||||
|
||||
try {
|
||||
await updateBucketSetting(bucketName, setting, value);
|
||||
} catch (error) {
|
||||
console.error('❌ 错误:', error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
main();
|
||||
}
|
||||
|
||||
module.exports = { updateBucketSetting };
|
||||
Reference in New Issue
Block a user