package web import ( "errors" "fmt" "strconv" "time" "dyproxy/.gen/model" "dyproxy/.gen/table" "github.com/go-jet/jet/v2/qrm" . "github.com/go-jet/jet/v2/sqlite" "github.com/gofiber/fiber/v3" "github.com/samber/lo" "github.com/sirupsen/logrus" ) type ExpertConfig struct { Voice string Hello string Wechat string Region []string NameKeyword []string Produce bool DefaultName bool DefaultAvatar bool } func (s *WebServer) routeGetDevices(c fiber.Ctx) error { devices := []model.Device{} stmt := table.Device.SELECT(table.Device.AllColumns).ORDER_BY(table.Device.ID) if err := stmt.QueryContext(c.UserContext(), s.db, &devices); err != nil { return err } expertsIds := lo.FilterMap(devices, func(device model.Device, _ int) (Expression, bool) { if device.Expert == "" { return nil, false } return String(device.Expert), true }) if len(expertsIds) == 0 { return c.JSON(devices) } type listDevice struct { model.Device `json:",inline"` ExpertName string } // find experts by ids experts := []model.Expert{} stmt = table.Expert.SELECT(table.Expert.AllColumns).WHERE(table.Expert.UID.IN(expertsIds...)) if err := stmt.QueryContext(c.UserContext(), s.db, &experts); err != nil { return err } expertsMap := make(map[string]string) for _, expert := range experts { expertsMap[expert.UID] = expert.RealName } list := make([]listDevice, 0, len(devices)) for _, device := range devices { if expertName, ok := expertsMap[device.Expert]; ok { list = append(list, listDevice{ Device: device, ExpertName: expertName, }) } else { list = append(list, listDevice{ Device: device, ExpertName: "未设置", }) } } return c.JSON(list) } func (s *WebServer) routeGetDevice(c fiber.Ctx) error { deviceID := c.Params("uuid") var device model.Device err := table.Device.SELECT(table.Device.AllColumns).WHERE(table.Device.UUID.EQ(String(deviceID))).QueryContext(c.UserContext(), s.db, &device) if err != nil { if errors.Is(err, qrm.ErrNoRows) { // create new device device.UUID = deviceID _, err = table.Device.INSERT(table.Device.AllColumns.Except(table.Device.ID)).MODEL(device).ExecContext(c.UserContext(), s.db) if err != nil { return err } return c.JSON(nil) } return err } return c.JSON(device) } func (s *WebServer) routeGetDeviceFollower(c fiber.Ctx) error { if s.pendingItems == nil { s.pendingItems = make(map[int32]time.Time) } // get device deviceID := c.Params("uuid") var device model.Device err := table.Device.SELECT(table.Device.AllColumns).WHERE(table.Device.UUID.EQ(String(deviceID))).QueryContext(c.UserContext(), s.db, &device) if err != nil { if errors.Is(err, qrm.ErrNoRows) { // create new device device.UUID = deviceID _, err = table.Device.INSERT(table.Device.AllColumns.Except(table.Device.ID)).MODEL(device).ExecContext(c.UserContext(), s.db) if err != nil { return err } return c.JSON(nil) } return err } if device.Expert == "" { return c.JSON(nil) } if device.State == StateStop { return c.JSON(nil) } tbl := table.Follower lastID := c.Query("last", "") if lastID != "" { id, err := strconv.Atoi(lastID) if err != nil { return err } // remove from pending s.listLock.Lock() delete(s.pendingItems, int32(id)) s.listLock.Unlock() tbl. UPDATE(table.Follower.Followed). SET(Int32(1)). WHERE(table.Follower.ID.EQ(Int32(int32(id)))). ExecContext(c.UserContext(), s.db) } pendingIDs := []Expression{} for i := range s.pendingItems { pendingIDs = append(pendingIDs, Int32(i)) } pendingIDs = []Expression{} // get device expert var expert model.Expert err = table.Expert.SELECT(table.Expert.AllColumns).WHERE(table.Expert.UID.EQ(String(device.Expert))).QueryContext(c.UserContext(), s.db, &expert) if err != nil { return err } c.Response().Header.Set("x-expert-uid", expert.UID) c.Response().Header.Set("x-config-at", fmt.Sprintf("%d", expert.ConfigAt)) if expert.State == StateStop { return c.JSON(nil) } condition := tbl.Followed.EQ(Int32(0)). AND(tbl.ExpertUID.EQ(String(device.Expert))). AND(tbl.ID.NOT_IN(pendingIDs...)). AND(tbl.CreatedAt.GT(Int32(expert.Since))) stmt := tbl. SELECT(tbl.AllColumns). WHERE(condition). ORDER_BY(table.Follower.ID.DESC()). LIMIT(1) logrus.Debug(stmt.DebugSql()) var follower model.Follower if err := stmt.QueryContext(c.UserContext(), s.db, &follower); err != nil { if errors.Is(err, qrm.ErrNoRows) { return c.JSON(nil) } return err } s.listLock.Lock() s.pendingItems[int32(follower.ID)] = time.Now() s.listLock.Unlock() return c.JSON(follower) } // routeSetDeviceExpert func (s *WebServer) routeSetDeviceExpert(c fiber.Ctx) error { deviceID := c.Params("uuid") uid := c.Params("uid") type body struct { Name string `json:"name"` } b := &body{} if err := c.Bind().JSON(b); err != nil { return err } var device model.Device err := table.Device.SELECT(table.Device.AllColumns).WHERE(table.Device.UUID.EQ(String(deviceID))).QueryContext(c.UserContext(), s.db, &device) if err != nil { return err } var expert model.Expert err = table.Expert.SELECT(table.Expert.UID).WHERE(table.Expert.UID.EQ(String(uid))).QueryContext(c.UserContext(), s.db, &expert) if err != nil { return err } device.Expert = expert.UID _, err = table.Device.UPDATE().SET( table.Device.Expert.SET(String(device.Expert)), table.Device.Name.SET(String(b.Name)), ).WHERE(table.Device.UUID.EQ(String(deviceID))).ExecContext(c.UserContext(), s.db) if err != nil { return err } return c.JSON(nil) } func (s *WebServer) routePatchDeviceState(c fiber.Ctx) error { var state struct { State string `json:"state"` Note string `json:"note"` } if err := c.Bind().JSON(&state); err != nil { return err } uuid := c.Params("uuid") tbl := table.Device _, err := tbl. UPDATE(). SET( tbl.State.SET(String(state.State)), tbl.Note.SET(String(state.Note)), ). WHERE(tbl.UUID.EQ(String(uuid))). ExecContext(c.UserContext(), s.db) return err }