2024-02-07 19:55:35 +05:30
#!/usr/bin/python3
2017-09-29 14:32:40 +02:00
# -*- coding: utf-8 -*-
2024-11-05 11:51:34 +01:00
import sys , os , subprocess , shutil , re , platform
2017-09-29 14:32:40 +02:00
import fnmatch
2024-12-11 12:32:24 +01:00
import pexpect
2017-09-29 14:32:40 +02:00
2024-12-11 12:15:58 +01:00
VERBOSE = ' VERBOSE ' in os . environ
CMDSHELL = ' MEGACMDSHELL ' in os . environ
if CMDSHELL :
MEGACMDSHELL = os . environ [ ' MEGACMDSHELL ' ]
2017-09-29 14:32:40 +02:00
2024-12-11 12:15:58 +01:00
if ' MEGA_EMAIL ' in os . environ and ' MEGA_PWD ' in os . environ and ' MEGA_EMAIL_AUX ' in os . environ and ' MEGA_PWD_AUX ' in os . environ :
MEGA_EMAIL = os . environ [ ' MEGA_EMAIL ' ]
MEGA_PWD = os . environ [ ' MEGA_PWD ' ]
MEGA_EMAIL_AUX = os . environ [ ' MEGA_EMAIL_AUX ' ]
MEGA_PWD_AUX = os . environ [ ' MEGA_PWD_AUX ' ]
else :
raise Exception ( ' Environment variables MEGA_EMAIL, MEGA_PWD, MEGA_EMAIL_AUX, MEGA_PWD_AUX are not defined. WARNING: Use a test account for $MEGA_EMAIL ' )
2017-09-29 14:32:40 +02:00
2024-11-05 11:51:34 +01:00
def build_command_name ( command ) :
if platform . system ( ) == ' Windows ' :
2024-11-05 14:46:11 +01:00
return ' MEGAclient.exe ' + command
2024-11-05 11:51:34 +01:00
elif platform . system ( ) == ' Darwin ' :
return ' mega-exec ' + command
else :
return ' mega- ' + command
GET = build_command_name ( ' get ' )
PUT = build_command_name ( ' put ' )
RM = build_command_name ( ' rm ' )
MV = build_command_name ( ' mv ' )
CD = build_command_name ( ' cd ' )
CP = build_command_name ( ' cp ' )
THUMB = build_command_name ( ' thumbnail ' )
LCD = build_command_name ( ' lcd ' )
MKDIR = build_command_name ( ' mkdir ' )
EXPORT = build_command_name ( ' export ' )
SHARE = build_command_name ( ' share ' )
INVITE = build_command_name ( ' invite ' )
FIND = build_command_name ( ' find ' )
WHOAMI = build_command_name ( ' whoami ' )
LOGOUT = build_command_name ( ' logout ' )
LOGIN = build_command_name ( ' login ' )
IPC = build_command_name ( ' ipc ' )
FTP = build_command_name ( ' ftp ' )
IMPORT = build_command_name ( ' import ' )
2017-10-05 12:26:28 +02:00
#execute command
2017-09-29 14:32:40 +02:00
def ec ( what ) :
if VERBOSE :
2024-02-07 19:55:35 +05:30
print ( " Executing " + what )
2017-09-29 14:32:40 +02:00
process = subprocess . Popen ( what , shell = True , stdout = subprocess . PIPE )
stdoutdata , stderrdata = process . communicate ( )
2024-02-07 19:55:35 +05:30
stdoutdata = stdoutdata . replace ( b ' \r \n ' , b ' \n ' )
2017-09-29 14:32:40 +02:00
if VERBOSE :
2024-02-07 19:55:35 +05:30
print ( stdoutdata . strip ( ) )
2017-09-29 14:32:40 +02:00
return stdoutdata , process . returncode
#execute and return only stdout contents
def ex ( what ) :
return ec ( what ) [ 0 ]
#return subprocess.Popen(what, shell=True, stdout=subprocess.PIPE).stdout.read()
#Execute and strip, return only stdout
def es ( what ) :
return ec ( what ) [ 0 ] . strip ( )
#Execute and strip with status code
def esc ( what ) :
ret = ec ( what )
return ret [ 0 ] . strip ( ) , ret [ 1 ]
2024-10-08 00:02:22 +02:00
2017-09-29 14:32:40 +02:00
#exit if failed
def ef ( what ) :
out , code = esc ( what )
if code != 0 :
2024-10-08 00:02:22 +02:00
print ( " FAILED trying " + what , file = sys . stderr )
print ( out , file = sys . stderr )
2017-09-29 14:32:40 +02:00
exit ( code )
2024-10-08 00:02:22 +02:00
return out
2017-09-29 14:32:40 +02:00
2017-10-05 12:26:28 +02:00
def cmdshell_ec ( what ) :
2024-12-11 12:32:24 +01:00
what = re . sub ( ' ^mega- ' , ' ' , what )
2017-10-05 12:26:28 +02:00
if VERBOSE :
2024-12-11 12:32:24 +01:00
print ( f ' Executing in cmdshell: { what } ' )
# We must ensure there are enough columns so long commands don't get truncated
child = pexpect . spawn ( MEGACMDSHELL , encoding = ' utf-8 ' , dimensions = ( 32 , 256 ) , timeout = None )
try :
# Wait for the shell prompt to be loaded
child . expect ( [ r ' \ $ ' , ' > ' ] )
child . sendline ( " lcd " + os . getcwd ( ) )
child . sendline ( what )
# Stop the shell
child . sendcontrol ( ' d ' )
child . expect ( pexpect . EOF )
# The whole output of the shell split by newlines
lines = child . before . replace ( ' \r \n ' , ' \n ' ) . split ( ' \n ' )
# Find the start of our command
start = next ( i for i , s in enumerate ( lines ) if what in s )
# Find the end of our shell by searching for Ctrl+D
end = next ( i for i , s in enumerate ( lines [ start + 1 : ] , start + 1 ) if ' (CTRL+D) ' in s )
# The output of our command is the string in-between the start and end indices
out = ' \n ' . join ( lines [ start + 1 : end ] ) . strip ( )
except pexpect . EOF :
print ( ' Shell session ended ' )
return ' ' , - 1
except pexpect . TIMEOUT :
print ( ' Timed out waiting for output ' )
return ' ' , - 1
finally :
child . close ( )
out = re . sub ( r ' .* \ x1b \ [K ' , ' ' , out ) # erase line controls
out = re . sub ( r ' .* \ r ' , ' ' , out ) # erase non printable stuff
if VERBOSE :
print ( f ' Exit code: { child . exitstatus } ' )
print ( f ' Out: { out } ' )
return out . encode ( ' utf-8 ' ) , child . exitstatus
2017-09-29 14:32:40 +02:00
2017-10-05 12:26:28 +02:00
#execute and return only stdout contents
def cmdshell_ex ( what ) :
return cmdshell_ec ( what ) [ 0 ]
2017-09-29 14:32:40 +02:00
2017-10-05 12:26:28 +02:00
#Execute and strip, return only stdout
def cmdshell_es ( what ) :
return cmdshell_ec ( what ) [ 0 ] . strip ( )
2017-09-29 14:32:40 +02:00
2017-10-05 12:26:28 +02:00
#Execute and strip with status code
def cmdshell_esc ( what ) :
ret = cmdshell_ec ( what )
return ret [ 0 ] . strip ( ) , ret [ 1 ]
2024-10-08 00:02:22 +02:00
2017-10-05 12:26:28 +02:00
#exit if failed
def cmdshell_ef ( what ) :
out , code = cmdshell_ec ( what )
if code != 0 :
2024-10-08 00:02:22 +02:00
print ( " FAILED trying " + str ( what ) , file = sys . stderr )
print ( out , file = sys . stderr )
2017-10-05 13:25:02 +02:00
exit ( code )
2017-10-05 12:26:28 +02:00
return out
2024-10-08 00:02:22 +02:00
2017-10-05 12:26:28 +02:00
def cmd_ec ( what ) :
if CMDSHELL : return cmdshell_ec ( what )
else : return ec ( what )
#execute and return only stdout contents
def cmd_ex ( what ) :
if CMDSHELL : return cmdshell_ex ( what )
else : return ex ( what )
#Execute and strip, return only stdout
def cmd_es ( what ) :
if CMDSHELL : return cmdshell_es ( what )
else : return es ( what )
#Execute and strip with status code
def cmd_esc ( what ) :
if CMDSHELL : return cmdshell_esc ( what )
else : return esc ( what )
#exit if failed
def cmd_ef ( what ) :
if CMDSHELL : return cmdshell_ef ( what )
else : return ef ( what )
2017-09-29 14:32:40 +02:00
def rmfolderifexisting ( what ) :
if os . path . exists ( what ) :
shutil . rmtree ( what )
def rmfileifexisting ( what ) :
if os . path . exists ( what ) :
os . remove ( what )
2024-10-08 00:02:22 +02:00
2017-09-29 14:32:40 +02:00
def rmcontentsifexisting ( what ) :
if os . path . exists ( what ) and os . path . isdir ( what ) :
shutil . rmtree ( what )
os . makedirs ( what )
2024-10-08 00:02:22 +02:00
2017-09-29 14:32:40 +02:00
def copybyfilepattern ( origin , pattern , destiny ) :
for f in fnmatch . filter ( os . listdir ( origin ) , pattern ) :
shutil . copy2 ( origin + ' / ' + f , destiny )
2024-10-08 00:02:22 +02:00
2017-09-29 14:32:40 +02:00
def copyfolder ( origin , destiny ) :
shutil . copytree ( origin , destiny + ' / ' + origin . split ( ' / ' ) [ - 1 ] )
2017-10-03 14:32:22 +02:00
def copybypattern ( origin , pattern , destiny ) :
for f in fnmatch . filter ( os . listdir ( origin ) , pattern ) :
if ( os . path . isdir ( origin + ' / ' + f ) ) :
copyfolder ( origin + ' / ' + f , destiny )
else :
shutil . copy2 ( origin + ' / ' + f , destiny )
2024-10-08 00:02:22 +02:00
2017-09-29 14:32:40 +02:00
def makedir ( what ) :
if ( not os . path . exists ( what ) ) :
os . makedirs ( what )
def osvar ( what ) :
try :
return os . environ [ what ]
except :
return " "
def sort ( what ) :
2024-02-07 19:55:35 +05:30
if isinstance ( what , bytes ) :
return b " \n " . join ( sorted ( what . split ( b " \n " ) ) ) . decode ( )
2017-09-29 14:32:40 +02:00
return " \n " . join ( sorted ( what . split ( " \n " ) ) )
def findR ( where , prefix = " " ) :
toret = " "
#~ print "e:",where
for f in os . listdir ( where ) :
#~ print "f:",where+"/"+f
toret + = prefix + f + " \n "
if ( os . path . isdir ( where + " / " + f ) ) :
#~ print "entering ",prefix+f
toret = toret + findR ( where + " / " + f , prefix + f + " / " )
return toret
def find ( where , prefix = " " ) :
if not os . path . exists ( where ) :
2024-02-07 19:55:35 +05:30
if VERBOSE : print ( " file not found in find: {} , {} " . format ( where , os . getcwd ( ) ) )
2017-09-29 14:32:40 +02:00
return " "
2024-10-08 00:02:22 +02:00
2017-09-29 14:32:40 +02:00
if ( not os . path . isdir ( where ) ) :
2024-10-08 00:02:22 +02:00
return prefix
2017-09-29 14:32:40 +02:00
if ( prefix == " " ) : toret = " . "
else : toret = prefix
2024-10-08 00:02:22 +02:00
2017-09-29 14:32:40 +02:00
if ( prefix == " . " ) :
toret + = " \n " + findR ( where ) . strip ( )
else :
if prefix . endswith ( ' / ' ) :
toret + = " \n " + findR ( where , prefix ) . strip ( )
else :
toret + = " \n " + findR ( where , prefix + " / " ) . strip ( )
return toret . strip ( )
2018-09-05 20:48:36 +02:00
def ls ( where , prefix = " " ) :
if not os . path . exists ( where ) :
2024-02-07 19:55:35 +05:30
if VERBOSE : print ( " file not found in find: {} , {} " . format ( where , os . getcwd ( ) ) )
2018-09-05 20:48:36 +02:00
return " "
2020-02-13 19:00:37 +01:00
toret = " . \n "
2018-09-05 20:48:36 +02:00
for f in os . listdir ( where ) :
toret + = prefix + f + " \n "
return toret
2017-09-29 14:32:40 +02:00
def touch ( what , times = None ) :
with open ( what , ' a ' ) :
os . utime ( what , times )
def out ( what , where ) :
#~ print(what, file=where)
with open ( where , ' w ' ) as f :
f . write ( what )
2024-03-13 17:17:34 +05:30
def clean_root_confirmed_by_user ( ) :
if " YES_I_KNOW_THIS_WILL_CLEAR_MY_MEGA_ACCOUNT " in os . environ :
val = os . environ [ " YES_I_KNOW_THIS_WILL_CLEAR_MY_MEGA_ACCOUNT " ]
return bool ( int ( val ) )
else :
return False