2020-02-04 16:24:24 -08:00
|
|
|
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
|
|
|
|
|
SAMPLEPATH = os.path.abspath(os.path.join(os.path.dirname(__file__),
|
|
|
|
|
'..',
|
|
|
|
|
'pointsbot.sample.toml'))
|
2020-02-01 00:23:15 -08:00
|
|
|
|
|
|
|
|
### Classes ###
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Config:
|
|
|
|
|
|
2020-02-03 18:53:23 -08:00
|
|
|
# Default config vals
|
2020-02-04 23:21:53 -08:00
|
|
|
DEFAULT_DBNAME = 'pointsbot.db'
|
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):
|
|
|
|
|
self._filepath = filepath
|
|
|
|
|
self._dirname = os.path.dirname(filepath)
|
|
|
|
|
|
|
|
|
|
if not database_path:
|
|
|
|
|
database_path = os.path.join(self._dirname, self.DEFAULT_DBNAME)
|
2020-02-05 10:39:05 -08:00
|
|
|
elif os.path.isdir(database_path):
|
|
|
|
|
database_path = os.path.join(database_path, self.DEFAULT_DBNAME)
|
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
|
|
|
|
|
|
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-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
|
|
|
|
2020-02-04 16:24:24 -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
|
|
|
|
|
|
|
|
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,
|
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'] = []
|
|
|
|
|
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)
|
|
|
|
|
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.')
|
2020-05-10 11:26:09 -07:00
|
|
|
print('\nIf a field is specified as optional, then you can skip it by just '
|
|
|
|
|
'pressing enter.\n')
|
2020-02-04 23:21:53 -08:00
|
|
|
|
2020-05-10 11:26:09 -07:00
|
|
|
configvals['core']['subreddit'] = input('name of subreddit to monitor? ')
|
2020-02-04 23:21:53 -08:00
|
|
|
print()
|
|
|
|
|
configvals['filepaths']['database'] = input('database filename? (optional) ')
|
2020-05-10 11:26:09 -07:00
|
|
|
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? ')
|
2020-05-10 11:26:09 -07:00
|
|
|
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.')
|
|
|
|
|
|
|
|
|
|
# add_another_level = True
|
|
|
|
|
response = 'y'
|
|
|
|
|
while response.lower().startswith('y'):
|
|
|
|
|
print('\n*** Adding a level ***')
|
2020-02-04 23:21:53 -08:00
|
|
|
level = {}
|
|
|
|
|
level['name'] = input('\nLevel 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) ')
|
2020-05-10 11:26:09 -07:00
|
|
|
# add_another_level = response.lower().startswith('y')
|
2020-02-04 23:21:53 -08:00
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|