테스트 사이트 - 개발 중인 베타 버전입니다

그누보드 자동 글 작성 + 멀티 파일 업로드 스크립트 (Python)

· 4년 전 · 7012 · 11

냑 회원님들 안녕하세요? ^-^

 

이번 주말에는 비가 많이 오네요~ 

 

다들 비 피해 없으시기를 기원할게요! :)

 

 

저번에 작성했던 'Python으로 구현한 그누보드 자동 글쓰기 함수'( https://sir.kr/g5_tip/15678 )를 보완하여

 

멀티 파일 업로드까지 가능하도록 업데이트 하였습니다 ^^

 

그누보드 PHP 내장함수를 사용할 수 없기 때문에 해당 함수를 파이썬으로 변환하여 적절히 처리했구요~

 

다만 replace_filename() 함수에서 SHA1 방식 암호화를 하는 부분 중에 사용자 IP는 제외했습니다.

 

참고로 pymysql과 ftputil을 제외하면 Anaconda에 포함된 기본 모듈만 사용했어요 :)

 

 

아래 스크립트는 외부에서 그누보드 DB 및 FTP에 접속하는 것을 전제로 구현되었기 때문에

 

호스팅 또는 VPS에서 DB와 FTP에 외부접속할 수 있도록 설정하셔야 정상적으로 작동합니다.

 

 

[code]

import pymysql, ftputil, hashlib, os, sys

from datetime import datetime

from PIL import Image


 

def file_type(x): # 그누보드의 bf_type 값을 반환하는 함수입니다. (디폴트 : 0)

    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(x.lower(), '0')


 

def file_upload(filename, bf_file): # FTP를 이용하여 파일을 업로드하는 함수입니다.

    with ftputil.FTPHost('URL을입력하세요', 'FTP계정명을입력하세요', 'FTP비번을입력하세요') as fh:

        fh.chdir('업로드할디렉토리를입력하세요ex./web/data/file/board')

        fh.upload(filename, bf_file, callback = None)

    return


 

def get_filename(filename): # 파일명을 변환하는 함수입니다.

    ms = datetime.now().microsecond

    encoded_name = filename.encode('utf-8')

    result = f'{ms}_{hashlib.sha1(encoded_name).hexdigest()}'

    return result


 

def board_write(board, subject, content, mb_id, nickname, file_list = None):

    # MySQL connection 및 cursor 생성

    conn = pymysql.connect(host = '연결할URL을입력하세요', 

                           user = 'MySQL유저명을입력하세요', 

                           password = 'MySQL비번을입력하세요',

                           db = 'MySQL디비명을입력하세요', 

                           charset = 'utf8')

    curs = conn.cursor()

 

    # 작성글 INSERT

    sql = f"select wr_num from g5_write_{board}"

    curs.execute(sql)

    wr_num = str(int(curs.fetchone()[0]) - 1)

    print(wr_num)

    now = datetime.today().strftime('%Y-%m-%d %H:%M:%S') # 그누보드의 날짜 형식 준수 (ex: 2021-04-05 23:45:15)

    sql = f"insert into g5_write_{board} set wr_num = {wr_num}, \

          wr_reply = '', wr_comment = 0, ca_name = '', wr_option = 'html1', wr_subject = '{subject}', \

          wr_content = '{content}', wr_link1 = '', wr_link2 = '', \

          wr_link1_hit = 0, wr_link2_hit = 0, wr_hit = 1, wr_good = 0, wr_nogood = 0, \

          mb_id = '{mb_id}', wr_password = '', wr_name = '{nickname}', wr_email = '', wr_homepage = '', \

          wr_datetime = '{now}', wr_last = '{now}', wr_ip = '111.111.111.111', \

          wr_1 = '', wr_2 = '', wr_3 = '', wr_4 = '', wr_5 = '', \

          wr_6 = '', wr_7 = '', wr_8 = '', wr_9 = '', wr_10 = '', \

          wr_comment_reply = '', wr_facebook_user = '', wr_twitter_user = '', \

          as_re_name = '', as_tag = '', as_map = '', as_icon = '', as_thumb = '', as_video = ''"

    curs.execute(sql)

 

    # 부모 아이디에 UPDATE

    sql = f"select wr_id from g5_write_{board}"

    curs.execute(sql)

    wr_id = str(curs.fetchall()[-1][0])

    print(f"wr_id : {wr_id}")

    sql = f"update g5_write_{board} set wr_parent = {wr_id} where wr_id = {wr_id}"

    curs.execute(sql)

 

    # 새글 INSERT

    sql = f"insert into g5_board_new ( bo_table, wr_id, wr_parent, bn_datetime, mb_id ) values \

          ( '{board}', '{wr_id}', '{wr_id}', '{now}', '{mb_id}' )"

    curs.execute(sql)

 

    # 게시글 1 증가

    sql = f"select bo_count_write from g5_board where bo_table = '{board}'"

    curs.execute(sql)

    bo_count_write = str(int(curs.fetchone()[0]))

    print(curs.fetchall())

    print(bo_count_write)

    sql = f"update g5_board set bo_count_write = {bo_count_write} + 1 where bo_table = '{board}'"

    curs.execute(sql)

 

    # 파일 업로드 및 관련 정보를 테이블에 저장

    if not file_list or file_list == [''] or file_list == []: # 첨부파일이 없는 경우에는 스크립트를 중단합니다.

        conn.close()

        sys.exit()

 

    file_count = len(file_list)

    for cnt, file in enumerate(file_list):

        ext = os.path.splitext(file)[1].lstrip('.')

        bf_file = f'{get_filename(file)}.{ext}'

        file_upload(file, bf_file)

        type = file_type(ext)

        if type != '0': # 이미지 파일의 경우 가로 및 세로를 구하고, 그 외의 경우에는 0을 대입합니다.

            im = Image.open(file)

            width, height = im.size

        else:

            width, height = 0, 0

        size = os.path.getsize(file)

        sql = f"insert into g5_board_file set bo_table = '{board}', wr_id = '{wr_id}', \

              bf_no = '{cnt}', bf_source = '{file}', bf_file = '{bf_file}', \

              bf_content = '', bf_download = 0, bf_filesize = '{size}', \

              bf_width = '{width}', bf_height = '{height}', bf_type = '{type}', bf_datetime = '{now}'"

        curs.execute(sql)

    

    # 파일의 개수를 게시물에 업데이트

    sql = f"update g5_write_board set wr_file = '{file_count}' where wr_id = '{wr_id}'"

    curs.execute(sql)

 

    # MySQL connection 닫기

    conn.close()

    return


 

def main():

    board = '게시판명을입력하세요'

    subject = '제목을입력하세요'

    content = '내용을입력하세요HTML태그도가능합니다'

    mb_id = '아이디를입력하세요'

    nickname = '닉네임을입력하세요'

    file_list = ['업로드할파일명을입력하세요', '업로드할파일명을입력하세요']

    board_write(board, subject, content, mb_id, nickname, file_list)


 

if __name__ == "__main__":

    main()

[/code]

 

 

위 스크립트를 활용하여 3개의 파일(PNG, GIF, PY)을 업로드한 결과는 다음과 같습니다 ^^

 

영문이나 숫자가 아닌 한글로 된 파일명도 정상적으로 업로드되는 것을 확인했어요~

 

아미나에서 테스트하였지만 그누보드 5.4에서도 대동소이할 것으로 생각되네요 :)

 

 

3666978703_1621123092.7271.png

(냥냥펀치!)

 

 

테스트해보니 작성자명을 계정의 실제 닉네임과 달리 적용한 경우에

 

위 함수로 글을 올린 후 로그인하여 글을 수정하면 해당 계정의 실제 닉네임으로 변경되는 점을 주의하셔야 됩니다!

 

 

crontab에 넣고 장기적으로 실사용하시려면 다음과 같은 부분을 보완하시는 것을 권장합니다 ^^

 

1. 오류 처리

 

파일 업로드 실패 등의 경우에 글과 첨부파일을 삭제하고 sys.exit() 하도록 처리하면 좋을 것 같네요.

 

 

2. 보안

 

사이트 운영자가 직접 글 내용과 이미지를 선별하여 사용할 것이라면 별다른 보안 이슈는 없겠지만,

 

명랑폐인 님께서 올려주신 '게시판 파싱후 글등록 처리 함수'을 참고하여 조금 더 보완하시면 도움이 될듯요~

 

https://sir.kr/g5_tip/6977

 

만약 타 사이트에서 파싱한 결과물을 위 함수를 이용하여 그대로 올리는 목적으로 사용하시려면

 

SQL injection, steganography 등 기법에도 대응할 수 있도록 보완해야 안전할 것 같습니다 ㅎㄷㄷ

 

 

이상 허접한 스크립트인데 읽어주셔서 감사합니다!

 

다음에는 위 함수를 활용하여 브라우저에 접속하지 않은 상태에서

 

곧바로 글 작성 및 첨부파일 업로드를 할 수 있는 GUI 프로그램을 작성해볼게요~ 

 

그럼 냑 회원님들 다들 좋은 주말 되시고, 내일까지 비가 온다니 아침에 우산 꼭 챙기세요 ^-^

 

감사합니다!!

댓글 작성

댓글을 작성하시려면 로그인이 필요합니다.

로그인하기

댓글 11개

1년 전

유용한 자료 감사합니다.

게시글 목록

번호 제목
24318
24317
24315
24309
24294
24293
24277
24262
24260
24253
24251
24236
24233
24228
24226
24221
24214
24203
24201
24199
24196
24195
24194
24192
24191
24187
24185
24183
24172
24168