├── .gitignore ├── CommandMessage.py ├── ComputerMonitor.py ├── Controller.py ├── Controller.pyw ├── CyberSocket.py ├── KeyboardListener.py ├── KeyboardManager.py ├── TcpServer.py ├── Unlocker.py ├── cybercontroller.bat ├── out.py ├── screen_shot.py ├── service.py └── test.py /.gitignore: -------------------------------------------------------------------------------- 1 | /__pycache__ -------------------------------------------------------------------------------- /CommandMessage.py: -------------------------------------------------------------------------------- 1 | class CommandMessage: 2 | def __init__(self,command,message): 3 | self.command = command 4 | self.message = message 5 | 6 | -------------------------------------------------------------------------------- /ComputerMonitor.py: -------------------------------------------------------------------------------- 1 | import threading 2 | from ctypes import * 3 | import time 4 | import subprocess 5 | 6 | class ComputerMonitor: 7 | def __init__(self, callback): 8 | self.callback = callback 9 | self.started = False 10 | 11 | def monitor(self): 12 | self.monit_windows_lock() 13 | 14 | def monit_windows_lock(self): 15 | while True: 16 | process_name='LogonUI.exe' 17 | callall='TASKLIST' 18 | outputall=subprocess.check_output(callall) 19 | outputstringall=str(outputall) 20 | if process_name in outputstringall: 21 | print("Locked.") 22 | if self.callback: 23 | self.callback() 24 | else: 25 | pass 26 | 27 | time.sleep(1) 28 | 29 | def start(self): 30 | monitor_threading = threading.Thread(target=self.monitor, args=()) 31 | monitor_threading.start() 32 | self.started = True 33 | -------------------------------------------------------------------------------- /Controller.py: -------------------------------------------------------------------------------- 1 | import threading 2 | from TcpServer import TcpServer 3 | from KeyboardListener import KeyboardListener 4 | from service import * 5 | from ComputerMonitor import ComputerMonitor 6 | from CommandMessage import CommandMessage; 7 | import json 8 | import pyautogui 9 | from KeyboardManager import * 10 | import time 11 | 12 | 13 | def on_message_received(data): 14 | command_message = json.loads(data) 15 | script = command_message["script"] 16 | params = command_message["params"] 17 | exec(script) 18 | 19 | def on_screen_locked(): 20 | print("screen locked") 21 | data = json.dumps({"command":2,"message":""}) 22 | print(data) 23 | tcpServer.send_text(data) 24 | 25 | computerMonitor = ComputerMonitor(on_screen_locked) 26 | 27 | def on_tcp_connected(): 28 | if not computerMonitor.started: 29 | computerMonitor.start() 30 | 31 | 32 | tcpServer = TcpServer() 33 | tcpServer.set_receive_listener(on_message_received) 34 | tcpServer.connected_listener = on_tcp_connected 35 | tcpServer.start() 36 | 37 | keyboardListener = KeyboardListener(tcpServer) 38 | 39 | def onTrans(): 40 | print("need trans") 41 | content = getClipContent() 42 | text = json.dumps({"command":1,"message":content}) 43 | 44 | tcpServer.send_text(text) 45 | 46 | keyboardListener.listen_keyboard(onTrans) -------------------------------------------------------------------------------- /Controller.pyw: -------------------------------------------------------------------------------- 1 | aAimport threading 2 | from TcpServer import TcpServer 3 | from KeyboardListener import KeyboardListener 4 | from service import * 5 | from ComputerMonitor import ComputerMonitor 6 | from CommandMessage import CommandMessage; 7 | import json 8 | import pyautogui 9 | from KeyboardManager import * 10 | import time 11 | 12 | 13 | def on_message_received(data): 14 | command_message = json.loads(data) 15 | script = command_message["script"] 16 | params = command_message["params"] 17 | exec(script) 18 | 19 | def on_screen_locked(): 20 | print("screen locked") 21 | data = json.dumps({"command":2,"message":""}) 22 | print(data) 23 | tcpServer.send_text(data) 24 | 25 | computerMonitor = ComputerMonitor(on_screen_locked) 26 | 27 | def on_tcp_connected(): 28 | if not computerMonitor.started: 29 | computerMonitor.start() 30 | 31 | 32 | tcpServer = TcpServer() 33 | tcpServer.set_receive_listener(on_message_received) 34 | tcpServer.connected_listener = on_tcp_connected 35 | tcpServer.start() 36 | 37 | keyboardListener = KeyboardListener(tcpServer) 38 | 39 | def onTrans(): 40 | print("need trans") 41 | content = getClipContent() 42 | text = json.dumps({"command":1,"message":content}) 43 | 44 | tcpServer.send_text(text) 45 | 46 | keyboardListener.listen_keyboard(onTrans) -------------------------------------------------------------------------------- /CyberSocket.py: -------------------------------------------------------------------------------- 1 | import socketserver 2 | import socket 3 | 4 | class CyberSocketServer(socketserver.BaseRequestHandler): 5 | def handle(self): 6 | print("connection from",self.client_address) 7 | while True: 8 | data = self.request.recv(2048) 9 | if not data: 10 | break 11 | print('recv:', data) 12 | 13 | class CyberSocket: 14 | def __init__(self): 15 | pass 16 | 17 | def start(self): 18 | hostname= socket.gethostname()#获取本地主机名 19 | sysinfo = socket.gethostbyname_ex(hostname) 20 | hostip=sysinfo[2][2] 21 | self.server = socketserver.ThreadingTCPServer((hostip, 2233), CyberSocketServer) 22 | print("server created") 23 | self.server.serve_forever() 24 | def send_data(self,data): 25 | request, client_address = self.server.get_request() 26 | data = data+"\n" 27 | print(data) 28 | request.sendall(data.encode()) 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /KeyboardListener.py: -------------------------------------------------------------------------------- 1 | import keyboard 2 | import time 3 | from screen_shot import ScreenCapture 4 | import io 5 | 6 | class KeyboardListener: 7 | def __init__(self, tcpServer): 8 | self.tcpServer = tcpServer 9 | self.t = 0 10 | self.c = 0 11 | self.key_state_map={} 12 | self.screen_capture = None 13 | 14 | def listen_keyboard(self,callback): 15 | self.callback = callback 16 | keyboard.hook(self.onKeyEvent) 17 | keyboard.wait() 18 | 19 | def onImgCapture(self,pic): 20 | imgByteArr = io.BytesIO() 21 | pic.save(imgByteArr, format='JPEG') 22 | bytes_data = imgByteArr.getvalue() 23 | self.tcpServer.send_img(bytes_data) 24 | 25 | def isCtrlHolding(self): 26 | return ('ctrl' in self.key_state_map and self.key_state_map['ctrl']=='down')\ 27 | or ('left ctrl' in self.key_state_map and self.key_state_map['left ctrl']=='down')\ 28 | or ('right ctrl' in self.key_state_map and self.key_state_map['right ctrl']=='down') 29 | 30 | def isAltHolding(self): 31 | return ('alt' in self.key_state_map and self.key_state_map['alt']=='down')\ 32 | or ('left alt' in self.key_state_map and self.key_state_map['left alt']=='down')\ 33 | or ('right alt' in self.key_state_map and self.key_state_map['right alt']=='down') 34 | 35 | def isKeyHolding(self,key): 36 | return (key in self.key_state_map and self.key_state_map[key]=='down') 37 | 38 | 39 | def onKeyEvent(self,key): 40 | #update key_state_map 41 | self.key_state_map[key.name.lower()]=key.event_type 42 | 43 | #is screenshoot? 44 | 45 | if self.isKeyHolding("caps lock")\ 46 | and key.event_type=="down"\ 47 | and key.name.lower()=="a": 48 | self.screen_capture = ScreenCapture() 49 | self.screen_capture.are_capture(self.onImgCapture) 50 | 51 | print(self.key_state_map) 52 | #is triple c? 53 | if key.event_type=="down" \ 54 | and key.name.lower()=="c" \ 55 | and self.isCtrlHolding(): 56 | 57 | if self.t == 0: 58 | self.t=time.time() 59 | self.c += 1 60 | print("wait for nex c",self.c) 61 | return 62 | 63 | if (time.time()-self.t<0.5): 64 | self.t=time.time() 65 | self.c += 1 66 | print("wait for nex c:",self.c) 67 | 68 | else: 69 | self.c = 0 70 | self.t=0 71 | print("wait for nex c",self.c) 72 | 73 | if self.c>=2: 74 | self.c=0 75 | print("need trans") 76 | if self.callback: 77 | self.callback() 78 | 79 | -------------------------------------------------------------------------------- /KeyboardManager.py: -------------------------------------------------------------------------------- 1 | import win32api 2 | import win32con 3 | import time 4 | import pyautogui 5 | import pyperclip 6 | key_map={ 7 | 'backspace':0x08, 8 | 'tab':0x09, 9 | 'clear':0x0C, 10 | 'enter':0x0D, 11 | 'shift':0x10, 12 | 'ctrl':0x11, 13 | 'alt':0x12, 14 | 'pause':0x13, 15 | 'caps_lock':0x14, 16 | 'esc':0x1B, 17 | 'spacebar':0x20, 18 | 'page_up':0x21, 19 | 'page_down':0x22, 20 | 'end':0x23, 21 | 'home':0x24, 22 | 'left_arrow':0x25, 23 | 'up_arrow':0x26, 24 | 'right_arrow':0x27, 25 | 'down_arrow':0x28, 26 | 'select':0x29, 27 | 'print':0x2A, 28 | 'execute':0x2B, 29 | 'print_screen':0x2C, 30 | 'ins':0x2D, 31 | 'del':0x2E, 32 | 'help':0x2F, 33 | '0':0x30, 34 | '1':0x31, 35 | '2':0x32, 36 | '3':0x33, 37 | '4':0x34, 38 | '5':0x35, 39 | '6':0x36, 40 | '7':0x37, 41 | '8':0x38, 42 | '9':0x39, 43 | 'a':0x41, 44 | 'b':0x42, 45 | 'c':0x43, 46 | 'd':0x44, 47 | 'e':0x45, 48 | 'f':0x46, 49 | 'g':0x47, 50 | 'h':0x48, 51 | 'i':0x49, 52 | 'j':0x4A, 53 | 'k':0x4B, 54 | 'l':0x4C, 55 | 'm':0x4D, 56 | 'n':0x4E, 57 | 'o':0x4F, 58 | 'p':0x50, 59 | 'q':0x51, 60 | 'r':0x52, 61 | 's':0x53, 62 | 't':0x54, 63 | 'u':0x55, 64 | 'v':0x56, 65 | 'w':0x57, 66 | 'x':0x58, 67 | 'y':0x59, 68 | 'z':0x5A, 69 | 'win':0x5B, 70 | 'numpad_0':0x60, 71 | 'numpad_1':0x61, 72 | 'numpad_2':0x62, 73 | 'numpad_3':0x63, 74 | 'numpad_4':0x64, 75 | 'numpad_5':0x65, 76 | 'numpad_6':0x66, 77 | 'numpad_7':0x67, 78 | 'numpad_8':0x68, 79 | 'numpad_9':0x69, 80 | 'multiply_key':0x6A, 81 | 'add_key':0x6B, 82 | 'separator_key':0x6C, 83 | 'subtract_key':0x6D, 84 | 'decimal_key':0x6E, 85 | 'divide_key':0x6F, 86 | 'F1':0x70, 87 | 'F2':0x71, 88 | 'F3':0x72, 89 | 'F4':0x73, 90 | 'F5':0x74, 91 | 'F6':0x75, 92 | 'F7':0x76, 93 | 'F8':0x77, 94 | 'F9':0x78, 95 | 'F10':0x79, 96 | 'F11':0x7A, 97 | 'F12':0x7B, 98 | 'F13':0x7C, 99 | 'F14':0x7D, 100 | 'F15':0x7E, 101 | 'F16':0x7F, 102 | 'F17':0x80, 103 | 'F18':0x81, 104 | 'F19':0x82, 105 | 'F20':0x83, 106 | 'F21':0x84, 107 | 'F22':0x85, 108 | 'F23':0x86, 109 | 'F24':0x87, 110 | 'num_lock':0x90, 111 | 'scroll_lock':0x91, 112 | 'left_shift':0xA0, 113 | 'right_shift ':0xA1, 114 | 'left_control':0xA2, 115 | 'right_control':0xA3, 116 | 'left_menu':0xA4, 117 | 'right_menu':0xA5, 118 | 'browser_back':0xA6, 119 | 'browser_forward':0xA7, 120 | 'browser_refresh':0xA8, 121 | 'browser_stop':0xA9, 122 | 'browser_search':0xAA, 123 | 'browser_favorites':0xAB, 124 | 'browser_start_and_home':0xAC, 125 | 'volume_mute':0xAD, 126 | 'volume_Down':0xAE, 127 | 'volume_up':0xAF, 128 | 'next_track':0xB0, 129 | 'previous_track':0xB1, 130 | 'stop_media':0xB2, 131 | 'play/pause_media':0xB3, 132 | 'start_mail':0xB4, 133 | 'select_media':0xB5, 134 | 'start_application_1':0xB6, 135 | 'start_application_2':0xB7, 136 | 'attn_key':0xF6, 137 | 'crsel_key':0xF7, 138 | 'exsel_key':0xF8, 139 | 'play_key':0xFA, 140 | 'zoom_key':0xFB, 141 | 'clear_key':0xFE, 142 | '+':0xBB, 143 | ',':0xBC, 144 | '-':0xBD, 145 | '.':0xBE, 146 | '/':0xBF, 147 | '`':0xC0, 148 | ';':0xBA, 149 | '[':0xDB, 150 | '\\':0xDC, 151 | ']':0xDD, 152 | "'":0xDE, 153 | '`':0xC0 154 | } 155 | 156 | def key_down(key): 157 | vk_code = key_map[key] 158 | win32api.keybd_event(vk_code, win32api.MapVirtualKey(vk_code, 0), 0, 0) 159 | 160 | 161 | def key_up(key): 162 | vk_code = key_map[key] 163 | win32api.keybd_event(vk_code, win32api.MapVirtualKey(vk_code, 0), win32con.KEYEVENTF_KEYUP, 0) 164 | 165 | 166 | def key_press(key, sleep_time=0.02): 167 | key_down(key) 168 | time.sleep(sleep_time) 169 | key_up(key) 170 | 171 | # time.sleep(3) 172 | # key_down("alt") 173 | # key_down("h") 174 | # key_press("f") 175 | # key_press("c") 176 | # key_up("alt") 177 | # key_up("h") 178 | # key_press("down_arrow",sleep_time=0) 179 | # key_press("down_arrow",sleep_time=0) 180 | # key_press("down_arrow",sleep_time=0) 181 | # key_press("down_arrow",sleep_time=0) 182 | # key_press("down_arrow",sleep_time=0) 183 | # key_press("down_arrow",sleep_time=0) 184 | # key_press("right_arrow",sleep_time=0) 185 | 186 | # key_press("enter") 187 | 188 | # # 输入 a 189 | # #key_press("a") 190 | 191 | # key_press('enter') 192 | # key_press('a') 193 | 194 | -------------------------------------------------------------------------------- /TcpServer.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import threading 3 | import json 4 | 5 | class TcpServer: 6 | def __init__(self): 7 | self.port=2233#设置端口 8 | self.HEAD_LEN=8 9 | self.tcpServerSocket=socket.socket()#创建socket对象 10 | hostname= socket.gethostname()#获取本地主机名 11 | sysinfo = socket.gethostbyname_ex(hostname) 12 | hostip=sysinfo[2][2] 13 | self.tcpServerSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)#让端口可以复用 14 | self.tcpServerSocket.bind((hostip,self.port))#将地址与套接字绑定,且套接字要求是从未被绑定过的 15 | self.tcpServerSocket.listen(5)#代办事件中排队等待connect的最大数目 16 | 17 | def set_receive_listener(self,receive_listener): 18 | self.receive_listener = receive_listener 19 | def server(self): 20 | while True: 21 | print("等待连接") 22 | self.clientSocket, addr = self.tcpServerSocket.accept() 23 | print ('连接地址:', addr) 24 | if self.connected_listener: 25 | self.connected_listener() 26 | while True: 27 | try: 28 | head_data=self.clientSocket.recv(self.HEAD_LEN) 29 | if not len(head_data)==8: 30 | print("bad package!head_data len:",head_data) 31 | self.restart() 32 | return 33 | body_len = self.get_length_from_head_data(head_data) 34 | body_data = self.clientSocket.recv(body_len) 35 | if not body_len==len(body_data): 36 | print("bad package!body_len:",body_len) 37 | self.restart() 38 | return 39 | data_type = self.get_type_from_head_data(head_data) 40 | 41 | if data_type == 1:#test/json data 42 | text = body_data.decode() 43 | print(text) 44 | if not text: 45 | break 46 | if self.receive_listener: 47 | self.receive_listener(text) 48 | elif data_type == 2:#image data 49 | pass 50 | 51 | except ConnectionResetError: 52 | print("ConnectionResetError!") 53 | self.restart() 54 | return 55 | 56 | 57 | self.clientSocket.close() # 关闭连接 58 | self.tcpServerSocket.close() 59 | 60 | def get_length_from_head_data(self,head_data): 61 | if(not len(head_data)==8): 62 | return 63 | ch1 = head_data[4] & 0x00FF; 64 | ch2 = head_data[5] & 0x00FF; 65 | ch3 = head_data[6] & 0x00FF; 66 | ch4 = head_data[7] & 0x00FF; 67 | return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0)); 68 | 69 | def get_type_from_head_data(self,head_data): 70 | if(not len(head_data)==8): 71 | return 72 | ch1 = head_data[0] & 0x00FF; 73 | ch2 = head_data[1] & 0x00FF; 74 | ch3 = head_data[2] & 0x00FF; 75 | ch4 = head_data[3] & 0x00FF; 76 | return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0)); 77 | 78 | 79 | def start(self): 80 | self.server_threading = threading.Thread(target=self.server, args=()) 81 | self.server_threading.start() 82 | 83 | def restart(self): 84 | self.start() 85 | 86 | def send_data(self, data): 87 | try: 88 | self.clientSocket.send(data) 89 | except ConnectionResetError: 90 | print("ConnectionResetError!") 91 | self.restart() 92 | def send_img(self, bytes_data): 93 | data = self.wrapper_data(2,bytes_data) 94 | self.send_data(data) 95 | 96 | def send_text(self, text): 97 | data = self.wrapper_data(1,text.encode()) 98 | self.send_data(data) 99 | 100 | def wrapper_data(self,data_type,body_data): 101 | 102 | print("data_type:",data_type) 103 | print("body_data len:",len(body_data)) 104 | 105 | 106 | type_bytes=data_type.to_bytes(4,'big') 107 | print("type_bytes:",type_bytes) 108 | body_len = len(body_data) 109 | 110 | body_len_bytes = body_len.to_bytes(4,'big') 111 | print("body_len_bytes:",body_len_bytes) 112 | 113 | head_data = type_bytes + body_len_bytes 114 | print("head_data:",head_data) 115 | 116 | data = head_data+body_data 117 | return data -------------------------------------------------------------------------------- /Unlocker.py: -------------------------------------------------------------------------------- 1 | from ctypes import * 2 | import time 3 | # while True: 4 | # u = windll.LoadLibrary('user32.dll') 5 | # result = u.GetForegroundWindow() 6 | # print(result) # 0则表示锁屏 7 | # time.sleep(2) 8 | 9 | 10 | import pyautogui 11 | pyautogui.FAILSAFE=False 12 | time.sleep(5) 13 | pyautogui.press('enter') # enter to login. 14 | 15 | #pyautogui.click(1025,513, 2) # click to show the password box 16 | time.sleep(1) 17 | pyautogui.typewrite("Asdfghjkl;'",2) # Type the password 18 | pyautogui.press('enter') # enter to login. 19 | time.sleep(2) 20 | 21 | -------------------------------------------------------------------------------- /cybercontroller.bat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KikiLetGo/CyberControllerServer/8dcf14964d6f15a83822712bd54528c5314a6f14/cybercontroller.bat -------------------------------------------------------------------------------- /out.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KikiLetGo/CyberControllerServer/8dcf14964d6f15a83822712bd54528c5314a6f14/out.py -------------------------------------------------------------------------------- /screen_shot.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | import tkinter 3 | import tkinter.filedialog 4 | import os 5 | from PIL import ImageGrab 6 | from time import sleep 7 | from tkinter import StringVar, IntVar 8 | 9 | class ScreenCapture: 10 | 11 | def __init__(self): 12 | pass 13 | def start(self): 14 | self.root = tkinter.Tk() 15 | self.root.geometry('0x0+0+0') 16 | self.root.resizable(False, False) 17 | self.X = tkinter.IntVar(value=0) 18 | self.Y = tkinter.IntVar(value=0) 19 | 20 | self.selectPosition=None 21 | screenWidth = self.root.winfo_screenwidth() 22 | screenHeight = self.root.winfo_screenheight() 23 | self.top = tkinter.Toplevel(self.root, width=screenWidth, height=screenHeight) 24 | self.top.overrideredirect(True) 25 | self.canvas = tkinter.Canvas(self.top,bg='white', width=screenWidth, height=screenHeight) 26 | self.p_w_picpath = tkinter.PhotoImage(file=self.filename) 27 | self.canvas.create_image(screenWidth//2, screenHeight//2, image=self.p_w_picpath) 28 | def onLeftButtonDown(event): 29 | self.X.set(event.x) 30 | self.Y.set(event.y) 31 | #开始截图 32 | self.sel = True 33 | self.canvas.bind('', onLeftButtonDown) 34 | 35 | def onLeftButtonMove(event): 36 | if not self.sel: 37 | return 38 | global lastDraw 39 | try: 40 | self.canvas.delete(lastDraw) 41 | except Exception as e: 42 | pass 43 | lastDraw = self.canvas.create_rectangle(self.X.get(), self.Y.get(), event.x, event.y, outline='red',width=8) 44 | self.canvas.bind('', onLeftButtonMove) 45 | 46 | def onLeftButtonUp(event): 47 | self.sel = False 48 | try: 49 | self.canvas.delete(lastDraw) 50 | except Exception as e: 51 | pass 52 | #sleep(0.1) 53 | myleft, myright = sorted([self.X.get(), event.x]) 54 | mytop, mybottom = sorted([self.Y.get(), event.y]) 55 | self.selectPosition=(myleft,myright,mytop,mybottom) 56 | pic = ImageGrab.grab((myleft+1, mytop+1, myright, mybottom)) 57 | self.destroy() 58 | if self.callback: 59 | self.callback(pic) 60 | 61 | self.canvas.bind('', onLeftButtonUp) 62 | self.canvas.pack(fill=tkinter.BOTH, expand=tkinter.YES) 63 | 64 | def destroy(self): 65 | self.top.destroy() 66 | self.root.destroy() 67 | 68 | def are_capture(self,callback): 69 | self.callback = callback 70 | self.filename = 'temp.png' 71 | im = ImageGrab.grab() 72 | im.save(self.filename) 73 | im.close() 74 | self.start() 75 | self.root.state('icon') 76 | os.remove(self.filename) 77 | self.root.mainloop() 78 | 79 | 80 | # def are_capture(callback): 81 | # filename = 'temp.png' 82 | # im = ImageGrab.grab() 83 | # im.save(filename) 84 | # im.close() 85 | # capture = MyCapture(filename) 86 | # capture.callback = callback 87 | # capture.root.state('icon') 88 | # sleep(0.2) 89 | # os.remove(filename) 90 | # capture.root.mainloop() 91 | -------------------------------------------------------------------------------- /service.py: -------------------------------------------------------------------------------- 1 | import pyperclip 2 | 3 | def getClipContent(): 4 | content = pyperclip.paste() 5 | return content -------------------------------------------------------------------------------- /test.py: -------------------------------------------------------------------------------- 1 | import pyautogui 2 | import time 3 | from KeyboardManager import key_press 4 | time.sleep(2) 5 | with open('./TcpServer.py', encoding='UTF-8') as f: 6 | while True: 7 | line = f.readline() 8 | if not line: 9 | break 10 | print(line) 11 | #pyautogui.typewrite(line) 12 | #key_press("home") 13 | for c in line: 14 | out = open('out.py','a') 15 | out.write(c) 16 | out.close() 17 | time.sleep(0.001) 18 | 19 | # for line in content: 20 | # print(line) 21 | 22 | # print('\n') 23 | # pyautogui.typewrite('\n') 24 | --------------------------------------------------------------------------------