newNews🚨🚨

the location of news.txt changed FYI 🚨 now you can read more files
This commit is contained in:
SpudGunMan
2025-10-08 01:14:10 -07:00
parent 691bc8d701
commit 2895e6c034
7 changed files with 59 additions and 17 deletions
+8 -3
View File
@@ -72,7 +72,7 @@ Welcome to the Mesh Bot project! This feature-rich bot is designed to enhance yo
### File Monitor Alerts
- **File Monitor**: Monitor a flat/text file for changes, broadcast the contents of the message to the mesh channel.
- **News File**: On request of news, the contents of the file are returned.
- **News File**: On request of news, the contents of the file are returned. Can also call multiple news sources or files.
- **Shell Command Access**: Pass commands via DM directly to the host OS
### Data Reporting
@@ -147,7 +147,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 (news.txt, by default) via the chunker on air | ✅ |
| `readnews` | returns the contents of a file (data/news.txt, by default) can also `news mesh` via the chunker on air | ✅ |
| `satpass` | returns the pass info from API for defined NORAD ID in config or Example: `satpass 25544,33591`| |
| `wiki:` | Searches Wikipedia 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 | ✅ |
@@ -451,7 +451,12 @@ rtl_fm -f 162425000 -s 22050 | multimon-ng -t raw -a EAS /dev/stdin | python eas
```
#### Newspaper on mesh
a newspaper could be built by external scripts. could use Ollama to compile text via news web pages and write news.txt
Maintain multiple news sources. Each source should be a file named `{source}_news.txt` in the `data/` directory (for example, `data/mesh_news.txt`).
- To read the default news, use the `readnews` command (reads from `data/news.txt`.
- To read a specific source, use `readnews abc` to read from `data/abc_news.txt`.
This allows you to organize and access different news feeds or categories easily.
External scripts can update these files as needed, and the bot will serve the latest content on request.
### Greet new nodes QRZ module
This isnt QRZ.com this is Q code for who is calling me, this will track new nodes and say hello
+1 -1
View File
@@ -284,7 +284,7 @@ broadcastCh = 2
# news command will return the contents of a text file
enable_read_news = False
news_file_path = news.txt
news_file_path = ../data/news.txt
# only return a single random line from the news file
news_random_line = False
+1
View File
@@ -0,0 +1 @@
Today in meshtastic you are looking at the coolest bot on the block.
+21 -1
View File
@@ -75,7 +75,7 @@ def auto_response(message, snr, rssi, hop, pkiStatus, message_from_id, channel_n
"pong": lambda: "🏓PING!!🛜",
"q:": lambda: quizHandler(message, message_from_id, deviceID),
"quiz": lambda: quizHandler(message, message_from_id, deviceID),
"readnews": lambda: read_news(),
"readnews": lambda: handleNews(message_from_id, deviceID, message, isDM),
"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),
@@ -333,6 +333,26 @@ def handle_wxalert(message_from_id, deviceID, message):
weatherAlert = weatherAlert[0]
return weatherAlert
def handleNews(message_from_id, deviceID, message, isDM):
news = ''
# if news source is provided pass that to read_news()
if "?" in message.lower():
return "returns the news. Add a source e.g. 📰readnews mesh"
elif "readnews" in message.lower():
source = message.lower().replace("readnews", "").strip()
if source:
news = read_news(source)
else:
news = read_news()
if news:
# if not a DM add the username to the beginning of msg
if not useDMForResponse and not isDM:
news = "@" + get_name_from_number(message_from_id, 'short', deviceID) + " " + news
return news
else:
return "No news for you!"
def handle_howfar(message, message_from_id, deviceID, isDM):
msg = ''
location = get_node_location(message_from_id, deviceID)
+27 -10
View File
@@ -9,11 +9,12 @@ import subprocess
trap_list_filemon = ("readnews",)
def read_file(file_monitor_file_path, random_line_only=False):
NEWS_DATA_DIR = os.path.join(os.path.dirname(__file__), '..', 'data')
newsSourcesList = []
def read_file(file_monitor_file_path, random_line_only=False):
try:
if not os.path.exists(file_monitor_file_path):
logger.warning(f"FileMon: File not found: {file_monitor_file_path}")
if file_monitor_file_path == "bee.txt":
return "🐝buzz 💐buzz buzz🍯"
if random_line_only:
@@ -29,21 +30,25 @@ def read_file(file_monitor_file_path, random_line_only=False):
except Exception as e:
logger.warning(f"FileMon: Error reading file: {file_monitor_file_path}")
return None
def read_news():
# read the news file on demand
return read_file(news_file_path, news_random_line_only)
def read_news(source=None):
# Reads the news file. If a source is provided, reads {source}_news.txt.
if source:
file_path = os.path.join(NEWS_DATA_DIR, f"{source}_news.txt")
else:
file_path = os.path.join(NEWS_DATA_DIR, news_file_path)
return read_file(file_path, news_random_line_only)
def write_news(content, append=False):
# write the news file on demand
try:
with open(news_file_path, 'a' if append else 'w', encoding='utf-8') as f:
f.write(content)
logger.info(f"FileMon: Updated {news_file_path}")
file_path = os.path.join(NEWS_DATA_DIR, news_file_path)
with open(file_path, 'a' if append else 'w', encoding='utf-8') as f:
#f.write(content)
logger.info(f"FileMon: Updated {file_path}")
return True
except Exception as e:
logger.warning(f"FileMon: Error writing file: {news_file_path}")
logger.warning(f"FileMon: Error writing file: {file_path}")
return False
async def watch_file():
@@ -119,3 +124,15 @@ def handleShellCmd(message, message_from_id, channel_number, isDM, deviceID):
return "x: command is disabled"
return "x: command executed with no output"
def initNewsSources():
#check for the files _news.txt and add to the newsHeadlines list
global newsSourcesList
newsSourcesList = []
for file in os.listdir(NEWS_DATA_DIR):
if file.endswith('_news.txt'):
source = file[:-9] # remove _news.txt
newsSourcesList.append(source)
#initialize the headlines on startup
initNewsSources()
+1 -1
View File
@@ -359,7 +359,7 @@ try:
file_monitor_file_path = config['fileMon'].get('file_path', 'alert.txt') # default alert.txt
file_monitor_broadcastCh = config['fileMon'].get('broadcastCh', '2').split(',') # default Channel 2
read_news_enabled = config['fileMon'].getboolean('enable_read_news', False) # default disabled
news_file_path = config['fileMon'].get('news_file_path', 'news.txt') # default news.txt
news_file_path = config['fileMon'].get('news_file_path', '../data/news.txt') # default ../data/news.txt
news_random_line_only = config['fileMon'].getboolean('news_random_line', False) # default False
enable_runShellCmd = config['fileMon'].getboolean('enable_runShellCmd', False) # default False
allowXcmd = config['fileMon'].getboolean('allowXcmd', False) # default False
-1
View File
@@ -1 +0,0 @@
no new news is good news!