Compare commits

..

No commits in common. "main" and "master" have entirely different histories.
main ... master

15 changed files with 110 additions and 421 deletions

6
.gitignore vendored
View File

@ -1,3 +1,5 @@
mc/
server/test.js
server/servers.db server/servers.db
ip.txt ip.txt
server/node_modules server/node_modules
@ -5,7 +7,3 @@ nimscan/bin
.vscode .vscode
server_backup server_backup
old_tests old_tests
nim_bot/src/token.key
nim_bot/src/tmp
nim_bot/src/bin
server/offline.db

View File

@ -1,10 +0,0 @@
# TaxenHeimer
TaxenHeimer is a project inspired by the famous CopenHeimer server scanner.
## Description
In this repository you'll find 2 directories, one with the scanner(client) and one with the backend(server)
```
Client: generate random IPs and ping for minecraft server with a handshake packet if received packet is valid sends the IP to the backend
Server: Query the IPs for all the needed informations, sends the to a discord webhook and saves them to a local SQLite3 database
```

View File

@ -1,7 +0,0 @@
# TaxenHeimer Discord Bot
Discord bot written in nim to help with easy query commands on the database
## Running
```
nim c src/nim_bot.nim
```

View File

@ -1,13 +0,0 @@
# Package
version = "0.1.0"
author = "TaxMachine"
description = "A new awesome nimble package"
license = "MIT"
srcDir = "src"
bin = @["nim_bot"]
# Dependencies
requires "nim >= 1.6.6"

View File

@ -1,3 +0,0 @@
switch("d", "ssl")
switch("d", "release")
switch("o", "bin/nim_bot")

View File

@ -1,188 +0,0 @@
import asyncdispatch, json, options, dimscord, strutils, harpoon, os, db_sqlite, strformat, tables
from uri import parseUri
discard os.execShellCmd("clear")
let
keyfile = readFile("token.key")
discord = newDiscordClient(keyfile)
prefix = "$"
proc onReady(s: Shard, r: Ready) {.event(discord).} =
echo "Login on " & $r.user
proc messageCreate(s: Shard, m: Message) {.event(discord).} =
if m.author.bot: return
if not m.content.startsWith(prefix): return
let
args = m.content.toLowerAscii().substr(prefix.len).split(" ")
argument = m.content.split(" ")
case args[0]:
of "help":
discard await discord.api.sendMessage(
m.channel_id,
embeds = @[Embed(
title: some "TaxenHeimer Bot",
fields: some @[EmbedField(
name: fmt"**{prefix}help**",
value: "`Displays this menu`",
inline: some true
),
EmbedField(
name: fmt"**{prefix}namemc**",
value: "`Displays informations about a minecraft account`",
inline: some true
),
EmbedField(
name: fmt"**{prefix}status**",
value: "`Gives overall informations on the database`",
inline: some true
)],
color: some 0x000066
)]
)
of "namemc":
if (argument.len < 2):
discard await discord.api.sendMessage(m.channel_id, "User not found")
else:
let
url = "https://api.ashcon.app/mojang/v2/user/" & argument[1]
data = getJson(parseUri(url))
if (data{"code"}.getInt == 404):
discard await discord.api.sendMessage(m.channel_id, "User not found")
else:
var
uuid = data["uuid"].getStr
renderurl = "https://crafatar.com/avatars/" & uuid
bodyurl = "https://crafatar.com/renders/body/" & uuid
username = data["username"].getStr
date = data{"created_at"}.getStr
usernamehistory = data["username_history"]
hist = ""
if (usernamehistory.len > 0):
for names in usernamehistory:
if (names{"changed_at"}.isNil):
hist.add(names["username"].getStr & " : " & "Original\n")
else:
var
cdate = names{"changed_at"}.getStr.split("T")
pdate = cdate[1].split(".")[0] & " " & cdate[0]
hist.add(names["username"].getStr & " : " & pdate & "\n")
else:
hist.add("No Name History")
discard await discord.api.sendMessage(
m.channel_id,
embeds = @[Embed(
title: some "Namemc Lookup",
fields: some @[EmbedField(
name: "**username**",
value: fmt"```{'\n'}{username}{'\n'}```",
inline: some true
),
EmbedField(
name: "**UUID**",
value: fmt"```{'\n'}{uuid}{'\n'}```",
inline: some true
),
EmbedField(
name: "**Creation Date(Might not be given)**",
value: fmt"```{'\n'}{date}{'\n'}```",
inline: some true
),
EmbedField(
name: "**Name History**",
value: fmt"```fix{'\n'}{hist}{'\n'}```",
inline: some false
)
],
thumbnail: some EmbedThumbnail(
url: some renderurl
),
image: some EmbedImage(
url: some bodyurl
),
color: some 0x000066
)]
)
of "status":
let
db = open("../../server/servers.db", "", "", "")
offdb = open("../../server/offline.db", "", "", "")
server = db.getAllRows(sql"SELECT host FROM servers").len
offline = offdb.getAllRows(sql"SELECT host FROM servers").len
total = server + offline
discard await discord.api.sendMessage(
m.channel_id,
embeds = @[Embed(
title: some "**Server Database Status**",
color: some 0x000066,
fields: some @[EmbedField(
name: "**Online Servers**",
value: fmt"```{$server} online servers```"
),
EmbedField(
name: "**Offline Servers**",
value: fmt"```{$offline} offline servers```"
),
EmbedField(
name: "**Total Servers**",
value: fmt"```{total} total servers```"
)]
)]
)
of "info":
discard await discord.api.sendMessage(
m.channel_id,
embeds = @[Embed(
title: some "TaxenHeimer bot",
description: some "```Discord bot that help to manage TaxenHeimer database queries```",
color: some 0x000066,
fields: some @[EmbedField(
name: "**Author**",
value: "```TaxMachine```",
inline: some true
),
EmbedField(
name: "**Language**",
value: "```nim```",
inline: some true
),
EmbedField(
name: "**Credits**",
value: "```\nPackage: https://nimble.directory/pkg/dimscord\nHelp: https://discord.gg/nim https://discord.gg/dimscord```"
)]
)]
)
proc guild_member_add(s: Shard, g: Guild, m: Member) {.event(discord).} =
discard await discord.api.sendMessage(
"999502028227227810",
embeds = @[Embed(
title: some "**Welcome**",
description: some fmt"Welcome <@{m.user.id}> to TaxenHeimer! Hope you'll have a great time :coffee:",
color: some 0x000066,
fields: some @[EmbedField(
name: "Member Count",
value: "```\n" & $g.members.len & "\n```"
)]
)]
)
discard discord.api.addGuildMemberRole(
g.id,
m.user.id,
"999538053943140463",
"Joining"
)
proc guild_member_remove(s: Shard, g: Guild, m: Member) {.event(discord).} =
discard await discord.api.sendMessage(
"1001391863263150150",
embeds = @[Embed(
title: some "**Goodbye**",
description: some fmt"Goodbye {m.user.username} :brain: :clown:",
color: some 0x000066,
fields: some @[EmbedField(
name: "Member Count",
value: "```\n" & $g.members.len & "\n```"
)]
)]
)
waitFor discord.startSession()

View File

@ -37,14 +37,13 @@ proc hit(host: string) {.gcsafe.} =
proc main(): void {.thread.} = proc main(): void {.thread.} =
while true: while true:
var var ip = GenerateIP()
ip = GenerateIP() var ping = status(ip)
ping = status(ip)
if ping: if ping:
hit(ip) hit(ip)
discard discard
discard os.execShellCmd("clear") var cmd = os.execShellCmd("clear")
var cLock: Lock var cLock: Lock
initLock(cLock) initLock(cLock)
var thread: Thread[void] var thread: Thread[void]

View File

@ -1,7 +0,0 @@
# TaxenHeimer Server Scanner
The project core, the program that is used to scan port on random IPs, written in nim for faster results. runs on 300 threads
## Running
```
nim c scanner.nim
```

View File

@ -1,4 +1 @@
--threads:on --threads:on
switch("d", "release")
switch("d", "ssl")
switch("o", "bin/scanner")

View File

@ -1,14 +0,0 @@
# TaxenHeimer Backend Server
Backend server for TaxenHeimer written in Node.JS
## Running it
Test environment
```
npm run test
```
Release<br>
(Uses bytenode to compile and makes scripts a bit faster)
```
npm run compile
npm run runc
```

5
server/config.json Normal file
View File

@ -0,0 +1,5 @@
{
"main": "https://discord.com/api/webhooks/999381041041129573/5vmF56GsDdg8D3HJWnu-pRsBmxqPqnzHBTQAu1yLcZQ93xhR36V2UUUVNhRrAHZQyKzA",
"neit": "https://discord.com/api/webhooks/1000916905600761887/yeC4nbJYeS38JlNdI42dh8cfcmeX0SZeFSvqmeCIdCZJtJewkq6DjIMXAjwmBhF65XtA",
"fronce": "https://discord.com/api/webhooks/1000903130222952518/cRK-SXahsWl8OT_N4HLnt7I0JebGnQh0gN3p3iOvCW_QIVC7hq2oWlmt6txC7NSXtv55"
}

View File

@ -1,20 +0,0 @@
@import url('https://fonts.googleapis.com/css2?family=Nunito+Sans:wght@200&display=swap');
.😳 {
padding: 10px;
color: #dcddde;
font-size: 20px;
border: solid rgba(168, 168, 168, 0.89) 1px;
}
.👽 {
font-family: 'Nunito Sans';
padding: 10px;
font-size: 25px;
color: rgba(255, 255, 255, 0.959);
text-align: center;
}
.💀 {
background-color: rgba(49, 49, 49, 0.89);
}
body {
background-color: rgb(20, 20, 20);
}

View File

@ -1,45 +1,24 @@
const express = require("express"), const express = require('express'),
sqlite3 = require("sqlite3"), sqlite3 = require('sqlite3'),
bodyParser = require("body-parser"), bodyParser = require('body-parser'),
mc = require("minecraft-server-util"),
Discord = require("discord-webhook-node"),
geoIP = require("geoip-lite"),
fs = require("fs"),
config = require("./config.json"),
app = express(), app = express(),
db = new sqlite3.Database("./servers.db"), mc = require('minecraft-server-util'),
offline = new sqlite3.Database("./offline.db"); discord = require('discord-webhook-node'),
geoip = require('geoip-lite'),
const createWebhook = url => new Discord.Webhook(url).setUsername("TaxenHeimer").setAvatar("https://cdn.discordapp.com/attachments/999167321631363126/999495738943868928/nn.png") fs = require('fs'),
const countrify = e => require("./countrycode.json")[e] config = require('./config.json')
const replaceMOTD = e => e.replace(/'/g, "\\'").replace(/-/g, '\\-') var webhook = new discord.Webhook(config.main)
const makeEmbed = (mc, neit) => { .setUsername("TaxenHeimer")
var Embed = new Discord.MessageBuilder() .setAvatar("https://cdn.discordapp.com/attachments/999167321631363126/999495738943868928/nn.png")
.setTitle("TaxenHeimer") var webhookfronce = new discord.Webhook(config.fronce)
.setColor("#00ff00") .setAvatar("https://cdn.discordapp.com/attachments/999167321631363126/999495738943868928/nn.png")
.addField("**Host**", `\`${mc.Server}\``, true) .setUsername("TaxenHeimer")
.addField("**Country**", `\`${countrify(mc.ip.country)}\``) var neithook = new discord.Webhook(config.neit)
.addField("**Version**", `\`${mc.version.name}\``, true) .setAvatar("https://cdn.discordapp.com/attachments/999167321631363126/999495738943868928/nn.png")
.addField("**Players**", `\`${mc.players.online}/${mc.players.max}\``, true) .setUsername("TaxenHeimer")
.addField("**Ping**", `\`${mc.roundTripLatency}ms\``, true) app.use(bodyParser.json())
.addField("**Motd**", "```\n" + mc.motd.clean + "\n```") app.use(bodyParser.urlencoded({extended: true}))
.addField("**Playerlist Sample**", "```fix\n" + mc.PlayerList + "\n```") db = new sqlite3.Database('./servers.db')
.addField("**IP Range**", "```\n" + geoIP.pretty(mc.ip.range[0]) + " - " + geoIP.pretty(mc.ip.range[1]) + "```")
.setTimestamp()
if (neit) Embed.setText("<@390491795655622657>")
return Embed
}
var webhooks = [
createWebhook(config.main),
createWebhook(config.fronce),
createWebhook(config.neit)
]
app.use(bodyParser.json()).use(bodyParser.urlencoded({
extended: true
}))
db.exec(`CREATE TABLE IF NOT EXISTS servers ( db.exec(`CREATE TABLE IF NOT EXISTS servers (
host text not null, host text not null,
version text not null, version text not null,
@ -49,114 +28,87 @@ db.exec(`CREATE TABLE IF NOT EXISTS servers (
motd text not null, motd text not null,
timestamp text not null timestamp text not null
)`) )`)
offline.exec(`CREATE TABLE IF NOT EXISTS servers ( function countrify(code) {
host text not null, var config = require('./countrycode.json')
timestamp text not null return config[code]
)`) }
app.post("/server", async (req, res) => { app.post('/server', async(req, res) => {
var Server = req.body.server var server = req.body.server
if (!Server) return res.send("specify a server") if (!server) return res.send("specify a server")
var ipfile = fs.readFileSync(`${__dirname}/ip.txt`, 'utf8')
if (ipfile.includes(server)) return;
res.send("allah") res.send("allah")
if (fs.readFileSync(`${__dirname}/ip.txt`).toString().includes(Server)) return mc.status(server, 25565, {enableSRV: true}).then(res => {
var Minecraft = await mc.status(Server, 25565, { var playerlist = ""
enableSRV: true if (res.players.sample != null) {
}).catch(e => { res.players.sample.forEach(e => playerlist += `${e.name}::${e.id}\n`)
offline.exec(`INSERT INTO servers VALUES ( } else {
'${Server}', playerlist += "No players"
'${new Date().toLocaleDateString("en-US")}' }
var ip = geoip.lookup(server)
if (res.motd.clean.includes("'")) var cleanmotd = res.motd.clean.replace(/'/g, "\\'")
else cleanmotd = res.motd.clean
if (res.motd.clean.includes('-')) var cleanmotd = res.motd.clean.replace(/-/g, '\\-')
else cleanmotd = res.motd.clean
db.exec(`INSERT INTO servers VALUES (
'${server}:25565',
'${res.version.name}',
'${res.players.online}/${res.players.max}',
'${playerlist}',
'${res.roundTripLatency}ms',
'${cleanmotd}',
'${(new Date()).toLocaleDateString('en-US')}'
)`) )`)
}) if (ip.country === "FR") {
fs.appendFileSync(`${__dirname}/ip.txt`, `${Server}\n`) const embed = new discord.MessageBuilder()
Minecraft.ip = geoIP.lookup(Server) .setTitle("TaxenHeimer")
Minecraft.Server = `${Server}:25565` .setColor("#00ff00")
var cleanMOTD = replaceMOTD(Minecraft.motd.clean) .addField("**Host**", `\`${server}:25565\``, true)
Minecraft.PlayerList = "" .addField("**Country**", `\`${countrify(ip.country)}\``)
Minecraft.players.sample ? Minecraft.players.sample.forEach(e => Minecraft.PlayerList += `${e.name} : ${e.id}\n`) : Minecraft.PlayerList = "No Players" .addField("**Version**", `\`${res.version.name} (${res.version.protocol})\``, true)
db.exec(`INSERT INTO servers VALUES ( .addField("**Players**", `\`${res.players.online}/${res.players.max}\``, true)
'${Minecraft.Server}', .addField("**Ping**", `\`${res.roundTripLatency}ms\``, true)
'${Minecraft.version.name}', .addField("**Motd**", "```\n"+res.motd.clean+"\n```")
'${Minecraft.players.online}/${Minecraft.players.max}', .addField("**Playerlist Sample**", "```\n"+playerlist+"\n```")
'${Minecraft.PlayerList.replace(/\n/g, "\\n")}', .addField("**IP Range**", "```\n" + geoip.pretty(ip.range[0]) + " - " + geoip.pretty(ip.range[1]) + "```")
'${Minecraft.roundTripLatency}ms', .setTimestamp()
'${cleanMOTD}', webhookfronce.send(embed)
'${new Date().toLocaleDateString('en-US')}' }
)`) if (res.version.name.includes("1.17")) {
switch (Minecraft.ip.country) { const embed = new discord.MessageBuilder()
default: break; .setText("<@390491795655622657>")
case "FR": .setTitle("TaxenHeimer")
webhooks[1].send(makeEmbed(Minecraft)) .setColor("#00ff00")
break .addField("**Host**", `\`${server}:25565\``, true)
} .addField("**Country**", `\`${countrify(ip.country)}\``)
switch(true) { .addField("**Version**", `\`${res.version.name} (${res.version.protocol})\``, true)
case Minecraft.version.name === "1.17": .addField("**Players**", `\`${res.players.online}/${res.players.max}\``, true)
webhooks[2].send(makeEmbed(Minecraft, "neit")) .addField("**Ping**", `\`${res.roundTripLatency}ms\``, true)
break; .addField("**Motd**", "```\n"+res.motd.clean+"\n```")
default: .addField("**Playerlist Sample**", "```\n"+playerlist+"\n```")
webhooks[0].send(makeEmbed(Minecraft)) .addField("**IP Range**", "```\n" + geoip.pretty(ip.range[0]) + " - " + geoip.pretty(ip.range[1]) + "```")
break .setTimestamp()
} neithook.send(embed)
}
const embed = new discord.MessageBuilder()
.setTitle("TaxenHeimer")
.setColor("#00ff00")
.addField("**Host**", `\`${server}:25565\``, true)
.addField("**Country**", `\`${countrify(ip.country)}\``)
.addField("**Version**", `\`${res.version.name} (${res.version.protocol})\``, true)
.addField("**Players**", `\`${res.players.online}/${res.players.max}\``, true)
.addField("**Ping**", `\`${res.roundTripLatency}ms\``, true)
.addField("**Motd**", "```\n"+res.motd.clean+"\n```")
.addField("**Playerlist Sample**", "```\n"+playerlist+"\n```")
.addField("**IP Range**", "```\n" + geoip.pretty(ip.range[0]) + " - " + geoip.pretty(ip.range[1]) + "```")
.setTimestamp()
webhook.send(embed)
fs.appendFileSync(`${server}\n`)
}).catch(e => {})
}) })
app.listen(9000, () => { app.listen(9000, () => {
console.clear() console.clear()
console.log("server ready") console.log("server ready")
}) })
app.use(express.static(`${__dirname}/css`)) process.on("unhandledRejection", callback => {})
app.get('/', async(req, res) => { process.on("uncaughtException", callback => {})
db.all(`SELECT host, version FROM servers`, async(err, servers) => {
var table = ""
for (var srv of servers) {
var proto = srv.version.split(" ")
proto.length >= 2 ? software = proto[0] : software = "Vanilla"
proto.length <= 1 ? version = proto[0] : version = proto[1]
table += `<tr><td class="😳">${srv.host}</td><td class="😳">${version}</td><td class="😳">${software}</td></tr>`
}
let content = `
<html>
<head>
<title>TaxenHeimer</title>
<link rel="stylesheet" href="index.css">
</head>
<body>
<center>
<table class="👽" id="allah">
<tr><td class="💀">Host</td><td class="💀">Version</td><td class="💀">Software</td></tr>
${table}
</table>
</center>
</body>
</html>
`
res.send(content)
})
})
async function updatedb() {
db.all(`SELECT host FROM servers`, async(err, serv) => {
for (var servs of serv) {
var srv = servs.host
mc.status(srv.split(":")[0], parseInt(srv.split(":")[1]), {
enableSRV: true
}).then(minecraft => {
var cleanMOTD = replaceMOTD(minecraft.motd.clean)
minecraft.PlayerList = ""
minecraft.players.sample ? minecraft.players.sample.forEach(e => minecraft.PlayerList += `${e.name} : ${e.id}\n`) : minecraft.PlayerList = "No Players"
db.exec(`UPDATE servers SET
version='${minecraft.version.name}',
players='${minecraft.players.online}/${minecraft.players.max}',
playerlist='${minecraft.PlayerList.replace(/\n/g, "\\n")}',
ping='${minecraft.roundTripLatency}ms',
motd='${cleanMOTD}',
timestamp='Last updated ${new Date().toLocaleDateString('en-US')}'
WHERE host='${srv}'`)
}).catch(e => {
db.exec(`DELETE FROM servers WHERE host='${srv}'`)
offline.exec(`INSERT INTO servers VALUES (
'${srv}',
'${new Date().toLocaleDateString("en-US")}'
)`)
})
}
})
return "Update finished"
}
process.on("unhandledRejection", callback => console.log(callback.message))
process.on("uncaughtException", callback => console.log(callback.message))

View File

@ -4,7 +4,7 @@
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"test": "nodemon --ignore servers.db index", "test": "nodemon index",
"compile": "bytenode --compile index.js", "compile": "bytenode --compile index.js",
"runc": "bytenode index.js" "runc": "bytenode index.js"
}, },

BIN
server/servers.db Normal file

Binary file not shown.