diff --git a/activity.py b/activity.py new file mode 100644 index 0000000..f9b27f1 --- /dev/null +++ b/activity.py @@ -0,0 +1,55 @@ +from django_coreprotect.models import SessionResult, ActivityResult +from django_coreprotect.utils import safe_int + + +class ActivityForm: + + def __init__(self): + self.players = "" + self.date_from = "" + self.date_to = "" + + +def activity_data(request): + request_data = request.GET + form = ActivityForm() + + # Players + form.players = request_data["players"] if "players" in request_data else "" + + # Date and Time + form.date_from = request_data["date_from"] if "date_from" in request_data else "" + form.date_to = request_data["date_to"] if "date_to" in request_data else "" + + return form + + +def activity_results(form): + query = "" + players = [] + if form.players: + for player in form.players.split(","): + players.append(player.strip()) + players_clause = " WHERE ({}) ".format(" OR ".join(["player LIKE '%{}%'".format(p) for p in players])) + query = '''SELECT + 0 AS id, cs.time AS unix, cu.user AS player, cs.action + FROM co_session cs + JOIN co_user cu ON cs.user = cu.id + {players} + '''.format(players=players_clause) + + if query: + print(query) + sessions = SessionResult.objects.raw(query) + activity = {} + for session in sessions: + time = -safe_int(session.unix) if session.action == 1 else safe_int(session.unix) + if session.player in activity: + activity[session.player] += time + else: + activity[session.player] = time + results = [] + for player, time in activity.items(): + results.append(ActivityResult(player, time)) + return results + return [] diff --git a/forms.py b/gui.py similarity index 93% rename from forms.py rename to gui.py index 5cbd740..c5b8bde 100644 --- a/forms.py +++ b/gui.py @@ -1,7 +1,9 @@ -from django_coreprotect.models import * +from django_coreprotect.models import CoWorld, GUIResult +from django_coreprotect.utils import safe_int, checkbox +from datetime import datetime -class Form: +class GUIForm: def __init__(self): self.block_break = False @@ -14,6 +16,7 @@ class Form: self.sign_place = False self.worlds = [] self.ignore_environment = False + self.oldest_first = False self.page = "" self.page_size = "" self.start = "" @@ -27,20 +30,9 @@ class Form: self.date_to = "" -def checkbox(value): - return True if value == "on" else False - - -def safe_int(value): - try: - return int(value) - except: - return 0 - - -def form_data(request): +def gui_data(request): request_data = request.GET - form = Form() + form = GUIForm() worlds = CoWorld.objects.all() # Actions @@ -72,6 +64,7 @@ def form_data(request): # Options form.ignore_environment = checkbox(request_data["ignore_environment"]) if "ignore_environment" in request_data else False + form.oldest_first = checkbox(request_data["oldest_first"]) if "oldest_first" in request_data else False # Limit Results form.page = request_data["page"] if "page" in request_data else "0" @@ -99,9 +92,10 @@ def form_data(request): return form -def result_data(form): +def gui_results(form): queries = [] ignore_environment = " AND player NOT LIKE '#%' " if form.ignore_environment else "" + oldest_first = " ASC " if form.oldest_first else " DESC " coords = [] radius = form.radius if form.radius else "0" @@ -226,8 +220,7 @@ def result_data(form): query = " UNION ".join(queries) if query: - query += " ORDER BY unix DESC LIMIT {}, {}".format(form.start, form.page_size) - print(query) + query += " ORDER BY unix {} LIMIT {}, {}".format(oldest_first, form.start, form.page_size) if query: - return CoResult.objects.raw(query) - return [] \ No newline at end of file + return GUIResult.objects.raw(query) + return [] diff --git a/migrations/0001_initial.py b/migrations/0001_initial.py deleted file mode 100644 index a90384b..0000000 --- a/migrations/0001_initial.py +++ /dev/null @@ -1,322 +0,0 @@ -# Generated by Django 2.2.3 on 2019-08-16 03:39 - -import django.contrib.auth.models -from django.db import migrations, models - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - ('auth', '0011_update_proxy_permissions'), - ] - - operations = [ - migrations.CreateModel( - name='CoArtMap', - fields=[ - ('id', models.IntegerField(primary_key=True, serialize=False)), - ('art', models.TextField(blank=True, null=True)), - ], - options={ - 'verbose_name': 'Art Map', - 'verbose_name_plural': 'Art Maps', - 'db_table': 'co_art_map', - 'managed': False, - }, - ), - migrations.CreateModel( - name='CoBlock', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('time', models.IntegerField(blank=True, null=True)), - ('user', models.IntegerField(blank=True, null=True)), - ('wid', models.IntegerField(blank=True, null=True)), - ('x', models.IntegerField(blank=True, null=True)), - ('y', models.IntegerField(blank=True, null=True)), - ('z', models.IntegerField(blank=True, null=True)), - ('type', models.IntegerField(blank=True, null=True)), - ('data', models.IntegerField(blank=True, null=True)), - ('meta', models.BinaryField(blank=True, null=True)), - ('blockdata', models.BinaryField(blank=True, null=True)), - ('action', models.IntegerField(blank=True, null=True)), - ('rolled_back', models.IntegerField(blank=True, null=True)), - ], - options={ - 'verbose_name': 'Block', - 'verbose_name_plural': 'Blocks', - 'db_table': 'co_block', - 'managed': False, - }, - ), - migrations.CreateModel( - name='CoBlockdataMap', - fields=[ - ('id', models.IntegerField(primary_key=True, serialize=False)), - ('data', models.TextField(blank=True, null=True)), - ], - options={ - 'verbose_name': 'BlockData Map', - 'verbose_name_plural': 'BlockData Maps', - 'db_table': 'co_blockdata_map', - 'managed': False, - }, - ), - migrations.CreateModel( - name='CoChat', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('time', models.IntegerField(blank=True, null=True)), - ('user', models.IntegerField(blank=True, null=True)), - ('message', models.TextField(blank=True, null=True)), - ], - options={ - 'verbose_name': 'Chat Message', - 'verbose_name_plural': 'Chat Messages', - 'db_table': 'co_chat', - 'managed': False, - }, - ), - migrations.CreateModel( - name='CoCommand', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('time', models.IntegerField(blank=True, null=True)), - ('user', models.IntegerField(blank=True, null=True)), - ('message', models.TextField(blank=True, null=True)), - ], - options={ - 'verbose_name': 'Command', - 'verbose_name_plural': 'Commands', - 'db_table': 'co_command', - 'managed': False, - }, - ), - migrations.CreateModel( - name='CoContainer', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('time', models.IntegerField(blank=True, null=True)), - ('user', models.IntegerField(blank=True, null=True)), - ('wid', models.IntegerField(blank=True, null=True)), - ('x', models.IntegerField(blank=True, null=True)), - ('y', models.IntegerField(blank=True, null=True)), - ('z', models.IntegerField(blank=True, null=True)), - ('type', models.IntegerField(blank=True, null=True)), - ('data', models.IntegerField(blank=True, null=True)), - ('amount', models.IntegerField(blank=True, null=True)), - ('metadata', models.BinaryField(blank=True, null=True)), - ('action', models.IntegerField(blank=True, null=True)), - ('rolled_back', models.IntegerField(blank=True, null=True)), - ], - options={ - 'verbose_name': 'Container Transaction', - 'verbose_name_plural': 'Container Transactions', - 'db_table': 'co_container', - 'managed': False, - }, - ), - migrations.CreateModel( - name='CoDatabaseLock', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('status', models.IntegerField(blank=True, null=True)), - ('time', models.IntegerField(blank=True, null=True)), - ], - options={ - 'verbose_name': 'Database Lock', - 'verbose_name_plural': 'Database Locks', - 'db_table': 'co_database_lock', - 'managed': False, - }, - ), - migrations.CreateModel( - name='CoEntity', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('time', models.IntegerField(blank=True, null=True)), - ('data', models.BinaryField(blank=True, null=True)), - ], - options={ - 'verbose_name': 'Entity', - 'verbose_name_plural': 'Entities', - 'db_table': 'co_entity', - 'managed': False, - }, - ), - migrations.CreateModel( - name='CoEntityMap', - fields=[ - ('id', models.IntegerField(primary_key=True, serialize=False)), - ('entity', models.TextField(blank=True, null=True)), - ], - options={ - 'verbose_name': 'Entity Mapping', - 'verbose_name_plural': 'Entity Mappings', - 'db_table': 'co_entity_map', - 'managed': False, - }, - ), - migrations.CreateModel( - name='CoMaterialMap', - fields=[ - ('id', models.IntegerField(primary_key=True, serialize=False)), - ('material', models.TextField(blank=True, null=True)), - ], - options={ - 'verbose_name': 'Material Mapping', - 'verbose_name_plural': 'Material Mappings', - 'db_table': 'co_material_map', - 'managed': False, - }, - ), - migrations.CreateModel( - name='CoResult', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('type', models.TextField()), - ('unix', models.TextField()), - ('player', models.TextField()), - ('action', models.TextField()), - ('data', models.TextField()), - ('x', models.TextField()), - ('y', models.TextField()), - ('z', models.TextField()), - ('world', models.TextField()), - ], - options={ - 'verbose_name': 'Result', - 'verbose_name_plural': 'Results', - 'managed': False, - }, - ), - migrations.CreateModel( - name='CoSession', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('time', models.IntegerField(blank=True, null=True)), - ('user', models.IntegerField(blank=True, null=True)), - ('wid', models.IntegerField(blank=True, null=True)), - ('x', models.IntegerField(blank=True, null=True)), - ('y', models.IntegerField(blank=True, null=True)), - ('z', models.IntegerField(blank=True, null=True)), - ('action', models.IntegerField(blank=True, null=True)), - ], - options={ - 'verbose_name': 'Session', - 'verbose_name_plural': 'Sessions', - 'db_table': 'co_session', - 'managed': False, - }, - ), - migrations.CreateModel( - name='CoSign', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('time', models.IntegerField(blank=True, null=True)), - ('user', models.IntegerField(blank=True, null=True)), - ('wid', models.IntegerField(blank=True, null=True)), - ('x', models.IntegerField(blank=True, null=True)), - ('y', models.IntegerField(blank=True, null=True)), - ('z', models.IntegerField(blank=True, null=True)), - ('color', models.IntegerField(blank=True, null=True)), - ('line_1', models.TextField(blank=True, null=True)), - ('line_2', models.TextField(blank=True, null=True)), - ('line_3', models.TextField(blank=True, null=True)), - ('line_4', models.TextField(blank=True, null=True)), - ], - options={ - 'verbose_name': 'Sign', - 'verbose_name_plural': 'Signs', - 'db_table': 'co_sign', - 'managed': False, - }, - ), - migrations.CreateModel( - name='CoSkull', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('time', models.IntegerField(blank=True, null=True)), - ('owner', models.TextField(blank=True, null=True)), - ], - options={ - 'verbose_name': 'Skull', - 'verbose_name_plural': 'Skulls', - 'db_table': 'co_skull', - 'managed': False, - }, - ), - migrations.CreateModel( - name='CoUser', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('time', models.IntegerField(blank=True, null=True)), - ('user', models.TextField(blank=True, null=True)), - ('uuid', models.TextField(blank=True, null=True)), - ], - options={ - 'verbose_name': 'User', - 'verbose_name_plural': 'Users', - 'db_table': 'co_user', - 'managed': False, - }, - ), - migrations.CreateModel( - name='CoUsernameLog', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('time', models.IntegerField(blank=True, null=True)), - ('uuid', models.TextField(blank=True, null=True)), - ('user', models.TextField(blank=True, null=True)), - ], - options={ - 'verbose_name': 'Username', - 'verbose_name_plural': 'Usernames', - 'db_table': 'co_username_log', - 'managed': False, - }, - ), - migrations.CreateModel( - name='CoVersion', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('time', models.IntegerField(blank=True, null=True)), - ('version', models.TextField(blank=True, null=True)), - ], - options={ - 'verbose_name': 'Version', - 'verbose_name_plural': 'Versions', - 'db_table': 'co_version', - 'managed': False, - }, - ), - migrations.CreateModel( - name='CoWorld', - fields=[ - ('id', models.IntegerField(primary_key=True, serialize=False)), - ('world', models.TextField(blank=True, null=True)), - ], - options={ - 'verbose_name': 'World', - 'verbose_name_plural': 'Worlds', - 'db_table': 'co_world', - 'managed': False, - }, - ), - migrations.CreateModel( - name='CoreProtectUser', - fields=[ - ], - options={ - 'permissions': (('gui', 'Can use CoreProtect GUI'), ('gui_extra', 'Can search Chat/Commands'), ('activity', 'Can use CoreProtect Activity Monitor')), - 'proxy': True, - 'indexes': [], - 'constraints': [], - }, - bases=('auth.user',), - managers=[ - ('objects', django.contrib.auth.models.UserManager()), - ], - ), - ] diff --git a/models.py b/models.py index 699dd3a..e50ec3b 100644 --- a/models.py +++ b/models.py @@ -1,6 +1,7 @@ from django.db import models from django.contrib.auth.models import User from datetime import datetime +from django_coreprotect.utils import safe_int class CoreProtectUser(User): @@ -290,7 +291,7 @@ class CoWorld(models.Model): return self.world -class CoResult(models.Model): +class GUIResult(models.Model): type = models.TextField() unix = models.TextField() player = models.TextField() @@ -338,5 +339,35 @@ class CoResult(models.Model): class Meta: managed = False - verbose_name = "Result" - verbose_name_plural = "Results" + verbose_name = "GUI Result" + verbose_name_plural = "GUI Results" + + +class SessionResult(models.Model): + unix = models.TextField() + player = models.TextField() + action = models.TextField() + + class Meta: + managed = False + verbose_name = "Session Result" + verbose_name_plural = "Session Results" + + +class ActivityResult: + + def __init__(self, player, time): + self.player = player + self.time = time + + @property + def time_display(self): + time = safe_int(self.time) + seconds = time % 60 + time //= 60 + minutes = time % 60 + time //= 60 + hours = time % 24 + time //= 24 + days = time + return "{}d, {}h, {}m, {}s".format(days, hours, minutes, seconds) diff --git a/static/coreprotect/css/main.css b/static/coreprotect/css/main.css index 4f12016..5283dee 100644 --- a/static/coreprotect/css/main.css +++ b/static/coreprotect/css/main.css @@ -1,3 +1,7 @@ .click-row { cursor: pointer; +} + +form { + margin-left: 7rem; } \ No newline at end of file diff --git a/static/coreprotect/img/intelli.png b/static/coreprotect/img/intelli.png new file mode 100644 index 0000000..043e470 Binary files /dev/null and b/static/coreprotect/img/intelli.png differ diff --git a/static/coreprotect/img/ymca.png b/static/coreprotect/img/ymca.png new file mode 100644 index 0000000..766142a Binary files /dev/null and b/static/coreprotect/img/ymca.png differ diff --git a/templates/coreprotect/activity.html b/templates/coreprotect/activity.html new file mode 100644 index 0000000..6443d9a --- /dev/null +++ b/templates/coreprotect/activity.html @@ -0,0 +1,84 @@ +{% extends "coreprotect/base.html" %} +{% load static %} +{% block head %} + +{% endblock %} +{% block body %} +
+Player | +Time | +
---|---|
{{ result.player }} | +{{ result.time_display }} | +