mirror of
https://github.com/yzernik/squeaknode.git
synced 2026-08-13 12:33:25 +02:00
Run codeformat (#184)
This commit is contained in:
parent
9a7d034771
commit
a3cd29f430
12 changed files with 219 additions and 242 deletions
|
|
@ -1,21 +1,14 @@
|
|||
import pytest
|
||||
|
||||
import grpc
|
||||
|
||||
import pytest
|
||||
from squeak.params import SelectParams
|
||||
|
||||
from proto import lnd_pb2 as ln
|
||||
from proto import lnd_pb2_grpc as lnrpc
|
||||
from proto import (
|
||||
squeak_admin_pb2,
|
||||
squeak_admin_pb2_grpc,
|
||||
squeak_server_pb2,
|
||||
squeak_server_pb2_grpc,
|
||||
)
|
||||
|
||||
from tests.util import generate_signing_key
|
||||
from tests.util import get_address
|
||||
from tests.util import load_lightning_client
|
||||
from tests.util import generate_signing_key, get_address, load_lightning_client
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
|
|
@ -23,24 +16,24 @@ def select_mainnet_params():
|
|||
# Set the network to simnet
|
||||
SelectParams("simnet")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def server_stub():
|
||||
with grpc.insecure_channel(
|
||||
"sqkserver:8774"
|
||||
) as server_channel:
|
||||
with grpc.insecure_channel("sqkserver:8774") as server_channel:
|
||||
yield squeak_server_pb2_grpc.SqueakServerStub(server_channel)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def admin_stub():
|
||||
with grpc.insecure_channel(
|
||||
"sqkserver:8994"
|
||||
) as admin_channel:
|
||||
with grpc.insecure_channel("sqkserver:8994") as admin_channel:
|
||||
yield squeak_admin_pb2_grpc.SqueakAdminStub(admin_channel)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def lightning_client():
|
||||
return load_lightning_client()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def whitelisted_signing_key(server_stub, admin_stub):
|
||||
# Create a signing key
|
||||
|
|
@ -51,8 +44,7 @@ def whitelisted_signing_key(server_stub, admin_stub):
|
|||
profile_address = get_address(signing_key)
|
||||
create_contact_profile_response = admin_stub.CreateContactProfile(
|
||||
squeak_admin_pb2.CreateContactProfileRequest(
|
||||
profile_name=profile_name,
|
||||
address=profile_address,
|
||||
profile_name=profile_name, address=profile_address,
|
||||
)
|
||||
)
|
||||
contact_profile_id = create_contact_profile_response.profile_id
|
||||
|
|
@ -60,14 +52,14 @@ def whitelisted_signing_key(server_stub, admin_stub):
|
|||
# Set the profile to be whitelisted
|
||||
admin_stub.SetSqueakProfileWhitelisted(
|
||||
squeak_admin_pb2.SetSqueakProfileWhitelistedRequest(
|
||||
profile_id=contact_profile_id,
|
||||
whitelisted=True,
|
||||
profile_id=contact_profile_id, whitelisted=True,
|
||||
)
|
||||
)
|
||||
|
||||
# Yield the signing key
|
||||
yield signing_key
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def nonwhitelisted_signing_key(server_stub, admin_stub):
|
||||
# Create a signing key
|
||||
|
|
@ -76,6 +68,7 @@ def nonwhitelisted_signing_key(server_stub, admin_stub):
|
|||
# Yield the signing key
|
||||
yield signing_key
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def signing_profile_id(server_stub, admin_stub):
|
||||
# Create a new signing profile
|
||||
|
|
@ -86,6 +79,7 @@ def signing_profile_id(server_stub, admin_stub):
|
|||
profile_id = create_signing_profile_response.profile_id
|
||||
yield profile_id
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def contact_profile_id(server_stub, admin_stub):
|
||||
# Create a new contact profile
|
||||
|
|
@ -94,13 +88,13 @@ def contact_profile_id(server_stub, admin_stub):
|
|||
contact_address = get_address(contact_signing_key)
|
||||
create_contact_profile_response = admin_stub.CreateContactProfile(
|
||||
squeak_admin_pb2.CreateContactProfileRequest(
|
||||
profile_name=contact_name,
|
||||
address=contact_address,
|
||||
profile_name=contact_name, address=contact_address,
|
||||
)
|
||||
)
|
||||
contact_profile_id = create_contact_profile_response.profile_id
|
||||
yield contact_profile_id
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def saved_squeak_hash(server_stub, admin_stub, signing_profile_id):
|
||||
# Create a new squeak using the new profile
|
||||
|
|
|
|||
|
|
@ -1,41 +1,40 @@
|
|||
from __future__ import print_function
|
||||
|
||||
import pytest
|
||||
import logging
|
||||
import time
|
||||
|
||||
import grpc
|
||||
from lnd_lightning_client import LNDLightningClient
|
||||
from squeak.core import HASH_LENGTH, CheckSqueak, CSqueak, MakeSqueakFromStr
|
||||
from squeak.core.encryption import CEncryptedDecryptionKey, generate_data_key
|
||||
from squeak.core.signing import CSigningKey, CSqueakAddress
|
||||
import pytest
|
||||
from squeak.core import CheckSqueak
|
||||
from squeak.core.encryption import CEncryptedDecryptionKey
|
||||
|
||||
from proto import lnd_pb2 as ln
|
||||
from proto import lnd_pb2_grpc as lnrpc
|
||||
from proto import (
|
||||
squeak_admin_pb2,
|
||||
squeak_admin_pb2_grpc,
|
||||
squeak_server_pb2,
|
||||
squeak_server_pb2_grpc,
|
||||
)
|
||||
|
||||
from tests.util import build_squeak_msg
|
||||
from tests.util import squeak_from_msg
|
||||
from tests.util import generate_signing_key
|
||||
from tests.util import generate_challenge_proof
|
||||
from tests.util import get_challenge
|
||||
from tests.util import get_address
|
||||
from tests.util import get_latest_block_info
|
||||
from tests.util import make_squeak
|
||||
from tests.util import get_hash
|
||||
from tests.util import bxor
|
||||
from tests.util import string_to_hex
|
||||
from tests.util import (
|
||||
build_squeak_msg,
|
||||
generate_challenge_proof,
|
||||
generate_signing_key,
|
||||
get_address,
|
||||
get_challenge,
|
||||
get_hash,
|
||||
get_latest_block_info,
|
||||
make_squeak,
|
||||
squeak_from_msg,
|
||||
string_to_hex,
|
||||
)
|
||||
|
||||
|
||||
def test_post_squeak(server_stub, admin_stub, lightning_client, whitelisted_signing_key):
|
||||
def test_post_squeak(
|
||||
server_stub, admin_stub, lightning_client, whitelisted_signing_key
|
||||
):
|
||||
# Post a squeak with a direct request to the server
|
||||
block_height, block_hash = get_latest_block_info(lightning_client)
|
||||
squeak = make_squeak(whitelisted_signing_key, "hello from itest!", block_hash, block_height)
|
||||
squeak = make_squeak(
|
||||
whitelisted_signing_key, "hello from itest!", block_hash, block_height
|
||||
)
|
||||
squeak_hash = get_hash(squeak)
|
||||
|
||||
squeak_msg = build_squeak_msg(squeak)
|
||||
|
|
@ -55,17 +54,21 @@ def test_post_squeak(server_stub, admin_stub, lightning_client, whitelisted_sign
|
|||
|
||||
assert get_hash(get_response_squeak) == get_hash(squeak)
|
||||
|
||||
def test_post_squeak_not_whitelisted(server_stub, admin_stub, lightning_client, nonwhitelisted_signing_key):
|
||||
|
||||
def test_post_squeak_not_whitelisted(
|
||||
server_stub, admin_stub, lightning_client, nonwhitelisted_signing_key
|
||||
):
|
||||
# Post a squeak with a direct request to the server
|
||||
block_height, block_hash = get_latest_block_info(lightning_client)
|
||||
squeak = make_squeak(nonwhitelisted_signing_key, "hello from itest!", block_hash, block_height)
|
||||
squeak = make_squeak(
|
||||
nonwhitelisted_signing_key, "hello from itest!", block_hash, block_height
|
||||
)
|
||||
squeak_hash = get_hash(squeak)
|
||||
|
||||
squeak_msg = build_squeak_msg(squeak)
|
||||
with pytest.raises(Exception):
|
||||
server_stub.PostSqueak(
|
||||
squeak_server_pb2.PostSqueakRequest(squeak=squeak_msg)
|
||||
)
|
||||
server_stub.PostSqueak(squeak_server_pb2.PostSqueakRequest(squeak=squeak_msg))
|
||||
|
||||
|
||||
def test_lookup_squeaks(server_stub, admin_stub, signing_profile_id, saved_squeak_hash):
|
||||
# Get the squeak profile
|
||||
|
|
@ -78,14 +81,13 @@ def test_lookup_squeaks(server_stub, admin_stub, signing_profile_id, saved_squea
|
|||
addresses = [squeak_profile_address]
|
||||
lookup_response = server_stub.LookupSqueaks(
|
||||
squeak_server_pb2.LookupSqueaksRequest(
|
||||
addresses=addresses,
|
||||
min_block=0,
|
||||
max_block=99999999,
|
||||
addresses=addresses, min_block=0, max_block=99999999,
|
||||
)
|
||||
)
|
||||
assert len(lookup_response.hashes) == 1
|
||||
assert saved_squeak_hash in set(lookup_response.hashes)
|
||||
|
||||
|
||||
def test_lookup_squeaks_empty_result(server_stub, admin_stub):
|
||||
signing_key = generate_signing_key()
|
||||
address = get_address(signing_key)
|
||||
|
|
@ -94,18 +96,15 @@ def test_lookup_squeaks_empty_result(server_stub, admin_stub):
|
|||
addresses = [address]
|
||||
lookup_response = server_stub.LookupSqueaks(
|
||||
squeak_server_pb2.LookupSqueaksRequest(
|
||||
addresses=addresses,
|
||||
min_block=0,
|
||||
max_block=99999999,
|
||||
addresses=addresses, min_block=0, max_block=99999999,
|
||||
)
|
||||
)
|
||||
assert len(lookup_response.hashes) == 0
|
||||
|
||||
|
||||
def test_sell_squeak(server_stub, admin_stub, lightning_client, saved_squeak_hash):
|
||||
# Check the server balance
|
||||
get_balance_response = admin_stub.LndWalletBalance(
|
||||
ln.WalletBalanceRequest()
|
||||
)
|
||||
get_balance_response = admin_stub.LndWalletBalance(ln.WalletBalanceRequest())
|
||||
initial_server_balance = get_balance_response.total_balance
|
||||
|
||||
# Get the squeak from the server
|
||||
|
|
@ -151,9 +150,7 @@ def test_sell_squeak(server_stub, admin_stub, lightning_client, saved_squeak_has
|
|||
list_channels_response = lightning_client.list_channels()
|
||||
|
||||
# Pay the invoice
|
||||
payment = lightning_client.pay_invoice_sync(
|
||||
buy_response.offer.payment_request
|
||||
)
|
||||
payment = lightning_client.pay_invoice_sync(buy_response.offer.payment_request)
|
||||
preimage = payment.payment_preimage
|
||||
|
||||
# Verify with the payment preimage and decryption key ciphertext
|
||||
|
|
@ -178,12 +175,11 @@ def test_sell_squeak(server_stub, admin_stub, lightning_client, saved_squeak_has
|
|||
break
|
||||
|
||||
# Check the server balance
|
||||
get_balance_response = admin_stub.LndWalletBalance(
|
||||
ln.WalletBalanceRequest()
|
||||
)
|
||||
get_balance_response = admin_stub.LndWalletBalance(ln.WalletBalanceRequest())
|
||||
final_server_balance = get_balance_response.total_balance
|
||||
assert final_server_balance - initial_server_balance == 1000
|
||||
|
||||
|
||||
def test_make_squeak(server_stub, admin_stub, signing_profile_id):
|
||||
# Create a new squeak using the new profile
|
||||
make_squeak_content = "Hello from the profile on the server!"
|
||||
|
|
@ -193,7 +189,7 @@ def test_make_squeak(server_stub, admin_stub, signing_profile_id):
|
|||
)
|
||||
)
|
||||
make_squeak_hash = make_squeak_response.squeak_hash
|
||||
assert len(make_squeak_hash) == 32*2
|
||||
assert len(make_squeak_hash) == 32 * 2
|
||||
|
||||
# Get the new squeak from the server
|
||||
get_squeak_response = server_stub.GetSqueak(
|
||||
|
|
@ -221,18 +217,19 @@ def test_make_squeak(server_stub, admin_stub, signing_profile_id):
|
|||
|
||||
# Get all squeak displays for the known address
|
||||
get_address_squeak_display_response = admin_stub.GetAddressSqueakDisplays(
|
||||
squeak_admin_pb2.GetAddressSqueakDisplaysRequest(
|
||||
address=squeak_profile_address
|
||||
)
|
||||
squeak_admin_pb2.GetAddressSqueakDisplaysRequest(address=squeak_profile_address)
|
||||
)
|
||||
assert (
|
||||
len(get_address_squeak_display_response.squeak_display_entries) == 1
|
||||
)
|
||||
for squeak_display_entry in get_address_squeak_display_response.squeak_display_entries:
|
||||
assert len(get_address_squeak_display_response.squeak_display_entries) == 1
|
||||
for (
|
||||
squeak_display_entry
|
||||
) in get_address_squeak_display_response.squeak_display_entries:
|
||||
assert squeak_display_entry.author_name == squeak_profile_name
|
||||
assert squeak_display_entry.author_address == squeak_profile_address
|
||||
|
||||
def test_make_reply_squeak(server_stub, admin_stub, saved_squeak_hash, signing_profile_id):
|
||||
|
||||
def test_make_reply_squeak(
|
||||
server_stub, admin_stub, saved_squeak_hash, signing_profile_id
|
||||
):
|
||||
# Make another squeak as a reply
|
||||
reply_1_squeak_response = admin_stub.MakeSqueak(
|
||||
squeak_admin_pb2.MakeSqueakRequest(
|
||||
|
|
@ -255,15 +252,15 @@ def test_make_reply_squeak(server_stub, admin_stub, saved_squeak_hash, signing_p
|
|||
|
||||
# Get the squeak and check that the reply field is correct
|
||||
get_reply_squeak_display_response = admin_stub.GetSqueakDisplay(
|
||||
squeak_admin_pb2.GetSqueakDisplayRequest(
|
||||
squeak_hash=reply_2_squeak_hash,
|
||||
)
|
||||
squeak_admin_pb2.GetSqueakDisplayRequest(squeak_hash=reply_2_squeak_hash,)
|
||||
)
|
||||
assert (
|
||||
get_reply_squeak_display_response.squeak_display_entry.squeak_hash == reply_2_squeak_hash
|
||||
get_reply_squeak_display_response.squeak_display_entry.squeak_hash
|
||||
== reply_2_squeak_hash
|
||||
)
|
||||
assert (
|
||||
get_reply_squeak_display_response.squeak_display_entry.reply_to == reply_1_squeak_hash
|
||||
get_reply_squeak_display_response.squeak_display_entry.reply_to
|
||||
== reply_1_squeak_hash
|
||||
)
|
||||
|
||||
# Get the ancestors of the latest reply squeak
|
||||
|
|
@ -272,9 +269,8 @@ def test_make_reply_squeak(server_stub, admin_stub, saved_squeak_hash, signing_p
|
|||
squeak_hash=reply_2_squeak_hash,
|
||||
)
|
||||
)
|
||||
assert (
|
||||
len(get_ancestors_response.squeak_display_entries) == 3
|
||||
)
|
||||
assert len(get_ancestors_response.squeak_display_entries) == 3
|
||||
|
||||
|
||||
def test_rate_limit(server_stub, admin_stub, signing_profile_id):
|
||||
# Make 10 squeak
|
||||
|
|
@ -289,6 +285,7 @@ def test_rate_limit(server_stub, admin_stub, signing_profile_id):
|
|||
make_extra_squeak_exception = e
|
||||
assert make_extra_squeak_exception is not None
|
||||
|
||||
|
||||
def test_make_signing_profile(server_stub, admin_stub):
|
||||
# Create a new signing profile
|
||||
profile_name = "test_signing_profile_name"
|
||||
|
|
@ -320,9 +317,8 @@ def test_make_signing_profile(server_stub, admin_stub):
|
|||
address=squeak_profile_address
|
||||
)
|
||||
)
|
||||
assert (
|
||||
get_profile_by_address_response.squeak_profile.profile_name == profile_name
|
||||
)
|
||||
assert get_profile_by_address_response.squeak_profile.profile_name == profile_name
|
||||
|
||||
|
||||
def test_make_contact_profile(server_stub, admin_stub):
|
||||
# Create a new contact profile
|
||||
|
|
@ -331,8 +327,7 @@ def test_make_contact_profile(server_stub, admin_stub):
|
|||
contact_address = get_address(contact_signing_key)
|
||||
create_contact_profile_response = admin_stub.CreateContactProfile(
|
||||
squeak_admin_pb2.CreateContactProfileRequest(
|
||||
profile_name=contact_name,
|
||||
address=contact_address,
|
||||
profile_name=contact_name, address=contact_address,
|
||||
)
|
||||
)
|
||||
contact_profile_id = create_contact_profile_response.profile_id
|
||||
|
|
@ -347,6 +342,7 @@ def test_make_contact_profile(server_stub, admin_stub):
|
|||
]
|
||||
assert contact_name in contact_profile_names
|
||||
|
||||
|
||||
def test_set_profile_whitelisted(server_stub, admin_stub, contact_profile_id):
|
||||
# Get the existing profile
|
||||
get_squeak_profile_response = admin_stub.GetSqueakProfile(
|
||||
|
|
@ -357,8 +353,7 @@ def test_set_profile_whitelisted(server_stub, admin_stub, contact_profile_id):
|
|||
# Set the profile to be whitelisted
|
||||
admin_stub.SetSqueakProfileWhitelisted(
|
||||
squeak_admin_pb2.SetSqueakProfileWhitelistedRequest(
|
||||
profile_id=contact_profile_id,
|
||||
whitelisted=True,
|
||||
profile_id=contact_profile_id, whitelisted=True,
|
||||
)
|
||||
)
|
||||
|
||||
|
|
@ -368,6 +363,7 @@ def test_set_profile_whitelisted(server_stub, admin_stub, contact_profile_id):
|
|||
)
|
||||
assert get_squeak_profile_response.squeak_profile.whitelisted == True
|
||||
|
||||
|
||||
def test_set_profile_following(server_stub, admin_stub, contact_profile_id):
|
||||
# Get the existing profile
|
||||
get_squeak_profile_response = admin_stub.GetSqueakProfile(
|
||||
|
|
@ -378,8 +374,7 @@ def test_set_profile_following(server_stub, admin_stub, contact_profile_id):
|
|||
# Set the profile to be following
|
||||
admin_stub.SetSqueakProfileFollowing(
|
||||
squeak_admin_pb2.SetSqueakProfileFollowingRequest(
|
||||
profile_id=contact_profile_id,
|
||||
following=True,
|
||||
profile_id=contact_profile_id, following=True,
|
||||
)
|
||||
)
|
||||
|
||||
|
|
@ -389,6 +384,7 @@ def test_set_profile_following(server_stub, admin_stub, contact_profile_id):
|
|||
)
|
||||
assert get_squeak_profile_response.squeak_profile.following == True
|
||||
|
||||
|
||||
def test_set_profile_sharing(server_stub, admin_stub, contact_profile_id):
|
||||
# Get the existing profile
|
||||
get_squeak_profile_response = admin_stub.GetSqueakProfile(
|
||||
|
|
@ -399,8 +395,7 @@ def test_set_profile_sharing(server_stub, admin_stub, contact_profile_id):
|
|||
# Set the profile to be sharing
|
||||
admin_stub.SetSqueakProfileSharing(
|
||||
squeak_admin_pb2.SetSqueakProfileSharingRequest(
|
||||
profile_id=contact_profile_id,
|
||||
sharing=True,
|
||||
profile_id=contact_profile_id, sharing=True,
|
||||
)
|
||||
)
|
||||
|
||||
|
|
@ -410,12 +405,14 @@ def test_set_profile_sharing(server_stub, admin_stub, contact_profile_id):
|
|||
)
|
||||
assert get_squeak_profile_response.squeak_profile.sharing == True
|
||||
|
||||
def test_get_following_squeaks(server_stub, admin_stub, saved_squeak_hash, signing_profile_id):
|
||||
|
||||
def test_get_following_squeaks(
|
||||
server_stub, admin_stub, saved_squeak_hash, signing_profile_id
|
||||
):
|
||||
# Set the profile to be following
|
||||
admin_stub.SetSqueakProfileFollowing(
|
||||
squeak_admin_pb2.SetSqueakProfileFollowingRequest(
|
||||
profile_id=signing_profile_id,
|
||||
following=True,
|
||||
profile_id=signing_profile_id, following=True,
|
||||
)
|
||||
)
|
||||
|
||||
|
|
@ -423,45 +420,38 @@ def test_get_following_squeaks(server_stub, admin_stub, saved_squeak_hash, signi
|
|||
get_followed_squeak_display_response = admin_stub.GetFollowedSqueakDisplays(
|
||||
squeak_admin_pb2.GetFollowedSqueakDisplaysRequest()
|
||||
)
|
||||
assert (
|
||||
len(get_followed_squeak_display_response.squeak_display_entries) == 1
|
||||
)
|
||||
for squeak_display_entry in get_followed_squeak_display_response.squeak_display_entries:
|
||||
assert len(get_followed_squeak_display_response.squeak_display_entries) == 1
|
||||
for (
|
||||
squeak_display_entry
|
||||
) in get_followed_squeak_display_response.squeak_display_entries:
|
||||
# TODO: check the profile id of the squeak display entry
|
||||
# assert squeak_display_entry.profile_id == signing_profile_id
|
||||
pass
|
||||
|
||||
|
||||
def test_delete_squeak(server_stub, admin_stub, saved_squeak_hash):
|
||||
# Delete the squeak
|
||||
admin_stub.DeleteSqueak(
|
||||
squeak_admin_pb2.DeleteSqueakRequest(
|
||||
squeak_hash=saved_squeak_hash.hex()
|
||||
)
|
||||
squeak_admin_pb2.DeleteSqueakRequest(squeak_hash=saved_squeak_hash.hex())
|
||||
)
|
||||
|
||||
# Try to get the squeak and fail
|
||||
with pytest.raises(Exception):
|
||||
get_response = server_stub.GetSqueak(
|
||||
squeak_server_pb2.GetSqueakRequest(
|
||||
hash=saved_squeak_hash
|
||||
)
|
||||
squeak_server_pb2.GetSqueakRequest(hash=saved_squeak_hash)
|
||||
)
|
||||
|
||||
|
||||
def test_add_server(server_stub, admin_stub):
|
||||
# Add a new server
|
||||
add_server_response = admin_stub.AddServer(
|
||||
squeak_admin_pb2.AddServerRequest(
|
||||
host="fake_host",
|
||||
port=1234,
|
||||
)
|
||||
squeak_admin_pb2.AddServerRequest(host="fake_host", port=1234,)
|
||||
)
|
||||
server_id = add_server_response.server_id
|
||||
|
||||
# Get the new server
|
||||
get_squeak_server_response = admin_stub.GetSqueakServer(
|
||||
squeak_admin_pb2.GetSqueakServerRequest(
|
||||
server_id=server_id
|
||||
)
|
||||
squeak_admin_pb2.GetSqueakServerRequest(server_id=server_id)
|
||||
)
|
||||
assert get_squeak_server_response.squeak_server.host == "fake_host"
|
||||
assert get_squeak_server_response.squeak_server.port == 1234
|
||||
|
|
|
|||
|
|
@ -1,14 +1,11 @@
|
|||
from __future__ import print_function
|
||||
|
||||
import logging
|
||||
import time
|
||||
|
||||
import grpc
|
||||
from lnd_lightning_client import LNDLightningClient
|
||||
from squeak.core import HASH_LENGTH, CheckSqueak, CSqueak, MakeSqueakFromStr
|
||||
from squeak.core.encryption import CEncryptedDecryptionKey, generate_data_key
|
||||
from squeak.core import HASH_LENGTH, CSqueak, MakeSqueakFromStr
|
||||
from squeak.core.encryption import generate_data_key
|
||||
from squeak.core.signing import CSigningKey, CSqueakAddress
|
||||
from squeak.params import SelectParams
|
||||
|
||||
from proto import lnd_pb2 as ln
|
||||
from proto import lnd_pb2_grpc as lnrpc
|
||||
|
|
|
|||
|
|
@ -31,8 +31,14 @@ class SqueakAdminServerHandler(object):
|
|||
return profile_id
|
||||
|
||||
def handle_create_contact_profile(self, profile_name, squeak_address):
|
||||
logger.info("Handle create contact profile with name: {}, address: {}".format(profile_name, squeak_address))
|
||||
profile_id = self.squeak_node.create_contact_profile(profile_name, squeak_address)
|
||||
logger.info(
|
||||
"Handle create contact profile with name: {}, address: {}".format(
|
||||
profile_name, squeak_address
|
||||
)
|
||||
)
|
||||
profile_id = self.squeak_node.create_contact_profile(
|
||||
profile_name, squeak_address
|
||||
)
|
||||
logger.info("New profile_id: {}".format(profile_id))
|
||||
return profile_id
|
||||
|
||||
|
|
@ -60,24 +66,27 @@ class SqueakAdminServerHandler(object):
|
|||
return squeak_profile
|
||||
|
||||
def handle_set_squeak_profile_whitelisted(self, profile_id, whitelisted):
|
||||
logger.info("Handle set squeak profile whitelisted with profile id: {}, whitelisted: {}".format(
|
||||
profile_id,
|
||||
whitelisted,
|
||||
))
|
||||
logger.info(
|
||||
"Handle set squeak profile whitelisted with profile id: {}, whitelisted: {}".format(
|
||||
profile_id, whitelisted,
|
||||
)
|
||||
)
|
||||
self.squeak_node.set_squeak_profile_whitelisted(profile_id, whitelisted)
|
||||
|
||||
def handle_set_squeak_profile_following(self, profile_id, following):
|
||||
logger.info("Handle set squeak profile following with profile id: {}, following: {}".format(
|
||||
profile_id,
|
||||
following,
|
||||
))
|
||||
logger.info(
|
||||
"Handle set squeak profile following with profile id: {}, following: {}".format(
|
||||
profile_id, following,
|
||||
)
|
||||
)
|
||||
self.squeak_node.set_squeak_profile_following(profile_id, following)
|
||||
|
||||
def handle_set_squeak_profile_sharing(self, profile_id, sharing):
|
||||
logger.info("Handle set squeak profile sharing with profile id: {}, sharing: {}".format(
|
||||
profile_id,
|
||||
sharing,
|
||||
))
|
||||
logger.info(
|
||||
"Handle set squeak profile sharing with profile id: {}, sharing: {}".format(
|
||||
profile_id, sharing,
|
||||
)
|
||||
)
|
||||
self.squeak_node.set_squeak_profile_sharing(profile_id, sharing)
|
||||
|
||||
def handle_make_squeak(self, profile_id, content_str, replyto_hash):
|
||||
|
|
@ -101,7 +110,9 @@ class SqueakAdminServerHandler(object):
|
|||
|
||||
def handle_get_followed_squeak_display_entries(self):
|
||||
logger.info("Handle get followed squeak display entries.")
|
||||
squeak_entries_with_profile = self.squeak_node.get_followed_squeak_entries_with_profile()
|
||||
squeak_entries_with_profile = (
|
||||
self.squeak_node.get_followed_squeak_entries_with_profile()
|
||||
)
|
||||
logger.info(
|
||||
"Got number of followed squeak entries: {}".format(
|
||||
len(squeak_entries_with_profile)
|
||||
|
|
@ -109,50 +120,46 @@ class SqueakAdminServerHandler(object):
|
|||
)
|
||||
return squeak_entries_with_profile
|
||||
|
||||
def handle_get_squeak_display_entries_for_address(self, address, min_block, max_block):
|
||||
def handle_get_squeak_display_entries_for_address(
|
||||
self, address, min_block, max_block
|
||||
):
|
||||
logger.info("Handle get squeak display entries for address: {}".format(address))
|
||||
squeak_entries_with_profile = self.squeak_node.get_squeak_entries_with_profile_for_address(
|
||||
address,
|
||||
min_block,
|
||||
max_block,
|
||||
address, min_block, max_block,
|
||||
)
|
||||
logger.info(
|
||||
"Got number of squeak entries: {}".format(
|
||||
"Got number of squeak entries: {}".format(len(squeak_entries_with_profile))
|
||||
)
|
||||
return squeak_entries_with_profile
|
||||
|
||||
def handle_get_ancestor_squeak_display_entries(self, squeak_hash_str):
|
||||
logger.info(
|
||||
"Handle get ancestor squeak display entries for squeak hash: {}".format(
|
||||
squeak_hash_str
|
||||
)
|
||||
)
|
||||
squeak_entries_with_profile = self.squeak_node.get_ancestor_squeak_entries_with_profile(
|
||||
squeak_hash_str,
|
||||
)
|
||||
logger.info(
|
||||
"Got number of ancestor squeak entries: {}".format(
|
||||
len(squeak_entries_with_profile)
|
||||
)
|
||||
)
|
||||
return squeak_entries_with_profile
|
||||
|
||||
def handle_get_ancestor_squeak_display_entries(self, squeak_hash_str):
|
||||
logger.info("Handle get ancestor squeak display entries for squeak hash: {}".format(squeak_hash_str))
|
||||
squeak_entries_with_profile = self.squeak_node.get_ancestor_squeak_entries_with_profile(
|
||||
squeak_hash_str,
|
||||
)
|
||||
logger.info("Got number of ancestor squeak entries: {}".format(len(squeak_entries_with_profile)))
|
||||
return squeak_entries_with_profile
|
||||
|
||||
def handle_delete_squeak(self, squeak_hash):
|
||||
logger.info("Handle delete squeak with hash: {}".format(squeak_hash))
|
||||
self.squeak_node.delete_squeak(
|
||||
squeak_hash
|
||||
)
|
||||
logger.info(
|
||||
"Deleted squeak entry with hash: {}".format(
|
||||
squeak_hash
|
||||
)
|
||||
)
|
||||
self.squeak_node.delete_squeak(squeak_hash)
|
||||
logger.info("Deleted squeak entry with hash: {}".format(squeak_hash))
|
||||
|
||||
def handle_add_server(self, server_name, server_host, server_port):
|
||||
logger.info("Handle add server with name: {}, host: {}, port: {}".format(
|
||||
server_name,
|
||||
server_host,
|
||||
server_port,
|
||||
))
|
||||
server_id = self.squeak_node.add_server(
|
||||
server_name,
|
||||
server_host,
|
||||
server_port,
|
||||
logger.info(
|
||||
"Handle add server with name: {}, host: {}, port: {}".format(
|
||||
server_name, server_host, server_port,
|
||||
)
|
||||
)
|
||||
server_id = self.squeak_node.add_server(server_name, server_host, server_port,)
|
||||
return server_id
|
||||
|
||||
def handle_get_squeak_server(self, server_id):
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
import sys
|
||||
|
||||
import logging
|
||||
import sys
|
||||
from concurrent import futures
|
||||
|
||||
import grpc
|
||||
|
||||
from proto import squeak_admin_pb2, squeak_admin_pb2_grpc
|
||||
|
||||
from squeakserver.server.util import get_hash, get_replyto
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
|
@ -21,7 +19,7 @@ class SqueakAdminServerServicer(squeak_admin_pb2_grpc.SqueakAdminServicer):
|
|||
self.handler = handler
|
||||
|
||||
def SayHello(self, request, context):
|
||||
return squeak_admin_pb2.HelloReply(message='Hello, %s!' % request.name)
|
||||
return squeak_admin_pb2.HelloReply(message="Hello, %s!" % request.name)
|
||||
|
||||
def LndGetInfo(self, request, context):
|
||||
return self.handler.handle_lnd_get_info()
|
||||
|
|
@ -38,48 +36,35 @@ class SqueakAdminServerServicer(squeak_admin_pb2_grpc.SqueakAdminServicer):
|
|||
profile_name = request.profile_name
|
||||
squeak_address = request.address
|
||||
profile_id = self.handler.handle_create_contact_profile(
|
||||
profile_name,
|
||||
squeak_address,
|
||||
profile_name, squeak_address,
|
||||
)
|
||||
return squeak_admin_pb2.CreateContactProfileReply(profile_id=profile_id,)
|
||||
|
||||
def GetSigningProfiles(self, request, context):
|
||||
profiles = self.handler.handle_get_signing_profiles()
|
||||
profile_msgs = [
|
||||
self._squeak_profile_to_message(profile)
|
||||
for profile in
|
||||
profiles
|
||||
self._squeak_profile_to_message(profile) for profile in profiles
|
||||
]
|
||||
return squeak_admin_pb2.GetSigningProfilesReply(
|
||||
squeak_profiles=profile_msgs
|
||||
)
|
||||
return squeak_admin_pb2.GetSigningProfilesReply(squeak_profiles=profile_msgs)
|
||||
|
||||
def GetContactProfiles(self, request, context):
|
||||
profiles = self.handler.handle_get_contact_profiles()
|
||||
profile_msgs = [
|
||||
self._squeak_profile_to_message(profile)
|
||||
for profile in
|
||||
profiles
|
||||
self._squeak_profile_to_message(profile) for profile in profiles
|
||||
]
|
||||
return squeak_admin_pb2.GetContactProfilesReply(
|
||||
squeak_profiles=profile_msgs
|
||||
)
|
||||
return squeak_admin_pb2.GetContactProfilesReply(squeak_profiles=profile_msgs)
|
||||
|
||||
def GetSqueakProfile(self, request, context):
|
||||
profile_id = request.profile_id
|
||||
squeak_profile = self.handler.handle_get_squeak_profile(profile_id)
|
||||
squeak_profile_msg = self._squeak_profile_to_message(squeak_profile)
|
||||
return squeak_admin_pb2.GetSqueakProfileReply(
|
||||
squeak_profile=squeak_profile_msg
|
||||
)
|
||||
return squeak_admin_pb2.GetSqueakProfileReply(squeak_profile=squeak_profile_msg)
|
||||
|
||||
def GetSqueakProfileByAddress(self, request, context):
|
||||
address = request.address
|
||||
squeak_profile = self.handler.handle_get_squeak_profile_by_address(address)
|
||||
squeak_profile_msg = self._squeak_profile_to_message(squeak_profile)
|
||||
return squeak_admin_pb2.GetSqueakProfileReply(
|
||||
squeak_profile=squeak_profile_msg
|
||||
)
|
||||
return squeak_admin_pb2.GetSqueakProfileReply(squeak_profile=squeak_profile_msg)
|
||||
|
||||
def SetSqueakProfileWhitelisted(self, request, context):
|
||||
profile_id = request.profile_id
|
||||
|
|
@ -122,11 +107,12 @@ class SqueakAdminServerServicer(squeak_admin_pb2_grpc.SqueakAdminServicer):
|
|||
)
|
||||
|
||||
def GetFollowedSqueakDisplays(self, request, context):
|
||||
squeak_entries_with_profile = self.handler.handle_get_followed_squeak_display_entries()
|
||||
squeak_entries_with_profile = (
|
||||
self.handler.handle_get_followed_squeak_display_entries()
|
||||
)
|
||||
squeak_display_msgs = [
|
||||
self._squeak_entry_to_message(entry)
|
||||
for entry in
|
||||
squeak_entries_with_profile
|
||||
for entry in squeak_entries_with_profile
|
||||
]
|
||||
return squeak_admin_pb2.GetFollowedSqueakDisplaysReply(
|
||||
squeak_display_entries=squeak_display_msgs
|
||||
|
|
@ -137,14 +123,11 @@ class SqueakAdminServerServicer(squeak_admin_pb2_grpc.SqueakAdminServicer):
|
|||
min_block = 0
|
||||
max_block = sys.maxsize
|
||||
squeak_entries_with_profile = self.handler.handle_get_squeak_display_entries_for_address(
|
||||
address,
|
||||
min_block,
|
||||
max_block,
|
||||
address, min_block, max_block,
|
||||
)
|
||||
squeak_display_msgs = [
|
||||
self._squeak_entry_to_message(entry)
|
||||
for entry in
|
||||
squeak_entries_with_profile
|
||||
for entry in squeak_entries_with_profile
|
||||
]
|
||||
return squeak_admin_pb2.GetAddressSqueakDisplaysReply(
|
||||
squeak_display_entries=squeak_display_msgs
|
||||
|
|
@ -157,8 +140,7 @@ class SqueakAdminServerServicer(squeak_admin_pb2_grpc.SqueakAdminServicer):
|
|||
)
|
||||
squeak_display_msgs = [
|
||||
self._squeak_entry_to_message(entry)
|
||||
for entry in
|
||||
squeak_entries_with_profile
|
||||
for entry in squeak_entries_with_profile
|
||||
]
|
||||
return squeak_admin_pb2.GetAncestorSqueakDisplaysReply(
|
||||
squeak_display_entries=squeak_display_msgs
|
||||
|
|
@ -167,9 +149,7 @@ class SqueakAdminServerServicer(squeak_admin_pb2_grpc.SqueakAdminServicer):
|
|||
def DeleteSqueak(self, request, context):
|
||||
squeak_hash_str = request.squeak_hash
|
||||
squeak_hash = bytes.fromhex(squeak_hash_str)
|
||||
self.handler.handle_delete_squeak(
|
||||
squeak_hash
|
||||
)
|
||||
self.handler.handle_delete_squeak(squeak_hash)
|
||||
return squeak_admin_pb2.DeleteSqueakReply()
|
||||
|
||||
def AddServer(self, request, context):
|
||||
|
|
@ -177,21 +157,15 @@ class SqueakAdminServerServicer(squeak_admin_pb2_grpc.SqueakAdminServicer):
|
|||
server_host = request.host
|
||||
server_port = request.port
|
||||
server_id = self.handler.handle_add_server(
|
||||
server_name,
|
||||
server_host,
|
||||
server_port,
|
||||
)
|
||||
return squeak_admin_pb2.AddServerReply(
|
||||
server_id=server_id
|
||||
server_name, server_host, server_port,
|
||||
)
|
||||
return squeak_admin_pb2.AddServerReply(server_id=server_id)
|
||||
|
||||
def GetSqueakServer(self, request, context):
|
||||
server_id = request.server_id
|
||||
squeak_server = self.handler.handle_get_squeak_server(server_id)
|
||||
squeak_server_msg = self._squeak_server_to_message(squeak_server)
|
||||
return squeak_admin_pb2.GetSqueakServerReply(
|
||||
squeak_server=squeak_server_msg
|
||||
)
|
||||
return squeak_admin_pb2.GetSqueakServerReply(squeak_server=squeak_server_msg)
|
||||
|
||||
def _squeak_entry_to_message(self, squeak_entry_with_profile):
|
||||
if squeak_entry_with_profile is None:
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import logging
|
|||
|
||||
from bitcoin.base58 import Base58ChecksumError
|
||||
from bitcoin.wallet import CBitcoinAddressError
|
||||
from squeak.core import CheckSqueak, CheckSqueakError, CSqueak
|
||||
from squeak.core.signing import CSqueakAddress
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
|
|
|||
|
|
@ -45,9 +45,7 @@ class SqueakNode:
|
|||
lightning_client,
|
||||
max_squeaks_per_address_per_hour,
|
||||
)
|
||||
self.squeak_whitelist = SqueakWhitelist(
|
||||
postgres_db,
|
||||
)
|
||||
self.squeak_whitelist = SqueakWhitelist(postgres_db,)
|
||||
|
||||
def start_running(self):
|
||||
# self.squeak_block_periodic_worker.start_running()
|
||||
|
|
@ -143,7 +141,7 @@ class SqueakNode:
|
|||
def create_contact_profile(self, profile_name, squeak_address):
|
||||
address_validator = SqueakAddressValidator()
|
||||
if not address_validator.validate(squeak_address):
|
||||
raise Exception('Invalid squeak address: {}'.format(squeak_address))
|
||||
raise Exception("Invalid squeak address: {}".format(squeak_address))
|
||||
squeak_profile = SqueakProfile(
|
||||
profile_id=None,
|
||||
profile_name=profile_name,
|
||||
|
|
@ -189,11 +187,11 @@ class SqueakNode:
|
|||
def get_followed_squeak_entries_with_profile(self):
|
||||
return self.postgres_db.get_followed_squeak_entries_with_profile()
|
||||
|
||||
def get_squeak_entries_with_profile_for_address(self, address, min_block, max_block):
|
||||
def get_squeak_entries_with_profile_for_address(
|
||||
self, address, min_block, max_block
|
||||
):
|
||||
return self.postgres_db.get_squeak_entries_with_profile_for_address(
|
||||
address,
|
||||
min_block,
|
||||
max_block,
|
||||
address, min_block, max_block,
|
||||
)
|
||||
|
||||
def get_ancestor_squeak_entries_with_profile(self, squeak_hash_str):
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
import logging
|
||||
import queue
|
||||
|
||||
from squeakserver.server.util import get_hash
|
||||
from squeakserver.node.block_info import BlockInfo
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -11,7 +9,13 @@ HOUR_IN_SECONDS = 3600
|
|||
|
||||
|
||||
class SqueakRateLimiter:
|
||||
def __init__(self, postgres_db, blockchain_client, lightning_client, max_squeaks_per_address_per_hour):
|
||||
def __init__(
|
||||
self,
|
||||
postgres_db,
|
||||
blockchain_client,
|
||||
lightning_client,
|
||||
max_squeaks_per_address_per_hour,
|
||||
):
|
||||
self.postgres_db = postgres_db
|
||||
self.blockchain_client = blockchain_client
|
||||
self.lightning_client = lightning_client
|
||||
|
|
@ -21,7 +25,11 @@ class SqueakRateLimiter:
|
|||
squeak_hash = get_hash(squeak)
|
||||
logger.info("Checking rate limit for squeak: {}".format(squeak_hash))
|
||||
current_squeak_count = self._get_current_squeak_count(squeak)
|
||||
logger.info("Current squeak count: {}, limit: {}".format(current_squeak_count, self.max_squeaks_per_address_per_hour))
|
||||
logger.info(
|
||||
"Current squeak count: {}, limit: {}".format(
|
||||
current_squeak_count, self.max_squeaks_per_address_per_hour
|
||||
)
|
||||
)
|
||||
return current_squeak_count < self.max_squeaks_per_address_per_hour
|
||||
|
||||
def _get_current_squeak_count(self, squeak):
|
||||
|
|
@ -29,11 +37,13 @@ class SqueakRateLimiter:
|
|||
return self._get_num_squeaks_in_last_hour(squeak_address)
|
||||
|
||||
def _get_num_squeaks_in_last_hour(self, squeak_address):
|
||||
logger.info("Getting squeak count for last hour for squeak address: {}".format(squeak_address))
|
||||
logger.info(
|
||||
"Getting squeak count for last hour for squeak address: {}".format(
|
||||
squeak_address
|
||||
)
|
||||
)
|
||||
hashes = self.postgres_db.lookup_squeaks_by_time(
|
||||
[squeak_address],
|
||||
HOUR_IN_SECONDS,
|
||||
include_unverified=True,
|
||||
[squeak_address], HOUR_IN_SECONDS, include_unverified=True,
|
||||
)
|
||||
return len(hashes)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,6 @@
|
|||
import logging
|
||||
import queue
|
||||
|
||||
from squeak.core.signing import CSqueakAddress
|
||||
|
||||
from squeakserver.server.util import get_hash
|
||||
from squeakserver.node.block_info import BlockInfo
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -19,7 +15,11 @@ class SqueakWhitelist:
|
|||
squeak_hash = get_hash(squeak).hex()
|
||||
squeak_address = squeak.GetAddress()
|
||||
squeak_address_str = str(squeak_address)
|
||||
logger.info("Checking whitelist for squeak hash: {}, squeak address: {}".format(squeak_hash, squeak_address_str))
|
||||
logger.info(
|
||||
"Checking whitelist for squeak hash: {}, squeak address: {}".format(
|
||||
squeak_hash, squeak_address_str
|
||||
)
|
||||
)
|
||||
logger.info("Allowed addresses: {}".format(self.allowed_addresses))
|
||||
is_allowed = squeak_address_str in self.allowed_addresses
|
||||
logger.info("Is squeak in whitelist: {}".format(is_allowed))
|
||||
|
|
@ -31,7 +31,4 @@ class SqueakWhitelist:
|
|||
|
||||
def _get_whitelisted_addresses(self):
|
||||
whitelisted_profiles = self.postgres_db.get_whitelisted_profiles()
|
||||
return [
|
||||
profile.address
|
||||
for profile in whitelisted_profiles
|
||||
]
|
||||
return [profile.address for profile in whitelisted_profiles]
|
||||
|
|
|
|||
|
|
@ -168,7 +168,12 @@ def run_server(config):
|
|||
|
||||
# Create and start the squeak node
|
||||
squeak_node = SqueakNode(
|
||||
postgres_db, blockchain_client, lightning_client, lightning_host_port, price, max_squeaks_per_address_per_hour
|
||||
postgres_db,
|
||||
blockchain_client,
|
||||
lightning_client,
|
||||
lightning_host_port,
|
||||
price,
|
||||
max_squeaks_per_address_per_hour,
|
||||
)
|
||||
squeak_node.start_running()
|
||||
|
||||
|
|
|
|||
|
|
@ -5,13 +5,12 @@ from psycopg2 import pool
|
|||
from psycopg2.extras import DictCursor
|
||||
from squeak.core import CSqueak
|
||||
|
||||
from squeakserver.blockchain.util import parse_block_header
|
||||
from squeakserver.core.squeak_entry import SqueakEntry
|
||||
from squeakserver.core.squeak_entry_with_profile import SqueakEntryWithProfile
|
||||
from squeakserver.server.squeak_profile import SqueakProfile
|
||||
from squeakserver.server.squeak_server import SqueakServer
|
||||
from squeakserver.server.util import get_hash
|
||||
from squeakserver.blockchain.util import parse_block_header
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -125,7 +124,9 @@ class PostgresDb:
|
|||
rows = curs.fetchall()
|
||||
return [self._parse_squeak_entry_with_profile(row) for row in rows]
|
||||
|
||||
def get_squeak_entries_with_profile_for_address(self, address, min_block, max_block):
|
||||
def get_squeak_entries_with_profile_for_address(
|
||||
self, address, min_block, max_block
|
||||
):
|
||||
""" Get a squeak. """
|
||||
sql = """
|
||||
SELECT * FROM squeak
|
||||
|
|
@ -182,12 +183,16 @@ class PostgresDb:
|
|||
with self.get_cursor() as curs:
|
||||
# mogrify to debug.
|
||||
# logger.info(curs.mogrify(sql, (addresses_tuple, min_block, max_block)))
|
||||
curs.execute(sql, (addresses_tuple, min_block, max_block, include_unverified))
|
||||
curs.execute(
|
||||
sql, (addresses_tuple, min_block, max_block, include_unverified)
|
||||
)
|
||||
rows = curs.fetchall()
|
||||
hashes = [bytes.fromhex(row["hash"]) for row in rows]
|
||||
return hashes
|
||||
|
||||
def lookup_squeaks_by_time(self, addresses, interval_seconds, include_unverified=False):
|
||||
def lookup_squeaks_by_time(
|
||||
self, addresses, interval_seconds, include_unverified=False
|
||||
):
|
||||
""" Lookup squeaks. """
|
||||
sql = """
|
||||
SELECT hash FROM squeak
|
||||
|
|
@ -419,7 +424,9 @@ class PostgresDb:
|
|||
)
|
||||
block_header_column = row["block_header"]
|
||||
block_header_bytes = bytes(block_header_column) if block_header_column else None
|
||||
block_header = parse_block_header(block_header_bytes) if block_header_bytes else None
|
||||
block_header = (
|
||||
parse_block_header(block_header_bytes) if block_header_bytes else None
|
||||
)
|
||||
return SqueakEntry(squeak=squeak, block_header=block_header)
|
||||
|
||||
def _parse_squeak_profile(self, row):
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
from collections import namedtuple
|
||||
|
||||
SqueakServer = namedtuple(
|
||||
"SqueakServer",
|
||||
"server_id, server_name, host, port, sharing, following",
|
||||
"SqueakServer", "server_id, server_name, host, port, sharing, following",
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue