rkdora's Blog

GAS (Google App Script) で WEBサイトを公開する

この記事では、GAS (Google App Script) で WEBサイトを公開する方法を紹介する。

demoはここをクリック

HelloWorldを表示する

  1. GASを用意する

f:id:rkdora:20200708200841p:plain

  1. コード.gsにdoGet関数を書く

f:id:rkdora:20200708201025p:plain

コード.gs

function doGet() {
  return HtmlService.createHtmlOutputFromFile(p); 
}
  1. index.htmlを用意する

f:id:rkdora:20200708201235p:plainf:id:rkdora:20200708201241p:plainf:id:rkdora:20200708201247p:plain

index.html

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>
    <h1>Hello World!</h1>
  </body>
</html>
  1. 公開する

f:id:rkdora:20200708201432p:plain

f:id:rkdora:20200708201438p:plain

f:id:rkdora:20200708201445p:plain

f:id:rkdora:20200708201452p:plain

f:id:rkdora:20200708201500p:plain

なんか上の方に邪魔なバーが表示される。

ページ遷移の実装

画面遷移の方法がちょっと特殊。 URLに持たせたパラメータを用いて表示するHTMLファイルを切り替える。

コード.gs

function doGet(e) {
  let p = e.parameter.p;
  let routes = ['index', 'cat'];
  
  if (routes.indexOf(p) != -1) {
    return HtmlService.createHtmlOutputFromFile(p);
  } else {
    return HtmlService.createHtmlOutputFromFile('index');
  }  
}

index.html

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>
    <h1>Hello World!</h1>
    <a href="https://script.google.com/macros/s/AKfycby8_E9GjqpntLmf27N7O-SVjNGGaLbLStWQUNCTcUagHQ76ZVs/exec?p=cat">cat.htmlへ移動</a>
  </body>
</html>

cat.html

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>
    <h1>I love Cat.</h1>
    <img src="https://1.bp.blogspot.com/-5JQicjad4tU/XQNunlpcxXI/AAAAAAABTJk/GBfBbe-LlGUV5KW5tIFB-xRA3OBl7kjtACLcBGAs/s350/pet_natsukareru_cat_man.png"/>
    <a href="https://script.google.com/macros/s/AKfycby8_E9GjqpntLmf27N7O-SVjNGGaLbLStWQUNCTcUagHQ76ZVs/exec?p=index">戻る</a>
  </body>
</html>

Project versionをNewにするのを忘れずに! f:id:rkdora:20200708201739p:plain f:id:rkdora:20200708201745p:plain f:id:rkdora:20200708201751p:plain

Bootstrap導入

getbootstrap.com

コード.gsは変わらない。

index.html

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">

    <title>MyPage</title>
  </head>
  <body>
    <nav class="navbar navbar-dark bg-dark">
      <div class="container">
        <a class="navbar-brand" href="https://script.google.com/macros/s/AKfycby8_E9GjqpntLmf27N7O-SVjNGGaLbLStWQUNCTcUagHQ76ZVs/exec?p=index">MyPage</a>
      </div>
    </nav>
  
    <div class="container">
      <h1>Hello World!</h1>
      <a href="https://script.google.com/macros/s/AKfycby8_E9GjqpntLmf27N7O-SVjNGGaLbLStWQUNCTcUagHQ76ZVs/exec?p=cat">cat.htmlへ移動</a>
    </div>
    
    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script>
  </body>
</html>

cat.html

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">

    <title>MyPage</title>
  </head>
  <body>
    <nav class="navbar navbar-dark bg-dark">
      <div class="container">
        <a class="navbar-brand" href="https://script.google.com/macros/s/AKfycby8_E9GjqpntLmf27N7O-SVjNGGaLbLStWQUNCTcUagHQ76ZVs/exec?p=index">MyPage</a>
      </div>
    </nav>
    
    <div class="container">
      <h1>I love Cat.</h1>
      <img src="https://1.bp.blogspot.com/-5JQicjad4tU/XQNunlpcxXI/AAAAAAABTJk/GBfBbe-LlGUV5KW5tIFB-xRA3OBl7kjtACLcBGAs/s350/pet_natsukareru_cat_man.png"/>
      <a href="https://script.google.com/macros/s/AKfycby8_E9GjqpntLmf27N7O-SVjNGGaLbLStWQUNCTcUagHQ76ZVs/exec?p=index">戻る</a>
    </div>
    
    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script>
  </body>
</html>

f:id:rkdora:20200708202557p:plain f:id:rkdora:20200708202604p:plain

GASを使ってサイトを作ることで、gmailスプレッドシートの情報を扱うことができて便利(主に社内向けサイトに使われているみたい)

VueでWebアプリを爆速デプロイしていく

目的

Vueでfirebaseにデプロイする方法を残す

前提

Vue cliの環境は整っている

流れ

  1. ローカルでVueプロジェクト作成
  2. firebase console上でプロジェクト作成
  3. デプロイ準備
  4. デプロイ

    1. ローカルでVueプロジェクト作成

    f:id:rkdora:20200623235635p:plain f:id:rkdora:20200623235654p:plain 何も考えずEnter

f:id:rkdora:20200623235728p:plain 成功

f:id:rkdora:20200623235756p:plain 移動し、起動する

f:id:rkdora:20200623235824p:plain この画面が出てきたらよし

これはスキップしていい。 f:id:rkdora:20200623235907p:plain とりあえず、ボタンをクリックしたら新しいタブが100個生成されるWebアプリにした。

2. firebase console上でプロジェクト作成

firebase consoleにアクセスする。 f:id:rkdora:20200624000147p:plain プロジェクトを追加

f:id:rkdora:20200624000219p:plain 好きな名前

f:id:rkdora:20200624000253p:plain f:id:rkdora:20200624000315p:plainf:id:rkdora:20200624000335p:plain 画面中央の「ウェブ」を選択

f:id:rkdora:20200624000402p:plain 好きな名前(URLになる)

3. デプロイ準備

f:id:rkdora:20200624000424p:plain ターミナルで、npm install -g firebase-toolsする(過去にしてればスキップして良い)

f:id:rkdora:20200624000438p:plain firebase login して、ログインする。

firebase initする。 f:id:rkdora:20200624000721p:plain 下矢印キーで移動し、hostingを選択(スペースで選択できる)。 その後、Enterキー。

f:id:rkdora:20200624000812p:plain please select optionでは、Use an existing projectを選択

その後、firebase上で作成したプロジェクト名を選択する

f:id:rkdora:20200624001004p:plain 一番注意するポイント

distと入力し、Enter

f:id:rkdora:20200624001100p:plain f:id:rkdora:20200624001133p:plainf:id:rkdora:20200624001144p:plain

4. デプロイ

f:id:rkdora:20200624001314p:plain npm run build

firebase deploy

これで表示されるURLをコピーしてブラウザで開くと、動作確認できる。


おまけ

www.youtube.com

f:id:rkdora:20200624001429p:plain 自分の場合はこの画面

f:id:rkdora:20200624001526p:plain ポップアップを許可してあげると。。。

f:id:rkdora:20200624001612p:plain

こちらから是非どうぞ( ̄ー ̄人)♪

chrome-tab-challenge

github.com

Ubuntu入れたらすぐにやること集

環境によってやらなくていいものもあり。

Ubuntu18.04

アップデート

sudo apt update && sudo apt upgrade -y
sudo apt-get update && sudo apt-get upgrade -y

フォルダ英語化

LANG=C xdg-user-dirs-gtk-update
ログアウトする

NVIDIAドライバ

sudo ubuntu-drivers devices
モデル名が正しいか確認
sudo ubuntu-drivers autoinstall

無線LAN子機認識させる

sudo apt install git dkms
git clone https://github.com/aircrack-ng/rtl8812au.git
make -C ./rtl8812au/
cd rtl8812au
sudo sh dkms-install.sh

windowsと9時間ずれる問題

timedatectl set-local-rtc 1

Chromeダウンロード

https://www.google.com/intl/ja_jp/chrome/

git

sudo apt install git

github:ssh

mkdir ~/.ssh cd ~/.ssh
ssh-keygen -t rsa
cat id_rsa.pub
Githubに公開鍵を登録
ssh -T git@github.com

Vim

sudo apt install vim

terminator

sudo apt install terminator

gimp

sudo add-apt-repository ppa:otto-kesselgulasch/gimp
sudo apt install gimp

atom

sudo add-apt-repository ppa:webupd8team/atom
sudo apt install atom

gufw (ファイアウォール)

sudo apt install gufw

openでフォルダを開く

vi ~/.bashrc
以下を追記
alias open='xdg-open'
source ~/.bashrc

MP4

sudo apt-get install ubuntu-restricted-extras
sudo apt-get install ffmpeg

Python (pyenv + pipenv)

sudo apt update && sudo apt install -y --no-install-recommends build-essential libffi-dev libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev git
git clone https://github.com/pyenv/pyenv.git ~/.pyenv
touch ~/.bash_profile
echo -e "# pyenv paths" >> ~/.bash_profile
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
echo 'eval "$(pyenv init -)"' >> ~/.bash_profile
source ~/.bash_profile
pyenv -v
pyenv install 3.8.2
pyenv global 3.8.2
pip install pipenv
python -V
mkdir 37
cd 37
pipenv install --python 3.7
pipenv shell

Node.js

sudo apt install -y nodejs npm
sudo npm install n -g
sudo n stable
sudo apt purge -y nodejs npm

ターミナルを立ち上げ直す。

参考:

Ubuntuに最新のNode.jsを難なくインストールする - Qiita

Ubuntu ログインループ問題(NVIDIA)

rkdora.hatenablog.com

昨日デスクトップPCにUbuntuを入れたのだが、

問題発生。

ログインできない。

パスワードを忘れたとかではないんよ。

Caps Lockが悪さしてるんかな〜?と最初は思っていたけど、CUIモード(Ctrl + Alt +F2)ならログインできるしどうも違うらしい。

色々調べてみてわかったが、どうやらログインループという現象らしい。

GPUNVIDIA特有の問題みたいだ。(自分のモデルは、GEFORCE GTX 1050Ti)

色々な記事を見て色々な方法でドライバを入れまくったがうまくいかず、しまいにはログイン画面すら開かなくなってしまった。

ということで、インストールからやり直し。

無線LAN子機の認識に関して、記事を残しておいて本当に良かった。

結局、超かんたんにNVIDIAのドライバを入れることができたので、残しとく。

sudo ubuntu-drivers devices
モデル名が正しいか確認
sudo ubuntu-drivers autoinstall
sudo reboot
nvidia-smiでこんな表示になったら成功

f:id:rkdora:20200508213618p:plain

またインストールしなおすことになりませんように(@_@)

デスクトップPCにUbuntu環境を構築したら無線LAN対応させるのに苦労したお話

デスクトップPCにUbuntuを入れた

デスクトップPCの特徴

SSDWindows、HHDはUbuntuデュアルブートする

たまたまUbuntu18.04はUSBに入れて保管していたため、Ubuntu20.04ではなく18.04でいくことに。
HHDをフォーマット。
BIOSからBOOTで、USBを一番上に。 USBに入り、指示されるがままHDDにUbuntuをインストール(ちゃんとSwapもつくったよ)。 無事、成功。

Ubuntuをネットにつなげたい

さあ、初期設定するぞーと思ったら、、、、

ネットにつながらない。

困った。

そこから色々調べて、無事に解決するまでの手順を残しておく(クッソ沼った)。

UbuntuWindowsノートPCを有線LANでつないでネットワーク接続をおこなう

無線LAN子機をUbuntuに認識させるためには、一旦ネットにつないで必要なものをインストールしないといけないっぽかった。

そのため、Wi-Fi → ノートPC(Windows) →有線LAN → デスクトップPC(Ubuntu)という構成にする。

  1. LANケーブルでノートPCとデスクトップPCをつなぐ
  2. Windows側でブリッジする

    1. コントロールパネル > ネットワークと共有センター > アダプタの設定の変更
    2. 無線LANと有線LANのネットワークカードを選択した状態で右クリックして、開いたメニューから「ブリッジ接続」を選択
  3. Windows側でenableにする

    1. 管理者としてコマンドプロンプトを起動
    2. netsh bridge show adapter
    3. netsh bridge set adapter 1 enable
    4. netsh bridge set adapter 2 enable
    5. netsh bridge show adapter
      disableからenableになればよし。

Ubuntu無線LAN子機を認識させる

  1. sudo apt install git dkms
  2. git clone https://github.com/aircrack-ng/rtl8812au.git
  3. make -C ./rtl8812au/
  4. cd rtl8812au
  5. sudo sh dkms-install.sh

無線LAN子機が認識された。 万歳(^^♪


次は、20にアップデートかなあ

Vue.js + Firebase + GitHub認証

JS-proを始めて1週間のVue.js初心者です。

今回は、タイトルにあるように「Vue.js + Firebase + GitHub認証」WEBアプリを実装していきます。

開発環境は、Ubuntu18.04LTS です。

流れは以下の通りです。

さあ、やっていきましょう。

Vue のプロジェクトを作成

  1. npm install -g @vue/cli
  2. vue create github-auth ⚠ここでは、アプリ名をgithub-authにしています。
  3. cd github-auth/
  4. npm run serve ブラウザからlocalhost:8080 にアクセスして、この画面が出てくれば成功 f:id:rkdora:20200506130128p:plain

Firebaseのプロジェクトを作成

  1. Firebase コンソールに移動
  2. プロジェクトを作成
    f:id:rkdora:20200506130520p:plain
    プロジェクトを追加
  3. ウェブアプリを追加
    f:id:rkdora:20200506135049p:plain
    ウェブアプリを追加

FirebaseとGithubを連携

  1. Authentication

    f:id:rkdora:20200506131225p:plain
    Authentication

    赤線のURLをコピーしておく f:id:rkdora:20200506133542p:plain

  2. Sign-in method
    GitHubを選択し、「有効」にする

    f:id:rkdora:20200506131741p:plain
    Sign-in method

  3. アプリを登録する
    Application name : my-github-auth(アプリ名)
    Homepage URL : ペーストし、末尾が.firebaseapp.com/になるようにする
    Authorization callback URL : ペーストする
    f:id:rkdora:20200506132054p:plain

  4. クライアントIDとクライアントシークレットをFirebase側に貼り付け
    赤部分 f:id:rkdora:20200506134003p:plain f:id:rkdora:20200506134123p:plain

  5. GitHubが有効になれば成功 f:id:rkdora:20200506134232p:plain

Vue のソースコードをいい感じに

  1. Firebaseプロジェクトの設定を開く

    f:id:rkdora:20200506135502p:plain
    設定を開く

  2. Firebase側の情報をコピー

    f:id:rkdora:20200506141855p:plain
    赤の部分

  3. src/main.js に貼り付け

import firebase from 'firebase'
import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

// Your web app's Firebase configuration
var firebaseConfig = {
  apiKey: "見せられないよ",
  authDomain: "github-auth-6d6da.firebaseapp.com",
  databaseURL: "https://github-auth-6d6da.firebaseio.com",
  projectId: "github-auth-6d6da",
  storageBucket: "github-auth-6d6da.appspot.com",
  messagingSenderId: "見せられないよ",
  appId: "見せられないよ"
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);

new Vue({
  render: h => h(App),
}).$mount('#app')
  1. src/App.vue
<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <GithubAuth msg="Welcome to Github-Auth"/>
  </div>
</template>

<script>
import GithubAuth from './components/GithubAuth.vue'

export default {
  name: 'App',
  components: {
    GithubAuth
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>
  1. src/components/GithubAuth.vue
<template>
  <div class="github-auth">
    <h1>{{ msg }}</h1>
    <div v-if="user.uid" key="login">
      <img :src="user.photoURL"/><br>
      [{{ user.displayName }}]<br>
      <button type="button" @click="doLogout">ログアウト</button>
    </div>
    <!-- 未ログイン時にはログインボタンを表示 -->
    <div v-else key="logout">
      <button type="button" @click="doLogin">ログイン</button>
    </div>
  </div>
</template>

<script>
import firebase from 'firebase'
export default {
  name: 'GithubAuth',
  props: {
    msg: String
  },
  data() {
    return {
      user: {}
    }
  },
  created() {
    firebase.auth().onAuthStateChanged(user => {
      this.user = user ? user : {}
    })
  },
  methods: {
    doLogin() {
      console.log("doLogin");
      const provider = new firebase.auth.GithubAuthProvider();
      firebase.auth().signInWithPopup(provider)
    },
    doLogout() {
      console.log("doLogout");
      firebase.auth().signOut()
    }
  }
}
</script>

完成

  1. npm install firebase
  2. npm run serve
  3. ブラウザでlocalhost:8080にアクセス f:id:rkdora:20200506144723p:plainf:id:rkdora:20200506144729p:plainf:id:rkdora:20200506144733p:plain

参考文献

Vue.js+Firebaseで認証付きチャット | 基礎から学ぶ Vue.js

Firebase のユーザーを管理する

JavaScript による GitHub を使用した認証  |  Firebase

ソースコード

github.com

【LINEbot】天気予報くんをつくる(その3 データベース)

つづき

rkdora.hatenablog.com

rkdora.hatenablog.com

実現したい機能

地域登録

ユーザーIDと地域を結びつけることで、天気を知りやすくする。

ソースコード

main.py

from flask import Flask, request, abort
from flask_sqlalchemy import SQLAlchemy

from linebot import (
    LineBotApi, WebhookHandler
)
from linebot.exceptions import (
    InvalidSignatureError
)
from linebot.models import (
    MessageEvent, TextMessage, TextSendMessage,
    TemplateSendMessage, ConfirmTemplate, PostbackAction,
    PostbackEvent
)
import os

import requests as rq
import json

import pickle

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = os.environ['DATABASE_URL']
db = SQLAlchemy(app)

LINE_CHANNEL_ACCESS_TOKEN = os.environ["LINE_CHANNEL_ACCESS_TOKEN"]
LINE_CHANNEL_SECRET = os.environ["LINE_CHANNEL_SECRET"]

line_bot_api = LineBotApi(LINE_CHANNEL_ACCESS_TOKEN)
handler = WebhookHandler(LINE_CHANNEL_SECRET)

city_path = 'city_dict.pickle'
with open(city_path, mode='rb') as f:
    city_dict = pickle.load(f)

city_list = list(city_dict.keys())

def get_weather_info(city_num):
    url = 'http://weather.livedoor.com/forecast/webservice/json/v1?'
    city_params = {'city': city_num}
    data = rq.get(url, params=city_params)
    content = json.loads(data.text)

    content_title = format(content['title'])
    content_text = format(content['description']['text'])
    content_time = format(content['description']['publicTime'])\
                    .replace('T', ' ').replace('-', '/')[:-5]

    return content_title + '\n\n' + content_text + '\n\n最終更新日時:' + content_time


# モデル作成
class MyCity(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.String(80))
    city_id = db.Column(db.String(80))

    def __init__(self, user_id, city_id):
        self.user_id = user_id
        self.city_id = city_id


def register_mycity(user_id, city_id):
    my_city = db.session.query(MyCity).filter(MyCity.user_id==user_id).first()

    if my_city:
        old_my_city_id = my_city.city_id
        my_city.city_id = city_id
        db.session.commit()
    else:
        reg = MyCity(user_id, city_id)
        db.session.add(reg)
        db.session.commit()


@app.route("/callback", methods=['POST'])
def callback():
    signature = request.headers['X-Line-Signature']

    body = request.get_data(as_text=True)
    app.logger.info("Request body: " + body)

    try:
        handler.handle(body, signature)
    except InvalidSignatureError:
        abort(400)

    return 'OK'


@handler.add(PostbackEvent)
def handle_postback(event):
    postback_data = event.postback.data
    if postback_data == 'no':
        text_message = 'かしこまりました'
    else:
        user_id = event.source.user_id
        register_mycity(user_id, postback_data)
        text_message = '登録しました'

    line_bot_api.reply_message(
        event.reply_token,
        TextSendMessage(text=text_message))


@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
    user_message = event.message.text

    if user_message in city_list:
        city_id = city_dict[user_message]
        text_message = get_weather_info(city_id)

        confirm_template_message = TemplateSendMessage(
            alt_text='Confirm template',
            template=ConfirmTemplate(
                text=user_message + 'を登録しますか?',
                actions=[
                    PostbackAction(
                        label='はい',
                        display_text='はい',
                        data=city_id
                    ),
                    PostbackAction(
                        label='いいえ',
                        display_text='いいえ',
                        data='no'
                    )
                ]
            )
        )
        messages = [TextSendMessage(text=text_message), confirm_template_message]
    elif '一覧' in user_message:
        text_message = '以下、対応地域一覧です。\n' + '\n'.join(city_list)
        messages = [TextSendMessage(text=text_message)]
    else:
        my_city = db.session.query(MyCity).filter(MyCity.user_id==event.source.user_id).first()
        if my_city:
            text_message1 = get_weather_info(my_city.city_id)
            text_message2 = '対応地域を知りたい場合は、「一覧」と話しかけてください。'
            messages = [TextSendMessage(text=text_message1), TextSendMessage(text=text_message2)]
        else:
            text_message1 = '久留米'
            text_message2 = '上記、入力例です。以下、対応地域一覧です。\n' + '\n'.join(city_list)

            messages = [TextSendMessage(text=text_message1), TextSendMessage(text=text_message2)]

    line_bot_api.reply_message(
        event.reply_token,
        messages)


if __name__ == "__main__":
    port = int(os.getenv("PORT", 5000))
    app.run(host="0.0.0.0", port=port)

その他省略 以下、リポジトリにて

github.com

手順

  1. pipenv install flask-sqlalchemy psycopg2
    エラーになった。
    sudo apt install libpq-dev
    上のコマンド実行後、再挑戦したら通った。

  2. Heroku側にPostgresのアドオンを追加
    heroku addons:add heroku-postgresql

  3. テーブル作成

$heroku run python
>>> from main import db
>>> db.create_all()

これで動く

以下、時々使う

データベースのリセット
heroku pg:reset DATABASE --confirm <app-name>

Herokuからデータベースを確認

$heroku run python
>>> from main import db, <Class Name>
>>> db.session.query(<Class Name>).all()

動作

f:id:rkdora:20200331204656p:plain

f:id:rkdora:20200331204712p:plain

f:id:rkdora:20200331204725p:plain

f:id:rkdora:20200331204738p:plain

f:id:rkdora:20200331204750p:plain

感想

せっかく、LINEbotの扱いを覚えたので今後すぐに思い出せるようにこの記事を書いた。 一ヶ月近く前にLINEbotを扱ったのだが、少し忘れているところもあり、いい復習になった。 地域名の選択を、プルダウンみたくやりたかったのだができないのだろうか。 効率よくできる案があればぜひ教えていただきたい。

LINEID

@872alddw f:id:rkdora:20200331205158p:plain

参考記事

PostgreSQLを用いたFlaskアプリのHerokuデプロイ(Flask-SQLAlchemy) - Qiita

Flask-SQLAlchemyの使い方 - Qiita

line-bot-sdk-python/app.py at master · line/line-bot-sdk-python · GitHub