From a3cdc80706667d1aa98a02969eff67e983e7e339 Mon Sep 17 00:00:00 2001 From: decoded Date: Sat, 5 Nov 2022 18:59:52 -0500 Subject: [PATCH] v2.667 --- dr1p4ns1.py | 424 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 261 insertions(+), 163 deletions(-) diff --git a/dr1p4ns1.py b/dr1p4ns1.py index 7fbcd36..f8e0d89 100644 --- a/dr1p4ns1.py +++ b/dr1p4ns1.py @@ -1,9 +1,15 @@ -########################################################################################### dr1p4ns1 version 2.666 ##### SOF +########################################################################################### dr1p4ns1 version 2.667 ##### SOF #################################################################################################### ####################### +import os +import shutil +import sys +import termios +import threading +import tty +from collections import namedtuple from glob import glob from time import sleep -from collections import namedtuple -import sys,tty,os,termios,shutil + #################################################################################################### ####################### #################################################################################################### ####################### ##### @@ -47,7 +53,10 @@ FIFO_PATH = f"{os.path.expanduser('~')}/.weechat/weechat_fifo" FIFO_ENABLED = True ##### COPY_PATH = f"{os.path.expanduser('~')}/Pictures" ##### DELETE_PATH = "/tmp" ##### -FLOODRATE_INTERVAL_SECONDS = 0.335 ##### +FLOODRATE_INTERVAL_SECONDS = 0.125 ##### +global SHOW_FILENAME ##### +SHOW_FILENAME=True ##### +DR1P_VERSION="2.667 - 11/05/22 - https://git.tcp.direct/decoded/dr1p4ns1" ##### #################################################################################################### ####################### #################################################################################################### ####################### ##### @@ -102,7 +111,6 @@ class D: self.delay=FLOODRATE_INTERVAL_SECONDS self.correct=0 ########################################################################################################## CLASS DR1P4NS1 - 2 - class dr1p4ns1: ############################################################################################################ LOOKUP TABLE commands = { @@ -117,7 +125,8 @@ class dr1p4ns1: 's': 'save_cursor', 'u': 'restore_cursor', 'm': 'color', - 'R': 'report_cursor_position'} + 'R': 'report_cursor_position', + 't': 'nfi'} ############################################################################################################ LOOKUP TABLE asc_table="""\ ╟ⁿΘΓΣαστΩδΦ∩ε∞─┼╔µ╞⌠÷≥√∙ ╓▄óúÑ₧ƒ\ @@ -190,6 +199,9 @@ class dr1p4ns1: f.close() ######################################################################################################### FILE OPERATIONS def openansi(self,s): + f=open('log','w') + f.write(f'{s}\n') + f.close() f=open(s,'rb') self.ansifile=f.read().decode('cp437') f.close() @@ -322,161 +334,168 @@ class dr1p4ns1: uniques=[] codes=[] processing='' - for i,_optype in enumerate(self.optype): - if _optype==2: - processing+=self.op[i] - offset+=len(self.op[i]) - elif _optype==3: - count=int(self.op[i].split('[')[1].split('C')[0]) - processing+=' '*count - elif _optype==1: - processing+=self.op[i] - _bseq='\r\n' - _xpos=processing.find(_bseq) - distance=0 - while not processing.find(_bseq) == -1: + try: + for i,_optype in enumerate(self.optype): + if _optype==2: + processing+=self.op[i] + offset+=len(self.op[i]) + elif _optype==3: + count=int(self.op[i].split('[')[1].split('C')[0]) + processing+=' '*count + elif _optype==1: + processing+=self.op[i] + _bseq='\r\n' _xpos=processing.find(_bseq) - if not _xpos == -1: - uniques.append(_bseq) - uniques.append(_xpos) - if len(self.stripcodes(processing[:_xpos])) >= 80: distance=80 - gaps=self.width-len(self.stripcodes(processing)[distance:].split('\r\n')[0]) - processing=processing.replace(_bseq,chr(32)*gaps,1) - if len(processing)-offset > self.width: - trailing_size=0 - while len(processing)-offset > self.width: - deconcatenate=processing[0:self.width+offset] - if deconcatenate.endswith('m'): - if not deconcatenate.rfind('\x1b')==-1: - trailing_size=len(deconcatenate[deconcatenate.rfind('\x1b'):]) - deconcatenate=deconcatenate[:deconcatenate.rfind('\x1b')] - processed.append(deconcatenate) - if len(uniques) < 2: - uniqued.append('') - else: + distance=0 + while not processing.find(_bseq) == -1: + _xpos=processing.find(_bseq) + if not _xpos == -1: + uniques.append(_bseq) + uniques.append(_xpos) + if len(self.stripcodes(processing[:_xpos])) >= 80: distance=80 + gaps=self.width-len(self.stripcodes(processing)[distance:].split('\r\n')[0]) + processing=processing.replace(_bseq,chr(32)*gaps,1) + if len(processing)-offset > self.width: + trailing_size=0 + while len(processing)-offset > self.width: + deconcatenate=processing[0:self.width+offset] + if deconcatenate.endswith('m'): + if not deconcatenate.rfind('\x1b')==-1: + trailing_size=len(deconcatenate[deconcatenate.rfind('\x1b'):]) + deconcatenate=deconcatenate[:deconcatenate.rfind('\x1b')] + processed.append(deconcatenate) + if len(uniques) < 2: + uniqued.append('') + else: + uniqued.append(uniques) uniqued.append(uniques) - uniqued.append(uniques) - uniques=[] - offsets.append(offset) - processing=processing.replace(deconcatenate,'',1) - offset=0+trailing_size - if len(processing) > 0: - gaps=int(80-len(self.stripcodes(processing))) - processing+=chr(32)*gaps - processed.append(processing) - processed_colors=[]; last_colors=''; color_fg=''; color_bg=''; color_set=''; - for y,__ in enumerate(processed): - code_start=0; code_end=0; code_state=False; codes=[]; - for x,_ in enumerate(__): - if not code_state: - if _ =='\x1b': - code_start = x - code_state = True - else: - if _ in self.commands: - if self.commands[_] == 'color': - code_end = x+1 - code_state = False - codes.append(__[code_start:code_end]) - for code in codes: - for _ in code.replace('m','').split('[')[1].split(';'): - if 0 <= int(_) <= 9: - color_set=_ - if 30 <= int(_) <= 39: - color_fg=_ - if 40 <= int(_) <= 49: - color_bg=_ - colors=f"{color_set}" - processed_colors.append(colors) - self.processed = processed - irc_processed=[] - terminal_processed=[] - color_table=[1,5,3,7,2,6,10,15,14,4,9,8,12,13,11,0]; - default_fg_color=7 - default_bg_color=0 - codes=[] - for _ in processed: - line=_ - for r in (('\x16',chr(9644)),('\x15','\u00A7')): - line=line.replace(*r) - _line=line - bold_offset=0 - bold_before=[] - bold_init=False - codes_root_popped=False - fg_color=color_table[default_fg_color] - bg_color=color_table[default_bg_color] - color_set='0' - for _ in [line[x[0]:x[1]+1] for x in zip([x for x in self.findall(line,'\x1b')],[line.find('m',x) for x in self.findall(line,'\x1b')])]: - codes.append(_) - code_values=_.split('[')[1].split(';') - code_replace=_ - newcode='' - for __ in code_values: - __=__.replace('m','') - if 0 <= int(__) <= 9: - color_set=int(__) - if color_set==1: - bold_offset=8 - bold_before=[] - else: - bold_offset=0 - elif 40 <= int(__) <= 49: - if bold_init and bold_offset==0: - bg_color=color_table[default_bg_color] - else: - bg_color=__ - if not bold_offset==0 and not bold_init: - bold_before.append(int(bg_color)) - elif 30 <= int(__) <= 39: - if bold_init and bold_offset==0: - fg_color=color_table[default_fg_color] - else: - fg_color=__ - if not bold_offset==0 and not bold_init: - bold_before.append(int(fg_color)) - if bold_init and bold_offset==0: - bold_init=False - newcode='\x03' - bold_before.sort() - for _ in bold_before: - if 30 <= int(_) <= 39: - newcode += str(color_table[default_fg_color]) - if 40 <= int(_) <= 49: - newcode += "," + str(color_table[default_bg_color]) - elif not bold_offset == 0 and not bold_init: - newcode='\x03' - bold_before.sort() - for _ in bold_before: - if 30 <= int(_) <= 39: - newcode+=str(color_table[int(fg_color)-30+bold_offset]) - if 40 <= int(_) <= 49: - newcode+=","+str(color_table[int(bg_color)-40]) - bold_init=True - elif not bold_offset == 0 and bold_init: - for _ in bold_before: - if len(bold_before)==1: + uniques=[] + offsets.append(offset) + processing=processing.replace(deconcatenate,'',1) + offset=0+trailing_size + if len(processing) > 0: + gaps=int(80-len(self.stripcodes(processing))) + processing+=chr(32)*gaps + processed.append(processing) + processed_colors=[]; last_colors=''; color_fg=''; color_bg=''; color_set=''; + for y,__ in enumerate(processed): + code_start=0; code_end=0; code_state=False; codes=[]; + for x,_ in enumerate(__): + if not code_state: + if _ =='\x1b': + code_start = x + code_state = True + else: + if _ in self.commands: + if self.commands[_] == 'color': + code_end = x+1 + code_state = False + codes.append(__[code_start:code_end]) + for code in codes: + for _ in code.replace('m','').split('[')[1].split(';'): + try: + if 0 <= int(_) <= 9: + color_set=_ if 30 <= int(_) <= 39: - bold_before.append(int(bg_color)) + color_fg=_ + if 40 <= int(_) <= 49: + color_bg=_ + except: + print('error') + pass + colors=f"{color_set}" + processed_colors.append(colors) + self.processed = processed + irc_processed=[] + terminal_processed=[] + color_table=[1,5,3,7,2,6,10,15,14,4,9,8,12,13,11,0]; + default_fg_color=7 + default_bg_color=0 + codes=[] + for _ in processed: + line=_ + for r in (('\x16',chr(9644)),('\x15','\u00A7')): + line=line.replace(*r) + _line=line + bold_offset=0 + bold_before=[] + bold_init=False + codes_root_popped=False + fg_color=color_table[default_fg_color] + bg_color=color_table[default_bg_color] + color_set='0' + for _ in [line[x[0]:x[1]+1] for x in zip([x for x in self.findall(line,'\x1b')],[line.find('m',x) for x in self.findall(line,'\x1b')])]: + codes.append(_) + code_values=_.split('[')[1].split(';') + code_replace=_ + newcode='' + for __ in code_values: + __=__.replace('m','') + if 0 <= int(__) <= 9: + color_set=int(__) + if color_set==1: + bold_offset=8 + bold_before=[] else: + bold_offset=0 + elif 40 <= int(__) <= 49: + if bold_init and bold_offset==0: + bg_color=color_table[default_bg_color] + else: + bg_color=__ + if not bold_offset==0 and not bold_init: + bold_before.append(int(bg_color)) + elif 30 <= int(__) <= 39: + if bold_init and bold_offset==0: + fg_color=color_table[default_fg_color] + else: + fg_color=__ + if not bold_offset==0 and not bold_init: bold_before.append(int(fg_color)) - newcode='\x03' - bold_before.sort() - for _ in bold_before: - if 30 <= int(_) <= 39: - newcode+=str(color_table[int(fg_color)-30+bold_offset]) - if 40 <= int(_) <= 49: - newcode+=","+str(color_table[int(bg_color)-40]) - else: - pass #non-bold-operations - if len(codes) == 1 and not codes_root_popped: - if color_set == 0: - _line=_line.replace(codes[-1],"",1) - codes_root_popped=True - else: - _line=_line.replace(code_replace,newcode,1) - irc_processed.append(_line) - terminal_processed.append(line) + if bold_init and bold_offset==0: + bold_init=False + newcode='\x03' + bold_before.sort() + for _ in bold_before: + if 30 <= int(_) <= 39: + newcode += str(color_table[default_fg_color]) + if 40 <= int(_) <= 49: + newcode += "," + str(color_table[default_bg_color]) + elif not bold_offset == 0 and not bold_init: + newcode='\x03' + bold_before.sort() + for _ in bold_before: + if 30 <= int(_) <= 39: + newcode+=str(color_table[int(fg_color)-30+bold_offset]) + if 40 <= int(_) <= 49: + newcode+=","+str(color_table[int(bg_color)-40]) + bold_init=True + elif not bold_offset == 0 and bold_init: + for _ in bold_before: + if len(bold_before)==1: + if 30 <= int(_) <= 39: + bold_before.append(int(bg_color)) + else: + bold_before.append(int(fg_color)) + newcode='\x03' + bold_before.sort() + for _ in bold_before: + if 30 <= int(_) <= 39: + newcode+=str(color_table[int(fg_color)-30+bold_offset]) + if 40 <= int(_) <= 49: + newcode+=","+str(color_table[int(bg_color)-40]) + else: + pass #non-bold-operations + if len(codes) == 1 and not codes_root_popped: + if color_set == 0: + _line=_line.replace(codes[-1],"",1) + codes_root_popped=True + else: + _line=_line.replace(code_replace,newcode,1) + irc_processed.append(_line) + terminal_processed.append(line) + except Exception as e: + print(f'bp error: {e}') #################################################################################################################### TOOL def getsauce(self): f=open(self.filename,'rb') @@ -486,6 +505,9 @@ class dr1p4ns1: self.sauce_found=True self.width=self.sauce[96] self.height=self.sauce[98] + if self.width==0: + print("ERROR: sauce.width has 0 value, defaulting to 80 width") + self.width=80 offset=len("SAUCE") self.sauce_version=str(int(self.sauce[offset:offset+2].strip())) offset+=2 @@ -604,6 +626,7 @@ class UI: termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_settings) ################################################################################### HUMAN INTERFACE * * * * * * * * * * * def uis_menu(self): + global SHOW_FILENAME index=0 try: print(f'loading: {self.files[index]}') @@ -616,8 +639,8 @@ class UI: try: while True: B='\x1b[1;94m'; C='\x1b[1;95m'; S='\x1b[1;36m'; M='\x1b[1;92m'; E='\x1b[0m'; R='\x1b[31m' - msg=f"{B}[ {C}DR1P {B}] {B}- {B}[ {M}x{B}: {M}exit{B}, {M}c{B}: {M}copy{B}, {M}R{B}: {M}remove{B}, {M}q{B}: {M}pumpqueue{B}, {M}p{B}: {M}pump{B}, " - msg+=f"{M}left{B}/{M}right{B}: {M}browse {B}] {B}- [ {M}d{B}: {M}delay{B} - {M}{dr1p.delay}{B} ]" + msg=f"{B}[ {C}DR1P {B}] {B}- {B}[ {M}x{B}: {M}exit{B}, {M}c{B}: {M}copy{B}, {M}R{B}: {M}remove{B}, {M}f{B}: {M}show_filename{B}:{C}{SHOW_FILENAME}{B}, {M}q{B}: {M}pumpqueue{B}, {M}z{B}/{M}p{B}: {M}auto{B}/{M}pump{B}, " + msg+=f"{M}left{B}/{M}right{B}: {M}browse {B}]\n[ {M}d{B}: {M}delay{B} - {M}{dr1p.delay}{B} ] {B}- " msg+=f"{B}[ {S}pumpqueue{B}: {C}{len(self.QUEUE)} {B}- {S}index{B}: {C}{index+1}{B}/{C}{len(self.files)} {B}- {S}filename{B}: {C}{d.filename} {B}]{E}" if self.REMOVED==True: msg+=f'{R} - FILE REMOVED' print(msg) @@ -680,6 +703,11 @@ class UI: sleep(1) print('\x1bc') decoder.as_terminal() + elif k == 'f': + if SHOW_FILENAME: + SHOW_FILENAME=False + else: + SHOW_FILENAME=True elif k == 'd': while True: print(f'{C}input floodrate delay{B}: {C}',end='') @@ -702,7 +730,39 @@ class UI: sleep(1) print('\x1bc') decoder.as_terminal() + + elif k == 'z': + import random + flag_done=False + if len(self.QUEUE)==0: + self.QUEUE=self.files + print(f'{R} pumpqueue empty: autopumping from directory index') + sleep(1) + else: + print(f'{R} autopumping from pump queue') + + while not flag_done: + if len(self.QUEUE) > 0: + print('\x1bc') + d=dr1p4ns1(ansifile=self.QUEUE[0][0],width=self.QUEUE[-1][1],debug=False) + decoder=ANSIDecoder(self.QUEUE[0][0],d.width) + decoder.as_terminal() + self.QUEUE.reverse() + buffer_filename, buffer_width=self.QUEUE[-1] + self.QUEUE.pop() + self.QUEUE.reverse() + decoder=ANSIDecoder(buffer_filename,buffer_width) + decoder.as_irc() + N=random.randint(5,10) + print(f'{C}SLEEPING {M}{N}{C} SECONDS BEFORE NEXT AUTOPUMP: {self.QUEUE[0][0]}') + sleep(N) + else: + flag_done=True + print(f'{B}NO FILES LEFT IN QUEUE - {R} EXITING') + sleep(1) + break elif k == 'p': + print(f'{C}p.u.m.p.i.n.g ', end = "") PMSG="" try: if FIFO_ENABLED: @@ -767,6 +827,9 @@ class ANSIDecodeError(ValueError): ############################################################################################################################# class ANSIDecoder: ############################################################################################################################# + ################# + ESCAPE_PUMP=False + ################# PALETTES = { 'vga': { False: ['000', 'a00', '0a0', 'a50', '00a', 'a0a', '0aa', 'aaa'], @@ -814,9 +877,13 @@ class ANSIDecoder: self.width = width self.strict = False self.filename=files - stream=open(self.filename,'rt',encoding='cp437') - if stream: - self.play(stream) + print(self.filename) + try: + stream=open(self.filename,'rt',encoding='cp437') + if stream: + self.play(stream) + except: + pass ######################################################################################################################### def write_char(self, char): # Handle an ordinary character @@ -1161,12 +1228,36 @@ class ANSIDecoder: self.output_lines.append(processing) processing='' ######################################################################################################################### + def getkeythreaded(self): + tty.setcbreak(sys.stdin.fileno()) + print('\x1b[31m<<< PRESS ANY KEY TO ABORT PUMP >>>') + b = os.read(sys.stdin.fileno(), 3).decode() + if len(b) == 3: + k = ord(b[2]) + else: + k = ord(b) + self.ESCAPE_PUMP=True + ######################################################################################################################### def as_irc(self): + DID_I_ABORT=False self.output_lines=[] self.as_irc_lines() + x=threading.Thread(target=self.getkeythreaded) + x.start() for _ in self.output_lines: self.fifo(_) sleep(dr1p.delay) + if self.ESCAPE_PUMP: + DID_I_ABORT=True + break + if SHOW_FILENAME: + self.fifo(f"\x035FILENAME\x034: \x035{self.filename.split('/')[-1]} \x034- \x035DR1P4NS1\x034:\x035 {DR1P_VERSION}") + x._stop() + self.ESCAPE_PUMP=False + if DID_I_ABORT: + print(f'\x1b[31m<<< ABORTED PUMP >>>') + self.fifo("\x035<<< ABORTED PUMP >>>") + sleep(3) ################################################################################################### RE-ENCODING ENCODINGS def as_terminal_lines(self): default_fg=7 @@ -1232,7 +1323,13 @@ class ANSIDecoder: processing+=f'\x1b[0;{attr[0]+30};{attr[1]+40}m' processing+=char last_attr=attr - self.output_lines.append(processing + '\x1b[40;37m') + if len(self.buffer[i]) == 0: + self.output_lines.append(f"{'█'*self.width}") + else: + distance=int(self.width)-len(line) + processing+=f"{'█'*distance}" + self.output_lines.append(processing) + # self.output_lines.append(processing + '\x1b[40;37m') processing='' ######################################################################################################################### def as_terminal(self): @@ -1240,6 +1337,7 @@ class ANSIDecoder: self.as_terminal_lines() for _ in self.output_lines: print(_) + ################################################################################################################### ENTRY - 1 if __name__=="__main__": dr1p=D() @@ -1247,4 +1345,4 @@ if __name__=="__main__": dr1p.files = getfiles(sys.argv) ui = UI(dr1p.files) #################################################################################################### ####################### -########################################################################################### dr1p4ns1 version 2.666 ##### EOF \ No newline at end of file +########################################################################################### dr1p4ns1 version 2.667 ##### EOF \ No newline at end of file