PyBitmessage/src/bitmessagecurses/__init__.py

1270 lines
60 KiB
Python
Raw Normal View History

2019-09-23 11:42:40 +02:00
"""
2019-12-27 15:12:57 +01:00
Bitmessage commandline interface
2019-09-23 11:42:40 +02:00
"""
# Copyright (c) 2014 Luke Montalvo <lukemontalvo@gmail.com>
# This file adds a alternative commandline interface, feel free to critique and fork
2019-09-23 11:42:40 +02:00
#
# This has only been tested on Arch Linux and Linux Mint
# Dependencies:
# * from python2-pip
# * python2-pythondialog
# * dialog
2019-09-23 11:42:40 +02:00
import ConfigParser
import curses
import os
import sys
import time
2019-09-23 11:42:40 +02:00
from textwrap import fill
from threading import Timer
from dialog import Dialog
import l10n
2019-09-23 11:42:40 +02:00
import network.stats
import queues
import shared
import shutdown
2018-11-01 15:28:42 +01:00
2019-12-27 15:12:57 +01:00
from addresses import addBMIfNotPresent, decodeAddress
from bmconfigparser import BMConfigParser
from helper_ackPayload import genAckPayload
from helper_sql import sqlExecute, sqlQuery
from inventory import Inventory
# pylint: disable=global-statement
2019-12-27 15:12:57 +01:00
quit_ = False
menutab = 1
menu = ["Inbox", "Send", "Sent", "Your Identities", "Subscriptions", "Address Book", "Blacklist", "Network Status"]
naptime = 100
log = ""
logpad = None
inventorydata = 0
startuptime = time.time()
inbox = []
inboxcur = 0
sentbox = []
sentcur = 0
addresses = []
addrcur = 0
addrcopy = 0
subscriptions = []
subcur = 0
addrbook = []
abookcur = 0
blacklist = []
blackcur = 0
bwtype = "black"
BROADCAST_STR = "[Broadcast subscribers]"
2019-09-23 11:42:40 +02:00
2019-12-27 15:12:57 +01:00
class printLog(object):
2019-09-23 11:42:40 +02:00
"""Printing logs"""
2019-12-27 15:12:57 +01:00
# pylint: disable=no-self-use
2019-09-23 11:42:40 +02:00
def write(self, output):
2019-12-27 15:12:57 +01:00
"""Write logs"""
global log
log += output
2019-09-23 11:42:40 +02:00
def flush(self):
2019-12-27 15:12:57 +01:00
"""Flush logs"""
pass
2019-09-23 11:42:40 +02:00
2019-12-27 15:12:57 +01:00
class errLog(object):
2019-09-23 11:42:40 +02:00
"""Error logs"""
2019-12-27 15:12:57 +01:00
# pylint: disable=no-self-use
def write(self, output):
2019-12-27 15:12:57 +01:00
"""Write error logs"""
global log
2019-09-23 11:42:40 +02:00
log += "!" + output
def flush(self):
2019-12-27 15:12:57 +01:00
"""Flush error logs"""
pass
2019-09-23 11:42:40 +02:00
printlog = printLog()
errlog = errLog()
def cpair(a):
2019-09-23 11:42:40 +02:00
"""Color pairs"""
r = curses.color_pair(a)
2019-09-23 11:42:40 +02:00
if r not in range(1, curses.COLOR_PAIRS - 1):
r = curses.color_pair(0)
return r
2019-09-23 11:42:40 +02:00
def ascii(s):
2019-09-23 11:42:40 +02:00
"""ASCII values"""
r = ""
for c in s:
if ord(c) in range(128):
r += c
return r
2019-09-23 11:42:40 +02:00
def drawmenu(stdscr):
2019-09-23 11:42:40 +02:00
"""Creating menu's"""
menustr = " "
2019-09-23 11:42:40 +02:00
for i, _ in enumerate(menu):
if menutab == i + 1:
menustr = menustr[:-1]
menustr += "["
2019-09-23 11:42:40 +02:00
menustr += str(i + 1) + menu[i]
if menutab == i + 1:
menustr += "] "
2019-09-23 11:42:40 +02:00
elif i != len(menu) - 1:
menustr += " "
stdscr.addstr(2, 5, menustr, curses.A_UNDERLINE)
2019-09-23 11:42:40 +02:00
def set_background_title(d, title):
2019-09-23 11:42:40 +02:00
"""Setting background title"""
try:
d.set_background_title(title)
except:
d.add_persistent_args(("--backtitle", title))
2019-09-23 11:42:40 +02:00
def scrollbox(d, text, height=None, width=None):
2019-09-23 11:42:40 +02:00
"""Setting scroll box"""
try:
2019-09-23 11:42:40 +02:00
d.scrollbox(text, height, width, exit_label="Continue")
except:
2019-09-23 11:42:40 +02:00
d.msgbox(text, height or 0, width or 0, ok_label="Continue")
def resetlookups():
2019-09-23 11:42:40 +02:00
"""Reset the Inventory Lookups"""
2019-12-27 15:12:57 +01:00
global inventorydata
inventorydata = Inventory().numberOfInventoryLookupsPerformed
Inventory().numberOfInventoryLookupsPerformed = 0
Timer(1, resetlookups, ()).start()
2019-09-23 11:42:40 +02:00
2019-12-27 15:12:57 +01:00
def drawtab(stdscr):
2019-09-23 11:42:40 +02:00
"""Method for drawing different tabs"""
2019-12-27 15:12:57 +01:00
# pylint: disable=too-many-branches, too-many-statements
2019-09-23 11:42:40 +02:00
if menutab in range(1, len(menu) + 1):
if menutab == 1: # Inbox
stdscr.addstr(3, 5, "To", curses.A_BOLD)
stdscr.addstr(3, 40, "From", curses.A_BOLD)
stdscr.addstr(3, 80, "Subject", curses.A_BOLD)
stdscr.addstr(3, 120, "Time Received", curses.A_BOLD)
stdscr.hline(4, 5, '-', 121)
2019-09-23 11:42:40 +02:00
for i, item in enumerate(inbox[max(min(len(inbox) - curses.LINES + 6, inboxcur - 5), 0):]):
if 6 + i < curses.LINES:
a = 0
2019-09-23 11:42:40 +02:00
if i == inboxcur - max(min(len(inbox) - curses.LINES + 6, inboxcur - 5), 0):
# Highlight current address
a = a | curses.A_REVERSE
2019-09-23 11:42:40 +02:00
if item[7] is False: # If not read, highlight
a = a | curses.A_BOLD
2019-09-23 11:42:40 +02:00
stdscr.addstr(5 + i, 5, item[1][:34], a)
stdscr.addstr(5 + i, 40, item[3][:39], a)
stdscr.addstr(5 + i, 80, item[5][:39], a)
stdscr.addstr(5 + i, 120, item[6][:39], a)
elif menutab == 3: # Sent
stdscr.addstr(3, 5, "To", curses.A_BOLD)
stdscr.addstr(3, 40, "From", curses.A_BOLD)
stdscr.addstr(3, 80, "Subject", curses.A_BOLD)
stdscr.addstr(3, 120, "Status", curses.A_BOLD)
stdscr.hline(4, 5, '-', 121)
2019-09-23 11:42:40 +02:00
for i, item in enumerate(sentbox[max(min(len(sentbox) - curses.LINES + 6, sentcur - 5), 0):]):
if 6 + i < curses.LINES:
a = 0
2019-09-23 11:42:40 +02:00
if i == sentcur - max(min(len(sentbox) - curses.LINES + 6, sentcur - 5), 0):
# Highlight current address
a = a | curses.A_REVERSE
2019-09-23 11:42:40 +02:00
stdscr.addstr(5 + i, 5, item[0][:34], a)
stdscr.addstr(5 + i, 40, item[2][:39], a)
stdscr.addstr(5 + i, 80, item[4][:39], a)
stdscr.addstr(5 + i, 120, item[5][:39], a)
elif menutab == 2 or menutab == 4: # Send or Identities
stdscr.addstr(3, 5, "Label", curses.A_BOLD)
stdscr.addstr(3, 40, "Address", curses.A_BOLD)
stdscr.addstr(3, 80, "Stream", curses.A_BOLD)
stdscr.hline(4, 5, '-', 81)
2019-09-23 11:42:40 +02:00
for i, item in enumerate(addresses[max(min(len(addresses) - curses.LINES + 6, addrcur - 5), 0):]):
if 6 + i < curses.LINES:
a = 0
2019-09-23 11:42:40 +02:00
if i == addrcur - max(min(len(addresses) - curses.LINES + 6, addrcur - 5), 0):
# Highlight current address
a = a | curses.A_REVERSE
2019-09-23 11:42:40 +02:00
if item[1] and item[3] not in [8, 9]: # Embolden enabled, non-special addresses
a = a | curses.A_BOLD
2019-09-23 11:42:40 +02:00
stdscr.addstr(5 + i, 5, item[0][:34], a)
stdscr.addstr(5 + i, 40, item[2][:39], cpair(item[3]) | a)
stdscr.addstr(5 + i, 80, str(1)[:39], a)
elif menutab == 5: # Subscriptions
stdscr.addstr(3, 5, "Label", curses.A_BOLD)
stdscr.addstr(3, 80, "Address", curses.A_BOLD)
stdscr.addstr(3, 120, "Enabled", curses.A_BOLD)
stdscr.hline(4, 5, '-', 121)
2019-09-23 11:42:40 +02:00
for i, item in enumerate(subscriptions[max(min(len(subscriptions) - curses.LINES + 6, subcur - 5), 0):]):
if 6 + i < curses.LINES:
a = 0
2019-09-23 11:42:40 +02:00
if i == subcur - max(min(len(subscriptions) - curses.LINES + 6, subcur - 5), 0):
# Highlight current address
a = a | curses.A_REVERSE
2019-09-23 11:42:40 +02:00
if item[2]: # Embolden enabled subscriptions
a = a | curses.A_BOLD
2019-09-23 11:42:40 +02:00
stdscr.addstr(5 + i, 5, item[0][:74], a)
stdscr.addstr(5 + i, 80, item[1][:39], a)
stdscr.addstr(5 + i, 120, str(item[2]), a)
elif menutab == 6: # Address book
stdscr.addstr(3, 5, "Label", curses.A_BOLD)
stdscr.addstr(3, 40, "Address", curses.A_BOLD)
stdscr.hline(4, 5, '-', 41)
2019-09-23 11:42:40 +02:00
for i, item in enumerate(addrbook[max(min(len(addrbook) - curses.LINES + 6, abookcur - 5), 0):]):
if 6 + i < curses.LINES:
a = 0
2019-09-23 11:42:40 +02:00
if i == abookcur - max(min(len(addrbook) - curses.LINES + 6, abookcur - 5), 0):
# Highlight current address
a = a | curses.A_REVERSE
2019-09-23 11:42:40 +02:00
stdscr.addstr(5 + i, 5, item[0][:34], a)
stdscr.addstr(5 + i, 40, item[1][:39], a)
elif menutab == 7: # Blacklist
stdscr.addstr(3, 5, "Type: " + bwtype)
stdscr.addstr(4, 5, "Label", curses.A_BOLD)
stdscr.addstr(4, 80, "Address", curses.A_BOLD)
stdscr.addstr(4, 120, "Enabled", curses.A_BOLD)
stdscr.hline(5, 5, '-', 121)
2019-09-23 11:42:40 +02:00
for i, item in enumerate(blacklist[max(min(len(blacklist) - curses.LINES + 6, blackcur - 5), 0):]):
if 7 + i < curses.LINES:
a = 0
2019-09-23 11:42:40 +02:00
if i == blackcur - max(min(len(blacklist) - curses.LINES + 6, blackcur - 5), 0):
# Highlight current address
a = a | curses.A_REVERSE
2019-09-23 11:42:40 +02:00
if item[2]: # Embolden enabled subscriptions
a = a | curses.A_BOLD
2019-09-23 11:42:40 +02:00
stdscr.addstr(6 + i, 5, item[0][:74], a)
stdscr.addstr(6 + i, 80, item[1][:39], a)
stdscr.addstr(6 + i, 120, str(item[2]), a)
elif menutab == 8: # Network status
# Connection data
2018-11-01 15:28:42 +01:00
connected_hosts = network.stats.connectedHostsList()
stdscr.addstr(
4, 5, "Total Connections: " +
str(len(connected_hosts)).ljust(2)
)
stdscr.addstr(6, 6, "Stream #", curses.A_BOLD)
stdscr.addstr(6, 18, "Connections", curses.A_BOLD)
stdscr.hline(7, 6, '-', 23)
streamcount = []
2018-11-01 15:28:42 +01:00
for host, stream in connected_hosts:
if stream >= len(streamcount):
streamcount.append(1)
else:
streamcount[stream] += 1
for i, item in enumerate(streamcount):
if i < 4:
if i == 0:
2019-09-23 11:42:40 +02:00
stdscr.addstr(8 + i, 6, "?")
else:
2019-09-23 11:42:40 +02:00
stdscr.addstr(8 + i, 6, str(i))
stdscr.addstr(8 + i, 18, str(item).ljust(2))
# Uptime and processing data
2019-09-23 11:42:40 +02:00
stdscr.addstr(6, 35, "Since startup on " + l10n.formatTimestamp(startuptime, False))
stdscr.addstr(7, 40, "Processed " + str(
shared.numberOfMessagesProcessed).ljust(4) + " person-to-person messages.")
stdscr.addstr(8, 40, "Processed " + str(
shared.numberOfBroadcastsProcessed).ljust(4) + " broadcast messages.")
stdscr.addstr(9, 40, "Processed " + str(
shared.numberOfPubkeysProcessed).ljust(4) + " public keys.")
# Inventory data
2019-09-23 11:42:40 +02:00
stdscr.addstr(11, 35, "Inventory lookups per second: " + str(inventorydata).ljust(3))
# Log
stdscr.addstr(13, 6, "Log", curses.A_BOLD)
n = log.count('\n')
if n > 0:
2019-12-27 15:12:57 +01:00
lg = log.split('\n')
if n > 512:
2019-12-27 15:12:57 +01:00
del lg[:(n - 256)]
logpad.erase()
2019-12-27 15:12:57 +01:00
n = len(lg)
for i, item in enumerate(lg):
a = 0
2019-09-23 11:42:40 +02:00
if item and item[0] == '!':
a = curses.color_pair(1)
item = item[1:]
logpad.addstr(i, 0, item, a)
2019-09-23 11:42:40 +02:00
logpad.refresh(n - curses.LINES + 2, 0, 14, 6, curses.LINES - 2, curses.COLS - 7)
stdscr.refresh()
2019-09-23 11:42:40 +02:00
def redraw(stdscr):
2019-09-23 11:42:40 +02:00
"""Redraw menu"""
stdscr.erase()
stdscr.border()
drawmenu(stdscr)
stdscr.refresh()
2019-09-23 11:42:40 +02:00
def dialogreset(stdscr):
2019-09-23 11:42:40 +02:00
"""Resetting dialogue"""
stdscr.clear()
stdscr.keypad(1)
curses.curs_set(0)
2019-09-23 11:42:40 +02:00
# pylint: disable=too-many-branches, too-many-statements
def handlech(c, stdscr):
2019-12-27 15:12:57 +01:00
"""Handle character given on the command-line interface"""
# pylint: disable=redefined-outer-name, too-many-nested-blocks, too-many-locals
if c != curses.ERR:
global inboxcur, addrcur, sentcur, subcur, abookcur, blackcur
2019-09-23 11:42:40 +02:00
if c in range(256):
if chr(c) in '12345678':
global menutab
menutab = int(chr(c))
elif chr(c) == 'q':
2019-12-27 15:12:57 +01:00
global quit_
quit_ = True
elif chr(c) == '\n':
curses.curs_set(1)
d = Dialog(dialog="dialog")
if menutab == 1:
set_background_title(d, "Inbox Message Dialog Box")
2019-09-23 11:42:40 +02:00
r, t = d.menu(
"Do what with \"" + inbox[inboxcur][5] + "\" from \"" + inbox[inboxcur][3] + "\"?",
choices=[
("1", "View message"),
("2", "Mark message as unread"),
("3", "Reply"),
("4", "Add sender to Address Book"),
("5", "Save message as text file"),
("6", "Move to trash")])
if r == d.DIALOG_OK:
2019-09-23 11:42:40 +02:00
if t == "1": # View
set_background_title(
d,
"\"" +
inbox[inboxcur][5] +
"\" from \"" +
inbox[inboxcur][3] +
"\" to \"" +
inbox[inboxcur][1] +
"\"")
data = "" # pyint: disable=redefined-outer-name
ret = sqlQuery("SELECT message FROM inbox WHERE msgid=?", inbox[inboxcur][0])
if ret != []:
for row in ret:
data, = row
data = shared.fixPotentiallyInvalidUTF8Data(data)
msg = ""
for i, item in enumerate(data.split("\n")):
2019-09-23 11:42:40 +02:00
msg += fill(item, replace_whitespace=False) + "\n"
scrollbox(d, unicode(ascii(msg)), 30, 80)
sqlExecute("UPDATE inbox SET read=1 WHERE msgid=?", inbox[inboxcur][0])
inbox[inboxcur][7] = 1
else:
scrollbox(d, unicode("Could not fetch message."))
2019-12-27 15:12:57 +01:00
elif t == "2": # Mark unread
sqlExecute("UPDATE inbox SET read=0 WHERE msgid=?", inbox[inboxcur][0])
inbox[inboxcur][7] = 0
2019-12-27 15:12:57 +01:00
elif t == "3": # Reply
curses.curs_set(1)
m = inbox[inboxcur]
fromaddr = m[4]
ischan = False
for i, item in enumerate(addresses):
if fromaddr == item[2] and item[3] != 0:
ischan = True
break
2019-12-27 15:12:57 +01:00
if not addresses[i][1]: # pylint: disable=undefined-loop-variable
2019-09-23 11:42:40 +02:00
scrollbox(d, unicode(
"Sending address disabled, please either enable it"
"or choose a different address."))
return
toaddr = m[2]
if ischan:
toaddr = fromaddr
2019-09-23 11:42:40 +02:00
subject = m[5]
if not m[5][:4] == "Re: ":
2019-09-23 11:42:40 +02:00
subject = "Re: " + m[5]
body = ""
ret = sqlQuery("SELECT message FROM inbox WHERE msgid=?", m[0])
if ret != []:
body = "\n\n------------------------------------------------------\n"
for row in ret:
body, = row
2019-09-23 11:42:40 +02:00
sendMessage(fromaddr, toaddr, ischan, subject, body, True)
dialogreset(stdscr)
2019-12-27 15:12:57 +01:00
elif t == "4": # Add to Address Book
addr = inbox[inboxcur][4]
2019-09-23 11:42:40 +02:00
if addr not in [item[1] for i, item in enumerate(addrbook)]:
r, t = d.inputbox("Label for address \"" + addr + "\"")
if r == d.DIALOG_OK:
label = t
sqlExecute("INSERT INTO addressbook VALUES (?,?)", label, addr)
# Prepend entry
addrbook.reverse()
addrbook.append([label, addr])
addrbook.reverse()
else:
scrollbox(d, unicode("The selected address is already in the Address Book."))
2019-12-27 15:12:57 +01:00
elif t == "5": # Save message
2019-09-23 11:42:40 +02:00
set_background_title(d, "Save \"" + inbox[inboxcur][5] + "\" as text file")
r, t = d.inputbox("Filename", init=inbox[inboxcur][5] + ".txt")
if r == d.DIALOG_OK:
msg = ""
ret = sqlQuery("SELECT message FROM inbox WHERE msgid=?", inbox[inboxcur][0])
if ret != []:
for row in ret:
msg, = row
2019-12-27 15:12:57 +01:00
fh = open(t, "a") # Open in append mode just in case
fh.write(msg)
fh.close()
else:
scrollbox(d, unicode("Could not fetch message."))
2019-12-27 15:12:57 +01:00
elif t == "6": # Move to trash
sqlExecute("UPDATE inbox SET folder='trash' WHERE msgid=?", inbox[inboxcur][0])
del inbox[inboxcur]
2019-09-23 11:42:40 +02:00
scrollbox(d, unicode(
"Message moved to trash. There is no interface to view your trash,"
" \nbut the message is still on disk if you are desperate to recover it."))
elif menutab == 2:
a = ""
2019-12-27 15:12:57 +01:00
if addresses[addrcur][3] != 0: # if current address is a chan
a = addresses[addrcur][2]
sendMessage(addresses[addrcur][2], a)
elif menutab == 3:
set_background_title(d, "Sent Messages Dialog Box")
2019-09-23 11:42:40 +02:00
r, t = d.menu(
"Do what with \"" + sentbox[sentcur][4] + "\" to \"" + sentbox[sentcur][0] + "\"?",
choices=[
("1", "View message"),
("2", "Move to trash")])
if r == d.DIALOG_OK:
2019-09-23 11:42:40 +02:00
if t == "1": # View
set_background_title(
d,
"\"" +
sentbox[sentcur][4] +
"\" from \"" +
sentbox[sentcur][3] +
"\" to \"" +
sentbox[sentcur][1] +
"\"")
data = ""
2019-09-23 11:42:40 +02:00
ret = sqlQuery(
"SELECT message FROM sent WHERE subject=? AND ackdata=?",
sentbox[sentcur][4],
sentbox[sentcur][6])
if ret != []:
for row in ret:
data, = row
data = shared.fixPotentiallyInvalidUTF8Data(data)
msg = ""
for i, item in enumerate(data.split("\n")):
2019-09-23 11:42:40 +02:00
msg += fill(item, replace_whitespace=False) + "\n"
scrollbox(d, unicode(ascii(msg)), 30, 80)
else:
scrollbox(d, unicode("Could not fetch message."))
2019-12-27 15:12:57 +01:00
elif t == "2": # Move to trash
2019-09-23 11:42:40 +02:00
sqlExecute(
"UPDATE sent SET folder='trash' WHERE subject=? AND ackdata=?",
sentbox[sentcur][4],
sentbox[sentcur][6])
del sentbox[sentcur]
2019-09-23 11:42:40 +02:00
scrollbox(d, unicode(
"Message moved to trash. There is no interface to view your trash"
" \nbut the message is still on disk if you are desperate to recover it."))
elif menutab == 4:
set_background_title(d, "Your Identities Dialog Box")
if len(addresses) <= addrcur:
2019-09-23 11:42:40 +02:00
r, t = d.menu(
"Do what with addresses?",
choices=[
("1", "Create new address")])
else:
2019-09-23 11:42:40 +02:00
r, t = d.menu(
"Do what with \"" + addresses[addrcur][0] + "\" : \"" + addresses[addrcur][2] + "\"?",
choices=[
("1", "Create new address"),
("2", "Send a message from this address"),
("3", "Rename"),
("4", "Enable"),
("5", "Disable"),
("6", "Delete"),
("7", "Special address behavior")])
if r == d.DIALOG_OK:
2019-12-27 15:12:57 +01:00
if t == "1": # Create new address
set_background_title(d, "Create new address")
2019-09-23 11:42:40 +02:00
scrollbox(
d, unicode(
"Here you may generate as many addresses as you like.\n"
"Indeed, creating and abandoning addresses is encouraged.\n"
"Deterministic addresses have several pros and cons:\n"
"\nPros:\n"
" * You can recreate your addresses on any computer from memory\n"
" * You need not worry about backing up your keys.dat file as long as you"
" \n can remember your passphrase\n"
"Cons:\n"
" * You must remember (or write down) your passphrase in order to recreate"
" \n your keys if they are lost\n"
" * You must also remember the address version and stream numbers\n"
" * If you choose a weak passphrase someone may be able to brute-force it"
" \n and then send and receive messages as you"))
r, t = d.menu(
"Choose an address generation technique",
choices=[
("1", "Use a random number generator"),
("2", "Use a passphrase")])
if r == d.DIALOG_OK:
if t == "1":
set_background_title(d, "Randomly generate address")
r, t = d.inputbox("Label (not shown to anyone except you)")
label = ""
2019-09-23 11:42:40 +02:00
if r == d.DIALOG_OK and t:
label = t
2019-09-23 11:42:40 +02:00
r, t = d.menu(
"Choose a stream",
choices=[("1", "Use the most available stream"),
("", "(Best if this is the first of many addresses you will create)"),
("2", "Use the same stream as an existing address"),
("", "(Saves you some bandwidth and processing power)")])
if r == d.DIALOG_OK:
if t == "1":
stream = 1
elif t == "2":
addrs = []
for i, item in enumerate(addresses):
addrs.append([str(i), item[2]])
r, t = d.menu("Choose an existing address's stream", choices=addrs)
if r == d.DIALOG_OK:
stream = decodeAddress(addrs[int(t)][1])[2]
shorten = False
2019-09-23 11:42:40 +02:00
r, t = d.checklist(
"Miscellaneous options",
choices=[(
"1",
"Spend time shortening the address",
1 if shorten else 0)])
if r == d.DIALOG_OK and "1" in t:
shorten = True
2019-09-23 11:42:40 +02:00
queues.addressGeneratorQueue.put((
"createRandomAddress",
4,
stream,
label,