Python 3 changes, add LICENSE, update README

Signed-off-by: jolheiser <john.olheiser@gmail.com>
py3
jolheiser 2022-02-12 15:21:03 -06:00
parent fd3ffa6857
commit f64c041930
Signed by: jolheiser
GPG Key ID: B853ADA5DA7BBF7A
9 changed files with 115 additions and 76 deletions

7
LICENSE 100644
View File

@ -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.

View File

@ -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)

View File

@ -1,6 +1,7 @@
from django_coreprotect.models import SessionResult, ActivityResult from django_coreprotect.models import SessionResult, ActivityResult
from django_coreprotect.utils import safe_int from django_coreprotect.utils import safe_int
from datetime import datetime from datetime import datetime
from typing import List
class ActivityForm: class ActivityForm:
@ -25,7 +26,7 @@ def activity_data(request):
return form return form
def activity_results(form): def activity_results(form) -> List[ActivityResult]:
query = "" query = ""
players_clause = "" players_clause = ""
@ -33,7 +34,8 @@ def activity_results(form):
players = [] players = []
for player in form.players.split(","): for player in form.players.split(","):
players.append(player.strip()) 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 = "" time_clause = ""
if form.date_from or form.date_to: 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) time_clause = " HAVING unix BETWEEN {} AND {} ".format(df, dt)
if players_clause or time_clause: if players_clause or time_clause:
query = '''SELECT query = f'''SELECT
0 AS id, cs.time AS unix, cu.user AS player, cs.action 0 AS id, cs.time AS unix, cu.user AS player, cs.action
FROM co_session cs FROM co_session cs
JOIN co_user cu ON cs.user = cu.rowid JOIN co_user cu ON cs.user = cu.rowid
{players} {players_clause}
{time} {time_clause}
'''.format(players=players_clause, time=time_clause) '''
if query: if query:
print(query)
sessions = SessionResult.objects.raw(query) sessions = SessionResult.objects.raw(query)
activity = {} activity = {}
last_session = {} last_session = {}

116
gui.py
View File

@ -1,6 +1,8 @@
from datetime import datetime from datetime import datetime
from django.db import connection 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.models import CoWorld, GUIResult
from django_coreprotect.utils import safe_int, checkbox, time_to_form from django_coreprotect.utils import safe_int, checkbox, time_to_form
@ -33,7 +35,7 @@ class GUIForm:
self.date_to = "" self.date_to = ""
def gui_data(request): def gui_data(request: HttpRequest) -> GUIForm:
request_data = request.GET request_data = request.GET
form = GUIForm() form = GUIForm()
worlds = CoWorld.objects.all() worlds = CoWorld.objects.all()
@ -56,7 +58,7 @@ def gui_data(request):
# Worlds # Worlds
request_worlds = request_data.getlist("world") request_worlds = request_data.getlist("world")
for world in worlds: for world in worlds:
world_id = "world_{}".format(world.id) world_id = f"world_{world.id}"
w = { w = {
"id": str(world.id), "id": str(world.id),
"world_id": world_id, "world_id": world_id,
@ -99,7 +101,7 @@ def gui_data(request):
return form return form
def gui_results(form): def gui_results(form: GUIForm) -> RawQuerySet:
queries = [] queries = []
ignore_environment = " AND cu.user NOT LIKE '#%%' " if form.ignore_environment else "" ignore_environment = " AND cu.user NOT LIKE '#%%' " if form.ignore_environment else ""
oldest_first = " ASC " if form.oldest_first else " DESC " oldest_first = " ASC " if form.oldest_first else " DESC "
@ -107,21 +109,23 @@ def gui_results(form):
coords = [] coords = []
radius = form.radius if form.radius else "0" radius = form.radius if form.radius else "0"
if form.x: 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: 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: 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 = "" coords_clause = ""
if coords: if coords:
coords_clause = " AND ({})".format(" AND ".join(coords)) clause = " AND ".join(coords)
coords_clause = f" AND ({clause})"
players = [] players = []
players_clause = "" players_clause = ""
if form.players: if form.players:
for player in form.players.split(","): for player in form.players.split(","):
players.append(player.strip()) 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 = []
blocks_clause = "" blocks_clause = ""
@ -130,14 +134,18 @@ def gui_results(form):
if form.blocks: if form.blocks:
for block in form.blocks.split(","): for block in form.blocks.split(","):
blocks.append(block.strip()) blocks.append(block.strip())
blocks_clause = " AND ({})".format(" OR ".join(["cmm.material LIKE 'minecraft:{}%%'".format(b) for b in blocks])) clause = " OR ".join([f"cmm.material LIKE 'minecraft:{b}%%'" for b in blocks])
chat_clause = " AND ({})".format(" OR ".join(["cc.message LIKE '%%{}%%'".format(b) for b in blocks])) blocks_clause = f" AND ({clause})"
command_clause = " AND ({})".format(" OR ".join(["cc.message LIKE '%%{}%%'".format(b) for b in blocks])) 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_clause = ""
worlds = [world["id"] for world in form.worlds if world["checked"]] worlds = [world["id"] for world in form.worlds if world["checked"]]
if len(worlds): 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 = "" time_clause = ""
if form.date_from or form.date_to: if form.date_from or form.date_to:
@ -146,7 +154,7 @@ def gui_results(form):
dt = datetime.now().timestamp() dt = datetime.now().timestamp()
if form.date_to and not form.date_from: if form.date_to and not form.date_from:
df = datetime.now().timestamp() 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 Break, Block Place, and Interact
block_actions = [] block_actions = []
@ -157,97 +165,95 @@ def gui_results(form):
if form.interact: if form.interact:
block_actions.append("2") block_actions.append("2")
if len(block_actions): 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 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 FROM co_block cb
JOIN co_user cu ON cb.user = cu.rowid JOIN co_user cu ON cb.user = cu.rowid
JOIN co_material_map cmm ON cb.type = cmm.rowid JOIN co_material_map cmm ON cb.type = cmm.rowid
JOIN co_world cw ON cb.wid = cw.rowid JOIN co_world cw ON cb.wid = cw.rowid
WHERE cb.action IN ({action}) WHERE cb.action IN ({",".join(block_actions)})
{ignore_environment} {ignore_environment}
{players} {players_clause}
{coords} {coords_clause}
{blocks} {blocks_clause}
{worlds} {worlds_clause}
{time} {time_clause}
'''.format(action=",".join(block_actions), ignore_environment=ignore_environment, players=players_clause, ''')
coords=coords_clause, blocks=blocks_clause, worlds=worlds_clause, time=time_clause))
# Chat # Chat
if form.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 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 FROM co_chat cc
JOIN co_user cu ON cc.user = cu.rowid JOIN co_user cu ON cc.user = cu.rowid
WHERE 1 = 1 WHERE 1 = 1
{players} {players_clause}
{chat} {chat_clause}
{time} {time_clause}
'''.format(players=players_clause, chat=chat_clause, time=time_clause)) ''')
# Chest Use # Chest Use
if form.chest_use: if form.chest_use:
concat = 'CONCAT(cc.amount, " ", cmm.material)' concat = 'CONCAT(cc.amount, " ", cmm.material)'
if connection.vendor == "sqlite": if connection.vendor == "sqlite":
concat = 'cc.amount || " " || cmm.material' 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 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 FROM co_container cc
JOIN co_user cu ON cc.user = cu.rowid JOIN co_user cu ON cc.user = cu.rowid
JOIN co_material_map cmm ON cc.type = cmm.rowid JOIN co_material_map cmm ON cc.type = cmm.rowid
JOIN co_world cw ON cc.wid = cw.rowid JOIN co_world cw ON cc.wid = cw.rowid
WHERE 1 = 1 WHERE 1 = 1
{worlds} {worlds_clause}
{players} {players_clause}
{coords} {coords_clause}
{blocks} {blocks_clause}
{time} {time_clause}
'''.format(concat=concat, worlds=worlds_clause, players=players_clause, coords=coords_clause, blocks=blocks_clause, time=time_clause)) ''')
# Commands # Commands
if form.command: 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 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 FROM co_command cc
JOIN co_user cu ON cc.user = cu.rowid JOIN co_user cu ON cc.user = cu.rowid
WHERE 1 = 1 WHERE 1 = 1
{players} {players_clause}
{command} {command_clause}
{coords} {coords_clause}
{time} {time_clause}
'''.format(players=players_clause, command=command_clause, coords=coords_clause, time=time_clause)) ''')
# Login/Logout # Login/Logout
if form.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 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 FROM co_session cs
JOIN co_user cu ON cs.user = cu.rowid JOIN co_user cu ON cs.user = cu.rowid
JOIN co_world cw ON cs.wid = cw.rowid JOIN co_world cw ON cs.wid = cw.rowid
WHERE 1 = 1 WHERE 1 = 1
{worlds} {worlds_clause}
{players} {players_clause}
{coords} {coords_clause}
{time} {time_clause}
'''.format(worlds=worlds_clause, players=players_clause, coords=coords_clause, time=time_clause)) ''')
# Sign Place # Sign Place
if form.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 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 FROM co_sign cs
JOIN co_user cu ON cs.user = cu.rowid JOIN co_user cu ON cs.user = cu.rowid
JOIN co_world cw ON cs.wid = cw.rowid JOIN co_world cw ON cs.wid = cw.rowid
WHERE 1 = 1 WHERE 1 = 1
{worlds} {worlds_clause}
{players} {players_clause}
{coords} {coords_clause}
{time} {time_clause}
'''.format(worlds=worlds_clause, players=players_clause, coords=coords_clause, time=time_clause)) ''')
query = " UNION ALL ".join(queries) query = " UNION ALL ".join(queries)
if query: if query:
query += " ORDER BY unix {} LIMIT {}, {}".format(oldest_first, form.start, form.page_size) query += f" ORDER BY unix {oldest_first} LIMIT {form.start}, {form.page_size}"
if query:
return GUIResult.objects.raw(query) return GUIResult.objects.raw(query)
return [] return GUIResult.objects.none()

View File

@ -8,7 +8,6 @@ from django_coreprotect.utils import safe_int
class CoreProtectUser(User): class CoreProtectUser(User):
class Meta: class Meta:
proxy = True proxy = True
permissions = ( permissions = (
@ -318,7 +317,7 @@ class Preset(models.Model):
enabled = models.BooleanField(default=True) enabled = models.BooleanField(default=True)
@property @property
def link(self): def link(self) -> str:
url = reverse("coreprotect_gui") + "?" url = reverse("coreprotect_gui") + "?"
params = [] params = []
if self.block_break: if self.block_break:
@ -385,7 +384,8 @@ class GUIResult(models.Model):
@property @property
def display_action(self): def display_action(self):
if self.type == "block": 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": if self.type == "chat":
return "Chat" return "Chat"
if self.type == "container": if self.type == "container":
@ -445,4 +445,4 @@ class ActivityResult:
hours = time % 24 hours = time % 24
time //= 24 time //= 24
days = time days = time
return "{}d, {}h, {}m, {}s".format(days, hours, minutes, seconds) return f"{days}d, {hours}h, {minutes}m, {seconds}s"

View File

@ -1,3 +0,0 @@
from django.test import TestCase
# Create your tests here.

View File

@ -1,5 +1,6 @@
from django.urls import path
from django.contrib.auth.decorators import permission_required from django.contrib.auth.decorators import permission_required
from django.urls import path
from django_coreprotect.views import GUI, GUIQuery, Activity, ActivityQuery from django_coreprotect.views import GUI, GUIQuery, Activity, ActivityQuery
urlpatterns = [ urlpatterns = [

View File

@ -1,19 +1,20 @@
import ast import ast
from datetime import datetime, timedelta 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 return True if value == "on" else False
def safe_int(value): def safe_int(value: Any) -> int:
try: try:
return int(value) return int(value)
except: except:
return 0 return 0
def time_to_form(date_time): def time_to_form(date_time: str) -> Optional[datetime]:
if date_time == "~T": if date_time == "~T":
return datetime.today() return datetime.today()
elif date_time == "~N": elif date_time == "~N":
@ -21,7 +22,7 @@ def time_to_form(date_time):
elif date_time == "~Y": elif date_time == "~Y":
return datetime.today() - timedelta(days=1) return datetime.today() - timedelta(days=1)
elif date_time == "": elif date_time == "":
return "" return None
else: else:
return datetime.utcfromtimestamp(float(date_time)) return datetime.utcfromtimestamp(float(date_time))

View File

@ -1,6 +1,7 @@
from django.http.response import JsonResponse from django.http.response import JsonResponse
from django.shortcuts import render from django.shortcuts import render
from django.views.generic import View from django.views.generic import View
from django.core import serializers
from django_coreprotect.activity import activity_data, activity_results from django_coreprotect.activity import activity_data, activity_results
from django_coreprotect.gui import gui_data, gui_results from django_coreprotect.gui import gui_data, gui_results
@ -25,7 +26,7 @@ class GUIQuery(View):
results = gui_results(form) results = gui_results(form)
if "format" in request.GET and request.GET["format"] == "json": if "format" in request.GET and request.GET["format"] == "json":
return JsonResponse(results) return serializers.serialize('json', results)
prev_page, next_page = False, False prev_page, next_page = False, False
if safe_int(form.page) > 0: if safe_int(form.page) > 0: