Skip to content

[DRAFT] Adds serverlist api #93

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions src/serverlist/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from datetime import timedelta

from django.db import models
from django.utils import timezone


class Server(models.Model):
name = models.CharField(max_length=100)
ip_address = models.CharField(max_length=50)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maximum length of a domain part is 63 characters, and an entire FQDN is 253. 50 could un-necessarily limit domains being used.

For example, cpee0dbd14eedcc-cme0dbd14eedca.cpe.net.cable.rogers.com is a real hostname (I found on Google) that measures >50 chars.

port = models.IntegerField()
player_count = models.IntegerField()
player_limit = models.IntegerField()
image_link = models.URLField()
round_time = models.TimeField()
windows_build = models.URLField()
linux_build = models.URLField()
mac_build = models.URLField()
build_version = models.CharField(max_length=16)
code_scan_version = models.CharField(max_length=16)
## TODO: ADD VALIDATION FOR APPROVED API KEYS SO THAT STRANGERS DONT SPAM STATIONHUB WITH INVALID SERVERS ##

def __str__(self):
return self.name

def save(self, *args, **kwargs):
self.updated_at = timezone.now()
super().save(*args, **kwargs)

def is_expired(self):
expiration_time = self.updated_at + timedelta(seconds=10)
return expiration_time < timezone.now()
7 changes: 7 additions & 0 deletions src/serverlist/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from django.urls import path

from .views import server_list

urlpatterns = [
path("serverlist/", server_list, name="server_list"),
]
110 changes: 110 additions & 0 deletions src/serverlist/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import json

from datetime import datetime

from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt

from .models import Server


def server_list(request):
servers = Server.objects.all()
data = []
## TODO: ADD VALIDATION FOR APPROVED API KEYS SO THAT STRANGERS DONT SPAM STATIONHUB WITH INVALID SERVERS ##
for server in servers:
if server.is_expired():
server.delete()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems expensive to delete each one separately
Can it be done in 1 operation?
I also suspect race condition is present. Imagine 2 requests coming in at the same time. Both connections try deleting same server. will it error?

else:
data.append(
{
"name": server.name,
"ip_address": server.ip_address,
"port": server.port,
"player_count": server.player_count,
"image_link": server.image_link,
}
)
return JsonResponse(data, safe=False)


@csrf_exempt
def add_server(request):
if request.method != "POST":
return JsonResponse({"error": "Only POST requests are allowed"}, status=405)
try:
server_validation = validate_server_info(request)
if server_validation.status_code != 200:
return server_validation
data = json.loads(request.body)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

django doesn't have ability to create model from json? weird code

name = data.get("name")
ip_address = data.get("ip_address")
port = data.get("port")
player_count = data.get("player_count")
player_limit = data.get("player_limit")
image_link = data.get("image_link")
windows_build = data.get("player_count")
linux_build = data.get("player_count")
mac_build = data.get("player_count")
build_version = data.get("player_count")
code_scan_version = data.get("player_count")

existing_server = Server.objects.filter(name=name).first()
if existing_server:
# In case the server updates its info quickly before the 10 seconds pass,
# we update everything while we're updating the experitation date as well
existing_server.ip_address = ip_address
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is wrong because .get() can return None

existing_server.port = port
existing_server.player_count = player_count
existing_server.player_limit = player_limit
existing_server.image_link = image_link
existing_server.windows_build = windows_build
existing_server.linux_build = linux_build
existing_server.mac_build = mac_build
existing_server.build_version = build_version
existing_server.code_scan_version = code_scan_version
existing_server.updated_at = datetime.now()
existing_server.save()
else:
Server.objects.create(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will error because .get() can return None

name=name,
ip_address=ip_address,
port=port,
player_count=player_count,
image_link=image_link,
updated_at=datetime.now(),
)
return JsonResponse({"success": "Server data added/updated successfully"}, status=200)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you don't need this json body

except Exception as e:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

enormous kilometer wide try block

return JsonResponse({"error": str(e)}, status=400)


def validate_server_info(request):
data = json.loads(request.body)
name = data.get("name")
ip_address = data.get("ip_address")
port = data.get("port")
windows_build = data.get("player_count")
linux_build = data.get("player_count")
mac_build = data.get("player_count")
build_version = data.get("player_count")
code_scan_version = data.get("player_count")

if name is None or ip_address is None or port is None:
return JsonResponse(
{
"error": "Identifying server info are required, otherwise the server will not show up or be connectable on stationhub."
},
status=400,
)

if (
windows_build is None
or linux_build is None
or mac_build is None
or build_version is None
or code_scan_version is None
):
return JsonResponse({"error": "Missing build information."}, status=400)

return JsonResponse({"success": "Server info validated successfully"}, status=200)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you don't need this json body

Loading