feeds.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. package traffic
  2. import (
  3. "apiote.xyz/p/szczanieckiej/config"
  4. "apiote.xyz/p/szczanieckiej/file"
  5. "fmt"
  6. "net/http"
  7. "os"
  8. "path/filepath"
  9. "strings"
  10. "time"
  11. "golang.org/x/text/language"
  12. "golang.org/x/text/transform"
  13. "git.sr.ht/~sircmpwn/go-bare"
  14. )
  15. func LastUpdate(feedsPath, feedID string) (time.Time, error) {
  16. updatesFilename := filepath.Join(feedsPath, "updated.bare")
  17. updatesFile, err := os.Open(updatesFilename)
  18. if err != nil {
  19. return time.Time{}, fmt.Errorf("while opening updates file: %w", err)
  20. }
  21. defer updatesFile.Close()
  22. var lastUpdated map[string]string
  23. err = bare.UnmarshalReader(updatesFile, &lastUpdated)
  24. if err != nil {
  25. return time.Time{}, fmt.Errorf("while unmarshaling updates file: %w", err)
  26. }
  27. t, err := time.Parse(time.RFC3339, lastUpdated[feedID])
  28. if err != nil {
  29. return time.Time{}, fmt.Errorf("while parsing update time: %w", err)
  30. }
  31. return t, nil
  32. }
  33. type Feed interface {
  34. fmt.Stringer
  35. ConvertVehicles(string) error
  36. GetVersions(time.Time) ([]Version, error)
  37. GetLocation() *time.Location
  38. RealtimeFeeds() []string
  39. Transformer() transform.Transformer
  40. Name() string
  41. Attribution() map[language.Tag]string // SHOULD have und tag
  42. Description() map[language.Tag]string // SHOULD have und tag
  43. Flags() FeedFlags
  44. FeedPrepareZip(string) error
  45. }
  46. type HeadsignSource uint
  47. const (
  48. HeadsignTripHeadsing HeadsignSource = iota
  49. HeadsignTripLastStop
  50. )
  51. type FeedFlags struct {
  52. Headsign HeadsignSource
  53. StopIdFormat string
  54. StopName string
  55. LineName string
  56. }
  57. func FeedPath(cfg config.Config, feed Feed) string {
  58. return filepath.Join(cfg.FeedsPath, feed.String())
  59. }
  60. func RegisterFeeds() map[string]Feed {
  61. return map[string]Feed{
  62. "poznan_ztm": ZtmPoznan{
  63. client: http.Client{
  64. Timeout: 30 * time.Second,
  65. },
  66. },
  67. "krakow_ztp": ZtpKrakow{},
  68. "gzm_ztm": GzmZtm{},
  69. }
  70. }
  71. func MakeVersion(s string, location *time.Location) (Version, error) {
  72. version := Version{}
  73. versionDates := strings.Split(s, "_")
  74. if len(versionDates) != 2 {
  75. return version, fmt.Errorf("invalid version string %s, not /.*_.*/", s)
  76. }
  77. validFrom, err := time.ParseInLocation("20060102", versionDates[0], location)
  78. if err != nil {
  79. return version, fmt.Errorf("invalid first part in %s: %w", s, err)
  80. }
  81. validTill, err := time.ParseInLocation("20060102", versionDates[1], location)
  82. if err != nil {
  83. return version, fmt.Errorf("invalid second part in %s: %w", s, err)
  84. }
  85. version.ValidFrom = validFrom
  86. version.ValidTill = validTill
  87. return version, nil
  88. }
  89. func ListVersions(cfg config.Config, f Feed) ([]Version, error) {
  90. versions := []Version{}
  91. versionNames, err := file.ListVersions(FeedPath(cfg, f), f.GetLocation())
  92. if err != nil {
  93. return versions, err
  94. }
  95. for _, name := range versionNames {
  96. version, err := MakeVersion(name, f.GetLocation())
  97. if err != nil {
  98. return versions, err
  99. }
  100. versions = append(versions, version)
  101. }
  102. return versions, err
  103. }
  104. func FindValidVersions(versions []Version, now time.Time) []Version {
  105. i := 0
  106. for _, version := range versions {
  107. if version.ValidFrom.Before(now) {
  108. i++
  109. } else {
  110. break
  111. }
  112. }
  113. if i > 0 {
  114. i = i - 1
  115. }
  116. validVersions := versions[i:]
  117. return validVersions
  118. }