github.com/e154/smart-home@v0.17.2-0.20240311175135-e530a6e5cd45/plugins/updater/actor.go (about) 1 // This file is part of the Smart Home 2 // Program complex distribution https://github.com/e154/smart-home 3 // Copyright (C) 2016-2023, Filippov Alex 4 // 5 // This library is free software: you can redistribute it and/or 6 // modify it under the terms of the GNU Lesser General Public 7 // License as published by the Free Software Foundation; either 8 // version 3 of the License, or (at your option) any later version. 9 // 10 // This library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 // Library General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public 16 // License along with this library. If not, see 17 // <https://www.gnu.org/licenses/>. 18 19 package updater 20 21 import ( 22 "encoding/json" 23 "github.com/e154/smart-home/common" 24 "sync" 25 "time" 26 27 m "github.com/e154/smart-home/models" 28 29 "github.com/Masterminds/semver" 30 "github.com/e154/smart-home/common/web" 31 "github.com/e154/smart-home/system/supervisor" 32 "github.com/e154/smart-home/version" 33 ) 34 35 // Actor ... 36 type Actor struct { 37 *supervisor.BaseActor 38 checkLock *sync.Mutex 39 latestVersion string 40 latestDownloadUrl string 41 latestVersionTime time.Time 42 lastCheck time.Time 43 currentVersion *semver.Version 44 } 45 46 // NewActor ... 47 func NewActor(entity *m.Entity, service supervisor.Service) *Actor { 48 49 var v = "v0.0.1" 50 if version.VersionString != "?" { 51 v = version.VersionString 52 } 53 currentVersion, err := semver.NewVersion(v) 54 if err != nil { 55 log.Error(err.Error()) 56 } 57 58 actor := &Actor{ 59 BaseActor: supervisor.NewBaseActor(entity, service), 60 checkLock: &sync.Mutex{}, 61 currentVersion: currentVersion, 62 } 63 64 if actor.Actions == nil { 65 actor.Actions = NewActions() 66 } 67 68 if actor.States == nil { 69 actor.States = NewStates() 70 } 71 72 return actor 73 } 74 75 func (e *Actor) Destroy() { 76 77 } 78 79 func (e *Actor) Spawn() { 80 e.check() 81 82 } 83 84 func (e *Actor) setState(v string) { 85 86 switch v { 87 case "exist_update": 88 e.SetActorState(common.String("exist_update")) 89 e.Value.Store(supervisor.StateOk) 90 return 91 case supervisor.StateError: 92 e.SetActorState(common.String("error")) 93 } 94 95 e.Value.Store(v) 96 } 97 98 func (e *Actor) check() { 99 100 e.checkLock.Lock() 101 var err error 102 defer func() { 103 if err != nil { 104 e.setState(supervisor.StateError) 105 return 106 } 107 e.checkLock.Unlock() 108 }() 109 110 var body []byte 111 if _, body, err = e.Service.Crawler().Probe(web.Request{Method: "GET", Url: uri, Timeout: 5 * time.Second}); err != nil { 112 return 113 } 114 115 data := GithubReleaseLatest{} 116 if err = json.Unmarshal(body, &data); err != nil { 117 return 118 } 119 120 e.lastCheck = time.Now() 121 e.latestVersion = data.TagName 122 e.latestVersionTime = data.CreatedAt.UTC() 123 for _, asset := range data.Assets { 124 e.latestDownloadUrl = asset.BrowserDownloadUrl 125 } 126 127 var releaseVersion *semver.Version 128 if releaseVersion, err = semver.NewVersion(e.latestVersion); err == nil { 129 // found update 130 if e.currentVersion != nil { 131 if compare := e.currentVersion.Compare(releaseVersion); compare < 0 { 132 e.setState("exist_update") 133 } 134 } 135 } 136 137 e.AttrMu.Lock() 138 e.Attrs[AttrUpdaterLatestVersion].Value = e.latestVersion 139 e.Attrs[AttrUpdaterLatestVersionTime].Value = e.latestVersionTime 140 e.Attrs[AttrUpdaterLatestLatestDownloadUrl].Value = e.latestDownloadUrl 141 e.Attrs[AttrUpdaterLatestCheck].Value = e.lastCheck 142 e.AttrMu.Unlock() 143 144 e.SaveState(false, true) 145 }