-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCloudflareManager.js
More file actions
119 lines (93 loc) · 3.38 KB
/
CloudflareManager.js
File metadata and controls
119 lines (93 loc) · 3.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import fetch from 'node-fetch';
export class CloudflareManager {
#apiToken;
#apiUrl = 'https://api.cloudflare.com/client/v4';
setApiToken(token) {
this.#apiToken = token;
}
async createDNSRecord(domain, subdomain, ip) {
const zoneId = await this.getZoneId(domain);
if (!zoneId) return false;
subdomain = subdomain.toLowerCase();
const recordName = subdomain === '@' ? domain :
subdomain === '*' ? `*.${domain}` :
subdomain === '*.*' ? `*.*.${domain}` :
`${subdomain}.${domain}`;
const existingRecord = await this.#findExistingRecord(zoneId, recordName);
const recordData = { type: 'A', name: recordName, content: ip, proxied: true };
const response = await this.#makeRequest(
existingRecord ? `zones/${zoneId}/dns_records/${existingRecord.id}` : `zones/${zoneId}/dns_records`,
existingRecord ? 'PUT' : 'POST',
recordData
);
return response?.success || false;
}
async getDomains() {
let result = [];
let page = 1;
while (true) {
const params = {
direction: 'desc',
per_page: 100,
page: page,
status: 'active'
};
const response = await this.#makeRequest('zones', 'GET', params);
if (!response?.success) {
console.error('Failed getting domains from Cloudflare:', response);
break;
}
result = [...result, ...response.result];
if (page >= (response.result_info?.total_pages || 0)) {
break;
}
page++;
}
return result.map(zone => zone.name);
}
async getZoneId(domain) {
const response = await this.#makeRequest('zones', 'GET', { name: domain });
return response?.success ? response.result[0]?.id : null;
}
async #makeRequest(endpoint, method = 'GET', data = null) {
const headers = {
'Authorization': `Bearer ${this.#apiToken}`,
'Content-Type': 'application/json'
};
const options = {
method,
headers
};
if (data && ['POST', 'PUT', 'PATCH'].includes(method)) {
options.body = JSON.stringify(data);
}
try {
const url = new URL(`${this.#apiUrl}/${endpoint}`);
if (method === 'GET' && data) {
Object.entries(data).forEach(([key, value]) =>
url.searchParams.append(key, value)
);
}
const response = await fetch(url, options);
return await response.json();
} catch (error) {
console.error('API request failed:', error);
return { success: false, error };
}
}
async #findExistingRecord(zoneId, name) {
const searchName = name.replace('*.', '');
const response = await this.#makeRequest(
`zones/${zoneId}/dns_records`,
'GET',
{ name: searchName }
);
if (!response?.success) {
return null;
}
return response.result.find(record =>
record.name === name ||
(record.name === `*.${searchName}` && name.includes('*'))
);
}
}