選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 

172 行
5.0 KiB

  1. package service
  2. import (
  3. "errors"
  4. "strings"
  5. "github.com/QuantumNous/new-api/common"
  6. "github.com/QuantumNous/new-api/constant"
  7. "github.com/QuantumNous/new-api/model"
  8. "gorm.io/gorm"
  9. )
  10. type VideoAssetFamily string
  11. const (
  12. VideoAssetFamilySeedance VideoAssetFamily = "seedance"
  13. VideoAssetFamilyKling VideoAssetFamily = "kling"
  14. )
  15. func VideoAssetChannelTypesForFamily(family VideoAssetFamily) []int {
  16. switch family {
  17. case VideoAssetFamilySeedance:
  18. return []int{
  19. constant.ChannelTypeDoubaoVideoCompatibleAiping,
  20. constant.ChannelTypeDoubaoVideoCompatibleTianyiYun,
  21. }
  22. case VideoAssetFamilyKling:
  23. return []int{
  24. constant.ChannelTypeKlingAiping,
  25. }
  26. default:
  27. return nil
  28. }
  29. }
  30. func VideoAssetFamilyForChannelType(channelType int) (VideoAssetFamily, bool) {
  31. for _, family := range []VideoAssetFamily{VideoAssetFamilySeedance, VideoAssetFamilyKling} {
  32. if channelTypeAllowed(channelType, VideoAssetChannelTypesForFamily(family)) {
  33. return family, true
  34. }
  35. }
  36. return "", false
  37. }
  38. func GetBoundVideoAssetChannelForModel(userId int, tokenGroup string, modelName string, family VideoAssetFamily) (*model.Channel, error) {
  39. bindings, err := model.GetUserAssetChannelsByTypes(userId, VideoAssetChannelTypesForFamily(family), tokenGroup)
  40. if err != nil {
  41. return nil, err
  42. }
  43. for _, binding := range bindings {
  44. channel, err := model.CacheGetChannel(binding.ChannelId)
  45. if err != nil {
  46. if errors.Is(err, gorm.ErrRecordNotFound) || common.MemoryCacheEnabled {
  47. continue
  48. }
  49. return nil, err
  50. }
  51. if IsUsableVideoAssetChannelForFamily(channel, tokenGroup, modelName, family) {
  52. return channel, nil
  53. }
  54. }
  55. return nil, nil
  56. }
  57. func ResolveVideoAssetChannelForModel(userId int, tokenGroup string, modelName string, family VideoAssetFamily) (*model.Channel, error) {
  58. channel, err := GetBoundVideoAssetChannelForModel(userId, tokenGroup, modelName, family)
  59. if err != nil {
  60. return nil, err
  61. }
  62. if channel != nil {
  63. return channel, nil
  64. }
  65. channel, err = autoMatchVideoAssetChannelForModel(tokenGroup, modelName, family)
  66. if err != nil {
  67. return nil, err
  68. }
  69. if channel == nil {
  70. return nil, nil
  71. }
  72. if err = BindVideoAssetChannel(userId, tokenGroup, channel, family); err != nil {
  73. return nil, err
  74. }
  75. return channel, nil
  76. }
  77. func BindVideoAssetChannel(userId int, tokenGroup string, channel *model.Channel, family VideoAssetFamily) error {
  78. if channel == nil {
  79. return nil
  80. }
  81. channelTypes := VideoAssetChannelTypesForFamily(family)
  82. if len(channelTypes) == 0 || !channelTypeAllowed(channel.Type, channelTypes) {
  83. return nil
  84. }
  85. otherTypes := make([]int, 0, len(channelTypes))
  86. for _, channelType := range channelTypes {
  87. if channelType != channel.Type {
  88. otherTypes = append(otherTypes, channelType)
  89. }
  90. }
  91. return model.DB.Transaction(func(tx *gorm.DB) error {
  92. if err := model.DeleteUserAssetChannelsByTypesWithTx(tx, userId, otherTypes, tokenGroup); err != nil {
  93. return err
  94. }
  95. return model.BindUserAssetChannelWithTx(tx, userId, channel.Type, tokenGroup, channel.Id)
  96. })
  97. }
  98. func HasVideoAssetChannelForGroupModel(tokenGroup string, modelName string, family VideoAssetFamily) bool {
  99. tokenGroup = strings.TrimSpace(tokenGroup)
  100. modelName = strings.TrimSpace(modelName)
  101. if tokenGroup == "" || modelName == "" {
  102. return false
  103. }
  104. channel, err := autoMatchVideoAssetChannelForModel(tokenGroup, modelName, family)
  105. return err == nil && channel != nil
  106. }
  107. func autoMatchVideoAssetChannelForModel(tokenGroup string, modelName string, family VideoAssetFamily) (*model.Channel, error) {
  108. for _, channelType := range VideoAssetChannelTypesForFamily(family) {
  109. for startIdx := 0; ; startIdx += DoubaoAssetChannelPageSize {
  110. candidates, err := model.GetChannelsByType(startIdx, DoubaoAssetChannelPageSize, true, channelType)
  111. if err != nil {
  112. return nil, err
  113. }
  114. for _, candidate := range candidates {
  115. if candidate == nil || !MatchDoubaoAssetGroup(candidate.GetGroups(), tokenGroup) {
  116. continue
  117. }
  118. channel, err := model.CacheGetChannel(candidate.Id)
  119. if err != nil {
  120. if errors.Is(err, gorm.ErrRecordNotFound) || common.MemoryCacheEnabled {
  121. continue
  122. }
  123. return nil, err
  124. }
  125. if IsUsableVideoAssetChannelForFamily(channel, tokenGroup, modelName, family) {
  126. return channel, nil
  127. }
  128. }
  129. if len(candidates) < DoubaoAssetChannelPageSize {
  130. break
  131. }
  132. }
  133. }
  134. return nil, nil
  135. }
  136. func IsUsableVideoAssetChannelForFamily(channel *model.Channel, tokenGroup string, modelName string, family VideoAssetFamily) bool {
  137. if channel == nil {
  138. return false
  139. }
  140. channelTypes := VideoAssetChannelTypesForFamily(family)
  141. if len(channelTypes) == 0 || !channelTypeAllowed(channel.Type, channelTypes) {
  142. return false
  143. }
  144. if channel.Status != common.ChannelStatusEnabled {
  145. return false
  146. }
  147. if strings.TrimSpace(channel.Key) == "" || len(channel.GetKeys()) == 0 {
  148. return false
  149. }
  150. if !MatchDoubaoAssetGroup(channel.GetGroups(), tokenGroup) {
  151. return false
  152. }
  153. modelName = strings.TrimSpace(modelName)
  154. if modelName == "" {
  155. return true
  156. }
  157. return model.IsChannelEnabledForGroupModel(tokenGroup, modelName, channel.Id)
  158. }