Spaces:
Paused
Paused
Mohammad Shahid commited on
Commit ·
53d6e0b
1
Parent(s): 5edf1f8
added lifetime link suppoert
Browse files- internal/routes/stream.go +1 -1
- internal/utils/helpers.go +37 -0
- internal/utils/reader.go +27 -0
internal/routes/stream.go
CHANGED
|
@@ -123,7 +123,7 @@ func getStreamRoute(ctx *gin.Context) {
|
|
| 123 |
ctx.Header("Content-Disposition", fmt.Sprintf("%s; filename=\"%s\"", disposition, file.FileName))
|
| 124 |
|
| 125 |
if r.Method != "HEAD" {
|
| 126 |
-
lr, _ := utils.NewTelegramReader(ctx, worker.Client, file.Location, start, end, contentLength)
|
| 127 |
if _, err := io.CopyN(w, lr, contentLength); err != nil {
|
| 128 |
log.Error("Error while copying stream", zap.Error(err))
|
| 129 |
}
|
|
|
|
| 123 |
ctx.Header("Content-Disposition", fmt.Sprintf("%s; filename=\"%s\"", disposition, file.FileName))
|
| 124 |
|
| 125 |
if r.Method != "HEAD" {
|
| 126 |
+
lr, _ := utils.NewTelegramReader(ctx, worker.Client, file.Location, start, end, contentLength, messageID)
|
| 127 |
if _, err := io.CopyN(w, lr, contentLength); err != nil {
|
| 128 |
log.Error("Error while copying stream", zap.Error(err))
|
| 129 |
}
|
internal/utils/helpers.go
CHANGED
|
@@ -179,3 +179,40 @@ func ForwardMessages(ctx *ext.Context, fromChatId, toChatId int64, messageID int
|
|
| 179 |
}
|
| 180 |
return update.(*tg.Updates), nil
|
| 181 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 179 |
}
|
| 180 |
return update.(*tg.Updates), nil
|
| 181 |
}
|
| 182 |
+
|
| 183 |
+
|
| 184 |
+
// Add this entire function to the end of internal/utils/helpers.go
|
| 185 |
+
|
| 186 |
+
// RefreshFileReference gets a new file reference for a message and updates the cache.
|
| 187 |
+
func RefreshFileReference(ctx context.Context, client *gotgproto.Client, messageID int) (*types.File, error) {
|
| 188 |
+
key := fmt.Sprintf("file:%d:%d", messageID, client.Self.ID)
|
| 189 |
+
log := Logger.Named("RefreshFileReference")
|
| 190 |
+
|
| 191 |
+
log.Debug("Refreshing file reference from Telegram", zap.Int("messageID", messageID), zap.Int64("clientID", client.Self.ID))
|
| 192 |
+
|
| 193 |
+
// Step 1: Get the message again from the API to get a fresh file_reference.
|
| 194 |
+
message, err := GetTGMessage(ctx, client, messageID)
|
| 195 |
+
if err != nil {
|
| 196 |
+
return nil, err
|
| 197 |
+
}
|
| 198 |
+
|
| 199 |
+
// Step 2: Convert the message media into our internal File type.
|
| 200 |
+
file, err := FileFromMedia(message.Media)
|
| 201 |
+
if err != nil {
|
| 202 |
+
return nil, err
|
| 203 |
+
}
|
| 204 |
+
|
| 205 |
+
// Step 3: Update the cache with the new, valid file data.
|
| 206 |
+
err = cache.GetCache().Set(
|
| 207 |
+
key,
|
| 208 |
+
file,
|
| 209 |
+
3600, // Cache for 1 hour
|
| 210 |
+
)
|
| 211 |
+
if err != nil {
|
| 212 |
+
// If caching fails, we can still proceed, but log the error.
|
| 213 |
+
log.Error("Failed to update cache with new file reference", zap.Error(err))
|
| 214 |
+
}
|
| 215 |
+
|
| 216 |
+
log.Debug("Successfully refreshed file reference and updated cache.", zap.Int("messageID", messageID))
|
| 217 |
+
return file, nil
|
| 218 |
+
}
|
internal/utils/reader.go
CHANGED
|
@@ -11,6 +11,7 @@ import (
|
|
| 11 |
)
|
| 12 |
|
| 13 |
type telegramReader struct {
|
|
|
|
| 14 |
ctx context.Context
|
| 15 |
log *zap.Logger
|
| 16 |
client *gotgproto.Client
|
|
@@ -36,9 +37,11 @@ func NewTelegramReader(
|
|
| 36 |
start int64,
|
| 37 |
end int64,
|
| 38 |
contentLength int64,
|
|
|
|
| 39 |
) (io.ReadCloser, error) {
|
| 40 |
|
| 41 |
r := &telegramReader{
|
|
|
|
| 42 |
ctx: ctx,
|
| 43 |
log: Logger.Named("telegramReader"),
|
| 44 |
location: location,
|
|
@@ -92,6 +95,30 @@ func (r *telegramReader) chunk(offset int64, limit int64) ([]byte, error) {
|
|
| 92 |
|
| 93 |
res, err := r.client.API().UploadGetFile(r.ctx, req)
|
| 94 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 95 |
if err != nil {
|
| 96 |
return nil, err
|
| 97 |
}
|
|
|
|
| 11 |
)
|
| 12 |
|
| 13 |
type telegramReader struct {
|
| 14 |
+
messageID int
|
| 15 |
ctx context.Context
|
| 16 |
log *zap.Logger
|
| 17 |
client *gotgproto.Client
|
|
|
|
| 37 |
start int64,
|
| 38 |
end int64,
|
| 39 |
contentLength int64,
|
| 40 |
+
messageID int
|
| 41 |
) (io.ReadCloser, error) {
|
| 42 |
|
| 43 |
r := &telegramReader{
|
| 44 |
+
messageID: messageID,
|
| 45 |
ctx: ctx,
|
| 46 |
log: Logger.Named("telegramReader"),
|
| 47 |
location: location,
|
|
|
|
| 95 |
|
| 96 |
res, err := r.client.API().UploadGetFile(r.ctx, req)
|
| 97 |
|
| 98 |
+
// Check if the file reference has expired.
|
| 99 |
+
if err != nil {
|
| 100 |
+
if tgerr.Is(err, "FILE_REFERENCE_EXPIRED") {
|
| 101 |
+
r.log.Info("File reference expired. Attempting to refresh.", zap.Int("messageID", r.messageID))
|
| 102 |
+
|
| 103 |
+
// Call our new refresh function from helpers.go
|
| 104 |
+
newFile, refreshErr := RefreshFileReference(r.ctx, r.client, r.messageID)
|
| 105 |
+
if refreshErr != nil {
|
| 106 |
+
r.log.Error("Failed to refresh file reference after it expired.", zap.Error(refreshErr))
|
| 107 |
+
// If we can't refresh, return the original "expired" error.
|
| 108 |
+
return nil, err
|
| 109 |
+
}
|
| 110 |
+
|
| 111 |
+
// Refresh was successful! Update the reader's location and the request object.
|
| 112 |
+
r.location = newFile.Location
|
| 113 |
+
req.Location = newFile.Location
|
| 114 |
+
r.log.Info("File reference refreshed successfully. Retrying file download.")
|
| 115 |
+
|
| 116 |
+
// Retry the download with the new, valid reference.
|
| 117 |
+
res, err = r.client.API().UploadGetFile(r.ctx, req)
|
| 118 |
+
}
|
| 119 |
+
}
|
| 120 |
+
|
| 121 |
+
// After the potential retry, check for errors one last time.
|
| 122 |
if err != nil {
|
| 123 |
return nil, err
|
| 124 |
}
|