# Build your own Chatbot - The source code of the chatbot is about the research published in Conference IS3C2020: [Visit here to view source code](https://github.com/shawnlintw/LINE_bot_assistant.git) - This steps is record that how to build a line chatbot via Django freamwork. <h2> Create a new django project </h2> 1. Switch to python enviroment 2. Create a new django project : `django-admin startproject PROJECT_NAME` 3. Create a new django app : `python manage.py startapp APP_NAME` 4. Create "static" folder : `mkdir -p static` 5. Create "templates" folder : `mkdir -p templates` 6. This will create or update the database ``` python manage.py makemigrations python manage.py migratie ``` 7. Edit the setting.py. setting.py is the configure file of project. 1. Enable/Disable debug mode change the setting in line 26 ``` DEBUG = True/Flase ``` 2. Add APP that you create into project configure. add APP_NAME into "INSTALLED_APPS" list ``` INSTALL_APPS =[ 'django.contrib.admin', 'django.contrin.auth', . . . 'APP_NAME', # The App you create. ] ``` 3. Setting the path of template ``` TEMPLATES =[ 'BACKEND':'django.template.backends.django.DjangoTemplates', 'DIRS' :[os.path.join(BASE_DIR, 'templates')], 'APP_DIRS' : True, ] ``` 4. Setting the path of static ``` STATIC_URL='/static/' STATICFILES_DIRS=[ os.path.join(BASE_DIR, 'static'), ] ``` 5. Setting the timezone and language ``` LANGUAGE_CODE= 'zh-Hant' # Traditional Chinese TIME_ZONE ='Asia/Taipei' ``` 8. Edit the urls.py 1. For example : Add two functions that named say_hello, hello2 ``` from django.conf.urls import url from APP_NAME.views import sayhello,hello2 urlpatterns =[ path('admin/', admin.site.urls), url(r'^$', sayhello), url(r'^hello2/(\w+)/$', hello2) ] ``` 10. Define the application function ( all function define in views.py ) 1. For example : Add two functions that named say_hello, hello2 ``` form django.http import HttpResponse . . . def sayhello(request): return HttpResponse("Hello Django!") def hello2(request, username): return HttpResponse("Hello" + username) ``` 11. Now we use the template to display instand of HttpResponse 1. Add a new function named hello3. 1. In views.py (locals() means pass all local variables to render function.) ``` from django.shortcuts import render from datetime import datetime def hello3(request, username): now=datetime.now() return render(request, "hello3.html", locals()) ``` 2. In urls.py ``` url(r'^hello3/(\w+)/$', hello3), ``` 3. Create hello3.html in template folder. ``` <!DOCTYPE html> <html> <head> <meta charset = 'utf-8'> <title> First template </title> </head> <body> <h1> Welcome {{username}} </h1> <h2> Now is {{now}} </h2> </body> </html> ``` 12. Execute service ``` python manage.py runserver ``` <h2> Use Django Database </h2> 1. Define data table class in model.py 2. create the middleware between database and django by use: ``` python manage.py makemigrations ``` 3. Updata database ``` python manage.py migrate ``` For example: 1. Create a data table name db_test. Add db class to model.py ``` from django.db import models class db_test(models.Model): cName = models.CharField(max_length =20, null=False) cSex = models.CharField(max_length =2, default='M', null=False) cEmail = models.EmailField(max_length=100, blank=True, default = '') def __str__(self): return self.cName ``` 2. Then Update the Database ``` python manage.py makemigrations python manage.py migrate ``` 3. Manage database by using django backend management. 1. Edit database class in model.py to admin.py. ``` form APP_NAME.models import db_test #Register your models here. admin.site.register(db_test) ``` 2. Create the user account for database manager. ``` python manage.py createsuperuser ``` 3. Running the service and open Browser and open web site in 127.0.0.1:8000/admin/ 4. Database inquiry by using the models method : objects.get() and objects.all() ``` datatable.objects.get(inquiry arg) ``` 1. For example : Display data by using Template. Add these line in urlpatterns section in urls.py ``` url(r'^listone/$',listone), url(r'^listall/$',listall), ``` 2. Then create the instance in views.py ``` from APP_NAME.models import db_test def listone(request): try: unit= db_test.objects.get(cName="shawn") # inquire one record. except: errormessage=("Reading Failed.") return render(request, "listone.html",locals()) def listall(request): try: names= db_test.objects.all().order_by('id') # inquire all records and sort by id. except: errormessage=("Reading Failed.") return render(request, "listall.html",locals()) ``` 3. Create listone.html in template folder: ``` <!DOCTYPE html> <html> <head> <title>Show one Record </title> </head> <body> <h2>Errormessage : {{errormessage}}</h2> No.: {{unit.id}} <br /> Name: {{unit.cName}} <br /> Sex: {{unit.cSex}} <br /> Email: {{unit.cEmail}} <br /> </body> </html> ``` 4. Create listall.html in template folder: ``` <!DOCTYPE html> <html> <head> <title>Show all Records </title> </head> <body> <h2>Errormessage : {{errormessage}}</h2> <table border="1" cellpadding ="0" cellspacing = "0"> <th>No.</th> <th>Name</th> <th>Sex</th> <th>Email</th> {% for name in names %} <tr> <td> {{name.id}}</td> <td> {{name.cName}} </td> <td> {{name.cSex }} </td> <td> {{name.cEmail}}</td> </tr> {% endfor %} </table> </body> </html> ``` 5. Add Insert Delete record 1. Add record : 1. edit in views.py ``` def insert(request): unit = db_test.objects.create(cName='Alex', cSex='F', cEmail='Alex@test.com.tw') unit.save() names = db_test.objects.all().order_by('-id') return render(request, "listall.html", locals()) ``` 2. Add these line in urlpatterns section in urls.py ``` url(r'^insert/$', views.insert), ``` 2. Modify record : 1. edit in views.py ``` def modify(request): unit=db_test.objects.get(cName='Alex') unit.cEmail='Alex_1@test.com.tw' unit.save() names=db_test.objects.all().order_by('-id') return render(request, "listall.html", locals()) ``` 2. Add these line in urlpatterns section in urls.py ``` url(r'^modify/$',views.modify), ``` 3. Delete record : 1. edit in views.py ``` def delete(request, cName=''): unit = db_test.objects.get(cName='Alex') unit.delete() names=db_test.objects.all().order_by('-id') return render(request, "listall.html", locals()) ``` 3. Add these line in urlpatterns section in urls.py ``` url(r'^delete/$', views.delete), ``` <h2> LINE BOT API </h2> 1. Create a LINE development account in [web site](https://developers.line.biz/en/) 2. Install LINE Bot SDK: ``` pip install line-bot-sdk==1.8.0 ``` 3. Get the LINE Bot CHANNEL_ACCESS_TOKEN and CHANNEL_SECRET from LINE develop 4. Add LINE_CHANNEL_ACCESS_TOKEN and CHANNEL_SECRET to settings.py ``` LINE_CHANNEL_ACCESS_TOKEN = 'developer's channel access token' LINE_CHANNEL_SECRET = 'developer's channel secret' ``` 5. Modify the Allowed host in setting.py ``` ALLOWED_HOSTS = ['*'] ``` 6. For Example, we create a 'callback' function. Add these lines to views.py ``` from django.conf import settings from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseForbidden from django.views.decorators.csrf import csrf_exempt from linebot import LineBotApi, WebhookParser from linebot.exceptions import InvalidSignatureError, LineBotApiError from linebot.models import MessageEvent, TextSendMessage line_bot_api = LineBotApi(settings.LINE_CHANNEL_ACCESS_TOKEN) parser = WebhookParser(settings.LINE_CHANNEL_SECRET) @csrf_exempt def callback(request): if request.method == 'POST': signature = request.META['HTTP_X_LINE_SIGNATURE'] body = request.body.decode('utf-8') try: events = parser.parser(body, signature) except InvalidSignatureError : return HttpResponseForbidden() except LineBotApiError: return HttpResponseBadRequest() for event in evnets: if isinstance(event, MessageEvent): #do somethings return HttpResponse() else: return HttpResponseBadRequest() ``` 7. Download and install [ngrok](https://ngrok.com/download) 8. Execute the Django service and ngrok ``` python manage.py runserver ngrok http PORT_NUMBER ``` 9. Configure the LINE Bot Webhook URL in Line [develop site](https://ngrok.com/download) Paste the ngrok web site into the webhooks field. For example : ngrok : https://1234abcd.ngrok.io Fill the https://1234abcd.ngrok.io/callback into webhook field. <h2> Django Channel <h2/> 1. Reference is [here](https://channels-docs-zhtw.readthedocs.io/zh_TW/latest/tutorial/index.html)