package main import ( "context" "encoding/json" "fmt" "os" "sort" "strconv" "strings" "sync" "time" "github.com/daniwalter001/jackett_fiber/types" "github.com/gofiber/fiber/v2" "github.com/joho/godotenv" ) func main() { enc := json.NewEncoder(os.Stdout) enc.SetEscapeHTML(false) ctx := context.Background() errDot := godotenv.Load("./.env") if errDot != nil { fmt.Println("Error loading .env file") } fmt.Printf("Creating... %t\n", createIfNotExist("./temp")) fmt.Printf("Creating... %t\n", createIfNotExist("./persistence")) //create redis client instance rdClient := RedisClient() status, errS := rdClient.Ping(ctx).Result() if errS != nil { fmt.Print("Error: ") fmt.Println(errS.Error()) } else { fmt.Print("OK redis: ") fmt.Println(status) } app := fiber.New() app.Get("/", func(c *fiber.Ctx) error { return c.Status(200).SendString("Working") }) app.Get("/manifest.json", func(c *fiber.Ctx) error { a := types.StreamManifest{ID: "strem.go.nyaa", Description: "Random Golang version on stremio Addon", Name: "GoDon Nyaa 2", Resources: []string{"stream"}, Version: "1.0.1", Types: []string{"movie", "series", "anime"}, Logo: "https://upload.wikimedia.org/wikipedia/commons/2/23/Golang.png", IdPrefixes: []string{"tt", "kitsu"}, Catalogs: []string{}} u, err := json.Marshal(a) if err != nil { return c.SendStatus(fiber.StatusOK) } c.Set("Access-Control-Allow-Origin", "*") c.Set("Access-Control-Allow-Headers", "*") c.Set("Content-Type", "application/json") return c.Status(fiber.StatusOK).SendString(string(u)) }) app.Get("/stream/:type/:id.json", func(c *fiber.Ctx) error { c.Set("Access-Control-Allow-Origin", "*") c.Set("Access-Control-Allow-Headers", "*") c.Set("Content-Type", "application/json") fmt.Printf("Id: %s\n", c.Params("id")) fmt.Printf("Type: %s\n", c.Params("type")) var s, e, abs_season, abs_episode int var tt string abs := "false" id := c.Params("id") id = strings.ReplaceAll(id, "%3A", ":") //Reading the cache streams, err := rdClient.JSONGet(ctx, id, "$").Result() if err == nil && streams != "" { fmt.Printf("Sending that %s shit from cache\n", id) var cachedStreams []types.StreamMeta errJson := json.Unmarshal([]byte(streams), &cachedStreams) if errJson != nil { fmt.Println(errJson) return c.Status(fiber.StatusNotFound).SendString("lol") } else if len(cachedStreams) > 0 { fmt.Printf("Sent %s from cache \n", id) return c.Status(fiber.StatusOK).JSON(cachedStreams[len(cachedStreams)-1]) } } type_ := c.Params("type") var tmp []string if strings.Contains(id, "kitsu") { tmp = getImdbFromKitsu(id) } else { tmp = strings.Split(id, ":") } fmt.Println(tmp) tt = tmp[0] if len(tmp) > 1 { s, _ = strconv.Atoi(tmp[1]) e, _ = strconv.Atoi(tmp[2]) if len(tmp) > 3 { abs_season, _ = strconv.Atoi(tmp[3]) abs_episode, _ = strconv.Atoi(tmp[4]) abs = tmp[5] } } name, year := getMeta(tt, type_) var results []types.ItemsParsed wg := sync.WaitGroup{} l := 5 if type_ == "series" { if abs == "true" { l = l + 2 } if s == 1 { l = l + 2 } } else if type_ == "movie" { l = 2 } fmt.Printf("Requests: %d\n", l) wg.Add(l) //========================================================= if type_ == "movie" { go func() { defer wg.Done() results = append(results, fetchTorrent(fmt.Sprintf("%s %s", simplifiedName(name), year), type_)...) }() go func() { defer wg.Done() results = append(results, fetchTorrent(fmt.Sprintf("%s %s", name, year), type_)...) }() } else { go func() { defer wg.Done() results = append(results, fetchTorrent(fmt.Sprintf("%s S%02d", simplifiedName(name), s), type_)...) }() go func() { defer wg.Done() results = append(results, fetchTorrent(fmt.Sprintf("%s batch", simplifiedName(name)), type_)...) }() go func() { defer wg.Done() results = append(results, fetchTorrent(fmt.Sprintf("%s complet", simplifiedName(name)), type_)...) }() go func() { defer wg.Done() results = append(results, fetchTorrent(fmt.Sprintf("%s S%02dE%02d", simplifiedName(name), s, e), type_)...) }() go func() { defer wg.Done() results = append(results, fetchTorrent(fmt.Sprintf("%s S%02dE%02d", name, s, e), type_)...) }() if s == 1 { go func() { defer wg.Done() results = append(results, fetchTorrent(fmt.Sprintf("%s E%02d", simplifiedName(name), e), type_)...) }() go func() { defer wg.Done() results = append(results, fetchTorrent(fmt.Sprintf("%s %02d", simplifiedName(name), e), type_)...) }() } if abs == "true" { go func() { defer wg.Done() results = append(results, fetchTorrent(fmt.Sprintf("%s E%03d", simplifiedName(name), abs_episode), type_)...) }() go func() { defer wg.Done() results = append(results, fetchTorrent(fmt.Sprintf("%s %03d", simplifiedName(name), abs_episode), type_)...) }() } } //========================================================= wg.Wait() sort.Slice(results, func(i, j int) bool { iv, _ := strconv.Atoi(results[i].Peers) jv, _ := strconv.Atoi(results[j].Peers) return iv > jv }) results = removeDuplicates(results) fmt.Printf("Results:%d\n", len(results)) maxRes, _ := strconv.Atoi(os.Getenv("MAX_RES")) if len(results) > maxRes { results = results[:maxRes] } // for index, el := range results { // fmt.Printf("%d. %s => %s\n", index, el.MagnetURI, el.Seeders) // } fmt.Printf("Retenus:%d\n", len(results)) var parsedTorrentFiles []types.ItemsParsed wg = sync.WaitGroup{} wg.Add(len(results)) for i := 0; i < len(results); i++ { go func(item types.ItemsParsed) { defer wg.Done() r := item if strings.Contains(item.MagnetURI, "magnet:?xt") { r = readTorrentFromMagnet(item) } else { r = readTorrent(item) } if len(r.TorrentData) != 0 { parsedTorrentFiles = append(parsedTorrentFiles, r) } }(results[i]) } wg.Wait() var parsedSuitableTorrentFiles []types.TorrentFile // var parsedSuitableTorrentFilesIndex = make([]int, len(parsedTorrentFiles)) var parsedSuitableTorrentFilesIndex = make(map[string]int, 0) for index, el := range parsedTorrentFiles { parsedSuitableTorrentFiles = make([]types.TorrentFile, 0) for _index, ell := range el.TorrentData { lower := strings.ToLower(ell.Name) if !isVideo(ell.Name) { continue } if type_ == "movie" { parsedSuitableTorrentFiles = append(parsedSuitableTorrentFiles, ell) parsedSuitableTorrentFilesIndex[ell.Name] = _index + 1 break } else { if isVideo(ell.Name) && (containEandS(lower, strconv.Itoa(s), strconv.Itoa(e), abs == "true", strconv.Itoa(abs_season), strconv.Itoa(abs_episode)) || containE_S(lower, strconv.Itoa(s), strconv.Itoa(e), abs == "true", strconv.Itoa(abs_season), strconv.Itoa(abs_episode)) || (s == 1 && (containsAbsoluteE(lower, strconv.Itoa(s), strconv.Itoa(e), true, strconv.Itoa(s), strconv.Itoa(e)) || containsAbsoluteE_(lower, strconv.Itoa(s), strconv.Itoa(e), true, strconv.Itoa(s), strconv.Itoa(e)))) || // false || (((abs == "true" && containsAbsoluteE(lower, strconv.Itoa(s), strconv.Itoa(e), true, strconv.Itoa(abs_season), strconv.Itoa(abs_episode))) || (abs == "true" && containsAbsoluteE_(lower, strconv.Itoa(s), strconv.Itoa(e), true, strconv.Itoa(abs_season), strconv.Itoa(abs_episode)))) && !(strings.Contains(lower, "s0") && strings.Contains(lower, "e0") && strings.Contains(lower, "season") && strings.Contains(lower, fmt.Sprintf("s%d", abs_season)) && strings.Contains(lower, fmt.Sprintf("e%d", abs_episode))))) { parsedSuitableTorrentFiles = append(parsedSuitableTorrentFiles, ell) parsedSuitableTorrentFilesIndex[ell.Name] = _index + 1 break } } } parsedTorrentFiles[index].TorrentData = parsedSuitableTorrentFiles } var ttttt types.StreamMeta parsedTorrentFiles = filter[types.ItemsParsed](parsedTorrentFiles, func(ip types.ItemsParsed) bool { return len(ip.TorrentData) != 0 }) fmt.Printf("Response %d\n", len(parsedTorrentFiles)) fmt.Println("Parsing that shit") wg = sync.WaitGroup{} wg.Add(len(parsedTorrentFiles)) for _, el := range parsedTorrentFiles { go func(item types.ItemsParsed) { defer wg.Done() for _, ell := range el.TorrentData { fmt.Println(ell.Name) if !isVideo(ell.Name) { continue } // ==========================No RD ============================= fmt.Printf("Bypassing RD...\n") announceList := append(ell.AnnounceList, fmt.Sprintf("dht:%s", ell.InfoHash)) ttttt.Streams = append(ttttt.Streams, types.TorrentStreams{Title: fmt.Sprintf("%s\n%s\n%s | %s", ell.TorrentName, ell.Name, getQuality(ell.Name), getSize(int(ell.Length))), Name: fmt.Sprintf("%s\n S:%s, P:%s", item.Tracker, item.Seeders, item.Peers), Type: type_, InfoHash: ell.InfoHash, Sources: announceList, BehaviorHints: types.BehaviorHints{BingeGroup: fmt.Sprintf("Jackett|%s", ell.InfoHash), NotWebReady: true}, FileIdx: parsedSuitableTorrentFilesIndex[ell.Name] - 1}) } }(el) } wg.Wait() if len(ttttt.Streams) > 0 { jsonBytes, errttt := json.Marshal(ttttt) if errttt == nil { _, errrrr := rdClient.JSONSet(ctx, id, "$", jsonBytes).Result() if errrrr == nil { rdClient.Expire(ctx, id, time.Hour*24*7).Result() } } } fmt.Println("Sending that shit") return c.Status(fiber.StatusOK).JSON(ttttt) }) port := "3000" if os.Getenv("PORT") != "" { port = os.Getenv("PORT") } app.Listen(fmt.Sprintf(":%s", port)) }