serie.go 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. package tmdb
  2. import (
  3. "notabug.org/apiote/amuse/config"
  4. "notabug.org/apiote/amuse/datastructure"
  5. "notabug.org/apiote/amuse/i18n"
  6. "notabug.org/apiote/amuse/network"
  7. "encoding/json"
  8. "fmt"
  9. "net/http"
  10. "strconv"
  11. "strings"
  12. "time"
  13. "notabug.org/apiote/gott"
  14. )
  15. type Episode struct {
  16. Air_date_str string `json:"air_date"`
  17. Air_date time.Time
  18. Episode_number int `json:"episode_number"`
  19. Name string
  20. Overview string
  21. Season_number int `json:"season_number"`
  22. Still_path string `json:"still_path"`
  23. Vote_count int `json:"vote_count"`
  24. Vote_average float32 `json:"vote_average"`
  25. Episode_code string
  26. Experiences []time.Time
  27. ContainsSpoilers bool
  28. }
  29. func (e Episode) IsWatched() bool {
  30. return len(e.Experiences) > 0 && !e.Experiences[0].IsZero()
  31. }
  32. func (e Episode) GetLastExperience(strings i18n.Translation, timezone string) string {
  33. return i18n.FormatDateNice(e.Experiences[0], strings, timezone)
  34. }
  35. type Season struct {
  36. Season_number int `json:"season_number"`
  37. Season_number_string string
  38. Episodes []Episode
  39. Credits ShowCredits
  40. }
  41. type TvSerie struct {
  42. Id string `json:"-"`
  43. Etag string
  44. Backdrop_path string `json:"backdrop_path"`
  45. Episode_run_time []int `json:"episode_run_time"`
  46. First_air_date_str string `json:"first_air_date"`
  47. First_air_date time.Time
  48. Genres []struct {
  49. Id int
  50. Name string
  51. }
  52. Last_air_date_str string `json:"last_air_date"`
  53. Last_air_date time.Time
  54. Last_episode_to_air Episode `json:"last_episode_to_air"`
  55. Name string
  56. Number_of_episodes int `json:"number_of_episodes"`
  57. Original_name string `json:"original_name"`
  58. Overview string
  59. Poster_path string `json:"poster_path"`
  60. Seasons []Season
  61. Status string
  62. Source string
  63. Type string
  64. Vote_count int `json:"vote_count"`
  65. Vote_average float32 `json:"vote_average"`
  66. Credits ShowCredits
  67. BasedOn datastructure.Book
  68. IsOnWantList bool
  69. Next_episode_to_watch Episode
  70. Progress int
  71. WatchedEpisodes int
  72. AllEpisodes int
  73. SkippedEpisodes int
  74. }
  75. func (s *TvSerie) GetItemInfo() datastructure.ItemInfo {
  76. genres := ""
  77. for _, genre := range s.Genres {
  78. genres += fmt.Sprintf("%d", genre.Id) + ","
  79. }
  80. years := strings.Split(s.GetYears(), "–")
  81. var (
  82. yearStart int64 = 0
  83. yearEnd int64 = 0
  84. )
  85. yearStart, _ = strconv.ParseInt(years[0], 10, 32)
  86. if len(years) > 1 {
  87. yearEnd, _ = strconv.ParseInt(years[1], 10, 32)
  88. }
  89. episodes := 0
  90. for _, season := range s.Seasons {
  91. episodes += len(season.Episodes)
  92. }
  93. itemInfo := datastructure.ItemInfo{
  94. Cover: s.Poster_path,
  95. Status: s.Status,
  96. Title: s.Original_name,
  97. YearStart: int(yearStart),
  98. YearEnd: int(yearEnd),
  99. Genres: genres,
  100. Episodes: episodes,
  101. // BasedOn
  102. }
  103. return itemInfo
  104. }
  105. func (s *TvSerie) GetItemType() datastructure.ItemType {
  106. return datastructure.ItemTypeTvserie
  107. }
  108. func (s *TvSerie) AddBasedOn(book datastructure.Book) {
  109. s.BasedOn = book
  110. }
  111. func (s *TvSerie) SetOnWantList(isOnList bool) {
  112. s.IsOnWantList = isOnList
  113. }
  114. func (s TvSerie) GetYears() string {
  115. if s.First_air_date.IsZero() {
  116. return ""
  117. } else if s.Status == "Ended" || s.Status == "Canceled" {
  118. if s.Last_air_date.Year() == s.First_air_date.Year() || s.Last_air_date.IsZero() {
  119. return strconv.FormatInt(int64(s.First_air_date.Year()), 10)
  120. } else {
  121. return strconv.FormatInt(int64(s.First_air_date.Year()), 10) + "–" + strconv.FormatInt(int64(s.Last_air_date.Year()), 10)
  122. }
  123. } else {
  124. return strconv.FormatInt(int64(s.First_air_date.Year()), 10) + "–"
  125. }
  126. }
  127. func createSerieRequest(args ...interface{}) (interface{}, error) {
  128. request := args[0].(*network.Request)
  129. result := args[1].(*network.Result)
  130. client := &http.Client{}
  131. httpRequest, err := http.NewRequest("GET", "https://api.themoviedb.org/3/tv/"+request.Id+"?api_key="+config.TmdbApiKey+"&language="+request.Language+"&append_to_response=credits", nil)
  132. result.Client = client
  133. result.Request = httpRequest
  134. return gott.Tuple(args), err
  135. }
  136. func unmarshalSerie(args ...interface{}) (interface{}, error) {
  137. request := args[0].(*network.Request)
  138. result := args[1].(*network.Result)
  139. serie := &TvSerie{}
  140. err := json.Unmarshal(result.Body, serie)
  141. serie.Id = request.Id
  142. serie.Source = "https://themoviedb.org/tv/" + request.Id
  143. result.Result = serie
  144. return gott.Tuple(args), err
  145. }
  146. func convertFirstDate(args ...interface{}) (interface{}, error) {
  147. serie := args[1].(*network.Result).Result.(*TvSerie)
  148. var (
  149. date time.Time
  150. err error
  151. )
  152. if serie.First_air_date_str != "" {
  153. date, err = time.Parse("2006-01-02", serie.First_air_date_str)
  154. serie.First_air_date = date
  155. }
  156. return gott.Tuple(args), err
  157. }
  158. func convertLatestDate(args ...interface{}) (interface{}, error) {
  159. serie := args[1].(*network.Result).Result.(*TvSerie)
  160. var (
  161. date time.Time
  162. err error
  163. )
  164. if serie.Last_air_date_str != "" {
  165. date, err = time.Parse("2006-01-02", serie.Last_air_date_str)
  166. serie.Last_air_date = date
  167. }
  168. return gott.Tuple(args), err
  169. }
  170. func convertLastDate(args ...interface{}) (interface{}, error) {
  171. serie := args[1].(*network.Result).Result.(*TvSerie)
  172. var (
  173. date time.Time
  174. err error
  175. )
  176. if serie.Last_episode_to_air.Air_date_str != "" {
  177. date, err = time.Parse("2006-01-02", serie.Last_episode_to_air.Air_date_str)
  178. serie.Last_episode_to_air.Air_date = date
  179. }
  180. return gott.Tuple(args), err
  181. }
  182. func createSeasonRequest(args ...interface{}) (interface{}, error) {
  183. request := args[0].(*network.Request)
  184. result := args[1].(*network.Result)
  185. client := &http.Client{}
  186. httpRequest, err := http.NewRequest("GET", "https://api.themoviedb.org/3/tv/"+request.Id+"/season/"+request.Subid+"?api_key="+config.TmdbApiKey+"&language="+request.Language+"&append_to_response=credits", nil)
  187. result.Client = client
  188. result.Request = httpRequest
  189. return gott.Tuple(args), err
  190. }
  191. func unmarshalSeason(args ...interface{}) (interface{}, error) {
  192. result := args[1].(*network.Result)
  193. season := &Season{}
  194. err := json.Unmarshal(result.Body, season)
  195. for i, episode := range season.Episodes {
  196. episode.Episode_code = fmt.Sprintf("S%02dE%02d", season.Season_number, episode.Episode_number)
  197. season.Episodes[i] = episode
  198. }
  199. season.Season_number_string = fmt.Sprintf("%02d", season.Season_number)
  200. result.Result = season
  201. return gott.Tuple(args), err
  202. }
  203. func convertSeasonDates(args ...interface{}) (interface{}, error) {
  204. season := args[1].(*network.Result).Result.(*Season)
  205. for i, episode := range season.Episodes {
  206. if episode.Air_date_str != "" {
  207. date, err := time.Parse("2006-01-02", episode.Air_date_str)
  208. if err != nil {
  209. return gott.Tuple(args), err
  210. }
  211. episode.Air_date = date
  212. season.Episodes[i] = episode
  213. }
  214. }
  215. return gott.Tuple(args), nil
  216. }
  217. func findLatestEpisodeCode(args ...interface{}) interface{} {
  218. serie := args[1].(*network.Result).Result.(*TvSerie)
  219. serie.Last_episode_to_air.Episode_code = fmt.Sprintf("S%02dE%02d",
  220. serie.Last_episode_to_air.Season_number, serie.Last_episode_to_air.Episode_number)
  221. return gott.Tuple(args)
  222. }
  223. func GetSerie(id, language string) (*TvSerie, error) {
  224. serie, err := gott.
  225. NewResult(gott.Tuple{&network.Request{Id: id, Language: language}, &network.Result{}}).
  226. Bind(createSerieRequest).
  227. Bind(getCacheEntry).
  228. Map(network.AddHeaders).
  229. Bind(network.DoRequest).
  230. Bind(network.HandleRequestError).
  231. Bind(network.ReadResponse).
  232. Tee(cleanCache).
  233. Tee(saveCacheEntry).
  234. Bind(unmarshalSerie).
  235. Bind(convertFirstDate).
  236. Bind(convertLatestDate).
  237. Bind(convertLastDate).
  238. Map(findLatestEpisodeCode).
  239. Finish()
  240. if err != nil {
  241. return &TvSerie{}, err
  242. } else {
  243. return serie.(gott.Tuple)[1].(*network.Result).Result.(*TvSerie), nil
  244. }
  245. }
  246. func GetSeason(serie *TvSerie, language string, seasonNumber int) (Season, error) {
  247. seasonNumberS := strconv.FormatInt(int64(seasonNumber), 10)
  248. s, err := gott.
  249. NewResult(gott.Tuple{&network.Request{Id: serie.Id, Language: language, Subid: seasonNumberS}, &network.Result{}}).
  250. Bind(createSeasonRequest).
  251. Bind(getCacheEntry).
  252. Map(network.AddHeaders).
  253. Bind(network.DoRequest).
  254. Bind(network.HandleRequestError).
  255. Bind(network.ReadResponse).
  256. Tee(cleanCache).
  257. Tee(saveCacheEntry).
  258. Bind(unmarshalSeason).
  259. Bind(convertSeasonDates).
  260. Finish()
  261. season := *s.(gott.Tuple)[1].(*network.Result).Result.(*Season)
  262. return season, err
  263. }
  264. func GetSeasons(serie *TvSerie, language string) ([]Season, error) {
  265. var seasons []Season
  266. for _, serieSeason := range serie.Seasons {
  267. season, err := GetSeason(serie, language, serieSeason.Season_number)
  268. if err != nil {
  269. return seasons, err
  270. }
  271. seasons = append(seasons, season)
  272. }
  273. return seasons, nil
  274. }