RedPlug's Tory

zabbix에서 기존에 활용하던 쉘스크립트에서 curl이 작동을 하지않아 (원인은 아직도 파악 못함..)

방법을 찾다가 python으로 설정이 가능해서 해당 부분으로 작성하였습니다.

 

 

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
#!/usr/bin/env python
# coding: utf-8
 
import requests
import sys
import json
 
## zabbix에서 가져오는 파라미터 값
sendto = str(sys.argv[1])
subject = str(sys.argv[2])
message = str(sys.argv[3])
 
username = "Zabbix Bot"
 
## slack webhooks URL
url = "https://hooks.slack.com/services/XXXXX"
 
 
if subject.startswith("OK"):
    icon = ":smile:"
    color = "good"
elif subject.startswith("PROBLEM"):
    icon = ":skull"
    color = "danger"
else:
    icon = ":innocent:"
    color = "#439FE0"
 
def send_message_to_slack(url,sendto,subject,message):
 
payload = {"channel" : sendto,
    "username" : username,
    "icon_emoji" : icon,
    "attachment" : [
        {
        "color" : color,
        "text" : message
        }
    ]
 
requests.post(url, data=json.dumps(payload), headers={'Content-Type''application/json'})
 
send_message_to_slack(url,sendto,subject,message)
 

연휴에 일시켜서 미안해 여울아..

월~금 퇴근 시간즈음에 슬랙봇으로 퇴근전에 해야될 일들을 알람을 받게끔 crontab을 설정해둔게 있는데

연휴때도 이게 작동을 하다보니 예외처리 할 수 있는 방법이 뭐가 있나 찾아보니 crontab으로는 없는 것 같아서 

급한대로 코드에 내요을 추가 해둠.

콜시스템 휴일 처리를 매년 초에 확인해서 별도로 예외처리 하던 것이 생각나서 하기 방법으로 처리 하기로 함.

예외처리 날짜 설정 > 해당날짜가 있을 경우에 실행 안되게 끔 if문 설정

DB나 어디서 긁어와서 하는 방법이 차후에도 손이 덜 가게끔 하는 방법이라 그렇게 변경은 해둬야 할것 같은데

우선 급한대로 요렇게 해두니 작동은 잘하는 것으로 확인.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import datetime as dt

## 현재날짜
now = dt.datetime.now().strftime("%Y-%m-%d")

## 예외처리할 날짜 리스트로 입력
exceptiondates = ["2021-02-13","2021-02-14"]

## 기본값
= 0

## 예외처리 날짜와 일치할 경우 i 에 + 1
for exceptiondate in exceptiondates:
    if now == exceptiondate:
        i = i + 1

## 예외처리가 없는경우 실행
if i == 0:
    print("슬랙봇 발송 내용이 요기에 들어감")
 

 

기존에 밥집 추천을 list로 만들어둔게 있었는데 변경할 때마다 매번 코드를 수정해줘야 하는 불편함이 좀 있어서...

밥집을 수정하면 코드를 수정해야 하는 번거로움이.ㅠㅠ

DB에서 긁어오는 방법으로 변경 하기로 합니다.

우선 서버에 마리아 DB를 설치 한 후에 기존에 리스트 값을 DB에 넣어줍니다. (csv로 밀어넣음)

(bob_db database에 bob table)

필드는 number, name, url

밥집 리스트DB를 불러와서 추천해주기 위한 모듈을 하나 만듭니다.

 

모듈에서 DB에서 number를 불러와서 db사이즈 확인 후 랜덤하게 숫자를 선택후에 해당 number에 해당하는 name과 url을 가져와서 슬랙 봇에 붙여넣을 수 있게 변경 후 값을 리턴 합니다.

bob_recommend.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
# -*- coding:utf-8 -*-
 
import os
 
import mysql.connector
 
import random
 
def food_answer():
    dbid = os.environ.get('DATABASE_ID')
    dbpassword = os.environ.get('DATABASE_PASSWORD')
 
    config = {
        "user": dbid,
        "password": dbpassword,
        "host""localhost"#local
        "database""bob_db"#Database name
        "port""3306" #port는 최초 설치 시 입력한 값(기본값은 3306)
    }
 
    try:
 
        conn = mysql.connector.connect(**config)
        print(conn)
        # db select, insert, update, delete 작업 객체
        cursor = conn.cursor()
        # 실행할 select 문 구성
        sql = "SELECT MAX(number) FROM bob"
        # cursor 객체를 이용해서 수행한다.
        cursor.execute(sql)
        # select 된 결과 셋 얻어오기
        resultList = cursor.fetchall()  # tuple 이 들어있는 list
        size = resultList[0][0]
        print(size)
        random_select = random.randrange(1,int(size))+1
        sql = f"SELECT name,url FROM bob where number = {random_select}"
        cursor.execute(sql)
        resultList = cursor.fetchall()  # tuple 이 들어있는 list
        result = f"<{resultList[0][1]}|*{resultList[0][0]}*>"
        return result
 
    except mysql.connector.Error as err:
 
        print(err)
 

마리아 디비 땡겨오는걸 어디선가 긁어왔는데 출처를 저장을 안해놨네요. (__);

메인 파일에서 모듈 불러오고, 함수 변경

 

정상적으로 작동 확인

 

슬랙봇 : github.com/redplug/slackbot

Jira에서 발송되는 메일큐가 쌓일 경우에 Slack으로 알람이 오도록 설정하는 코드입니다.

마켓 플레이스에 xml로 볼 수 있게끔 만들어진 앱이 있어서 해당 앱을 설치 후 이용하였습니다.

 

Atlassian Marketplace Mail Queue Monitor REST API (Free)

marketplace.atlassian.com/apps/1214195/mail-queue-monitor-rest-api?hosting=server&tab=overview

 

Mail Queue Monitor REST API

Ever had outgoing mail fail unnoticed? Monitor your error queue to detect issues before your users do

marketplace.atlassian.com

 

 

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
import requests
import xml.etree.ElementTree as ET
 
# 웹훅 URL 주소
webhookurl = "Webhook URL"
 
# jira URL 주소
jiraurl = 'https://jira.redplug.com/rest/mailqueue/1.0/status'
 
# 알람 체크 갯수
notisize = 100 
 
# 웹훅 발송 함수
def send_message_to_slack(text):
   payload = {"text": text}
   requests.post(webhookurl, json=payload)
 
 
# 메일큐 확인
response = requests.get(jiraurl)
status = response.status_code
text = response.text
root = ET.fromstring(response.text)
size = int(root.find('size').text)
errorsize = int(root.find('errorSize').text)
 
# notisize 넘을경우 웹훅 
if size > notisize or errorsize > notisize:
   send_message_to_slack(f'JIRA Mail Queue Check \n Mail Queue Size : {size}개 \nMail Error Queie Size : {errorsize}개')
else:
   pass
 

slack 발송 테스트(notisize -1로 설정 후 실행)

 

현재 슬랙봇 만드는 과정은

노트북 Pycham으로 작업 > 커밋후 github로 푸시 > github에서 Jenkins로 webhook > jenkins에서 AWS로 pull > AWS에서 슬랙봇 가동의 형태로 이루어 지고 있습니다. (github 푸시 이후로 자동)

사실 처음에는 공부했던 파이썬을 어디 써먹을데 없나 하다가 예전부터 슬랙봇을 만들어보고 싶다라는 생각으로 시작했는데 생각보다 뭔가 하나씩 늘어가는 느낌이라 주말에 소소한 재미가 되고 있네요.

오늘은 github에 올리고 있던 슬랙봇 레파지토리를 공개로 돌려 보려고 합니다.

예전부터 퍼블릭으로 하려고 했는데 현재 작성하고 있던 파이썬 코드에는 슬랙봇 ID, 토큰, 네이버 클라이언트 ID, Secret 4가지가 포함이 되어있다보니 공개를 못하고 있었는데, 찾아보니 리눅스의 환경변수를 이용해서 가져오는 방법이 있어 해당 방법을 적용하였습니다.

우선

vi ~/.bashrc로 들어가서 최 하단에 export로 변수를 추가해줍니다. 

이후 source ~/.bashrc를 실행해서 export 명령어를 적용시키고

export 로 적용된 변수를 확인합니다.

이후 실제 작성하고 있던 코드상에 값들을 변수 값으로 대체를 합니다.

import os 추가 후

각 변수 별로 os.environ.get('export변수명') 으로 대체

코드 상에서 값들은 모두 삭제를 하였고

github에 기존 이력이 남아있기 때문에 히스토리를 삭제 해야 합니다.

삭제하는 방법은

1. 작업 폴더에서 .git 폴더를 삭제, 리눅스의 경우 rm -rf .git

2. 깃 초기화

git init

 

3. 초기화할 파일 추가 후 최초 커밋

git add .

git commit -m "first commit"

 

4. 저장소 연결 후 푸시

git remote add orign <github url>

git push -u --force origin master

github URL은 레파지토리 > code에서 확인 가능

 

github에서 히스토리 삭제 확인

이후 해당 레파지토리 > Settings > 최하단에 Change repository visibility에서 Make public 선택하고 하단에 레파지토리명 입력 후에 변경 처리 하면됩니다.

 

 

업무를 하던 도중 주소줄여서 적어야 하는 케이스가 간혹 생겨 귀찮이즘에 슬랙봇을 만들어야겠다! 라는 생각을 합니다.

주소 단축사이트에서 웹크롤링을 이용해서 가져오려고 했는데 뭔가 불필요한 부분이 많은것 같아서 API를 찾아보던 중 네이버에서 제공 하는 API가 있어서 그걸 이용하여 만들어 보았습니다.

 

url 단축 API를 사용하기 위해서는 네이버 개발자 센터에 계정등록 > 애플리케이션 등록 > 클라이언트 아이디와 시크릿 값을 받아와야 합니다.

developers.naver.com/docs/utils/shortenurl/

 

단축 URL API 적용 가이드

단축 URL API는 원본 URL을 `http://me2.do/example`과 같은 형태의 짧은 URL로 반환하는 RESTful API입니다.

developers.naver.com

상기 주소에 사전 준비사항 참고하여 필요한 값을 생성합니다.

Client ID, Client Secret 값을 우선 만들어둡니다.

 

 

Slackchatbot.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
from urlshort import url_short
        elif event_message.find(surl) > -1:
            channel = slack_event["event"]["channel"]
            orignalurl = event_message.replace("주소단축 ","")
            print(surl)
            if event_message.replace(" ",""== surl:
                slack.chat.post_message(channel, f"주소단축 뒤에 주소를 넣어주시면 여울이가 줄여줄게요")
 
            elif event_message != surl:
                ssurl = url_short(orignalurl)
                username = '여울이가 주소를 줄여줘요!'
                icon_emoji = ''
                attachement = {
                    'pretext''여울이의 ShortUrl',
                    "fallback""여울이 ShortUrl",
                    "text": f"여울이가 주소를 줄였어요.  {ssurl}\n",
                    "fields": [
                        {
                            "value""",
                            "short"False
                        }
                    ],
                    "color""good",
                }
 
                slack.chat.post_message(channel, attachments=[attachement], username=username, icon_emoji=icon_emoji)
 
            return make_response("앱 멘션 메시지가 보내졌습니다."200, )
 
 

urlshort.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
# -*- coding: utf-8 -*-
 
import urllib.request
 
import json

import html
 
def url_short(orignalurl):
    replaceurl = html.unescape(orignalurl.replace("<""").replace(">""")) # 슬랙에서 링크일 경우 <> 붙여ㅓ 해당 부분 삭제
    index = replaceurl.find("|"# http를 넣지 않을경우 |이후 추가적으로 문자열이 찍혀 해당 부분 삭제하기 위함
    client_id = "AAAAA"  # 개발자센터에서 발급받은 Client ID 값
    client_secret = "BBBBB"  # 개발자센터에서 발급받은 Client Secret 값
    encText = urllib.parse.quote(replaceurl[:index]) # index위치 이후 삭제
    data = "url=" + encText
    url = "https://openapi.naver.com/v1/util/shorturl"
    request = urllib.request.Request(url)
    request.add_header("X-Naver-Client-Id", client_id)
    request.add_header("X-Naver-Client-Secret", client_secret)
    response = urllib.request.urlopen(request, data=data.encode("utf-8"))
    rescode = response.getcode()
    if (rescode == 200):
        response_body = response.read()
        shorturl = json.loads(response_body.decode('utf-8'))
        returnurl = shorturl['result']['url']
    else:
        print("Error Code:" + rescode)
 
    print(returnurl)
    return returnurl
 
 

실제 주소를 줄여주는 코드(개발자 센터 예제에서 필요한 부분만 수정하였습니다.)

 

정상적으로 값을 가져옵니다.

봇으로 간단하게 메시지 보내는 코드

반복이 필요한 경우 crontab을 이용하여 반복 실행한다

# -*- coding: utf-8 -*-
from slacker import Slacker


token = '봇토큰'
slack = Slacker (token)

slack.chat.post_message('#채널명', ":이모지:제목:이모지: \n 내용 \n https://naver.com")

 

 

밥집 추천 슬랙 봇

  • 사전에 봇 등록하여 토큰발급과 event Subscriptions 등록 필요.
  • 플라스크를 이용하여 봇에게 멘션이 들어올 경우 밥집을 랜덤하게 리턴해주는 코드

 

# -*- coding: utf-8 -*-

import json

from slacker import Slacker

from flask import Flask, request, make_response

import random

## 슬랙 봇 토큰 ## 
token  = "슬랙봇 토큰"

slack = Slacker(token)

app = Flask(__name__)

def get_answer():
    food = ['밥집1','밥집2','밥집3']
    random.shuffle(food)
    return food


# 이벤트 핸들하는 함수

def event_handler(event_type, slack_event):

    if event_type == "app_mention":

        channel = slack_event["event"]["channel"]

        text = get_answer()

        slack.chat.post_message(channel, "오늘의 밥집 추천은 {text[0]} 입니다")

        return make_response("앱 멘션 메시지가 보내졌습니다.", 200, )

    message = "[%s] 이벤트 핸들러를 찾을 수 없습니다." % event_type

    return make_response(message, 200, {"X-Slack-No-Retry": 1})



@app.route("/slack", methods=["GET", "POST"])

def hears():

    slack_event = json.loads(request.data)

    if "challenge" in slack_event:

        return make_response(slack_event["challenge"], 200, {"content_type": "application/json"})

    if "event" in slack_event:

        event_type = slack_event["event"]["type"]

        return event_handler(event_type, slack_event)

    return make_response("슬랙 요청에 이벤트가 없습니다.", 404, {"X-Slack-No-Retry": 1})



if __name__ == '__main__':

    app.run('0.0.0.0', port=8080)

 

 

latest 변수와 latest.txt파일에 제목을 비교해서 동일한 값이 아닐 경우 새글이 올라왔어요 + 글제목 + 링크를 함께 텔레그렘 봇이 보내주는 코드

텔레그램 봇 사진 발급 필요.

requests, bs4, telegram봇 모듈 설치 필요.

새글이 있을 경우 텔레그램 봇이 뿌려줌

반복은 crontab을 통해서 원하는 기간별로 진행

#tigpnd.py
# -*- coding: utf-8 -*-

import requests
from bs4 import BeautifulSoup
import os
import time

import telegram


bot = telegram.Bot(token='텔레그램봇토큰')
chat_id = bot.getUpdates()[-1].message.chat.id

BASE_DIR = os.path.dirname(os.path.abspath(__file__))
req = requests.get('https://www.thisisgame.com/pad/tboard/?board=25')
html = req.text
soup = BeautifulSoup(html, 'html.parser')
posts = soup.select('td > a')
latest = posts[14].text
href = posts[14].get('href')
url = 'https://www.thisisgame.com/pad/tboard/'
link = url + str(href)
with open(os.path.join(BASE_DIR, 'latest.txt'), 'r+') as f_read:
    before = f_read.readline()
    if before != latest:
        bot.sendMessage(chat_id=chat_id, text='새 글이 올라왔어요! : ' + latest + link)
    f_read.close()

with open(os.path.join(BASE_DIR, 'latest.txt'), 'w+') as f_write:
    f_write.write(latest)
    print(latest)
    f_write.close()