Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 

80 linhas
3.0 KiB

  1. package service
  2. import (
  3. "errors"
  4. "fmt"
  5. "net/http"
  6. "github.com/QuantumNous/new-api/common"
  7. "github.com/QuantumNous/new-api/model"
  8. "gorm.io/gorm"
  9. )
  10. func ResolveAssetChannelForOperation(userID int, tokenGroup string, operation AssetOperation) (*model.Channel, AssetAdapter, *AssetError) {
  11. bindings, err := model.GetUserAssetChannelsByTypes(userID, RegisteredAssetChannelTypes(), tokenGroup)
  12. if err != nil {
  13. return nil, nil, newAssetError(AssetErrorServer, err.Error(), http.StatusInternalServerError)
  14. }
  15. if len(bindings) > 0 {
  16. binding := bindings[0]
  17. channel, err := model.CacheGetChannel(binding.ChannelId)
  18. if err != nil {
  19. if errors.Is(err, gorm.ErrRecordNotFound) || common.MemoryCacheEnabled {
  20. return nil, nil, newAssetError(AssetErrorBindingInvalid, "bound asset channel not found", http.StatusBadGateway)
  21. }
  22. return nil, nil, newAssetError(AssetErrorServer, err.Error(), http.StatusInternalServerError)
  23. }
  24. adapter, ok := GetAssetAdapter(channel.Type)
  25. if channel.Status != common.ChannelStatusEnabled || !assetChannelHasKey(channel) || !MatchDoubaoAssetGroup(channel.GetGroups(), tokenGroup) || !ok {
  26. return nil, nil, newAssetError(AssetErrorBindingInvalid, "bound asset channel is not available for asset library", http.StatusBadGateway)
  27. }
  28. if !adapter.Supports(operation) {
  29. return nil, nil, newAssetError(AssetErrorOperationNotSupported, fmt.Sprintf("asset operation %s is not supported by bound channel", operation), http.StatusBadRequest)
  30. }
  31. return channel, adapter, nil
  32. }
  33. channel, adapter, err := autoMatchAssetChannelForOperation(tokenGroup, operation)
  34. if err != nil {
  35. return nil, nil, newAssetError(AssetErrorServer, err.Error(), http.StatusInternalServerError)
  36. }
  37. if channel == nil {
  38. return nil, nil, newAssetError(AssetErrorChannelNotFound, "no available asset channel supports requested operation", http.StatusBadGateway)
  39. }
  40. return channel, adapter, nil
  41. }
  42. func autoMatchAssetChannelForOperation(tokenGroup string, operation AssetOperation) (*model.Channel, AssetAdapter, error) {
  43. for _, channelType := range RegisteredAssetChannelTypes() {
  44. adapter, ok := GetAssetAdapter(channelType)
  45. if !ok || !adapter.Supports(operation) {
  46. continue
  47. }
  48. for startIdx := 0; ; startIdx += DoubaoAssetChannelPageSize {
  49. candidates, err := model.GetChannelsByType(startIdx, DoubaoAssetChannelPageSize, true, channelType)
  50. if err != nil {
  51. return nil, nil, err
  52. }
  53. for _, candidate := range candidates {
  54. if candidate == nil || !MatchDoubaoAssetGroup(candidate.GetGroups(), tokenGroup) {
  55. continue
  56. }
  57. channel, err := model.CacheGetChannel(candidate.Id)
  58. if err != nil {
  59. if errors.Is(err, gorm.ErrRecordNotFound) || common.MemoryCacheEnabled {
  60. continue
  61. }
  62. return nil, nil, err
  63. }
  64. if channel.Status == common.ChannelStatusEnabled && assetChannelHasKey(channel) && MatchDoubaoAssetGroup(channel.GetGroups(), tokenGroup) {
  65. return channel, adapter, nil
  66. }
  67. }
  68. if len(candidates) < DoubaoAssetChannelPageSize {
  69. break
  70. }
  71. }
  72. }
  73. return nil, nil, nil
  74. }