From 376dd8683ec686d653b40bdf1a92931b9e5edd41 Mon Sep 17 00:00:00 2001 From: Kevin Zheng Date: Fri, 15 May 2020 14:24:58 -0700 Subject: [PATCH] Convert CFBank to sqlite3 --- python/CFBank.py | 79 ++++++++++++++----------------- python/CFSqlDb.py | 8 ++++ python/events/init/CFBank_Init.py | 39 +++++++++++++++ 3 files changed, 82 insertions(+), 44 deletions(-) create mode 100644 python/CFSqlDb.py create mode 100644 python/events/init/CFBank_Init.py diff --git a/python/CFBank.py b/python/CFBank.py index d4106402c..cb668b1e1 100644 --- a/python/CFBank.py +++ b/python/CFBank.py @@ -4,15 +4,15 @@ Created by: Joris Bontje This module stores bank account information. """ -import os.path -import shelve - import Crossfire +import CFSqlDb as cfdb class CFBank: - def __init__(self, bankfile): - self.bankdb_file = os.path.join(Crossfire.LocalDirectory(), bankfile) - self.bankdb = shelve.open(self.bankdb_file) + def __init__(self): + self.bankdb = cfdb.open() + + def init_schema(self): + self.bankdb.execute("CREATE TABLE IF NOT EXISTS bank_accounts ('name' TEXT PRIMARY KEY, 'balance' INT);") def __enter__(self): return self @@ -20,60 +20,51 @@ class CFBank: def __exit__(self, exc_type, exc_value, traceback): self.close() + def ensure(self, user): + self.bankdb.execute("INSERT OR IGNORE INTO bank_accounts VALUES (?, 0)", (user,)) + def deposit(self, user, amount): - if not user in self.bankdb: - self.bankdb[user] = amount - else: - balance = self.bankdb[user] - self.bankdb[user] = balance + amount + if amount > 0: + self.ensure(user) + self.bankdb.execute("UPDATE bank_accounts SET balance = balance + ? WHERE name=?", (amount, user)) def withdraw(self, user, amount): - if user in self.bankdb: - balance = self.getbalance(user) - if balance >= amount: - self.bankdb[user] = balance - amount - return 1 - return 0 + if self.getbalance(user) - amount < 0: + return 0 + else: + self.bankdb.execute("UPDATE bank_accounts SET balance = balance - ? WHERE name=?", (amount, user)) + return 1 def getbalance(self, user): - self._convert(user) - if user in self.bankdb: - return self.bankdb[user] + self.convert_legacy_balance(user) + c = self.bankdb.cursor() + c.execute("SELECT balance FROM bank_accounts WHERE name=?", (user,)) + result = c.fetchone() + if result is not None: + return result[0] else: return 0 def remove_account(self, user): - if user in self.bankdb: - del self.bankdb[user] - Crossfire.Log(Crossfire.LogDebug, - "%s's bank account removed." % user) - return 1 - else: - return 0 + c.execute("DELETE FROM bank_accounts WHERE name=?", (user,)) def close(self): + self.bankdb.commit() self.bankdb.close() - def _convert(self, name): + def convert_legacy_balance(self, name): """Move a player's balance from the player file to the bank.""" player = Crossfire.FindPlayer(name) if player is None: - return 0 - old_balance = _balance_legacy(player) - if old_balance > 0: - Crossfire.Log(Crossfire.LogInfo, - "Converting bank account for %s with %d silver" \ - % (name, old_balance)) + return + balance_str = player.ReadKey("balance") + try: + old_balance = int(balance_str) + Crossfire.Log(Crossfire.LogInfo, "Converting bank account for %s with %d silver" % (name, old_balance)) self.deposit(name, old_balance) - player.WriteKey("balance", "moved-to-bank-file", 1) + except ValueError: + pass + player.WriteKey("balance", None, 0) def open(): - return CFBank('ImperialBank_DB') - -def _balance_legacy(player): - """Return the balance of the given player's bank account.""" - try: - balance_str = player.ReadKey("balance") - return int(balance_str) - except ValueError: - return 0 + return CFBank() diff --git a/python/CFSqlDb.py b/python/CFSqlDb.py new file mode 100644 index 000000000..c536deea7 --- /dev/null +++ b/python/CFSqlDb.py @@ -0,0 +1,8 @@ +import os.path +import sqlite3 + +import Crossfire + +def open(): + path = os.path.join(Crossfire.LocalDirectory(), 'crossfire.db') + return sqlite3.connect(path) diff --git a/python/events/init/CFBank_Init.py b/python/events/init/CFBank_Init.py new file mode 100644 index 000000000..56f823c72 --- /dev/null +++ b/python/events/init/CFBank_Init.py @@ -0,0 +1,39 @@ +import os.path + +import Crossfire +import CFBank + +def convert_bdb(bank): + path = os.path.join(Crossfire.LocalDirectory(), 'ImperialBank_DB.db') + if os.path.isfile(path): + Crossfire.Log(Crossfire.LogInfo, "Converting ImperialBank_DB.db (BDB)") + import berkeleydb.dbshelve as shelve + accounts = shelve.open(path, 'r') + for account in accounts.keys(): + name = account.decode('ascii') + balance = accounts[account] + bank.deposit(name, balance) + accounts.close() + bak_file = os.path.join(Crossfire.LocalDirectory(), 'ImperialBank_DB.db.bak') + os.rename(path, bak_file) + +def convert(bank): + path = os.path.join(Crossfire.LocalDirectory(), 'ImperialBank_DB') + if os.path.isfile(path): + Crossfire.Log(Crossfire.LogInfo, "Converting ImperialBank_DB (DBM)") + import shelve + s = shelve.open(path, 'r') + for name, balance in s.iteritems(): + bank.deposit(name, balance) + s.close() + bak_file = os.path.join(Crossfire.LocalDirectory(), 'ImperialBank_DB.bak') + os.rename(path, bak_file) + +def main(): + Crossfire.Log(Crossfire.LogInfo, "Initializing CFBank") + with CFBank.CFBank() as bank: + bank.init_schema() + convert_bdb(bank) + convert(bank) + +main()