Final PR #1
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
Copyright © 2024 Raul
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"github.com/jroimartin/gocui"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
// clientCmd represents the client command
|
||||||
|
var clientCmd = &cobra.Command{
|
||||||
|
Use: "client",
|
||||||
|
Short: "Connect to a mini-chat server",
|
||||||
|
Long: `Connect to a mini-chat server.
|
||||||
|
Example:
|
||||||
|
./mini-chat client --ip 192.168.0.50 --port 1337`,
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
client(cmd)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
var conn net.Conn
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
rootCmd.AddCommand(clientCmd)
|
||||||
|
|
||||||
|
// Here you will define your flags and configuration settings.
|
||||||
|
|
||||||
|
// Cobra supports Persistent Flags which will work for this command
|
||||||
|
// and all subcommands, e.g.:
|
||||||
|
// clientCmd.PersistentFlags().String("foo", "", "A help for foo")
|
||||||
|
clientCmd.Flags().String("ip", "", "Server to connect to")
|
||||||
|
clientCmd.Flags().String("port", "1302", "Port to connect to")
|
||||||
|
|
||||||
|
// Cobra supports local flags which will only run when this command
|
||||||
|
// is called directly, e.g.:
|
||||||
|
// clientCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
||||||
|
}
|
||||||
|
|
||||||
|
func client(cmd *cobra.Command) {
|
||||||
|
port, _ := cmd.Flags().GetString("port")
|
||||||
|
ip, _ := cmd.Flags().GetString("ip")
|
||||||
|
if ip == "" {
|
||||||
|
fmt.Println("Not enough arguments, run \"-h\" parameter to see all the parameters!")
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
if port == "" {
|
||||||
|
port = "1302"
|
||||||
|
}
|
||||||
|
socket := ip + ":" + port
|
||||||
|
conn, err = net.Dial("tcp", socket)
|
||||||
|
cobra.CheckErr(err)
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
reply := make([]byte, 1024)
|
||||||
|
conn.Read(reply)
|
||||||
|
fmt.Print(string(reply))
|
||||||
|
|
||||||
|
msg, err := bufio.NewReader(os.Stdin).ReadString('\n')
|
||||||
|
cobra.CheckErr(err)
|
||||||
|
conn.Write([]byte(msg))
|
||||||
|
|
||||||
|
ui(conn)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendmsg(g *gocui.Gui, v *gocui.View) error {
|
||||||
|
textarea, err := g.View("textarea")
|
||||||
|
if err != nil {
|
||||||
|
log.Panicln(err)
|
||||||
|
}
|
||||||
|
message := textarea.Buffer()
|
||||||
|
msg := string(message)
|
||||||
|
if msg == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if msg == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprint(conn, msg)
|
||||||
|
textarea.Clear()
|
||||||
|
textarea.SetCursor(0, 0)
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -90,25 +90,11 @@ func masterReceiver(slaveChannel chan<- string, masterChannel <-chan string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// func receiver(conn net.Conn, ch chan string) {
|
|
||||||
// fmt.Println("THE RECEIVER HAS BEEN STARTED, YOU CAN ONLY SEE THIS MESSAGE ONCE")
|
|
||||||
// receiverIsStarted = false
|
|
||||||
// for {
|
|
||||||
// select {
|
|
||||||
// case otherMessage := <-ch:
|
|
||||||
// conn.Write([]byte(otherMessage))
|
|
||||||
// default:
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
func handleConn(conn net.Conn, slaveChannel <-chan string, masterChannel chan<- string) {
|
func handleConn(conn net.Conn, slaveChannel <-chan string, masterChannel chan<- string) {
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
//var otherMessage string
|
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
//select {
|
|
||||||
message := <-slaveChannel
|
message := <-slaveChannel
|
||||||
conn.Write([]byte(message))
|
conn.Write([]byte(message))
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/jroimartin/gocui"
|
||||||
|
"github.com/nsf/termbox-go"
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ui(conn net.Conn) {
|
||||||
|
g, err := gocui.NewGui(gocui.OutputNormal)
|
||||||
|
if err != nil {
|
||||||
|
log.Panicln(err)
|
||||||
|
}
|
||||||
|
defer g.Close()
|
||||||
|
g.SetManagerFunc(layout)
|
||||||
|
g.Mouse = true
|
||||||
|
g.Cursor = true
|
||||||
|
initKeybindings(g)
|
||||||
|
|
||||||
|
go listener(g, conn)
|
||||||
|
|
||||||
|
if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
|
||||||
|
log.Panicln(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func listener(g *gocui.Gui, conn net.Conn) {
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
chatbox, err := g.View("chatbox")
|
||||||
|
if err != nil {
|
||||||
|
log.Panicln(err)
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
reply := make([]byte, 2048)
|
||||||
|
_, err := conn.Read(reply)
|
||||||
|
if err != nil {
|
||||||
|
g.Close()
|
||||||
|
log.Fatalf("Server closed connection\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintln(chatbox, string(reply))
|
||||||
|
termbox.Interrupt()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func quit(*gocui.Gui, *gocui.View) error {
|
||||||
|
return gocui.ErrQuit
|
||||||
|
}
|
||||||
|
|
||||||
|
func initKeybindings(g *gocui.Gui) error {
|
||||||
|
if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil {
|
||||||
|
log.Panicln(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := g.SetKeybinding("button", gocui.MouseLeft, gocui.ModNone, sendmsg); err != nil {
|
||||||
|
log.Panicln(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := g.SetKeybinding("textarea", gocui.KeyEnter, gocui.ModNone, sendmsg); err != nil {
|
||||||
|
log.Panicln(err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func layout(g *gocui.Gui) error {
|
||||||
|
maxX, maxY := g.Size()
|
||||||
|
|
||||||
|
if chatbox, err := g.SetView("chatbox", 2, 1, maxX/2+40, maxY-6); err != nil {
|
||||||
|
if err != gocui.ErrUnknownView {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
chatbox.Title = "Chat Box"
|
||||||
|
}
|
||||||
|
|
||||||
|
if button, err := g.SetView("button", maxX/2+32, maxY-4, maxX/2+40, maxY-2); err != nil {
|
||||||
|
if err != gocui.ErrUnknownView {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
//button.BgColor = gocui.ColorRed
|
||||||
|
button.Wrap = true
|
||||||
|
button.Frame = true
|
||||||
|
fmt.Fprintln(button, "Send it")
|
||||||
|
}
|
||||||
|
|
||||||
|
if textarea, err := g.SetView("textarea", 2, maxY-4, maxX/2+28, maxY-2); err != nil {
|
||||||
|
if err != gocui.ErrUnknownView {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := g.SetCurrentView("textarea"); err != nil {
|
||||||
|
log.Panicln(err)
|
||||||
|
}
|
||||||
|
textarea.Title = "Send message"
|
||||||
|
textarea.Wrap = true
|
||||||
|
textarea.Editable = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// if currentUsers, err := g.SetView("currentUsers", maxX/2+42, 1, maxX-6, maxY-6); err != nil {
|
||||||
|
// if err != gocui.ErrUnknownView {
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
|
// currentUsers.Title = "Connected users"
|
||||||
|
// }
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
8
go.mod
8
go.mod
|
@ -2,9 +2,15 @@ module mini-chat
|
||||||
|
|
||||||
go 1.22.1
|
go 1.22.1
|
||||||
|
|
||||||
require github.com/spf13/cobra v1.8.0
|
require (
|
||||||
|
github.com/jroimartin/gocui v0.5.0
|
||||||
|
github.com/nsf/termbox-go v1.1.1
|
||||||
|
github.com/spf13/cobra v1.8.0
|
||||||
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
|
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||||
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
)
|
)
|
||||||
|
|
10
go.sum
10
go.sum
|
@ -1,6 +1,16 @@
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||||
|
github.com/jroimartin/gocui v0.5.0 h1:DCZc97zY9dMnHXJSJLLmx9VqiEnAj0yh0eTNpuEtG/4=
|
||||||
|
github.com/jroimartin/gocui v0.5.0/go.mod h1:l7Hz8DoYoL6NoYnlnaX6XCNR62G7J5FfSW5jEogzaxE=
|
||||||
|
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||||
|
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||||
|
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||||
|
github.com/nsf/termbox-go v1.1.1 h1:nksUPLCb73Q++DwbYUBEglYBRPZyoXJdrj5L+TkjyZY=
|
||||||
|
github.com/nsf/termbox-go v1.1.1/go.mod h1:T0cTdVuOwf7pHQNtfhnEbzHbcNyCEcVU4YPpouCbVxo=
|
||||||
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
|
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||||
|
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
|
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
|
||||||
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
|
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
|
||||||
|
|
Loading…
Reference in New Issue