def get_menu(): categories_order = [0] categories = {0: {'name': 'No category', 'id': 0}} for cat in CategoryController(g.user.id).read().order_by('name'): categories_order.append(cat.id) categories[cat.id] = cat.dump() unread = ArticleController(g.user.id).count_by_feed(readed=False) for cat_id in categories: categories[cat_id]['unread'] = 0 categories[cat_id]['feeds'] = [] feeds = {feed.id: feed.dump() for feed in FeedController(g.user.id).read()} for feed_id, feed in feeds.items(): feed['created_stamp'] = timegm(feed['created_date'].timetuple()) * 1000 feed['last_stamp'] = timegm(feed['last_retrieved'].timetuple()) * 1000 feed['category_id'] = feed['category_id'] or 0 feed['unread'] = unread.get(feed['id'], 0) if not feed['filters']: feed['filters'] = [] if feed.get('icon_url'): feed['icon_url'] = url_for('icon.icon', url=feed['icon_url']) categories[feed['category_id']]['unread'] += feed['unread'] categories[feed['category_id']]['feeds'].append(feed_id) return jsonify( **{ 'feeds': feeds, 'categories': categories, 'categories_order': categories_order, 'crawling_method': conf.CRAWLING_METHOD, 'max_error': conf.DEFAULT_MAX_ERROR, 'error_threshold': conf.ERROR_THRESHOLD, 'is_admin': g.user.is_admin(), 'all_unread_count': sum(unread.values()) })
def get_menu(): categories_order = [0] categories = {0: {'name': 'No category', 'id': 0}} for cat in CategoryController(current_user.id).read().order_by('name'): categories_order.append(cat.id) categories[cat.id] = cat unread = ArticleController(current_user.id).count_by_feed(readed=False) for cat_id in categories: categories[cat_id]['unread'] = 0 categories[cat_id]['feeds'] = [] feeds = {feed.id: feed for feed in FeedController(current_user.id).read()} for feed_id, feed in feeds.items(): feed['created_stamp'] = timegm(feed.created_date.timetuple()) * 1000 feed['last_stamp'] = timegm(feed.last_retrieved.timetuple()) * 1000 feed['category_id'] = feed.category_id or 0 feed['unread'] = unread.get(feed.id, 0) if not feed.filters: feed['filters'] = [] if feed.icon_url: feed['icon_url'] = url_for('icon.icon', url=feed.icon_url) categories[feed['category_id']]['unread'] += feed['unread'] categories[feed['category_id']]['feeds'].append(feed_id) return {'feeds': feeds, 'categories': categories, 'categories_order': categories_order, 'crawling_method': conf.CRAWLING_METHOD, 'max_error': conf.DEFAULT_MAX_ERROR, 'error_threshold': conf.ERROR_THRESHOLD, 'is_admin': current_user.is_admin, 'all_unread_count': sum(unread.values())}
def populate_db(): db_create() ucontr = UserController() ccontr = CategoryController() fcontr = FeedController() acontr = ArticleController() ccontr = CategoryController() user1, user2 = [ucontr.create(login=name, email="*****@*****.**" % name, password=name) for name in ["user1", "user2"]] article_total = 0 for user in (user1, user2): for i in range(3): cat_id = None if i: cat_id = ccontr.create(user_id=user.id, name="category%d" % i).id feed = fcontr.create(link="feed%d" % i, user_id=user.id, category_id=cat_id, title="%s feed%d" % (user.login, i)) for j in range(3): entry = "%s %s article%d" % (user.login, feed.title, j) article_total += 1 acontr.create(entry_id=entry, link='http://test.te/%d' % article_total, feed_id=feed.id, user_id=user.id, category_id=cat_id, title=entry, content="content %d" % article_total)
def home(): """Displays the home page of the connected user. """ art_contr = ArticleController(current_user.id) unread = art_contr.count_by_feed(readed=False) nb_unread = art_contr.read_light(readed=False).count() feeds = { feed.id: feed for feed in sorted( current_user.feeds, key=lambda x: x.title.lower(), reverse=False ) } filter_ = request.args.get("filter_", "unread") feed_id = int(request.args.get("feed", 0)) liked = int(request.args.get("liked", 0)) == 1 limit = request.args.get("limit", 1000) filters = {} if filter_ in ["read", "unread"]: filters["readed"] = filter_ == "read" if feed_id: filters["feed_id"] = feed_id if liked: filters["like"] = int(liked) == 1 articles = art_contr.read_ordered(**filters) if limit != "all": limit = int(limit) articles = articles.limit(limit) in_error = { feed.id: feed.error_count for feed in FeedController(current_user.id).read(error_count__gt=0).all() } def gen_url(filter_=filter_, limit=limit, feed=feed_id, liked=liked): return "?filter_=%s&limit=%s&feed=%d&liked=%s" % ( filter_, limit, feed, 1 if liked else 0, ) return render_template( "home.html", nb_unread=nb_unread, gen_url=gen_url, feed_id=feed_id, filter_=filter_, limit=limit, feeds=feeds, liked=liked, unread=dict(unread), articles=articles.all(), in_error=in_error, )
def feeds(): "Lists the subscribed feeds in a table." art_contr = ArticleController(g.user.id) return render_template('feeds.html', feeds=FeedController(g.user.id).read(), unread_article_count=art_contr.count_by_feed(readed=False), article_count=art_contr.count_by_feed())
def populate_db(): db_create() ucontr = UserController() ccontr = CategoryController() fcontr = FeedController() acontr = ArticleController() ccontr = CategoryController() user1, user2 = [ ucontr.create(login=name, email="*****@*****.**" % name, password=name) for name in ["user1", "user2"] ] article_total = 0 for user in (user1, user2): for i in range(3): cat_id = None if i: cat_id = ccontr.create(user_id=user.id, name="category%d" % i).id feed = fcontr.create(link="feed%d" % i, user_id=user.id, category_id=cat_id, title="%s feed%d" % (user.login, i)) for j in range(3): entry = "%s %s article%d" % (user.login, feed.title, j) article_total += 1 acontr.create(entry_id=entry, link='http://test.te/%d' % article_total, feed_id=feed.id, user_id=user.id, category_id=cat_id, title=entry, content="content %d" % article_total)
def feeds(): "Lists the subscribed feeds in a table." art_contr = ArticleController(current_user.id) return render_template('feeds.html', feeds=FeedController(current_user.id).read(), unread_article_count=art_contr.count_by_feed(readed=False), article_count=art_contr.count_by_feed())
def list_(): "Lists the subscribed feeds in a table." art_contr = ArticleController(g.user.id) return render_template('categories.html', categories=list(CategoryController(g.user.id).read()), feeds_count=FeedController(g.user.id).count_by_category(), unread_article_count=art_contr.count_by_category(readed=False), article_count=art_contr.count_by_category())
def like(article_id=None): """ Mark or unmark an article as favorites. """ art_contr = ArticleController(current_user.id) article = art_contr.get(id=article_id) art_contr = art_contr.update({'id': article_id}, {'like': not article.like}) return redirect(redirect_url())
def get_middle_panel(): filters = _get_filters(request.args) art_contr = ArticleController(g.user.id) fd_hash = {feed.id: {'title': feed.title, 'icon_url': url_for('icon.icon', url=feed.icon_url) if feed.icon_url else None} for feed in FeedController(g.user.id).read()} articles = art_contr.read(**filters).order_by(Article.date.desc()) return _articles_to_json(articles, fd_hash)
def get_article(article_id): contr = ArticleController(g.user.id) article = contr.get(id=article_id).dump() if not article['readed']: contr.update({'id': article_id}, {'readed': True}) article['category_id'] = article['category_id'] or 0 feed = FeedController(g.user.id).get(id=article['feed_id']) article['icon_url'] = url_for('icon.icon', url=feed.icon_url) \ if feed.icon_url else None return jsonify(**article)
def list_(): "Lists the subscribed feeds in a table." art_contr = ArticleController(current_user.id) return render_template( 'categories.html', categories=list( CategoryController(current_user.id).read().order_by('name')), feeds_count=FeedController(current_user.id).count_by_category(), unread_article_count=art_contr.count_by_category(readed=False), article_count=art_contr.count_by_category())
def article(article_id=None): """ Presents an article. """ art_contr = ArticleController(current_user.id) article = art_contr.get(id=article_id) if not article.readed: art_contr.update({"id": article.id}, {"readed": True}) return render_template("article.html", head_titles=[clear_string(article.title)], article=article)
def test_article_get_unread(self): self.assertEquals({ 1: 3, 2: 3, 3: 3 }, ArticleController(2).count_by_feed(readed=False)) self.assertEquals({ 4: 3, 5: 3, 6: 3 }, ArticleController(3).count_by_feed(readed=False))
def get_article(article_id, parse=False): locale = get_locale() contr = ArticleController(current_user.id) article = contr.get(id=article_id) if not article.readed: article['readed'] = True contr.update({'id': article_id}, {'readed': True}) article['category_id'] = article.category_id or 0 feed = FeedController(current_user.id).get(id=article.feed_id) article['icon_url'] = url_for('icon.icon', url=feed.icon_url) \ if feed.icon_url else None article['date'] = format_datetime(localize(article.date), locale=locale) return article
def expire(): """ Delete articles older than the given number of weeks. """ current_time = datetime.utcnow() weeks_ago = current_time - timedelta(int(request.args.get('weeks', 10))) art_contr = ArticleController(g.user.id) query = art_contr.read(__or__={'date__lt': weeks_ago, 'retrieved_date__lt': weeks_ago}) count = query.count() query.delete() flash(gettext('%(count)d articles deleted', count=count), 'info') return redirect(redirect_url())
def get_middle_panel(): filters = _get_filters(request.args) art_contr = ArticleController(g.user.id) fd_hash = { feed.id: { 'title': feed.title, 'icon_url': url_for('icon.icon', url=feed.icon_url) if feed.icon_url else None } for feed in FeedController(g.user.id).read() } articles = art_contr.read(**filters).order_by(Article.date.desc()) return _articles_to_json(articles, fd_hash)
def get_article(article_id, parse=False): locale = get_locale() contr = ArticleController(current_user.id) article = contr.get(id=article_id) if not article.readed: article["readed"] = True contr.update({"id": article_id}, {"readed": True}) article["category_id"] = article.category_id or 0 feed = FeedController(current_user.id).get(id=article.feed_id) article["icon_url"] = ( url_for("icon.icon", url=feed.icon_url) if feed.icon_url else None ) article["date"] = format_datetime(localize(article.date), locale=locale) return article
def user(user_id=None): """ See information about a user (stations, etc.). """ user = UserController().get(id=user_id) if user is not None: article_contr = ArticleController(user_id) return render_template('/admin/user.html', user=user, feeds=user.feeds, article_count=article_contr.count_by_feed(), unread_article_count=article_contr.count_by_feed(readed=False)) else: flash(gettext('This user does not exist.'), 'danger') return redirect(redirect_url())
def management(): """ Display the management page. """ if request.method == 'POST': if None != request.files.get('opmlfile', None): # Import an OPML file data = request.files.get('opmlfile', None) if not misc_utils.allowed_file(data.filename): flash(gettext('File not allowed.'), 'danger') else: try: nb = import_opml(current_user.nickname, data.read()) if conf.CRAWLING_METHOD == "classic": misc_utils.fetch(current_user.id, None) flash( str(nb) + ' ' + gettext('feeds imported.'), "success") flash(gettext("Downloading articles..."), 'info') except: flash(gettext("Impossible to import the new feeds."), "danger") elif None != request.files.get('jsonfile', None): # Import an account data = request.files.get('jsonfile', None) if not misc_utils.allowed_file(data.filename): flash(gettext('File not allowed.'), 'danger') else: try: nb = import_json(current_user.nickname, data.read()) flash(gettext('Account imported.'), "success") except: flash(gettext("Impossible to import the account."), "danger") else: flash(gettext('File not allowed.'), 'danger') nb_feeds = FeedController(current_user.id).read().count() art_contr = ArticleController(current_user.id) nb_articles = art_contr.read().count() nb_unread_articles = art_contr.read(readed=False).count() nb_categories = CategoryController(current_user.id).read().count() nb_bookmarks = BookmarkController(current_user.id).read().count() return render_template('management.html', user=current_user, nb_feeds=nb_feeds, nb_articles=nb_articles, nb_unread_articles=nb_unread_articles, nb_categories=nb_categories, nb_bookmarks=nb_bookmarks)
async def insert_database(user, feed): articles = await parse_feed(user, feed) if None is articles: return [] logger.debug('inserting articles for {}'.format(feed.title)) logger.info("Database insertion...") new_articles = [] art_contr = ArticleController(user.id) for article in articles: existing_article_req = art_contr.read(feed_id=feed.id, **extract_id(article)) exist = existing_article_req.count() != 0 if exist: # if the article has been already retrieved, we only update # the content or the title logger.debug("Article %r (%r) already in the database.", article['title'], article['link']) existing_article = existing_article_req.first() new_updated_date = None try: new_updated_date = dateutil.parser.parse(article['updated']) except Exception as e: print(e)#new_updated_date = existing_article.date if None is existing_article.updated_date: existing_article.updated_date = new_updated_date.replace(tzinfo=None) if existing_article.updated_date.strftime('%Y-%m-%dT%H:%M:%S') != \ new_updated_date.strftime('%Y-%m-%dT%H:%M:%S'): existing_article.updated_date = \ new_updated_date.replace(tzinfo=None) if existing_article.title != article['title']: existing_article.title = article['title'] content = get_article_content(article) if existing_article.content != content: existing_article.content = content existing_article.readed = False art_contr.update({'entry_id': existing_article.entry_id}, existing_article.dump()) continue article = construct_article(article, feed) try: new_articles.append(art_contr.create(**article)) logger.info("New article % (%r) added.", article['title'], article['link']) except Exception: logger.exception("Error when inserting article in database:") continue return new_articles
async def insert_database(user, feed): articles = await parse_feed(user, feed) if None is articles: return [] logger.info('Inserting articles for {}'.format(feed.title)) new_articles = [] art_contr = ArticleController(user.id) for article in articles: new_article = await construct_article(article, feed) try: existing_article_req = art_contr.read(feed_id=feed.id, entry_id=extract_id(article)) except Exception as e: logger.exception("existing_article_req: " + str(e)) continue exist = existing_article_req.count() != 0 if exist: # if the article has been already retrieved, we only update # the content or the title logger.info('Article already in the database: {}'. \ format(article['link'])) existing_article = existing_article_req.first() if new_article['date'].replace(tzinfo=None) != \ existing_article.date: existing_article.date = new_article['date'] existing_article.updated_date = new_article['date'] if existing_article.title != new_article['title']: existing_article.title = new_article['title'] content = get_article_content(article) if existing_article.content != content: existing_article.content = content existing_article.readed = False art_contr.update({'entry_id': existing_article.entry_id}, existing_article.dump()) logger.info('Article updated: {}'.format(article['link'])) continue # insertion of the new article try: new_articles.append(art_contr.create(**new_article)) logger.info('New article added: {}'.format(new_article['link'])) except Exception: logger.exception('Error when inserting article in database:') continue return new_articles
def history(user_id, year=None, month=None): """ Sort articles by year and month. """ articles_counter = Counter() articles = ArticleController(user_id).read() if None != year: articles = articles.filter(sqlalchemy.extract('year', 'Article.date') == year) if None != month: articles = articles.filter(sqlalchemy.extract('month', 'Article.date') == month) for article in articles.all(): if None != year: articles_counter[article.date.month] += 1 else: articles_counter[article.date.year] += 1 return articles_counter, articles
def delete(article_id=None): "Delete an article from the database." article = ArticleController(current_user.id).delete(article_id) flash( gettext('Article %(article_title)s deleted', article_title=article.title), 'success') return redirect(url_for('home'))
def history(year=None, month=None): cntr, artcles = ArticleController(current_user.id).get_history(year, month) return render_template('history.html', articles_counter=cntr, articles=artcles, year=year, month=month)
def management(): """ Display the management page. """ if request.method == 'POST': if None != request.files.get('opmlfile', None): # Import an OPML file data = request.files.get('opmlfile', None) if not misc_utils.allowed_file(data.filename): flash(gettext('File not allowed.'), 'danger') else: try: nb = import_opml(current_user.nickname, data.read()) if conf.CRAWLING_METHOD == "classic": misc_utils.fetch(current_user.id, None) flash(str(nb) + ' ' + gettext('feeds imported.'), "success") flash(gettext("Downloading articles..."), 'info') except: flash(gettext("Impossible to import the new feeds."), "danger") elif None != request.files.get('jsonfile', None): # Import an account data = request.files.get('jsonfile', None) if not misc_utils.allowed_file(data.filename): flash(gettext('File not allowed.'), 'danger') else: try: nb = import_json(current_user.nickname, data.read()) flash(gettext('Account imported.'), "success") except: flash(gettext("Impossible to import the account."), "danger") else: flash(gettext('File not allowed.'), 'danger') nb_feeds = FeedController(current_user.id).read().count() art_contr = ArticleController(current_user.id) nb_articles = art_contr.read().count() nb_unread_articles = art_contr.read(readed=False).count() nb_categories = CategoryController(current_user.id).read().count() nb_bookmarks = BookmarkController(current_user.id).read().count() return render_template('management.html', user=current_user, nb_feeds=nb_feeds, nb_articles=nb_articles, nb_unread_articles=nb_unread_articles, nb_categories=nb_categories, nb_bookmarks=nb_bookmarks)
def feed_view(feed_id=None, user_id=None): feed = FeedController(user_id).get(id=feed_id) word_size = 6 category = None if feed.category_id: category = CategoryController(user_id).get(id=feed.category_id) filters = {} filters["feed_id"] = feed_id articles = ArticleController(user_id).read_light(**filters) # Server-side pagination page, per_page, offset = get_page_args(per_page_parameter="per_page") pagination = Pagination( page=page, total=articles.count(), css_framework="bootstrap3", search=False, record_name="articles", per_page=per_page, ) today = datetime.now() try: last_article = articles[0].date first_article = articles[-1].date delta = last_article - first_article average = round(float(articles.count()) / abs(delta.days), 2) except Exception as e: last_article = datetime.fromtimestamp(0) first_article = datetime.fromtimestamp(0) delta = last_article - first_article average = 0 elapsed = today - last_article return render_template( "feed.html", head_titles=[utils.clear_string(feed.title)], feed=feed, category=category, articles=articles.offset(offset).limit(per_page), pagination=pagination, first_post_date=first_article, end_post_date=last_article, average=average, delta=delta, elapsed=elapsed, )
def test_feed_rights(self): cat = CategoryController(2).read()[0].dump() self.assertTrue(3, ArticleController().read(category_id=cat['id']).count()) self.assertTrue(3, FeedController().read(category_id=cat['id']).count()) self._test_controller_rights(cat, UserController().get(id=cat['user_id']))
def article(article_id=None): """ Presents the content of an article. """ article = ArticleController(g.user.id).get(id=article_id) previous_article = article.previous_article() if previous_article is None: previous_article = article.source.articles[0] next_article = article.next_article() if next_article is None: next_article = article.source.articles[-1] return render_template('article.html', head_titles=[clear_string(article.title)], article=article, previous_article=previous_article, next_article=next_article)
def user_stream(per_page, nickname=None): """ Display the stream of a user (list of articles of public feed). """ user_contr = UserController() user = user_contr.get(nickname=nickname) if not user.is_public_profile: if current_user.is_authenticated and current_user.id == user.id: flash(gettext("You must set your profile to public."), "info") return redirect(url_for("user.profile")) category_id = int(request.args.get("category_id", 0)) category = CategoryController().read(id=category_id).first() # Load the public feeds filters = {} filters["private"] = False if category_id: filters["category_id"] = category_id feeds = FeedController().read(**filters).all() # Re-initializes the filters to load the articles filters = {} filters["feed_id__in"] = [feed.id for feed in feeds] if category: filters["category_id"] = category_id articles = ArticleController(user.id).read_light(**filters) # Server-side pagination page, per_page, offset = get_page_args(per_page_parameter="per_page") pagination = Pagination( page=page, total=articles.count(), css_framework="bootstrap3", search=False, record_name="articles", per_page=per_page, ) return render_template( "user_stream.html", user=user, articles=articles.offset(offset).limit(per_page), category=category, pagination=pagination, )
def article(article_id=None): """ Presents an article. """ article = ArticleController(current_user.id).get(id=article_id) return render_template('article.html', head_titles=[clear_string(article.title)], article=article)
async def insert_articles(queue, nḅ_producers=1): """Consumer coroutines. """ nb_producers_done = 0 while True: item = await queue.get() if item is None: nb_producers_done += 1 if nb_producers_done == nḅ_producers: print('All producers done.') print('Process finished.') break continue user, feed, articles = item if None is articles: logger.info('None') articles = [] logger.info('Inserting articles for {}'.format(feed.link)) art_contr = ArticleController(user.id) for article in articles: new_article = await construct_article(article, feed) try: existing_article_req = art_contr.read( user_id=user.id, feed_id=feed.id, entry_id=extract_id(article)) except Exception as e: logger.exception("existing_article_req: " + str(e)) continue exist = existing_article_req.count() != 0 if exist: continue # insertion of the new article try: art_contr.create(**new_article) logger.info('New article added: {}'.format(new_article['link'])) except Exception: logger.exception('Error when inserting article in database.') continue
def test_feed_and_article_deletion(self): ccontr = CategoryController(2) cat = ccontr.read()[0].dump() ccontr.delete(cat['id']) self.assertEquals(0, ArticleController().read(category_id=cat['id']).count()) self.assertEquals(0, FeedController().read(category_id=cat['id']).count())
def expire(): """ Delete articles older than the given number of weeks. """ current_time = datetime.utcnow() weeks_ago = current_time - timedelta(int(request.args.get('weeks', 10))) art_contr = ArticleController(current_user.id) query = art_contr.read(__or__={ 'date__lt': weeks_ago, 'retrieved_date__lt': weeks_ago }) count = query.count() query.delete() db.session.commit() flash(gettext('%(count)d articles deleted', count=count), 'info') return redirect(redirect_url())
def user(user_id=None): """ See information about a user (stations, etc.). """ user = UserController().get(id=user_id) if user is not None: article_contr = ArticleController(user_id) return render_template( '/admin/user.html', user=user, feeds=FeedController().read(user_id=user_id).order_by('title'), article_count=article_contr.count_by_feed(), unread_article_count=article_contr.count_by_feed(readed=False)) else: flash(gettext('This user does not exist.'), 'warn') return redirect(redirect_url())
def get_article(article_id, parse=False): locale = get_locale() contr = ArticleController(current_user.id) article = contr.get(id=article_id) if not article.readed: article['readed'] = True contr.update({'id': article_id}, {'readed': True}) article['category_id'] = article.category_id or 0 feed = FeedController(current_user.id).get(id=article.feed_id) article['icon_url'] = url_for('icon.icon', url=feed.icon_url) \ if feed.icon_url else None readability_available = bool(current_user.readability_key or conf.PLUGINS_READABILITY_KEY) article['date'] = format_datetime(localize(article.date), locale=locale) article['readability_available'] = readability_available if parse or (not article.readability_parsed and feed.readability_auto_parse and readability_available): try: new_content = readability.parse( article.link, current_user.readability_key or conf.PLUGINS_READABILITY_KEY) except Exception as error: flash("Readability failed with %r" % error, "error") article['readability_parsed'] = False else: article['readability_parsed'] = True article['content'] = clean_urls(new_content, article['link']) new_attr = {'readability_parsed': True, 'content': new_content} contr.update({'id': article['id']}, new_attr) return article
def history(user_id, year=None, month=None): """ Sort articles by year and month. """ articles_counter = Counter() articles = ArticleController(user_id).read() if None != year: articles = articles.filter( sqlalchemy.extract("year", "Article.date") == year) if None != month: articles = articles.filter( sqlalchemy.extract("month", "Article.date") == month) for article in articles.all(): if None != year: articles_counter[article.date.month] += 1 else: articles_counter[article.date.year] += 1 return articles_counter, articles
def management(): """ Display the management page. """ if request.method == "POST": if None != request.files.get("opmlfile", None): # Import an OPML file data = request.files.get("opmlfile", None) if not utils.allowed_file(data.filename): flash(gettext("File not allowed."), "danger") else: try: nb = utils.import_opml(g.user.email, data.read()) if conf.CRAWLING_METHOD == "classic": utils.fetch(g.user.email, None) flash(str(nb) + " " + gettext("feeds imported."), "success") flash(gettext("Downloading articles..."), "info") except: flash(gettext("Impossible to import the new feeds."), "danger") elif None != request.files.get("jsonfile", None): # Import an account data = request.files.get("jsonfile", None) if not utils.allowed_file(data.filename): flash(gettext("File not allowed."), "danger") else: try: nb = utils.import_json(g.user.email, data.read()) flash(gettext("Account imported."), "success") except: flash(gettext("Impossible to import the account."), "danger") else: flash(gettext("File not allowed."), "danger") nb_feeds = FeedController(g.user.id).read().count() art_contr = ArticleController(g.user.id) nb_articles = art_contr.read().count() nb_unread_articles = art_contr.read(readed=False).count() return render_template( "management.html", user=g.user, nb_feeds=nb_feeds, nb_articles=nb_articles, nb_unread_articles=nb_unread_articles, )
def article_pub(article_id=None): """ Presents an article of a public feed if the profile of the owner is also public. """ article = ArticleController().get(id=article_id) if article.source.private or not article.source.user.is_public_profile: return render_template('errors/404.html'), 404 return render_template('article_pub.html', head_titles=[clear_string(article.title)], article=article)
def delete(article_id=None): """ Delete an article from the database. """ article = ArticleController(current_user.id).delete(article_id) flash( gettext("Article %(article_title)s deleted", article_title=article.title), "success", ) return redirect(url_for("home"))
def get_menu(): now, locale = datetime.now(), get_locale() categories_order = [0] categories = {0: {'name': 'No category', 'id': 0}} for cat in CategoryController(current_user.id).read().order_by('name'): categories_order.append(cat.id) categories[cat.id] = cat unread = ArticleController(current_user.id).count_by_feed(readed=False) for cat_id in categories: categories[cat_id]['unread'] = 0 categories[cat_id]['feeds'] = [] feeds = {feed.id: feed for feed in FeedController(current_user.id).read()} for feed_id, feed in feeds.items(): feed['created_rel'] = format_timedelta(feed.created_date - now, add_direction=True, locale=locale) feed['last_rel'] = format_timedelta(feed.last_retrieved - now, add_direction=True, locale=locale) feed['created_date'] = format_datetime(localize(feed.created_date), locale=locale) feed['last_retrieved'] = format_datetime(localize(feed.last_retrieved), locale=locale) feed['category_id'] = feed.category_id or 0 feed['unread'] = unread.get(feed.id, 0) if not feed.filters: feed['filters'] = [] if feed.icon_url: feed['icon_url'] = url_for('icon.icon', url=feed.icon_url) categories[feed['category_id']]['unread'] += feed['unread'] categories[feed['category_id']]['feeds'].append(feed_id) return { 'feeds': feeds, 'categories': categories, 'categories_order': categories_order, 'crawling_method': conf.CRAWLER_TYPE, 'max_error': conf.FEED_ERROR_MAX, 'error_threshold': conf.FEED_ERROR_THRESHOLD, 'is_admin': current_user.is_admin, 'all_unread_count': sum(unread.values()) }
async def insert_database(user, feed): articles = await parse_feed(user, feed) if None is articles: return [] logger.debug('inserting articles for {}'.format(feed.title)) logger.info("Database insertion...") new_articles = [] art_contr = ArticleController(user.id) for article in articles: existing_article_req = art_contr.read(feed_id=feed.id, **extract_id(article)) exist = existing_article_req.count() != 0 if exist: existing_article = existing_article_req.first() is_updated = False logger.debug("Article %r (%r) already in the database.", article['title'], article['link']) content = get_article_content(article) if existing_article.title != article['title']: existing_article.title = article['title'] is_updated = True if existing_article.content != content: existing_article.content = content existing_article.readed = False is_updated = True if is_updated: art_contr.update({'entry_id': existing_article.entry_id}, existing_article.dump()) continue article = construct_article(article, feed.dump()) try: new_articles.append(art_contr.create(**article)) logger.info("New article % (%r) added.", article['title'], article['link']) except Exception: logger.exception("Error when inserting article in database:") continue return new_articles
def mark_as(new_value='read', feed_id=None, article_id=None): """ Mark all unreaded articles as read. """ readed = new_value == 'read' art_contr = ArticleController(current_user.id) filters = {'readed': not readed} if feed_id is not None: filters['feed_id'] = feed_id message = 'Feed marked as %s.' elif article_id is not None: filters['id'] = article_id message = 'Article marked as %s.' else: message = 'All article marked as %s.' art_contr.update(filters, {"readed": readed}) flash(gettext(message % new_value), 'info') if readed: return redirect(redirect_url()) return redirect('home')
def mark_as(new_value="read", feed_id=None, article_id=None): """ Mark a single article or all articles of a feed as read/unread. """ readed = new_value == "read" art_contr = ArticleController(current_user.id) filters = {"readed": not readed} if feed_id is not None: filters["feed_id"] = feed_id message = "Feed marked as %s." elif article_id is not None: filters["id"] = article_id message = "Article marked as %s." else: message = "All article marked as %s." art_contr.update(filters, {"readed": readed}) flash(gettext(message % new_value), "info") # if readed: # return redirect(redirect_url()) return redirect(url_for("home"))
def get_article(article_id, parse=False): locale = get_locale() contr = ArticleController(current_user.id) article = contr.get(id=article_id) if not article.readed: article['readed'] = True contr.update({'id': article_id}, {'readed': True}) article['category_id'] = article.category_id or 0 feed = FeedController(current_user.id).get(id=article.feed_id) article['icon_url'] = url_for('icon.icon', url=feed.icon_url) \ if feed.icon_url else None readability_available = bool(current_user.readability_key or conf.PLUGINS_READABILITY_KEY) article['date'] = format_datetime(localize(article.date), locale=locale) article['readability_available'] = readability_available if parse or (not article.readability_parsed and feed.readability_auto_parse and readability_available): try: new_content = readability.parse(article.link, current_user.readability_key or conf.PLUGINS_READABILITY_KEY) except Exception as error: flash("Readability failed with %r" % error, "error") article['readability_parsed'] = False else: article['readability_parsed'] = True article['content'] = clean_urls(new_content, article['link']) new_attr = {'readability_parsed': True, 'content': new_content} contr.update({'id': article['id']}, new_attr) return article
def update(action, feed_id=None): readed = action == 'read' filters = {'readed__ne': readed} nb_days = request.args.get('nb_days', 0, type=int) if nb_days != 0: filters['date__lt'] = datetime.now() - timedelta(days=nb_days) if feed_id: filters['feed_id'] = feed_id ArticleController(current_user.id).update(filters, {'readed': readed}) flash(gettext('Feed successfully updated.'), 'success') return redirect(request.referrer or url_for('home'))
def user_stream(per_page, nickname=None): """ Display the stream of a user (list of articles of public feed). """ user_contr = UserController() user = user_contr.get(nickname=nickname) if not user.is_public_profile: if current_user.is_authenticated and current_user.id == user.id: flash(gettext('You must set your profile to public.'), 'info') return redirect(url_for('user.profile')) category_id = int(request.args.get('category_id', 0)) category = CategoryController().read(id=category_id).first() # Load the public feeds filters = {} filters['private'] = False if category_id: filters['category_id'] = category_id feeds = FeedController().read(**filters).all() # Re-initializes the filters to load the articles filters = {} filters['feed_id__in'] = [feed.id for feed in feeds] if category: filters['category_id'] = category_id articles = ArticleController(user.id).read_light(**filters) # Server-side pagination page, per_page, offset = get_page_args(per_page_parameter='per_page') pagination = Pagination(page=page, total=articles.count(), css_framework='bootstrap3', search=False, record_name='articles', per_page=per_page) return render_template('user_stream.html', user=user, articles=articles.offset(offset).limit(per_page), category=category, pagination=pagination)
def get_menu(): now, locale = datetime.now(), get_locale() categories_order = [0] categories = {0: {'name': 'No category', 'id': 0}} for cat in CategoryController(current_user.id).read().order_by('name'): categories_order.append(cat.id) categories[cat.id] = cat unread = ArticleController(current_user.id).count_by_feed(readed=False) for cat_id in categories: categories[cat_id]['unread'] = 0 categories[cat_id]['feeds'] = [] feeds = {feed.id: feed for feed in FeedController(current_user.id).read()} for feed_id, feed in feeds.items(): feed['created_rel'] = format_timedelta(feed.created_date - now, add_direction=True, locale=locale) feed['last_rel'] = format_timedelta(feed.last_retrieved - now, add_direction=True, locale=locale) feed['created_date'] = format_datetime(localize(feed.created_date), locale=locale) feed['last_retrieved'] = format_datetime(localize(feed.last_retrieved), locale=locale) feed['category_id'] = feed.category_id or 0 feed['unread'] = unread.get(feed.id, 0) if not feed.filters: feed['filters'] = [] if feed.icon_url: feed['icon_url'] = url_for('icon.icon', url=feed.icon_url) categories[feed['category_id']]['unread'] += feed['unread'] categories[feed['category_id']]['feeds'].append(feed_id) return {'feeds': feeds, 'categories': categories, 'categories_order': categories_order, 'crawling_method': conf.CRAWLER_TYPE, 'max_error': conf.FEED_ERROR_MAX, 'error_threshold': conf.FEED_ERROR_THRESHOLD, 'is_admin': current_user.is_admin, 'all_unread_count': sum(unread.values())}
def redirect_to_article(article_id): contr = ArticleController(current_user.id) article = contr.get(id=article_id) if not article.readed: contr.update({'id': article.id}, {'readed': True}) return redirect(article.link)
def execute(self): counts = ArticleController(ignore_context=True).count_by_user_id() print("articles.value %s" % sum(counts.values())) for user, count in counts.items(): print("articles_user_%s.value %s" % (user, count))
def get_middle_panel(): filters = _get_filters(request.args) art_contr = ArticleController(current_user.id) articles = art_contr.read_light(**filters) return _articles_to_json(articles)
def mark_all_as_read(): filters = _get_filters(request.json) acontr = ArticleController(current_user.id) processed_articles = _articles_to_json(acontr.read_light(**filters)) acontr.update(filters, {'readed': True}) return processed_articles