subdocupdater.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. package subscriptionmanager
  2. import (
  3. "fmt"
  4. "strings"
  5. "time"
  6. "unicode"
  7. "golang.org/x/crypto/sha3"
  8. "github.com/v2fly/v2ray-core/v5/app/subscription/containers"
  9. "github.com/v2fly/v2ray-core/v5/app/subscription/documentfetcher"
  10. "github.com/v2fly/v2ray-core/v5/app/subscription/specs"
  11. )
  12. func (s *SubscriptionManagerImpl) updateSubscription(subscriptionName string) error {
  13. var trackedSub *trackedSubscription
  14. if trackedSubFound, found := s.trackedSubscriptions[subscriptionName]; !found {
  15. return newError("not found")
  16. } else {
  17. trackedSub = trackedSubFound
  18. }
  19. importSource := trackedSub.importSource
  20. docFetcher, err := documentfetcher.GetFetcher("http")
  21. if err != nil {
  22. return newError("failed to get fetcher: ", err)
  23. }
  24. if strings.HasPrefix(importSource.Url, "data:") {
  25. docFetcher, err = documentfetcher.GetFetcher("dataurl")
  26. if err != nil {
  27. return newError("failed to get fetcher: ", err)
  28. }
  29. }
  30. downloadedDocument, err := docFetcher.DownloadDocument(s.ctx, importSource)
  31. if err != nil {
  32. return newError("failed to download document: ", err)
  33. }
  34. trackedSub.originalDocument = downloadedDocument
  35. container, err := containers.TryAllParsers(trackedSub.originalDocument, "")
  36. if err != nil {
  37. return newError("failed to parse document: ", err)
  38. }
  39. trackedSub.originalContainer = container
  40. parsedDocument := &specs.SubscriptionDocument{}
  41. parsedDocument.Metadata = container.Metadata
  42. trackedSub.originalServerConfig = make(map[string]*originalServerConfig)
  43. for _, server := range trackedSub.originalContainer.ServerSpecs {
  44. documentHash := sha3.Sum256(server.Content)
  45. serverConfigHashName := fmt.Sprintf("%x", documentHash)
  46. parsed, err := s.converter.TryAllConverters(server.Content, "outbound", server.KindHint)
  47. if err != nil {
  48. trackedSub.originalServerConfig["!!!"+serverConfigHashName] = &originalServerConfig{data: server.Content}
  49. continue
  50. }
  51. s.polyfillServerConfig(parsed, serverConfigHashName)
  52. parsedDocument.Server = append(parsedDocument.Server, parsed)
  53. trackedSub.originalServerConfig[parsed.Id] = &originalServerConfig{data: server.Content}
  54. }
  55. newError("new subscription document fetched and parsed from ", subscriptionName).AtInfo().WriteToLog()
  56. if err := s.applySubscriptionTo(subscriptionName, parsedDocument); err != nil {
  57. return newError("failed to apply subscription: ", err)
  58. }
  59. trackedSub.currentDocument = parsedDocument
  60. trackedSub.currentDocumentExpireTime = time.Now().Add(time.Second * time.Duration(importSource.DefaultExpireSeconds))
  61. return nil
  62. }
  63. func (s *SubscriptionManagerImpl) polyfillServerConfig(document *specs.SubscriptionServerConfig, hash string) {
  64. document.Id = hash
  65. if document.Metadata == nil {
  66. document.Metadata = make(map[string]string)
  67. }
  68. if id, ok := document.Metadata[ServerMetadataID]; !ok || id == "" {
  69. document.Metadata[ServerMetadataID] = document.Id
  70. } else {
  71. document.Id = document.Metadata[ServerMetadataID]
  72. }
  73. if fqn, ok := document.Metadata[ServerMetadataFullyQualifiedName]; !ok || fqn == "" {
  74. document.Metadata[ServerMetadataFullyQualifiedName] = hash
  75. }
  76. if tagName, ok := document.Metadata[ServerMetadataTagName]; !ok || tagName == "" {
  77. document.Metadata[ServerMetadataTagName] = document.Metadata[ServerMetadataID]
  78. }
  79. document.Metadata[ServerMetadataTagName] = s.restrictTagName(document.Metadata[ServerMetadataTagName])
  80. }
  81. func (s *SubscriptionManagerImpl) restrictTagName(tagName string) string {
  82. newTagName := &strings.Builder{}
  83. somethingRemoved := false
  84. for _, c := range tagName {
  85. if (unicode.IsLetter(c) || unicode.IsNumber(c)) && c < 128 {
  86. newTagName.WriteRune(c)
  87. } else {
  88. somethingRemoved = true
  89. }
  90. }
  91. newTagNameString := newTagName.String()
  92. if len(newTagNameString) > 24 {
  93. newTagNameString = newTagNameString[:15]
  94. somethingRemoved = true
  95. }
  96. if somethingRemoved {
  97. hashedTagName := sha3.Sum256([]byte(tagName))
  98. hashedTagNameString := fmt.Sprintf("%x", hashedTagName)
  99. newTagNameString = newTagNameString + "_" + hashedTagNameString[:8]
  100. }
  101. return newTagNameString
  102. }