mirror of https://github.com/186526/net186-bot
Init
This commit is contained in:
parent
1c1dabbb33
commit
2a5e1b74c9
|
@ -102,3 +102,5 @@ dist
|
|||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
src/config.ts
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"name": "net186-bot",
|
||||
"version": "0.0.1",
|
||||
"description": "A looking glass telegram bot using hyperglass' openapi.",
|
||||
"main": "dist/app.js",
|
||||
"scripts": {
|
||||
"build": "rm -rf dist/* && tsc",
|
||||
"start": "node dist/app.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/186526/net186-bot.git"
|
||||
},
|
||||
"author": "real186526 <i@186526.xyz>",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/186526/net186-bot/issues"
|
||||
},
|
||||
"homepage": "https://github.com/186526/net186-bot#readme",
|
||||
"devDependencies": {
|
||||
"@types/node": "^18.11.18",
|
||||
"tslint": "^6.1.3",
|
||||
"typescript": "^4.9.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.2.2",
|
||||
"ip-address": "^8.1.0",
|
||||
"telegraf": "^4.11.2"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
import axios, { AxiosInstance } from "axios";
|
||||
import { adapter, capabilities, device, info, queryError, querySuccess } from "../types/adapter";
|
||||
import { Address4, Address6 } from 'ip-address';
|
||||
|
||||
interface deviceRaw {
|
||||
name: string;
|
||||
network: {
|
||||
name: string;
|
||||
display_name: string;
|
||||
};
|
||||
vrfs: {
|
||||
name: string;
|
||||
display_name: string;
|
||||
}[];
|
||||
}
|
||||
|
||||
interface queryTypeRaw {
|
||||
name: capabilities;
|
||||
display_name: string;
|
||||
enable: boolean;
|
||||
}
|
||||
|
||||
export default class Hyperglass implements adapter {
|
||||
private axiosInstance: AxiosInstance;
|
||||
constructor(link: string) {
|
||||
this.axiosInstance = axios.create({
|
||||
baseURL: link,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
transformRequest: [
|
||||
(data: object) => {
|
||||
return JSON.stringify(data);
|
||||
},
|
||||
],
|
||||
transformResponse: [
|
||||
(data: string) => {
|
||||
return JSON.parse(data);
|
||||
},
|
||||
],
|
||||
validateStatus: function (status) {
|
||||
return status < 500;
|
||||
}
|
||||
});
|
||||
this.axiosInstance.get("/api/info").then((r) => {
|
||||
if (!(r.data.version as string).includes("hyperglass")) {
|
||||
throw new Error(
|
||||
"Not found hyperglass in /api/info. Please check your Hyperglass URL."
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async info(): Promise<info> {
|
||||
const response = await this.axiosInstance.get("/api/info");
|
||||
return {
|
||||
name: response.data.name,
|
||||
organization: response.data.organization,
|
||||
};
|
||||
}
|
||||
|
||||
async devicesRaw(): Promise<deviceRaw[]> {
|
||||
const response = await this.axiosInstance.get("/api/devices");
|
||||
return response.data as deviceRaw[];
|
||||
}
|
||||
async listQueiesTypeRaw(): Promise<queryTypeRaw[]> {
|
||||
const response = await this.axiosInstance.get("/api/queries");
|
||||
return response.data as queryTypeRaw[];
|
||||
}
|
||||
|
||||
async capabilities(): Promise<capabilities[]> {
|
||||
return (await this.listQueiesTypeRaw()).reduce(
|
||||
(previous: capabilities[], current) => {
|
||||
if (current.enable) {
|
||||
previous.push(current.name);
|
||||
}
|
||||
return previous;
|
||||
},
|
||||
[]
|
||||
);
|
||||
}
|
||||
async devices(): Promise<device[]> {
|
||||
const devicesRaw = await this.devicesRaw();
|
||||
const globalCapabilities = await this.capabilities();
|
||||
return devicesRaw.map((k) => {
|
||||
return {
|
||||
name: k.name,
|
||||
group: k.network.display_name,
|
||||
capabilities: globalCapabilities,
|
||||
vrfs: k.vrfs.map((k) => k.name),
|
||||
};
|
||||
});
|
||||
}
|
||||
async query(capability: capabilities, device: device, vrf: string, target: Address4 | Address6): Promise<queryError | querySuccess> {
|
||||
|
||||
const response = await this.axiosInstance.post("api/query/", {
|
||||
query_location: device.name.replace(/[^A-Za-z0-9\_\-\s]/g,"").replaceAll(" ","_").toLowerCase(),
|
||||
query_target: target.address,
|
||||
query_vrf: vrf,
|
||||
query_type: capability,
|
||||
});
|
||||
|
||||
if (response.status == 200) {
|
||||
return {
|
||||
level: response.data.level as "success",
|
||||
output: response.data.output as string,
|
||||
timestamp: new Date(response.data.timestamp),
|
||||
} as querySuccess;
|
||||
} else if (response.status == 400) {
|
||||
return {
|
||||
level: response.data.level as "danger",
|
||||
output: "Request Content Error: " + response.data.output as string,
|
||||
} as queryError;
|
||||
} else if (response.status == 422) {
|
||||
return {
|
||||
level: response.data.level as "danger",
|
||||
output: "Request Format Error: " + response.data.output as string,
|
||||
} as queryError;
|
||||
} else if (response.status == 500) {
|
||||
return {
|
||||
level: response.data.level as "danger",
|
||||
output: "Server Error: " + response.data.output as string,
|
||||
} as queryError;
|
||||
} else {
|
||||
return {
|
||||
level: "danger",
|
||||
output: "Unknown Error.",
|
||||
} as queryError;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
import { Context, Telegraf } from 'telegraf';
|
||||
import { Update } from 'typegram';
|
||||
import handleInfo from './handler/info';
|
||||
import config from "./config";
|
||||
|
||||
const bot: Telegraf<Context<Update>> = new Telegraf(config.token);
|
||||
|
||||
bot.start(handleInfo(config.adapter));
|
||||
|
||||
bot.launch();
|
|
@ -0,0 +1,9 @@
|
|||
import { Context } from "telegraf";
|
||||
import { adapter } from "../types/adapter";
|
||||
|
||||
export default function handleInfo(adapter: adapter) {
|
||||
return async (ctx: Context)=>{
|
||||
const info = await adapter.info();
|
||||
ctx.reply(`${info.name} Bot from ${info.organization}.`)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
import { Address4, Address6 } from "ip-address";
|
||||
|
||||
enum capabilities {
|
||||
"BGP Route" = "bgp_route",
|
||||
"Ping" = "ping",
|
||||
"Traceroute" = "traceroute",
|
||||
}
|
||||
|
||||
interface info {
|
||||
name: string;
|
||||
organization: string;
|
||||
}
|
||||
|
||||
interface device {
|
||||
name: string;
|
||||
group: string;
|
||||
capabilities: capabilities[];
|
||||
vrfs: string[];
|
||||
}
|
||||
|
||||
interface queryResponse {
|
||||
level: "success" | "warning" | "error" | "danger";
|
||||
}
|
||||
|
||||
interface queryError extends queryResponse {
|
||||
output?: string;
|
||||
}
|
||||
|
||||
interface querySuccess extends queryResponse {
|
||||
level: "success";
|
||||
output: string;
|
||||
timestamp: Date;
|
||||
}
|
||||
|
||||
interface adapter {
|
||||
info(): Promise<info>;
|
||||
devices(): Promise<device[]>;
|
||||
query(
|
||||
capability: capabilities,
|
||||
device: device,
|
||||
vrf: string,
|
||||
target: Address4 | Address6
|
||||
): Promise<queryError | querySuccess | queryResponse>;
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
interface config {
|
||||
token: string; // Telegram Bot token.
|
||||
adapter: adapter;
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"esModuleInterop": true,
|
||||
"target": "es2021",
|
||||
"moduleResolution": "node",
|
||||
"strict": true,
|
||||
"sourceMap": true,
|
||||
"lib": [
|
||||
"es2021"
|
||||
],
|
||||
"skipLibCheck": true,
|
||||
"rootDir": "src",
|
||||
"outDir": "dist"
|
||||
},
|
||||
"typeRoots": [
|
||||
"./src/types"
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue