Stage 11: account linking & merge (email + Telegram Login Widget)
Tests · Go / test (push) Successful in 7s
Tests · Integration / integration (push) Successful in 11s
Tests · UI / test (push) Successful in 20s
Tests · Go / test (pull_request) Successful in 6s
Tests · Integration / integration (pull_request) Successful in 11s
Tests · UI / test (pull_request) Successful in 19s
Tests · Go / test (push) Successful in 7s
Tests · Integration / integration (push) Successful in 11s
Tests · UI / test (push) Successful in 20s
Tests · Go / test (pull_request) Successful in 6s
Tests · Integration / integration (pull_request) Successful in 11s
Tests · UI / test (pull_request) Successful in 19s
Link an email (confirm-code) or Telegram (web Login Widget) to the current account; if the identity already has its own account, merge the two into the one in use (the current account is primary, except a guest initiator whose durable counterpart wins). The merge runs in one transaction (internal/accountmerge): stats + hint wallet summed, paid_account ORed, identities/games/chat/complaints transferred, friends/blocks de-duplicated, the secondary kept as a merged_into tombstone so a shared finished game's no-cascade FKs hold; a shared active game blocks the merge. - migration 00009: accounts.paid_account, merged_into, merged_at (+ jetgen) - internal/link orchestrator; session.RevokeAllForAccount on merge - connector ValidateLoginWidget RPC + loginwidget HMAC validator - edge ops link.email.request/confirm/merge, link.telegram.confirm/merge; supersedes the Stage 8 email.bind.* surface (request never reveals 'taken' before the code is verified, so a probe cannot enumerate addresses) - UI Profile link section + irreversible-merge dialog; Telegram web sign-in - focused regression tests (merge core, guest inversion, active-game refusal, finished-shared-game kept), gateway transcode + connector + UI codec/e2e - docs: PLAN, ARCHITECTURE 3/4/9, FUNCTIONAL(+ru), module READMEs
This commit is contained in:
@@ -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,
|
||||
},
|
||||
|
||||
@@ -20,6 +20,11 @@ service Telegram {
|
||||
// the authenticated user. The gateway calls it during the auth.telegram edge
|
||||
// operation, then provisions the session through the backend internal API.
|
||||
rpc ValidateInitData(ValidateInitDataRequest) returns (ValidateInitDataResponse);
|
||||
// ValidateLoginWidget verifies Telegram Login Widget authorization data (the web
|
||||
// sign-in flow, HMAC under SHA-256(bot_token)) and returns the authenticated
|
||||
// user. The gateway calls it during the link.telegram edge operation to attach a
|
||||
// Telegram identity to an existing account (Stage 11).
|
||||
rpc ValidateLoginWidget(ValidateLoginWidgetRequest) returns (ValidateLoginWidgetResponse);
|
||||
// Notify delivers an out-of-app notification for a backend push event. The
|
||||
// gateway calls it only for a recipient with no live in-app stream (so the
|
||||
// platform push never duplicates in-app delivery). The connector renders a
|
||||
@@ -50,6 +55,21 @@ message ValidateInitDataResponse {
|
||||
string language_code = 4;
|
||||
}
|
||||
|
||||
// ValidateLoginWidgetRequest carries the Login Widget result serialized as a URL
|
||||
// query string (the widget fields plus the hash, e.g. "auth_date=...&id=...&hash=...").
|
||||
message ValidateLoginWidgetRequest {
|
||||
string data = 1;
|
||||
}
|
||||
|
||||
// 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).
|
||||
message ValidateLoginWidgetResponse {
|
||||
string external_id = 1;
|
||||
string username = 2;
|
||||
string first_name = 3;
|
||||
}
|
||||
|
||||
// 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.
|
||||
|
||||
@@ -30,10 +30,11 @@ import (
|
||||
const _ = grpc.SupportPackageIsVersion9
|
||||
|
||||
const (
|
||||
Telegram_ValidateInitData_FullMethodName = "/scrabble.telegram.v1.Telegram/ValidateInitData"
|
||||
Telegram_Notify_FullMethodName = "/scrabble.telegram.v1.Telegram/Notify"
|
||||
Telegram_SendToUser_FullMethodName = "/scrabble.telegram.v1.Telegram/SendToUser"
|
||||
Telegram_SendToGameChannel_FullMethodName = "/scrabble.telegram.v1.Telegram/SendToGameChannel"
|
||||
Telegram_ValidateInitData_FullMethodName = "/scrabble.telegram.v1.Telegram/ValidateInitData"
|
||||
Telegram_ValidateLoginWidget_FullMethodName = "/scrabble.telegram.v1.Telegram/ValidateLoginWidget"
|
||||
Telegram_Notify_FullMethodName = "/scrabble.telegram.v1.Telegram/Notify"
|
||||
Telegram_SendToUser_FullMethodName = "/scrabble.telegram.v1.Telegram/SendToUser"
|
||||
Telegram_SendToGameChannel_FullMethodName = "/scrabble.telegram.v1.Telegram/SendToGameChannel"
|
||||
)
|
||||
|
||||
// TelegramClient is the client API for Telegram service.
|
||||
@@ -46,6 +47,11 @@ type TelegramClient interface {
|
||||
// the authenticated user. The gateway calls it during the auth.telegram edge
|
||||
// operation, then provisions the session through the backend internal API.
|
||||
ValidateInitData(ctx context.Context, in *ValidateInitDataRequest, opts ...grpc.CallOption) (*ValidateInitDataResponse, error)
|
||||
// ValidateLoginWidget verifies Telegram Login Widget authorization data (the web
|
||||
// sign-in flow, HMAC under SHA-256(bot_token)) and returns the authenticated
|
||||
// user. The gateway calls it during the link.telegram edge operation to attach a
|
||||
// Telegram identity to an existing account (Stage 11).
|
||||
ValidateLoginWidget(ctx context.Context, in *ValidateLoginWidgetRequest, opts ...grpc.CallOption) (*ValidateLoginWidgetResponse, error)
|
||||
// Notify delivers an out-of-app notification for a backend push event. The
|
||||
// gateway calls it only for a recipient with no live in-app stream (so the
|
||||
// platform push never duplicates in-app delivery). The connector renders a
|
||||
@@ -79,6 +85,16 @@ func (c *telegramClient) ValidateInitData(ctx context.Context, in *ValidateInitD
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *telegramClient) ValidateLoginWidget(ctx context.Context, in *ValidateLoginWidgetRequest, opts ...grpc.CallOption) (*ValidateLoginWidgetResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(ValidateLoginWidgetResponse)
|
||||
err := c.cc.Invoke(ctx, Telegram_ValidateLoginWidget_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *telegramClient) Notify(ctx context.Context, in *NotifyRequest, opts ...grpc.CallOption) (*NotifyResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(NotifyResponse)
|
||||
@@ -119,6 +135,11 @@ type TelegramServer interface {
|
||||
// the authenticated user. The gateway calls it during the auth.telegram edge
|
||||
// operation, then provisions the session through the backend internal API.
|
||||
ValidateInitData(context.Context, *ValidateInitDataRequest) (*ValidateInitDataResponse, error)
|
||||
// ValidateLoginWidget verifies Telegram Login Widget authorization data (the web
|
||||
// sign-in flow, HMAC under SHA-256(bot_token)) and returns the authenticated
|
||||
// user. The gateway calls it during the link.telegram edge operation to attach a
|
||||
// Telegram identity to an existing account (Stage 11).
|
||||
ValidateLoginWidget(context.Context, *ValidateLoginWidgetRequest) (*ValidateLoginWidgetResponse, error)
|
||||
// Notify delivers an out-of-app notification for a backend push event. The
|
||||
// gateway calls it only for a recipient with no live in-app stream (so the
|
||||
// platform push never duplicates in-app delivery). The connector renders a
|
||||
@@ -145,6 +166,9 @@ type UnimplementedTelegramServer struct{}
|
||||
func (UnimplementedTelegramServer) ValidateInitData(context.Context, *ValidateInitDataRequest) (*ValidateInitDataResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ValidateInitData not implemented")
|
||||
}
|
||||
func (UnimplementedTelegramServer) ValidateLoginWidget(context.Context, *ValidateLoginWidgetRequest) (*ValidateLoginWidgetResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ValidateLoginWidget not implemented")
|
||||
}
|
||||
func (UnimplementedTelegramServer) Notify(context.Context, *NotifyRequest) (*NotifyResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Notify not implemented")
|
||||
}
|
||||
@@ -193,6 +217,24 @@ func _Telegram_ValidateInitData_Handler(srv interface{}, ctx context.Context, de
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Telegram_ValidateLoginWidget_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ValidateLoginWidgetRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(TelegramServer).ValidateLoginWidget(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Telegram_ValidateLoginWidget_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(TelegramServer).ValidateLoginWidget(ctx, req.(*ValidateLoginWidgetRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Telegram_Notify_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(NotifyRequest)
|
||||
if err := dec(in); err != nil {
|
||||
@@ -258,6 +300,10 @@ var Telegram_ServiceDesc = grpc.ServiceDesc{
|
||||
MethodName: "ValidateInitData",
|
||||
Handler: _Telegram_ValidateInitData_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ValidateLoginWidget",
|
||||
Handler: _Telegram_ValidateLoginWidget_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Notify",
|
||||
Handler: _Telegram_Notify_Handler,
|
||||
|
||||
Reference in New Issue
Block a user