Python 위챗 자동화 봇: pip 설치를 통한 활용성 증대

이 문서는 Python 기반 위챗(WeChat) 자동화 봇의 사용 편의성을 개선하고, 표준 Python 패키지 관리 도구인 pip를 통해 손쉽게 설치 및 관리할 수 있도록 최적화된 방법에 대해 설명합니다.

주요 개선 사항

  • 핵심 후킹(hooking) 기능을 담당하는 라이브러리를 독립적인 Python 패키지로 분리하여 PyPI(Python Package Index)에 배포했습니다.
  • 위챗 관련 자동화 기능을 제공하는 코드를 별도의 라이브러리로 분리하고, 이 역시 pip를 통해 설치 가능하도록 제공합니다.
  • 모든 관련 소스 코드는 하나의 통합된 Git 저장소에서 관리되어, 향후 업데이트 및 기능 추가가 용이합니다.

사용 가이드

지원되는 위챗 클라이언트 버전

현재 다음 버전의 위챗 클라이언트가 공식적으로 지원됩니다:

  • 32비트: 3.9.8.12
  • 64비트: 3.9.8.15

최신 위챗 버전 지원은 지속적으로 업데이트될 예정이며, 커뮤니티 기여를 통해 더 빠르게 반영될 수 있습니다.

현재 제공되는 기능

  • 텍스트 메시지 전송
  • 이미지 메시지 전송
  • 위챗 내부 로그 출력 후킹
  • 수신 메시지 후킹 (향후 업데이트 예정)
  • 메시지 회수 방지 (향후 업데이트 예정)

환경 설정

  1. 지원되는 위챗 클라이언트 버전 설치 (다운로드 링크: https://www.123pan.com/s/ihEKVv-XcWx.html, 추출 코드: 5WLu)
  2. 설치한 위챗 클라이언트의 비트 수(32비트 또는 64비트)에 맞는 Python 3.7 이상 버전을 설치합니다.
  3. 다음 명령을 사용하여 필요한 라이브러리를 설치합니다:
    pip install --upgrade wechat_pyrobot

이후 코드 업데이트가 필요한 경우, 위의 pip install --upgrade wechat_pyrobot 명령을 다시 실행하여 최신 버전을 적용할 수 있습니다.

기본 사용법: 프로세스 주입

먼저, 작업 디렉토리(예: robot_scripts)를 생성하고 그 안에 main_injector.py (파일명은 자유) 파일을 생성하여 다음 코드를 작성합니다.

import os
from py_process_hooker import inject_python_and_monitor_dir

if __name__ == "__main__":
    target_process_name = "WeChat.exe"
    display_console_output = True # 디버깅을 위해 콘솔 출력 활성화 여부
    
    # 현재 스크립트 파일의 경로를 모니터링 대상으로 지정
    script_directory = os.path.dirname(os.path.abspath(__file__)) 
    
    inject_python_and_monitor_dir(
        target_process_name, 
        script_directory, 
        open_console=display_console_output
    )
    print(f"[{target_process_name}] 프로세스에 Python 스크립트 주입을 시도합니다.")
    print(f"모니터링 디렉토리: {script_directory}")
    if display_console_output:
        print("디버그 콘솔이 활성화됩니다.")
    else:
        print("콘솔 출력은 비활성화됩니다.")

위챗을 실행하고 로그인한 후, 이 main_injector.py 파일을 실행하면 Python 코드가 위챗 프로세스에 주입되고 디버깅을 위한 콘솔이 열립니다. display_console_output 값을 False로 설정하면 콘솔이 열리지 않지만, 디버깅 시에는 True로 설정하는 것이 편리합니다.

main_injector.py가 실행된 후, 동일한 디렉토리에 생성하는 Python 코드 파일(숫자로 시작하지 않는 파일명)은 자동으로 위챗 프로세스 내에서 로드되고 실행됩니다.

메시지 전송 예제

message_sender_example.py 파일을 생성하여 다음 코드를 저장합니다:

import time
from wechat_pyrobot.api import MessageSender # 새로운 모듈 경로 사용

# 메시지 전송 클라이언트 인스턴스 생성
msg_client = MessageSender()

# 파일 도우미(filehelper)에게 텍스트 메시지 전송
target_recipient_id = "filehelper" 
text_content = "파이썬 자동화 봇에서 보낸 테스트 메시지입니다!"
msg_client.send_text(target_recipient_id, text_content)
print(f"텍스트 메시지 전송 완료: '{text_content}'")

# 메시지 전송 간에는 적절한 시간 간격을 두어 안정적인 작동을 보장합니다.
time.sleep(1.5) # 1.5초 대기

# 이미지 메시지 전송
# 로컬 시스템에 존재하는 이미지 파일의 전체 경로를 지정합니다.
image_file_path = r"C:\Users\Public\Pictures\Sample Pictures\Koala.jpg" # 예시 이미지 경로
msg_client.send_image(target_recipient_id, image_file_path)
print(f"이미지 전송 완료: '{image_file_path}'")

첫 번째 인수는 메시지를 받을 위챗 ID(wxid)이며, 두 번째 인수는 메시지 내용입니다. 위챗 ID를 얻는 방법은 수신 메시지 후킹 기능과 함께 추후 자세히 설명될 예정입니다.

메시지 전송 시 무한 루프를 사용하면 Python 프로세스가 블로킹될 수 있으므로 주의해야 합니다. 정기적인 메시지 전송이 필요한 경우 Python의 threading.Timer 또는 다중 스레딩(threading.Thread) 기능을 활용하는 것을 권장합니다.

정기 메시지 전송

scheduled_messages.py 파일을 생성하여 다음 코드를 작성합니다:

import time
from threading import Timer
from wechat_pyrobot.api import MessageSender

message_handler = MessageSender() # 메시지 전송 핸들러 인스턴스
active_timer_instance = None # 전역 타이머 인스턴스

def send_scheduled_message(sequence_number: int):
    global active_timer_instance
    
    current_time_str = time.strftime("%Y-%m-%d %H:%M:%S")
    message_to_send = f"정기 알림 ({current_time_str}): {sequence_number}번째 메시지"
    
    message_handler.send_text("filehelper", message_to_send)
    print(f"정기 메시지 전송됨: {message_to_send}")
    
    # 다음 메시지는 12초 후에 다시 실행되도록 예약합니다.
    active_timer_instance = Timer(12, send_scheduled_message, (sequence_number + 1,))
    active_timer_instance.start()
 
print("초기 3초 대기 후 정기 메시지 전송을 시작합니다.")
# 초기 타이머 실행을 3초 후로 설정합니다.
active_timer_instance = Timer(3, send_scheduled_message, (1,))
active_timer_instance.start()

# 타이머 취소 예시: active_timer_instance.cancel()

특정 시각에 메시지를 보내야 하는 경우, 1초마다 타이머를 실행하여 현재 시간이 요구 사항을 충족하는지 확인하고, 조건이 맞으면 메시지를 보내는 방식으로 구현할 수 있습니다.

실행 중인 타이머를 외부에서 취소해야 하는 경우, sys.modules를 활용할 수 있습니다. 예를 들어, cancel_timer.py라는 파일을 생성하여 다음과 같이 작성할 수 있습니다:

import sys

# 'scheduled_messages'는 이전에 Timer를 생성한 스크립트 파일의 이름입니다.
# 해당 스크립트가 로드되어 있어야 합니다.
target_module_name = "scheduled_messages" 

if target_module_name in sys.modules:
    timer_script_module = sys.modules[target_module_name]
    
    # 'active_timer_instance'는 'scheduled_messages.py' 내에서 정의된 전역 타이머 변수입니다.
    if hasattr(timer_script_module, "active_timer_instance") and timer_script_module.active_timer_instance is not None:
        timer_script_module.active_timer_instance.cancel()
        print(f"모듈 '{target_module_name}'의 예약된 메시지 타이머가 성공적으로 취소되었습니다.")
    else:
        print(f"모듈 '{target_module_name}'에서 타이머 인스턴스를 찾을 수 없거나 이미 취소되었습니다.")
else:
    print(f"모듈 '{target_module_name}'이(가) 로드되지 않았습니다. 타이머 스크립트가 실행 중인지 확인하세요.")

로그 후킹

log_monitor.py 파일을 생성하여 다음 코드를 저장합니다:

from wechat_pyrobot.api import LogMonitor

log_monitor_controller = LogMonitor() # 로그 모니터 인스턴스
log_monitor_controller.enable_hooking() # 로그 후킹 활성화
print("위챗 내부 로그 후킹 기능이 활성화되었습니다. 콘솔에서 실시간 로그를 확인할 수 있습니다.")

로그 후킹은 위챗 내부에서 콜백 함수가 호출되므로 Python 프로세스를 블로킹하지 않습니다. 따라서 별도의 다중 스레딩을 구현할 필요가 없습니다.

모듈 간 상호작용 (고급 활용)

앞서 설명했듯이, 동적으로 로드된 모든 Python 모듈은 sys.modules 딕셔너리에 저장됩니다. 이 "핫 로딩" 메커니즘은 코드를 모듈 형태로 로드하기 때문에, 새로 작성한 파일에서 이전에 로드된 모듈의 변수나 함수에 접근할 수 있습니다.

예를 들어, 로그 후킹을 중지해야 하는 경우, disable_log_hook.py 파일을 생성하여 다음과 같이 작성할 수 있습니다:

from wechat_pyrobot.api import LogMonitor

# LogMonitor 클래스는 싱글톤(Singleton) 패턴으로 구현되어 있으므로,
# 새로운 인스턴스를 생성해도 기존에 활성화된 인스턴스를 반환합니다.
log_control = LogMonitor() 
log_control.disable_hooking() # 로그 후킹 비활성화
print("위챗 로그 후킹 기능이 비활성화되었습니다.")

이는 타이머나 다중 스레딩을 제어할 때 특히 유용합니다. LogMonitor와 같은 일부 클래스는 싱글톤 패턴으로 설계되어 있어, 별도로 sys.modules를 통해 인스턴스를 가져올 필요 없이 새로운 인스턴스를 생성하는 것만으로도 기존 인스턴스를 제어할 수 있습니다.

태그: WeChat Automation Python Bot pip Installation Process Hooking Windows API

7월 29일 10:11에 게시됨