commit 6e2e3460d646389ec9e8b1b056ba0885edfb0230 Author: yyasha Date: Thu Nov 23 18:44:58 2023 +0300 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4c49bd7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.env diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..a04e355 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,16 @@ +FROM golang:alpine AS builder +LABEL builder=true +WORKDIR /build + +ADD go.mod . + +COPY . . +RUN go mod download +RUN CGO_ENABLED=0 GOOS=linux go build -ldflags "-w -s" -o main main.go + +FROM alpine + +WORKDIR /build + +COPY --from=builder /build/main /build/main +CMD ["./main"] diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..9702371 --- /dev/null +++ b/Makefile @@ -0,0 +1,5 @@ +docker_build: + docker build -t registry.computernetthings.ru/vk_tg_bridge:latest . && docker image prune -f + +docker_push: + docker push registry.computernetthings.ru/vk_tg_bridge:latest diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..b5f2282 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,7 @@ +version: '3' + +services: + auth_service: + image: registry.computernetthings.ru/vk_tg_bridge + restart: unless-stopped + env_file: .env diff --git a/env.example b/env.example new file mode 100644 index 0000000..3c41b30 --- /dev/null +++ b/env.example @@ -0,0 +1,4 @@ +TgAPIKey=token +VkAPIKey=token +TgChatID=123 +Workers=5 diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..ff18d97 --- /dev/null +++ b/go.mod @@ -0,0 +1,15 @@ +module bridge + +go 1.20 + +require ( + github.com/SevereCloud/vksdk/v2 v2.16.1 // indirect + github.com/cenkalti/backoff/v4 v4.1.2 // indirect + github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1 // indirect + github.com/klauspost/compress v1.16.7 // indirect + github.com/s32x/httpclient v0.0.0-20220217184346-6df4d4d51c14 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.0 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + golang.org/x/text v0.13.0 // indirect + h12.io/socks v1.0.3 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..22c923a --- /dev/null +++ b/go.sum @@ -0,0 +1,20 @@ +github.com/SevereCloud/vksdk/v2 v2.16.1 h1:UiazL3vTy7lMm33oIXRMxXg8S5I8bQuqEdLtbmOSpG4= +github.com/SevereCloud/vksdk/v2 v2.16.1/go.mod h1:UfVcBt8qh5+gIflQO6L+CWwrXcpwhOl5hKvKf8sXUd8= +github.com/cenkalti/backoff/v4 v4.1.2 h1:6Yo7N8UP2K6LWZnW94DLVSSrbobcWdVzAYOisuDPIFo= +github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1 h1:wG8n/XJQ07TmjbITcGiUaOtXxdrINDz1b0J1w0SzqDc= +github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1/go.mod h1:A2S0CWkNylc2phvKXWBBdD3K0iGnDBGbzRpISP2zBl8= +github.com/h12w/go-socks5 v0.0.0-20200522160539-76189e178364/go.mod h1:eDJQioIyy4Yn3MVivT7rv/39gAJTrA7lgmYr8EW950c= +github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= +github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= +github.com/s32x/httpclient v0.0.0-20220217184346-6df4d4d51c14 h1:7X+d8s674m+oOrb2YbbBrtA1Ey1puN9mBvHp2SWfkig= +github.com/s32x/httpclient v0.0.0-20220217184346-6df4d4d51c14/go.mod h1:FqlhGa3u28mSvrE2aDhpKc1h1WpEcjmrXFkN/e2qnxQ= +github.com/vmihailenco/msgpack/v5 v5.4.0 h1:hRM0digJwyR6vll33NNAwCFguy5JuBD6jxDmQP3l608= +github.com/vmihailenco/msgpack/v5 v5.4.0/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +h12.io/socks v1.0.3 h1:Ka3qaQewws4j4/eDQnOdpr4wXsC//dXtWvftlIcCQUo= +h12.io/socks v1.0.3/go.mod h1:AIhxy1jOId/XCz9BO+EIgNL2rQiPTBNnOfnVnQ+3Eck= diff --git a/main.go b/main.go new file mode 100644 index 0000000..2f5a9ae --- /dev/null +++ b/main.go @@ -0,0 +1,162 @@ +package main + +import ( + "context" + "errors" + "fmt" + "log" + "os" + "runtime" + "strconv" + + "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 workers_count int = 5 +// const tg_chat_id int64 = -1002135430788 +// const tg_bot_key string = "6548829570:AAFi_K-YhJwP7asF2-bwSCxrNAkkI7c7Xd0" +// const vk_api_key string = "vk1.a.iQX883p6Es-adfHxxEBd1KSEodg79PqVNatiWAadchBPzhYJz2UGE5pgPmXNFlygj3RqTJQ7gB3juUayHFm4yYgV9fE6LPx_z3EkD3L57zXmNrLGjMdSASud4dXe7yfQNQP4OoPmmSAH4MZubPGK1JWWxzRe4wgYaooAA5ehRtcQOYjzser3kfJemt-uvT93ccikgR66QSjq0bGDsmeUyw" + +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 = true + + 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 + client := httpclient.New().WithHeader("User-Agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36") + 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) + } +}