film.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. package tmdb
  2. import (
  3. "notabug.org/apiote/amuse/config"
  4. "notabug.org/apiote/amuse/i18n"
  5. "notabug.org/apiote/amuse/network"
  6. "notabug.org/apiote/amuse/datastructure"
  7. "encoding/json"
  8. "net/http"
  9. "sort"
  10. "time"
  11. "fmt"
  12. "notabug.org/apiote/gott"
  13. )
  14. type Collection struct {
  15. Id int
  16. Name string
  17. Parts []struct {
  18. Id int
  19. Release_date_str string `json:"release_date"`
  20. Release_date time.Time
  21. Poster_path string `json:"poster_path"`
  22. Title string
  23. IsWatched bool
  24. }
  25. }
  26. type Film struct {
  27. Id int
  28. Etag string
  29. Backdrop_path string `json:"backdrop_path"`
  30. Collection Collection `json:"belongs_to_collection"`
  31. Genres []struct {
  32. Id int
  33. Name string
  34. }
  35. Original_title string `json:"original_title"`
  36. Overview string
  37. Poster_path string `json:"poster_path"`
  38. Release_date_str string `json:"release_date"`
  39. Release_date time.Time
  40. Runtime int
  41. Status string
  42. Tagline string
  43. Title string
  44. Vote_count int `json:"vote_count"`
  45. Vote_average float32 `json:"vote_average"`
  46. Source string
  47. Credits ShowCredits
  48. BasedOn datastructure.Book
  49. Experiences []time.Time
  50. IsOnWantList bool
  51. }
  52. func (f *Film) GetItemInfo() datastructure.ItemInfo {
  53. part := 0
  54. for i, p := range f.Collection.Parts {
  55. if p.Title == f.Title {
  56. part = i
  57. break
  58. }
  59. }
  60. genres := ""
  61. for _, genre := range f.Genres {
  62. genres += fmt.Sprintf("%d", genre.Id) + ","
  63. }
  64. itemInfo := datastructure.ItemInfo{
  65. Cover: f.Poster_path,
  66. Status: f.Status,
  67. Title: f.Original_title,
  68. YearStart: f.Release_date.Year(),
  69. // todo BasedOn:
  70. Genres: genres,
  71. Runtime: f.Runtime,
  72. Collection: f.Collection.Id,
  73. Part: part,
  74. }
  75. return itemInfo
  76. }
  77. func (f *Film) GetItemType() datastructure.ItemType {
  78. return datastructure.ItemTypeFilm
  79. }
  80. func (f *Film) AddBasedOn(book datastructure.Book) {
  81. f.BasedOn = book
  82. }
  83. func (f *Film) SetOnWantList(isOnList bool) {
  84. f.IsOnWantList = isOnList
  85. }
  86. func (f Film) GetLastExperience(strings i18n.Translation, timezone string) string {
  87. return i18n.FormatDateNice(f.Experiences[0], strings, timezone)
  88. }
  89. func (f Film) GetLastExperienceFull(strings i18n.Translation) string {
  90. return i18n.FormatDate(f.Experiences[0], strings.Global["date_format_full"], strings.Global)
  91. }
  92. func createFilmRequest(args ...interface{}) (interface{}, error) {
  93. request := args[0].(*network.Request)
  94. result := args[1].(*network.Result)
  95. result.Client = &http.Client{}
  96. httpRequest, err := http.NewRequest("GET", "https://api.themoviedb.org/3/movie/"+request.Id+"?api_key="+config.TmdbApiKey+"&language="+request.Language+"&append_to_response=credits", nil)
  97. result.Request = httpRequest
  98. return gott.Tuple(args), err
  99. }
  100. func unmarshalFilm(args ...interface{}) (interface{}, error) {
  101. id := args[0].(*network.Request).Id
  102. result := args[1].(*network.Result)
  103. film := &Film{}
  104. err := json.Unmarshal(result.Body, film)
  105. film.Source = "https://www.themoviedb.org/movie/" + id
  106. film.Etag = result.Etag
  107. result.Result = film
  108. return gott.Tuple(args), err
  109. }
  110. func convertFilmDate(args ...interface{}) (interface{}, error) {
  111. result := args[1].(*network.Result)
  112. film := result.Result.(*Film)
  113. if film.Release_date_str != "" {
  114. date, err := time.Parse("2006-01-02", film.Release_date_str)
  115. film.Release_date = date
  116. result.Result = film
  117. return gott.Tuple(args), err
  118. }
  119. return gott.Tuple(args), nil
  120. }
  121. func createCollectionRequest(args ...interface{}) (interface{}, error) {
  122. request := args[0].(*network.Request)
  123. result := args[1].(*network.Result)
  124. result.Client = &http.Client{}
  125. httpRequest, err := http.NewRequest("GET", "https://api.themoviedb.org/3/collection/"+request.Id+"?api_key="+config.TmdbApiKey+"&language="+request.Language, nil)
  126. result.Request = httpRequest
  127. return gott.Tuple(args), err
  128. }
  129. func unmarshalCollection(args ...interface{}) (interface{}, error) {
  130. result := args[1].(*network.Result)
  131. collection := &Collection{}
  132. err := json.Unmarshal(result.Body, collection)
  133. result.Result = collection
  134. return gott.Tuple(args), err
  135. }
  136. func convertCollectionDates(args ...interface{}) (interface{}, error) {
  137. collection := args[1].(*network.Result).Result.(*Collection)
  138. for i, part := range collection.Parts {
  139. if part.Release_date_str != "" {
  140. date, err := time.Parse("2006-01-02", part.Release_date_str)
  141. if err != nil {
  142. return gott.Tuple(args), err
  143. }
  144. part.Release_date = date
  145. collection.Parts[i] = part
  146. }
  147. }
  148. return gott.Tuple(args), nil
  149. }
  150. func sortCollection(args ...interface{}) interface{} {
  151. collection := args[1].(*network.Result).Result.(*Collection)
  152. sort.Slice(collection.Parts, func(i, j int) bool {
  153. isBefore := collection.Parts[i].Release_date.Before(collection.Parts[j].Release_date)
  154. return (isBefore && !collection.Parts[i].Release_date.IsZero()) ||
  155. (!isBefore && collection.Parts[j].Release_date.IsZero())
  156. })
  157. return gott.Tuple(args)
  158. }
  159. func GetFilm(id, language string) (*Film, error) {
  160. film, err := gott.
  161. NewResult(gott.Tuple{&network.Request{Id: id, Language: language}, &network.Result{}}).
  162. Bind(createFilmRequest).
  163. Bind(getCacheEntry).
  164. Map(network.AddHeaders).
  165. Bind(network.DoRequest).
  166. Bind(network.HandleRequestError).
  167. Bind(network.ReadResponse).
  168. Tee(cleanCache).
  169. Tee(saveCacheEntry).
  170. Bind(unmarshalFilm).
  171. Bind(convertFilmDate).
  172. Finish()
  173. if err != nil {
  174. return &Film{}, err
  175. } else {
  176. return film.(gott.Tuple)[1].(*network.Result).Result.(*Film), nil
  177. }
  178. }
  179. func GetCollection(id, language string) (*Collection, error) {
  180. collection, err := gott.
  181. NewResult(gott.Tuple{&network.Request{Id: id, Language: language}, &network.Result{}}).
  182. Bind(createCollectionRequest).
  183. Bind(getCacheEntry).
  184. Map(network.AddHeaders).
  185. Bind(network.DoRequest).
  186. Bind(network.HandleRequestError).
  187. Bind(network.ReadResponse).
  188. Tee(cleanCache).
  189. Tee(saveCacheEntry).
  190. Bind(unmarshalCollection).
  191. Bind(convertCollectionDates).
  192. Map(sortCollection).
  193. Finish()
  194. if err != nil {
  195. return &Collection{}, err
  196. } else {
  197. return collection.(gott.Tuple)[1].(*network.Result).Result.(*Collection), nil
  198. }
  199. }