From c2a5373186a672e272030116f478a2dffff39cdb Mon Sep 17 00:00:00 2001 From: Jigar-f Date: Tue, 31 Oct 2023 17:46:20 +0530 Subject: [PATCH 01/17] Added Plan V3 API. --- internalsdk/apimodels/api.go | 52 ++++++++++++++++++++++-- internalsdk/apimodels/json_models.go | 59 ++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+), 4 deletions(-) diff --git a/internalsdk/apimodels/api.go b/internalsdk/apimodels/api.go index 9c5803c13..8a7d8979e 100644 --- a/internalsdk/apimodels/api.go +++ b/internalsdk/apimodels/api.go @@ -12,6 +12,13 @@ const ( baseUrl = "https://api.getiantem.org" userDetailUrl = baseUrl + "/user-data" userCreateUrl = baseUrl + "/user-create" + plansV3Url = baseUrl + "/plans-v3" +) + +const ( + headerDeviceId = "X-Lantern-Device-Id" + headerUserId = "X-Lantern-User-Id" + headerProToken = "X-Lantern-Pro-Token" ) var ( @@ -28,9 +35,9 @@ func FechUserDetail(deviceId string, userId string, token string) (*UserDetailRe } // Add headers - req.Header.Set("X-Lantern-Device-Id", deviceId) - req.Header.Set("X-Lantern-User-Id", userId) - req.Header.Set("X-Lantern-Pro-Token", token) + req.Header.Set(headerDeviceId, deviceId) + req.Header.Set(headerUserId, userId) + req.Header.Set(headerProToken, token) log.Debugf("Headers set") // Initialize a new http client @@ -75,7 +82,7 @@ func UserCreate(deviceId string, local string) (*UserResponse, error) { } // Add headers - req.Header.Set("X-Lantern-Device-Id", deviceId) + req.Header.Set(headerDeviceId, deviceId) log.Debugf("Headers set") // Initialize a new http client client := &http.Client{} @@ -94,3 +101,40 @@ func UserCreate(deviceId string, local string) (*UserResponse, error) { } return &userResponse, nil } + +func PlansV3(deviceId string, userId string, local string, token string, countryCode string) (*PlansResponse, error) { + req, err := http.NewRequest("GET", plansV3Url, nil) + if err != nil { + log.Errorf("Error creating plans request: %v", err) + return nil, err + } + //Add query params + q := req.URL.Query() + q.Add("locale", local) + q.Add("countrycode", countryCode) + req.URL.RawQuery = q.Encode() + + // Add headers + req.Header.Set(headerDeviceId, deviceId) + req.Header.Set(headerUserId, userId) + req.Header.Set(headerProToken, token) + log.Debugf("Plans Headers set") + // Initialize a new http client + client := &http.Client{} + // Send the request + resp, err := client.Do(req) + if err != nil { + log.Errorf("Error sending plans request: %v", err) + return nil, err + } + + defer resp.Body.Close() + + var plans PlansResponse + // Read and decode the response body + if err := json.NewDecoder(resp.Body).Decode(&plans); err != nil { + log.Errorf("Error decoding response body: %v", err) + return nil, err + } + return &plans, nil +} diff --git a/internalsdk/apimodels/json_models.go b/internalsdk/apimodels/json_models.go index 659764345..9d703cf70 100644 --- a/internalsdk/apimodels/json_models.go +++ b/internalsdk/apimodels/json_models.go @@ -42,3 +42,62 @@ type UserDevice struct { Name string `json:"name"` Created int64 `json:"created"` } + +// Plans Json struct + +type PlansResponse struct { + Plans []Plan `json:"plans"` + Providers Providers `json:"providers"` +} + +type Plan struct { + ID string `json:"id"` + Description string `json:"description"` + Duration Duration `json:"duration"` + Price Price `json:"price"` + ExpectedMonthlyPrice Price `json:"expectedMonthlyPrice"` + UsdPrice int64 `json:"usdPrice"` + UsdPrice1Y int64 `json:"usdPrice1Y"` + UsdPrice2Y int64 `json:"usdPrice2Y"` + RedeemFor RedeemFor `json:"redeemFor"` + RenewalBonus RedeemFor `json:"renewalBonus"` + RenewalBonusExpired RedeemFor `json:"renewalBonusExpired"` + RenewalBonusExpected RedeemFor `json:"renewalBonusExpected"` + Discount float64 `json:"discount"` + BestValue bool `json:"bestValue"` + Level string `json:"level"` +} + +type Duration struct { + Days int64 `json:"days"` + Months int64 `json:"months"` + Years int64 `json:"years"` +} + +type Price struct { + Usd int64 `json:"usd"` +} + +type RedeemFor struct { + Days int64 `json:"days"` + Months int64 `json:"months"` +} + +type Providers struct { + Android []Android `json:"android"` + Desktop []Android `json:"desktop"` +} + +type Android struct { + Method string `json:"method"` + Providers []Provider `json:"providers"` +} + +type Provider struct { + Name string `json:"name"` + Data *Data `json:"data,omitempty"` +} + +type Data struct { + PubKey string `json:"pubKey"` +} From 29a056d475ee605fc21983bd23654c3d841a3d01 Mon Sep 17 00:00:00 2001 From: Jigar-f Date: Tue, 31 Oct 2023 18:16:18 +0530 Subject: [PATCH 02/17] Enable Upgrade screen and start working on currency format. --- .../org/getlantern/lantern/model/ProPlan.java | 2 +- go.mod | 2 + go.sum | 5 + internalsdk/protos/vpn.pb.go | 189 ++++++++++++------ internalsdk/session_model.go | 63 ++++++ internalsdk/utils.go | 52 +++++ lib/account/account.dart | 51 +++-- lib/plans/plans.dart | 8 +- protos_shared/vpn.proto | 4 + 9 files changed, 280 insertions(+), 96 deletions(-) diff --git a/android/app/src/main/java/org/getlantern/lantern/model/ProPlan.java b/android/app/src/main/java/org/getlantern/lantern/model/ProPlan.java index 62afaf7fe..ba1cd6977 100644 --- a/android/app/src/main/java/org/getlantern/lantern/model/ProPlan.java +++ b/android/app/src/main/java/org/getlantern/lantern/model/ProPlan.java @@ -288,7 +288,7 @@ public String getFormattedPrice(Map price) { return getFormattedPrice(price, false); } - private String getFormattedPrice(Map price, boolean formatFloat) { + private String getFormattedPrice(Map price, boolean formatFloat) { final String formattedPrice; Long currencyPrice = price.get(currencyCode); if (currencyPrice == null) { diff --git a/go.mod b/go.mod index 9f8f0bfbe..e6030d066 100644 --- a/go.mod +++ b/go.mod @@ -22,6 +22,7 @@ replace github.com/google/netstack => github.com/getlantern/netstack v0.0.0-2022 replace github.com/eycorsican/go-tun2socks => github.com/getlantern/go-tun2socks v1.16.12-0.20201218023150-b68f09e5ae93 require ( + github.com/bojanz/currency v1.1.3 github.com/getlantern/appdir v0.0.0-20200615192800-a0ef1968f4da github.com/getlantern/autoupdate v0.0.0-20231030193554-30131726a6d9 github.com/getlantern/dnsgrab v0.0.0-20230822102054-7ff232ec3148 @@ -87,6 +88,7 @@ require ( github.com/bradfitz/iter v0.0.0-20191230175014-e8f45d346db8 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cockroachdb/apd/v3 v3.2.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dchest/siphash v1.2.1 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect diff --git a/go.sum b/go.sum index 49d9fd6c5..de502a4fb 100644 --- a/go.sum +++ b/go.sum @@ -197,6 +197,8 @@ github.com/bits-and-blooms/bitset v1.3.0 h1:h7mv5q31cthBTd7V4kLAZaIThj1e8vPGcSqp github.com/bits-and-blooms/bitset v1.3.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/bojanz/currency v1.1.3 h1:Ie8LYoMegQQlXH5Lq/gMRaWAD8J2/DYPewv+JV6UTPs= +github.com/bojanz/currency v1.1.3/go.mod h1:jNoZiJyRTqoU5DFoa+n+9lputxPUDa8Fz8BdDrW06Go= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/bradfitz/iter v0.0.0-20140124041915-454541ec3da2/go.mod h1:PyRFw1Lt2wKX4ZVSQ2mk+PeDa1rxyObEDlApuIsUKuo= github.com/bradfitz/iter v0.0.0-20190303215204-33e6a9893b0c/go.mod h1:PyRFw1Lt2wKX4ZVSQ2mk+PeDa1rxyObEDlApuIsUKuo= @@ -222,6 +224,8 @@ github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cockroachdb/apd/v3 v3.2.1 h1:U+8j7t0axsIgvQUqthuNm82HIrYXodOV2iWLWtEaIwg= +github.com/cockroachdb/apd/v3 v3.2.1/go.mod h1:klXJcjp+FffLTHlhIG69tezTDvdP065naDsHzKhYSqc= github.com/colinmarc/hdfs/v2 v2.1.1/go.mod h1:M3x+k8UKKmxtFu++uAZ0OtDU8jR3jnaZIAc6yK4Ue0c= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= @@ -764,6 +768,7 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/ledisdb/ledisdb v0.0.0-20200510135210-d35789ec47e6/go.mod h1:n931TsDuKuq+uX4v1fulaMbA/7ZLLhjc85h7chZGBCQ= +github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOSqcmlfs= github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= github.com/lispad/go-generics-tools v1.1.0 h1:mbSgcxdFVmpoyso1X/MJHXbSbSL3dD+qhRryyxk+/XY= diff --git a/internalsdk/protos/vpn.pb.go b/internalsdk/protos/vpn.pb.go index f4bd18172..0046bf2b4 100644 --- a/internalsdk/protos/vpn.pb.go +++ b/internalsdk/protos/vpn.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v4.23.3 +// protoc-gen-go v1.26.0 +// protoc v4.23.4 // source: protos_shared/vpn.proto package protos @@ -335,6 +335,53 @@ func (x *Devices) GetDevices() []*Device { return nil } +type Plans struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Plan []*Plan `protobuf:"bytes,1,rep,name=plan,proto3" json:"plan,omitempty"` +} + +func (x *Plans) Reset() { + *x = Plans{} + if protoimpl.UnsafeEnabled { + mi := &file_protos_shared_vpn_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Plans) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Plans) ProtoMessage() {} + +func (x *Plans) ProtoReflect() protoreflect.Message { + mi := &file_protos_shared_vpn_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 Plans.ProtoReflect.Descriptor instead. +func (*Plans) Descriptor() ([]byte, []int) { + return file_protos_shared_vpn_proto_rawDescGZIP(), []int{5} +} + +func (x *Plans) GetPlan() []*Plan { + if x != nil { + return x.Plan + } + return nil +} + type Plan struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -355,7 +402,7 @@ type Plan struct { func (x *Plan) Reset() { *x = Plan{} if protoimpl.UnsafeEnabled { - mi := &file_protos_shared_vpn_proto_msgTypes[5] + mi := &file_protos_shared_vpn_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -368,7 +415,7 @@ func (x *Plan) String() string { func (*Plan) ProtoMessage() {} func (x *Plan) ProtoReflect() protoreflect.Message { - mi := &file_protos_shared_vpn_proto_msgTypes[5] + mi := &file_protos_shared_vpn_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -381,7 +428,7 @@ func (x *Plan) ProtoReflect() protoreflect.Message { // Deprecated: Use Plan.ProtoReflect.Descriptor instead. func (*Plan) Descriptor() ([]byte, []int) { - return file_protos_shared_vpn_proto_rawDescGZIP(), []int{5} + return file_protos_shared_vpn_proto_rawDescGZIP(), []int{6} } func (x *Plan) GetId() string { @@ -465,7 +512,7 @@ type PaymentProviders struct { func (x *PaymentProviders) Reset() { *x = PaymentProviders{} if protoimpl.UnsafeEnabled { - mi := &file_protos_shared_vpn_proto_msgTypes[6] + mi := &file_protos_shared_vpn_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -478,7 +525,7 @@ func (x *PaymentProviders) String() string { func (*PaymentProviders) ProtoMessage() {} func (x *PaymentProviders) ProtoReflect() protoreflect.Message { - mi := &file_protos_shared_vpn_proto_msgTypes[6] + mi := &file_protos_shared_vpn_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -491,7 +538,7 @@ func (x *PaymentProviders) ProtoReflect() protoreflect.Message { // Deprecated: Use PaymentProviders.ProtoReflect.Descriptor instead. func (*PaymentProviders) Descriptor() ([]byte, []int) { - return file_protos_shared_vpn_proto_rawDescGZIP(), []int{6} + return file_protos_shared_vpn_proto_rawDescGZIP(), []int{7} } func (x *PaymentProviders) GetName() string { @@ -513,7 +560,7 @@ type PaymentMethod struct { func (x *PaymentMethod) Reset() { *x = PaymentMethod{} if protoimpl.UnsafeEnabled { - mi := &file_protos_shared_vpn_proto_msgTypes[7] + mi := &file_protos_shared_vpn_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -526,7 +573,7 @@ func (x *PaymentMethod) String() string { func (*PaymentMethod) ProtoMessage() {} func (x *PaymentMethod) ProtoReflect() protoreflect.Message { - mi := &file_protos_shared_vpn_proto_msgTypes[7] + mi := &file_protos_shared_vpn_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -539,7 +586,7 @@ func (x *PaymentMethod) ProtoReflect() protoreflect.Message { // Deprecated: Use PaymentMethod.ProtoReflect.Descriptor instead. func (*PaymentMethod) Descriptor() ([]byte, []int) { - return file_protos_shared_vpn_proto_rawDescGZIP(), []int{7} + return file_protos_shared_vpn_proto_rawDescGZIP(), []int{8} } func (x *PaymentMethod) GetMethod() string { @@ -589,43 +636,45 @@ var file_protos_shared_vpn_proto_rawDesc = []byte{ 0x52, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x22, 0x2c, 0x0a, 0x07, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x21, 0x0a, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x07, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x07, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x22, 0x98, 0x03, 0x0a, 0x04, 0x50, 0x6c, 0x61, 0x6e, - 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, - 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x65, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x62, 0x65, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x64, 0x50, 0x72, 0x69, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x08, 0x75, 0x73, 0x64, 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x26, 0x0a, 0x05, - 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x50, 0x6c, - 0x61, 0x6e, 0x2e, 0x50, 0x72, 0x69, 0x63, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x70, - 0x72, 0x69, 0x63, 0x65, 0x12, 0x36, 0x0a, 0x16, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x73, - 0x74, 0x42, 0x69, 0x6c, 0x6c, 0x65, 0x64, 0x4f, 0x6e, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x73, 0x74, 0x42, - 0x69, 0x6c, 0x6c, 0x65, 0x64, 0x4f, 0x6e, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0c, - 0x6f, 0x6e, 0x65, 0x4d, 0x6f, 0x6e, 0x74, 0x68, 0x43, 0x6f, 0x73, 0x74, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0c, 0x6f, 0x6e, 0x65, 0x4d, 0x6f, 0x6e, 0x74, 0x68, 0x43, 0x6f, 0x73, 0x74, - 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x73, 0x74, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x73, 0x74, 0x12, 0x26, - 0x0a, 0x0e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x74, 0x65, 0x64, 0x42, 0x6f, 0x6e, 0x75, 0x73, - 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x74, 0x65, - 0x64, 0x42, 0x6f, 0x6e, 0x75, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x72, 0x65, 0x6e, 0x65, 0x77, 0x61, - 0x6c, 0x54, 0x65, 0x78, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x65, 0x6e, - 0x65, 0x77, 0x61, 0x6c, 0x54, 0x65, 0x78, 0x74, 0x1a, 0x38, 0x0a, 0x0a, 0x50, 0x72, 0x69, 0x63, - 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, - 0x38, 0x01, 0x22, 0x26, 0x0a, 0x10, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, - 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x58, 0x0a, 0x0d, 0x50, 0x61, - 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x6d, - 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, - 0x68, 0x6f, 0x64, 0x12, 0x2f, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, - 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, - 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x76, 0x69, - 0x64, 0x65, 0x72, 0x73, 0x42, 0x1b, 0x0a, 0x10, 0x69, 0x6f, 0x2e, 0x6c, 0x61, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5a, 0x07, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x22, 0x22, 0x0a, 0x05, 0x50, 0x6c, 0x61, 0x6e, 0x73, + 0x12, 0x19, 0x0a, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x05, + 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x52, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x22, 0x98, 0x03, 0x0a, 0x04, + 0x50, 0x6c, 0x61, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x02, 0x69, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x65, 0x73, 0x74, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x62, 0x65, 0x73, 0x74, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x64, 0x50, 0x72, 0x69, 0x63, 0x65, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x75, 0x73, 0x64, 0x50, 0x72, 0x69, 0x63, 0x65, + 0x12, 0x26, 0x0a, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x10, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x2e, 0x50, 0x72, 0x69, 0x63, 0x65, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x52, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x12, 0x36, 0x0a, 0x16, 0x74, 0x6f, 0x74, 0x61, + 0x6c, 0x43, 0x6f, 0x73, 0x74, 0x42, 0x69, 0x6c, 0x6c, 0x65, 0x64, 0x4f, 0x6e, 0x65, 0x54, 0x69, + 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, + 0x6f, 0x73, 0x74, 0x42, 0x69, 0x6c, 0x6c, 0x65, 0x64, 0x4f, 0x6e, 0x65, 0x54, 0x69, 0x6d, 0x65, + 0x12, 0x22, 0x0a, 0x0c, 0x6f, 0x6e, 0x65, 0x4d, 0x6f, 0x6e, 0x74, 0x68, 0x43, 0x6f, 0x73, 0x74, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6f, 0x6e, 0x65, 0x4d, 0x6f, 0x6e, 0x74, 0x68, + 0x43, 0x6f, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x73, + 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, + 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x74, 0x65, 0x64, 0x42, + 0x6f, 0x6e, 0x75, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x66, 0x6f, 0x72, 0x6d, + 0x61, 0x74, 0x74, 0x65, 0x64, 0x42, 0x6f, 0x6e, 0x75, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x72, 0x65, + 0x6e, 0x65, 0x77, 0x61, 0x6c, 0x54, 0x65, 0x78, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0b, 0x72, 0x65, 0x6e, 0x65, 0x77, 0x61, 0x6c, 0x54, 0x65, 0x78, 0x74, 0x1a, 0x38, 0x0a, 0x0a, + 0x50, 0x72, 0x69, 0x63, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x26, 0x0a, 0x10, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, + 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x58, + 0x0a, 0x0d, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, + 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x2f, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x76, 0x69, + 0x64, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x50, 0x61, 0x79, + 0x6d, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x52, 0x09, 0x70, + 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x42, 0x1b, 0x0a, 0x10, 0x69, 0x6f, 0x2e, 0x6c, + 0x61, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5a, 0x07, 0x2f, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -640,27 +689,29 @@ func file_protos_shared_vpn_proto_rawDescGZIP() []byte { return file_protos_shared_vpn_proto_rawDescData } -var file_protos_shared_vpn_proto_msgTypes = make([]protoimpl.MessageInfo, 9) +var file_protos_shared_vpn_proto_msgTypes = make([]protoimpl.MessageInfo, 10) var file_protos_shared_vpn_proto_goTypes = []interface{}{ (*ServerInfo)(nil), // 0: ServerInfo (*Bandwidth)(nil), // 1: Bandwidth (*AppData)(nil), // 2: AppData (*Device)(nil), // 3: Device (*Devices)(nil), // 4: Devices - (*Plan)(nil), // 5: Plan - (*PaymentProviders)(nil), // 6: PaymentProviders - (*PaymentMethod)(nil), // 7: PaymentMethod - nil, // 8: Plan.PriceEntry + (*Plans)(nil), // 5: Plans + (*Plan)(nil), // 6: Plan + (*PaymentProviders)(nil), // 7: PaymentProviders + (*PaymentMethod)(nil), // 8: PaymentMethod + nil, // 9: Plan.PriceEntry } var file_protos_shared_vpn_proto_depIdxs = []int32{ 3, // 0: Devices.devices:type_name -> Device - 8, // 1: Plan.price:type_name -> Plan.PriceEntry - 6, // 2: PaymentMethod.providers:type_name -> PaymentProviders - 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 + 6, // 1: Plans.plan:type_name -> Plan + 9, // 2: Plan.price:type_name -> Plan.PriceEntry + 7, // 3: PaymentMethod.providers:type_name -> PaymentProviders + 4, // [4:4] is the sub-list for method output_type + 4, // [4:4] is the sub-list for method input_type + 4, // [4:4] is the sub-list for extension type_name + 4, // [4:4] is the sub-list for extension extendee + 0, // [0:4] is the sub-list for field type_name } func init() { file_protos_shared_vpn_proto_init() } @@ -730,7 +781,7 @@ func file_protos_shared_vpn_proto_init() { } } file_protos_shared_vpn_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Plan); i { + switch v := v.(*Plans); i { case 0: return &v.state case 1: @@ -742,7 +793,7 @@ func file_protos_shared_vpn_proto_init() { } } file_protos_shared_vpn_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PaymentProviders); i { + switch v := v.(*Plan); i { case 0: return &v.state case 1: @@ -754,6 +805,18 @@ func file_protos_shared_vpn_proto_init() { } } file_protos_shared_vpn_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PaymentProviders); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_protos_shared_vpn_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PaymentMethod); i { case 0: return &v.state @@ -772,7 +835,7 @@ func file_protos_shared_vpn_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_protos_shared_vpn_proto_rawDesc, NumEnums: 0, - NumMessages: 9, + NumMessages: 10, NumExtensions: 0, NumServices: 0, }, diff --git a/internalsdk/session_model.go b/internalsdk/session_model.go index 724bf9d98..4aee0f17f 100644 --- a/internalsdk/session_model.go +++ b/internalsdk/session_model.go @@ -57,6 +57,7 @@ const ( pathStoreVersion = "storeVersion" pathSelectedTab = "/selectedTab" pathServerInfo = "/server_info" + pathPlans = "/plans/" currentTermsVersion = 1 ) @@ -82,6 +83,7 @@ func NewSessionModel(mdb minisql.DB, opts *SessionModelOpts) (*SessionModel, err } base.db.RegisterType(1000, &protos.ServerInfo{}) base.db.RegisterType(2000, &protos.Devices{}) + base.db.RegisterType(3000, &protos.Plan{}) m := &SessionModel{baseModel: base} m.baseModel.doInvokeMethod = m.doInvokeMethod return m, m.initSessionModel(opts) @@ -256,6 +258,34 @@ func (m *SessionModel) initSessionModel(opts *SessionModelOpts) error { if err != nil { return err } + + toekns, err := m.GetToken() + if err != nil { + return err + } + userIdStr := fmt.Sprintf("%d", userId) + countryCode, err := m.GetCountryCode() + if err != nil { + return err + } + + // Run Plans in background + // go func() { + // data, err := apimodels.PlansV3(opts.DeviceID, userIdStr, lang, toekns, countryCode) + // if err != nil { + // log.Errorf("Error while Plans v3 request:", err) // Optional: log the error + // return + // } + // log.Debugf("Plans Response", data) + // }() + + // //Get all the Plans + plans, err := apimodels.PlansV3(opts.DeviceID, userIdStr, lang, toekns, countryCode) + if err != nil { + return err + } + setPlans(m.baseModel, plans.Plans) + return nil } @@ -398,6 +428,39 @@ func setDevices(m *baseModel, devices []apimodels.UserDevice) error { return nil } +func storePlanDetail(m *baseModel, plan apimodels.PlansResponse) error { + log.Debugf("Storing Plan details ") + err := setPlans(m, plan.Plans) + if err != nil { + return err + } + + log.Debugf("Plan details stored successful") + return nil +} + +func setPlans(m *baseModel, plans []apimodels.Plan) error { + var protoPlans []*protos.Plan + for _, plans := range plans { + protoPlan := &protos.Plan{ + Id: plans.ID, + Description: plans.Description, + BestValue: plans.BestValue, + UsdPrice: plans.UsdPrice, + Price: map[string]int64{ + "usd": plans.Price.Usd, + }, + } + protoPlans = append(protoPlans, protoPlan) + } + + pathdb.Mutate(m.db, func(tx pathdb.TX) error { + pathdb.Put(tx, pathPlans, protoPlans, "") + return nil + }) + return nil +} + func (m *SessionModel) GetTimeZone() (string, error) { return pathdb.Get[string](m.baseModel.db, pathTimezoneID) } diff --git a/internalsdk/utils.go b/internalsdk/utils.go index 152e0af02..5d582f9fa 100644 --- a/internalsdk/utils.go +++ b/internalsdk/utils.go @@ -2,8 +2,11 @@ package internalsdk import ( "encoding/binary" + "fmt" "math" + "strings" + "github.com/bojanz/currency" "github.com/getlantern/errors" ) @@ -14,3 +17,52 @@ func BytesToFloat64LittleEndian(b []byte) (float64, error) { bits := binary.LittleEndian.Uint64(b) return math.Float64frombits(bits), nil } + +func updatePrice() { + // formattedBouns := formatRenewalBonusExpected() + +} + +func formatRenewalBonusExpected(planBonus int64, days int64, longForm bool) string { + var bonusParts []string + if planBonus == 0 && days == 0 { + return "" + } + if longForm { + // "1 month and 15 days" + if planBonus > 0 { + monthStr := "month" + if planBonus > 1 { + monthStr = "months" + } + bonusParts = append(bonusParts, fmt.Sprintf("%d %s", planBonus, monthStr)) + } + if days > 0 { + dayStr := "day" + if days > 1 { + dayStr = "days" + } + bonusParts = append(bonusParts, fmt.Sprintf("%d %s", days, dayStr)) + } + return strings.Join(bonusParts, " and ") + } else { + totalDays := planBonus*30 + days + dayStr := "day" + if totalDays > 1 { + dayStr = "days" + } + return fmt.Sprintf("%d %s", totalDays, dayStr) + } +} + +func getSymbol(currencyCode string) (string, error) { + locale := currency.NewAmount() + formatter := currency.GetCurrencyCodes() + + currency.NewAmount("8", currency.GetSymbol()) + + if err != nil { + return "", err // handle error + } + return unit.Symbol(), nil +} diff --git a/lib/account/account.dart b/lib/account/account.dart index aad9669ab..8ced5fbf9 100644 --- a/lib/account/account.dart +++ b/lib/account/account.dart @@ -3,7 +3,7 @@ import 'package:lantern/messaging/messaging_model.dart'; @RoutePage(name: 'Account') class AccountMenu extends StatelessWidget { - const AccountMenu({Key? key}) : super(key: key); + const AccountMenu({Key? key}) : super(key: key); Future authorizeDeviceForPro(BuildContext context) async => await context.pushRoute(AuthorizePro()); @@ -48,15 +48,14 @@ class AccountMenu extends StatelessWidget { ) : const SizedBox(), ), - if (Platform.isAndroid) - ListItemFactory.settingsItem( - key: AppKeys.upgrade_lantern_pro, - icon: ImagePaths.pro_icon_black, - content: 'Upgrade to Lantern Pro'.i18n, - onTap: () { - upgradeToLanternPro(context); - }, - ), + ListItemFactory.settingsItem( + key: AppKeys.upgrade_lantern_pro, + icon: ImagePaths.pro_icon_black, + content: 'Upgrade to Lantern Pro'.i18n, + onTap: () { + upgradeToLanternPro(context); + }, + ), ListItemFactory.settingsItem( icon: ImagePaths.star, content: 'Invite Friends'.i18n, @@ -80,23 +79,21 @@ class AccountMenu extends StatelessWidget { return [ messagingModel.getOnBoardingStatus( (context, hasBeenOnboarded, child) => - messagingModel.getCopiedRecoveryStatus( - (BuildContext context, bool hasCopiedRecoveryKey, Widget? child) => - ListItemFactory.settingsItem( - key: AppKeys.account_management, - icon: ImagePaths.account, - content: 'account_management'.i18n, - onTap: () async => await context - .pushRoute(AccountManagement(isPro: true)), - trailingArray: [ - if (!hasCopiedRecoveryKey && hasBeenOnboarded == true) - const CAssetImage( - path: ImagePaths.badge, - ), - ], - ) - - ), + messagingModel.getCopiedRecoveryStatus((BuildContext context, + bool hasCopiedRecoveryKey, Widget? child) => + ListItemFactory.settingsItem( + key: AppKeys.account_management, + icon: ImagePaths.account, + content: 'account_management'.i18n, + onTap: () async => + await context.pushRoute(AccountManagement(isPro: true)), + trailingArray: [ + if (!hasCopiedRecoveryKey && hasBeenOnboarded == true) + const CAssetImage( + path: ImagePaths.badge, + ), + ], + )), ), ListItemFactory.settingsItem( icon: ImagePaths.star, diff --git a/lib/plans/plans.dart b/lib/plans/plans.dart index 6ab9f3268..b178d3532 100644 --- a/lib/plans/plans.dart +++ b/lib/plans/plans.dart @@ -64,11 +64,9 @@ class PlansPage extends StatelessWidget { color: white, child: Row( children: [ - Container( - child: const CAssetImage( - path: ImagePaths.lantern_pro_logotype, - size: 20, - ), + const CAssetImage( + path: ImagePaths.lantern_pro_logotype, + size: 20, ), const Spacer(), IconButton( diff --git a/protos_shared/vpn.proto b/protos_shared/vpn.proto index c6d3a7bdc..89a1e2266 100644 --- a/protos_shared/vpn.proto +++ b/protos_shared/vpn.proto @@ -32,6 +32,10 @@ message Devices { repeated Device devices = 1; } +message Plans { + repeated Plan plan = 1; +} + message Plan { string id = 1; string description = 2; From 1a94fb6ccd5679e03d525a992f485762a5eb9c6f Mon Sep 17 00:00:00 2001 From: Jigar-f Date: Wed, 1 Nov 2023 17:22:52 +0530 Subject: [PATCH 03/17] Completed pre process of plans. --- internalsdk/apimodels/json_models.go | 43 +++++++++-------- internalsdk/session_model.go | 55 ++++++++++++++------- internalsdk/utils.go | 71 ++++++++++++++++++++-------- 3 files changed, 112 insertions(+), 57 deletions(-) diff --git a/internalsdk/apimodels/json_models.go b/internalsdk/apimodels/json_models.go index 9d703cf70..fb0d50468 100644 --- a/internalsdk/apimodels/json_models.go +++ b/internalsdk/apimodels/json_models.go @@ -51,21 +51,30 @@ type PlansResponse struct { } type Plan struct { - ID string `json:"id"` - Description string `json:"description"` - Duration Duration `json:"duration"` - Price Price `json:"price"` - ExpectedMonthlyPrice Price `json:"expectedMonthlyPrice"` - UsdPrice int64 `json:"usdPrice"` - UsdPrice1Y int64 `json:"usdPrice1Y"` - UsdPrice2Y int64 `json:"usdPrice2Y"` - RedeemFor RedeemFor `json:"redeemFor"` - RenewalBonus RedeemFor `json:"renewalBonus"` - RenewalBonusExpired RedeemFor `json:"renewalBonusExpired"` - RenewalBonusExpected RedeemFor `json:"renewalBonusExpected"` - Discount float64 `json:"discount"` - BestValue bool `json:"bestValue"` - Level string `json:"level"` + ID string `json:"id"` + Description string `json:"description"` + Duration Duration `json:"duration"` + Price map[string]int64 `json:"price"` + ExpectedMonthlyPrice map[string]int64 `json:"expectedMonthlyPrice"` + UsdPrice int64 `json:"usdPrice"` + UsdPrice1Y int64 `json:"usdPrice1Y"` + UsdPrice2Y int64 `json:"usdPrice2Y"` + RedeemFor RedeemFor `json:"redeemFor"` + RenewalBonus RedeemFor `json:"renewalBonus"` + RenewalBonusExpired RedeemFor `json:"renewalBonusExpired"` + RenewalBonusExpected RedeemFor `json:"renewalBonusExpected"` + Discount float64 `json:"discount"` + BestValue bool `json:"bestValue"` + Level string `json:"level"` + TotalCostBilledOneTime string + FormattedDiscount string + FormattedBonus string + OneMonthCost string + TotalCost string +} + +type Price struct { + Usd int64 `json:"usd"` } type Duration struct { @@ -74,10 +83,6 @@ type Duration struct { Years int64 `json:"years"` } -type Price struct { - Usd int64 `json:"usd"` -} - type RedeemFor struct { Days int64 `json:"days"` Months int64 `json:"months"` diff --git a/internalsdk/session_model.go b/internalsdk/session_model.go index 4aee0f17f..4bc917b4c 100644 --- a/internalsdk/session_model.go +++ b/internalsdk/session_model.go @@ -4,6 +4,7 @@ import ( "fmt" "path/filepath" "strconv" + "strings" "github.com/getlantern/android-lantern/internalsdk/apimodels" "github.com/getlantern/android-lantern/internalsdk/protos" @@ -84,6 +85,7 @@ func NewSessionModel(mdb minisql.DB, opts *SessionModelOpts) (*SessionModel, err base.db.RegisterType(1000, &protos.ServerInfo{}) base.db.RegisterType(2000, &protos.Devices{}) base.db.RegisterType(3000, &protos.Plan{}) + base.db.RegisterType(4000, &protos.Plans{}) m := &SessionModel{baseModel: base} m.baseModel.doInvokeMethod = m.doInvokeMethod return m, m.initSessionModel(opts) @@ -282,10 +284,17 @@ func (m *SessionModel) initSessionModel(opts *SessionModelOpts) error { // //Get all the Plans plans, err := apimodels.PlansV3(opts.DeviceID, userIdStr, lang, toekns, countryCode) if err != nil { + log.Debugf("Plans V3 error: %v", err) + return err } - setPlans(m.baseModel, plans.Plans) + log.Debugf("Plans V3 response: %+v", plans) + /// Process Plans and providers + err = storePlanDetail(m.baseModel, *plans) + if err != nil { + return err + } return nil } @@ -434,31 +443,41 @@ func storePlanDetail(m *baseModel, plan apimodels.PlansResponse) error { if err != nil { return err } - log.Debugf("Plan details stored successful") return nil } func setPlans(m *baseModel, plans []apimodels.Plan) error { - var protoPlans []*protos.Plan - for _, plans := range plans { - protoPlan := &protos.Plan{ - Id: plans.ID, - Description: plans.Description, - BestValue: plans.BestValue, - UsdPrice: plans.UsdPrice, - Price: map[string]int64{ - "usd": plans.Price.Usd, - }, + return pathdb.Mutate(m.db, func(tx pathdb.TX) error { + for _, plans := range plans { + // Update priceing for each plan + err := updatePrice(&plans) + if err != nil { + log.Debugf("Error while updateing price") + return err + } + log.Debugf("Plans Values %+v", plans) + pathPlanId := pathPlans + strings.Split(plans.ID, "-")[0] + protoPlan := &protos.Plan{ + Id: plans.ID, + Description: plans.Description, + BestValue: plans.BestValue, + UsdPrice: plans.UsdPrice, + TotalCostBilledOneTime: plans.TotalCostBilledOneTime, + Price: plans.Price, + OneMonthCost: plans.OneMonthCost, + TotalCost: plans.TotalCost, + FormattedBonus: plans.FormattedBonus, + RenewalText: "This is needs to be changed", + } + err = pathdb.Put(tx, pathPlanId, protoPlan, "") + if err != nil { + log.Debugf("Error while addding price") + return err + } } - protoPlans = append(protoPlans, protoPlan) - } - - pathdb.Mutate(m.db, func(tx pathdb.TX) error { - pathdb.Put(tx, pathPlans, protoPlans, "") return nil }) - return nil } func (m *SessionModel) GetTimeZone() (string, error) { diff --git a/internalsdk/utils.go b/internalsdk/utils.go index 5d582f9fa..6f8e89517 100644 --- a/internalsdk/utils.go +++ b/internalsdk/utils.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/bojanz/currency" + "github.com/getlantern/android-lantern/internalsdk/apimodels" "github.com/getlantern/errors" ) @@ -18,24 +19,66 @@ func BytesToFloat64LittleEndian(b []byte) (float64, error) { return math.Float64frombits(bits), nil } -func updatePrice() { - // formattedBouns := formatRenewalBonusExpected() +func updatePrice(plan *apimodels.Plan) error { + bonous := plan.RenewalBonusExpected + formattedBouns := formatRenewalBonusExpected(bonous.Months, bonous.Days, false) + log.Debugf("updateprice formattedBouns %v", formattedBouns) + totalCost, err := formatPrice(plan.Price) + log.Debugf("updateprice Total cost %v", totalCost) + if err != nil { + return err + } + //One Month Price + oneMonthCost, err := formatPrice(plan.ExpectedMonthlyPrice) + if err != nil { + return err + } + log.Debugf("updateprice oneMonthCost %v", oneMonthCost) + var formattedDiscount string + if plan.Discount > 0 { + discountPercentage := math.Round(plan.Discount * 100) + formattedDiscount = fmt.Sprintf("Save: %v%%", discountPercentage) + } + + plan.TotalCostBilledOneTime = fmt.Sprintf("%v billed one time", totalCost) + plan.OneMonthCost = oneMonthCost + plan.FormattedBonus = formattedBouns + plan.FormattedDiscount = formattedDiscount + plan.TotalCost = totalCost + return nil +} + +func formatPrice(price map[string]int64) (string, error) { + locale := currency.NewLocale("en_us") + formatter := currency.NewFormatter(locale) + formatter.MaxDigits = 2 + for currencyCode, amount := range price { + amountStr := fmt.Sprintf("%.2f", float64(amount)/100.00) + log.Debugf("Amount is %v", amountStr) + amount, err := currency.NewAmount(amountStr, strings.ToUpper(currencyCode)) + if err != nil { + return "", err + } + log.Debugf("Formated price is %v", formatter.Format(amount)) + return formatter.Format(amount), nil + } + return "", nil } -func formatRenewalBonusExpected(planBonus int64, days int64, longForm bool) string { +func formatRenewalBonusExpected(months int64, days int64, longForm bool) string { var bonusParts []string - if planBonus == 0 && days == 0 { + if months == 0 && days == 0 { return "" } if longForm { // "1 month and 15 days" - if planBonus > 0 { + if months > 0 { monthStr := "month" - if planBonus > 1 { + if months > 1 { monthStr = "months" } - bonusParts = append(bonusParts, fmt.Sprintf("%d %s", planBonus, monthStr)) + bonusParts = append(bonusParts, fmt.Sprintf("%d %s", months, monthStr)) } if days > 0 { dayStr := "day" @@ -46,7 +89,7 @@ func formatRenewalBonusExpected(planBonus int64, days int64, longForm bool) stri } return strings.Join(bonusParts, " and ") } else { - totalDays := planBonus*30 + days + totalDays := months*30 + days dayStr := "day" if totalDays > 1 { dayStr = "days" @@ -54,15 +97,3 @@ func formatRenewalBonusExpected(planBonus int64, days int64, longForm bool) stri return fmt.Sprintf("%d %s", totalDays, dayStr) } } - -func getSymbol(currencyCode string) (string, error) { - locale := currency.NewAmount() - formatter := currency.GetCurrencyCodes() - - currency.NewAmount("8", currency.GetSymbol()) - - if err != nil { - return "", err // handle error - } - return unit.Symbol(), nil -} From fa43a12cff3b405c488fc1e65415fe85504e336f Mon Sep 17 00:00:00 2001 From: Jigar-f Date: Wed, 1 Nov 2023 18:11:14 +0530 Subject: [PATCH 04/17] Use dynamic local. --- internalsdk/session_model.go | 9 ++++++++- internalsdk/utils.go | 10 +++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/internalsdk/session_model.go b/internalsdk/session_model.go index 4bc917b4c..f8e275c1d 100644 --- a/internalsdk/session_model.go +++ b/internalsdk/session_model.go @@ -448,10 +448,17 @@ func storePlanDetail(m *baseModel, plan apimodels.PlansResponse) error { } func setPlans(m *baseModel, plans []apimodels.Plan) error { + return pathdb.Mutate(m.db, func(tx pathdb.TX) error { + //Get local from user + lang, err := pathdb.Get[string](tx, pathLang) + if err != nil { + return err + } + for _, plans := range plans { // Update priceing for each plan - err := updatePrice(&plans) + err := updatePrice(&plans, lang) if err != nil { log.Debugf("Error while updateing price") return err diff --git a/internalsdk/utils.go b/internalsdk/utils.go index 6f8e89517..dd26d38ef 100644 --- a/internalsdk/utils.go +++ b/internalsdk/utils.go @@ -19,17 +19,17 @@ func BytesToFloat64LittleEndian(b []byte) (float64, error) { return math.Float64frombits(bits), nil } -func updatePrice(plan *apimodels.Plan) error { +func updatePrice(plan *apimodels.Plan, local string) error { bonous := plan.RenewalBonusExpected formattedBouns := formatRenewalBonusExpected(bonous.Months, bonous.Days, false) log.Debugf("updateprice formattedBouns %v", formattedBouns) - totalCost, err := formatPrice(plan.Price) + totalCost, err := formatPrice(plan.Price, local) log.Debugf("updateprice Total cost %v", totalCost) if err != nil { return err } //One Month Price - oneMonthCost, err := formatPrice(plan.ExpectedMonthlyPrice) + oneMonthCost, err := formatPrice(plan.ExpectedMonthlyPrice, local) if err != nil { return err } @@ -48,8 +48,8 @@ func updatePrice(plan *apimodels.Plan) error { return nil } -func formatPrice(price map[string]int64) (string, error) { - locale := currency.NewLocale("en_us") +func formatPrice(price map[string]int64, local string) (string, error) { + locale := currency.NewLocale(local) formatter := currency.NewFormatter(locale) formatter.MaxDigits = 2 From c9a0d9ff856d62379d29b61951086c2d99d95047 Mon Sep 17 00:00:00 2001 From: Jigar-f Date: Thu, 2 Nov 2023 13:13:27 +0530 Subject: [PATCH 05/17] Append currency code. --- internalsdk/session_model.go | 17 ++++++++-- internalsdk/utils.go | 2 +- lib/plans/plan_details.dart | 66 +++++++++++++++++++++--------------- 3 files changed, 53 insertions(+), 32 deletions(-) diff --git a/internalsdk/session_model.go b/internalsdk/session_model.go index f8e275c1d..480e9738d 100644 --- a/internalsdk/session_model.go +++ b/internalsdk/session_model.go @@ -133,6 +133,8 @@ func (m *SessionModel) doInvokeMethod(method string, arguments Arguments) (inter if err != nil { return nil, err } + //Todo find way to call PLans api everytime user chnage lang + //So plans will apper in there local lang return true, nil case "acceptTerms": err := acceptTerms(m.baseModel) @@ -261,7 +263,7 @@ func (m *SessionModel) initSessionModel(opts *SessionModelOpts) error { return err } - toekns, err := m.GetToken() + token, err := m.GetToken() if err != nil { return err } @@ -282,16 +284,25 @@ func (m *SessionModel) initSessionModel(opts *SessionModelOpts) error { // }() // //Get all the Plans - plans, err := apimodels.PlansV3(opts.DeviceID, userIdStr, lang, toekns, countryCode) + err = getPlansV3(m.baseModel, opts.DeviceID, userIdStr, lang, token, countryCode) if err != nil { log.Debugf("Plans V3 error: %v", err) + return err + } + return nil +} + +func getPlansV3(m *baseModel, deviceId string, userId string, lang string, token string, countyCode string) error { + plans, err := apimodels.PlansV3(deviceId, userId, lang, token, countyCode) + if err != nil { + log.Debugf("Plans V3 error: %v", err) return err } log.Debugf("Plans V3 response: %+v", plans) /// Process Plans and providers - err = storePlanDetail(m.baseModel, *plans) + err = storePlanDetail(m, *plans) if err != nil { return err } diff --git a/internalsdk/utils.go b/internalsdk/utils.go index dd26d38ef..32022084f 100644 --- a/internalsdk/utils.go +++ b/internalsdk/utils.go @@ -61,7 +61,7 @@ func formatPrice(price map[string]int64, local string) (string, error) { return "", err } log.Debugf("Formated price is %v", formatter.Format(amount)) - return formatter.Format(amount), nil + return strings.ToUpper(currencyCode) + formatter.Format(amount), nil } return "", nil } diff --git a/lib/plans/plan_details.dart b/lib/plans/plan_details.dart index 51654359a..114f4925f 100644 --- a/lib/plans/plan_details.dart +++ b/lib/plans/plan_details.dart @@ -20,34 +20,7 @@ class PlanCard extends StatelessWidget { return Padding( padding: const EdgeInsetsDirectional.only(bottom: 16.0), child: CInkWell( - onTap: () async { - final isPlayVersion = sessionModel.isPlayVersion.value ?? false; - final inRussia = sessionModel.country.value == 'RU'; - - // * Play version - if (isPlayVersion && !inRussia) { - await sessionModel - .submitGooglePlay(planName) - .onError((error, stackTrace) { - // on failure - CDialog.showError( - context, - error: e, - stackTrace: stackTrace, - description: - (error as PlatformException).message ?? error.toString(), - ); - }); - } else { - // * Proceed to our own Checkout - await context.pushRoute( - Checkout( - plan: plan, - isPro: isPro, - ), - ); - } - }, + onTap:()=>onPlanTap(context,planName) , child: Stack( alignment: Alignment.bottomCenter, children: [ @@ -145,6 +118,43 @@ class PlanCard extends StatelessWidget { ), ); } + + + Future onPlanTap(BuildContext context,String planName) async { + if (Platform.isAndroid) { + final isPlayVersion = sessionModel.isPlayVersion.value ?? false; + final inRussia = sessionModel.country.value == 'RU'; + //If user is downloaded from Play store and !inRussia then + //Go with In App purchase + if (isPlayVersion && !inRussia) { + await sessionModel + .submitGooglePlay(planName) + .onError((error, stackTrace) { + // on failure + CDialog.showError( + context, + error: e, + stackTrace: stackTrace, + description: + (error as PlatformException).message ?? error.toString(), + ); + }); + } else { + // * Proceed to our own Checkout + await context.pushRoute( + Checkout( + plan: plan, + isPro: isPro, + ), + ); + } + }else{ + // * Proceed to IOS + + } + } + + } class PlanStep extends StatelessWidget { From c957f4370076e9c635de4f618773fc5a2a6c79d8 Mon Sep 17 00:00:00 2001 From: Jigar-f Date: Thu, 2 Nov 2023 17:22:45 +0530 Subject: [PATCH 06/17] Added In App Purchase for IOS. --- ios/Podfile.lock | 7 ++++ lib/common/common.dart | 4 ++ lib/core/purchase/app_purchase.dart | 62 +++++++++++++++++++++++++++++ lib/core/services.dart | 9 +++++ lib/main.dart | 6 ++- lib/plans/plan_details.dart | 17 ++++---- pubspec.lock | 40 +++++++++++++++++++ pubspec.yaml | 6 +++ 8 files changed, 141 insertions(+), 10 deletions(-) create mode 100644 lib/core/purchase/app_purchase.dart create mode 100644 lib/core/services.dart diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 80b7c6a43..1277dd5a5 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -110,6 +110,9 @@ PODS: - "GoogleUtilities/NSData+zlib (7.11.5)" - GoogleUtilities/Reachability (7.11.5): - GoogleUtilities/Logger + - in_app_purchase_storekit (0.0.1): + - Flutter + - FlutterMacOS - integration_test (0.0.1): - Flutter - libwebp (1.3.2): @@ -192,6 +195,7 @@ DEPENDENCIES: - flutter_uploader (from `.symlinks/plugins/flutter_uploader/ios`) - fluttertoast (from `.symlinks/plugins/fluttertoast/ios`) - google_mobile_ads (from `.symlinks/plugins/google_mobile_ads/ios`) + - in_app_purchase_storekit (from `.symlinks/plugins/in_app_purchase_storekit/darwin`) - integration_test (from `.symlinks/plugins/integration_test/ios`) - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) @@ -259,6 +263,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/fluttertoast/ios" google_mobile_ads: :path: ".symlinks/plugins/google_mobile_ads/ios" + in_app_purchase_storekit: + :path: ".symlinks/plugins/in_app_purchase_storekit/darwin" integration_test: :path: ".symlinks/plugins/integration_test/ios" package_info_plus: @@ -310,6 +316,7 @@ SPEC CHECKSUMS: GoogleAppMeasurement: 722db6550d1e6d552b08398b69a975ac61039338 GoogleUserMessagingPlatform: dce302b8f1b84d6e945812ee7a15c3f65a102cbf GoogleUtilities: 13e2c67ede716b8741c7989e26893d151b2b2084 + in_app_purchase_storekit: 4fb7ee9e824b1f09107fbfbbce8c4b276366dc43 integration_test: 13825b8a9334a850581300559b8839134b124670 libwebp: 1786c9f4ff8a279e4dac1e8f385004d5fc253009 MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb diff --git a/lib/common/common.dart b/lib/common/common.dart index 64a1b3506..240bc8efa 100644 --- a/lib/common/common.dart +++ b/lib/common/common.dart @@ -101,3 +101,7 @@ export 'ui/custom/text_field.dart'; export 'ui/custom/fullscreen_video_viewer.dart'; export 'ui/custom/fullscreen_image_viewer.dart'; export 'ui/custom/fullscreen_viewer.dart'; + + +// Services +export 'package:lantern/core/services.dart'; \ No newline at end of file diff --git a/lib/core/purchase/app_purchase.dart b/lib/core/purchase/app_purchase.dart new file mode 100644 index 000000000..fea8278b9 --- /dev/null +++ b/lib/core/purchase/app_purchase.dart @@ -0,0 +1,62 @@ +import 'package:in_app_purchase/in_app_purchase.dart'; + +import '../../common/common.dart'; + +class AppPurchase { + final InAppPurchase _inAppPurchase = InAppPurchase.instance; + StreamSubscription>? _subscription; + List plansSku = []; + final Set _iosPlansIds = {"1Y"}; + + void init() { + getAvailablePlans(); + final purchaseUpdated = _inAppPurchase.purchaseStream; + _subscription = purchaseUpdated.listen( + _onPurchaseUpdate, + onDone: _updateStreamOnDone, + onError: _updateStreamOnError, + ); + } + + Future getAvailablePlans() async { + final response = await _inAppPurchase.queryProductDetails(_iosPlansIds); + plansSku.clear(); + plansSku.addAll(response.productDetails); + } + + void startPurchase(String planId) { + final plan = _normalizePlan(planId); + final purchaseParam = PurchaseParam(productDetails: plan); + _inAppPurchase.buyConsumable(purchaseParam: purchaseParam); + } + + ProductDetails _normalizePlan(String planId) { + /// We have different ids for IOS, Android And servers + /// Convert Server plan to App Store plans + /// For ios we are using plans such as 1Y, 2Y, but server plan is 1y-xx-xx + /// So we split and compare with lowercase + final newPlanId = planId.split('-')[0]; + return plansSku.firstWhere( + (element) => element.id.toLowerCase() == newPlanId.toLowerCase()); + } + + // Internal methods + Future _onPurchaseUpdate(List purchaseDetailsList) async { + // Handle purchases here + for (final purchase in purchaseDetailsList) { + print("purchase $purchase"); + if (purchase.pendingCompletePurchase) { + await _inAppPurchase.completePurchase(purchase); + } + } + } + + void _updateStreamOnDone() { + _subscription?.cancel(); + } + + void _updateStreamOnError(dynamic error) { + //Handle error here + print("purchase error $error"); + } +} diff --git a/lib/core/services.dart b/lib/core/services.dart new file mode 100644 index 000000000..e5ac2f5b2 --- /dev/null +++ b/lib/core/services.dart @@ -0,0 +1,9 @@ +import 'package:get_it/get_it.dart'; +import 'package:lantern/core/purchase/app_purchase.dart'; + +final GetIt sl = GetIt.instance; + +void init() { + //Inject + sl.registerLazySingleton(() => AppPurchase()); +} diff --git a/lib/main.dart b/lib/main.dart index be76173de..1e1d4388e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -2,6 +2,8 @@ import 'package:flutter_driver/driver_extension.dart'; import 'package:google_mobile_ads/google_mobile_ads.dart'; import 'package:lantern/app.dart'; import 'package:lantern/common/common.dart'; +import 'package:lantern/core/purchase/app_purchase.dart'; +import 'package:lantern/core/services.dart'; import 'catcher_setup.dart'; @@ -13,8 +15,10 @@ Future main() async { print("Flutter extension enabled $flavor"); enableFlutterDriverExtension(); } - WidgetsFlutterBinding.ensureInitialized(); + // Inject all the services + init(); + sl().init(); await _initGoogleMobileAds(); await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); diff --git a/lib/plans/plan_details.dart b/lib/plans/plan_details.dart index 114f4925f..05c2c53e2 100644 --- a/lib/plans/plan_details.dart +++ b/lib/plans/plan_details.dart @@ -1,4 +1,5 @@ import 'package:lantern/common/common.dart'; +import 'package:lantern/core/purchase/app_purchase.dart'; class PlanCard extends StatelessWidget { final Plan plan; @@ -20,7 +21,7 @@ class PlanCard extends StatelessWidget { return Padding( padding: const EdgeInsetsDirectional.only(bottom: 16.0), child: CInkWell( - onTap:()=>onPlanTap(context,planName) , + onTap: () => onPlanTap(context, planName), child: Stack( alignment: Alignment.bottomCenter, children: [ @@ -119,8 +120,7 @@ class PlanCard extends StatelessWidget { ); } - - Future onPlanTap(BuildContext context,String planName) async { + Future onPlanTap(BuildContext context, String planName) async { if (Platform.isAndroid) { final isPlayVersion = sessionModel.isPlayVersion.value ?? false; final inRussia = sessionModel.country.value == 'RU'; @@ -136,7 +136,7 @@ class PlanCard extends StatelessWidget { error: e, stackTrace: stackTrace, description: - (error as PlatformException).message ?? error.toString(), + (error as PlatformException).message ?? error.toString(), ); }); } else { @@ -148,13 +148,12 @@ class PlanCard extends StatelessWidget { ), ); } - }else{ - // * Proceed to IOS - + } else { + // * Proceed to IOSs + final appPurchase = sl(); + appPurchase.startPurchase(plan.id); } } - - } class PlanStep extends StatelessWidget { diff --git a/pubspec.lock b/pubspec.lock index 1ee8ef8f6..7bd4833b9 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -671,6 +671,14 @@ packages: description: flutter source: sdk version: "0.0.0" + get_it: + dependency: "direct main" + description: + name: get_it + sha256: f79870884de16d689cf9a7d15eedf31ed61d750e813c538a6efb92660fea83c3 + url: "https://pub.dev" + source: hosted + version: "7.6.4" gettext_parser: dependency: transitive description: @@ -759,6 +767,38 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.0" + in_app_purchase: + dependency: "direct main" + description: + name: in_app_purchase + sha256: bdda02b5b11b56d5e29c7f0c57c433db3452b0c8ce1c37cbfcf1de52946efd9f + url: "https://pub.dev" + source: hosted + version: "3.1.11" + in_app_purchase_android: + dependency: transitive + description: + name: in_app_purchase_android + sha256: c4b84caa4e2c7ffebda444c5033fd8423cc3a45a6e1066929bbbcd4daf665db5 + url: "https://pub.dev" + source: hosted + version: "0.3.0+15" + in_app_purchase_platform_interface: + dependency: transitive + description: + name: in_app_purchase_platform_interface + sha256: "5168afbc54f406f741252b66d41872c1193a0066a6edcb587176290b92e2d537" + url: "https://pub.dev" + source: hosted + version: "1.3.6" + in_app_purchase_storekit: + dependency: transitive + description: + name: in_app_purchase_storekit + sha256: "88afd256c7605d431f0ce29d0161f9554851f90ecb92ceb9e18196c4e7858d52" + url: "https://pub.dev" + source: hosted + version: "0.3.6+7" infinite_scroll_pagination: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index d6074d8d7..d8da8667e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -112,10 +112,16 @@ dependencies: permission_handler: ^10.4.3 flutter_markdown: ^0.6.17+1 + # Purchase + in_app_purchase: ^3.1.11 + # Ads google_mobile_ads: ^3.0.0 # clever_ads_solutions: ^0.1.0 + # Service Locator + get_it: ^7.6.4 + # wakelock ^0.6.2 requires win32 ^2.0.0 or ^3.0.0 # See https://github.com/creativecreatorormaybenot/wakelock/issues/211 From e908c4b09e12f869cab265c22321afcf9b7b18d4 Mon Sep 17 00:00:00 2001 From: Jigar-f Date: Fri, 3 Nov 2023 18:04:51 +0530 Subject: [PATCH 07/17] Started working on API. --- internalsdk/apimodels/api.go | 37 +++++++++++++++++++++++++ internalsdk/session_model.go | 42 +++++++++++++++++++++++++++-- lib/core/purchase/app_purchase.dart | 2 +- lib/plans/reseller_checkout.dart | 2 +- 4 files changed, 79 insertions(+), 4 deletions(-) diff --git a/internalsdk/apimodels/api.go b/internalsdk/apimodels/api.go index 8a7d8979e..f07389fa1 100644 --- a/internalsdk/apimodels/api.go +++ b/internalsdk/apimodels/api.go @@ -8,6 +8,8 @@ import ( "github.com/getlantern/golog" ) +var session SessionModel + const ( baseUrl = "https://api.getiantem.org" userDetailUrl = baseUrl + "/user-data" @@ -138,3 +140,38 @@ func PlansV3(deviceId string, userId string, local string, token string, country } return &plans, nil } + +// func PurchaseRequest(planId string, email string, token string, paymentProvider string, deviceName string) error { +func PurchaseRequest(session *SessionModel, paymentProvider string) error { + base := session.baseModel + // data := map[string]interface{}{ + // "idempotencyKey": strconv.FormatInt(time.Now().UnixNano(), 10), + // "provider": paymentProvider, + // "email": email, + // "plan": planId, + // "currency": "usd", + // "deviceName": deviceName, + // } + + // switch paymentProvider { + // case PaymentProviderResellerCode: + // data["resellerCode"] = resellerCode + + // } + + // body, err := createJsonBody(data) + // if err != nil { + // log.Errorf("Error while creating json body") + // return err + // } + return nil +} + +// Utils methods convert json body +func createJsonBody(data map[string]interface{}) (*bytes.Buffer, error) { + jsonData, err := json.Marshal(data) + if err != nil { + return nil, err + } + return bytes.NewBuffer(jsonData), nil +} diff --git a/internalsdk/session_model.go b/internalsdk/session_model.go index 480e9738d..42bf61b3f 100644 --- a/internalsdk/session_model.go +++ b/internalsdk/session_model.go @@ -21,6 +21,15 @@ type SessionModel struct { *baseModel } +// Expose payment providers +const ( + PaymentProviderStripe = "stripe" + PaymentProviderFreekassa = "freekassa" + PaymentProviderGooglePlay = "googleplay" + PaymentProviderBTCPay = "btcpay" + PaymentProviderResellerCode = "reseller-code" +) + // List of we are using for Session Model const ( pathDeviceID = "deviceid" @@ -59,6 +68,7 @@ const ( pathSelectedTab = "/selectedTab" pathServerInfo = "/server_info" pathPlans = "/plans/" + pathResellerCode = "resellercode" currentTermsVersion = 1 ) @@ -163,12 +173,15 @@ func (m *SessionModel) doInvokeMethod(method string, arguments Arguments) (inter return nil, err } return true, nil - case "createUser": - err := userCreate(m.baseModel, arguments.Scalar().String()) + case "redeemResellerCode": + email := arguments.Get("email").String() + resellerCode := arguments.Get("resellerCode").String() + err := redeemResellerCode(m, email, resellerCode) if err != nil { return nil, err } return true, nil + default: return m.methodNotImplemented(method) } @@ -284,6 +297,10 @@ func (m *SessionModel) initSessionModel(opts *SessionModelOpts) error { // }() // //Get all the Plans + + //Know Issue + //When use install app first time + // Plans API is failing err = getPlansV3(m.baseModel, opts.DeviceID, userIdStr, lang, token, countryCode) if err != nil { log.Debugf("Plans V3 error: %v", err) @@ -661,6 +678,11 @@ func setUserIdAndToken(m *baseModel, userId int, token string) error { return pathdb.Put(tx, pathToken, token, "") }) } +func setResellerCode(m *baseModel, resellerCode string) error { + return pathdb.Mutate(m.db, func(tx pathdb.TX) error { + return pathdb.Put(tx, pathResellerCode, resellerCode, "") + }) +} // Create user // Todo-: Create Sprate http client to manag and reuse client @@ -774,3 +796,19 @@ func reportIssue(session *SessionModel, email string, issue string, description log.Debugf("Report an issue index %v desc %v level %v email %v, device %v model %v version %v ", issueKey, description, level, email, device, model, osVersion) return SendIssueReport(session, issueKey, description, level, email, device, model, osVersion) } + +func redeemResellerCode(m *SessionModel, email string, resellerCode string) error { + err := setEmail(m.baseModel, email) + if err != nil { + log.Errorf("Error while setting email %v", err) + return err + } + setResellerCode(m.baseModel, resellerCode) + if err != nil { + log.Errorf("Error while setting resellerCode %v", err) + return err + } + apimodels.PurchaseRequest(m, PaymentProviderResellerCode) + + return nil +} diff --git a/lib/core/purchase/app_purchase.dart b/lib/core/purchase/app_purchase.dart index fea8278b9..8641c93ee 100644 --- a/lib/core/purchase/app_purchase.dart +++ b/lib/core/purchase/app_purchase.dart @@ -6,7 +6,7 @@ class AppPurchase { final InAppPurchase _inAppPurchase = InAppPurchase.instance; StreamSubscription>? _subscription; List plansSku = []; - final Set _iosPlansIds = {"1Y"}; + final Set _iosPlansIds = {"1Y",'2Y'}; void init() { getAvailablePlans(); diff --git a/lib/plans/reseller_checkout.dart b/lib/plans/reseller_checkout.dart index 19d1ca04f..19f9aa4a0 100644 --- a/lib/plans/reseller_checkout.dart +++ b/lib/plans/reseller_checkout.dart @@ -36,7 +36,7 @@ class ResellerCodeFormatter extends TextInputFormatter { class ResellerCodeCheckout extends StatefulWidget { final bool isPro; - ResellerCodeCheckout({ + const ResellerCodeCheckout({ required this.isPro, Key? key, }) : super(key: key); From 13b4a6be5d0a23dece49054e063c774e108cdcdb Mon Sep 17 00:00:00 2001 From: Jigar-f Date: Mon, 6 Nov 2023 18:28:53 +0530 Subject: [PATCH 08/17] Implement helper for purchase request. --- internalsdk/apimodels/api.go | 66 ++++++++++++++++++++++-------------- internalsdk/session_model.go | 37 ++++++++++++++++---- internalsdk/utils.go | 35 +++++++++++++++++++ 3 files changed, 107 insertions(+), 31 deletions(-) diff --git a/internalsdk/apimodels/api.go b/internalsdk/apimodels/api.go index f07389fa1..fb8df2a42 100644 --- a/internalsdk/apimodels/api.go +++ b/internalsdk/apimodels/api.go @@ -3,18 +3,18 @@ package apimodels import ( "bytes" "encoding/json" + "io/ioutil" "net/http" "github.com/getlantern/golog" ) -var session SessionModel - const ( baseUrl = "https://api.getiantem.org" userDetailUrl = baseUrl + "/user-data" userCreateUrl = baseUrl + "/user-create" plansV3Url = baseUrl + "/plans-v3" + purchaseUrl = baseUrl + "/purchase" ) const ( @@ -141,29 +141,45 @@ func PlansV3(deviceId string, userId string, local string, token string, country return &plans, nil } -// func PurchaseRequest(planId string, email string, token string, paymentProvider string, deviceName string) error { -func PurchaseRequest(session *SessionModel, paymentProvider string) error { - base := session.baseModel - // data := map[string]interface{}{ - // "idempotencyKey": strconv.FormatInt(time.Now().UnixNano(), 10), - // "provider": paymentProvider, - // "email": email, - // "plan": planId, - // "currency": "usd", - // "deviceName": deviceName, - // } - - // switch paymentProvider { - // case PaymentProviderResellerCode: - // data["resellerCode"] = resellerCode - - // } - - // body, err := createJsonBody(data) - // if err != nil { - // log.Errorf("Error while creating json body") - // return err - // } +func PurchaseRequest(data map[string]interface{}, deviceId string, userId string, token string) error { + log.Debugf("purchase request body %v", data) + body, err := createJsonBody(data) + if err != nil { + log.Errorf("Error while creating json body") + return err + } + // Create a new request + req, err := http.NewRequest("POST", purchaseUrl, body) + if err != nil { + log.Errorf("Error creating new request: %v", err) + return err + } + + // Add headers + req.Header.Set(headerDeviceId, deviceId) + req.Header.Set(headerUserId, userId) + req.Header.Set(headerProToken, token) + + client := &http.Client{} + // Send the request + resp, err := client.Do(req) + if err != nil { + log.Errorf("Error sending puchase request: %v", err) + return err + } + + defer resp.Body.Close() + + bodyStr, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Fatalf("Error reading response body: %v", err) + return err + } + + // body is a byte slice ([]byte), often we convert it to a string for easier handling + bodyString := string(bodyStr) + log.Debugf("Purchase Request %v", bodyString) + return nil } diff --git a/internalsdk/session_model.go b/internalsdk/session_model.go index 42bf61b3f..da0ac605a 100644 --- a/internalsdk/session_model.go +++ b/internalsdk/session_model.go @@ -23,11 +23,11 @@ type SessionModel struct { // Expose payment providers const ( - PaymentProviderStripe = "stripe" - PaymentProviderFreekassa = "freekassa" - PaymentProviderGooglePlay = "googleplay" - PaymentProviderBTCPay = "btcpay" - PaymentProviderResellerCode = "reseller-code" + paymentProviderStripe = "stripe" + paymentProviderFreekassa = "freekassa" + paymentProviderGooglePlay = "googleplay" + paymentProviderBTCPay = "btcpay" + paymentProviderResellerCode = "reseller-code" ) // List of we are using for Session Model @@ -808,7 +808,32 @@ func redeemResellerCode(m *SessionModel, email string, resellerCode string) erro log.Errorf("Error while setting resellerCode %v", err) return err } - apimodels.PurchaseRequest(m, PaymentProviderResellerCode) + + err, purchaseData := createPurchaseData(m, paymentProviderResellerCode, resellerCode) + if err != nil { + log.Errorf("Error while creating purchase data %v", err) + return err + } + + deviecId, err := m.GetDeviceID() + if err != nil { + return err + } + userId, err := m.GetUserID() + if err != nil { + return err + } + userIdStr := fmt.Sprintf("%d", userId) + + token, err := m.GetToken() + if err != nil { + return err + } + + err = apimodels.PurchaseRequest(purchaseData, deviecId, userIdStr, token) + if err != nil { + return err + } return nil } diff --git a/internalsdk/utils.go b/internalsdk/utils.go index 32022084f..17285eeea 100644 --- a/internalsdk/utils.go +++ b/internalsdk/utils.go @@ -4,11 +4,14 @@ import ( "encoding/binary" "fmt" "math" + "strconv" "strings" + "time" "github.com/bojanz/currency" "github.com/getlantern/android-lantern/internalsdk/apimodels" "github.com/getlantern/errors" + "github.com/getlantern/pathdb" ) func BytesToFloat64LittleEndian(b []byte) (float64, error) { @@ -97,3 +100,35 @@ func formatRenewalBonusExpected(months int64, days int64, longForm bool) string return fmt.Sprintf("%d %s", totalDays, dayStr) } } + +//Create Purchase Request + +func createPurchaseData(session *SessionModel, paymentProvider string, resellerCode string) (error, map[string]interface{}) { + email, err := session.Email() + if err != nil { + return err, nil + } + + device, err := pathdb.Get[string](session.db, pathDevice) + if err != nil { + return err, nil + } + + data := map[string]interface{}{ + "idempotencyKey": strconv.FormatInt(time.Now().UnixNano(), 10), + "provider": paymentProvider, + "email": email, + "deviceName": device, + } + + switch paymentProvider { + case paymentProviderResellerCode: + data["provider"] = "reseller-code" + data["resellerCode"] = resellerCode + data["currency"] = "usd" + data["plan"] = "" + } + + return nil, data + +} From adff056c8c61d75e51fd8656e59f7cb34a1252ec Mon Sep 17 00:00:00 2001 From: Jigar-f Date: Tue, 7 Nov 2023 13:25:06 +0530 Subject: [PATCH 09/17] Implemented Promo code flow. --- internalsdk/apimodels/api.go | 37 ++++++++--------- internalsdk/apimodels/json_models.go | 8 ++++ internalsdk/session_model.go | 9 +++- internalsdk/utils.go | 8 ++-- lib/common/session_model.dart | 4 +- lib/plans/reseller_checkout.dart | 62 ++++++++++++++-------------- lib/plans/utils.dart | 4 +- 7 files changed, 75 insertions(+), 57 deletions(-) diff --git a/internalsdk/apimodels/api.go b/internalsdk/apimodels/api.go index fb8df2a42..383da6645 100644 --- a/internalsdk/apimodels/api.go +++ b/internalsdk/apimodels/api.go @@ -3,7 +3,6 @@ package apimodels import ( "bytes" "encoding/json" - "io/ioutil" "net/http" "github.com/getlantern/golog" @@ -18,9 +17,10 @@ const ( ) const ( - headerDeviceId = "X-Lantern-Device-Id" - headerUserId = "X-Lantern-User-Id" - headerProToken = "X-Lantern-Pro-Token" + headerDeviceId = "X-Lantern-Device-Id" + headerUserId = "X-Lantern-User-Id" + headerProToken = "X-Lantern-Pro-Token" + headerContentType = "Content-Type" ) var ( @@ -141,50 +141,49 @@ func PlansV3(deviceId string, userId string, local string, token string, country return &plans, nil } -func PurchaseRequest(data map[string]interface{}, deviceId string, userId string, token string) error { +func PurchaseRequest(data map[string]string, deviceId string, userId string, token string) (*PurchaseResponse, error) { log.Debugf("purchase request body %v", data) body, err := createJsonBody(data) if err != nil { log.Errorf("Error while creating json body") - return err + return nil, err } + + log.Debugf("Encoded body %v", body) // Create a new request req, err := http.NewRequest("POST", purchaseUrl, body) if err != nil { log.Errorf("Error creating new request: %v", err) - return err + return nil, err } // Add headers req.Header.Set(headerDeviceId, deviceId) req.Header.Set(headerUserId, userId) req.Header.Set(headerProToken, token) + req.Header.Set(headerContentType, "application/json") client := &http.Client{} // Send the request resp, err := client.Do(req) if err != nil { log.Errorf("Error sending puchase request: %v", err) - return err + return nil, err } defer resp.Body.Close() - bodyStr, err := ioutil.ReadAll(resp.Body) - if err != nil { - log.Fatalf("Error reading response body: %v", err) - return err + var purchase PurchaseResponse + // Read and decode the response body + if err := json.NewDecoder(resp.Body).Decode(&purchase); err != nil { + log.Errorf("Error decoding response body: %v", err) + return nil, err } - - // body is a byte slice ([]byte), often we convert it to a string for easier handling - bodyString := string(bodyStr) - log.Debugf("Purchase Request %v", bodyString) - - return nil + return &purchase, nil } // Utils methods convert json body -func createJsonBody(data map[string]interface{}) (*bytes.Buffer, error) { +func createJsonBody(data map[string]string) (*bytes.Buffer, error) { jsonData, err := json.Marshal(data) if err != nil { return nil, err diff --git a/internalsdk/apimodels/json_models.go b/internalsdk/apimodels/json_models.go index fb0d50468..0d6bbe360 100644 --- a/internalsdk/apimodels/json_models.go +++ b/internalsdk/apimodels/json_models.go @@ -106,3 +106,11 @@ type Provider struct { type Data struct { PubKey string `json:"pubKey"` } + +//Purchase Request + +type PurchaseResponse struct { + PaymentStatus string `json:"paymentStatus"` + Plan Plan `json:"plan"` + Status string `json:"status"` +} diff --git a/internalsdk/session_model.go b/internalsdk/session_model.go index da0ac605a..b3889d8dd 100644 --- a/internalsdk/session_model.go +++ b/internalsdk/session_model.go @@ -829,11 +829,16 @@ func redeemResellerCode(m *SessionModel, email string, resellerCode string) erro if err != nil { return err } - - err = apimodels.PurchaseRequest(purchaseData, deviecId, userIdStr, token) + purchase, err := apimodels.PurchaseRequest(purchaseData, deviecId, userIdStr, token) if err != nil { return err } + log.Debugf("Purchase Request response %v", purchase) + // Set user to pro + err = setProUser(m.baseModel, true) + if err != nil { + return err + } return nil } diff --git a/internalsdk/utils.go b/internalsdk/utils.go index 17285eeea..0ffc1ba0d 100644 --- a/internalsdk/utils.go +++ b/internalsdk/utils.go @@ -103,18 +103,18 @@ func formatRenewalBonusExpected(months int64, days int64, longForm bool) string //Create Purchase Request -func createPurchaseData(session *SessionModel, paymentProvider string, resellerCode string) (error, map[string]interface{}) { +func createPurchaseData(session *SessionModel, paymentProvider string, resellerCode string) (error, map[string]string) { email, err := session.Email() if err != nil { return err, nil } - device, err := pathdb.Get[string](session.db, pathDevice) + device, err := pathdb.Get[string](session.db, pathModel) if err != nil { return err, nil } - data := map[string]interface{}{ + data := map[string]string{ "idempotencyKey": strconv.FormatInt(time.Now().UnixNano(), 10), "provider": paymentProvider, "email": email, @@ -123,7 +123,7 @@ func createPurchaseData(session *SessionModel, paymentProvider string, resellerC switch paymentProvider { case paymentProviderResellerCode: - data["provider"] = "reseller-code" + data["provider"] = paymentProviderResellerCode data["resellerCode"] = resellerCode data["currency"] = "usd" data["plan"] = "" diff --git a/lib/common/session_model.dart b/lib/common/session_model.dart index b1e162063..f33d3f09b 100644 --- a/lib/common/session_model.dart +++ b/lib/common/session_model.dart @@ -368,7 +368,9 @@ class SessionModel extends Model { return methodChannel.invokeMethod('redeemResellerCode', { 'email': email, 'resellerCode': resellerCode, - }).then((value) => value as String); + }).then((value) { + print("value $value"); + }); } Future submitBitcoinPayment( diff --git a/lib/plans/reseller_checkout.dart b/lib/plans/reseller_checkout.dart index 19f9aa4a0..c40e9377f 100644 --- a/lib/plans/reseller_checkout.dart +++ b/lib/plans/reseller_checkout.dart @@ -51,7 +51,7 @@ class _ResellerCodeCheckoutState extends State { formKey: emailFieldKey, validator: (value) => EmailValidator.validate(value ?? '') ? null - : 'please_enter_a_valid_email_address'.i18n, + : 'please_entera_valid_email_address'.i18n, ); final resellerCodeFieldKey = GlobalKey(); @@ -156,35 +156,7 @@ class _ResellerCodeCheckoutState extends State { emailFieldKey.currentState?.validate() == false || resellerCodeFieldKey.currentState?.validate() == false, text: copy, - onPressed: () async { - context.loaderOverlay.show(); - await sessionModel - .redeemResellerCode( - emailController.text, - resellerCodeController.text, - ) - .timeout( - defaultTimeoutDuration, - onTimeout: () => onAPIcallTimeout( - code: 'redeemresellerCodeTimeout', - message: 'reseller_timeout'.i18n, - ), - ) - .then((value) { - context.loaderOverlay.hide(); - showSuccessDialog(context, widget.isPro, true); - }).onError((error, stackTrace) { - context.loaderOverlay.hide(); - CDialog.showError( - context, - error: e, - stackTrace: stackTrace, - description: (error as PlatformException) - .message - .toString(), // This is coming localized - ); - }); - }, + onPressed: onRegisterTap, ), ], ) @@ -194,4 +166,34 @@ class _ResellerCodeCheckoutState extends State { ); }); } + + Future onRegisterTap() async { + context.loaderOverlay.show(); + try { + await sessionModel + .redeemResellerCode( + emailController.text, + resellerCodeController.text, + ).timeout( + defaultTimeoutDuration, + onTimeout: () => onAPIcallTimeout( + code: 'redeemresellerCodeTimeout', + message: 'reseller_timeout'.i18n, + ), + ); + + context.loaderOverlay.hide(); + showSuccessDialog(context, widget.isPro, true); + } catch (error,s) { + context.loaderOverlay.hide(); + CDialog.showError( + context, + error: e, + stackTrace: s, + description: (error as PlatformException) + .message + .toString(), // This is coming localized + ); + } + } } diff --git a/lib/plans/utils.dart b/lib/plans/utils.dart index 204213adf..f1d4ff644 100644 --- a/lib/plans/utils.dart +++ b/lib/plans/utils.dart @@ -33,7 +33,9 @@ void showSuccessDialog(BuildContext context, bool isPro, [bool? isReseller]) { description: description, actionLabel: 'continue_to_pro'.i18n, agreeAction: () async { - await context.pushRoute(Home()); + // Note: whatever page you need to popUtil + // it will pop that page + context.router.popUntil((route) => route.settings.name == PlansPage.name); return true; }, ); From c8a402ee3adc9fad78f4988808025c862aa150bc Mon Sep 17 00:00:00 2001 From: Jigar-f Date: Tue, 7 Nov 2023 16:41:03 +0530 Subject: [PATCH 10/17] Fixed issue device nog showing up. --- internalsdk/session_model.go | 6 +++++- lib/account/account_management.dart | 2 +- lib/common/session_model.dart | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/internalsdk/session_model.go b/internalsdk/session_model.go index b3889d8dd..adc9885a1 100644 --- a/internalsdk/session_model.go +++ b/internalsdk/session_model.go @@ -94,6 +94,7 @@ func NewSessionModel(mdb minisql.DB, opts *SessionModelOpts) (*SessionModel, err } base.db.RegisterType(1000, &protos.ServerInfo{}) base.db.RegisterType(2000, &protos.Devices{}) + base.db.RegisterType(5000, &protos.Device{}) base.db.RegisterType(3000, &protos.Plan{}) base.db.RegisterType(4000, &protos.Plans{}) m := &SessionModel{baseModel: base} @@ -448,6 +449,7 @@ func setLanguage(m *baseModel, lang string) error { } func setDevices(m *baseModel, devices []apimodels.UserDevice) error { + log.Debugf("Device list %v", devices) var protoDevices []*protos.Device for _, device := range devices { protoDevice := &protos.Device{ @@ -458,10 +460,12 @@ func setDevices(m *baseModel, devices []apimodels.UserDevice) error { protoDevices = append(protoDevices, protoDevice) } + userDevice := &protos.Devices{Devices: protoDevices} pathdb.Mutate(m.db, func(tx pathdb.TX) error { - pathdb.Put(tx, pathDevices, protoDevices, "") + pathdb.Put(tx, pathDevices, userDevice, "") return nil }) + log.Debugf("Device stored successfully") return nil } diff --git a/lib/account/account_management.dart b/lib/account/account_management.dart index fdeb2fb2f..dffd30e1d 100644 --- a/lib/account/account_management.dart +++ b/lib/account/account_management.dart @@ -2,7 +2,7 @@ import 'package:lantern/messaging/messaging.dart'; @RoutePage(name: 'AccountManagement') class AccountManagement extends StatefulWidget { - AccountManagement({Key? key, required this.isPro}) : super(key: key); + const AccountManagement({Key? key, required this.isPro}) : super(key: key); final bool isPro; @override diff --git a/lib/common/session_model.dart b/lib/common/session_model.dart index f33d3f09b..381b057d1 100644 --- a/lib/common/session_model.dart +++ b/lib/common/session_model.dart @@ -149,6 +149,7 @@ class SessionModel extends Model { 'devices', builder: builder, deserialize: (Uint8List serialized) { + print("devices $serialized"); return Devices.fromBuffer(serialized); }, ); From 1453a51d95fb5ffbefb3e3bc10b344852471bbd6 Mon Sep 17 00:00:00 2001 From: Jigar-f Date: Tue, 7 Nov 2023 17:00:05 +0530 Subject: [PATCH 11/17] Calculate Expirydate --- internalsdk/session_model.go | 26 ++++++++++++++++++++ ios/Runner/Lantern/Models/SessionModel.swift | 2 +- lib/account/account_management.dart | 3 ++- 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/internalsdk/session_model.go b/internalsdk/session_model.go index adc9885a1..853f8b2f2 100644 --- a/internalsdk/session_model.go +++ b/internalsdk/session_model.go @@ -5,6 +5,7 @@ import ( "path/filepath" "strconv" "strings" + "time" "github.com/getlantern/android-lantern/internalsdk/apimodels" "github.com/getlantern/android-lantern/internalsdk/protos" @@ -69,6 +70,8 @@ const ( pathServerInfo = "/server_info" pathPlans = "/plans/" pathResellerCode = "resellercode" + pathExpirydate = "expirydate" + pathExpirystr = "expirydatestr" currentTermsVersion = 1 ) @@ -429,6 +432,23 @@ func setUserLevel(m *baseModel, userLevel string) error { return pathdb.Put(tx, pathUserLevel, userLevel, "") }) } +func setExpiration(m *baseModel, expiration int64) error { + if expiration == 0 { + return nil + } + + expiry := time.Unix(0, expiration*int64(time.Second)) + dateFormat := "01/02/2006" + dateStr := expiry.Format(dateFormat) + + return pathdb.Mutate(m.db, func(tx pathdb.TX) error { + err := pathdb.Put[string](tx, pathExpirystr, dateStr, "") + if err != nil { + return err + } + return pathdb.Put[int64](tx, pathExpirydate, expiration, "") + }) +} func getUserLevel(m *baseModel) (string, error) { return pathdb.Get[string](m.db, pathUserLevel) @@ -745,6 +765,7 @@ func cacheUserDetail(m *baseModel, userDetail *apimodels.UserDetailResponse) err return err } } + if userDetail.UserStatus != "" && userDetail.UserStatus == "active" && userDetail.UserLevel == "pro" { setProUser(m, true) } else { @@ -755,6 +776,11 @@ func cacheUserDetail(m *baseModel, userDetail *apimodels.UserDetailResponse) err return err } + err = setExpiration(m, userDetail.Expiration) + if err != nil { + return err + } + //Store all device err = setDevices(m, userDetail.Devices) if err != nil { diff --git a/ios/Runner/Lantern/Models/SessionModel.swift b/ios/Runner/Lantern/Models/SessionModel.swift index ed7b56d43..adff2fb29 100644 --- a/ios/Runner/Lantern/Models/SessionModel.swift +++ b/ios/Runner/Lantern/Models/SessionModel.swift @@ -30,7 +30,7 @@ class SessionModel: BaseModel { opts.playVersion = (isRunningFromAppStore() || isRunningInTestFlightEnvironment()) opts.timeZone = TimeZone.current.identifier opts.device = systemName // IOS does not provide Device name directly - opts.model = systemName + opts.model = model opts.osVersion = systemVersion opts.paymentTestMode = AppEnvironment.current == AppEnvironment.appiumTest diff --git a/lib/account/account_management.dart b/lib/account/account_management.dart index dffd30e1d..cf3d4cf1f 100644 --- a/lib/account/account_management.dart +++ b/lib/account/account_management.dart @@ -257,7 +257,8 @@ class _AccountManagementState extends State }), ); - if (devices.devices.length < 3) { + // IOS does not support Link devices at the moment + if (devices.devices.length < 3&& Platform.isAndroid ) { proItems.add( ListItemFactory.settingsItem( content: '', From de360376351d54bbe0f309f3d2afbc818cf6e028 Mon Sep 17 00:00:00 2001 From: Jigar-f Date: Wed, 8 Nov 2023 17:33:44 +0530 Subject: [PATCH 12/17] Added mock API call for apple pay. --- internalsdk/session_model.go | 43 +++++++++++++++++++++++++++-- internalsdk/utils.go | 7 ++++- lib/common/session_model.dart | 8 ++++++ lib/core/purchase/app_purchase.dart | 42 ++++++++++++++++++++++++---- lib/plans/plan_details.dart | 6 +++- 5 files changed, 95 insertions(+), 11 deletions(-) diff --git a/internalsdk/session_model.go b/internalsdk/session_model.go index 853f8b2f2..5c21bbd52 100644 --- a/internalsdk/session_model.go +++ b/internalsdk/session_model.go @@ -27,6 +27,7 @@ const ( paymentProviderStripe = "stripe" paymentProviderFreekassa = "freekassa" paymentProviderGooglePlay = "googleplay" + paymentProviderApplePay = "applepay" paymentProviderBTCPay = "btcpay" paymentProviderResellerCode = "reseller-code" ) @@ -186,6 +187,15 @@ func (m *SessionModel) doInvokeMethod(method string, arguments Arguments) (inter } return true, nil + case "submitApplePayPayment": + plandId := arguments.Get("planID").String() + purchaseId := arguments.Get("purchaseId").String() + err := submitApplePayPayment(m, plandId, purchaseId) + if err != nil { + return nil, err + } + return true, nil + default: return m.methodNotImplemented(method) } @@ -839,7 +849,7 @@ func redeemResellerCode(m *SessionModel, email string, resellerCode string) erro return err } - err, purchaseData := createPurchaseData(m, paymentProviderResellerCode, resellerCode) + err, purchaseData := createPurchaseData(m, paymentProviderResellerCode, resellerCode, "") if err != nil { log.Errorf("Error while creating purchase data %v", err) return err @@ -866,9 +876,36 @@ func redeemResellerCode(m *SessionModel, email string, resellerCode string) erro log.Debugf("Purchase Request response %v", purchase) // Set user to pro - err = setProUser(m.baseModel, true) + return setProUser(m.baseModel, true) +} + +func submitApplePayPayment(m *SessionModel, planId string, purchaseToken string) error { + err, purchaseData := createPurchaseData(m, paymentProviderApplePay, "", purchaseToken) + if err != nil { + log.Errorf("Error while creating purchase data %v", err) + return err + } + + deviecId, err := m.GetDeviceID() if err != nil { return err } - return nil + userId, err := m.GetUserID() + if err != nil { + return err + } + userIdStr := fmt.Sprintf("%d", userId) + + token, err := m.GetToken() + if err != nil { + return err + } + purchase, err := apimodels.PurchaseRequest(purchaseData, deviecId, userIdStr, token) + if err != nil { + return err + } + log.Debugf("Purchase Request response %v", purchase) + + // Set user to pro + return setProUser(m.baseModel, true) } diff --git a/internalsdk/utils.go b/internalsdk/utils.go index 0ffc1ba0d..7222b9378 100644 --- a/internalsdk/utils.go +++ b/internalsdk/utils.go @@ -103,7 +103,7 @@ func formatRenewalBonusExpected(months int64, days int64, longForm bool) string //Create Purchase Request -func createPurchaseData(session *SessionModel, paymentProvider string, resellerCode string) (error, map[string]string) { +func createPurchaseData(session *SessionModel, paymentProvider string, resellerCode string, purchaseToken string) (error, map[string]string) { email, err := session.Email() if err != nil { return err, nil @@ -127,6 +127,11 @@ func createPurchaseData(session *SessionModel, paymentProvider string, resellerC data["resellerCode"] = resellerCode data["currency"] = "usd" data["plan"] = "" + case paymentProviderApplePay: + data["token"] = purchaseToken + data["currency"] = "usd" + data["plan"] = "" + } return nil, data diff --git a/lib/common/session_model.dart b/lib/common/session_model.dart index 381b057d1..faaaa3a90 100644 --- a/lib/common/session_model.dart +++ b/lib/common/session_model.dart @@ -393,6 +393,14 @@ class SessionModel extends Model { }).then((value) => value as String); } + Future submitApplePlay(String planID,String purchaseToken) async { + return methodChannel + .invokeMethod('submitApplePayPayment', { + 'planID': planID, + 'purchaseId': purchaseToken, + }).then((value) => value as String); + } + Future submitStripePayment( String planID, String email, diff --git a/lib/core/purchase/app_purchase.dart b/lib/core/purchase/app_purchase.dart index 8641c93ee..5f526b08e 100644 --- a/lib/core/purchase/app_purchase.dart +++ b/lib/core/purchase/app_purchase.dart @@ -1,4 +1,6 @@ import 'package:in_app_purchase/in_app_purchase.dart'; +import 'package:lantern/replica/common.dart'; +import 'package:sentry_flutter/sentry_flutter.dart'; import '../../common/common.dart'; @@ -6,7 +8,10 @@ class AppPurchase { final InAppPurchase _inAppPurchase = InAppPurchase.instance; StreamSubscription>? _subscription; List plansSku = []; - final Set _iosPlansIds = {"1Y",'2Y'}; + final Set _iosPlansIds = {"1Y", '2Y'}; + VoidCallback? _onSuccess; + Function(dynamic error)? _onError; + String _planId = ""; void init() { getAvailablePlans(); @@ -24,7 +29,12 @@ class AppPurchase { plansSku.addAll(response.productDetails); } - void startPurchase(String planId) { + void startPurchase(String planId, + {required VoidCallback onSuccess, + required Function(dynamic error) onFailure}) { + _planId = planId; + _onSuccess = onSuccess; + _onError = onFailure; final plan = _normalizePlan(planId); final purchaseParam = PurchaseParam(productDetails: plan); _inAppPurchase.buyConsumable(purchaseParam: purchaseParam); @@ -41,22 +51,42 @@ class AppPurchase { } // Internal methods - Future _onPurchaseUpdate(List purchaseDetailsList) async { - // Handle purchases here - for (final purchase in purchaseDetailsList) { - print("purchase $purchase"); + Future _onPurchaseUpdate( + List purchaseDetailsList) async { + print("purchase length ${purchaseDetailsList.length}"); + final purchase = purchaseDetailsList[0]; + // // Handle purchases here + // for (final purchase in purchaseDetailsList) { + // print("purchase $purchase"); + // } + + logger.i('Calling Purchase API'); + try { + sessionModel.submitApplePlay(_planId, purchase.purchaseID!); + + //Check if purchase is sill in pending state complete purchase if (purchase.pendingCompletePurchase) { await _inAppPurchase.completePurchase(purchase); } + _onSuccess?.call(); + } catch (e) { + logger.e('Error while calling purchase api', error: e); + Sentry.captureException(e); } } void _updateStreamOnDone() { + _onError = null; + _onSuccess = null; + _planId = ""; _subscription?.cancel(); } void _updateStreamOnError(dynamic error) { //Handle error here print("purchase error $error"); + if (_onError != null) { + _onError?.call(error); + } } } diff --git a/lib/plans/plan_details.dart b/lib/plans/plan_details.dart index 05c2c53e2..47dbd97bf 100644 --- a/lib/plans/plan_details.dart +++ b/lib/plans/plan_details.dart @@ -151,7 +151,11 @@ class PlanCard extends StatelessWidget { } else { // * Proceed to IOSs final appPurchase = sl(); - appPurchase.startPurchase(plan.id); + appPurchase.startPurchase( + plan.id, + onSuccess: () {}, + onFailure: (error) {}, + ); } } } From 7f0370448620c58a6473440c40ad88acca34aa02 Mon Sep 17 00:00:00 2001 From: Jigar-f Date: Thu, 9 Nov 2023 18:23:55 +0530 Subject: [PATCH 13/17] Run mode tidy and removes static data. --- go.sum | 260 +++++++++++------------------------ internalsdk/session_model.go | 2 +- 2 files changed, 80 insertions(+), 182 deletions(-) diff --git a/go.sum b/go.sum index de502a4fb..963764a3e 100644 --- a/go.sum +++ b/go.sum @@ -8,33 +8,23 @@ cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= crawshaw.io/iox v0.0.0-20181124134642-c51c3df30797 h1:yDf7ARQc637HoxDho7xjqdvO5ZA2Yb+xzv/fOnnvZzw= crawshaw.io/iox v0.0.0-20181124134642-c51c3df30797/go.mod h1:sXBiorCo8c46JlQV3oXPKINnZ8mcqnye1EkVkqsectk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -filippo.io/edwards25519 v1.0.0-rc.1.0.20210721174708-390f27c3be20 h1:iJoUgXvhagsNMrJrvavw7vu1eG8+hm6jLOxlLFcoODw= filippo.io/edwards25519 v1.0.0-rc.1.0.20210721174708-390f27c3be20/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= +filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek= +filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= git.torproject.org/pluggable-transports/goptlib.git v1.0.0/go.mod h1:YT4XMSkuEXbtqlydr9+OxqFAyspUv0Gr9qhM3B++o/Q= git.torproject.org/pluggable-transports/goptlib.git v1.3.0 h1:G+iuRUblCCC2xnO+0ag1/4+aaM98D5mjWP1M0v9s8a0= git.torproject.org/pluggable-transports/goptlib.git v1.3.0/go.mod h1:4PBMl1dg7/3vMWSoWb46eGWlrxkUyn/CAJmxhDLAlDs= @@ -51,16 +41,16 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/FZambia/sentinel v1.0.0/go.mod h1:ytL1Am/RLlAoAXG6Kj5LNuw/TRRQrv2rt2FT26vP5gI= github.com/HdrHistogram/hdrhistogram-go v1.1.0/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/OperatorFoundation/Replicant-go/Replicant/v3 v3.0.18 h1:X9YwrPdOBnE50znY+zJp1mSjoNMmlGh+IyMGgp0FZUQ= -github.com/OperatorFoundation/Replicant-go/Replicant/v3 v3.0.18/go.mod h1:nKEZhzG+AdShUn/S4iagty1ZvrXYlfR61Yy5+L5QSiw= -github.com/OperatorFoundation/Starbridge-go/Starbridge/v3 v3.0.15 h1:0+m6/vYoq+IaToQzbBxB9I/MjwqinzNexY1lIPybez0= -github.com/OperatorFoundation/Starbridge-go/Starbridge/v3 v3.0.15/go.mod h1:Fom8ZiXWCvpSuxC0mEx+kKfSfc8xmS0EVPq2/uxgBpw= +github.com/OperatorFoundation/Replicant-go/Replicant/v3 v3.0.23 h1:g0kC1BDonLwNse78HRsudElKEDfXHusLQ9Nfekl/l0o= +github.com/OperatorFoundation/Replicant-go/Replicant/v3 v3.0.23/go.mod h1:QVlygHzbNc/fX+OHurCRC0AFwISJAUQbPaqdEfAkUio= +github.com/OperatorFoundation/Starbridge-go/Starbridge/v3 v3.0.17 h1:F7IpGVx5URu+s1v9JqioSz+1AE2O+QvQZ8Vl0q6JH8w= +github.com/OperatorFoundation/Starbridge-go/Starbridge/v3 v3.0.17/go.mod h1:CbJW3yjWzIzHMEChQ4X6gvXeSf/CCpKOYQltQU8DC/s= github.com/OperatorFoundation/ghostwriter-go v1.0.6 h1:2E5D4qDKwsV+LQoKGtgIyjq5JvMiBZf8ySR8q0PP4vc= github.com/OperatorFoundation/ghostwriter-go v1.0.6/go.mod h1:+uejzC1RRxZwngnCArqZX3d7i6ZX4Si8jNG8G6oCIKQ= github.com/OperatorFoundation/go-bloom v1.0.1 h1:8q/rfgfG7OvwGkmzusIuV8PlS8MvA/T0kQ2MXm9371g= github.com/OperatorFoundation/go-bloom v1.0.1/go.mod h1:b6bJWAnYIhwDgFIIolHyeuTYbPWAYj1Lnnwvcoa7P38= -github.com/OperatorFoundation/go-shadowsocks2 v1.1.15 h1:g2tyzfsV2d8cnwe5/RaCAuzI9reLupE3GVafM+abqqU= -github.com/OperatorFoundation/go-shadowsocks2 v1.1.15/go.mod h1:yw8jel8UNDWkJNE3wwAfEyctdCw6DI1FWBrZgcuoBfI= +github.com/OperatorFoundation/go-shadowsocks2 v1.2.1 h1:hyf+kZq2rb/Kjw440hZUuedV0UG4DeB4irW6c0cPpOE= +github.com/OperatorFoundation/go-shadowsocks2 v1.2.1/go.mod h1:lH6+PiEc2/aDpMqZrLzMz+o2dlE1rPME6GYZN1j4Bsg= github.com/PuerkitoBio/goquery v1.8.1 h1:uQxhNlArOIdbrH1tr0UXwdVFgDcZDrZVdcpygAcwmWM= github.com/PuerkitoBio/goquery v1.8.1/go.mod h1:Q8ICL1kNUJ2sXGoAhPGUdYDJvgQgHzJsnnd3H7Ho5jQ= github.com/RoaringBitmap/roaring v0.4.7/go.mod h1:8khRDP4HmeXns4xIj9oGrKSz7XTQiJx2zgh7AcNke4w= @@ -94,8 +84,8 @@ github.com/alicebob/miniredis v2.5.0+incompatible/go.mod h1:8HZjEj4yU0dwhYHky+Dx github.com/alicebob/miniredis/v2 v2.15.1/go.mod h1:gquAfGbzn92jvtrSC69+6zZnwSODVXVpYDRaGhWaL6I= github.com/anacrolix/chansync v0.3.0 h1:lRu9tbeuw3wl+PhMu/r+JJCRu5ArFXIluOgdF0ao6/U= github.com/anacrolix/chansync v0.3.0/go.mod h1:DZsatdsdXxD0WiwcGl0nJVwyjCKMDv+knl1q2iBjA2k= -github.com/anacrolix/confluence v1.11.1-0.20220330234942-3c7a0c445dad h1:KP7qkQCOxvmKKTnr/2hcb0J6/VZ7aUT/9YArZGizeMM= -github.com/anacrolix/confluence v1.11.1-0.20220330234942-3c7a0c445dad/go.mod h1:f4JSWzsXnqHaz/lDXbHRaisy/cUsITruVOgaWhAlsAM= +github.com/anacrolix/confluence v1.12.0 h1:NgrsfhebrJUiZgFfFCqPvV3L23k3kOJdkLXhNhlrnAs= +github.com/anacrolix/confluence v1.12.0/go.mod h1:u0JTZ8Et0hC6MwSySOeYy11cUC0qGA7ntKvlIjOkfYI= github.com/anacrolix/dht/v2 v2.20.0 h1:eDx9lfE9iCSf5sPK0290GToHURNhEFuUGN8iyvhvJDk= github.com/anacrolix/dht/v2 v2.20.0/go.mod h1:SDGC+sEs1pnO2sJGYuhvIis7T8749dDHNfcjtdH4e3g= github.com/anacrolix/envpprof v0.0.0-20180404065416-323002cec2fa/go.mod h1:KgHhUaQMc8cC0+cEflSgCFNFbKwi5h54gqtVn8yhP7c= @@ -103,8 +93,8 @@ github.com/anacrolix/envpprof v1.0.0/go.mod h1:KgHhUaQMc8cC0+cEflSgCFNFbKwi5h54g github.com/anacrolix/envpprof v1.1.0/go.mod h1:My7T5oSqVfEn4MD4Meczkw/f5lSIndGAKu/0SM/rkf4= github.com/anacrolix/envpprof v1.2.1 h1:25TJe6t/i0AfzzldiGFKCpD+s+dk8lONBcacJZB2rdE= github.com/anacrolix/envpprof v1.2.1/go.mod h1:My7T5oSqVfEn4MD4Meczkw/f5lSIndGAKu/0SM/rkf4= -github.com/anacrolix/generics v0.0.0-20230428105757-683593396d68 h1:fyXlBfnlFzZSFckJ8QLb2lfmWfY++4RiUnae7ZMuv0A= -github.com/anacrolix/generics v0.0.0-20230428105757-683593396d68/go.mod h1:ff2rHB/joTV03aMSSn/AZNnaIpUw0h3njetGsaXcMy8= +github.com/anacrolix/generics v0.0.0-20230816103846-fe11fdc0e0e3 h1:O5xBrk97JnkTZdTsxsnQOBfD22/4L5rJXrBZrKUhJOY= +github.com/anacrolix/generics v0.0.0-20230816103846-fe11fdc0e0e3/go.mod h1:ff2rHB/joTV03aMSSn/AZNnaIpUw0h3njetGsaXcMy8= github.com/anacrolix/go-libutp v1.3.1 h1:idJzreNLl+hNjGC3ZnUOjujEaryeOGgkwHLqSGoige0= github.com/anacrolix/go-libutp v1.3.1/go.mod h1:heF41EC8kN0qCLMokLBVkB8NXiLwx3t8R8810MTNI5o= github.com/anacrolix/log v0.3.0/go.mod h1:lWvLTqzAnCWPJA08T2HCstZi0L1y2Wyvm3FJgwU9jwU= @@ -133,8 +123,8 @@ github.com/anacrolix/mmsg v1.0.0 h1:btC7YLjOn29aTUAExJiVUhQOuf/8rhm+/nWCMAnL3Hg= github.com/anacrolix/mmsg v1.0.0/go.mod h1:x8kRaJY/dCrY9Al0PEcj1mb/uFHwP6GCJ9fLl4thEPc= github.com/anacrolix/multiless v0.3.1-0.20221221005021-2d12701f83f7 h1:lOtCD+LzoD1g7bowhYJNR++uV+FyY5bTZXKwnPex9S8= github.com/anacrolix/multiless v0.3.1-0.20221221005021-2d12701f83f7/go.mod h1:zJv1JF9AqdZiHwxqPgjuOZDGWER6nyE48WBCi/OOrMM= -github.com/anacrolix/squirrel v0.4.1-0.20230623120945-75cf0ad9a958 h1:A+tNxHKFCGj/CP8WaQDZC+QwDjjoXUHDByIzKVyzKw4= -github.com/anacrolix/squirrel v0.4.1-0.20230623120945-75cf0ad9a958/go.mod h1:YzgVvikMdFD441oTWlNG189bpKabO9Sbf3uCSVgca04= +github.com/anacrolix/squirrel v0.4.1 h1:AmyXOEADG24keqgzutp+ioxJInpWHvVqeWOiHTbkeXk= +github.com/anacrolix/squirrel v0.4.1/go.mod h1:YzgVvikMdFD441oTWlNG189bpKabO9Sbf3uCSVgca04= github.com/anacrolix/stm v0.2.0/go.mod h1:zoVQRvSiGjGoTmbM0vSLIiaKjWtNPeTvXUSdJQA4hsg= github.com/anacrolix/stm v0.4.1-0.20221221005312-96d17df0e496 h1:aMiRi2kOOd+nG64suAmFMVnNK2E6GsnLif7ia9tI3cA= github.com/anacrolix/stm v0.4.1-0.20221221005312-96d17df0e496/go.mod h1:DBm8/1OXm4A4RZ6Xa9u/eOsjeAXCaoRYvd2JzlskXeM= @@ -145,8 +135,8 @@ github.com/anacrolix/sync v0.4.0/go.mod h1:BbecHL6jDSExojhNtgTFSBcdGerzNc64tz3DC github.com/anacrolix/tagflag v0.0.0-20180109131632-2146c8d41bf0/go.mod h1:1m2U/K6ZT+JZG0+bdMK6qauP49QT4wE5pmhJXOKKCHw= github.com/anacrolix/tagflag v1.0.0/go.mod h1:1m2U/K6ZT+JZG0+bdMK6qauP49QT4wE5pmhJXOKKCHw= github.com/anacrolix/tagflag v1.1.0/go.mod h1:Scxs9CV10NQatSmbyjqmqmeQNwGzlNe0CMUMIxqHIG8= -github.com/anacrolix/torrent v1.52.1 h1:y5MW2EkXgkVyWbmoYFj2qVpy/3TchYpCEEulxrV45cE= -github.com/anacrolix/torrent v1.52.1/go.mod h1:3FzugiL498Wp8yMm064ZjARChHXAtlgk36/TrkYhzio= +github.com/anacrolix/torrent v1.52.6 h1:QRLte7x68cXvAmG6WpBqInl0ayCxBYaG1bOP5busnaI= +github.com/anacrolix/torrent v1.52.6/go.mod h1:dA7tlQGWx1oCogZcnvjTCU2pQaNOyY2YgyG2kumC1H0= github.com/anacrolix/upnp v0.1.3-0.20220123035249-922794e51c96 h1:QAVZ3pN/J4/UziniAhJR2OZ9Ox5kOY2053tBbbqUPYA= github.com/anacrolix/upnp v0.1.3-0.20220123035249-922794e51c96/go.mod h1:Wa6n8cYIdaG35x15aH3Zy6d03f7P728QfdcDeD/IEOs= github.com/anacrolix/utp v0.1.0 h1:FOpQOmIwYsnENnz7tAGohA+r6iXpRjrq8ssKSre2Cp4= @@ -156,7 +146,6 @@ github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/ github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c= github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apache/arrow/go/arrow v0.0.0-20200730104253-651201b0f516/go.mod h1:QNYViu/X0HXDHw7m3KXzWSVXIbfUvJqBFe6Gj8/pYA0= github.com/apache/thrift v0.0.0-20181112125854-24918abba929/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= @@ -217,13 +206,7 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudfoundry/gosigar v1.1.0/go.mod h1:3qLfc2GlfmwOx2+ZDaRGH3Y9fwQ0sQeaAleo2GV5pH0= github.com/cloudfoundry/gosigar v1.2.0/go.mod h1:3qLfc2GlfmwOx2+ZDaRGH3Y9fwQ0sQeaAleo2GV5pH0= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/apd/v3 v3.2.1 h1:U+8j7t0axsIgvQUqthuNm82HIrYXodOV2iWLWtEaIwg= github.com/cockroachdb/apd/v3 v3.2.1/go.mod h1:klXJcjp+FffLTHlhIG69tezTDvdP065naDsHzKhYSqc= github.com/colinmarc/hdfs/v2 v2.1.1/go.mod h1:M3x+k8UKKmxtFu++uAZ0OtDU8jR3jnaZIAc6yK4Ue0c= @@ -237,8 +220,9 @@ github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76/go.mod h1:vYwsqCOLxGii github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dchest/siphash v1.2.1 h1:4cLinnzVJDKxTCl9B01807Yiy+W7ZzVHj/KIroQRvT4= github.com/dchest/siphash v1.2.1/go.mod h1:q+IRvb2gOSrUnYoPqHiyHXS0FOBBOdl6tONBlVnOnt4= +github.com/dchest/siphash v1.2.3 h1:QXwFc8cFOR2dSa/gE6o/HokBMWtLUaNDVd+22aKHeEA= +github.com/dchest/siphash v1.2.3/go.mod h1:0NvQU092bT0ipiFN++/rXm69QG9tVxLAlQHIXMPAkHc= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= @@ -274,10 +258,7 @@ github.com/enobufs/go-nats v0.0.1 h1:uzC0mxan4hyGzUFG7cShFmk6c+XYgfoT8yTBgF5CJYw github.com/enobufs/go-nats v0.0.1/go.mod h1:ZF0vpSk02ALIMFsHkIO4MHXUN1v3nLZssTaG+fgX/io= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/felixge/httpsnoop v1.0.0/go.mod h1:3+D9sFq0ahK/JeJPhCBUV1xlf4/eIYrUQaxulT0VzX8= github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= @@ -289,9 +270,8 @@ github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0X github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/gaukas/godicttls v0.0.3 h1:YNDIf0d9adcxOijiLrEzpfZGAkNwLRzPaG6OjU7EITk= -github.com/gaukas/godicttls v0.0.3/go.mod h1:l6EenT4TLWgTdwslVb4sEMOCf7Bv0JAK67deKr9/NCI= -github.com/getlantern/appdir v0.0.0-20160830121117-659a155d06e8/go.mod h1:3vR6+jQdWfWojZ77w+htCqEF5MO/Y2twJOpAvFuM9po= +github.com/gaukas/godicttls v0.0.4 h1:NlRaXb3J6hAnTmWdsEKb9bcSBD6BvcIjdGdeb0zfXbk= +github.com/gaukas/godicttls v0.0.4/go.mod h1:l6EenT4TLWgTdwslVb4sEMOCf7Bv0JAK67deKr9/NCI= github.com/getlantern/appdir v0.0.0-20180320102544-7c0f9d241ea7/go.mod h1:3vR6+jQdWfWojZ77w+htCqEF5MO/Y2twJOpAvFuM9po= github.com/getlantern/appdir v0.0.0-20200615192800-a0ef1968f4da h1:T/pxF37Z9SIQCHhMMUITZ3rhKRL0Noi9XxNwxKdBNw0= github.com/getlantern/appdir v0.0.0-20200615192800-a0ef1968f4da/go.mod h1:3vR6+jQdWfWojZ77w+htCqEF5MO/Y2twJOpAvFuM9po= @@ -360,8 +340,8 @@ github.com/getlantern/fdcount v0.0.0-20210503151800-5decd65b3731/go.mod h1:XZwE+ github.com/getlantern/filepersist v0.0.0-20160317154340-c5f0cd24e799/go.mod h1:8DGAx0LNUfXNnEH+fXI0s3OCBA/351kZCiz/8YSK3i8= github.com/getlantern/filepersist v0.0.0-20210901195658-ed29a1cb0b7c h1:mcz27xtAkb1OuOLBct/uFfL1p3XxAIcFct82GbT+UZM= github.com/getlantern/filepersist v0.0.0-20210901195658-ed29a1cb0b7c/go.mod h1:8DGAx0LNUfXNnEH+fXI0s3OCBA/351kZCiz/8YSK3i8= -github.com/getlantern/flashlight/v7 v7.6.18 h1:8rNNX0lyss8wUe/EIshzG9pL0Ei+4W0A5xh3un4lHlc= -github.com/getlantern/flashlight/v7 v7.6.18/go.mod h1:AP+Mr/htyAcx7XUhb+GyPfPBLfJ0D25SJCubBvauoA8= +github.com/getlantern/flashlight/v7 v7.6.19 h1:yGNp6NnabhHjLnZkhOwfVFMJzsbKjo8BVqo8iKUXEO4= +github.com/getlantern/flashlight/v7 v7.6.19/go.mod h1:Aui1+XJ8wUkihKv1MDrLJQwzK5C4kxHjte4YX8Jx5a0= github.com/getlantern/framed v0.0.0-20190601192238-ceb6431eeede h1:yrU6Px3ZkvCsDLPryPGi6FN+2iqFPq+JeCb7EFoDBhw= github.com/getlantern/framed v0.0.0-20190601192238-ceb6431eeede/go.mod h1:nhnoiS6DE6zfe+BaCMU4YI01UpsuiXnDqM5S8jxHuuI= github.com/getlantern/fronted v0.0.0-20230601004823-7fec719639d8 h1:r/Z/SPPIfLXDI3QA7/tE6nOfPncrqeUPDjiFjnNGP50= @@ -399,10 +379,8 @@ github.com/getlantern/hidden v0.0.0-20190325191715-f02dbb02be55/go.mod h1:6mmzY2 github.com/getlantern/hidden v0.0.0-20201229170000-e66e7f878730/go.mod h1:6mmzY2kW1TOOrVy+r41Za2MxXM+hhqTtY3oBKd2AgFA= github.com/getlantern/hidden v0.0.0-20220104173330-f221c5a24770 h1:cSrD9ryDfTV2yaur9Qk3rHYD414j3Q1rl7+L0AylxrE= github.com/getlantern/hidden v0.0.0-20220104173330-f221c5a24770/go.mod h1:GOQsoDnEHl6ZmNIL+5uVo+JWRFWozMEp18Izcb++H+A= -github.com/getlantern/http-proxy v0.0.3-0.20230405160101-eb4bf4e4a733 h1:bAVwkX1pvHqqrxuoZ2ElGr2FElnjE/+yOpqUSOrVnJg= -github.com/getlantern/http-proxy v0.0.3-0.20230405160101-eb4bf4e4a733/go.mod h1:zsMtNKXEfy+y3RBqe3wcd05VivKAswrIvlVsFrj7Fwk= -github.com/getlantern/http-proxy-lantern/v2 v2.8.3-0.20230822194736-c6ce61180a3a h1:nR1zM2FsFZF4P4hRuAosn9ob0LnkiYyM3SHgPFI5C6Q= -github.com/getlantern/http-proxy-lantern/v2 v2.8.3-0.20230822194736-c6ce61180a3a/go.mod h1:Ghj3WWaSmNBeDbSElm/Zsnb/xUiZjGDTAN9h2javcHE= +github.com/getlantern/http-proxy-lantern/v2 v2.10.0 h1:cnKPteRz1xE1iAZMCuTpQX5cQXUPMOoLq+FdhFAfIyQ= +github.com/getlantern/http-proxy-lantern/v2 v2.10.0/go.mod h1:bY0Uxqvojq1Uj6R7DwyqGh+YxNeZ4vF/N+TtwXVjALg= github.com/getlantern/httpseverywhere v0.0.0-20201210200013-19ae11fc4eca h1:Of3VwFEfKbVnK5/VGy05XUbi6QvTs5Y2eLDfPv3O50E= github.com/getlantern/httpseverywhere v0.0.0-20201210200013-19ae11fc4eca/go.mod h1:TNC/xJFmctsSGyXqcnVWwCRCPD/4zGQP7yBVnLDRa/U= github.com/getlantern/i18n v0.0.0-20181205222232-2afc4f49bb1c h1:+JnT+Rwa/3rksc4Zi0u6fJ/WX+tPK58GtsrcXWVUU2U= @@ -435,12 +413,10 @@ github.com/getlantern/lantern-shadowsocks v1.3.6-0.20230301223223-150b18ac427d h github.com/getlantern/lantern-shadowsocks v1.3.6-0.20230301223223-150b18ac427d/go.mod h1:Wwa1uDdu6LxVRANcN2dQ+aNI0rY+km+dqHW2G9Qm34k= github.com/getlantern/mandrill v0.0.0-20221004112352-e7c04248adcb h1:oyEMOT9jn4bzKyivF2sVBogsXyL8fBCK7HIT/P6h64Y= github.com/getlantern/mandrill v0.0.0-20221004112352-e7c04248adcb/go.mod h1:gz4iIB+vPk8hWxkAnnZSudQuIpBMnW7i89eHl9Fl+I8= -github.com/getlantern/measured v0.0.0-20170302221919-0582bf799783/go.mod h1:5OW2WJitCKExpSw2bploW2fM7PjOd6QnLqyp+IqToqU= -github.com/getlantern/measured v0.0.0-20210507000559-ec5307b2b8be h1:rfdOTeKew6zcpf5BQ566WInLINdZARimtWVLcgP/a4I= -github.com/getlantern/measured v0.0.0-20210507000559-ec5307b2b8be/go.mod h1:QG6d9+nAxD1PjVjgGLUUHPZBQUp20/h7j8a3kxd/8Rc= +github.com/getlantern/measured v0.0.0-20230919230611-3d9e3776a6cd h1:pDfqh9yd58OW9vQzv4U+q6G+LfbNXVhbWcBWmC5Dkm4= +github.com/getlantern/measured v0.0.0-20230919230611-3d9e3776a6cd/go.mod h1:QG6d9+nAxD1PjVjgGLUUHPZBQUp20/h7j8a3kxd/8Rc= github.com/getlantern/meta-scrubber v0.0.1 h1:WknyffbSpb5kEwDQ6lrN9+KohCGnqhs5zQfGk4sFRGo= github.com/getlantern/meta-scrubber v0.0.1/go.mod h1:nYmOMQXbex3emWMNbt/iDKTXE1q53x1dDxCspxjwxyY= -github.com/getlantern/mitm v0.0.0-20180205214248-4ce456bae650/go.mod h1:jmIVbVxSVLdeY5hlD+6chiOR/9CdzPjVgIIQphviCl0= github.com/getlantern/mitm v0.0.0-20231025115752-54d3e43899b7 h1:l9/yc7C0eaF4UQWgxAdtOnYKNfS74NMaInZ9vrlNKWI= github.com/getlantern/mitm v0.0.0-20231025115752-54d3e43899b7/go.mod h1:sCAOk1Y9pRrLuK0sSH3Rz2lubOBIl04h7pD/+UZM/lc= github.com/getlantern/mockconn v0.0.0-20190708122800-637bd46d8034/go.mod h1:+F5GJ7qGpQ03DBtcOEyQpM30ix4BLswdaojecFtsdy8= @@ -453,14 +429,13 @@ github.com/getlantern/mtime v0.0.0-20170117193331-ba114e4a82b0/go.mod h1:u537FS7 github.com/getlantern/mtime v0.0.0-20200228202836-084e1d8282b0/go.mod h1:GfzwugvtH7YcmNIrHHizeyImsgEdyL88YkdnK28B14c= github.com/getlantern/mtime v0.0.0-20200417132445-23682092d1f7 h1:03J6Cb42EG06lHgpOFGm5BOax4qFqlSbSeKO2RGrj2g= github.com/getlantern/mtime v0.0.0-20200417132445-23682092d1f7/go.mod h1:GfzwugvtH7YcmNIrHHizeyImsgEdyL88YkdnK28B14c= -github.com/getlantern/multipath v0.0.0-20220920195041-55195f38df73 h1:nRyc0NS4ViqrjxD7WcwbOnKC2kEThjJm+JUCiaDdkXY= -github.com/getlantern/multipath v0.0.0-20220920195041-55195f38df73/go.mod h1:uzxEbpNdIj+Iw9lEVuY1HF3OdAJ4RJykQHSL8lPee4M= +github.com/getlantern/multipath v0.0.0-20230510135141-717ed305ef50 h1:+3K4Zk0NuXGHdPOL6uqchUUFyLUIl0CIdlp6ksgZxDM= +github.com/getlantern/multipath v0.0.0-20230510135141-717ed305ef50/go.mod h1:uzxEbpNdIj+Iw9lEVuY1HF3OdAJ4RJykQHSL8lPee4M= github.com/getlantern/netstack v0.0.0-20220824143118-037ff0cd9c33 h1:xRYz3XSG5NFKM2PtxfJd5c8m16GpHN0YXF2PZAMaHP8= github.com/getlantern/netstack v0.0.0-20220824143118-037ff0cd9c33/go.mod h1:Cqo5uZK3k9SmJcFVvRlBKQPY/2NB2NkdBPP9sn3qnHI= github.com/getlantern/nettest v1.0.0 h1:xg8vq9JrGzrFGFkFGwZwIJ5+kwtvyqNDIADwrANvhQg= github.com/getlantern/nettest v1.0.0/go.mod h1:8wY0QwrdpkayCBQXjhZoJuwu2IHfp4UErrxgwaJ2UM4= github.com/getlantern/netx v0.0.0-20190110220209-9912de6f94fd/go.mod h1:wKdY0ikOgzrWSeB9UyBVKPRhjXQ+vTb+BPeJuypUuNE= -github.com/getlantern/netx v0.0.0-20210803075350-eb4fa6261e47/go.mod h1:g7yY/ImU8M+7lS09wVG3GTsxNvtPMTvkeWZVfxowtMo= github.com/getlantern/netx v0.0.0-20211206143627-7ccfeb739cbd h1:z5IehLDMqMwJ0oeFIaMHhySRU8r1lRMh7WQ0Wn0LioA= github.com/getlantern/netx v0.0.0-20211206143627-7ccfeb739cbd/go.mod h1:WEXF4pfIfnHBUAKwLa4DW7kcEINtG6wjUkbL2btwXZQ= github.com/getlantern/ops v0.0.0-20190325191751-d70cb0d6f85f/go.mod h1:D5ao98qkA6pxftxoqzibIBBrLSUli+kYnJqrgBf9cIA= @@ -474,20 +449,19 @@ github.com/getlantern/packetforward v0.0.0-20201001150407-c68a447b0360 h1:pijUoo github.com/getlantern/packetforward v0.0.0-20201001150407-c68a447b0360/go.mod h1:nsJPNYUSY96xB+p7uiDW8O4uiKea+KjeUdS5d6tf9IU= github.com/getlantern/pathdb v0.0.0-20231026090702-54ee1ddd99eb h1:rbkflUPjr83ON7c+4LqU2Y/rJzv9P/fmocXDLLm0hWQ= github.com/getlantern/pathdb v0.0.0-20231026090702-54ee1ddd99eb/go.mod h1:SFQy+f58IbLpnbq2nVqlq7ccwaUiO7ablKv631WVIuc= -github.com/getlantern/preconn v0.0.0-20180328114929-0b5766010efe/go.mod h1:FvIxQD61iYA42UjaJyzGl9DNne8jbowbgicdeNk/7kE= github.com/getlantern/preconn v1.0.0 h1:DsY3l/y/BJUj86WyaxXylbJnCC9QbKcc3D6js6rFL60= github.com/getlantern/preconn v1.0.0/go.mod h1:i/AnXvx715Fq7HgZLlmQlw3sGfEkku8BQT5hLHMK4+k= github.com/getlantern/probe v0.0.0-20191107230642-ed284e08029a/go.mod h1:EPE0nd9YNS2FTIz+2EOkqojCuqaQlJ+fTiLPklsqe/E= github.com/getlantern/probe v0.0.0-20211216020459-69afa01c1c5c h1:bWusw8SYvl/iq+nHzSIe4oC7HdwaCN0KQEZkIHimamM= github.com/getlantern/probednet v0.0.0-20190725133252-1cfdb2354b4d/go.mod h1:7sl7hPjPDAqXyxVx7mhrKfvb4oCX/ROhcs16w2EhWX8= github.com/getlantern/probednet v0.0.0-20211216020507-22fd9c1d3bf6 h1:8jg6OehdQr90Ybmyc68raXEqM/1hk8E7F2YAUfmcvzE= -github.com/getlantern/proxy/v2 v2.0.0/go.mod h1:81jIwwI/5NGYj2CSvbsZapcTe87jd6AeEu6yJD1NKIg= -github.com/getlantern/proxy/v2 v2.0.1 h1:Qphu2HCVNHsYS/Rj5OQsgobCHpSZsFws6nD2XDy6gXk= -github.com/getlantern/proxy/v2 v2.0.1/go.mod h1:teUfqDKSD5HIJkH+n/2gHJUmJYKPox/sipLrrBYZP/w= +github.com/getlantern/proxy/v3 v3.0.0-20231031142453-252ab678e6b7 h1:r6lDJ9gea/mIvI5QGQm6rzp/iEV/IpqdH+lSL3r0fgk= +github.com/getlantern/proxy/v3 v3.0.0-20231031142453-252ab678e6b7/go.mod h1:SUQ8fQ0ImT7N7taLLU21HI7i9VR8j/bSxG/OiwSZM4s= github.com/getlantern/proxybench v0.0.0-20220404140110-f49055cb86de h1:328hcuyQi8KGZr4GV2EtWllwBmS10oVGevwZEOk2dDE= github.com/getlantern/proxybench v0.0.0-20220404140110-f49055cb86de/go.mod h1:kF5QcNhyCA0tpZ+MLVdeJb0bZpgXyMjR/CnPtaltlFU= -github.com/getlantern/psmux v1.5.15-0.20200903210100-947ca5d91683 h1:Asfm7ajzavuSZC+5b+tPwXwyvlw188NM9hKM7wNMNGg= github.com/getlantern/psmux v1.5.15-0.20200903210100-947ca5d91683/go.mod h1:GtXRvtMItoflWGLPE7GNq+AdL7BnmpaaNLtDQVD1XHU= +github.com/getlantern/psmux v1.5.15 h1:VUCEk8MIsvAj90wNYRyY2fE9ZL4LIRhi1W5V9aycA9A= +github.com/getlantern/psmux v1.5.15/go.mod h1:nyp/sr4uTbWpUh7Q2WovRb07LeLNUxDg8kAdS726FIw= github.com/getlantern/quicwrapper v0.0.0-20230523101504-1ec066b7f869 h1:nx0sr8jXoEBbI0jHDOHIkM0z5dXotQRUSsE/e7lUGXw= github.com/getlantern/quicwrapper v0.0.0-20230523101504-1ec066b7f869/go.mod h1:0k08ZBlQon93TrW6KmBLhLSz89qHQFR2LstGlIRgYo8= github.com/getlantern/ratelimit v0.0.0-20220926192648-933ab81a6fc7 h1:47FJ5kTeXc3I1VPpi2hWW9I16/Y3K0cpUq/B7oWJGF8= @@ -575,8 +549,9 @@ github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LB github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= @@ -588,7 +563,6 @@ github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgR github.com/golang/geo v0.0.0-20200319012246-673a6f80352d h1:C/hKUcHT483btRbeGkrRjJz+Zbcj8audldIi9tRJDCc= github.com/golang/geo v0.0.0-20200319012246-673a6f80352d/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -600,9 +574,7 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -610,7 +582,6 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= @@ -619,7 +590,6 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= @@ -645,33 +615,29 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM= github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20220608213341-c488b8fa1db3 h1:mpL/HvfIgIejhVwAfxBQkwEjlhP5o0O9RAeTAjpwzxc= -github.com/google/pprof v0.0.0-20220608213341-c488b8fa1db3/go.mod h1:gSuNB+gJaOiQKLEZ+q+PK9Mq3SOzhRcw2GsGS/FhYDk= +github.com/google/pprof v0.0.0-20230821062121-407c9e7a662f h1:pDhu5sgp8yJlEF/g6osliIIpF9K4F5jvkULXa4daRDQ= +github.com/google/pprof v0.0.0-20230821062121-407c9e7a662f/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= @@ -691,10 +657,8 @@ github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.10.2 h1:ERKrevVTnCw3Wu4I3mtR15QU3gtWy86cBo6De0jEohg= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.10.2/go.mod h1:chrfS3YoLAlKTRE5cFWvCbt8uGAjshktT4PveTUpsFQ= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= github.com/hashicorp/go-uuid v0.0.0-20180228145832-27454136f036/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -733,8 +697,8 @@ github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVY github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= 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/kataras/golog v0.1.8 h1:isP8th4PJH2SrbkciKnylaND9xoTtfxv++NB+DF0l9g= -github.com/kataras/pio v0.0.11 h1:kqreJ5KOEXGMwHAWHDwIl+mjfNCPhAwZPa8gK7MKlyw= +github.com/kataras/golog v0.1.9 h1:vLvSDpP7kihFGKFAvBSofYo7qZNULYSHOH2D7rPTKJk= +github.com/kataras/pio v0.0.12 h1:o52SfVYauS3J5X08fNjlGS5arXHjW/ItLkyLcKjoH6w= github.com/kennygrant/sanitize v1.2.4 h1:gN25/otpP5vAsO2djbMhF/LQX6R7+O1TB4yv8NzpJ3o= github.com/kennygrant/sanitize v1.2.4/go.mod h1:LGsjYYtgxbetdg5owWB2mpgUL6e2nfw2eObZ0u0qvak= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= @@ -743,8 +707,8 @@ github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0 github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.13.1/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= -github.com/klauspost/compress v1.16.6 h1:91SKEy4K37vkp255cJ8QesJhjyRO0hn9i9G0GoUwLsk= -github.com/klauspost/compress v1.16.6/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= +github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid v1.2.4/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid v1.3.1 h1:5JNjFYYQrZeKRJ0734q51WCEEn2huer72Dc7K+R/b6s= @@ -771,8 +735,6 @@ github.com/ledisdb/ledisdb v0.0.0-20200510135210-d35789ec47e6/go.mod h1:n931TsDu github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOSqcmlfs= github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= -github.com/lispad/go-generics-tools v1.1.0 h1:mbSgcxdFVmpoyso1X/MJHXbSbSL3dD+qhRryyxk+/XY= -github.com/lispad/go-generics-tools v1.1.0/go.mod h1:2csd1EJljo/gy5qG4khXol7ivCPptNjG5Uv2X8MgK84= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= github.com/mattn/go-ieproxy v0.0.1/go.mod h1:pYabZ6IHcRpFh7vIaLfK7rdcWgFEb3SFJ6/gNWuh88E= @@ -792,7 +754,6 @@ github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc= github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg= -github.com/mitchellh/go-server-timing v1.0.0/go.mod h1:RdipKQzCJaL4HyxFQBINbf4XoDdZKkSshqw9Bbsx1ic= github.com/mitchellh/go-server-timing v1.0.1 h1:f00/aIe8T3MrnLhQHu3tSWvnwc5GV/p5eutuu3hF/tE= github.com/mitchellh/go-server-timing v1.0.1/go.mod h1:Mo6GKi9FSLwWFAMn3bqVPWe20y5ri5QGQuO9D9MCOxk= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= @@ -804,8 +765,8 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/montanaflynn/stats v0.5.0 h1:2EkzeTSqBB4V4bJwWrt5gIIrZmpJBcoIRGS2kWLgzmk= github.com/montanaflynn/stats v0.5.0/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= -github.com/montanaflynn/stats v0.6.6 h1:Duep6KMIDpY4Yo11iFsvyqJDyfzLF9+sndUKT+v64GQ= github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM= github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw= @@ -827,15 +788,15 @@ github.com/onsi/ginkgo v1.15.0/go.mod h1:hF8qUzuuC8DJGygJH3726JnCZX4MYbRB8yFfISq github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.2.0 h1:3ZNA3L1c5FYDFTTxbFeVGGD8jYvjYauHD30YgLxVsNI= -github.com/onsi/ginkgo/v2 v2.2.0/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk= +github.com/onsi/ginkgo/v2 v2.12.0 h1:UIVDowFPwpg6yMUpPjGkYvf06K3RAiJXUhCxEwQVHRI= +github.com/onsi/ginkgo/v2 v2.12.0/go.mod h1:ZNEzXISYlqpb8S36iN71ifqLi3vVD1rVJGvWRCJOUpQ= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.5/go.mod h1:gza4q3jKQJijlu05nKWRCW/GavJumGt8aNRxWg7mt48= github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q= +github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= @@ -969,7 +930,6 @@ github.com/rickar/props v0.0.0-20170718221555-0b06aeb2f037/go.mod h1:F1p8BNM4IXv github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg= github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= @@ -1070,8 +1030,8 @@ github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oW github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8= github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/vharitonsky/iniflags v0.0.0-20180513140207-a33cd0b5f3de/go.mod h1:irMhzlTz8+fVFj6CH2AN2i+WI5S6wWFtK3MBCIxIpyI= +github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc h1:R83G5ikgLMxrBvLh22JhdfI8K6YXEPHx5P03Uu3DRs4= github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= -github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f h1:p4VB7kIXpOQvVn1ZaTIVp+3vuYAXFe3OJEvjbUYJLaA= github.com/vulcand/oxy v1.4.2 h1:KibUVdKrwy7eXR3uHS2pYoZ9dCzKVcgDNHD2jkPZmxU= github.com/willf/bitset v1.1.9/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= github.com/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= @@ -1089,9 +1049,7 @@ github.com/xtaci/smux v1.5.10/go.mod h1:OMlQbT5vcgl2gb49mFkYo6SMf+zP3rcjcwQz7ZU7 github.com/xtaci/smux v1.5.24 h1:77emW9dtnOxxOQ5ltR+8BbsX1kzcOxQ5gB+aaV9hXOY= github.com/xtaci/smux v1.5.24/go.mod h1:OMlQbT5vcgl2gb49mFkYo6SMf+zP3rcjcwQz7ZU7IGY= github.com/xwb1989/sqlparser v0.0.0-20180606152119-120387863bf2/go.mod h1:hzfGeIUDq/j97IG+FhNqkowIyEcD88LrW6fyU3K3WqY= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= @@ -1112,38 +1070,34 @@ go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.42.0 h1:pginetY7+onl4qN1vl0xW/V/v6OBZ0vVdH+esuJgvmM= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.42.0/go.mod h1:XiYsayHc36K3EByOO6nbAXnAWbrUxdjUROCEeeROOH8= go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= go.opentelemetry.io/otel v1.9.0/go.mod h1:np4EoPGzoPs3O67xUVNoPPcmSvsfOxNlNA4F4AC+0Eo= -go.opentelemetry.io/otel v1.16.0 h1:Z7GVAX/UkAXPKsy94IU+i6thsQS4nb7LviLpnaNeW8s= -go.opentelemetry.io/otel v1.16.0/go.mod h1:vl0h9NUa1D5s1nv3A5vZOYWn8av4K8Ml6JDeHrT/bx4= -go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0 h1:t4ZwRPU+emrcvM2e9DHd0Fsf0JTPVcbfa/BhTDF03d0= -go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0/go.mod h1:vLarbg68dH2Wa77g71zmKQqlQ8+8Rq3GRG31uc0WcWI= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.39.0 h1:f6BwB2OACc3FCbYVznctQ9V6KK7Vq6CjmYXJ7DeSs4E= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.39.0/go.mod h1:UqL5mZ3qs6XYhDnZaW1Ps4upD+PX6LipH40AoeuIlwU= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.39.0 h1:IZXpCEtI7BbX01DRQEWTGDkvjMB6hEhiEZXS+eg2YqY= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.39.0/go.mod h1:xY111jIZtWb+pUUgT4UiiSonAaY2cD2Ts5zvuKLki3o= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.16.0 h1:cbsD4cUcviQGXdw8+bo5x2wazq10SKz8hEbtCRPcU78= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.16.0/go.mod h1:JgXSGah17croqhJfhByOLVY719k1emAXC8MVhCIJlRs= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.16.0 h1:iqjq9LAB8aK++sKVcELezzn655JnBNdsDhghU4G/So8= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.16.0/go.mod h1:hGXzO5bhhSHZnKvrDaXB82Y9DRFour0Nz/KrBh7reWw= +go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs= +go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0 h1:ZtfnDL+tUrs1F0Pzfwbg2d59Gru9NCH3bgSHBM6LDwU= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0/go.mod h1:hG4Fj/y8TR/tlEDREo8tWstl9fO9gcFkn4xrx0Io8xU= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.42.0 h1:wNMDy/LVGLj2h3p6zg4d0gypKfWKSWI14E1C4smOgl8= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.42.0/go.mod h1:YfbDdXAAkemWJK3H/DshvlrxqFB2rtW4rY6ky/3x/H0= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU= go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= -go.opentelemetry.io/otel/metric v1.16.0 h1:RbrpwVG1Hfv85LgnZ7+txXioPDoh6EdbZHo26Q3hqOo= -go.opentelemetry.io/otel/metric v1.16.0/go.mod h1:QE47cpOmkwipPiefDwo2wDzwJrlfxxNYodqc4xnGCo4= +go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE= +go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8= go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= -go.opentelemetry.io/otel/sdk v1.16.0 h1:Z1Ok1YsijYL0CSJpHt4cS3wDDh7p572grzNrBMiMWgE= -go.opentelemetry.io/otel/sdk v1.16.0/go.mod h1:tMsIuKXuuIWPBAOrH+eHtvhTL+SntFtXF9QD68aP6p4= -go.opentelemetry.io/otel/sdk/metric v0.39.0 h1:Kun8i1eYf48kHH83RucG93ffz0zGV1sh46FAScOTuDI= -go.opentelemetry.io/otel/sdk/metric v0.39.0/go.mod h1:piDIRgjcK7u0HCL5pCA4e74qpK/jk3NiUoAHATVAmiI= +go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o= +go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= +go.opentelemetry.io/otel/sdk/metric v1.19.0 h1:EJoTO5qysMsYCa+w4UghwFV/ptQgqSL/8Ni+hx+8i1k= +go.opentelemetry.io/otel/sdk/metric v1.19.0/go.mod h1:XjG0jQyFJrv2PbMvwND7LwCEhsJzCzV5210euduKcKY= go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= go.opentelemetry.io/otel/trace v1.9.0/go.mod h1:2737Q0MuG8q1uILYm2YYVkAyLtOofiTNGg6VODnOiPo= -go.opentelemetry.io/otel/trace v1.16.0 h1:8JRpaObFoW0pxuVPapkgH8UhHQj+bJW8jJsCZEu5MQs= -go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLkqr2QVwea0ef0= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw= -go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= +go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg= +go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= +go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= +go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= @@ -1197,8 +1151,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20221217163422-3c43f8badb15 h1:5oN1Pz/eDhCpbMbLstvIPa0b/BEQo6g6nwV3pLjfM6w= -golang.org/x/exp v0.0.0-20221217163422-3c43f8badb15/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 h1:m64FZMko/V45gv0bNmrNYoDEq8U5YUhetc9cBWKS1TQ= +golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -1211,7 +1165,6 @@ golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mobile v0.0.0-20231006135142-2b44d11868fe h1:lrXv4yHeD9FA8PSJATWowP1QvexpyAPWmPia+Kbzql8= @@ -1243,7 +1196,6 @@ golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190912160710-24e19bdeb0f2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -1255,17 +1207,12 @@ golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200320220750-118fecf932d8/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= @@ -1289,15 +1236,12 @@ golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1343,15 +1287,9 @@ golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200828194041-157a740278f4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200916084744-dbad9cb7cb7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1391,7 +1329,6 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= @@ -1441,18 +1378,7 @@ golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200425043458-8463f397d07c/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= @@ -1479,19 +1405,11 @@ google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsb google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= @@ -1511,23 +1429,13 @@ google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvx google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 h1:DdoeryqhaXp1LtT/emMP1BRJPHHKFi5akj/nbx/zNTA= -google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= +google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97 h1:SeZZZx0cP0fqUyA+oRzP9k7cSwJlvDFiROO72uwD6i0= +google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97 h1:W18sezcAYs+3tDZX4F80yctqa12jcP1PUS2gQu1zTPU= +google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97/go.mod h1:iargEX0SFPm3xcfMI0d1domjg0ZF4Aa0p2awqyxhvF0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a h1:a2MQQVoTo96JC9PMGtGBymLp7+/RzpFc2yX/9WfFg1c= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a/go.mod h1:4cYg8o5yUbm77w8ZX00LhMVNl/YVBFJRYWDc0uYWMs0= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -1539,16 +1447,9 @@ google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQ google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag= -google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= +google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ= +google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1561,7 +1462,6 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= @@ -1588,7 +1488,6 @@ gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -1607,7 +1506,6 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= howett.net/plist v1.0.0 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM= howett.net/plist v1.0.0/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g= nhooyr.io/websocket v1.8.10 h1:mv4p+MnGrLDcPlBoWsvPP7XCzTYMXP9F9eIGoKbgx7Q= diff --git a/internalsdk/session_model.go b/internalsdk/session_model.go index 5c21bbd52..b623baa30 100644 --- a/internalsdk/session_model.go +++ b/internalsdk/session_model.go @@ -537,7 +537,7 @@ func setPlans(m *baseModel, plans []apimodels.Plan) error { OneMonthCost: plans.OneMonthCost, TotalCost: plans.TotalCost, FormattedBonus: plans.FormattedBonus, - RenewalText: "This is needs to be changed", + RenewalText: "", } err = pathdb.Put(tx, pathPlanId, protoPlan, "") if err != nil { From a41db2843fd489a199abda1830322cdbe327656c Mon Sep 17 00:00:00 2001 From: Jigar-f Date: Mon, 20 Nov 2023 18:09:30 +0530 Subject: [PATCH 14/17] Fetch user id for first time user. --- internalsdk/session_model.go | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/internalsdk/session_model.go b/internalsdk/session_model.go index b623baa30..a19a81aec 100644 --- a/internalsdk/session_model.go +++ b/internalsdk/session_model.go @@ -294,37 +294,31 @@ func (m *SessionModel) initSessionModel(opts *SessionModelOpts) error { if err != nil { return err } - userIdStr := fmt.Sprintf("%d", userId) countryCode, err := m.GetCountryCode() if err != nil { return err } + //Get all the Plans + userIdStr := fmt.Sprintf("%d", userId) + if userId == 0 { + tempUserId, err := m.GetUserID() + if err != nil { + return err + } + userIdStr = fmt.Sprintf("%d", tempUserId) + } - // Run Plans in background - // go func() { - // data, err := apimodels.PlansV3(opts.DeviceID, userIdStr, lang, toekns, countryCode) - // if err != nil { - // log.Errorf("Error while Plans v3 request:", err) // Optional: log the error - // return - // } - // log.Debugf("Plans Response", data) - // }() - - // //Get all the Plans - - //Know Issue - //When use install app first time - // Plans API is failing err = getPlansV3(m.baseModel, opts.DeviceID, userIdStr, lang, token, countryCode) if err != nil { log.Debugf("Plans V3 error: %v", err) return err } - return nil } func getPlansV3(m *baseModel, deviceId string, userId string, lang string, token string, countyCode string) error { + // + log.Debugf("Request data deviceID %v userId %v lang %v token %v countyCode %v", deviceId, userId, lang, token, countyCode) plans, err := apimodels.PlansV3(deviceId, userId, lang, token, countyCode) if err != nil { log.Debugf("Plans V3 error: %v", err) From ccf76dafaaa30a83e4051f836fd10655af11e1bc Mon Sep 17 00:00:00 2001 From: Eli Yukelzon Date: Tue, 12 Dec 2023 06:45:12 +0100 Subject: [PATCH 15/17] Fixed iOS IAP. (#962) * Update flashlight and go versions (#949) * Update flashlight and go versions * Do not enforce go version in Makefile * Revert "Update flashlight and go versions (#949)" (#950) This reverts commit eab0e693ab7516b78a089515474844fffbd14904. * add a template for GitHub integrated release notes * generate automatic changelog on release, then trigger automation repo * fixed IAP flow * fixed IAP flow --------- Co-authored-by: Myles Horton Co-authored-by: atavism Co-authored-by: Jay <110402935+jay-418@users.noreply.github.com> --- .github/release.yml | 27 ++++++++ .github/workflows/release-changelog.yml | 42 +++++++++++++ internalsdk/session_model.go | 12 ++-- internalsdk/utils.go | 6 +- lib/common/session_model.dart | 4 +- lib/core/purchase/app_purchase.dart | 61 +++++++++++-------- macos/Flutter/GeneratedPluginRegistrant.swift | 2 + 7 files changed, 119 insertions(+), 35 deletions(-) create mode 100644 .github/release.yml create mode 100644 .github/workflows/release-changelog.yml diff --git a/.github/release.yml b/.github/release.yml new file mode 100644 index 000000000..83994b6a0 --- /dev/null +++ b/.github/release.yml @@ -0,0 +1,27 @@ +# template for auto-generated release notes +# https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes + +changelog: + # exclude: + # labels: + # - ignore-for-release + # authors: + # - octocat + categories: + - title: ✨ Major Features + labels: + - epic + - title: 🪲 Bug Fixes + labels: + - bug + - cs + - title: 📱 Team Apps + labels: + - team_apps + - title: 📶 Team SDK + labels: + - team_sdk + - title: 🛠️ Team Infra + labels: + - team_infra + - telemetry diff --git a/.github/workflows/release-changelog.yml b/.github/workflows/release-changelog.yml new file mode 100644 index 000000000..6a8e893db --- /dev/null +++ b/.github/workflows/release-changelog.yml @@ -0,0 +1,42 @@ +name: Release and Changelog + +on: + workflow_dispatch: + push: + tags: + # a prerelease noted by a hyphen will not trigger + - 'lantern-[0-9]+.[0-9]+.[0-9]+' + +jobs: + create-release: + runs-on: ubuntu-latest + steps: + - name: Create release + env: + GH_TOKEN: ${{ github.token }} + # https://docs.github.com/en/rest/releases/releases?apiVersion=2022-11-28#create-a-release + run: | + gh api -i \ + --method POST \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + /repos/${{ github.repository }}/releases \ + -f tag_name='${{ github.ref_name }}' \ + -f name='Release ${{ github.ref_name }}' \ + -f body='🤖 Autogenerated changelog for ${{ github.repository }} ${{ github.ref_name }}' \ + -F draft=false \ + -F prerelease=false \ + -F generate_release_notes=true + - name: Strip repository name of owner + id: repo + run: | + echo "REPO_NAME=$(echo ${{ github.repository }} | sed s/'${{ github.repository_owner }}\/'//g)" >> "$GITHUB_OUTPUT" + - name: Trigger QC Checklist in customer-service repo + env: + GH_GRANTS_TOKEN: ${{ secrets.GH_GRANTS_TOKEN }} + run: | + echo "Sending QC Checklist trigger for ${{ steps.repo.outputs.REPO_NAME }} ${{ github.ref_name }}" + curl -i -H "Accept: application/vnd.github.everest-preview+json" \ + -H "Authorization: token $GH_GRANTS_TOKEN" \ + --request POST --data '{"event_type": "TRIGGER_QC_CHECKLIST", "client_payload": { "platform": "${{ steps.repo.outputs.REPO_NAME }}", "version": "${{ github.ref_name }}"}}' \ + https://api.github.com/repos/getlantern/customer-support/dispatches diff --git a/internalsdk/session_model.go b/internalsdk/session_model.go index a19a81aec..59c4db545 100644 --- a/internalsdk/session_model.go +++ b/internalsdk/session_model.go @@ -843,7 +843,7 @@ func redeemResellerCode(m *SessionModel, email string, resellerCode string) erro return err } - err, purchaseData := createPurchaseData(m, paymentProviderResellerCode, resellerCode, "") + err, purchaseData := createPurchaseData(m, paymentProviderResellerCode, resellerCode, "", "") if err != nil { log.Errorf("Error while creating purchase data %v", err) return err @@ -874,12 +874,13 @@ func redeemResellerCode(m *SessionModel, email string, resellerCode string) erro } func submitApplePayPayment(m *SessionModel, planId string, purchaseToken string) error { - err, purchaseData := createPurchaseData(m, paymentProviderApplePay, "", purchaseToken) + log.Errorf("Submit Apple Pay Payment planId %v purchaseToken %v", planId, purchaseToken) + err, purchaseData := createPurchaseData(m, paymentProviderApplePay, "", purchaseToken, planId) if err != nil { log.Errorf("Error while creating purchase data %v", err) return err } - + log.Errorf("Purchase data %v", purchaseData) deviecId, err := m.GetDeviceID() if err != nil { return err @@ -898,8 +899,11 @@ func submitApplePayPayment(m *SessionModel, planId string, purchaseToken string) if err != nil { return err } - log.Debugf("Purchase Request response %v", purchase) + log.Errorf("Purchase Request response %+v", purchase) + if purchase.Status != "ok" { + return errors.New("Purchase Request failed") + } // Set user to pro return setProUser(m.baseModel, true) } diff --git a/internalsdk/utils.go b/internalsdk/utils.go index 7222b9378..e84db8244 100644 --- a/internalsdk/utils.go +++ b/internalsdk/utils.go @@ -103,7 +103,7 @@ func formatRenewalBonusExpected(months int64, days int64, longForm bool) string //Create Purchase Request -func createPurchaseData(session *SessionModel, paymentProvider string, resellerCode string, purchaseToken string) (error, map[string]string) { +func createPurchaseData(session *SessionModel, paymentProvider string, resellerCode string, purchaseToken string, planId string) (error, map[string]string) { email, err := session.Email() if err != nil { return err, nil @@ -126,11 +126,11 @@ func createPurchaseData(session *SessionModel, paymentProvider string, resellerC data["provider"] = paymentProviderResellerCode data["resellerCode"] = resellerCode data["currency"] = "usd" - data["plan"] = "" + data["plan"] = planId case paymentProviderApplePay: data["token"] = purchaseToken data["currency"] = "usd" - data["plan"] = "" + data["plan"] = planId } diff --git a/lib/common/session_model.dart b/lib/common/session_model.dart index faaaa3a90..78cf1d26c 100644 --- a/lib/common/session_model.dart +++ b/lib/common/session_model.dart @@ -393,12 +393,12 @@ class SessionModel extends Model { }).then((value) => value as String); } - Future submitApplePlay(String planID,String purchaseToken) async { + Future submitApplePlay(String planID, String purchaseToken) async { return methodChannel .invokeMethod('submitApplePayPayment', { 'planID': planID, 'purchaseId': purchaseToken, - }).then((value) => value as String); + }); } Future submitStripePayment( diff --git a/lib/core/purchase/app_purchase.dart b/lib/core/purchase/app_purchase.dart index 5f526b08e..a363b5af4 100644 --- a/lib/core/purchase/app_purchase.dart +++ b/lib/core/purchase/app_purchase.dart @@ -14,13 +14,13 @@ class AppPurchase { String _planId = ""; void init() { - getAvailablePlans(); final purchaseUpdated = _inAppPurchase.purchaseStream; _subscription = purchaseUpdated.listen( _onPurchaseUpdate, onDone: _updateStreamOnDone, onError: _updateStreamOnError, ); + getAvailablePlans(); } Future getAvailablePlans() async { @@ -29,15 +29,22 @@ class AppPurchase { plansSku.addAll(response.productDetails); } - void startPurchase(String planId, - {required VoidCallback onSuccess, - required Function(dynamic error) onFailure}) { + Future startPurchase( + String planId, { + required VoidCallback onSuccess, + required Function(dynamic error) onFailure, + }) async { _planId = planId; _onSuccess = onSuccess; _onError = onFailure; final plan = _normalizePlan(planId); final purchaseParam = PurchaseParam(productDetails: plan); - _inAppPurchase.buyConsumable(purchaseParam: purchaseParam); + try { + await _inAppPurchase.buyConsumable(purchaseParam: purchaseParam); + } on PlatformException catch (e) { + logger.e('Error while calling purchase api', error: e); + Sentry.captureException(e); + } } ProductDetails _normalizePlan(String planId) { @@ -47,31 +54,33 @@ class AppPurchase { /// So we split and compare with lowercase final newPlanId = planId.split('-')[0]; return plansSku.firstWhere( - (element) => element.id.toLowerCase() == newPlanId.toLowerCase()); + (element) => element.id.toLowerCase() == newPlanId.toLowerCase(), + ); } - // Internal methods Future _onPurchaseUpdate( - List purchaseDetailsList) async { - print("purchase length ${purchaseDetailsList.length}"); - final purchase = purchaseDetailsList[0]; - // // Handle purchases here - // for (final purchase in purchaseDetailsList) { - // print("purchase $purchase"); - // } - - logger.i('Calling Purchase API'); - try { - sessionModel.submitApplePlay(_planId, purchase.purchaseID!); + List purchaseDetailsList, + ) async { + for (var purchaseDetails in purchaseDetailsList) { + await _handlePurchase(purchaseDetails); + } + } - //Check if purchase is sill in pending state complete purchase - if (purchase.pendingCompletePurchase) { - await _inAppPurchase.completePurchase(purchase); + Future _handlePurchase(PurchaseDetails purchaseDetails) async { + if (purchaseDetails.status == PurchaseStatus.purchased) { + try { + await sessionModel.submitApplePlay( + _planId, + purchaseDetails.verificationData.serverVerificationData, + ); + _onSuccess?.call(); + } catch (e) { + logger.e("purchase error", error: e); + Sentry.captureException(e); } - _onSuccess?.call(); - } catch (e) { - logger.e('Error while calling purchase api', error: e); - Sentry.captureException(e); + } + if (purchaseDetails.pendingCompletePurchase) { + await _inAppPurchase.completePurchase(purchaseDetails); } } @@ -84,7 +93,7 @@ class AppPurchase { void _updateStreamOnError(dynamic error) { //Handle error here - print("purchase error $error"); + logger.e("purchase error", error: error); if (_onError != null) { _onError?.call(error); } diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index d3a76df8c..09998cfdf 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -10,6 +10,7 @@ import device_info_plus import emoji_picker_flutter import flutter_inappwebview import flutter_local_notifications +import in_app_purchase_storekit import package_info_plus import path_provider_foundation import sentry_flutter @@ -25,6 +26,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { EmojiPickerFlutterPlugin.register(with: registry.registrar(forPlugin: "EmojiPickerFlutterPlugin")) InAppWebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "InAppWebViewFlutterPlugin")) FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin")) + InAppPurchasePlugin.register(with: registry.registrar(forPlugin: "InAppPurchasePlugin")) FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) SentryFlutterPlugin.register(with: registry.registrar(forPlugin: "SentryFlutterPlugin")) From f387dd99e126aefbaf089eeff72200be736548c1 Mon Sep 17 00:00:00 2001 From: Jigar-f Date: Tue, 12 Dec 2023 12:52:25 +0530 Subject: [PATCH 16/17] Added error handling. --- internalsdk/session_model.go | 3 +- lib/core/purchase/app_purchase.dart | 11 ++++ lib/plans/plan_details.dart | 89 +++++++++++++++++++---------- 3 files changed, 72 insertions(+), 31 deletions(-) diff --git a/internalsdk/session_model.go b/internalsdk/session_model.go index 59c4db545..7c7728d6d 100644 --- a/internalsdk/session_model.go +++ b/internalsdk/session_model.go @@ -874,13 +874,12 @@ func redeemResellerCode(m *SessionModel, email string, resellerCode string) erro } func submitApplePayPayment(m *SessionModel, planId string, purchaseToken string) error { - log.Errorf("Submit Apple Pay Payment planId %v purchaseToken %v", planId, purchaseToken) + log.Debugf("Submit Apple Pay Payment planId %v purchaseToken %v", planId, purchaseToken) err, purchaseData := createPurchaseData(m, paymentProviderApplePay, "", purchaseToken, planId) if err != nil { log.Errorf("Error while creating purchase data %v", err) return err } - log.Errorf("Purchase data %v", purchaseData) deviecId, err := m.GetDeviceID() if err != nil { return err diff --git a/lib/core/purchase/app_purchase.dart b/lib/core/purchase/app_purchase.dart index a363b5af4..178ac2e13 100644 --- a/lib/core/purchase/app_purchase.dart +++ b/lib/core/purchase/app_purchase.dart @@ -44,6 +44,10 @@ class AppPurchase { } on PlatformException catch (e) { logger.e('Error while calling purchase api', error: e); Sentry.captureException(e); + _onError?.call(e); + } catch (e) { + logger.e('Payment failed', error: e); + _onError?.call(e); } } @@ -61,12 +65,18 @@ class AppPurchase { Future _onPurchaseUpdate( List purchaseDetailsList, ) async { + logger.i("_onPurchaseUpdate called with $purchaseDetailsList"); for (var purchaseDetails in purchaseDetailsList) { await _handlePurchase(purchaseDetails); } } Future _handlePurchase(PurchaseDetails purchaseDetails) async { + if (purchaseDetails.status == PurchaseStatus.canceled) { + // User has canceled the purchase + _onError?.call(purchaseDetails); + return; + } if (purchaseDetails.status == PurchaseStatus.purchased) { try { await sessionModel.submitApplePlay( @@ -77,6 +87,7 @@ class AppPurchase { } catch (e) { logger.e("purchase error", error: e); Sentry.captureException(e); + _onError?.call(e); } } if (purchaseDetails.pendingCompletePurchase) { diff --git a/lib/plans/plan_details.dart b/lib/plans/plan_details.dart index 47dbd97bf..16474a359 100644 --- a/lib/plans/plan_details.dart +++ b/lib/plans/plan_details.dart @@ -1,5 +1,6 @@ import 'package:lantern/common/common.dart'; import 'package:lantern/core/purchase/app_purchase.dart'; +import 'package:lantern/plans/utils.dart'; class PlanCard extends StatelessWidget { final Plan plan; @@ -122,39 +123,69 @@ class PlanCard extends StatelessWidget { Future onPlanTap(BuildContext context, String planName) async { if (Platform.isAndroid) { - final isPlayVersion = sessionModel.isPlayVersion.value ?? false; - final inRussia = sessionModel.country.value == 'RU'; - //If user is downloaded from Play store and !inRussia then - //Go with In App purchase - if (isPlayVersion && !inRussia) { - await sessionModel - .submitGooglePlay(planName) - .onError((error, stackTrace) { - // on failure - CDialog.showError( - context, - error: e, - stackTrace: stackTrace, - description: - (error as PlatformException).message ?? error.toString(), - ); - }); - } else { - // * Proceed to our own Checkout - await context.pushRoute( - Checkout( - plan: plan, - isPro: isPro, - ), + _proceedToAndroidCheckout(context, planName); + } else { + _proceedToCheckoutIOS(context); + } + } + + Future _proceedToAndroidCheckout( + BuildContext context, String planName) async { + final isPlayVersion = sessionModel.isPlayVersion.value ?? false; + final inRussia = sessionModel.country.value == 'RU'; + //If user is downloaded from Play store and !inRussia then + //Go with In App purchase + if (isPlayVersion && !inRussia) { + await sessionModel + .submitGooglePlay(planName) + .onError((error, stackTrace) { + // on failure + CDialog.showError( + context, + error: e, + stackTrace: stackTrace, + description: (error as PlatformException).message ?? error.toString(), ); - } + }); } else { - // * Proceed to IOSs - final appPurchase = sl(); + _proceedToCustomCheckout(context); + } + } + + Future _proceedToCustomCheckout(BuildContext context) async { + await context.pushRoute( + Checkout( + plan: plan, + isPro: isPro, + ), + ); + } + + void _proceedToCheckoutIOS(BuildContext context) { + final appPurchase = sl(); + try { + context.loaderOverlay.show(); appPurchase.startPurchase( plan.id, - onSuccess: () {}, - onFailure: (error) {}, + onSuccess: () { + context.loaderOverlay.hide(); + showSuccessDialog(context, isPro); + }, + onFailure: (error) { + context.loaderOverlay.hide(); + CDialog.showError( + context, + error: error, + description: error.toString(), + ); + }, + ); + } catch (e) { + context.loaderOverlay.hide(); + CDialog.showError( + context, + error: e, + description: e.toString(), ); } } From 9b657e11c3a1e38bbe561d93ebefa8385504e5ad Mon Sep 17 00:00:00 2001 From: Jigar-f Date: Wed, 13 Dec 2023 12:01:34 +0530 Subject: [PATCH 17/17] Changes in logs. --- internalsdk/session_model.go | 2 +- lib/core/purchase/app_purchase.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/internalsdk/session_model.go b/internalsdk/session_model.go index 7c7728d6d..07e05acd5 100644 --- a/internalsdk/session_model.go +++ b/internalsdk/session_model.go @@ -898,7 +898,7 @@ func submitApplePayPayment(m *SessionModel, planId string, purchaseToken string) if err != nil { return err } - log.Errorf("Purchase Request response %+v", purchase) + log.Debugf("Purchase Request response %+v", purchase) if purchase.Status != "ok" { return errors.New("Purchase Request failed") diff --git a/lib/core/purchase/app_purchase.dart b/lib/core/purchase/app_purchase.dart index 178ac2e13..ddf6f7f12 100644 --- a/lib/core/purchase/app_purchase.dart +++ b/lib/core/purchase/app_purchase.dart @@ -74,7 +74,7 @@ class AppPurchase { Future _handlePurchase(PurchaseDetails purchaseDetails) async { if (purchaseDetails.status == PurchaseStatus.canceled) { // User has canceled the purchase - _onError?.call(purchaseDetails); + _onError?.call("Purchase canceled"); return; } if (purchaseDetails.status == PurchaseStatus.purchased) {