AWSTemplateFormatVersion: 2010-09-09
Parameters:
  # Twitter
  ConsumerKey:
    Default: '***ConsumerKey***'
    Description: Twitter App Consumer Key
    Type: String
  ConsumerSecret:
    Default: '***ConsumerSecret***'
    Description: Twitter App Consumer Secret
    Type: String
  AccessToken:
    Default: '***AccessToken***'
    Description: Twitter App Access Token
    Type: String
  AccessTokenSecret:
    Default: '***AccessTokenSecret***'
    Description: Twitter App Access Token Secret
    Type: String

  # deploy package location
  UploadedPackageBucketName:
    Default: netebakari
    AllowedPattern: '^[a-z0-9\-\.]+$'
    Description: Your S3 Bucket Name
    Type: String
  UploadedPackageKeyName:
    Default: twitter-timeline-tracker/timeline-tracker-latest.zip
    Description: Path to uploaded deploy package
    Type: String

  # config
  TTLinDays:
    Default: 3
    Description: DynamoDB TTL in days
    Type: Number
  DaysToArchive:
    Default: 4
    Description: Number of days to archive tweets
    Type: Number
  IncludeFollowers:
    Default: false
    AllowedPattern: "true|false"
    Description: "'true' or 'false'. If true, all the tweets of your followers fetched and archived"
    Type: String
  UtfOffsetInHours:
    Default: 9
    Description: timezone
    Type: Number
  TwitterUserId:
    Default: "12345"
    AllowedPattern: "^[0-9]+$"
    Description: Your Twitter Id *not screen name*
    Type: String

  # AWS Resources
  S3BucketName:
    Default: "your-bucket-name-for-tweet-log"
    AllowedPattern: '^[a-z0-9\-\.]+$'
    Description: S3 Bucket Name (MUST already exits)
    Type: String
  DynamoDbTableName:
    Default: TwitterTLTracker-Timelines
    Description: DynamoDB Table Name
    Type: String
  QueueName:
    Default: TwitterTLTracker-ScheduleQueue
    Description: SQS Queue Name
    Type: String
  RoleName:
    Default: TwitterTLTracker-Lambda
    Description: IAM Role Name (only for Lambda)
    Type: String
  
Resources:
  UserIdQueue:
    Type: 'AWS::SQS::Queue'
    Properties:
      VisibilityTimeout: 300
      QueueName: !Sub '${QueueName}'

  TimelineDynamoDB:
    Type: 'AWS::DynamoDB::Table'
    Properties:
      TableName: !Sub '${DynamoDbTableName}'
      AttributeDefinitions:
        - AttributeName: id_str
          AttributeType: S
      KeySchema:
        - AttributeName: id_str
          KeyType: HASH
      ProvisionedThroughput:
        ReadCapacityUnits: 1
        WriteCapacityUnits: 1
      TimeToLiveSpecification:
        AttributeName: TTL
        Enabled: true

  IAMRoleForLambda:
    Type: 'AWS::IAM::Role'
    Properties:
      RoleName: !Sub ${RoleName}
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Path: /
  IamPolicyLambda1:
    Type: 'AWS::IAM::Policy'
    Properties:
      PolicyName: CloudWatch-Logs
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action:
              - 'logs:CreateLogGroup'
              - 'logs:CreateLogStream'
              - 'logs:PutLogEvents'
            Resource: "*"
      Roles:
        - !Ref IAMRoleForLambda

  IamPolicyLambda2:
    Type: 'AWS::IAM::Policy'
    Properties:
      PolicyName: SQS-DynamoDB-S3-Lambda
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action:
              - 'lambda:InvokeFunction'
            Resource: !GetAtt LambdaTLMerger.Arn
          - Effect: Allow
            Action:
              - 'sqs:DeleteMessage'
              - 'sqs:ReceiveMessage'
              - 'sqs:SendMessage'
              - 'sqs:GetQueueAttributes'
            Resource: !GetAtt UserIdQueue.Arn
          - Effect: Allow
            Action:
              - "dynamodb:PutItem"
              - "dynamodb:Scan"
              - "dynamodb:Query"
              - "dynamodb:UpdateItem"
            Resource: !GetAtt TimelineDynamoDB.Arn
          - Effect: Allow
            Action:
              - "s3:PutObject"
              - "s3:ListBucket"
              - "s3:GetObject"
            Resource:
              - !Sub arn:aws:s3:::${S3BucketName}/*
              - !Sub arn:aws:s3:::${S3BucketName}
      Roles:
        - !Ref IAMRoleForLambda

  LambdaHomeTL:
    Type: 'AWS::Lambda::Function'
    Properties:
      FunctionName: Twitter-TL-Tracker-HomeTimeline
      Description: '[Twitter-TL-Tracker] Home TL'
      Environment:
        Variables:
          twitter_consumer_key: !Sub ${ConsumerKey}
          twitter_consumer_secret: !Sub ${ConsumerSecret}
          twitter_access_token: !Sub ${AccessToken}
          twitter_access_token_secret: !Sub ${AccessTokenSecret}
          dynamoDb_region: !Sub ${AWS::Region}
          dynamoDb_tableName: !Sub ${DynamoDbTableName}
          dynamoDb_ttlInDays: !Sub ${TTLinDays}
          sqs_region: !Sub ${AWS::Region}
          sqs_queueUrl: !Sub https://sqs.${AWS::Region}.amazonaws.com/${AWS::AccountId}/${QueueName}
          s3_region: !Sub ${AWS::Region}
          s3_bucket: !Sub ${S3BucketName}
          options_daysToArchive: !Sub ${DaysToArchive}
          options_includeFollowers: !Sub ${IncludeFollowers}
          options_utfOffset: !Sub ${UtfOffsetInHours}
          options_myUserIdStr: !Sub ${TwitterUserId}
      Handler: "index.homeTimeline"
      MemorySize: 256
      Role: !GetAtt IAMRoleForLambda.Arn
      Runtime: nodejs12.x
      Timeout: 55
      Code:
        S3Bucket: !Sub ${UploadedPackageBucketName}
        S3Key: !Sub ${UploadedPackageKeyName}

  LambdaQueueFiller:
    Type: 'AWS::Lambda::Function'
    Properties:
      FunctionName: Twitter-TL-Tracker-QueueFiller
      Description: '[Twitter-TL-Tracker] Scheduler'
      Environment:
        Variables:
          twitter_consumer_key: !Sub ${ConsumerKey}
          twitter_consumer_secret: !Sub ${ConsumerSecret}
          twitter_access_token: !Sub ${AccessToken}
          twitter_access_token_secret: !Sub ${AccessTokenSecret}
          dynamoDb_region: !Sub ${AWS::Region}
          dynamoDb_tableName: !Sub ${DynamoDbTableName}
          dynamoDb_ttlInDays: !Sub ${TTLinDays}
          sqs_region: !Sub ${AWS::Region}
          sqs_queueUrl: !Sub https://sqs.${AWS::Region}.amazonaws.com/${AWS::AccountId}/${QueueName}
          s3_region: !Sub ${AWS::Region}
          s3_bucket: !Sub ${S3BucketName}
          options_daysToArchive: !Sub ${DaysToArchive}
          options_includeFollowers: !Sub ${IncludeFollowers}
          options_utfOffset: !Sub ${UtfOffsetInHours}
          options_myUserIdStr: !Sub ${TwitterUserId}
      Handler: "index.hourlyTask"
      MemorySize: 128
      Role: !GetAtt IAMRoleForLambda.Arn
      Runtime: nodejs12.x
      Timeout: 240
      Code:
        S3Bucket: !Sub ${UploadedPackageBucketName}
        S3Key: !Sub ${UploadedPackageKeyName}

  LambdaUserTL:
    Type: 'AWS::Lambda::Function'
    Properties:
      FunctionName: Twitter-TL-Tracker-userTL
      Description: '[Twitter-TL-Tracker] User TL'
      Environment:
        Variables:
          twitter_consumer_key: !Sub ${ConsumerKey}
          twitter_consumer_secret: !Sub ${ConsumerSecret}
          twitter_access_token: !Sub ${AccessToken}
          twitter_access_token_secret: !Sub ${AccessTokenSecret}
          dynamoDb_region: !Sub ${AWS::Region}
          dynamoDb_tableName: !Sub ${DynamoDbTableName}
          dynamoDb_ttlInDays: !Sub ${TTLinDays}
          sqs_region: !Sub ${AWS::Region}
          sqs_queueUrl: !Sub https://sqs.${AWS::Region}.amazonaws.com/${AWS::AccountId}/${QueueName}
          s3_region: !Sub ${AWS::Region}
          s3_bucket: !Sub ${S3BucketName}
          options_daysToArchive: !Sub ${DaysToArchive}
          options_includeFollowers: !Sub ${IncludeFollowers}
          options_utfOffset: !Sub ${UtfOffsetInHours}
          options_myUserIdStr: !Sub ${TwitterUserId}
      Handler: "index.userTL"
      MemorySize: 320
      Role: !GetAtt IAMRoleForLambda.Arn
      Runtime: nodejs12.x
      Timeout: 240
      Code:
        S3Bucket: !Sub ${UploadedPackageBucketName}
        S3Key: !Sub ${UploadedPackageKeyName}

  LambdaTLMerger:
    Type: 'AWS::Lambda::Function'
    Properties:
      FunctionName: Twitter-TL-Tracker-merger
      Description: '[Twitter-TL-Tracker] Merge TL'
      Environment:
        Variables:
          twitter_consumer_key: !Sub ${ConsumerKey}
          twitter_consumer_secret: !Sub ${ConsumerSecret}
          twitter_access_token: !Sub ${AccessToken}
          twitter_access_token_secret: !Sub ${AccessTokenSecret}
          dynamoDb_region: !Sub ${AWS::Region}
          dynamoDb_tableName: !Sub ${DynamoDbTableName}
          dynamoDb_ttlInDays: !Sub ${TTLinDays}
          sqs_region: !Sub ${AWS::Region}
          sqs_queueUrl: !Sub https://sqs.${AWS::Region}.amazonaws.com/${AWS::AccountId}/${QueueName}
          s3_region: !Sub ${AWS::Region}
          s3_bucket: !Sub ${S3BucketName}
          options_daysToArchive: !Sub ${DaysToArchive}
          options_includeFollowers: !Sub ${IncludeFollowers}
          options_utfOffset: !Sub ${UtfOffsetInHours}
          options_myUserIdStr: !Sub ${TwitterUserId}
      Handler: "index.archive"
      MemorySize: 1024
      Role: !GetAtt IAMRoleForLambda.Arn
      Runtime: nodejs12.x
      Timeout: 300
      Code:
        S3Bucket: !Sub ${UploadedPackageBucketName}
        S3Key: !Sub ${UploadedPackageKeyName}


  LamdaUserTLTrigger:
    Type: "AWS::Events::Rule"
    Properties:
      Description: "every 2 minutes"
      Name: LamdaUserTLTrigger
      ScheduleExpression: "cron(*/2 * * * ? *)"
      State: ENABLED
      Targets:
        - Arn: !GetAtt LambdaUserTL.Arn
          Id: LambdaUserTL-every2minutes
        - Arn: !GetAtt LambdaHomeTL.Arn
          Id: LambdaHomeTL-every2minutes

  LambdaInvokePermission1:
    Type: AWS::Lambda::Permission
    Properties: 
      Action: lambda:InvokeFunction
      FunctionName: !Ref LambdaUserTL
      Principal: events.amazonaws.com
      SourceArn: !GetAtt LamdaUserTLTrigger.Arn

  LambdaInvokePermission2:
    Type: AWS::Lambda::Permission
    Properties: 
      Action: lambda:InvokeFunction
      FunctionName: !Ref LambdaHomeTL
      Principal: events.amazonaws.com
      SourceArn: !GetAtt LamdaUserTLTrigger.Arn

  LamdaUserQueueTrigger:
    Type: "AWS::Events::Rule"
    Properties:
      Description: "every 30 minutes"
      Name: LamdaUserQueueTrigger
      ScheduleExpression: "cron(*/30 * * * ? *)"
      State: ENABLED
      Targets:
        - Arn: !GetAtt LambdaQueueFiller.Arn
          Id: LambdaQueueFiller-every2minutes

  LambdaInvokePermission3:
    Type: AWS::Lambda::Permission
    Properties: 
      Action: lambda:InvokeFunction
      FunctionName: !Ref LambdaQueueFiller
      Principal: events.amazonaws.com
      SourceArn: !GetAtt LamdaUserQueueTrigger.Arn


  LamdaTLMergerTrigger:
    Type: "AWS::Events::Rule"
    Properties:
      Description: "every midnight"
      Name: LamdaTLMergerTrigger
      ScheduleExpression: "cron(5 15 * * ? *)"
      State: ENABLED
      Targets:
        - Arn: !GetAtt LambdaTLMerger.Arn
          Id: LambdaTLMerger-everyMidnight

  LambdaInvokePermission4:
    Type: AWS::Lambda::Permission
    Properties: 
      Action: lambda:InvokeFunction
      FunctionName: !Ref LambdaTLMerger
      Principal: events.amazonaws.com
      SourceArn: !GetAtt LamdaTLMergerTrigger.Arn

