Files
PointsBot/pointsbot/config.py

199 lines
7.0 KiB
Python
Raw Normal View History

import os
2020-02-01 00:23:15 -08:00
import os.path
2020-02-04 23:21:53 -08:00
from collections import namedtuple
from copy import deepcopy
2020-02-03 18:53:23 -08:00
import toml
2020-02-01 00:23:15 -08:00
from .level import Level
### Globals ###
2020-02-04 23:21:53 -08:00
DATADIR = os.path.join(os.path.expanduser('~'), '.pointsbot')
CONFIGPATH = os.path.join(DATADIR, 'pointsbot.toml')
# Path to the sample config file
# Unused for now
2020-02-04 23:21:53 -08:00
SAMPLEPATH = os.path.abspath(os.path.join(os.path.dirname(__file__),
'..',
'pointsbot.sample.toml'))
2020-02-01 00:23:15 -08:00
### Primary 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)
interactive_config(filepath)
return Config.from_toml(filepath)
2020-02-01 00:23:15 -08:00
### Classes ###
class Config:
2020-02-03 18:53:23 -08:00
# Default config vals
DEFAULT_DB_NAME = 'pointsbot.db'
DEFAULT_LOG_NAME = 'pointsbot.log'
2020-02-03 18:53:23 -08:00
2020-02-04 23:21:53 -08:00
def __init__(self, filepath, subreddit, client_id, client_secret, username,
password, levels, database_path=None, log_path=None,
2020-12-13 13:33:59 -08:00
feedback_url=None, scoreboard_url=None, tag_string=None):
2020-02-04 23:21:53 -08:00
self._filepath = filepath
self._dirname = os.path.dirname(filepath)
if not log_path:
log_path = os.path.join(self._dirname, self.DEFAULT_LOG_NAME)
elif os.path.isdir(log_path):
log_path = os.path.join(log_path, self.DEFAULT_LOG_NAME)
self.log_path = log_path
# TODO init logging here so it can be used immediately?
2020-02-04 23:21:53 -08:00
if not database_path:
database_path = os.path.join(self._dirname, self.DEFAULT_DB_NAME)
2020-02-05 10:39:05 -08:00
elif os.path.isdir(database_path):
database_path = os.path.join(database_path, self.DEFAULT_DB_NAME)
2020-02-01 00:23:15 -08:00
self.database_path = database_path
2020-02-03 18:53:23 -08:00
2020-02-04 23:21:53 -08:00
self.subreddit = subreddit
self.feedback_url = feedback_url
self.scoreboard_url = scoreboard_url
2020-02-04 23:21:53 -08:00
2020-02-03 18:53:23 -08:00
self.client_id = client_id
self.client_secret = client_secret
self.username = username
self.password = password
self.levels = levels
2020-12-13 13:33:59 -08:00
if tag_string is None:
self.tags = None
else:
self.tags = tag_string.lower().split(",")
2020-02-01 00:23:15 -08:00
@classmethod
2020-02-04 23:21:53 -08:00
def from_toml(cls, filepath):
2020-02-03 18:53:23 -08:00
obj = toml.load(filepath)
2020-02-01 00:23:15 -08:00
# Create list of level objects, in ascending order by point value
2020-02-01 00:23:15 -08:00
levels = []
2020-02-03 18:53:23 -08:00
for lvl in obj['levels']:
2020-02-04 23:21:53 -08:00
flair_template_id = lvl.get('flair_template_id', None)
if flair_template_id == '':
2020-02-03 18:53:23 -08:00
flair_template_id = None
levels.append(Level(lvl['name'], lvl['points'], flair_template_id))
levels.sort(key=lambda l: l.points)
2020-02-05 10:39:05 -08:00
dbpath = obj['filepaths']['database']
if dbpath:
dbpath = os.path.abspath(os.path.expandvars(os.path.expanduser(dbpath)))
2020-02-01 00:23:15 -08:00
logpath = obj['filepaths']['log']
if logpath:
logpath = os.path.abspath(os.path.expandvars(os.path.expanduser(logpath)))
2020-02-01 00:23:15 -08:00
return cls(
2020-02-04 23:21:53 -08:00
filepath,
2020-02-03 18:53:23 -08:00
obj['core']['subreddit'],
obj['credentials']['client_id'],
obj['credentials']['client_secret'],
obj['credentials']['username'],
obj['credentials']['password'],
levels,
2020-02-05 10:39:05 -08:00
database_path=dbpath,
log_path=logpath,
feedback_url=obj['links']['feedback'],
scoreboard_url=obj['links']['scoreboard'],
2020-12-13 13:33:59 -08:00
tag_string=obj['core']['valid_tags'],
2020-02-01 00:23:15 -08:00
)
2020-02-04 23:21:53 -08:00
def save(self):
obj = deepcopy(vars(self))
orig_levels, obj['levels'] = obj['levels'], []
# obj['levels'] = []
2020-02-04 23:21:53 -08:00
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)
### Interactive Config Editing ###
def interactive_config(dest):
configvals = {
'core': {},
'links': {},
2020-02-04 23:21:53 -08:00
'filepaths': {},
'credentials': {},
'levels': [],
}
print('\n' + ('#' * 80) + '\nCONFIGURING THE BOT\n' + ('#' * 80) + '\n')
print('Type a value for each field, then press enter.')
print('\nIf a field is specified as optional, then you can skip it by just '
'pressing enter.')
print("\nIt is recommended that you skip any fields that you aren't sure "
'about')
2020-02-04 23:21:53 -08:00
print('\n*** Core Configuration ***\n')
configvals['core']['subreddit'] = input('name of subreddit to monitor? ')
2020-02-04 23:21:53 -08:00
print()
configvals['filepaths']['database'] = input('database filepath? (optional) ')
configvals['filepaths']['log'] = input('log filepath? (optional) ')
print('\n*** Website Links ***\n')
print('These values should only be provided if you have valid URLs for '
'websites that provide these services for your subreddit.\n')
configvals['links']['feedback'] = input('feedback webpage URL? (optional) ')
configvals['links']['scoreboard'] = input('scoreboard webpage URL? (optional) ')
print('\n*** Bot account details ***\n')
2020-02-04 23:21:53 -08:00
configvals['credentials']['client_id'] = input('client_id? ')
configvals['credentials']['client_secret'] = input('client_secret? ')
configvals['credentials']['username'] = input('bot username? ')
configvals['credentials']['password'] = input('bot password? ')
print('\n*** Flair Levels ***\n')
print('These fields will determine the different levels that your '
'subreddit users can achieve by earning points.')
print('\nFor each level, you should provide...')
print("\t- Level name: the text that appears in the user's flair")
print('\t- Level points: the number of points needed to reach the level')
print('\t- Flair template ID: (optional) the flair template ID in your')
print('\t subreddit to be used for this level flair')
print('\nThese may be provided in any order; the bot will sort them later.')
print('\nDo not provide more than one level with the same number of points.')
print('\nNote that at the moment, providing a level points value of zero '
'will not set a default flair, because users must solve at least one '
'issue before the bot will keep track of their points and set their '
'flair for the first time.')
print('\nFor any more questions, please refer to the README on the Github '
'page.')
response = 'y'
while response.lower().startswith('y'):
print('\n*** Adding a level ***\n')
2020-02-04 23:21:53 -08:00
level = {}
level['name'] = input('Level name? ')
2020-02-05 10:39:05 -08:00
level['points'] = int(input('Level points? '))
2020-02-04 23:21:53 -08:00
level['flair_template_id'] = input('Flair template ID? (optional) ')
configvals['levels'].append(level)
response = input('\nAdd another level? (y/n) ')
with open(dest, 'w') as f:
toml.dump(configvals, f)
2020-02-05 10:39:05 -08:00
print('#' * 80 + f'\nConfig settings saved to {dest}\n' + '#' * 80)
2020-02-01 00:23:15 -08:00