Exemplo n.º 1
0
def cal_page():
    """课表导出页面视图函数"""
    from everyclass.server.calendar import ics_generator
    from everyclass.server.db.dao import get_classes_for_student, get_my_semesters, check_if_stu_exist
    from everyclass.server.db.model import Semester

    # 如果请求中包含 id 就写入 session
    if request.values.get('id'):
        if not check_if_stu_exist(request.values.get('id')):
            flash("你输入的学号不存在")
            return redirect(url_for("main.main"))
        session['stu_id'] = request.values.get('id')

    # 如果 session 中有 stu_id 就生成 ics 并返回页面,没有就跳转回首页
    if session.get('stu_id', None):
        # 获得学生姓名和他的合法学期
        my_available_semesters, student_name = get_my_semesters(
            session['stu_id'])
        semester = Semester.get()
        student_classes = get_classes_for_student(session['stu_id'], semester)
        ics_generator.generate(session['stu_id'], student_name,
                               student_classes, semester.to_str(simplify=True),
                               semester.to_tuple())
        return render_template('ics.html',
                               student_id=session['stu_id'],
                               semester=semester.to_str(simplify=True))
    else:
        return redirect(url_for('main.main'))
Exemplo n.º 2
0
def get_courses(student_id, semester):
    """
    提供学号与学期,返回学生当前学期的课表。

    :param student_id: 学号
    :param semester: 学期
    """
    import json
    from everyclass.server.db.dao import get_classes_for_student
    from everyclass.server.db.model import Semester
    from everyclass.server.exceptions import IllegalSemesterException, NoStudentException

    try:
        courses = get_classes_for_student(student_id, Semester(semester))
        # TODO: handle if semester does not exist

        elasticapm.set_custom_context(stu_id=student_id, semester=semester)

        courses_to_return = {}
        for k, v in courses.items():
            if str(k[0]) not in courses_to_return:
                courses_to_return[str(k[0])] = {}
            courses_to_return[str(k[0])][str(k[1])] = v
        return json.dumps({'courses': courses_to_return})
    except IllegalSemesterException:
        response = jsonify({'error': 'wrong semester'})
        response.status_code = 400
        return response
    except NoStudentException:
        response = jsonify({'error': 'no such student'})
        response.status_code = 400
        return response
Exemplo n.º 3
0
def get_ics(student_id, semester_str):
    """
    iCalendar service
    """
    from everyclass.server.calendar import ics_generator
    from everyclass.server.db.dao import check_if_stu_exist, get_my_semesters, get_classes_for_student
    from everyclass.server.db.model import Semester
    from everyclass.server.exceptions import IllegalSemesterException
    from everyclass.server import logger

    # TODO: generate ics here and return it to user, instead of generating .ics files in other places.
    # 临时 fix
    place = student_id.find('-')
    semester_str = student_id[place + 1:len(student_id)] + '-' + semester_str
    student_id = student_id[:place]

    # 学号检测
    if not check_if_stu_exist(student_id):
        flash("{} 学号不存在".format(student_id))
        logger.warning("[ics] {} 学号不存在".format(student_id))
        return redirect(url_for("main.main"))

    # 学期检测
    my_available_semesters, student_name = get_my_semesters(student_id)
    try:
        semester = Semester(semester_str)
    except IllegalSemesterException:
        flash("{} 学期格式错误".format(semester_str))
        logger.warning("{} 学期格式错误".format(semester_str))
        return redirect(url_for("main.main"))
    if semester not in my_available_semesters:
        flash("{} 学期不适用于此学生".format(semester_str))
        logger.warning("{} 学期不适用于此学生".format(semester_str))
        return redirect(url_for("main.main"))

    student_classes = get_classes_for_student(student_id, semester)
    ics_generator.generate(student_id, student_name, student_classes,
                           semester.to_str(simplify=True), semester.to_tuple())

    return send_from_directory("../../calendar_files",
                               student_id + "-" + semester_str + ".ics",
                               as_attachment=True,
                               mimetype='text/calendar')
Exemplo n.º 4
0
def batch_generate():
    """生成当前学期所有学生的 ics 文件,每次更新当前学期数据后使用"""
    from everyclass.server import create_app
    from everyclass.server.db.dao import get_all_students, get_classes_for_student
    from everyclass.server.db.model import Semester

    config = get_config()
    now_semester = Semester(config.DEFAULT_SEMESTER)
    now_semester_str = str(now_semester)

    with create_app(offline=True).app_context():
        students = get_all_students()
        print("Total {} students".format(len(students)))
        for each in students:
            if now_semester_str in each[2]:
                print("Generate .ics for [{}]{}...".format(each[0], each[1]))
                student_classes = get_classes_for_student(
                    each[0], now_semester)
                generate(student_id=each[0],
                         student_name=each[1],
                         student_classes=student_classes,
                         semester_string=now_semester.to_str(simplify=True),
                         semester=now_semester.to_tuple())
        print("Done.")
Exemplo n.º 5
0
def query():
    """
    查询本人课表视图函数
    正常情况应该是 post 方法,但是也兼容 get 防止意外情况,提高用户体验
    """
    from flask import request, render_template, redirect, url_for, session
    from flask import current_app as app
    import elasticapm

    from everyclass.server.tools import is_chinese_char
    from everyclass.server.exceptions import NoStudentException, IllegalSemesterException
    from everyclass.server.db.mysql import get_local_conn
    from everyclass.server.db.dao import faculty_lookup
    from everyclass.server.db.dao import class_lookup
    from everyclass.server.db.dao import get_classes_for_student
    from everyclass.server.db.model import Semester
    from everyclass.server.db.dao import get_privacy_settings
    from everyclass.server.db.dao import get_my_semesters
    from everyclass.server.db.dao import check_if_stu_exist

    # if under maintenance, return to maintenance.html
    if app.config["MAINTENANCE"]:
        return render_template("maintenance.html")

    db = get_local_conn()
    cursor = db.cursor()

    # 如 URL 中有 id 参数,判断是姓名还是学号,然后赋学号给student_id
    if request.values.get('id'):
        id_or_name = request.values.get('id')

        # 首末均为中文,判断为人名
        if is_chinese_char(id_or_name[0:1]) and is_chinese_char(
                id_or_name[-1:]):
            # 使用人名查询打点
            elasticapm.tag(ec_query_method='by_name')

            mysql_query = "SELECT name,xh FROM ec_students WHERE name=%s"
            cursor.execute(mysql_query, (id_or_name, ))
            result = cursor.fetchall()
            if cursor.rowcount > 1:
                # 查询到多个同名,进入选择界面
                students_list = list()
                for each_student in result:
                    students_list.append([
                        each_student[0], each_student[1],
                        faculty_lookup(each_student[1]),
                        class_lookup(each_student[1])
                    ])
                return render_template("query_same_name.html",
                                       count=cursor.rowcount,
                                       student_info=students_list)
            elif cursor.rowcount == 1:
                # 仅能查询到一个人,则赋值学号
                student_id = result[0][1]
            else:
                # 查无此人
                elasticapm.tag(ec_query_not_found=True)
                return _no_student_handle(id_or_name)

        # id 不为中文,则为学号
        else:
            # 学号查询打点
            elasticapm.tag(ec_query_method='by_id')
            student_id = request.values.get('id')

            # 判断学号是否有效
            if not check_if_stu_exist(student_id):
                elasticapm.tag(ec_query_not_found=True)
                return _no_student_handle(student_id)

        # 写入 session 的学号一定有效
        session['stu_id'] = student_id

    # url 中没有 id 参数但 session 中有
    elif session.get('stu_id', None):
        elasticapm.tag(ec_query_method='by_session')
        student_id = session['stu_id']

    # 既没有 id 参数也没有 session,无法知道需要查询谁的课表,返回主页
    else:
        elasticapm.tag(ec_query_method='exception')
        return redirect(url_for('main.main'))

    # 查询学生本人的可用学期
    my_available_semesters, student_name = get_my_semesters(student_id)

    # 如果没有学期,则直接返回
    if not my_available_semesters:
        logger.warning('Not any semester in ec_student', stack=True)
        return _no_student_handle()

    # 如URL参数中包含学期,判断有效性后更新 session
    if request.values.get('semester'):
        try:
            sem = Semester(request.values.get('semester'))
            if sem in my_available_semesters:
                session['semester'] = sem.to_tuple()
                if app.config['DEBUG']:
                    print('[query.query] updated session semester to',
                          Semester(session['semester']).to_str())

        # 用户指定的学期格式不合法
        except IllegalSemesterException:
            if app.config['DEBUG']:
                print('[query.query] IllegalSemesterException handled.' +
                      Semester(session['semester']).to_str())
            session['semester'] = my_available_semesters[-1].to_tuple()

    cursor.close()  # 关闭数据库连接

    # 如果 session 中无学期或学期无效,回落到本人可用最新学期
    # session 中学期使用 tuple 保存,因为 Semester 对象无法被序列化
    semester = session.get('semester', None)
    if not semester or Semester(semester) not in my_available_semesters:
        session['semester'] = my_available_semesters[-1].to_tuple()

    try:
        student_classes = get_classes_for_student(student_id=student_id,
                                                  sem=Semester(
                                                      session['semester']))
    except NoStudentException:
        return _no_student_handle(student_id)
    else:
        # 空闲周末判断,考虑到大多数人周末都是没有课程的
        empty_weekend = True
        for cls_time in range(1, 7):
            for cls_day in range(6, 8):
                if (cls_day, cls_time) in student_classes:
                    empty_weekend = False

        # 空闲课程判断,考虑到大多数人11-12节都是没有课程的
        empty_6 = True
        for cls_day in range(1, 8):
            if (cls_day, 6) in student_classes:
                empty_6 = False
        empty_5 = True
        for cls_day in range(1, 8):
            if (cls_day, 5) in student_classes:
                empty_5 = False

        # available_semesters 为当前学生所能选择的学期,是一个list。
        # 当中每一项又是一个包含两项的list,第一项为学期string,第二项为True/False表示是否为当前学期。
        available_semesters = []

        for each_semester in my_available_semesters:
            if session['semester'] == each_semester:
                available_semesters.append([each_semester, True])
            else:
                available_semesters.append([each_semester, False])

        # Privacy settings
        # Available privacy settings: "show_table_on_page", "import_to_calender", "major"
        privacy_settings = get_privacy_settings(student_id)

        # privacy on
        if "show_table_on_page" in privacy_settings:
            return render_template(
                'blocked.html',
                name=student_name,
                falculty=faculty_lookup(student_id),
                class_name=class_lookup(student_id),
                stu_id=student_id,
                available_semesters=available_semesters,
                no_import_to_calender=True
                if "import_to_calender" in privacy_settings else False)

        # privacy off
        return render_template('query.html',
                               name=student_name,
                               falculty=faculty_lookup(student_id),
                               class_name=class_lookup(student_id),
                               stu_id=student_id,
                               classes=student_classes,
                               empty_wkend=empty_weekend,
                               empty_6=empty_6,
                               empty_5=empty_5,
                               available_semesters=available_semesters)