Clone
1
Plugins
Lisa edited this page 2025-03-26 20:19:22 +01:00

Novel, Anti-Abuse Plugin system!

Upgrade your novel with plugins

Novel like many other softwares has got built-in plugin (module) system.

Plugins can add new features, integrations and overall enchant novel user experience.

Creating a plugin

Firstly lets start with how plugins are built:

Create new file in /plugins directory, example: plugin.py

# plugins/plugin.py
from utils.Logger import Log # You can import novel built-in features! For example logger.

class Plugin:
    def __init__(self):
        self.version = "1.0.0"
        self.name = "My awesome plugin!"
    
    def on_start(self, *args, **kwargs): # Execute something on plugin start!
        Log.v("="*10)
        Log.v("")
        Log.v("Hello, this is an example plugin!")
        Log.v("")
        Log.v("="*10)

This code above implement basic Hello world plugin.

There are more events, here is the list:

## Watchdog
on_created() : Called when a file is created.
# def on_created(self, *args, **kwargs):
#     Log.v(f"File created args={args}, kwargs={kwargs}")
# > See Utils/Watchdog for refference
on_deleted() : Called when a file is deleted.
# def on_deleted(self, *args, **kwargs):
#     Log.v(f"File deleted args={args}, kwargs={kwargs}")
# > See Utils/Watchdog for refference
on_modified() : Called when a file is modified.
# def on_modified(self, *args, **kwargs):
#     Log.v(f"File modified args={args}, kwargs={kwargs}")
# > See Utils/Watchdog for refference
on_moved() : Called when a file is moved.
# def on_moved(self, *args, **kwargs):
#     Log.v(f"File moved args={args}, kwargs={kwargs}") 
# > See Utils/Watchdog for refference


## Scaner
on_scan() : Called when a scan is started.
# def on_scan(self, *args, **kwargs):
#     Log.v(f"Scan started args={args}, kwargs={kwargs}")
# > Utils/Watchdog refference:
#     plugin.on_scan(event_path, file_content, flag_type)

on_scan_completed() : Called when a scan is completed.
# def on_scan_completed(self, *args, **kwargs):
#     Log.v(f"Scan completed args={args}, kwargs={kwargs}")
# > Utils/Watchdog refference:
#     plugin.on_scan_completed(event_path, file_content, flag_type, results)

## AI
on_ai_analysis_completed() : Called when an AI analysis is completed.
# def on_ai_analysis_completed(self, *args, **kwargs):
#     Log.v(f"AI analysis completed args={args}, kwargs={kwargs}")
# > Utils/Watchdog refference:
#     plugin.on_ai_analysis_completed(event_path, file_content, flag_type, results, analysis_result)

Communication with other plugins

To implement communication with other plugins/calling other plugins function we will use module "inspect" on plugin which is being called. Plugin which you want to call should implement calling system!

Example for such implementation:

# plugins/example_call.py
from utils.Logger import Log
import inspect

def _get_plugin_name():
    try:
        # First try to get the caller's plugin name
        for frame_record in inspect.stack():
            frame = frame_record[0]
            if 'self' in frame.f_locals:
                instance = frame.f_locals['self']
                # Check if this is a plugin instance with a name attribute
                if hasattr(instance, 'name') and 'plugins' in frame.f_globals.get('__file__', ''):
                    return instance.name
        
        # If we couldn't find a plugin name in the call stack, check if we're being called by another plugin
        for frame_record in inspect.stack():
            module = inspect.getmodule(frame_record[0])
            if module and hasattr(module, '__file__') and 'plugins' in module.__file__:
                # Extract the plugin name from the filename
                return "Called from " + module.__name__.split('.')[-1]
    except Exception as e:
        return f"Error: {str(e)}"
    return "Unknown"

class Plugin:
    def __init__(self):
        self.version = "1.0.0"
        self.name = "Example function call"

    def demo(self, *args, **kwargs):
        Log.v(f"This is \"demo\" function. I am called by \"{_get_plugin_name()}\" with the argument received: args={args}, kwargs={kwargs}")
        
    def on_start(self, *args, **kwargs):
        Log.v("="*10)
        Log.v("")
        Log.v("Hello, this is an example plugin where you can call demo function!")
        Log.v("")
        Log.v("="*10)

plugin which calls said function:

from utils.Logger import Log
from plugins.example_call import Plugin as example_call

class Plugin:
    def __init__(self):
        self.version = "1.0.0"
        self.name = "Call Other Plugin"

    def on_start(self, *args, **kwargs):
        Log.v("="*10)
        Log.v("")
        Log.v("Hello, this is \"Call Other Plugin!\"")
        Log.v("This plugin will call example_call's \"demo\" function with arguments.")
        Log.v("")
        Log.v("="*10)

        example_call().demo(1,2,3, a=2)

This might be useful for integration plugins which just implement webhook/integration with another REST API, Database or etc.