github.com/aldelo/common@v1.5.1/wrapper/sns/sns.go (about) 1 package sns 2 3 /* 4 * Copyright 2020-2023 Aldelo, LP 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 // ================================================================================================================= 20 // AWS CREDENTIAL: 21 // use $> aws configure (to set aws access key and secret to target machine) 22 // Store AWS Access ID and Secret Key into Default Profile Using '$ aws configure' cli 23 // 24 // To Install & Setup AWS CLI on Host: 25 // 1) https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2-linux.html 26 // On Ubuntu, if host does not have zip and unzip: 27 // $> sudo apt install zip 28 // $> sudo apt install unzip 29 // On Ubuntu, to install AWS CLI v2: 30 // $> curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" 31 // $> unzip awscliv2.zip 32 // $> sudo ./aws/install 33 // 2) $> aws configure set region awsRegionName --profile default 34 // 3) $> aws configure 35 // follow prompts to enter Access ID and Secret Key 36 // 37 // AWS Region Name Reference: 38 // us-west-2, us-east-1, ap-northeast-1, etc 39 // See: https://docs.aws.amazon.com/general/latest/gr/rande.html 40 // ================================================================================================================= 41 42 import ( 43 "context" 44 "errors" 45 util "github.com/aldelo/common" 46 awshttp2 "github.com/aldelo/common/wrapper/aws" 47 awsregion "github.com/aldelo/common/wrapper/aws/awsregion" 48 "github.com/aldelo/common/wrapper/sns/snsapplicationplatform" 49 "github.com/aldelo/common/wrapper/sns/snscreatetopicattribute" 50 "github.com/aldelo/common/wrapper/sns/snsendpointattribute" 51 "github.com/aldelo/common/wrapper/sns/snsgetsubscriptionattribute" 52 "github.com/aldelo/common/wrapper/sns/snsgettopicattribute" 53 "github.com/aldelo/common/wrapper/sns/snsplatformapplicationattribute" 54 "github.com/aldelo/common/wrapper/sns/snsprotocol" 55 "github.com/aldelo/common/wrapper/sns/snssubscribeattribute" 56 "github.com/aldelo/common/wrapper/xray" 57 "github.com/aws/aws-sdk-go/aws" 58 "github.com/aws/aws-sdk-go/aws/session" 59 "github.com/aws/aws-sdk-go/service/sns" 60 awsxray "github.com/aws/aws-xray-sdk-go/xray" 61 "net/http" 62 "time" 63 ) 64 65 // ================================================================================================================ 66 // STRUCTS 67 // ================================================================================================================ 68 69 // SNS struct encapsulates the AWS SNS access functionality 70 type SNS struct { 71 // define the AWS region that SNS is located at 72 AwsRegion awsregion.AWSRegion 73 74 // custom http2 client options 75 HttpOptions *awshttp2.HttpClientSettings 76 77 // optional, sms sender name info 78 SMSSenderName string 79 80 // optional, indicates if sms message sent is transaction or promotional 81 SMSTransactional bool 82 83 // store sns client object 84 snsClient *sns.SNS 85 86 _parentSegment *xray.XRayParentSegment 87 } 88 89 // SubscribedTopic struct encapsulates the AWS SNS subscribed topic data 90 type SubscribedTopic struct { 91 SubscriptionArn string 92 TopicArn string 93 Protocol snsprotocol.SNSProtocol 94 Endpoint string 95 Owner string 96 } 97 98 // ================================================================================================================ 99 // STRUCTS FUNCTIONS 100 // ================================================================================================================ 101 102 // ---------------------------------------------------------------------------------------------------------------- 103 // utility functions 104 // ---------------------------------------------------------------------------------------------------------------- 105 106 // Connect will establish a connection to the SNS service 107 func (s *SNS) Connect(parentSegment ...*xray.XRayParentSegment) (err error) { 108 if xray.XRayServiceOn() { 109 if len(parentSegment) > 0 { 110 s._parentSegment = parentSegment[0] 111 } 112 113 seg := xray.NewSegment("SNS-Connect", s._parentSegment) 114 defer seg.Close() 115 defer func() { 116 _ = seg.Seg.AddMetadata("SNS-AWS-Region", s.AwsRegion) 117 _ = seg.Seg.AddMetadata("SNS-SMS-Sender-Name", s.SMSSenderName) 118 _ = seg.Seg.AddMetadata("SNS-SMS-Transactional", s.SMSTransactional) 119 120 if err != nil { 121 _ = seg.Seg.AddError(err) 122 } 123 }() 124 125 err = s.connectInternal() 126 127 if err == nil { 128 awsxray.AWS(s.snsClient.Client) 129 } 130 131 return err 132 } else { 133 return s.connectInternal() 134 } 135 } 136 137 // Connect will establish a connection to the SNS service 138 func (s *SNS) connectInternal() error { 139 // clean up prior object 140 s.snsClient = nil 141 142 if !s.AwsRegion.Valid() || s.AwsRegion == awsregion.UNKNOWN { 143 return errors.New("Connect To SNS Failed: (AWS Session Error) " + "Region is Required") 144 } 145 146 // create custom http2 client if needed 147 var httpCli *http.Client 148 var httpErr error 149 150 if s.HttpOptions == nil { 151 s.HttpOptions = new(awshttp2.HttpClientSettings) 152 } 153 154 // use custom http2 client 155 h2 := &awshttp2.AwsHttp2Client{ 156 Options: s.HttpOptions, 157 } 158 159 if httpCli, httpErr = h2.NewHttp2Client(); httpErr != nil { 160 return errors.New("Connect to SNS Failed: (AWS Session Error) " + "Create Custom Http2 Client Errored = " + httpErr.Error()) 161 } 162 163 // establish aws session connection and keep session object in struct 164 if sess, err := session.NewSession( 165 &aws.Config{ 166 Region: aws.String(s.AwsRegion.Key()), 167 HTTPClient: httpCli, 168 }); err != nil { 169 // aws session error 170 return errors.New("Connect To SNS Failed: (AWS Session Error) " + err.Error()) 171 } else { 172 // create cached objects for shared use 173 s.snsClient = sns.New(sess) 174 175 if s.snsClient == nil { 176 return errors.New("Connect To SNS Client Failed: (New SNS Client Connection) " + "Connection Object Nil") 177 } 178 179 // session stored to struct 180 return nil 181 } 182 } 183 184 // Disconnect will disjoin from aws session by clearing it 185 func (s *SNS) Disconnect() { 186 s.snsClient = nil 187 } 188 189 // UpdateParentSegment updates this struct's xray parent segment, if no parent segment, set nil 190 func (s *SNS) UpdateParentSegment(parentSegment *xray.XRayParentSegment) { 191 s._parentSegment = parentSegment 192 } 193 194 // ---------------------------------------------------------------------------------------------------------------- 195 // internal helper methods 196 // ---------------------------------------------------------------------------------------------------------------- 197 198 // toAwsCreateTopicAttributes will convert from strongly typed to aws accepted map 199 func (s *SNS) toAwsCreateTopicAttributes(attributes map[snscreatetopicattribute.SNSCreateTopicAttribute]string) (newMap map[string]*string) { 200 // validate 201 if attributes == nil { 202 return nil 203 } 204 205 // make map 206 newMap = make(map[string]*string) 207 208 for k, v := range attributes { 209 if k.Valid() && k != snscreatetopicattribute.UNKNOWN { 210 newMap[k.Key()] = aws.String(v) 211 } 212 } 213 214 return newMap 215 } 216 217 // fromAwsCreateTopicAttributes will convert from aws map to strongly typed map 218 func (s *SNS) fromAwsCreateTopicAttributes(attributes map[string]*string) (newMap map[snscreatetopicattribute.SNSCreateTopicAttribute]string) { 219 // validate 220 if attributes == nil { 221 return nil 222 } 223 224 // make map 225 newMap = make(map[snscreatetopicattribute.SNSCreateTopicAttribute]string) 226 var conv snscreatetopicattribute.SNSCreateTopicAttribute 227 228 for k, v := range attributes { 229 if util.LenTrim(k) > 0 { 230 v1 := aws.StringValue(v) 231 232 if k1, err := conv.ParseByKey(k); err == nil { 233 newMap[k1] = v1 234 } 235 } 236 } 237 238 return newMap 239 } 240 241 // toAwsGetTopicAttributes will convert from strongly typed to aws accepted map 242 func (s *SNS) toAwsGetTopicAttributes(attributes map[snsgettopicattribute.SNSGetTopicAttribute]string) (newMap map[string]*string) { 243 // validate 244 if attributes == nil { 245 return nil 246 } 247 248 // make map 249 newMap = make(map[string]*string) 250 251 for k, v := range attributes { 252 if k.Valid() && k != snsgettopicattribute.UNKNOWN { 253 newMap[k.Key()] = aws.String(v) 254 } 255 } 256 257 return newMap 258 } 259 260 // fromAwsGetTopicAttributes will convert from aws map to strongly typed map 261 func (s *SNS) fromAwsGetTopicAttributes(attributes map[string]*string) (newMap map[snsgettopicattribute.SNSGetTopicAttribute]string) { 262 // validate 263 if attributes == nil { 264 return nil 265 } 266 267 // make map 268 newMap = make(map[snsgettopicattribute.SNSGetTopicAttribute]string) 269 var conv snsgettopicattribute.SNSGetTopicAttribute 270 271 for k, v := range attributes { 272 if util.LenTrim(k) > 0 { 273 v1 := aws.StringValue(v) 274 275 if k1, err := conv.ParseByKey(k); err == nil { 276 newMap[k1] = v1 277 } 278 } 279 } 280 281 return newMap 282 } 283 284 // toAwsSubscribeAttributes will convert from strongly typed to aws accepted map 285 func (s *SNS) toAwsSubscribeAttributes(attributes map[snssubscribeattribute.SNSSubscribeAttribute]string) (newMap map[string]*string) { 286 // validate 287 if attributes == nil { 288 return nil 289 } 290 291 // make map 292 newMap = make(map[string]*string) 293 294 for k, v := range attributes { 295 if k.Valid() && k != snssubscribeattribute.UNKNOWN { 296 newMap[k.Key()] = aws.String(v) 297 } 298 } 299 300 return newMap 301 } 302 303 // fromAwsSubscribeAttributes will convert from aws map to strongly typed map 304 func (s *SNS) fromAwsSubscribeAttributes(attributes map[string]*string) (newMap map[snssubscribeattribute.SNSSubscribeAttribute]string) { 305 // validate 306 if attributes == nil { 307 return nil 308 } 309 310 // make map 311 newMap = make(map[snssubscribeattribute.SNSSubscribeAttribute]string) 312 var conv snssubscribeattribute.SNSSubscribeAttribute 313 314 for k, v := range attributes { 315 if util.LenTrim(k) > 0 { 316 v1 := aws.StringValue(v) 317 318 if k1, err := conv.ParseByKey(k); err == nil { 319 newMap[k1] = v1 320 } 321 } 322 } 323 324 return newMap 325 } 326 327 // toAwsGetSubscriptionAttributes will convert from strongly typed to aws accepted map 328 func (s *SNS) toAwsGetSubscriptionAttributes(attributes map[snsgetsubscriptionattribute.SNSGetSubscriptionAttribute]string) (newMap map[string]*string) { 329 // validate 330 if attributes == nil { 331 return nil 332 } 333 334 // make map 335 newMap = make(map[string]*string) 336 337 for k, v := range attributes { 338 if k.Valid() && k != snsgetsubscriptionattribute.UNKNOWN { 339 newMap[k.Key()] = aws.String(v) 340 } 341 } 342 343 return newMap 344 } 345 346 // fromAwsGetSubscriptionAttributes will convert from aws map to strongly typed map 347 func (s *SNS) fromAwsGetSubscriptionAttributes(attributes map[string]*string) (newMap map[snsgetsubscriptionattribute.SNSGetSubscriptionAttribute]string) { 348 // validate 349 if attributes == nil { 350 return nil 351 } 352 353 // make map 354 newMap = make(map[snsgetsubscriptionattribute.SNSGetSubscriptionAttribute]string) 355 var conv snsgetsubscriptionattribute.SNSGetSubscriptionAttribute 356 357 for k, v := range attributes { 358 if util.LenTrim(k) > 0 { 359 v1 := aws.StringValue(v) 360 361 if k1, err := conv.ParseByKey(k); err == nil { 362 newMap[k1] = v1 363 } 364 } 365 } 366 367 return newMap 368 } 369 370 // toAwsPlatformApplicationAttributes will convert from strongly typed to aws accepted map 371 func (s *SNS) toAwsPlatformApplicationAttributes(attributes map[snsplatformapplicationattribute.SNSPlatformApplicationAttribute]string) (newMap map[string]*string) { 372 // validate 373 if attributes == nil { 374 return nil 375 } 376 377 // make map 378 newMap = make(map[string]*string) 379 380 for k, v := range attributes { 381 if k.Valid() && k != snsplatformapplicationattribute.UNKNOWN { 382 newMap[k.Key()] = aws.String(v) 383 } 384 } 385 386 return newMap 387 } 388 389 // fromAwsPlatformApplicationAttributes will convert from aws map to strongly typed map 390 func (s *SNS) fromAwsPlatformApplicationAttributes(attributes map[string]*string) (newMap map[snsplatformapplicationattribute.SNSPlatformApplicationAttribute]string) { 391 // validate 392 if attributes == nil { 393 return nil 394 } 395 396 // make map 397 newMap = make(map[snsplatformapplicationattribute.SNSPlatformApplicationAttribute]string) 398 var conv snsplatformapplicationattribute.SNSPlatformApplicationAttribute 399 400 for k, v := range attributes { 401 if util.LenTrim(k) > 0 { 402 v1 := aws.StringValue(v) 403 404 if k1, err := conv.ParseByKey(k); err == nil { 405 newMap[k1] = v1 406 } 407 } 408 } 409 410 return newMap 411 } 412 413 // toAwsEndpointAttributes will convert from strongly typed to aws accepted map 414 func (s *SNS) toAwsEndpointAttributes(attributes map[snsendpointattribute.SNSEndpointAttribute]string) (newMap map[string]*string) { 415 // validate 416 if attributes == nil { 417 return nil 418 } 419 420 // make map 421 newMap = make(map[string]*string) 422 423 for k, v := range attributes { 424 if k.Valid() && k != snsendpointattribute.UNKNOWN { 425 newMap[k.Key()] = aws.String(v) 426 } 427 } 428 429 return newMap 430 } 431 432 // fromAwsEndpointAttributes will convert from aws map to strongly typed map 433 func (s *SNS) fromAwsEndpointAttributes(attributes map[string]*string) (newMap map[snsendpointattribute.SNSEndpointAttribute]string) { 434 // validate 435 if attributes == nil { 436 return nil 437 } 438 439 // make map 440 newMap = make(map[snsendpointattribute.SNSEndpointAttribute]string) 441 var conv snsendpointattribute.SNSEndpointAttribute 442 443 for k, v := range attributes { 444 if util.LenTrim(k) > 0 { 445 v1 := aws.StringValue(v) 446 447 if k1, err := conv.ParseByKey(k); err == nil { 448 newMap[k1] = v1 449 } 450 } 451 } 452 453 return newMap 454 } 455 456 // ---------------------------------------------------------------------------------------------------------------- 457 // topic methods 458 // ---------------------------------------------------------------------------------------------------------------- 459 460 // CreateTopic will create a new topic in SNS for clients to subscribe, 461 // once topic is created, the topicArn is returned for subsequent uses 462 // 463 // Parameters: 464 // 1. topicName = required, the name of the topic to create in SNS 465 // 2. attributes = optional, topic attributes to further customize the topic 466 // 3. timeOutDuration = optional, indicates timeout value for context 467 // 468 // Topic Attributes: (Key = Expected Value) 469 // 1. DeliveryPolicy = The JSON serialization of the topic's delivery policy 470 // 2. DisplayName = The human-readable name used in the From field for notifications to email and email-json endpoints 471 // 3. Policy = The JSON serialization of the topic's access control policy 472 // 473 // The following attribute applies only to server-side-encryption (https://docs.aws.amazon.com/sns/latest/dg/sns-server-side-encryption.html): 474 // 475 // a) KmsMasterKeyId = The ID of an AWS-managed customer master key (CMK) for Amazon SNS or a custom CMK. 476 // For more information, see Key Terms (https://docs.aws.amazon.com/sns/latest/dg/sns-server-side-encryption.html#sse-key-terms) 477 // For more examples, see KeyId (https://docs.aws.amazon.com/kms/latest/APIReference/API_DescribeKey.html#API_DescribeKey_RequestParameters) in the AWS Key Management Service API Reference 478 func (s *SNS) CreateTopic(topicName string, attributes map[snscreatetopicattribute.SNSCreateTopicAttribute]string, timeOutDuration ...time.Duration) (topicArn string, err error) { 479 segCtx := context.Background() 480 segCtxSet := false 481 482 seg := xray.NewSegmentNullable("SNS-CreateTopic", s._parentSegment) 483 484 if seg != nil { 485 segCtx = seg.Ctx 486 segCtxSet = true 487 488 defer seg.Close() 489 defer func() { 490 _ = seg.Seg.AddMetadata("SNS-CreateTopic-TopicName", topicName) 491 _ = seg.Seg.AddMetadata("SNS-CreateTopic-Attributes", attributes) 492 _ = seg.Seg.AddMetadata("SNS-CreateTopic-Result-TopicArn", topicArn) 493 494 if err != nil { 495 _ = seg.Seg.AddError(err) 496 } 497 }() 498 } 499 500 // validation 501 if s.snsClient == nil { 502 err = errors.New("CreateTopic Failed: " + "SNS Client is Required") 503 return "", err 504 } 505 506 if util.LenTrim(topicName) <= 0 { 507 err = errors.New("CreateTopic Failed: " + "Topic Name is Required") 508 return "", err 509 } 510 511 // create input object 512 input := &sns.CreateTopicInput{ 513 Name: aws.String(topicName), 514 } 515 516 if attributes != nil { 517 input.Attributes = s.toAwsCreateTopicAttributes(attributes) 518 } 519 520 // perform action 521 var output *sns.CreateTopicOutput 522 523 if len(timeOutDuration) > 0 { 524 ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0]) 525 defer cancel() 526 527 output, err = s.snsClient.CreateTopicWithContext(ctx, input) 528 } else { 529 if segCtxSet { 530 output, err = s.snsClient.CreateTopicWithContext(segCtx, input) 531 } else { 532 output, err = s.snsClient.CreateTopic(input) 533 } 534 } 535 536 // evaluate result 537 if err != nil { 538 err = errors.New("CreateTopic Failed: (Create Action) " + err.Error()) 539 return "", err 540 } 541 542 topicArn = *output.TopicArn 543 return topicArn, nil 544 } 545 546 // DeleteTopic will delete an existing SNS topic by topicArn, 547 // returns nil if successful 548 func (s *SNS) DeleteTopic(topicArn string, timeOutDuration ...time.Duration) (err error) { 549 segCtx := context.Background() 550 segCtxSet := false 551 552 seg := xray.NewSegmentNullable("SNS-DeleteTopic", s._parentSegment) 553 554 if seg != nil { 555 segCtx = seg.Ctx 556 segCtxSet = true 557 558 defer seg.Close() 559 defer func() { 560 _ = seg.Seg.AddMetadata("SNS-DeleteTopic-TopicArn", topicArn) 561 562 if err != nil { 563 _ = seg.Seg.AddError(err) 564 } 565 }() 566 } 567 568 // validation 569 if s.snsClient == nil { 570 err = errors.New("DeleteTopic Failed: " + "SNS Client is Required") 571 return err 572 } 573 574 if util.LenTrim(topicArn) <= 0 { 575 err = errors.New("DeleteTopic Failed: " + "Topic ARN is Required") 576 return err 577 } 578 579 // create input object 580 input := &sns.DeleteTopicInput{ 581 TopicArn: aws.String(topicArn), 582 } 583 584 // perform action 585 if len(timeOutDuration) > 0 { 586 ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0]) 587 defer cancel() 588 589 _, err = s.snsClient.DeleteTopicWithContext(ctx, input) 590 } else { 591 if segCtxSet { 592 _, err = s.snsClient.DeleteTopicWithContext(segCtx, input) 593 } else { 594 _, err = s.snsClient.DeleteTopic(input) 595 } 596 } 597 598 // evaluate result 599 if err != nil { 600 err = errors.New("DeleteTopic Failed: (Delete Action) " + err.Error()) 601 return err 602 } else { 603 return nil 604 } 605 } 606 607 // ListTopics will list SNS topics, with optional nextToken for retrieving more list from a prior call 608 // 609 // Parameters: 610 // 1. nextToken = optional, if prior call returned more...token, pass in here to retrieve the related list 611 // 2. timeOutDuration = optional, indicates timeout value for context 612 // 613 // Return Values: 614 // 1. topicArnsList = string slice of topic ARNs, nil if not set 615 // 2. moreTopicArnsNextToken = if there are more topics, this token is filled, to query more, use the token as input parameter, blank if no more 616 // 3. err = error info if any 617 func (s *SNS) ListTopics(nextToken string, timeOutDuration ...time.Duration) (topicArnsList []string, moreTopicArnsNextToken string, err error) { 618 segCtx := context.Background() 619 segCtxSet := false 620 621 seg := xray.NewSegmentNullable("SNS-ListTopics", s._parentSegment) 622 623 if seg != nil { 624 segCtx = seg.Ctx 625 segCtxSet = true 626 627 defer seg.Close() 628 defer func() { 629 _ = seg.Seg.AddMetadata("SNS-ListTopics-NextToken", nextToken) 630 _ = seg.Seg.AddMetadata("SNS-ListTopics-Result-TopicArnsList", topicArnsList) 631 _ = seg.Seg.AddMetadata("SNS-ListTopics-Result-NextToken", moreTopicArnsNextToken) 632 633 if err != nil { 634 _ = seg.Seg.AddError(err) 635 } 636 }() 637 } 638 639 // validation 640 if s.snsClient == nil { 641 err = errors.New("ListTopics Failed: " + "SNS Client is Required") 642 return nil, "", err 643 } 644 645 // create input object 646 input := &sns.ListTopicsInput{} 647 648 if util.LenTrim(nextToken) > 0 { 649 input.NextToken = aws.String(nextToken) 650 } 651 652 // perform action 653 var output *sns.ListTopicsOutput 654 655 if len(timeOutDuration) > 0 { 656 ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0]) 657 defer cancel() 658 659 output, err = s.snsClient.ListTopicsWithContext(ctx, input) 660 } else { 661 if segCtxSet { 662 output, err = s.snsClient.ListTopicsWithContext(segCtx, input) 663 } else { 664 output, err = s.snsClient.ListTopics(input) 665 } 666 } 667 668 // evaluate result 669 if err != nil { 670 err = errors.New("ListTopics Failed: (List Action) " + err.Error()) 671 return nil, "", err 672 } 673 674 moreTopicArnsNextToken = aws.StringValue(output.NextToken) 675 676 for _, v := range output.Topics { 677 buf := aws.StringValue(v.TopicArn) 678 679 if util.LenTrim(buf) > 0 { 680 topicArnsList = append(topicArnsList, buf) 681 } 682 } 683 684 return topicArnsList, moreTopicArnsNextToken, nil 685 } 686 687 // GetTopicAttributes will retrieve a map of topic attributes based on topicArn 688 // 689 // Parameters: 690 // 1. topicArn = required, specify the topicArn to retrieve related topic attributes 691 // 2. timeOutDuration = optional, indicates timeout value for context 692 // 693 // Return Values: 694 // 1. attributes = map of sns get topic attributes key value pairs related to teh topic ARN being queried 695 // 2. err = error info if any 696 // 697 // Topic Attributes: (Key = Expected Value) 698 // 1. DeliveryPolicy = The JSON serialization of the topic's delivery policy (See Subscribe DeliveryPolicy Json Format) 699 // 2. DisplayName = The human-readable name used in the From field for notifications to email and email-json endpoints 700 // 3. Owner = The AWS account ID of the topic's owner 701 // 4. Policy = The JSON serialization of the topic's access control policy 702 // 5. SubscriptionsConfirmed = The number of confirmed subscriptions for the topic 703 // 6. SubscriptionsDeleted = The number of deleted subscriptions for the topic 704 // 7. SubscriptionsPending = The number of subscriptions pending confirmation for the topic 705 // 8. TopicArn = The topic's ARN 706 // 9. EffectiveDeliveryPolicy = Yhe JSON serialization of the effective delivery policy, taking system defaults into account 707 // 708 // The following attribute applies only to server-side-encryption (https://docs.aws.amazon.com/sns/latest/dg/sns-server-side-encryption.html): 709 // 710 // a) KmsMasterKeyId = The ID of an AWS-managed customer master key (CMK) for Amazon SNS or a custom CMK. 711 // For more information, see Key Terms (https://docs.aws.amazon.com/sns/latest/dg/sns-server-side-encryption.html#sse-key-terms) 712 // For more examples, see KeyId (https://docs.aws.amazon.com/kms/latest/APIReference/API_DescribeKey.html#API_DescribeKey_RequestParameters) in the AWS Key Management Service API Reference 713 func (s *SNS) GetTopicAttributes(topicArn string, timeOutDuration ...time.Duration) (attributes map[snsgettopicattribute.SNSGetTopicAttribute]string, err error) { 714 segCtx := context.Background() 715 segCtxSet := false 716 717 seg := xray.NewSegmentNullable("SNS-GetTopicAttributes", s._parentSegment) 718 719 if seg != nil { 720 segCtx = seg.Ctx 721 segCtxSet = true 722 723 defer seg.Close() 724 defer func() { 725 _ = seg.Seg.AddMetadata("SNS-GetTopicAttributes-TopicArn", topicArn) 726 _ = seg.Seg.AddMetadata("SNS-GetTopicAttributes-Result-Attributes", attributes) 727 728 if err != nil { 729 _ = seg.Seg.AddError(err) 730 } 731 }() 732 } 733 734 // validation 735 if s.snsClient == nil { 736 err = errors.New("GetTopicAttributes Failed: " + "SNS Client is Required") 737 return nil, err 738 } 739 740 if util.LenTrim(topicArn) <= 0 { 741 err = errors.New("GetTopicAttributes Failed: " + "Topic ARN is Required") 742 return nil, err 743 } 744 745 // create input object 746 input := &sns.GetTopicAttributesInput{ 747 TopicArn: aws.String(topicArn), 748 } 749 750 // perform action 751 var output *sns.GetTopicAttributesOutput 752 753 if len(timeOutDuration) > 0 { 754 ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0]) 755 defer cancel() 756 757 output, err = s.snsClient.GetTopicAttributesWithContext(ctx, input) 758 } else { 759 if segCtxSet { 760 output, err = s.snsClient.GetTopicAttributesWithContext(segCtx, input) 761 } else { 762 output, err = s.snsClient.GetTopicAttributes(input) 763 } 764 } 765 766 // evaluate result 767 if err != nil { 768 err = errors.New("GetTopicAttributes Failed: (Get Action) " + err.Error()) 769 return nil, err 770 } 771 772 attributes = s.fromAwsGetTopicAttributes(output.Attributes) 773 return attributes, nil 774 } 775 776 // SetTopicAttribute will set or update a topic attribute, 777 // For attribute value or Json format, see corresponding notes in CreateTopic where applicable 778 func (s *SNS) SetTopicAttribute(topicArn string, 779 attributeName snscreatetopicattribute.SNSCreateTopicAttribute, 780 attributeValue string, 781 timeOutDuration ...time.Duration) (err error) { 782 segCtx := context.Background() 783 segCtxSet := false 784 785 seg := xray.NewSegmentNullable("SNS-SetTopicAttribute", s._parentSegment) 786 787 if seg != nil { 788 segCtx = seg.Ctx 789 segCtxSet = true 790 791 defer seg.Close() 792 defer func() { 793 _ = seg.Seg.AddMetadata("SNS-SetTopicAttribute-TopicArn", topicArn) 794 _ = seg.Seg.AddMetadata("SNS-SetTopicAttribute-AttributeName", attributeName) 795 _ = seg.Seg.AddMetadata("SNS-SetTopicAttribute-AttributeValue", attributeValue) 796 797 if err != nil { 798 _ = seg.Seg.AddError(err) 799 } 800 }() 801 } 802 803 // validation 804 if s.snsClient == nil { 805 err = errors.New("SetTopicAttribute Failed: " + "SNS Client is Required") 806 return err 807 } 808 809 if util.LenTrim(topicArn) <= 0 { 810 err = errors.New("SetTopicAttribute Failed: " + "Topic ARN is Required") 811 return err 812 } 813 814 if !attributeName.Valid() || attributeName == snscreatetopicattribute.UNKNOWN { 815 err = errors.New("SetTopicAttribute Failed: " + "Attribute Name is Required") 816 return err 817 } 818 819 // create input object 820 input := &sns.SetTopicAttributesInput{ 821 TopicArn: aws.String(topicArn), 822 AttributeName: aws.String(attributeName.Key()), 823 AttributeValue: aws.String(attributeValue), 824 } 825 826 // perform action 827 if len(timeOutDuration) > 0 { 828 ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0]) 829 defer cancel() 830 831 _, err = s.snsClient.SetTopicAttributesWithContext(ctx, input) 832 } else { 833 if segCtxSet { 834 _, err = s.snsClient.SetTopicAttributesWithContext(segCtx, input) 835 } else { 836 _, err = s.snsClient.SetTopicAttributes(input) 837 } 838 } 839 840 // evaluate result 841 if err != nil { 842 err = errors.New("SetTopicAttribute Failed: (Set Action) " + err.Error()) 843 return err 844 } else { 845 return nil 846 } 847 } 848 849 // ---------------------------------------------------------------------------------------------------------------- 850 // subscriber methods 851 // ---------------------------------------------------------------------------------------------------------------- 852 853 // Subscribe will allow client to subscribe to a SNS topic (previously created with CreateTopic method), 854 // the subscriptionArn is returned upon success, 855 // 856 // if subscription needs client confirmation, then the string 'pending confirmation' is returned instead 857 // 858 // Parameters: 859 // 1. topicArn = required, subscribe to this topic ARN 860 // 2. protocol = required, SNS callback protocol, so that when publish to the topic occurs, this protocol is used as callback 861 // 3. endPoint = required, SNS callback endpoint, so that when publish to the topic occurs, this endpoint is triggered by the callback 862 // 4. attributes = optional, map of sns subscribe attribute key value pairs 863 // 5. timeOutDuration = optional, indicates timeout value for context 864 // 865 // Protocols: (Key = Expected Value) 866 // 1. http = delivery of JSON-encoded message via HTTP POST 867 // 2. https = delivery of JSON-encoded message via HTTPS POST 868 // 3. email = delivery of message via SMTP 869 // 4. email-json = delivery of JSON-encoded message via SMTP 870 // 5. sms = delivery of message via SMS 871 // 6. sqs = delivery of JSON-encoded message to an Amazon SQS queue 872 // 7. application = delivery of JSON-encoded message to an EndpointArn for a mobile app and device 873 // 8. lambda = delivery of JSON-encoded message to an Amazon Lambda function 874 // 875 // Endpoint To Receive Notifications: (Based on Protocol) 876 // 1. http protocol = the endpoint is an URL beginning with http:// 877 // 2. https protocol = the endpoint is a URL beginning with https:// 878 // 3. email protocol = the endpoint is an email address 879 // 4. email-json protocol = the endpoint is an email address 880 // 5. sms protocol = the endpoint is a phone number of an SMS-enabled device 881 // 6. sqs protocol = the endpoint is the ARN of an Amazon SQS queue 882 // 7. application protocol = the endpoint is the EndpointArn of a mobile app and device 883 // 8. lambda protocol = the endpoint is the ARN of an Amazon Lambda function 884 // 885 // Subscribe Attributes: (Key = Expected Value) 886 // 1. DeliveryPolicy = The policy that defines how Amazon SNS retries failed deliveries to HTTP/S endpoints 887 // *) example to set delivery policy to 5 retries: 888 // { 889 // "healthyRetryPolicy": { 890 // "minDelayTarget": <intValue>, 891 // "maxDelayTarget": <intValue>, 892 // "numRetries": <intValue>, 893 // "numMaxDelayRetries": <intValue>, 894 // "backoffFunction": "<linear|arithmetic|geometric|exponential>" 895 // }, 896 // "throttlePolicy": { 897 // "maxReceivesPerSecond": <intValue> 898 // } 899 // } 900 // *) Not All Json Elements Need To Be Filled in Policy, Use What is Needed, such as: 901 // { "healthyRetryPolicy": { "numRetries": 5 } } 902 // 2. FilterPolicy = The simple JSON object that lets your subscriber receive only a subset of messages, 903 // rather than receiving every message published to the topic: 904 // *) subscriber attribute controls filter allowance, 905 // publish attribute indicates attributes contained in message 906 // *) if any single attribute in this policy doesn't match an attribute assigned to message, this policy rejects the message: 907 // { 908 // "store": ["example_corp"], 909 // "event": [{"anything-but": "order_cancelled"}], 910 // "customer_interests": ["rugby", "football", "baseball"], 911 // "price_usd": [{"numeric": [">=", 100]}] 912 // } 913 // *) "xyz": [{"anything-but": ...}] keyword indicates to match anything but the defined value ... Json element (... may be string or numeric) 914 // *) "xyz": [{"prefix": ...}] keyword indicates to match value prefixed from the defined value ... in Json element 915 // *) "xyz": [{"numeric": ["=", ...]}] keyword indicates numeric equal matching as indicated by numeric and = 916 // *) "xyz": [{"numeric": [">", ...]}] keyword indicates numeric compare matching as indicated by numeric and >, <, >=, <= 917 // *) "xyz": [{"numeric": [">", 0, "<", 100]}] keyword indicates numeric ranged compare matching as indicated by numeric and >, <, in parts 918 // *) "xyz": [{"exists": true}] keyword indicates attribute xyz exists matching 919 // 3. RawMessageDelivery = When set to true, enables raw message delivery to Amazon SQS or HTTP/S endpoints. 920 // This eliminates the need for the endpoints to process JSON formatting, which is otherwise created for Amazon SNS metadata 921 // 4. RedrivePolicy = When specified, sends undeliverable messages to the specified Amazon SQS dead-letter queue. 922 // Messages that can't be delivered due to client errors (for example, when the subscribed endpoint is unreachable), 923 // or server errors (for example, when the service that powers the subscribed endpoint becomes unavailable), 924 // are held in the dead-letter queue for further analysis or reprocessing 925 // *) example of RedrivePolicy to route failed messages to Dead Letter Queue (DLQ): 926 // { 927 // "deadLetterTargetArn": "dead letter sns queue arn such as arn:aws:sqs:us-east-2:12345678021:MyDeadLetterQueue" 928 // } 929 // 930 // Subscription Confirmation Support: 931 // 1. Http / Https Endpoints Requires Subscription Confirmation Support, See Details in URL Below: 932 // a) https://docs.aws.amazon.com/sns/latest/dg/sns-http-https-endpoint-as-subscriber.html 933 // 2. Once Subscribe action is performed, SNS sends confirmation notification to the HTTP/s Endpoint: 934 // b) Client Upon Receipt of the SNS Notification, Retrieve Token and Respond via ConfirmSubscription method 935 func (s *SNS) Subscribe(topicArn string, 936 protocol snsprotocol.SNSProtocol, 937 endPoint string, 938 attributes map[snssubscribeattribute.SNSSubscribeAttribute]string, 939 timeOutDuration ...time.Duration) (subscriptionArn string, err error) { 940 segCtx := context.Background() 941 segCtxSet := false 942 943 seg := xray.NewSegmentNullable("SNS-Subscribe", s._parentSegment) 944 945 if seg != nil { 946 segCtx = seg.Ctx 947 segCtxSet = true 948 949 defer seg.Close() 950 defer func() { 951 _ = seg.Seg.AddMetadata("SNS-Subscribe-TopicArn", topicArn) 952 _ = seg.Seg.AddMetadata("SNS-Subscribe-Protocol", protocol) 953 _ = seg.Seg.AddMetadata("SNS-Subscribe-Endpoint", endPoint) 954 _ = seg.Seg.AddMetadata("SNS-Subscribe-Attributes", attributes) 955 _ = seg.Seg.AddMetadata("SNS-Subscribe-Result-SubscriptionArn", subscriptionArn) 956 957 if err != nil { 958 _ = seg.Seg.AddError(err) 959 } 960 }() 961 } 962 963 // validation 964 if s.snsClient == nil { 965 err = errors.New("Subscribe Failed: " + "SNS Client is Required") 966 return "", err 967 } 968 969 if util.LenTrim(topicArn) <= 0 { 970 err = errors.New("Subscribe Failed: " + "Topic ARN is Required") 971 return "", err 972 } 973 974 if !protocol.Valid() || protocol == snsprotocol.UNKNOWN { 975 err = errors.New("Subscribe Failed: " + "Protocol is Required") 976 return "", err 977 } 978 979 if util.LenTrim(endPoint) <= 0 { 980 err = errors.New("Subscribe Failed: " + "Endpoint is Required") 981 return "", err 982 } 983 984 // create input object 985 input := &sns.SubscribeInput{ 986 TopicArn: aws.String(topicArn), 987 Protocol: aws.String(protocol.Key()), 988 Endpoint: aws.String(endPoint), 989 } 990 991 if attributes != nil { 992 input.Attributes = s.toAwsSubscribeAttributes(attributes) 993 } 994 995 // perform action 996 var output *sns.SubscribeOutput 997 998 if len(timeOutDuration) > 0 { 999 ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0]) 1000 defer cancel() 1001 1002 output, err = s.snsClient.SubscribeWithContext(ctx, input) 1003 } else { 1004 if segCtxSet { 1005 output, err = s.snsClient.SubscribeWithContext(segCtx, input) 1006 } else { 1007 output, err = s.snsClient.Subscribe(input) 1008 } 1009 } 1010 1011 // evaluate result 1012 if err != nil { 1013 err = errors.New("Subscribe Failed: (Subscribe Action) " + err.Error()) 1014 return "", err 1015 } 1016 1017 subscriptionArn = *output.SubscriptionArn 1018 return subscriptionArn, nil 1019 } 1020 1021 // Unsubscribe will remove a subscription in SNS via subscriptionArn, 1022 // nil is returned if successful, otherwise err is filled with error info 1023 // 1024 // Parameters: 1025 // 1. subscriptionArn = required, the subscription ARN to remove from SNS 1026 // 2. timeOutDuration = optional, indicates timeout value for context 1027 func (s *SNS) Unsubscribe(subscriptionArn string, timeOutDuration ...time.Duration) (err error) { 1028 segCtx := context.Background() 1029 segCtxSet := false 1030 1031 seg := xray.NewSegmentNullable("SNS-Unsubscribe", s._parentSegment) 1032 1033 if seg != nil { 1034 segCtx = seg.Ctx 1035 segCtxSet = true 1036 1037 defer seg.Close() 1038 defer func() { 1039 _ = seg.Seg.AddMetadata("SNS-Unsubscribe-SubscriptionArn", subscriptionArn) 1040 1041 if err != nil { 1042 _ = seg.Seg.AddError(err) 1043 } 1044 }() 1045 } 1046 1047 // validation 1048 if s.snsClient == nil { 1049 err = errors.New("Unsubscribe Failed: " + "SNS Client is Required") 1050 return err 1051 } 1052 1053 if util.LenTrim(subscriptionArn) <= 0 { 1054 err = errors.New("Unsubscribe Failed: " + "Subscription ARN is Required") 1055 return err 1056 } 1057 1058 // create input object 1059 input := &sns.UnsubscribeInput{ 1060 SubscriptionArn: aws.String(subscriptionArn), 1061 } 1062 1063 // perform action 1064 if len(timeOutDuration) > 0 { 1065 ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0]) 1066 defer cancel() 1067 1068 _, err = s.snsClient.UnsubscribeWithContext(ctx, input) 1069 } else { 1070 if segCtxSet { 1071 _, err = s.snsClient.UnsubscribeWithContext(segCtx, input) 1072 } else { 1073 _, err = s.snsClient.Unsubscribe(input) 1074 } 1075 } 1076 1077 // evaluate result 1078 if err != nil { 1079 err = errors.New("Unsubscribe Failed: (Unsubscribe Action) " + err.Error()) 1080 return err 1081 } else { 1082 return nil 1083 } 1084 } 1085 1086 // ConfirmSubscription will confirm a pending subscription upon receive of SNS notification for subscription confirmation, 1087 // the SNS subscription confirmation will contain a Token which is needed by ConfirmSubscription as input parameter in order to confirm, 1088 // 1089 // Parameters: 1090 // 1. topicArn = required, the topic in SNS to confirm subscription for 1091 // 2. token = required, the token from SNS confirmation notification receive upon call to Subscribe 1092 // 3. timeOutDuration = optional, indicates timeout value for context 1093 // 1094 // Return Values: 1095 // 1. subscriptionArn = upon confirmation, the subscription ARN attained 1096 // 2. err = the error info if any 1097 // 1098 // Subscription Confirmation Support: 1099 // 1. Http / Https / Email Endpoints Requires Subscription Confirmation Support, See Details in URL Below: 1100 // a) https://docs.aws.amazon.com/sns/latest/dg/sns-http-https-endpoint-as-subscriber.html 1101 // 2. Once Subscribe action is performed, SNS sends confirmation notification to the HTTP/s Endpoint: 1102 // b) Client Upon Receipt of the SNS Notification, Retrieve Token and Respond via ConfirmSubscription method 1103 func (s *SNS) ConfirmSubscription(topicArn string, token string, timeOutDuration ...time.Duration) (subscriptionArn string, err error) { 1104 segCtx := context.Background() 1105 segCtxSet := false 1106 1107 seg := xray.NewSegmentNullable("SNS-ConfirmSubscription", s._parentSegment) 1108 1109 if seg != nil { 1110 segCtx = seg.Ctx 1111 segCtxSet = true 1112 1113 defer seg.Close() 1114 defer func() { 1115 _ = seg.Seg.AddMetadata("SNS-ConfirmSubscription-TopicArn", topicArn) 1116 _ = seg.Seg.AddMetadata("SNS-ConfirmSubscription-Token", token) 1117 _ = seg.Seg.AddMetadata("SNS-ConfirmSubscription-Result-SubscriptionArn", subscriptionArn) 1118 1119 if err != nil { 1120 _ = seg.Seg.AddError(err) 1121 } 1122 }() 1123 } 1124 1125 // validation 1126 if s.snsClient == nil { 1127 err = errors.New("ConfirmSubscription Failed: " + "SNS Client is Required") 1128 return "", err 1129 } 1130 1131 if util.LenTrim(topicArn) <= 0 { 1132 err = errors.New("ConfirmSubscription Failed: " + "Topic ARN is Required") 1133 return "", err 1134 } 1135 1136 if util.LenTrim(token) <= 0 { 1137 err = errors.New("ConfirmSubscription Failed: " + "Token is Required (From Subscribe Action's SNS Confirmation Notification)") 1138 return "", err 1139 } 1140 1141 // create input object 1142 input := &sns.ConfirmSubscriptionInput{ 1143 TopicArn: aws.String(topicArn), 1144 Token: aws.String(token), 1145 } 1146 1147 // perform action 1148 var output *sns.ConfirmSubscriptionOutput 1149 1150 if len(timeOutDuration) > 0 { 1151 ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0]) 1152 defer cancel() 1153 1154 output, err = s.snsClient.ConfirmSubscriptionWithContext(ctx, input) 1155 } else { 1156 if segCtxSet { 1157 output, err = s.snsClient.ConfirmSubscriptionWithContext(segCtx, input) 1158 } else { 1159 output, err = s.snsClient.ConfirmSubscription(input) 1160 } 1161 } 1162 1163 // evaluate result 1164 if err != nil { 1165 err = errors.New("ConfirmSubscription Failed: (ConfirmSubscription Action) " + err.Error()) 1166 return "", err 1167 } 1168 1169 subscriptionArn = *output.SubscriptionArn 1170 return subscriptionArn, nil 1171 } 1172 1173 // ListSubscriptions will list SNS subscriptions, with optional nextToken for retrieving more list from a prior call 1174 // 1175 // Parameters: 1176 // 1. nextToken = optional, if prior call returned more...token, pass in here to retrieve the related list 1177 // 2. timeOutDuration = optional, indicates timeout value for context 1178 // 1179 // Return Values: 1180 // 1. subscriptionsList = *SubscribedTopic slice containing subscriptions along with its related topic, nil if not set 1181 // 2. moreSubscriptionsNextToken = if there are more subscriptions, this token is filled, to query more, use the token as input parameter, blank if no more 1182 // 3. err = error info if any 1183 func (s *SNS) ListSubscriptions(nextToken string, timeOutDuration ...time.Duration) (subscriptionsList []*SubscribedTopic, moreSubscriptionsNextToken string, err error) { 1184 segCtx := context.Background() 1185 segCtxSet := false 1186 1187 seg := xray.NewSegmentNullable("SNS-ListSubscriptions", s._parentSegment) 1188 1189 if seg != nil { 1190 segCtx = seg.Ctx 1191 segCtxSet = true 1192 1193 defer seg.Close() 1194 defer func() { 1195 _ = seg.Seg.AddMetadata("SNS-ListSubscriptions-NextToken", nextToken) 1196 _ = seg.Seg.AddMetadata("SNS-ListSubscriptions-Result-SubscriptionsList", subscriptionsList) 1197 _ = seg.Seg.AddMetadata("SNS-ListSubscriptions-Result-NextToken", moreSubscriptionsNextToken) 1198 1199 if err != nil { 1200 _ = seg.Seg.AddError(err) 1201 } 1202 }() 1203 } 1204 1205 // validation 1206 if s.snsClient == nil { 1207 err = errors.New("ListSubscriptions Failed: " + "SNS Client is Required") 1208 return nil, "", err 1209 } 1210 1211 // create input object 1212 input := &sns.ListSubscriptionsInput{} 1213 1214 if util.LenTrim(nextToken) > 0 { 1215 input.NextToken = aws.String(nextToken) 1216 } 1217 1218 // perform action 1219 var output *sns.ListSubscriptionsOutput 1220 1221 if len(timeOutDuration) > 0 { 1222 ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0]) 1223 defer cancel() 1224 1225 output, err = s.snsClient.ListSubscriptionsWithContext(ctx, input) 1226 } else { 1227 if segCtxSet { 1228 output, err = s.snsClient.ListSubscriptionsWithContext(segCtx, input) 1229 } else { 1230 output, err = s.snsClient.ListSubscriptions(input) 1231 } 1232 } 1233 1234 // evaluate result 1235 if err != nil { 1236 err = errors.New("ListSubscriptions Failed: (List Action) " + err.Error()) 1237 return nil, "", err 1238 } 1239 1240 moreSubscriptionsNextToken = aws.StringValue(output.NextToken) 1241 1242 if len(output.Subscriptions) > 0 { 1243 var conv snsprotocol.SNSProtocol 1244 1245 for _, v := range output.Subscriptions { 1246 if p, e := conv.ParseByKey(aws.StringValue(v.Protocol)); e == nil { 1247 subscriptionsList = append(subscriptionsList, &SubscribedTopic{ 1248 SubscriptionArn: aws.StringValue(v.SubscriptionArn), 1249 TopicArn: aws.StringValue(v.TopicArn), 1250 Endpoint: aws.StringValue(v.Endpoint), 1251 Owner: aws.StringValue(v.Owner), 1252 Protocol: p, 1253 }) 1254 } 1255 } 1256 } 1257 1258 return subscriptionsList, moreSubscriptionsNextToken, nil 1259 } 1260 1261 // ListSubscriptionsByTopic will list SNS subscriptions by a specific topic via topicArn, 1262 // with optional nextToken for retrieving more list from a prior call 1263 // 1264 // Parameters: 1265 // 1. topicArn = required, list subscriptions based on this topic ARN 1266 // 2. nextToken = optional, if prior call returned more...token, pass in here to retrieve the related list 1267 // 3. timeOutDuration = optional, indicates timeout value for context 1268 // 1269 // Return Values: 1270 // 1. subscriptionsList = *SubscribedTopic slice containing subscriptions along with its related topic, nil if not set 1271 // 2. moreSubscriptionsNextToken = if there are more subscriptions, this token is filled, to query more, use the token as input parameter, blank if no more 1272 // 3. err = error info if any 1273 func (s *SNS) ListSubscriptionsByTopic(topicArn string, nextToken string, timeOutDuration ...time.Duration) (subscriptionsList []*SubscribedTopic, moreSubscriptionsNextToken string, err error) { 1274 segCtx := context.Background() 1275 segCtxSet := false 1276 1277 seg := xray.NewSegmentNullable("SNS-ListSubscriptionsByTopic", s._parentSegment) 1278 1279 if seg != nil { 1280 segCtx = seg.Ctx 1281 segCtxSet = true 1282 1283 defer seg.Close() 1284 defer func() { 1285 _ = seg.Seg.AddMetadata("SNS-ListSubscriptionsByTopic-TopicArn", topicArn) 1286 _ = seg.Seg.AddMetadata("SNS-ListSubscriptionsByTopic-NextToken", nextToken) 1287 _ = seg.Seg.AddMetadata("SNS-ListSubscriptionsByTopic-Result-SubscriptionsList", subscriptionsList) 1288 _ = seg.Seg.AddMetadata("SNS-ListSubscriptionsByTopic-Result-NextToken", moreSubscriptionsNextToken) 1289 1290 if err != nil { 1291 _ = seg.Seg.AddError(err) 1292 } 1293 }() 1294 } 1295 1296 // validation 1297 if s.snsClient == nil { 1298 err = errors.New("ListSubscriptionsByTopic Failed: " + "SNS Client is Required") 1299 return nil, "", err 1300 } 1301 1302 if util.LenTrim(topicArn) <= 0 { 1303 err = errors.New("ListSubscriptionsByTopic Failed: " + "Topic ARN is Required") 1304 return nil, "", err 1305 } 1306 1307 // create input object 1308 input := &sns.ListSubscriptionsByTopicInput{ 1309 TopicArn: aws.String(topicArn), 1310 } 1311 1312 if util.LenTrim(nextToken) > 0 { 1313 input.NextToken = aws.String(nextToken) 1314 } 1315 1316 // perform action 1317 var output *sns.ListSubscriptionsByTopicOutput 1318 1319 if len(timeOutDuration) > 0 { 1320 ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0]) 1321 defer cancel() 1322 1323 output, err = s.snsClient.ListSubscriptionsByTopicWithContext(ctx, input) 1324 } else { 1325 if segCtxSet { 1326 output, err = s.snsClient.ListSubscriptionsByTopicWithContext(segCtx, input) 1327 } else { 1328 output, err = s.snsClient.ListSubscriptionsByTopic(input) 1329 } 1330 } 1331 1332 // evaluate result 1333 if err != nil { 1334 err = errors.New("ListSubscriptionsByTopic Failed: (List Action) " + err.Error()) 1335 return nil, "", err 1336 } 1337 1338 moreSubscriptionsNextToken = aws.StringValue(output.NextToken) 1339 1340 if len(output.Subscriptions) > 0 { 1341 var conv snsprotocol.SNSProtocol 1342 1343 for _, v := range output.Subscriptions { 1344 if p, e := conv.ParseByKey(aws.StringValue(v.Protocol)); e == nil { 1345 subscriptionsList = append(subscriptionsList, &SubscribedTopic{ 1346 SubscriptionArn: aws.StringValue(v.SubscriptionArn), 1347 TopicArn: aws.StringValue(v.TopicArn), 1348 Endpoint: aws.StringValue(v.Endpoint), 1349 Owner: aws.StringValue(v.Owner), 1350 Protocol: p, 1351 }) 1352 } 1353 } 1354 } 1355 1356 return subscriptionsList, moreSubscriptionsNextToken, nil 1357 } 1358 1359 // GetSubscriptionAttributes will retrieve all subscription attributes for a specific subscription based on subscriptionArn 1360 // 1361 // Parameters: 1362 // 1. subscriptionArn = required, the subscriptionArn for which attributes are retrieved from 1363 // 2. timeOutDuration = optional, indicates timeout value for context 1364 // 1365 // Return Values: 1366 // 1. attributes = map of sns get subscription attributes in key value pairs 1367 // 2. err = error info if any 1368 // 1369 // Subscription Attributes: (Key = Expected Value) 1370 // 1. ConfirmationWasAuthenticated = true if the subscription confirmation request was authenticated 1371 // 2. DeliveryPolicy = The JSON serialization of the subscription's delivery policy (See Subscribe Notes) 1372 // 3. EffectiveDeliveryPolicy = The JSON serialization of the effective delivery policy that takes into account the topic delivery policy, 1373 // and account system defaults (See Subscribe Notes for DeliveryPolicy Json format) 1374 // 4. FilterPolicy = The filter policy JSON that is assigned to the subscription (See Subscribe Notes) 1375 // 5. Owner = The AWS account ID of the subscription's owner 1376 // 6. PendingConfirmation = true if the subscription hasn't been confirmed, 1377 // To confirm a pending subscription, call the ConfirmSubscription action with a confirmation token 1378 // 7. RawMessageDelivery = true if raw message delivery is enabled for the subscription. 1379 // Raw messages are free of JSON formatting and can be sent to HTTP/S and Amazon SQS endpoints 1380 // 8. RedrivePolicy = When specified, sends undeliverable messages to the specified Amazon SQS dead-letter queue. 1381 // Messages that can't be delivered due to client errors (for example, when the subscribed endpoint is unreachable), 1382 // or server errors (for example, when the service that powers the subscribed endpoint becomes unavailable) 1383 // are held in the dead-letter queue for further analysis or reprocessing (See Subscribe Notes) 1384 // 9. SubscriptionArn = The subscription's ARN 1385 // 10. TopicArn = The topic ARN that the subscription is associated with 1386 func (s *SNS) GetSubscriptionAttributes(subscriptionArn string, timeOutDuration ...time.Duration) (attributes map[snsgetsubscriptionattribute.SNSGetSubscriptionAttribute]string, err error) { 1387 segCtx := context.Background() 1388 segCtxSet := false 1389 1390 seg := xray.NewSegmentNullable("SNS-GetSubscriptionAttributes", s._parentSegment) 1391 1392 if seg != nil { 1393 segCtx = seg.Ctx 1394 segCtxSet = true 1395 1396 defer seg.Close() 1397 defer func() { 1398 _ = seg.Seg.AddMetadata("SNS-GetSubscriptionAttributes-SubscriptionArn", subscriptionArn) 1399 _ = seg.Seg.AddMetadata("SNS-GetSubscriptionAttributes-Result-Attributes", attributes) 1400 1401 if err != nil { 1402 _ = seg.Seg.AddError(err) 1403 } 1404 }() 1405 } 1406 1407 // validation 1408 if s.snsClient == nil { 1409 err = errors.New("GetSubscriptionAttributes Failed: " + "SNS Client is Required") 1410 return nil, err 1411 } 1412 1413 if util.LenTrim(subscriptionArn) <= 0 { 1414 err = errors.New("GetSubscriptionAttributes Failed: " + "Subscription ARN is Required") 1415 return nil, err 1416 } 1417 1418 // create input object 1419 input := &sns.GetSubscriptionAttributesInput{ 1420 SubscriptionArn: aws.String(subscriptionArn), 1421 } 1422 1423 // perform action 1424 var output *sns.GetSubscriptionAttributesOutput 1425 1426 if len(timeOutDuration) > 0 { 1427 ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0]) 1428 defer cancel() 1429 1430 output, err = s.snsClient.GetSubscriptionAttributesWithContext(ctx, input) 1431 } else { 1432 if segCtxSet { 1433 output, err = s.snsClient.GetSubscriptionAttributesWithContext(segCtx, input) 1434 } else { 1435 output, err = s.snsClient.GetSubscriptionAttributes(input) 1436 } 1437 } 1438 1439 // evaluate result 1440 if err != nil { 1441 err = errors.New("GetSubscriptionAttributes Failed: (Get Action) " + err.Error()) 1442 return nil, err 1443 } 1444 1445 attributes = s.fromAwsGetSubscriptionAttributes(output.Attributes) 1446 return attributes, nil 1447 } 1448 1449 // SetSubscriptionAttribute will set or update a subscription attribute, 1450 // For attribute value or Json format, see corresponding notes in Subscribe where applicable 1451 func (s *SNS) SetSubscriptionAttribute(subscriptionArn string, 1452 attributeName snssubscribeattribute.SNSSubscribeAttribute, 1453 attributeValue string, 1454 timeOutDuration ...time.Duration) (err error) { 1455 segCtx := context.Background() 1456 segCtxSet := false 1457 1458 seg := xray.NewSegmentNullable("SNS-SetSubscriptionAttribute", s._parentSegment) 1459 1460 if seg != nil { 1461 segCtx = seg.Ctx 1462 segCtxSet = true 1463 1464 defer seg.Close() 1465 defer func() { 1466 _ = seg.Seg.AddMetadata("SNS-SetSubscriptionAttribute-SubscriptionArn", subscriptionArn) 1467 _ = seg.Seg.AddMetadata("SNS-SetSubscriptionAttribute-AttributeName", attributeName) 1468 _ = seg.Seg.AddMetadata("SNS-SetSubscriptionAttribute-AttributeValue", attributeValue) 1469 1470 if err != nil { 1471 _ = seg.Seg.AddError(err) 1472 } 1473 }() 1474 } 1475 1476 // validation 1477 if s.snsClient == nil { 1478 err = errors.New("SetSubscriptionAttribute Failed: " + "SNS Client is Required") 1479 return err 1480 } 1481 1482 if util.LenTrim(subscriptionArn) <= 0 { 1483 err = errors.New("SetSubscriptionAttribute Failed: " + "Subscription ARN is Required") 1484 return err 1485 } 1486 1487 if !attributeName.Valid() || attributeName == snssubscribeattribute.UNKNOWN { 1488 err = errors.New("SetSubscriptionAttribute Failed: " + "Attribute Name is Required") 1489 return err 1490 } 1491 1492 // create input object 1493 input := &sns.SetSubscriptionAttributesInput{ 1494 SubscriptionArn: aws.String(subscriptionArn), 1495 AttributeName: aws.String(attributeName.Key()), 1496 AttributeValue: aws.String(attributeValue), 1497 } 1498 1499 // perform action 1500 if len(timeOutDuration) > 0 { 1501 ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0]) 1502 defer cancel() 1503 1504 _, err = s.snsClient.SetSubscriptionAttributesWithContext(ctx, input) 1505 } else { 1506 if segCtxSet { 1507 _, err = s.snsClient.SetSubscriptionAttributesWithContext(segCtx, input) 1508 } else { 1509 _, err = s.snsClient.SetSubscriptionAttributes(input) 1510 } 1511 } 1512 1513 // evaluate result 1514 if err != nil { 1515 err = errors.New("SetSubscriptionAttribute Failed: (Set Action) " + err.Error()) 1516 return err 1517 } else { 1518 return nil 1519 } 1520 } 1521 1522 // ---------------------------------------------------------------------------------------------------------------- 1523 // publisher methods 1524 // ---------------------------------------------------------------------------------------------------------------- 1525 1526 // Publish will publish a message to a topic or target via topicArn or targetArn respectively, 1527 // upon publish completed, the messageId is returned 1528 // 1529 // Parameters: 1530 // 1. topicArn = required but mutually exclusive, either topicArn or targetArn must be set (but NOT BOTH) 1531 // 2. targetArn = required but mutually exclusive, either topicArn or targetArn must be set (but NOT BOTH) 1532 // 3. message = required, the message to publish, up to 256KB 1533 // 4. subject = optional, only for email endpoints, up to 100 characters 1534 // 5. attributes = optional, message attributes 1535 // a) Other than defining Endpoint attributes as indicated in note below, 1536 // b) attributes can also contain Message specific attributes for use for Subscriber Filter Policy and etc, 1537 // *) For example, custom attribute name and value for the message can be defined in this map as metadata, 1538 // so that when Subscriber receives it can apply filter policy etc (See Subscribe method Filter Policy for more info) 1539 // i.e attributes["customer_interests"] = "rugby" 1540 // i.e attributes["price_usd"] = 100 1541 // 6. timeOutDuration = optional, indicates timeout value for context 1542 // 1543 // Message Attribute Keys: 1544 // 1. ADM 1545 // a) AWS.SNS.MOBILE.ADM.TTL 1546 // 2. APNs 1547 // a) AWS.SNS.MOBILE.APNS_MDM.TTL 1548 // b) AWS.SNS.MOBILE.APNS_MDM_SANDBOX.TTL 1549 // c) AWS.SNS.MOBILE.APNS_PASSBOOK.TTL 1550 // d) AWS.SNS.MOBILE.APNS_PASSBOOK_SANDBOX.TTL 1551 // e) AWS.SNS.MOBILE.APNS_SANDBOX.TTL 1552 // f) AWS.SNS.MOBILE.APNS_VOIP.TTL 1553 // g) AWS.SNS.MOBILE.APNS_VOIP_SANDBOX.TTL 1554 // h) AWS.SNS.MOBILE.APNS.COLLAPSE_ID 1555 // i) AWS.SNS.MOBILE.APNS.PRIORITY 1556 // j) AWS.SNS.MOBILE.APNS.PUSH_TYPE 1557 // k) AWS.SNS.MOBILE.APNS.TOPIC 1558 // l) AWS.SNS.MOBILE.APNS.TTL 1559 // m) AWS.SNS.MOBILE.PREFERRED_AUTHENTICATION_METHOD 1560 // 3. Custom Message Attribute Key Value Pairs 1561 // a) For Use Against Subscriber Filter Policy Matching 1562 func (s *SNS) Publish(topicArn string, 1563 targetArn string, 1564 message string, 1565 subject string, 1566 attributes map[string]*sns.MessageAttributeValue, 1567 timeOutDuration ...time.Duration) (messageId string, err error) { 1568 segCtx := context.Background() 1569 segCtxSet := false 1570 1571 seg := xray.NewSegmentNullable("SNS-Publish", s._parentSegment) 1572 1573 if seg != nil { 1574 segCtx = seg.Ctx 1575 segCtxSet = true 1576 1577 defer seg.Close() 1578 defer func() { 1579 _ = seg.Seg.AddMetadata("SNS-Publish-TopicArn", topicArn) 1580 _ = seg.Seg.AddMetadata("SNS-Publish-TargetArn", targetArn) 1581 _ = seg.Seg.AddMetadata("SNS-Publish-Message", message) 1582 _ = seg.Seg.AddMetadata("SNS-Publish-Subject", subject) 1583 _ = seg.Seg.AddMetadata("SNS-Publish-Attributes", attributes) 1584 _ = seg.Seg.AddMetadata("SNS-Publish-Result-MessageID", messageId) 1585 1586 if err != nil { 1587 _ = seg.Seg.AddError(err) 1588 } 1589 }() 1590 } 1591 1592 // validation 1593 if s.snsClient == nil { 1594 err = errors.New("Publish Failed: " + "SNS Client is Required") 1595 return "", err 1596 } 1597 1598 if util.LenTrim(topicArn) <= 0 && util.LenTrim(targetArn) <= 0 { 1599 err = errors.New("Publish Failed: " + "Either Topic ARN or Target ARN is Required") 1600 return "", err 1601 } 1602 1603 if util.LenTrim(message) <= 0 { 1604 err = errors.New("Publish Failed: " + "Message is Required") 1605 return "", err 1606 } 1607 1608 if len(subject) > 0 { 1609 if util.LenTrim(subject) > 100 { 1610 err = errors.New("Publish Failed: " + "Subject Maximum Characters is 100") 1611 return "", err 1612 } 1613 } 1614 1615 // create input object 1616 input := &sns.PublishInput{ 1617 Message: aws.String(message), 1618 } 1619 1620 if util.LenTrim(topicArn) > 0 { 1621 input.TopicArn = aws.String(topicArn) 1622 } 1623 1624 if util.LenTrim(targetArn) > 0 { 1625 input.TargetArn = aws.String(targetArn) 1626 } 1627 1628 if util.LenTrim(subject) > 0 { 1629 input.Subject = aws.String(subject) 1630 } 1631 1632 if attributes != nil { 1633 input.MessageAttributes = attributes 1634 } 1635 1636 // perform action 1637 var output *sns.PublishOutput 1638 1639 if len(timeOutDuration) > 0 { 1640 ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0]) 1641 defer cancel() 1642 1643 output, err = s.snsClient.PublishWithContext(ctx, input) 1644 } else { 1645 if segCtxSet { 1646 output, err = s.snsClient.PublishWithContext(segCtx, input) 1647 } else { 1648 output, err = s.snsClient.Publish(input) 1649 } 1650 } 1651 1652 // evaluate result 1653 if err != nil { 1654 err = errors.New("Publish Failed: (Publish Action) " + err.Error()) 1655 return "", err 1656 } else { 1657 messageId = *output.MessageId 1658 return messageId, nil 1659 } 1660 } 1661 1662 // ---------------------------------------------------------------------------------------------------------------- 1663 // sms methods 1664 // ---------------------------------------------------------------------------------------------------------------- 1665 1666 // SendSMS will send a message to a specific SMS phone number, where phone number is in E.164 format (+12095551212 for example where +1 is country code), 1667 // upon sms successfully sent, the messageId is returned 1668 // 1669 // Parameters: 1670 // 1. phoneNumber = required, phone number to deliver an SMS message. Use E.164 format (+12095551212 where +1 is country code) 1671 // 2. message = required, the message to publish; max is 140 ascii characters (70 characters when in UCS-2 encoding) 1672 // 3. timeOutDuration = optional, indicates timeout value for context 1673 // 1674 // Fixed Message Attributes Explained: 1675 // 1. AWS.SNS.SMS.SenderID = A custom ID that contains 3-11 alphanumeric characters, including at least one letter and no spaces. 1676 // The sender ID is displayed as the message sender on the receiving device. 1677 // For example, you can use your business brand to make the message source easier to recognize. 1678 // Support for sender IDs varies by country and/or region. 1679 // For example, messages delivered to U.S. phone numbers will not display the sender ID. 1680 // For the countries and regions that support sender IDs, see Supported Regions and countries. 1681 // If you do not specify a sender ID, the message will display a long code as the sender ID in supported countries and regions. 1682 // For countries or regions that require an alphabetic sender ID, the message displays NOTICE as the sender ID. 1683 // This message-level attribute overrides the account-level attribute DefaultSenderID, which you set using the SetSMSAttributes request. 1684 // 2. AWS.SNS.SMS.SMSType = The type of message that you are sending: 1685 // a) Promotional = (default) – Noncritical messages, such as marketing messages. 1686 // Amazon SNS optimizes the message delivery to incur the lowest cost. 1687 // b) Transactional = Critical messages that support customer transactions, 1688 // such as one-time passcodes for multi-factor authentication. 1689 // Amazon SNS optimizes the message delivery to achieve the highest reliability. 1690 // This message-level attribute overrides the account-level attribute DefaultSMSType, 1691 // which you set using the SetSMSAttributes request. 1692 func (s *SNS) SendSMS(phoneNumber string, 1693 message string, 1694 timeOutDuration ...time.Duration) (messageId string, err error) { 1695 segCtx := context.Background() 1696 segCtxSet := false 1697 1698 seg := xray.NewSegmentNullable("SNS-SendSMS", s._parentSegment) 1699 1700 if seg != nil { 1701 segCtx = seg.Ctx 1702 segCtxSet = true 1703 1704 defer seg.Close() 1705 defer func() { 1706 _ = seg.Seg.AddMetadata("SNS-SendSMS-Phone", phoneNumber) 1707 _ = seg.Seg.AddMetadata("SNS-SendSMS-Message", message) 1708 _ = seg.Seg.AddMetadata("SNS-SendSMS-Result-MessageID", messageId) 1709 1710 if err != nil { 1711 _ = seg.Seg.AddError(err) 1712 } 1713 }() 1714 } 1715 1716 // validation 1717 if s.snsClient == nil { 1718 err = errors.New("SendSMS Failed: " + "SNS Client is Required") 1719 return "", err 1720 } 1721 1722 if util.LenTrim(phoneNumber) <= 0 { 1723 err = errors.New("SendSMS Failed: " + "SMS Phone Number is Required") 1724 return "", err 1725 } 1726 1727 if util.LenTrim(message) <= 0 { 1728 err = errors.New("SendSMS Failed: " + "Message is Required") 1729 return "", err 1730 } 1731 1732 if len(message) > 140 { 1733 err = errors.New("SendSMS Failed: " + "SMS Text Message Maximum Characters Limited to 140") 1734 return "", err 1735 } 1736 1737 // fixed attributes 1738 m := make(map[string]*sns.MessageAttributeValue) 1739 1740 if util.LenTrim(s.SMSSenderName) > 0 { 1741 m["AWS.SNS.SMS.SenderID"] = &sns.MessageAttributeValue{StringValue: aws.String(s.SMSSenderName), DataType: aws.String("String")} 1742 } 1743 1744 smsTypeName := "Promotional" 1745 1746 if s.SMSTransactional { 1747 smsTypeName = "Transactional" 1748 } 1749 1750 m["AWS.SNS.SMS.SMSType"] = &sns.MessageAttributeValue{StringValue: aws.String(smsTypeName), DataType: aws.String("String")} 1751 1752 // create input object 1753 input := &sns.PublishInput{ 1754 PhoneNumber: aws.String(phoneNumber), 1755 Message: aws.String(message), 1756 MessageAttributes: m, 1757 } 1758 1759 // perform action 1760 var output *sns.PublishOutput 1761 1762 if len(timeOutDuration) > 0 { 1763 ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0]) 1764 defer cancel() 1765 1766 output, err = s.snsClient.PublishWithContext(ctx, input) 1767 } else { 1768 if segCtxSet { 1769 output, err = s.snsClient.PublishWithContext(segCtx, input) 1770 } else { 1771 output, err = s.snsClient.Publish(input) 1772 } 1773 } 1774 1775 // evaluate result 1776 if err != nil { 1777 err = errors.New("SendSMS Failed: (SMS Send Action) " + err.Error()) 1778 return "", err 1779 } else { 1780 messageId = *output.MessageId 1781 return messageId, nil 1782 } 1783 } 1784 1785 // OptInPhoneNumber will opt in a SMS phone number to SNS for receiving messages (explict allow), 1786 // returns nil if successful, otherwise error info is returned 1787 // 1788 // Parameters: 1789 // 1. phoneNumber = required, phone number to opt in. Use E.164 format (+12095551212 where +1 is country code) 1790 // 2. timeOutDuration = optional, indicates timeout value for context 1791 func (s *SNS) OptInPhoneNumber(phoneNumber string, timeOutDuration ...time.Duration) (err error) { 1792 segCtx := context.Background() 1793 segCtxSet := false 1794 1795 seg := xray.NewSegmentNullable("SNS-OptInPhoneNumber", s._parentSegment) 1796 1797 if seg != nil { 1798 segCtx = seg.Ctx 1799 segCtxSet = true 1800 1801 defer seg.Close() 1802 defer func() { 1803 _ = seg.Seg.AddMetadata("SNS-OptInPhoneNumber-Phone", phoneNumber) 1804 1805 if err != nil { 1806 _ = seg.Seg.AddError(err) 1807 } 1808 }() 1809 } 1810 1811 // validation 1812 if s.snsClient == nil { 1813 err = errors.New("OptInPhoneNumber Failed: " + "SNS Client is Required") 1814 return err 1815 } 1816 1817 if util.LenTrim(phoneNumber) <= 0 { 1818 err = errors.New("OptInPhoneNumber Failed: " + "Phone Number is Required, in E.164 Format (i.e. +12095551212)") 1819 return err 1820 } 1821 1822 // create input object 1823 input := &sns.OptInPhoneNumberInput{ 1824 PhoneNumber: aws.String(phoneNumber), 1825 } 1826 1827 // perform action 1828 if len(timeOutDuration) > 0 { 1829 ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0]) 1830 defer cancel() 1831 1832 _, err = s.snsClient.OptInPhoneNumberWithContext(ctx, input) 1833 } else { 1834 if segCtxSet { 1835 _, err = s.snsClient.OptInPhoneNumberWithContext(segCtx, input) 1836 } else { 1837 _, err = s.snsClient.OptInPhoneNumber(input) 1838 } 1839 } 1840 1841 // evaluate result 1842 if err != nil { 1843 err = errors.New("OptInPhoneNumber Failed: (Action) " + err.Error()) 1844 return err 1845 } else { 1846 return nil 1847 } 1848 } 1849 1850 // CheckIfPhoneNumberIsOptedOut will verify if a phone number is opted out of message reception 1851 // 1852 // Parameters: 1853 // 1. phoneNumber = required, phone number to check if opted out. Use E.164 format (+12095551212 where +1 is country code) 1854 // 2. timeOutDuration = optional, indicates timeout value for context 1855 // 1856 // Return Values: 1857 // 1. optedOut = bool indicating if the given phone via input parameter was opted out (true), or not (false) 1858 // 2. err = error info if any 1859 func (s *SNS) CheckIfPhoneNumberIsOptedOut(phoneNumber string, timeOutDuration ...time.Duration) (optedOut bool, err error) { 1860 segCtx := context.Background() 1861 segCtxSet := false 1862 1863 seg := xray.NewSegmentNullable("SNS-CheckIfPhoneNumberIsOptedOutParentSegment", s._parentSegment) 1864 1865 if seg != nil { 1866 segCtx = seg.Ctx 1867 segCtxSet = true 1868 1869 defer seg.Close() 1870 defer func() { 1871 _ = seg.Seg.AddMetadata("SNS-CheckIfPhoneNumberIsOptedOut-Phone", phoneNumber) 1872 _ = seg.Seg.AddMetadata("SNS-CheckIfPhoneNumberIsOptedOut-Result-OptedOut", optedOut) 1873 1874 if err != nil { 1875 _ = seg.Seg.AddError(err) 1876 } 1877 }() 1878 } 1879 1880 // validation 1881 if s.snsClient == nil { 1882 err = errors.New("CheckIfPhoneNumberIsOptedOut Failed: " + "SNS Client is Required") 1883 return false, err 1884 } 1885 1886 if util.LenTrim(phoneNumber) <= 0 { 1887 err = errors.New("CheckIfPhoneNumberIsOptedOut Failed: " + "Phone Number is Required, in E.164 Format (i.e. +12095551212)") 1888 return false, err 1889 } 1890 1891 // create input object 1892 input := &sns.CheckIfPhoneNumberIsOptedOutInput{ 1893 PhoneNumber: aws.String(phoneNumber), 1894 } 1895 1896 // perform action 1897 var output *sns.CheckIfPhoneNumberIsOptedOutOutput 1898 1899 if len(timeOutDuration) > 0 { 1900 ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0]) 1901 defer cancel() 1902 1903 output, err = s.snsClient.CheckIfPhoneNumberIsOptedOutWithContext(ctx, input) 1904 } else { 1905 if segCtxSet { 1906 output, err = s.snsClient.CheckIfPhoneNumberIsOptedOutWithContext(segCtx, input) 1907 } else { 1908 output, err = s.snsClient.CheckIfPhoneNumberIsOptedOut(input) 1909 } 1910 } 1911 1912 // evaluate result 1913 if err != nil { 1914 err = errors.New("CheckIfPhoneNumberIsOptedOut Failed: (Action) " + err.Error()) 1915 return false, err 1916 } else { 1917 optedOut = *output.IsOptedOut 1918 return optedOut, nil 1919 } 1920 } 1921 1922 // ListPhoneNumbersOptedOut will list opted out phone numbers, with optional nextToken for retrieving more list from a prior call 1923 // 1924 // Parameters: 1925 // 1. nextToken = optional, if prior call returned more...token, pass in here to retrieve the related list 1926 // 2. timeOutDuration = optional, indicates timeout value for context 1927 // 1928 // Return Values: 1929 // 1. phonesList = string slice of opted out phone numbers, nil if not set 1930 // 2. morePhonesNextToken = if there are more opted out phone numbers, this token is filled, to query more, use the token as input parameter, blank if no more 1931 // 3. err = error info if any 1932 func (s *SNS) ListPhoneNumbersOptedOut(nextToken string, timeOutDuration ...time.Duration) (phonesList []string, morePhonesNextToken string, err error) { 1933 segCtx := context.Background() 1934 segCtxSet := false 1935 1936 seg := xray.NewSegmentNullable("SNS-ListPhoneNumbersOptedOut", s._parentSegment) 1937 1938 if seg != nil { 1939 segCtx = seg.Ctx 1940 segCtxSet = true 1941 1942 defer seg.Close() 1943 defer func() { 1944 _ = seg.Seg.AddMetadata("SNS-ListPhoneNumbersOptedOut-NextToken", nextToken) 1945 _ = seg.Seg.AddMetadata("SNS-ListPhoneNumbersOptedOut-Result-PhonesList", phonesList) 1946 _ = seg.Seg.AddMetadata("SNS-ListPhoneNumbersOptedOut-Result-NextToken", morePhonesNextToken) 1947 1948 if err != nil { 1949 _ = seg.Seg.AddError(err) 1950 } 1951 }() 1952 } 1953 1954 // validation 1955 if s.snsClient == nil { 1956 err = errors.New("ListPhoneNumbersOptedOut Failed: " + "SNS Client is Required") 1957 return nil, "", err 1958 } 1959 1960 // create input object 1961 input := &sns.ListPhoneNumbersOptedOutInput{} 1962 1963 if util.LenTrim(nextToken) > 0 { 1964 input.NextToken = aws.String(nextToken) 1965 } 1966 1967 // perform action 1968 var output *sns.ListPhoneNumbersOptedOutOutput 1969 1970 if len(timeOutDuration) > 0 { 1971 ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0]) 1972 defer cancel() 1973 1974 output, err = s.snsClient.ListPhoneNumbersOptedOutWithContext(ctx, input) 1975 } else { 1976 if segCtxSet { 1977 output, err = s.snsClient.ListPhoneNumbersOptedOutWithContext(segCtx, input) 1978 } else { 1979 output, err = s.snsClient.ListPhoneNumbersOptedOut(input) 1980 } 1981 } 1982 1983 // evaluate result 1984 if err != nil { 1985 err = errors.New("ListPhoneNumbersOptedOut Failed: (Action) " + err.Error()) 1986 return nil, "", err 1987 } 1988 1989 morePhonesNextToken = aws.StringValue(output.NextToken) 1990 1991 phonesList = aws.StringValueSlice(output.PhoneNumbers) 1992 return phonesList, morePhonesNextToken, nil 1993 } 1994 1995 // ---------------------------------------------------------------------------------------------------------------- 1996 // application endpoint APNS (Apple Push Notification Service) / FCM (Firebase Cloud Messaging) methods 1997 // ---------------------------------------------------------------------------------------------------------------- 1998 1999 // CreatePlatformApplication will create a SNS platform application used for app notification via APNS, FCM, ADM etc. 2000 // this method creates the application so that then Endpoint (devices that receives) for this application may be created to complete the setup. 2001 // 2002 // Once the application and endpoint is created, then for a device to Subscribe to a topic and receive SNS notifications 2003 // via APNS, FCM, etc, the device will use the Subscribe's protocol as Application, and specify the Endpoint ARN accordingly. 2004 // 2005 // For the device to receive SNS notifications when provider Publish, the appropriate protocol specific setup is needed during 2006 // Endpoint creation, for example, APNS requires to set private key and SSL certificate in Application Attributes' PlatformCredential and PlatformPrincipal (See notes below) 2007 // 2008 // In general, first create the Application via CreatePlatformApplication, 2009 // Once application exists, then for each device that needs to receive SNS notification, create the appropriate Endpoint via CreatePlatformEndpoint 2010 // 2011 // Parameters: 2012 // 1. name = required, platform application name 2013 // 2. platform = required, the sns platform association with this application, such as APNS, FCM etc. 2014 // 3. attributes = required, map of platform application attributes that defines specific values related to the chosen platform (see notes below) 2015 // 4. timeOutDuration = optional, indicates timeout value for context 2016 // 2017 // Return Values: 2018 // 1. platformApplicationArn = the created platform application's ARN 2019 // 2. err = error info if any 2020 // 2021 // Platform Application Attributes: (Key = Expected Value) 2022 // 1. PlatformCredential = The credential received from the notification service, 2023 // For APNS and APNS_SANDBOX, PlatformCredential is the private key 2024 // For GCM (Firebase Cloud Messaging), PlatformCredential is API key 2025 // For ADM, PlatformCredential is client secret 2026 // 2. PlatformPrincipal = The principal received from the notification service, 2027 // For APNS and APNS_SANDBOX, PlatformPrincipal is SSL certificate 2028 // For GCM (Firebase Cloud Messaging), there is no PlatformPrincipal 2029 // For ADM, PlatformPrincipal is client id 2030 // 3. EventEndpointCreated = Topic ARN to which EndpointCreated event notifications are sent 2031 // 4. EventEndpointDeleted = Topic ARN to which EndpointDeleted event notifications are sent 2032 // 5. EventEndpointUpdated = Topic ARN to which EndpointUpdate event notifications are sent 2033 // 6. EventDeliveryFailure = Topic ARN to which DeliveryFailure event notifications are sent upon Direct Publish delivery failure (permanent) to one of the application's endpoints 2034 // 7. SuccessFeedbackRoleArn = IAM role ARN used to give Amazon SNS write access to use CloudWatch Logs on your behalf 2035 // 8. FailureFeedbackRoleArn = IAM role ARN used to give Amazon SNS write access to use CloudWatch Logs on your behalf 2036 // 9. SuccessFeedbackSampleRate = Sample rate percentage (0-100) of successfully delivered messages 2037 func (s *SNS) CreatePlatformApplication(name string, 2038 platform snsapplicationplatform.SNSApplicationPlatform, 2039 attributes map[snsplatformapplicationattribute.SNSPlatformApplicationAttribute]string, 2040 timeOutDuration ...time.Duration) (platformApplicationArn string, err error) { 2041 segCtx := context.Background() 2042 segCtxSet := false 2043 2044 seg := xray.NewSegmentNullable("SNS-CreatePlatformApplication", s._parentSegment) 2045 2046 if seg != nil { 2047 segCtx = seg.Ctx 2048 segCtxSet = true 2049 2050 defer seg.Close() 2051 defer func() { 2052 _ = seg.Seg.AddMetadata("SNS-CreatePlatformApplication-Name", name) 2053 _ = seg.Seg.AddMetadata("SNS-CreatePlatformApplication-Platform", platform) 2054 _ = seg.Seg.AddMetadata("SNS-CreatePlatformApplication-Attributes", attributes) 2055 _ = seg.Seg.AddMetadata("SNS-CreatePlatformApplication-Result-PlatformApplicationArn", platformApplicationArn) 2056 2057 if err != nil { 2058 _ = seg.Seg.AddError(err) 2059 } 2060 }() 2061 } 2062 2063 // validation 2064 if s.snsClient == nil { 2065 err = errors.New("CreatePlatformApplication Failed: " + "SNS Client is Required") 2066 return "", err 2067 } 2068 2069 if util.LenTrim(name) <= 0 { 2070 err = errors.New("CreatePlatformApplication Failed: " + "Name is Required") 2071 return "", err 2072 } 2073 2074 if !platform.Valid() || platform == snsapplicationplatform.UNKNOWN { 2075 err = errors.New("CreatePlatformApplication Failed: " + "Platform is Required") 2076 return "", err 2077 } 2078 2079 if attributes == nil { 2080 err = errors.New("CreatePlatformApplication Failed: " + "Attributes Map is Required") 2081 return "", err 2082 } 2083 2084 // create input object 2085 input := &sns.CreatePlatformApplicationInput{ 2086 Name: aws.String(name), 2087 Platform: aws.String(platform.Key()), 2088 Attributes: s.toAwsPlatformApplicationAttributes(attributes), 2089 } 2090 2091 // perform action 2092 var output *sns.CreatePlatformApplicationOutput 2093 2094 if len(timeOutDuration) > 0 { 2095 ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0]) 2096 defer cancel() 2097 2098 output, err = s.snsClient.CreatePlatformApplicationWithContext(ctx, input) 2099 } else { 2100 if segCtxSet { 2101 output, err = s.snsClient.CreatePlatformApplicationWithContext(segCtx, input) 2102 } else { 2103 output, err = s.snsClient.CreatePlatformApplication(input) 2104 } 2105 } 2106 2107 // evaluate result 2108 if err != nil { 2109 err = errors.New("CreatePlatformApplication Failed: (Create Action) " + err.Error()) 2110 return "", err 2111 } else { 2112 platformApplicationArn = *output.PlatformApplicationArn 2113 return platformApplicationArn, nil 2114 } 2115 } 2116 2117 // DeletePlatformApplication will delete a platform application by platformApplicationArn, 2118 // returns nil if successful, otherwise error info is returned 2119 // 2120 // Parameters: 2121 // 1. platformApplicationArn = the platform application to delete via platform application ARN specified 2122 // 2. timeOutDuration = optional, indicates timeout value for context 2123 func (s *SNS) DeletePlatformApplication(platformApplicationArn string, timeOutDuration ...time.Duration) (err error) { 2124 segCtx := context.Background() 2125 segCtxSet := false 2126 2127 seg := xray.NewSegmentNullable("SNS-DeletePlatformApplication", s._parentSegment) 2128 2129 if seg != nil { 2130 segCtx = seg.Ctx 2131 segCtxSet = true 2132 2133 defer seg.Close() 2134 defer func() { 2135 _ = seg.Seg.AddMetadata("SNS-DeletePlatformApplication-PlatformApplicationArn", platformApplicationArn) 2136 2137 if err != nil { 2138 _ = seg.Seg.AddError(err) 2139 } 2140 }() 2141 } 2142 2143 // validation 2144 if s.snsClient == nil { 2145 err = errors.New("DeletePlatformApplication Failed: " + "SNS Client is Required") 2146 return err 2147 } 2148 2149 if util.LenTrim(platformApplicationArn) <= 0 { 2150 err = errors.New("DeletePlatformApplication Failed: " + "Platform Application ARN is Required") 2151 return err 2152 } 2153 2154 // create input object 2155 input := &sns.DeletePlatformApplicationInput{ 2156 PlatformApplicationArn: aws.String(platformApplicationArn), 2157 } 2158 2159 // perform action 2160 if len(timeOutDuration) > 0 { 2161 ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0]) 2162 defer cancel() 2163 2164 _, err = s.snsClient.DeletePlatformApplicationWithContext(ctx, input) 2165 } else { 2166 if segCtxSet { 2167 _, err = s.snsClient.DeletePlatformApplicationWithContext(segCtx, input) 2168 } else { 2169 _, err = s.snsClient.DeletePlatformApplication(input) 2170 } 2171 } 2172 2173 // evaluate result 2174 if err != nil { 2175 err = errors.New("DeletePlatformApplication Failed: (Delete Action) " + err.Error()) 2176 return err 2177 } else { 2178 return nil 2179 } 2180 } 2181 2182 // ListPlatformApplications will list platform application ARNs, with optional nextToken for retrieving more list from a prior call 2183 // 2184 // Parameters: 2185 // 1. nextToken = optional, if prior call returned more...token, pass in here to retrieve the related list 2186 // 2. timeOutDuration = optional, indicates timeout value for context 2187 // 2188 // Return Values: 2189 // 1. platformApplicationArnsList = string slice of platform application ARNs, nil if not set 2190 // 2. moreAppArnsNextToken = if there are more platform application ARNs, this token is filled, to query more, use the token as input parameter, blank if no more 2191 // 3. err = error info if any 2192 func (s *SNS) ListPlatformApplications(nextToken string, timeOutDuration ...time.Duration) (platformApplicationArnsList []string, moreAppArnsNextToken string, err error) { 2193 segCtx := context.Background() 2194 segCtxSet := false 2195 2196 seg := xray.NewSegmentNullable("SNS-ListPlatformApplications", s._parentSegment) 2197 2198 if seg != nil { 2199 segCtx = seg.Ctx 2200 segCtxSet = true 2201 2202 defer seg.Close() 2203 defer func() { 2204 _ = seg.Seg.AddMetadata("SNS-ListPlatformApplications-NextToken", nextToken) 2205 _ = seg.Seg.AddMetadata("SNS-ListPlatformApplications-Result-PlatformApplicationArnsList", platformApplicationArnsList) 2206 _ = seg.Seg.AddMetadata("SNS-ListPlatformApplications-Result-NextToken", moreAppArnsNextToken) 2207 2208 if err != nil { 2209 _ = seg.Seg.AddError(err) 2210 } 2211 }() 2212 } 2213 2214 // validation 2215 if s.snsClient == nil { 2216 err = errors.New("ListPlatformApplications Failed: " + "SNS Client is Required") 2217 return nil, "", err 2218 } 2219 2220 // create input object 2221 input := &sns.ListPlatformApplicationsInput{} 2222 2223 if util.LenTrim(nextToken) > 0 { 2224 input.NextToken = aws.String(nextToken) 2225 } 2226 2227 // perform action 2228 var output *sns.ListPlatformApplicationsOutput 2229 2230 if len(timeOutDuration) > 0 { 2231 ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0]) 2232 defer cancel() 2233 2234 output, err = s.snsClient.ListPlatformApplicationsWithContext(ctx, input) 2235 } else { 2236 if segCtxSet { 2237 output, err = s.snsClient.ListPlatformApplicationsWithContext(segCtx, input) 2238 } else { 2239 output, err = s.snsClient.ListPlatformApplications(input) 2240 } 2241 } 2242 2243 // evaluate result 2244 if err != nil { 2245 err = errors.New("ListPlatformApplications Failed: (List Action) " + err.Error()) 2246 return nil, "", err 2247 } 2248 2249 moreAppArnsNextToken = aws.StringValue(output.NextToken) 2250 2251 for _, v := range output.PlatformApplications { 2252 if v != nil { 2253 if v1 := aws.StringValue(v.PlatformApplicationArn); util.LenTrim(v1) > 0 { 2254 platformApplicationArnsList = append(platformApplicationArnsList, v1) 2255 } 2256 } 2257 } 2258 2259 return platformApplicationArnsList, moreAppArnsNextToken, nil 2260 } 2261 2262 // GetPlatformApplicationAttributes will retrieve application attributes based on a specific platform application ARN 2263 // 2264 // Parameters: 2265 // 1. platformApplicationArn = required, the platform application ARN used to retrieve related application attributes 2266 // 2. timeOutDuration = optional, indicates timeout value for context 2267 // 2268 // Return Values: 2269 // 1. attributes = map of sns platform application attributes related to the given platform application ARN 2270 // 2. err = error info if any 2271 func (s *SNS) GetPlatformApplicationAttributes(platformApplicationArn string, timeOutDuration ...time.Duration) (attributes map[snsplatformapplicationattribute.SNSPlatformApplicationAttribute]string, err error) { 2272 segCtx := context.Background() 2273 segCtxSet := false 2274 2275 seg := xray.NewSegmentNullable("SNS-GetPlatformApplicationAttributes", s._parentSegment) 2276 2277 if seg != nil { 2278 segCtx = seg.Ctx 2279 segCtxSet = true 2280 2281 defer seg.Close() 2282 defer func() { 2283 _ = seg.Seg.AddMetadata("SNS-GetPlatformApplicationAttributes-PlatformApplicationArn", platformApplicationArn) 2284 _ = seg.Seg.AddMetadata("SNS-GetPlatformApplicationAttributes-Result-Attributes", attributes) 2285 2286 if err != nil { 2287 _ = seg.Seg.AddError(err) 2288 } 2289 }() 2290 } 2291 2292 // validation 2293 if s.snsClient == nil { 2294 err = errors.New("GetPlatformApplicationAttributes Failed: " + "SNS Client is Required") 2295 return nil, err 2296 } 2297 2298 if util.LenTrim(platformApplicationArn) <= 0 { 2299 err = errors.New("GetPlatformApplicationAttributes Failed: " + "Platform Application ARN is Required") 2300 return nil, err 2301 } 2302 2303 // create input object 2304 input := &sns.GetPlatformApplicationAttributesInput{ 2305 PlatformApplicationArn: aws.String(platformApplicationArn), 2306 } 2307 2308 // perform action 2309 var output *sns.GetPlatformApplicationAttributesOutput 2310 2311 if len(timeOutDuration) > 0 { 2312 ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0]) 2313 defer cancel() 2314 2315 output, err = s.snsClient.GetPlatformApplicationAttributesWithContext(ctx, input) 2316 } else { 2317 if segCtxSet { 2318 output, err = s.snsClient.GetPlatformApplicationAttributesWithContext(segCtx, input) 2319 } else { 2320 output, err = s.snsClient.GetPlatformApplicationAttributes(input) 2321 } 2322 } 2323 2324 // evaluate result 2325 if err != nil { 2326 err = errors.New("GetPlatformApplicationAttributes Failed: (Get Action) " + err.Error()) 2327 return nil, err 2328 } 2329 2330 attributes = s.fromAwsPlatformApplicationAttributes(output.Attributes) 2331 return attributes, nil 2332 } 2333 2334 // SetPlatformApplicationAttributes will set or update platform application attributes, 2335 // For attribute value or Json format, see corresponding notes in CreatePlatformApplication where applicable 2336 func (s *SNS) SetPlatformApplicationAttributes(platformApplicationArn string, 2337 attributes map[snsplatformapplicationattribute.SNSPlatformApplicationAttribute]string, 2338 timeOutDuration ...time.Duration) (err error) { 2339 segCtx := context.Background() 2340 segCtxSet := false 2341 2342 seg := xray.NewSegmentNullable("SNS-SetPlatformApplicationAttributes", s._parentSegment) 2343 2344 if seg != nil { 2345 segCtx = seg.Ctx 2346 segCtxSet = true 2347 2348 defer seg.Close() 2349 defer func() { 2350 _ = seg.Seg.AddMetadata("SNS-SetPlatformApplicationAttributes-PlatformApplicationArn", platformApplicationArn) 2351 _ = seg.Seg.AddMetadata("SNS-SetPlatformApplicationAttributes-Attributes", attributes) 2352 2353 if err != nil { 2354 _ = seg.Seg.AddError(err) 2355 } 2356 }() 2357 } 2358 2359 if s.snsClient == nil { 2360 err = errors.New("SetPlatformApplicationAttributes Failed: " + "SNS Client is Required") 2361 return err 2362 } 2363 2364 if util.LenTrim(platformApplicationArn) <= 0 { 2365 err = errors.New("SetPlatformApplicationAttributes Failed: " + "Platform Application ARN is Required") 2366 return err 2367 } 2368 2369 if attributes == nil { 2370 err = errors.New("SetPlatformApplicationAttributes Failed: " + "Attributes Map is Required") 2371 return err 2372 } 2373 2374 // create input 2375 input := &sns.SetPlatformApplicationAttributesInput{ 2376 PlatformApplicationArn: aws.String(platformApplicationArn), 2377 Attributes: s.toAwsPlatformApplicationAttributes(attributes), 2378 } 2379 2380 // perform action 2381 if len(timeOutDuration) > 0 { 2382 ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0]) 2383 defer cancel() 2384 2385 _, err = s.snsClient.SetPlatformApplicationAttributesWithContext(ctx, input) 2386 } else { 2387 if segCtxSet { 2388 _, err = s.snsClient.SetPlatformApplicationAttributesWithContext(segCtx, input) 2389 } else { 2390 _, err = s.snsClient.SetPlatformApplicationAttributes(input) 2391 } 2392 } 2393 2394 // evaluate result 2395 if err != nil { 2396 err = errors.New("SetPlatformApplicationAttributes Failed: (Set Action) " + err.Error()) 2397 return err 2398 } else { 2399 return nil 2400 } 2401 } 2402 2403 // CreatePlatformEndpoint will create a device endpoint for a specific platform application, 2404 // this is the endpoint that will receive SNS notifications via defined protocol such as APNS or FCM 2405 // 2406 // Parameters: 2407 // 1. platformApplicationArn = required, Plaform application ARN that was created, endpoint is added to this platform application 2408 // 2. token = Unique identifier created by the notification service for an app on a device, 2409 // The specific name for Token will vary, depending on which notification service is being used, 2410 // For example, when using APNS as the notification service, you need the device token, 2411 // Alternatively, when using FCM or ADM, the device token equivalent is called the registration ID 2412 // 3. customUserData = optional, Arbitrary user data to associate with the endpoint, 2413 // Amazon SNS does not use this data. The data must be in UTF-8 format and less than 2KB 2414 // 4. timeOutDuration = optional, indicates timeout value for context 2415 // 2416 // Return Values: 2417 // 1. endpointArn = the created endpoint ARN 2418 // 2. err = the error info if any 2419 func (s *SNS) CreatePlatformEndpoint(platformApplicationArn string, 2420 token string, 2421 customUserData string, 2422 timeOutDuration ...time.Duration) (endpointArn string, err error) { 2423 segCtx := context.Background() 2424 segCtxSet := false 2425 2426 seg := xray.NewSegmentNullable("SNS-CreatePlatformEndpoint", s._parentSegment) 2427 2428 if seg != nil { 2429 segCtx = seg.Ctx 2430 segCtxSet = true 2431 2432 defer seg.Close() 2433 defer func() { 2434 _ = seg.Seg.AddMetadata("SNS-CreatePlatformEndpoint-PlatformApplicationArn", platformApplicationArn) 2435 _ = seg.Seg.AddMetadata("SNS-CreatePlatformEndpoint-Token", token) 2436 _ = seg.Seg.AddMetadata("SNS-CreatePlatformEndpoint-CustomUserData", customUserData) 2437 _ = seg.Seg.AddMetadata("SNS-CreatePlatformEndpoint-Result-EndpointArn", endpointArn) 2438 2439 if err != nil { 2440 _ = seg.Seg.AddError(err) 2441 } 2442 }() 2443 } 2444 2445 // validation 2446 if s.snsClient == nil { 2447 err = errors.New("CreatePlatformEndpoint Failed: " + "SNS Client is Required") 2448 return "", err 2449 } 2450 2451 if util.LenTrim(platformApplicationArn) <= 0 { 2452 err = errors.New("CreatePlatformEndpoint Failed: " + "Platform Application ARN is Required") 2453 return "", err 2454 } 2455 2456 if util.LenTrim(token) <= 0 { 2457 err = errors.New("CreatePlatformEndpoint Failed: " + "Token is Required") 2458 return "", err 2459 } 2460 2461 // create input object 2462 input := &sns.CreatePlatformEndpointInput{ 2463 PlatformApplicationArn: aws.String(platformApplicationArn), 2464 Token: aws.String(token), 2465 } 2466 2467 if util.LenTrim(customUserData) > 0 { 2468 input.CustomUserData = aws.String(customUserData) 2469 } 2470 2471 // perform action 2472 var output *sns.CreatePlatformEndpointOutput 2473 2474 if len(timeOutDuration) > 0 { 2475 ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0]) 2476 defer cancel() 2477 2478 output, err = s.snsClient.CreatePlatformEndpointWithContext(ctx, input) 2479 } else { 2480 if segCtxSet { 2481 output, err = s.snsClient.CreatePlatformEndpointWithContext(segCtx, input) 2482 } else { 2483 output, err = s.snsClient.CreatePlatformEndpoint(input) 2484 } 2485 } 2486 2487 // evaluate result 2488 if err != nil { 2489 err = errors.New("CreatePlatformEndpoint Failed: (Create Action) " + err.Error()) 2490 return "", err 2491 } else { 2492 endpointArn = aws.StringValue(output.EndpointArn) 2493 return endpointArn, nil 2494 } 2495 } 2496 2497 // DeletePlatformEndpoint will delete an endpoint based on endpointArn, 2498 // returns nil if successful, otherwise error info is returned 2499 // 2500 // Parameters: 2501 // 1. endpointArn = required, the endpoint to delete 2502 // 2. timeOutDuration = optional, indicates timeout value for context 2503 func (s *SNS) DeletePlatformEndpoint(endpointArn string, timeOutDuration ...time.Duration) (err error) { 2504 segCtx := context.Background() 2505 segCtxSet := false 2506 2507 seg := xray.NewSegmentNullable("SNS-DeletePlatformEndpoint", s._parentSegment) 2508 2509 if seg != nil { 2510 segCtx = seg.Ctx 2511 segCtxSet = true 2512 2513 defer seg.Close() 2514 defer func() { 2515 _ = seg.Seg.AddMetadata("SNS-DeletePlatformEndpoint-EndpointArn", endpointArn) 2516 2517 if err != nil { 2518 _ = seg.Seg.AddError(err) 2519 } 2520 }() 2521 } 2522 2523 // validation 2524 if s.snsClient == nil { 2525 err = errors.New("DeletePlatformEndpoint Failed: " + "SNS Client is Required") 2526 return err 2527 } 2528 2529 if util.LenTrim(endpointArn) <= 0 { 2530 err = errors.New("DeletePlatformEndpoint Failed: " + "Endpoint ARN is Required") 2531 return err 2532 } 2533 2534 // create input object 2535 input := &sns.DeleteEndpointInput{ 2536 EndpointArn: aws.String(endpointArn), 2537 } 2538 2539 // perform action 2540 if len(timeOutDuration) > 0 { 2541 ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0]) 2542 defer cancel() 2543 2544 _, err = s.snsClient.DeleteEndpointWithContext(ctx, input) 2545 } else { 2546 if segCtxSet { 2547 _, err = s.snsClient.DeleteEndpointWithContext(segCtx, input) 2548 } else { 2549 _, err = s.snsClient.DeleteEndpoint(input) 2550 } 2551 } 2552 2553 // evaluate result 2554 if err != nil { 2555 err = errors.New("DeletePlatformEndpoint Failed: (Delete Action) " + err.Error()) 2556 return err 2557 } else { 2558 return nil 2559 } 2560 } 2561 2562 // ListEndpointsByPlatformApplication will list endpoints by platform application, with optional nextToken for retrieving more list from a prior call 2563 // 2564 // Parameters: 2565 // 1. platformApplicationArn = required, the platform application to filter for its related endpoints to retrieve 2566 // 2. nextToken = optional, if prior call returned more...token, pass in here to retrieve the related list 2567 // 3. timeOutDuration = optional, indicates timeout value for context 2568 // 2569 // Return Values: 2570 // 1. endpointArnsList = string slice of endpoint ARNs under the given platform application ARN, nil if not set 2571 // 2. moreEndpointArnsNextToken = if there are more endpoints to load, this token is filled, to query more, use the token as input parameter, blank if no more 2572 // 3. err = error info if any 2573 func (s *SNS) ListEndpointsByPlatformApplication(platformApplicationArn string, 2574 nextToken string, 2575 timeOutDuration ...time.Duration) (endpointArnsList []string, moreEndpointArnsNextToken string, err error) { 2576 segCtx := context.Background() 2577 segCtxSet := false 2578 2579 seg := xray.NewSegmentNullable("SNS-ListEndpointsByPlatformApplication", s._parentSegment) 2580 2581 if seg != nil { 2582 segCtx = seg.Ctx 2583 segCtxSet = true 2584 2585 defer seg.Close() 2586 defer func() { 2587 _ = seg.Seg.AddMetadata("SNS-ListEndpointsByPlatformApplication-PlatformApplicationArn", platformApplicationArn) 2588 _ = seg.Seg.AddMetadata("SNS-ListEndpointsByPlatformApplication-NextToken", nextToken) 2589 _ = seg.Seg.AddMetadata("SNS-ListEndpointsByPlatformApplication-Result-EndpointArnsList", endpointArnsList) 2590 _ = seg.Seg.AddMetadata("SNS-ListEndpointsByPlatformApplication-Result-NextToken", moreEndpointArnsNextToken) 2591 2592 if err != nil { 2593 _ = seg.Seg.AddError(err) 2594 } 2595 }() 2596 } 2597 2598 // validation 2599 if s.snsClient == nil { 2600 err = errors.New("ListEndpointsByPlatformApplication Failed: " + "SNS Client is Required") 2601 return nil, "", err 2602 } 2603 2604 if util.LenTrim(platformApplicationArn) <= 0 { 2605 err = errors.New("ListEndpointsByPlatformApplication Failed: " + "Platform Application ARN is Required") 2606 return nil, "", err 2607 } 2608 2609 // create input object 2610 input := &sns.ListEndpointsByPlatformApplicationInput{ 2611 PlatformApplicationArn: aws.String(platformApplicationArn), 2612 } 2613 2614 if util.LenTrim(nextToken) > 0 { 2615 input.NextToken = aws.String(nextToken) 2616 } 2617 2618 // perform action 2619 var output *sns.ListEndpointsByPlatformApplicationOutput 2620 2621 if len(timeOutDuration) > 0 { 2622 ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0]) 2623 defer cancel() 2624 2625 output, err = s.snsClient.ListEndpointsByPlatformApplicationWithContext(ctx, input) 2626 } else { 2627 if segCtxSet { 2628 output, err = s.snsClient.ListEndpointsByPlatformApplicationWithContext(segCtx, input) 2629 } else { 2630 output, err = s.snsClient.ListEndpointsByPlatformApplication(input) 2631 } 2632 } 2633 2634 // evaluate result 2635 if err != nil { 2636 err = errors.New("ListEndpointsByPlatformApplication Failed: (List Action) " + err.Error()) 2637 return nil, "", err 2638 } 2639 2640 moreEndpointArnsNextToken = aws.StringValue(output.NextToken) 2641 2642 for _, v := range output.Endpoints { 2643 if v != nil { 2644 if v1 := aws.StringValue(v.EndpointArn); util.LenTrim(v1) > 0 { 2645 endpointArnsList = append(endpointArnsList, v1) 2646 } 2647 } 2648 } 2649 2650 return endpointArnsList, moreEndpointArnsNextToken, nil 2651 } 2652 2653 // GetPlatformEndpointAttributes will retrieve endpoint attributes based on a specific endpoint ARN 2654 // 2655 // Parameters: 2656 // 1. endpointArn = required, the endpoint ARN used to retrieve related endpoint attributes 2657 // 2. timeOutDuration = optional, indicates timeout value for context 2658 // 2659 // Return Values: 2660 // 1. attributes = map of sns endpoint attributes related to the given endpoint ARN 2661 // 2. err = error info if any 2662 // 2663 // Endpoint Attributes: (Key = Expected Value) 2664 // 1. CustomUserData = arbitrary user data to associate with the endpoint. 2665 // Amazon SNS does not use this data. 2666 // The data must be in UTF-8 format and less than 2KB. 2667 // 2. Enabled = flag that enables/disables delivery to the endpoint. Amazon 2668 // SNS will set this to false when a notification service indicates to Amazon SNS that the endpoint is invalid. 2669 // Users can set it back to true, typically after updating Token. 2670 // 3. Token = device token, also referred to as a registration id, for an app and mobile device. 2671 // This is returned from the notification service when an app and mobile device are registered with the notification service. 2672 // The device token for the iOS platform is returned in lowercase. 2673 func (s *SNS) GetPlatformEndpointAttributes(endpointArn string, timeOutDuration ...time.Duration) (attributes map[snsendpointattribute.SNSEndpointAttribute]string, err error) { 2674 segCtx := context.Background() 2675 segCtxSet := false 2676 2677 seg := xray.NewSegmentNullable("SNS-GetPlatformEndpointAttributes", s._parentSegment) 2678 2679 if seg != nil { 2680 segCtx = seg.Ctx 2681 segCtxSet = true 2682 2683 defer seg.Close() 2684 defer func() { 2685 _ = seg.Seg.AddMetadata("SNS-GetPlatformEndpointAttributes-EndpointArn", endpointArn) 2686 _ = seg.Seg.AddMetadata("SNS-GetPlatformEndpointAttributes-Result-Attributes", attributes) 2687 2688 if err != nil { 2689 _ = seg.Seg.AddError(err) 2690 } 2691 }() 2692 } 2693 2694 // validation 2695 if s.snsClient == nil { 2696 err = errors.New("GetPlatformEndpointAttributes Failed: " + "SNS Client is Required") 2697 return nil, err 2698 } 2699 2700 if util.LenTrim(endpointArn) <= 0 { 2701 err = errors.New("GetPlatformEndpointAttributes Failed: " + "Endpoint ARN is Required") 2702 return nil, err 2703 } 2704 2705 // create input object 2706 input := &sns.GetEndpointAttributesInput{ 2707 EndpointArn: aws.String(endpointArn), 2708 } 2709 2710 // perform action 2711 var output *sns.GetEndpointAttributesOutput 2712 2713 if len(timeOutDuration) > 0 { 2714 ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0]) 2715 defer cancel() 2716 2717 output, err = s.snsClient.GetEndpointAttributesWithContext(ctx, input) 2718 } else { 2719 if segCtxSet { 2720 output, err = s.snsClient.GetEndpointAttributesWithContext(segCtx, input) 2721 } else { 2722 output, err = s.snsClient.GetEndpointAttributes(input) 2723 } 2724 } 2725 2726 // evaluate result 2727 if err != nil { 2728 err = errors.New("GetPlatformEndpointAttributes Failed: (Get Action) " + err.Error()) 2729 return nil, err 2730 } else { 2731 attributes = s.fromAwsEndpointAttributes(output.Attributes) 2732 return attributes, nil 2733 } 2734 } 2735 2736 // SetPlatformEndpointAttributes will set or update platform endpoint attributes, 2737 // For attribute value or Json format, see corresponding notes in CreatePlatformEndpoint where applicable 2738 func (s *SNS) SetPlatformEndpointAttributes(endpointArn string, 2739 attributes map[snsendpointattribute.SNSEndpointAttribute]string, 2740 timeOutDuration ...time.Duration) (err error) { 2741 segCtx := context.Background() 2742 segCtxSet := false 2743 2744 seg := xray.NewSegmentNullable("SNS-SetPlatformEndpointAttributes", s._parentSegment) 2745 2746 if seg != nil { 2747 segCtx = seg.Ctx 2748 segCtxSet = true 2749 2750 defer seg.Close() 2751 defer func() { 2752 _ = seg.Seg.AddMetadata("SNS-SetPlatformEndpointAttributes-EndpointArn", endpointArn) 2753 _ = seg.Seg.AddMetadata("SNS-SetPlatformEndpointAttributes-Attributes", attributes) 2754 2755 if err != nil { 2756 _ = seg.Seg.AddError(err) 2757 } 2758 }() 2759 } 2760 2761 // validation 2762 if s.snsClient == nil { 2763 err = errors.New("SetPlatformEndpointAttributes Failed: " + "SNS Client is Required") 2764 return err 2765 } 2766 2767 if util.LenTrim(endpointArn) <= 0 { 2768 err = errors.New("SetPlatformEndpointAttributes Failed: " + "Endpoint ARN is Required") 2769 return err 2770 } 2771 2772 if attributes == nil { 2773 err = errors.New("SetPlatformEndpointAttributes Failed: " + "Attributes Map is Required") 2774 return err 2775 } 2776 2777 // create input 2778 input := &sns.SetEndpointAttributesInput{ 2779 EndpointArn: aws.String(endpointArn), 2780 Attributes: s.toAwsEndpointAttributes(attributes), 2781 } 2782 2783 // perform action 2784 if len(timeOutDuration) > 0 { 2785 ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0]) 2786 defer cancel() 2787 2788 _, err = s.snsClient.SetEndpointAttributesWithContext(ctx, input) 2789 } else { 2790 if segCtxSet { 2791 _, err = s.snsClient.SetEndpointAttributesWithContext(segCtx, input) 2792 } else { 2793 _, err = s.snsClient.SetEndpointAttributes(input) 2794 } 2795 } 2796 2797 // evaluate result 2798 if err != nil { 2799 err = errors.New("SetPlatformEndpointAttributes Failed: (Set Action) " + err.Error()) 2800 return err 2801 } else { 2802 return nil 2803 } 2804 }