Removed history, due to sensitive data
0
CHANGELOG.md
Normal file
19
LICENSE
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (c) 2022 Sebastian Obele / obele.eu
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
189
README.md
Normal file
@ -0,0 +1,189 @@
|
||||
# LXMF-Tools
|
||||
Various small programs and tools which use the message protocol LXMF from https://github.com/markqvist/LXMF
|
||||
|
||||
|
||||
## lxmf_bridge_matrix
|
||||
For more information, see the detailed [README.md](lxmf_bridge_matrix).
|
||||
|
||||
|
||||
## lxmf_bridge_meshtastic
|
||||
For more information, see the detailed [README.md](lxmf_bridge_meshtastic).
|
||||
|
||||
|
||||
## lxmf_bridge_mqtt
|
||||
This program provides an interface between LXMF and MQTT. It serves as a single message endpoint and not to transfer the LXMF/Reticlum traffic 1:1 to MQTT. It serves the purpose of providing an endpoint in the Reticulum network for third party applications that can communicate via MQTT. Through this all LXMF capable applications can communicate with it via messages. This can be used for example to communicate via text messages with a smarthome system (FHEM, openHAB, ioBroker, Node-RED or similar). The transmission format used by MQTT is JSON with freely definable topics. The target system can then respond to these JSON messages.
|
||||
|
||||
For more information, see the detailed [README.md](lxmf_bridge_mqtt).
|
||||
|
||||
|
||||
## lxmf_bridge_telegram
|
||||
For more information, see the detailed [README.md](lxmf_bridge_telegram).
|
||||
|
||||
|
||||
## lxmf_chatbot
|
||||
This program provides a simple chatbot (RiveScript) which can communicate via LXMF.
|
||||
|
||||
For more information, see the detailed [README.md](lxmf_chatbot).
|
||||
|
||||
|
||||
## lxmf_cmd
|
||||
This program executes any text received by message as a system command and returns the output of the command as a message. Only single commands can be executed directly. No interactive terminal is created.
|
||||
|
||||
For more information, see the detailed [README.md](lxmf_cmd).
|
||||
|
||||
|
||||
## lxmf_distribution_group
|
||||
This program provides an email like distribution group. It will distribute incoming LXMF messages to multiple recipients. Since this program acts as a normal LXMF endpoint, all compatible chat applications can be used. In addition to simple messaging, there is a simple command-based user interface. Where all relevant actions for daily administration can be performed. The basic configuration is done in the configuration files. There are various options to adapt the entire behavior of the group to personal needs. This distribution group is much more than a standard email distribution group. It emulates advanced group functions with automatic notifications etc. Different user permissions can be defined. For each user type, the range of functions can be defined individually. The normal users have only small rights. While a moderator or admin can perform everything necessary by simple commands. Once the basic configuration is done, everything else can be done by LXMF messages as commands.
|
||||
|
||||
For more information, see the detailed [README.md](lxmf_distribution_group).
|
||||
|
||||
|
||||
## lxmf_distribution_group_minimal
|
||||
This program is a minimalist version of the normal distribution group. The functionality is reduced to a minimum. Only sender and receiver users can be defined. Messages are then sent to the other users accordingly. There is no user interface or other notifications. Only the messages are distributed 1:1. The administration is done completely by the respective configuration files which are to be edited accordingly.
|
||||
|
||||
For more information, see the detailed [README.md](lxmf_distribution_group_minimal).
|
||||
|
||||
|
||||
## lxmf_echo
|
||||
This program is a simple echo server. All received messages are sent back 1:1 as an answer. This can be used as a simple counterpart to test the chat functionality of applications.
|
||||
|
||||
For more information, see the detailed [README.md](lxmf_echo).
|
||||
|
||||
|
||||
## lxmf_ping
|
||||
This program sends an adjustable number of LXMF messages to a destination. Then a simple statistic is created to check the success or failure of a single message. This tool can be useful to load the LXMF/Reticulum network with a defined load of messages. This can be used to simulate a certain amount of users.
|
||||
|
||||
For more information, see the detailed [README.md](lxmf_ping).
|
||||
|
||||
|
||||
## lxmf_terminal
|
||||
This program provides a complete terminal session on the server. Any commands can be executed on the target device. The communication is done by single LXMF messages. This offers the advantage that simple terminal commands can be used by any LXMF capable application.
|
||||
|
||||
For more information, see the detailed [README.md](lxmf_terminal).
|
||||
|
||||
|
||||
## General Information for all tools/programs
|
||||
|
||||
|
||||
### Current Status:
|
||||
It should currently be considered beta software. All core features are implemented and functioning, but additions will probably occur as real-world use is explored. There will be bugs.
|
||||
The full documentation is not yet available. Due to lack of time I can also not say when this will be further processed.
|
||||
|
||||
|
||||
### Install:
|
||||
- Install all required prerequisites. (Default Reticulum installation. Only necessary if reticulum is not yet installed.)
|
||||
```bash
|
||||
apt update
|
||||
apt upgrade
|
||||
|
||||
apt install python3-pip
|
||||
|
||||
pip install pip --upgrade
|
||||
reboot
|
||||
|
||||
pip3 install rns
|
||||
pip3 install pyserial netifaces
|
||||
|
||||
pip3 install lxmf
|
||||
```
|
||||
|
||||
- Change the Reticulum configuration to suit your needs and use-case.
|
||||
```bash
|
||||
nano /.reticulum/config
|
||||
```
|
||||
|
||||
- Download the [file](lxmf_distribution_group.py) from this repository.
|
||||
```bash
|
||||
wget https://raw.githubusercontent.com/SebastianObi/LXMF-Tools/main/lxmf_distribution_group/lxmf_distribution_group.py
|
||||
```
|
||||
|
||||
- Make it executable with the following command
|
||||
```bash
|
||||
chmod +x lxmf_distribution_group.py
|
||||
```
|
||||
|
||||
### Start:
|
||||
- Start it
|
||||
```bash
|
||||
./lxmf_distribution_group.py
|
||||
```
|
||||
- After the first start edit the configuration file to suit your needs and use-case. The file location is displayed.
|
||||
- Example minimal configuration (override of the default config `config.cfg`). These are the most relevant settings that need to be adjusted. All other settings are in `config.cfg`
|
||||
```bash
|
||||
nano /root/.lxmf_distribution_group/config.cfg.owr
|
||||
```
|
||||
- Start it again. Finished!
|
||||
```bash
|
||||
./lxmf_distribution_group.py
|
||||
```
|
||||
|
||||
|
||||
### Run as a system service/deamon:
|
||||
- Create a service file.
|
||||
```bash
|
||||
nano /etc/systemd/system/lxmf_distribution_group.service
|
||||
```
|
||||
- Copy and edit the following content to your own needs.
|
||||
```bash
|
||||
[Unit]
|
||||
Description=lxmf_distribution_group.py Daemon
|
||||
After=multi-user.target
|
||||
[Service]
|
||||
# ExecStartPre=/bin/sleep 10
|
||||
Type=simple
|
||||
Restart=always
|
||||
RestartSec=3
|
||||
User=root
|
||||
ExecStart=/root/lxmf_distribution_group.py
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
- Enable the service.
|
||||
```bash
|
||||
systemctl enable lxmf_distribution_group
|
||||
```
|
||||
- Start the service.
|
||||
```bash
|
||||
systemctl start lxmf_distribution_group
|
||||
```
|
||||
|
||||
|
||||
### Start/Stop service:
|
||||
```bash
|
||||
systemctl start lxmf_distribution_group
|
||||
systemctl stop lxmf_distribution_group
|
||||
```
|
||||
|
||||
|
||||
### Enable/Disable service:
|
||||
```bash
|
||||
systemctl enable lxmf_distribution_group
|
||||
systemctl disable lxmf_distribution_group
|
||||
```
|
||||
|
||||
|
||||
### Run several instances (To copy the same application):
|
||||
- Run the program with a different configuration path.
|
||||
```bash
|
||||
./lxmf_distribution_group.py -p /root/.lxmf_distribution_group_2nd
|
||||
./lxmf_distribution_group.py -p /root/.lxmf_distribution_group_3nd
|
||||
```
|
||||
- After the first start edit the configuration file to suit your needs and use-case. The file location is displayed.
|
||||
|
||||
|
||||
## Support / Donations
|
||||
You can help support the continued development by donating via one of the following channels:
|
||||
|
||||
- PayPal: https://paypal.me/SebastianObi
|
||||
- Liberapay: https://liberapay.com/SebastianObi/donate
|
||||
|
||||
|
||||
## Support in another way?
|
||||
You are welcome to participate in the development. Just create a pull request. Or just contact me for further clarifications.
|
||||
|
||||
|
||||
## Do you need a special function or customization?
|
||||
Then feel free to contact me. Customizations or tools developed specifically for you can be realized.
|
||||
|
||||
|
||||
## FAQ
|
132
build_git.sh
Executable file
@ -0,0 +1,132 @@
|
||||
#!/bin/bash
|
||||
|
||||
|
||||
##############################################################################################################
|
||||
# Configuration
|
||||
|
||||
|
||||
BRANCH="main"
|
||||
ORIGIN="git@github.com:SebastianObi/LXMF-Tools.git"
|
||||
FILES_ADD=("*")
|
||||
FILES_REMOVE=(".git/*")
|
||||
COMMENT_COMMIT="$(date +%Y-%m-%d_%H:%M:%S)"
|
||||
COMMENT_CLEAR="Removed history, due to sensitive data"
|
||||
COMMENT_INIT="Initial commit"
|
||||
|
||||
|
||||
##############################################################################################################
|
||||
# Functions
|
||||
|
||||
|
||||
_prompt() {
|
||||
echo -e ""
|
||||
echo -e "Select an option:"
|
||||
options=("Commit/Push" "Clear History" "Init" "Exit")
|
||||
select opt in "${options[@]}"; do
|
||||
case $opt in
|
||||
"Commit/Push"*)
|
||||
_commit
|
||||
break;;
|
||||
"Clear History"*)
|
||||
_clear
|
||||
break;;
|
||||
"Init"*)
|
||||
_init
|
||||
break;;
|
||||
"Exit"*)
|
||||
echo -e ""
|
||||
echo -e "Exit"
|
||||
break;;
|
||||
*)
|
||||
echo -e "Invalid choice!"
|
||||
break;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
_define_files() {
|
||||
for file in ${FILES_ADD[@]}; do
|
||||
git add "${file}"
|
||||
done
|
||||
|
||||
for file in ${FILES_REMOVE[@]}; do
|
||||
git reset -- "${file}"
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
_commit() {
|
||||
_define_files
|
||||
|
||||
git diff --numstat
|
||||
|
||||
echo -e ""
|
||||
echo -e "Commit/Push to Git"
|
||||
echo -e "Comment:"
|
||||
|
||||
read VAR
|
||||
if [ -z "${VAR}" ]; then
|
||||
VAR="${COMMENT_COMMIT}"
|
||||
fi
|
||||
|
||||
git commit -a -m "${VAR}"
|
||||
git push
|
||||
}
|
||||
|
||||
|
||||
_clear() {
|
||||
echo -e ""
|
||||
echo -e "Clear History"
|
||||
echo -e "Comment:"
|
||||
|
||||
read VAR
|
||||
if [ -z "${VAR}" ]; then
|
||||
VAR="${COMMENT_CLEAR}"
|
||||
fi
|
||||
|
||||
rm -rf .git
|
||||
|
||||
git init
|
||||
|
||||
_define_files
|
||||
|
||||
git commit -m "${VAR}"
|
||||
git branch -M "${BRANCH}"
|
||||
git remote add origin "${ORIGIN}"
|
||||
git push -f -u origin "${BRANCH}"
|
||||
}
|
||||
|
||||
|
||||
_init() {
|
||||
echo -e ""
|
||||
echo -e "Init"
|
||||
echo -e "Comment:"
|
||||
|
||||
read VAR
|
||||
if [ -z "${VAR}" ]; then
|
||||
VAR="${COMMENT_INIT}"
|
||||
fi
|
||||
|
||||
rm -rf .git
|
||||
|
||||
git init
|
||||
|
||||
_define_files
|
||||
|
||||
git branch -M "${BRANCH}"
|
||||
git remote add origin "${ORIGIN}"
|
||||
|
||||
git pull origin "${BRANCH}"
|
||||
|
||||
git commit -m "${VAR}"
|
||||
|
||||
git push -f -u origin "${BRANCH}"
|
||||
}
|
||||
|
||||
|
||||
##############################################################################################################
|
||||
# Setup/Start
|
||||
|
||||
|
||||
_prompt
|
BIN
docs/screenshots/lxmf_bridge_mqtt_01.png
Normal file
After Width: | Height: | Size: 61 KiB |
BIN
docs/screenshots/lxmf_chatbot_01.png
Normal file
After Width: | Height: | Size: 64 KiB |
BIN
docs/screenshots/lxmf_cmd_01.png
Normal file
After Width: | Height: | Size: 56 KiB |
BIN
docs/screenshots/lxmf_distribution_group_01.png
Normal file
After Width: | Height: | Size: 9.2 KiB |
BIN
docs/screenshots/lxmf_distribution_group_02.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
docs/screenshots/lxmf_distribution_group_03.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
docs/screenshots/lxmf_distribution_group_04.png
Normal file
After Width: | Height: | Size: 8.7 KiB |
BIN
docs/screenshots/lxmf_distribution_group_05.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
docs/screenshots/lxmf_distribution_group_06.png
Normal file
After Width: | Height: | Size: 9.5 KiB |
BIN
docs/screenshots/lxmf_distribution_group_07.png
Normal file
After Width: | Height: | Size: 5.9 KiB |
BIN
docs/screenshots/lxmf_distribution_group_08.png
Normal file
After Width: | Height: | Size: 82 KiB |
BIN
docs/screenshots/lxmf_distribution_group_minimal_01.png
Normal file
After Width: | Height: | Size: 7.7 KiB |
BIN
docs/screenshots/lxmf_distribution_group_minimal_02.png
Normal file
After Width: | Height: | Size: 7.3 KiB |
BIN
docs/screenshots/lxmf_distribution_group_minimal_03.png
Normal file
After Width: | Height: | Size: 75 KiB |
BIN
docs/screenshots/lxmf_echo_01.png
Normal file
After Width: | Height: | Size: 47 KiB |
BIN
docs/screenshots/lxmf_ping_01.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
docs/screenshots/lxmf_terminal_01.png
Normal file
After Width: | Height: | Size: 56 KiB |
0
lxmf_bridge_matrix/CHANGELOG.md
Normal file
6
lxmf_bridge_matrix/README.md
Normal file
@ -0,0 +1,6 @@
|
||||
# lxmf_bridge_matrix
|
||||
|
||||
|
||||
## Overview
|
||||
|
||||
For more information, see the configuration options (at the end of the program files). Everything else is briefly documented there. After the first start this configuration will be created as default config in the corresponding file.
|
0
lxmf_bridge_matrix/lxmf_bridge_matrix.py
Executable file
0
lxmf_bridge_meshtastic/CHANGELOG.md
Normal file
6
lxmf_bridge_meshtastic/README.md
Normal file
@ -0,0 +1,6 @@
|
||||
# lxmf_bridge_meshtastic
|
||||
|
||||
|
||||
## Overview
|
||||
|
||||
For more information, see the configuration options (at the end of the program files). Everything else is briefly documented there. After the first start this configuration will be created as default config in the corresponding file.
|
0
lxmf_bridge_meshtastic/lxmf_bridge_meshtastic.py
Executable file
0
lxmf_bridge_mqtt/CHANGELOG.md
Normal file
200
lxmf_bridge_mqtt/README.md
Normal file
@ -0,0 +1,200 @@
|
||||
# lxmf_bridge_mqtt
|
||||
This program provides an interface between LXMF and MQTT. It serves as a single message endpoint and not to transfer the LXMF/Reticlum traffic 1:1 to MQTT. It serves the purpose of providing an endpoint in the Reticulum network for third party applications that can communicate via MQTT. Through this all LXMF capable applications can communicate with it via messages. This can be used for example to communicate via text messages with a smarthome system (FHEM, openHAB, ioBroker, Node-RED or similar). The transmission format used by MQTT is JSON with freely definable topics. The target system can then respond to these JSON messages.
|
||||
|
||||
For more information, see the configuration options (at the end of the program files). Everything else is briefly documented there. After the first start this configuration will be created as default config in the corresponding file.
|
||||
|
||||
|
||||
### Features
|
||||
- Compatible with all LXMF applications (NomadNet, Sideband, ...)
|
||||
- Compatible with all MQTT servers
|
||||
|
||||
|
||||
## Examples of use
|
||||
|
||||
###
|
||||
|
||||
### General info how the messages are transported
|
||||
All messages between client<->server are transported as single 1:1 messages in the LXMF/Reticulum network.
|
||||
Accordingly, encryption takes place between these end points.
|
||||
If a direct delivery of the message does not work, it is sent to a propagation node. There it is stored temporarily and can be retrieved by the client later.
|
||||
|
||||
As these are normal LXMF messages, any LXMF capable application can be used to communicate with the group.
|
||||
|
||||
|
||||
## Current Status
|
||||
It should currently be considered beta software. All core features are implemented and functioning, but additions will probably occur as real-world use is explored. There will be bugs.
|
||||
The full documentation is not yet available. Due to lack of time I can also not say when this will be further processed.
|
||||
|
||||
|
||||
## Screenshots / Usage examples
|
||||
<img src="../docs/screenshots/lxmf_bridge_mqtt_01.png" width="200px">
|
||||
|
||||
|
||||
## Installation manual
|
||||
|
||||
### Install:
|
||||
- Install all required prerequisites. (Default Reticulum installation. Only necessary if reticulum is not yet installed.)
|
||||
```bash
|
||||
apt update
|
||||
apt upgrade
|
||||
|
||||
apt install python3-pip
|
||||
|
||||
pip install pip --upgrade
|
||||
reboot
|
||||
|
||||
pip3 install rns
|
||||
pip3 install pyserial netifaces
|
||||
|
||||
pip3 install lxmf
|
||||
```
|
||||
- Change the Reticulum configuration to suit your needs and use-case.
|
||||
```bash
|
||||
nano /.reticulum/config
|
||||
```
|
||||
- Download the [file](lxmf_bridge_mqtt.py) from this repository.
|
||||
```bash
|
||||
wget https://raw.githubusercontent.com/SebastianObi/LXMF-Tools/main/lxmf_bridge_mqtt/lxmf_bridge_mqtt.py
|
||||
```
|
||||
- Make it executable with the following command
|
||||
```bash
|
||||
chmod +x lxmf_bridge_mqtt.py
|
||||
```
|
||||
|
||||
### Start:
|
||||
- Start it
|
||||
```bash
|
||||
./lxmf_bridge_mqtt.py
|
||||
```
|
||||
- After the first start edit the configuration file to suit your needs and use-case. The file location is displayed.
|
||||
- Example minimal configuration (override of the default config `config.cfg`). These are the most relevant settings that need to be adjusted. All other settings are in `config.cfg`
|
||||
```bash
|
||||
nano /root/.lxmf_bridge_mqtt/config.cfg.owr
|
||||
```
|
||||
```bash
|
||||
```
|
||||
- Start it again. Finished!
|
||||
```bash
|
||||
./lxmf_bridge_mqtt.py
|
||||
```
|
||||
|
||||
|
||||
### Run as a system service/deamon:
|
||||
- Create a service file.
|
||||
```bash
|
||||
nano /etc/systemd/system/lxmf_bridge_mqtt.service
|
||||
```
|
||||
- Copy and edit the following content to your own needs.
|
||||
```bash
|
||||
[Unit]
|
||||
Description=LXMF Bridge MQTT Daemon
|
||||
After=multi-user.target
|
||||
[Service]
|
||||
# ExecStartPre=/bin/sleep 10
|
||||
Type=simple
|
||||
Restart=always
|
||||
RestartSec=3
|
||||
User=root
|
||||
ExecStart=/root/lxmf_bridge_mqtt.py
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
- Enable the service.
|
||||
```bash
|
||||
systemctl enable lxmf_bridge_mqtt
|
||||
```
|
||||
- Start the service.
|
||||
```bash
|
||||
systemctl start lxmf_bridge_mqtt
|
||||
```
|
||||
|
||||
|
||||
### Start/Stop service:
|
||||
```bash
|
||||
systemctl start lxmf_bridge_mqtt
|
||||
systemctl stop lxmf_bridge_mqtt
|
||||
```
|
||||
|
||||
|
||||
### Enable/Disable service:
|
||||
```bash
|
||||
systemctl enable lxmf_bridge_mqtt
|
||||
systemctl disable lxmf_bridge_mqtt
|
||||
```
|
||||
|
||||
|
||||
### Run several instances (To copy the same application):
|
||||
- Run the program with a different configuration path.
|
||||
```bash
|
||||
./lxmf_bridge_mqtt.py -p /root/.lxmf_bridge_mqtt_2nd
|
||||
./lxmf_bridge_mqtt.py -p /root/.lxmf_bridge_mqtt_3nd
|
||||
```
|
||||
- After the first start edit the configuration file to suit your needs and use-case. The file location is displayed.
|
||||
|
||||
|
||||
### First usage:
|
||||
- With a manual start via the console, the own LXMF address is displayed:
|
||||
```
|
||||
[] ...............................................................................
|
||||
[] LXMF - Address: <801f48d54bc71cb3e0886944832aaf8d>
|
||||
[] ...............................................................................`
|
||||
```
|
||||
- This address is also annouced at startup in the default setting.
|
||||
- Now the software can be used.
|
||||
|
||||
|
||||
### Startup parameters:
|
||||
```bash
|
||||
usage: lxmf_distribution_group_minimal.py [-h] [-p PATH] [-pr PATH_RNS] [-pl PATH_LOG] [-l LOGLEVEL] [-s] [--exampleconfig]
|
||||
[--exampleconfigoverride] [--exampledata]
|
||||
|
||||
LXMF Distribution Group - Server-Side group functions for LXMF based apps
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
-p PATH, --path PATH Path to alternative config directory
|
||||
-pr PATH_RNS, --path_rns PATH_RNS
|
||||
Path to alternative Reticulum config directory
|
||||
-pl PATH_LOG, --path_log PATH_LOG
|
||||
Path to alternative log directory
|
||||
-l LOGLEVEL, --loglevel LOGLEVEL
|
||||
-s, --service Running as a service and should log to file
|
||||
--exampleconfig Print verbose configuration example to stdout and exit
|
||||
--exampleconfigoverride
|
||||
Print verbose configuration example to stdout and exit
|
||||
--exampledata Print verbose configuration example to stdout and exit
|
||||
```
|
||||
|
||||
|
||||
### Config/data files:
|
||||
- config.cfg
|
||||
|
||||
This is the default config file.
|
||||
|
||||
- config.cfg.owr
|
||||
|
||||
This is the user configuration file to override the default configuration file.
|
||||
All settings made here have precedence.
|
||||
This file can be used to clearly summarize all settings that deviate from the default.
|
||||
This also has the advantage that all changed settings can be kept when updating the program.
|
||||
|
||||
|
||||
## Configuration manual (Examples)
|
||||
The configurations shown here are only a part of the total configuration.
|
||||
It only serves to show the configuration that is necessary and adapted for the respective function.
|
||||
All configurations must be made in the file `config.cfg.owr`.
|
||||
All possible settings can be seen in the default configuration file `config.cfg`.
|
||||
|
||||
|
||||
## Admin manual
|
||||
This guide applies to all admins. Here are briefly explained the administative possibilities.
|
||||
|
||||
|
||||
## User manual
|
||||
This guide applies to users or admins. Here are briefly explained the normal possibilities of the software.
|
||||
|
||||
|
||||
## FAQ
|
||||
|
||||
### How do I start with the software?
|
||||
You should read the `Installation manual` section. There everything is explained briefly. Just work through everything from top to bottom :)
|
1407
lxmf_bridge_mqtt/lxmf_bridge_mqtt.py
Executable file
0
lxmf_bridge_telegram/CHANGELOG.md
Normal file
6
lxmf_bridge_telegram/README.md
Normal file
@ -0,0 +1,6 @@
|
||||
# lxmf_bridge_telegram
|
||||
|
||||
|
||||
## Overview
|
||||
|
||||
For more information, see the configuration options (at the end of the program files). Everything else is briefly documented there. After the first start this configuration will be created as default config in the corresponding file.
|
0
lxmf_bridge_telegram/lxmf_bridge_telegram.py
Executable file
0
lxmf_chatbot/CHANGELOG.md
Normal file
197
lxmf_chatbot/README.md
Normal file
@ -0,0 +1,197 @@
|
||||
# lxmf_chatbot
|
||||
This program provides a simple chatbot (RiveScript) which can communicate via LXMF.
|
||||
|
||||
For more information, see the configuration options (at the end of the program files). Everything else is briefly documented there. After the first start this configuration will be created as default config in the corresponding file.
|
||||
|
||||
|
||||
### Features
|
||||
- Compatible with all LXMF applications (NomadNet, Sideband, ...)
|
||||
|
||||
|
||||
## Examples of use
|
||||
|
||||
###
|
||||
|
||||
### General info how the messages are transported
|
||||
All messages between client<->server are transported as single 1:1 messages in the LXMF/Reticulum network.
|
||||
Accordingly, encryption takes place between these end points.
|
||||
If a direct delivery of the message does not work, it is sent to a propagation node. There it is stored temporarily and can be retrieved by the client later.
|
||||
|
||||
As these are normal LXMF messages, any LXMF capable application can be used to communicate with the group.
|
||||
|
||||
|
||||
## Current Status
|
||||
It should currently be considered beta software. All core features are implemented and functioning, but additions will probably occur as real-world use is explored. There will be bugs.
|
||||
The full documentation is not yet available. Due to lack of time I can also not say when this will be further processed.
|
||||
|
||||
|
||||
## Screenshots / Usage examples
|
||||
<img src="../docs/screenshots/lxmf_chatbot_01.png" width="200px">
|
||||
|
||||
|
||||
## Installation manual
|
||||
|
||||
### Install:
|
||||
- Install all required prerequisites. (Default Reticulum installation. Only necessary if reticulum is not yet installed.)
|
||||
```bash
|
||||
apt update
|
||||
apt upgrade
|
||||
|
||||
apt install python3-pip
|
||||
|
||||
pip install pip --upgrade
|
||||
reboot
|
||||
|
||||
pip3 install rns
|
||||
pip3 install pyserial netifaces
|
||||
|
||||
pip3 install lxmf
|
||||
```
|
||||
- Change the Reticulum configuration to suit your needs and use-case.
|
||||
```bash
|
||||
nano /.reticulum/config
|
||||
```
|
||||
- Download the [file](lxmf_chatbot.py) from this repository.
|
||||
```bash
|
||||
wget https://raw.githubusercontent.com/SebastianObi/LXMF-Tools/main/lxmf_chatbot/lxmf_chatbot.py
|
||||
```
|
||||
- Make it executable with the following command
|
||||
```bash
|
||||
chmod +x lxmf_chatbot.py
|
||||
```
|
||||
|
||||
### Start:
|
||||
- Start it
|
||||
```bash
|
||||
./lxmf_chatbot.py
|
||||
```
|
||||
- After the first start edit the configuration file to suit your needs and use-case. The file location is displayed.
|
||||
- Example minimal configuration (override of the default config `config.cfg`). These are the most relevant settings that need to be adjusted. All other settings are in `config.cfg`
|
||||
```bash
|
||||
nano /root/.lxmf_chatbot/config.cfg.owr
|
||||
```
|
||||
```bash
|
||||
```
|
||||
- Start it again. Finished!
|
||||
```bash
|
||||
./lxmf_chatbot.py
|
||||
```
|
||||
|
||||
|
||||
### Run as a system service/deamon:
|
||||
- Create a service file.
|
||||
```bash
|
||||
nano /etc/systemd/system/lxmf_chatbot.service
|
||||
```
|
||||
- Copy and edit the following content to your own needs.
|
||||
```bash
|
||||
[Unit]
|
||||
Description=lxmf_chatbot.py Daemon
|
||||
After=multi-user.target
|
||||
[Service]
|
||||
# ExecStartPre=/bin/sleep 10
|
||||
Type=simple
|
||||
Restart=always
|
||||
RestartSec=3
|
||||
User=root
|
||||
ExecStart=/root/lxmf_chatbot.py
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
- Enable the service.
|
||||
```bash
|
||||
systemctl enable lxmf_chatbot
|
||||
```
|
||||
- Start the service.
|
||||
```bash
|
||||
systemctl start lxmf_chatbot
|
||||
```
|
||||
|
||||
|
||||
### Start/Stop service:
|
||||
```bash
|
||||
systemctl start lxmf_chatbot
|
||||
systemctl stop lxmf_chatbot
|
||||
```
|
||||
|
||||
|
||||
### Enable/Disable service:
|
||||
```bash
|
||||
systemctl enable lxmf_chatbot
|
||||
systemctl disable lxmf_chatbot
|
||||
```
|
||||
|
||||
|
||||
### Run several instances (To copy the same application):
|
||||
- Run the program with a different configuration path.
|
||||
```bash
|
||||
./lxmf_chatbot.py -p /root/.lxmf_chatbot_2nd
|
||||
./lxmf_chatbot.py -p /root/.lxmf_chatbot_3nd
|
||||
```
|
||||
- After the first start edit the configuration file to suit your needs and use-case. The file location is displayed.
|
||||
|
||||
|
||||
### First usage:
|
||||
- With a manual start via the console, the own LXMF address is displayed:
|
||||
```
|
||||
[] ...............................................................................
|
||||
[] LXMF - Address: <801f48d54bc71cb3e0886944832aaf8d>
|
||||
[] ...............................................................................`
|
||||
```
|
||||
- This address is also annouced at startup in the default setting.
|
||||
- Now the software can be used.
|
||||
|
||||
|
||||
### Startup parameters:
|
||||
```bash
|
||||
usage: lxmf_chatbot.py [-h] [-p PATH] [-pr PATH_RNS] [-pl PATH_LOG] [-l LOGLEVEL] [-s] [--exampleconfig] [--exampleconfigoverride]
|
||||
|
||||
LXMF Chatbot - Simple chatbot (RiveScript) for LXMF messages
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
-p PATH, --path PATH Path to alternative config directory
|
||||
-pr PATH_RNS, --path_rns PATH_RNS
|
||||
Path to alternative Reticulum config directory
|
||||
-pl PATH_LOG, --path_log PATH_LOG
|
||||
Path to alternative log directory
|
||||
-l LOGLEVEL, --loglevel LOGLEVEL
|
||||
-s, --service Running as a service and should log to file
|
||||
--exampleconfig Print verbose configuration example to stdout and exit
|
||||
--exampleconfigoverride
|
||||
Print verbose configuration example to stdout and exit
|
||||
```
|
||||
|
||||
|
||||
### Config/data files:
|
||||
- config.cfg
|
||||
|
||||
This is the default config file.
|
||||
|
||||
- config.cfg.owr
|
||||
|
||||
This is the user configuration file to override the default configuration file.
|
||||
All settings made here have precedence.
|
||||
This file can be used to clearly summarize all settings that deviate from the default.
|
||||
This also has the advantage that all changed settings can be kept when updating the program.
|
||||
|
||||
|
||||
## Configuration manual (Examples)
|
||||
The configurations shown here are only a part of the total configuration.
|
||||
It only serves to show the configuration that is necessary and adapted for the respective function.
|
||||
All configurations must be made in the file `config.cfg.owr`.
|
||||
All possible settings can be seen in the default configuration file `config.cfg`.
|
||||
|
||||
|
||||
## Admin manual
|
||||
This guide applies to all admins. Here are briefly explained the administative possibilities.
|
||||
|
||||
|
||||
## User manual
|
||||
This guide applies to users or admins. Here are briefly explained the normal possibilities of the software.
|
||||
|
||||
|
||||
## FAQ
|
||||
|
||||
### How do I start with the software?
|
||||
You should read the `Installation manual` section. There everything is explained briefly. Just work through everything from top to bottom :)
|
1145
lxmf_chatbot/lxmf_chatbot.py
Executable file
0
lxmf_cmd/CHANGELOG.md
Normal file
196
lxmf_cmd/README.md
Normal file
@ -0,0 +1,196 @@
|
||||
# lxmf_cmd
|
||||
This program executes any text received by message as a system command and returns the output of the command as a message. Only single commands can be executed directly. No interactive terminal is created.
|
||||
|
||||
For more information, see the configuration options (at the end of the program files). Everything else is briefly documented there. After the first start this configuration will be created as default config in the corresponding file.
|
||||
|
||||
|
||||
### Features
|
||||
- Compatible with all LXMF applications (NomadNet, Sideband, ...)
|
||||
|
||||
|
||||
## Examples of use
|
||||
|
||||
###
|
||||
|
||||
### General info how the messages are transported
|
||||
All messages between client<->server are transported as single 1:1 messages in the LXMF/Reticulum network.
|
||||
Accordingly, encryption takes place between these end points.
|
||||
If a direct delivery of the message does not work, it is sent to a propagation node. There it is stored temporarily and can be retrieved by the client later.
|
||||
|
||||
As these are normal LXMF messages, any LXMF capable application can be used to communicate with the group.
|
||||
|
||||
|
||||
## Current Status
|
||||
It should currently be considered beta software. All core features are implemented and functioning, but additions will probably occur as real-world use is explored. There will be bugs.
|
||||
The full documentation is not yet available. Due to lack of time I can also not say when this will be further processed.
|
||||
|
||||
|
||||
## Screenshots / Usage examples
|
||||
<img src="../docs/screenshots/lxmf_cmd_01.png" width="200px">
|
||||
|
||||
## Installation manual
|
||||
|
||||
### Install:
|
||||
- Install all required prerequisites. (Default Reticulum installation. Only necessary if reticulum is not yet installed.)
|
||||
```bash
|
||||
apt update
|
||||
apt upgrade
|
||||
|
||||
apt install python3-pip
|
||||
|
||||
pip install pip --upgrade
|
||||
reboot
|
||||
|
||||
pip3 install rns
|
||||
pip3 install pyserial netifaces
|
||||
|
||||
pip3 install lxmf
|
||||
```
|
||||
- Change the Reticulum configuration to suit your needs and use-case.
|
||||
```bash
|
||||
nano /.reticulum/config
|
||||
```
|
||||
- Download the [file](lxmf_cmd.py) from this repository.
|
||||
```bash
|
||||
wget https://raw.githubusercontent.com/SebastianObi/LXMF-Tools/main/lxmf_cmd/lxmf_cmd.py
|
||||
```
|
||||
- Make it executable with the following command
|
||||
```bash
|
||||
chmod +x lxmf_cmd.py
|
||||
```
|
||||
|
||||
### Start:
|
||||
- Start it
|
||||
```bash
|
||||
./lxmf_cmd.py
|
||||
```
|
||||
- After the first start edit the configuration file to suit your needs and use-case. The file location is displayed.
|
||||
- Example minimal configuration (override of the default config `config.cfg`). These are the most relevant settings that need to be adjusted. All other settings are in `config.cfg`
|
||||
```bash
|
||||
nano /root/.lxmf_cmd/config.cfg.owr
|
||||
```
|
||||
```bash
|
||||
```
|
||||
- Start it again. Finished!
|
||||
```bash
|
||||
./lxmf_cmd.py
|
||||
```
|
||||
|
||||
|
||||
### Run as a system service/deamon:
|
||||
- Create a service file.
|
||||
```bash
|
||||
nano /etc/systemd/system/lxmf_cmd.service
|
||||
```
|
||||
- Copy and edit the following content to your own needs.
|
||||
```bash
|
||||
[Unit]
|
||||
Description=lxmf_cmd.py Daemon
|
||||
After=multi-user.target
|
||||
[Service]
|
||||
# ExecStartPre=/bin/sleep 10
|
||||
Type=simple
|
||||
Restart=always
|
||||
RestartSec=3
|
||||
User=root
|
||||
ExecStart=/root/lxmf_cmd.py
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
- Enable the service.
|
||||
```bash
|
||||
systemctl enable lxmf_cmd
|
||||
```
|
||||
- Start the service.
|
||||
```bash
|
||||
systemctl start lxmf_cmd
|
||||
```
|
||||
|
||||
|
||||
### Start/Stop service:
|
||||
```bash
|
||||
systemctl start lxmf_cmd
|
||||
systemctl stop lxmf_cmd
|
||||
```
|
||||
|
||||
|
||||
### Enable/Disable service:
|
||||
```bash
|
||||
systemctl enable lxmf_cmd
|
||||
systemctl disable lxmf_cmd
|
||||
```
|
||||
|
||||
|
||||
### Run several instances (To copy the same application):
|
||||
- Run the program with a different configuration path.
|
||||
```bash
|
||||
./lxmf_cmd.py -p /root/.lxmf_cmd_2nd
|
||||
./lxmf_cmd.py -p /root/.lxmf_cmd_3nd
|
||||
```
|
||||
- After the first start edit the configuration file to suit your needs and use-case. The file location is displayed.
|
||||
|
||||
|
||||
### First usage:
|
||||
- With a manual start via the console, the own LXMF address is displayed:
|
||||
```
|
||||
[] ...............................................................................
|
||||
[] LXMF - Address: <801f48d54bc71cb3e0886944832aaf8d>
|
||||
[] ...............................................................................`
|
||||
```
|
||||
- This address is also annouced at startup in the default setting.
|
||||
- Now the software can be used.
|
||||
|
||||
|
||||
### Startup parameters:
|
||||
```bash
|
||||
usage: lxmf_cmd.py [-h] [-p PATH] [-pr PATH_RNS] [-pl PATH_LOG] [-l LOGLEVEL] [-s] [--exampleconfig] [--exampleconfigoverride]
|
||||
|
||||
LXMF CMD -
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
-p PATH, --path PATH Path to alternative config directory
|
||||
-pr PATH_RNS, --path_rns PATH_RNS
|
||||
Path to alternative Reticulum config directory
|
||||
-pl PATH_LOG, --path_log PATH_LOG
|
||||
Path to alternative log directory
|
||||
-l LOGLEVEL, --loglevel LOGLEVEL
|
||||
-s, --service Running as a service and should log to file
|
||||
--exampleconfig Print verbose configuration example to stdout and exit
|
||||
--exampleconfigoverride
|
||||
Print verbose configuration example to stdout and exit
|
||||
```
|
||||
|
||||
|
||||
### Config/data files:
|
||||
- config.cfg
|
||||
|
||||
This is the default config file.
|
||||
|
||||
- config.cfg.owr
|
||||
|
||||
This is the user configuration file to override the default configuration file.
|
||||
All settings made here have precedence.
|
||||
This file can be used to clearly summarize all settings that deviate from the default.
|
||||
This also has the advantage that all changed settings can be kept when updating the program.
|
||||
|
||||
|
||||
## Configuration manual (Examples)
|
||||
The configurations shown here are only a part of the total configuration.
|
||||
It only serves to show the configuration that is necessary and adapted for the respective function.
|
||||
All configurations must be made in the file `config.cfg.owr`.
|
||||
All possible settings can be seen in the default configuration file `config.cfg`.
|
||||
|
||||
|
||||
## Admin manual
|
||||
This guide applies to all admins. Here are briefly explained the administative possibilities.
|
||||
|
||||
|
||||
## User manual
|
||||
This guide applies to users or admins. Here are briefly explained the normal possibilities of the software.
|
||||
|
||||
|
||||
## FAQ
|
||||
|
||||
### How do I start with the software?
|
||||
You should read the `Installation manual` section. There everything is explained briefly. Just work through everything from top to bottom :)
|
1169
lxmf_cmd/lxmf_cmd.py
Executable file
0
lxmf_distribution_group/CHANGELOG.md
Normal file
685
lxmf_distribution_group/README.md
Normal file
@ -0,0 +1,685 @@
|
||||
# lxmf_distribution_group
|
||||
This program provides an email like distribution group. It will distribute incoming LXMF messages to multiple recipients. Since this program acts as a normal LXMF endpoint, all compatible chat applications can be used. In addition to simple messaging, there is a simple command-based user interface. Where all relevant actions for daily administration can be performed. The basic configuration is done in the configuration files. There are various options to adapt the entire behavior of the group to personal needs. This distribution group is much more than a standard email distribution group. It emulates advanced group functions with automatic notifications etc. Different user permissions can be defined. For each user type, the range of functions can be defined individually. The normal users have only small rights. While a moderator or admin can perform everything necessary by simple commands. Once the basic configuration is done, everything else can be done by LXMF messages as commands.
|
||||
|
||||
For more information, see the configuration options (at the end of the program files). Everything else is briefly documented there. After the first start this configuration will be created as default config in the corresponding file.
|
||||
|
||||
|
||||
### Features
|
||||
- Compatible with all LXMF applications (NomadNet, Sideband, ...)
|
||||
- Server/Node based message routing and processing
|
||||
- Direct or propagated message delivery (receive/send)
|
||||
- Simple group functions (As in other messenger apps)
|
||||
- User authorization and permissions
|
||||
- Different user types with different permissions
|
||||
- Automatic or manual group joining
|
||||
- Text based interface to display advanced functions or infos
|
||||
- Cluster of several groups (communication between groups with different levels)
|
||||
- Automatic negotiation of the clusters
|
||||
- Statistics at cluster, group and user level
|
||||
- Easy configuration within readable config files
|
||||
- Various admin commands for the daily tasks to be controlled via LXMF messages
|
||||
- Group description, rules and pinned messages
|
||||
- Optional enableable waiting room for new members before joining the group
|
||||
- Multiple language support (English & German are predifined)
|
||||
|
||||
|
||||
## Examples of use
|
||||
|
||||
### Local self-sufficient group
|
||||
In a small group of people, this group software can be hosted on a centrally located node. This then allows users to communicate with each other via this group.
|
||||
|
||||
### Multiple local self-sufficient group
|
||||
On the same node/server several groups can be operated independently of each other. How this works is described below in the installation instructions.
|
||||
|
||||
### Networking groups as a cluster
|
||||
It is possible to connect several locally independent groups to a cluster. This makes it possible to send messages from one group to another.
|
||||
|
||||
### Hierarchical cluster groups over widely spread areas
|
||||
A group cluster can be built in several levels. A group can be labeled with several names according to the naming of the levels.
|
||||
This makes it possible, for example to send a messages to several groups at the same time. So you could define the cluster names as follows. `Country/Region/City`
|
||||
With this it is possible to contact all groups of a certain country or region.
|
||||
|
||||
### General info how the messages are transported
|
||||
All messages between client<->group-server and group-server<->group-server are transported as single 1:1 messages in the LXMF/Reticulum network.
|
||||
Accordingly, encryption takes place between these end points.
|
||||
If a direct delivery of the message does not work, it is sent to a propagation node. There it is stored temporarily and can be retrieved by the client later.
|
||||
|
||||
As these are normal LXMF messages, any LXMF capable application can be used to communicate with the group.
|
||||
|
||||
When a message is sent to a multi-level (hierarchical) cluster. A 1:1 connection is always established from the source to each target group in this cluster level.
|
||||
|
||||
There is no central server for communication between the individual groups. This offers the advantage that all groups work autonomously. A failure of a group only affects this one local group.
|
||||
|
||||
|
||||
## Current Status
|
||||
It should currently be considered beta software. All core features are implemented and functioning, but additions will probably occur as real-world use is explored. There will be bugs.
|
||||
The full documentation is not yet available. Due to lack of time I can also not say when this will be further processed.
|
||||
|
||||
|
||||
## Development Roadmap
|
||||
- Planned, but not yet scheduled
|
||||
- Parameters for backup/restore configuration and data
|
||||
- Parameters for backup/restore identity
|
||||
- Cluster bridges/repeater
|
||||
- Different message priorities
|
||||
- Fallback solution: Master/Slave
|
||||
- Centralized user/group authorization
|
||||
- Internal queue with prioritization
|
||||
- More intelligent messages sending
|
||||
- Command to display the send status of the last message
|
||||
- Automatic send confirmation
|
||||
- Complete documentation
|
||||
|
||||
|
||||
## Screenshots / Usage examples
|
||||
<img src="../docs/screenshots/lxmf_distribution_group_01.png" width="200px"><img src="../docs/screenshots/lxmf_distribution_group_02.png" width="200px"><img src="../docs/screenshots/lxmf_distribution_group_03.png" width="200px"><img src="../docs/screenshots/lxmf_distribution_group_04.png" width="200px"><img src="../docs/screenshots/lxmf_distribution_group_05.png" width="200px"><img src="../docs/screenshots/lxmf_distribution_group_06.png" width="200px"><img src="../docs/screenshots/lxmf_distribution_group_07.png" width="200px"><img src="../docs/screenshots/lxmf_distribution_group_08.png" width="200px">
|
||||
|
||||
|
||||
## Installation manual
|
||||
|
||||
### Install:
|
||||
- Install all required prerequisites. (Default Reticulum installation. Only necessary if reticulum is not yet installed.)
|
||||
```bash
|
||||
apt update
|
||||
apt upgrade
|
||||
|
||||
apt install python3-pip
|
||||
|
||||
pip install pip --upgrade
|
||||
reboot
|
||||
|
||||
pip3 install rns
|
||||
pip3 install pyserial netifaces
|
||||
|
||||
pip3 install lxmf
|
||||
```
|
||||
- Change the Reticulum configuration to suit your needs and use-case.
|
||||
```bash
|
||||
nano /.reticulum/config
|
||||
```
|
||||
- Download the [file](lxmf_distribution_group.py) from this repository.
|
||||
```bash
|
||||
wget https://raw.githubusercontent.com/SebastianObi/LXMF-Tools/main/lxmf_distribution_group/lxmf_distribution_group.py
|
||||
```
|
||||
- Make it executable with the following command
|
||||
```bash
|
||||
chmod +x lxmf_distribution_group.py
|
||||
```
|
||||
|
||||
### Start:
|
||||
- Start it
|
||||
```bash
|
||||
./lxmf_distribution_group.py
|
||||
```
|
||||
- After the first start edit the configuration file to suit your needs and use-case. The file location is displayed.
|
||||
- Example minimal configuration (override of the default config `config.cfg`). These are the most relevant settings that need to be adjusted. All other settings are in `config.cfg`
|
||||
```bash
|
||||
nano /root/.lxmf_distribution_group/config.cfg.owr
|
||||
```
|
||||
```bash
|
||||
# This is the user configuration file to override the default configuration file.
|
||||
# All settings made here have precedence.
|
||||
# This file can be used to clearly summarize all settings that deviate from the default.
|
||||
# This also has the advantage that all changed settings can be kept when updating the program.
|
||||
|
||||
|
||||
#### Main program settings ####
|
||||
[main]
|
||||
|
||||
# Default language.
|
||||
lng = en # en/de
|
||||
|
||||
|
||||
#### LXMF connection settings ####
|
||||
[lxmf]
|
||||
|
||||
# The name will be visible to other peers
|
||||
# on the network, and included in announces.
|
||||
# It is also used in the group description/info.
|
||||
display_name = Distribution Group
|
||||
|
||||
# Propagation node address/hash.
|
||||
propagation_node = ca2762fe5283873719aececfb9e18835
|
||||
|
||||
# Try to deliver a message via the LXMF propagation network,
|
||||
# if a direct delivery to the recipient is not possible.
|
||||
try_propagation_on_fail = Yes
|
||||
|
||||
|
||||
#### Cluster settings ####
|
||||
[cluster]
|
||||
|
||||
# Enable/Disable this functionality.
|
||||
enabled = True
|
||||
|
||||
# To use several completely separate clusters/groups,
|
||||
# an individual name and type can be assigned here.
|
||||
name = grp
|
||||
type = cluster
|
||||
|
||||
# Slash-separated list with the names of this cluster.
|
||||
# No spaces are allowed in the name.
|
||||
# All send messages that match the name will be received.
|
||||
# The last name is the main name of this group
|
||||
# and is used as source for send messages.
|
||||
display_name = County/Region/City
|
||||
|
||||
|
||||
#### Statistic/Counter settings ####
|
||||
[statistic]
|
||||
|
||||
# Enable/Disable this functionality.
|
||||
enabled = True
|
||||
```
|
||||
- Start it again. Finished!
|
||||
```bash
|
||||
./lxmf_distribution_group.py
|
||||
```
|
||||
|
||||
|
||||
### Run as a system service/deamon:
|
||||
- Create a service file.
|
||||
```bash
|
||||
nano /etc/systemd/system/lxmf_distribution_group.service
|
||||
```
|
||||
- Copy and edit the following content to your own needs.
|
||||
```bash
|
||||
[Unit]
|
||||
Description=lxmf_distribution_group.py Daemon
|
||||
After=multi-user.target
|
||||
[Service]
|
||||
# ExecStartPre=/bin/sleep 10
|
||||
Type=simple
|
||||
Restart=always
|
||||
RestartSec=3
|
||||
User=root
|
||||
ExecStart=/root/lxmf_distribution_group.py
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
- Enable the service.
|
||||
```bash
|
||||
systemctl enable lxmf_distribution_group
|
||||
```
|
||||
- Start the service.
|
||||
```bash
|
||||
systemctl start lxmf_distribution_group
|
||||
```
|
||||
|
||||
|
||||
### Start/Stop service:
|
||||
```bash
|
||||
systemctl start lxmf_distribution_group
|
||||
systemctl stop lxmf_distribution_group
|
||||
```
|
||||
|
||||
|
||||
### Enable/Disable service:
|
||||
```bash
|
||||
systemctl enable lxmf_distribution_group
|
||||
systemctl disable lxmf_distribution_group
|
||||
```
|
||||
|
||||
|
||||
### Run several instances (To copy the same application):
|
||||
- Run the program with a different configuration path.
|
||||
```bash
|
||||
./lxmf_distribution_group.py -p /root/.lxmf_distribution_group_2nd
|
||||
./lxmf_distribution_group.py -p /root/.lxmf_distribution_group_3nd
|
||||
```
|
||||
- After the first start edit the configuration file to suit your needs and use-case. The file location is displayed.
|
||||
|
||||
|
||||
### First usage:
|
||||
- With a manual start via the console, the own group LXMF address is displayed:
|
||||
```
|
||||
[] ...............................................................................
|
||||
[] LXMF - Address: <801f48d54bc71cb3e0886944832aaf8d>
|
||||
[] ...............................................................................`
|
||||
```
|
||||
- This address is also annouced at startup in the default setting.
|
||||
- If auto add user is active (default) you can simply send a first message via Sideband/NomadNet to this address. After that you are a member of the group and can use the functions.
|
||||
- Alternatively, the users can also be entered manually in the `data.cfg` file. It is necessary to add an admin user here to use all commands via LXMF messages!
|
||||
- Now the group can be used.
|
||||
|
||||
|
||||
### Startup parameters:
|
||||
```bash
|
||||
usage: lxmf_distribution_group.py [-h] [-p PATH] [-pr PATH_RNS] [-pl PATH_LOG] [-l LOGLEVEL] [-s] [--exampleconfig] [--exampleconfigoverride] [--exampledata]
|
||||
|
||||
LXMF Distribution Group - Server-Side group functions for LXMF based apps
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
-p PATH, --path PATH Path to alternative config directory
|
||||
-pr PATH_RNS, --path_rns PATH_RNS
|
||||
Path to alternative Reticulum config directory
|
||||
-pl PATH_LOG, --path_log PATH_LOG
|
||||
Path to alternative log directory
|
||||
-l LOGLEVEL, --loglevel LOGLEVEL
|
||||
-s, --service Running as a service and should log to file
|
||||
--exampleconfig Print verbose configuration example to stdout and exit
|
||||
--exampleconfigoverride
|
||||
Print verbose configuration example to stdout and exit
|
||||
--exampledata Print verbose configuration example to stdout and exit
|
||||
```
|
||||
|
||||
|
||||
### Config/data files:
|
||||
- config.cfg
|
||||
|
||||
This is the default config file.
|
||||
|
||||
- config.cfg.owr
|
||||
|
||||
This is the user configuration file to override the default configuration file.
|
||||
All settings made here have precedence.
|
||||
This file can be used to clearly summarize all settings that deviate from the default.
|
||||
This also has the advantage that all changed settings can be kept when updating the program.
|
||||
|
||||
- data.cfg
|
||||
|
||||
This is the data file. It is automatically created and saved/overwritten.
|
||||
It contains data managed by the software itself.
|
||||
If manual adjustments are made here, the program must be shut down first!
|
||||
|
||||
|
||||
## Configuration manual (Examples)
|
||||
The configurations shown here are only a part of the total configuration.
|
||||
It only serves to show the configuration that is necessary and adapted for the respective function.
|
||||
All configurations must be made in the file `config.cfg.owr`.
|
||||
All possible settings can be seen in the default configuration file `config.cfg`.
|
||||
|
||||
|
||||
### Cluster:
|
||||
This example shows the configuration for a cluster with 2 groups. This allows communication between both groups.
|
||||
It is possible to write directly to each group or to the higher level which then includes both groups.
|
||||
|
||||
- Group #1 `config.cfg.owr`
|
||||
```
|
||||
[lxmf]
|
||||
display_name = Group Test 1
|
||||
[cluster]
|
||||
enabled = True
|
||||
name = test
|
||||
type = cluster
|
||||
display_name = Germany/NRW/Düsseldorf
|
||||
```
|
||||
|
||||
- Group #1 `data.cfg`
|
||||
```
|
||||
[main]
|
||||
enabled_cluster = True
|
||||
auto_add_cluster = True
|
||||
```
|
||||
|
||||
- Group #2 `config.cfg.owr`
|
||||
```
|
||||
[lxmf]
|
||||
display_name = Group Test 2
|
||||
[cluster]
|
||||
enabled = True
|
||||
name = test
|
||||
type = cluster
|
||||
display_name = Germany/Bayern/München
|
||||
```
|
||||
|
||||
- Group #2 `data.cfg`
|
||||
```
|
||||
[main]
|
||||
enabled_cluster = True
|
||||
auto_add_cluster = True
|
||||
```
|
||||
|
||||
|
||||
### 2 independent cluster:
|
||||
This example shows the configuration for 2 separate clusters.
|
||||
This makes it possible to operate several clusters in parallel via the same communication network.
|
||||
It is important to configure the `name` and `type` differently.
|
||||
|
||||
- Cluster #1 - Group #1 `config.cfg.owr`
|
||||
```
|
||||
[lxmf]
|
||||
display_name = Group Test 1
|
||||
[cluster]
|
||||
enabled = True
|
||||
name = test1
|
||||
type = cluster
|
||||
display_name = Germany/NRW/Düsseldorf
|
||||
```
|
||||
|
||||
- Cluster #1 - Group #1 `data.cfg`
|
||||
```
|
||||
[main]
|
||||
enabled_cluster = True
|
||||
auto_add_cluster = True
|
||||
```
|
||||
|
||||
- Cluster #2 - Group #1 `config.cfg.owr`
|
||||
```
|
||||
[lxmf]
|
||||
display_name = Group Test 1
|
||||
[cluster]
|
||||
enabled = True
|
||||
name = test2
|
||||
type = cluster
|
||||
display_name = Germany/NRW/Düsseldorf
|
||||
```
|
||||
|
||||
- Cluster #2 - Group #1 `data.cfg`
|
||||
```
|
||||
[main]
|
||||
enabled_cluster = True
|
||||
auto_add_cluster = True
|
||||
```
|
||||
|
||||
|
||||
### Members/Clusters:
|
||||
Normally all data here (`data.cfg`) is created automatically by the software. Based on automatic creation of new users/clusters or executed commands for administration.
|
||||
Here are a few examples of how the content can look. Of course, the file can also be edited manually. This is necessary if an auto add is disabled.
|
||||
Please do not forget to close the program first!
|
||||
|
||||
- Group #1 `data.cfg`
|
||||
```
|
||||
[user]
|
||||
04652a820cc69d47940ce39050c455a6 = Test User 1
|
||||
|
||||
[cluster]
|
||||
d1b551e1b89fff5a4a6f2aaff2464971 = Germany/Bayern/München
|
||||
```
|
||||
|
||||
- Group #2 `data.cfg`
|
||||
```
|
||||
[user]
|
||||
18201a931dd69d47940ce39050c487c9 = Test User 1
|
||||
|
||||
[cluster]
|
||||
801f48d54bc71cb3e0886944832aaf8d = Germany/NRW/Düsseldorf
|
||||
```
|
||||
|
||||
|
||||
### Waiting room for new members:
|
||||
This example shows the configuration for a waiting room for new members.
|
||||
When an unknown user joins the group by the first message to the group, he is added to the "wait" type.
|
||||
There he will be in a kind of waiting room where no messages can be written and received.
|
||||
An admin or moderator can then allow or disallow this user.
|
||||
|
||||
The configuration shows only the minimum necessary part for this functionality. Of course, further rights can be assigned to the users.
|
||||
|
||||
- `config.cfg.owr`
|
||||
```
|
||||
[rights]
|
||||
admin = interface,receive_join,allow,deny
|
||||
mod = interface,receive_join,allow,deny
|
||||
wait =
|
||||
|
||||
[interface_messages]
|
||||
auto_add_wait = Welcome to the group "!display_name!"!!n!!n!You still need to be allowed to join. You will be notified automatically.
|
||||
auto_add_wait-de = Willkommen in der Gruppe "!display_name!"!!n!!n!Der Beitritt muss ihnen noch erlaubt werden. Sie werden darüber automatisch benachrichtigt.
|
||||
|
||||
allow_user = You have been allowed to join the group "!display_name!"!!n!!n!!description!!n!!n!The messages sent here are distributed to all group members.!n!!n!For help enter /?!n!!n!To read the group rules use the command /rules!n!!n!Please assign a nickname with the command /name
|
||||
allow_user-de = Sie wurden erlaubt der Gruppe "!display_name!" beizutreten!!n!!n!!description!!n!!n!Die hier gesendeten Nachrichten werden an alle Gruppenmitglieder verteilt.!n!!n!Für Hilfe geben Sie /? ein.!n!!n!Um die Gruppenregeln zu lesen verwenden Sie den Befehl /rules!n!!n!Bitte vergeben Sie einen Nickname mit dem Befehl /name
|
||||
|
||||
deny_user = You have been denied to join the group "!display_name!"!
|
||||
deny_user-de = Ihnen wurde der Beitritt in die Gruppe "!display_name!" abgelehnt!
|
||||
|
||||
member_join = !source_name! <!source_address!> joins the waiting room and must be allowed to join the group.
|
||||
member_join-de = !source_name! <!source_address!> betritt den Warteraum und muss zur Gruppe zugelassen werden.
|
||||
```
|
||||
|
||||
- `data.cfg`
|
||||
```
|
||||
[main]
|
||||
auto_add_user = True
|
||||
auto_add_user_type = wait
|
||||
allow_user = True
|
||||
allow_user_type = user
|
||||
deny_user = True
|
||||
deny_user_type = block_wait
|
||||
```
|
||||
|
||||
|
||||
## Admin manual
|
||||
This guide applies to all admins. Here are briefly explained the administative possibilities.
|
||||
|
||||
An administartor has correspondingly higher permissions and more commands are available. In general, the permissions can be freely defined. All users/admins etc. can also generally have the same permissions.
|
||||
|
||||
|
||||
### Activate/deactivate functions:
|
||||
The following functions can be adjusted accordingly by command.
|
||||
|
||||
`/enable_local <true/false>` = Local message routing
|
||||
|
||||
`/enable_cluster <true/false>` = Cluster message routing
|
||||
|
||||
`/auto_add_user <true/false>` = Add unknown user functionality
|
||||
|
||||
`/auto_add_cluster <true/false>` = Add unknown cluster functionality
|
||||
|
||||
|
||||
### Change values:
|
||||
`/description <description>` = Change description
|
||||
|
||||
`/rules <description>` = Change rules
|
||||
|
||||
|
||||
### Send a manual announce of the group and cluster:
|
||||
`/announce`
|
||||
|
||||
|
||||
### Manage users (display of existing users):
|
||||
`/show or /list`
|
||||
|
||||
`/show or /list <admin/mod/user/guest>`
|
||||
|
||||
`/search <nickname/user_address>`
|
||||
|
||||
|
||||
### Manage users (invite):
|
||||
Additional users can be invited, this can be done with the command `/invite <user_address>`.
|
||||
Then the user gets a welcome message and enters the group.
|
||||
|
||||
|
||||
### Manage users (allow/deny):
|
||||
If the waiting room is activated, the users can be administered with the following 2 commands.
|
||||
|
||||
`/allow <user_address>`
|
||||
|
||||
`/deny <user_address>`
|
||||
|
||||
|
||||
### Manage users (add/delete/move):
|
||||
The following commands can be used to administrate the users.
|
||||
Only in case of an invite a welcome message will be sent to the user. Users added here will not get a notification and have to start the first conversation with the group themselves. Or get a message sent directly.
|
||||
|
||||
`/add <admin/mod/user/guest> <user_address> <user_name>`
|
||||
|
||||
`/del or /rm <admin/mod/user/guest> <user_address>`
|
||||
|
||||
`/del or /rm <user_address>`
|
||||
|
||||
`/move <admin/mod/user/guest> <user_address>`
|
||||
|
||||
|
||||
### Manage users (kick/block/unblock):
|
||||
The following commands can be used to remove/enable the users.
|
||||
|
||||
`/kick <user_address>`
|
||||
|
||||
`/block <user_address>`
|
||||
|
||||
`/unblock <user_address>`
|
||||
|
||||
|
||||
### Save data:
|
||||
If an automatic save is set in the config nothing has to be done here. If not or additionally the data can be saved with the following command.
|
||||
|
||||
`/save`
|
||||
|
||||
|
||||
### Help:
|
||||
To display the help and all available commands the following commands can be used. `/help` or `/?`
|
||||
|
||||
|
||||
### Examples of possible commands:
|
||||
```
|
||||
/help or /? = Shows this help
|
||||
/leave or /part = Leave group
|
||||
/name = Show current nickname
|
||||
/nick = Show current nickname
|
||||
/name <your nickname> = Change/Define nickname
|
||||
/nick <your nickname> = Change/Define nickname
|
||||
/address = Dislay address info
|
||||
/info = Show group info
|
||||
/description = Show current description
|
||||
/rules = Show current rules
|
||||
/version = Show version info
|
||||
/groups or /cluster = Show all groups/clusters
|
||||
/groups <name> = Searches for a group/cluster by name
|
||||
/members or /names or /who = Show all group members
|
||||
/admins = Show group admins
|
||||
/moderators or /mods = Show group moderators
|
||||
/users = Show group users
|
||||
/guests = Show group guests
|
||||
/search <nickname/user_address> = Searches for a user by nickname or address
|
||||
/whois <nickname/user_address> = Searches for a user by nickname or address
|
||||
/activitys = Show user activitys
|
||||
/statistic or /stat = Show group statistic
|
||||
/status = Show status
|
||||
/delivery or /message = Show delivery status of last message
|
||||
/enable_local <true/false> = Local message routing
|
||||
/enable_cluster <true/false> = Cluster message routing
|
||||
/auto_add_user <true/false> = Add unknown user functionality
|
||||
/auto_add_user_type <admin/mod/user/guest>
|
||||
/auto_add_cluster <true/false> = Add unknown cluster functionality
|
||||
/invite_user <true/false> = Invite functionality
|
||||
/invite_user_type <admin/mod/user/guest>
|
||||
/description <description> = Change description
|
||||
/rules <description> = Change rules
|
||||
/announce = Send announce
|
||||
/sync = Synchronize messages with propagation node
|
||||
/show run = Show current configuration
|
||||
/show or /list
|
||||
/show or /list <admin/mod/user/guest>
|
||||
/add <admin/mod/user/guest> <user_address> <user_name>
|
||||
/del or /rm <admin/mod/user/guest> <user_address>
|
||||
/del or /rm <user_address>
|
||||
/move <admin/mod/user/guest> <user_address>
|
||||
/invite <user_address> = Invites user to group
|
||||
/kick <user_address> = Kicks user out of group
|
||||
/block <user_address> = Block user
|
||||
/ban <user_address> = Block user
|
||||
/unblock <user_address> = Unblock user
|
||||
/unban <user_address> = Unblock user
|
||||
/load or /read = Read the configuration/data
|
||||
/save or /wr = Saves the current configuration/data
|
||||
```
|
||||
|
||||
|
||||
## User manual
|
||||
This guide applies to users or admins. Here are briefly explained the normal possibilities of the software.
|
||||
|
||||
|
||||
### Start/Join the group:
|
||||
Just send a first message to the group address with Sideband/NomadNet.
|
||||
However, this is only possible if automatic joining of the group is activated.
|
||||
|
||||
|
||||
### Send local group message:
|
||||
Any normal text without `/` or `@` at the beginning will be interpreted as a normal message and sent to all local members accordingly. There is nothing else to consider here.
|
||||
|
||||
|
||||
### Send cluster message:
|
||||
It is possible to send messages to other groups which are part of the cluster. To do this you must first enter the command `@` followed by the target name of the group and then the normal message text.
|
||||
|
||||
For example `@Berlin Hello this is a test :)`. So this example would send this message to the Berlin group.
|
||||
|
||||
A group in a cluster can be arranged hierarchically in different levels. If the higher level is defined as the target, all groups below it receive this message.
|
||||
|
||||
For example, there are the following 3 groups `Germany/Berlin` and `Germany/Hamburg` and `Germany/Munich`. Accordingly, these can be written to directly or a higher level.
|
||||
|
||||
With the command `@Germany ` all 3 groups are now accessible. With the command `@Munich ` only this one group is accessible.
|
||||
|
||||
|
||||
### Pin message (local group):
|
||||
It is possible to pin local group messages permanently. This will then sent to all members. Additionally, all pinned messages can be displayed later.
|
||||
|
||||
This feature is useful to give new members access to important news from the past.
|
||||
|
||||
`/pin` = Display all pinned messages
|
||||
|
||||
`/pin <message text>` = Pin a new message
|
||||
|
||||
`/unpin <#id>` = Remove a pinned message
|
||||
|
||||
|
||||
### Pin message (cluster group):
|
||||
It is possible to pin cluster group messages permanently. This will then sent to all members. Additionally, all pinned messages can be displayed later.
|
||||
|
||||
This feature is useful to give new members access to important news from the past.
|
||||
|
||||
`@Group /pin <message text>` = Pin a new message
|
||||
|
||||
|
||||
### Interface/Commands:
|
||||
A simple text-message based user interface is integrated. Like you might know it from other chat programs. Every command must start with the delimiter `/`. Then followed by the command and any data. For example `/name My new nick name`.
|
||||
|
||||
If there is no `/` at the beginning this is a normal message and will be sent to the other members.
|
||||
|
||||
|
||||
### Help:
|
||||
To display the help and all available commands the following commands can be used. `/help` or `/?`
|
||||
|
||||
|
||||
### Leave the group:
|
||||
The `/leave` command is used to leave the group. Afterwards, the group can be re-entered (if it is allowed).
|
||||
|
||||
|
||||
### Invite users:
|
||||
If the admin has allowed additional users to be invited, this can be done with the command `/invite <user_address>`.
|
||||
Then the user gets a welcome message and enters the group.
|
||||
|
||||
|
||||
### Change nickname:
|
||||
The own nickname is either assigned automatically via received announce (after joining the group) or can be changed via the following command.
|
||||
|
||||
`/name <your new nnockname>` For example `/name Max Walker`.
|
||||
|
||||
|
||||
### Examples of possible commands:
|
||||
```
|
||||
/help or /? = Shows this help
|
||||
/leave or /part = Leave group
|
||||
/name = Show current nickname
|
||||
/nick = Show current nickname
|
||||
/name <your nickname> = Change/Define nickname
|
||||
/nick <your nickname> = Change/Define nickname
|
||||
/address = Dislay address info
|
||||
/info = Show group info
|
||||
/description = Show current description
|
||||
/rules = Show current rules
|
||||
/version = Show version info
|
||||
/groups or /cluster = Show all groups/clusters
|
||||
/groups <name> = Searches for a group/cluster by name
|
||||
/members or /names or /who = Show all group members
|
||||
/admins = Show group admins
|
||||
/moderators or /mods = Show group moderators
|
||||
/users = Show group users
|
||||
/guests = Show group guests
|
||||
/search <nickname/user_address> = Searches for a user by nickname or address
|
||||
/whois <nickname/user_address> = Searches for a user by nickname or address
|
||||
/activitys = Show user activitys
|
||||
/statistic or /stat = Show group statistic
|
||||
/delivery or /message = Show delivery status of last message
|
||||
/invite <user_address> = Invites user to group
|
||||
```
|
||||
|
||||
|
||||
## FAQ
|
||||
|
||||
### Why this server based group function and no direct groups in the client software?
|
||||
At the time of the development of these group functions there is no other possibility to use groups via Sideband/Nomadnet. Therefore this software was developed as a workaround.
|
||||
This software also offers other functions than a normal group broadcast.
|
||||
|
||||
### How do I start with the software?
|
||||
You should read the `Installation manual` section. There everything is explained briefly. Just work through everything from top to bottom :)
|
4676
lxmf_distribution_group/lxmf_distribution_group.py
Executable file
0
lxmf_distribution_group_minimal/CHANGELOG.md
Normal file
295
lxmf_distribution_group_minimal/README.md
Normal file
@ -0,0 +1,295 @@
|
||||
# lxmf_distribution_group_minimal
|
||||
This program is a minimalist version of the normal distribution group. The functionality is reduced to a minimum. Only sender and receiver users can be defined. Messages are then sent to the other users accordingly. There is no user interface or other notifications. Only the messages are distributed 1:1. The administration is done completely by the respective configuration files which are to be edited accordingly.
|
||||
|
||||
For more information, see the configuration options (at the end of the program files). Everything else is briefly documented there. After the first start this configuration will be created as default config in the corresponding file.
|
||||
|
||||
|
||||
### Features
|
||||
- Compatible with all LXMF applications (NomadNet, Sideband, ...)
|
||||
- Server/Node based message routing and processing
|
||||
- Direct or propagated message delivery (receive/send)
|
||||
- Easy distribution of incoming messages to recipients
|
||||
|
||||
|
||||
## Examples of use
|
||||
|
||||
### Local self-sufficient group
|
||||
In a small group of people, this group software can be hosted on a centrally located node. This then allows users to communicate with each other via this group.
|
||||
|
||||
### Multiple local self-sufficient group
|
||||
On the same node/server several groups can be operated independently of each other. How this works is described below in the installation instructions.
|
||||
|
||||
### General info how the messages are transported
|
||||
All messages between client<->group-server are transported as single 1:1 messages in the LXMF/Reticulum network.
|
||||
Accordingly, encryption takes place between these end points.
|
||||
If a direct delivery of the message does not work, it is sent to a propagation node. There it is stored temporarily and can be retrieved by the client later.
|
||||
|
||||
As these are normal LXMF messages, any LXMF capable application can be used to communicate with the group.
|
||||
|
||||
|
||||
## Current Status
|
||||
It should currently be considered beta software. All core features are implemented and functioning, but additions will probably occur as real-world use is explored. There will be bugs.
|
||||
The full documentation is not yet available. Due to lack of time I can also not say when this will be further processed.
|
||||
|
||||
|
||||
## Screenshots / Usage examples
|
||||
<img src="../docs/screenshots/lxmf_distribution_group_minimal_01.png" width="200px"><img src="../docs/screenshots/lxmf_distribution_group_minimal_02.png" width="200px"><img src="../docs/screenshots/lxmf_distribution_group_minimal_03.png" width="200px">
|
||||
|
||||
|
||||
## Installation manual
|
||||
|
||||
### Install:
|
||||
- Install all required prerequisites. (Default Reticulum installation. Only necessary if reticulum is not yet installed.)
|
||||
```bash
|
||||
apt update
|
||||
apt upgrade
|
||||
|
||||
apt install python3-pip
|
||||
|
||||
pip install pip --upgrade
|
||||
reboot
|
||||
|
||||
pip3 install rns
|
||||
pip3 install pyserial netifaces
|
||||
|
||||
pip3 install lxmf
|
||||
```
|
||||
- Change the Reticulum configuration to suit your needs and use-case.
|
||||
```bash
|
||||
nano /.reticulum/config
|
||||
```
|
||||
- Download the [file](lxmf_distribution_group_minimal.py) from this repository.
|
||||
```bash
|
||||
wget https://raw.githubusercontent.com/SebastianObi/LXMF-Tools/main/lxmf_distribution_group_minimal/lxmf_distribution_group_minimal.py
|
||||
```
|
||||
- Make it executable with the following command
|
||||
```bash
|
||||
chmod +x lxmf_distribution_group_minimal.py
|
||||
```
|
||||
|
||||
### Start:
|
||||
- Start it
|
||||
```bash
|
||||
./lxmf_distribution_group_minimal.py
|
||||
```
|
||||
- After the first start edit the configuration file to suit your needs and use-case. The file location is displayed.
|
||||
- Example minimal configuration (override of the default config `config.cfg`). These are the most relevant settings that need to be adjusted. All other settings are in `config.cfg`
|
||||
```bash
|
||||
nano /root/.lxmf_distribution_group_minimal/config.cfg.owr
|
||||
```
|
||||
```bash
|
||||
# This is the user configuration file to override the default configuration file.
|
||||
# All settings made here have precedence.
|
||||
# This file can be used to clearly summarize all settings that deviate from the default.
|
||||
# This also has the advantage that all changed settings can be kept when updating the program.
|
||||
|
||||
#### LXMF connection settings ####
|
||||
[lxmf]
|
||||
|
||||
# The name will be visible to other peers
|
||||
# on the network, and included in announces.
|
||||
# It is also used in the group description/info.
|
||||
display_name = Distribution Group
|
||||
|
||||
# Propagation node address/hash.
|
||||
propagation_node = ca2762fe5283873719aececfb9e18835
|
||||
|
||||
# Try to deliver a message via the LXMF propagation network,
|
||||
# if a direct delivery to the recipient is not possible.
|
||||
try_propagation_on_fail = Yes
|
||||
```
|
||||
- Start it again. Finished!
|
||||
```bash
|
||||
./lxmf_distribution_group_minimal.py
|
||||
```
|
||||
|
||||
|
||||
### Run as a system service/deamon:
|
||||
- Create a service file.
|
||||
```bash
|
||||
nano /etc/systemd/system/lxmf_distribution_group_minimal.service
|
||||
```
|
||||
- Copy and edit the following content to your own needs.
|
||||
```bash
|
||||
[Unit]
|
||||
Description=lxmf_distribution_group_minimal.py Daemon
|
||||
After=multi-user.target
|
||||
[Service]
|
||||
# ExecStartPre=/bin/sleep 10
|
||||
Type=simple
|
||||
Restart=always
|
||||
RestartSec=3
|
||||
User=root
|
||||
ExecStart=/root/lxmf_distribution_group_minimal.py
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
- Enable the service.
|
||||
```bash
|
||||
systemctl enable lxmf_distribution_group_minimal
|
||||
```
|
||||
- Start the service.
|
||||
```bash
|
||||
systemctl start lxmf_distribution_group_minimal
|
||||
```
|
||||
|
||||
|
||||
### Start/Stop service:
|
||||
```bash
|
||||
systemctl start lxmf_distribution_group_minimal
|
||||
systemctl stop lxmf_distribution_group_minimal
|
||||
```
|
||||
|
||||
|
||||
### Enable/Disable service:
|
||||
```bash
|
||||
systemctl enable lxmf_distribution_group_minimal
|
||||
systemctl disable lxmf_distribution_group_minimal
|
||||
```
|
||||
|
||||
|
||||
### Run several instances (To copy the same application):
|
||||
- Run the program with a different configuration path.
|
||||
```bash
|
||||
./lxmf_distribution_group_minimal.py -p /root/.lxmf_distribution_group_minimal_2nd
|
||||
./lxmf_distribution_group_minimal.py -p /root/.lxmf_distribution_group_minimal_3nd
|
||||
```
|
||||
- After the first start edit the configuration file to suit your needs and use-case. The file location is displayed.
|
||||
|
||||
|
||||
### First usage:
|
||||
- With a manual start via the console, the own group LXMF address is displayed:
|
||||
```
|
||||
[] ...............................................................................
|
||||
[] LXMF - Address: <801f48d54bc71cb3e0886944832aaf8d>
|
||||
[] ...............................................................................`
|
||||
```
|
||||
- This address is also annouced at startup in the default setting.
|
||||
- The users need to be entered manually in the `data.cfg` file.
|
||||
- Now the group can be used.
|
||||
|
||||
|
||||
### Startup parameters:
|
||||
```bash
|
||||
usage: lxmf_distribution_group_minimal.py [-h] [-p PATH] [-pr PATH_RNS] [-pl PATH_LOG] [-l LOGLEVEL] [-s] [--exampleconfig] [--exampleconfigoverride] [--exampledata]
|
||||
|
||||
LXMF Distribution Group - Server-Side group functions for LXMF based apps
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
-p PATH, --path PATH Path to alternative config directory
|
||||
-pr PATH_RNS, --path_rns PATH_RNS
|
||||
Path to alternative Reticulum config directory
|
||||
-pl PATH_LOG, --path_log PATH_LOG
|
||||
Path to alternative log directory
|
||||
-l LOGLEVEL, --loglevel LOGLEVEL
|
||||
-s, --service Running as a service and should log to file
|
||||
--exampleconfig Print verbose configuration example to stdout and exit
|
||||
--exampleconfigoverride
|
||||
Print verbose configuration example to stdout and exit
|
||||
--exampledata Print verbose configuration example to stdout and exit
|
||||
```
|
||||
|
||||
|
||||
### Config/data files:
|
||||
- config.cfg
|
||||
|
||||
This is the default config file.
|
||||
|
||||
- config.cfg.owr
|
||||
|
||||
This is the user configuration file to override the default configuration file.
|
||||
All settings made here have precedence.
|
||||
This file can be used to clearly summarize all settings that deviate from the default.
|
||||
This also has the advantage that all changed settings can be kept when updating the program.
|
||||
|
||||
- data.cfg
|
||||
|
||||
This is the data file.
|
||||
It contains the user data.
|
||||
|
||||
|
||||
## Configuration manual (Examples)
|
||||
The configurations shown here are only a part of the total configuration.
|
||||
It only serves to show the configuration that is necessary and adapted for the respective function.
|
||||
All configurations must be made in the file `config.cfg.owr`.
|
||||
All possible settings can be seen in the default configuration file `config.cfg`.
|
||||
|
||||
|
||||
### Members:
|
||||
All data here (`data.cfg`) contains the end users. The users must be maintained manually. There is no automatic joining to the group.
|
||||
Please do not forget to restart the program after a modification!
|
||||
|
||||
- Receive only and send only members `data.cfg`
|
||||
```
|
||||
[send]
|
||||
04652a820cc69d47940ce39050c455a6 = Test user with send only right 1
|
||||
|
||||
[receive]
|
||||
d1b551e1b89fff5a4a6f2aaff2464971 = Test user with receive only right 1
|
||||
801f48d54bc71cb3e0886944832aaf8d = Test user with receive only right 2
|
||||
|
||||
[receive_send]
|
||||
```
|
||||
|
||||
- Receive and send members (Anyone can communicate with anyone)`data.cfg`
|
||||
```
|
||||
[send]
|
||||
|
||||
[receive]
|
||||
|
||||
[receive_send]
|
||||
04652a820cc69d47940ce39050c455a6 = Test user 1
|
||||
d1b551e1b89fff5a4a6f2aaff2464971 = Test user 2
|
||||
801f48d54bc71cb3e0886944832aaf8d = Test user 3
|
||||
```
|
||||
|
||||
|
||||
## Admin manual
|
||||
This guide applies to all admins. Here are briefly explained the administative possibilities.
|
||||
|
||||
### Manage users:
|
||||
All users are maintained directly in the `data.cfg` file.
|
||||
There is no automatic joining to the group.
|
||||
Please do not forget to restart the program after a modification!
|
||||
|
||||
```
|
||||
# This is the data file. It is automatically created and saved/overwritten.
|
||||
# It contains data managed by the software itself.
|
||||
# If manual adjustments are made here, the program must be shut down first!
|
||||
|
||||
|
||||
#### User with send only rights ####
|
||||
[send]
|
||||
04652a820cc69d47940ce39050c455a6 = Test user 1
|
||||
|
||||
#### User with receive only rights ####
|
||||
[receive]
|
||||
d1b551e1b89fff5a4a6f2aaff2464971 = Test user 2
|
||||
|
||||
#### User with receive and send rights ####
|
||||
[receive_send]
|
||||
801f48d54bc71cb3e0886944832aaf8d = Test user 3
|
||||
```
|
||||
|
||||
|
||||
## User manual
|
||||
This guide applies to users or admins. Here are briefly explained the normal possibilities of the software.
|
||||
|
||||
|
||||
### Start/Join the group:
|
||||
The administrator must create new users manually.
|
||||
|
||||
|
||||
### Send message:
|
||||
Any text will be interpreted as a normal message and sent to all members accordingly. There is nothing else to consider here.
|
||||
|
||||
|
||||
## FAQ
|
||||
|
||||
### Why this server based group function and no direct groups in the client software?
|
||||
At the time of the development of these group functions there is no other possibility to use groups via Sideband/Nomadnet. Therefore this software was developed as a workaround.
|
||||
This software also offers other functions than a normal group broadcast.
|
||||
|
||||
### How do I start with the software?
|
||||
You should read the `Installation manual` section. There everything is explained briefly. Just work through everything from top to bottom :)
|
1297
lxmf_distribution_group_minimal/lxmf_distribution_group_minimal.py
Executable file
0
lxmf_echo/CHANGELOG.md
Normal file
197
lxmf_echo/README.md
Normal file
@ -0,0 +1,197 @@
|
||||
# lxmf_echo
|
||||
This program is a simple echo server. All received messages are sent back 1:1 as an answer. This can be used as a simple counterpart to test the chat functionality of applications.
|
||||
|
||||
For more information, see the configuration options (at the end of the program files). Everything else is briefly documented there. After the first start this configuration will be created as default config in the corresponding file.
|
||||
|
||||
|
||||
### Features
|
||||
- Compatible with all LXMF applications (NomadNet, Sideband, ...)
|
||||
|
||||
|
||||
## Examples of use
|
||||
|
||||
###
|
||||
|
||||
### General info how the messages are transported
|
||||
All messages between client<->server are transported as single 1:1 messages in the LXMF/Reticulum network.
|
||||
Accordingly, encryption takes place between these end points.
|
||||
If a direct delivery of the message does not work, it is sent to a propagation node. There it is stored temporarily and can be retrieved by the client later.
|
||||
|
||||
As these are normal LXMF messages, any LXMF capable application can be used to communicate with the group.
|
||||
|
||||
|
||||
## Current Status
|
||||
It should currently be considered beta software. All core features are implemented and functioning, but additions will probably occur as real-world use is explored. There will be bugs.
|
||||
The full documentation is not yet available. Due to lack of time I can also not say when this will be further processed.
|
||||
|
||||
|
||||
## Screenshots / Usage examples
|
||||
<img src="../docs/screenshots/lxmf_echo_01.png" width="200px">
|
||||
|
||||
|
||||
## Installation manual
|
||||
|
||||
### Install:
|
||||
- Install all required prerequisites. (Default Reticulum installation. Only necessary if reticulum is not yet installed.)
|
||||
```bash
|
||||
apt update
|
||||
apt upgrade
|
||||
|
||||
apt install python3-pip
|
||||
|
||||
pip install pip --upgrade
|
||||
reboot
|
||||
|
||||
pip3 install rns
|
||||
pip3 install pyserial netifaces
|
||||
|
||||
pip3 install lxmf
|
||||
```
|
||||
- Change the Reticulum configuration to suit your needs and use-case.
|
||||
```bash
|
||||
nano /.reticulum/config
|
||||
```
|
||||
- Download the [file](lxmf_echo.py) from this repository.
|
||||
```bash
|
||||
wget https://raw.githubusercontent.com/SebastianObi/LXMF-Tools/main/lxmf_echo/lxmf_echo.py
|
||||
```
|
||||
- Make it executable with the following command
|
||||
```bash
|
||||
chmod +x lxmf_echo.py
|
||||
```
|
||||
|
||||
### Start:
|
||||
- Start it
|
||||
```bash
|
||||
./lxmf_echo.py
|
||||
```
|
||||
- After the first start edit the configuration file to suit your needs and use-case. The file location is displayed.
|
||||
- Example minimal configuration (override of the default config `config.cfg`). These are the most relevant settings that need to be adjusted. All other settings are in `config.cfg`
|
||||
```bash
|
||||
nano /root/.lxmf_echo/config.cfg.owr
|
||||
```
|
||||
```bash
|
||||
```
|
||||
- Start it again. Finished!
|
||||
```bash
|
||||
./lxmf_echo.py
|
||||
```
|
||||
|
||||
|
||||
### Run as a system service/deamon:
|
||||
- Create a service file.
|
||||
```bash
|
||||
nano /etc/systemd/system/lxmf_echo.service
|
||||
```
|
||||
- Copy and edit the following content to your own needs.
|
||||
```bash
|
||||
[Unit]
|
||||
Description=lxmf_echo.py Daemon
|
||||
After=multi-user.target
|
||||
[Service]
|
||||
# ExecStartPre=/bin/sleep 10
|
||||
Type=simple
|
||||
Restart=always
|
||||
RestartSec=3
|
||||
User=root
|
||||
ExecStart=/root/lxmf_echo.py
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
- Enable the service.
|
||||
```bash
|
||||
systemctl enable lxmf_echo
|
||||
```
|
||||
- Start the service.
|
||||
```bash
|
||||
systemctl start lxmf_echo
|
||||
```
|
||||
|
||||
|
||||
### Start/Stop service:
|
||||
```bash
|
||||
systemctl start lxmf_echo
|
||||
systemctl stop lxmf_echo
|
||||
```
|
||||
|
||||
|
||||
### Enable/Disable service:
|
||||
```bash
|
||||
systemctl enable lxmf_echo
|
||||
systemctl disable lxmf_echo
|
||||
```
|
||||
|
||||
|
||||
### Run several instances (To copy the same application):
|
||||
- Run the program with a different configuration path.
|
||||
```bash
|
||||
./lxmf_echo.py -p /root/.lxmf_echo_2nd
|
||||
./lxmf_echo.py -p /root/.lxmf_echo_3nd
|
||||
```
|
||||
- After the first start edit the configuration file to suit your needs and use-case. The file location is displayed.
|
||||
|
||||
|
||||
### First usage:
|
||||
- With a manual start via the console, the own LXMF address is displayed:
|
||||
```
|
||||
[] ...............................................................................
|
||||
[] LXMF - Address: <801f48d54bc71cb3e0886944832aaf8d>
|
||||
[] ...............................................................................`
|
||||
```
|
||||
- This address is also annouced at startup in the default setting.
|
||||
- Now the software can be used.
|
||||
|
||||
|
||||
### Startup parameters:
|
||||
```bash
|
||||
usage: lxmf_echo.py [-h] [-p PATH] [-pr PATH_RNS] [-pl PATH_LOG] [-l LOGLEVEL] [-s] [--exampleconfig] [--exampleconfigoverride]
|
||||
|
||||
LXMF Echo -
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
-p PATH, --path PATH Path to alternative config directory
|
||||
-pr PATH_RNS, --path_rns PATH_RNS
|
||||
Path to alternative Reticulum config directory
|
||||
-pl PATH_LOG, --path_log PATH_LOG
|
||||
Path to alternative log directory
|
||||
-l LOGLEVEL, --loglevel LOGLEVEL
|
||||
-s, --service Running as a service and should log to file
|
||||
--exampleconfig Print verbose configuration example to stdout and exit
|
||||
--exampleconfigoverride
|
||||
Print verbose configuration example to stdout and exit
|
||||
```
|
||||
|
||||
|
||||
### Config/data files:
|
||||
- config.cfg
|
||||
|
||||
This is the default config file.
|
||||
|
||||
- config.cfg.owr
|
||||
|
||||
This is the user configuration file to override the default configuration file.
|
||||
All settings made here have precedence.
|
||||
This file can be used to clearly summarize all settings that deviate from the default.
|
||||
This also has the advantage that all changed settings can be kept when updating the program.
|
||||
|
||||
|
||||
## Configuration manual (Examples)
|
||||
The configurations shown here are only a part of the total configuration.
|
||||
It only serves to show the configuration that is necessary and adapted for the respective function.
|
||||
All configurations must be made in the file `config.cfg.owr`.
|
||||
All possible settings can be seen in the default configuration file `config.cfg`.
|
||||
|
||||
|
||||
## Admin manual
|
||||
This guide applies to all admins. Here are briefly explained the administative possibilities.
|
||||
|
||||
|
||||
## User manual
|
||||
This guide applies to users or admins. Here are briefly explained the normal possibilities of the software.
|
||||
|
||||
|
||||
## FAQ
|
||||
|
||||
### How do I start with the software?
|
||||
You should read the `Installation manual` section. There everything is explained briefly. Just work through everything from top to bottom :)
|
1126
lxmf_echo/lxmf_echo.py
Executable file
0
lxmf_ping/CHANGELOG.md
Normal file
100
lxmf_ping/README.md
Normal file
@ -0,0 +1,100 @@
|
||||
# lxmf_ping
|
||||
This program sends an adjustable number of LXMF messages to a destination. Then a simple statistic is created to check the success or failure of a single message. This tool can be useful to load the LXMF/Reticulum network with a defined load of messages. This can be used to simulate a certain amount of users.
|
||||
|
||||
For more information, see the configuration options (at the end of the program files). Everything else is briefly documented there. After the first start this configuration will be created as default config in the corresponding file.
|
||||
|
||||
|
||||
### Features
|
||||
- Compatible with all LXMF applications (NomadNet, Sideband, ...)
|
||||
|
||||
|
||||
## Examples of use
|
||||
|
||||
###
|
||||
|
||||
### General info how the messages are transported
|
||||
All messages between client<->server are transported as single 1:1 messages in the LXMF/Reticulum network.
|
||||
Accordingly, encryption takes place between these end points.
|
||||
If a direct delivery of the message does not work, it is sent to a propagation node. There it is stored temporarily and can be retrieved by the client later.
|
||||
|
||||
As these are normal LXMF messages, any LXMF capable application can be used to communicate with the group.
|
||||
|
||||
|
||||
## Current Status
|
||||
It should currently be considered beta software. All core features are implemented and functioning, but additions will probably occur as real-world use is explored. There will be bugs.
|
||||
The full documentation is not yet available. Due to lack of time I can also not say when this will be further processed.
|
||||
|
||||
|
||||
## Screenshots / Usage examples
|
||||
<img src="../docs/screenshots/lxmf_ping_01.png" width="1000px">
|
||||
|
||||
|
||||
## Installation manual
|
||||
|
||||
### Install:
|
||||
- Install all required prerequisites. (Default Reticulum installation. Only necessary if reticulum is not yet installed.)
|
||||
```bash
|
||||
apt update
|
||||
apt upgrade
|
||||
|
||||
apt install python3-pip
|
||||
|
||||
pip install pip --upgrade
|
||||
reboot
|
||||
|
||||
pip3 install rns
|
||||
pip3 install pyserial netifaces
|
||||
|
||||
pip3 install lxmf
|
||||
```
|
||||
- Change the Reticulum configuration to suit your needs and use-case.
|
||||
```bash
|
||||
nano /.reticulum/config
|
||||
```
|
||||
- Download the [file](lxmf_ping.py) from this repository.
|
||||
```bash
|
||||
wget https://raw.githubusercontent.com/SebastianObi/LXMF-Tools/main/lxmf_ping/lxmf_ping.py
|
||||
```
|
||||
- Make it executable with the following command
|
||||
```bash
|
||||
chmod +x lxmf_ping.py
|
||||
```
|
||||
|
||||
### Start:
|
||||
- Start it
|
||||
```bash
|
||||
./lxmf_ping.py
|
||||
```
|
||||
|
||||
|
||||
### Startup parameters:
|
||||
```bash
|
||||
usage: lxmf_ping.py [-h] [-p PATH] [-pr PATH_RNS] [-pl PATH_LOG] [-l LOGLEVEL] -d DEST [-t TIME] [-s SIZE] [-c COUNT] [-i INST]
|
||||
|
||||
LXMF Ping - Periodically sends pings/messages and evaluates the status
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
-p PATH, --path PATH Path to alternative config directory
|
||||
-pr PATH_RNS, --path_rns PATH_RNS
|
||||
Path to alternative Reticulum config directory
|
||||
-pl PATH_LOG, --path_log PATH_LOG
|
||||
Path to alternative log directory
|
||||
-l LOGLEVEL, --loglevel LOGLEVEL
|
||||
-d DEST, --dest DEST Single destination hash or ,-separated list with destination hashs or . for random destination
|
||||
-t TIME, --time TIME Time between messages in seconds
|
||||
-s SIZE, --size SIZE Size (lenght) of the message content
|
||||
-c COUNT, --count COUNT
|
||||
Maximum message send count (0=no end)
|
||||
-i INST, --inst INST Parallel instances (different sender addresses)
|
||||
```
|
||||
|
||||
|
||||
## User manual
|
||||
This guide applies to users or admins. Here are briefly explained the normal possibilities of the software.
|
||||
|
||||
|
||||
## FAQ
|
||||
|
||||
### How do I start with the software?
|
||||
You should read the `Installation manual` section. There everything is explained briefly. Just work through everything from top to bottom :)
|
782
lxmf_ping/lxmf_ping.py
Executable file
@ -0,0 +1,782 @@
|
||||
#!/usr/bin/env python3
|
||||
##############################################################################################################
|
||||
#
|
||||
# Copyright (c) 2022 Sebastian Obele / obele.eu
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
#
|
||||
# This software uses the following software-parts:
|
||||
# Reticulum, LXMF, NomadNet / Copyright (c) 2016-2022 Mark Qvist / unsigned.io / MIT License
|
||||
#
|
||||
##############################################################################################################
|
||||
|
||||
|
||||
##############################################################################################################
|
||||
# Include
|
||||
|
||||
|
||||
#### System ####
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
import argparse
|
||||
|
||||
#### JSON ####
|
||||
import json
|
||||
import pickle
|
||||
|
||||
#### String ####
|
||||
import string
|
||||
|
||||
#### Other ####
|
||||
import random
|
||||
import secrets
|
||||
|
||||
#### Process ####
|
||||
import signal
|
||||
import threading
|
||||
|
||||
#### Reticulum, LXMF ####
|
||||
# Install: pip3 install rns lxmf
|
||||
# Source: https://markqvist.github.io
|
||||
import RNS
|
||||
import LXMF
|
||||
import RNS.vendor.umsgpack as umsgpack
|
||||
|
||||
|
||||
##############################################################################################################
|
||||
# Globals
|
||||
|
||||
|
||||
#### Global Variables - Configuration ####
|
||||
NAME = "LXMF Ping"
|
||||
DESCRIPTION = "Periodically sends pings/messages and evaluates the status"
|
||||
VERSION = "0.0.1 (2022-10-21)"
|
||||
COPYRIGHT = "(c) 2022 Sebastian Obele / obele.eu"
|
||||
PATH = os.path.expanduser("~") + "/." + os.path.splitext(os.path.basename(__file__))[0]
|
||||
PATH_RNS = None
|
||||
|
||||
|
||||
|
||||
|
||||
#### Global Variables - System (Not changeable) ####
|
||||
DATA = None
|
||||
RNS_CONNECTION = None
|
||||
LXMF_CONNECTION = None
|
||||
|
||||
|
||||
##############################################################################################################
|
||||
# LXMF Class
|
||||
|
||||
|
||||
class lxmf_connection:
|
||||
message_received_callback = None
|
||||
message_notification_callback = None
|
||||
message_notification_success_callback = None
|
||||
message_notification_failed_callback = None
|
||||
|
||||
|
||||
def __init__(self, storage_path=None, identity_file="identity", identity=None, destination_name="lxmf", destination_type="delivery", display_name="", send_delay=0, desired_method="direct", propagation_node=None, try_propagation_on_fail=False, announce_startup=False, announce_startup_delay=0, announce_periodic=False, announce_periodic_interval=360, sync_startup=False, sync_startup_delay=0, sync_limit=8, sync_periodic=False, sync_periodic_interval=360):
|
||||
self.storage_path = storage_path
|
||||
|
||||
self.identity_file = identity_file
|
||||
|
||||
self.identity = identity
|
||||
|
||||
self.destination_name = destination_name
|
||||
self.destination_type = destination_type
|
||||
self.aspect_filter = self.destination_name + "." + self.destination_type
|
||||
|
||||
self.display_name = display_name
|
||||
|
||||
self.send_delay = int(send_delay)
|
||||
|
||||
if desired_method == "propagated" or desired_method == "PROPAGATED":
|
||||
self.desired_method_direct = False
|
||||
else:
|
||||
self.desired_method_direct = True
|
||||
self.propagation_node = propagation_node
|
||||
self.try_propagation_on_fail = try_propagation_on_fail
|
||||
|
||||
self.announce_startup = announce_startup
|
||||
self.announce_startup_delay = int(announce_startup_delay)
|
||||
|
||||
self.announce_periodic = announce_periodic
|
||||
self.announce_periodic_interval = int(announce_periodic_interval)
|
||||
|
||||
self.sync_startup = sync_startup
|
||||
self.sync_startup_delay = int(sync_startup_delay)
|
||||
self.sync_limit = int(sync_limit)
|
||||
self.sync_periodic = sync_periodic
|
||||
self.sync_periodic_interval = int(sync_periodic_interval)
|
||||
|
||||
if not os.path.isdir(self.storage_path):
|
||||
os.makedirs(self.storage_path)
|
||||
log("LXMF - Storage path was created", LOG_NOTICE)
|
||||
log("LXMF - Storage path: " + self.storage_path, LOG_INFO)
|
||||
|
||||
if self.identity:
|
||||
log("LXMF - Using existing Primary Identity %s" % (str(self.identity)))
|
||||
else:
|
||||
if not self.identity_file:
|
||||
self.identity_file = "identity"
|
||||
self.identity_path = self.storage_path + "/" + self.identity_file
|
||||
if os.path.isfile(self.identity_path):
|
||||
try:
|
||||
self.identity = RNS.Identity.from_file(self.identity_path)
|
||||
if self.identity != None:
|
||||
log("LXMF - Loaded Primary Identity %s from %s" % (str(self.identity), self.identity_path))
|
||||
else:
|
||||
log("LXMF - Could not load the Primary Identity from "+self.identity_path, LOG_ERROR)
|
||||
except Exception as e:
|
||||
log("LXMF - Could not load the Primary Identity from "+self.identity_path, LOG_ERROR)
|
||||
log("LXMF - The contained exception was: %s" % (str(e)), LOG_ERROR)
|
||||
else:
|
||||
try:
|
||||
log("LXMF - No Primary Identity file found, creating new...")
|
||||
self.identity = RNS.Identity()
|
||||
self.identity.to_file(self.identity_path)
|
||||
log("LXMF - Created new Primary Identity %s" % (str(self.identity)))
|
||||
except Exception as e:
|
||||
log("LXMF - Could not create and save a new Primary Identity", LOG_ERROR)
|
||||
log("LXMF - The contained exception was: %s" % (str(e)), LOG_ERROR)
|
||||
|
||||
self.message_router = LXMF.LXMRouter(identity=self.identity, storagepath=self.storage_path)
|
||||
|
||||
self.destination = self.message_router.register_delivery_identity(self.identity, display_name=self.display_name)
|
||||
|
||||
self.message_router.register_delivery_callback(self.process_lxmf_message_propagated)
|
||||
|
||||
if self.display_name == "":
|
||||
self.display_name = RNS.prettyhexrep(self.destination_hash())
|
||||
|
||||
self.destination.set_default_app_data(self.display_name.encode("utf-8"))
|
||||
|
||||
self.destination.set_proof_strategy(RNS.Destination.PROVE_ALL)
|
||||
|
||||
RNS.Identity.remember(packet_hash=None, destination_hash=self.destination.hash, public_key=self.identity.get_public_key(), app_data=None)
|
||||
|
||||
log("LXMF - Identity: " + str(self.identity), LOG_INFO)
|
||||
log("LXMF - Destination: " + str(self.destination), LOG_INFO)
|
||||
log("LXMF - Hash: " + RNS.prettyhexrep(self.destination_hash()), LOG_INFO)
|
||||
|
||||
self.destination.set_link_established_callback(self.client_connected)
|
||||
|
||||
self.autoselect_propagation_node()
|
||||
|
||||
if self.announce_startup or self.announce_periodic:
|
||||
self.announce(True)
|
||||
|
||||
if self.sync_startup or self.sync_periodic:
|
||||
self.sync(True)
|
||||
|
||||
|
||||
def register_announce_callback(self, handler_function):
|
||||
self.announce_callback = handler_function(self.aspect_filter)
|
||||
RNS.Transport.register_announce_handler(self.announce_callback)
|
||||
|
||||
|
||||
def register_message_received_callback(self, handler_function):
|
||||
self.message_received_callback = handler_function
|
||||
|
||||
|
||||
def register_message_notification_callback(self, handler_function):
|
||||
self.message_notification_callback = handler_function
|
||||
|
||||
|
||||
def register_message_notification_success_callback(self, handler_function):
|
||||
self.message_notification_success_callback = handler_function
|
||||
|
||||
|
||||
def register_message_notification_failed_callback(self, handler_function):
|
||||
self.message_notification_failed_callback = handler_function
|
||||
|
||||
|
||||
def destination_hash(self):
|
||||
return self.destination.hash
|
||||
|
||||
|
||||
def destination_hash_str(self):
|
||||
return RNS.hexrep(self.destination.hash, False)
|
||||
|
||||
|
||||
def destination_check(self, destination):
|
||||
if type(destination) is not bytes:
|
||||
if len(destination) == ((RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2)+2:
|
||||
destination = destination[1:-1]
|
||||
|
||||
if len(destination) != ((RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2):
|
||||
log("LXMF - Destination length is invalid", LOG_ERROR)
|
||||
return False
|
||||
|
||||
try:
|
||||
destination = bytes.fromhex(destination)
|
||||
except Exception as e:
|
||||
log("LXMF - Destination is invalid", LOG_ERROR)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def destination_correct(self, destination):
|
||||
if type(destination) is not bytes:
|
||||
if len(destination) == ((RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2)+2:
|
||||
destination = destination[1:-1]
|
||||
|
||||
if len(destination) != ((RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2):
|
||||
return ""
|
||||
|
||||
try:
|
||||
destination_bytes = bytes.fromhex(destination)
|
||||
return destination
|
||||
except Exception as e:
|
||||
return ""
|
||||
|
||||
return ""
|
||||
|
||||
|
||||
def send(self, destination, content="", title=None, fields=None, timestamp=None, app_data=""):
|
||||
if type(destination) is not bytes:
|
||||
if len(destination) == ((RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2)+2:
|
||||
destination = destination[1:-1]
|
||||
|
||||
if len(destination) != ((RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2):
|
||||
log("LXMF - Destination length is invalid", LOG_ERROR)
|
||||
return
|
||||
|
||||
try:
|
||||
destination = bytes.fromhex(destination)
|
||||
except Exception as e:
|
||||
log("LXMF - Destination is invalid", LOG_ERROR)
|
||||
return
|
||||
|
||||
destination_identity = RNS.Identity.recall(destination)
|
||||
destination = RNS.Destination(destination_identity, RNS.Destination.OUT, RNS.Destination.SINGLE, self.destination_name, self.destination_type)
|
||||
self.send_message(destination, self.destination, content, title, fields, timestamp, app_data)
|
||||
|
||||
|
||||
def send_message(self, destination, source, content="", title=None, fields=None, timestamp=None, app_data=""):
|
||||
if self.desired_method_direct:
|
||||
desired_method = LXMF.LXMessage.DIRECT
|
||||
else:
|
||||
desired_method = LXMF.LXMessage.PROPAGATED
|
||||
|
||||
message = LXMF.LXMessage(destination, source, content, title=title, desired_method=desired_method)
|
||||
|
||||
if fields is not None:
|
||||
message.fields = fields
|
||||
|
||||
if timestamp is not None:
|
||||
message.timestamp = timestamp
|
||||
|
||||
message.app_data = app_data
|
||||
|
||||
self.message_method(message)
|
||||
self.log_message(message, "LXMF - Message send")
|
||||
|
||||
message.register_delivery_callback(self.message_notification)
|
||||
message.register_failed_callback(self.message_notification)
|
||||
|
||||
if self.message_router.get_outbound_propagation_node() != None:
|
||||
message.try_propagation_on_fail = self.try_propagation_on_fail
|
||||
|
||||
try:
|
||||
self.message_router.handle_outbound(message)
|
||||
time.sleep(self.send_delay)
|
||||
except Exception as e:
|
||||
log("LXMF - Could not send message " + str(message), LOG_ERROR)
|
||||
log("LXMF - The contained exception was: " + str(e), LOG_ERROR)
|
||||
return
|
||||
|
||||
|
||||
def message_notification(self, message):
|
||||
self.message_method(message)
|
||||
|
||||
if self.message_notification_callback is not None:
|
||||
self.message_notification_callback(message)
|
||||
|
||||
if message.state == LXMF.LXMessage.FAILED and hasattr(message, "try_propagation_on_fail") and message.try_propagation_on_fail:
|
||||
self.log_message(message, "LXMF - Delivery receipt (failed) Retrying as propagated message")
|
||||
message.try_propagation_on_fail = None
|
||||
message.delivery_attempts = 0
|
||||
del message.next_delivery_attempt
|
||||
message.packed = None
|
||||
message.desired_method = LXMF.LXMessage.PROPAGATED
|
||||
self.message_router.handle_outbound(message)
|
||||
elif message.state == LXMF.LXMessage.FAILED:
|
||||
self.log_message(message, "LXMF - Delivery receipt (failed)")
|
||||
if self.message_notification_failed_callback is not None:
|
||||
self.message_notification_failed_callback(message)
|
||||
else:
|
||||
self.log_message(message, "LXMF - Delivery receipt (success)")
|
||||
if self.message_notification_success_callback is not None:
|
||||
self.message_notification_success_callback(message)
|
||||
|
||||
|
||||
def message_method(self, message):
|
||||
if message.desired_method == LXMF.LXMessage.DIRECT:
|
||||
message.desired_method_str = "direct"
|
||||
elif message.desired_method == LXMF.LXMessage.PROPAGATED:
|
||||
message.desired_method_str = "propagated"
|
||||
|
||||
|
||||
def announce(self, initial=False):
|
||||
announce_timer = None
|
||||
|
||||
if self.announce_periodic and self.announce_periodic_interval > 0:
|
||||
announce_timer = threading.Timer(self.announce_periodic_interval*60, self.announce)
|
||||
announce_timer.daemon = True
|
||||
announce_timer.start()
|
||||
|
||||
if initial:
|
||||
if self.announce_startup:
|
||||
if self.announce_startup_delay > 0:
|
||||
if announce_timer is not None:
|
||||
announce_timer.cancel()
|
||||
announce_timer = threading.Timer(self.announce_startup_delay, self.announce)
|
||||
announce_timer.daemon = True
|
||||
announce_timer.start()
|
||||
else:
|
||||
self.announce_now()
|
||||
return
|
||||
|
||||
self.announce_now()
|
||||
|
||||
|
||||
def announce_now(self, app_data=None):
|
||||
if app_data:
|
||||
self.destination.announce(app_data.encode("utf-8"))
|
||||
log("LXMF - Announced: " + RNS.prettyhexrep(self.destination_hash()) + ":" + app_data, LOG_DEBUG)
|
||||
else:
|
||||
self.destination.announce()
|
||||
log("LXMF - Announced: " + RNS.prettyhexrep(self.destination_hash()) + ": " + self.display_name, LOG_DEBUG)
|
||||
|
||||
|
||||
def sync(self, initial=False):
|
||||
sync_timer = None
|
||||
|
||||
if self.sync_periodic and self.sync_periodic_interval > 0:
|
||||
sync_timer = threading.Timer(self.sync_periodic_interval*60, self.sync)
|
||||
sync_timer.daemon = True
|
||||
sync_timer.start()
|
||||
|
||||
if initial:
|
||||
if self.sync_startup:
|
||||
if self.sync_startup_delay > 0:
|
||||
if sync_timer is not None:
|
||||
sync_timer.cancel()
|
||||
sync_timer = threading.Timer(self.sync_startup_delay, self.sync)
|
||||
sync_timer.daemon = True
|
||||
sync_timer.start()
|
||||
else:
|
||||
self.sync_now(self.sync_limit)
|
||||
return
|
||||
|
||||
self.sync_now(self.sync_limit)
|
||||
|
||||
|
||||
def sync_now(self, limit=None):
|
||||
if self.message_router.get_outbound_propagation_node() is not None:
|
||||
if self.message_router.propagation_transfer_state == LXMF.LXMRouter.PR_IDLE or self.message_router.propagation_transfer_state == LXMF.LXMRouter.PR_COMPLETE:
|
||||
log("LXMF - Message sync requested from propagation node " + RNS.prettyhexrep(self.message_router.get_outbound_propagation_node()) + " for " + str(self.identity))
|
||||
self.message_router.request_messages_from_propagation_node(self.identity, max_messages = limit)
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def autoselect_propagation_node(self):
|
||||
if self.propagation_node is not None:
|
||||
if len(self.propagation_node) != ((RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2):
|
||||
log("LXMF - Propagation node length is invalid", LOG_ERROR)
|
||||
else:
|
||||
try:
|
||||
propagation_hash = bytes.fromhex(self.propagation_node)
|
||||
except Exception as e:
|
||||
log("LXMF - Propagation node is invalid", LOG_ERROR)
|
||||
return
|
||||
|
||||
node_identity = RNS.Identity.recall(propagation_hash)
|
||||
if node_identity != None:
|
||||
log("LXMF - Propagation node: " + RNS.prettyhexrep(propagation_hash), LOG_INFO)
|
||||
propagation_hash = RNS.Destination.hash_from_name_and_identity("lxmf.propagation", node_identity)
|
||||
self.message_router.set_outbound_propagation_node(propagation_hash)
|
||||
else:
|
||||
log("LXMF - Propagation node identity not known", LOG_ERROR)
|
||||
|
||||
|
||||
def client_connected(self, link):
|
||||
log("LXMF - Client connected " + str(link), LOG_EXTREME)
|
||||
link.set_resource_strategy(RNS.Link.ACCEPT_ALL)
|
||||
link.set_resource_concluded_callback(self.resource_concluded)
|
||||
link.set_packet_callback(self.packet_received)
|
||||
|
||||
|
||||
def packet_received(self, lxmf_bytes, packet):
|
||||
log("LXMF - Single packet delivered " + str(packet), LOG_EXTREME)
|
||||
self.process_lxmf_message_bytes(lxmf_bytes)
|
||||
|
||||
|
||||
def resource_concluded(self, resource):
|
||||
log("LXMF - Resource data transfer (multi packet) delivered " + str(resource.file), LOG_EXTREME)
|
||||
if resource.status == RNS.Resource.COMPLETE:
|
||||
lxmf_bytes = resource.data.read()
|
||||
self.process_lxmf_message_bytes(lxmf_bytes)
|
||||
else:
|
||||
log("LXMF - Received resource message is not complete", LOG_EXTREME)
|
||||
|
||||
|
||||
def process_lxmf_message_bytes(self, lxmf_bytes):
|
||||
try:
|
||||
message = LXMF.LXMessage.unpack_from_bytes(lxmf_bytes)
|
||||
except Exception as e:
|
||||
log("LXMF - Could not assemble LXMF message from received data", LOG_ERROR)
|
||||
log("LXMF - The contained exception was: " + str(e), LOG_ERROR)
|
||||
return
|
||||
|
||||
message.desired_method = LXMF.LXMessage.DIRECT
|
||||
|
||||
self.message_method(message)
|
||||
self.log_message(message, "LXMF - Message received")
|
||||
|
||||
if self.message_received_callback is not None:
|
||||
log("LXMF - Call to registered message received callback", LOG_DEBUG)
|
||||
self.message_received_callback(message)
|
||||
else:
|
||||
log("LXMF - No message received callback registered", LOG_DEBUG)
|
||||
|
||||
|
||||
def process_lxmf_message_propagated(self, message):
|
||||
message.desired_method = LXMF.LXMessage.PROPAGATED
|
||||
|
||||
self.message_method(message)
|
||||
self.log_message(message, "LXMF - Message received")
|
||||
|
||||
if self.message_received_callback is not None:
|
||||
log("LXMF - Call to registered message received callback", LOG_DEBUG)
|
||||
self.message_received_callback(message)
|
||||
else:
|
||||
log("LXMF - No message received callback registered", LOG_DEBUG)
|
||||
|
||||
|
||||
def log_message(self, message, message_tag="LXMF - Message log"):
|
||||
if message.signature_validated:
|
||||
signature_string = "Validated"
|
||||
else:
|
||||
if message.unverified_reason == LXMF.LXMessage.SIGNATURE_INVALID:
|
||||
signature_string = "Invalid signature"
|
||||
elif message.unverified_reason == LXMF.LXMessage.SOURCE_UNKNOWN:
|
||||
signature_string = "Cannot verify, source is unknown"
|
||||
else:
|
||||
signature_string = "Signature is invalid, reason undetermined"
|
||||
title = message.title.decode('utf-8')
|
||||
content = message.content.decode('utf-8')
|
||||
fields = message.fields
|
||||
log(message_tag + ":", LOG_DEBUG)
|
||||
log("- Date/Time: " + time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(message.timestamp)), LOG_DEBUG)
|
||||
log("- Title: " + title, LOG_DEBUG)
|
||||
log("- Content: " + content, LOG_DEBUG)
|
||||
log("- Fields: " + str(fields), LOG_DEBUG)
|
||||
log("- Size: " + str(len(title) + len(content) + len(title) + len(pickle.dumps(fields))) + " bytes", LOG_DEBUG)
|
||||
log("- Source: " + RNS.prettyhexrep(message.source_hash), LOG_DEBUG)
|
||||
log("- Destination: " + RNS.prettyhexrep(message.destination_hash), LOG_DEBUG)
|
||||
log("- Signature: " + signature_string, LOG_DEBUG)
|
||||
log("- Attempts: " + str(message.delivery_attempts), LOG_DEBUG)
|
||||
if hasattr(message, "desired_method_str"):
|
||||
log("- Method: " + message.desired_method_str + " (" + str(message.desired_method) + ")", LOG_DEBUG)
|
||||
else:
|
||||
log("- Method: " + str(message.desired_method), LOG_DEBUG)
|
||||
if hasattr(message, "app_data"):
|
||||
log("- App Data: " + message.app_data, LOG_DEBUG)
|
||||
|
||||
|
||||
##############################################################################################################
|
||||
# LXMF Functions
|
||||
|
||||
|
||||
#### LXMF - Success ####
|
||||
def lxmf_success(message):
|
||||
global DATA
|
||||
key = RNS.hexrep(message.destination_hash, False)
|
||||
if not key in DATA:
|
||||
key = "."
|
||||
if not key in DATA:
|
||||
return
|
||||
DATA[key]["count_success"] = DATA[key]["count_success"] + 1
|
||||
timestamp = round(float(time.time()) - float(message.timestamp), 4)
|
||||
if DATA[key]["time_min"] == 0 or DATA[key]["time_min"] > timestamp:
|
||||
DATA[key]["time_min"] = timestamp
|
||||
if DATA[key]["time_max"] == 0 or DATA[key]["time_max"] < timestamp:
|
||||
DATA[key]["time_max"] = timestamp
|
||||
DATA[key]["time"] = DATA[key]["time"] + timestamp
|
||||
DATA[key]["time_avg"] = round(DATA[key]["time"]/DATA[key]["count_success"], 4)
|
||||
count = str(message.content)
|
||||
if "#" in count:
|
||||
count = count.split("#", 1)[1]
|
||||
count = count.split(" ", 1)[0]
|
||||
else:
|
||||
count = ""
|
||||
print("Destination: " + str (key) + " | #: " + str(count) + " | Messages delivered: " + str(DATA[key]["count_success"]) + "/" + str(DATA[key]["count"]) + " (" + str(round(100/DATA[key]["count"]*DATA[key]["count_success"], 2)) + "%) | Time (min / max / avg): " + str(DATA[key]["time_min"]) + " / " + str(DATA[key]["time_max"]) + " / " + str(DATA[key]["time_avg"]) + " | Info: Success")
|
||||
|
||||
|
||||
|
||||
|
||||
#### LXMF - Failed ####
|
||||
def lxmf_failed(message):
|
||||
global DATA
|
||||
key = RNS.hexrep(message.destination_hash, False)
|
||||
if not key in DATA:
|
||||
key = "."
|
||||
if not key in DATA:
|
||||
return
|
||||
DATA[key]["count_failed"] = DATA[key]["count_failed"] + 1
|
||||
count = str(message.content)
|
||||
if "#" in count:
|
||||
count = count.split("#", 1)[1]
|
||||
count = count.split(" ", 1)[0]
|
||||
else:
|
||||
count = ""
|
||||
print("Destination: " + str (key) + " | #: " + str(count) + " | Messages delivered: " + str(DATA[key]["count_success"]) + "/" + str(DATA[key]["count"]) + " (" + str(round(100/DATA[key]["count"]*DATA[key]["count_success"], 2)) + "%) | Time (min / max / avg): " + str(DATA[key]["time_min"]) + " / " + str(DATA[key]["time_max"]) + " / " + str(DATA[key]["time_avg"]) + " | Info: Failed")
|
||||
|
||||
|
||||
##############################################################################################################
|
||||
# Value convert
|
||||
|
||||
|
||||
def val_to_bool(val):
|
||||
if val == "on" or val == "On" or val == "true" or val == "True" or val == "yes" or val == "Yes" or val == "1" or val == "open" or val == "opened" or val == "up":
|
||||
return True
|
||||
elif val == "off" or val == "Off" or val == "false" or val == "False" or val == "no" or val == "No" or val == "0" or val == "close" or val == "closed" or val == "down":
|
||||
return False
|
||||
elif val != "":
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
##############################################################################################################
|
||||
# Log
|
||||
|
||||
|
||||
LOG_FORCE = -1
|
||||
LOG_CRITICAL = 0
|
||||
LOG_ERROR = 1
|
||||
LOG_WARNING = 2
|
||||
LOG_NOTICE = 3
|
||||
LOG_INFO = 4
|
||||
LOG_VERBOSE = 5
|
||||
LOG_DEBUG = 6
|
||||
LOG_EXTREME = 7
|
||||
|
||||
LOG_LEVEL = LOG_NOTICE
|
||||
LOG_LEVEL_SERVICE = LOG_NOTICE
|
||||
LOG_TIMEFMT = "%Y-%m-%d %H:%M:%S"
|
||||
LOG_MAXSIZE = 5*1024*1024
|
||||
LOG_PREFIX = ""
|
||||
LOG_SUFFIX = ""
|
||||
LOG_FILE = ""
|
||||
|
||||
|
||||
|
||||
|
||||
def log(text, level=3, file=None):
|
||||
if not LOG_LEVEL:
|
||||
return
|
||||
|
||||
if LOG_LEVEL >= level:
|
||||
name = "Unknown"
|
||||
if (level == LOG_FORCE):
|
||||
name = ""
|
||||
if (level == LOG_CRITICAL):
|
||||
name = "Critical"
|
||||
if (level == LOG_ERROR):
|
||||
name = "Error"
|
||||
if (level == LOG_WARNING):
|
||||
name = "Warning"
|
||||
if (level == LOG_NOTICE):
|
||||
name = "Notice"
|
||||
if (level == LOG_INFO):
|
||||
name = "Info"
|
||||
if (level == LOG_VERBOSE):
|
||||
name = "Verbose"
|
||||
if (level == LOG_DEBUG):
|
||||
name = "Debug"
|
||||
if (level == LOG_EXTREME):
|
||||
name = "Extra"
|
||||
|
||||
if not isinstance(text, str):
|
||||
text = str(text)
|
||||
|
||||
text = "[" + time.strftime(LOG_TIMEFMT, time.localtime(time.time())) +"] [" + name + "] " + LOG_PREFIX + text + LOG_SUFFIX
|
||||
|
||||
if file == None and LOG_FILE != "":
|
||||
file = LOG_FILE
|
||||
|
||||
if file == None:
|
||||
print(text)
|
||||
else:
|
||||
try:
|
||||
file_handle = open(file, "a")
|
||||
file_handle.write(text + "\n")
|
||||
file_handle.close()
|
||||
|
||||
if os.path.getsize(file) > LOG_MAXSIZE:
|
||||
file_prev = file + ".1"
|
||||
if os.path.isfile(file_prev):
|
||||
os.unlink(file_prev)
|
||||
os.rename(file, file_prev)
|
||||
except:
|
||||
return
|
||||
|
||||
|
||||
##############################################################################################################
|
||||
# System
|
||||
|
||||
|
||||
#### Panic #####
|
||||
def panic():
|
||||
sys.exit(255)
|
||||
|
||||
|
||||
#### Exit #####
|
||||
def exit():
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
##############################################################################################################
|
||||
# Setup/Start
|
||||
|
||||
|
||||
#### Setup #####
|
||||
def setup(path=None, path_rns=None, path_log=None, loglevel=None, dest="", interval=1, size=128, count=0, inst=1):
|
||||
global DATA
|
||||
global PATH
|
||||
global PATH_RNS
|
||||
global LOG_LEVEL
|
||||
global LOG_FILE
|
||||
global RNS_CONNECTION
|
||||
global LXMF_CONNECTION
|
||||
|
||||
if path is not None:
|
||||
if path.endswith("/"):
|
||||
path = path[:-1]
|
||||
PATH = path
|
||||
|
||||
if path_rns is not None:
|
||||
if path_rns.endswith("/"):
|
||||
path_rns = path_rns[:-1]
|
||||
PATH_RNS = path_rns
|
||||
|
||||
if loglevel is not None:
|
||||
LOG_LEVEL = loglevel
|
||||
rns_loglevel = loglevel
|
||||
else:
|
||||
rns_loglevel = None
|
||||
|
||||
RNS_CONNECTION = RNS.Reticulum(configdir=PATH_RNS, loglevel=rns_loglevel)
|
||||
|
||||
print("...............................................................................")
|
||||
print(" Name: " + NAME + " - " + DESCRIPTION)
|
||||
print("Program File: " + __file__)
|
||||
print(" Version: " + VERSION)
|
||||
print(" Copyright: " + COPYRIGHT)
|
||||
print("...............................................................................")
|
||||
|
||||
log("LXMF - Connecting ...", LOG_DEBUG)
|
||||
|
||||
if path is None:
|
||||
path = PATH
|
||||
|
||||
LXMF_CONNECTION = lxmf_connection(storage_path=path)
|
||||
|
||||
LXMF_CONNECTION.register_message_notification_success_callback(lxmf_success)
|
||||
LXMF_CONNECTION.register_message_notification_failed_callback(lxmf_failed)
|
||||
|
||||
log("LXMF - Connected", LOG_DEBUG)
|
||||
|
||||
log("...............................................................................", LOG_FORCE)
|
||||
log("LXMF - Address: " + RNS.prettyhexrep(LXMF_CONNECTION.destination_hash()), LOG_FORCE)
|
||||
log("...............................................................................", LOG_FORCE)
|
||||
|
||||
DATA = {}
|
||||
destinations = dest.split(",")
|
||||
for key in destinations:
|
||||
DATA[key] = {}
|
||||
DATA[key]["count"] = 0
|
||||
DATA[key]["count_success"] = 0
|
||||
DATA[key]["count_failed"] = 0
|
||||
DATA[key]["time"] = 0
|
||||
DATA[key]["time_min"] = 0
|
||||
DATA[key]["time_max"] = 0
|
||||
DATA[key]["time_avg"] = 0
|
||||
|
||||
count_current = 0
|
||||
while True:
|
||||
if count == 0 or count_current < count:
|
||||
count_current = count_current + 1
|
||||
letters = string.ascii_lowercase
|
||||
content = ''.join(random.choice(letters) for i in range(size))
|
||||
for key in DATA:
|
||||
DATA[key]["count"] = DATA[key]["count"] + 1
|
||||
content = "#"+ str(DATA[key]["count"]) + " " + content
|
||||
content = content[:size]
|
||||
if key == ".":
|
||||
LXMF_CONNECTION.send(secrets.token_hex(nbytes=10), content, "")
|
||||
else:
|
||||
LXMF_CONNECTION.send(key, content, "")
|
||||
print("Destination: " + str (key) + " | #: " + str(DATA[key]["count"]) + " | Messages delivered: " + str(DATA[key]["count_success"]) + "/" + str(DATA[key]["count"]) + " (" + str(round(100/DATA[key]["count"]*DATA[key]["count_success"], 2)) + "%) | Time (min / max / avg): " + str(DATA[key]["time_min"]) + " / " + str(DATA[key]["time_max"]) + " / " + str(DATA[key]["time_avg"]) + " | Info: Sending/Queued")
|
||||
time.sleep(interval)
|
||||
|
||||
|
||||
|
||||
|
||||
#### Start ####
|
||||
def main():
|
||||
try:
|
||||
description = NAME + " - " + DESCRIPTION
|
||||
parser = argparse.ArgumentParser(description=description)
|
||||
|
||||
parser.add_argument("-p", "--path", action="store", type=str, default=None, help="Path to alternative config directory")
|
||||
parser.add_argument("-pr", "--path_rns", action="store", type=str, default=None, help="Path to alternative Reticulum config directory")
|
||||
parser.add_argument("-pl", "--path_log", action="store", type=str, default=None, help="Path to alternative log directory")
|
||||
parser.add_argument("-l", "--loglevel", action="store", type=int, default=LOG_LEVEL)
|
||||
|
||||
parser.add_argument("-d", "--dest", action="store", required=True, type=str, default=None, help="Single destination hash or ,-separated list with destination hashs or . for random destination")
|
||||
parser.add_argument("-t", "--time", action="store", type=float, default=1, help="Time between messages in seconds")
|
||||
parser.add_argument("-s", "--size", action="store", type=int, default=128, help="Size (lenght) of the message content")
|
||||
parser.add_argument("-c", "--count", action="store", type=float, default=0, help="Maximum message send count (0=no end)")
|
||||
parser.add_argument("-i", "--inst", action="store", type=int, default=1, help="Parallel instances (different sender addresses)")
|
||||
|
||||
params = parser.parse_args()
|
||||
|
||||
setup(path=params.path, path_rns=params.path_rns, path_log=params.path_log, loglevel=params.loglevel, dest=params.dest, interval=params.time, size=params.size, count=params.count, inst=params.inst)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("Terminated by CTRL-C")
|
||||
exit()
|
||||
|
||||
|
||||
##############################################################################################################
|
||||
# Init
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
0
lxmf_terminal/CHANGELOG.md
Normal file
197
lxmf_terminal/README.md
Normal file
@ -0,0 +1,197 @@
|
||||
# lxmf_terminal
|
||||
This program provides a complete terminal session on the server. Any commands can be executed on the target device. The communication is done by single LXMF messages. This offers the advantage that simple terminal commands can be used by any LXMF capable application.
|
||||
|
||||
For more information, see the configuration options (at the end of the program files). Everything else is briefly documented there. After the first start this configuration will be created as default config in the corresponding file.
|
||||
|
||||
|
||||
### Features
|
||||
- Compatible with all LXMF applications (NomadNet, Sideband, ...)
|
||||
|
||||
|
||||
## Examples of use
|
||||
|
||||
###
|
||||
|
||||
### General info how the messages are transported
|
||||
All messages between client<->server are transported as single 1:1 messages in the LXMF/Reticulum network.
|
||||
Accordingly, encryption takes place between these end points.
|
||||
If a direct delivery of the message does not work, it is sent to a propagation node. There it is stored temporarily and can be retrieved by the client later.
|
||||
|
||||
As these are normal LXMF messages, any LXMF capable application can be used to communicate with the group.
|
||||
|
||||
|
||||
## Current Status
|
||||
It should currently be considered beta software. All core features are implemented and functioning, but additions will probably occur as real-world use is explored. There will be bugs.
|
||||
The full documentation is not yet available. Due to lack of time I can also not say when this will be further processed.
|
||||
|
||||
|
||||
## Screenshots / Usage examples
|
||||
<img src="../docs/screenshots/lxmf_terminal_01.png" width="200px">
|
||||
|
||||
|
||||
## Installation manual
|
||||
|
||||
### Install:
|
||||
- Install all required prerequisites. (Default Reticulum installation. Only necessary if reticulum is not yet installed.)
|
||||
```bash
|
||||
apt update
|
||||
apt upgrade
|
||||
|
||||
apt install python3-pip
|
||||
|
||||
pip install pip --upgrade
|
||||
reboot
|
||||
|
||||
pip3 install rns
|
||||
pip3 install pyserial netifaces
|
||||
|
||||
pip3 install lxmf
|
||||
```
|
||||
- Change the Reticulum configuration to suit your needs and use-case.
|
||||
```bash
|
||||
nano /.reticulum/config
|
||||
```
|
||||
- Download the [file](lxmf_terminal.py) from this repository.
|
||||
```bash
|
||||
wget https://raw.githubusercontent.com/SebastianObi/LXMF-Tools/main/lxmf_terminal/lxmf_terminal.py
|
||||
```
|
||||
- Make it executable with the following command
|
||||
```bash
|
||||
chmod +x lxmf_terminal.py
|
||||
```
|
||||
|
||||
### Start:
|
||||
- Start it
|
||||
```bash
|
||||
./lxmf_terminal.py
|
||||
```
|
||||
- After the first start edit the configuration file to suit your needs and use-case. The file location is displayed.
|
||||
- Example minimal configuration (override of the default config `config.cfg`). These are the most relevant settings that need to be adjusted. All other settings are in `config.cfg`
|
||||
```bash
|
||||
nano /root/.lxmf_terminal/config.cfg.owr
|
||||
```
|
||||
```bash
|
||||
```
|
||||
- Start it again. Finished!
|
||||
```bash
|
||||
./lxmf_terminal.py
|
||||
```
|
||||
|
||||
|
||||
### Run as a system service/deamon:
|
||||
- Create a service file.
|
||||
```bash
|
||||
nano /etc/systemd/system/lxmf_terminal.service
|
||||
```
|
||||
- Copy and edit the following content to your own needs.
|
||||
```bash
|
||||
[Unit]
|
||||
Description=lxmf_terminal.py Daemon
|
||||
After=multi-user.target
|
||||
[Service]
|
||||
# ExecStartPre=/bin/sleep 10
|
||||
Type=simple
|
||||
Restart=always
|
||||
RestartSec=3
|
||||
User=root
|
||||
ExecStart=/root/lxmf_terminal.py
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
- Enable the service.
|
||||
```bash
|
||||
systemctl enable lxmf_terminal
|
||||
```
|
||||
- Start the service.
|
||||
```bash
|
||||
systemctl start lxmf_terminal
|
||||
```
|
||||
|
||||
|
||||
### Start/Stop service:
|
||||
```bash
|
||||
systemctl start lxmf_terminal
|
||||
systemctl stop lxmf_terminal
|
||||
```
|
||||
|
||||
|
||||
### Enable/Disable service:
|
||||
```bash
|
||||
systemctl enable lxmf_terminal
|
||||
systemctl disable lxmf_terminal
|
||||
```
|
||||
|
||||
|
||||
### Run several instances (To copy the same application):
|
||||
- Run the program with a different configuration path.
|
||||
```bash
|
||||
./lxmf_terminal.py -p /root/.lxmf_terminal_2nd
|
||||
./lxmf_terminal.py -p /root/.lxmf_terminal_3nd
|
||||
```
|
||||
- After the first start edit the configuration file to suit your needs and use-case. The file location is displayed.
|
||||
|
||||
|
||||
### First usage:
|
||||
- With a manual start via the console, the own LXMF address is displayed:
|
||||
```
|
||||
[] ...............................................................................
|
||||
[] LXMF - Address: <801f48d54bc71cb3e0886944832aaf8d>
|
||||
[] ...............................................................................`
|
||||
```
|
||||
- This address is also annouced at startup in the default setting.
|
||||
- Now the software can be used.
|
||||
|
||||
|
||||
### Startup parameters:
|
||||
```bash
|
||||
usage: lxmf_terminal.py [-h] [-p PATH] [-pr PATH_RNS] [-pl PATH_LOG] [-l LOGLEVEL] [-s] [--exampleconfig] [--exampleconfigoverride]
|
||||
|
||||
LXMF Terminal -
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
-p PATH, --path PATH Path to alternative config directory
|
||||
-pr PATH_RNS, --path_rns PATH_RNS
|
||||
Path to alternative Reticulum config directory
|
||||
-pl PATH_LOG, --path_log PATH_LOG
|
||||
Path to alternative log directory
|
||||
-l LOGLEVEL, --loglevel LOGLEVEL
|
||||
-s, --service Running as a service and should log to file
|
||||
--exampleconfig Print verbose configuration example to stdout and exit
|
||||
--exampleconfigoverride
|
||||
Print verbose configuration example to stdout and exit
|
||||
```
|
||||
|
||||
|
||||
### Config/data files:
|
||||
- config.cfg
|
||||
|
||||
This is the default config file.
|
||||
|
||||
- config.cfg.owr
|
||||
|
||||
This is the user configuration file to override the default configuration file.
|
||||
All settings made here have precedence.
|
||||
This file can be used to clearly summarize all settings that deviate from the default.
|
||||
This also has the advantage that all changed settings can be kept when updating the program.
|
||||
|
||||
|
||||
## Configuration manual (Examples)
|
||||
The configurations shown here are only a part of the total configuration.
|
||||
It only serves to show the configuration that is necessary and adapted for the respective function.
|
||||
All configurations must be made in the file `config.cfg.owr`.
|
||||
All possible settings can be seen in the default configuration file `config.cfg`.
|
||||
|
||||
|
||||
## Admin manual
|
||||
This guide applies to all admins. Here are briefly explained the administative possibilities.
|
||||
|
||||
|
||||
## User manual
|
||||
This guide applies to users or admins. Here are briefly explained the normal possibilities of the software.
|
||||
|
||||
|
||||
## FAQ
|
||||
|
||||
### How do I start with the software?
|
||||
You should read the `Installation manual` section. There everything is explained briefly. Just work through everything from top to bottom :)
|