@tiahui/anitorrent-cli
Version:
CLI tool for video management with PeerTube and Storj S3
220 lines (187 loc) • 6.84 kB
JavaScript
const fs = require('fs').promises;
const path = require('path');
const os = require('os');
class ConfigManager {
constructor(configFile = null) {
this.globalConfigDir = this.getGlobalConfigDir();
this.configFile = configFile || path.join(this.globalConfigDir, 'config.json');
this.tokenFile = path.join(this.globalConfigDir, 'peertube-token.json');
this.config = {};
this.loadConfigSync();
}
getGlobalConfigDir() {
const homeDir = os.homedir();
let configDir;
if (process.platform === 'win32') {
configDir = path.join(homeDir, 'AppData', 'Roaming', 'anitorrent-cli');
} else {
configDir = path.join(homeDir, '.config', 'anitorrent-cli');
}
return configDir;
}
async ensureConfigDir() {
try {
await fs.mkdir(this.globalConfigDir, { recursive: true });
} catch (error) {
if (error.code !== 'EEXIST') {
throw error;
}
}
}
loadConfigSync(customConfigFile = null) {
const configPath = customConfigFile || this.configFile;
try {
const fsSync = require('fs');
const configData = fsSync.readFileSync(configPath, 'utf8');
this.config = JSON.parse(configData);
} catch (error) {
if (customConfigFile) {
throw new Error(`Config file not found: ${configPath}`);
}
this.config = {};
}
}
async loadConfig(customConfigFile = null) {
const configPath = customConfigFile || this.configFile;
try {
const configData = await fs.readFile(configPath, 'utf8');
this.config = JSON.parse(configData);
} catch (error) {
if (customConfigFile) {
throw new Error(`Config file not found: ${configPath}`);
}
this.config = {};
}
}
async saveConfig() {
await this.ensureConfigDir();
await fs.writeFile(this.configFile, JSON.stringify(this.config, null, 2));
}
get(key, defaultValue = null) {
return this.config[key] || defaultValue;
}
set(key, value) {
this.config[key] = value;
}
getRequired(key) {
const value = this.config[key];
if (!value) {
throw new Error(`Required configuration variable ${key} is not set`);
}
return value;
}
async exists() {
try {
await fs.access(this.configFile);
return true;
} catch {
return false;
}
}
async createTemplate() {
await this.ensureConfigDir();
const template = {
R2_ACCESS_KEY_ID: 'your_access_key_id',
R2_SECRET_ACCESS_KEY: 'your_secret_access_key',
R2_ENDPOINT: 'https://your-account-id.r2.cloudflarestorage.com',
R2_BUCKET_NAME: 'your_bucket_name',
R2_PUBLIC_DOMAIN: 'https://cdn.anitorrent.com',
PEERTUBE_USERNAME: 'your_username',
PEERTUBE_PASSWORD: 'your_password',
PEERTUBE_API_URL: 'https://peertube.anitorrent.com/api/v1',
DEFAULT_CHANNEL_ID: '',
DEFAULT_PRIVACY_LEVEL: '5',
DEFAULT_VIDEO_PASSWORD: 'AniTorrent108',
CLAUDE_API_KEY: 'your_claude_api_key',
ANITORRENT_API_KEY: 'your_anitorrent_api_key'
};
this.config = template;
await this.saveConfig();
}
validateRequired() {
const requiredVars = [
'R2_ACCESS_KEY_ID',
'R2_SECRET_ACCESS_KEY',
'R2_ENDPOINT',
'R2_BUCKET_NAME',
'PEERTUBE_USERNAME',
'PEERTUBE_PASSWORD'
];
const missing = requiredVars.filter(varName => !this.config[varName] || this.config[varName].startsWith('your_'));
if (missing.length > 0) {
throw new Error(`Missing required configuration variables: ${missing.join(', ')}`);
}
return true;
}
getR2Config() {
return {
accessKeyId: this.getRequired('R2_ACCESS_KEY_ID'),
secretAccessKey: this.getRequired('R2_SECRET_ACCESS_KEY'),
endpoint: this.getRequired('R2_ENDPOINT'),
bucketName: this.getRequired('R2_BUCKET_NAME'),
publicDomain: this.get('R2_PUBLIC_DOMAIN', 'https://cdn.anitorrent.com')
};
}
getPeerTubeConfig() {
return {
apiUrl: this.get('PEERTUBE_API_URL', 'https://peertube.anitorrent.com/api/v1'),
username: this.getRequired('PEERTUBE_USERNAME'),
password: this.getRequired('PEERTUBE_PASSWORD'),
tokenFile: this.tokenFile
};
}
getDefaults() {
return {
channelId: this.get('DEFAULT_CHANNEL_ID') ? parseInt(this.get('DEFAULT_CHANNEL_ID')) : null,
privacy: parseInt(this.get('DEFAULT_PRIVACY_LEVEL', '5')),
videoPassword: this.get('DEFAULT_VIDEO_PASSWORD') || null
};
}
async getDefaultChannelId() {
const configuredChannelId = this.get('DEFAULT_CHANNEL_ID');
if (configuredChannelId) {
return parseInt(configuredChannelId);
}
const PeerTubeService = require('../services/peertube-service');
const peertubeService = new PeerTubeService(this.getPeerTubeConfig());
try {
const userInfo = await peertubeService.getCurrentUser();
if (userInfo.videoChannels && userInfo.videoChannels.length > 0) {
return userInfo.videoChannels[0].id;
}
} catch (error) {
throw new Error('Unable to determine default channel ID. Please configure DEFAULT_CHANNEL_ID');
}
throw new Error('No channels found for this user');
}
showConfig(hideSensitive = true) {
const config = { ...this.config };
if (hideSensitive) {
const sensitiveKeys = [
'R2_ACCESS_KEY_ID', 'R2_SECRET_ACCESS_KEY',
'PEERTUBE_PASSWORD', 'DEFAULT_VIDEO_PASSWORD', 'CLAUDE_API_KEY', 'ANITORRENT_API_KEY'
];
sensitiveKeys.forEach(key => {
if (config[key]) {
config[key] = '***HIDDEN***';
}
});
}
return config;
}
getTranslationConfig() {
return {
apiKey: this.get('CLAUDE_API_KEY')
};
}
getAniTorrentConfig() {
return {
apiKey: this.get('ANITORRENT_API_KEY'),
apiUrl: 'https://api.anitorrent.com'
};
}
getConfigPath() {
return this.configFile;
}
}
module.exports = ConfigManager;