mirror of
				https://github.com/owncast/owncast.git
				synced 2025-11-04 05:17:27 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			129 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			129 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package chat
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	"io"
 | 
						|
	"time"
 | 
						|
 | 
						|
	log "github.com/sirupsen/logrus"
 | 
						|
	"golang.org/x/net/websocket"
 | 
						|
 | 
						|
	"github.com/gabek/owncast/models"
 | 
						|
	"github.com/gabek/owncast/utils"
 | 
						|
 | 
						|
	"github.com/teris-io/shortid"
 | 
						|
)
 | 
						|
 | 
						|
const channelBufSize = 100
 | 
						|
 | 
						|
//Client represents a chat client.
 | 
						|
type Client struct {
 | 
						|
	ConnectedAt  time.Time
 | 
						|
	MessageCount int
 | 
						|
 | 
						|
	id     string
 | 
						|
	ws     *websocket.Conn
 | 
						|
	ch     chan models.ChatMessage
 | 
						|
	pingch chan models.PingMessage
 | 
						|
 | 
						|
	doneCh chan bool
 | 
						|
}
 | 
						|
 | 
						|
//NewClient creates a new chat client
 | 
						|
func NewClient(ws *websocket.Conn) *Client {
 | 
						|
	if ws == nil {
 | 
						|
		log.Panicln("ws cannot be nil")
 | 
						|
	}
 | 
						|
 | 
						|
	ch := make(chan models.ChatMessage, channelBufSize)
 | 
						|
	doneCh := make(chan bool)
 | 
						|
	pingch := make(chan models.PingMessage)
 | 
						|
	clientID := utils.GenerateClientIDFromRequest(ws.Request())
 | 
						|
 | 
						|
	return &Client{time.Now(), 0, clientID, ws, ch, pingch, doneCh}
 | 
						|
}
 | 
						|
 | 
						|
//GetConnection gets the connection for the client
 | 
						|
func (c *Client) GetConnection() *websocket.Conn {
 | 
						|
	return c.ws
 | 
						|
}
 | 
						|
 | 
						|
func (c *Client) Write(msg models.ChatMessage) {
 | 
						|
	select {
 | 
						|
	case c.ch <- msg:
 | 
						|
	default:
 | 
						|
		_server.remove(c)
 | 
						|
		_server.err(fmt.Errorf("client %s is disconnected", c.id))
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
//Done marks the client as done
 | 
						|
func (c *Client) Done() {
 | 
						|
	c.doneCh <- true
 | 
						|
}
 | 
						|
 | 
						|
// Listen Write and Read request via chanel
 | 
						|
func (c *Client) Listen() {
 | 
						|
	go c.listenWrite()
 | 
						|
	c.listenRead()
 | 
						|
}
 | 
						|
 | 
						|
// Listen write request via chanel
 | 
						|
func (c *Client) listenWrite() {
 | 
						|
	for {
 | 
						|
		select {
 | 
						|
		// Send a PING keepalive
 | 
						|
		case msg := <-c.pingch:
 | 
						|
			websocket.JSON.Send(c.ws, msg)
 | 
						|
		// send message to the client
 | 
						|
		case msg := <-c.ch:
 | 
						|
			// log.Println("Send:", msg)
 | 
						|
			websocket.JSON.Send(c.ws, msg)
 | 
						|
 | 
						|
		// receive done request
 | 
						|
		case <-c.doneCh:
 | 
						|
			_server.remove(c)
 | 
						|
			c.doneCh <- true // for listenRead method
 | 
						|
			return
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// Listen read request via chanel
 | 
						|
func (c *Client) listenRead() {
 | 
						|
	for {
 | 
						|
		select {
 | 
						|
 | 
						|
		// receive done request
 | 
						|
		case <-c.doneCh:
 | 
						|
			_server.remove(c)
 | 
						|
			c.doneCh <- true // for listenWrite method
 | 
						|
			return
 | 
						|
 | 
						|
		// read data from websocket connection
 | 
						|
		default:
 | 
						|
			var msg models.ChatMessage
 | 
						|
			id, err := shortid.Generate()
 | 
						|
			if err != nil {
 | 
						|
				log.Panicln(err)
 | 
						|
			}
 | 
						|
 | 
						|
			msg.ID = id
 | 
						|
			msg.MessageType = "CHAT"
 | 
						|
			msg.Timestamp = time.Now()
 | 
						|
 | 
						|
			if err := websocket.JSON.Receive(c.ws, &msg); err == io.EOF {
 | 
						|
				c.doneCh <- true
 | 
						|
				return
 | 
						|
			} else if err != nil {
 | 
						|
				_server.err(err)
 | 
						|
			} else {
 | 
						|
				c.MessageCount++
 | 
						|
 | 
						|
				msg.ClientID = c.id
 | 
						|
				_server.SendToAll(msg)
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 |