Expanded linting + fix warnings (#1396)
* Expand the linters and types of warnings to improve consistency and safety * Fail lint workflow if there are errors * golint has been replaced by revive * Hand-pick some of the default exclude list * Ignore error when trying to delete preview gif * Ignore linter warning opening playlist path * Rename user field Id -> ID * A bunch of renames to address linter warnings * Rename ChatClient -> Client per linter suggestion best practice * Rename ChatServer -> Server per linter suggestion best practice * More linter warning fixes * Add missing comments to all exported functions and properties
This commit is contained in:
@@ -12,6 +12,7 @@ import (
|
||||
|
||||
var getStatus func() models.Status
|
||||
|
||||
// Start begins the chat server.
|
||||
func Start(getStatusFunc func() models.Status) error {
|
||||
setupPersistence()
|
||||
|
||||
@@ -26,11 +27,11 @@ func Start(getStatusFunc func() models.Status) error {
|
||||
}
|
||||
|
||||
// GetClientsForUser will return chat connections that are owned by a specific user.
|
||||
func GetClientsForUser(userID string) ([]*ChatClient, error) {
|
||||
clients := map[string][]*ChatClient{}
|
||||
func GetClientsForUser(userID string) ([]*Client, error) {
|
||||
clients := map[string][]*Client{}
|
||||
|
||||
for _, client := range _server.clients {
|
||||
clients[client.User.Id] = append(clients[client.User.Id], client)
|
||||
clients[client.User.ID] = append(clients[client.User.ID], client)
|
||||
}
|
||||
|
||||
if _, exists := clients[userID]; !exists {
|
||||
@@ -40,8 +41,9 @@ func GetClientsForUser(userID string) ([]*ChatClient, error) {
|
||||
return clients[userID], nil
|
||||
}
|
||||
|
||||
func GetClients() []*ChatClient {
|
||||
clients := []*ChatClient{}
|
||||
// GetClients will return all the current chat clients connected.
|
||||
func GetClients() []*Client {
|
||||
clients := []*Client{}
|
||||
|
||||
// Convert the keyed map to a slice.
|
||||
for _, client := range _server.clients {
|
||||
@@ -55,6 +57,7 @@ func GetClients() []*ChatClient {
|
||||
return clients
|
||||
}
|
||||
|
||||
// SendSystemMessage will send a message string as a system message to all clients.
|
||||
func SendSystemMessage(text string, ephemeral bool) error {
|
||||
message := events.SystemMessageEvent{
|
||||
MessageEvent: events.MessageEvent{
|
||||
@@ -69,12 +72,13 @@ func SendSystemMessage(text string, ephemeral bool) error {
|
||||
}
|
||||
|
||||
if !ephemeral {
|
||||
saveEvent(message.Id, "system", message.Body, message.GetMessageType(), nil, message.Timestamp)
|
||||
saveEvent(message.ID, "system", message.Body, message.GetMessageType(), nil, message.Timestamp)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SendSystemAction will send a system action string as an action event to all clients.
|
||||
func SendSystemAction(text string, ephemeral bool) error {
|
||||
message := events.ActionEvent{
|
||||
MessageEvent: events.MessageEvent{
|
||||
@@ -90,20 +94,23 @@ func SendSystemAction(text string, ephemeral bool) error {
|
||||
}
|
||||
|
||||
if !ephemeral {
|
||||
saveEvent(message.Id, "action", message.Body, message.GetMessageType(), nil, message.Timestamp)
|
||||
saveEvent(message.ID, "action", message.Body, message.GetMessageType(), nil, message.Timestamp)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SendAllWelcomeMessage will send the chat message to all connected clients.
|
||||
func SendAllWelcomeMessage() {
|
||||
_server.sendAllWelcomeMessage()
|
||||
}
|
||||
|
||||
// Broadcast will send all connected clients the outbound object provided.
|
||||
func Broadcast(event events.OutboundEvent) error {
|
||||
return _server.Broadcast(event.GetBroadcastPayload())
|
||||
}
|
||||
|
||||
// HandleClientConnection handles a single inbound websocket connection.
|
||||
func HandleClientConnection(w http.ResponseWriter, r *http.Request) {
|
||||
_server.HandleClientConnection(w, r)
|
||||
}
|
||||
|
||||
@@ -15,12 +15,13 @@ import (
|
||||
"github.com/owncast/owncast/geoip"
|
||||
)
|
||||
|
||||
type ChatClient struct {
|
||||
// Client represents a single chat client.
|
||||
type Client struct {
|
||||
id uint
|
||||
accessToken string
|
||||
conn *websocket.Conn
|
||||
User *user.User `json:"user"`
|
||||
server *ChatServer
|
||||
server *Server
|
||||
ipAddress string `json:"-"`
|
||||
// Buffered channel of outbound messages.
|
||||
send chan []byte
|
||||
@@ -35,7 +36,7 @@ type ChatClient struct {
|
||||
|
||||
type chatClientEvent struct {
|
||||
data []byte
|
||||
client *ChatClient
|
||||
client *Client
|
||||
}
|
||||
|
||||
const (
|
||||
@@ -64,7 +65,7 @@ var (
|
||||
space = []byte{' '}
|
||||
)
|
||||
|
||||
func (c *ChatClient) sendConnectedClientInfo() {
|
||||
func (c *Client) sendConnectedClientInfo() {
|
||||
payload := events.EventPayload{
|
||||
"type": events.ConnectedUserInfo,
|
||||
"user": c.User,
|
||||
@@ -73,7 +74,7 @@ func (c *ChatClient) sendConnectedClientInfo() {
|
||||
c.sendPayload(payload)
|
||||
}
|
||||
|
||||
func (c *ChatClient) readPump() {
|
||||
func (c *Client) readPump() {
|
||||
// Allow 3 messages every two seconds.
|
||||
limit := rate.Every(2 * time.Second / 3)
|
||||
c.rateLimiter = rate.NewLimiter(limit, 1)
|
||||
@@ -122,11 +123,11 @@ func (c *ChatClient) readPump() {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ChatClient) writePump() {
|
||||
func (c *Client) writePump() {
|
||||
ticker := time.NewTicker(pingPeriod)
|
||||
defer func() {
|
||||
ticker.Stop()
|
||||
c.conn.Close()
|
||||
_ = c.conn.Close()
|
||||
}()
|
||||
|
||||
for {
|
||||
@@ -167,14 +168,14 @@ func (c *ChatClient) writePump() {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ChatClient) handleEvent(data []byte) {
|
||||
func (c *Client) handleEvent(data []byte) {
|
||||
c.server.inbound <- chatClientEvent{data: data, client: c}
|
||||
}
|
||||
|
||||
func (c *ChatClient) close() {
|
||||
func (c *Client) close() {
|
||||
log.Traceln("client closed:", c.User.DisplayName, c.id, c.ipAddress)
|
||||
|
||||
c.conn.Close()
|
||||
_ = c.conn.Close()
|
||||
c.server.unregister <- c.id
|
||||
if c.send != nil {
|
||||
close(c.send)
|
||||
@@ -182,18 +183,18 @@ func (c *ChatClient) close() {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ChatClient) passesRateLimit() bool {
|
||||
func (c *Client) passesRateLimit() bool {
|
||||
return c.rateLimiter.Allow() && !c.inTimeout
|
||||
}
|
||||
|
||||
func (c *ChatClient) startChatRejectionTimeout() {
|
||||
func (c *Client) startChatRejectionTimeout() {
|
||||
if c.timeoutTimer != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.inTimeout = true
|
||||
c.timeoutTimer = time.NewTimer(10 * time.Second)
|
||||
go func(c *ChatClient) {
|
||||
go func(c *Client) {
|
||||
for range c.timeoutTimer.C {
|
||||
c.inTimeout = false
|
||||
c.timeoutTimer = nil
|
||||
@@ -203,7 +204,7 @@ func (c *ChatClient) startChatRejectionTimeout() {
|
||||
c.sendAction("You are temporarily blocked from sending chat messages due to perceived flooding.")
|
||||
}
|
||||
|
||||
func (c *ChatClient) sendPayload(payload events.EventPayload) {
|
||||
func (c *Client) sendPayload(payload events.EventPayload) {
|
||||
var data []byte
|
||||
data, err := json.Marshal(payload)
|
||||
if err != nil {
|
||||
@@ -216,7 +217,7 @@ func (c *ChatClient) sendPayload(payload events.EventPayload) {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ChatClient) sendAction(message string) {
|
||||
func (c *Client) sendAction(message string) {
|
||||
clientMessage := events.ActionEvent{
|
||||
MessageEvent: events.MessageEvent{
|
||||
Body: message,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// nolint:goimports
|
||||
// +build !freebsd
|
||||
|
||||
package chat
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func (s *ChatServer) userNameChanged(eventData chatClientEvent) {
|
||||
func (s *Server) userNameChanged(eventData chatClientEvent) {
|
||||
var receivedEvent events.NameChangeEvent
|
||||
if err := json.Unmarshal(eventData.data, &receivedEvent); err != nil {
|
||||
log.Errorln("error unmarshalling to NameChangeEvent", err)
|
||||
@@ -43,7 +43,7 @@ func (s *ChatServer) userNameChanged(eventData chatClientEvent) {
|
||||
oldName := savedUser.DisplayName
|
||||
|
||||
// Save the new name
|
||||
user.ChangeUsername(eventData.client.User.Id, receivedEvent.NewName)
|
||||
user.ChangeUsername(eventData.client.User.ID, receivedEvent.NewName)
|
||||
|
||||
// Update the connected clients associated user with the new name
|
||||
now := time.Now()
|
||||
@@ -69,7 +69,7 @@ func (s *ChatServer) userNameChanged(eventData chatClientEvent) {
|
||||
webhooks.SendChatEventUsernameChanged(receivedEvent)
|
||||
}
|
||||
|
||||
func (s *ChatServer) userMessageSent(eventData chatClientEvent) {
|
||||
func (s *Server) userMessageSent(eventData chatClientEvent) {
|
||||
var event events.UserMessageEvent
|
||||
if err := json.Unmarshal(eventData.data, &event); err != nil {
|
||||
log.Errorln("error unmarshalling to UserMessageEvent", err)
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
package events
|
||||
|
||||
// ActionEvent represents an action that took place, not a chat message.
|
||||
type ActionEvent struct {
|
||||
Event
|
||||
MessageEvent
|
||||
}
|
||||
|
||||
// ActionEvent will return the object to send to all chat users.
|
||||
// GetBroadcastPayload will return the object to send to all chat users.
|
||||
func (e *ActionEvent) GetBroadcastPayload() EventPayload {
|
||||
return EventPayload{
|
||||
"id": e.Id,
|
||||
"id": e.ID,
|
||||
"timestamp": e.Timestamp,
|
||||
"body": e.Body,
|
||||
"type": e.GetMessageType(),
|
||||
}
|
||||
}
|
||||
|
||||
// GetMessageType will return the type of message.
|
||||
func (e *ActionEvent) GetMessageType() EventType {
|
||||
return ChatActionSent
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
// EventPayload is a generic key/value map for sending out to chat clients.
|
||||
type EventPayload map[string]interface{}
|
||||
|
||||
// OutboundEvent represents an event that is sent out to all listeners of the chat server.
|
||||
type OutboundEvent interface {
|
||||
GetBroadcastPayload() EventPayload
|
||||
GetMessageType() EventType
|
||||
@@ -28,10 +29,11 @@ type OutboundEvent interface {
|
||||
// Event is any kind of event. A type is required to be specified.
|
||||
type Event struct {
|
||||
Type EventType `json:"type,omitempty"`
|
||||
Id string `json:"id"`
|
||||
ID string `json:"id"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
}
|
||||
|
||||
// UserEvent is an event with an associated user.
|
||||
type UserEvent struct {
|
||||
User *user.User `json:"user"`
|
||||
HiddenAt *time.Time `json:"hiddenAt,omitempty"`
|
||||
@@ -44,6 +46,7 @@ type MessageEvent struct {
|
||||
RawBody string `json:"-"`
|
||||
}
|
||||
|
||||
// SystemActionEvent is an event that represents an action that took place, not a chat message.
|
||||
type SystemActionEvent struct {
|
||||
Event
|
||||
MessageEvent
|
||||
@@ -51,13 +54,13 @@ type SystemActionEvent struct {
|
||||
|
||||
// SetDefaults will set default properties of all inbound events.
|
||||
func (e *Event) SetDefaults() {
|
||||
e.Id = shortid.MustGenerate()
|
||||
e.ID = shortid.MustGenerate()
|
||||
e.Timestamp = time.Now()
|
||||
}
|
||||
|
||||
// SetDefaults will set default properties of all inbound events.
|
||||
func (e *UserMessageEvent) SetDefaults() {
|
||||
e.Id = shortid.MustGenerate()
|
||||
e.ID = shortid.MustGenerate()
|
||||
e.Timestamp = time.Now()
|
||||
e.RenderAndSanitizeMessageBody()
|
||||
}
|
||||
@@ -92,6 +95,7 @@ func RenderAndSanitize(raw string) string {
|
||||
return strings.TrimSpace(safe)
|
||||
}
|
||||
|
||||
// RenderMarkdown will return HTML rendered from the string body of a chat message.
|
||||
func RenderMarkdown(raw string) string {
|
||||
markdown := goldmark.New(
|
||||
goldmark.WithRendererOptions(
|
||||
|
||||
@@ -27,8 +27,11 @@ const (
|
||||
// ConnectedUserInfo is a private event to a user letting them know their user details.
|
||||
ConnectedUserInfo EventType = "CONNECTED_USER_INFO"
|
||||
// ChatActionSent is a generic chat action that can be used for anything that doesn't need specific handling or formatting.
|
||||
ChatActionSent EventType = "CHAT_ACTION"
|
||||
ErrorNeedsRegistration EventType = "ERROR_NEEDS_REGISTRATION"
|
||||
ChatActionSent EventType = "CHAT_ACTION"
|
||||
// ErrorNeedsRegistration is an error returned when the client needs to perform registration.
|
||||
ErrorNeedsRegistration EventType = "ERROR_NEEDS_REGISTRATION"
|
||||
// ErrorMaxConnectionsExceeded is an error returned when the server determined it should not handle more connections.
|
||||
ErrorMaxConnectionsExceeded EventType = "ERROR_MAX_CONNECTIONS_EXCEEDED"
|
||||
ErrorUserDisabled EventType = "ERROR_USER_DISABLED"
|
||||
// ErrorUserDisabled is an error returned when the connecting user has been previously banned/disabled.
|
||||
ErrorUserDisabled EventType = "ERROR_USER_DISABLED"
|
||||
)
|
||||
|
||||
@@ -7,7 +7,7 @@ type NameChangeEvent struct {
|
||||
NewName string `json:"newName"`
|
||||
}
|
||||
|
||||
// NameChangeEventBroadcast is fired when a user changes their chat display name.
|
||||
// NameChangeBroadcast represents a user changing their chat display name.
|
||||
type NameChangeBroadcast struct {
|
||||
Event
|
||||
UserEvent
|
||||
@@ -17,7 +17,7 @@ type NameChangeBroadcast struct {
|
||||
// GetBroadcastPayload will return the object to send to all chat users.
|
||||
func (e *NameChangeBroadcast) GetBroadcastPayload() EventPayload {
|
||||
return EventPayload{
|
||||
"id": e.Id,
|
||||
"id": e.ID,
|
||||
"timestamp": e.Timestamp,
|
||||
"user": e.User,
|
||||
"oldName": e.Oldname,
|
||||
|
||||
@@ -8,10 +8,10 @@ type SystemMessageEvent struct {
|
||||
MessageEvent
|
||||
}
|
||||
|
||||
// SystemMessageEvent will return the object to send to all chat users.
|
||||
// GetBroadcastPayload will return the object to send to all chat users.
|
||||
func (e *SystemMessageEvent) GetBroadcastPayload() EventPayload {
|
||||
return EventPayload{
|
||||
"id": e.Id,
|
||||
"id": e.ID,
|
||||
"timestamp": e.Timestamp,
|
||||
"body": e.Body,
|
||||
"type": SystemMessageSent,
|
||||
@@ -21,6 +21,7 @@ func (e *SystemMessageEvent) GetBroadcastPayload() EventPayload {
|
||||
}
|
||||
}
|
||||
|
||||
// GetMessageType will return the event type for this message.
|
||||
func (e *SystemMessageEvent) GetMessageType() EventType {
|
||||
return SystemMessageSent
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ type UserDisabledEvent struct {
|
||||
func (e *UserDisabledEvent) GetBroadcastPayload() EventPayload {
|
||||
return EventPayload{
|
||||
"type": ErrorUserDisabled,
|
||||
"id": e.Id,
|
||||
"id": e.ID,
|
||||
"timestamp": e.Timestamp,
|
||||
"user": e.User,
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ type UserJoinedEvent struct {
|
||||
func (e *UserJoinedEvent) GetBroadcastPayload() EventPayload {
|
||||
return EventPayload{
|
||||
"type": UserJoined,
|
||||
"id": e.Id,
|
||||
"id": e.ID,
|
||||
"timestamp": e.Timestamp,
|
||||
"user": e.User,
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ type UserMessageEvent struct {
|
||||
// GetBroadcastPayload will return the object to send to all chat users.
|
||||
func (e *UserMessageEvent) GetBroadcastPayload() EventPayload {
|
||||
return EventPayload{
|
||||
"id": e.Id,
|
||||
"id": e.ID,
|
||||
"timestamp": e.Timestamp,
|
||||
"body": e.Body,
|
||||
"user": e.User,
|
||||
@@ -19,6 +19,7 @@ func (e *UserMessageEvent) GetBroadcastPayload() EventPayload {
|
||||
}
|
||||
}
|
||||
|
||||
// GetMessageType will return the event type for this message.
|
||||
func (e *UserMessageEvent) GetMessageType() EventType {
|
||||
return MessageSent
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// SetMessagesVisibility will set the visibility of multiple messages by ID.
|
||||
func SetMessagesVisibility(messageIDs []string, visibility bool) error {
|
||||
// Save new message visibility
|
||||
if err := saveMessageVisibility(messageIDs, visibility); err != nil {
|
||||
@@ -17,7 +18,7 @@ func SetMessagesVisibility(messageIDs []string, visibility bool) error {
|
||||
// Note: Our client expects a single message at a time, so we can't just
|
||||
// send an array of messages in a single update.
|
||||
for _, id := range messageIDs {
|
||||
message, err := getMessageById(id)
|
||||
message, err := getMessageByID(id)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
continue
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
"github.com/owncast/owncast/core/chat/events"
|
||||
"github.com/owncast/owncast/core/data"
|
||||
"github.com/owncast/owncast/core/user"
|
||||
@@ -33,11 +32,12 @@ func setupPersistence() {
|
||||
}()
|
||||
}
|
||||
|
||||
// SaveUserMessage will save a single chat event to the messages database.
|
||||
func SaveUserMessage(event events.UserMessageEvent) {
|
||||
saveEvent(event.Id, event.User.Id, event.Body, event.Type, event.HiddenAt, event.Timestamp)
|
||||
saveEvent(event.ID, event.User.ID, event.Body, event.Type, event.HiddenAt, event.Timestamp)
|
||||
}
|
||||
|
||||
func saveEvent(id string, userId string, body string, eventType string, hidden *time.Time, timestamp time.Time) {
|
||||
func saveEvent(id string, userID string, body string, eventType string, hidden *time.Time, timestamp time.Time) {
|
||||
defer func() {
|
||||
_historyCache = nil
|
||||
}()
|
||||
@@ -61,7 +61,7 @@ func saveEvent(id string, userId string, body string, eventType string, hidden *
|
||||
|
||||
defer stmt.Close()
|
||||
|
||||
if _, err = stmt.Exec(id, userId, body, eventType, hidden, timestamp); err != nil {
|
||||
if _, err = stmt.Exec(id, userID, body, eventType, hidden, timestamp); err != nil {
|
||||
log.Errorln("error saving", eventType, err)
|
||||
return
|
||||
}
|
||||
@@ -82,7 +82,7 @@ func getChat(query string) []events.UserMessageEvent {
|
||||
|
||||
for rows.Next() {
|
||||
var id string
|
||||
var userId string
|
||||
var userID string
|
||||
var body string
|
||||
var messageType models.EventType
|
||||
var hiddenAt *time.Time
|
||||
@@ -96,7 +96,7 @@ func getChat(query string) []events.UserMessageEvent {
|
||||
var userNameChangedAt *time.Time
|
||||
|
||||
// Convert a database row into a chat event
|
||||
err = rows.Scan(&id, &userId, &body, &messageType, &hiddenAt, ×tamp, &userDisplayName, &userDisplayColor, &userCreatedAt, &userDisabledAt, &previousUsernames, &userNameChangedAt)
|
||||
err = rows.Scan(&id, &userID, &body, &messageType, &hiddenAt, ×tamp, &userDisplayName, &userDisplayColor, &userCreatedAt, &userDisabledAt, &previousUsernames, &userNameChangedAt)
|
||||
if err != nil {
|
||||
log.Errorln("There is a problem converting query to chat objects. Please report this:", query)
|
||||
break
|
||||
@@ -120,7 +120,7 @@ func getChat(query string) []events.UserMessageEvent {
|
||||
}
|
||||
|
||||
user := user.User{
|
||||
Id: userId,
|
||||
ID: userID,
|
||||
AccessToken: "",
|
||||
DisplayName: *userDisplayName,
|
||||
DisplayColor: *userDisplayColor,
|
||||
@@ -133,7 +133,7 @@ func getChat(query string) []events.UserMessageEvent {
|
||||
message := events.UserMessageEvent{
|
||||
Event: events.Event{
|
||||
Type: messageType,
|
||||
Id: id,
|
||||
ID: id,
|
||||
Timestamp: timestamp,
|
||||
},
|
||||
UserEvent: events.UserEvent{
|
||||
@@ -154,6 +154,7 @@ func getChat(query string) []events.UserMessageEvent {
|
||||
|
||||
var _historyCache *[]events.UserMessageEvent
|
||||
|
||||
// GetChatModerationHistory will return all the chat messages suitable for moderation purposes.
|
||||
func GetChatModerationHistory() []events.UserMessageEvent {
|
||||
if _historyCache != nil {
|
||||
return *_historyCache
|
||||
@@ -168,6 +169,7 @@ func GetChatModerationHistory() []events.UserMessageEvent {
|
||||
return result
|
||||
}
|
||||
|
||||
// GetChatHistory will return all the chat messages suitable for returning as user-facing chat history.
|
||||
func GetChatHistory() []events.UserMessageEvent {
|
||||
// Get all visible messages
|
||||
var query = fmt.Sprintf("SELECT messages.id, user_id, body, eventType, hidden_at, timestamp, display_name, display_color, created_at, disabled_at, previous_names, namechanged_at FROM messages, users WHERE messages.user_id = users.id AND hidden_at IS NULL AND disabled_at IS NULL ORDER BY timestamp DESC LIMIT %d", maxBacklogNumber)
|
||||
@@ -181,9 +183,9 @@ func GetChatHistory() []events.UserMessageEvent {
|
||||
return m
|
||||
}
|
||||
|
||||
// SetMessageVisibilityForUserId will bulk change the visibility of messages for a user
|
||||
// SetMessageVisibilityForUserID will bulk change the visibility of messages for a user
|
||||
// and then send out visibility changed events to chat clients.
|
||||
func SetMessageVisibilityForUserId(userID string, visible bool) error {
|
||||
func SetMessageVisibilityForUserID(userID string, visible bool) error {
|
||||
defer func() {
|
||||
_historyCache = nil
|
||||
}()
|
||||
@@ -198,7 +200,7 @@ func SetMessageVisibilityForUserId(userID string, visible bool) error {
|
||||
}
|
||||
|
||||
for _, message := range messages {
|
||||
ids = append(ids, message.Id)
|
||||
ids = append(ids, message.ID)
|
||||
}
|
||||
|
||||
// Tell the clients to hide/show these messages.
|
||||
@@ -250,29 +252,29 @@ func saveMessageVisibility(messageIDs []string, visible bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func getMessageById(messageID string) (*events.UserMessageEvent, error) {
|
||||
func getMessageByID(messageID string) (*events.UserMessageEvent, error) {
|
||||
var query = "SELECT * FROM messages WHERE id = ?"
|
||||
row := _datastore.DB.QueryRow(query, messageID)
|
||||
|
||||
var id string
|
||||
var userId string
|
||||
var userID string
|
||||
var body string
|
||||
var eventType models.EventType
|
||||
var hiddenAt *time.Time
|
||||
var timestamp time.Time
|
||||
|
||||
err := row.Scan(&id, &userId, &body, &eventType, &hiddenAt, ×tamp)
|
||||
err := row.Scan(&id, &userID, &body, &eventType, &hiddenAt, ×tamp)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
user := user.GetUserById(userId)
|
||||
user := user.GetUserByID(userID)
|
||||
|
||||
return &events.UserMessageEvent{
|
||||
events.Event{
|
||||
Type: eventType,
|
||||
Id: id,
|
||||
ID: id,
|
||||
Timestamp: timestamp,
|
||||
},
|
||||
events.UserEvent{
|
||||
|
||||
@@ -18,12 +18,13 @@ import (
|
||||
"github.com/owncast/owncast/utils"
|
||||
)
|
||||
|
||||
var _server *ChatServer
|
||||
var _server *Server
|
||||
|
||||
type ChatServer struct {
|
||||
// Server represents an instance of the chat server.
|
||||
type Server struct {
|
||||
mu sync.RWMutex
|
||||
seq uint
|
||||
clients map[uint]*ChatClient
|
||||
clients map[uint]*Client
|
||||
maxSocketConnectionLimit int64
|
||||
|
||||
// send outbound message payload to all clients
|
||||
@@ -36,12 +37,13 @@ type ChatServer struct {
|
||||
unregister chan uint // the ChatClient id
|
||||
}
|
||||
|
||||
func NewChat() *ChatServer {
|
||||
// NewChat will return a new instance of the chat server.
|
||||
func NewChat() *Server {
|
||||
maximumConcurrentConnectionLimit := getMaximumConcurrentConnectionLimit()
|
||||
setSystemConcurrentConnectionLimit(maximumConcurrentConnectionLimit)
|
||||
|
||||
server := &ChatServer{
|
||||
clients: map[uint]*ChatClient{},
|
||||
server := &Server{
|
||||
clients: map[uint]*Client{},
|
||||
outbound: make(chan []byte),
|
||||
inbound: make(chan chatClientEvent),
|
||||
unregister: make(chan uint),
|
||||
@@ -51,13 +53,14 @@ func NewChat() *ChatServer {
|
||||
return server
|
||||
}
|
||||
|
||||
func (s *ChatServer) Run() {
|
||||
// Run will start the chat server.
|
||||
func (s *Server) Run() {
|
||||
for {
|
||||
select {
|
||||
case clientId := <-s.unregister:
|
||||
if _, ok := s.clients[clientId]; ok {
|
||||
case clientID := <-s.unregister:
|
||||
if _, ok := s.clients[clientID]; ok {
|
||||
s.mu.Lock()
|
||||
delete(s.clients, clientId)
|
||||
delete(s.clients, clientID)
|
||||
s.mu.Unlock()
|
||||
}
|
||||
|
||||
@@ -68,8 +71,8 @@ func (s *ChatServer) Run() {
|
||||
}
|
||||
|
||||
// Addclient registers new connection as a User.
|
||||
func (s *ChatServer) Addclient(conn *websocket.Conn, user *user.User, accessToken string, userAgent string, ipAddress string) *ChatClient {
|
||||
client := &ChatClient{
|
||||
func (s *Server) Addclient(conn *websocket.Conn, user *user.User, accessToken string, userAgent string, ipAddress string) *Client {
|
||||
client := &Client{
|
||||
server: s,
|
||||
conn: conn,
|
||||
User: user,
|
||||
@@ -101,14 +104,14 @@ func (s *ChatServer) Addclient(conn *websocket.Conn, user *user.User, accessToke
|
||||
}
|
||||
|
||||
// Asynchronously, optionally, fetch GeoIP data.
|
||||
go func(client *ChatClient) {
|
||||
go func(client *Client) {
|
||||
client.Geo = geoip.GetGeoFromIP(ipAddress)
|
||||
}(client)
|
||||
|
||||
return client
|
||||
}
|
||||
|
||||
func (s *ChatServer) sendUserJoinedMessage(c *ChatClient) {
|
||||
func (s *Server) sendUserJoinedMessage(c *Client) {
|
||||
userJoinedEvent := events.UserJoinedEvent{}
|
||||
userJoinedEvent.SetDefaults()
|
||||
userJoinedEvent.User = c.User
|
||||
@@ -121,7 +124,8 @@ func (s *ChatServer) sendUserJoinedMessage(c *ChatClient) {
|
||||
webhooks.SendChatEventUserJoined(userJoinedEvent)
|
||||
}
|
||||
|
||||
func (s *ChatServer) ClientClosed(c *ChatClient) {
|
||||
// ClientClosed is fired when a client disconnects or connection is dropped.
|
||||
func (s *Server) ClientClosed(c *Client) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
c.close()
|
||||
@@ -132,7 +136,8 @@ func (s *ChatServer) ClientClosed(c *ChatClient) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ChatServer) HandleClientConnection(w http.ResponseWriter, r *http.Request) {
|
||||
// HandleClientConnection is fired when a single client connects to the websocket.
|
||||
func (s *Server) HandleClientConnection(w http.ResponseWriter, r *http.Request) {
|
||||
if data.GetChatDisabled() {
|
||||
_, _ = w.Write([]byte(events.ChatDisabled))
|
||||
return
|
||||
@@ -155,7 +160,7 @@ func (s *ChatServer) HandleClientConnection(w http.ResponseWriter, r *http.Reque
|
||||
if accessToken == "" {
|
||||
log.Errorln("Access token is required")
|
||||
// Return HTTP status code
|
||||
conn.Close()
|
||||
_ = conn.Close()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -166,17 +171,17 @@ func (s *ChatServer) HandleClientConnection(w http.ResponseWriter, r *http.Reque
|
||||
"type": events.ErrorNeedsRegistration,
|
||||
})
|
||||
// Send error that registration is required
|
||||
conn.Close()
|
||||
_ = conn.Close()
|
||||
return
|
||||
}
|
||||
|
||||
// User is disabled therefore we should disconnect.
|
||||
if user.DisabledAt != nil {
|
||||
log.Traceln("Disabled user", user.Id, user.DisplayName, "rejected")
|
||||
log.Traceln("Disabled user", user.ID, user.DisplayName, "rejected")
|
||||
_ = conn.WriteJSON(events.EventPayload{
|
||||
"type": events.ErrorUserDisabled,
|
||||
})
|
||||
conn.Close()
|
||||
_ = conn.Close()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -187,7 +192,7 @@ func (s *ChatServer) HandleClientConnection(w http.ResponseWriter, r *http.Reque
|
||||
}
|
||||
|
||||
// Broadcast sends message to all connected clients.
|
||||
func (s *ChatServer) Broadcast(payload events.EventPayload) error {
|
||||
func (s *Server) Broadcast(payload events.EventPayload) error {
|
||||
data, err := json.Marshal(payload)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -212,7 +217,8 @@ func (s *ChatServer) Broadcast(payload events.EventPayload) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *ChatServer) Send(payload events.EventPayload, client *ChatClient) {
|
||||
// Send will send a single payload to a single connected client.
|
||||
func (s *Server) Send(payload events.EventPayload, client *Client) {
|
||||
data, err := json.Marshal(payload)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
@@ -223,7 +229,7 @@ func (s *ChatServer) Send(payload events.EventPayload, client *ChatClient) {
|
||||
}
|
||||
|
||||
// DisconnectUser will forcefully disconnect all clients belonging to a user by ID.
|
||||
func (s *ChatServer) DisconnectUser(userID string) {
|
||||
func (s *Server) DisconnectUser(userID string) {
|
||||
s.mu.Lock()
|
||||
clients, err := GetClientsForUser(userID)
|
||||
s.mu.Unlock()
|
||||
@@ -234,9 +240,9 @@ func (s *ChatServer) DisconnectUser(userID string) {
|
||||
}
|
||||
|
||||
for _, client := range clients {
|
||||
log.Traceln("Disconnecting client", client.User.Id, "owned by", client.User.DisplayName)
|
||||
log.Traceln("Disconnecting client", client.User.ID, "owned by", client.User.DisplayName)
|
||||
|
||||
go func(client *ChatClient) {
|
||||
go func(client *Client) {
|
||||
event := events.UserDisabledEvent{}
|
||||
event.SetDefaults()
|
||||
|
||||
@@ -257,7 +263,7 @@ func (s *ChatServer) DisconnectUser(userID string) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ChatServer) eventReceived(event chatClientEvent) {
|
||||
func (s *Server) eventReceived(event chatClientEvent) {
|
||||
var typecheck map[string]interface{}
|
||||
if err := json.Unmarshal(event.data, &typecheck); err != nil {
|
||||
log.Debugln(err)
|
||||
@@ -277,7 +283,7 @@ func (s *ChatServer) eventReceived(event chatClientEvent) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ChatServer) sendWelcomeMessageToClient(c *ChatClient) {
|
||||
func (s *Server) sendWelcomeMessageToClient(c *Client) {
|
||||
// Add an artificial delay so people notice this message come in.
|
||||
time.Sleep(7 * time.Second)
|
||||
|
||||
@@ -288,7 +294,7 @@ func (s *ChatServer) sendWelcomeMessageToClient(c *ChatClient) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ChatServer) sendAllWelcomeMessage() {
|
||||
func (s *Server) sendAllWelcomeMessage() {
|
||||
welcomeMessage := utils.RenderSimpleMarkdown(data.GetServerWelcomeMessage())
|
||||
|
||||
if welcomeMessage != "" {
|
||||
@@ -303,7 +309,7 @@ func (s *ChatServer) sendAllWelcomeMessage() {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ChatServer) sendSystemMessageToClient(c *ChatClient, message string) {
|
||||
func (s *Server) sendSystemMessageToClient(c *Client, message string) {
|
||||
clientMessage := events.SystemMessageEvent{
|
||||
Event: events.Event{},
|
||||
MessageEvent: events.MessageEvent{
|
||||
@@ -314,7 +320,7 @@ func (s *ChatServer) sendSystemMessageToClient(c *ChatClient, message string) {
|
||||
s.Send(clientMessage.GetBroadcastPayload(), c)
|
||||
}
|
||||
|
||||
func (s *ChatServer) sendActionToClient(c *ChatClient, message string) {
|
||||
func (s *Server) sendActionToClient(c *Client, message string) {
|
||||
clientMessage := events.ActionEvent{
|
||||
MessageEvent: events.MessageEvent{
|
||||
Body: message,
|
||||
|
||||
Reference in New Issue
Block a user