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 process_form(category_id=None): form = CategoryForm() cat_contr = CategoryController(g.user.id) if not form.validate(): return render_template('edit_category.html', form=form) existing_cats = list(cat_contr.read(name=form.name.data)) if existing_cats and category_id is None: flash(gettext("Couldn't add category: already exists."), "warning") return redirect(url_for('category.form', category_id=existing_cats[0].id)) # Edit an existing category category_attr = {'name': form.name.data} if category_id is not None: cat_contr.update({'id': category_id}, category_attr) flash(gettext('Category %(cat_name)r successfully updated.', cat_name=category_attr['name']), 'success') return redirect(url_for('category.form', category_id=category_id)) # Create a new category new_category = cat_contr.create(**category_attr) flash(gettext('Category %(category_name)r successfully created.', category_name=new_category.name), 'success') return redirect(url_for('category.form', category_id=new_category.id))
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 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 opml_import(): if request.files.get('opmlfile', None) is None: flash(gettext('Got no file'), 'warning') return redirect(url_for('user.profile')) data = request.files.get('opmlfile', None) try: subscriptions = opml.from_string(data.read()) except: flash(gettext("Couldn't parse file"), 'danger') return redirect(request.referrer) ccontr = CategoryController(current_user.id) fcontr = FeedController(current_user.id) created_count, existing_count, failed_count = 0, 0, 0 categories = {cat.name: cat.id for cat in ccontr.read()} for line in subscriptions: try: link = line.xmlUrl except Exception: failed_count += 1 continue # don't import twice if fcontr.read(link=link).count(): existing_count += 1 continue # handling categories cat_id = None category = getattr(line, 'category', None) if category: if category not in categories: new_category = ccontr.create(name=category) categories[new_category.name] = new_category.id cat_id = categories[category] fcontr.create(title=getattr(line, 'text', None), category_id=cat_id, description=getattr(line, 'description', None), link=link, site_link=getattr(line, 'htmlUrl', None)) created_count += 1 flash( gettext( "Created %(created)d feed ! (%(failed)d import failed, " "%(existing)d were already existing)", created=created_count, failed=failed_count, existing=existing_count), "info") return redirect(url_for('user.profile'))
def export(): """ Export feeds to OPML. """ include_disabled = request.args.get("includedisabled", "") == "on" include_private = request.args.get("includeprivate", "") == "on" include_exceeded_error_count = (request.args.get( "includeexceedederrorcount", "") == "on") filter = {} if not include_disabled: filter["enabled"] = True if not include_private: filter["private"] = False if not include_exceeded_error_count: filter["error_count__lt"] = conf.DEFAULT_MAX_ERROR user = UserController(current_user.id).get(id=current_user.id) feeds = FeedController(current_user.id).read(**filter) categories = { cat.id: cat.dump() for cat in CategoryController(user.id).read() } response = make_response( render_template( "opml.xml", user=user, feeds=feeds, categories=categories, now=datetime.now(), )) response.headers["Content-Type"] = "application/xml" response.headers["Content-Disposition"] = "attachment; filename=feeds.opml" return response
def form(feed_id=None): action = gettext("Add a feed") categories = CategoryController(current_user.id).read() head_titles = [action] if feed_id is None: form = AddFeedForm() form.set_category_choices(categories) return render_template("edit_feed.html", action=action, head_titles=head_titles, form=form) feed = FeedController(current_user.id).get(id=feed_id) form = AddFeedForm(obj=feed) form.set_category_choices(categories) action = gettext("Edit feed") head_titles = [action] if feed.title: head_titles.append(feed.title) return render_template( "edit_feed.html", action=action, head_titles=head_titles, categories=categories, form=form, feed=feed, )
def export(): """ Export feeds to OPML. """ include_disabled = request.args.get('includedisabled', '') == 'on' include_private = request.args.get('includeprivate', '') == 'on' include_exceeded_error_count = request.args. \ get('includeexceedederrorcount', '') == 'on' filter = {} if not include_disabled: filter['enabled'] = True if not include_private: filter['private'] = False if not include_exceeded_error_count: filter['error_count__lt'] = conf.DEFAULT_MAX_ERROR user = UserController(current_user.id).get(id=current_user.id) feeds = FeedController(current_user.id).read(**filter) categories = { cat.id: cat.dump() for cat in CategoryController(user.id).read() } response = make_response( render_template('opml.xml', user=user, feeds=feeds, categories=categories, now=datetime.now())) response.headers['Content-Type'] = 'application/xml' response.headers['Content-Disposition'] = 'attachment; filename=feeds.opml' return response
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 export(): """ Export to OPML or JSON. """ user = UserController(current_user.id).get(id=current_user.id) if request.args.get('format') == "JSON": # Export to JSON for the export of account. try: json_result = export_json(user) except Exception as e: flash(gettext("Error when exporting articles."), 'danger') return redirect(redirect_url()) response = make_response(json_result) response.mimetype = 'application/json' response.headers["Content-Disposition"] \ = 'attachment; filename=account.json' elif request.args.get('format') == "OPML": # Export to the OPML format. categories = { cat.id: cat.dump() for cat in CategoryController(user.id).read() } response = make_response( render_template('opml.xml', user=user, categories=categories, now=datetime.now())) response.headers['Content-Type'] = 'application/xml' response.headers[ 'Content-Disposition'] = 'attachment; filename=feeds.opml' else: flash(gettext('Export format not supported.'), 'warning') return redirect(redirect_url()) return response
def opml_import(): if request.files.get('opmlfile', None) is None: flash(gettext('Got no file'), 'warning') return redirect(url_for('user.profile')) data = request.files.get('opmlfile', None) try: subscriptions = opml.from_string(data.read()) except: flash(gettext("Couldn't parse file"), 'danger') return redirect(request.referrer) ccontr = CategoryController(current_user.id) fcontr = FeedController(current_user.id) created_count, existing_count, failed_count = 0, 0, 0 categories = {cat.name: cat.id for cat in ccontr.read()} for line in subscriptions: try: link = line.xmlUrl except Exception: failed_count += 1 continue # don't import twice if fcontr.read(link=link).count(): existing_count += 1 continue # handling categories cat_id = None category = getattr(line, 'category', None) if category: if category not in categories: new_category = ccontr.create(name=category) categories[new_category.name] = new_category.id cat_id = categories[category] fcontr.create(title=getattr(line, 'text', None), category_id=cat_id, description=getattr(line, 'description', None), link=link, site_link=getattr(line, 'htmlUrl', None)) created_count += 1 flash(gettext("Created %(created)d feed ! (%(failed)d import failed, " "%(existing)d were already existing)", created=created_count, failed=failed_count, existing=existing_count), "info") return redirect(url_for('user.profile'))
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 process_form(feed_id=None): form = AddFeedForm() feed_contr = FeedController(current_user.id) form.set_category_choices(CategoryController(current_user.id).read()) if not form.validate(): return render_template("edit_feed.html", form=form) existing_feeds = list(feed_contr.read(link=form.link.data)) if existing_feeds and feed_id is None: flash(gettext("Couldn't add feed: feed already exists."), "warning") return redirect(url_for("feed.form", feed_id=existing_feeds[0].id)) # Edit an existing feed feed_attr = { "title": form.title.data, "enabled": form.enabled.data, "link": form.link.data, "site_link": form.site_link.data, "filters": [], "category_id": form.category_id.data, "private": form.private.data, } if not feed_attr["category_id"] or feed_attr["category_id"] == "0": del feed_attr["category_id"] for filter_attr in ("type", "pattern", "action on", "action"): for i, value in enumerate( request.form.getlist(filter_attr.replace(" ", "_"))): if i >= len(feed_attr["filters"]): feed_attr["filters"].append({}) feed_attr["filters"][i][filter_attr] = value if feed_id is not None: feed_contr.update({"id": feed_id}, feed_attr) flash( gettext( "Feed %(feed_title)r successfully updated.", feed_title=feed_attr["title"], ), "success", ) return redirect(url_for("feed.form", feed_id=feed_id)) # Create a new feed new_feed = feed_contr.create(**feed_attr) flash( gettext("Feed %(feed_title)r successfully created.", feed_title=new_feed.title), "success", ) if conf.CRAWLING_METHOD == "default": misc_utils.fetch(current_user.id, new_feed.id) flash(gettext("Downloading articles for the new feed..."), "info") return redirect(url_for("feed.form", feed_id=new_feed.id))
def delete(category_id=None): category = CategoryController(current_user.id).delete(category_id) flash( gettext( "Category %(category_name)s successfully deleted.", category_name=category.name, ), "success", ) return redirect(redirect_url())
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 update(self, filters, attrs): user_id = attrs.get('user_id', self.user_id) if 'feed_id' in attrs: feed = FeedController().get(id=attrs['feed_id']) assert feed.user_id == user_id, "no right on feed %r" % feed.id attrs['category_id'] = feed.category_id if attrs.get('category_id'): cat = CategoryController().get(id=attrs['category_id']) assert self.user_id is None or cat.user_id == user_id, \ "no right on cat %r" % cat.id return super().update(filters, attrs)
def update(self, filters, attrs): user_id = attrs.get("user_id", self.user_id) if "feed_id" in attrs: feed = FeedController().get(id=attrs["feed_id"]) assert feed.user_id == user_id, "no right on feed %r" % feed.id attrs["category_id"] = feed.category_id if attrs.get("category_id"): cat = CategoryController().get(id=attrs["category_id"]) assert self.user_id is None or cat.user_id == user_id, ( "no right on cat %r" % cat.id ) return super().update(filters, attrs)
def process_form(category_id=None): form = CategoryForm() cat_contr = CategoryController(current_user.id) if not form.validate(): return render_template('edit_category.html', form=form) existing_cats = list(cat_contr.read(name=form.name.data)) if existing_cats and category_id is None: flash(gettext("Couldn't add category: already exists."), "warning") return redirect( url_for('category.form', category_id=existing_cats[0].id)) # Edit an existing category category_attr = {'name': form.name.data} if category_id is not None: cat_contr.update({'id': category_id}, category_attr) flash( gettext('Category %(cat_name)r successfully updated.', cat_name=category_attr['name']), 'success') return redirect(url_for('category.form', category_id=category_id)) # Create a new category new_category = cat_contr.create(**category_attr) flash( gettext('Category %(category_name)r successfully created.', category_name=new_category.name), 'success') return redirect(url_for('category.form', category_id=new_category.id))
def process_form(feed_id=None): form = AddFeedForm() feed_contr = FeedController(current_user.id) form.set_category_choices(CategoryController(current_user.id).read()) if not form.validate(): return render_template('edit_feed.html', form=form) existing_feeds = list(feed_contr.read(link=form.link.data)) if existing_feeds and feed_id is None: flash(gettext("Couldn't add feed: feed already exists."), "warning") return redirect(url_for('feed.form', feed_id=existing_feeds[0].id)) # Edit an existing feed feed_attr = { 'title': form.title.data, 'enabled': form.enabled.data, 'link': form.link.data, 'site_link': form.site_link.data, 'filters': [], 'category_id': form.category_id.data, 'private': form.private.data } if not feed_attr['category_id'] or feed_attr['category_id'] == '0': del feed_attr['category_id'] for filter_attr in ('type', 'pattern', 'action on', 'action'): for i, value in enumerate( request.form.getlist(filter_attr.replace(' ', '_'))): if i >= len(feed_attr['filters']): feed_attr['filters'].append({}) feed_attr['filters'][i][filter_attr] = value if feed_id is not None: feed_contr.update({'id': feed_id}, feed_attr) flash( gettext('Feed %(feed_title)r successfully updated.', feed_title=feed_attr['title']), 'success') return redirect(url_for('feed.form', feed_id=feed_id)) # Create a new feed new_feed = feed_contr.create(**feed_attr) flash( gettext('Feed %(feed_title)r successfully created.', feed_title=new_feed.title), 'success') if conf.CRAWLING_METHOD == "default": misc_utils.fetch(current_user.id, new_feed.id) flash(gettext("Downloading articles for the new feed..."), 'info') return redirect(url_for('feed.form', feed_id=new_feed.id))
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 opml_export(): user = UserController(current_user.id).get(id=current_user.id) categories = { cat.id: cat for cat in CategoryController(current_user.id).read() } response = make_response( render_template('opml.xml', user=user, categories=categories, feeds=FeedController(current_user.id).read(), now=datetime.now())) response.headers['Content-Type'] = 'application/xml' response.headers['Content-Disposition'] = 'attachment; filename=feeds.opml' return response
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 export_opml(): """ Export all feeds to OPML. """ user = UserController(g.user.id).get(id=g.user.id) categories = { cat.id: cat.dump() for cat in CategoryController(g.user.id).read() } response = make_response( render_template('opml.xml', user=user, categories=categories, now=datetime.datetime.now())) response.headers['Content-Type'] = 'application/xml' response.headers['Content-Disposition'] = 'attachment; filename=feeds.opml' return response
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 form(category_id=None): action = gettext("Add a category") head_titles = [action] if category_id is None: return render_template('edit_category.html', action=action, head_titles=head_titles, form=CategoryForm()) category = CategoryController(current_user.id).get(id=category_id) action = gettext('Edit category') head_titles = [action] if category.name: head_titles.append(category.name) return render_template('edit_category.html', action=action, head_titles=head_titles, category=category, form=CategoryForm(obj=category))
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 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) articles = ArticleController(user_id) \ .read(feed_id=feed_id) \ .order_by(desc("date")).all() top_words = misc_utils.top_words(articles, n=50, size=int(word_size)) tag_cloud = misc_utils.tag_cloud(top_words) today = datetime.now() try: last_article = articles[0].date first_article = articles[-1].date delta = last_article - first_article average = round(float(len(articles)) / abs(delta.days), 2) except: 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, articles=articles, tag_cloud=tag_cloud, first_post_date=first_article, end_post_date=last_article, category=category, average=average, delta=delta, elapsed=elapsed)