subdocupdater.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  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. downloadedDocument, err := docFetcher.DownloadDocument(s.ctx, importSource)
  25. if err != nil {
  26. return newError("failed to download document: ", err)
  27. }
  28. trackedSub.originalDocument = downloadedDocument
  29. container, err := containers.TryAllParsers(trackedSub.originalDocument, "")
  30. if err != nil {
  31. return newError("failed to parse document: ", err)
  32. }
  33. trackedSub.originalContainer = container
  34. parsedDocument := &specs.SubscriptionDocument{}
  35. parsedDocument.Metadata = container.Metadata
  36. trackedSub.originalServerConfig = make(map[string]*originalServerConfig)
  37. for _, server := range trackedSub.originalContainer.ServerSpecs {
  38. documentHash := sha3.Sum256(server.Content)
  39. serverConfigHashName := fmt.Sprintf("%x", documentHash)
  40. parsed, err := s.converter.TryAllConverters(server.Content, "outbound", server.KindHint)
  41. if err != nil {
  42. trackedSub.originalServerConfig["!!!"+serverConfigHashName] = &originalServerConfig{data: server.Content}
  43. continue
  44. }
  45. s.polyfillServerConfig(parsed, serverConfigHashName)
  46. parsedDocument.Server = append(parsedDocument.Server, parsed)
  47. trackedSub.originalServerConfig[parsed.Id] = &originalServerConfig{data: server.Content}
  48. }
  49. newError("new subscription document fetched and parsed from ", subscriptionName).AtInfo().WriteToLog()
  50. if err := s.applySubscriptionTo(subscriptionName, parsedDocument); err != nil {
  51. return newError("failed to apply subscription: ", err)
  52. }
  53. trackedSub.currentDocument = parsedDocument
  54. trackedSub.currentDocumentExpireTime = time.Now().Add(time.Second * time.Duration(importSource.DefaultExpireSeconds))
  55. return nil
  56. }
  57. func (s *SubscriptionManagerImpl) polyfillServerConfig(document *specs.SubscriptionServerConfig, hash string) {
  58. document.Id = hash
  59. if document.Metadata == nil {
  60. document.Metadata = make(map[string]string)
  61. }
  62. if id, ok := document.Metadata[ServerMetadataID]; !ok || id == "" {
  63. document.Metadata[ServerMetadataID] = document.Id
  64. } else {
  65. document.Id = document.Metadata[ServerMetadataID]
  66. }
  67. if fqn, ok := document.Metadata[ServerMetadataFullyQualifiedName]; !ok || fqn == "" {
  68. document.Metadata[ServerMetadataFullyQualifiedName] = hash
  69. }
  70. if tagName, ok := document.Metadata[ServerMetadataTagName]; !ok || tagName == "" {
  71. document.Metadata[ServerMetadataTagName] = document.Metadata[ServerMetadataID]
  72. }
  73. document.Metadata[ServerMetadataTagName] = s.restrictTagName(document.Metadata[ServerMetadataTagName])
  74. }
  75. func (s *SubscriptionManagerImpl) restrictTagName(tagName string) string {
  76. newTagName := &strings.Builder{}
  77. somethingRemoved := false
  78. for _, c := range tagName {
  79. if (unicode.IsLetter(c) || unicode.IsNumber(c)) && c < 128 {
  80. newTagName.WriteRune(c)
  81. } else {
  82. somethingRemoved = true
  83. }
  84. }
  85. newTagNameString := newTagName.String()
  86. if len(newTagNameString) > 24 {
  87. newTagNameString = newTagNameString[:15]
  88. somethingRemoved = true
  89. }
  90. if somethingRemoved {
  91. hashedTagName := sha3.Sum256([]byte(tagName))
  92. hashedTagNameString := fmt.Sprintf("%x", hashedTagName)
  93. newTagNameString = newTagNameString + "_" + hashedTagNameString[:8]
  94. }
  95. return newTagNameString
  96. }