gBBS/internal/telnet/telnet.go

171 lines
4.6 KiB
Go

package telnet
import (
"bufio"
"fmt"
"gbbs/internal/config"
"gbbs/internal/messageboard"
"gbbs/internal/prompt"
"gbbs/internal/user"
"net"
"strings"
"time"
)
func Serve(cfg *config.Config, userManager *user.Manager, messageBoard *messageboard.MessageBoard) error {
listener, err := net.Listen("tcp", fmt.Sprintf(":%d", cfg.TelnetPort))
if err != nil {
return err
}
defer listener.Close()
for {
conn, err := listener.Accept()
if err != nil {
continue
}
go handleConnection(conn, cfg, userManager, messageBoard)
}
}
func handleConnection(conn net.Conn, cfg *config.Config, userManager *user.Manager, messageBoard *messageboard.MessageBoard) {
defer conn.Close()
writer := bufio.NewWriter(conn)
reader := bufio.NewReader(conn)
welcomeScreen, err := prompt.ReadWelcomeScreen(cfg)
if err != nil {
fmt.Fprintf(writer, "Error reading welcome screen: %v\n", err)
return
}
fmt.Fprint(writer, welcomeScreen)
writer.Flush()
for {
fmt.Fprintf(writer, "\n\033[0;31mPlease choose an option:\033[0m\n")
fmt.Fprintf(writer, "\033[1;32mL\033[0m - Login\n")
fmt.Fprintf(writer, "\033[1;32mR\033[0m - Register\n\n")
fmt.Fprintf(writer, "\033[0;32mYour choice: \033[0m")
writer.Flush()
choice, _ := reader.ReadString('\n')
choice = strings.TrimSpace(choice)
if strings.EqualFold(choice, "L") {
username, err := login(reader, writer, userManager)
if err != nil {
fmt.Fprintf(writer, "\033[0;31mLogin failed: %v\033[0m\n", err)
writer.Flush()
continue
}
fmt.Fprintf(writer, "\n\033[1;32mLogin successful! Welcome, %s!\033[0m\n", username)
writer.Flush()
time.Sleep(2 * time.Second) // Pause for 2 seconds to show the message
handleBBS(username, reader, writer, messageBoard)
return
} else if strings.EqualFold(choice, "R") {
username, err := register(reader, writer, userManager)
if err != nil {
fmt.Fprintf(writer, "\033[0;31mRegistration failed: %v\033[0m\n", err)
writer.Flush()
continue
}
fmt.Fprintf(writer, "\n\033[1;32mRegistration successful! Welcome, %s!\033[0m\n", username)
writer.Flush()
time.Sleep(2 * time.Second) // Pause for 2 seconds to show the message
handleBBS(username, reader, writer, messageBoard)
return
} else {
fmt.Fprintf(writer, "\033[0;31mInvalid choice. Please try again.\033[0m\n")
writer.Flush()
}
}
}
func login(reader *bufio.Reader, writer *bufio.Writer, userManager *user.Manager) (string, error) {
fmt.Fprintf(writer, "Username: ")
writer.Flush()
username, _ := reader.ReadString('\n')
username = strings.TrimSpace(username)
fmt.Fprintf(writer, "Password: ")
writer.Flush()
password, _ := reader.ReadString('\n')
password = strings.TrimSpace(password)
authenticated, err := userManager.Authenticate(username, password)
if err != nil {
return "", err
}
if !authenticated {
return "", fmt.Errorf("invalid username or password")
}
return username, nil
}
func register(reader *bufio.Reader, writer *bufio.Writer, userManager *user.Manager) (string, error) {
fmt.Fprintf(writer, "Choose a username: ")
writer.Flush()
username, _ := reader.ReadString('\n')
username = strings.TrimSpace(username)
fmt.Fprintf(writer, "Choose a password: ")
writer.Flush()
password, _ := reader.ReadString('\n')
password = strings.TrimSpace(password)
err := userManager.CreateUser(username, password)
if err != nil {
return "", err
}
return username, nil
}
func handleBBS(username string, reader *bufio.Reader, writer *bufio.Writer, messageBoard *messageboard.MessageBoard) {
for {
fmt.Fprintf(writer, "\n\033[0;36mBBS Menu:\033[0m\n")
fmt.Fprintf(writer, "1. Read messages\n")
fmt.Fprintf(writer, "2. Post message\n")
fmt.Fprintf(writer, "3. Logout\n")
fmt.Fprintf(writer, "Choice: ")
writer.Flush()
choice, _ := reader.ReadString('\n')
choice = strings.TrimSpace(choice)
switch choice {
case "1":
messages, err := messageBoard.GetMessages()
if err != nil {
fmt.Fprintf(writer, "\033[0;31mError reading messages: %v\033[0m\n", err)
} else {
for _, msg := range messages {
fmt.Fprintf(writer, "%s\n", msg)
}
}
case "2":
fmt.Fprintf(writer, "Enter your message: ")
writer.Flush()
message, _ := reader.ReadString('\n')
message = strings.TrimSpace(message)
err := messageBoard.PostMessage(username, message)
if err != nil {
fmt.Fprintf(writer, "\033[0;31mError posting message: %v\033[0m\n", err)
} else {
fmt.Fprintf(writer, "\033[0;32mMessage posted successfully!\033[0m\n")
}
case "3":
fmt.Fprintf(writer, "\033[0;33mGoodbye!\033[0m\n")
writer.Flush()
return
default:
fmt.Fprintf(writer, "\033[0;31mInvalid choice. Please try again.\033[0m\n")
}
writer.Flush()
}
}