mirror of
https://github.com/krau/SaveAny-Bot.git
synced 2026-05-12 02:19:55 +08:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8ea5be5b90 | ||
|
|
7f483056e0 | ||
|
|
a6f88d7f75 | ||
|
|
b757df0b5e | ||
|
|
b017046c8b |
38
.github/workflows/build-docker.yml
vendored
38
.github/workflows/build-docker.yml
vendored
@@ -20,19 +20,6 @@ jobs:
|
|||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up QEMU
|
|
||||||
uses: docker/setup-qemu-action@v3
|
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v3
|
|
||||||
|
|
||||||
- name: Login to GitHub Container Registry
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
registry: ${{ env.REGISTRY }}
|
|
||||||
username: ${{ github.actor }}
|
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Extract metadata for Docker
|
- name: Extract metadata for Docker
|
||||||
id: meta
|
id: meta
|
||||||
uses: docker/metadata-action@v5
|
uses: docker/metadata-action@v5
|
||||||
@@ -50,11 +37,36 @@ jobs:
|
|||||||
org.opencontainers.image.source=https://github.com/krau/SaveAny-Bot
|
org.opencontainers.image.source=https://github.com/krau/SaveAny-Bot
|
||||||
org.opencontainers.image.url=https://github.com/krau/SaveAny-Bot
|
org.opencontainers.image.url=https://github.com/krau/SaveAny-Bot
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Login to GitHub Container Registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ${{ env.REGISTRY }}
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Extract version from Git Ref
|
||||||
|
id: extract_version
|
||||||
|
run: |
|
||||||
|
VERSION=$(echo "${{ github.ref }}" | sed 's/refs\/tags\/v//')
|
||||||
|
echo "VERSION=${VERSION}" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Build and push Docker image
|
- name: Build and push Docker image
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
||||||
|
build-args: |
|
||||||
|
VERSION=${{ steps.meta.outputs.version }}
|
||||||
|
GitCommit=${{ github.sha }}
|
||||||
|
BuildTime=${{ format(github.event.repository.updated_at, 'yyyy-MM-dd HH:mm:ss') }}
|
||||||
push: true
|
push: true
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
|||||||
23
Dockerfile
23
Dockerfile
@@ -1,24 +1,27 @@
|
|||||||
FROM golang:alpine AS builder
|
FROM golang:alpine AS builder
|
||||||
|
|
||||||
|
ARG VERSION="dev"
|
||||||
|
ARG GitCommit="Unknown"
|
||||||
|
ARG BuildTime="Unknown"
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w -X github.com/krau/SaveAny-Bot/common.Version=Docker" -o saveany-bot .
|
RUN --mount=type=cache,target=/root/.cache/go-build \
|
||||||
|
--mount=type=cache,target=/go/pkg \
|
||||||
|
CGO_ENABLED=0 \
|
||||||
|
go build -trimpath \
|
||||||
|
-ldflags "-s -w \
|
||||||
|
-X github.com/krau/SaveAny-Bot/common.Version=${VERSION} \
|
||||||
|
-X github.com/krau/SaveAny-Bot/common.GitCommit=${GiTCommit} \
|
||||||
|
-X github.com/krau/SaveAny-Bot/common.BuildTime=${BuildTime}" \
|
||||||
|
-o saveany-bot .
|
||||||
|
|
||||||
FROM alpine:latest
|
FROM alpine:latest
|
||||||
|
|
||||||
RUN addgroup -S saveany && adduser -S saveany -G saveany
|
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
COPY --from=builder /app/saveany-bot .
|
COPY --from=builder /app/saveany-bot .
|
||||||
|
|
||||||
RUN mkdir -p /app/data /app/downloads /app/cache && \
|
|
||||||
chown -R saveany:saveany /app /app/downloads /app/cache /app/data
|
|
||||||
|
|
||||||
RUN chmod +x /app/saveany-bot
|
|
||||||
|
|
||||||
USER saveany
|
|
||||||
|
|
||||||
ENTRYPOINT ["/app/saveany-bot"]
|
ENTRYPOINT ["/app/saveany-bot"]
|
||||||
|
|||||||
95
bot/handle_send.go
Normal file
95
bot/handle_send.go
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
package bot
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/celestix/gotgproto/dispatcher"
|
||||||
|
"github.com/celestix/gotgproto/ext"
|
||||||
|
tgtypes "github.com/celestix/gotgproto/types"
|
||||||
|
"github.com/gotd/td/tg"
|
||||||
|
)
|
||||||
|
|
||||||
|
func copyMediaToChat(ctx *ext.Context, msg *tg.Message, chatID int64) (*tgtypes.Message, error) {
|
||||||
|
media, ok := msg.GetMedia()
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("获取媒体失败")
|
||||||
|
}
|
||||||
|
|
||||||
|
req := &tg.MessagesSendMediaRequest{
|
||||||
|
InvertMedia: msg.InvertMedia,
|
||||||
|
Message: msg.Message,
|
||||||
|
}
|
||||||
|
|
||||||
|
switch m := media.(type) {
|
||||||
|
case *tg.MessageMediaDocument:
|
||||||
|
document, ok := m.Document.AsNotEmpty()
|
||||||
|
if !ok {
|
||||||
|
return nil, ErrEmptyDocument
|
||||||
|
}
|
||||||
|
inputMedia := &tg.InputMediaDocument{
|
||||||
|
ID: document.AsInput(),
|
||||||
|
}
|
||||||
|
inputMedia.SetFlags()
|
||||||
|
req.Media = inputMedia
|
||||||
|
|
||||||
|
case *tg.MessageMediaPhoto:
|
||||||
|
photo, ok := m.Photo.AsNotEmpty()
|
||||||
|
if !ok {
|
||||||
|
return nil, ErrEmptyPhoto
|
||||||
|
}
|
||||||
|
inputMedia := &tg.InputMediaPhoto{
|
||||||
|
ID: photo.AsInput(),
|
||||||
|
}
|
||||||
|
inputMedia.SetFlags()
|
||||||
|
req.Media = inputMedia
|
||||||
|
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("不支持的媒体类型: %T", media)
|
||||||
|
}
|
||||||
|
|
||||||
|
req.SetEntities(msg.Entities)
|
||||||
|
req.SetFlags()
|
||||||
|
|
||||||
|
return ctx.SendMedia(chatID, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendFileToTelegram(ctx *ext.Context, update *ext.Update) error {
|
||||||
|
args := strings.Split(string(update.CallbackQuery.Data), " ")
|
||||||
|
if len(args) < 3 {
|
||||||
|
ctx.AnswerCallback(&tg.MessagesSetBotCallbackAnswerRequest{
|
||||||
|
QueryID: update.CallbackQuery.QueryID,
|
||||||
|
Alert: true,
|
||||||
|
Message: "参数错误",
|
||||||
|
CacheTime: 5,
|
||||||
|
})
|
||||||
|
return dispatcher.EndGroups
|
||||||
|
}
|
||||||
|
fileChatID, _ := strconv.Atoi(args[1])
|
||||||
|
fileMessageID, _ := strconv.Atoi(args[2])
|
||||||
|
fileMessage, err := GetTGMessage(ctx, int64(fileChatID), fileMessageID)
|
||||||
|
if err != nil {
|
||||||
|
ctx.AnswerCallback(&tg.MessagesSetBotCallbackAnswerRequest{
|
||||||
|
QueryID: update.CallbackQuery.QueryID,
|
||||||
|
Alert: true,
|
||||||
|
Message: "无法获取文件消息",
|
||||||
|
CacheTime: 5,
|
||||||
|
})
|
||||||
|
return dispatcher.EndGroups
|
||||||
|
}
|
||||||
|
_, err = copyMediaToChat(ctx, fileMessage, update.EffectiveChat().GetID())
|
||||||
|
if err != nil {
|
||||||
|
ctx.AnswerCallback(&tg.MessagesSetBotCallbackAnswerRequest{
|
||||||
|
QueryID: update.CallbackQuery.QueryID,
|
||||||
|
Alert: true,
|
||||||
|
Message: fmt.Sprintf("发送文件失败: %s", err),
|
||||||
|
CacheTime: 5,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
ctx.AnswerCallback(&tg.MessagesSetBotCallbackAnswerRequest{
|
||||||
|
QueryID: update.CallbackQuery.QueryID,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return dispatcher.EndGroups
|
||||||
|
}
|
||||||
@@ -29,5 +29,6 @@ func RegisterHandlers(dispatcher dispatcher.Dispatcher) {
|
|||||||
dispatcher.AddHandler(handlers.NewCallbackQuery(filters.CallbackQuery.Prefix("add"), AddToQueue))
|
dispatcher.AddHandler(handlers.NewCallbackQuery(filters.CallbackQuery.Prefix("add"), AddToQueue))
|
||||||
dispatcher.AddHandler(handlers.NewCallbackQuery(filters.CallbackQuery.Prefix("set_default"), setDefaultStorage))
|
dispatcher.AddHandler(handlers.NewCallbackQuery(filters.CallbackQuery.Prefix("set_default"), setDefaultStorage))
|
||||||
dispatcher.AddHandler(handlers.NewCallbackQuery(filters.CallbackQuery.Prefix("cancel"), cancelTask))
|
dispatcher.AddHandler(handlers.NewCallbackQuery(filters.CallbackQuery.Prefix("cancel"), cancelTask))
|
||||||
|
dispatcher.AddHandler(handlers.NewCallbackQuery(filters.CallbackQuery.Prefix("send_here"), sendFileToTelegram))
|
||||||
dispatcher.AddHandler(handlers.NewMessage(filters.Message.Media, handleFileMessage))
|
dispatcher.AddHandler(handlers.NewMessage(filters.Message.Media, handleFileMessage))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,6 +71,14 @@ func getSelectStorageMarkup(userChatID int64, fileChatID, fileMessageID int) (*t
|
|||||||
row.Buttons = buttons[i:min(i+3, len(buttons))]
|
row.Buttons = buttons[i:min(i+3, len(buttons))]
|
||||||
markup.Rows = append(markup.Rows, row)
|
markup.Rows = append(markup.Rows, row)
|
||||||
}
|
}
|
||||||
|
markup.Rows = append(markup.Rows, tg.KeyboardButtonRow{
|
||||||
|
Buttons: []tg.KeyboardButtonClass{
|
||||||
|
&tg.KeyboardButtonCallback{
|
||||||
|
Text: "发送到当前聊天",
|
||||||
|
Data: []byte(fmt.Sprintf("send_here %d %d", fileChatID, fileMessageID)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
return markup, nil
|
return markup, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user