138
lib/ip-monitor-service.js
Archivo normal
138
lib/ip-monitor-service.js
Archivo normal
@@ -0,0 +1,138 @@
|
||||
import { readFileSync, writeFileSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
|
||||
const configPath = join(process.cwd(), 'config.json');
|
||||
|
||||
export class IPMonitorService {
|
||||
constructor() {
|
||||
this.loadConfig();
|
||||
}
|
||||
|
||||
loadConfig() {
|
||||
try {
|
||||
this.config = JSON.parse(readFileSync(configPath, 'utf8'));
|
||||
} catch (error) {
|
||||
console.error('Error loading config:', error);
|
||||
this.config = { ipProviders: [], currentIPs: {} };
|
||||
}
|
||||
}
|
||||
|
||||
async fetchIPFromProvider(provider, type = 'ipv4') {
|
||||
const url = type === 'ipv4' ? provider.ipv4Url : provider.ipv6Url;
|
||||
|
||||
try {
|
||||
const response = await fetch(url, {
|
||||
headers: {
|
||||
'User-Agent': 'Mozilla/5.0 (compatible; OVH-DNS-Manager/1.0)'
|
||||
}
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const text = await response.text();
|
||||
const ip = text.trim();
|
||||
|
||||
// Basic validation
|
||||
if (type === 'ipv4') {
|
||||
const ipv4Regex = /^(\d{1,3}\.){3}\d{1,3}$/;
|
||||
if (!ipv4Regex.test(ip)) {
|
||||
throw new Error('Invalid IPv4 format');
|
||||
}
|
||||
} else if (type === 'ipv6') {
|
||||
const ipv6Regex = /^([0-9a-fA-F]{0,4}:){2,7}[0-9a-fA-F]{0,4}$/;
|
||||
if (!ipv6Regex.test(ip)) {
|
||||
throw new Error('Invalid IPv6 format');
|
||||
}
|
||||
}
|
||||
|
||||
return ip;
|
||||
} catch (error) {
|
||||
console.error(`Error fetching ${type} from ${provider.name}:`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async getCurrentIPs() {
|
||||
const enabledProviders = this.config.ipProviders?.filter(p => p.enabled) || [];
|
||||
|
||||
if (enabledProviders.length === 0) {
|
||||
throw new Error('No IP providers enabled');
|
||||
}
|
||||
|
||||
let ipv4 = null;
|
||||
let ipv6 = null;
|
||||
|
||||
// Try each provider until we get valid IPs
|
||||
for (const provider of enabledProviders) {
|
||||
if (!ipv4) {
|
||||
try {
|
||||
ipv4 = await this.fetchIPFromProvider(provider, 'ipv4');
|
||||
} catch {
|
||||
console.error(`Failed to get IPv4 from ${provider.name}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (!ipv6) {
|
||||
try {
|
||||
ipv6 = await this.fetchIPFromProvider(provider, 'ipv6');
|
||||
} catch {
|
||||
console.error(`Failed to get IPv6 from ${provider.name}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (ipv4 && ipv6) break;
|
||||
}
|
||||
|
||||
// Update config with new IPs
|
||||
if (ipv4 || ipv6) {
|
||||
this.updateCurrentIPs({ ipv4, ipv6 });
|
||||
}
|
||||
|
||||
return { ipv4, ipv6 };
|
||||
}
|
||||
|
||||
updateCurrentIPs(ips) {
|
||||
try {
|
||||
this.config.currentIPs = {
|
||||
...this.config.currentIPs,
|
||||
...ips,
|
||||
lastUpdate: new Date().toISOString()
|
||||
};
|
||||
|
||||
writeFileSync(configPath, JSON.stringify(this.config, null, 2), 'utf8');
|
||||
} catch (error) {
|
||||
console.error('Error updating current IPs in config:', error);
|
||||
}
|
||||
}
|
||||
|
||||
getStoredIPs() {
|
||||
return this.config.currentIPs || { ipv4: null, ipv6: null, lastUpdate: null };
|
||||
}
|
||||
|
||||
async checkAndUpdateIPs() {
|
||||
try {
|
||||
const newIPs = await this.getCurrentIPs();
|
||||
const storedIPs = this.getStoredIPs();
|
||||
|
||||
const changed = {
|
||||
ipv4: newIPs.ipv4 && newIPs.ipv4 !== storedIPs.ipv4,
|
||||
ipv6: newIPs.ipv6 && newIPs.ipv6 !== storedIPs.ipv6
|
||||
};
|
||||
|
||||
return {
|
||||
changed: changed.ipv4 || changed.ipv6,
|
||||
newIPs,
|
||||
oldIPs: storedIPs,
|
||||
details: changed
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Error checking IPs:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const ipMonitorServiceInstance = new IPMonitorService();
|
||||
export default ipMonitorServiceInstance;
|
||||
200
lib/ovh-service.js
Archivo normal
200
lib/ovh-service.js
Archivo normal
@@ -0,0 +1,200 @@
|
||||
import ovh from '@ovhcloud/node-ovh';
|
||||
import { readFileSync, writeFileSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
|
||||
const configPath = join(process.cwd(), 'config.json');
|
||||
|
||||
export class OVHService {
|
||||
constructor() {
|
||||
this.clients = new Map();
|
||||
this.loadConfig();
|
||||
}
|
||||
|
||||
loadConfig() {
|
||||
try {
|
||||
const config = JSON.parse(readFileSync(configPath, 'utf8'));
|
||||
this.config = config;
|
||||
|
||||
// Initialize OVH clients for each account
|
||||
config.ovhAccounts.forEach(account => {
|
||||
if (account.appKey && account.appSecret && account.consumerKey) {
|
||||
this.clients.set(account.id, ovh({
|
||||
appKey: account.appKey,
|
||||
appSecret: account.appSecret,
|
||||
consumerKey: account.consumerKey,
|
||||
endpoint: account.endpoint || 'ovh-eu'
|
||||
}));
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error loading config:', error);
|
||||
this.config = { ovhAccounts: [], ipProviders: [], autoUpdate: { enabled: false }, currentIPs: {} };
|
||||
}
|
||||
}
|
||||
|
||||
getClientForDomain(domain) {
|
||||
// Find which account manages this domain
|
||||
for (const account of this.config.ovhAccounts) {
|
||||
if (account.domains && account.domains.includes(domain)) {
|
||||
return this.clients.get(account.id);
|
||||
}
|
||||
}
|
||||
// Return first available client as fallback
|
||||
return this.clients.values().next().value;
|
||||
}
|
||||
|
||||
async getAllDomains() {
|
||||
const allDomains = [];
|
||||
|
||||
for (const [accountId, client] of this.clients.entries()) {
|
||||
try {
|
||||
const domains = await client.requestPromised('GET', '/domain/zone');
|
||||
const account = this.config.ovhAccounts.find(acc => acc.id === accountId);
|
||||
|
||||
allDomains.push(...domains.map(domain => ({
|
||||
domain,
|
||||
accountId,
|
||||
accountName: account?.name || accountId
|
||||
})));
|
||||
} catch (error) {
|
||||
console.error(`Error fetching domains from account ${accountId}:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
return allDomains;
|
||||
}
|
||||
|
||||
async getDNSRecords(zoneName) {
|
||||
try {
|
||||
const client = this.getClientForDomain(zoneName);
|
||||
if (!client) {
|
||||
throw new Error('No OVH client configured for this domain');
|
||||
}
|
||||
|
||||
const recordIds = await client.requestPromised('GET', `/domain/zone/${zoneName}/record`);
|
||||
|
||||
const records = await Promise.all(
|
||||
recordIds.map(async (id) => {
|
||||
const record = await client.requestPromised('GET', `/domain/zone/${zoneName}/record/${id}`);
|
||||
return { ...record, id };
|
||||
})
|
||||
);
|
||||
|
||||
return records;
|
||||
} catch (error) {
|
||||
console.error(`Failed to fetch DNS records for ${zoneName}:`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async createDNSRecord(zoneName, recordData) {
|
||||
try {
|
||||
const client = this.getClientForDomain(zoneName);
|
||||
if (!client) {
|
||||
throw new Error('No OVH client configured for this domain');
|
||||
}
|
||||
|
||||
const record = await client.requestPromised('POST', `/domain/zone/${zoneName}/record`, recordData);
|
||||
await this.refreshZone(zoneName);
|
||||
|
||||
return record;
|
||||
} catch (error) {
|
||||
console.error(`Failed to create DNS record in ${zoneName}:`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async updateDNSRecord(zoneName, recordId, recordData) {
|
||||
try {
|
||||
const client = this.getClientForDomain(zoneName);
|
||||
if (!client) {
|
||||
throw new Error('No OVH client configured for this domain');
|
||||
}
|
||||
|
||||
const record = await client.requestPromised('PUT', `/domain/zone/${zoneName}/record/${recordId}`, recordData);
|
||||
await this.refreshZone(zoneName);
|
||||
|
||||
return record;
|
||||
} catch (error) {
|
||||
console.error(`Failed to update DNS record ${recordId} in ${zoneName}:`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async deleteDNSRecord(zoneName, recordId) {
|
||||
try {
|
||||
const client = this.getClientForDomain(zoneName);
|
||||
if (!client) {
|
||||
throw new Error('No OVH client configured for this domain');
|
||||
}
|
||||
|
||||
await client.requestPromised('DELETE', `/domain/zone/${zoneName}/record/${recordId}`);
|
||||
await this.refreshZone(zoneName);
|
||||
} catch (error) {
|
||||
console.error(`Failed to delete DNS record ${recordId} from ${zoneName}:`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async refreshZone(domain) {
|
||||
try {
|
||||
const client = this.getClientForDomain(domain);
|
||||
if (!client) {
|
||||
throw new Error('No OVH client configured for this domain');
|
||||
}
|
||||
|
||||
const result = await client.requestPromised('POST', `/domain/zone/${domain}/refresh`);
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error(`Failed to refresh DNS zone: ${domain}`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async bulkUpdateRecords(zoneName, recordIds, updateData) {
|
||||
const results = [];
|
||||
|
||||
for (const recordId of recordIds) {
|
||||
try {
|
||||
const result = await this.updateDNSRecord(zoneName, recordId, updateData);
|
||||
results.push({ recordId, success: true, result });
|
||||
} catch (error) {
|
||||
results.push({ recordId, success: false, error: error.message });
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
getConfig() {
|
||||
return this.config;
|
||||
}
|
||||
|
||||
saveConfig(newConfig) {
|
||||
try {
|
||||
writeFileSync(configPath, JSON.stringify(newConfig, null, 2), 'utf8');
|
||||
this.config = newConfig;
|
||||
|
||||
// Reinitialize clients
|
||||
this.clients.clear();
|
||||
newConfig.ovhAccounts.forEach(account => {
|
||||
if (account.appKey && account.appSecret && account.consumerKey) {
|
||||
this.clients.set(account.id, ovh({
|
||||
appKey: account.appKey,
|
||||
appSecret: account.appSecret,
|
||||
consumerKey: account.consumerKey,
|
||||
endpoint: account.endpoint || 'ovh-eu'
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Error saving config:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const ovhServiceInstance = new OVHService();
|
||||
export default ovhServiceInstance;
|
||||
Referencia en una nueva incidencia
Block a user