Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-fanficfare for 
openSUSE:Factory checked in at 2026-04-04 19:08:02
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-fanficfare (Old)
 and      /work/SRC/openSUSE:Factory/.python-fanficfare.new.21863 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-fanficfare"

Sat Apr  4 19:08:02 2026 rev:78 rq:1344572 version:4.56.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-fanficfare/python-fanficfare.changes      
2026-03-02 17:40:30.367796089 +0100
+++ 
/work/SRC/openSUSE:Factory/.python-fanficfare.new.21863/python-fanficfare.changes
   2026-04-04 19:09:58.191404086 +0200
@@ -1,0 +2,14 @@
+Sat Apr  4 11:40:27 UTC 2026 - Matej Cepl <[email protected]>
+
+- Update to the version 4.56.0:
+  - Add Reject URLs: Accept story URLs drag/drop & paste like Add
+    Stories by URL
+  - Add top menu items for Add/Edit Reject URLs.
+  - Remove fanficfare_macmenuhack.
+  - Epub Update: Don't cache cover image with others, trips
+    dedup.
+  - adapter_literotica: Fix for site change (#1318), collect tags
+    on one-shots.
+  - Make seriesUrl mutable again.
+
+-------------------------------------------------------------------

Old:
----
  FanFicFare-4.55.0.tar.gz

New:
----
  FanFicFare-4.56.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-fanficfare.spec ++++++
--- /var/tmp/diff_new_pack.T7i5Eb/_old  2026-04-04 19:09:58.751427047 +0200
+++ /var/tmp/diff_new_pack.T7i5Eb/_new  2026-04-04 19:09:58.751427047 +0200
@@ -20,7 +20,7 @@
 %define modnamedown fanficfare
 %define skip_python2 1
 Name:           python-fanficfare
-Version:        4.55.0
+Version:        4.56.0
 Release:        0
 Summary:        Tool for making eBooks from stories on fanfiction and other 
web sites
 License:        GPL-3.0-only

++++++ FanFicFare-4.55.0.tar.gz -> FanFicFare-4.56.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/FanFicFare-4.55.0/calibre-plugin/__init__.py 
new/FanFicFare-4.56.0/calibre-plugin/__init__.py
--- old/FanFicFare-4.55.0/calibre-plugin/__init__.py    2026-03-01 
16:25:11.000000000 +0100
+++ new/FanFicFare-4.56.0/calibre-plugin/__init__.py    2026-04-02 
17:03:42.000000000 +0200
@@ -33,7 +33,7 @@
 from calibre.customize import InterfaceActionBase
 
 # pulled out from FanFicFareBase for saving in prefs.py
-__version__ = (4, 55, 0)
+__version__ = (4, 56, 0)
 
 ## Apparently the name for this class doesn't matter--it was still
 ## 'demo' for the first few versions.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/FanFicFare-4.55.0/calibre-plugin/config.py 
new/FanFicFare-4.56.0/calibre-plugin/config.py
--- old/FanFicFare-4.55.0/calibre-plugin/config.py      2026-03-01 
16:25:11.000000000 +0100
+++ new/FanFicFare-4.56.0/calibre-plugin/config.py      2026-04-02 
17:03:42.000000000 +0200
@@ -760,6 +760,7 @@
                            tooltip=_("One URL per 
line:\n<b>http://...,note</b>\n<b>http://...,title by author - note</b>"),
                            rejectreasons=rejecturllist.get_reject_reasons(),
                            reasonslabel=_('Add this reason to all URLs 
added:'),
+                           accept_storyurls=True,
                            save_size_name='fff:Add Reject List')
         d.exec_()
         if d.result() == d.Accepted:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/FanFicFare-4.55.0/calibre-plugin/dialogs.py 
new/FanFicFare-4.56.0/calibre-plugin/dialogs.py
--- old/FanFicFare-4.55.0/calibre-plugin/dialogs.py     2026-03-01 
16:25:11.000000000 +0100
+++ new/FanFicFare-4.56.0/calibre-plugin/dialogs.py     2026-04-02 
17:03:42.000000000 +0200
@@ -1328,6 +1328,7 @@
                  icon=None, title=None, label=None, tooltip=None,
                  read_only=False,
                  rejectreasons=[],reasonslabel=None,
+                 accept_storyurls=False,
                  save_size_name='fff:edit text dialog',
                  ):
         SizePersistedDialog.__init__(self, parent, save_size_name)
@@ -1341,7 +1342,10 @@
             self.setWindowIcon(icon)
         self.l.addWidget(self.label)
 
-        self.textedit = QTextEdit(self)
+        if accept_storyurls:
+            self.textedit = DroppableQTextEdit(self)
+        else:
+            self.textedit = QTextEdit(self)
         self.textedit.setLineWrapMode(QTextEditNoWrap)
         self.textedit.setReadOnly(read_only)
         self.textedit.setText(text)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/FanFicFare-4.55.0/calibre-plugin/fff_plugin.py 
new/FanFicFare-4.56.0/calibre-plugin/fff_plugin.py
--- old/FanFicFare-4.55.0/calibre-plugin/fff_plugin.py  2026-03-01 
16:25:11.000000000 +0100
+++ new/FanFicFare-4.56.0/calibre-plugin/fff_plugin.py  2026-04-02 
17:03:42.000000000 +0200
@@ -10,7 +10,9 @@
 import fanficfare.six as six
 from fanficfare.six import ensure_text, string_types, text_type as unicode
 
-# import cProfile
+# from io import StringIO
+# import cProfile, pstats
+# from pstats import SortKey
 
 # def do_cprofile(func):
 #     def profiled_func(*args, **kwargs):
@@ -21,7 +23,12 @@
 #             profile.disable()
 #             return result
 #         finally:
-#             profile.print_stats()
+#             # profile.print_stats()
+#             s = StringIO()
+#             sortby = SortKey.CUMULATIVE
+#             ps = pstats.Stats(profile, stream=s).sort_stats(sortby)
+#             ps.print_stats(20)
+#             print(s.getvalue())
 #     return profiled_func
 
 import logging
@@ -111,7 +118,8 @@
     LoopProgressDialog, UserPassDialog, AboutDialog, CollectURLDialog,
     RejectListDialog, EmailPassDialog, TOTPDialog,
     save_collisions, question_dialog_all,
-    NotGoingToDownload, RejectUrlEntry, IniTextDialog)
+    NotGoingToDownload, RejectUrlEntry, IniTextDialog,
+    EditTextDialog)
 
 # because calibre immediately transforms html into zip and don't want
 # to have an 'if html'.  db.has_format is cool with the case mismatch,
@@ -205,20 +213,6 @@
                                            prefs,
                                            self.qaction.icon())
 
-    ## Kludgey, yes, but with the real configuration inside the
-    ## library now, how else would a user be able to change this
-    ## setting if it's crashing calibre?
-    def check_macmenuhack(self):
-        try:
-            return self.macmenuhack
-        except:
-            file_path = os.path.join(calibre_config_dir,
-                                     
*("plugins/fanficfare_macmenuhack.txt".split('/')))
-            file_path = os.path.abspath(file_path)
-            logger.debug("Plugin %s macmenuhack 
file_path:%s"%(self.name,file_path))
-            self.macmenuhack = os.access(file_path, os.F_OK)
-            return self.macmenuhack
-
     accepts_drops = True
 
     def accept_enter_event(self, event, mime_data):
@@ -443,30 +437,38 @@
             self.reject_list_action = self.create_menu_item_ex(self.menu, 
_('Reject Selected Books'),
                                                                
unique_name='Reject Selected Books', image='rotate-right.png',
                                                                
triggered=self.reject_list_urls)
-            # self.menu.addSeparator()
 
-            # print("platform.system():%s"%platform.system())
-            # print("platform.mac_ver()[0]:%s"%platform.mac_ver()[0])
-            if not self.check_macmenuhack(): # not platform.mac_ver()[0]: # 
Some macs crash on these menu items for unknown reasons.
-                self.menu.addSeparator()
-                self.editpersonalini_action = 
self.create_menu_item_ex(self.menu, _('Edit personal.ini'),
-                                                                       image= 
'config.png',
-                                                                       
unique_name='Edit personal.ini',
-                                                                       
shortcut_name=_('Edit personal.ini'),
-                                                                       
triggered=self.editpersonalini)
-
-                self.config_action = self.create_menu_item_ex(self.menu, 
_('&Configure FanFicFare'),
-                                                              image= 
'config.png',
-                                                              
unique_name='Configure FanFicFare',
-                                                              
shortcut_name=_('Configure FanFicFare'),
-                                                              
triggered=do_user_config)
-
-                self.about_action = self.create_menu_item_ex(self.menu, 
_('About FanFicFare'),
-                                                             image= 
'images/icon.png',
-                                                             
unique_name='About FanFicFare',
-                                                             
shortcut_name=_('About FanFicFare'),
-                                                             
triggered=self.about)
+            self.add_reject_urls_action = self.create_menu_item_ex(self.menu, 
_('Add Reject URLs'),
+                                                                   
image='rotate-right.png',
+                                                                   
unique_name='Add Reject URLs',
+                                                                   
shortcut_name=_('Add Reject URLs'),
+                                                                   
triggered=self.add_reject_urls)
+
+            self.edit_reject_urls_action = self.create_menu_item_ex(self.menu, 
_('Edit Reject URLs'),
+                                                                    
image='rotate-right.png',
+                                                                    
unique_name='Edit Reject URLs',
+                                                                    
shortcut_name=_('Edit Reject URLs'),
+                                                                    
triggered=self.edit_reject_urls)
+
+            self.menu.addSeparator()
 
+            self.editpersonalini_action = self.create_menu_item_ex(self.menu, 
_('Edit personal.ini'),
+                                                                   image= 
'config.png',
+                                                                   
unique_name='Edit personal.ini',
+                                                                   
shortcut_name=_('Edit personal.ini'),
+                                                                   
triggered=self.editpersonalini)
+
+            self.config_action = self.create_menu_item_ex(self.menu, 
_('&Configure FanFicFare'),
+                                                          image= 'config.png',
+                                                          
unique_name='Configure FanFicFare',
+                                                          
shortcut_name=_('Configure FanFicFare'),
+                                                          
triggered=do_user_config)
+
+            self.about_action = self.create_menu_item_ex(self.menu, _('About 
FanFicFare'),
+                                                         image= 
'images/icon.png',
+                                                         unique_name='About 
FanFicFare',
+                                                         
shortcut_name=_('About FanFicFare'),
+                                                         triggered=self.about)
             self.gui.keyboard.finalize()
 
     def about(self,checked):
@@ -502,6 +504,35 @@
                 prefs['personal.ini'] = get_resources('plugin-example.ini')
             prefs.save_to_db()
 
+    def add_reject_urls(self):
+        d = EditTextDialog(self.gui,
+                           "http://example.com/story.php?sid=5,"+_("Reason why 
I rejected it")+"\nhttp://example.com/story.php?sid=6,"+_("Title by Author")+" 
- "+_("Reason why I rejected it"),
+                           # icon=self.windowIcon(),
+                           title=_("FanFicFare"),
+                           label=_("Add Reject URLs. Use: 
<b>http://...,note</b> or <b>http://...,title by author - note</b><br>Invalid 
story URLs will be ignored."),
+                           tooltip=_("One URL per 
line:\n<b>http://...,note</b>\n<b>http://...,title by author - note</b>"),
+                           rejectreasons=rejecturllist.get_reject_reasons(),
+                           reasonslabel=_('Add this reason to all URLs 
added:'),
+                           accept_storyurls=True,
+                           save_size_name='fff:Add Reject List')
+        d.exec_()
+        if d.result() == d.Accepted:
+            rejecturllist.add_text(d.get_plain_text(),d.get_reason_text())
+
+    def edit_reject_urls(self):
+        with busy_cursor():
+            d = RejectListDialog(self.gui,
+                                 rejecturllist.get_list(),
+                                 
rejectreasons=rejecturllist.get_reject_reasons(),
+                                 header=_("Edit Reject URLs List"),
+                                 show_delete=False,
+                                 show_all_reasons=False)
+        d.exec_()
+        if d.result() != d.Accepted:
+            return
+        with busy_cursor():
+            rejecturllist.add(d.get_reject_list(),clear=True)
+
     def create_menu_item_ex(self, parent_menu, menu_text, image=None, 
tooltip=None,
                            shortcut=None, triggered=None, is_checked=None, 
shortcut_name=None,
                            unique_name=None):
@@ -1869,6 +1900,7 @@
         else:
             return None
 
+    # @do_cprofile
     def update_books_loop(self,book,db=None,
                           options={'fileform':'epub',
                                    'collision':ADDNEW,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/FanFicFare-4.55.0/calibre-plugin/jobs.py 
new/FanFicFare-4.56.0/calibre-plugin/jobs.py
--- old/FanFicFare-4.55.0/calibre-plugin/jobs.py        2026-03-01 
16:25:11.000000000 +0100
+++ new/FanFicFare-4.56.0/calibre-plugin/jobs.py        2026-04-02 
17:03:42.000000000 +0200
@@ -59,6 +59,7 @@
 
     do_list = []
     done_list = []
+    logger.info("\n\n"+_("Downloading FanFiction 
Stories")+"\n%s\n"%("\n".join([ "%(status)s %(url)s %(comment)s" % book for 
book in book_list])))
     ## pass failures from metadata through bg job so all results are
     ## together.
     for book in book_list:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/FanFicFare-4.55.0/fanficfare/adapters/adapter_literotica.py 
new/FanFicFare-4.56.0/fanficfare/adapters/adapter_literotica.py
--- old/FanFicFare-4.55.0/fanficfare/adapters/adapter_literotica.py     
2026-03-01 16:25:11.000000000 +0100
+++ new/FanFicFare-4.56.0/fanficfare/adapters/adapter_literotica.py     
2026-04-02 17:03:42.000000000 +0200
@@ -241,7 +241,7 @@
             self.story.extendList('eroticatags', [ stripHTML(t).title() for t 
in soup.select('div#tabpanel-tags a.av_as') ])
         if soup.select('div[class^="_widget__tags_"]'):
             # logger.debug("tags2")
-            self.story.extendList('eroticatags', [ stripHTML(t).title() for t 
in soup.select('div[class^="_widget__tags_"] a[class^="_tags__link_"]') ])
+            self.story.extendList('eroticatags', [ stripHTML(t).title() for t 
in soup.select('div[class^="_widget__tags_"] a[class^="_tag_item_"]') ])
         # logger.debug(self.story.getList('eroticatags'))
 
         ## look first for 'Series Introduction', then Info panel short desc
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/FanFicFare-4.55.0/fanficfare/adapters/base_adapter.py 
new/FanFicFare-4.56.0/fanficfare/adapters/base_adapter.py
--- old/FanFicFare-4.55.0/fanficfare/adapters/base_adapter.py   2026-03-01 
16:25:11.000000000 +0100
+++ new/FanFicFare-4.56.0/fanficfare/adapters/base_adapter.py   2026-04-02 
17:03:42.000000000 +0200
@@ -782,7 +782,7 @@
                         
(img['src'],longdesc)=self.story.addImgUrl(url,self.img_url_trans(img['src']),fetch,
                                                                    
coverexclusion=self.getConfig('cover_exclusion_regexp'))
                         if longdesc:
-                            logger.debug("---set longdesc:%s"%longdesc)
+                            # logger.debug("---set longdesc:%s"%longdesc)
                             img['longdesc'] = longdesc
                 except AttributeError as ae:
                     logger.info("Parsing for img tags failed--probably poor 
input HTML.  Skipping img(%s)"%img)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/FanFicFare-4.55.0/fanficfare/cli.py 
new/FanFicFare-4.56.0/fanficfare/cli.py
--- old/FanFicFare-4.55.0/fanficfare/cli.py     2026-03-01 16:25:11.000000000 
+0100
+++ new/FanFicFare-4.56.0/fanficfare/cli.py     2026-04-02 17:03:42.000000000 
+0200
@@ -28,7 +28,7 @@
 import os, sys, platform
 
 
-version="4.55.0"
+version="4.56.0"
 os.environ['CURRENT_VERSION_ID']=version
 
 global_cache = 'global_cache'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/FanFicFare-4.55.0/fanficfare/configurable.py 
new/FanFicFare-4.56.0/fanficfare/configurable.py
--- old/FanFicFare-4.55.0/fanficfare/configurable.py    2026-03-01 
16:25:11.000000000 +0100
+++ new/FanFicFare-4.56.0/fanficfare/configurable.py    2026-04-02 
17:03:42.000000000 +0200
@@ -526,7 +526,6 @@
     return list([
             'authorId',
             'authorUrl',
-            'seriesUrl',
             'storyId',
             'storyUrl',
             'langcode',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/FanFicFare-4.55.0/fanficfare/epubutils.py 
new/FanFicFare-4.56.0/fanficfare/epubutils.py
--- old/FanFicFare-4.55.0/fanficfare/epubutils.py       2026-03-01 
16:25:11.000000000 +0100
+++ new/FanFicFare-4.56.0/fanficfare/epubutils.py       2026-04-02 
17:03:42.000000000 +0200
@@ -304,6 +304,10 @@
         for item in contentdom.getElementsByTagName("item"):
             href=relpath+item.getAttribute("href")
             if item.getAttribute("media-type").startswith("image/") and 
getsoups:
+                if oldcover and href == oldcover[3]:
+                    # don't include cover image, already handled by
+                    # oldcover code and can trip de-dup unintentionally.
+                    continue
                 img_url = href.replace("OEBPS/","")
                 # logger.debug("-->img img:%s"%img_url)
                 if img_url not in images:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/FanFicFare-4.55.0/fanficfare/story.py 
new/FanFicFare-4.56.0/fanficfare/story.py
--- old/FanFicFare-4.55.0/fanficfare/story.py   2026-03-01 16:25:11.000000000 
+0100
+++ new/FanFicFare-4.56.0/fanficfare/story.py   2026-04-02 17:03:42.000000000 
+0200
@@ -658,7 +658,7 @@
         if failure:
             info['newsrc'] = 'failedtoload'
             info['actuallyused'] = False
-        
logger.debug("add_img(%s,%s,%s,%s,%s,used:%s)"%(url,ext,mime,uuid,info['newsrc'],info['actuallyused']))
+        # 
logger.debug("add_img(%s,%s,%s,%s,%s,used:%s)"%(url,ext,mime,uuid,info['newsrc'],info['actuallyused']))
         return info
 
     def cache_failed_url(self,url):
@@ -1639,7 +1639,7 @@
             ## likely changed to jpg.
             (src,data)=oldimgs[url]
             ext = src.split('.')[-1]
-            logger.debug("load_oldimgs:(%s,%s,%s)"%(url,ext,imagetypes[ext]))
+            # logger.debug("load_oldimgs:(%s,%s,%s)"%(url,ext,imagetypes[ext]))
             self.img_store.add_img(url,
                                    ext,
                                    imagetypes[ext],
@@ -1746,7 +1746,7 @@
                     (data,ext,mime) = no_convert_image(imgurl,
                                                        imgdata)
                 else:
-                    logger.debug("Doing image processing on (%s)"%imgurl)
+                    # logger.debug("Doing image processing on (%s)"%imgurl)
                     try:
                         sizes = [ int(x) for x in 
self.getConfigList('image_max_size',['580', '725']) ]
                     except Exception as e:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/FanFicFare-4.55.0/pyproject.toml 
new/FanFicFare-4.56.0/pyproject.toml
--- old/FanFicFare-4.55.0/pyproject.toml        2026-03-01 16:25:11.000000000 
+0100
+++ new/FanFicFare-4.56.0/pyproject.toml        2026-04-02 17:03:42.000000000 
+0200
@@ -16,7 +16,7 @@
 #
 # For a discussion on single-sourcing the version, see
 # https://packaging.python.org/guides/single-sourcing-package-version/
-version = "4.55.0"
+version = "4.56.0"
 
 # This is a one-line description or tagline of what your project does. This
 # corresponds to the "Summary" metadata field:

Reply via email to