Files
torrserver/server/tgbot/ffp.go
T
nkozobrod 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
Initial commit: docker compose config
2026-05-30 12:07:11 +00:00

210 lines
5.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package tgbot
import (
"encoding/json"
"fmt"
"strconv"
"strings"
"server/ffprobe"
"server/settings"
"server/torr"
"github.com/dustin/go-humanize"
tele "gopkg.in/telebot.v4"
ffp "gopkg.in/vansante/go-ffprobe.v2"
)
// TODO: Use internal API for ffp
func cmdFfp(c tele.Context) error {
uid := c.Sender().ID
args := c.Args()
if len(args) < 2 {
return c.Send(tr(uid, "ffp_usage"))
}
hash := resolveHash(c, args[0])
if hash == "" {
return c.Send(tr(uid, "invalid_hash"))
}
id, err := strconv.Atoi(args[1])
if err != nil || id < 1 {
return c.Send(tr(uid, "ffp_file_index"))
}
asJSON := false
if len(args) >= 3 {
last := strings.ToLower(strings.TrimSpace(args[len(args)-1]))
if last == "json" || last == "--json" || last == "-j" {
asJSON = true
}
}
t := torr.GetTorrent(hash)
if t == nil {
return c.Send(tr(uid, "torrent_not_found"))
}
proto := "http"
port := settings.Port
if settings.Ssl {
proto = "https"
port = settings.SslPort
}
link := fmt.Sprintf("%s://127.0.0.1:%s/play/%s/%d", proto, port, hash, id)
data, err := ffprobe.ProbeUrl(link)
if err != nil {
return c.Send(fmt.Sprintf(tr(uid, "ffp_error"), err.Error()))
}
var msg string
if asJSON {
buf, _ := json.MarshalIndent(data, "", " ")
msg = "<pre>" + strings.ReplaceAll(string(buf), "<", "&lt;") + "</pre>"
if len(msg) > 4000 {
msg = msg[:4000] + "\n...</pre>"
}
} else {
msg = formatFfpHuman(data, uid)
if len(msg) > 4000 {
msg = msg[:4000] + "\n..."
}
}
return c.Send(msg)
}
func formatFfpHuman(data *ffp.ProbeData, uid int64) string {
var sb strings.Builder
if data.Format != nil {
f := data.Format
sb.WriteString("<b>📁 " + tr(uid, "ffp_format") + "</b>\n")
fmt.Fprintf(&sb, " %s: %s\n", tr(uid, "ffp_container"), f.FormatLongName)
if f.DurationSeconds > 0 {
d := int(f.DurationSeconds)
h, m, s := d/3600, (d%3600)/60, d%60
fmt.Fprintf(&sb, " %s: %02d:%02d:%02d\n", tr(uid, "ffp_duration"), h, m, s)
}
if f.Size != "" {
if size, err := strconv.ParseInt(f.Size, 10, 64); err == nil {
fmt.Fprintf(&sb, " %s: %s\n", tr(uid, "ffp_size"), humanize.IBytes(uint64(size)))
} else {
fmt.Fprintf(&sb, " %s: %s\n", tr(uid, "ffp_size"), f.Size)
}
}
if f.BitRate != "" {
if br, err := strconv.ParseInt(f.BitRate, 10, 64); err == nil {
fmt.Fprintf(&sb, " %s: %s/s\n", tr(uid, "ffp_bitrate"), humanize.IBytes(uint64(br)))
} else {
fmt.Fprintf(&sb, " %s: %s\n", tr(uid, "ffp_bitrate"), f.BitRate)
}
}
sb.WriteString("\n")
}
sb.WriteString("<b>🎬 " + tr(uid, "ffp_streams") + "</b>\n\n")
for i, s := range data.Streams {
title := getTag(s.TagList, "title")
lang := getTag(s.TagList, "language")
if lang != "" {
lang = " [" + lang + "]"
}
switch s.CodecType {
case "video":
fmt.Fprintf(&sb, "<b>#%d %s</b>%s\n", i, tr(uid, "ffp_video"), lang)
fmt.Fprintf(&sb, " %s: %s", tr(uid, "ffp_codec"), s.CodecLongName)
if s.Profile != "" {
fmt.Fprintf(&sb, " (%s)", s.Profile)
}
sb.WriteString("\n")
if s.Width > 0 && s.Height > 0 {
fmt.Fprintf(&sb, " %s: %d×%d", tr(uid, "ffp_resolution"), s.Width, s.Height)
if s.DisplayAspectRatio != "" && s.DisplayAspectRatio != "0:0" {
fmt.Fprintf(&sb, " (%s)", s.DisplayAspectRatio)
}
sb.WriteString("\n")
}
if s.PixFmt != "" {
fmt.Fprintf(&sb, " %s: %s\n", tr(uid, "ffp_pixel"), s.PixFmt)
}
if s.RFrameRate != "" && s.RFrameRate != "0/0" {
fmt.Fprintf(&sb, " %s: %s\n", tr(uid, "ffp_fps"), s.RFrameRate)
}
if s.BitRate != "" {
if br, err := strconv.ParseInt(s.BitRate, 10, 64); err == nil {
fmt.Fprintf(&sb, " %s: %s/s\n", tr(uid, "ffp_bitrate"), humanize.IBytes(uint64(br)))
}
}
if s.ColorSpace != "" || s.ColorTransfer != "" {
fmt.Fprintf(&sb, " %s: %s / %s / %s\n", tr(uid, "ffp_color"), s.ColorSpace, s.ColorTransfer, s.ColorPrimaries)
}
if title != "" {
fmt.Fprintf(&sb, " %s: %s\n", tr(uid, "ffp_title"), escapeHtml(title))
}
case "audio":
fmt.Fprintf(&sb, "<b>#%d %s</b>%s\n", i, tr(uid, "ffp_audio"), lang)
fmt.Fprintf(&sb, " %s: %s", tr(uid, "ffp_codec"), s.CodecLongName)
if s.Profile != "" {
fmt.Fprintf(&sb, " (%s)", s.Profile)
}
sb.WriteString("\n")
if s.SampleRate != "" {
fmt.Fprintf(&sb, " %s: %s Hz\n", tr(uid, "ffp_samplerate"), s.SampleRate)
}
if s.Channels > 0 {
ch := s.ChannelLayout
if ch == "" {
ch = fmt.Sprintf("%d ch", s.Channels)
}
fmt.Fprintf(&sb, " %s: %s\n", tr(uid, "ffp_channels"), ch)
}
if s.BitRate != "" {
if br, err := strconv.ParseInt(s.BitRate, 10, 64); err == nil {
fmt.Fprintf(&sb, " %s: %s/s\n", tr(uid, "ffp_bitrate"), humanize.IBytes(uint64(br)))
}
}
if title != "" {
fmt.Fprintf(&sb, " %s: %s\n", tr(uid, "ffp_title"), escapeHtml(title))
}
case "subtitle":
fmt.Fprintf(&sb, "<b>#%d %s</b>%s\n", i, tr(uid, "ffp_subtitle"), lang)
fmt.Fprintf(&sb, " %s: %s\n", tr(uid, "ffp_codec"), s.CodecLongName)
if title != "" {
fmt.Fprintf(&sb, " %s: %s\n", tr(uid, "ffp_title"), escapeHtml(title))
}
default:
fmt.Fprintf(&sb, "<b>#%d %s</b>\n", i, s.CodecType)
fmt.Fprintf(&sb, " %s: %s\n", tr(uid, "ffp_codec"), s.CodecLongName)
}
sb.WriteString("\n")
}
return strings.TrimSuffix(sb.String(), "\n\n")
}
func getTag(tags ffp.Tags, key string) string {
if tags == nil {
return ""
}
if v, ok := tags[key]; ok && v != nil {
if s, ok := v.(string); ok {
return s
}
return fmt.Sprint(v)
}
for k, v := range tags {
if strings.HasPrefix(k, key+"-") && v != nil {
if s, ok := v.(string); ok {
return s
}
return fmt.Sprint(v)
}
}
return ""
}