Python - 텔레그램 API를 활용한 챗봇 만들기

|

[1] 텔레그램 가입하기

텔레그램 홈페이지에서 가입하기

[2] 봇 생성 = Key 발급받기

1, 텔레그램 가입 후 BotFather를 검색한다.

views

2, BotFather 대화창에서 /start를 입력한다.

각 종 기능들을 설명과 함께 알려준다.

views

3, 봇 만들기

/ newbot 명령어를 친 뒤, 생성할 봇의 이름을 정의해주면

KEY를 발급 받을 수 있다.

views

4, 방금 만든 봇 이름을 검색해서 친구 추가 하기!

views

5, 메세지 보내놓기

views

[3] python을 통해 Bot에게 보낸 메세지 받기

1, Python을 통해 방금 위에서 Bot에게 보낸 메세지 데이터 가져오기

requests 모듈 사용을 위해서 install을 해주어야 한다. -> pip install requests

import requests
import os

# 환경 변수 PATH에 등록된 TELEGRAM_TOKEN을 가져온다.
token = os.getenv('TELEGRAM_TOKEN')

# 업데이트 내용 받아오기
# 아래의 주소를 호출하면, 업데이트 된 봇의 내용을 가져올 수 있다.
url = 'https://api.telegram.org/bot{}/getUpdates'.format(token)
response = json.loads(requests.get(url).text) # json으로 받기
print(response)

'''
결과값
{'ok': True, 'result': [{'update_id': 412826971, 'message': {'message_id': 1, 'from': {'id': 748290634, 'is_bot': False, 'first_name': 'Jungjung'}, 'chat': {'id': 748290634, 'first_name': 'Jungjung', 'type': 'private'}, 'date': 1561216164, 'text': '/start', 'entities': [{'offset': 0, 'length': 6, 'type': 'bot_command'}]}}, {'update_id': 412826972, 'message': {'message_id': 2, 'from': {'id': 748290634, 'is_bot': False, 'first_name': 'Jungjung', 'language_code': 'ko'}, 'chat': {'id': 748290634, 'first_name': 'Jungjung', 'type': 'private'}, 'date': 1561216177, 'text': 'Hi !!!!!!!!!'}}]}

'''

[4] Bot에게 받은 메세지 그대로 전송해보기

import requests
import os

# 환경 변수 PATH에 등록된 TELEGRAM_TOKEN을 가져온다.
token = os.getenv('TELEGRAM_TOKEN')

# 업데이트 내용 받아오기
# 아래의 주소를 호출하면, 업데이트 된 봇의 내용을 가져올 수 있다.
url = 'https://api.telegram.org/bot{}/getUpdates'.format(token)
response = json.loads(requests.get(url).text) # json으로 받기

# 아래의 주소를 이용하면 Bot을 통해 메세지를 전송할 수 있다.
url = 'https://api.telegram.org/bot{}/sendMessage'.format(token)

# 나의 chat_id와, msg를 getUpdates 통해 가져온 json데이터를 파싱해서 가져온다.
chat_id = response["result"][-1]["message"]["from"]["id"]
msg = response["result"][-1]["message"]["text"]
# print(chat_id)
# print(msg)

# sendMessage url을 통해 Bot에게 parameter를 전송한다.
requests.get(url, params = {"chat_id" : chat_id, "text" : msg})
views

활용하기

text = response["result"][-1]["message"]["text"]
msg = text
if text == '안녕':
    msg = '안녕하세요'

requests.get(url, params = {"chat_id" : chat_id, "text" : msg})
views

text 데이터를 가져와 아래와 같이 활용하면,

텔레그램과 크롤링, api를 활용해서 원하는 정보를 편하게 확인 할 수 있다.


나는 평소 방탈출 카페를 즐겨 가는데, 매번 홈페이지에서 예약 정보를 확인하기가 귀찮아서

자주가는 방탈출 카페의 예약 정보를 크롤링하여서 챗봇을 이용해 활용했다.

views

다른 텔레그램 챗봇 활용 예시 보러가기

Django-mysite만들기6 ajax를 이용한 아이디 중복 체크

|

django mini project

cafe24신입사원 교육과정 - django 수업 내용 정리

강사님github


전체 코드 보기


[1] json data 받기 연습

json 데이터 받는 연습을 위해, 임시로 urls.py

path('helloworld/hello3/', helloworld_views.hello3), url을 추가한다.

views.py

def hello3(request):
    # 전송할 json 데이터
    jsonresult = {
        'result' : 'success',
        'data' : ['hello', 1, 2, True, ('a','b','c')]
    }
    
    # 바로 브라우저에 띄우기
    return JsonResponse(jsonresult)
views
브라우저에서 확인하기

json데이터 받는 것 확인 완료!



[2] email 중복체크 구현하기

django jquery 라이브러리 다운로드

views
위 그림의 경로에 jquery를 넣어줬다.

나의 경우, settings.py에서 static 디렉토리의 경로를

STATIC_URL = '/assets/' 

위 코드와 같이 지정했기 때문에,

html파일에서 제이쿼리를 로드하기 위해서 아래의 코드를 적어주면 된다.

<script src="/assets/js/jquery/jquery-1.9.0.js"></script>


잠깐 자바스크립트 함수 호출 방법을 연습!

function f(){
    console.log("hello~")
}
$(f);
$(function(){
    console.log("hello~")
});
f = function(){
    console.log("hello~")
}
$(f);

다 같은 코드로 함수가 실행된다.


이메일 중복 구현 - jquery, ajax

[1] urls.py path 추가

ajax를 통해 email 중복 체크를 할 urls를 매핑해준다.

path('user/api/checkemail', user_views.checkemail),

[2] views.py - 해당 이메일의 객체 존재 여부 체크

def checkemail(request):
    try:
        user = User.objects.get(email=request.GET['email'])
    except Exception as e:
        user = None
    result = {
        'result':'success',
        # 'data' : model_to_dict(user)  # console에서 확인
        'data' : "not exist" if user is None else "exist"
    }
    return JsonResponse(result)

get 파라미터를 통해 email 데이터를 받아, DB에 그 email과 일치하는 데이터가 있는지 확인 후, result를 return해준다.

[3] ajax 처리

joinform.html

<script>
	/* 중복체크! */
	$(function(){
		$('#btn-email').click(function(){
			var email = $('#email').val()
			if(email == ''){
				alert('이메일을 입력해주세요.')
				return;
			}
			$.ajax({
				url:'/user/api/checkemail?email='+email,
				type:'get',
				dataType:'json',
				success:function(response){
					if(response.result != 'success'){
						console.error(response.data)
						return;
					}
					if(response.data == 'exist'){
						alert("존재하는 이메일 입니다!ㅇㅠㅇ");
						$('#email').val('').focus();
						return;
					}else{
						$('#img-email').show();
						$('#btn-email').hide();
						return;
					}
				},
                error : function(xhr, error){
					alert("서버와의 통신에서 문제가 발생했습니다.");
					console.error("error : " + error);
				}
			})
		});
</script>

위의 자바스크립트 코드를 통해, 비동기적 통신으로 중복체크를 가능하게 했다.

joinform.html

<form id="join-form" name="joinForm" method="post" action="/user/join">
    
    [..코드 생략..]
    
	<label class="block-label" for="email">이메일</label>
	<input id="email" name="email" type="text" value="">
	<img id="img-email" src="/assets/images/check.png" style="display:none;">
	<input id="btn-email" type="button" value="이메일 중복체크">
    
    [..코드 생략..]
    
	<input type="submit" id="join-submit" id_check_result="fail" value="가입하기">
</form>

[4] 중복체크 후 input data를 수정한 경우

중복체크 후 input의 value를 수정한 경우, 다시 중복체크를 하도록 처리를 해야한다.

$('#email').change(function () {
    $('#img-email').hide();
    $('#btn-email').show();
});

id=email인 input이 수정되었을 때, 다시 이메일을 체크하도록 ui변경

$("#join-submit").attr("id_check_result", "success");

이메일 중복체크를 성공한 경우 submit의 어트리뷰트 값을 변경시킨다.

$('#join-form').submit(function() {
    if($("#join-submit").attr("id_check_result") == "fail") {
        alert("id 중복체크를 해주시기 바랍니다.");
        $("#email").focus();
        return false;
    }
});

$("#email").on("propertychange change keyup paste input", function(){
    $('#img-email').hide();
    $('#btn-email').show();
    $("#join-submit").attr("id_check_result", "fail");
});

만약, submit의 어트리뷰트가 fail인 경우, 다시 중복체크 하도록 처리한다.

브라우져의 개발자 모드 어트리뷰트를 변경한 경우 넘어갈 수 없도록

propertychange change keyup paste input,

$("#join-submit").attr("id_check_result", "fail"); 코드를 추가했다.

javascript 전체 코드

<script>
	/* 중복체크! */
	$(function(){
		/* 아이디 수정했을 때 */
		$('#email').change(function () {
			$('#img-email').hide();
			$('#btn-email').show();
		});

		$('#btn-email').click(function(){
			var email = $('#email').val()
			if(email == ''){
				alert('이메일을 입력해주세요.')
				return;
			}

			$.ajax({
				url:'/user/api/checkemail?email='+email,
				type:'get',
				dataType:'json',
				success:function(response){
					if(response.result != 'success'){
						console.error(response.data)
						return;
					}
					if(response.data == 'exist'){
						alert("존재하는 이메일 입니다!ㅇㅠㅇ");
						$('#email').val('').focus();
						return;
					}else{
						$('#img-email').show();
						$('#btn-email').hide();
						$("#join-submit").attr("id_check_result", "success");
						return;
					}
					// console.log(response)
				},
                error : function(xhr, error){
					alert("서버와의 통신에서 문제가 발생했습니다.");
					console.error("error : " + error);
				}
			})
		});

    $('#join-form').submit(function() {
		   if($("input:checkbox[id='agree-prov']").is(":checked") == false) {
		      alert("약관동의를 확인하여 주시기 바랍니다.");
		      return false;
		   }

		   console.log($("#join-submit").attr("id_check_result"));

		   if($("#join-submit").attr("id_check_result") == "fail") {
		      alert("id 중복체크를 해주시기 바랍니다.");
		      $("#email").focus();
		      return false;
		   }
		});

		$("#email").on("propertychange change keyup paste input", function(){
		   $('#img-email').hide();
		   $('#btn-email').show();
		   $("#join-submit").attr("id_check_result", "fail");
		});
	});
</script>
views
중복체크 알림
views
중복체크 성공
views
회원가입 성공

Django-mysite만들기5 회원정보 수정 기능 추가

|

django mini project

cafe24신입사원 교육과정 - django 수업 내용 정리

강사님github


전체 코드 보기


urls.py에 매핑 코드 추가

urlpatterns = [
	...
    # 업데이트 폼
    path('user/updateform', user_views.updateform),
    
    # db update
    path('user/update', user_views.update),
	...
]

views.py 처리

# 회원정보 수정 폼
def updateform(request):
    user = User.objects.get(id=request.session['authUser']['id'])
    data = {
        'user':user
    }
    return render(request, 'user/updateform.html', data)

# 업데이트 처리
def update(request):
    user = User.objects.get(id=request.session['authUser']['id'])
    user.name = request.POST['name']

    user.gender = request.POST['gender']
    if request.POST['password'] is not '':
        user.password = request.POST['password']
    user.save()
    
    # 수정정보 다시 가져오기
    # 세션을 전체 가져오기
    # request.session['authUser'] = model_to_dict(user)
    
    # 현재 세션의 데이터만 변경하기
    request.session['authUser']['name']=user.name
    return HttpResponseRedirect('/user/updateform?result=success')

updateform.html코드

Django-mysite만들기4 로그인 로그아웃 기능 추가(django session)

|

django mini project

cafe24신입사원 교육과정 - django 수업 내용 정리

강사님github


전체 코드 보기


login 만들기

로그인 폼 만들기 : loginform.html코드

views

urls.py 매핑 코드 추가

urlpatterns = [
	...
    # 로그인 폼을 보여주기
    path('user/loginform', user_views.loginform),
    
    # 로그인 로직(DB에 데이터 추가)
    path('user/login', user_views.login),
	...
]

views.py 로그인 세션 로직 처리

# login
def loginform(request):
    return render(request, 'user/loginform.html')

def login(request):
    # ORM문법을 통해, email과 password가 일치하는 결과 객체를 가져온다.
    results =  User.objects.filter(email=request.POST['email']).filter(password=request.POST['password'])

    # 해당하는 데이터가 없으면 -> 로그인 실패
    if len(results)==0:
        return HttpResponseRedirect('/user/loginform?result=fail')

    # 해당하는 데이터가 있다면 -> 세션 등록
    authUser = results[0]
    request.session['authUser'] = model_to_dict(authUser)

    return HttpResponseRedirect('/')

base.html코드 -> 세션 처리!

views

seesion이 존재하지 않는 경우 -> 로그인, 회원가입

seesion이 존재하는 경우 -> 회원정보 수정, 로그아웃 보여주기

logout 처리

urls.py 매핑 경로 추가

urlpatterns = [
	...
    path('user/logout', user_views.logout),
	...
]

views.py 로그아웃 세션 로직 처리

def logout(request):
    # authUser로 존재하는 세션 지우기
    del request.session['authUser']
    return HttpResponseRedirect('/')

이렇게 하면, 로그아웃 눌러야지 로그아웃이 되고,

로그인 상태로 서버를 껐다 키면 세션 남아있다.

< 해결방법 >

settings.py에 다음 코드를 추가하면 된다.

# 브라우저 닫으면 session 없애기
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
# update되면 session바로 반영
SESSION_SAVE_EVERY_REQUEST = True

단, 열려있는 모든 브라우저 창을 닫고 다시 접근해야한다.


Python HTTPServer를 이용한 서버 띄우기

|

전체코드보기


HTTPServer를 이용해 서버 띄우기

from http.server import BaseHTTPRequestHandler, HTTPServer

port = 9999

class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header('Content-Type', 'text/html; charset=utf-8')
        self.end_headers()
        self.wfile.write('<h1>안녕하세요</h1>'.encode('utf-8'))

httpd = HTTPServer(('0.0.0.0', port), SimpleHTTPRequestHandler)
print(f'Server running on port:{port}')
httpd.serve_forever()
views
서버 접근하기 성공

[1] 직접 url 파라미터 받아보기

ex) http://localhost:9999/user/login?id=jungeun&password=1234로 접근하기

만약 로그인 화면이라고 가정을 한다면,

class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        print(self.path)
<출력> /user/login?id=jungeun&password=1234

파라미터를 받아오기위해 문자열을 분리해야한다.

서버의 ['/favicon.ico']이 같이 오기 때문에 if문을 사용해 걸러보자!

class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        # print(self.path)
        if '?' in self.path:
            urls = self.path.split('?')
            path = urls[0]
            qs = urls[1].split('&')
            print(path, qs)
<출력> /user/login ['id=jungeun', 'password=1234']

[2] url parse 사용으로 파라미터 받기

class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        result = urlparse(self.path)
        print(result)
<출력>
ParseResult(scheme='', netloc='', path='/user/login', params='', query='id=jungeun&password=1234', fragment='')

ParseResult(scheme='', netloc='', path='/favicon.ico', params='', query='', fragment='')

params 분리하기

class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        result = urlparse(self.path)
        params = parse_qs(result.query)
        print(params)
<출력> {'id': ['jungeun'], 'password': ['1234']}

파라미터가 왜 list일까?

check box 같은 경우, 다중 선택으로 parameter를 보낼 때, 같은 name으로 value가 멀티로 날라오는 경우가 있기 때문이다.

장고의 urls.py 에서도 이렇게 url path를 가져와서 url을 매핑 하는 것 같다.

from django.urls import path
import mycontroller

urlpatterns = [
    path('/user/login' : mycontroller.login),
]