mirror of
https://github.com/idanoo/autobrr
synced 2025-07-23 00:39:13 +00:00
feat: return action rejections from arrs (#103)
* refactor: push status * feat: return push status for arr actions
This commit is contained in:
parent
20138030e1
commit
373c85f060
16 changed files with 294 additions and 255 deletions
|
@ -10,7 +10,7 @@ import (
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *service) lidarr(release domain.Release, action domain.Action) error {
|
func (s *service) lidarr(release domain.Release, action domain.Action) ([]string, error) {
|
||||||
log.Trace().Msg("action LIDARR")
|
log.Trace().Msg("action LIDARR")
|
||||||
|
|
||||||
// TODO validate data
|
// TODO validate data
|
||||||
|
@ -18,13 +18,13 @@ func (s *service) lidarr(release domain.Release, action domain.Action) error {
|
||||||
// get client for action
|
// get client for action
|
||||||
client, err := s.clientSvc.FindByID(context.TODO(), action.ClientID)
|
client, err := s.clientSvc.FindByID(context.TODO(), action.ClientID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msgf("error finding client: %v", action.ClientID)
|
log.Error().Err(err).Msgf("lidarr: error finding client: %v", action.ClientID)
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// return early if no client found
|
// return early if no client found
|
||||||
if client == nil {
|
if client == nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// initial config
|
// initial config
|
||||||
|
@ -52,23 +52,19 @@ func (s *service) lidarr(release domain.Release, action domain.Action) error {
|
||||||
PublishDate: time.Now().Format(time.RFC3339),
|
PublishDate: time.Now().Format(time.RFC3339),
|
||||||
}
|
}
|
||||||
|
|
||||||
success, rejections, err := arr.Push(r)
|
rejections, err := arr.Push(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Stack().Err(err).Msgf("lidarr: failed to push release: %v", r)
|
log.Error().Stack().Err(err).Msgf("lidarr: failed to push release: %v", r)
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !success {
|
if rejections != nil {
|
||||||
log.Debug().Msgf("lidarr: release push rejected: %v, indexer %v to %v reasons: '%v'", r.Title, r.Indexer, client.Host, rejections)
|
log.Debug().Msgf("lidarr: release push rejected: %v, indexer %v to %v reasons: '%v'", r.Title, r.Indexer, client.Host, rejections)
|
||||||
|
|
||||||
// save pushed release
|
return rejections, nil
|
||||||
s.bus.Publish("release:update-push-status-rejected", release.ID, rejections)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debug().Msgf("lidarr: successfully pushed release: %v, indexer %v to %v", r.Title, r.Indexer, client.Host)
|
log.Debug().Msgf("lidarr: successfully pushed release: %v, indexer %v to %v", r.Title, r.Indexer, client.Host)
|
||||||
|
|
||||||
s.bus.Publish("release:update-push-status", release.ID, domain.ReleasePushStatusApproved)
|
return nil, nil
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,8 +10,8 @@ import (
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
const REANNOUNCE_MAX_ATTEMPTS = 30
|
const ReannounceMaxAttempts = 30
|
||||||
const REANNOUNCE_INTERVAL = 7000
|
const ReannounceInterval = 7000
|
||||||
|
|
||||||
func (s *service) qbittorrent(qbt *qbittorrent.Client, action domain.Action, hash string, torrentFile string) error {
|
func (s *service) qbittorrent(qbt *qbittorrent.Client, action domain.Action, hash string, torrentFile string) error {
|
||||||
log.Debug().Msgf("action qBittorrent: %v", action.Name)
|
log.Debug().Msgf("action qBittorrent: %v", action.Name)
|
||||||
|
@ -134,7 +134,7 @@ func checkTrackerStatus(qb qbittorrent.Client, hash string) error {
|
||||||
// initial sleep to give tracker a head start
|
// initial sleep to give tracker a head start
|
||||||
time.Sleep(2 * time.Second)
|
time.Sleep(2 * time.Second)
|
||||||
|
|
||||||
for attempts < REANNOUNCE_MAX_ATTEMPTS {
|
for attempts < ReannounceMaxAttempts {
|
||||||
log.Debug().Msgf("qBittorrent - run re-announce %v attempt: %v", hash, attempts)
|
log.Debug().Msgf("qBittorrent - run re-announce %v attempt: %v", hash, attempts)
|
||||||
|
|
||||||
trackers, err := qb.GetTorrentTrackers(hash)
|
trackers, err := qb.GetTorrentTrackers(hash)
|
||||||
|
@ -157,7 +157,7 @@ func checkTrackerStatus(qb qbittorrent.Client, hash string) error {
|
||||||
attempts++
|
attempts++
|
||||||
|
|
||||||
// add delay for next run
|
// add delay for next run
|
||||||
time.Sleep(REANNOUNCE_INTERVAL * time.Millisecond)
|
time.Sleep(ReannounceInterval * time.Millisecond)
|
||||||
|
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *service) radarr(release domain.Release, action domain.Action) error {
|
func (s *service) radarr(release domain.Release, action domain.Action) ([]string, error) {
|
||||||
log.Trace().Msg("action RADARR")
|
log.Trace().Msg("action RADARR")
|
||||||
|
|
||||||
// TODO validate data
|
// TODO validate data
|
||||||
|
@ -18,13 +18,13 @@ func (s *service) radarr(release domain.Release, action domain.Action) error {
|
||||||
// get client for action
|
// get client for action
|
||||||
client, err := s.clientSvc.FindByID(context.TODO(), action.ClientID)
|
client, err := s.clientSvc.FindByID(context.TODO(), action.ClientID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msgf("error finding client: %v", action.ClientID)
|
log.Error().Err(err).Msgf("radarr: error finding client: %v", action.ClientID)
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// return early if no client found
|
// return early if no client found
|
||||||
if client == nil {
|
if client == nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// initial config
|
// initial config
|
||||||
|
@ -52,23 +52,19 @@ func (s *service) radarr(release domain.Release, action domain.Action) error {
|
||||||
PublishDate: time.Now().Format(time.RFC3339),
|
PublishDate: time.Now().Format(time.RFC3339),
|
||||||
}
|
}
|
||||||
|
|
||||||
success, rejections, err := arr.Push(r)
|
rejections, err := arr.Push(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Stack().Err(err).Msgf("radarr: failed to push release: %v", r)
|
log.Error().Stack().Err(err).Msgf("radarr: failed to push release: %v", r)
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !success {
|
if rejections != nil {
|
||||||
log.Debug().Msgf("radarr: release push rejected: %v, indexer %v to %v reasons: '%v'", r.Title, r.Indexer, client.Host, rejections)
|
log.Debug().Msgf("radarr: release push rejected: %v, indexer %v to %v reasons: '%v'", r.Title, r.Indexer, client.Host, rejections)
|
||||||
|
|
||||||
// save pushed release
|
return rejections, nil
|
||||||
s.bus.Publish("release:update-push-status-rejected", release.ID, rejections)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debug().Msgf("radarr: successfully pushed release: %v, indexer %v to %v", r.Title, r.Indexer, client.Host)
|
log.Debug().Msgf("radarr: successfully pushed release: %v, indexer %v to %v", r.Title, r.Indexer, client.Host)
|
||||||
|
|
||||||
s.bus.Publish("release:update-push-status", release.ID, domain.ReleasePushStatusApproved)
|
return nil, nil
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,169 +13,30 @@ import (
|
||||||
|
|
||||||
func (s *service) RunActions(actions []domain.Action, release domain.Release) error {
|
func (s *service) RunActions(actions []domain.Action, release domain.Release) error {
|
||||||
|
|
||||||
var err error
|
|
||||||
var tmpFile string
|
|
||||||
var hash string
|
|
||||||
|
|
||||||
for _, action := range actions {
|
for _, action := range actions {
|
||||||
|
// only run active actions
|
||||||
if !action.Enabled {
|
if !action.Enabled {
|
||||||
// only run active actions
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debug().Msgf("process action: %v for '%v'", action.Name, release.TorrentName)
|
log.Debug().Msgf("process action: %v for '%v'", action.Name, release.TorrentName)
|
||||||
|
|
||||||
actionStatus := domain.ReleaseActionStatus{
|
go func(release domain.Release, action domain.Action) {
|
||||||
ReleaseID: release.ID,
|
err := s.runAction(action, release)
|
||||||
Status: domain.ReleasePushStatusPending,
|
|
||||||
Action: action.Name,
|
|
||||||
Type: action.Type,
|
|
||||||
Rejections: []string{},
|
|
||||||
Timestamp: time.Now(),
|
|
||||||
}
|
|
||||||
|
|
||||||
s.bus.Publish("release:store-action-status", &actionStatus)
|
|
||||||
|
|
||||||
switch action.Type {
|
|
||||||
case domain.ActionTypeTest:
|
|
||||||
s.test(action.Name)
|
|
||||||
|
|
||||||
case domain.ActionTypeExec:
|
|
||||||
if release.TorrentTmpFile == "" {
|
|
||||||
t, err := release.DownloadTorrentFile(nil)
|
|
||||||
if err != nil {
|
|
||||||
log.Error().Stack().Err(err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpFile = t.TmpFileName
|
|
||||||
}
|
|
||||||
|
|
||||||
go func(release domain.Release, action domain.Action, tmpFile string) {
|
|
||||||
s.execCmd(release, action, tmpFile)
|
|
||||||
}(release, action, tmpFile)
|
|
||||||
|
|
||||||
case domain.ActionTypeWatchFolder:
|
|
||||||
if release.TorrentTmpFile == "" {
|
|
||||||
t, err := release.DownloadTorrentFile(nil)
|
|
||||||
if err != nil {
|
|
||||||
log.Error().Stack().Err(err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpFile = t.TmpFileName
|
|
||||||
}
|
|
||||||
s.watchFolder(action.WatchFolder, tmpFile)
|
|
||||||
|
|
||||||
case domain.ActionTypeDelugeV1, domain.ActionTypeDelugeV2:
|
|
||||||
canDownload, err := s.delugeCheckRulesCanDownload(action)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Stack().Err(err).Msgf("error checking client rules: %v", action.Name)
|
log.Err(err).Stack().Msgf("process action failed: %v for '%v'", action.Name, release.TorrentName)
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !canDownload {
|
|
||||||
s.bus.Publish("release:store-action-status", &domain.ReleaseActionStatus{
|
s.bus.Publish("release:store-action-status", &domain.ReleaseActionStatus{
|
||||||
ID: actionStatus.ID,
|
|
||||||
ReleaseID: release.ID,
|
ReleaseID: release.ID,
|
||||||
Status: domain.ReleasePushStatusRejected,
|
Status: domain.ReleasePushStatusErr,
|
||||||
Action: action.Name,
|
Action: action.Name,
|
||||||
Type: action.Type,
|
Type: action.Type,
|
||||||
Rejections: []string{"deluge busy"},
|
Rejections: []string{err.Error()},
|
||||||
|
Timestamp: time.Now(),
|
||||||
})
|
})
|
||||||
continue
|
return
|
||||||
}
|
}
|
||||||
if release.TorrentTmpFile == "" {
|
}(release, action)
|
||||||
t, err := release.DownloadTorrentFile(nil)
|
|
||||||
if err != nil {
|
|
||||||
log.Error().Stack().Err(err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpFile = t.TmpFileName
|
|
||||||
}
|
|
||||||
|
|
||||||
go func(action domain.Action, tmpFile string) {
|
|
||||||
err = s.deluge(action, tmpFile)
|
|
||||||
if err != nil {
|
|
||||||
log.Error().Stack().Err(err).Msg("error sending torrent to Deluge")
|
|
||||||
}
|
|
||||||
}(action, tmpFile)
|
|
||||||
|
|
||||||
case domain.ActionTypeQbittorrent:
|
|
||||||
canDownload, client, err := s.qbittorrentCheckRulesCanDownload(action)
|
|
||||||
if err != nil {
|
|
||||||
log.Error().Stack().Err(err).Msgf("error checking client rules: %v", action.Name)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !canDownload {
|
|
||||||
s.bus.Publish("release:store-action-status", &domain.ReleaseActionStatus{
|
|
||||||
ID: actionStatus.ID,
|
|
||||||
ReleaseID: release.ID,
|
|
||||||
Status: domain.ReleasePushStatusRejected,
|
|
||||||
Action: action.Name,
|
|
||||||
Type: action.Type,
|
|
||||||
Rejections: []string{"qbittorrent busy"},
|
|
||||||
})
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if release.TorrentTmpFile == "" {
|
|
||||||
t, err := release.DownloadTorrentFile(nil)
|
|
||||||
if err != nil {
|
|
||||||
log.Error().Stack().Err(err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpFile = t.TmpFileName
|
|
||||||
hash = t.MetaInfo.HashInfoBytes().String()
|
|
||||||
}
|
|
||||||
|
|
||||||
go func(action domain.Action, hash string, tmpFile string) {
|
|
||||||
err = s.qbittorrent(client, action, hash, tmpFile)
|
|
||||||
if err != nil {
|
|
||||||
log.Error().Stack().Err(err).Msg("error sending torrent to qBittorrent")
|
|
||||||
}
|
|
||||||
}(action, hash, tmpFile)
|
|
||||||
|
|
||||||
case domain.ActionTypeRadarr:
|
|
||||||
go func(release domain.Release, action domain.Action) {
|
|
||||||
err = s.radarr(release, action)
|
|
||||||
if err != nil {
|
|
||||||
log.Error().Stack().Err(err).Msg("error sending torrent to radarr")
|
|
||||||
//continue
|
|
||||||
}
|
|
||||||
}(release, action)
|
|
||||||
|
|
||||||
case domain.ActionTypeSonarr:
|
|
||||||
go func(release domain.Release, action domain.Action) {
|
|
||||||
err = s.sonarr(release, action)
|
|
||||||
if err != nil {
|
|
||||||
log.Error().Stack().Err(err).Msg("error sending torrent to sonarr")
|
|
||||||
//continue
|
|
||||||
}
|
|
||||||
}(release, action)
|
|
||||||
|
|
||||||
case domain.ActionTypeLidarr:
|
|
||||||
go func(release domain.Release, action domain.Action) {
|
|
||||||
err = s.lidarr(release, action)
|
|
||||||
if err != nil {
|
|
||||||
log.Error().Stack().Err(err).Msg("error sending torrent to lidarr")
|
|
||||||
//continue
|
|
||||||
}
|
|
||||||
}(release, action)
|
|
||||||
|
|
||||||
default:
|
|
||||||
log.Warn().Msgf("unsupported action: %v type: %v", action.Name, action.Type)
|
|
||||||
}
|
|
||||||
|
|
||||||
s.bus.Publish("release:store-action-status", &domain.ReleaseActionStatus{
|
|
||||||
ID: actionStatus.ID,
|
|
||||||
ReleaseID: release.ID,
|
|
||||||
Status: domain.ReleasePushStatusApproved,
|
|
||||||
Action: action.Name,
|
|
||||||
Type: action.Type,
|
|
||||||
Rejections: []string{},
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// safe to delete tmp file
|
// safe to delete tmp file
|
||||||
|
@ -183,6 +44,144 @@ func (s *service) RunActions(actions []domain.Action, release domain.Release) er
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *service) runAction(action domain.Action, release domain.Release) error {
|
||||||
|
|
||||||
|
var err error
|
||||||
|
var tmpFile string
|
||||||
|
var hash string
|
||||||
|
var rejections []string
|
||||||
|
|
||||||
|
switch action.Type {
|
||||||
|
case domain.ActionTypeTest:
|
||||||
|
s.test(action.Name)
|
||||||
|
|
||||||
|
case domain.ActionTypeExec:
|
||||||
|
if release.TorrentTmpFile == "" {
|
||||||
|
t, err := release.DownloadTorrentFile(nil)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Stack().Err(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpFile = t.TmpFileName
|
||||||
|
}
|
||||||
|
|
||||||
|
s.execCmd(release, action, tmpFile)
|
||||||
|
|
||||||
|
case domain.ActionTypeWatchFolder:
|
||||||
|
if release.TorrentTmpFile == "" {
|
||||||
|
t, err := release.DownloadTorrentFile(nil)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Stack().Err(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpFile = t.TmpFileName
|
||||||
|
}
|
||||||
|
s.watchFolder(action.WatchFolder, tmpFile)
|
||||||
|
|
||||||
|
case domain.ActionTypeDelugeV1, domain.ActionTypeDelugeV2:
|
||||||
|
canDownload, err := s.delugeCheckRulesCanDownload(action)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Stack().Err(err).Msgf("error checking client rules: %v", action.Name)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !canDownload {
|
||||||
|
rejections = []string{"deluge busy"}
|
||||||
|
}
|
||||||
|
|
||||||
|
if release.TorrentTmpFile == "" {
|
||||||
|
t, err := release.DownloadTorrentFile(nil)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Stack().Err(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpFile = t.TmpFileName
|
||||||
|
}
|
||||||
|
err = s.deluge(action, tmpFile)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Stack().Err(err).Msg("error sending torrent to Deluge")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
case domain.ActionTypeQbittorrent:
|
||||||
|
canDownload, client, err := s.qbittorrentCheckRulesCanDownload(action)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Stack().Err(err).Msgf("error checking client rules: %v", action.Name)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !canDownload {
|
||||||
|
rejections = []string{"qBittorrent busy"}
|
||||||
|
}
|
||||||
|
|
||||||
|
if release.TorrentTmpFile == "" {
|
||||||
|
t, err := release.DownloadTorrentFile(nil)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Stack().Err(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpFile = t.TmpFileName
|
||||||
|
hash = t.MetaInfo.HashInfoBytes().String()
|
||||||
|
}
|
||||||
|
err = s.qbittorrent(client, action, hash, tmpFile)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Stack().Err(err).Msg("error sending torrent to qBittorrent")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
case domain.ActionTypeRadarr:
|
||||||
|
rejections, err = s.radarr(release, action)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Stack().Err(err).Msg("error sending torrent to radarr")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
case domain.ActionTypeSonarr:
|
||||||
|
rejections, err = s.sonarr(release, action)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Stack().Err(err).Msg("error sending torrent to sonarr")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
case domain.ActionTypeLidarr:
|
||||||
|
rejections, err = s.lidarr(release, action)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Stack().Err(err).Msg("error sending torrent to lidarr")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
log.Warn().Msgf("unsupported action: %v type: %v", action.Name, action.Type)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if rejections != nil {
|
||||||
|
s.bus.Publish("release:push-rejected", &domain.ReleaseActionStatus{
|
||||||
|
ReleaseID: release.ID,
|
||||||
|
Status: domain.ReleasePushStatusRejected,
|
||||||
|
Action: action.Name,
|
||||||
|
Type: action.Type,
|
||||||
|
Rejections: rejections,
|
||||||
|
Timestamp: time.Now(),
|
||||||
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
s.bus.Publish("release:push-approved", &domain.ReleaseActionStatus{
|
||||||
|
ReleaseID: release.ID,
|
||||||
|
Status: domain.ReleasePushStatusApproved,
|
||||||
|
Action: action.Name,
|
||||||
|
Type: action.Type,
|
||||||
|
Rejections: []string{},
|
||||||
|
Timestamp: time.Now(),
|
||||||
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *service) CheckCanDownload(actions []domain.Action) bool {
|
func (s *service) CheckCanDownload(actions []domain.Action) bool {
|
||||||
for _, action := range actions {
|
for _, action := range actions {
|
||||||
if !action.Enabled {
|
if !action.Enabled {
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *service) sonarr(release domain.Release, action domain.Action) error {
|
func (s *service) sonarr(release domain.Release, action domain.Action) ([]string, error) {
|
||||||
log.Trace().Msg("action SONARR")
|
log.Trace().Msg("action SONARR")
|
||||||
|
|
||||||
// TODO validate data
|
// TODO validate data
|
||||||
|
@ -18,13 +18,13 @@ func (s *service) sonarr(release domain.Release, action domain.Action) error {
|
||||||
// get client for action
|
// get client for action
|
||||||
client, err := s.clientSvc.FindByID(context.TODO(), action.ClientID)
|
client, err := s.clientSvc.FindByID(context.TODO(), action.ClientID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msgf("error finding client: %v", action.ClientID)
|
log.Error().Err(err).Msgf("sonarr: error finding client: %v", action.ClientID)
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// return early if no client found
|
// return early if no client found
|
||||||
if client == nil {
|
if client == nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// initial config
|
// initial config
|
||||||
|
@ -52,23 +52,19 @@ func (s *service) sonarr(release domain.Release, action domain.Action) error {
|
||||||
PublishDate: time.Now().Format(time.RFC3339),
|
PublishDate: time.Now().Format(time.RFC3339),
|
||||||
}
|
}
|
||||||
|
|
||||||
success, rejections, err := arr.Push(r)
|
rejections, err := arr.Push(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Stack().Err(err).Msgf("sonarr: failed to push release: %v", r)
|
log.Error().Stack().Err(err).Msgf("sonarr: failed to push release: %v", r)
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !success {
|
if rejections != nil {
|
||||||
log.Debug().Msgf("sonarr: release push rejected: %v, indexer %v to %v reasons: '%v'", r.Title, r.Indexer, client.Host, rejections)
|
log.Debug().Msgf("sonarr: release push rejected: %v, indexer %v to %v reasons: '%v'", r.Title, r.Indexer, client.Host, rejections)
|
||||||
|
|
||||||
// save pushed release
|
return rejections, nil
|
||||||
s.bus.Publish("release:update-push-status-rejected", release.ID, rejections)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debug().Msgf("sonarr: successfully pushed release: %v, indexer %v to %v", r.Title, r.Indexer, client.Host)
|
log.Debug().Msgf("sonarr: successfully pushed release: %v, indexer %v to %v", r.Title, r.Indexer, client.Host)
|
||||||
|
|
||||||
s.bus.Publish("release:update-push-status", release.ID, domain.ReleasePushStatusApproved)
|
return nil, nil
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1457,7 +1457,7 @@ type ReleasePushStatus string
|
||||||
const (
|
const (
|
||||||
ReleasePushStatusApproved ReleasePushStatus = "PUSH_APPROVED"
|
ReleasePushStatusApproved ReleasePushStatus = "PUSH_APPROVED"
|
||||||
ReleasePushStatusRejected ReleasePushStatus = "PUSH_REJECTED"
|
ReleasePushStatusRejected ReleasePushStatus = "PUSH_REJECTED"
|
||||||
ReleasePushStatusMixed ReleasePushStatus = "MIXED" // For multiple actions, one might go and the other not
|
ReleasePushStatusErr ReleasePushStatus = "PUSH_ERROR"
|
||||||
ReleasePushStatusPending ReleasePushStatus = "PENDING" // Initial status
|
ReleasePushStatusPending ReleasePushStatus = "PENDING" // Initial status
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,8 @@ func NewSubscribers(eventbus EventBus.Bus, releaseSvc release.Service) Subscribe
|
||||||
|
|
||||||
func (s Subscriber) Register() {
|
func (s Subscriber) Register() {
|
||||||
s.eventbus.Subscribe("release:store-action-status", s.releaseActionStatus)
|
s.eventbus.Subscribe("release:store-action-status", s.releaseActionStatus)
|
||||||
|
s.eventbus.Subscribe("release:push-rejected", s.releasePushRejected)
|
||||||
|
s.eventbus.Subscribe("release:push-approved", s.releasePushApproved)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s Subscriber) releaseActionStatus(actionStatus *domain.ReleaseActionStatus) {
|
func (s Subscriber) releaseActionStatus(actionStatus *domain.ReleaseActionStatus) {
|
||||||
|
@ -35,3 +37,21 @@ func (s Subscriber) releaseActionStatus(actionStatus *domain.ReleaseActionStatus
|
||||||
log.Error().Err(err).Msgf("events: 'release:store-action-status' error")
|
log.Error().Err(err).Msgf("events: 'release:store-action-status' error")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s Subscriber) releasePushRejected(actionStatus *domain.ReleaseActionStatus) {
|
||||||
|
log.Trace().Msgf("events: 'release:push-rejected' '%+v'", actionStatus)
|
||||||
|
|
||||||
|
err := s.releaseSvc.StoreReleaseActionStatus(context.Background(), actionStatus)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Msgf("events: 'release:push-rejected' error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Subscriber) releasePushApproved(actionStatus *domain.ReleaseActionStatus) {
|
||||||
|
log.Trace().Msgf("events: 'release:push-approved' '%+v'", actionStatus)
|
||||||
|
|
||||||
|
err := s.releaseSvc.StoreReleaseActionStatus(context.Background(), actionStatus)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Msgf("events: 'release:push-approved' error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ type Config struct {
|
||||||
|
|
||||||
type Client interface {
|
type Client interface {
|
||||||
Test() (*SystemStatusResponse, error)
|
Test() (*SystemStatusResponse, error)
|
||||||
Push(release Release) (bool, string, error)
|
Push(release Release) ([]string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type client struct {
|
type client struct {
|
||||||
|
@ -93,15 +93,15 @@ func (c *client) Test() (*SystemStatusResponse, error) {
|
||||||
return &response, nil
|
return &response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *client) Push(release Release) (bool, string, error) {
|
func (c *client) Push(release Release) ([]string, error) {
|
||||||
res, err := c.post("release/push", release)
|
res, err := c.post("release/push", release)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Stack().Err(err).Msg("lidarr client post error")
|
log.Error().Stack().Err(err).Msg("lidarr client post error")
|
||||||
return false, "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if res == nil {
|
if res == nil {
|
||||||
return false, "", nil
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
defer res.Body.Close()
|
defer res.Body.Close()
|
||||||
|
@ -109,14 +109,14 @@ func (c *client) Push(release Release) (bool, string, error) {
|
||||||
body, err := io.ReadAll(res.Body)
|
body, err := io.ReadAll(res.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Stack().Err(err).Msg("lidarr client error reading body")
|
log.Error().Stack().Err(err).Msg("lidarr client error reading body")
|
||||||
return false, "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
pushResponse := PushResponse{}
|
pushResponse := PushResponse{}
|
||||||
err = json.Unmarshal(body, &pushResponse)
|
err = json.Unmarshal(body, &pushResponse)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Stack().Err(err).Msg("lidarr client error json unmarshal")
|
log.Error().Stack().Err(err).Msg("lidarr client error json unmarshal")
|
||||||
return false, "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Trace().Msgf("lidarr release/push response body: %+v", string(body))
|
log.Trace().Msgf("lidarr release/push response body: %+v", string(body))
|
||||||
|
@ -126,8 +126,8 @@ func (c *client) Push(release Release) (bool, string, error) {
|
||||||
rejections := strings.Join(pushResponse.Rejections, ", ")
|
rejections := strings.Join(pushResponse.Rejections, ", ")
|
||||||
|
|
||||||
log.Trace().Msgf("lidarr push rejected: %s - reasons: %q", release.Title, rejections)
|
log.Trace().Msgf("lidarr push rejected: %s - reasons: %q", release.Title, rejections)
|
||||||
return false, rejections, nil
|
return pushResponse.Rejections, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return true, "", nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,11 +46,12 @@ func Test_client_Push(t *testing.T) {
|
||||||
release Release
|
release Release
|
||||||
}
|
}
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
fields fields
|
fields fields
|
||||||
args args
|
args args
|
||||||
err error
|
err error
|
||||||
wantErr bool
|
rejections []string
|
||||||
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "push",
|
name: "push",
|
||||||
|
@ -72,8 +73,7 @@ func Test_client_Push(t *testing.T) {
|
||||||
Protocol: "torrent",
|
Protocol: "torrent",
|
||||||
PublishDate: "2021-08-21T15:36:00Z",
|
PublishDate: "2021-08-21T15:36:00Z",
|
||||||
}},
|
}},
|
||||||
err: errors.New("lidarr push rejected Unknown Artist"),
|
rejections: []string{"Unknown Artist"},
|
||||||
wantErr: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "push_error",
|
name: "push_error",
|
||||||
|
@ -95,15 +95,15 @@ func Test_client_Push(t *testing.T) {
|
||||||
Protocol: "torrent",
|
Protocol: "torrent",
|
||||||
PublishDate: "2021-08-21T15:36:00Z",
|
PublishDate: "2021-08-21T15:36:00Z",
|
||||||
}},
|
}},
|
||||||
err: errors.New("lidarr push rejected Unknown Artist"),
|
rejections: []string{"Unknown Artist"},
|
||||||
wantErr: true,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
c := New(tt.fields.config)
|
c := New(tt.fields.config)
|
||||||
|
|
||||||
_, _, err := c.Push(tt.args.release)
|
rejections, err := c.Push(tt.args.release)
|
||||||
|
assert.Equal(t, tt.rejections, rejections)
|
||||||
if tt.wantErr && assert.Error(t, err) {
|
if tt.wantErr && assert.Error(t, err) {
|
||||||
assert.Equal(t, tt.err, err)
|
assert.Equal(t, tt.err, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ type Config struct {
|
||||||
|
|
||||||
type Client interface {
|
type Client interface {
|
||||||
Test() (*SystemStatusResponse, error)
|
Test() (*SystemStatusResponse, error)
|
||||||
Push(release Release) (bool, string, error)
|
Push(release Release) ([]string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type client struct {
|
type client struct {
|
||||||
|
@ -92,15 +92,15 @@ func (c *client) Test() (*SystemStatusResponse, error) {
|
||||||
return &response, nil
|
return &response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *client) Push(release Release) (bool, string, error) {
|
func (c *client) Push(release Release) ([]string, error) {
|
||||||
res, err := c.post("release/push", release)
|
res, err := c.post("release/push", release)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Stack().Err(err).Msg("radarr client post error")
|
log.Error().Stack().Err(err).Msg("radarr client post error")
|
||||||
return false, "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if res == nil {
|
if res == nil {
|
||||||
return false, "", nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
defer res.Body.Close()
|
defer res.Body.Close()
|
||||||
|
@ -108,14 +108,14 @@ func (c *client) Push(release Release) (bool, string, error) {
|
||||||
body, err := io.ReadAll(res.Body)
|
body, err := io.ReadAll(res.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Stack().Err(err).Msg("radarr client error reading body")
|
log.Error().Stack().Err(err).Msg("radarr client error reading body")
|
||||||
return false, "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
pushResponse := make([]PushResponse, 0)
|
pushResponse := make([]PushResponse, 0)
|
||||||
err = json.Unmarshal(body, &pushResponse)
|
err = json.Unmarshal(body, &pushResponse)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Stack().Err(err).Msg("radarr client error json unmarshal")
|
log.Error().Stack().Err(err).Msg("radarr client error json unmarshal")
|
||||||
return false, "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Trace().Msgf("radarr release/push response body: %+v", string(body))
|
log.Trace().Msgf("radarr release/push response body: %+v", string(body))
|
||||||
|
@ -125,9 +125,9 @@ func (c *client) Push(release Release) (bool, string, error) {
|
||||||
rejections := strings.Join(pushResponse[0].Rejections, ", ")
|
rejections := strings.Join(pushResponse[0].Rejections, ", ")
|
||||||
|
|
||||||
log.Trace().Msgf("radarr push rejected: %s - reasons: %q", release.Title, rejections)
|
log.Trace().Msgf("radarr push rejected: %s - reasons: %q", release.Title, rejections)
|
||||||
return false, rejections, nil
|
return pushResponse[0].Rejections, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// success true
|
// success true
|
||||||
return true, "", nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,11 +47,12 @@ func Test_client_Push(t *testing.T) {
|
||||||
release Release
|
release Release
|
||||||
}
|
}
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
fields fields
|
fields fields
|
||||||
args args
|
args args
|
||||||
err error
|
rejections []string
|
||||||
wantErr bool
|
err error
|
||||||
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "push",
|
name: "push",
|
||||||
|
@ -73,8 +74,9 @@ func Test_client_Push(t *testing.T) {
|
||||||
Protocol: "torrent",
|
Protocol: "torrent",
|
||||||
PublishDate: "2021-08-21T15:36:00Z",
|
PublishDate: "2021-08-21T15:36:00Z",
|
||||||
}},
|
}},
|
||||||
err: errors.New("radarr push rejected Could not find Some Old Movie"),
|
rejections: []string{"Could not find Some Old Movie"},
|
||||||
wantErr: true,
|
//err: errors.New("radarr push rejected Could not find Some Old Movie"),
|
||||||
|
//wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "push_error",
|
name: "push_error",
|
||||||
|
@ -96,15 +98,17 @@ func Test_client_Push(t *testing.T) {
|
||||||
Protocol: "torrent",
|
Protocol: "torrent",
|
||||||
PublishDate: "2021-08-21T15:36:00Z",
|
PublishDate: "2021-08-21T15:36:00Z",
|
||||||
}},
|
}},
|
||||||
err: errors.New("radarr push rejected Could not find Some Old Movie"),
|
rejections: []string{"Could not find Some Old Movie"},
|
||||||
wantErr: true,
|
//err: errors.New("radarr push rejected Could not find Some Old Movie"),
|
||||||
|
//wantErr: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
c := New(tt.fields.config)
|
c := New(tt.fields.config)
|
||||||
|
|
||||||
_, _, err := c.Push(tt.args.release)
|
rejections, err := c.Push(tt.args.release)
|
||||||
|
assert.Equal(t, tt.rejections, rejections)
|
||||||
if tt.wantErr && assert.Error(t, err) {
|
if tt.wantErr && assert.Error(t, err) {
|
||||||
assert.Equal(t, tt.err, err)
|
assert.Equal(t, tt.err, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ type Config struct {
|
||||||
|
|
||||||
type Client interface {
|
type Client interface {
|
||||||
Test() (*SystemStatusResponse, error)
|
Test() (*SystemStatusResponse, error)
|
||||||
Push(release Release) (bool, string, error)
|
Push(release Release) ([]string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type client struct {
|
type client struct {
|
||||||
|
@ -93,15 +93,15 @@ func (c *client) Test() (*SystemStatusResponse, error) {
|
||||||
return &response, nil
|
return &response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *client) Push(release Release) (bool, string, error) {
|
func (c *client) Push(release Release) ([]string, error) {
|
||||||
res, err := c.post("release/push", release)
|
res, err := c.post("release/push", release)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Stack().Err(err).Msg("sonarr client post error")
|
log.Error().Stack().Err(err).Msg("sonarr client post error")
|
||||||
return false, "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if res == nil {
|
if res == nil {
|
||||||
return false, "", nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
defer res.Body.Close()
|
defer res.Body.Close()
|
||||||
|
@ -109,14 +109,14 @@ func (c *client) Push(release Release) (bool, string, error) {
|
||||||
body, err := io.ReadAll(res.Body)
|
body, err := io.ReadAll(res.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Stack().Err(err).Msg("sonarr client error reading body")
|
log.Error().Stack().Err(err).Msg("sonarr client error reading body")
|
||||||
return false, "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
pushResponse := make([]PushResponse, 0)
|
pushResponse := make([]PushResponse, 0)
|
||||||
err = json.Unmarshal(body, &pushResponse)
|
err = json.Unmarshal(body, &pushResponse)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Stack().Err(err).Msg("sonarr client error json unmarshal")
|
log.Error().Stack().Err(err).Msg("sonarr client error json unmarshal")
|
||||||
return false, "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Trace().Msgf("sonarr release/push response body: %+v", string(body))
|
log.Trace().Msgf("sonarr release/push response body: %+v", string(body))
|
||||||
|
@ -126,9 +126,9 @@ func (c *client) Push(release Release) (bool, string, error) {
|
||||||
rejections := strings.Join(pushResponse[0].Rejections, ", ")
|
rejections := strings.Join(pushResponse[0].Rejections, ", ")
|
||||||
|
|
||||||
log.Trace().Msgf("sonarr push rejected: %s - reasons: %q", release.Title, rejections)
|
log.Trace().Msgf("sonarr push rejected: %s - reasons: %q", release.Title, rejections)
|
||||||
return false, rejections, nil
|
return pushResponse[0].Rejections, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// successful push
|
// successful push
|
||||||
return true, "", nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,11 +47,12 @@ func Test_client_Push(t *testing.T) {
|
||||||
release Release
|
release Release
|
||||||
}
|
}
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
fields fields
|
fields fields
|
||||||
args args
|
args args
|
||||||
err error
|
rejections []string
|
||||||
wantErr bool
|
err error
|
||||||
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "push",
|
name: "push",
|
||||||
|
@ -73,8 +74,9 @@ func Test_client_Push(t *testing.T) {
|
||||||
Protocol: "torrent",
|
Protocol: "torrent",
|
||||||
PublishDate: "2021-08-21T15:36:00Z",
|
PublishDate: "2021-08-21T15:36:00Z",
|
||||||
}},
|
}},
|
||||||
err: errors.New("sonarr push rejected Unknown Series"),
|
rejections: []string{"Unknown Series"},
|
||||||
wantErr: true,
|
//err: errors.New("sonarr push rejected Unknown Series"),
|
||||||
|
//wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "push_error",
|
name: "push_error",
|
||||||
|
@ -96,15 +98,17 @@ func Test_client_Push(t *testing.T) {
|
||||||
Protocol: "torrent",
|
Protocol: "torrent",
|
||||||
PublishDate: "2021-08-21T15:36:00Z",
|
PublishDate: "2021-08-21T15:36:00Z",
|
||||||
}},
|
}},
|
||||||
err: errors.New("sonarr push rejected Unknown Series"),
|
rejections: []string{"Unknown Series"},
|
||||||
wantErr: true,
|
//err: errors.New("sonarr push rejected Unknown Series"),
|
||||||
|
//wantErr: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
c := New(tt.fields.config)
|
c := New(tt.fields.config)
|
||||||
|
|
||||||
_, _, err := c.Push(tt.args.release)
|
rejections, err := c.Push(tt.args.release)
|
||||||
|
assert.Equal(t, tt.rejections, rejections)
|
||||||
if tt.wantErr && assert.Error(t, err) {
|
if tt.wantErr && assert.Error(t, err) {
|
||||||
assert.Equal(t, tt.err, err)
|
assert.Equal(t, tt.err, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ExclamationCircleIcon } from "@heroicons/react/outline"
|
import { BanIcon, ExclamationCircleIcon } from "@heroicons/react/outline"
|
||||||
import ClockIcon from "@heroicons/react/outline/ClockIcon"
|
import ClockIcon from "@heroicons/react/outline/ClockIcon"
|
||||||
import { ChevronDoubleLeftIcon, ChevronLeftIcon, ChevronRightIcon, ChevronDoubleRightIcon, CheckIcon } from "@heroicons/react/solid"
|
import { ChevronDoubleLeftIcon, ChevronLeftIcon, ChevronRightIcon, ChevronDoubleRightIcon, CheckIcon } from "@heroicons/react/solid"
|
||||||
import { formatDistanceToNowStrict } from "date-fns"
|
import { formatDistanceToNowStrict } from "date-fns"
|
||||||
|
@ -7,7 +7,7 @@ import { useQuery } from "react-query"
|
||||||
import { useTable, useSortBy, usePagination } from "react-table"
|
import { useTable, useSortBy, usePagination } from "react-table"
|
||||||
import APIClient from "../api/APIClient"
|
import APIClient from "../api/APIClient"
|
||||||
import { EmptyListState } from "../components/emptystates"
|
import { EmptyListState } from "../components/emptystates"
|
||||||
import { classNames } from "../utils"
|
import { classNames, simplifyDate } from "../utils"
|
||||||
|
|
||||||
export function Releases() {
|
export function Releases() {
|
||||||
return (
|
return (
|
||||||
|
@ -127,19 +127,22 @@ interface ReleaseStatusCellProps {
|
||||||
|
|
||||||
export function ReleaseStatusCell({ value, column, row }: ReleaseStatusCellProps) {
|
export function ReleaseStatusCell({ value, column, row }: ReleaseStatusCellProps) {
|
||||||
const statusMap: any = {
|
const statusMap: any = {
|
||||||
"PUSH_REJECTED": <span className="mr-1 inline-flex items-center rounded text-xs font-semibold uppercase bg-pink-100 text-pink-800 hover:bg-pink-300">
|
"PUSH_ERROR": <span className="mr-1 inline-flex items-center rounded text-xs font-semibold uppercase bg-pink-100 text-pink-800 hover:bg-pink-300 cursor-pointer">
|
||||||
<ExclamationCircleIcon className="h-5 w-5" aria-hidden="true" />
|
<ExclamationCircleIcon className="h-5 w-5" aria-hidden="true" />
|
||||||
</span>,
|
</span>,
|
||||||
"PUSH_APPROVED": <span className="mr-1 inline-flex items-center rounded text-xs font-semibold uppercase bg-green-100 text-green-800 hover:bg-green-300">
|
"PUSH_REJECTED": <span className="mr-1 inline-flex items-center rounded text-xs font-semibold uppercase bg-blue-200 dark:bg-blue-100 text-blue-400 dark:text-blue-800 hover:bg-blue-300 dark:hover:bg-blue-400 cursor-pointer">
|
||||||
|
<BanIcon className="h-5 w-5" aria-hidden="true" />
|
||||||
|
</span>,
|
||||||
|
"PUSH_APPROVED": <span className="mr-1 inline-flex items-center rounded text-xs font-semibold uppercase bg-green-100 text-green-800 hover:bg-green-300 cursor-pointer">
|
||||||
<CheckIcon className="h-5 w-5" aria-hidden="true" />
|
<CheckIcon className="h-5 w-5" aria-hidden="true" />
|
||||||
</span>,
|
</span>,
|
||||||
"PENDING": <span className="mr-1 inline-flex items-center rounded text-xs font-semibold uppercase bg-yellow-100 text-yellow-800 hover:bg-yellow-200">
|
"PENDING": <span className="mr-1 inline-flex items-center rounded text-xs font-semibold uppercase bg-yellow-100 text-yellow-800 hover:bg-yellow-200 cursor-pointer">
|
||||||
<ClockIcon className="h-5 w-5" aria-hidden="true" />
|
<ClockIcon className="h-5 w-5" aria-hidden="true" />
|
||||||
</span>,
|
</span>,
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div className="flex text-sm font-medium text-gray-900 dark:text-gray-300">
|
<div className="flex text-sm font-medium text-gray-900 dark:text-gray-300">
|
||||||
{value.map((v, idx) => <div key={idx} title={`action: ${v.action}, type: ${v.type}, status: ${v.status}, ;time: ${v.timestamp}`}>{statusMap[v.status]}</div>)}
|
{value.map((v, idx) => <div key={idx} title={`action: ${v.action}, type: ${v.type}, status: ${v.status}, time: ${simplifyDate(v.timestamp)}, rejections: ${v?.rejections}`}>{statusMap[v.status]}</div>)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
2
web/src/types/Release.d.ts
vendored
2
web/src/types/Release.d.ts
vendored
|
@ -18,7 +18,7 @@ interface ReleaseActionStatus {
|
||||||
action: string;
|
action: string;
|
||||||
type: string;
|
type: string;
|
||||||
rejections: string[];
|
rejections: string[];
|
||||||
timestamp: Date
|
timestamp: string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ReleaseFindResponse {
|
interface ReleaseFindResponse {
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { formatDistanceToNowStrict, formatISO9075 } from "date-fns";
|
||||||
|
|
||||||
// sleep for x ms
|
// sleep for x ms
|
||||||
export function sleep(ms: number) {
|
export function sleep(ms: number) {
|
||||||
return new Promise(resolve => setTimeout(resolve, ms));
|
return new Promise(resolve => setTimeout(resolve, ms));
|
||||||
|
@ -56,4 +58,23 @@ export function classNames(...classes: string[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// column widths for inputs etc
|
// column widths for inputs etc
|
||||||
export type COL_WIDTHS = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
|
export type COL_WIDTHS = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
|
||||||
|
|
||||||
|
// simplify date
|
||||||
|
export function simplifyDate(date: string) {
|
||||||
|
if (date !== "0001-01-01T00:00:00Z") {
|
||||||
|
return formatISO9075(new Date(date))
|
||||||
|
}
|
||||||
|
return "n/a"
|
||||||
|
}
|
||||||
|
|
||||||
|
// if empty date show as n/a
|
||||||
|
export function IsEmptyDate(date: string) {
|
||||||
|
if (date !== "0001-01-01T00:00:00Z") {
|
||||||
|
return formatDistanceToNowStrict(
|
||||||
|
new Date(date),
|
||||||
|
{ addSuffix: true }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return "n/a"
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue