diff --git a/Pipfile b/Pipfile index 3c92edc..9a38135 100644 --- a/Pipfile +++ b/Pipfile @@ -6,8 +6,8 @@ verify_ssl = true [dev-packages] [packages] -praw = "*" toml = "*" +praw = "*" [requires] python_version = "3.7" diff --git a/Pipfile.lock b/Pipfile.lock index 2ce9ee2..1177136 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -61,10 +61,10 @@ }, "six": { "hashes": [ - "sha256:1f1b7d42e254082a9db6279deae68afb421ceba6158efa6131de7b3003ee93fd", - "sha256:30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66" + "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a", + "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c" ], - "version": "==1.13.0" + "version": "==1.14.0" }, "toml": { "hashes": [ @@ -83,10 +83,10 @@ }, "urllib3": { "hashes": [ - "sha256:a8a318824cc77d1fd4b2bec2ded92646630d7fe8619497b142c84a9e6f5a7293", - "sha256:f3c5fd51747d450d4dcf6f923c81f78f811aab8205fda64b0aba34a4e48b0745" + "sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc", + "sha256:87716c2d2a7121198ebcb7ce7cccf6ce5e9ba539041cfbaeecfb641dc0bf6acc" ], - "version": "==1.25.7" + "version": "==1.25.8" }, "websocket-client": { "hashes": [ diff --git a/pointsbot.sample.toml b/pointsbot.sample.toml index 467040f..6e87ee9 100644 --- a/pointsbot.sample.toml +++ b/pointsbot.sample.toml @@ -17,8 +17,9 @@ subreddit = "" ################################################################################ [filepaths] -# The name of the SQLite database file to use. -database = "pointsbot.db" +# The name of the SQLite database file to use. This value is optional; if not +# specified, a default filepath will be used. +database = "" ################################################################################ diff --git a/pointsbot/bot.py b/pointsbot/bot.py index 0ffa0a3..1b55fb3 100644 --- a/pointsbot/bot.py +++ b/pointsbot/bot.py @@ -19,7 +19,8 @@ TEST_COMMENTS = False def run(): - cfg = config.Config.load() + #cfg = config.Config.load() + cfg = config.load() levels = cfg.levels reddit = praw.Reddit(client_id=cfg.client_id, diff --git a/pointsbot/config.py b/pointsbot/config.py index 8f583a8..67bab15 100644 --- a/pointsbot/config.py +++ b/pointsbot/config.py @@ -1,6 +1,7 @@ import os import os.path -# from os.path import abspath, dirname, expanduser, join +from collections import namedtuple +from copy import deepcopy import toml @@ -8,24 +9,34 @@ from .level import Level ### Globals ### -# ROOTPATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) +DATADIR = os.path.join(os.path.expanduser('~'), '.pointsbot') +CONFIGPATH = os.path.join(DATADIR, 'pointsbot.toml') + +# Path to the sample config file +SAMPLEPATH = os.path.abspath(os.path.join(os.path.dirname(__file__), + '..', + 'pointsbot.sample.toml')) ### Classes ### class Config: - DATADIR = os.path.join(os.path.expanduser('~'), '.pointsbot') - PATH = os.path.join(DATADIR, 'pointsbot.toml') - # Default config vals - DEFAULT_DBPATH = os.path.join(DATADIR, 'pointsbot.db') + # DEFAULT_DBPATH = os.path.join(DATADIR, 'pointsbot.db') + DEFAULT_DBNAME = 'pointsbot.db' - def __init__(self, subreddit, client_id, client_secret, username, password, - levels, database_path=DEFAULT_DBPATH): - self.subreddit = subreddit + def __init__(self, filepath, subreddit, client_id, client_secret, username, + password, levels, database_path=None): + self._filepath = filepath + self._dirname = os.path.dirname(filepath) + + if not database_path: + database_path = os.path.join(self._dirname, self.DEFAULT_DBNAME) self.database_path = database_path + self.subreddit = subreddit + self.client_id = client_id self.client_secret = client_secret self.username = username @@ -34,32 +45,103 @@ class Config: self.levels = levels @classmethod - def load(cls, filepath=PATH): + def from_toml(cls, filepath): obj = toml.load(filepath) # Create list of level objects, in ascending order by point value levels = [] for lvl in obj['levels']: - flair_template_id = lvl['flair_template_id'] - if flair_template_id == "": + flair_template_id = lvl.get('flair_template_id', None) + if flair_template_id == '': flair_template_id = None levels.append(Level(lvl['name'], lvl['points'], flair_template_id)) levels.sort(key=lambda l: l.points) - database_path = os.path.join(cls.DATADIR, obj['filepaths']['database']) + # database_path = os.path.join(DATADIR, obj['filepaths']['database']) return cls( + filepath, obj['core']['subreddit'], obj['credentials']['client_id'], obj['credentials']['client_secret'], obj['credentials']['username'], obj['credentials']['password'], levels, - database_path=database_path, + database_path=obj['filepaths']['database'], + # database_path=database_path, ) - @classmethod - def dump(cls, obj, filepath=PATH): - pass + def save(self): + obj = deepcopy(vars(self)) + orig_levels = obj['levels'] + obj['levels'] = [] + for level in orig_levels: + obj['levels'].append({ + 'name': level.name, + 'points': level.points, + 'flair_template_id': level.flair_template_id, + }) + + with open(self._filepath, 'w') as f: + toml.dump(obj, f) + + +### Functions ### + + +def load(filepath=CONFIGPATH): + # Prompt user for config values if file doesn't exist + if not os.path.exists(filepath): + datadir = os.path.dirname(filepath) + if not os.path.exists(datadir): + os.makedirs(datadir) + + # with open(SAMPLEPATH) as fin: + # with open(filepath, 'w') as fout: + # fout.write(fin.read()) + + interactive_config(filepath) + + return Config.from_toml(filepath) + + +### Interactive Config Editing ### + + +def interactive_config(dest): + configvals = { + 'core': {}, + 'filepaths': {}, + 'credentials': {}, + 'levels': [], + } + + print('#' * 80 + '\nCONFIGURING THE BOT\n' + '#' * 80) + print('\nType a value for each field, then press enter.') + print('\nIf the field is specified as optional, leave blank to skip.\n') + + configvals['core']['subreddit'] = input('subreddit? ') + print() + configvals['filepaths']['database'] = input('database filename? (optional) ') + print() + configvals['credentials']['client_id'] = input('client_id? ') + configvals['credentials']['client_secret'] = input('client_secret? ') + configvals['credentials']['username'] = input('username? ') + configvals['credentials']['password'] = input('password? ') + + add_another_level = True + while add_another_level: + level = {} + level['name'] = input('\nLevel name? ') + level['points'] = input('Level points? ') + level['flair_template_id'] = input('Flair template ID? (optional) ') + configvals['levels'].append(level) + + response = input('\nAdd another level? (y/n) ') + add_another_level = response.lower().startswith('y') + + with open(dest, 'w') as f: + toml.dump(configvals, f) + print(f'\nConfig settings saved to {dest}')