mirror of
https://gitlab.com/chicken-riders/RcGcDw.git
synced 2025-02-23 00:24:09 +00:00
Added #279, added priority number for hooks so they can be started in sequence, added condition for running a hook
This commit is contained in:
parent
afc503a285
commit
f870a53e82
|
@ -27,3 +27,21 @@ def example_pre_hook(context: Context, change: dict):
|
|||
def example_post_hook(message: DiscordMessage, metadata: DiscordMessageMetadata, context: Context, change: dict):
|
||||
print("Our Discord message looks as follows: ")
|
||||
print(message)
|
||||
|
||||
|
||||
def verify_upload(context: Context, change: dict) -> bool:
|
||||
return hasattr(context, "event") and context.event.startswith("upload")
|
||||
|
||||
|
||||
@pre_hook(priority=105, condition=verify_upload)
|
||||
def example_pre_hook_with_args(context: Context, change: dict):
|
||||
print("I'm an upload! Also I'm using a fancy decorator!")
|
||||
|
||||
|
||||
def never_register_this_one(settings):
|
||||
return False
|
||||
|
||||
|
||||
@pre_hook(priority=2, register=never_register_this_one)
|
||||
def example_pre_hook_that_will_never_register(context: Context, change: dict):
|
||||
print("EVIL THINGS HAPPENING IN HERE MUHAHHAHAHHA")
|
|
@ -14,27 +14,53 @@
|
|||
# along with RcGcDw. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import logging
|
||||
import functools
|
||||
from src.configloader import settings
|
||||
from typing import Optional, Callable
|
||||
import src.api.hooks
|
||||
|
||||
logger = logging.getLogger("src.api.hook")
|
||||
|
||||
def pre_hook(func):
|
||||
|
||||
def pre_hook(_func: Optional[Callable] = None, priority: int = 100, condition: Optional[Callable] = None, register: Optional[Callable] = None):
|
||||
"""
|
||||
Decorator to register a pre hook and return a function
|
||||
|
||||
:return: func
|
||||
"""
|
||||
def decorator_prehook(func):
|
||||
if register is None or register(settings):
|
||||
logger.info("{hook_name} has been registered as a pre hook.".format(hook_name=func.__name__))
|
||||
src.api.hooks.pre_hooks.append(func)
|
||||
return func
|
||||
src.api.hooks.pre_hooks.append((func, priority, condition))
|
||||
|
||||
@functools.wraps(func)
|
||||
def wrapper_prehook(*args, **kwargs):
|
||||
return func(*args, **kwargs)
|
||||
return wrapper_prehook
|
||||
|
||||
if _func is None:
|
||||
return decorator_prehook
|
||||
else:
|
||||
return decorator_prehook(_func)
|
||||
|
||||
|
||||
def post_hook(func):
|
||||
def post_hook(_func: Optional[Callable] = None, priority: int = 100, condition: Optional[Callable] = None, register: Optional[Callable] = None):
|
||||
"""
|
||||
Decorator to register a post hook and return a function
|
||||
|
||||
:return: func
|
||||
"""
|
||||
def decorator_posthook(func):
|
||||
if register is None or register(settings):
|
||||
logger.info("{hook_name} has been registered as a post hook.".format(hook_name=func.__name__))
|
||||
src.api.hooks.post_hooks.append(func)
|
||||
return func
|
||||
src.api.hooks.post_hooks.append((func, priority, condition))
|
||||
|
||||
@functools.wraps(func)
|
||||
def wrapper_posthook(*args, **kwargs):
|
||||
return func(*args, **kwargs)
|
||||
return wrapper_posthook
|
||||
|
||||
if _func is None:
|
||||
return decorator_posthook
|
||||
else:
|
||||
return decorator_posthook(_func)
|
||||
|
|
|
@ -14,10 +14,10 @@
|
|||
# along with RcGcDw. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Made just to avoid circular imports
|
||||
from typing import Callable, List, Dict
|
||||
from typing import Callable, List, Dict, Tuple, Optional
|
||||
from src.discord.message import DiscordMessage, DiscordMessageMetadata
|
||||
from src.api.context import Context
|
||||
|
||||
formatter_hooks: Dict[str, Callable[[Context, dict], DiscordMessage]] = {}
|
||||
pre_hooks: List[Callable[[Context, dict], None]] = []
|
||||
post_hooks: List[Callable[[DiscordMessage, DiscordMessageMetadata, Context, dict], None]] = []
|
||||
pre_hooks: List[Tuple[Callable[[Context, dict], None], int, Optional[Callable[[Context, dict], bool]]]] = []
|
||||
post_hooks: List[Tuple[Callable[[DiscordMessage, DiscordMessageMetadata, Context, dict], None], int, Optional[Callable[[DiscordMessage, DiscordMessageMetadata, Context, dict], bool]]]] = []
|
19
src/misc.py
19
src/misc.py
|
@ -17,9 +17,11 @@
|
|||
import base64
|
||||
import json, logging, sys, re, platform
|
||||
from html.parser import HTMLParser
|
||||
from typing import Callable, Tuple, List, Optional, Union
|
||||
from urllib.parse import urlparse, urlunparse
|
||||
import requests
|
||||
|
||||
from api.context import Context
|
||||
from src.argparser import command_args
|
||||
from src.configloader import settings
|
||||
import src.api.util
|
||||
|
@ -314,13 +316,24 @@ def prepare_paths(path: str, dry=False):
|
|||
prepare_paths(settings["wiki_url"])
|
||||
|
||||
|
||||
def run_hooks(hooks, *arguments):
|
||||
def run_hooks(hooks: Union[List[Tuple[Callable[[Context, dict], None], int, Optional[Callable]]], List[Tuple[Callable[[DiscordMessage, DiscordMessageMetadata, Context, dict], None], int, Optional[Callable]]]], *arguments):
|
||||
for hook in hooks:
|
||||
if hook[2] is not None:
|
||||
try:
|
||||
hook(*arguments)
|
||||
if hook[2](*arguments) is False:
|
||||
misc_logger.debug(f"Ignoring hook {hook[0].__name__} due to conditions not being met for execution")
|
||||
continue
|
||||
except:
|
||||
if settings.get("error_tolerance", 1) > 0:
|
||||
misc_logger.exception("On running a pre hook, ignoring pre-hook")
|
||||
misc_logger.exception("On running a hook check function, ignoring hook")
|
||||
else:
|
||||
raise
|
||||
try:
|
||||
misc_logger.debug(f"Running {hook[0].__name__} hook")
|
||||
hook[0](*arguments)
|
||||
except:
|
||||
if settings.get("error_tolerance", 1) > 0:
|
||||
misc_logger.exception("On running a hook, ignoring hook")
|
||||
else:
|
||||
raise
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import operator
|
||||
# This file is part of Recent changes Goat compatible Discord webhook (RcGcDw).
|
||||
|
||||
# RcGcDw is free software: you can redistribute it and/or modify
|
||||
|
@ -25,7 +25,8 @@ import src.configloader
|
|||
from src.migrations import *
|
||||
from collections import defaultdict, Counter, OrderedDict
|
||||
from src.argparser import command_args
|
||||
from typing import Optional
|
||||
from typing import Optional, Callable, Tuple
|
||||
from operator import itemgetter
|
||||
import src.api.client
|
||||
from src.api.context import Context
|
||||
from src.api.hooks import formatter_hooks, pre_hooks, post_hooks
|
||||
|
@ -53,6 +54,12 @@ logger = logging.getLogger("rcgcdw")
|
|||
logger.debug("Current settings: {settings}".format(settings=settings))
|
||||
|
||||
|
||||
def sort_hooks():
|
||||
"""Sort hooks according to their priority, first are executed hooks that have higher priority then lower"""
|
||||
pre_hooks.sort(key=operator.itemgetter(1), reverse=True)
|
||||
post_hooks.sort(key=operator.itemgetter(1), reverse=True)
|
||||
|
||||
|
||||
def load_extensions():
|
||||
"""Loads all of the extensions, can be a local import because all we need is them to register"""
|
||||
try:
|
||||
|
@ -309,6 +316,7 @@ def abuselog_processing(entry):
|
|||
|
||||
|
||||
load_extensions()
|
||||
sort_hooks()
|
||||
# Log in and download wiki information
|
||||
wiki = Wiki(rc_processor, abuselog_processing)
|
||||
client = src.api.client.Client(formatter_hooks, wiki)
|
||||
|
|
Loading…
Reference in a new issue