A clean, Markdown-based publishing platform made for writers. Write together, and build a community. https://writefreely.org
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.
 
 
 
 
 

107 lines
2.9 KiB

  1. /*
  2. * Copyright © 2019-2020 A Bunch Tell LLC.
  3. *
  4. * This file is part of WriteFreely.
  5. *
  6. * WriteFreely is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Affero General Public License, included
  8. * in the LICENSE file in this source code package.
  9. */
  10. package writefreely
  11. import (
  12. "io/ioutil"
  13. "net/http"
  14. "strings"
  15. "sync"
  16. "time"
  17. )
  18. // updatesCacheTime is the default interval between cache updates for new
  19. // software versions
  20. const defaultUpdatesCacheTime = 12 * time.Hour
  21. // updatesCache holds data about current and new releases of the writefreely
  22. // software
  23. type updatesCache struct {
  24. mu sync.Mutex
  25. frequency time.Duration
  26. lastCheck time.Time
  27. latestVersion string
  28. currentVersion string
  29. }
  30. // CheckNow asks for the latest released version of writefreely and updates
  31. // the cache last checked time. If the version postdates the current 'latest'
  32. // the version value is replaced.
  33. func (uc *updatesCache) CheckNow() error {
  34. uc.mu.Lock()
  35. defer uc.mu.Unlock()
  36. latestRemote, err := newVersionCheck()
  37. if err != nil {
  38. return err
  39. }
  40. uc.lastCheck = time.Now()
  41. if CompareSemver(latestRemote, uc.latestVersion) == 1 {
  42. uc.latestVersion = latestRemote
  43. }
  44. return nil
  45. }
  46. // AreAvailable updates the cache if the frequency duration has passed
  47. // then returns if the latest release is newer than the current running version.
  48. func (uc updatesCache) AreAvailable() bool {
  49. if time.Since(uc.lastCheck) > uc.frequency {
  50. uc.CheckNow()
  51. }
  52. return CompareSemver(uc.latestVersion, uc.currentVersion) == 1
  53. }
  54. // LatestVersion returns the latest stored version available.
  55. func (uc updatesCache) LatestVersion() string {
  56. return uc.latestVersion
  57. }
  58. // ReleaseNotesURL returns the full URL to the blog.writefreely.org release notes
  59. // for the latest version as stored in the cache.
  60. func (uc updatesCache) ReleaseNotesURL() string {
  61. ver := strings.TrimPrefix(uc.latestVersion, "v")
  62. ver = strings.TrimSuffix(ver, ".0")
  63. // hack until go 1.12 in build/travis
  64. seg := strings.Split(ver, ".")
  65. return "https://blog.writefreely.org/version-" + strings.Join(seg, "-")
  66. }
  67. // newUpdatesCache returns an initialized updates cache
  68. func newUpdatesCache(expiry time.Duration) *updatesCache {
  69. cache := updatesCache{
  70. frequency: expiry,
  71. currentVersion: "v" + softwareVer,
  72. }
  73. cache.CheckNow()
  74. return &cache
  75. }
  76. // InitUpdates initializes the updates cache, if the config value is set
  77. // It uses the defaultUpdatesCacheTime for the cache expiry
  78. func (app *App) InitUpdates() {
  79. if app.cfg.App.UpdateChecks {
  80. app.updates = newUpdatesCache(defaultUpdatesCacheTime)
  81. }
  82. }
  83. func newVersionCheck() (string, error) {
  84. res, err := http.Get("https://version.writefreely.org")
  85. if err == nil && res.StatusCode == http.StatusOK {
  86. defer res.Body.Close()
  87. body, err := ioutil.ReadAll(res.Body)
  88. if err != nil {
  89. return "", err
  90. }
  91. return string(body), nil
  92. }
  93. return "", err
  94. }