Пример #1
0
func ShowEpisodes(ctx *gin.Context) {
	showId, _ := strconv.Atoi(ctx.Params.ByName("showId"))
	seasonNumber, _ := strconv.Atoi(ctx.Params.ByName("season"))
	language := config.Get().Language
	show := tmdb.GetShow(showId, language)
	season := tmdb.GetSeason(showId, seasonNumber, language)
	items := season.Episodes.ToListItems(show, season)

	for _, item := range items {
		playUrl := UrlForXBMC("/show/%d/season/%d/episode/%d/play",
			show.Id,
			seasonNumber,
			item.Info.Episode,
		)
		episodeLinksUrl := UrlForXBMC("/show/%d/season/%d/episode/%d/links",
			show.Id,
			seasonNumber,
			item.Info.Episode,
		)
		if config.Get().ChooseStreamAuto == true {
			item.Path = playUrl
		} else {
			item.Path = episodeLinksUrl
		}
		item.ContextMenu = [][]string{
			[]string{"LOCALIZE[30202]", fmt.Sprintf("XBMC.PlayMedia(%s)", episodeLinksUrl)},
			[]string{"LOCALIZE[30023]", fmt.Sprintf("XBMC.PlayMedia(%s)", playUrl)},
			[]string{"LOCALIZE[30203]", "XBMC.Action(Info)"},
			[]string{"LOCALIZE[30037]", fmt.Sprintf("XBMC.RunPlugin(%s)", UrlForXBMC("/setviewmode/episodes"))},
		}
		item.IsPlayable = true
	}

	ctx.JSON(200, xbmc.NewView("episodes", items))
}
Пример #2
0
func MoviesMostVoted(ctx *gin.Context) {
	page := -1
	if config.Get().EnablePaging == true {
		currentpage, err := strconv.Atoi(ctx.DefaultQuery("page", "0"))
		if err == nil {
			page = currentpage
		}
	}
	renderMovies(tmdb.MostVotedMoviesComplete("", config.Get().Language, page), ctx, page)
}
Пример #3
0
func TopRatedShows(ctx *gin.Context) {
	page := -1
	if config.Get().EnablePagination == true {
		currentpage, err := strconv.Atoi(ctx.DefaultQuery("page", "0"))
		if err == nil {
			page = currentpage
		}
	}
	renderShows(tmdb.TopRatedShowsComplete("", config.Get().Language, page), ctx, page)
}
Пример #4
0
func TopRatedMovies(ctx *gin.Context) {
	genre := ctx.Params.ByName("genre")
	if genre == "0" {
		genre = ""
	}
	page := -1
	if config.Get().EnablePaging == true {
		currentpage, err := strconv.Atoi(ctx.DefaultQuery("page", "0"))
		if err == nil {
			page = currentpage
		}
	}
	renderMovies(tmdb.TopRatedMoviesComplete(genre, config.Get().Language, page), ctx, page)
}
Пример #5
0
func MakeQuasarRepositoryAddon() error {
	addonId := "repository.quasar"
	addonName := "Quasar Repository"

	quasarHost := fmt.Sprintf("http://localhost:%d", config.ListenPort)
	addon := &xbmc.Addon{
		Id:           addonId,
		Name:         addonName,
		Version:      util.Version,
		ProviderName: config.Get().Info.Author,
		Extensions: []*xbmc.AddonExtension{
			&xbmc.AddonExtension{
				Point: "xbmc.addon.repository",
				Name:  addonName,
				Info: &xbmc.AddonRepositoryInfo{
					Text:       quasarHost + "/repository/scakemyer/plugin.video.quasar/addons.xml",
					Compressed: false,
				},
				Checksum: quasarHost + "/repository/scakemyer/plugin.video.quasar/addons.xml.md5",
				Datadir: &xbmc.AddonRepositoryDataDir{
					Text: quasarHost + "/repository/scakemyer/",
					Zip:  true,
				},
			},
			&xbmc.AddonExtension{
				Point: "xbmc.addon.metadata",
				Summaries: []*xbmc.AddonText{
					&xbmc.AddonText{"GitHub repository for Quasar Updates", "en"},
				},
				Platform: "all",
			},
		},
	}

	addonPath := filepath.Clean(filepath.Join(config.Get().Info.Path, "..", addonId))
	if err := os.MkdirAll(addonPath, 0777); err != nil {
		return err
	}

	if err := copyFile(filepath.Join(config.Get().Info.Path, "icon.png"), filepath.Join(addonPath, "icon.png")); err != nil {
		return err
	}

	addonXmlFile, err := os.Create(filepath.Join(addonPath, "addon.xml"))
	if err != nil {
		return err
	}
	defer addonXmlFile.Close()
	return xml.NewEncoder(addonXmlFile).Encode(addon)
}
Пример #6
0
func PlayShow(ctx *gin.Context) {
	if config.Get().ChooseStreamAuto == true {
		ShowEpisodePlay(ctx)
	} else {
		ShowEpisodeLinks(ctx)
	}
}
Пример #7
0
func RemoveShow(ctx *gin.Context) {
	LibraryPath := config.Get().LibraryPath
	ShowsLibraryPath := filepath.Join(LibraryPath, "Shows")
	DBPath := filepath.Join(LibraryPath, fmt.Sprintf("%s.json", DBName))
	showId := ctx.Params.ByName("showId")
	show, err := tvdb.NewShow(showId, "en")
	if err != nil {
		ctx.String(404, "")
		return
	}
	ShowPath := filepath.Join(ShowsLibraryPath, toFileName(show.SeriesName))

	if err := RemoveFromJsonDB(DBPath, showId, LShow); err != nil {
		libraryLog.Info("Unable to remove show from db")
		ctx.String(404, "")
		return
	}

	if err := os.RemoveAll(ShowPath); err != nil {
		libraryLog.Info("Unable to remove show folder")
		ctx.String(404, "")
		return
	}

	xbmc.Notify("Quasar", "LOCALIZE[30222]", config.AddonIcon())
	ctx.String(200, "")
	xbmc.VideoLibraryClean()
	libraryLog.Info("Show removed")
}
Пример #8
0
func PlayMovie(ctx *gin.Context) {
	if config.Get().ChooseStreamAuto == true {
		MoviePlay(ctx)
	} else {
		MovieLinks(ctx)
	}
}
Пример #9
0
func CheckApiKey() {
	tmdbLog.Info("Checking TMDB API key...")

	customApiKey := config.Get().TMDBApiKey
	if customApiKey != "" {
		apiKeys = append(apiKeys, customApiKey)
		apiKey = customApiKey
	}

	result := false
	for index := len(apiKeys); index >= 0; index-- {
		result = tmdbCheck(apiKey)
		if result {
			tmdbLog.Noticef("TMDB API key check passed, using %s...", apiKey[:7])
			break
		} else {
			tmdbLog.Warningf("TMDB API key failed: %s", apiKey)
			if apiKey == apiKeys[index] {
				apiKeys = append(apiKeys[:index], apiKeys[index+1:]...)
			}
			apiKey = apiKeys[rand.Int()%len(apiKeys)]
		}
	}
	if result == false {
		tmdbLog.Error("No valid TMDB API key found")
	}
}
Пример #10
0
func GetCount(ctx *gin.Context) {
	LibraryPath := config.Get().LibraryPath
	DBPath := filepath.Join(LibraryPath, fmt.Sprintf("%s.json", DBName))
	var db DataBase

	if _, err := os.Stat(DBPath); err == nil {
		file, err := ioutil.ReadFile(DBPath)
		if err != nil {
			ctx.Writer.Header().Set("Access-Control-Allow-Origin", "*")
			ctx.JSON(200, gin.H{
				"success": false,
			})
			return
		}
		json.Unmarshal(file, &db)
	}

	ctx.Writer.Header().Set("Access-Control-Allow-Origin", "*")
	ctx.JSON(200, gin.H{
		"success": true,
		"movies":  len(db.Movies),
		"shows":   len(db.Shows),
		"total":   len(db.Movies) + len(db.Shows),
	})
}
Пример #11
0
func GetSurgeClearances() {
	header := http.Header{
		"Content-type": []string{"application/json"},
	}
	params := napping.Params{}.AsUrlValues()

	req := napping.Request{
		Url:    fmt.Sprintf("%s/%s", "https://cloudhole.surge.sh", "cloudhole.json"),
		Method: "GET",
		Params: &params,
		Header: &header,
	}

	resp, err := napping.Send(&req)

	var tmpClearances []*Clearance
	if err == nil && resp.Status() == 200 {
		resp.Unmarshal(&tmpClearances)
	}

	apiKey := config.Get().CloudHoleKey
	for _, clearance := range tmpClearances {
		if clearance.Key == apiKey {
			clearances = append(clearances, clearance)
		}
	}
}
Пример #12
0
func getMovieById(movieId string, language string) *Movie {
	var movie *Movie
	cacheStore := cache.NewFileStore(path.Join(config.Get().ProfilePath, "cache"))
	key := fmt.Sprintf("com.tmdb.movie.%s.%s", movieId, language)
	if err := cacheStore.Get(key, &movie); err != nil {
		rateLimiter.Call(func() {
			urlValues := napping.Params{
				"api_key":            apiKey,
				"append_to_response": "credits,images,alternative_titles,translations,external_ids,trailers",
				"language":           language,
			}.AsUrlValues()
			napping.Get(
				tmdbEndpoint+"movie/"+movieId,
				&urlValues,
				&movie,
				nil,
			)
			if movie != nil {
				cacheStore.Set(key, movie, cacheTime)
			}
		})
	}
	if movie == nil {
		return nil
	}
	switch t := movie.RawPopularity.(type) {
	case string:
		popularity, _ := strconv.ParseFloat(t, 64)
		movie.Popularity = popularity
	case float64:
		movie.Popularity = t
	}
	return movie
}
Пример #13
0
func SearchMovies(query string, page string) (movies []*Movies, err error) {
	endPoint := "search"

	params := napping.Params{
		"page": page,
		"limit": strconv.Itoa(config.Get().ResultsPerPage),
		"query": query,
		"extended": "full,images",
	}.AsUrlValues()

	resp, err := Get(endPoint, params)

	if err != nil {
		return movies, err
	} else if resp.Status() != 200 {
		return movies, errors.New(fmt.Sprintf("SearchMovies bad status: %d", resp.Status()))
	}

  // TODO use response headers for pagination limits:
  // X-Pagination-Page-Count:10
  // X-Pagination-Item-Count:100

	resp.Unmarshal(&movies)
	return movies, err
}
Пример #14
0
func Play(btService *bittorrent.BTService) gin.HandlerFunc {
	return func(ctx *gin.Context) {
		uri := ctx.Request.URL.Query().Get("uri")
		if uri == "" {
			return
		}
		fileIndex := -1
		index := ctx.Request.URL.Query().Get("index")
		if index != "" {
			fIndex, err := strconv.Atoi(index)
			if err == nil {
				fileIndex = fIndex
			}
		}
		torrent := bittorrent.NewTorrent(uri)
		magnet := torrent.Magnet()
		boosters := url.Values{
			"tr": providers.DefaultTrackers,
		}
		magnet += "&" + boosters.Encode()
		player := bittorrent.NewBTPlayer(btService, magnet, config.Get().KeepFilesAfterStop == false, fileIndex)
		if player.Buffer() != nil {
			return
		}
		hostname := "localhost"
		if localIP, err := util.LocalIP(); err == nil {
			hostname = localIP.String()
		}
		rUrl, _ := url.Parse(fmt.Sprintf("http://%s:%d/files/%s", hostname, config.ListenPort, player.PlayURL()))
		ctx.Redirect(302, rUrl.String())
	}
}
Пример #15
0
func TopShows(topCategory string, page string) (shows []*Shows, err error) {
	endPoint := "shows/" + topCategory

	params := napping.Params{
		"page":     page,
		"limit":    strconv.Itoa(config.Get().ResultsPerPage),
		"extended": "full,images",
	}.AsUrlValues()

	resp, err := Get(endPoint, params)

	if err != nil {
		return shows, err
	} else if resp.Status() != 200 {
		return shows, errors.New(fmt.Sprintf("TopShows bad status: %d", resp.Status()))
	}

	if topCategory == "popular" {
		var showList []*Show
		resp.Unmarshal(&showList)

		showListing := make([]*Shows, 0)
		for _, show := range showList {
			showItem := Shows{
				Show: show,
			}
			showListing = append(showListing, &showItem)
		}
		shows = showListing
	} else {
		resp.Unmarshal(&shows)
	}
	return shows, err
}
Пример #16
0
func Post(endPoint string, payload *bytes.Buffer) (resp *napping.Response, err error) {
	header := http.Header{
		"Content-type":      []string{"application/json"},
		"Authorization":     []string{fmt.Sprintf("Bearer %s", config.Get().TraktToken)},
		"trakt-api-key":     []string{ClientId},
		"trakt-api-version": []string{ApiVersion},
		"User-Agent":        []string{clearance.UserAgent},
		"Cookie":            []string{clearance.Cookies},
	}

	req := napping.Request{
		Url:        fmt.Sprintf("%s/%s", ApiUrl, endPoint),
		Method:     "POST",
		RawPayload: true,
		Payload:    payload,
		Header:     &header,
	}

	resp, err = napping.Send(&req)
	if err == nil && resp.Status() == 403 && retries < 3 {
		retries += 1
		err = newClearance()
		if err == nil {
			resp, err = Post(endPoint, payload)
		}
	}

	return resp, err
}
Пример #17
0
func GetWithAuth(endPoint string, params url.Values) (resp *napping.Response, err error) {
	header := http.Header{
		"Content-type":      []string{"application/json"},
		"Authorization":     []string{fmt.Sprintf("Bearer %s", config.Get().TraktToken)},
		"trakt-api-key":     []string{ClientId},
		"trakt-api-version": []string{ApiVersion},
		"User-Agent":        []string{clearance.UserAgent},
		"Cookie":            []string{clearance.Cookies},
	}

	req := napping.Request{
		Url:    fmt.Sprintf("%s/%s", ApiUrl, endPoint),
		Method: "GET",
		Params: &params,
		Header: &header,
	}

	resp, err = napping.Send(&req)
	if err == nil && resp.Status() == 403 && retries < 3 {
		retries += 1
		err = newClearance()
		if err == nil {
			resp, err = GetWithAuth(endPoint, params)
		}
	}

	return resp, err
}
Пример #18
0
func GetShow(showId int, language string) *Show {
	var show *Show
	cacheStore := cache.NewFileStore(path.Join(config.Get().ProfilePath, "cache"))
	key := fmt.Sprintf("com.tmdb.show.%d.%s", showId, language)
	if err := cacheStore.Get(key, &show); err != nil {
		rateLimiter.Call(func() {
			urlValues := napping.Params{
				"api_key":            apiKey,
				"append_to_response": "credits,images,alternative_titles,translations,external_ids",
				"language":           language,
			}.AsUrlValues()
			napping.Get(
				tmdbEndpoint+"tv/"+strconv.Itoa(showId),
				&urlValues,
				&show,
				nil,
			)
		})
		if show != nil {
			cacheStore.Set(key, show, cacheTime)
		}
	}
	if show == nil {
		return nil
	}
	switch t := show.RawPopularity.(type) {
	case string:
		if popularity, err := strconv.ParseFloat(t, 64); err == nil {
			show.Popularity = popularity
		}
	case float64:
		show.Popularity = t
	}
	return show
}
Пример #19
0
func TVIndex(ctx *gin.Context) {
	items := xbmc.ListItems{
		{Label: "LOCALIZE[30209]", Path: UrlForXBMC("/shows/search"), Thumbnail: config.AddonResource("img", "search.png")},
		{Label: "LOCALIZE[30056]", Path: UrlForXBMC("/shows/trakt/"), Thumbnail: config.AddonResource("img", "trakt.png")},
		{Label: "LOCALIZE[30238]", Path: UrlForXBMC("/shows/recent/episodes"), Thumbnail: config.AddonResource("img", "fresh.png")},
		{Label: "LOCALIZE[30237]", Path: UrlForXBMC("/shows/recent/shows"), Thumbnail: config.AddonResource("img", "clock.png")},
		{Label: "LOCALIZE[30210]", Path: UrlForXBMC("/shows/popular"), Thumbnail: config.AddonResource("img", "popular.png")},
		{Label: "LOCALIZE[30211]", Path: UrlForXBMC("/shows/top"), Thumbnail: config.AddonResource("img", "top_rated.png")},
		{Label: "LOCALIZE[30212]", Path: UrlForXBMC("/shows/mostvoted"), Thumbnail: config.AddonResource("img", "most_voted.png")},
	}
	for _, genre := range tmdb.GetTVGenres(config.Get().Language) {
		slug, _ := genreSlugs[genre.Id]
		items = append(items, &xbmc.ListItem{
			Label:     genre.Name,
			Path:      UrlForXBMC("/shows/popular/%s", strconv.Itoa(genre.Id)),
			Thumbnail: config.AddonResource("img", fmt.Sprintf("genre_%s.png", slug)),
			ContextMenu: [][]string{
				[]string{"LOCALIZE[30237]", fmt.Sprintf("Container.Update(%s)", UrlForXBMC("/shows/recent/shows/%s", strconv.Itoa(genre.Id)))},
				[]string{"LOCALIZE[30238]", fmt.Sprintf("Container.Update(%s)", UrlForXBMC("/shows/recent/episodes/%s", strconv.Itoa(genre.Id)))},
			},
		})
	}

	ctx.JSON(200, xbmc.NewView("", items))
}
Пример #20
0
func Find(externalId string, externalSource string) *FindResult {
	var result *FindResult

	cacheStore := cache.NewFileStore(path.Join(config.Get().ProfilePath, "cache"))
	key := fmt.Sprintf("com.tmdb.find.%s.%s", externalSource, externalId)
	if err := cacheStore.Get(key, &result); err != nil {
		rateLimiter.Call(func() {
			urlValues := napping.Params{
				"api_key":         apiKey,
				"external_source": externalSource,
			}.AsUrlValues()
			resp, err := napping.Get(
				tmdbEndpoint+"find/"+externalId,
				&urlValues,
				&result,
				nil,
			)
			if err != nil {
				panic(err)
			}
			if resp.Status() != 200 {
				panic(errors.New(fmt.Sprintf("Bad status: %d", resp.Status())))
			}
			cacheStore.Set(key, result, 365*24*time.Hour)
		})
	}

	return result
}
Пример #21
0
func GetSeason(showId int, seasonNumber int, language string) *Season {
	var season *Season
	cacheStore := cache.NewFileStore(path.Join(config.Get().ProfilePath, "cache"))
	key := fmt.Sprintf("com.tmdb.season.%d.%d.%s", showId, seasonNumber, language)
	if err := cacheStore.Get(key, &season); err != nil {
		rateLimiter.Call(func() {
			urlValues := napping.Params{
				"api_key":            apiKey,
				"append_to_response": "credits,images,videos,external_ids",
				"language":           language,
			}.AsUrlValues()
			resp, err := napping.Get(
				fmt.Sprintf("%stv/%d/season/%d", tmdbEndpoint, showId, seasonNumber),
				&urlValues,
				&season,
				nil,
			)
			if err != nil {
				panic(err)
			}
			if resp.Status() != 200 {
				panic(errors.New(fmt.Sprintf("Bad status: %d", resp.Status())))
			}
		})
		season.EpisodeCount = len(season.Episodes)
		if season != nil {
			cacheStore.Set(key, season, cacheTime)
		}
	}
	if season == nil {
		return nil
	}
	return season
}
Пример #22
0
func InJsonDB(ID string, ltype int) (bool, error) {
	var db DataBase
	LibraryPath := config.Get().LibraryPath
	DBPath := filepath.Join(LibraryPath, fmt.Sprintf("%s.json", DBName))

	if _, err := os.Stat(DBPath); err == nil {
		file, err := ioutil.ReadFile(DBPath)
		if err != nil {
			return false, err
		}
		json.Unmarshal(file, &db)
	}

	if ltype == LMovie {
		for _, movieId := range db.Movies {
			if movieId == ID {
				return true, nil
			}
		}
	} else if ltype == LShow {
		for _, showId := range db.Shows {
			if showId == ID {
				return true, nil
			}
		}
	} else {
		return false, fmt.Errorf("Unknown content type")
	}

	return false, nil
}
Пример #23
0
func GetList(listId string, language string, page int) Movies {
	var results *List
	listResultsPerPage := config.Get().ResultsPerPage

	rateLimiter.Call(func() {
		urlValues := napping.Params{
			"api_key": apiKey,
		}.AsUrlValues()
		resp, err := napping.Get(
			tmdbEndpoint+"list/"+listId,
			&urlValues,
			&results,
			nil,
		)
		if err != nil {
			log.Error(err.Error())
			xbmc.Notify("Quasar", "GetList failed, check your logs.", config.AddonIcon())
		} else if resp.Status() != 200 {
			message := fmt.Sprintf("GetList bad status: %d", resp.Status())
			log.Error(message)
			xbmc.Notify("Quasar", message, config.AddonIcon())
		}
	})
	tmdbIds := make([]int, 0, listResultsPerPage)
	for i, movie := range results.Items {
		if i < page*listResultsPerPage {
			continue
		}
		tmdbIds = append(tmdbIds, movie.Id)
		if i >= (startPage+page)*listResultsPerPage-1 {
			break
		}
	}
	return GetMovies(tmdbIds, language)
}
Пример #24
0
func TopMovies(topCategory string, page string) (movies []*Movies, err error) {
	endPoint := "movies/" + topCategory

	params := napping.Params{
		"page": page,
		"limit": strconv.Itoa(config.Get().ResultsPerPage),
		"extended": "full,images",
	}.AsUrlValues()

	resp, err := Get(endPoint, params)

	if err != nil {
		return movies, err
	} else if resp.Status() != 200 {
		return movies, errors.New(fmt.Sprintf("TopMovies bad status: %d", resp.Status()))
	}

	if topCategory == "popular" {
		var movieList []*Movie
		resp.Unmarshal(&movieList)

	  movieListing := make([]*Movies, 0)
	  for _, movie := range movieList {
			movieItem := Movies{
	      Movie: movie,
	    }
	    movieListing = append(movieListing, &movieItem)
	  }
		movies = movieListing
	} else {
		resp.Unmarshal(&movies)
	}
	return movies, err
}
Пример #25
0
func RemoveShow(ctx *gin.Context) {
	LibraryPath := config.Get().LibraryPath
	ShowsLibraryPath := filepath.Join(LibraryPath, "Shows")
	DBPath := filepath.Join(LibraryPath, fmt.Sprintf("%s.json", DBName))
	showId := ctx.Params.ByName("showId")
	Id, _ := strconv.Atoi(showId)
	show := tmdb.GetShow(Id, "en")
	if show == nil {
		ctx.String(404, "")
		return
	}
	ShowStrm := toFileName(fmt.Sprintf("%s (%s)", show.Name, strings.Split(show.FirstAirDate, "-")[0]))
	ShowPath := filepath.Join(ShowsLibraryPath, ShowStrm)

	if err := RemoveFromJsonDB(DBPath, showId, LShow); err != nil {
		libraryLog.Error("Unable to remove show from db")
		ctx.String(404, "")
		return
	}

	if err := os.RemoveAll(ShowPath); err != nil {
		libraryLog.Error("Unable to remove show folder")
		ctx.String(404, "")
		return
	}

	xbmc.Notify("Quasar", "LOCALIZE[30222]", config.AddonIcon())
	ctx.String(200, "")
	xbmc.VideoLibraryClean()
	ClearCache(ctx)
	xbmc.Refresh()
	libraryLog.Notice("Show removed")
}
Пример #26
0
func Lookup(ctx *gin.Context) {
	var db DataBase

	LibraryPath := config.Get().LibraryPath
	DBPath := filepath.Join(LibraryPath, fmt.Sprintf("%s.json", DBName))

	if _, err := os.Stat(DBPath); err == nil {
		file, err := ioutil.ReadFile(DBPath)
		if err != nil {
			ctx.Writer.Header().Set("Access-Control-Allow-Origin", "*")
			ctx.JSON(200, gin.H{
				"success": false,
			})
			return
		}
		json.Unmarshal(file, &db)
	}

	Movies := make([]*Item, 0, len(db.Movies))
	Shows := make([]*Item, 0, len(db.Shows))

	for i := 0; i < len(db.Movies); i++ {
		movie := tmdb.GetMovieById(db.Movies[i], "en")
		Movies = append(Movies, &Item{
			Id:       db.Movies[i],
			Title:    movie.OriginalTitle,
			Year:     strings.Split(movie.ReleaseDate, "-")[0],
			Overview: movie.Overview,
			Poster:   tmdb.ImageURL(movie.PosterPath, "w500"),
		})
	}

	for i := 0; i < len(db.Shows); i++ {
		showId, _ := strconv.Atoi(db.Shows[i])
		show := tmdb.GetShow(showId, "en")
		if show == nil {
			ctx.Writer.Header().Set("Access-Control-Allow-Origin", "*")
			ctx.JSON(200, gin.H{
				"success": false,
			})
			return
		}
		Shows = append(Shows, &Item{
			Id:       db.Shows[i],
			Title:    show.Name,
			Year:     strings.Split(show.FirstAirDate, "-")[0],
			Overview: show.Overview,
			Poster:   tmdb.ImageURL(show.PosterPath, "w500"),
		})
	}

	ctx.Writer.Header().Set("Access-Control-Allow-Origin", "*")
	ctx.JSON(200, gin.H{
		"success": true,
		"results": gin.H{
			"movies": Movies,
			"shows":  Shows,
		},
	})
}
Пример #27
0
func RemoveMovie(ctx *gin.Context) {
	LibraryPath := config.Get().LibraryPath
	MoviesLibraryPath := filepath.Join(LibraryPath, "Movies")
	DBPath := filepath.Join(LibraryPath, fmt.Sprintf("%s.json", DBName))
	imdbId := ctx.Params.ByName("imdbId")
	movie := tmdb.GetMovieFromIMDB(imdbId, "en")
	MovieStrm := toFileName(fmt.Sprintf("%s (%s)", movie.OriginalTitle, strings.Split(movie.ReleaseDate, "-")[0]))
	MoviePath := filepath.Join(MoviesLibraryPath, MovieStrm)

	if err := RemoveFromJsonDB(DBPath, imdbId, LMovie); err != nil {
		libraryLog.Info("Unable to remove movie from db")
		ctx.String(404, "")
		return
	}

	if err := os.RemoveAll(MoviePath); err != nil {
		libraryLog.Info("Unable to remove movie folder")
		ctx.String(404, "")
		return
	}

	xbmc.Notify("Quasar", "LOCALIZE[30222]", config.AddonIcon())
	ctx.String(200, "")
	xbmc.VideoLibraryClean()
	libraryLog.Info("Movie removed")
}
Пример #28
0
func (as *AddonSearcher) call(method string, searchObject interface{}) []*bittorrent.Torrent {
	torrents := make([]*bittorrent.Torrent, 0)
	cid, c := GetCallback()
	cbUrl := fmt.Sprintf("%s/callbacks/%s", util.GetHTTPHost(), cid)

	payload := &SearchPayload{
		Method:       method,
		CallbackURL:  cbUrl,
		SearchObject: searchObject,
	}

	xbmc.ExecuteAddon(as.addonId, payload.String())

	timeout := providerTimeout()
	conf := config.Get()
	if conf.CustomProviderTimeoutEnabled == true {
		timeout = time.Duration(conf.CustomProviderTimeout) * time.Second
	}

	select {
	case <-time.After(timeout):
		as.log.Info("Provider %s was too slow. Ignored.", as.addonId)
		RemoveCallback(cid)
	case result := <-c:
		json.Unmarshal(result, &torrents)
	}

	return torrents
}
Пример #29
0
func Find(externalId string, externalSource string) *FindResult {
	var result *FindResult

	cacheStore := cache.NewFileStore(path.Join(config.Get().ProfilePath, "cache"))
	key := fmt.Sprintf("com.tmdb.find.%s.%s", externalSource, externalId)
	if err := cacheStore.Get(key, &result); err != nil {
		rateLimiter.Call(func() {
			urlValues := napping.Params{
				"api_key":         apiKey,
				"external_source": externalSource,
			}.AsUrlValues()
			resp, err := napping.Get(
				tmdbEndpoint+"find/"+externalId,
				&urlValues,
				&result,
				nil,
			)
			if err != nil {
				log.Error(err.Error())
				xbmc.Notify("Quasar", "Failed Find call, check your logs.", config.AddonIcon())
			} else if resp.Status() != 200 {
				message := fmt.Sprintf("Find call bad status: %d", resp.Status())
				log.Error(message)
				xbmc.Notify("Quasar", message, config.AddonIcon())
			}
			cacheStore.Set(key, result, 365*24*time.Hour)
		})
	}

	return result
}
Пример #30
0
func TopRatedMovies(ctx *gin.Context) {
	genre := ctx.Params.ByName("genre")
	if genre == "0" {
		genre = ""
	}
	page, _ := strconv.Atoi(ctx.DefaultQuery("page", "0"))
	renderMovies(tmdb.TopRatedMovies(genre, config.Get().Language, page), ctx, page, "")
}