kopia lustrzana https://github.com/mate-dev/meshtastic-matrix-relay
				
				
				
			Add parameter passing to plugins and help
							rodzic
							
								
									1cb11342e6
								
							
						
					
					
						commit
						d7f027358b
					
				| 
						 | 
				
			
			@ -5,6 +5,8 @@ import requests
 | 
			
		|||
from PIL import Image
 | 
			
		||||
from nio import AsyncClient, UploadResponse
 | 
			
		||||
from plugins.base_plugin import BasePlugin
 | 
			
		||||
import re
 | 
			
		||||
from matrix_utils import connect_matrix
 | 
			
		||||
 | 
			
		||||
def load_env_variable(key):
 | 
			
		||||
    env_path = os.path.join(os.path.dirname(__file__), '.env')
 | 
			
		||||
| 
						 | 
				
			
			@ -14,6 +16,19 @@ def load_env_variable(key):
 | 
			
		|||
                return line.strip().split('=')[1].strip().strip('"')
 | 
			
		||||
    return None
 | 
			
		||||
 | 
			
		||||
def parse_timeframe(timeframe):
 | 
			
		||||
    unit_multipliers = {
 | 
			
		||||
        'm': 60,            # minute to seconds
 | 
			
		||||
        'h': 60 * 60,       # hour to seconds
 | 
			
		||||
        'd': 24 * 60 * 60,  # day to seconds
 | 
			
		||||
        'M': 30 * 24 * 60 * 60  # month to seconds (approximation)
 | 
			
		||||
    }
 | 
			
		||||
    match = re.match(r'(\d+)([mhdM])', timeframe)
 | 
			
		||||
    if match:
 | 
			
		||||
        value, unit = match.groups()
 | 
			
		||||
        return int(value) * unit_multipliers[unit]
 | 
			
		||||
    return 24 * 60 * 60  # default to 1 day in seconds
 | 
			
		||||
 | 
			
		||||
class Plugin(BasePlugin):
 | 
			
		||||
    plugin_name = "airutilz"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -21,7 +36,7 @@ class Plugin(BasePlugin):
 | 
			
		|||
    def description(self):
 | 
			
		||||
        return "Generates and returns Air Utilization TX."
 | 
			
		||||
 | 
			
		||||
    async def get_image_url(self):
 | 
			
		||||
    async def get_image_url(self, timeframe):
 | 
			
		||||
        base_url = load_env_variable('GRAFANA_BASE_URL')
 | 
			
		||||
        org_id = "1"
 | 
			
		||||
        panel_id = "4"
 | 
			
		||||
| 
						 | 
				
			
			@ -31,13 +46,15 @@ class Plugin(BasePlugin):
 | 
			
		|||
        tz = "Europe/Warsaw"
 | 
			
		||||
 | 
			
		||||
        to_time = int(time.time() * 1000)
 | 
			
		||||
        from_time = to_time - 24 * 60 * 60 * 1000
 | 
			
		||||
        from_time = to_time - parse_timeframe(timeframe) * 1000
 | 
			
		||||
 | 
			
		||||
        url = (
 | 
			
		||||
            f"{base_url}?orgId={org_id}&from={from_time}&to={to_time}&"
 | 
			
		||||
            f"panelId={panel_id}&width={width}&height={height}&scale={scale}&tz={tz}"
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        self.logger.debug(f"Generated URL: {url}")
 | 
			
		||||
 | 
			
		||||
        return url
 | 
			
		||||
 | 
			
		||||
    async def handle_meshtastic_message(self, packet, formatted_message, longname, meshnet_name):
 | 
			
		||||
| 
						 | 
				
			
			@ -54,17 +71,44 @@ class Plugin(BasePlugin):
 | 
			
		|||
        if not self.matches(full_message):
 | 
			
		||||
            return False
 | 
			
		||||
 | 
			
		||||
        from matrix_utils import connect_matrix
 | 
			
		||||
        self.logger.debug(f"Received message: {full_message}")
 | 
			
		||||
 | 
			
		||||
        matrix_client = await connect_matrix()
 | 
			
		||||
 | 
			
		||||
        url = await self.get_image_url()
 | 
			
		||||
        # Check if the message is a help request
 | 
			
		||||
        if 'help' in full_message:
 | 
			
		||||
            help_message = ("Usage: !airutilz [timeframe]\n"
 | 
			
		||||
                            "Timeframe format examples:\n"
 | 
			
		||||
                            "5m - last 5 minutes\n"
 | 
			
		||||
                            "1h - last 1 hour\n"
 | 
			
		||||
                            "2d - last 2 days\n"
 | 
			
		||||
                            "1M - last 1 month")
 | 
			
		||||
            await matrix_client.room_send(
 | 
			
		||||
                room_id=room.room_id,
 | 
			
		||||
                message_type="m.room.message",
 | 
			
		||||
                content={"msgtype": "m.text", "body": help_message},
 | 
			
		||||
            )
 | 
			
		||||
            return True
 | 
			
		||||
 | 
			
		||||
        # Extract timeframe from the message
 | 
			
		||||
        pattern = r"^.*: !airutilz(?: (\d+[mhdM]?))?$"
 | 
			
		||||
        match = re.match(pattern, full_message)
 | 
			
		||||
 | 
			
		||||
        if match:
 | 
			
		||||
            timeframe = match.group(1) or '1d'  # default to last 1 day
 | 
			
		||||
        else:
 | 
			
		||||
            timeframe = '1d'
 | 
			
		||||
 | 
			
		||||
        self.logger.debug(f"Extracted timeframe: {timeframe}")
 | 
			
		||||
 | 
			
		||||
        url = await self.get_image_url(timeframe)
 | 
			
		||||
        token = load_env_variable('GRAFANA_API_KEY')
 | 
			
		||||
        headers = {
 | 
			
		||||
            "Authorization": f"Bearer {token}"
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            self.logger.debug(f"Fetching image from URL: {url} with headers: {headers}")
 | 
			
		||||
            response = requests.get(url, headers=headers)
 | 
			
		||||
            response.raise_for_status()
 | 
			
		||||
            self.logger.info("Image successfully fetched from Grafana")
 | 
			
		||||
| 
						 | 
				
			
			@ -73,6 +117,7 @@ class Plugin(BasePlugin):
 | 
			
		|||
            return False
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            self.logger.debug(f"Processing image data")
 | 
			
		||||
            image = Image.open(io.BytesIO(response.content))
 | 
			
		||||
            await self.send_image(matrix_client, room.room_id, image)
 | 
			
		||||
            self.logger.info("Image successfully sent to room")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,8 @@ import requests
 | 
			
		|||
from PIL import Image
 | 
			
		||||
from nio import AsyncClient, UploadResponse
 | 
			
		||||
from plugins.base_plugin import BasePlugin
 | 
			
		||||
import re
 | 
			
		||||
from matrix_utils import connect_matrix
 | 
			
		||||
 | 
			
		||||
def load_env_variable(key):
 | 
			
		||||
    env_path = os.path.join(os.path.dirname(__file__), '.env')
 | 
			
		||||
| 
						 | 
				
			
			@ -14,6 +16,19 @@ def load_env_variable(key):
 | 
			
		|||
                return line.strip().split('=')[1].strip().strip('"')
 | 
			
		||||
    return None
 | 
			
		||||
 | 
			
		||||
def parse_timeframe(timeframe):
 | 
			
		||||
    unit_multipliers = {
 | 
			
		||||
        'm': 60,            # minute to seconds
 | 
			
		||||
        'h': 60 * 60,       # hour to seconds
 | 
			
		||||
        'd': 24 * 60 * 60,  # day to seconds
 | 
			
		||||
        'M': 30 * 24 * 60 * 60  # month to seconds (approximation)
 | 
			
		||||
    }
 | 
			
		||||
    match = re.match(r'(\d+)([mhdM])', timeframe)
 | 
			
		||||
    if match:
 | 
			
		||||
        value, unit = match.groups()
 | 
			
		||||
        return int(value) * unit_multipliers[unit]
 | 
			
		||||
    return 24 * 60 * 60  # default to 1 day in seconds
 | 
			
		||||
 | 
			
		||||
class Plugin(BasePlugin):
 | 
			
		||||
    plugin_name = "battery"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -21,7 +36,7 @@ class Plugin(BasePlugin):
 | 
			
		|||
    def description(self):
 | 
			
		||||
        return "Generates and returns Battery Level."
 | 
			
		||||
 | 
			
		||||
    async def get_image_url(self):
 | 
			
		||||
    async def get_image_url(self, timeframe):
 | 
			
		||||
        base_url = load_env_variable('GRAFANA_BASE_URL')
 | 
			
		||||
        org_id = "1"
 | 
			
		||||
        panel_id = "1"
 | 
			
		||||
| 
						 | 
				
			
			@ -31,13 +46,15 @@ class Plugin(BasePlugin):
 | 
			
		|||
        tz = "Europe/Warsaw"
 | 
			
		||||
 | 
			
		||||
        to_time = int(time.time() * 1000)
 | 
			
		||||
        from_time = to_time - 24 * 60 * 60 * 1000
 | 
			
		||||
        from_time = to_time - parse_timeframe(timeframe) * 1000
 | 
			
		||||
 | 
			
		||||
        url = (
 | 
			
		||||
            f"{base_url}?orgId={org_id}&from={from_time}&to={to_time}&"
 | 
			
		||||
            f"panelId={panel_id}&width={width}&height={height}&scale={scale}&tz={tz}"
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        self.logger.debug(f"Generated URL: {url}")
 | 
			
		||||
 | 
			
		||||
        return url
 | 
			
		||||
 | 
			
		||||
    async def handle_meshtastic_message(self, packet, formatted_message, longname, meshnet_name):
 | 
			
		||||
| 
						 | 
				
			
			@ -54,17 +71,44 @@ class Plugin(BasePlugin):
 | 
			
		|||
        if not self.matches(full_message):
 | 
			
		||||
            return False
 | 
			
		||||
 | 
			
		||||
        from matrix_utils import connect_matrix
 | 
			
		||||
        self.logger.debug(f"Received message: {full_message}")
 | 
			
		||||
 | 
			
		||||
        matrix_client = await connect_matrix()
 | 
			
		||||
 | 
			
		||||
        url = await self.get_image_url()
 | 
			
		||||
        # Check if the message is a help request
 | 
			
		||||
        if 'help' in full_message:
 | 
			
		||||
            help_message = ("Usage: !battery [timeframe]\n"
 | 
			
		||||
                            "Timeframe format examples:\n"
 | 
			
		||||
                            "5m - last 5 minutes\n"
 | 
			
		||||
                            "1h - last 1 hour\n"
 | 
			
		||||
                            "2d - last 2 days\n"
 | 
			
		||||
                            "1M - last 1 month")
 | 
			
		||||
            await matrix_client.room_send(
 | 
			
		||||
                room_id=room.room_id,
 | 
			
		||||
                message_type="m.room.message",
 | 
			
		||||
                content={"msgtype": "m.text", "body": help_message},
 | 
			
		||||
            )
 | 
			
		||||
            return True
 | 
			
		||||
 | 
			
		||||
        # Extract timeframe from the message
 | 
			
		||||
        pattern = r"^.*: !battery(?: (\d+[mhdM]?))?$"
 | 
			
		||||
        match = re.match(pattern, full_message)
 | 
			
		||||
 | 
			
		||||
        if match:
 | 
			
		||||
            timeframe = match.group(1) or '1d'  # default to last 1 day
 | 
			
		||||
        else:
 | 
			
		||||
            timeframe = '1d'
 | 
			
		||||
 | 
			
		||||
        self.logger.debug(f"Extracted timeframe: {timeframe}")
 | 
			
		||||
 | 
			
		||||
        url = await self.get_image_url(timeframe)
 | 
			
		||||
        token = load_env_variable('GRAFANA_API_KEY')
 | 
			
		||||
        headers = {
 | 
			
		||||
            "Authorization": f"Bearer {token}"
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            self.logger.debug(f"Fetching image from URL: {url} with headers: {headers}")
 | 
			
		||||
            response = requests.get(url, headers=headers)
 | 
			
		||||
            response.raise_for_status()
 | 
			
		||||
            self.logger.info("Image successfully fetched from Grafana")
 | 
			
		||||
| 
						 | 
				
			
			@ -73,6 +117,7 @@ class Plugin(BasePlugin):
 | 
			
		|||
            return False
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            self.logger.debug(f"Processing image data")
 | 
			
		||||
            image = Image.open(io.BytesIO(response.content))
 | 
			
		||||
            await self.send_image(matrix_client, room.room_id, image)
 | 
			
		||||
            self.logger.info("Image successfully sent to room")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,8 @@ import requests
 | 
			
		|||
from PIL import Image
 | 
			
		||||
from nio import AsyncClient, UploadResponse
 | 
			
		||||
from plugins.base_plugin import BasePlugin
 | 
			
		||||
import re
 | 
			
		||||
from matrix_utils import connect_matrix
 | 
			
		||||
 | 
			
		||||
def load_env_variable(key):
 | 
			
		||||
    env_path = os.path.join(os.path.dirname(__file__), '.env')
 | 
			
		||||
| 
						 | 
				
			
			@ -14,6 +16,19 @@ def load_env_variable(key):
 | 
			
		|||
                return line.strip().split('=')[1].strip().strip('"')
 | 
			
		||||
    return None
 | 
			
		||||
 | 
			
		||||
def parse_timeframe(timeframe):
 | 
			
		||||
    unit_multipliers = {
 | 
			
		||||
        'm': 60,            # minute to seconds
 | 
			
		||||
        'h': 60 * 60,       # hour to seconds
 | 
			
		||||
        'd': 24 * 60 * 60,  # day to seconds
 | 
			
		||||
        'M': 30 * 24 * 60 * 60  # month to seconds (approximation)
 | 
			
		||||
    }
 | 
			
		||||
    match = re.match(r'(\d+)([mhdM])', timeframe)
 | 
			
		||||
    if match:
 | 
			
		||||
        value, unit = match.groups()
 | 
			
		||||
        return int(value) * unit_multipliers[unit]
 | 
			
		||||
    return 24 * 60 * 60  # default to 1 day in seconds
 | 
			
		||||
 | 
			
		||||
class Plugin(BasePlugin):
 | 
			
		||||
    plugin_name = "chutilz"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -21,7 +36,7 @@ class Plugin(BasePlugin):
 | 
			
		|||
    def description(self):
 | 
			
		||||
        return "Generates and returns Channels utilization."
 | 
			
		||||
 | 
			
		||||
    async def get_image_url(self):
 | 
			
		||||
    async def get_image_url(self, timeframe):
 | 
			
		||||
        base_url = load_env_variable('GRAFANA_BASE_URL')
 | 
			
		||||
        org_id = "1"
 | 
			
		||||
        panel_id = "3"
 | 
			
		||||
| 
						 | 
				
			
			@ -31,13 +46,15 @@ class Plugin(BasePlugin):
 | 
			
		|||
        tz = "Europe/Warsaw"
 | 
			
		||||
 | 
			
		||||
        to_time = int(time.time() * 1000)
 | 
			
		||||
        from_time = to_time - 24 * 60 * 60 * 1000
 | 
			
		||||
        from_time = to_time - parse_timeframe(timeframe) * 1000
 | 
			
		||||
 | 
			
		||||
        url = (
 | 
			
		||||
            f"{base_url}?orgId={org_id}&from={from_time}&to={to_time}&"
 | 
			
		||||
            f"panelId={panel_id}&width={width}&height={height}&scale={scale}&tz={tz}"
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        self.logger.debug(f"Generated URL: {url}")
 | 
			
		||||
 | 
			
		||||
        return url
 | 
			
		||||
 | 
			
		||||
    async def handle_meshtastic_message(self, packet, formatted_message, longname, meshnet_name):
 | 
			
		||||
| 
						 | 
				
			
			@ -54,17 +71,44 @@ class Plugin(BasePlugin):
 | 
			
		|||
        if not self.matches(full_message):
 | 
			
		||||
            return False
 | 
			
		||||
 | 
			
		||||
        from matrix_utils import connect_matrix
 | 
			
		||||
        self.logger.debug(f"Received message: {full_message}")
 | 
			
		||||
 | 
			
		||||
        matrix_client = await connect_matrix()
 | 
			
		||||
 | 
			
		||||
        url = await self.get_image_url()
 | 
			
		||||
        # Check if the message is a help request
 | 
			
		||||
        if 'help' in full_message:
 | 
			
		||||
            help_message = ("Usage: !chutilz [timeframe]\n"
 | 
			
		||||
                            "Timeframe format examples:\n"
 | 
			
		||||
                            "5m - last 5 minutes\n"
 | 
			
		||||
                            "1h - last 1 hour\n"
 | 
			
		||||
                            "2d - last 2 days\n"
 | 
			
		||||
                            "1M - last 1 month")
 | 
			
		||||
            await matrix_client.room_send(
 | 
			
		||||
                room_id=room.room_id,
 | 
			
		||||
                message_type="m.room.message",
 | 
			
		||||
                content={"msgtype": "m.text", "body": help_message},
 | 
			
		||||
            )
 | 
			
		||||
            return True
 | 
			
		||||
 | 
			
		||||
        # Extract timeframe from the message
 | 
			
		||||
        pattern = r"^.*: !chutilz(?: (\d+[mhdM]?))?$"
 | 
			
		||||
        match = re.match(pattern, full_message)
 | 
			
		||||
 | 
			
		||||
        if match:
 | 
			
		||||
            timeframe = match.group(1) or '1d'  # default to last 1 day
 | 
			
		||||
        else:
 | 
			
		||||
            timeframe = '1d'
 | 
			
		||||
 | 
			
		||||
        self.logger.debug(f"Extracted timeframe: {timeframe}")
 | 
			
		||||
 | 
			
		||||
        url = await self.get_image_url(timeframe)
 | 
			
		||||
        token = load_env_variable('GRAFANA_API_KEY')
 | 
			
		||||
        headers = {
 | 
			
		||||
            "Authorization": f"Bearer {token}"
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            self.logger.debug(f"Fetching image from URL: {url} with headers: {headers}")
 | 
			
		||||
            response = requests.get(url, headers=headers)
 | 
			
		||||
            response.raise_for_status()
 | 
			
		||||
            self.logger.info("Image successfully fetched from Grafana")
 | 
			
		||||
| 
						 | 
				
			
			@ -73,6 +117,7 @@ class Plugin(BasePlugin):
 | 
			
		|||
            return False
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            self.logger.debug(f"Processing image data")
 | 
			
		||||
            image = Image.open(io.BytesIO(response.content))
 | 
			
		||||
            await self.send_image(matrix_client, room.room_id, image)
 | 
			
		||||
            self.logger.info("Image successfully sent to room")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,8 @@ import requests
 | 
			
		|||
from PIL import Image
 | 
			
		||||
from nio import AsyncClient, UploadResponse
 | 
			
		||||
from plugins.base_plugin import BasePlugin
 | 
			
		||||
import re
 | 
			
		||||
from matrix_utils import connect_matrix
 | 
			
		||||
 | 
			
		||||
def load_env_variable(key):
 | 
			
		||||
    env_path = os.path.join(os.path.dirname(__file__), '.env')
 | 
			
		||||
| 
						 | 
				
			
			@ -14,6 +16,19 @@ def load_env_variable(key):
 | 
			
		|||
                return line.strip().split('=')[1].strip().strip('"')
 | 
			
		||||
    return None
 | 
			
		||||
 | 
			
		||||
def parse_timeframe(timeframe):
 | 
			
		||||
    unit_multipliers = {
 | 
			
		||||
        'm': 60,            # minute to seconds
 | 
			
		||||
        'h': 60 * 60,       # hour to seconds
 | 
			
		||||
        'd': 24 * 60 * 60,  # day to seconds
 | 
			
		||||
        'M': 30 * 24 * 60 * 60  # month to seconds (approximation)
 | 
			
		||||
    }
 | 
			
		||||
    match = re.match(r'(\d+)([mhdM])', timeframe)
 | 
			
		||||
    if match:
 | 
			
		||||
        value, unit = match.groups()
 | 
			
		||||
        return int(value) * unit_multipliers[unit]
 | 
			
		||||
    return 24 * 60 * 60  # default to 1 day in seconds
 | 
			
		||||
 | 
			
		||||
class Plugin(BasePlugin):
 | 
			
		||||
    plugin_name = "snr"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -21,23 +36,25 @@ class Plugin(BasePlugin):
 | 
			
		|||
    def description(self):
 | 
			
		||||
        return "Generates and returns Signal to Noise Ratio (SNR)."
 | 
			
		||||
 | 
			
		||||
    async def get_image_url(self):
 | 
			
		||||
    async def get_image_url(self, timeframe):
 | 
			
		||||
        base_url = load_env_variable('GRAFANA_BASE_URL')
 | 
			
		||||
        org_id = "1"
 | 
			
		||||
        panel_id = "6"
 | 
			
		||||
        width = "1200"
 | 
			
		||||
        height = "600"
 | 
			
		||||
        scale = "1"
 | 
			
		||||
        scale = "2"
 | 
			
		||||
        tz = "Europe/Warsaw"
 | 
			
		||||
 | 
			
		||||
        to_time = int(time.time() * 1000)
 | 
			
		||||
        from_time = to_time - 24 * 60 * 60 * 1000
 | 
			
		||||
        from_time = to_time - parse_timeframe(timeframe) * 1000
 | 
			
		||||
 | 
			
		||||
        url = (
 | 
			
		||||
            f"{base_url}?orgId={org_id}&from={from_time}&to={to_time}&"
 | 
			
		||||
            f"panelId={panel_id}&width={width}&height={height}&scale={scale}&tz={tz}"
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        self.logger.debug(f"Generated URL: {url}")
 | 
			
		||||
 | 
			
		||||
        return url
 | 
			
		||||
 | 
			
		||||
    async def handle_meshtastic_message(self, packet, formatted_message, longname, meshnet_name):
 | 
			
		||||
| 
						 | 
				
			
			@ -54,17 +71,44 @@ class Plugin(BasePlugin):
 | 
			
		|||
        if not self.matches(full_message):
 | 
			
		||||
            return False
 | 
			
		||||
 | 
			
		||||
        from matrix_utils import connect_matrix
 | 
			
		||||
        self.logger.debug(f"Received message: {full_message}")
 | 
			
		||||
 | 
			
		||||
        matrix_client = await connect_matrix()
 | 
			
		||||
 | 
			
		||||
        url = await self.get_image_url()
 | 
			
		||||
        # Check if the message is a help request
 | 
			
		||||
        if 'help' in full_message:
 | 
			
		||||
            help_message = ("Usage: !snr [timeframe]\n"
 | 
			
		||||
                            "Timeframe format examples:\n"
 | 
			
		||||
                            "5m - last 5 minutes\n"
 | 
			
		||||
                            "1h - last 1 hour\n"
 | 
			
		||||
                            "2d - last 2 days\n"
 | 
			
		||||
                            "1M - last 1 month")
 | 
			
		||||
            await matrix_client.room_send(
 | 
			
		||||
                room_id=room.room_id,
 | 
			
		||||
                message_type="m.room.message",
 | 
			
		||||
                content={"msgtype": "m.text", "body": help_message},
 | 
			
		||||
            )
 | 
			
		||||
            return True
 | 
			
		||||
 | 
			
		||||
        # Extract timeframe from the message
 | 
			
		||||
        pattern = r"^.*: !snr(?: (\d+[mhdM]?))?$"
 | 
			
		||||
        match = re.match(pattern, full_message)
 | 
			
		||||
 | 
			
		||||
        if match:
 | 
			
		||||
            timeframe = match.group(1) or '1d'  # default to last 1 day
 | 
			
		||||
        else:
 | 
			
		||||
            timeframe = '1d'
 | 
			
		||||
 | 
			
		||||
        self.logger.debug(f"Extracted timeframe: {timeframe}")
 | 
			
		||||
 | 
			
		||||
        url = await self.get_image_url(timeframe)
 | 
			
		||||
        token = load_env_variable('GRAFANA_API_KEY')
 | 
			
		||||
        headers = {
 | 
			
		||||
            "Authorization": f"Bearer {token}"
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            self.logger.debug(f"Fetching image from URL: {url} with headers: {headers}")
 | 
			
		||||
            response = requests.get(url, headers=headers)
 | 
			
		||||
            response.raise_for_status()
 | 
			
		||||
            self.logger.info("Image successfully fetched from Grafana")
 | 
			
		||||
| 
						 | 
				
			
			@ -73,6 +117,7 @@ class Plugin(BasePlugin):
 | 
			
		|||
            return False
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            self.logger.debug(f"Processing image data")
 | 
			
		||||
            image = Image.open(io.BytesIO(response.content))
 | 
			
		||||
            await self.send_image(matrix_client, room.room_id, image)
 | 
			
		||||
            self.logger.info("Image successfully sent to room")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,8 @@ import requests
 | 
			
		|||
from PIL import Image
 | 
			
		||||
from nio import AsyncClient, UploadResponse
 | 
			
		||||
from plugins.base_plugin import BasePlugin
 | 
			
		||||
import re
 | 
			
		||||
from matrix_utils import connect_matrix
 | 
			
		||||
 | 
			
		||||
def load_env_variable(key):
 | 
			
		||||
    env_path = os.path.join(os.path.dirname(__file__), '.env')
 | 
			
		||||
| 
						 | 
				
			
			@ -14,6 +16,19 @@ def load_env_variable(key):
 | 
			
		|||
                return line.strip().split('=')[1].strip().strip('"')
 | 
			
		||||
    return None
 | 
			
		||||
 | 
			
		||||
def parse_timeframe(timeframe):
 | 
			
		||||
    unit_multipliers = {
 | 
			
		||||
        'm': 60,            # minute to seconds
 | 
			
		||||
        'h': 60 * 60,       # hour to seconds
 | 
			
		||||
        'd': 24 * 60 * 60,  # day to seconds
 | 
			
		||||
        'M': 30 * 24 * 60 * 60  # month to seconds (approximation)
 | 
			
		||||
    }
 | 
			
		||||
    match = re.match(r'(\d+)([mhdM])', timeframe)
 | 
			
		||||
    if match:
 | 
			
		||||
        value, unit = match.groups()
 | 
			
		||||
        return int(value) * unit_multipliers[unit]
 | 
			
		||||
    return 24 * 60 * 60  # default to 1 day in seconds
 | 
			
		||||
 | 
			
		||||
class Plugin(BasePlugin):
 | 
			
		||||
    plugin_name = "voltage"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -21,7 +36,7 @@ class Plugin(BasePlugin):
 | 
			
		|||
    def description(self):
 | 
			
		||||
        return "Generates and returns Voltage."
 | 
			
		||||
 | 
			
		||||
    async def get_image_url(self):
 | 
			
		||||
    async def get_image_url(self, timeframe):
 | 
			
		||||
        base_url = load_env_variable('GRAFANA_BASE_URL')
 | 
			
		||||
        org_id = "1"
 | 
			
		||||
        panel_id = "6"
 | 
			
		||||
| 
						 | 
				
			
			@ -31,13 +46,15 @@ class Plugin(BasePlugin):
 | 
			
		|||
        tz = "Europe/Warsaw"
 | 
			
		||||
 | 
			
		||||
        to_time = int(time.time() * 1000)
 | 
			
		||||
        from_time = to_time - 24 * 60 * 60 * 1000
 | 
			
		||||
        from_time = to_time - parse_timeframe(timeframe) * 1000
 | 
			
		||||
 | 
			
		||||
        url = (
 | 
			
		||||
            f"{base_url}?orgId={org_id}&from={from_time}&to={to_time}&"
 | 
			
		||||
            f"panelId={panel_id}&width={width}&height={height}&scale={scale}&tz={tz}"
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        self.logger.debug(f"Generated URL: {url}")
 | 
			
		||||
 | 
			
		||||
        return url
 | 
			
		||||
 | 
			
		||||
    async def handle_meshtastic_message(self, packet, formatted_message, longname, meshnet_name):
 | 
			
		||||
| 
						 | 
				
			
			@ -54,17 +71,44 @@ class Plugin(BasePlugin):
 | 
			
		|||
        if not self.matches(full_message):
 | 
			
		||||
            return False
 | 
			
		||||
 | 
			
		||||
        from matrix_utils import connect_matrix
 | 
			
		||||
        self.logger.debug(f"Received message: {full_message}")
 | 
			
		||||
 | 
			
		||||
        matrix_client = await connect_matrix()
 | 
			
		||||
 | 
			
		||||
        url = await self.get_image_url()
 | 
			
		||||
        # Check if the message is a help request
 | 
			
		||||
        if 'help' in full_message:
 | 
			
		||||
            help_message = ("Usage: !voltage [timeframe]\n"
 | 
			
		||||
                            "Timeframe format examples:\n"
 | 
			
		||||
                            "5m - last 5 minutes\n"
 | 
			
		||||
                            "1h - last 1 hour\n"
 | 
			
		||||
                            "2d - last 2 days\n"
 | 
			
		||||
                            "1M - last 1 month")
 | 
			
		||||
            await matrix_client.room_send(
 | 
			
		||||
                room_id=room.room_id,
 | 
			
		||||
                message_type="m.room.message",
 | 
			
		||||
                content={"msgtype": "m.text", "body": help_message},
 | 
			
		||||
            )
 | 
			
		||||
            return True
 | 
			
		||||
 | 
			
		||||
        # Extract timeframe from the message
 | 
			
		||||
        pattern = r"^.*: !voltage(?: (\d+[mhdM]?))?$"
 | 
			
		||||
        match = re.match(pattern, full_message)
 | 
			
		||||
 | 
			
		||||
        if match:
 | 
			
		||||
            timeframe = match.group(1) or '1d'  # default to last 1 day
 | 
			
		||||
        else:
 | 
			
		||||
            timeframe = '1d'
 | 
			
		||||
 | 
			
		||||
        self.logger.debug(f"Extracted timeframe: {timeframe}")
 | 
			
		||||
 | 
			
		||||
        url = await self.get_image_url(timeframe)
 | 
			
		||||
        token = load_env_variable('GRAFANA_API_KEY')
 | 
			
		||||
        headers = {
 | 
			
		||||
            "Authorization": f"Bearer {token}"
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            self.logger.debug(f"Fetching image from URL: {url} with headers: {headers}")
 | 
			
		||||
            response = requests.get(url, headers=headers)
 | 
			
		||||
            response.raise_for_status()
 | 
			
		||||
            self.logger.info("Image successfully fetched from Grafana")
 | 
			
		||||
| 
						 | 
				
			
			@ -73,6 +117,7 @@ class Plugin(BasePlugin):
 | 
			
		|||
            return False
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            self.logger.debug(f"Processing image data")
 | 
			
		||||
            image = Image.open(io.BytesIO(response.content))
 | 
			
		||||
            await self.send_image(matrix_client, room.room_id, image)
 | 
			
		||||
            self.logger.info("Image successfully sent to room")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Ładowanie…
	
		Reference in New Issue