Files
IRC-kosmi-relay/cmd/kosmi-client/main.go

147 lines
3.3 KiB
Go

package main
import (
"bufio"
"flag"
"fmt"
"log"
"os"
"os/signal"
"strings"
"syscall"
"time"
)
var (
token = flag.String("token", "", "JWT token for authentication (get from browser DevTools)")
room = flag.String("room", "", "Room ID to join (e.g., @hyperspaceout)")
email = flag.String("email", "", "Email for login (requires --password, not yet implemented)")
password = flag.String("password", "", "Password for login (requires --email, not yet implemented)")
)
func main() {
flag.Parse()
// Validate required flags
if *room == "" {
log.Fatal("Error: --room is required")
}
// Get authentication token
authToken, err := GetToken(*token, *email, *password)
if err != nil {
log.Fatalf("Authentication error: %v", err)
}
// Create client
client := NewKosmiClient(authToken, *room)
// Set up message handler to print incoming messages
client.SetMessageHandler(func(msg Message) {
timestamp := formatTime(msg.Time)
fmt.Printf("\r[%s] %s: %s\n> ", timestamp, msg.DisplayName, msg.Body)
})
// Connect to Kosmi
if err := client.Connect(); err != nil {
log.Fatalf("Connection error: %v", err)
}
// Set up graceful shutdown
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
// Start goroutine to handle shutdown signal
shutdownChan := make(chan struct{})
go func() {
<-sigChan
fmt.Println("\n\nReceived interrupt signal, shutting down gracefully...")
close(shutdownChan)
}()
// Print usage instructions
fmt.Println("\n" + strings.Repeat("=", 60))
fmt.Println("Connected! Type messages and press Enter to send.")
fmt.Println("Press Ctrl+C to exit.")
fmt.Println(strings.Repeat("=", 60) + "\n")
// Start interactive CLI loop
go func() {
scanner := bufio.NewScanner(os.Stdin)
fmt.Print("> ")
for scanner.Scan() {
select {
case <-shutdownChan:
return
default:
}
text := strings.TrimSpace(scanner.Text())
// Skip empty messages
if text == "" {
fmt.Print("> ")
continue
}
// Handle special commands
if text == "/quit" || text == "/exit" {
fmt.Println("Exiting...")
close(shutdownChan)
return
}
if text == "/help" {
printHelp()
fmt.Print("> ")
continue
}
// Send the message
if err := client.SendMessage(text); err != nil {
fmt.Printf("\rError sending message: %v\n> ", err)
} else {
// Clear the line and reprint prompt
fmt.Print("> ")
}
}
if err := scanner.Err(); err != nil {
log.Printf("Scanner error: %v", err)
}
}()
// Wait for shutdown signal
<-shutdownChan
// Close the client gracefully
if err := client.Close(); err != nil {
log.Printf("Error closing client: %v", err)
}
// Give a moment for cleanup
time.Sleep(200 * time.Millisecond)
fmt.Println("Goodbye!")
}
// formatTime converts ISO timestamp to readable format
func formatTime(isoTime string) string {
t, err := time.Parse(time.RFC3339, isoTime)
if err != nil {
return isoTime
}
return t.Format("15:04:05")
}
// printHelp displays available commands
func printHelp() {
fmt.Println("\nAvailable commands:")
fmt.Println(" /help - Show this help message")
fmt.Println(" /quit - Exit the client")
fmt.Println(" /exit - Exit the client")
fmt.Println("\nJust type any text and press Enter to send a message.")
}