2022-10-21 11:58:11 -04:00
#!/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 datetime
import argparse
#### Config ####
import configparser
#### Variables ####
from collections import defaultdict
#### JSON ####
import json
import pickle
#### String ####
import string
2023-04-25 01:15:17 -04:00
#### Regex ####
import re
2022-10-21 11:58:11 -04:00
#### Search ####
import fnmatch
#### 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 Distribution Group "
DESCRIPTION = " Server-Side group functions for LXMF based apps "
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
CONFIG = None
STATISTIC = None
RNS_MAIN_CONNECTION = None
LXMF_CONNECTION = None
RNS_CONNECTION = None
2022-11-08 12:34:34 -05:00
CONV_P2P = 0x01
CONV_GROUP = 0x02
CONV_BROADCAST = 0x03
CONV_DISTRIBUTION_GROUP = 0x04
2022-10-21 11:58:11 -04:00
##############################################################################################################
# LXMF Class
class lxmf_connection :
message_received_callback = None
message_notification_callback = None
message_notification_success_callback = None
message_notification_failed_callback = None
2023-04-25 01:15:17 -04:00
config_set_callback = None
2022-10-21 11:58:11 -04:00
2023-04-25 01:15:17 -04:00
def __init__ ( self , storage_path = None , identity_file = " identity " , identity = None , destination_name = " lxmf " , destination_type = " delivery " , display_name = " " , announce_data = None , announce_hidden = False , send_delay = 0 , desired_method = " direct " , propagation_node = None , propagation_node_auto = False , propagation_node_active = 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 ) :
2022-10-21 11:58:11 -04:00
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
2022-12-07 11:05:23 -05:00
self . announce_data = announce_data
2023-04-25 01:15:17 -04:00
self . announce_hidden = announce_hidden
2022-10-21 11:58:11 -04:00
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
2023-04-25 01:15:17 -04:00
self . propagation_node_auto = propagation_node_auto
self . propagation_node_active = propagation_node_active
2022-10-21 11:58:11 -04:00
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 )
2023-04-25 01:15:17 -04:00
if not self . storage_path :
log ( " LXMF - No storage_path parameter " , LOG_ERROR )
return
2022-10-21 11:58:11 -04:00
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 )
2022-12-07 11:05:23 -05:00
if self . destination_name == " lxmf " and self . destination_type == " delivery " :
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 )
else :
self . destination = RNS . Destination ( self . identity , RNS . Destination . IN , RNS . Destination . SINGLE , self . destination_name , self . destination_type )
2022-10-21 11:58:11 -04:00
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 )
2023-04-25 01:15:17 -04:00
if self . propagation_node_auto :
self . propagation_callback = lxmf_connection_propagation ( self , " lxmf.propagation " )
RNS . Transport . register_announce_handler ( self . propagation_callback )
if self . propagation_node_active :
self . propagation_node_set ( self . propagation_node_active )
elif self . propagation_node :
self . propagation_node_set ( self . propagation_node )
else :
self . propagation_node_set ( self . propagation_node )
2022-10-21 11:58:11 -04:00
if self . announce_startup or self . announce_periodic :
2023-04-25 01:15:17 -04:00
self . announce ( initial = True )
2022-10-21 11:58:11 -04:00
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
2023-04-25 01:15:17 -04:00
def register_config_set_callback ( self , handler_function ) :
self . config_set_callback = handler_function
2022-10-21 11:58:11 -04:00
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 " "
2023-04-25 01:15:17 -04:00
def send ( self , destination , content = " " , title = " " , fields = None , timestamp = None , app_data = " " , destination_name = None , destination_type = None ) :
2022-10-21 11:58:11 -04:00
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 )
2023-06-05 08:36:42 -04:00
return None
2022-10-21 11:58:11 -04:00
try :
destination = bytes . fromhex ( destination )
except Exception as e :
log ( " LXMF - Destination is invalid " , LOG_ERROR )
2023-06-05 08:36:42 -04:00
return None
2022-10-21 11:58:11 -04:00
2023-04-25 01:15:17 -04:00
if destination_name == None :
destination_name = self . destination_name
if destination_type == None :
destination_type = self . destination_type
2022-10-21 11:58:11 -04:00
destination_identity = RNS . Identity . recall ( destination )
2023-04-25 01:15:17 -04:00
destination = RNS . Destination ( destination_identity , RNS . Destination . OUT , RNS . Destination . SINGLE , destination_name , destination_type )
2023-06-05 08:36:42 -04:00
return self . send_message ( destination , self . destination , content , title , fields , timestamp , app_data )
2022-10-21 11:58:11 -04:00
2022-10-25 03:02:42 -04:00
def send_message ( self , destination , source , content = " " , title = " " , fields = None , timestamp = None , app_data = " " ) :
2022-10-21 11:58:11 -04:00
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 )
2023-06-05 08:36:42 -04:00
return message . hash
2022-10-21 11:58:11 -04:00
except Exception as e :
log ( " LXMF - Could not send message " + str ( message ) , LOG_ERROR )
log ( " LXMF - The contained exception was: " + str ( e ) , LOG_ERROR )
2023-06-05 08:36:42 -04:00
return None
2022-10-21 11:58:11 -04:00
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 "
2023-04-25 01:15:17 -04:00
def announce ( self , app_data = None , attached_interface = None , initial = False ) :
2022-10-21 11:58:11 -04:00
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 :
2023-04-25 01:15:17 -04:00
self . announce_now ( app_data = app_data , attached_interface = attached_interface )
2022-10-21 11:58:11 -04:00
return
2023-04-25 01:15:17 -04:00
self . announce_now ( app_data = app_data , attached_interface = attached_interface )
2022-10-21 11:58:11 -04:00
2023-04-25 01:15:17 -04:00
def announce_now ( self , app_data = None , attached_interface = None ) :
if self . announce_hidden :
self . destination . announce ( " " . encode ( " utf-8 " ) , attached_interface = attached_interface )
log ( " LXMF - Announced: " + RNS . prettyhexrep ( self . destination_hash ( ) ) + " (Hidden) " , LOG_DEBUG )
elif app_data != None :
2022-12-07 11:05:23 -05:00
if isinstance ( app_data , str ) :
2023-04-25 01:15:17 -04:00
self . destination . announce ( app_data . encode ( " utf-8 " ) , attached_interface = attached_interface )
log ( " LXMF - Announced: " + RNS . prettyhexrep ( self . destination_hash ( ) ) + " : " + app_data , LOG_DEBUG )
2022-12-07 11:05:23 -05:00
else :
2023-04-25 01:15:17 -04:00
self . destination . announce ( app_data , attached_interface = attached_interface )
2022-12-07 11:05:23 -05:00
log ( " LMF - Announced: " + RNS . prettyhexrep ( self . destination_hash ( ) ) , LOG_DEBUG )
elif self . announce_data :
if isinstance ( self . announce_data , str ) :
2023-04-25 01:15:17 -04:00
self . destination . announce ( self . announce_data . encode ( " utf-8 " ) , attached_interface = attached_interface )
2022-12-07 11:05:23 -05:00
log ( " LXMF - Announced: " + RNS . prettyhexrep ( self . destination_hash ( ) ) + " : " + self . announce_data , LOG_DEBUG )
else :
2023-04-25 01:15:17 -04:00
self . destination . announce ( self . announce_data , attached_interface = attached_interface )
2022-12-07 11:05:23 -05:00
log ( " LXMF - Announced: " + RNS . prettyhexrep ( self . destination_hash ( ) ) , LOG_DEBUG )
2022-10-21 11:58:11 -04:00
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 :
2023-07-29 13:35:54 -04:00
log ( " LXMF - Message sync requested from propagation node " + RNS . prettyhexrep ( self . message_router . get_outbound_propagation_node ( ) ) + " for " + str ( self . identity ) , LOG_DEBUG )
2022-10-21 11:58:11 -04:00
self . message_router . request_messages_from_propagation_node ( self . identity , max_messages = limit )
return True
else :
return False
else :
return False
2023-04-25 01:15:17 -04:00
def propagation_node_set ( self , dest_str ) :
if not dest_str :
return False
2022-10-21 11:58:11 -04:00
2023-04-25 01:15:17 -04:00
if len ( dest_str ) != ( ( RNS . Reticulum . TRUNCATED_HASHLENGTH / / 8 ) * 2 ) :
log ( " LXMF - Propagation node length is invalid " , LOG_ERROR )
return False
try :
dest_hash = bytes . fromhex ( dest_str )
except Exception as e :
log ( " LXMF - Propagation node is invalid " , LOG_ERROR )
return False
node_identity = RNS . Identity . recall ( dest_hash )
if node_identity != None :
log ( " LXMF - Propagation node: " + RNS . prettyhexrep ( dest_hash ) , LOG_INFO )
dest_hash = RNS . Destination . hash_from_name_and_identity ( " lxmf.propagation " , node_identity )
self . message_router . set_outbound_propagation_node ( dest_hash )
self . propagation_node_active = dest_str
return True
else :
log ( " LXMF - Propagation node identity not known " , LOG_ERROR )
return False
def propagation_node_update ( self , dest_str ) :
if self . propagation_node_hash_str ( ) != dest_str :
if self . propagation_node_set ( dest_str ) and self . config_set_callback is not None :
self . config_set_callback ( " propagation_node_active " , dest_str )
def propagation_node_hash ( self ) :
try :
return bytes . fromhex ( self . propagation_node_active )
except :
return None
def propagation_node_hash_str ( self ) :
if self . propagation_node_active :
return self . propagation_node_active
else :
return " "
2022-10-21 11:58:11 -04:00
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 )
2023-04-25 01:15:17 -04:00
class lxmf_connection_propagation ( ) :
def __init__ ( self , owner , aspect_filter = None ) :
self . owner = owner
self . aspect_filter = aspect_filter
EMITTED_DELTA_GRACE = 300
EMITTED_DELTA_IGNORE = 10
def received_announce ( self , destination_hash , announced_identity , app_data ) :
if app_data == None :
return
if len ( app_data ) == 0 :
return
try :
unpacked = umsgpack . unpackb ( app_data )
node_active = unpacked [ 0 ]
emitted = unpacked [ 1 ]
hop_count = RNS . Transport . hops_to ( destination_hash )
age = time . time ( ) - emitted
if age < 0 :
if age < - 1 * PropDetector . EMITTED_DELTA_GRACE :
return
log ( " LXMF - Received an propagation node announce from " + RNS . prettyhexrep ( destination_hash ) + " : " + str ( age ) + " seconds ago, " + str ( hop_count ) + " hops away " , LOG_INFO )
if self . owner . propagation_node_active == None :
self . owner . propagation_node_update ( RNS . hexrep ( destination_hash , False ) )
else :
prev_hop_count = RNS . Transport . hops_to ( self . owner . propagation_node_hash ( ) )
if hop_count < = prev_hop_count :
self . owner . propagation_node_update ( RNS . hexrep ( destination_hash , False ) )
except :
return
2022-10-21 11:58:11 -04:00
##############################################################################################################
# RNS Class
class rns_connection :
2023-04-25 01:15:17 -04:00
def __init__ ( self , storage_path = None , identity_file = " identity " , identity = None , destination_name = " rns " , destination_type = " connect " , announce_startup = False , announce_startup_delay = 0 , announce_periodic = False , announce_periodic_interval = 360 , announce_data = " " , announce_hidden = False ) :
2022-10-21 11:58:11 -04:00
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 . 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 . announce_data = announce_data
2023-04-25 01:15:17 -04:00
self . announce_hidden = announce_hidden
if not self . storage_path :
log ( " RNS - No storage_path parameter " , LOG_ERROR )
return
2022-10-21 11:58:11 -04:00
if not os . path . isdir ( self . storage_path ) :
os . makedirs ( self . storage_path )
log ( " RNS - Storage path was created " , LOG_NOTICE )
log ( " RNS - Storage path: " + self . storage_path , LOG_INFO )
if self . identity :
log ( " RNS - 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 ( " RNS - Loaded Primary Identity %s from %s " % ( str ( self . identity ) , self . identity_path ) )
else :
log ( " RNS - Could not load the Primary Identity from " + self . identity_path , LOG_ERROR )
except Exception as e :
log ( " RNS - Could not load the Primary Identity from " + self . identity_path , LOG_ERROR )
log ( " RNS - The contained exception was: %s " % ( str ( e ) ) , LOG_ERROR )
else :
try :
log ( " RNS - No Primary Identity file found, creating new... " )
self . identity = RNS . Identity ( )
self . identity . to_file ( self . identity_path )
log ( " RNS - Created new Primary Identity %s " % ( str ( self . identity ) ) )
except Exception as e :
log ( " RNS - Could not create and save a new Primary Identity " , LOG_ERROR )
log ( " RNS - The contained exception was: %s " % ( str ( e ) ) , LOG_ERROR )
self . destination = RNS . Destination ( self . identity , RNS . Destination . IN , RNS . Destination . SINGLE , self . destination_name , self . destination_type )
self . destination . set_proof_strategy ( RNS . Destination . PROVE_ALL )
if self . announce_startup or self . announce_periodic :
2023-04-25 01:15:17 -04:00
self . announce ( initial = True )
2022-10-21 11:58:11 -04:00
def register_announce_callback ( self , handler_function ) :
self . announce_callback = handler_function ( self . aspect_filter )
RNS . Transport . register_announce_handler ( self . announce_callback )
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 ( " RNS - Destination length is invalid " , LOG_ERROR )
return False
try :
destination = bytes . fromhex ( destination )
except Exception as e :
log ( " RNS - 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 " "
2023-04-25 01:15:17 -04:00
def announce ( self , app_data = None , attached_interface = None , initial = False ) :
announce_timer = None
2022-10-21 11:58:11 -04:00
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 :
2023-04-25 01:15:17 -04:00
if announce_timer is not None :
announce_timer . cancel ( )
2022-10-21 11:58:11 -04:00
announce_timer = threading . Timer ( self . announce_startup_delay , self . announce )
announce_timer . daemon = True
announce_timer . start ( )
else :
2023-04-25 01:15:17 -04:00
self . announce_now ( app_data = app_data , attached_interface = attached_interface )
2022-10-21 11:58:11 -04:00
return
2023-04-25 01:15:17 -04:00
self . announce_now ( app_data = app_data , attached_interface = attached_interface )
2022-10-21 11:58:11 -04:00
2023-04-25 01:15:17 -04:00
def announce_now ( self , app_data = None , attached_interface = None ) :
if self . announce_hidden :
self . destination . announce ( " " . encode ( " utf-8 " ) , attached_interface = attached_interface )
log ( " RNS - Announced: " + RNS . prettyhexrep ( self . destination_hash ( ) ) + " (Hidden) " , LOG_DEBUG )
elif app_data != None :
2022-12-07 11:05:23 -05:00
if isinstance ( app_data , str ) :
2023-04-25 01:15:17 -04:00
self . destination . announce ( app_data . encode ( " utf-8 " ) , attached_interface = attached_interface )
log ( " RNS - Announced: " + RNS . prettyhexrep ( self . destination_hash ( ) ) + " : " + app_data , LOG_DEBUG )
2022-12-07 11:05:23 -05:00
else :
2023-04-25 01:15:17 -04:00
self . destination . announce ( app_data , attached_interface = attached_interface )
2022-12-07 11:05:23 -05:00
log ( " RNS - Announced: " + RNS . prettyhexrep ( self . destination_hash ( ) ) , LOG_DEBUG )
2022-10-21 11:58:11 -04:00
else :
2022-12-07 11:05:23 -05:00
if isinstance ( self . announce_data , str ) :
2023-04-25 01:15:17 -04:00
self . destination . announce ( self . announce_data . encode ( " utf-8 " ) , attached_interface = attached_interface )
2022-12-07 11:05:23 -05:00
log ( " RNS - Announced: " + RNS . prettyhexrep ( self . destination_hash ( ) ) + " : " + self . announce_data , LOG_DEBUG )
else :
2023-04-25 01:15:17 -04:00
self . destination . announce ( self . announce_data , attached_interface = attached_interface )
2022-12-07 11:05:23 -05:00
log ( " RNS - Announced: " + RNS . prettyhexrep ( self . destination_hash ( ) ) , LOG_DEBUG )
2022-10-21 11:58:11 -04:00
##############################################################################################################
# LXMF Functions
#### LXMF - Announce ####
class lxmf_announce_callback :
def __init__ ( self , aspect_filter = None ) :
self . aspect_filter = aspect_filter
@staticmethod
def received_announce ( destination_hash , announced_identity , app_data ) :
2023-06-05 08:36:42 -04:00
if app_data == None :
return
2022-10-21 11:58:11 -04:00
2023-06-05 08:36:42 -04:00
if len ( app_data ) == 0 :
return
2022-10-21 11:58:11 -04:00
2023-06-05 08:36:42 -04:00
try :
app_data_dict = umsgpack . unpackb ( app_data )
if isinstance ( app_data_dict , dict ) and " c " in app_data_dict :
app_data = app_data_dict [ " c " ]
except :
pass
2022-10-21 11:58:11 -04:00
2023-06-06 07:23:31 -04:00
try :
app_data = app_data . decode ( " utf-8 " ) . strip ( )
except :
return
log ( " LXMF - Received an announce from " + RNS . prettyhexrep ( destination_hash ) + " : " + app_data , LOG_INFO )
2022-10-21 11:58:11 -04:00
2023-06-05 08:36:42 -04:00
global DATA
lng_key = " - " + CONFIG [ " main " ] [ " lng " ]
sections = [ ]
for ( key , val ) in CONFIG . items ( " rights " ) :
if DATA . has_section ( key ) :
sections . append ( key )
if CONFIG [ " main " ] . getboolean ( " auto_name_def " ) or CONFIG [ " main " ] . getboolean ( " auto_name_change " ) :
source_hash = RNS . hexrep ( destination_hash , False )
for section in DATA . sections ( ) :
for ( key , val ) in DATA . items ( section ) :
if key == source_hash :
if ( val == " " and CONFIG [ " main " ] . getboolean ( " auto_name_def " ) ) or ( val != " " and CONFIG [ " main " ] . getboolean ( " auto_name_change " ) ) :
2023-06-06 07:23:31 -04:00
value = app_data
2023-06-05 08:36:42 -04:00
if value != DATA [ section ] [ key ] :
if DATA [ section ] [ key ] == " " :
content_type = " name_def "
content_add = " " + value
else :
content_type = " name_change "
content_add = " " + DATA [ section ] [ key ] + " -> " + value
DATA [ section ] [ key ] = value
content_group = config_get ( CONFIG , " interface_messages " , " member_ " + content_type , " " , lng_key )
if content_group != " " :
fields = fields_generate ( lng_key , h = destination_hash , n = value , tpl = content_type )
content_group = replace ( content_group , source_hash , value , " " , lng_key )
content_group = content_group + content_add
for section in sections :
if " receive_auto_ " + content_type in config_get ( CONFIG , " rights " , section ) . split ( " , " ) :
for ( key , val ) in DATA . items ( section ) :
if key != source_hash :
LXMF_CONNECTION . send ( key , content_group , " " , fields , None , " interface_send " )
if CONFIG [ " main " ] . getboolean ( " auto_save_data " ) :
DATA . remove_option ( " main " , " unsaved " )
if not data_save ( PATH + " /data.cfg " ) :
2022-10-21 11:58:11 -04:00
DATA [ " main " ] [ " unsaved " ] = " True "
2023-06-05 08:36:42 -04:00
else :
DATA [ " main " ] [ " unsaved " ] = " True "
2022-10-21 11:58:11 -04:00
#### LXMF - Message ####
def lxmf_message_received_callback ( message ) :
if CONFIG [ " lxmf " ] . getboolean ( " signature_validated " ) and not message . signature_validated :
log ( " LXMF - Source " + RNS . prettyhexrep ( message . source_hash ) + " have no valid signature " , LOG_DEBUG )
return
2023-06-05 08:36:42 -04:00
title = message . title . decode ( ' utf-8 ' ) . strip ( )
2023-11-17 13:37:31 -05:00
denys = config_getarray ( CONFIG , " message " , " deny_title " )
if len ( denys ) > 0 :
2023-06-05 08:36:42 -04:00
if " * " in denys :
return
for deny in denys :
if deny in title :
return
content = message . content . decode ( ' utf-8 ' ) . strip ( )
2023-11-17 13:37:31 -05:00
denys = config_getarray ( CONFIG , " message " , " deny_content " )
if len ( denys ) > 0 :
2023-06-05 08:36:42 -04:00
if " * " in denys :
return
for deny in denys :
if deny in title :
return
if message . fields :
2023-11-17 13:37:31 -05:00
denys = config_getarray ( CONFIG , " message " , " deny_fields " )
if len ( denys ) > 0 :
2023-06-05 08:36:42 -04:00
if " * " in denys :
return
for deny in denys :
if deny in message . fields :
return
if not CONFIG [ " message " ] . getboolean ( " title " ) :
title = " "
2022-12-07 11:05:23 -05:00
if CONFIG [ " message " ] . getboolean ( " fields " ) and message . fields :
pass
elif content == " " :
2022-10-21 11:58:11 -04:00
return
fields = message . fields
lng_key = " - " + CONFIG [ " main " ] [ " lng " ]
sections = [ ]
for ( key , val ) in CONFIG . items ( " rights " ) :
if DATA . has_section ( key ) :
sections . append ( key )
destination_hash = RNS . hexrep ( message . destination_hash , False )
source_hash = RNS . hexrep ( message . source_hash , False )
source_name = " "
source_right = " "
for section in DATA . sections ( ) :
if section . startswith ( " block " ) :
if DATA . has_option ( section , source_hash ) :
log ( " LXMF - Source " + RNS . prettyhexrep ( message . source_hash ) + " blocked " , LOG_DEBUG )
source_right = section . replace ( " block_ " , " " )
source_rights = config_get ( CONFIG , " rights " , source_right )
source_rights = source_rights . split ( " , " )
if " reply_block " in source_rights :
content_user = config_get ( CONFIG , " interface_messages " , " reply_block " , " " , lng_key )
content_user = replace ( content_user , source_hash , source_name , source_right , lng_key )
if content_user != " " :
2023-04-25 01:15:17 -04:00
LXMF_CONNECTION . send ( source_hash , content_user , " " , fields_generate ( lng_key ) , None , " interface_send " )
2022-10-21 11:58:11 -04:00
return
2022-10-22 05:50:19 -04:00
source_rights = [ ]
2022-10-21 11:58:11 -04:00
for section in DATA . sections ( ) :
for ( key , val ) in DATA . items ( section ) :
if key == source_hash :
2022-10-22 05:50:19 -04:00
if source_name == " " :
source_name = val
2022-10-21 11:58:11 -04:00
source_right = section
2022-10-22 05:50:19 -04:00
source_rights . append ( section )
2022-10-21 11:58:11 -04:00
if fields :
if " c_n " in fields and " c_t " in fields and " m_t " in fields :
2022-10-22 05:50:19 -04:00
if fields [ " c_n " ] == CONFIG [ " cluster " ] [ " name " ] and fields [ " c_t " ] == CONFIG [ " cluster " ] [ " type " ] and " cluster " in source_rights and config_getboolean ( CONFIG , " cluster " , " enabled " ) :
2023-04-25 01:15:17 -04:00
title_prefix = config_get ( CONFIG , " message " , " cluster_receive_title_prefix " , " " , lng_key )
2022-10-21 11:58:11 -04:00
content_prefix = config_get ( CONFIG , " message " , " cluster_receive_prefix " , " " , lng_key )
content_suffix = config_get ( CONFIG , " message " , " cluster_receive_suffix " , " " , lng_key )
2023-04-25 01:15:17 -04:00
title_prefix = replace ( title_prefix , source_hash , source_name , source_right , lng_key )
2022-10-21 11:58:11 -04:00
content_prefix = replace ( content_prefix , source_hash , source_name , source_right , lng_key )
content_suffix = replace ( content_suffix , source_hash , source_name , source_right , lng_key )
source = source_name . rsplit ( ' / ' , 1 ) [ - 1 ]
destination = config_get ( CONFIG , " cluster " , " display_name " , " " , lng_key ) . rsplit ( ' / ' , 1 ) [ - 1 ]
2023-04-25 01:15:17 -04:00
title_prefix = title_prefix . replace ( CONFIG [ " interface " ] [ " delimiter_output " ] + " cluster_source " + CONFIG [ " interface " ] [ " delimiter_output " ] , source )
title_prefix = title_prefix . replace ( CONFIG [ " interface " ] [ " delimiter_output " ] + " cluster_destination " + CONFIG [ " interface " ] [ " delimiter_output " ] , destination )
2022-10-21 11:58:11 -04:00
content_prefix = content_prefix . replace ( CONFIG [ " interface " ] [ " delimiter_output " ] + " cluster_source " + CONFIG [ " interface " ] [ " delimiter_output " ] , source )
content_prefix = content_prefix . replace ( CONFIG [ " interface " ] [ " delimiter_output " ] + " cluster_destination " + CONFIG [ " interface " ] [ " delimiter_output " ] , destination )
content_suffix = content_suffix . replace ( CONFIG [ " interface " ] [ " delimiter_output " ] + " cluster_source " + CONFIG [ " interface " ] [ " delimiter_output " ] , source )
content_suffix = content_suffix . replace ( CONFIG [ " interface " ] [ " delimiter_output " ] + " cluster_destination " + CONFIG [ " interface " ] [ " delimiter_output " ] , destination )
search = config_get ( CONFIG , " message " , " cluster_receive_search " )
if search != " " :
content = content . replace ( search , config_get ( CONFIG , " message " , " cluster_receive_replace " ) )
search = config_get ( CONFIG , " message " , " cluster_receive_regex_search " )
if search != " " :
content = re . sub ( search , config_get ( CONFIG , " message " , " cluster_receive_regex_replace " ) , content )
2023-04-25 01:15:17 -04:00
title = title_prefix + title
2022-10-21 11:58:11 -04:00
content = content_prefix + content + content_suffix
if config_get ( CONFIG , " message " , " timestamp " , " " , lng_key ) == " client " :
timestamp = message . timestamp
else :
timestamp = time . time ( )
2022-12-07 11:05:23 -05:00
if CONFIG [ " message " ] . getboolean ( " fields " ) :
if message . fields :
2023-04-25 01:15:17 -04:00
fields = fields_remove ( message . fields , " fields_remove_anonymous " if " anonymous " in source_rights else " fields_remove " )
2022-12-07 11:05:23 -05:00
else :
fields = { }
else :
fields = { }
2023-04-25 01:15:17 -04:00
fields = fields ( fields )
2022-12-07 11:05:23 -05:00
2022-10-21 11:58:11 -04:00
if CONFIG [ " statistic " ] . getboolean ( " enabled " ) and CONFIG [ " statistic " ] . getboolean ( " cluster " ) :
statistic ( " add " , " cluster_in_ " + message . desired_method_str )
if fields [ " m_t " ] == " message " :
for section in sections :
if " receive_cluster " in config_get ( CONFIG , " rights " , section ) . split ( " , " ) :
for ( key , val ) in DATA . items ( section ) :
if key != source_hash :
2022-12-07 11:05:23 -05:00
LXMF_CONNECTION . send ( key , content , title , fields , timestamp , " cluster_send " )
2022-10-21 11:58:11 -04:00
elif fields [ " m_t " ] == " pin " :
delimiter = CONFIG [ " interface " ] [ " delimiter_output " ]
value_new = config_get ( CONFIG , " interface_menu " , " cluster_pin " , " " , lng_key )
value_new = replace ( value_new , source_hash , source_name , source_right , lng_key )
value_new = value_new . replace ( delimiter + " value " + delimiter , content )
key = time . strftime ( config_get ( CONFIG , " message " , " pin_id " , " % y % m %d - % H % M % S " , lng_key ) , time . localtime ( time . time ( ) ) )
if DATA . has_option ( " pin " , key ) :
key = key + " - "
key_int = 0
while DATA . has_option ( " pin " , key + str ( key_int ) ) :
key_int + = 1
key = key + str ( key_int )
DATA [ " pin " ] [ key ] = value_new
content_group = config_get ( CONFIG , " interface_messages " , " cluster_pin_add " , " " , lng_key )
content_group = replace ( content_group , source_hash , source_name , source_right , lng_key )
content_group = content_group . replace ( delimiter + " key " + delimiter , key )
content_group = content_group . replace ( delimiter + " value " + delimiter , value_new )
if content_group != " " :
for section in sections :
if " receive_cluster_pin_add " in config_get ( CONFIG , " rights " , section ) . split ( " , " ) :
for ( key , val ) in DATA . items ( section ) :
if key != source_hash :
2022-12-07 11:05:23 -05:00
LXMF_CONNECTION . send ( key , content_group , " " , fields , None , " cluster_send " )
2022-10-21 11:58:11 -04:00
if CONFIG [ " main " ] . getboolean ( " auto_save_data " ) :
DATA . remove_option ( " main " , " unsaved " )
if not data_save ( PATH + " /data.cfg " ) :
DATA [ " main " ] [ " unsaved " ] = " True "
else :
DATA [ " main " ] [ " unsaved " ] = " True "
2022-12-07 11:05:23 -05:00
return
2022-10-21 11:58:11 -04:00
if source_right == " " and DATA [ " main " ] . getboolean ( " auto_add_user " ) :
if CONFIG [ " lxmf " ] . getboolean ( " signature_validated_new " ) and not message . signature_validated :
log ( " LXMF - Source " + RNS . prettyhexrep ( message . source_hash ) + " have no valid signature ' new ' " , LOG_DEBUG )
return
2023-04-25 01:15:17 -04:00
source_right = DATA [ " main " ] [ " auto_add_user_type " ]
if DATA . has_section ( source_right ) and source_right != " main " :
2022-11-08 12:34:34 -05:00
if CONFIG [ " main " ] . getboolean ( " auto_name_add " ) :
app_data = RNS . Identity . recall_app_data ( message . source_hash )
2023-06-05 08:36:42 -04:00
if app_data != None and len ( app_data ) > 0 :
try :
app_data_dict = umsgpack . unpackb ( app_data )
if isinstance ( app_data_dict , dict ) and " c " in app_data_dict :
app_data = app_data_dict [ " c " ]
except :
pass
2022-11-08 12:34:34 -05:00
source_name = app_data . decode ( ' utf-8 ' )
2023-04-25 01:15:17 -04:00
DATA [ source_right ] [ source_hash ] = source_name
2022-10-21 11:58:11 -04:00
DATA . remove_option ( " main " , " unsaved " )
2023-04-25 01:15:17 -04:00
content = config_get ( CONFIG , " interface_messages " , " auto_add_ " + source_right , " " , lng_key )
2022-10-21 11:58:11 -04:00
content_group = config_get ( CONFIG , " interface_messages " , " member_join " , " " , lng_key )
content_group = replace ( content_group , source_hash , source_name , source_right , lng_key )
if content_group != " " :
2023-04-25 01:15:17 -04:00
fields = fields_generate ( lng_key , h = message . source_hash , n = source_name , m = True , tpl = " join " )
2022-10-21 11:58:11 -04:00
for section in sections :
if " receive_join " in config_get ( CONFIG , " rights " , section ) . split ( " , " ) :
for ( key , val ) in DATA . items ( section ) :
if key != source_hash :
2023-04-25 01:15:17 -04:00
LXMF_CONNECTION . send ( key , content_group , title , fields , None , " interface_send " )
2022-10-21 11:58:11 -04:00
if CONFIG [ " main " ] . getboolean ( " auto_save_data " ) :
DATA . remove_option ( " main " , " unsaved " )
if not data_save ( PATH + " /data.cfg " ) :
DATA [ " main " ] [ " unsaved " ] = " True "
else :
DATA [ " main " ] [ " unsaved " ] = " True "
content = replace ( content , source_hash , source_name , source_right , lng_key )
if content != " " :
2023-04-25 01:15:17 -04:00
LXMF_CONNECTION . send ( source_hash , content , title , fields_generate ( lng_key , m = True , d = True , r = True , cmd = source_right , config = source_right , tpl = " info " ) , None , " interface_send " )
2022-10-21 11:58:11 -04:00
return
elif source_right == " " :
log ( " LXMF - Source " + RNS . prettyhexrep ( message . source_hash ) + " not exist (auto add disabled) " , LOG_DEBUG )
return
source_rights = config_get ( CONFIG , " rights " , source_right )
if source_rights == " " :
log ( " LXMF - Source " + RNS . prettyhexrep ( message . source_hash ) + " have no right " , LOG_DEBUG )
return
source_rights = source_rights . split ( " , " )
if CONFIG [ " lxmf " ] . getboolean ( " signature_validated_known " ) and not message . signature_validated :
log ( " LXMF - Source " + RNS . prettyhexrep ( message . source_hash ) + " have no valid signature ' known ' " , LOG_DEBUG )
if " reply_signature " in source_rights :
content_user = config_get ( CONFIG , " interface_messages " , " reply_signature " , " " , lng_key )
content_user = replace ( content_user , source_hash , source_name , source_right , lng_key )
if content_user != " " :
2023-04-25 01:15:17 -04:00
LXMF_CONNECTION . send ( source_hash , content_user , " " , fields_generate ( lng_key ) , None , " interface_send " )
2022-10-21 11:58:11 -04:00
return
length = config_getint ( CONFIG , " message " , " receive_length_min " , 0 , lng_key )
if length > 0 :
if len ( content ) < length :
if " reply_length_min " in source_rights :
content_user = config_get ( CONFIG , " interface_messages " , " reply_length_min " , " " , lng_key )
content_user = replace ( content_user , source_hash , source_name , source_right , lng_key )
if content_user != " " :
2023-04-25 01:15:17 -04:00
LXMF_CONNECTION . send ( source_hash , content_user , " " , fields_generate ( lng_key ) , None , " interface_send " )
2022-10-21 11:58:11 -04:00
return
length = config_getint ( CONFIG , " message " , " receive_length_max " , 0 , lng_key )
if length > 0 :
if len ( content ) > length :
if " reply_length_max " in source_rights :
content_user = config_get ( CONFIG , " interface_messages " , " reply_length_max " , " " , lng_key )
content_user = replace ( content_user , source_hash , source_name , source_right , lng_key )
if content_user != " " :
2023-04-25 01:15:17 -04:00
LXMF_CONNECTION . send ( source_hash , content_user , " " , fields_generate ( lng_key ) , None , " interface_send " )
2022-10-21 11:58:11 -04:00
return
2023-04-25 01:15:17 -04:00
title_prefix = config_get ( CONFIG , " message " , " receive_title_prefix " , " " , lng_key )
2022-10-21 11:58:11 -04:00
content_prefix = config_get ( CONFIG , " message " , " receive_prefix " , " " , lng_key )
content_suffix = config_get ( CONFIG , " message " , " receive_suffix " , " " , lng_key )
search = config_get ( CONFIG , " message " , " receive_search " )
if search != " " :
content = content . replace ( search , config_get ( CONFIG , " message " , " receive_replace " ) )
search = config_get ( CONFIG , " message " , " receive_regex_search " )
if search != " " :
content = re . sub ( search , config_get ( CONFIG , " message " , " receive_regex_replace " ) , content )
2023-04-25 01:15:17 -04:00
title = title_prefix + title
2022-10-21 11:58:11 -04:00
content = content_prefix + content + content_suffix
# Interface
if content . startswith ( CONFIG [ " interface " ] [ " delimiter_input " ] ) :
if not config_getboolean ( CONFIG , " interface " , " enabled " ) :
log ( " LXMF - Source " + RNS . prettyhexrep ( message . source_hash ) + " ' interface ' disabled " , LOG_DEBUG )
if " reply_interface_enabled " in source_rights :
content_user = config_get ( CONFIG , " interface_messages " , " reply_interface_enabled " , " " , lng_key )
content_user = replace ( content_user , source_hash , source_name , source_right , lng_key )
if content_user != " " :
2023-04-25 01:15:17 -04:00
LXMF_CONNECTION . send ( source_hash , content_user , " " , fields_generate ( lng_key ) , None , " interface_send " )
2022-10-21 11:58:11 -04:00
return
if " interface " not in source_rights :
log ( " LXMF - Source " + RNS . prettyhexrep ( message . source_hash ) + " ' interface ' not allowed " , LOG_DEBUG )
if " reply_interface_right " in source_rights :
content_user = config_get ( CONFIG , " interface_messages " , " reply_interface_right " , " " , lng_key )
content_user = replace ( content_user , source_hash , source_name , source_right , lng_key )
if content_user != " " :
2023-04-25 01:15:17 -04:00
LXMF_CONNECTION . send ( source_hash , content_user , " " , fields_generate ( lng_key ) , None , " interface_send " )
2022-10-21 11:58:11 -04:00
return
2023-04-25 01:15:17 -04:00
content = interface ( content [ len ( CONFIG [ " interface " ] [ " delimiter_input " ] ) : ] , source_hash , source_name , source_right , source_rights , lng_key , message )
2022-10-21 11:58:11 -04:00
if content == " " :
log ( " LXMF - Source " + RNS . prettyhexrep ( message . source_hash ) + " ' interface ' not allowed (empty response) " , LOG_DEBUG )
return
if CONFIG [ " statistic " ] . getboolean ( " enabled " ) :
if CONFIG [ " statistic " ] . getboolean ( " interface " ) :
statistic ( " add " , " interface_received_ " + message . desired_method_str )
if CONFIG [ " statistic " ] . getboolean ( " user " ) :
statistic ( " value_set " , source_hash , " activity " , time . strftime ( " % Y- % m- %d % H: % M: % S " , time . localtime ( time . time ( ) ) ) )
statistic ( " value_set " , source_hash , " activity_receive " , time . strftime ( " % Y- % m- %d % H: % M: % S " , time . localtime ( time . time ( ) ) ) )
2023-04-25 01:15:17 -04:00
LXMF_CONNECTION . send ( source_hash , content , " " , fields_generate ( lng_key ) , None , " interface_send " )
2022-10-21 11:58:11 -04:00
return
# Message - Cluster
if content . startswith ( CONFIG [ " cluster " ] [ " delimiter_input " ] ) :
if not config_getboolean ( CONFIG , " cluster " , " enabled " ) or not DATA [ " main " ] . getboolean ( " enabled_cluster " ) :
log ( " LXMF - Source " + RNS . prettyhexrep ( message . source_hash ) + " ' cluster ' disabled " , LOG_DEBUG )
if " reply_cluster_enabled " in source_rights :
content_user = config_get ( CONFIG , " interface_messages " , " reply_cluster_enabled " , " " , lng_key )
content_user = replace ( content_user , source_hash , source_name , source_right , lng_key )
if content_user != " " :
2023-04-25 01:15:17 -04:00
LXMF_CONNECTION . send ( source_hash , content_user , " " , fields_generate ( lng_key ) , None , " interface_send " )
2022-10-21 11:58:11 -04:00
return
if " send_cluster " not in source_rights :
log ( " LXMF - Source " + RNS . prettyhexrep ( message . source_hash ) + " ' cluster ' not allowed " , LOG_DEBUG )
if " reply_cluster_right " in source_rights :
content_user = config_get ( CONFIG , " interface_messages " , " reply_cluster_right " , " " , lng_key )
content_user = replace ( content_user , source_hash , source_name , source_right , lng_key )
if content_user != " " :
2023-04-25 01:15:17 -04:00
LXMF_CONNECTION . send ( source_hash , content_user , " " , fields_generate ( lng_key ) , None , " interface_send " )
2022-10-21 11:58:11 -04:00
return
try :
content = content [ len ( CONFIG [ " cluster " ] [ " delimiter_input " ] ) : ]
destination , content = content . split ( " " , 1 )
except :
2023-04-25 01:15:17 -04:00
LXMF_CONNECTION . send ( source_hash , config_get ( CONFIG , " interface_menu " , " cluster_format_error " , " " , lng_key ) , " " , fields_generate ( lng_key ) , None , " interface_send " )
2022-10-21 11:58:11 -04:00
return
destinations = [ ]
for ( key , val ) in DATA . items ( " cluster " ) :
if key != destination_hash and destination in val . split ( " / " ) :
destinations . append ( key )
if len ( destinations ) == 0 :
2023-04-25 01:15:17 -04:00
LXMF_CONNECTION . send ( source_hash , config_get ( CONFIG , " interface_menu " , " cluster_found_error " , " " , lng_key ) , " " , fields_generate ( lng_key ) , None , " interface_send " )
2022-10-21 11:58:11 -04:00
return
length = config_getint ( CONFIG , " message " , " cluster_send_length_min " , 0 , lng_key )
if length > 0 :
if len ( content ) < length :
if " reply_length_min " in source_rights :
content_user = config_get ( CONFIG , " interface_messages " , " reply_length_min " , " " , lng_key )
content_user = replace ( content_user , source_hash , source_name , source_right , lng_key )
if content_user != " " :
2023-04-25 01:15:17 -04:00
LXMF_CONNECTION . send ( source_hash , content_user , " " , fields_generate ( lng_key ) , None , " interface_send " )
2022-10-21 11:58:11 -04:00
return
length = config_getint ( CONFIG , " message " , " cluster_send_length_max " , 0 , lng_key )
if length > 0 :
if len ( content ) > length :
if " reply_length_max " in source_rights :
content_user = config_get ( CONFIG , " interface_messages " , " reply_length_max " , " " , lng_key )
content_user = replace ( content_user , source_hash , source_name , source_right , lng_key )
if content_user != " " :
2023-04-25 01:15:17 -04:00
LXMF_CONNECTION . send ( source_hash , content_user , " " , fields_generate ( lng_key ) , None , " interface_send " )
2022-10-21 11:58:11 -04:00
return
2023-04-25 01:15:17 -04:00
title_prefix = config_get ( CONFIG , " message " , " cluster_send_title_prefix " , " " , lng_key )
2022-10-21 11:58:11 -04:00
content_prefix = config_get ( CONFIG , " message " , " cluster_send_prefix " , " " , lng_key )
content_suffix = config_get ( CONFIG , " message " , " cluster_send_suffix " , " " , lng_key )
2023-04-25 01:15:17 -04:00
if " anonymous " in source_rights :
title_prefix = replace ( title_prefix , " " , " " , source_right , lng_key )
content_prefix = replace ( content_prefix , " " , " " , source_right , lng_key )
content_suffix = replace ( content_suffix , " " , " " , source_right , lng_key )
else :
title_prefix = replace ( title_prefix , source_hash , source_name , source_right , lng_key )
content_prefix = replace ( content_prefix , source_hash , source_name , source_right , lng_key )
content_suffix = replace ( content_suffix , source_hash , source_name , source_right , lng_key )
2022-10-21 11:58:11 -04:00
source = config_get ( CONFIG , " cluster " , " display_name " , " " , lng_key ) . rsplit ( ' / ' , 1 ) [ - 1 ]
2023-04-25 01:15:17 -04:00
title_prefix = title_prefix . replace ( CONFIG [ " interface " ] [ " delimiter_output " ] + " cluster_source " + CONFIG [ " interface " ] [ " delimiter_output " ] , source )
title_prefix = title_prefix . replace ( CONFIG [ " interface " ] [ " delimiter_output " ] + " cluster_destination " + CONFIG [ " interface " ] [ " delimiter_output " ] , destination )
2022-10-21 11:58:11 -04:00
content_prefix = content_prefix . replace ( CONFIG [ " interface " ] [ " delimiter_output " ] + " cluster_source " + CONFIG [ " interface " ] [ " delimiter_output " ] , source )
content_prefix = content_prefix . replace ( CONFIG [ " interface " ] [ " delimiter_output " ] + " cluster_destination " + CONFIG [ " interface " ] [ " delimiter_output " ] , destination )
content_suffix = content_suffix . replace ( CONFIG [ " interface " ] [ " delimiter_output " ] + " cluster_source " + CONFIG [ " interface " ] [ " delimiter_output " ] , source )
content_suffix = content_suffix . replace ( CONFIG [ " interface " ] [ " delimiter_output " ] + " cluster_destination " + CONFIG [ " interface " ] [ " delimiter_output " ] , destination )
search = config_get ( CONFIG , " message " , " cluster_send_search " )
if search != " " :
content = content . replace ( search , config_get ( CONFIG , " message " , " cluster_send_replace " ) )
search = config_get ( CONFIG , " message " , " cluster_send_regex_search " )
if search != " " :
content = re . sub ( search , config_get ( CONFIG , " message " , " cluster_send_regex_replace " ) , content )
2022-12-07 11:05:23 -05:00
if CONFIG [ " message " ] . getboolean ( " fields " ) :
if message . fields :
2023-04-25 01:15:17 -04:00
fields = fields_remove ( message . fields , " fields_remove_anonymous " if " anonymous " in source_rights else " fields_remove " )
2022-12-07 11:05:23 -05:00
else :
fields = { }
else :
fields = { }
2023-04-25 01:15:17 -04:00
if CONFIG [ " main " ] . getboolean ( " fields_message " ) :
2023-11-17 13:37:31 -05:00
if not 0xA7 in fields :
fields [ 0xA7 ] = message . hash
if not " anonymous " in source_rights and 0xAF not in fields :
fields [ 0xAF ] = { }
fields [ 0xAF ] [ " h " ] = message . source_hash
fields [ 0xAF ] [ " n " ] = source_name
2022-10-21 11:58:11 -04:00
fields [ " c_n " ] = CONFIG [ " cluster " ] [ " name " ]
fields [ " c_t " ] = CONFIG [ " cluster " ] [ " type " ]
delimiter_input = CONFIG [ " interface " ] [ " delimiter_input " ]
if ( content . startswith ( delimiter_input + " pin " ) or content . startswith ( delimiter_input + " pins " ) ) and " cluster_pin_add " in source_rights :
content = content . lstrip ( delimiter_input + " pin " )
content = content . lstrip ( delimiter_input + " pins " )
fields [ " m_t " ] = " pin "
else :
fields [ " m_t " ] = " message "
2023-04-25 01:15:17 -04:00
title = title_prefix + title
2022-10-21 11:58:11 -04:00
content = content_prefix + content + content_suffix
if config_get ( CONFIG , " message " , " timestamp " , " " , lng_key ) == " client " :
timestamp = message . timestamp
else :
timestamp = time . time ( )
if CONFIG [ " statistic " ] . getboolean ( " enabled " ) :
if CONFIG [ " statistic " ] . getboolean ( " cluster " ) :
statistic ( " add " , " cluster_received_ " + message . desired_method_str )
if CONFIG [ " statistic " ] . getboolean ( " user " ) :
statistic ( " add " , source_hash )
statistic ( " value_set " , source_hash , " activity " , time . strftime ( " % Y- % m- %d % H: % M: % S " , time . localtime ( time . time ( ) ) ) )
statistic ( " value_set " , source_hash , " activity_receive " , time . strftime ( " % Y- % m- %d % H: % M: % S " , time . localtime ( time . time ( ) ) ) )
for val in destinations :
LXMF_CONNECTION . send ( key , content , title , fields , timestamp , " cluster_out " )
cluster_loop = False
if destination in config_get ( CONFIG , " cluster " , " display_name " , " " , lng_key ) . split ( " / " ) :
cluster_loop = True
2022-12-07 11:05:23 -05:00
if CONFIG [ " message " ] . getboolean ( " fields " ) :
if message . fields :
2023-04-25 01:15:17 -04:00
fields = fields_remove ( message . fields , " fields_remove_anonymous " if " anonymous " in source_rights else " fields_remove " )
2022-12-07 11:05:23 -05:00
else :
fields = { }
else :
fields = { }
2023-04-25 01:15:17 -04:00
if CONFIG [ " main " ] . getboolean ( " fields_message " ) :
if CONFIG [ " lxmf " ] [ " destination_type_conv " ] != " " :
2023-11-17 13:37:31 -05:00
fields [ 0xB3 ] = CONFIG [ " lxmf " ] . getint ( " destination_type_conv " )
if not 0xA7 in fields :
fields [ 0xA7 ] = message . hash
if not " anonymous " in source_rights and 0xAF not in fields :
fields [ 0xAF ] = { }
fields [ 0xAF ] [ " h " ] = message . source_hash
fields [ 0xAF ] [ " n " ] = source_name
2022-12-07 11:05:23 -05:00
2022-10-21 11:58:11 -04:00
for section in sections :
if " receive_cluster_send " in config_get ( CONFIG , " rights " , section ) . split ( " , " ) or ( cluster_loop and " receive_cluster_loop " in config_get ( CONFIG , " rights " , section ) . split ( " , " ) ) :
for ( key , val ) in DATA . items ( section ) :
if key != source_hash :
2022-12-07 11:05:23 -05:00
LXMF_CONNECTION . send ( key , content , title , fields , timestamp , " local_send " )
2022-10-21 11:58:11 -04:00
return
# Message - Local
if DATA [ " main " ] . getboolean ( " enabled_local " ) :
if " send_local " in source_rights :
length = config_getint ( CONFIG , " message " , " send_length_min " , 0 , lng_key )
if length > 0 :
if len ( content ) < length :
if " reply_length_min " in source_rights :
content_user = config_get ( CONFIG , " interface_messages " , " reply_length_min " , " " , lng_key )
content_user = replace ( content_user , source_hash , source_name , source_right , lng_key )
if content_user != " " :
2023-04-25 01:15:17 -04:00
LXMF_CONNECTION . send ( source_hash , content_user , " " , fields_generate ( lng_key ) , None , " interface_send " )
2022-10-21 11:58:11 -04:00
return
length = config_getint ( CONFIG , " message " , " send_length_max " , 0 , lng_key )
if length > 0 :
if len ( content ) > length :
if " reply_length_max " in source_rights :
content_user = config_get ( CONFIG , " interface_messages " , " reply_length_max " , " " , lng_key )
content_user = replace ( content_user , source_hash , source_name , source_right , lng_key )
if content_user != " " :
2023-04-25 01:15:17 -04:00
LXMF_CONNECTION . send ( source_hash , content_user , " " , fields_generate ( lng_key ) , None , " interface_send " )
2022-10-21 11:58:11 -04:00
return
2023-04-25 01:15:17 -04:00
title_prefix = config_get ( CONFIG , " message " , " send_title_prefix " , " " , lng_key )
2022-10-21 11:58:11 -04:00
content_prefix = config_get ( CONFIG , " message " , " send_prefix " , " " , lng_key )
content_suffix = config_get ( CONFIG , " message " , " send_suffix " , " " , lng_key )
2023-04-25 01:15:17 -04:00
if " anonymous " in source_rights :
title_prefix = replace ( title_prefix , " " , " " , source_right , lng_key )
content_prefix = replace ( content_prefix , " " , " " , source_right , lng_key )
content_suffix = replace ( content_suffix , " " , " " , source_right , lng_key )
else :
title_prefix = replace ( title_prefix , source_hash , source_name , source_right , lng_key )
content_prefix = replace ( content_prefix , source_hash , source_name , source_right , lng_key )
content_suffix = replace ( content_suffix , source_hash , source_name , source_right , lng_key )
2022-10-21 11:58:11 -04:00
search = config_get ( CONFIG , " message " , " send_search " )
if search != " " :
content = content . replace ( search , config_get ( CONFIG , " message " , " send_replace " ) )
search = config_get ( CONFIG , " message " , " send_regex_search " )
if search != " " :
content = re . sub ( search , config_get ( CONFIG , " message " , " send_regex_replace " ) , content )
2023-04-25 01:15:17 -04:00
title = title_prefix + title
2022-10-21 11:58:11 -04:00
content = content_prefix + content + content_suffix
2022-12-07 11:05:23 -05:00
if CONFIG [ " message " ] . getboolean ( " fields " ) :
if message . fields :
2023-04-25 01:15:17 -04:00
fields = fields_remove ( message . fields , " fields_remove_anonymous " if " anonymous " in source_rights else " fields_remove " )
2022-12-07 11:05:23 -05:00
else :
fields = { }
else :
fields = { }
2023-04-25 01:15:17 -04:00
if CONFIG [ " main " ] . getboolean ( " fields_message " ) :
if CONFIG [ " lxmf " ] [ " destination_type_conv " ] != " " :
2023-11-17 13:37:31 -05:00
fields [ 0xB3 ] = CONFIG [ " lxmf " ] . getint ( " destination_type_conv " )
if not 0xA7 in fields :
fields [ 0xA7 ] = message . hash
if not " anonymous " in source_rights and 0xAF not in fields :
fields [ 0xAF ] = { }
fields [ 0xAF ] [ " h " ] = message . source_hash
fields [ 0xAF ] [ " n " ] = source_name
2022-12-07 11:05:23 -05:00
2022-10-21 11:58:11 -04:00
if config_get ( CONFIG , " message " , " timestamp " , " " , lng_key ) == " client " :
timestamp = message . timestamp
else :
timestamp = time . time ( )
if CONFIG [ " statistic " ] . getboolean ( " enabled " ) :
if CONFIG [ " statistic " ] . getboolean ( " local " ) :
statistic ( " add " , " local_received_ " + message . desired_method_str )
if CONFIG [ " statistic " ] . getboolean ( " user " ) :
statistic ( " add " , source_hash )
statistic ( " value_set " , source_hash , " activity " , time . strftime ( " % Y- % m- %d % H: % M: % S " , time . localtime ( time . time ( ) ) ) )
statistic ( " value_set " , source_hash , " activity_receive " , time . strftime ( " % Y- % m- %d % H: % M: % S " , time . localtime ( time . time ( ) ) ) )
for section in sections :
if " receive_local " in config_get ( CONFIG , " rights " , section ) . split ( " , " ) :
for ( key , val ) in DATA . items ( section ) :
if key != source_hash :
2022-12-07 11:05:23 -05:00
LXMF_CONNECTION . send ( key , content , title , fields , timestamp , " local_send " )
2022-10-21 11:58:11 -04:00
return
else :
log ( " LXMF - Source " + RNS . prettyhexrep ( message . source_hash ) + " ' send ' not allowed " , LOG_DEBUG )
if " reply_local_right " in source_rights :
content_user = config_get ( CONFIG , " interface_messages " , " reply_local_right " , " " , lng_key )
content_user = replace ( content_user , source_hash , source_name , source_right , lng_key )
if content_user != " " :
2023-04-25 01:15:17 -04:00
LXMF_CONNECTION . send ( source_hash , content_user , " " , fields_generate ( lng_key ) , None , " interface_send " )
2022-10-21 11:58:11 -04:00
else :
if " reply_local_enabled " in source_rights :
content_user = config_get ( CONFIG , " interface_messages " , " reply_local_enabled " , " " , lng_key )
content_user = replace ( content_user , source_hash , source_name , source_right , lng_key )
if content_user != " " :
2023-04-25 01:15:17 -04:00
LXMF_CONNECTION . send ( source_hash , content_user , " " , fields_generate ( lng_key ) , None , " interface_send " )
2022-10-21 11:58:11 -04:00
return
#### LXMF - Notification ####
def lxmf_message_notification_success_callback ( message ) :
if CONFIG [ " statistic " ] . getboolean ( " enabled " ) :
if message . app_data . startswith ( " cluster " ) and CONFIG [ " statistic " ] . getboolean ( " cluster " ) :
statistic ( " add " , message . app_data + " _ " + message . desired_method_str + " _success " )
2022-10-22 05:50:19 -04:00
elif message . app_data . startswith ( " router " ) and CONFIG [ " statistic " ] . getboolean ( " router " ) :
statistic ( " add " , message . app_data + " _ " + message . desired_method_str + " _success " )
2022-10-21 11:58:11 -04:00
elif message . app_data . startswith ( " local " ) and CONFIG [ " statistic " ] . getboolean ( " local " ) :
statistic ( " add " , message . app_data + " _ " + message . desired_method_str + " _success " )
elif message . app_data . startswith ( " interface " ) and CONFIG [ " statistic " ] . getboolean ( " interface " ) :
statistic ( " add " , message . app_data + " _ " + message . desired_method_str + " _success " )
if CONFIG [ " statistic " ] . getboolean ( " user " ) :
if message . desired_method_str == " direct " :
destination_hash = RNS . hexrep ( message . destination_hash , False )
statistic ( " value_set " , destination_hash , " activity " , time . strftime ( " % Y- % m- %d % H: % M: % S " , time . localtime ( time . time ( ) ) ) )
statistic ( " value_set " , destination_hash , " activity_send " , time . strftime ( " % Y- % m- %d % H: % M: % S " , time . localtime ( time . time ( ) ) ) )
return
#### LXMF - Notification ####
def lxmf_message_notification_failed_callback ( message ) :
if CONFIG [ " statistic " ] . getboolean ( " enabled " ) :
if message . app_data . startswith ( " cluster " ) and CONFIG [ " statistic " ] . getboolean ( " cluster " ) :
statistic ( " add " , message . app_data + " _ " + message . desired_method_str + " _failed " )
2022-10-22 05:50:19 -04:00
elif message . app_data . startswith ( " router " ) and CONFIG [ " statistic " ] . getboolean ( " router " ) :
statistic ( " add " , message . app_data + " _ " + message . desired_method_str + " _failed " )
2022-10-21 11:58:11 -04:00
elif message . app_data . startswith ( " local " ) and CONFIG [ " statistic " ] . getboolean ( " local " ) :
statistic ( " add " , message . app_data + " _ " + message . desired_method_str + " _failed " )
elif message . app_data . startswith ( " interface " ) and CONFIG [ " statistic " ] . getboolean ( " interface " ) :
statistic ( " add " , message . app_data + " _ " + message . desired_method_str + " _failed " )
return
##############################################################################################################
# RNS Functions
class rns_announce_callback :
def __init__ ( self , aspect_filter = None ) :
self . aspect_filter = aspect_filter
@staticmethod
def received_announce ( destination_hash , announced_identity , app_data ) :
if app_data != None :
log ( " Cluster - Received an announce from " + RNS . prettyhexrep ( destination_hash ) + " : " + app_data . decode ( " utf-8 " ) , LOG_INFO )
global DATA
lng_key = " - " + CONFIG [ " main " ] [ " lng " ]
sections = [ ]
for ( key , val ) in CONFIG . items ( " rights " ) :
if DATA . has_section ( key ) :
sections . append ( key )
receive = app_data . decode ( " utf-8 " )
if receive != " " :
receive = json . loads ( receive )
2022-10-22 05:50:19 -04:00
executed = False
2022-10-21 11:58:11 -04:00
2022-10-22 05:50:19 -04:00
if " h " in receive and " c " in receive and " c_n " in receive and CONFIG [ " cluster " ] . getboolean ( " enabled " ) and DATA [ " main " ] . getboolean ( " auto_add_cluster " ) :
2022-10-21 11:58:11 -04:00
if receive [ " c " ] == " 1 " :
2022-10-22 05:50:19 -04:00
if not DATA . has_option ( " cluster " , receive [ " h " ] ) :
2022-10-21 11:58:11 -04:00
content_group = config_get ( CONFIG , " interface_messages " , " cluster_join " , " " , lng_key )
2022-10-22 05:50:19 -04:00
content_group = replace ( content_group , receive [ " h " ] , receive [ " c_n " ] , " " , lng_key )
2022-10-21 11:58:11 -04:00
if content_group != " " :
for section in sections :
if " receive_cluster_join " in config_get ( CONFIG , " rights " , section ) . split ( " , " ) :
for ( key , val ) in DATA . items ( section ) :
2023-04-25 01:15:17 -04:00
LXMF_CONNECTION . send ( key , content_group , " " , fields_generate ( lng_key ) , None , " interface_send " )
2022-10-22 05:50:19 -04:00
DATA [ " cluster " ] [ receive [ " h " ] ] = receive [ " c_n " ]
executed = True
2022-10-21 11:58:11 -04:00
2022-10-22 05:50:19 -04:00
if " h " in receive and " r " in receive and " r_n " in receive and CONFIG [ " router " ] . getboolean ( " enabled " ) and DATA [ " main " ] . getboolean ( " auto_add_router " ) :
if receive [ " r " ] == " 1 " :
DATA [ " router " ] [ receive [ " h " ] ] = receive [ " r_n " ]
executed = True
2022-10-21 11:58:11 -04:00
2022-10-22 05:50:19 -04:00
if executed :
if CONFIG [ " main " ] . getboolean ( " auto_save_data " ) :
DATA . remove_option ( " main " , " unsaved " )
if not data_save ( PATH + " /data.cfg " ) :
2022-10-21 11:58:11 -04:00
DATA [ " main " ] [ " unsaved " ] = " True "
2022-10-22 05:50:19 -04:00
else :
DATA [ " main " ] [ " unsaved " ] = " True "
2022-10-21 11:58:11 -04:00
##############################################################################################################
# Interface
#### Interface #####
2023-04-25 01:15:17 -04:00
def interface ( cmd , source_hash , source_name , source_right , source_rights , lng_key , message ) :
2022-10-21 11:58:11 -04:00
cmd = cmd . strip ( )
content = " "
delimiter = CONFIG [ " interface " ] [ " delimiter_output " ]
sections = [ ]
for ( key , val ) in CONFIG . items ( " rights " ) :
if DATA . has_section ( key ) :
sections . append ( key )
# "/help" command.
if ( cmd == " help " or cmd == " ? " ) and " help " in source_rights :
content = config_get ( CONFIG , " interface_menu " , " help_ " + source_right , " " , lng_key )
interface_help = " "
interface_help_command = " "
for value in source_rights :
interface_help = interface_help + config_get ( CONFIG , " interface_help " , value , " " , lng_key )
interface_help_command = interface_help_command + config_get ( CONFIG , " interface_help_command " , value , " " , lng_key )
content = content . replace ( delimiter + " interface_help " + delimiter , interface_help )
content = content . replace ( delimiter + " interface_help_command " + delimiter , interface_help_command )
content = replace ( content , source_hash , source_name , source_right , lng_key )
2023-04-25 01:15:17 -04:00
# "/update" command.
elif ( cmd == " update " ) and " update " in source_rights :
try :
content = config_get ( CONFIG , " interface_menu " , " update_ok " , " " , lng_key )
LXMF_CONNECTION . send ( source_hash , content , " " , fields_generate ( lng_key , m = True , d = True , r = True , cmd = source_right , config = source_right , tpl = " update " ) , None , " interface_send " )
content = " "
except :
content = config_get ( CONFIG , " interface_menu " , " update_error " , " " , lng_key )
2023-06-05 08:36:42 -04:00
# "/update_all" command.
elif ( cmd == " update_all " ) and " update_all " in source_rights :
try :
content = config_get ( CONFIG , " interface_menu " , " update_all_ok " , " " , lng_key )
for section in sections :
for ( key , val ) in DATA . items ( section ) :
LXMF_CONNECTION . send ( key , content , " " , fields_generate ( lng_key , m = True , d = True , r = True , cmd = section , config = section , tpl = " update " ) , None , " interface_send " )
content = " "
except :
content = config_get ( CONFIG , " interface_menu " , " update_all_error " , " " , lng_key )
2023-04-25 01:15:17 -04:00
# "/join" command.
elif ( cmd == " join " or cmd == " subscribe " ) and " join " in source_rights :
try :
content = config_get ( CONFIG , " interface_messages " , " auto_add_ " + source_right , " " , lng_key )
content = replace ( content , source_hash , source_name , source_right , lng_key )
if content != " " :
LXMF_CONNECTION . send ( source_hash , content , " " , fields_generate ( lng_key , m = True , d = True , r = True , cmd = source_right , config = source_right , tpl = " info " ) , None , " interface_send " )
content = " "
except :
content = config_get ( CONFIG , " interface_menu " , " join_error " , " " , lng_key )
2022-10-21 11:58:11 -04:00
# "/leave" command.
2023-04-25 01:15:17 -04:00
elif ( cmd == " leave " or cmd == " unsubscribe " or cmd == " part " ) and " leave " in source_rights :
2022-10-21 11:58:11 -04:00
try :
for section in sections :
for ( key , val ) in DATA . items ( section ) :
if key == source_hash :
DATA . remove_option ( section , key )
if CONFIG [ " statistic " ] . getboolean ( " enabled " ) :
statistic ( " del " , key )
content_group = config_get ( CONFIG , " interface_messages " , " member_leave " , " " , lng_key )
content_group = replace ( content_group , source_hash , source_name , source_right , lng_key )
if content_group != " " :
2023-04-25 01:15:17 -04:00
fields = fields_generate ( lng_key , h = message . source_hash , n = source_name , m = True , tpl = " leave " )
2022-10-21 11:58:11 -04:00
for section in sections :
if " receive_leave " in config_get ( CONFIG , " rights " , section ) . split ( " , " ) :
for ( key , val ) in DATA . items ( section ) :
2023-04-25 01:15:17 -04:00
LXMF_CONNECTION . send ( key , content_group , " " , fields , None , " interface_send " )
2022-10-21 11:58:11 -04:00
content = config_get ( CONFIG , " interface_menu " , " leave_ok " , " " , lng_key )
2023-04-25 01:15:17 -04:00
content = replace ( content , source_hash , source_name , source_right , lng_key )
if content != " " :
2023-11-17 13:37:31 -05:00
LXMF_CONNECTION . send ( source_hash , content , " " , { 0xA3 : None , 0xB1 : " info " } , None , " interface_send " )
2023-04-25 01:15:17 -04:00
content = " "
2022-10-21 11:58:11 -04:00
if CONFIG [ " main " ] . getboolean ( " auto_save_data " ) :
DATA . remove_option ( " main " , " unsaved " )
if not data_save ( PATH + " /data.cfg " ) :
DATA [ " main " ] [ " unsaved " ] = " True "
else :
DATA [ " main " ] [ " unsaved " ] = " True "
except :
content = config_get ( CONFIG , " interface_menu " , " leave_error " , " " , lng_key )
# "/name" command.
elif ( cmd == " name " or cmd == " nick " ) and " name " in source_rights :
content = config_get ( CONFIG , " interface_menu " , " name " , " " , lng_key )
content = replace ( content , source_hash , source_name , source_right , lng_key )
elif ( cmd . startswith ( " name " ) or cmd . startswith ( " nick " ) or cmd . startswith ( " setname " ) ) and " name " in source_rights :
try :
cmd , value = cmd . split ( " " , 1 )
for section in sections :
for ( key , val ) in DATA . items ( section ) :
if key == source_hash :
DATA [ section ] [ key ] = value
if source_name == " " :
content_type = " name_def "
content_add = " " + value
else :
content_type = " name_change "
content_add = " " + source_name + " -> " + value
content_group = config_get ( CONFIG , " interface_messages " , " member_ " + content_type , " " , lng_key )
if content_group != " " :
2023-04-25 01:15:17 -04:00
fields = fields_generate ( lng_key , h = message . source_hash , n = source_name , tpl = content_type )
2022-10-21 11:58:11 -04:00
content_group = replace ( content_group , source_hash , source_name , source_right , lng_key )
content_group = content_group + content_add
for section in sections :
if " receive_ " + content_type in config_get ( CONFIG , " rights " , section ) . split ( " , " ) :
for ( key , val ) in DATA . items ( section ) :
if key != source_hash :
2023-04-25 01:15:17 -04:00
LXMF_CONNECTION . send ( key , content_group , " " , fields , None , " interface_send " )
2022-10-21 11:58:11 -04:00
content = config_get ( CONFIG , " interface_menu " , " name_ok " , " " , lng_key ) + " " + value
if CONFIG [ " main " ] . getboolean ( " auto_save_data " ) :
DATA . remove_option ( " main " , " unsaved " )
if not data_save ( PATH + " /data.cfg " ) :
DATA [ " main " ] [ " unsaved " ] = " True "
else :
DATA [ " main " ] [ " unsaved " ] = " True "
except :
content = config_get ( CONFIG , " interface_menu " , " name_error " , " " , lng_key )
# "/address" command.
elif cmd == " address " and " address " in source_rights :
content = config_get ( CONFIG , " interface_menu " , " address_ " + source_right , " " , lng_key )
content = replace ( content , source_hash , source_name , source_right , lng_key )
# "/info" command.
elif cmd == " info " and " info " in source_rights :
content = config_get ( CONFIG , " interface_menu " , " info_ " + source_right , " " , lng_key )
content = replace ( content , source_hash , source_name , source_right , lng_key )
# "/pin" command.
elif ( cmd == " pin " or cmd == " pins " ) and " pin " in source_rights :
count = 0
content = config_get ( CONFIG , " interface_menu " , " pin_header " , " " , lng_key )
content = replace ( content , source_hash , source_name , source_right , lng_key )
for ( key , val ) in DATA . items ( " pin " ) :
count + = 1
content = content + " # " + key + " \n " + val + " \n \n "
content = content . replace ( delimiter + " count " + delimiter , str ( count ) )
elif ( cmd . startswith ( " pin " ) or cmd . startswith ( " pins " ) ) and " pin_add " in source_rights :
try :
cmd , value = cmd . split ( " " , 1 )
value_new = config_get ( CONFIG , " interface_menu " , " pin " , " " , lng_key )
value_new = replace ( value_new , source_hash , source_name , source_right , lng_key )
value_new = value_new . replace ( delimiter + " value " + delimiter , value )
key = time . strftime ( config_get ( CONFIG , " message " , " pin_id " , " % y % m %d - % H % M % S " , lng_key ) , time . localtime ( time . time ( ) ) )
if DATA . has_option ( " pin " , key ) :
key = key + " - "
key_int = 0
while DATA . has_option ( " pin " , key + str ( key_int ) ) :
key_int + = 1
key = key + str ( key_int )
DATA [ " pin " ] [ key ] = value_new
content_group = config_get ( CONFIG , " interface_messages " , " pin_add " , " " , lng_key )
content_group = replace ( content_group , source_hash , source_name , source_right , lng_key )
content_group = content_group . replace ( delimiter + " key " + delimiter , key )
content_group = content_group . replace ( delimiter + " value " + delimiter , value_new )
if content_group != " " :
for section in sections :
if " receive_pin_add " in config_get ( CONFIG , " rights " , section ) . split ( " , " ) :
for ( key , val ) in DATA . items ( section ) :
if key != source_hash :
2023-04-25 01:15:17 -04:00
LXMF_CONNECTION . send ( key , content_group , " " , fields_generate ( lng_key , h = message . source_hash , n = source_name ) , None , " interface_send " )
2022-10-21 11:58:11 -04:00
content = config_get ( CONFIG , " interface_menu " , " pin_add_ok " , " " , lng_key )
if CONFIG [ " main " ] . getboolean ( " auto_save_data " ) :
DATA . remove_option ( " main " , " unsaved " )
if not data_save ( PATH + " /data.cfg " ) :
DATA [ " main " ] [ " unsaved " ] = " True "
else :
DATA [ " main " ] [ " unsaved " ] = " True "
except :
content = config_get ( CONFIG , " interface_menu " , " cmd_error " , " " , lng_key )
elif ( cmd . startswith ( " unpin " ) or cmd . startswith ( " unpins " ) ) and " pin_remove " in source_rights :
try :
cmd , key = cmd . split ( " " , 1 )
if key . startswith ( " # " ) :
key = key [ 1 : ]
if DATA . has_option ( " pin " , key ) :
value = DATA [ " pin " ] [ key ]
DATA . remove_option ( " pin " , key )
content_group = config_get ( CONFIG , " interface_messages " , " pin_remove " , " " , lng_key )
content_group = replace ( content_group , source_hash , source_name , source_right , lng_key )
content_group = content_group . replace ( delimiter + " key " + delimiter , key )
content_group = content_group . replace ( delimiter + " value " + delimiter , value )
if content_group != " " :
for section in sections :
if " receive_pin_add " in config_get ( CONFIG , " rights " , section ) . split ( " , " ) :
for ( key , val ) in DATA . items ( section ) :
if key != source_hash :
2023-04-25 01:15:17 -04:00
LXMF_CONNECTION . send ( key , content_group , " " , fields_generate ( lng_key , h = message . source_hash , n = source_name ) , None , " interface_send " )
2022-10-21 11:58:11 -04:00
content = config_get ( CONFIG , " interface_menu " , " pin_remove_ok " , " " , lng_key )
if CONFIG [ " main " ] . getboolean ( " auto_save_data " ) :
DATA . remove_option ( " main " , " unsaved " )
if not data_save ( PATH + " /data.cfg " ) :
DATA [ " main " ] [ " unsaved " ] = " True "
else :
DATA [ " main " ] [ " unsaved " ] = " True "
else :
content = config_get ( CONFIG , " interface_menu " , " pin_found_error " , " " , lng_key )
except :
content = config_get ( CONFIG , " interface_menu " , " cmd_error " , " " , lng_key )
# "/version" command.
elif cmd == " version " and " version " in source_rights :
content = config_get ( CONFIG , " interface_menu " , " version_header " , " " , lng_key )
content = replace ( content , source_hash , source_name , source_right , lng_key )
content = content + NAME + " \n " + DESCRIPTION + " \n V " + VERSION
# "/groups" command.
elif ( cmd == " groups " or cmd == " group " or cmd == " cluster " ) and " groups " in source_rights :
count = 0
content = config_get ( CONFIG , " interface_menu " , " groups_header " , " " , lng_key )
content = replace ( content , source_hash , source_name , source_right , lng_key )
content_member = config_get ( CONFIG , " interface_menu " , " groups_member " , " " , lng_key )
data_dict = defaultdict ( dict )
section = " cluster "
for ( key , val ) in DATA . items ( section ) :
data_dict [ val ] = key
for key in sorted ( data_dict ) :
count + = 1
content = content + replace ( content_member , data_dict [ key ] , key , section , lng_key )
content = content . replace ( delimiter + " count " + delimiter , str ( count ) )
elif ( cmd . startswith ( " groups " ) or cmd . startswith ( " group " ) or cmd . startswith ( " cluster " ) ) and " groups " in source_rights :
try :
cmd , value = cmd . split ( " " , 1 )
executed = False
count = 0
content = config_get ( CONFIG , " interface_menu " , " groups_search_header " , " " , lng_key )
content = replace ( content , source_hash , source_name , source_right , lng_key )
content_member = config_get ( CONFIG , " interface_menu " , " groups_search_member " , " " , lng_key )
data_dict = defaultdict ( dict )
section = " cluster "
for ( key , val ) in DATA . items ( section ) :
if value in val :
executed = True
data_dict [ val ] = key
for key in sorted ( data_dict ) :
count + = 1
content = content + replace ( content_member , data_dict [ key ] , key , section , lng_key )
content = content . replace ( delimiter + " count " + delimiter , str ( count ) )
if not executed :
content = config_get ( CONFIG , " interface_menu " , " groups_search_found_error " , " " , lng_key )
except :
content = config_get ( CONFIG , " interface_menu " , " cmd_error " , " " , lng_key )
# "/members" command.
elif ( cmd == " members " or cmd == " member " or cmd == " names " or cmd == " who " ) and " members " in source_rights :
count = 0
content = config_get ( CONFIG , " interface_menu " , " members_header " , " " , lng_key )
content = replace ( content , source_hash , source_name , source_right , lng_key )
content_member = config_get ( CONFIG , " interface_menu " , " members_member " , " " , lng_key )
for section in sections :
for ( key , val ) in DATA . items ( section ) :
count + = 1
content = content + replace ( content_member , key , val , section , lng_key )
content = content . replace ( delimiter + " count " + delimiter , str ( count ) )
# "/search" command.
elif ( cmd . startswith ( " search " ) or cmd . startswith ( " whois " ) or cmd . startswith ( " w " ) ) and " search " in source_rights :
try :
cmd , value = cmd . split ( " " , 1 )
executed = False
count = 0
content = config_get ( CONFIG , " interface_menu " , " search_header " , " " , lng_key )
content = replace ( content , source_hash , source_name , source_right , lng_key )
content_member = config_get ( CONFIG , " interface_menu " , " search_member " , " " , lng_key )
for section in sections :
for ( key , val ) in DATA . items ( section ) :
if fnmatch . fnmatch ( key , value ) or fnmatch . fnmatch ( val , value ) :
executed = True
count + = 1
content = content + replace ( content_member , key , val , section , lng_key ) . replace ( delimiter + " activity_receive " + delimiter , statistic_value_get ( key , " activity_receive " ) ) . replace ( delimiter + " activity_send " + delimiter , statistic_value_get ( key , " activity_send " ) )
content = content . replace ( delimiter + " count " + delimiter , str ( count ) )
if not executed :
content = config_get ( CONFIG , " interface_menu " , " search_found_error " , " " , lng_key )
except :
content = config_get ( CONFIG , " interface_menu " , " cmd_error " , " " , lng_key )
# "/activitys" command.
elif ( cmd == " activitys " or cmd == " activity " ) and " activitys " in source_rights :
count = 0
content = config_get ( CONFIG , " interface_menu " , " activitys_header " , " " , lng_key )
content = replace ( content , source_hash , source_name , source_right , lng_key )
content_member = config_get ( CONFIG , " interface_menu " , " activitys_member " , " " , lng_key )
for section in sections :
for ( key , val ) in DATA . items ( section ) :
count + = 1
content = content + replace ( content_member , key , val , section , lng_key ) . replace ( delimiter + " activity_receive " + delimiter , statistic_value_get ( key , " activity_receive " ) ) . replace ( delimiter + " activity_send " + delimiter , statistic_value_get ( key , " activity_send " ) )
content = content . replace ( delimiter + " count " + delimiter , str ( count ) )
# "/statistic" command.
elif ( cmd == " statistic " or cmd == " stat " or cmd == " stats " or cmd . startswith ( " statistic " ) or cmd . startswith ( " stat " ) or cmd . startswith ( " stats " ) ) and " statistic " in source_rights :
try :
cmd , value = cmd . split ( " " , 1 )
except :
value = " day "
values = [ " day " , " last_day " , " week " , " last_week " , " month " , " last_month " , " year " , " last_year " , " all " , " max " ]
if value in values :
if CONFIG [ " statistic " ] . getboolean ( " enabled " ) and CONFIG [ " statistic " ] . getboolean ( " cluster " ) and " statistic_cluster " in source_rights and ( " statistic_min " in source_rights or " statistic_full " in source_rights ) :
content = content + replace ( config_get ( CONFIG , " interface_menu " , " statistic_header_cluster " , " " , lng_key ) , source_hash , source_name , source_right , lng_key ) . replace ( delimiter + " value " + delimiter , value )
if " statistic_min " in source_rights :
statistic_recalculate ( " cluster_received_direct " )
statistic_recalculate ( " cluster_received_propagated " )
statistic_recalculate ( " cluster_send_direct_success " )
statistic_recalculate ( " cluster_send_propagated_success " )
statistic_recalculate ( " cluster_send_direct_failed " )
statistic_recalculate ( " cluster_send_propagated_failed " )
statistic_recalculate ( " cluster_in_direct " )
statistic_recalculate ( " cluster_in_propagated " )
statistic_recalculate ( " cluster_out_direct_success " )
statistic_recalculate ( " cluster_out_propagated_success " )
statistic_recalculate ( " cluster_out_direct_failed " )
statistic_recalculate ( " cluster_out_propagated_failed " )
content = content + " #Received: " + statistic_value_get ( " cluster_received_direct " , value + " _value " , " 0 " ) + " d/ " + statistic_value_get ( " cluster_received_propagated " , value + " _value " , " 0 " ) + " p \n "
content = content + " #Send OK: " + statistic_value_get ( " cluster_send_direct_success " , value + " _value " , " 0 " ) + " d/ " + statistic_value_get ( " cluster_send_propagated_success " , value + " _value " , " 0 " ) + " p \n "
content = content + " #Send Failed: " + statistic_value_get ( " cluster_send_direct_failed " , value + " _value " , " 0 " ) + " d/ " + statistic_value_get ( " cluster_send_propagated_failed " , value + " _value " , " 0 " ) + " p \n "
content = content + " #In: " + statistic_value_get ( " cluster_in_direct " , value + " _value " , " 0 " ) + " d/ " + statistic_value_get ( " cluster_in_propagated " , value + " _value " , " 0 " ) + " p \n "
content = content + " #Out OK: " + statistic_value_get ( " cluster_out_direct_success " , value + " _value " , " 0 " ) + " d/ " + statistic_value_get ( " cluster_out_propagated_success " , value + " _value " , " 0 " ) + " p \n "
content = content + " #Out Failed: " + statistic_value_get ( " cluster_out_direct_failed " , value + " _value " , " 0 " ) + " d/ " + statistic_value_get ( " cluster_out_propagated_failed " , value + " _value " , " 0 " ) + " p \n \n "
if " statistic_full " in source_rights :
content = content + " #Received - Direct: \n " + statistic_get ( " cluster_received_direct " ) + " \n \n "
content = content + " #Received - Propagated: \n " + statistic_get ( " cluster_received_propagated " ) + " \n \n "
content = content + " #Send - Direct - Success: \n " + statistic_get ( " cluster_send_direct_success " ) + " \n \n "
content = content + " #Send - Propagated - Success: \n " + statistic_get ( " cluster_send_propagated_success " ) + " \n \n "
content = content + " #Send - Direct - Failed: \n " + statistic_get ( " cluster_send_direct_failed " ) + " \n \n "
content = content + " #Send - Propagated - Failed: \n " + statistic_get ( " cluster_send_propagated_failed " ) + " \n \n "
content = content + " #In - Direct: \n " + statistic_get ( " cluster_in_direct " ) + " \n \n "
content = content + " #In - Propagated: \n " + statistic_get ( " cluster_in_propagated " ) + " \n \n "
content = content + " #Out - Direct - Success: \n " + statistic_get ( " cluster_out_direct_success " ) + " \n \n "
content = content + " #Out - Propagated - Success: \n " + statistic_get ( " cluster_out_propagated_success " ) + " \n \n "
content = content + " #Out - Direct - Failed: \n " + statistic_get ( " cluster_out_direct_failed " ) + " \n \n "
content = content + " #Out - Propagated - Failed: \n " + statistic_get ( " cluster_out_propagated_failed " ) + " \n \n "
2022-10-22 05:50:19 -04:00
if CONFIG [ " statistic " ] . getboolean ( " enabled " ) and CONFIG [ " statistic " ] . getboolean ( " router " ) and " statistic_router " in source_rights and ( " statistic_min " in source_rights or " statistic_full " in source_rights ) :
content = content + replace ( config_get ( CONFIG , " interface_menu " , " statistic_header_router " , " " , lng_key ) , source_hash , source_name , source_right , lng_key ) . replace ( delimiter + " value " + delimiter , value )
if " statistic_min " in source_rights :
statistic_recalculate ( " router_in_direct " )
statistic_recalculate ( " router_in_propagated " )
statistic_recalculate ( " router_out_direct_success " )
statistic_recalculate ( " router_out_propagated_success " )
statistic_recalculate ( " router_out_direct_failed " )
statistic_recalculate ( " router_out_propagated_failed " )
content = content + " #In: " + statistic_value_get ( " router_in_direct " , value + " _value " , " 0 " ) + " d/ " + statistic_value_get ( " router_in_propagated " , value + " _value " , " 0 " ) + " p \n "
content = content + " #Out OK: " + statistic_value_get ( " router_out_direct_success " , value + " _value " , " 0 " ) + " d/ " + statistic_value_get ( " router_out_propagated_success " , value + " _value " , " 0 " ) + " p \n "
content = content + " #Out Failed: " + statistic_value_get ( " router_out_direct_failed " , value + " _value " , " 0 " ) + " d/ " + statistic_value_get ( " router_out_propagated_failed " , value + " _value " , " 0 " ) + " p \n \n "
if " statistic_full " in source_rights :
content = content + " #In - Direct: \n " + statistic_get ( " router_in_direct " ) + " \n \n "
content = content + " #In - Propagated: \n " + statistic_get ( " router_in_propagated " ) + " \n \n "
content = content + " #Out - Direct - Success: \n " + statistic_get ( " router_out_direct_success " ) + " \n \n "
content = content + " #Out - Propagated - Success: \n " + statistic_get ( " router_out_propagated_success " ) + " \n \n "
content = content + " #Out - Direct - Failed: \n " + statistic_get ( " router_out_direct_failed " ) + " \n \n "
content = content + " #Out - Propagated - Failed: \n " + statistic_get ( " router_out_propagated_failed " ) + " \n \n "
2022-10-21 11:58:11 -04:00
if CONFIG [ " statistic " ] . getboolean ( " enabled " ) and CONFIG [ " statistic " ] . getboolean ( " local " ) and " statistic_local " in source_rights and ( " statistic_min " in source_rights or " statistic_full " in source_rights ) :
content = content + replace ( config_get ( CONFIG , " interface_menu " , " statistic_header_local " , " " , lng_key ) , source_hash , source_name , source_right , lng_key ) . replace ( delimiter + " value " + delimiter , value )
if " statistic_min " in source_rights :
statistic_recalculate ( " local_received_direct " )
statistic_recalculate ( " local_received_propagated " )
statistic_recalculate ( " local_send_direct_success " )
statistic_recalculate ( " local_send_propagated_success " )
statistic_recalculate ( " local_send_direct_failed " )
statistic_recalculate ( " local_send_propagated_failed " )
content = content + " #Received: " + statistic_value_get ( " local_received_direct " , value + " _value " , " 0 " ) + " d/ " + statistic_value_get ( " local_received_propagated " , value + " _value " , " 0 " ) + " p \n "
content = content + " #Send OK: " + statistic_value_get ( " local_send_direct_success " , value + " _value " , " 0 " ) + " d/ " + statistic_value_get ( " local_send_propagated_success " , value + " _value " , " 0 " ) + " p \n "
content = content + " #Send Failed: " + statistic_value_get ( " local_send_direct_failed " , value + " _value " , " 0 " ) + " d/ " + statistic_value_get ( " local_send_propagated_failed " , value + " _value " , " 0 " ) + " p \n \n "
if " statistic_full " in source_rights :
content = content + " #Received - Direct: \n " + statistic_get ( " local_received_direct " ) + " \n \n "
content = content + " #Received - Propagated: \n " + statistic_get ( " local_received_propagated " ) + " \n \n "
content = content + " #Send - Direct - Success: \n " + statistic_get ( " local_send_direct_success " ) + " \n \n "
content = content + " #Send - Propagated - Success: \n " + statistic_get ( " local_send_propagated_success " ) + " \n \n "
content = content + " #Send - Direct - Failed: \n " + statistic_get ( " local_send_direct_failed " ) + " \n \n "
content = content + " #Send - Propagated - Failed: \n " + statistic_get ( " local_send_propagated_failed " ) + " \n \n "
if CONFIG [ " statistic " ] . getboolean ( " enabled " ) and CONFIG [ " statistic " ] . getboolean ( " interface " ) and " statistic_interface " in source_rights and ( " statistic_min " in source_rights or " statistic_full " in source_rights ) :
content = content + replace ( config_get ( CONFIG , " interface_menu " , " statistic_header_interface " , " " , lng_key ) , source_hash , source_name , source_right , lng_key ) . replace ( delimiter + " value " + delimiter , value )
if " statistic_min " in source_rights :
statistic_recalculate ( " interface_received_direct " )
statistic_recalculate ( " interface_received_propagated " )
statistic_recalculate ( " interface_send_direct_success " )
statistic_recalculate ( " interface_send_propagated_success " )
statistic_recalculate ( " interface_send_direct_failed " )
statistic_recalculate ( " interface_send_propagated_failed " )
content = content + " #Received: " + statistic_value_get ( " local_received_direct " , value + " _value " , " 0 " ) + " d/ " + statistic_value_get ( " local_received_propagated " , value + " _value " , " 0 " ) + " p \n "
content = content + " #Send OK: " + statistic_value_get ( " interface_send_direct_success " , value + " _value " , " 0 " ) + " d/ " + statistic_value_get ( " interface_send_propagated_success " , value + " _value " , " 0 " ) + " p \n "
content = content + " #Send Failed: " + statistic_value_get ( " interface_send_direct_failed " , value + " _value " , " 0 " ) + " d/ " + statistic_value_get ( " interface_send_propagated_failed " , value + " _value " , " 0 " ) + " p \n \n "
if " statistic_full " in source_rights :
content = content + " #Received - Direct: \n " + statistic_get ( " interface_received_direct " ) + " \n \n "
content = content + " #Received - Propagated: \n " + statistic_get ( " interface_received_propagated " ) + " \n \n "
content = content + " #Send - Direct - Success: \n " + statistic_get ( " interface_send_direct_success " ) + " \n \n "
content = content + " #Send - Propagated - Success: \n " + statistic_get ( " interface_send_propagated_success " ) + " \n \n "
content = content + " #Send - Direct - Failed: \n " + statistic_get ( " interface_send_direct_failed " ) + " \n \n "
content = content + " #Send - Propagated - Failed: \n " + statistic_get ( " interface_send_propagated_failed " ) + " \n \n "
if CONFIG [ " statistic " ] . getboolean ( " enabled " ) and CONFIG [ " statistic " ] . getboolean ( " user " ) and " statistic_self " in source_rights and ( " statistic_min " in source_rights or " statistic_full " in source_rights ) :
content = content + replace ( config_get ( CONFIG , " interface_menu " , " statistic_header_self " , " " , lng_key ) , source_hash , source_name , source_right , lng_key ) . replace ( delimiter + " value " + delimiter , value )
if " statistic_min " in source_rights or " statistic_full " in source_rights :
content = content + statistic_get ( source_hash ) + " \n \n "
if CONFIG [ " statistic " ] . getboolean ( " enabled " ) and CONFIG [ " statistic " ] . getboolean ( " user " ) and " statistic_user " in source_rights and ( " statistic_min " in source_rights or " statistic_full " in source_rights ) :
content = content + replace ( config_get ( CONFIG , " interface_menu " , " statistic_header_user " , " " , lng_key ) , source_hash , source_name , source_right , lng_key ) . replace ( delimiter + " value " + delimiter , value )
for section in STATISTIC . sections ( ) :
if section != " main " and not section . startswith ( " cluster " ) and not section . startswith ( " local " ) and not section . startswith ( " interface " ) :
if " statistic_min " in source_rights :
statistic_recalculate ( section )
content = " < " + section + " >: " + statistic_value_get ( section , value + " _value " ) + " \n "
if " statistic_full " in source_rights :
content = " < " + section + " >: \n " + statistic_get ( section ) + " \n \n "
else :
content = config_get ( CONFIG , " interface_menu " , " statistic_found_error " , " " , lng_key )
# "/status" command.
elif cmd == " status " and " status " in source_rights :
content = config_get ( CONFIG , " interface_menu " , " status_ " + source_right , " " , lng_key )
content = replace ( content , source_hash , source_name , source_right , lng_key )
content = content . replace ( delimiter + " enabled_local " + delimiter , DATA [ " main " ] [ " enabled_local " ] )
content = content . replace ( delimiter + " enabled_cluster " + delimiter , DATA [ " main " ] [ " enabled_cluster " ] )
# "/delivery" command.
#elif cmd == "delivery" and "delivery" in source_rights:
2023-04-25 01:15:17 -04:00
# TODO
2022-10-21 11:58:11 -04:00
# "/enable_local" command.
elif cmd == " enable_local " and " enable_local " in source_rights :
if DATA [ " main " ] . getboolean ( " enabled_local " ) :
content = config_get ( CONFIG , " interface_menu " , " enable_local_true " , " " , lng_key )
else :
content = config_get ( CONFIG , " interface_menu " , " enable_local_false " , " " , lng_key )
elif cmd . startswith ( " enable_local " ) and " enable_local " in source_rights :
try :
cmd , value = cmd . split ( " " , 1 )
if val_to_bool ( value ) :
DATA [ " main " ] [ " enabled_local " ] = " True "
content = config_get ( CONFIG , " interface_menu " , " enable_local_true " , " " , lng_key )
DATA [ " main " ] [ " unsaved_local " ] = " True "
else :
DATA [ " main " ] [ " enabled_local " ] = " False "
content = config_get ( CONFIG , " interface_menu " , " enable_local_false " , " " , lng_key )
DATA [ " main " ] [ " unsaved " ] = " True "
except :
content = config_get ( CONFIG , " interface_menu " , " enable_local_error " , " " , lng_key )
# "/enable_cluster" command.
elif cmd == " enable_cluster " and " enable_cluster " in source_rights :
if DATA [ " main " ] . getboolean ( " enabled_cluster " ) :
content = config_get ( CONFIG , " interface_menu " , " enable_cluster_true " , " " , lng_key )
else :
content = config_get ( CONFIG , " interface_menu " , " enable_cluster_false " , " " , lng_key )
elif cmd . startswith ( " enable_cluster " ) and " enable_cluster " in source_rights :
try :
cmd , value = cmd . split ( " " , 1 )
if val_to_bool ( value ) :
DATA [ " main " ] [ " enabled_cluster " ] = " True "
content = config_get ( CONFIG , " interface_menu " , " enable_cluster_true " , " " , lng_key )
DATA [ " main " ] [ " unsaved_cluster " ] = " True "
else :
DATA [ " main " ] [ " enabled_cluster " ] = " False "
content = config_get ( CONFIG , " interface_menu " , " enable_cluster_false " , " " , lng_key )
DATA [ " main " ] [ " unsaved " ] = " True "
except :
content = config_get ( CONFIG , " interface_menu " , " enable_cluster_error " , " " , lng_key )
# "/auto_add_user" command.
elif cmd == " auto_add_user " and " auto_add_user " in source_rights :
if DATA [ " main " ] . getboolean ( " auto_add_user " ) :
content = config_get ( CONFIG , " interface_menu " , " auto_add_user_true " , " " , lng_key )
else :
content = config_get ( CONFIG , " interface_menu " , " auto_add_user_false " , " " , lng_key )
elif cmd . startswith ( " auto_add_user " ) and " auto_add_user " in source_rights :
try :
cmd , value = cmd . split ( " " , 1 )
if val_to_bool ( value ) :
DATA [ " main " ] [ " auto_add_user " ] = " True "
content = config_get ( CONFIG , " interface_menu " , " auto_add_user_true " , " " , lng_key )
DATA [ " main " ] [ " unsaved " ] = " True "
else :
DATA [ " main " ] [ " auto_add_user " ] = " False "
content = config_get ( CONFIG , " interface_menu " , " auto_add_user_false " , " " , lng_key )
DATA [ " main " ] [ " unsaved " ] = " True "
except :
content = config_get ( CONFIG , " interface_menu " , " auto_add_user_error " , " " , lng_key )
# "/auto_add_user_type" command.
elif cmd == " auto_add_user_type " and " auto_add_user_type " in source_rights :
content = config_get ( DATA , " main " , " auto_add_user_type " , " " , lng_key )
elif cmd . startswith ( " auto_add_user_type " ) and " auto_add_user_type " in source_rights :
try :
cmd , value = cmd . split ( " " , 1 )
DATA [ " main " ] [ " auto_add_user_type " ] = value
content = config_get ( CONFIG , " interface_menu " , " auto_add_user_type " , " " , lng_key ) + " " + value
DATA [ " main " ] [ " unsaved " ] = " True "
except :
content = config_get ( CONFIG , " interface_menu " , " auto_add_user_type_error " , " " , lng_key )
# "/auto_add_cluster" command.
elif cmd == " auto_add_cluster " and " auto_add_cluster " in source_rights :
if DATA [ " main " ] . getboolean ( " auto_add_cluster " ) :
content = config_get ( CONFIG , " interface_menu " , " auto_add_cluster_true " , " " , lng_key )
else :
content = config_get ( CONFIG , " interface_menu " , " auto_add_cluster_false " , " " , lng_key )
elif cmd . startswith ( " auto_add_cluster " ) and " auto_add_cluster " in source_rights :
try :
cmd , value = cmd . split ( " " , 1 )
if val_to_bool ( value ) :
DATA [ " main " ] [ " auto_add_cluster " ] = " True "
content = config_get ( CONFIG , " interface_menu " , " auto_add_cluster_true " , " " , lng_key )
DATA [ " main " ] [ " unsaved " ] = " True "
else :
DATA [ " main " ] [ " auto_add_cluster " ] = " False "
content = config_get ( CONFIG , " interface_menu " , " auto_add_cluster_false " , " " , lng_key )
DATA [ " main " ] [ " unsaved " ] = " True "
except :
content = config_get ( CONFIG , " interface_menu " , " auto_add_cluster_error " , " " , lng_key )
2022-10-22 05:50:19 -04:00
# "/auto_add_router" command.
elif cmd == " auto_add_router " and " auto_add_router " in source_rights :
if DATA [ " main " ] . getboolean ( " auto_add_router " ) :
content = config_get ( CONFIG , " interface_menu " , " auto_add_router_true " , " " , lng_key )
else :
content = config_get ( CONFIG , " interface_menu " , " auto_add_router_false " , " " , lng_key )
elif cmd . startswith ( " auto_add_router " ) and " auto_add_router " in source_rights :
try :
cmd , value = cmd . split ( " " , 1 )
if val_to_bool ( value ) :
DATA [ " main " ] [ " auto_add_router " ] = " True "
content = config_get ( CONFIG , " interface_menu " , " auto_add_router_true " , " " , lng_key )
DATA [ " main " ] [ " unsaved " ] = " True "
else :
DATA [ " main " ] [ " auto_add_router " ] = " False "
content = config_get ( CONFIG , " interface_menu " , " auto_add_router_false " , " " , lng_key )
DATA [ " main " ] [ " unsaved " ] = " True "
except :
content = config_get ( CONFIG , " interface_menu " , " auto_add_router_error " , " " , lng_key )
2022-10-21 11:58:11 -04:00
# "/invite_user" command.
elif cmd == " invite_user " and " invite_user " in source_rights :
if DATA [ " main " ] . getboolean ( " invite_user " ) :
content = config_get ( CONFIG , " interface_menu " , " invite_user_true " , " " , lng_key )
else :
content = config_get ( CONFIG , " interface_menu " , " invite_user_false " , " " , lng_key )
elif cmd . startswith ( " invite_user " ) and " invite_user " in source_rights :
try :
cmd , value = cmd . split ( " " , 1 )
if val_to_bool ( value ) :
DATA [ " main " ] [ " invite_user " ] = " True "
content = config_get ( CONFIG , " interface_menu " , " invite_user_true " , " " , lng_key )
DATA [ " main " ] [ " unsaved " ] = " True "
else :
DATA [ " main " ] [ " invite_user " ] = " False "
content = config_get ( CONFIG , " interface_menu " , " invite_user_false " , " " , lng_key )
DATA [ " main " ] [ " unsaved " ] = " True "
except :
content = config_get ( CONFIG , " interface_menu " , " invite_user_error " , " " , lng_key )
# "/invite_user_type" command.
elif cmd == " invite_user_type " and " invite_user_type " in source_rights :
content = config_get ( DATA , " main " , " invite_user_type " , " " , lng_key )
elif cmd . startswith ( " invite_user_type " ) and " invite_user_type " in source_rights :
try :
cmd , value = cmd . split ( " " , 1 )
DATA [ " main " ] [ " invite_user_type " ] = value
content = config_get ( CONFIG , " interface_menu " , " invite_user_type " , " " , lng_key ) + " " + value
DATA [ " main " ] [ " unsaved " ] = " True "
except :
content = config_get ( CONFIG , " interface_menu " , " invite_user_type_error " , " " , lng_key )
# "/allow_user" command.
elif cmd == " allow_user " and " allow_user " in source_rights :
if DATA [ " main " ] . getboolean ( " allow_user " ) :
content = config_get ( CONFIG , " interface_menu " , " allow_user_true " , " " , lng_key )
else :
content = config_get ( CONFIG , " interface_menu " , " allow_user_false " , " " , lng_key )
elif cmd . startswith ( " allow_user " ) and " allow_user " in source_rights :
try :
cmd , value = cmd . split ( " " , 1 )
if val_to_bool ( value ) :
DATA [ " main " ] [ " allow_user " ] = " True "
content = config_get ( CONFIG , " interface_menu " , " allow_user_true " , " " , lng_key )
DATA [ " main " ] [ " unsaved " ] = " True "
else :
DATA [ " main " ] [ " allow_user " ] = " False "
content = config_get ( CONFIG , " interface_menu " , " allow_user_false " , " " , lng_key )
DATA [ " main " ] [ " unsaved " ] = " True "
except :
content = config_get ( CONFIG , " interface_menu " , " allow_user_error " , " " , lng_key )
# "/allow_user_type" command.
elif cmd == " allow_user_type " and " allow_user_type " in source_rights :
content = config_get ( DATA , " main " , " allow_user_type " , " " , lng_key )
elif cmd . startswith ( " allow_user_type " ) and " allow_user_type " in source_rights :
try :
cmd , value = cmd . split ( " " , 1 )
DATA [ " main " ] [ " allow_user_type " ] = value
content = config_get ( CONFIG , " interface_menu " , " allow_user_type " , " " , lng_key ) + " " + value
DATA [ " main " ] [ " unsaved " ] = " True "
except :
content = config_get ( CONFIG , " interface_menu " , " allow_user_type_error " , " " , lng_key )
# "/deny_user" command.
elif cmd == " deny_user " and " deny_user " in source_rights :
if DATA [ " main " ] . getboolean ( " deny_user " ) :
content = config_get ( CONFIG , " interface_menu " , " deny_user_true " , " " , lng_key )
else :
content = config_get ( CONFIG , " interface_menu " , " deny_user_false " , " " , lng_key )
elif cmd . startswith ( " deny_user " ) and " deny_user " in source_rights :
try :
cmd , value = cmd . split ( " " , 1 )
if val_to_bool ( value ) :
DATA [ " main " ] [ " deny_user " ] = " True "
content = config_get ( CONFIG , " interface_menu " , " deny_user_true " , " " , lng_key )
DATA [ " main " ] [ " unsaved " ] = " True "
else :
DATA [ " main " ] [ " deny_user " ] = " False "
content = config_get ( CONFIG , " interface_menu " , " deny_user_false " , " " , lng_key )
DATA [ " main " ] [ " unsaved " ] = " True "
except :
content = config_get ( CONFIG , " interface_menu " , " deny_user_error " , " " , lng_key )
# "/deny_user_type" command.
elif cmd == " deny_user_type " and " deny_user_type " in source_rights :
content = config_get ( DATA , " main " , " deny_user_type " , " " , lng_key )
elif cmd . startswith ( " deny_user_type " ) and " deny_user_type " in source_rights :
try :
cmd , value = cmd . split ( " " , 1 )
DATA [ " main " ] [ " deny_user_type " ] = value
content = config_get ( CONFIG , " interface_menu " , " deny_user_type " , " " , lng_key ) + " " + value
DATA [ " main " ] [ " unsaved " ] = " True "
except :
content = config_get ( CONFIG , " interface_menu " , " deny_user_type_error " , " " , lng_key )
# "/description" command.
elif cmd == " description " and " description " in source_rights :
content = config_get ( DATA , " main " , " description " , " " , lng_key )
content = replace ( content , source_hash , source_name , source_right , lng_key )
elif cmd . startswith ( " description " ) and " description_set " in source_rights :
try :
cmd , value = cmd . split ( " " , 1 )
DATA [ " main " ] [ " description " + lng_key ] = value
content_group = config_get ( CONFIG , " interface_messages " , " description " , " " , lng_key )
content_group = replace ( content_group , source_hash , source_name , source_right , lng_key )
if content_group != " " :
for section in sections :
if " receive_description " in config_get ( CONFIG , " rights " , section ) . split ( " , " ) :
for ( key , val ) in DATA . items ( section ) :
if key != source_hash :
2023-04-25 01:15:17 -04:00
LXMF_CONNECTION . send ( key , content_group , " " , fields_generate ( lng_key , h = message . source_hash , n = source_name , tpl = " description " ) , None , " interface_send " )
2022-10-21 11:58:11 -04:00
content = config_get ( CONFIG , " interface_menu " , " description " , " " , lng_key ) + " " + value
DATA [ " main " ] [ " unsaved " ] = " True "
except :
content = config_get ( CONFIG , " interface_menu " , " description_error " , " " , lng_key )
# "/rules" command.
elif cmd == " rules " and " rules " in source_rights :
content = config_get ( DATA , " main " , " rules " , " " , lng_key )
content = replace ( content , source_hash , source_name , source_right , lng_key )
elif cmd . startswith ( " rules " ) and " rules_set " in source_rights :
try :
cmd , value = cmd . split ( " " , 1 )
DATA [ " main " ] [ " rules " + lng_key ] = value
content_group = config_get ( CONFIG , " interface_messages " , " rules " , " " , lng_key )
content_group = replace ( content_group , source_hash , source_name , source_right , lng_key )
if content_group != " " :
for section in sections :
if " receive_rules " in config_get ( CONFIG , " rights " , section ) . split ( " , " ) :
for ( key , val ) in DATA . items ( section ) :
if key != source_hash :
2023-04-25 01:15:17 -04:00
LXMF_CONNECTION . send ( key , content_group , " " , fields_generate ( lng_key , h = message . source_hash , n = source_name , tpl = " rules " ) , None , " interface_send " )
2022-10-21 11:58:11 -04:00
content = config_get ( CONFIG , " interface_menu " , " rules " , " " , lng_key ) + " " + value
DATA [ " main " ] [ " unsaved " ] = " True "
except :
content = config_get ( CONFIG , " interface_menu " , " rules_error " , " " , lng_key )
# "/readme" command.
elif cmd == " readme " and " readme " in source_rights :
content = config_get ( CONFIG , " interface_menu " , " readme " , " " , lng_key )
content = replace ( content , source_hash , source_name , source_right , lng_key )
# "/time" command.
elif cmd == " time " and " time " in source_rights :
content = config_get ( CONFIG , " interface_menu " , " time " , " " , lng_key )
content = time . strftime ( content , time . localtime ( time . time ( ) ) )
content = replace ( content , source_hash , source_name , source_right , lng_key )
# "/announce" command.
elif cmd == " announce " and " announce " in source_rights :
content = config_get ( CONFIG , " interface_menu " , " announce " , " " , lng_key )
content = replace ( content , source_hash , source_name , source_right , lng_key )
LXMF_CONNECTION . announce_now ( )
if CONFIG [ " cluster " ] . getboolean ( " enabled " ) :
RNS_CONNECTION . announce_now ( )
# "/sync" command.
elif cmd == " sync " and " sync " in source_rights :
content = config_get ( CONFIG , " interface_menu " , " sync " , " " , lng_key )
content = replace ( content , source_hash , source_name , source_right , lng_key )
LXMF_CONNECTION . sync_now ( )
# "/show run" command.
elif ( cmd == " show run " or cmd == " sh run " ) and " show_run " in source_rights :
content = config_get ( CONFIG , " interface_menu " , " show_run_header " , " " , lng_key )
content = replace ( content , source_hash , source_name , source_right , lng_key )
for ( key , val ) in DATA . items ( " main " ) :
content = content + key + " = " + val + " \n "
# "/show" command.
elif ( cmd . startswith ( " show " ) or cmd . startswith ( " list " ) or cmd . startswith ( " sh " ) ) and " show " in source_rights :
try :
cmd , key = cmd . split ( " " , 1 )
if DATA . has_section ( key ) and key != " main " :
content = config_get ( CONFIG , " interface_menu " , " show_header " , " " , lng_key )
content = replace ( content , source_hash , source_name , source_right , lng_key )
content = content + " [ " + key + " ] \n "
for ( section_key , section_val ) in DATA . items ( key ) :
content = content + section_key + " = " + section_val + " \n "
else :
content = config_get ( CONFIG , " interface_menu " , " user_type_error " , " " , lng_key ) + " " + key
except :
content = config_get ( CONFIG , " interface_menu " , " show_header " , " " , lng_key )
content = replace ( content , source_hash , source_name , source_right , lng_key )
for section in DATA . sections ( ) :
if section in sections or section . replace ( " block_ " , " " ) in sections :
content = content + " [ " + section + " ] \n "
for ( key , val ) in DATA . items ( section ) :
content = content + key + " = " + val + " \n "
content = content + " \n "
# "/user" command.
elif cmd . startswith ( " add " ) and " add " in source_rights :
try :
cmd , key , value , name = cmd . split ( " " , 3 )
if DATA . has_section ( key ) and key != " main " :
value = LXMF_CONNECTION . destination_correct ( value )
if value != " " :
for section in DATA . sections ( ) :
if section != " main " :
for ( key , val ) in DATA . items ( section ) :
if key == value :
DATA . remove_option ( section , key )
DATA [ key ] [ value ] = name
content = config_get ( CONFIG , " interface_menu " , " user_add " , " " , lng_key ) + " " + value + " -> " + key
DATA [ " main " ] [ " unsaved " ] = " True "
else :
content = config_get ( CONFIG , " interface_menu " , " user_format_error " , " " , lng_key )
else :
content = config_get ( CONFIG , " interface_menu " , " user_type_error " , " " , lng_key )
except :
content = config_get ( CONFIG , " interface_menu " , " cmd_error " , " " , lng_key )
# "/user" command.
elif ( cmd . startswith ( " del " ) or cmd . startswith ( " rm " ) or cmd . startswith ( " delete " ) ) and " del " in source_rights :
try :
cmd , key , value = cmd . split ( " " , 2 )
if DATA . has_section ( key ) and key != " main " :
value = LXMF_CONNECTION . destination_correct ( value )
if value != " " :
if DATA . has_option ( key , value ) :
DATA . remove_option ( key , value )
content = config_get ( CONFIG , " interface_menu " , " user_del " , " " , lng_key ) + " " + value + " -> " + key
DATA [ " main " ] [ " unsaved " ] = " True "
if CONFIG [ " statistic " ] . getboolean ( " enabled " ) :
statistic ( " del " , value )
else :
content = config_get ( CONFIG , " interface_menu " , " user_error " , " " , lng_key ) + " " + value + " -> " + key
else :
content = config_get ( CONFIG , " interface_menu " , " user_format_error " , " " , lng_key )
else :
content = config_get ( CONFIG , " interface_menu " , " user_type_error " , " " , lng_key )
except :
try :
cmd , value = cmd . split ( " " , 1 )
value = LXMF_CONNECTION . destination_correct ( value )
if value != " " :
for section in DATA . sections ( ) :
if section != " main " :
for ( key , val ) in DATA . items ( section ) :
if key == value :
DATA . remove_option ( section , key )
if CONFIG [ " statistic " ] . getboolean ( " enabled " ) :
statistic ( " del " , value )
content = " OK: Removed user ' " + value + " ' from all types "
DATA [ " main " ] [ " unsaved " ] = " True "
else :
content = config_get ( CONFIG , " interface_menu " , " user_format_error " , " " , lng_key )
except :
content = config_get ( CONFIG , " interface_menu " , " cmd_error " , " " , lng_key )
# "/user" command.
elif ( cmd . startswith ( " move " ) or cmd . startswith ( " mv " ) ) and " move " in source_rights :
try :
cmd , key , value = cmd . split ( " " , 2 )
if DATA . has_section ( key ) and key != " main " :
value = LXMF_CONNECTION . destination_correct ( value )
if value != " " :
for section in DATA . sections ( ) :
if section != " main " :
for ( key_old , val_old ) in DATA . items ( section ) :
if key_old == value :
DATA . remove_option ( section , key_old )
DATA [ key ] [ value ] = val_old
content = config_get ( CONFIG , " interface_menu " , " user_move " , " " , lng_key ) + " " + value + " -> " + key
DATA [ " main " ] [ " unsaved " ] = " True "
if content == " " :
content = config_get ( CONFIG , " interface_menu " , " user_format_error " , " " , lng_key )
else :
content = config_get ( CONFIG , " interface_menu " , " user_format_error " , " " , lng_key )
else :
content = config_get ( CONFIG , " interface_menu " , " user_type_error " , " " , lng_key )
except :
content = config_get ( CONFIG , " interface_menu " , " cmd_error " , " " , lng_key )
2022-10-22 10:44:55 -04:00
# "/user" command.
elif cmd . startswith ( " rename " ) and " rename " in source_rights :
try :
cmd , key , value = cmd . split ( " " , 2 )
key = LXMF_CONNECTION . destination_correct ( key )
if key != " " :
executed = False
for section in sections :
if DATA . has_option ( section , key ) :
content = config_get ( CONFIG , " interface_menu " , " user_rename " , " " , lng_key ) + " " + DATA [ section ] [ key ] + " -> " + value
DATA [ section ] [ key ] = value
executed = True
if executed :
if CONFIG [ " main " ] . getboolean ( " auto_save_data " ) :
DATA . remove_option ( " main " , " unsaved " )
if not data_save ( PATH + " /data.cfg " ) :
DATA [ " main " ] [ " unsaved " ] = " True "
else :
DATA [ " main " ] [ " unsaved " ] = " True "
else :
content = config_get ( CONFIG , " interface_menu " , " user_found_error " , " " , lng_key )
else :
content = config_get ( CONFIG , " interface_menu " , " user_format_error " , " " , lng_key )
except :
content = config_get ( CONFIG , " interface_menu " , " cmd_error " , " " , lng_key )
2022-10-21 11:58:11 -04:00
# "/invite" command.
elif cmd . startswith ( " invite " ) and " invite " in source_rights :
if DATA [ " main " ] . getboolean ( " invite_user " ) :
try :
cmd , value = cmd . split ( " " , 1 )
key = DATA [ " main " ] [ " invite_user_type " ]
if DATA . has_section ( key ) and key != " main " :
value = LXMF_CONNECTION . destination_correct ( value )
if value != " " :
2022-11-08 12:34:34 -05:00
user_name = " "
if CONFIG [ " main " ] . getboolean ( " auto_name_add " ) :
app_data = RNS . Identity . recall_app_data ( bytes . fromhex ( value ) )
if app_data != None :
user_name = app_data . decode ( ' utf-8 ' )
DATA [ key ] [ value ] = user_name
2022-10-21 11:58:11 -04:00
content_user = config_get ( CONFIG , " interface_messages " , " invite_ " + key , " " , lng_key )
content_user = replace ( content_user , source_hash , source_name , source_right , lng_key )
2022-11-08 12:34:34 -05:00
content_user = content_user . replace ( delimiter + " user_name " + delimiter , user_name )
2022-10-21 11:58:11 -04:00
if content_user != " " :
2023-04-25 01:15:17 -04:00
LXMF_CONNECTION . send ( value , content_user , " " , fields_generate ( lng_key , m = True , d = True , r = True , cmd = key , config = key ) , None , " interface_send " )
2022-10-21 11:58:11 -04:00
content_group = config_get ( CONFIG , " interface_messages " , " member_invite " , " " , lng_key )
content_group = replace ( content_group , source_hash , source_name , source_right , lng_key )
content_group = content_group . replace ( delimiter + " user_address " + delimiter , value )
2022-11-08 12:34:34 -05:00
content_group = content_group . replace ( delimiter + " user_name " + delimiter , user_name )
2022-10-21 11:58:11 -04:00
if content_group != " " :
2023-04-25 01:15:17 -04:00
fields = fields_generate ( lng_key , h = bytes . fromhex ( value ) , n = user_name , m = True , tpl = " invite " )
2022-10-21 11:58:11 -04:00
for section in sections :
if " receive_invite " in config_get ( CONFIG , " rights " , section ) . split ( " , " ) :
for ( key , val ) in DATA . items ( section ) :
if key != source_hash :
2023-04-25 01:15:17 -04:00
LXMF_CONNECTION . send ( key , content_group , " " , fields , None , " interface_send " )
2022-10-21 11:58:11 -04:00
content = config_get ( CONFIG , " interface_menu " , " invite_ok " , " " , lng_key ) + " < " + value + " > "
if CONFIG [ " main " ] . getboolean ( " auto_save_data " ) :
DATA . remove_option ( " main " , " unsaved " )
if not data_save ( PATH + " /data.cfg " ) :
DATA [ " main " ] [ " unsaved " ] = " True "
else :
DATA [ " main " ] [ " unsaved " ] = " True "
else :
content = config_get ( CONFIG , " interface_menu " , " invite_format_error " , " " , lng_key )
else :
content = config_get ( CONFIG , " interface_menu " , " invite_type_error " , " " , lng_key )
except :
content = config_get ( CONFIG , " interface_menu " , " cmd_error " , " " , lng_key )
else :
content = config_get ( CONFIG , " interface_menu " , " cmd_error " , " " , lng_key )
# "/kick" command.
elif cmd . startswith ( " kick " ) and " kick " in source_rights :
try :
cmd , value = cmd . split ( " " , 1 )
value = LXMF_CONNECTION . destination_correct ( value )
if value != " " :
executed = False
for section in sections :
for ( key , val ) in DATA . items ( section ) :
if key == value :
user_section = section
user_name = val
executed = True
DATA . remove_option ( section , key )
if executed :
if CONFIG [ " statistic " ] . getboolean ( " enabled " ) :
statistic ( " del " , value )
content_user = config_get ( CONFIG , " interface_messages " , " kick_ " + user_section , " " , lng_key )
content_user = replace ( content_user , source_hash , source_name , source_right , lng_key )
if content_user != " " :
2023-04-25 01:15:17 -04:00
LXMF_CONNECTION . send ( value , content_user , " " , fields_generate ( lng_key ) , None , " interface_send " )
2022-10-21 11:58:11 -04:00
content_group = config_get ( CONFIG , " interface_messages " , " member_kick " , " " , lng_key )
content_group = replace ( content_group , source_hash , source_name , source_right , lng_key )
content_group = content_group . replace ( delimiter + " user_address " + delimiter , value )
content_group = content_group . replace ( delimiter + " user_name " + delimiter , user_name )
if content_group != " " :
2023-04-25 01:15:17 -04:00
fields = fields_generate ( lng_key , h = bytes . fromhex ( value ) , n = user_name , m = True , tpl = " kick " )
2022-10-21 11:58:11 -04:00
for section in sections :
if " receive_kick " in config_get ( CONFIG , " rights " , section ) . split ( " , " ) :
for ( key , val ) in DATA . items ( section ) :
2023-04-25 01:15:17 -04:00
LXMF_CONNECTION . send ( key , content_group , " " , fields , None , " interface_send " )
2022-10-21 11:58:11 -04:00
content = config_get ( CONFIG , " interface_menu " , " kick_ok " , " " , lng_key )
content = content . replace ( delimiter + " user_address " + delimiter , value )
content = content . replace ( delimiter + " user_name " + delimiter , user_name )
if CONFIG [ " main " ] . getboolean ( " auto_save_data " ) :
DATA . remove_option ( " main " , " unsaved " )
if not data_save ( PATH + " /data.cfg " ) :
DATA [ " main " ] [ " unsaved " ] = " True "
else :
DATA [ " main " ] [ " unsaved " ] = " True "
else :
content = config_get ( CONFIG , " interface_menu " , " kick_found_error " , " " , lng_key )
else :
content = config_get ( CONFIG , " interface_menu " , " kick_format_error " , " " , lng_key )
except :
content = config_get ( CONFIG , " interface_menu " , " cmd_error " , " " , lng_key )
# "/block" command.
elif ( cmd . startswith ( " block " ) or cmd . startswith ( " ban " ) ) and " block " in source_rights :
try :
cmd , value = cmd . split ( " " , 1 )
value = LXMF_CONNECTION . destination_correct ( value )
if value != " " :
executed = False
for section in sections :
for ( key , val ) in DATA . items ( section ) :
if key == value :
user_section = section
user_name = val
executed = True
if not DATA . has_section ( " block_ " + section ) :
DATA . add_section ( " block_ " + section )
DATA [ " block_ " + section ] [ key ] = val
DATA . remove_option ( section , key )
if executed :
content_user = config_get ( CONFIG , " interface_messages " , " block_ " + user_section , " " , lng_key )
content_user = replace ( content_user , source_hash , source_name , source_right , lng_key )
if content_user != " " :
2023-04-25 01:15:17 -04:00
LXMF_CONNECTION . send ( value , content_user , " " , fields_generate ( lng_key ) , None , " interface_send " )
2022-10-21 11:58:11 -04:00
content_group = config_get ( CONFIG , " interface_messages " , " member_block " , " " , lng_key )
content_group = replace ( content_group , source_hash , source_name , source_right , lng_key )
content_group = content_group . replace ( delimiter + " user_address " + delimiter , value )
content_group = content_group . replace ( delimiter + " user_name " + delimiter , user_name )
if content_group != " " :
2023-04-25 01:15:17 -04:00
fields = fields_generate ( lng_key , h = bytes . fromhex ( value ) , n = user_name , m = True , tpl = " block " )
2022-10-21 11:58:11 -04:00
for section in sections :
if " receive_block " in config_get ( CONFIG , " rights " , section ) . split ( " , " ) :
for ( key , val ) in DATA . items ( section ) :
2023-04-25 01:15:17 -04:00
LXMF_CONNECTION . send ( key , content_group , " " , fields , None , " interface_send " )
2022-10-21 11:58:11 -04:00
content = config_get ( CONFIG , " interface_menu " , " block_ok " , " " , lng_key )
content = content . replace ( delimiter + " user_address " + delimiter , value )
content = content . replace ( delimiter + " user_name " + delimiter , user_name )
if CONFIG [ " main " ] . getboolean ( " auto_save_data " ) :
DATA . remove_option ( " main " , " unsaved " )
if not data_save ( PATH + " /data.cfg " ) :
DATA [ " main " ] [ " unsaved " ] = " True "
else :
DATA [ " main " ] [ " unsaved " ] = " True "
else :
content = config_get ( CONFIG , " interface_menu " , " block_found_error " , " " , lng_key )
else :
content = config_get ( CONFIG , " interface_menu " , " block_format_error " , " " , lng_key )
except :
content = config_get ( CONFIG , " interface_menu " , " cmd_error " , " " , lng_key )
# "/unblock" command.
elif ( cmd . startswith ( " unblock " ) or cmd . startswith ( " unban " ) ) and " unblock " in source_rights :
try :
cmd , value = cmd . split ( " " , 1 )
value = LXMF_CONNECTION . destination_correct ( value )
if value != " " :
executed = False
for section in DATA . sections ( ) :
if section . startswith ( " block " ) :
for ( key , val ) in DATA . items ( section ) :
if key == value :
user_section = section . replace ( " block_ " , " " )
user_name = val
executed = True
if not DATA . has_section ( user_section ) :
DATA . add_section ( user_section )
DATA [ user_section ] [ key ] = val
DATA . remove_option ( section , key )
if executed :
content_user = config_get ( CONFIG , " interface_messages " , " unblock_ " + user_section , " " , lng_key )
content_user = replace ( content_user , source_hash , source_name , source_right , lng_key )
if content_user != " " :
2023-04-25 01:15:17 -04:00
LXMF_CONNECTION . send ( value , content_user , " " , fields_generate ( lng_key , m = True , d = True , r = True , cmd = user_section , config = user_section ) , None , " interface_send " )
2022-10-21 11:58:11 -04:00
content_group = config_get ( CONFIG , " interface_messages " , " member_unblock " , " " , lng_key )
content_group = replace ( content_group , source_hash , source_name , source_right , lng_key )
content_group = content_group . replace ( delimiter + " user_address " + delimiter , value )
content_group = content_group . replace ( delimiter + " user_name " + delimiter , user_name )
if content_group != " " :
2023-04-25 01:15:17 -04:00
fields = fields_generate ( lng_key , h = bytes . fromhex ( value ) , n = user_name , m = True , tpl = " unblock " )
2022-10-21 11:58:11 -04:00
for section in sections :
if " receive_block " in config_get ( CONFIG , " rights " , section ) . split ( " , " ) :
for ( key , val ) in DATA . items ( section ) :
2023-04-25 01:15:17 -04:00
LXMF_CONNECTION . send ( key , content_group , " " , fields , None , " interface_send " )
2022-10-21 11:58:11 -04:00
content = config_get ( CONFIG , " interface_menu " , " unblock_ok " , " " , lng_key )
content = content . replace ( delimiter + " user_address " + delimiter , value )
content = content . replace ( delimiter + " user_name " + delimiter , user_name )
if CONFIG [ " main " ] . getboolean ( " auto_save_data " ) :
DATA . remove_option ( " main " , " unsaved " )
if not data_save ( PATH + " /data.cfg " ) :
DATA [ " main " ] [ " unsaved " ] = " True "
else :
DATA [ " main " ] [ " unsaved " ] = " True "
else :
content = config_get ( CONFIG , " interface_menu " , " unblock_found_error " , " " , lng_key )
else :
content = config_get ( CONFIG , " interface_menu " , " unblock_format_error " , " " , lng_key )
except :
content = config_get ( CONFIG , " interface_menu " , " cmd_error " , " " , lng_key )
# "/allow" command.
elif cmd . startswith ( " allow " ) and " allow " in source_rights :
try :
cmd , value = cmd . split ( " " , 1 )
user_section = DATA [ " main " ] [ " allow_user_type " ]
if DATA . has_section ( user_section ) and user_section != " main " :
value = LXMF_CONNECTION . destination_correct ( value )
if value != " " :
executed = False
section = " wait "
if DATA . has_section ( section ) :
for ( key , val ) in DATA . items ( section ) :
if key == value :
user_name = val
executed = True
DATA [ user_section ] [ key ] = val
DATA . remove_option ( section , key )
if executed :
content_user = config_get ( CONFIG , " interface_messages " , " allow_ " + user_section , " " , lng_key )
content_user = replace ( content_user , source_hash , source_name , source_right , lng_key )
if content_user != " " :
2023-04-25 01:15:17 -04:00
LXMF_CONNECTION . send ( value , content_user , " " , fields_generate ( lng_key , m = True , d = True , r = True , cmd = user_section , config = user_section ) , None , " interface_send " )
2022-10-21 11:58:11 -04:00
content_group = config_get ( CONFIG , " interface_messages " , " member_allow " , " " , lng_key )
content_group = replace ( content_group , source_hash , source_name , source_right , lng_key )
content_group = content_group . replace ( delimiter + " user_address " + delimiter , value )
content_group = content_group . replace ( delimiter + " user_name " + delimiter , user_name )
if content_group != " " :
2023-04-25 01:15:17 -04:00
fields = fields_generate ( lng_key , h = bytes . fromhex ( value ) , n = user_name , m = True , tpl = " allow " )
2022-10-21 11:58:11 -04:00
for section in sections :
if " receive_block " in config_get ( CONFIG , " rights " , section ) . split ( " , " ) :
for ( key , val ) in DATA . items ( section ) :
2023-04-25 01:15:17 -04:00
LXMF_CONNECTION . send ( key , content_group , " " , fields , None , " interface_send " )
2022-10-21 11:58:11 -04:00
content = config_get ( CONFIG , " interface_menu " , " allow_ok " , " " , lng_key )
content = content . replace ( delimiter + " user_address " + delimiter , value )
content = content . replace ( delimiter + " user_name " + delimiter , user_name )
if CONFIG [ " main " ] . getboolean ( " auto_save_data " ) :
DATA . remove_option ( " main " , " unsaved " )
if not data_save ( PATH + " /data.cfg " ) :
DATA [ " main " ] [ " unsaved " ] = " True "
else :
DATA [ " main " ] [ " unsaved " ] = " True "
else :
content = config_get ( CONFIG , " interface_menu " , " allow_found_error " , " " , lng_key )
else :
content = config_get ( CONFIG , " interface_menu " , " allow_format_error " , " " , lng_key )
else :
content = config_get ( CONFIG , " interface_menu " , " allow_type_error " , " " , lng_key )
except :
content = config_get ( CONFIG , " interface_menu " , " cmd_error " , " " , lng_key )
# "/deny" command.
elif cmd . startswith ( " deny " ) and " deny " in source_rights :
try :
cmd , value = cmd . split ( " " , 1 )
user_section = DATA [ " main " ] [ " deny_user_type " ]
if DATA . has_section ( user_section ) and user_section != " main " :
value = LXMF_CONNECTION . destination_correct ( value )
if value != " " :
executed = False
for section in sections :
for ( key , val ) in DATA . items ( section ) :
if key == value :
user_name = val
executed = True
DATA [ user_section ] [ key ] = val
DATA . remove_option ( section , key )
if executed :
content_user = config_get ( CONFIG , " interface_messages " , " deny_ " + user_section , " " , lng_key )
content_user = replace ( content_user , source_hash , source_name , source_right , lng_key )
if content_user != " " :
2023-04-25 01:15:17 -04:00
LXMF_CONNECTION . send ( value , content_user , " " , fields_generate ( lng_key ) , None , " interface_send " )
2022-10-21 11:58:11 -04:00
content_group = config_get ( CONFIG , " interface_messages " , " member_deny " , " " , lng_key )
content_group = replace ( content_group , source_hash , source_name , source_right , lng_key )
content_group = content_group . replace ( delimiter + " user_address " + delimiter , value )
content_group = content_group . replace ( delimiter + " user_name " + delimiter , user_name )
if content_group != " " :
2023-04-25 01:15:17 -04:00
fields = fields_generate ( lng_key , h = bytes . fromhex ( value ) , n = user_name , m = True , tpl = " deny " )
2022-10-21 11:58:11 -04:00
for section in sections :
if " receive_block " in config_get ( CONFIG , " rights " , section ) . split ( " , " ) :
for ( key , val ) in DATA . items ( section ) :
2023-04-25 01:15:17 -04:00
LXMF_CONNECTION . send ( key , content_group , " " , fields , None , " interface_send " )
2022-10-21 11:58:11 -04:00
content = config_get ( CONFIG , " interface_menu " , " deny_ok " , " " , lng_key )
content = content . replace ( delimiter + " user_address " + delimiter , value )
content = content . replace ( delimiter + " user_name " + delimiter , user_name )
if CONFIG [ " main " ] . getboolean ( " auto_save_data " ) :
DATA . remove_option ( " main " , " unsaved " )
if not data_save ( PATH + " /data.cfg " ) :
DATA [ " main " ] [ " unsaved " ] = " True "
else :
DATA [ " main " ] [ " unsaved " ] = " True "
else :
content = config_get ( CONFIG , " interface_menu " , " deny_found_error " , " " , lng_key )
else :
content = config_get ( CONFIG , " interface_menu " , " deny_format_error " , " " , lng_key )
else :
content = config_get ( CONFIG , " interface_menu " , " deny_type_error " , " " , lng_key )
except :
content = config_get ( CONFIG , " interface_menu " , " cmd_error " , " " , lng_key )
# "/load" command.
elif ( cmd == " load " or cmd == " read " ) and " load " in source_rights :
if data_read ( PATH + " /data.cfg " ) :
content = config_get ( CONFIG , " interface_menu " , " load_ok " , " " , lng_key )
else :
content = config_get ( CONFIG , " interface_menu " , " load_error " , " " , lng_key )
# "/save" command.
elif ( cmd == " save " or cmd == " wr " ) and " save " in source_rights :
DATA . remove_option ( " main " , " unsaved " )
if data_save ( PATH + " /data.cfg " ) :
content = config_get ( CONFIG , " interface_menu " , " save_ok " , " " , lng_key )
else :
content = config_get ( CONFIG , " interface_menu " , " save_error " , " " , lng_key )
DATA [ " main " ] [ " unsaved " ] = " True "
if CONFIG [ " statistic " ] . getboolean ( " enabled " ) :
statistic_save ( PATH + " /statistic.cfg " )
# "/reload" command.
elif cmd == " reload " and " reload " in source_rights :
content = config_get ( CONFIG , " interface_menu " , " reload_error " , " " , lng_key )
DATA . remove_option ( " main " , " unsaved " )
if data_save ( PATH + " /data.cfg " ) :
if data_read ( PATH + " /data.cfg " ) :
content = config_get ( CONFIG , " interface_menu " , " reload_ok " , " " , lng_key )
else :
DATA [ " main " ] [ " unsaved " ] = " True "
# "/reset" command.
elif cmd . startswith ( " reset statistic " ) and " reset " in source_rights :
try :
cmd , key , value = cmd . split ( " " , 2 )
if value == " all " :
for section in STATISTIC . sections ( ) :
statistic_reset ( section )
if CONFIG [ " main " ] . getboolean ( " auto_save_statistic " ) :
statistic_save ( PATH + " /statistic.cfg " )
else :
if not STATISTIC . has_section ( " main " ) :
STATISTIC . add_section ( " main " )
STATISTIC [ " main " ] [ " unsaved " ] = " True "
content = config_get ( CONFIG , " interface_menu " , " reset_statistic_ok " , " " , lng_key )
elif value == " cluster " :
for section in STATISTIC . sections ( ) :
if section . startswith ( " cluster " ) :
statistic_reset ( section )
if CONFIG [ " main " ] . getboolean ( " auto_save_statistic " ) :
statistic_save ( PATH + " /statistic.cfg " )
else :
if not STATISTIC . has_section ( " main " ) :
STATISTIC . add_section ( " main " )
STATISTIC [ " main " ] [ " unsaved " ] = " True "
content = config_get ( CONFIG , " interface_menu " , " reset_statistic_ok " , " " , lng_key )
elif value == " local " :
for section in STATISTIC . sections ( ) :
if section . startswith ( " local " ) :
statistic_reset ( section )
if CONFIG [ " main " ] . getboolean ( " auto_save_statistic " ) :
statistic_save ( PATH + " /statistic.cfg " )
else :
if not STATISTIC . has_section ( " main " ) :
STATISTIC . add_section ( " main " )
STATISTIC [ " main " ] [ " unsaved " ] = " True "
content = config_get ( CONFIG , " interface_menu " , " reset_statistic_ok " , " " , lng_key )
elif value == " interface " :
for section in STATISTIC . sections ( ) :
if section . startswith ( " interface " ) :
statistic_reset ( section )
if CONFIG [ " main " ] . getboolean ( " auto_save_statistic " ) :
statistic_save ( PATH + " /statistic.cfg " )
else :
if not STATISTIC . has_section ( " main " ) :
STATISTIC . add_section ( " main " )
STATISTIC [ " main " ] [ " unsaved " ] = " True "
content = config_get ( CONFIG , " interface_menu " , " reset_statistic_ok " , " " , lng_key )
elif value == " user " :
for section in STATISTIC . sections ( ) :
if not section . startswith ( " cluster " ) and not section . startswith ( " local " ) and not section . startswith ( " interface " ) :
statistic_reset ( section )
if CONFIG [ " main " ] . getboolean ( " auto_save_statistic " ) :
statistic_save ( PATH + " /statistic.cfg " )
else :
if not STATISTIC . has_section ( " main " ) :
STATISTIC . add_section ( " main " )
STATISTIC [ " main " ] [ " unsaved " ] = " True "
content = config_get ( CONFIG , " interface_menu " , " reset_statistic_ok " , " " , lng_key )
else :
content = config_get ( CONFIG , " interface_menu " , " reset_statistic_error " , " " , lng_key )
except :
content = config_get ( CONFIG , " interface_menu " , " cmd_error " , " " , lng_key )
else :
# "/admins" command.
# "/moderators" command.
# "/users" command.
# "/guests" command.
executed = False
for section in sections :
if ( cmd == section or cmd == section + " s " ) and section + " s " in source_rights :
count = 0
content = config_get ( CONFIG , " interface_menu " , section + " s_header " , " " , lng_key )
content = replace ( content , source_hash , source_name , source_right , lng_key )
content_member = config_get ( CONFIG , " interface_menu " , section + " s_member " , " " , lng_key )
for ( key , val ) in DATA . items ( section ) :
count + = 1
content = content + replace ( content_member , key , val , section , lng_key )
content = content . replace ( delimiter + " count " + delimiter , str ( count ) )
executed = True
break
# cmd_unknown
if not executed :
content = config_get ( CONFIG , " interface_menu " , " cmd_unknown " , " " , lng_key )
# unsaved
if DATA [ " main " ] . getboolean ( " unsaved " ) and " unsaved " in source_rights :
if CONFIG [ " main " ] . getboolean ( " auto_save_data " ) :
DATA . remove_option ( " main " , " unsaved " )
if data_save ( PATH + " /data.cfg " ) :
content = content + " \n " + config_get ( CONFIG , " interface_menu " , " save_ok " , " " , lng_key )
else :
content = content + " \n " + config_get ( CONFIG , " interface_menu " , " save_error " , " " , lng_key )
DATA [ " main " ] [ " unsaved " ] = " True "
else :
content = content + " \n " + config_get ( CONFIG , " interface_menu " , " save_info " , " " , lng_key )
return content
2023-04-25 01:15:17 -04:00
#### Fields #####
def fields_remove ( fields = None , key = " fields_remove " ) :
2023-11-17 13:37:31 -05:00
search = config_getarray ( CONFIG , " message " , key )
2023-04-25 01:15:17 -04:00
delete = [ ]
for field in fields :
if field in search :
delete . append ( field )
for field in delete :
del fields [ field ]
return fields
#### Fields #####
def fields_generate ( lng_key , fields = None , h = None , n = None , m = False , d = False , r = False , cmd = None , config = None , tpl = None ) :
if not CONFIG [ " main " ] . getboolean ( " fields_message " ) :
return fields
if not fields :
fields = { }
if CONFIG [ " lxmf " ] [ " destination_type_conv " ] != " " :
2023-11-17 13:37:31 -05:00
fields [ 0xB3 ] = CONFIG [ " lxmf " ] . getint ( " destination_type_conv " )
2023-04-25 01:15:17 -04:00
if h :
2023-11-17 13:37:31 -05:00
fields [ 0xAF ] = { }
fields [ 0xAF ] [ " h " ] = h
2023-04-25 01:15:17 -04:00
if n :
2023-11-17 13:37:31 -05:00
fields [ 0xAF ] [ " n " ] = n
2023-04-25 01:15:17 -04:00
else :
2023-11-17 13:37:31 -05:00
fields [ 0xAF ] [ " n " ] = " "
2023-04-25 01:15:17 -04:00
if m or d or r or cmd or config :
2023-11-17 13:37:31 -05:00
fields [ 0xA3 ] = { }
2023-04-25 01:15:17 -04:00
if m :
2023-11-17 13:37:31 -05:00
fields [ 0xA3 ] [ " m " ] = { }
2023-04-25 01:15:17 -04:00
for ( key , val ) in CONFIG . items ( " rights " ) :
if DATA . has_section ( key ) :
2023-11-17 13:37:31 -05:00
fields [ 0xA3 ] [ " m " ] [ key ] = { }
2023-04-25 01:15:17 -04:00
for ( section_key , section_val ) in DATA . items ( key ) :
try :
h = bytes . fromhex ( LXMF_CONNECTION . destination_correct ( section_key ) )
2023-11-17 13:37:31 -05:00
fields [ 0xA3 ] [ " m " ] [ key ] [ h ] = section_val
2023-04-25 01:15:17 -04:00
except :
pass
if d :
2023-11-17 13:37:31 -05:00
fields [ 0xA3 ] [ " d " ] = config_get ( DATA , " main " , " description " , " " , lng_key ) . replace ( CONFIG [ " interface " ] [ " delimiter_output " ] + " n " + CONFIG [ " interface " ] [ " delimiter_output " ] , " \n " )
2023-04-25 01:15:17 -04:00
if r :
2023-11-17 13:37:31 -05:00
fields [ 0xA3 ] [ " r " ] = config_get ( DATA , " main " , " rules " , " " , lng_key ) . replace ( CONFIG [ " interface " ] [ " delimiter_output " ] + " n " + CONFIG [ " interface " ] [ " delimiter_output " ] , " \n " )
2023-04-25 01:15:17 -04:00
if cmd :
2023-11-17 13:37:31 -05:00
fields [ 0xA3 ] [ " cmd " ] = [ ]
2023-04-25 01:15:17 -04:00
if CONFIG . has_option ( " cmds " , cmd ) :
cmds = config_get ( CONFIG , " cmds " , cmd ) . split ( " , " )
for cmd in cmds :
2023-11-17 13:37:31 -05:00
fields [ 0xA3 ] [ " cmd " ] . append ( { " c " : " / " + cmd } )
2023-04-25 01:15:17 -04:00
if config :
2023-11-17 13:37:31 -05:00
fields [ 0xA3 ] [ " config " ] = { }
2023-04-25 01:15:17 -04:00
if CONFIG . has_option ( " configs " , config ) :
configs = config_get ( CONFIG , " configs " , config ) . split ( " , " )
for config in configs :
if config != " " :
key , value = config . split ( " = " , 1 )
2023-11-17 13:37:31 -05:00
fields [ 0xA3 ] [ " config " ] [ key ] = val_to_val ( value )
2023-04-25 01:15:17 -04:00
2023-07-29 13:35:54 -04:00
if cmd or config :
if DATA . has_section ( " topics " ) :
2023-11-17 13:37:31 -05:00
fields [ 0xA3 ] [ " topics " ] = { }
2023-07-29 13:35:54 -04:00
for ( key , val ) in DATA . items ( " topics " ) :
try :
2023-11-17 13:37:31 -05:00
fields [ 0xA3 ] [ " topics " ] [ int ( key ) ] = val
2023-07-29 13:35:54 -04:00
except :
pass
2023-04-25 01:15:17 -04:00
if tpl :
2023-11-17 13:37:31 -05:00
fields [ 0xB1 ] = tpl
2023-04-25 01:15:17 -04:00
return fields
2022-10-21 11:58:11 -04:00
#### Replace #####
def replace ( text , source_hash , source_name , source_right , lng_key ) :
delimiter = CONFIG [ " interface " ] [ " delimiter_output " ]
text = text . replace ( delimiter + " source_address " + delimiter , source_hash )
text = text . replace ( delimiter + " source_name " + delimiter , source_name )
text = text . replace ( delimiter + " source_right " + delimiter , source_right )
text = text . replace ( delimiter + " name " + delimiter , config_get ( CONFIG , " main " , " name " , " " , lng_key ) )
text = text . replace ( delimiter + " display_name " + delimiter , config_get ( CONFIG , " lxmf " , " display_name " , " " , lng_key ) )
text = text . replace ( delimiter + " description " + delimiter , config_get ( DATA , " main " , " description " , " " , lng_key ) )
text = text . replace ( delimiter + " rules " + delimiter , config_get ( DATA , " main " , " rules " , " " , lng_key ) )
text = text . replace ( delimiter + " destination_address " + delimiter , LXMF_CONNECTION . destination_hash_str ( ) )
text = text . replace ( delimiter + " propagation_node " + delimiter , config_get ( CONFIG , " lxmf " , " propagation_node " , " " , lng_key ) )
text = text . replace ( delimiter + " cluster_name " + delimiter , config_get ( CONFIG , " cluster " , " display_name " , " " , lng_key ) . rsplit ( ' / ' , 1 ) [ - 1 ] )
text = text . replace ( delimiter + " n " + delimiter , " \n " )
if delimiter + " count_members " + delimiter in text :
count = 0
2022-10-23 13:26:06 -04:00
for ( section , section_val ) in CONFIG . items ( " rights " ) :
2022-10-21 11:58:11 -04:00
if DATA . has_section ( section ) :
for ( key , val ) in DATA . items ( section ) :
count + = 1
text = text . replace ( delimiter + " count_members " + delimiter , str ( count ) )
if delimiter + " count_pin " + delimiter in text :
count = 0
if DATA . has_section ( " pin " ) :
for ( key , val ) in DATA . items ( " pin " ) :
count + = 1
text = text . replace ( delimiter + " count_pin " + delimiter , str ( count ) )
return text
##############################################################################################################
# Config
#### Config - Get #####
def config_get ( config , section , key , default = " " , lng_key = " " ) :
if not config or section == " " or key == " " : return default
if not config . has_section ( section ) : return default
if config . has_option ( section , key + lng_key ) :
return config [ section ] [ key + lng_key ]
elif config . has_option ( section , key ) :
return config [ section ] [ key ]
return default
2023-11-17 13:37:31 -05:00
def config_getarray ( config , section , key , default = [ ] , lng_key = " " ) :
if not config or section == " " or key == " " : return default
if not config . has_section ( section ) : return default
value = " "
if config . has_option ( section , key + lng_key ) :
value = config [ section ] [ key + lng_key ]
elif config . has_option ( section , key ) :
value = config [ section ] [ key ]
if value != " " :
values_return = [ ]
values = value . split ( " , " )
for value in values :
values_return . append ( val_to_val ( value . strip ( ) ) )
return values_return
return default
2022-10-21 11:58:11 -04:00
def config_getint ( config , section , key , default = 0 , lng_key = " " ) :
if not config or section == " " or key == " " : return default
if not config . has_section ( section ) : return default
if config . has_option ( section , key + lng_key ) :
return config . getint ( section , key + lng_key )
elif config . has_option ( section , key ) :
return config . getint ( section , key )
return default
def config_getboolean ( config , section , key , default = False , lng_key = " " ) :
if not config or section == " " or key == " " : return default
if not config . has_section ( section ) : return default
if config . has_option ( section , key + lng_key ) :
return config [ section ] . getboolean ( key + lng_key )
elif config . has_option ( section , key ) :
return config [ section ] . getboolean ( key )
return default
def config_getsection ( config , section , default = " " , lng_key = " " ) :
if not config or section == " " : return default
if not config . has_section ( section ) : return default
if config . has_section ( section + lng_key ) :
return key + lng_key
elif config . has_section ( section ) :
return key
return default
def config_getoption ( config , section , key , default = False , lng_key = " " ) :
if not config or section == " " or key == " " : return default
if not config . has_section ( section ) : return default
if config . has_option ( section , key + lng_key ) :
return key + lng_key
elif config . has_option ( section , key ) :
return key
return default
2023-04-25 01:15:17 -04:00
#### Config - Set #####
def config_set ( key = None , value = " " ) :
global PATH
try :
file = PATH + " /config.cfg.owr "
if os . path . isfile ( file ) :
fh = open ( file , ' r ' )
data = fh . read ( )
fh . close ( )
data = re . sub ( r ' ^#? ' + key + ' ( +)?=( +)?( \ w+)? ' , key + " = " + value , data , count = 1 , flags = re . MULTILINE )
fh = open ( file , ' w ' )
fh . write ( data )
fh . close ( )
file = PATH + " /config.cfg "
if os . path . isfile ( file ) :
fh = open ( file , ' r ' )
data = fh . read ( )
fh . close ( )
data = re . sub ( r ' ^#? ' + key + ' ( +)?=( +)?( \ w+)? ' , key + " = " + value , data , count = 1 , flags = re . MULTILINE )
fh = open ( file , ' w ' )
fh . write ( data )
fh . close ( )
except :
pass
2022-10-21 11:58:11 -04:00
#### Config - Read #####
def config_read ( file = None , file_override = None ) :
global CONFIG
if file is None :
return False
else :
CONFIG = configparser . ConfigParser ( allow_no_value = True , inline_comment_prefixes = " # " )
CONFIG . sections ( )
if os . path . isfile ( file ) :
try :
if file_override is None :
CONFIG . read ( file , encoding = ' utf-8 ' )
elif os . path . isfile ( file_override ) :
CONFIG . read ( [ file , file_override ] , encoding = ' utf-8 ' )
else :
CONFIG . read ( file , encoding = ' utf-8 ' )
except Exception as e :
return False
else :
if not config_default ( file = file , file_override = file_override ) :
return False
return True
#### Config - Save #####
def config_save ( file = None ) :
global CONFIG
if file is None :
return False
else :
if os . path . isfile ( file ) :
try :
with open ( file , " w " ) as file :
CONFIG . write ( file )
except Exception as e :
return False
else :
return False
return True
#### Config - Default #####
def config_default ( file = None , file_override = None ) :
global CONFIG
if file is None :
return False
elif DEFAULT_CONFIG != " " :
if file_override and DEFAULT_CONFIG_OVERRIDE != " " :
if not os . path . isdir ( os . path . dirname ( file_override ) ) :
try :
os . makedirs ( os . path . dirname ( file_override ) )
except Exception :
return False
if not os . path . exists ( file_override ) :
try :
config_file = open ( file_override , " w " )
config_file . write ( DEFAULT_CONFIG_OVERRIDE )
config_file . close ( )
except :
return False
if not os . path . isdir ( os . path . dirname ( file ) ) :
try :
os . makedirs ( os . path . dirname ( file ) )
except Exception :
return False
try :
config_file = open ( file , " w " )
config_file . write ( DEFAULT_CONFIG )
config_file . close ( )
if not config_read ( file = file , file_override = file_override ) :
return False
except :
return False
else :
return False
if not CONFIG . has_section ( " main " ) : CONFIG . add_section ( " main " )
CONFIG [ " main " ] [ " default_config " ] = " True "
return True
##############################################################################################################
# Data
#### Data - Read #####
def data_read ( file = None ) :
global DATA
if file is None :
return False
else :
DATA = configparser . ConfigParser ( allow_no_value = True , inline_comment_prefixes = " # " )
DATA . sections ( )
if os . path . isfile ( file ) :
try :
DATA . read ( file )
except Exception as e :
return False
else :
if not data_default ( file = file ) :
return False
return True
#### Data - Save #####
def data_save ( file = None ) :
global DATA
if file is None :
return False
else :
if os . path . isfile ( file ) :
try :
with open ( file , " w " ) as file :
DATA . write ( file )
except Exception as e :
return False
else :
return False
return True
#### Data - Save #####
def data_save_periodic ( initial = False ) :
data_timer = threading . Timer ( CONFIG . getint ( " main " , " periodic_save_data_interval " ) * 60 , data_save_periodic )
data_timer . daemon = True
data_timer . start ( )
if initial :
return
global DATA
if DATA . has_section ( " main " ) :
if DATA [ " main " ] . getboolean ( " unsaved " ) :
DATA . remove_option ( " main " , " unsaved " )
if not data_save ( PATH + " /data.cfg " ) :
DATA [ " main " ] [ " unsaved " ] = " True "
#### Data - Default #####
def data_default ( file = None ) :
global DATA
if file is None :
return False
elif DEFAULT_DATA != " " :
if not os . path . isdir ( os . path . dirname ( file ) ) :
try :
os . makedirs ( os . path . dirname ( file ) )
except Exception :
return False
try :
data_file = open ( file , " w " )
data_file . write ( DEFAULT_DATA )
data_file . close ( )
if not data_read ( file = file ) :
return False
except :
return False
else :
return False
return True
##############################################################################################################
# Statistic/Counter
#### Statistic #####
def statistic ( cmd = " add " , section = " global " , key = " " , value = 1 ) :
global STATISTIC
changed = False
if cmd == " add " :
statistic_add ( section , value )
changed = True
elif cmd == " del " :
statistic_del ( section )
changed = True
elif cmd == " reset " :
statistic_reset ( section )
changed = True
elif cmd == " get " :
return statistic_get ( section )
elif cmd == " value_set " :
statistic_value_set ( section , key , value )
changed = True
elif cmd == " value_get " :
return statistic_value_get ( section , key )
elif cmd == " read " :
return statistic_read ( PATH + " /statistic.cfg " )
elif cmd == " save " :
return statistic_save ( PATH + " /statistic.cfg " )
if changed :
if CONFIG [ " main " ] . getboolean ( " auto_save_statistic " ) :
statistic_save ( PATH + " /statistic.cfg " )
else :
if not STATISTIC . has_section ( " main " ) :
STATISTIC . add_section ( " main " )
STATISTIC [ " main " ] [ " unsaved " ] = " True "
#### Statistic - Add #####
def statistic_add ( section = " global " , value = 1 ) :
global STATISTIC
if not STATISTIC . has_section ( section ) :
statistic_default ( section )
statistic_recalculate ( section )
date = datetime . date . today ( )
day = date . timetuple ( ) . tm_yday
month = date . timetuple ( ) . tm_mon
year = date . timetuple ( ) . tm_year
2023-06-06 07:23:31 -04:00
week = date . isocalendar ( ) [ 1 ]
2022-10-21 11:58:11 -04:00
#day
if STATISTIC [ section ] [ " day_index " ] == str ( day ) :
STATISTIC [ section ] [ " day_value " ] = str ( STATISTIC . getint ( section , " day_value " ) + value )
#week
if STATISTIC [ section ] [ " week_index " ] == str ( week ) :
STATISTIC [ section ] [ " week_value " ] = str ( STATISTIC . getint ( section , " week_value " ) + value )
#month
if STATISTIC [ section ] [ " month_index " ] == str ( month ) :
STATISTIC [ section ] [ " month_value " ] = str ( STATISTIC . getint ( section , " month_value " ) + value )
#year
if STATISTIC [ section ] [ " year_index " ] == str ( year ) :
STATISTIC [ section ] [ " year_value " ] = str ( STATISTIC . getint ( section , " year_value " ) + value )
#all
STATISTIC [ section ] [ " all_value " ] = str ( STATISTIC . getint ( section , " all_value " ) + value )
#max
if STATISTIC . getint ( section , " day_value " ) > STATISTIC . getint ( section , " max_value " ) :
STATISTIC [ section ] [ " max_value " ] = STATISTIC [ section ] [ " day_value " ]
STATISTIC [ section ] [ " max_index " ] = time . strftime ( " % Y- % m- %d " , time . localtime ( time . time ( ) ) )
return
#### Statistic - Recalculate #####
def statistic_recalculate ( section = " global " ) :
global STATISTIC
if not STATISTIC . has_section ( section ) :
return
date = datetime . date . today ( )
day = date . timetuple ( ) . tm_yday
month = date . timetuple ( ) . tm_mon
year = date . timetuple ( ) . tm_year
2023-06-06 07:23:31 -04:00
week = date . isocalendar ( ) [ 1 ]
2022-10-21 11:58:11 -04:00
#day
if STATISTIC [ section ] [ " day_index " ] != str ( day ) :
if STATISTIC [ section ] [ " day_index " ] == str ( day - 1 ) :
STATISTIC [ section ] [ " last_day_value " ] = STATISTIC [ section ] [ " day_value " ]
STATISTIC [ section ] [ " last_day_index " ] = str ( day - 1 )
else :
STATISTIC [ section ] [ " last_day_value " ] = " 0 "
STATISTIC [ section ] [ " last_day_index " ] = str ( day - 1 )
STATISTIC [ section ] [ " day_value " ] = " 0 "
STATISTIC [ section ] [ " day_index " ] = str ( day )
#week
if STATISTIC [ section ] [ " week_index " ] != str ( week ) :
if STATISTIC [ section ] [ " week_index " ] == str ( week - 1 ) :
STATISTIC [ section ] [ " last_week_value " ] = STATISTIC [ section ] [ " week_value " ]
STATISTIC [ section ] [ " last_week_index " ] = str ( week - 1 )
else :
STATISTIC [ section ] [ " last_week_value " ] = " 0 "
STATISTIC [ section ] [ " last_week_index " ] = str ( week - 1 )
STATISTIC [ section ] [ " week_value " ] = " 0 "
STATISTIC [ section ] [ " week_index " ] = str ( week )
#month
if STATISTIC [ section ] [ " month_index " ] != str ( month ) :
if STATISTIC [ section ] [ " month_index " ] == str ( month - 1 ) :
STATISTIC [ section ] [ " last_month_value " ] = STATISTIC [ section ] [ " month_value " ]
STATISTIC [ section ] [ " last_month_index " ] = str ( month - 1 )
else :
STATISTIC [ section ] [ " last_month_value " ] = " 0 "
STATISTIC [ section ] [ " last_month_index " ] = str ( month - 1 )
STATISTIC [ section ] [ " month_value " ] = " 0 "
STATISTIC [ section ] [ " month_index " ] = str ( month )
#year
if STATISTIC [ section ] [ " year_index " ] != str ( year ) :
if STATISTIC [ section ] [ " year_index " ] == str ( year - 1 ) :
STATISTIC [ section ] [ " last_year_value " ] = STATISTIC [ section ] [ " year_value " ]
STATISTIC [ section ] [ " last_year_index " ] = str ( year - 1 )
else :
STATISTIC [ section ] [ " last_year_value " ] = " 0 "
STATISTIC [ section ] [ " last_year_index " ] = str ( year - 1 )
STATISTIC [ section ] [ " year_value " ] = " 0 "
STATISTIC [ section ] [ " year_index " ] = str ( year )
return
#### Statistic - Del #####
def statistic_del ( section = " global " ) :
global STATISTIC
if STATISTIC . has_section ( section ) :
STATISTIC . remove_section ( section )
#### Statistic - Reset #####
def statistic_reset ( section = " global " ) :
statistic_del ( section )
statistic_add ( section , 0 )
#### Statistic - Get #####
def statistic_get ( section = " global " ) :
global STATISTIC
text = " "
if STATISTIC . has_section ( section ) :
statistic_recalculate ( section )
for ( key , val ) in STATISTIC . items ( section ) :
if key . endswith ( " _value " ) :
text = text + key . capitalize ( ) + " : " + val + " \n "
text = text . replace ( " _value " , " " )
text = text . replace ( " _ " , " " )
text = text . strip ( )
return text
#### Statistic - Value set #####
def statistic_value_set ( section , key , value ) :
global STATISTIC
if not STATISTIC . has_section ( section ) :
statistic_default ( section )
STATISTIC [ section ] [ key ] = value
#### Statistic - Value get #####
def statistic_value_get ( section , key , default = " " ) :
global STATISTIC
if STATISTIC . has_section ( section ) :
if STATISTIC . has_option ( section , key ) :
return STATISTIC [ section ] [ key ]
return default
#### Statistic - Read #####
def statistic_read ( file = None ) :
global STATISTIC
if file is None :
return False
else :
STATISTIC = configparser . ConfigParser ( allow_no_value = True , inline_comment_prefixes = " # " )
STATISTIC . sections ( )
if os . path . isfile ( file ) :
try :
STATISTIC . read ( file )
except Exception as e :
return False
return True
#### Statistic - Save #####
def statistic_save ( file = None ) :
global STATISTIC
if file is None :
return False
else :
try :
with open ( file , " w " ) as file :
if STATISTIC . has_section ( " main " ) :
STATISTIC . remove_section ( " main " )
STATISTIC . write ( file )
except Exception as e :
return False
return True
#### Statistic - Save #####
def statistic_save_periodic ( initial = False ) :
statistic_timer = threading . Timer ( CONFIG . getint ( " main " , " periodic_save_statistic_interval " ) * 60 , statistic_save_periodic )
statistic_timer . daemon = True
statistic_timer . start ( )
if initial :
return
global STATISTIC
if STATISTIC . has_section ( " main " ) :
if STATISTIC [ " main " ] . getboolean ( " unsaved " ) :
STATISTIC . remove_section ( " main " )
if not statistic_save ( PATH + " /statistic.cfg " ) :
if not STATISTIC . has_section ( " main " ) :
STATISTIC . add_section ( " main " )
STATISTIC [ " main " ] [ " unsaved " ] = " True "
#### Statistic - Default #####
def statistic_default ( section = " global " ) :
global STATISTIC
date = datetime . date . today ( )
day = date . timetuple ( ) . tm_yday
month = date . timetuple ( ) . tm_mon
year = date . timetuple ( ) . tm_year
2023-06-06 07:23:31 -04:00
week = date . isocalendar ( ) [ 1 ]
2022-10-21 11:58:11 -04:00
STATISTIC . add_section ( section )
STATISTIC [ section ] [ " day_value " ] = " 0 "
STATISTIC [ section ] [ " day_index " ] = str ( day )
STATISTIC [ section ] [ " last_day_value " ] = " 0 "
STATISTIC [ section ] [ " last_day_index " ] = str ( day - 1 )
STATISTIC [ section ] [ " week_value " ] = " 0 "
STATISTIC [ section ] [ " week_index " ] = str ( week )
STATISTIC [ section ] [ " last_week_value " ] = " 0 "
STATISTIC [ section ] [ " last_week_index " ] = str ( week - 1 )
STATISTIC [ section ] [ " month_value " ] = " 0 "
STATISTIC [ section ] [ " month_index " ] = str ( month )
STATISTIC [ section ] [ " last_month_value " ] = " 0 "
STATISTIC [ section ] [ " last_month_index " ] = str ( month - 1 )
STATISTIC [ section ] [ " year_value " ] = " 0 "
STATISTIC [ section ] [ " year_index " ] = str ( year )
STATISTIC [ section ] [ " last_year_value " ] = " 0 "
STATISTIC [ section ] [ " last_year_index " ] = str ( year - 1 )
STATISTIC [ section ] [ " all_value " ] = " 0 "
STATISTIC [ section ] [ " max_value " ] = " 0 "
STATISTIC [ section ] [ " max_index " ] = time . strftime ( " % Y- % m- %d " , time . localtime ( time . time ( ) ) )
##############################################################################################################
# Value convert
2023-04-25 01:15:17 -04:00
def val_to_bool ( val , fallback_true = True , fallback_false = False ) :
2022-10-21 11:58:11 -04:00
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 != " " :
2023-04-25 01:15:17 -04:00
return fallback_true
2022-10-21 11:58:11 -04:00
else :
2023-04-25 01:15:17 -04:00
return fallback_false
2022-10-21 11:58:11 -04:00
2023-06-05 08:36:42 -04:00
def val_to_val ( val ) :
if val . isdigit ( ) :
return int ( val )
elif val . isnumeric ( ) :
return float ( val )
elif val . lower ( ) == " true " :
return True
elif val . lower ( ) == " false " :
return False
2023-11-17 13:37:31 -05:00
elif val . startswith ( " 0x " ) or val . startswith ( " 0X " ) :
try :
val_int = int ( val , 16 )
return val_int
except :
pass
return val
2023-06-05 08:36:42 -04:00
2022-10-21 11:58:11 -04:00
##############################################################################################################
# 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 , service = False ) :
global PATH
global PATH_RNS
global LOG_LEVEL
global LOG_FILE
global RNS_MAIN_CONNECTION
global LXMF_CONNECTION
global RNS_CONNECTION
2023-04-25 01:15:17 -04:00
2022-10-21 11:58:11 -04:00
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
if service :
LOG_LEVEL = LOG_LEVEL_SERVICE
if path_log is not None :
if path_log . endswith ( " / " ) :
path_log = path_log [ : - 1 ]
LOG_FILE = path_log
else :
LOG_FILE = PATH
LOG_FILE = LOG_FILE + " / " + NAME + " .log "
rns_loglevel = None
if not config_read ( PATH + " /config.cfg " , PATH + " /config.cfg.owr " ) :
print ( " Config - Error reading config file " + PATH + " /config.cfg " )
panic ( )
if not data_read ( PATH + " /data.cfg " ) :
print ( " Data - Error reading data file " + PATH + " /data.cfg " )
panic ( )
if CONFIG [ " main " ] . getboolean ( " default_config " ) :
print ( " Exit! " )
print ( " First start with the default config! " )
print ( " You should probably edit the config file \" " + PATH + " /config.cfg \" to suit your needs and use-case! " )
print ( " You should make all your changes at the user configuration file \" " + PATH + " /config.cfg.owr \" to override the default configuration file! " )
print ( " Then restart this program again! " )
exit ( )
if not CONFIG [ " main " ] . getboolean ( " enabled " ) :
print ( " Disabled in config file. Exit! " )
exit ( )
if CONFIG [ " statistic " ] . getboolean ( " enabled " ) :
2023-07-29 13:35:54 -04:00
if not statistic_read ( PATH + " /statistic.cfg " ) :
print ( " Statistic - Error reading statistic file " + PATH + " /statistic.cfg " )
panic ( )
2022-10-21 11:58:11 -04:00
2023-04-25 01:15:17 -04:00
if CONFIG . has_section ( " cmds " ) and CONFIG . has_section ( " rights " ) :
for ( key , val ) in CONFIG . items ( " cmds " ) :
if val != " " and CONFIG . has_option ( " rights " , key ) :
CONFIG [ " rights " ] [ key ] + = " ,interface, " + val
2022-10-21 11:58:11 -04:00
RNS_MAIN_CONNECTION = RNS . Reticulum ( configdir = PATH_RNS , loglevel = rns_loglevel )
log ( " ............................................................................... " , LOG_INFO )
log ( " Name: " + CONFIG [ " main " ] [ " name " ] , LOG_INFO )
log ( " Program File: " + __file__ , LOG_INFO )
log ( " Config File: " + PATH + " /config " , LOG_INFO )
log ( " Data File: " + PATH + " /data.cfg " , LOG_INFO )
log ( " Version: " + VERSION , LOG_INFO )
log ( " Copyright: " + COPYRIGHT , LOG_INFO )
log ( " ............................................................................... " , LOG_INFO )
log ( " LXMF - Connecting ... " , LOG_DEBUG )
if CONFIG . has_option ( " lxmf " , " propagation_node " ) :
config_propagation_node = CONFIG [ " lxmf " ] [ " propagation_node " ]
else :
config_propagation_node = None
2023-04-25 01:15:17 -04:00
if CONFIG . has_option ( " lxmf " , " propagation_node_active " ) :
config_propagation_node_active = CONFIG [ " lxmf " ] [ " propagation_node_active " ]
else :
config_propagation_node_active = None
2022-10-21 11:58:11 -04:00
if path is None :
path = PATH
2022-11-08 12:34:34 -05:00
display_name = CONFIG [ " lxmf " ] [ " display_name " ]
2023-04-25 01:15:17 -04:00
announce_data = None
2022-11-08 12:34:34 -05:00
if CONFIG [ " lxmf " ] [ " destination_type_conv " ] != " " :
try :
2023-04-25 01:15:17 -04:00
if CONFIG [ " main " ] . getboolean ( " fields_announce " ) :
2023-11-17 13:37:31 -05:00
announce_data = umsgpack . packb ( { " c " : CONFIG [ " lxmf " ] [ " display_name " ] . encode ( " utf-8 " ) , " t " : None , " f " : { 0xB3 : CONFIG [ " lxmf " ] . getint ( " destination_type_conv " ) } } )
2023-04-25 01:15:17 -04:00
else :
display_name + = chr ( CONFIG [ " lxmf " ] . getint ( " destination_type_conv " ) )
2022-11-08 12:34:34 -05:00
except :
pass
2022-10-21 11:58:11 -04:00
LXMF_CONNECTION = lxmf_connection (
storage_path = path ,
identity_file = " identity " ,
identity = None ,
destination_name = CONFIG [ " lxmf " ] [ " destination_name " ] ,
destination_type = CONFIG [ " lxmf " ] [ " destination_type " ] ,
2022-11-08 12:34:34 -05:00
display_name = display_name ,
2023-04-25 01:15:17 -04:00
announce_data = announce_data ,
announce_hidden = CONFIG [ " lxmf " ] . getboolean ( " announce_hidden " ) ,
2022-10-21 11:58:11 -04:00
send_delay = CONFIG [ " lxmf " ] [ " send_delay " ] ,
desired_method = CONFIG [ " lxmf " ] [ " desired_method " ] ,
propagation_node = config_propagation_node ,
2023-04-25 01:15:17 -04:00
propagation_node_auto = CONFIG [ " lxmf " ] . getboolean ( " propagation_node_auto " ) ,
propagation_node_active = config_propagation_node_active ,
2022-10-21 11:58:11 -04:00
try_propagation_on_fail = CONFIG [ " lxmf " ] . getboolean ( " try_propagation_on_fail " ) ,
announce_startup = CONFIG [ " lxmf " ] . getboolean ( " announce_startup " ) ,
announce_startup_delay = CONFIG [ " lxmf " ] [ " announce_startup_delay " ] ,
announce_periodic = CONFIG [ " lxmf " ] . getboolean ( " announce_periodic " ) ,
announce_periodic_interval = CONFIG [ " lxmf " ] [ " announce_periodic_interval " ] ,
sync_startup = CONFIG [ " lxmf " ] . getboolean ( " sync_startup " ) ,
sync_startup_delay = CONFIG [ " lxmf " ] [ " sync_startup_delay " ] ,
sync_limit = CONFIG [ " lxmf " ] [ " sync_limit " ] ,
sync_periodic = CONFIG [ " lxmf " ] . getboolean ( " sync_periodic " ) ,
sync_periodic_interval = CONFIG [ " lxmf " ] [ " sync_periodic_interval " ] )
LXMF_CONNECTION . register_announce_callback ( lxmf_announce_callback )
LXMF_CONNECTION . register_message_received_callback ( lxmf_message_received_callback )
2023-04-25 01:15:17 -04:00
LXMF_CONNECTION . register_config_set_callback ( config_set )
2022-10-21 11:58:11 -04:00
if CONFIG [ " statistic " ] . getboolean ( " enabled " ) :
LXMF_CONNECTION . register_message_notification_success_callback ( lxmf_message_notification_success_callback )
LXMF_CONNECTION . register_message_notification_failed_callback ( lxmf_message_notification_failed_callback )
log ( " LXMF - Connected " , LOG_DEBUG )
log ( " ............................................................................... " , LOG_FORCE )
log ( " LXMF - Address: " + RNS . prettyhexrep ( LXMF_CONNECTION . destination_hash ( ) ) , LOG_FORCE )
log ( " ............................................................................... " , LOG_FORCE )
2022-10-22 05:50:19 -04:00
if CONFIG [ " cluster " ] . getboolean ( " enabled " ) or CONFIG [ " router " ] . getboolean ( " enabled " ) or CONFIG [ " high_availability " ] . getboolean ( " enabled " ) :
2022-10-21 11:58:11 -04:00
announce_data = defaultdict ( dict )
2022-10-22 05:50:19 -04:00
announce_data [ " h " ] = LXMF_CONNECTION . destination_hash_str ( )
2022-10-21 11:58:11 -04:00
if CONFIG [ " high_availability " ] . getboolean ( " enabled " ) :
announce_data [ " ha " ] = " 1 "
announce_data [ " ha_r " ] = CONFIG [ " high_availability " ] [ " role " ]
else :
announce_data [ " ha " ] = " 0 "
if CONFIG [ " cluster " ] . getboolean ( " enabled " ) :
announce_data [ " c " ] = " 1 "
2022-10-22 05:50:19 -04:00
announce_data [ " c_n " ] = CONFIG [ " cluster " ] [ " display_name " ] . replace ( " " , " " )
2022-10-21 11:58:11 -04:00
else :
announce_data [ " c " ] = " 0 "
2022-10-22 05:50:19 -04:00
if CONFIG [ " router " ] . getboolean ( " enabled " ) :
announce_data [ " r " ] = " 1 "
announce_data [ " r_n " ] = CONFIG [ " router " ] [ " display_name " ] . replace ( " " , " " )
else :
announce_data [ " r " ] = " 0 "
2022-10-21 11:58:11 -04:00
log ( " RNS - Connecting ... " , LOG_DEBUG )
RNS_CONNECTION = rns_connection (
storage_path = path ,
identity_file = " identity " ,
identity = LXMF_CONNECTION . identity ,
destination_name = CONFIG [ " cluster " ] [ " name " ] ,
destination_type = CONFIG [ " cluster " ] [ " type " ] ,
announce_startup = CONFIG [ " rns " ] . getboolean ( " announce_startup " ) ,
announce_startup_delay = CONFIG [ " rns " ] [ " announce_startup_delay " ] ,
announce_periodic = CONFIG [ " rns " ] . getboolean ( " announce_periodic " ) ,
announce_periodic_interval = CONFIG [ " rns " ] [ " announce_periodic_interval " ] ,
2023-04-25 01:15:17 -04:00
announce_data = json . dumps ( announce_data , separators = ( ' , ' , ' : ' ) ) ,
announce_hidden = CONFIG [ " rns " ] . getboolean ( " announce_hidden " )
2022-10-21 11:58:11 -04:00
)
RNS_CONNECTION . register_announce_callback ( rns_announce_callback )
log ( " RNS - Connected " , LOG_DEBUG )
if CONFIG [ " main " ] . getboolean ( " periodic_save_data " ) :
data_save_periodic ( True )
if CONFIG [ " main " ] . getboolean ( " periodic_save_statistic " ) :
statistic_save_periodic ( True )
while True :
time . sleep ( 1 )
#### 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 ( " -s " , " --service " , action = " store_true " , default = False , help = " Running as a service and should log to file " )
parser . add_argument ( " --exampleconfig " , action = " store_true " , default = False , help = " Print verbose configuration example to stdout and exit " )
parser . add_argument ( " --exampleconfigoverride " , action = " store_true " , default = False , help = " Print verbose configuration example to stdout and exit " )
parser . add_argument ( " --exampledata " , action = " store_true " , default = False , help = " Print verbose configuration example to stdout and exit " )
params = parser . parse_args ( )
if params . exampleconfig :
print ( " Config File: " + PATH + " /config.cfg " )
print ( " Content: " )
print ( DEFAULT_CONFIG )
exit ( )
if params . exampleconfigoverride :
print ( " Config Override File: " + PATH + " /config.cfg.owr " )
print ( " Content: " )
print ( DEFAULT_CONFIG_OVERRIDE )
exit ( )
if params . exampledata :
print ( " Data File: " + PATH + " /data.cfg " )
print ( " Content: " )
print ( DEFAULT_DATA )
exit ( )
setup ( path = params . path , path_rns = params . path_rns , path_log = params . path_log , loglevel = params . loglevel , service = params . service )
except KeyboardInterrupt :
print ( " Terminated by CTRL-C " )
exit ( )
##############################################################################################################
# Files
#### Default configuration override file ####
DEFAULT_CONFIG_OVERRIDE = ''' # 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
2023-04-25 01:15:17 -04:00
# Set propagation node automatically.
propagation_node_auto = True
2022-10-21 11:58:11 -04:00
# 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.
2022-10-22 05:50:19 -04:00
# This feature can be used to build multi level group structures.
# All send messages that match the name (all levels) will be received.
# The last name is the main name of this group and is used as source for send messages.
2022-10-21 11:58:11 -04:00
# No spaces are allowed in the name.
display_name = County / Region / City
2022-10-22 05:50:19 -04:00
#### Router settings ####
[ router ]
# Enable/Disable router functionality.
enabled = True
# Comma-separated list with the names for which the messages are to be routed/repeated.
# The names and levels must match the used display_name of the cluster accordingly.
# No spaces are allowed in the name.
display_name = Country , Country / Region
2022-10-21 11:58:11 -04:00
#### High availability settings ####
[ high_availability ]
# Enable/Disable this functionality.
enabled = False
# Role of this node (master/slave)
role = master
# Peer address
peer =
#### Statistic/Counter settings ####
[ statistic ]
# Enable/Disable this functionality.
enabled = True
'''
#### Default configuration file ####
DEFAULT_CONFIG = ''' # This is the default config file.
# You should probably edit it to suit your needs and use-case.
#### Main program settings ####
[ main ]
# Enable/Disable this functionality.
enabled = True
# Name of the program. Only for display in the log or program startup.
name = Distribution Group
# Default language.
# The following languages are available. Other languages can be defined below in the "interface" settings.
# You have to add the language key to the settings to be used. For example "-de".
# en/de
lng = en
# Auto save changes.
# If there are changes in the data or statistics, they can be saved directly in the files.
# Attention: This can lead to very high write cycles.
# If you want to prevent frequent writing, please set this to 'False' and use the peridodic save function.
auto_save_data = True
auto_save_statistic = False
# Periodic actions - Save changes periodically.
periodic_save_data = True
periodic_save_data_interval = 30 #Minutes
periodic_save_statistic = True
periodic_save_statistic_interval = 30 #Minutes
# Auto apply name from announces.
# As an alternative to defining the nickname manually, it can be used automatically from the announce.
2022-11-08 12:34:34 -05:00
auto_name_add = True
2022-10-21 11:58:11 -04:00
auto_name_def = True
2023-06-05 08:36:42 -04:00
auto_name_change = True
2022-10-21 11:58:11 -04:00
2023-04-25 01:15:17 -04:00
# Transport extended data in the announce and fields variable.
# This is needed for the integration of advanced client apps.
fields_announce = False
fields_message = False
2022-10-21 11:58:11 -04:00
#### LXMF connection settings ####
[ lxmf ]
# Destination name & type need to fits the LXMF protocoll
# to be compatibel with other LXMF programs.
destination_name = lxmf
destination_type = delivery
2023-06-05 08:36:42 -04:00
destination_type_conv = #4=Group, 6=Channel (Only for use with Communicator-Software.)
2022-10-21 11:58:11 -04:00
# 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
# Default send method.
desired_method = direct #direct/propagated
# Propagation node address/hash.
2023-04-25 01:15:17 -04:00
propagation_node =
# Set propagation node automatically.
propagation_node_auto = True
# Current propagation node (Automatically set by the software).
propagation_node_active =
2022-10-21 11:58:11 -04:00
# 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
# The peer is announced at startup
# to let other peers reach it immediately.
announce_startup = Yes
announce_startup_delay = 0 #Seconds
# The peer is announced periodically
# to let other peers reach it.
announce_periodic = Yes
announce_periodic_interval = 120 #Minutes
2023-04-25 01:15:17 -04:00
# The announce is hidden for client applications
# but is still used for the routing tables.
announce_hidden = No
2022-10-21 11:58:11 -04:00
# Some waiting time after message send
# for LXMF/Reticulum processing.
send_delay = 0 #Seconds
# Sync LXMF messages at startup.
sync_startup = No
sync_startup_delay = 0 #Seconds
# Sync LXMF messages periodically.
sync_periodic = No
# The sync interval in minutes.
sync_periodic_interval = 360 #Minutes
# Automatic LXMF syncs will only
# download x messages at a time. You can change
# this number, or set the option to 0 to disable
# the limit, and download everything every time.
2023-06-05 08:36:42 -04:00
sync_limit = 0
2022-10-21 11:58:11 -04:00
# Allow only messages with valid signature.
signature_validated = No
signature_validated_new = No
signature_validated_known = No
#### RNS connection settings ####
[ rns ]
# Destination name & type need to fits the RNS protocoll
# to be compatibel with other RNS programs.
destination_name = grp
destination_type = cluster
# The peer is announced at startup
# to let other peers reach it immediately.
announce_startup = Yes
announce_startup_delay = 0 #Seconds
# The peer is announced periodically
# to let other peers reach it.
announce_periodic = Yes
announce_periodic_interval = 120 #Minutes
2023-04-25 01:15:17 -04:00
# The announce is hidden for client applications
# but is still used for the routing tables.
announce_hidden = No
2022-10-21 11:58:11 -04:00
#### Cluster settings ####
[ cluster ]
# Enable/Disable this functionality.
2023-04-25 01:15:17 -04:00
enabled = False
2022-10-21 11:58:11 -04:00
# 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.
2022-10-22 05:50:19 -04:00
# This feature can be used to build multi level group structures.
# All send messages that match the name (all levels) will be received.
# The last name is the main name of this group and is used as source for send messages.
2022-10-21 11:58:11 -04:00
# No spaces are allowed in the name.
display_name = County / Region / City
# Define the delimiters for cluster input.
delimiter_input = @
2022-10-22 05:50:19 -04:00
#### Router settings ####
[ router ]
# Enable/Disable router functionality.
2023-04-25 01:15:17 -04:00
enabled = False
2022-10-22 05:50:19 -04:00
# Comma-separated list with the names for which the messages are to be routed/repeated.
# The names and levels must match the used display_name of the cluster accordingly.
# No spaces are allowed in the name.
display_name = Country , Country / Region
2022-10-21 11:58:11 -04:00
#### High availability settings ####
[ high_availability ]
# Enable/Disable this functionality.
enabled = False
# Role of this node (master/slave)
role = master
# Peer address
peer =
# Sync
sync_periodic_interval = 30 #Minutes
# Sync at startup
sync_startup = No
sync_startup_delay = 0 #Seconds
# Heartbeat
heartbeat_interval = 1 #Minutes
heartbeat_timeout = 15 #Minutes
#### Message settings ####
[ message ]
## Each message received (message and command) ##
2023-06-05 08:36:42 -04:00
# Deny message if the title/content/fields contains the following content.
# Comma-separated list with text or field keys.
# *=any
deny_title =
deny_content =
deny_fields =
2022-10-21 11:58:11 -04:00
# Text is added.
2023-04-25 01:15:17 -04:00
receive_title_prefix =
2022-10-21 11:58:11 -04:00
receive_prefix =
receive_suffix =
# Text is replaced.
receive_search =
receive_replace =
# Text is replaced by regular expression.
receive_regex_search =
receive_regex_replace =
# Length limitation.
receive_length_min = 0 #0=any length
receive_length_max = 0 #0=any length
## Each message send (message) ##
# Text is added.
2023-04-25 01:15:17 -04:00
send_title_prefix = #!source_name!!n!<!source_address!>!n!
2022-10-21 11:58:11 -04:00
send_prefix = ! source_name ! ! n ! < ! source_address ! > ! n !
send_suffix =
# Text is replaced.
send_search =
send_replace =
# Text is replaced by regular expression.
send_regex_search =
send_regex_replace =
# Length limitation.
send_length_min = 0 #0=any length
send_length_max = 0 #0=any length
## Each cluster message received (message and command) ##
# Text is added.
2023-04-25 01:15:17 -04:00
cluster_receive_title_prefix = #@!cluster_source!->
2022-10-21 11:58:11 -04:00
cluster_receive_prefix = @ ! cluster_source ! - >
cluster_receive_suffix =
# Text is replaced.
cluster_receive_search =
cluster_receive_replace =
# Text is replaced by regular expression.
cluster_receive_regex_search =
cluster_receive_regex_replace =
# Length limitation.
cluster_receive_length_min = 0 #0=any length
cluster_receive_length_max = 0 #0=any length
## Each cluster message send (message) ##
# Text is added.
2023-04-25 01:15:17 -04:00
cluster_send_title_prefix = #@!cluster_destination!!n!!source_name!!n!<!source_address!>!n!
2022-10-21 11:58:11 -04:00
cluster_send_prefix = @ ! cluster_destination ! ! n ! ! source_name ! ! n ! < ! source_address ! > ! n !
cluster_send_suffix =
# Text is replaced.
cluster_send_search =
cluster_send_replace =
# Text is replaced by regular expression.
cluster_send_regex_search =
cluster_send_regex_replace =
# Length limitation.
cluster_send_length_min = 0 #0=any length
cluster_send_length_max = 0 #0=any length
## Each pinned message ##
pin_id = % % y % % m % % d - % % H % % M % % S
# Define which message timestamp should be used.
timestamp = client #client/server
2022-12-07 11:05:23 -05:00
# Use title/fields.
title = Yes
fields = Yes
2023-04-25 01:15:17 -04:00
# Comma-separated list with fields which will be removed.
fields_remove =
fields_remove_anonymous =
2022-10-21 11:58:11 -04:00
#### Statistic/Counter settings ####
[ statistic ]
# Enable/Disable this functionality.
enabled = True
# Create cluster statistics.
cluster = True
2022-10-22 05:50:19 -04:00
# Create router statistics.
router = True
2022-10-21 11:58:11 -04:00
# Create local/group statistics.
local = True
# Create interface statistics.
interface = True
# Create user statistics.
user = True
#### User rights assignment ####
# Define the individual rights for the different user types.
# Delimiter for different rights: ,
[ rights ]
2023-06-05 08:36:42 -04:00
admin = interface , receive_local , receive_cluster , receive_cluster_pin_add , receive_cluster_loop , receive_cluster_join , receive_join , receive_leave , receive_invite , receive_kick , receive_block , receive_unblock , receive_allow , receive_deny , receive_description , receive_rules , receive_pin_add , receive_pin_remove , receive_name_def , receive_name_change , receive_auto_name_def , receive_auto_name_change , reply_signature , reply_cluster_enabled , reply_cluster_right , reply_interface_enabled , reply_interface_right , reply_local_enabled , reply_local_right , reply_block , reply_length_min , reply_length_max , send_local , send_cluster , help , update , update_all , join , leave , name , address , info , pin , pin_add , pin_remove , cluster_pin_add , description , rules , readme , time , version , groups , members , admins , moderators , users , guests , search , activitys , statistic , statistic_min , statistic_full , statistic_cluster , statistic_router , statistic_local , statistic_interface , statistic_self , statistic_user , status , delivery , enable_local , enable_cluster , auto_add_user , auto_add_user_type , auto_add_cluster , auto_add_router , invite_user , invite_user_type , allow_user , allow_user_type , deny_user , deny_user_type , description_set , rules_set , announce , sync , show_run , show , add , del , move , rename , invite , kick , block , unblock , allow , deny , load , save , reload , reset , unsaved
mod = interface , receive_local , receive_cluster , receive_cluster_pin_add , receive_cluster_loop , receive_join , receive_leave , receive_invite , receive_kick , receive_block , receive_unblock , receive_allow , receive_deny , receive_description , receive_rules , receive_pin_add , reply_signature , reply_cluster_enabled , reply_cluster_right , reply_interface_enabled , reply_interface_right , reply_local_enabled , reply_local_right , reply_block , reply_length_min , reply_length_max , send_local , send_cluster , help , update , update_all , join , leave , name , address , info , pin , pin_add , pin_remove , cluster_pin_add , description , rules , readme , time , version , groups , members , admins , moderators , users , guests , search , activitys , statistic , statistic_min , statistic_cluster , statistic_router , statistic_local , statistic_self , delivery , show , add , del , move , rename , invite , kick , block , unblock , allow , deny
2023-04-25 01:15:17 -04:00
user = interface , receive_local , receive_cluster , receive_cluster_pin_add , receive_cluster_loop , receive_join , receive_leave , receive_invite , receive_kick , receive_block , receive_unblock , receive_allow , receive_description , receive_rules , receive_pin_add , reply_signature , reply_cluster_enabled , reply_cluster_right , reply_interface_enabled , reply_interface_right , reply_local_enabled , reply_local_right , reply_block , reply_length_min , reply_length_max , send_local , send_cluster , help , update , join , leave , name , address , info , pin , pin_add , pin_remove , cluster_pin_add , description , rules , readme , time , version , groups , members , admins , moderators , users , guests , search , activitys , statistic , statistic_min , statistic_cluster , statistic_router , statistic_local , statistic_self , delivery , invite
guest = interface , receive_local , receive_cluster , receive_cluster_loop , update , join , leave
wait = interface , update , join , leave
#### User cmd assignment ####
# Define the individual cmds for the different user types.
# Delimiter for different cmds: ,
[ cmds ]
2023-06-05 08:36:42 -04:00
admin = update , update_all , leave , invite , kick , block , unblock , allow , deny
mod = update , update_all , leave , invite , kick , block , unblock , allow , deny
2023-04-25 01:15:17 -04:00
user = leave , invite
guest = leave
wait = leave
#### User config assignment ####
# Define the individual configs for the different user types.
# Delimiter for different configs: ,
[ configs ]
admin = #file_tx_enabled=True,audio_tx_enabled=True
mod =
user =
guest =
2022-10-21 11:58:11 -04:00
wait =
2023-04-25 01:15:17 -04:00
#### User rights/cmds options ####
# The following rights/cmds can be assigned:
# anonymous = Hide source identity.
2022-10-21 11:58:11 -04:00
# interface = General function of the command interface.
# receive_local = Receive local (own group) messages.
# receive_cluster = Receive cluster (foreign group) messages.
# receive_cluster_pin_add = Receive cluster (foreign group) pinned messages.
# receive_cluster_send = Receive a copy of the message sent to another cluster.
# receive_cluster_loop = Receive message which is sent to a higher hierarchy in the cluster and includes the own cluster.
# receive_cluster_join = Receive an info message when a new cluster joins.
# receive_join = Receive an info message when a new user joins.
# receive_leave = Receive an info message when a user leaves.
# receive_invite = Receive an info message when a user is invited.
# receive_kick = Receive an info message when a user is kicked.
# receive_block = Receive an info message when a user is blocked.
# receive_unblock = Receive an info message when a user is unblocked.
# receive_allow = Receive an info message when a user has been allowed.
# receive_deny = Receive an info message when a user has been denied.
# receive_description = Receive an info message when the group description is changed.
# receive_pin_add = Receive an info message when a message is pinned.
# receive_pin_remove = Receive an info message when a pinned message is removed.
# receive_rules = Receive an info message when the group rules are changed.
# receive_name_def = Receive an info message when a user assigns a name.
# receive_name_change = Receive an info message when a user changes his name.
# receive_auto_name_def = Receive an info message when a user assigns a name.
# receive_auto_name_change = Receive an info message when a user changes his name.
# reply_signature = Receive an error message if the signature is invalid.
# reply_cluster_enabled = Receive an error message when the cluster is disabled.
# reply_cluster_right = Receive an error message when you do not have permission to send in the cluster.
# reply_interface_enabled = Receive an error message when the interface is disabled.
# reply_interface_right = Receive an error message if you do not have permission to use the interface.
# reply_local_enabled = Receive an error message when sending a local message is disabled.
# reply_local_right = Receive an error message when you do not have permission to send locally.
# reply_block = Receive an error message when you are blocked.
# reply_length_min = Receive an error message if the message length is too short.
# reply_length_max = Receive an error message if the message length is too long.
# send_local = Allows you to send loacally in your own group.
# send_cluster = Allows sending to another cluster/group.
# help = Use of the "/help" command allowed.
2023-04-25 01:15:17 -04:00
# update = Use of the "/update" command allowed.
# join = Use of the "/join" command allowed.
2022-10-21 11:58:11 -04:00
# leave = Use of the "/leave" command allowed.
# name = Use of the "/name" command allowed.
# address = Use of the "/address" command allowed.
# info = Use of the "/info" command allowed.
# pin = Use of the "/pin" command allowed.
# pin_add = Use of the "/pin" command allowed.
# pin_remove = Use of the "/pin" command allowed.
# cluster_pin_add = Use of the "/pin" command allowed.
# version = Use of the "/version" command allowed.
# groups = Use of the "/groups" command allowed.
# members = Use of the "/members" command allowed.
# admins = Use of the "/admins" command allowed.
# moderators = Use of the "/moderators" command allowed.
# users = Use of the "/users" command allowed.
# guests = Use of the "/guests" command allowed.
# search = Use of the "/search" command allowed.
# activitys = Use of the "/activitys" command allowed.
# statistic = Use of the "/statistic" command allowed.
# statistic_min = Minimal statistics output.
# statistic_full = Full/Maximal statistics output.
# statistic_cluster = Displays the cluster statistics on the statistics text.
2022-10-22 05:50:19 -04:00
# statistic_router = Displays the cluster statistics on the statistics text.
2022-10-21 11:58:11 -04:00
# statistic_local = Displays the local statistics on the statistics text.
# statistic_interface = Displays the interface statistics on the statistics text.
# statistic_self = Displays the own statistics on the statistics text.
# statistic_user = Displays the user statistics on the statistics text.
# status = Use of the "/status" command allowed.
# delivery = Use of the "/delivery" command allowed.
# enable_local = Use of the "/enable_local" command allowed.
# enable_cluster = Use of the "/enable_cluster" command allowed.
# auto_add_user = Use of the "/auto_add_user" command allowed.
# auto_add_user_type = Use of the "/auto_add_user_type" command allowed.
# auto_add_cluster = Use of the "/auto_add_cluster" command allowed.
2022-10-22 05:50:19 -04:00
# auto_add_router = Use of the "/auto_add_router" command allowed.
2022-10-21 11:58:11 -04:00
# invite_user = Use of the "/invite_user" command allowed.
# invite_user_type = Use of the "/invite_user_type" command allowed.
# allow_user = Use of the "/allow_user" command allowed.
# allow_user_type = Use of the "/allow_user_type" command allowed.
# deny_user = Use of the "/deny_user" command allowed.
# deny_user_type = Use of the "/deny_user_type" command allowed.
# description = Use of the "/description" command allowed.
# description_set = Use of the "/description" command allowed.
# rules = Use of the "/rules" command allowed.
# rules_set = Use of the "/rules" command allowed.
# readme = Use of the "/readme" command allowed.
# time = Use of the "/time" command allowed.
# announce = Use of the "/announce" command allowed.
# sync = Use of the "/sync" command allowed.
# show_run = Use of the "/show_run" command allowed.
# show = Use of the "/show" command allowed.
# add = Use of the "/add" command allowed.
# del = Use of the "/del" command allowed.
# move = Use of the "/move" command allowed.
2022-10-22 10:44:55 -04:00
# rename = Use of the "/rename" command allowed.
2022-10-21 11:58:11 -04:00
# invite = Use of the "/invite" command allowed.
# kick = Use of the "/kick" command allowed.
# block = Use of the "/block" command allowed.
# unblock = Use of the "/unblock" command allowed.
# allow = Use of the "/allow" command allowed.
# deny = Use of the "/deny" command allowed.
# load = Use of the "/load" command allowed.
# save = Use of the "/save" command allowed.
# reload = Use of the "/reload" command allowed.
# reset = Use of the "/reset" command allowed.
# unsaved = Displays the status of the data file when using any action/command.
#### Interface settings - General ####
[ interface ]
# Enable/Disable the whole interface/commands.
enabled = True
# Define the delimiters for command input/output.
delimiter_input = /
delimiter_output = !
#### Interface settings - Messages ####
# Define messages for user or automatic actions.
# These messages are sent automatically when a corresponding action is triggered.
# If a message is to be deactivated simply comment it out.
[ interface_messages ]
# Auto user add. (Single message to the user.)
auto_error = ERROR : Joining the group is not possible .
auto_error - de = FEHLER : Beitritt zur Gruppe ist nicht möglich .
2022-11-08 12:34:34 -05:00
auto_add_admin = Welcome to 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 ! Pinned messages : ! count_pin ! ! n ! Use the command / pin to display them . ! n ! ! n ! Your current nickname is " !source_name! " . Please change your nickname with the command / name
auto_add_admin - de = Willkommen in der Gruppe " !display_name! " ! ! 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 ! Angepinnte Nachrichten : ! count_pin ! ! n ! Verwenden Sie den Befehl / pin um sie anzuzeigen . ! n ! ! n ! Dein aktueller Nickname ist " !source_name! " Bitte ändern Sie ihren Nickname mit dem Befehl / name
auto_add_mod = Welcome to 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 ! Pinned messages : ! count_pin ! ! n ! Use the command / pin to display them . ! n ! ! n ! Your current nickname is " !source_name! " . Please change your nickname with the command / name
auto_add_mod - de = Willkommen in der Gruppe " !display_name! " ! ! 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 ! Angepinnte Nachrichten : ! count_pin ! ! n ! Verwenden Sie den Befehl / pin um sie anzuzeigen . ! n ! ! n ! Dein aktueller Nickname ist " !source_name! " Bitte ändern Sie ihren Nickname mit dem Befehl / name
auto_add_user = Welcome to 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 ! Pinned messages : ! count_pin ! ! n ! Use the command / pin to display them . ! n ! ! n ! Your current nickname is " !source_name! " . Please change your nickname with the command / name
auto_add_user - de = Willkommen in der Gruppe " !display_name! " ! ! 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 ! Angepinnte Nachrichten : ! count_pin ! ! n ! Verwenden Sie den Befehl / pin um sie anzuzeigen . ! n ! ! n ! Dein aktueller Nickname ist " !source_name! " Bitte ändern Sie ihren Nickname mit dem Befehl / name
2022-10-21 11:58:11 -04:00
auto_add_guest = Welcome to the group " !display_name! " ! ! n ! ! n ! ! description ! ! n ! ! n ! You can only receive messages . ! n ! ! n ! Pinned messages : ! count_pin ! ! n ! Use the command / pin to display them . ! n ! ! n ! To leave the group use the following command : / leave
auto_add_guest - de = Willkommen in der Gruppe " !display_name! " ! ! n ! ! n ! ! description ! ! n ! ! n ! Sie können nur Nachrichten empfangen . ! n ! ! n ! Angepinnte Nachrichten : ! count_pin ! ! n ! Verwenden Sie den Befehl / pin um sie anzuzeigen . ! n ! ! n ! Um die Gruppe zu verlassen verwenden Sie folgenden Befehl : / leave
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 .
# Manual/Admin user add. (Single message to the user.)
add_admin =
add_admin - de =
add_mod =
add_mod - de =
add_user =
add_user - de =
add_guest =
add_guest - de =
add_wait =
add_wait - de =
# Invite user. (Single message to the user.)
2022-11-08 12:34:34 -05:00
invite_admin = You have been invited by ! source_name ! < ! source_address ! > to 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 ! Your current nickname is " !user_name! " . Please change your nickname with the command / name
invite_admin - de = Sie wurden von ! source_name ! < ! source_address ! > in die Gruppe " !display_name! " eingeladen ! ! 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 ! Dein aktueller Nickname ist " !user_name! " Bitte ändern Sie ihren Nickname mit dem Befehl / name
invite_mod = You have been invited by ! source_name ! < ! source_address ! > to 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 ! Your current nickname is " !user_name! " . Please change your nickname with the command / name
invite_mod - de = Sie wurden von ! source_name ! < ! source_address ! > in die Gruppe " !display_name! " eingeladen ! ! 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 ! Dein aktueller Nickname ist " !user_name! " Bitte ändern Sie ihren Nickname mit dem Befehl / name
invite_user = You have been invited by ! source_name ! < ! source_address ! > to 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 ! Your current nickname is " !user_name! " . Please change your nickname with the command / name
invite_user - de = Sie wurden von ! source_name ! < ! source_address ! > in die Gruppe " !display_name! " eingeladen ! ! 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 ! Dein aktueller Nickname ist " !user_name! " Bitte ändern Sie ihren Nickname mit dem Befehl / name
2022-10-21 11:58:11 -04:00
invite_guest = You have been invited by ! source_name ! < ! source_address ! > to the group " !display_name! " ! ! n ! ! n ! ! description ! ! n ! ! n ! You can only receive messages . ! n ! ! n ! To leave the group use the following command : / leave
invite_guest - de = Sie wurden von ! source_name ! < ! source_address ! > in die Gruppe " !display_name! " eingeladen ! ! n ! ! n ! ! description ! ! n ! ! n ! Sie können nur Nachrichten empfangen . ! n ! ! n ! Um die Gruppe zu verlassen verwenden Sie folgenden Befehl : / leave
invite_wait = You have been invited by ! source_name ! < ! source_address ! > to the group " !display_name! " ! ! n ! ! n ! You still need to be allowed to join . You will be notified automatically .
invite_wait - de = Sie wurden von ! source_name ! < ! source_address ! > in die Gruppe " !display_name! " eingeladen ! ! n ! ! n ! Der Beitritt muss ihnen noch erlaubt werden . Sie werden darüber automatisch benachrichtigt .
# Kick user. (Single message to the user.)
kick_admin = You have been kicked out of the group !
kick_admin - de = Sie wurden aus der Gruppe geworfen !
kick_mod = You have been kicked out of the group !
kick_mod - de = Sie wurden aus der Gruppe geworfen !
kick_user = You have been kicked out of the group !
kick_user - de = Sie wurden aus der Gruppe geworfen !
kick_guest = You have been kicked out of the group !
kick_guest - de = Sie wurden aus der Gruppe geworfen !
kick_wait = You have been kicked out of the group !
kick_wait - de = Sie wurden aus der Gruppe geworfen !
# Block user. (Single message to the user.)
block_admin =
block_admin - de =
block_mod =
block_mod - de =
block_user =
block_user - de =
block_guest =
block_guest - de =
block_wait =
block_wait - de =
# Unblock user. (Single message to the user.)
unblock_admin =
unblock_admin - de =
unblock_mod =
unblock_mod - de =
unblock_user =
unblock_user - de =
unblock_guest =
unblock_guest - de =
unblock_wait =
unblock_wait - de =
# Allow user. (Single message to the user.)
allow_admin = 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_admin - 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
allow_mod = 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_mod - 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
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
allow_guest = You have been allowed to join the group " !display_name! " ! ! n ! ! n ! ! description ! ! n ! ! n ! You can only receive messages . ! n ! ! n ! To leave the group use the following command : / leave
allow_guest - de = Sie wurden erlaubt der Gruppe " !display_name! " beizutreten ! ! n ! ! n ! ! description ! ! n ! ! n ! Sie können nur Nachrichten empfangen . ! n ! ! n ! Um die Gruppe zu verlassen verwenden Sie folgenden Befehl : / leave
allow_wait =
allow_wait - de =
# Deny user. (Single message to the user.)
deny_admin = You have been denied to join the group " !display_name! " !
deny_admin - de = Ihnen wurde der Beitritt in die Gruppe " !display_name! " abgelehnt !
deny_mod = You have been denied to join the group " !display_name! " !
deny_mod - de = Ihnen wurde der Beitritt in die Gruppe " !display_name! " abgelehnt !
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 !
deny_guest = You have been denied to join the group " !display_name! " !
deny_guest - de = Ihnen wurde der Beitritt in die Gruppe " !display_name! " abgelehnt !
deny_wait =
deny_wait - de =
# General user/member messages. (Group message to all group members.)
member_join = ! source_name ! < ! source_address ! > joins the group .
member_join - de = ! source_name ! < ! source_address ! > tritt der Gruppe bei .
member_leave = ! source_name ! < ! source_address ! > leave the group .
member_leave - de = ! source_name ! < ! source_address ! > verlässt die Gruppe .
2022-11-08 12:34:34 -05:00
member_invite = ! user_name ! < ! user_address ! > was invited to the group by ! source_name ! < ! source_address ! >
member_invite - de = ! user_name ! < ! user_address ! > wurde in die Gruppe eingeladen von ! source_name ! < ! source_address ! >
2022-10-21 11:58:11 -04:00
member_kick = ! user_name ! < ! user_address ! > was kicked out of the group by ! source_name ! < ! source_address ! >
member_kick - de = ! user_name ! < ! user_address ! > wurde aus der Gruppe geworfen von ! source_name ! < ! source_address ! >
member_block = ! user_name ! < ! user_address ! > was blocked by ! source_name ! < ! source_address ! >
member_block - de = ! user_name ! < ! user_address ! > wurde geblockt von ! source_name ! < ! source_address ! >
member_unblock = ! user_name ! < ! user_address ! > was unblocked by ! source_name ! < ! source_address ! >
member_unblock - de = ! user_name ! < ! user_address ! > wurde entsperrt von ! source_name ! < ! source_address ! >
member_allow = ! user_name ! < ! user_address ! > was allowed by ! source_name ! < ! source_address ! >
member_allow - de = ! user_name ! < ! user_address ! > wurde erlaubt von ! source_name ! < ! source_address ! >
member_deny = ! user_name ! < ! user_address ! > was denied by ! source_name ! < ! source_address ! >
member_deny - de = ! user_name ! < ! user_address ! > wurde abgelehnt von ! source_name ! < ! source_address ! >
member_name_def = < ! source_address ! > defined the name :
member_name_def - de = < ! source_address ! > hat den Namen definiert :
member_name_change = < ! source_address ! > changed the name :
member_name_change - de = < ! source_address ! > hat den Namen geändert :
description = ! source_name ! < ! source_address ! > has changed the group description : ! n ! ! n ! ! description !
description - de = ! source_name ! < ! source_address ! > hat die Gruppenbeschreibung geändert : ! n ! ! n ! ! description !
rules = ! source_name ! < ! source_address ! > has changed the group rules : ! n ! ! n ! ! rules !
rules - de = ! source_name ! < ! source_address ! > hat die Gruppenregeln geändert : ! n ! ! n ! ! rules !
cluster_join = New cluster / group connected : ! source_name ! < ! source_address ! >
cluster_join - de = Neue Cluster / Gruppe verbunden : ! source_name ! < ! source_address ! >
pin_add = New pinned message : ! n ! #!key!!n!!value!
pin_add - de = Neue angeheftete Nachricht : ! n ! #!key!!n!!value!
pin_remove = Removed pinned message : ! n ! #!key!!n!!value!
pin_remove - de = Angeheftete Nachricht entfernt : ! n ! #!key!!n!!value!
cluster_pin_add = New pinned message : ! n ! #!key!!n!!value!
cluster_pin_add - de = Neue angeheftete Nachricht : ! n ! #!key!!n!!value!
# Reply messages. (Single message to the user.)
reply_signature = Info : Signature invalid !
reply_signature - de = Info : Signatur ungültig !
reply_cluster_enabled = Info : Cluster disabled !
reply_cluster_enabled - de = Info : Cluster deaktiviert !
reply_cluster_right = Info : No authorization for cluster messages !
reply_cluster_right - de = Keine Berechtigung für Clusternachrichten !
reply_interface_enabled = Info : Commands disabled !
reply_interface_enabled - de = Info : Befehle deaktiviert !
reply_interface_right = Info : No authorization for commands !
reply_interface_right - de = Info : Keine Berechtigung für Befehle !
reply_local_enabled = Info : Group deactivated !
reply_local_enabled - de = Info : Gruppe deaktiviert !
reply_local_right = Info : No authorization to send messages !
reply_local_right - de = Info : Keine Berechtigung zum senden von Nachrichten !
reply_block = Info : You are blocked !
reply_block - de = Info : Sie sind geblockt !
reply_length_min = Info : Minimum message length not reached !
reply_length_min - de = Info : Minimale Nachrichtenlänge unterschritten !
reply_length_max = Info : Maximum message length exceeded !
reply_length_max - de = Info : Maximale Nachrichtenlänge überschritten !
#### Interface settings - Menu/command ####
# Define menu/command texts.
# These texts are used within the menu the user has to start.
[ interface_menu ]
# "/help" command.
help_admin = Group : ! n ! ! display_name ! ! n ! ! n ! Description : ! n ! ! description ! ! n ! ! n ! Number of members : ! count_members ! ! n ! Nickname : ! source_name ! ! n ! User right / type : ! source_right ! ! n ! ! n ! ! interface_help ! ! n ! Commands : ! n ! ! interface_help_command !
help_admin - de = Gruppe : ! n ! ! display_name ! ! n ! ! n ! Beschreibung : ! n ! ! description ! ! n ! ! n ! Anzahl Mitglieder : ! count_members ! ! n ! Nickname : ! source_name ! ! n ! Benutzer Recht / Typ : ! source_right ! ! n ! ! n ! ! interface_help ! ! n ! Befehle : ! n ! ! interface_help_command !
help_mod = Group : ! n ! ! display_name ! ! n ! ! n ! Description : ! n ! ! description ! ! n ! ! n ! Number of members : ! count_members ! ! n ! Nickname : ! source_name ! ! n ! User right / type : ! source_right ! ! n ! ! n ! ! interface_help ! ! n ! Commands : ! n ! ! interface_help_command !
help_mod - de = Gruppe : ! n ! ! display_name ! ! n ! ! n ! Beschreibung : ! n ! ! description ! ! n ! ! n ! Anzahl Mitglieder : ! count_members ! ! n ! Nickname : ! source_name ! ! n ! Benutzer Recht / Typ : ! source_right ! ! n ! ! n ! ! interface_help ! ! n ! Befehle : ! n ! ! interface_help_command !
help_user = Group : ! n ! ! display_name ! ! n ! ! n ! Description : ! n ! ! description ! ! n ! ! n ! Number of members : ! count_members ! ! n ! Nickname : ! source_name ! ! n ! User right / type : ! source_right ! ! n ! ! n ! ! interface_help ! ! n ! Commands : ! n ! ! interface_help_command !
help_user - de = Gruppe : ! n ! ! display_name ! ! n ! ! n ! Beschreibung : ! n ! ! description ! ! n ! ! n ! Anzahl Mitglieder : ! count_members ! ! n ! Nickname : ! source_name ! ! n ! Benutzer Recht / Typ : ! source_right ! ! n ! ! n ! ! interface_help ! ! n ! Befehle : ! n ! ! interface_help_command !
help_guest =
help_guest - de =
2023-04-25 01:15:17 -04:00
# "/update" command.
update_ok = OK : Data updated .
update_ok - de = OK : Daten aktualisiert .
update_error = ERROR : Updating data .
update_error - de = FEHLER : Daten aktualisieren .
2023-06-05 08:36:42 -04:00
# "/update_all" command.
update_all_ok = OK : Data updated .
update_all_ok - de = OK : Daten aktualisiert .
update_all_error = ERROR : Updating data .
update_all_error - de = FEHLER : Daten aktualisieren .
2023-04-25 01:15:17 -04:00
# "/join" command.
join_error = ERROR : While joining group .
join_error - de = FEHLER : Beim Beitritt in die Gruppe .
2022-10-21 11:58:11 -04:00
# "/leave" command.
leave_ok = OK : You leaved the group .
leave_ok - de = OK : Sie haben die Gruppe verlassen .
leave_error = ERROR : While leaving group .
leave_error - de = FEHLER : Beim Verlassen der Gruppe .
# "/name" command.
name = Current nickname : ! source_name !
name - de = Aktueller Nickname : ! source_name !
name_ok = OK : Changed name :
name_ok - de = OK : Name geändert :
name_error = ERROR : Changing name :
name_error - de = FEHLER : Name ändern :
# "/address" command.
address_admin = Group address : ! n ! < ! destination_address ! > ! n ! ! n ! Propagation node : ! n ! < ! propagation_node ! >
address_admin - de = Gruppenadresse : ! n ! < ! destination_address ! > ! n ! ! n ! Propagation Node : ! n ! < ! propagation_node ! >
address_mod = Group address : ! n ! < ! destination_address ! > ! n ! ! n ! Propagation node : ! n ! < ! propagation_node ! >
address_mod - de = Gruppenadresse : ! n ! < ! destination_address ! > ! n ! ! n ! Propagation Node : ! n ! < ! propagation_node ! >
address_user = Group address : ! n ! < ! destination_address ! > ! n ! ! n ! Propagation node : ! n ! < ! propagation_node ! >
address_user - de = Gruppenadresse : ! n ! < ! destination_address ! > ! n ! ! n ! Propagation Node : ! n ! < ! propagation_node ! >
address_guest = Group address : ! n ! < ! destination_address ! > ! n ! ! n ! Propagation node : ! n ! < ! propagation_node ! >
address_guest - de = Gruppenadresse : ! n ! < ! destination_address ! > ! n ! ! n ! Propagation Node : ! n ! < ! propagation_node ! >
# "/info" command.
info_admin = Group : ! n ! ! display_name ! ! n ! ! n ! Description : ! n ! ! description ! ! n ! ! n ! Number of members : ! count_members ! ! n ! Pinned messages : ! count_pin ! ! n ! Use the command / pin to display them .
info_admin - de = Gruppe : ! n ! ! display_name ! ! n ! ! n ! Beschreibung : ! n ! ! description ! ! n ! ! n ! Anzahl Mitglieder : ! count_members ! ! n ! Angepinnte Nachrichten : ! count_pin ! ! n ! Verwenden Sie den Befehl / pin um sie anzuzeigen .
info_mod = Group : ! n ! ! display_name ! ! n ! ! n ! Description : ! n ! ! description ! ! n ! ! n ! Number of members : ! count_members ! ! n ! Pinned messages : ! count_pin ! ! n ! Use the command / pin to display them .
info_mod - de = Gruppe : ! n ! ! display_name ! ! n ! ! n ! Beschreibung : ! n ! ! description ! ! n ! ! n ! Anzahl Mitglieder : ! count_members ! ! n ! Angepinnte Nachrichten : ! count_pin ! ! n ! Verwenden Sie den Befehl / pin um sie anzuzeigen .
info_user = Group : ! n ! ! display_name ! ! n ! ! n ! Description : ! n ! ! description ! ! n ! ! n ! Number of members : ! count_members ! ! n ! Pinned messages : ! count_pin ! ! n ! Use the command / pin to display them .
info_user - de = Gruppe : ! n ! ! display_name ! ! n ! ! n ! Beschreibung : ! n ! ! description ! ! n ! ! n ! Anzahl Mitglieder : ! count_members ! ! n ! Angepinnte Nachrichten : ! count_pin ! ! n ! Verwenden Sie den Befehl / pin um sie anzuzeigen .
info_guest = Group : ! n ! ! display_name ! ! n ! ! n ! Description : ! n ! ! description ! ! n ! ! n ! Number of members : ! count_members ! ! n ! Pinned messages : ! count_pin ! ! n ! Use the command / pin to display them .
info_guest - de = Gruppe : ! n ! ! display_name ! ! n ! ! n ! Beschreibung : ! n ! ! description ! ! n ! ! n ! Anzahl Mitglieder : ! count_members ! ! n ! Angepinnte Nachrichten : ! count_pin ! ! n ! Verwenden Sie den Befehl / pin um sie anzuzeigen .
# "/pin" command.
pin_header = Pinned messages ( ! count ! ) : ! n ! ! n !
pin_header - de = Angeheftete Nachrichten ( ! count ! ) : ! n ! ! n !
pin = ! source_name ! ! n ! < ! source_address ! > ! n ! ! value !
pin - de = ! source_name ! ! n ! < ! source_address ! > ! n ! ! value !
pin_add_ok = OK : Message pinned
pin_add_ok - de = OK : Nachricht angeheftet
pin_remove_ok = OK : Message removed
pin_remove_ok - de = OK : Nachricht entfernt
pin_found_error = ERROR : Message ID not found
pin_found_error - de = FEHLER : Nachrichten ID nicht gefunden
cluster_pin = ! value !
cluster_pin - de = ! value !
# "/version" command.
version_header = Version info : ! n ! ! n !
version_header - de = Versionsinformationen : ! n ! ! n !
# "/groups" command.
groups_header = Groups / Cluster ( ! count ! ) : ! n ! ! n !
groups_header - de = Gruppen / Cluster ( ! count ! ) : ! n ! ! n !
groups_member = ! source_name ! ! n !
groups_member - de = ! source_name ! ! n !
groups_search_header = Found groups / cluster ( ! count ! ) : ! n ! ! n !
groups_search_header - de = Gefundene Gruppen / Cluster ( ! count ! ) : ! n ! ! n !
groups_search_member = ! source_name ! ! n !
groups_search_member - de = ! source_name ! ! n !
groups_search_found_error = ERROR : Group / Cluster not found
groups_search_found_error - de = FEHLER : Gruppe / Cluster nicht gefunden
# "/members" command.
members_header = Group members ( ! count ! ) : ! n ! ! n !
members_header - de = Gruppenmitglieder ( ! count ! ) : ! n ! ! n !
members_member = ! source_name ! ! n ! < ! source_address ! > ! n ! ! n !
members_member - de = ! source_name ! ! n ! < ! source_address ! > ! n ! ! n !
# "/admins" command.
admins_header = Group admins ( ! count ! ) : ! n ! ! n !
admins_header - de = Gruppenadmins ( ! count ! ) : ! n ! ! n !
admins_member = ! source_name ! ! n ! < ! source_address ! > ! n ! ! n !
admins_member - de = ! source_name ! ! n ! < ! source_address ! > ! n ! ! n !
# "/moderators" command.
moderators_header = Group moderators ( ! count ! ) : ! n ! ! n !
moderators_header - de = Gruppenmoderatoren ( ! count ! ) : ! n ! ! n !
moderators_member = ! source_name ! ! n ! < ! source_address ! > ! n ! ! n !
moderators_member - de = ! source_name ! ! n ! < ! source_address ! > ! n ! ! n !
# "/users" command.
users_header = Group users ( ! count ! ) : ! n ! ! n !
users_header - de = Gruppenbenutzer ( ! count ! ) : ! n ! ! n !
users_member = ! source_name ! ! n ! < ! source_address ! > ! n ! ! n !
users_member - de = ! source_name ! ! n ! < ! source_address ! > ! n ! ! n !
# "/guests" command.
guests_header = Group guests ( ! count ! ) : ! n ! ! n !
guests_header - de = Gruppengäste ( ! count ! ) : ! n ! ! n !
guests_member = ! source_name ! ! n ! < ! source_address ! > ! n ! ! n !
guests_member - de = ! source_name ! ! n ! < ! source_address ! > ! n ! ! n !
# "/search" command.
search_header = Found members ( ! count ! ) : ! n ! ! n !
search_header - de = Gefundene Mitglieder ( ! count ! ) : ! n ! ! n !
search_member = ! source_name ! ! n ! < ! source_address ! > ! n ! ! activity_receive ! / ! activity_send ! ! n ! ! n !
search_member - de = ! source_name ! ! n ! < ! source_address ! > ! n ! ! activity_receive ! / ! activity_send ! ! n ! ! n !
search_found_error = ERROR : Nickname or address not found
search_found_error - de = FEHLER : Benutzername oder Adresse nicht gefunden
# "/activitys" command.
activitys_header = User activitys ( ! count ! ) : ! n ! ( receive / send ) ! n ! ! n !
activitys_header - de = Benutzeraktivitäten ( ! count ! ) : ! n ! ( empf . / gesendet ) ! n ! ! n !
activitys_member = ! source_name ! ! n ! < ! source_address ! > ! n ! ! activity_receive ! / ! activity_send ! ! n ! ! n !
activitys_member - de = ! source_name ! ! n ! < ! source_address ! > ! n ! ! activity_receive ! / ! activity_send ! ! n ! ! n !
# "/statistic" command.
statistic_header_cluster = - - Cluster statistics - ! value ! - - ! n !
statistic_header_cluster - de = - - Cluster - Statistik - ! value ! - - ! n !
2022-10-22 05:50:19 -04:00
statistic_header_router = - - Router statistics - ! value ! - - ! n !
statistic_header_router - de = - - Router - Statistik - ! value ! - - ! n !
2022-10-21 11:58:11 -04:00
statistic_header_local = - - Group statistics - ! value ! - - ! n !
statistic_header_local - de = - - Gruppen - Statistik - ! value ! - - ! n !
statistic_header_interface = - - Interface statistics - ! value ! - - ! n !
statistic_header_interface - de = - - Interface - Statistik - ! value ! - - ! n !
statistic_header_user = - - User statistics - ! value ! - - ! n !
statistic_header_user - de = - - Benutzer - Statistik - ! value ! - - ! n !
statistic_header_self = - - Own statistics - - ! n !
statistic_header_self - de = - - Eigene - Statistik - - ! n !
statistic_found_error = ERROR : Statistic type not found
statistic_found_error - de = FEHLER : Statistik typ nicht vorhanden
# "/status" command.
status_admin = Status : ! n ! ! n ! Local message routing : ! enabled_local ! ! n ! Cluster message routing : ! enabled_cluster ! ! n !
status_admin - de = Status : ! n ! ! n ! Lokales Nachrichten Routing : ! enabled_local ! ! n ! Cluster Nachrichten Routing : ! enabled_cluster ! ! n !
status_mod = Status : ! n ! ! n ! Local message routing : ! enabled_local ! ! n ! Cluster message routing : ! enabled_cluster ! ! n !
status_mod - de = Status : ! n ! ! n ! Lokales Nachrichten Routing : ! enabled_local ! ! n ! Cluster Nachrichten Routing : ! enabled_cluster ! ! n !
status_user = Status : ! n ! ! n ! Local message routing : ! enabled_local ! ! n ! Cluster message routing : ! enabled_cluster ! ! n !
status_user - de = Status : ! n ! ! n ! Lokales Nachrichten Routing : ! enabled_local ! ! n ! Cluster Nachrichten Routing : ! enabled_cluster ! ! n !
status_guest = Status : ! n ! ! n ! Local message routing : ! enabled_local ! ! n ! Cluster message routing : ! enabled_cluster ! ! n !
status_guest - de = Status : ! n ! ! n ! Lokales Nachrichten Routing : ! enabled_local ! ! n ! Cluster Nachrichten Routing : ! enabled_cluster ! ! n !
# "/delivery" command.
# todo
# "/enable_local" command.
enable_local_true = OK : Local message routing enabled .
enable_local_true - de = OK : Lokales Nachrichten Routing aktiviert .
enable_local_false = OK : Local message routing disabled .
enable_local_false - de = OK : Lokales Nachrichten Routing deaktiviert .
enable_local_error = ERROR : Local message routing change .
enable_local_error - de = FEHLER : Änderung Lokales Nachrichten Routing .
# "/enable_cluster" command.
enable_cluster_true = OK : Cluster message routing enabled .
enable_cluster_true - de = OK : Cluster Nachrichten Routing aktiviert .
enable_cluster_false = OK : Cluster message routing disabled .
enable_cluster_false - de = OK : Cluster Nachrichten Routing deaktiviert .
enable_cluster_error = ERROR : Cluster message routing change .
enable_cluster_error - de = FEHLER : Änderung Cluster Nachrichten Routing .
# "/auto_add_user" command.
auto_add_user_true = OK : Auto add user enabled .
auto_add_user_true - de = OK : Benutzer automatisch hinzufügen aktiviert .
auto_add_user_false = OK : Auto add user disabled .
auto_add_user_false - de = OK : Benutzer automatisch hinzufügen deaktiviert .
auto_add_user_error = ERROR : Auto add user change .
auto_add_user_error - de = FEHLER : Änderung Benutzer automatisch hinzufügen .
# "/auto_add_user_type" command.
auto_add_user_type = OK : User type changed to :
auto_add_user_type - de = OK : Benutzertyp geändert in :
auto_add_user_type_error = ERROR : User type change .
auto_add_user_type_error - de = FEHLER : Änderung des Benutzertyps .
# "/auto_add_cluster" command.
auto_add_cluster_true = OK : Auto add cluster enabled .
auto_add_cluster_true - de = OK : Cluster / Gruppen automatisch hinzufügen aktiviert .
auto_add_cluster_false = OK : Auto add cluster disabled .
auto_add_cluster_false - de = OK : Cluster / Gruppen automatisch hinzufügen deaktiviert .
auto_add_cluster_error = ERROR : Auto add cluster change .
auto_add_cluster_error - de = FEHLER : Änderung Cluster / Gruppen automatisch hinzufügen .
2022-10-22 05:50:19 -04:00
# "/auto_add_router" command.
auto_add_router_true = OK : Auto add router enabled .
auto_add_router_true - de = OK : Router automatisch hinzufügen aktiviert .
auto_add_router_false = OK : Auto add router disabled .
auto_add_router_false - de = OK : Router automatisch hinzufügen deaktiviert .
auto_add_router_error = ERROR : Auto add router change .
auto_add_router_error - de = FEHLER : Änderung Router automatisch hinzufügen .
2022-10-21 11:58:11 -04:00
# "/invite_user" command.
invite_user_true = OK : Invite user enabled .
invite_user_true - de = OK : Benutzer einladen aktiviert .
invite_user_false = OK : Invite user disabled .
invite_user_false - de = OK : Benutzer einladen deaktiviert .
invite_user_error = ERROR : Invite user change .
invite_user_error - de = FEHLER : Änderung Benutzer einladen .
# "/invite_user_type" command.
invite_user_type = OK : User type changed to :
invite_user_type - de = OK : Benutzertyp geändert in :
invite_user_type_error = ERROR : User type change .
invite_user_type_error - de = FEHLER : Änderung des Benutzertyps .
# "/allow_user" command.
allow_user_true = OK : Allow user enabled .
allow_user_true - de = OK : Benutzer erlauben aktiviert .
allow_user_false = OK : Allow user disabled .
allow_user_false - de = OK : Benutzer erlauben deaktiviert .
allow_user_error = ERROR : Allow user change .
allow_user_error - de = FEHLER : Änderung Benutzer erlauben .
# "/allow_user_type" command.
allow_user_type = OK : User type changed to :
allow_user_type - de = OK : Benutzertyp geändert in :
allow_user_type_error = ERROR : User type change .
allow_user_type_error - de = FEHLER : Änderung des Benutzertyps .
# "/deny_user" command.
deny_user_true = OK : Deny user enabled .
deny_user_true - de = OK : Benutzer ablehnen aktiviert .
deny_user_false = OK : Deny user disabled .
deny_user_false - de = OK : Benutzer ablehnen deaktiviert .
deny_user_error = ERROR : Deny user change .
deny_user_error - de = FEHLER : Änderung Benutzer ablehnen .
# "/deny_user_type" command.
deny_user_type = OK : User type changed to :
deny_user_type - de = OK : Benutzertyp geändert in :
deny_user_type_error = ERROR : User type change .
deny_user_type_error - de = FEHLER : Änderung des Benutzertyps .
# "/description" command.
description = OK : Description changed to :
description - de = OK : Beschreibung geändert in :
description_error = ERROR : Description change .
description_error - de = FEHLER : Beschreibung ändern .
# "/rules" command.
rules = OK : Rules changed to :
rules - de = OK : Regeln geändert in :
rules_error = ERROR : Rules change .
rules_error - de = FEHLER : Regeln ändern .
# "/readme" command.
readme =
readme - de =
# "/time" command.
time = Current server time : % % Y - % % m - % % d % % H : % % M : % % S
time - de = Aktuelle Server - Zeit : % % Y - % % m - % % d % % H : % % M : % % S
# "/announce" command.
announce = Announce send .
announce - de = Announce gesendet .
# "/sync" command.
sync = Synchronize messages with propagation node < ! propagation_node ! > .
sync - de = Synchronisiere Nachrichten mit Propagation node < ! propagation_node ! > .
# "/show run" command.
show_run_header = Current settings / data : ! n ! ! n !
show_run_header - de = Aktuelle Konfiguration / Daten : ! n ! ! n !
# "/show" command.
show_header =
show_header - de =
# "/user" command.
user_add = OK : Added user - > group :
user_add - de = OK : Benutzer - > Gruppe hinzugefügt :
user_del = OK : Removed user - > group :
user_del - de = OK : Entfernter Benutzer - > Gruppe :
user_move = OK : Moved user - > group :
user_move - de = OK : Benutzer - > Gruppe verschoben :
2022-10-22 10:44:55 -04:00
user_rename = OK : Renamed user :
user_rename - de = OK : Umbenannter Benutzer :
2022-10-21 11:58:11 -04:00
user_error = ERROR : Unknown user - > group :
user_error - de = FEHLER : Unbekannter Benutzer - > Gruppe :
2022-10-22 10:44:55 -04:00
user_found_error = ERROR : User not found
user_found_error - de = FEHLER : Benutzer nicht gefunden
2022-10-21 11:58:11 -04:00
user_format_error = ERROR : Wrong user format
user_format_error - de = FEHLER : Falsches Benutzerformat
user_type_error = ERROR : Unknown user type
user_type_error - de = FEHLER : Unbekannter Benutzertyp
# "/invite" command.
invite_ok = OK : Invited user :
invite_ok - de = OK : Benutzer eingeladen :
invite_error = ERROR : Inviting user :
invite_error - de = FEHLER : Benutzer einladen :
invite_format_error = ERROR : Wrong user format
invite_format_error - de = FEHLER : Falsches Benutzerformat
invite_type_error = ERROR : Unknown user type
invite_type_error - de = FEHLER : Unbekannter Benutzertyp
# "/kick" command.
kick_ok = OK : User kicked out : ! user_name ! < ! user_address ! >
kick_ok - de = OK : Benutzer rausgeworfen : ! user_name ! < ! user_address ! >
kick_found_error = ERROR : User address not found
kick_found_error - de = FEHLER : Benutzer Adresse nicht gefunden
kick_format_error = ERROR : Wrong user format
kick_format_error - de = FEHLER : Falsches Benutzerformat
# "/block" command.
block_ok = OK : User blocked : ! user_name ! < ! user_address ! >
block_ok - de = OK : Benutzer blockiert : ! user_name ! < ! user_address ! >
block_found_error = ERROR : User address not found
block_found_error - de = FEHLER : Benutzer Adresse nicht gefunden
block_format_error = ERROR : Wrong user format
block_format_error - de = FEHLER : Falsches Benutzerformat
# "/unblock" command.
unblock_ok = OK : User unblocked : ! user_name ! < ! user_address ! >
unblock_ok - de = OK : Blockerierung des Benutzers aufgehoben : ! user_name ! < ! user_address ! >
unblock_found_error = ERROR : User address not found
unblock_found_error - de = FEHLER : Benutzer Adresse nicht gefunden
unblock_format_error = ERROR : Wrong user format
unblock_format_error - de = FEHLER : Falsches Benutzerformat
# "/allow" command.
allow_ok = OK : User allowed : ! user_name ! < ! user_address ! >
allow_ok - de = OK : Benutzer erlaubt : ! user_name ! < ! user_address ! >
allow_found_error = ERROR : User address not found
allow_found_error - de = FEHLER : Benutzer Adresse nicht gefunden
allow_format_error = ERROR : Wrong user format
allow_format_error - de = FEHLER : Falsches Benutzerformat
allow_type_error = ERROR : Unknown user type
allow_type_error - de = FEHLER : Unbekannter Benutzertyp
# "/deny" command.
deny_ok = OK : User denied : ! user_name ! < ! user_address ! >
deny_ok - de = OK : Benutzer abgelehnt : ! user_name ! < ! user_address ! >
deny_found_error = ERROR : User address not found
deny_found_error - de = FEHLER : Benutzer Adresse nicht gefunden
deny_format_error = ERROR : Wrong user format
deny_format_error - de = FEHLER : Falsches Benutzerformat
deny_type_error = ERROR : Unknown user type
deny_type_error - de = FEHLER : Unbekannter Benutzertyp
# "/load" command.
load_ok = OK : Loading configuration / data .
load_ok - de = OK : Konfiguration / Daten werden geladen .
load_error = ERROR : Loading configuration / data .
load_error - de = FEHLER : Konfiguration / Daten werden geladen .
# "/save" command.
save_ok = OK : Saved configuration / data .
save_ok - de = OK : Konfiguration / Daten gespeichert .
save_error = ERROR : Saving configuration / data .
save_error - de = FEHLER : Speichern der Konfiguration / Daten .
save_info = INFO : Unsaved changes ! Please run the command ' /save ' to save these changes permanently !
save_info - de = INFO : Nicht gespeicherte Änderungen ! Bitte führen Sie den Befehl ' /save ' aus , um diese Änderungen dauerhaft zu speichern !
# "/reload" command.
reload_ok = OK : Reloaded configuration / data .
reload_ok - de = OK : Konfiguration / Daten neu geladen .
reload_error = ERROR : Reload configuration / data .
reload_error - de = FEHLER : Neu laden der Konfiguration / Daten .
# "/reset" command.
reset_statistic_ok = OK : Reset statistic .
reset_statistic_ok - de = OK : Statistik zurückgesetzt .
reset_statistic_error = ERROR : Reset statistic .
reset_statistic_error - de = FEHLER : Statistik zurücksetzen .
# Cluster messages.
cluster_found_error = ERROR : Cluster name not found
cluster_found_error - de = FEHLER : Clustername nicht gefunden
cluster_format_error = ERROR : Wrong cluster format
cluster_format_error - de = FEHLER : Falsches Clusterformat
# General messages.
cmd_error = ERROR : Processing command .
cmd_error - de = FEHLER : Verarbeitung des Befehls .
cmd_unknown = ERROR : Unknown command . Type / ? for help .
cmd_unknown - de = FEHLER : Unbekannter Befehl . Geben Sie / ? für Hilfe ein .
#### Interface settings - Help ####
# Define help texts.
# These texts are used within the help-menu.
# Only the commands defined in the user rights are displayed.
# If a message is to be deactivated simply comment it out.
[ interface_help ]
send_local = To send a message simply enter any text . ! n ! ! n !
send_local - de = Um eine Nachricht zu senden , geben Sie einfach einen beliebigen Text ein . ! n ! ! n !
send_cluster = To send a message to another group enter the destination group with the following command followed by the message : @destination message . ! n ! ! n !
send_cluster - de = Um eine Nachricht an eine andere Gruppe zu senden , geben Sie die Zielgruppe mit dem folgenden Befehl gefolgt von der Nachricht ein : @Zielname Nachricht . ! n ! ! n !
interface = If the sent message is displayed as delivered and no error message is received , everything has worked fine . ! n ! ! n !
interface - de = Wenn die gesendete Nachricht als zugestellt angezeigt wird und keine Fehlermeldung eingeht , hat alles fehlerfrei funktioniert . ! n ! ! n !
# Define help texts.
# These texts are used within the help-menu.
# Only the commands defined in the user rights are displayed.
# If a message is to be deactivated simply comment it out.
[ interface_help_command ]
help = / help or / ? = Shows this help ! n !
help - de = / help oder / ? = Zeigt diese Hilfe an ! n !
leave = / leave or / part = Leave group ! n !
leave - de = / leave oder / part = Gruppe verlassen ! n !
name = / name = Show current nickname ! n ! / nick = Show current nickname ! n ! / name < your nickname > = Change / Define nickname ! n ! / nick < your nickname > = Change / Define nickname ! n !
name - de = / name = Aktueller Nickname anzeigen ! n ! / nick = Aktueller Nickname anzeigen ! n ! / name < dein Nichname > = Ändern / Definieren des Nickname ! n ! / nick < dein Nichname > = Ändern / Definieren des Nickname ! n !
address = / address = Dislay address info ! n !
address - de = / address = Adressinfos anzeigen ! n !
info = / info = Show group info ! n !
info - de = / info = Gruppeninfos anzeigen ! n !
pin = / pin = Show pinned messages ! n !
pin - de = / pin = Angeheftete Nachrichten anzeigen ! n !
pin_add = / pin < message > = Pin a message ! n !
pin_add - de = / pin < Nachricht > = Nachricht anheften ! n !
pin_remove = / unpin < #id> = Removes a pinned message!n!
pin_remove - de = / unpin < #id> = Angeheftete Nachricht entfernen!n!
version = / version = Show version info ! n !
version - de = / version = Versionsinformationen anzeigen ! n !
groups = / groups or / cluster = Show all groups / clusters ! n ! / groups < name > = Searches for a group / cluster by name ! n !
groups - de = / groups oder / cluster = Alle Gruppen / Cluster anzeigen ! n ! / groups < name > = Sucht nach einer Gruppe / Cluster nach Namen ! n !
members = / members or / names or / who = Show all group members ! n !
members - de = / members oder / names oder / who = Alle Gruppenmitglieder anzeigen ! n !
admins = / admins = Show group admins ! n !
admins - de = / admins = Gruppenadmins anzeigen ! n !
moderators = / moderators or / mods = Show group moderators ! n !
moderators - de = / moderators oder / mods = Gruppenmoderatoren anzeigen ! n !
users = / users = Show group users ! n !
users - de = / users = Gruppenbenutzer anzeigen ! n !
guests = / guests = Show group guests ! n !
guests - de = / guests = Gruppengäste anzeigen ! n !
search = / search < nickname / user_address > = Searches for a user by nickname or address ! n ! / whois < nickname / user_address > = Searches for a user by nickname or address ! n !
search - de = / search < nickname / user_address > = Sucht einen Benutzer anhand des Nicknamens oder Adresse ! n ! / whois < nickname / user_address > = Sucht einen Benutzer anhand des Nicknamens oder Adresse ! n !
activitys = / activitys = Show user activitys ! n !
activitys - de = / activitys = Benutzeraktivitäten anzeigen ! n !
statistic = / statistic or / stat = Show group statistic ! n ! / statistic < day / week / month / year / all > or / stat < day / week / month / year / all > = Show group statistic ! n !
statistic - de = / statistic oder / stat = Gruppenstatistik anzeigen ! n ! / statistic < day / week / month / year / all > oder / stat < day / week / month / year / all > = Gruppenstatistik anzeigen ! n !
status = / status = Show status ! n !
status - de = / status = Status anzeigen ! n !
delivery = / delivery or / message = Show delivery status of last message ! n !
delivery - de = / delivery oder / message = Lieferstatus der letzten Nachricht anzeigen ! n !
enable_local = / enable_local < true / false > = Local message routing ! n !
enable_local - de = / enable_local < true / false > Lokales Nachrichten Routing ! n !
enable_cluster = / enable_cluster < true / false > = Cluster message routing ! n !
enable_cluster - de = / enable_cluster < true / false > Cluster Nachrichten Routing ! n !
auto_add_user = / auto_add_user < true / false > = Add unknown user functionality ! n !
auto_add_user - de = / auto_add_user < true / false > = Unbekannten Benutzer hinzufügen Funktionalität ! n !
auto_add_user_type = / auto_add_user_type < admin / mod / user / guest > ! n !
auto_add_user_type - de = / auto_add_user_type < admin / mod / user / guest > ! n !
auto_add_cluster = / auto_add_cluster < true / false > = Add unknown cluster functionality ! n !
auto_add_cluster - de = / auto_add_cluster < true / false > = Unbekannten Cluster / Gruppen hinzufügen Funktionalität ! n !
2022-10-22 05:50:19 -04:00
auto_add_router = / auto_add_router < true / false > = Add unknown router functionality ! n !
auto_add_router - de = / auto_add_router < true / false > = Unbekannten Router hinzufügen Funktionalität ! n !
2022-10-21 11:58:11 -04:00
invite_user = / invite_user < true / false > = Invite functionality ! n !
invite_user - de = / invite_user < true / false > = Einladung Funktionalität ! n !
invite_user_type = / invite_user_type < admin / mod / user / guest > ! n !
invite_user_type - de = / invite_user_type < admin / mod / user / guest > ! n !
allow_user = / allow_user < true / false > = Allow user functionality ! n !
allow_user - de = / allow_user < true / false > = Benutzer erlauben Funktionalität ! n !
allow_user_type = / allow_user_type < admin / mod / user / guest > ! n !
allow_user_type - de = / allow_user_type < admin / mod / user / guest > ! n !
deny_user = / deny_user < true / false > = Deny user functionality ! n !
deny_user - de = / deny_user < true / false > = Benutzer ablehnen Funktionalität ! n !
deny_user_type = / deny_user_type < admin / mod / user / guest > ! n !
deny_user_type - de = / deny_user_type < admin / mod / user / guest > ! n !
description = / description = Show current description ! n !
description - de = / description = Aktuelle Beschreibung anzeigen ! n !
description_set = / description < description > = Change description ! n !
description_set - de = / description < description > ! n ! = Beschreibung ändern
rules = / rules = Show current rules ! n !
rules - de = / rules = Aktuelle Regeln anzeigen ! n !
rules_set = / rules < description > = Change rules ! n !
rules_set - de = / rules < description > ! n ! = Regeln ändern
readme = / readme = Show readme ! n !
readme - de = / readme = Liesmich anzeigen ! n !
time = / time = Show date / time ! n !
time - de = / time = Datum / Uhrzeit anzeigen ! n !
announce = / announce = Send announce ! n !
announce - de = / announce = Announce senden ! n !
sync = / sync = Synchronize messages with propagation node ! n !
sync - de = / sync = Nachrichten mit Propagation Node synchronisieren ! n !
show_run = / show run = Show current configuration ! n !
show_run - de = / show run = Aktuelle Konfiguration anzeigen ! n !
show = / show or / list ! n ! / show or / list < admin / mod / user / guest > ! n !
show - de = / show oder / list ! n ! / show oder / list < admin / mod / user / guest > ! n !
add = / add < admin / mod / user / guest > < user_address > < user_name > ! n !
add - de = / add < admin / mod / user / guest > < user_address > < user_name > ! n !
del = / del or / rm < admin / mod / user / guest > < user_address > ! n ! / del or / rm < user_address > ! n !
del - de = / del oder / rm < admin / mod / user / guest > < user_address > ! n ! / del oder / rm < user_address > ! n !
move = / move < admin / mod / user / guest > < user_address > ! n !
move - de = / move < admin / mod / user / guest > < user_address > ! n !
2022-10-22 10:44:55 -04:00
rename = / rename < user_address > < new nickname > = Change nickname ! n !
rename - de = / rename < user_address > < new nickname > = Ändern des Nickname ! n !
2022-10-21 11:58:11 -04:00
invite = / invite < user_address > = Invites user to group ! n !
invite - de = / invite < user_address > = Lädt Benutzer zur Gruppe ein ! n !
kick = / kick < user_address > = Kicks user out of group ! n !
kick - de = / kick < user_address > = Wirft den Benutzer aus der Gruppe ! n !
block = / block < user_address > = Block user ! n ! / ban < user_address > = Block user ! n !
block - de = / block < user_address > = Blockiert Benutzer ! n ! / ban < user_address > = Blockiert Benutzer ! n !
unblock = / unblock < user_address > = Unblock user ! n ! / unban < user_address > = Unblock user ! n !
unblock - de = / unblock < user_address > = Blockierung des Benutzers aufheben ! n ! / unban < user_address > = Blockierung des Benutzers aufheben ! n !
allow = / allow < user_address > = Allow user ! n !
allow - de = / allow < user_address > = Benutzer erlauben ! n !
deny = / deny < user_address > = Deny user ! n !
deny - de = / deny < user_address > = Benutzer ablehnen ! n !
load = / load or / read = Read the configuration / data ! n !
load - de = / load oder / read = Lesen der Konfiguration / Daten ! n !
save = / save or / wr = Saves the current configuration / data ! n !
save - de = / save oder / wr = Speichert die aktuelle Konfiguration / Daten ! n !
reload = / reload = Reload the current configuration / data ! n !
reload - de = / reload = Neu laden der aktuelle Konfiguration / Daten ! n !
reset = / reset statistic < all / cluster / local / interface / user > = Reset statistic ! n !
reset - de = / reset statistic < all / cluster / local / interface / user > = Statisktik zurücksetzenn ! n !
'''
#### Default data file ####
DEFAULT_DATA = ''' # 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!
#### High availability settings ####
[ high_availability ]
role = master
last_heartbeat = 0000 - 00 - 00 00 : 00 : 00
#### Main program settings ####
[ main ]
enabled_local = True
enabled_cluster = True
auto_add_user = True
auto_add_user_type = user
auto_add_cluster = True
2022-10-22 05:50:19 -04:00
auto_add_router = True
2022-10-21 11:58:11 -04:00
invite_user = True
invite_user_type = user
allow_user = True
allow_user_type = user
deny_user = True
deny_user_type = block_wait
2023-04-25 01:15:17 -04:00
description =
description - de =
2022-10-21 11:58:11 -04:00
rules = Please follow the general rules of etiquette which should be taken for granted ! ! n ! Prohibited are : ! n ! Spam , insults , violence , sex , illegal topics
rules - de = Bitte befolgen Sie die allgemeinen benimm - dich - Regeln welche als selbstverständlich gelten sollten ! ! n ! Verboten sind : ! n ! Spam , Beleidigungen , Gewalt , Sex , illegale Themen
2023-07-29 13:35:54 -04:00
#### Topics ####
[ topics ]
2022-10-21 11:58:11 -04:00
#### Admin user ####
[ admin ]
#### Mod/Moderator user ####
[ mod ]
#### User ####
[ user ]
#### Guest user ####
[ guest ]
#### Wait user ####
[ wait ]
#### Blocked user ####
[ block_admin ]
[ block_mod ]
[ block_user ]
[ block_guest ]
[ block_wait ]
#### Cluster (Automatically or manual created) ####
[ cluster ]
[ block_cluster ]
2022-10-22 05:50:19 -04:00
#### Router (Automatically or manual created) ####
[ router ]
[ block_router ]
2022-10-21 11:58:11 -04:00
#### Pinned messages (Automatically created) ####
[ pin ]
'''
##############################################################################################################
# Init
if __name__ == " __main__ " :
main ( )