class ComicReadingList(EventDispatcher): # ids = DictProperty({}) name = StringProperty() comics = ListProperty() data = DictProperty() slug = StringProperty() comic_db = ObjectProperty() comic_json = ListProperty() cb_only_read_active = BooleanProperty(False) cb_only_read_active = BooleanProperty(False) cb_purge_active = BooleanProperty(False) cb_optimize_size_active = BooleanProperty(False) cb_limit_active = BooleanProperty(False) limit_num = NumericProperty(25) sw_syn_this_active = BooleanProperty(False) comic_db_in = BooleanProperty(False) db = ObjectProperty() comics_loaded = ObjectProperty(False) last_comic_read = NumericProperty() start_last_sync_num = NumericProperty(0) end_last_sync_num = NumericProperty(0) totalCount = NumericProperty() pickled_data = ObjectProperty() sync_list = ListProperty() def __init__(self, name="", data=None, slug="", mode="Server"): self.slug = slug self.name = name self.event = None if data != "db_data": self.pickled_data = pickle.dumps(data, -1) self.data = pickle.loads(self.pickled_data) self.comic_json = self.data["items"] if mode != "FileOpen": if name == "Single_FileLoad": self.totalCount = 0 else: self.totalCount = self.data["totalCount"] if mode != "FileOpen": self.get_or_create_db_item(mode=mode) def add_comic(self, comic, index=0): """ Add Single comic book to this colection """ self.comics.insert(0, comic) def get_or_create_db_item(self, mode): tmp_defaults = {} try: for key in READINGLIST_DB_KEYS: if key == "data": new_dict = {k: self.data[k] for k in self.data.keys()} tmp_defaults["data"] = new_dict else: tmp_defaults[key] = getattr(self, key) db_item, created = ReadingList.get_or_create( slug=self.slug, defaults=tmp_defaults ) self.db = db_item if db_item: for key in READINGLIST_DB_KEYS: setattr(self, key, getattr(db_item, key)) if created is True: len_dbcomics = len(db_item.comics) if ( len_dbcomics == len(self.comic_json) and len(self.comic_json) != 0 ): self.comic_db_in = True self.comics = self.db.comics.order_by( -Comic.comic_index.index ) else: self.comic_db_in = True comicindex_db = ComicIndex.get( ComicIndex.readinglist == self.slug ) if mode == "local_file": list_comics = self.db.comics.where( Comic.is_sync == True, Comic.local_file != "" ).order_by( # noqa comicindex_db.index ) print(f"len:{len(list_comics)}") else: list_comics = self.db.comics.order_by( comicindex_db.index ) for comic in list_comics: new_comic = ComicBook( comic_Id=comic.Id, readlist_obj=self, mode="db_data", ) self.comics.append(new_comic) self.comics_loaded = True except peewee.OperationalError: Logger.critical( "Somthing happened in get_or_create of readinglist" ) def save_settings(self, *args, **kwargs): try: rl = ReadingList.get(ReadingList.slug == self.slug) for key in READINGLIST_SETTINGS_KEYS: setattr(rl, key, kwargs[key]) setattr(self, key, kwargs[key]) rl.save() except peewee.OperationalError: pass def do_db_refresh(self, screen=None): def __finish_toast(dt): app = App.get_running_app() screen = app.manager.get_screen("server_readinglists_screen") screen.refresh_callback() toast("DataBase Refresh Complete") def __got_readlist_data(results): def __updated_progress(results): pass the_keys = [ "Id", "Series", "Number", "Volume", "Year", "Month", "UserCurrentPage", "UserLastPageRead", "PageCount", "Summary", "FilePath", ] for server_comic in results["items"]: for db_comic in self.comics: if db_comic.Id == server_comic["Id"]: for key in the_keys: if getattr(db_comic, key) != server_comic[key]: if key in ( "UserCurrentPage", "UserLastPageRead", ) and (db_comic.is_sync): if ( db_comic.UserLastPageRead > server_comic["UserLastPageRead"] ) or ( db_comic.UserCurrentPage > server_comic["UserCurrentPage"] ): if ( db_comic.UserCurrentPage > db_comic.UserLastPageRead ): current_page = ( db_comic.UserCurrentPage ) # noqa else: current_page = ( db_comic.UserLastPageRead ) # noqa update_url = "{}/Comics/{}/Progress".format( api_url, db_comic.Id ) self.fetch_data.update_progress( update_url, current_page, callback=lambda req, results: __updated_progress( results ), ) else: x_str = db_comic.__str__ Logger.info( "Updating DB Record for {} of {}".format( key, x_str ) ) toast( "Updating DB Record for {} of {}".format( key, x_str ) ) db_item = Comic.get( Comic.Id == db_comic.Id ) if db_item: setattr( db_item, key, server_comic[key] ) db_item.save() setattr(self, key, db_item) Clock.schedule_once(__finish_toast, 3) self.fetch_data = ComicServerConn() app = App.get_running_app() api_url = app.api_url server_url = f"{api_url}/Lists/{self.slug}/Comics/" self.fetch_data.get_server_data_callback( server_url, callback=lambda req, results: __got_readlist_data(results), ) def get_last_comic_read(self): last_read_comic = 0 for comic in self.comics: if ( comic.UserLastPageRead == comic.PageCount - 1 and comic.PageCount > 1 ): last_read_comic = self.comics.index(comic) return last_read_comic def do_sync(self): def _syncrun_callback(*args): pass app = App.get_running_app() if app.sync_is_running is True: self.please_wait_dialog = MDDialog( title="Sync Already in Progress", size_hint=(0.8, 0.4), text_button_ok="Ok", text=f"Please wait till current Sync is done", events_callback=_syncrun_callback, ) self.please_wait_dialog.open() return self.num_file_done = 0 sync_range = 0 self.fetch_data = ComicServerConn() rl_db = ReadingList.get(ReadingList.slug == self.slug) end_last_sync_num = rl_db.end_last_sync_num if end_last_sync_num != 0: end_last_sync_num = end_last_sync_num - 1 comicindex_db = ComicIndex.get(ComicIndex.readinglist == self.slug) last_read_comic_db = self.db.comics.where( (Comic.UserLastPageRead == Comic.PageCount - 1) & (Comic.PageCount > 1) ).order_by(comicindex_db.index) if len(last_read_comic_db) > 1: last_read_index = ComicIndex.get( ComicIndex.comic == last_read_comic_db[-1].Id, ComicIndex.readinglist == self.slug, ).index elif len(last_read_comic_db) != 0: last_read_index = ComicIndex.get( ComicIndex.comic == last_read_comic_db[0].Id, ComicIndex.readinglist == self.slug, ).index else: last_read_index = 0 if self.cb_limit_active: if self.cb_only_read_active: list_comics = self.db.comics.where( ~(Comic.UserLastPageRead == Comic.PageCount - 1) & (Comic.PageCount > 1) & (Comic.been_sync) != True ).order_by( comicindex_db.index ) # noqa: E712 if last_read_index < end_last_sync_num: sync_range = int(self.limit_num) tmp_comic_list = list_comics[0:int(sync_range)] else: sync_range = int(end_last_sync_num) + int(self.limit_num) tmp_comic_list = list_comics[end_last_sync_num:int(sync_range)] purge_list = self.db.comics.where( (Comic.UserLastPageRead == Comic.PageCount - 1) & (Comic.PageCount > 1) & (Comic.is_sync == True) ).order_by( comicindex_db.index ) # noqa: E712 else: list_comics = ( Comic.select() .where( (Comic.is_sync == False) & (Comic.been_sync == False) ) .order_by(comicindex_db.index) ) # noqa: E712,E501 sync_range = int(self.limit_num) tmp_comic_list = list_comics[0:int(sync_range)] purge_list = self.db.comics.where( Comic.is_sync == True ).order_by( comicindex_db.index ) # noqa: E712 else: sync_range = int(len(self.comics)) # rl_db.end_last_sync_num = new_end_last_sync_num # rl_db.save() if self.cb_only_read_active: list_comics = self.db.comics.where( ~(Comic.UserLastPageRead == Comic.PageCount - 1) & (Comic.PageCount > 1) ).order_by( comicindex_db.index ) # noqa: E712 tmp_comic_list = list_comics[0:int(sync_range)] else: list_comics = self.db.comics.where( (Comic.is_sync == False) & (Comic.been_sync == False) ).order_by( comicindex_db.index ) # noqa: E712,E501 tmp_comic_list = list_comics db_item = ReadingList.get(ReadingList.slug == self.slug) for key in READINGLIST_SETTINGS_KEYS: v = getattr(db_item, key) globals()["%s" % key] = v app = App.get_running_app() id_folder = os.path.join(app.sync_folder, self.slug) my_comic_dir = Path(os.path.join(id_folder, "comics")) if os.path.isdir(my_comic_dir): print(f"{get_size(my_comic_dir)/1000000} MB") sync_comic_list = [] for comic in tmp_comic_list: if comic.is_sync is False: sync_comic_list.append(comic) if self.cb_purge_active: for item in purge_list: os.remove(item.local_file) db_comic = Comic.get(Comic.Id == item.Id) db_comic.is_sync = False db_comic.local_file = "" db_comic.save() server_readinglists_screen = app.manager.get_screen( "server_readinglists_screen" ) server_readinglists_screen.file_sync_update(item.Id, False) self.sync_readinglist(comic_list=sync_comic_list) def get_server_file_download(self, req_url, callback, file_path): def is_finished(dt): if req.is_finished is True: app = App.get_running_app() screen = app.manager.get_screen("server_readinglists_screen") screen.ids.sync_button.enabled = True Clock.schedule_once(self.download_file) else: Clock.schedule_once(is_finished, 0.25) app = App.get_running_app() username = app.config.get("General", "username") api_key = app.config.get("General", "api_key") str_cookie = f"API_apiKey={api_key}; BCR_username={username}" head = { "Content-Type": "application/json", "Accept": "application/json", "Cookie": str_cookie, } req = UrlRequest( req_url, req_headers=head, on_success=callback, file_path=file_path ) app = App.get_running_app() screen = app.manager.get_screen("server_readinglists_screen") if len(self.sync_list) != 0: screen.ids.sync_status_lbl.text = ( f"Sync is Running Left in Que: {len(self.sync_list)}" ) Clock.schedule_once(is_finished, 0.25) else: toast("Reading List has been Synced, Refreshing Screen") screen.ids.sync_status_lbl.text = "" screen.ids.sync_button.enabled = True app.sync_is_running = False # screen.refresh_callback() def got_file(self, comic_obj, comic_file="", *args, **kwargs): def file_finished_toast(dt): toast(f"{os.path.basename(comic_file)} Synced") self.num_file_done += 1 Clock.schedule_once(file_finished_toast) self.file_download = True db_comic = Comic.get(Comic.Id == comic_obj.Id) db_comic.is_sync = True db_comic.save() db_comic = Comic.get(Comic.Id == comic_obj.Id) db_comic.local_file = comic_file db_comic.been_sync = True db_comic.save() rl_db = ReadingList.get(ReadingList.slug == self.slug) rl_db.end_last_sync_num += 1 rl_db.save() app = App.get_running_app() server_readinglists_screen = app.manager.get_screen( "server_readinglists_screen" ) server_readinglists_screen.file_sync_update(comic_obj.Id, True) def download_file(self, dt): def got_thumb(results): pass app = App.get_running_app() screen = app.manager.get_screen("server_readinglists_screen") screen.ids.sync_button.enabled = False if len(self.sync_list) == 0: toast("Reading List has been Synced, Refreshing Screen") app = App.get_running_app() screen = app.manager.get_screen("server_readinglists_screen") screen.ids.sync_status_lbl.text = "" screen.ids.sync_button.enabled = True app.sync_is_running = False # screen.refresh_callback() return comic = self.sync_list.pop(0) self.file_download = False file_name = ntpath.basename(comic.FilePath) y = 240 part_url = f"/Comics/{comic.Id}/Pages/0?" app = App.get_running_app() part_api = f"&apiKey={app.api_key}&height={round(dp(y))}" thumb_url = f"{app.api_url}{part_url}{part_api}" if self.cb_optimize_size_active is False: sync_url = f"{app.api_url}/Comics/{comic.Id}/Sync/File/" elif self.cb_optimize_size_active is True: sync_url = f"{app.api_url}/Comics/{comic.Id}/Sync/Webp" app = App.get_running_app() id_folder = os.path.join(app.sync_folder, self.slug) self.my_comic_dir = Path(os.path.join(id_folder, "comics")) self.my_thumb_dir = Path(os.path.join(id_folder, "thumb")) if not self.my_comic_dir.is_dir(): os.makedirs(self.my_comic_dir) if not self.my_thumb_dir.is_dir(): os.makedirs(self.my_thumb_dir) t_file = os.path.join(self.my_comic_dir, file_name) self.get_server_file_download( sync_url, callback=self.got_file(comic, comic_file=t_file), file_path=t_file, ) thumb_name = f"{comic.Id}.jpg" self.fetch_data.get_server_file_download( thumb_url, callback=lambda req, results: got_thumb(results), file_path=os.path.join(self.my_thumb_dir, thumb_name), ) def _finish_sync(self, comic_list, *largs): def __finish_toast(dt): toast("Reading List has been Synced, Refreshing Screen") # app = App.get_running_app() # screen = app.manager.get_screen("server_readinglists_screen") # screen.refresh_callback() list_comics = comic_list num_comic = len(list_comics) if self.num_file_done == num_comic: Clock.schedule_once(__finish_toast, 3) self.event.cancel() self.event = None def sync_readinglist(self, comic_list=[]): app = App.get_running_app() self.sync_list = comic_list app = App.get_running_app() screen = app.manager.get_screen("server_readinglists_screen") screen.ids.sync_status_lbl.text = ( f"Sync is Running Comics to Sync: {len(self.sync_list)}" ) app.sync_is_running = True screen.ids.sync_button.enabled = False Clock.schedule_once(self.download_file)
class BaseScreen(Screen): app = App.get_running_app() username = ConfigParserProperty("", "General", "username", app.config) password = ConfigParserProperty("", "General", "password", app.config) api_key = ConfigParserProperty("", "General", "api_key", app.config) base_url = ConfigParserProperty("", "General", "base_url", app.config) def __init__(self, **kwargs): super(BaseScreen, self).__init__(**kwargs) self.app = App.get_running_app() self.fetch_data = None self.Data = "" self.fetch_data = ComicServerConn() self.myLoginPop = LoginPopupContent() self.popup = LoginPopup( content=self.myLoginPop, size_hint=(None, None), size=(500, 400) ) # self.update_settings() # self.bind(username=self.update_settings) # self.bind_settings() self.password = self.app.password self.api_key = self.app.api_key self.username = self.app.username self.base_url = self.app.base_url self.open_last_comic_startup = self.app.open_last_comic_startup def update_settings(self, *args): print(f"This is running : {self.username}") # self.username = self.app.username def on_pre_enter(self, *args): self.check_login() def check_login(self): # see if user has a api key stored from server if self.api_key == "": self.myLoginPop.ids.info.text = "[color=#FF0000]\ No API key stored login to get one\ [/color]" # self.open_popup() # self.fetch_data.get_api_key(req_url,self.username,self.password,self) else: tmp_readinglist_name = self.app.config.get( "Saved", "last_reading_list_name" ) tmp_readinglist_Id = self.app.config.get( "Saved", "last_reading_list_id" ) if tmp_readinglist_Id == "": return else: pass Clock.schedule_once( lambda dt: self.build_last_comic_section( tmp_readinglist_name, tmp_readinglist_Id ) ) def open_comic( self, tmp_last_comic_id="", tmp_last_comic_type="", paginator_obj=None, comic=None, tmp_last_pag_pagnum=None, ): if tmp_last_comic_type == "local_file": view_mode = "Sync" else: view_mode = "Server" screen = self.app.manager.get_screen("comic_book_screen") screen.setup_screen( readinglist_obj=self.new_readinglist, comic_obj=comic, paginator_obj=paginator_obj, pag_pagenum=tmp_last_pag_pagnum, last_load=0, view_mode=view_mode, ) self.app.manager.current = "comic_book_screen" self.app.app_started = True def validate_user(self): def got_api(result): api_key = result["ApiKey"] self.app.config.set("General", "api_key", api_key) self.app.config.write() self.api_key = api_key self.myLoginPop.ids.info.text = "[color=#008000]\ Login Sucessful API key saved\ [/color]" self.popup.dismiss() tmp_readinglist_name = self.app.config.get( "Saved", "last_reading_list_name" ) tmp_readinglist_Id = self.app.config.get( "Saved", "last_reading_list_id" ) if tmp_readinglist_Id == "": return else: Clock.schedule_once( lambda dt: self.build_last_comic_section( tmp_readinglist_name, tmp_readinglist_Id ) ) user = self.myLoginPop.ids.username_field.text pwd = self.myLoginPop.ids.pwd_field.text url = self.myLoginPop.ids.url_field.text self.base_url = url.strip() self.username = user self.password = pwd req_url = f"{self.app.base_url}/auth" self.fetch_data.get_api_key( req_url, user, pwd, callback=lambda req, results: got_api(results) ) def call_collect( self, set_mode, readinglists_screen, readinglist_name, readinglist_Id ): Clock.schedule_once( lambda dt: readinglists_screen.collect_readinglist_data( readinglist_name=readinglist_name, readinglist_Id=readinglist_Id, mode=set_mode, ) ) def build_last_comic_section( # noqa self, readinglist_name, readinglist_Id ): def __got_readlist_data(results): async def __load_readinglist_scree(paginator_obj=None): if tmp_last_comic_type == "local_file": x_readinglists_screen = self.app.manager.get_screen( "local_readinglists_screen" ) else: x_readinglists_screen = self.app.manager.get_screen( "server_readinglists_screen" ) x_readinglists_screen.list_loaded = False x_readinglists_screen.setup_screen() x_readinglists_screen.page_number = tmp_last_pag_pagnum x_readinglists_screen.loading_done = False self.call_collect( set_mode, x_readinglists_screen, readinglist_name, readinglist_Id, ) tmp_last_comic_id = self.app.config.get("Saved", "last_comic_id") tmp_last_comic_type = self.app.config.get( "Saved", "last_comic_type" ) tmp_last_pag_pagnum = int( self.app.config.get("Saved", "last_pag_pagnum") ) if tmp_last_comic_id == "": return else: query = ReadingList.select().where( ReadingList.slug == readinglist_Id ) if query.exists(): Logger.info(f"{readinglist_name} already in Database") set_mode = "From DataBase" mode = "" if tmp_last_comic_type == "local_file": mode = "local_file" self.new_readinglist = ComicReadingList( name=self.readinglist_name, data="db_data", slug=self.readinglist_Id, mode=mode, ) # self.new_readinglist.comics_write() max_books_page = int( self.app.config.get("General", "max_books_page") ) new_readinglist_reversed = self.new_readinglist.comics paginator_obj = Paginator( new_readinglist_reversed, max_books_page ) for x in range(1, paginator_obj.num_pages()): this_page = paginator_obj.page(x) for comic in this_page.object_list: if tmp_last_comic_id == comic.Id: tmp_last_pag_pagnum = this_page.number asynckivy.start( __load_readinglist_scree(paginator_obj=paginator_obj) ) if ( self.open_last_comic_startup == 1 and not self.app.app_started ): for comic in self.new_readinglist.comics: if comic.slug == tmp_last_comic_id: self.open_comic( tmp_last_comic_id=tmp_last_comic_id, tmp_last_comic_type=tmp_last_comic_type, paginator_obj=paginator_obj, comic=comic, tmp_last_pag_pagnum=tmp_last_pag_pagnum, ) else: grid = self.ids["main_grid"] grid.cols = 1 grid.clear_widgets() for comic in self.new_readinglist.comics: if comic.slug == tmp_last_comic_id: c = ReadingListComicImage(comic_obj=comic) c.readinglist_obj = self.new_readinglist c.paginator_obj = paginator_obj x = self.app.comic_thumb_width y = self.app.comic_thumb_height if tmp_last_comic_type == "local_file": if comic.local_file == "": return import os id_folder = os.path.join( self.app.sync_folder, self.new_readinglist.slug, ) my_thumb_dir = os.path.join( id_folder, "thumb" ) thumb_name = f"{comic.Id}.jpg" t_file = os.path.join( my_thumb_dir, thumb_name ) c_image_source = t_file else: round_y = round(dp(y)) part_url = f"/Comics/{comic.Id}/Pages/0?" part_api = "&apiKey={}&height={}".format( self.api_key, round_y ) c_image_source = "{}{}{}".format( self.app.api_url, part_url, part_api ) c.source = c_image_source c.PageCount = comic.PageCount c.pag_pagenum = tmp_last_pag_pagnum if tmp_last_comic_type == "local_file": c.view_mode = "Sync" strtxt = f"{comic.Series} #{comic.Number}" tmp_color = get_hex_from_color((1, 1, 1, 1)) c.text = f"[color={tmp_color}]{strtxt}[/color]" grid.add_widget(c) tmp_txt = f"Last Comic Load from \ {self.new_readinglist.name}" self.ids.last_comic_label.text = tmp_txt else: Logger.info( f"{readinglist_name} \ not in Database This could be a problems" ) set_mode = "From Server" # set_mode = 'From Server' self.readinglist_name = readinglist_name # self.app.set_screen(self.readinglist_name + ' Page 1') self.reading_list_title = self.readinglist_name + " Page 1" self.readinglist_Id = readinglist_Id # self.fetch_data.get_list_count(lsit_count_url,self) tmp_last_comic_type = self.app.config.get("Saved", "last_comic_type") if tmp_last_comic_type == "local_file": Clock.schedule_once(lambda dt: __got_readlist_data("none"), 0.15) else: self.fetch_data = ComicServerConn() lsit_count_url = ( f"{self.app.api_url}/Lists/{readinglist_Id}/Comics/" ) # noqa self.fetch_data.get_server_data_callback( lsit_count_url, callback=lambda req, results: __got_readlist_data(results), ) def update_leaf(self): Window.fullscreen = "auto" def open_popup(self): self.popup.open() def close_popup(self): self.popup.dismiss() def got_error(self, req, results): Logger.critical("ERROR in %s %s" % (inspect.stack()[0][3], results)) def got_time_out(self, req, results): Logger.critical("ERROR in %s %s" % (inspect.stack()[0][3], results)) def got_failure(self, req, results): Logger.critical("ERROR in %s %s" % (inspect.stack()[0][3], results)) def got_redirect(self, req, results): Logger.critical("ERROR in %s %s" % (inspect.stack()[0][3], results)) def callback_for_menu_items(self, *args): pass