emby.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. package emby_helper
  2. import (
  3. "fmt"
  4. "github.com/allanpk716/ChineseSubFinder/internal/common"
  5. "github.com/allanpk716/ChineseSubFinder/internal/pkg/log_helper"
  6. "github.com/allanpk716/ChineseSubFinder/internal/types/emby"
  7. "github.com/go-resty/resty/v2"
  8. "github.com/panjf2000/ants/v2"
  9. "golang.org/x/net/context"
  10. "sync"
  11. "time"
  12. )
  13. type EmbyApi struct {
  14. embyConfig emby.EmbyConfig
  15. threads int
  16. timeOut time.Duration
  17. }
  18. func NewEmbyHelper(embyConfig emby.EmbyConfig) *EmbyApi {
  19. em := EmbyApi{}
  20. em.embyConfig = embyConfig
  21. if em.embyConfig.LimitCount < common.EmbyApiGetItemsLimitMin ||
  22. em.embyConfig.LimitCount > common.EmbyApiGetItemsLimitMax {
  23. em.embyConfig.LimitCount = common.EmbyApiGetItemsLimitMin
  24. }
  25. em.threads = 6
  26. em.timeOut = 5 * time.Second
  27. return &em
  28. }
  29. // RefreshRecentlyVideoInfo 字幕下载完毕一次,就可以触发一次这个。并发 6 线程去刷新
  30. func (em EmbyApi) RefreshRecentlyVideoInfo() error {
  31. items, err := em.GetRecentlyItems()
  32. if err != nil {
  33. return err
  34. }
  35. updateFunc := func(i interface{}) error {
  36. tmpId := i.(string)
  37. return em.UpdateVideoSubList(tmpId)
  38. }
  39. p, err := ants.NewPoolWithFunc(em.threads, func(inData interface{}) {
  40. data := inData.(InputData)
  41. defer data.Wg.Done()
  42. ctx, cancel := context.WithTimeout(context.Background(), em.timeOut)
  43. defer cancel()
  44. done := make(chan error, 1)
  45. panicChan := make(chan interface{}, 1)
  46. go func() {
  47. defer func() {
  48. if p := recover(); p != nil {
  49. panicChan <- p
  50. }
  51. }()
  52. done <- updateFunc(data.Id)
  53. }()
  54. select {
  55. case err = <-done:
  56. if err != nil {
  57. log_helper.GetLogger().Errorln("RefreshRecentlyVideoInfo.NewPoolWithFunc got error", err)
  58. }
  59. return
  60. case p := <-panicChan:
  61. log_helper.GetLogger().Errorln("RefreshRecentlyVideoInfo.NewPoolWithFunc got panic", p)
  62. case <-ctx.Done():
  63. log_helper.GetLogger().Errorln("RefreshRecentlyVideoInfo.NewPoolWithFunc got time out", ctx.Err())
  64. return
  65. }
  66. })
  67. if err != nil {
  68. return err
  69. }
  70. defer p.Release()
  71. wg := sync.WaitGroup{}
  72. for _, item := range items.Items {
  73. wg.Add(1)
  74. err = p.Invoke(InputData{Id: item.Id, Wg: &wg})
  75. if err != nil {
  76. log_helper.GetLogger().Errorln("RefreshRecentlyVideoInfo ants.Invoke", err)
  77. }
  78. }
  79. wg.Wait()
  80. return nil
  81. }
  82. // GetRecentlyItems 在 API 调试界面 -- ItemsService
  83. func (em EmbyApi) GetRecentlyItems() (emby.EmbyRecentlyItems, error) {
  84. var recItems emby.EmbyRecentlyItems
  85. _, err := em.getNewClient().R().
  86. SetQueryParams(map[string]string{
  87. "api_key": em.embyConfig.ApiKey,
  88. "IsUnaired": "false",
  89. "Limit": fmt.Sprintf("%d", em.embyConfig.LimitCount),
  90. "Recursive": "true",
  91. "SortOrder": "Descending",
  92. "IncludeItemTypes": "Episode,Movie",
  93. "Filters": "IsNotFolder",
  94. "SortBy": "DateCreated",
  95. }).
  96. SetResult(&recItems).
  97. Get(em.embyConfig.Url + "/emby/Items")
  98. if err != nil {
  99. return emby.EmbyRecentlyItems{}, err
  100. }
  101. return recItems, nil
  102. }
  103. // GetItemAncestors 在 API 调试界面 -- LibraryService
  104. func (em EmbyApi) GetItemAncestors(id string) ([]emby.EmbyItemsAncestors, error) {
  105. var recItems []emby.EmbyItemsAncestors
  106. _, err := em.getNewClient().R().
  107. SetQueryParams(map[string]string{
  108. "api_key": em.embyConfig.ApiKey,
  109. }).
  110. SetResult(&recItems).
  111. Get(em.embyConfig.Url + "/emby/Items/" + id + "/Ancestors")
  112. if err != nil {
  113. return nil, err
  114. }
  115. return recItems, nil
  116. }
  117. // GetItemVideoInfo 在 API 调试界面 -- UserLibraryService
  118. func (em EmbyApi) GetItemVideoInfo(id string) (emby.EmbyVideoInfo, error) {
  119. var recItem emby.EmbyVideoInfo
  120. _, err := em.getNewClient().R().
  121. SetQueryParams(map[string]string{
  122. "api_key": em.embyConfig.ApiKey,
  123. }).
  124. SetResult(&recItem).
  125. Get(em.embyConfig.Url + "/emby/LiveTv/Programs/" + id)
  126. if err != nil {
  127. return emby.EmbyVideoInfo{}, err
  128. }
  129. return recItem, nil
  130. }
  131. // UpdateVideoSubList 在 API 调试界面 -- ItemRefreshService
  132. func (em EmbyApi) UpdateVideoSubList(id string) error {
  133. _, err := em.getNewClient().R().
  134. SetQueryParams(map[string]string{
  135. "api_key": em.embyConfig.ApiKey,
  136. }).
  137. Post(em.embyConfig.Url + "/emby/Items/" + id + "/Refresh")
  138. if err != nil {
  139. return err
  140. }
  141. return nil
  142. }
  143. func (em EmbyApi) getNewClient() *resty.Client {
  144. tmpClient := resty.New()
  145. tmpClient.RemoveProxy()
  146. tmpClient.SetTimeout(em.timeOut)
  147. return tmpClient
  148. }
  149. type InputData struct {
  150. Id string
  151. Wg *sync.WaitGroup
  152. }