Skip to content

Commit 432e119

Browse files
committed
1.55.5 redo uuid system
1 parent 6cd8bce commit 432e119

13 files changed

Lines changed: 2071 additions & 148 deletions

File tree

assets/control

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
Package: craftserversetup
2-
Version: 1.55.4
2+
Version: 1.55.5
33
Maintainer: Enderbyte Programs <enderbyte09@gmail.com>
44
Homepage: https://github.com/Enderbyte-Programs/CraftServerSetup
55
Architecture: all

changelog

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
1.55.5:
2+
- Add UUID table export for first join and last seen
3+
- Overhaul UUID system
14
1.55.4:
25
- Add ability to launch a shell from manage server menu (Java and Bedrock)
36
1.55.3:

export

Lines changed: 1883 additions & 0 deletions
Large diffs are not rendered by default.

src/analytics.py

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,17 @@
1414
import logfilters
1515
import analyticsstructures
1616
import analyticsexplorer
17-
18-
#TODO - split this file into analyticsexplorer.py and analyticsstructures.py
17+
import uuid
18+
from time import sleep
19+
import uuidmgr
1920

2021
def analytics_loader(stdscr,serverdir):
2122
telemetry.telemetric_action("analytics")
2223
if uicomponents.resource_warning(stdscr):
2324
return
2425
renaminghandler.autoupdate_cache(stdscr,serverdir)
26+
uuidmgr.load_from_logs(stdscr,serverdir)
27+
2528
analytics_file_path = serverdir + os.sep + "anacache.json.gz"
2629
cursesplus.displaymsg(stdscr,["Loading from cache..."],False)
2730
readfrom = datetime.datetime(2000,1,1,0,0,0)
@@ -129,6 +132,7 @@ def analytics_loader(stdscr,serverdir):
129132

130133
for k in final:
131134
final[k].onlineplayers = utils.remove_duplicates_from_list(final[k].onlineplayers)
135+
final[k].onlineplayers = utils.recursive_remove_if_contains(final[k].onlineplayers,["\"","{","/"])
132136

133137
#Find last zeroed time to store in cache
134138
storeto = analyticsstructures.get_minute_id_from_datetime(readfrom)#By default, store none. Then, try to find the last zero point
@@ -297,7 +301,7 @@ def analytics_loader(stdscr,serverdir):
297301
elif wtd == 10:
298302
plf = 0
299303
cursesplus.displaymsg(stdscr,["Analyzing data",f"{plf} players found"],False)
300-
sortop = uicomponents.menu(stdscr,["Alphabetically","Recent -> Old"],"Choose search option")
304+
sortop = uicomponents.menu(stdscr,["Alphabetically","Recent -> Old","Export UUIDs"],"Choose search option or data option")
301305
fjblock:dict[str,datetime.datetime] = {}
302306
for line in reversed(list(workingdata.values())):
303307
for pl in line.onlineplayers:
@@ -306,6 +310,10 @@ def analytics_loader(stdscr,serverdir):
306310
plf += 1
307311
cursesplus.displaymsg(stdscr,["Analyzing data",f"{plf} players found"],False)
308312

313+
if sortop == 2:
314+
do_date_based_uuid_export(stdscr,fjblock)
315+
continue
316+
309317
if sortop == 0:
310318
fjblock = dict(sorted(fjblock.items()))#Sort A-Z
311319

@@ -318,7 +326,7 @@ def analytics_loader(stdscr,serverdir):
318326
elif wtd == 11:
319327
plf = 0
320328
cursesplus.displaymsg(stdscr,["Analyzing data",f"{plf} players found"],False)
321-
sortop = uicomponents.menu(stdscr,["Alphabetically","Oldest to newest"],"Choose search option")
329+
sortop = uicomponents.menu(stdscr,["Alphabetically","Oldest to newest","Export UUIDs"],"Choose search option or data option")
322330
fjblock:dict[str,datetime.datetime] = {}
323331
for line in list(workingdata.values()):
324332
for pl in line.onlineplayers:
@@ -327,6 +335,10 @@ def analytics_loader(stdscr,serverdir):
327335
plf += 1
328336
cursesplus.displaymsg(stdscr,["Analyzing data",f"{plf} players found"],False)
329337

338+
if sortop == 2:
339+
do_date_based_uuid_export(stdscr,fjblock)
340+
continue
341+
330342
if sortop == 0:
331343
fjblock = dict(sorted(fjblock.items()))#Sort A-Z
332344

@@ -342,4 +354,43 @@ def analytics_loader(stdscr,serverdir):
342354
cursesplus.messagebox.showinfo(stdscr,["The analytics cache has been reset."])
343355
return
344356

357+
def do_date_based_uuid_export(stdscr,vals:dict[str,datetime.datetime]) -> None:
358+
"""Produces and writes a file. Each line is one user. First block before space is uuid. All names are built to handle name changes"""
359+
cursesplus.displaymsg(stdscr,["Please wait..."],False)
345360

361+
tempresult:dict[str,int] = {}
362+
363+
for kvpair in list(vals.items()):
364+
latest_uname = renaminghandler.get_current_name_of(kvpair[0])
365+
tempresult[latest_uname] = int(kvpair[1].timestamp())
366+
367+
cursesplus.displaymsg(stdscr,["It is now time to convert names into UUIDs","They will be processed at 1/second max","Press enter to proceed."])
368+
369+
result:dict[str,int] = {}
370+
all_items = list(tempresult.items())
371+
372+
pbar = cursesplus.ProgressBar(stdscr,len(all_items),bar_type=cursesplus.ProgressBarTypes.FullScreenProgressBar,show_log=True,message="Loading UUIDs")
373+
374+
while len(all_items) > 0:
375+
376+
selitem = all_items.pop()
377+
mresult = uuidmgr.get_uuid_from_name(selitem[0])
378+
if mresult == "":
379+
continue
380+
381+
cursesplus.displaymsg(stdscr,[f"{len(all_items)} remaining"],False)
382+
result[str(mresult)] = selitem[1]
383+
pbar.step(f"{selitem[0]} -> {mresult}",True)
384+
385+
pbar.done()
386+
387+
388+
outfile = cursesplus.savefile_selector(stdscr)
389+
with open(outfile,"w+") as f:
390+
for resitem in list(result.items()):
391+
f.write(resitem[0])
392+
f.write(" ")
393+
f.write(str(resitem[1]))
394+
f.write("\n")
395+
396+
cursesplus.messagebox.showinfo(stdscr,["Saved successfully"])

src/appdata.py

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -215,14 +215,10 @@ def compatibilize_appdata(data:dict) -> dict:
215215
"language" : None
216216
}
217217

218-
UUID_INDEX:dict = {}
219-
220218
def setup_appdata():
221219
"""Load appdata from the file and populate the appdata.APPDATA variable."""
222220
global APPDATA
223221
global APPDATAFILE
224-
global UUIDFILE
225-
global UUID_INDEX
226222
APPDATAFILE = APPDATADIR+"/config.json"
227223
if not os.path.isfile(APPDATAFILE):
228224
with open(APPDATAFILE,"w+") as f:
@@ -238,19 +234,6 @@ def setup_appdata():
238234
APPDATA = __DEFAULTAPPDATA__
239235
APPDATA = compatibilize_appdata(APPDATA)
240236

241-
UUIDFILE = APPDATADIR+"/uuidindex.json.gz"
242-
243-
if not os.path.isfile(UUIDFILE):
244-
with open(UUIDFILE,"wb+") as f:
245-
f.write(gzip.compress(json.dumps({}).encode()))
246-
else:
247-
try:
248-
with open(UUIDFILE,"rb") as f:
249-
UUID_INDEX = json.loads(gzip.decompress(f.read()))
250-
except:
251-
with open(UUIDFILE,"wb+") as f:
252-
f.write(gzip.compress(json.dumps({}).encode()))
253-
254237
def self_compatibilize():
255238
"""Execute a compatibilization and repair routine on appdata.APPDATA"""
256239
global APPDATA
@@ -261,12 +244,8 @@ def updateappdata():
261244
"""Write in-memory appdata and UUID cache to the disk"""
262245

263246
global APPDATAFILE
264-
global UUID_INDEX
265-
global UUIDFILE
266247
with open(APPDATAFILE,"w+") as f:
267248
f.write(json.dumps(APPDATA,indent=2))
268-
with open(UUIDFILE,"wb+") as f:
269-
f.write(gzip.compress(json.dumps(UUID_INDEX).encode()))#Write compressed file
270249

271250
def get_setting_value(key:str) -> typing.Any:
272251
return APPDATA["settings"][key]["value"]

src/logfilters.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,7 @@ def is_logentry_a_command(l:logutils.LogEntry) -> bool:
1818
return len(re.findall(r"[a-zA-Z0-9_]+\sissued server command: .*",l.data)) > 0
1919

2020
def player_rename(l:logutils.LogEntry) -> bool:
21-
return len(re.findall(r"\S+ \(formerly known as \S+\)",l.data)) > 0
21+
return len(re.findall(r"\S+ \(formerly known as \S+\)",l.data)) > 0
22+
23+
def get_uuid(l:logutils.LogEntry) -> bool:
24+
return len(re.findall(r": UUID of player \S+ is \S+$",l.data) + re.findall(r"Floodgate player logged in as \S+ joined \(UUID: \S+\)",l.data)) > 0

src/logloader.py

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -104,24 +104,4 @@ def create_log_entry(data:str,fromfilename:str) -> logutils.LogEntry:
104104
int(fromfilename.split("-")[1]),
105105
int(fromfilename.split("-")[2])
106106
)
107-
return logutils.LogEntry(fromfilename,ld,data)
108-
109-
def load_server_logs_and_find(stdscr,serverdir:str,tofind:str) -> list[str]:
110-
"""Find specific matches of regex, removing the rest of the log entry"""
111-
cursesplus.displaymsg(stdscr,["Loading Logs, Please wait..."],False)
112-
logfile = serverdir + "/logs"
113-
if not os.path.isdir(logfile):
114-
return []
115-
dirstack.pushd(logfile)
116-
logs:list[str] = [l for l in os.listdir(logfile) if l.endswith(".gz") or l.endswith(".log")]
117-
p = cursesplus.ProgressBar(stdscr,len(logs),cursesplus.ProgressBarTypes.SmallProgressBar,cursesplus.ProgressBarLocations.TOP,message="Loading logs")
118-
final:list[str] = []
119-
for lf in logs:
120-
p.step(lf)
121-
if lf.endswith(".gz"):
122-
with open(lf,'rb') as f:
123-
final.extend(re.findall(tofind,gzip.decompress(f.read()).decode()))
124-
else:
125-
with open(lf) as f:
126-
final.extend(re.findall(tofind,f.read()))
127-
return final
107+
return logutils.LogEntry(fromfilename,ld,data)

0 commit comments

Comments
 (0)