Compare commits
No commits in common. "bc8c852e4be1b166481a41315797c83c256faba4" and "3c79ebfbb41d12a2d7f196f328012debca0f9881" have entirely different histories.
bc8c852e4b
...
3c79ebfbb4
|
@ -1,6 +1,8 @@
|
||||||
name: Go audit
|
name: Go audit
|
||||||
run-name: ${{ gitea.actor }} pulled to main! 🚀
|
run-name: ${{ gitea.actor }} pushed to main! 🚀
|
||||||
on:
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [main]
|
branches: [main]
|
||||||
jobs:
|
jobs:
|
||||||
|
|
|
@ -2,13 +2,10 @@
|
||||||
|
|
||||||
Tiny IRC-like chat server written in Go
|
Tiny IRC-like chat server written in Go
|
||||||
|
|
||||||
<p align="center">
|
|
||||||
<img width="90%" height="90%" src="https://git.bulgariu.xyz/raul/mini-chat/raw/branch/testing/demo.gif"/>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
## Usage examples
|
## Usage examples
|
||||||
|
|
||||||
### Starting the server:
|
### Starting the server:
|
||||||
./mini-chat server --port 1337 --history chat.log
|
./mini-chat server --port 1337
|
||||||
|
|
||||||
### Connecting to the server:
|
### Connecting to the server:
|
||||||
./mini-chat client --ip 192.168.0.100 --port 1337
|
./mini-chat client --ip 192.168.0.100 --port 1337
|
||||||
|
|
|
@ -22,12 +22,6 @@ type Message struct {
|
||||||
Server net.Conn
|
Server net.Conn
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProfileData struct {
|
|
||||||
Username string
|
|
||||||
}
|
|
||||||
|
|
||||||
var Profile ProfileData
|
|
||||||
|
|
||||||
func (m Message) toSend() {
|
func (m Message) toSend() {
|
||||||
m.Server.Write([]byte(m.Contents))
|
m.Server.Write([]byte(m.Contents))
|
||||||
}
|
}
|
||||||
|
@ -99,8 +93,6 @@ func sendName(conn net.Conn) {
|
||||||
log.Fatalf("Error occurred sending message to server: %v\n", err)
|
log.Fatalf("Error occurred sending message to server: %v\n", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
Profile.Username = strings.TrimRight(message, "\n")
|
|
||||||
|
|
||||||
if _, err := conn.Write([]byte(message)); err != nil {
|
if _, err := conn.Write([]byte(message)); err != nil {
|
||||||
log.Fatalf("Error occurred writing to server: %v\n", err)
|
log.Fatalf("Error occurred writing to server: %v\n", err)
|
||||||
}
|
}
|
||||||
|
@ -151,91 +143,50 @@ func sendToServer(g *gocui.Gui, v *gocui.View) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func scrollView(v *gocui.View, dy int) error {
|
|
||||||
if v != nil {
|
|
||||||
v.Autoscroll = false
|
|
||||||
ox, oy := v.Origin()
|
|
||||||
if err := v.SetOrigin(ox, oy+dy); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func autoscroll(g *gocui.Gui, v *gocui.View) error {
|
|
||||||
chatbox, err := g.View("chatbox")
|
|
||||||
if err != nil {
|
|
||||||
log.Panicf("Error happened setting autoscroll: %v\n", err)
|
|
||||||
}
|
|
||||||
chatbox.Autoscroll = true
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func initKeybindings(g *gocui.Gui) error {
|
func initKeybindings(g *gocui.Gui) error {
|
||||||
if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil {
|
if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil {
|
||||||
log.Panicln(err)
|
log.Panicln(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// if err := g.SetKeybinding("button", gocui.MouseLeft, gocui.ModNone, sendToServer); err != nil {
|
if err := g.SetKeybinding("button", gocui.MouseLeft, gocui.ModNone, sendToServer); err != nil {
|
||||||
// log.Panicln(err)
|
|
||||||
// }
|
|
||||||
|
|
||||||
if err := g.SetKeybinding("textarea", gocui.KeyCtrlA, gocui.ModNone, autoscroll); err != nil {
|
|
||||||
log.Panicln(err)
|
log.Panicln(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := g.SetKeybinding("textarea", gocui.KeyEnter, gocui.ModNone, sendToServer); err != nil {
|
if err := g.SetKeybinding("textarea", gocui.KeyEnter, gocui.ModNone, sendToServer); err != nil {
|
||||||
log.Panicln(err)
|
log.Panicln(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := g.SetKeybinding("chatbox", gocui.MouseWheelUp, gocui.ModNone,
|
|
||||||
func(g *gocui.Gui, v *gocui.View) error {
|
|
||||||
scrollView(v, -1)
|
|
||||||
return nil
|
|
||||||
}); err != nil {
|
|
||||||
log.Panicln(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := g.SetKeybinding("chatbox", gocui.MouseWheelDown, gocui.ModNone,
|
|
||||||
func(g *gocui.Gui, v *gocui.View) error {
|
|
||||||
scrollView(v, 1)
|
|
||||||
return nil
|
|
||||||
}); err != nil {
|
|
||||||
log.Panicln(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func layout(g *gocui.Gui) error {
|
func layout(g *gocui.Gui) error {
|
||||||
maxX, maxY := g.Size()
|
maxX, maxY := g.Size()
|
||||||
|
|
||||||
if chatbox, err := g.SetView("chatbox", 2, 1, maxX-2, maxY-5); err != nil {
|
if chatbox, err := g.SetView("chatbox", 2, 1, maxX/2+40, maxY-5); err != nil {
|
||||||
if err != gocui.ErrUnknownView {
|
if err != gocui.ErrUnknownView {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
chatbox.Autoscroll = true
|
chatbox.Autoscroll = true
|
||||||
chatbox.Title = "Chat Box (Find source at https://git.bulgariu.xyz/raul/mini-chat!)"
|
chatbox.Title = "Chat Box"
|
||||||
}
|
}
|
||||||
|
|
||||||
// if button, err := g.SetView("button", maxX/2+32, maxY-4, maxX-28, maxY-2); err != nil {
|
if button, err := g.SetView("button", maxX/2+32, maxY-4, maxX/2+40, maxY-2); err != nil {
|
||||||
// if err != gocui.ErrUnknownView {
|
if err != gocui.ErrUnknownView {
|
||||||
// return err
|
return err
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// button.Wrap = true
|
|
||||||
// button.Frame = true
|
|
||||||
// fmt.Fprintln(button, "Send it")
|
|
||||||
// }
|
|
||||||
|
|
||||||
if textarea, err := g.SetView("textarea", 2, maxY-4, maxX-2, maxY-2); err != nil {
|
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 {
|
if err != gocui.ErrUnknownView {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if _, err := g.SetCurrentView("textarea"); err != nil {
|
if _, err := g.SetCurrentView("textarea"); err != nil {
|
||||||
log.Panicln(err)
|
log.Panicln(err)
|
||||||
}
|
}
|
||||||
textarea.Title = "(" + Profile.Username + ") " + "Send message" + " (Ctrl+A: Autoscroll)"
|
textarea.Title = "Send message"
|
||||||
textarea.Wrap = true
|
textarea.Wrap = true
|
||||||
textarea.Editable = true
|
textarea.Editable = true
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,6 @@ func init() {
|
||||||
// and all subcommands, e.g.:
|
// and all subcommands, e.g.:
|
||||||
// serverCmd.PersistentFlags().String("foo", "", "A help for foo")
|
// serverCmd.PersistentFlags().String("foo", "", "A help for foo")
|
||||||
serverCmd.PersistentFlags().String("port", "1302", "port to use for listening")
|
serverCmd.PersistentFlags().String("port", "1302", "port to use for listening")
|
||||||
serverCmd.PersistentFlags().String("history", "", "File to store and recover chat history from")
|
|
||||||
|
|
||||||
// Cobra supports local flags which will only run when this command
|
// Cobra supports local flags which will only run when this command
|
||||||
// is called directly, e.g.:
|
// is called directly, e.g.:
|
||||||
|
@ -52,13 +51,5 @@ func setServerParameters(cmd *cobra.Command) error {
|
||||||
if parameterPort != "" {
|
if parameterPort != "" {
|
||||||
listenPort = parameterPort
|
listenPort = parameterPort
|
||||||
}
|
}
|
||||||
parameterHistory, err := cmd.Flags().GetString("history")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if parameterHistory != "" {
|
|
||||||
logLocation = parameterHistory
|
|
||||||
isLogging = true
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,17 +9,17 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
listenPort string = "1302"
|
listenPort string = "1302"
|
||||||
isLogging bool = false
|
|
||||||
logLocation string
|
|
||||||
listenerList []chan string
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Creator interface {
|
||||||
|
CreateUser()
|
||||||
|
}
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
Username string
|
Username string
|
||||||
IP string
|
IP string
|
||||||
|
@ -49,6 +49,8 @@ func Server() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var listenerList []chan string
|
||||||
|
|
||||||
func getUsername(conn net.Conn) (s string, err error) {
|
func getUsername(conn net.Conn) (s string, err error) {
|
||||||
conn.Write([]byte("What's your name?\nChoice: "))
|
conn.Write([]byte("What's your name?\nChoice: "))
|
||||||
name, err := bufio.NewReader(conn).ReadString('\n')
|
name, err := bufio.NewReader(conn).ReadString('\n')
|
||||||
|
@ -76,22 +78,6 @@ func removeFromList(chatChan chan string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func populateChat(conn net.Conn) {
|
|
||||||
if isLogging == false {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
file, err := os.Open(logLocation)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Error opening file for populating: %v\n", err)
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
scanner := bufio.NewScanner(file)
|
|
||||||
for scanner.Scan() {
|
|
||||||
conn.Write([]byte(fmt.Sprintln(scanner.Text())))
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleConn(conn net.Conn, chatChan chan string) {
|
func handleConn(conn net.Conn, chatChan chan string) {
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
|
@ -108,13 +94,11 @@ func handleConn(conn net.Conn, chatChan chan string) {
|
||||||
}
|
}
|
||||||
userIP := getIP(conn)
|
userIP := getIP(conn)
|
||||||
//////////////////////////////////
|
//////////////////////////////////
|
||||||
populateChat(conn)
|
|
||||||
|
|
||||||
newUserTemplate := new(User)
|
newUserTemplate := new(User)
|
||||||
newUser := newUserTemplate.CreateUser(userName, userIP)
|
newUser := newUserTemplate.CreateUser(userName, userIP)
|
||||||
joinMessage := fmt.Sprintf("%v has joined the chat!", newUser.Username)
|
joinMessage := fmt.Sprintf("%v has joined the chat!", newUser.Username)
|
||||||
fmt.Println(joinMessage)
|
fmt.Println(joinMessage)
|
||||||
addToLog(fmt.Sprintln(joinMessage))
|
|
||||||
//conn.Write([]byte(joinMessage))
|
//conn.Write([]byte(joinMessage))
|
||||||
sendMessage(joinMessage)
|
sendMessage(joinMessage)
|
||||||
|
|
||||||
|
@ -124,7 +108,6 @@ func handleConn(conn net.Conn, chatChan chan string) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
quitMessage := fmt.Sprintf("%v has disconnected!", newUser.Username)
|
quitMessage := fmt.Sprintf("%v has disconnected!", newUser.Username)
|
||||||
fmt.Println(quitMessage)
|
fmt.Println(quitMessage)
|
||||||
addToLog(fmt.Sprintln(quitMessage))
|
|
||||||
sendMessage(quitMessage)
|
sendMessage(quitMessage)
|
||||||
//removeFromList(chatChan)
|
//removeFromList(chatChan)
|
||||||
// if _, err := conn.Write([]byte(quitMessage)); err != nil {
|
// if _, err := conn.Write([]byte(quitMessage)); err != nil {
|
||||||
|
@ -133,9 +116,7 @@ func handleConn(conn net.Conn, chatChan chan string) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
finalMessage := fmt.Sprintf("[%v] %v: %v", newUser.IP, newUser.Username, strings.TrimRight(message, "\n"))
|
finalMessage := fmt.Sprintf("[%v] %v: %v", newUser.IP, newUser.Username, strings.TrimRight(message, "\n"))
|
||||||
fm := fmt.Sprintf("%v\n", finalMessage)
|
fmt.Printf("%v\n", finalMessage)
|
||||||
fmt.Print(fm)
|
|
||||||
addToLog(fm)
|
|
||||||
sendMessage(finalMessage)
|
sendMessage(finalMessage)
|
||||||
|
|
||||||
//chatChan <- finalMessage
|
//chatChan <- finalMessage
|
||||||
|
@ -167,15 +148,3 @@ func getIP(conn net.Conn) (IP string) {
|
||||||
}
|
}
|
||||||
return IP
|
return IP
|
||||||
}
|
}
|
||||||
|
|
||||||
func addToLog(s string) {
|
|
||||||
if isLogging == false {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
file, err := os.OpenFile(logLocation, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0640)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Error occurred: %v\n", err)
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
file.WriteString(s)
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue