# -*- 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(): # 날씨 정보 문자열 얻기 weather_content = get_precipitation_summary() # MAIN['content'] 업데이트 MAIN['content'] = weather_content today = datetime.today().strftime('%Y%m%d') script_dir = os.path.dirname(os.path.abspath(__file__)) capture_script = os.path.join(script_dir, 'weather_capture.py') weather_filename = f'weather_capture_{today}.png' weather_file = os.path.join(script_dir, weather_filename) thumb_file = os.path.join(script_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}") except Exception as e: print(f"[삭제 오류] {type(e).__name__}: {e}") if __name__ == "__main__": main()