2019-01-09 22:59:03 +00:00
from . import ClientConstants as CC
from . import ClientData
from . import ClientDefaults
from . import ClientGUICommon
from . import ClientGUIDialogs
from . import ClientGUIDialogsQuick
from . import ClientGUIMenus
from . import ClientGUIControls
2019-06-26 21:27:18 +00:00
from . import ClientGUIFunctions
2019-01-09 22:59:03 +00:00
from . import ClientGUIListBoxes
from . import ClientGUIListCtrl
from . import ClientGUIParsing
from . import ClientGUIScrolledPanels
from . import ClientGUIScrolledPanelsEdit
from . import ClientGUISerialisable
from . import ClientGUITopLevelWindows
from . import ClientImporting
from . import ClientNetworking
from . import ClientNetworkingBandwidth
from . import ClientNetworkingContexts
from . import ClientNetworkingDomain
from . import ClientNetworkingLogin
from . import ClientNetworkingJobs
from . import ClientNetworkingSessions
from . import ClientParsing
from . import ClientPaths
from . import ClientSerialisable
from . import ClientThreading
from . import HydrusConstants as HC
from . import HydrusData
from . import HydrusExceptions
from . import HydrusGlobals as HG
from . import HydrusSerialisable
from . import HydrusTags
from . import HydrusText
2018-10-17 21:00:09 +00:00
import itertools
import os
import re
import threading
import traceback
import time
import wx
class EditLoginCredentialsPanel ( ClientGUIScrolledPanels . EditPanel ) :
2018-10-24 21:34:02 +00:00
def __init__ ( self , parent , credential_definitions , credentials ) :
ClientGUIScrolledPanels . EditPanel . __init__ ( self , parent )
#
self . _control_data = [ ]
rows = [ ]
credential_definitions = list ( credential_definitions )
credential_definitions . sort ( key = lambda cd : cd . ShouldHide ( ) )
for credential_definition in credential_definitions :
if credential_definition . ShouldHide ( ) :
style = wx . TE_PASSWORD
else :
style = 0
control = wx . TextCtrl ( self , style = style )
name = credential_definition . GetName ( )
if name in credentials :
control . SetValue ( credentials [ name ] )
control . Bind ( wx . EVT_TEXT , self . EventKey )
control_st = ClientGUICommon . BetterStaticText ( self )
self . _control_data . append ( ( credential_definition , control , control_st ) )
hbox = wx . BoxSizer ( wx . HORIZONTAL )
hbox . Add ( control , CC . FLAGS_EXPAND_BOTH_WAYS )
hbox . Add ( control_st , CC . FLAGS_EXPAND_BOTH_WAYS )
rows . append ( ( credential_definition . GetName ( ) + ' : ' , hbox ) )
gridbox = ClientGUICommon . WrapInGrid ( self , rows )
self . SetSizer ( gridbox )
self . _UpdateSts ( )
def _UpdateSts ( self ) :
for ( credential_definition , control , control_st ) in self . _control_data :
value = control . GetValue ( )
colour = ( 127 , 0 , 0 )
if value == ' ' :
string_match = credential_definition . GetStringMatch ( )
if string_match is None :
st_label = ' '
else :
2019-01-09 22:59:03 +00:00
st_label = string_match . ToString ( )
2018-10-24 21:34:02 +00:00
else :
try :
credential_definition . Test ( value )
2019-01-09 22:59:03 +00:00
st_label = ' looks good \u2713 '
2018-10-24 21:34:02 +00:00
colour = ( 0 , 127 , 0 )
except Exception as e :
2019-01-09 22:59:03 +00:00
st_label = str ( e )
2018-10-24 21:34:02 +00:00
control_st . SetLabelText ( st_label )
control_st . SetForegroundColour ( colour )
2018-11-14 23:10:55 +00:00
def CanOK ( self ) :
2018-10-24 21:34:02 +00:00
2018-11-14 23:10:55 +00:00
veto_errors = [ ]
2018-10-24 21:34:02 +00:00
for ( credential_definition , control , control_st ) in self . _control_data :
name = credential_definition . GetName ( )
value = control . GetValue ( )
if value == ' ' :
2018-11-14 23:10:55 +00:00
veto_errors . append ( ' Value for ' + name + ' is blank! ' )
2018-10-24 21:34:02 +00:00
else :
try :
credential_definition . Test ( value )
except Exception as e :
2019-01-09 22:59:03 +00:00
veto_errors . append ( ' For ' + name + ' : ' + str ( e ) )
2018-11-14 23:10:55 +00:00
if len ( veto_errors ) > 0 :
message = ' These values are invalid--are you sure this is ok? '
message + = os . linesep * 2
message + = os . linesep . join ( veto_errors )
with ClientGUIDialogs . DialogYesNo ( self , message ) as dlg :
if dlg . ShowModal ( ) != wx . ID_YES :
return False
2018-10-24 21:34:02 +00:00
2018-11-14 23:10:55 +00:00
return True
def EventKey ( self , event ) :
self . _UpdateSts ( )
event . Skip ( )
def GetValue ( self ) :
credentials = { }
for ( credential_definition , control , control_st ) in self . _control_data :
name = credential_definition . GetName ( )
value = control . GetValue ( )
2018-10-24 21:34:02 +00:00
credentials [ name ] = value
return credentials
2018-10-17 21:00:09 +00:00
class EditLoginCredentialDefinitionPanel ( ClientGUIScrolledPanels . EditPanel ) :
def __init__ ( self , parent , credential_definition ) :
ClientGUIScrolledPanels . EditPanel . __init__ ( self , parent )
#
self . _name = wx . TextCtrl ( self )
self . _credential_type = ClientGUICommon . BetterChoice ( self )
for credential_type in [ ClientNetworkingLogin . CREDENTIAL_TYPE_TEXT , ClientNetworkingLogin . CREDENTIAL_TYPE_PASS ] :
self . _credential_type . Append ( ClientNetworkingLogin . credential_type_str_lookup [ credential_type ] , credential_type )
string_match = credential_definition . GetStringMatch ( )
self . _string_match = ClientGUIControls . StringMatchButton ( self , string_match )
#
self . _name . SetValue ( credential_definition . GetName ( ) )
self . _credential_type . SelectClientData ( credential_definition . GetType ( ) )
#
rows = [ ]
rows . append ( ( ' name: ' , self . _name ) )
rows . append ( ( ' input type: ' , self . _credential_type ) )
rows . append ( ( ' permitted input: ' , self . _string_match ) )
gridbox = ClientGUICommon . WrapInGrid ( self , rows )
self . SetSizer ( gridbox )
def GetValue ( self ) :
name = self . _name . GetValue ( )
credential_type = self . _credential_type . GetChoice ( )
string_match = self . _string_match . GetValue ( )
credential_definition = ClientNetworkingLogin . LoginCredentialDefinition ( name = name , credential_type = credential_type , string_match = string_match )
return credential_definition
class EditLoginsPanel ( ClientGUIScrolledPanels . EditPanel ) :
2018-10-24 21:34:02 +00:00
def __init__ ( self , parent , engine , login_scripts , domains_to_login_info ) :
ClientGUIScrolledPanels . EditPanel . __init__ ( self , parent )
self . _engine = engine
self . _login_scripts = login_scripts
2018-11-21 22:22:36 +00:00
self . _domains_to_login_after_ok = [ ]
2019-06-26 21:27:18 +00:00
self . _domains_and_login_info_panel = ClientGUIListCtrl . BetterListCtrlPanel ( self )
2018-10-24 21:34:02 +00:00
2018-11-14 23:10:55 +00:00
columns = [ ( ' domain ' , 20 ) , ( ' login script ' , - 1 ) , ( ' access given ' , 36 ) , ( ' active? ' , 8 ) , ( ' logged in now? ' , 28 ) , ( ' validity ' , 28 ) , ( ' recent error/delay? ' , 21 ) ]
2018-10-24 21:34:02 +00:00
2019-06-26 21:27:18 +00:00
self . _domains_and_login_info = ClientGUIListCtrl . BetterListCtrl ( self . _domains_and_login_info_panel , ' domains_to_login_info ' , 8 , 36 , columns , self . _ConvertDomainAndLoginInfoListCtrlTuples , use_simple_delete = True , activation_callback = self . _EditCredentials )
2018-10-24 21:34:02 +00:00
2019-06-26 21:27:18 +00:00
self . _domains_and_login_info_panel . SetListCtrl ( self . _domains_and_login_info )
2018-10-24 21:34:02 +00:00
2019-06-26 21:27:18 +00:00
self . _domains_and_login_info_panel . AddButton ( ' add ' , self . _Add )
self . _domains_and_login_info_panel . AddDeleteButton ( )
self . _domains_and_login_info_panel . AddSeparator ( )
self . _domains_and_login_info_panel . AddButton ( ' edit credentials ' , self . _EditCredentials , enabled_check_func = self . _CanEditCreds )
self . _domains_and_login_info_panel . AddButton ( ' change login script ' , self . _EditLoginScript , enabled_only_on_selection = True )
self . _domains_and_login_info_panel . AddButton ( ' flip active ' , self . _FlipActive , enabled_only_on_selection = True )
self . _domains_and_login_info_panel . AddSeparator ( )
self . _domains_and_login_info_panel . AddButton ( ' scrub invalidity ' , self . _ScrubInvalidity , enabled_check_func = self . _CanScrubInvalidity )
self . _domains_and_login_info_panel . AddButton ( ' scrub delays ' , self . _ScrubDelays , enabled_check_func = self . _CanScrubDelays )
self . _domains_and_login_info_panel . NewButtonRow ( )
self . _domains_and_login_info_panel . AddButton ( ' do login now ' , self . _DoLogin , enabled_check_func = self . _CanDoLogin )
self . _domains_and_login_info_panel . AddButton ( ' reset login (delete cookies) ' , self . _ClearSessions , enabled_only_on_selection = True )
2018-10-24 21:34:02 +00:00
#
listctrl_data = [ ]
2019-01-09 22:59:03 +00:00
for ( login_domain , ( login_script_key_and_name , credentials , login_access_type , login_access_text , active , validity , validity_error_text , no_work_until , no_work_until_reason ) ) in list ( domains_to_login_info . items ( ) ) :
2018-10-24 21:34:02 +00:00
credentials_tuple = tuple ( credentials . items ( ) )
domain_and_login_info = ( login_domain , login_script_key_and_name , credentials_tuple , login_access_type , login_access_text , active , validity , validity_error_text , no_work_until , no_work_until_reason )
listctrl_data . append ( domain_and_login_info )
self . _domains_and_login_info . AddDatas ( listctrl_data )
self . _domains_and_login_info . Sort ( 0 )
#
vbox = wx . BoxSizer ( wx . VERTICAL )
warning = ' WARNING: Your credentials are stored in plaintext! For this and other reasons, I recommend you use throwaway accounts with hydrus! '
warning_st = ClientGUICommon . BetterStaticText ( self , warning )
warning_st . SetForegroundColour ( ( 128 , 0 , 0 ) )
vbox . Add ( warning_st , CC . FLAGS_CENTER )
2019-06-26 21:27:18 +00:00
vbox . Add ( self . _domains_and_login_info_panel , CC . FLAGS_EXPAND_BOTH_WAYS )
2018-10-24 21:34:02 +00:00
self . SetSizer ( vbox )
def _Add ( self ) :
if len ( self . _login_scripts ) == 0 :
wx . MessageBox ( ' You have no login scripts, so you cannot add a new login! ' )
return
choice_tuples = [ ( login_script . GetName ( ) , login_script ) for login_script in self . _login_scripts ]
2018-11-14 23:10:55 +00:00
try :
2018-10-24 21:34:02 +00:00
2018-11-14 23:10:55 +00:00
login_script = ClientGUIDialogsQuick . SelectFromList ( self , ' select the login script to use ' , choice_tuples )
except HydrusExceptions . CancelledException :
return
2018-10-24 21:34:02 +00:00
example_domains = set ( login_script . GetExampleDomains ( ) )
domains_in_use = { login_domain for ( login_domain , login_script_key_and_name , credentials_tuple , login_access_type , login_access_text , active , validity , validity_error_text , no_work_until , no_work_until_reason ) in self . _domains_and_login_info . GetData ( ) }
available_examples = list ( example_domains . difference ( domains_in_use ) )
available_examples . sort ( )
if len ( available_examples ) > 0 :
choice_tuples = [ ( login_domain , login_domain ) for login_domain in available_examples ]
choice_tuples . append ( ( ' use other domain ' , None ) )
2018-11-14 23:10:55 +00:00
try :
2018-10-24 21:34:02 +00:00
2018-11-14 23:10:55 +00:00
login_domain = ClientGUIDialogsQuick . SelectFromList ( self , ' select the domain to use ' , choice_tuples , sort_tuples = False )
except HydrusExceptions . CancelledException :
return
if login_domain is not None :
( login_access_type , login_access_text ) = login_script . GetExampleDomainInfo ( login_domain )
2018-10-24 21:34:02 +00:00
else :
login_domain = None
if login_domain is None :
with ClientGUIDialogs . DialogTextEntry ( self , ' enter the domain ' , default = ' example.com ' , allow_blank = False ) as dlg :
if dlg . ShowModal ( ) == wx . ID_OK :
login_domain = dlg . GetValue ( )
if login_domain in domains_in_use :
wx . MessageBox ( ' That domain is already in use! ' )
return
a_types = [ ClientNetworkingLogin . LOGIN_ACCESS_TYPE_EVERYTHING , ClientNetworkingLogin . LOGIN_ACCESS_TYPE_NSFW , ClientNetworkingLogin . LOGIN_ACCESS_TYPE_SPECIAL , ClientNetworkingLogin . LOGIN_ACCESS_TYPE_USER_PREFS_ONLY ]
choice_tuples = [ ( ClientNetworkingLogin . login_access_type_str_lookup [ a_type ] , a_type ) for a_type in a_types ]
2018-11-14 23:10:55 +00:00
try :
2018-10-24 21:34:02 +00:00
2018-11-14 23:10:55 +00:00
login_access_type = ClientGUIDialogsQuick . SelectFromList ( self , ' select what type of access the login gives to this domain ' , choice_tuples , sort_tuples = False )
except HydrusExceptions . CancelledException :
return
2018-10-24 21:34:02 +00:00
login_access_text = ClientNetworkingLogin . login_access_type_default_description_lookup [ login_access_type ]
with ClientGUIDialogs . DialogTextEntry ( self , ' edit the access description, if needed ' , default = login_access_text , allow_blank = False ) as dlg :
if dlg . ShowModal ( ) == wx . ID_OK :
login_access_text = dlg . GetValue ( )
else :
return
else :
return
credential_definitions = login_script . GetCredentialDefinitions ( )
credentials = { }
if len ( credential_definitions ) > 0 :
with ClientGUITopLevelWindows . DialogEdit ( self , ' edit login ' ) as dlg :
panel = EditLoginCredentialsPanel ( dlg , credential_definitions , credentials )
dlg . SetPanel ( panel )
if dlg . ShowModal ( ) == wx . ID_OK :
credentials = panel . GetValue ( )
else :
return
2018-11-14 23:10:55 +00:00
try :
login_script . CheckCanLogin ( credentials )
validity = ClientNetworkingLogin . VALIDITY_UNTESTED
validity_error_text = ' '
# hacky: if there are creds, is at least one not empty string?
2019-01-09 22:59:03 +00:00
creds_are_good = len ( credentials ) == 0 or True in ( value != ' ' for value in list ( credentials . values ( ) ) )
2018-11-14 23:10:55 +00:00
except HydrusExceptions . ValidationException as e :
validity = ClientNetworkingLogin . VALIDITY_INVALID
2019-01-09 22:59:03 +00:00
validity_error_text = str ( e )
2018-11-14 23:10:55 +00:00
creds_are_good = False
2018-10-24 21:34:02 +00:00
2018-11-14 23:10:55 +00:00
if creds_are_good :
2018-10-24 21:34:02 +00:00
2018-11-14 23:10:55 +00:00
message = ' Activate this login script for this domain? '
with ClientGUIDialogs . DialogYesNo ( self , message , title = message ) as dlg :
2018-10-24 21:34:02 +00:00
2018-11-14 23:10:55 +00:00
if dlg . ShowModal ( ) == wx . ID_YES :
active = True
else :
active = False
2018-10-24 21:34:02 +00:00
2018-11-14 23:10:55 +00:00
else :
active = False
2018-10-24 21:34:02 +00:00
login_script_key_and_name = login_script . GetLoginScriptKeyAndName ( )
credentials_tuple = tuple ( credentials . items ( ) )
no_work_until = 0
no_work_until_reason = ' '
domain_and_login_info = ( login_domain , login_script_key_and_name , credentials_tuple , login_access_type , login_access_text , active , validity , validity_error_text , no_work_until , no_work_until_reason )
self . _domains_and_login_info . AddDatas ( ( domain_and_login_info , ) )
self . _domains_and_login_info . Sort ( )
2018-11-21 22:22:36 +00:00
def _CanDoLogin ( self ) :
domain_and_login_infos = self . _domains_and_login_info . GetData ( only_selected = True )
for domain_and_login_info in domain_and_login_infos :
( login_domain , login_script_key_and_name , credentials_tuple , login_access_type , login_access_text , active , validity , validity_error_text , no_work_until , no_work_until_reason ) = domain_and_login_info
if not active :
continue
if validity == ClientNetworkingLogin . VALIDITY_INVALID :
continue
try :
login_script = self . _GetLoginScript ( login_script_key_and_name )
network_context = ClientNetworkingContexts . NetworkContext ( context_type = CC . NETWORK_CONTEXT_DOMAIN , context_data = login_domain )
logged_in = login_script . IsLoggedIn ( self . _engine , network_context )
if logged_in :
continue
except HydrusExceptions . DataMissing :
continue
return True
return False
2018-10-24 21:34:02 +00:00
def _CanEditCreds ( self ) :
domain_and_login_infos = self . _domains_and_login_info . GetData ( only_selected = True )
for domain_and_login_info in domain_and_login_infos :
( login_domain , login_script_key_and_name , credentials_tuple , login_access_type , login_access_text , active , validity , validity_error_text , no_work_until , no_work_until_reason ) = domain_and_login_info
try :
login_script = self . _GetLoginScript ( login_script_key_and_name )
if len ( login_script . GetCredentialDefinitions ( ) ) > 0 :
return True
except HydrusExceptions . DataMissing :
continue
return False
2018-11-14 23:10:55 +00:00
def _CanScrubDelays ( self ) :
domain_and_login_infos = self . _domains_and_login_info . GetData ( only_selected = True )
for domain_and_login_info in domain_and_login_infos :
( login_domain , login_script_key_and_name , credentials_tuple , login_access_type , login_access_text , active , validity , validity_error_text , no_work_until , no_work_until_reason ) = domain_and_login_info
if not HydrusData . TimeHasPassed ( no_work_until ) or no_work_until_reason != ' ' :
return True
return False
def _CanScrubInvalidity ( self ) :
domain_and_login_infos = self . _domains_and_login_info . GetData ( only_selected = True )
for domain_and_login_info in domain_and_login_infos :
( login_domain , login_script_key_and_name , credentials_tuple , login_access_type , login_access_text , active , validity , validity_error_text , no_work_until , no_work_until_reason ) = domain_and_login_info
if validity == ClientNetworkingLogin . VALIDITY_INVALID :
return True
return False
2018-10-24 21:34:02 +00:00
def _ClearSessions ( self ) :
domain_and_login_infos = self . _domains_and_login_info . GetData ( only_selected = True )
if len ( domain_and_login_infos ) > 0 :
message = ' Are you sure you want to clear these domains \' sessions? This will delete all their existing cookies and cannot be undone. '
with ClientGUIDialogs . DialogYesNo ( self , message ) as dlg :
if dlg . ShowModal ( ) != wx . ID_YES :
return
for domain_and_login_info in domain_and_login_infos :
( login_domain , login_script_key_and_name , credentials_tuple , login_access_type , login_access_text , active , validity , validity_error_text , no_work_until , no_work_until_reason ) = domain_and_login_info
network_context = ClientNetworkingContexts . NetworkContext ( context_type = CC . NETWORK_CONTEXT_DOMAIN , context_data = login_domain )
self . _engine . session_manager . ClearSession ( network_context )
self . _domains_and_login_info . UpdateDatas ( )
2019-06-26 21:27:18 +00:00
self . _domains_and_login_info_panel . UpdateButtons ( )
2018-10-24 21:34:02 +00:00
def _ConvertDomainAndLoginInfoListCtrlTuples ( self , domain_and_login_info ) :
( login_domain , login_script_key_and_name , credentials_tuple , login_access_type , login_access_text , active , validity , validity_error_text , no_work_until , no_work_until_reason ) = domain_and_login_info
2018-11-14 23:10:55 +00:00
login_expiry = None
2018-10-24 21:34:02 +00:00
try :
login_script = self . _GetLoginScript ( login_script_key_and_name )
sort_login_script = login_script . GetName ( )
2018-11-07 23:09:40 +00:00
network_context = ClientNetworkingContexts . NetworkContext ( context_type = CC . NETWORK_CONTEXT_DOMAIN , context_data = login_domain )
logged_in = login_script . IsLoggedIn ( self . _engine , network_context )
2018-11-14 23:10:55 +00:00
if logged_in :
login_expiry = login_script . GetLoginExpiry ( self . _engine , network_context )
2018-10-24 21:34:02 +00:00
except HydrusExceptions . DataMissing :
sort_login_script = ' login script not found '
2018-11-07 23:09:40 +00:00
logged_in = False
2018-10-24 21:34:02 +00:00
access = ClientNetworkingLogin . login_access_type_str_lookup [ login_access_type ] + ' - ' + login_access_text
if active :
sort_active = ' yes '
else :
sort_active = ' no '
sort_validity = ClientNetworkingLogin . validity_str_lookup [ validity ]
if len ( validity_error_text ) > 0 :
sort_validity + = ' - ' + validity_error_text
2018-11-14 23:10:55 +00:00
sort_logged_in = ( logged_in , login_expiry )
2018-10-24 21:34:02 +00:00
if HydrusData . TimeHasPassed ( no_work_until ) :
pretty_no_work_until = ' '
else :
pretty_no_work_until = HydrusData . ConvertTimestampToPrettyExpires ( no_work_until ) + ' - ' + no_work_until_reason
pretty_login_domain = login_domain
pretty_login_script = sort_login_script
pretty_access = access
pretty_active = sort_active
2018-12-12 22:15:46 +00:00
if active :
pretty_validity = sort_validity
else :
pretty_validity = ' '
2018-11-14 23:10:55 +00:00
if logged_in :
if login_expiry is None :
pretty_login_expiry = ' session '
else :
pretty_login_expiry = HydrusData . ConvertTimestampToPrettyExpires ( login_expiry )
pretty_logged_in = ' yes - ' + pretty_login_expiry
else :
pretty_logged_in = ' no '
2018-10-24 21:34:02 +00:00
display_tuple = ( pretty_login_domain , pretty_login_script , pretty_access , pretty_active , pretty_logged_in , pretty_validity , pretty_no_work_until )
sort_tuple = ( login_domain , sort_login_script , access , sort_active , sort_logged_in , sort_validity , no_work_until )
return ( display_tuple , sort_tuple )
2018-11-21 22:22:36 +00:00
def _DoLogin ( self ) :
domains_to_login = [ ]
domain_and_login_infos = self . _domains_and_login_info . GetData ( only_selected = True )
for domain_and_login_info in domain_and_login_infos :
( login_domain , login_script_key_and_name , credentials_tuple , login_access_type , login_access_text , active , validity , validity_error_text , no_work_until , no_work_until_reason ) = domain_and_login_info
if not active :
continue
if validity == ClientNetworkingLogin . VALIDITY_INVALID :
continue
try :
login_script = self . _GetLoginScript ( login_script_key_and_name )
network_context = ClientNetworkingContexts . NetworkContext ( context_type = CC . NETWORK_CONTEXT_DOMAIN , context_data = login_domain )
logged_in = login_script . IsLoggedIn ( self . _engine , network_context )
if logged_in :
continue
except HydrusExceptions . DataMissing :
continue
domains_to_login . append ( login_domain )
if len ( domains_to_login ) == 0 :
wx . MessageBox ( ' Unfortunately, none of the selected domains appear able to log in. Do you need to activate or scrub something somewhere? ' )
else :
domains_to_login . sort ( )
message = ' It looks like the following domains can log in: '
message + = os . linesep * 2
message + = os . linesep . join ( domains_to_login )
message + = os . linesep * 2
message + = ' The dialog will ok and the login attempts will start. Is this ok? '
with ClientGUIDialogs . DialogYesNo ( self , message ) as dlg :
if dlg . ShowModal ( ) != wx . ID_YES :
return
self . _domains_to_login_after_ok = domains_to_login
self . GetParent ( ) . DoOK ( )
2018-10-24 21:34:02 +00:00
def _EditCredentials ( self ) :
domain_and_login_infos = self . _domains_and_login_info . GetData ( only_selected = True )
for domain_and_login_info in domain_and_login_infos :
( login_domain , login_script_key_and_name , credentials_tuple , login_access_type , login_access_text , active , validity , validity_error_text , no_work_until , no_work_until_reason ) = domain_and_login_info
try :
login_script = self . _GetLoginScript ( login_script_key_and_name )
except HydrusExceptions . DataMissing :
wx . MessageBox ( ' Could not find a login script for " ' + login_domain + ' " ! Please re-add the login script in the other dialog or update the entry here to a new one! ' )
return
credential_definitions = login_script . GetCredentialDefinitions ( )
if len ( credential_definitions ) > 0 :
with ClientGUITopLevelWindows . DialogEdit ( self , ' edit login ' ) as dlg :
credentials = dict ( credentials_tuple )
panel = EditLoginCredentialsPanel ( dlg , credential_definitions , credentials )
dlg . SetPanel ( panel )
if dlg . ShowModal ( ) == wx . ID_OK :
credentials = panel . GetValue ( )
else :
return
else :
continue
2018-11-14 23:10:55 +00:00
try :
login_script . CheckCanLogin ( credentials )
validity = ClientNetworkingLogin . VALIDITY_UNTESTED
validity_error_text = ' '
# hacky: if there are creds, is at least one not empty string?
2019-01-09 22:59:03 +00:00
creds_are_good = len ( credentials ) == 0 or True in ( value != ' ' for value in list ( credentials . values ( ) ) )
2018-11-14 23:10:55 +00:00
except HydrusExceptions . ValidationException as e :
validity = ClientNetworkingLogin . VALIDITY_INVALID
2019-01-09 22:59:03 +00:00
validity_error_text = str ( e )
2018-11-14 23:10:55 +00:00
creds_are_good = False
2018-10-24 21:34:02 +00:00
credentials_tuple = tuple ( credentials . items ( ) )
2018-11-14 23:10:55 +00:00
if creds_are_good :
2018-10-24 21:34:02 +00:00
2018-11-14 23:10:55 +00:00
if not active :
message = ' Activate this login script for this domain? '
2018-10-24 21:34:02 +00:00
2018-11-14 23:10:55 +00:00
with ClientGUIDialogs . DialogYesNo ( self , message , title = message ) as dlg :
2018-10-24 21:34:02 +00:00
2018-11-14 23:10:55 +00:00
if dlg . ShowModal ( ) == wx . ID_YES :
active = True
2018-10-24 21:34:02 +00:00
2018-11-14 23:10:55 +00:00
else :
active = False
2018-10-24 21:34:02 +00:00
no_work_until = 0
no_work_until_reason = ' '
edited_domain_and_login_info = ( login_domain , login_script_key_and_name , credentials_tuple , login_access_type , login_access_text , active , validity , validity_error_text , no_work_until , no_work_until_reason )
self . _domains_and_login_info . DeleteDatas ( ( domain_and_login_info , ) )
self . _domains_and_login_info . AddDatas ( ( edited_domain_and_login_info , ) )
self . _domains_and_login_info . Sort ( )
def _EditLoginScript ( self ) :
domain_and_login_infos = self . _domains_and_login_info . GetData ( only_selected = True )
for domain_and_login_info in domain_and_login_infos :
( login_domain , login_script_key_and_name , credentials_tuple , login_access_type , login_access_text , active , validity , validity_error_text , no_work_until , no_work_until_reason ) = domain_and_login_info
try :
2018-11-21 22:22:36 +00:00
current_login_script = self . _GetLoginScript ( login_script_key_and_name )
2018-10-24 21:34:02 +00:00
except HydrusExceptions . DataMissing :
2018-11-21 22:22:36 +00:00
current_login_script = None
potential_login_scripts = list ( self . _login_scripts )
potential_login_scripts . sort ( key = lambda ls : ls . GetName ( ) )
matching_potential_login_scripts = [ login_script for login_script in potential_login_scripts if login_domain in login_script . GetExampleDomains ( ) ]
unmatching_potential_login_scripts = [ login_script for login_script in potential_login_scripts if login_domain not in login_script . GetExampleDomains ( ) ]
choice_tuples = [ ( login_script . GetName ( ) , login_script ) for login_script in matching_potential_login_scripts ]
if len ( matching_potential_login_scripts ) > 0 and len ( unmatching_potential_login_scripts ) > 0 :
choice_tuples . append ( ( ' ------ ' , None ) )
2018-10-24 21:34:02 +00:00
2018-11-21 22:22:36 +00:00
choice_tuples . extend ( [ ( login_script . GetName ( ) , login_script ) for login_script in unmatching_potential_login_scripts ] )
2018-10-24 21:34:02 +00:00
2018-11-14 23:10:55 +00:00
try :
2018-10-24 21:34:02 +00:00
2018-11-21 22:22:36 +00:00
login_script = ClientGUIDialogsQuick . SelectFromList ( self , ' select the login script to use ' , choice_tuples , value_to_select = current_login_script , sort_tuples = False )
2018-10-24 21:34:02 +00:00
2018-11-14 23:10:55 +00:00
except HydrusExceptions . CancelledException :
break
2018-11-21 22:22:36 +00:00
if login_script is None :
break
if login_script == current_login_script :
break
2018-11-14 23:10:55 +00:00
login_script_key_and_name = login_script . GetLoginScriptKeyAndName ( )
2018-10-24 21:34:02 +00:00
try :
( login_access_type , login_access_text ) = login_script . GetExampleDomainInfo ( login_domain )
except HydrusExceptions . DataMissing :
a_types = [ ClientNetworkingLogin . LOGIN_ACCESS_TYPE_EVERYTHING , ClientNetworkingLogin . LOGIN_ACCESS_TYPE_NSFW , ClientNetworkingLogin . LOGIN_ACCESS_TYPE_SPECIAL , ClientNetworkingLogin . LOGIN_ACCESS_TYPE_USER_PREFS_ONLY ]
choice_tuples = [ ( ClientNetworkingLogin . login_access_type_str_lookup [ a_type ] , a_type ) for a_type in a_types ]
2018-11-14 23:10:55 +00:00
try :
2018-10-24 21:34:02 +00:00
2018-11-14 23:10:55 +00:00
login_access_type = ClientGUIDialogsQuick . SelectFromList ( self , ' select what type of access the login gives to this domain ' , choice_tuples , sort_tuples = False )
except HydrusExceptions . CancelledException :
break
2018-10-24 21:34:02 +00:00
login_access_text = ClientNetworkingLogin . login_access_type_default_description_lookup [ login_access_type ]
with ClientGUIDialogs . DialogTextEntry ( self , ' edit the access description, if needed ' , default = login_access_text , allow_blank = False ) as dlg :
if dlg . ShowModal ( ) == wx . ID_OK :
login_access_text = dlg . GetValue ( )
else :
2018-11-14 23:10:55 +00:00
break
2018-10-24 21:34:02 +00:00
2018-11-14 23:10:55 +00:00
credentials = dict ( credentials_tuple )
try :
login_script . CheckCanLogin ( credentials )
validity = ClientNetworkingLogin . VALIDITY_UNTESTED
validity_error_text = ' '
creds_are_good = True
except HydrusExceptions . ValidationException as e :
validity = ClientNetworkingLogin . VALIDITY_INVALID
2019-01-09 22:59:03 +00:00
validity_error_text = str ( e )
2018-11-14 23:10:55 +00:00
creds_are_good = False
if not creds_are_good :
active = False
2018-10-24 21:34:02 +00:00
no_work_until = 0
no_work_until_reason = ' '
edited_domain_and_login_info = ( login_domain , login_script_key_and_name , credentials_tuple , login_access_type , login_access_text , active , validity , validity_error_text , no_work_until , no_work_until_reason )
self . _domains_and_login_info . DeleteDatas ( ( domain_and_login_info , ) )
self . _domains_and_login_info . AddDatas ( ( edited_domain_and_login_info , ) )
self . _domains_and_login_info . Sort ( )
def _FlipActive ( self ) :
domain_and_login_infos = self . _domains_and_login_info . GetData ( only_selected = True )
for domain_and_login_info in domain_and_login_infos :
( login_domain , login_script_key_and_name , credentials_tuple , login_access_type , login_access_text , active , validity , validity_error_text , no_work_until , no_work_until_reason ) = domain_and_login_info
active = not active
flipped_domain_and_login_info = ( login_domain , login_script_key_and_name , credentials_tuple , login_access_type , login_access_text , active , validity , validity_error_text , no_work_until , no_work_until_reason )
self . _domains_and_login_info . DeleteDatas ( ( domain_and_login_info , ) )
self . _domains_and_login_info . AddDatas ( ( flipped_domain_and_login_info , ) )
self . _domains_and_login_info . Sort ( )
def _GetLoginScript ( self , login_script_key_and_name ) :
( login_script_key , login_script_name ) = login_script_key_and_name
for login_script in self . _login_scripts :
if login_script . GetLoginScriptKey ( ) == login_script_key :
return login_script
for login_script in self . _login_scripts :
if login_script . GetName ( ) == login_script_name :
return login_script
raise HydrusExceptions . DataMissing ( ' No login script found! ' )
def _ScrubDelays ( self ) :
domain_and_login_infos = self . _domains_and_login_info . GetData ( only_selected = True )
for domain_and_login_info in domain_and_login_infos :
( login_domain , login_script_key_and_name , credentials_tuple , login_access_type , login_access_text , active , validity , validity_error_text , no_work_until , no_work_until_reason ) = domain_and_login_info
no_work_until = 0
no_work_until_reason = ' '
scrubbed_domain_and_login_info = ( login_domain , login_script_key_and_name , credentials_tuple , login_access_type , login_access_text , active , validity , validity_error_text , no_work_until , no_work_until_reason )
self . _domains_and_login_info . DeleteDatas ( ( domain_and_login_info , ) )
self . _domains_and_login_info . AddDatas ( ( scrubbed_domain_and_login_info , ) )
self . _domains_and_login_info . Sort ( )
2018-11-14 23:10:55 +00:00
def _ScrubInvalidity ( self ) :
domain_and_login_infos = self . _domains_and_login_info . GetData ( only_selected = True )
for domain_and_login_info in domain_and_login_infos :
( login_domain , login_script_key_and_name , credentials_tuple , login_access_type , login_access_text , active , validity , validity_error_text , no_work_until , no_work_until_reason ) = domain_and_login_info
if validity != ClientNetworkingLogin . VALIDITY_INVALID :
continue
try :
try :
login_script = self . _GetLoginScript ( login_script_key_and_name )
except HydrusExceptions . DataMissing :
continue
credentials = dict ( credentials_tuple )
login_script . CheckCanLogin ( credentials )
validity = ClientNetworkingLogin . VALIDITY_UNTESTED
validity_error_text = ' '
except HydrusExceptions . ValidationException as e :
validity = ClientNetworkingLogin . VALIDITY_INVALID
2019-01-09 22:59:03 +00:00
validity_error_text = str ( e )
2018-11-14 23:10:55 +00:00
scrubbed_domain_and_login_info = ( login_domain , login_script_key_and_name , credentials_tuple , login_access_type , login_access_text , active , validity , validity_error_text , no_work_until , no_work_until_reason )
self . _domains_and_login_info . DeleteDatas ( ( domain_and_login_info , ) )
self . _domains_and_login_info . AddDatas ( ( scrubbed_domain_and_login_info , ) )
self . _domains_and_login_info . Sort ( )
2018-11-21 22:22:36 +00:00
def GetDomainsToLoginAfterOK ( self ) :
return self . _domains_to_login_after_ok
2018-10-24 21:34:02 +00:00
def GetValue ( self ) :
domains_to_login_info = dict ( )
for ( login_domain , login_script_key_and_name , credentials_tuple , login_access_type , login_access_text , active , validity , validity_error_text , no_work_until , no_work_until_reason ) in self . _domains_and_login_info . GetData ( ) :
credentials = dict ( credentials_tuple )
domains_to_login_info [ login_domain ] = ( login_script_key_and_name , credentials , login_access_type , login_access_text , active , validity , validity_error_text , no_work_until , no_work_until_reason )
return domains_to_login_info
2018-10-17 21:00:09 +00:00
2018-10-31 21:41:14 +00:00
def GenerateTestNetworkJobPresentationContextFactory ( window , network_job_control ) :
def network_job_presentation_context_factory ( network_job ) :
def wx_set_it ( nj ) :
if not window :
return
network_job_control . SetNetworkJob ( nj )
def enter_call ( ) :
wx . CallAfter ( wx_set_it , network_job )
def exit_call ( ) :
wx . CallAfter ( wx_set_it , None )
return ClientImporting . NetworkJobPresentationContext ( enter_call , exit_call )
return network_job_presentation_context_factory
class ReviewTestResultPanel ( ClientGUIScrolledPanels . ReviewPanel ) :
def __init__ ( self , parent , test_result ) :
ClientGUIScrolledPanels . ReviewPanel . __init__ ( self , parent )
( name , url , body , self . _downloaded_data , new_temp_strings , new_cookie_strings , result ) = test_result
self . _name = ClientGUICommon . BetterStaticText ( self , label = name )
self . _url = wx . TextCtrl ( self )
self . _body = wx . TextCtrl ( self , style = wx . TE_MULTILINE )
self . _body . SetEditable ( False )
2019-06-26 21:27:18 +00:00
min_size = ClientGUIFunctions . ConvertTextToPixels ( self . _body , ( 64 , 3 ) )
2018-10-31 21:41:14 +00:00
self . _body . SetMinClientSize ( min_size )
self . _data_preview = wx . TextCtrl ( self , style = wx . TE_MULTILINE )
self . _data_preview . SetEditable ( False )
2019-06-26 21:27:18 +00:00
min_size = ClientGUIFunctions . ConvertTextToPixels ( self . _data_preview , ( 64 , 8 ) )
2018-10-31 21:41:14 +00:00
self . _data_preview . SetMinClientSize ( min_size )
self . _data_copy_button = ClientGUICommon . BetterBitmapButton ( self , CC . GlobalBMPs . copy , self . _CopyData )
self . _data_copy_button . SetToolTip ( ' Copy the current example data to the clipboard. ' )
self . _temp_variables = wx . TextCtrl ( self , style = wx . TE_MULTILINE )
self . _temp_variables . SetEditable ( False )
2019-06-26 21:27:18 +00:00
min_size = ClientGUIFunctions . ConvertTextToPixels ( self . _temp_variables , ( 64 , 6 ) )
2018-10-31 21:41:14 +00:00
self . _temp_variables . SetMinClientSize ( min_size )
self . _cookies = wx . TextCtrl ( self , style = wx . TE_MULTILINE )
self . _cookies . SetEditable ( False )
2019-06-26 21:27:18 +00:00
min_size = ClientGUIFunctions . ConvertTextToPixels ( self . _cookies , ( 64 , 6 ) )
2018-10-31 21:41:14 +00:00
self . _cookies . SetMinClientSize ( min_size )
self . _result = ClientGUICommon . BetterStaticText ( self , label = result )
#
self . _url . SetValue ( url )
if body is not None :
try :
self . _body . SetValue ( body )
except :
2019-01-09 22:59:03 +00:00
self . _body . SetValue ( str ( body ) )
2018-10-31 21:41:14 +00:00
2019-01-09 22:59:03 +00:00
self . _data_preview . SetValue ( str ( self . _downloaded_data [ : 1024 ] ) )
2018-10-31 21:41:14 +00:00
self . _temp_variables . SetValue ( os . linesep . join ( new_temp_strings ) )
self . _cookies . SetValue ( os . linesep . join ( new_cookie_strings ) )
#
rows = [ ]
rows . append ( ( ' name: ' , self . _name ) )
rows . append ( ( ' url: ' , self . _url ) )
rows . append ( ( ' body (if set): ' , self . _body ) )
rows . append ( ( ' data: ' , self . _data_preview ) )
rows . append ( ( ' copy data: ' , self . _data_copy_button ) )
rows . append ( ( ' new temp vars: ' , self . _temp_variables ) )
rows . append ( ( ' new cookies: ' , self . _cookies ) )
rows . append ( ( ' result: ' , self . _result ) )
gridbox = ClientGUICommon . WrapInGrid ( self , rows )
self . SetSizer ( gridbox )
def _CopyData ( self ) :
HG . client_controller . pub ( ' clipboard ' , ' text ' , self . _downloaded_data )
2018-10-17 21:00:09 +00:00
class EditLoginScriptPanel ( ClientGUIScrolledPanels . EditPanel ) :
def __init__ ( self , parent , login_script ) :
ClientGUIScrolledPanels . EditPanel . __init__ ( self , parent )
self . _original_login_script = login_script
2018-10-31 21:41:14 +00:00
self . _currently_testing = False
self . _test_domain = ' '
self . _test_credentials = { }
2018-10-17 21:00:09 +00:00
#
menu_items = [ ]
page_func = HydrusData . Call ( ClientPaths . LaunchPathInWebBrowser , os . path . join ( HC . HELP_DIR , ' downloader_login.html ' ) )
menu_items . append ( ( ' normal ' , ' open the login scripts help ' , ' Open the help page for login scripts in your web browser. ' , page_func ) )
help_button = ClientGUICommon . MenuBitmapButton ( self , CC . GlobalBMPs . help , menu_items )
help_hbox = ClientGUICommon . WrapInText ( help_button , self , ' help for this panel --> ' , wx . Colour ( 0 , 0 , 255 ) )
#
self . _name = wx . TextCtrl ( self )
#
credential_definitions_box_panel = ClientGUICommon . StaticBox ( self , ' credential definitions ' )
credential_definitions_panel = ClientGUIListCtrl . BetterListCtrlPanel ( credential_definitions_box_panel )
columns = [ ( ' name ' , - 1 ) , ( ' type ' , 10 ) , ( ' value ' , 16 ) ]
self . _credential_definitions = ClientGUIListCtrl . BetterListCtrl ( credential_definitions_panel , ' credential_definitions ' , 4 , 16 , columns , self . _ConvertCredentialDefinitionToListCtrlTuples , use_simple_delete = True , activation_callback = self . _EditCredentialDefinitions )
credential_definitions_panel . SetListCtrl ( self . _credential_definitions )
credential_definitions_panel . AddButton ( ' add ' , self . _AddCredentialDefinition )
credential_definitions_panel . AddButton ( ' edit ' , self . _EditCredentialDefinitions , enabled_only_on_selection = True )
credential_definitions_panel . AddDeleteButton ( )
#
login_steps_box_panel = ClientGUICommon . StaticBox ( self , ' login steps ' )
columns = [ ( ' name ' , - 1 ) , ( ' url ' , 56 ) ]
self . _login_steps = ClientGUIListBoxes . QueueListBox ( login_steps_box_panel , 5 , self . _ConvertLoginStepToListBoxString , add_callable = self . _AddLoginStep , edit_callable = self . _EditLoginStep )
#
required_cookies_info_box_panel = ClientGUICommon . StaticBox ( self , ' cookies required to consider session logged in ' )
2018-11-14 23:10:55 +00:00
self . _required_cookies_info = ClientGUIControls . StringMatchToStringMatchDictControl ( required_cookies_info_box_panel , login_script . GetRequiredCookiesInfo ( ) , min_height = 4 , key_name = ' cookie name ' )
2018-10-17 21:00:09 +00:00
#
example_domains_info_box_panel = ClientGUICommon . StaticBox ( self , ' example domains ' )
example_domains_info_panel = ClientGUIListCtrl . BetterListCtrlPanel ( example_domains_info_box_panel )
columns = [ ( ' domain ' , - 1 ) , ( ' access type ' , 14 ) , ( ' description ' , 40 ) ]
self . _example_domains_info = ClientGUIListCtrl . BetterListCtrl ( example_domains_info_panel , ' example_domains_info ' , 6 , 16 , columns , self . _ConvertExampleDomainInfoToListCtrlTuples , use_simple_delete = True , activation_callback = self . _EditExampleDomainsInfo )
example_domains_info_panel . SetListCtrl ( self . _example_domains_info )
example_domains_info_panel . AddButton ( ' add ' , self . _AddExampleDomainsInfo )
example_domains_info_panel . AddButton ( ' edit ' , self . _EditExampleDomainsInfo , enabled_only_on_selection = True )
example_domains_info_panel . AddDeleteButton ( )
#
2018-10-31 21:41:14 +00:00
test_panel = ClientGUICommon . StaticBox ( self , ' testing ' )
self . _test_button = ClientGUICommon . BetterButton ( test_panel , ' run test ' , self . _DoTest )
self . _test_network_job_control = ClientGUIControls . NetworkJobControl ( test_panel )
test_listctrl_panel = ClientGUIListCtrl . BetterListCtrlPanel ( test_panel )
columns = [ ( ' step ' , - 1 ) , ( ' url ' , 36 ) , ( ' result ' , 14 ) ]
self . _test_listctrl = ClientGUIListCtrl . BetterListCtrl ( test_listctrl_panel , ' test_login_script_results ' , 6 , 20 , columns , self . _ConvertTestResultToListCtrlTuples , activation_callback = self . _ReviewTestResult )
test_listctrl_panel . SetListCtrl ( self . _test_listctrl )
test_listctrl_panel . AddButton ( ' review ' , self . _ReviewTestResult , enabled_only_on_selection = True )
self . _final_test_result = ClientGUICommon . BetterStaticText ( test_panel )
#
2018-10-17 21:00:09 +00:00
self . _name . SetValue ( login_script . GetName ( ) )
self . _credential_definitions . SetData ( login_script . GetCredentialDefinitions ( ) )
self . _login_steps . AddDatas ( login_script . GetLoginSteps ( ) )
self . _example_domains_info . SetData ( login_script . GetExampleDomainsInfo ( ) )
#
credential_definitions_box_panel . Add ( credential_definitions_panel , CC . FLAGS_EXPAND_BOTH_WAYS )
login_steps_box_panel . Add ( self . _login_steps , CC . FLAGS_EXPAND_BOTH_WAYS )
required_cookies_info_box_panel . Add ( self . _required_cookies_info , CC . FLAGS_EXPAND_BOTH_WAYS )
example_domains_info_box_panel . Add ( example_domains_info_panel , CC . FLAGS_EXPAND_BOTH_WAYS )
2018-10-31 21:41:14 +00:00
test_panel . Add ( self . _test_button , CC . FLAGS_EXPAND_PERPENDICULAR )
test_panel . Add ( self . _test_network_job_control , CC . FLAGS_EXPAND_PERPENDICULAR )
test_panel . Add ( test_listctrl_panel , CC . FLAGS_EXPAND_BOTH_WAYS )
test_panel . Add ( self . _final_test_result , CC . FLAGS_EXPAND_PERPENDICULAR )
2018-10-17 21:00:09 +00:00
#
rows = [ ]
rows . append ( ( ' name: ' , self . _name ) )
gridbox = ClientGUICommon . WrapInGrid ( self , rows )
vbox = ClientGUICommon . BetterBoxSizer ( wx . VERTICAL )
vbox . Add ( help_hbox , CC . FLAGS_BUTTON_SIZER )
vbox . Add ( gridbox , CC . FLAGS_EXPAND_SIZER_PERPENDICULAR )
vbox . Add ( credential_definitions_box_panel , CC . FLAGS_EXPAND_BOTH_WAYS )
vbox . Add ( login_steps_box_panel , CC . FLAGS_EXPAND_BOTH_WAYS )
vbox . Add ( required_cookies_info_box_panel , CC . FLAGS_EXPAND_BOTH_WAYS )
vbox . Add ( example_domains_info_box_panel , CC . FLAGS_EXPAND_BOTH_WAYS )
2018-10-31 21:41:14 +00:00
hbox = ClientGUICommon . BetterBoxSizer ( wx . HORIZONTAL )
hbox . Add ( vbox , CC . FLAGS_EXPAND_SIZER_BOTH_WAYS )
hbox . Add ( test_panel , CC . FLAGS_EXPAND_BOTH_WAYS )
self . SetSizer ( hbox )
2018-10-17 21:00:09 +00:00
def _AddCredentialDefinition ( self ) :
new_credential_definition = ClientNetworkingLogin . LoginCredentialDefinition ( )
with ClientGUITopLevelWindows . DialogEdit ( self , ' edit parser ' , frame_key = ' deeply_nested_dialog ' ) as dlg_edit :
panel = EditLoginCredentialDefinitionPanel ( dlg_edit , new_credential_definition )
dlg_edit . SetPanel ( panel )
if dlg_edit . ShowModal ( ) == wx . ID_OK :
new_credential_definition = panel . GetValue ( )
HydrusSerialisable . SetNonDupeName ( new_credential_definition , self . _GetExistingCredentialDefinitionNames ( ) )
self . _credential_definitions . AddDatas ( ( new_credential_definition , ) )
self . _credential_definitions . Sort ( )
def _AddExampleDomainsInfo ( self ) :
( domain , access_type , access_text ) = ( ' example.com ' , ClientNetworkingLogin . LOGIN_ACCESS_TYPE_NSFW , ClientNetworkingLogin . login_access_type_default_description_lookup [ ClientNetworkingLogin . LOGIN_ACCESS_TYPE_NSFW ] )
with ClientGUIDialogs . DialogTextEntry ( self , ' edit the domain ' , default = domain , allow_blank = False ) as dlg :
if dlg . ShowModal ( ) == wx . ID_OK :
domain = dlg . GetValue ( )
else :
return
existing_domains = self . _GetExistingDomains ( )
if domain in existing_domains :
wx . MessageBox ( ' That domain already exists! ' )
return
a_types = [ ClientNetworkingLogin . LOGIN_ACCESS_TYPE_EVERYTHING , ClientNetworkingLogin . LOGIN_ACCESS_TYPE_NSFW , ClientNetworkingLogin . LOGIN_ACCESS_TYPE_SPECIAL , ClientNetworkingLogin . LOGIN_ACCESS_TYPE_USER_PREFS_ONLY ]
choice_tuples = [ ( ClientNetworkingLogin . login_access_type_str_lookup [ a_type ] , a_type ) for a_type in a_types ]
2018-11-14 23:10:55 +00:00
try :
2018-10-17 21:00:09 +00:00
2018-11-14 23:10:55 +00:00
new_access_type = ClientGUIDialogsQuick . SelectFromList ( self , ' select what type of access the login gives to this domain ' , choice_tuples , value_to_select = access_type , sort_tuples = False )
except HydrusExceptions . CancelledException :
return
2018-10-17 21:00:09 +00:00
if new_access_type != access_type :
access_type = new_access_type
access_text = ClientNetworkingLogin . login_access_type_default_description_lookup [ access_type ]
with ClientGUIDialogs . DialogTextEntry ( self , ' edit the access description, if needed ' , default = access_text , allow_blank = False ) as dlg :
if dlg . ShowModal ( ) == wx . ID_OK :
access_text = dlg . GetValue ( )
else :
return
example_domain_info = ( domain , access_type , access_text )
self . _example_domains_info . AddDatas ( ( example_domain_info , ) )
self . _example_domains_info . Sort ( )
def _AddLoginStep ( self ) :
login_step = ClientNetworkingLogin . LoginStep ( )
return self . _EditLoginStep ( login_step )
def _ConvertCredentialDefinitionToListCtrlTuples ( self , credential_definition ) :
name = credential_definition . GetName ( )
credential_type = credential_definition . GetType ( )
type_string = ClientNetworkingLogin . credential_type_str_lookup [ credential_type ]
string_match = credential_definition . GetStringMatch ( )
2019-01-09 22:59:03 +00:00
value = string_match . ToString ( )
2018-10-17 21:00:09 +00:00
pretty_name = name
pretty_type_string = type_string
pretty_value = value
display_tuple = ( pretty_name , pretty_type_string , pretty_value )
sort_tuple = ( name , type_string , value )
return ( display_tuple , sort_tuple )
def _ConvertExampleDomainInfoToListCtrlTuples ( self , example_domain_info ) :
( domain , access_type , access_text ) = example_domain_info
pretty_domain = domain
pretty_access_type = ClientNetworkingLogin . login_access_type_str_lookup [ access_type ]
pretty_access_text = access_text
display_tuple = ( pretty_domain , pretty_access_type , pretty_access_text )
sort_tuple = ( domain , pretty_access_type , access_text )
return ( display_tuple , sort_tuple )
def _ConvertLoginStepToListBoxString ( self , login_step ) :
name = login_step . GetName ( )
return name
2018-10-31 21:41:14 +00:00
def _ConvertTestResultToListCtrlTuples ( self , test_result ) :
( name , url , body , downloaded_data , new_temp_strings , new_cookie_strings , result ) = test_result
pretty_name = name
pretty_url = url
pretty_result = result
display_tuple = ( pretty_name , pretty_url , pretty_result )
sort_tuple = ( name , url , result )
return ( display_tuple , sort_tuple )
2018-10-17 21:00:09 +00:00
def _EditCredentialDefinitions ( self ) :
credential_definitions = self . _credential_definitions . GetData ( only_selected = True )
for credential_definition in credential_definitions :
with ClientGUITopLevelWindows . DialogEdit ( self , ' edit login script ' , frame_key = ' deeply_nested_dialog ' ) as dlg :
panel = EditLoginCredentialDefinitionPanel ( dlg , credential_definition )
dlg . SetPanel ( panel )
if dlg . ShowModal ( ) == wx . ID_OK :
edited_credential_definition = panel . GetValue ( )
self . _credential_definitions . DeleteDatas ( ( credential_definition , ) )
HydrusSerialisable . SetNonDupeName ( edited_credential_definition , self . _GetExistingCredentialDefinitionNames ( ) )
self . _credential_definitions . AddDatas ( ( edited_credential_definition , ) )
else :
break
self . _credential_definitions . Sort ( )
2018-10-31 21:41:14 +00:00
def _DoTest ( self ) :
def wx_add_result ( test_result ) :
if not self :
return
self . _test_listctrl . AddDatas ( ( test_result , ) )
def receive_result ( test_result ) :
wx . CallAfter ( wx_add_result , test_result )
def clean_up ( final_result ) :
if not self :
return
wx . MessageBox ( final_result )
self . _final_test_result . SetLabelText ( final_result )
self . _test_button . Enable ( )
self . _currently_testing = False
def do_it ( login_script , domain , credentials , network_job_presentation_context_factory ) :
try :
login_result = ' login did not finish '
# a potential here is to properly inform the login manager of the domain map and hence read back the invalidation text
# but I am catching the info in the raised exception, so nbd really, I think
bandwidth_manager = ClientNetworkingBandwidth . NetworkBandwidthManager ( )
session_manager = ClientNetworkingSessions . NetworkSessionManager ( )
domain_manager = ClientNetworkingDomain . NetworkDomainManager ( )
login_manager = ClientNetworkingLogin . NetworkLoginManager ( )
network_engine = ClientNetworking . NetworkEngine ( HG . client_controller , bandwidth_manager , session_manager , domain_manager , login_manager )
HG . client_controller . CallToThreadLongRunning ( network_engine . MainLoop )
network_context = ClientNetworkingContexts . NetworkContext . STATICGenerateForDomain ( domain )
login_result = login_script . Start ( network_engine , network_context , credentials , network_job_presentation_context_factory = network_job_presentation_context_factory , test_result_callable = wx_add_result )
except Exception as e :
2019-01-09 22:59:03 +00:00
login_result = str ( e )
2018-10-31 21:41:14 +00:00
HydrusData . ShowException ( e )
finally :
network_engine . Shutdown ( )
wx . CallAfter ( clean_up , login_result )
2018-11-07 23:09:40 +00:00
if self . _currently_testing :
wx . MessageBox ( ' Currently testing already! Please cancel current job! ' )
return
try :
login_script = self . GetValue ( )
except HydrusExceptions . VetoException :
return
if self . _test_domain == ' ' :
example_domains = list ( login_script . GetExampleDomains ( ) )
example_domains . sort ( )
if len ( example_domains ) > 0 :
self . _test_domain = example_domains [ 0 ]
2018-10-31 21:41:14 +00:00
with ClientGUIDialogs . DialogTextEntry ( self , ' edit the domain ' , default = self . _test_domain , allow_blank = False ) as dlg :
if dlg . ShowModal ( ) == wx . ID_OK :
self . _test_domain = dlg . GetValue ( )
else :
return
credential_definitions = login_script . GetCredentialDefinitions ( )
if len ( credential_definitions ) > 0 :
with ClientGUITopLevelWindows . DialogEdit ( self , ' edit login ' ) as dlg :
panel = EditLoginCredentialsPanel ( dlg , credential_definitions , self . _test_credentials )
dlg . SetPanel ( panel )
if dlg . ShowModal ( ) == wx . ID_OK :
self . _test_credentials = panel . GetValue ( )
else :
return
else :
self . _test_credentials = { }
2018-11-07 23:09:40 +00:00
self . _test_listctrl . DeleteDatas ( self . _test_listctrl . GetData ( ) )
self . _test_button . Disable ( )
2018-10-31 21:41:14 +00:00
network_job_presentation_context_factory = GenerateTestNetworkJobPresentationContextFactory ( self , self . _test_network_job_control )
self . _currently_testing = True
HG . client_controller . CallToThread ( do_it , login_script , self . _test_domain , self . _test_credentials , network_job_presentation_context_factory )
2018-10-17 21:00:09 +00:00
def _EditExampleDomainsInfo ( self ) :
selected_example_domains_info = self . _example_domains_info . GetData ( only_selected = True )
for example_domain_info in selected_example_domains_info :
( original_domain , access_type , access_text ) = example_domain_info
with ClientGUIDialogs . DialogTextEntry ( self , ' edit the domain ' , default = original_domain , allow_blank = False ) as dlg :
if dlg . ShowModal ( ) == wx . ID_OK :
domain = dlg . GetValue ( )
else :
break
existing_domains = self . _GetExistingDomains ( )
if domain != original_domain and domain in existing_domains :
wx . MessageBox ( ' That domain already exists! ' )
break
a_types = [ ClientNetworkingLogin . LOGIN_ACCESS_TYPE_EVERYTHING , ClientNetworkingLogin . LOGIN_ACCESS_TYPE_NSFW , ClientNetworkingLogin . LOGIN_ACCESS_TYPE_SPECIAL , ClientNetworkingLogin . LOGIN_ACCESS_TYPE_USER_PREFS_ONLY ]
choice_tuples = [ ( ClientNetworkingLogin . login_access_type_str_lookup [ a_type ] , a_type ) for a_type in a_types ]
2018-11-14 23:10:55 +00:00
try :
2018-10-17 21:00:09 +00:00
2018-11-14 23:10:55 +00:00
new_access_type = ClientGUIDialogsQuick . SelectFromList ( self , ' select what type of access the login gives to this domain ' , choice_tuples , value_to_select = access_type , sort_tuples = False )
except HydrusExceptions . CancelledException :
break
2018-10-17 21:00:09 +00:00
if new_access_type != access_type :
access_type = new_access_type
access_text = ClientNetworkingLogin . login_access_type_default_description_lookup [ access_type ]
with ClientGUIDialogs . DialogTextEntry ( self , ' edit the access description, if needed ' , default = access_text , allow_blank = False ) as dlg :
if dlg . ShowModal ( ) == wx . ID_OK :
access_text = dlg . GetValue ( )
else :
break
self . _example_domains_info . DeleteDatas ( ( example_domain_info , ) )
edited_example_domain_info = ( domain , access_type , access_text )
self . _example_domains_info . AddDatas ( ( edited_example_domain_info , ) )
self . _example_domains_info . Sort ( )
def _EditLoginStep ( self , login_step ) :
with ClientGUITopLevelWindows . DialogEdit ( self , ' edit login step ' ) as dlg :
panel = EditLoginStepPanel ( dlg , login_step )
dlg . SetPanel ( panel )
if dlg . ShowModal ( ) == wx . ID_OK :
login_step = panel . GetValue ( )
return login_step
else :
raise HydrusExceptions . VetoException ( )
def _GetExistingCredentialDefinitionNames ( self ) :
return { credential_definition . GetName ( ) for credential_definition in self . _credential_definitions . GetData ( ) }
def _GetExistingDomains ( self ) :
return { domain for ( domain , access_type , access_text ) in self . _example_domains_info . GetData ( ) }
2018-10-31 21:41:14 +00:00
def _ReviewTestResult ( self ) :
for test_result in self . _test_listctrl . GetData ( only_selected = True ) :
frame = ClientGUITopLevelWindows . FrameThatTakesScrollablePanel ( self , ' login test result ' )
panel = ReviewTestResultPanel ( frame , test_result )
frame . SetPanel ( panel )
2018-10-17 21:00:09 +00:00
def GetValue ( self ) :
2018-10-31 21:41:14 +00:00
if self . _currently_testing :
raise HydrusExceptions . VetoException ( ' Currently testing! Please cancel it first! ' )
2018-10-17 21:00:09 +00:00
name = self . _name . GetValue ( )
login_script_key = self . _original_login_script . GetLoginScriptKey ( )
required_cookies_info = self . _required_cookies_info . GetValue ( )
credential_definitions = self . _credential_definitions . GetData ( )
login_steps = self . _login_steps . GetData ( )
example_domains_info = self . _example_domains_info . GetData ( )
credential_names = { credential_definition . GetName ( ) for credential_definition in credential_definitions }
login_script = ClientNetworkingLogin . LoginScriptDomain ( name = name , login_script_key = login_script_key , required_cookies_info = required_cookies_info , credential_definitions = credential_definitions , login_steps = login_steps , example_domains_info = example_domains_info )
login_script . SetLoginScriptKey ( login_script_key )
try :
login_script . CheckIsValid ( )
except HydrusExceptions . ValidationException as e :
message = ' There is a problem with this script. The reason is: '
message + = os . linesep * 2
2019-01-09 22:59:03 +00:00
message + = str ( e )
2018-10-17 21:00:09 +00:00
message + = os . linesep * 2
2018-10-31 21:41:14 +00:00
message + = ' Do you want to proceed with this invalid script, or go back and fix it? '
2018-10-17 21:00:09 +00:00
with ClientGUIDialogs . DialogYesNo ( self , message , yes_label = ' ok as invalid ' , no_label = ' go back ' ) as dlg :
if dlg . ShowModal ( ) != wx . ID_YES :
raise HydrusExceptions . VetoException ( ' The ok event has been cancelled! ' )
return login_script
class EditLoginScriptsPanel ( ClientGUIScrolledPanels . EditPanel ) :
def __init__ ( self , parent , login_scripts ) :
ClientGUIScrolledPanels . EditPanel . __init__ ( self , parent )
login_scripts_panel = ClientGUIListCtrl . BetterListCtrlPanel ( self )
columns = [ ( ' name ' , - 1 ) , ( ' example domains ' , 40 ) ]
self . _login_scripts = ClientGUIListCtrl . BetterListCtrl ( login_scripts_panel , ' login_scripts ' , 20 , 24 , columns , self . _ConvertLoginScriptToListCtrlTuples , use_simple_delete = True , activation_callback = self . _Edit )
login_scripts_panel . SetListCtrl ( self . _login_scripts )
login_scripts_panel . AddButton ( ' add ' , self . _Add )
login_scripts_panel . AddButton ( ' edit ' , self . _Edit , enabled_only_on_selection = True )
login_scripts_panel . AddDeleteButton ( )
login_scripts_panel . AddSeparator ( )
login_scripts_panel . AddImportExportButtons ( ( ClientNetworkingLogin . LoginScriptDomain , ) , self . _AddLoginScript )
login_scripts_panel . AddSeparator ( )
login_scripts_panel . AddDefaultsButton ( ClientDefaults . GetDefaultLoginScripts , self . _AddLoginScript )
#
self . _login_scripts . AddDatas ( login_scripts )
#
vbox = wx . BoxSizer ( wx . VERTICAL )
vbox . Add ( login_scripts_panel , CC . FLAGS_EXPAND_BOTH_WAYS )
self . SetSizer ( vbox )
def _Add ( self ) :
new_login_script = ClientNetworkingLogin . LoginScriptDomain ( )
with ClientGUITopLevelWindows . DialogEdit ( self , ' edit login script ' , frame_key = ' deeply_nested_dialog ' ) as dlg_edit :
panel = EditLoginScriptPanel ( dlg_edit , new_login_script )
dlg_edit . SetPanel ( panel )
if dlg_edit . ShowModal ( ) == wx . ID_OK :
new_login_script = panel . GetValue ( )
self . _AddLoginScript ( new_login_script )
self . _login_scripts . Sort ( )
def _AddLoginScript ( self , login_script ) :
HydrusSerialisable . SetNonDupeName ( login_script , self . _GetExistingNames ( ) )
login_script . RegenerateLoginScriptKey ( )
self . _login_scripts . AddDatas ( ( login_script , ) )
def _ConvertLoginScriptToListCtrlTuples ( self , login_script ) :
name = login_script . GetName ( )
example_domains = list ( login_script . GetExampleDomains ( ) )
example_domains . sort ( )
pretty_name = name
pretty_example_domains = ' , ' . join ( example_domains )
display_tuple = ( pretty_name , pretty_example_domains )
sort_tuple = ( name , example_domains )
return ( display_tuple , sort_tuple )
def _Edit ( self ) :
login_scripts = self . _login_scripts . GetData ( only_selected = True )
for login_script in login_scripts :
with ClientGUITopLevelWindows . DialogEdit ( self , ' edit login script ' , frame_key = ' deeply_nested_dialog ' ) as dlg :
panel = EditLoginScriptPanel ( dlg , login_script )
dlg . SetPanel ( panel )
if dlg . ShowModal ( ) == wx . ID_OK :
edited_login_script = panel . GetValue ( )
self . _login_scripts . DeleteDatas ( ( login_script , ) )
HydrusSerialisable . SetNonDupeName ( edited_login_script , self . _GetExistingNames ( ) )
self . _login_scripts . AddDatas ( ( edited_login_script , ) )
else :
break
self . _login_scripts . Sort ( )
def _GetExistingNames ( self ) :
names = { login_script . GetName ( ) for login_script in self . _login_scripts . GetData ( ) }
return names
def GetValue ( self ) :
return self . _login_scripts . GetData ( )
class EditLoginStepPanel ( ClientGUIScrolledPanels . EditPanel ) :
def __init__ ( self , parent , login_step ) :
ClientGUIScrolledPanels . EditPanel . __init__ ( self , parent )
#
name = login_step . GetName ( )
( scheme , method , subdomain , path , required_credentials , static_args , temp_args , required_cookies_info , content_parsers ) = login_step . ToTuple ( )
#
self . _name = wx . TextCtrl ( self )
self . _method = ClientGUICommon . BetterChoice ( self )
self . _method . Append ( ' GET ' , ' GET ' )
self . _method . Append ( ' POST ' , ' POST ' )
self . _scheme = ClientGUICommon . BetterChoice ( self )
self . _scheme . Append ( ' http ' , ' http ' )
self . _scheme . Append ( ' https ' , ' https ' )
self . _subdomain = ClientGUICommon . NoneableTextCtrl ( self , none_phrase = ' none ' )
self . _path = wx . TextCtrl ( self )
required_credentials_panel = ClientGUICommon . StaticBox ( self , ' credentials to send ' )
self . _required_credentials = ClientGUIControls . StringToStringDictControl ( required_credentials_panel , required_credentials , min_height = 4 , key_name = ' credential name ' , value_name = ' parameter name ' )
#
static_args_panel = ClientGUICommon . StaticBox ( self , ' static variables to send ' )
self . _static_args = ClientGUIControls . StringToStringDictControl ( static_args_panel , static_args , min_height = 4 , key_name = ' parameter name ' , value_name = ' value ' )
#
temp_args_panel = ClientGUICommon . StaticBox ( self , ' temporary variables to send ' )
self . _temp_args = ClientGUIControls . StringToStringDictControl ( temp_args_panel , temp_args , min_height = 4 , key_name = ' temp variable name ' , value_name = ' parameter name ' )
#
required_cookies_info_box_panel = ClientGUICommon . StaticBox ( self , ' cookies required to consider step successful ' )
2018-11-14 23:10:55 +00:00
self . _required_cookies_info = ClientGUIControls . StringMatchToStringMatchDictControl ( required_cookies_info_box_panel , required_cookies_info , min_height = 4 , key_name = ' cookie name ' )
2018-10-17 21:00:09 +00:00
#
content_parsers_panel = ClientGUICommon . StaticBox ( self , ' content parsers ' )
test_context_callable = lambda : ( { } , ' ' )
permitted_content_types = [ HC . CONTENT_TYPE_VARIABLE , HC . CONTENT_TYPE_VETO ]
self . _content_parsers = ClientGUIParsing . EditContentParsersPanel ( content_parsers_panel , test_context_callable , permitted_content_types )
# a test panel a la pageparsers
#
self . _name . SetValue ( name )
self . _scheme . SelectClientData ( scheme )
self . _method . SelectClientData ( method )
self . _subdomain . SetValue ( subdomain )
self . _path . SetValue ( path )
self . _content_parsers . AddDatas ( content_parsers )
#
required_credentials_panel . Add ( self . _required_credentials , CC . FLAGS_EXPAND_BOTH_WAYS )
static_args_panel . Add ( self . _static_args , CC . FLAGS_EXPAND_BOTH_WAYS )
temp_args_panel . Add ( self . _temp_args , CC . FLAGS_EXPAND_BOTH_WAYS )
required_cookies_info_box_panel . Add ( self . _required_cookies_info , CC . FLAGS_EXPAND_BOTH_WAYS )
content_parsers_panel . Add ( self . _content_parsers , CC . FLAGS_EXPAND_BOTH_WAYS )
#
rows = [ ]
rows . append ( ( ' name: ' , self . _name ) )
rows . append ( ( ' scheme: ' , self . _scheme ) )
rows . append ( ( ' method: ' , self . _method ) )
rows . append ( ( ' subdomain (replaces www, if present): ' , self . _subdomain ) )
rows . append ( ( ' path: ' , self . _path ) )
gridbox = ClientGUICommon . WrapInGrid ( self , rows )
vbox = ClientGUICommon . BetterBoxSizer ( wx . VERTICAL )
2019-05-22 22:35:06 +00:00
vbox . Add ( gridbox , CC . FLAGS_EXPAND_SIZER_PERPENDICULAR )
2018-10-17 21:00:09 +00:00
vbox . Add ( required_credentials_panel , CC . FLAGS_EXPAND_BOTH_WAYS )
vbox . Add ( static_args_panel , CC . FLAGS_EXPAND_BOTH_WAYS )
vbox . Add ( temp_args_panel , CC . FLAGS_EXPAND_BOTH_WAYS )
vbox . Add ( required_cookies_info_box_panel , CC . FLAGS_EXPAND_BOTH_WAYS )
vbox . Add ( content_parsers_panel , CC . FLAGS_EXPAND_BOTH_WAYS )
self . SetSizer ( vbox )
def GetValue ( self ) :
name = self . _name . GetValue ( )
scheme = self . _scheme . GetChoice ( )
method = self . _method . GetChoice ( )
subdomain = self . _subdomain . GetValue ( )
path = self . _path . GetValue ( )
required_credentials = self . _required_credentials . GetValue ( )
static_args = self . _static_args . GetValue ( )
temp_args = self . _temp_args . GetValue ( )
required_cookies_info = self . _required_cookies_info . GetValue ( )
content_parsers = self . _content_parsers . GetData ( )
if subdomain == ' ' :
subdomain = None
login_step = ClientNetworkingLogin . LoginStep ( name = name , scheme = scheme , method = method , subdomain = subdomain , path = path )
login_step . SetComplicatedVariables ( required_credentials , static_args , temp_args , required_cookies_info , content_parsers )
return login_step