updateCheck.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. package updatecheck
  2. import (
  3. "encoding/json"
  4. config "github.com/OliveTin/OliveTin/internal/config"
  5. "github.com/OliveTin/OliveTin/internal/installationinfo"
  6. "github.com/robfig/cron/v3"
  7. log "github.com/sirupsen/logrus"
  8. "io"
  9. "net/http"
  10. "os"
  11. )
  12. type versionMapType struct {
  13. ApiVersion int
  14. Latest string
  15. History map[string]string
  16. }
  17. // StartUpdateChecker will start a job that runs periodically, checking
  18. // for updates.
  19. func StartUpdateChecker(cfg *config.Config) {
  20. if !cfg.CheckForUpdates {
  21. installationinfo.Runtime.AvailableVersion = "none"
  22. log.Infof("Update checking is disabled")
  23. return
  24. }
  25. s := cron.New()
  26. // Several values have been tried here.
  27. // 1st: Every 24h - very spammy.
  28. // 2nd: Every 7d - (168 hours - much more reasonable, but it checks in at the same time/day each week.
  29. // Current: Every 100h is not so spammy, and has the advantage that the checkin time "shifts" hours.
  30. s.AddFunc("@every 100h", func() {
  31. actualCheckForUpdate()
  32. })
  33. go actualCheckForUpdate() // On startup
  34. go s.Start()
  35. }
  36. func parseVersion(input []byte) string {
  37. versionMap := &versionMapType{}
  38. err := json.Unmarshal(input, &versionMap)
  39. if err != nil {
  40. log.Errorf("Update check unmarshal failure: %v", err)
  41. return "none"
  42. } else {
  43. log.Infof("Update check remote version: %+v, latest version: %+v", versionMap.Latest, installationinfo.Build.Version)
  44. if installationinfo.Build.Version == versionMap.Latest {
  45. return "none"
  46. } else {
  47. return versionMap.Latest
  48. }
  49. }
  50. }
  51. func doRequest() string {
  52. req, err := http.NewRequest("GET", "http://update-check.olivetin.app/versions.json", nil)
  53. if err != nil {
  54. log.Errorf("Update check failed %v", err)
  55. return "none"
  56. }
  57. resp, err := http.DefaultClient.Do(req)
  58. if err != nil {
  59. log.Errorf("Update check failed %v", err)
  60. return "none"
  61. }
  62. versionMap, _ := io.ReadAll(resp.Body)
  63. defer resp.Body.Close()
  64. return parseVersion(versionMap)
  65. }
  66. func actualCheckForUpdate() {
  67. if installationinfo.Build.Version == "dev" && os.Getenv("OLIVETIN_FORCE_UPDATE_CHECK") == "" {
  68. installationinfo.Runtime.AvailableVersion = "you-are-using-a-dev-build"
  69. } else {
  70. installationinfo.Runtime.AvailableVersion = doRequest()
  71. }
  72. log.WithFields(log.Fields{
  73. "CurrentVersion": installationinfo.Build.Version,
  74. "NewVersion": installationinfo.Runtime.AvailableVersion,
  75. }).Infof("Update check complete")
  76. }