Add better messages for send response errors

This commit is contained in:
Tulir Asokan 2024-06-07 18:24:25 +03:00
parent 2660e3fa91
commit 18f012d2d0
16 changed files with 64 additions and 26 deletions

View file

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.31.0 // protoc-gen-go v1.34.1
// protoc v3.21.12 // protoc v3.21.12
// source: authentication.proto // source: authentication.proto

View file

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.31.0 // protoc-gen-go v1.34.1
// protoc v3.21.12 // protoc v3.21.12
// source: client.proto // source: client.proto
@ -2647,7 +2647,8 @@ type SendMessageResponse struct {
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
Status SendMessageResponse_Status `protobuf:"varint,3,opt,name=status,proto3,enum=client.SendMessageResponse_Status" json:"status,omitempty"` GoogleAccountSwitch *AccountChangeOrSomethingEvent `protobuf:"bytes,2,opt,name=googleAccountSwitch,proto3" json:"googleAccountSwitch,omitempty"`
Status SendMessageResponse_Status `protobuf:"varint,3,opt,name=status,proto3,enum=client.SendMessageResponse_Status" json:"status,omitempty"`
} }
func (x *SendMessageResponse) Reset() { func (x *SendMessageResponse) Reset() {
@ -2682,6 +2683,13 @@ func (*SendMessageResponse) Descriptor() ([]byte, []int) {
return file_client_proto_rawDescGZIP(), []int{41} return file_client_proto_rawDescGZIP(), []int{41}
} }
func (x *SendMessageResponse) GetGoogleAccountSwitch() *AccountChangeOrSomethingEvent {
if x != nil {
return x.GoogleAccountSwitch
}
return nil
}
func (x *SendMessageResponse) GetStatus() SendMessageResponse_Status { func (x *SendMessageResponse) GetStatus() SendMessageResponse_Status {
if x != nil { if x != nil {
return x.Status return x.Status
@ -3289,7 +3297,8 @@ var file_client_proto_goTypes = []interface{}{
(*SIMPayload)(nil), // 67: settings.SIMPayload (*SIMPayload)(nil), // 67: settings.SIMPayload
(*MessageInfo)(nil), // 68: conversations.MessageInfo (*MessageInfo)(nil), // 68: conversations.MessageInfo
(*MessageContent)(nil), // 69: conversations.MessageContent (*MessageContent)(nil), // 69: conversations.MessageContent
(*ReactionData)(nil), // 70: conversations.ReactionData (*AccountChangeOrSomethingEvent)(nil), // 70: events.AccountChangeOrSomethingEvent
(*ReactionData)(nil), // 71: conversations.ReactionData
} }
var file_client_proto_depIdxs = []int32{ var file_client_proto_depIdxs = []int32{
58, // 0: client.ReceiveMessagesRequest.auth:type_name -> authentication.AuthMessage 58, // 0: client.ReceiveMessagesRequest.auth:type_name -> authentication.AuthMessage
@ -3329,19 +3338,20 @@ var file_client_proto_depIdxs = []int32{
46, // 34: client.MessagePayload.messagePayloadContent:type_name -> client.MessagePayloadContent 46, // 34: client.MessagePayload.messagePayloadContent:type_name -> client.MessagePayloadContent
68, // 35: client.MessagePayload.messageInfo:type_name -> conversations.MessageInfo 68, // 35: client.MessagePayload.messageInfo:type_name -> conversations.MessageInfo
69, // 36: client.MessagePayloadContent.messageContent:type_name -> conversations.MessageContent 69, // 36: client.MessagePayloadContent.messageContent:type_name -> conversations.MessageContent
4, // 37: client.SendMessageResponse.status:type_name -> client.SendMessageResponse.Status 70, // 37: client.SendMessageResponse.googleAccountSwitch:type_name -> events.AccountChangeOrSomethingEvent
70, // 38: client.SendReactionRequest.reactionData:type_name -> conversations.ReactionData 4, // 38: client.SendMessageResponse.status:type_name -> client.SendMessageResponse.Status
5, // 39: client.SendReactionRequest.action:type_name -> client.SendReactionRequest.Action 71, // 39: client.SendReactionRequest.reactionData:type_name -> conversations.ReactionData
67, // 40: client.SendReactionRequest.SIMPayload:type_name -> settings.SIMPayload 5, // 40: client.SendReactionRequest.action:type_name -> client.SendReactionRequest.Action
57, // 41: client.TypingUpdateRequest.data:type_name -> client.TypingUpdateRequest.Data 67, // 41: client.SendReactionRequest.SIMPayload:type_name -> settings.SIMPayload
52, // 42: client.ReceiveMessagesRequest.UnknownEmptyObject2.unknown:type_name -> client.ReceiveMessagesRequest.UnknownEmptyObject1 57, // 42: client.TypingUpdateRequest.data:type_name -> client.TypingUpdateRequest.Data
60, // 43: client.AckMessageRequest.Message.device:type_name -> authentication.Device 52, // 43: client.ReceiveMessagesRequest.UnknownEmptyObject2.unknown:type_name -> client.ReceiveMessagesRequest.UnknownEmptyObject1
18, // 44: client.GetThumbnailResponse.Thumbnail.data:type_name -> client.ThumbnailData 60, // 44: client.AckMessageRequest.Message.device:type_name -> authentication.Device
45, // [45:45] is the sub-list for method output_type 18, // 45: client.GetThumbnailResponse.Thumbnail.data:type_name -> client.ThumbnailData
45, // [45:45] is the sub-list for method input_type 46, // [46:46] is the sub-list for method output_type
45, // [45:45] is the sub-list for extension type_name 46, // [46:46] is the sub-list for method input_type
45, // [45:45] is the sub-list for extension extendee 46, // [46:46] is the sub-list for extension type_name
0, // [0:45] is the sub-list for field type_name 46, // [46:46] is the sub-list for extension extendee
0, // [0:46] is the sub-list for field type_name
} }
func init() { file_client_proto_init() } func init() { file_client_proto_init() }
@ -3353,6 +3363,7 @@ func file_client_proto_init() {
file_authentication_proto_init() file_authentication_proto_init()
file_settings_proto_init() file_settings_proto_init()
file_util_proto_init() file_util_proto_init()
file_events_proto_init()
if !protoimpl.UnsafeEnabled { if !protoimpl.UnsafeEnabled {
file_client_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { file_client_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*NotifyDittoActivityRequest); i { switch v := v.(*NotifyDittoActivityRequest); i {

Binary file not shown.

View file

@ -7,6 +7,7 @@ import "conversations.proto";
import "authentication.proto"; import "authentication.proto";
import "settings.proto"; import "settings.proto";
import "util.proto"; import "util.proto";
import "events.proto";
message NotifyDittoActivityRequest { message NotifyDittoActivityRequest {
// This is not actually a boolean: after logging out, field 2 has value 2, and field 3 has value 1. // This is not actually a boolean: after logging out, field 2 has value 2, and field 3 has value 1.
@ -283,6 +284,7 @@ message SendMessageResponse {
FAILURE_3 = 3; FAILURE_3 = 3;
FAILURE_4 = 4; // not default sms app? FAILURE_4 = 4; // not default sms app?
} }
events.AccountChangeOrSomethingEvent googleAccountSwitch = 2;
Status status = 3; Status status = 3;
} }

View file

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.31.0 // protoc-gen-go v1.34.1
// protoc v3.21.12 // protoc v3.21.12
// source: config.proto // source: config.proto

View file

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.31.0 // protoc-gen-go v1.34.1
// protoc v3.21.12 // protoc v3.21.12
// source: conversations.proto // source: conversations.proto

View file

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.31.0 // protoc-gen-go v1.34.1
// protoc v3.21.12 // protoc v3.21.12
// source: events.proto // source: events.proto

View file

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.31.0 // protoc-gen-go v1.34.1
// protoc v3.21.12 // protoc v3.21.12
// source: pblite.proto // source: pblite.proto

View file

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.31.0 // protoc-gen-go v1.34.1
// protoc v3.21.12 // protoc v3.21.12
// source: rpc.proto // source: rpc.proto
@ -123,6 +123,7 @@ const (
ActionType_CREATE_GAIA_PAIRING_CLIENT_FINISHED ActionType = 45 ActionType_CREATE_GAIA_PAIRING_CLIENT_FINISHED ActionType = 45
ActionType_UNPAIR_GAIA_PAIRING ActionType = 46 ActionType_UNPAIR_GAIA_PAIRING ActionType = 46
ActionType_CANCEL_GAIA_PAIRING ActionType = 47 ActionType_CANCEL_GAIA_PAIRING ActionType = 47
ActionType_PREWARM ActionType = 48
) )
// Enum value maps for ActionType. // Enum value maps for ActionType.
@ -174,6 +175,7 @@ var (
45: "CREATE_GAIA_PAIRING_CLIENT_FINISHED", 45: "CREATE_GAIA_PAIRING_CLIENT_FINISHED",
46: "UNPAIR_GAIA_PAIRING", 46: "UNPAIR_GAIA_PAIRING",
47: "CANCEL_GAIA_PAIRING", 47: "CANCEL_GAIA_PAIRING",
48: "PREWARM",
} }
ActionType_value = map[string]int32{ ActionType_value = map[string]int32{
"UNSPECIFIED": 0, "UNSPECIFIED": 0,
@ -222,6 +224,7 @@ var (
"CREATE_GAIA_PAIRING_CLIENT_FINISHED": 45, "CREATE_GAIA_PAIRING_CLIENT_FINISHED": 45,
"UNPAIR_GAIA_PAIRING": 46, "UNPAIR_GAIA_PAIRING": 46,
"CANCEL_GAIA_PAIRING": 47, "CANCEL_GAIA_PAIRING": 47,
"PREWARM": 48,
} }
) )

Binary file not shown.

View file

@ -161,6 +161,7 @@ enum ActionType {
CREATE_GAIA_PAIRING_CLIENT_FINISHED = 45; CREATE_GAIA_PAIRING_CLIENT_FINISHED = 45;
UNPAIR_GAIA_PAIRING = 46; UNPAIR_GAIA_PAIRING = 46;
CANCEL_GAIA_PAIRING = 47; CANCEL_GAIA_PAIRING = 47;
PREWARM = 48;
} }
enum MessageType { enum MessageType {

View file

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.31.0 // protoc-gen-go v1.34.1
// protoc v3.21.12 // protoc v3.21.12
// source: settings.proto // source: settings.proto

View file

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.31.0 // protoc-gen-go v1.34.1
// protoc v3.21.12 // protoc v3.21.12
// source: ukey.proto // source: ukey.proto

View file

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.31.0 // protoc-gen-go v1.34.1
// protoc v3.21.12 // protoc v3.21.12
// source: util.proto // source: util.proto

View file

@ -86,6 +86,7 @@ func (ose OutgoingStatusError) Is(other error) bool {
func errorToStatusReason(err error) (reason event.MessageStatusReason, status event.MessageStatus, isCertain, sendNotice bool, humanMessage string) { func errorToStatusReason(err error) (reason event.MessageStatusReason, status event.MessageStatus, isCertain, sendNotice bool, humanMessage string) {
var ose OutgoingStatusError var ose OutgoingStatusError
var rse *responseStatusError
switch { switch {
case errors.Is(err, errUnexpectedParsedContentType), case errors.Is(err, errUnexpectedParsedContentType),
errors.Is(err, errUnknownMsgType): errors.Is(err, errUnknownMsgType):
@ -104,6 +105,8 @@ func errorToStatusReason(err error) (reason event.MessageStatusReason, status ev
return event.MessageStatusTooOld, event.MessageStatusRetriable, false, true, "sending the message is taking long; is your phone online?" return event.MessageStatusTooOld, event.MessageStatusRetriable, false, true, "sending the message is taking long; is your phone online?"
case errors.Is(err, errTargetNotFound): case errors.Is(err, errTargetNotFound):
return event.MessageStatusGenericError, event.MessageStatusFail, true, false, "" return event.MessageStatusGenericError, event.MessageStatusFail, true, false, ""
case errors.As(err, &rse):
return event.MessageStatusNetworkError, event.MessageStatusRetriable, true, true, rse.Error()
case errors.As(err, &ose): case errors.As(err, &ose):
return event.MessageStatusNetworkError, event.MessageStatusFail, true, true, ose.HumanError() return event.MessageStatusNetworkError, event.MessageStatusFail, true, true, ose.HumanError()
default: default:

View file

@ -2049,6 +2049,24 @@ func (portal *Portal) reuploadMedia(ctx context.Context, sender *User, content *
return resp, nil return resp, nil
} }
type responseStatusError gmproto.SendMessageResponse
func (rse *responseStatusError) Error() string {
switch rse.Status {
case 0:
if rse.GoogleAccountSwitch != nil && strings.ContainsRune(rse.GoogleAccountSwitch.GetAccount(), '@') {
return "Switch back to QR pairing or log in with Google account to send messages"
}
case gmproto.SendMessageResponse_FAILURE_2:
return "Unknown permanent error"
case gmproto.SendMessageResponse_FAILURE_3:
return "Unknown temporary error"
case gmproto.SendMessageResponse_FAILURE_4:
return "Google Messages is not your default SMS app"
}
return fmt.Sprintf("Unrecognized response status %d", rse.Status)
}
func (portal *Portal) HandleMatrixMessage(sender *User, evt *event.Event, timings messageTimings) { func (portal *Portal) HandleMatrixMessage(sender *User, evt *event.Event, timings messageTimings) {
ms := metricSender{portal: portal, timings: &timings} ms := metricSender{portal: portal, timings: &timings}
@ -2093,7 +2111,7 @@ func (portal *Portal) HandleMatrixMessage(sender *User, evt *event.Event, timing
} else if resp.Status != gmproto.SendMessageResponse_SUCCESS { } else if resp.Status != gmproto.SendMessageResponse_SUCCESS {
outgoingMsg.Errored = true outgoingMsg.Errored = true
outgoingMsg.Acked = true outgoingMsg.Acked = true
go ms.sendMessageMetrics(ctx, sender, evt, fmt.Errorf("response status %d", resp.Status), "Error sending", true) go ms.sendMessageMetrics(ctx, sender, evt, (*responseStatusError)(resp), "Error sending", true)
} else { } else {
outgoingMsg.Acked = true outgoingMsg.Acked = true
go ms.sendMessageMetrics(ctx, sender, evt, nil, "", true) go ms.sendMessageMetrics(ctx, sender, evt, nil, "", true)