def get_bottom_post_list(api, board): api._goto_board(board, end=True) last_screen = api.connect_core.get_screen_queue()[-1] # print(last_screen) bottom_screen = [ line for line in last_screen.split('\n') if '★' in line[:8] ] bottom_length = len(bottom_screen) # bottom_screen = '\n'.join(bottom_screen) # print(bottom_screen) if bottom_length == 0: log.log(api.config, log.level.INFO, i18n.CatchBottomPostSuccess) return list() cmd_list = list() cmd_list.append(command.QueryPost) cmd = ''.join(cmd_list) target_list = [ connect_core.TargetUnit([ i18n.CatchPost, i18n.Success, ], screens.Target.QueryPost, break_detect=True, refresh=False, log_level=log.level.DEBUG), connect_core.TargetUnit([ i18n.PostDeleted, i18n.Success, ], screens.Target.InBoard, break_detect=True, log_level=log.level.DEBUG), connect_core.TargetUnit(i18n.NoSuchBoard, screens.Target.MainMenu_Exiting, exceptions_=exceptions.NoSuchBoard( api.config, board)), ] result = list() for _ in range(0, bottom_length): api.connect_core.send(cmd, target_list) last_screen = api.connect_core.get_screen_queue()[-1] lock_post, post_author, post_title, post_aid, post_web, post_money, list_date, push_number, post_index = \ _api_util.parse_query_post( api, last_screen) current_post = api.get_post(board, post_aid=post_aid, query=True) # print(current_post.aid) # print(current_post.title) # print('==========================') result.append(current_post) cmd_list = list() cmd_list.append(command.Enter) cmd_list.append(command.Up) cmd_list.append(command.QueryPost) cmd = ''.join(cmd_list) log.log(api.config, log.level.INFO, i18n.CatchBottomPostSuccess) return list(reversed(result))
def get_post(api, board: str, post_aid: str = None, post_index: int = 0, search_type: int = 0, search_condition: str = None, search_list: list = None, query: bool = False) -> data_type.PostInfo: api._goto_board(board) cmd_list = list() if post_aid is not None: cmd_list.append('#' + post_aid) elif post_index != 0: if search_condition is not None: if search_type == data_type.post_search_type.KEYWORD: cmd_list.append('/') elif search_type == data_type.post_search_type.AUTHOR: cmd_list.append('a') elif search_type == data_type.post_search_type.PUSH: cmd_list.append('Z') elif search_type == data_type.post_search_type.MARK: cmd_list.append('G') elif search_type == data_type.post_search_type.MONEY: cmd_list.append('A') cmd_list.append(search_condition) cmd_list.append(command.Enter) if search_list is not None: for search_type_, search_condition_ in search_list: if search_type_ == data_type.post_search_type.KEYWORD: cmd_list.append('/') elif search_type_ == data_type.post_search_type.AUTHOR: cmd_list.append('a') elif search_type_ == data_type.post_search_type.PUSH: cmd_list.append('Z') elif search_type_ == data_type.post_search_type.MARK: cmd_list.append('G') elif search_type_ == data_type.post_search_type.MONEY: cmd_list.append('A') cmd_list.append(search_condition_) cmd_list.append(command.Enter) cmd_list.append(str(max(1, post_index - 100))) cmd_list.append(command.Enter) cmd_list.append(str(post_index)) cmd_list.append(command.Enter) cmd_list.append(command.QueryPost) cmd = ''.join(cmd_list) target_list = [ connect_core.TargetUnit([ i18n.CatchPost, i18n.Success, ], screens.Target.QueryPost, break_detect=True, refresh=False, log_level=log.level.DEBUG), connect_core.TargetUnit([ i18n.PostDeleted, i18n.Success, ], screens.Target.InBoard, break_detect=True, log_level=log.level.DEBUG), connect_core.TargetUnit(i18n.NoSuchBoard, screens.Target.MainMenu_Exiting, exceptions_=exceptions.NoSuchBoard( api.config, board)), ] index = api.connect_core.send(cmd, target_list) ori_screen = api.connect_core.get_screen_queue()[-1] post_author = None post_title = None if index < 0 or index == 1: # 文章被刪除 log.log(api.config, log.level.DEBUG, i18n.PostDeleted) log.show_value(api.config, log.level.DEBUG, 'OriScreen', ori_screen) cursor_line = [ line for line in ori_screen.split('\n') if line.startswith(api.cursor) ] if len(cursor_line) != 1: raise exceptions.UnknownError(ori_screen) cursor_line = cursor_line[0] log.show_value(api.config, log.level.DEBUG, 'CursorLine', cursor_line) pattern = re.compile('[\d]+\/[\d]+') pattern_result = pattern.search(cursor_line) if pattern_result is None: list_date = None else: list_date = pattern_result.group(0) list_date = list_date[-5:] pattern = re.compile('\[[\w]+\]') pattern_result = pattern.search(cursor_line) if pattern_result is not None: post_del_status = data_type.post_delete_status.AUTHOR else: pattern = re.compile('<[\w]+>') pattern_result = pattern.search(cursor_line) post_del_status = data_type.post_delete_status.MODERATOR # > 79843 9/11 - □ (本文已被吃掉)< # > 76060 8/28 - □ (本文已被刪除) [weida7332] # print(f'O=>{CursorLine}<') if pattern_result is not None: post_author = pattern_result.group(0)[1:-1] else: post_author = None post_del_status = data_type.post_delete_status.UNKNOWN log.show_value(api.config, log.level.DEBUG, 'ListDate', list_date) log.show_value(api.config, log.level.DEBUG, 'PostAuthor', post_author) log.show_value(api.config, log.level.DEBUG, 'post_del_status', post_del_status) return data_type.PostInfo(board=board, author=post_author, list_date=list_date, delete_status=post_del_status, format_check=True) elif index == 0: lock_post, post_author, post_title, post_aid, post_web, post_money, list_date, push_number, post_index = \ _api_util.parse_query_post( api, ori_screen) if lock_post: post = data_type.PostInfo(board=board, aid=post_aid, index=post_index, author=post_author, title=post_title, web_url=post_web, money=post_money, list_date=list_date, format_check=True, push_number=push_number, lock=True) return post if query: post = data_type.PostInfo(board=board, aid=post_aid, index=post_index, author=post_author, title=post_title, web_url=post_web, money=post_money, list_date=list_date, format_check=True, push_number=push_number) return post origin_post, has_control_code = _api_util.get_content(api) if origin_post is None: post = data_type.PostInfo(board=board, aid=post_aid, index=post_index, author=post_author, title=post_title, web_url=post_web, money=post_money, list_date=list_date, control_code=has_control_code, format_check=False, push_number=push_number, unconfirmed=api.Unconfirmed) return post # print('=' * 20) # print(origin_post) # print('=' * 20) content_start = '───────────────────────────────────────' content_end = list() content_end.append('--\n※ 發信站: 批踢踢實業坊') content_end.append('--\n※ 發信站: 批踢踢兔(ptt2.cc)') content_end.append('--\n※ 發信站: 新批踢踢(ptt2.twbbs.org.tw)') post_author_pattern_new = re.compile('作者 (.+) 看板') post_author_pattern_old = re.compile('作者 (.+)') board_pattern = re.compile('看板 (.+)') post_date = None post_content = list() ip = None location = None push_list = list() # 格式確認,亂改的我也沒辦法Q_Q origin_post_lines = origin_post.split('\n') author_line = origin_post_lines[0] if board.lower() == 'allpost': board_line = author_line[author_line.find(')') + 1:] pattern_result = board_pattern.search(board_line) if pattern_result is not None: board_temp = post_author = pattern_result.group(0) board_temp = board_temp[2:].strip() if len(board_temp) > 0: board = board_temp log.show_value(api.config, log.level.DEBUG, i18n.Board, board) pattern_result = post_author_pattern_new.search(author_line) if pattern_result is not None: post_author = pattern_result.group(0) post_author = post_author[:post_author.rfind(')') + 1] else: pattern_result = post_author_pattern_old.search(author_line) if pattern_result is None: log.show_value(api.config, log.level.DEBUG, i18n.SubstandardPost, i18n.Author) post = data_type.PostInfo( board=board, aid=post_aid, index=post_index, author=post_author, date=post_date, title=post_title, web_url=post_web, money=post_money, content=post_content, ip=ip, push_list=push_list, list_date=list_date, control_code=has_control_code, format_check=False, location=location, push_number=push_number, origin_post=origin_post, unconfirmed=api.Unconfirmed, ) return post post_author = pattern_result.group(0) post_author = post_author[:post_author.rfind(')') + 1] post_author = post_author[4:].strip() log.show_value(api.config, log.level.DEBUG, i18n.Author, post_author) post_title_pattern = re.compile('標題 (.+)') title_line = origin_post_lines[1] pattern_result = post_title_pattern.search(title_line) if pattern_result is None: log.show_value(api.config, log.level.DEBUG, i18n.SubstandardPost, i18n.Title) post = data_type.PostInfo(board=board, aid=post_aid, index=post_index, author=post_author, date=post_date, title=post_title, web_url=post_web, money=post_money, content=post_content, ip=ip, push_list=push_list, list_date=list_date, control_code=has_control_code, format_check=False, location=location, push_number=push_number, origin_post=origin_post, unconfirmed=api.Unconfirmed) return post post_title = pattern_result.group(0) post_title = post_title[4:].strip() log.show_value(api.config, log.level.DEBUG, i18n.Title, post_title) post_date_pattern = re.compile('時間 .{24}') date_line = origin_post_lines[2] pattern_result = post_date_pattern.search(date_line) if pattern_result is None: log.show_value(api.config, log.level.DEBUG, i18n.SubstandardPost, i18n.Date) post = data_type.PostInfo( board=board, aid=post_aid, index=post_index, author=post_author, date=post_date, title=post_title, web_url=post_web, money=post_money, content=post_content, ip=ip, push_list=push_list, list_date=list_date, control_code=has_control_code, format_check=False, location=location, push_number=push_number, origin_post=origin_post, unconfirmed=api.Unconfirmed, ) return post post_date = pattern_result.group(0) post_date = post_date[4:].strip() log.show_value(api.config, log.level.DEBUG, i18n.Date, post_date) content_fail = True if content_start not in origin_post: # print('Type 1') content_fail = True else: post_content = origin_post post_content = post_content[post_content.find(content_start) + len(content_start) + 1:] # print('Type 2') # print(f'PostContent [{PostContent}]') for EC in content_end: # + 3 = 把 --\n 拿掉 # print(f'EC [{EC}]') if EC in post_content: content_fail = False post_content = post_content[:post_content.rfind(EC) + 3] origin_post_lines = origin_post[origin_post.find(EC):] # post_content = post_content.strip() origin_post_lines = origin_post_lines.split('\n') break if content_fail: log.show_value(api.config, log.level.DEBUG, i18n.SubstandardPost, i18n.Content) post = data_type.PostInfo( board=board, aid=post_aid, index=post_index, author=post_author, date=post_date, title=post_title, web_url=post_web, money=post_money, content=post_content, ip=ip, push_list=push_list, list_date=list_date, control_code=has_control_code, format_check=False, location=location, push_number=push_number, origin_post=origin_post, unconfirmed=api.Unconfirmed, ) return post log.show_value(api.config, log.level.DEBUG, i18n.Content, post_content) info_lines = [ line for line in origin_post_lines if line.startswith('※') or line.startswith('◆') ] pattern = re.compile('[\d]+\.[\d]+\.[\d]+\.[\d]+') pattern_p2 = re.compile('[\d]+-[\d]+-[\d]+-[\d]+') for line in reversed(info_lines): log.show_value(api.config, log.level.DEBUG, 'IP Line', line) # type 1 # ※ 編輯: CodingMan (111.243.146.98 臺灣) # ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 111.243.146.98 (臺灣) # type 2 # ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 116.241.32.178 # ※ 編輯: kill77845 (114.136.55.237), 12/08/2018 16:47:59 # type 3 # ※ 發信站: 批踢踢實業坊(ptt.cc) # ◆ From: 211.20.78.69 # ※ 編輯: JCC 來自: 211.20.78.69 (06/20 10:22) # ※ 編輯: JCC (118.163.28.150), 12/03/2015 14:25:35 pattern_result = pattern.search(line) if pattern_result is not None: ip = pattern_result.group(0) location_temp = line[line.find(ip) + len(ip):].strip() location_temp = location_temp.replace('(', '') location_temp = location_temp[:location_temp.rfind(')')] location_temp = location_temp.strip() # print(f'=>[{LocationTemp}]') if ' ' not in location_temp and len(location_temp) > 0: location = location_temp log.show_value(api.config, log.level.DEBUG, 'Location', location) break pattern_result = pattern_p2.search(line) if pattern_result is not None: ip = pattern_result.group(0) ip = ip.replace('-', '.') # print(f'IP -> [{IP}]') break if api.config.host == data_type.host_type.PTT1: if ip is None: log.show_value(api.config, log.level.DEBUG, i18n.SubstandardPost, 'IP') post = data_type.PostInfo( board=board, aid=post_aid, index=post_index, author=post_author, date=post_date, title=post_title, web_url=post_web, money=post_money, content=post_content, ip=ip, push_list=push_list, list_date=list_date, control_code=has_control_code, format_check=False, location=location, push_number=push_number, origin_post=origin_post, unconfirmed=api.Unconfirmed, ) return post log.show_value(api.config, log.level.DEBUG, 'IP', ip) push_author_pattern = re.compile('[推|噓|→] [\w| ]+:') push_date_pattern = re.compile('[\d]+/[\d]+ [\d]+:[\d]+') push_ip_pattern = re.compile('[\d]+\.[\d]+\.[\d]+\.[\d]+') push_list = list() for line in origin_post_lines: if line.startswith('推'): push_type = data_type.push_type.PUSH elif line.startswith('噓 '): push_type = data_type.push_type.BOO elif line.startswith('→ '): push_type = data_type.push_type.ARROW else: continue result = push_author_pattern.search(line) if result is None: # 不符合推文格式 continue push_author = result.group(0)[2:-1].strip() log.show_value(api.config, log.level.DEBUG, [ i18n.Push, i18n.ID, ], push_author) result = push_date_pattern.search(line) if result is None: continue push_date = result.group(0) log.show_value(api.config, log.level.DEBUG, [ i18n.Push, i18n.Date, ], push_date) push_ip = None result = push_ip_pattern.search(line) if result is not None: push_ip = result.group(0) log.show_value(api.config, log.level.DEBUG, [ i18n.Push, 'IP', ], push_ip) push_content = line[line.find(push_author) + len(push_author):] # PushContent = PushContent.replace(PushDate, '') if api.config.host == data_type.host_type.PTT1: push_content = push_content[:push_content.rfind(push_date)] else: # → CodingMan:What is Ptt? 推 10/04 13:25 push_content = push_content[:push_content.rfind(push_date) - 2] if push_ip is not None: push_content = push_content.replace(push_ip, '') push_content = push_content[push_content.find(':') + 1:].strip() log.show_value(api.config, log.level.DEBUG, [ i18n.Push, i18n.Content, ], push_content) current_push = data_type.PushInfo(push_type, push_author, push_content, push_ip, push_date) push_list.append(current_push) post = data_type.PostInfo( board=board, aid=post_aid, index=post_index, author=post_author, date=post_date, title=post_title, web_url=post_web, money=post_money, content=post_content, ip=ip, push_list=push_list, list_date=list_date, control_code=has_control_code, format_check=True, location=location, push_number=push_number, origin_post=origin_post, unconfirmed=api.Unconfirmed, ) return post
def get_post(api, board: str, post_aid: str = None, post_index: int = 0, search_type: int = 0, search_condition: str = None, search_list: list = None, query: bool = False) -> data_type.PostInfo: cmd_list = [] cmd_list.append(command.GoMainMenu) cmd_list.append('qs') cmd_list.append(board) cmd_list.append(command.Enter) cmd_list.append(command.Ctrl_C * 2) cmd_list.append(command.Space) if post_aid is not None: cmd_list.append('#' + post_aid) elif post_index != 0: if search_condition is not None: if search_type == data_type.post_search_type.KEYWORD: cmd_list.append('/') elif search_type == data_type.post_search_type.AUTHOR: cmd_list.append('a') elif search_type == data_type.post_search_type.PUSH: cmd_list.append('Z') elif search_type == data_type.post_search_type.MARK: cmd_list.append('G') elif search_type == data_type.post_search_type.MONEY: cmd_list.append('A') cmd_list.append(search_condition) cmd_list.append(command.Enter) if search_list is not None: for search_type_, search_condition_ in search_list: if search_type_ == data_type.post_search_type.KEYWORD: cmd_list.append('/') elif search_type_ == data_type.post_search_type.AUTHOR: cmd_list.append('a') elif search_type_ == data_type.post_search_type.PUSH: cmd_list.append('Z') elif search_type_ == data_type.post_search_type.MARK: cmd_list.append('G') elif search_type_ == data_type.post_search_type.MONEY: cmd_list.append('A') cmd_list.append(search_condition_) cmd_list.append(command.Enter) cmd_list.append(str(post_index)) cmd_list.append(command.Enter) cmd_list.append(command.QueryPost) cmd = ''.join(cmd_list) target_list = [ connect_core.TargetUnit([ i18n.CatchPost, i18n.Success, ], screens.Target.QueryPost, break_detect=True, refresh=False, log_level=log.level.DEBUG), connect_core.TargetUnit([ i18n.PostDeleted, i18n.Success, ], screens.Target.InBoard, break_detect=True, log_level=log.level.DEBUG), connect_core.TargetUnit(i18n.NoSuchBoard, screens.Target.MainMenu_Exiting, exceptions_=exceptions.NoSuchBoard( api.config, board)), ] index = api.connect_core.send(cmd, target_list) ori_screen = api.connect_core.get_screen_queue()[-1] post_author = None post_title = None if index < 0 or index == 1: # 文章被刪除 log.log(api.config, log.level.DEBUG, i18n.PostDeleted) log.show_value(api.config, log.level.DEBUG, 'OriScreen', ori_screen) cursor_line = [ line for line in ori_screen.split('\n') if line.startswith(api.cursor) ] if len(cursor_line) != 1: raise exceptions.UnknownError(ori_screen) cursor_line = cursor_line[0] log.show_value(api.config, log.level.DEBUG, 'CursorLine', cursor_line) pattern = re.compile('[\d]+\/[\d]+') pattern_result = pattern.search(cursor_line) if pattern_result is None: list_date = None else: list_date = pattern_result.group(0) list_date = list_date[-5:] pattern = re.compile('\[[\w]+\]') pattern_result = pattern.search(cursor_line) if pattern_result is not None: post_del_status = data_type.post_delete_status.AUTHOR else: pattern = re.compile('<[\w]+>') pattern_result = pattern.search(cursor_line) post_del_status = data_type.post_delete_status.MODERATOR # > 79843 9/11 - □ (本文已被吃掉)< # > 76060 8/28 - □ (本文已被刪除) [weida7332] # print(f'O=>{CursorLine}<') if pattern_result is not None: post_author = pattern_result.group(0)[1:-1] else: post_author = None post_del_status = data_type.post_delete_status.UNKNOWN log.show_value(api.config, log.level.DEBUG, 'ListDate', list_date) log.show_value(api.config, log.level.DEBUG, 'PostAuthor', post_author) log.show_value(api.config, log.level.DEBUG, 'post_del_status', post_del_status) return data_type.PostInfo(board=board, author=post_author, list_date=list_date, delete_status=post_del_status, format_check=True) elif index == 0: lock_post = False try: cursor_line = [ line for line in ori_screen.split('\n') if line.strip().startswith(api.cursor) ][0] except Exception as e: print(api.cursor) print(ori_screen) raise e post_author = cursor_line if '□' in post_author: post_author = post_author[:post_author.find('□')].strip() elif 'R:' in post_author: post_author = post_author[:post_author.find('R:')].strip() elif ' 轉 ' in post_author: post_author = post_author[:post_author.find('轉')].strip() elif ' 鎖 ' in post_author: post_author = post_author[:post_author.find('鎖')].strip() lock_post = True post_author = post_author[post_author.rfind(' '):].strip() post_title = cursor_line if ' □ ' in post_title: post_title = post_title[post_title.find('□') + 1:].strip() elif ' R:' in post_title: post_title = post_title[post_title.find('R:'):].strip() elif ' 轉 ' in post_title: # print(f'[{PostTitle}]=========>') post_title = post_title[post_title.find('轉') + 1:].strip() post_title = f'Fw: {post_title}' # print(f'=========>[{PostTitle}]') elif ' 鎖 ' in post_title: post_title = post_title[post_title.find('鎖') + 1:].strip() ori_screen_temp = ori_screen[ori_screen.find('┌──────────'):] ori_screen_temp = ori_screen_temp[:ori_screen_temp. find('└─────────────')] aid_line = [ line for line in ori_screen.split('\n') if line.startswith('│ 文章代碼(AID)') ] if len(aid_line) == 1: aid_line = aid_line[0] pattern = re.compile('#[\w|-]+') pattern_result = pattern.search(aid_line) post_aid = pattern_result.group(0)[1:] pattern = re.compile('文章網址: https:[\S]+html') pattern_result = pattern.search(ori_screen_temp) if pattern_result is None: post_web = None else: post_web = pattern_result.group(0)[6:] pattern = re.compile('這一篇文章值 [\d]+ Ptt幣') pattern_result = pattern.search(ori_screen_temp) if pattern_result is None: # 特殊文章無價格 post_money = -1 else: post_money = pattern_result.group(0)[7:] post_money = post_money[:post_money.find(' ')] post_money = int(post_money) pattern = re.compile('[\d]+\/[\d]+') pattern_result = pattern.search(cursor_line) if pattern_result is None: list_date = None else: list_date = pattern_result.group(0) list_date = list_date[-5:] # print(list_date) # > 7485 9 8/09 CodingMan □ [閒聊] PTT Library 更新 # > 79189 M 1 9/17 LittleCalf □ [公告] 禁言退文公告 # >781508 +爆 9/17 jodojeda □ [新聞] 國人吃魚少 學者:應把吃魚當成輕鬆愉快 # >781406 +X1 9/17 kingofage111 R: [申請] ReDmango 請辭Gossiping板主職務 if post_index == 0: pattern = re.compile('[\d]+') pattern_result = pattern.search(cursor_line) if pattern_result is not None: post_index = int(pattern_result.group(0)) push_number = cursor_line # print(f'2>{push_number}<') push_number = push_number[7:10] # print(push_number) push_number = push_number.split(' ') # print(PushNumber) push_number = list(filter(None, push_number)) # print(PushNumber) if len(push_number) == 0: push_number = None else: push_number = push_number[-1] # print(PushNumber) if push_number.startswith('+') or push_number.startswith('~'): push_number = push_number[1:] # print(PushNumber) if push_number.lower().startswith('m'): push_number = push_number[1:] # print(PushNumber) if push_number.lower().startswith('!'): push_number = push_number[1:] if push_number.lower().startswith('s'): push_number = push_number[1:] if push_number.lower().startswith('='): push_number = push_number[1:] if len(push_number) == 0: push_number = None # print(PushNumber) log.show_value(api.config, log.level.DEBUG, 'PostAuthor', post_author) log.show_value(api.config, log.level.DEBUG, 'PostTitle', post_title) log.show_value(api.config, log.level.DEBUG, 'PostAID', post_aid) log.show_value(api.config, log.level.DEBUG, 'PostWeb', post_web) log.show_value(api.config, log.level.DEBUG, 'PostMoney', post_money) log.show_value(api.config, log.level.DEBUG, 'ListDate', list_date) log.show_value(api.config, log.level.DEBUG, 'PushNumber', push_number) if lock_post: post = data_type.PostInfo( board=board, aid=post_aid, index=post_index, author=post_author, title=post_title, web_url=post_web, money=post_money, list_date=list_date, format_check=True, push_number=push_number, lock=True, ) return post if query: post = data_type.PostInfo( board=board, aid=post_aid, index=post_index, author=post_author, title=post_title, web_url=post_web, money=post_money, list_date=list_date, format_check=True, push_number=push_number, ) return post origin_post, has_control_code = _api_util.get_content(api) if origin_post is None: post = data_type.PostInfo( board=board, aid=post_aid, index=post_index, author=post_author, title=post_title, web_url=post_web, money=post_money, list_date=list_date, control_code=has_control_code, format_check=False, push_number=push_number, unconfirmed=api.Unconfirmed, ) return post # print('=' * 20) # print(origin_post) # print('=' * 20) content_start = '───────────────────────────────────────' content_end = [] content_end.append('--\n※ 發信站: 批踢踢實業坊') content_end.append('--\n※ 發信站: 批踢踢兔(ptt2.cc)') content_end.append('--\n※ 發信站: 新批踢踢(ptt2.twbbs.org.tw)') post_author_pattern_new = re.compile('作者 (.+) 看板') post_author_pattern_old = re.compile('作者 (.+)') board_pattern = re.compile('看板 (.+)') post_date = None post_content = [] ip = None location = None push_list = [] # 格式確認,亂改的我也沒辦法Q_Q origin_post_lines = origin_post.split('\n') author_line = origin_post_lines[0] if board.lower() == 'allpost': board_line = author_line[author_line.find(')') + 1:] pattern_result = board_pattern.search(board_line) if pattern_result is not None: board_temp = post_author = pattern_result.group(0) board_temp = board_temp[2:].strip() if len(board_temp) > 0: board = board_temp log.show_value(api.config, log.level.DEBUG, i18n.Board, board) pattern_result = post_author_pattern_new.search(author_line) if pattern_result is not None: post_author = pattern_result.group(0) post_author = post_author[:post_author.rfind(')') + 1] else: pattern_result = post_author_pattern_old.search(author_line) if pattern_result is None: log.show_value(api.config, log.level.DEBUG, i18n.SubstandardPost, i18n.Author) post = data_type.PostInfo( board=board, aid=post_aid, index=post_index, author=post_author, date=post_date, title=post_title, web_url=post_web, money=post_money, content=post_content, ip=ip, push_list=push_list, list_date=list_date, control_code=has_control_code, format_check=False, location=location, push_number=push_number, origin_post=origin_post, unconfirmed=api.Unconfirmed, ) return post post_author = pattern_result.group(0) post_author = post_author[:post_author.rfind(')') + 1] post_author = post_author[4:].strip() log.show_value(api.config, log.level.DEBUG, i18n.Author, post_author) post_title_pattern = re.compile('標題 (.+)') title_line = origin_post_lines[1] pattern_result = post_title_pattern.search(title_line) if pattern_result is None: log.show_value(api.config, log.level.DEBUG, i18n.SubstandardPost, i18n.Title) post = data_type.PostInfo( board=board, aid=post_aid, index=post_index, author=post_author, date=post_date, title=post_title, web_url=post_web, money=post_money, content=post_content, ip=ip, push_list=push_list, list_date=list_date, control_code=has_control_code, format_check=False, location=location, push_number=push_number, origin_post=origin_post, unconfirmed=api.Unconfirmed, ) return post post_title = pattern_result.group(0) post_title = post_title[4:].strip() log.show_value(api.config, log.level.DEBUG, i18n.Title, post_title) post_date_pattern = re.compile('時間 (.+)') date_line = origin_post_lines[2] pattern_result = post_date_pattern.search(date_line) if pattern_result is None: log.show_value(api.config, log.level.DEBUG, i18n.SubstandardPost, i18n.Date) post = data_type.PostInfo( board=board, aid=post_aid, index=post_index, author=post_author, date=post_date, title=post_title, web_url=post_web, money=post_money, content=post_content, ip=ip, push_list=push_list, list_date=list_date, control_code=has_control_code, format_check=False, location=location, push_number=push_number, origin_post=origin_post, unconfirmed=api.Unconfirmed, ) return post post_date = pattern_result.group(0) post_date = post_date[4:].strip() log.show_value(api.config, log.level.DEBUG, i18n.Date, post_date) content_fail = True if content_start not in origin_post: # print('Type 1') content_fail = True else: post_content = origin_post post_content = post_content[post_content.find(content_start) + len(content_start) + 1:] # print('Type 2') # print(f'PostContent [{PostContent}]') for EC in content_end: # + 3 = 把 --\n 拿掉 # print(f'EC [{EC}]') if EC in post_content: content_fail = False post_content = post_content[:post_content.rfind(EC) + 3] origin_post_lines = origin_post[origin_post.find(EC):] # post_content = post_content.strip() origin_post_lines = origin_post_lines.split('\n') break if content_fail: log.show_value(api.config, log.level.DEBUG, i18n.SubstandardPost, i18n.Content) post = data_type.PostInfo( board=board, aid=post_aid, index=post_index, author=post_author, date=post_date, title=post_title, web_url=post_web, money=post_money, content=post_content, ip=ip, push_list=push_list, list_date=list_date, control_code=has_control_code, format_check=False, location=location, push_number=push_number, origin_post=origin_post, unconfirmed=api.Unconfirmed, ) return post log.show_value(api.config, log.level.DEBUG, i18n.Content, post_content) info_lines = [ line for line in origin_post_lines if line.startswith('※') or line.startswith('◆') ] pattern = re.compile('[\d]+\.[\d]+\.[\d]+\.[\d]+') pattern_p2 = re.compile('[\d]+-[\d]+-[\d]+-[\d]+') for line in reversed(info_lines): log.show_value(api.config, log.level.DEBUG, 'IP Line', line) # type 1 # ※ 編輯: CodingMan (111.243.146.98 臺灣) # ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 111.243.146.98 (臺灣) # type 2 # ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 116.241.32.178 # ※ 編輯: kill77845 (114.136.55.237), 12/08/2018 16:47:59 # type 3 # ※ 發信站: 批踢踢實業坊(ptt.cc) # ◆ From: 211.20.78.69 # ※ 編輯: JCC 來自: 211.20.78.69 (06/20 10:22) # ※ 編輯: JCC (118.163.28.150), 12/03/2015 14:25:35 pattern_result = pattern.search(line) if pattern_result is not None: ip = pattern_result.group(0) location_temp = line[line.find(ip) + len(ip):].strip() location_temp = location_temp.replace('(', '') location_temp = location_temp[:location_temp.rfind(')')] location_temp = location_temp.strip() # print(f'=>[{LocationTemp}]') if ' ' not in location_temp and len(location_temp) > 0: location = location_temp log.show_value(api.config, log.level.DEBUG, 'Location', location) break pattern_result = pattern_p2.search(line) if pattern_result is not None: ip = pattern_result.group(0) ip = ip.replace('-', '.') # print(f'IP -> [{IP}]') break if api.config.host == data_type.host_type.PTT1: if ip is None: log.show_value(api.config, log.level.DEBUG, i18n.SubstandardPost, 'IP') post = data_type.PostInfo( board=board, aid=post_aid, index=post_index, author=post_author, date=post_date, title=post_title, web_url=post_web, money=post_money, content=post_content, ip=ip, push_list=push_list, list_date=list_date, control_code=has_control_code, format_check=False, location=location, push_number=push_number, origin_post=origin_post, unconfirmed=api.Unconfirmed, ) return post log.show_value(api.config, log.level.DEBUG, 'IP', ip) push_author_pattern = re.compile('[推|噓|→] [\w| ]+:') push_date_pattern = re.compile('[\d]+/[\d]+ [\d]+:[\d]+') push_ip_pattern = re.compile('[\d]+\.[\d]+\.[\d]+\.[\d]+') push_list = [] for line in origin_post_lines: if line.startswith('推'): push_type = data_type.push_type.PUSH elif line.startswith('噓 '): push_type = data_type.push_type.BOO elif line.startswith('→ '): push_type = data_type.push_type.ARROW else: continue result = push_author_pattern.search(line) if result is None: # 不符合推文格式 continue push_author = result.group(0)[2:-1].strip() log.show_value(api.config, log.level.DEBUG, [ i18n.Push, i18n.ID, ], push_author) result = push_date_pattern.search(line) if result is None: continue push_date = result.group(0) log.show_value(api.config, log.level.DEBUG, [ i18n.Push, i18n.Date, ], push_date) push_ip = None result = push_ip_pattern.search(line) if result is not None: push_ip = result.group(0) log.show_value(api.config, log.level.DEBUG, [ i18n.Push, 'IP', ], push_ip) push_content = line[line.find(push_author) + len(push_author):] # PushContent = PushContent.replace(PushDate, '') if api.config.host == data_type.host_type.PTT1: push_content = push_content[:push_content.rfind(push_date)] else: # → CodingMan:What is Ptt? 推 10/04 13:25 push_content = push_content[:push_content.rfind(push_date) - 2] if push_ip is not None: push_content = push_content.replace(push_ip, '') push_content = push_content[push_content.find(':') + 1:].strip() log.show_value(api.config, log.level.DEBUG, [ i18n.Push, i18n.Content, ], push_content) current_push = data_type.PushInfo(push_type, push_author, push_content, push_ip, push_date) push_list.append(current_push) post = data_type.PostInfo( board=board, aid=post_aid, index=post_index, author=post_author, date=post_date, title=post_title, web_url=post_web, money=post_money, content=post_content, ip=ip, push_list=push_list, list_date=list_date, control_code=has_control_code, format_check=True, location=location, push_number=push_number, origin_post=origin_post, unconfirmed=api.Unconfirmed, ) return post
def login(api, ptt_id, password, kick_other_login): if api._login_status: api.logout() api.config.kick_other_login = kick_other_login def kick_other_loginDisplayMsg(): if api.config.kick_other_login: return i18n.kick_other_login return i18n.Notkick_other_login def kick_other_loginResponse(Screen): if api.config.kick_other_login: return 'y' + command.Enter return 'n' + command.Enter api._mailbox_full = False def mailbox_full(): log.log(api.config, log.level.INFO, i18n.MailBoxFull) api._mailbox_full = True if len(password) > 8: password = password[:8] ptt_id = ptt_id.strip() password = password.strip() api._ID = ptt_id api._Password = password api.config.kick_other_login = kick_other_login api.connect_core.connect() log.show_value(api.config, log.level.INFO, [i18n.login, i18n.ID], ptt_id) target_list = [ connect_core.TargetUnit( # i18n.HasNewMailGotoMainMenu, i18n.MailBox, screens.Target.InMailBox, # 加個進去 A 選單再出來的動作,讓畫面更新最底下一行 response=command.GoMainMenu + 'A' + command.Right + command.Left, break_detect=True), connect_core.TargetUnit(i18n.loginSuccess, screens.Target.MainMenu, break_detect=True), connect_core.TargetUnit( i18n.GoMainMenu, '【看板列表】', response=command.GoMainMenu, ), connect_core.TargetUnit(i18n.ErrorIDPW, '密碼不對', break_detect=True, exceptions_=exceptions.WrongIDorPassword()), connect_core.TargetUnit(i18n.LoginTooOften, '登入太頻繁', break_detect=True, exceptions_=exceptions.LoginTooOften()), connect_core.TargetUnit( i18n.SystemBusyTryLater, '系統過載', break_detect=True, ), connect_core.TargetUnit( i18n.DelWrongPWRecord, '您要刪除以上錯誤嘗試的記錄嗎', response='y' + command.Enter, ), connect_core.TargetUnit( i18n.PostNotFinish, '請選擇暫存檔 (0-9)[0]', response=command.Enter, ), connect_core.TargetUnit( i18n.PostNotFinish, '有一篇文章尚未完成', response='Q' + command.Enter, ), connect_core.TargetUnit( i18n.SigningUnPleaseWait, '登入中,請稍候', ), connect_core.TargetUnit( kick_other_loginDisplayMsg, '您想刪除其他重複登入的連線嗎', response=kick_other_loginResponse, ), connect_core.TargetUnit(i18n.AnyKeyContinue, '任意鍵', response=command.Enter), connect_core.TargetUnit( i18n.SigningUpdate, '正在更新與同步線上使用者及好友名單', ), connect_core.TargetUnit( i18n.GoMainMenu, '【分類看板】', response=command.GoMainMenu, ), ] cmd_list = [] cmd_list.append(ptt_id) cmd_list.append(command.Enter) cmd_list.append(password) cmd_list.append(command.Enter) cmd = ''.join(cmd_list) index = api.connect_core.send( cmd, target_list, screen_timeout=api.config.screen_long_timeout, refresh=False, secret=True) ori_screen = api.connect_core.get_screen_queue()[-1] if index == 0: current_capacity, max_capacity = _api_util.get_mailbox_capacity(api) log.log(api.config, log.level.INFO, i18n.HasNewMailGotoMainMenu) if current_capacity > max_capacity: api._mailbox_full = True log.log(api.config, log.level.INFO, i18n.MailBoxFull) if api._mailbox_full: log.log(api.config, log.level.INFO, i18n.UseMailboxAPIWillLogoutAfterExecution) target_list = [ connect_core.TargetUnit(i18n.loginSuccess, screens.Target.MainMenu, break_detect=True) ] cmd = command.GoMainMenu + 'A' + command.Right + command.Left index = api.connect_core.send( cmd, target_list, screen_timeout=api.config.screen_long_timeout, secret=True) ori_screen = api.connect_core.get_screen_queue()[-1] if target_list[index].get_display_msg() != i18n.loginSuccess: print(ori_screen) raise exceptions.LoginError() if '> (' in ori_screen: api.cursor = data_type.Cursor.NEW log.log(api.config, log.level.DEBUG, i18n.NewCursor) else: api.cursor = data_type.Cursor.OLD log.log(api.config, log.level.DEBUG, i18n.OldCursor) if api.cursor not in screens.Target.InBoardWithCursor: screens.Target.InBoardWithCursor.append('\n' + api.cursor) if len(screens.Target.MainMenu) == len(screens.Target.CursorToGoodbye): if api.cursor == '>': screens.Target.CursorToGoodbye.append('> (G)oodbye') else: screens.Target.CursorToGoodbye.append('●(G)oodbye') api._unregistered_user = True if '(T)alk' in ori_screen: api._unregistered_user = False if '(P)lay' in ori_screen: api._unregistered_user = False if '(N)amelist' in ori_screen: api._unregistered_user = False if api._unregistered_user: # print(ori_screen) log.log(api.config, log.level.INFO, i18n.UnregisteredUserCantUseAllAPI) api._login_status = True
def throw_waterball(api: object, target_id: str, content: str) -> None: max_length = 50 water_ball_list = list() temp_start_index = 0 temp_end_index = temp_start_index + 1 while temp_end_index <= len(content): temp = '' last_temp = None while len(temp.encode('big5-uao', 'ignore')) < max_length: temp = content[temp_start_index:temp_end_index] if not len(temp.encode('big5-uao', 'ignore')) < max_length: break elif content.endswith(temp) and temp_start_index != 0: break elif temp.endswith('\n'): break elif last_temp == temp: break temp_end_index += 1 last_temp = temp water_ball_list.append(temp.strip()) temp_start_index = temp_end_index temp_end_index = temp_start_index + 1 water_ball_list = filter(None, water_ball_list) for waterball in water_ball_list: if api._LastThrowWaterBallTime != 0: current_time = time.time() while (current_time - api._LastThrowWaterBallTime) < 3.2: time.sleep(0.1) current_time = time.time() log.show_value( api.config, log.level.INFO, i18n.WaterBall, waterball ) target_list = [ connect_core.TargetUnit( i18n.SetCallStatus, '您的呼叫器目前設定為關閉', response='y' + command.Enter, ), # 對方已落跑了 connect_core.TargetUnit( i18n.SetCallStatus, '◆ 糟糕! 對方已落跑了', exceptions_=exceptions.UserOffline(target_id) ), connect_core.TargetUnit( [ i18n.Throw, target_id, i18n.WaterBall ], '丟 ' + target_id + ' 水球:', response=waterball + command.Enter * 2 + command.GoMainMenu, ), connect_core.TargetUnit( [ i18n.Throw, i18n.WaterBall, i18n.Success ], screens.Target.MainMenu, break_detect=True ) ] cmd_list = list() cmd_list.append(command.GoMainMenu) cmd_list.append('T') cmd_list.append(command.Enter) cmd_list.append('U') cmd_list.append(command.Enter) if '【好友列表】' in api.connect_core.get_screen_queue()[-1]: cmd_list.append('f') cmd_list.append('s') cmd_list.append(target_id) cmd_list.append(command.Enter) cmd_list.append('w') cmd = ''.join(cmd_list) api.connect_core.send( cmd, target_list, screen_timeout=api.config.screen_long_timeout ) api._LastThrowWaterBallTime = time.time()
def mail(api, ptt_id: str, title: str, content: str, sign_file) -> None: # log.showValue( # api.config, # log.level.INFO, # [ # i18n.PTT, # i18n.Msg # ], # i18n.MarkPost # ) CmdList = [] CmdList.append(command.GoMainMenu) CmdList.append('M') CmdList.append(command.Enter) CmdList.append('S') CmdList.append(command.Enter) CmdList.append(ptt_id) CmdList.append(command.Enter) Cmd = ''.join(CmdList) TargetList = [ connect_core.TargetUnit([i18n.Start, i18n.SendMail], '主題:', break_detect=True), connect_core.TargetUnit(i18n.NoSuchUser, '【電子郵件】', exceptions_=exceptions.NoSuchUser(ptt_id)), ] api.connect_core.send(Cmd, TargetList, screen_timeout=api.config.screen_long_timeout) CmdList = [] CmdList.append(title) CmdList.append(command.Enter) CmdList.append(content) CmdList.append(command.Ctrl_X) Cmd = ''.join(CmdList) if sign_file == 0: SingFileSelection = i18n.NoSignatureFile else: SingFileSelection = i18n.Select + ' ' + \ str(sign_file) + 'th ' + i18n.SignatureFile TargetList = [ connect_core.TargetUnit(i18n.AnyKeyContinue, '任意鍵', break_detect=True), connect_core.TargetUnit( i18n.SaveFile, '確定要儲存檔案嗎', response='s' + command.Enter, # Refresh=False, ), connect_core.TargetUnit(i18n.SelfSaveDraft, '是否自存底稿', response='y' + command.Enter), connect_core.TargetUnit(SingFileSelection, '選擇簽名檔', response=str(sign_file) + command.Enter), connect_core.TargetUnit(SingFileSelection, 'x=隨機', response=str(sign_file) + command.Enter), ] api.connect_core.send(Cmd, TargetList, screen_timeout=api.config.screen_post_timeout) log.show_value(api.config, log.level.INFO, i18n.SendMail, i18n.Success)
def get_board_list(api) -> list: # log.showValue( # api.config, # log.level.INFO, # [ # i18n.PTT, # i18n.Msg # ], # i18n.MarkPost # ) cmd_list = list() cmd_list.append(command.GoMainMenu) cmd_list.append('F') cmd_list.append(command.Enter) cmd_list.append('y') cmd_list.append('$') cmd = ''.join(cmd_list) target_list = [ connect_core.TargetUnit( i18n.BoardList, screens.Target.InBoardList, break_detect=True ) ] api.connect_core.send( cmd, target_list, screen_timeout=api.config.screen_long_timeout ) ori_screen = api.connect_core.get_screen_queue()[-1] max_no = 0 for line in ori_screen.split('\n'): if '◎' not in line and '●' not in line: continue if line.startswith(api.cursor): line = line[len(api.cursor):] # print(f'->{line}<') if '◎' in line: front_part = line[:line.find('◎')] else: front_part = line[:line.find('●')] front_part_list = [x for x in front_part.split(' ')] front_part_list = list(filter(None, front_part_list)) # print(f'FrontPartList =>{FrontPartList}<=') max_no = int(front_part_list[0].rstrip(')')) log.show_value( api.config, log.level.DEBUG, 'MaxNo', max_no ) if api.config.log_level == log.level.INFO: pb = progressbar.ProgressBar( max_value=max_no, redirect_stdout=True ) cmd_list = list() cmd_list.append(command.GoMainMenu) cmd_list.append('F') cmd_list.append(command.Enter) cmd_list.append('y') cmd_list.append('0') cmd = ''.join(cmd_list) board_list = list() while True: api.connect_core.send( cmd, target_list, screen_timeout=api.config.screen_long_timeout ) ori_screen = api.connect_core.get_screen_queue()[-1] # print(OriScreen) for line in ori_screen.split('\n'): if '◎' not in line and '●' not in line: continue if line.startswith(api.cursor): line = line[len(api.cursor):] # print(f'->{line}<') if '◎' in line: front_part = line[:line.find('◎')] else: front_part = line[:line.find('●')] front_part_list = [x for x in front_part.split(' ')] front_part_list = list(filter(None, front_part_list)) # print(f'FrontPartList =>{FrontPartList}<=') no = int(front_part_list[0].rstrip(')')) # print(f'No =>{no}<=') # print(f'LastNo =>{LastNo}<=') log.show_value( api.config, log.level.DEBUG, 'Board NO', no ) board_name = front_part_list[1] if board_name.startswith('ˇ'): board_name = board_name[1:] log.show_value( api.config, log.level.DEBUG, 'Board Name', board_name ) board_list.append(board_name) if api.config.log_level == log.level.INFO: pb.update(no) if no >= max_no: break cmd = command.Ctrl_F if api.config.log_level == log.level.INFO: pb.finish() return board_list
def post( api: object, board: str, title: str, content: str, post_type: int, sign_file) -> None: cmd_list = [] cmd_list.append(command.GoMainMenu) cmd_list.append('qs') cmd_list.append(board) cmd_list.append(command.Enter) cmd_list.append(command.Ctrl_C * 2) cmd_list.append(command.Space) cmd_list.append(command.Ctrl_P) cmd = ''.join(cmd_list) target_list = [ connect_core.TargetUnit( i18n.HasPostPermission, '發表文章於【', break_detect=True, ), connect_core.TargetUnit( i18n.NoPermission, '使用者不可發言', break_detect=True, ), connect_core.TargetUnit( i18n.NoPermission, '無法發文: 未達看板要求權限', break_detect=True ), ] index = api.connect_core.send(cmd, target_list) if index < 0: screens.show(api.config, api.connect_core.get_screen_queue()) raise exceptions.UnknownError(i18n.UnknownError) if index == 1 or index == 2: raise exceptions.NoPermission(i18n.NoPermission) screens.show(api.config, api.connect_core.get_screen_queue()) cmd_list = [] cmd_list.append(str(post_type)) cmd_list.append(command.Enter) cmd_list.append(str(title)) cmd_list.append(command.Enter) cmd_list.append(command.Ctrl_Y * 40) cmd_list.append(str(content)) cmd_list.append(command.Ctrl_X) cmd = ''.join(cmd_list) target_list = [ connect_core.TargetUnit( i18n.AnyKeyContinue, '任意鍵繼續', break_detect=True, ), connect_core.TargetUnit( i18n.SaveFile, '確定要儲存檔案嗎', response='s' + command.Enter, ), connect_core.TargetUnit( i18n.SelectSignature, 'x=隨機', response=str(sign_file) + command.Enter, ), ] index = api.connect_core.send( cmd, target_list, screen_timeout=api.config.screen_post_timeout )
def markPost(api, mark_type: int, board: str, post_aid: str, post_index: int, search_type: int, search_condition: str) -> None: log.show_value(api.config, log.level.INFO, [i18n.PTT, i18n.Msg], i18n.MarkPost) check_value.check(api.config, int, 'mark_type', mark_type, value_class=data_type.mark_type) check_value.check(api.config, str, 'Board', board) if post_aid is not None: check_value.check(api.config, str, 'PostAID', post_aid) check_value.check(api.config, int, 'PostIndex', post_index) check_value.check(api.config, int, 'SearchType', search_type, value_class=data_type.post_search_type) if search_condition is not None: check_value.check(api.config, str, 'SearchCondition', search_condition) if len(board) == 0: raise ValueError(log.merge([i18n.Board, i18n.ErrorParameter, board])) if post_index != 0 and isinstance(post_aid, str): raise ValueError( log.merge( ['PostIndex', 'PostAID', i18n.ErrorParameter, i18n.BothInput])) if post_index == 0 and post_aid is None: raise ValueError( log.merge(['PostIndex', 'PostAID', i18n.ErrorParameter])) if search_condition is not None and search_type == 0: raise ValueError(log.merge([ 'SearchType', i18n.ErrorParameter, ])) if search_type == data_type.post_search_type.PUSH: try: S = int(search_condition) except ValueError: raise ValueError( log.merge([ 'SearchCondition', i18n.ErrorParameter, ])) if not (-100 <= S <= 110): raise ValueError( log.merge([ 'SearchCondition', i18n.ErrorParameter, ])) if post_aid is not None and search_condition is not None: raise ValueError( log.merge([ 'PostAID', 'SearchCondition', i18n.ErrorParameter, i18n.BothInput, ])) if post_index != 0: NewestIndex = api._get_newest_index(data_type.index_type.BBS, board=board, search_type=search_type, search_condition=search_condition) check_value.check_index(api.config, 'PostIndex', post_index, max_value=NewestIndex) if mark_type == data_type.mark_type.UNCONFIRMED: # 批踢踢兔沒有待證文章功能 QQ if api.config.host == data_type.host_type.PTT2: raise exceptions.HostNotSupport(lib_util.get_current_func_name()) api._check_board(board, check_moderator=True) cmd_list = [] cmd_list.append(command.GoMainMenu) cmd_list.append('qs') cmd_list.append(board) cmd_list.append(command.Enter) cmd = ''.join(cmd_list) target_list = [ connect_core.TargetUnit( i18n.AnyKeyContinue, '任意鍵', response=' ', ), connect_core.TargetUnit([ '動畫播放中', ], '互動式動畫播放中', response=command.Ctrl_C, log_level=log.level.DEBUG), connect_core.TargetUnit([ '進板成功', ], screens.Target.InBoard, break_detect=True, log_level=log.level.DEBUG), ] index = api.connect_core.send(cmd, target_list) cmd_list = [] if post_aid is not None: cmd_list.append('#' + post_aid) elif post_index != 0: if search_condition is not None: if search_type == data_type.post_search_type.KEYWORD: cmd_list.append('/') elif search_type == data_type.post_search_type.AUTHOR: cmd_list.append('a') elif search_type == data_type.post_search_type.PUSH: cmd_list.append('Z') elif search_type == data_type.post_search_type.MARK: cmd_list.append('G') elif search_type == data_type.post_search_type.MONEY: cmd_list.append('A') cmd_list.append(search_condition) cmd_list.append(command.Enter) cmd_list.append(str(post_index)) cmd_list.append(command.Enter) if mark_type == data_type.mark_type.S: cmd_list.append('L') elif mark_type == data_type.mark_type.D: cmd_list.append('t') elif mark_type == data_type.mark_type.DeleteD: cmd_list.append(command.Ctrl_D) elif mark_type == data_type.mark_type.M: cmd_list.append('m') elif mark_type == data_type.mark_type.UNCONFIRMED: cmd_list.append(command.Ctrl_E + 'S') cmd = ''.join(cmd_list) target_list = [ connect_core.TargetUnit([i18n.DelAllMarkPost], '刪除所有標記', response='y' + command.Enter, log_level=log.level.INFO), connect_core.TargetUnit([ i18n.Mark, i18n.Success, ], screens.Target.InBoard, break_detect=True, log_level=log.level.INFO), ] index = api.connect_core.send(cmd, target_list)
def reply_post( api, reply_type: int, board: str, content: str, sign_file, post_aid: str, post_index: int) ->None: # log.showValue( # api.config, # log.level.INFO, # [ # i18n.PTT, # i18n.Msg # ], # i18n.MarkPost # ) cmd_list = [] cmd_list.append(command.GoMainMenu) cmd_list.append('qs') cmd_list.append(board) cmd_list.append(command.Enter) cmd_list.append(command.Ctrl_C * 2) cmd_list.append(command.Space) if post_aid is not None: cmd_list.append('#' + post_aid) elif post_index != 0: cmd_list.append(str(post_index)) cmd_list.append(command.Enter * 2) cmd_list.append('r') if reply_type == data_type.reply_type.BOARD: reply_target_unit = connect_core.TargetUnit( i18n.ReplyBoard, '▲ 回應至', log_level=log.level.INFO, response='F' + command.Enter ) elif reply_type == data_type.reply_type.MAIL: reply_target_unit = connect_core.TargetUnit( i18n.ReplyMail, '▲ 回應至', log_level=log.level.INFO, response='M' + command.Enter ) elif reply_type == data_type.reply_type.BOARD_MAIL: reply_target_unit = connect_core.TargetUnit( i18n.ReplyBoard_Mail, '▲ 回應至', log_level=log.level.INFO, response='B' + command.Enter ) cmd = ''.join(cmd_list) target_list = [ connect_core.TargetUnit( i18n.AnyKeyContinue, '任意鍵繼續', break_detect=True, ), connect_core.TargetUnit( i18n.NoResponse, '◆ 很抱歉, 此文章已結案並標記, 不得回應', log_level=log.level.INFO, exceptions_=exceptions.NoResponse() ), connect_core.TargetUnit( i18n.ForcedWrite, '(E)繼續編輯 (W)強制寫入', log_level=log.level.INFO, response='W' + command.Enter ), connect_core.TargetUnit( i18n.SelectSignature, '請選擇簽名檔', response=str(sign_file) + command.Enter, ), connect_core.TargetUnit( i18n.SaveFile, '確定要儲存檔案嗎', response='s' + command.Enter, ), connect_core.TargetUnit( i18n.EditPost, '編輯文章', log_level=log.level.INFO, response=str(content) + command.Enter + command.Ctrl_X ), connect_core.TargetUnit( i18n.QuoteOriginal, '請問要引用原文嗎', log_level=log.level.DEBUG, response='Y' + command.Enter ), connect_core.TargetUnit( i18n.UseTheOriginalTitle, '採用原標題[Y/n]?', log_level=log.level.DEBUG, response='Y' + command.Enter ), reply_target_unit, connect_core.TargetUnit( i18n.SelfSaveDraft, '已順利寄出,是否自存底稿', log_level=log.level.DEBUG, response='Y' + command.Enter ), ] api.connect_core.send( cmd, target_list, screen_timeout=api.config.screen_long_timeout ) log.log( api.config, log.level.INFO, i18n.RespondSuccess )
def del_post( api, board_info, board, post_aid: str = None, post_index: int = 0) -> None: check_author = True for moderator in board_info.moderators: if api._ID.lower() == moderator.lower(): check_author = False break post_info = api.get_post(board, post_aid=post_aid, post_index=post_index, query=True) if post_info.delete_status != data_type.post_delete_status.NOT_DELETED: if post_aid is not None: raise exceptions.DeletedPost(board, post_aid) else: raise exceptions.DeletedPost(board, post_index) if check_author: if api._ID.lower() != post_info.author.lower(): raise exceptions.NoPermission(i18n.NoPermission) api._goto_board(board) cmd_list = list() if post_aid is not None: cmd_list.append('#' + post_aid) elif post_index != 0: cmd_list.append(str(post_index)) cmd_list.append(command.Enter) cmd_list.append('d') cmd = ''.join(cmd_list) api.confirm = False def confirm_delete_handler(screen): api.confirm = True target_list = [ connect_core.TargetUnit( i18n.AnyKeyContinue, '請按任意鍵繼續', response=' '), connect_core.TargetUnit( i18n.ConfirmDelete, '請確定刪除(Y/N)?[N]', response='y' + command.Enter, max_match=1, handler=confirm_delete_handler), connect_core.TargetUnit( i18n.DeleteSuccess, screens.Target.InBoard, break_detect=True), ] index = api.connect_core.send( cmd, target_list) # last_screen = api.connect_core.get_screen_queue()[-1] # print(api.confirm) # print(last_screen) # print(index) if index == 1: if not api.confirm: raise exceptions.NoPermission(i18n.NoPermission) if index == -1: if post_aid is not None: raise exceptions.NoSuchPost(board, post_aid) else: raise exceptions.NoSuchPost(board, post_index)
def mail(api, ptt_id: str, title: str, content: str, sign_file, backup: bool = True) -> None: cmd_list = list() # 回到主選單 cmd_list.append(command.GoMainMenu) # 私人信件區 cmd_list.append('M') cmd_list.append(command.Enter) # 站內寄信 cmd_list.append('S') cmd_list.append(command.Enter) # 輸入 id cmd_list.append(ptt_id) cmd_list.append(command.Enter) cmd = ''.join(cmd_list) # 定義如何根據情況回覆訊息 target_list = [ connect_core.TargetUnit([i18n.Start, i18n.SendMail], '主題:', break_detect=True), connect_core.TargetUnit(i18n.NoSuchUser, '【電子郵件】', exceptions_=exceptions.NoSuchUser(ptt_id)) ] api.connect_core.send(cmd, target_list, screen_timeout=api.config.screen_long_timeout) cmd_list = list() # 輸入標題 cmd_list.append(title) cmd_list.append(command.Enter) # 輸入內容 cmd_list.append(content) # 儲存檔案 cmd_list.append(command.Ctrl_X) cmd = ''.join(cmd_list) # 根據簽名檔調整顯示訊息 if sign_file == 0: sing_file_selection = i18n.NoSignatureFile else: sing_file_selection = i18n.Select + ' ' + \ str(sign_file) + 'th ' + i18n.SignatureFile # 定義如何根據情況回覆訊息 target_list = [ connect_core.TargetUnit(i18n.AnyKeyContinue, '任意鍵', break_detect=True), connect_core.TargetUnit( i18n.SaveFile, '確定要儲存檔案嗎', response='s' + command.Enter, ), connect_core.TargetUnit( i18n.SelfSaveDraft if backup else i18n.NotSelfSaveDraft, '是否自存底稿', response=('y' if backup else 'n') + command.Enter), connect_core.TargetUnit(sing_file_selection, '選擇簽名檔', response=str(sign_file) + command.Enter), connect_core.TargetUnit(sing_file_selection, 'x=隨機', response=str(sign_file) + command.Enter), ] # 送出訊息 api.connect_core.send(cmd, target_list, screen_timeout=api.config.screen_post_timeout) log.show_value(api.config, log.level.INFO, i18n.SendMail, i18n.Success)
def get_mail(api, index, search_type: int = 0, search_condition: str = None, search_list: list = None) -> data_type.MailInfo: cmd_list = list() # 回到主選單 cmd_list.append(command.GoMainMenu) # 進入信箱 cmd_list.append(command.Ctrl_Z) cmd_list.append('m') # 處理條件整理出指令 _cmd_list, normal_newest_index = _api_util.get_search_condition_cmd( api, data_type.index_type.MAIL, search_type, search_condition, search_list, None) cmd_list.extend(_cmd_list) # 前進至目標信件位置 cmd_list.append(str(index)) cmd_list.append(command.Enter) cmd = ''.join(cmd_list) # 有時候會沒有最底下一列,只好偵測游標是否出現 if api.cursor == data_type.Cursor.NEW: space_length = 6 - len(api.cursor) - len(str(index)) else: space_length = 5 - len(api.cursor) - len(str(index)) fast_target = f"{api.cursor}{' ' * space_length}{index}" # 定義如何根據情況回覆訊息 target_list = [ connect_core.TargetUnit(i18n.MailBox, screens.Target.InMailBox, break_detect=True, log_level=log.level.DEBUG), connect_core.TargetUnit(i18n.MailBox, fast_target, break_detect=True, log_level=log.level.DEBUG) ] # 送出訊息 api.connect_core.send(cmd, target_list) # 取得信件全文 origin_mail, _ = _api_util.get_content(api, post_mode=False) # 使用表示式分析信件作者 pattern_result = mail_author_pattern.search(origin_mail) if pattern_result is None: mail_author = None else: mail_author = pattern_result.group(0)[2:].strip() log.show_value(api.config, log.level.DEBUG, i18n.Author, mail_author) # 使用表示式分析信件標題 pattern_result = mail_title_pattern.search(origin_mail) if pattern_result is None: mail_title = None else: mail_title = pattern_result.group(0)[2:].strip() log.show_value(api.config, log.level.DEBUG, i18n.Title, mail_title) # 使用表示式分析信件日期 pattern_result = mail_date_pattern.search(origin_mail) if pattern_result is None: mail_date = None else: mail_date = pattern_result.group(0)[2:].strip() log.show_value(api.config, log.level.DEBUG, i18n.Date, mail_date) # 從全文拿掉信件開頭作為信件內文 mail_content = origin_mail[origin_mail.find(content_start) + len(content_start) + 1:] # 紅包偵測 red_envelope = False if content_end not in origin_mail and 'Ptt幣的大紅包喔' in origin_mail: mail_content = mail_content.strip() red_envelope = True else: mail_content = mail_content[:mail_content.rfind(content_end) + 3] log.show_value(api.config, log.level.DEBUG, i18n.Content, mail_content) if red_envelope: mail_ip = None mail_location = None else: # ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 111.242.182.114 # ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 59.104.127.126 (臺灣) # 非紅包開始解析 ip 與 地區 ip_line_list = origin_mail.split('\n') ip_line = [x for x in ip_line_list if x.startswith(content_end[3:])] if len(ip_line) == 0: # 沒 ip 就沒地區 mail_ip = None mail_location = None else: ip_line = ip_line[0] result = ip_pattern.search(ip_line) if result is None: ip_line = [ x for x in ip_line_list if x.startswith(content_ip_old) ] if len(ip_line) == 0: mail_ip = None else: ip_line = ip_line[0] result = ip_pattern.search(ip_line) mail_ip = result.group(0) else: mail_ip = result.group(0) log.show_value(api.config, log.level.DEBUG, [ i18n.MailBox, 'IP', ], mail_ip) location = ip_line[ip_line.find(mail_ip) + len(mail_ip):].strip() if len(location) == 0: mail_location = None else: # print(location) mail_location = location[1:-1] log.show_value(api.config, log.level.DEBUG, [ i18n.MailBox, 'location', ], mail_location) mail_result = data_type.MailInfo(origin_mail=origin_mail, author=mail_author, title=mail_title, date=mail_date, content=mail_content, ip=mail_ip, location=mail_location, is_red_envelope=red_envelope) return mail_result
def bucket(api: object, board: str, bucket_days: int, reason: str, ptt_id: str) -> None: api._goto_board(board) cmd_list = list() cmd_list.append('i') cmd_list.append(command.Ctrl_P) cmd_list.append('w') cmd_list.append(command.Enter) cmd_list.append('a') cmd_list.append(command.Enter) cmd_list.append(ptt_id) cmd_list.append(command.Enter) cmd = ''.join(cmd_list) cmd_list = list() cmd_list.append(str(bucket_days)) cmd_list.append(command.Enter) cmd_list.append(reason) cmd_list.append(command.Enter) cmd_list.append('y') cmd_list.append(command.Enter) cmd_part2 = ''.join(cmd_list) target_list = [ connect_core.TargetUnit( [ i18n.bucket, i18n.Fail, ], '◆ 使用者之前已被禁言', exceptions_=exceptions.UserHasPreviouslyBeenBanned()), connect_core.TargetUnit( i18n.InputBucketDays_Reason, '請以數字跟單位(預設為天)輸入期限', response=cmd_part2, ), connect_core.TargetUnit( [ i18n.bucket, i18n.Success, ], '其它鍵結束', response=command.Enter, ), connect_core.TargetUnit( [ i18n.bucket, i18n.Success, ], '權限設定系統', response=command.Enter, ), connect_core.TargetUnit( [ i18n.bucket, i18n.Success, ], '任意鍵', response=command.Space, ), connect_core.TargetUnit([ i18n.bucket, i18n.Success, ], screens.Target.InBoard, break_detect=True), ] api.connect_core.send(cmd, target_list)
def get_content(api, post_mode: bool = True): api.Unconfirmed = False def is_unconfirmed_handler(screen): api.Unconfirmed = True if post_mode: cmd = command.Enter * 2 else: cmd = command.Enter target_list = [ # 待證實文章 connect_core.TargetUnit(i18n.UnconfirmedPost, '本篇文章內容經站方授權之板務管理人員判斷有尚待證實之處', response=' ', handler=is_unconfirmed_handler), connect_core.TargetUnit([ i18n.BrowsePost, i18n.Done, ], screens.Target.PostEnd, break_detect=True, log_level=log.level.DEBUG), connect_core.TargetUnit([ i18n.BrowsePost, ], screens.Target.InPost, break_detect=True, log_level=log.level.DEBUG), connect_core.TargetUnit([ i18n.PostNoContent, ], screens.Target.PostNoContent, break_detect=True, log_level=log.level.DEBUG), # 動畫文章 connect_core.TargetUnit([ i18n.AnimationPost, ], screens.Target.Animation, response=command.GoMainMenu_TypeQ, break_detect_after_send=True), ] line_from_pattern = re.compile('[\d]+~[\d]+') content_start = '───────────────────────────────────────' content_end = list() content_end.append('--\n※ 發信站: 批踢踢實業坊') content_end.append('--\n※ 發信站: 批踢踢兔(ptt2.cc)') content_end.append('--\n※ 發信站: 新批踢踢(ptt2.twbbs.org.tw)') has_control_code = False control_code_mode = False push_start = False content_start_exist = False content_start_jump = False content_start_jump_set = False first_page = True origin_post = list() stop_dict = dict() while True: index = api.connect_core.send(cmd, target_list) if index == 3 or index == 4: return None, False last_screen = api.connect_core.get_screen_queue()[-1] lines = last_screen.split('\n') last_line = lines[-1] lines.pop() last_screen = '\n'.join(lines) if content_start in last_screen and not content_start_exist: content_start_exist = True if content_start_exist: if not content_start_jump_set: if content_start not in last_screen: content_start_jump = True content_start_jump_set = True else: content_start_jump = False pattern_result = line_from_pattern.search(last_line) if pattern_result is None: control_code_mode = True has_control_code = True else: last_read_line_list = pattern_result.group(0).split('~') last_read_line_a_temp = int(last_read_line_list[0]) last_read_line_b_temp = int(last_read_line_list[1]) if control_code_mode: last_read_line_a = last_read_line_a_temp - 1 last_read_line_b = last_read_line_b_temp - 1 control_code_mode = False if first_page: first_page = False origin_post.append(last_screen) else: # print(LastScreen) # print(f'last_read_line_a_temp [{last_read_line_a_temp}]') # print(f'last_read_line_b_temp [{last_read_line_b_temp}]') # print(f'last_read_line_a {last_read_line_a}') # print(f'last_read_line_b {last_read_line_b}') # print(f'GetLineB {last_read_line_a_temp - last_read_line_a}') # print(f'GetLineA {last_read_line_b_temp - last_read_line_b}') # print(f'show line {last_read_line_b_temp - last_read_line_a_temp + 1}') if not control_code_mode: if last_read_line_a_temp in stop_dict: new_content_part = '\n'.join( lines[-stop_dict[last_read_line_a_temp]:]) stop_dict = dict() else: get_line_b = last_read_line_b_temp - last_read_line_b if get_line_b > 0: # print('Type 1') # print(f'Type 1 line_dis [{line_dis}]') # print(f'Type 1 get_line_b [{get_line_b}]') # print('index', index) new_content_part = '\n'.join(lines[-get_line_b:]) if index == 1 and len( new_content_part) == get_line_b - 1: # print(1) new_content_part = '\n'.join( lines[-(get_line_b * 2):]) elif origin_post: # print(2) last_line_temp = origin_post[-1].strip() try_line = lines[-(get_line_b + 1)].strip() if not last_line_temp.endswith(try_line): # print(3) # print('=====' * 20) # print('== last line [', last_line_temp, ']') # print('== try_line [', try_line, ']') new_content_part = try_line + '\n' + new_content_part stop_dict = dict() else: # 駐足現象,LastReadLineB跟上一次相比並沒有改變 if (last_read_line_b_temp + 1) not in stop_dict: stop_dict[last_read_line_b_temp + 1] = 1 stop_dict[last_read_line_b_temp + 1] += 1 get_line_a = last_read_line_a_temp - last_read_line_a if get_line_a > 0: # print(f'Type 2 get_line_a [{get_line_a}]') new_content_part = '\n'.join(lines[-get_line_a:]) else: new_content_part = '\n'.join(lines) else: new_content_part = lines[-1] origin_post.append(new_content_part) log.show_value(api.config, log.level.DEBUG, 'NewContentPart', new_content_part) if index == 1: if content_start_jump and len(new_content_part) == 0: # print(f'!!!GetLineB {GetLineB}') get_line_b += 1 new_content_part = '\n'.join(lines[-get_line_b:]) # print(f'!!!NewContentPart {NewContentPart}') origin_post.pop() origin_post.append(new_content_part) break if not control_code_mode: last_read_line_a = last_read_line_a_temp last_read_line_b = last_read_line_b_temp for EC in content_end: if EC in last_screen: push_start = True break if not push_start: cmd = command.Down else: cmd = command.Right # print(api.Unconfirmed) origin_post = '\n'.join(origin_post) # OriginPost = [line.strip() for line in OriginPost.split('\n')] # OriginPost = '\n'.join(OriginPost) log.show_value(api.config, log.level.DEBUG, 'OriginPost', origin_post) return origin_post, has_control_code
def get_board_info(api, board: str, get_post_kind: bool, call_by_others: bool) -> None: if call_by_others: log_level = log.level.DEBUG else: log_level = log.level.INFO api._goto_board(board, refresh=True) ori_screen = api.connect_core.get_screen_queue()[-1] # print(ori_screen) nuser = None for line in ori_screen.split('\n'): if '編號' not in line: continue if '日 期' not in line: continue if '人氣' not in line: continue nuser = line break if nuser is None: raise exceptions.NoSuchBoard(api.config, board) # print('------------------------') # print('nuser', nuser) # print('------------------------') if '[靜]' in nuser: online_user = 0 else: if '編號' not in nuser or '人氣' not in nuser: raise exceptions.NoSuchBoard(api.config, board) pattern = re.compile('[\d]+') r = pattern.search(nuser) if r is None: raise exceptions.NoSuchBoard(api.config, board) # 減一是把自己本身拿掉 online_user = int(r.group(0)) - 1 log.show_value(api.config, log.level.DEBUG, '人氣', online_user) target_list = [ connect_core.TargetUnit(i18n.ReadingBoardInfo, '任意鍵繼續', break_detect=True, log_level=log_level), ] api.connect_core.send('i', target_list) ori_screen = api.connect_core.get_screen_queue()[-1] # print(ori_screen) p = re.compile('《(.+)》看板設定') r = p.search(ori_screen) if r is not None: boardname = r.group(0)[1:-5].strip() log.show_value(api.config, log.level.DEBUG, '看板名稱', boardname) if boardname.lower() != board.lower(): raise exceptions.NoSuchBoard(api.config, board) p = re.compile('中文敘述: (.+)') r = p.search(ori_screen) if r is not None: chinese_des = r.group(0)[5:].strip() log.show_value(api.config, log.level.DEBUG, '中文敘述', chinese_des) p = re.compile('板主名單: (.+)') r = p.search(ori_screen) if r is not None: moderator_line = r.group(0)[5:].strip() if '(無)' in moderator_line: moderators = list() else: moderators = moderator_line.split('/') for moderator in moderators.copy(): check = True for c in moderator: if len(c.encode('big5')) > 1: check = False break if not check: moderators.remove(moderator) log.show_value(api.config, log.level.DEBUG, '板主名單', moderators) open_status = ('公開狀態(是否隱形): 公開' in ori_screen) log.show_value(api.config, log.level.DEBUG, '公開狀態', open_status) into_top_ten_when_hide = ('隱板時 可以 進入十大排行榜' in ori_screen) log.show_value(api.config, log.level.DEBUG, '隱板時可以進入十大排行榜', into_top_ten_when_hide) non_board_members_post = ('開放 非看板會員發文' in ori_screen) log.show_value(api.config, log.level.DEBUG, '非看板會員發文', non_board_members_post) reply_post = ('開放 回應文章' in ori_screen) log.show_value(api.config, log.level.DEBUG, '回應文章', reply_post) self_del_post = ('開放 自刪文章' in ori_screen) log.show_value(api.config, log.level.DEBUG, '自刪文章', self_del_post) push_post = ('開放 推薦文章' in ori_screen) log.show_value(api.config, log.level.DEBUG, '推薦文章', push_post) boo_post = ('開放 噓文' in ori_screen) log.show_value(api.config, log.level.DEBUG, '噓文', boo_post) # 限制 快速連推文章, 最低間隔時間: 5 秒 # 開放 快速連推文章 fast_push = ('開放 快速連推文章' in ori_screen) log.show_value(api.config, log.level.DEBUG, '快速連推文章', fast_push) if not fast_push: p = re.compile('最低間隔時間: [\d]+') r = p.search(ori_screen) if r is not None: min_interval = r.group(0)[7:].strip() min_interval = int(min_interval) else: min_interval = 0 log.show_value(api.config, log.level.DEBUG, '最低間隔時間', min_interval) else: min_interval = 0 # 推文時 自動 記錄來源 IP # 推文時 不會 記錄來源 IP push_record_ip = ('推文時 自動 記錄來源 IP' in ori_screen) log.show_value(api.config, log.level.DEBUG, '記錄來源 IP', push_record_ip) # 推文時 對齊 開頭 # 推文時 不用對齊 開頭 push_aligned = ('推文時 對齊 開頭' in ori_screen) log.show_value(api.config, log.level.DEBUG, '對齊開頭', push_aligned) # 板主 可 刪除部份違規文字 moderator_can_del_illegal_content = ('板主 可 刪除部份違規文字' in ori_screen) log.show_value(api.config, log.level.DEBUG, '板主可刪除部份違規文字', moderator_can_del_illegal_content) # 轉錄文章 會 自動記錄,且 需要 發文權限 tran_post_auto_recorded_and_require_post_permissions = ( '轉錄文章 會 自動記錄,且 需要 發文權限' in ori_screen) log.show_value(api.config, log.level.DEBUG, '轉錄文章 會 自動記錄,且 需要 發文權限', tran_post_auto_recorded_and_require_post_permissions) cool_mode = ('未 設為冷靜模式' not in ori_screen) log.show_value(api.config, log.level.DEBUG, '冷靜模式', cool_mode) require18 = ('禁止 未滿十八歲進入' in ori_screen) log.show_value(api.config, log.level.DEBUG, '禁止未滿十八歲進入', require18) p = re.compile('登入次數 [\d]+ 次以上') r = p.search(ori_screen) if r is not None: require_login_time = r.group(0).split(' ')[1] require_login_time = int(require_login_time) else: require_login_time = 0 log.show_value(api.config, log.level.DEBUG, '發文限制登入次數', require_login_time) p = re.compile('退文篇數 [\d]+ 篇以下') r = p.search(ori_screen) if r is not None: require_illegal_post = r.group(0).split(' ')[1] require_illegal_post = int(require_illegal_post) else: require_illegal_post = 0 log.show_value(api.config, log.level.DEBUG, '發文限制退文篇數', require_illegal_post) kind_list = None if get_post_kind: api._goto_board(board) # Go certain board, then post to get post type info cmd_list = list() cmd_list.append(command.Ctrl_P) cmd = ''.join(cmd_list) target_list = [ connect_core.TargetUnit(i18n.NoPermission, '無法發文: 未達看板要求權限', break_detect=True), connect_core.TargetUnit(i18n.Done, '或不選)', break_detect=True) ] index = api.connect_core.send(cmd, target_list) if index == 0: raise exceptions.NoPermission(i18n.NoPermission) # no post permission ori_screen = api.connect_core.get_screen_queue()[-1] screen_lines = ori_screen.split('\n') for i in screen_lines: if '種類:' in i: type_pattern = re.compile('\d\.([^\ ]*)') # 0 is not present any type that the key hold None object kind_list = type_pattern.findall(i) break # Clear post status cmd_list = list() cmd_list.append(command.Ctrl_C) cmd_list.append(command.Ctrl_C) cmd = ''.join(cmd_list) target_list = [ connect_core.TargetUnit(i18n.Done, screens.Target.InBoard, break_detect=True) ] api.connect_core.send(cmd, target_list) board_info = data_type.BoardInfo( boardname, online_user, chinese_des, moderators, open_status, into_top_ten_when_hide, non_board_members_post, reply_post, self_del_post, push_post, boo_post, fast_push, min_interval, push_record_ip, push_aligned, moderator_can_del_illegal_content, tran_post_auto_recorded_and_require_post_permissions, cool_mode, require18, require_login_time, require_illegal_post, kind_list) return board_info
def get_post_index( api, board: str, aid: str) -> int: api._goto_board(board) cmd_list = list() cmd_list.append('#') cmd_list.append(aid) cmd_list.append(command.Enter) cmd = ''.join(cmd_list) no_such_post = i18n.NoSuchPost no_such_post = i18n.replace(no_such_post, board, aid) target_list = [ connect_core.TargetUnit( no_such_post, '找不到這個文章代碼', log_level=log.level.DEBUG, exceptions_=exceptions.NoSuchPost(board, aid) ), # 此狀態下無法使用搜尋文章代碼(AID)功能 connect_core.TargetUnit( i18n.CanNotUseSearchPostCodeF, '此狀態下無法使用搜尋文章代碼(AID)功能', exceptions_=exceptions.CanNotUseSearchPostCode() ), connect_core.TargetUnit( i18n.NoPost, '沒有文章...', exceptions_=exceptions.NoSuchPost(board, aid) ), connect_core.TargetUnit( i18n.Success, screens.Target.InBoard, break_detect=True, log_level=log.level.DEBUG ), connect_core.TargetUnit( i18n.Success, screens.Target.InBoardWithCursor, break_detect=True, log_level=log.level.DEBUG ), connect_core.TargetUnit( i18n.NoSuchBoard, screens.Target.MainMenu_Exiting, exceptions_=exceptions.NoSuchBoard(api.config, board) # BreakDetect=True, ) ] index = api.connect_core.send( cmd, target_list ) ori_screen = api.connect_core.get_screen_queue()[-1] if index < 0: # print(OriScreen) raise exceptions.NoSuchBoard(api.config, board) # if index == 5: # print(OriScreen) # raise exceptions.NoSuchBoard(api.config, Board) # print(index) # print(OriScreen) screen_list = ori_screen.split('\n') line = [x for x in screen_list if x.startswith(api.cursor)] line = line[0] last_line = screen_list[screen_list.index(line) - 1] # print(LastLine) # print(line) if '編號' in last_line and '人氣:' in last_line: index = line[1:].strip() index_fix = False else: index = last_line.strip() index_fix = True while ' ' in index: index = index.replace(' ', ' ') index_list = index.split(' ') index = index_list[0] if index == '★': return 0 index = int(index) if index_fix: index += 1 # print(Index) return index
def get_user(api, ptt_id: str) -> data_type.UserInfo: cmd_list = list() cmd_list.append(command.GoMainMenu) cmd_list.append('T') cmd_list.append(command.Enter) cmd_list.append('Q') cmd_list.append(command.Enter) cmd_list.append(ptt_id) cmd_list.append(command.Enter) cmd = ''.join(cmd_list) target_list = [ connect_core.TargetUnit( [ i18n.GetUser, i18n.Success, ], screens.Target.AnyKey, break_detect=True), connect_core.TargetUnit( [ i18n.GetUser, i18n.Fail, ], screens.Target.InTalk, break_detect=True), ] index = api.connect_core.send( cmd, target_list) ori_screen = api.connect_core.get_screen_queue()[-1] if index == 1: raise exceptions.NoSuchUser(ptt_id) # PTT1 # 《ID暱稱》CodingMan (專業程式 BUG 製造機)《經濟狀況》小康 ($73866) # 《登入次數》1118 次 (同天內只計一次) 《有效文章》15 篇 (退:0) # 《目前動態》閱讀文章 《私人信箱》最近無新信件 # 《上次上站》10/06/2019 17:29:49 Sun 《上次故鄉》111.251.231.184 # 《 五子棋 》 0 勝 0 敗 0 和 《象棋戰績》 0 勝 0 敗 0 和 # https://github.com/Truth0906/PTTLibrary # 強大的 PTT 函式庫 # 提供您 快速 穩定 完整 的 PTT API # 提供專業的 PTT 機器人諮詢服務 # PTT2 # 《ID暱稱》CodingMan (專業程式 BUG 製造機)《經濟狀況》家徒四壁 ($0) # 《登入次數》8 次 (同天內只計一次) 《有效文章》0 篇 # 《目前動態》看板列表 《私人信箱》最近無新信件 # 《上次上站》10/06/2019 17:27:55 Sun 《上次故鄉》111.251.231.184 # 《 五子棋 》 0 勝 0 敗 0 和 《象棋戰績》 0 勝 0 敗 0 和 # 《個人名片》CodingMan 目前沒有名片 # print(ori_screen) # data = lib_util.get_sub_string_list(ori_screen, '》', ['《', '\n']) data = parse_user_page(ori_screen) if len(data) < 10: print('\n'.join(data)) print(len(data)) raise exceptions.ParseError(ori_screen) # print('\n=> '.join(data)) ptt_id = data[0] money = data[1] login_time = int(data[2]) temp = re.findall(r'\d+', data[3]) legal_post = int(temp[0]) # PTT2 沒有退文 if api.config.host == data_type.host_type.PTT1: illegal_post = int(temp[1]) else: illegal_post = -1 status = data[4] mail = data[5] last_login = data[6] last_ip = data[7] five_chess = data[8] chess = data[9] signature_file = '\n'.join(ori_screen.split('\n')[6:-1]) log.show_value(api.config, log.level.DEBUG, 'ptt_id', ptt_id) log.show_value(api.config, log.level.DEBUG, 'money', money) log.show_value(api.config, log.level.DEBUG, 'login_time', login_time) log.show_value(api.config, log.level.DEBUG, 'legal_post', legal_post) log.show_value(api.config, log.level.DEBUG, 'illegal_post', illegal_post) log.show_value(api.config, log.level.DEBUG, 'status', status) log.show_value(api.config, log.level.DEBUG, 'mail', mail) log.show_value(api.config, log.level.DEBUG, 'last_login', last_login) log.show_value(api.config, log.level.DEBUG, 'last_ip', last_ip) log.show_value(api.config, log.level.DEBUG, 'five_chess', five_chess) log.show_value(api.config, log.level.DEBUG, 'chess', chess) log.show_value(api.config, log.level.DEBUG, 'signature_file', signature_file) user = data_type.UserInfo( ptt_id, money, login_time, legal_post, illegal_post, status, mail, last_login, last_ip, five_chess, chess, signature_file) return user
def get_mail(api, index) -> data_type.MailInfo: cmd_list = [] cmd_list.append(command.GoMainMenu) cmd_list.append(command.Ctrl_Z) cmd_list.append('m') cmd_list.append(str(index)) cmd_list.append(command.Enter) # cmd_list.append(command.Enter) cmd = ''.join(cmd_list) fast_target = '' for i in range(0, 5): space = ' ' * i fast_target = f'{api.cursor}{space}{index}' if api.cursor == data_type.Cursor.NEW: if len(fast_target) == 6: break else: if len(fast_target) == 5: break target_list = [ connect_core.TargetUnit(i18n.MailBox, screens.Target.InMailBox, break_detect=True, log_level=log.level.DEBUG), connect_core.TargetUnit(i18n.MailBox, fast_target, break_detect=True, log_level=log.level.DEBUG) ] api.connect_core.send( cmd, target_list, ) # last_screen = api.connect_core.get_screen_queue()[-1] # print(last_screen) origin_mail, _ = _api_util.get_content(api, post_mode=False) # print(origin_mail) mail_author_pattern = re.compile('作者 (.+)') pattern_result = mail_author_pattern.search(origin_mail) mail_author = pattern_result.group(0)[2:].strip() log.show_value(api.config, log.level.DEBUG, i18n.Author, mail_author) mail_title_pattern = re.compile('標題 (.+)') pattern_result = mail_title_pattern.search(origin_mail) mail_title = pattern_result.group(0)[2:].strip() log.show_value(api.config, log.level.DEBUG, i18n.Title, mail_title) mail_date_pattern = re.compile('時間 (.+)') pattern_result = mail_date_pattern.search(origin_mail) mail_date = pattern_result.group(0)[2:].strip() log.show_value(api.config, log.level.DEBUG, i18n.Date, mail_date) content_start = '───────────────────────────────────────' content_end = '--\n※ 發信站: 批踢踢實業坊(ptt.cc)' mail_content = origin_mail[origin_mail.find(content_start) + len(content_start) + 1:] red_envelope = False if content_end not in origin_mail and 'Ptt幣的大紅包喔' in origin_mail: mail_content = mail_content.strip() red_envelope = True else: mail_content = mail_content[:mail_content.rfind(content_end) + 3] log.show_value(api.config, log.level.DEBUG, i18n.Content, mail_content) if red_envelope: mail_ip = None mail_location = None else: # ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 111.242.182.114 # ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 59.104.127.126 (臺灣) ip_line = origin_mail.split('\n') ip_line = [x for x in ip_line if x.startswith(content_end[3:])][0] # print(ip_line) pattern = re.compile('[\d]+\.[\d]+\.[\d]+\.[\d]+') result = pattern.search(ip_line) mail_ip = result.group(0) log.show_value(api.config, log.level.DEBUG, [ i18n.MailBox, 'IP', ], mail_ip) location = ip_line[ip_line.find(mail_ip) + len(mail_ip):].strip() if len(location) == 0: mail_location = None else: # print(location) mail_location = location[1:-1] log.show_value(api.config, log.level.DEBUG, [ i18n.MailBox, 'location', ], mail_location) mail_result = data_type.MailInfo(origin_mail=origin_mail, author=mail_author, title=mail_title, date=mail_date, content=mail_content, ip=mail_ip, location=mail_location, red_envelope=red_envelope) return mail_result
def get_favourite_board(api) -> list: cmd_list = list() cmd_list.append(command.GoMainMenu) cmd_list.append('F') cmd_list.append(command.Enter) cmd_list.append('0') cmd = ''.join(cmd_list) target_list = [ connect_core.TargetUnit( i18n.FavouriteBoardList, '選擇看板', break_detect=True ) ] board_list = list() favourite_board_list = list() while True: api.connect_core.send( cmd, target_list ) ori_screen = api.connect_core.get_screen_queue()[-1] # print(OriScreen) screen_buf = ori_screen screen_buf = [x for x in screen_buf.split('\n')][3:][:-1] screen_buf[0] = ' ' + screen_buf[0][1:] screen_buf = [x for x in screen_buf] min_len = 47 # for line in ScreenBuf: # print(line[:MinLen - len(line)]) # print(len(line)) for i, line in enumerate(screen_buf): if len(screen_buf[i]) == 0: continue if len(screen_buf[i]) <= min_len: # print(f'[{ScreenBuf[i]}]') screen_buf[i] = screen_buf[i] + \ (' ' * ((min_len + 1) - len(screen_buf[i]))) screen_buf = [x[10:min_len - len(x)].strip() for x in screen_buf] screen_buf = list(filter(None, screen_buf)) for i, line in enumerate(screen_buf): # print(i) # 16 = line.find('◎') linebuff = line[:16].strip() board_type = linebuff[-2:] board = linebuff[:-2].strip() if board.startswith('ˇ'): board = board[1:] board_title = line[17:].strip() # print(line) # print('\t' + Type) # print('\t' + Board) # print('\t' + BoardTitle) if board in board_list: return favourite_board_list board_list.append(board) # # print('board', board) # print('board_type', board_type) # print('board_title', board_title) f_board = data_type.FavouriteBoard( board, board_type, board_title ) favourite_board_list.append(f_board) # print(len(FavouriteBoardList)) # print(len(screen_buf)) if len(screen_buf) < 20: break cmd = command.Ctrl_F # ScreenBuf = '\n'.join(ScreenBuf) # print(ScreenBuf) # print(len(FavouriteBoardList)) return favourite_board_list
def get_newest_index( api, index_type: int, board: str = None, # BBS search_type: int = 0, search_condition: str = None, search_list: list = None) -> int: if index_type == data_type.index_type.BBS: check_value.check(api.config, str, 'Board', board) api._check_board(board) check_value.check(api.config, int, 'SearchType', search_type, value_class=data_type.post_search_type) if search_condition is not None: check_value.check(api.config, str, 'SearchCondition', search_condition) if search_list is not None: check_value.check(api.config, list, 'search_list', search_list) check_value.check(api.config, int, 'SearchType', search_type) api._goto_board(board) cmd_list = list() normal_newest_index = -1 if search_condition is not None: normal_newest_index = get_newest_index(api, index_type, board=board) if search_type == data_type.post_search_type.KEYWORD: cmd_list.append('/') elif search_type == data_type.post_search_type.AUTHOR: cmd_list.append('a') elif search_type == data_type.post_search_type.PUSH: cmd_list.append('Z') elif search_type == data_type.post_search_type.MARK: cmd_list.append('G') elif search_type == data_type.post_search_type.MONEY: cmd_list.append('A') cmd_list.append(search_condition) cmd_list.append(command.Enter) if search_list is not None: if normal_newest_index == -1: normal_newest_index = get_newest_index(api, index_type, board=board) for search_type_, search_condition_ in search_list: if search_type_ == data_type.post_search_type.KEYWORD: cmd_list.append('/') elif search_type_ == data_type.post_search_type.AUTHOR: cmd_list.append('a') elif search_type_ == data_type.post_search_type.PUSH: cmd_list.append('Z') elif search_type_ == data_type.post_search_type.MARK: cmd_list.append('G') elif search_type_ == data_type.post_search_type.MONEY: cmd_list.append('A') cmd_list.append(search_condition_) cmd_list.append(command.Enter) cmd_list.append('1') cmd_list.append(command.Enter) cmd_list.append('$') cmd = ''.join(cmd_list) target_list = [ connect_core.TargetUnit(i18n.NoPost, '沒有文章...', break_detect=True, log_level=log.level.DEBUG), connect_core.TargetUnit(i18n.Success, screens.Target.InBoard, break_detect=True, log_level=log.level.DEBUG), connect_core.TargetUnit(i18n.Success, screens.Target.InBoardWithCursor, break_detect=True, log_level=log.level.DEBUG), connect_core.TargetUnit(i18n.NoSuchBoard, screens.Target.MainMenu_Exiting, exceptions_=exceptions.NoSuchBoard( api.config, board)), ] index = api.connect_core.send(cmd, target_list) if index < 0: # OriScreen = api.connect_core.getScreenQueue()[-1] # print(OriScreen) raise exceptions.NoSuchBoard(api.config, board) if index == 0: return 0 newest_index = _get_newest_index(api) if normal_newest_index == newest_index: raise exceptions.NoSearchResult() elif index_type == data_type.index_type.WEB: # web _NewestIndex = None newest_index = 0 _url = 'https://www.ptt.cc/bbs/' url = _url + board r = requests.get(url, cookies={'over18': '1'}) if r.status_code != requests.codes.ok: raise exceptions.NoSuchBoard(api.config, board) soup = BeautifulSoup(r.text, 'html.parser') for index, data in enumerate( soup.select('div.btn-group.btn-group-paging a')): text = data.text herf = data.get('href') if '上頁' in text: _NewestIndex = herf.split('index')[1].split('.')[0] # print("_NewestIndex: " + _NewestIndex) _NewestIndex = int(_NewestIndex) if _NewestIndex is None: raise exceptions.UnknownError('') newest_index = (_NewestIndex) + 1 elif index_type == data_type.index_type.MAIL: cmd_list = list() cmd_list.append(command.GoMainMenu) cmd_list.append(command.Ctrl_Z) cmd_list.append('m') cmd_list.append(command.Ctrl_F * 50) cmd = ''.join(cmd_list) target_list = [ connect_core.TargetUnit( i18n.MailBox, screens.Target.InMailBox, break_detect=True, # log_level=log.level.DEBUG ), connect_core.TargetUnit(i18n.NoMail, screens.Target.CursorToGoodbye, break_detect=True, log_level=log.level.DEBUG), ] def get_index(api): current_capacity, _ = _api_util.get_mailbox_capacity(api) last_screen = api.connect_core.get_screen_queue()[-1] cursor_line = [ x for x in last_screen.split('\n') if x.strip().startswith(api.cursor) ][0] # print(cursor_line) list_index = int(re.compile('(\d+)').search(cursor_line).group(0)) if list_index > current_capacity: newest_index = list_index else: newest_index = current_capacity return newest_index for _ in range(3): index = api.connect_core.send( cmd, target_list, ) if index == 0: newest_index = get_index(api) break newest_index = 0 return newest_index
def push( api, board: str, push_type: int, push_content: str, post_aid: str, post_index: int) -> None: cmd_list = [] cmd_list.append(command.GoMainMenu) cmd_list.append('qs') cmd_list.append(board) cmd_list.append(command.Enter) cmd_list.append(command.Ctrl_C * 2) cmd_list.append(command.Space) if post_aid is not None: cmd_list.append('#' + post_aid) elif post_index != 0: cmd_list.append(str(post_index)) cmd_list.append(command.Enter) cmd_list.append(command.Push) cmd = ''.join(cmd_list) target_list = [ connect_core.TargetUnit( i18n.HasPushPermission, '您覺得這篇', log_level=log.level.DEBUG, break_detect=True ), connect_core.TargetUnit( i18n.OnlyArrow, '加註方式', log_level=log.level.DEBUG, break_detect=True ), connect_core.TargetUnit( i18n.NoFastPush, '禁止快速連續推文', log_level=log.level.INFO, break_detect=True, exceptions_=exceptions.NoFastPush() ), connect_core.TargetUnit( i18n.NoFastPush, '禁止短時間內大量推文', log_level=log.level.INFO, break_detect=True, exceptions_=exceptions.NoFastPush() ), connect_core.TargetUnit( i18n.NoPermission, '使用者不可發言', log_level=log.level.INFO, break_detect=True, exceptions_=exceptions.NoPermission(i18n.NoPermission) ), connect_core.TargetUnit( i18n.NoPush, '◆ 抱歉, 禁止推薦', log_level=log.level.INFO, break_detect=True, exceptions_=exceptions.NoPush() ), ] index = api.connect_core.send( cmd, target_list ) if index == -1: if post_aid is not None: raise exceptions.NoSuchPost(board, post_aid) else: raise exceptions.NoSuchPost(board, post_index) cmd_list = [] if index == 0: push_option_line = api.connect_core.get_screen_queue()[-1] push_option_line = push_option_line.split('\n')[-1] log.show_value(api.config, log.level.DEBUG, 'Push option line', push_option_line) enable_push = '值得推薦' in push_option_line enable_boo = '給它噓聲' in push_option_line enable_arrow = '只加→註解' in push_option_line log.show_value(api.config, log.level.DEBUG, 'Push', enable_push) log.show_value(api.config, log.level.DEBUG, 'Boo', enable_boo) log.show_value(api.config, log.level.DEBUG, 'Arrow', enable_arrow) if push_type == data_type.push_type.PUSH and not enable_push: push_type = data_type.push_type.ARROW elif push_type == data_type.push_type.BOO and not enable_boo: push_type = data_type.push_type.ARROW elif push_type == data_type.push_type.ARROW and not enable_arrow: push_type = data_type.push_type.PUSH cmd_list.append(str(push_type)) # elif index == 1: # push_type = data_type.push_type.ARROW cmd_list.append(push_content) cmd_list.append(command.Enter) cmd_list.append('y') cmd_list.append(command.Enter) cmd = ''.join(cmd_list) target_list = [ connect_core.TargetUnit( [ i18n.Push, i18n.Success, ], screens.Target.InBoard, break_detect=True, log_level=log.level.DEBUG ), ] api.connect_core.send( cmd, target_list )
def get_waterball(api, operate_type:int) -> list: if operate_type == data_type.waterball_operate_type.NOTHING: water_ball_operate_type = 'R' elif operate_type == data_type.waterball_operate_type.CLEAR: water_ball_operate_type = 'C' + command.Enter + 'Y' elif operate_type == data_type.waterball_operate_type.MAIL: water_ball_operate_type = 'M' target_list = [ connect_core.TargetUnit( i18n.NoWaterball, '◆ 暫無訊息記錄', break_detect=True, log_level=log.level.DEBUG ), connect_core.TargetUnit( [ i18n.BrowseWaterball, i18n.Done, ], screens.Target.WaterBallListEnd, response=command.Left + water_ball_operate_type + command.Enter + command.GoMainMenu, break_detect_after_send=True, log_level=log.level.DEBUG ), connect_core.TargetUnit( [ i18n.BrowseWaterball, ], screens.Target.InWaterBallList, break_detect=True, log_level=log.level.DEBUG ), ] cmd_list = [command.GoMainMenu, 'T', command.Enter, 'D', command.Enter] cmd = ''.join(cmd_list) line_from_pattern = re.compile('[\d]+~[\d]+') to_water_ball_target_pattern = re.compile('To [\w]+:') from_water_ball_target_pattern = re.compile('★[\w]+ ') water_ball_date_pattern = re.compile( '\[[\d]+/[\d]+/[\d]+ [\d]+:[\d]+:[\d]+\]') all_waterball = list() first_page = True while True: index = api.connect_core.send( cmd, target_list, # screen_timeout=1 ) log.show_value( api.config, log.level.DEBUG, 'index', index ) if index == 0: return [] ori_screen = api.connect_core.get_screen_queue()[-1] lines = ori_screen.split('\n') last_line = lines[-1] lines.pop() lines = list(filter(None, lines)) ori_screen = '\n'.join(lines) # print('=' * 50) # print(OriScreen) # print('=' * 50) # ScreenTemp = OriScreen log.show_value( api.config, log.level.DEBUG, 'OriScreen', ori_screen ) log.show_value( api.config, log.level.DEBUG, 'LastLine', last_line ) if last_line.startswith('★'): continue # 整理水球換行格式 # ScreenTemp = ScreenTemp.replace( # ']\n', ']==PTTWaterBallNewLine==') # ScreenTemp = ScreenTemp.replace('\\\n', '') # ScreenTemp = ScreenTemp.replace('\n', '') # ScreenTemp = ScreenTemp.replace( # ']==PTTWaterBallNewLine==', ']\n') # print('=' * 50) # print(LastLine) # print('=' * 50) pattern_result = line_from_pattern.search(last_line) try: last_read_line_list = pattern_result.group(0).split('~') except Exception as e: import traceback traceback.print_tb(e.__traceback__) print(e) print(f'ori_screen {ori_screen}') print(f'last_line {last_line}') raise e last_read_line_a_temp = int(last_read_line_list[0]) last_read_line_b_temp = int(last_read_line_list[1]) # last_read_line_a = last_read_line_a_temp - 1 # last_read_line_b = last_read_line_b_temp - 1 if first_page: first_page = False all_waterball.append(ori_screen) last_read_line_a = last_read_line_a_temp - 1 last_read_line_b = last_read_line_b_temp - 1 else: get_line_a = last_read_line_a_temp - last_read_line_a get_line_b = last_read_line_b_temp - last_read_line_b # print(f'last_read_line_a [{last_read_line_a}]') # print(f'last_read_line_b [{last_read_line_b}]') # print(f'last_read_line_a_temp [{last_read_line_a_temp}]') # print(f'last_read_line_b_temp [{last_read_line_b_temp}]') # print(f'get_line_a [{get_line_a}]') # print(f'get_line_b [{get_line_b}]') if get_line_b > 0: # print('Type 1') if not all_waterball[-1].endswith(']'): get_line_b += 1 new_content_part = '\n'.join(lines[-get_line_b:]) else: # print('Type 2') if get_line_a > 0: # print('Type 2 - 1') if len(lines[-get_line_a]) == 0: # print('!!!!!!!!!') get_line_a += 1 new_content_part = '\n'.join(lines[-get_line_a:]) else: # print('Type 2 - 2') new_content_part = '\n'.join(lines) all_waterball.append(new_content_part) log.show_value( api.config, log.level.DEBUG, 'NewContentPart', new_content_part ) if index == 1: break last_read_line_a = last_read_line_a_temp last_read_line_b = last_read_line_b_temp cmd = command.Down all_waterball = '\n'.join(all_waterball) if api.config.host == data_type.host_type.PTT1: all_waterball = all_waterball.replace( ']\n', ']==PTTWaterBallNewLine==') all_waterball = all_waterball.replace('\n', '') all_waterball = all_waterball.replace( ']==PTTWaterBallNewLine==', ']\n') else: all_waterball = all_waterball.replace('\\\n', '') log.show_value( api.config, log.level.DEBUG, 'AllWaterball', all_waterball ) # print('=' * 20) # print(AllWaterball) # print('=' * 20) water_ball_list = list() for line in all_waterball.split('\n'): if (not line.startswith('To')) and (not line.startswith('★')): log.show_value( api.config, log.level.DEBUG, 'Discard waterball', line ) continue log.show_value( api.config, log.level.DEBUG, 'Ready to parse waterball', line ) if line.startswith('To'): log.show_value( api.config, log.level.DEBUG, 'Waterball Type', 'Send' ) waterball_type = data_type.waterball_type.SEND pattern_result = to_water_ball_target_pattern.search(line) target = pattern_result.group(0)[3:-1] pattern_result = water_ball_date_pattern.search(line) date = pattern_result.group(0)[1:-1] content = line content = content[content.find( target + ':') + len(target + ':'):] content = content[:content.rfind(date) - 1] content = content.strip() elif line.startswith('★'): log.show_value( api.config, log.level.DEBUG, 'Waterball Type', 'Catch' ) waterball_type = data_type.waterball_type.CATCH pattern_result = from_water_ball_target_pattern.search(line) target = pattern_result.group(0)[1:-1] pattern_result = water_ball_date_pattern.search(line) date = pattern_result.group(0)[1:-1] content = line content = content[content.find( target + ' ') + len(target + ' '):] content = content[:content.rfind(date) - 1] content = content.strip() log.show_value( api.config, log.level.DEBUG, 'Waterball target', target ) log.show_value( api.config, log.level.DEBUG, 'Waterball content', content ) log.show_value( api.config, log.level.DEBUG, 'Waterball date', date ) current_waterball = data_type.WaterballInfo( waterball_type, target, content, date ) water_ball_list.append(current_waterball) return water_ball_list
def get_call_status(api) -> None: cmd_list = [] cmd_list.append(command.GoMainMenu) cmd_list.append('A') cmd_list.append(command.Right) cmd_list.append(command.Left) cmd = ''.join(cmd_list) target_list = [ connect_core.TargetUnit([ i18n.GetCallStatus, i18n.Success, ], '[呼叫器]打開', break_detect=True, log_level=log.level.DEBUG), connect_core.TargetUnit([ i18n.GetCallStatus, i18n.Success, ], '[呼叫器]拔掉', break_detect=True, log_level=log.level.DEBUG), connect_core.TargetUnit([ i18n.GetCallStatus, i18n.Success, ], '[呼叫器]防水', break_detect=True, log_level=log.level.DEBUG), connect_core.TargetUnit([ i18n.GetCallStatus, i18n.Success, ], '[呼叫器]好友', break_detect=True, log_level=log.level.DEBUG), connect_core.TargetUnit([ i18n.GetCallStatus, i18n.Success, ], '[呼叫器]關閉', break_detect=True, log_level=log.level.DEBUG), connect_core.TargetUnit([ i18n.GetCallStatus, ], '★', response=cmd, log_level=log.level.DEBUG), ] for i in range(2): index = api.connect_core.send(cmd, target_list) if index < 0: if i == 0: continue ori_screen = api.connect_core.get_screen_queue()[-1] raise exceptions.UnknownError(ori_screen) if index == 0: return data_type.call_status.ON if index == 1: return data_type.call_status.UNPLUG if index == 2: return data_type.call_status.WATERPROOF if index == 3: return data_type.call_status.FRIEND if index == 4: return data_type.call_status.OFF ori_screen = api.connect_core.get_screen_queue()[-1] raise exceptions.UnknownError(ori_screen)
def search_user(api: object, ptt_id: str, min_page: int, max_page: int) -> list: cmd_list = [] cmd_list.append(command.GoMainMenu) cmd_list.append('T') cmd_list.append(command.Enter) cmd_list.append('Q') cmd_list.append(command.Enter) cmd_list.append(ptt_id) cmd = ''.join(cmd_list) if min_page is not None: template = min_page else: template = 1 appendstr = ' ' * template cmdtemp = cmd + appendstr target_list = [ connect_core.TargetUnit( i18n.AnyKeyContinue, '任意鍵', break_detect=True, ), ] resultlist = [] while True: api.connect_core.send(cmdtemp, target_list) ori_screen = api.connect_core.get_screen_queue()[-1] log.log(api.config, log.level.INFO, i18n.Reading) # print(OriScreen) # print(len(OriScreen.split('\n'))) if len(ori_screen.split('\n')) == 2: resultid = ori_screen.split('\n')[1] resultid = resultid[resultid.find(' ') + 1:].strip() # print(resultid) resultlist.append(resultid) break else: ori_screen = ori_screen.split('\n')[3:-1] ori_screen = '\n'.join(ori_screen) templist = ori_screen.replace('\n', ' ') while ' ' in templist: templist = templist.replace(' ', ' ') templist = templist.split(' ') resultlist.extend(templist) # print(templist) # print(len(templist)) if len(templist) != 100 and len(templist) != 120: break template += 1 if max_page is not None: if template > max_page: break cmdtemp = ' ' log.log(api.config, log.level.INFO, i18n.ReadComplete) api.connect_core.send( command.Enter, [ # 《ID暱稱》 connect_core.TargetUnit( i18n.QuitUserProfile, '《ID暱稱》', response=command.Enter, # log_level=log.level.DEBUG ), connect_core.TargetUnit( i18n.Done, '查詢網友', break_detect=True, # log_level=log.level.DEBUG ) ]) return list(filter(None, resultlist))
def has_new_mail(api) -> int: cmd_list = list() cmd_list.append(command.GoMainMenu) cmd_list.append(command.Ctrl_Z) cmd_list.append('m') # cmd_list.append('1') # cmd_list.append(command.Enter) cmd = ''.join(cmd_list) current_capacity = None plus_count = 0 index_pattern = re.compile('(\d+)') checked_index_list = list() break_detect = False target_list = [ connect_core.TargetUnit(i18n.MailBox, screens.Target.InMailBox, break_detect=True, log_level=log.level.DEBUG) ] api.connect_core.send( cmd, target_list, ) current_capacity, _ = _api_util.get_mailbox_capacity(api) if current_capacity > 20: cmd_list = list() cmd_list.append(command.GoMainMenu) cmd_list.append(command.Ctrl_Z) cmd_list.append('m') cmd_list.append('1') cmd_list.append(command.Enter) cmd = ''.join(cmd_list) while True: if current_capacity > 20: api.connect_core.send( cmd, target_list, ) last_screen = api.connect_core.get_screen_queue()[-1] last_screen_list = last_screen.split('\n') last_screen_list = last_screen_list[3:-1] last_screen_list = [x[:10] for x in last_screen_list] current_plus_count = 0 for line in last_screen_list: if str(current_capacity) in line: break_detect = True index_result = index_pattern.search(line) if index_result is None: continue current_index = index_result.group(0) if current_index in checked_index_list: continue checked_index_list.append(current_index) if '+' not in line: continue current_plus_count += 1 plus_count += current_plus_count if break_detect: break cmd = command.Ctrl_F return plus_count