From e258e98ba59d39027d3ee7b4c9e8dd3a3aba723d Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 17 Jun 2021 18:24:54 +0100 Subject: [PATCH] add ability to send sms in emoji (#165) --- emoji/handler/emoji.go | 58 ++++++++++ emoji/proto/emoji.pb.go | 199 ++++++++++++++++++++++++++++++---- emoji/proto/emoji.pb.micro.go | 17 +++ emoji/proto/emoji.proto | 16 +++ emoji/publicapi.json | 5 +- go.mod | 6 + go.sum | 12 ++ 7 files changed, 291 insertions(+), 22 deletions(-) diff --git a/emoji/handler/emoji.go b/emoji/handler/emoji.go index e60130a..49127cb 100644 --- a/emoji/handler/emoji.go +++ b/emoji/handler/emoji.go @@ -2,8 +2,12 @@ package handler import ( "context" + "net/url" + "github.com/kevinburke/twilio-go" "github.com/enescakir/emoji" + "github.com/micro/micro/v3/service/config" + "github.com/micro/micro/v3/service/logger" "github.com/micro/micro/v3/service/errors" pb "github.com/micro/services/emoji/proto" ) @@ -32,3 +36,57 @@ func (e *Emoji) Print(ctx context.Context, req *pb.PrintRequest, rsp *pb.PrintRe rsp.Text = emoji.Parse(req.Text) return nil } + +func (e *Emoji) Send(ctx context.Context, req *pb.SendRequest, rsp *pb.SendResponse) error { + if len(req.From) == 0 { + return errors.BadRequest("emoji.send", "require from field") + } + if len(req.To) == 0 { + return errors.BadRequest("emoji.send", "require to field") + } + if len(req.Message) == 0 { + return errors.BadRequest("emoji.send", "message is blank") + } + + v, err := config.Get("twilio.sid") + if err != nil { + logger.Error("Failed to get twilio.sid config") + return errors.InternalServerError("emoji.send", "failed to send message") + } + sid := v.String("") + + v, err = config.Get("twilio.token") + if err != nil { + logger.Error("Failed to get twilio.token config") + return errors.InternalServerError("emoji.send", "failed to send message") + } + token := v.String("") + + v, err = config.Get("twilio.number") + if err != nil { + logger.Error("Failed to get twilio.number config") + return errors.InternalServerError("emoji.send", "failed to send message") + } + number := v.String("") + + message := emoji.Parse(req.Message) + message += " Sent from " + req.From + + vals := url.Values{} + vals.Set("Body", message) + vals.Set("From", number) + vals.Set("To", req.To) + // non configurable and must match publicapi.json + vals.Set("MaxPrice", "0.01") + + client := twilio.NewClient(sid, token, nil) + _, err = client.Messages.Create(ctx, vals) + if err != nil { + logger.Errorf("Failed to send message: %v", err) + return errors.InternalServerError("emoji.send", "failed to send message: %v", err.Error()) + } + + rsp.Success = true + + return nil +} diff --git a/emoji/proto/emoji.pb.go b/emoji/proto/emoji.pb.go index 87164f5..f660be7 100644 --- a/emoji/proto/emoji.pb.go +++ b/emoji/proto/emoji.pb.go @@ -20,12 +20,13 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) -// Find an alias and return the emoji +// Find an emoji by its alias e.g :beer: type FindRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // the alias code e.g :beer: Alias string `protobuf:"bytes,1,opt,name=alias,proto3" json:"alias,omitempty"` } @@ -73,6 +74,7 @@ type FindResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // the unicode emoji 🍺 Emoji string `protobuf:"bytes,2,opt,name=emoji,proto3" json:"emoji,omitempty"` } @@ -121,6 +123,7 @@ type FlagRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // country code e.g GB Code string `protobuf:"bytes,1,opt,name=code,proto3" json:"code,omitempty"` } @@ -168,6 +171,7 @@ type FlagResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // the emoji flag Flag string `protobuf:"bytes,2,opt,name=flag,proto3" json:"flag,omitempty"` } @@ -308,6 +312,121 @@ func (x *PrintResponse) GetText() string { return "" } +// Send an emoji to anyone via SMS +type SendRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // who the message is from e.g Alice + From string `protobuf:"bytes,1,opt,name=from,proto3" json:"from,omitempty"` + // phone number to send to (including international dialing code) + To string `protobuf:"bytes,2,opt,name=to,proto3" json:"to,omitempty"` + // message to send including emoji aliases + Message string `protobuf:"bytes,3,opt,name=message,proto3" json:"message,omitempty"` +} + +func (x *SendRequest) Reset() { + *x = SendRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_emoji_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SendRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SendRequest) ProtoMessage() {} + +func (x *SendRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_emoji_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 SendRequest.ProtoReflect.Descriptor instead. +func (*SendRequest) Descriptor() ([]byte, []int) { + return file_proto_emoji_proto_rawDescGZIP(), []int{6} +} + +func (x *SendRequest) GetFrom() string { + if x != nil { + return x.From + } + return "" +} + +func (x *SendRequest) GetTo() string { + if x != nil { + return x.To + } + return "" +} + +func (x *SendRequest) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +type SendResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // whether or not it succeeded + Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` +} + +func (x *SendResponse) Reset() { + *x = SendResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_emoji_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SendResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SendResponse) ProtoMessage() {} + +func (x *SendResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_emoji_proto_msgTypes[7] + 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 SendResponse.ProtoReflect.Descriptor instead. +func (*SendResponse) Descriptor() ([]byte, []int) { + return file_proto_emoji_proto_rawDescGZIP(), []int{7} +} + +func (x *SendResponse) GetSuccess() bool { + if x != nil { + return x.Success + } + return false +} + var File_proto_emoji_proto protoreflect.FileDescriptor var file_proto_emoji_proto_rawDesc = []byte{ @@ -326,19 +445,29 @@ var file_proto_emoji_proto_rawDesc = []byte{ 0x74, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x22, 0x23, 0x0a, 0x0d, 0x50, 0x72, 0x69, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x74, 0x65, 0x78, 0x74, 0x32, 0xa3, 0x01, 0x0a, 0x05, 0x45, 0x6d, 0x6f, 0x6a, 0x69, 0x12, - 0x31, 0x0a, 0x04, 0x46, 0x69, 0x6e, 0x64, 0x12, 0x12, 0x2e, 0x65, 0x6d, 0x6f, 0x6a, 0x69, 0x2e, - 0x46, 0x69, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x65, 0x6d, - 0x6f, 0x6a, 0x69, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x00, 0x12, 0x31, 0x0a, 0x04, 0x46, 0x6c, 0x61, 0x67, 0x12, 0x12, 0x2e, 0x65, 0x6d, 0x6f, - 0x6a, 0x69, 0x2e, 0x46, 0x6c, 0x61, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, - 0x2e, 0x65, 0x6d, 0x6f, 0x6a, 0x69, 0x2e, 0x46, 0x6c, 0x61, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x34, 0x0a, 0x05, 0x50, 0x72, 0x69, 0x6e, 0x74, 0x12, 0x13, - 0x2e, 0x65, 0x6d, 0x6f, 0x6a, 0x69, 0x2e, 0x50, 0x72, 0x69, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x65, 0x6d, 0x6f, 0x6a, 0x69, 0x2e, 0x50, 0x72, 0x69, 0x6e, - 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x0f, 0x5a, 0x0d, 0x2e, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x3b, 0x65, 0x6d, 0x6f, 0x6a, 0x69, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, + 0x04, 0x74, 0x65, 0x78, 0x74, 0x22, 0x4b, 0x0a, 0x0b, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x6f, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x74, 0x6f, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x22, 0x28, 0x0a, 0x0c, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 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, 0x32, 0xd6, 0x01, 0x0a, + 0x05, 0x45, 0x6d, 0x6f, 0x6a, 0x69, 0x12, 0x31, 0x0a, 0x04, 0x46, 0x69, 0x6e, 0x64, 0x12, 0x12, + 0x2e, 0x65, 0x6d, 0x6f, 0x6a, 0x69, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x65, 0x6d, 0x6f, 0x6a, 0x69, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x31, 0x0a, 0x04, 0x46, 0x6c, 0x61, + 0x67, 0x12, 0x12, 0x2e, 0x65, 0x6d, 0x6f, 0x6a, 0x69, 0x2e, 0x46, 0x6c, 0x61, 0x67, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x65, 0x6d, 0x6f, 0x6a, 0x69, 0x2e, 0x46, 0x6c, + 0x61, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x34, 0x0a, 0x05, + 0x50, 0x72, 0x69, 0x6e, 0x74, 0x12, 0x13, 0x2e, 0x65, 0x6d, 0x6f, 0x6a, 0x69, 0x2e, 0x50, 0x72, + 0x69, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x65, 0x6d, 0x6f, + 0x6a, 0x69, 0x2e, 0x50, 0x72, 0x69, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x00, 0x12, 0x31, 0x0a, 0x04, 0x53, 0x65, 0x6e, 0x64, 0x12, 0x12, 0x2e, 0x65, 0x6d, 0x6f, + 0x6a, 0x69, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, + 0x2e, 0x65, 0x6d, 0x6f, 0x6a, 0x69, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x0f, 0x5a, 0x0d, 0x2e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x3b, 0x65, 0x6d, 0x6f, 0x6a, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -353,7 +482,7 @@ func file_proto_emoji_proto_rawDescGZIP() []byte { return file_proto_emoji_proto_rawDescData } -var file_proto_emoji_proto_msgTypes = make([]protoimpl.MessageInfo, 6) +var file_proto_emoji_proto_msgTypes = make([]protoimpl.MessageInfo, 8) var file_proto_emoji_proto_goTypes = []interface{}{ (*FindRequest)(nil), // 0: emoji.FindRequest (*FindResponse)(nil), // 1: emoji.FindResponse @@ -361,16 +490,20 @@ var file_proto_emoji_proto_goTypes = []interface{}{ (*FlagResponse)(nil), // 3: emoji.FlagResponse (*PrintRequest)(nil), // 4: emoji.PrintRequest (*PrintResponse)(nil), // 5: emoji.PrintResponse + (*SendRequest)(nil), // 6: emoji.SendRequest + (*SendResponse)(nil), // 7: emoji.SendResponse } var file_proto_emoji_proto_depIdxs = []int32{ 0, // 0: emoji.Emoji.Find:input_type -> emoji.FindRequest 2, // 1: emoji.Emoji.Flag:input_type -> emoji.FlagRequest 4, // 2: emoji.Emoji.Print:input_type -> emoji.PrintRequest - 1, // 3: emoji.Emoji.Find:output_type -> emoji.FindResponse - 3, // 4: emoji.Emoji.Flag:output_type -> emoji.FlagResponse - 5, // 5: emoji.Emoji.Print:output_type -> emoji.PrintResponse - 3, // [3:6] is the sub-list for method output_type - 0, // [0:3] is the sub-list for method input_type + 6, // 3: emoji.Emoji.Send:input_type -> emoji.SendRequest + 1, // 4: emoji.Emoji.Find:output_type -> emoji.FindResponse + 3, // 5: emoji.Emoji.Flag:output_type -> emoji.FlagResponse + 5, // 6: emoji.Emoji.Print:output_type -> emoji.PrintResponse + 7, // 7: emoji.Emoji.Send:output_type -> emoji.SendResponse + 4, // [4:8] is the sub-list for method output_type + 0, // [0:4] 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 @@ -454,6 +587,30 @@ func file_proto_emoji_proto_init() { return nil } } + file_proto_emoji_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SendRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_emoji_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SendResponse); 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{ @@ -461,7 +618,7 @@ func file_proto_emoji_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proto_emoji_proto_rawDesc, NumEnums: 0, - NumMessages: 6, + NumMessages: 8, NumExtensions: 0, NumServices: 1, }, diff --git a/emoji/proto/emoji.pb.micro.go b/emoji/proto/emoji.pb.micro.go index 57dcbac..88e8489 100644 --- a/emoji/proto/emoji.pb.micro.go +++ b/emoji/proto/emoji.pb.micro.go @@ -45,6 +45,7 @@ type EmojiService interface { Find(ctx context.Context, in *FindRequest, opts ...client.CallOption) (*FindResponse, error) Flag(ctx context.Context, in *FlagRequest, opts ...client.CallOption) (*FlagResponse, error) Print(ctx context.Context, in *PrintRequest, opts ...client.CallOption) (*PrintResponse, error) + Send(ctx context.Context, in *SendRequest, opts ...client.CallOption) (*SendResponse, error) } type emojiService struct { @@ -89,12 +90,23 @@ func (c *emojiService) Print(ctx context.Context, in *PrintRequest, opts ...clie return out, nil } +func (c *emojiService) Send(ctx context.Context, in *SendRequest, opts ...client.CallOption) (*SendResponse, error) { + req := c.c.NewRequest(c.name, "Emoji.Send", in) + out := new(SendResponse) + err := c.c.Call(ctx, req, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // Server API for Emoji service type EmojiHandler interface { Find(context.Context, *FindRequest, *FindResponse) error Flag(context.Context, *FlagRequest, *FlagResponse) error Print(context.Context, *PrintRequest, *PrintResponse) error + Send(context.Context, *SendRequest, *SendResponse) error } func RegisterEmojiHandler(s server.Server, hdlr EmojiHandler, opts ...server.HandlerOption) error { @@ -102,6 +114,7 @@ func RegisterEmojiHandler(s server.Server, hdlr EmojiHandler, opts ...server.Han Find(ctx context.Context, in *FindRequest, out *FindResponse) error Flag(ctx context.Context, in *FlagRequest, out *FlagResponse) error Print(ctx context.Context, in *PrintRequest, out *PrintResponse) error + Send(ctx context.Context, in *SendRequest, out *SendResponse) error } type Emoji struct { emoji @@ -125,3 +138,7 @@ func (h *emojiHandler) Flag(ctx context.Context, in *FlagRequest, out *FlagRespo func (h *emojiHandler) Print(ctx context.Context, in *PrintRequest, out *PrintResponse) error { return h.EmojiHandler.Print(ctx, in, out) } + +func (h *emojiHandler) Send(ctx context.Context, in *SendRequest, out *SendResponse) error { + return h.EmojiHandler.Send(ctx, in, out) +} diff --git a/emoji/proto/emoji.proto b/emoji/proto/emoji.proto index 533cfcf..7292834 100644 --- a/emoji/proto/emoji.proto +++ b/emoji/proto/emoji.proto @@ -8,6 +8,7 @@ service Emoji { rpc Find(FindRequest) returns (FindResponse) {} rpc Flag(FlagRequest) returns (FlagResponse) {} rpc Print(PrintRequest) returns (PrintResponse) {} + rpc Send(SendRequest) returns (SendResponse) {} } // Find an emoji by its alias e.g :beer: @@ -43,3 +44,18 @@ message PrintResponse { // text with rendered emojis string text = 1; } + +// Send an emoji to anyone via SMS +message SendRequest { + // who the message is from e.g Alice + string from = 1; + // phone number to send to (including international dialing code) + string to = 2; + // message to send including emoji aliases + string message = 3; +} + +message SendResponse { + // whether or not it succeeded + bool success = 1; +} diff --git a/emoji/publicapi.json b/emoji/publicapi.json index 73f4abf..a262a3a 100644 --- a/emoji/publicapi.json +++ b/emoji/publicapi.json @@ -1,5 +1,8 @@ { "name": "emoji", "icon": "😀", - "category": "web" + "category": "web", + "pricing": { + "Emoji.Send": 100 + } } diff --git a/go.mod b/go.mod index b91b204..0df7529 100644 --- a/go.mod +++ b/go.mod @@ -20,6 +20,10 @@ require ( github.com/hailocab/go-geoindex v0.0.0-20160127134810-64631bfe9711 github.com/hashicorp/golang-lru v0.5.3 github.com/jackc/pgx/v4 v4.10.1 + github.com/kevinburke/go-types v0.0.0-20201208005256-aee49f568a20 // indirect + github.com/kevinburke/go.uuid v1.2.0 // indirect + github.com/kevinburke/rest v0.0.0-20210506044642-5611499aa33c // indirect + github.com/kevinburke/twilio-go v0.0.0-20210327194925-1623146bcf73 github.com/lib/pq v1.9.0 // indirect github.com/mattheath/base62 v0.0.0-20150408093626-b80cdc656a7a // indirect github.com/mattheath/kala v0.0.0-20171219141654-d6276794bf0e @@ -35,6 +39,8 @@ require ( github.com/stoewer/go-strcase v1.2.0 github.com/stretchr/testify v1.7.0 github.com/teris-io/shortid v0.0.0-20171029131806-771a37caa5cf + github.com/ttacon/builder v0.0.0-20170518171403-c099f663e1c2 // indirect + github.com/ttacon/libphonenumber v1.2.1 // indirect github.com/uber/jaeger-client-go v2.29.1+incompatible // indirect github.com/uber/jaeger-lib v2.4.1+incompatible // indirect go.opencensus.io v0.22.4 // indirect diff --git a/go.sum b/go.sum index 8b45094..6f50310 100644 --- a/go.sum +++ b/go.sum @@ -302,6 +302,14 @@ github.com/juju/fslock v0.0.0-20160525022230-4d5c94c67b4b h1:FQ7+9fxhyp82ks9vAuy github.com/juju/fslock v0.0.0-20160525022230-4d5c94c67b4b/go.mod h1:HMcgvsgd0Fjj4XXDkbjdmlbI505rUPBs6WBMYg2pXks= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= +github.com/kevinburke/go-types v0.0.0-20201208005256-aee49f568a20 h1:Tux1t20gPWp4zkjCCdv2rLAwp+T3jCEROsEuvXp50FI= +github.com/kevinburke/go-types v0.0.0-20201208005256-aee49f568a20/go.mod h1:/Pk5i/SqYdYv1cie5wGwoZ4P6TpgMi+Yf58mtJSHdOw= +github.com/kevinburke/go.uuid v1.2.0 h1:+1qP8NdkJfgOSTrrrUuA7h0djr1VY77HFXYjR+zUcUo= +github.com/kevinburke/go.uuid v1.2.0/go.mod h1:9gVngk1Hq1FjwewVAjsWEUT+xc6jP+p62CASaGmQ0NQ= +github.com/kevinburke/rest v0.0.0-20210506044642-5611499aa33c h1:hnbwWED5rIu+UaMkLR3JtnscMVGqp35lfzQwLuZAAUY= +github.com/kevinburke/rest v0.0.0-20210506044642-5611499aa33c/go.mod h1:pD+iEcdAGVXld5foVN4e24zb/6fnb60tgZPZ3P/3T/I= +github.com/kevinburke/twilio-go v0.0.0-20210327194925-1623146bcf73 h1:PSsFm2SRpq9LnaRHLz4u9ZZ3liWjgXM6OMxXE4/qlgY= +github.com/kevinburke/twilio-go v0.0.0-20210327194925-1623146bcf73/go.mod h1:Fm9alkN1/LPVY1eqD/psyMwPWE4VWl4P01/nTYZKzBk= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid v1.3.1 h1:5JNjFYYQrZeKRJ0734q51WCEEn2huer72Dc7K+R/b6s= @@ -497,6 +505,10 @@ github.com/teris-io/shortid v0.0.0-20171029131806-771a37caa5cf h1:Z2X3Os7oRzpdJ7 github.com/teris-io/shortid v0.0.0-20171029131806-771a37caa5cf/go.mod h1:M8agBzgqHIhgj7wEn9/0hJUZcrvt9VY+Ln+S1I5Mha0= github.com/timewasted/linode v0.0.0-20160829202747-37e84520dcf7/go.mod h1:imsgLplxEC/etjIhdr3dNzV3JeT27LbVu5pYWm0JCBY= github.com/transip/gotransip v0.0.0-20190812104329-6d8d9179b66f/go.mod h1:i0f4R4o2HM0m3DZYQWsj6/MEowD57VzoH0v3d7igeFY= +github.com/ttacon/builder v0.0.0-20170518171403-c099f663e1c2 h1:5u+EJUQiosu3JFX0XS0qTf5FznsMOzTjGqavBGuCbo0= +github.com/ttacon/builder v0.0.0-20170518171403-c099f663e1c2/go.mod h1:4kyMkleCiLkgY6z8gK5BkI01ChBtxR0ro3I1ZDcGM3w= +github.com/ttacon/libphonenumber v1.2.1 h1:fzOfY5zUADkCkbIafAed11gL1sW+bJ26p6zWLBMElR4= +github.com/ttacon/libphonenumber v1.2.1/go.mod h1:E0TpmdVMq5dyVlQ7oenAkhsLu86OkUl+yR4OAxyEg/M= github.com/uber-go/atomic v1.3.2/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g= github.com/uber/jaeger-client-go v2.29.1+incompatible h1:R9ec3zO3sGpzs0abd43Y+fBZRJ9uiH6lXyR/+u6brW4= github.com/uber/jaeger-client-go v2.29.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=