mirror of
https://github.com/SpudGunMan/meshing-around.git
synced 2026-03-28 17:32:36 +01:00
Compare commits
79 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4b79c6304f | ||
|
|
22f63e1056 | ||
|
|
bf1613ba66 | ||
|
|
38e04db0cb | ||
|
|
08cc3034a2 | ||
|
|
a0eb176b6e | ||
|
|
a43774b33f | ||
|
|
8369b4d205 | ||
|
|
87e51cf9f9 | ||
|
|
8a8fb79fde | ||
|
|
1dc4cf36b1 | ||
|
|
75cf43e02a | ||
|
|
dd8357453b | ||
|
|
e9b273a62c | ||
|
|
ebebd0fda6 | ||
|
|
3e06902b07 | ||
|
|
a874b42c41 | ||
|
|
4fad58f7fe | ||
|
|
276e4c3d09 | ||
|
|
8aef4d605b | ||
|
|
962c891baa | ||
|
|
eb596ea901 | ||
|
|
e708ec9adc | ||
|
|
c631a083ea | ||
|
|
169ea8c233 | ||
|
|
241e2258e8 | ||
|
|
5d2d6bc5fb | ||
|
|
c7ef22f5c2 | ||
|
|
3ec89decf0 | ||
|
|
2693f47ed5 | ||
|
|
496a13e0e0 | ||
|
|
71ef416dbb | ||
|
|
5bc80c8677 | ||
|
|
8c300f467c | ||
|
|
78b3bf1475 | ||
|
|
ce74f910a7 | ||
|
|
ece531249e | ||
|
|
5052e2510e | ||
|
|
b8f8f80499 | ||
|
|
a13d98e32b | ||
|
|
94996dcec8 | ||
|
|
4b8ce30df8 | ||
|
|
485a37e9b5 | ||
|
|
b41adb12f7 | ||
|
|
a9cd443bdd | ||
|
|
92b9df718f | ||
|
|
a6a4f91d83 | ||
|
|
0fb2c498f4 | ||
|
|
d87e70f7ee | ||
|
|
bee8bae0ae | ||
|
|
d5ef277121 | ||
|
|
dfc8e6c108 | ||
|
|
9100aee91f | ||
|
|
c94cc92d1c | ||
|
|
a41f5e3aca | ||
|
|
cc2d15de0d | ||
|
|
39e08aedae | ||
|
|
fe8730fb1f | ||
|
|
aac3ac8947 | ||
|
|
1acc908bb8 | ||
|
|
47ed98a5e1 | ||
|
|
103034d1b8 | ||
|
|
608714d00a | ||
|
|
575c287860 | ||
|
|
820470bef7 | ||
|
|
ea000ef56c | ||
|
|
793b8f8495 | ||
|
|
373eee3024 | ||
|
|
194273635e | ||
|
|
0972d7d89d | ||
|
|
d1415f9d86 | ||
|
|
b3ff3bb406 | ||
|
|
1efce62a8a | ||
|
|
442f2ff927 | ||
|
|
84cefa1be8 | ||
|
|
45e9c1eccb | ||
|
|
e7e2c9604e | ||
|
|
edaf6875ef | ||
|
|
e7976a0a88 |
10
README.md
10
README.md
@@ -46,6 +46,7 @@ Any messages that are over 160 characters are chunked into 160 message bytes to
|
||||
- `messages` Replay the last messages heard, like Store and Forward
|
||||
- `motd` or to set the message `motd $New Message Of the day`
|
||||
- `lheard` returns the last 5 heard nodes with SNR, can also use `sitrep`
|
||||
- `history` returns the last commands ran by user(s)
|
||||
- `cmd` returns the list of commands (the help message)
|
||||
- Games
|
||||
- `lemonstand` plays the classic Lemonade Stand Finance game via DM
|
||||
@@ -121,6 +122,13 @@ enabled = False
|
||||
DadJokes = False
|
||||
StoreForward = False
|
||||
```
|
||||
History command is like a linix terminal, shows the last commands the user ran and the `lheard` reflects last users on the bot.
|
||||
```
|
||||
# history command
|
||||
enableCmdHistory = True
|
||||
# command history ignore list ex: 2813308004,4258675309
|
||||
lheardCmdIgnoreNodes =
|
||||
```
|
||||
Sentry Bot detects anyone coming close to the bot-node
|
||||
```
|
||||
# detect anyone close to the bot
|
||||
@@ -258,5 +266,5 @@ Games Ported from..
|
||||
- https://github.com/devtronvarma/Video-Poker-Terminal-Game
|
||||
|
||||
GitHub user Nestpebble, for new ideas and enhancments, mrpatrick1991 For Docker configs, PiDiBi looking at test functions and other suggestions like wxc, CPU use, and alerting ideas
|
||||
Discord and Mesh user Cisien, and github Hailo1999, for testing and ideas! Lots of individuals on the Meshtastic discord who have tossed out ideas and tested code!
|
||||
Discord and Mesh user Cisien, bitflip, and github Hailo1999, for testing and feature ideas! Lots of individuals on the Meshtastic discord who have tossed out ideas and tested code!
|
||||
|
||||
|
||||
@@ -45,6 +45,10 @@ ollama = False
|
||||
# StoreForward Enabled and Limits
|
||||
StoreForward = True
|
||||
StoreLimit = 3
|
||||
# history command
|
||||
enableCmdHistory = True
|
||||
# command history ignore list ex: 2813308004,4258675309
|
||||
lheardCmdIgnoreNodes =
|
||||
# 24 hour clock
|
||||
zuluTime = False
|
||||
# wait time for URL requests
|
||||
@@ -121,6 +125,6 @@ signalCycleLimit = 5
|
||||
# delay in seconds for response to avoid message collision
|
||||
responseDelay = 0.7
|
||||
# delay in seconds for splits in messages to avoid message collision
|
||||
splitDelay = 0.7
|
||||
splitDelay = 0.0
|
||||
# message chunk size for sending at high success rate
|
||||
MESSAGE_CHUNK_SIZE = 160
|
||||
|
||||
@@ -6,42 +6,42 @@ import pickle # pip install pickle
|
||||
try:
|
||||
with open('../bbsdb.pkl', 'rb') as f:
|
||||
bbs_messages = pickle.load(f)
|
||||
except:
|
||||
except Exception as e:
|
||||
try:
|
||||
with open('bbsdb.pkl', 'rb') as f:
|
||||
bbs_messages = pickle.load(f)
|
||||
except:
|
||||
except Exception as e:
|
||||
print ("\nSystem: bbsdb.pkl not found")
|
||||
|
||||
try:
|
||||
with open('../bbsdm.pkl', 'rb') as f:
|
||||
bbs_dm = pickle.load(f)
|
||||
except:
|
||||
except Exception as e:
|
||||
try:
|
||||
with open('bbsdm.pkl', 'rb') as f:
|
||||
bbs_dm = pickle.load(f)
|
||||
except:
|
||||
except Exception as e:
|
||||
print ("\nSystem: bbsdm.pkl not found")
|
||||
|
||||
# Game HS tables
|
||||
try:
|
||||
with open('../lemonade_hs.pkl', 'rb') as f:
|
||||
lemon_score = pickle.load(f)
|
||||
except:
|
||||
except Exception as e:
|
||||
try:
|
||||
with open('lemonade_hs.pkl', 'rb') as f:
|
||||
lemon_score = pickle.load(f)
|
||||
except:
|
||||
except Exception as e:
|
||||
print ("\nSystem: lemonade_hs.pkl not found")
|
||||
|
||||
try:
|
||||
with open('../dopewar_hs.pkl', 'rb') as f:
|
||||
dopewar_score = pickle.load(f)
|
||||
except:
|
||||
except Exception as e:
|
||||
try:
|
||||
with open('dopewar_hs.pkl', 'rb') as f:
|
||||
dopewar_score = pickle.load(f)
|
||||
except:
|
||||
except Exception as e:
|
||||
print ("\nSystem: dopewar_hs.pkl not found")
|
||||
|
||||
|
||||
|
||||
@@ -7,8 +7,12 @@ Description=MESH-BOT
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=pi
|
||||
Group=pi
|
||||
WorkingDirectory=/dir/
|
||||
ExecStart=/usr/bin/bash /dir/launch.sh mesh
|
||||
ExecStart=python3 mesh_bot.py
|
||||
ExecStop=pkill -f mesh_bot.py
|
||||
|
||||
# Disable Python's buffering of STDOUT and STDERR, so that output from the
|
||||
# service shows up immediately in systemd's logs
|
||||
|
||||
@@ -7,8 +7,12 @@ Description=PONG-BOT
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=pi
|
||||
Group=pi
|
||||
WorkingDirectory=/dir/
|
||||
ExecStart=/usr/bin/bash /dir/launch.sh pong
|
||||
ExecStart=python3 pong_bot.py
|
||||
ExecStop=pkill -f pong_bot.py
|
||||
|
||||
# Disable Python's buffering of STDOUT and STDERR, so that output from the
|
||||
# service shows up immediately in systemd's logs
|
||||
|
||||
68
install.sh
68
install.sh
@@ -2,8 +2,13 @@
|
||||
|
||||
# install.sh
|
||||
cd "$(dirname "$0")"
|
||||
program_path=$(pwd)
|
||||
cp etc/pong_bot.tmp etc/pong_bot.service
|
||||
cp etc/mesh_bot.tmp etc/mesh_bot.service
|
||||
|
||||
printf "\nMeshing Around Installer\n"
|
||||
printf "\nThis script will install the Meshing Around bot and its dependencies works best in debian/ubuntu\n"
|
||||
printf "\nChecking for dependencies\n"
|
||||
|
||||
|
||||
# add user to groups for serial access
|
||||
@@ -33,21 +38,12 @@ printf "\nConfig file generated\n"
|
||||
# set virtual environment and install dependencies
|
||||
printf "\nMeshing Around Installer\n"
|
||||
|
||||
#check if python3 has venv module
|
||||
if ! python3 -m venv --help &> /dev/null
|
||||
then
|
||||
printf "Python3 venv module not found, please install python3-venv with your OS\n"
|
||||
else
|
||||
printf "Python3 venv module found\n"
|
||||
fi
|
||||
|
||||
echo "Do you want to install the bot in a virtual environment? (y/n)"
|
||||
read venv
|
||||
|
||||
if [ $venv == "y" ]; then
|
||||
# set virtual environment
|
||||
if ! python3 -m venv --help &> /dev/null
|
||||
then
|
||||
if ! python3 -m venv --help &> /dev/null; then
|
||||
printf "Python3 venv module not found, please install python3-venv with your OS\n"
|
||||
exit 1
|
||||
else
|
||||
@@ -55,13 +51,28 @@ if [ $venv == "y" ]; then
|
||||
python3 -m venv venv
|
||||
source venv/bin/activate
|
||||
|
||||
# install dependencies
|
||||
pip install -U -r requirements.txt
|
||||
#check if python3 has venv module
|
||||
if [ -f venv/bin/activate ]; then
|
||||
printf "\nFpund virtual environment for python\n"
|
||||
else
|
||||
sudo apt-get install python3-venv
|
||||
printf "\nPython3 venv module not found, please install python3-venv with your OS if not already done. re-run the script\n"
|
||||
exxt 1
|
||||
fi
|
||||
|
||||
# config service files for virtual environment
|
||||
replace="s|python3 mesh_bot.py|/usr/bin/bash launch.sh mesh|g"
|
||||
sed -i "$replace" etc/mesh_bot.service
|
||||
replace="s|python3 pong_bot.py|/usr/bin/bash launch.sh pong|g"
|
||||
sed -i "$replace" etc/pong_bot.service
|
||||
|
||||
# install dependencies
|
||||
pip install -U -r requirements.txt
|
||||
fi
|
||||
else
|
||||
printf "\nSkipping virtual environment...\n"
|
||||
# install dependencies
|
||||
printf "Are you on Raspberry Pi?\nshould we add --break-system-packages to the pip install command? (y/n)"
|
||||
printf "Are you on Raspberry Pi(debian/ubuntu)?\nshould we add --break-system-packages to the pip install command? (y/n)"
|
||||
read rpi
|
||||
if [ $rpi == "y" ]; then
|
||||
pip install -U -r requirements.txt --break-system-packages
|
||||
@@ -74,33 +85,39 @@ printf "\n\n"
|
||||
echo "Which bot do you want to install as a service? Pong Mesh or None? (pong/mesh/n)"
|
||||
read bot
|
||||
|
||||
#set the correct path in the service file
|
||||
program_path=$(pwd)
|
||||
cp etc/pong_bot.tmp etc/pong_bot.service
|
||||
cp etc/mesh_bot.tmp etc/mesh_bot.service
|
||||
# set the correct path in the service file
|
||||
replace="s|/dir/|$program_path/|g"
|
||||
sed -i $replace etc/pong_bot.service
|
||||
sed -i $replace etc/mesh_bot.service
|
||||
# set the correct user in the service file?
|
||||
whoami=$(whoami)
|
||||
replace="s|User=pi|User=$whoami|g"
|
||||
sed -i $replace etc/pong_bot.service
|
||||
sed -i $replace etc/mesh_bot.service
|
||||
replace="s|Group=pi|Group=$whoami|g"
|
||||
sed -i $replace etc/pong_bot.service
|
||||
sed -i $replace etc/mesh_bot.service
|
||||
sudo systemctl daemon-reload
|
||||
printf "\n service files updated\n"
|
||||
|
||||
# ask if emoji font should be installed for linux
|
||||
echo "Do you want to install the emoji font for debian linux? (y/n)"
|
||||
echo "Do you want to install the emoji font for debian/ubuntu linux? (y/n)"
|
||||
read emoji
|
||||
if [ $emoji == "y" ]; then
|
||||
sudo apt-get install fonts-noto-color-emoji
|
||||
sudo apt-get install -y fonts-noto-color-emoji
|
||||
echo "Emoji font installed!, reboot to load the font"
|
||||
fi
|
||||
|
||||
if [ $bot == "pong" ]; then
|
||||
# install service for pong bot
|
||||
sudo cp etc/pong_bot.service /etc/systemd/system/
|
||||
exit 0
|
||||
sudo systemctl enable pong_bot.service
|
||||
fi
|
||||
|
||||
if [ $bot == "mesh" ]; then
|
||||
# install service for mesh bot
|
||||
sudo cp etc/mesh_bot.service /etc/systemd/system/
|
||||
exit 0
|
||||
sudo systemctl enable mesh_bot.service
|
||||
fi
|
||||
|
||||
if [ $bot == "n" ]; then
|
||||
@@ -124,11 +141,14 @@ if [ $ollama == "y" ]; then
|
||||
echo "Do you want to install the Gemma2:2b components? (y/n)"
|
||||
read gemma
|
||||
if [ $gemma == "y" ]; then
|
||||
olamma pull gemma2:2b
|
||||
ollama pull gemma2:2b
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Good time to reboot? (y/n)"
|
||||
read reboot
|
||||
if [ $reboot == "y" ]; then
|
||||
sudo reboot
|
||||
fi
|
||||
|
||||
|
||||
printf "\nGoodbye!"
|
||||
exit 0
|
||||
|
||||
347
mesh_bot.py
347
mesh_bot.py
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python3
|
||||
#!/usr/bin/python3
|
||||
# Meshtastic Autoresponder MESH Bot
|
||||
# K7MHI Kelly Keeton 2024
|
||||
|
||||
@@ -8,61 +8,89 @@ from pubsub import pub # pip install pubsub
|
||||
from modules.log import *
|
||||
from modules.system import *
|
||||
|
||||
def auto_response(message, snr, rssi, hop, message_from_id, channel_number, deviceID):
|
||||
# list of commands to remove from the default list for DM only
|
||||
restrictedCommands = ["blackjack", "videopoker", "dopewars", "lemonstand"]
|
||||
restrictedResponse = "🤖only available in a Direct Message📵" # "" for none
|
||||
|
||||
# Global Variables
|
||||
cmdHistory = [] # list to hold the last commands
|
||||
DEBUGpacket = False # Debug print the packet rx
|
||||
|
||||
def auto_response(message, snr, rssi, hop, pkiStatus, message_from_id, channel_number, deviceID, isDM):
|
||||
global cmdHistory
|
||||
#Auto response to messages
|
||||
message_lower = message.lower()
|
||||
bot_response = "I'm sorry, I'm afraid I can't do that."
|
||||
bot_response = "🤖I'm sorry, I'm afraid I can't do that."
|
||||
|
||||
command_handler = {
|
||||
"ping": lambda: handle_ping(message, hop, snr, rssi),
|
||||
"pong": lambda: "🏓PING!!",
|
||||
"motd": lambda: handle_motd(message, message_from_id),
|
||||
"bbshelp": bbs_help,
|
||||
"wxalert": lambda: handle_wxalert(message_from_id, deviceID, message),
|
||||
"wxa": lambda: handle_wxalert(message_from_id, deviceID, message),
|
||||
"wxc": lambda: handle_wxc(message_from_id, deviceID, 'wxc'),
|
||||
"wx": lambda: handle_wxc(message_from_id, deviceID, 'wx'),
|
||||
"wiki:": lambda: handle_wiki(message),
|
||||
"games": lambda: gamesCmdList,
|
||||
"dopewars": lambda: handleDopeWars(message_from_id, message, deviceID),
|
||||
"lemonstand": lambda: handleLemonade(message_from_id, message),
|
||||
"blackjack": lambda: handleBlackJack(message_from_id, message),
|
||||
"videopoker": lambda: handleVideoPoker(message_from_id, message),
|
||||
"globalthermonuclearwar": lambda: handle_gTnW(),
|
||||
"ask:": lambda: handle_llm(message_from_id, channel_number, deviceID, message, publicChannel),
|
||||
"askai": lambda: handle_llm(message_from_id, channel_number, deviceID, message, publicChannel),
|
||||
"joke": tell_joke,
|
||||
"bbslist": bbs_list_messages,
|
||||
"bbspost": lambda: handle_bbspost(message, message_from_id, deviceID),
|
||||
"bbsread": lambda: handle_bbsread(message),
|
||||
"bbsdelete": lambda: handle_bbsdelete(message, message_from_id),
|
||||
"messages": lambda: handle_messages(deviceID, channel_number, msg_history, publicChannel),
|
||||
"cmd": lambda: help_message,
|
||||
"cmd?": lambda: help_message,
|
||||
"sun": lambda: handle_sun(message_from_id, deviceID, channel_number),
|
||||
"hfcond": hf_band_conditions,
|
||||
"solar": lambda: drap_xray_conditions() + "\n" + solar_conditions(),
|
||||
"lheard": lambda: handle_lheard(),
|
||||
"sitrep": lambda: handle_lheard(),
|
||||
"whereami": lambda: handle_whereami(message_from_id, deviceID, channel_number),
|
||||
"tide": lambda: handle_tide(message_from_id, deviceID, channel_number),
|
||||
"moon": lambda: handle_moon(message_from_id, deviceID, channel_number),
|
||||
"ack": lambda: handle_ack(hop, snr, rssi),
|
||||
"testing": lambda: handle_testing(message, hop, snr, rssi),
|
||||
"test": lambda: handle_testing(message, hop, snr, rssi),
|
||||
"whoami": lambda: handle_whoami(message_from_id, deviceID, hop, snr, rssi)
|
||||
# Command List
|
||||
default_commands = {
|
||||
"ping": lambda: handle_ping(message, hop, snr, rssi),
|
||||
"pong": lambda: "🏓PING!!",
|
||||
"motd": lambda: handle_motd(message, message_from_id),
|
||||
"bbshelp": bbs_help,
|
||||
"wxalert": lambda: handle_wxalert(message_from_id, deviceID, message),
|
||||
"wxa": lambda: handle_wxalert(message_from_id, deviceID, message),
|
||||
"wxc": lambda: handle_wxc(message_from_id, deviceID, 'wxc'),
|
||||
"wx": lambda: handle_wxc(message_from_id, deviceID, 'wx'),
|
||||
"wiki:": lambda: handle_wiki(message),
|
||||
"games": lambda: gamesCmdList,
|
||||
"dopewars": lambda: handleDopeWars(message_from_id, message, deviceID),
|
||||
"lemonstand": lambda: handleLemonade(message_from_id, message),
|
||||
"blackjack": lambda: handleBlackJack(message_from_id, message),
|
||||
"videopoker": lambda: handleVideoPoker(message_from_id, message),
|
||||
"globalthermonuclearwar": lambda: handle_gTnW(),
|
||||
"ask:": lambda: handle_llm(message_from_id, channel_number, deviceID, message, publicChannel),
|
||||
"askai": lambda: handle_llm(message_from_id, channel_number, deviceID, message, publicChannel),
|
||||
"joke": tell_joke,
|
||||
"bbslist": bbs_list_messages,
|
||||
"bbspost": lambda: handle_bbspost(message, message_from_id, deviceID),
|
||||
"bbsread": lambda: handle_bbsread(message),
|
||||
"bbsdelete": lambda: handle_bbsdelete(message, message_from_id),
|
||||
"messages": lambda: handle_messages(deviceID, channel_number, msg_history, publicChannel),
|
||||
"cmd": lambda: help_message,
|
||||
"history": lambda: handle_history(message_from_id, deviceID),
|
||||
"sun": lambda: handle_sun(message_from_id, deviceID, channel_number),
|
||||
"hfcond": hf_band_conditions,
|
||||
"solar": lambda: drap_xray_conditions() + "\n" + solar_conditions(),
|
||||
"lheard": lambda: handle_lheard(message_from_id, deviceID),
|
||||
"sitrep": lambda: handle_lheard(message_from_id, deviceID),
|
||||
"whereami": lambda: handle_whereami(message_from_id, deviceID, channel_number),
|
||||
"tide": lambda: handle_tide(message_from_id, deviceID, channel_number),
|
||||
"moon": lambda: handle_moon(message_from_id, deviceID, channel_number),
|
||||
"ack": lambda: handle_ack(hop, snr, rssi),
|
||||
"testing": lambda: handle_testing(message, hop, snr, rssi),
|
||||
"test": lambda: handle_testing(message, hop, snr, rssi),
|
||||
"whoami": lambda: handle_whoami(message_from_id, deviceID, hop, snr, rssi, pkiStatus)
|
||||
}
|
||||
|
||||
# set the command handler
|
||||
command_handler = default_commands
|
||||
cmds = [] # list to hold the commands found in the message
|
||||
# check the message for commands words list, processed after system.messageTrap
|
||||
for key in command_handler:
|
||||
if key in message_lower.split(' '):
|
||||
word = message_lower.split(' ')
|
||||
if key in word:
|
||||
# append all the commands found in the message to the cmds list
|
||||
cmds.append({'cmd': key, 'index': message_lower.index(key)})
|
||||
# check for commands with a question mark
|
||||
if key + "?" in word:
|
||||
# append all the commands found in the message to the cmds list
|
||||
cmds.append({'cmd': key, 'index': message_lower.index(key)})
|
||||
|
||||
if len(cmds) > 0:
|
||||
# sort the commands by index value
|
||||
cmds = sorted(cmds, key=lambda k: k['index'])
|
||||
logger.debug(f"System: Bot detected Commands:{cmds}")
|
||||
# run the first command after sorting
|
||||
bot_response = command_handler[cmds[0]['cmd']]()
|
||||
# check the command isnt a isDM only command
|
||||
if cmds[0]['cmd'] in restrictedCommands and not isDM:
|
||||
bot_response = restrictedResponse
|
||||
else:
|
||||
# run the first command after sorting
|
||||
bot_response = command_handler[cmds[0]['cmd']]()
|
||||
# append the command to the cmdHistory list for lheard and history
|
||||
if len(cmdHistory) > 50:
|
||||
cmdHistory.pop(0)
|
||||
cmdHistory.append({'nodeID': message_from_id, 'cmd': cmds[0]['cmd'], 'time': time.time()})
|
||||
|
||||
# wait a responseDelay to avoid message collision from lora-ack
|
||||
time.sleep(responseDelay)
|
||||
@@ -130,9 +158,9 @@ def handle_wiki(message):
|
||||
if "wiki:" in message.lower():
|
||||
search = message.split(":")[1]
|
||||
search = search.strip()
|
||||
return get_wikipedia_summary(search)
|
||||
else:
|
||||
return "Please add a search term example:wiki: travelling gnome"
|
||||
if search:
|
||||
return get_wikipedia_summary(search)
|
||||
return "Please add a search term example:wiki: travelling gnome"
|
||||
|
||||
# Runtime Variables for LLM
|
||||
llmRunCounter = 0
|
||||
@@ -140,7 +168,7 @@ llmTotalRuntime = []
|
||||
llmLocationTable = [{'nodeID': 1234567890, 'location': 'No Location'},]
|
||||
|
||||
def handle_llm(message_from_id, channel_number, deviceID, message, publicChannel):
|
||||
global llmRunCounter, llmLocationTable, llmTotalRuntime, location_enabled, antiSpam, useDMForResponse, NO_DATA_NOGPS
|
||||
global llmRunCounter, llmLocationTable, llmTotalRuntime, cmdHistory
|
||||
location_name = 'no location provided'
|
||||
|
||||
if location_enabled:
|
||||
@@ -164,6 +192,8 @@ def handle_llm(message_from_id, channel_number, deviceID, message, publicChannel
|
||||
else:
|
||||
# likely a DM
|
||||
user_input = message
|
||||
# consider this a command use for the cmdHistory list
|
||||
cmdHistory.append({'nodeID': message_from_id, 'cmd': 'llm-use', 'time': time.time()})
|
||||
|
||||
# if the message_from_id is not in the llmLocationTable send the welcome message
|
||||
for i in range(0, len(llmLocationTable)):
|
||||
@@ -224,7 +254,7 @@ def handle_llm(message_from_id, channel_number, deviceID, message, publicChannel
|
||||
end = time.time()
|
||||
llmRunCounter += 1
|
||||
llmTotalRuntime.append(end - start)
|
||||
|
||||
|
||||
return response
|
||||
|
||||
def handleDopeWars(nodeID, message, rxNode):
|
||||
@@ -240,7 +270,8 @@ def handleDopeWars(nodeID, message, rxNode):
|
||||
if not last_cmd:
|
||||
msg = 'Welcome to 💊Dope Wars!💉 You have ' + str(total_days) + ' days to make as much 💰 as possible! '
|
||||
high_score = getHighScoreDw()
|
||||
msg += 'The High Score is $' + "{:,}".format(high_score.get('cash')) + ' by user ' + get_name_from_number(high_score.get('userID') , 'short', rxNode) + f'.\n'
|
||||
msg += 'The High Score is $' + "{:,}".format(high_score.get('cash')) + ' by user ' + get_name_from_number(high_score.get('userID') , 'short', rxNode)
|
||||
msg += 'Game Played via Direct Message.' + f'.\n'
|
||||
msg += playDopeWars(nodeID, message)
|
||||
else:
|
||||
logger.debug("System: DopeWars: last_cmd: " + str(last_cmd))
|
||||
@@ -258,7 +289,7 @@ def handle_gTnW():
|
||||
|
||||
def handleLemonade(nodeID, message):
|
||||
global lemonadeTracker, lemonadeCups, lemonadeLemons, lemonadeSugar, lemonadeWeeks, lemonadeScore, lemon_starting_cash, lemon_total_weeks
|
||||
|
||||
msg = ""
|
||||
def create_player(nodeID):
|
||||
# create new player
|
||||
logger.debug("System: Lemonade: New Player: " + str(nodeID))
|
||||
@@ -277,8 +308,9 @@ def handleLemonade(nodeID, message):
|
||||
# create new player if not in tracker
|
||||
if last_cmd == "":
|
||||
create_player(nodeID)
|
||||
msg += "Welcome to 🍋Lemonade Stand!🍋 Game Played via Direct Message."
|
||||
|
||||
msg = start_lemonade(nodeID=nodeID, message=message, celsius=False)
|
||||
msg += start_lemonade(nodeID=nodeID, message=message, celsius=False)
|
||||
# wait a second to keep from message collision
|
||||
time.sleep(1)
|
||||
return msg
|
||||
@@ -297,6 +329,7 @@ def handleBlackJack(nodeID, message):
|
||||
if message.lower().startswith("l"):
|
||||
logger.debug(f"System: BlackJack: {nodeID} is leaving the table")
|
||||
# add 16 hours to the player time to leave the table, this will be detected by bot logic as player leaving
|
||||
msg = "You have left the table."
|
||||
for i in range(len(jackTracker)):
|
||||
if jackTracker[i]['nodeID'] == nodeID:
|
||||
jackTracker[i]['time'] = time.time() - 57600
|
||||
@@ -305,6 +338,7 @@ def handleBlackJack(nodeID, message):
|
||||
jackTracker[i]['d_cards'] = []
|
||||
jackTracker[i]['p_hand'] = []
|
||||
jackTracker[i]['d_hand'] = []
|
||||
return msg
|
||||
|
||||
# # Save the game state to pickle
|
||||
# try:
|
||||
@@ -330,7 +364,7 @@ def handleBlackJack(nodeID, message):
|
||||
|
||||
if last_cmd != "":
|
||||
logger.debug(f"System: BlackJack: {nodeID} last command: {last_cmd}")
|
||||
|
||||
time.sleep(1)
|
||||
return msg
|
||||
|
||||
def handleVideoPoker(nodeID, message):
|
||||
@@ -341,10 +375,12 @@ def handleVideoPoker(nodeID, message):
|
||||
if message.lower().startswith("l"):
|
||||
logger.debug(f"System: VideoPoker: {nodeID} is leaving the table")
|
||||
# add 16 hours to the player time to leave the table, this will be detected by bot logic as player leaving
|
||||
msg = "You have left the table."
|
||||
for i in range(len(vpTracker)):
|
||||
if vpTracker[i]['nodeID'] == nodeID:
|
||||
vpTracker[i]['time'] = time.time() - 57600
|
||||
vpTracker[i]['cmd'] = "new"
|
||||
return msg
|
||||
else:
|
||||
# Play Video Poker
|
||||
msg = playVideoPoker(nodeID=nodeID, message=message)
|
||||
@@ -377,22 +413,22 @@ def handleVideoPoker(nodeID, message):
|
||||
|
||||
if last_cmd != "":
|
||||
logger.debug(f"System: VideoPoker: {nodeID} last command: {last_cmd}")
|
||||
|
||||
time.sleep(1)
|
||||
return msg
|
||||
|
||||
def handle_wxc(message_from_id, deviceID, cmd):
|
||||
location = get_node_location(message_from_id, deviceID)
|
||||
if use_meteo_wxApi and not "wxc" in cmd and not use_metric:
|
||||
logger.debug(f"System: Bot Returning Open-Meteo API for weather imperial")
|
||||
logger.debug("System: Bot Returning Open-Meteo API for weather imperial")
|
||||
weather = get_wx_meteo(str(location[0]), str(location[1]))
|
||||
elif use_meteo_wxApi:
|
||||
logger.debug(f"System: Bot Returning Open-Meteo API for weather metric")
|
||||
logger.debug("System: Bot Returning Open-Meteo API for weather metric")
|
||||
weather = get_wx_meteo(str(location[0]), str(location[1]), 1)
|
||||
elif not use_meteo_wxApi and "wxc" in cmd or use_metric:
|
||||
logger.debug(f"System: Bot Returning NOAA API for weather metric")
|
||||
logger.debug("System: Bot Returning NOAA API for weather metric")
|
||||
weather = get_weather(str(location[0]), str(location[1]), 1)
|
||||
else:
|
||||
logger.debug(f"System: Bot Returning NOAA API for weather imperial")
|
||||
logger.debug("System: Bot Returning NOAA API for weather imperial")
|
||||
weather = get_weather(str(location[0]), str(location[1]))
|
||||
return weather
|
||||
|
||||
@@ -451,19 +487,115 @@ def handle_sun(message_from_id, deviceID, channel_number):
|
||||
location = get_node_location(message_from_id, deviceID, channel_number)
|
||||
return get_sun(str(location[0]), str(location[1]))
|
||||
|
||||
def handle_lheard():
|
||||
bot_response = "Last heard:\n" + str(get_node_list(1))
|
||||
chutil1 = interface1.nodes.get(decimal_to_hex(myNodeNum1), {}).get("deviceMetrics", {}).get("channelUtilization", 0)
|
||||
chutil1 = "{:.2f}".format(chutil1)
|
||||
def handle_lheard(nodeid, deviceID):
|
||||
# display last heard nodes add to response
|
||||
bot_response = str(get_node_list(1))
|
||||
# gather telemetry
|
||||
chutil1 = round(interface1.nodes.get(decimal_to_hex(myNodeNum1), {}).get("deviceMetrics", {}).get("channelUtilization", 0), 1)
|
||||
airUtilTx = round(interface1.nodes.get(decimal_to_hex(myNodeNum1), {}).get("deviceMetrics", {}).get("airUtilTx", 0), 1)
|
||||
uptimeSeconds = interface1.nodes.get(decimal_to_hex(myNodeNum1), {}).get("deviceMetrics", {}).get("uptimeSeconds", 0)
|
||||
batteryLevel = interface1.nodes.get(decimal_to_hex(myNodeNum1), {}).get("deviceMetrics", {}).get("batteryLevel", 0)
|
||||
voltage = interface1.nodes.get(decimal_to_hex(myNodeNum1), {}).get("deviceMetrics", {}).get("voltage", 0)
|
||||
if interface2_enabled:
|
||||
bot_response += "Port2:\n" + str(get_node_list(2))
|
||||
chutil2 = interface2.nodes.get(decimal_to_hex(myNodeNum2), {}).get("deviceMetrics", {}).get("channelUtilization", 0)
|
||||
chutil2 = "{:.2f}".format(chutil2)
|
||||
bot_response += "Ch Use: " + str(chutil1) + "%"
|
||||
bot_response += "P2:\n" + str(get_node_list(2))
|
||||
chutil2 = round(interface2.nodes.get(decimal_to_hex(myNodeNum2), {}).get("deviceMetrics", {}).get("channelUtilization", 0), 1)
|
||||
airUtilTx2 = round(interface2.nodes.get(decimal_to_hex(myNodeNum2), {}).get("deviceMetrics", {}).get("airUtilTx", 0), 1)
|
||||
uptimeSeconds2 = interface2.nodes.get(decimal_to_hex(myNodeNum2), {}).get("deviceMetrics", {}).get("uptimeSeconds", 0)
|
||||
batteryLevel2 = interface2.nodes.get(decimal_to_hex(myNodeNum2), {}).get("deviceMetrics", {}).get("batteryLevel", 0)
|
||||
voltage2 = interface2.nodes.get(decimal_to_hex(myNodeNum2), {}).get("deviceMetrics", {}).get("voltage", 0)
|
||||
else:
|
||||
chutil2, airUtilTx2, uptimeSeconds2, batteryLevel2, voltage2 = 0, 0, 0, 0, 0
|
||||
# add the channel utilization and airUtilTx to the bot response
|
||||
bot_response += "\nUse/Tx " + str(chutil1) + "%" + "/" + str(airUtilTx) + "%"
|
||||
if interface2_enabled:
|
||||
bot_response += " P2:" + str(chutil2) + "%"
|
||||
bot_response += " P2:" + str(chutil2) + "%" + "/" + str(airUtilTx2) + "%"
|
||||
# convert uptime to minutes, hours, or days
|
||||
if uptimeSeconds > 0 or uptimeSeconds2 > 0:
|
||||
uptimeSeconds = round(uptimeSeconds / 60)
|
||||
uptimeSeconds2 = round(uptimeSeconds2 / 60)
|
||||
designator = "m"
|
||||
if uptimeSeconds > 60 or uptimeSeconds2 > 60:
|
||||
uptimeSeconds = round(uptimeSeconds / 60)
|
||||
uptimeSeconds2 = round(uptimeSeconds2 / 60)
|
||||
designator = "h"
|
||||
if uptimeSeconds > 24 or uptimeSeconds2 > 24:
|
||||
uptimeSeconds = round(uptimeSeconds / 24)
|
||||
uptimeSeconds2 = round(uptimeSeconds2 / 24)
|
||||
designator = "d"
|
||||
# add uptime and battery info to the bot response
|
||||
bot_response += "\nUptime:" + str(uptimeSeconds) + designator
|
||||
if interface2_enabled:
|
||||
bot_response += f" P2:" + {uptimeSeconds2} + {designator}
|
||||
if not batteryLevel == 101:
|
||||
bot_response += f" Bat: {batteryLevel}% Volt: {voltage}"
|
||||
if interface2_enabled and not batteryLevel2 == 101:
|
||||
bot_response += f" P2: Bat: {batteryLevel2}% Volt: {voltage2}"
|
||||
# show last users of the bot with the cmdHistory list
|
||||
history = handle_history(nodeid, deviceID, lheard=True)
|
||||
if history:
|
||||
bot_response += f'\n{history}'
|
||||
return bot_response
|
||||
|
||||
def handle_history(nodeid, deviceID, lheard=False):
|
||||
global cmdHistory, lheardCmdIgnoreNode, bbs_admin_list
|
||||
msg = ""
|
||||
buffer = []
|
||||
|
||||
# show the last commands from the user to the bot
|
||||
if not lheard:
|
||||
for i in range(len(cmdHistory)):
|
||||
prettyTime = round((time.time() - cmdHistory[i]['time']) / 600) * 5
|
||||
if prettyTime < 60:
|
||||
prettyTime = str(prettyTime) + "m"
|
||||
elif prettyTime < 1440:
|
||||
prettyTime = str(round(prettyTime/60)) + "h"
|
||||
else:
|
||||
prettyTime = str(round(prettyTime/1440)) + "d"
|
||||
|
||||
# history display output
|
||||
if nodeid in bbs_admin_list and cmdHistory[i]['nodeID'] not in lheardCmdIgnoreNode:
|
||||
buffer.append((get_name_from_number(cmdHistory[i]['nodeID'], 'short', deviceID), cmdHistory[i]['cmd'], prettyTime))
|
||||
elif cmdHistory[i]['nodeID'] == nodeid and cmdHistory[i]['nodeID'] not in lheardCmdIgnoreNode:
|
||||
buffer.append((get_name_from_number(nodeid, 'short', deviceID), cmdHistory[i]['cmd'], prettyTime))
|
||||
# message for output of the last commands
|
||||
buffer.reverse()
|
||||
# only return the last 4 commands
|
||||
if len(buffer) > 4:
|
||||
buffer = buffer[-4:]
|
||||
# create the message from the buffer list
|
||||
for i in range(0, len(buffer)):
|
||||
msg += f"{buffer[i][0]}: {buffer[i][1]} :{buffer[i][2]} ago"
|
||||
if i < len(buffer) - 1:
|
||||
msg += "\n"
|
||||
else:
|
||||
# sort the cmdHistory list by time, return the username and time into a new list which used for display
|
||||
for i in range(len(cmdHistory)):
|
||||
prettyTime = round((time.time() - cmdHistory[i]['time']) / 600) * 5
|
||||
if prettyTime < 60:
|
||||
prettyTime = str(prettyTime) + "m"
|
||||
elif prettyTime < 1440:
|
||||
prettyTime = str(round(prettyTime/60)) + "h"
|
||||
else:
|
||||
prettyTime = str(round(prettyTime/1440)) + "d"
|
||||
|
||||
if cmdHistory[i]['nodeID'] not in lheardCmdIgnoreNode:
|
||||
# add line to a new list for display
|
||||
nodeName = get_name_from_number(cmdHistory[i]['nodeID'], 'short', deviceID)
|
||||
if not any(d[0] == nodeName for d in buffer):
|
||||
buffer.append((nodeName, prettyTime))
|
||||
else:
|
||||
# update the time for the node in the buffer for the latest time in cmdHistory
|
||||
for j in range(len(buffer)):
|
||||
if buffer[j][0] == nodeName:
|
||||
buffer[j] = (nodeName, prettyTime)
|
||||
|
||||
# create the message from the buffer list
|
||||
for i in range(0, len(buffer)):
|
||||
msg += f"{buffer[i][0]} seen {buffer[i][1]} ago"
|
||||
if i < len(buffer) - 1:
|
||||
msg += "\n"
|
||||
return msg
|
||||
|
||||
def handle_whereami(message_from_id, deviceID, channel_number):
|
||||
location = get_node_location(message_from_id, deviceID, channel_number)
|
||||
return where_am_i(str(location[0]), str(location[1]))
|
||||
@@ -499,13 +631,15 @@ def handle_testing(message, hop, snr, rssi):
|
||||
else:
|
||||
return "🎙Testing 1,2,3 " + hop
|
||||
|
||||
def handle_whoami(message_from_id, deviceID, hop, snr, rssi):
|
||||
def handle_whoami(message_from_id, deviceID, hop, snr, rssi, pkiStatus):
|
||||
loc = []
|
||||
msg = "You are " + str(message_from_id) + " AKA " +\
|
||||
str(get_name_from_number(message_from_id, 'long', deviceID) + " AKA, " +\
|
||||
str(get_name_from_number(message_from_id, 'short', deviceID)) + " AKA, " +\
|
||||
str(decimal_to_hex(message_from_id)) + f"\n")
|
||||
msg += f"I see the signal strength is {rssi} and the SNR is {snr} with hop count of {hop} \n"
|
||||
if pkiStatus[0]:
|
||||
msg += f"Your PKI bit is {pkiStatus[0]} pubKey: {pkiStatus[1]}"
|
||||
|
||||
loc = get_node_location(message_from_id, deviceID)
|
||||
if loc != [latitudeValue,longitudeValue]:
|
||||
@@ -518,7 +652,7 @@ def onDisconnect(interface):
|
||||
rxType = type(interface).__name__
|
||||
if rxType == 'SerialInterface':
|
||||
rxInterface = interface.__dict__.get('devPath', 'unknown')
|
||||
logger.critical(f"System: Lost Connection to Device {rxInterface}")
|
||||
logger.critical("System: Lost Connection to Device {rxInterface}")
|
||||
if port1 in rxInterface:
|
||||
retry_int1 = True
|
||||
elif interface2_enabled and port2 in rxInterface:
|
||||
@@ -526,14 +660,14 @@ def onDisconnect(interface):
|
||||
|
||||
if rxType == 'TCPInterface':
|
||||
rxHost = interface.__dict__.get('hostname', 'unknown')
|
||||
logger.critical(f"System: Lost Connection to Device {rxHost}")
|
||||
logger.critical("System: Lost Connection to Device {rxHost}")
|
||||
if hostname1 in rxHost and interface1_type == 'tcp':
|
||||
retry_int1 = True
|
||||
elif interface2_enabled and hostname2 in rxHost and interface2_type == 'tcp':
|
||||
retry_int2 = True
|
||||
|
||||
if rxType == 'BLEInterface':
|
||||
logger.critical(f"System: Lost Connection to Device BLE")
|
||||
logger.critical("System: Lost Connection to Device BLE")
|
||||
if interface1_type == 'ble':
|
||||
retry_int1 = True
|
||||
elif interface2_enabled and interface2_type == 'ble':
|
||||
@@ -543,9 +677,20 @@ def onReceive(packet, interface):
|
||||
# extract interface defailts from interface object
|
||||
rxType = type(interface).__name__
|
||||
rxNode = 0
|
||||
#logger.debug(f"System: Packet Received on {rxType}")
|
||||
# Debug print the interface object
|
||||
#for item in interface.__dict__.items(): print (item)
|
||||
message_from_id = 0
|
||||
snr = 0
|
||||
rssi = 0
|
||||
hop = 0
|
||||
hop_away = 0
|
||||
pkiStatus = (False, 'ABC')
|
||||
isDM = False
|
||||
|
||||
if DEBUGpacket:
|
||||
# Debug print the interface object
|
||||
for item in interface.__dict__.items(): intDebug = f"{item}\n"
|
||||
logger.debug(f"System: Packet Received on {rxType} Interface\n {intDebug} \n END of interface \n")
|
||||
# Debug print the packet for debugging
|
||||
logger.debug(f"Packet Received\n {packet} \n END of packet \n")
|
||||
|
||||
if rxType == 'SerialInterface':
|
||||
rxInterface = interface.__dict__.get('devPath', 'unknown')
|
||||
@@ -567,10 +712,6 @@ def onReceive(packet, interface):
|
||||
elif interface2_enabled and interface2_type == 'ble':
|
||||
rxNode = 2
|
||||
|
||||
# Debug print the packet for debugging
|
||||
#print(f"Packet Received\n {packet} \n END of packet \n")
|
||||
message_from_id = 0
|
||||
|
||||
# check for BBS DM for mail delivery
|
||||
if bbs_enabled and 'decoded' in packet:
|
||||
message_from_id = packet['from']
|
||||
@@ -590,8 +731,6 @@ def onReceive(packet, interface):
|
||||
send_message(message, channel_number, message_from_id, rxNode)
|
||||
|
||||
# check for a message packet and process it
|
||||
snr = 0
|
||||
rssi = 0
|
||||
try:
|
||||
if 'decoded' in packet and packet['decoded']['portnum'] == 'TEXT_MESSAGE_APP':
|
||||
message_bytes = packet['decoded']['payload']
|
||||
@@ -606,13 +745,16 @@ def onReceive(packet, interface):
|
||||
# check if the packet has a channel flag use it
|
||||
if packet.get('channel'):
|
||||
channel_number = packet.get('channel', 0)
|
||||
|
||||
|
||||
# check if the packet has a publicKey flag use it
|
||||
if packet.get('publicKey'):
|
||||
pkiStatus = (packet.get('pkiEncrypted', False), packet.get('publicKey', 'ABC'))
|
||||
|
||||
# check if the packet has a hop count flag use it
|
||||
if packet.get('hopsAway'):
|
||||
hop_away = packet.get('hopsAway', 0)
|
||||
else:
|
||||
# if the packet does not have a hop count try other methods
|
||||
hop_away = 0
|
||||
if packet.get('hopLimit'):
|
||||
hop_limit = packet.get('hopLimit', 0)
|
||||
else:
|
||||
@@ -643,14 +785,16 @@ def onReceive(packet, interface):
|
||||
# If the packet is a DM (Direct Message) respond to it, otherwise validate its a message for us on the channel
|
||||
if packet['to'] == myNodeNum1 or packet['to'] == myNodeNum2:
|
||||
# message is DM to us
|
||||
isDM = True
|
||||
# check if the message contains a trap word, DMs are always responded to
|
||||
if messageTrap(message_string):
|
||||
# log the message to the message log
|
||||
logger.info(f"Device:{rxNode} Channel: {channel_number} " + CustomFormatter.green + f"Received DM: " + CustomFormatter.white + f"{message_string} " + CustomFormatter.purple +\
|
||||
"From: " + CustomFormatter.white + f"{get_name_from_number(message_from_id, 'long', rxNode)}")
|
||||
# respond with DM
|
||||
send_message(auto_response(message_string, snr, rssi, hop, message_from_id, channel_number, rxNode), channel_number, message_from_id, rxNode)
|
||||
send_message(auto_response(message_string, snr, rssi, hop, pkiStatus, message_from_id, channel_number, rxNode, isDM), channel_number, message_from_id, rxNode)
|
||||
else:
|
||||
# DM is usefull for games or LLM
|
||||
# DM is useful for games or LLM
|
||||
if games_enabled:
|
||||
playingGame = False
|
||||
# if in a game we cant use LLM disable for duration of game
|
||||
@@ -699,6 +843,11 @@ def onReceive(packet, interface):
|
||||
|
||||
# play the game
|
||||
send_message(handleVideoPoker(message_from_id, message_string), channel_number, message_from_id, rxNode)
|
||||
else:
|
||||
# reset the player if the time exceeds 8 hours
|
||||
vpTracker[i]['cmd'] = "gameOver"
|
||||
vpTracker[i]['player'] = None
|
||||
vpTracker[i]['deck'] = None
|
||||
|
||||
for i in range(0, len(jackTracker)):
|
||||
if jackTracker[i].get('nodeID') == message_from_id:
|
||||
@@ -711,6 +860,13 @@ def onReceive(packet, interface):
|
||||
|
||||
# play the game
|
||||
send_message(handleBlackJack(message_from_id, message_string), channel_number, message_from_id, rxNode)
|
||||
else:
|
||||
# reset the player if the time exceeds 8 hours
|
||||
jackTracker[i]['cmd'] = "new"
|
||||
jackTracker[i]['p_cards'] = []
|
||||
jackTracker[i]['d_cards'] = []
|
||||
jackTracker[i]['p_hand'] = []
|
||||
jackTracker[i]['d_hand'] = []
|
||||
else:
|
||||
playingGame = False
|
||||
|
||||
@@ -734,7 +890,7 @@ def onReceive(packet, interface):
|
||||
"From: " + CustomFormatter.white + f"{get_name_from_number(message_from_id, 'long', rxNode)}")
|
||||
if useDMForResponse:
|
||||
# respond to channel message via direct message
|
||||
send_message(auto_response(message_string, snr, rssi, hop, message_from_id, channel_number, rxNode), channel_number, message_from_id, rxNode)
|
||||
send_message(auto_response(message_string, snr, rssi, hop, pkiStatus, message_from_id, channel_number, rxNode, isDM), channel_number, message_from_id, rxNode)
|
||||
else:
|
||||
# or respond to channel message on the channel itself
|
||||
if channel_number == publicChannel and antiSpam:
|
||||
@@ -742,10 +898,10 @@ def onReceive(packet, interface):
|
||||
logger.error(f"System: AntiSpam protection, sending DM to: {get_name_from_number(message_from_id, 'long', rxNode)}")
|
||||
|
||||
# respond to channel message via direct message
|
||||
send_message(auto_response(message_string, snr, rssi, hop, message_from_id, channel_number, rxNode), channel_number, message_from_id, rxNode)
|
||||
send_message(auto_response(message_string, snr, rssi, hop, pkiStatus, message_from_id, channel_number, rxNode, isDM), channel_number, message_from_id, rxNode)
|
||||
else:
|
||||
# respond to channel message on the channel itself
|
||||
send_message(auto_response(message_string, snr, rssi, hop, message_from_id, channel_number, rxNode), channel_number, 0, rxNode)
|
||||
send_message(auto_response(message_string, snr, rssi, hop, pkiStatus, message_from_id, channel_number, rxNode, isDM), channel_number, 0, rxNode)
|
||||
else:
|
||||
# message is not for bot to respond to
|
||||
# ignore the message but add it to the message history list
|
||||
@@ -799,24 +955,24 @@ async def start_rx():
|
||||
logger.info(f"System: Autoresponder Started for Device2 {get_name_from_number(myNodeNum2, 'long', 2)},"
|
||||
f"{get_name_from_number(myNodeNum2, 'short', 2)}. NodeID: {myNodeNum2}, {decimal_to_hex(myNodeNum2)}")
|
||||
if log_messages_to_file:
|
||||
logger.debug(f"System: Logging Messages to disk")
|
||||
logger.debug("System: Logging Messages to disk")
|
||||
if syslog_to_file:
|
||||
logger.debug(f"System: Logging System Logs to disk")
|
||||
logger.debug("System: Logging System Logs to disk")
|
||||
if bbs_enabled:
|
||||
logger.debug(f"System: BBS Enabled, {bbsdb} has {len(bbs_messages)} messages. Direct Mail Messages waiting: {(len(bbs_dm) - 1)}")
|
||||
if solar_conditions_enabled:
|
||||
logger.debug(f"System: Celestial Telemetry Enabled")
|
||||
logger.debug("System: Celestial Telemetry Enabled")
|
||||
if location_enabled:
|
||||
if use_meteo_wxApi:
|
||||
logger.debug(f"System: Location Telemetry Enabled using Open-Meteo API")
|
||||
logger.debug("System: Location Telemetry Enabled using Open-Meteo API")
|
||||
else:
|
||||
logger.debug(f"System: Location Telemetry Enabled using NOAA API")
|
||||
logger.debug("System: Location Telemetry Enabled using NOAA API")
|
||||
if dad_jokes_enabled:
|
||||
logger.debug(f"System: Dad Jokes Enabled!")
|
||||
logger.debug("System: Dad Jokes Enabled!")
|
||||
if games_enabled:
|
||||
logger.debug(f"System: Games Enabled!")
|
||||
logger.debug("System: Games Enabled!")
|
||||
if wikipedia_enabled:
|
||||
logger.debug(f"System: Wikipedia search Enabled")
|
||||
logger.debug("System: Wikipedia search Enabled")
|
||||
if motd_enabled:
|
||||
logger.debug(f"System: MOTD Enabled using {MOTD}")
|
||||
if sentry_enabled:
|
||||
@@ -880,5 +1036,4 @@ try:
|
||||
except KeyboardInterrupt:
|
||||
exit_handler()
|
||||
pass
|
||||
|
||||
# EOF
|
||||
|
||||
@@ -16,7 +16,7 @@ def load_bbsdb():
|
||||
try:
|
||||
with open('bbsdb.pkl', 'rb') as f:
|
||||
bbs_messages = pickle.load(f)
|
||||
except:
|
||||
except Exception as e:
|
||||
bbs_messages = [[1, "Welcome to meshBBS", "Welcome to the BBS, please post a message!",0]]
|
||||
logger.debug("System: Creating new bbsdb.pkl")
|
||||
with open('bbsdb.pkl', 'wb') as f:
|
||||
|
||||
@@ -138,7 +138,7 @@ def success_rate(card, obj_h):
|
||||
l_rate -= 99
|
||||
msg += f"If Hit, chance {100-l_rate}% failure, and {l_rate}% success"
|
||||
else:
|
||||
msg += f"If Hit, a low chance of success."
|
||||
msg += "If Hit, a low chance of success."
|
||||
return msg
|
||||
|
||||
def hits(obj_de):
|
||||
@@ -256,7 +256,7 @@ def playBlackJack(nodeID, message):
|
||||
logger.debug(f"System: BlackJack: New Player {nodeID}")
|
||||
jackTracker.append({'nodeID': nodeID, 'cmd': 'new', 'time': time.time(), 'cash': jack_starting_cash,\
|
||||
'bet': 0, 'gameStats': {'p_win': p_win, 'd_win': d_win, 'draw': draw}, 'p_cards':p_cards, 'd_cards':d_cards, 'p_hand':p_hand.cards, 'd_hand':d_hand.cards, 'next_card':next_card})
|
||||
return f"Welcome to BlackJack!♠️♥️♣️♦️ you have {p_chips.total} chips, Whats your bet?"
|
||||
return f"Welcome to BlackJack!♠️♥️♣️♦️ you have {p_chips.total} chips. Game Played via Direct Message. Whats your bet?"
|
||||
|
||||
if getLastCmdJack(nodeID) == "new":
|
||||
# Place Bet
|
||||
@@ -267,9 +267,6 @@ def playBlackJack(nodeID, message):
|
||||
bet_money = 5
|
||||
else:
|
||||
bet_money = bet_money
|
||||
# handle # message
|
||||
if bet_money != 0:
|
||||
bet_money = int(bet_money)
|
||||
else:
|
||||
bet_money = int(message)
|
||||
|
||||
@@ -278,7 +275,7 @@ def playBlackJack(nodeID, message):
|
||||
else:
|
||||
return f"Invalid Bet, the maximum bet you can place is {p_chips.total}"
|
||||
except ValueError:
|
||||
return f"Invalid Bet, the maximum bet you can place is {p_chips.total}"
|
||||
return f"Invalid Bet, the maximum bet, {p_chips.total}"
|
||||
|
||||
# Show the cards
|
||||
msg += show_some(p_cards, d_cards, p_hand)
|
||||
@@ -381,10 +378,10 @@ def playBlackJack(nodeID, message):
|
||||
# recall the game state
|
||||
for i in range(len(jackTracker)):
|
||||
if jackTracker[i]['nodeID'] == nodeID:
|
||||
p_chips.total = jackTracker[i]['cash']
|
||||
p_chips.bet = jackTracker[i]['bet']
|
||||
p_win = jackTracker[i]['gameStats']['p_win']
|
||||
d_win = jackTracker[i]['gameStats']['d_win']
|
||||
p_chips.total = int(jackTracker[i]['cash'])
|
||||
p_chips.bet = int(jackTracker[i]['bet'])
|
||||
p_win = int(jackTracker[i]['gameStats']['p_win'])
|
||||
d_win = int(jackTracker[i]['gameStats']['d_win'])
|
||||
draw = jackTracker[i]['gameStats']['draw']
|
||||
p_cards = jackTracker[i]['p_cards']
|
||||
d_cards = jackTracker[i]['d_cards']
|
||||
@@ -408,15 +405,15 @@ def playBlackJack(nodeID, message):
|
||||
# Check who wins
|
||||
if push(p_hand, d_hand):
|
||||
draw += 1
|
||||
msg += f"👌PUSH"
|
||||
msg += "👌PUSH"
|
||||
elif player_wins(p_hand, d_hand, p_chips):
|
||||
p_win += 1
|
||||
msg += f"🎉PLAYER WINS🎰"
|
||||
msg += "🎉PLAYER WINS🎰"
|
||||
elif dealer_wins(p_hand, d_hand, p_chips):
|
||||
d_win += 1
|
||||
msg += f"👎DEALER WINS"
|
||||
msg += "👎DEALER WINS"
|
||||
else:
|
||||
msg += f"👎DEALER WINS"
|
||||
msg += "👎DEALER WINS"
|
||||
|
||||
# Display the Game Stats
|
||||
msg += gameStats(str(p_win), str(d_win), str(draw))
|
||||
@@ -424,7 +421,7 @@ def playBlackJack(nodeID, message):
|
||||
# Display the chips left
|
||||
if p_chips.total < 1:
|
||||
if p_chips.total > 0:
|
||||
msg += f"🪙Keep the change you filthy animal!"
|
||||
msg += "🪙Keep the change you filthy animal!"
|
||||
else:
|
||||
msg += "💸NO MORE MONEY! Game Over!"
|
||||
p_chips.total = jack_starting_cash
|
||||
|
||||
@@ -218,7 +218,7 @@ def buy_func(nodeID, price_list, choice=0, value='0'):
|
||||
msg = f"Didnt see a qty. ex: b,1,10 buys 10 of {my_drugs[1].name}, can also use m for max"
|
||||
return msg
|
||||
elif buy_amount not in range(1, 101):
|
||||
msg = f"Enter qty or m for max"
|
||||
msg = "Enter qty or m for max"
|
||||
return msg
|
||||
elif buy_amount > 100 - inventory:
|
||||
msg = "You don\'t have enough space for all that.🎒"
|
||||
@@ -273,10 +273,10 @@ def sell_func(nodeID, price_list, choice=0, value='0'):
|
||||
else:
|
||||
sell_amount = int(sell_amount)
|
||||
if sell_amount not in range(1, 101):
|
||||
msg = f"You can only sell between 1 and 100"
|
||||
msg = "You can only sell between 1 and 100"
|
||||
return msg
|
||||
except ValueError:
|
||||
msg = f"Enter qty or m for max"
|
||||
msg = "Enter qty or m for max"
|
||||
return msg
|
||||
|
||||
# check if the user has any of the drug they are trying to sell
|
||||
@@ -329,7 +329,7 @@ def get_location_table(nodeID, choice=0):
|
||||
loc_table_string = ''
|
||||
for i in range(len(loc)):
|
||||
loc_table_string += str(i+1) + '. ' + loc[i] + ' '
|
||||
loc_table_string += f' Where do you want to 🛫?#'
|
||||
loc_table_string += ' Where do you want to 🛫?#'
|
||||
return loc_table_string
|
||||
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ def start_lemonade(nodeID, message, celsius=False):
|
||||
endGame(nodeID)
|
||||
return "Goodbye!👋"
|
||||
|
||||
title="Lemonade Stand🍋"
|
||||
title="LemonStand🍋"
|
||||
# Define the temperature unit symbols
|
||||
fahrenheit_unit = "ºF"
|
||||
celsius_unit = "ºC"
|
||||
|
||||
@@ -204,6 +204,7 @@ def abbreviate_weather(row):
|
||||
"precipitation": "precip",
|
||||
"showers": "shwrs",
|
||||
"thunderstorms": "t-storms",
|
||||
"thunderstorm": "t-storm",
|
||||
"quarters": "qtrs",
|
||||
"quarter": "qtr"
|
||||
}
|
||||
|
||||
@@ -104,6 +104,8 @@ try:
|
||||
welcome_message = (f"{welcome_message}").replace('\\n', '\n') # allow for newlines in the welcome message
|
||||
motd_enabled = config['general'].getboolean('motdEnabled', True)
|
||||
MOTD = config['general'].get('motd', MOTD)
|
||||
enableCmdHistory = config['general'].getboolean('enableCmdHistory', True)
|
||||
lheardCmdIgnoreNode = config['general'].get('lheardCmdIgnoreNode', '').split(',')
|
||||
whoami_enabled = config['general'].getboolean('whoami', True)
|
||||
dad_jokes_enabled = config['general'].getboolean('DadJokes', False)
|
||||
solar_conditions_enabled = config['general'].getboolean('spaceWeather', True)
|
||||
|
||||
@@ -45,6 +45,13 @@ if solar_conditions_enabled:
|
||||
from modules.solarconditions import * # from the spudgunman/meshing-around repo
|
||||
trap_list = trap_list + trap_list_solarconditions # items hfcond, solar, sun, moon
|
||||
help_message = help_message + ", sun, hfcond, solar, moon"
|
||||
else:
|
||||
hf_band_conditions = False
|
||||
|
||||
# Command History Configuration
|
||||
if enableCmdHistory:
|
||||
trap_list = trap_list + ("history",)
|
||||
#help_message = help_message + ", history"
|
||||
|
||||
# Location Configuration
|
||||
if location_enabled:
|
||||
@@ -58,12 +65,16 @@ if location_enabled:
|
||||
else:
|
||||
# NOAA only features
|
||||
help_message = help_message + ", wxa, tide"
|
||||
|
||||
|
||||
# BBS Configuration
|
||||
if bbs_enabled:
|
||||
from modules.bbstools import * # from the spudgunman/meshing-around repo
|
||||
trap_list = trap_list + trap_list_bbs # items bbslist, bbspost, bbsread, bbsdelete, bbshelp
|
||||
help_message = help_message + ", bbslist, bbshelp"
|
||||
else:
|
||||
bbs_help = False
|
||||
bbs_list_messages = False
|
||||
|
||||
|
||||
# Dad Jokes Configuration
|
||||
if dad_jokes_enabled:
|
||||
@@ -112,7 +123,7 @@ if games_enabled is True:
|
||||
help_message = help_message + ", games"
|
||||
trap_list = trap_list + ("games",)
|
||||
gTnW_enabled = True
|
||||
gamesCmdList = "CMD: "
|
||||
gamesCmdList = "Play via DM🕹️ CMD: "
|
||||
if dopewars_enabled:
|
||||
gamesCmdList += "DopeWars, "
|
||||
if lemonade_enabled:
|
||||
@@ -125,6 +136,8 @@ if games_enabled is True:
|
||||
if videoPoker_enabled:
|
||||
gamesCmdList += "VideoPoker, "
|
||||
gamesCmdList = gamesCmdList[:-2] # remove the last comma
|
||||
else:
|
||||
gamesCmdList = ""
|
||||
|
||||
# Scheduled Broadcast Configuration
|
||||
if scheduler_enabled:
|
||||
@@ -574,12 +587,22 @@ def get_wikipedia_summary(search_term):
|
||||
return summary
|
||||
|
||||
def messageTrap(msg):
|
||||
# Check if the message contains a trap word
|
||||
# Check if the message contains a trap word, this is the first filter for listning to messages
|
||||
# after this the message is passed to the command_handler in the bot.py which is switch case filter for applying word to function
|
||||
|
||||
# Split Message on assumed words spaces m for m = msg.split(" ")
|
||||
# t in trap_list, built by the config and system.py not the user
|
||||
message_list=msg.split(" ")
|
||||
for m in message_list:
|
||||
for t in trap_list:
|
||||
# if word in message is in the trap list, return True
|
||||
if t.lower() == m.lower():
|
||||
return True
|
||||
# if no trap words found, run a search for near misses like ping? or cmd?
|
||||
for m in message_list:
|
||||
for t in range(len(trap_list)):
|
||||
if m.endswith('?') and m[:-1].lower() == trap_list[t]:
|
||||
return True
|
||||
return False
|
||||
|
||||
def exit_handler():
|
||||
|
||||
@@ -54,10 +54,8 @@ def drawCardsVp(*cards, return_string=True):
|
||||
# "King" should be "K" and "10" should still be "10"
|
||||
if card.rank == 10: # ten is the only one who's rank is 2 char long
|
||||
rank = str(card.rank)
|
||||
space = '' # if we write "10" on the card that line will be 1 char to long
|
||||
else:
|
||||
rank = str(card.rank)[0] # some have a rank of 'King' this changes that to a simple 'K' ("King" doesn't fit)
|
||||
space = ' ' # no "10", we use a blank space to will the void
|
||||
# get the cards suit in two steps
|
||||
suit = suits_name.index(card.suit)
|
||||
suit = suits_symbols[suit]
|
||||
@@ -282,7 +280,7 @@ def playVideoPoker(nodeID, message):
|
||||
# create new player if not in tracker
|
||||
logger.debug(f"System: VideoPoker: New Player {nodeID}")
|
||||
vpTracker.append({'nodeID': nodeID, 'cmd': 'new', 'time': time.time(), 'cash': vpStartingCash, 'player': None, 'deck': None, 'highScore': 0, 'drawCount': 0})
|
||||
return f"Welcome to 🎰 VideoPoker! you have {vpStartingCash} coins, Whats your bet?"
|
||||
return f"Welcome to 🎰 VideoPoker! you have {vpStartingCash} coins, Game Played via Direct Message. Whats your bet?"
|
||||
|
||||
# Gather the player's bet
|
||||
if getLastCmdVp(nodeID) == "new" or getLastCmdVp(nodeID) == "gameOver":
|
||||
|
||||
28
pong_bot.py
28
pong_bot.py
@@ -8,7 +8,7 @@ from pubsub import pub # pip install pubsub
|
||||
from modules.log import *
|
||||
from modules.system import *
|
||||
|
||||
responseDelay = 0.7 # delay in seconds for response to avoid message collision
|
||||
DEBUGpacket = False # Debug print the packet rx
|
||||
|
||||
def auto_response(message, snr, rssi, hop, message_from_id, channel_number, deviceID):
|
||||
# Auto response to messages
|
||||
@@ -117,8 +117,18 @@ def onReceive(packet, interface):
|
||||
# extract interface defailts from interface object
|
||||
rxType = type(interface).__name__
|
||||
rxNode = 0
|
||||
# Debug print the interface object
|
||||
#for item in interface.__dict__.items(): print (item)
|
||||
message_from_id = 0
|
||||
snr = 0
|
||||
rssi = 0
|
||||
hop = 0
|
||||
hop_away = 0
|
||||
|
||||
if DEBUGpacket:
|
||||
# Debug print the interface object
|
||||
for item in interface.__dict__.items(): intDebug = f"{item}\n"
|
||||
logger.debug(f"System: Packet Received on {rxType} Interface\n {intDebug} \n END of interface \n")
|
||||
# Debug print the packet for debugging
|
||||
logger.debug(f"Packet Received\n {packet} \n END of packet \n")
|
||||
|
||||
if rxType == 'SerialInterface':
|
||||
rxInterface = interface.__dict__.get('devPath', 'unknown')
|
||||
@@ -140,13 +150,7 @@ def onReceive(packet, interface):
|
||||
elif interface2_enabled and interface2_type == 'ble':
|
||||
rxNode = 2
|
||||
|
||||
# Debug print the packet for debugging
|
||||
#print(f"Packet Received\n {packet} \n END of packet \n")
|
||||
message_from_id = 0
|
||||
|
||||
# check for a message packet and process it
|
||||
snr = 0
|
||||
rssi = 0
|
||||
try:
|
||||
if 'decoded' in packet and packet['decoded']['portnum'] == 'TEXT_MESSAGE_APP':
|
||||
message_bytes = packet['decoded']['payload']
|
||||
@@ -281,13 +285,13 @@ async def start_rx():
|
||||
logger.info(f"System: Autoresponder Started for Device2 {get_name_from_number(myNodeNum2, 'long', 2)},"
|
||||
f"{get_name_from_number(myNodeNum2, 'short', 2)}. NodeID: {myNodeNum2}, {decimal_to_hex(myNodeNum2)}")
|
||||
if log_messages_to_file:
|
||||
logger.debug(f"System: Logging Messages to disk")
|
||||
logger.debug("System: Logging Messages to disk")
|
||||
if sentry_enabled:
|
||||
logger.debug(f"System: Sentry Enabled")
|
||||
logger.debug("System: Sentry Enabled")
|
||||
if store_forward_enabled:
|
||||
logger.debug(f"System: Store and Forward Enabled using limit: {storeFlimit}")
|
||||
if useDMForResponse:
|
||||
logger.debug(f"System: Respond by DM only")
|
||||
logger.debug("System: Respond by DM only")
|
||||
if repeater_enabled and interface2_enabled:
|
||||
logger.debug(f"System: Repeater Enabled for Channels: {repeater_channels}")
|
||||
if radio_detection_enabled:
|
||||
|
||||
Reference in New Issue
Block a user