[RUBY] Informez régulièrement Slack des articles stockés dans Qiita avec AWS Lambda + DynamoDB + CloudWatch

Aperçu

--Je veux apprendre en touchant les services AWS

Quoi utiliser

un service Utilisation
AWS Lambda Pour récupérer des articles stockés depuis l'API Qiita et notifier Slack
Amazon DynamoDB Étant donné que l'article obtenu à partir de l'API Qiita ne contient pas d'informations sur "quand il a été stocké", les informations de notification sont dupliquées. Pour éviter cela, conservez les informations précédemment notifiées
Amazon CloudWatch Pour une exécution régulière de Lambda
AWS SAM (modèle d'application sans serveur) Pour déployer des applications construites localement sur chaque service
Qiita API Pour acquérir des informations stockées

Vue d'ensemble

↑ se résume comme suit. Slack App (1).png

ordre du jour

[0. Préparation](# 0-Préparation) [1. Créer un modèle](# 1-Créer un modèle) [2. Déployer à l'aide de SAM](# 2-Déployer à l'aide de sam) [3. Notify Slack](# 3-Notify slack) [4. Notifier Slack des informations boursières à l'aide de l'API Qiita](Notifier Slack des informations boursières à l'aide de # 4-qiita-api) [5. Gérer l'historique des notifications à l'aide de DynamoDB](# 5-Gérer l'historique des notifications à l'aide de dynamodb) [6. Faire exécuter CloudWatch Lambda périodiquement à tout moment](# 6-faire en sorte que cloudwatch exécute lambda à tout moment)

0. Préparation préalable

AWS

Si ce qui suit n'a pas été créé ou installé, exécutez-le comme il convient.

--Créer un compte AWS

Slack

Installez l'application webhook sur le canal dont vous souhaitez être averti et vérifiez le fonctionnement. Référence: Procédure d'acquisition d'URL Slack Webhook --Qiita

la mise en oeuvre

1. Créez un modèle

Créez un modèle avec la commande sam.

$ sam init -n qiita-stocks-notifier -r ruby2.5
option La description
-n, --name TEXT initLe nom du projet créé par la commande.
-r, --runtime Spécification du runtime. Cette foisrubyJe l'ai fait.

Référence: sam init --AWS serverless application model

J'ai choisi la valeur par défaut pour les questions posées dans la console. Lorsque la commande est terminée, un modèle avec la structure suivante est créé sous le répertoire.

$ tree
.
├── Gemfile
├── README.md
├── events
│   └── event.json
├── hello_world
│   ├── Gemfile
│   └── app.rb
├── template.yaml
└── tests
    └── unit
        └── test_handler.rb

Le contenu de ** hello_world / app.rb ** ne produit qu'un message.

2. Déployer à l'aide de SAM

Maintenant que le modèle a été créé, déployons-le sur Lambda. Référence: [Tutoriel: Deploying Hello World Applications-AWS Serverless Application Model](https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/serverless-getting-started-hello- world.html)

$ sam build
$ sam deploy --guided
#Je vais répondre à la question.

Lorsque le déploiement est terminé normalement, la chaîne de caractères est sortie vers la console et vous pouvez confirmer qu'elle est fluide.

 {"message": "hello world"}

Confirmez que l'application déployée est reflétée dans l'écran de gestion de Lambda. ダウンロード (2).png

3. Notifier Slack

Ajoutez slack-notifier à ** hello_world / Gemfile ** et ** bundle install **. stevenosloan/slack-notifier: A simple wrapper for posting to slack channels

gem "slack-notifier"
$ bundle

Initialisez ʻapp.rb en passant l'URL de Hooks à slack-notifier` comme indiqué ci-dessous, et essayez d'envoyer le libellé de test.

app.rb


require "json"
require "slack-notifier"

def lambda_handler(event:, context:)
  notifier = Slack::Notifier.new "https://hooks.slack.com/services/**/**" do
    defaults channel: "#qiita-slacks-notification"
  end
  notifier.ping "yeah"
end

3.1 Déployer et vérifier le fonctionnement

Une fois la modification terminée, générez-la et déployez-la pour vérifier l'opération.

$ sam build
$ sam deploy

Sélectionnez "Sélectionner un événement de test" -> "Définir un événement de test" sur l'écran d'administration Lambda. スクリーンショット 2020-06-07 5.37.06.png

Ce sera un écran pour sélectionner les paramètres de l'application créée, mais cette fois le comportement ne change pas en fonction des paramètres Laissez la valeur par défaut. スクリーンショット 2020-06-07 5.38.52.png

Après avoir terminé le "Set Test Event", sélectionnez "Test" et confirmez que le message est envoyé à Slack. スクリーンショット 2020-06-07 1.02.08.png

Vous pouvez maintenant confirmer la communication de ** Lambda ** à Slack.

4. Informer Slack des informations sur les stocks à l'aide de l'API Qiita

Ensuite, récupérez le stock de l'utilisateur dans Qiita API et notifiez-le.

4.1 Consulter la documentation de l'API

Voici l'API pour obtenir les articles stockés par l'utilisateur. Documentation API Qiita v2 - Qiita: Développeur

Insérez la gemme ** Faraday ** pour faciliter l'interaction avec les API externes. Référence: lostisland / faraday: bibliothèque client HTTP simple mais flexible, avec prise en charge de plusieurs backends.

gem "faraday"
$ bundle

4.2 Mise en œuvre de la partie notification

Le schéma de la partie mise en œuvre est le suivant.

-Obtenir des informations boursières de l'API en utilisant ** Faraday ** --Notifiez Slack de la réponse dans un tableau par ** titre ** et ** URL **

app.rb


require 'json'
require 'faraday'
require 'slack-notifier'

USER_ID = "{Mon ID utilisateur}".freeze

def lambda_handler(event:, context:)
  #Obtenez des informations sur les stocks de l'API
  response = Faraday.get("https://qiita/api/v2/user/#{USER_ID}/stocks", page: 1, per_page: 10)

  #Organisez les titres et les URL dans un tableau
  messages = JSON.parse(response.body).each_with_object([]) do |res, ary|
    ary << [res["title"], res["url"]]
  end

  notifier = Slack::Notifier.new "https://hooks.slack.com/services/**/**" do
    defaults channel: "#qiita-slacks-notification"
  end

  notifier.ping "Je publierai l'article stocké chez Qiita la semaine dernière"
  messages.each do |message|
    notifier.ping message[0]
    notifier.ping message[1]
    notifier.ping "- - - - - - - - - - - - - - - - - - - - "
  end
end

Une fois le correctif terminé, essayez d'utiliser sam local invoke, qui vous permet de tester votre application localement.

sam local invoke --no-event
option La description
--no-event Appelez la fonction avec un événement vide. Utilisez une autre option si vous souhaitez transmettre des paramètres pour la vérification.

Référence: [sam local invoke --AWS serverless application model](https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-local- invoke.html)

Vous pouvez confirmer que les informations boursières ont été envoyées à Slack en exécutant la commande.

スクリーンショット 2020-06-07 2.08.04.png

5. Gérez l'historique des notifications à l'aide de DynamoDB

La partie notification est terminée, mais si elle est laissée telle quelle, les mêmes informations peuvent circuler à chaque fois, je voudrais donc éviter que l'article une fois notifié ne soit notifié. Utilisez ** DynamoDB ** pour enregistrer les informations de notification et empêcher la notification d'informations dans la base de données.

Utilisez la gemme ** ʻaws-record` ** pour échanger des données avec DynamoDB. aws/aws-sdk-ruby-record: Official repository for the aws-record gem, an abstraction for Amazon DynamoDB.

5.1 Mise en œuvre

template.yml

AWSTemplateFormatVersion: '2010-09-09'
...
Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
    Properties:
      CodeUri: hello_world/
      Handler: app.lambda_handler
      Runtime: ruby2.5
      Policies:
+     #Créer dans DynamoDB/Read/Update/Accorder la permission de supprimer
+     - DynamoDBCrudPolicy:
+         TableName: !Ref NotifiedMessageDDBTable
+     #Variable d'environnement
+     Environment:
+       Variables:
+         DDB_TABLE: !Ref NotifiedMessageDDBTable
      Events:
        HelloWorld:
          Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
          Properties:
            Path: /hello
            Method: get
+ NotifiedMessageDDBTable:
+   Type: AWS::Serverless::SimpleTable
...

app.rb


require 'aws-record'
require 'json'
require 'faraday'
require 'slack-notifier'

USER_ID = "{Mon ID utilisateur}".freeze

class NotifiedMessage
  include Aws::Record
  set_table_name ENV['DDB_TABLE']
  string_attr :id, hash_key: true
  string_attr :title
  string_attr :url
end

def lambda_handler(event:, context:)
  #Recevoir des informations notifiées
  already_notified_messages = []
  NotifiedMessage.scan.each do |notified_message|
    already_notified_messages << notified_message.url
  end

  #Obtenez des articles stockés à partir de l'API et organisez uniquement les articles non annoncés dans un tableau
  response = Faraday.get("https://qiita.com/api/v2/users/#{USER_ID}/stocks", page: 1, per_page: 10)
  messages = JSON.parse(response.body).each_with_object([]) do |res, ary|
    ary << [res["title"], res["url"]] unless already_notified_messages.include? res["url"]
  end

  notifier = Slack::Notifier.new "https://hooks.slack.com/services/xx/xx" do
    defaults channel: "#qiita-stocks-notification"
  end
  notifier.ping "Je n'avais aucun article en stock cette semaine" and return if messages.size.zero?

  #Notifier Slack et enregistrer dans la base de données
  notifier.ping "Je publierai l'article stocké chez Qiita la semaine dernière"
  messages.each do |message|
    notifier.ping message[0]
    notifier.ping message[1]
    notifier.ping "- - - - - - - - - - - - - - - - - - - -"

    notified_message = NotifiedMessage.new(id: SecureRandom.uuid, title: message["title"], url: message["url"])
    notified_message.save!
  end
end

Si vous déployez et testez cela, vous pouvez vérifier la table ajoutée sur l'écran de gestion de DynamoDB, et vous pouvez insérer les 10 dernières informations boursières.

スクリーンショット 2020-06-07 3.05.25.png ダウンロード (3).png

6.Faites en sorte que CloudWatch exécute Lambda à tout moment

Enfin, assurez-vous de recevoir des notifications à Slack à un moment agréable chaque semaine.

6.1 Paramètres de planification

Si vous sélectionnez ** ʻAjouter un déclencheur` ** et sélectionnez "** CloudWatch Events / Event Bridge **" dans la recherche, vous pouvez définir les règles d'exécution, donc je les ai définies comme suit. スクリーンショット 2020-06-07 4.29.19.png

Bien que la compression ait été divulguée, la partie de la ** formule de planification ** a été correctement définie avec cron (0 12? * SAT *) (tous les samedis à midi). Référence: Schedule expression using Rate or Cron --AWS Lambda

Si vous vérifiez le planificateur de CloudWatch, vous pouvez voir qu'il s'exécute ** tous les samedis à midi ** comme indiqué ci-dessous. スクリーンショット 2020-06-07 4.34.54.png

Résumé

Vous avez maintenant reçu des notifications de stock hebdomadaires de Qiita. Cependant, s'il est laissé tel quel, le nombre de lectures de DynamoDB augmentera et le portefeuille sera pincé, il est donc nécessaire de restreindre les informations à acquérir en passant «query» à «scan». J'ai beaucoup appris des services AWS car je ne les comprends souvent qu'en les touchant.

Je vous serais reconnaissant si vous pouviez signaler des erreurs.

Article de référence

Documentation officielle

Le blog que j'ai utilisé comme référence

Recommended Posts

Informez régulièrement Slack des articles stockés dans Qiita avec AWS Lambda + DynamoDB + CloudWatch
Publiez régulièrement des images de tweets sur Twitter avec AWS Lambda + Java