mirror of
https://github.com/tiennm99/export-telegram-group-members.git
synced 2026-10-15 14:16:27 +00:00
refactor(store): drop the Telethon session import
The Go session is already stored, so the one-time conversion from the Python version's Telethon session is no longer needed. Remove it along with its tests and the README upgrade section.
This commit is contained in:
1 parent
d041503a47
commit
56d71a0e79
5 files changed
+9
-95
No files matched your search
@@ -147,14 +147,6 @@ All groups in one crawl share one timestamp. The login session grants full
|
||||
account access, so restrict Redis access accordingly; deleting
|
||||
`telegram-export:session-gotd` forces a clean re-login.
|
||||
|
||||
### Upgrading from the Python version
|
||||
|
||||
The config and export keys keep the same format, so existing crawls stay
|
||||
readable by `compare` and `export`. The Python version kept a Telethon session
|
||||
under `telegram-export:session`. On first run, the Go version converts it into
|
||||
`telegram-export:session-gotd`, so you do not need a new login code. The old key
|
||||
is only read, never changed, and can be deleted afterwards.
|
||||
|
||||
## Development
|
||||
|
||||
```bash
|
||||
|
||||
@@ -24,7 +24,7 @@ func TestConfigRoundTrip(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadConfigReadsPythonWrittenJSON(t *testing.T) {
|
||||
func TestLoadConfigReadsStoredJSON(t *testing.T) {
|
||||
st, mr := newTestStore(t)
|
||||
mr.Set("telegram-export:config",
|
||||
`{"api_id": 123, "api_hash": "hash", "phone": "+1555", "group_ids": [-1001234567890]}`)
|
||||
|
||||
@@ -11,12 +11,7 @@ import (
|
||||
|
||||
// The login session grants full account access; it lives only in Redis
|
||||
// (behind TLS/auth), never on local disk. Deleting it forces a clean re-login.
|
||||
//
|
||||
// The Python version stored a Telethon StringSession under "session". This
|
||||
// version keeps its own format under a separate key and only reads the old
|
||||
// one once, so an existing login carries over without a new code.
|
||||
func sessionKey() string { return key("session-gotd") }
|
||||
func telethonSessionKey() string { return key("session") }
|
||||
func sessionKey() string { return key("session-gotd") }
|
||||
|
||||
// SessionStorage implements gotd's session.Storage on Redis.
|
||||
type SessionStorage struct {
|
||||
@@ -28,33 +23,16 @@ func (s *Store) SessionStorage() *SessionStorage {
|
||||
return &SessionStorage{store: s}
|
||||
}
|
||||
|
||||
// LoadSession returns the stored session, importing a Telethon session when
|
||||
// no gotd session exists yet.
|
||||
// LoadSession returns the stored session, or session.ErrNotFound before the
|
||||
// first login.
|
||||
func (ss *SessionStorage) LoadSession(ctx context.Context) ([]byte, error) {
|
||||
raw, err := ss.store.rdb.Get(ctx, sessionKey()).Bytes()
|
||||
if err == nil {
|
||||
return raw, nil
|
||||
if errors.Is(err, redis.Nil) {
|
||||
return nil, session.ErrNotFound
|
||||
}
|
||||
if !errors.Is(err, redis.Nil) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("read session: %w", err)
|
||||
}
|
||||
|
||||
telethon, err := ss.store.rdb.Get(ctx, telethonSessionKey()).Result()
|
||||
if errors.Is(err, redis.Nil) || telethon == "" {
|
||||
return nil, session.ErrNotFound
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("read Telethon session: %w", err)
|
||||
}
|
||||
|
||||
raw, err = convertTelethonSession(ctx, telethon)
|
||||
if err != nil {
|
||||
// An unreadable old session should mean a fresh login, not a dead end.
|
||||
return nil, session.ErrNotFound
|
||||
}
|
||||
if err := ss.StoreSession(ctx, raw); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return raw, nil
|
||||
}
|
||||
|
||||
@@ -65,15 +43,3 @@ func (ss *SessionStorage) StoreSession(ctx context.Context, data []byte) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func convertTelethonSession(ctx context.Context, telethon string) ([]byte, error) {
|
||||
data, err := session.TelethonSession(telethon)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var mem session.StorageMemory
|
||||
if err := (&session.Loader{Storage: &mem}).Save(ctx, data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return mem.LoadSession(ctx)
|
||||
}
|
||||
@@ -1,23 +1,13 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/gotd/td/session"
|
||||
)
|
||||
|
||||
// telethonString builds a Telethon StringSession: version "1" plus base64
|
||||
// of DC ID, IPv4, port, and a 256-byte auth key.
|
||||
func telethonString(dc byte) string {
|
||||
raw := []byte{dc, 149, 154, 167, 51, 0x01, 0xbb}
|
||||
raw = append(raw, bytes.Repeat([]byte{7}, 256)...)
|
||||
return "1" + base64.URLEncoding.EncodeToString(raw)
|
||||
}
|
||||
|
||||
func TestLoadSessionNotFound(t *testing.T) {
|
||||
st, _ := newTestStore(t)
|
||||
|
||||
@@ -39,37 +29,3 @@ func TestSessionRoundTrip(t *testing.T) {
|
||||
t.Fatalf("LoadSession = %q, %v", got, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadSessionImportsTelethonSession(t *testing.T) {
|
||||
st, mr := newTestStore(t)
|
||||
ctx := context.Background()
|
||||
mr.Set("telegram-export:session", telethonString(2))
|
||||
|
||||
raw, err := st.SessionStorage().LoadSession(ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("LoadSession: %v", err)
|
||||
}
|
||||
data, err := (&session.Loader{Storage: st.SessionStorage()}).Load(ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("Loader.Load: %v", err)
|
||||
}
|
||||
if data.DC != 2 || data.Addr != "149.154.167.51:443" {
|
||||
t.Fatalf("imported session DC=%d Addr=%q", data.DC, data.Addr)
|
||||
}
|
||||
if stored, _ := mr.Get("telegram-export:session-gotd"); stored != string(raw) {
|
||||
t.Fatal("imported session was not saved under the gotd key")
|
||||
}
|
||||
if old, _ := mr.Get("telegram-export:session"); old != telethonString(2) {
|
||||
t.Fatal("Telethon session key was modified")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadSessionIgnoresBrokenTelethonSession(t *testing.T) {
|
||||
st, mr := newTestStore(t)
|
||||
mr.Set("telegram-export:session", "not-a-session")
|
||||
|
||||
_, err := st.SessionStorage().LoadSession(context.Background())
|
||||
if !errors.Is(err, session.ErrNotFound) {
|
||||
t.Fatalf("LoadSession error = %v, want session.ErrNotFound", err)
|
||||
}
|
||||
}
|
||||
@@ -22,8 +22,8 @@ type groupRef struct {
|
||||
id int64
|
||||
}
|
||||
|
||||
// parseGroupID splits a marked ID (as Telethon and the Python version store
|
||||
// it) into a basic group or a channel/supergroup and its raw Telegram ID.
|
||||
// parseGroupID splits a marked ID (as configured and stored) into a basic
|
||||
// group or a channel/supergroup and its raw Telegram ID.
|
||||
func parseGroupID(markedID int64) (groupRef, error) {
|
||||
switch {
|
||||
case markedID <= -channelIDOffset:
|
||||
|
||||
Reference in new issue
Block a user