2021-04-08 10:29:43 -04:00
import os
2021-11-05 05:59:51 -04:00
import io
2021-11-04 16:51:11 -04:00
import sys
2021-05-04 05:09:41 -04:00
import time
2021-04-08 10:29:43 -04:00
import atexit
2021-12-11 13:20:34 -05:00
import threading
2021-11-04 16:51:11 -04:00
import traceback
2021-11-05 05:59:51 -04:00
import contextlib
2021-04-08 10:29:43 -04:00
2021-04-08 14:57:31 -04:00
import RNS
2021-05-04 05:09:41 -04:00
import LXMF
2021-04-08 14:57:31 -04:00
import nomadnet
2021-10-03 12:44:00 -04:00
from nomadnet . Directory import DirectoryEntry
2021-05-15 15:08:30 -04:00
import RNS . vendor . umsgpack as msgpack
2021-04-08 14:57:31 -04:00
from . _version import __version__
2021-04-08 10:29:43 -04:00
from . vendor . configobj import ConfigObj
class NomadNetworkApp :
2021-05-04 14:53:03 -04:00
time_format = " % Y- % m- %d % H: % M: % S "
2021-04-08 10:29:43 -04:00
_shared_instance = None
configdir = os . path . expanduser ( " ~ " ) + " /.nomadnetwork "
2021-12-11 13:20:34 -05:00
START_ANNOUNCE_DELAY = 3
2021-04-08 14:57:31 -04:00
def exit_handler ( self ) :
2021-05-13 10:39:50 -04:00
RNS . log ( " Nomad Network Client exit handler executing... " , RNS . LOG_VERBOSE )
RNS . log ( " Saving directory... " , RNS . LOG_VERBOSE )
self . directory . save_to_disk ( )
RNS . log ( " Nomad Network Client exiting now " , RNS . LOG_VERBOSE )
2021-04-08 10:29:43 -04:00
2021-11-04 16:51:11 -04:00
def exception_handler ( self , e_type , e_value , e_traceback ) :
RNS . log ( " An unhandled exception occurred, the details of which will be dumped below " , RNS . LOG_ERROR )
RNS . log ( " Type : " + str ( e_type ) , RNS . LOG_ERROR )
RNS . log ( " Value : " + str ( e_value ) , RNS . LOG_ERROR )
t_string = " "
for line in traceback . format_tb ( e_traceback ) :
t_string + = line
RNS . log ( " Trace : \n " + t_string , RNS . LOG_ERROR )
if issubclass ( e_type , KeyboardInterrupt ) :
sys . __excepthook__ ( e_type , e_value , e_traceback )
2021-04-08 10:29:43 -04:00
def __init__ ( self , configdir = None , rnsconfigdir = None ) :
2021-04-08 14:57:31 -04:00
self . version = __version__
2021-04-08 11:08:07 -04:00
self . enable_client = False
self . enable_node = False
self . identity = None
2021-04-08 14:57:31 -04:00
self . uimode = None
2021-04-08 10:29:43 -04:00
if configdir == None :
self . configdir = NomadNetworkApp . configdir
else :
self . configdir = configdir
if NomadNetworkApp . _shared_instance == None :
NomadNetworkApp . _shared_instance = self
2021-05-13 10:39:50 -04:00
self . rns = RNS . Reticulum ( configdir = rnsconfigdir )
2021-05-04 05:09:41 -04:00
self . configpath = self . configdir + " /config "
self . logfilepath = self . configdir + " /logfile "
2021-11-05 05:59:51 -04:00
self . errorfilepath = self . configdir + " /errors "
2021-05-04 05:09:41 -04:00
self . storagepath = self . configdir + " /storage "
self . identitypath = self . configdir + " /storage/identity "
self . cachepath = self . configdir + " /storage/cache "
self . resourcepath = self . configdir + " /storage/resources "
self . conversationpath = self . configdir + " /storage/conversations "
2021-05-13 10:39:50 -04:00
self . directorypath = self . configdir + " /storage/directory "
2021-05-15 15:08:30 -04:00
self . peersettingspath = self . configdir + " /storage/peersettings "
2021-04-08 11:08:07 -04:00
2021-08-26 09:26:12 -04:00
self . pagespath = self . configdir + " /storage/pages "
self . filespath = self . configdir + " /storage/files "
2021-09-17 12:45:08 -04:00
self . cachepath = self . configdir + " /storage/cache "
2021-08-26 09:26:12 -04:00
2021-09-10 15:33:29 -04:00
self . downloads_path = os . path . expanduser ( " ~/Downloads " )
2021-09-11 06:21:35 -04:00
self . firstrun = False
2021-10-03 12:44:00 -04:00
self . peer_announce_at_start = True
self . try_propagation_on_fail = True
2021-09-16 13:54:32 -04:00
2021-04-08 11:08:07 -04:00
if not os . path . isdir ( self . storagepath ) :
os . makedirs ( self . storagepath )
if not os . path . isdir ( self . cachepath ) :
os . makedirs ( self . cachepath )
if not os . path . isdir ( self . resourcepath ) :
os . makedirs ( self . resourcepath )
2021-05-04 05:09:41 -04:00
if not os . path . isdir ( self . conversationpath ) :
os . makedirs ( self . conversationpath )
2021-08-26 09:26:12 -04:00
if not os . path . isdir ( self . pagespath ) :
os . makedirs ( self . pagespath )
if not os . path . isdir ( self . filespath ) :
os . makedirs ( self . filespath )
2021-09-17 12:45:08 -04:00
if not os . path . isdir ( self . cachepath ) :
os . makedirs ( self . cachepath )
2021-04-08 11:08:07 -04:00
if os . path . isfile ( self . configpath ) :
try :
self . config = ConfigObj ( self . configpath )
2021-04-09 16:07:38 -04:00
try :
self . applyConfig ( )
except Exception as e :
RNS . log ( " The configuration file is invalid. The contained exception was: " + str ( e ) , RNS . LOG_ERROR )
nomadnet . panic ( )
2021-04-08 11:08:07 -04:00
RNS . log ( " Configuration loaded from " + self . configpath )
except Exception as e :
RNS . log ( " Could not parse the configuration at " + self . configpath , RNS . LOG_ERROR )
RNS . log ( " Check your configuration file for errors! " , RNS . LOG_ERROR )
2021-04-08 14:57:31 -04:00
nomadnet . panic ( )
2021-04-08 11:08:07 -04:00
else :
RNS . log ( " Could not load config file, creating default configuration file... " )
self . createDefaultConfig ( )
2021-09-11 06:21:35 -04:00
self . firstrun = True
2021-04-08 11:08:07 -04:00
if os . path . isfile ( self . identitypath ) :
try :
self . identity = RNS . Identity . from_file ( self . identitypath )
if self . identity != None :
RNS . log ( " Loaded Primary Identity %s from %s " % ( str ( self . identity ) , self . identitypath ) )
else :
RNS . log ( " Could not load the Primary Identity from " + self . identitypath , RNS . LOG_ERROR )
2021-04-08 14:57:31 -04:00
nomadnet . panic ( )
2021-04-08 11:08:07 -04:00
except Exception as e :
RNS . log ( " Could not load the Primary Identity from " + self . identitypath , RNS . LOG_ERROR )
RNS . log ( " The contained exception was: %s " % ( str ( e ) ) , RNS . LOG_ERROR )
2021-04-08 14:57:31 -04:00
nomadnet . panic ( )
2021-04-08 11:08:07 -04:00
else :
try :
RNS . log ( " No Primary Identity file found, creating new... " )
self . identity = RNS . Identity ( )
2021-05-16 18:07:11 -04:00
self . identity . to_file ( self . identitypath )
2021-04-08 11:08:07 -04:00
RNS . log ( " Created new Primary Identity %s " % ( str ( self . identity ) ) )
except Exception as e :
RNS . log ( " Could not create and save a new Primary Identity " , RNS . LOG_ERROR )
RNS . log ( " The contained exception was: %s " % ( str ( e ) ) , RNS . LOG_ERROR )
2021-04-09 16:07:38 -04:00
nomadnet . panic ( )
2021-05-15 15:08:30 -04:00
if os . path . isfile ( self . peersettingspath ) :
try :
file = open ( self . peersettingspath , " rb " )
self . peer_settings = msgpack . unpackb ( file . read ( ) )
file . close ( )
2021-09-16 14:44:15 -04:00
if not " node_last_announce " in self . peer_settings :
self . peer_settings [ " node_last_announce " ] = None
2021-09-17 12:45:08 -04:00
2021-10-08 05:17:58 -04:00
if not " propagation_node " in self . peer_settings :
self . peer_settings [ " propagation_node " ] = None
2021-05-15 15:08:30 -04:00
except Exception as e :
RNS . log ( " Could not load local peer settings from " + self . peersettingspath , RNS . LOG_ERROR )
RNS . log ( " The contained exception was: %s " % ( str ( e ) ) , RNS . LOG_ERROR )
nomadnet . panic ( )
else :
try :
RNS . log ( " No peer settings file found, creating new... " )
self . peer_settings = {
2021-09-11 06:21:35 -04:00
" display_name " : " Anonymous Peer " ,
2021-05-15 15:08:30 -04:00
" announce_interval " : None ,
" last_announce " : None ,
2021-09-16 14:44:15 -04:00
" node_last_announce " : None ,
2021-10-08 05:17:58 -04:00
" propagation_node " : None
2021-05-15 15:08:30 -04:00
}
self . save_peer_settings ( )
RNS . log ( " Created new peer settings file " )
except Exception as e :
RNS . log ( " Could not create and save a new peer settings file " , RNS . LOG_ERROR )
RNS . log ( " The contained exception was: %s " % ( str ( e ) ) , RNS . LOG_ERROR )
nomadnet . panic ( )
2021-04-08 11:08:07 -04:00
2021-10-03 12:44:00 -04:00
self . directory = nomadnet . Directory ( self )
2021-04-08 10:29:43 -04:00
2021-10-08 02:53:25 -04:00
self . message_router = LXMF . LXMRouter ( identity = self . identity , storagepath = self . storagepath , autopeer = True )
2021-05-04 05:09:41 -04:00
self . message_router . register_delivery_callback ( self . lxmf_delivery )
2021-05-15 15:08:30 -04:00
self . lxmf_destination = self . message_router . register_delivery_identity ( self . identity , display_name = self . peer_settings [ " display_name " ] )
2021-05-16 09:51:33 -04:00
self . lxmf_destination . set_default_app_data ( self . get_display_name_bytes )
2021-05-14 11:51:38 -04:00
RNS . Identity . remember (
packet_hash = None ,
destination_hash = self . lxmf_destination . hash ,
2021-05-20 16:29:02 -04:00
public_key = self . identity . get_public_key ( ) ,
2021-05-14 11:51:38 -04:00
app_data = None
)
2021-05-04 05:09:41 -04:00
RNS . log ( " LXMF Router ready to receive on: " + RNS . prettyhexrep ( self . lxmf_destination . hash ) )
2021-08-26 09:26:12 -04:00
if self . enable_node :
2021-10-08 02:53:25 -04:00
self . message_router . enable_propagation ( )
2021-10-03 12:44:00 -04:00
RNS . log ( " LXMF Propagation Node started on: " + RNS . prettyhexrep ( self . message_router . propagation_destination . hash ) )
2021-08-26 09:26:12 -04:00
self . node = nomadnet . Node ( self )
else :
self . node = None
2021-08-26 10:17:01 -04:00
RNS . Transport . register_announce_handler ( nomadnet . Conversation )
RNS . Transport . register_announce_handler ( nomadnet . Directory )
2021-10-03 12:44:00 -04:00
self . autoselect_propagation_node ( )
2021-09-16 13:54:32 -04:00
if self . peer_announce_at_start :
2021-12-11 13:20:34 -05:00
def delayed_announce ( ) :
time . sleep ( NomadNetworkApp . START_ANNOUNCE_DELAY )
self . announce_now ( )
da_thread = threading . Thread ( target = delayed_announce )
da_thread . setDaemon ( True )
da_thread . start ( )
2021-09-16 13:54:32 -04:00
2021-10-03 12:44:00 -04:00
atexit . register ( self . exit_handler )
2021-11-04 16:51:11 -04:00
sys . excepthook = self . exception_handler
2021-10-03 12:44:00 -04:00
2021-11-05 05:59:51 -04:00
# This stderr redirect is needed to stop urwid
# from spewing KeyErrors to the console and thus,
# messing up the UI. A pull request to fix the
# bug in urwid was submitted, but until it is
# merged, this hack will mitigate it.
strio = io . StringIO ( )
with contextlib . redirect_stderr ( strio ) :
nomadnet . ui . spawn ( self . uimode )
if strio . tell ( ) > 0 :
try :
strio . seek ( 0 )
err_file = open ( self . errorfilepath , " w " )
err_file . write ( strio . read ( ) )
err_file . close ( )
except Exception as e :
RNS . log ( " Could not write stderr output to error log file at " + str ( self . errorfilepath ) + " . " , RNS . LOG_ERROR )
RNS . log ( " The contained exception was: " + str ( e ) , RNS . LOG_ERROR )
2021-04-08 14:57:31 -04:00
2021-05-15 15:08:30 -04:00
def set_display_name ( self , display_name ) :
self . peer_settings [ " display_name " ] = display_name
self . lxmf_destination . display_name = display_name
self . save_peer_settings ( )
def get_display_name ( self ) :
return self . peer_settings [ " display_name " ]
2021-05-16 09:51:33 -04:00
def get_display_name_bytes ( self ) :
return self . peer_settings [ " display_name " ] . encode ( " utf-8 " )
2021-10-07 12:14:06 -04:00
def get_sync_status ( self ) :
if self . message_router . propagation_transfer_state == LXMF . LXMRouter . PR_IDLE :
return " Idle "
elif self . message_router . propagation_transfer_state == LXMF . LXMRouter . PR_PATH_REQUESTED :
return " Path requested "
elif self . message_router . propagation_transfer_state == LXMF . LXMRouter . PR_LINK_ESTABLISHING :
return " Establishing link "
elif self . message_router . propagation_transfer_state == LXMF . LXMRouter . PR_LINK_ESTABLISHED :
return " Link established "
elif self . message_router . propagation_transfer_state == LXMF . LXMRouter . PR_REQUEST_SENT :
2021-10-12 15:08:31 -04:00
return " Sync request sent "
elif self . message_router . propagation_transfer_state == LXMF . LXMRouter . PR_RECEIVING :
2021-10-07 12:14:06 -04:00
return " Receiving messages "
elif self . message_router . propagation_transfer_state == LXMF . LXMRouter . PR_RESPONSE_RECEIVED :
return " Messages received "
elif self . message_router . propagation_transfer_state == LXMF . LXMRouter . PR_COMPLETE :
new_msgs = self . message_router . propagation_transfer_last_result
if new_msgs == 0 :
return " Done, no new messages "
else :
return " Downloaded " + str ( new_msgs ) + " new messages "
else :
return " Unknown "
def sync_status_show_percent ( self ) :
if self . message_router . propagation_transfer_state == LXMF . LXMRouter . PR_IDLE :
return False
elif self . message_router . propagation_transfer_state == LXMF . LXMRouter . PR_PATH_REQUESTED :
return True
elif self . message_router . propagation_transfer_state == LXMF . LXMRouter . PR_LINK_ESTABLISHING :
return True
elif self . message_router . propagation_transfer_state == LXMF . LXMRouter . PR_LINK_ESTABLISHED :
return True
elif self . message_router . propagation_transfer_state == LXMF . LXMRouter . PR_REQUEST_SENT :
return True
2021-10-12 15:12:32 -04:00
elif self . message_router . propagation_transfer_state == LXMF . LXMRouter . PR_RECEIVING :
return True
2021-10-07 12:14:06 -04:00
elif self . message_router . propagation_transfer_state == LXMF . LXMRouter . PR_RESPONSE_RECEIVED :
return True
elif self . message_router . propagation_transfer_state == LXMF . LXMRouter . PR_COMPLETE :
return False
else :
return False
def get_sync_progress ( self ) :
return self . message_router . propagation_transfer_progress
2021-10-08 05:58:24 -04:00
def request_lxmf_sync ( self , limit = None ) :
2021-10-07 12:14:06 -04:00
if self . message_router . propagation_transfer_state == LXMF . LXMRouter . PR_IDLE or self . message_router . propagation_transfer_state == LXMF . LXMRouter . PR_COMPLETE :
2021-10-08 05:58:24 -04:00
self . message_router . request_messages_from_propagation_node ( self . identity , max_messages = limit )
2021-10-07 12:14:06 -04:00
def cancel_lxmf_sync ( self ) :
if self . message_router . propagation_transfer_state != LXMF . LXMRouter . PR_IDLE :
self . message_router . cancel_propagation_node_requests ( )
2021-05-15 15:08:30 -04:00
def announce_now ( self ) :
self . lxmf_destination . announce ( )
self . peer_settings [ " last_announce " ] = time . time ( )
self . save_peer_settings ( )
2021-10-03 12:44:00 -04:00
def autoselect_propagation_node ( self ) :
selected_node = None
2021-10-08 05:17:58 -04:00
if " propagation_node " in self . peer_settings and self . directory . find ( self . peer_settings [ " propagation_node " ] ) :
selected_node = self . directory . find ( self . peer_settings [ " propagation_node " ] )
else :
nodes = self . directory . known_nodes ( )
trusted_nodes = [ ]
best_hops = RNS . Transport . PATHFINDER_M + 1
for node in nodes :
if node . trust_level == DirectoryEntry . TRUSTED :
hops = RNS . Transport . hops_to ( node . source_hash )
2021-10-03 12:44:00 -04:00
2021-10-08 05:17:58 -04:00
if hops < best_hops :
best_hops = hops
selected_node = node
2021-10-03 12:44:00 -04:00
if selected_node == None :
RNS . log ( " Could not autoselect a prepagation node! LXMF propagation will not be available until a trusted node announces on the network. " , RNS . LOG_WARNING )
else :
node_identity = RNS . Identity . recall ( selected_node . source_hash )
2021-10-07 15:04:11 -04:00
if node_identity != None :
propagation_hash = RNS . Destination . hash_from_name_and_identity ( " lxmf.propagation " , node_identity )
RNS . log ( " Selecting " + selected_node . display_name + " " + RNS . prettyhexrep ( propagation_hash ) + " as default LXMF propagation node " , RNS . LOG_INFO )
self . message_router . set_outbound_propagation_node ( propagation_hash )
else :
RNS . log ( " Could not recall identity for autoselected LXMF propagation node " + RNS . prettyhexrep ( selected_node . source_hash ) , RNS . LOG_WARNING )
RNS . log ( " LXMF propagation will not be available until a trusted node announces on the network. " , RNS . LOG_WARNING )
2021-10-08 05:17:58 -04:00
def get_user_selected_propagation_node ( self ) :
if " propagation_node " in self . peer_settings :
return self . peer_settings [ " propagation_node " ]
else :
return None
def set_user_selected_propagation_node ( self , node_hash ) :
self . peer_settings [ " propagation_node " ] = node_hash
self . save_peer_settings ( )
self . autoselect_propagation_node ( )
2021-10-08 03:12:20 -04:00
def get_default_propagation_node ( self ) :
return self . message_router . get_outbound_propagation_node ( )
2021-10-03 12:44:00 -04:00
2021-05-15 15:08:30 -04:00
def save_peer_settings ( self ) :
file = open ( self . peersettingspath , " wb " )
file . write ( msgpack . packb ( self . peer_settings ) )
file . close ( )
2021-04-08 10:29:43 -04:00
2021-05-04 05:09:41 -04:00
def lxmf_delivery ( self , message ) :
time_string = time . strftime ( " % Y- % m- %d % H: % M: % S " , time . localtime ( message . timestamp ) )
signature_string = " Signature is invalid, reason undetermined "
if message . signature_validated :
signature_string = " Validated "
else :
if message . unverified_reason == LXMF . LXMessage . SIGNATURE_INVALID :
signature_string = " Invalid signature "
if message . unverified_reason == LXMF . LXMessage . SOURCE_UNKNOWN :
signature_string = " Cannot verify, source is unknown "
nomadnet . Conversation . ingest ( message , self )
2021-05-04 09:10:21 -04:00
def conversations ( self ) :
return nomadnet . Conversation . conversation_list ( self )
2021-05-04 05:09:41 -04:00
2021-09-23 11:20:13 -04:00
def has_unread_conversations ( self ) :
if len ( nomadnet . Conversation . unread_conversations ) > 0 :
return True
else :
return False
2021-09-05 14:38:10 -04:00
def conversation_is_unread ( self , source_hash ) :
if bytes . fromhex ( source_hash ) in nomadnet . Conversation . unread_conversations :
return True
else :
return False
def mark_conversation_read ( self , source_hash ) :
if bytes . fromhex ( source_hash ) in nomadnet . Conversation . unread_conversations :
nomadnet . Conversation . unread_conversations . pop ( bytes . fromhex ( source_hash ) )
if os . path . isfile ( self . conversationpath + " / " + source_hash + " /unread " ) :
os . unlink ( self . conversationpath + " / " + source_hash + " /unread " )
2021-04-08 11:08:07 -04:00
def createDefaultConfig ( self ) :
self . config = ConfigObj ( __default_nomadnet_config__ )
self . config . filename = self . configpath
if not os . path . isdir ( self . configdir ) :
os . makedirs ( self . configdir )
self . config . write ( )
self . applyConfig ( )
def applyConfig ( self ) :
if " logging " in self . config :
for option in self . config [ " logging " ] :
value = self . config [ " logging " ] [ option ]
if option == " loglevel " :
RNS . loglevel = int ( value )
if RNS . loglevel < 0 :
RNS . loglevel = 0
if RNS . loglevel > 7 :
RNS . loglevel = 7
2021-04-09 16:07:38 -04:00
if option == " destination " :
if value . lower ( ) == " file " :
RNS . logdest = RNS . LOG_FILE
if " logfile " in self . config [ " logging " ] :
self . logfilepath = self . config [ " logging " ] [ " logfile " ]
RNS . logfile = self . logfilepath
else :
RNS . logdest = RNS . LOG_STDOUT
2021-04-08 11:08:07 -04:00
if " client " in self . config :
for option in self . config [ " client " ] :
value = self . config [ " client " ] [ option ]
if option == " enable_client " :
value = self . config [ " client " ] . as_bool ( option )
self . enable_client = value
2021-09-10 15:33:29 -04:00
if option == " downloads_path " :
value = self . config [ " client " ] [ " downloads_path " ]
self . downloads_path = os . path . expanduser ( value )
2021-09-16 13:54:32 -04:00
if option == " announce_at_start " :
value = self . config [ " client " ] . as_bool ( option )
self . peer_announce_at_start = value
2021-10-03 12:44:00 -04:00
if option == " try_propagation_on_send_fail " :
value = self . config [ " client " ] . as_bool ( option )
self . try_propagation_on_fail = value
2021-04-08 14:57:31 -04:00
if option == " user_interface " :
value = value . lower ( )
if value == " none " :
self . uimode = nomadnet . ui . UI_NONE
if value == " menu " :
self . uimode = nomadnet . ui . UI_MENU
if value == " text " :
self . uimode = nomadnet . ui . UI_TEXT
2021-04-09 16:07:38 -04:00
if " textui " in self . config :
if not " intro_time " in self . config [ " textui " ] :
self . config [ " textui " ] [ " intro_time " ] = 1
else :
self . config [ " textui " ] [ " intro_time " ] = self . config [ " textui " ] . as_int ( " intro_time " )
2021-06-30 16:17:21 -04:00
if not " editor " in self . config [ " textui " ] :
self . config [ " textui " ] [ " editor " ] = " editor "
2021-07-02 07:35:10 -04:00
if not " glyphs " in self . config [ " textui " ] :
self . config [ " textui " ] [ " glyphs " ] = " unicode "
2021-06-30 17:29:37 -04:00
if not " mouse_enabled " in self . config [ " textui " ] :
self . config [ " textui " ] [ " mouse_enabled " ] = True
else :
2021-07-02 09:34:08 -04:00
self . config [ " textui " ] [ " mouse_enabled " ] = self . config [ " textui " ] . as_bool ( " mouse_enabled " )
2021-06-30 17:29:37 -04:00
2021-07-04 19:15:02 -04:00
if not " hide_guide " in self . config [ " textui " ] :
self . config [ " textui " ] [ " hide_guide " ] = False
else :
self . config [ " textui " ] [ " hide_guide " ] = self . config [ " textui " ] . as_bool ( " hide_guide " )
2021-05-15 15:08:30 -04:00
if not " animation_interval " in self . config [ " textui " ] :
self . config [ " textui " ] [ " animation_interval " ] = 1
else :
self . config [ " textui " ] [ " animation_interval " ] = self . config [ " textui " ] . as_int ( " animation_interval " )
2021-04-09 16:07:38 -04:00
if not " colormode " in self . config [ " textui " ] :
self . config [ " textui " ] [ " colormode " ] = nomadnet . ui . COLORMODE_16
else :
if self . config [ " textui " ] [ " colormode " ] . lower ( ) == " monochrome " :
2021-05-04 14:53:03 -04:00
self . config [ " textui " ] [ " colormode " ] = nomadnet . ui . TextUI . COLORMODE_MONO
2021-04-09 16:07:38 -04:00
elif self . config [ " textui " ] [ " colormode " ] . lower ( ) == " 16 " :
2021-05-04 14:53:03 -04:00
self . config [ " textui " ] [ " colormode " ] = nomadnet . ui . TextUI . COLORMODE_16
2021-04-09 16:07:38 -04:00
elif self . config [ " textui " ] [ " colormode " ] . lower ( ) == " 88 " :
2021-05-04 14:53:03 -04:00
self . config [ " textui " ] [ " colormode " ] = nomadnet . ui . TextUI . COLORMODE_88
2021-04-09 16:07:38 -04:00
elif self . config [ " textui " ] [ " colormode " ] . lower ( ) == " 256 " :
2021-05-04 14:53:03 -04:00
self . config [ " textui " ] [ " colormode " ] = nomadnet . ui . TextUI . COLORMODE_256
2021-04-09 16:07:38 -04:00
elif self . config [ " textui " ] [ " colormode " ] . lower ( ) == " 24bit " :
2021-05-04 14:53:03 -04:00
self . config [ " textui " ] [ " colormode " ] = nomadnet . ui . TextUI . COLORMODE_TRUE
2021-04-09 16:07:38 -04:00
else :
raise ValueError ( " The selected Text UI color mode is invalid " )
if not " theme " in self . config [ " textui " ] :
2021-05-04 14:53:03 -04:00
self . config [ " textui " ] [ " theme " ] = nomadnet . ui . TextUI . THEME_DARK
2021-04-09 16:07:38 -04:00
else :
if self . config [ " textui " ] [ " theme " ] . lower ( ) == " dark " :
2021-05-04 14:53:03 -04:00
self . config [ " textui " ] [ " theme " ] = nomadnet . ui . TextUI . THEME_DARK
2021-04-09 16:07:38 -04:00
elif self . config [ " textui " ] [ " theme " ] . lower ( ) == " light " :
2021-05-04 14:53:03 -04:00
self . config [ " textui " ] [ " theme " ] = nomadnet . ui . TextUI . THEME_LIGHT
2021-04-09 16:07:38 -04:00
else :
raise ValueError ( " The selected Text UI theme is invalid " )
else :
raise KeyError ( " Text UI selected in configuration file, but no [textui] section found " )
2021-04-08 14:57:31 -04:00
if value == " graphical " :
self . uimode = nomadnet . ui . UI_GRAPHICAL
if value == " web " :
self . uimode = nomadnet . ui . UI_WEB
2021-04-08 11:08:07 -04:00
if " node " in self . config :
2021-08-26 09:26:12 -04:00
if not " enable_node " in self . config [ " node " ] :
self . enable_node = False
else :
self . enable_node = self . config [ " node " ] . as_bool ( " enable_node " )
if not " node_name " in self . config [ " node " ] :
self . node_name = None
else :
value = self . config [ " node " ] [ " node_name " ]
if value . lower ( ) == " none " :
self . node_name = None
else :
self . node_name = self . config [ " node " ] [ " node_name " ]
if not " announce_at_start " in self . config [ " node " ] :
self . node_announce_at_start = False
else :
2021-09-16 13:54:32 -04:00
value = self . config [ " node " ] . as_bool ( " announce_at_start " )
self . node_announce_at_start = value
2021-08-26 09:26:12 -04:00
if not " announce_interval " in self . config [ " node " ] :
self . node_announce_interval = 720
else :
2021-08-26 10:29:35 -04:00
value = self . config [ " node " ] . as_int ( " announce_interval " )
2021-08-26 09:26:12 -04:00
if value < 1 :
value = 1
self . node_announce_interval = value
2021-04-08 11:08:07 -04:00
2021-08-26 09:26:12 -04:00
if " pages_path " in self . config [ " node " ] :
self . pagespath = self . config [ " node " ] [ " pages_path " ]
2021-04-08 11:08:07 -04:00
2021-08-26 09:26:12 -04:00
if " files_path " in self . config [ " node " ] :
self . filespath = self . config [ " node " ] [ " files_path " ]
2021-04-08 10:29:43 -04:00
@staticmethod
def get_shared_instance ( ) :
if NomadNetworkApp . _shared_instance != None :
return NomadNetworkApp . _shared_instance
else :
raise UnboundLocalError ( " No Nomad Network applications have been instantiated yet " )
def quit ( self ) :
RNS . log ( " Nomad Network Client shutting down... " )
2021-04-08 11:08:07 -04:00
os . _exit ( 0 )
# Default configuration file:
__default_nomadnet_config__ = ''' # This is the default Nomad Network config file.
# You should probably edit it to suit your needs and use-case,
[ logging ]
# Valid log levels are 0 through 7:
# 0: Log only critical information
# 1: Log errors and lower log levels
# 2: Log warnings and lower log levels
# 3: Log notices and lower log levels
# 4: Log info and lower (this is the default)
# 5: Verbose logging
# 6: Debug logging
# 7: Extreme logging
loglevel = 4
2021-04-09 16:07:38 -04:00
destination = file
2021-04-08 11:08:07 -04:00
[ client ]
2021-07-02 09:34:08 -04:00
enable_client = yes
2021-04-08 14:57:31 -04:00
user_interface = text
2021-09-10 15:33:29 -04:00
downloads_path = ~ / Downloads
2021-04-08 11:08:07 -04:00
2021-09-16 13:54:32 -04:00
# By default, the peer is announced at startup
# to let other peers reach it immediately.
announce_at_start = yes
2021-10-03 12:44:00 -04:00
# By default, the client will try to deliver a
# message via the LXMF propagation network, if
# a direct delivery to the recipient is not
# possible.
try_propagation_on_send_fail = yes
2021-04-09 16:07:38 -04:00
[ textui ]
2021-06-30 16:17:21 -04:00
# Amount of time to show intro screen
2021-04-09 16:07:38 -04:00
intro_time = 1
2021-09-17 15:16:30 -04:00
# You can specify the display theme.
2021-09-25 10:57:29 -04:00
# theme = light
theme = dark
2021-09-17 15:16:30 -04:00
2021-04-09 16:07:38 -04:00
# Specify the number of colors to use
# valid colormodes are:
# monochrome, 16, 88, 256 and 24bit
#
2021-09-11 06:21:35 -04:00
# The default is a conservative 256 colors.
# If your terminal does not support this,
# you can lower it. Some terminals support
2021-05-27 04:40:13 -04:00
# 24 bit color.
2021-04-09 16:07:38 -04:00
# colormode = monochrome
2021-09-11 06:21:35 -04:00
# colormode = 16
2021-05-27 04:39:34 -04:00
# colormode = 88
2021-09-11 06:21:35 -04:00
colormode = 256
2021-04-09 16:07:38 -04:00
# colormode = 24bit
2021-07-02 07:35:10 -04:00
# By default, unicode glyphs are used. If
# you have a Nerd Font installed, you can
# enable this for a better user interface.
# You can also enable plain text glyphs if
# your terminal doesn't support unicode.
# glyphs = plain
glyphs = unicode
# glyphs = nerdfont
2021-06-30 17:29:37 -04:00
# You can specify whether mouse events
# should be considered as input to the
# application. On by default.
mouse_enabled = True
2021-06-30 16:17:21 -04:00
# What editor to use for editing text. By
# default the operating systems "editor"
# alias will be used.
editor = editor
2021-07-04 19:15:02 -04:00
# If you don't want the Guide section to
# show up in the menu, you can disable it.
hide_guide = no
2021-04-08 11:08:07 -04:00
[ node ]
2021-08-26 09:26:12 -04:00
# Whether to enable node hosting
2021-07-02 09:34:08 -04:00
enable_node = no
2021-04-08 11:08:07 -04:00
2021-08-26 09:26:12 -04:00
# The node name will be visible to other
# peers on the network, and included in
# announces.
node_name = None
# Automatic announce interval in minutes.
2021-09-25 10:57:29 -04:00
# 6 hours by default.
2021-08-26 09:26:12 -04:00
2021-09-25 10:57:29 -04:00
announce_interval = 360
2021-08-26 09:26:12 -04:00
# Whether to announce when the node starts
2021-09-25 10:57:29 -04:00
announce_at_start = Yes
2021-08-26 09:26:12 -04:00
2021-04-08 11:08:07 -04:00
''' .splitlines()