Compress saves and cleanup older than 48h saves
authorJoann Mõndresku <joann@cernodile.com>
Thu, 16 May 2024 16:50:51 +0000 (19:50 +0300)
committerJoann Mõndresku <joann@cernodile.com>
Thu, 16 May 2024 16:50:51 +0000 (19:50 +0300)
app.py
db_store.py

diff --git a/app.py b/app.py
index 02a91bdcd3ad2b79363901fc6939096c5304ec0b..eaef3d5e8776c2d3a915faedc57fded8114ddbd1 100644 (file)
--- a/app.py
+++ b/app.py
@@ -5,6 +5,7 @@
 import base64
 import datetime
 import time
+import zlib
 
 import ei_pb2 as EIProto
 
@@ -38,12 +39,14 @@ def ei_routes(subpath):
                Backups = db_store.get_backups(ContactReq.user_id)
                if len(Backups) > 0:
                        # Lets process backups - check for any forced ones first
+                       now = datetime.datetime.now()
+                       cleanup_ids = []
                        for backup in Backups:
                                if backup[2] == True:
                                        # Force backup found - lets serialize the payload
                                        SaveBackup = EIProto.Backup()
                                        try:
-                                               SaveBackup.ParseFromString(base64.b64decode(backup[3]))
+                                               SaveBackup.ParseFromString(base64.b64decode(zlib.decompress(backup[3])))
                                                SaveBackup.force_backup = True
                                                SaveBackup.force_offer_backup = True
                                                ContactResp.backup.CopyFrom(SaveBackup)
@@ -52,6 +55,12 @@ def ei_routes(subpath):
                                        except:
                                                print("Failed to force serve backup - perhaps some logic error?")
                                                break
+                               else:
+                                       then = datetime.datetime.fromtimestamp(backup[1])
+                                       if (now - then).days > 1:
+                                               cleanup_ids.append(backup[0])
+                       if len(cleanup_ids) > 0:
+                               db_store.cleanup_backups(cleanup_ids)
                        # TODO: Check for soul eggs/eggs of prophecy and determine algorithm for "is it worth offering?"
                elif ContactReq.user_id in upgrade_cache:
                        print("Found an unupgraded save - lets upgrade the permit level to Pro")
@@ -69,7 +78,7 @@ def ei_routes(subpath):
                        upgrade_cache[SaveBackup.user_id] = SaveBackup
                else:
                        # start storing backups after permit upgrades
-                       db_store.add_backup(SaveBackup.user_id, request.form["data"].replace(" ", "+"))
+                       db_store.add_backup(SaveBackup.user_id, base64.b64encode(zlib.compress(SaveBackup.SerializeToString())))
        elif subpath == "get_periodicals":
                PeriodicalResp = EIProto.PeriodicalsResponse()
                for evt in events.get_active_events():
@@ -108,7 +117,7 @@ def ei_ps_routes(userid, method):
        if len(Backups) == 0:
                return "No such user found", 404
        SaveBackup = EIProto.Backup()
-       SaveBackup.ParseFromString(base64.b64decode(Backups[-1][3]))
+       SaveBackup.ParseFromString(base64.b64decode(zlib.decompress(Backups[-1][3])))
        if method == "break_piggy":
                if not SaveBackup.stats.piggy_full:
                        return "Piggy Bank not full.", 403
@@ -124,7 +133,7 @@ def ei_ps_routes(userid, method):
                        # BEFORE ENABLING - Piggy bank doesn't reset, need to find a way to trigger that.
                        SaveBackup.game.piggy_bank = 1
                        SaveBackup.game.piggy_full_alert_shown = False
-                       db_store.update_backup(Backups[-1][0], base64.b64encode(SaveBackup.SerializeToString()), True)
+                       db_store.update_backup(Backups[-1][0], base64.b64encode(zlib.compress(SaveBackup.SerializeToString())), True)
                        return "Broke the piggy bank - accept the backup offer when restarting your game.", 200
                else:
                        return "You need to have waited at least a week since filling the piggy bank before breaking it.", 403
index 9a3b421a209c5e84db509342ad51bcc888dff2ef..45db008c13924241834af33a1b328c40e26baa1b 100644 (file)
@@ -32,6 +32,14 @@ def get_backup(ref_id):
        else:
                return tuple[0]
 
+def cleanup_backups(numids):
+       con = get_connection("backups")
+       cur = con.cursor()
+       cur.execute("DELETE FROM Backups WHERE BackupID IN(" + (", ".join(map(str, numids))) + ")")
+       con.commit()
+       con.close()
+       return
+
 def get_backups(device_id):
        if not device_id.isalnum():
                return []
@@ -39,17 +47,32 @@ def get_backups(device_id):
        cur = con.cursor()
        res = cur.execute("SELECT BackupID, BackupStamp, ForceOffer, Payload FROM Backups WHERE DeviceID=\"" + device_id + "\"")
        x = res.fetchall()
+       con.close()
        if x is None:
                return []
        else:
                return x
 
+def get_last_backup(device_id):
+       if not device_id.isalnum():
+               return None
+       con = get_connection("backups")
+       cur = con.cursor()
+       res = cur.execute("SELECT BackupID, BackupStamp, ForceOffer, Payload FROM Backups WHERE DeviceID=\"" + device_id + "\" ORDER BY BackupID DESC LIMIT 1")
+       x = res.fetchall()
+       con.close()
+       if x is None:
+               return []
+       else:
+               return x[0]
+
 def add_backup(device_id, b64str):
        if not device_id.isalnum():
-               return
+                       return
        con = get_connection("backups")
        cur = con.cursor()
-       res = cur.execute("INSERT INTO Backups(DeviceID, BackupStamp, ForceOffer, Payload) VALUES(?, ?, ?, ?)", (device_id, int(time.time()), False, b64str))
+       stamp = int(time.time())
+       res = cur.execute("INSERT INTO Backups(DeviceID, BackupStamp, ForceOffer, Payload) VALUES(?, ?, ?, ?)", (device_id, stamp, False, b64str))
        con.commit()
        con.close()
        return
@@ -69,6 +92,20 @@ def offer_backup_id_to_new_device(refID, device_id):
        add_backup(device_id, srcBackup)
        return
 
+# If you used my server prior to zlib saves, uncomment and run once.
+#import zlib
+#import base64
+#def compress_to_zlib():
+#      con = get_connection("backups")
+#      cur = con.cursor()
+#      res = cur.execute("SELECT BackupID, ForceOffer, Payload FROM Backups");
+#      x = res.fetchall()
+#      con.close()
+#      for backup in x:
+#              print(backup[0])
+#              update_backup(backup[0], base64.b64encode(zlib.compress(base64.b64decode(backup[2]))), backup[1])
+#compress_to_zlib()
+
 ## MANUAL TRANSFER EXAMPLE
 ## TODO: Admin API endpoint for this
 # offer_backup_id_to_new_device(2, "f7c9c95ce5f6d06a")