package main import ( "fmt" "log" "net" "strings" "crypto/tls" "github.com/oschwald/geoip2-golang" "github.com/thoj/go-ircevent" ) func main() { config, err := LoadConfig("config.json") if err != nil { log.Fatalf("Error loading config: %v", err) } irccon := irc.IRC(config.Nickname, config.Nickname) irccon.VerboseCallbackHandler = true irccon.Debug = true irccon.UseTLS = config.SSL irccon.TLSConfig = &tls.Config{InsecureSkipVerify: true} err = irccon.Connect(fmt.Sprintf("%s:%d", config.IRCServer, config.IRCPort)) if err != nil { log.Fatalf("Failed to connect to IRC server: %v", err) } irccon.AddCallback("001", func(e *irc.Event) { for _, channel := range config.Channels { irccon.Join(channel) } }) irccon.AddCallback("PRIVMSG", func(e *irc.Event) { if len(e.Arguments) < 2 { return } message := e.Arguments[1] parts := strings.Fields(message) if len(parts) == 0 { return } cmd := strings.TrimPrefix(parts[0], "!") if commandFunc, ok := commands[cmd]; ok { commandFunc(irccon, e, parts) } }) irccon.Loop() } type CommandFunc func(irccon *irc.Connection, e *irc.Event, args []string) var commands = map[string]CommandFunc{ "geoip": handleGeoIPCommand, // add more commands here } func handleGeoIPCommand(irccon *irc.Connection, e *irc.Event, args []string) { if len(args) < 2 { irccon.Privmsg(e.Arguments[0], "Usage: !geoip ") return } ipOrDomain := args[1] config, err := LoadConfig("config.json") if err != nil { log.Fatalf("Error loading config: %v", err) } cityDbPath := config.GeoIPDatabase // Update with actual path asnDbPath := config.GeoIPASN // Update with actual path ip := net.ParseIP(ipOrDomain) if ip == nil { resolvedIP, err := net.LookupIP(ipOrDomain) if err != nil || len(resolvedIP) == 0 { irccon.Privmsg(e.Arguments[0], fmt.Sprintf("Invalid IP address or domain: %s", ipOrDomain)) return } ip = resolvedIP[0] } var ( city = "N/A" subdivision = "N/A" country = "N/A" latitude = "N/A" longitude = "N/A" asn = "N/A" isp = "N/A" ) // Lookup City Information if cityDb, err := geoip2.Open(cityDbPath); err == nil { defer cityDb.Close() if cityRecord, err := cityDb.City(ip); err == nil { if name := cityRecord.City.Names["en"]; name != "" { city = name } if len(cityRecord.Subdivisions) > 0 { if name := cityRecord.Subdivisions[0].Names["en"]; name != "" { subdivision = name } } if name := cityRecord.Country.Names["en"]; name != "" { country = name } if lat := cityRecord.Location.Latitude; lat != 0 { latitude = fmt.Sprintf("%.6f", lat) } if lon := cityRecord.Location.Longitude; lon != 0 { longitude = fmt.Sprintf("%.6f", lon) } } else { log.Printf("City lookup error: %v", err) } } else { log.Printf("Error opening City database: %v", err) } // Lookup ASN Information if asnDb, err := geoip2.Open(asnDbPath); err == nil { defer asnDb.Close() if asnRecord, err := asnDb.ASN(ip); err == nil { if asnNum := asnRecord.AutonomousSystemNumber; asnNum != 0 { asn = fmt.Sprintf("%d", asnNum) } if org := asnRecord.AutonomousSystemOrganization; org != "" { isp = org } } else { log.Printf("ASN lookup error: %v", err) } } else { log.Printf("Error opening ASN database: %v", err) } response := fmt.Sprintf( "IP: %s | Location: %s, %s, %s | Coordinates: %s, %s | ASN: %s | ISP: %s", ip.String(), city, subdivision, country, latitude, longitude, asn, isp, ) irccon.Privmsg(e.Arguments[0], response) }