<commit_before>#! /usr/bin/env python
#-*- coding: utf-8 -*-

# pyAggr3g470r - A Web based news aggregator.
# Copyright (C) 2010-2012  <NAME> - http://cedricbonhomme.org/
#
# For more information : http://bitbucket.org/cedricbonhomme/pyaggr3g470r/
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>

__author__ = "<NAME>"
__version__ = "$Revision: 3.6 $"
__date__ = "$Date: 2010/01/29 $"
__revision__ = "$Date: 2012/11/26 $"
__copyright__ = "Copyright (c) <NAME>"
__license__ = "GPLv3"

#
# This file contains the "Root" class which describes
# all pages of pyAggr3g470r. These pages are:
# - main page;
# - management;
# - history;
# - favorites;
# - notifications;
# - unread;
# - feed summary.
#

import os
import re
import calendar

import cherrypy
from mako.template import Template
from mako.lookup import TemplateLookup
lookup = TemplateLookup(directories=['templates'])

from collections import Counter
import datetime

import conf
import utils
import export
import mongodb
import feedgetter
from auth import AuthController, require, member_of, name_is
#from qrcode.pyqrnative.PyQRNative import QRCode, QRErrorCorrectLevel, CodeOverflowException
#from qrcode import qr


def error_404(status, message, traceback, version):
    """
    Display an error if the page does not exist.
    """
    html = htmlheader()
    html += htmlnav
    html += "<br /><br />Error %s - This page does not exist." % status
    html += "\n<hr />\n" + htmlfooter
    return html

def handle_error():
    """
    Handle different type of errors.
    """
    html = htmlheader()
    html += htmlnav
    html += "<br /><br />Sorry, an error occured"
    html += "\n<hr />\n" + htmlfooter
    cherrypy.response.status = 500
    cherrypy.response.body = [html]

def htmlheader(text=""):
    """
    Return the header of the HTML page with the number of unread articles
    in the 'title' HTML tag..
    """
    return '<!DOCTYPE html>\n' + \
        '<head>' + \
        '\n\t<title>'+ text +' - pyAggr3g470r - News aggregator</title>\n' + \
        '\t<link rel="stylesheet" type="text/css" href="/css/style.css" />' + \
        '\n\t<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>\n' + \
        '\n\t<script type="text/javascript" src="https://apis.google.com/js/plusone.js"></script>\n' + \
        '</head>\n'

htmlfooter = '<p>This software is under GPLv3 license. You are welcome to copy, modify or' + \
            ' redistribute the source code according to the' + \
            ' <a href="http://www.gnu.org/licenses/gpl-3.0.txt">GPLv3</a> license.</p></div>\n' + \
            '</body>\n</html>'

htmlnav = '<body>\n<h1><div class="right innerlogo"><a href="/"><img src="/img/tuxrss.png"' + \
        """ title="What's new today?"/></a>""" + \
        '</div><a name="top"><a href="/">pyAggr3g470r - News aggregator</a></a></h1>\n'

class RestrictedArea(object):
    """
    All methods in this controller (and subcontrollers) is
    open only to members of the admin group
    """
    _cp_config = {
        'auth.require': [member_of('admin')]
    }

    @cherrypy.expose
    def index(self):
        return """This is the admin only area."""

class pyAggr3g470r(object):
    """
    Main class.
    All pages of pyAggr3g470r are described in this class.
    """
    _cp_config = {'request.error_response': handle_error, \
                    'tools.sessions.on': True, \
                    'tools.auth.on': True}

    def __init__(self):
        """
        """
        self.auth = AuthController()
        restricted = RestrictedArea()

        self.mongo = mongodb.Articles(conf.MONGODB_ADDRESS, conf.MONGODB_PORT, \
                        conf.MONGODB_DBNAME, conf.MONGODB_USER, conf.MONGODB_PASSWORD)
    @require()
    def index(self):
        """
        Main page containing the list of feeds and articles.
        """
        feeds = self.mongo.get_all_feeds()
        nb_unread_articles = self.mongo.nb_unread_articles()
        nb_favorites = self.mongo.nb_favorites()
        nb_mail_notifications = self.mongo.nb_mail_notifications()
        tmpl = lookup.get_template("index.html")
        return tmpl.render(feeds=feeds, nb_feeds=len(feeds), mongo=self.mongo, \
                            nb_favorites=nb_favorites, nb_unread_articles=nb_unread_articles, \
                            nb_mail_notifications=nb_mail_notifications, header_text=nb_unread_articles)

    index.exposed = True

    @require()
    def management(self):
        """
        Management page.
        Allows adding and deleting feeds. Export functions of the MongoDB data base
        and display some statistics.
        """
        feeds = self.mongo.get_all_feeds()
        nb_mail_notifications = self.mongo.nb_mail_notifications()
        nb_favorites = self.mongo.nb_favorites()
        nb_articles = self.mongo.nb_articles()
        nb_unread_articles = self.mongo.nb_unread_articles()
        tmpl = lookup.get_template("management.html")
        return tmpl.render(feeds=feeds, nb_mail_notifications=nb_mail_notifications, \
                            nb_favorites=nb_favorites, nb_articles=nb_articles, \
                            nb_unread_articles=nb_unread_articles)

    management.exposed = True

    @require()
    def statistics(self, word_size=6):
        """
        More advanced statistics.
        """
        articles = self.mongo.get_articless()
        top_words = utils.top_words(articles, n=50, size=int(word_size))
        tag_cloud = utils.tag_cloud(top_words)
        tmpl = lookup.get_template("statistics.html")
        return tmpl.render(articles=articles, word_size=word_size, tag_cloud=tag_cloud)

    statistics.exposed = True

    @require()
    def search(self, query=None):
        """
        Simply search for the string 'query'
        in the description of the article.
        """
        param, _, value = query.partition(':')
        wordre = re.compile(r'\b%s\b' % param, re.I)
        feed_id = None
        if param == "Feed":
            feed_id, _, query = value.partition(':')
        html = htmlheader()
        html += htmlnav
        html += """<div class="left inner">"""
        html += """<h1>Articles containing the string <i>%s</i></h1><br />""" % (query,)

        if feed_id is not None:
            for article in self.mongo.get_articles(feed_id):
                article_content = utils.clear_string(article.article_description)
                if not article_content:
                    utils.clear_string(article.article_title)
                if wordre.findall(article_content) != []:<commit_msg>Fixed typo name of a function).<commit_after>#! /usr/bin/env python
#-*- coding: utf-8 -*-

# pyAggr3g470r - A Web based news aggregator.
# Copyright (C) 2010-2012  <NAME> - http://cedricbonhomme.org/
#
# For more information : http://bitbucket.org/cedricbonhomme/pyaggr3g470r/
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>

__author__ = "<NAME>"
__version__ = "$Revision: 3.6 $"
__date__ = "$Date: 2010/01/29 $"
__revision__ = "$Date: 2012/11/26 $"
__copyright__ = "Copyright (c) <NAME>"
__license__ = "GPLv3"

#
# This file contains the "Root" class which describes
# all pages of pyAggr3g470r. These pages are:
# - main page;
# - management;
# - history;
# - favorites;
# - notifications;
# - unread;
# - feed summary.
#

import os
import re
import calendar

import cherrypy
from mako.template import Template
from mako.lookup import TemplateLookup
lookup = TemplateLookup(directories=['templates'])

from collections import Counter
import datetime

import conf
import utils
import export
import mongodb
import feedgetter
from auth import AuthController, require, member_of, name_is
#from qrcode.pyqrnative.PyQRNative import QRCode, QRErrorCorrectLevel, CodeOverflowException
#from qrcode import qr


def error_404(status, message, traceback, version):
    """
    Display an error if the page does not exist.
    """
    html = htmlheader()
    html += htmlnav
    html += "<br /><br />Error %s - This page does not exist." % status
    html += "\n<hr />\n" + htmlfooter
    return html

def handle_error():
    """
    Handle different type of errors.
    """
    html = htmlheader()
    html += htmlnav
    html += "<br /><br />Sorry, an error occured"
    html += "\n<hr />\n" + htmlfooter
    cherrypy.response.status = 500
    cherrypy.response.body = [html]

def htmlheader(text=""):
    """
    Return the header of the HTML page with the number of unread articles
    in the 'title' HTML tag..
    """
    return '<!DOCTYPE html>\n' + \
        '<head>' + \
        '\n\t<title>'+ text +' - pyAggr3g470r - News aggregator</title>\n' + \
        '\t<link rel="stylesheet" type="text/css" href="/css/style.css" />' + \
        '\n\t<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>\n' + \
        '\n\t<script type="text/javascript" src="https://apis.google.com/js/plusone.js"></script>\n' + \
        '</head>\n'

htmlfooter = '<p>This software is under GPLv3 license. You are welcome to copy, modify or' + \
            ' redistribute the source code according to the' + \
            ' <a href="http://www.gnu.org/licenses/gpl-3.0.txt">GPLv3</a> license.</p></div>\n' + \
            '</body>\n</html>'

htmlnav = '<body>\n<h1><div class="right innerlogo"><a href="/"><img src="/img/tuxrss.png"' + \
        """ title="What's new today?"/></a>""" + \
        '</div><a name="top"><a href="/">pyAggr3g470r - News aggregator</a></a></h1>\n'

class RestrictedArea(object):
    """
    All methods in this controller (and subcontrollers) is
    open only to members of the admin group
    """
    _cp_config = {
        'auth.require': [member_of('admin')]
    }

    @cherrypy.expose
    def index(self):
        return """This is the admin only area."""

class pyAggr3g470r(object):
    """
    Main class.
    All pages of pyAggr3g470r are described in this class.
    """
    _cp_config = {'request.error_response': handle_error, \
                    'tools.sessions.on': True, \
                    'tools.auth.on': True}

    def __init__(self):
        """
        """
        self.auth = AuthController()
        restricted = RestrictedArea()

        self.mongo = mongodb.Articles(conf.MONGODB_ADDRESS, conf.MONGODB_PORT, \
                        conf.MONGODB_DBNAME, conf.MONGODB_USER, conf.MONGODB_PASSWORD)
    @require()
    def index(self):
        """
        Main page containing the list of feeds and articles.
        """
        feeds = self.mongo.get_all_feeds()
        nb_unread_articles = self.mongo.nb_unread_articles()
        nb_favorites = self.mongo.nb_favorites()
        nb_mail_notifications = self.mongo.nb_mail_notifications()
        tmpl = lookup.get_template("index.html")
        return tmpl.render(feeds=feeds, nb_feeds=len(feeds), mongo=self.mongo, \
                            nb_favorites=nb_favorites, nb_unread_articles=nb_unread_articles, \
                            nb_mail_notifications=nb_mail_notifications, header_text=nb_unread_articles)

    index.exposed = True

    @require()
    def management(self):
        """
        Management page.
        Allows adding and deleting feeds. Export functions of the MongoDB data base
        and display some statistics.
        """
        feeds = self.mongo.get_all_feeds()
        nb_mail_notifications = self.mongo.nb_mail_notifications()
        nb_favorites = self.mongo.nb_favorites()
        nb_articles = self.mongo.nb_articles()
        nb_unread_articles = self.mongo.nb_unread_articles()
        tmpl = lookup.get_template("management.html")
        return tmpl.render(feeds=feeds, nb_mail_notifications=nb_mail_notifications, \
                            nb_favorites=nb_favorites, nb_articles=nb_articles, \
                            nb_unread_articles=nb_unread_articles)

    management.exposed = True

    @require()
    def statistics(self, word_size=6):
        """
        More advanced statistics.
        """
        articles = self.mongo.get_articles()
        top_words = utils.top_words(articles, n=50, size=int(word_size))
        tag_cloud = utils.tag_cloud(top_words)
        tmpl = lookup.get_template("statistics.html")
        return tmpl.render(articles=articles, word_size=word_size, tag_cloud=tag_cloud)

    statistics.exposed = True

    @require()
    def search(self, query=None):
        """
        Simply search for the string 'query'
        in the description of the article.
        """
        param, _, value = query.partition(':')
        wordre = re.compile(r'\b%s\b' % param, re.I)
        feed_id = None
        if param == "Feed":
            feed_id, _, query = value.partition(':')
        html = htmlheader()
        html += htmlnav
        html += """<div class="left inner">"""
        html += """<h1>Articles containing the string <i>%s</i></h1><br />""" % (query,)

        if feed_id is not None:
            for article in self.mongo.get_articles(feed_id):
                article_content = utils.clear_string(article.article_description)
                if not article_content:
                    utils.clear_string(article.article_title)
                if wordre.findall(article_content) != []:
{'fraction_non_alphanumeric': 0.1250087199162888, 'fraction_numerical': 0.010463899546564353, 'mean_word_length': 2.678727226071337, 'pattern_counts': {'":': 2, '<': 91, '<?xml version=': 0, '>': 91, 'https://': 2, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7354434', 'n_tokens_mistral': 4621, 'n_tokens_neox': 4406, 'n_words': 1153}