Stage 11: account linking & merge (email + Telegram Login Widget) (#12)
Tests · Go / test (push) Successful in 7s
Tests · Integration / integration (push) Successful in 11s
Tests · UI / test (push) Successful in 18s

This commit was merged in pull request #12.
This commit is contained in:
2026-06-04 09:18:17 +00:00
parent 3a640a17a4
commit 01485d8fc6
68 changed files with 3331 additions and 369 deletions
+158 -36
View File
@@ -148,6 +148,115 @@ func (x *ValidateInitDataResponse) GetLanguageCode() string {
return ""
}
// ValidateLoginWidgetRequest carries the Login Widget result serialized as a URL
// query string (the widget fields plus the hash, e.g. "auth_date=...&id=...&hash=...").
type ValidateLoginWidgetRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
Data string `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ValidateLoginWidgetRequest) Reset() {
*x = ValidateLoginWidgetRequest{}
mi := &file_telegram_v1_telegram_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ValidateLoginWidgetRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ValidateLoginWidgetRequest) ProtoMessage() {}
func (x *ValidateLoginWidgetRequest) ProtoReflect() protoreflect.Message {
mi := &file_telegram_v1_telegram_proto_msgTypes[2]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ValidateLoginWidgetRequest.ProtoReflect.Descriptor instead.
func (*ValidateLoginWidgetRequest) Descriptor() ([]byte, []int) {
return file_telegram_v1_telegram_proto_rawDescGZIP(), []int{2}
}
func (x *ValidateLoginWidgetRequest) GetData() string {
if x != nil {
return x.Data
}
return ""
}
// ValidateLoginWidgetResponse is the validated identity. external_id is the
// Telegram user id used as the identities external_id. The Login Widget carries no
// language_code (unlike Mini App initData).
type ValidateLoginWidgetResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
ExternalId string `protobuf:"bytes,1,opt,name=external_id,json=externalId,proto3" json:"external_id,omitempty"`
Username string `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"`
FirstName string `protobuf:"bytes,3,opt,name=first_name,json=firstName,proto3" json:"first_name,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ValidateLoginWidgetResponse) Reset() {
*x = ValidateLoginWidgetResponse{}
mi := &file_telegram_v1_telegram_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ValidateLoginWidgetResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ValidateLoginWidgetResponse) ProtoMessage() {}
func (x *ValidateLoginWidgetResponse) ProtoReflect() protoreflect.Message {
mi := &file_telegram_v1_telegram_proto_msgTypes[3]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ValidateLoginWidgetResponse.ProtoReflect.Descriptor instead.
func (*ValidateLoginWidgetResponse) Descriptor() ([]byte, []int) {
return file_telegram_v1_telegram_proto_rawDescGZIP(), []int{3}
}
func (x *ValidateLoginWidgetResponse) GetExternalId() string {
if x != nil {
return x.ExternalId
}
return ""
}
func (x *ValidateLoginWidgetResponse) GetUsername() string {
if x != nil {
return x.Username
}
return ""
}
func (x *ValidateLoginWidgetResponse) GetFirstName() string {
if x != nil {
return x.FirstName
}
return ""
}
// NotifyRequest addresses a push event to one recipient. kind is the backend push
// catalog kind (your_turn, nudge, match_found, notify); payload is the FlatBuffers
// scrabblefb.* body for that kind; language (en/ru) selects the message template.
@@ -163,7 +272,7 @@ type NotifyRequest struct {
func (x *NotifyRequest) Reset() {
*x = NotifyRequest{}
mi := &file_telegram_v1_telegram_proto_msgTypes[2]
mi := &file_telegram_v1_telegram_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -175,7 +284,7 @@ func (x *NotifyRequest) String() string {
func (*NotifyRequest) ProtoMessage() {}
func (x *NotifyRequest) ProtoReflect() protoreflect.Message {
mi := &file_telegram_v1_telegram_proto_msgTypes[2]
mi := &file_telegram_v1_telegram_proto_msgTypes[4]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -188,7 +297,7 @@ func (x *NotifyRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use NotifyRequest.ProtoReflect.Descriptor instead.
func (*NotifyRequest) Descriptor() ([]byte, []int) {
return file_telegram_v1_telegram_proto_rawDescGZIP(), []int{2}
return file_telegram_v1_telegram_proto_rawDescGZIP(), []int{4}
}
func (x *NotifyRequest) GetExternalId() string {
@@ -230,7 +339,7 @@ type NotifyResponse struct {
func (x *NotifyResponse) Reset() {
*x = NotifyResponse{}
mi := &file_telegram_v1_telegram_proto_msgTypes[3]
mi := &file_telegram_v1_telegram_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -242,7 +351,7 @@ func (x *NotifyResponse) String() string {
func (*NotifyResponse) ProtoMessage() {}
func (x *NotifyResponse) ProtoReflect() protoreflect.Message {
mi := &file_telegram_v1_telegram_proto_msgTypes[3]
mi := &file_telegram_v1_telegram_proto_msgTypes[5]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -255,7 +364,7 @@ func (x *NotifyResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use NotifyResponse.ProtoReflect.Descriptor instead.
func (*NotifyResponse) Descriptor() ([]byte, []int) {
return file_telegram_v1_telegram_proto_rawDescGZIP(), []int{3}
return file_telegram_v1_telegram_proto_rawDescGZIP(), []int{5}
}
func (x *NotifyResponse) GetDelivered() bool {
@@ -276,7 +385,7 @@ type SendToUserRequest struct {
func (x *SendToUserRequest) Reset() {
*x = SendToUserRequest{}
mi := &file_telegram_v1_telegram_proto_msgTypes[4]
mi := &file_telegram_v1_telegram_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -288,7 +397,7 @@ func (x *SendToUserRequest) String() string {
func (*SendToUserRequest) ProtoMessage() {}
func (x *SendToUserRequest) ProtoReflect() protoreflect.Message {
mi := &file_telegram_v1_telegram_proto_msgTypes[4]
mi := &file_telegram_v1_telegram_proto_msgTypes[6]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -301,7 +410,7 @@ func (x *SendToUserRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use SendToUserRequest.ProtoReflect.Descriptor instead.
func (*SendToUserRequest) Descriptor() ([]byte, []int) {
return file_telegram_v1_telegram_proto_rawDescGZIP(), []int{4}
return file_telegram_v1_telegram_proto_rawDescGZIP(), []int{6}
}
func (x *SendToUserRequest) GetExternalId() string {
@@ -328,7 +437,7 @@ type SendToGameChannelRequest struct {
func (x *SendToGameChannelRequest) Reset() {
*x = SendToGameChannelRequest{}
mi := &file_telegram_v1_telegram_proto_msgTypes[5]
mi := &file_telegram_v1_telegram_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -340,7 +449,7 @@ func (x *SendToGameChannelRequest) String() string {
func (*SendToGameChannelRequest) ProtoMessage() {}
func (x *SendToGameChannelRequest) ProtoReflect() protoreflect.Message {
mi := &file_telegram_v1_telegram_proto_msgTypes[5]
mi := &file_telegram_v1_telegram_proto_msgTypes[7]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -353,7 +462,7 @@ func (x *SendToGameChannelRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use SendToGameChannelRequest.ProtoReflect.Descriptor instead.
func (*SendToGameChannelRequest) Descriptor() ([]byte, []int) {
return file_telegram_v1_telegram_proto_rawDescGZIP(), []int{5}
return file_telegram_v1_telegram_proto_rawDescGZIP(), []int{7}
}
func (x *SendToGameChannelRequest) GetText() string {
@@ -373,7 +482,7 @@ type SendResponse struct {
func (x *SendResponse) Reset() {
*x = SendResponse{}
mi := &file_telegram_v1_telegram_proto_msgTypes[6]
mi := &file_telegram_v1_telegram_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -385,7 +494,7 @@ func (x *SendResponse) String() string {
func (*SendResponse) ProtoMessage() {}
func (x *SendResponse) ProtoReflect() protoreflect.Message {
mi := &file_telegram_v1_telegram_proto_msgTypes[6]
mi := &file_telegram_v1_telegram_proto_msgTypes[8]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -398,7 +507,7 @@ func (x *SendResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use SendResponse.ProtoReflect.Descriptor instead.
func (*SendResponse) Descriptor() ([]byte, []int) {
return file_telegram_v1_telegram_proto_rawDescGZIP(), []int{6}
return file_telegram_v1_telegram_proto_rawDescGZIP(), []int{8}
}
func (x *SendResponse) GetDelivered() bool {
@@ -421,7 +530,15 @@ const file_telegram_v1_telegram_proto_rawDesc = "" +
"\busername\x18\x02 \x01(\tR\busername\x12\x1d\n" +
"\n" +
"first_name\x18\x03 \x01(\tR\tfirstName\x12#\n" +
"\rlanguage_code\x18\x04 \x01(\tR\flanguageCode\"z\n" +
"\rlanguage_code\x18\x04 \x01(\tR\flanguageCode\"0\n" +
"\x1aValidateLoginWidgetRequest\x12\x12\n" +
"\x04data\x18\x01 \x01(\tR\x04data\"y\n" +
"\x1bValidateLoginWidgetResponse\x12\x1f\n" +
"\vexternal_id\x18\x01 \x01(\tR\n" +
"externalId\x12\x1a\n" +
"\busername\x18\x02 \x01(\tR\busername\x12\x1d\n" +
"\n" +
"first_name\x18\x03 \x01(\tR\tfirstName\"z\n" +
"\rNotifyRequest\x12\x1f\n" +
"\vexternal_id\x18\x01 \x01(\tR\n" +
"externalId\x12\x12\n" +
@@ -437,9 +554,10 @@ const file_telegram_v1_telegram_proto_rawDesc = "" +
"\x18SendToGameChannelRequest\x12\x12\n" +
"\x04text\x18\x01 \x01(\tR\x04text\",\n" +
"\fSendResponse\x12\x1c\n" +
"\tdelivered\x18\x01 \x01(\bR\tdelivered2\x96\x03\n" +
"\tdelivered\x18\x01 \x01(\bR\tdelivered2\x92\x04\n" +
"\bTelegram\x12q\n" +
"\x10ValidateInitData\x12-.scrabble.telegram.v1.ValidateInitDataRequest\x1a..scrabble.telegram.v1.ValidateInitDataResponse\x12S\n" +
"\x10ValidateInitData\x12-.scrabble.telegram.v1.ValidateInitDataRequest\x1a..scrabble.telegram.v1.ValidateInitDataResponse\x12z\n" +
"\x13ValidateLoginWidget\x120.scrabble.telegram.v1.ValidateLoginWidgetRequest\x1a1.scrabble.telegram.v1.ValidateLoginWidgetResponse\x12S\n" +
"\x06Notify\x12#.scrabble.telegram.v1.NotifyRequest\x1a$.scrabble.telegram.v1.NotifyResponse\x12Y\n" +
"\n" +
"SendToUser\x12'.scrabble.telegram.v1.SendToUserRequest\x1a\".scrabble.telegram.v1.SendResponse\x12g\n" +
@@ -457,27 +575,31 @@ func file_telegram_v1_telegram_proto_rawDescGZIP() []byte {
return file_telegram_v1_telegram_proto_rawDescData
}
var file_telegram_v1_telegram_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
var file_telegram_v1_telegram_proto_msgTypes = make([]protoimpl.MessageInfo, 9)
var file_telegram_v1_telegram_proto_goTypes = []any{
(*ValidateInitDataRequest)(nil), // 0: scrabble.telegram.v1.ValidateInitDataRequest
(*ValidateInitDataResponse)(nil), // 1: scrabble.telegram.v1.ValidateInitDataResponse
(*NotifyRequest)(nil), // 2: scrabble.telegram.v1.NotifyRequest
(*NotifyResponse)(nil), // 3: scrabble.telegram.v1.NotifyResponse
(*SendToUserRequest)(nil), // 4: scrabble.telegram.v1.SendToUserRequest
(*SendToGameChannelRequest)(nil), // 5: scrabble.telegram.v1.SendToGameChannelRequest
(*SendResponse)(nil), // 6: scrabble.telegram.v1.SendResponse
(*ValidateInitDataRequest)(nil), // 0: scrabble.telegram.v1.ValidateInitDataRequest
(*ValidateInitDataResponse)(nil), // 1: scrabble.telegram.v1.ValidateInitDataResponse
(*ValidateLoginWidgetRequest)(nil), // 2: scrabble.telegram.v1.ValidateLoginWidgetRequest
(*ValidateLoginWidgetResponse)(nil), // 3: scrabble.telegram.v1.ValidateLoginWidgetResponse
(*NotifyRequest)(nil), // 4: scrabble.telegram.v1.NotifyRequest
(*NotifyResponse)(nil), // 5: scrabble.telegram.v1.NotifyResponse
(*SendToUserRequest)(nil), // 6: scrabble.telegram.v1.SendToUserRequest
(*SendToGameChannelRequest)(nil), // 7: scrabble.telegram.v1.SendToGameChannelRequest
(*SendResponse)(nil), // 8: scrabble.telegram.v1.SendResponse
}
var file_telegram_v1_telegram_proto_depIdxs = []int32{
0, // 0: scrabble.telegram.v1.Telegram.ValidateInitData:input_type -> scrabble.telegram.v1.ValidateInitDataRequest
2, // 1: scrabble.telegram.v1.Telegram.Notify:input_type -> scrabble.telegram.v1.NotifyRequest
4, // 2: scrabble.telegram.v1.Telegram.SendToUser:input_type -> scrabble.telegram.v1.SendToUserRequest
5, // 3: scrabble.telegram.v1.Telegram.SendToGameChannel:input_type -> scrabble.telegram.v1.SendToGameChannelRequest
1, // 4: scrabble.telegram.v1.Telegram.ValidateInitData:output_type -> scrabble.telegram.v1.ValidateInitDataResponse
3, // 5: scrabble.telegram.v1.Telegram.Notify:output_type -> scrabble.telegram.v1.NotifyResponse
6, // 6: scrabble.telegram.v1.Telegram.SendToUser:output_type -> scrabble.telegram.v1.SendResponse
6, // 7: scrabble.telegram.v1.Telegram.SendToGameChannel:output_type -> scrabble.telegram.v1.SendResponse
4, // [4:8] is the sub-list for method output_type
0, // [0:4] is the sub-list for method input_type
2, // 1: scrabble.telegram.v1.Telegram.ValidateLoginWidget:input_type -> scrabble.telegram.v1.ValidateLoginWidgetRequest
4, // 2: scrabble.telegram.v1.Telegram.Notify:input_type -> scrabble.telegram.v1.NotifyRequest
6, // 3: scrabble.telegram.v1.Telegram.SendToUser:input_type -> scrabble.telegram.v1.SendToUserRequest
7, // 4: scrabble.telegram.v1.Telegram.SendToGameChannel:input_type -> scrabble.telegram.v1.SendToGameChannelRequest
1, // 5: scrabble.telegram.v1.Telegram.ValidateInitData:output_type -> scrabble.telegram.v1.ValidateInitDataResponse
3, // 6: scrabble.telegram.v1.Telegram.ValidateLoginWidget:output_type -> scrabble.telegram.v1.ValidateLoginWidgetResponse
5, // 7: scrabble.telegram.v1.Telegram.Notify:output_type -> scrabble.telegram.v1.NotifyResponse
8, // 8: scrabble.telegram.v1.Telegram.SendToUser:output_type -> scrabble.telegram.v1.SendResponse
8, // 9: scrabble.telegram.v1.Telegram.SendToGameChannel:output_type -> scrabble.telegram.v1.SendResponse
5, // [5:10] is the sub-list for method output_type
0, // [0:5] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
@@ -494,7 +616,7 @@ func file_telegram_v1_telegram_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_telegram_v1_telegram_proto_rawDesc), len(file_telegram_v1_telegram_proto_rawDesc)),
NumEnums: 0,
NumMessages: 7,
NumMessages: 9,
NumExtensions: 0,
NumServices: 1,
},