diff --git a/src/client.test.ts b/src/client.test.ts
index 34b373c2..ce13bcfd 100644
--- a/src/client.test.ts
+++ b/src/client.test.ts
@@ -2,26 +2,23 @@ import { jest } from '@jest/globals';
import nock from 'nock';
import { Blob } from 'node-fetch';
import { Client } from './client';
-import type { Host } from './config';
+import { Host } from './config';
import { Config } from './config';
import { ErrorNotification } from './notify';
describe('Client', () => {
- const host: Host = {
- baseUrl: 'http://10.0.0.2',
- password: 'mypassword'
- };
+ const host = new Host('http://10.0.0.2', 'mypassword');
const createClient = async () => {
- nock(host.baseUrl).get('/admin/index.php?login').reply(200);
- nock(host.baseUrl)
+ nock(host.fullUrl).get('/admin/index.php?login').reply(200);
+ nock(host.fullUrl)
.post('/admin/index.php?login')
.reply(
200,
'
abcdefgijklmnopqrstuvwxyzabcdefgijklmnopqrst
'
);
- return { teleporter: nock(host.baseUrl), client: await Client.create(host) };
+ return { teleporter: nock(host.fullUrl), client: await Client.create(host) };
};
beforeEach(() => {
@@ -30,8 +27,8 @@ describe('Client', () => {
describe('create', () => {
test('should throw error if status code is not ok', async () => {
- const initialRequest = nock(host.baseUrl).get('/admin/index.php?login').reply(200);
- const loginRequest = nock(host.baseUrl).post('/admin/index.php?login').reply(500);
+ const initialRequest = nock(host.fullUrl).get('/admin/index.php?login').reply(200);
+ const loginRequest = nock(host.fullUrl).post('/admin/index.php?login').reply(500);
const expectError = expect(Client.create(host)).rejects;
@@ -50,8 +47,8 @@ describe('Client', () => {
});
test('should throw error if no token is present', async () => {
- const initialRequest = nock(host.baseUrl).get('/admin/index.php?login').reply(200);
- const loginRequest = nock(host.baseUrl).post('/admin/index.php?login').reply(200);
+ const initialRequest = nock(host.fullUrl).get('/admin/index.php?login').reply(200);
+ const loginRequest = nock(host.fullUrl).post('/admin/index.php?login').reply(200);
const expectError = expect(Client.create(host)).rejects;
@@ -69,8 +66,8 @@ describe('Client', () => {
});
test('should throw error if token is in incorrect format', async () => {
- const initialRequest = nock(host.baseUrl).get('/admin/index.php?login').reply(200);
- const loginRequest = nock(host.baseUrl)
+ const initialRequest = nock(host.fullUrl).get('/admin/index.php?login').reply(200);
+ const loginRequest = nock(host.fullUrl)
.post('/admin/index.php?login')
.reply(200, 'abcdef
');
@@ -90,8 +87,8 @@ describe('Client', () => {
});
test('should return client', async () => {
- const initialRequest = nock(host.baseUrl).get('/admin/index.php?login').reply(200);
- const loginRequest = nock(host.baseUrl)
+ const initialRequest = nock(host.fullUrl).get('/admin/index.php?login').reply(200);
+ const loginRequest = nock(host.fullUrl)
.post('/admin/index.php?login')
.reply(
200,
@@ -237,18 +234,18 @@ describe('Client', () => {
.reply(
200,
'Processed adlist (14 entries)
\n' +
- 'Processed adlist group assignments (13 entries)
\n' +
- 'Processed blacklist (exact) (0 entries)
\n' +
- 'Processed blacklist (regex) (3 entries)
\n' +
- 'Processed client (8 entries)
\n' +
- 'Processed client group assignments (16 entries)
\n' +
- 'Processed local DNS records (41 entries)
\n' +
- 'Processed domain_audit (0 entries)
\n' +
- 'Processed black-/whitelist group assignments (10 entries)
\n' +
- 'Processed group (3 entries)
\n' +
- 'Processed whitelist (exact) (4 entries)
\n' +
- 'Processed whitelist (regex) (0 entries)
\n' +
- 'OK'
+ 'Processed adlist group assignments (13 entries)
\n' +
+ 'Processed blacklist (exact) (0 entries)
\n' +
+ 'Processed blacklist (regex) (3 entries)
\n' +
+ 'Processed client (8 entries)
\n' +
+ 'Processed client group assignments (16 entries)
\n' +
+ 'Processed local DNS records (41 entries)
\n' +
+ 'Processed domain_audit (0 entries)
\n' +
+ 'Processed black-/whitelist group assignments (10 entries)
\n' +
+ 'Processed group (3 entries)
\n' +
+ 'Processed whitelist (exact) (4 entries)
\n' +
+ 'Processed whitelist (regex) (0 entries)
\n' +
+ 'OK'
);
teleporter
.get('/admin/scripts/pi-hole/php/gravity.sh.php', undefined)
@@ -276,18 +273,18 @@ describe('Client', () => {
.reply(
200,
'Processed adlist (14 entries)
\n' +
- 'Processed adlist group assignments (13 entries)
\n' +
- 'Processed blacklist (exact) (0 entries)
\n' +
- 'Processed blacklist (regex) (3 entries)
\n' +
- 'Processed client (8 entries)
\n' +
- 'Processed client group assignments (16 entries)
\n' +
- 'Processed local DNS records (41 entries)
\n' +
- 'Processed domain_audit (0 entries)
\n' +
- 'Processed black-/whitelist group assignments (10 entries)
\n' +
- 'Processed group (3 entries)
\n' +
- 'Processed whitelist (exact) (4 entries)
\n' +
- 'Processed whitelist (regex) (0 entries)
\n' +
- 'OK'
+ 'Processed adlist group assignments (13 entries)
\n' +
+ 'Processed blacklist (exact) (0 entries)
\n' +
+ 'Processed blacklist (regex) (3 entries)
\n' +
+ 'Processed client (8 entries)
\n' +
+ 'Processed client group assignments (16 entries)
\n' +
+ 'Processed local DNS records (41 entries)
\n' +
+ 'Processed domain_audit (0 entries)
\n' +
+ 'Processed black-/whitelist group assignments (10 entries)
\n' +
+ 'Processed group (3 entries)
\n' +
+ 'Processed whitelist (exact) (4 entries)
\n' +
+ 'Processed whitelist (regex) (0 entries)
\n' +
+ 'OK'
);
teleporter
.get('/admin/scripts/pi-hole/php/gravity.sh.php', undefined)
@@ -336,18 +333,18 @@ describe('Client', () => {
.reply(
200,
'Processed adlist (14 entries)
\n' +
- 'Processed adlist group assignments (13 entries)
\n' +
- 'Processed blacklist (exact) (0 entries)
\n' +
- 'Processed blacklist (regex) (3 entries)
\n' +
- 'Processed client (8 entries)
\n' +
- 'Processed client group assignments (16 entries)
\n' +
- 'Processed local DNS records (41 entries)
\n' +
- 'Processed domain_audit (0 entries)
\n' +
- 'Processed black-/whitelist group assignments (10 entries)
\n' +
- 'Processed group (3 entries)
\n' +
- 'Processed whitelist (exact) (4 entries)
\n' +
- 'Processed whitelist (regex) (0 entries)
\n' +
- 'OK'
+ 'Processed adlist group assignments (13 entries)
\n' +
+ 'Processed blacklist (exact) (0 entries)
\n' +
+ 'Processed blacklist (regex) (3 entries)
\n' +
+ 'Processed client (8 entries)
\n' +
+ 'Processed client group assignments (16 entries)
\n' +
+ 'Processed local DNS records (41 entries)
\n' +
+ 'Processed domain_audit (0 entries)
\n' +
+ 'Processed black-/whitelist group assignments (10 entries)
\n' +
+ 'Processed group (3 entries)
\n' +
+ 'Processed whitelist (exact) (4 entries)
\n' +
+ 'Processed whitelist (regex) (0 entries)
\n' +
+ 'OK'
);
const result = await client.uploadBackup(backup);
diff --git a/src/client.ts b/src/client.ts
index 5d049094..5448fd95 100644
--- a/src/client.ts
+++ b/src/client.ts
@@ -18,14 +18,14 @@ export class Client {
private fetch: NodeFetchCookie,
private host: Host,
private token: string
- ) {}
+ ) { }
public static async create(host: Host): Promise {
- Log.info(chalk.yellow(`➡️ Signing in to ${host.baseUrl}...`));
+ Log.info(chalk.yellow(`➡️ Signing in to ${host.fullUrl}...`));
const fetch = fetchCookie(nodeFetch);
- await fetch(`${host.baseUrl}/admin/index.php?login`, { method: 'GET' });
- const response = await fetch(`${host.baseUrl}/admin/index.php?login`, {
+ await fetch(`${host.fullUrl}/admin/index.php?login`, { method: 'GET' });
+ const response = await fetch(`${host.fullUrl}/admin/index.php?login`, {
headers: {
'content-type': 'application/x-www-form-urlencoded'
},
@@ -34,9 +34,9 @@ export class Client {
});
if (response.status !== 200)
throw new ErrorNotification({
- message: `There was an error logging in to "${host.baseUrl}" - are you able to log in with the configured password?`,
+ message: `There was an error logging in to "${host.fullUrl}" - are you able to log in with the configured password?`,
verbose: {
- host: host.baseUrl,
+ host: host.fullUrl,
status: response.status,
responseBody: await response.text()
}
@@ -44,7 +44,7 @@ export class Client {
const token = this.parseResponseForToken(host, await response.text());
- Log.info(chalk.green(`✔️ Successfully signed in to ${host.baseUrl}!`));
+ Log.info(chalk.green(`✔️ Successfully signed in to ${host.fullUrl}!`));
return new this(fetch, host, token);
}
@@ -53,9 +53,9 @@ export class Client {
const tokenDiv = root.querySelector('#token');
if (!tokenDiv)
throw new ErrorNotification({
- message: `No token could be found while logging in to "${host.baseUrl}" - are you able to log in with the configured password?`,
+ message: `No token could be found while logging in to "${host.fullUrl}" - are you able to log in with the configured password?`,
verbose: {
- host: host.baseUrl,
+ host: host.fullUrl,
innerHtml: root.innerHTML
}
});
@@ -63,9 +63,9 @@ export class Client {
const token = tokenDiv.innerText;
if (token.length != 44)
throw new ErrorNotification({
- message: `A token was found but could not be validated while logging in to "${host.baseUrl}" - are you able to log in with the configured password?`,
+ message: `A token was found but could not be validated while logging in to "${host.fullUrl}" - are you able to log in with the configured password?`,
verbose: {
- host: host.baseUrl,
+ host: host.fullUrl,
token: token
}
});
@@ -74,11 +74,11 @@ export class Client {
}
public async downloadBackup(): Promise {
- Log.info(chalk.yellow(`➡️ Downloading backup from ${this.host.baseUrl}...`));
+ Log.info(chalk.yellow(`➡️ Downloading backup from ${this.host.fullUrl}...`));
const form = this.generateForm();
const response = await this.fetch(
- `${this.host.baseUrl}/admin/scripts/pi-hole/php/teleporter.php`,
+ `${this.host.fullUrl}/admin/scripts/pi-hole/php/teleporter.php`,
{
body: form,
method: 'POST'
@@ -89,9 +89,9 @@ export class Client {
response.headers.get('content-type') !== 'application/gzip'
)
throw new ErrorNotification({
- message: `Failed to download backup from "${this.host.baseUrl}".`,
+ message: `Failed to download backup from "${this.host.fullUrl}".`,
verbose: {
- host: this.host.baseUrl,
+ host: this.host.fullUrl,
status: response.status,
responseBody: await response.text()
}
@@ -99,19 +99,19 @@ export class Client {
const data = await response.arrayBuffer();
- Log.info(chalk.green(`✔️ Backup from ${this.host.baseUrl} completed!`));
+ Log.info(chalk.green(`✔️ Backup from ${this.host.fullUrl} completed!`));
return new Blob([data]);
}
public async uploadBackup(backup: Blob): Promise {
- Log.info(chalk.yellow(`➡️ Uploading backup to ${this.host.baseUrl}...`));
+ Log.info(chalk.yellow(`➡️ Uploading backup to ${this.host.fullUrl}...`));
const form = this.generateForm();
form.append('action', 'in');
form.append('zip_file', backup, 'backup.tar.gz');
const uploadResponse = await this.fetch(
- `${this.host.baseUrl}/admin/scripts/pi-hole/php/teleporter.php`,
+ `${this.host.fullUrl}/admin/scripts/pi-hole/php/teleporter.php`,
{
body: form,
method: 'POST'
@@ -120,21 +120,21 @@ export class Client {
const uploadText = await uploadResponse.text();
if (uploadResponse.status !== 200 || !uploadText.endsWith('OK'))
throw new ErrorNotification({
- message: `Failed to upload backup to "${this.host.baseUrl}".`,
+ message: `Failed to upload backup to "${this.host.fullUrl}".`,
verbose: {
- host: this.host.baseUrl,
+ host: this.host.fullUrl,
status: uploadResponse.status,
responseBody: uploadText
}
});
- Log.info(chalk.green(`✔️ Backup uploaded to ${this.host.baseUrl}!`));
+ Log.info(chalk.green(`✔️ Backup uploaded to ${this.host.fullUrl}!`));
Log.verbose(`Result:\n${chalk.blue(uploadText)}`);
if (Config.updateGravity) {
- Log.info(chalk.yellow(`➡️ Updating gravity on ${this.host.baseUrl}...`));
+ Log.info(chalk.yellow(`➡️ Updating gravity on ${this.host.fullUrl}...`));
const gravityUpdateResponse = await this.fetch(
- `${this.host.baseUrl}/admin/scripts/pi-hole/php/gravity.sh.php`,
+ `${this.host.fullUrl}/admin/scripts/pi-hole/php/gravity.sh.php`,
{ method: 'GET' }
);
@@ -146,15 +146,15 @@ export class Client {
!updateText.endsWith('Pi-hole blocking is enabled')
)
throw new ErrorNotification({
- message: `Failed updating gravity on "${this.host.baseUrl}".`,
+ message: `Failed updating gravity on "${this.host.fullUrl}".`,
verbose: {
- host: this.host.baseUrl,
+ host: this.host.fullUrl,
status: gravityUpdateResponse.status,
eventStream: updateText
}
});
- Log.info(chalk.green(`✔️ Gravity updated on ${this.host.baseUrl}!`));
+ Log.info(chalk.green(`✔️ Gravity updated on ${this.host.fullUrl}!`));
Log.verbose(`Result:\n${chalk.blue(updateText)}`);
}
diff --git a/src/config.test.ts b/src/config.test.ts
index 9295877f..218ebe4a 100644
--- a/src/config.test.ts
+++ b/src/config.test.ts
@@ -91,12 +91,14 @@ describe('Config', () => {
const expected = {
baseUrl: 'http://10.0.0.2',
+ fullUrl: 'http://10.0.0.2',
+ path: '',
password: 'mypassword'
};
- expect(Config.primaryHost).toStrictEqual(expected);
+ expect(Config.primaryHost).toEqual(expected);
resetEnv();
- expect(Config.primaryHost).toStrictEqual(expected);
+ expect(Config.primaryHost).toEqual(expected);
});
});
@@ -132,13 +134,15 @@ describe('Config', () => {
const expected = [
{
baseUrl: 'http://10.0.0.3',
- password: 'mypassword'
+ password: 'mypassword',
+ fullUrl: 'http://10.0.0.3',
+ path: ''
}
];
- expect(Config.secondaryHosts).toStrictEqual(expected);
+ expect(Config.secondaryHosts).toEqual(expected);
resetEnv();
- expect(Config.secondaryHosts).toStrictEqual(expected);
+ expect(Config.secondaryHosts).toEqual(expected);
});
test('should return multiple secondary hosts', () => {
@@ -151,18 +155,24 @@ describe('Config', () => {
process.env['SECONDARY_HOST_5_BASE_URL'] = 'http://10.0.0.7';
process.env['SECONDARY_HOST_5_PASSWORD'] = 'mypassword4';
- expect(Config.secondaryHosts).toStrictEqual([
+ expect(Config.secondaryHosts).toEqual([
{
baseUrl: 'http://10.0.0.3',
- password: 'mypassword1'
+ password: 'mypassword1',
+ fullUrl: 'http://10.0.0.3',
+ path: ''
},
{
baseUrl: 'http://10.0.0.4',
- password: 'mypassword2'
+ password: 'mypassword2',
+ fullUrl: 'http://10.0.0.4',
+ path: ''
},
{
baseUrl: 'http://10.0.0.5',
- password: 'mypassword3'
+ password: 'mypassword3',
+ fullUrl: 'http://10.0.0.5',
+ path: ''
}
]);
});
diff --git a/src/config.ts b/src/config.ts
index de45ad16..8421fda5 100644
--- a/src/config.ts
+++ b/src/config.ts
@@ -7,10 +7,10 @@ export class Config {
private static _intervalMinutes?: number;
static get primaryHost(): Host {
- this._primaryHost ??= {
- baseUrl: this.getRequiredEnv('PRIMARY_HOST_BASE_URL'),
- password: this.getRequiredEnv('PRIMARY_HOST_PASSWORD')
- };
+ this._primaryHost ??= new Host(
+ this.getRequiredEnv('PRIMARY_HOST_BASE_URL'),
+ this.getRequiredEnv('PRIMARY_HOST_PASSWORD')
+ );
return this._primaryHost;
}
@@ -18,10 +18,10 @@ export class Config {
static get secondaryHosts(): Host[] {
if (!this._secondaryHosts) {
this._secondaryHosts = [
- {
- baseUrl: this.getRequiredEnv('SECONDARY_HOST_1_BASE_URL'),
- password: this.getRequiredEnv('SECONDARY_HOST_1_PASSWORD')
- }
+ new Host(
+ this.getRequiredEnv('SECONDARY_HOST_1_BASE_URL'),
+ this.getRequiredEnv('SECONDARY_HOST_1_PASSWORD')
+ )
];
let count = 2;
@@ -29,10 +29,11 @@ export class Config {
process.env[`SECONDARY_HOST_${count}_BASE_URL`] !== undefined &&
process.env[`SECONDARY_HOST_${count}_PASSWORD`] !== undefined
) {
- this._secondaryHosts.push({
- baseUrl: process.env[`SECONDARY_HOST_${count}_BASE_URL`]!,
- password: process.env[`SECONDARY_HOST_${count}_PASSWORD`]!
- });
+ this._secondaryHosts.push(
+ new Host(
+ this.getRequiredEnv(`SECONDARY_HOST_${count}_BASE_URL`),
+ this.getRequiredEnv(`SECONDARY_HOST_${count}_PASSWORD`)
+ ));
count++;
}
@@ -42,7 +43,7 @@ export class Config {
}
static get allHostBaseUrls(): string[] {
- return [this.primaryHost, ...this.secondaryHosts].map((host) => host.baseUrl);
+ return [this.primaryHost, ...this.secondaryHosts].map((host) => host.fullUrl);
}
static get syncOptions(): SyncOptions {
@@ -160,7 +161,18 @@ export interface SyncOptions {
flushtables: boolean;
}
-export interface Host {
- baseUrl: string;
+export class Host {
+ private baseUrl: string;
+ private path: string;
+ fullUrl: string;
password: string;
+
+ constructor(baseUrl: string, password: string, path?: string) {
+ this.path = path ?? '';
+ this.baseUrl = baseUrl;
+ this.password = password
+ this.fullUrl = this.baseUrl + this.path
+ }
}
+
+
diff --git a/src/sync.test.ts b/src/sync.test.ts
index 4a361157..29d8a0c5 100644
--- a/src/sync.test.ts
+++ b/src/sync.test.ts
@@ -3,7 +3,7 @@ import chalk from 'chalk';
import nock from 'nock';
import { Blob } from 'node-fetch';
import { Client } from './client';
-import { Config } from './config';
+import { Config, Host } from './config';
import { Log } from './log';
import { ErrorNotification, Notify } from './notify';
import { Sync } from './sync';
@@ -20,19 +20,10 @@ describe('entrypoint', () => {
let secondaryHostClient1: Client;
let secondaryHostClient2: Client;
- const primaryHostValue = {
- baseUrl: 'http://10.0.0.2',
- password: 'password1'
- };
+ const primaryHostValue = new Host('http://10.0.0.2', 'password1');
const secondaryHostsValue = [
- {
- baseUrl: 'http://10.0.0.3',
- password: 'password2'
- },
- {
- baseUrl: 'http://10.0.0.4',
- password: 'password3'
- }
+ new Host('http://10.0.0.3', 'password2'),
+ new Host('http://10.0.0.4', 'password3')
];
const backupData = new Blob([]);