You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

102 lines
2.6 KiB

  1. package service
  2. import (
  3. "context"
  4. "net/http"
  5. "sort"
  6. "strings"
  7. "github.com/QuantumNous/new-api/constant"
  8. "github.com/QuantumNous/new-api/model"
  9. )
  10. const (
  11. AssetErrorInvalidRequest = "invalid_request_error"
  12. AssetErrorChannelNotFound = "asset_channel_not_found"
  13. AssetErrorBindingInvalid = "asset_channel_binding_invalid"
  14. AssetErrorOperationNotSupported = "asset_operation_not_supported"
  15. AssetErrorNotFound = "asset_not_found"
  16. AssetErrorUpstream = "upstream_error"
  17. AssetErrorServer = "server_error"
  18. )
  19. type AssetError struct {
  20. Type string
  21. Message string
  22. HTTPStatus int
  23. }
  24. func newAssetError(errType string, message string, status int) *AssetError {
  25. if status == 0 {
  26. status = http.StatusBadGateway
  27. }
  28. return &AssetError{Type: errType, Message: message, HTTPStatus: status}
  29. }
  30. type AssetRequest struct {
  31. Action AssetActionSpec
  32. Version string
  33. Body map[string]any
  34. RawBody []byte
  35. }
  36. type AssetUpstreamResponse struct {
  37. StatusCode int
  38. Header http.Header
  39. Body []byte
  40. }
  41. type AssetAdapter interface {
  42. Name() string
  43. Supports(operation AssetOperation) bool
  44. DoAssetRequest(ctx context.Context, channel *model.Channel, req AssetRequest) (*AssetUpstreamResponse, *AssetError)
  45. }
  46. var assetAdapters = map[int]AssetAdapter{}
  47. func init() {
  48. registerDefaultAssetAdapters()
  49. }
  50. func registerDefaultAssetAdapters() {
  51. assetAdapters[constant.ChannelTypeChinaMobileSeedance] = NewChinaMobileAssetAdapter()
  52. assetAdapters[constant.ChannelTypeDoubaoVideoCompatibleAiping] = NewCompatibleAssetAdapter("aiping_asset", []AssetOperation{
  53. AssetOperationAssetCreate,
  54. AssetOperationAssetList,
  55. AssetOperationAssetGet,
  56. AssetOperationAssetUpdate,
  57. AssetOperationAssetDelete,
  58. })
  59. assetAdapters[constant.ChannelTypeDoubaoVideoCompatibleTianyiYun] = NewTianyiYunAssetAdapter()
  60. }
  61. func GetAssetAdapter(channelType int) (AssetAdapter, bool) {
  62. adapter, ok := assetAdapters[channelType]
  63. return adapter, ok
  64. }
  65. func OverrideAssetAdapterForTest(channelType int, adapter AssetAdapter) func() {
  66. oldAdapter, hadOldAdapter := assetAdapters[channelType]
  67. assetAdapters[channelType] = adapter
  68. return func() {
  69. if hadOldAdapter {
  70. assetAdapters[channelType] = oldAdapter
  71. } else {
  72. delete(assetAdapters, channelType)
  73. }
  74. }
  75. }
  76. func RegisteredAssetChannelTypes() []int {
  77. types := make([]int, 0, len(assetAdapters))
  78. for channelType := range assetAdapters {
  79. types = append(types, channelType)
  80. }
  81. sort.Ints(types)
  82. return types
  83. }
  84. func assetChannelHasKey(channel *model.Channel) bool {
  85. return channel != nil && strings.TrimSpace(channel.Key) != "" && len(channel.GetKeys()) > 0
  86. }