Fix: buildable
This commit is contained in:
		| @@ -2,14 +2,12 @@ package handlers | |||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"encoding/json" |  | ||||||
| 	"errors" | 	"errors" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"gralias/broker" | 	"gralias/broker" | ||||||
| 	"gralias/llmapi" | 	"gralias/llmapi" | ||||||
| 	"gralias/models" | 	"gralias/models" | ||||||
| 	"gralias/wordloader" | 	"gralias/wordloader" | ||||||
| 	"strings" |  | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func createRoom(ctx context.Context, req *models.RoomReq) (*models.Room, error) { | func createRoom(ctx context.Context, req *models.RoomReq) (*models.Room, error) { | ||||||
| @@ -20,7 +18,7 @@ func createRoom(ctx context.Context, req *models.RoomReq) (*models.Room, error) | |||||||
| 	} | 	} | ||||||
| 	room := req.CreateRoom(creator) | 	room := req.CreateRoom(creator) | ||||||
| 	room.RoomLink = cfg.BaseURL + "/room-join?id=" + room.ID | 	room.RoomLink = cfg.BaseURL + "/room-join?id=" + room.ID | ||||||
| 	if err := repo.CreateRoom(ctx, room); err != nil { | 	if err := repo.RoomCreate(ctx, room); err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 	return room, nil | 	return room, nil | ||||||
| @@ -109,25 +107,24 @@ func notifyBotIfNeeded(room *models.Room) { | |||||||
| // 	return nil | // 	return nil | ||||||
| // } | // } | ||||||
|  |  | ||||||
| func getAllNames() []string { | // func getAllNames() []string { | ||||||
| 	names := []string{} | // 	names := []string{} | ||||||
| 	// will not scale | // 	// will not scale | ||||||
| 	wholeMemStore := memcache.GetAll() | // 	session := &models.Session{} | ||||||
| 	session := &models.Session{} | // 	// filter by key size only sessions | ||||||
| 	// filter by key size only sessions | // 	for _, name := range wholeMemStore { | ||||||
| 	for k, v := range wholeMemStore { | // 		// xid is 20 in len | ||||||
| 		// xid is 20 in len | // 		if len(k) != 20 { | ||||||
| 		if len(k) != 20 { | // 			continue | ||||||
| 			continue | // 		} | ||||||
| 		} | // 		if err := json.Unmarshal(v, &session); err != nil { | ||||||
| 		if err := json.Unmarshal(v, &session); err != nil { | // 			log.Error("failed to unmarshal", "error", err) | ||||||
| 			log.Error("failed to unmarshal", "error", err) | // 			continue | ||||||
| 			continue | // 		} | ||||||
| 		} | // 		names = append(names, session.Username) | ||||||
| 		names = append(names, session.Username) | // 	} | ||||||
| 	} | // 	return names | ||||||
| 	return names | // } | ||||||
| } |  | ||||||
|  |  | ||||||
| // can room exists without state? I think no | // can room exists without state? I think no | ||||||
| func getFullInfoByCtx(ctx context.Context) (*models.FullInfo, error) { | func getFullInfoByCtx(ctx context.Context) (*models.FullInfo, error) { | ||||||
| @@ -142,7 +139,7 @@ func getFullInfoByCtx(ctx context.Context) (*models.FullInfo, error) { | |||||||
| 		return resp, nil | 		return resp, nil | ||||||
| 	} | 	} | ||||||
| 	// room, err := getRoomByID(state.RoomID) | 	// room, err := getRoomByID(state.RoomID) | ||||||
| 	room, err := repo.GetRoomByID(ctx, state.RoomID) | 	room, err := repo.RoomGetByID(ctx, state.RoomID) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		log.Warn("failed to find room despite knowing room_id;", | 		log.Warn("failed to find room despite knowing room_id;", | ||||||
| 			"room_id", state.RoomID) | 			"room_id", state.RoomID) | ||||||
| @@ -158,7 +155,7 @@ func getPlayerByCtx(ctx context.Context) (*models.Player, error) { | |||||||
| 		log.Debug("no username in ctx") | 		log.Debug("no username in ctx") | ||||||
| 		return &models.Player{}, errors.New("no username in ctx") | 		return &models.Player{}, errors.New("no username in ctx") | ||||||
| 	} | 	} | ||||||
| 	return repo.GetPlayerByName(username) | 	return repo.PlayerGetByName(username) | ||||||
| } | } | ||||||
|  |  | ||||||
| // // DEPRECATED | // // DEPRECATED | ||||||
| @@ -249,41 +246,15 @@ func joinTeam(ctx context.Context, role, team string) (*models.FullInfo, error) | |||||||
| // } | // } | ||||||
|  |  | ||||||
| // get bots | // get bots | ||||||
| func listBots() map[string]map[string]string { | func listBots() []models.Player { | ||||||
| 	cacheMap := memcache.GetAll() | 	bots, err := repo.PlayerList(true) | ||||||
| 	resp := make(map[string]map[string]string) | 	if err != nil { | ||||||
| 	// no way to know if room is public until unmarshal -_-; | 		log.Error("failed to fetch bots from db", "error", err) | ||||||
| 	for key, value := range cacheMap { |  | ||||||
| 		if strings.HasPrefix(key, models.CacheBotPredix) { |  | ||||||
| 			botMap := make(map[string]string) |  | ||||||
| 			if err := json.Unmarshal(value, &botMap); err != nil { |  | ||||||
| 				log.Warn("failed to unmarshal bot", "error", err) |  | ||||||
| 				continue |  | ||||||
| 			} |  | ||||||
| 			resp[botMap["bot_name"]] = botMap |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
| 	return resp | 	return bots | ||||||
| } | } | ||||||
|  |  | ||||||
| // get players | // get players | ||||||
| func listPlayers() map[string]map[string]string { |  | ||||||
| 	cacheMap := memcache.GetAll() |  | ||||||
| 	resp := make(map[string]map[string]string) |  | ||||||
| 	// no way to know if room is public until unmarshal -_-; |  | ||||||
| 	for key, value := range cacheMap { |  | ||||||
| 		if strings.HasPrefix(key, models.CacheStatePrefix) { |  | ||||||
| 			playerMap := make(map[string]string) |  | ||||||
| 			if err := json.Unmarshal(value, &playerMap); err != nil { |  | ||||||
| 				log.Warn("failed to unmarshal player", "error", err) |  | ||||||
| 				continue |  | ||||||
| 			} |  | ||||||
| 			resp[playerMap["Username"]] = playerMap |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return resp |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func notify(event, msg string) { | func notify(event, msg string) { | ||||||
| 	Notifier.Notifier <- broker.NotificationEvent{ | 	Notifier.Notifier <- broker.NotificationEvent{ | ||||||
| 		EventName: event, | 		EventName: event, | ||||||
| @@ -312,54 +283,54 @@ func loadCards(room *models.Room) { | |||||||
|  |  | ||||||
| func recoverBots() { | func recoverBots() { | ||||||
| 	bots := listBots() | 	bots := listBots() | ||||||
| 	for botName, botMap := range bots { | 	for _, bot := range bots { | ||||||
| 		if err := recoverBot(botMap); err != nil { | 		if err := recoverBot(bot); err != nil { | ||||||
| 			log.Warn("failed to recover bot", "botName", botName, "error", err) | 			log.Warn("failed to recover bot", "botName", bot.Username, "error", err) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func recoverBot(bm map[string]string) error { | func recoverBot(bm models.Player) error { | ||||||
| 	// check if room still exists | 	// check if room still exists | ||||||
| 	if _, err := getRoomByID(bm["room_id"]); err != nil { | 	if _, err := repo.RoomGetByID(context.Background(), bm.RoomID); err != nil { | ||||||
| 		return fmt.Errorf("no such room: %s; err: %w", bm["room_id"], err) | 		return fmt.Errorf("no such room: %s; err: %w", bm.RoomID, err) | ||||||
| 	} | 	} | ||||||
| 	log.Debug("recovering bot", "bot", bm) | 	log.Debug("recovering bot", "bot", bm) | ||||||
| 	_, err := llmapi.NewBot(bm["role"], bm["team"], bm["bot_name"], bm["room_id"], cfg, true) | 	_, err := llmapi.NewBot(string(bm.Role), string(bm.Team), bm.Username, bm.RoomID, cfg, true) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func recoverPlayers() { | // func recoverPlayers() { | ||||||
| 	players := listPlayers() | // 	players := listPlayers() | ||||||
| 	for playerName, playerMap := range players { | // 	for playerName, playerMap := range players { | ||||||
| 		if err := recoverPlayer(playerMap); err != nil { | // 		if err := recoverPlayer(playerMap); err != nil { | ||||||
| 			log.Warn("failed to recover player", "playerName", playerName, "error", err) | // 			log.Warn("failed to recover player", "playerName", playerName, "error", err) | ||||||
| 		} | // 		} | ||||||
| 	} | // 	} | ||||||
| } | // } | ||||||
|  |  | ||||||
| func recoverPlayer(pm map[string]string) error { | // func recoverPlayer(pm map[string]string) error { | ||||||
| 	// check if room still exists | // 	// check if room still exists | ||||||
| 	room, err := getRoomByID(pm["RoomID"]) | // 	room, err := repo.RoomGetByID(context.Background(), pm["RoomID"]) | ||||||
| 	if err != nil { | // 	if err != nil { | ||||||
| 		return fmt.Errorf("no such room: %s; err: %w", pm["RoomID"], err) | // 		return fmt.Errorf("no such room: %s; err: %w", pm["RoomID"], err) | ||||||
| 	} | // 	} | ||||||
| 	log.Debug("recovering player", "player", pm) | // 	log.Debug("recovering player", "player", pm) | ||||||
| 	role, team, ok := room.GetPlayerByName(pm["Username"]) | // 	role, team, ok := room.GetPlayerByName(pm["Username"]) | ||||||
| 	if !ok { | // 	if !ok { | ||||||
| 		return fmt.Errorf("failed to find player %s in the room %v", pm["Username"], room) | // 		return fmt.Errorf("failed to find player %s in the room %v", pm["Username"], room) | ||||||
| 	} | // 	} | ||||||
| 	us := &models.UserState{ | // 	us := &models.Player{ | ||||||
| 		Username: pm["Username"], | // 		Username: pm["Username"], | ||||||
| 		RoomID:   pm["RoomID"], | // 		RoomID:   pm["RoomID"], | ||||||
| 		Team:     team, | // 		Team:     team, | ||||||
| 		Role:     role, | // 		Role:     role, | ||||||
| 	} | // 	} | ||||||
| 	return saveState(pm["Username"], us) | // 	return saveState(pm["Username"], us) | ||||||
| } | // } | ||||||
|  |  | ||||||
| // validateMove checks if it is players turn | // validateMove checks if it is players turn | ||||||
| func validateMove(fi *models.FullInfo, ur models.UserRole) error { | func validateMove(fi *models.FullInfo, ur models.UserRole) error { | ||||||
|   | |||||||
| @@ -7,6 +7,7 @@ import ( | |||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"gralias/models" | 	"gralias/models" | ||||||
|  | 	"gralias/pkg/cache" | ||||||
| 	"gralias/utils" | 	"gralias/utils" | ||||||
| 	"html/template" | 	"html/template" | ||||||
| 	"net/http" | 	"net/http" | ||||||
| @@ -36,7 +37,12 @@ func HandleNameCheck(w http.ResponseWriter, r *http.Request) { | |||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	cleanName := utils.RemoveSpacesFromStr(username) | 	cleanName := utils.RemoveSpacesFromStr(username) | ||||||
| 	allNames := getAllNames() | 	// allNames := getAllNames() | ||||||
|  | 	allNames, err := repo.PlayerListNames() | ||||||
|  | 	if err != nil { | ||||||
|  | 		abortWithError(w, err.Error()) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
| 	log.Info("names check", "taken_names", allNames, "trying_name", cleanName) | 	log.Info("names check", "taken_names", allNames, "trying_name", cleanName) | ||||||
| 	tmpl, err := template.ParseGlob("components/*.html") | 	tmpl, err := template.ParseGlob("components/*.html") | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| @@ -175,7 +181,7 @@ func makeCookie(username string, remote string) (*http.Cookie, error) { | |||||||
| } | } | ||||||
|  |  | ||||||
| func cacheGetSession(key string) (*models.Session, error) { | func cacheGetSession(key string) (*models.Session, error) { | ||||||
| 	userSessionB, err := memcache.Get(key) | 	userSessionB, err := cache.MemCache.Get(key) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| @@ -191,7 +197,7 @@ func cacheSetSession(key string, session *models.Session) error { | |||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	memcache.Set(key, sesb) | 	cache.MemCache.Set(key, sesb) | ||||||
| 	memcache.Expire(key, cfg.SessionLifetime) | 	cache.MemCache.Expire(key, cfg.SessionLifetime) | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|   | |||||||
| @@ -4,13 +4,11 @@ import ( | |||||||
| 	"gralias/broker" | 	"gralias/broker" | ||||||
| 	"gralias/config" | 	"gralias/config" | ||||||
| 	"gralias/models" | 	"gralias/models" | ||||||
| 	"gralias/pkg/cache" |  | ||||||
| 	"gralias/repos" | 	"gralias/repos" | ||||||
| 	"html/template" | 	"html/template" | ||||||
| 	"log/slog" | 	"log/slog" | ||||||
| 	"net/http" | 	"net/http" | ||||||
| 	"os" | 	"os" | ||||||
| 	"time" |  | ||||||
| ) | ) | ||||||
|  |  | ||||||
| var ( | var ( | ||||||
| @@ -29,13 +27,13 @@ func init() { | |||||||
| 	// memcache = cache.MemCache | 	// memcache = cache.MemCache | ||||||
| 	cfg = config.LoadConfigOrDefault("") | 	cfg = config.LoadConfigOrDefault("") | ||||||
| 	Notifier = broker.Notifier | 	Notifier = broker.Notifier | ||||||
| 	cache.MemCache.StartBackupRoutine(15 * time.Second) // Reduced backup interval | 	// cache.MemCache.StartBackupRoutine(15 * time.Second) // Reduced backup interval | ||||||
| 	// bot loader | 	// bot loader | ||||||
| 	// check the rooms if it has bot_{digits} in them, create bots if have | 	// check the rooms if it has bot_{digits} in them, create bots if have | ||||||
| 	repo = repos.NewRepoProvider("sqlite3://../gralias.db") | 	repo = repos.NewRepoProvider("sqlite3://../gralias.db") | ||||||
| 	recoverBots() | 	recoverBots() | ||||||
| 	// if player has a roomID, but no team and role, try to recover | 	// if player has a roomID, but no team and role, try to recover | ||||||
| 	recoverPlayers() | 	// recoverPlayers() | ||||||
| } | } | ||||||
|  |  | ||||||
| func HandlePing(w http.ResponseWriter, r *http.Request) { | func HandlePing(w http.ResponseWriter, r *http.Request) { | ||||||
|   | |||||||
| @@ -6,6 +6,7 @@ import ( | |||||||
| 	"crypto/sha256" | 	"crypto/sha256" | ||||||
| 	"encoding/base64" | 	"encoding/base64" | ||||||
| 	"gralias/models" | 	"gralias/models" | ||||||
|  | 	"gralias/pkg/cache" | ||||||
| 	"net/http" | 	"net/http" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -70,7 +71,7 @@ func GetSession(next http.Handler) http.Handler { | |||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
| 		if userSession.IsExpired() { | 		if userSession.IsExpired() { | ||||||
| 			memcache.RemoveKey(sessionToken) | 			cache.MemCache.RemoveKey(sessionToken) | ||||||
| 			msg := "session is expired" | 			msg := "session is expired" | ||||||
| 			log.Debug(msg, "error", err, "token", sessionToken) | 			log.Debug(msg, "error", err, "token", sessionToken) | ||||||
| 			next.ServeHTTP(w, r) | 			next.ServeHTTP(w, r) | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| package handlers | package handlers | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  | 	"context" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"gralias/models" | 	"gralias/models" | ||||||
| 	"sync" | 	"sync" | ||||||
| @@ -35,7 +36,7 @@ func StartTurnTimer(roomID string, duration time.Duration) { | |||||||
| 			case <-done: | 			case <-done: | ||||||
| 				return | 				return | ||||||
| 			case <-ticker.C: | 			case <-ticker.C: | ||||||
| 				room, err := getRoomByID(roomID) | 				room, err := repo.RoomGetByID(context.Background(), roomID) | ||||||
| 				if err != nil { | 				if err != nil { | ||||||
| 					log.Error("failed to get room by id", "error", err) | 					log.Error("failed to get room by id", "error", err) | ||||||
| 					StopTurnTimer(roomID) | 					StopTurnTimer(roomID) | ||||||
| @@ -45,7 +46,7 @@ func StartTurnTimer(roomID string, duration time.Duration) { | |||||||
| 					log.Info("turn time is over", "room_id", roomID) | 					log.Info("turn time is over", "room_id", roomID) | ||||||
| 					room.ChangeTurn() | 					room.ChangeTurn() | ||||||
| 					room.MimeDone = false | 					room.MimeDone = false | ||||||
| 					if err := saveRoom(room); err != nil { | 					if err := repo.RoomUpdate(context.Background(), room); err != nil { | ||||||
| 						log.Error("failed to save room", "error", err) | 						log.Error("failed to save room", "error", err) | ||||||
| 					} | 					} | ||||||
| 					notify(models.NotifyTurnTimerPrefix+room.ID, fmt.Sprintf("%d", room.Settings.TurnSecondsLeft)) | 					notify(models.NotifyTurnTimerPrefix+room.ID, fmt.Sprintf("%d", room.Settings.TurnSecondsLeft)) | ||||||
| @@ -72,4 +73,3 @@ func StopTurnTimer(roomID string) { | |||||||
| 		delete(timers, roomID) | 		delete(timers, roomID) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -378,7 +378,7 @@ type WordCard struct { | |||||||
| 	Word     string     `json:"word" db:"word"` | 	Word     string     `json:"word" db:"word"` | ||||||
| 	Color    WordColor  `json:"color" db:"color"` | 	Color    WordColor  `json:"color" db:"color"` | ||||||
| 	Revealed bool       `json:"revealed" db:"revealed"` | 	Revealed bool       `json:"revealed" db:"revealed"` | ||||||
| 	MimeView bool       `json:"mime_view" db:"mime_view"` // user who sees that card is mime | 	Mime     bool       `json:"mime" db:"mime"` // user who sees that card is mime | ||||||
| 	Mark     []CardMark `json:"marks" db:"-"` | 	Mark     []CardMark `json:"marks" db:"-"` | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -402,13 +402,16 @@ type RoomReq struct { | |||||||
|  |  | ||||||
| func (rr *RoomReq) CreateRoom(creator string) *Room { | func (rr *RoomReq) CreateRoom(creator string) *Room { | ||||||
| 	roomID := xid.New().String() | 	roomID := xid.New().String() | ||||||
|  | 	settings := GameSettings{ | ||||||
|  | 		Language:  rr.Language, | ||||||
|  | 		RoundTime: rr.RoundTime, | ||||||
|  | 		RoomPass:  rr.RoomPass, | ||||||
|  | 	} | ||||||
| 	return &Room{ | 	return &Room{ | ||||||
| 		ID:          roomID, | 		ID:          roomID, | ||||||
| 		CreatedAt:   time.Now(), | 		CreatedAt:   time.Now(), | ||||||
| 		CreatorName: creator, | 		CreatorName: creator, | ||||||
| 		Language:    rr.Language, | 		Settings:    settings, | ||||||
| 		RoundTime:   rr.RoundTime, |  | ||||||
| 		RoomPass:    rr.RoomPass, |  | ||||||
| 		BotMap:      make(map[string]BotPlayer), | 		BotMap:      make(map[string]BotPlayer), | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -12,6 +12,17 @@ type PlayersRepo interface { | |||||||
| 	PlayerDelete(roomID, username string) error | 	PlayerDelete(roomID, username string) error | ||||||
| 	PlayerSetRoomID(username, roomID string) error | 	PlayerSetRoomID(username, roomID string) error | ||||||
| 	PlayerExitRoom(username string) error | 	PlayerExitRoom(username string) error | ||||||
|  | 	PlayerListNames() ([]string, error) | ||||||
|  | 	PlayerList(isBot bool) ([]models.Player, error) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (p *RepoProvider) PlayerListNames() ([]string, error) { | ||||||
|  | 	var names []string | ||||||
|  | 	err := p.DB.SelectContext(context.Background(), &names, "SELECT username FROM players;") | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	return names, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (p *RepoProvider) PlayerGetByName(username string) (*models.Player, error) { | func (p *RepoProvider) PlayerGetByName(username string) (*models.Player, error) { | ||||||
| @@ -49,3 +60,18 @@ func (p *RepoProvider) PlayerExitRoom(username string) error { | |||||||
| 	_, err := p.DB.ExecContext(context.Background(), "UPDATE players SET room_id = null WHERE username = ?", username) | 	_, err := p.DB.ExecContext(context.Background(), "UPDATE players SET room_id = null WHERE username = ?", username) | ||||||
| 	return err | 	return err | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (p *RepoProvider) PlayerList(isBot bool) ([]models.Player, error) { | ||||||
|  | 	var players []models.Player | ||||||
|  | 	var query string | ||||||
|  | 	if isBot { | ||||||
|  | 		query = "SELECT id, room_id, username, team, role, is_bot FROM players WHERE is_bot = true;" | ||||||
|  | 	} else { | ||||||
|  | 		query = "SELECT id, room_id, username, team, role, is_bot FROM players WHERE is_bot = false;" | ||||||
|  | 	} | ||||||
|  | 	err := p.DB.SelectContext(context.Background(), &players, query) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	return players, nil | ||||||
|  | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Grail Finder
					Grail Finder