Example #1
0
def character_recent_activity_api(slug):
    try:
        character = sqla.session.query(sqlm.Character).filter_by(slug=slug.strip().lower())[0]
    except IndexError:
        abort(404)

    try:
        draw = int(request.args.get("draw"))
    except:
        draw = 0

    table_data = []

    posts = sqla.session.query(sqlm.Post).filter_by(character=character).all()

    for i, post in enumerate(posts):
        table_data.append(
            [
                """<a href="/t/%s/page/1/post/%s">%s</a>""" % (
                        post.topic.slug,
                        post.id,
                        post.topic.title
                    ),
                post.author.display_name,
                humanize_time(post.created),
                arrow.get(post.created).timestamp
            ]
        )
    data = {
        "draw": draw,
        "recordsTotal": len(table_data),
        "recordsFiltered": len(table_data),
        "data": table_data
    }
    return app.jsonify(data)
Example #2
0
def dashboard_notifications():
    notifications = sqla.session.query(sqlm.Notification) \
        .filter_by(
            user=current_user,
            acknowledged=False) \
        .options(joinedload(sqlm.Notification.author))\
        .order_by(sqlm.Notification.created).all()
    parsed_notifications = []

    for notification in notifications:
        try:
            parsed_ = {}
            parsed_["time"] = humanize_time(notification.created)
            parsed_["stamp"] = arrow.get(notification.created).timestamp
            parsed_["member_disp_name"] = notification.author.display_name
            parsed_["member_url"] = notification.author.my_url
            parsed_["member_pk"] = str(notification.author.id)
            parsed_["member_avatar"] = notification.author.get_avatar_url("40")
            parsed_["text"] = notification.message
            parsed_["id"] = notification.id
            parsed_["_id"] = notification.id
            parsed_["category"] = notification.category
            parsed_["url"] = notification.url
            parsed_["ref"] = md5(notification.url+notification.message)
            parsed_notifications.append(parsed_)
        except AttributeError:
            pass

    return app.jsonify(notifications=parsed_notifications)
def status_update_replies(status):
    try:
        status = sqla.session.query(sqlm.StatusUpdate).filter_by(id=status)[0]
    except:
        return abort(404)

    request.canonical = app.config['BASE'] + "/status/%s" % (status, )

    if status.hidden == True and (current_user.is_admin != True
                                  or current_user.is_mod != True):
        return abort(404)

    cleaner = ForumHTMLCleaner()

    replies = []
    for reply in sqla.session.query(sqlm.StatusComment).filter_by(
            status=status, hidden=False).order_by(sqlm.StatusComment.created):
        parsed_reply = {}
        parsed_reply["text"] = cleaner.escape(reply.message)
        parsed_reply["user_name"] = reply.author.display_name
        parsed_reply["author_login_name"] = reply.author.my_url
        parsed_reply["user_avatar"] = reply.author.get_avatar_url("60")
        parsed_reply["user_avatar_x"] = reply.author.avatar_60_x
        parsed_reply["user_avatar_y"] = reply.author.avatar_60_y
        parsed_reply["is_admin"] = current_user.is_admin
        parsed_reply["time"] = humanize_time(reply.created)
        parsed_reply["idx"] = reply.id
        replies.append(parsed_reply)

    return app.jsonify(replies=replies, count=status.get_comment_count())
Example #4
0
def broadcast(to, category, url, title, description, content, author, priority=0):
    
    # Hack for hidden areas of the forum
    try:
        if content.hidden == True:
            return
    except:
        pass
        
    try:
        if content.topic.hidden == True:
            return
    except:
        pass
        
    if category not in [x[0] for x in sqlm.Notification.NOTIFICATION_CATEGORIES]:
        raise TypeError("Category is not defined in NOTIFICATION_CATEGORIES.")

    if to == "ALL":
        to = sqla.session.query(sqlm.User).filter_by(banned=False).all()

    now = arrow.utcnow()
    author = author

    send_to_logins = []
    notification_counts = {}
    dashboard_notifications = {}
    notification_ids = {}
    timestamp = None
    reference = None

    for u in to:
        try:
            if not type(u) == sqlm.User:
                user = sqla.session.query(sqlm.User).filter_by(banned=False).filter_by(login_name=u)[0]
            else:
                user = u
            try:
                if current_user == user:
                    continue
            except:
                pass
        except IndexError:
            continue
        
        if type(content) == sqlm.Category:
            cat_perm_calculus = CategoryPermissionCalculator(user)
            if not cat_perm_calculus.can_view_topics(content.id, content.can_view_topics):
                return abort(404)
                
        if type(content) == sqlm.Topic:
            cat_perm_calculus = CategoryPermissionCalculator(user)
            if not cat_perm_calculus.can_view_topics(content.category.id, content.category.can_view_topics):
                return abort(404)

        if user.notification_preferences is None:
            user.notification_preferences = {}
            flag_modified(user, "notification_preferences")
            sqla.session.add(user)
            sqla.session.commit()

        if not user.notification_preferences.get(category, {"dashboard": True}).get("dashboard"):
            continue

        try:
            ignore = sqla.session.query(sqlm.IgnoringUser).filter_by(user=user, ignoring=author)[0]
            continue
        except:
            pass

        new_notification = sqlm.Notification(
            category = category,
            user = user,
            author = author,
            created = now.datetime.replace(tzinfo=None),
            url = url,
            message = title,
            priority = priority,
            snippet = description
        )

        sqla.session.add(new_notification)
        sqla.session.commit()

        send_to_logins.append(u.listener_token)
        notification_counts[u.listener_token] = u.get_notification_count()
        notification_ids[u.listener_token] = new_notification.id
        dashboard_notifications[u.listener_token] = u.get_dashboard_notifications()
        timestamp = new_notification.created

    data = {
        "users": send_to_logins,
        "count": notification_counts,
        "dashboard_count": dashboard_notifications,
        "category": category,
        "author": author.display_name,
        "member_name": author.login_name,
        "member_pk": str(author.id),
        "member_disp_name": author.display_name,
        "author_url": "/member/"+author.my_url,
        "member_url": "/member/"+author.my_url,
        "author_avatar": author.get_avatar_url("40"),
        "time": humanize_time(now.datetime),
        "url": url,
        "stamp": humanize_time(timestamp),
        "text": title,
        "priority": priority,
        "id": notification_ids,
        "ref": reference
    }
    data["ref"] = md5(url+title)

    thread = Thread(target=send_message, args=(data, ))
    thread.start()
def make_status_update_reply(status):
    try:
        status = sqla.session.query(sqlm.StatusUpdate).filter_by(id=status)[0]
    except:
        return abort(404)

    if status.hidden == True and (current_user.is_admin != True
                                  or current_user.is_mod != True):
        return abort(404)

    if status.muted and current_user != status.author:
        return app.jsonify(error="This status update is silenced. Shhh!")

    if (current_user in [u.ignoring for u in status.author.ignored_users
                         ]) and not current_user.is_admin:
        return app.jsonify(error="User has blocked you.")

    try:
        if not (current_user.is_admin or current_user.is_mod) and \
                (sqla.session.query(sqlm.StatusUpdateUser). \
                filter_by(status=status, author=current_user)[0].blocked):
            return app.jsonify(
                error="You have been blocked from this status update.")
    except IndexError:
        pass

    if status.locked:
        return app.jsonify(error="This status update is locked.")

    if status.get_comment_count() > 199:
        return app.jsonify(error="This status update is full!")

    request_json = request.get_json(force=True)

    if request_json.get("reply", "").strip() == "":
        return app.jsonify(error="Your status update is empty.")

    if len(request_json.get("reply", "")) > 1000:
        return app.jsonify(error="Your status update is too long.")

    cleaner = ForumHTMLCleaner()
    try:
        cleaner.escape(request_json.get("reply", ""))
    except:
        return abort(500)

    _html = request_json.get("reply", "").strip()

    user_last_comment = False
    for comment in status.comments:
        if comment.author == current_user:
            user_last_comment = comment
    if user_last_comment:
        difference = (arrow.utcnow().datetime -
                      arrow.get(user_last_comment.created).datetime).seconds
        if difference < 2:
            return app.jsonify(
                error="Please wait %s seconds before you can reply again." %
                (2 - difference))

    sc = sqlm.StatusComment()
    sc.created = arrow.utcnow().datetime.replace(tzinfo=None)
    sc.message = _html
    sc.author = current_user
    sc.status = status

    sqla.session.add(sc)
    sqla.session.commit()

    status.replies = status.get_comment_count()
    status.last_replied = arrow.utcnow().datetime.replace(tzinfo=None)

    sqla.session.add(status)
    sqla.session.commit()

    if not current_user in status.participants:
        status.participants.append(current_user)

    clean_html_parser = ForumPostParser()
    parsed_reply = {}
    parsed_reply["text"] = cleaner.escape(sc.message)
    parsed_reply["user_name"] = sc.author.display_name
    parsed_reply["user_avatar"] = sc.author.get_avatar_url("60")
    parsed_reply["user_avatar_x"] = sc.author.avatar_60_x
    parsed_reply["author_login_name"] = sc.author.my_url
    parsed_reply["user_avatar_y"] = sc.author.avatar_60_y
    parsed_reply["time"] = humanize_time(sc.created)

    send_notify_to_users = []
    exclude_from_mention = []
    for user in sqla.session.query(
            sqlm.StatusUpdateUser).filter_by(status=status).all():
        if user.author == current_user:
            exclude_from_mention.append(user.author.id)
            continue

        if user.ignoring:
            exclude_from_mention.append(user.author.id)
            continue

        if user.author == status.author:
            exclude_from_mention.append(user.author.id)
            continue

        send_notify_to_users.append(user.author)
        exclude_from_mention.append(user.author.id)

    broadcast(to=send_notify_to_users,
              category="status",
              url="/status/" + str(status.id),
              title="replied to %s's status update" %
              (str(status.author.display_name), ),
              description=status.message,
              content=status,
              author=current_user)

    try:
        status_user = sqla.session.query(sqlm.StatusUpdateUser).filter_by(
            status=status, author=status.author)[0]
    except IndexError:
        status_user = None

    if current_user != status.author:
        if status_user == None:
            broadcast(to=[status.author],
                      category="status",
                      url="/status/" + str(status.id),
                      title="replied to your status update",
                      description=status.message,
                      content=status,
                      author=current_user)
        else:
            if not status_user.ignoring:
                broadcast(to=[status.author],
                          category="status",
                          url="/status/" + str(status.id),
                          title="replied to your status update",
                          description=status.message,
                          content=status,
                          author=current_user)

    scan_status_for_mentions(sc, exclude_from_mention, is_reply=True)

    return app.jsonify(newest_reply=parsed_reply,
                       count=status.get_comment_count(),
                       success=True)
def status_update_index():
    count = session.get("count", 15)
    authors = session.get("authors", [])
    search = session.get("search", "")

    if request.method == 'POST':
        request_json = request.get_json(force=True)

        count = int(request_json.get("count", 15))
        if count > 1000:
            count = 1000
        session["count"] = count

        search = request_json.get("search", "")[0:100]
        session["search"] = search

        if request_json.get("authors"):
            author_objects = list(
                        sqla.session.query(sqlm.User) \
                            .filter(sqlm.User.id.in_(request_json.get("authors"))) \
                            .all()
                    )
            session["authors"] = [{
                "id": a.id,
                "text": a.display_name
            } for a in author_objects]
            authors = [{
                "id": a.id,
                "text": a.display_name
            } for a in author_objects]

    query_ = sqla.session.query(sqlm.StatusUpdate).filter_by(hidden=False)
    if authors:
        query_ = query_.filter(
            sqlm.StatusUpdate.author_id.in_([a["id"] for a in authors]))
    status_updates = parse_search_string(search, sqlm.StatusUpdate, query_, [
        "message",
    ]).order_by(sqla.desc(sqlm.StatusUpdate.created))[:count]

    cleaner = ForumHTMLCleaner()

    if request.method == 'POST':
        parsed_statuses = []
        for status in status_updates:
            parsed_status = {}

            parsed_status["_id"] = status.id
            parsed_status["profile_address"] = url_for(
                'view_profile', login_name=status.author.my_url)
            parsed_status["user_name"] = status.author.display_name
            parsed_status["message"] = cleaner.escape(status.message)
            parsed_status["user_avatar"] = status.author.get_avatar_url("60")
            if status.attached_to_user != None:
                parsed_status[
                    "attached_to_user"] = status.attached_to_user.display_name
                parsed_status["attached_to_user_url"] = url_for(
                    'view_profile', login_name=status.attached_to_user.my_url)
            else:
                parsed_status["attached_to_user"] = False
            parsed_status["user_avatar_x"] = status.author.avatar_60_x
            parsed_status["user_avatar_y"] = status.author.avatar_60_y
            parsed_status["created"] = humanize_time(status.created)
            parsed_status["comment_count"] = status.get_comment_count()
            parsed_statuses.append(parsed_status)
        return app.jsonify(status_updates=parsed_statuses)
    else:
        return render_template("core/status_index.jade",
                               page_title="Status Updates - %s" %
                               (app.get_site_config("core.site-name"), ),
                               status_updates=status_updates,
                               count=count,
                               search=search,
                               authors=json.dumps(authors))
Example #7
0
def messages_topics():
    request_json = request.get_json(force=True)
    page = request_json.get("page", 1)
    pagination = request_json.get("pagination", 20)

    if page < 1:
        page = 1

    try:
        minimum = (int(page) - 1) * int(pagination)
        maximum = int(page) * int(pagination)
    except:
        minimum = 0
        maximum = 20

    messages_count = sqla.session.query(sqlm.PrivateMessage) \
        .join(sqlm.PrivateMessageUser.pm) \
        .filter(
            sqlm.PrivateMessageUser.author == current_user,
            sqlm.PrivateMessageUser.blocked == False,
            sqlm.PrivateMessageUser.exited == False
            ).count()

    messages = sqla.session.query(sqlm.PrivateMessage) \
        .join(sqlm.PrivateMessageUser.pm) \
        .filter(
            sqlm.PrivateMessageUser.author == current_user,
            sqlm.PrivateMessageUser.blocked == False,
            sqlm.PrivateMessageUser.exited == False
            ) \
        .join(sqlm.PrivateMessage.last_reply) \
        .order_by(sqlm.PrivateMessageReply.created.desc())[minimum:maximum]

    parsed_messages = []

    for message in messages:
        _parsed = {}

        pm_participants = sqla.session.query(
            sqlm.PrivateMessageUser).filter_by(pm=message).filter(
                sqlm.PrivateMessageUser.author != current_user).all()

        last_viewed = sqla.session.query(
            sqlm.PrivateMessageUser.last_viewed).filter_by(
                pm=message, author=current_user)[0]

        try:
            _parsed["participants"] = [[
                u.author.my_url, u.author.display_name, ", "
            ] for u in pm_participants]
            _parsed["participants"][-1][2] = ""
        except:
            continue

        _parsed["creator"] = message.author.display_name
        _parsed["created"] = humanize_time(message.created, "MMM D YYYY")

        if last_viewed[0] == None:
            _parsed["new_messages"] = False
        elif last_viewed[
                0] < message.last_reply.created and message.last_reply.author != current_user:
            _parsed["new_messages"] = True
        else:
            _parsed["new_messages"] = False

        _parsed["last_post_date"] = humanize_time(message.last_reply.created)
        _parsed["last_post_by"] = message.last_reply.author.display_name
        _parsed["last_post_x"] = message.last_reply.author.avatar_40_x
        _parsed["last_post_y"] = message.last_reply.author.avatar_40_y
        _parsed["last_post_by_login_name"] = message.last_reply.author.my_url
        _parsed[
            "last_post_author_avatar"] = message.last_reply.author.get_avatar_url(
                "60")
        _parsed["message_count"] = "{:,}".format(message.count)
        _parsed["_id"] = message.id
        _parsed["title"] = message.title
        try:
            _parsed["last_page"] = float(message.count) / float(pagination)
        except:
            _parsed["last_page"] = 1
        _parsed["last_pages"] = _parsed["last_page"] > 1
        parsed_messages.append(_parsed)

    return app.jsonify(topics=parsed_messages, count=messages_count)
Example #8
0
def private_message_posts(pk):
    try:
        topic = sqla.session.query(sqlm.PrivateMessage).filter_by(id=pk)[0]
    except IndexError:
        return abort(404)

    try:
        pm_user = sqla.session.query(sqlm.PrivateMessageUser).filter_by(
            pm=topic, author=current_user)[0]
    except IndexError:
        if current_user.login_name in ["scarlet", "zoop"]:
            pass
        else:
            return abort(404)

    request_json = request.get_json(force=True)

    try:
        pagination = int(request_json.get("pagination", 20))
        page = int(request_json.get("page", 1))
    except:
        pagination = 20
        page = 1

    posts = sqla.session.query(sqlm.PrivateMessageReply) \
        .filter_by(pm=topic).order_by(sqlm.PrivateMessageReply.created) \
        [(page-1)*pagination:page*pagination]

    post_count = sqla.session.query(sqlm.PrivateMessageReply) \
        .filter_by(pm=topic).count()
    parsed_posts = []

    for post in posts:
        clean_html_parser = ForumPostParser()
        parsed_post = {}
        parsed_post["created"] = humanize_time(post.created, "MMM D YYYY")
        parsed_post["modified"] = humanize_time(post.modified, "MMM D YYYY")
        parsed_post["html"] = clean_html_parser.parse(post.message,
                                                      _object=post)
        parsed_post["user_avatar"] = post.author.get_avatar_url()
        parsed_post["user_avatar_x"] = post.author.avatar_full_x
        parsed_post["user_avatar_y"] = post.author.avatar_full_y
        parsed_post["user_avatar_60"] = post.author.get_avatar_url("60")
        parsed_post["user_avatar_x_60"] = post.author.avatar_60_x
        parsed_post["user_avatar_y_60"] = post.author.avatar_60_y
        parsed_post["user_title"] = post.author.title
        parsed_post["author_login_name"] = post.author.my_url
        parsed_post["author_actual_login_name"] = post.author.login_name
        parsed_post["_id"] = post.id

        if current_user.is_authenticated:
            if post.author.id == current_user.id:
                parsed_post["is_author"] = True
            else:
                parsed_post["is_author"] = False
        else:
            parsed_post["is_author"] = False

        if post.author.last_seen != None:
            if arrow.get(post.author.last_seen) > arrow.utcnow().replace(
                    minutes=-15).datetime:
                parsed_post["author_online"] = True
            else:
                parsed_post["author_online"] = False
        else:
            parsed_post["author_online"] = False

        parsed_posts.append(parsed_post)

    return app.jsonify(posts=parsed_posts, count=post_count)
Example #9
0
def new_message_in_pm_topic(pk):
    try:
        topic = sqla.session.query(sqlm.PrivateMessage).filter_by(id=pk)[0]
    except IndexError:
        return abort(404)

    try:
        pm_user = sqla.session.query(sqlm.PrivateMessageUser).filter_by(
            pm=topic, author=current_user)[0]
    except IndexError:
        return abort(404)

    difference = (arrow.utcnow().datetime -
                  arrow.get(topic.last_reply.created).datetime).seconds
    if difference < 10 and topic.last_reply.author == current_user:
        return app.jsonify(
            error="Please wait %s seconds before you can reply again." %
            (10 - difference))

    request_json = request.get_json(force=True)

    if len(request_json.get("text", "")) > 50000:
        return app.jsonify(error="Your post is too large.")

    if request_json.get("text", "").strip() == "":
        return app.jsonify(error="Your post is empty.")

    non_left_or_blocked_users = sqla.session.query(
        sqlm.PrivateMessageUser).filter_by(pm=topic,
                                           exited=False,
                                           blocked=False).count()

    if non_left_or_blocked_users == 1:
        return app.jsonify(
            error=
            "There is only one participant in this private message. Don't talk to yourself. :)"
        )

    cleaner = ForumHTMLCleaner()
    try:
        post_html = cleaner.clean(request_json.get("post", ""))
    except:
        return abort(500)

    message = sqlm.PrivateMessageReply()
    message.message = post_html
    message.author = current_user
    message.created = arrow.utcnow().datetime.replace(tzinfo=None)
    message.pm = topic
    message.pm_title = topic.title
    sqla.session.add(message)
    sqla.session.commit()

    topic.last_reply = message
    topic.count = topic.count + 1
    sqla.session.add(topic)
    sqla.session.commit()

    clean_html_parser = ForumPostParser()
    parsed_post = {}
    parsed_post["created"] = humanize_time(message.created, "MMM D YYYY")
    parsed_post["modified"] = humanize_time(message.modified, "MMM D YYYY")
    parsed_post["html"] = clean_html_parser.parse(message.message,
                                                  _object=message)
    parsed_post["user_avatar"] = message.author.get_avatar_url()
    parsed_post["user_avatar_x"] = message.author.avatar_full_x
    parsed_post["user_avatar_y"] = message.author.avatar_full_y
    parsed_post["user_avatar_60"] = message.author.get_avatar_url("60")
    parsed_post["user_avatar_x_60"] = message.author.avatar_60_x
    parsed_post["user_avatar_y_60"] = message.author.avatar_60_y
    parsed_post["user_title"] = message.author.title
    parsed_post["_id"] = message.id
    parsed_post["author_name"] = message.author.display_name
    parsed_post["author_login_name"] = message.author.my_url
    parsed_post["author_actual_login_name"] = message.author.login_name
    post_count = sqla.session.query(
        sqlm.PrivateMessageReply).filter_by(pm=topic).count()

    notify_users = []
    for u in sqla.session.query(sqlm.PrivateMessageUser).filter_by(pm=topic):
        if u.author == message.author:
            continue
        if u.exited or u.blocked or u.ignoring:
            continue
        notify_users.append(u.author)

    broadcast(to=notify_users,
              category="pm",
              url="/messages/%s/page/1/post/%s" %
              (str(topic.id), str(message.id)),
              title="replied to %s" % (str(topic.title)),
              description=message.message,
              content=topic,
              author=message.author)

    return app.jsonify(newest_post=parsed_post, count=post_count, success=True)
Example #10
0
def character_list_api():
    try:
        current = int(request.args.get("start"))
    except:
        current = 0

    try:
        draw = int(request.args.get("draw"))
    except:
        draw = 0

    try:
        length = int(request.args.get("length"))
    except:
        length = 10

    try:
        order = int(request.args.get("order[0][column]"))
    except:
        order = 4

    if order == 0:
        order = "name"
    elif order == 1:
        order = "age"
    elif order == 2:
        order = "species"
    elif order == 3:
        order = "created"
    else:
        order = "created"

    try:
        direction = request.args.get("order[0][dir]")
    except:
        direction = "desc"

    query = request.args.get("search[value]", "")[0:100]
    
    if current_user.is_admin:
        character_count = sqla.session.query(sqlm.Character).count()
        filtered_character_count = parse_search_string(
                query, sqlm.Character, sqla.session.query(sqlm.Character), ["name",]
            ).count()
    else:
        character_count = sqla.session.query(sqlm.Character).count()
        filtered_character_count = parse_search_string(
                query, sqlm.Character, sqla.session.query(sqlm.Character), ["name",]
            ).filter_by(hidden=False).count()

    if direction == "desc":
        if current_user.is_admin:
            characters = parse_search_string(
                    query, sqlm.Character, sqla.session.query(sqlm.Character), ["name",]
                ).order_by(sqla.desc(getattr(sqlm.Character, order)))[current:current+length]
        else:
            characters = parse_search_string(
                    query, sqlm.Character, sqla.session.query(sqlm.Character), ["name",]
                ).filter_by(hidden=False).order_by(sqla.desc(getattr(sqlm.Character, order)))[current:current+length]
    else:
        if current_user.is_admin:
            characters = parse_search_string(
                    query, sqlm.Character, sqla.session.query(sqlm.Character), ["name",]
                ).order_by(getattr(sqlm.Character, order))[current:current+length]
        else:
            characters = parse_search_string(
                    query, sqlm.Character, sqla.session.query(sqlm.Character), ["name",]
                ).filter_by(hidden=False).order_by(getattr(sqlm.Character, order))[current:current+length]
            
    table_data = []
    
    for i, character in enumerate(characters):
        if character.hidden:
            table_data.append(
                [
                    """<a href="/characters/%s">%s</a>   """ % (
                            character.slug,
                            character.name + " (HIDDEN)"
                        ),
                    character.author.display_name, 
                    get_preview(character.other, 50),
                    humanize_time(character.created),
                    "", ""
                ]
            )
        else:
            table_data.append(
                [
                    """<a href="/characters/%s">%s</a>   """ % (
                            character.slug,
                            character.name
                        ),
                    character.author.display_name, 
                    get_preview(character.other, 50),
                    humanize_time(character.created),
                    "", ""
                ]
            )
            
    data = {
        "draw": draw,
        "recordsTotal": character_count,
        "recordsFiltered": filtered_character_count,
        "data": table_data
    }
    return app.jsonify(data)
Example #11
0
def search_lookup():
    request_json = request.get_json(force=True)
    content_type = request_json.get("content_type", "posts")
    session["content_type"] = content_type
    query = request_json.get("q", "")[0:300]

    if len(query) < 3:
        return app.jsonify(
            error="Please enter at least 3 characters to search.")

    difference = (arrow.utcnow().datetime -
                  arrow.get(current_user.last_search_time).datetime).seconds
    if difference < 120 and not current_user.is_admin:
        return app.jsonify(
            error="Please wait %s seconds before searching again." %
            (120 - difference))

    try:
        session["query"] = query
    except:
        pass

    try:
        timezone = pytz.timezone(current_user.time_zone)
    except:
        timezone = pytz.timezone("US/Pacific")

    try:
        start_date = arrow.get(request_json.get("start_date", ""), [
            "M/D/YY",
        ])
        offset = timezone.utcoffset(start_date.naive).total_seconds()
        start_date = start_date.replace(seconds=-offset).datetime.replace(
            tzinfo=None)
        session["start_date"] = request_json.get("start_date", "")
    except:
        start_date = False
        session["start_date"] = ""

    try:  # created
        end_date = arrow.get(request_json.get("end_date", ""), [
            "M/D/YY",
        ])
        offset = timezone.utcoffset(end_date.naive).total_seconds()
        end_date = end_date.replace(seconds=-offset).replace(
            hours=24).datetime.replace(tzinfo=None)
        session["end_date"] = request_json.get("end_date", "")
    except:
        end_date = False
        session["end_date"] = ""

    try:  # category
        categories = list(
                sqla.session.query(sqlm.Category) \
                    .filter(sqlm.Category.id.in_(request_json.get("categories"))) \
                    .all()
            )
        session["categories"] = [{
            "id": c.id,
            "name": c.name
        } for c in categories]
    except:
        categories = []
        session["categories"] = []

    try:  # category
        blogs = list(
                sqla.session.query(sqlm.Blog) \
                    .filter(sqlm.Blog.id.in_(request_json.get("blogs"))) \
                    .all()
            )
        # session["categories"] = [{"id": c.id, "name": c.name} for c in categories]
    except:
        blogs = []
        # session["categories"] = []

    try:
        if content_type == "posts":
            topics = list(
                sqla.session.query(sqlm.Topic) \
                    .filter(sqlm.Topic.id.in_(request_json.get("topics"))) \
                    .all()
            )
        elif content_type == "messages":
            topics = list(
                sqla.session.query(sqlm.PrivateMessage) \
                    .filter(sqlm.PrivateMessage.id.in_(request_json.get("topics"))) \
                    .all()
            )
        session["topics"] = [{"id": t.id, "title": t.title} for t in topics]
    except:
        topics = []
        session["topics"] = []

    try:
        authors = list(
                sqla.session.query(sqlm.User) \
                    .filter(sqlm.User.id.in_(request_json.get("authors"))) \
                    .all()
            )
        session["search_authors"] = [{
            "id": a.id,
            "display_name": a.display_name
        } for a in authors]
    except:
        authors = []
        session["search_authors"] = []

    pagination = 20
    try:
        page = int(request_json.get("page", 1))
    except:
        page = 1

    if content_type == "posts":
        query_ = sqla.session.query(sqlm.Post)
        model_ = sqlm.Post
    elif content_type == "topics":
        query_ = sqla.session.query(sqlm.Topic)
        model_ = sqlm.Topic
    elif content_type == "status":
        query_ = sqla.session.query(sqlm.StatusUpdate)
        model_ = sqlm.StatusUpdate
    elif content_type == "messages":
        query_ = sqla.session.query(sqlm.PrivateMessageReply)
        model_ = sqlm.PrivateMessageReply
    elif content_type == "blogs":
        query_ = sqla.session.query(sqlm.BlogEntry)
        model_ = sqlm.BlogEntry

    if start_date:
        query_ = query_.filter(model_.created >= start_date)

    if end_date:
        query_ = query_.filter(model_.created <= end_date)

    if categories and content_type == "topics":
        query_ = query_.filter(
            model_.category_id.in_([c.id for c in categories]))

    if blogs and content_type == "blogs":
        query_ = query_.filter(model_.blog_id.in_([b.id for b in blogs]))

    if topics and content_type == "posts":
        query_ = query_.filter(model_.topic_id.in_([t.id for t in topics]))
    if topics and content_type == "messages":
        query_ = query_.filter(model_.pm_id.in_([t.id for t in topics]))

    if authors:
        query_ = query_.filter(model_.author_id.in_([a.id for a in authors]))

    parsed_results = []
    if content_type == "posts":
        if current_user.is_admin:
            query_ = search(query_, query) \
                .join(sqlm.Post.topic) \
                .filter(model_.hidden==False)
        else:
            _cat_perms = current_user.get_category_permission_subquery()

            query_ = search(query_, query) \
                .join(sqlm.Post.topic) \
                .join(_cat_perms, _cat_perms.c.category_id == sqlm.Topic.category_id) \
                .filter(_cat_perms.c.category_can_view_topics == True) \
                .filter(model_.hidden==False)

        results = query_.order_by(sqla.desc(model_.created)).paginate(
            page, pagination, False)
        has_next = len(
            query_.order_by(sqla.desc(model_.created)).paginate(
                pagination + 1, 1, False).items) > 0
        if has_next:
            count = 21
        elif len(results.items) == 0:
            count = 0
        else:
            count = 20
        for result in results.items:
            parsed_result = {}
            parsed_result["time"] = humanize_time(result.created)
            parsed_result["title"] = result.topic.title
            parsed_result["url"] = "/t/" + str(
                result.topic.slug) + "/page/1/post/" + str(result.id)
            parsed_result["description"] = result.html
            parsed_result["author_profile_link"] = result.author.my_url
            parsed_result["author_name"] = result.author.display_name
            parsed_result["readmore"] = True
            parsed_results.append(parsed_result)
    elif content_type == "topics":
        query_ = parse_search_string(query, model_, query_, ["title",]) \
            .filter(model_.hidden==False)

        if not current_user.is_admin:
            _cat_perms = current_user.get_category_permission_subquery()

            query_ = query_ \
                .join(_cat_perms, _cat_perms.c.category_id == sqlm.Topic.category_id) \
                .filter(_cat_perms.c.category_can_view_topics == True)

        count = query_.count()

        if current_user.is_admin:
            results = query_ \
                .join(sqlm.Topic.recent_post) \
                .order_by(sqla.desc(sqlm.Post.created)).paginate(page, pagination, False)
        else:
            results = query_ \
                .join(sqlm.Topic.recent_post) \
                .order_by(sqla.desc(sqlm.Post.created)).paginate(page, pagination, False)

        for result in results.items:
            parsed_result = {}
            parsed_result["time"] = humanize_time(result.created)
            parsed_result["title"] = result.title
            parsed_result["url"] = "/t/" + result.slug
            parsed_result["description"] = ""
            parsed_result["author_profile_link"] = result.author.my_url
            parsed_result["author_name"] = result.author.display_name
            parsed_result["readmore"] = False
            parsed_results.append(parsed_result)
    elif content_type == "blogs":
        query_ = parse_search_string(query, model_, query_, ["html", "title"])
        count = query_.count()

        results = query_ \
            .join(sqlm.BlogEntry.blog) \
            .filter(sqlm.Blog.disabled.isnot(True)) \
            .filter(sqlm.BlogEntry.draft.isnot(True)) \
            .filter(sqlm.BlogEntry.published.isnot(None)) \
            .filter(sqla.or_(
                sqlm.Blog.privacy_setting == "all",
                sqlm.Blog.privacy_setting == "members"
            )) \
            .order_by(sqla.desc(sqlm.BlogEntry.published))[(page-1)*pagination:pagination*page]

        for result in results:
            parsed_result = {}
            parsed_result["time"] = humanize_time(result.created)
            parsed_result["title"] = result.title
            parsed_result["url"] = "/blog/" + str(
                result.blog.slug) + "/e/" + str(result.slug)
            parsed_result["description"] = result.html
            parsed_result["author_profile_link"] = result.author.my_url
            parsed_result["author_name"] = result.author.display_name
            parsed_result["readmore"] = True
            parsed_results.append(parsed_result)

    elif content_type == "status":
        query_ = parse_search_string(query, model_, query_, [
            "message",
        ]).filter(model_.hidden == False)
        count = query_.count()

        results = query_ \
            .order_by(sqla.desc(sqlm.StatusUpdate.created))[(page-1)*pagination:pagination*page]

        for result in results:
            parsed_result = {}
            parsed_result["time"] = humanize_time(result.created)
            parsed_result["title"] = result.message
            parsed_result["description"] = ""
            parsed_result["url"] = "/status/" + str(result.id)
            parsed_result["author_profile_link"] = result.author.my_url
            parsed_result["author_name"] = result.author.display_name
            parsed_result["readmore"] = False
            parsed_results.append(parsed_result)

    elif content_type == "messages":
        query_ = query_.join(sqlm.PrivateMessageUser, sqlm.PrivateMessageUser.pm_id == sqlm.PrivateMessageReply.pm_id) \
            .filter(
                sqlm.PrivateMessageUser.author == current_user,
                sqlm.PrivateMessageUser.blocked == False,
                sqlm.PrivateMessageUser.exited == False
            ).order_by(sqlm.PrivateMessageReply.created.desc())
        query_ = parse_search_string(query, model_, query_,
                                     [sqlm.PrivateMessageReply.message])
        count = query_.count()
        results = query_[(page - 1) * pagination:pagination * page]

        for result in results:
            parsed_result = {}
            parsed_result["time"] = humanize_time(result.created)
            parsed_result["title"] = result.pm.title
            parsed_result["description"] = result.message
            parsed_result["url"] = "/messages/" + str(
                result.pm.id) + "/page/1/post/" + str(result.id)
            parsed_result["author_profile_link"] = result.author.my_url
            parsed_result["author_name"] = result.author.display_name
            parsed_result["readmore"] = True
            parsed_results.append(parsed_result)

    current_user.last_search_time = arrow.utcnow().datetime.replace(
        tzinfo=None)
    return app.jsonify(results=parsed_results,
                       count=count,
                       pagination=pagination)