add channel auto join function

main
Philip Meyerdierks 2025-09-16 10:32:13 +02:00
parent 21d2e5f7d2
commit 3cad908f1f
4 changed files with 190 additions and 9 deletions

View File

@ -10,6 +10,7 @@ import (
"strconv"
"strings"
"sync"
"xdcc-cli/config"
"xdcc-cli/pb"
"xdcc-cli/search"
table "xdcc-cli/table"
@ -158,7 +159,7 @@ func loadUrlListFile(filePath string) []string {
}
func printGetUsageAndExit(flagSet *flag.FlagSet) {
fmt.Printf("usage: get url1 url2 ... [-o path] [-i file] [--ssl-only]\n\nFlag set:\n")
fmt.Printf("usage: get url1 url2 ... [-o path] [-i file] [--ssl-only] [-c config]\n\nFlag set:\n")
flagSet.PrintDefaults()
os.Exit(0)
}
@ -167,11 +168,18 @@ func execGet(args []string) {
getCmd := flag.NewFlagSet("get", flag.ExitOnError)
path := getCmd.String("o", ".", "output folder of dowloaded file")
inputFile := getCmd.String("i", "", "input file containing a list of urls")
configFile := getCmd.String("c", "", "config file for network-channel mappings (defaults to ~/.xdcc-cli-config.json)")
sslOnly := getCmd.Bool("ssl-only", false, "force the client to use TSL connection")
urlList := parseFlags(getCmd, args)
// Bestimme den Konfigurationspfad
configPath := *configFile
if configPath == "" {
configPath = config.DefaultConfigPath()
}
if *inputFile != "" {
urlList = append(urlList, loadUrlListFile(*inputFile)...)
}
@ -194,9 +202,10 @@ func execGet(args []string) {
}
transfer := xdcc.NewTransfer(xdcc.Config{
File: *url,
OutPath: *path,
SSLOnly: *sslOnly,
File: *url,
OutPath: *path,
SSLOnly: *sslOnly,
ConfigPath: configPath,
})
wg.Add(1)

138
config/config.go Normal file
View File

@ -0,0 +1,138 @@
package config
import (
"encoding/json"
"fmt"
"io"
"os"
"path/filepath"
"strings"
)
// NetworkChannelsConfig definiert die Konfiguration für automatische Channel-Joins
type NetworkChannelsConfig struct {
Networks map[string][]string `json:"networks"`
}
// DefaultConfigPath gibt den Standardpfad für die Konfigurationsdatei zurück
func DefaultConfigPath() string {
homeDir, err := os.UserHomeDir()
if err != nil {
return ".xdcc-cli-config.json"
}
return filepath.Join(homeDir, ".xdcc-cli-config.json")
}
// LoadConfig lädt die Konfiguration aus einer JSON-Datei
func LoadConfig(configPath string) (*NetworkChannelsConfig, error) {
// Wenn die Datei nicht existiert, gibt eine leere Konfiguration zurück
if _, err := os.Stat(configPath); os.IsNotExist(err) {
return &NetworkChannelsConfig{
Networks: make(map[string][]string),
}, nil
}
file, err := os.Open(configPath)
if err != nil {
return nil, fmt.Errorf("fehler beim Öffnen der Konfigurationsdatei: %v", err)
}
defer file.Close()
data, err := io.ReadAll(file)
if err != nil {
return nil, fmt.Errorf("fehler beim Lesen der Konfigurationsdatei: %v", err)
}
var config NetworkChannelsConfig
if err := json.Unmarshal(data, &config); err != nil {
return nil, fmt.Errorf("fehler beim Parsen der Konfigurationsdatei: %v", err)
}
// Initialisiere Networks falls nil
if config.Networks == nil {
config.Networks = make(map[string][]string)
}
return &config, nil
}
// SaveConfig speichert die Konfiguration in eine JSON-Datei
func SaveConfig(configPath string, config *NetworkChannelsConfig) error {
data, err := json.MarshalIndent(config, "", " ")
if err != nil {
return fmt.Errorf("fehler beim Serialisieren der Konfiguration: %v", err)
}
if err := os.WriteFile(configPath, data, 0644); err != nil {
return fmt.Errorf("fehler beim Schreiben der Konfigurationsdatei: %v", err)
}
return nil
}
// GetChannelsForNetwork gibt die konfigurierten Channels für ein Netzwerk zurück
func (c *NetworkChannelsConfig) GetChannelsForNetwork(network string) []string {
channels, exists := c.Networks[network]
if !exists {
return []string{}
}
// Stelle sicher, dass alle Channels mit # beginnen
normalizedChannels := make([]string, len(channels))
for i, channel := range channels {
if channel != "" && !strings.HasPrefix(channel, "#") {
normalizedChannels[i] = "#" + channel
} else {
normalizedChannels[i] = channel
}
}
return normalizedChannels
}
// AddChannelToNetwork fügt einen Channel zu einem Netzwerk hinzu
func (c *NetworkChannelsConfig) AddChannelToNetwork(network, channel string) {
if c.Networks == nil {
c.Networks = make(map[string][]string)
}
// Normalisiere den Channel-Namen
if channel != "" && !strings.HasPrefix(channel, "#") {
channel = "#" + channel
}
// Prüfe ob der Channel bereits existiert
for _, existingChannel := range c.Networks[network] {
if existingChannel == channel {
return // Channel bereits vorhanden
}
}
c.Networks[network] = append(c.Networks[network], channel)
}
// RemoveChannelFromNetwork entfernt einen Channel von einem Netzwerk
func (c *NetworkChannelsConfig) RemoveChannelFromNetwork(network, channel string) {
if c.Networks == nil {
return
}
// Normalisiere den Channel-Namen
if channel != "" && !strings.HasPrefix(channel, "#") {
channel = "#" + channel
}
channels := c.Networks[network]
for i, existingChannel := range channels {
if existingChannel == channel {
// Entferne den Channel aus dem Slice
c.Networks[network] = append(channels[:i], channels[i+1:]...)
break
}
}
// Entferne das Netzwerk wenn keine Channels mehr vorhanden sind
if len(c.Networks[network]) == 0 {
delete(c.Networks, network)
}
}

16
config/config.json Normal file
View File

@ -0,0 +1,16 @@
{
"networks": {
"irc.rizon.net": [
"#elitewarez"
],
"irc.highway.net": [
"#beast-xdcc",
"#moviegods"
],
"irc.abjects.net": [
"#beast-xdcc",
"#moviegods",
"#mg-chat"
]
}
}

View File

@ -13,6 +13,7 @@ import (
"strconv"
"strings"
"time"
"xdcc-cli/config"
irc "github.com/fluffle/goirc/client"
)
@ -168,9 +169,10 @@ type XdccTransfer struct {
}
type Config struct {
File IRCFile
OutPath string
SSLOnly bool
File IRCFile
OutPath string
SSLOnly bool
ConfigPath string
}
func NewTransfer(c Config) Transfer {
@ -207,7 +209,7 @@ func newXdccTransfer(c Config, enableSSL bool, skipCertificateCheck bool) *XdccT
connAttempts: 0,
events: make(chan TransferEvent, defaultEventChanSize),
}
t.setupHandlers(file.Channel, file.UserName, file.Slot)
t.setupHandlers(file.Channel, file.UserName, file.Slot, c.ConfigPath)
return t
}
@ -215,14 +217,30 @@ func (transfer *XdccTransfer) send(req CTCPRequest) {
transfer.conn.Privmsg(transfer.url.UserName, req.String())
}
func (transfer *XdccTransfer) setupHandlers(channel string, userName string, slot int) {
func (transfer *XdccTransfer) setupHandlers(channel string, userName string, slot int, configPath string) {
conn := transfer.conn
// e.g. join channel on connect.
conn.HandleFunc(irc.CONNECTED,
func(conn *irc.Conn, line *irc.Line) {
transfer.connAttempts = 0
// Betrete den Haupt-Channel (für den Download)
conn.Join(channel)
// Lade die Konfiguration und betrete zusätzliche Channels
if configPath != "" {
if cfg, err := config.LoadConfig(configPath); err == nil {
additionalChannels := cfg.GetChannelsForNetwork(transfer.url.Network)
for _, additionalChannel := range additionalChannels {
// Verhindere doppeltes Betreten des gleichen Channels
if !strings.EqualFold(additionalChannel, channel) {
conn.Join(additionalChannel)
}
}
}
// Ignoriere Konfigurationsfehler stillschweigend - die Anwendung soll weiter funktionieren
}
})
conn.HandleFunc(irc.ERROR, func(conn *irc.Conn, line *irc.Line) {