def _RefreshExternalIP(self): def work_callable(): try: external_ip = HydrusNATPunch.GetExternalIP() external_ip_text = 'External IP: {}'.format(external_ip) except Exception as e: external_ip_text = 'Error finding external IP: ' + str(e) return external_ip_text def publish_callable(external_ip_text): self._external_ip = external_ip_text self._status_st.setText(self._external_ip) self._status_st.setText('Loading external IP\u2026') async_job = ClientGUIAsync.AsyncQtJob(self, work_callable, publish_callable) async_job.start()
def _InitialiseAccountTypes( self ): service = self._service def work_callable(): response = service.Request( HC.GET, 'account_types' ) account_types = response[ 'account_types' ] return account_types def publish_callable( result ): self._account_types = result self._account_types_choice.setEnabled( True ) self._account_types_button.setEnabled( True ) self._account_types.sort( key = lambda at: str( at ) ) for account_type in self._account_types: self._account_types_choice.addItem( str( account_type ), account_type ) self._account_types_choice.setEnabled( False ) self._account_types_button.setEnabled( False ) job = ClientGUIAsync.AsyncQtJob( self, work_callable, publish_callable ) job.start()
def _DoSetMessage(self): subject_accounts = self._account_panel.GetCheckedAccounts() if len(subject_accounts) == 0: QW.QMessageBox.information(self, 'Information', 'No accounts selected for action!') return message = self._message_text.text() if message == '': yn_message = 'Clear message for the selected accounts?' else: yn_message = 'Set this message for the selected accounts?' result = ClientGUIDialogsQuick.GetYesNo(self, yn_message) if result != QW.QDialog.Accepted: return subject_account_keys = [ subject_account.GetAccountKey() for subject_account in subject_accounts ] service = self._service def work_callable(): for subject_account_key in subject_account_keys: service.Request( HC.POST, 'modify_account_set_message', { 'subject_identifier': HydrusNetwork.AccountIdentifier( account_key=subject_account_key), 'message': message }) return 1 def publish_callable(gumpf): QW.QMessageBox.information(self, 'Information', 'Done!') self._account_panel.RefreshAccounts() self._DisableUIForJob('setting message\u2026') job = ClientGUIAsync.AsyncQtJob(self, work_callable, publish_callable) job.start()
def _DoExpires( self, subject_account_keys_and_new_expires ): if len( subject_account_keys_and_new_expires ) == 0: QW.QMessageBox.information( self, 'Information', 'No accounts selected for action!' ) return service = self._service def work_callable(): for ( subject_account_key, new_expires ) in subject_account_keys_and_new_expires: service.Request( HC.POST, 'modify_account_expires', { 'subject_identifier' : HydrusNetwork.AccountIdentifier( account_key = subject_account_key ), 'expires' : new_expires } ) return 1 def publish_callable( gumpf ): QW.QMessageBox.information( self, 'Information', 'Done!' ) self._account_panel.RefreshAccounts() self._DisableUIForJob( 'setting new expiry\u2026' ) job = ClientGUIAsync.AsyncQtJob( self, work_callable, publish_callable ) job.start()
def _Add( self ): external_port = HC.DEFAULT_SERVICE_PORT protocol = 'TCP' internal_port = HC.DEFAULT_SERVICE_PORT description = 'hydrus service' duration = 0 with ClientGUIDialogs.DialogInputUPnPMapping( self, external_port, protocol, internal_port, description, duration ) as dlg: if dlg.exec() == QW.QDialog.Accepted: ( external_port, protocol, internal_port, description, duration ) = dlg.GetInfo() remove_existing = False if self._MappingExists( external_port, protocol ): remove_existing = True text = '{}:({}) is already mapped! Ok to overwrite whatever it currently is?' result = ClientGUIDialogsQuick.GetYesNo( self, text, yes_label = 'do it', no_label = 'forget it' ) if result != QW.QDialog.Accepted: return def work_callable(): if remove_existing: HydrusNATPunch.RemoveUPnPMapping( external_port, protocol ) internal_client = HydrusNATPunch.GetLocalIP() HydrusNATPunch.AddUPnPMapping( internal_client, internal_port, external_port, protocol, description, duration = duration ) return True def publish_callable( result ): self._mappings_listctrl_panel.setEnabled( True ) self._RefreshMappings() self._mappings_listctrl_panel.setEnabled( False ) async_job = ClientGUIAsync.AsyncQtJob( self, work_callable, publish_callable ) async_job.start()
def _DoUnban(self): subject_accounts = self._account_panel.GetCheckedAccounts() if len(subject_accounts) == 0: QW.QMessageBox.information(self, 'Information', 'No accounts selected for action!') return subject_accounts = [ subject_account for subject_account in subject_accounts if subject_account.IsBanned() ] if len(subject_accounts) == 0: QW.QMessageBox.information( self, 'Information', 'None of the selected accounts are banned!') return subject_account_keys = [ subject_account.GetAccountKey() for subject_account in subject_accounts ] service = self._service def work_callable(): for subject_account_key in subject_account_keys: service.Request( HC.POST, 'modify_account_unban', { 'subject_identifier': HydrusNetwork.AccountIdentifier( account_key=subject_account_key) }) return 1 def publish_callable(gumpf): QW.QMessageBox.information(self, 'Information', 'Done!') self._account_panel.RefreshAccounts() self._DisableUIForJob('unbanning\u2026') job = ClientGUIAsync.AsyncQtJob(self, work_callable, publish_callable) job.start()
def _Edit( self ): selected_mappings = self._mappings_list.GetData( only_selected = True ) if len( selected_mappings ) > 0: selected_mapping = selected_mappings[0] ( description, internal_ip, internal_port, old_external_port, old_protocol, duration ) = selected_mapping with ClientGUIDialogs.DialogInputUPnPMapping( self, old_external_port, old_protocol, internal_port, description, duration ) as dlg: if dlg.exec() == QW.QDialog.Accepted: ( external_port, protocol, internal_port, description, duration ) = dlg.GetInfo() remove_old = self._MappingExists( old_external_port, old_protocol ) remove_existing = ( old_external_port != external_port or old_protocol != protocol ) and self._MappingExists( external_port, protocol ) def work_callable(): if remove_old: HydrusNATPunch.RemoveUPnPMapping( old_external_port, old_protocol ) if remove_existing: HydrusNATPunch.RemoveUPnPMapping( external_port, protocol ) internal_client = HydrusNATPunch.GetLocalIP() HydrusNATPunch.AddUPnPMapping( internal_client, internal_port, external_port, protocol, description, duration = duration ) return True def publish_callable( result ): self._mappings_listctrl_panel.setEnabled( True ) self._RefreshMappings() self._mappings_listctrl_panel.setEnabled( False ) async_job = ClientGUIAsync.AsyncQtJob( self, work_callable, publish_callable ) async_job.start()
def __init__(self, controller, ui): self._controller = controller self._lock = threading.Lock() self._updater = ClientGUIAsync.FastThreadToGUIUpdater(ui, ui.SetDirty) self._title_text = '' self._status_text = '' self._status_subtext = '' self._controller.sub(self, 'SetTitleText', 'splash_set_title_text') self._controller.sub(self, 'SetText', 'splash_set_status_text') self._controller.sub(self, 'SetSubtext', 'splash_set_status_subtext')
def _DoAccountType(self): subject_account_keys = self._account_panel.GetCheckedAccountKeys() if len(subject_account_keys) == 0: QW.QMessageBox.information(self, 'Information', 'No accounts selected for action!') return service = self._service account_type = self._account_types_choice.GetValue() account_type_key = account_type.GetAccountTypeKey() def work_callable(): for subject_account_key in subject_account_keys: service.Request( HC.POST, 'modify_account_account_type', { 'subject_identifier': HydrusNetwork.AccountIdentifier( account_key=subject_account_key), 'account_type_key': account_type_key }) return 1 def publish_callable(gumpf): QW.QMessageBox.information(self, 'Information', 'Done!') self._account_panel.RefreshAccounts() self._DisableUIForJob('setting new account type\u2026') job = ClientGUIAsync.AsyncQtJob(self, work_callable, publish_callable) job.start()
def _Remove(self): text = 'Remove these port mappings?' text += os.linesep * 2 text += 'If a mapping does not disappear after a remove, it may be hard-added in the router\'s settings interface. In this case, you will have to go there to fix it.' result = ClientGUIDialogsQuick.GetYesNo(self, text, yes_label='do it', no_label='forget it') if result != QW.QDialog.Accepted: return selected_mappings = self._mappings_list.GetData(only_selected=True) def work_callable(): for selected_mapping in selected_mappings: (description, internal_ip, internal_port, external_port, protocol, duration) = selected_mapping HydrusNATPunch.RemoveUPnPMapping(external_port, protocol) return True def publish_callable(result): self._mappings_listctrl_panel.setEnabled(True) self._RefreshMappings() self._mappings_listctrl_panel.setEnabled(False) async_job = ClientGUIAsync.AsyncQtJob(self, work_callable, publish_callable) async_job.start()
def SetWindow(self, ui: FrameSplashPanel): self._updater = ClientGUIAsync.FastThreadToGUIUpdater(ui, ui.SetDirty)
def _RefreshMappings(self): def work_callable(): try: mappings = HydrusNATPunch.GetUPnPMappings() except Exception as e: HydrusData.ShowException(e) return e return mappings def publish_callable(result): if isinstance(result, Exception): e = result QP.CallAfter( QW.QMessageBox.critical, self, 'Error', 'Could not load mappings:' + os.linesep * 2 + str(e)) self._status_st.setText(str(e)) return self._mappings_listctrl_panel.setEnabled(True) mappings = result self._mappings_lookup = { (external_port, protocol) for (description, internal_ip, internal_port, external_port, protocol, duration) in mappings } self._mappings_list.SetData(mappings) self._status_st.clear() if self._external_ip is not None: self._status_st.setText(self._external_ip) elif not self._started_external_ip_fetch: self._started_external_ip_fetch = True self._RefreshExternalIP() self._status_st.setText('Refreshing mappings--please wait\u2026') self._mappings_list.SetData([]) self._mappings_listctrl_panel.setEnabled(False) async_job = ClientGUIAsync.AsyncQtJob(self, work_callable, publish_callable) async_job.start()
def _RefreshAccounts( self ): account_identifiers = self._account_identifiers service = self._service selected_account_keys = self.GetCheckedAccountKeys() def work_callable(): account_errors = set() account_keys_to_accounts = {} account_keys_to_account_info = {} for account_identifier in account_identifiers: try: result = service.Request( HC.GET, 'other_account', { 'subject_identifier' : account_identifier } ) except Exception as e: account_errors.add( str( e ) ) continue if 'account' in result: account = result[ 'account' ] account_key = account.GetAccountKey() if account_key in account_keys_to_accounts: continue account_keys_to_accounts[ account_key ] = account try: response = self._service.Request( HC.GET, 'account_info', { 'subject_identifier' : HydrusNetwork.AccountIdentifier( account_key = account_key ) } ) except Exception as e: HydrusData.PrintException( e ) continue account_string = str( response[ 'account_info' ] ) account_keys_to_account_info[ account_key ] = account_string return ( account_keys_to_accounts, account_keys_to_account_info, account_errors ) def publish_callable( result ): ( self._account_keys_to_accounts, self._account_keys_to_account_info, account_errors ) = result if len( account_errors ) > 0: account_errors = sorted( account_errors ) QW.QMessageBox.information( self, 'Information', 'Errors were encountered during account fetch:{}{}'.format( os.linesep * 2, os.linesep.join( account_errors ) ) ) if not self._done_first_fetch: # if we launched with CPU-expensive mapping identifiers, let's move to nice account keys for future refreshes self._account_identifiers = [ HydrusNetwork.AccountIdentifier( account_key = account_key ) for account_key in self._account_keys_to_accounts.keys() ] # account_keys_sorted = sorted( list( self._account_keys_to_accounts.keys() ), key = lambda sak: ( self._account_keys_to_accounts[ sak ].GetAccountType().GetTitle(), sak.hex() ) ) my_admin_account = self._service.GetAccount() my_admin_account_key = my_admin_account.GetAccountKey() for account_key in account_keys_sorted: item = QW.QListWidgetItem() item.setFlags( item.flags() | QC.Qt.ItemIsUserCheckable ) account = self._account_keys_to_accounts[ account_key ] text = account.GetSingleLineTitle() if account_key == my_admin_account_key: text = 'THIS IS YOU: {}'.format( text ) item.setText( text ) if not self._done_first_fetch or account_key in selected_account_keys: item.setCheckState( QC.Qt.Checked ) else: item.setCheckState( QC.Qt.Unchecked ) item.setData( QC.Qt.UserRole, account_key ) self._account_list.addItem( item ) # self._status_st.setVisible( False ) self._status_st.setText( '' ) if self._account_list.count() > 0: self._account_list.item( 0 ).setSelected( True ) self._AccountClicked() self._accounts_loaded = True self._done_first_fetch = True self.accountsFetchFinished.emit() self._status_st.setVisible( True ) self._status_st.setText( 'fetching accounts\u2026' ) self._accounts_loaded = False self._account_list.clear() self._account_info_box.clear() self._account_keys_to_accounts = {} self._account_keys_to_account_info = {} self.accountsFetchStarted.emit() job = ClientGUIAsync.AsyncQtJob( self, work_callable, publish_callable ) job.start()
def _DoBan( self ): subject_accounts = self._account_panel.GetCheckedAccounts() if len( subject_accounts ) == 0: QW.QMessageBox.information( self, 'Information', 'No accounts selected for action!' ) return some_are_banned = True in ( subject_account.IsBanned() for subject_account in subject_accounts ) if some_are_banned: message = 'Some of these selected accounts are already banned. Sure you want to overwrite the bans?' result = ClientGUIDialogsQuick.GetYesNo( self, message ) if result != QW.QDialog.Accepted: return subject_account_keys = [ subject_account.GetAccountKey() for subject_account in subject_accounts ] reason = self._ban_reason.text() if reason == '': QW.QMessageBox.information( self, 'Information', 'The ban reason is empty!' ) return message = 'Ban these user(s)? All of their pending petitions will be deleted serverside.' result = ClientGUIDialogsQuick.GetYesNo( self, message ) if result != QW.QDialog.Accepted: return expires = self._ban_expires.GetValue() if expires is not None: expires += HydrusData.GetNow() service = self._service def work_callable(): for subject_account_key in subject_account_keys: service.Request( HC.POST, 'modify_account_ban', { 'subject_identifier' : HydrusNetwork.AccountIdentifier( account_key = subject_account_key ), 'reason' : reason, 'expires' : expires } ) return 1 def publish_callable( gumpf ): QW.QMessageBox.information( self, 'Information', 'Done!' ) self._account_panel.RefreshAccounts() self._DisableUIForJob( 'banning\u2026' ) job = ClientGUIAsync.AsyncQtJob( self, work_callable, publish_callable ) job.start()
def MoveOrDuplicateLocalFiles( win: QW.QWidget, dest_service_key: bytes, action: int, media: typing.Collection[ ClientMedia.MediaSingleton ], source_service_key: typing.Optional[ bytes ] = None ): dest_service_name = HG.client_controller.services_manager.GetName( dest_service_key ) applicable_media = [ m for m in media if m.GetLocationsManager().IsLocal() and dest_service_key not in m.GetLocationsManager().GetCurrent() and m.GetMime() not in HC.HYDRUS_UPDATE_FILES ] if len( applicable_media ) == 0: return ( local_duplicable_to_file_service_keys, local_moveable_from_and_to_file_service_keys ) = GetLocalFileActionServiceKeys( media ) do_yes_no = True yes_no_text = 'Add {} files to {}?'.format( HydrusData.ToHumanInt( len( applicable_media ) ), dest_service_name ) if action == HC.CONTENT_UPDATE_MOVE: local_moveable_from_and_to_file_service_keys = { pair for pair in local_moveable_from_and_to_file_service_keys if pair[1] == dest_service_key } potential_source_service_keys = { pair[0] for pair in local_moveable_from_and_to_file_service_keys } potential_source_service_keys_to_applicable_media = collections.defaultdict( list ) for m in applicable_media: current = m.GetLocationsManager().GetCurrent() for potential_source_service_key in potential_source_service_keys: if potential_source_service_key in current: potential_source_service_keys_to_applicable_media[ potential_source_service_key ].append( m ) if source_service_key is None: if len( potential_source_service_keys ) == 0: return elif len( potential_source_service_keys ) == 1: ( source_service_key, ) = potential_source_service_keys else: do_yes_no = False num_applicable_media = len( applicable_media ) choice_tuples = [] for potential_source_service_key in potential_source_service_keys: potential_source_service_name = HG.client_controller.services_manager.GetName( potential_source_service_key ) text = 'move {} in "{}" to "{}"'.format( len( potential_source_service_keys_to_applicable_media[ potential_source_service_key ] ), potential_source_service_name, dest_service_name ) description = 'Move from {} to {}.'.format( potential_source_service_name, dest_service_name ) choice_tuples.append( ( text, potential_source_service_key, description ) ) choice_tuples.sort() try: source_service_key = ClientGUIDialogsQuick.SelectFromListButtons( win, 'select source service', choice_tuples, message = 'Select where we are moving from. Note this may not cover all files.' ) except HydrusExceptions.CancelledException: return source_service_name = HG.client_controller.services_manager.GetName( source_service_key ) applicable_media = potential_source_service_keys_to_applicable_media[ source_service_key ] yes_no_text = 'Move {} files from {} to {}?'.format( HydrusData.ToHumanInt( len( applicable_media ) ), source_service_name, dest_service_name ) if len( applicable_media ) == 0: return if do_yes_no: result = ClientGUIDialogsQuick.GetYesNo( win, yes_no_text ) if result != QW.QDialog.Accepted: return def work_callable(): job_key = ClientThreading.JobKey( cancellable = True ) title = 'moving files' if action == HC.CONTENT_UPDATE_MOVE else 'adding files' job_key.SetStatusTitle( title ) BLOCK_SIZE = 64 if len( applicable_media ) > BLOCK_SIZE: HG.client_controller.pub( 'message', job_key ) pauser = HydrusData.BigJobPauser() num_to_do = len( applicable_media ) now = HydrusData.GetNow() for ( i, block_of_media ) in enumerate( HydrusData.SplitListIntoChunks( applicable_media, BLOCK_SIZE ) ): if job_key.IsCancelled(): break job_key.SetVariable( 'popup_text_1', HydrusData.ConvertValueRangeToPrettyString( i * BLOCK_SIZE, num_to_do ) ) job_key.SetVariable( 'popup_gauge_1', ( i * BLOCK_SIZE, num_to_do ) ) content_updates = [] undelete_hashes = set() for m in block_of_media: if dest_service_key in m.GetLocationsManager().GetDeleted(): undelete_hashes.add( m.GetHash() ) else: content_updates.append( HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_ADD, ( m.GetMediaResult().GetFileInfoManager(), now ) ) ) if len( undelete_hashes ) > 0: content_updates.append( HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_UNDELETE, undelete_hashes ) ) HG.client_controller.WriteSynchronous( 'content_updates', { dest_service_key : content_updates } ) if action == HC.CONTENT_UPDATE_MOVE: block_of_hashes = [ m.GetHash() for m in block_of_media ] content_updates = [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_DELETE, block_of_hashes, reason = 'Moved to {}'.format( dest_service_name ) ) ] HG.client_controller.WriteSynchronous( 'content_updates', { source_service_key : content_updates } ) pauser.Pause() job_key.Delete() def publish_callable( result ): pass job = ClientGUIAsync.AsyncQtJob( win, work_callable, publish_callable ) job.start()