263 lines
6.0 KiB
Go
263 lines
6.0 KiB
Go
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
|
|
}
|