diff --git a/forms.py b/forms.py new file mode 100644 index 0000000..5cbd740 --- /dev/null +++ b/forms.py @@ -0,0 +1,233 @@ +from django_coreprotect.models import * + + +class Form: + + def __init__(self): + self.block_break = False + self.block_place = False + self.chat = False + self.chest_use = False + self.command = False + self.interact = False + self.login_logout = False + self.sign_place = False + self.worlds = [] + self.ignore_environment = False + self.page = "" + self.page_size = "" + self.start = "" + self.players = "" + self.x = "" + self.y = "" + self.z = "" + self.radius = "" + self.blocks = "" + self.date_from = "" + 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): + request_data = request.GET + form = Form() + worlds = CoWorld.objects.all() + + # Actions + form.block_break = checkbox(request_data["block_break"]) if "block_break" in request_data else False + form.block_place = checkbox(request_data["block_place"]) if "block_place" in request_data else False + form.chat = checkbox(request_data["chat"]) if "chat" in request_data else False + form.chest_use = checkbox(request_data["chest_use"]) if "chest_use" in request_data else False + form.command = checkbox(request_data["command"]) if "command" in request_data else False + form.interact = checkbox(request_data["interact"]) if "interact" in request_data else False + form.login_logout = checkbox(request_data["login_logout"]) if "login_logout" in request_data else False + form.sign_place = checkbox(request_data["sign_place"]) if "sign_place" in request_data else False + + # Permissions + if not request.user.has_perm("django_coreprotect.gui_extra"): + form.chat = False + form.command = False + + # Worlds + request_worlds = request_data.getlist("world") + for world in worlds: + world_id = "world_{}".format(world.id) + w = { + "id": str(world.id), + "world_id": world_id, + "checked": True if str(world.id) in request_worlds else False, + "name": world.world + } + form.worlds.append(w) + + # Options + form.ignore_environment = checkbox(request_data["ignore_environment"]) if "ignore_environment" in request_data else False + + # Limit Results + form.page = request_data["page"] if "page" in request_data else "0" + form.page_size = request_data["page_size"] if "page_size" in request_data else "20" + if safe_int(form.page_size) == 0 or safe_int(form.page_size) > 1000: + form.page_size = "1000" + form.start = (safe_int(form.page) * safe_int(form.page_size)) + + # Players + form.players = request_data["players"] if "players" in request_data else "" + + # Coordinates + form.x = request_data["x"] if "x" in request_data else "" + form.y = request_data["y"] if "y" in request_data else "" + form.z = request_data["z"] if "z" in request_data else "" + form.radius = request_data["radius"] if "radius" in request_data else "" + + # Blocks + form.blocks = request_data["blocks"] if "blocks" 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 result_data(form): + queries = [] + ignore_environment = " AND player NOT LIKE '#%' " if form.ignore_environment else "" + + coords = [] + radius = form.radius if form.radius else "0" + if form.x: + coords.append(" AND x BETWEEN {0} - {1} AND {0} + {1}".format(form.x, radius)) + if form.y: + coords.append(" AND y BETWEEN {0} - {1} AND {0} + {1}".format(form.y, radius)) + if form.z: + coords.append(" AND z BETWEEN {0} - {1} AND {0} + {1}".format(form.z, radius)) + coords_clause = " AND ".join(coords) + + players = [] + players_clause = "" + if form.players: + for player in form.players.split(","): + players.append(player.strip()) + players_clause = " AND ({})".format(" OR ".join(["player LIKE '%{}%'".format(p) for p in players])) + + worlds_clause = "" + worlds = [world["id"] for world in form.worlds if world["checked"]] + if len(worlds): + worlds_clause = " AND cw.id IN ({})".format(",".join(worlds)) + + time_clause = "" + if form.date_from or form.date_to: + df, dt = form.date_from, form.date_to + if form.date_from and not form.date_to: + dt = datetime.now().timestamp() + if form.date_to and not form.date_from: + df = datetime.now().timestamp() + time_clause = " AND unix BETWEEN {} AND {} ".format(df, dt) + + # Block Break, Block Place, and Interact + block_actions = [] + if form.block_break: + block_actions.append("0") + if form.block_place: + block_actions.append("1") + if form.interact: + block_actions.append("2") + if len(block_actions): + queries.append('''SELECT + 0 AS id, "block" AS type, cb.time AS unix, cu.user AS player, cb.action, cmm.material AS data, cb.x, cb.y, cb.z, cw.world + FROM co_block cb + JOIN co_user cu ON cb.user = cu.id + JOIN co_material_map cmm ON cb.type = cmm.id + JOIN co_world cw ON cb.wid = cw.id + WHERE cb.action IN ({action}) + {ignore_environment} + {players} + {coords} + {worlds} + {time} + '''.format(action=",".join(block_actions), ignore_environment=ignore_environment, players=players_clause, + coords=coords_clause, worlds=worlds_clause, time=time_clause)) + + # Chat + if form.chat: + queries.append('''SELECT + 0 AS id, "chat" AS type, cc.time AS unix, cu.user AS player, "" AS action, cc.message AS data, "" AS x, "" AS y, "" AS z, "" AS world + FROM co_chat cc + JOIN co_user cu ON cc.user = cu.id + WHERE 1 = 1 + {players} + {time} + '''.format(players=players_clause, time=time_clause)) + + # Chest Use + if form.chest_use: + queries.append('''SELECT + 0 AS id, "container" AS type, cc.time AS unix, cu.user AS player, cc.action, cc.amount || " " || cmm.material AS data, cc.x, cc.y, cc.z, cw.world + FROM co_container cc + JOIN co_user cu ON cc.user = cu.id + JOIN co_material_map cmm ON cc.type = cmm.id + JOIN co_world cw ON cc.wid = cw.id + WHERE 1 = 1 + {worlds} + {players} + {coords} + {time} + '''.format(worlds=worlds_clause, players=players_clause, coords=coords_clause, time=time_clause)) + + # Commands + if form.command: + queries.append('''SELECT + 0 AS id, "command" AS type, cc.time AS unix, cu.user AS player, "" AS action, cc.message AS data, "" AS x, "" AS y, "" AS z, "" AS world + FROM co_command cc + JOIN co_user cu ON cc.user = cu.id + WHERE 1 = 1 + {players} + {coords} + {time} + '''.format(players=players_clause, coords=coords_clause, time=time_clause)) + + # Login/Logout + if form.login_logout: + queries.append('''SELECT + 0 AS id, "session" AS type, cs.time AS unix, cu.user AS player, cs.action, "" AS data, cs.x, cs.y, cs.z, cw.world + FROM co_session cs + JOIN co_user cu ON cs.user = cu.id + JOIN co_world cw ON cs.wid = cw.id + WHERE 1 = 1 + {worlds} + {players} + {coords} + {time} + '''.format(worlds=worlds_clause, players=players_clause, coords=coords_clause, time=time_clause)) + + # Sign Place + if form.sign_place: + queries.append('''SELECT + 0 AS id, "sign" AS type, cs.time AS unix, cu.user AS player, "" AS action, cs.line_1 || "|" || cs.line_2 || "|" || cs.line_3 || "|" || cs.line_4 AS data, cs.x, cs.y, cs.z, cw.world + FROM co_sign cs + JOIN co_user cu ON cs.user = cu.id + JOIN co_world cw ON cs.wid = cw.id + WHERE 1 = 1 + {worlds} + {players} + {coords} + {time} + '''.format(worlds=worlds_clause, players=players_clause, coords=coords_clause, time=time_clause)) + + query = " UNION ".join(queries) + if query: + query += " ORDER BY unix DESC LIMIT {}, {}".format(form.start, form.page_size) + print(query) + if query: + return CoResult.objects.raw(query) + return [] \ No newline at end of file diff --git a/migrations/0001_initial.py b/migrations/0001_initial.py new file mode 100644 index 0000000..a90384b --- /dev/null +++ b/migrations/0001_initial.py @@ -0,0 +1,322 @@ +# 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 5a3cbee..699dd3a 100644 --- a/models.py +++ b/models.py @@ -8,9 +8,9 @@ class CoreProtectUser(User): class Meta: proxy = True permissions = ( - ('coreprotect_base', 'Can use CoreProtect GUI'), - ('coreprotect_extra', 'Can search Chat/Commands'), - ('coreprotect_activity', 'Can use CoreProtect Activity Monitor'), + ('gui', 'Can use CoreProtect GUI'), + ('gui_extra', 'Can search Chat/Commands'), + ('activity', 'Can use CoreProtect Activity Monitor'), ) diff --git a/templates/coreprotect/coreprotect.html b/templates/coreprotect/coreprotect.html index 01d3ca1..49bc6ea 100644 --- a/templates/coreprotect/coreprotect.html +++ b/templates/coreprotect/coreprotect.html @@ -38,7 +38,7 @@
- +
@@ -46,7 +46,7 @@
- +
@@ -197,27 +197,39 @@ let url = new URL(window.location); let pageParam = url.searchParams.get("page"); - let page = 1; + let page = 0; if (pageParam !== "") { page = parseInt(pageParam); if (isNaN(page)) { - page = 1; + page = 0; } } function attachPagination() { - document.getElementById("prev").addEventListener("click", function() { - document.getElementById("page").value = (page-1).toString(); - document.getElementById("search").click(); - }); - document.getElementById("next").addEventListener("click", function() { - document.getElementById("page").value = (page+1).toString(); - document.getElementById("search").click(); - }); + let prev = document.getElementById("prev"); + if (prev.getAttribute("disabled") == null) { + prev.addEventListener("click", function () { + document.getElementById("page").value = (--page).toString(); + search(false); + }); + } + + let next = document.getElementById("next"); + if (next.getAttribute("disabled") == null) { + next.addEventListener("click", function () { + document.getElementById("page").value = (++page).toString(); + search(false); + }); + } } - document.getElementById("search").addEventListener("click", function() { + function search(resetPage) { elementHTML("results", 'Querying Database...
'); + if (resetPage) { + page = 0; + document.getElementById("page").value = "0"; + } + let form = document.getElementById("coreprotect_form"); let formData = new FormData(form); ajax("GET", "{% url "coreprotect_query" %}?" + formURI(formData), function(status, data) { @@ -226,6 +238,10 @@ attachPagination(); }); window.history.pushState("", "", "{% url "coreprotect_index" %}?" + formURI(formData)); + } + + document.getElementById("search").addEventListener("click", function() { + search(true); }); document.getElementById("clear").addEventListener("click", function() { diff --git a/urls.py b/urls.py index f1167fc..43ace8b 100644 --- a/urls.py +++ b/urls.py @@ -3,6 +3,6 @@ from django.contrib.auth.decorators import permission_required from django_coreprotect.views import Home, Query urlpatterns = [ - path('', permission_required('coreprotect_base')(Home.as_view()), name="coreprotect_index"), - path('query/', permission_required('coreprotect_base')(Query.as_view()), name="coreprotect_query"), + path('', permission_required('django_coreprotect.gui')(Home.as_view()), name="coreprotect_index"), + path('query/', permission_required('django_coreprotect.gui')(Query.as_view()), name="coreprotect_query"), ] diff --git a/views.py b/views.py index 56d2324..29e6bfa 100644 --- a/views.py +++ b/views.py @@ -1,13 +1,13 @@ from django.shortcuts import render from django.views.generic import View from django.http.response import JsonResponse -from django_coreprotect.models import * +from django_coreprotect.forms import * class Home(View): def get(self, request): - form = form_data(request.GET) + form = form_data(request) return render(request, "coreprotect/coreprotect.html", {"form": form}) def post(self, request): @@ -17,243 +17,19 @@ class Home(View): class Query(View): def get(self, request): - form = form_data(request.GET) + form = form_data(request) results = result_data(form) if "format" in request.GET and request.GET["format"] == "json": return JsonResponse(results) prev_page, next_page = False, False - if form.page != "1": + if safe_int(form.page) > 0: prev_page = True - if int(form.page) * int(form.page_size) < 1000: + if len(results) == safe_int(form.page_size): next_page = True return render(request, "coreprotect/table.html", {"results": results, "num": len(results), "prev": prev_page, "next": next_page}) def post(self, request): pass - - -class Form: - - def __init__(self): - self.block_break = False - self.block_place = False - self.chat = False - self.chest_use = False - self.command = False - self.interact = False - self.login_logout = False - self.sign_place = False - self.worlds = [] - self.ignore_environment = False - self.page = "" - self.page_size = "" - self.start = "" - self.players = "" - self.x = "" - self.y = "" - self.z = "" - self.radius = "" - self.blocks = "" - self.date_from = "" - self.date_to = "" - - -def form_data(request_data): - form = Form() - worlds = CoWorld.objects.all() - - # Actions - form.block_break = checkbox(request_data["block_break"]) if "block_break" in request_data else False - form.block_place = checkbox(request_data["block_place"]) if "block_place" in request_data else False - form.chat = checkbox(request_data["chat"]) if "chat" in request_data else False - form.chest_use = checkbox(request_data["chest_use"]) if "chest_use" in request_data else False - form.command = checkbox(request_data["command"]) if "command" in request_data else False - form.interact = checkbox(request_data["interact"]) if "interact" in request_data else False - form.login_logout = checkbox(request_data["login_logout"]) if "login_logout" in request_data else False - form.sign_place = checkbox(request_data["sign_place"]) if "sign_place" in request_data else False - - # Worlds - request_worlds = request_data.getlist("world") - for world in worlds: - world_id = "world_{}".format(world.id) - w = { - "id": str(world.id), - "world_id": world_id, - "checked": True if str(world.id) in request_worlds else False, - "name": world.world - } - form.worlds.append(w) - - # Options - form.ignore_environment = checkbox(request_data["ignore_environment"]) if "ignore_environment" in request_data else False - - # Limit Results - form.page = request_data["page"] if "page" in request_data else "1" - form.page_size = request_data["page_size"] if "page_size" in request_data else "20" - if int(form.page_size) > 1000: - form.page_size = "1000" - start = (int(form.page) * int(form.page_size)) - form.start = str(start) if start <= 1000 - int(form.page_size) else str(1000 - int(form.page_size)) - - - # Players - form.players = request_data["players"] if "players" in request_data else "" - - # Coordinates - form.x = request_data["x"] if "x" in request_data else "" - form.y = request_data["y"] if "y" in request_data else "" - form.z = request_data["z"] if "z" in request_data else "" - form.radius = request_data["radius"] if "radius" in request_data else "" - - # Blocks - form.blocks = request_data["blocks"] if "blocks" 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 checkbox(value): - return True if value == "on" else False - - -def result_data(form): - queries = [] - ignore_environment = " AND player NOT LIKE '#%' " if form.ignore_environment else "" - - coords = [] - radius = form.radius if form.radius else "0" - if form.x: - coords.append(" AND x BETWEEN {0} - {1} AND {0} + {1}".format(form.x, radius)) - if form.y: - coords.append(" AND y BETWEEN {0} - {1} AND {0} + {1}".format(form.y, radius)) - if form.z: - coords.append(" AND z BETWEEN {0} - {1} AND {0} + {1}".format(form.z, radius)) - coords_clause = " AND ".join(coords) - - players = [] - players_clause = "" - if form.players: - for player in form.players.split(","): - players.append(player.strip()) - players_clause = " AND ({})".format(" OR ".join(["player LIKE '%{}%'".format(p) for p in players])) - - worlds_clause = "" - worlds = [world["id"] for world in form.worlds if world["checked"]] - if len(worlds): - worlds_clause = " AND cw.id IN ({})".format(",".join(worlds)) - - time_clause = "" - if form.date_from or form.date_to: - df, dt = None, None - if form.date_from and not form.date_to: - df = form.date_from - dt = datetime.now().timestamp() - if form.date_to and not form.date_from: - df = datetime.now().timestamp() - dt = form.date_to - time_clause = " AND unix BETWEEN {} AND {} ".format(df, dt) - - # Block Break, Block Place, and Interact - block_actions = [] - if form.block_break: - block_actions.append("0") - if form.block_place: - block_actions.append("1") - if form.interact: - block_actions.append("2") - if len(block_actions): - queries.append('''SELECT - 0 AS id, "block" AS type, cb.time AS unix, cu.user AS player, cb.action, cmm.material AS data, cb.x, cb.y, cb.z, cw.world - FROM co_block cb - JOIN co_user cu ON cb.user = cu.id - JOIN co_material_map cmm ON cb.type = cmm.id - JOIN co_world cw ON cb.wid = cw.id - WHERE cb.action IN ({action}) - {ignore_environment} - {players} - {coords} - {worlds} - {time} - '''.format(action=",".join(block_actions), ignore_environment=ignore_environment, players=players_clause, - coords=coords_clause, worlds=worlds_clause, time=time_clause)) - - # Chat - if form.chat: - queries.append('''SELECT - 0 AS id, "chat" AS type, cc.time AS unix, cu.user AS player, "" AS action, cc.message AS data, "" AS x, "" AS y, "" AS z, "" AS world - FROM co_chat cc - JOIN co_user cu ON cc.user = cu.id - WHERE 1 = 1 - {players} - {time} - '''.format(players=players_clause, time=time_clause)) - - # Chest Use - if form.chest_use: - queries.append('''SELECT - 0 AS id, "container" AS type, cc.time AS unix, cu.user AS player, cc.action, cc.amount || " " || cmm.material AS data, cc.x, cc.y, cc.z, cw.world - FROM co_container cc - JOIN co_user cu ON cc.user = cu.id - JOIN co_material_map cmm ON cc.type = cmm.id - JOIN co_world cw ON cc.wid = cw.id - WHERE 1 = 1 - {worlds} - {players} - {coords} - {time} - '''.format(worlds=worlds_clause, players=players_clause, coords=coords_clause, time=time_clause)) - - # Commands - if form.command: - queries.append('''SELECT - 0 AS id, "command" AS type, cc.time AS unix, cu.user AS player, "" AS action, cc.message AS data, "" AS x, "" AS y, "" AS z, "" AS world - FROM co_command cc - JOIN co_user cu ON cc.user = cu.id - WHERE 1 = 1 - {players} - {coords} - {time} - '''.format(players=players_clause, coords=coords_clause, time=time_clause)) - - # Login/Logout - if form.login_logout: - queries.append('''SELECT - 0 AS id, "session" AS type, cs.time AS unix, cu.user AS player, cs.action, "" AS data, cs.x, cs.y, cs.z, cw.world - FROM co_session cs - JOIN co_user cu ON cs.user = cu.id - JOIN co_world cw ON cs.wid = cw.id - WHERE 1 = 1 - {worlds} - {players} - {coords} - {time} - '''.format(worlds=worlds_clause, players=players_clause, coords=coords_clause, time=time_clause)) - - # Sign Place - if form.sign_place: - queries.append('''SELECT - 0 AS id, "sign" AS type, cs.time AS unix, cu.user AS player, "" AS action, cs.line_1 || "|" || cs.line_2 || "|" || cs.line_3 || "|" || cs.line_4 AS data, cs.x, cs.y, cs.z, cw.world - FROM co_sign cs - JOIN co_user cu ON cs.user = cu.id - JOIN co_world cw ON cs.wid = cw.id - WHERE 1 = 1 - {worlds} - {players} - {coords} - {time} - '''.format(worlds=worlds_clause, players=players_clause, coords=coords_clause, time=time_clause)) - - query = " UNION ".join(queries) - if query: - query += " ORDER BY unix LIMIT {}, {}".format(form.start, form.page_size) - print(query) - if query: - return CoResult.objects.raw(query) - return []