시스템에 중요한 이벤트가 발생하면
카카오톡의 나에게 메시지 보내기 기능을 이용해 전달하는 기능을 추가해 보겠다.
두 가지 메시지를 보낼 건데
- 매일 장이 끝나고 보유 주식 자산에 대한 최종 리포트 하나
- 매달 1회 새로운 주식 종목이 추천되고 추천하는 주식에 대해 알려주는 리포트 하나
카카오 관련 API를 사용하기 위해서는 KAKAO 개발자에 우선 등록해야한다.
로그인 후 상단의 "내 애플리케이션"을 클릭 한 후 "애플리케이션 추가하기"를 클릭!
정보 입력 후 저장
접속하면 다음과 같이 4개의 키가 보이는데, 우리가 사용할 키는 REST API키이다.
왼쪽의 카카오 로그인을 클릭한 후에 상태를 ON 하도록 하자.
그리고 "Redirect URI"에 수정을 클릭한 후 "http://localhost.com"을 추가하도록하자.
나는 내가 사용하는 스플렁크 인스턴스 주소와 포트번호를 넣어줬다.
DNS가 있는 컴퓨터에서 작업하면 자신의 DNS로 입력해도 된다.
다음 왼쪽의 "동의항목" 을 클릭한 후 "카카오톡 메시지 전송" 에 "선택 동의" 로 설정한다.
다음은 브라우져를 통해서 다음 URL을 실행한다.
https://kauth.kakao.com/oauth/authorize?client_id={REST_API_KEY}&response_type=code&redirect_uri={REDIRECT_URI}
이를 수행하고 기다리면 (쫌 한참 기다리면...) 다음처럼 화면이 전환되는데 접속할 수 없다는 에러가 나온다. 절대 당황하지 말자.
(접속이 되어야 하는지 알고 수 십번 수행해 봤다...)
리다이렉트된 URL 에 보면 code=XXXXXXXXX 로 되어 있는 부분 인증 키를 기억하자.
이 인증 키를 가지고 다시 한번 인증을 받아야 한다.
여기에서는 파이썬 코드를 사용한다.
import json
import requests
url = "https://kauth.kakao.com/oauth/token"
data = {
"grant_type" : "authorization_code",
"client_id" : "{REST_API_KEY}", # 가장 첫 화면에 있던 REST API 키 입력
"redirect_uri" : "https://localhost.com",
"code" : "{CODE}" # 방금 받은 코드 키 입력
}
response = requests.post(url, data=data)
tokens = response.json()
print(tokens)
이 코드를 실행하면 화면에 다음처럼 접근 토큰과 갱신 토큰을 얻게 된다.
{'access_token': 'VVi64gBCvP0WRoAios80cQdNRisMr_DfOto5FugTCioljgAAAYj2bhJl',
'token_type': 'bearer',
'refresh_token': 'pkmcap5Gz1uFQXVZ0j__3Vv6tTCWejitMcN07ILpCioljgAAAYj2bhJj',
'expires_in': 21599,
'scope': 'talk_message',
'refresh_token_expires_in': 5183999}
접근 토큰은 유효시간이 6시간 정도 갱신 토큰은 60일 정도 된다.
그래서 이 작업을 2달에 한 번씩 수행해야 하는 듯하다.
이 작업까지 하면 우선 카카오톡에 나에게 메시지 보내기 기능을 할 준비가 되었다.
import json
import requests
url = "https://kapi.kakao.com/v2/api/talk/memo/default/send"
access_token="Nju...Uw" # 위에서 받은 접근 토큰
# 사용자 토큰
headers = {
"Authorization": "Bearer " + access_token
}
# 전송할 데이터 포맷
data = {
"template_object" : json.dumps({ "object_type" : "text",
"text" : "Hello, world!",
"link" : {
"web_url" : "www.splunk.com"
}
})
}
response = requests.post(url, headers=headers, data=data)
print(response.status_code)
if response.json().get('result_code') == 0:
print('메시지를 성공적으로 보냈습니다.')
else:
print('메시지를 성공적으로 보내지 못했습니다. 오류메시지 : ' + str(response.json()))
이렇게 해서 매시지를 수신 받았다면 성공이다.
이 접근 코드의 유효기간은 6시간 밖에 안되기 때문에
주기적으로 갱신 토큰을 이용해서 접근 토큰을 갱신해 줘야 한다.
import json
import requests
# TOKEN Refresh
url = "https://kauth.kakao.com/oauth/token"
data = {
"grant_type": "refresh_token",
"client_id" : "{REST_API_KEY}",
"refresh_token" : 'Q6iQ...jBkUg' # 이번에는 갱신 토큰을 넣어 준다.
}
response = requests.post(url, data=data)
tokens = response.json()
print(tokens)
access_token = tokens["access_token"]
print(access_token)
{'access_token': 'O3EGtfljuHruXZ6VO6viaD8F_m8o4_FXsSv-gZ6YCj11GQAAAYj2ebH1',
'token_type': 'bearer',
'expires_in': 21599}
O3EGtfljuHruXZ6VO6viaD8F_m8o4_FXsSv-gZ6YCj11GQAAAYj2ebH1
자 위의 코드들을 한 곳에 엮어 주면 우선 알람을 카카오톡으로 보낼 준비는 끝났다.
카카오톡 개발자 API 가이드
https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api
이제 스플렁크로 돌아와서 "kakao alert action" 이라는 새로운 앱을 생성한다.
(새로운 앱 생성하는 자세한 방법은 Phase 1 참고)
새로운 알람 메시지를 만들기 위해서는 다음과 같은 작업이 필요하다.
${KAKAO_ALERT_HOME} = $SPLUNK_HOME/etc/apps/kakao_alert_action
- README/alert_actions.conf.spec # 도움말 파일
- README/savedsearches.conf.spec # 도움말 파일
- appserver/static/kakao.png # 앱 아이콘 파일
- bin/kakao.py # 메시지를 보내는 실행 파일
- default/alert_actions.conf # 얼럿 설정 파일 & 실행 파일에 보낼 파라미터 설정
- default/data/ui/alerts/kakao.html # 알람 웹 화면에서 보여질 폼 화면 구성
- metadata/default.meta # 전역에서 사용할 수 있도록 설정
작업 해야 할 부분이 많다. 우선 도움말 파일부터 살펴보자.
$ vi ${KAKAO_ALERT_HOME}/README/alert_actions.conf.spec
[kakao]
param.base_url = <string>
* Kakao API base URL - adjust if you're using you own server on premise
param.auth_token = <string>
* Kakao OAuth2 token
$ vi ${KAKAO_ALERT_HOME}/README/savedsearches.conf.spec
# Kakao alert settings
action.kakao = [0|1]
* Enable Kakao notification
action.kakao.param.message = <string>
* The message to send to the kakao.
* (required)
action.kakao.param.message_format = [text|html]
* The format of the notification (optional)
* Default is "text"
* (optional)
action.kakao.param.auth_token = <string>
* Override Kakao API auth token from global alert_actions config
* (optional)
$ vi ${KAKAO_ALERT_HOME}/default/alert_actions.conf
[kakao]
is_custom = 1
label = Kakao
description = Send a message to a Kakao channel
icon_path = kakao.png
python.version = python3
payload_format = json
#Custom params
param.base_url = https://kapi.kakao.com/v2/api/talk/memo/default/send
param.auth_token = O3EGtfljuHruXZ6VO6viaD8F_m8o4_FXsSv-gZ6YCj11GQAAAYj2ebH1
여기에서 특히 중요한 점은 auth_token 이다. 앞에서 말했듯이 접근 키는 6시간 후에 만료되는 키이기 때문에 이 키를 넣게 되면 매우 자주 바꿔줘야 한다. 그렇기 때문에 갱신 키를 입력하고 코드 안에서 접근 키를 새로 얻어서 사용해야 한다. 그리고 이 키도 2달에 한 번씩 새로 갈아줘야 한다. (auth_token 에 처음 받은 코드를 넣고 전체를 가는 것도 고려해 볼만할듯.......)
$ vi ${KAKAO_ALERT_HOME}/default/data/ui/alerts/kakao.html
<form class="form-horizontal form-complex">
<div class="control-group">
<!-- 메시지를 작성하는 폼 -->
<label class="control-label" for="kakao_message">Message</label>
<div class="controls">
<textarea name="action.kakao.param.message" id="kakao_message"></textarea>
<span class="help-block">
The chat message for the Kakao
Include tokens to insert text based on search results.
<a href="192.168.11.130:8000/help?location=learnmore.alert.action.tokens" target="_blank"
title="Splunk help">Learn More <i class="icon-external"></i></a>
</span>
</div>
</div>
<div class="control-group">
<!-- 메시지 포맷을 설정하는 부분 (plain text/html) 인데 아직 사용하지 않는다 -->
<label class="control-label">Message Format</label>
<div class="controls">
<label class="radio" for="kakao_message_format_plain">
<input id="kakao_message_format_plain" type="radio" name="action.kakao.param.message_format" value="plain">
Plain Text
</label>
<label class="radio" for="kakao_message_format_html">
<input id="kakao_message_format_html" type="radio" name="action.kakao.param.message_format" value="html">
HTML
</label>
</div>
</div>
<div class="control-group">
<!-- 토큰 값을 넣어 주는 부분. 이 곳에 값을 넣으면 기본 설정되어 있는 값에 덮어 쓰여진다. -->
<label class="control-label" for="kakao_auth_token">Auth Token</label>
<div class="controls">
<input type="text" name="action.kakao.param.auth_token" id="kakao_auth_token" placeholder="Optional">
<span class="help-block">Override the globally configured Kakao Auth Token for this alert.</span>
</div>
</div>
</form>
$ vi ${KAKAO_ALERT_HOME}/metadata/default.meta
[]
export = system # 전역에서 사용할 수 있도록 해준다.
마지막 코드 부분이다.
$ vi ${KAKAO_ALERT_HOME}/bin/kakao.py
from __future__ import print_function
from builtins import str
import sys, os, datetime
import json
import requests
from requests.exceptions import HTTPError
# splunkd.log 에 로그를 쓴다.
def log(msg, *args):
sys.stderr.write(msg + " ".join([str(a) for a in args]) + "\n")
# Refresh 토큰을 이용해서 Access 토큰을 얻는다.
def getAccessToken(refresh_token):
REFRESH_URL = "https://kauth.kakao.com/oauth/token"
CLIENT_ID = "{MY_REST_API_KEY}"
access_token = ""
# TOKEN Refresh
data = {
"grant_type": "refresh_token",
"client_id" : CLIENT_ID,
"refresh_token" : refresh_token
}
try :
response = requests.post(REFRESH_URL, data=data)
tokens = response.json()
access_token = tokens["access_token"]
log("INFO successfully refreshed KAKAO access_token")
except HTTPError as http_err:
print(f"FATAL error occured: {http_err}", file=sys.stderr)
except Exception as err:
print(f"FATAL error occured: {err}", file=sys.stderr)
return access_token
def send(settings):
# defat/alert_action.conf 에 있는 설정에서 값을 얻어 온다.
refresh_token = settings.get('auth_token')
access_token = getAccessToken(refresh_token)
URL = settings.get('base_url').rstrip('/')
headers = {
"Authorization": "Bearer " + access_token
}
# message는 설정에서 'message' 를 통해 얻어 올 수 있다.
data = {
"template_object" : json.dumps({ "object_type" : "text",
"text" : settings.get('message'),
"link" : {
"web_url" : "https://www.splunk.com"
}
})
}
response = requests.post(URL, headers=headers, data=data)
if response.json().get('result_code') == 0:
return True;
else:
print('Fail: ' + str(response.json()))
return False;
# 이 부분은 그대로 사용하자...
if __name__ == "__main__":
if len(sys.argv) > 1 and sys.argv[1] == "--execute":
payload = json.loads(sys.stdin.read())
if not send(payload.get('configuration')):
print("FATAL Failed trying to send notification", file=sys.stderr)
sys.exit(2)
else:
print("INFO Kakao notification successfully sent", file=sys.stderr)
else:
print("FATAL Unsupported execution mode (expected --execute flag)", file=sys.stderr)
sys.exit(1)
앞에서 보았던 파이썬 파일을 설정만 바뀌고 그대로 가져온 코드이다.
이제 알람을 보낼 앱에 대한 모든 준비가 끝났다.
주기적으로 메시지를 보낼 savedsearch 를 만들어 보자.
먼저 첫 번째 보낼 메시지는 매일 장이 끝나면 나의 자산 상태를 보고하는 SPL 이다.
| inputlookup my_stock |map search="| readstock code=$code$ | spath | eval share = $share$ | table code, price, share "
| eval asset = share * price
| lookup kospi_200 code OUTPUT name
| stats list(name) as name, list(price) as price, list(asset) as asset
| eval name = mvjoin(name, ","), price = mvjoin(price, ",") , asset = mvjoin(asset, ",")
단문으로 보내기 위해서 관련 데이터를 모두 하나의 row로 모았다.
해당 결과를 다음처럼 보고서로 만든다.
다른 이름으로 저장에서 보고서 클릭
이름을 입력하고 저장
스케쥴 클릭
자 이렇게 해서 새로운 스케쥴을 등록 했다. 매 시간 다음처럼 메시지를 받을 수 있다.
다음은 새로운 포트폴리오가 만들어 졌을 때 이를 카카오톡으로 보낸다.
실행 쿼리는 다음과 같다.
index="monte"
| rename code{} as codes, rate{} as rates
| eventstats latest(date) as latest_date
| where date = latest_date
| table date, Sharpe, codes , rates, Returns, Risk| sort -Sharpe limit=1
| streamstats count
| `my_mvexpand2(codes, rates)`
| rex field=codes "^(?<code>\d+).KS"
| lookup kospi_200 code OUTPUT name
| join code type=outer [ | inputlookup my_stock ]
| table code, interest, share, Sharpe, rates, name, Returns, Risk
| eval interest = if(isnull(interest), 1, interest), share = if(isnull(share), 0, share), target=round(rates * 100, 0)
| eval _key = code
| table _key, code, interest, share, target, name
| outputlookup my_stock append=true override_if_empty=true
| stats list(name) as name
| eval name = mvjoin(name, ",")
여기에서는 새로운 포트폴리오가 생성되면
가장 좋은 "Sharpe" 값을 선택하고 이를 kv-store 에 업데이트 한다. (Phase 3 참조)
그리고 메시지를 보낼 내용을 한 줄로 만들어 주었다.
이번에 my_stock 에 target 을 추가해서 업데이트 하였다.
target은 나의 총 자금에서 target 에 도달할 때 까지 주식을 보유하는데 사용할 것이다.
my_stock kv-store에 target 필드 추가
매월 1일 10시에 해당 포트폴리오를 업데이트 하고 메시지를 보낸다.
이렇게 해서 이번에는 저장된 검색을 만들고 이를 카카오톡으로 상황 메시지를 보내도록 만드는 과정을 살펴 보았다.
현재는 나홀로 시스템이기 때문에 카카오톡에 대한 기본 설정으로 가능하지만, 여러 명이 사용하는 시스템을 만들기 위해서는 위에 있는 카카오톡 개발자 메뉴얼을 통해서 하나씩 업그레이드 해 나가도록 하자.
'Splunk > Splunk Project' 카테고리의 다른 글
[ Splunk Project ] Splunk로 주식 분석 | Phase 10. 주식 매매 결정 하기 2 (0) | 2023.06.26 |
---|---|
[ Splunk Project ] Splunk로 주식 분석 | Phase 9. 주식 매매 결정 하기 (0) | 2023.06.26 |
[ Splunk Project ] Splunk로 주식 분석 | Phase 7. 주식 종목 추천 (0) | 2023.06.26 |
[ Splunk Project ] Splunk로 주식 분석 | Phase 6. 주식 포트폴리오 구성하기 (0) | 2023.06.22 |
[ Splunk Project ] Splunk로 주식 분석 | Phase 5. 주가 예측해 보기 (0) | 2023.06.22 |