【Alibaba Cloud】【Resource Orchestration Service】ROSを使用して、VPC、VSwitch、SG、ECSを作成する。

はじめに

Resource Orchestration Service(以下、ROS)とは中国のクラウドサービスであるAlibaba Cloudを監視するサービスです。
AWSでいうと CloudFormationと同様のサービスです。
一度、テンプレートを作成してしまえば、構築が簡単にできます。
また、リソース単位でを構成管理でき、うっかりしたインスタン立ち上げっぱなし、削除間違いを防げます。
今回はROSでの、ECS+VPC+VSwitch+SGのテンプレート作成方法を説明します。
ROSのコンソールの説明は公式サイトを参考にしてください。

ROSTemplate

---
ROSTemplateFormatVersion: '2015-09-01'
Description: " A simple ECS instance includes a security group. You only need to designate
  an imageID."

Parameters:
  prefix:
    Type: String
    AllowedPattern: "[a-zA-Z0-9]*"
    Description: Resource prefix(Alphabet/Number Only, No Space)
    Label: prefix
  InstanceType:
    Type: String
    Description: ECS Instance Type    #インスタンスタイプ
    AllowedValues:
    - ecs.t5-lc1m1.small
    - ecs.n4.small
    - ecs.sn1.medium
    - ecs.sn1ne.large
    Default: ecs.t5-lc1m1.small
    Label: ECS Instance Type
  SourceCidrIp:
    Type: String
    AllowedPattern: "(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])/32"
    Description: "Security Group Source ssh, Your Global Address (XXX.XXX.XXX.XXX/32)"
    Default:                # グローバルアドレス
    Label: SourceCidrIp
  KeyPairName:
    Type: String
    Description: "KeyPairName"
    Default:                # keypairName
    Label: KeyPairName  

# ROSでの成果物
Resources:
  vpc1:
    Type: ALIYUN::ECS::VPC
    Description: test_vpc
    Properties:
      CidrBlock: 10.0.0.0/8     #   VPC IP
      VpcName:
        Fn::Join:
        - "-"
        - - Ref: prefix
          - VPC
  VSwitch1:
    Type: ALIYUN::ECS::VSwitch
    Properties:
      VpcId:
        Ref: vpc1
      VSwitchName:
        Fn::Join:
        - "-"
        - - Ref: prefix
          - VSwitch
      Description: test_vswtich
      ZoneId: ap-northeast-1a       #   リージョンとゾーン
      CidrBlock: 10.1.0.0/24        #   VSitch IP
  sg1:
    Type: ALIYUN::ECS::SecurityGroup
    Properties:
      VpcId:
        Ref: vpc1
      SecurityGroupName:
        Fn::Join:
        - "-"
        - - Ref: prefix
          - sg
      Description: test_securitygrorup
      SecurityGroupIngress:         #   インバウンドの設定
      - PortRange: 22/22            #   ポートをレンジで設定
        Priority: '1'               #   優先度
        IpProtocol: tcp             #  プロトコル all/tcp/udp/icmp
        SourceCidrIp:
          Ref: SourceCidrIp
        NicType: intranet
      SecurityGroupEgress:          #  アウトバウントの設定
      - PortRange: "-1/-1"          # allまたはicmpは-1/-1を指定
        Priority: '1'
        IpProtocol: all             # プロトコル all/tcp/udp/icmp
        DestCidrIp: 0.0.0.0/0
        NicType: intranet
  ecs1:
    Type: ALIYUN::ECS::Instance
    Properties:
      InstanceName:
        Fn::Join:
        - "-"
        - - Ref: prefix
          - ECS
      HostName:
        Fn::Join:
        - "-"
        - - Ref: prefix
          - ECS
      Description: test ec2
      PrivateIpAddress: 10.1.0.1        # プライベートアドレス
      ZoneId: ap-northeast-1a
      InstanceType:
        Ref: InstanceType
      InstanceChargeType: PostPaid      # 従量課金
      SpotStrategy: NoSpot              # 通常の従量課金インスタンス
      ImageId: centos_7                 # OSのイメージを設定
      SystemDiskCategory: cloud_ssd     # ディスクのタイプ
      SystemDiskSize: '40'              # ディスクサイズ
      InternetMaxBandwidthIn: '5'       # 最大トラフィック
      InternetChargeType: PayByTraffic  # トラフィックで課金
      KeyPairName:
        Ref: KeyPairName
      VpcId:
        Ref: vpc1
      VSwitchId:
        Ref: VSwitch1
      SecurityGroupId:
        Ref: sg1

# ROSのOutPuts(出力)に表記する値の設定
Outputs:
  vpc1_id:
    Value:
      Fn::GetAtt:
      - vpc1
      - VpcId
    Description: test_vpc
  vswitch1_id:
    Value:
      Fn::GetAtt:
      - VSwitch1
      - VSwitchId
    Description: test_VSwitch
  sg1_id:
    Value:
      Fn::GetAtt:
      - sg1
      - SecurityGroupId
    Description: test_sg
  ecs1_id:
    Value:
      Fn::GetAtt:
        - ecs1
        - InstanceId
    Description: test_ecs
  ecs1_PrivateIp:
    Value:
      Fn::GetAtt:
        - ecs1
        - PrivateIp
    Description: test_ecs
  ecs1_PublicIp:
    Value:
      Fn::GetAtt:
        - ecs1
        - PublicIp
    Description: test_ecs

上記をAlibaba CloudのROSコンソールより、アップロードすれば、スタックが作成されます。

Parameter

Parameters:
  prefix:
    Type: String
    AllowedPattern: "[a-zA-Z0-9]*"
    Description: Resource prefix(Alphabet/Number Only, No Space)
    Label: prefix
  InstanceType:
    Type: String
    Description: ECS Instance Type    #インスタンスタイプ
    AllowedValues:
    - ecs.t5-lc1m1.small
    - ecs.n4.small
    - ecs.sn1.medium
    - ecs.sn1ne.large
    Default: ecs.t5-lc1m1.small
    Label: ECS Instance Type
  SourceCidrIp:
    Type: String
    AllowedPattern: "(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])/32"
    Description: "Security Group Source ssh, Your Global Address (XXX.XXX.XXX.XXX/32)"
    Default:                # グローバルアドレス
    Label: SourceCidrIp
  KeyPairName:
    Type: String
    Description: "KeyPairName"
    Default:                # keypairName
    Label: KeyPairName  

ROS内で使用するパラメータを設定します。各変数ごとに以下の設定します。
また、テンプレートパラメータの設定時に値を入力することができます。

項目 備考
Type 型を設定
AllowedPattern テンプレートパラメータの設定時の入力規則 を設定
AllowedValues ここに設定した値のみ、記入できる。テンプレートパラメータの設定時にドロップダウンメニューになる。
Default テンプレートパラメータの設定時のデフォルト値を設定
Label 任意のラベルを設定
Description 説明を入力

SourceCidrIpでは入力規則により、グローバルアドレスのみの入力を許可しています。

Resources(VPC

Resources:
  vpc1:
    Type: ALIYUN::ECS::VPC
    Description: test_vpc
    Properties:
      CidrBlock: 10.0.0.0/8     #   VPC IP
      VpcName:
        Fn::Join:
        - "-"
        - - Ref: prefix
          - VPC

Type でVPCのタイプである。ALIYUN::ECS::VPCを設定します。
PropertiesでVPCの細かい設定を記入しています。

      Fn::Join:
        - "-"
        - - Ref: prefix
          - VPC

VpcNameではVPCの名前を設定しますが関数を使用して、Parametarで設定した変数prefixとVPCを結合させています。 VPC名が<prefixで設定した値>-ECSになります。

Resources(VSwitch)

  VSwitch1:
    Type: ALIYUN::ECS::VSwitch
    Properties:
      VpcId:
        Ref: vpc1
      VSwitchName:
        Fn::Join:
        - "-"
        - - Ref: prefix
          - VSwitch
      Description: test_vswtich
      ZoneId: ap-northeast-1a       #   リージョンとゾーン
      CidrBlock: 10.1.0.0/24        #   VSitch IP

基本的にVPCと一緒です。ZoneIdでap-northeast-1a東京リージョンのZoneAをしています。
aを忘れないでください。

Resources(SecurityGroup)

  sg1:
    Type: ALIYUN::ECS::SecurityGroup
    Properties:
      VpcId:
        Ref: vpc1
      SecurityGroupName:
        Fn::Join:
        - "-"
        - - Ref: prefix
          - sg
      Description: test_securitygrorup
      SecurityGroupIngress:         #   インバウンドの設定
      - PortRange: 22/22            #   ポートをレンジで設定
        Priority: '1'               #   優先度
        IpProtocol: tcp             #  プロトコル all/tcp/udp/icmp
        SourceCidrIp:
          Ref: SourceCidrIp
        NicType: intranet
      SecurityGroupEgress:          #  アウトバウントの設定
      - PortRange: "-1/-1"          # allまたはicmpは-1/-1を指定
        Priority: '1'
        IpProtocol: all             # プロトコル all/tcp/udp/icmp
        DestCidrIp: 0.0.0.0/0
        NicType: intranet

SecurityGroupIngressはインバウンド側の設定です。
PortRange22/22、IpProtocol: tcpsshをのみ許可しています。
また、SourceCidrIpでグローバルアドレスのみにし、セキュアにしています。
SecurityGroupEgressはアウンバウンド側の設定です。
全て許可しています。

Resources(ECS)

  ecs1:
    Type: ALIYUN::ECS::Instance
    Properties:
      InstanceName:
        Fn::Join:
        - "-"
        - - Ref: prefix
          - ECS
      HostName:
        Fn::Join:
        - "-"
        - - Ref: prefix
          - ECS
      Description: test ec2
      PrivateIpAddress: 10.1.0.1        # プライベートアドレス
      ZoneId: ap-northeast-1a
      InstanceType:
        Ref: InstanceType
      InstanceChargeType: PostPaid      # 従量課金
      SpotStrategy: NoSpot              # 通常の従量課金インスタンス
      ImageId: centos_7                 # OSのイメージを設定
      SystemDiskCategory: cloud_ssd     # ディスクのタイプ
      SystemDiskSize: '40'              # ディスクサイズ
      InternetMaxBandwidthIn: '5'       # 最大トラフィック
      InternetChargeType: PayByTraffic  # トラフィックで課金
      KeyPairName:
        Ref: KeyPairName
      VpcId:
        Ref: vpc1
      VSwitchId:
        Ref: VSwitch1
      SecurityGroupId:
        Ref: sg1

ECSの設置をします。
色々設定項目がありますが、以下の設定は絶対に間違えないでください。
‘InstanceChargeType: PostPaid‘ 従量課金
‘InternetChargeType: PayByTraffic‘ トラフィックで課金
細かい設定は参考文献を元に決定してください。

Outputs

Outputs:
  vpc1_id:
    Value:
      Fn::GetAtt:
      - vpc1
      - VpcId
    Description: test_vpc
  vswitch1_id:
    Value:
      Fn::GetAtt:
      - VSwitch1
      - VSwitchId
    Description: test_VSwitch
  sg1_id:
    Value:
      Fn::GetAtt:
      - sg1
      - SecurityGroupId
    Description: test_sg
  ecs1_id:
    Value:
      Fn::GetAtt:
        - ecs1
        - InstanceId
    Description: test_ecs
  ecs1_PrivateIp:
    Value:
      Fn::GetAtt:
        - ecs1
        - PrivateIp
    Description: test_ecs
  ecs1_PublicIp:
    Value:
      Fn::GetAtt:
        - ecs1
        - PublicIp
    Description: test_ecs

ROSのコンソール画面の出力タブに表示する項目を設定します。
OutPutsは設定しなくても動作しますが、よく使用する項目(IPアドレスとか)を設定しておくことで、構成管理がしやすくなります。

    Value:
      Fn::GetAtt:
        - ecs1
        - PrivateIp

上記は、ECSのIPアドレスを関数により呼び出しています。
ECSとIPがOutPuts画面からわかるので、いちいちECSのコンソール画面に飛ばなくてもよくなります。

さいごに

ROSはCloudFormationと作成方法が似ているので、意外と導入は容易なのではないかと思います。
また、日本語のドキュメントががあるので、そちらを参考に作成するのが良いと感じました。

参考文献

   

【Alibaba Cloud】【Cloud Monitor】【Zabbix】Alibaba Cloudの監視サービスCloud Monitor をZabbixと連携する。

はじめに

Cloud Monitorとは中国のクラウドサービスであるAlibaba Cloudを監視するサービスです。 AWSでいうとCloudWatchと同様のサービスです。 ZabbixとCloud MonitorのAPIと連携することで、Zabbix画面上でAlibaba Cloudサービスを監視することができます。 今回はCloud MonitorのAPIを連携するためのスクリプトについて説明します。 最低限必要な情報のみ記載しているため、追加で監視したい場合は適宜追加してください。

事前準備

  • Zabbix構築済み。
  • Cloud Monitor にてサービスを監視済み。
  • Cloud Monitor の権限があるRAMロールを作成済み。

Cloud Monitor API連携スクリプト

#! /usr/bin/env python3
#coding=utf-8
# Alibaba Cloudのモジュールのインポート
from aliyunsdkcore.client import AcsClient
from aliyunsdkcms.request.v20190101.DescribeMetricListRequest import DescribeMetricListRequest

import json

# 監視対象
accessKeyId = 'accessKeyId'
accessSecretKey = 'accessSecretKey'
region = 'region'
instanceId = 'instanceId'

# 監視対象の取得
client = AcsClient(accessKeyId, accessSecretKey, region)

#### Cloud Monitor にリクエスト
request = DescribeMetricListRequest()
request.set_Dimensions("{'instanceId': '" + instanceId  + "'}")
request.set_accept_format('json')

# 監視対象サービス
request.set_Namespace('acs_vpn')
request.set_MetricName('net_rx.rate')

# リクエスト取得
response = client.do_action_with_exception(request)

# 監視項目の値を加工
Datapoint = json.loads(json.loads(response)["Datapoints"])[-1]
DatapointValue = Datapoint["Value"]

print(DatapointValue)

上記を作成し、Zabbixの外部スクリプト連携を行うとZabbixで監視することができます。 Zabbixの外部スクリプトのせっていについては、別の機会に説明したいと思います。 以下に、スクリプトの詳細な説明を記載します。

Alibaba Cloudのモジュールのインポート

from aliyunsdkcore.client import AcsClient
from aliyunsdkcms.request.v20190101.DescribeMetricListRequest import DescribeMetricListRequest

Cloud Monitor と連携するために必要なモジュール群です。環境によってはpip3 installでモジュールをインストールしてください。 また、 v20190101となっているように、バージョンによってはモジュールが動作しない可能性があり、頻繁に変わると思われます。

監視対象

accessKeyId = 'accessKeyId'
accessSecretKey = 'accessSecretKey'
region = 'region'
instanceId = 'instanceId'

事前に作成したRAMユーザーのアクセスキーとシークレットキーを記載してください。 また、リージョンと監視対象のインスタンスIDを記載してください。

Cloud Monitor にリクエストする値の設定

request = DescribeMetricListRequest()
request.set_Dimensions("{'instanceId': '" + instanceId  + "'}")
request.set_accept_format('json')
  • DescribeMetricListRequest()
    Cloud Monitor にリクエストするための変数を格納します。
  • request.set_Dimensions()
    監視インスタンスのIDを設定
  • request.set_accept_format()
    フォーマットを指定します。サンプルではJSONを指定しています。

Cloud Monitor にリクエストする値の設定(監視対象サービスとメトリック)

request.set_Namespace('acs_vpn')
request.set_MetricName('net_rx.rate')
  • request.set_Namespace()
    こちらで監視サービスを設定します。スクリプトの例ではVPN Gatewayです。 対象がECSの場合はacs_vpnacs_ecs_dashboardになります。
  • request.set_MetricName()
    こちらで監視メトリックを設定します。サンプルでは受信の帯域幅を取得しています。 サービスにより様々な値があります。
    監視サービスと監視メトリックを変更する場合はこちらの値を、適宜変更します。
    参考文献のプリセットメトリックのリファレンスを元に値を決めてください。

リクエスト取得

response = client.do_action_with_exception(request)

上記で、設定した値でCloud Monitor から値を取得します。

監視項目の値を加工

Datapoint = json.loads(json.loads(response)["Datapoints"])[-1]
DatapointValue = Datapoint["Value"]

print(DatapointValue)

リクエストした値には様々な値が格納されているためDatapointsのみ出力し、[-1]で最新の値のみを取得しています。
また、Valueのみ取得し、printで出力します。

さいごに

上記のスクリプトをZabbixの外部スクリプト連携にて、監視するとスクリプトの値を監視することができます。 Cloud Monitor のリクエストにセットする値はタイムスタンプなど、ほかにも様々な値があります。
参考文献のDescribeMetricListをもとに値を決めてください。

参考文献

【PowerShell】Powershellの起動時にログを生成するショートカット作成

はじめに

Cloud Monitorとは中国のクラウドサービスでであるAlibaba Cloudを監視するサービスです。 AWSでいうとCloudWatchと同様のサービスです。 ZabbixとCloud MonitorのAPIと連携することで、Zabbix画面上でAlibaba Cloudサービスを監視することができます。 今回はCloud MonitorのAPIを連携するためのスクリプトについて説明します。 最低限必要な情報のみ記載してないため、追加で監視したい場合は適宜追加してください。

事前準備

  • Zabbix構築済み。
  • Cloud Monitor にてサービスを監視済み。
  • Cloud Monitor の権限があるRAMロールを作成済み。

Cloud Monitor API連携スクリプト

#! /usr/bin/env python3
#coding=utf-8
# Alibaba Cloudのモジュールのインポート
from aliyunsdkcore.client import AcsClient
from aliyunsdkcms.request.v20190101.DescribeMetricListRequest import DescribeMetricListRequest

import json

# 監視対象
accessKeyId = 'accessKeyId'
accessSecretKey = 'accessSecretKey'
region = 'region'
instanceId = 'instanceId'

# 監視対象の取得
client = AcsClient(accessKeyId, accessSecretKey, region)

#### Cloud Monitor にリクエスト
request = DescribeMetricListRequest()
request.set_Dimensions("{'instanceId': '" + instanceId  + "'}")
request.set_accept_format('json')

# 監視対象サービス
request.set_Namespace('acs_vpn')
request.set_MetricName('net_rx.rate')

# リクエスト取得
response = client.do_action_with_exception(request)

# 監視項目の値を加工
Datapoint = json.loads(json.loads(response)["Datapoints"])[-1]
DatapointValue = Datapoint["Value"]

print(DatapointValue)

上記を作成し、Zabbixの外部スクリプト連携を行うとZabbixで監視することができます。 Zabbixの外部スクリプトのせっていについては、別の機会に説明したいと思います。 以下に、スクリプトの詳細な説明を記載します。

 Alibaba Cloudのモジュールのインポート

from aliyunsdkcore.client import AcsClient
from aliyunsdkcms.request.v20190101.DescribeMetricListRequest import DescribeMetricListRequest

Cloud Monitor と連携するために必要なモジュール群です。環境によってはpip3 installでモジュールをインストールしてください。 また、 v20190101となっているように、バージョンによってはモジュールが動作しない可能性があり、頻繁に変わると思われます。

監視対象

accessKeyId = 'accessKeyId'
accessSecretKey = 'accessSecretKey'
region = 'region'
instanceId = 'instanceId'

事前に作成したRAMユーザーのアクセスキーとシークレットキーを記載してください。 また、監視対象のリージョンのインスタンスIDを記載してください。

⃣Cloud Monitor にリクエストする値の設定

request = DescribeMetricListRequest()
request.set_Dimensions("{'instanceId': '" + instanceId  + "'}")
request.set_accept_format('json')
  • DescribeMetricListRequest() Cloud Monitor にリクエストする値を設定します。
  • request.set_Dimensions() 監視インスタンスのIDを設定
  • request.set_accept_format() フォーマットを指定。デフォルトでJSONで取得します。

Cloud Monitor にリクエストする値の設定(監視対象サービスとメトリック)

request.set_Namespace('acs_vpn')
request.set_MetricName('net_rx.rate')
  • request.set_Namespace() こちらで監視サービスを設定します。スクリプトの例ではVPN GateWayです。 対象がECSの場合はacs_vpnacs_ecsになります。
  • request.set_MetricName() こちらで監視メトリックを設定します。サンプルでは受信の帯域幅を取得しています。 サービスにより様々な値があります。
    監視サービスと監視メトリックが変更する場合はこちらの値を、適宜変更します。

リクエスト取得

response = client.do_action_with_exception(request)

上記で、設定した値でCloud Monitor から値を取得します。

 監視項目の値を加工

Datapoint = json.loads(json.loads(response)["Datapoints"])[-1]
DatapointValue = Datapoint["Value"]

print(DatapointValue)

リクエストした値には様々な値が格納されているためDatapointsのみ出力し、[-1]で最新の値のみを取得している。
また、["Value"]のみ取得し、printで出力する。

さいごに

上記のスクリプトをZabbixの外部スクリプト連携にて、監視するとスクリプトの値を監視することができます。

参考文献

【GAS】【LINE】GASでLINEBOTを作成する。(その2)

GASでLINEBotを作成

本記事は前回の続きです。 shiojojo.hatenablog.com 前回の約束通り、中身について解説したいと思います。

コード

前回説明したコードです。LINEにメッセージを送信すると、いついかなる時も「いつもよろしく」と返信してくれます。

// LINE Bot のアクセストークン
var CHANNEL_ACCESS_TOKEN = '<発行したアクセストークン>'

// HTTPリクエスト POST  
var linePost = 'https://api.line.me/v2/bot/message/reply';

function doPost(e) {
  //送信するメッセージを作成
  
  // Jsonにパース
  var json = JSON.parse(e.postData.contents);
  // 返信するためのトークンを取得
  var replyToken = json.events[0].replyToken;

  
  // メッセージをLINEに送信  
  UrlFetchApp.fetch(linePost, {
    'headers': {
      'Content-Type': 'application/json; charset=UTF-8',
      'Authorization': 'Bearer ' + CHANNEL_ACCESS_TOKEN,
    },
    'method': 'post',
    'payload': JSON.stringify({
      'replyToken': replyToken,
      'messages': [{'type': 'text', 'text': 'いつもよろしく。'}]
    }),
  });
  return ContentService.createTextOutput(JSON.stringify({'content': 'post ok'})).setMimeType(ContentService.MimeType.JSON);
}

細かく説明したいと思います。 ターゲットはGASを片手間でやってて、詳しい説明はいらない向けです。 もっと詳しく知りたい方は力が及ばなくて、すみません。

アクセストーク

// LINE Bot のアクセストークン
var CHANNEL_ACCESS_TOKEN = '<発行したアクセストークン>'

これはLINBBotで発行したアクセストークンを変数として格納します。
こういうもんだと理解してください。 ただ、Gitで管理する場合はアクセストークンは別ファイルにて管理しましょう。
隠すべき情報はきちんと隠しましょう。

replyのHTTPリクエス

// HTTPリクエスト POST  
var linePost = 'https://api.line.me/v2/bot/message/reply';

リプライのメッセージを作成するときは上記のHTTPSにPOSTします。 こういうものだと理解しましょう。 もっと詳しく知りたい方は以下のサイトにて公式ドキュメントがあります。 developers.line.biz
プッシュなど状況に応じて、変更しましょう。

メッセージの作成

LINEBotのメイン処理です。
Lineにメッセージが送信されると、doPost(e)の処理されメッセージが返信されます。
この中身をいじくりまわすと、メッセージを連投したり、画像を送ったりもできます。

function doPost(e) {
  //送信するメッセージを作成
  
  // Jsonにパース
  var json = JSON.parse(e.postData.contents);
  // 返信するためのトークンを取得
  var replyToken = json.events[0].replyToken;

  
  // メッセージをLINEに送信  
  UrlFetchApp.fetch(linePost, {
    'headers': {
      'Content-Type': 'application/json; charset=UTF-8',
      'Authorization': 'Bearer ' + CHANNEL_ACCESS_TOKEN,
    },
    'method': 'post',
    'payload': JSON.stringify({
      'replyToken': replyToken,
      'messages': [{'type': 'text', 'text': 'いつもよろしく。'}]
    }),
  });
  return ContentService.createTextOutput(JSON.stringify({'content': 'post ok'})).setMimeType(ContentService.MimeType.JSON);
}

この中身も一応説明します。

JSONにパース

var json = JSON.parse(e.postData.contents);

上記でJSONにパースします。
JSONにパースしないと送れないので、そういうもんだと思ってください。

リプライトークンの取得

var replyToken = json.events[0].replyToken;

リプライ用のトークンを取得します。 メッセージを受けた先がわからないと、どこにリプライを送ればわからないので取得します。 とういうことで、そういうものだと理解してください。

メッセージの送信

以下の処理でメッセージを送信します。 messagesの中身以外は基本的に変更の必要はありません。

  UrlFetchApp.fetch(linePost, {
    'headers': {
      'Content-Type': 'application/json; charset=UTF-8',
      'Authorization': 'Bearer ' + CHANNEL_ACCESS_TOKEN,
    },
    'method': 'post',
    'payload': JSON.stringify({
      'replyToken': replyToken,
      'messages': [{'type': 'text', 'text': 'いつもよろしく。'}]
    }),
  });

メッセージの中身

以下の中で送るメッセージを内容を送ります。

'messages': [{'type': 'text', 'text': 'いつもよろしく。'}]

配列で管理されており、配列の中身はJSONになっております。
個々の中身を変更することで、いろんなメッセージを送れます。

  • 連投する場合
'messages': [{'type': 'text', 'text': 'いつもよろしく。'} , {'type': 'text', 'text': 'いつもよろしく。'}]

連投する場合はJSONを続けて書きます。

  • 画像を送る場合
'messages': [{ "type": "image","originalContentUrl": <画像のURL> ,"previewImageUrl": <画像のURL>}]

上記のようにいろいろへんこうすることで、画像メッセージを送ることができます。

もっと詳しく知りたい方は、やはり公式ドキュメントです。 developers.line.biz
適宜変更しましょう。

送信情報の取得

以下をコードに書くと、LINEのメッセージを送信したユーザーの情報を取得できます。

  • ユーザーのラインメッセージ
var userMessage = json.events[0].message.text;  

ユーザーが送ってきたメッセージを取得できます。

  • ユーザーのユーザーID
var sourceUserId = json.events[0].source.userId;

メッセージを送ってきたユーザーのIDを取得できます。 LINEではユーザーを一意のIDで管理しており、ユーザーごとにメッセージを返信する内容を変更するときに使えますね。

  • ユーザーのグループID
var sourceGroupId = json.events[0].source.groupId;

LINEBOTがグループラインでメッセージを受けとったときのグループIDを取得できます。

まとめ

基本的なことは説明したつもりです。
あとは状況に応してメッセージを取得し、返信しましょう。
GASを利用して、スプレッドシートに記載したメッセージなども送ることができます。

後もっと詳しく知りたい方は、やはり公式ドキュメントをみることです。 developers.line.biz

【GAS】【LINE】GASでLINEBOTを作成する。(その1)

GASでLINEBotを作成

LINE DevelopersのMessaging APIを使用してBotを作成します。
LINEBotがスプレッドシートに記載している内容を返信してくれます。
また、メッセージの内容をスプレッドシートに記載してくれたります。
画像も返信してくれるので、非常に便利です。
私は大喜利のお題を出してくれる大喜利君というLINEBotを作成しました。
「お題」とメッセージを投稿すると、スプレッドシートに記載したお題をだしてくれます。さらに私が回答を投稿するとスプレッドシートに記録してくれます。
また、「写真」とメッセージを投稿すると写真でお題を出してくれます。写真で一言みたいな感じですね。 LINEBOTのおかげで、非常に人生が豊かになりました。
あなたも人生のいろどりを豊かにするためにLINEBotを作成しましょう。

LINE Developers の料金に関して

LINEの料金はフリー、ベーシック、プロの3種類があります。
昔はいくつかあったみたいですが、公式アカウントが統合した結果3つになったみたいです。
以下に、料金体系を記載しておきます。今回はフリーで作成するので、無料で実装できます。
基本的に大規模で使用しない限りは無料で十分だと思います。

at.line.me

今回すること

今回は、「いつもよろしく」と言い返してくれるBotを作成します。 コードの中身に関しては次回以降に説明しようと思います。

LINE DevelopersのMessaging APIの登録

以下、公式サイトの手順で、LINE DevelopersのMessaging APIの登録をします。

developers.line.biz

GASのコードの設定

スプレッドシートから、スクリプトエディタを起動して、以下のコードを記載してください。アクセストークンは後で設定します。

// LINE Bot のアクセストークン
var CHANNEL_ACCESS_TOKEN = '<発行したアクセストークン>'

// HTTPリクエスト POST  
var linePost = 'https://api.line.me/v2/bot/message/reply';

function doPost(e) {
  //送信するメッセージを作成
  
  // Jsonにパース
  var json = JSON.parse(e.postData.contents);
  // 返信するためのトークンを取得
  var replyToken = json.events[0].replyToken;

  
  // メッセージをLINEに送信  
  UrlFetchApp.fetch(linePost, {
    'headers': {
      'Content-Type': 'application/json; charset=UTF-8',
      'Authorization': 'Bearer ' + CHANNEL_ACCESS_TOKEN,
    },
    'method': 'post',
    'payload': JSON.stringify({
      'replyToken': replyToken,
      'messages': [{'type': 'text', 'text': 'いつもよろしく。'}]
    }),
  });
  return ContentService.createTextOutput(JSON.stringify({'content': 'post ok'})).setMimeType(ContentService.MimeType.JSON);
}

Webアプリケーションとして導入

  1. 上段から [公開] -> [Webアプリケーションとして導入] を選択します。
  2. ポップアップから、 [Who has access to the app:] の項目から[anyone, even anonymouse]を選択します。あとはデフォルトでおっけいです
  3. Deployを押下します。
  4. するとまたポップアップがでるので[許可を確認]を押下します。
  5. するとまたポップアップがでるので(しつこいですね)アカウント選択します。
    環境によっては許可されていないサイトなど出てきますが、基本的には全部OKで問題ないです。
  6. 最後に[Current web app URL:]に記載されているURLをメモっておき、OKを押下します。 こちらをLINEのWebhookの宛先に指定します。

Webhookの利用

  1. LINEのDevelopersから先ほど作成したチャネル設定に移動します。
  2. Messaging API設定を押下します。
  3. Webhook URLに先ほど[Current web app URL:]に記載されていたURLを設定します。  
  4. Webhookの利用を有効化します。
  5. チャネルアクセストークンの発行を押下し、トークンを発行します。アクセストークンをメモします。

アクセストークンの設定

  1. 先ほどメモしたアクセストークンをGASの変数CHANNEL_ACCESS_TOKENに設定するため、<発行したアクセストークン>にを書き換えます。
  2. 上段から [公開] -> [Webアプリケーションとして導入] を選択します。
  3. [Project version:]を[New]に変更し、更新を押下します。

Project version更新しないとGASの変更が反映されないので、スクリプトを変更するたびに実施してください。

LINE公式アカウント機能(お好みで)

Messaging API設定から設定します。
LINE公式アカウント機能について説明します。

  • グループ・複数人チャットへの参加を許可する
    有効にするとライングループに参加できます。しないといくら誘ってもグループに参加してくれません。人見知りBOTのままです。 グループラインに参加させるならこの設定は有効化してください。

  • 応答メッセージ
    無効にすると自動的に変身されるメッセージが無効化されます。
    デフォルトでは自動的に謝罪のメッセージをBOT君が送ります。うるさいんで無効化することをお勧めします。

  • あいさつメッセージ
    グループの参加時など始めた会話するときに送られるメッセージを無効にできます。
    用途によって、使い分けてください。

LineBotを友達に登録

  1. LINE DeveloperのMessaging API設定にあるQRコードを読み取り友達に登録します。
  2. Botに直接メッセージまたはグループにメッセージを送信します。

すると、いつもよろしくと返信してくれます。
すごい簡単ですね。
私はBOTをを友達に登録するのに時間がかかってしまいました。
QRコードで友達登録できるなんて初めて知りました。友達が少ないとこういうところで苦労するんですね。

次回以降はスクリプトの中身について解説できたらなと思っています。

【GAS】【Git】GASをGitで管理する方法。

Google Apps Script (以下、GASとする。)はWeb上の開発環境に保存されており、 バージョン管理がしにくく、保存が消えてしまうのではと思いの方も中にはいるのではないのでしょうか。
私は、ぼーっとしてて削除したことがあり、そのあと、お酒に逃げたことがあります。 今回の方法を使用すると、Gitで管理でき、ローカル環境で開発もできるので便利です。

claspとは

claspとは、GASを操作できるCLIツールらしい。 詳しくはよく知らないです。 ローカル環境にプロジェクトをクローンするために使用します。

claspインストール

1.npmのインストール

Node.jsのパッケージ管理ツール、claspをインストールするために使用する。
以下のサイトからNodeJSをインストールします。 nodejs.org

2.claspをインストールする。

以下のコマンドでclaspをインストールします。

npm i @google/clasp -g

3.claspを有効化する。

claspを使用できるようにGoogle Apps Script APIを押下し、ONに変更する。 script.google.com

4.claspにログイン

以下のコマンドでclaspにログインする。

clasp login

ログインするとWebブラウザが立ち上がるので、権限を確認して許可する。

gitで管理

1.クライアントにGitをインストールする。

クライアントの端末にGitをインストールしておく。

2.プロジェクトをクローンする。

プロジェクトの上部にある [ファイル] -> [プロジェクトのプロパティ] ->  [スクリプト ID] をコピーする。 以下のコマンドで対象のプロジェクトをクローンします。

clasp clone  [スクリプト ID]

すると、ローカルにプロジェクトに紐づくスクリプトファイルがクローンされます。 ここまですると、ローカル環境で開発することができます。

ちなみに、ファイル名に/を入れるとローカルではディレクトリ以下にファイルが保存されます。

  • 【例】 GAS上の名前がsrc/test.gsの場合
    ローカル環境ではsrcディレクトリ配下にtest.gsが作成されます。
    アカウントやパスワード情報の大事なファイルをディレクトリに分けて管理する場合などに便利です。

3.Gitで管理しないファイルを.gitignoreに記載する。

claspでクローンすると以下、2つのファイルが生成されます。

  • .clasp.json
    スクリプトIDが記載されてる。

  • appsscript.json
    アクセス権などの情報が記載されてる。

Gitで管理する場合は好ましくないので .gitignore を作成し、記載してください。

clasp.json
appsscript.json

4.GitHubにプロジェクトを作成し、ファイルをコミットする。

これで、GASをGitでバージョン管理できます。

Google Apps Script 入門 #1

Google Apps Script とは

Googleスプレッドシートで動かせるスクリプトの事。 通称GASっていうらしい。
ググるときはGASの方が引っかかるような気がする。
ExcelでいうVBAみたいなもん。
Excelと違って、クライアントにインストールしないので、いつでも実行できるのがいいところ。
あと、JavaScriptで書けるのでVBAより学習コストが低いかもしれない。
私はVBAから入った人なので、そういった人向けです。

使い方

ここでは、スプレッドシートからの使い方を説明します。

GAS起動

スプレッドシートをひらいて ツール -> スクリプトエディタ を選択する。 するとVBAみたいな開発環境が出てきます。

Hello world

初めてなので、Hello Worldをしてみる。セルに入れるのはキャプチャが面倒なので、今回はログに出力する。 以下のコードを入れてます。

function myFunction() {
  Logger.log('Hello World');
}

保存できないと実行できないのでファイルを保存します。この辺はVBAと異なる。 保存した後、再生ボタンみたいなやつが実行なので、押下して実行します。

何も起こってないようですが、ログにHello Worldと出力されてるのでログを確認します。 ログはCtrl+Enterで確認できます。
f:id:shiojojo:20191117151617j:plain
すると、上記のようにHello Worldとログに表示されることがわかります。

まとめ

VBAができるならGASも問題なくできると思った。書き方は全く違うけどね。