package main import ( "context" "errors" "fmt" "log" "os" "runtime" "strconv" "strings" "github.com/SevereCloud/vksdk/v2/api" "github.com/SevereCloud/vksdk/v2/events" "github.com/SevereCloud/vksdk/v2/longpoll-bot" "github.com/s32x/httpclient" tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5" ) var video_links chan (string) const PCUserAgent string = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36" const MobileUserAgent string = "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Mobile Safari/537.36" func main() { // get config mustConfigLoad() // create chan video_links = make(chan string, Conf.Workers*2) // run vk go RunVK() // run tg go RunTG() // select {} } type Config struct { Workers int TgAPIKey string TgChatID int64 VkAPIKey string } var Conf Config func mustConfigLoad() { var err error Conf.Workers, err = strconv.Atoi(os.Getenv("Workers")) if err != nil { panic(err) } Conf.TgAPIKey = os.Getenv("TgAPIKey") Conf.VkAPIKey = os.Getenv("VkAPIKey") Conf.TgChatID, err = strconv.ParseInt(os.Getenv("TgChatID"), 10, 64) if err != nil { panic(err) } } func RunVK() { vk := api.NewVK(Conf.VkAPIKey) // get information about the group group, err := vk.GroupsGetByID(nil) if err != nil { log.Fatal(err) } // Initializing Long Poll lp, err := longpoll.NewLongPoll(vk, group[0].ID) if err != nil { log.Fatal(err) } // New message event lp.MessageNew(func(_ context.Context, obj events.MessageNewObject) { log.Printf("%d: %s", obj.Message.PeerID, obj.Message.Text) for _, obj := range obj.Message.Attachments { objectsw: switch obj.Type { case "story": // fmt.Printf("Story %+v\n", obj.Story.Video.Files) // get video link from struct var videolink string switch { case obj.Story.Video.Files.Mp4_720 != "": videolink = obj.Story.Video.Files.Mp4_720 case obj.Story.Video.Files.Mp4_480 != "": videolink = obj.Story.Video.Files.Mp4_480 case obj.Story.Video.Files.Mp4_360 != "": videolink = obj.Story.Video.Files.Mp4_360 case obj.Story.Video.Files.Mp4_240 != "": videolink = obj.Story.Video.Files.Mp4_240 default: error_logging(errors.New("cannot find video link")) break objectsw } // fmt.Println("Story:", videolink) error_logging(err) // send video to tg video_links <- videolink } } }) // Run Bots Long Poll log.Println("[VK] Start Long Poll") if err := lp.Run(); err != nil { log.Fatal(err) } } func RunTG() { bot, err := tgbotapi.NewBotAPI(Conf.TgAPIKey) if err != nil { log.Panic(err) } bot.Debug = false log.Printf("[TG] Authorized on account %s", bot.Self.UserName) u := tgbotapi.NewUpdate(0) u.Timeout = 60 for i := 0; i < Conf.Workers; i++ { go tg_worker(i+1, bot) } } func tg_worker(id int, bot *tgbotapi.BotAPI) { for link := range video_links { log.Println(fmt.Sprintf("[%d]", id), "Получена ссылка, загружаю:", link) // get video by link var client *httpclient.Client if strings.Contains(link, "VK_ANDROID") { // create mobile client client = httpclient.New().WithHeader("User-Agent", MobileUserAgent) } else { // create Desktop client client = httpclient.New().WithHeader("User-Agent", PCUserAgent) } resp, err := client.Get(link).Do() error_logging(err) body, err := resp.Bytes() error_logging(err) msg := tgbotapi.NewVideo(Conf.TgChatID, tgbotapi.FileBytes{Name: "story", Bytes: body}) log.Println(fmt.Sprintf("[%d]", id), "Отправляю видео в телеграм...") _, err = bot.Send(msg) error_logging(err) } } // Log errors func error_logging(err error) { if err != nil { pc := make([]uintptr, 10) n := runtime.Callers(2, pc) frames := runtime.CallersFrames(pc[:n]) frame, _ := frames.Next() // fmt.Printf("%s:%d %s\n", frame.File, frame.Line, frame.Function) log.Printf("[Parser] error on %s line %d: %s", frame.Function, frame.Line, err) } }