Python 3 changes, add LICENSE, update README #5

Open
jolheiser wants to merge 1 commits from py3 into master
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.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 = {}

116
gui.py
View File

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

View File

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

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.urls import path
from django_coreprotect.views import GUI, GUIQuery, Activity, ActivityQuery
urlpatterns = [

View File

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

View File

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