From 4da3e68c62b496f77ff994ae66d8e5f7ebda7bf1 Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Thu, 9 Oct 2025 19:06:38 -0700 Subject: [PATCH] readrss thanks FJRP you can now return an rss feed --- README.md | 4 +++- config.template | 6 ++++++ mesh_bot.py | 3 +++ modules/rss.py | 33 +++++++++++++++++++++++++++++++++ modules/settings.py | 4 ++++ modules/system.py | 6 ++++++ 6 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 modules/rss.py diff --git a/README.md b/README.md index a2255e0..0e4ee9e 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,7 @@ Welcome to the Mesh Bot project! This feature-rich bot is designed to enhance yo ### Data Reporting - **HTML Generator**: Visualize bot traffic and data flows with a built-in HTML generator for [data reporting](logs/README.md). +- **RSS and news feeds**: Get data in mesh from many sources! ### Robust Message Handling - **Message Chunking**: Automatically chunk messages over 160 characters to ensure higher delivery success across hops. @@ -149,6 +150,7 @@ git clone https://github.com/spudgunman/meshing-around | `askai` and `ask:` | Ask Ollama LLM AI for a response. Example: `askai what temp do I cook chicken` | ✅ | | `messages` | Replays the last messages heard on device, like Store and Forward, returns the PublicChannel and Current | ✅ | | `readnews` | returns the contents of a file (data/news.txt, by default) can also `news mesh` via the chunker on air | ✅ | +| `readrss` | returns a set RSS feed on air | | | `satpass` | returns the pass info from API for defined NORAD ID in config or Example: `satpass 25544,33591`| | | `wiki:` | Searches Wikipedia (or local Kiwix server) and returns the first few sentences of the first result if a match. Example: `wiki: lora radio` | | `howfar` | returns the distance you have traveled since your last HowFar. `howfar reset` to start over | ✅ | @@ -576,7 +578,7 @@ I used ideas and snippets from other responder bots and want to call them out! - **mikecarper**: ideas, and testing. hamtest - **c.merphy360**: high altitude alerts - **Iris**: testing and finding 🐞 -- **Cisien, bitflip, Woof, propstg, snydermesh, trs2982, Josh, mesb1, and Hailo1999**: For testing and feature ideas on Discord and GitHub. +- **Cisien, bitflip, Woof, propstg, snydermesh, trs2982, FJRPilot, Josh, mesb1, and Hailo1999**: For testing and feature ideas on Discord and GitHub. - **Meshtastic Discord Community**: For tossing out ideas and testing code. ### Tools diff --git a/config.template b/config.template index 73f0245..ef684f9 100644 --- a/config.template +++ b/config.template @@ -55,6 +55,12 @@ DadJokesEmoji = False # enable or disable the Solar module spaceWeather = True +# enable or disable the RSS module, and truncate the story +rssEnable = True +rssFeedURL = http://www.hackaday.com/rss.xml +rssMaxItems = 3 +rssTruncate = 100 + # enable or disable the wikipedia search module wikipedia = True # Use local Kiwix server instead of online Wikipedia diff --git a/mesh_bot.py b/mesh_bot.py index 5fdc5cb..d2e6ec3 100755 --- a/mesh_bot.py +++ b/mesh_bot.py @@ -77,6 +77,7 @@ def auto_response(message, snr, rssi, hop, pkiStatus, message_from_id, channel_n "q:": lambda: quizHandler(message, message_from_id, deviceID), "quiz": lambda: quizHandler(message, message_from_id, deviceID), "readnews": lambda: handleNews(message_from_id, deviceID, message, isDM), + "readrss": lambda: get_rss_feed() if rssEnable else "RSS feed module is disabled", "riverflow": lambda: handle_riverFlow(message, message_from_id, deviceID), "rlist": lambda: handle_repeaterQuery(message_from_id, deviceID, channel_number), "satpass": lambda: handle_satpass(message_from_id, deviceID, channel_number, message), @@ -1701,6 +1702,8 @@ async def start_rx(): logger.debug("System: Games Enabled!") if wikipedia_enabled: logger.debug("System: Wikipedia search Enabled") + if rssEnabled: + logger.debug(f"System: RSS Feed Reader Enabled for {rssFeedURL}") if motd_enabled: logger.debug(f"System: MOTD Enabled using {MOTD}") if sentry_enabled: diff --git a/modules/rss.py b/modules/rss.py new file mode 100644 index 0000000..7d01927 --- /dev/null +++ b/modules/rss.py @@ -0,0 +1,33 @@ +# rss feed module for meshing-around 2025 +from modules.log import * +import urllib.request +import xml.etree.ElementTree as ET + +RSS_FEED_URL = rssFeedURL +RSS_RETURN_COUNT = rssMaxItems +RSS_TRIM_LENGTH = rssTruncate + +def get_rss_feed(): + try: + with urllib.request.urlopen(RSS_FEED_URL) as response: + xml_data = response.read() + root = ET.fromstring(xml_data) + items = root.findall('.//item')[:RSS_RETURN_COUNT] + if not items: + return "No RSS feed entries found." + formatted_entries = [] + for item in items: + title = item.findtext('title', default='No title') + link = item.findtext('link', default='No link') + description = item.findtext('description', default='No description') + pub_date = item.findtext('pubDate', default='No date') + + # strip all HTML tags and markup + description = ''.join(ET.fromstring(f"
{description}
").itertext()) + if len(description) > RSS_TRIM_LENGTH: + description = description[:97] + "..." + + formatted_entries.append(f"{title}\n{description}\n") + return "\n".join(formatted_entries) + except Exception as e: + return f"Error fetching RSS feed: {e}" diff --git a/modules/settings.py b/modules/settings.py index ea71ea8..ab557fd 100644 --- a/modules/settings.py +++ b/modules/settings.py @@ -240,6 +240,10 @@ try: favoriteNodeList = config['general'].get('favoriteNodeList', '').split(',') enableEcho = config['general'].getboolean('enableEcho', False) # default False echoChannel = config['general'].getint('echoChannel', '9') # default 9, empty string to ignore + rssEnable = config['general'].getboolean('rssEnable', True) # default True + rssFeedURL = config['general'].get('rssFeedURL', 'http://www.hackaday.com/rss.xml') + rssMaxItems = config['general'].getint('rssMaxItems', 3) # default 3 items + rssTruncate = config['general'].getint('rssTruncate', 100) # default 100 characters # emergency response emergency_responder_enabled = config['emergencyHandler'].getboolean('enabled', False) diff --git a/modules/system.py b/modules/system.py index 9c8b59a..02bffcd 100644 --- a/modules/system.py +++ b/modules/system.py @@ -210,6 +210,12 @@ if wikipedia_enabled: trap_list = trap_list + ("wiki:",) help_message = help_message + ", wiki:" +# RSS Feed Configuration +if rssEnable: + from modules.rss import * # from the spudgunman/meshing-around repo + trap_list = trap_list + ("readrss",) + help_message = help_message + ", readrss" + # LLM Configuration if llm_enabled: from modules.llm import * # from the spudgunman/meshing-around repo