def inform_new_student(student):
    path_to_templates = config_get_section_attribute('DIRECTORIES', 'path_to_templates')
    student_email_templates = read_in_templates(path_to_templates + '/student_new_account')
    sender = '"DragonNet Admin" <*****@*****.**>'
    sf = NS(student)
    email = Email(config_get_section_attribute('EMAIL', 'domain'))
    email.define_sender('*****@*****.**', "DragonNet Admin")
    email.use_templates(student_email_templates)
    email.make_subject(sf("New Student in Homeroom {homeroom}, {lastfirst}"))
    homeroom_teacher = student.homeroom_teacher
    if homeroom_teacher:
          email.add_to(homeroom_teacher.email)
    # ssis does not want this feature
    #for guardian_email in student.guardian_emails:
    #      email.add_to(guardian_email)
    # for class_teacher in student.get_teachers_as_list():
    #       email.add_to(class_teacher + '@ssis-suzhou.net')
    # if student.grade in [11, 12]:
    #       email.add_cc('*****@*****.**')
    #       email.add_cc('*****@*****.**')
    # elif student.grade in [6, 7, 8, 9, 10]:
    #       email.add_cc('*****@*****.**')
    email.add_bcc('*****@*****.**')
    email.add_bcc('*****@*****.**')
    email.define_fields(sf)

    email.send()
Esempio n. 2
0
    def __init__(self):
        """
        Does the work of reading in basic information from file, creates native Python structures
        StudentNumber\tHomeroom\tLastFirst\tguardianemails
        """
        self.settings = define_command_line_arguments(
                               'verbose', 'log_level', 'dry_run', 'teachers', 'courses',
                               'students', 'email_list', 'families', 'parents',
                               'automagic_emails', 'profiles', 'input_okay', 'updaters',
                               'enroll_cohorts', 'enroll_courses', 'remove_enrollments', inspect_student=False)

        self.logger = logging.getLogger(self.__class__.__name__)
        self.path_to_powerschool = config_get_section_attribute('DIRECTORIES', 'path_to_powerschool_dump')
        self.path_to_output = config_get_section_attribute('DIRECTORIES', 'path_to_output')
        self.student_info_file = AutoSendFile('dist', 'studentinfo')
        self.student_info_controller = Controller(Student)
        self.course_info_controller = Controller(Course)
        self.teacher_info_controller = Controller(Teacher)
        self.schedule_info_controller = Controller(Schedule)
        self.allocation_info_controller = Controller(Allocation)
        self.user_data = ServerInfo().get_student_info()
        self.read_in()
        homerooms = None
        self._secondary_homerooms = None
        self._elementary_homerooms = None
        self.get_homerooms()
        self.get_secondary_homerooms()
    def __init__(self, school, unique):
        """
        Main task here is to set self.path
        """

        self.logger = logging.getLogger(self.__class__.__name__)

        path_to_powerschool = config_get_section_attribute('DIRECTORIES', 'path_to_powerschool_dump')
        if not path_to_powerschool:
            raise NotImplemented("Something wrong with the powerschool directory information")

        self.school = school
        self.unique = unique
        self.convert_entities = HTMLParser().unescape

        self.debug = config_get_section_attribute('DEBUGGING', 'print_autosend')

        # Dynamically look at the directory and use the latest version
        path = path_to_powerschool + '/' + version_format.format(minor_version='', **locals())
        path = path.split(os.path.sep)[-1]
        candidates = [g for g in [f.split(os.path.sep)[-1] for f in os.listdir(path_to_powerschool)] if path in g]
        candidates = sorted(candidates)
        if not candidates:
            self.debug and self.logger.warning("Autosend file not present for {} {}\ncontent method set to yield nothing".format(self.school, self.unique))
            self.content = lambda *args, **kwargs: []
            return
        final = candidates[-1]
        self.path = path_to_powerschool + '/' + final
        self.debug and self.logger.warning('Autosend: {}_{}\nParsing this file: {}'.format(school, unique, self.path))
 def __init__(self):
     sf = NS()
     sf.db_name = config_get_section_attribute('MOODLE', 'db_name')
     sf.db_username = config_get_section_attribute('MOODLE', 'db_username')
     sf.db_password = config_get_section_attribute('MOODLE', 'db_password')
     sf.db_host = config_get_section_attribute('MOODLE', 'db_host')
     self.db = postgresql.open(sf('pq://{db_username}:{db_password}@{db_host}/{db_name}'))
     self.sql = self.db.prepare
    def post_to_wordpress(self, url, blog, author, hour, format=True):
        """
        SIMPLISTIC WAY TO GET WHAT COULD BE AN EMAIL ONTO A WORDPRESS BLOG
        REQUIRES wp-cli https://github.com/wp-cli/wp-cli
        """
        if format:
            self.prepare_formatting()
        path_to_wordpress = config_get_section_attribute('SITES', 'path_to_docroot', required=True)
        path_to_wpcli = config_get_section_attribute('SITES', 'path_to_wpcli', required=True)
        if not url:
            wordpress_url = config_get_section_attribute('SITES', 'url', required=True)
        else:
            wordpress_url = url

        # Get the user information first
        command = "{} --path={} user get {} --format=json ".format(path_to_wpcli, path_to_wordpress, author)
        to_call = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
        result, err = to_call.communicate()
        import json
        user = json.loads(result.decode())

        # Now clean up the html, add links if not there and remove errant tags, also clean up for passing on
        try:
            from lxml.html.clean import Cleaner
            from lxml.html.clean import autolink_html
        except ImportError:
            click.secho('We need lxml!', fg='red')

        content = self.get_html()
        cleaner = Cleaner(remove_tags=['p', 'div'])  # Moodle's editor has loads of lonely p and div tags
        content = cleaner.clean_html(content)
        content = autolink_html(content)
        replace_apostrophes = "'\\''"
        content = content.replace("'", replace_apostrophes).replace('\r', ' ')   # escape apostrophes for bash

        date_as_string = '{}-{}-{} {}:{}:00'.format(self.date.year, self.date.month, self.date.day, hour.tm_hour, hour.tm_min)

        d = {
            'title': self.get_subject(),   # remove the 'Student Notices for' part
            'author': user['ID'],
            'content': content,
            'date': date_as_string,
            'blog': blog,
            'url': wordpress_url,
            'path_to_wpcli': path_to_wpcli,
            'path_to_docroot': path_to_wordpress
            }

        command = """{path_to_wpcli} post create --path={path_to_docroot} --post_type=post --post_title='{title}' --post_content='{content}' --post_author={author} --post_status=future --post_date='{date}' --url={url}/{blog}""".format(**d)
        subprocess.call(command, shell=True)
 def remove_user_from_all_groups(self, user):
     """
     Used in old_* accounts functions
     """
     debug = config_get_section_attribute('DEBUGGING', 'inspect_soft_deletion_groups')
     for group in user.groups:
         self.logger.warning("Removing old_student {} from group {} ".format(user, group))
         self.moodlemod.remove_user_from_group(user.idnumber, group.idnumber)
 def check_for_keep_username_startswith(self, user):
     with_what = config_get_section_attribute('MOODLE', 'keep_username_startswith')
     if not with_what:
         return False
     with_what = with_what.split(',')
     for this in with_what:
         if user.username.startswith(this):
             return True
     return False
 def process_courses(self):
     debug = config_get_section_attribute('DEBUGGING', 'print_courses')
     for course in self.district_courses.content():
         new = self.courses.make_without_conversion(
             course.idnumber, course.fullname, course.grade, course.database_id
             )
         debug and self.logger.warning(new)
     if debug:
         from IPython import embed
         embed()
Esempio n. 9
0
	def process(self):
		# Basically just calls every process_x method we have
		debug = config_get_section_attribute('DEBUGGING', 'print_process')
		order = ['students', 'teachers', 'parents', 'parent_links', 'cohorts', 'courses', 'schedules',  'mrbs_editors']
		for o in order:
			method_name = 'process_{}'.format(o)
			method = getattr(self, method_name)
			debug and self.logger.warning(method)
			method()
		self._processed = True
 def __init__(self):
     self.logger = logging.getLogger(self.__class__.__name__)
     self.logger.warn('Started at {}'.format( datetime.datetime.now() ) )
     self.arguments = define_command_line_arguments(*self.switches, **self.strings)
     self.config = config
     self.tree = InfoController()
     if 'DEFAULTS' in self.config.sections():
         for key in self.config['DEFAULTS']:
             setattr(self, key, self.config.getboolean('DEFAULTS', key))
     self.email_server = None
     # TODO: Figure out if this is really needed
     if self.config.has_section("EMAIL"):
         self.email_server = self.config['EMAIL'].get('domain')
     if not self.email_server:
         self.email_server = 'localhost'
     have_email_section = self.config.has_section('EMAIL')
     have_moodle_section = self.config.has_section('MOODLE')
     # moodle link
     self.server_information = ServerInfo()
     # required paths
     self.path_to_powerschool = config_get_section_attribute('DIRECTORIES', 'path_to_powerschool_dump')
     self.path_to_output = config_get_section_attribute('DIRECTORIES', 'path_to_output')
     self.path_to_errors = config_get_section_attribute('DIRECTORIES', 'path_to_errors')
def inform_parent_username_changed(parent, password):
    """
    parent is object
    """
    path_to_templates = config_get_section_attribute('DIRECTORIES', 'path_to_templates')
    parent_email_templates = read_in_templates(path_to_templates + '/parent_username_changed')
    email = Email(config_get_section_attribute('EMAIL', 'domain'))
    email.define_sender('*****@*****.**', "DragonNet Admin")
    email.use_templates(parent_email_templates)
    email.make_subject("Notification of updated SSIS DragonNet username")
    email.add_to(parent.email)
    for student in parent.children:
        if student.is_korean:
            email.add_language('kor')
        if student.is_chinese:
            email.add_language('chi')
    email.add_bcc('*****@*****.**')
    email.add_bcc('*****@*****.**')
    email.define_field('username', parent.email)
    email.define_field('salutation', 'Dear SSIS Parent')
    email.define_field('password', password)

    email.send()
def inform_new_parent(parent):
    """
    parent is object
    """
    path_to_templates = config_get_section_attribute('DIRECTORIES', 'path_to_templates')
    parent_email_templates = read_in_templates(path_to_templates + '/parent_new_account')
    email = Email(config_get_section_attribute('EMAIL', 'domain'))
    email.define_sender('*****@*****.**', "DragonNet Admin")
    email.use_templates(parent_email_templates)
    email.make_subject("Your SSIS DragonNet Parent Account")
    for parent_email in parent.emails:
        email.add_to(parent_email)
    for student in parent.children:
        if student.is_korean:
            email.add_language('kor')
        if student.is_chinese:
            email.add_language('chi')
    email.add_bcc('*****@*****.**')
    email.add_bcc('*****@*****.**')
    email.define_field('username', parent.email)
    email.define_field('salutation', 'Dear Parent')

    email.send()
    def __init__(self, verbose=False):
        #TODO: Get this info from standard settings and config
        self.verbose = verbose
        self.logger = logging.getLogger(self.__class__.__name__)
        self.default_logger = self.logger.debug
        self.sf = NS()
        self.email_accounts = config_get_section_attribute('EMAIL', 'check_accounts')
        self.moodle_accounts = config_get_section_attribute('MOODLE', 'sync')
        # TODO: Depreciate this stupid dry run thingie, make it a logging feature instead
        self.dry_run = config_get_section_attribute('DEFAULTS', 'dry_run')
        self.path_to_cli = config_get_section_attribute('MOODLE', 'path_to_cli')
        self.path_to_php = config_get_section_attribute('MOODLE', 'path_to_php')
        if not self.path_to_php:
            self.path_to_php = '/usr/bin/php'

        # Moodle requires any php files to be run from the admin/cli directory
        os.chdir(self.path_to_cli)

        # And now, spawn it
        cmd = "{} {}/phpclimoodle.php".format(self.path_to_php, self.path_to_cli)
        self.process = pexpect.spawn(cmd)
        self.process.delaybeforesend = 0  # speed things up a bit, eh?
        self.process.timeout = 3600
        self.process.expect_exact('?: ') # not sure why this works the first time
Esempio n. 14
0
def email_user(path_to_users, username=None, idnumber=None):
    """
    Check to see if user has their account set up or not.
    """
    if path_to_users == 'path_to_users':
        from psmdlsyncer.settings import config_get_section_attribute
        path_to_users = config_get_section_attribute('DIRECTORIES', 'path_to_users')
    import os
    yes = "User has an account in this system"
    no = "User does NOT have an account system"
    _list = os.listdir(path_to_users)
    if idnumber and idnumber in _list:
        click.echo(yes)
        return
    if username and username in _list:
        click.echo(yes)
        return
    click.echo(no)
Esempio n. 15
0
	def process_schedules(self):
		"""
		Schedule should just have the keys for student and teachers
		"""
		for school in ['elementary', 'secondary']:
			self.logger.warning('{} processing {} schedule'.format(self.__class__.__name__, school))
			# calls both secondary_schedule.content, elementary_schedule.content
			method = getattr(self, "{}_schedule".format(school))
			for schedule in method.content():
				self.default_logger('Processing {} schedule: {}'.format(school, schedule))
				course_key, period_info, section_number, teacher_key, student_key = schedule
				course = self.courses.get(course_key, self.convert_course)
				student = self.students.get_key(student_key)
				# Do some sanity checks
				if not student:
					self.default_logger("Student not found, sometimes happens for some odd reason {}".format(student_key))
					continue

				if not course:
					self.logger.debug("Course not found! {}".format(course_key))
					continue
				if course.exclude:
					self.default_logger("Course {} has been excluded!".format(course_key))
					# And so we should skip this schedule entirely!
					continue
				teacher = self.teachers.get_key(teacher_key)
				if not teacher:
					self.logger.warning("Teacher not found! {}".format(teacher_key))
					continue
				group = self.groups.make_group(student, course, teacher, section_number, period_info)
				if not group:
					self.logger.warning("Group not found! {}".format(section_number))
					continue


				self.associate(course, teacher, group, student)

				if student.login_method == 'manual':
					self.online_portfolios.make(student.idnumber)

				if str(config_get_section_attribute('DEBUGGING', 'inspect_teacher_schedule')) == teacher_key:
					self.logger.warning('{}\n{}\n{}\n'.format(teacher, group, student))
					from IPython import embed
					embed()
Esempio n. 16
0
def student_emails(path_to_output, user_id, group_id):
    """
    Output into a file stuff needed for PowerSchool to read in via AutoCom
    """
    from psmdlsyncer.settings import config, config_get_section_attribute
    from psmdlsyncer.sql import MoodleDBSession

    path_to_powerschool = config_get_section_attribute('DIRECTORIES', 'path_to_powerschool_dump')

    db = MoodleDBSession()

    with open(path_to_output, 'w') as _file:
        for student in db.users_enrolled_in_this_cohort('studentsALL'):
            if student.idnumber and student.username and student.email:
                if student.idnumber != '99999':
                    _file.write('{},{},{}\n'.format(student.idnumber, student.username, student.email))

    import os
    os.chown(path_to_output, int(user_id), int(group_id))
    def init(self):
        # Setup formatting templates for emails, can be overridden if different look required
        # The default below creates a simple list format
        # Need two {{ and }} because it goes through a parser later at another layer
        # Also, since it goes to an email, CSS is avoided
        self.start_html_tag    = '<html>'
        self.end_html_tag      = "</html>"
        self.header_pre_tag    = '<h3>'
        self.header_post_tag   = "</h3>"
        self.begin_section_tag = "<ul>"
        self.end_section_tag   = "</ul>"
        self.begin_list_tag    = '<li>'
        self.end_list_tag      = "</li>"
        self.colon             = ":"
        self.attachment_header = 'Attachments'
        self.email_editing     = False

        self.server = config_get_section_attribute('EMAIL', 'domain')
        if not self.server:
            print("Using localhost for mail server")
            self.server = 'localhost'
        
        self.name = self.__class__.__name__.replace("_", " ")
        # Class-specific settings, which are delegated to sub-classes
        self.define()

        # Initial values
        month = self.date.month
        day   = self.date.day
        year  = self.date.year

        if self.section_field:
            self.section_field_object = FieldObject(self.database_name, self.section_field)
            self.section_field_default_value = self.section_field_object.default_value()
        else:
            self.section_field_object = None
            self.section_field_default_value = None
        
        self.start_date_field = StartDateField(self.database_name, 'Start Date')
        self.end_date_field   = EndDateField(self.database_name, 'End Date')
        self.process()

        self.edit_word = "Edit"
Esempio n. 18
0
def membership(username):
    from psmdlsyncer.settings import config_get_section_attribute
    from functools import partial
    import os
    # Set up directory and path checks with partials
    path_to_postfix = config_get_section_attribute('DIRECTORIES', 'path_to_postfix', required=True)
    os.chdir(path_to_postfix)
    resolve_this = partial(os.path.join, os.getcwd())

    for this_one in os.listdir('.'):
        full_path = resolve_this(this_one)
        if os.path.isdir(full_path):
            os.chdir(full_path)
            for file_name in os.listdir('.'):
                group, _ = os.path.splitext(file_name)
                with open(os.path.join(os.getcwd(), file_name)) as _file:
                    for line in _file:
                        if username in line:
                            click.echo(group)
 def go(self, **kwargs):
     debug = config_get_section_attribute('DEBUGGING', 'print_dispatches')
     for item in self.subtract():
         if self.template and hasattr(item, 'status'):
             if item.status in ['new_teacher', 'new_student']:
                 self._repeat = True
             dispatch = self.template.get(item.status)
         else:
             dispatch = None
         if dispatch:
             debug and print(item)
             if self.teachersonly:
                 if item.right and hasattr(item.right, 'idnumber') and self.right.teachers.get_key(item.right.idnumber):
                     dispatch(item)
             elif self.studentsonly:
                 if item.right and hasattr(item.right, 'idnumber') and self.right.students.get_key(item.right.idnumber):
                     dispatch(item)
             else:
                 dispatch(item)
         else:
             #TODO: Handle unrecognized statuses here
             self.logger.warning("This item wasn't handled, because a handler ({}) wasn't defined!".format(item.status))
    def go(self):
        path = None
        if self.config.has_section("EMAIL"):
            path = config_get_section_attribute('DIRECTORIES', 'path_to_postfix')
        if not path:
            path = self.output_path + '/postfix'

        ns = self.make_ns()
        ns.PATH = path
        ns.EXT = '.txt'
        ns.INCLUDE = ' :include:'

        # The clear_folder routine erases all files in a certain folder
        # That has implications for postfix (when we're on the server), because
        # if you delete the .db files then postfix won't work. That is bad.
        # So, tell clear_folder to exclude them
        exclude_db_files = lambda x: x.endswith('.db')
        self.logger.debug("Clearing folders in postfix")
        clear_folder( ns.PATH, exclude=exclude_db_files)
        clear_folder(ns('{PATH}/grades'))
        clear_folder(ns('{PATH}/homerooms'))
        clear_folder(ns('{PATH}/classes'))
        clear_folder(ns('{PATH}/parentlink'))
        clear_folder(ns('{PATH}/teacherlink'))
        clear_folder(ns('{PATH}/special'))
        clear_folder(ns('{PATH}/departments'))
        clear_folder(ns('{PATH}/activities'))

        special_directory = []

        self.logger.debug("Setting up largest mailing lists first")

        for item in ['ALL', 'SEC', 'ELEM', 'KOREAN', 'CHINESE']:
            ns.this = item
            special_directory.append( ns('usebccparents{this}{COLON}{INCLUDE}{PATH}{SLASH}special{SLASH}usebccparents{this}{EXT}') )

        with open( ns('{PATH}/special{EXT}'), 'w') as f:
            f.write( "\n".join(special_directory) )

        usebccparentsALL = []
        usebccstudentsALL = []
        usebccparentsELEM = []
        usebccparentsSEC = []
        usebccstudentsSEC = []
        usebccparentsCHINESE = []
        usebccparentsCHINESEELEM = []
        usebccparentsCHINESESEC = []
        usebccparentsCHINESEGRADE = defaultdict(list)
        usebccparentsKOREAN = []
        usebccparentsKOREANELEM = []
        usebccparentsKOREANSEC = []
        usebccparentsKOREANGRADE = defaultdict(list)
        usebccparentsJAPANESE = []
        usebccparentsJAPANESEELEM = []
        usebccparentsJAPANESESEC = []
        usebccparentsJAPANESEGRADE = defaultdict(list)
        # SWA DISTRIBUTION LISTS
        usebccparentsSWA = []
        usebccstudentsSWA = []
        usebccparentsSWAGRADE = defaultdict(list)
        usebccstudentsSWAGRADE = defaultdict(list)
        # HR AND GRADE
        usebccparentsHOMEROOM = defaultdict(list)
        usebccparentsGRADE = defaultdict(list)
        usebccparentsHOMEROOM = defaultdict(list)
        usebccstudentsELEM = defaultdict(list)
        usebccstudentsGRADE = defaultdict(list)
        usebccstudentsHOMEROOM = defaultdict(list)
        parentlink = defaultdict(list)
        teacherlink = defaultdict(list)
        teachersGRADE = defaultdict(list)
        hrlink = defaultdict(list)
        classes = defaultdict(list)
        classesPARENTS = defaultdict(list)
        special = defaultdict(list)

        self.logger.debug('Clearing the table on moodle')
        self.server_information.create_temp_storage('student_email_info', 'list', 'email')
        self.server_information.empty_temp_storage('student_email_info')
        if self.arguments.update_moodle:
            write_db = self.server_information.add_temp_storage
        else:
            write_db = do_nothing
        self.logger.debug("Setting email lists")
        for student in self.tree.students:
            ns.homeroom = student.homeroom
            ns.grade = student.grade

            # TODO: Check for now grade or homeroom and warn
            if student.grade is "" or student.grade is None:
                self.logger.warn("This student does not have a grade:\n{}".format(student))
            if not student.homeroom:
                self.logger.warn("This student does not have a homeroom:\n{}".format(student))

            # USE ns.grade BECAUSE student.grade IS AN INTEGER
            # TODO: DO WE MAKE student.grade A STRING?
            # OR PUT THIS IN THE OBJECT SOMEWHOW?
            if ns.grade <= 0:
                ns.grade = {0: 'K', -1: 'R', -2: 'G', -3:'PK', -4:'N'}.get(ns.grade, None)

            usebccparentsALL.extend( student.guardian_emails )
            ns.grade and usebccparentsGRADE[ns.grade].extend(student.guardian_emails)
            ns.homeroom and usebccparentsHOMEROOM[ns.homeroom].extend(student.guardian_emails)

            if student.is_elementary:
                usebccparentsELEM.extend(student.guardian_emails)

            if student.is_secondary:
                usebccparentsSEC.extend(student.guardian_emails)
                usebccstudentsSEC.append(student.email)
                if ns.grade:
                    usebccstudentsGRADE[ns.grade].append(student.email)
                    teachersGRADE[ns.grade].extend(student.teacher_emails)
                if student.homeroom:
                    usebccstudentsHOMEROOM[ns.homeroom].append(student.email)
                parentlink[student.username].extend( student.guardian_emails )
                teacherlink[student.username].extend(student.teacher_emails)
                hrlink[student.username].append(student.homeroom_teacher_email)
                for group in student.group_names:
                    classes[group].append(student.email)
                    classesPARENTS[group].extend(student.guardian_emails)

            if student.is_chinese:
                usebccparentsCHINESE.extend( student.guardian_emails )
                student.is_secondary and usebccparentsCHINESESEC.extend( student.guardian_emails )
                student.is_elementary and usebccparentsCHINESEELEM.extend( student.guardian_emails )
                usebccparentsCHINESEGRADE[ns.grade].extend( student.guardian_emails )
            if student.is_korean:
                usebccparentsKOREAN.extend( student.guardian_emails )
                student.is_secondary and usebccparentsKOREANSEC.extend( student.guardian_emails )
                student.is_elementary and usebccparentsKOREANELEM.extend( student.guardian_emails )
                usebccparentsKOREANGRADE[ns.grade].extend( student.guardian_emails )
            if student.is_japanese:
                usebccparentsJAPANESE.extend( student.guardian_emails )
                student.is_secondary and usebccparentsJAPANESESEC.extend( student.guardian_emails )
                student.is_elementary and usebccparentsJAPANESEELEM.extend( student.guardian_emails )
                usebccparentsJAPANESEGRADE[ns.grade].extend( student.guardian_emails )
            if student.is_SWA:
                usebccparentsSWA.extend( student.guardian_emails )
                usebccstudentsSWA.append( student.email )
                usebccparentsSWAGRADE[ns.grade].extend( student.guardian_emails )
                usebccstudentsSWAGRADE[ns.grade].append( student.email )

        for ns.email in set(usebccparentsALL):
            write_db('student_email_info', list='usebccparentsALL', email=ns.email)

        for ns.email in set(usebccparentsSEC):
            write_db('student_email_info', list='usebccparentsSEC', email=ns.email)

        for ns.email in set(usebccparentsELEM):
            write_db('student_email_info', list='usebccparentsELEM', email=ns.email)

        for ns.email in set(usebccparentsSWA):
            write_db('student_email_info', list='usebccparentsSWA', email=ns.email)

        for ns.email in set(usebccstudentsSWA):
            write_db('student_email_info', list='usebccstudentsSWA', email=ns.email)

        for ns.grade in usebccparentsGRADE:
            for ns.email in set(usebccparentsGRADE[ns.grade]):
                write_db('student_email_info', list=ns('usebccparents{grade}'), email=ns('{email}'))

        for ns.grade in usebccstudentsGRADE:
            for ns.email in set(usebccstudentsGRADE[ns.grade]):
                write_db('student_email_info', list=ns('usebccstudents{grade}'), email=ns('{email}'))

        for ns.grade in teachersGRADE:
            for ns.email in set(teachersGRADE[ns.grade]):
                write_db('student_email_info', list=ns('teachers{grade}'), email=ns('{email}'))

        for ns.homeroom in usebccparentsHOMEROOM:
            for ns.email in set(usebccparentsHOMEROOM[ns.homeroom]):
                write_db('student_email_info', list=ns('usebccparents{homeroom}'), email=ns('{email}'))

        for ns.homeroom in usebccstudentsHOMEROOM:
            for ns.email in set(usebccstudentsHOMEROOM[ns.homeroom]):
                write_db('student_email_info', list=ns('usebccstudents{homeroom}'), email=ns('{email}'))

        for ns.student in teacherlink:
            for ns.email in set(teacherlink[ns.student]):
                write_db('student_email_info', list=ns('{student}TEACHERS'), email=ns('{email}'))

        for ns.student in parentlink:
            for ns.email in set(parentlink[ns.student]):
                write_db('student_email_info', list=ns('{student}PARENTS'), email=ns('{email}'))

        for ns.student in hrlink:
            for ns.email in set(hrlink[ns.student]):
                write_db('student_email_info', list=ns('{student}HR'), email=ns('{email}'))            

        for ns.klass in classes:
            for ns.email in classes[ns.klass]:
                write_db('student_email_info', list=ns('{klass}'), email=ns('{email}'))

        for ns.klass in classesPARENTS:
            for ns.email in classes[ns.klass]:
                write_db('student_email_info', list=ns('{klass}PARENTS'), email=ns('{email}'))

        # GRADES
        directory_write = []
        for ns.grade in usebccparentsGRADE:
            directory_write.append( ns('usebccparents{grade}{COLON}{INCLUDE}{PATH}{SLASH}grades{SLASH}usebccparents{grade}{EXT}') )
            with open( ns('{PATH}{SLASH}grades{SLASH}usebccparents{grade}{EXT}'), 'w') as f:
                f.write( '\n'.join(set(usebccparentsGRADE[ns.grade])) )
        for ns.grade in usebccstudentsGRADE:
            directory_write.append( ns('usebccstudents{grade}{COLON}{INCLUDE}{PATH}{SLASH}grades{SLASH}usebccstudents{grade}{EXT}') )
            with open( ns('{PATH}{SLASH}grades{SLASH}usebccstudents{grade}{EXT}'), 'w') as f:
                f.write( '\n'.join(set(usebccstudentsGRADE[ns.grade])) )
        for ns.grade in teachersGRADE:
            directory_write.append( ns('teachers{grade}{COLON}{INCLUDE}{PATH}{SLASH}grades{SLASH}teachers{grade}{EXT}') )
            with open( ns('{PATH}{SLASH}grades{SLASH}teachers{grade}{EXT}'), 'w') as f:
                f.write( '\n'.join(set(teachersGRADE[ns.grade])) )
        with open( ns('{PATH}{SLASH}grades{EXT}'), 'w') as f:
            f.write( '\n'.join(directory_write) )

            #HS

        # HOMEROOMS
        directory_write = []
        for ns.homeroom in usebccparentsHOMEROOM:
            directory_write.append( ns('usebccparents{homeroom}{COLON}{INCLUDE}{PATH}{SLASH}homerooms{SLASH}usebccparents{homeroom}{EXT}') )
            with open( ns('{PATH}{SLASH}homerooms{SLASH}usebccparents{homeroom}{EXT}'), 'w') as f:
                f.write( '\n'.join(set(usebccparentsHOMEROOM[ns.homeroom])) )
        for ns.homeroom in usebccstudentsHOMEROOM:
            directory_write.append( ns('usebccstudents{homeroom}{COLON}{INCLUDE}{PATH}{SLASH}homerooms{SLASH}usebccstudents{homeroom}{EXT}') )
            with open( ns('{PATH}{SLASH}homerooms{SLASH}usebccstudents{homeroom}{EXT}'), 'w') as f:
                f.write( '\n'.join(set(usebccstudentsHOMEROOM[ns.homeroom])) )
        with open( ns('{PATH}{SLASH}homerooms{EXT}'), 'w') as f:
            f.write( '\n'.join(directory_write) )

        # TEACHERLINK
        directory_write = []
        for ns.student in teacherlink:
            directory_write.append( ns('{student}TEACHERS{COLON}{INCLUDE}{PATH}{SLASH}teacherlink{SLASH}{student}TEACHERS{EXT}') )
            with open( ns('{PATH}{SLASH}teacherlink{SLASH}{student}TEACHERS{EXT}'), 'w') as f:
                f.write( '\n'.join(set(teacherlink[ns.student])) )
        with open( ns('{PATH}{SLASH}teacherlink{EXT}'), 'w') as f:
            f.write( '\n'.join(directory_write) )

        # PARENTLINK
        directory_write = []
        for ns.student in parentlink:
            directory_write.append( ns('{student}PARENTS{COLON}{INCLUDE}{PATH}{SLASH}parentlink{SLASH}{student}PARENTS{EXT}') )
            with open( ns('{PATH}{SLASH}parentlink{SLASH}{student}PARENTS{EXT}'), 'w') as f:
                f.write( '\n'.join(set(parentlink[ns.student])) )
        with open( ns('{PATH}{SLASH}parentlink{EXT}'), 'w') as f:
            f.write( '\n'.join(directory_write) )

        # HRLINK
        directory_write = []
        for ns.student in hrlink:
            if hrlink[ns.student]:  # not all kids have a homeroom teacher....
                directory_write.append( ns('{student}HR{COLON}{INCLUDE}{PATH}{SLASH}homeroomlink{SLASH}{student}HR{EXT}') )
                with open( ns('{PATH}{SLASH}homeroomlink{SLASH}{student}HR{EXT}'), 'w') as f:
                    try:
                        f.write( '\n'.join(set(hrlink[ns.student])) )
                    except TypeError:
                        pass
        with open( ns('{PATH}{SLASH}homeroomlink{EXT}'), 'w') as f:
            f.write( '\n'.join(directory_write) )
        
        with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsALL{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccparentsALL) )

        with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsSEC{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccparentsSEC) )

        with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsELEM{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccparentsELEM) )

        with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsCHINESE{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccparentsCHINESE) )

        with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsCHINESESEC{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccparentsCHINESESEC) )

        with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsCHINESEELEM{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccparentsCHINESEELEM) )

        for ns.grade in usebccparentsCHINESEGRADE:
            with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsCHINESE{grade}{EXT}'), 'w') as f:
                f.write( '\n'.join(set(usebccparentsCHINESEGRADE[ns.grade])) )

        with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsKOREAN{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccparentsKOREAN) )

        with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsKOREANELEM{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccparentsKOREANSEC) )

        with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsKOREANSEC{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccparentsKOREANSEC) )

        for ns.grade in usebccparentsKOREANGRADE:
            with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsKOREAN{grade}{EXT}'), 'w') as f:
                f.write( '\n'.join(set(usebccparentsKOREANGRADE[ns.grade])) )

        with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsJAPANESE{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccparentsJAPANESE) )

        with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsJAPANESESEC{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccparentsJAPANESESEC) )

        for ns.grade in usebccparentsJAPANESEGRADE:
            with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsJAPANESE{grade}{EXT}'), 'w') as f:
                f.write( '\n'.join(set(usebccparentsJAPANESEGRADE[ns.grade])) )

        with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsSWA{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccparentsSWA) )

        with open( ns('{PATH}{SLASH}special{SLASH}usebccstudentsSWA{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccstudentsSWA) )
                
        with open( ns('{PATH}{SLASH}special{EXT}'), 'w') as f:
            for ns.this in ['usebccparentsALL', 'usebccparentsSEC', 'usebccparentsELEM',
                            'usebccparentsKOREAN', 'usebccparentsKOREANSEC', 'usebccparentsKOREANELEM',
                            'usebccparentsCHINESE', 'usebccparentsCHINESESEC', 'usebccparentsCHINESEELEM',
                            'usebccparentsJAPANESE', 'usebccparentsJAPANESESEC', 'usebccparentsJAPANESEELEM', 
                            'usebccparentsSWA', 'usebccstudentsSWA']:
                f.write( ns('{this}{COLON}{INCLUDE}{PATH}{SLASH}special{SLASH}{this}{EXT}{NEWLINE}') )
            for ns.grade in usebccparentsKOREANGRADE:
                f.write( ns('usebccparentsKOREAN{grade}{COLON}{INCLUDE}{PATH}{SLASH}special{SLASH}usebccparentsKOREAN{grade}{EXT}{NEWLINE}') )
            for ns.grade in usebccparentsCHINESEGRADE:
                f.write( ns('usebccparentsCHINESE{grade}{COLON}{INCLUDE}{PATH}{SLASH}special{SLASH}usebccparentsCHINESE{grade}{EXT}{NEWLINE}') )
            for ns.grade in usebccparentsJAPANESEGRADE:
                f.write( ns('usebccparentsJAPANESE{grade}{COLON}{INCLUDE}{PATH}{SLASH}special{SLASH}usebccparentsJAPANESE{grade}{EXT}{NEWLINE}') )

        # CLASSES
        directory_write = []
        for ns.klass in classes:
            directory_write.append( ns('{klass}{COLON}{INCLUDE}{PATH}{SLASH}classes{SLASH}{klass}{EXT}') )
        for ns.klass in classesPARENTS:
            directory_write.append( ns('{klass}PARENTS{COLON}{INCLUDE}{PATH}{SLASH}classes{SLASH}{klass}PARENTS{EXT}') )
        with open( ns('{PATH}{SLASH}classes{EXT}'), 'w') as f:
            f.write( '\n'.join(directory_write) )

        for ns.klass in classes:
            with open( ns('{PATH}{SLASH}classes{SLASH}{klass}{EXT}'), 'w') as f:
                f.write( '\n'.join(set(classes[ns.klass])) )

        for ns.klass in classesPARENTS:
            with open( ns('{PATH}{SLASH}classes{SLASH}{klass}PARENTS{EXT}'), 'w') as f:
                f.write( '\n'.join(set(classesPARENTS[ns.klass])) )

        self.logger.debug("Set up department batch emails")
        ##  SETUP DEPARTMENTS, including by homeroom teachers
        depart_dict = {}
        homeroom_teachers_dict = {}
        for teacher in self.tree.teachers:
            departments = teacher.get_departments()
            for department in departments:
                d_email_name = department_email_names.get(department)
                if not d_email_name:
                    continue
                if not d_email_name in list(depart_dict.keys()):
                    heads = department_heads.get(department, [])  # returns a list
                    depart_dict[d_email_name] = []
                    for head in heads:
                        self.logger.debug("Adding {} (the head) into department {}".format(head, d_email_name))
                        depart_dict[d_email_name].append(head + "@ssis-suzhou.net")
                if teacher and not teacher.email in depart_dict[d_email_name]:
                    self.logger.debug("Adding {} into department {}".format(teacher, d_email_name))
                    depart_dict[d_email_name].append(teacher.email)

            if teacher.homeroom:
                ns.homeroom = teacher.homeroom
                if not teacher.homeroom in homeroom_teachers_dict.keys():
                    homeroom_teachers_dict[teacher.homeroom] = True
                    setup_postfix = ns('{PATH}/departments{EXT}')
                    with open(setup_postfix, 'a') as f:
                        f.write(ns("homeroomteachers{homeroom}: :include:{PATH}/departments/homeroomteachers{homeroom}{EXT}\n"))
                setup_postfix = ns('{PATH}/departments/homeroomteachers{homeroom}{EXT}')
                with open(setup_postfix, 'a') as f:
                    f.write(teacher.email + '\n')

        for ns.department in list(depart_dict.keys()):
            # department is now actually the email name we want to use 
            setup_postfix = ns('{PATH}/departments{EXT}')
            with open(setup_postfix, 'a') as f:
                f.write( ns("{department}: :include:{PATH}/departments/{department}{EXT}\n") )

            setup_postfix = ns('{PATH}/departments/{department}{EXT}')
            with open(setup_postfix, 'w') as f:
                f.write( "\n".join(depart_dict[ns.department]) )

        # SETUP SECONDARY ACTIVITIES
        results = self.server_information.get_all_users_activity_enrollments()
        ns = NS()
        ns.domain = 'student.ssis-suzhou.net'
        activities_postfix = defaultdict(list)
        activities_postfix_parents = defaultdict(list)
        for result in results:
            activity_name, student_key = result
            student = self.tree.student_from_ID(student_key)
            if not student:
                # in case of outlyer
                continue
            if not student:
                self.logger.warning('This student is listed as having enrolled into an activity, ' + \
                                    'but no longer seems to be available at school. Ignored. {}'.format(student_key))
                continue
            activities_postfix[activity_name].append(student.email)
            activities_postfix_parents[activity_name].append(student.parent_link_email)

        # DO THE ACTIVITY EMAILS
        ns.path = config_get_section_attribute('DIRECTORIES', 'path_to_postfix')
        ns.base = 'activities'
        ns.SUFFIX = "ACT"
        ns.EXT = '.txt'
        ns.INCLUDE = ':include:'
        ns.activities_path = ns('{path}{SLASH}activities')
        with open(ns('{path}{SLASH}{base}{EXT}'), 'w'):
            pass

        for activity_name in activities_postfix:
            ns.handle = name_to_email(activity_name)
            ns.full_email = ns('{handle}{SUFFIX}')
            with open(ns('{path}{SLASH}{base}{EXT}'), 'a') as f:
                f.write(ns('{full_email}{COLON}{SPACE}{INCLUDE}' + \
                           '{activities_path}{SLASH}{full_email}{EXT}{NEWLINE}'))
            with open(ns('{activities_path}{SLASH}{full_email}{EXT}'), 'a') as f:
                f.write("\n".join(activities_postfix[activity_name]))

        ns.SUFFIX = "ACTPARENTS"
        for activity_name in activities_postfix_parents:
            ns.handle = name_to_email(activity_name)
            ns.full_email = ns('{handle}{SUFFIX}')
            with open(ns('{path}{SLASH}{base}{EXT}'), 'a') as f:
                f.write(ns('{full_email}{COLON}{SPACE}{INCLUDE}' + \
                           '{activities_path}{SLASH}{full_email}{EXT}{NEWLINE}'))
            with open(ns('{activities_path}{SLASH}{full_email}{EXT}'), 'a') as f:
                f.write("\n".join(activities_postfix_parents[activity_name]))
        
        # run newaliases command on exit if we're on the server
        newaliases_path = False
        if self.config.has_section('EMAIL'):
            newaliases_path = self.config['EMAIL'].get('newaliases_path')
        if newaliases_path:
            self.logger.info("Running newaliases")
            p = subprocess.Popen(newaliases_path, shell=True)
            self.logger.info(p.communicate())
        else:
            self.logger.warn("newaliases not run!")
from psmdlsyncer.settings import config_get_section_attribute
import datetime
import re

output = config_get_section_attribute('DIRECTORIES', 'path_to_output')
def out(line):
    with open(output + '/mail_stats.txt', 'a') as f:
        f.write(str(line) + '\n')

today = datetime.datetime.today().strftime('%b %d')
out("-----------")
out(today)
students = {}
pop3 = {}
imap = {}
count = 0
with open('/var/log/dovecot.log') as f:
        for line in f:
                if re.match(r'^'+today, line):
                        userinfo = re.sub(r'^(.*?)Login: user=<', '', line)
                        userinfo = re.sub(r'>.*', '', userinfo)
                        userinfo = userinfo.strip('\n').strip()
                        if not ' ' in userinfo:
                                if not userinfo in students:
                                        students[userinfo] = 0
                                students[userinfo] += 1

                                pop = re.match(r'.* pop3.*', line)
                                if pop:
                                        if not userinfo in list(pop3.keys()):
                                                pop3[userinfo] = 0
    def __init__(self):
        super().__init__()
        self.raw = self.sql("select distinct usr.firstname, usr.lastname, dr.timecreated, dc.content, dc.fieldid, dc.recordid from ssismdl_data_content dc " +
                            "join ssismdl_data_records dr on dc.recordid = dr.id " +
                            "join ssismdl_user usr on dr.userid = usr.id " +
                       "join ssismdl_data_fields df on dc.fieldid = df.id " + "join ssismdl_data d on df.dataid = 4 order by dc.recordid")()
        record_ids = []
        path_to_probe = config_get_section_attribute("DIRECTORIES", 'path_to_output')
        path_to_probe += '/probe/'
        
        for line in self.raw:
            r_id = line[k_record_id]
            if not r_id in record_ids:
                record_ids.append( r_id )
        # teachers holds the data organized by teachers
        teachers = defaultdict(list)
        # powerschool variable holds the data that will actually be written to file
        powerschool = ['Student_Number\tTest_Date\tGrade_Level\tReading_Age_1\tScore_2\tCategory_3\tIndications_3\tDifferential_1']
        # reads in student info from powerschool autosend
        student_info = Tree()        

        # loop through the records in the database module, match them up with the student info
        # and export the data accordingly
        for record_id in record_ids:
            this_entry = [ i for i in self.raw if i[k_record_id] == record_id ]
            if this_entry:
                entry = NS()
                entry.teacher = this_entry[0][0] + " " + this_entry[0][1]
                entry.date = timestamp_to_python_date(this_entry[0][2])
                entry.date_entered = entry.date.strftime('%m/%d/%Y')
                entry.test_date = {2012:make_date(2012, 10, 15), 2013:make_date(2013, 5, 15)}.get(entry.date.year)
                entry.test_date_output = entry.test_date.strftime('%m/%d/%Y')
                for row in this_entry:
                    field_id = row[k_field_id]
                    if field_id == k_student_name:
                        entry.student = row[k_content]
                        entry.powerschoolid = entry.student
                        match = re.search( '\((.*) (.*)\)', entry.student)
                        if match:
                            entry.homeroom, entry.powerschoolid = match.groups()
                            entry.grade = re.sub('[A-Z]', '', entry.homeroom)
                        else:
                            entry.homeroom = ''
                            entry.grade = -1
                    elif field_id == k_percentage:
                        entry.percent = row[k_content]
                    elif field_id == k_analysis:
                        entry.analysis = ', '.join(row[k_content].split('##')) if row[k_content] else ""
                    elif field_id == k_type:
                        entry.type = row[k_content]
                    elif field_id == k_set:
                        entry.set = row[k_content]
                        if not entry.set:
                            print(this_entry)
                        entry.reading_age = reading_age_from_set.get(entry.set)

                # gets the student class that has autosend data
                student = student_info.get_student(str(entry.powerschoolid))
                if not student:
                    # student no longer at ssis
                    continue
                if not entry.reading_age:
                    # no longer in the system (left) just skip it
                    # what about that dude's data!?
                    print("Something wrong with the data of this student")
                    continue
                date_to_age = lambda x: float(x.days) / 365.25
                entry.age = date_to_age(entry.test_date - student.birthday)
                entry.differential = round(entry.reading_age - entry.age, 2)
                teachers[entry.teacher].append( entry )
                powerschool.append( entry('{powerschoolid}{TAB}{test_date_output}{TAB}{grade}{TAB}{reading_age}{TAB}{percent}{TAB}{type}{TAB}{analysis}{TAB}{differential}') )
        with open(path_to_probe + 'powerschool.txt', 'w') as f:
            f.write( "\n".join(powerschool) )
        for teacher in teachers:
            with open(path_to_probe + '{}.txt'.format(teacher), 'w') as f:
                entries = teachers[teacher]
                entries.sort(key=lambda x: x.student)
                for entry in entries:
                    f.write(entry.student+ '\n')
                    f.write("\tSet:      {}\n".format(entry.set))
                    f.write("\tPercent:  {}\n".format(entry.percent))
                    f.write("\tAnalysis: {}\n".format(entry.analysis))
                    f.write("\tType:     {}\n".format(entry.type))
                    f.write('\n')
 def __init__(self, school, unique):
     self.school = school
     self.unique = unique
     self.path_to_passwd = config_get_section_attribute('EMAIL', 'path_to_passwd')
from psmdlsyncer.settings import config_get_section_attribute
from psmdlsyncer.sql import MoodleDBConnection
import postgresql
import datetime

convert = datetime.datetime.fromtimestamp

output = config_get_section_attribute("DIRECTORIES", "path_to_output")


def out(line):
    with open(output + "/account_stats.txt", "a") as f:
        f.write(str(line) + "\n")


out(datetime.datetime.today())

has = 0
cannot = 0
last_week = 0
last_month = 0
oneweekago = datetime.datetime.today() - datetime.timedelta(days=7)
onemonthago = datetime.datetime.today() - datetime.timedelta(days=30)
dnet = MoodleDBConnection()
raw = dnet.call_sql("select lastaccess,lastlogin,idnumber from ssismdl_user where idnumber like '%P' and deleted=0")
total = len(raw)

for line in raw:
    lastaccess, lastlogin, idnumber = line
    lastaccess_date = convert(lastaccess)
    lastlogin_date = convert(lastlogin)
 def __init__(self):
     super().__init__()
     self.default_logger = self.logger.debug
     self.new_email_cmd = config_get_section_attribute('DIRECTORIES', 'path_to_newstudent_script')
Esempio n. 26
0
from psmdlsyncer.settings import config, config_get_section_attribute
print('done')

import csv

path_to_students = config_get_section_attribute('DIRECTORIES', 'path_to_powerschool_dump')
path_to_students += '/ssis_dist_studentinfo_v4.0'

with open(path_to_students) as _file:
    readin = csv.reader(_file, delimiter='\t')
    for line in readin:
        print(line)
Esempio n. 27
0
    def process_schedules(self):
        super().process_schedules()

        path = None
        if config.has_section("EMAIL"):
            path = config_get_section_attribute('DIRECTORIES', 'path_to_postfix')
        if not path:
            path = self.output_path + '/postfix'

        ns = NS2()
        ns.PATH = path
        ns.EXT = '.txt'
        ns.INCLUDE = ' :include:'

        # The clear_folder routine erases all files in a certain folder
        # That has implications for postfix (when we're on the server), because
        # if you delete the .db files then postfix won't work. That is bad.
        # So, tell clear_folder to exclude them
        exclude_db_files = lambda x: x.endswith('.db')
        self.logger.debug("Clearing folders in postfix")
        clear_folder( ns.PATH, exclude=exclude_db_files)
        clear_folder(ns('{PATH}/grades'))
        clear_folder(ns('{PATH}/homerooms'))
        clear_folder(ns('{PATH}/classes'))
        clear_folder(ns('{PATH}/parentlink'))
        clear_folder(ns('{PATH}/teacherlink'))
        clear_folder(ns('{PATH}/special'))
        clear_folder(ns('{PATH}/departments'))
        clear_folder(ns('{PATH}/activities'))

        special_directory = []

        self.logger.debug("Setting up largest mailing lists first")

        for item in ['ALL', 'SEC', 'ELEM', 'KOREAN', 'CHINESE']:
            ns.this = item
            special_directory.append( ns('usebccparents{this}{COLON}{INCLUDE}{PATH}{SLASH}special{SLASH}usebccparents{this}{EXT}') )

        with open( ns('{PATH}/special{EXT}'), 'w') as f:
            f.write( "\n".join(special_directory) )

        usebccparentsALL = []
        usebccstudentsALL = []
        usebccparentsELEM = []
        usebccparentsSEC = []
        usebccstudentsSEC = []
        koreanstudentsSEC = []
        chinesestudentsSEC = []
        usebccparentsCHINESE = []
        usebccparentsCHINESEELEM = []
        usebccparentsCHINESESEC = []
        usebccparentsCHINESEGRADE = defaultdict(list)
        usebccparentsKOREAN = []
        usebccparentsKOREANELEM = []
        usebccparentsKOREANSEC = []
        usebccparentsKOREANGRADE = defaultdict(list)
        usebccparentsJAPANESE = []
        usebccparentsJAPANESEELEM = []
        usebccparentsJAPANESESEC = []
        usebccparentsJAPANESEGRADE = defaultdict(list)
        # SWA DISTRIBUTION LISTS
        usebccparentsSWA = []
        usebccstudentsSWA = []
        usebccparentsNOTSWA = []
        usebccparentsSWAGRADE = defaultdict(list)
        usebccstudentsSWAGRADE = defaultdict(list)
        usebccparentsGERMAN = []
        usebccparentsNOTGERMAN = []
        # HR AND GRADE
        usebccparentsHOMEROOM = defaultdict(list)
        usebccparentsGRADE = defaultdict(list)
        usebccparentsHOMEROOM = defaultdict(list)
        usebccstudentsELEM = defaultdict(list)
        usebccstudentsGRADE = defaultdict(list)
        usebccstudentsHOMEROOM = defaultdict(list)
        parentlink = defaultdict(list)
        teacherlink = defaultdict(list)
        teachersGRADE = defaultdict(list)
        hrlink = defaultdict(list)
        classes = defaultdict(list)
        classesPARENTS = defaultdict(list)
        special = defaultdict(list)

        for student in self.students.get_objects():
            ns.homeroom = student.homeroom
            ns.grade = student.grade

            # TODO: Check for now grade or homeroom and warn
            if student.grade is "" or student.grade is None:
                self.logger.warn("This student does not have a grade:\n{}".format(student))
            if not student.homeroom:
                self.logger.warn("This student does not have a homeroom:\n{}".format(student))

            # USE ns.grade BECAUSE student.grade IS AN INTEGER
            # TODO: DO WE MAKE student.grade A STRING?
            # OR PUT THIS IN THE OBJECT SOMEWHOW?
            if ns.grade <= 0:
                ns.grade = {0: 'K', -1: 'R', -2: 'G', -3:'PK', -4:'N'}.get(ns.grade, None)

            usebccparentsALL.extend( student.guardian_emails )
            ns.grade and usebccparentsGRADE[ns.grade].extend(student.guardian_emails)
            ns.homeroom and usebccparentsHOMEROOM[ns.homeroom].extend(student.guardian_emails)

            if student.is_elementary:
                usebccparentsELEM.extend(student.guardian_emails)
                parentlink[student.username].extend( student.guardian_emails )
                teacherlink[student.username].extend(student.teacher_emails)
                hrlink[student.username].append(student.homeroom_teacher_email)

            if student.is_secondary:
                usebccparentsSEC.extend(student.guardian_emails)
                usebccstudentsSEC.append(student.email)
                if ns.grade:
                    usebccstudentsGRADE[ns.grade].append(student.email)
                    teachersGRADE[ns.grade].extend(student.teacher_emails)
                if student.homeroom:
                    usebccstudentsHOMEROOM[ns.homeroom].append(student.email)
                parentlink[student.username].extend( student.guardian_emails )
                teacherlink[student.username].extend(student.teacher_emails)
                hrlink[student.username].append(student.homeroom_teacher_email)
                for group in student.groups:
                    classes[group.idnumber].append(student.email)
                    classesPARENTS[group.idnumber].extend(student.guardian_emails)

                if student.is_korean:
                    koreanstudentsSEC.append( student.email )
                if student.is_chinese:
                    chinesestudentsSEC.append( student.email )

            if student.is_chinese and not excluded_from_chinese_list(student):
                usebccparentsCHINESE.extend( student.guardian_emails )
                student.is_secondary and usebccparentsCHINESESEC.extend( student.guardian_emails )
                student.is_elementary and usebccparentsCHINESEELEM.extend( student.guardian_emails )
                usebccparentsCHINESEGRADE[ns.grade].extend( student.guardian_emails )
            if student.is_korean:
                usebccparentsKOREAN.extend( student.guardian_emails )
                student.is_secondary and usebccparentsKOREANSEC.extend( student.guardian_emails )
                student.is_elementary and usebccparentsKOREANELEM.extend( student.guardian_emails )
                usebccparentsKOREANGRADE[ns.grade].extend( student.guardian_emails )
            if student.is_japanese:
                usebccparentsJAPANESE.extend( student.guardian_emails )
                student.is_secondary and usebccparentsJAPANESESEC.extend( student.guardian_emails )
                student.is_elementary and usebccparentsJAPANESEELEM.extend( student.guardian_emails )
                usebccparentsJAPANESEGRADE[ns.grade].extend( student.guardian_emails )
            if student.is_german:
                usebccparentsGERMAN.extend( student.guardian_emails )
            else:
                usebccparentsNOTGERMAN.extend( student.guardian_emails )
            if student.is_SWA:
                usebccparentsSWA.extend( student.guardian_emails )
                usebccstudentsSWA.append( student.email )
                usebccparentsSWAGRADE[ns.grade].extend( student.guardian_emails )
                usebccstudentsSWAGRADE[ns.grade].append( student.email )
            else:
                usebccparentsNOTSWA.extend( student.guardian_emails )

        # GRADES
        directory_write = []
        for ns.grade in usebccparentsGRADE:
            directory_write.append( ns('usebccparents{grade}{COLON}{INCLUDE}{PATH}{SLASH}grades{SLASH}usebccparents{grade}{EXT}') )
            with open( ns('{PATH}{SLASH}grades{SLASH}usebccparents{grade}{EXT}'), 'w') as f:
                f.write( '\n'.join(set(usebccparentsGRADE[ns.grade])) )
        for ns.grade in usebccstudentsGRADE:
            directory_write.append( ns('usebccstudents{grade}{COLON}{INCLUDE}{PATH}{SLASH}grades{SLASH}usebccstudents{grade}{EXT}') )
            with open( ns('{PATH}{SLASH}grades{SLASH}usebccstudents{grade}{EXT}'), 'w') as f:
                f.write( '\n'.join(set(usebccstudentsGRADE[ns.grade])) )
        for ns.grade in teachersGRADE:
            directory_write.append( ns('teachers{grade}{COLON}{INCLUDE}{PATH}{SLASH}grades{SLASH}teachers{grade}{EXT}') )
            with open( ns('{PATH}{SLASH}grades{SLASH}teachers{grade}{EXT}'), 'w') as f:
                f.write( '\n'.join(set(teachersGRADE[ns.grade])) )
        with open( ns('{PATH}{SLASH}grades{EXT}'), 'w') as f:
            f.write( '\n'.join(directory_write) )

            #HS

        # HOMEROOMS
        directory_write = []
        for ns.homeroom in usebccparentsHOMEROOM:
            directory_write.append( ns('usebccparents{homeroom}{COLON}{INCLUDE}{PATH}{SLASH}homerooms{SLASH}usebccparents{homeroom}{EXT}') )
            with open( ns('{PATH}{SLASH}homerooms{SLASH}usebccparents{homeroom}{EXT}'), 'w') as f:
                f.write( '\n'.join(set(usebccparentsHOMEROOM[ns.homeroom])) )
        for ns.homeroom in usebccstudentsHOMEROOM:
            directory_write.append( ns('usebccstudents{homeroom}{COLON}{INCLUDE}{PATH}{SLASH}homerooms{SLASH}usebccstudents{homeroom}{EXT}') )
            with open( ns('{PATH}{SLASH}homerooms{SLASH}usebccstudents{homeroom}{EXT}'), 'w') as f:
                f.write( '\n'.join(set(usebccstudentsHOMEROOM[ns.homeroom])) )
        with open( ns('{PATH}{SLASH}homerooms{EXT}'), 'w') as f:
            f.write( '\n'.join(directory_write) )

        # TEACHERLINK
        directory_write = []
        for ns.student in teacherlink:
            directory_write.append( ns('{student}TEACHERS{COLON}{INCLUDE}{PATH}{SLASH}teacherlink{SLASH}{student}TEACHERS{EXT}') )
            with open( ns('{PATH}{SLASH}teacherlink{SLASH}{student}TEACHERS{EXT}'), 'w') as f:
                f.write( '\n'.join(set(teacherlink[ns.student])) )
        with open( ns('{PATH}{SLASH}teacherlink{EXT}'), 'w') as f:
            f.write( '\n'.join(directory_write) )

        # PARENTLINK
        directory_write = []
        for ns.student in parentlink:
            directory_write.append( ns('{student}PARENTS{COLON}{INCLUDE}{PATH}{SLASH}parentlink{SLASH}{student}PARENTS{EXT}') )
            with open( ns('{PATH}{SLASH}parentlink{SLASH}{student}PARENTS{EXT}'), 'w') as f:
                f.write( '\n'.join(set(parentlink[ns.student])) )
        with open( ns('{PATH}{SLASH}parentlink{EXT}'), 'w') as f:
            f.write( '\n'.join(directory_write) )

        # HRLINK
        directory_write = []
        for ns.student in hrlink:
            if hrlink[ns.student]:  # not all kids have a homeroom teacher....
                directory_write.append( ns('{student}HR{COLON}{INCLUDE}{PATH}{SLASH}homeroomlink{SLASH}{student}HR{EXT}') )
                with open( ns('{PATH}{SLASH}homeroomlink{SLASH}{student}HR{EXT}'), 'w') as f:
                    try:
                        f.write( '\n'.join(set(hrlink[ns.student])) )
                    except TypeError:
                      pass
        with open( ns('{PATH}{SLASH}homeroomlink{EXT}'), 'w') as f:
            f.write( '\n'.join(directory_write) )

        with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsALL{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccparentsALL) )

        with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsSEC{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccparentsSEC) )

        with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsELEM{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccparentsELEM) )

        with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsCHINESE{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccparentsCHINESE) )

        with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsCHINESESEC{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccparentsCHINESESEC) )

        with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsCHINESEELEM{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccparentsCHINESEELEM) )

        for ns.grade in usebccparentsCHINESEGRADE:
            with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsCHINESE{grade}{EXT}'), 'w') as f:
                f.write( '\n'.join(set(usebccparentsCHINESEGRADE[ns.grade])) )

        with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsKOREAN{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccparentsKOREAN) )

        with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsKOREANELEM{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccparentsKOREANSEC) )

        with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsKOREANSEC{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccparentsKOREANSEC) )

        for ns.grade in usebccparentsKOREANGRADE:
            with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsKOREAN{grade}{EXT}'), 'w') as f:
                f.write( '\n'.join(set(usebccparentsKOREANGRADE[ns.grade])) )

        with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsJAPANESE{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccparentsJAPANESE) )

        with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsJAPANESESEC{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccparentsJAPANESESEC) )

        for ns.grade in usebccparentsJAPANESEGRADE:
            with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsJAPANESE{grade}{EXT}'), 'w') as f:
                f.write( '\n'.join(set(usebccparentsJAPANESEGRADE[ns.grade])) )

        with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsSWA{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccparentsSWA) )

        with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsNOTSWA{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccparentsNOTSWA) )

        with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsGERMAN{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccparentsGERMAN) )

        with open( ns('{PATH}{SLASH}special{SLASH}usebccparentsNOTGERMAN{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccparentsNOTGERMAN) )

        with open( ns('{PATH}{SLASH}special{SLASH}usebccstudentsSWA{EXT}'), 'w') as f:
            f.write( '\n'.join(usebccstudentsSWA) )

        with open( ns('{PATH}{SLASH}special{SLASH}koreanstudentsSEC{EXT}'), 'w') as f:
            f.write( '\n'.join(koreanstudentsSEC) )

        with open( ns('{PATH}{SLASH}special{SLASH}chinesestudentsSEC{EXT}'), 'w') as f:
            f.write( '\n'.join(chinesestudentsSEC) )

        with open( ns('{PATH}{SLASH}special{EXT}'), 'w') as f:
            for ns.this in ['usebccparentsALL', 'usebccparentsSEC', 'usebccparentsELEM',
                            'usebccparentsKOREAN', 'usebccparentsKOREANSEC', 'usebccparentsKOREANELEM',
                            'usebccparentsCHINESE', 'usebccparentsCHINESESEC', 'usebccparentsCHINESEELEM',
                            'usebccparentsJAPANESE', 'usebccparentsJAPANESESEC', 'usebccparentsJAPANESEELEM',
                            'usebccparentsSWA', 'usebccstudentsSWA', 'usebccparentsNOTSWA', 'usebccparentsNOTGERMAN', 'usebccparentsGERMAN', 'koreanstudentsSEC', 'chinesestudentsSEC']:
                f.write( ns('{this}{COLON}{INCLUDE}{PATH}{SLASH}special{SLASH}{this}{EXT}{NEWLINE}') )
            for ns.grade in usebccparentsKOREANGRADE:
                f.write( ns('usebccparentsKOREAN{grade}{COLON}{INCLUDE}{PATH}{SLASH}special{SLASH}usebccparentsKOREAN{grade}{EXT}{NEWLINE}') )
            for ns.grade in usebccparentsCHINESEGRADE:
                f.write( ns('usebccparentsCHINESE{grade}{COLON}{INCLUDE}{PATH}{SLASH}special{SLASH}usebccparentsCHINESE{grade}{EXT}{NEWLINE}') )
            for ns.grade in usebccparentsJAPANESEGRADE:
                f.write( ns('usebccparentsJAPANESE{grade}{COLON}{INCLUDE}{PATH}{SLASH}special{SLASH}usebccparentsJAPANESE{grade}{EXT}{NEWLINE}') )

        # CLASSES
        directory_write = []
        for ns.klass in classes:
            directory_write.append( ns('{klass}{COLON}{INCLUDE}{PATH}{SLASH}classes{SLASH}{klass}{EXT}') )
        for ns.klass in classesPARENTS:
            directory_write.append( ns('{klass}PARENTS{COLON}{INCLUDE}{PATH}{SLASH}classes{SLASH}{klass}PARENTS{EXT}') )
        with open( ns('{PATH}{SLASH}classes{EXT}'), 'w') as f:
            f.write( '\n'.join(directory_write) )

        for ns.klass in classes:
            with open( ns('{PATH}{SLASH}classes{SLASH}{klass}{EXT}'), 'w') as f:
                f.write( '\n'.join(set(classes[ns.klass])) )

        for ns.klass in classesPARENTS:
            with open( ns('{PATH}{SLASH}classes{SLASH}{klass}PARENTS{EXT}'), 'w') as f:
                f.write( '\n'.join(set(classesPARENTS[ns.klass])) )

        self.logger.debug("Set up department batch emails")
        ##  SETUP DEPARTMENTS, including by homeroom teachers
        depart_dict = {}
        homeroom_teachers_dict = {}
        for teacher in self.teachers.get_objects():
            departments = teacher.get_departments()
            for department in departments:
                d_email_name = department_email_names.get(department)
                if not d_email_name:
                    continue
                if not d_email_name in list(depart_dict.keys()):
                    heads = department_heads.get(department, [])  # returns a list
                    depart_dict[d_email_name] = []
                    for head in heads:
                        self.logger.debug("Adding {} (the head) into department {}".format(head, d_email_name))
                        depart_dict[d_email_name].append(head + "@ssis-suzhou.net")
                if teacher and not teacher.email in depart_dict[d_email_name]:
                    self.logger.debug("Adding {} into department {}".format(teacher, d_email_name))
                    depart_dict[d_email_name].append(teacher.email)

            if teacher.homeroom:
                ns.homeroom = teacher.homeroom
                if not teacher.homeroom in homeroom_teachers_dict.keys():
                    homeroom_teachers_dict[teacher.homeroom] = True
                    setup_postfix = ns('{PATH}/departments{EXT}')
                    with open(setup_postfix, 'a') as f:
                        f.write(ns("homeroomteachers{homeroom}: :include:{PATH}/departments/homeroomteachers{homeroom}{EXT}\n"))
                setup_postfix = ns('{PATH}/departments/homeroomteachers{homeroom}{EXT}')
                with open(setup_postfix, 'a') as f:
                    f.write(teacher.email + '\n')

        for ns.department in list(depart_dict.keys()):
            # department is now actually the email name we want to use
            setup_postfix = ns('{PATH}/departments{EXT}')
            with open(setup_postfix, 'a') as f:
                f.write( ns("{department}: :include:{PATH}/departments/{department}{EXT}\n") )

            setup_postfix = ns('{PATH}/departments/{department}{EXT}')
            with open(setup_postfix, 'w') as f:
                f.write( "\n".join(depart_dict[ns.department]) )
import logging
import re
import os
import csv
from psmdlsyncer.settings import config_get_section_attribute
from html.parser import HTMLParser

# This is the version of the autosend files
# With each increase of number in the version, means that something about the fields have changed from within autosend
major_version = 4
prefix = config_get_section_attribute('AUTOSEND', 'prefix')
version_format = "{prefix}_{{school}}_{{unique}}_v{major_version}.{{minor_version}}".format(prefix=prefix, major_version=major_version)


class AutoSendImport:

    def __init__(self, school, unique):
        """
        Main task here is to set self.path
        """

        self.logger = logging.getLogger(self.__class__.__name__)

        path_to_powerschool = config_get_section_attribute('DIRECTORIES', 'path_to_powerschool_dump')
        if not path_to_powerschool:
            raise NotImplemented("Something wrong with the powerschool directory information")

        self.school = school
        self.unique = unique
        self.convert_entities = HTMLParser().unescape
        result = 100 + trans[re.sub("[0-9]", "", what)]
    elif "7" in what:
        result = 200 + trans[re.sub("[0-9]", "", what)]
    elif "8" in what:
        result = 300 + trans[re.sub("[0-9]", "", what)]
    elif "9" in what:
        result = 400 + trans[re.sub("[0-9]", "", what)]
    elif "10" in what:
        result = 500 + trans[re.sub("[0-9]", "", what)]
    elif "11" in what:
        result = 600 + trans[re.sub("[0-9]", "", what)]
    elif "12" in what:
        result = 700 + trans[re.sub("[0-9]", "", what)]
    elif re.sub("[1..9]", "", what):
        result = ord(re.sub("[1..9]", "", what)[0])
    return result


area = config_get_section_attribute("EMAIL", "aliases_path")
area += "/homerooms"

import os

user = os.listdir(area)

for item in user:
    item = item.strip()
    item = item.replace(".txt", "@student.ssis-suzhou.net")
    item = '<a href="mailto:?bcc={0}">{0}</a><br />'.format(item)
    print(item)
"""

"""
import re
path_to_mail_log = '/var/log/mail.log'
from psmdlsyncer.settings import config_get_section_attribute, \
     define_command_line_arguments
from psmdlsyncer.html_email import Email
from psmdlsyncer.utils import NS
from collections import defaultdict
from xml.sax.saxutils import escape
args = define_command_line_arguments('stdout', 'no_emails')
output = config_get_section_attribute('DIRECTORIES', 'path_to_output')
domain = config_get_section_attribute('EMAIL', 'domain')
if not domain:
    domain = 'localhost'
def out(line):
    with open(output + '/bounce_stats.txt', 'a') as f:
        f.write(str(line) + '\n')

class Bounce:
    def __init__(self):
        self.count = 0
        self.messages = []
        self.key = ""
    def __repr__(self):
        return self.key + ': ' + str(self.count) + '\n' + str(self.messages)

bounces = defaultdict(Bounce)
for line in open(path_to_mail_log):
    for search_item in ['status=bounced', 'status=deferred']: