diff --git a/data/gnu_autoupload.py b/data/gnu_autoupload.py index 322bede..1d22914 100644 --- a/data/gnu_autoupload.py +++ b/data/gnu_autoupload.py @@ -4,7 +4,7 @@ gnu_autoupload.py 기능: 1. Selenium을 이용해 날씨 정보를 캡처 (weather_capture.py 호출) -2. FTP를 이용해 이미지 업로드 +2. FTP를 이용해 이미지 업로드 (썸네일 포함) 3. 그누보드 DB에 게시글 및 첨부파일 정보 자동 등록 """ @@ -21,39 +21,27 @@ import ftputil from config import DB_CONFIG, FTP_CONFIG, MAIN - # --------------------------- # 이미지 캡처 관련 함수 # --------------------------- def capture_image(script_path, output_path, max_attempts=5): - """ - weather_capture.py를 실행해 이미지 파일을 생성 - :param script_path: 캡처 스크립트 경로 - :param output_path: 기대되는 이미지 파일 경로 - :param max_attempts: 최대 재시도 횟수 - :return: 성공 여부 (True/False) - """ for attempt in range(max_attempts): - print(f"[{datetime.now().strftime('%H:%M:%S')}] 캡처 시도 {attempt + 1}/{max_attempts}") + print(f"[{datetime.now().strftime('%H:%M:%S')}] \uac00\uc0ac\uac1c \uc2dc\ub3c4 {attempt + 1}/{max_attempts}") try: subprocess.run(['python3', script_path], check=True) except subprocess.CalledProcessError as e: - print(f"[오류] weather_capture.py 실행 실패: {e}") + print(f"[\uc624\ub958] weather_capture.py \uc2e4\ud589 \uc2e4\ud328: {e}") if os.path.isfile(output_path): - print(f"[성공] 이미지 캡처 완료: {output_path}") + print(f"[\uc131\uacf5] \uc774\ubbf8\uc9c0 \uce90\ud504 \uc644\ub8cc: {output_path}") return True time.sleep(2) - print(f"[실패] {max_attempts}회 시도 후에도 이미지가 생성되지 않았습니다.") + print(f"[\uc2e4\ud328] {max_attempts}\ud68c \uc2dc\ub3c4 \ud6c4\uc5d0\ub3c4 \uc774\ubbf8\uc9c0\uac00 \uc0dd\uc131\ub418\uc9c0 \uc54a\uc558\uc2b5\ub2c8\ub2e4.") 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', @@ -61,64 +49,37 @@ def file_type(ext): '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): - """ - FTP 서버에 파일 업로드 - :param filename: 로컬 경로 - :param 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}") + print(f"[\uc5c5\ub85c\ub4dc \uc644\ub8cc] {filename} → {bf_file}") return True except Exception as e: - print(f"[FTP 오류] {type(e).__name__}: {e}") + print(f"[FTP \uc624\ub958] {type(e).__name__}: {e}") return False - # --------------------------- # 게시글 작성 함수 # --------------------------- def write_board(board, subject, content, mb_id, nickname, ca_name=None, file_list=None): - """ - 그누보드 DB에 게시글과 파일을 한 트랜잭션으로 삽입 - :param board: 게시판 ID - :param subject: 제목 - :param content: 내용 - :param mb_id: 회원 ID - :param nickname: 작성자 이름 - :param ca_name: 카테고리명 - :param file_list: 첨부파일 경로 리스트 - """ try: - # 데이터베이스 연결 conn = pymysql.connect( - host=DB_CONFIG['HOST'], - user=DB_CONFIG['USER'], - db=DB_CONFIG['DBNAME'], - password=DB_CONFIG['PASS'], - charset='utf8' + host=DB_CONFIG['HOST'], user=DB_CONFIG['USER'], db=DB_CONFIG['DBNAME'], + password=DB_CONFIG['PASS'], charset='utf8' ) curs = conn.cursor() now = datetime.now().strftime('%Y-%m-%d %H:%M:%S') - # 게시글 번호(wr_num) 계산 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, @@ -131,24 +92,19 @@ def write_board(board, subject, content, mb_id, nickname, ca_name=None, file_lis """, (ca_name, subject, content, mb_id, nickname, now, now)) - # wr_id 조회 curs.execute(f"SELECT wr_id FROM g5_write_{board} ORDER BY wr_id DESC LIMIT 1") wr_id = str(curs.fetchone()[0]) - # wr_parent 업데이트 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): @@ -170,48 +126,43 @@ def write_board(board, subject, content, mb_id, nickname, ca_name=None, file_lis size, width, height, img_type, now)) file_count += 1 else: - print(f"[경고] 파일 업로드 실패: {file}") + print(f"[\uacbd\uace0] \ud30c\uc77c \uc5c5\ub85c\ub4dc \uc2e4\ud328: {file}") - # 첨부파일 수 업데이트 curs.execute(f"UPDATE g5_write_{board} SET wr_file = %s WHERE wr_id = %s", (file_count, wr_id)) - - # 트랜잭션 커밋 (단 1회) conn.commit() - print("[완료] 게시글 작성 및 파일 업로드 완료") + print("[\uc644\ub8cc] \uac8c\uc2dc\uae00 \uc791\uc131 \ubc0f \ud30c\uc77c \uc5c5\ub85c\ub4dc \uc644\ub8cc") except Exception as e: - # 예외 발생 시 롤백 conn.rollback() - print(f"[DB 오류] {type(e).__name__}: {e}") + print(f"[DB \uc624\ub958] {type(e).__name__}: {e}") finally: - # 연결 종료 conn.close() - - # --------------------------- # 메인 실행 함수 # --------------------------- def main(): - # 파일 경로 및 이름 설정 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 os.path.isfile(thumb_file): + print(f"[\uc624\ub958] \uc368\uba58\ub0b4\uc77c \ud30c\uc77c\uc774 \uc874\uc7ac\ud558\uc9c0 \uc54a\uc74c: {thumb_file}") + return + 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'] = MAIN['file2'] = weather_file + MAIN['subject'] = f"[{datetime.now().strftime('%Y-%m-%d')}] \ub0a0\uc528 \uc815\ubcf4" + MAIN['file1'] = thumb_file + MAIN['file2'] = weather_file - file_list = [MAIN['file1']] + file_list = [MAIN['file1'], MAIN['file2']] - # 게시글 작성 write_board( board=MAIN['board'], subject=MAIN['subject'], @@ -222,14 +173,12 @@ def main(): file_list=file_list ) - # 캡처 파일 삭제 try: if os.path.isfile(weather_file): os.remove(weather_file) - print(f"[삭제 완료] {weather_file}") + print(f"[\uc0ad\uc81c \uc644\ub8cc] {weather_file}") except Exception as e: - print(f"[삭제 오류] {type(e).__name__}: {e}") - + print(f"[\uc0ad\uc81c \uc624\ub958] {type(e).__name__}: {e}") # --------------------------- # 스크립트 실행 진입점