Files
fg-auto/autouploader/gnu_autoupload.py

212 lines
7.8 KiB
Python

# -*- coding: utf-8 -*-
"""
gnu_autoupload.py
기능:
1. Selenium을 이용해 날씨 정보를 캡처 (weather_capture.py 호출)
2. FTP를 이용해 이미지 업로드
3. 그누보드 DB에 게시글 및 첨부파일 정보 자동 등록
"""
import os
import sys
import time
import subprocess
import tempfile
import hashlib
from datetime import datetime
from PIL import Image
import pymysql
import ftputil
from config import DB_CONFIG, FTP_CONFIG, MAIN
from weather import get_precipitation_summary
# ---------------------------
# 이미지 캡처 함수
# ---------------------------
def capture_image(script_path, output_path, max_attempts=5):
for attempt in range(max_attempts):
print(f"[{datetime.now().strftime('%H:%M:%S')}] 이미지 캡처 시도 {attempt + 1}/{max_attempts}")
try:
subprocess.run([sys.executable, script_path], check=True)
except subprocess.CalledProcessError as e:
print(f"[오류] weather_capture.py 실행 실패: {e}")
if os.path.isfile(output_path):
print(f"[성공] 이미지가 정상적으로 캡처되었습니다: {output_path}")
return True
time.sleep(2)
print(f"[실패] {max_attempts}회 시도 후에도 이미지가 생성되지 않았습니다.")
return False
# ---------------------------
# 파일 관련 유틸 함수
# ---------------------------
def file_type(ext):
return {
'gif': '1', 'jpeg': '2', 'jpg': '2', 'png': '3', 'swf': '4',
'psd': '5', 'bmp': '6', 'tif': '7', 'tiff': '7', 'jpc': '9',
'jp2': '10', 'jpx': '11', 'jb2': '12', 'swc': '13', 'iff': '14',
'wbmp': '15', 'xbm': '16'
}.get(ext.lower(), '0')
def get_filename(filename):
ms = datetime.now().microsecond
encoded_name = filename.encode('utf-8')
return f'{ms}_{hashlib.sha1(encoded_name).hexdigest()}'
def file_upload(filename, bf_file):
try:
with ftputil.FTPHost(FTP_CONFIG['HOST'], FTP_CONFIG['USER'], FTP_CONFIG['PASS']) as fh:
fh.chdir(FTP_CONFIG['UPLOAD_DIR'])
fh.upload(filename, bf_file)
print(f"[업로드 완료] '{filename}''{bf_file}' 로 FTP 업로드 완료")
return True
except Exception as e:
print(f"[FTP 오류] {type(e).__name__}: {e}")
return False
# ---------------------------
# 게시글 작성 함수
# ---------------------------
def write_board(board, subject, content, mb_id, nickname, ca_name=None, file_list=None):
try:
conn = pymysql.connect(
host=DB_CONFIG['HOST'],
user=DB_CONFIG['USER'],
db=DB_CONFIG['DBNAME'],
password=DB_CONFIG['PASS'],
charset=DB_CONFIG['CHARSET']
)
curs = conn.cursor()
now = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
curs.execute(f"SELECT wr_num FROM g5_write_{board}")
wr_num = str(int(curs.fetchone()[0]) - 1)
curs.execute(f"""INSERT INTO g5_write_{board} SET wr_num = {wr_num},
wr_reply = '', wr_comment = 0, ca_name = %s, wr_option = 'html1', wr_subject = %s,
wr_content = %s, wr_link1 = '', wr_link2 = '', wr_link1_hit = 0, wr_link2_hit = 0,
wr_hit = 1, wr_good = 0, wr_nogood = 0, mb_id = %s, wr_password = '',
wr_name = %s, wr_email = '', wr_homepage = '',
wr_datetime = %s, wr_last = %s,
wr_ip = '111.111.111.111',
wr_comment_reply = '', wr_facebook_user = '', wr_twitter_user = '',
wr_1 = '', wr_2 = '', wr_3 = '', wr_4 = '', wr_5 = '', wr_6 = '', wr_7 = '', wr_8 = '', wr_9 = '', wr_10 = ''
""",
(ca_name, subject, content, mb_id, nickname, now, now))
curs.execute(f"SELECT wr_id FROM g5_write_{board} ORDER BY wr_id DESC LIMIT 1")
wr_id = str(curs.fetchone()[0])
curs.execute(f"UPDATE g5_write_{board} SET wr_parent = {wr_id} WHERE wr_id = {wr_id}")
curs.execute(f"""INSERT INTO g5_board_new (bo_table, wr_id, wr_parent, bn_datetime, mb_id)
VALUES (%s, %s, %s, %s, %s)""", (board, wr_id, wr_id, now, mb_id))
curs.execute(f"SELECT bo_count_write FROM g5_board WHERE bo_table = %s", (board,))
bo_count_write = int(curs.fetchone()[0])
curs.execute(f"UPDATE g5_board SET bo_count_write = %s WHERE bo_table = %s",
(bo_count_write + 1, board))
file_count = 0
if file_list:
for idx, file in enumerate(file_list):
ext = os.path.splitext(file)[1].lstrip('.')
bf_file = f"{get_filename(file)}.{ext}"
if file_upload(file, bf_file):
img_type = file_type(ext)
width, height = (0, 0)
if img_type != '0':
with Image.open(file) as img:
width, height = img.size
size = os.path.getsize(file)
curs.execute(f"""INSERT INTO g5_board_file SET bo_table = %s, wr_id = %s, bf_no = %s,
bf_source = %s, bf_file = %s, bf_content = '', bf_download = 0,
bf_filesize = %s, bf_width = %s, bf_height = %s, bf_type = %s, bf_datetime = %s""",
(board, wr_id, idx, os.path.basename(file), bf_file,
size, width, height, img_type, now))
file_count += 1
else:
raise Exception(f"[FTP 오류] 파일 업로드 실패: {file}")
curs.execute(f"UPDATE g5_write_{board} SET wr_file = %s WHERE wr_id = %s", (file_count, wr_id))
conn.commit()
print("[성공] 게시글과 첨부파일 등록 완료")
except Exception as e:
conn.rollback()
if "[FTP 오류]" in str(e):
print(f"[FTP 오류] {e}")
else:
print(f"[DB 오류] {type(e).__name__}: {e}")
raise
finally:
conn.close()
# ---------------------------
# 메인 실행 함수
# ---------------------------
def main():
# 기상청 API로 얻어오는 데이터와 캡처의 데이터가 다르므로 내용에 대해 업데이트 하지 않음.
# 날씨 정보 문자열 얻기
#weather_content = get_precipitation_summary()
# MAIN['content'] 업데이트
#MAIN['content'] = weather_content
# 무료입장 조건에 대해서만 안내함.
MAIN["content"] = """
<p>Rainy Day 이벤트 적용안내</p>
<p><b>10:00 ~ 22:00까지의 예보를 합산하며, ~1mm인 경우 0.5mm로 계산합니다.</b></p>
"""
today = datetime.today().strftime('%Y%m%d')
data_dir = '/data' # 파일 저장 및 업로드 디렉토리
capture_script = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'weather_capture.py')
weather_filename = f'weather_capture_{today}.png'
weather_file = os.path.join(data_dir, weather_filename)
thumb_file = os.path.join(data_dir, 'thumb.jpg')
if not capture_image(capture_script, weather_file):
return
FTP_CONFIG['UPLOAD_DIR'] = f"/www/data/file/{MAIN['board']}/"
MAIN['subject'] = f"{datetime.now().strftime('%Y-%m-%d')} 날씨정보"
MAIN['file1'] = thumb_file
MAIN['file2'] = weather_file
file_list = [MAIN['file1'], MAIN['file2']]
write_board(
board=MAIN['board'],
subject=MAIN['subject'],
content=MAIN['content'],
mb_id=MAIN['mb_id'],
nickname=MAIN['nickname'],
ca_name=MAIN['ca_name'],
file_list=file_list
)
try:
## weather_file만 삭제, thumb.jpg는 삭제하지 않음
#if os.path.isfile(weather_file):
# os.remove(weather_file)
# print(f"[정리 완료] 캡처 이미지 삭제됨: {weather_file}")
pass
except Exception as e:
print(f"[삭제 오류] {type(e).__name__}: {e}")
if __name__ == "__main__":
main()