본문 바로가기

프로그램 개발일지

[Python] 파이썬 카카오톡 제어하기 - 1

 

Instagram

 

www.instagram.com

 

 

 

 

파이썬에서 카카오톡의 대화내용을 확인하는 코드다.

관련 매크로를 제작하려다가 스탑 되어서 .......

블로그에 코드 남기려는 용도로 남겨본다.

 

 

 

 

 

import time, win32con, win32api, win32gui, ctypes, psutil, win32process, re, os

 

필요한 모듈.

 

 

 

 

 

 

class kakao():
    def chatlist(self, name):
        hwndkakao = win32gui.FindWindow(None, "카카오톡")
        hwndkakao_edit1 = win32gui.FindWindowEx( hwndkakao, None, "EVA_ChildWindow", None)
        hwndkakao_edit2_1 = win32gui.FindWindowEx( hwndkakao_edit1, None, "EVA_Window", None)
        hwndkakao_edit2_2 = win32gui.FindWindowEx( hwndkakao_edit1, hwndkakao_edit2_1, "EVA_Window", None)
        hwndkakao_edit3 = win32gui.FindWindowEx( hwndkakao_edit2_2, None, "Edit", None)

        win32api.SendMessage(hwndkakao_edit3, win32con.WM_SETTEXT, 0, name)
        time.sleep(1)
        win32api.PostMessage(hwndkakao_edit3, win32con.WM_KEYDOWN, win32con.VK_RETURN, 0)
        time.sleep(0.01)
        win32api.PostMessage(hwndkakao_edit3, win32con.WM_KEYUP, win32con.VK_RETURN, 0)
        return name
    def getchatting(self, chatroom_name, chat_url):
        file_url = rf'{chat_url.replace('/','\\')}\{self.reply(chatroom_name)}.txt'
        if os.path.exists(file_url):
            os.remove(file_url)
        while True:
            hwndMain = win32gui.FindWindow(None, chatroom_name)
            hwndListControl = win32gui.FindWindowEx(hwndMain, None, "EVA_VH_ListControl_Dblclk", None)
            if hwndListControl == 0:
                self.chatlist(chatroom_name)
                time.sleep(2)
            else:
                break
        ########################################################################################
        while True:
            self.PostKeyEx(hwndListControl, ord('S'), [win32con.VK_CONTROL], False)
            hwnd = win32gui.FindWindow(None, '다른 이름으로 저장')
            if hwnd:
                while True:
                    child_windows = self.enum_child_windows(hwnd)
                    if child_windows:
                        for child_hwnd in child_windows:
                            print(child_hwnd, 2)
                            win32gui.SendMessage(child_hwnd, win32con.WM_SETTEXT, 0, file_url)
                            time.sleep(1)
                            self.PostKeyEx(child_hwnd, ord('S'), [win32con.VK_MENU], False)
                            time.sleep(1)
                        if os.path.exists(file_url):
                            break
                break
            else:
                time.sleep(0.5)

        hwndkakao = win32gui.FindWindow(None, chatroom_name)
        win32gui.PostMessage(hwndkakao, win32con.WM_CLOSE, 0, 0)
        return
    def enum_child_windows(self,parent_hwnd):
        edit_windows = []

        def enum_callback(hwnd, lParam):
            class_name = win32gui.GetClassName(hwnd)
            if class_name == "Edit":
                edit_windows.append(hwnd)

        win32gui.EnumChildWindows(parent_hwnd, enum_callback, None)
        return edit_windows
    def PostKeyEx(self, hwnd, key, shift, specialkey):
        PBYTE256 = ctypes.c_ubyte * 256
        _user32 = ctypes.WinDLL("user32")
        GetKeyboardState = _user32.GetKeyboardState
        SetKeyboardState = _user32.SetKeyboardState
        PostMessage = win32api.PostMessage
        SendMessage = win32gui.SendMessage
        IsWindow = win32gui.IsWindow
        GetCurrentThreadId = win32api.GetCurrentThreadId
        GetWindowThreadProcessId = _user32.GetWindowThreadProcessId
        AttachThreadInput = _user32.AttachThreadInput

        MapVirtualKeyA = _user32.MapVirtualKeyA
        MakeLong = win32api.MAKELONG
        w = win32con
        if IsWindow(hwnd):

            ThreadId = GetWindowThreadProcessId(hwnd, None)

            lparam = MakeLong(0, MapVirtualKeyA(key, 0))
            msg_down = w.WM_KEYDOWN
            msg_up = w.WM_KEYUP

            if specialkey:
                lparam = lparam | 0x1000000

            if len(shift) > 0:
                pKeyBuffers = PBYTE256()
                pKeyBuffers_old = PBYTE256()

                SendMessage(hwnd, w.WM_ACTIVATE, w.WA_ACTIVE, 0)
                AttachThreadInput(GetCurrentThreadId(), ThreadId, True)
                GetKeyboardState(ctypes.byref(pKeyBuffers_old))

                for modkey in shift:
                    if modkey == w.VK_MENU:
                        lparam = lparam | 0x20000000
                        msg_down = w.WM_SYSKEYDOWN
                        msg_up = w.WM_SYSKEYUP
                    pKeyBuffers[modkey] |= 128

                SetKeyboardState(ctypes.byref(pKeyBuffers))
                time.sleep(0.01)
                PostMessage(hwnd, msg_down, key, lparam)
                time.sleep(0.01)
                PostMessage(hwnd, msg_up, key, lparam | 0xC0000000)
                time.sleep(0.01)
                SetKeyboardState(ctypes.byref(pKeyBuffers_old))
                time.sleep(0.01)
                AttachThreadInput(GetCurrentThreadId(), ThreadId, False)
            else:
                SendMessage(hwnd, msg_down, key, lparam)
                SendMessage(hwnd, msg_up, key, lparam | 0xC0000000)
    def get_chattitle(self):
        kakaotalk_process = None
        for proc in psutil.process_iter(attrs=['pid', 'name']):
            if proc.info['name'] == 'KakaoTalk.exe':
                kakaotalk_process = proc
                break
        if not kakaotalk_process:
            print("KAKAOTALK 프로세스를 찾을 수 없습니다.")
            return

        chattings = []
        def enum_callback(hwnd, lParam):
            _, found_pid = win32process.GetWindowThreadProcessId(hwnd)
            if found_pid == kakaotalk_process.pid:
                window_text = win32gui.GetWindowText(hwnd)
                if re.search('[가-힣]', window_text) and window_text != '카카오톡':
                    chattings.append(window_text)
        win32gui.EnumWindows(enum_callback, None)
        return chattings
    def reply(self,input_string):
        cleaned_string = re.sub(r'[^가-힣a-zA-Z0-9]', '', input_string)
        return cleaned_string