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  }