2016-07-20 19:00:34 +02:00
|
|
|
import base64
|
2016-10-18 03:00:24 +02:00
|
|
|
import datetime
|
|
|
|
import logging
|
2015-08-20 17:27:15 +02:00
|
|
|
import random
|
2016-10-18 03:00:24 +02:00
|
|
|
import socket
|
2016-12-30 19:35:17 +01:00
|
|
|
import string
|
2017-03-15 21:19:11 +01:00
|
|
|
import json
|
2015-08-20 17:27:15 +02:00
|
|
|
|
2016-11-19 23:58:40 +01:00
|
|
|
import pkg_resources
|
|
|
|
|
2017-04-07 02:37:10 +02:00
|
|
|
from lbryschema.claim import ClaimDict
|
2016-07-25 23:09:13 +02:00
|
|
|
from lbrynet.core.cryptoutils import get_lbry_hash_obj
|
|
|
|
|
2016-09-30 06:06:07 +02:00
|
|
|
# digest_size is in bytes, and blob hashes are hex encoded
|
|
|
|
blobhash_length = get_lbry_hash_obj().digest_size * 2
|
2015-08-20 17:27:15 +02:00
|
|
|
|
2016-10-18 03:00:24 +02:00
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
2016-10-05 21:16:20 +02:00
|
|
|
# defining these time functions here allows for easier overriding in testing
|
2016-09-30 06:06:07 +02:00
|
|
|
def now():
|
|
|
|
return datetime.datetime.now()
|
|
|
|
|
2016-10-05 21:16:20 +02:00
|
|
|
|
2016-09-30 06:06:07 +02:00
|
|
|
def utcnow():
|
|
|
|
return datetime.datetime.utcnow()
|
|
|
|
|
2016-10-05 21:16:20 +02:00
|
|
|
|
2016-09-30 06:06:07 +02:00
|
|
|
def isonow():
|
|
|
|
"""Return utc now in isoformat with timezone"""
|
|
|
|
return utcnow().isoformat() + 'Z'
|
|
|
|
|
2016-10-31 22:19:19 +01:00
|
|
|
|
2016-09-30 06:06:07 +02:00
|
|
|
def today():
|
|
|
|
return datetime.datetime.today()
|
|
|
|
|
|
|
|
|
2017-01-02 20:52:24 +01:00
|
|
|
def timedelta(**kwargs):
|
|
|
|
return datetime.timedelta(**kwargs)
|
|
|
|
|
|
|
|
|
|
|
|
def datetime_obj(*args, **kwargs):
|
|
|
|
return datetime.datetime(*args, **kwargs)
|
|
|
|
|
|
|
|
|
2017-02-09 17:22:23 +01:00
|
|
|
def call_later(delay, func, *args, **kwargs):
|
2017-04-10 16:51:49 +02:00
|
|
|
# Import here to ensure that it gets called after installing a reactor
|
2017-02-09 17:22:23 +01:00
|
|
|
# see: http://twistedmatrix.com/documents/current/core/howto/choosing-reactor.html
|
|
|
|
from twisted.internet import reactor
|
|
|
|
return reactor.callLater(delay, func, *args, **kwargs)
|
|
|
|
|
2017-06-20 21:03:17 +02:00
|
|
|
def safe_start_looping_call(looping_call, interval_sec):
|
|
|
|
if not looping_call.running:
|
|
|
|
looping_call.start(interval_sec)
|
|
|
|
|
|
|
|
def safe_stop_looping_call(looping_call):
|
|
|
|
if looping_call.running:
|
|
|
|
looping_call.stop()
|
2017-02-09 17:22:23 +01:00
|
|
|
|
2015-08-20 17:27:15 +02:00
|
|
|
def generate_id(num=None):
|
|
|
|
h = get_lbry_hash_obj()
|
|
|
|
if num is not None:
|
|
|
|
h.update(str(num))
|
|
|
|
else:
|
|
|
|
h.update(str(random.getrandbits(512)))
|
|
|
|
return h.digest()
|
|
|
|
|
|
|
|
|
2016-10-05 21:16:20 +02:00
|
|
|
def is_valid_hashcharacter(char):
|
|
|
|
return char in "0123456789abcdef"
|
|
|
|
|
|
|
|
|
2015-08-20 17:27:15 +02:00
|
|
|
def is_valid_blobhash(blobhash):
|
2016-10-19 00:25:16 +02:00
|
|
|
"""Checks whether the blobhash is the correct length and contains only
|
|
|
|
valid characters (0-9, a-f)
|
|
|
|
|
2015-08-20 17:27:15 +02:00
|
|
|
@param blobhash: string, the blobhash to check
|
|
|
|
|
2016-10-19 00:25:16 +02:00
|
|
|
@return: True/False
|
2015-08-20 17:27:15 +02:00
|
|
|
"""
|
2016-10-19 00:25:16 +02:00
|
|
|
return len(blobhash) == blobhash_length and all(is_valid_hashcharacter(l) for l in blobhash)
|
2016-07-25 23:09:13 +02:00
|
|
|
|
|
|
|
|
|
|
|
def version_is_greater_than(a, b):
|
|
|
|
"""Returns True if version a is more recent than version b"""
|
2016-11-19 23:58:40 +01:00
|
|
|
return pkg_resources.parse_version(a) > pkg_resources.parse_version(b)
|
2016-07-20 19:00:34 +02:00
|
|
|
|
|
|
|
|
|
|
|
def deobfuscate(obfustacated):
|
|
|
|
return base64.b64decode(obfustacated.decode('rot13'))
|
|
|
|
|
|
|
|
|
|
|
|
def obfuscate(plain):
|
|
|
|
return base64.b64encode(plain).encode('rot13')
|
2016-09-16 06:14:25 +02:00
|
|
|
|
|
|
|
|
2017-04-10 16:51:49 +02:00
|
|
|
def check_connection(server="lbry.io", port=80):
|
2016-10-18 03:00:24 +02:00
|
|
|
"""Attempts to open a socket to server:port and returns True if successful."""
|
|
|
|
try:
|
2016-11-11 17:10:00 +01:00
|
|
|
log.debug('Checking connection to %s:%s', server, port)
|
2016-10-18 03:00:24 +02:00
|
|
|
host = socket.gethostbyname(server)
|
|
|
|
s = socket.create_connection((host, port), 2)
|
2016-11-11 17:10:00 +01:00
|
|
|
log.debug('Connection successful')
|
2016-10-18 03:00:24 +02:00
|
|
|
return True
|
|
|
|
except Exception as ex:
|
|
|
|
log.info(
|
|
|
|
"Failed to connect to %s:%s. Maybe the internet connection is not working",
|
|
|
|
server, port, exc_info=True)
|
|
|
|
return False
|
2016-10-22 00:26:36 +02:00
|
|
|
|
|
|
|
|
2016-12-30 19:35:17 +01:00
|
|
|
def random_string(length=10, chars=string.ascii_lowercase):
|
|
|
|
return ''.join([random.choice(chars) for _ in range(length)])
|
2017-02-16 15:09:21 +01:00
|
|
|
|
|
|
|
|
|
|
|
def short_hash(hash_str):
|
|
|
|
return hash_str[:6]
|
2017-03-09 16:39:17 +01:00
|
|
|
|
|
|
|
|
|
|
|
def get_sd_hash(stream_info):
|
|
|
|
if not stream_info:
|
|
|
|
return None
|
2017-04-07 02:37:10 +02:00
|
|
|
if isinstance(stream_info, ClaimDict):
|
|
|
|
return stream_info.source_hash
|
2017-04-05 01:42:35 +02:00
|
|
|
return stream_info['stream']['source']['source']
|
2017-03-15 21:19:11 +01:00
|
|
|
|
|
|
|
|
|
|
|
def json_dumps_pretty(obj, **kwargs):
|
|
|
|
return json.dumps(obj, sort_keys=True, indent=2, separators=(',', ': '), **kwargs)
|