2023-12-08 05:46:06 +08:00
|
|
|
package reader
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"io"
|
|
|
|
|
|
|
|
"github.com/divyam234/teldrive/internal/crypt"
|
|
|
|
"github.com/divyam234/teldrive/pkg/types"
|
|
|
|
"github.com/gotd/td/telegram"
|
|
|
|
)
|
|
|
|
|
|
|
|
type decrpytedReader struct {
|
|
|
|
ctx context.Context
|
|
|
|
parts []types.Part
|
|
|
|
pos int
|
|
|
|
client *telegram.Client
|
|
|
|
reader io.ReadCloser
|
2024-03-10 22:40:09 +08:00
|
|
|
limit int64
|
|
|
|
err error
|
2024-02-12 04:52:41 +08:00
|
|
|
encryptionKey string
|
2023-12-08 05:46:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func NewDecryptedReader(
|
|
|
|
ctx context.Context,
|
|
|
|
client *telegram.Client,
|
|
|
|
parts []types.Part,
|
2024-03-10 22:40:09 +08:00
|
|
|
limit int64,
|
2024-02-12 04:52:41 +08:00
|
|
|
encryptionKey string) (io.ReadCloser, error) {
|
2023-12-08 05:46:06 +08:00
|
|
|
|
|
|
|
r := &decrpytedReader{
|
|
|
|
ctx: ctx,
|
|
|
|
parts: parts,
|
|
|
|
client: client,
|
2024-03-10 22:40:09 +08:00
|
|
|
limit: limit,
|
2024-02-12 04:52:41 +08:00
|
|
|
encryptionKey: encryptionKey,
|
2023-12-08 05:46:06 +08:00
|
|
|
}
|
|
|
|
res, err := r.nextPart()
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
r.reader = res
|
|
|
|
|
|
|
|
return r, nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *decrpytedReader) Read(p []byte) (n int, err error) {
|
|
|
|
|
2024-03-10 22:40:09 +08:00
|
|
|
if r.err != nil {
|
|
|
|
return 0, r.err
|
|
|
|
}
|
|
|
|
|
|
|
|
if r.limit <= 0 {
|
|
|
|
return 0, io.EOF
|
|
|
|
}
|
|
|
|
|
2023-12-08 05:46:06 +08:00
|
|
|
n, err = r.reader.Read(p)
|
|
|
|
|
2024-03-10 22:40:09 +08:00
|
|
|
if err == nil {
|
|
|
|
r.limit -= int64(n)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err == io.EOF {
|
|
|
|
if r.limit > 0 {
|
|
|
|
err = nil
|
|
|
|
}
|
2023-12-08 05:46:06 +08:00
|
|
|
r.pos++
|
|
|
|
if r.pos < len(r.parts) {
|
2024-03-10 22:40:09 +08:00
|
|
|
r.reader, err = newTGReader(r.ctx, r.client, r.parts[r.pos])
|
2023-12-08 05:46:06 +08:00
|
|
|
}
|
|
|
|
}
|
2024-03-10 22:40:09 +08:00
|
|
|
r.err = err
|
|
|
|
return
|
2023-12-08 05:46:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (r *decrpytedReader) Close() (err error) {
|
|
|
|
if r.reader != nil {
|
|
|
|
err = r.reader.Close()
|
|
|
|
r.reader = nil
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *decrpytedReader) nextPart() (io.ReadCloser, error) {
|
|
|
|
|
2024-02-12 04:52:41 +08:00
|
|
|
cipher, _ := crypt.NewCipher(r.encryptionKey, r.parts[r.pos].Salt)
|
2023-12-08 15:46:05 +08:00
|
|
|
|
|
|
|
return cipher.DecryptDataSeek(r.ctx,
|
2023-12-08 05:46:06 +08:00
|
|
|
func(ctx context.Context,
|
|
|
|
underlyingOffset,
|
|
|
|
underlyingLimit int64) (io.ReadCloser, error) {
|
|
|
|
|
|
|
|
var end int64
|
|
|
|
|
|
|
|
if underlyingLimit >= 0 {
|
|
|
|
end = min(r.parts[r.pos].Size-1, underlyingOffset+underlyingLimit-1)
|
|
|
|
}
|
|
|
|
|
2024-03-10 22:40:09 +08:00
|
|
|
return newTGReader(r.ctx, r.client, types.Part{
|
2023-12-08 05:46:06 +08:00
|
|
|
Start: underlyingOffset,
|
|
|
|
End: end,
|
|
|
|
Location: r.parts[r.pos].Location,
|
|
|
|
})
|
|
|
|
}, r.parts[r.pos].Start, r.parts[r.pos].End-r.parts[r.pos].Start+1)
|
|
|
|
|
|
|
|
}
|