Skip to content

Commit 5235372

Browse files
authored
Merge pull request #157 from Design0r/master
added live channel api endpoint and moved legacy widget to api module
2 parents c3c3894 + ef72e07 commit 5235372

8 files changed

+309
-174
lines changed

spybot/api.py

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
from django.http.request import HttpRequest
2+
from django.http.response import JsonResponse
3+
4+
from spybot.schemas import LiveResponse, TSChannelSchema, TSUserSchema
5+
6+
from .models import TSChannel, TSUserActivity
7+
8+
9+
def widget_legacy(request: HttpRequest) -> JsonResponse:
10+
sessions = TSUserActivity.objects.filter(end_time=None)
11+
12+
active_clients: list[str] = []
13+
inactive_clients: list[str] = []
14+
for session in sessions:
15+
user_name = session.tsuser.name
16+
channel_name = session.channel.name
17+
if channel_name == "bei Bedarf anstupsen" or channel_name == "AFK":
18+
inactive_clients.append(user_name)
19+
else:
20+
active_clients.append(user_name)
21+
22+
res = {"activeClients": active_clients, "inactiveClients": inactive_clients}
23+
return JsonResponse(res)
24+
25+
26+
def live_api(request: HttpRequest) -> JsonResponse:
27+
channels: list[TSChannelSchema] = [
28+
{"id": c.id, "name": c.name} for c in TSChannel.objects.order_by("order")
29+
]
30+
sessions = TSUserActivity.objects.filter(end_time=None)
31+
32+
clients: list[TSUserSchema] = [
33+
{"channel_id": s.channel.id, "name": s.tsuser.name} for s in sessions
34+
]
35+
36+
res: LiveResponse = {"clients": clients, "channels": channels}
37+
return JsonResponse(res)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Generated by Django 5.1.6 on 2025-02-20 17:47
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('spybot', '0002_alter_loginlink_code'),
10+
]
11+
12+
operations = [
13+
migrations.RenameIndex(
14+
model_name='hourlyactivity',
15+
new_name='hourlyactiv_datetim_4aadb3_idx',
16+
old_name='HourlyActiv_datetim_96f0af_idx',
17+
),
18+
migrations.RenameIndex(
19+
model_name='tsuseractivity',
20+
new_name='tsuseractiv_startti_ebb367_idx',
21+
old_name='TSUserActiv_startTi_95ea75_idx',
22+
),
23+
migrations.AlterField(
24+
model_name='tschannel',
25+
name='id',
26+
field=models.AutoField(primary_key=True, serialize=False),
27+
),
28+
migrations.AlterField(
29+
model_name='tsuseractivity',
30+
name='id',
31+
field=models.AutoField(primary_key=True, serialize=False),
32+
),
33+
]

spybot/models.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ def __str__(self):
3636

3737

3838
class TSChannel(DebuggableModel):
39-
id = models.PositiveIntegerField(primary_key=True)
39+
id = models.AutoField(primary_key=True)
4040
name = models.CharField(max_length=64, blank=True, null=True)
4141
order = models.PositiveIntegerField(null=False)
4242

spybot/schemas.py

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
from typing import TypedDict
2+
3+
4+
class TSChannelSchema(TypedDict):
5+
id: int
6+
name: str
7+
8+
9+
class TSUserSchema(TypedDict):
10+
name: str
11+
channel_id: int
12+
13+
14+
class LiveResponse(TypedDict):
15+
clients: list[TSUserSchema]
16+
channels: list[TSChannelSchema]
17+
18+
19+
class UserChannelSchema(TypedDict):
20+
channel_id: int
21+
name: str

spybot/tests/test_api.py

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import json
2+
3+
from django.http.request import HttpRequest
4+
from django.test import TestCase
5+
6+
from spybot.api import live_api, widget_legacy
7+
from spybot.models import TSChannel, TSUser, TSUserActivity
8+
9+
10+
class ApiTestCase(TestCase):
11+
def setUp(self):
12+
user_a = TSUser.objects.create(name="userA", client_id=1, online=False)
13+
user_b = TSUser.objects.create(name="userB", client_id=2, online=False)
14+
15+
channel_a = TSChannel.objects.create(name="channelA", order=1)
16+
channel_b = TSChannel.objects.create(name="AFK", order=2)
17+
18+
TSUserActivity.objects.create(tsuser=user_a, channel=channel_a, end_time=None)
19+
TSUserActivity.objects.create(tsuser=user_b, channel=channel_b, end_time=None)
20+
21+
def test_legacy_widget(self):
22+
result = widget_legacy(HttpRequest())
23+
data = json.loads(result.content)
24+
25+
self.assertEqual(data["activeClients"], ["userA"])
26+
assert data["inactiveClients"] == ["userB"]
27+
28+
def test_live_view(self):
29+
result = live_api(HttpRequest())
30+
data = json.loads(result.content)
31+
32+
self.assertEqual(
33+
data,
34+
{
35+
"clients": [
36+
{"channel_id": 3, "name": "userA"},
37+
{"channel_id": 4, "name": "userB"},
38+
],
39+
"channels": [{"id": 3, "name": "channelA"}, {"id": 4, "name": "AFK"}],
40+
},
41+
)

spybot/urls.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
from django.urls import path
22

33
from .auth import auth
4+
from . import api
45
from .auth import passkeys
56
from .views import views
67
from .views.fragments import activity_chart
78

89
urlpatterns = [
910
path('live/', views.live, name='live'),
1011
path('', views.home, name='home'),
11-
path('widget_legacy', views.widget_legacy, name='widget_legacy'),
1212
path('timeline', views.timeline, name='timeline'),
1313
path('halloffame', views.halloffame, name='halloffame'),
1414
path('u/<int:user_id>', views.user, name='user'),
@@ -28,5 +28,10 @@
2828
path('passkeys/generate-registration-options', passkeys.generate_registration_options, name='passkeys_generate-registration-options'),
2929
path('passkeys/verify-registration', passkeys.verify_registration, name='passkeys_verify-registration'),
3030
path('passkeys/verify-authentication', passkeys.verify_authentication, name='passkeys_verify-authentication'),
31+
32+
# API
33+
path('api/v1/live', api.live_api, name='live_api'),
34+
path('api/v1/widget', api.widget_legacy, name='widget_api'),
35+
path('widget_legacy', api.widget_legacy, name='widget_legacy'),
3136
]
3237

spybot/views/views.py

+13-27
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,24 @@
55

66
from django.contrib.auth.decorators import login_required
77
from django.db.models import Q
8-
from django.http import JsonResponse, HttpResponse, Http404, HttpResponseForbidden
9-
from django.shortcuts import render, get_object_or_404
8+
from django.http import HttpResponse, HttpResponseForbidden
9+
from django.shortcuts import get_object_or_404, render
1010
from django.utils import timezone
1111

1212
from spybot import visualization
13-
14-
from spybot.forms import TimeRangeForm, AddSteamIDForm
13+
from spybot.forms import AddSteamIDForm, TimeRangeForm
14+
from spybot.models import (
15+
MergedUser,
16+
NewsEvent,
17+
SteamID,
18+
TSChannel,
19+
TSUserActivity,
20+
UserPasskey,
21+
)
1522
from spybot.remote.steam_api import get_steam_user_playing_info
16-
from spybot.views.fragments.activity_chart import activity_chart_data
17-
from spybot.models import TSChannel, TSUserActivity, NewsEvent, MergedUser, UserPasskey, SteamID
1823
from spybot.templatetags import ts_filters
19-
20-
from Spybot2 import settings
21-
import requests
22-
23-
from spybot.views.common import get_user, get_context
24+
from spybot.views.common import get_context, get_user
25+
from spybot.views.fragments.activity_chart import activity_chart_data
2426
from spybot.views.fragments.profile_steamids import profile_steamids_data
2527

2628

@@ -97,22 +99,6 @@ def live(request):
9799
return render(request, 'spybot/live.html', {'clients': clients, 'channels': channels})
98100

99101

100-
def widget_legacy(request):
101-
sessions = TSUserActivity.objects.filter(end_time=None)
102-
103-
active_clients = []
104-
inactive_clients = []
105-
res = {}
106-
for session in sessions:
107-
user_name = session.tsuser.name
108-
channel_name = session.channel.name
109-
if channel_name == "bei Bedarf anstupsen" or channel_name == "AFK":
110-
inactive_clients.append(user_name)
111-
else:
112-
active_clients.append(user_name)
113-
res["activeClients"] = active_clients
114-
res["inactiveClients"] = inactive_clients
115-
return JsonResponse(res)
116102

117103

118104
def timeline(request):

0 commit comments

Comments
 (0)