Пример #1
0
def save_users():
    """
    添加用户

    :param: data: [ { 'sno': '123456' } ] 新生学号
    :param: group: 管理层
    :param: department: 部门
    """

    _data: dict = request.get_json(force=True)

    data: typing.List[dict] = _data.get('data')
    group: str = _data.get('group')
    department: str = _data.get('department')

    if data is None:
        raise HttpError(400, '请输入学号')
    if group is None:
        raise HttpError(400, '请选择管理层')
    if department is None:
        raise HttpError(400, '请选择部门')

    database.save_users(data, group, department)

    return {'message': '添加成功'}
Пример #2
0
def follow_user(uuid: str, username: str, status: int):
    """
    关注或取关用户
    """
    me: User = _get_user(uuid=uuid)
    if me is None:
        raise HttpError(401, '用户不存在,请重新登录')
    user: User = _get_user(username=username)
    if user is None:
        raise HttpError(404, '用户不存在')

    follow: Follow = _get_follow(user_id=me.user_id,
                                 followed_user_id=user.user_id)
    if follow:
        if follow.status == status:
            raise HttpError(400, f'{"已" if status else "未"}关注该用户')
        follow.status = status
        num = 1 if status else -1
    else:
        if not status:
            raise HttpError(400, '未关注该用户')
        follow: Follow = Follow(
            user_id=me.user_id,
            followed_user_id=user.user_id,
        )
        num = 1
        db.session.add(follow)

    me.follow_num = me.follow_num + num
    user.fans_num = user.fans_num + num
    db.session.commit()
Пример #3
0
def get_qrcode_timecapsule(openid: str, offset: int) -> dict:
    user: User = (
        User
            .query
            .filter_by(open_id=openid)
            .first()
    )

    if not user:
        raise HttpError(404, "没有参与活动")
    count: int = (
        ToTaCapsules
            .query
            .filter_by(from_qrcode=True, receiver_tel=user.phone)
            .count()
    )
    if count == 0:
        raise HttpError(404, '没有更多了')

    if offset is None:
        offset = 0
    else:
        offset = int(offset) % count
    capsule: ToTaCapsules = (
        ToTaCapsules
            .query
            .filter_by(from_qrcode=True, receiver_tel=user.phone)
            .offset(int(offset))
            .first()
    )

    return capsule.to_dict()
Пример #4
0
def update_current_user_avatar():
    """
    修改用户头像

    :param: avatar: file 头像文件
    """

    avatar: FileStorage = request.files.get('avatar')

    if avatar is None:
        raise HttpError(400, '请上传头像')

    extension_name = avatar.filename.split('.')[-1]
    if extension_name not in ['png', 'jpg', 'jpeg', 'gif']:
        raise HttpError(400, '目前只支持jpg, png, gif格式')

    filename = uuid.uuid4().hex + '.' + extension_name

    path = BaseConfig.upload_dir + filename

    avatar.save(path)

    avatar_path = database.update_avatar(session.get('user_id'), path)

    return {'avatar': avatar_path}
Пример #5
0
def get_not_deleted_users():
    """
    获取所有未删除的用户信息

    :param: type: 获取方式,不填为所有、group为同管理层、department为同部门,search为查询
    :param: page: 页数,默认1
    :param: limit: 每页数量,默认20

    :param: query: 查询关键字
    """

    page = int(request.args.get('page')) if str(
        request.args.get('page')).isdigit() else 1
    limit = int(request.args.get('limit')) if str(
        request.args.get('limit')).isdigit() else 20

    _type = request.args.get('type')
    if _type is None:
        users_info, users_count = database.get_users_info(page, limit)
    elif _type == 'group':
        users_info, users_count = database.get_same_group_users_info(
            session.get('user_id'), page, limit)
    elif _type == 'department':
        users_info, users_count = database.get_same_department_users_info(
            session.get('user_id'), page, limit)
    elif _type == 'search':
        query: str = request.args.get('query')
        if query is None:
            raise HttpError(400, '请输入查询关键字')
        users_info, users_count = database.query_users(query, page, limit)
    else:
        raise HttpError(400, 'type参数错误')

    return _users_info_return_data(users_info, users_count, page, limit)
Пример #6
0
def delete_comment(comment_id: int, uuid: str):
    """
    删除评论
    :param comment_id: 评论id
    :param uuid: uuid
    """
    comment: Comment = _get_comment(comment_id=comment_id)
    if not comment:
        raise HttpError(404, '评论不存在')

    comment_info: dict = _get_post_or_comment_info(comment)
    if not uuid == comment_info.get('uuid'):
        raise HttpError(403, '没有权限删除该评论')

    if comment.type:
        parent_comment: Comment = _get_comment(comment_id=comment.parent_id)
        parent_comment.comments_num = parent_comment.comments_num - 1
        if parent_comment.type:
            root_comment: Comment = _get_comment(comment_id=comment.root_id)
            root_comment.comments_num = root_comment.comments_num - 1
    else:
        parent_post: Post = _get_post(post_id=comment.parent_id)
        parent_post.comments_num = parent_post.comments_num - 1

    comment.deleted_at = datetime.datetime.now()
    db.session.commit()
Пример #7
0
def is_ongoing():
    begin = datetime.datetime.strptime(BaseConfig.begin, '%Y-%m-%d %H:%M:%S')
    end = datetime.datetime.strptime(BaseConfig.end, '%Y-%m-%d %H:%M:%S')
    now = datetime.datetime.strptime(
        datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
        '%Y-%m-%d %H:%M:%S')
    if now < begin:
        raise HttpError(410, '活动还未开始')
    elif now > end:
        raise HttpError(410, '活动已结束')
Пример #8
0
def save_image(dir_name: str, img: FileStorage) -> str:
    if img is None:
        raise HttpError(400, '上传图片失败')
    extension_name = img.filename.split('.')[-1]
    if extension_name not in ['png', 'jpg', 'jpeg', 'gif']:
        raise HttpError(400, '目前只支持jpg, png, gif格式')
    filename = uuid.uuid4().hex + '.' + extension_name
    path = dir_name + filename
    img.save(path)

    return filename
Пример #9
0
def update_user_password(uuid: str, password: str, old_pwd: str):
    """
    修改密码
    :param uuid: uuid
    :param old_pwd: 旧密码
    :param password: 新密码
    """
    user: User = _get_user(uuid=uuid)
    if user is None:
        raise HttpError(404, '用户不存在')
    if not user.check_password(old_pwd):
        raise HttpError(400, '旧密码错误')
    user.update_password(password)
    db.session.commit()
Пример #10
0
def get_comments(parent_id: int,
                 _type: int,
                 limit: int = 5,
                 last_comment_id: int = 0) -> (typing.List[dict], int):
    """
    通过id获取某个帖子或评论的多条评论
    :param: parent_id: 被评论的帖子或评论的id
    :param: _type: 是什么的评论,0是帖子,1是评论
    :param: last_id: 已获取评论中最后一个评论的id,默认为0
    :param: limit: 要获取的数目, 默认为5
    :return: [
        {
            "comment_id": "评论id",
            "parent_id": "被评论的帖子或评论的id",
            "type": "是什么的评论,0是帖子,1是评论",
            "content": "评论内容",
            "comments_num": "评论数目",
            "username": "******",
            "uuid": "发帖人uuid"
        }
        ...
    ]
    """
    if int(_type):  # 评论
        obj: Comment = _get_comment(comment_id=parent_id)
    else:  # 帖子
        obj: Post = _get_post(post_id=parent_id)
    if obj is None:
        raise HttpError(404, f'{"评论" if int(_type) else "帖子"}不存在')

    return _get_comments(last_comment_id, limit, root_id=parent_id,
                         type=_type), obj.comments_num
Пример #11
0
def get_user_info(uuid: str, username: str) -> dict:
    """
    获取用户信息
    :param uuid: uuid
    :param username 用户名
    :return: {
        "username": "******",
        "uuid": "uuid"
    }
    """
    if uuid:
        user: User = _get_user(uuid=uuid)
    else:
        user: User = _get_user(username=username)

    if user is None:
        raise HttpError(404, '用户不存在')

    if user.username == session.get('username'):
        return user.to_dict()
    else:
        me: User = _get_user(uuid=session.get('uuid'))
        follow: Follow = _get_follow(user_id=me.user_id,
                                     followed_user_id=user.user_id)
        if follow is None:
            status = False
        else:
            status = follow.status
        return {**user.to_dict(), 'follow_status': status}
Пример #12
0
def update_post(post_id: int):
    """
    修改帖子
    :param post_id: 帖子id
    :param: content: 帖子内容
    :return: {
        "data": {
            "post_id": "帖子id"
        },
        "msg": "OK",
        "status": 200
    }
    """
    content: str = request.form.get('content')
    ret = check_post_or_comment_content(content)
    if ret is not True:
        raise HttpError(400, ret)

    imgs_name = [
        save_image(BaseConfig.post_image_dir, img)
        for img in request.files.getlist('imgs')
    ]

    return Result.OK().data({
        'post_id':
        database.update_post(content=content,
                             imgs_name=imgs_name,
                             uuid=session.get('uuid'),
                             post_id=post_id)
    }).build()
Пример #13
0
def save_comment():
    """
    发表评论
    :param: parent_id: 被评论的帖子或评论的id
    :param: type: 是什么的评论,0是帖子,1是评论
    :param: content: 内容
    :return: {
        "data": {
            "comment_id": "评论id"
        },
        "msg": "OK",
        "status": 200
    }
    """
    content: str = request.form.get('content')
    ret = check_post_or_comment_content(content)
    if ret is not True:
        raise HttpError(400, ret)

    parent_id: int = request.form.get('parent_id')
    _type: int = request.form.get('type')

    img: FileStorage = request.files.get('img')
    img_name = None if img is None else save_image(
        BaseConfig.comment_image_dir, img)

    database.save_comment(content=content,
                          parent_id=parent_id,
                          _type=_type,
                          img_name=img_name,
                          uuid=session.get('uuid'))

    return Result.OK().build()
Пример #14
0
def update_comment(comment_id: int):
    """
    修改评论
    :param comment_id: 评论id
    :param: content: 新内容
    :return: {
        "data": {
            "comment_id": "评论id"
        },
        "msg": "OK",
        "status": 200
    }
    """
    content: str = request.form.get('content')
    ret = check_post_or_comment_content(content)
    if ret is not True:
        raise HttpError(400, ret)

    img: FileStorage = request.files.get('img')
    img_name = None if img is None else save_image(
        BaseConfig.comment_image_dir, img)

    database.update_comment(content=content,
                            img_name=img_name,
                            comment_id=comment_id,
                            uuid=session.get('uuid'))

    return Result.OK().build()
Пример #15
0
    def get_media(self, media_id):
        """
        下载多媒体文件
        https://developers.weixin.qq.com/doc/offiaccount/Asset_Management/Get_temporary_materials.html

        :param media_id: 前端传来的媒体文件ID
        """

        resp, content_type = self.get_media_resp(media_id)

        if content_type == 'application/json' or content_type == 'text/plain':  # Content-Type 不是媒体类型,说明请求出错,判断错误码
            data: dict = json.loads(resp.content)
            if data.get('errcode') == 40014:  # access_token过期
                self.refresh_token()
                resp, content_type = self.get_media_resp(media_id)
                if content_type == 'application/json' or content_type == 'text/plain':
                    data: dict = json.loads(resp.content)
            if data.get('errcode') == 40007:  # 不合法的媒体文件id
                raise HttpError(400, 'media_id无效')

            manage_wechat_error(data, [], '下载媒体文件失败')

        encoded_media = base64.b64encode(io.BytesIO(
            resp.content).read()).decode('ascii')

        return {
            'media_data': encoded_media,
            'content_type': resp.headers.get('Content-Type')
        }
Пример #16
0
def save_comment(content: str, img_name: str, parent_id: int, _type: int,
                 uuid: str) -> (int, str, str):
    """
    发表评论
    :param content: 评论内容
    :param img_name: 图片名
    :param parent_id: 被评论的帖子或评论的id
    :param _type: 是什么的评论,0是帖子,1是评论
    :param uuid: 发表评论的用户的uuid
    :return: comment_id
    """
    user: User = _get_user(uuid=uuid)
    if not User:
        raise HttpError(404, '用户不存在')

    if int(_type):  # 是评论
        comment: Comment = _get_comment(comment_id=parent_id)
        if not comment:
            raise HttpError(404, '评论不存在')
        comment.comments_num = comment.comments_num + 1
        if comment.type:  # 使根评论的评论数量加一
            root_comment: Comment = _get_comment(comment_id=comment.root_id)
            root_comment.comments_num = root_comment.comments_num + 1

        post_id = comment.post_id
        if comment.type:  # 父节点是对评论的评论,则将root_id设置为父节点的root_id
            root_id = comment.root_id
        else:  # 对帖子的评论,root_id设置为该评论的comment_id
            root_id = comment.comment_id
    else:  # 是帖子
        post: Post = _get_post(post_id=parent_id)
        if not post:
            raise HttpError(404, '帖子不存在')
        post.comments_num = post.comments_num + 1
        root_id = post.post_id
        post_id = post.post_id

    comment = Comment(user_id=user.user_id,
                      parent_id=parent_id,
                      root_id=root_id,
                      post_id=post_id,
                      type=_type,
                      content=content,
                      img_name=img_name)

    db.session.add(comment)
    db.session.commit()
Пример #17
0
def save_users(data: typing.List[dict], group_name: str, department_name: str):
    """
    添加用户

    :param data: [ { 'sno': '123456' } ] 新生学号
    :param group_name: 管理层
    :param department_name: 部门
    """

    department: Department = (Department.query.filter_by(
        name=department_name).first())

    if department is None:
        raise HttpError(400, '部门不存在')

    helper.check_permission(department.department_id)

    group: Group = (Group.query.filter_by(name=group_name).first())

    if group is None:
        raise HttpError(400, '管理层不存在')

    for d in data:
        sno = d.get('sno')
        if sno is None or len(sno) != 12:
            db.session.rollback()
            raise HttpError(400, '学号错误')

        user: User = (User.query.filter_by(sno=sno).first())

        if user is not None:
            db.session.rollback()
            raise HttpError(400, f'学号 {sno} 已存在')

        user: User = User(sno=sno,
                          password='******',
                          group_id=group.group_id,
                          department_id=department.department_id)
        db.session.add(user)
        db.session.flush()
        detail: Detail = Detail(user_id=user.user_id,
                                sex='不明',
                                avatar='storage/avatars/default.jpg',
                                name='',
                                birth='2000-01-01')
        db.session.add(detail)
    db.session.commit()
Пример #18
0
def update_user_detail(uuid: str, user_detail: dict):
    """
    修改用户信息
    :param uuid: uuid
    :param user_detail: 用户信息
    """
    user: User = _get_user(uuid=uuid)

    if user is None:
        raise HttpError(404, '用户不存在')

    if user.username != user_detail.get('username'):
        new_user: User = _get_user(username=user_detail.get('username'))
        if new_user:
            raise HttpError(409, '用户名已存在')
    user.update(**user_detail)
    db.session.commit()
Пример #19
0
def check_permission(department_id: int = None, check: bool = True) -> bool:
    current_user: User = User.query.get(session.get('user_id'))
    permission = bool(
        current_user.group_id < 5 and
        current_user.department_id == department_id if department_id else True
    )
    if check and not permission:
        raise HttpError(403, '没有权限')
    return permission
Пример #20
0
def follow_user():
    """
    关注或取关用户
    """
    data: dict = request.get_json(force=True)

    username: str = data.get('username')
    if username is None:
        raise HttpError(400, '用户名错误')
    if username == session.get('username'):
        raise HttpError(400, '无法关注自己')

    status: bool = data.get('status')
    if status is None:
        raise HttpError(400, '请选择要进行的操作')

    database.follow_user(session.get('uuid'), username, status)
    return Result.OK().build()
Пример #21
0
def delete_post(post_id: int, uuid: str):
    """
    删除帖子
    :param post_id: 帖子id
    :param uuid: 发帖人uuid
    """
    post: Post = _get_post(post_id=post_id)
    if not post:
        raise HttpError(404, '帖子不存在')

    post_info = _get_post_or_comment_info(post)
    if not uuid == post_info.get('uuid'):
        raise HttpError(403, '没有权限删除该帖子')
    post.deleted_at = datetime.datetime.now()

    user: User = _get_user(uuid=uuid)
    if user is None:
        raise HttpError(404, '用户不存在')
    user.posts_num = user.posts_num - 1

    db.session.commit()
Пример #22
0
def check_user_info(data: dict):
    # 性别
    sex = data.get('sex') or '不明'
    if sex not in ['男', '女', '不明']:
        raise HttpError(400, '性别填写错误')

    # 校区
    campus = data.get('campus')
    if campus is not None and campus not in ['大学城校区', '五山校区', '国际校区']:
        raise HttpError(400, '校区填写错误')

    # 学院
    college_id = data.get('college_id') or -1
    if college_id != -1:
        college: College = (
            College
                .query
                .get(college_id)
        )
        if college is None:
            raise HttpError(400, '学院不存在')
Пример #23
0
def manage_wechat_error(data: dict, login_codes: list, msg: str):
    """
    处理微信返回的错误
    全局错误码:https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Global_Return_Code.html

    :param data: 微信返回的数据,包含errcode和errmsg
    :param login_codes: errcode在这之中时返回401,否则返回500
    :param msg: 执行失败的错误信息,返回给前端、记录在log中
    """

    errcode = data.get('errcode')

    if errcode is None or errcode == 0:
        return
    if errcode == -1:
        raise HttpError(504, '微信服务器超时')
    if errcode in login_codes:
        raise HttpError(401, '请先登录微信')

    logger(msg, data)
    raise HttpError(400, msg, data)
Пример #24
0
def update_comment(comment_id: int, img_name: str, content: str,
                   uuid: str) -> int:
    """
    更新评论
    :param comment_id: 评论id
    :param img_name: 图片名
    :param content: 新内容
    :param uuid: uuid
    :return: comment_id
    """
    comment: Comment = _get_comment(comment_id=comment_id)
    if not comment:
        raise HttpError(404, '评论不存在')

    comment_info: dict = _get_post_or_comment_info(comment)
    if not uuid == comment_info.get('uuid'):
        raise HttpError(403, '没有权限修改该评论')

    comment.content = content
    comment.img_name = img_name
    db.session.commit()
Пример #25
0
def user_login(username: str, password: str) -> tuple:
    """
    用户登录
    :param username: 用户名
    :param password: 密码
    :return: (uuid, username)
    """
    user: User = _get_user(username=username)
    if user is None or not user.check_password(password):
        raise HttpError(400, '用户名或密码错误')

    return user.uuid, user.username
Пример #26
0
def get_code_timecapsule(code: str) -> dict:
    code = code.upper()
    capsule: ToTaCapsules = (
        ToTaCapsules
            .query
            .filter_by(code=code)
            .first()
    )

    if not capsule:
        raise HttpError(404, "取信码不存在")

    return capsule.to_dict()
Пример #27
0
def check_wechat_login():
    if not session.get('openid'):
        resp = requests.get(
            'https://hemc.100steps.net/2020/wechat/auth/user/openid',
            cookies=request.cookies)
        try:
            data = json.loads(resp.content)
            if 'openid' in data:
                session['openid'] = data.get('openid')
        except:
            current_app.logger.error(traceback.format_exc())
    if not session.get('openid'):
        raise HttpError(401, '请先登录微信')
Пример #28
0
def update_post(content: str, imgs_name: list, uuid: str, post_id: int) -> int:
    """
    修改帖子
    :param content: 新内容
    :param imgs_name: 图片名
    :param uuid: 发贴人uuid
    :param post_id: 帖子id
    :return: post_id
    """
    post: Post = _get_post(post_id=post_id)
    if not post:
        raise HttpError(404, '帖子不存在')

    post_info: dict = _get_post_or_comment_info(post)
    if not uuid == post_info.get('uuid'):
        raise HttpError(403, '没有权限修改该帖子')

    post.content = content
    post.imgs_name = imgs_name
    db.session.commit()

    return post.post_id
Пример #29
0
def create_user(username: str, password: str) -> tuple:
    """
    创建用户
    :param username: 用户名
    :param password: 密码
    :return: (uuid, username)
    """
    user: User = _get_user(username=username)
    if user:
        raise HttpError(409, '用户已存在')
    user: User = User(username=username, password=password)
    db.session.add(user)
    db.session.commit()
    return user.uuid, user.username
Пример #30
0
def login(sno: str, password: str):
    """
    用户登录

    :param sno: 学号
    :param password: 密码

    :return: user_id
    """

    user: User = (User.query.filter_by(sno=sno).first())

    if user is None or not user.check_password(password):
        raise HttpError(400, '学号或密码错误')

    return user.user_id