Skip to content

Instantly share code, notes, and snippets.

@PaulSonOfLars
Created December 24, 2021 09:56
Show Gist options
  • Save PaulSonOfLars/49039e6422f21d5f54d0fe06e18d5143 to your computer and use it in GitHub Desktop.
Save PaulSonOfLars/49039e6422f21d5f54d0fe06e18d5143 to your computer and use it in GitHub Desktop.
Telegram Inline query unhasher
import (
"bytes"
"encoding/base64"
"encoding/binary"
"fmt"
"strconv"
)
func UnpackInlineMessageId(inlineMessageId string) (int64, int64, int64, int64, error) {
bs, err := base64.RawURLEncoding.DecodeString(inlineMessageId)
if err != nil {
return 0, 0, 0, 0, fmt.Errorf("failed to base64 decode inline message ID: %w", err)
}
// unsigned 32
dcId, err := readULong(bs[0:4])
if err != nil {
return 0, 0, 0, 0, fmt.Errorf("failed to get DC ID from inline message ID: %w", err)
}
// unsigned 32
messageId, err := readULong(bs[4:8])
if err != nil {
return 0, 0, 0, 0, fmt.Errorf("failed to get message ID from inline message ID: %w", err)
}
// Some odd logic is required to deal with 32/64 bit ids
var chatId int64
var queryId int64
if len(bs) == 20 {
// signed 32
chatId, err = readLong(bs[8:12])
if err != nil {
return 0, 0, 0, 0, fmt.Errorf("failed to get 32bit chat ID from inline message ID: %w", err)
}
// signed 64
queryId, err = readLongLong(bs[12:20])
if err != nil {
return 0, 0, 0, 0, fmt.Errorf("failed to get query ID from inline message ID: %w", err)
}
} else {
// signed 64
chatId, err = readLongLong(bs[8:16])
if err != nil {
return 0, 0, 0, 0, fmt.Errorf("failed to get 64bit chat ID from inline message ID: %w", err)
}
// signed 64
queryId, err = readLongLong(bs[16:24])
if err != nil {
return 0, 0, 0, 0, fmt.Errorf("failed to get query ID from inline message ID: %w", err)
}
}
if chatId < 0 {
fullChatId := "-100" + strconv.FormatInt(-chatId, 10)
chatId, err = strconv.ParseInt(fullChatId, 10, 64)
if err != nil {
return 0, 0, 0, 0, fmt.Errorf("failed to fix chat ID to bot API: %w", err)
}
}
return dcId, messageId, chatId, queryId, nil
}
func readULong(b []byte) (int64, error) {
buf := bytes.NewBuffer(b)
var x uint32
err := binary.Read(buf, binary.LittleEndian, &x)
if err != nil {
return 0, err
}
return int64(x), nil
}
func readLong(b []byte) (int64, error) {
buf := bytes.NewBuffer(b)
var x int32
err := binary.Read(buf, binary.LittleEndian, &x)
if err != nil {
return 0, err
}
return int64(x), nil
}
func readLongLong(b []byte) (int64, error) {
buf := bytes.NewBuffer(b)
var x int64
err := binary.Read(buf, binary.LittleEndian, &x)
if err != nil {
return 0, err
}
return x, nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment