diff --git a/endpoints/helpers.py b/endpoints/helpers.py index c9628b2..f397fa1 100644 --- a/endpoints/helpers.py +++ b/endpoints/helpers.py @@ -1,9 +1,13 @@ import json +import logging # Ensure logging is imported from typing import Literal, Mapping, Optional from werkzeug import Request, Response from middlewares.discord_middleware import DiscordMiddleware +from middlewares.folo_middleware import FoloMiddleware # Import FoloMiddleware from middlewares.default_middleware import DefaultMiddleware +logger = logging.getLogger(__name__) # Ensure logger is initialized + def apply_middleware(r: Request, settings: Mapping) -> Optional[Response]: """ Applies middleware based on the settings provided. @@ -12,27 +16,51 @@ def apply_middleware(r: Request, settings: Mapping) -> Optional[Response]: :param settings: A dictionary containing configuration settings :return: A Response object if middleware processing returns a response, otherwise None """ + middleware_response: Optional[Response] = None + middleware_processed_request = False # Flag to see if a specific middleware modified the request + try: middleware_type = settings.get("middleware") signature_verification_key = settings.get("signature_verification_key") if middleware_type == "discord": + logger.debug("Applying Discord middleware") middleware = DiscordMiddleware(signature_verification_key) - response = middleware.invoke(r) - if response: - return response - except (json.JSONDecodeError, KeyError, TypeError) as e: - print(f"Middleware Error: {str(e)}") - return Response(json.dumps({"error": f"Middleware error: {str(e)}"}), status=500, content_type="application/json") + middleware_response = middleware.invoke(r) + if hasattr(r, 'default_middleware_json'): # Check if DiscordMiddleware modified the request + middleware_processed_request = True + elif middleware_type == "folo": + logger.debug("Applying Folo middleware") + middleware = FoloMiddleware() # Instantiate FoloMiddleware + middleware_response = middleware.invoke(r) # Call its invoke method + if hasattr(r, 'default_middleware_json'): # Check if FoloMiddleware modified the request + middleware_processed_request = True + + if middleware_response: # If any middleware returned a direct response (e.g. on error) + return middleware_response - try: - default_middleware = DefaultMiddleware() - default_middleware.invoke(r, settings) - except (json.JSONDecodeError, KeyError, TypeError) as e: - print(f"Default Middleware Error: {str(e)}") - return Response(json.dumps({"error": f"Default Middleware error: {str(e)}"}), status=500, content_type="application/json") + except Exception as e: # Catch errors during specific middleware instantiation or invocation + logger.error(f"Error during {middleware_type} middleware processing: {str(e)}", exc_info=True) + return Response(json.dumps({"error": f"Error in {middleware_type} middleware: {str(e)}"}), + status=500, content_type="application/json") - return None + # Apply DefaultMiddleware only if no other middleware has processed the request + # and no specific middleware returned an error response. + if not middleware_processed_request and not middleware_response: + try: + logger.debug("Applying Default middleware") + default_middleware = DefaultMiddleware() + # Assuming DefaultMiddleware.invoke might also set r.default_middleware_json or return a Response + # It should also return None if it just modifies r.default_middleware_json + default_middleware_response = default_middleware.invoke(r, settings) + if default_middleware_response: + return default_middleware_response + except Exception as e: + logger.error(f"Default Middleware Error: {str(e)}", exc_info=True) + return Response(json.dumps({"error": f"Default Middleware error: {str(e)}"}), + status=500, content_type="application/json") + + return None # If all middlewares passed (returned None) and did not error def validate_api_key(r: Request, settings: Mapping) -> Optional[Response]: """ diff --git a/group/webhook.yaml b/group/webhook.yaml index 3fd3101..9a0163c 100644 --- a/group/webhook.yaml +++ b/group/webhook.yaml @@ -64,6 +64,11 @@ settings: en_US: Discord zh_Hans: Discord pt_BR: Discord + - value: folo + label: + en_US: Folo + zh_Hans: Folo + pt_BR: Folo - value: none label: en_US: None diff --git a/manifest.yaml b/manifest.yaml index a344baf..cbf41bb 100644 --- a/manifest.yaml +++ b/manifest.yaml @@ -1,4 +1,4 @@ -version: 0.5.1 +version: 0.5.2 type: plugin author: perzeuss name: webhook diff --git a/middlewares/folo_middleware.py b/middlewares/folo_middleware.py new file mode 100644 index 0000000..d73485d --- /dev/null +++ b/middlewares/folo_middleware.py @@ -0,0 +1,87 @@ +import json +import logging +from werkzeug import Request, Response +from typing import Optional + +logger = logging.getLogger(__name__) + +class FoloMiddleware: + def __init__(self): + """ + Initializes the FoloMiddleware. + Currently, it does not require specific settings from the main config. + """ + pass + + def invoke(self, r: Request) -> Optional[Response]: + """ + Processes the request if it's a Folo webhook. + - Parses the Folo payload. + - Transforms it into the Dify-expected format with query="start" + and specific fields mapped to inputs. + - Stores the transformed payload in r.default_middleware_json. + + Returns: + - A Response object if an error occurs during processing (e.g., invalid payload). + - None if the transformation is successful, allowing the main handler to proceed + using r.default_middleware_json. + """ + logger.debug("FoloMiddleware: Processing request...") + try: + folo_payload = r.get_json() + if not folo_payload or "entry" not in folo_payload: + logger.error("FoloMiddleware: Invalid or missing 'entry' in Folo payload.") + return Response( + json.dumps({"error": "Folo middleware: Invalid payload, 'entry' field is missing."}), + status=400, + content_type="application/json" + ) + + entry = folo_payload.get("entry", {}) + + # Extract required fields from the Folo 'entry' object + title = entry.get("title") + content = entry.get("content") + author = entry.get("author") + url = entry.get("url") + published_at = entry.get("publishedAt") + description = entry.get("description") + + # Construct the new payload for Dify + dify_inputs = { + "title": title, + "content": content, + "author": author, + "url": url, + "publishedAt": published_at, + "description": description + } + + # Add debug logging for extracted inputs + logger.debug(f"FoloMiddleware: Extracted inputs for Dify: {dify_inputs}") + + dify_payload = { + "query": "start", + "inputs": dify_inputs + } + + # Store the transformed payload in the request object for the main endpoint handler + r.default_middleware_json = dify_payload + logger.info("FoloMiddleware: Payload transformed successfully and stored in r.default_middleware_json.") + + return None # Indicate successful transformation + + except json.JSONDecodeError as e: + logger.error(f"FoloMiddleware: JSONDecodeError while parsing Folo payload - {str(e)}") + return Response( + json.dumps({"error": f"Folo middleware: Invalid JSON payload - {str(e)}"}), + status=400, + content_type="application/json" + ) + except Exception as e: + logger.error(f"FoloMiddleware: Unexpected error during processing - {str(e)}", exc_info=True) + return Response( + json.dumps({"error": f"Folo middleware: Unexpected error - {str(e)}"}), + status=500, + content_type="application/json" + )