mirror of
https://github.com/naoufalzerai/simple-chat.git
synced 2025-11-08 06:15:54 +00:00
Create main.go
This commit is contained in:
parent
59a9f0b581
commit
0e66713e8a
135
main.go
Normal file
135
main.go
Normal file
@ -0,0 +1,135 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/go-redis/redis/v8"
|
||||
)
|
||||
|
||||
var (
|
||||
ctx = context.Background()
|
||||
TTL = time.Minute * 20
|
||||
conn = redis.NewClient(&redis.Options{
|
||||
Addr: "localhost:6379",
|
||||
Password: "", // no password set
|
||||
DB: 0, // use default DB
|
||||
})
|
||||
)
|
||||
|
||||
func main() {
|
||||
// The user name is the only argument, so we'll grab that here
|
||||
if len(os.Args) != 2 {
|
||||
fmt.Println("Usage: goredchat username")
|
||||
os.Exit(1)
|
||||
}
|
||||
username := os.Args[1]
|
||||
|
||||
defer conn.Close()
|
||||
|
||||
// We make a key and set it with the username as a value and a time to live
|
||||
// this will be the lock on the username and if we can't set it, its a name clash
|
||||
|
||||
userkey := "online." + username
|
||||
val, err := conn.Set(ctx, userkey, username, TTL).Result()
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if val == "" {
|
||||
fmt.Println("User already online")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
valint, err := conn.SAdd(ctx, "users", username).Result()
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if valint == 0 {
|
||||
fmt.Println("User still in online set")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// A ticker will let us update our presence on the Redis server
|
||||
tickerChan := time.NewTicker(time.Second * 60).C
|
||||
|
||||
// Now we create a channel and go routine that'll subscribe to our published messages
|
||||
// We'll give it its own connection because subscribes like to have their own connection
|
||||
subChan := make(chan string)
|
||||
go func() {
|
||||
|
||||
psc := conn.Subscribe(ctx, "messages")
|
||||
_, err := psc.Receive(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// Go channel which receives messages.
|
||||
ch := psc.Channel()
|
||||
for v := range ch {
|
||||
subChan <- string(v.Payload)
|
||||
}
|
||||
}()
|
||||
|
||||
// Now we'll make a simple channel and go routine that listens for complete lines from the user
|
||||
// When a complete line is entered, it'll be delivered to the channel.
|
||||
sayChan := make(chan string)
|
||||
go func() {
|
||||
prompt := username + ">"
|
||||
bio := bufio.NewReader(os.Stdin)
|
||||
for {
|
||||
fmt.Print(prompt)
|
||||
line, _, err := bio.ReadLine()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
sayChan <- "/exit"
|
||||
return
|
||||
}
|
||||
sayChan <- string(line)
|
||||
}
|
||||
}()
|
||||
|
||||
conn.Publish(ctx, "messages", username+" has joined")
|
||||
|
||||
chatExit := false
|
||||
|
||||
for !chatExit {
|
||||
select {
|
||||
case msg := <-subChan:
|
||||
fmt.Println(msg)
|
||||
case <-tickerChan:
|
||||
val, err = conn.Set(ctx, userkey, username, TTL).Result()
|
||||
if err != nil || val == "" {
|
||||
fmt.Println("Heartbeat set failed")
|
||||
chatExit = true
|
||||
}
|
||||
case line := <-sayChan:
|
||||
if line == "/exit" {
|
||||
chatExit = true
|
||||
} else if line == "/who" {
|
||||
names, _ := conn.SMembers(ctx, "users").Result()
|
||||
|
||||
for _, name := range names {
|
||||
fmt.Println(name)
|
||||
}
|
||||
} else {
|
||||
conn.Publish(ctx, "messages", username+":"+line)
|
||||
}
|
||||
default:
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
// We're leaving so let's delete the userkey and remove the username from the online set
|
||||
conn.Del(ctx, userkey)
|
||||
conn.SRem(ctx, "users", username)
|
||||
conn.Publish(ctx, "messages", username+" has left")
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user