Implement joining and parting channels
This commit is contained in:
parent
3d91c4164e
commit
b401fe939f
17
app/urls.py
17
app/urls.py
|
@ -28,6 +28,7 @@ from core.views.manage.threshold.irc import (
|
|||
ThresholdIRCNetworkInfo,
|
||||
ThresholdIRCNetworkInfoEdit,
|
||||
ThresholdIRCNetworkRelays,
|
||||
ThresholdIRCNetworkRelayStatus,
|
||||
ThresholdIRCNetworks,
|
||||
ThresholdIRCStats,
|
||||
)
|
||||
|
@ -119,11 +120,27 @@ urlpatterns = [
|
|||
ThresholdIRCNetworkRelays.as_view(),
|
||||
name="threshold_irc_network_relays",
|
||||
),
|
||||
path(
|
||||
"manage/threshold/irc/network/<str:net>/<int:num>/<int:status>/",
|
||||
ThresholdIRCNetworkRelayStatus.as_view(),
|
||||
name="threshold_irc_network_relay_status",
|
||||
),
|
||||
path(
|
||||
"manage/threshold/irc/network/<str:net>/channels/",
|
||||
ThresholdIRCNetworkChannels.as_view(),
|
||||
name="threshold_irc_network_channels",
|
||||
),
|
||||
path(
|
||||
"manage/threshold/irc/network/<str:net>/channel/<channel>/",
|
||||
ThresholdIRCNetworkChannels.as_view(),
|
||||
name="threshold_irc_network_channel",
|
||||
),
|
||||
# No channel argument as we're gonna do a form
|
||||
path(
|
||||
"manage/threshold/irc/network/<str:net>/channel/",
|
||||
ThresholdIRCNetworkChannels.as_view(),
|
||||
name="threshold_irc_network_channel",
|
||||
),
|
||||
##
|
||||
path("api/chans/", ThresholdChans.as_view(), name="chans"),
|
||||
path("api/users/", ThresholdUsers.as_view(), name="users"),
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import urllib.parse
|
||||
|
||||
from core.lib.threshold import threshold_request
|
||||
|
||||
|
||||
|
@ -31,8 +33,15 @@ def get_irc_network(net):
|
|||
def edit_irc_network(net, data):
|
||||
url = f"irc/network/{net}/edit"
|
||||
payload = dict(data)
|
||||
network = threshold_request(url, payload)
|
||||
return network
|
||||
result = threshold_request(url, payload)
|
||||
return result
|
||||
|
||||
|
||||
def change_network_status(net, num, status):
|
||||
url = f"irc/network/{net}/{num}"
|
||||
payload = {"status": status}
|
||||
result = threshold_request(url, payload)
|
||||
return result
|
||||
|
||||
|
||||
def get_irc_relays(net):
|
||||
|
@ -40,7 +49,7 @@ def get_irc_relays(net):
|
|||
payload = {}
|
||||
relays = threshold_request(url, payload)
|
||||
if not relays:
|
||||
return []
|
||||
return {}
|
||||
return relays
|
||||
|
||||
|
||||
|
@ -49,5 +58,25 @@ def get_irc_channels(net):
|
|||
payload = {}
|
||||
channels = threshold_request(url, payload)
|
||||
if not channels:
|
||||
return []
|
||||
return {}
|
||||
return channels
|
||||
|
||||
|
||||
def part_channel(net, channel):
|
||||
channel = urllib.parse.quote(channel, safe="")
|
||||
url = f"irc/network/{net}/channel/{channel}"
|
||||
payload = {}
|
||||
parted = threshold_request(url, payload, method="DELETE")
|
||||
if not parted:
|
||||
return {}
|
||||
return parted
|
||||
|
||||
|
||||
def join_channel(net, channel):
|
||||
channel = urllib.parse.quote(channel, safe="")
|
||||
url = f"irc/network/{net}/channel/{channel}"
|
||||
payload = {}
|
||||
joined = threshold_request(url, payload, method="PUT")
|
||||
if not joined:
|
||||
return {}
|
||||
return joined
|
||||
|
|
|
@ -37,14 +37,28 @@ def sort_data(data):
|
|||
data[item] = OrderedDict({k: v for k, v in sorted_item})
|
||||
|
||||
|
||||
def threshold_request(url, data):
|
||||
def threshold_request(url, data, method="POST"):
|
||||
headers = {
|
||||
"ApiKey": settings.THRESHOLD_API_KEY,
|
||||
"Token": settings.THRESHOLD_API_TOKEN,
|
||||
}
|
||||
for key in data:
|
||||
data[key] = escape(data[key])
|
||||
r = requests.post(
|
||||
|
||||
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
|
||||
print("SENDING TO", url)
|
||||
|
||||
r = method(
|
||||
f"{settings.THRESHOLD_ENDPOINT}/{url}/", data=dumps(data), headers=headers
|
||||
)
|
||||
if not r.headers.get("Counter") == settings.THRESHOLD_API_COUNTER:
|
||||
|
|
|
@ -1,8 +1,17 @@
|
|||
<div id="channels">
|
||||
{% if message is not None %}
|
||||
<div class="notification is-{{ class }}" hx-ext="remove-me" remove-me="3s">
|
||||
{{ message }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if channels is not None %}
|
||||
<div class="content" style="max-height: 30em; overflow: auto;">
|
||||
<div class="table-container">
|
||||
<table class="table is-fullwidth is-hoverable">
|
||||
<thead>
|
||||
<th>channel</th>
|
||||
<th>actions</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for channel, info in channels.items %}
|
||||
<tr>
|
||||
|
@ -12,6 +21,18 @@
|
|||
{{ info }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<button
|
||||
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
|
||||
hx-delete="{% url 'threshold_irc_network_channel' net channel %}"
|
||||
hx-target="#channels"
|
||||
hx-swap="outerHTML"
|
||||
class="button is-danger is-small">
|
||||
<span class="icon" data-tooltip="Part">
|
||||
<i class="fa-solid fa-xmark" aria-hidden="true"></i>
|
||||
</span>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
style="display: none;"
|
||||
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
|
||||
hx-post="{% url 'threshold_irc_network_info' net %}"
|
||||
hx-trigger="load"
|
||||
hx-trigger="load, every 5s"
|
||||
hx-target="#info"
|
||||
hx-swap="outerHTML">
|
||||
</div>
|
||||
|
@ -13,8 +13,8 @@
|
|||
<div
|
||||
style="display: none;"
|
||||
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
|
||||
hx-post="{% url 'threshold_irc_network_relays' net %}"
|
||||
hx-trigger="load"
|
||||
hx-get="{% url 'threshold_irc_network_relays' net %}"
|
||||
hx-trigger="load, every 5s"
|
||||
hx-target="#relays"
|
||||
hx-swap="outerHTML">
|
||||
</div>
|
||||
|
@ -23,7 +23,7 @@
|
|||
style="display: none;"
|
||||
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
|
||||
hx-post="{% url 'threshold_irc_network_channels' net %}"
|
||||
hx-trigger="load"
|
||||
hx-trigger="load, every 5s"
|
||||
hx-target="#channels"
|
||||
hx-swap="outerHTML">
|
||||
</div>
|
||||
|
@ -57,4 +57,37 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="columns">
|
||||
<div class="column is-half">
|
||||
<div class="box">
|
||||
<form method="POST">
|
||||
<div class="field">
|
||||
<div class="field-body">
|
||||
<div class="field">
|
||||
<div class="control is-expanded has-icons-left">
|
||||
<input id="query" name="channel" class="input" type="text" placeholder="channel">
|
||||
<span class="icon is-small is-left">
|
||||
<i class="fa-solid fa-hashtag"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="control">
|
||||
<button
|
||||
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
|
||||
class="button is-primary is-fullwidth"
|
||||
hx-put="{% url 'threshold_irc_network_channel' net %}"
|
||||
hx-trigger="click"
|
||||
hx-target="#channels"
|
||||
hx-swap="outerHTML">
|
||||
Join
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
{% load index %}
|
||||
<div id="relays">
|
||||
{% if message is not None %}
|
||||
<div class="notification is-{{ class }}" hx-ext="remove-me" remove-me="3s">
|
||||
{{ message }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if relays is not None %}
|
||||
<div class="content" style="max-height: 30em; overflow: auto;">
|
||||
<div class="table-container">
|
||||
|
@ -34,10 +40,30 @@
|
|||
<span class="icon">
|
||||
<i class="fa-solid fa-check" aria-hidden="true"></i>
|
||||
</span>
|
||||
<button
|
||||
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
|
||||
hx-get="{% url 'threshold_irc_network_relay_status' relay|index:'net' relay|index:'id' 0 %}"
|
||||
hx-target="#relays"
|
||||
hx-swap="outerHTML"
|
||||
class="button is-danger is-small">
|
||||
<span class="icon" data-tooltip="Disable">
|
||||
<i class="fa-solid fa-wifi-slash" aria-hidden="true"></i>
|
||||
</span>
|
||||
</button>
|
||||
{% else %}
|
||||
<span class="icon">
|
||||
<i class="fa-solid fa-xmark" aria-hidden="true"></i>
|
||||
</span>
|
||||
<button
|
||||
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
|
||||
hx-get="{% url 'threshold_irc_network_relay_status' relay|index:'net' relay|index:'id' 1 %}"
|
||||
hx-target="#relays"
|
||||
hx-swap="outerHTML"
|
||||
class="button is-success is-small">
|
||||
<span class="icon" data-tooltip="Enable">
|
||||
<i class="fa-solid fa-wifi" aria-hidden="true"></i>
|
||||
</span>
|
||||
</button>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
|
|
|
@ -3,14 +3,7 @@ from django.views import View
|
|||
from rest_framework.parsers import FormParser
|
||||
from rest_framework.views import APIView
|
||||
|
||||
from core.lib.manage.threshold import (
|
||||
edit_irc_network,
|
||||
get_irc_channels,
|
||||
get_irc_network,
|
||||
get_irc_networks,
|
||||
get_irc_relays,
|
||||
get_irc_stats,
|
||||
)
|
||||
from core.lib.manage import threshold
|
||||
from core.views.manage.permissions import SuperUserRequiredMixin
|
||||
|
||||
|
||||
|
@ -18,7 +11,7 @@ class ThresholdIRCStats(SuperUserRequiredMixin, View):
|
|||
stats_template = "manage/threshold/irc/overview/stats.html"
|
||||
|
||||
def post(self, request):
|
||||
stats = get_irc_stats()
|
||||
stats = threshold.get_irc_stats()
|
||||
context = {"stats": stats}
|
||||
return render(request, self.stats_template, context)
|
||||
|
||||
|
@ -27,7 +20,7 @@ class ThresholdIRCNetworks(SuperUserRequiredMixin, View):
|
|||
template_name = "manage/threshold/irc/overview/networks.html"
|
||||
|
||||
def post(self, request):
|
||||
networks = get_irc_networks()
|
||||
networks = threshold.get_irc_networks()
|
||||
context = {"networks": networks}
|
||||
return render(request, self.template_name, context)
|
||||
|
||||
|
@ -36,7 +29,7 @@ class ThresholdIRCNetworkInfo(SuperUserRequiredMixin, View):
|
|||
template_name = "manage/threshold/irc/network/info.html"
|
||||
|
||||
def post(self, request, net):
|
||||
network = get_irc_network(net)
|
||||
network = threshold.get_irc_network(net)
|
||||
context = {"network": network}
|
||||
return render(request, self.template_name, context)
|
||||
|
||||
|
@ -49,7 +42,7 @@ class ThresholdIRCNetworkInfoEdit(SuperUserRequiredMixin, APIView):
|
|||
"""
|
||||
Return the form to edit a network.
|
||||
"""
|
||||
network = get_irc_network(net)
|
||||
network = threshold.get_irc_network(net)
|
||||
editable = ["auth", "host", "last", "port", "security"]
|
||||
context = {
|
||||
"net": net,
|
||||
|
@ -63,7 +56,7 @@ class ThresholdIRCNetworkInfoEdit(SuperUserRequiredMixin, APIView):
|
|||
Returns the info pane with a message about the success.
|
||||
"""
|
||||
template_name = "manage/threshold/irc/network/info.html"
|
||||
edited = edit_irc_network(net, request.data)
|
||||
edited = threshold.edit_irc_network(net, request.data)
|
||||
if edited["success"]:
|
||||
message = "Successfully edited!"
|
||||
message_class = "success"
|
||||
|
@ -73,7 +66,7 @@ class ThresholdIRCNetworkInfoEdit(SuperUserRequiredMixin, APIView):
|
|||
else:
|
||||
message = "Error editing network"
|
||||
message_class = "danger"
|
||||
network = get_irc_network(net)
|
||||
network = threshold.get_irc_network(net)
|
||||
context = {"network": network, "message": message, "class": message_class}
|
||||
return render(request, template_name, context)
|
||||
|
||||
|
@ -81,16 +74,105 @@ class ThresholdIRCNetworkInfoEdit(SuperUserRequiredMixin, APIView):
|
|||
class ThresholdIRCNetworkRelays(SuperUserRequiredMixin, View):
|
||||
template_name = "manage/threshold/irc/network/relays.html"
|
||||
|
||||
def post(self, request, net):
|
||||
relays = get_irc_relays(net)
|
||||
def get(self, request, net):
|
||||
relays = threshold.get_irc_relays(net)
|
||||
context = {"relays": relays["relays"]}
|
||||
return render(request, self.template_name, context)
|
||||
|
||||
|
||||
class ThresholdIRCNetworkChannels(SuperUserRequiredMixin, View):
|
||||
class ThresholdIRCNetworkRelayStatus(SuperUserRequiredMixin, APIView):
|
||||
template_name = "manage/threshold/irc/network/relays.html"
|
||||
|
||||
def get(self, request, net, num, status):
|
||||
"""
|
||||
Change the status of a relay.
|
||||
"""
|
||||
edited = threshold.change_network_status(net, num, status)
|
||||
if edited["success"]:
|
||||
message = "Successfully completed!"
|
||||
message_class = "success"
|
||||
else:
|
||||
if "reason" in edited:
|
||||
message = f"Error updating status: {edited['reason']}"
|
||||
else:
|
||||
message = "Error updating status"
|
||||
message_class = "danger"
|
||||
relays = threshold.get_irc_relays(net)
|
||||
context = {
|
||||
"relays": relays["relays"],
|
||||
"message": message,
|
||||
"class": message_class,
|
||||
}
|
||||
return render(request, self.template_name, context)
|
||||
|
||||
|
||||
class ThresholdIRCNetworkChannels(SuperUserRequiredMixin, APIView):
|
||||
"""
|
||||
List the channels a network is on.
|
||||
Allow parting and joining new ones.
|
||||
Re-render the same template if we join/part to make it simple.
|
||||
"""
|
||||
|
||||
template_name = "manage/threshold/irc/network/channels.html"
|
||||
parser_classes = [FormParser]
|
||||
|
||||
def post(self, request, net):
|
||||
channels = get_irc_channels(net)
|
||||
context = {"channels": channels["channels"]}
|
||||
"""
|
||||
Get list of channels for network.
|
||||
:param net: network name
|
||||
"""
|
||||
channels = threshold.get_irc_channels(net)
|
||||
context = {"net": net, "channels": channels["channels"]}
|
||||
return render(request, self.template_name, context)
|
||||
|
||||
def delete(self, request, net, channel):
|
||||
"""
|
||||
Part a channel.
|
||||
:param net: network name
|
||||
:param channel: channel name
|
||||
"""
|
||||
parted = threshold.part_channel(net, channel)
|
||||
if parted:
|
||||
message = f"Requested part on relays: {', '.join(parted['relays'])}"
|
||||
message_class = "success"
|
||||
else:
|
||||
message = parted["reason"]
|
||||
message_class = "danger"
|
||||
|
||||
channels = threshold.get_irc_channels(net)
|
||||
context = {
|
||||
"net": net,
|
||||
"channels": channels["channels"],
|
||||
"message": message,
|
||||
"class": message_class,
|
||||
}
|
||||
return render(request, self.template_name, context)
|
||||
|
||||
def put(self, request, net):
|
||||
"""
|
||||
Join a channel.
|
||||
:param net: network name
|
||||
"""
|
||||
if "channel" not in request.data:
|
||||
message = "No channel specified"
|
||||
message_class = "danger"
|
||||
else:
|
||||
channel = request.data["channel"]
|
||||
print("CHANNEL", channel)
|
||||
joined = threshold.join_channel(net, channel)
|
||||
print("JOINED", joined)
|
||||
if joined:
|
||||
message = f"Requested join on relay: {joined['relays']}"
|
||||
message_class = "success"
|
||||
else:
|
||||
message = joined["reason"]
|
||||
message_class = "danger"
|
||||
|
||||
channels = threshold.get_irc_channels(net)
|
||||
context = {
|
||||
"net": net,
|
||||
"channels": channels["channels"],
|
||||
"message": message,
|
||||
"class": message_class,
|
||||
}
|
||||
return render(request, self.template_name, context)
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
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 django.http import HttpResponse, HttpResponseForbidden, JsonResponse
|
||||
from rest_framework.parsers import FormParser
|
||||
from rest_framework.views import APIView
|
||||
import json
|
||||
|
||||
from core.lib.opensearch import query_results
|
||||
|
||||
|
||||
from core.lib.threshold import (
|
||||
annotate_num_chans,
|
||||
annotate_num_users,
|
||||
|
@ -16,6 +16,7 @@ from core.lib.threshold import (
|
|||
get_users,
|
||||
)
|
||||
|
||||
|
||||
class Drilldown(LoginRequiredMixin, View):
|
||||
template_name = "ui/drilldown/drilldown.html"
|
||||
plan_name = "drilldown"
|
||||
|
@ -28,6 +29,7 @@ class Drilldown(LoginRequiredMixin, View):
|
|||
}
|
||||
return render(request, self.template_name, context)
|
||||
|
||||
|
||||
class DrilldownSearch(LoginRequiredMixin, View):
|
||||
# parser_classes = [JSONParser]
|
||||
template_name = "ui/drilldown/results.html"
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
from ast import literal_eval
|
||||
|
||||
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 django.http import HttpResponse, HttpResponseForbidden, JsonResponse
|
||||
|
||||
from rest_framework.views import APIView
|
||||
|
||||
from core.lib.meta import get_meta
|
||||
from core.lib.nicktrace import get_nicks
|
||||
from core.lib.opensearch import query_single_result
|
||||
|
@ -15,7 +17,6 @@ from core.lib.threshold import (
|
|||
get_chans,
|
||||
get_users,
|
||||
)
|
||||
from ast import literal_eval
|
||||
|
||||
|
||||
class Insights(LoginRequiredMixin, View):
|
||||
|
@ -27,6 +28,7 @@ class Insights(LoginRequiredMixin, View):
|
|||
return render(request, "denied.html")
|
||||
return render(request, self.template_name)
|
||||
|
||||
|
||||
class InsightsSearch(LoginRequiredMixin, View):
|
||||
# parser_classes = [JSONParser]
|
||||
template_name = "ui/insights/info.html"
|
||||
|
|
Loading…
Reference in New Issue