1# SPDX-License-Identifier: ISC 2# Copyright (c) Justus Winter <4winter@informatik.uni-hamburg.de> 3 4import os 5import re 6import collections 7import shlex 8 9from afew.configparser import ConfigParser 10from afew.FilterRegistry import all_filters 11 12user_config_dir = os.path.join(os.environ.get('XDG_CONFIG_HOME', 13 os.path.expanduser('~/.config')), 14 'afew') 15user_config_dir = os.path.expandvars(user_config_dir) 16 17settings = ConfigParser() 18# preserve the capitalization of the keys. 19settings.optionxform = str 20 21settings.readfp(open(os.path.join(os.path.dirname(__file__), 'defaults', 'afew.config'))) 22settings.read(os.path.join(user_config_dir, 'config')) 23 24# All the values for keys listed here are interpreted as ;-delimited lists 25value_is_a_list = ['tags', 'tags_blacklist'] 26mail_mover_section = 'MailMover' 27 28section_re = re.compile(r'^(?P<name>[a-z_][a-z0-9_]*)(\((?P<parent_class>[a-z_][a-z0-9_]*)\)|\.(?P<index>\d+))?$', re.I) 29 30 31def get_filter_chain(database): 32 filter_chain = [] 33 34 for section in settings.sections(): 35 if section == 'global' or section == mail_mover_section: 36 continue 37 38 match = section_re.match(section) 39 if not match: 40 raise SyntaxError('Malformed section title %r.' % section) 41 42 kwargs = dict( 43 (key, settings.get(section, key)) 44 if key not in value_is_a_list else 45 (key, settings.get_list(section, key)) 46 for key in settings.options(section) 47 ) 48 49 if match.group('parent_class'): 50 try: 51 parent_class = all_filters[match.group('parent_class')] 52 except KeyError: 53 raise NameError( 54 'Parent class %r not found in filter type definition %r.' % (match.group('parent_class'), section)) 55 56 new_type = type(match.group('name'), (parent_class,), kwargs) 57 all_filters[match.group('name')] = new_type 58 else: 59 try: 60 klass = all_filters[match.group('name')] 61 except KeyError: 62 raise NameError('Filter type %r not found.' % match.group('name')) 63 filter_chain.append(klass(database, **kwargs)) 64 65 return filter_chain 66 67 68def get_mail_move_rules(): 69 rule_pattern = re.compile(r"'(.+?)':((?P<quote>['\"])(.*?)(?P=quote)|\S+)") 70 if settings.has_option(mail_mover_section, 'folders'): 71 all_rules = collections.OrderedDict() 72 73 for folder in shlex.split(settings.get(mail_mover_section, 'folders')): 74 if settings.has_option(mail_mover_section, folder): 75 rules = collections.OrderedDict() 76 raw_rules = re.findall(rule_pattern, 77 settings.get(mail_mover_section, folder)) 78 for rule in raw_rules: 79 query = rule[0] 80 destination = rule[3] or rule[1] 81 rules[query] = destination 82 all_rules[folder] = rules 83 else: 84 raise NameError("No rules specified for maildir '{}'.".format(folder)) 85 86 return all_rules 87 else: 88 raise NameError("No folders defined to move mails from.") 89 90 91def get_mail_move_age(): 92 max_age = 0 93 if settings.has_option(mail_mover_section, 'max_age'): 94 max_age = settings.get(mail_mover_section, 'max_age') 95 return max_age 96 97 98def get_mail_move_rename(): 99 rename = False 100 if settings.has_option(mail_mover_section, 'rename'): 101 rename = settings.get(mail_mover_section, 'rename').lower() == 'true' 102 return rename 103