import contracts
import events
+import db_store
upgrade_cache = {}
app = Flask(__name__)
contracts.load_contracts()
+db_store.create_backups_db()
@app.route('/ei/<path:subpath>', methods=['POST'])
def ei_routes(subpath):
ContactReq = EIProto.EggIncFirstContactRequest()
ContactReq.ParseFromString(data)
ContactResp = EIProto.EggIncFirstContactResponse()
- if ContactReq.user_id in upgrade_cache:
+ Backups = db_store.get_backups(ContactReq.user_id)
+ if len(Backups) > 0:
+ # Lets process backups - check for any forced ones first
+ 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.force_backup = True
+ SaveBackup.force_offer_backup = True
+ ContactResp.backup.CopyFrom(SaveBackup)
+ db_store.update_backup(backup[0], backup[3], False)
+ break
+ except:
+ print("Failed to force serve backup - perhaps some logic error?")
+ break
+ # 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")
ContactResp.backup.CopyFrom(cache[ContactReq.user_id])
del upgrade_cache[ContactReq.user_id]
SaveBackup.force_backup = True
SaveBackup.force_offer_backup = True
upgrade_cache[SaveBackup.user_id] = SaveBackup
+ else:
+ # start storing backups after permit upgrades
+ db_store.add_backup(SaveBackup.user_id, request.form["data"].replace(" ", "+"))
elif subpath == "get_periodicals":
PeriodicalResp = EIProto.PeriodicalsResponse()
for evt in events.get_active_events():
--- /dev/null
+# db_store.py - Providing "cloud saves" and such
+import sqlite3
+import time
+
+# TODO: Truncate last x backups from a given device ID
+def get_connection(dbName):
+ con = sqlite3.connect("db/" + dbName + ".db")
+ return con
+
+def create_backups_db():
+ FreshInstall = True
+ con = get_connection("backups")
+ cur = con.cursor()
+ try:
+ cur.execute("CREATE TABLE Backups(BackupID INTEGER PRIMARY KEY AUTOINCREMENT, DeviceID TEXT, BackupStamp BIGINT, ForceOffer BOOL, Payload TEXT)")
+ except:
+ FreshInstall = False
+ con.commit()
+ con.close()
+ return FreshInstall
+
+def get_backup(ref_id):
+ if not isinstance(ref_id, int):
+ return None
+ con = get_connection("backups")
+ cur = con.cursor()
+ res = cur.execute("SELECT Payload FROM Backups WHERE BackupID=" + str(ref_id))
+ tuple = res.fetchone()
+ con.close()
+ if tuple is None:
+ return tuple
+ else:
+ return tuple[0]
+
+def get_backups(device_id):
+ if not device_id.isalnum():
+ return []
+ con = get_connection("backups")
+ cur = con.cursor()
+ res = cur.execute("SELECT BackupID, BackupStamp, ForceOffer, Payload FROM Backups WHERE DeviceID=\"" + device_id + "\"")
+ x = res.fetchall()
+ if x is None:
+ return []
+ else:
+ return x
+
+def add_backup(device_id, b64str):
+ if not device_id.isalnum():
+ 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))
+ con.commit()
+ con.close()
+ return
+
+def update_backup(refID, b64str, Force):
+ con = get_connection("backups")
+ cur = con.cursor()
+ res = cur.execute("UPDATE Backups SET ForceOffer=?, Payload=? WHERE BackupID=" + str(refID), (Force, b64str))
+ con.commit()
+ con.close()
+ return
+
+def offer_backup_id_to_new_device(refID, device_id):
+ srcBackup = get_backup(refID)
+ if srcBackup is None:
+ return
+ add_backup(device_id, srcBackup)
+ return
+
+## MANUAL TRANSFER EXAMPLE
+## TODO: Admin API endpoint for this
+# offer_backup_id_to_new_device(2, "f7c9c95ce5f6d06a")