🎉 Initial commit
commit
e118d4d38b
|
@ -0,0 +1 @@
|
|||
config.js
|
|
@ -0,0 +1,11 @@
|
|||
export const
|
||||
/**
|
||||
* Sentry DSN
|
||||
* @type {string}
|
||||
*/
|
||||
sentryDsn = 'https://fa582994e64a4b0ba33591cf5bfbbc9c@sentry.kaki87.net/6',
|
||||
/**
|
||||
* HTTP port
|
||||
* @type {number}
|
||||
*/
|
||||
port = 3071;
|
|
@ -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())
|
||||
};
|
||||
};
|
|
@ -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();
|
|
@ -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;
|
||||
}
|
||||
};
|
|
@ -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;
|
||||
}
|
||||
};
|
Loading…
Reference in New Issue