<commit_before>from pathlib import Path
from typing import Dict

from ruamel.yaml import safe_load as yaml_load

CONFIG_FILE = 'config.yaml'
CONFIG_VERSION = 1
BASIC_CONFIG = f'''\
version: {CONFIG_VERSION}
twitch:
    client_id: <your client-id>

main:
    channel: <twitch channel>
    # Depends on stream. Leave blank for source (chunked) quality.
    quality: <quality>
    temp_dir: <path to temporary directory>

storage:
    path: <path where vods should be stored>
    # Python 3.6 f-string. Valid arguments: {{title}} {{id}} {{type}} {{channel}} {{game}} {{date}}
    # '*' will be added to the new filename if file already exist in storage
    vod_path: <"{{channel}}/{{id}} {{date:%Y-%m-%d}} {{title}}.ts">

telegram:
    enabled: False
    api_token: <Telegram bot API token>
    chat_id: <your chat id>
'''


def init(path: str = CONFIG_FILE) -> Dict:
    if not Path(path).exists():
        create(path)
        print(f'Please check configuration file {path}')
        quit(0)
    return load(path)


def create(path: str) -> None:
    with open(path, 'w') as file:
        file.write(BASIC_CONFIG)


def load(path: str) -> Dict:
    with open(path, 'rt') as file:
        config = yaml_load(file.read())
    validate(config)
    return config


def validate(config: dict) -> None:
    groups = {'twitch', 'main', 'storage'}
    twitch_keys = {'client_id'}
    main_keys = {'channel', 'quality', 'temp_dir'}
    storage_keys = {'path', 'vod_path'}
    error_msg = "'{key}' is empty or some keys missing {keys}"
    if not config.get('version') or config['version'] != CONFIG_VERSION:
        raise ValidationConfigError(f'Configuration file {CONFIG_FILE} does not match. Try to create a new one.')
    if not groups.issubset(config.keys()):
        raise ValidationConfigError(f'Some keys missing {groups - config.keys()}')
    if not config['twitch'] or not twitch_keys.issubset(config['twitch'].keys()):
        raise ValidationConfigError(error_msg.format(key='twitch', keys=twitch_keys - config['twitch'].keys()))
    if not config['main'] or not main_keys.issubset(config['main'].keys()):
        raise ValidationConfigError(error_msg.format(key='main', keys=main_keys - config['main'].keys()))
    if not config['storage'] or not storage_keys.issubset(config['storage'].keys()):
        raise ValidationConfigError(error_msg.format(key='storage', keys=main_keys - config['storage'].keys()))


class ValidationConfigError(Exception):
    def __init__(self, message: str) -> None:
        self.message: str = message<commit_msg>Refactoring config.py<commit_after>from typing import Dict, Optional

from strictyaml import as_document, Map, Bool, Regex, load as yaml_load

_WORD = Regex('^[\w]+$')
_PATH = Regex('[^<>]+')

CONFIG_FILE = 'config.yaml'
__CONFIG_VERSION = 1
__CONFIG_SCHEMA = Map({
    'version': Regex(f'{__CONFIG_VERSION}'),
    'twitch': Map({'client_id': _WORD, }),
    'main': Map({'channel': _WORD, 'quality': Regex('^[\w]*$'), 'temp_dir': _PATH, }),
    'storage': Map({'path': _PATH, 'vod_path': _PATH, }),
    'telegram': Map({'enabled': Bool(), 'api_token': Regex('^[\w:_\-]+$'), 'chat_id': _WORD, }),
})


def load(path: str = CONFIG_FILE) -> Optional[Dict]:
    with open(path, 'rt') as file:
        return yaml_load(file.read(), schema=__CONFIG_SCHEMA).data


def create(path: str = CONFIG_FILE) -> None:
    with open(path, 'w') as file:
        config = as_document({
            'version': __CONFIG_VERSION,
            'twitch': {
                'client_id': '<your client-id>',
            },
            'main': {
                'channel': '<twitch channel>',
                'quality': '<quality>',
                'temp_dir': '<path to temporary directory>',
            },
            'storage': {
                'path': '<path where vods should be stored>',
                'vod_path': '<"{{channel}}/{{id}} {{date:%Y-%m-%d}} {{title}}.ts">',
            },
            'telegram': {
                'enabled': False,
                'api_token': '<Telegram bot API token>',
                'chat_id': '<your chat id>',
            },
        })

        comment_quality = 'Depends on stream. Leave blank for source (chunked) quality.'
        comment_vod_path = (
            "Python 3.6 f-string. Valid arguments: {{title}} {{id}} {{type}} {{channel}} {{game}} {{date}}\n"
            "'*' will be added to the new filename if file already exist in storage")
        config.as_marked_up()['main'].yaml_set_comment_before_after_key('quality', before=comment_quality, indent=2)
        config.as_marked_up()['storage'].yaml_set_comment_before_after_key('vod_path', before=comment_vod_path,
                                                                           indent=2)
        file.write(config.as_yaml())
{'fraction_non_alphanumeric': 0.16044463087248323, 'fraction_numerical': 0.0018875838926174498, 'mean_word_length': 3.0346869712351947, 'pattern_counts': {'":': 0, '<': 20, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 3, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4381901', 'n_tokens_mistral': 1489, 'n_tokens_neox': 1467, 'n_words': 386}