Add initial Google Messages library
This commit is contained in:
parent
a8bdcb2750
commit
02ef5ab82c
72 changed files with 12059 additions and 0 deletions
637
libgm/binary/client.pb.go
Normal file
637
libgm/binary/client.pb.go
Normal file
|
@ -0,0 +1,637 @@
|
|||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.30.0
|
||||
// protoc v3.21.12
|
||||
// source: client.proto
|
||||
|
||||
package binary
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type SendMessage struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
PairedDevice *Device `protobuf:"bytes,1,opt,name=pairedDevice,proto3" json:"pairedDevice,omitempty"`
|
||||
MessageData *MessageData `protobuf:"bytes,2,opt,name=messageData,proto3" json:"messageData,omitempty"`
|
||||
AuthData *AuthMessage `protobuf:"bytes,3,opt,name=authData,proto3" json:"authData,omitempty"`
|
||||
Ttl int64 `protobuf:"varint,5,opt,name=ttl,proto3" json:"ttl,omitempty"`
|
||||
EmptyArr *EmptyArr `protobuf:"bytes,9,opt,name=emptyArr,proto3" json:"emptyArr,omitempty"`
|
||||
}
|
||||
|
||||
func (x *SendMessage) Reset() {
|
||||
*x = SendMessage{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_client_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *SendMessage) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*SendMessage) ProtoMessage() {}
|
||||
|
||||
func (x *SendMessage) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_client_proto_msgTypes[0]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use SendMessage.ProtoReflect.Descriptor instead.
|
||||
func (*SendMessage) Descriptor() ([]byte, []int) {
|
||||
return file_client_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *SendMessage) GetPairedDevice() *Device {
|
||||
if x != nil {
|
||||
return x.PairedDevice
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *SendMessage) GetMessageData() *MessageData {
|
||||
if x != nil {
|
||||
return x.MessageData
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *SendMessage) GetAuthData() *AuthMessage {
|
||||
if x != nil {
|
||||
return x.AuthData
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *SendMessage) GetTtl() int64 {
|
||||
if x != nil {
|
||||
return x.Ttl
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *SendMessage) GetEmptyArr() *EmptyArr {
|
||||
if x != nil {
|
||||
return x.EmptyArr
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type AckMessagePayload struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
AuthData *AuthMessage `protobuf:"bytes,1,opt,name=authData,proto3" json:"authData,omitempty"`
|
||||
EmptyArr *EmptyArr `protobuf:"bytes,2,opt,name=emptyArr,proto3" json:"emptyArr,omitempty"`
|
||||
NoClue []byte `protobuf:"bytes,3,opt,name=noClue,proto3" json:"noClue,omitempty"`
|
||||
}
|
||||
|
||||
func (x *AckMessagePayload) Reset() {
|
||||
*x = AckMessagePayload{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_client_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *AckMessagePayload) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*AckMessagePayload) ProtoMessage() {}
|
||||
|
||||
func (x *AckMessagePayload) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_client_proto_msgTypes[1]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use AckMessagePayload.ProtoReflect.Descriptor instead.
|
||||
func (*AckMessagePayload) Descriptor() ([]byte, []int) {
|
||||
return file_client_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *AckMessagePayload) GetAuthData() *AuthMessage {
|
||||
if x != nil {
|
||||
return x.AuthData
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *AckMessagePayload) GetEmptyArr() *EmptyArr {
|
||||
if x != nil {
|
||||
return x.EmptyArr
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *AckMessagePayload) GetNoClue() []byte {
|
||||
if x != nil {
|
||||
return x.NoClue
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type AckMessageData struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"`
|
||||
Device *Device `protobuf:"bytes,2,opt,name=device,proto3" json:"device,omitempty"`
|
||||
}
|
||||
|
||||
func (x *AckMessageData) Reset() {
|
||||
*x = AckMessageData{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_client_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *AckMessageData) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*AckMessageData) ProtoMessage() {}
|
||||
|
||||
func (x *AckMessageData) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_client_proto_msgTypes[2]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use AckMessageData.ProtoReflect.Descriptor instead.
|
||||
func (*AckMessageData) Descriptor() ([]byte, []int) {
|
||||
return file_client_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *AckMessageData) GetRequestId() string {
|
||||
if x != nil {
|
||||
return x.RequestId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *AckMessageData) GetDevice() *Device {
|
||||
if x != nil {
|
||||
return x.Device
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ImageMetaData struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
ImageId string `protobuf:"bytes,1,opt,name=imageId,proto3" json:"imageId,omitempty"`
|
||||
Encrypted bool `protobuf:"varint,2,opt,name=encrypted,proto3" json:"encrypted,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ImageMetaData) Reset() {
|
||||
*x = ImageMetaData{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_client_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ImageMetaData) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ImageMetaData) ProtoMessage() {}
|
||||
|
||||
func (x *ImageMetaData) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_client_proto_msgTypes[3]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ImageMetaData.ProtoReflect.Descriptor instead.
|
||||
func (*ImageMetaData) Descriptor() ([]byte, []int) {
|
||||
return file_client_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
func (x *ImageMetaData) GetImageId() string {
|
||||
if x != nil {
|
||||
return x.ImageId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ImageMetaData) GetEncrypted() bool {
|
||||
if x != nil {
|
||||
return x.Encrypted
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type UploadImagePayload struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
MetaData *ImageMetaData `protobuf:"bytes,1,opt,name=metaData,proto3" json:"metaData,omitempty"`
|
||||
AuthData *AuthMessageBytes `protobuf:"bytes,2,opt,name=authData,proto3" json:"authData,omitempty"`
|
||||
}
|
||||
|
||||
func (x *UploadImagePayload) Reset() {
|
||||
*x = UploadImagePayload{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_client_proto_msgTypes[4]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *UploadImagePayload) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*UploadImagePayload) ProtoMessage() {}
|
||||
|
||||
func (x *UploadImagePayload) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_client_proto_msgTypes[4]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use UploadImagePayload.ProtoReflect.Descriptor instead.
|
||||
func (*UploadImagePayload) Descriptor() ([]byte, []int) {
|
||||
return file_client_proto_rawDescGZIP(), []int{4}
|
||||
}
|
||||
|
||||
func (x *UploadImagePayload) GetMetaData() *ImageMetaData {
|
||||
if x != nil {
|
||||
return x.MetaData
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *UploadImagePayload) GetAuthData() *AuthMessageBytes {
|
||||
if x != nil {
|
||||
return x.AuthData
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type BugleBackendService struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Data *BugleCode `protobuf:"bytes,6,opt,name=data,proto3" json:"data,omitempty"`
|
||||
}
|
||||
|
||||
func (x *BugleBackendService) Reset() {
|
||||
*x = BugleBackendService{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_client_proto_msgTypes[5]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *BugleBackendService) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*BugleBackendService) ProtoMessage() {}
|
||||
|
||||
func (x *BugleBackendService) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_client_proto_msgTypes[5]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use BugleBackendService.ProtoReflect.Descriptor instead.
|
||||
func (*BugleBackendService) Descriptor() ([]byte, []int) {
|
||||
return file_client_proto_rawDescGZIP(), []int{5}
|
||||
}
|
||||
|
||||
func (x *BugleBackendService) GetData() *BugleCode {
|
||||
if x != nil {
|
||||
return x.Data
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type BugleCode struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Type int64 `protobuf:"varint,2,opt,name=type,proto3" json:"type,omitempty"`
|
||||
}
|
||||
|
||||
func (x *BugleCode) Reset() {
|
||||
*x = BugleCode{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_client_proto_msgTypes[6]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *BugleCode) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*BugleCode) ProtoMessage() {}
|
||||
|
||||
func (x *BugleCode) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_client_proto_msgTypes[6]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use BugleCode.ProtoReflect.Descriptor instead.
|
||||
func (*BugleCode) Descriptor() ([]byte, []int) {
|
||||
return file_client_proto_rawDescGZIP(), []int{6}
|
||||
}
|
||||
|
||||
func (x *BugleCode) GetType() int64 {
|
||||
if x != nil {
|
||||
return x.Type
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
var File_client_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_client_proto_rawDesc = []byte{
|
||||
0x0a, 0x0c, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06,
|
||||
0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x1a, 0x0e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73,
|
||||
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xf1, 0x01, 0x0a, 0x0b, 0x53, 0x65, 0x6e, 0x64, 0x4d,
|
||||
0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x34, 0x0a, 0x0c, 0x70, 0x61, 0x69, 0x72, 0x65, 0x64,
|
||||
0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d,
|
||||
0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x0c,
|
||||
0x70, 0x61, 0x69, 0x72, 0x65, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x37, 0x0a, 0x0b,
|
||||
0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x44, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||
0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x4d, 0x65, 0x73,
|
||||
0x73, 0x61, 0x67, 0x65, 0x44, 0x61, 0x74, 0x61, 0x52, 0x0b, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
|
||||
0x65, 0x44, 0x61, 0x74, 0x61, 0x12, 0x31, 0x0a, 0x08, 0x61, 0x75, 0x74, 0x68, 0x44, 0x61, 0x74,
|
||||
0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
|
||||
0x65, 0x73, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x08,
|
||||
0x61, 0x75, 0x74, 0x68, 0x44, 0x61, 0x74, 0x61, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x74, 0x6c, 0x18,
|
||||
0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x74, 0x74, 0x6c, 0x12, 0x2e, 0x0a, 0x08, 0x65, 0x6d,
|
||||
0x70, 0x74, 0x79, 0x41, 0x72, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d,
|
||||
0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x41, 0x72, 0x72,
|
||||
0x52, 0x08, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x41, 0x72, 0x72, 0x22, 0x8e, 0x01, 0x0a, 0x11, 0x41,
|
||||
0x63, 0x6b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64,
|
||||
0x12, 0x31, 0x0a, 0x08, 0x61, 0x75, 0x74, 0x68, 0x44, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x41, 0x75,
|
||||
0x74, 0x68, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x08, 0x61, 0x75, 0x74, 0x68, 0x44,
|
||||
0x61, 0x74, 0x61, 0x12, 0x2e, 0x0a, 0x08, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x41, 0x72, 0x72, 0x18,
|
||||
0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73,
|
||||
0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x41, 0x72, 0x72, 0x52, 0x08, 0x65, 0x6d, 0x70, 0x74, 0x79,
|
||||
0x41, 0x72, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x6f, 0x43, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20,
|
||||
0x01, 0x28, 0x0c, 0x52, 0x06, 0x6e, 0x6f, 0x43, 0x6c, 0x75, 0x65, 0x22, 0x59, 0x0a, 0x0e, 0x41,
|
||||
0x63, 0x6b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x44, 0x61, 0x74, 0x61, 0x12, 0x1d, 0x0a,
|
||||
0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x06,
|
||||
0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d,
|
||||
0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x06,
|
||||
0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x22, 0x47, 0x0a, 0x0d, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x4d,
|
||||
0x65, 0x74, 0x61, 0x44, 0x61, 0x74, 0x61, 0x12, 0x18, 0x0a, 0x07, 0x69, 0x6d, 0x61, 0x67, 0x65,
|
||||
0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x49,
|
||||
0x64, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x18, 0x02,
|
||||
0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x22,
|
||||
0x7f, 0x0a, 0x12, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x50, 0x61,
|
||||
0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x31, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x44, 0x61, 0x74,
|
||||
0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74,
|
||||
0x2e, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x44, 0x61, 0x74, 0x61, 0x52, 0x08,
|
||||
0x6d, 0x65, 0x74, 0x61, 0x44, 0x61, 0x74, 0x61, 0x12, 0x36, 0x0a, 0x08, 0x61, 0x75, 0x74, 0x68,
|
||||
0x44, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x65, 0x73,
|
||||
0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
|
||||
0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x52, 0x08, 0x61, 0x75, 0x74, 0x68, 0x44, 0x61, 0x74, 0x61,
|
||||
0x22, 0x3c, 0x0a, 0x13, 0x42, 0x75, 0x67, 0x6c, 0x65, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64,
|
||||
0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x25, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18,
|
||||
0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x42,
|
||||
0x75, 0x67, 0x6c, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x1f,
|
||||
0x0a, 0x09, 0x42, 0x75, 0x67, 0x6c, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74,
|
||||
0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x42,
|
||||
0x0e, 0x5a, 0x0c, 0x2e, 0x2e, 0x2f, 0x2e, 0x2e, 0x2f, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x62,
|
||||
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_client_proto_rawDescOnce sync.Once
|
||||
file_client_proto_rawDescData = file_client_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_client_proto_rawDescGZIP() []byte {
|
||||
file_client_proto_rawDescOnce.Do(func() {
|
||||
file_client_proto_rawDescData = protoimpl.X.CompressGZIP(file_client_proto_rawDescData)
|
||||
})
|
||||
return file_client_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_client_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
|
||||
var file_client_proto_goTypes = []interface{}{
|
||||
(*SendMessage)(nil), // 0: client.SendMessage
|
||||
(*AckMessagePayload)(nil), // 1: client.AckMessagePayload
|
||||
(*AckMessageData)(nil), // 2: client.AckMessageData
|
||||
(*ImageMetaData)(nil), // 3: client.ImageMetaData
|
||||
(*UploadImagePayload)(nil), // 4: client.UploadImagePayload
|
||||
(*BugleBackendService)(nil), // 5: client.BugleBackendService
|
||||
(*BugleCode)(nil), // 6: client.BugleCode
|
||||
(*Device)(nil), // 7: messages.Device
|
||||
(*MessageData)(nil), // 8: messages.MessageData
|
||||
(*AuthMessage)(nil), // 9: messages.AuthMessage
|
||||
(*EmptyArr)(nil), // 10: messages.EmptyArr
|
||||
(*AuthMessageBytes)(nil), // 11: messages.AuthMessageBytes
|
||||
}
|
||||
var file_client_proto_depIdxs = []int32{
|
||||
7, // 0: client.SendMessage.pairedDevice:type_name -> messages.Device
|
||||
8, // 1: client.SendMessage.messageData:type_name -> messages.MessageData
|
||||
9, // 2: client.SendMessage.authData:type_name -> messages.AuthMessage
|
||||
10, // 3: client.SendMessage.emptyArr:type_name -> messages.EmptyArr
|
||||
9, // 4: client.AckMessagePayload.authData:type_name -> messages.AuthMessage
|
||||
10, // 5: client.AckMessagePayload.emptyArr:type_name -> messages.EmptyArr
|
||||
7, // 6: client.AckMessageData.device:type_name -> messages.Device
|
||||
3, // 7: client.UploadImagePayload.metaData:type_name -> client.ImageMetaData
|
||||
11, // 8: client.UploadImagePayload.authData:type_name -> messages.AuthMessageBytes
|
||||
6, // 9: client.BugleBackendService.data:type_name -> client.BugleCode
|
||||
10, // [10:10] is the sub-list for method output_type
|
||||
10, // [10:10] is the sub-list for method input_type
|
||||
10, // [10:10] is the sub-list for extension type_name
|
||||
10, // [10:10] is the sub-list for extension extendee
|
||||
0, // [0:10] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_client_proto_init() }
|
||||
func file_client_proto_init() {
|
||||
if File_client_proto != nil {
|
||||
return
|
||||
}
|
||||
file_messages_proto_init()
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_client_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*SendMessage); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_client_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*AckMessagePayload); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_client_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*AckMessageData); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_client_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ImageMetaData); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_client_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*UploadImagePayload); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_client_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*BugleBackendService); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_client_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*BugleCode); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_client_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 7,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_client_proto_goTypes,
|
||||
DependencyIndexes: file_client_proto_depIdxs,
|
||||
MessageInfos: file_client_proto_msgTypes,
|
||||
}.Build()
|
||||
File_client_proto = out.File
|
||||
file_client_proto_rawDesc = nil
|
||||
file_client_proto_goTypes = nil
|
||||
file_client_proto_depIdxs = nil
|
||||
}
|
2314
libgm/binary/conversations.pb.go
Normal file
2314
libgm/binary/conversations.pb.go
Normal file
File diff suppressed because it is too large
Load diff
424
libgm/binary/events.pb.go
Normal file
424
libgm/binary/events.pb.go
Normal file
|
@ -0,0 +1,424 @@
|
|||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.30.0
|
||||
// protoc v3.21.12
|
||||
// source: events.proto
|
||||
|
||||
package binary
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type Event struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// Types that are assignable to Event:
|
||||
//
|
||||
// *Event_ConversationEvent
|
||||
// *Event_MessageEvent
|
||||
// *Event_UserAlertEvent
|
||||
Event isEvent_Event `protobuf_oneof:"event"`
|
||||
}
|
||||
|
||||
func (x *Event) Reset() {
|
||||
*x = Event{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_events_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *Event) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Event) ProtoMessage() {}
|
||||
|
||||
func (x *Event) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_events_proto_msgTypes[0]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use Event.ProtoReflect.Descriptor instead.
|
||||
func (*Event) Descriptor() ([]byte, []int) {
|
||||
return file_events_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (m *Event) GetEvent() isEvent_Event {
|
||||
if m != nil {
|
||||
return m.Event
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Event) GetConversationEvent() *ConversationEvent {
|
||||
if x, ok := x.GetEvent().(*Event_ConversationEvent); ok {
|
||||
return x.ConversationEvent
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Event) GetMessageEvent() *MessageEvent {
|
||||
if x, ok := x.GetEvent().(*Event_MessageEvent); ok {
|
||||
return x.MessageEvent
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Event) GetUserAlertEvent() *UserAlertEvent {
|
||||
if x, ok := x.GetEvent().(*Event_UserAlertEvent); ok {
|
||||
return x.UserAlertEvent
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type isEvent_Event interface {
|
||||
isEvent_Event()
|
||||
}
|
||||
|
||||
type Event_ConversationEvent struct {
|
||||
ConversationEvent *ConversationEvent `protobuf:"bytes,2,opt,name=conversationEvent,proto3,oneof"`
|
||||
}
|
||||
|
||||
type Event_MessageEvent struct {
|
||||
MessageEvent *MessageEvent `protobuf:"bytes,3,opt,name=messageEvent,proto3,oneof"`
|
||||
}
|
||||
|
||||
type Event_UserAlertEvent struct {
|
||||
UserAlertEvent *UserAlertEvent `protobuf:"bytes,6,opt,name=userAlertEvent,proto3,oneof"`
|
||||
}
|
||||
|
||||
func (*Event_ConversationEvent) isEvent_Event() {}
|
||||
|
||||
func (*Event_MessageEvent) isEvent_Event() {}
|
||||
|
||||
func (*Event_UserAlertEvent) isEvent_Event() {}
|
||||
|
||||
type ConversationEvent struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Data *Conversation `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ConversationEvent) Reset() {
|
||||
*x = ConversationEvent{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_events_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ConversationEvent) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ConversationEvent) ProtoMessage() {}
|
||||
|
||||
func (x *ConversationEvent) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_events_proto_msgTypes[1]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ConversationEvent.ProtoReflect.Descriptor instead.
|
||||
func (*ConversationEvent) Descriptor() ([]byte, []int) {
|
||||
return file_events_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *ConversationEvent) GetData() *Conversation {
|
||||
if x != nil {
|
||||
return x.Data
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type MessageEvent struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Data *Message `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
|
||||
}
|
||||
|
||||
func (x *MessageEvent) Reset() {
|
||||
*x = MessageEvent{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_events_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *MessageEvent) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*MessageEvent) ProtoMessage() {}
|
||||
|
||||
func (x *MessageEvent) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_events_proto_msgTypes[2]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use MessageEvent.ProtoReflect.Descriptor instead.
|
||||
func (*MessageEvent) Descriptor() ([]byte, []int) {
|
||||
return file_events_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *MessageEvent) GetData() *Message {
|
||||
if x != nil {
|
||||
return x.Data
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type UserAlertEvent struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// 2 = BROWSER_ACTIVE (new session created in other browser)
|
||||
//
|
||||
// 1 = ?
|
||||
//
|
||||
// 8 = INACTIVE_LACK_OF_ACTIVITY
|
||||
//
|
||||
// 7 = INACTIVE_TIMEOUT
|
||||
//
|
||||
// 5|6 = BATTERY (tf?)
|
||||
//
|
||||
// 3|4 = DATA_CONNECTION (tf?)
|
||||
//
|
||||
// 10 = OBSERVER_REGISTERED (tf?)
|
||||
AlertType int64 `protobuf:"varint,2,opt,name=alert_type,json=alertType,proto3" json:"alert_type,omitempty"`
|
||||
}
|
||||
|
||||
func (x *UserAlertEvent) Reset() {
|
||||
*x = UserAlertEvent{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_events_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *UserAlertEvent) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*UserAlertEvent) ProtoMessage() {}
|
||||
|
||||
func (x *UserAlertEvent) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_events_proto_msgTypes[3]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use UserAlertEvent.ProtoReflect.Descriptor instead.
|
||||
func (*UserAlertEvent) Descriptor() ([]byte, []int) {
|
||||
return file_events_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
func (x *UserAlertEvent) GetAlertType() int64 {
|
||||
if x != nil {
|
||||
return x.AlertType
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
var File_events_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_events_proto_rawDesc = []byte{
|
||||
0x0a, 0x0c, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06,
|
||||
0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x1a, 0x0e, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73,
|
||||
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x0e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73,
|
||||
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x13, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xd9, 0x01, 0x0a, 0x05,
|
||||
0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x49, 0x0a, 0x11, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73,
|
||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
|
||||
0x32, 0x19, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72,
|
||||
0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x11, 0x63,
|
||||
0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74,
|
||||
0x12, 0x3a, 0x0a, 0x0c, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74,
|
||||
0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e,
|
||||
0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0c,
|
||||
0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x40, 0x0a, 0x0e,
|
||||
0x75, 0x73, 0x65, 0x72, 0x41, 0x6c, 0x65, 0x72, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x06,
|
||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x55, 0x73,
|
||||
0x65, 0x72, 0x41, 0x6c, 0x65, 0x72, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0e,
|
||||
0x75, 0x73, 0x65, 0x72, 0x41, 0x6c, 0x65, 0x72, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x42, 0x07,
|
||||
0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x22, 0x44, 0x0a, 0x11, 0x43, 0x6f, 0x6e, 0x76, 0x65,
|
||||
0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x2f, 0x0a, 0x04,
|
||||
0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x63, 0x6f, 0x6e,
|
||||
0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x76, 0x65,
|
||||
0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x3a, 0x0a,
|
||||
0x0c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x2a, 0x0a,
|
||||
0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x6f,
|
||||
0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4d, 0x65, 0x73, 0x73,
|
||||
0x61, 0x67, 0x65, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x2f, 0x0a, 0x0e, 0x55, 0x73, 0x65,
|
||||
0x72, 0x41, 0x6c, 0x65, 0x72, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x61,
|
||||
0x6c, 0x65, 0x72, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52,
|
||||
0x09, 0x61, 0x6c, 0x65, 0x72, 0x74, 0x54, 0x79, 0x70, 0x65, 0x42, 0x0e, 0x5a, 0x0c, 0x2e, 0x2e,
|
||||
0x2f, 0x2e, 0x2e, 0x2f, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_events_proto_rawDescOnce sync.Once
|
||||
file_events_proto_rawDescData = file_events_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_events_proto_rawDescGZIP() []byte {
|
||||
file_events_proto_rawDescOnce.Do(func() {
|
||||
file_events_proto_rawDescData = protoimpl.X.CompressGZIP(file_events_proto_rawDescData)
|
||||
})
|
||||
return file_events_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_events_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
|
||||
var file_events_proto_goTypes = []interface{}{
|
||||
(*Event)(nil), // 0: events.Event
|
||||
(*ConversationEvent)(nil), // 1: events.ConversationEvent
|
||||
(*MessageEvent)(nil), // 2: events.MessageEvent
|
||||
(*UserAlertEvent)(nil), // 3: events.UserAlertEvent
|
||||
(*Conversation)(nil), // 4: conversations.Conversation
|
||||
(*Message)(nil), // 5: conversations.Message
|
||||
}
|
||||
var file_events_proto_depIdxs = []int32{
|
||||
1, // 0: events.Event.conversationEvent:type_name -> events.ConversationEvent
|
||||
2, // 1: events.Event.messageEvent:type_name -> events.MessageEvent
|
||||
3, // 2: events.Event.userAlertEvent:type_name -> events.UserAlertEvent
|
||||
4, // 3: events.ConversationEvent.data:type_name -> conversations.Conversation
|
||||
5, // 4: events.MessageEvent.data:type_name -> conversations.Message
|
||||
5, // [5:5] is the sub-list for method output_type
|
||||
5, // [5:5] is the sub-list for method input_type
|
||||
5, // [5:5] is the sub-list for extension type_name
|
||||
5, // [5:5] is the sub-list for extension extendee
|
||||
0, // [0:5] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_events_proto_init() }
|
||||
func file_events_proto_init() {
|
||||
if File_events_proto != nil {
|
||||
return
|
||||
}
|
||||
file_settings_proto_init()
|
||||
file_messages_proto_init()
|
||||
file_conversations_proto_init()
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_events_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*Event); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_events_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ConversationEvent); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_events_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*MessageEvent); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_events_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*UserAlertEvent); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
file_events_proto_msgTypes[0].OneofWrappers = []interface{}{
|
||||
(*Event_ConversationEvent)(nil),
|
||||
(*Event_MessageEvent)(nil),
|
||||
(*Event_UserAlertEvent)(nil),
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_events_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 4,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_events_proto_goTypes,
|
||||
DependencyIndexes: file_events_proto_depIdxs,
|
||||
MessageInfos: file_events_proto_msgTypes,
|
||||
}.Build()
|
||||
File_events_proto = out.File
|
||||
file_events_proto_rawDesc = nil
|
||||
file_events_proto_goTypes = nil
|
||||
file_events_proto_depIdxs = nil
|
||||
}
|
318
libgm/binary/media.pb.go
Normal file
318
libgm/binary/media.pb.go
Normal file
|
@ -0,0 +1,318 @@
|
|||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.30.0
|
||||
// protoc v3.21.12
|
||||
// source: media.proto
|
||||
|
||||
package binary
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type StartMediaUploadPayload struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
ImageType int64 `protobuf:"varint,1,opt,name=imageType,proto3" json:"imageType,omitempty"`
|
||||
AuthData *AuthMessageBytes `protobuf:"bytes,2,opt,name=authData,proto3" json:"authData,omitempty"`
|
||||
Mobile *Device `protobuf:"bytes,3,opt,name=mobile,proto3" json:"mobile,omitempty"`
|
||||
}
|
||||
|
||||
func (x *StartMediaUploadPayload) Reset() {
|
||||
*x = StartMediaUploadPayload{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_media_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *StartMediaUploadPayload) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*StartMediaUploadPayload) ProtoMessage() {}
|
||||
|
||||
func (x *StartMediaUploadPayload) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_media_proto_msgTypes[0]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use StartMediaUploadPayload.ProtoReflect.Descriptor instead.
|
||||
func (*StartMediaUploadPayload) Descriptor() ([]byte, []int) {
|
||||
return file_media_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *StartMediaUploadPayload) GetImageType() int64 {
|
||||
if x != nil {
|
||||
return x.ImageType
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *StartMediaUploadPayload) GetAuthData() *AuthMessageBytes {
|
||||
if x != nil {
|
||||
return x.AuthData
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *StartMediaUploadPayload) GetMobile() *Device {
|
||||
if x != nil {
|
||||
return x.Mobile
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type UploadMediaResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Media *Media `protobuf:"bytes,1,opt,name=media,proto3" json:"media,omitempty"`
|
||||
Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"`
|
||||
}
|
||||
|
||||
func (x *UploadMediaResponse) Reset() {
|
||||
*x = UploadMediaResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_media_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *UploadMediaResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*UploadMediaResponse) ProtoMessage() {}
|
||||
|
||||
func (x *UploadMediaResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_media_proto_msgTypes[1]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use UploadMediaResponse.ProtoReflect.Descriptor instead.
|
||||
func (*UploadMediaResponse) Descriptor() ([]byte, []int) {
|
||||
return file_media_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *UploadMediaResponse) GetMedia() *Media {
|
||||
if x != nil {
|
||||
return x.Media
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *UploadMediaResponse) GetMessage() string {
|
||||
if x != nil {
|
||||
return x.Message
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type Media struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
MediaId string `protobuf:"bytes,1,opt,name=mediaId,proto3" json:"mediaId,omitempty"`
|
||||
MediaNumber int64 `protobuf:"varint,2,opt,name=mediaNumber,proto3" json:"mediaNumber,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Media) Reset() {
|
||||
*x = Media{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_media_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *Media) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Media) ProtoMessage() {}
|
||||
|
||||
func (x *Media) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_media_proto_msgTypes[2]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use Media.ProtoReflect.Descriptor instead.
|
||||
func (*Media) Descriptor() ([]byte, []int) {
|
||||
return file_media_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *Media) GetMediaId() string {
|
||||
if x != nil {
|
||||
return x.MediaId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Media) GetMediaNumber() int64 {
|
||||
if x != nil {
|
||||
return x.MediaNumber
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
var File_media_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_media_proto_rawDesc = []byte{
|
||||
0x0a, 0x0b, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x6d,
|
||||
0x65, 0x64, 0x69, 0x61, 0x1a, 0x0e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x22, 0x99, 0x01, 0x0a, 0x17, 0x53, 0x74, 0x61, 0x72, 0x74, 0x4d, 0x65,
|
||||
0x64, 0x69, 0x61, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64,
|
||||
0x12, 0x1c, 0x0a, 0x09, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x03, 0x52, 0x09, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x36,
|
||||
0x0a, 0x08, 0x61, 0x75, 0x74, 0x68, 0x44, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
|
||||
0x32, 0x1a, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x41, 0x75, 0x74, 0x68,
|
||||
0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x52, 0x08, 0x61, 0x75,
|
||||
0x74, 0x68, 0x44, 0x61, 0x74, 0x61, 0x12, 0x28, 0x0a, 0x06, 0x6d, 0x6f, 0x62, 0x69, 0x6c, 0x65,
|
||||
0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
|
||||
0x73, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x06, 0x6d, 0x6f, 0x62, 0x69, 0x6c, 0x65,
|
||||
0x22, 0x53, 0x0a, 0x13, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x4d, 0x65, 0x64, 0x69, 0x61, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x22, 0x0a, 0x05, 0x6d, 0x65, 0x64, 0x69, 0x61,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2e, 0x4d,
|
||||
0x65, 0x64, 0x69, 0x61, 0x52, 0x05, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x12, 0x18, 0x0a, 0x07, 0x6d,
|
||||
0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65,
|
||||
0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x43, 0x0a, 0x05, 0x4d, 0x65, 0x64, 0x69, 0x61, 0x12, 0x18,
|
||||
0x0a, 0x07, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x07, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x49, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x6d, 0x65, 0x64, 0x69,
|
||||
0x61, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x6d,
|
||||
0x65, 0x64, 0x69, 0x61, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x42, 0x0e, 0x5a, 0x0c, 0x2e, 0x2e,
|
||||
0x2f, 0x2e, 0x2e, 0x2f, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_media_proto_rawDescOnce sync.Once
|
||||
file_media_proto_rawDescData = file_media_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_media_proto_rawDescGZIP() []byte {
|
||||
file_media_proto_rawDescOnce.Do(func() {
|
||||
file_media_proto_rawDescData = protoimpl.X.CompressGZIP(file_media_proto_rawDescData)
|
||||
})
|
||||
return file_media_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_media_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
|
||||
var file_media_proto_goTypes = []interface{}{
|
||||
(*StartMediaUploadPayload)(nil), // 0: media.StartMediaUploadPayload
|
||||
(*UploadMediaResponse)(nil), // 1: media.UploadMediaResponse
|
||||
(*Media)(nil), // 2: media.Media
|
||||
(*AuthMessageBytes)(nil), // 3: messages.AuthMessageBytes
|
||||
(*Device)(nil), // 4: messages.Device
|
||||
}
|
||||
var file_media_proto_depIdxs = []int32{
|
||||
3, // 0: media.StartMediaUploadPayload.authData:type_name -> messages.AuthMessageBytes
|
||||
4, // 1: media.StartMediaUploadPayload.mobile:type_name -> messages.Device
|
||||
2, // 2: media.UploadMediaResponse.media:type_name -> media.Media
|
||||
3, // [3:3] is the sub-list for method output_type
|
||||
3, // [3:3] is the sub-list for method input_type
|
||||
3, // [3:3] is the sub-list for extension type_name
|
||||
3, // [3:3] is the sub-list for extension extendee
|
||||
0, // [0:3] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_media_proto_init() }
|
||||
func file_media_proto_init() {
|
||||
if File_media_proto != nil {
|
||||
return
|
||||
}
|
||||
file_messages_proto_init()
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_media_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*StartMediaUploadPayload); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_media_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*UploadMediaResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_media_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*Media); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_media_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 3,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_media_proto_goTypes,
|
||||
DependencyIndexes: file_media_proto_depIdxs,
|
||||
MessageInfos: file_media_proto_msgTypes,
|
||||
}.Build()
|
||||
File_media_proto = out.File
|
||||
file_media_proto_rawDesc = nil
|
||||
file_media_proto_goTypes = nil
|
||||
file_media_proto_depIdxs = nil
|
||||
}
|
1086
libgm/binary/messages.pb.go
Normal file
1086
libgm/binary/messages.pb.go
Normal file
File diff suppressed because it is too large
Load diff
689
libgm/binary/pairing.pb.go
Normal file
689
libgm/binary/pairing.pb.go
Normal file
|
@ -0,0 +1,689 @@
|
|||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.30.0
|
||||
// protoc v3.21.12
|
||||
// source: pairing.proto
|
||||
|
||||
package binary
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type BrowserDetails struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
UserAgent string `protobuf:"bytes,1,opt,name=user_agent,json=userAgent,proto3" json:"user_agent,omitempty"`
|
||||
SomeInt int32 `protobuf:"varint,2,opt,name=someInt,proto3" json:"someInt,omitempty"`
|
||||
Os string `protobuf:"bytes,3,opt,name=os,proto3" json:"os,omitempty"`
|
||||
SomeBool bool `protobuf:"varint,6,opt,name=someBool,proto3" json:"someBool,omitempty"`
|
||||
}
|
||||
|
||||
func (x *BrowserDetails) Reset() {
|
||||
*x = BrowserDetails{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_pairing_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *BrowserDetails) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*BrowserDetails) ProtoMessage() {}
|
||||
|
||||
func (x *BrowserDetails) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_pairing_proto_msgTypes[0]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use BrowserDetails.ProtoReflect.Descriptor instead.
|
||||
func (*BrowserDetails) Descriptor() ([]byte, []int) {
|
||||
return file_pairing_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *BrowserDetails) GetUserAgent() string {
|
||||
if x != nil {
|
||||
return x.UserAgent
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *BrowserDetails) GetSomeInt() int32 {
|
||||
if x != nil {
|
||||
return x.SomeInt
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *BrowserDetails) GetOs() string {
|
||||
if x != nil {
|
||||
return x.Os
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *BrowserDetails) GetSomeBool() bool {
|
||||
if x != nil {
|
||||
return x.SomeBool
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type PhoneRelayBody struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||
Bugle string `protobuf:"bytes,3,opt,name=bugle,proto3" json:"bugle,omitempty"`
|
||||
RpcKey []byte `protobuf:"bytes,6,opt,name=rpcKey,proto3" json:"rpcKey,omitempty"`
|
||||
Date *Date `protobuf:"bytes,7,opt,name=date,proto3" json:"date,omitempty"`
|
||||
}
|
||||
|
||||
func (x *PhoneRelayBody) Reset() {
|
||||
*x = PhoneRelayBody{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_pairing_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *PhoneRelayBody) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*PhoneRelayBody) ProtoMessage() {}
|
||||
|
||||
func (x *PhoneRelayBody) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_pairing_proto_msgTypes[1]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use PhoneRelayBody.ProtoReflect.Descriptor instead.
|
||||
func (*PhoneRelayBody) Descriptor() ([]byte, []int) {
|
||||
return file_pairing_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *PhoneRelayBody) GetId() string {
|
||||
if x != nil {
|
||||
return x.Id
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *PhoneRelayBody) GetBugle() string {
|
||||
if x != nil {
|
||||
return x.Bugle
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *PhoneRelayBody) GetRpcKey() []byte {
|
||||
if x != nil {
|
||||
return x.RpcKey
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *PhoneRelayBody) GetDate() *Date {
|
||||
if x != nil {
|
||||
return x.Date
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ECDSAKeys struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
ProtoVersion int64 `protobuf:"varint,1,opt,name=protoVersion,proto3" json:"protoVersion,omitempty"` // idk?
|
||||
EncryptedKeys []byte `protobuf:"bytes,2,opt,name=encryptedKeys,proto3" json:"encryptedKeys,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ECDSAKeys) Reset() {
|
||||
*x = ECDSAKeys{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_pairing_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ECDSAKeys) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ECDSAKeys) ProtoMessage() {}
|
||||
|
||||
func (x *ECDSAKeys) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_pairing_proto_msgTypes[2]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ECDSAKeys.ProtoReflect.Descriptor instead.
|
||||
func (*ECDSAKeys) Descriptor() ([]byte, []int) {
|
||||
return file_pairing_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *ECDSAKeys) GetProtoVersion() int64 {
|
||||
if x != nil {
|
||||
return x.ProtoVersion
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *ECDSAKeys) GetEncryptedKeys() []byte {
|
||||
if x != nil {
|
||||
return x.EncryptedKeys
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type PairDeviceData struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Mobile *Device `protobuf:"bytes,1,opt,name=mobile,proto3" json:"mobile,omitempty"`
|
||||
EcdsaKeys *ECDSAKeys `protobuf:"bytes,6,opt,name=ecdsaKeys,proto3" json:"ecdsaKeys,omitempty"`
|
||||
WebAuthKeyData *WebAuthKey `protobuf:"bytes,2,opt,name=webAuthKeyData,proto3" json:"webAuthKeyData,omitempty"`
|
||||
Browser *Device `protobuf:"bytes,3,opt,name=browser,proto3" json:"browser,omitempty"`
|
||||
}
|
||||
|
||||
func (x *PairDeviceData) Reset() {
|
||||
*x = PairDeviceData{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_pairing_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *PairDeviceData) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*PairDeviceData) ProtoMessage() {}
|
||||
|
||||
func (x *PairDeviceData) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_pairing_proto_msgTypes[3]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use PairDeviceData.ProtoReflect.Descriptor instead.
|
||||
func (*PairDeviceData) Descriptor() ([]byte, []int) {
|
||||
return file_pairing_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
func (x *PairDeviceData) GetMobile() *Device {
|
||||
if x != nil {
|
||||
return x.Mobile
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *PairDeviceData) GetEcdsaKeys() *ECDSAKeys {
|
||||
if x != nil {
|
||||
return x.EcdsaKeys
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *PairDeviceData) GetWebAuthKeyData() *WebAuthKey {
|
||||
if x != nil {
|
||||
return x.WebAuthKeyData
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *PairDeviceData) GetBrowser() *Device {
|
||||
if x != nil {
|
||||
return x.Browser
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type WebAuthKey struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
WebAuthKey []byte `protobuf:"bytes,1,opt,name=webAuthKey,proto3" json:"webAuthKey,omitempty"`
|
||||
ValidFor int64 `protobuf:"varint,2,opt,name=validFor,proto3" json:"validFor,omitempty"`
|
||||
}
|
||||
|
||||
func (x *WebAuthKey) Reset() {
|
||||
*x = WebAuthKey{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_pairing_proto_msgTypes[4]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *WebAuthKey) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*WebAuthKey) ProtoMessage() {}
|
||||
|
||||
func (x *WebAuthKey) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_pairing_proto_msgTypes[4]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use WebAuthKey.ProtoReflect.Descriptor instead.
|
||||
func (*WebAuthKey) Descriptor() ([]byte, []int) {
|
||||
return file_pairing_proto_rawDescGZIP(), []int{4}
|
||||
}
|
||||
|
||||
func (x *WebAuthKey) GetWebAuthKey() []byte {
|
||||
if x != nil {
|
||||
return x.WebAuthKey
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *WebAuthKey) GetValidFor() int64 {
|
||||
if x != nil {
|
||||
return x.ValidFor
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type Container struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
PhoneRelay *PhoneRelayBody `protobuf:"bytes,1,opt,name=PhoneRelay,proto3" json:"PhoneRelay,omitempty"`
|
||||
BrowserDetails *BrowserDetails `protobuf:"bytes,3,opt,name=browserDetails,proto3" json:"browserDetails,omitempty"`
|
||||
PairDeviceData *PairDeviceData `protobuf:"bytes,4,opt,name=pairDeviceData,proto3" json:"pairDeviceData,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Container) Reset() {
|
||||
*x = Container{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_pairing_proto_msgTypes[5]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *Container) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Container) ProtoMessage() {}
|
||||
|
||||
func (x *Container) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_pairing_proto_msgTypes[5]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use Container.ProtoReflect.Descriptor instead.
|
||||
func (*Container) Descriptor() ([]byte, []int) {
|
||||
return file_pairing_proto_rawDescGZIP(), []int{5}
|
||||
}
|
||||
|
||||
func (x *Container) GetPhoneRelay() *PhoneRelayBody {
|
||||
if x != nil {
|
||||
return x.PhoneRelay
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Container) GetBrowserDetails() *BrowserDetails {
|
||||
if x != nil {
|
||||
return x.BrowserDetails
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Container) GetPairDeviceData() *PairDeviceData {
|
||||
if x != nil {
|
||||
return x.PairDeviceData
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type UrlData struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
PairingKey []byte `protobuf:"bytes,1,opt,name=pairingKey,proto3" json:"pairingKey,omitempty"`
|
||||
AES_CTR_KEY_256 []byte `protobuf:"bytes,2,opt,name=AES_CTR_KEY_256,json=AESCTRKEY256,proto3" json:"AES_CTR_KEY_256,omitempty"`
|
||||
SHA_256_KEY []byte `protobuf:"bytes,3,opt,name=SHA_256_KEY,json=SHA256KEY,proto3" json:"SHA_256_KEY,omitempty"`
|
||||
}
|
||||
|
||||
func (x *UrlData) Reset() {
|
||||
*x = UrlData{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_pairing_proto_msgTypes[6]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *UrlData) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*UrlData) ProtoMessage() {}
|
||||
|
||||
func (x *UrlData) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_pairing_proto_msgTypes[6]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use UrlData.ProtoReflect.Descriptor instead.
|
||||
func (*UrlData) Descriptor() ([]byte, []int) {
|
||||
return file_pairing_proto_rawDescGZIP(), []int{6}
|
||||
}
|
||||
|
||||
func (x *UrlData) GetPairingKey() []byte {
|
||||
if x != nil {
|
||||
return x.PairingKey
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *UrlData) GetAES_CTR_KEY_256() []byte {
|
||||
if x != nil {
|
||||
return x.AES_CTR_KEY_256
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *UrlData) GetSHA_256_KEY() []byte {
|
||||
if x != nil {
|
||||
return x.SHA_256_KEY
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var File_pairing_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_pairing_proto_rawDesc = []byte{
|
||||
0x0a, 0x0d, 0x70, 0x61, 0x69, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
|
||||
0x07, 0x70, 0x61, 0x69, 0x72, 0x69, 0x6e, 0x67, 0x1a, 0x0e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
|
||||
0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x75, 0x0a, 0x0e, 0x42, 0x72, 0x6f, 0x77,
|
||||
0x73, 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x73,
|
||||
0x65, 0x72, 0x5f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
|
||||
0x75, 0x73, 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x6f, 0x6d,
|
||||
0x65, 0x49, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x73, 0x6f, 0x6d, 0x65,
|
||||
0x49, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x02, 0x6f, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x6f, 0x6d, 0x65, 0x42, 0x6f, 0x6f, 0x6c, 0x18,
|
||||
0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x73, 0x6f, 0x6d, 0x65, 0x42, 0x6f, 0x6f, 0x6c, 0x22,
|
||||
0x72, 0x0a, 0x0e, 0x50, 0x68, 0x6f, 0x6e, 0x65, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x42, 0x6f, 0x64,
|
||||
0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69,
|
||||
0x64, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x75, 0x67, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x05, 0x62, 0x75, 0x67, 0x6c, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x70, 0x63, 0x4b, 0x65,
|
||||
0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x72, 0x70, 0x63, 0x4b, 0x65, 0x79, 0x12,
|
||||
0x22, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e,
|
||||
0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x44, 0x61, 0x74, 0x65, 0x52, 0x04, 0x64,
|
||||
0x61, 0x74, 0x65, 0x22, 0x55, 0x0a, 0x09, 0x45, 0x43, 0x44, 0x53, 0x41, 0x4b, 0x65, 0x79, 0x73,
|
||||
0x12, 0x22, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x56, 0x65, 0x72,
|
||||
0x73, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x0d, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65,
|
||||
0x64, 0x4b, 0x65, 0x79, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x65, 0x6e, 0x63,
|
||||
0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x22, 0xd5, 0x01, 0x0a, 0x0e, 0x50,
|
||||
0x61, 0x69, 0x72, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x12, 0x28, 0x0a,
|
||||
0x06, 0x6d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e,
|
||||
0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52,
|
||||
0x06, 0x6d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x12, 0x30, 0x0a, 0x09, 0x65, 0x63, 0x64, 0x73, 0x61,
|
||||
0x4b, 0x65, 0x79, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x61, 0x69,
|
||||
0x72, 0x69, 0x6e, 0x67, 0x2e, 0x45, 0x43, 0x44, 0x53, 0x41, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x09,
|
||||
0x65, 0x63, 0x64, 0x73, 0x61, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x3b, 0x0a, 0x0e, 0x77, 0x65, 0x62,
|
||||
0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x44, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||
0x0b, 0x32, 0x13, 0x2e, 0x70, 0x61, 0x69, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x57, 0x65, 0x62, 0x41,
|
||||
0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x52, 0x0e, 0x77, 0x65, 0x62, 0x41, 0x75, 0x74, 0x68, 0x4b,
|
||||
0x65, 0x79, 0x44, 0x61, 0x74, 0x61, 0x12, 0x2a, 0x0a, 0x07, 0x62, 0x72, 0x6f, 0x77, 0x73, 0x65,
|
||||
0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
|
||||
0x65, 0x73, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x07, 0x62, 0x72, 0x6f, 0x77, 0x73,
|
||||
0x65, 0x72, 0x22, 0x48, 0x0a, 0x0a, 0x57, 0x65, 0x62, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79,
|
||||
0x12, 0x1e, 0x0a, 0x0a, 0x77, 0x65, 0x62, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x77, 0x65, 0x62, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79,
|
||||
0x12, 0x1a, 0x0a, 0x08, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x46, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01,
|
||||
0x28, 0x03, 0x52, 0x08, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x46, 0x6f, 0x72, 0x22, 0xc6, 0x01, 0x0a,
|
||||
0x09, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x37, 0x0a, 0x0a, 0x50, 0x68,
|
||||
0x6f, 0x6e, 0x65, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17,
|
||||
0x2e, 0x70, 0x61, 0x69, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x68, 0x6f, 0x6e, 0x65, 0x52, 0x65,
|
||||
0x6c, 0x61, 0x79, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x0a, 0x50, 0x68, 0x6f, 0x6e, 0x65, 0x52, 0x65,
|
||||
0x6c, 0x61, 0x79, 0x12, 0x3f, 0x0a, 0x0e, 0x62, 0x72, 0x6f, 0x77, 0x73, 0x65, 0x72, 0x44, 0x65,
|
||||
0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x61,
|
||||
0x69, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x42, 0x72, 0x6f, 0x77, 0x73, 0x65, 0x72, 0x44, 0x65, 0x74,
|
||||
0x61, 0x69, 0x6c, 0x73, 0x52, 0x0e, 0x62, 0x72, 0x6f, 0x77, 0x73, 0x65, 0x72, 0x44, 0x65, 0x74,
|
||||
0x61, 0x69, 0x6c, 0x73, 0x12, 0x3f, 0x0a, 0x0e, 0x70, 0x61, 0x69, 0x72, 0x44, 0x65, 0x76, 0x69,
|
||||
0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70,
|
||||
0x61, 0x69, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x61, 0x69, 0x72, 0x44, 0x65, 0x76, 0x69, 0x63,
|
||||
0x65, 0x44, 0x61, 0x74, 0x61, 0x52, 0x0e, 0x70, 0x61, 0x69, 0x72, 0x44, 0x65, 0x76, 0x69, 0x63,
|
||||
0x65, 0x44, 0x61, 0x74, 0x61, 0x22, 0x70, 0x0a, 0x07, 0x55, 0x72, 0x6c, 0x44, 0x61, 0x74, 0x61,
|
||||
0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x61, 0x69, 0x72, 0x69, 0x6e, 0x67, 0x4b, 0x65, 0x79, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x70, 0x61, 0x69, 0x72, 0x69, 0x6e, 0x67, 0x4b, 0x65, 0x79,
|
||||
0x12, 0x25, 0x0a, 0x0f, 0x41, 0x45, 0x53, 0x5f, 0x43, 0x54, 0x52, 0x5f, 0x4b, 0x45, 0x59, 0x5f,
|
||||
0x32, 0x35, 0x36, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x41, 0x45, 0x53, 0x43, 0x54,
|
||||
0x52, 0x4b, 0x45, 0x59, 0x32, 0x35, 0x36, 0x12, 0x1e, 0x0a, 0x0b, 0x53, 0x48, 0x41, 0x5f, 0x32,
|
||||
0x35, 0x36, 0x5f, 0x4b, 0x45, 0x59, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x53, 0x48,
|
||||
0x41, 0x32, 0x35, 0x36, 0x4b, 0x45, 0x59, 0x42, 0x0e, 0x5a, 0x0c, 0x2e, 0x2e, 0x2f, 0x2e, 0x2e,
|
||||
0x2f, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_pairing_proto_rawDescOnce sync.Once
|
||||
file_pairing_proto_rawDescData = file_pairing_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_pairing_proto_rawDescGZIP() []byte {
|
||||
file_pairing_proto_rawDescOnce.Do(func() {
|
||||
file_pairing_proto_rawDescData = protoimpl.X.CompressGZIP(file_pairing_proto_rawDescData)
|
||||
})
|
||||
return file_pairing_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_pairing_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
|
||||
var file_pairing_proto_goTypes = []interface{}{
|
||||
(*BrowserDetails)(nil), // 0: pairing.BrowserDetails
|
||||
(*PhoneRelayBody)(nil), // 1: pairing.PhoneRelayBody
|
||||
(*ECDSAKeys)(nil), // 2: pairing.ECDSAKeys
|
||||
(*PairDeviceData)(nil), // 3: pairing.PairDeviceData
|
||||
(*WebAuthKey)(nil), // 4: pairing.WebAuthKey
|
||||
(*Container)(nil), // 5: pairing.Container
|
||||
(*UrlData)(nil), // 6: pairing.UrlData
|
||||
(*Date)(nil), // 7: messages.Date
|
||||
(*Device)(nil), // 8: messages.Device
|
||||
}
|
||||
var file_pairing_proto_depIdxs = []int32{
|
||||
7, // 0: pairing.PhoneRelayBody.date:type_name -> messages.Date
|
||||
8, // 1: pairing.PairDeviceData.mobile:type_name -> messages.Device
|
||||
2, // 2: pairing.PairDeviceData.ecdsaKeys:type_name -> pairing.ECDSAKeys
|
||||
4, // 3: pairing.PairDeviceData.webAuthKeyData:type_name -> pairing.WebAuthKey
|
||||
8, // 4: pairing.PairDeviceData.browser:type_name -> messages.Device
|
||||
1, // 5: pairing.Container.PhoneRelay:type_name -> pairing.PhoneRelayBody
|
||||
0, // 6: pairing.Container.browserDetails:type_name -> pairing.BrowserDetails
|
||||
3, // 7: pairing.Container.pairDeviceData:type_name -> pairing.PairDeviceData
|
||||
8, // [8:8] is the sub-list for method output_type
|
||||
8, // [8:8] is the sub-list for method input_type
|
||||
8, // [8:8] is the sub-list for extension type_name
|
||||
8, // [8:8] is the sub-list for extension extendee
|
||||
0, // [0:8] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_pairing_proto_init() }
|
||||
func file_pairing_proto_init() {
|
||||
if File_pairing_proto != nil {
|
||||
return
|
||||
}
|
||||
file_messages_proto_init()
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_pairing_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*BrowserDetails); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_pairing_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*PhoneRelayBody); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_pairing_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ECDSAKeys); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_pairing_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*PairDeviceData); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_pairing_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*WebAuthKey); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_pairing_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*Container); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_pairing_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*UrlData); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_pairing_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 7,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_pairing_proto_goTypes,
|
||||
DependencyIndexes: file_pairing_proto_depIdxs,
|
||||
MessageInfos: file_pairing_proto_msgTypes,
|
||||
}.Build()
|
||||
File_pairing_proto = out.File
|
||||
file_pairing_proto_rawDesc = nil
|
||||
file_pairing_proto_goTypes = nil
|
||||
file_pairing_proto_depIdxs = nil
|
||||
}
|
22
libgm/binary/protoUtil.go
Normal file
22
libgm/binary/protoUtil.go
Normal file
|
@ -0,0 +1,22 @@
|
|||
package binary
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
func EncodeProtoMessage(message proto.Message) ([]byte, error) {
|
||||
data, err := proto.Marshal(message)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to encode proto message: %v", err)
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func DecodeProtoMessage(data []byte, message proto.Message) error {
|
||||
err := proto.Unmarshal(data, message)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to decode proto message: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
43
libgm/binary/raw/client.proto
Normal file
43
libgm/binary/raw/client.proto
Normal file
|
@ -0,0 +1,43 @@
|
|||
syntax = "proto3";
|
||||
package client;
|
||||
|
||||
option go_package = "../../binary";
|
||||
|
||||
import "messages.proto";
|
||||
|
||||
message SendMessage {
|
||||
messages.Device pairedDevice = 1;
|
||||
messages.MessageData messageData = 2;
|
||||
messages.AuthMessage authData = 3;
|
||||
int64 ttl = 5;
|
||||
messages.EmptyArr emptyArr = 9;
|
||||
}
|
||||
|
||||
message AckMessagePayload {
|
||||
messages.AuthMessage authData = 1;
|
||||
messages.EmptyArr emptyArr = 2;
|
||||
bytes noClue = 3;
|
||||
}
|
||||
|
||||
message AckMessageData {
|
||||
string request_id = 1;
|
||||
messages.Device device = 2;
|
||||
}
|
||||
|
||||
message ImageMetaData {
|
||||
string imageId = 1;
|
||||
bool encrypted = 2;
|
||||
}
|
||||
|
||||
message UploadImagePayload {
|
||||
ImageMetaData metaData = 1;
|
||||
messages.AuthMessageBytes authData = 2;
|
||||
}
|
||||
|
||||
message BugleBackendService {
|
||||
BugleCode data = 6;
|
||||
}
|
||||
|
||||
message BugleCode {
|
||||
int64 type = 2;
|
||||
}
|
194
libgm/binary/raw/conversations.proto
Normal file
194
libgm/binary/raw/conversations.proto
Normal file
|
@ -0,0 +1,194 @@
|
|||
syntax = "proto3";
|
||||
package conversations;
|
||||
|
||||
option go_package = "../../binary";
|
||||
|
||||
message SendMessagePayload {
|
||||
string conversationId = 2;
|
||||
MessagePayload messagePayload = 3;
|
||||
string tmpId = 5;
|
||||
}
|
||||
|
||||
message MessagePayload {
|
||||
string tmpId = 1;
|
||||
MessagePayloadContent messagePayloadContent = 6;
|
||||
string conversationId = 7;
|
||||
string selfParticipantId = 9; // might be participantId
|
||||
repeated MessageInfo messageInfo = 10;
|
||||
string tmpId2 = 12;
|
||||
}
|
||||
|
||||
message MessagePayloadContent {
|
||||
MessageContent messageContent = 1;
|
||||
}
|
||||
|
||||
message OpenConversationPayload {
|
||||
string conversationId = 2;
|
||||
}
|
||||
|
||||
message PrepareOpenConversationPayload {
|
||||
int64 field2 = 2; // only seen value 1
|
||||
}
|
||||
|
||||
message FetchConversationMessagesPayload {
|
||||
string conversationId = 2;
|
||||
int64 count = 3;
|
||||
|
||||
Cursor cursor = 5;
|
||||
}
|
||||
|
||||
message ListCoversationsPayload {
|
||||
int64 count = 2; // no idea if this is actually amount to list
|
||||
int64 field4 = 4; // no idea what this is , but only value ive seen is 1
|
||||
}
|
||||
|
||||
message FetchMessagesResponse {
|
||||
repeated Message messages = 2;
|
||||
bytes someBytes = 3;
|
||||
int64 totalMessages = 4;
|
||||
Cursor cursor = 5;
|
||||
}
|
||||
|
||||
message Cursor {
|
||||
string someStr = 1;
|
||||
int64 nextCursor = 2;
|
||||
}
|
||||
|
||||
enum MessageType {
|
||||
UNKNOWN = 0;
|
||||
TEXT = 1;
|
||||
IMAGE = 2;
|
||||
VIDEO = 3;
|
||||
AUDIO = 4;
|
||||
ATTACHMENT = 5;
|
||||
LOCATION = 6;
|
||||
RICH_CARD = 7;
|
||||
VCARD = 8;
|
||||
MMS_NEEDS_DOWNLOAD = 9;
|
||||
REPLY = 10;
|
||||
}
|
||||
|
||||
message Message {
|
||||
string messageId = 1;
|
||||
IsFromMe from = 3;
|
||||
MessageStatus messageStatus = 4;
|
||||
int64 timestamp = 5;
|
||||
string conversationId = 7;
|
||||
string participantId = 9;
|
||||
repeated MessageInfo messageInfo = 10;
|
||||
MessageType type = 11;
|
||||
string tmpId = 12;
|
||||
}
|
||||
|
||||
message MessageInfo {
|
||||
string orderInternal = 1;
|
||||
oneof data {
|
||||
MessageContent messageContent = 2;
|
||||
ImageContent imageContent = 3;
|
||||
}
|
||||
}
|
||||
|
||||
message ImageContent {
|
||||
int64 someNumber = 1;
|
||||
string imageId = 2;
|
||||
string imageName = 4;
|
||||
int64 size = 5;
|
||||
ImagePixels pixels = 6;
|
||||
bytes imageData = 7;
|
||||
string imageId2 = 9;
|
||||
bytes decryptionKey = 11;
|
||||
bytes decryptionKey2 = 12; // same value as decryptionkey?
|
||||
}
|
||||
|
||||
message ImagePixels {
|
||||
int64 width = 1;
|
||||
int64 height = 2;
|
||||
}
|
||||
|
||||
message MessageContent {
|
||||
string content = 1;
|
||||
}
|
||||
|
||||
message IsFromMe {
|
||||
bool fromMe = 1;
|
||||
}
|
||||
|
||||
enum MsgStatusCode {
|
||||
UNKNOWN_STATUS = 0;
|
||||
SENDING = 5;
|
||||
SENT = 1;
|
||||
}
|
||||
|
||||
message MessageStatus {
|
||||
/*
|
||||
// MMS / SMS
|
||||
UNKNOWN_STATUS = 0;
|
||||
SENDING = 5;
|
||||
SENT = 1;
|
||||
|
||||
// RCS
|
||||
READ|SEEN = 11;
|
||||
*/
|
||||
int64 code = 2;
|
||||
string errMsg = 4;
|
||||
string msgStatus = 5;
|
||||
}
|
||||
|
||||
message Conversations {
|
||||
repeated Conversation conversations = 2;
|
||||
}
|
||||
|
||||
message Conversation {
|
||||
string conversationId = 1;
|
||||
string name = 2;
|
||||
LatestMessage latestMessage = 4;
|
||||
int64 timestampMs = 5;
|
||||
|
||||
bool isGroupChat = 10; // not certain
|
||||
string selfParticipantId = 11;
|
||||
/*
|
||||
1 = unarchived
|
||||
2 = archived
|
||||
3 = deleted
|
||||
*/
|
||||
//bool bool1 = 13;
|
||||
int64 status = 12;
|
||||
string hashHex = 15;
|
||||
string messageId = 17;
|
||||
repeated Participant participants = 20;
|
||||
repeated string otherParticipants = 21; // participant ids excluding me
|
||||
int64 type = 22;
|
||||
}
|
||||
|
||||
message Participant {
|
||||
SmallInfo smallInfo = 1;
|
||||
string hashHex = 5;
|
||||
bool isMe = 6;
|
||||
Muted muted = 7;
|
||||
//bool bool2 = 8;
|
||||
int64 bs = 14;
|
||||
string displayName = 15;
|
||||
}
|
||||
|
||||
message SmallInfo {
|
||||
int64 type = 1;
|
||||
string number = 2;
|
||||
string participantId = 3;
|
||||
}
|
||||
|
||||
message LatestMessage {
|
||||
string content = 1;
|
||||
bool fromMe = 2; // isMe?
|
||||
|
||||
string displayName = 4;
|
||||
//Unknown unknown = 5;
|
||||
}
|
||||
|
||||
message Unknown {
|
||||
int64 field1 = 1;
|
||||
int64 field2 = 2;
|
||||
}
|
||||
|
||||
message Muted {
|
||||
bool isMuted = 1;
|
||||
}
|
58
libgm/binary/raw/events.proto
Normal file
58
libgm/binary/raw/events.proto
Normal file
|
@ -0,0 +1,58 @@
|
|||
syntax = "proto3";
|
||||
package events;
|
||||
|
||||
option go_package = "../../binary";
|
||||
|
||||
import "settings.proto";
|
||||
import "messages.proto";
|
||||
import "conversations.proto";
|
||||
|
||||
/*
|
||||
Cases
|
||||
2 = CONVERSATION
|
||||
3 = MESSAGE
|
||||
5 = PHONE SETTINGS
|
||||
|
||||
6 = Cases
|
||||
2 = updated session
|
||||
8 = INACTIVE_LACK_OF_ACTIVITY
|
||||
7 = BROWSER_INACTIVE_FROM_TIMEOUT
|
||||
6|5 = user_alert:battery
|
||||
3|4 = user_alert:data_connection
|
||||
10 = OBSERVER_REGISTERED
|
||||
*/
|
||||
|
||||
message Event {
|
||||
oneof event {
|
||||
ConversationEvent conversationEvent = 2;
|
||||
MessageEvent messageEvent = 3;
|
||||
UserAlertEvent userAlertEvent = 6;
|
||||
}
|
||||
}
|
||||
|
||||
message ConversationEvent {
|
||||
conversations.Conversation data = 2;
|
||||
}
|
||||
|
||||
message MessageEvent {
|
||||
conversations.Message data = 2;
|
||||
}
|
||||
|
||||
message UserAlertEvent {
|
||||
/*
|
||||
2 = BROWSER_ACTIVE (new session created in other browser)
|
||||
|
||||
1 = ?
|
||||
|
||||
8 = INACTIVE_LACK_OF_ACTIVITY
|
||||
|
||||
7 = INACTIVE_TIMEOUT
|
||||
|
||||
5|6 = BATTERY (tf?)
|
||||
|
||||
3|4 = DATA_CONNECTION (tf?)
|
||||
|
||||
10 = OBSERVER_REGISTERED (tf?)
|
||||
*/
|
||||
int64 alert_type = 2;
|
||||
}
|
22
libgm/binary/raw/media.proto
Normal file
22
libgm/binary/raw/media.proto
Normal file
|
@ -0,0 +1,22 @@
|
|||
syntax = "proto3";
|
||||
package media;
|
||||
|
||||
option go_package = "../../binary";
|
||||
|
||||
import "messages.proto";
|
||||
|
||||
message StartMediaUploadPayload {
|
||||
int64 imageType = 1;
|
||||
messages.AuthMessageBytes authData = 2;
|
||||
messages.Device mobile = 3;
|
||||
}
|
||||
|
||||
message UploadMediaResponse {
|
||||
Media media = 1;
|
||||
string message = 2;
|
||||
}
|
||||
|
||||
message Media {
|
||||
string mediaId = 1;
|
||||
int64 mediaNumber = 2;
|
||||
}
|
82
libgm/binary/raw/messages.proto
Normal file
82
libgm/binary/raw/messages.proto
Normal file
|
@ -0,0 +1,82 @@
|
|||
syntax = "proto3";
|
||||
package messages;
|
||||
|
||||
option go_package = "../../binary";
|
||||
|
||||
message EncodedPayload {
|
||||
string request_id = 1;
|
||||
int64 opcode = 2;
|
||||
bytes encryptedData = 5;
|
||||
string session_id = 6;
|
||||
}
|
||||
|
||||
message EncodedResponse {
|
||||
string request_id = 1;
|
||||
//int64 msg = 2;
|
||||
int64 unixNano = 3;
|
||||
int64 opcode = 4;
|
||||
//bytes keyData = 5;
|
||||
bool sub = 6;
|
||||
int64 third = 7;
|
||||
bytes encryptedData = 8;
|
||||
bool field9 = 9;
|
||||
}
|
||||
|
||||
message MessageData {
|
||||
string request_id = 1;
|
||||
int64 routing_op_code = 2;
|
||||
string ts1 = 3;
|
||||
int64 field5 = 5;
|
||||
string ts2 = 6;
|
||||
string someString = 7;
|
||||
Device mobile = 8;
|
||||
Device browser = 9;
|
||||
string encodedData = 12;
|
||||
string encoded_request_id = 17;
|
||||
MsgTypeArr msgTypeArr = 23;
|
||||
}
|
||||
|
||||
message MsgTypeArr {
|
||||
EmptyArr emptyArr = 1;
|
||||
int64 msgType = 2;
|
||||
}
|
||||
|
||||
message EmptyArr {
|
||||
|
||||
}
|
||||
|
||||
message AuthMessage {
|
||||
string request_id = 1;
|
||||
string rpcKey = 6;
|
||||
Date date = 7;
|
||||
}
|
||||
|
||||
message AuthMessageBytes {
|
||||
string request_id = 1;
|
||||
bytes rpcKey = 6;
|
||||
Date date = 7;
|
||||
}
|
||||
|
||||
message BaseData {
|
||||
int64 Ttl = 2;
|
||||
EmptyArr emptyArr = 6;
|
||||
}
|
||||
|
||||
message RPCResponse {
|
||||
bytes unknown = 1;
|
||||
MessageData data = 2;
|
||||
}
|
||||
|
||||
message Device {
|
||||
int64 userId = 1;
|
||||
string registrationId = 2;
|
||||
string network = 3;
|
||||
}
|
||||
|
||||
message Date {
|
||||
int64 year = 3;
|
||||
int64 seq1 = 4;
|
||||
int64 seq2 = 5;
|
||||
int64 seq3 = 7;
|
||||
int64 seq4 = 9;
|
||||
}
|
49
libgm/binary/raw/pairing.proto
Normal file
49
libgm/binary/raw/pairing.proto
Normal file
|
@ -0,0 +1,49 @@
|
|||
syntax = "proto3";
|
||||
package pairing;
|
||||
|
||||
option go_package = "../../binary";
|
||||
|
||||
import "messages.proto";
|
||||
|
||||
message BrowserDetails {
|
||||
string user_agent = 1;
|
||||
int32 someInt = 2;
|
||||
string os = 3;
|
||||
bool someBool = 6;
|
||||
}
|
||||
|
||||
message PhoneRelayBody {
|
||||
string id = 1;
|
||||
string bugle = 3;
|
||||
bytes rpcKey = 6;
|
||||
messages.Date date = 7;
|
||||
}
|
||||
|
||||
message ECDSAKeys {
|
||||
int64 protoVersion = 1; // idk?
|
||||
bytes encryptedKeys = 2;
|
||||
}
|
||||
|
||||
message PairDeviceData {
|
||||
messages.Device mobile = 1;
|
||||
ECDSAKeys ecdsaKeys = 6;
|
||||
WebAuthKey webAuthKeyData = 2;
|
||||
messages.Device browser = 3;
|
||||
}
|
||||
|
||||
message WebAuthKey {
|
||||
bytes webAuthKey = 1;
|
||||
int64 validFor = 2;
|
||||
}
|
||||
|
||||
message Container {
|
||||
PhoneRelayBody PhoneRelay = 1;
|
||||
BrowserDetails browserDetails = 3;
|
||||
PairDeviceData pairDeviceData = 4;
|
||||
}
|
||||
|
||||
message UrlData {
|
||||
bytes pairingKey = 1;
|
||||
bytes AES_CTR_KEY_256 = 2;
|
||||
bytes SHA_256_KEY = 3;
|
||||
}
|
39
libgm/binary/raw/relay.proto
Normal file
39
libgm/binary/raw/relay.proto
Normal file
|
@ -0,0 +1,39 @@
|
|||
syntax = "proto3";
|
||||
package registerPhoneRelay;
|
||||
|
||||
option go_package = "../../binary";
|
||||
|
||||
message RegisterPhoneRelayResponse {
|
||||
Message1 field1 = 1;
|
||||
Message2 field2 = 2;
|
||||
bytes PairingKey = 3;
|
||||
int64 field4 = 4;
|
||||
Message3 field5 = 5;
|
||||
bytes field6 = 6;
|
||||
}
|
||||
|
||||
message Message1 {
|
||||
int64 pubKey = 2;
|
||||
}
|
||||
|
||||
message Message2 {
|
||||
int64 field1 = 1;
|
||||
bytes field2 = 2;
|
||||
string field3 = 3;
|
||||
}
|
||||
|
||||
message Message3 {
|
||||
bytes rpcKey = 1;
|
||||
int64 field2 = 2;
|
||||
}
|
||||
|
||||
message RefreshPhoneRelayResponse {
|
||||
Message1 field1 = 1;
|
||||
bytes pairKey = 2;
|
||||
int64 validFor = 3;
|
||||
}
|
||||
|
||||
message WebEncryptionKeyResponse {
|
||||
Message1 curve = 1;
|
||||
bytes key = 2;
|
||||
}
|
19
libgm/binary/raw/responses.proto
Normal file
19
libgm/binary/raw/responses.proto
Normal file
|
@ -0,0 +1,19 @@
|
|||
syntax = "proto3";
|
||||
package responses;
|
||||
|
||||
option go_package = "../../binary";
|
||||
|
||||
import "settings.proto";
|
||||
import "conversations.proto";
|
||||
|
||||
message PrepareNewSession {
|
||||
bool success = 1;
|
||||
}
|
||||
|
||||
message NewSession {
|
||||
settings.Settings settings = 5;
|
||||
}
|
||||
|
||||
message SendMessageResponse {
|
||||
conversations.MessageType type = 3;
|
||||
}
|
75
libgm/binary/raw/settings.proto
Normal file
75
libgm/binary/raw/settings.proto
Normal file
|
@ -0,0 +1,75 @@
|
|||
syntax = "proto3";
|
||||
package settings;
|
||||
|
||||
option go_package = "../../binary";
|
||||
|
||||
|
||||
message Settings {
|
||||
Data data = 2;
|
||||
OpCodeData opCodeData = 3;
|
||||
BooleanFields boolFields = 4;
|
||||
string version = 5;
|
||||
bool bool1 = 7;
|
||||
BooleanFields2 boolFields2 = 8;
|
||||
string emptyString = 9;
|
||||
BooleanFields3 boolFields3 = 10;
|
||||
}
|
||||
|
||||
message Data { // i think its simdata? no clue
|
||||
BoolMsg boolMsg = 3;
|
||||
SimData simData = 5;
|
||||
bool bool1 = 6;
|
||||
NoClue noClue = 7;
|
||||
}
|
||||
|
||||
message BoolMsg {
|
||||
bool bool1 = 1;
|
||||
}
|
||||
|
||||
message SimData {
|
||||
UnknownMessage unknownMessage = 1;
|
||||
bool bool1 = 2;
|
||||
string carrierName = 3;
|
||||
string hexHash = 4;
|
||||
int64 int1 = 5;
|
||||
}
|
||||
|
||||
message UnknownMessage {
|
||||
int64 int1 = 1;
|
||||
int64 int2 = 2;
|
||||
}
|
||||
|
||||
message NoClue { // just a guess lol
|
||||
string count = 1;
|
||||
}
|
||||
|
||||
message OpCodeData {
|
||||
bool field7 = 7;
|
||||
string jsonData = 16;
|
||||
}
|
||||
|
||||
message BooleanFields {
|
||||
bool bool1 = 1;
|
||||
bool bool2 = 2;
|
||||
bool bool3 = 3;
|
||||
bool bool4 = 4;
|
||||
}
|
||||
|
||||
message BooleanFields2 {
|
||||
bool bool1 = 1;
|
||||
bool bool2 = 2;
|
||||
BoolMsg boolMsg1 = 3;
|
||||
BoolMsg boolMsg2 = 5;
|
||||
bool bool3 = 6;
|
||||
}
|
||||
|
||||
message BooleanFields3 {
|
||||
bool bool1 = 1;
|
||||
bool bool3 = 3;
|
||||
bool bool4 = 4;
|
||||
bool bool5 = 5;
|
||||
bool bool6 = 6;
|
||||
bool bool7 = 7;
|
||||
bool bool8 = 8;
|
||||
bool bool9 = 9;
|
||||
}
|
576
libgm/binary/relay.pb.go
Normal file
576
libgm/binary/relay.pb.go
Normal file
|
@ -0,0 +1,576 @@
|
|||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.30.0
|
||||
// protoc v3.21.12
|
||||
// source: relay.proto
|
||||
|
||||
package binary
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type RegisterPhoneRelayResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Field1 *Message1 `protobuf:"bytes,1,opt,name=field1,proto3" json:"field1,omitempty"`
|
||||
Field2 *Message2 `protobuf:"bytes,2,opt,name=field2,proto3" json:"field2,omitempty"`
|
||||
PairingKey []byte `protobuf:"bytes,3,opt,name=PairingKey,proto3" json:"PairingKey,omitempty"`
|
||||
Field4 int64 `protobuf:"varint,4,opt,name=field4,proto3" json:"field4,omitempty"`
|
||||
Field5 *Message3 `protobuf:"bytes,5,opt,name=field5,proto3" json:"field5,omitempty"`
|
||||
Field6 []byte `protobuf:"bytes,6,opt,name=field6,proto3" json:"field6,omitempty"`
|
||||
}
|
||||
|
||||
func (x *RegisterPhoneRelayResponse) Reset() {
|
||||
*x = RegisterPhoneRelayResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_relay_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *RegisterPhoneRelayResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*RegisterPhoneRelayResponse) ProtoMessage() {}
|
||||
|
||||
func (x *RegisterPhoneRelayResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_relay_proto_msgTypes[0]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use RegisterPhoneRelayResponse.ProtoReflect.Descriptor instead.
|
||||
func (*RegisterPhoneRelayResponse) Descriptor() ([]byte, []int) {
|
||||
return file_relay_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *RegisterPhoneRelayResponse) GetField1() *Message1 {
|
||||
if x != nil {
|
||||
return x.Field1
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *RegisterPhoneRelayResponse) GetField2() *Message2 {
|
||||
if x != nil {
|
||||
return x.Field2
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *RegisterPhoneRelayResponse) GetPairingKey() []byte {
|
||||
if x != nil {
|
||||
return x.PairingKey
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *RegisterPhoneRelayResponse) GetField4() int64 {
|
||||
if x != nil {
|
||||
return x.Field4
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *RegisterPhoneRelayResponse) GetField5() *Message3 {
|
||||
if x != nil {
|
||||
return x.Field5
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *RegisterPhoneRelayResponse) GetField6() []byte {
|
||||
if x != nil {
|
||||
return x.Field6
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Message1 struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
PubKey int64 `protobuf:"varint,2,opt,name=pubKey,proto3" json:"pubKey,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Message1) Reset() {
|
||||
*x = Message1{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_relay_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *Message1) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Message1) ProtoMessage() {}
|
||||
|
||||
func (x *Message1) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_relay_proto_msgTypes[1]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use Message1.ProtoReflect.Descriptor instead.
|
||||
func (*Message1) Descriptor() ([]byte, []int) {
|
||||
return file_relay_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *Message1) GetPubKey() int64 {
|
||||
if x != nil {
|
||||
return x.PubKey
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type Message2 struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Field1 int64 `protobuf:"varint,1,opt,name=field1,proto3" json:"field1,omitempty"`
|
||||
Field2 []byte `protobuf:"bytes,2,opt,name=field2,proto3" json:"field2,omitempty"`
|
||||
Field3 string `protobuf:"bytes,3,opt,name=field3,proto3" json:"field3,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Message2) Reset() {
|
||||
*x = Message2{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_relay_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *Message2) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Message2) ProtoMessage() {}
|
||||
|
||||
func (x *Message2) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_relay_proto_msgTypes[2]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use Message2.ProtoReflect.Descriptor instead.
|
||||
func (*Message2) Descriptor() ([]byte, []int) {
|
||||
return file_relay_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *Message2) GetField1() int64 {
|
||||
if x != nil {
|
||||
return x.Field1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Message2) GetField2() []byte {
|
||||
if x != nil {
|
||||
return x.Field2
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Message2) GetField3() string {
|
||||
if x != nil {
|
||||
return x.Field3
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type Message3 struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
RpcKey []byte `protobuf:"bytes,1,opt,name=rpcKey,proto3" json:"rpcKey,omitempty"`
|
||||
Field2 int64 `protobuf:"varint,2,opt,name=field2,proto3" json:"field2,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Message3) Reset() {
|
||||
*x = Message3{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_relay_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *Message3) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Message3) ProtoMessage() {}
|
||||
|
||||
func (x *Message3) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_relay_proto_msgTypes[3]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use Message3.ProtoReflect.Descriptor instead.
|
||||
func (*Message3) Descriptor() ([]byte, []int) {
|
||||
return file_relay_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
func (x *Message3) GetRpcKey() []byte {
|
||||
if x != nil {
|
||||
return x.RpcKey
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Message3) GetField2() int64 {
|
||||
if x != nil {
|
||||
return x.Field2
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type RefreshPhoneRelayResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Field1 *Message1 `protobuf:"bytes,1,opt,name=field1,proto3" json:"field1,omitempty"`
|
||||
PairKey []byte `protobuf:"bytes,2,opt,name=pairKey,proto3" json:"pairKey,omitempty"`
|
||||
ValidFor int64 `protobuf:"varint,3,opt,name=validFor,proto3" json:"validFor,omitempty"`
|
||||
}
|
||||
|
||||
func (x *RefreshPhoneRelayResponse) Reset() {
|
||||
*x = RefreshPhoneRelayResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_relay_proto_msgTypes[4]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *RefreshPhoneRelayResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*RefreshPhoneRelayResponse) ProtoMessage() {}
|
||||
|
||||
func (x *RefreshPhoneRelayResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_relay_proto_msgTypes[4]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use RefreshPhoneRelayResponse.ProtoReflect.Descriptor instead.
|
||||
func (*RefreshPhoneRelayResponse) Descriptor() ([]byte, []int) {
|
||||
return file_relay_proto_rawDescGZIP(), []int{4}
|
||||
}
|
||||
|
||||
func (x *RefreshPhoneRelayResponse) GetField1() *Message1 {
|
||||
if x != nil {
|
||||
return x.Field1
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *RefreshPhoneRelayResponse) GetPairKey() []byte {
|
||||
if x != nil {
|
||||
return x.PairKey
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *RefreshPhoneRelayResponse) GetValidFor() int64 {
|
||||
if x != nil {
|
||||
return x.ValidFor
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type WebEncryptionKeyResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Curve *Message1 `protobuf:"bytes,1,opt,name=curve,proto3" json:"curve,omitempty"`
|
||||
Key []byte `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
|
||||
}
|
||||
|
||||
func (x *WebEncryptionKeyResponse) Reset() {
|
||||
*x = WebEncryptionKeyResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_relay_proto_msgTypes[5]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *WebEncryptionKeyResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*WebEncryptionKeyResponse) ProtoMessage() {}
|
||||
|
||||
func (x *WebEncryptionKeyResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_relay_proto_msgTypes[5]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use WebEncryptionKeyResponse.ProtoReflect.Descriptor instead.
|
||||
func (*WebEncryptionKeyResponse) Descriptor() ([]byte, []int) {
|
||||
return file_relay_proto_rawDescGZIP(), []int{5}
|
||||
}
|
||||
|
||||
func (x *WebEncryptionKeyResponse) GetCurve() *Message1 {
|
||||
if x != nil {
|
||||
return x.Curve
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *WebEncryptionKeyResponse) GetKey() []byte {
|
||||
if x != nil {
|
||||
return x.Key
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var File_relay_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_relay_proto_rawDesc = []byte{
|
||||
0x0a, 0x0b, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x72,
|
||||
0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x50, 0x68, 0x6f, 0x6e, 0x65, 0x52, 0x65, 0x6c, 0x61,
|
||||
0x79, 0x22, 0x8e, 0x02, 0x0a, 0x1a, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x50, 0x68,
|
||||
0x6f, 0x6e, 0x65, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||
0x12, 0x34, 0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x31, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
|
||||
0x32, 0x1c, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x50, 0x68, 0x6f, 0x6e, 0x65,
|
||||
0x52, 0x65, 0x6c, 0x61, 0x79, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x31, 0x52, 0x06,
|
||||
0x66, 0x69, 0x65, 0x6c, 0x64, 0x31, 0x12, 0x34, 0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x32,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65,
|
||||
0x72, 0x50, 0x68, 0x6f, 0x6e, 0x65, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x2e, 0x4d, 0x65, 0x73, 0x73,
|
||||
0x61, 0x67, 0x65, 0x32, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x32, 0x12, 0x1e, 0x0a, 0x0a,
|
||||
0x50, 0x61, 0x69, 0x72, 0x69, 0x6e, 0x67, 0x4b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c,
|
||||
0x52, 0x0a, 0x50, 0x61, 0x69, 0x72, 0x69, 0x6e, 0x67, 0x4b, 0x65, 0x79, 0x12, 0x16, 0x0a, 0x06,
|
||||
0x66, 0x69, 0x65, 0x6c, 0x64, 0x34, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x66, 0x69,
|
||||
0x65, 0x6c, 0x64, 0x34, 0x12, 0x34, 0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x35, 0x18, 0x05,
|
||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x50,
|
||||
0x68, 0x6f, 0x6e, 0x65, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
|
||||
0x65, 0x33, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x35, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x69,
|
||||
0x65, 0x6c, 0x64, 0x36, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c,
|
||||
0x64, 0x36, 0x22, 0x22, 0x0a, 0x08, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x31, 0x12, 0x16,
|
||||
0x0a, 0x06, 0x70, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06,
|
||||
0x70, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x22, 0x52, 0x0a, 0x08, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
|
||||
0x65, 0x32, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x31, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x03, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x31, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x69,
|
||||
0x65, 0x6c, 0x64, 0x32, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c,
|
||||
0x64, 0x32, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x33, 0x18, 0x03, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x33, 0x22, 0x3a, 0x0a, 0x08, 0x4d, 0x65,
|
||||
0x73, 0x73, 0x61, 0x67, 0x65, 0x33, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x70, 0x63, 0x4b, 0x65, 0x79,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x72, 0x70, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x16,
|
||||
0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x32, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06,
|
||||
0x66, 0x69, 0x65, 0x6c, 0x64, 0x32, 0x22, 0x87, 0x01, 0x0a, 0x19, 0x52, 0x65, 0x66, 0x72, 0x65,
|
||||
0x73, 0x68, 0x50, 0x68, 0x6f, 0x6e, 0x65, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x52, 0x65, 0x73, 0x70,
|
||||
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x31, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x50,
|
||||
0x68, 0x6f, 0x6e, 0x65, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
|
||||
0x65, 0x31, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x31, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61,
|
||||
0x69, 0x72, 0x4b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x69,
|
||||
0x72, 0x4b, 0x65, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x46, 0x6f, 0x72,
|
||||
0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x46, 0x6f, 0x72,
|
||||
0x22, 0x60, 0x0a, 0x18, 0x57, 0x65, 0x62, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x05,
|
||||
0x63, 0x75, 0x72, 0x76, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x72, 0x65,
|
||||
0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x50, 0x68, 0x6f, 0x6e, 0x65, 0x52, 0x65, 0x6c, 0x61, 0x79,
|
||||
0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x31, 0x52, 0x05, 0x63, 0x75, 0x72, 0x76, 0x65,
|
||||
0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b,
|
||||
0x65, 0x79, 0x42, 0x0e, 0x5a, 0x0c, 0x2e, 0x2e, 0x2f, 0x2e, 0x2e, 0x2f, 0x62, 0x69, 0x6e, 0x61,
|
||||
0x72, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_relay_proto_rawDescOnce sync.Once
|
||||
file_relay_proto_rawDescData = file_relay_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_relay_proto_rawDescGZIP() []byte {
|
||||
file_relay_proto_rawDescOnce.Do(func() {
|
||||
file_relay_proto_rawDescData = protoimpl.X.CompressGZIP(file_relay_proto_rawDescData)
|
||||
})
|
||||
return file_relay_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_relay_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
|
||||
var file_relay_proto_goTypes = []interface{}{
|
||||
(*RegisterPhoneRelayResponse)(nil), // 0: registerPhoneRelay.RegisterPhoneRelayResponse
|
||||
(*Message1)(nil), // 1: registerPhoneRelay.Message1
|
||||
(*Message2)(nil), // 2: registerPhoneRelay.Message2
|
||||
(*Message3)(nil), // 3: registerPhoneRelay.Message3
|
||||
(*RefreshPhoneRelayResponse)(nil), // 4: registerPhoneRelay.RefreshPhoneRelayResponse
|
||||
(*WebEncryptionKeyResponse)(nil), // 5: registerPhoneRelay.WebEncryptionKeyResponse
|
||||
}
|
||||
var file_relay_proto_depIdxs = []int32{
|
||||
1, // 0: registerPhoneRelay.RegisterPhoneRelayResponse.field1:type_name -> registerPhoneRelay.Message1
|
||||
2, // 1: registerPhoneRelay.RegisterPhoneRelayResponse.field2:type_name -> registerPhoneRelay.Message2
|
||||
3, // 2: registerPhoneRelay.RegisterPhoneRelayResponse.field5:type_name -> registerPhoneRelay.Message3
|
||||
1, // 3: registerPhoneRelay.RefreshPhoneRelayResponse.field1:type_name -> registerPhoneRelay.Message1
|
||||
1, // 4: registerPhoneRelay.WebEncryptionKeyResponse.curve:type_name -> registerPhoneRelay.Message1
|
||||
5, // [5:5] is the sub-list for method output_type
|
||||
5, // [5:5] is the sub-list for method input_type
|
||||
5, // [5:5] is the sub-list for extension type_name
|
||||
5, // [5:5] is the sub-list for extension extendee
|
||||
0, // [0:5] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_relay_proto_init() }
|
||||
func file_relay_proto_init() {
|
||||
if File_relay_proto != nil {
|
||||
return
|
||||
}
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_relay_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*RegisterPhoneRelayResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_relay_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*Message1); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_relay_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*Message2); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_relay_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*Message3); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_relay_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*RefreshPhoneRelayResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_relay_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*WebEncryptionKeyResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_relay_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 6,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_relay_proto_goTypes,
|
||||
DependencyIndexes: file_relay_proto_depIdxs,
|
||||
MessageInfos: file_relay_proto_msgTypes,
|
||||
}.Build()
|
||||
File_relay_proto = out.File
|
||||
file_relay_proto_rawDesc = nil
|
||||
file_relay_proto_goTypes = nil
|
||||
file_relay_proto_depIdxs = nil
|
||||
}
|
279
libgm/binary/responses.pb.go
Normal file
279
libgm/binary/responses.pb.go
Normal file
|
@ -0,0 +1,279 @@
|
|||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.30.0
|
||||
// protoc v3.21.12
|
||||
// source: responses.proto
|
||||
|
||||
package binary
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type PrepareNewSession struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"`
|
||||
}
|
||||
|
||||
func (x *PrepareNewSession) Reset() {
|
||||
*x = PrepareNewSession{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_responses_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *PrepareNewSession) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*PrepareNewSession) ProtoMessage() {}
|
||||
|
||||
func (x *PrepareNewSession) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_responses_proto_msgTypes[0]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use PrepareNewSession.ProtoReflect.Descriptor instead.
|
||||
func (*PrepareNewSession) Descriptor() ([]byte, []int) {
|
||||
return file_responses_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *PrepareNewSession) GetSuccess() bool {
|
||||
if x != nil {
|
||||
return x.Success
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type NewSession struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Settings *Settings `protobuf:"bytes,5,opt,name=settings,proto3" json:"settings,omitempty"`
|
||||
}
|
||||
|
||||
func (x *NewSession) Reset() {
|
||||
*x = NewSession{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_responses_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *NewSession) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*NewSession) ProtoMessage() {}
|
||||
|
||||
func (x *NewSession) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_responses_proto_msgTypes[1]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use NewSession.ProtoReflect.Descriptor instead.
|
||||
func (*NewSession) Descriptor() ([]byte, []int) {
|
||||
return file_responses_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *NewSession) GetSettings() *Settings {
|
||||
if x != nil {
|
||||
return x.Settings
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type SendMessageResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Type MessageType `protobuf:"varint,3,opt,name=type,proto3,enum=conversations.MessageType" json:"type,omitempty"`
|
||||
}
|
||||
|
||||
func (x *SendMessageResponse) Reset() {
|
||||
*x = SendMessageResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_responses_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *SendMessageResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*SendMessageResponse) ProtoMessage() {}
|
||||
|
||||
func (x *SendMessageResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_responses_proto_msgTypes[2]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use SendMessageResponse.ProtoReflect.Descriptor instead.
|
||||
func (*SendMessageResponse) Descriptor() ([]byte, []int) {
|
||||
return file_responses_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *SendMessageResponse) GetType() MessageType {
|
||||
if x != nil {
|
||||
return x.Type
|
||||
}
|
||||
return MessageType_UNKNOWN
|
||||
}
|
||||
|
||||
var File_responses_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_responses_proto_rawDesc = []byte{
|
||||
0x0a, 0x0f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x12, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x1a, 0x0e, 0x73, 0x65,
|
||||
0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x13, 0x63, 0x6f,
|
||||
0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x22, 0x2d, 0x0a, 0x11, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x4e, 0x65, 0x77, 0x53,
|
||||
0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73,
|
||||
0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73,
|
||||
0x22, 0x3c, 0x0a, 0x0a, 0x4e, 0x65, 0x77, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2e,
|
||||
0x0a, 0x08, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b,
|
||||
0x32, 0x12, 0x2e, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x53, 0x65, 0x74, 0x74,
|
||||
0x69, 0x6e, 0x67, 0x73, 0x52, 0x08, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x45,
|
||||
0x0a, 0x13, 0x53, 0x65, 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20,
|
||||
0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x73, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52,
|
||||
0x04, 0x74, 0x79, 0x70, 0x65, 0x42, 0x0e, 0x5a, 0x0c, 0x2e, 0x2e, 0x2f, 0x2e, 0x2e, 0x2f, 0x62,
|
||||
0x69, 0x6e, 0x61, 0x72, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_responses_proto_rawDescOnce sync.Once
|
||||
file_responses_proto_rawDescData = file_responses_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_responses_proto_rawDescGZIP() []byte {
|
||||
file_responses_proto_rawDescOnce.Do(func() {
|
||||
file_responses_proto_rawDescData = protoimpl.X.CompressGZIP(file_responses_proto_rawDescData)
|
||||
})
|
||||
return file_responses_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_responses_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
|
||||
var file_responses_proto_goTypes = []interface{}{
|
||||
(*PrepareNewSession)(nil), // 0: responses.PrepareNewSession
|
||||
(*NewSession)(nil), // 1: responses.NewSession
|
||||
(*SendMessageResponse)(nil), // 2: responses.SendMessageResponse
|
||||
(*Settings)(nil), // 3: settings.Settings
|
||||
(MessageType)(0), // 4: conversations.MessageType
|
||||
}
|
||||
var file_responses_proto_depIdxs = []int32{
|
||||
3, // 0: responses.NewSession.settings:type_name -> settings.Settings
|
||||
4, // 1: responses.SendMessageResponse.type:type_name -> conversations.MessageType
|
||||
2, // [2:2] is the sub-list for method output_type
|
||||
2, // [2:2] is the sub-list for method input_type
|
||||
2, // [2:2] is the sub-list for extension type_name
|
||||
2, // [2:2] is the sub-list for extension extendee
|
||||
0, // [0:2] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_responses_proto_init() }
|
||||
func file_responses_proto_init() {
|
||||
if File_responses_proto != nil {
|
||||
return
|
||||
}
|
||||
file_settings_proto_init()
|
||||
file_conversations_proto_init()
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_responses_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*PrepareNewSession); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_responses_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*NewSession); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_responses_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*SendMessageResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_responses_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 3,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_responses_proto_goTypes,
|
||||
DependencyIndexes: file_responses_proto_depIdxs,
|
||||
MessageInfos: file_responses_proto_msgTypes,
|
||||
}.Build()
|
||||
File_responses_proto = out.File
|
||||
file_responses_proto_rawDesc = nil
|
||||
file_responses_proto_goTypes = nil
|
||||
file_responses_proto_depIdxs = nil
|
||||
}
|
1016
libgm/binary/settings.pb.go
Normal file
1016
libgm/binary/settings.pb.go
Normal file
File diff suppressed because it is too large
Load diff
12
libgm/bugle_service.go
Normal file
12
libgm/bugle_service.go
Normal file
|
@ -0,0 +1,12 @@
|
|||
package textgapi
|
||||
|
||||
import "go.mau.fi/mautrix-gmessages/libgm/binary"
|
||||
|
||||
func (c *Client) handleBugleOpCode(bugleData *binary.BugleBackendService) {
|
||||
switch bugleData.Data.Type {
|
||||
case 2:
|
||||
c.Logger.Info().Any("type", bugleData.Data.Type).Msg("Updated sessionId to " + c.sessionHandler.sessionId + " due to BROWSER_ACTIVE alert")
|
||||
case 6:
|
||||
c.Logger.Info().Any("type", bugleData.Data.Type).Msg("USER_ALERT:BATTERY") // tf ?
|
||||
}
|
||||
}
|
71
libgm/builders/tenor.go
Normal file
71
libgm/builders/tenor.go
Normal file
|
@ -0,0 +1,71 @@
|
|||
package builders
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
"go.mau.fi/mautrix-gmessages/libgm/util"
|
||||
)
|
||||
|
||||
type TenorSearch struct {
|
||||
query string
|
||||
locale string
|
||||
content_filter string
|
||||
media_filter string
|
||||
limit string // limit results
|
||||
}
|
||||
|
||||
func NewTenorSearchBuilder() *TenorSearch {
|
||||
return &TenorSearch{}
|
||||
}
|
||||
|
||||
func (t *TenorSearch) SetQuery(query string) *TenorSearch {
|
||||
t.query = query
|
||||
return t
|
||||
}
|
||||
func (t *TenorSearch) SetLocale(locale string) *TenorSearch {
|
||||
t.locale = locale
|
||||
return t
|
||||
}
|
||||
func (t *TenorSearch) SetContentFilter(content_filter string) *TenorSearch {
|
||||
t.content_filter = content_filter
|
||||
return t
|
||||
}
|
||||
func (t *TenorSearch) SetMediaFilter(media_filter string) *TenorSearch {
|
||||
t.media_filter = media_filter
|
||||
return t
|
||||
}
|
||||
func (t *TenorSearch) SetLimit(limit string) *TenorSearch {
|
||||
t.limit = limit
|
||||
return t
|
||||
}
|
||||
func (t *TenorSearch) Build() (string, error) {
|
||||
if t.query == "" {
|
||||
return "", fmt.Errorf("failed to build TenorSearch: query is empty")
|
||||
}
|
||||
params := url.Values{}
|
||||
params.Add("key", util.TENOR_API_KEY)
|
||||
params.Add("q", t.query)
|
||||
|
||||
if t.locale == "" {
|
||||
t.locale = "en-US"
|
||||
}
|
||||
params.Add("locale", t.locale)
|
||||
|
||||
if t.content_filter == "" {
|
||||
t.content_filter = "medium"
|
||||
}
|
||||
params.Add("contentfilter", t.content_filter)
|
||||
|
||||
if t.media_filter == "" {
|
||||
t.media_filter = "minimal"
|
||||
}
|
||||
params.Add("media_filter", t.media_filter)
|
||||
|
||||
if t.limit == "" {
|
||||
t.limit = "16"
|
||||
}
|
||||
params.Add("limit", t.limit)
|
||||
|
||||
return "?" + params.Encode(), nil
|
||||
}
|
66
libgm/cache/cache.go
vendored
Normal file
66
libgm/cache/cache.go
vendored
Normal file
|
@ -0,0 +1,66 @@
|
|||
package cache
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"go.mau.fi/mautrix-gmessages/libgm/binary"
|
||||
)
|
||||
|
||||
type Cache struct {
|
||||
Conversations Conversations `json:"conversations"`
|
||||
Settings Settings `json:"sim,omitempty"`
|
||||
}
|
||||
|
||||
func LoadCache(path string) Cache {
|
||||
data, readErr := os.ReadFile(path)
|
||||
if readErr != nil {
|
||||
log.Fatal(readErr)
|
||||
}
|
||||
var cache Cache
|
||||
err := json.Unmarshal(data, &cache)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return cache
|
||||
}
|
||||
|
||||
func (c *Cache) OrderMapToInterface() map[string]interface{} {
|
||||
convIdMapStringInterface := make(map[string]interface{})
|
||||
for key, value := range c.Conversations.Order {
|
||||
convIdMapStringInterface[strconv.Itoa(key)] = value
|
||||
}
|
||||
return convIdMapStringInterface
|
||||
}
|
||||
|
||||
func (c *Cache) SetSettings(settings *binary.Settings) {
|
||||
c.Settings = Settings{
|
||||
CarrierName: settings.Data.SimData.CarrierName,
|
||||
HexHash: settings.Data.SimData.HexHash,
|
||||
Version: settings.Version,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Cache) SetMessages(messages *binary.FetchMessagesResponse) {
|
||||
for _, msg := range messages.Messages {
|
||||
convo, ok := c.Conversations.Conversations[msg.ConversationId]
|
||||
if !ok {
|
||||
// handle error, such as creating a new conversation or returning
|
||||
fmt.Printf("Could not find conversation with id %s", msg.ConversationId)
|
||||
return
|
||||
} else {
|
||||
convo.UpdateMessage(msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Cache) SetConversations(conversations *binary.Conversations) {
|
||||
for order, conv := range conversations.Conversations {
|
||||
convertedConv := NewConversation(c, conv)
|
||||
c.Conversations.Order[order] = conv.ConversationId
|
||||
c.Conversations.Conversations[conv.ConversationId] = convertedConv
|
||||
}
|
||||
}
|
290
libgm/cache/conversation.go
vendored
Normal file
290
libgm/cache/conversation.go
vendored
Normal file
|
@ -0,0 +1,290 @@
|
|||
package cache
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"sort"
|
||||
|
||||
"go.mau.fi/mautrix-gmessages/libgm/binary"
|
||||
)
|
||||
|
||||
type SmallInfo struct {
|
||||
Type int64 `json:"type,omitempty"`
|
||||
Number string `json:"number,omitempty"`
|
||||
ParticipantId string `json:"participantId,omitempty"`
|
||||
}
|
||||
|
||||
type Participant struct {
|
||||
SmallInfo *SmallInfo `json:"smallInfo,omitempty"`
|
||||
HexHash string `json:"hexHash,omitempty"`
|
||||
IsMe bool `json:"isMe,omitempty"`
|
||||
Bs int64 `json:"bs,omitempty"`
|
||||
DisplayName string `json:"displayName,omitempty"`
|
||||
}
|
||||
|
||||
type ImagePixels struct {
|
||||
Width int64 `json:"width,omitempty"`
|
||||
Height int64 `json:"height,omitempty"`
|
||||
}
|
||||
|
||||
type ImageMessage struct {
|
||||
SomeNumber int64 `json:"someNumber"`
|
||||
ImageId string `json:"imageId"`
|
||||
ImageName string `json:"imageName"`
|
||||
Size int64 `json:"size"`
|
||||
Pixels ImagePixels `json:"pixels"`
|
||||
ImageBuffer []byte `json:"imageBuffer"`
|
||||
DecryptionKey []byte `json:"decryptionKey"`
|
||||
}
|
||||
|
||||
type TextMessage struct {
|
||||
Content string `json:"content"`
|
||||
}
|
||||
|
||||
type IsFromMe struct {
|
||||
FromMe bool `json:"fromMe"`
|
||||
}
|
||||
|
||||
type MessageData struct {
|
||||
OrderInternal string `json:"orderInternal"`
|
||||
TextData *TextMessage `json:"textData,omitempty"`
|
||||
ImageData *ImageMessage `json:"imageData,omitempty"`
|
||||
}
|
||||
|
||||
type MessageStatus struct {
|
||||
Code int64 `json:"code,omitempty"`
|
||||
ErrMsg string `json:"errMsg,omitempty"`
|
||||
MsgType string `json:"msgType,omitempty"`
|
||||
}
|
||||
|
||||
type Message struct {
|
||||
cache *Cache
|
||||
|
||||
MessageId string `json:"messageId"`
|
||||
From IsFromMe `json:"from"`
|
||||
MessageStatus MessageStatus `json:"details"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
ConvId string `json:"convId"`
|
||||
ParticipantId string `json:"participantId"`
|
||||
MessageData []MessageData `json:"messageData"`
|
||||
MessageType string `json:"messageType"`
|
||||
}
|
||||
|
||||
func (m *Message) FromMe() bool {
|
||||
conv, _ := m.cache.Conversations.GetConversation(m.ConvId)
|
||||
return m.ParticipantId == conv.SelfParticipantId
|
||||
}
|
||||
|
||||
type LatestMessage struct {
|
||||
Content string `json:"content,omitempty"`
|
||||
FromMe bool `json:"fromMe,omitempty"`
|
||||
DisplayName string `json:"displayName,omitempty"`
|
||||
MessageId string `json:"messageId,omitempty"`
|
||||
}
|
||||
|
||||
type Conversation struct {
|
||||
cache *Cache
|
||||
|
||||
MessageOrder map[int]string `json:"messageOrder"`
|
||||
Messages map[string]Message `json:"messages"`
|
||||
ConversationId string `json:"conversationId"`
|
||||
DisplayName string `json:"displayName"`
|
||||
LatestMessage LatestMessage `json:"latestMessage"`
|
||||
IsGroupChat bool `json:"isGroupChat,omitempty"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
Status int64 `json:"status"`
|
||||
HexHash string `json:"hexHash"`
|
||||
Type int64 `json:"type"`
|
||||
SelfParticipantId string `json:"selfParticipantId,omitempty"`
|
||||
Participants []Participant `json:"participants"`
|
||||
ParticipantIds []string `json:"participantIds,omitempty"` // excluded self id
|
||||
}
|
||||
|
||||
type Conversations struct {
|
||||
cache *Cache
|
||||
/*
|
||||
{0: "1", 1: "4"}
|
||||
order -> conversationId
|
||||
index 0 = first conversation in order
|
||||
*/
|
||||
Order map[int]string `json:"order"`
|
||||
/*
|
||||
Map conversations by conversationId
|
||||
*/
|
||||
Conversations map[string]*Conversation `json:"conversations"`
|
||||
}
|
||||
|
||||
func (c *Conversations) SetCache(cache *Cache) {
|
||||
c.cache = cache
|
||||
}
|
||||
|
||||
func (c *Conversations) DeleteConversation(convId string) {
|
||||
delete(c.Conversations, convId)
|
||||
}
|
||||
|
||||
func (c *Conversations) UpdateConversation(conversation *binary.Conversation) *Conversation {
|
||||
newConversation := NewConversation(c.cache, conversation)
|
||||
c.Conversations[conversation.ConversationId] = newConversation
|
||||
return newConversation
|
||||
}
|
||||
|
||||
func (c *Conversation) GetMessage(msgId string) (Message, error) {
|
||||
message, foundMsg := c.Messages[msgId]
|
||||
if !foundMsg {
|
||||
return Message{}, fmt.Errorf("could not find that message cached")
|
||||
}
|
||||
return message, nil
|
||||
}
|
||||
|
||||
func (c *Conversation) Delete() {
|
||||
c.cache.Conversations.DeleteConversation(c.ConversationId)
|
||||
}
|
||||
|
||||
func (c *Conversation) UpdateMessage(msg *binary.Message) Message {
|
||||
newMsg := NewMessage(c.cache, msg)
|
||||
|
||||
if c.Messages == nil {
|
||||
log.Println("c.messages was nil so created new map")
|
||||
c.Messages = make(map[string]Message)
|
||||
}
|
||||
|
||||
c.Messages[msg.MessageId] = newMsg
|
||||
return newMsg
|
||||
}
|
||||
|
||||
func (c *Conversations) GetConversationByOrder(order int) (*Conversation, error) {
|
||||
convId, ok := c.Order[order]
|
||||
if !ok {
|
||||
return &Conversation{}, fmt.Errorf("could not find a conversation that occupies that order")
|
||||
}
|
||||
conversation, foundConvo := c.Conversations[convId]
|
||||
if !foundConvo {
|
||||
return &Conversation{}, fmt.Errorf("could not find that conversation cached, oddly enough it seems to be cached in the order map though... investigate further")
|
||||
}
|
||||
return conversation, nil
|
||||
}
|
||||
|
||||
func (c *Conversation) GetOrderSlice() []string {
|
||||
keys := make([]string, 0, len(c.Messages))
|
||||
for k := range c.Messages {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Slice(keys, func(i, j int) bool {
|
||||
return c.Messages[keys[i]].Timestamp < c.Messages[keys[j]].Timestamp
|
||||
})
|
||||
return keys
|
||||
}
|
||||
|
||||
func (c *Conversations) GetOrderSlice() []int {
|
||||
s := make([]int, 0)
|
||||
for i := range c.Order {
|
||||
s = append(s, i)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (c *Conversations) GetConversation(convId string) (*Conversation, error) {
|
||||
convo, ok := c.Conversations[convId]
|
||||
if !ok {
|
||||
// handle error, such as creating a new conversation or returning
|
||||
return &Conversation{}, fmt.Errorf("could not find conversation cached")
|
||||
} else {
|
||||
return convo, nil
|
||||
}
|
||||
}
|
||||
|
||||
func NewConversation(cache *Cache, conv *binary.Conversation) *Conversation {
|
||||
currConv, convErr := cache.Conversations.GetConversation(conv.ConversationId)
|
||||
participants := ParseParticipants(conv.Participants)
|
||||
newConversation := Conversation{
|
||||
cache: cache,
|
||||
ConversationId: conv.ConversationId,
|
||||
DisplayName: conv.Name,
|
||||
Timestamp: conv.TimestampMs,
|
||||
Status: conv.Status,
|
||||
HexHash: conv.HashHex,
|
||||
Type: conv.Type,
|
||||
Participants: participants,
|
||||
ParticipantIds: conv.OtherParticipants,
|
||||
SelfParticipantId: conv.SelfParticipantId,
|
||||
}
|
||||
|
||||
if conv.LatestMessage != nil {
|
||||
newConversation.LatestMessage = LatestMessage{
|
||||
Content: conv.LatestMessage.Content,
|
||||
FromMe: conv.LatestMessage.FromMe,
|
||||
DisplayName: conv.LatestMessage.DisplayName,
|
||||
MessageId: conv.MessageId,
|
||||
}
|
||||
}
|
||||
|
||||
if convErr == nil {
|
||||
newConversation.MessageOrder = currConv.MessageOrder
|
||||
newConversation.Messages = currConv.Messages
|
||||
} else {
|
||||
newConversation.MessageOrder = make(map[int]string)
|
||||
newConversation.Messages = make(map[string]Message)
|
||||
}
|
||||
return &newConversation
|
||||
}
|
||||
|
||||
func ParseParticipants(participants []*binary.Participant) []Participant {
|
||||
partSlice := make([]Participant, 0)
|
||||
for _, p := range participants {
|
||||
partSlice = append(partSlice, Participant{
|
||||
SmallInfo: &SmallInfo{
|
||||
Type: p.SmallInfo.Type,
|
||||
Number: p.SmallInfo.Number,
|
||||
ParticipantId: p.SmallInfo.ParticipantId,
|
||||
},
|
||||
HexHash: p.HashHex,
|
||||
IsMe: p.IsMe,
|
||||
Bs: p.Bs,
|
||||
DisplayName: p.DisplayName,
|
||||
})
|
||||
}
|
||||
return partSlice
|
||||
}
|
||||
|
||||
func NewMessage(cache *Cache, message *binary.Message) Message {
|
||||
msg := Message{
|
||||
cache: cache,
|
||||
MessageId: message.MessageId,
|
||||
ConvId: message.ConversationId,
|
||||
From: IsFromMe{
|
||||
FromMe: message.From.FromMe,
|
||||
},
|
||||
Timestamp: message.Timestamp,
|
||||
ParticipantId: message.ParticipantId,
|
||||
MessageType: message.Type.String(),
|
||||
MessageStatus: MessageStatus{
|
||||
Code: message.MessageStatus.Code,
|
||||
ErrMsg: message.MessageStatus.ErrMsg,
|
||||
MsgType: message.MessageStatus.MsgStatus,
|
||||
},
|
||||
MessageData: make([]MessageData, 0),
|
||||
}
|
||||
for _, data := range message.MessageInfo {
|
||||
msgData := MessageData{
|
||||
OrderInternal: data.OrderInternal,
|
||||
}
|
||||
switch d := data.Data.(type) {
|
||||
case *binary.MessageInfo_ImageContent:
|
||||
msgData.ImageData = &ImageMessage{
|
||||
SomeNumber: d.ImageContent.SomeNumber,
|
||||
ImageId: d.ImageContent.ImageId,
|
||||
ImageName: d.ImageContent.ImageName,
|
||||
Size: d.ImageContent.Size,
|
||||
Pixels: ImagePixels{Width: d.ImageContent.Pixels.Width, Height: d.ImageContent.Pixels.Height},
|
||||
ImageBuffer: d.ImageContent.ImageData,
|
||||
DecryptionKey: d.ImageContent.DecryptionKey,
|
||||
}
|
||||
case *binary.MessageInfo_MessageContent:
|
||||
msgData.TextData = &TextMessage{
|
||||
Content: d.MessageContent.Content,
|
||||
}
|
||||
}
|
||||
msg.MessageData = append(msg.MessageData, msgData)
|
||||
}
|
||||
return msg
|
||||
}
|
8
libgm/cache/settings.go
vendored
Normal file
8
libgm/cache/settings.go
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
package cache
|
||||
|
||||
|
||||
type Settings struct {
|
||||
CarrierName string `json:"carrierName,omitempty"`
|
||||
HexHash string `json:"hexHash,omitempty"`
|
||||
Version string `json:"version,omitempty"`
|
||||
}
|
242
libgm/client.go
Normal file
242
libgm/client.go
Normal file
|
@ -0,0 +1,242 @@
|
|||
package textgapi
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
|
||||
"go.mau.fi/mautrix-gmessages/libgm/binary"
|
||||
"go.mau.fi/mautrix-gmessages/libgm/cache"
|
||||
"go.mau.fi/mautrix-gmessages/libgm/crypto"
|
||||
"go.mau.fi/mautrix-gmessages/libgm/payload"
|
||||
"go.mau.fi/mautrix-gmessages/libgm/util"
|
||||
)
|
||||
|
||||
type DevicePair struct {
|
||||
Mobile *binary.Device
|
||||
Browser *binary.Device
|
||||
}
|
||||
type Proxy func(*http.Request) (*url.URL, error)
|
||||
type EventHandler func(evt interface{})
|
||||
type Client struct {
|
||||
Logger zerolog.Logger
|
||||
Conversations *Conversations
|
||||
Session *Session
|
||||
rpc *RPC
|
||||
devicePair *DevicePair
|
||||
pairer *Pairer
|
||||
cryptor *crypto.Cryptor
|
||||
imageCryptor *crypto.ImageCryptor
|
||||
evHandler EventHandler
|
||||
sessionHandler *SessionHandler
|
||||
instructions *Instructions
|
||||
|
||||
rpcKey string
|
||||
ttl int64
|
||||
|
||||
proxy Proxy
|
||||
http *http.Client
|
||||
|
||||
cache cache.Cache
|
||||
}
|
||||
|
||||
func NewClient(devicePair *DevicePair, cryptor *crypto.Cryptor, logger zerolog.Logger, proxy *string) *Client {
|
||||
sessionHandler := &SessionHandler{
|
||||
requests: make(map[string]map[int64]*ResponseChan),
|
||||
responseTimeout: time.Duration(5000) * time.Millisecond,
|
||||
}
|
||||
if cryptor == nil {
|
||||
cryptor = crypto.NewCryptor(nil, nil)
|
||||
}
|
||||
cli := &Client{
|
||||
Logger: logger,
|
||||
devicePair: devicePair,
|
||||
sessionHandler: sessionHandler,
|
||||
cryptor: cryptor,
|
||||
imageCryptor: &crypto.ImageCryptor{},
|
||||
http: &http.Client{},
|
||||
cache: cache.Cache{},
|
||||
}
|
||||
sessionHandler.client = cli
|
||||
cli.instructions = NewInstructions(cli.cryptor)
|
||||
if proxy != nil {
|
||||
cli.SetProxy(*proxy)
|
||||
}
|
||||
rpc := &RPC{client: cli, http: &http.Client{Transport: &http.Transport{Proxy: cli.proxy}}}
|
||||
cli.rpc = rpc
|
||||
cli.Logger.Debug().Any("data", cryptor).Msg("Cryptor")
|
||||
cli.cache.Conversations = cache.Conversations{
|
||||
Conversations: make(map[string]*cache.Conversation),
|
||||
Order: make(map[int]string),
|
||||
}
|
||||
cli.cache.Conversations.SetCache(&cli.cache)
|
||||
cli.setApiMethods()
|
||||
return cli
|
||||
}
|
||||
|
||||
func (c *Client) SetEventHandler(eventHandler EventHandler) {
|
||||
c.evHandler = eventHandler
|
||||
}
|
||||
|
||||
func (c *Client) SetProxy(proxy string) error {
|
||||
proxyParsed, err := url.Parse(proxy)
|
||||
if err != nil {
|
||||
c.Logger.Fatal().Err(err).Msg("Failed to set proxy")
|
||||
}
|
||||
proxyUrl := http.ProxyURL(proxyParsed)
|
||||
c.http.Transport = &http.Transport{
|
||||
Proxy: proxyUrl,
|
||||
}
|
||||
c.proxy = proxyUrl
|
||||
c.Logger.Debug().Any("proxy", proxyParsed.Host).Msg("SetProxy")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) Connect(rpcKey string) error {
|
||||
rpcPayload, receiveMesageSessionId, err := payload.ReceiveMessages(rpcKey)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return err
|
||||
}
|
||||
c.rpc.rpcSessionId = receiveMesageSessionId
|
||||
c.rpcKey = rpcKey
|
||||
c.rpc.ListenReceiveMessages(rpcPayload)
|
||||
c.Logger.Debug().Any("rpcKey", rpcKey).Msg("Successfully connected to server")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) Reconnect(rpcKey string) error {
|
||||
c.rpc.CloseConnection()
|
||||
for c.rpc.conn != nil {
|
||||
time.Sleep(time.Millisecond * 100)
|
||||
}
|
||||
err := c.Connect(rpcKey)
|
||||
if err != nil {
|
||||
c.Logger.Err(err).Any("rpcKey", rpcKey).Msg("Failed to reconnect")
|
||||
return err
|
||||
}
|
||||
c.Logger.Debug().Any("rpcKey", rpcKey).Msg("Successfully reconnected to server")
|
||||
sendInitialDataErr := c.rpc.sendInitialData()
|
||||
if sendInitialDataErr != nil {
|
||||
log.Fatal(sendInitialDataErr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) triggerEvent(evt interface{}) {
|
||||
if c.evHandler != nil {
|
||||
c.evHandler(evt)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) setApiMethods() {
|
||||
c.Conversations = &Conversations{
|
||||
client: c,
|
||||
openConversation: openConversation{
|
||||
client: c,
|
||||
},
|
||||
fetchConversationMessages: fetchConversationMessages{
|
||||
client: c,
|
||||
},
|
||||
}
|
||||
c.Session = &Session{
|
||||
client: c,
|
||||
prepareNewSession: prepareNewSession{
|
||||
client: c,
|
||||
},
|
||||
newSession: newSession{
|
||||
client: c,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) decryptImages(messages *binary.FetchMessagesResponse) error {
|
||||
for _, msg := range messages.Messages {
|
||||
switch msg.GetType() {
|
||||
case *binary.MessageType_IMAGE.Enum():
|
||||
for _, details := range msg.GetMessageInfo() {
|
||||
switch data := details.GetData().(type) {
|
||||
case *binary.MessageInfo_ImageContent:
|
||||
decryptedImageData, err := c.decryptImageData(data.ImageContent.ImageId, data.ImageContent.DecryptionKey)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return err
|
||||
}
|
||||
data.ImageContent.ImageData = decryptedImageData
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) decryptImageData(imageId string, key []byte) ([]byte, error) {
|
||||
decodedRpcKey, err := crypto.Base64DecodeStandard(c.rpcKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
reqId := util.RandomUUIDv4()
|
||||
download_metadata := &binary.UploadImagePayload{
|
||||
MetaData: &binary.ImageMetaData{
|
||||
ImageId: imageId,
|
||||
Encrypted: true,
|
||||
},
|
||||
AuthData: &binary.AuthMessageBytes{
|
||||
RequestId: reqId,
|
||||
RpcKey: decodedRpcKey,
|
||||
Date: &binary.Date{
|
||||
Year: 2023,
|
||||
Seq1: 6,
|
||||
Seq2: 8,
|
||||
Seq3: 4,
|
||||
Seq4: 6,
|
||||
},
|
||||
},
|
||||
}
|
||||
download_metadata_bytes, err2 := binary.EncodeProtoMessage(download_metadata)
|
||||
if err2 != nil {
|
||||
return nil, err2
|
||||
}
|
||||
download_metadata_b64 := crypto.EncodeBase64Standard(download_metadata_bytes)
|
||||
req, err := http.NewRequest("GET", util.UPLOAD_MEDIA, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
util.BuildUploadHeaders(req, download_metadata_b64)
|
||||
res, reqErr := c.http.Do(req)
|
||||
if reqErr != nil {
|
||||
return nil, reqErr
|
||||
}
|
||||
c.Logger.Info().Any("url", util.UPLOAD_MEDIA).Any("headers", res.Request.Header).Msg("Decrypt Image Headers")
|
||||
defer res.Body.Close()
|
||||
encryptedBuffImg, err3 := io.ReadAll(res.Body)
|
||||
if err3 != nil {
|
||||
return nil, err3
|
||||
}
|
||||
c.Logger.Debug().Any("key", key).Any("encryptedLength", len(encryptedBuffImg)).Msg("Attempting to decrypt image")
|
||||
c.imageCryptor.UpdateDecryptionKey(key)
|
||||
decryptedImageBytes, decryptionErr := c.imageCryptor.DecryptData(encryptedBuffImg)
|
||||
if decryptionErr != nil {
|
||||
log.Println("Error:", decryptionErr)
|
||||
return nil, decryptionErr
|
||||
}
|
||||
return decryptedImageBytes, nil
|
||||
}
|
||||
|
||||
func (c *Client) SaveCache(path string) {
|
||||
toSaveJson, jsonErr := json.Marshal(c.cache)
|
||||
if jsonErr != nil {
|
||||
log.Fatal(jsonErr)
|
||||
}
|
||||
os.WriteFile(path, toSaveJson, os.ModePerm)
|
||||
}
|
||||
|
||||
func (c *Client) GetCache() cache.Cache {
|
||||
return c.cache
|
||||
}
|
33
libgm/command_handler.go
Normal file
33
libgm/command_handler.go
Normal file
|
@ -0,0 +1,33 @@
|
|||
package textgapi
|
||||
|
||||
import (
|
||||
"go.mau.fi/mautrix-gmessages/libgm/binary"
|
||||
"go.mau.fi/mautrix-gmessages/libgm/util"
|
||||
)
|
||||
|
||||
func (c *Client) processSessionResponse(prepareSession []*Response, newSession []*Response) (*util.SessionResponse, error) {
|
||||
prepDecoded, prepDecodeErr := prepareSession[0].decryptData()
|
||||
if prepDecodeErr != nil {
|
||||
return nil, prepDecodeErr
|
||||
}
|
||||
|
||||
sessDecoded, sessDecodeErr := newSession[0].decryptData()
|
||||
if sessDecodeErr != nil {
|
||||
return nil, sessDecodeErr
|
||||
}
|
||||
|
||||
sess := sessDecoded.(*binary.NewSession)
|
||||
prep := prepDecoded.(*binary.PrepareNewSession)
|
||||
return &util.SessionResponse{
|
||||
Success: prep.Success,
|
||||
Settings: sess.Settings,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *Client) processFetchMessagesResponse(fetchMessagesRes []*Response, openConversationRes []*Response, setActiveConversationRes []*Response) (*binary.FetchMessagesResponse, error) {
|
||||
messagesDecoded, messagesDecodeErr := fetchMessagesRes[0].decryptData()
|
||||
if messagesDecodeErr != nil {
|
||||
return nil, messagesDecodeErr
|
||||
}
|
||||
return messagesDecoded.(*binary.FetchMessagesResponse), nil
|
||||
}
|
208
libgm/conversations.go
Normal file
208
libgm/conversations.go
Normal file
|
@ -0,0 +1,208 @@
|
|||
package textgapi
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"go.mau.fi/mautrix-gmessages/libgm/binary"
|
||||
)
|
||||
|
||||
type Conversations struct {
|
||||
client *Client
|
||||
|
||||
watching string // current open conversation
|
||||
|
||||
openConversation openConversation
|
||||
fetchConversationMessages fetchConversationMessages
|
||||
}
|
||||
|
||||
func (c *Conversations) List(count int64) (*binary.Conversations, error) {
|
||||
encryptedProtoPayload := &binary.ListCoversationsPayload{Count: count, Field4: 1}
|
||||
instruction, _ := c.client.instructions.GetInstruction(LIST_CONVERSATIONS)
|
||||
sentRequestId, _ := c.client.createAndSendRequest(instruction.Opcode, c.client.ttl, false, encryptedProtoPayload.ProtoReflect())
|
||||
|
||||
responses, err := c.client.sessionHandler.WaitForResponse(sentRequestId, instruction.Opcode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
decryptedProto, decryptErr := responses[0].decryptData()
|
||||
if decryptErr != nil {
|
||||
return nil, decryptErr
|
||||
}
|
||||
|
||||
if decryptedData, ok := decryptedProto.(*binary.Conversations); ok {
|
||||
c.client.cache.SetConversations(decryptedData)
|
||||
return decryptedData, nil
|
||||
} else {
|
||||
return nil, fmt.Errorf("failed to assert decryptedProto into type Conversations")
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Conversations) SendMessage(messageBuilder *MessageBuilder) (*binary.SendMessageResponse, error) {
|
||||
conv, notFound := c.client.cache.Conversations.GetConversation(messageBuilder.GetConversationId())
|
||||
if notFound != nil {
|
||||
log.Fatal(notFound)
|
||||
}
|
||||
|
||||
hasSelfParticipantId := messageBuilder.GetSelfParticipantId()
|
||||
if hasSelfParticipantId == "" {
|
||||
messageBuilder.SetSelfParticipantId(conv.SelfParticipantId)
|
||||
}
|
||||
|
||||
encryptedProtoPayload, failedToBuild := messageBuilder.Build()
|
||||
if failedToBuild != nil {
|
||||
log.Fatal(failedToBuild)
|
||||
}
|
||||
|
||||
instruction, _ := c.client.instructions.GetInstruction(SEND_TEXT_MESSAGE)
|
||||
c.client.Logger.Debug().Any("payload", encryptedProtoPayload).Msg("SendMessage Payload")
|
||||
sentRequestId, _ := c.client.createAndSendRequest(instruction.Opcode, c.client.ttl, false, encryptedProtoPayload.ProtoReflect())
|
||||
|
||||
responses, err := c.client.sessionHandler.WaitForResponse(sentRequestId, instruction.Opcode)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
decryptedProto, decryptErr := responses[0].decryptData()
|
||||
if decryptErr != nil {
|
||||
return nil, decryptErr
|
||||
}
|
||||
|
||||
if decryptedData, ok := decryptedProto.(*binary.SendMessageResponse); ok {
|
||||
return decryptedData, nil
|
||||
} else {
|
||||
return nil, fmt.Errorf("failed to assert decryptedProto into type SendMessageResponse")
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Conversations) FetchMessages(convId string, count int64, cursor *binary.Cursor) (*binary.FetchMessagesResponse, error) {
|
||||
|
||||
var openConversationRes []*Response
|
||||
var openConversationErr error
|
||||
if c.watching != convId {
|
||||
openConversationRes, openConversationErr = c.openConversation.Execute(convId)
|
||||
if openConversationErr != nil {
|
||||
return nil, openConversationErr
|
||||
}
|
||||
c.watching = convId
|
||||
}
|
||||
|
||||
fetchMessagesRes, fetchMessagesErr := c.fetchConversationMessages.Execute(convId, count, cursor)
|
||||
if fetchMessagesErr != nil {
|
||||
return nil, fetchMessagesErr
|
||||
}
|
||||
|
||||
fetchedMessagesResponse, processFail := c.client.processFetchMessagesResponse(fetchMessagesRes, openConversationRes, nil)
|
||||
if processFail != nil {
|
||||
return nil, processFail
|
||||
}
|
||||
|
||||
c.client.cache.SetMessages(fetchedMessagesResponse)
|
||||
return fetchedMessagesResponse, nil
|
||||
}
|
||||
|
||||
type fetchConversationMessages struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
func (f *fetchConversationMessages) Execute(convId string, count int64, cursor *binary.Cursor) ([]*Response, error) {
|
||||
encryptedProtoPayload := &binary.FetchConversationMessagesPayload{ConversationId: convId, Count: count, Cursor: cursor}
|
||||
instruction, _ := f.client.instructions.GetInstruction(FETCH_MESSAGES_CONVERSATION)
|
||||
sentRequestId, _ := f.client.createAndSendRequest(instruction.Opcode, f.client.ttl, false, encryptedProtoPayload.ProtoReflect())
|
||||
|
||||
responses, err := f.client.sessionHandler.WaitForResponse(sentRequestId, instruction.Opcode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return responses, nil
|
||||
}
|
||||
|
||||
type openConversation struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
func (o *openConversation) Execute(convId string) ([]*Response, error) {
|
||||
encryptedProtoPayload := &binary.OpenConversationPayload{ConversationId: convId}
|
||||
instruction, _ := o.client.instructions.GetInstruction(OPEN_CONVERSATION)
|
||||
sentRequestId, _ := o.client.createAndSendRequest(instruction.Opcode, o.client.ttl, false, encryptedProtoPayload.ProtoReflect())
|
||||
|
||||
responses, err := o.client.sessionHandler.WaitForResponse(sentRequestId, instruction.Opcode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Rest of the processing...
|
||||
|
||||
return responses, nil
|
||||
}
|
||||
|
||||
/*
|
||||
func (c *Conversations) SendMessage(conversationId string, content string, participantCount string) (*binary.SendMessageResponse, error) {
|
||||
encryptedProtoPayload := payload.NewSendConversationTextMessage(conversationId, content, participantCount)
|
||||
sentRequestId, _ := c.client.createAndSendRequest(3, c.client.ttl, false, encryptedProtoPayload.ProtoReflect())
|
||||
c.client.Logger.Debug().Any("requestId", sentRequestId).Msg("Sent sendmessage request.")
|
||||
response, responseErr := c.client.sessionHandler.WaitForResponse(sentRequestId, 3)
|
||||
if responseErr != nil {
|
||||
c.client.Logger.Err(responseErr).Msg("SendMessage channel response error")
|
||||
return nil, responseErr
|
||||
} else {
|
||||
decryptedProto, decryptErr := response.decryptData()
|
||||
if decryptErr != nil {
|
||||
return nil, decryptErr
|
||||
}
|
||||
|
||||
if decryptedData, ok := decryptedProto.(*binary.SendMessageResponse); ok {
|
||||
return decryptedData, nil
|
||||
} else {
|
||||
return nil, fmt.Errorf("failed to assert decryptedProto into type SendMessageResponse")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Conversations) PrepareOpen() (interface{}, error) {
|
||||
encryptedProtoPayload := &binary.PrepareOpenConversationPayload{Field2:1}
|
||||
sentRequestId, _ := c.client.createAndSendRequest(22, c.client.ttl, false, encryptedProtoPayload.ProtoReflect())
|
||||
c.client.Logger.Debug().Any("requestId", sentRequestId).Msg("Sent PrepareOpenConversation request.")
|
||||
response, responseErr := c.client.sessionHandler.WaitForResponse(sentRequestId, 22)
|
||||
if responseErr != nil {
|
||||
c.client.Logger.Err(responseErr).Msg("PrepareOpenConversation channel response error")
|
||||
return nil, responseErr
|
||||
} else {
|
||||
c.client.Logger.Info().Any("response", response).Msg("PrepareOpenConversation response data")
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (c *Conversations) Open(conversationId string) (interface{}, error) {
|
||||
encryptedProtoPayload := &binary.OpenConversationPayload{ConversationId:conversationId}
|
||||
sentRequestId, _ := c.client.createAndSendRequest(21, c.client.ttl, false, encryptedProtoPayload.ProtoReflect())
|
||||
c.client.Logger.Debug().Any("requestId", sentRequestId).Msg("Sent OpenConversation request.")
|
||||
response, responseErr := c.client.sessionHandler.WaitForResponse(sentRequestId, 21)
|
||||
if responseErr != nil {
|
||||
c.client.Logger.Err(responseErr).Msg("OpenConversation channel response error")
|
||||
return nil, responseErr
|
||||
} else {
|
||||
c.client.Logger.Info().Any("response", response).Msg("OpenConversation response data")
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (c *Conversations) FetchMessages(conversationId string, count int64) (*binary.FetchMessagesResponse, error) {
|
||||
encryptedProtoPayload := &binary.FetchConversationMessagesPayload{ConversationId:conversationId,Count:count}
|
||||
sentRequestId, _ := c.client.createAndSendRequest(2, c.client.ttl, false, encryptedProtoPayload.ProtoReflect())
|
||||
c.client.Logger.Debug().Any("requestId", sentRequestId).Msg("Sent FetchMessages request.")
|
||||
response, responseErr := c.client.sessionHandler.WaitForResponse(sentRequestId, 2)
|
||||
if responseErr != nil {
|
||||
c.client.Logger.Err(responseErr).Msg("FetchMessages channel response error")
|
||||
return nil, responseErr
|
||||
} else {
|
||||
decryptedMessages, decryptedErr := c.client.newMessagesResponse(response)
|
||||
if decryptedErr != nil {
|
||||
return nil, decryptedErr
|
||||
}
|
||||
return decryptedMessages, nil
|
||||
}
|
||||
}
|
||||
*/
|
41
libgm/crypto/B64.go
Normal file
41
libgm/crypto/B64.go
Normal file
|
@ -0,0 +1,41 @@
|
|||
package crypto
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func EncodeBase64Standard(data []byte) string {
|
||||
return base64.StdEncoding.EncodeToString(data)
|
||||
}
|
||||
|
||||
func EncodeBase64(data []byte) string {
|
||||
return base64.RawURLEncoding.EncodeToString(data)
|
||||
}
|
||||
|
||||
func Base64Decode(input string) ([]byte, error) {
|
||||
padding := len(input) % 4
|
||||
if padding > 0 {
|
||||
input += strings.Repeat("=", 4-padding)
|
||||
}
|
||||
|
||||
data, err := base64.URLEncoding.DecodeString(input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func Base64DecodeStandard(input string) ([]byte, error) {
|
||||
decoded, err := base64.StdEncoding.DecodeString(input)
|
||||
if err != nil {
|
||||
fmt.Println("decode error:", err)
|
||||
return nil, err
|
||||
}
|
||||
return decoded, nil
|
||||
}
|
||||
|
||||
func Base64Encode(input []byte) string {
|
||||
return base64.StdEncoding.EncodeToString(input)
|
||||
}
|
113
libgm/crypto/ECDSA.go
Normal file
113
libgm/crypto/ECDSA.go
Normal file
|
@ -0,0 +1,113 @@
|
|||
package crypto
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
type JWK struct {
|
||||
Kty string `json:"kty"`
|
||||
Crv string `json:"crv"`
|
||||
D string `json:"d"`
|
||||
X string `json:"x"`
|
||||
Y string `json:"y"`
|
||||
Ext bool `json:"ext"`
|
||||
KeyOps []string `json:"key_ops"`
|
||||
PrivateBytes []byte `json:"privateBytes,omitempty"`
|
||||
}
|
||||
|
||||
// Returns a byte slice containing the JWK and an error if the generation or export failed.
|
||||
func (t *JWK) Marshal() ([]byte, error) {
|
||||
JWKJSON, err := json.Marshal(t)
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to marshal JWK: %v", err)
|
||||
return nil,err
|
||||
}
|
||||
fmt.Printf("%s\n", JWKJSON)
|
||||
return JWKJSON,err
|
||||
}
|
||||
|
||||
func (t *JWK) PrivKeyB64Bytes() ([]byte, error){
|
||||
decodedPrivateKey, err2 := Base64Decode(t.D)
|
||||
return decodedPrivateKey, err2
|
||||
}
|
||||
|
||||
func (t *JWK) ExtractPublicKeyDetails(pubKey []byte) *JWK {
|
||||
x := EncodeBase64(pubKey[1:33])
|
||||
y := EncodeBase64(pubKey[33:])
|
||||
return &JWK{
|
||||
Kty: "EC",
|
||||
Crv: "P-256",
|
||||
X: x,
|
||||
Y: y,
|
||||
}
|
||||
}
|
||||
|
||||
func (t *JWK) DecompressPubkey() (*ecdsa.PublicKey, error) {
|
||||
xBytes, err := base64.RawURLEncoding.DecodeString(t.X)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
yBytes, err := base64.RawURLEncoding.DecodeString(t.Y)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
x := new(big.Int).SetBytes(xBytes)
|
||||
y := new(big.Int).SetBytes(yBytes)
|
||||
pubKey := &ecdsa.PublicKey{
|
||||
Curve: elliptic.P256(),
|
||||
X: x,
|
||||
Y: y,
|
||||
}
|
||||
return pubKey, nil
|
||||
}
|
||||
|
||||
func (t *JWK) UncompressPubKey() ([]byte, error) {
|
||||
xBytes, err := base64.RawURLEncoding.DecodeString(t.X)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
yBytes, err := base64.RawURLEncoding.DecodeString(t.Y)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
x := new(big.Int).SetBytes(xBytes)
|
||||
y := new(big.Int).SetBytes(yBytes)
|
||||
|
||||
pubKey := &ecdsa.PublicKey{
|
||||
Curve: elliptic.P256(),
|
||||
X: x,
|
||||
Y: y,
|
||||
}
|
||||
|
||||
uncompressedPubKey := elliptic.Marshal(pubKey.Curve, pubKey.X, pubKey.Y)
|
||||
|
||||
return uncompressedPubKey, nil
|
||||
}
|
||||
|
||||
// GenerateECDSA_P256_JWK generates a new ECDSA private key with P-256 curve
|
||||
func GenerateECDSA_P256_JWK() (*JWK, error) {
|
||||
privKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to generate private key: %v", err)
|
||||
return nil,err
|
||||
}
|
||||
|
||||
JWK := &JWK{
|
||||
Kty: "EC",
|
||||
Crv: "P-256",
|
||||
D: base64.RawURLEncoding.EncodeToString(privKey.D.Bytes()),
|
||||
X: base64.RawURLEncoding.EncodeToString(privKey.X.Bytes()),
|
||||
Y: base64.RawURLEncoding.EncodeToString(privKey.Y.Bytes()),
|
||||
Ext: true,
|
||||
KeyOps: []string{"sign"},
|
||||
}
|
||||
return JWK,nil
|
||||
}
|
115
libgm/crypto/cryptor.go
Normal file
115
libgm/crypto/cryptor.go
Normal file
|
@ -0,0 +1,115 @@
|
|||
package crypto
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/hmac"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
|
||||
"go.mau.fi/mautrix-gmessages/libgm/binary"
|
||||
)
|
||||
|
||||
type Cryptor struct {
|
||||
AES_CTR_KEY_256, SHA_256_KEY []byte
|
||||
}
|
||||
|
||||
func NewCryptor(aes_key []byte, sha_key []byte) *Cryptor {
|
||||
if aes_key != nil && sha_key != nil {
|
||||
return &Cryptor{
|
||||
AES_CTR_KEY_256: aes_key,
|
||||
SHA_256_KEY: sha_key,
|
||||
}
|
||||
}
|
||||
aes_key, sha_key = GenerateKeys()
|
||||
return &Cryptor{
|
||||
AES_CTR_KEY_256: aes_key,
|
||||
SHA_256_KEY: sha_key,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Cryptor) SaveAsJson() {
|
||||
AES_B64, SHA_B64 := EncodeBase64Standard(c.AES_CTR_KEY_256), EncodeBase64Standard(c.SHA_256_KEY)
|
||||
inter := struct {
|
||||
AES_CTR_KEY_256 string
|
||||
SHA_256_KEY string
|
||||
}{
|
||||
AES_CTR_KEY_256: AES_B64,
|
||||
SHA_256_KEY: SHA_B64,
|
||||
}
|
||||
jsonData, _ := json.Marshal(inter)
|
||||
os.WriteFile("cryptor.json", jsonData, os.ModePerm)
|
||||
}
|
||||
|
||||
func (c *Cryptor) Encrypt(plaintext []byte) ([]byte, error) {
|
||||
iv := make([]byte, aes.BlockSize)
|
||||
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
block, err := aes.NewCipher(c.AES_CTR_KEY_256)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ciphertext := make([]byte, len(plaintext))
|
||||
stream := cipher.NewCTR(block, iv)
|
||||
stream.XORKeyStream(ciphertext, plaintext)
|
||||
|
||||
ciphertext = append(ciphertext, iv...)
|
||||
|
||||
mac := hmac.New(sha256.New, c.SHA_256_KEY)
|
||||
mac.Write(ciphertext)
|
||||
hmac := mac.Sum(nil)
|
||||
|
||||
ciphertext = append(ciphertext, hmac...)
|
||||
|
||||
return ciphertext, nil
|
||||
}
|
||||
|
||||
func (c *Cryptor) Decrypt(encryptedData []byte) ([]byte, error) {
|
||||
if len(encryptedData) < 48 {
|
||||
return nil, errors.New("input data is too short")
|
||||
}
|
||||
|
||||
hmacSignature := encryptedData[len(encryptedData)-32:]
|
||||
encryptedDataWithoutHMAC := encryptedData[:len(encryptedData)-32]
|
||||
|
||||
mac := hmac.New(sha256.New, c.SHA_256_KEY)
|
||||
mac.Write(encryptedDataWithoutHMAC)
|
||||
expectedHMAC := mac.Sum(nil)
|
||||
|
||||
if !hmac.Equal(hmacSignature, expectedHMAC) {
|
||||
return nil, errors.New("HMAC mismatch")
|
||||
}
|
||||
|
||||
iv := encryptedDataWithoutHMAC[len(encryptedDataWithoutHMAC)-16:]
|
||||
encryptedDataWithoutHMAC = encryptedDataWithoutHMAC[:len(encryptedDataWithoutHMAC)-16]
|
||||
|
||||
block, err := aes.NewCipher(c.AES_CTR_KEY_256)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stream := cipher.NewCTR(block, iv)
|
||||
stream.XORKeyStream(encryptedDataWithoutHMAC, encryptedDataWithoutHMAC)
|
||||
|
||||
return encryptedDataWithoutHMAC, nil
|
||||
}
|
||||
|
||||
func (c *Cryptor) DecryptAndDecodeData(encryptedData []byte, message protoreflect.ProtoMessage) error {
|
||||
decryptedData, err := c.Decrypt(encryptedData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = binary.DecodeProtoMessage(decryptedData, message)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
32
libgm/crypto/decode.go
Normal file
32
libgm/crypto/decode.go
Normal file
|
@ -0,0 +1,32 @@
|
|||
package crypto
|
||||
|
||||
import (
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
"go.mau.fi/mautrix-gmessages/libgm/binary"
|
||||
)
|
||||
|
||||
func DecodeAndEncodeB64(data string, msg proto.Message) error {
|
||||
decodedBytes, err := Base64DecodeStandard(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = binary.DecodeProtoMessage(decodedBytes, msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func DecodeEncodedResponse(data string) (*binary.EncodedResponse, error) {
|
||||
decodedBytes, err := Base64DecodeStandard(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
decodedData := &binary.EncodedResponse{}
|
||||
err = binary.DecodeProtoMessage(decodedBytes, decodedData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return decodedData, nil
|
||||
}
|
60
libgm/crypto/encode.go
Normal file
60
libgm/crypto/encode.go
Normal file
|
@ -0,0 +1,60 @@
|
|||
package crypto
|
||||
|
||||
import (
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
"go.mau.fi/mautrix-gmessages/libgm/binary"
|
||||
)
|
||||
|
||||
var SequenceOne = []int{1, 2, 840, 10045, 2, 1}
|
||||
var SequenceTwo = []int{1, 2, 840, 10045, 3, 1, 7}
|
||||
|
||||
func EncodeValues(a *[]byte, b []int) {
|
||||
*a = append(*a, 6)
|
||||
idx := len(*a)
|
||||
*a = append(*a, 0)
|
||||
*a = append(*a, byte(40*b[0]+b[1]))
|
||||
for i := 2; i < len(b); i++ {
|
||||
d := b[i]
|
||||
e := make([]byte, 0)
|
||||
if d > 128 {
|
||||
e = append(e, byte(d/128)+128)
|
||||
}
|
||||
e = append(e, byte(d%128))
|
||||
*a = append(*a, e...)
|
||||
}
|
||||
(*a)[idx] = byte(len(*a) - idx - 1)
|
||||
}
|
||||
|
||||
func AppendBytes(a []byte, b []byte) []byte {
|
||||
newA := make([]byte, len(a))
|
||||
copy(newA, a)
|
||||
|
||||
newA = HelperAppendBytes(newA, 48)
|
||||
newA = HelperAppendBytes(newA, byte(len(b)))
|
||||
for _, value := range b {
|
||||
newA = HelperAppendBytes(newA, value)
|
||||
}
|
||||
return newA
|
||||
}
|
||||
|
||||
func HelperAppendBytes(a []byte, b byte) []byte {
|
||||
return append(a, b)
|
||||
}
|
||||
|
||||
func AppendByteSequence(byteArr1 []byte, byteArr2 []byte, uncompressedPublicKey []byte) []byte {
|
||||
copiedByteArray := AppendBytes(byteArr1, byteArr2)
|
||||
copiedByteArray = HelperAppendBytes(copiedByteArray, 3)
|
||||
copiedByteArray = HelperAppendBytes(copiedByteArray, uint8(len(uncompressedPublicKey)+1))
|
||||
copiedByteArray = HelperAppendBytes(copiedByteArray, 0)
|
||||
return copiedByteArray
|
||||
}
|
||||
|
||||
func EncodeProtoB64(message proto.Message) (string, error) {
|
||||
protoBytes, protoErr := binary.EncodeProtoMessage(message)
|
||||
if protoErr != nil {
|
||||
return "", protoErr
|
||||
}
|
||||
encodedStr := EncodeBase64Standard(protoBytes)
|
||||
return encodedStr, nil
|
||||
}
|
27
libgm/crypto/generate.go
Normal file
27
libgm/crypto/generate.go
Normal file
|
@ -0,0 +1,27 @@
|
|||
package crypto
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"log"
|
||||
)
|
||||
|
||||
func GenerateKey(length int) ([]byte, error) {
|
||||
key := make([]byte, length)
|
||||
_, err := rand.Read(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return key, nil
|
||||
}
|
||||
|
||||
func GenerateKeys() ([]byte, []byte) {
|
||||
key, err := GenerateKey(32)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
key2, err2 := GenerateKey(32)
|
||||
if err2 != nil {
|
||||
log.Fatal(err2)
|
||||
}
|
||||
return key, key2
|
||||
}
|
194
libgm/crypto/imageCryptor.go
Normal file
194
libgm/crypto/imageCryptor.go
Normal file
|
@ -0,0 +1,194 @@
|
|||
package crypto
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"math"
|
||||
)
|
||||
|
||||
type ImageCryptor struct {
|
||||
key []byte
|
||||
}
|
||||
|
||||
func NewImageCryptor(key []byte) (*ImageCryptor, error) {
|
||||
if len(key) != 32 {
|
||||
return nil, fmt.Errorf("unsupported AES key length (got=%d expected=32)", len(key))
|
||||
}
|
||||
return &ImageCryptor{key: key}, nil
|
||||
}
|
||||
|
||||
func (ic *ImageCryptor) GetKey() []byte {
|
||||
return ic.key
|
||||
}
|
||||
|
||||
func (ic *ImageCryptor) UpdateDecryptionKey(key []byte) {
|
||||
ic.key = key
|
||||
}
|
||||
|
||||
func (ic *ImageCryptor) Encrypt(imageBytes []byte, aad []byte) ([]byte, error) {
|
||||
block, err := aes.NewCipher(ic.key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
gcm, err := cipher.NewGCM(block)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nonce := make([]byte, gcm.NonceSize())
|
||||
_, err = rand.Read(nonce)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ciphertext := gcm.Seal(nonce, nonce, imageBytes, aad)
|
||||
return ciphertext, nil
|
||||
}
|
||||
|
||||
func (ic *ImageCryptor) Decrypt(iv []byte, data []byte, aad []byte) ([]byte, error) {
|
||||
block, err := aes.NewCipher(ic.key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
gcm, err := cipher.NewGCM(block)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(data) < gcm.NonceSize() {
|
||||
return nil, fmt.Errorf("invalid encrypted data length (got=%d)", len(data))
|
||||
}
|
||||
|
||||
ciphertext := data[gcm.NonceSize():]
|
||||
|
||||
decrypted, err := gcm.Open(nil, iv, ciphertext, aad)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return decrypted, nil
|
||||
}
|
||||
|
||||
func (ic *ImageCryptor) EncryptData(data []byte) ([]byte, error) {
|
||||
rawChunkSize := 1 << 15
|
||||
chunkSize := rawChunkSize-28
|
||||
var tasks []chan []byte
|
||||
chunkIndex := 0
|
||||
|
||||
for i := 0; i < len(data); i += chunkSize {
|
||||
if i+chunkSize > len(data) {
|
||||
chunkSize = len(data) - i
|
||||
}
|
||||
|
||||
chunk := make([]byte, chunkSize)
|
||||
copy(chunk, data[i:i+chunkSize])
|
||||
|
||||
aad := ic.calculateAAD(chunkIndex, i+chunkSize, len(data))
|
||||
tasks = append(tasks, make(chan []byte))
|
||||
go func(chunk, aad []byte, task chan []byte) {
|
||||
encrypted, err := ic.Encrypt(chunk, aad)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
task <- nil
|
||||
} else {
|
||||
task <- encrypted
|
||||
}
|
||||
}(chunk, aad, tasks[chunkIndex])
|
||||
|
||||
chunkIndex++
|
||||
}
|
||||
|
||||
var result [][]byte
|
||||
for _, task := range tasks {
|
||||
encrypted := <-task
|
||||
if encrypted == nil {
|
||||
continue
|
||||
}
|
||||
result = append(result, encrypted)
|
||||
}
|
||||
|
||||
var concatted []byte
|
||||
for _, r := range result {
|
||||
concatted = append(concatted, r...)
|
||||
}
|
||||
|
||||
encryptedHeader := []byte{0, byte(math.Log2(float64(rawChunkSize)))}
|
||||
|
||||
return append(encryptedHeader, concatted...), nil
|
||||
}
|
||||
|
||||
func (ic *ImageCryptor) DecryptData(encryptedData []byte) ([]byte, error) {
|
||||
if len(encryptedData) == 0 || len(ic.key) != 32 {
|
||||
return encryptedData, nil
|
||||
}
|
||||
if encryptedData[0] != 0 {
|
||||
return nil, fmt.Errorf("invalid first-byte header signature (got=%o , expected=%o)", encryptedData[0], 0)
|
||||
}
|
||||
|
||||
chunkSize := 1 << encryptedData[1]
|
||||
encryptedData = encryptedData[2:]
|
||||
|
||||
var tasks []chan []byte
|
||||
chunkIndex := 0
|
||||
|
||||
for i := 0; i < len(encryptedData); i += chunkSize {
|
||||
if i+chunkSize > len(encryptedData) {
|
||||
chunkSize = len(encryptedData) - i
|
||||
}
|
||||
|
||||
chunk := make([]byte, chunkSize)
|
||||
copy(chunk, encryptedData[i:i+chunkSize])
|
||||
|
||||
iv := chunk[:12]
|
||||
aad := ic.calculateAAD(chunkIndex, i+chunkSize, len(encryptedData))
|
||||
tasks = append(tasks, make(chan []byte))
|
||||
go func(iv, chunk, aad []byte, task chan []byte) {
|
||||
decrypted, err := ic.Decrypt(iv, chunk, aad)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
task <- nil
|
||||
} else {
|
||||
task <- decrypted
|
||||
}
|
||||
}(iv, chunk, aad, tasks[chunkIndex])
|
||||
|
||||
chunkIndex++
|
||||
}
|
||||
|
||||
var result [][]byte
|
||||
for _, task := range tasks {
|
||||
decrypted := <-task
|
||||
if decrypted == nil {
|
||||
continue
|
||||
}
|
||||
result = append(result, decrypted)
|
||||
}
|
||||
|
||||
var concatted []byte
|
||||
for _, r := range result {
|
||||
concatted = append(concatted, r...)
|
||||
}
|
||||
|
||||
return concatted, nil
|
||||
}
|
||||
|
||||
func (ic *ImageCryptor) calculateAAD(index, end, total int) []byte {
|
||||
aad := make([]byte, 5)
|
||||
|
||||
i := 4
|
||||
for index > 0 {
|
||||
aad[i] = byte(index % 256)
|
||||
index = index / 256
|
||||
i--
|
||||
}
|
||||
|
||||
if end >= total {
|
||||
aad[0] = 1
|
||||
}
|
||||
|
||||
return aad
|
||||
}
|
43
libgm/debug/logger.go
Normal file
43
libgm/debug/logger.go
Normal file
|
@ -0,0 +1,43 @@
|
|||
package debug
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/mattn/go-colorable"
|
||||
zerolog "github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
var colors = map[string]string{
|
||||
"text": "\x1b[38;5;6m%s\x1b[0m",
|
||||
"debug": "\x1b[32mDEBUG\x1b[0m",
|
||||
"gray": "\x1b[38;5;8m%s\x1b[0m",
|
||||
"info": "\x1b[38;5;111mINFO\x1b[0m",
|
||||
"error": "\x1b[38;5;204mERROR\x1b[0m",
|
||||
"fatal": "\x1b[38;5;52mFATAL\x1b[0m",
|
||||
}
|
||||
|
||||
var output = zerolog.ConsoleWriter{
|
||||
Out: colorable.NewColorableStdout(),
|
||||
TimeFormat: time.ANSIC,
|
||||
FormatLevel: func(i interface{}) string {
|
||||
name := fmt.Sprintf("%s", i)
|
||||
coloredName := colors[name]
|
||||
return coloredName
|
||||
},
|
||||
FormatMessage: func(i interface{}) string {
|
||||
coloredMsg := fmt.Sprintf(colors["text"], i)
|
||||
return coloredMsg
|
||||
},
|
||||
FormatFieldName: func(i interface{}) string {
|
||||
name := fmt.Sprintf("%s", i)
|
||||
return fmt.Sprintf(colors["gray"], name+"=")
|
||||
},
|
||||
FormatFieldValue: func(i interface{}) string {
|
||||
return fmt.Sprintf("%s", i)
|
||||
},
|
||||
NoColor: false,
|
||||
}
|
||||
|
||||
func NewLogger() zerolog.Logger {
|
||||
return zerolog.New(output).With().Timestamp().Logger()
|
||||
}
|
26
libgm/event_handler.go
Normal file
26
libgm/event_handler.go
Normal file
|
@ -0,0 +1,26 @@
|
|||
package textgapi
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"go.mau.fi/mautrix-gmessages/libgm/binary"
|
||||
)
|
||||
|
||||
func (c *Client) handleEventOpCode(response *Response) {
|
||||
//c.Logger.Debug().Any("res", response).Msg("got event response")
|
||||
eventData := &binary.Event{}
|
||||
decryptedErr := c.cryptor.DecryptAndDecodeData(response.Data.EncryptedData, eventData)
|
||||
if decryptedErr != nil {
|
||||
log.Fatal(decryptedErr)
|
||||
}
|
||||
switch evt := eventData.Event.(type) {
|
||||
case *binary.Event_MessageEvent:
|
||||
c.handleMessageEvent(response, evt)
|
||||
case *binary.Event_ConversationEvent:
|
||||
c.handleConversationEvent(response, evt)
|
||||
case *binary.Event_UserAlertEvent:
|
||||
c.handleUserAlertEvent(response, evt)
|
||||
default:
|
||||
c.Logger.Debug().Any("res", response).Msg("unknown event")
|
||||
}
|
||||
}
|
67
libgm/events/conversations.go
Normal file
67
libgm/events/conversations.go
Normal file
|
@ -0,0 +1,67 @@
|
|||
package events
|
||||
|
||||
import "go.mau.fi/mautrix-gmessages/libgm/cache"
|
||||
|
||||
type ConversationEvent interface {
|
||||
GetConversation() *cache.Conversation
|
||||
}
|
||||
|
||||
// Triggered when tabbing out of a conversation
|
||||
type CONVERSATION_EXIT struct {
|
||||
Conversation *cache.Conversation
|
||||
}
|
||||
|
||||
func (c *CONVERSATION_EXIT) GetConversation() *cache.Conversation {
|
||||
return c.Conversation
|
||||
}
|
||||
|
||||
// Triggered when a conversation is archived
|
||||
type CONVERSATION_ARCHIVED struct {
|
||||
Conversation *cache.Conversation
|
||||
}
|
||||
|
||||
func (c *CONVERSATION_ARCHIVED) GetConversation() *cache.Conversation {
|
||||
return c.Conversation
|
||||
}
|
||||
|
||||
// Triggered when a conversation is unarchived
|
||||
type CONVERSATION_UNARCHIVED struct {
|
||||
Conversation *cache.Conversation
|
||||
}
|
||||
|
||||
func (c *CONVERSATION_UNARCHIVED) GetConversation() *cache.Conversation {
|
||||
return c.Conversation
|
||||
}
|
||||
|
||||
// Triggered when a conversation is deleted
|
||||
type CONVERSATION_DELETED struct {
|
||||
Conversation *cache.Conversation
|
||||
}
|
||||
|
||||
func (c *CONVERSATION_DELETED) GetConversation() *cache.Conversation {
|
||||
return c.Conversation
|
||||
}
|
||||
|
||||
func NewConversationExit(conversation *cache.Conversation) ConversationEvent {
|
||||
return &CONVERSATION_EXIT{
|
||||
Conversation: conversation,
|
||||
}
|
||||
}
|
||||
|
||||
func NewConversationArchived(conversation *cache.Conversation) ConversationEvent {
|
||||
return &CONVERSATION_ARCHIVED{
|
||||
Conversation: conversation,
|
||||
}
|
||||
}
|
||||
|
||||
func NewConversationUnarchived(conversation *cache.Conversation) ConversationEvent {
|
||||
return &CONVERSATION_UNARCHIVED{
|
||||
Conversation: conversation,
|
||||
}
|
||||
}
|
||||
|
||||
func NewConversationDeleted(conversation *cache.Conversation) ConversationEvent {
|
||||
return &CONVERSATION_DELETED{
|
||||
Conversation: conversation,
|
||||
}
|
||||
}
|
65
libgm/events/messages.go
Normal file
65
libgm/events/messages.go
Normal file
|
@ -0,0 +1,65 @@
|
|||
package events
|
||||
|
||||
import (
|
||||
"go.mau.fi/mautrix-gmessages/libgm/cache"
|
||||
)
|
||||
|
||||
type MessageEvent interface {
|
||||
GetMessage() cache.Message
|
||||
}
|
||||
|
||||
type MESSAGE_SENDING struct {
|
||||
Message cache.Message
|
||||
}
|
||||
|
||||
func (m *MESSAGE_SENDING) GetMessage() cache.Message {
|
||||
return m.Message
|
||||
}
|
||||
|
||||
func NewMessageSending(message cache.Message) MessageEvent {
|
||||
return &MESSAGE_SENDING{
|
||||
Message: message,
|
||||
}
|
||||
}
|
||||
|
||||
type MESSAGE_SENT struct {
|
||||
Message cache.Message
|
||||
}
|
||||
|
||||
func (m *MESSAGE_SENT) GetMessage() cache.Message {
|
||||
return m.Message
|
||||
}
|
||||
|
||||
func NewMessageSent(message cache.Message) MessageEvent {
|
||||
return &MESSAGE_SENT{
|
||||
Message: message,
|
||||
}
|
||||
}
|
||||
|
||||
type MESSAGE_RECEIVING struct {
|
||||
Message cache.Message
|
||||
}
|
||||
|
||||
func (m *MESSAGE_RECEIVING) GetMessage() cache.Message {
|
||||
return m.Message
|
||||
}
|
||||
|
||||
func NewMessageReceiving(message cache.Message) MessageEvent {
|
||||
return &MESSAGE_RECEIVING{
|
||||
Message: message,
|
||||
}
|
||||
}
|
||||
|
||||
type MESSAGE_RECEIVED struct {
|
||||
Message cache.Message
|
||||
}
|
||||
|
||||
func (m *MESSAGE_RECEIVED) GetMessage() cache.Message {
|
||||
return m.Message
|
||||
}
|
||||
|
||||
func NewMessageReceived(message cache.Message) MessageEvent {
|
||||
return &MESSAGE_RECEIVED{
|
||||
Message: message,
|
||||
}
|
||||
}
|
22
libgm/events/qr.go
Normal file
22
libgm/events/qr.go
Normal file
|
@ -0,0 +1,22 @@
|
|||
package events
|
||||
|
||||
type QRCODE_UPDATED struct {
|
||||
Image []byte
|
||||
Height int
|
||||
Width int
|
||||
|
||||
googleUrl string
|
||||
}
|
||||
|
||||
func NewQrCodeUpdated(image []byte, height int, width int, googleUrl string) *QRCODE_UPDATED {
|
||||
return &QRCODE_UPDATED{
|
||||
Image: image,
|
||||
Height: height,
|
||||
Width: width,
|
||||
googleUrl: googleUrl,
|
||||
}
|
||||
}
|
||||
|
||||
func (q *QRCODE_UPDATED) GetGoogleUrl() string {
|
||||
return q.googleUrl
|
||||
}
|
18
libgm/events/ready.go
Normal file
18
libgm/events/ready.go
Normal file
|
@ -0,0 +1,18 @@
|
|||
package events
|
||||
|
||||
import (
|
||||
"go.mau.fi/mautrix-gmessages/libgm/binary"
|
||||
"go.mau.fi/mautrix-gmessages/libgm/util"
|
||||
)
|
||||
|
||||
type CLIENT_READY struct {
|
||||
Session *util.SessionResponse
|
||||
Conversations []*binary.Conversation
|
||||
}
|
||||
|
||||
func NewClientReady(session *util.SessionResponse, conversationList *binary.Conversations) *CLIENT_READY {
|
||||
return &CLIENT_READY{
|
||||
Session: session,
|
||||
Conversations: conversationList.Conversations,
|
||||
}
|
||||
}
|
24
libgm/events/useralerts.go
Normal file
24
libgm/events/useralerts.go
Normal file
|
@ -0,0 +1,24 @@
|
|||
package events
|
||||
|
||||
|
||||
type BROWSER_ACTIVE struct {
|
||||
SessionId string
|
||||
}
|
||||
|
||||
func NewBrowserActive(sessionId string) *BROWSER_ACTIVE {
|
||||
return &BROWSER_ACTIVE{
|
||||
SessionId: sessionId,
|
||||
}
|
||||
}
|
||||
|
||||
type BATTERY struct {}
|
||||
|
||||
func NewBattery() *BATTERY {
|
||||
return &BATTERY{}
|
||||
}
|
||||
|
||||
type DATA_CONNECTION struct {}
|
||||
|
||||
func NewDataConnection() *DATA_CONNECTION {
|
||||
return &DATA_CONNECTION{}
|
||||
}
|
44
libgm/handler_conversation.go
Normal file
44
libgm/handler_conversation.go
Normal file
|
@ -0,0 +1,44 @@
|
|||
package textgapi
|
||||
|
||||
import (
|
||||
"go.mau.fi/mautrix-gmessages/libgm/binary"
|
||||
"go.mau.fi/mautrix-gmessages/libgm/cache"
|
||||
"go.mau.fi/mautrix-gmessages/libgm/events"
|
||||
)
|
||||
|
||||
func (c *Client) handleConversationEvent(response *Response, evtData *binary.Event_ConversationEvent) {
|
||||
lastCacheConv, notExists := c.cache.Conversations.GetConversation(evtData.ConversationEvent.Data.ConversationId)
|
||||
evtConv := evtData.ConversationEvent.Data
|
||||
|
||||
//c.Logger.Debug().Any("convData", evtConv).Msg("Got conversation event!")
|
||||
var eventData events.ConversationEvent
|
||||
if evtConv.Status == 3 {
|
||||
lastCacheConv.Delete()
|
||||
eventData = events.NewConversationDeleted(lastCacheConv)
|
||||
c.triggerEvent(eventData)
|
||||
return
|
||||
}
|
||||
updatedCacheConv := c.cache.Conversations.UpdateConversation(evtConv)
|
||||
eventData = c.getConversationEventInterface(lastCacheConv, updatedCacheConv, notExists)
|
||||
if eventData == nil {
|
||||
return
|
||||
}
|
||||
c.triggerEvent(eventData)
|
||||
}
|
||||
|
||||
func (c *Client) getConversationEventInterface(lastCacheConv *cache.Conversation, updatedCacheConv *cache.Conversation, notExists error) events.ConversationEvent {
|
||||
var evt events.ConversationEvent
|
||||
convStatus := updatedCacheConv.Status
|
||||
|
||||
switch convStatus {
|
||||
case 1: // unarchived
|
||||
if lastCacheConv.Status != 1 {
|
||||
evt = events.NewConversationUnarchived(updatedCacheConv)
|
||||
}
|
||||
case 2: // archived
|
||||
evt = events.NewConversationArchived(updatedCacheConv)
|
||||
case 3: // deleted
|
||||
evt = events.NewConversationDeleted(updatedCacheConv)
|
||||
}
|
||||
return evt
|
||||
}
|
57
libgm/handler_message.go
Normal file
57
libgm/handler_message.go
Normal file
|
@ -0,0 +1,57 @@
|
|||
package textgapi
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"go.mau.fi/mautrix-gmessages/libgm/binary"
|
||||
"go.mau.fi/mautrix-gmessages/libgm/cache"
|
||||
|
||||
//"github.com/0xzer/textgapi/cache"
|
||||
"go.mau.fi/mautrix-gmessages/libgm/events"
|
||||
)
|
||||
|
||||
func (c *Client) handleMessageEvent(response *Response, evtData *binary.Event_MessageEvent) {
|
||||
msgData := evtData.MessageEvent.Data
|
||||
currConv, convNotFound := c.cache.Conversations.GetConversation(msgData.ConversationId)
|
||||
if convNotFound != nil {
|
||||
log.Fatal(convNotFound)
|
||||
}
|
||||
lastCacheMsg, errGetMsg := currConv.GetMessage(msgData.MessageId)
|
||||
|
||||
updatedCacheMsg := currConv.UpdateMessage(msgData)
|
||||
eventData := c.getMessageEventInterface(currConv, lastCacheMsg, errGetMsg, updatedCacheMsg)
|
||||
if eventData == nil {
|
||||
return
|
||||
}
|
||||
c.triggerEvent(eventData)
|
||||
}
|
||||
|
||||
func (c *Client) getMessageEventInterface(currConv *cache.Conversation, lastCacheMsg cache.Message, lastCacheErr error, evtMsg cache.Message) events.MessageEvent {
|
||||
var evt events.MessageEvent
|
||||
|
||||
msgStatusCode := evtMsg.MessageStatus.Code
|
||||
fromMe := evtMsg.FromMe()
|
||||
|
||||
switch msgStatusCode {
|
||||
case 5: // sending
|
||||
if lastCacheErr != nil {
|
||||
if fromMe {
|
||||
evt = events.NewMessageSending(evtMsg)
|
||||
} else {
|
||||
evt = events.NewMessageReceiving(evtMsg)
|
||||
}
|
||||
}
|
||||
case 1: // sent
|
||||
if lastCacheMsg.MessageStatus.Code != 1 {
|
||||
if fromMe {
|
||||
evt = events.NewMessageSent(evtMsg)
|
||||
} else {
|
||||
evt = events.NewMessageReceived(evtMsg)
|
||||
}
|
||||
}
|
||||
default:
|
||||
c.Logger.Debug().Any("data", evtMsg).Msg("Unknown msgstatus code")
|
||||
}
|
||||
|
||||
return evt
|
||||
}
|
23
libgm/handler_useralert.go
Normal file
23
libgm/handler_useralert.go
Normal file
|
@ -0,0 +1,23 @@
|
|||
package textgapi
|
||||
|
||||
import (
|
||||
"go.mau.fi/mautrix-gmessages/libgm/binary"
|
||||
"go.mau.fi/mautrix-gmessages/libgm/events"
|
||||
)
|
||||
|
||||
func (c *Client) handleUserAlertEvent(response *Response, evtData *binary.Event_UserAlertEvent) {
|
||||
switch evtData.UserAlertEvent.AlertType {
|
||||
case 2:
|
||||
browserActive := events.NewBrowserActive(response.Data.RequestId)
|
||||
c.triggerEvent(browserActive)
|
||||
return
|
||||
case 5, 6:
|
||||
batteryEvt := events.NewBattery()
|
||||
c.triggerEvent(batteryEvt)
|
||||
return
|
||||
case 3, 4:
|
||||
dataConnectionEvt := events.NewDataConnection()
|
||||
c.triggerEvent(dataConnectionEvt)
|
||||
return
|
||||
}
|
||||
}
|
171
libgm/image_builder.go
Normal file
171
libgm/image_builder.go
Normal file
|
@ -0,0 +1,171 @@
|
|||
package textgapi
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
validator "github.com/gabriel-vasile/mimetype"
|
||||
|
||||
"go.mau.fi/mautrix-gmessages/libgm/crypto"
|
||||
"go.mau.fi/mautrix-gmessages/libgm/util"
|
||||
)
|
||||
|
||||
type ImageType struct {
|
||||
Extension string
|
||||
Format string
|
||||
Type int64
|
||||
}
|
||||
|
||||
var ImageTypes = map[string]ImageType{
|
||||
"image/jpeg": {Extension: "jpeg", Format: "image/jpeg", Type: 1},
|
||||
"image/jpg": {Extension: "jpg", Format: "image/jpg", Type: 2},
|
||||
"image/png": {Extension: "png", Format: "image/png", Type: 3},
|
||||
"image/gif": {Extension: "gif", Format: "image/gif", Type: 4},
|
||||
"image/wbmp": {Extension: "wbmp", Format: "image/wbmp", Type: 5},
|
||||
"image/bmp": {Extension: "bmp", Format: "image/bmp", Type: 6},
|
||||
"image/x-ms-bmp": {Extension: "bmp", Format: "image/x-ms-bmp", Type: 6},
|
||||
"audio/aac": {Extension: "aac", Format: "audio/aac", Type: 14},
|
||||
"audio/amr": {Extension: "amr", Format: "audio/amr", Type: 15},
|
||||
"audio/mp3": {Extension: "mp3", Format: "audio/mp3", Type: 16},
|
||||
"audio/mpeg": {Extension: "mpeg", Format: "audio/mpeg", Type: 17},
|
||||
"audio/mpg": {Extension: "mpg", Format: "audio/mpg", Type: 18},
|
||||
"audio/mp4": {Extension: "mp4", Format: "audio/mp4", Type: 19},
|
||||
"audio/mp4-latm": {Extension: "latm", Format: "audio/mp4-latm", Type: 20},
|
||||
"audio/3gpp": {Extension: "3gpp", Format: "audio/3gpp", Type: 21},
|
||||
"audio/ogg": {Extension: "ogg", Format: "audio/ogg", Type: 22},
|
||||
"video/mp4": {Extension: "mp4", Format: "video/mp4", Type: 8},
|
||||
"video/3gpp2": {Extension: "3gpp2", Format: "video/3gpp2", Type: 9},
|
||||
"video/3gpp": {Extension: "3gpp", Format: "video/3gpp", Type: 10},
|
||||
"video/webm": {Extension: "webm", Format: "video/webm", Type: 11},
|
||||
"video/x-matroska": {Extension: "mkv", Format: "video/x-matroska", Type: 12},
|
||||
"application/pdf": {Extension: "pdf", Format: "application/pdf", Type: 25},
|
||||
"application/txt": {Extension: "txt", Format: "application/txt", Type: 26},
|
||||
"application/html": {Extension: "html", Format: "application/html", Type: 27},
|
||||
"application/msword": {Extension: "doc", Format: "application/msword", Type: 28},
|
||||
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": {Extension: "docx", Format: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", Type: 29},
|
||||
"application/vnd.openxmlformats-officedocument.presentationml.presentation": {Extension: "pptx", Format: "application/vnd.openxmlformats-officedocument.presentationml.presentation", Type: 30},
|
||||
"application/vnd.ms-powerpoint": {Extension: "ppt", Format: "application/vnd.ms-powerpoint", Type: 31},
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": {Extension: "xlsx", Format: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", Type: 32},
|
||||
"application/vnd.ms-excel": {Extension: "xls", Format: "application/vnd.ms-excel", Type: 33},
|
||||
"application/vnd.android.package-archive": {Extension: "apk", Format: "application/vnd.android.package-archive", Type: 34},
|
||||
"application/zip": {Extension: "zip", Format: "application/zip", Type: 35},
|
||||
"application/java-archive": {Extension: "jar", Format: "application/java-archive", Type: 36},
|
||||
"text/x-vCalendar": {Extension: "vcs", Format: "text/x-vCalendar", Type: 38},
|
||||
"text/x-vcalendar": {Extension: "ics", Format: "text/x-vcalendar", Type: 39},
|
||||
"text/calendar": {Extension: "ics", Format: "text/calendar", Type: 40},
|
||||
"application/vcs": {Extension: "vcs", Format: "application/vcs", Type: 41},
|
||||
"application/ics": {Extension: "ics", Format: "application/ics", Type: 42},
|
||||
"application/hbs-vcs": {Extension: "vcs", Format: "application/hbs-vcs", Type: 43},
|
||||
"text/vcard": {Extension: "vcard", Format: "text/vcard", Type: 24},
|
||||
"text/x-vcard": {Extension: "vcard", Format: "text/x-vcard", Type: 24},
|
||||
}
|
||||
|
||||
type Image struct {
|
||||
imageCryptor *crypto.ImageCryptor
|
||||
|
||||
imageName string
|
||||
imageId string
|
||||
imageType ImageType
|
||||
imageBytes []byte
|
||||
imageSize int64
|
||||
}
|
||||
|
||||
func (i *Image) GetEncryptedBytes() ([]byte, error) {
|
||||
encryptedBytes, encryptErr := i.imageCryptor.EncryptData(i.imageBytes)
|
||||
if encryptErr != nil {
|
||||
return nil, encryptErr
|
||||
}
|
||||
return encryptedBytes, nil
|
||||
}
|
||||
|
||||
func (i *Image) GetImageCryptor() *crypto.ImageCryptor {
|
||||
return i.imageCryptor
|
||||
}
|
||||
|
||||
func (i *Image) GetImageName() string {
|
||||
return i.imageName
|
||||
}
|
||||
|
||||
func (i *Image) GetImageBytes() []byte {
|
||||
return i.imageBytes
|
||||
}
|
||||
|
||||
func (i *Image) GetImageSize() int64 {
|
||||
return i.imageSize
|
||||
}
|
||||
|
||||
func (i *Image) GetImageType() ImageType {
|
||||
return i.imageType
|
||||
}
|
||||
|
||||
func (i *Image) GetImageId() string {
|
||||
return i.imageId
|
||||
}
|
||||
|
||||
func (mb *MessageBuilder) AddImageFromPath(filePath string) *MessageBuilder {
|
||||
if mb.err != nil {
|
||||
return mb
|
||||
}
|
||||
file, err := os.ReadFile(filePath)
|
||||
if err != nil {
|
||||
mb.err = err
|
||||
return mb
|
||||
}
|
||||
return mb.AddImage(file)
|
||||
}
|
||||
|
||||
// This is the equivalent of dragging an image into the window on messages web
|
||||
//
|
||||
// Keep in mind that adding an image to a MessageBuilder will also upload the image to googles server
|
||||
func (mb *MessageBuilder) AddImage(imgBytes []byte) *MessageBuilder {
|
||||
if mb.err != nil {
|
||||
return mb
|
||||
}
|
||||
|
||||
newImage, newImageErr := mb.newImageData(imgBytes)
|
||||
if newImageErr != nil {
|
||||
mb.err = newImageErr
|
||||
return mb
|
||||
}
|
||||
|
||||
startUploadImage, failedUpload := mb.client.StartUploadMedia(newImage)
|
||||
if failedUpload != nil {
|
||||
mb.err = failedUpload
|
||||
return mb
|
||||
}
|
||||
|
||||
finalizedImage, failedFinalize := mb.client.FinalizeUploadMedia(startUploadImage)
|
||||
if failedFinalize != nil {
|
||||
mb.err = failedFinalize
|
||||
return mb
|
||||
}
|
||||
|
||||
mb.images = append(mb.images, finalizedImage)
|
||||
return mb
|
||||
}
|
||||
|
||||
func (mb *MessageBuilder) newImageData(imgBytes []byte) (*Image, error) {
|
||||
imgFormat := validator.Detect(imgBytes)
|
||||
if imgFormat.String() == "text/plain" {
|
||||
return nil, fmt.Errorf("could not validate media content-type: received %s", imgFormat.String())
|
||||
}
|
||||
imgType := ImageTypes[imgFormat.String()]
|
||||
imageId := util.GenerateImageId()
|
||||
imageName := util.RandStr(8) + "." + imgType.Extension
|
||||
decryptionKey, err := crypto.GenerateKey(32)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
imageCryptor, cryptorErr := crypto.NewImageCryptor(decryptionKey)
|
||||
if cryptorErr != nil {
|
||||
return nil, cryptorErr
|
||||
}
|
||||
return &Image{
|
||||
imageCryptor: imageCryptor,
|
||||
imageId: imageId,
|
||||
imageBytes: imgBytes,
|
||||
imageType: imgType,
|
||||
imageSize: int64(len(imgBytes)),
|
||||
imageName: imageName,
|
||||
}, nil
|
||||
}
|
78
libgm/instructions.go
Normal file
78
libgm/instructions.go
Normal file
|
@ -0,0 +1,78 @@
|
|||
package textgapi
|
||||
|
||||
import (
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
|
||||
"go.mau.fi/mautrix-gmessages/libgm/binary"
|
||||
"go.mau.fi/mautrix-gmessages/libgm/crypto"
|
||||
)
|
||||
|
||||
const (
|
||||
ROUTING_OPCODE = 19
|
||||
MSG_TYPE_TWO = 2
|
||||
MSG_TYPE_SIXTEEN = 16
|
||||
|
||||
/*
|
||||
Session
|
||||
*/
|
||||
PREPARE_NEW_SESSION_OPCODE = 31
|
||||
NEW_SESSION_OPCODE = 16
|
||||
|
||||
/*
|
||||
Conversation
|
||||
*/
|
||||
LIST_CONVERSATIONS = 1
|
||||
SET_ACTIVE_CONVERSATION = 22
|
||||
OPEN_CONVERSATION = 21
|
||||
FETCH_MESSAGES_CONVERSATION = 2
|
||||
SEND_TEXT_MESSAGE = 3
|
||||
)
|
||||
|
||||
type Instruction struct {
|
||||
cryptor *crypto.Cryptor
|
||||
RoutingOpCode int64
|
||||
Opcode int64
|
||||
MsgType int64
|
||||
EncryptedData []byte
|
||||
DecryptedProtoMessage proto.Message
|
||||
ExpectedResponses int64 // count expected responses
|
||||
ProcessResponses func(responses []*Response) (interface{}, error) // function that decodes & decrypts the slice into appropriate response
|
||||
}
|
||||
|
||||
func (c *Client) EncryptPayloadData(message protoreflect.Message) ([]byte, error) {
|
||||
protoBytes, err1 := binary.EncodeProtoMessage(message.Interface())
|
||||
if err1 != nil {
|
||||
return nil, err1
|
||||
}
|
||||
encryptedBytes, err := c.cryptor.Encrypt(protoBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return encryptedBytes, nil
|
||||
}
|
||||
|
||||
type Instructions struct {
|
||||
data map[int64]*Instruction
|
||||
}
|
||||
|
||||
func NewInstructions(cryptor *crypto.Cryptor) *Instructions {
|
||||
return &Instructions{
|
||||
data: map[int64]*Instruction{
|
||||
PREPARE_NEW_SESSION_OPCODE: {cryptor, ROUTING_OPCODE, PREPARE_NEW_SESSION_OPCODE, MSG_TYPE_TWO, nil, &binary.PrepareNewSession{}, 1, nil},
|
||||
NEW_SESSION_OPCODE: {cryptor, ROUTING_OPCODE, NEW_SESSION_OPCODE, MSG_TYPE_TWO, nil, &binary.NewSession{}, 2, nil}, // create new session
|
||||
LIST_CONVERSATIONS: {cryptor, ROUTING_OPCODE, LIST_CONVERSATIONS, MSG_TYPE_SIXTEEN, nil, &binary.Conversations{}, 1, nil}, // list conversations
|
||||
|
||||
//22: {cryptor,19,22,2,nil,nil}, // SET ACTIVE SESSION WINDOW
|
||||
OPEN_CONVERSATION: {cryptor, ROUTING_OPCODE, OPEN_CONVERSATION, MSG_TYPE_TWO, nil, nil, 2, nil}, // open conversation
|
||||
FETCH_MESSAGES_CONVERSATION: {cryptor, ROUTING_OPCODE, FETCH_MESSAGES_CONVERSATION, MSG_TYPE_TWO, nil, &binary.FetchMessagesResponse{}, 1, nil}, // fetch messages in convo
|
||||
SEND_TEXT_MESSAGE: {cryptor, ROUTING_OPCODE, SEND_TEXT_MESSAGE, MSG_TYPE_TWO, nil, &binary.SendMessageResponse{}, 1, nil},
|
||||
//3: {cryptor,19,3,2,nil,&binary.SendMessageResponse{}}, // send text message
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (i *Instructions) GetInstruction(key int64) (*Instruction, bool) {
|
||||
instruction, ok := i.data[key]
|
||||
return instruction, ok
|
||||
}
|
53
libgm/json_proto/deseralize.go
Normal file
53
libgm/json_proto/deseralize.go
Normal file
|
@ -0,0 +1,53 @@
|
|||
package json_proto
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
)
|
||||
|
||||
func Deserialize(data []interface{}, m protoreflect.Message) error {
|
||||
for i := 0; i < m.Descriptor().Fields().Len(); i++ {
|
||||
fieldDescriptor := m.Descriptor().Fields().Get(i)
|
||||
index := int(fieldDescriptor.Number()) - 1
|
||||
if index < 0 || index >= len(data) || data[index] == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
val := data[index]
|
||||
|
||||
switch fieldDescriptor.Kind() {
|
||||
case protoreflect.MessageKind:
|
||||
nestedData, ok := val.([]interface{})
|
||||
if !ok {
|
||||
return fmt.Errorf("expected slice, got %T", val)
|
||||
}
|
||||
nestedMessage := m.NewField(fieldDescriptor).Message()
|
||||
if err := Deserialize(nestedData, nestedMessage); err != nil {
|
||||
return err
|
||||
}
|
||||
m.Set(fieldDescriptor, protoreflect.ValueOfMessage(nestedMessage))
|
||||
case protoreflect.BytesKind:
|
||||
bytes, ok := val.([]byte)
|
||||
if !ok {
|
||||
return fmt.Errorf("expected bytes, got %T", val)
|
||||
}
|
||||
m.Set(fieldDescriptor, protoreflect.ValueOfBytes(bytes))
|
||||
case protoreflect.Int32Kind, protoreflect.Int64Kind:
|
||||
num, ok := val.(float64)
|
||||
if !ok {
|
||||
return fmt.Errorf("expected number, got %T", val)
|
||||
}
|
||||
m.Set(fieldDescriptor, protoreflect.ValueOf(int64(num)))
|
||||
case protoreflect.StringKind:
|
||||
str, ok := val.(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("expected string, got %T", val)
|
||||
}
|
||||
m.Set(fieldDescriptor, protoreflect.ValueOf(str))
|
||||
default:
|
||||
// ignore fields of other types
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
100
libgm/json_proto/serialize.go
Normal file
100
libgm/json_proto/serialize.go
Normal file
|
@ -0,0 +1,100 @@
|
|||
package json_proto
|
||||
|
||||
/*
|
||||
in protobuf, a message looks like this:
|
||||
|
||||
message SomeMessage {
|
||||
string stringField1 = 1;
|
||||
int64 intField = 6;
|
||||
bytes byteField = 9;
|
||||
}
|
||||
|
||||
but when this function is done serializing this protobuf message into a slice, it should look something like this:
|
||||
|
||||
[
|
||||
"someString",
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
6,
|
||||
nil,
|
||||
nil,
|
||||
"\x9\x91\x942"
|
||||
]
|
||||
|
||||
Any integer should be translated into int64, it doesn't matter if it's defined as int32 in the proto schema.
|
||||
In the finished serialized slice it should be int64.
|
||||
Let's also take in count where there is a message nested inside a message:
|
||||
message SomeMessage {
|
||||
string stringField1 = 1;
|
||||
NestedMessage1 nestedMessage1 = 2;
|
||||
int64 intField = 6;
|
||||
bytes byteField = 9;
|
||||
}
|
||||
|
||||
message NestedMessage1 {
|
||||
string msg1 = 1;
|
||||
}
|
||||
|
||||
Then the serialized output would be:
|
||||
[
|
||||
"someString",
|
||||
["msg1FieldValue"],
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
6,
|
||||
nil,
|
||||
nil,
|
||||
"\x9\x91\x942"
|
||||
]
|
||||
This means that any slice inside of the current slice, indicates another message nested inside of it.
|
||||
*/
|
||||
|
||||
import (
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
)
|
||||
|
||||
func Serialize(m protoreflect.Message) ([]interface{}, error) {
|
||||
maxFieldNumber := 0
|
||||
for i := 0; i < m.Descriptor().Fields().Len(); i++ {
|
||||
fieldNumber := int(m.Descriptor().Fields().Get(i).Number())
|
||||
if fieldNumber > maxFieldNumber {
|
||||
maxFieldNumber = fieldNumber
|
||||
}
|
||||
}
|
||||
|
||||
serialized := make([]interface{}, maxFieldNumber)
|
||||
for i := 0; i < m.Descriptor().Fields().Len(); i++ {
|
||||
fieldDescriptor := m.Descriptor().Fields().Get(i)
|
||||
fieldValue := m.Get(fieldDescriptor)
|
||||
fieldNumber := int(fieldDescriptor.Number())
|
||||
switch fieldDescriptor.Kind() {
|
||||
case protoreflect.MessageKind:
|
||||
if m.Has(fieldDescriptor) {
|
||||
serializedMsg, err := Serialize(fieldValue.Message().Interface().ProtoReflect())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
serialized[fieldNumber-1] = serializedMsg
|
||||
}
|
||||
case protoreflect.BytesKind:
|
||||
if m.Has(fieldDescriptor) {
|
||||
serialized[fieldNumber-1] = fieldValue.Bytes()
|
||||
}
|
||||
case protoreflect.Int32Kind, protoreflect.Int64Kind:
|
||||
if m.Has(fieldDescriptor) {
|
||||
serialized[fieldNumber-1] = fieldValue.Int()
|
||||
}
|
||||
case protoreflect.StringKind:
|
||||
if m.Has(fieldDescriptor) {
|
||||
serialized[fieldNumber-1] = fieldValue.String()
|
||||
}
|
||||
default:
|
||||
// ignore fields of other types
|
||||
}
|
||||
}
|
||||
|
||||
return serialized, nil
|
||||
}
|
166
libgm/media_processor.go
Normal file
166
libgm/media_processor.go
Normal file
|
@ -0,0 +1,166 @@
|
|||
package textgapi
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"go.mau.fi/mautrix-gmessages/libgm/binary"
|
||||
"go.mau.fi/mautrix-gmessages/libgm/crypto"
|
||||
"go.mau.fi/mautrix-gmessages/libgm/util"
|
||||
)
|
||||
|
||||
type StartGoogleUpload struct {
|
||||
UploadId string
|
||||
UploadUrl string
|
||||
UploadStatus string
|
||||
ChunkGranularity int64
|
||||
ControlUrl string
|
||||
|
||||
Image *Image
|
||||
EncryptedMediaBytes []byte
|
||||
}
|
||||
|
||||
type MediaUpload struct {
|
||||
MediaId string
|
||||
MediaNumber int64
|
||||
Image *Image
|
||||
}
|
||||
|
||||
var (
|
||||
errStartUploadMedia = errors.New("failed to start uploading media")
|
||||
errFinalizeUploadMedia = errors.New("failed to finalize uploading media")
|
||||
)
|
||||
|
||||
func (c *Client) FinalizeUploadMedia(upload *StartGoogleUpload) (*MediaUpload, error) {
|
||||
imageType := upload.Image.GetImageType()
|
||||
encryptedImageSize := strconv.Itoa(len(upload.EncryptedMediaBytes))
|
||||
|
||||
log.Println("EncryptedImageSize:", encryptedImageSize)
|
||||
finalizeUploadHeaders := util.NewMediaUploadHeaders(encryptedImageSize, "upload, finalize", "0", imageType.Format, "")
|
||||
req, reqErr := http.NewRequest("POST", upload.UploadUrl, bytes.NewBuffer(upload.EncryptedMediaBytes))
|
||||
if reqErr != nil {
|
||||
return nil, reqErr
|
||||
}
|
||||
|
||||
req.Header = *finalizeUploadHeaders
|
||||
|
||||
res, resErr := c.http.Do(req)
|
||||
if resErr != nil {
|
||||
log.Fatal(resErr)
|
||||
}
|
||||
|
||||
statusCode := res.StatusCode
|
||||
if statusCode != 200 {
|
||||
return nil, errFinalizeUploadMedia
|
||||
}
|
||||
|
||||
defer res.Body.Close()
|
||||
|
||||
rHeaders := res.Header
|
||||
googleResponse, err3 := io.ReadAll(res.Body)
|
||||
if err3 != nil {
|
||||
return nil, err3
|
||||
}
|
||||
|
||||
uploadStatus := rHeaders.Get("x-goog-upload-status")
|
||||
log.Println("Upload Status: ", uploadStatus)
|
||||
|
||||
mediaIds := &binary.UploadMediaResponse{}
|
||||
err3 = crypto.DecodeAndEncodeB64(string(googleResponse), mediaIds)
|
||||
if err3 != nil {
|
||||
return nil, err3
|
||||
}
|
||||
return &MediaUpload{
|
||||
MediaId: mediaIds.Media.MediaId,
|
||||
MediaNumber: mediaIds.Media.MediaNumber,
|
||||
Image: upload.Image,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *Client) StartUploadMedia(image *Image) (*StartGoogleUpload, error) {
|
||||
imageType := image.GetImageType()
|
||||
|
||||
encryptedImageBytes, encryptErr := image.GetEncryptedBytes()
|
||||
if encryptErr != nil {
|
||||
return nil, encryptErr
|
||||
}
|
||||
encryptedImageSize := strconv.Itoa(len(encryptedImageBytes))
|
||||
|
||||
startUploadHeaders := util.NewMediaUploadHeaders(encryptedImageSize, "start", "", imageType.Format, "resumable")
|
||||
startUploadPayload, buildPayloadErr := c.buildStartUploadPayload()
|
||||
if buildPayloadErr != nil {
|
||||
return nil, buildPayloadErr
|
||||
}
|
||||
|
||||
req, reqErr := http.NewRequest("POST", util.UPLOAD_MEDIA, bytes.NewBuffer([]byte(startUploadPayload)))
|
||||
if reqErr != nil {
|
||||
return nil, reqErr
|
||||
}
|
||||
|
||||
req.Header = *startUploadHeaders
|
||||
|
||||
res, resErr := c.http.Do(req)
|
||||
if resErr != nil {
|
||||
log.Fatal(resErr)
|
||||
}
|
||||
|
||||
statusCode := res.StatusCode
|
||||
if statusCode != 200 {
|
||||
return nil, errStartUploadMedia
|
||||
}
|
||||
|
||||
rHeaders := res.Header
|
||||
|
||||
chunkGranularity, convertErr := strconv.Atoi(rHeaders.Get("x-goog-upload-chunk-granularity"))
|
||||
if convertErr != nil {
|
||||
return nil, convertErr
|
||||
}
|
||||
|
||||
uploadResponse := &StartGoogleUpload{
|
||||
UploadId: rHeaders.Get("x-guploader-uploadid"),
|
||||
UploadUrl: rHeaders.Get("x-goog-upload-url"),
|
||||
UploadStatus: rHeaders.Get("x-goog-upload-status"),
|
||||
ChunkGranularity: int64(chunkGranularity),
|
||||
ControlUrl: rHeaders.Get("x-goog-upload-control-url"),
|
||||
|
||||
Image: image,
|
||||
EncryptedMediaBytes: encryptedImageBytes,
|
||||
}
|
||||
return uploadResponse, nil
|
||||
}
|
||||
|
||||
func (c *Client) buildStartUploadPayload() (string, error) {
|
||||
|
||||
decodedRpcKey, err := crypto.Base64DecodeStandard(c.rpcKey)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
requestId := util.RandomUUIDv4()
|
||||
protoData := &binary.StartMediaUploadPayload{
|
||||
ImageType: 1,
|
||||
AuthData: &binary.AuthMessageBytes{
|
||||
RequestId: requestId,
|
||||
RpcKey: decodedRpcKey,
|
||||
Date: &binary.Date{
|
||||
Year: 2023,
|
||||
Seq1: 6,
|
||||
Seq2: 8,
|
||||
Seq3: 4,
|
||||
Seq4: 6,
|
||||
},
|
||||
},
|
||||
Mobile: c.devicePair.Mobile,
|
||||
}
|
||||
|
||||
protoDataEncoded, protoEncodeErr := crypto.EncodeProtoB64(protoData)
|
||||
if protoEncodeErr != nil {
|
||||
return "", protoEncodeErr
|
||||
}
|
||||
|
||||
return protoDataEncoded, nil
|
||||
}
|
174
libgm/message_builder.go
Normal file
174
libgm/message_builder.go
Normal file
|
@ -0,0 +1,174 @@
|
|||
package textgapi
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
|
||||
"go.mau.fi/mautrix-gmessages/libgm/binary"
|
||||
"go.mau.fi/mautrix-gmessages/libgm/util"
|
||||
)
|
||||
|
||||
var (
|
||||
errContentNotSet = errors.New("failed to build MessageBuilder: content must be larger than length 0")
|
||||
errConversationIdNotSet = errors.New("failed to build MessageBuilder: conversationId is empty")
|
||||
errSelfParticipantIdNotSet = errors.New("failed to build MessageBuilder: selfParticipantId is empty")
|
||||
)
|
||||
|
||||
type MessageBuilder struct {
|
||||
client *Client
|
||||
|
||||
content string
|
||||
conversationId string
|
||||
tmpId string
|
||||
selfParticipantId string
|
||||
|
||||
images []*MediaUpload
|
||||
|
||||
err error
|
||||
}
|
||||
|
||||
// Add this method to retrieve the stored error
|
||||
func (mb *MessageBuilder) Err() error {
|
||||
return mb.err
|
||||
}
|
||||
|
||||
func (mb *MessageBuilder) GetImages() []*MediaUpload {
|
||||
return mb.images
|
||||
}
|
||||
|
||||
func (mb *MessageBuilder) GetContent() string {
|
||||
return mb.content
|
||||
}
|
||||
|
||||
func (mb *MessageBuilder) SetContent(content string) *MessageBuilder {
|
||||
mb.content = content
|
||||
return mb
|
||||
}
|
||||
|
||||
func (mb *MessageBuilder) GetConversationId() string {
|
||||
return mb.conversationId
|
||||
}
|
||||
|
||||
func (mb *MessageBuilder) SetConversationId(conversationId string) *MessageBuilder {
|
||||
mb.conversationId = conversationId
|
||||
return mb
|
||||
}
|
||||
|
||||
func (mb *MessageBuilder) GetSelfParticipantId() string {
|
||||
return mb.selfParticipantId
|
||||
}
|
||||
|
||||
// sendmessage function will set this automatically but if u want to set it yourself feel free
|
||||
func (mb *MessageBuilder) SetSelfParticipantId(participantId string) *MessageBuilder {
|
||||
mb.selfParticipantId = participantId
|
||||
return mb
|
||||
}
|
||||
|
||||
func (mb *MessageBuilder) GetTmpId() string {
|
||||
return mb.tmpId
|
||||
}
|
||||
|
||||
// sendmessage function will set this automatically but if u want to set it yourself feel free
|
||||
func (mb *MessageBuilder) SetTmpId(tmpId string) *MessageBuilder {
|
||||
mb.tmpId = tmpId
|
||||
return mb
|
||||
}
|
||||
|
||||
func (mb *MessageBuilder) Build() (*binary.SendMessagePayload, error) {
|
||||
|
||||
if mb.conversationId == "" {
|
||||
return nil, errConversationIdNotSet
|
||||
}
|
||||
|
||||
if mb.selfParticipantId == "" {
|
||||
return nil, errSelfParticipantIdNotSet
|
||||
}
|
||||
|
||||
if mb.content == "" {
|
||||
return nil, errContentNotSet
|
||||
}
|
||||
|
||||
if mb.tmpId == "" {
|
||||
mb.tmpId = util.GenerateTmpId()
|
||||
}
|
||||
|
||||
return mb.newSendConversationMessage(), nil
|
||||
}
|
||||
|
||||
func (c *Client) NewMessageBuilder() *MessageBuilder {
|
||||
mb := &MessageBuilder{
|
||||
client: c,
|
||||
}
|
||||
|
||||
tmpId := util.GenerateTmpId()
|
||||
mb.SetTmpId(tmpId)
|
||||
|
||||
return mb
|
||||
}
|
||||
|
||||
func (mb *MessageBuilder) newSendConversationMessage() *binary.SendMessagePayload {
|
||||
|
||||
convId := mb.GetConversationId()
|
||||
content := mb.GetContent()
|
||||
selfParticipantId := mb.GetSelfParticipantId()
|
||||
tmpId := mb.GetTmpId()
|
||||
|
||||
messageInfo := make([]*binary.MessageInfo, 0)
|
||||
messageInfo = append(messageInfo, &binary.MessageInfo{Data: &binary.MessageInfo_MessageContent{
|
||||
MessageContent: &binary.MessageContent{
|
||||
Content: content,
|
||||
},
|
||||
}})
|
||||
|
||||
mb.appendImagesPayload(&messageInfo)
|
||||
|
||||
sendMsgPayload := &binary.SendMessagePayload{
|
||||
ConversationId: convId,
|
||||
MessagePayload: &binary.MessagePayload{
|
||||
TmpId: tmpId,
|
||||
ConversationId: convId,
|
||||
SelfParticipantId: selfParticipantId,
|
||||
MessageInfo: messageInfo,
|
||||
TmpId2: tmpId,
|
||||
},
|
||||
TmpId: tmpId,
|
||||
}
|
||||
if len(content) > 0 {
|
||||
sendMsgPayload.MessagePayload.MessagePayloadContent = &binary.MessagePayloadContent{
|
||||
MessageContent: &binary.MessageContent{
|
||||
Content: content,
|
||||
},
|
||||
}
|
||||
}
|
||||
mb.client.Logger.Debug().Any("sendMsgPayload", sendMsgPayload).Msg("sendMessagePayload")
|
||||
|
||||
return sendMsgPayload
|
||||
}
|
||||
|
||||
func (mb *MessageBuilder) appendImagesPayload(messageInfo *[]*binary.MessageInfo) {
|
||||
if len(mb.images) <= 0 {
|
||||
log.Println("0 images to append, ignoring")
|
||||
return
|
||||
}
|
||||
|
||||
for _, media := range mb.images {
|
||||
imgData := mb.newImageContent(media)
|
||||
*messageInfo = append(*messageInfo, imgData)
|
||||
}
|
||||
}
|
||||
|
||||
func (mb *MessageBuilder) newImageContent(media *MediaUpload) *binary.MessageInfo {
|
||||
imageMessage := &binary.MessageInfo{
|
||||
Data: &binary.MessageInfo_ImageContent{
|
||||
ImageContent: &binary.ImageContent{
|
||||
SomeNumber: media.Image.GetImageType().Type,
|
||||
ImageId: media.MediaId,
|
||||
ImageName: media.Image.GetImageName(),
|
||||
Size: media.Image.GetImageSize(),
|
||||
DecryptionKey: media.Image.GetImageCryptor().GetKey(),
|
||||
},
|
||||
},
|
||||
}
|
||||
mb.client.Logger.Debug().Any("imageMessage", imageMessage).Msg("New Image Content")
|
||||
return imageMessage
|
||||
}
|
25
libgm/misc.go
Normal file
25
libgm/misc.go
Normal file
|
@ -0,0 +1,25 @@
|
|||
package textgapi
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"go.mau.fi/mautrix-gmessages/libgm/builders"
|
||||
"go.mau.fi/mautrix-gmessages/libgm/util"
|
||||
)
|
||||
|
||||
type Misc struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
func (m *Misc) TenorSearch(searchOpts *builders.TenorSearch) (interface{}, error) {
|
||||
searchQuery, buildErr := searchOpts.Build()
|
||||
if buildErr != nil {
|
||||
return nil, buildErr
|
||||
}
|
||||
|
||||
uri := util.TENOR_SEARCH_GIF + searchQuery
|
||||
log.Println(uri)
|
||||
os.Exit(1)
|
||||
return nil, nil
|
||||
}
|
71
libgm/msg_handler.go
Normal file
71
libgm/msg_handler.go
Normal file
|
@ -0,0 +1,71 @@
|
|||
package textgapi
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"go.mau.fi/mautrix-gmessages/libgm/binary"
|
||||
"go.mau.fi/mautrix-gmessages/libgm/json_proto"
|
||||
)
|
||||
|
||||
func (r *RPC) HandleRPCMsg(msgArr []interface{}) {
|
||||
/*
|
||||
if data[0] == 44 { // ','
|
||||
data = data[1:]
|
||||
}
|
||||
|
||||
var msgArr []interface{}
|
||||
err := r.tryUnmarshalJSON(data, &msgArr)
|
||||
if err != nil {
|
||||
r.client.Logger.Error().Err(fmt.Errorf("got invalid json string %s", string(data))).Msg("rpc msg err")
|
||||
r.HandleByLength(data)
|
||||
return
|
||||
}
|
||||
*/
|
||||
response := &binary.RPCResponse{}
|
||||
deserializeErr := json_proto.Deserialize(msgArr, response.ProtoReflect())
|
||||
if deserializeErr != nil {
|
||||
r.client.Logger.Error().Err(fmt.Errorf("failed to deserialize response %s", msgArr)).Msg("rpc deserialize msg err")
|
||||
return
|
||||
}
|
||||
//r.client.Logger.Debug().Any("byteLength", len(data)).Any("unmarshaled", response).Any("raw", string(data)).Msg("RPC Msg")
|
||||
if response.Data == nil {
|
||||
r.client.Logger.Error().Err(fmt.Errorf("Response data was nil %s", msgArr)).Msg("rpc msg data err")
|
||||
return
|
||||
}
|
||||
if response.Data.RoutingOpCode == 19 {
|
||||
parsedResponse, failedParse := r.client.sessionHandler.NewResponse(response)
|
||||
if failedParse != nil {
|
||||
log.Fatal(failedParse)
|
||||
}
|
||||
//hasBody := parsedResponse.Data.EncryptedData == nil
|
||||
//r.client.Logger.Info().Any("msgData", parsedResponse).Msg("Got event!")
|
||||
r.client.sessionHandler.addResponseAck(parsedResponse.ResponseId)
|
||||
_, waitingForResponse := r.client.sessionHandler.requests[parsedResponse.Data.RequestId]
|
||||
//log.Println(fmt.Sprintf("%v %v %v %v %v %v %v", parsedResponse.RoutingOpCode, parsedResponse.Data.Opcode, parsedResponse.Data.Sub, parsedResponse.Data.Third, parsedResponse.Data.Field9, hasBody, waitingForResponse))
|
||||
//r.client.Logger.Debug().Any("waitingForResponse?", waitingForResponse).Msg("Got rpc response from server")
|
||||
if parsedResponse.Data.Opcode == 16 || waitingForResponse {
|
||||
if waitingForResponse {
|
||||
r.client.sessionHandler.respondToRequestChannel(parsedResponse)
|
||||
return
|
||||
}
|
||||
if parsedResponse.Data.Opcode == 16 {
|
||||
r.client.handleEventOpCode(parsedResponse)
|
||||
}
|
||||
} else {
|
||||
|
||||
}
|
||||
} else {
|
||||
r.client.handleSeperateOpCode(response.Data)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *RPC) tryUnmarshalJSON(jsonData []byte, msgArr *[]interface{}) error {
|
||||
err := json.Unmarshal(jsonData, &msgArr)
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *RPC) HandleByLength(data []byte) {
|
||||
r.client.Logger.Debug().Any("byteLength", len(data)).Any("corrupt raw", string(data)).Msg("RPC Corrupt json")
|
||||
}
|
39
libgm/opcode_handler.go
Normal file
39
libgm/opcode_handler.go
Normal file
|
@ -0,0 +1,39 @@
|
|||
package textgapi
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"go.mau.fi/mautrix-gmessages/libgm/binary"
|
||||
"go.mau.fi/mautrix-gmessages/libgm/crypto"
|
||||
)
|
||||
|
||||
func (c *Client) handleSeperateOpCode(msgData *binary.MessageData) {
|
||||
decodedBytes, err := crypto.Base64DecodeStandard(msgData.EncodedData)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
switch msgData.RoutingOpCode {
|
||||
case 14: // paired successful
|
||||
decodedData := &binary.Container{}
|
||||
err = binary.DecodeProtoMessage(decodedBytes, decodedData)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
c.Logger.Debug().Any("data", decodedData).Msg("Paired device decoded data")
|
||||
c.pairer.pairCallback(decodedData)
|
||||
default:
|
||||
decodedData := &binary.EncodedResponse{}
|
||||
err = binary.DecodeProtoMessage(decodedBytes, decodedData)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if (decodedData.Sub && decodedData.Third != 0) && decodedData.EncryptedData != nil {
|
||||
bugleData := &binary.BugleBackendService{}
|
||||
err = c.cryptor.DecryptAndDecodeData(decodedData.EncryptedData, bugleData)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
c.handleBugleOpCode(bugleData)
|
||||
}
|
||||
}
|
||||
}
|
161
libgm/pair.go
Normal file
161
libgm/pair.go
Normal file
|
@ -0,0 +1,161 @@
|
|||
package textgapi
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"go.mau.fi/mautrix-gmessages/libgm/binary"
|
||||
"go.mau.fi/mautrix-gmessages/libgm/crypto"
|
||||
"go.mau.fi/mautrix-gmessages/libgm/payload"
|
||||
"go.mau.fi/mautrix-gmessages/libgm/util"
|
||||
)
|
||||
|
||||
type Pairer struct {
|
||||
client *Client
|
||||
KeyData *crypto.JWK
|
||||
ticker *time.Ticker
|
||||
tickerTime time.Duration
|
||||
qrCodePx int
|
||||
pairingKey []byte
|
||||
}
|
||||
|
||||
/*
|
||||
refreshQrCodeTime is the interval to refresh the qr code in seconds, this is usually 20 seconds.
|
||||
*/
|
||||
func (c *Client) NewPairer(keyData *crypto.JWK, refreshQrCodeTime int) (*Pairer, error) {
|
||||
if keyData == nil {
|
||||
var err error
|
||||
keyData, err = crypto.GenerateECDSA_P256_JWK()
|
||||
if err != nil {
|
||||
c.Logger.Error().Any("data", keyData).Msg(err.Error())
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
p := &Pairer{
|
||||
client: c,
|
||||
KeyData: keyData,
|
||||
qrCodePx: 214,
|
||||
tickerTime: time.Duration(refreshQrCodeTime) * time.Second,
|
||||
}
|
||||
c.pairer = p
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func (p *Pairer) SetQRCodePx(pixels int) {
|
||||
p.qrCodePx = pixels
|
||||
}
|
||||
|
||||
func (p *Pairer) RegisterPhoneRelay() (*binary.RegisterPhoneRelayResponse, error) {
|
||||
body, _, err := payload.RegisterPhoneRelay(p.KeyData)
|
||||
if err != nil {
|
||||
p.client.Logger.Err(err)
|
||||
return &binary.RegisterPhoneRelayResponse{}, err
|
||||
}
|
||||
//p.client.Logger.Debug().Any("keyByteLength", len(jsonPayload.EcdsaKeysContainer.EcdsaKeys.EncryptedKeys)).Any("json", jsonPayload).Any("base64", body).Msg("RegisterPhoneRelay Payload")
|
||||
relayResponse, reqErr := p.client.MakeRelayRequest(util.REGISTER_PHONE_RELAY, body)
|
||||
if reqErr != nil {
|
||||
p.client.Logger.Err(reqErr)
|
||||
return nil, err
|
||||
}
|
||||
responseBody, err2 := io.ReadAll(relayResponse.Body)
|
||||
if err2 != nil {
|
||||
return nil, err2
|
||||
}
|
||||
relayResponse.Body.Close()
|
||||
res := &binary.RegisterPhoneRelayResponse{}
|
||||
err3 := binary.DecodeProtoMessage(responseBody, res)
|
||||
if err3 != nil {
|
||||
return nil, err3
|
||||
}
|
||||
p.pairingKey = res.GetPairingKey()
|
||||
qrCode, qrErr := p.GenerateQRCode(p.qrCodePx)
|
||||
if qrErr != nil {
|
||||
return nil, qrErr
|
||||
}
|
||||
p.client.triggerEvent(qrCode)
|
||||
p.startRefreshRelayTask()
|
||||
return res, err
|
||||
}
|
||||
|
||||
func (p *Pairer) startRefreshRelayTask() {
|
||||
if p.ticker != nil {
|
||||
p.ticker.Stop()
|
||||
}
|
||||
ticker := time.NewTicker(30 * time.Second)
|
||||
p.ticker = ticker
|
||||
go func() {
|
||||
for range ticker.C {
|
||||
p.RefreshPhoneRelay()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (p *Pairer) RefreshPhoneRelay() {
|
||||
body, _, err := payload.RefreshPhoneRelay(p.client.rpcKey)
|
||||
if err != nil {
|
||||
p.client.Logger.Err(err).Msg("refresh phone relay err")
|
||||
return
|
||||
}
|
||||
//p.client.Logger.Debug().Any("keyByteLength", len(jsonPayload.PhoneRelay.RpcKey)).Any("json", jsonPayload).Any("base64", body).Msg("RefreshPhoneRelay Payload")
|
||||
relayResponse, reqErr := p.client.MakeRelayRequest(util.REFRESH_PHONE_RELAY, body)
|
||||
if reqErr != nil {
|
||||
p.client.Logger.Err(reqErr).Msg("refresh phone relay err")
|
||||
}
|
||||
responseBody, err2 := io.ReadAll(relayResponse.Body)
|
||||
defer relayResponse.Body.Close()
|
||||
if err2 != nil {
|
||||
p.client.Logger.Err(err2).Msg("refresh phone relay err")
|
||||
}
|
||||
p.client.Logger.Debug().Any("responseLength", len(responseBody)).Msg("Response Body Length")
|
||||
res := &binary.RefreshPhoneRelayResponse{}
|
||||
err3 := binary.DecodeProtoMessage(responseBody, res)
|
||||
if err3 != nil {
|
||||
p.client.Logger.Err(err3)
|
||||
}
|
||||
p.pairingKey = res.GetPairKey()
|
||||
p.client.Logger.Debug().Any("res", res).Msg("RefreshPhoneRelayResponse")
|
||||
qrCode, qrErr := p.GenerateQRCode(p.qrCodePx)
|
||||
if qrErr != nil {
|
||||
log.Fatal(qrErr)
|
||||
}
|
||||
p.client.triggerEvent(qrCode)
|
||||
}
|
||||
|
||||
func (p *Pairer) GetWebEncryptionKey() {
|
||||
body, _, err2 := payload.GetWebEncryptionKey(p.client.rpc.webAuthKey)
|
||||
if err2 != nil {
|
||||
p.client.Logger.Err(err2).Msg("web encryption key err")
|
||||
return
|
||||
}
|
||||
//p.client.Logger.Debug().Any("keyByteLength", len(rawData.PhoneRelay.RpcKey)).Any("json", rawData).Any("base64", body).Msg("GetWebEncryptionKey Payload")
|
||||
webKeyResponse, reqErr := p.client.MakeRelayRequest(util.GET_WEB_ENCRYPTION_KEY, body)
|
||||
if reqErr != nil {
|
||||
p.client.Logger.Err(reqErr).Msg("Web encryption key request err")
|
||||
}
|
||||
responseBody, err2 := io.ReadAll(webKeyResponse.Body)
|
||||
defer webKeyResponse.Body.Close()
|
||||
if err2 != nil {
|
||||
p.client.Logger.Err(err2).Msg("Web encryption key read response err")
|
||||
return
|
||||
}
|
||||
//p.client.Logger.Debug().Any("responseLength", len(responseBody)).Any("raw", responseBody).Msg("Response Body Length")
|
||||
parsedResponse := &binary.WebEncryptionKeyResponse{}
|
||||
err2 = binary.DecodeProtoMessage(responseBody, parsedResponse)
|
||||
if err2 != nil {
|
||||
p.client.Logger.Err(err2).Msg("Parse webkeyresponse into proto struct error")
|
||||
}
|
||||
key := crypto.EncodeBase64Standard(p.client.rpc.webAuthKey)
|
||||
p.ticker.Stop()
|
||||
reconnectErr := p.client.Reconnect(key)
|
||||
if reconnectErr != nil {
|
||||
log.Fatal(reconnectErr)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Pairer) pairCallback(pairData *binary.Container) {
|
||||
p.client.rpc.webAuthKey = pairData.PairDeviceData.WebAuthKeyData.WebAuthKey
|
||||
p.client.ttl = pairData.PairDeviceData.WebAuthKeyData.ValidFor
|
||||
p.client.devicePair = &DevicePair{Mobile: pairData.PairDeviceData.Mobile, Browser: pairData.PairDeviceData.Browser}
|
||||
p.client.pairer.GetWebEncryptionKey()
|
||||
}
|
1
libgm/payload/conversations.go
Normal file
1
libgm/payload/conversations.go
Normal file
|
@ -0,0 +1 @@
|
|||
package payload
|
31
libgm/payload/getWebEncryptionKey.go
Normal file
31
libgm/payload/getWebEncryptionKey.go
Normal file
|
@ -0,0 +1,31 @@
|
|||
package payload
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"go.mau.fi/mautrix-gmessages/libgm/binary"
|
||||
"go.mau.fi/mautrix-gmessages/libgm/util"
|
||||
)
|
||||
|
||||
func GetWebEncryptionKey(WebPairKey []byte) ([]byte, *binary.Container, error) {
|
||||
log.Println(WebPairKey)
|
||||
id := util.RandomUUIDv4()
|
||||
payload := &binary.Container{
|
||||
PhoneRelay: &binary.PhoneRelayBody{
|
||||
Id: id,
|
||||
RpcKey: WebPairKey,
|
||||
Date: &binary.Date{
|
||||
Year: 2023,
|
||||
Seq1: 6,
|
||||
Seq2: 8,
|
||||
Seq3: 4,
|
||||
Seq4: 6,
|
||||
},
|
||||
},
|
||||
}
|
||||
encodedPayload, err2 := binary.EncodeProtoMessage(payload)
|
||||
if err2 != nil {
|
||||
return nil, payload, err2
|
||||
}
|
||||
return encodedPayload, payload, nil
|
||||
}
|
44
libgm/payload/receiveMessages.go
Normal file
44
libgm/payload/receiveMessages.go
Normal file
|
@ -0,0 +1,44 @@
|
|||
package payload
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"go.mau.fi/mautrix-gmessages/libgm/util"
|
||||
)
|
||||
|
||||
func ReceiveMessages(rpcKey string) ([]byte, string, error) {
|
||||
id := util.RandomUUIDv4()
|
||||
data := []interface{}{
|
||||
[]interface{}{
|
||||
id,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
rpcKey,
|
||||
[]interface{}{
|
||||
nil,
|
||||
nil,
|
||||
2023,
|
||||
6,
|
||||
8,
|
||||
nil,
|
||||
4,
|
||||
nil,
|
||||
6,
|
||||
},
|
||||
},
|
||||
nil,
|
||||
nil,
|
||||
[]interface{}{
|
||||
nil,
|
||||
[]interface{}{},
|
||||
},
|
||||
}
|
||||
|
||||
jsonData, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return jsonData, id, nil
|
||||
}
|
33
libgm/payload/refreshPhoneRelay.go
Normal file
33
libgm/payload/refreshPhoneRelay.go
Normal file
|
@ -0,0 +1,33 @@
|
|||
package payload
|
||||
|
||||
import (
|
||||
"go.mau.fi/mautrix-gmessages/libgm/binary"
|
||||
"go.mau.fi/mautrix-gmessages/libgm/crypto"
|
||||
"go.mau.fi/mautrix-gmessages/libgm/util"
|
||||
)
|
||||
|
||||
func RefreshPhoneRelay(rpcKey string) ([]byte, *binary.Container, error) {
|
||||
decodedRpcKey, err1 := crypto.Base64DecodeStandard(rpcKey)
|
||||
if err1 != nil {
|
||||
return nil, nil, err1
|
||||
}
|
||||
payload := &binary.Container{
|
||||
PhoneRelay: &binary.PhoneRelayBody{
|
||||
Id: util.RandomUUIDv4(),
|
||||
Bugle: "Bugle",
|
||||
RpcKey: decodedRpcKey,
|
||||
Date: &binary.Date{
|
||||
Year: 2023,
|
||||
Seq1: 6,
|
||||
Seq2: 8,
|
||||
Seq3: 4,
|
||||
Seq4: 6,
|
||||
},
|
||||
},
|
||||
}
|
||||
encodedPayload, err2 := binary.EncodeProtoMessage(payload)
|
||||
if err2 != nil {
|
||||
return nil, payload, err2
|
||||
}
|
||||
return encodedPayload, payload, nil
|
||||
}
|
63
libgm/payload/registerPhoneRelay.go
Normal file
63
libgm/payload/registerPhoneRelay.go
Normal file
|
@ -0,0 +1,63 @@
|
|||
package payload
|
||||
|
||||
import (
|
||||
"go.mau.fi/mautrix-gmessages/libgm/binary"
|
||||
"go.mau.fi/mautrix-gmessages/libgm/crypto"
|
||||
"go.mau.fi/mautrix-gmessages/libgm/util"
|
||||
)
|
||||
|
||||
func RegisterPhoneRelay(jwk *crypto.JWK) ([]byte, *binary.Container, error) {
|
||||
id := util.RandomUUIDv4()
|
||||
decodedPrivateKey, err2 := jwk.PrivKeyB64Bytes()
|
||||
if err2 != nil {
|
||||
return nil, nil, err2
|
||||
}
|
||||
jwk.PrivateBytes = decodedPrivateKey
|
||||
uncompressedPublicKey, err3 := jwk.UncompressPubKey()
|
||||
if err3 != nil {
|
||||
return nil, nil, err3
|
||||
}
|
||||
var emptyByteArray []byte
|
||||
crypto.EncodeValues(&emptyByteArray, crypto.SequenceOne)
|
||||
crypto.EncodeValues(&emptyByteArray, crypto.SequenceTwo)
|
||||
|
||||
var copiedByteArray []byte
|
||||
copiedByteArray = crypto.AppendByteSequence(copiedByteArray, emptyByteArray, uncompressedPublicKey)
|
||||
for _, value := range uncompressedPublicKey {
|
||||
copiedByteArray = crypto.HelperAppendBytes(copiedByteArray, value)
|
||||
}
|
||||
|
||||
var emptyByteArray2 []byte
|
||||
emptyByteArray2 = crypto.AppendBytes(emptyByteArray2, copiedByteArray[0:])
|
||||
|
||||
payloadData := &binary.Container{
|
||||
PhoneRelay: &binary.PhoneRelayBody{
|
||||
Id: id,
|
||||
Bugle: "Bugle",
|
||||
Date: &binary.Date{
|
||||
Year: 2023,
|
||||
Seq1: 6,
|
||||
Seq2: 8,
|
||||
Seq3: 4,
|
||||
Seq4: 6,
|
||||
},
|
||||
},
|
||||
BrowserDetails: &binary.BrowserDetails{
|
||||
UserAgent: util.USER_AGENT,
|
||||
SomeInt: 2,
|
||||
SomeBool: true,
|
||||
Os: util.OS,
|
||||
},
|
||||
PairDeviceData: &binary.PairDeviceData{
|
||||
EcdsaKeys: &binary.ECDSAKeys{
|
||||
ProtoVersion: 2,
|
||||
EncryptedKeys: emptyByteArray2,
|
||||
},
|
||||
},
|
||||
}
|
||||
encoded, err4 := binary.EncodeProtoMessage(payloadData)
|
||||
if err4 != nil {
|
||||
return nil, payloadData, err4
|
||||
}
|
||||
return encoded, payloadData, nil
|
||||
}
|
42
libgm/payload/sendMessage.go
Normal file
42
libgm/payload/sendMessage.go
Normal file
|
@ -0,0 +1,42 @@
|
|||
package payload
|
||||
|
||||
import "go.mau.fi/mautrix-gmessages/libgm/binary"
|
||||
|
||||
func NewMessageData(requestID string, encodedStr string, routingOpCode int64, msgType int64) *binary.MessageData {
|
||||
return &binary.MessageData{
|
||||
RequestId: requestID,
|
||||
RoutingOpCode: routingOpCode,
|
||||
EncodedData: encodedStr,
|
||||
MsgTypeArr: &binary.MsgTypeArr{
|
||||
EmptyArr: &binary.EmptyArr{},
|
||||
MsgType: msgType,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func NewEncodedPayload(requestId string, opCode int64, encryptedData []byte, sessionId string) *binary.EncodedPayload {
|
||||
return &binary.EncodedPayload{
|
||||
RequestId: requestId,
|
||||
Opcode: opCode,
|
||||
EncryptedData: encryptedData,
|
||||
SessionId: sessionId,
|
||||
}
|
||||
}
|
||||
|
||||
func NewAuthData(requestId string, rpcKey string, date *binary.Date) *binary.AuthMessage {
|
||||
return &binary.AuthMessage{
|
||||
RequestId: requestId,
|
||||
RpcKey: rpcKey,
|
||||
Date: date,
|
||||
}
|
||||
}
|
||||
|
||||
func NewSendMessage(pairedDevice *binary.Device, messageData *binary.MessageData, authData *binary.AuthMessage, ttl int64) *binary.SendMessage {
|
||||
return &binary.SendMessage{
|
||||
PairedDevice: pairedDevice,
|
||||
MessageData: messageData,
|
||||
AuthData: authData,
|
||||
Ttl: ttl,
|
||||
EmptyArr: &binary.EmptyArr{},
|
||||
}
|
||||
}
|
36
libgm/qr.go
Normal file
36
libgm/qr.go
Normal file
|
@ -0,0 +1,36 @@
|
|||
package textgapi
|
||||
|
||||
import (
|
||||
"go.mau.fi/mautrix-gmessages/libgm/binary"
|
||||
"go.mau.fi/mautrix-gmessages/libgm/crypto"
|
||||
"go.mau.fi/mautrix-gmessages/libgm/events"
|
||||
"go.mau.fi/mautrix-gmessages/libgm/util"
|
||||
|
||||
"github.com/skip2/go-qrcode"
|
||||
)
|
||||
|
||||
func (p *Pairer) GenerateQRCodeData() (string, error) {
|
||||
urlData := &binary.UrlData{
|
||||
PairingKey: p.pairingKey,
|
||||
AES_CTR_KEY_256: p.client.cryptor.AES_CTR_KEY_256,
|
||||
SHA_256_KEY: p.client.cryptor.SHA_256_KEY,
|
||||
}
|
||||
encodedUrlData, err := binary.EncodeProtoMessage(urlData)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
cData := crypto.Base64Encode(encodedUrlData)
|
||||
return util.QR_CODE_URL + cData, nil
|
||||
}
|
||||
|
||||
func (p *Pairer) GenerateQRCode(size int) (*events.QRCODE_UPDATED, error) {
|
||||
data, err1 := p.GenerateQRCodeData()
|
||||
if err1 != nil {
|
||||
return nil, err1
|
||||
}
|
||||
png, err2 := qrcode.Encode(data, qrcode.Highest, size)
|
||||
if err2 != nil {
|
||||
return nil, err2
|
||||
}
|
||||
return events.NewQrCodeUpdated(png, size, size, data), nil
|
||||
}
|
70
libgm/request.go
Normal file
70
libgm/request.go
Normal file
|
@ -0,0 +1,70 @@
|
|||
package textgapi
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net/http"
|
||||
"reflect"
|
||||
|
||||
"go.mau.fi/mautrix-gmessages/libgm/util"
|
||||
)
|
||||
|
||||
func (c *Client) PostRequest(url string, payload []byte, headers interface{}) (*http.Response, error) {
|
||||
req, err := http.NewRequest("POST", url, bytes.NewReader(payload))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
reqHeaders := &http.Header{}
|
||||
SetHeaders(reqHeaders, headers)
|
||||
req.Header = *reqHeaders
|
||||
//c.Logger.Info().Any("headers", req.Header).Msg("POST Request Headers")
|
||||
res, reqErr := c.http.Do(req)
|
||||
if reqErr != nil {
|
||||
return res, reqErr
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (c *Client) GetRequest(url string, headers interface{}) (*http.Response, error) {
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
reqHeaders := &http.Header{}
|
||||
SetHeaders(reqHeaders, headers)
|
||||
req.Header = *reqHeaders
|
||||
//c.Logger.Info().Any("headers", req.Header).Msg("GET Request Headers")
|
||||
res, reqErr := c.http.Do(req)
|
||||
if reqErr != nil {
|
||||
return res, reqErr
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (c *Client) MakeRelayRequest(url string, body []byte) (*http.Response, error) {
|
||||
req, err := http.NewRequest("POST", url, bytes.NewReader(body))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
util.BuildRelayHeaders(req, "application/x-protobuf", "*/*")
|
||||
res, reqErr := c.http.Do(req)
|
||||
//c.Logger.Info().Any("bodyLength", len(body)).Any("url", url).Any("headers", res.Request.Header).Msg("Relay Request Headers")
|
||||
if reqErr != nil {
|
||||
return res, reqErr
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func SetHeaders(h *http.Header, headers interface{}) {
|
||||
if headers == nil {
|
||||
return
|
||||
}
|
||||
v := reflect.ValueOf(headers)
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
field := v.Type().Field(i)
|
||||
value := v.Field(i).String()
|
||||
if !v.Field(i).IsZero() {
|
||||
h.Set(field.Tag.Get("header"), value)
|
||||
}
|
||||
}
|
||||
}
|
16
libgm/response.go
Normal file
16
libgm/response.go
Normal file
|
@ -0,0 +1,16 @@
|
|||
package textgapi
|
||||
|
||||
import "go.mau.fi/mautrix-gmessages/libgm/binary"
|
||||
|
||||
func (c *Client) newMessagesResponse(responseData *Response) (*binary.FetchMessagesResponse, error) {
|
||||
messages := &binary.FetchMessagesResponse{}
|
||||
decryptErr := c.cryptor.DecryptAndDecodeData(responseData.Data.EncryptedData, messages)
|
||||
if decryptErr != nil {
|
||||
return nil, decryptErr
|
||||
}
|
||||
decryptErr = c.decryptImages(messages)
|
||||
if decryptErr != nil {
|
||||
return nil, decryptErr
|
||||
}
|
||||
return messages, nil
|
||||
}
|
102
libgm/response_handler.go
Normal file
102
libgm/response_handler.go
Normal file
|
@ -0,0 +1,102 @@
|
|||
package textgapi
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type ResponseChan struct {
|
||||
responses []*Response
|
||||
receivedResponses int64
|
||||
wg sync.WaitGroup
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
func (s *SessionHandler) addRequestToChannel(requestId string, opCode int64) {
|
||||
instruction, notOk := s.client.instructions.GetInstruction(opCode)
|
||||
if !notOk {
|
||||
log.Fatal(notOk)
|
||||
}
|
||||
if msgMap, ok := s.requests[requestId]; ok {
|
||||
responseChan := &ResponseChan{
|
||||
responses: make([]*Response, 0, instruction.ExpectedResponses),
|
||||
receivedResponses: 0,
|
||||
wg: sync.WaitGroup{},
|
||||
mu: sync.Mutex{},
|
||||
}
|
||||
msgMap[opCode] = responseChan
|
||||
responseChan.wg.Add(int(instruction.ExpectedResponses))
|
||||
responseChan.mu.Lock()
|
||||
} else {
|
||||
s.requests[requestId] = make(map[int64]*ResponseChan)
|
||||
responseChan := &ResponseChan{
|
||||
responses: make([]*Response, 0, instruction.ExpectedResponses),
|
||||
receivedResponses: 0,
|
||||
wg: sync.WaitGroup{},
|
||||
mu: sync.Mutex{},
|
||||
}
|
||||
s.requests[requestId][opCode] = responseChan
|
||||
responseChan.wg.Add(int(instruction.ExpectedResponses))
|
||||
responseChan.mu.Lock()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func (s *SessionHandler) respondToRequestChannel(res *Response) {
|
||||
requestId := res.Data.RequestId
|
||||
reqChannel, ok := s.requests[requestId]
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
opCodeResponseChan, ok2 := reqChannel[res.Data.Opcode]
|
||||
if !ok2 {
|
||||
return
|
||||
}
|
||||
|
||||
opCodeResponseChan.mu.Lock()
|
||||
|
||||
opCodeResponseChan.responses = append(opCodeResponseChan.responses, res)
|
||||
|
||||
s.client.Logger.Debug().Any("opcode", res.Data.Opcode).Msg("Got response")
|
||||
|
||||
instruction, ok3 := s.client.instructions.GetInstruction(res.Data.Opcode)
|
||||
if opCodeResponseChan.receivedResponses >= instruction.ExpectedResponses {
|
||||
s.client.Logger.Debug().Any("opcode", res.Data.Opcode).Msg("Ignoring opcode")
|
||||
return
|
||||
}
|
||||
opCodeResponseChan.receivedResponses++
|
||||
opCodeResponseChan.wg.Done()
|
||||
if !ok3 {
|
||||
log.Fatal(ok3)
|
||||
opCodeResponseChan.mu.Unlock()
|
||||
return
|
||||
}
|
||||
if opCodeResponseChan.receivedResponses >= instruction.ExpectedResponses {
|
||||
delete(reqChannel, res.Data.Opcode)
|
||||
if len(reqChannel) == 0 {
|
||||
delete(s.requests, requestId)
|
||||
}
|
||||
}
|
||||
|
||||
opCodeResponseChan.mu.Unlock()
|
||||
}
|
||||
|
||||
func (s *SessionHandler) WaitForResponse(requestId string, opCode int64) ([]*Response, error) {
|
||||
requestResponses, ok := s.requests[requestId]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("no response channel found for request ID: %s (opcode: %v)", requestId, opCode)
|
||||
}
|
||||
responseChan, ok2 := requestResponses[opCode]
|
||||
if !ok2 {
|
||||
return nil, fmt.Errorf("no response channel found for opCode: %v (requestId: %s)", opCode, requestId)
|
||||
}
|
||||
|
||||
// Unlock so responses can be received
|
||||
responseChan.mu.Unlock()
|
||||
|
||||
// Wait for all responses to be received
|
||||
responseChan.wg.Wait()
|
||||
|
||||
return responseChan.responses, nil
|
||||
}
|
168
libgm/rpc.go
Normal file
168
libgm/rpc.go
Normal file
|
@ -0,0 +1,168 @@
|
|||
package textgapi
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"go.mau.fi/mautrix-gmessages/libgm/events"
|
||||
"go.mau.fi/mautrix-gmessages/libgm/util"
|
||||
)
|
||||
|
||||
type RPC struct {
|
||||
client *Client
|
||||
http *http.Client
|
||||
conn io.ReadCloser
|
||||
rpcSessionId string
|
||||
webAuthKey []byte
|
||||
}
|
||||
|
||||
func (r *RPC) ListenReceiveMessages(payload []byte) {
|
||||
req, err := http.NewRequest("POST", util.RECEIVE_MESSAGES, bytes.NewReader(payload))
|
||||
if err != nil {
|
||||
log.Fatalf("Error creating request: %v", err)
|
||||
}
|
||||
util.BuildRelayHeaders(req, "application/json+protobuf", "*/*")
|
||||
resp, reqErr := r.http.Do(req)
|
||||
//r.client.Logger.Info().Any("bodyLength", len(payload)).Any("url", util.RECEIVE_MESSAGES).Any("headers", resp.Request.Header).Msg("RPC Request Headers")
|
||||
if reqErr != nil {
|
||||
log.Fatalf("Error making request: %v", err)
|
||||
}
|
||||
r.conn = resp.Body
|
||||
go r.startReadingData(resp.Body)
|
||||
}
|
||||
|
||||
/*
|
||||
The start of a message always begins with byte 44 (",")
|
||||
If the message is parsable (after , has been removed) as an array of interfaces:
|
||||
func (r *RPC) tryUnmarshalJSON(jsonData []byte, msgArr *[]interface{}) error {
|
||||
err := json.Unmarshal(jsonData, &msgArr)
|
||||
return err
|
||||
}
|
||||
then the message is complete and it should continue to the HandleRPCMsg function and it should also reset the buffer so that the next message can be received properly.
|
||||
|
||||
if it's not parsable, it should just append the received data to the buf and attempt to parse it until it's parsable. Because that would indicate that the full msg has been received
|
||||
*/
|
||||
|
||||
func (r *RPC) startReadingData(rc io.ReadCloser) {
|
||||
defer rc.Close()
|
||||
reader := bufio.NewReader(rc)
|
||||
buf := make([]byte, 2621440)
|
||||
var accumulatedData []byte
|
||||
for {
|
||||
n, err := reader.Read(buf)
|
||||
if err != nil {
|
||||
if errors.Is(err, os.ErrClosed) {
|
||||
r.client.Logger.Err(err).Msg("Closed body from server")
|
||||
r.conn = nil
|
||||
return
|
||||
}
|
||||
r.client.Logger.Err(err).Msg("Stopped reading data from server")
|
||||
return
|
||||
}
|
||||
chunk := buf[:n]
|
||||
if n <= 25 {
|
||||
isHeartBeat := r.isHeartBeat(chunk)
|
||||
if isHeartBeat {
|
||||
r.client.Logger.Info().Any("heartBeat", isHeartBeat).Msg("Got heartbeat message")
|
||||
}
|
||||
isStartData := r.isStartRead(chunk)
|
||||
if isStartData {
|
||||
r.client.Logger.Info().Any("startRead", isHeartBeat).Msg("Got startReading message")
|
||||
}
|
||||
accumulatedData = []byte{}
|
||||
continue
|
||||
}
|
||||
|
||||
if len(accumulatedData) == 0 {
|
||||
chunk = bytes.TrimPrefix(chunk, []byte{44})
|
||||
}
|
||||
accumulatedData = append(accumulatedData, chunk...)
|
||||
var msgArr []interface{}
|
||||
err = r.tryUnmarshalJSON(accumulatedData, &msgArr)
|
||||
if err != nil {
|
||||
//r.client.Logger.Err(err).Any("accumulated", string(accumulatedData)).Msg("Unable to unmarshal data, will wait for more data")
|
||||
continue
|
||||
}
|
||||
|
||||
accumulatedData = []byte{}
|
||||
r.client.Logger.Info().Any("val", msgArr).Msg("MsgArr")
|
||||
go r.HandleRPCMsg(msgArr)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *RPC) isStartRead(data []byte) bool {
|
||||
return string(data) == "[[[null,null,null,[]]"
|
||||
}
|
||||
|
||||
func (r *RPC) isHeartBeat(data []byte) bool {
|
||||
return string(data) == ",[null,null,[]]"
|
||||
}
|
||||
|
||||
/*
|
||||
func (r *RPC) startReadingData(rc io.ReadCloser) {
|
||||
defer rc.Close()
|
||||
reader := bufio.NewReader(rc)
|
||||
buf := make([]byte, 5242880)
|
||||
for {
|
||||
n, err := reader.Read(buf)
|
||||
if err != nil {
|
||||
if errors.Is(err, os.ErrClosed) {
|
||||
r.client.Logger.Err(err).Msg("Closed body from server")
|
||||
r.conn = nil
|
||||
return
|
||||
}
|
||||
r.client.Logger.Err(err).Msg("Stopped reading data from server")
|
||||
return
|
||||
}
|
||||
chunk := buf[:n]
|
||||
var msgArr []interface{}
|
||||
isComplete := r.tryUnmarshalJSON(chunk, &msgArr)
|
||||
r.client.Logger.Info().Any("val", chunk[0] == 44).Any("isComplete", string(chunk)).Msg("is Start?")
|
||||
go r.HandleRPCMsg(buf[:n])
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
func (r *RPC) CloseConnection() {
|
||||
if r.conn != nil {
|
||||
r.client.Logger.Debug().Msg("Attempting to connection...")
|
||||
r.conn.Close()
|
||||
r.conn = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (r *RPC) sendMessageRequest(url string, payload []byte) (*http.Response, error) {
|
||||
req, err := http.NewRequest("POST", url, bytes.NewReader(payload))
|
||||
if err != nil {
|
||||
log.Fatalf("Error creating request: %v", err)
|
||||
}
|
||||
util.BuildRelayHeaders(req, "application/json+protobuf", "*/*")
|
||||
resp, reqErr := r.client.http.Do(req)
|
||||
//r.client.Logger.Info().Any("bodyLength", len(payload)).Any("url", url).Any("headers", resp.Request.Header).Msg("RPC Request Headers")
|
||||
if reqErr != nil {
|
||||
log.Fatalf("Error making request: %v", err)
|
||||
}
|
||||
return resp, reqErr
|
||||
}
|
||||
|
||||
func (r *RPC) sendInitialData() error {
|
||||
sessionResponse, err := r.client.Session.SetActiveSession()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
conversationList, convErr := r.client.Conversations.List(25)
|
||||
if convErr != nil {
|
||||
return convErr
|
||||
}
|
||||
|
||||
evtData := events.NewClientReady(sessionResponse, conversationList)
|
||||
r.client.triggerEvent(evtData)
|
||||
r.client.sessionHandler.startAckInterval()
|
||||
return nil
|
||||
}
|
66
libgm/session.go
Normal file
66
libgm/session.go
Normal file
|
@ -0,0 +1,66 @@
|
|||
package textgapi
|
||||
|
||||
import "go.mau.fi/mautrix-gmessages/libgm/util"
|
||||
|
||||
type Session struct {
|
||||
client *Client
|
||||
|
||||
prepareNewSession prepareNewSession
|
||||
newSession newSession
|
||||
}
|
||||
|
||||
func (s *Session) SetActiveSession() (*util.SessionResponse, error) {
|
||||
s.client.sessionHandler.ResetSessionId()
|
||||
|
||||
prepareResponses, prepareSessionErr := s.prepareNewSession.Execute()
|
||||
if prepareSessionErr != nil {
|
||||
return nil, prepareSessionErr
|
||||
}
|
||||
|
||||
newSessionResponses, newSessionErr := s.newSession.Execute()
|
||||
if newSessionErr != nil {
|
||||
return nil, newSessionErr
|
||||
}
|
||||
|
||||
sessionResponse, processFail := s.client.processSessionResponse(prepareResponses, newSessionResponses)
|
||||
if processFail != nil {
|
||||
return nil, processFail
|
||||
}
|
||||
|
||||
s.client.cache.SetSettings(sessionResponse.Settings)
|
||||
return sessionResponse, nil
|
||||
}
|
||||
|
||||
type prepareNewSession struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
func (p *prepareNewSession) Execute() ([]*Response, error) {
|
||||
instruction, _ := p.client.instructions.GetInstruction(PREPARE_NEW_SESSION_OPCODE)
|
||||
sentRequestId, _ := p.client.createAndSendRequest(instruction.Opcode, p.client.ttl, false, nil)
|
||||
|
||||
responses, err := p.client.sessionHandler.WaitForResponse(sentRequestId, instruction.Opcode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return responses, nil
|
||||
}
|
||||
|
||||
type newSession struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
func (n *newSession) Execute() ([]*Response, error) {
|
||||
instruction, _ := n.client.instructions.GetInstruction(NEW_SESSION_OPCODE)
|
||||
sentRequestId, _ := n.client.createAndSendRequest(instruction.Opcode, 0, true, nil)
|
||||
|
||||
responses, err := n.client.sessionHandler.WaitForResponse(sentRequestId, instruction.Opcode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Rest of the processing...
|
||||
|
||||
return responses, nil
|
||||
}
|
216
libgm/session_handler.go
Normal file
216
libgm/session_handler.go
Normal file
|
@ -0,0 +1,216 @@
|
|||
package textgapi
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"golang.org/x/exp/slices"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
|
||||
"go.mau.fi/mautrix-gmessages/libgm/binary"
|
||||
"go.mau.fi/mautrix-gmessages/libgm/crypto"
|
||||
"go.mau.fi/mautrix-gmessages/libgm/json_proto"
|
||||
"go.mau.fi/mautrix-gmessages/libgm/payload"
|
||||
"go.mau.fi/mautrix-gmessages/libgm/util"
|
||||
)
|
||||
|
||||
type Response struct {
|
||||
client *Client
|
||||
ResponseId string
|
||||
RoutingOpCode int64
|
||||
Data *binary.EncodedResponse // base64 encoded (decode -> protomessage)
|
||||
|
||||
StartExecute string
|
||||
FinishExecute string
|
||||
DevicePair *DevicePair
|
||||
}
|
||||
|
||||
type SessionHandler struct {
|
||||
client *Client
|
||||
requests map[string]map[int64]*ResponseChan
|
||||
|
||||
ackMap []string
|
||||
ackTicker *time.Ticker
|
||||
|
||||
sessionId string
|
||||
|
||||
responseTimeout time.Duration
|
||||
}
|
||||
|
||||
func (s *SessionHandler) SetResponseTimeout(milliSeconds int) {
|
||||
s.responseTimeout = time.Duration(milliSeconds) * time.Millisecond
|
||||
}
|
||||
|
||||
func (s *SessionHandler) ResetSessionId() {
|
||||
s.sessionId = util.RandomUUIDv4()
|
||||
}
|
||||
|
||||
func (c *Client) createAndSendRequest(instructionId int64, ttl int64, newSession bool, encryptedProtoMessage protoreflect.Message) (string, error) {
|
||||
requestId := util.RandomUUIDv4()
|
||||
instruction, ok := c.instructions.GetInstruction(instructionId)
|
||||
if !ok {
|
||||
return "", fmt.Errorf("failed to get instruction: %v does not exist", instructionId)
|
||||
}
|
||||
|
||||
if newSession {
|
||||
requestId = c.sessionHandler.sessionId
|
||||
}
|
||||
|
||||
var encryptedData []byte
|
||||
var encryptErr error
|
||||
if encryptedProtoMessage != nil {
|
||||
encryptedData, encryptErr = c.EncryptPayloadData(encryptedProtoMessage)
|
||||
if encryptErr != nil {
|
||||
return "", fmt.Errorf("failed to encrypt payload data for opcode: %v", instructionId)
|
||||
}
|
||||
c.Logger.Info().Any("encryptedData", encryptedData).Msg("Sending request with encrypted data")
|
||||
}
|
||||
|
||||
encodedData := payload.NewEncodedPayload(requestId, instruction.Opcode, encryptedData, c.sessionHandler.sessionId)
|
||||
encodedStr, encodeErr := crypto.EncodeProtoB64(encodedData)
|
||||
if encodeErr != nil {
|
||||
log.Fatalf("Failed to encode data: %v", encodeErr)
|
||||
}
|
||||
messageData := payload.NewMessageData(requestId, encodedStr, instruction.RoutingOpCode, instruction.MsgType)
|
||||
authMessage := payload.NewAuthData(requestId, c.rpcKey, &binary.Date{Year: 2023, Seq1: 6, Seq2: 8, Seq3: 4, Seq4: 6})
|
||||
sendMessage := payload.NewSendMessage(c.devicePair.Mobile, messageData, authMessage, ttl)
|
||||
|
||||
sentRequestId, reqErr := c.sessionHandler.completeSendMessage(encodedData.RequestId, instruction.Opcode, sendMessage)
|
||||
if reqErr != nil {
|
||||
return "", fmt.Errorf("failed to send message request for opcode: %v", instructionId)
|
||||
}
|
||||
return sentRequestId, nil
|
||||
}
|
||||
|
||||
func (s *SessionHandler) completeSendMessage(requestId string, opCode int64, msg *binary.SendMessage) (string, error) {
|
||||
jsonData, err := s.toJSON(msg.ProtoReflect())
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
//s.client.Logger.Debug().Any("payload", string(jsonData)).Msg("Sending message request")
|
||||
s.addRequestToChannel(requestId, opCode)
|
||||
_, reqErr := s.client.rpc.sendMessageRequest(util.SEND_MESSAGE, jsonData)
|
||||
if reqErr != nil {
|
||||
return "", reqErr
|
||||
}
|
||||
return requestId, nil
|
||||
}
|
||||
|
||||
func (s *SessionHandler) toJSON(message protoreflect.Message) ([]byte, error) {
|
||||
interfaceArr, err := json_proto.Serialize(message)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
jsonData, jsonErr := json.Marshal(interfaceArr)
|
||||
if jsonErr != nil {
|
||||
return nil, jsonErr
|
||||
}
|
||||
return jsonData, nil
|
||||
}
|
||||
|
||||
func (s *SessionHandler) addResponseAck(responseId string) {
|
||||
hasResponseId := slices.Contains(s.ackMap, responseId)
|
||||
if !hasResponseId {
|
||||
s.ackMap = append(s.ackMap, responseId)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SessionHandler) startAckInterval() {
|
||||
if s.ackTicker != nil {
|
||||
s.ackTicker.Stop()
|
||||
}
|
||||
ticker := time.NewTicker(5 * time.Second)
|
||||
s.ackTicker = ticker
|
||||
go func() {
|
||||
for range ticker.C {
|
||||
s.sendAckRequest()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (s *SessionHandler) sendAckRequest() {
|
||||
if len(s.ackMap) <= 0 {
|
||||
return
|
||||
}
|
||||
reqId := util.RandomUUIDv4()
|
||||
ackMessagePayload := &binary.AckMessagePayload{
|
||||
AuthData: &binary.AuthMessage{
|
||||
RequestId: reqId,
|
||||
RpcKey: s.client.rpcKey,
|
||||
Date: &binary.Date{Year: 2023, Seq1: 6, Seq2: 8, Seq3: 4, Seq4: 6},
|
||||
},
|
||||
EmptyArr: &binary.EmptyArr{},
|
||||
NoClue: nil,
|
||||
}
|
||||
dataArray, err := json_proto.Serialize(ackMessagePayload.ProtoReflect())
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
ackMessages := make([][]interface{}, 0)
|
||||
for _, reqId := range s.ackMap {
|
||||
ackMessageData := &binary.AckMessageData{RequestId: reqId, Device: s.client.devicePair.Browser}
|
||||
ackMessageDataArr, err := json_proto.Serialize(ackMessageData.ProtoReflect())
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
ackMessages = append(ackMessages, ackMessageDataArr)
|
||||
s.ackMap = util.RemoveFromSlice(s.ackMap, reqId)
|
||||
}
|
||||
dataArray = append(dataArray, ackMessages)
|
||||
jsonData, jsonErr := json.Marshal(dataArray)
|
||||
if jsonErr != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
_, err = s.client.rpc.sendMessageRequest(util.ACK_MESSAGES, jsonData)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
log.Println("[ACK] Sent Request")
|
||||
}
|
||||
|
||||
func (s *SessionHandler) NewResponse(response *binary.RPCResponse) (*Response, error) {
|
||||
//s.client.Logger.Debug().Any("rpcResponse", response).Msg("Raw rpc response")
|
||||
decodedData, err := crypto.DecodeEncodedResponse(response.Data.EncodedData)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return nil, err
|
||||
}
|
||||
return &Response{
|
||||
client: s.client,
|
||||
ResponseId: response.Data.RequestId,
|
||||
RoutingOpCode: response.Data.RoutingOpCode,
|
||||
StartExecute: response.Data.Ts1,
|
||||
FinishExecute: response.Data.Ts2,
|
||||
DevicePair: &DevicePair{
|
||||
Mobile: response.Data.Mobile,
|
||||
Browser: response.Data.Browser,
|
||||
},
|
||||
Data: decodedData,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (r *Response) decryptData() (proto.Message, error) {
|
||||
if r.Data.EncryptedData != nil {
|
||||
instruction, ok := r.client.instructions.GetInstruction(r.Data.Opcode)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("failed to decrypt data for unknown opcode: %v", r.Data.Opcode)
|
||||
}
|
||||
decryptedBytes, errDecrypt := instruction.cryptor.Decrypt(r.Data.EncryptedData)
|
||||
if errDecrypt != nil {
|
||||
return nil, errDecrypt
|
||||
}
|
||||
//os.WriteFile("opcode_"+strconv.Itoa(int(instruction.Opcode))+".bin", decryptedBytes, os.ModePerm)
|
||||
|
||||
protoMessageData := instruction.DecryptedProtoMessage.ProtoReflect().Type().New().Interface()
|
||||
decodeProtoErr := binary.DecodeProtoMessage(decryptedBytes, protoMessageData)
|
||||
if decodeProtoErr != nil {
|
||||
return nil, decodeProtoErr
|
||||
}
|
||||
|
||||
return protoMessageData, nil
|
||||
}
|
||||
return nil, fmt.Errorf("no encrypted data to decrypt for requestId: %s", r.Data.RequestId)
|
||||
}
|
9
libgm/util/constants.go
Normal file
9
libgm/util/constants.go
Normal file
|
@ -0,0 +1,9 @@
|
|||
package util
|
||||
|
||||
|
||||
var GOOG_API_KEY = "AIzaSyCA4RsOZUFrm9whhtGosPlJLmVPnfSHKz8"
|
||||
var USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36"
|
||||
var OS = "Linux"
|
||||
var X_USER_AGENT = "grpc-web-javascript/0.1"
|
||||
var QR_CODE_URL = "https://support.google.com/messages/?p=web_computer#?c="
|
||||
var TENOR_API_KEY = "YR0F99AJ65AV"
|
12
libgm/util/errors.go
Normal file
12
libgm/util/errors.go
Normal file
|
@ -0,0 +1,12 @@
|
|||
package util
|
||||
|
||||
import "fmt"
|
||||
|
||||
|
||||
type InstructionNotFound struct {
|
||||
Opcode int64
|
||||
}
|
||||
|
||||
func (e *InstructionNotFound) Error() string {
|
||||
return fmt.Sprintf("Could not find instruction for opcode %d", e.Opcode)
|
||||
}
|
135
libgm/util/func.go
Normal file
135
libgm/util/func.go
Normal file
|
@ -0,0 +1,135 @@
|
|||
package util
|
||||
|
||||
import (
|
||||
crand "crypto/rand"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/nu7hatch/gouuid"
|
||||
)
|
||||
|
||||
var Charset = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890")
|
||||
|
||||
func RandStr(length int) string {
|
||||
b := make([]rune, length)
|
||||
for i := range b {
|
||||
b[i] = Charset[rand.Intn(len(Charset))]
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func GenerateImageId() string {
|
||||
part1 := RandomUUIDv4()
|
||||
part2 := RandStr(25)
|
||||
return part1 + "/" + part2
|
||||
}
|
||||
|
||||
func GenerateTmpId() string {
|
||||
src := rand.NewSource(time.Now().UnixNano())
|
||||
r := rand.New(src)
|
||||
randNum := r.Int63n(1e12)
|
||||
return fmt.Sprintf("tmp_%012d", randNum)
|
||||
}
|
||||
|
||||
func ParseTimestamp(unixTs int64) time.Time {
|
||||
seconds := unixTs / int64(time.Second / time.Microsecond)
|
||||
nanoseconds := (unixTs % int64(time.Second / time.Microsecond)) * int64(time.Microsecond / time.Nanosecond)
|
||||
return time.Unix(seconds, nanoseconds).UTC()
|
||||
}
|
||||
|
||||
func RandomHex(n int) string {
|
||||
bytes := make([]byte, n)
|
||||
crand.Read(bytes)
|
||||
return hex.EncodeToString(bytes)
|
||||
}
|
||||
|
||||
func RandomUUIDv4() string {
|
||||
id, _ := uuid.NewV4()
|
||||
return id.String()
|
||||
}
|
||||
|
||||
func RemoveFromSlice(s []string, v string) []string {
|
||||
newS := []string{}
|
||||
for _, i := range s {
|
||||
if i != v {
|
||||
newS = append(newS, i)
|
||||
}
|
||||
}
|
||||
return newS
|
||||
}
|
||||
|
||||
func BuildRelayHeaders(req *http.Request, contentType string, accept string) {
|
||||
req.Header.Add("host", "instantmessaging-pa.googleapis.com")
|
||||
req.Header.Add("connection", "keep-alive")
|
||||
req.Header.Add("sec-ch-ua", "\"Google Chrome\";v=\"113\", \"Chromium\";v=\"113\", \"Not-A.Brand\";v=\"24\"")
|
||||
req.Header.Add("x-user-agent", X_USER_AGENT)
|
||||
req.Header.Add("x-goog-api-key", GOOG_API_KEY)
|
||||
if len(contentType) > 0 {
|
||||
req.Header.Add("content-type", contentType)
|
||||
}
|
||||
req.Header.Add("sec-ch-ua-mobile", "?0")
|
||||
req.Header.Add("user-agent", USER_AGENT)
|
||||
req.Header.Add("sec-ch-ua-platform", "\""+OS+"\"")
|
||||
req.Header.Add("accept", accept)
|
||||
req.Header.Add("origin", "https://messages.google.com")
|
||||
req.Header.Add("sec-fetch-site", "cross-site")
|
||||
req.Header.Add("sec-fetch-mode", "cors")
|
||||
req.Header.Add("sec-fetch-dest", "empty")
|
||||
req.Header.Add("referer", "https://messages.google.com/")
|
||||
req.Header.Add("accept-language", "en-US,en;q=0.9")
|
||||
}
|
||||
|
||||
func BuildUploadHeaders(req *http.Request, metadata string) {
|
||||
req.Header.Add("host", "instantmessaging-pa.googleapis.com")
|
||||
req.Header.Add("connection", "keep-alive")
|
||||
req.Header.Add("x-goog-download-metadata", metadata)
|
||||
req.Header.Add("sec-ch-ua", "\"Google Chrome\";v=\"113\", \"Chromium\";v=\"113\", \"Not-A.Brand\";v=\"24\"")
|
||||
req.Header.Add("sec-ch-ua-mobile", "?0")
|
||||
req.Header.Add("user-agent", USER_AGENT)
|
||||
req.Header.Add("sec-ch-ua-platform", "\""+OS+"\"")
|
||||
req.Header.Add("accept", "*/*")
|
||||
req.Header.Add("origin", "https://messages.google.com")
|
||||
req.Header.Add("sec-fetch-site", "cross-site")
|
||||
req.Header.Add("sec-fetch-mode", "cors")
|
||||
req.Header.Add("sec-fetch-dest", "empty")
|
||||
req.Header.Add("referer", "https://messages.google.com/")
|
||||
req.Header.Add("accept-encoding", "gzip, deflate, br")
|
||||
req.Header.Add("accept-language", "en-US,en;q=0.9")
|
||||
}
|
||||
|
||||
func NewMediaUploadHeaders(imageSize string, command string, uploadOffset string, imageContentType string, protocol string) *http.Header {
|
||||
headers := &http.Header{}
|
||||
|
||||
headers.Add("host", "instantmessaging-pa.googleapis.com")
|
||||
headers.Add("connection", "keep-alive")
|
||||
headers.Add("sec-ch-ua", "\"Google Chrome\";v=\"113\", \"Chromium\";v=\"113\", \"Not-A.Brand\";v=\"24\"")
|
||||
if protocol != "" {
|
||||
headers.Add("x-goog-upload-protocol", protocol)
|
||||
}
|
||||
headers.Add("x-goog-upload-header-content-length", imageSize)
|
||||
headers.Add("sec-ch-ua-mobile", "?0")
|
||||
headers.Add("user-agent", USER_AGENT)
|
||||
if imageContentType != "" {
|
||||
headers.Add("x-goog-upload-header-content-type", imageContentType)
|
||||
}
|
||||
headers.Add("content-type", "application/x-www-form-urlencoded;charset=UTF-8")
|
||||
if command != "" {
|
||||
headers.Add("x-goog-upload-command", command)
|
||||
}
|
||||
if uploadOffset != "" {
|
||||
headers.Add("x-goog-upload-offset", uploadOffset)
|
||||
}
|
||||
headers.Add("sec-ch-ua-platform", "\""+OS+"\"")
|
||||
headers.Add("accept", "*/*")
|
||||
headers.Add("origin", "https://messages.google.com")
|
||||
headers.Add("sec-fetch-site", "cross-site")
|
||||
headers.Add("sec-fetch-mode", "cors")
|
||||
headers.Add("sec-fetch-dest", "empty")
|
||||
headers.Add("referer", "https://messages.google.com/")
|
||||
headers.Add("accept-encoding", "gzip, deflate, br")
|
||||
headers.Add("accept-language", "en-US,en;q=0.9")
|
||||
return headers
|
||||
}
|
23
libgm/util/paths.go
Normal file
23
libgm/util/paths.go
Normal file
|
@ -0,0 +1,23 @@
|
|||
package util
|
||||
|
||||
var MESSAGES_GOOGLE_BASE_URL = "https://messages.google.com"
|
||||
|
||||
var MESSAGES_GOOGLE_AUTHENTICATION = MESSAGES_GOOGLE_BASE_URL+"/web/authentication"
|
||||
var MESSAGES_GOOGLE_TIMESOURCE = MESSAGES_GOOGLE_BASE_URL+"/web/timesource"
|
||||
|
||||
var INSTANT_MESSAGING = "https://instantmessaging-pa.googleapis.com"
|
||||
|
||||
var UPLOAD_MEDIA = INSTANT_MESSAGING+"/upload"
|
||||
|
||||
var PAIRING = INSTANT_MESSAGING+"/$rpc/google.internal.communications.instantmessaging.v1.Pairing"
|
||||
var REGISTER_PHONE_RELAY = PAIRING+"/RegisterPhoneRelay"
|
||||
var REFRESH_PHONE_RELAY = PAIRING+"/RefreshPhoneRelay"
|
||||
var GET_WEB_ENCRYPTION_KEY = PAIRING+"/GetWebEncryptionKey"
|
||||
|
||||
var MESSAGING = INSTANT_MESSAGING+"/$rpc/google.internal.communications.instantmessaging.v1.Messaging"
|
||||
var RECEIVE_MESSAGES = MESSAGING+"/ReceiveMessages"
|
||||
var SEND_MESSAGE = MESSAGING+"/SendMessage"
|
||||
var ACK_MESSAGES = MESSAGING+"/AckMessages"
|
||||
|
||||
var TENOR_BASE_URL = "https://api.tenor.com/v1"
|
||||
var TENOR_SEARCH_GIF = TENOR_BASE_URL+"/search"
|
111
libgm/util/structs.go
Normal file
111
libgm/util/structs.go
Normal file
|
@ -0,0 +1,111 @@
|
|||
package util
|
||||
|
||||
import "go.mau.fi/mautrix-gmessages/libgm/binary"
|
||||
|
||||
type SessionResponse struct {
|
||||
Success bool
|
||||
Settings *binary.Settings
|
||||
}
|
||||
|
||||
type Headers struct {
|
||||
Host string `json:"host,omitempty" header:"host"`
|
||||
Connection string `json:"connection,omitempty" header:"connection"`
|
||||
SecChUa string `json:"sec-ch-ua,omitempty" header:"sec-ch-ua"`
|
||||
SecChUaMobile string `json:"sec-ch-ua-mobile,omitempty" header:"sec-ch-ua-mobile"`
|
||||
SecChUaPlatform string `json:"sec-ch-ua-platform,omitempty" header:"sec-ch-ua-platform"`
|
||||
UpgradeInsecureRequests string `json:"upgrade-insecure-requests,omitempty" header:"upgrade-insecure-requests"`
|
||||
UserAgent string `json:"user-agent,omitempty" header:"user-agent"`
|
||||
Accept string `json:"accept,omitempty" header:"accept"`
|
||||
Cookie string `json:"cookie,omitempty" header:"cookie"`
|
||||
Referer string `json:"referer,omitempty" header:"referer"`
|
||||
SecFetchSite string `json:"sec-fetch-site,omitempty" header:"sec-fetch-site"`
|
||||
SecFetchMode string `json:"sec-fetch-mode,omitempty" header:"sec-fetch-mode"`
|
||||
SecFetchUser string `json:"sec-fetch-user,omitempty" header:"sec-fetch-user"`
|
||||
SecFetchDest string `json:"sec-fetch-dest,omitempty" header:"sec-fetch-dest"`
|
||||
AcceptEncoding string `json:"accept-encoding,omitempty" header:"accept-encoding"`
|
||||
AcceptLanguage string `json:"accept-language,omitempty" header:"accept-language"`
|
||||
}
|
||||
|
||||
func (h *Headers) Build() {
|
||||
h.Connection = "keep-alive"
|
||||
h.SecChUa = `"Google Chrome";v="113", "Chromium";v="113", "Not-A.Brand";v="24"`
|
||||
h.SecChUaMobile = "?0"
|
||||
h.SecChUaPlatform = `"Linux"`
|
||||
h.UpgradeInsecureRequests = "1"
|
||||
h.UserAgent = USER_AGENT
|
||||
h.Accept = `text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7`
|
||||
h.SecFetchSite = "none"
|
||||
h.SecFetchMode = "navigate"
|
||||
h.SecFetchUser = "?1"
|
||||
h.SecFetchDest = "document"
|
||||
h.AcceptEncoding = "gzip, deflate, br"
|
||||
h.AcceptLanguage = "en-US,en;q=0.9"
|
||||
}
|
||||
|
||||
func (h *Headers) SetReferer(referer string) {
|
||||
h.Referer = referer
|
||||
}
|
||||
|
||||
func (h *Headers) SetSecFetchSite(val string) {
|
||||
h.SecFetchSite = val
|
||||
}
|
||||
|
||||
func (h *Headers) SetSecFetchUser(val string) {
|
||||
h.SecFetchUser = val
|
||||
}
|
||||
|
||||
func (h *Headers) SetSecFetchDest(val string) {
|
||||
h.SecFetchDest = val
|
||||
}
|
||||
|
||||
func (h *Headers) SetUpgradeInsecureRequests(val string) {
|
||||
h.UpgradeInsecureRequests = val
|
||||
}
|
||||
|
||||
func (h *Headers) SetAccept(val string) {
|
||||
h.Accept = val
|
||||
}
|
||||
|
||||
type RelayHeaders struct {
|
||||
Host string `json:"host,omitempty"`
|
||||
Connection string `json:"connection,omitempty"`
|
||||
SecChUa string `json:"sec-ch-ua,omitempty"`
|
||||
XUserAgent string `json:"x-user-agent,omitempty"`
|
||||
XGoogAPIKey string `json:"x-goog-api-key,omitempty"`
|
||||
ContentType string `json:"content-type,omitempty"`
|
||||
SecChUaMobile string `json:"sec-ch-ua-mobile,omitempty"`
|
||||
UserAgent string `json:"user-agent,omitempty"`
|
||||
SecChUaPlatform string `json:"sec-ch-ua-platform,omitempty"`
|
||||
Accept string `json:"accept,omitempty"`
|
||||
Origin string `json:"origin,omitempty"`
|
||||
XClientData string `json:"x-client-data,omitempty"`
|
||||
SecFetchSite string `json:"sec-fetch-site,omitempty"`
|
||||
SecFetchMode string `json:"sec-fetch-mode,omitempty"`
|
||||
SecFetchDest string `json:"sec-fetch-dest,omitempty"`
|
||||
Referer string `json:"referer,omitempty"`
|
||||
AcceptEncoding string `json:"accept-encoding,omitempty"`
|
||||
AcceptLanguage string `json:"accept-language,omitempty"`
|
||||
}
|
||||
|
||||
type MediaUploadHeaders struct {
|
||||
Host string `json:"host"`
|
||||
Connection string `json:"connection"`
|
||||
SecChUa string `json:"sec-ch-ua"`
|
||||
XGoogUploadProtocol string `json:"x-goog-upload-protocol"`
|
||||
XGoogUploadHeaderContentLength string `json:"x-goog-upload-header-content-length"`
|
||||
SecChUaMobile string `json:"sec-ch-ua-mobile"`
|
||||
UserAgent string `json:"user-agent"`
|
||||
XGoogUploadHeaderContentType string `json:"x-goog-upload-header-content-type"`
|
||||
ContentType string `json:"content-type"`
|
||||
XGoogUploadCommand string `json:"x-goog-upload-command"`
|
||||
SecChUaPlatform string `json:"sec-ch-ua-platform"`
|
||||
Accept string `json:"accept"`
|
||||
Origin string `json:"origin"`
|
||||
XClientData string `json:"x-client-data"`
|
||||
SecFetchSite string `json:"sec-fetch-site"`
|
||||
SecFetchMode string `json:"sec-fetch-mode"`
|
||||
SecFetchDest string `json:"sec-fetch-dest"`
|
||||
Referer string `json:"referer"`
|
||||
AcceptEncoding string `json:"accept-encoding"`
|
||||
AcceptLanguage string `json:"accept-language"`
|
||||
}
|
Loading…
Reference in a new issue