Skip to content

Commit 25f0bee

Browse files
authored
add gramjs support (#110)
* Add gramjs.go * Update sessionConstructor.go support gramjs * Create main.go Create gramjs examples * Update gramjs.go
1 parent f663025 commit 25f0bee

File tree

3 files changed

+144
-0
lines changed

3 files changed

+144
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"log"
6+
7+
"github.com/celestix/gotgproto"
8+
"github.com/celestix/gotgproto/sessionMaker"
9+
)
10+
11+
func main() {
12+
client, err := gotgproto.NewClient(
13+
// Get AppID from https://my.telegram.org/apps
14+
123456,
15+
// Get ApiHash from https://my.telegram.org/apps
16+
"API_HASH_HERE",
17+
// ClientType, as we defined above
18+
gotgproto.ClientTypePhone("PHONE_NUMBER_HERE"),
19+
// Optional parameters of client
20+
&gotgproto.ClientOpts{
21+
Session: sessionMaker.GramjsSession("enter session string here").
22+
// Sqlite session name (if you're not using memory session)
23+
// i.e. InMemory in ClientOpts is set to false
24+
// It will be saved as my_session.session as per this example.
25+
Name("my_session"),
26+
},
27+
)
28+
if err != nil {
29+
log.Fatalln("failed to start client:", err)
30+
}
31+
32+
fmt.Printf("client (@%s) has been started...\n", client.Self.Username)
33+
34+
client.Idle()
35+
}

sessionMaker/gramjs.go

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package sessionMaker
2+
3+
import (
4+
"encoding/base64"
5+
"encoding/binary"
6+
"net"
7+
"strconv"
8+
"bytes"
9+
"github.com/go-faster/errors"
10+
"github.com/gotd/td/session"
11+
"github.com/gotd/td/crypto"
12+
)
13+
14+
func DecodeGramjsSession(hx string) (*session.Data, error) {
15+
return decodeGramjsSession(hx)
16+
}
17+
18+
func decodeGramjsSession(sessionStr string) (*session.Data, error) {
19+
data := struct {
20+
Version string
21+
DCID uint8
22+
ServerAddress string
23+
Port int16
24+
Key []byte
25+
AuthKey string
26+
KeyId string
27+
}{}
28+
29+
if len(sessionStr) == 0 || sessionStr[0] != '1' {
30+
return nil, errors.New("invalid session string")
31+
}
32+
strsession := sessionStr[1:]
33+
decodedBytes, err := base64.StdEncoding.DecodeString(strsession)
34+
if err != nil {
35+
return nil, err
36+
}
37+
38+
reader := bytes.NewReader(decodedBytes)
39+
40+
data.Version = "1"
41+
42+
err = binary.Read(reader, binary.BigEndian, &data.DCID)
43+
if err != nil {
44+
return nil, err
45+
}
46+
47+
addressLength := make([]byte, 2)
48+
_, err = reader.Read(addressLength)
49+
if err != nil {
50+
return nil, err
51+
}
52+
53+
addressLen := int(binary.BigEndian.Uint16(addressLength))
54+
addressBuffer := make([]byte, addressLen)
55+
_, err = reader.Read(addressBuffer)
56+
if err != nil {
57+
return nil, err
58+
}
59+
data.ServerAddress = string(bytes.TrimRight(addressBuffer, "\x00"))
60+
61+
portBuffer := make([]byte, 2)
62+
_, err = reader.Read(portBuffer)
63+
if err != nil {
64+
return nil, err
65+
}
66+
data.Port = int16(binary.BigEndian.Uint16(portBuffer))
67+
68+
keyLength := len(decodedBytes) - (5 + addressLen) // DCID(1 byte), Address Length(2 bytes), Address, Port(2 bytes)
69+
data.Key = make([]byte, keyLength)
70+
_, err = reader.Read(data.Key)
71+
if err != nil {
72+
return nil, err
73+
}
74+
75+
data.AuthKey = base64.StdEncoding.EncodeToString(data.Key)
76+
keyid := crypto.Key(data.Key).WithID().ID
77+
data.KeyId = base64.StdEncoding.EncodeToString(keyid[:])
78+
return &session.Data{
79+
DC: int(data.DCID),
80+
Addr: net.JoinHostPort(data.ServerAddress, strconv.Itoa(int(data.Port))),
81+
AuthKey: data.Key,
82+
AuthKeyID: keyid[:],
83+
}, nil
84+
}

sessionMaker/sessionConstructor.go

+25
Original file line numberDiff line numberDiff line change
@@ -157,3 +157,28 @@ func (s *TdataSessionConstructor) loadSession() (sessionName, []byte, error) {
157157
})
158158
return sessionNameString(s.name), data, err
159159
}
160+
161+
type GramjsSessionConstructor struct {
162+
name, value string
163+
}
164+
165+
func GramjsSession(value string) *GramjsSessionConstructor {
166+
return &GramjsSessionConstructor{value: value}
167+
}
168+
169+
func (s *GramjsSessionConstructor) Name(name string) *GramjsSessionConstructor {
170+
s.name = name
171+
return s
172+
}
173+
174+
func (s *GramjsSessionConstructor) loadSession() (sessionName, []byte, error) {
175+
sd, err := DecodeGramjsSession(s.value)
176+
if err != nil {
177+
return sessionNameString(s.name), nil, err
178+
}
179+
data, err := json.Marshal(jsonData{
180+
Version: storage.LatestVersion,
181+
Data: *sd,
182+
})
183+
return sessionNameString(s.name), data, err
184+
}

0 commit comments

Comments
 (0)