616c6b1c62
Release Docker multi arch / docker (push) Has been cancelled
Test Install Script / Test Script Syntax (push) Has been cancelled
Test Install Script / Test on almalinux-10 (default) (push) Has been cancelled
Test Install Script / Test on almalinux-10 (root) (push) Has been cancelled
Test Install Script / Test on almalinux-8 (default) (push) Has been cancelled
Test Install Script / Test on almalinux-8 (root) (push) Has been cancelled
Test Install Script / Test on almalinux-9 (default) (push) Has been cancelled
Test Install Script / Test on almalinux-9 (root) (push) Has been cancelled
Test Install Script / Test on amazonlinux-2 (default) (push) Has been cancelled
Test Install Script / Test on amazonlinux-2 (root) (push) Has been cancelled
Test Install Script / Test on debian-11 (default) (push) Has been cancelled
Test Install Script / Test on debian-11 (root) (push) Has been cancelled
Test Install Script / Test on debian-12 (default) (push) Has been cancelled
Test Install Script / Test on debian-12 (root) (push) Has been cancelled
Test Install Script / Test on debian-13 (default) (push) Has been cancelled
Test Install Script / Test on debian-13 (root) (push) Has been cancelled
Test Install Script / Test on fedora-latest (default) (push) Has been cancelled
Test Install Script / Test on fedora-latest (root) (push) Has been cancelled
Test Install Script / Test on rocky-10 (default) (push) Has been cancelled
Test Install Script / Test on rocky-10 (root) (push) Has been cancelled
Test Install Script / Test on rocky-8 (default) (push) Has been cancelled
Test Install Script / Test on rocky-8 (root) (push) Has been cancelled
Test Install Script / Test on rocky-9 (default) (push) Has been cancelled
Test Install Script / Test on rocky-9 (root) (push) Has been cancelled
Test Install Script / Test on ubuntu-22.04 (default) (push) Has been cancelled
Test Install Script / Test on ubuntu-22.04 (root) (push) Has been cancelled
Test Install Script / Test on ubuntu-24.04 (default) (push) Has been cancelled
Test Install Script / Test on ubuntu-24.04 (root) (push) Has been cancelled
139 lines
3.1 KiB
Go
139 lines
3.1 KiB
Go
package tgbot
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"sync"
|
|
"time"
|
|
|
|
tele "gopkg.in/telebot.v4"
|
|
"server/rutor/models"
|
|
)
|
|
|
|
type searchCacheEntry struct {
|
|
results []*models.TorrentDetails
|
|
expires time.Time
|
|
}
|
|
|
|
var (
|
|
searchCache = make(map[int64]*searchCacheEntry)
|
|
searchCacheMu sync.RWMutex
|
|
cacheTTL = 10 * time.Minute
|
|
cacheMaxSize = 1000
|
|
)
|
|
|
|
func init() {
|
|
go searchCacheCleanup()
|
|
}
|
|
|
|
func searchCacheCleanup() {
|
|
ticker := time.NewTicker(time.Minute)
|
|
for range ticker.C {
|
|
searchCacheMu.Lock()
|
|
now := time.Now()
|
|
for id, entry := range searchCache {
|
|
if entry == nil || now.After(entry.expires) {
|
|
delete(searchCache, id)
|
|
}
|
|
}
|
|
if len(searchCache) > cacheMaxSize {
|
|
evict := len(searchCache) - cacheMaxSize
|
|
if evict < len(searchCache)/10 {
|
|
evict = len(searchCache) / 10
|
|
}
|
|
if evict < 1 {
|
|
evict = 1
|
|
}
|
|
type kv struct {
|
|
id int64
|
|
exp time.Time
|
|
}
|
|
var entries []kv
|
|
for id, entry := range searchCache {
|
|
if entry != nil {
|
|
entries = append(entries, kv{id, entry.expires})
|
|
}
|
|
}
|
|
for evict > 0 && len(entries) > 0 {
|
|
oldest := 0
|
|
for j := 1; j < len(entries); j++ {
|
|
if entries[j].exp.Before(entries[oldest].exp) {
|
|
oldest = j
|
|
}
|
|
}
|
|
delete(searchCache, entries[oldest].id)
|
|
entries[oldest] = entries[len(entries)-1]
|
|
entries = entries[:len(entries)-1]
|
|
evict--
|
|
}
|
|
}
|
|
searchCacheMu.Unlock()
|
|
}
|
|
}
|
|
|
|
func storeSearchResults(userID int64, results []*models.TorrentDetails) {
|
|
searchCacheMu.Lock()
|
|
defer searchCacheMu.Unlock()
|
|
searchCache[userID] = &searchCacheEntry{
|
|
results: results,
|
|
expires: time.Now().Add(cacheTTL),
|
|
}
|
|
}
|
|
|
|
func getSearchResult(userID int64, index int) *models.TorrentDetails {
|
|
searchCacheMu.Lock()
|
|
defer searchCacheMu.Unlock()
|
|
entry, ok := searchCache[userID]
|
|
if !ok || entry == nil || time.Now().After(entry.expires) {
|
|
return nil
|
|
}
|
|
if index < 0 || index >= len(entry.results) {
|
|
return nil
|
|
}
|
|
return entry.results[index]
|
|
}
|
|
|
|
func getSearchResultsSlice(userID int64, offset, limit int) ([]*models.TorrentDetails, int) {
|
|
searchCacheMu.Lock()
|
|
defer searchCacheMu.Unlock()
|
|
entry, ok := searchCache[userID]
|
|
if !ok || entry == nil || time.Now().After(entry.expires) {
|
|
return nil, 0
|
|
}
|
|
total := len(entry.results)
|
|
if offset >= total {
|
|
return nil, total
|
|
}
|
|
end := offset + limit
|
|
if end > total {
|
|
end = total
|
|
}
|
|
slice := make([]*models.TorrentDetails, end-offset)
|
|
copy(slice, entry.results[offset:end])
|
|
return slice, total
|
|
}
|
|
|
|
func callbackSearchAdd(c tele.Context, indexStr string) error {
|
|
uid := c.Sender().ID
|
|
index, parseErr := strconv.Atoi(indexStr)
|
|
if parseErr != nil {
|
|
return c.Respond(&tele.CallbackResponse{Text: tr(uid, "error")})
|
|
}
|
|
item := getSearchResult(uid, index)
|
|
if item == nil {
|
|
return c.Respond(&tele.CallbackResponse{Text: tr(uid, "search_expired")})
|
|
}
|
|
link := item.Magnet
|
|
if link == "" {
|
|
link = item.Link
|
|
}
|
|
if link == "" {
|
|
return c.Respond(&tele.CallbackResponse{Text: tr(uid, "search_no_link")})
|
|
}
|
|
_ = c.Respond(&tele.CallbackResponse{Text: tr(uid, "search_adding")})
|
|
if err := addTorrent(c, link); err != nil {
|
|
return c.Send(fmt.Sprintf(tr(uid, "add_error"), err.Error()))
|
|
}
|
|
return list(c)
|
|
}
|