[RUBY] Il n'y avait pas beaucoup d'informations sur le chèque-cadeau premium de la ville, j'ai donc essayé de le rendre plus facile à utiliser avec LINE Bot sans autorisation.

introduction

J'habite dans la ville de Kawaguchi, dans la préfecture de Saitama, et j'ai récemment reçu un dépliant disant que j'émettrais un "chèque-cadeau avec prime". En gros, si vous achetez un chèque-cadeau de 20 000 yens, vous pouvez en acheter 24 000 dans un magasin local. Je pensais que c'était assez pratique, alors j'ai accédé à la page d'accueil pour savoir dans quel type de magasin il peut être utilisé, mais il n'y a pas de liste de magasins et il existe un lien direct vers un PDF qui résume les informations du magasin. C'était seulement. .. .. スクリーンショット 2020-09-13 23.44.02.png

Cela rend la recherche difficile. .. .. Donc, je l'ai transformé en un Bot LINE sans permission · Recherche par mots-clés ・ Recherchez le magasin utilisable le plus proche à partir des informations de localisation J'ai essayé de le mettre en œuvre pour que cela puisse être fait.

Que expliquer dans cet article

Créer une application Rails Déployer sur Heroku Préparation de LIEN Bot Implémentation de LIENBot (Aum return BOT) Lire le fichier CSV Implémentation de la fonction de recherche simple

La mise en œuvre détaillée sera divisée en une deuxième partie.

environnement

Ruby 2.6.6 Rails 6.0.3.3

Préparation préalable

Installez rbenv installation de git enregistrement du compte heroku Un outil capable de convertir un PDF en CSV (je l'ai fait avec Adobe Acrobat)

Créer une application Rails

Tout d'abord, créez un répertoire pour l'application (la méthode dans cet article sera le nom de l'application tel qu'il est, alors réfléchissons-y avant de le créer)

$ mkdir kawaguchi_ticketl_inebot
$ cd kawaguchi_ticketl_inebot

Je pense que la version de ruby n'est pas très ancienne, mais je préciserai 2.6.6 pour le moment.

$ rbenv install 2.6.6
$ rbenv local 2.6.6

Exécutez le bundle init pour créer un Gemfile

$ bundle init

Supprimez le commentaire Rails dans le Gemfile créé et installez le bundle

$ bundle install --path=vendor/bundle

Comme il n'est utilisé que pour LINE Bot, créez une application Rails en mode api. Je vais le faire avec postgreql pour que je puisse le donner à heroku en douceur. On vous demandera si vous voulez écraser le Gemfile, mais vous pouvez l'écraser.

$ bundle exec rails new . --api -d postgresql
$ bundle exec rails db:create

Une fois que vous avez fait cela, démarrez le serveur et vérifiez simplement si vous pouvez y accéder. Vérifiez en accédant à http: // localhost: 3000 /

$ bundle exec rails s

スクリーンショット 2020-09-13 23.59.14.png

Tu peux le faire

(référence) Cet article était très facile à comprendre [Jusqu'à ce qu'un débutant publie son propre bot LINE dans Ruby](https://qiita.com/taki-ikat/items/2a0187b30e4baca8b9c7#2-line-developers%E3%82%B3%E3%83%B3%E3 % 82% BD% E3% 83% BC% E3% 83% AB% E3% 81% A7% E3% 83% 81% E3% 83% A3% E3% 83% 8D% E3% 83% AB% E3% 82 % 92% E4% BD% 9C% E6% 88% 90) Gérer la version ruby avec rbenv

Déployer sur Heroku

Vous pouvez le faire plus tard, mais une fois que vous l'avez poussé vers heroku. Si vous n'êtes pas encore enregistré ou configuré herokub, veuillez d'abord le faire.

$ heroku create
Creating app... done, ⬢ young-temple-xxxxxx
https://young-temple-xxxxxx.herokuapp.com/ | https://git.heroku.com/young-temple-xxxxxx.git
$ git add .
$ git commit -m 'first commit'
$ git push heroku master

Notez l'URL affichée lorsque vous créez heroku car vous l'utiliserez plus tard. (Ici, https://young-temple-xxxxxx.herokuapp.com/)

Vous pouvez le donner à github etc., mais l'ignorer pour le moment

(référence) Flux de pousser vers github et donner à heroku

Préparation de LINE Bot

Enregistrement de la chaîne

Reportez-vous ici https://developers.line.biz/ja/docs/messaging-api/getting-started/#using-console

Enregistrement du bot

Reportez-vous ici https://developers.line.biz/ja/docs/messaging-api/building-bot/

L'URL du webhook ne peut pas encore être définie, nous la définirons donc plus tard.

Définissez le jeton d'accès au canal et le secret du canal sur les variables d'environnement d'heroku

$ heroku config:set LINE_CHANNEL_SECRET=xxxxxxxxxxxxxxxxxx
$ heroku config:set LINE_CHANNEL_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Implémentation de LINE Bot

Ajoutez ce qui suit au Gemfile

gem 'line-bot-api'
$ bundle install

itinéraires ajoutés

routes.rb


Rails.application.routes.draw do
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
  post '/callback' => 'webhook#callback'
end

Créer un contrôleur

$ rails g controller webhook  

Tout d'abord, faisons-le selon l'exemple de https://github.com/line/line-bot-sdk-ruby

app/controllers/webhook_controller.rb


class WebhookController < ApplicationController
  require 'line/bot'

  def client
    @client ||= Line::Bot::Client.new { |config|
      config.channel_secret = ENV["LINE_CHANNEL_SECRET"]
      config.channel_token = ENV["LINE_CHANNEL_TOKEN"]
    }
  end

  def callback
    body = request.body.read

    signature = request.env['HTTP_X_LINE_SIGNATURE']
    unless client.validate_signature(body, signature)
      error 400 do 'Bad Request' end
    end

    events = client.parse_events_from(body)
    events.each do |event|
      case event
      when Line::Bot::Event::Message
        case event.type
        when Line::Bot::Event::MessageType::Text
          message = {
            type: 'text',
            text: event.message['text']
          }
          client.reply_message(event['replyToken'], message)
        when Line::Bot::Event::MessageType::Image, Line::Bot::Event::MessageType::Video
          response = client.get_message_content(event.message['id'])
          tf = Tempfile.open("content")
          tf.write(response.body)
        end
      end

      # Don't forget to return a successful response
      "OK"
    end
  end
end

Je le donnerai à heroku

$ git add .
$ git commit -m 'add controller'
$ git push heroku master

Reportez-vous ici et définissez l'URL affichée lors de l'exécution de heroku create comme URL Webhook. https://developers.line.biz/ja/docs/messaging-api/building-bot/

スクリーンショット 2020-09-14 0.57.13.png

Jusqu'à ce point, "Aum Return Bot" est terminé スクリーンショット 2020-09-14 0.22.25.png

Lire le fichier CSV

Le Bot créé jusqu'à présent n'est qu'un robot de retour de perroquet, nous allons donc lire les données et les rendre consultables.

Cette fois, je vais lire ces CSV スクリーンショット 2020-09-14 0.24.47.png De là Conversion du PDF obtenu en CSV chose

Créer un modèle pour le chargement du CSV

$ bundle exec rails g model store
Running via Spring preloader in process 76501
      invoke  active_record
      create    db/migrate/20200911182431_create_stores.rb
      create    app/models/store.rb
      invoke    test_unit
      create      test/models/store_test.rb
      create      test/fixtures/stores.yml

Modifier le fichier de migration

db/migrate/20200911182431_create_stores.rb


class CreateStores < ActiveRecord::Migration[6.0]
  def change
    create_table :stores do |t|
      t.string :store_association_name, comment: 'Nom de l'association du magasin'
      t.string :store_name, comment: 'Nom du magasin'
      t.string :postal_code, comment: 'Code postal'
      t.string :address, comment: 'adresse de rue'
      t.string :tel, comment: 'téléphone'
      t.string :lineup, comment: 'Traitement du nom du produit'
      t.timestamps
    end
  end
end

Effectuer la migration

$ bundle exec rake db:migrat

Maintenant que nous avons la place pour mettre les données, nous allons créer un programme pour prendre dans le CSV.

$ bundle exec rails g task import_csv
Running via Spring preloader in process 76763
      create  lib/tasks/import_csv.rake

lib/tasks/import_csv.rake


require 'csv'
namespace :import_csv do
  desc 'Importez la version CSV du PDF émis par Kawaguchi City Shopping Street'
  task :store, ['file_name'] => :environment do |_, args|
    #Obtenez le chemin du fichier à importer.
    #Puisqu'il y a probablement plusieurs noms de fichiers, spécifiez le nom de fichier lors de l'exécution de la tâche
    path = Rails.root.to_s + '/db/csv/' + args.file_name
    #Tableau pour stocker les données à importer
    list = []
    CSV.foreach(path, headers: true) do |row|
      list << {
          #Veuillez ajuster en fonction de l'en-tête du CSV à importer
          store_association_name: row['Nom de l'association du magasin'],
          store_name: row['Nom du magasin'],
          postal_code: row['Code postal'],
          address: row['adresse de rue'],
          tel: row['téléphone'],
          lineup: row['Traitement du nom du produit']
      }
    end
    puts 'Lancer le processus d'importation'
    begin
      Store.create!(list)
      puts 'Importation terminée'
    rescue => exception
      puts 'Échec de l'importation'
      puts exception
    end
  end
end

Vérifiez si la tâche est enregistrée

$ bundle exec rake -T
rake about                           # List versions of all Rails frameworks and the environment
rake action_mailbox:ingress:exim     # Relay an inbound email from Exim to Action Mailbox (URL and INGRESS_PASSWO...
rake action_mailbox:ingress:postfix  # Relay an inbound email from Postfix to Action Mailbox (URL and INGRESS_PAS...
rake action_mailbox:ingress:qmail    # Relay an inbound email from Qmail to Action Mailbox (URL and INGRESS_PASSW...
rake action_mailbox:install          # Copy over the migration
rake action_text:install             # Copy over the migration, stylesheet, and JavaScript files
rake active_storage:install          # Copy over the migration needed to the application
rake app:template                    # Applies the template supplied by LOCATION=(/path/to/template) or URL
rake app:update                      # Update configs and some other initially generated files (or use just updat...
rake db:create                       # Creates the database from DATABASE_URL or config/database.yml for the curr...
rake db:drop                         # Drops the database from DATABASE_URL or config/database.yml for the curren...
rake db:environment:set              # Set the environment value for the database
rake db:fixtures:load                # Loads fixtures into the current environment's database
rake db:migrate                      # Migrate the database (options: VERSION=x, VERBOSE=false, SCOPE=blog)
rake db:migrate:status               # Display status of migrations
rake db:prepare                      # Runs setup if database does not exist, or runs migrations if it does
rake db:rollback                     # Rolls the schema back to the previous version (specify steps w/ STEP=n)
rake db:schema:cache:clear           # Clears a db/schema_cache.yml file
rake db:schema:cache:dump            # Creates a db/schema_cache.yml file
rake db:schema:dump                  # Creates a db/schema.rb file that is portable against any DB supported by A...
rake db:schema:load                  # Loads a schema.rb file into the database
rake db:seed                         # Loads the seed data from db/seeds.rb
rake db:seed:replant                 # Truncates tables of each database for current environment and loads the seeds
rake db:setup                        # Creates the database, loads the schema, and initializes with the seed data...
rake db:structure:dump               # Dumps the database structure to db/structure.sql
rake db:structure:load               # Recreates the databases from the structure.sql file
rake db:version                      # Retrieves the current schema version number
rake import_csv:store[file_name]     #Importez la version CSV du PDF émis par Kawaguchi City Shopping Street
rake log:clear                       # Truncates all/specified *.log files in log/ to zero bytes (specify which l...
rake middleware                      # Prints out your Rack middleware stack
rake restart                         # Restart app by touching tmp/restart.txt
rake secret                          # Generate a cryptographically secure secret key (this is typically used to ...
rake stats                           # Report code statistics (KLOCs, etc) from the application or engine
rake test                            # Runs all tests in test folder except system ones
rake test:db                         # Run tests quickly, but also reset db
rake test:system                     # Run system tests only
rake time:zones[country_or_offset]   # List all time zones, list by two-letter country code (`rails time:zones[US...
rake tmp:clear                       # Clear cache, socket and screenshot files from tmp/ (narrow w/ tmp:cache:cl...
rake tmp:create                      # Creates tmp directories for cache, sockets, and pids
rake yarn:install                    # Install all JavaScript dependencies as specified via Yarn
rake zeitwerk:check                  # Checks project structure for Zeitwerk compatibility

Il semble que la tâche soit enregistrée.

Ensuite, installez le fichier CSV à importer. Créez un répertoire appelé csv sous db et placez-y le fichier CSV Si vous rencontrez des difficultés pour vous préparer, veuillez l'obtenir à partir de ici スクリーンショット 2020-09-14 0.37.04.png

Exécutez la commande rake pour capturer CSV

$ bundle exec rake import_csv:store['kawaguchi.csv']
Lancer le processus d'importation
Importation terminée

Assurez-vous d'avoir vraiment les données

$ bundle exec rails c
Running via Spring preloader in process 77369
Loading development environment (Rails 6.0.3.3)
irb(main):001:0> Store.all
  Store Load (0.7ms)  SELECT "stores".* FROM "stores" LIMIT $1  [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<Store id: 1, store_association_name: nil, store_name: "EK Auto Co., Ltd.", postal_code: "332-0025", address: "Haramachi 16-10", tel: "255-4980", lineup: "Inspection de voiture, tôlerie, réparation générale, voiture neuve, vente de voitures d'occasion", created_at: "2020-09-11 18:37:12", updated_at: "2020-09-11 18:37:12">, #<Store id: 2, store_association_name: nil, store_name: "ACE-LAB", postal_code: "332-0034", address: "Namiki 3-3-19", tel: "287-9465", lineup: "Salon de beauté", created_at: "2020-09-11 18:37:12", updated_at: "2020-09-11 18:37:12">...

Cela semble être inclus.

Ajouter une fonction de recherche simple au magasin

app/models/store.rb


class Store < ApplicationRecord
  def self.search(txt)
    Store.where(lineup: txt)
    .or(Store.where(store_association_name: txt))
    .or(Store.where(store_name: txt)).limit(5)
  end

  def self.get_search_message(txt)
    stores = Store.search(txt)
    message = []
    stores.each do |s|
      message << s.store_name
    end
    message << 'Aucun résultat trouvé' if message.blank?
    message.join(', ')
  end
end

app/controllers/webhook_controller.rb


class WebhookController < ApplicationController
  require 'line/bot'

  def client
    @client ||= Line::Bot::Client.new { |config|
      config.channel_secret = ENV["LINE_CHANNEL_SECRET"]
      config.channel_token = ENV["LINE_CHANNEL_TOKEN"]
    }
  end

  def callback
    body = request.body.read

    signature = request.env['HTTP_X_LINE_SIGNATURE']
    unless client.validate_signature(body, signature)
      error 400 do 'Bad Request' end
    end

    events = client.parse_events_from(body)
    events.each do |event|
      case event
      when Line::Bot::Event::Message
        case event.type
        when Line::Bot::Event::MessageType::Text
          message = {
            type: 'text',
            #Correct ↓
            text: Store.get_search_message(event.message['text'])
          }
          client.reply_message(event['replyToken'], message)
        when Line::Bot::Event::MessageType::Image, Line::Bot::Event::MessageType::Video
          response = client.get_message_content(event.message['id'])
          tf = Tempfile.open("content")
          tf.write(response.body)
        end
      end

      # Don't forget to return a successful response
      "OK"
    end
  end
end

C'est trop facile, mais donnons-le à heroku une fois car nous remplirons les détails dans la deuxième partie

$ git add .
$ git commit -m 'easy search'
$ git push heroku master

Vous devez faire ce que vous avez fait dans votre propre environnement dans l'environnement d'heroku.

$ heroku run rake db:migrate
$ heroku run rake import_csv:store['kawaguchi.csv']

Vous avez maintenant un bot qui renvoie les résultats de la recherche スクリーンショット 2020-09-14 0.48.39.png

Recommended Posts

Il n'y avait pas beaucoup d'informations sur le chèque-cadeau premium de la ville, j'ai donc essayé de le rendre plus facile à utiliser avec LINE Bot sans autorisation.
Facile à créer LINE BOT avec Java Servlet Partie 2: J'ai essayé des messages image et des modèles
À propos de la question pour laquelle j'étais accro à l'utilisation de hashmap
Je voulais faciliter la programmation JavaFX avec Spring Framework