aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorterminaldweller <devi@terminaldweller.com>2025-08-17 22:06:33 +0000
committerterminaldweller <devi@terminaldweller.com>2025-08-17 22:06:33 +0000
commitfe0fe6da38dbf2b19a6a294a66a01809b8d961c7 (patch)
tree6d04935d826d27c1694c207ebd251554245e9bc7
parentaddes user agents. added aliases. (diff)
downloadmilla-main.tar.gz
milla-main.zip
ghost WIPHEADmain
-rw-r--r--ghost.go104
-rw-r--r--go.mod4
-rw-r--r--go.sum9
-rw-r--r--main.go10
-rw-r--r--plugins/euvd.lua72
-rw-r--r--types.go28
-rw-r--r--useragents.go3
7 files changed, 227 insertions, 3 deletions
diff --git a/ghost.go b/ghost.go
new file mode 100644
index 0000000..d3f4396
--- /dev/null
+++ b/ghost.go
@@ -0,0 +1,104 @@
+package main
+
+import (
+ "bufio"
+ "crypto/tls"
+ "io"
+ "log"
+ "net"
+ "sync"
+
+ ircgomsg "github.com/ergochat/irc-go/ircmsg"
+)
+
+func ghost(serverAddress, listenAddress string) {
+ listener, err := net.Listen("tcp", listenAddress)
+ if err != nil {
+ log.Fatalf("Failed to listen on %s: %v", listenAddress, err)
+ }
+ defer listener.Close()
+
+ log.Printf("IRC Bouncer listening on %s", listenAddress)
+ log.Printf("Connecting clients to IRC server: %s", serverAddress)
+
+ for {
+ clientConn, err := listener.Accept()
+ if err != nil {
+ log.Printf("Failed to accept client connection: %v", err)
+
+ continue
+ }
+
+ go handleClientConnection(clientConn, serverAddress)
+ }
+}
+
+func handleClientConnection(clientConn net.Conn, serverAddress string) {
+ log.Printf("Client connected from: %s", clientConn.RemoteAddr())
+
+ // ircServerConn, err := net.Dial("tcp", serverAddress)
+ ircServerConn, err := tls.Dial("tcp", serverAddress, nil)
+ if err != nil {
+ log.Printf("Failed to connect to IRC server %s: %v", serverAddress, err)
+ clientConn.Close()
+
+ return
+ }
+
+ log.Printf("Successfully connected to IRC server: %s", serverAddress)
+
+ done := make(chan struct{})
+
+ var once sync.Once
+
+ closeConnections := func() {
+ once.Do(func() {
+ clientConn.Close()
+ ircServerConn.Close()
+ close(done)
+ })
+ }
+
+ go relay(clientConn, ircServerConn, closeConnections)
+
+ go relay(ircServerConn, clientConn, closeConnections)
+
+ <-done
+ log.Printf("Connection closed for client: %s", clientConn.RemoteAddr())
+}
+
+func relay(src, dest net.Conn, closer func()) {
+ reader := bufio.NewReader(src)
+
+ for {
+ line, err := reader.ReadString('\n')
+ if err != nil {
+ if err != io.EOF {
+ log.Printf("Relay read error on: %v", err)
+ }
+ closer()
+
+ return
+ }
+
+ msg, err := ircgomsg.ParseLine(line)
+ if err != nil {
+ log.Printf("Failed to parse IRC message: %v", err)
+ }
+
+ if msg.Command == "PRIVMSG" {
+ }
+
+ if msg.Command == "MSG" {
+ }
+
+ log.Println(msg)
+
+ _, err = io.WriteString(dest, line)
+ if err != nil {
+ closer()
+
+ return
+ }
+ }
+}
diff --git a/go.mod b/go.mod
index 4be11d5..c6eefb7 100644
--- a/go.mod
+++ b/go.mod
@@ -10,6 +10,8 @@ require (
github.com/alecthomas/chroma/v2 v2.16.0
github.com/cenkalti/backoff/v5 v5.0.2
github.com/cjoudrey/gluahttp v0.0.0-20201111170219-25003d9adfa9
+ github.com/coyim/otr3 v0.0.0-20230314203300-86897a28af47
+ github.com/ergochat/irc-go v0.4.0
github.com/jackc/pgx/v5 v5.7.4
github.com/kohkimakimoto/gluayaml v0.0.0-20160815032708-6fe413d49d73
github.com/layeh/gopher-json v0.0.0-20201124131017-552bb3c4c3bf
@@ -29,6 +31,8 @@ require (
cloud.google.com/go/compute/metadata v0.6.0 // indirect
github.com/PuerkitoBio/goquery v1.10.3 // indirect
github.com/andybalholm/cascadia v1.3.3 // indirect
+ github.com/awnumar/memcall v0.1.2 // indirect
+ github.com/coyim/constbn v0.0.0-20230207191538-27f0129d98cd // indirect
github.com/dlclark/regexp2 v1.11.5 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/go-logr/logr v1.4.2 // indirect
diff --git a/go.sum b/go.sum
index 41704ed..3bd7354 100644
--- a/go.sum
+++ b/go.sum
@@ -18,15 +18,23 @@ github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc
github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
github.com/andybalholm/cascadia v1.3.3 h1:AG2YHrzJIm4BZ19iwJ/DAua6Btl3IwJX+VI4kktS1LM=
github.com/andybalholm/cascadia v1.3.3/go.mod h1:xNd9bqTn98Ln4DwST8/nG+H0yuB8Hmgu1YHNnWw0GeA=
+github.com/awnumar/memcall v0.1.2 h1:7gOfDTL+BJ6nnbtAp9+HQzUFjtP1hEseRQq8eP055QY=
+github.com/awnumar/memcall v0.1.2/go.mod h1:S911igBPR9CThzd/hYQQmTc9SWNu3ZHIlCGaWsWsoJo=
github.com/cenkalti/backoff/v5 v5.0.2 h1:rIfFVxEf1QsI7E1ZHfp/B4DF/6QBAUhmgkxc0H7Zss8=
github.com/cenkalti/backoff/v5 v5.0.2/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
github.com/cjoudrey/gluahttp v0.0.0-20201111170219-25003d9adfa9 h1:rdWOzitWlNYeUsXmz+IQfa9NkGEq3gA/qQ3mOEqBU6o=
github.com/cjoudrey/gluahttp v0.0.0-20201111170219-25003d9adfa9/go.mod h1:X97UjDTXp+7bayQSFZk2hPvCTmTZIicUjZQRtkwgAKY=
+github.com/coyim/constbn v0.0.0-20230207191538-27f0129d98cd h1:tWNy3iPXxx5wmWH8qm7TuDM9vDLWWj18Pp7uxUQILpo=
+github.com/coyim/constbn v0.0.0-20230207191538-27f0129d98cd/go.mod h1:3IbgUXKHr9lHYW0qRClJ+UiGNwcvWm5Ce1iOY2Pe/oA=
+github.com/coyim/otr3 v0.0.0-20230314203300-86897a28af47 h1:mL+cP7RQUnuAhGW4+wPouDQEU1YuslV/4vjkcI4Ec2w=
+github.com/coyim/otr3 v0.0.0-20230314203300-86897a28af47/go.mod h1:7iUG2JMfJTDx4XgHkrSsCtS3iLGCnuEjuZXoXO3lBrc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ=
github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
+github.com/ergochat/irc-go v0.4.0 h1:0YibCKfAAtwxQdNjLQd9xpIEPisLcJ45f8FNsMHAuZc=
+github.com/ergochat/irc-go v0.4.0/go.mod h1:2vi7KNpIPWnReB5hmLpl92eMywQvuIeIIGdt/FQCph0=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
@@ -147,6 +155,7 @@ golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
diff --git a/main.go b/main.go
index ba7f379..ae0273b 100644
--- a/main.go
+++ b/main.go
@@ -467,6 +467,14 @@ func runCommand(
}
appConfig.deleteLstate(args[1])
+ case "list":
+ if !isFromAdmin(appConfig.Admins, event) {
+ break
+ }
+
+ for key, value := range appConfig.LuaCommands {
+ client.Cmd.Reply(event, fmt.Sprintf("%s: %s", key, value.Path))
+ }
case "remind":
if len(args) < 2 { //nolint: mnd,gomnd
client.Cmd.Message(event.Source.Name, errNotEnoughArgs.Error())
@@ -555,7 +563,7 @@ func runCommand(
query = strings.TrimPrefix(cmd, args[0])
}
- log.Println(args[1], query)
+ log.Println("query:", query)
response := UserAgentsGet(args[1], query, appConfig)
// client.Cmd.Reply(event, response)
diff --git a/plugins/euvd.lua b/plugins/euvd.lua
new file mode 100644
index 0000000..9b67831
--- /dev/null
+++ b/plugins/euvd.lua
@@ -0,0 +1,72 @@
+local milla = require("milla")
+local os = require("os")
+local json = require("json")
+
+-- https://euvd.enisa.europa.eu/apidoc
+function euvd(cli_args)
+ local args = {}
+ for i in string.gmatch(cli_args, "%S+") do table.insert(args, i) end
+
+ os.setenv("http_proxy", "http://172.17.0.1:8120")
+
+ local http = require("http")
+ local url
+
+ local url_latest =
+ "https://euvdservices.enisa.europa.eu/api/lastvulnerabilities"
+ local url_exploited =
+ "https://euvdservices.enisa.europa.eu/api/exploitedvulnerabilities"
+ local url_critical =
+ "https://euvdservices.enisa.europa.eu/api/criticalvulnerabilities"
+
+ if args[1] == "latest" then
+ url = url_latest
+ elseif args[1] == "exploited" then
+ url = url_exploited
+ elseif args[1] == "critical" then
+ url = url_critical
+ else
+ return "Invalid command"
+ end
+
+ local response, err = http.request("GET", url, {timeout = "10s"})
+ if err ~= nil then
+ print(err)
+ return err
+ end
+ print(response.body)
+
+ local json_response, err = json.decode(response.body)
+ if err ~= nil then
+ print(err)
+ return err
+ end
+
+ if response.status_code ~= 200 then
+ return "Error: " .. response.status_code
+ end
+
+ local result = ""
+ for k, v in ipairs(json_response) do
+ result = result .. "id: " .. v["id"] .. "\n"
+ result = result .. "description: " .. v["description"] .. "\n"
+ result = result .. "datePublished: " .. v["datePublished"] .. "\n"
+ result = result .. "dateUpdated: " .. v["dateUpdated"] .. "\n"
+ result = result .. "baseScore: " .. v["baseScore"] .. "\n"
+ result = result .. "baseScoreVersion: " .. v["baseScoreVersion"] .. "\n"
+ result = result .. "baseScoreVector: " .. v["baseScoreVector"] .. "\n"
+ result = result .. "references: " .. v["references"] .. "\n"
+ result = result .. "aliases: " .. v["aliases"] .. "\n"
+ result = result .. "assigner: " .. v["assigner"] .. "\n"
+ result = result .. "epss: " .. v["epss"] .. "\n"
+ result = result ..
+ "----------------------------------------------------------------" ..
+ "\n"
+ end
+
+ print(result)
+
+ return result
+end
+
+milla.register_cmd("/plugins/euvd.lua", "euvd", "euvd")
diff --git a/types.go b/types.go
index f796b66..2939645 100644
--- a/types.go
+++ b/types.go
@@ -207,7 +207,8 @@ func (config *TomlConfig) deleteTriggeredScript(name string) {
}
type AppConfig struct {
- Ircd map[string]TomlConfig `toml:"ircd"`
+ Ircd map[string]TomlConfig `toml:"ircd"`
+ Ghost map[string]GhostNetwork `toml:"ghost"`
}
type OllamaRequestOptions struct {
@@ -328,3 +329,28 @@ type UserAgentResponse struct {
type Alias struct {
Alias string `toml:"alias"`
}
+
+type GhostRuleSet struct {
+ DisableAll bool `toml:"disableAll"`
+ WhiteList []string `toml:"whiteList"`
+ EnableAll bool `toml:"enableAll"`
+ BlackList []string `toml:"blackList"`
+ Outward bool `toml:"outward"`
+}
+
+type GhostNetwork struct {
+ ServerAddress string `toml:"serverAddress"`
+ UseTLS bool `toml:"useTLS"`
+ SkipTLSVerify bool `toml:"skipTLSVerify"`
+ Nick string `toml:"nick"`
+ SaslUser string `toml:"saslUser"`
+ SaslPass string `toml:"saslPass"`
+ CertPath string `toml:"certPath"`
+ KeyPath string `toml:"keyPath"`
+ ListenAddress string `toml:"listenAddress"`
+ Rephrase bool `toml:"rephrase"`
+ OllamaEndpoint string `toml:"ollamaEndpoint"`
+ Instructions []string `toml:"instructions"`
+ Prompt string `toml:"prompt"`
+ GhostRuleSets []GhostRuleSet `toml:"ghostRuleSets"`
+}
diff --git a/useragents.go b/useragents.go
index 0c51e61..fd2d3b8 100644
--- a/useragents.go
+++ b/useragents.go
@@ -29,10 +29,11 @@ func UserAgentsGet(uaActionName, query string, appConfig *TomlConfig) string {
userAgentRequest.Agent_Name = appConfig.UserAgentActions[uaActionName].Agent_Name
userAgentRequest.Instructions = appConfig.UserAgentActions[uaActionName].Instructions
- userAgentRequest.Query = appConfig.UserAgentActions[uaActionName].Query
if query != "" {
userAgentRequest.Query = query
+ } else {
+ userAgentRequest.Query = appConfig.UserAgentActions[uaActionName].Query
}
log.Println("UserAgentRequest:", appConfig.UserAgentActions[uaActionName])