Implement Insights page

This commit is contained in:
2022-07-21 13:51:55 +01:00
parent a56042376c
commit 185bda02ea
15 changed files with 652 additions and 274 deletions

View File

@@ -0,0 +1,88 @@
import json
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpResponse, HttpResponseForbidden, JsonResponse
from django.shortcuts import render
from django.views import View
from rest_framework.parsers import FormParser
from rest_framework.views import APIView
from core.lib.opensearch import query_results
from core.lib.threshold import (
annotate_num_chans,
annotate_num_users,
get_chans,
get_users,
)
class DrilldownSearch(LoginRequiredMixin, View):
# parser_classes = [JSONParser]
template_name = "ui/drilldown/results.html"
plan_name = "drilldown"
def post(self, request):
if not request.user.has_plan(self.plan_name):
return HttpResponseForbidden()
context = query_results(request)
if not context:
return HttpResponseForbidden()
context["data"] = json.dumps(
[
{
"text": item.get("msg", None) or item.get("id"),
"nick": item.get("nick", None),
"value": item.get("sentiment", None) or None,
"date": item.get("ts"),
}
for item in context["results"]
]
)
if context:
return render(request, self.template_name, context)
else:
return HttpResponse("No results")
class ThresholdInfoModal(LoginRequiredMixin, APIView):
parser_classes = [FormParser]
plan_name = "drilldown"
template_name = "modals/drilldown.html"
def post(self, request):
if not request.user.has_plan(self.plan_name):
return JsonResponse({"success": False})
if "net" not in request.data:
return JsonResponse({"success": False})
if "nick" not in request.data:
return JsonResponse({"success": False})
if "channel" not in request.data:
return JsonResponse({"success": False})
net = request.data["net"]
nick = request.data["nick"]
channel = request.data["channel"]
channels = get_chans(net, [nick])
users = get_users(net, [channel])
num_users = annotate_num_users(net, channels)
num_chans = annotate_num_chans(net, users)
if channels:
inter_users = get_users(net, channels)
else:
inter_users = []
if users:
inter_chans = get_chans(net, users)
else:
inter_chans = []
context = {
"net": net,
"nick": nick,
"channel": channel,
"chans": channels,
"users": users,
"inter_chans": inter_chans,
"inter_users": inter_users,
"num_users": num_users,
"num_chans": num_chans,
}
return render(request, self.template_name, context)

View File

@@ -0,0 +1,75 @@
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpResponse, HttpResponseForbidden, JsonResponse
from django.shortcuts import render
from django.views import View
from rest_framework.parsers import FormParser
from rest_framework.views import APIView
from core.lib.opensearch import query_single_result
from core.lib.threshold import (
annotate_num_chans,
annotate_num_users,
get_chans,
get_users,
)
class InsightsSearch(LoginRequiredMixin, View):
# parser_classes = [JSONParser]
template_name = "ui/insights/results.html"
plan_name = "drilldown"
def post(self, request):
if not request.user.has_plan(self.plan_name):
return HttpResponseForbidden()
results, context = query_single_result(request)
if not context:
return HttpResponseForbidden()
if context:
return render(request, self.template_name, context)
else:
return HttpResponse("No results")
class InsightsInfoModal(LoginRequiredMixin, APIView):
parser_classes = [FormParser]
plan_name = "drilldown"
template_name = "modals/insights.html"
def post(self, request):
if not request.user.has_plan(self.plan_name):
return JsonResponse({"success": False})
if "net" not in request.data:
return JsonResponse({"success": False})
if "nick" not in request.data:
return JsonResponse({"success": False})
if "channel" not in request.data:
return JsonResponse({"success": False})
net = request.data["net"]
nick = request.data["nick"]
channel = request.data["channel"]
channels = get_chans(net, [nick])
users = get_users(net, [channel])
num_users = annotate_num_users(net, channels)
num_chans = annotate_num_chans(net, users)
if channels:
inter_users = get_users(net, channels)
else:
inter_users = []
if users:
inter_chans = get_chans(net, users)
else:
inter_chans = []
context = {
"net": net,
"nick": nick,
"channel": channel,
"chans": channels,
"users": users,
"inter_chans": inter_chans,
"inter_users": inter_users,
"num_users": num_users,
"num_chans": num_chans,
}
return render(request, self.template_name, context)

View File

@@ -1,119 +0,0 @@
import json
from django.conf import settings
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpResponse, HttpResponseForbidden, JsonResponse
from django.shortcuts import render
from django.views import View
from core.lib.opensearch import initialise_opensearch, run_main_query
from core.lib.threshold import annotate_num_chans, annotate_num_users, annotate_online
client = initialise_opensearch()
def query_results(request, post_params, api=False):
fields = None
if "fields" in request.POST:
fields = request.POST.getlist("fields")
if "size" in request.POST:
size = request.POST["size"]
if "query" in request.POST:
query = request.POST["query"]
results = run_main_query(client, request.user, query, fields, size)
if not results:
return False
results_parsed = []
if "hits" in results.keys():
if "hits" in results["hits"]:
for item in results["hits"]["hits"]:
element = item["_source"]
element["id"] = item["_id"]
ts = element["ts"]
ts_spl = ts.split("T")
date = ts_spl[0]
time = ts_spl[1]
element["date"] = date
element["time"] = time
results_parsed.append(element)
# Figure out items with net (not discord)
nets = set()
for x in results_parsed:
if "net" in x:
nets.add(x["net"])
for net in nets:
# Annotate the online attribute from Threshold
online_info = annotate_online(
net, [x["nick"] for x in results_parsed if x["src"] == "irc"]
)
# Annotate the number of users in the channel
num_users = annotate_num_users(
net, [x["channel"] for x in results_parsed if x["src"] == "irc"]
)
# Annotate the number channels the user is on
num_chans = annotate_num_chans(
net, [x["nick"] for x in results_parsed if x["src"] == "irc"]
)
for item in results_parsed:
if item["nick"] in online_info:
item["online"] = online_info[item["nick"]]
if item["channel"] in num_users:
item["num_users"] = num_users[item["channel"]]
if item["nick"] in num_chans:
item["num_chans"] = num_chans[item["nick"]]
context = {
"query": query,
"results": results_parsed,
"card": results["hits"]["total"]["value"],
"took": results["took"],
"redacted": results["redacted"],
"exemption": results["exemption"],
"fields": settings.OPENSEARCH_MAIN_SEARCH_FIELDS,
"sizes": settings.OPENSEARCH_MAIN_SIZES,
"timescales": settings.OPENSEARCH_MAIN_TIMESCALES,
}
return context
class Search(LoginRequiredMixin, View):
# parser_classes = [JSONParser]
template_name = "ui/results.html"
plan_name = "drilldown"
def post(self, request):
if not request.user.has_plan(self.plan_name):
return HttpResponseForbidden()
context = query_results(request, request.POST)
if not context:
return HttpResponseForbidden()
context["data"] = json.dumps(
[
{
"text": item.get("msg", None) or item.get("id"),
"nick": item.get("nick", None),
"value": item.get("sentiment", None) or None,
"date": item.get("ts"),
}
for item in context["results"]
]
)
if context:
return render(request, self.template_name, context)
else:
return HttpResponse("No results")
class APISearch(LoginRequiredMixin, View):
# parser_classes = [JSONParser]
template_name = "ui/results.html"
plan_name = "drilldown"
def post(self, request):
if not request.user.has_plan(self.plan_name):
return JsonResponse({"success": False})
context = query_results(request, request.POST)
return JsonResponse(context)