hydrus/include/ClientGUILogin.py

2148 lines
79 KiB
Python
Raw Normal View History

2018-10-17 21:00:09 +00:00
import ClientConstants as CC
import ClientData
import ClientDefaults
import ClientGUICommon
import ClientGUIDialogs
2018-11-14 23:10:55 +00:00
import ClientGUIDialogsQuick
2018-10-17 21:00:09 +00:00
import ClientGUIMenus
import ClientGUIControls
import ClientGUIListBoxes
import ClientGUIListCtrl
import ClientGUIParsing
import ClientGUIScrolledPanels
import ClientGUIScrolledPanelsEdit
import ClientGUISerialisable
import ClientGUITopLevelWindows
2018-10-31 21:41:14 +00:00
import ClientImporting
import ClientNetworking
import ClientNetworkingBandwidth
2018-10-17 21:00:09 +00:00
import ClientNetworkingContexts
import ClientNetworkingDomain
import ClientNetworkingLogin
import ClientNetworkingJobs
2018-10-31 21:41:14 +00:00
import ClientNetworkingSessions
2018-10-17 21:00:09 +00:00
import ClientParsing
import ClientPaths
import ClientSerialisable
import ClientThreading
import HydrusConstants as HC
import HydrusData
import HydrusExceptions
import HydrusGlobals as HG
import HydrusSerialisable
import HydrusTags
import HydrusText
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:
st_label = string_match.ToUnicode()
else:
try:
credential_definition.Test( value )
st_label = u'looks good \u2713'
colour = ( 0, 127, 0 )
except Exception as e:
st_label = HydrusData.ToUnicode( e )
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:
2018-11-14 23:10:55 +00:00
veto_errors.append( 'For ' + name + ': ' + HydrusData.ToUnicode( e ) )
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 = []
2018-10-24 21:34:02 +00:00
domains_and_login_info_panel = ClientGUIListCtrl.BetterListCtrlPanel( self )
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
self._domains_and_login_info = ClientGUIListCtrl.BetterListCtrl( domains_and_login_info_panel, 'domains_to_login_info', 8, 36, columns, self._ConvertDomainAndLoginInfoListCtrlTuples, use_simple_delete = True, activation_callback = self._EditCredentials )
domains_and_login_info_panel.SetListCtrl( self._domains_and_login_info )
domains_and_login_info_panel.AddButton( 'add', self._Add )
domains_and_login_info_panel.AddDeleteButton()
domains_and_login_info_panel.AddSeparator()
domains_and_login_info_panel.AddButton( 'edit credentials', self._EditCredentials, enabled_check_func = self._CanEditCreds )
2018-11-21 22:22:36 +00:00
domains_and_login_info_panel.AddButton( 'change login script', self._EditLoginScript, enabled_only_on_selection = True )
2018-10-24 21:34:02 +00:00
domains_and_login_info_panel.AddButton( 'flip active', self._FlipActive, enabled_only_on_selection = True )
domains_and_login_info_panel.AddSeparator()
2018-11-14 23:10:55 +00:00
domains_and_login_info_panel.AddButton( 'scrub invalidity', self._ScrubInvalidity, enabled_check_func = self._CanScrubInvalidity )
domains_and_login_info_panel.AddButton( 'scrub delays', self._ScrubDelays, enabled_check_func = self._CanScrubDelays )
2018-10-24 21:34:02 +00:00
domains_and_login_info_panel.NewButtonRow()
2018-11-21 22:22:36 +00:00
domains_and_login_info_panel.AddButton( 'do login now', self._DoLogin, enabled_check_func = self._CanDoLogin )
2018-10-24 21:34:02 +00:00
domains_and_login_info_panel.AddButton( 'reset login (delete cookies)', self._ClearSessions, enabled_only_on_selection = True )
#
listctrl_data = []
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 domains_to_login_info.items():
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 )
vbox.Add( domains_and_login_info_panel, CC.FLAGS_EXPAND_BOTH_WAYS )
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?
creds_are_good = len( credentials ) == 0 or True in ( value != '' for value in credentials.values() )
except HydrusExceptions.ValidationException as e:
validity = ClientNetworkingLogin.VALIDITY_INVALID
validity_error_text = HydrusData.ToUnicode( e )
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()
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?
creds_are_good = len( credentials ) == 0 or True in ( value != '' for value in credentials.values() )
except HydrusExceptions.ValidationException as e:
validity = ClientNetworkingLogin.VALIDITY_INVALID
validity_error_text = HydrusData.ToUnicode( e )
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
validity_error_text = HydrusData.ToUnicode( e )
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
validity_error_text = HydrusData.ToUnicode( e )
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 )
min_size = ClientGUICommon.ConvertTextToPixels( self._body, ( 64, 3 ) )
self._body.SetMinClientSize( min_size )
self._data_preview = wx.TextCtrl( self, style = wx.TE_MULTILINE )
self._data_preview.SetEditable( False )
min_size = ClientGUICommon.ConvertTextToPixels( self._data_preview, ( 64, 8 ) )
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 )
min_size = ClientGUICommon.ConvertTextToPixels( self._temp_variables, ( 64, 6 ) )
self._temp_variables.SetMinClientSize( min_size )
self._cookies = wx.TextCtrl( self, style = wx.TE_MULTILINE )
self._cookies.SetEditable( False )
min_size = ClientGUICommon.ConvertTextToPixels( self._cookies, ( 64, 6 ) )
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:
self._body.SetValue( HydrusData.ToUnicode( body ) )
self._data_preview.SetValue( HydrusData.ToUnicode( self._downloaded_data[:1024] ) )
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()
value = string_match.ToUnicode()
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:
login_result = HydrusData.ToUnicode( e )
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
message += HydrusData.ToUnicode( e )
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 )
vbox.Add( gridbox, CC.FLAGS_EXPAND_PERPENDICULAR )
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