diff --git a/.gitignore b/.gitignore index 550648c7b6..0f969ba7cc 100644 --- a/.gitignore +++ b/.gitignore @@ -106,6 +106,7 @@ out/ # Personal load details src/ web/ +data/*.db data/last-location*.json data/cells-*.json data/map-caught-*.json diff --git a/pokemongo_bot/__init__.py b/pokemongo_bot/__init__.py index 62d3969ba7..eaa6572056 100644 --- a/pokemongo_bot/__init__.py +++ b/pokemongo_bot/__init__.py @@ -29,6 +29,7 @@ from pokemongo_bot.socketio_server.runner import SocketIoRunner from pokemongo_bot.websocket_remote_control import WebsocketRemoteControl from pokemongo_bot.base_dir import _base_dir +from pokemongo_bot.datastore import DatabaseManager, Datastore from worker_result import WorkerResult from tree_config_builder import ConfigException, MismatchTaskApiVersion, TreeConfigBuilder from inventory import init_inventory @@ -36,7 +37,7 @@ import struct -class PokemonGoBot(object): +class PokemonGoBot(Datastore): @property def position(self): return self.api._position_lat, self.api._position_lng, 0 @@ -56,6 +57,9 @@ def player_data(self): def __init__(self, config): self.config = config + self.database = DatabaseManager(self) + super(PokemonGoBot, self).__init__() + self.fort_timeouts = dict() self.pokemon_list = json.load( open(os.path.join(_base_dir, 'data', 'pokemon.json')) @@ -679,6 +683,9 @@ def login(self): ) time.sleep(10) + with self.database.backend.connection as conn: + conn.execute('''INSERT INTO login (timestamp, message) VALUES (?, ?)''', (time.time(), 'LOGIN_SUCCESS')) + self.event_manager.emit( 'login_successful', sender=self, diff --git a/pokemongo_bot/datastore.py b/pokemongo_bot/datastore.py new file mode 100644 index 0000000000..38f4f2c8b6 --- /dev/null +++ b/pokemongo_bot/datastore.py @@ -0,0 +1,51 @@ +""" +Use the built-in sqlite3 library as a datastore, + +To handle database migrations, use the `yoyo-migrations` package. +For further details on this, see: +https://pypi.python.org/pypi/yoyo-migrations +""" + +import inspect +import os +import sys +import warnings + +try: + from yoyo import read_migrations, get_backend +except ImportError: + warnings.warn('Please run `pip install -r requirements.txt` to ensure you have the latest required packages') + sys.exit(-1) + + +_DEFAULT = object() + +class DatabaseManager(object): + def __init__(self, bot): + self.bot = bot + + @property + def backend(self): + return get_backend('sqlite:///data/{}.db'.format(self.bot.config.username)) + + +class Datastore(object): + MIGRATIONS_PATH = _DEFAULT + + def __init__(self): + """ + When a subclass is initiated, the migrations should automatically be run. + """ + path = self.MIGRATIONS_PATH + + if path is _DEFAULT: + # `migrations` should be a sub directory of the calling package, unless a path is specified + filename = inspect.stack()[1][1] + path = os.path.join(os.path.dirname(filename), 'migrations') + elif not os.path.isdir(str(path)): + raise RuntimeError('The migrations directory does not exist') + + backend = self.database.backend + with backend.connection as conn: + migrations = read_migrations(path) + backend.apply_migrations(backend.to_apply(migrations)) diff --git a/pokemongo_bot/migrations/pokemongobot.py b/pokemongo_bot/migrations/pokemongobot.py new file mode 100644 index 0000000000..2a68265241 --- /dev/null +++ b/pokemongo_bot/migrations/pokemongobot.py @@ -0,0 +1,5 @@ +from yoyo import step + +step( + "CREATE TABLE login (timestamp INTEGER, message TEXT)", +) diff --git a/requirements.txt b/requirements.txt index 4179e1b002..adeeabab87 100644 --- a/requirements.txt +++ b/requirements.txt @@ -23,3 +23,4 @@ timeout-decorator==0.3.2 raven==5.23.0 demjson==2.2.4 greenlet==0.4.9 +yoyo-migrations==5.0.3