Example #1
0
def paper_search():
    if request.method == 'POST':
        DBsession = sessionmaker(bind=db.engine)
        data = request.get_data()
        json_data = json.loads(data.decode('utf-8'))
        catlog = json_data.get('catlog')
        keyword = json_data.get('keyword')
        dbsession = DBsession()
        retList = []
        if catlog == 'note':
            full = dbsession.query(notes, user._account).join(
                user,
                user._id == notes._uid).filter(FullTextSearch(keyword, notes))
            for note in full:
                notep = note[0]
                if notep._parentid != None:
                    continue
                id = notep._id
                uid = notep._uid
                content = notep.notesContent
                _numOfnotes = notep._numOfnotes
                pid = notep._pid
                account = note[1]

                thumup = 0
                retList.append({
                    'id': id,
                    'uid': uid,
                    'note': content,
                    'account': account,
                    'thumup': thumup,
                    'numOfReply': _numOfnotes,
                    'pid': pid
                })
            ret_dict = {'state': 'success', "notes_json": retList}
            notes_json = json.dumps(ret_dict)
            print(notes_json)
            return notes_json
        if catlog == 'paper':
            full = dbsession.query(paper).filter(FullTextSearch(
                keyword, paper))
            for part in full:
                retList.append({
                    "id": part._id,
                    "title": part._title,
                    "abstract": part._abstract,
                    "content": part._abstract,
                    "author": part._author,
                    "catlog": part._catlog,
                    "numOfnotes": part._numOfnotes
                })

            ret_dict = {'state': 'success', "paper_json": retList}
            paper_json = json.dumps(ret_dict)
            print(paper_json)
            dbsession.close()
            return paper_json
        dbsession.close()
        return "failed"
def mysql_fulltext_query(mysql, count, search_terms, topics, unwanted_topics, user_topics, unwanted_user_topics, language,
                      upper_bounds,
                      lower_bounds):
    class FulltextContext(FullText):
        __fulltext_columns__ = ('article.content', 'article.title')

    query = mysql.query(Article)
    # if no user topics wanted or un_wanted we can do NATURAL LANGUAGE mode
    # otherwise do BOOLEAN MODE
    if not unwanted_user_topics and not user_topics:
        boolean_query = False
        if search_terms:
            search = search_terms
            query = mysql.query(Article).filter(FullTextSearch(search, FulltextContext, FullTextMode.NATURAL))
    else:  # build a boolean query instead
        boolean_query = True
        unwanted_user_topics = add_symbol_in_front_of_words('-', unwanted_user_topics)
        user_topics = add_symbol_in_front_of_words('', user_topics)
        search_terms = add_symbol_in_front_of_words('', search_terms)
        search = search_terms + " " + user_topics.strip() + " " + unwanted_user_topics.strip()
        query = mysql.query(Article).filter(FullTextSearch(search, FulltextContext, FullTextMode.BOOLEAN))

    # Language
    query = query.filter(Article.language_id == language.id)

    # Topics
    topic_IDs = split_numbers_in_string(topics)
    topic_conditions = []
    if topic_IDs:
        for ID in topic_IDs:
            topic_conditions.append(Article.Topic.id == ID)
        query = query.filter(or_(*topic_conditions))

    # Unwanted topics
    unwanted_topic_IDs = split_numbers_in_string(unwanted_topics)
    untopic_conditions = []

    if unwanted_topic_IDs:
        for ID in unwanted_topic_IDs:
            untopic_conditions.append(Article.Topic.id != ID)
        query = query.filter(or_(*untopic_conditions))

    # difficulty, upper and lower
    query = query.filter(lower_bounds < Article.fk_difficulty)
    query = query.filter(upper_bounds > Article.fk_difficulty)
    # if boolean search mode in fulltext then order by relevance score
    if boolean_query:
        query = query.order_by(desc(FullTextSearch(search, FulltextContext, FullTextMode.BOOLEAN)))

    return query.limit(count)
Example #3
0
    def search_related_entity_for_api(self, query, result_limit=10):
        try:
            print(
                "search for",
                query,
            )
            print("type chunk ", type(query))
            query = unicode(query)
            print(
                "search for",
                query,
            )
            print("type chunk ", type(query))

            max_limit = result_limit + 50
            # max_limit = result_limit
            statement = self.get_session().query(EntityForQA).filter(
                EntityForQA.source == "api",
                FullTextSearch(query, EntityForQA, FullTextMode.NATURAL))
            if result_limit == 0:
                entity_for_qa_list = statement.all()
            else:
                entity_for_qa_list = statement.limit(max_limit).all()
            return entity_for_qa_list
        except Exception, e:
            print(e)
            self.clean_session()
            if self.logger:
                self.logger.exception("exception occur in query=%s", query)
            return []
Example #4
0
 def test_fulltext_query(self):
     full = self.session.query(RecipeReviewModel).filter(
         FullTextSearch('spam', RecipeReviewModel))
     self.assertEqual(
         full.count(),
         2,
     )
     full = self.session.query(RecipeReviewModelForMigration).filter(
         FullTextSearch('spam', RecipeReviewModelForMigration))
     self.assertEqual(
         full.count(),
         2,
     )
     raw = self.session.execute(
         'SELECT * FROM {0} WHERE MATCH (commentor, review) AGAINST ("spam")'
         .format(RecipeReviewModel.__tablename__))
     self.assertEqual(full.count(), raw.rowcount, 'Query Test Failed')
 def search(self, text, limit):
     """
     Fulltext Search models.
     :param text:
     :param limit:
     :return:
     """
     return self.__model__.query.filter(FullTextSearch(text, self.__model__))
Example #6
0
 def test_fulltext_query_boolean_mode(self):
     full = self.session.query(RecipeReviewModel).filter(
         FullTextSearch('spa*', RecipeReviewModel, FullTextMode.BOOLEAN))
     self.assertEqual(
         full.count(),
         3,
     )
     full = self.session.query(RecipeReviewModelForMigration).filter(
         FullTextSearch('spa*', RecipeReviewModelForMigration,
                        FullTextMode.BOOLEAN))
     self.assertEqual(
         full.count(),
         3,
     )
     raw = self.session.execute(
         'SELECT * FROM {0} WHERE MATCH (commentor, review) AGAINST ("spa*" IN BOOLEAN MODE)'
         .format(RecipeReviewModel.__tablename__))
     self.assertEqual(full.count(), raw.rowcount, 'Query Test Failed')
Example #7
0
 def test_fulltext_qutoe_query(self):
     full = self.session.query(RecipeReviewModel).filter(
         FullTextSearch('"parrot can"', RecipeReviewModel,
                        FullTextMode.BOOLEAN))
     self.assertEqual(
         full.count(),
         2,
     )
     full = self.session.query(RecipeReviewModelForMigration).filter(
         FullTextSearch('"parrot can"', RecipeReviewModelForMigration,
                        FullTextMode.BOOLEAN))
     self.assertEqual(
         full.count(),
         2,
     )
     raw = self.session.execute(
         """SELECT * FROM {0} WHERE MATCH (commentor, review) AGAINST ('"parrot can"' IN BOOLEAN MODE)"""
         .format(RecipeReviewModel.__tablename__))
     self.assertEqual(full.count(), raw.rowcount)
Example #8
0
 def test_fulltext_query_natural_mode(self):
     full = self.session.query(RecipeReviewModel).filter(
         FullTextSearch('spam', RecipeReviewModel, FullTextMode.NATURAL))
     self.assertEqual(
         full.count(),
         3,
     )
     raw = self.session.execute(
         'SELECT * FROM {0} WHERE MATCH (commentor, review) AGAINST ("spam" IN NATURAL LANGUAGE MODE)'
         .format(RecipeReviewModel.__tablename__))
     self.assertEqual(full.count(), raw.rowcount, 'Query Test Failed')
Example #9
0
def lookup_text(db):
    q = request.query.q
    if not q:
        abort(400, 'q is a required parameter')
    entity = db.query(Expression).filter(FullTextSearch(
        q, Expression)).limit(1000).all()
    d = []
    for row in entity:
        d.append({'href': "%s/works/%s" % (app.config['api.base'], row.id)})

    response.content_type = 'application/json'
    return dumps(d)
Example #10
0
 def test_fulltext_query_query_expansion_mode(self):
     full = self.session.query(RecipeReviewModel).filter(
         FullTextSearch('spam', RecipeReviewModel,
                        FullTextMode.QUERY_EXPANSION))
     self.assertEqual(
         full.count(),
         3,
     )
     raw = self.session.execute(
         'SELECT * FROM {0} WHERE MATCH (commentor, review) AGAINST ("spam" WITH QUERY EXPANSION)'
         .format(RecipeReviewModel.__tablename__))
     self.assertEqual(full.count(), raw.rowcount, 'Query Test Failed')
Example #11
0
 def get_quote_suggestions(self, query, n=10):
     session = Session()
     query_ft = query
     # replace problematic characters for fulltext search
     for char in '()+-*~@<>"':
         query_ft = query.replace(char, ' ')
     quotes = (session.query(Quote).filter(
         FullTextSearch(
             query_ft + '*', Quote, FullTextMode.BOOLEAN)).filter(
                 Quote.quote.like('%' + query.strip() + '%')).order_by(
                     func.length(Quote.quote)).limit(n).all())
     Session.remove()
     return quotes
Example #12
0
 def get_person_suggestions(self, query, n=10):
     session = Session()
     query_ft = query
     # replace problematic characters for fulltext search
     for char in '()+-*~@<>"':
         query_ft = query_ft.replace(char, ' ')
     people = (session.query(Person).filter(
         FullTextSearch(
             query_ft + '*', Person, FullTextMode.BOOLEAN)).filter(
                 Person.name.like('%' + query.strip() + '%')).order_by(
                     func.length(Person.name)).limit(n).all())
     Session.remove()
     return people
Example #13
0
    def test_github_issue_9(self):
        # https://github.com/mengzhuo/sqlalchemy-fulltext-search/issues/9
        full = self.session.query(RecipeReviewModel).filter(
            RecipeReviewModel.id >= 1)
        full = full.filter(
            FullTextSearch('the -rainbow', RecipeReviewModel,
                           FullTextMode.BOOLEAN)).limit(20)
        self.assertEqual(full.count(), 0)
        raw = self.session.execute(
            'SELECT * FROM {0} WHERE MATCH (commentor, review) AGAINST ("the -rainbow" IN BOOLEAN MODE)'
            .format(RecipeReviewModel.__tablename__))
        self.assertEqual(full.count(), raw.rowcount, 'Query Test Failed')

        full = self.session.query(RecipeReviewModelForMigration).filter(
            RecipeReviewModelForMigration.id >= 1)
        full = full.filter(
            FullTextSearch('the -rainbow', RecipeReviewModelForMigration,
                           FullTextMode.BOOLEAN)).limit(20)
        self.assertEqual(full.count(), 0)
        raw = self.session.execute(
            'SELECT * FROM {0} WHERE MATCH (commentor, review) AGAINST ("the -rainbow" IN BOOLEAN MODE)'
            .format(RecipeReviewModelForMigration.__tablename__))
        self.assertEqual(full.count(), raw.rowcount, 'Query Test Failed')
Example #14
0
 def search(self, query, result_limit=0):
     try:
         statement = self.get_session().query(WikipediaEntityName).filter(
             FullTextSearch(query, WikipediaEntityName,
                            FullTextMode.NATURAL))
         if result_limit == 0:
             result = statement.limit(300).all()
         else:
             result = statement.limit(result_limit).all()
         return result
     except Exception, e:
         print(e)
         self.clean_session()
         if self.logger:
             self.logger.exception("exception occur in query=%s", query)
         return []
Example #15
0
    def full_text_search_in_nature_language(
            self,
            query,
            model_class,
            limit=ALL_RESULT,
            result_format=RESULT_FORMAT_ALL_INFO):
        if result_format == DBSearcher.RESULT_FORMAT_ALL_INFO:
            session_query = self.get_session().query(model_class)
        else:
            session_query = self.get_session().query(model_class.id)

        session_query = session_query.filter(
            FullTextSearch(query, model_class, FullTextMode.NATURAL))
        if limit == DBSearcher.ALL_RESULT:
            limit = DBSearcher.MAX_RESULT_NUM
        return session_query.limit(limit).all()
Example #16
0
def scholarly_search_name():
    """
        Run this to autocomplete.
        Params are author_name and refresh
    """

    a_name = request.args.get('author')
    refresh = request.args.get('refresh')
    tsess = Session()
    author = tsess.query(TempAuthor).filter(FullTextSearch(a_name,
                                                           TempAuthor)).all()
    print([a.name, a.scholar_id] for a in list(author))

    if not refresh and author:
        return jsonify({
            'from':
            'db',
            'results': [{
                'name': a.name,
                'affiliation': a.organization,
                'scholar_id': a.scholar_id,
            } for a in list(author)]
        })  # [vars(a) for a in list(author)]})

    author = a_name
    if author:
        authors = []
        search_query = scholarly.search_author(author)
        try:
            authors = list(search_query)
            authors = [{
                "name": auth.name,
                "affiliation": auth.affiliation,
                "scholar_id": auth.id
            } for auth in authors]

            # Start running the analysis for the authors

            subprocess.Popen(["python3", "fetch_profile.py", "author"] +
                             author.split(" "))
        except StopIteration as e:
            return jsonify(**{'error': 'Scholarly did not find author'})
        return jsonify(**{"results": authors})
    else:
        return jsonify(**{"results": []})
Example #17
0
 def search_sentence_answer(self, query, result_limit=10):
     try:
         max_limit = result_limit + 50
         statement = self.get_session().query(
             DocumentSentenceText.doc_id, DocumentSentenceText.text).filter(
                 FullTextSearch(query, DocumentSentenceText,
                                FullTextMode.NATURAL))
         print(statement)
         if result_limit == 0:
             sentence_list = statement.all()
         else:
             sentence_list = statement.limit(max_limit).all()
         return sentence_list[:result_limit]
     except Exception, e:
         print(e)
         self.clean_session()
         if self.logger:
             self.logger.exception("exception occur in query=%s", query)
         return []
Example #18
0
    def search_post(self, query, result_limit=10):
        try:
            max_limit = result_limit + 50
            statement = self.get_session().query(PostsRecord).filter(
                FullTextSearch(query, PostsRecord, FullTextMode.NATURAL))

            if result_limit == 0:
                post_list = statement.all()
            else:
                post_list = statement.limit(max_limit).all()

            post_list.sort(key=lambda x: x.score, reverse=True)

            return post_list[:result_limit]
        except Exception:
            self.clean_session()
            if self.logger:
                self.logger.exception("exception occur in query=%s", query)
            return []
Example #19
0
    def filter_query(self, query, overview=False):
        query = query.filter(
            Document.analysis_nature_id == self.nature_id,
            Document.country == self.country,
        )

        if not overview and self.medium:
            query = query.filter(Document.medium == self.medium)

        query = query.filter(Document.published_at >= self.published_from,
                             Document.published_at <= self.published_to)

        if self.source_person_id.data:
            query = query\
                .join(DocumentSource)\
                .filter(DocumentSource.person_id == self.source_person_id.data)

        if self.q.data:
            # full text search
            query = query.filter(
                FullTextSearch(self.q.data, Document, FullTextMode.NATURAL))

        return query
Example #20
0
def search(query,
           orderby='creation',
           filter_user=None,
           search_title=True,
           search_text=True,
           subreddit=None):
    """
    search for threads (and maybe comments in the future)
    """
    if not query:
        return []
    query = query.strip()

    base_qs = Thread.query.join(Publication).filter(
        FullTextSearch(query, Publication, FullTextMode.NATURAL))

    if orderby == 'creation':
        base_qs = base_qs.order_by(db.desc(Thread.created_on))
    elif orderby == 'title':
        base_qs = base_qs.order_by(Thread.title)
    elif orderby == 'numb_comments':
        pass

    return base_qs
Example #21
0
 def test_fulltext_cjk_query(self):
     cjk = self.session.query(RecipeReviewModel).filter(
         FullTextSearch('中国人'.decode('utf8'), RecipeReviewModel))
     self.assertEqual(cjk.count(), 2)
Example #22
0
    def filter_query(self, query):
        query = query.filter(
            Document.analysis_nature_id == self.analysis_nature_id.data)

        if self.cluster_id.data:
            query = query.join(ClusteredDocument)\
                         .filter(ClusteredDocument.cluster_id == self.cluster_id.data)

        if self.medium_id.data:
            query = query.filter(Document.medium_id.in_(self.medium_id.data))

        if self.user_id.data:
            if self.user_id.data == '-':
                query = query.filter(
                    or_(
                        Document.created_by_user_id == None,  # noqa
                        Document.checked_by_user_id == None))
            else:
                query = query.filter(
                    or_(Document.created_by_user_id == self.user_id.data,
                        Document.checked_by_user_id == self.user_id.data))

        if self.country_id.data:
            query = query.filter(Document.country_id.in_(self.country_id.data))

        if self.created_from:
            query = query.filter(Document.created_at >= self.created_from)

        if self.created_to:
            query = query.filter(Document.created_at <= self.created_to)

        if self.published_from:
            query = query.filter(Document.published_at >= self.published_from)

        if self.published_to:
            query = query.filter(Document.published_at <= self.published_to)

        if self.source_person_id.data:
            query = query\
                .join(DocumentSource)\
                .filter(DocumentSource.person_id == self.source_person_id.data)

        if self.problems.data:
            for code in self.problems.data:
                query = DocumentAnalysisProblem.lookup(code).filter_query(
                    query)

        if self.flagged.data:
            query = query.filter(Document.flagged == True)  # noqa

        if self.has_url.data == '1':
            query = query.filter(Document.url != None,
                                 Document.url != '')  # noqa
        elif self.has_url.data == '0':
            query = query.filter(or_(Document.url == None,
                                     Document.url == ''))  # noqa

        if self.q.data:
            # full text search
            query = query.filter(
                FullTextSearch(self.q.data, Document, FullTextMode.NATURAL))

        if self.tags.data:
            tags = set(f for f in re.split('\s*,\s*', self.tags.data) if f)
            for tag in tags:
                query = query.filter(Document.tags.contains(tag))

        return query
Example #23
0
 def test_fulltext_form_query(self):
     FullTextSearch('spam', RecipeReviewModel)
     FullTextSearch('spam', RecipeReviewModelForMigration)
Example #24
0
def search_db(term='',
              user=None,
              sort='id',
              order='desc',
              category='0_0',
              quality_filter='0',
              page=1,
              rss=False,
              admin=False,
              logged_in_user=None,
              per_page=75):
    if page > 4294967295:
        flask.abort(404)

    sort_keys = {
        'id': models.Torrent.id,
        'size': models.Torrent.filesize,
        # Disable this because we disabled this in search_elastic, for the sake of consistency:
        # 'name': models.Torrent.display_name,
        'comments': models.Torrent.comment_count,
        'seeders': models.Statistic.seed_count,
        'leechers': models.Statistic.leech_count,
        'downloads': models.Statistic.download_count
    }

    sort_column = sort_keys.get(sort.lower())
    if sort_column is None:
        flask.abort(400)

    order_keys = {'desc': 'desc', 'asc': 'asc'}

    order_ = order.lower()
    if order_ not in order_keys:
        flask.abort(400)

    filter_keys = {
        '0': None,
        '1': (models.TorrentFlags.REMAKE, False),
        '2': (models.TorrentFlags.TRUSTED, True),
        '3': (models.TorrentFlags.COMPLETE, True)
    }

    sentinel = object()
    filter_tuple = filter_keys.get(quality_filter.lower(), sentinel)
    if filter_tuple is sentinel:
        flask.abort(400)

    if user:
        user = models.User.by_id(user)
        if not user:
            flask.abort(404)
        user = user.id

    main_category = None
    sub_category = None
    main_cat_id = 0
    sub_cat_id = 0
    if category:
        cat_match = re.match(r'^(\d+)_(\d+)$', category)
        if not cat_match:
            flask.abort(400)

        main_cat_id = int(cat_match.group(1))
        sub_cat_id = int(cat_match.group(2))

        if main_cat_id > 0:
            if sub_cat_id > 0:
                sub_category = models.SubCategory.by_category_ids(
                    main_cat_id, sub_cat_id)
            else:
                main_category = models.MainCategory.by_id(main_cat_id)

            if not category:
                flask.abort(400)

    # Force sort by id desc if rss
    if rss:
        sort_column = sort_keys['id']
        order = 'desc'

    same_user = False
    if logged_in_user:
        same_user = logged_in_user.id == user

    model_class = models.TorrentNameSearch if term else models.Torrent

    query = db.session.query(model_class)

    # This is... eh. Optimize the COUNT() query since MySQL is bad at that.
    # See http://docs.sqlalchemy.org/en/rel_1_1/orm/query.html#sqlalchemy.orm.query.Query.count
    # Wrap the queries into the helper class to deduplicate code and apply filters to both in one go
    count_query = db.session.query(sqlalchemy.func.count(model_class.id))
    qpc = QueryPairCaller(query, count_query)

    # User view (/user/username)
    if user:
        qpc.filter(models.Torrent.uploader_id == user)

        if not admin:
            # Hide all DELETED torrents if regular user
            qpc.filter(
                models.Torrent.flags.op('&')(int(
                    models.TorrentFlags.DELETED)).is_(False))
            # If logged in user is not the same as the user being viewed,
            # show only torrents that aren't hidden or anonymous
            #
            # If logged in user is the same as the user being viewed,
            # show all torrents including hidden and anonymous ones
            #
            # On RSS pages in user view,
            # show only torrents that aren't hidden or anonymous no matter what
            if not same_user or rss:
                qpc.filter(
                    models.Torrent.flags.op('&')(
                        int(models.TorrentFlags.HIDDEN
                            | models.TorrentFlags.ANONYMOUS)).is_(False))
    # General view (homepage, general search view)
    else:
        if not admin:
            # Hide all DELETED torrents if regular user
            qpc.filter(
                models.Torrent.flags.op('&')(int(
                    models.TorrentFlags.DELETED)).is_(False))
            # If logged in, show all torrents that aren't hidden unless they belong to you
            # On RSS pages, show all public torrents and nothing more.
            if logged_in_user and not rss:
                qpc.filter((models.Torrent.flags.op('&')
                            (int(models.TorrentFlags.HIDDEN)).is_(False))
                           | (models.Torrent.uploader_id == logged_in_user.id))
            # Otherwise, show all torrents that aren't hidden
            else:
                qpc.filter(
                    models.Torrent.flags.op('&')(int(
                        models.TorrentFlags.HIDDEN)).is_(False))

    if main_category:
        qpc.filter(models.Torrent.main_category_id == main_cat_id)
    elif sub_category:
        qpc.filter((models.Torrent.main_category_id == main_cat_id)
                   & (models.Torrent.sub_category_id == sub_cat_id))

    if filter_tuple:
        qpc.filter(
            models.Torrent.flags.op('&')(int(filter_tuple[0])).is_(
                filter_tuple[1]))

    if term:
        for item in shlex.split(term, posix=False):
            if len(item) >= 2:
                qpc.filter(
                    FullTextSearch(item, models.TorrentNameSearch,
                                   FullTextMode.NATURAL))

    query, count_query = qpc.items
    # Sort and order
    if sort_column.class_ != models.Torrent:
        index_name = _get_index_name(sort_column)
        query = query.join(sort_column.class_)
        query = query.with_hint(sort_column.class_,
                                'USE INDEX ({0})'.format(index_name))

    query = query.order_by(getattr(sort_column, order)())

    if rss:
        query = query.limit(per_page)
    else:
        query = query.paginate_faste(page,
                                     per_page=per_page,
                                     step=5,
                                     count_query=count_query)

    return query
Example #25
0
 def test_fulltext_cjk_query(self):
     _ = self.session.query(RecipeReviewModel).filter(
         FullTextSearch('中国人'.decode('utf8'), RecipeReviewModel))
     _ = self.session.query(RecipeReviewModelForMigration).filter(
         FullTextSearch('中国人'.decode('utf8'),
                        RecipeReviewModelForMigration))
 def searched_paginate(self, page, per_page, text):
     paginated = self.__model__.query.filter(FullTextSearch(text, self.__model__, FulltextMode.BOOLEAN)).paginate(page, per_page, False)
     return paginated.items, paginated.has_prev, paginated.has_next
Example #27
0
 def _build_fulltext_search(self,
                            model_cls,
                            query,
                            q,
                            mode=FullTextMode.BOOLEAN):
     return query.filter(FullTextSearch(q, model_cls, mode=mode))
Example #28
0
def search_db(term='',
              user=None,
              sort='id',
              order='desc',
              category='0_0',
              quality_filter='0',
              page=1,
              rss=False,
              admin=False,
              logged_in_user=None,
              per_page=75):
    sort_keys = {
        'id': models.Torrent.id,
        'size': models.Torrent.filesize,
        # 'name': models.Torrent.display_name, # Disable this because we disabled this in search_elastic, for the sake of consistency
        'seeders': models.Statistic.seed_count,
        'leechers': models.Statistic.leech_count,
        'downloads': models.Statistic.download_count
    }

    sort_ = sort.lower()
    if sort_ not in sort_keys:
        flask.abort(400)
    sort = sort_keys[sort]

    order_keys = {'desc': 'desc', 'asc': 'asc'}

    order_ = order.lower()
    if order_ not in order_keys:
        flask.abort(400)

    filter_keys = {
        '0': None,
        '1': (models.TorrentFlags.REMAKE, False),
        '2': (models.TorrentFlags.TRUSTED, True),
        '3': (models.TorrentFlags.COMPLETE, True)
    }

    sentinel = object()
    filter_tuple = filter_keys.get(quality_filter.lower(), sentinel)
    if filter_tuple is sentinel:
        flask.abort(400)

    if user:
        user = models.User.by_id(user)
        if not user:
            flask.abort(404)
        user = user.id

    main_category = None
    sub_category = None
    main_cat_id = 0
    sub_cat_id = 0
    if category:
        cat_match = re.match(r'^(\d+)_(\d+)$', category)
        if not cat_match:
            flask.abort(400)

        main_cat_id = int(cat_match.group(1))
        sub_cat_id = int(cat_match.group(2))

        if main_cat_id > 0:
            if sub_cat_id > 0:
                sub_category = models.SubCategory.by_category_ids(
                    main_cat_id, sub_cat_id)
            else:
                main_category = models.MainCategory.by_id(main_cat_id)

            if not category:
                flask.abort(400)

    # Force sort by id desc if rss
    if rss:
        sort = sort_keys['id']
        order = 'desc'

    same_user = False
    if logged_in_user:
        same_user = logged_in_user.id == user

    if term:
        query = db.session.query(models.TorrentNameSearch)
    else:
        query = models.Torrent.query

    # User view (/user/username)
    if user:
        query = query.filter(models.Torrent.uploader_id == user)

        if not admin:
            # Hide all DELETED torrents if regular user
            query = query.filter(
                models.Torrent.flags.op('&')(int(
                    models.TorrentFlags.DELETED)).is_(False))
            # If logged in user is not the same as the user being viewed, show only torrents that aren't hidden or anonymous
            # If logged in user is the same as the user being viewed, show all torrents including hidden and anonymous ones
            # On RSS pages in user view, show only torrents that aren't hidden or anonymous no matter what
            if not same_user or rss:
                query = query.filter(
                    models.Torrent.flags.op('&')(
                        int(models.TorrentFlags.HIDDEN
                            | models.TorrentFlags.ANONYMOUS)).is_(False))
    # General view (homepage, general search view)
    else:
        if not admin:
            # Hide all DELETED torrents if regular user
            query = query.filter(
                models.Torrent.flags.op('&')(int(
                    models.TorrentFlags.DELETED)).is_(False))
            # If logged in, show all torrents that aren't hidden unless they belong to you
            # On RSS pages, show all public torrents and nothing more.
            if logged_in_user and not rss:
                query = query.filter(
                    (models.Torrent.flags.op('&')
                     (int(models.TorrentFlags.HIDDEN)).is_(False))
                    | (models.Torrent.uploader_id == logged_in_user.id))
            # Otherwise, show all torrents that aren't hidden
            else:
                query = query.filter(
                    models.Torrent.flags.op('&')(int(
                        models.TorrentFlags.HIDDEN)).is_(False))

    if main_category:
        query = query.filter(models.Torrent.main_category_id == main_cat_id)
    elif sub_category:
        query = query.filter((models.Torrent.main_category_id == main_cat_id)
                             & (models.Torrent.sub_category_id == sub_cat_id))

    if filter_tuple:
        query = query.filter(
            models.Torrent.flags.op('&')(int(filter_tuple[0])).is_(
                filter_tuple[1]))

    if term:
        for item in shlex.split(term, posix=False):
            if len(item) >= 2:
                query = query.filter(
                    FullTextSearch(item, models.TorrentNameSearch,
                                   FullTextMode.NATURAL))

    # Sort and order
    if sort.class_ != models.Torrent:
        query = query.join(sort.class_)

    query = query.order_by(getattr(sort, order)())

    if rss:
        query = query.limit(per_page)
    else:
        query = query.paginate_faste(page, per_page=per_page, step=5)

    return query
Example #29
0
def search(term='',
           user=None,
           sort='id',
           order='desc',
           category='0_0',
           quality_filter='0',
           page=1,
           rss=False,
           admin=False):
    sort_keys = {
        'id': models.Torrent.id,
        'size': models.Torrent.filesize,
        'name': models.Torrent.display_name,
        'seeders': models.Statistic.seed_count,
        'leechers': models.Statistic.leech_count,
        'downloads': models.Statistic.download_count
    }

    sort_ = sort.lower()
    if sort_ not in sort_keys:
        flask.abort(400)
    sort = sort_keys[sort]

    order_keys = {'desc': 'desc', 'asc': 'asc'}

    order_ = order.lower()
    if order_ not in order_keys:
        flask.abort(400)

    filter_keys = {
        '0': None,
        '1': (models.TorrentFlags.REMAKE, False),
        '2': (models.TorrentFlags.TRUSTED, True),
        '3': (models.TorrentFlags.COMPLETE, True)
    }

    sentinel = object()
    filter_tuple = filter_keys.get(quality_filter.lower(), sentinel)
    if filter_tuple is sentinel:
        flask.abort(400)

    if user:
        user = models.User.by_id(user)
        if not user:
            flask.abort(404)
        user = user.id

    main_category = None
    sub_category = None
    main_cat_id = 0
    sub_cat_id = 0
    if category:
        cat_match = re.match(r'^(\d+)_(\d+)$', category)
        if not cat_match:
            flask.abort(400)

        main_cat_id = int(cat_match.group(1))
        sub_cat_id = int(cat_match.group(2))

        if main_cat_id > 0:
            if sub_cat_id > 0:
                sub_category = models.SubCategory.by_category_ids(
                    main_cat_id, sub_cat_id)
            else:
                main_category = models.MainCategory.by_id(main_cat_id)

            if not category:
                flask.abort(400)

    # Force sort by id desc if rss
    if rss:
        sort = sort_keys['id']
        order = 'desc'
        page = 1

    same_user = False
    if flask.g.user:
        same_user = flask.g.user.id == user

    if term:
        query = db.session.query(models.TorrentNameSearch)
    else:
        query = models.Torrent.query

    # Filter by user
    if user:
        query = query.filter(models.Torrent.uploader_id == user)
        # If admin, show everything
        if not admin:
            # If user is not logged in or the accessed feed doesn't belong to user,
            # hide anonymous torrents belonging to the queried user
            if not same_user:
                query = query.filter(
                    models.Torrent.flags.op('&')(
                        int(models.TorrentFlags.ANONYMOUS
                            | models.TorrentFlags.DELETED)).is_(False))

    if main_category:
        query = query.filter(models.Torrent.main_category_id == main_cat_id)
    elif sub_category:
        query = query.filter((models.Torrent.main_category_id == main_cat_id)
                             & (models.Torrent.sub_category_id == sub_cat_id))

    if filter_tuple:
        query = query.filter(
            models.Torrent.flags.op('&')(int(filter_tuple[0])).is_(
                filter_tuple[1]))

    # If admin, show everything
    if not admin:
        query = query.filter(
            models.Torrent.flags.op('&')(
                int(models.TorrentFlags.HIDDEN
                    | models.TorrentFlags.DELETED)).is_(False))

    if term:
        for item in shlex.split(term, posix=False):
            if len(item) >= 2:
                query = query.filter(
                    FullTextSearch(item, models.TorrentNameSearch,
                                   FullTextMode.NATURAL))

    # Sort and order
    if sort.class_ != models.Torrent:
        query = query.join(sort.class_)

    query = query.order_by(getattr(sort, order)())

    if rss:
        query = query.limit(app.config['RESULTS_PER_PAGE'])
    else:
        query = query.paginate_faste(page,
                                     per_page=app.config['RESULTS_PER_PAGE'],
                                     step=5)

    return query