Chore: solved some todos
This commit is contained in:
		| @@ -10,7 +10,7 @@ import ( | |||||||
| type Config struct { | type Config struct { | ||||||
| 	ServerConfig    ServerConfig `toml:"SERVICE"` | 	ServerConfig    ServerConfig `toml:"SERVICE"` | ||||||
| 	BaseURL         string       `toml:"BASE_URL"` | 	BaseURL         string       `toml:"BASE_URL"` | ||||||
| 	SessionLifetime int          `toml:"SESSION_LIFETIME_SECONDS"` | 	SessionLifetime int64        `toml:"SESSION_LIFETIME_SECONDS"` | ||||||
| 	CookieSecret    string       `toml:"COOKIE_SECRET"` | 	CookieSecret    string       `toml:"COOKIE_SECRET"` | ||||||
| 	LLMConfig       LLMConfig    `toml:"LLM"` | 	LLMConfig       LLMConfig    `toml:"LLM"` | ||||||
| } | } | ||||||
|   | |||||||
| @@ -183,17 +183,6 @@ func cacheSetSession(key string, session *models.Session) error { | |||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	memcache.Set(key, sesb) | 	memcache.Set(key, sesb) | ||||||
| 	// TODO: to config | 	memcache.Expire(key, cfg.SessionLifetime) | ||||||
| 	memcache.Expire(key, 60*60) |  | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| // unused |  | ||||||
| // func updateRoomInSession(ctx context.Context, roomID string) (context.Context, error) { |  | ||||||
| // 	s, ok := ctx.Value(models.CtxSessionKey).(*models.Session) |  | ||||||
| // 	if !ok { |  | ||||||
| // 		return context.TODO(), errors.New("failed to extract session from ctx") |  | ||||||
| // 	} |  | ||||||
| // 	s.CurrentRoom = roomID |  | ||||||
| // 	return context.WithValue(ctx, "session", s), nil |  | ||||||
| // } |  | ||||||
|   | |||||||
| @@ -167,8 +167,6 @@ func HandleAddBot(w http.ResponseWriter, r *http.Request) { | |||||||
| 		abortWithError(w, err.Error()) | 		abortWithError(w, err.Error()) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	// TODO: what if bot exists already? |  | ||||||
| 	// control number and names of bots |  | ||||||
| 	botname := fmt.Sprintf("bot_%d", len(llmapi.SignalChanMap)+1) // what if many rooms? | 	botname := fmt.Sprintf("bot_%d", len(llmapi.SignalChanMap)+1) // what if many rooms? | ||||||
| 	bot, err := llmapi.NewBot(role, team, botname, fi.Room.ID, cfg) | 	bot, err := llmapi.NewBot(role, team, botname, fi.Room.ID, cfg) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
|   | |||||||
| @@ -135,11 +135,14 @@ func HandleStartGame(w http.ResponseWriter, r *http.Request) { | |||||||
| 		abortWithError(w, err.Error()) | 		abortWithError(w, err.Error()) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	// TODO: check if enough players; also button should be hidden if already running | 	// check if enough players | ||||||
|  | 	if err := fi.Room.CanStart(); err != nil { | ||||||
|  | 		abortWithError(w, err.Error()) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
| 	fi.Room.IsRunning = true | 	fi.Room.IsRunning = true | ||||||
| 	fi.Room.IsOver = false | 	fi.Room.IsOver = false | ||||||
| 	fi.Room.TeamTurn = "blue" | 	fi.Room.TeamTurn = "blue" | ||||||
| 	// fi.Room.LoadTestCards() |  | ||||||
| 	loadCards(fi.Room) | 	loadCards(fi.Room) | ||||||
| 	fi.Room.UpdateCounter() | 	fi.Room.UpdateCounter() | ||||||
| 	fi.Room.TeamWon = "" | 	fi.Room.TeamWon = "" | ||||||
|   | |||||||
| @@ -26,7 +26,6 @@ func init() { | |||||||
| 	memcache = cache.MemCache | 	memcache = cache.MemCache | ||||||
| 	cfg = config.LoadConfigOrDefault("") | 	cfg = config.LoadConfigOrDefault("") | ||||||
| 	Notifier = broker.Notifier | 	Notifier = broker.Notifier | ||||||
| 	// go Notifier.Listen() |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func HandlePing(w http.ResponseWriter, r *http.Request) { | func HandlePing(w http.ResponseWriter, r *http.Request) { | ||||||
| @@ -84,6 +83,7 @@ func HandleExit(w http.ResponseWriter, r *http.Request) { | |||||||
| 	if len(exitedRoom.PlayerList) == 0 || creatorLeft { | 	if len(exitedRoom.PlayerList) == 0 || creatorLeft { | ||||||
| 		removeRoom(exitedRoom.ID) | 		removeRoom(exitedRoom.ID) | ||||||
| 		// TODO: notify users if creator left | 		// TODO: notify users if creator left | ||||||
|  | 		// and throw them away | ||||||
| 		notify(models.NotifyRoomListUpdate, "") | 		notify(models.NotifyRoomListUpdate, "") | ||||||
| 	} | 	} | ||||||
| 	if err := saveState(fi.State.Username, fi.State); err != nil { | 	if err := saveState(fi.State.Username, fi.State); err != nil { | ||||||
|   | |||||||
| @@ -26,9 +26,7 @@ func LogRequests(next http.Handler) http.Handler { | |||||||
|  |  | ||||||
| func GetSession(next http.Handler) http.Handler { | func GetSession(next http.Handler) http.Handler { | ||||||
| 	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | 	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		// TODO: move | 		sessionCookie, err := r.Cookie(models.AuthCookie) | ||||||
| 		cookieName := "session_token" |  | ||||||
| 		sessionCookie, err := r.Cookie(cookieName) |  | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			msg := "auth failed; failed to get session token from cookies" | 			msg := "auth failed; failed to get session token from cookies" | ||||||
| 			log.Debug(msg, "error", err) | 			log.Debug(msg, "error", err) | ||||||
| @@ -54,7 +52,7 @@ func GetSession(next http.Handler) http.Handler { | |||||||
| 		sessionToken := cookieValue[sha256.Size:] | 		sessionToken := cookieValue[sha256.Size:] | ||||||
| 		//verify signature | 		//verify signature | ||||||
| 		mac := hmac.New(sha256.New, []byte(cfg.CookieSecret)) | 		mac := hmac.New(sha256.New, []byte(cfg.CookieSecret)) | ||||||
| 		mac.Write([]byte(cookieName)) | 		mac.Write([]byte(models.AuthCookie)) | ||||||
| 		mac.Write([]byte(sessionToken)) | 		mac.Write([]byte(sessionToken)) | ||||||
| 		expectedSignature := mac.Sum(nil) | 		expectedSignature := mac.Sum(nil) | ||||||
| 		if !hmac.Equal([]byte(signature), expectedSignature) { | 		if !hmac.Equal([]byte(signature), expectedSignature) { | ||||||
|   | |||||||
| @@ -15,13 +15,6 @@ import ( | |||||||
| 	"strings" | 	"strings" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // TODO: config for url and token |  | ||||||
| // completion prompt |  | ||||||
| // MIME: llm needs to know all the cards, colors and previous actions |  | ||||||
| // GUESSER: llm needs to know all the cards and previous actions |  | ||||||
|  |  | ||||||
| // channels are not serializable |  | ||||||
|  |  | ||||||
| var ( | var ( | ||||||
| 	// botname -> channel | 	// botname -> channel | ||||||
| 	SignalChanMap = make(map[string]chan bool) | 	SignalChanMap = make(map[string]chan bool) | ||||||
| @@ -29,7 +22,6 @@ var ( | |||||||
| 	// got prompt: control character (\\u0000-\\u001F) found while parsing a string at line 4 column 0 | 	// got prompt: control character (\\u0000-\\u001F) found while parsing a string at line 4 column 0 | ||||||
| 	MimePrompt    = `we are playing alias;\nyou are a mime (player who gives a clue of one noun word and number of cards you expect them to open) of the %s team (people who would guess by your clue want open the %s cards);\nplease return your clue, number of cards to open and what words you mean them to find using that clue in json like:\n{\n\"clue\": \"one-word-noun\",\n\"number\": \"number-from-0-to-9\",\n\"words_I_mean_my_team_to_open\": [\"this\", \"that\", ...]\n}\nthe team who openes all their cards first wins.\nplease return json only.\nunopen Blue cards left: %d;\nunopen Red cards left: %d;\nhere is the game info in json:\n%s` | 	MimePrompt    = `we are playing alias;\nyou are a mime (player who gives a clue of one noun word and number of cards you expect them to open) of the %s team (people who would guess by your clue want open the %s cards);\nplease return your clue, number of cards to open and what words you mean them to find using that clue in json like:\n{\n\"clue\": \"one-word-noun\",\n\"number\": \"number-from-0-to-9\",\n\"words_I_mean_my_team_to_open\": [\"this\", \"that\", ...]\n}\nthe team who openes all their cards first wins.\nplease return json only.\nunopen Blue cards left: %d;\nunopen Red cards left: %d;\nhere is the game info in json:\n%s` | ||||||
| 	GuesserPrompt = `we are playing alias;\nyou are to guess words of the %s team (people who would guess by your clue want open the %s cards) by given clue and a number of meant guesses;\nplease return your guesses and words that you did not wish to open, but think that they could be also meant by the clue in json like:\n{\n\"guesses\": [\"word1\", \"word2\", ...],\n\"could_be\": [\"this\", \"that\", ...]\n}\nthe team who openes all their cards first wins.\nplease return json only.\nunopen Blue cards left: %d;\nunopen Red cards left: %d;\nhere is the game info in json:\n%s` | 	GuesserPrompt = `we are playing alias;\nyou are to guess words of the %s team (people who would guess by your clue want open the %s cards) by given clue and a number of meant guesses;\nplease return your guesses and words that you did not wish to open, but think that they could be also meant by the clue in json like:\n{\n\"guesses\": [\"word1\", \"word2\", ...],\n\"could_be\": [\"this\", \"that\", ...]\n}\nthe team who openes all their cards first wins.\nplease return json only.\nunopen Blue cards left: %d;\nunopen Red cards left: %d;\nhere is the game info in json:\n%s` | ||||||
| 	// notifier = |  | ||||||
| ) | ) | ||||||
|  |  | ||||||
| type DSResp struct { | type DSResp struct { | ||||||
| @@ -245,6 +237,13 @@ func NewBot(role, team, name, roomID string, cfg *config.Config) (*Bot, error) { | |||||||
| 		Role: models.StrToUserRole(role), | 		Role: models.StrToUserRole(role), | ||||||
| 		Team: models.StrToUserTeam(team), | 		Team: models.StrToUserTeam(team), | ||||||
| 	} | 	} | ||||||
|  | 	// check if already has the same team-role bot | ||||||
|  | 	// only one is allowed | ||||||
|  | 	for n, p := range room.BotMap { | ||||||
|  | 		if p.Role == bp.Role && p.Team == bp.Team { | ||||||
|  | 			return nil, fmt.Errorf("already has such bot with name: %s", n) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| 	room.BotMap[name] = bp | 	room.BotMap[name] = bp | ||||||
| 	switch team { | 	switch team { | ||||||
| 	case "red": | 	case "red": | ||||||
| @@ -385,11 +384,5 @@ func (b *Bot) CallLLM(prompt string) ([]byte, error) { | |||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 	b.log.Debug("llm resp", "body", string(body)) | 	b.log.Debug("llm resp", "body", string(body)) | ||||||
| 	// TODO: case where it has other text, not only json |  | ||||||
| 	// TODO: how to know which resp it is? mime or guessser? |  | ||||||
| 	// resp := &MimeResp{} |  | ||||||
| 	// if err := json.Unmarshal(body, &resp); err != nil { |  | ||||||
| 	// 	return nil, err |  | ||||||
| 	// } |  | ||||||
| 	return body, nil | 	return body, nil | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										18
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								main.go
									
									
									
									
									
								
							| @@ -1,20 +1,27 @@ | |||||||
| package main | package main | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"golias/config" | ||||||
| 	"golias/handlers" | 	"golias/handlers" | ||||||
| 	"log/slog" | 	"log/slog" | ||||||
| 	"net/http" | 	"net/http" | ||||||
| 	"time" | 	"time" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // TODO: add config as param | var cfg *config.Config | ||||||
|  |  | ||||||
|  | func init() { | ||||||
|  | 	cfg = config.LoadConfigOrDefault("") | ||||||
|  | } | ||||||
|  |  | ||||||
| func ListenToRequests(port string) error { | func ListenToRequests(port string) error { | ||||||
| 	mux := http.NewServeMux() | 	mux := http.NewServeMux() | ||||||
| 	server := &http.Server{ | 	server := &http.Server{ | ||||||
| 		Handler:      handlers.LogRequests(handlers.GetSession(mux)), | 		Handler:      handlers.LogRequests(handlers.GetSession(mux)), | ||||||
| 		Addr:         port, | 		Addr:         fmt.Sprintf(":%s", port), | ||||||
| 		ReadTimeout:  time.Second * 5, | 		ReadTimeout:  time.Second * 5, // TODO: to cfg | ||||||
| 		WriteTimeout: 0, // sse streaming | 		WriteTimeout: 0,               // sse streaming | ||||||
| 	} | 	} | ||||||
| 	fs := http.FileServer(http.Dir("assets/")) | 	fs := http.FileServer(http.Dir("assets/")) | ||||||
| 	mux.Handle("GET /assets/", http.StripPrefix("/assets/", fs)) | 	mux.Handle("GET /assets/", http.StripPrefix("/assets/", fs)) | ||||||
| @@ -43,8 +50,7 @@ func ListenToRequests(port string) error { | |||||||
| } | } | ||||||
|  |  | ||||||
| func main() { | func main() { | ||||||
| 	port := ":3000" | 	err := ListenToRequests(cfg.ServerConfig.Port) | ||||||
| 	err := ListenToRequests(port) |  | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		panic(err) | 		panic(err) | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| package models | package models | ||||||
|  |  | ||||||
| var ( | var ( | ||||||
|  | 	AuthCookie     = "session_token" | ||||||
| 	CtxRoomIDKey   = "current_room" | 	CtxRoomIDKey   = "current_room" | ||||||
| 	CtxUsernameKey = "username" | 	CtxUsernameKey = "username" | ||||||
| 	CtxSessionKey  = "session" | 	CtxSessionKey  = "session" | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| package models | package models | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  | 	"errors" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"golias/utils" | 	"golias/utils" | ||||||
| 	"time" | 	"time" | ||||||
| @@ -83,6 +84,25 @@ type Room struct { | |||||||
| 	TeamWon UserTeam // blue | red | 	TeamWon UserTeam // blue | red | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (r *Room) CanStart() error { | ||||||
|  | 	if r.IsRunning { | ||||||
|  | 		return errors.New("cannot start; game is already running") | ||||||
|  | 	} | ||||||
|  | 	if r.RedTeam.Mime == "" { | ||||||
|  | 		return errors.New("cannot start; red team has no mime") | ||||||
|  | 	} | ||||||
|  | 	if r.BlueTeam.Mime == "" { | ||||||
|  | 		return errors.New("cannot start; blue team has no mime") | ||||||
|  | 	} | ||||||
|  | 	if len(r.RedTeam.Guessers) == 0 { | ||||||
|  | 		return errors.New("cannot start; red team has no guessers") | ||||||
|  | 	} | ||||||
|  | 	if len(r.BlueTeam.Guessers) == 0 { | ||||||
|  | 		return errors.New("cannot start; blue team has no guessers") | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
| // WhichBotToMove returns bot name that have to move or empty string | // WhichBotToMove returns bot name that have to move or empty string | ||||||
| func (r *Room) WhichBotToMove() string { | func (r *Room) WhichBotToMove() string { | ||||||
| 	fmt.Println("looking for bot to move", "team-turn", r.TeamTurn, "mime-done", r.MimeDone, "bot-map", r.BotMap, "is_running", r.IsRunning) | 	fmt.Println("looking for bot to move", "team-turn", r.TeamTurn, "mime-done", r.MimeDone, "bot-map", r.BotMap, "is_running", r.IsRunning) | ||||||
| @@ -141,46 +161,6 @@ func (r *Room) UpdateCounter() { | |||||||
| 	r.BlueCounter = blueCounter | 	r.BlueCounter = blueCounter | ||||||
| } | } | ||||||
|  |  | ||||||
| // func (r *Room) LoadTestCards() { |  | ||||||
| // 	// TODO: pass room settings |  | ||||||
| // 	// TODO: map language to path |  | ||||||
| // 	wl := wordloader.InitDefaultLoader("assets/words/en_nouns.txt") |  | ||||||
| // 	cards, err := wl.Load() |  | ||||||
| // 	if err != nil { |  | ||||||
| // 		// no logger |  | ||||||
| // 		fmt.Println("failed to load cards", "error", err) |  | ||||||
| // 	} |  | ||||||
| // 	r.Cards = cards |  | ||||||
| // 	// cards := []WordCard{ |  | ||||||
| // 	// 	{Word: "hamster", Color: "blue"}, |  | ||||||
| // 	// 	{Word: "child", Color: "red"}, |  | ||||||
| // 	// 	{Word: "wheel", Color: "white"}, |  | ||||||
| // 	// 	{Word: "condition", Color: "black"}, |  | ||||||
| // 	// 	{Word: "test", Color: "white"}, |  | ||||||
| // 	// 	{Word: "ball", Color: "blue"}, |  | ||||||
| // 	// 	{Word: "violin", Color: "red"}, |  | ||||||
| // 	// 	{Word: "rat", Color: "white"}, |  | ||||||
| // 	// 	{Word: "perplexity", Color: "blue"}, |  | ||||||
| // 	// 	{Word: "notion", Color: "red"}, |  | ||||||
| // 	// 	{Word: "guitar", Color: "blue"}, |  | ||||||
| // 	// 	{Word: "ocean", Color: "blue"}, |  | ||||||
| // 	// 	{Word: "moon", Color: "blue"}, |  | ||||||
| // 	// 	{Word: "coffee", Color: "blue"}, |  | ||||||
| // 	// 	{Word: "mountain", Color: "blue"}, |  | ||||||
| // 	// 	{Word: "book", Color: "blue"}, |  | ||||||
| // 	// 	{Word: "camera", Color: "blue"}, |  | ||||||
| // 	// 	{Word: "apple", Color: "red"}, |  | ||||||
| // 	// 	{Word: "fire", Color: "red"}, |  | ||||||
| // 	// 	{Word: "rose", Color: "red"}, |  | ||||||
| // 	// 	{Word: "sun", Color: "red"}, |  | ||||||
| // 	// 	{Word: "cherry", Color: "red"}, |  | ||||||
| // 	// 	{Word: "heart", Color: "red"}, |  | ||||||
| // 	// 	{Word: "tomato", Color: "red"}, |  | ||||||
| // 	// 	{Word: "cloud", Color: "white"}, |  | ||||||
| // 	// } |  | ||||||
| // 	// r.Cards = cards |  | ||||||
| // } |  | ||||||
|  |  | ||||||
| func (r *Room) ChangeTurn() { | func (r *Room) ChangeTurn() { | ||||||
| 	switch r.TeamTurn { | 	switch r.TeamTurn { | ||||||
| 	case "blue": | 	case "blue": | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Grail Finder
					Grail Finder