/ blottertrax / config.py
config.py
1 import configparser 2 import os 3 4 5 class _ConfigBase: 6 # We don't want to accidentally add anything to this config. 7 # This allows us to throw and error in the __new__ call above if a programmer makes a typo. 8 # For instance, using cls._instance.YOUTUBE_CLIENT_SECRET rather than cls._instance.YOUTUBE.CLIENT_SECRET 9 def __setattr__(self, key, value): 10 if hasattr(self, key): 11 object.__setattr__(self, key, value) 12 else: 13 raise TypeError( 14 "{} is a frozen class. You cannot dynamically add properties. Property attempted: {}, value: {}".format( 15 self, key, value)) 16 17 18 class Config(_ConfigBase): 19 _instance = None 20 21 # Note: You must specify a default value. The value of None is fine. 22 class _REDDIT(_ConfigBase): 23 CLIENT_ID: str = None 24 CLIENT_SECRET: str = None 25 USER_NAME: str = None 26 PASSWORD: str = None 27 28 SUBREDDIT: str = None 29 REMOVE_SUBMISSIONS_ON_ERROR: bool = False 30 MINIMUM_ACCOUNT_AGE = 200 31 MINIMUM_COMMENT_KARMA = 50 32 USER_AGENT = "BlotterTrax /r/listentothis submission bot" 33 34 class _YOUTUBE(_ConfigBase): 35 KEY: str = None 36 THRESHOLD: int = 1_000_000 37 38 class _LASTFM(_ConfigBase): 39 KEY: str = None 40 SECRET: str = None 41 USERNAME: str = None 42 PASSWORD: str = None 43 LISTENER_THRESHOLD: int = 500_000 44 SCROBBLE_THRESHOLD: int = 4_000_000 45 46 class _SOUNDCLOUD(_ConfigBase): 47 KEY: str = None 48 THRESHOLD: int = 1_000_000 49 50 class _MUSICBRAINZ(_ConfigBase): 51 USER: str = None 52 PASSWORD: str = None 53 54 class _APP(_ConfigBase): 55 OVERALL_LISTEN_THRESHOLD: int = 2_000_000 56 57 REDDIT: _REDDIT = _REDDIT() 58 YOUTUBE: _YOUTUBE = _YOUTUBE() 59 LASTFM: _LASTFM = _LASTFM() 60 SOUNDCLOUD: _SOUNDCLOUD = _SOUNDCLOUD() 61 MUSICBRAINZ: _MUSICBRAINZ = _MUSICBRAINZ() 62 APP: _APP = _APP() 63 64 # Ensure singleton so we aren't reading the config over and over for each service using it. 65 def __new__(cls): 66 if cls._instance is None: 67 cls._instance = super(Config, cls).__new__(cls) 68 config = configparser.ConfigParser(strict=False, interpolation=None) 69 70 try: 71 config.read('{}/../conf/config.ini'.format(os.path.dirname(os.path.realpath(__file__)))) 72 cls._instance.REDDIT.CLIENT_ID = config.get('REDDIT', 'CLIENT_ID') 73 cls._instance.REDDIT.CLIENT_SECRET = config.get('REDDIT', 'CLIENT_SECRET') 74 cls._instance.REDDIT.PASSWORD = config.get('REDDIT', 'PASSWORD') 75 cls._instance.REDDIT.USER_NAME = config.get('REDDIT', 'USER_NAME') 76 cls._instance.REDDIT.SUBREDDIT = config.get('REDDIT', 'SUBREDDIT') 77 78 cls._instance.REDDIT.MINIMUM_ACCOUNT_AGE = config.getint('REDDIT', 'MINIMUM_ACCOUNT_AGE') 79 cls._instance.REDDIT.MINIMUM_COMMENT_KARMA = config.getint('REDDIT', 'MINIMUM_COMMENT_KARMA') 80 cls._instance.REDDIT.USER_AGENT = config.get('REDDIT', 'USER_AGENT') 81 82 cls._instance.REDDIT.REMOVE_SUBMISSIONS_ON_ERROR = config.getboolean('REDDIT', 'REMOVE_SUBMISSIONS') 83 84 cls._instance.YOUTUBE.KEY = config.get('YOUTUBE', 'KEY') 85 86 cls._instance.LASTFM.KEY = config.get('LASTFM', 'KEY') 87 cls._instance.LASTFM.SECRET = config.get('LASTFM', 'SECRET') 88 cls._instance.LASTFM.USERNAME = config.get('LASTFM', 'USERNAME') 89 cls._instance.LASTFM.PASSWORD = config.get('LASTFM', 'PASSWORD') 90 91 cls._instance.LASTFM.LISTENER_THRESHOLD = config.getint('LASTFM', 'LISTENER_THRESHOLD', 92 fallback=500_000) 93 cls._instance.LASTFM.SCROBBLE_THRESHOLD = config.getint('LASTFM', 'SCROBBLE_THRESHOLD', 94 fallback=4_000_000) 95 96 cls._instance.SOUNDCLOUD.KEY = config.get('SOUNDCLOUD', 'KEY') 97 cls._instance.SOUNDCLOUD.THRESHOLD = config.getint('SOUNDCLOUD', 'THRESHOLD', fallback=1_000_000) 98 99 cls._instance.MUSICBRAINZ.USER = config.get('MUSICBRAINZ', 'USER') 100 cls._instance.MUSICBRAINZ.PASSWORD = config.get('MUSICBRAINZ', 'PASSWORD') 101 102 cls._instance.APP.OVERALL_LISTEN_THRESHOLD = config.getint('APP', 103 'OVERALL_LISTEN_THRESHOLD', 104 fallback=3_000_000) 105 106 except TypeError as e: 107 print(e) 108 exit('Additional field detected on config class. Please add this in the proper way.') 109 except Exception: 110 exit("Please make sure conf/config.ini is set") 111 112 return cls._instance 113 114 def is_config_valid(self) -> bool: 115 return True