| 
			
			 | 
		#61 | 
| 
			
			
			
			 Custom User Title 
			
			![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 11,359 
				Karma: 79528341 
				Join Date: Oct 2018 
				Location: Canada 
				
				
				Device: Kobo Libra H2O, formerly Aura HD 
				
				
				 | 
	
	
	
		
		
			
			 
				
				Convert public-domain identifiers
			 
			
			
			Here is a chain that uses templates to convert url/uri identifiers from three public-domain book websites (Project Gutenberg, Standard Ebooks, and Global Grey) to site-specific ones. Mostly because it looks nicer in book details.  
		
	
		
		
			![]() Before installing this, go to Preferences > Look & Feel > Book Details > Create rules to convert identifiers into link. Then add these three rules: Project Gutenberg Key: gutenberg Template: https://www.gutenberg.org/ebooks/{id} Standard Ebooks Key: standard Template: https://standardebooks.org/ebooks/{id} Global Grey Key: gg Template: https://www.globalgreyebooks.com/{id}-ebook.html Note that it uses the publisher field to identify whether to convert the IDs. Last edited by ownedbycats; 05-18-2024 at 08:44 PM.  | 
| 
		 | 
	
	
	
		
		
		
		
			 
		
		
		
		
		
		
		
			
		
		
		
	 | 
| 
			
			 | 
		#62 | |
| 
			
			
			
			 want to learn what I want 
			
			![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 1,681 
				Karma: 7908443 
				Join Date: Sep 2020 
				
				
				
				Device: none 
				
				
				 | 
	
	
	
		
		
		
		
		 Quote: 
	
  | 
|
| 
		 | 
	
	
	
		
		
		
		
			 
		
		
		
		
		
		
		
			
		
		
		
	 | 
| 
			
			 | 
		#63 | 
| 
			
			
			
			 Custom User Title 
			
			![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 11,359 
				Karma: 79528341 
				Join Date: Oct 2018 
				Location: Canada 
				
				
				Device: Kobo Libra H2O, formerly Aura HD 
				
				
				 | 
	
	
	
		
		
			
			 
				
				[FanFicFare] Copy StoryURL to personal.ini
			 
			
			
			For FanFicFare users, this chain I made to easily add a new StoryURL section. First it copies this to clipboard: 
		
	
		
		
			Code: 
	## Test Author - Test Title [https://www.fanfiction.net/s/123456/1/] Then it opens personal.ini to paste it in. Last edited by ownedbycats; 05-18-2024 at 08:43 PM.  | 
| 
		 | 
	
	
	
		
		
		
		
			 
		
		
		
		
		
		
		
			
		
		
		
	 | 
| 
			
			 | 
		#64 | 
| 
			
			
			
			 Member 
			
			![]() Posts: 11 
				Karma: 10 
				Join Date: Jun 2024 
				
				
				
				Device: Koba Aura 
				
				
				 | 
	
	
	
		
		
			
			 
				
				FanFicFare module
			 
			
			
			This module was not created by me but by the creator of FanFicFare. Just wanted to share it 
		
	
		
		
		
		
		
		
		
		
		
		
	
	https://www.mobileread.com/forums/sh...postcount=9637 The FFF plugin has a signal it will emit after the "proceed with updating your library" dialog. Code: 
	from calibre_plugins.action_chains.events import ChainEvent
class SearchChanged(ChainEvent):
    # replace with the name of your event
    name = 'FFF done'
    def get_event_signal(self):
        return self.gui.iactions['FanFicFare'].download_finished_signal
 | 
| 
		 | 
	
	
	
		
		
		
		
			 
		
		
		
		
		
		
		
			
		
		
		
	 | 
| 
			
			 | 
		#65 | |
| 
			
			
			
			 Wizard 
			
			![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 1,216 
				Karma: 1995558 
				Join Date: Aug 2015 
				
				
				
				Device: Kindle 
				
				
				 | 
	
	
	
		
		
		
		
		 Quote: 
	
  | 
|
| 
		 | 
	
	
	
		
		
		
		
			 
		
		
		
		
		
		
		
			
		
		
		
	 | 
| 
			
			 | 
		#66 | |
| 
			
			
			
			 Member 
			
			![]() Posts: 11 
				Karma: 10 
				Join Date: Jun 2024 
				
				
				
				Device: Koba Aura 
				
				
				 | 
	
	
	
		
		
		
		
		 Quote: 
	
 I asked JimmXinu to add such a file to his plugin for future updates  | 
|
| 
		 | 
	
	
	
		
		
		
		
			 
		
		
		
		
		
		
		
			
		
		
		
	 | 
| 
			
			 | 
		#67 | |
| 
			
			
			
			 Connoisseur 
			
			![]() Posts: 66 
				Karma: 10 
				Join Date: Nov 2023 
				
				
				
				Device: Kindle Oasis 
				
				
				 | 
	
	
	
		
		
		
		
		 Quote: 
	
  | 
|
| 
		 | 
	
	
	
		
		
		
		
			 
		
		
		
		
		
		
		
			
		
		
		
	 | 
| 
			
			 | 
		#68 | 
| 
			
			
			
			 Junior Member 
			
			![]() Posts: 3 
				Karma: 10 
				Join Date: Jan 2025 
				
				
				
				Device: kindle paperwhite 
				
				
				 | 
	
	
	
		
		
		
		
		 
			
			Hi, for the event 'Books Added' still works in the latest version of calibre? I get this error: 
		
	
		
		
		
		
		
		
		
		
		
		
		
			Code: 
	calibre, version 7.24.0
ERROR: Unhandled exception: <b>KeyError</b>:'select_books'
calibre 7.24  embedded-python: True
Linux-4.4.302+-x86_64-with-glibc2.39 Linux ('64bit', 'ELF')
('Linux', '4.4.302+', '#72806 SMP Thu Sep 5 13:45:50 CST 2024')
Python 3.11.5
Interface language: None
EXE path: /opt/calibre/bin/calibre
Successfully initialized third party plugins: DeACSM (0, 0, 16) && Gather KFX-ZIP (from KFX Input) (2, 19, 0) && DeDRM (10, 0, 9) && Package KFX (from KFX Input) (2, 19, 0) && Action Chains (1, 20, 8) && Count Pages (1, 13, 6) && Embed Comic Metadata (1, 6, 6) && Find Duplicates (1, 10, 9) && KFX metadata reader (from KFX Input) (2, 19, 0) && From KFX (2, 19, 0) && KFX Input (2, 19, 0) && Set KFX metadata (from KFX Output) (2, 13, 0) && KFX Output (2, 13, 0) && Obok DeDRM (10, 0, 9)
Traceback (most recent call last):
  File "calibre_plugins.action_chains.gui.events_dialogs", line 280, in _on_event_opts_button_clicked
    d.load_settings(self.event_opts)
  File "calibre_plugins.action_chains.gui.events_dialogs", line 127, in load_settings
    self.widget.load_settings(settings)
  File "Books Added", line 48, in load_settings
KeyError: 'select_books'
Last edited by webysther; 01-20-2025 at 11:48 AM.  | 
| 
		 | 
	
	
	
		
		
		
		
			 
		
		
		
		
		
		
		
			
		
		
		
	 | 
| 
			
			 | 
		#69 | |
| 
			
			
			
			 Wizard 
			
			![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 1,216 
				Karma: 1995558 
				Join Date: Aug 2015 
				
				
				
				Device: Kindle 
				
				
				 | 
	
	
	
		
		
		
		
		 Quote: 
	
  | 
|
| 
		 | 
	
	
	
		
		
		
		
			 
		
		
		
		
		
		
		
			
		
		
		
	 | 
| 
			
			 | 
		#70 | 
| 
			
			
			
			 Wizard 
			
			![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 1,216 
				Karma: 1995558 
				Join Date: Aug 2015 
				
				
				
				Device: Kindle 
				
				
				 | 
	
	
	
		
		
			
			 
				
				Duplicate a book
			 
			
			
			Action to duplicate a book, originally written by bluefish2020 
		
	
		
		
		
		
		
		
		
		
		
		
		
			Code: 
	import os
from calibre_plugins.action_chains.actions.base import ChainAction
class DuplicateBookAction(ChainAction):
    name = 'Duplicate Book'
    support_scopes = True
    # code adapted from calibre/gui2/actions/add.py:add_empty()
    def run(self, gui, settings, chain):
        db = gui.current_db
        selected_books = chain.scope().get_book_ids()
        
        ids, orig_fmts = [], []
        for book_id in selected_books:
            metadata = db.get_metadata(book_id, index_is_id=True, get_cover=True, cover_as_data=True)
            orig_fmts = tuple(db.new_api.format(book_id, fmt, as_path=True) for fmt in db.new_api.formats(book_id))
            new_book_id = db.import_book(metadata, orig_fmts)
            ids.append(new_book_id)
            
        self.refresh_gui(gui, len(selected_books))
        # entirely optional: select and mark the copies
        if ids:
            ids.reverse()
            gui.library_view.select_rows(ids)
            db.set_marked_ids({id: 'duplicate' for id in ids})
        # clean up temp files created by new_api.format()
        for path in orig_fmts:
            os.remove(path)                        
    def refresh_gui(self, gui, num):
        gui.library_view.model().books_added(num)
        gui.refresh_cover_browser()
        gui.tags_view.recount()
Last edited by capink; 05-25-2025 at 10:01 PM.  | 
| 
		 | 
	
	
	
		
		
		
		
			 
		
		
		
		
		
		
		
			
		
		
		
	 | 
| 
			
			 | 
		#71 | 
| 
			
			
			
			 Junior Member 
			
			![]() Posts: 1 
				Karma: 10 
				Join Date: Jun 2025 
				
				
				
				Device: Kobo Clara 
				
				
				 | 
	
	
	
		
		
			
			 
				
				Event for same time everyday
			 
			
			
			Added an event to occur at the same time everyday, may add days of the week selections as well later. 
		
	
		
		
		
		
		
		
		
		
		
		
	
	Code: 
	from calibre_plugins.action_chains.events import ChainEvent
from qt.core import QApplication, Qt, QWidget, QVBoxLayout, QGroupBox, QLabel, QTimeEdit, QTimer, QTime, pyqtSignal
from calibre.utils.date import now
from calibre import prints
from calibre.constants import DEBUG
from datetime import datetime
class ConfigWidget(QWidget):
    def __init__(self, plugin_action):
        QWidget.__init__(self)
        self.plugin_action = plugin_action
        self.gui = plugin_action.gui
        self.db = self.gui.current_db
        self._init_controls()
    def _init_controls(self):
        l = self.l = QVBoxLayout()
        self.setLayout(l)
        
        time_edit_box = QGroupBox('Trigger time (24h format):')
        time_edit_box_l = QVBoxLayout()
        time_edit_box.setLayout(time_edit_box_l)
        l.addWidget(time_edit_box)
        self.time_edit = QTimeEdit()
        self.time_edit.setDisplayFormat('HH:mm')
        self.time_edit.setTime(QTime.fromString('08:00', 'HH:mm'))
        time_edit_box_l.addWidget(self.time_edit)
        
        l.addStretch(1)
        
        self.setMinimumSize(300,300)
    def load_settings(self, settings):
        if settings:
            self.time_edit.setTime(QTime.fromString(settings['trigger_time'], 'HH:mm'))
    def save_settings(self):
        settings = {}
        settings['trigger_time'] = self.time_edit.time().toString('HH:mm')
        self.plugin_action.plugin_restart_required.emit('events_dialog', 'Timer event interval')
        return settings
class TimeOfDayEvent(ChainEvent):
    name = 'Time of Day'
    time_triggered = pyqtSignal()
    def __init__(self, plugin_action):
        ChainEvent.__init__(self, plugin_action)
        self.last_triggered_date = None
        QTimer.singleShot(5*1000, self.check_time)
    def get_target_time(self):
        event_options = self.get_options()
        target_time = event_options.get('trigger_time','08:00')
        return target_time
    def get_event_signal(self):
        return self.time_triggered
    
    def config_widget(self):
        return ConfigWidget
    def check_time(self):    
        now_time = QTime.currentTime()
        today_str = now().date().isoformat()
        if datetime.now().strftime('%H:%M') + '' == self.get_target_time():
            if self.last_triggered_date != today_str:
                if not self.plugin_action.chainStack:
                    QTimer.singleShot(0, self.time_triggered.emit)
                    self.last_triggered_date = today_str
 | 
| 
		 | 
	
	
	
		
		
		
		
			 
		
		
		
		
		
		
		
			
		
		
		
	 | 
| 
			
			 | 
		#72 | 
| 
			
			
			
			 Guru 
			
			![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 922 
				Karma: 810834 
				Join Date: Sep 2017 
				Location: Buenos Aires, Argentina 
				
				
				Device: moon+ reader, kindle paperwhite 
				
				
				 | 
	
	
	
		
		
		
		
		 
			
			Hi everyone, I have a question. 
		
	
		
		
		
		
		
		
		
		
		
		
	
	I'd like to have Calibre automatically open a small list of books in the e-book viewer when I open it. I've created a virtual library with the six books I want it to open. But I can't automate the next step. Could you help me with an action that opens six books from a virtual library?  | 
| 
		 | 
	
	
	
		
		
		
		
			 
		
		
		
		
		
		
		
			
		
		
		
	 | 
| 
			
			 | 
		#73 | |
| 
			
			
			
			 Well trained by Cats 
			
			![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 31,267 
				Karma: 61916422 
				Join Date: Aug 2009 
				Location: The Central Coast of California 
				
				
				Device: Kobo Libra2,Kobo Aura2v1, K4NT(Fixed: New Bat.), Galaxy Tab A 
				
				
				 | 
	
	
	
		
		
		
		
		 Quote: 
	
    Oh this post was in Action chains   
		 | 
|
| 
		 | 
	
	
	
		
		
		
		
			 
		
		
		
		
		
		
		
			
		
		
		
	 | 
| 
			
			 | 
		#74 | 
| 
			
			
			
			 Guru 
			
			![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 922 
				Karma: 810834 
				Join Date: Sep 2017 
				Location: Buenos Aires, Argentina 
				
				
				Device: moon+ reader, kindle paperwhite 
				
				
				 | 
	
	|
| 
		 | 
	
	
	
		
		
		
		
			 
		
		
		
		
		
		
		
			
		
		
		
	 | 
| 
			
			 | 
		#75 | |
| 
			
			
			
			 Well trained by Cats 
			
			![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 31,267 
				Karma: 61916422 
				Join Date: Aug 2009 
				Location: The Central Coast of California 
				
				
				Device: Kobo Libra2,Kobo Aura2v1, K4NT(Fixed: New Bat.), Galaxy Tab A 
				
				
				 | 
	
	
	
		
		
		
		
		 Quote: 
	
 ![]() IIRC this one has been there since VL's was first added.  | 
|
| 
		 | 
	
	
	
		
		
		
		
			 
		
		
		
		
		
		
		
			
		
		
		
	 | 
![]()  | 
            
        
            
            
  | 
    
			 
			Similar Threads
		 | 
	||||
| Thread | Thread Starter | Forum | Replies | Last Post | 
| [GUI Plugin] Action Chains | capink | Plugins | 1556 | 10-26-2025 02:09 PM | 
| Book Scanning tool chains | tomsem | Workshop | 17 | 12-03-2023 10:19 AM | 
| Mystery and Crime Thorne, Guy: Chance in Chains (1914); v1 | Pulpmeister | Kindle Books | 0 | 11-25-2018 10:09 PM | 
| Mystery and Crime Thorne, Guy: Chance in Chains (1914); v1 | Pulpmeister | ePub Books | 0 | 11-25-2018 10:08 PM | 
| Could this be the last year for the big chains? | Connallmac | News | 66 | 01-07-2011 05:11 PM |