BareRTC/pkg/server.go
Noah Petherbridge 52df45b2e9 GORM for the database for Postgres support
* For the Direct Message History database, use gorm.io as ORM so that Postgres
  can be used instead of SQLite for bigger chat room instances.
* In settings.toml: the new DatabaseType field defaults to 'sqlite3' but can be
  set to 'postgres' and use the credentials in the new PostgresDatabase field.
* The DirectMessage table schema is also updated to deprecate the Timestamp int
  field in favor of a proper CreatedAt datetime field. Existing SQLite instances
  will upgrade their table in the background, converting Timestamp to CreatedAt
  and blanking out the legacy Timestamp column.
* Fix some DB queries so when paginating your DMs history username list, sorting
  it by timestamp now works reliably.
* For existing SQLite instances that want to switch to Postgres, use the
  scripts/sqlite2psql.py script to transfer your database over.
2025-07-06 11:56:20 -07:00

105 lines
3.2 KiB
Go

package barertc
import (
"fmt"
"io"
"net/http"
"sync"
"time"
"git.kirsle.net/apps/barertc/pkg/config"
"git.kirsle.net/apps/barertc/pkg/log"
"git.kirsle.net/apps/barertc/pkg/models"
)
// Server is the primary back-end server struct for BareRTC, see main.go
type Server struct {
// Timestamp when the server started.
upSince time.Time
// HTTP router.
mux *http.ServeMux
// Max number of messages we'll buffer for a subscriber
subscriberMessageBuffer int
// Connected WebSocket subscribers.
subscribersMu sync.RWMutex
subscribers map[*Subscriber]struct{}
// Cached filehandles for channel logging.
logfh map[string]io.WriteCloser
}
// NewServer initializes the Server.
func NewServer() *Server {
return &Server{
subscriberMessageBuffer: 32,
subscribers: make(map[*Subscriber]struct{}),
}
}
// Setup the server: configure HTTP routes, etc.
func (s *Server) Setup() error {
// Enable the SQLite database for DM history?
if config.Current.DirectMessageHistory.Enabled {
var connstr string
switch config.Current.DirectMessageHistory.DatabaseType {
case "sqlite3":
connstr = config.Current.DirectMessageHistory.SQLiteDatabase
case "postgres":
connstr = config.Current.DirectMessageHistory.PostgresDatabase
default:
return fmt.Errorf("settings.toml: DirectMessageHistory: DatabaseType must be either sqlite or postgres")
}
if err := models.Initialize(config.Current.DirectMessageHistory.DatabaseType, connstr); err != nil {
log.Error("Error initializing SQLite database: %s", err)
}
}
var mux = http.NewServeMux()
mux.Handle("/", IndexPage())
mux.Handle("/about", AboutPage())
mux.Handle("/logout", LogoutPage())
mux.Handle("/ws", s.WebSocket())
mux.Handle("/poll", s.PollingAPI())
mux.Handle("/api/statistics", s.Statistics())
mux.Handle("/api/blocklist", s.BlockList())
mux.Handle("/api/block/now", s.BlockNow())
mux.Handle("/api/disconnect/now", s.DisconnectNow())
mux.Handle("/api/authenticate", s.Authenticate())
mux.Handle("/api/amend-jwt", s.AmendJWT())
mux.Handle("/api/shutdown", s.ShutdownAPI())
mux.Handle("/api/profile", s.UserProfile())
mux.Handle("/api/message/history", s.MessageHistory())
mux.Handle("/api/message/usernames", s.MessageUsernameHistory())
mux.Handle("/api/message/clear", s.ClearMessages())
mux.Handle("/assets/", http.StripPrefix("/assets/", http.FileServer(http.Dir("dist/assets"))))
mux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("dist/static"))))
s.mux = mux
return nil
}
// ListenAndServe starts the web server.
func (s *Server) ListenAndServe(address string) error {
// Run the polling user idle kicker.
s.upSince = time.Now()
go s.KickIdlePollUsers()
go s.sendWhoListAfterReady()
return http.ListenAndServe(address, s.mux)
}
// Send first WhoList update 15 seconds after the server reboots. This is in case a lot of chatters
// are online during a reboot: we avoid broadcasting Presence for 30 seconds and WhoList for 15 to
// reduce chatter and avoid kicking clients offline repeatedly for filling up their message buffer
// as everyone rejoins the chat all at once.
func (s *Server) sendWhoListAfterReady() {
time.Sleep(16 * time.Second)
log.Info("Up 15 seconds, sending WhoList to any online chatters")
s.SendWhoList()
}