Version 133
This commit is contained in:
parent
72a2605d5b
commit
8585942d95
|
@ -8,6 +8,20 @@
|
|||
<div class="content">
|
||||
<h3>changelog</h3>
|
||||
<ul>
|
||||
<li><h3>version 133</h3></li>
|
||||
<ul>
|
||||
<li>reworked the add file process to correct file repository file counts</li>
|
||||
<li>made add file process to calculate inbox and local thumbnail count more efficiently</li>
|
||||
<li>fixed a critical bug in server db creation that was stopping file repository service from working</li>
|
||||
<li>added go/exit fullscreen options to fullscreen right click menu as alternative for default shortcut 'f'</li>
|
||||
<li>improved fullscreen position, size, maximised, and borderless state memory</li>
|
||||
<li>removed old 'fullscreen_borderless' option in local options</li>
|
||||
<li>thread checker now supports 8chan urls</li>
|
||||
<li>thread checker now has 'number of checks still to do' spin control so you have more options to fire and forget</li>
|
||||
<li>improved how the thread checker constructs and passes url information around</li>
|
||||
<li>improved some thread checker timing logic which _might_ have been causing problems</li>
|
||||
<li>improved some thread checker error reporting</li>
|
||||
</ul>
|
||||
<li><h3>version 132</h3></li>
|
||||
<ul>
|
||||
<li>merged two complicated serverside account tables into two simpler tables</li>
|
||||
|
@ -26,7 +40,7 @@
|
|||
<li>added 'copy account key' button to review services, which will now be the thing for users to use if they need an admin to modify their account</li>
|
||||
<li>fixed serverside credential verification for non-instantiated (still have a registration key) access keys</li>
|
||||
<li>added a bit of explaining text to the 'waiting' autocomplete state</li>
|
||||
<li>fixed a typo when deleting files from a file repo</li>
|
||||
<li>fixed a typo that caused errors when deleting files from a file repo</li>
|
||||
</ul>
|
||||
<li><h3>version 131</h3></li>
|
||||
<ul>
|
||||
|
|
|
@ -228,7 +228,6 @@ default_sort_by_choices.append( ( 'namespaces', [ 'creator', 'series', 'title',
|
|||
|
||||
CLIENT_DEFAULT_OPTIONS[ 'sort_by' ] = default_sort_by_choices
|
||||
CLIENT_DEFAULT_OPTIONS[ 'show_all_tags_in_autocomplete' ] = True
|
||||
CLIENT_DEFAULT_OPTIONS[ 'fullscreen_borderless' ] = True
|
||||
|
||||
CLIENT_DEFAULT_OPTIONS[ 'default_advanced_tag_options' ] = {}
|
||||
|
||||
|
@ -295,9 +294,11 @@ CLIENT_DEFAULT_OPTIONS[ 'pause_subs_sync' ] = False
|
|||
|
||||
client_size = {}
|
||||
|
||||
client_size[ 'gui_fullscreen' ] = False
|
||||
client_size[ 'gui_maximised' ] = True
|
||||
client_size[ 'gui_restored_size' ] = [ 640, 480 ]
|
||||
client_size[ 'gui_restored_position' ] = [ 20, 20 ]
|
||||
client_size[ 'fs_fullscreen' ] = True
|
||||
client_size[ 'fs_maximised' ] = True
|
||||
client_size[ 'fs_restored_size' ] = [ 640, 480 ]
|
||||
client_size[ 'fs_restored_position' ] = [ 20, 20 ]
|
||||
|
|
|
@ -1270,42 +1270,43 @@ class TagDB( object ):
|
|||
|
||||
class ServiceDB( FileDB, MessageDB, TagDB, RatingDB ):
|
||||
|
||||
def _AddFiles( self, c, files_info_rows ):
|
||||
def _AddFile( self, c, service_id, hash_id, size, mime, timestamp, width, height, duration, num_frames, num_words ):
|
||||
|
||||
# service_id, hash_id, size, mime, timestamp, width, height, duration, num_frames, num_words
|
||||
result = c.execute( 'SELECT 1 FROM files_info WHERE service_id = ? AND hash_id = ?;', ( service_id, hash_id ) ).fetchone()
|
||||
|
||||
c.executemany( 'INSERT OR IGNORE INTO files_info VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ? );', files_info_rows )
|
||||
|
||||
service_ids_to_rows = HC.BuildKeyToListDict( [ ( row[ 0 ], row[ 1: ] ) for row in files_info_rows ] )
|
||||
|
||||
for ( service_id, rows ) in service_ids_to_rows.items():
|
||||
if result is None:
|
||||
|
||||
hash_ids = [ row[ 0 ] for row in rows ]
|
||||
|
||||
splayed_hash_ids = HC.SplayListForDB( hash_ids )
|
||||
|
||||
c.execute( 'DELETE FROM deleted_files WHERE service_id = ? AND hash_id IN ' + splayed_hash_ids + ';', ( service_id, ) )
|
||||
|
||||
num_deleted_files_rescinded = self._GetRowCount( c )
|
||||
|
||||
c.execute( 'DELETE FROM file_transfers WHERE service_id = ? AND hash_id IN ' + splayed_hash_ids + ';', ( service_id, ) )
|
||||
|
||||
total_size = sum( [ row[ 1 ] for row in rows ] )
|
||||
num_files = len( rows )
|
||||
num_thumbnails = len( [ 1 for row in rows if row[ 2 ] in HC.MIMES_WITH_THUMBNAILS ] )
|
||||
c.execute( 'INSERT OR IGNORE INTO files_info VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ? );', ( service_id, hash_id, size, mime, timestamp, width, height, duration, num_frames, num_words ) )
|
||||
|
||||
service_info_updates = []
|
||||
|
||||
service_info_updates.append( ( total_size, service_id, HC.SERVICE_INFO_TOTAL_SIZE ) )
|
||||
service_info_updates.append( ( num_files, service_id, HC.SERVICE_INFO_NUM_FILES ) )
|
||||
service_info_updates.append( ( num_thumbnails, service_id, HC.SERVICE_INFO_NUM_THUMBNAILS ) )
|
||||
service_info_updates.append( ( -num_deleted_files_rescinded, service_id, HC.SERVICE_INFO_NUM_DELETED_FILES ) )
|
||||
result = c.execute( 'SELECT 1 FROM deleted_files WHERE service_id = ? AND hash_id = ?;', ( service_id, hash_id ) ).fetchone()
|
||||
|
||||
if result is not None:
|
||||
|
||||
c.execute( 'DELETE FROM deleted_files WHERE service_id = ? AND hash_id = ?;', ( service_id, hash_id ) )
|
||||
|
||||
service_info_updates.append( ( -1, service_id, HC.SERVICE_INFO_NUM_DELETED_FILES ) )
|
||||
|
||||
|
||||
if service_id != self._local_file_service_id:
|
||||
|
||||
result = c.execute( 'SELECT 1 FROM file_inbox WHERE hash_id = ?;', ( hash_id, ) ).fetchone()
|
||||
|
||||
if result is not None: service_info_updates.append( ( 1, service_id, HC.SERVICE_INFO_NUM_INBOX ) )
|
||||
|
||||
|
||||
service_info_updates.append( ( size, service_id, HC.SERVICE_INFO_TOTAL_SIZE ) )
|
||||
service_info_updates.append( ( 1, service_id, HC.SERVICE_INFO_NUM_FILES ) )
|
||||
if mime in HC.MIMES_WITH_THUMBNAILS: service_info_updates.append( ( 1, service_id, HC.SERVICE_INFO_NUM_THUMBNAILS ) )
|
||||
|
||||
c.executemany( 'UPDATE service_info SET info = info + ? WHERE service_id = ? AND info_type = ?;', service_info_updates )
|
||||
|
||||
c.execute( 'DELETE FROM service_info WHERE service_id = ? AND info_type IN ' + HC.SplayListForDB( ( HC.SERVICE_INFO_NUM_INBOX, HC.SERVICE_INFO_NUM_THUMBNAILS_LOCAL ) ) + ';', ( service_id, ) )
|
||||
c.execute( 'DELETE FROM file_transfers WHERE service_id = ? AND hash_id = ? ;', ( service_id, hash_id ) )
|
||||
|
||||
self._UpdateAutocompleteTagCacheFromFiles( c, service_id, hash_ids, 1 )
|
||||
if mime in HC.MIMES_WITH_THUMBNAILS: c.execute( 'DELETE FROM service_info WHERE service_id = ? AND info_type = ?;', ( service_id, HC.SERVICE_INFO_NUM_THUMBNAILS_LOCAL ) )
|
||||
|
||||
self._UpdateAutocompleteTagCacheFromFiles( c, service_id, ( hash_id, ), 1 )
|
||||
|
||||
|
||||
|
||||
|
@ -3081,9 +3082,7 @@ class ServiceDB( FileDB, MessageDB, TagDB, RatingDB ):
|
|||
self._AddThumbnails( c, [ ( hash, thumbnail ) ] )
|
||||
|
||||
|
||||
files_info_rows = [ ( self._local_file_service_id, hash_id, size, mime, timestamp, width, height, duration, num_frames, num_words ) ]
|
||||
|
||||
self._AddFiles( c, files_info_rows )
|
||||
self._AddFile( c, self._local_file_service_id, hash_id, size, mime, timestamp, width, height, duration, num_frames, num_words )
|
||||
|
||||
content_update = HC.ContentUpdate( HC.CONTENT_DATA_TYPE_FILES, HC.CONTENT_UPDATE_ADD, ( hash, size, mime, timestamp, width, height, duration, num_frames, num_words ) )
|
||||
|
||||
|
@ -3182,9 +3181,7 @@ class ServiceDB( FileDB, MessageDB, TagDB, RatingDB ):
|
|||
|
||||
hash_id = self._GetHashId( c, hash )
|
||||
|
||||
file_info_row = ( service_id, hash_id, size, mime, timestamp, width, height, duration, num_frames, num_words )
|
||||
|
||||
self._AddFiles( c, ( file_info_row, ) )
|
||||
self._AddFile( c, service_id, hash_id, size, mime, timestamp, width, height, duration, num_frames, num_words )
|
||||
|
||||
notify_new_thumbnails = True
|
||||
|
||||
|
@ -5309,6 +5306,25 @@ class DB( ServiceDB ):
|
|||
|
||||
|
||||
|
||||
if version == 132:
|
||||
|
||||
c.execute( 'DELETE FROM service_info WHERE info_type = ?;', ( HC.SERVICE_INFO_NUM_FILES, ) )
|
||||
|
||||
#
|
||||
|
||||
( HC.options, ) = c.execute( 'SELECT options FROM options;' ).fetchone()
|
||||
|
||||
client_size = HC.options[ 'client_size' ]
|
||||
|
||||
client_size[ 'fs_fullscreen' ] = True
|
||||
|
||||
client_size[ 'gui_fullscreen' ] = False
|
||||
|
||||
del HC.options[ 'fullscreen_borderless' ]
|
||||
|
||||
c.execute( 'UPDATE options SET options = ?;', ( HC.options, ) )
|
||||
|
||||
|
||||
c.execute( 'UPDATE version SET version = ?;', ( version + 1, ) )
|
||||
|
||||
HC.is_db_updated = True
|
||||
|
|
|
@ -879,11 +879,6 @@ class CanvasFullscreenMediaList( ClientGUIMixins.ListeningMediaList, Canvas, Cli
|
|||
|
||||
self.Show( True )
|
||||
|
||||
if self.IsMaximized() and HC.options[ 'fullscreen_borderless' ]:
|
||||
|
||||
self.ShowFullScreen( True, wx.FULLSCREEN_ALL )
|
||||
|
||||
|
||||
HC.app.SetTopWindow( self )
|
||||
|
||||
self._timer_cursor_hide = wx.Timer( self, id = ID_TIMER_CURSOR_HIDE )
|
||||
|
@ -1637,6 +1632,11 @@ class CanvasFullscreenMediaListBrowser( CanvasFullscreenMediaList ):
|
|||
menu.AppendMenu( CC.ID_NULL, 'start slideshow', slideshow )
|
||||
if self._timer_slideshow.IsRunning(): menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'slideshow_pause_play' ), 'stop slideshow' )
|
||||
|
||||
menu.AppendSeparator()
|
||||
|
||||
if self.IsFullScreen(): menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'fullscreen_switch' ), 'exit fullscreen' )
|
||||
else: menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'fullscreen_switch' ), 'go fullscreen' )
|
||||
|
||||
self._menu_open = True
|
||||
|
||||
self.PopupMenu( menu )
|
||||
|
@ -1991,10 +1991,10 @@ class CanvasFullscreenMediaListCustomFilter( CanvasFullscreenMediaList ):
|
|||
|
||||
copy_menu = wx.Menu()
|
||||
|
||||
copy_menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'copy_files' ) , 'file' )
|
||||
copy_menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'copy_hash' ) , 'hash' )
|
||||
copy_menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'copy_path' ) , 'path' )
|
||||
copy_menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'copy_local_url' ) , 'local url' )
|
||||
copy_menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'copy_files' ), 'file' )
|
||||
copy_menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'copy_hash' ), 'hash' )
|
||||
copy_menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'copy_path' ), 'path' )
|
||||
copy_menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'copy_local_url' ), 'local url' )
|
||||
|
||||
share_menu.AppendMenu( CC.ID_NULL, 'copy', copy_menu )
|
||||
|
||||
|
@ -2002,6 +2002,9 @@ class CanvasFullscreenMediaListCustomFilter( CanvasFullscreenMediaList ):
|
|||
|
||||
menu.AppendSeparator()
|
||||
|
||||
if self.IsFullScreen(): menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'fullscreen_switch' ), 'exit fullscreen' )
|
||||
else: menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'fullscreen_switch' ), 'go fullscreen' )
|
||||
|
||||
self._menu_open = True
|
||||
|
||||
self.PopupMenu( menu )
|
||||
|
@ -2758,11 +2761,6 @@ class RatingsFilterFrameNumerical( ClientGUICommon.FrameThatResizes ):
|
|||
|
||||
self.Show( True )
|
||||
|
||||
if self.IsMaximized() and HC.options[ 'fullscreen_borderless' ]:
|
||||
|
||||
self.ShowFullScreen( True, wx.FULLSCREEN_ALL )
|
||||
|
||||
|
||||
HC.app.SetTopWindow( self )
|
||||
|
||||
self._left_window = self._Panel( self._splitter )
|
||||
|
|
|
@ -1332,29 +1332,25 @@ class FrameThatResizes( Frame ):
|
|||
|
||||
Frame.__init__( self, *args, **kwargs )
|
||||
|
||||
self._InitialiseSizeAndPosition()
|
||||
|
||||
self.Bind( wx.EVT_SIZE, self.EventSpecialResize )
|
||||
self.Bind( wx.EVT_MOVE, self.EventSpecialMove )
|
||||
|
||||
|
||||
def _InitialiseSizeAndPosition( self ):
|
||||
|
||||
client_size = HC.options[ 'client_size' ]
|
||||
|
||||
self.SetInitialSize( client_size[ self._resize_option_prefix + 'restored_size' ] )
|
||||
|
||||
self.SetMinSize( ( 480, 360 ) )
|
||||
|
||||
self._TryToSetPosition()
|
||||
|
||||
if client_size[ self._resize_option_prefix + 'maximised' ]: self.Maximize()
|
||||
|
||||
self.Bind( wx.EVT_SIZE, self.EventSpecialResize )
|
||||
self.Bind( wx.EVT_MOVE_END, self.EventSpecialMoveEnd )
|
||||
|
||||
|
||||
def _TryToSetPosition( self ):
|
||||
|
||||
client_size = HC.options[ 'client_size' ]
|
||||
|
||||
position = client_size[ self._resize_option_prefix + 'restored_position' ]
|
||||
|
||||
display_index = wx.Display.GetFromPoint( position )
|
||||
|
||||
if display_index == wx.NOT_FOUND: client_size[ self._resize_option_prefix + 'restored_position' ] = [ 20, 20 ]
|
||||
if display_index == wx.NOT_FOUND: client_size[ self._resize_option_prefix + 'restored_position' ] = ( 20, 20 )
|
||||
else:
|
||||
|
||||
display = wx.Display( display_index )
|
||||
|
@ -1366,46 +1362,48 @@ class FrameThatResizes( Frame ):
|
|||
x_bad = p_x < geometry.x or p_x > geometry.x + geometry.width
|
||||
y_bad = p_y < geometry.y or p_y > geometry.y + geometry.height
|
||||
|
||||
if x_bad or y_bad: client_size[ self._resize_option_prefix + 'restored_position' ] = [ 20, 20 ]
|
||||
if x_bad or y_bad: client_size[ self._resize_option_prefix + 'restored_position' ] = ( 20, 20 )
|
||||
|
||||
|
||||
self.SetPosition( client_size[ self._resize_option_prefix + 'restored_position' ] )
|
||||
|
||||
if client_size[ self._resize_option_prefix + 'maximised' ]: self.Maximize()
|
||||
|
||||
if client_size[ self._resize_option_prefix + 'fullscreen' ]: wx.CallAfter( self.ShowFullScreen, True, wx.FULLSCREEN_ALL )
|
||||
|
||||
|
||||
def EventSpecialMoveEnd( self, event ):
|
||||
def _RecordSizeAndPosition( self ):
|
||||
|
||||
client_size = HC.options[ 'client_size' ]
|
||||
|
||||
client_size[ self._resize_option_prefix + 'restored_position' ] = list( self.GetPosition() )
|
||||
client_size[ self._resize_option_prefix + 'maximised' ] = self.IsMaximized()
|
||||
client_size[ self._resize_option_prefix + 'fullscreen' ] = self.IsFullScreen()
|
||||
|
||||
if not ( self.IsMaximized() or self.IsFullScreen() ):
|
||||
|
||||
# when dragging window up to be maximised, reported position is sometimes a bit dodgy
|
||||
|
||||
display_index = wx.Display.GetFromPoint( self.GetPosition() )
|
||||
|
||||
if display_index != wx.NOT_FOUND:
|
||||
|
||||
client_size[ self._resize_option_prefix + 'restored_size' ] = tuple( self.GetSize() )
|
||||
|
||||
client_size[ self._resize_option_prefix + 'restored_position' ] = tuple( self.GetPosition() )
|
||||
|
||||
|
||||
|
||||
|
||||
def EventSpecialMove( self, event ):
|
||||
|
||||
self._RecordSizeAndPosition()
|
||||
|
||||
event.Skip()
|
||||
|
||||
|
||||
def EventSpecialResize( self, event ):
|
||||
|
||||
client_size = HC.options[ 'client_size' ]
|
||||
|
||||
if self.IsMaximized() or self.IsFullScreen():
|
||||
|
||||
client_size[ self._resize_option_prefix + 'maximised' ] = True
|
||||
|
||||
else:
|
||||
|
||||
if client_size[ self._resize_option_prefix + 'maximised' ]: # we have just restored, so set size
|
||||
|
||||
self.SetSize( client_size[ self._resize_option_prefix + 'restored_size' ] )
|
||||
|
||||
self._TryToSetPosition()
|
||||
|
||||
else: # we have resized manually, so set new size
|
||||
|
||||
client_size[ self._resize_option_prefix + 'restored_size' ] = list( self.GetSize() )
|
||||
|
||||
client_size[ self._resize_option_prefix + 'restored_position' ] = list( self.GetPosition() )
|
||||
|
||||
|
||||
client_size[ self._resize_option_prefix + 'maximised' ] = False
|
||||
|
||||
self._RecordSizeAndPosition()
|
||||
|
||||
event.Skip()
|
||||
|
||||
|
|
|
@ -2853,8 +2853,6 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ):
|
|||
|
||||
self._default_tag_repository = ClientGUICommon.BetterChoice( self._gui_page )
|
||||
|
||||
self._fullscreen_borderless = wx.CheckBox( self._gui_page )
|
||||
|
||||
self._listbook.AddPage( self._gui_page, 'gui' )
|
||||
|
||||
# sound
|
||||
|
@ -3083,8 +3081,6 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ):
|
|||
|
||||
self._default_tag_repository.SelectClientData( default_tag_repository_key )
|
||||
|
||||
self._fullscreen_borderless.SetValue( HC.options[ 'fullscreen_borderless' ] )
|
||||
|
||||
#
|
||||
|
||||
self._play_dumper_noises.SetValue( HC.options[ 'play_dumper_noises' ] )
|
||||
|
@ -3278,9 +3274,6 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ):
|
|||
gridbox.AddF( wx.StaticText( self._gui_page, label = 'By default, search non-local tags in write-autocomplete: ' ), FLAGS_MIXED )
|
||||
gridbox.AddF( self._gui_show_all_tags_in_autocomplete, FLAGS_MIXED )
|
||||
|
||||
gridbox.AddF( wx.StaticText( self._gui_page, label = 'By default, show fullscreen without borders: ' ), FLAGS_MIXED )
|
||||
gridbox.AddF( self._fullscreen_borderless, FLAGS_MIXED )
|
||||
|
||||
self._gui_page.SetSizer( gridbox )
|
||||
|
||||
#
|
||||
|
@ -3721,7 +3714,6 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ):
|
|||
HC.options[ 'confirm_client_exit' ] = self._confirm_client_exit.GetValue()
|
||||
HC.options[ 'gui_capitalisation' ] = self._gui_capitalisation.GetValue()
|
||||
HC.options[ 'show_all_tags_in_autocomplete' ] = self._gui_show_all_tags_in_autocomplete.GetValue()
|
||||
HC.options[ 'fullscreen_borderless' ] = self._fullscreen_borderless.GetValue()
|
||||
|
||||
HC.options[ 'export_path' ] = HC.ConvertAbsPathToPortablePath( self._export_location.GetPath() )
|
||||
HC.options[ 'default_sort' ] = self._default_sort.GetSelection()
|
||||
|
|
|
@ -1665,9 +1665,13 @@ class ManagementPanelImportThreadWatcher( ManagementPanelImport ):
|
|||
|
||||
self._thread_info = wx.StaticText( self._thread_panel, label = 'enter a 4chan thread url' )
|
||||
|
||||
self._thread_time = wx.SpinCtrl( self._thread_panel, min = 30, max = 1800 )
|
||||
self._thread_times_to_check = wx.SpinCtrl( self._thread_panel, size = ( 60, -1 ), min = 0, max = 100 )
|
||||
self._thread_times_to_check.SetValue( 5 )
|
||||
self._thread_times_to_check.Bind( wx.EVT_SPINCTRL, self.EventThreadVariable )
|
||||
|
||||
self._thread_time = wx.SpinCtrl( self._thread_panel, size = ( 100, -1 ), min = 30, max = 86400 )
|
||||
self._thread_time.SetValue( 180 )
|
||||
self._thread_time.Bind( wx.EVT_SPINCTRL, self.EventThreadTime )
|
||||
self._thread_time.Bind( wx.EVT_SPINCTRL, self.EventThreadVariable )
|
||||
|
||||
self._thread_input = wx.TextCtrl( self._thread_panel, style = wx.TE_PROCESS_ENTER )
|
||||
self._thread_input.Bind( wx.EVT_KEY_DOWN, self.EventKeyDown )
|
||||
|
@ -1677,7 +1681,9 @@ class ManagementPanelImportThreadWatcher( ManagementPanelImport ):
|
|||
|
||||
hbox = wx.BoxSizer( wx.HORIZONTAL )
|
||||
|
||||
hbox.AddF( wx.StaticText( self._thread_panel, label = 'check every ' ), FLAGS_MIXED )
|
||||
hbox.AddF( wx.StaticText( self._thread_panel, label = 'check ' ), FLAGS_MIXED )
|
||||
hbox.AddF( self._thread_times_to_check, FLAGS_MIXED )
|
||||
hbox.AddF( wx.StaticText( self._thread_panel, label = ' more times, every ' ), FLAGS_MIXED )
|
||||
hbox.AddF( self._thread_time, FLAGS_MIXED )
|
||||
hbox.AddF( wx.StaticText( self._thread_panel, label = ' seconds' ), FLAGS_MIXED )
|
||||
|
||||
|
@ -1695,13 +1701,15 @@ class ManagementPanelImportThreadWatcher( ManagementPanelImport ):
|
|||
vbox.AddF( self._advanced_tag_options, FLAGS_EXPAND_PERPENDICULAR )
|
||||
|
||||
|
||||
def _SetThreadTime( self ):
|
||||
def _SetThreadVariables( self ):
|
||||
|
||||
import_queue_job_key = self._import_controller.GetJobKey( 'import_queue' )
|
||||
|
||||
thread_time = self._thread_time.GetValue()
|
||||
thread_times_to_check = self._thread_times_to_check.GetValue()
|
||||
|
||||
import_queue_job_key.SetVariable( 'thread_time', thread_time )
|
||||
import_queue_job_key.SetVariable( 'thread_times_to_check', thread_times_to_check )
|
||||
|
||||
|
||||
def _UpdateGUI( self ):
|
||||
|
@ -1736,11 +1744,23 @@ class ManagementPanelImportThreadWatcher( ManagementPanelImport ):
|
|||
|
||||
else: self._thread_pause_button.Disable()
|
||||
|
||||
# times to check
|
||||
|
||||
try:
|
||||
|
||||
thread_times_to_check = import_queue_job_key.GetVariable( 'thread_times_to_check' )
|
||||
|
||||
self._thread_times_to_check.SetValue( thread_times_to_check )
|
||||
|
||||
except: self._SetThreadVariables()
|
||||
|
||||
|
||||
def EventKeyDown( self, event ):
|
||||
|
||||
if event.KeyCode in ( wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER ):
|
||||
|
||||
self._SetThreadVariables()
|
||||
|
||||
url = self._thread_input.GetValue()
|
||||
|
||||
if url == '': return
|
||||
|
@ -1759,31 +1779,59 @@ class ManagementPanelImportThreadWatcher( ManagementPanelImport ):
|
|||
|
||||
except: raise Exception ( 'Could not understand that url!' )
|
||||
|
||||
if host is None or '4chan.org' not in host: raise Exception( 'This only works for 4chan right now!' )
|
||||
is_4chan = '4chan.org' in host
|
||||
is_8chan = '8chan.co' in host
|
||||
|
||||
if not ( is_4chan or is_8chan ): raise Exception( 'This only works for 4chan right now!' )
|
||||
|
||||
try:
|
||||
|
||||
# 4chan
|
||||
# /asp/thread/382059/post-your-favourite-martial-arts-video-if-martin
|
||||
# http://a.4cdn.org/asp/thread/382059.json
|
||||
# http://i.4cdn.org/asp/ for images
|
||||
|
||||
( board, rest_of_request ) = request[1:].split( '/thread/', 1 )
|
||||
# 8chan
|
||||
# /v/res/406061.html
|
||||
# http://8chan.co/v/res/406061.json
|
||||
# http://8chan.co/v/src/ for images
|
||||
|
||||
if '/' in rest_of_request: ( thread_id, gumpf ) = rest_of_request.split( '/' )
|
||||
else: thread_id = rest_of_request
|
||||
if is_4chan:
|
||||
|
||||
( board, rest_of_request ) = request[1:].split( '/thread/', 1 )
|
||||
|
||||
if '/' in rest_of_request: ( thread_id, gumpf ) = rest_of_request.split( '/' )
|
||||
else: thread_id = rest_of_request
|
||||
|
||||
json_url = 'http://a.4cdn.org/' + board + '/thread/' + thread_id + '.json'
|
||||
image_base = 'http://i.4cdn.org/' + board + '/'
|
||||
|
||||
elif is_8chan:
|
||||
|
||||
( board, rest_of_request ) = request[1:].split( '/res/', 1 )
|
||||
|
||||
json_url = url[:-4] + 'json'
|
||||
image_base = 'http://8chan.co/' + board + '/src/'
|
||||
|
||||
|
||||
except: raise Exception( 'Could not understand the board or thread id!' )
|
||||
|
||||
except Exception as e:
|
||||
|
||||
self._thread_info.SetLabel( HC.u( e ) )
|
||||
import_queue_job_key = self._import_controller.GetJobKey( 'import_queue' )
|
||||
|
||||
import_queue_job_key.SetVariable( 'status', HC.u( e ) )
|
||||
|
||||
HC.ShowException( e )
|
||||
|
||||
return
|
||||
|
||||
|
||||
self._thread_input.Disable()
|
||||
|
||||
self._SetThreadTime()
|
||||
self._SetThreadVariables()
|
||||
|
||||
self._import_controller.PendImportQueue( ( board, thread_id ) )
|
||||
self._import_controller.PendImportQueue( ( json_url, image_base ) )
|
||||
|
||||
else: event.Skip()
|
||||
|
||||
|
@ -1797,7 +1845,7 @@ class ManagementPanelImportThreadWatcher( ManagementPanelImport ):
|
|||
self._UpdateGUI()
|
||||
|
||||
|
||||
def EventThreadTime( self, event ): self._SetThreadTime()
|
||||
def EventThreadVariable( self, event ): self._SetThreadVariables()
|
||||
|
||||
def GetAdvancedTagOptions( self ): return self._advanced_tag_options.GetInfo()
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ options = {}
|
|||
# Misc
|
||||
|
||||
NETWORK_VERSION = 15
|
||||
SOFTWARE_VERSION = 132
|
||||
SOFTWARE_VERSION = 133
|
||||
|
||||
UNSCALED_THUMBNAIL_DIMENSIONS = ( 200, 200 )
|
||||
|
||||
|
|
|
@ -1234,12 +1234,7 @@ class ImportArgsGeneratorThread( ImportArgsGenerator ):
|
|||
|
||||
self._job_key.SetVariable( 'status', 'downloading' )
|
||||
|
||||
( md5, board, image_name, ext, filename ) = self._item
|
||||
|
||||
# where do I get 4chan_board from? is it set to the controller_job_key?
|
||||
# that'd prob be the best place, but think about it
|
||||
|
||||
url = 'http://images.4chan.org/' + board + '/src/' + image_name + ext
|
||||
( md5, image_url, filename ) = self._item
|
||||
|
||||
def hook( range, value ):
|
||||
|
||||
|
@ -1247,20 +1242,20 @@ class ImportArgsGeneratorThread( ImportArgsGenerator ):
|
|||
self._job_key.SetVariable( 'value', value )
|
||||
|
||||
|
||||
temp_path = HC.http.Request( HC.GET, url, report_hooks = [ hook ], response_to_path = True )
|
||||
temp_path = HC.http.Request( HC.GET, image_url, report_hooks = [ hook ], response_to_path = True )
|
||||
|
||||
tags = [ 'filename:' + filename + ext ]
|
||||
tags = [ 'filename:' + filename ]
|
||||
|
||||
service_keys_to_tags = ConvertTagsToServiceKeysToTags( tags, self._advanced_tag_options )
|
||||
|
||||
return ( url, temp_path, service_keys_to_tags, url )
|
||||
return ( image_url, temp_path, service_keys_to_tags, image_url )
|
||||
|
||||
|
||||
def _CheckCurrentStatus( self ):
|
||||
|
||||
self._job_key.SetVariable( 'status', 'checking md5 status' )
|
||||
|
||||
( md5, board, image_name, ext, filename ) = self._item
|
||||
( md5, image_url, filename ) = self._item
|
||||
|
||||
( status, hash ) = HC.app.Read( 'md5_status', md5 )
|
||||
|
||||
|
@ -1684,13 +1679,31 @@ class ImportQueueGeneratorThread( ImportQueueGenerator ):
|
|||
|
||||
try:
|
||||
|
||||
( board, thread_id ) = self._item
|
||||
( json_url, image_base ) = self._item
|
||||
|
||||
last_thread_check = 0
|
||||
image_infos_already_added = set()
|
||||
|
||||
while True:
|
||||
first_run = True
|
||||
|
||||
while True:
|
||||
|
||||
if not first_run:
|
||||
|
||||
thread_times_to_check = self._job_key.GetVariable( 'thread_times_to_check' )
|
||||
|
||||
while thread_times_to_check == 0:
|
||||
|
||||
self._job_key.SetVariable( 'status', 'checking is finished' )
|
||||
|
||||
time.sleep( 1 )
|
||||
|
||||
if self._job_key.IsCancelled(): break
|
||||
|
||||
thread_times_to_check = self._job_key.GetVariable( 'thread_times_to_check' )
|
||||
|
||||
|
||||
|
||||
if self._job_key.IsPaused():
|
||||
|
||||
self._job_key.SetVariable( 'status', 'paused' )
|
||||
|
@ -1710,17 +1723,26 @@ class ImportQueueGeneratorThread( ImportQueueGenerator ):
|
|||
|
||||
self._job_key.SetVariable( 'status', 'checking thread' )
|
||||
|
||||
url = 'http://a.4cdn.org/' + board + '/thread/' + thread_id + '.json'
|
||||
|
||||
try:
|
||||
|
||||
raw_json = HC.http.Request( HC.GET, url )
|
||||
raw_json = HC.http.Request( HC.GET, json_url )
|
||||
|
||||
json_dict = json.loads( raw_json )
|
||||
|
||||
posts_list = json_dict[ 'posts' ]
|
||||
|
||||
image_infos = [ ( post[ 'md5' ].decode( 'base64' ), board, HC.u( post[ 'tim' ] ), post[ 'ext' ], post[ 'filename' ] ) for post in posts_list if 'md5' in post ]
|
||||
image_infos = []
|
||||
|
||||
for post in posts_list:
|
||||
|
||||
if 'md5' not in post: continue
|
||||
|
||||
image_md5 = post[ 'md5' ].decode( 'base64' )
|
||||
image_url = image_base + HC.u( post[ 'tim' ] ) + post[ 'ext' ]
|
||||
image_original_filename = post[ 'filename' ] + post[ 'ext' ]
|
||||
|
||||
image_infos.append( ( image_md5, image_url, image_original_filename ) )
|
||||
|
||||
|
||||
image_infos_i_can_add = [ image_info for image_info in image_infos if image_info not in image_infos_already_added ]
|
||||
|
||||
|
@ -1741,8 +1763,15 @@ class ImportQueueGeneratorThread( ImportQueueGenerator ):
|
|||
|
||||
last_thread_check = HC.GetNow()
|
||||
|
||||
if first_run: first_run = False
|
||||
else:
|
||||
|
||||
if thread_times_to_check > 0: self._job_key.SetVariable( 'thread_times_to_check', thread_times_to_check - 1 )
|
||||
|
||||
|
||||
else: self._job_key.SetVariable( 'status', 'rechecking thread ' + HC.ConvertTimestampToPrettyPending( next_thread_check ) )
|
||||
|
||||
time.sleep( 0.1 )
|
||||
|
||||
|
||||
except Exception as e:
|
||||
|
|
|
@ -2029,11 +2029,14 @@ class DB( ServiceDB ):
|
|||
|
||||
hex_chars = '0123456789abcdef'
|
||||
|
||||
for ( one, two ) in itertools.product( hex_chars, hex_chars ):
|
||||
for dir in dirs:
|
||||
|
||||
new_dir = dir + os.path.sep + one + two
|
||||
|
||||
if not os.path.exists( new_dir ): os.mkdir( new_dir )
|
||||
for ( one, two ) in itertools.product( hex_chars, hex_chars ):
|
||||
|
||||
new_dir = dir + os.path.sep + one + two
|
||||
|
||||
if not os.path.exists( new_dir ): os.mkdir( new_dir )
|
||||
|
||||
|
||||
|
||||
( db, c ) = self._GetDBCursor()
|
||||
|
@ -2408,6 +2411,23 @@ class DB( ServiceDB ):
|
|||
|
||||
|
||||
|
||||
if version == 132:
|
||||
|
||||
dirs = ( HC.SERVER_FILES_DIR, HC.SERVER_THUMBNAILS_DIR, HC.SERVER_MESSAGES_DIR )
|
||||
|
||||
hex_chars = '0123456789abcdef'
|
||||
|
||||
for dir in dirs:
|
||||
|
||||
for ( one, two ) in itertools.product( hex_chars, hex_chars ):
|
||||
|
||||
new_dir = dir + os.path.sep + one + two
|
||||
|
||||
if not os.path.exists( new_dir ): os.mkdir( new_dir )
|
||||
|
||||
|
||||
|
||||
|
||||
c.execute( 'UPDATE version SET version = ?;', ( version + 1, ) )
|
||||
|
||||
|
||||
|
|
|
@ -1152,4 +1152,56 @@ class TestServerDB( unittest.TestCase ):
|
|||
HC.SERVER_FILES_DIR = self._old_server_files_dir
|
||||
HC.SERVER_THUMBNAILS_DIR = self._old_server_thumbnails_dir
|
||||
|
||||
|
||||
|
||||
# add read and write funcs like with client db
|
||||
|
||||
def _test_account_creation( self ):
|
||||
|
||||
# create rkeys
|
||||
# create akeys
|
||||
# test successive rkey fetch gives new akeys
|
||||
# get session with akey
|
||||
# make sure rkey is now dead
|
||||
|
||||
pass
|
||||
|
||||
|
||||
def _test_content_creation( self ):
|
||||
|
||||
# create some tag and hashes business, try uploading a file, and test that
|
||||
|
||||
# fetch content update, test it. I think that works
|
||||
|
||||
pass
|
||||
|
||||
|
||||
def _test_init_server_admin( self ):
|
||||
|
||||
# do it, however it works
|
||||
|
||||
pass
|
||||
|
||||
|
||||
def _test_service_creation( self ):
|
||||
|
||||
# add tag, add file repo
|
||||
|
||||
# fetch service info or whatever to test
|
||||
|
||||
# change the port
|
||||
|
||||
# fetch service info or whatever to test
|
||||
|
||||
pass
|
||||
|
||||
|
||||
def test_server( self ):
|
||||
|
||||
self._test_init_server_admin()
|
||||
|
||||
self._test_service_creation()
|
||||
|
||||
self._test_account_creation()
|
||||
|
||||
self._test_content_creation()
|
||||
|
||||
|
|
Loading…
Reference in New Issue