Skip to content

Commit

Permalink
Add files via upload
Browse files Browse the repository at this point in the history
  • Loading branch information
0xzer authored Aug 26, 2023
1 parent 0d8b9fe commit f519e30
Show file tree
Hide file tree
Showing 50 changed files with 3,439 additions and 0 deletions.
30 changes: 30 additions & 0 deletions byter/byter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package byter

import (
"bytes"
"reflect"
)

var stringLengthTags = map[string]reflect.Kind{
"uint8": reflect.Uint8,
"uint16": reflect.Uint16,
"uint32": reflect.Uint32,
"uint64": reflect.Uint64,
"int8": reflect.Uint8,
"byte": reflect.Uint8,
"int16": reflect.Int16,
"int32": reflect.Int32,
"int64": reflect.Int64,
}

type byter struct {
Buff *bytes.Buffer
}

type EnumMarker interface {
IsEnum()
}

func (b *byter) isEnum(field reflect.Value) bool {
return field.CanInterface() && reflect.PtrTo(field.Type()).Implements(reflect.TypeOf((*EnumMarker)(nil)).Elem())
}
124 changes: 124 additions & 0 deletions byter/read.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package byter

import (
"bytes"
"encoding/binary"
"errors"
"fmt"
"log"
"reflect"
)

func NewReader(data []byte) *byter {
return &byter{
Buff: bytes.NewBuffer(data),
}
}

func (b *byter) readInteger(kind reflect.Kind, size int, endian string) uint64 {
buffer := make([]byte, size)
_, err := b.Buff.Read(buffer)
if err != nil {
log.Printf("Error reading integer: %v\n", err)
return 0
}

if kind == reflect.Uint8 {
return uint64(buffer[0])
}

switch endian {
case "big":
switch kind {
case reflect.Uint16:
return uint64(binary.BigEndian.Uint16(buffer))
case reflect.Uint32:
return uint64(binary.BigEndian.Uint32(buffer))
case reflect.Uint64:
return binary.BigEndian.Uint64(buffer)
}
case "little":
switch kind {
case reflect.Uint16:
return uint64(binary.LittleEndian.Uint16(buffer))
case reflect.Uint32:
return uint64(binary.LittleEndian.Uint32(buffer))
case reflect.Uint64:
return binary.LittleEndian.Uint64(buffer)
}
}

log.Printf("Unsupported endianness: %s\n", endian)
return 0
}

func (b *byter) ReadToStruct(s interface{}) error {
values := reflect.ValueOf(s)
if values.Kind() == reflect.Ptr && values.Elem().Kind() == reflect.Struct {
values = values.Elem()
} else {
return fmt.Errorf("expected a pointer to a struct")
}

for i := 0; i < values.NumField(); i++ {
field := values.Field(i)
if !field.CanSet() {
continue
}
switch field.Kind() {
case reflect.Bool:
boolByte := b.Buff.Next(1)
field.SetBool(boolByte[0] != 0)
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
hasVLQTag := values.Type().Field(i).Tag.Get("vlq")
if hasVLQTag != "" {
uintValue, err := b.DecodeVLQ()
if err != nil {
return err
}
field.SetUint(uint64(uintValue))
} else {
size := int(field.Type().Size())
endianess := values.Type().Field(i).Tag.Get("endian")
uintValue := b.readInteger(field.Kind(), size, endianess)
field.SetUint(uintValue)
}
case reflect.String:
strLen, _ := binary.ReadUvarint(b.Buff)
data := make([]byte, strLen)
b.Buff.Read(data)
field.SetString(string(data))
case reflect.Interface:
if field.IsNil() {
continue
}
default:
return fmt.Errorf("unsupported type %s for field %s", field.Type(), values.Type().Field(i).Name)
}
}

return nil
}

func (b *byter) DecodeVLQ() (int, error) {
multiplier := 1
value := 0
var encodedByte byte
var err error

for {
encodedByte, err = b.Buff.ReadByte()
if err != nil {
return 0, err
}
value += int(encodedByte&0x7F) * multiplier
if multiplier > 2097152 {
return 0, errors.New("malformed remaining length")
}
multiplier *= 128
if (encodedByte & 0x80) == 0 {
break
}
}
return value, nil
}
137 changes: 137 additions & 0 deletions byter/write.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package byter

import (
"bytes"
"encoding/binary"
"fmt"
"log"
"reflect"
)

func NewWriter() *byter {
return &byter{
Buff: bytes.NewBuffer(make([]byte, 0)),
}
}

func (b *byter) writeInteger(value uint64, kind reflect.Kind, endian string) error {
if kind == reflect.Uint8 {
return b.Buff.WriteByte(byte(value))
}

if endian == "" {
endian = "big"
}
switch endian {
case "big":
switch kind {
case reflect.Uint16:
return binary.Write(b.Buff, binary.BigEndian, uint16(value))
case reflect.Uint32:
return binary.Write(b.Buff, binary.BigEndian, uint32(value))
case reflect.Uint64:
return binary.Write(b.Buff, binary.BigEndian, value)
}
case "little":
switch kind {
case reflect.Uint16:
return binary.Write(b.Buff, binary.LittleEndian, uint16(value))
case reflect.Uint32:
return binary.Write(b.Buff, binary.LittleEndian, uint32(value))
case reflect.Uint64:
return binary.Write(b.Buff, binary.LittleEndian, value)
}
default:
return fmt.Errorf("received unsupported endianness while trying to write %v: %s", kind, endian)
}

return nil
}

func (b *byter) WriteFromStruct(s interface{}) ([]byte, error) {
values := reflect.ValueOf(s)
if values.Kind() == reflect.Ptr && values.Elem().Kind() == reflect.Struct {
values = values.Elem()
} else {
return nil, fmt.Errorf("expected a struct")
}

for i := 0; i < values.NumField(); i++ {
field := values.Field(i)
switch field.Kind() {
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
if b.isEnum(field) {
enumValue := uint8(field.Uint()) // TO-DO: support all int vals
b.Buff.WriteByte(enumValue)
continue
}
hasVLQTag := values.Type().Field(i).Tag.Get("vlq")
if hasVLQTag != "" {
err := b.EncodeVLQ(int(field.Uint())) // Convert to int because our VLQ function takes an int
if err != nil {
return nil, err
}
continue
} else {
endianess := values.Type().Field(i).Tag.Get("endian")
err := b.writeInteger(field.Uint(), field.Kind(), endianess)
if err != nil {
return nil, err
}
}
case reflect.String:
str := field.String()
f := values.Type().Field(i)
lengthType := f.Tag.Get("lengthType")
endianess := f.Tag.Get("endian")
err := b.writeString(str, lengthType, endianess)
if err != nil {
return nil, err
}
/*
case reflect.Struct:
sBytes, err := b.WriteFromStruct(field)
if err != nil {
return nil, err
}
b.Buff.Write(sBytes)
*/
default:
log.Printf("Unsupported type %s for field %s\n", field.Type(), values.Type().Field(i).Name)
}
}

return b.Buff.Bytes(), nil
}

func (b *byter) writeString(s string, lengthType string, endianess string) error {
if endianess == "" {
endianess = "big"
}

b.writeInteger(uint64(len(s)), stringLengthTags[lengthType], endianess)
_, err := b.Buff.Write([]byte(s))
return err
}

func (b *byter) EncodeVLQ(value int) error {
var encodedByte byte
for {
encodedByte = byte(value & 0x7F)
value >>= 7
if value > 0 {
encodedByte |= 0x80
}

err := b.Buff.WriteByte(encodedByte)
if err != nil {
return err
}

if value == 0 {
break
}
}

return nil
}
91 changes: 91 additions & 0 deletions client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package messagix

import (
"encoding/json"
"log"
"net/http"
"net/url"
"os"

"github.com/0xzer/messagix/types"
"github.com/rs/zerolog"
)

var USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36"

type EventHandler func(evt interface{})
type Proxy func(*http.Request) (*url.URL, error)
type Client struct {
http *http.Client
socket *Socket
taskManager *TaskManager
eventHandler EventHandler
configs *Configs

Logger zerolog.Logger
cookies *types.Cookies
proxy Proxy
}

// pass an empty zerolog.Logger{} for no logging
func NewClient(cookies *types.Cookies, logger zerolog.Logger, proxy Proxy) *Client {
if cookies == nil {
log.Fatal("cookie struct can not be nil")
}

cli := &Client{
http: &http.Client{
Transport: &http.Transport{
Proxy: proxy,
},
},
cookies: cookies,
proxy: proxy,
Logger: logger,
}

socket := cli.NewSocketClient()
cli.socket = socket

cli.configs = &Configs{client: cli}

moduleLoader := &ModuleParser{}
moduleLoader.load()


configSetupErr := cli.configs.SetupConfigs()
if configSetupErr != nil {
log.Fatal(configSetupErr)
}

taskManager := &TaskManager{client: cli, activeTaskIds: make([]int, 0), currTasks: make([]TaskData, 0)}
cli.taskManager = taskManager

cli.taskManager.AddNewTask(&GetContactsTask{Limit: 100})

log.Println(cli.taskManager.FinalizePayload())
os.Exit(1)
return cli
}

func (c *Client) SetEventHandler(handler EventHandler) {
c.eventHandler = handler
}

// Sets the topics the client should subscribe to
func (c *Client) SetTopics(topics []Topic) {
c.socket.setTopics(topics)
}

func (c *Client) Connect() error {
return c.socket.Connect()
}

func (c *Client) SaveSession(path string) error {
jsonBytes, err := json.Marshal(c.cookies)
if err != nil {
return err
}

return os.WriteFile(path, jsonBytes, os.ModePerm)
}
Loading

0 comments on commit f519e30

Please sign in to comment.