Register your favorite shop / facility with your favorite name and create a Line-bot that can retrieve information about that shop / facility.
app.py Sample code distributed by Line.
from flask import Flask, request, abort
from linebot import (
LineBotApi, WebhookHandler
)
from linebot.exceptions import (
InvalidSignatureError
)
from linebot.models import (
MessageEvent, TextMessage, TextSendMessage,
)
app = Flask(__name__)
# line-access from the developers page_token and channel_Generate each secret and put it in a variable here
#If you don't know, see other articles. Many other people have written it, so I'll omit it here.
line_bot_api = LineBotApi('YOUR_CHANNEL_ACCESS_TOKEN')
handler = WebhookHandler('YOUR_CHANNEL_SECRET')
@app.route("/callback", methods=['POST'])
def callback():
# get X-Line-Signature header value
signature = request.headers['X-Line-Signature']
# get request body as text
body = request.get_data(as_text=True)
app.logger.info("Request body: " + body)
# handle webhook body
try:
handler.handle(body, signature)
except InvalidSignatureError:
print("Invalid signature. Please check your channel access token/channel secret.")
abort(400)
return 'OK'
#The event contains a lot of user information.
@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
line_bot_api.reply_message(
event.reply_token,
TextSendMessage(text=event.message.text))
if __name__ == "__main__":
app.run()
Prepare the following two in the same folder.
Be sure to install gunicorn. (It seems to be a library required for heroku server) Using a python virtual environment called venv makes it even cleaner, but I didn't do it because I couldn't do it well as described in Recent article.
argon2-cffi==20.1.0
asgiref==3.2.10
async-generator==1.10
attrs==20.2.0
backcall==0.2.0
bleach==3.1.5
certifi==2020.6.20
cffi==1.14.2
chardet==3.0.4
click==7.1.2
colorama==0.4.3
decorator==4.4.2
defusedxml==0.6.0
entrypoints==0.3
Flask==1.1.2
gunicorn==20.0.4
idna==2.10
itsdangerous==1.1.0
jedi==0.17.2
Jinja2==2.11.2
json5==0.9.5
jsonschema==3.2.0
line-bot-sdk==1.17.0
MarkupSafe==1.1.1
mistune==0.8.4
nbclient==0.5.0
nbconvert==6.0.2
nbformat==5.0.7
nest-asyncio==1.4.0
notebook==6.1.4
numpy==1.19.2
packaging==20.4
pandocfilters==1.4.2
parso==0.7.1
pickleshare==0.7.5
prometheus-client==0.8.0
prompt-toolkit==3.0.7
pycparser==2.20
Pygments==2.7.0
pyparsing==2.4.7
pyrsistent==0.17.3
python-dateutil==2.8.1
pytz==2020.1
pywinpty==0.5.7
pyzmq==19.0.2
requests==2.24.0
selenium==3.141.0
Send2Trash==1.5.0
six==1.15.0
sqlparse==0.3.1
terminado==0.8.3
testpath==0.4.4
tornado==6.0.4
urllib3==1.25.10
wcwidth==0.2.5
webencodings==0.5.1
Werkzeug==1.0.1
Procfile
web: gunicorn app:app --log-file -
Follow the steps below to deploy to heroku!
heroku login
heroku git:clone -a [My app name]
cd [My app name]
* If you are working in the current directory, you do not have to do it
git add . #I'm adding a file
git commit -am "make it better" #I'm updating the changed file
git push heroku master #I'm pushing
Let's send a message to line for the time being like this.
Solution: Nothing in particular. Just look at the Google Map Api documentation.
Solution: This was quite annoying. At first I thought I should try using a database, but I stopped this time because the learning cost seemed to be high. Next, I saved the dictionary in a pickle file and tried it, but for some reason it didn't work. Is binary data useless? ?? The cause is not clear. Finally I decided to save the dictionary in json format. It worked, but the data disappears every time I make a change. I thought I'd send the json file when I entered the password on line, but this time I stopped.
Solution This was quite difficult again. In addition to "register" and "delete" variables, I made four responses: "confirm" the variables I created and "confirm" the information about shops and facilities. (It doesn't explain the solution, but I hope you can see the python file below.)
I intend to include as many libraries and grammars as possible for my study.
app.py main file.
import json
class create_reply_message(object):
user_id = None
user_dictionaries = None
the_user_dictionary = None
def __init__(self, user_id=None,*args, **kwargs):
super().__init__(*args, **kwargs)
self.user_id = user_id
#Preparing a dictionary
with open("users_info.json", 'r') as f:
self.user_dictionaries = json.load(f)
self.the_user_dictionary = self.user_dictionaries.setdefault(self.user_id, {})
def legister_fav_shop_institution(self, shop_institute_actual_name, shop_institute_variable):
user_dictionaries_copy = self.user_dictionaries.copy()
the_user_dictionary_copy = user_dictionaries_copy[self.user_id]
the_user_dictionary_copy[shop_institute_variable] = shop_institute_actual_name
with open("users_info.json", 'w') as f:
json.dump(user_dictionaries_copy, f)
return 'Completion of registration!'
def confirm_what_legistered(self):
if self.the_user_dictionary == {}:
reply_msg = "There are no registered shops / facilities yet ..."
return reply_msg
else:
reply_msg = []
for dict_key in self.the_user_dictionary:
reply_msg.append(dict_key)
reply_msg.insert(0, f'The registered shops and facilities are below{len(self.the_user_dictionary)}Tsu! !!')
return "\Hmm·".join(reply_msg)
def delete_fav_shop_institution(self, shop_institute_variable):
user_dictionaries_copy = self.user_dictionaries.copy()
the_user_dictionary_copy = user_dictionaries_copy[self.user_id]
del the_user_dictionary_copy[shop_institute_variable]
with open("users_info.json", 'w') as f:
json.dump(user_dictionaries_copy, f)
return shop_institute_variable + 'Is deleted!'
google_maps_client.py A class that just gets information from Google Map Api and puts it in the self. variable.
import requests
from urllib.parse import urlencode, urlparse, parse_qsl
class locate_fav_shop_institution(object):
data_type="json"
location_query = None
api_key = None
def __init__(self, api_key=None, shop_institution_name=None,
*args, **kwargs):
super().__init__(*args, **kwargs)
if api_key == None:
raise Exception('API key is required')
self.api_key = api_key
self.location_query = shop_institution_name
if self.location_query != None:
self.place_id = self.extract_place_id()
if self.place_id == '':
raise Exception('Your fav shop/instition couldn\'t be located.')
self.fav_shop_institution_info = self.extract_details()
def extract_place_id(self):
base_endpoint_places = f"https://maps.googleapis.com/maps/api/place/findplacefromtext/{self.data_type}"
params = {
"key": self.api_key,
"input": self.location_query,
"inputtype": "textquery",
"fields": "place_id"
}
params_encoded = urlencode(params)
places_endpoint = f"{base_endpoint_places}?{params_encoded}"
r = requests.get(places_endpoint)
if r.status_code not in range(200, 299):
return ""
return r.json()['candidates'][0]['place_id']
def extract_details(self):
detail_base_endpoint = f"https://maps.googleapis.com/maps/api/place/details/{self.data_type}"
detail_params = {
"place_id": f"{self.place_id}",
"fields": "business_status,opening_hours,formatted_phone_number,website",
"language": "ja",
"key": self.api_key
}
detail_params_encoded = urlencode(detail_params)
detail_url = f"{detail_base_endpoint}?{detail_params_encoded}"
r = requests.get(detail_url)
return r.json()['result']
how_to_reply.py A class that enables you to respond to messages received from the other party.
import json
class create_reply_message(object):
user_id = None
user_dictionaries = None
the_user_dictionary = None
def __init__(self, user_id=None,*args, **kwargs):
super().__init__(*args, **kwargs)
self.user_id = user_id
#Preparing a dictionary
with open("users_info.json", 'r') as f:
self.user_dictionaries = json.load(f)
self.the_user_dictionary = self.user_dictionaries.setdefault(self.user_id, {})
def legister_fav_shop_institution(self, shop_institute_actual_name, shop_institute_variable):
user_dictionaries_copy = self.user_dictionaries.copy()
the_user_dictionary_copy = user_dictionaries_copy[self.user_id]
the_user_dictionary_copy[shop_institute_variable] = shop_institute_actual_name
with open("users_info.json", 'w') as f:
json.dump(user_dictionaries_copy, f)
return 'Completion of registration!'
def confirm_what_legistered(self):
if self.the_user_dictionary == {}:
reply_msg = "There are no registered shops / facilities yet ..."
return reply_msg
else:
reply_msg = []
for dict_key in self.the_user_dictionary:
reply_msg.append(dict_key)
reply_msg.insert(0, f'The registered shops and facilities are below{len(self.the_user_dictionary)}Tsu! !!')
return "\Hmm·".join(reply_msg)
def delete_fav_shop_institution(self, shop_institute_variable):
user_dictionaries_copy = self.user_dictionaries.copy()
the_user_dictionary_copy = user_dictionaries_copy[self.user_id]
del the_user_dictionary_copy[shop_institute_variable]
with open("users_info.json", 'w') as f:
json.dump(user_dictionaries_copy, f)
return shop_institute_variable + 'Is deleted!'
personal_informations.py Since it contains personal information, it will not be posted. I've added s to the uncountable noun information ...
confirm.txt A template text to send when you get information about a store / facility.
$I've seen the name!
$businessStatus
This week's schedule is ↓↓
$openingHours
If anything happens, contact the phone number below!
$phoneNumber
By the way, the homepage is ↓↓
$website
explanation.txt Text for the template to describe the bot.
$Thank you for contacting name!
$If you want to know the shops / facilities that name has registered so far
"Verification"Please send!
(Example: Confirmation)
$When you want to check the information of shops and facilities that name has registered so far
"Verification[Registered name]"Please send!
(Example: Confirmation library)
When you want to register new shop / facility information
"Registration[Official name of shop / facility] [Registered name]"Please send!
(Example: Registered Tokyo Institute of Technology Library)
On the contrary, when you want to delete the information of the shop / facility
"Delete[Registered name]"Please send!
(Example: Deleted library)
nice to meet you! !!
user_info.json A json file that stores user information. It didn't work with the pickle file, so I chose json. I wanted to use a database if possible.
{user_id: {"\u81ea\u8ee2\u8eca\u5c4b": "\u30b5\u30a4\u30af\u30eb\u30d9\u30fc\u30b9\u3042\u3055\u3072\u4e09\u9df9\u4e95\u53e3\u5e97", "\u3061\u305a\u3051": "\u6771\u4eac\u5de5\u696d\u5927\u5b66\u4ed8\u5c5e\u56f3\u66f8\u9928"}}
It's not explained at all, but I completed it like this. I'm a beginner, so even though it's Python, the code has become quite difficult to read, but if you're interested, please read it.
Send an appropriate message and it will return a line-bot description.
You can check the names you have registered so far!
You can newly register your favorite shops and facilities. Be sure to make the space between them full-width!
You can delete the shops / facilities registered so far.
You can check business hours, phone numbers, and web pages to see if the store is open.
--The code is dirty. --The explanation is difficult to understand. --There is still little knowledge and few choices (in my own). --I haven't picked up the error (I should have got the error, but I don't know where it came from ... but it still works, but I wanted to find and fix it.) --After a certain amount of time (30 minutes), heroku's server turns off (money problem). The fatal problem that the information is reset when the server is turned off because I did it with the json file this time.
There is no end to the list of bad things, but after all manufacturing is really fun! Since my major is mechanical engineering, I don't have many opportunities to write programming, and I may not have time to study other things because I'm going to be quite busy with laboratory-related classes, but I can come up with ideas and make things. It's the same in that respect, and I'm sure it will be beneficial. And above all, it's fun, so I'd like to continue programming.
It is a line-bot made by ↓. It was made by a beginner, and there are a lot of errors (I know a few, but I haven't fixed it, lol) I made it very hard! I would be grateful if you could add friends.
Recommended Posts