forked from hashiba-k-jp/hakodate-a05
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathapp.py
317 lines (264 loc) · 10.9 KB
/
app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
from flask import Flask, render_template, request, jsonify
from src.findNearestEvacuation.find_evacuation_point import find_evacuation_point
from src.getInfoFromJMA.initData import initData
import pprint as pp
from initApp import initApp
import base64,hashlib,hmac #署名検証用
import os,sys
import psycopg2
import uuid
import secrets
from linebot.models import TextSendMessage
from linebot import(
LineBotApi
)
import linebot
from funcs import *
app = Flask(__name__)
#各種定数を定義
#DEBUG = os.environ.get('IS_DEBUG') == 'True' #デバッグ用のフラグ
CHANNEL_SECRET = os.environ.get('CHANNEL_SECRET')
ROOT_URL = os.environ.get('ROOT_URL')
CONSOLE_ROOT_URL = '{ROOT_URL}/control'.format(
ROOT_URL=ROOT_URL
)
@app.route('/control/<uuid:id>')
def control_console(id):
#DBへのコネクションを作成
conn = db_connect()
cursor = conn.cursor()
#DB上にidが存在するかを確認
sql = "SELECT EXISTS (SELECT * FROM public.verify WHERE id='{}');".format(id)
cursor.execute(sql)
result = cursor.fetchone()[0]
conn.commit()
#データベース上に存在しない場合正規のリクエストではないため500を返す
if result == False:
cursor.close()
conn.close()
return '',500,{}
else:
cursor.close()
conn.close()
return render_template("control.html",title="避難所経路探索|登録",id=id)
@app.route('/control/form', methods=['POST'])
def control_form():
#送信データから値を抽出
user_uuid = request.form.get('user_uuid')
user_accept = request.form.get('user_resistration_accept_checkbox')
try:
#DBのコネクションを作成
conn = db_connect()
cursor = conn.cursor()
#user_accept==onの時ユーザーを登録
if user_accept == '1':
#DBからuserのidを取得
sql = "SELECT user_id FROM public.verify WHERE id='{}';".format(user_uuid)
cursor.execute(sql)
user_id = cursor.fetchone()[0]
conn.commit()
#DBから函館の地域コードを取得
sql = "SELECT id FROM public.area WHERE area_name='函館市';"
cursor.execute(sql)
area_id = cursor.fetchone()[0]
conn.commit()
#resistrationにすでに登録されているかを確認
sql = 'SELECT EXISTS (SELECT * FROM public.resistration WHERE user_id={user_id} AND area_id={area_id});'.format(user_id=user_id,area_id=area_id)
cursor.execute(sql)
resistration_result = cursor.fetchone()[0]
conn.commit()
if resistration_result == True:
cursor.close()
conn.close()
return render_template(
'resistration_result.html',
title='避難所経路探索|登録結果',
result='すでに登録されています。',
result_text='登録した心当たりがない場合は管理者にお問い合わせください。'
)
else:
#resistrationに登録
sql = "INSERT INTO public.resistration(user_id,area_id) VALUES('{user_id}','{area_id}');".format(
user_id = user_id,
area_id = area_id
)
cursor.execute(sql)
conn.commit()
#verifyからユーザーを削除
sql = "DELETE FROM public.verify WHERE id = '{}';".format(user_uuid)
cursor.execute(sql)
conn.commit()
cursor.close()
conn.close()
return render_template(
'resistration_result.html',
title='避難所経路探索|登録結果',
result='登録完了',
result_text='登録が完了しました。このページを閉じてください。'
)
else:
#DBからユーザの情報を削除
#userのidを取得
sql = "SELECT user_id FROM public.verify WHERE id='{}'".format(user_uuid)
cursor.execute(sql)
id = cursor.fetchone()[0]
conn.commit()
#public.userからユーザ情報を削除
sql = 'DELETE FROM public.user WHERE id={}'.format(id)
cursor.execute(sql)
conn.commit()
cursor.close()
conn.close()
return render_template(
'resistration_result.html',
title='避難所経路探索|登録結果',
result='情報削除完了',
result_text='データベースからご利用者様の情報を削除しました。またのご利用をお待ちしています。'
)
except psycopg2.IntegrityError:
print('SQL RERATION ERROR!!')
return render_template(
'resistration_result.html',
title='避難所経路探索|登録結果',
result='内部エラー',
result_text='システム内部でエラーが発生しました。もう一度登録を試みてください。'
)
@app.route('/webhock', methods=['POST'])
def webhock():
data = request.get_json() #user_id抽出用のリクエストデータ(json)
print('data_type:{}'.format(type(data)))
body = request.get_data(as_text=True) #検証用のリクエストデータ(string)
signature = request.headers.get('x-line-signature')
try:
conn = db_connect()
if validation(body=body, signature=signature.encode('utf-8')) == True: #イベントの真贋判定
for line in data["events"]:
user_id=''
#ソースがユーザからのイベントである場合のみuser_idを抽出
if line['source']['type'] == 'user':
user_id = line["source"]['userId']
else:
#ソースがユーザーからのイベントではない時400を返して処理を終える
return '',200,{}
#DB操作用のカーソルを作成
cursor = conn.cursor()
#user_idが既にDB上に存在しているか確認する
sql = "SELECT EXISTS (SELECT * FROM public.user WHERE user_id='{}');".format(user_id)
cursor.execute(sql)
conn.commit()
result = cursor.fetchone()
print('Result:{}'.format(result))
#存在しない時DBに登録
if result[0] == False:
sql = "INSERT INTO public.user(user_id) VALUES('{}');".format(user_id)
cursor.execute(sql)
conn.commit()
#イベントがmessageである時送信されたテキストの解析
if line['type'] == 'message':
if line['message']['text'] == '登録' or line['message']['text'] == '初期設定':
#URL用のUUIDの生成
user_uuid = uuid.uuid4()
#DBからuserのidを取得
sql = "SELECT id FROM public.user WHERE user_id='{}'".format(user_id)
cursor.execute(sql)
id = cursor.fetchone()[0]
conn.commit()
#public.verifyにユーザーの情報が存在する場合は削除する
sql ="SELECT EXISTS (SELECT * FROM public.verify WHERE user_id={});".format(id)
cursor.execute(sql)
if cursor.fetchone()[0] == True:
sql = "DELETE FROM public.verify WHERE user_id={}".format(id)
cursor.execute(sql)
conn.commit()
else:
conn.commit()
#DBにUUIDとverify_hash,userのidを記録
sql = "INSERT INTO public.verify(id,user_id) VALUES ('{uuid}',{user_id});".format(
uuid=user_uuid,
user_id=id
)
cursor.execute(sql)
conn.commit()
#ユーザにURLと認証コードを送信
#URLを送信
url_msg = '管理用コンソール用URL\nhttps://{root_url}/{uuid}'.format(
root_url=CONSOLE_ROOT_URL,
uuid=user_uuid
)
send_msg_with_line(user_id=user_id, msgs=[url_msg])
#DBとの接続を解除
cursor.close()
conn.close()
#messageではない時200を返して処理を終了
else:
return '',200,{}
#全ての処理が正常終了した時200を返す
return '',200,{}
else:
#正規のリクエストではないため200を返して終了
return 'Bad Request',400,{}
except:
return 200
@app.route('/location', methods=['GET'])
def get_location_get():
name_type = {
'03': "洪水",
'04': "洪水",
'05': "洪水",
'33': "洪水",
'35': "洪水",
'20': "濃霧注意報(テスト用)",
'50': "地震",
'08': "高潮",
'38': "高潮",
'70': "崖崩れ、土石流及び地滑り",
}
try:
req = request.args
warningCode = req.get("warningCode")
warningName = name_type[warningCode]
except:
warningName = "その他の災害"
return render_template(
'gps_design.html',
title='Get Location App',
warningName=warningName
)
@app.route('/location', methods=['POST'])
def get_location_post():
lat = request.form['lat']
lng = request.form['lng']
userID = request.form['userID']
warningCode = request.form['warningCode']
print(lat, lng, userID, warningCode)
notiData = find_evacuation_point(
currentAddress=None,
hazardType=warningCode,
GPS={
'N': lat,
'E': lng
},
userID=userID
)
pp.pprint(notiData)
if not(notiData['ErrorCode'] is None):
return jsonify({'message': notiData['ErrorCode']}), 500
else:
send_msg_with_line(
user_id=notiData['userID'],
msgs=[notiData['url']],
)
return notiData['EvacuationPoint']
#署名検証用の関数
def validation(body,signature):
hash = hmac.new(CHANNEL_SECRET.encode('utf-8'),
body.encode('utf-8'), hashlib.sha256).digest()
val_signature = base64.b64encode(hash)
if val_signature == signature:
return True
else:
return False
if __name__ == "__main__":
initApp()
initData()
app.run(debug=False, host='localhost', port=5001)