mirror of
https://github.com/markqvist/NomadNet.git
synced 2025-12-17 14:54:26 +01:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
77c9e6c9eb | ||
|
|
ecb6ca6553 | ||
|
|
18cc588f93 | ||
|
|
ed64837a6c | ||
|
|
4a1832ae34 | ||
|
|
648242b99f | ||
|
|
8ad19cf048 | ||
|
|
7bf577a8c5 | ||
|
|
b14d42a17c | ||
|
|
51f0048e7c | ||
|
|
c2fb2ca9f8 |
@@ -8,7 +8,7 @@ Nomad Network allows you to build private and resilient communications platforms
|
|||||||
|
|
||||||
Nomad Network is build on [LXMF](https://github.com/markqvist/LXMF) and [Reticulum](https://github.com/markqvist/Reticulum), which together provides the cryptographic mesh functionality and peer-to-peer message routing that Nomad Network relies on. This foundation also makes it possible to use the program over a very wide variety of communication mediums, from packet radio to fiber optics.
|
Nomad Network is build on [LXMF](https://github.com/markqvist/LXMF) and [Reticulum](https://github.com/markqvist/Reticulum), which together provides the cryptographic mesh functionality and peer-to-peer message routing that Nomad Network relies on. This foundation also makes it possible to use the program over a very wide variety of communication mediums, from packet radio to fiber optics.
|
||||||
|
|
||||||
Nomad Network does not need any connections to the public internet to work. In fact, it doesn't even need an IP or Ethernet network. You can use it entirely over packet radio, LoRa or even serial lines. But if you wish, you can bridge islanded networks over the Internet or private ethernet networks, or you can build networks running completely over the Internet. The choice is yours.
|
Nomad Network does not need any connections to the public internet to work. In fact, it doesn't even need an IP or Ethernet network. You can use it entirely over packet radio, LoRa or even serial lines. But if you wish, you can bridge islanded networks over the Internet or private ethernet networks, or you can build networks running completely over the Internet. The choice is yours. Since Nomad Network uses Reticulum, it is efficient enough to run even over *extremely* low-bandwidth medium, and has been succesfully used over 300bps radio links.
|
||||||
|
|
||||||
If you'd rather want to use an LXMF client with a graphical user interface, you may want to take a look at [Sideband](https://github.com/markqvist/sideband), which is available for Linux, Android and macOS.
|
If you'd rather want to use an LXMF client with a graphical user interface, you may want to take a look at [Sideband](https://github.com/markqvist/sideband), which is available for Linux, Android and macOS.
|
||||||
|
|
||||||
@@ -161,7 +161,6 @@ You can help support the continued development of open, free and private communi
|
|||||||
- New major features
|
- New major features
|
||||||
- Network-wide propagated bulletins and discussion threads
|
- Network-wide propagated bulletins and discussion threads
|
||||||
- Collaborative maps and geospatial information sharing
|
- Collaborative maps and geospatial information sharing
|
||||||
- Facilitation of trade and barter
|
|
||||||
- Minor improvements and fixes
|
- Minor improvements and fixes
|
||||||
- Link status (RSSI and SNR) in conversation or conv list
|
- Link status (RSSI and SNR) in conversation or conv list
|
||||||
- Ctrl-M shorcut for jumping to menu
|
- Ctrl-M shorcut for jumping to menu
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
__version__ = "0.4.8"
|
__version__ = "0.5.0"
|
||||||
|
|||||||
@@ -97,10 +97,10 @@ GLYPHSETS = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if platform.system() == "Darwin":
|
if platform.system() == "Darwin":
|
||||||
urm_char = " \uf0e0 "
|
urm_char = " \uf0e0"
|
||||||
ur_char = "\uf0e0 "
|
ur_char = "\uf0e0 "
|
||||||
else:
|
else:
|
||||||
urm_char = " \uf003 "
|
urm_char = " \uf003"
|
||||||
ur_char = "\uf003 "
|
ur_char = "\uf003 "
|
||||||
|
|
||||||
GLYPHS = {
|
GLYPHS = {
|
||||||
@@ -115,17 +115,17 @@ GLYPHS = {
|
|||||||
("arrow_u", "/\\", "\u2191", "\u2191"),
|
("arrow_u", "/\\", "\u2191", "\u2191"),
|
||||||
("arrow_d", "\\/", "\u2193", "\u2193"),
|
("arrow_d", "\\/", "\u2193", "\u2193"),
|
||||||
("warning", "!", "\u26a0", "\uf12a"),
|
("warning", "!", "\u26a0", "\uf12a"),
|
||||||
("info", "i", "\u2139", "\ufb4d"),
|
("info", "i", "\u2139", "\U000f064e"),
|
||||||
("unread", "[!]", "\u2709", ur_char),
|
("unread", "[!]", "\u2709", ur_char),
|
||||||
("divider1", "-", "\u2504", "\u2504"),
|
("divider1", "-", "\u2504", "\u2504"),
|
||||||
("peer", "[P]", "\u24c5 ", "\uf415"),
|
("peer", "[P]", "\u24c5 ", "\uf415"),
|
||||||
("node", "[N]", "\u24c3 ", "\uf502"),
|
("node", "[N]", "\u24c3 ", "\U000f0002"),
|
||||||
("page", "", "\u25a4 ", "\uf719 "),
|
("page", "", "\u25a4 ", "\uf719 "),
|
||||||
("speed", "", "\u25F7 ", "\uf9c4"),
|
("speed", "", "\u25F7 ", "\U000f04c5 "),
|
||||||
("decoration_menu", " +", " +", " \uf93a"),
|
("decoration_menu", " +", " +", " \U000f043b"),
|
||||||
("unread_menu", " !", " \u2709", urm_char),
|
("unread_menu", " !", " \u2709", urm_char),
|
||||||
("globe", "", "", "\uf484"),
|
("globe", "", "", "\uf484"),
|
||||||
("sent", "/\\", "\u2191", "\ufbf4"),
|
("sent", "/\\", "\u2191", "\U000f0cd8"),
|
||||||
("papermsg", "P", "\u25a4", "\uf719"),
|
("papermsg", "P", "\u25a4", "\uf719"),
|
||||||
("qrcode", "QR", "\u25a4", "\uf029"),
|
("qrcode", "QR", "\u25a4", "\uf029"),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1056,7 +1056,7 @@ class ConversationWidget(urwid.WidgetWrap):
|
|||||||
else:
|
else:
|
||||||
warning = urwid.AttrMap(
|
warning = urwid.AttrMap(
|
||||||
urwid.Padding(urwid.Text(
|
urwid.Padding(urwid.Text(
|
||||||
"\n"+g["info"]+"\n\nYou cannot currently message this peer, since it's identity keys are not known. "
|
"\n"+g["info"]+"\n\nYou cannot currently message this peer, since its identity keys are not known. "
|
||||||
"The keys have been requested from the network and should arrive shortly, if available. "
|
"The keys have been requested from the network and should arrive shortly, if available. "
|
||||||
"Close this conversation and reopen it to try again.\n\n"
|
"Close this conversation and reopen it to try again.\n\n"
|
||||||
"To query the network manually, select this conversation in the conversation list, "
|
"To query the network manually, select this conversation in the conversation list, "
|
||||||
|
|||||||
@@ -485,6 +485,12 @@ Selects which interface to use. Currently, only the `!text`! interface is availa
|
|||||||
Sets the filesystem path to store downloaded files in.
|
Sets the filesystem path to store downloaded files in.
|
||||||
<
|
<
|
||||||
|
|
||||||
|
>>>
|
||||||
|
`!notify_on_new_message = yes`!
|
||||||
|
>>>>
|
||||||
|
Sets whether to output a notification character (bell or flash) to the terminal when a new message is received.
|
||||||
|
<
|
||||||
|
|
||||||
>>>
|
>>>
|
||||||
`!announce_at_start = yes`!
|
`!announce_at_start = yes`!
|
||||||
>>>>
|
>>>>
|
||||||
@@ -783,7 +789,7 @@ The following line should contain a grayscale gradient bar:
|
|||||||
|
|
||||||
Unicode Glyphs : \u2713 \u2715 \u26a0 \u24c3 \u2193
|
Unicode Glyphs : \u2713 \u2715 \u26a0 \u24c3 \u2193
|
||||||
|
|
||||||
Nerd Font Glyphs : \uf484 \uf9c4 \uf719 \uf502 \uf415 \uf023 \uf06e
|
Nerd Font Glyphs : \uf484 \U000f04c5 \U000f0219 \U000f0002 \uf415 \uf023 \uf06e
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
@@ -1064,7 +1070,7 @@ Links can contain request variables and a list of fields to submit to the node-s
|
|||||||
`=
|
`=
|
||||||
``
|
``
|
||||||
|
|
||||||
Note the `!*`! following the extra `!\``! at the end of the path. This `!*`! denotes `*all fields`*. You can also specify a list of fields to include:
|
Note the `!*`! following the extra `!\\``! at the end of the path. This `!*`! denotes `*all fields`*. You can also specify a list of fields to include:
|
||||||
|
|
||||||
`Faaa
|
`Faaa
|
||||||
`=
|
`=
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import itertools
|
||||||
|
import mmap
|
||||||
import urwid
|
import urwid
|
||||||
import nomadnet
|
import nomadnet
|
||||||
|
|
||||||
|
|
||||||
class LogDisplayShortcuts():
|
class LogDisplayShortcuts():
|
||||||
def __init__(self, app):
|
def __init__(self, app):
|
||||||
import urwid
|
import urwid
|
||||||
@@ -8,28 +13,31 @@ class LogDisplayShortcuts():
|
|||||||
|
|
||||||
self.widget = urwid.AttrMap(urwid.Text(""), "shortcutbar")
|
self.widget = urwid.AttrMap(urwid.Text(""), "shortcutbar")
|
||||||
|
|
||||||
|
|
||||||
class LogDisplay():
|
class LogDisplay():
|
||||||
def __init__(self, app):
|
def __init__(self, app):
|
||||||
self.app = app
|
self.app = app
|
||||||
self.log_term = None
|
|
||||||
|
|
||||||
self.shortcuts_display = LogDisplayShortcuts(self.app)
|
self.shortcuts_display = LogDisplayShortcuts(self.app)
|
||||||
self.widget = None
|
self.widget = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def log_term(self):
|
||||||
|
return self.widget
|
||||||
|
|
||||||
def show(self):
|
def show(self):
|
||||||
if self.log_term == None:
|
if self.widget is None:
|
||||||
self.log_term = LogTerminal(self.app)
|
self.widget = log_widget(self.app)
|
||||||
self.widget = urwid.LineBox(self.log_term)
|
|
||||||
|
|
||||||
def kill(self):
|
def kill(self):
|
||||||
if self.log_term != None:
|
if self.widget is not None:
|
||||||
self.log_term.terminate()
|
self.widget.terminate()
|
||||||
self.log_term = None
|
|
||||||
self.widget = None
|
self.widget = None
|
||||||
|
|
||||||
def shortcuts(self):
|
def shortcuts(self):
|
||||||
return self.shortcuts_display
|
return self.shortcuts_display
|
||||||
|
|
||||||
|
|
||||||
class LogTerminal(urwid.WidgetWrap):
|
class LogTerminal(urwid.WidgetWrap):
|
||||||
def __init__(self, app):
|
def __init__(self, app):
|
||||||
self.app = app
|
self.app = app
|
||||||
@@ -39,7 +47,8 @@ class LogTerminal(urwid.WidgetWrap):
|
|||||||
escape_sequence="up",
|
escape_sequence="up",
|
||||||
main_loop=self.app.ui.loop,
|
main_loop=self.app.ui.loop,
|
||||||
)
|
)
|
||||||
super().__init__(self.log_term)
|
self.widget = urwid.LineBox(self.log_term)
|
||||||
|
super().__init__(self.widget)
|
||||||
|
|
||||||
def terminate(self):
|
def terminate(self):
|
||||||
self.log_term.terminate()
|
self.log_term.terminate()
|
||||||
@@ -49,4 +58,70 @@ class LogTerminal(urwid.WidgetWrap):
|
|||||||
if key == "up":
|
if key == "up":
|
||||||
nomadnet.NomadNetworkApp.get_shared_instance().ui.main_display.frame.focus_position = "header"
|
nomadnet.NomadNetworkApp.get_shared_instance().ui.main_display.frame.focus_position = "header"
|
||||||
|
|
||||||
return super(LogTerminal, self).keypress(size, key)
|
return super(LogTerminal, self).keypress(size, key)
|
||||||
|
|
||||||
|
|
||||||
|
class LogTail(urwid.WidgetWrap):
|
||||||
|
def __init__(self, app):
|
||||||
|
self.app = app
|
||||||
|
self.log_tail = urwid.Text(tail(self.app.logfilepath, 50))
|
||||||
|
self.log = urwid.Scrollable(self.log_tail)
|
||||||
|
self.log.set_scrollpos(-1)
|
||||||
|
self.log_scrollbar = urwid.ScrollBar(self.log)
|
||||||
|
# We have this here because ui.textui.Main depends on this field to kill it
|
||||||
|
self.log_term = None
|
||||||
|
|
||||||
|
super().__init__(self.log_scrollbar)
|
||||||
|
|
||||||
|
def terminate(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def log_widget(app, platform=sys.platform):
|
||||||
|
if platform == "win32":
|
||||||
|
return LogTail(app)
|
||||||
|
else:
|
||||||
|
return LogTerminal(app)
|
||||||
|
|
||||||
|
# https://stackoverflow.com/a/34029605/3713120
|
||||||
|
def _tail(f_name, n, offset=0):
|
||||||
|
def skip_back_lines(mm: mmap.mmap, numlines: int, startidx: int) -> int:
|
||||||
|
'''Factored out to simplify handling of n and offset'''
|
||||||
|
for _ in itertools.repeat(None, numlines):
|
||||||
|
startidx = mm.rfind(b'\n', 0, startidx)
|
||||||
|
if startidx < 0:
|
||||||
|
break
|
||||||
|
return startidx
|
||||||
|
|
||||||
|
# Open file in binary mode
|
||||||
|
with open(f_name, 'rb') as binf, mmap.mmap(binf.fileno(), 0, access=mmap.ACCESS_READ) as mm:
|
||||||
|
# len(mm) - 1 handles files ending w/newline by getting the prior line
|
||||||
|
startofline = skip_back_lines(mm, offset, len(mm) - 1)
|
||||||
|
if startofline < 0:
|
||||||
|
return [] # Offset lines consumed whole file, nothing to return
|
||||||
|
# If using a generator function (yield-ing, see below),
|
||||||
|
# this should be a plain return, no empty list
|
||||||
|
|
||||||
|
endoflines = startofline + 1 # Slice end to omit offset lines
|
||||||
|
|
||||||
|
# Find start of lines to capture (add 1 to move from newline to beginning of following line)
|
||||||
|
startofline = skip_back_lines(mm, n, startofline) + 1
|
||||||
|
|
||||||
|
# Passing True to splitlines makes it return the list of lines without
|
||||||
|
# removing the trailing newline (if any), so list mimics f.readlines()
|
||||||
|
# return mm[startofline:endoflines].splitlines(True)
|
||||||
|
# If Windows style \r\n newlines need to be normalized to \n
|
||||||
|
return mm[startofline:endoflines].replace(os.linesep.encode(sys.getdefaultencoding()), b'\n').splitlines(True)
|
||||||
|
|
||||||
|
|
||||||
|
def tail(f_name, n):
|
||||||
|
"""
|
||||||
|
Return the last n lines of a given file name, f_name.
|
||||||
|
Akin to `tail -<n> <f_name>`
|
||||||
|
"""
|
||||||
|
def decode(b):
|
||||||
|
return b.decode(encoding)
|
||||||
|
|
||||||
|
encoding = sys.getdefaultencoding()
|
||||||
|
lines = map(decode, _tail(f_name=f_name, n=n))
|
||||||
|
return ''.join(lines)
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
compiler==0.2.0
|
|
||||||
configobj==5.0.8
|
|
||||||
lxmf==0.3.2
|
|
||||||
rns==0.5.7
|
|
||||||
setuptools==68.0.0
|
|
||||||
urwid==2.1.2
|
|
||||||
2
setup.py
2
setup.py
@@ -30,6 +30,6 @@ setuptools.setup(
|
|||||||
entry_points= {
|
entry_points= {
|
||||||
'console_scripts': ['nomadnet=nomadnet.nomadnet:main']
|
'console_scripts': ['nomadnet=nomadnet.nomadnet:main']
|
||||||
},
|
},
|
||||||
install_requires=["rns>=0.7.2", "lxmf>=0.4.1", "urwid>=2.4.2,!=2.4.3", "qrcode"],
|
install_requires=["rns>=0.7.6", "lxmf>=0.4.5", "urwid>=2.4.4", "qrcode"],
|
||||||
python_requires=">=3.6",
|
python_requires=">=3.6",
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user