package tgbot import ( "fmt" "strconv" "strings" tele "gopkg.in/telebot.v4" "server/rutor" "server/rutor/models" sets "server/settings" "server/torznab" ) func cmdSearch(c tele.Context) error { if sets.BTsets == nil || (!sets.BTsets.EnableRutorSearch && !sets.BTsets.EnableTorznabSearch) { return c.Send(tr(c.Sender().ID, "search_disabled_rutor")) } args := c.Args() if len(args) == 0 { return c.Send(tr(c.Sender().ID, "search_usage")) } query := strings.Join(args, " ") uid := c.Sender().ID statusMsg, err := c.Bot().Send(c.Sender(), tr(uid, "searching")) if err != nil { return err } go func() { var list []*models.TorrentDetails if sets.BTsets != nil && sets.BTsets.EnableRutorSearch { list = append(list, rutor.Search(query)...) } if sets.BTsets != nil && sets.BTsets.EnableTorznabSearch { list = append(list, torznab.Search(query, -1)...) } source := "RuTor+Torznab" sendSearchResultsAsync(c.Bot(), c.Sender(), statusMsg, uid, query, list, source) }() return nil } func cmdSearchRutor(c tele.Context) error { if sets.BTsets == nil || !sets.BTsets.EnableRutorSearch { return c.Send(tr(c.Sender().ID, "search_disabled_rutor")) } args := c.Args() if len(args) == 0 { return c.Send(tr(c.Sender().ID, "rutor_usage")) } query := strings.Join(args, " ") uid := c.Sender().ID statusMsg, err := c.Bot().Send(c.Sender(), tr(uid, "searching")) if err != nil { return err } go func() { list := rutor.Search(query) sendSearchResultsAsync(c.Bot(), c.Sender(), statusMsg, uid, query, list, "RuTor") }() return nil } func cmdTorznab(c tele.Context) error { if sets.BTsets == nil || !sets.BTsets.EnableTorznabSearch { return c.Send(tr(c.Sender().ID, "search_disabled_torznab")) } args := c.Args() if len(args) == 0 { return c.Send(tr(c.Sender().ID, "torznab_usage")) } query := strings.Join(args, " ") index := -1 if len(args) > 1 { if i, err := strconv.Atoi(args[len(args)-1]); err == nil && i >= 0 && i < 100 { index = i query = strings.Join(args[:len(args)-1], " ") } } uid := c.Sender().ID statusMsg, err := c.Bot().Send(c.Sender(), tr(uid, "searching")) if err != nil { return err } go func() { list := torznab.Search(query, index) sendSearchResultsAsync(c.Bot(), c.Sender(), statusMsg, uid, query, list, "Torznab") }() return nil } func sendSearchResultsAsync(api tele.API, recipient tele.Recipient, statusMsg *tele.Message, userID int64, query string, list []*models.TorrentDetails, source string) { if len(list) == 0 { _, _ = api.Edit(statusMsg, fmt.Sprintf(tr(userID, "search_not_found"), query, source)) return } _ = api.Delete(statusMsg) _ = sendSearchResultsToRecipient(api, recipient, userID, 0, list, source) } func sendSearchResultsToRecipient(api tele.API, recipient tele.Recipient, userID int64, offset int, list []*models.TorrentDetails, source string) error { const pageSize = 10 if offset == 0 { storeSearchResults(userID, list) } start := offset end := offset + pageSize if end > len(list) { end = len(list) } page := list[start:end] for i, item := range page { idx := offset + i link := item.Magnet if link == "" { link = item.Link } if link == "" { continue } size := item.Size if size == "" { size = "?" } txt := fmt.Sprintf("%d. %s (%s) S:%d P:%d", idx+1, escapeHtml(item.Title), size, item.Seed, item.Peer) btnAdd := tele.InlineButton{Text: tr(userID, "btn_add"), Unique: "fadd", Data: strconv.Itoa(idx)} kbd := &tele.ReplyMarkup{InlineKeyboard: [][]tele.InlineButton{{btnAdd}}} _, _ = api.Send(recipient, txt, kbd) } if end < len(list) { btnMore := tele.InlineButton{Text: "🔍 " + tr(userID, "search_more"), Unique: "fmore", Data: strconv.Itoa(end)} kbd := &tele.ReplyMarkup{InlineKeyboard: [][]tele.InlineButton{{btnMore}}} _, _ = api.Send(recipient, fmt.Sprintf(tr(userID, "search_more_hint"), end, len(list)), kbd) } return nil } func callbackSearchMore(c tele.Context, offsetStr string) error { uid := c.Sender().ID offset, err := strconv.Atoi(offsetStr) if err != nil || offset < 0 { return c.Respond(&tele.CallbackResponse{Text: tr(uid, "error")}) } slice, total := getSearchResultsSlice(uid, offset, 10) if len(slice) == 0 { return c.Respond(&tele.CallbackResponse{Text: tr(uid, "search_expired")}) } _ = c.Respond(&tele.CallbackResponse{}) if c.Callback().Message != nil { _ = c.Bot().Delete(c.Callback().Message) } return sendSearchResultsPage(c.Bot(), c.Sender(), uid, offset, slice, total) } func sendSearchResultsPage(api tele.API, recipient tele.Recipient, userID int64, offset int, page []*models.TorrentDetails, total int) error { for i, item := range page { idx := offset + i link := item.Magnet if link == "" { link = item.Link } if link == "" { continue } size := item.Size if size == "" { size = "?" } txt := fmt.Sprintf("%d. %s (%s) S:%d P:%d", idx+1, escapeHtml(item.Title), size, item.Seed, item.Peer) btnAdd := tele.InlineButton{Text: tr(userID, "btn_add"), Unique: "fadd", Data: strconv.Itoa(idx)} kbd := &tele.ReplyMarkup{InlineKeyboard: [][]tele.InlineButton{{btnAdd}}} _, _ = api.Send(recipient, txt, kbd) } nextOffset := offset + len(page) if nextOffset < total { btnMore := tele.InlineButton{Text: "🔍 " + tr(userID, "search_more"), Unique: "fmore", Data: strconv.Itoa(nextOffset)} kbd := &tele.ReplyMarkup{InlineKeyboard: [][]tele.InlineButton{{btnMore}}} _, _ = api.Send(recipient, fmt.Sprintf(tr(userID, "search_more_hint"), nextOffset, total), kbd) } return nil }