🎉 Initial commit

master
KaKi87 2022-12-27 21:37:27 +01:00
commit e118d4d38b
6 changed files with 283 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
config.js

11
config.example.js Normal file
View File

@ -0,0 +1,11 @@
export const
/**
* Sentry DSN
* @type {string}
*/
sentryDsn = 'https://fa582994e64a4b0ba33591cf5bfbbc9c@sentry.kaki87.net/6',
/**
* HTTP port
* @type {number}
*/
port = 3071;

11
lib/exec.js Normal file
View File

@ -0,0 +1,11 @@
export default async (...args) => {
const command = Deno.run({
cmd: args,
stdout: 'piped',
stderr: 'piped'
});
return {
stdout: new TextDecoder().decode(await command.output()),
stderr: new TextDecoder().decode(await command.stderrOutput())
};
};

47
main.js Normal file
View File

@ -0,0 +1,47 @@
import * as Sentry from 'npm:@sentry/node@7.28.1';
import pogo from 'https://deno.land/x/pogo@v0.6.0/main.ts';
import {
createServerHelper
} from 'https://git.kaki87.net/KaKi87/pogo-helpers/raw/commit/a80ff83ec392106f783f531b37e0f722d65e4d11/mod.js';
import dns from './src/dns.js';
import whois from './src/whois.js';
import {
sentryDsn,
port
} from './config.js';
Sentry.init({
dsn: sentryDsn,
integrations: [
new Sentry.Integrations.Context({
app: true,
os: true,
device: false,
culture: true
})
]
});
const
server = pogo.server({
port
}),
{
createRoute
} = createServerHelper(
server,
{
isCors: true,
onError: error => {
Sentry.captureException(error);
console.error(error);
}
}
);
createRoute(dns);
createRoute(whois);
server.start();

127
src/dns.js Normal file
View File

@ -0,0 +1,127 @@
import Joi from 'npm:joi@17.6.1';
import exec from '../lib/exec.js';
export default {
method: 'GET',
path: '/dns/{hostname}',
schema: Joi.object({
path: Joi.object({
hostname: Joi
.string()
.hostname()
.required()
}),
params: Joi.object({
nameserver: Joi
.string()
.hostname()
.default('8.8.8.8'),
record: Joi
.string()
.valid(
'ANY',
'A',
'AAAA',
'AFSDB',
'APL',
'AXFR',
'CAA',
'CDNSKEY',
'CDS',
'CERT',
'CNAME',
'CSYNC',
'DHCID',
'DLV',
'DNAME',
'DNSKEY',
'DS',
'EUI48',
'EUI64',
'HINFO',
'HIP',
'HTTPS',
'IPSECKEY',
'IXFR',
'KEY',
'KX',
'LOC',
'MX',
'NAPTR',
'NS',
'NSEC3',
'NSEC3PARAM',
'NSEC',
'NXT',
'OPENPGPKEY',
'OPT',
'PTR',
'RP',
'RRSIG',
'SIG',
'SMIMEA',
'SOA',
'SSHFP',
'SVCB',
'SRV',
'TA',
'TKEY',
'TLSA',
'TSIG',
'TXT',
'URI',
'ZONEMD'
)
.default('ANY')
})
}),
handler: async (
request,
h,
{
path: {
hostname
},
params: {
nameserver,
record
},
response
}
) => {
const {
stdout,
stderr
} = await exec(
'dig',
`@${nameserver}`,
hostname,
record,
'+noall',
'+answer'
);
response.body = {
success: stdout && !stderr,
data: stdout
.split('\n')
.filter(Boolean)
.map(line => {
const [
domain,
ttl
,,
type,
...value
] = line.split(/\s+/g);
return {
domain,
ttl: parseInt(ttl),
type,
value: value.join(' ')
};
})
};
return response;
}
};

86
src/whois.js Normal file
View File

@ -0,0 +1,86 @@
import Joi from 'npm:joi@17.6.1';
import exec from '../lib/exec.js';
export default {
method: 'GET',
path: '/whois/{hostname}',
schema: Joi.object({
path: Joi.object({
hostname: Joi
.string()
.hostname()
.required()
}),
params: Joi.object({
format: Joi
.string()
.valid(
'text',
'json',
'nestedJson'
)
.default('json')
})
}),
handler: async (
request,
h,
{
path: {
hostname
},
params: {
format
},
response
}
) => {
const {
stdout,
stderr
} = await exec(
'whois',
hostname
);
let data;
switch(format){
case 'text': {
data = stdout;
break;
}
case 'json':
case 'nestedJson': {
data = {};
for(const line of stdout.split('\n')){
const [, key, value] = line.match(/^\s*([\w\s]+)[^\w]?\s+(.+)$/) || [];
if(key && value){
if(format === 'json'){
if(!data[key])
data[key] = [];
data[key].push(value);
}
else if(format === 'nestedJson'){
const keys = key.split(/\s+/g);
let parentObject = data;
for(const key of keys){
if(!parentObject[key])
parentObject[key] = {};
parentObject = parentObject[key];
}
if(!parentObject.$)
parentObject.$ = [];
parentObject.$.push(value);
}
}
}
break;
}
}
response.body = {
success: stdout && !stderr,
data
};
return response;
}
};