package chatpb import ( "fmt" "os" "github.com/google/uuid" "go.wit.com/log" "google.golang.org/protobuf/proto" ) func (c *Chats) AddRegexComment(s string) *ChatEntry { log.Info("FIX") return nil } func (c *Chats) AddUserComment(s string) *ChatEntry { log.Info("FIX") return nil } func UnmarshalChats(data []byte) (*Chats, error) { c := new(Chats) err := c.Unmarshal(data) return c, err } func UnmarshalChatsTEXT(data []byte) (*Chats, error) { c := new(Chats) err := c.UnmarshalTEXT(data) return c, err } func (all *Chats) AddFile(filename string) error { // Nil checks for safety. if all == nil { return fmt.Errorf("cannot call AddFile on a nil *Chats object") } if all.Chats == nil { all.Chats = make([]*Chat, 0) } data, err := os.ReadFile(filename) if err != nil { log.Fatalf("Error reading file %s: %v", filename, err) return err } logData, err := UnmarshalChatsTEXT(data) if err != nil { log.Fatalf("Error unmarshaling log file %s: %v", filename, err) return err } // New, simplified logic assumes all files use the new nested format. for _, chatGroup := range logData.GetChats() { // It's now a direct append since the structure is the same. // We still clone to ensure the appended data is a safe copy. newChatGroup := proto.Clone(chatGroup).(*Chat) all.AppendByUuid(newChatGroup) } return nil } func (chats *Chats) VerifyUuids() bool { var changed bool all := chats.SortByUuid() for all.Scan() { chat := all.Next() if chat.Uuid == "" { chat.Uuid = uuid.New().String() changed = true } } return changed } func (c *Chat) VerifyUuid() bool { if c.Uuid == "" { c.Uuid = uuid.New().String() return true } return false } func (x *Chats) AppendNew(y *Chat) { x.Lock() defer x.Unlock() var chat *Chat chat = proto.Clone(y).(*Chat) x.Chats = append(x.Chats, chat) } // a Append() shortcut (that does Clone() with a mutex) notsure if it really works func (x *Chat) AppendEntry(y *ChatEntry) { x.Lock() defer x.Unlock() x.Entries = append(x.Entries, proto.Clone(y).(*ChatEntry)) } // returns true if the pb is probably the same func (c *ChatEntry) VerifyGeminiRequest(pb *GeminiRequest) (int, int, bool) { if c.GeminiRequest == nil { log.Warn("There is no GeminiRequest in the chat protobuf") return -1, -1, false } if pb == nil { log.Warn("There is no GeminiRequest in the passed in protobuf") return -1, -1, false } if len(c.GeminiRequest.GetContents()) != len(pb.GetContents()) { log.Warn("c != pb", len(c.GeminiRequest.GetContents()), len(pb.GetContents())) return -1, -1, false } var cCount int // # of Parts in all the Contents var pbCount int // # of Parts in all the Contents for _, grc := range c.GeminiRequest.GetContents() { cCount += len(grc.GetParts()) } for _, grc := range pb.GetContents() { pbCount += len(grc.GetParts()) } if cCount != pbCount { log.Warn("c != pb", cCount, pbCount) return len(c.GeminiRequest.GetContents()), cCount, false } log.Info("EVERYTHING MATCHED", cCount, pbCount, len(c.GeminiRequest.GetContents()), len(pb.GetContents())) return len(c.GeminiRequest.GetContents()), cCount, true }