Author: Adam <git@apiote.tk>
skip specials by their codes not by number of them
db/db.go | 63 +++++++++++++++++++++++++++++++++++++-- libamuse/account.go | 74 +++++++++++++++++++++++++++++++++++++++------- libamuse/serie.go | 9 +++++ tmdb/serie.go | 51 ++++++++++++++++++++++----------
diff --git a/db/db.go b/db/db.go index 56174347af8520d35560cd2937cb5534ee90c5b1..5e68a6438645f4c74e84ecf318bc2f2fd5263a9c 100644 --- a/db/db.go +++ b/db/db.go @@ -373,7 +373,7 @@ return int(insertedRowsNumber - deletedRowsNumber), nil } -func SkipSpecials(username, itemId string, episodesNumber int, itemType datastructure.ItemType, datetime time.Time) (int, error) { +func SkipSpecials(username, itemId string, episodes []string, itemType datastructure.ItemType) (int, error) { db, err := sql.Open("sqlite3", utils.DataHome+"/amuse.db") if err != nil { fmt.Fprintf(os.Stderr, "DB open err\n") @@ -408,12 +408,11 @@ } modifiedRows := 0 - for e := 1; e <= episodesNumber; e++ { - episodeId := fmt.Sprintf("%s/S00E%02d", itemId, e) + for _, episodeId := range episodes { if watched[episodeId] > 0 { continue } - _, err = tx.Exec(`insert into experiences values(?, ?, ?, ?)`, username, itemType, episodeId, datetime) + _, err = tx.Exec(`insert into experiences values(?, ?, ?, ?)`, username, itemType, episodeId, "0001-01-01 00:00:00+00:00") if err != nil { if err.Error()[:6] != "UNIQUE" { fmt.Fprintf(os.Stderr, "Insert err %v\n", err) @@ -432,6 +431,62 @@ return 0, err } return modifiedRows, nil +} + +func ClearSpecials(username, itemId string, episodes []string, itemType datastructure.ItemType) error { + db, err := sql.Open("sqlite3", utils.DataHome+"/amuse.db") + if err != nil { + fmt.Fprintf(os.Stderr, "DB open err\n") + return err + } + defer db.Close() + + tx, err := db.Begin() + if err != nil { + fmt.Fprintf(os.Stderr, "Transaction err %s\n", err) + return err + } + defer tx.Rollback() + + rows, err := tx.Query(`select item_id from experiences where item_type = ? and item_id like ? || '/S00E%' and username = ? and time = "0001-01-01 00:00:00+00:00"`, itemType, itemId, username) + if err != nil { + fmt.Fprintf(os.Stderr, "Select err %v\n", err) + return err + } + defer rows.Close() + + watched := []string{} + for rows.Next() { + var watchedId string + err := rows.Scan(&watchedId) + if err != nil { + fmt.Fprintf(os.Stderr, "Scan err %v\n", err) + return err + } + watched = append(watched, watchedId) + } + + seriesEpisodes := map[string]int{} + for _, episode := range episodes { + seriesEpisodes[episode]++ + } + + for _, episode := range watched { + if seriesEpisodes[episode] == 0 { + _, err = tx.Exec(`delete from experiences where item_type = ? and item_id = ? and username = ?`, itemType, episode, username) + if err != nil { + fmt.Fprintf(os.Stderr, "Delete err %v\n", err) + return err + } + } + } + + err = tx.Commit() + if err != nil { + fmt.Fprintf(os.Stderr, "Commit err %v\n", err) + return err + } + return nil } func AddToWantList(username, itemId string, itemType datastructure.ItemType) error { diff --git a/libamuse/account.go b/libamuse/account.go index bca7dc747063ebecbb74cb9d08878a2262e7ad44..9f4fdd2d7117a2f73aea4ce4e3047ecc00c57a9f 100644 --- a/libamuse/account.go +++ b/libamuse/account.go @@ -4,6 +4,7 @@ import ( "notabug.org/apiote/amuse/accounts" "notabug.org/apiote/amuse/datastructure" "notabug.org/apiote/amuse/db" + "notabug.org/apiote/amuse/tmdb" "errors" "fmt" @@ -80,6 +81,8 @@ Finish() if err == nil { args = arg.(gott.Tuple) } + default: + err = errors.New("Wrong ItemType: " + itemType) } return gott.Tuple(args), err } @@ -112,9 +115,17 @@ return err } +func splitItemId(args ...interface{}) interface{} { + data := args[0].(*RequestData) + itemId := args[3].(string) + id := strings.Split(itemId, "/") + data.id = id[0] + return gott.Tuple(args) +} + func parseExperienceDate(args ...interface{}) (interface{}, error) { result := args[1].(*Result) - datetime := args[3].(string) + datetime := args[4].(string) var t time.Time var err error = nil if datetime == "" { @@ -129,34 +140,51 @@ } t, err = time.ParseInLocation("2006-01-02T15:04:05", datetime, location) } t = t.In(time.UTC) - result.result = t + result.result2 = t + return gott.Tuple(args), err +} + +func getSpecials(args ...interface{}) (interface{}, error) { + itemId := args[3].(string) + var err error + + id := strings.Split(itemId, "/") + if len(id) > 1 && id[1][3] == 'A' { + arg, err := gott. + NewResult(gott.Tuple(args)). + Bind(getSeason0). + Finish() + if err == nil { + args = arg.(gott.Tuple) + } + } return gott.Tuple(args), err } func addToExperiences(args ...interface{}) (interface{}, error) { data := args[0].(*RequestData) result := args[1].(*Result) + t := result.result2.(time.Time) itemType := args[2].(string) - t := result.result.(time.Time) + itemId := args[3].(string) var ( err error = nil refs int ) - id := strings.Split(data.id, "/") + id := strings.Split(itemId, "/") if len(id) > 1 && id[1][3] == 'A' { - var episodesNumber int - _, err := fmt.Sscanf(id[1][4:], "%d", &episodesNumber) - if err != nil { - return gott.Tuple(args), err + serie := result.result.(*tmdb.TvSerie) + episodes := []string{} + for _, episode := range serie.Seasons[0].Episodes { + episodes = append(episodes, data.id+"/"+episode.Episode_code) } - refs, err = db.SkipSpecials(result.user.Username, id[0], episodesNumber, datastructure.ItemType(itemType), t) + refs, err = db.SkipSpecials(result.user.Username, id[0], episodes, datastructure.ItemType(itemType)) } else { refs, err = db.AddToExperiences(result.user.Username, data.id, datastructure.ItemType(itemType), t) } result.result2 = refs - data.id = id[0] if len(id) > 1 { return gott.Tuple(args), errors.New("Skip") } @@ -164,6 +192,25 @@ return gott.Tuple(args), err } +func clearSpecials(args ...interface{}) (interface{}, error) { + data := args[0].(*RequestData) + result := args[1].(*Result) + itemType := args[2].(string) + itemId := args[3].(string) + id := strings.Split(itemId, "/") + + var err error + if len(id) > 1 && id[1][3] == 'A' { + serie := result.result.(*tmdb.TvSerie) + episodes := []string{} + for _, episode := range serie.Seasons[0].Episodes { + episodes = append(episodes, data.id+"/"+episode.Episode_code) + } + err = db.ClearSpecials(result.user.Username, id[0], episodes, datastructure.ItemType(itemType)) + } + return gott.Tuple(args), err +} + func removeFromWantList(args ...interface{}) (interface{}, error) { data := args[0].(*RequestData) result := args[1].(*Result) @@ -186,13 +233,16 @@ func AddToExperiences(username string, auth accounts.Authentication, itemId, itemType, datetime, language, mimetype string) error { auth.Necessary = true _, err := gott. - NewResult(gott.Tuple{&RequestData{id: itemId, language: language, mimetype: mimetype, auth: auth, username: username}, &Result{}, itemType, datetime}). + NewResult(gott.Tuple{&RequestData{language: language, mimetype: mimetype, auth: auth, username: username}, &Result{}, itemType, itemId, datetime}). + Map(splitItemId). Bind(parseLanguage). Bind(verifyToken). Bind(verifyUser). Bind(parseExperienceDate). + Bind(getItem). + Bind(getSpecials). + Bind(clearSpecials). Bind(addToExperiences). - Bind(getItem). Bind(cacheItem). Bind(removeFromWantList). Bind(removeCacheItem). diff --git a/libamuse/serie.go b/libamuse/serie.go index c3e4c9987a26369b2c855a64efdb0fd0d0c93a90..521d830267da953390b8db839e9c2667c9cac83e 100644 --- a/libamuse/serie.go +++ b/libamuse/serie.go @@ -37,6 +37,15 @@ tvSerie.Seasons = seasons return gott.Tuple(args), err } +func getSeason0(args ...interface{}) (interface{}, error) { + result := args[1].(*Result) + tvSerie := result.result.(*tmdb.TvSerie) + languages := result.languages + seasons, err := tmdb.GetSeason0(tvSerie, languages[0].String()) + tvSerie.Seasons = seasons + return gott.Tuple(args), err +} + func mergeCredits(args ...interface{}) (interface{}, error) { result := args[1].(*Result) mergedCast := map[string]tmdb.ShowCastEntry{} diff --git a/tmdb/serie.go b/tmdb/serie.go index 6c7528fd31239f054b0ce6baf7e7c1fead11a74e..dc33ebcef5bf1d6d597a06da72c04877119a7203 100644 --- a/tmdb/serie.go +++ b/tmdb/serie.go @@ -242,26 +242,45 @@ return serie.(gott.Tuple)[1].(*network.Result).Result.(*TvSerie), nil } } +func getSeason(serie *TvSerie, language string, seasonNumber int) (Season, error) { + seasonNumberS := strconv.FormatInt(int64(seasonNumber), 10) + s, err := gott. + NewResult(gott.Tuple{&network.Request{Id: serie.Id, Language: language, Subid: seasonNumberS}, &network.Result{}}). + Bind(createSeasonRequest). + Bind(getCacheEntry). + Map(network.AddHeaders). + Bind(network.DoRequest). + Bind(network.HandleRequestError). + Bind(network.ReadResponse). + Tee(cleanCache). + Tee(saveCacheEntry). + Bind(unmarshalSeason). + Bind(convertSeasonDates). + Finish() + season := *s.(gott.Tuple)[1].(*network.Result).Result.(*Season) + return season, err +} + +func GetSeason0(serie *TvSerie, language string) ([]Season, error) { + seasons := []Season{} + var ( + err error + season Season + ) + if serie.Seasons[0].Season_number == 0 { + season, err = getSeason(serie, language, 0) + seasons = append(seasons, season) + } + return seasons, err +} + func GetSeasons(serie *TvSerie, language string) ([]Season, error) { var err error var seasons []Season - for _, season := range serie.Seasons { - seasonNumber := strconv.FormatInt(int64(season.Season_number), 10) - s, err2 := gott. - NewResult(gott.Tuple{&network.Request{Id: serie.Id, Language: language, Subid: seasonNumber}, &network.Result{}}). - Bind(createSeasonRequest). - Bind(getCacheEntry). - Map(network.AddHeaders). - Bind(network.DoRequest). - Bind(network.HandleRequestError). - Bind(network.ReadResponse). - Tee(cleanCache). - Tee(saveCacheEntry). - Bind(unmarshalSeason). - Bind(convertSeasonDates). - Finish() + for _, serieSeason := range serie.Seasons { + season, err2 := getSeason(serie, language, serieSeason.Season_number) err = utils.Or(err, err2) - seasons = append(seasons, *s.(gott.Tuple)[1].(*network.Result).Result.(*Season)) + seasons = append(seasons, season) } return seasons, err }