2022-07-21 12:51:12 +00:00
|
|
|
import logging
|
|
|
|
from json import dumps
|
2022-07-26 21:15:30 +00:00
|
|
|
from operator import itemgetter
|
|
|
|
from typing import OrderedDict
|
2022-07-21 12:51:12 +00:00
|
|
|
|
|
|
|
import requests
|
|
|
|
from django.conf import settings
|
|
|
|
from requests.exceptions import JSONDecodeError
|
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
|
|
def escape(obj):
|
|
|
|
chars = ["[", "]", "^", "-", "*", "?"]
|
|
|
|
if isinstance(obj, str):
|
|
|
|
obj = obj.replace("\\", "\\\\")
|
|
|
|
for i in chars:
|
|
|
|
obj = obj.replace(i, "\\" + i)
|
|
|
|
elif isinstance(obj, list):
|
|
|
|
for i in obj:
|
|
|
|
i = escape(i)
|
|
|
|
elif isinstance(obj, dict):
|
|
|
|
for key in obj:
|
|
|
|
obj[key] = escape(obj[key])
|
|
|
|
return obj
|
|
|
|
|
|
|
|
|
2022-07-21 12:51:43 +00:00
|
|
|
def sort_data(data):
|
2022-07-29 21:22:22 +00:00
|
|
|
for item in data.keys():
|
2022-07-21 12:51:43 +00:00
|
|
|
if isinstance(data[item], list):
|
2022-07-29 21:22:22 +00:00
|
|
|
cont = False
|
2022-07-29 21:22:22 +00:00
|
|
|
for v in data[item]:
|
|
|
|
if isinstance(v, list):
|
|
|
|
cont = True
|
|
|
|
if isinstance(v, dict):
|
|
|
|
cont = True
|
|
|
|
if cont:
|
|
|
|
continue
|
2022-07-21 12:51:43 +00:00
|
|
|
data[item].sort()
|
2022-07-26 21:15:30 +00:00
|
|
|
elif isinstance(data[item], dict):
|
2022-07-29 21:22:22 +00:00
|
|
|
# Don't sort nested stuff
|
|
|
|
cont = False
|
|
|
|
for k, v in data[item].items():
|
|
|
|
if isinstance(v, list):
|
|
|
|
cont = True
|
|
|
|
if isinstance(v, dict):
|
|
|
|
cont = True
|
|
|
|
if cont:
|
|
|
|
continue
|
2022-07-26 21:15:30 +00:00
|
|
|
sorted_item = sorted(data[item].items(), key=itemgetter(1), reverse=True)
|
|
|
|
data[item] = OrderedDict({k: v for k, v in sorted_item})
|
2022-07-21 12:51:43 +00:00
|
|
|
|
|
|
|
|
2022-08-01 18:06:56 +00:00
|
|
|
def threshold_request(url, data, method="POST", esc=False):
|
2022-07-21 12:51:12 +00:00
|
|
|
headers = {
|
|
|
|
"ApiKey": settings.THRESHOLD_API_KEY,
|
|
|
|
"Token": settings.THRESHOLD_API_TOKEN,
|
|
|
|
}
|
2022-08-01 18:06:56 +00:00
|
|
|
if esc:
|
|
|
|
for key in data:
|
|
|
|
data[key] = escape(data[key])
|
2022-07-27 19:53:41 +00:00
|
|
|
|
|
|
|
if method == "POST":
|
|
|
|
method = requests.post
|
|
|
|
elif method == "GET":
|
|
|
|
method = requests.get
|
|
|
|
elif method == "DELETE":
|
|
|
|
method = requests.delete
|
|
|
|
elif method == "PUT":
|
|
|
|
method = requests.put
|
|
|
|
else:
|
|
|
|
logger.error("Invalid method specified")
|
|
|
|
method = requests.get
|
|
|
|
|
|
|
|
r = method(
|
2022-07-21 12:51:12 +00:00
|
|
|
f"{settings.THRESHOLD_ENDPOINT}/{url}/", data=dumps(data), headers=headers
|
|
|
|
)
|
|
|
|
if not r.headers.get("Counter") == settings.THRESHOLD_API_COUNTER:
|
|
|
|
logger.error(
|
|
|
|
(
|
|
|
|
f"Threshold API counter mismatch: "
|
|
|
|
f"{r.headers.get('Counter')} != "
|
|
|
|
f"{settings.THRESHOLD_API_COUNTER}"
|
|
|
|
)
|
|
|
|
)
|
|
|
|
return False
|
|
|
|
try:
|
|
|
|
response = r.json()
|
2022-07-21 12:51:48 +00:00
|
|
|
sort_data(response)
|
2022-07-21 12:51:12 +00:00
|
|
|
except JSONDecodeError:
|
|
|
|
logging.error(f"Invalid JSON response: {r.text}")
|
2022-07-21 12:51:48 +00:00
|
|
|
return False
|
2022-07-21 12:51:12 +00:00
|
|
|
return response
|
|
|
|
|
|
|
|
|
|
|
|
def get_chans(net, query):
|
|
|
|
url = "chans"
|
|
|
|
payload = {"net": net, "query": query}
|
2022-08-01 18:06:56 +00:00
|
|
|
channels = threshold_request(url, payload, esc=True)
|
2022-07-21 12:51:12 +00:00
|
|
|
if not channels:
|
|
|
|
return []
|
|
|
|
return channels["chans"]
|
|
|
|
|
|
|
|
|
|
|
|
def get_users(net, query):
|
|
|
|
url = "users"
|
|
|
|
payload = {"net": net, "query": query}
|
2022-08-01 18:06:56 +00:00
|
|
|
users = threshold_request(url, payload, esc=True)
|
2022-07-21 12:51:12 +00:00
|
|
|
if not users:
|
|
|
|
return []
|
|
|
|
return users["users"]
|
|
|
|
|
|
|
|
|
|
|
|
def annotate_online(net, query):
|
|
|
|
url = "online"
|
|
|
|
payload = {"net": net, "query": query}
|
2022-08-01 18:06:56 +00:00
|
|
|
online_info = threshold_request(url, payload, esc=True)
|
2022-07-21 12:51:12 +00:00
|
|
|
if not online_info:
|
|
|
|
return {}
|
|
|
|
return online_info
|
2022-07-21 12:51:48 +00:00
|
|
|
|
|
|
|
|
|
|
|
def annotate_num_users(net, query):
|
|
|
|
url = "num_users"
|
|
|
|
payload = {"net": net, "query": query}
|
2022-08-01 18:06:56 +00:00
|
|
|
user_num_map = threshold_request(url, payload, esc=True)
|
2022-07-21 12:51:48 +00:00
|
|
|
if not user_num_map:
|
|
|
|
return {}
|
|
|
|
return user_num_map
|
|
|
|
|
|
|
|
|
|
|
|
def annotate_num_chans(net, query):
|
|
|
|
url = "num_chans"
|
|
|
|
payload = {"net": net, "query": query}
|
2022-08-01 18:06:56 +00:00
|
|
|
chan_num_map = threshold_request(url, payload, esc=True)
|
2022-07-21 12:51:48 +00:00
|
|
|
if not chan_num_map:
|
|
|
|
return {}
|
|
|
|
return chan_num_map
|