From f64c0419303b4309c067efe36914c6e79143d103 Mon Sep 17 00:00:00 2001 From: jolheiser Date: Sat, 12 Feb 2022 15:21:03 -0600 Subject: [PATCH] Python 3 changes, add LICENSE, update README Signed-off-by: jolheiser --- LICENSE | 7 ++++ README.md | 27 +++++++++++- activity.py | 15 +++---- gui.py | 116 +++++++++++++++++++++++++++------------------------- models.py | 8 ++-- tests.py | 3 -- urls.py | 3 +- utils.py | 9 ++-- views.py | 3 +- 9 files changed, 115 insertions(+), 76 deletions(-) create mode 100644 LICENSE delete mode 100644 tests.py diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8b9a29c --- /dev/null +++ b/LICENSE @@ -0,0 +1,7 @@ +Copyright 2021 John Olheiser + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md index bfe6e35..ce0568d 100644 --- a/README.md +++ b/README.md @@ -1 +1,26 @@ -# DjangoCoreProtect +# Django CoreProtect + +## Settings + +```python +INSTALLED_APPS = [ + 'django_coreprotect', +] + +DATABASE_ROUTERS = [ + 'django_coreprotect.router.CoreProtectRouter' +] +DATABASES = { + 'django_coreprotect': { + 'ENGINE': 'django.db.backends.mysql', + 'NAME': '...', + 'USER': '...', + 'PASSWORD': '...', + 'HOST': '127.0.0.1', + } +} +``` + +## License + +[MIT](LICENSE) \ No newline at end of file diff --git a/activity.py b/activity.py index 74a9865..9c1ca57 100644 --- a/activity.py +++ b/activity.py @@ -1,6 +1,7 @@ from django_coreprotect.models import SessionResult, ActivityResult from django_coreprotect.utils import safe_int from datetime import datetime +from typing import List class ActivityForm: @@ -25,7 +26,7 @@ def activity_data(request): return form -def activity_results(form): +def activity_results(form) -> List[ActivityResult]: query = "" players_clause = "" @@ -33,7 +34,8 @@ def activity_results(form): players = [] for player in form.players.split(","): players.append(player.strip()) - players_clause = " WHERE ({}) ".format(" OR ".join(["cu.user LIKE '%%{}%%'".format(p) for p in players])) + clause = " OR ".join([f"cu.user LIKE '%%{p}%%'" for p in players]) + players_clause = f" WHERE ({clause}) " time_clause = "" if form.date_from or form.date_to: @@ -45,16 +47,15 @@ def activity_results(form): time_clause = " HAVING unix BETWEEN {} AND {} ".format(df, dt) if players_clause or time_clause: - query = '''SELECT + query = f'''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.rowid - {players} - {time} - '''.format(players=players_clause, time=time_clause) + {players_clause} + {time_clause} + ''' if query: - print(query) sessions = SessionResult.objects.raw(query) activity = {} last_session = {} diff --git a/gui.py b/gui.py index e81d85a..87ee154 100644 --- a/gui.py +++ b/gui.py @@ -1,6 +1,8 @@ from datetime import datetime from django.db import connection +from django.db.models.query import RawQuerySet +from django.http import HttpRequest from django_coreprotect.models import CoWorld, GUIResult from django_coreprotect.utils import safe_int, checkbox, time_to_form @@ -33,7 +35,7 @@ class GUIForm: self.date_to = "" -def gui_data(request): +def gui_data(request: HttpRequest) -> GUIForm: request_data = request.GET form = GUIForm() worlds = CoWorld.objects.all() @@ -56,7 +58,7 @@ def gui_data(request): # Worlds request_worlds = request_data.getlist("world") for world in worlds: - world_id = "world_{}".format(world.id) + world_id = f"world_{world.id}" w = { "id": str(world.id), "world_id": world_id, @@ -99,7 +101,7 @@ def gui_data(request): return form -def gui_results(form): +def gui_results(form: GUIForm) -> RawQuerySet: queries = [] ignore_environment = " AND cu.user NOT LIKE '#%%' " if form.ignore_environment else "" oldest_first = " ASC " if form.oldest_first else " DESC " @@ -107,21 +109,23 @@ def gui_results(form): coords = [] radius = form.radius if form.radius else "0" if form.x: - coords.append(" x BETWEEN {0} - {1} AND {0} + {1}".format(form.x, radius)) + coords.append(f" x BETWEEN {form.x} - {radius} AND {form.x} + {radius}") if form.y: - coords.append(" y BETWEEN {0} - {1} AND {0} + {1}".format(form.y, radius)) + coords.append(f" y BETWEEN {form.y} - {radius} AND {form.y} + {radius}") if form.z: - coords.append(" z BETWEEN {0} - {1} AND {0} + {1}".format(form.z, radius)) + coords.append(f" z BETWEEN {form.z} - {radius} AND {form.z} + {radius}") coords_clause = "" if coords: - coords_clause = " AND ({})".format(" AND ".join(coords)) + clause = " AND ".join(coords) + coords_clause = f" AND ({clause})" players = [] players_clause = "" if form.players: for player in form.players.split(","): players.append(player.strip()) - players_clause = " AND ({})".format(" OR ".join(["cu.user LIKE '{}%%'".format(p) for p in players])) + clause = " OR ".join([f"cu.user LIKE '{p}%%'" for p in players]) + players_clause = f" AND ({clause})" blocks = [] blocks_clause = "" @@ -130,14 +134,18 @@ def gui_results(form): if form.blocks: for block in form.blocks.split(","): blocks.append(block.strip()) - blocks_clause = " AND ({})".format(" OR ".join(["cmm.material LIKE 'minecraft:{}%%'".format(b) for b in blocks])) - chat_clause = " AND ({})".format(" OR ".join(["cc.message LIKE '%%{}%%'".format(b) for b in blocks])) - command_clause = " AND ({})".format(" OR ".join(["cc.message LIKE '%%{}%%'".format(b) for b in blocks])) + clause = " OR ".join([f"cmm.material LIKE 'minecraft:{b}%%'" for b in blocks]) + blocks_clause = f" AND ({clause})" + clause = " OR ".join([f"cc.message LIKE '%%{b}%%'" for b in blocks]) + chat_clause = f" AND ({clause})" + clause = " OR ".join([f"cc.message LIKE '%%{b}%%'" for b in blocks]) + command_clause = f" AND ({clause})" worlds_clause = "" worlds = [world["id"] for world in form.worlds if world["checked"]] if len(worlds): - worlds_clause = " AND cw.rowid IN ({})".format(",".join(worlds)) + clause = ",".join(worlds) + worlds_clause = f" AND cw.rowid IN ({clause})" time_clause = "" if form.date_from or form.date_to: @@ -146,7 +154,7 @@ def gui_results(form): dt = datetime.now().timestamp() if form.date_to and not form.date_from: df = datetime.now().timestamp() - time_clause = " GROUP BY unix HAVING unix BETWEEN {} AND {} ".format(df, dt) + time_clause = f" GROUP BY unix HAVING unix BETWEEN {df} AND {dt} " # Block Break, Block Place, and Interact block_actions = [] @@ -157,97 +165,95 @@ def gui_results(form): if form.interact: block_actions.append("2") if len(block_actions): - queries.append('''SELECT + queries.append(f'''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.rowid JOIN co_material_map cmm ON cb.type = cmm.rowid JOIN co_world cw ON cb.wid = cw.rowid - WHERE cb.action IN ({action}) + WHERE cb.action IN ({",".join(block_actions)}) {ignore_environment} - {players} - {coords} - {blocks} - {worlds} - {time} - '''.format(action=",".join(block_actions), ignore_environment=ignore_environment, players=players_clause, - coords=coords_clause, blocks=blocks_clause, worlds=worlds_clause, time=time_clause)) + {players_clause} + {coords_clause} + {blocks_clause} + {worlds_clause} + {time_clause} + ''') # Chat if form.chat: - queries.append('''SELECT + queries.append(f'''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.rowid WHERE 1 = 1 - {players} - {chat} - {time} - '''.format(players=players_clause, chat=chat_clause, time=time_clause)) + {players_clause} + {chat_clause} + {time_clause} + ''') # Chest Use if form.chest_use: concat = 'CONCAT(cc.amount, " ", cmm.material)' if connection.vendor == "sqlite": concat = 'cc.amount || " " || cmm.material' - queries.append('''SELECT + queries.append(f'''SELECT 0 AS id, "container" AS type, cc.time AS unix, cu.user AS player, cc.action, {concat} AS data, cc.x, cc.y, cc.z, cw.world FROM co_container cc JOIN co_user cu ON cc.user = cu.rowid JOIN co_material_map cmm ON cc.type = cmm.rowid JOIN co_world cw ON cc.wid = cw.rowid WHERE 1 = 1 - {worlds} - {players} - {coords} - {blocks} - {time} - '''.format(concat=concat, worlds=worlds_clause, players=players_clause, coords=coords_clause, blocks=blocks_clause, time=time_clause)) + {worlds_clause} + {players_clause} + {coords_clause} + {blocks_clause} + {time_clause} + ''') # Commands if form.command: - queries.append('''SELECT + queries.append(f'''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.rowid WHERE 1 = 1 - {players} - {command} - {coords} - {time} - '''.format(players=players_clause, command=command_clause, coords=coords_clause, time=time_clause)) + {players_clause} + {command_clause} + {coords_clause} + {time_clause} + ''') # Login/Logout if form.login_logout: - queries.append('''SELECT + queries.append(f'''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.rowid JOIN co_world cw ON cs.wid = cw.rowid WHERE 1 = 1 - {worlds} - {players} - {coords} - {time} - '''.format(worlds=worlds_clause, players=players_clause, coords=coords_clause, time=time_clause)) + {worlds_clause} + {players_clause} + {coords_clause} + {time_clause} + ''') # Sign Place if form.sign_place: - queries.append('''SELECT + queries.append(f'''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.rowid JOIN co_world cw ON cs.wid = cw.rowid WHERE 1 = 1 - {worlds} - {players} - {coords} - {time} - '''.format(worlds=worlds_clause, players=players_clause, coords=coords_clause, time=time_clause)) + {worlds_clause} + {players_clause} + {coords_clause} + {time_clause} + ''') query = " UNION ALL ".join(queries) if query: - query += " ORDER BY unix {} LIMIT {}, {}".format(oldest_first, form.start, form.page_size) - if query: + query += f" ORDER BY unix {oldest_first} LIMIT {form.start}, {form.page_size}" return GUIResult.objects.raw(query) - return [] + return GUIResult.objects.none() diff --git a/models.py b/models.py index 15bede9..89f2f30 100644 --- a/models.py +++ b/models.py @@ -8,7 +8,6 @@ from django_coreprotect.utils import safe_int class CoreProtectUser(User): - class Meta: proxy = True permissions = ( @@ -318,7 +317,7 @@ class Preset(models.Model): enabled = models.BooleanField(default=True) @property - def link(self): + def link(self) -> str: url = reverse("coreprotect_gui") + "?" params = [] if self.block_break: @@ -385,7 +384,8 @@ class GUIResult(models.Model): @property def display_action(self): if self.type == "block": - return "Block Break" if str(self.action) == "0" else "Block Place" if str(self.action) == "1" else "Interact/Used" + return "Block Break" if str(self.action) == "0" else "Block Place" if str( + self.action) == "1" else "Interact/Used" if self.type == "chat": return "Chat" if self.type == "container": @@ -445,4 +445,4 @@ class ActivityResult: hours = time % 24 time //= 24 days = time - return "{}d, {}h, {}m, {}s".format(days, hours, minutes, seconds) + return f"{days}d, {hours}h, {minutes}m, {seconds}s" diff --git a/tests.py b/tests.py deleted file mode 100644 index 7ce503c..0000000 --- a/tests.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.test import TestCase - -# Create your tests here. diff --git a/urls.py b/urls.py index 28eecae..1f4af1a 100644 --- a/urls.py +++ b/urls.py @@ -1,5 +1,6 @@ -from django.urls import path from django.contrib.auth.decorators import permission_required +from django.urls import path + from django_coreprotect.views import GUI, GUIQuery, Activity, ActivityQuery urlpatterns = [ diff --git a/utils.py b/utils.py index c8ddeae..68a62f4 100644 --- a/utils.py +++ b/utils.py @@ -1,19 +1,20 @@ import ast from datetime import datetime, timedelta +from typing import Any, Optional -def checkbox(value): +def checkbox(value: str) -> bool: return True if value == "on" else False -def safe_int(value): +def safe_int(value: Any) -> int: try: return int(value) except: return 0 -def time_to_form(date_time): +def time_to_form(date_time: str) -> Optional[datetime]: if date_time == "~T": return datetime.today() elif date_time == "~N": @@ -21,7 +22,7 @@ def time_to_form(date_time): elif date_time == "~Y": return datetime.today() - timedelta(days=1) elif date_time == "": - return "" + return None else: return datetime.utcfromtimestamp(float(date_time)) diff --git a/views.py b/views.py index 1596230..ced3ae1 100644 --- a/views.py +++ b/views.py @@ -1,6 +1,7 @@ from django.http.response import JsonResponse from django.shortcuts import render from django.views.generic import View +from django.core import serializers from django_coreprotect.activity import activity_data, activity_results from django_coreprotect.gui import gui_data, gui_results @@ -25,7 +26,7 @@ class GUIQuery(View): results = gui_results(form) if "format" in request.GET and request.GET["format"] == "json": - return JsonResponse(results) + return serializers.serialize('json', results) prev_page, next_page = False, False if safe_int(form.page) > 0: