Beispiel #1
0
func (t *Tag) Validate() error {
	if t.data.Value == "" {
		return content.NewValidationError(errors.New("Tag has no value"))
	}

	if t.user == nil || t.user.Data().Login == "" {
		return content.NewValidationError(errors.New("Tag has no user"))
	}

	return nil
}
Beispiel #2
0
func (f Feed) Validate() error {
	if f.data.Link == "" {
		return content.NewValidationError(errors.New("Feed has no link"))
	}

	if u, err := url.Parse(f.data.Link); err != nil || !u.IsAbs() {
		return content.NewValidationError(errors.New("Feed has no link"))
	}

	return nil
}
Beispiel #3
0
func (a Article) Validate() error {
	if a.data.FeedId == 0 {
		return content.NewValidationError(errors.New("Article has no feed id"))
	}

	if !a.data.Guid.Valid && a.data.Link == "" {
		return content.NewValidationError(errors.New("Article has no guid or link"))
	}

	return nil
}
Beispiel #4
0
func (u User) Validate() error {
	if u.data.Login == "" {
		return content.NewValidationError(errors.New("Invalid user login"))
	}
	if u.data.Email != "" {
		if _, err := mail.ParseAddress(u.String()); err != nil {
			return content.NewValidationError(err)
		}
	}

	return nil
}
Beispiel #5
0
func (s *Subscription) Validate() error {
	if s.data.Link == "" {
		return content.NewValidationError(errors.New("No subscription link"))
	}

	if u, err := url.Parse(s.data.Link); err != nil || !u.IsAbs() {
		return content.NewValidationError(errors.New("Invalid subscription link"))
	}

	if s.data.FeedId == 0 {
		return content.NewValidationError(errors.New("Invalid feed id"))
	}

	return nil
}
Beispiel #6
0
func (uf *UserFeed) UnreadArticles(paging ...int) (ua []content.UserArticle) {
	if uf.HasErr() {
		return
	}

	if err := uf.Validate(); err != nil {
		uf.Err(err)
		return
	}

	id := uf.Data().Id
	if id == 0 {
		uf.Err(content.NewValidationError(errors.New("Invalid feed id")))
		return
	}

	uf.logger.Infof("Getting unread articles for feed %d\n", id)

	articles := uf.getArticles("ar.article_id IS NULL", "", paging...)
	ua = make([]content.UserArticle, len(articles))
	for i := range articles {
		ua[i] = articles[i]
	}

	return
}
Beispiel #7
0
func (ae ArticleExtract) Validate() error {
	if ae.data.ArticleId == 0 {
		return content.NewValidationError(errors.New("Article extract has no article id"))
	}

	return nil
}
Beispiel #8
0
func (a *Article) Extract() (ae content.ArticleExtract) {
	ae = a.Repo().ArticleExtract()
	if a.HasErr() {
		ae.Err(a.Err())
		return
	}

	id := a.Data().Id
	if id == 0 {
		a.Err(content.NewValidationError(errors.New("Invalid article id")))
		return
	}

	a.logger.Infof("Getting article '%d' extract\n", id)

	var i data.ArticleExtract
	if err := a.db.Get(&i, a.db.SQL().Article.GetExtract, id); err != nil {
		if err == sql.ErrNoRows {
			err = content.ErrNoContent
		}
		ae.Err(err)
	}

	i.ArticleId = id
	ae.Data(i)

	return
}
Beispiel #9
0
func (a *Article) Thumbnail() (at content.ArticleThumbnail) {
	at = a.Repo().ArticleThumbnail()
	if a.HasErr() {
		at.Err(a.Err())
		return
	}

	id := a.Data().Id
	if id == 0 {
		a.Err(content.NewValidationError(errors.New("Invalid article id")))
		return
	}

	a.logger.Infof("Getting article '%d' thumbnail\n", id)

	var i data.ArticleThumbnail
	if err := a.db.Get(&i, a.db.SQL().Article.GetThumbnail, id); err != nil {
		if err == sql.ErrNoRows {
			err = content.ErrNoContent
		}
		at.Err(err)
	}

	i.ArticleId = id
	at.Data(i)

	return
}
Beispiel #10
0
func (f *Feed) Subscription() (s content.Subscription) {
	s = f.Repo().Subscription()
	if f.HasErr() {
		s.Err(f.Err())
		return
	}

	id := f.Data().Id
	if id == 0 {
		f.Err(content.NewValidationError(errors.New("Invalid feed id")))
		return
	}

	f.logger.Infof("Getting subcription for feed %d\n", id)

	var in data.Subscription
	if err := f.db.Get(&in, f.db.SQL().Feed.GetHubbubSubscription, id); err != nil {
		if err == sql.ErrNoRows {
			err = content.ErrNoContent
		}
		s.Err(err)
	}

	in.FeedId = id
	s.Data(in)

	return
}
Beispiel #11
0
func (asc ArticleScores) Validate() error {
	if asc.data.ArticleId == 0 {
		return content.NewValidationError(errors.New("Article scores has no article id"))
	}

	return nil
}
Beispiel #12
0
func (sa *ScoredArticle) Scores() (asc content.ArticleScores) {
	asc = sa.Repo().ArticleScores()
	if sa.HasErr() {
		asc.Err(sa.Err())
		return
	}

	id := sa.Data().Id
	if id == 0 {
		sa.Err(content.NewValidationError(errors.New("Invalid article id")))
		return
	}

	sa.logger.Infof("Getting article '%d' scores\n", id)

	var i data.ArticleScores
	if err := sa.db.Get(&i, sa.db.SQL("get_article_scores"), id); err != nil {
		if err == sql.ErrNoRows {
			err = content.ErrNoContent
		}
		asc.Err(err)
	}

	i.ArticleId = id
	asc.Data(i)

	return
}
Beispiel #13
0
func (f *Feed) Users() (u []content.User) {
	if f.HasErr() {
		return
	}

	id := f.Data().Id
	if id == 0 {
		f.Err(content.NewValidationError(errors.New("Invalid feed id")))
		return
	}

	f.logger.Infof("Getting users for feed %d\n", id)

	var in []data.User
	if err := f.db.Select(&in, f.db.SQL().Feed.GetUsers, id); err != nil {
		f.Err(err)
		return
	}

	u = make([]content.User, len(in))
	for i := range in {
		u[i] = f.Repo().User()
		u[i].Data(in[i])

		if u[i].HasErr() {
			f.Err(u[i].Err())
			return
		}
	}

	return
}
Beispiel #14
0
func (d Domain) Validate() error {
	if d.url == nil {
		return content.NewValidationError(errors.New("No url"))
	}

	return nil
}
Beispiel #15
0
func (uf *UserFeed) Articles(o ...data.ArticleQueryOptions) (ua []content.UserArticle) {
	if uf.HasErr() {
		return
	}

	if err := uf.Validate(); err != nil {
		uf.Err(err)
		return
	}

	id := uf.Data().Id
	if id == 0 {
		uf.Err(content.NewValidationError(errors.New("Invalid feed id")))
		return
	}

	var opts data.ArticleQueryOptions
	if len(o) > 0 {
		opts = o[0]
	}

	uf.logger.Infof("Getting articles for feed %d with options: %#v\n", id, opts)

	where := "uf.feed_id = $2"

	u := uf.User()
	ua = getArticles(u, uf.db, uf.logger, opts, uf, "", where, []interface{}{uf.Data().Id})

	if u.HasErr() {
		uf.Err(u.Err())
	}

	return
}
Beispiel #16
0
func (uf UserFeed) Validate() error {
	if uf.user == nil || uf.user.Data().Login == "" {
		return content.NewValidationError(errors.New("UserFeed has no user"))
	}

	return nil
}
Beispiel #17
0
func (a *Article) Scores() (as content.ArticleScores) {
	as = a.Repo().ArticleScores()
	if a.HasErr() {
		as.Err(a.Err())
		return
	}

	id := a.Data().Id
	if id == 0 {
		a.Err(content.NewValidationError(errors.New("Invalid article id")))
		return
	}

	a.logger.Infof("Getting article '%d' scores\n", id)

	var i data.ArticleScores
	if err := a.db.Get(&i, a.db.SQL().Article.GetScores, id); err != nil {
		if err == sql.ErrNoRows {
			err = content.ErrNoContent
		}
		as.Err(err)
	}

	i.ArticleId = id
	as.Data(i)

	return
}
Beispiel #18
0
func (f *Feed) AddArticles(articles []content.Article) {
	if f.HasErr() {
		return
	}

	id := f.Data().Id
	if id == 0 {
		f.Err(content.NewValidationError(errors.New("Invalid feed id")))
		return
	}

	f.logger.Infof("Adding %d articles to feed %d\n", len(articles), id)

	tx, err := f.db.Beginx()
	if err != nil {
		f.Err(err)
		return
	}
	defer tx.Rollback()

	newArticles := f.updateFeedArticles(tx, articles)

	if f.HasErr() {
		return
	}

	tx.Commit()

	f.newArticles = newArticles
}
Beispiel #19
0
func (f *Feed) LatestArticles() (a []content.Article) {
	if f.HasErr() {
		return
	}

	id := f.Data().Id
	if id == 0 {
		f.Err(content.NewValidationError(errors.New("Invalid feed id")))
		return
	}

	f.logger.Infof("Getting latest feed %d articles\n", id)

	var data []data.Article
	if err := f.db.Select(&data, f.db.SQL().Feed.GetLatestArticles, id); err != nil {
		f.Err(err)
		return
	}

	a = make([]content.Article, len(data))
	for i := range data {
		a[i] = f.Repo().Article()
		a[i].Data(data[i])
	}

	return
}
Beispiel #20
0
func (at ArticleThumbnail) Validate() error {
	if at.data.ArticleId == 0 {
		return content.NewValidationError(errors.New("Article thumbnail has no article id"))
	}

	return nil
}
Beispiel #21
0
func (uf *UserFeed) ReadBefore(date time.Time, read bool) {
	if uf.HasErr() {
		return
	}

	if err := uf.Validate(); err != nil {
		uf.Err(err)
		return
	}

	id := uf.Data().Id
	if id == 0 {
		uf.Err(content.NewValidationError(errors.New("Invalid feed id")))
		return
	}

	login := uf.User().Data().Login
	uf.logger.Infof("Marking user %s feed %d articles before %v as read: %v\n", login, id, date, read)

	tx, err := uf.db.Beginx()
	if err != nil {
		uf.Err(err)
		return
	}
	defer tx.Rollback()

	stmt, err := tx.Preparex(uf.db.SQL("delete_all_users_articles_read_by_feed_date"))
	if err != nil {
		uf.Err(err)
		return
	}
	defer stmt.Close()

	_, err = stmt.Exec(login, id, date)
	if err != nil {
		uf.Err(err)
		return
	}

	if read {
		stmt, err = tx.Preparex(uf.db.SQL("create_all_users_articles_read_by_feed_date"))
		if err != nil {
			uf.Err(err)
			return
		}
		defer stmt.Close()

		_, err = stmt.Exec(login, id, date)
		if err != nil {
			uf.Err(err)
			return
		}
	}

	tx.Commit()
}
Beispiel #22
0
func (ua *UserArticle) Read(read bool) {
	if ua.HasErr() {
		return
	}

	d := ua.Data()
	if d.Id == 0 {
		ua.Err(content.NewValidationError(errors.New("Invalid article id")))
		return
	}

	login := ua.User().Data().Login
	ua.logger.Infof("Marking user '%s' article '%d' as read: %v\n", login, d.Id, read)

	tx, err := ua.db.Beginx()
	if err != nil {
		ua.Err(err)
		return
	}
	defer tx.Rollback()

	stmt, err := tx.Preparex(ua.db.SQL("delete_user_article_read"))

	if err != nil {
		ua.Err(err)
		return
	}
	defer stmt.Close()

	_, err = stmt.Exec(login, d.Id)
	if err != nil {
		ua.Err(err)
		return
	}

	d.Read = read

	if read {
		stmt, err = tx.Preparex(ua.db.SQL("create_user_article_read"))
		if err != nil {
			ua.Err(err)
			return
		}
		defer stmt.Close()

		_, err = stmt.Exec(login, d.Id)
		ua.Err(err)
	}

	tx.Commit()

	ua.Data(d)
}
Beispiel #23
0
func (uf *UserFeed) Detach() {
	if uf.HasErr() {
		return
	}

	if err := uf.Validate(); err != nil {
		uf.Err(err)
		return
	}

	id := uf.Data().Id
	if id == 0 {
		uf.Err(content.NewValidationError(errors.New("Invalid feed id")))
		return
	}

	login := uf.User().Data().Login
	uf.logger.Infof("Detaching feed %d from user %s\n", id, login)

	tx, err := uf.db.Beginx()
	if err != nil {
		uf.Err(err)
		return
	}
	defer tx.Rollback()

	stmt, err := tx.Preparex(uf.db.SQL().Feed.Detach)
	if err != nil {
		uf.Err(err)
		return
	}
	defer stmt.Close()

	_, err = stmt.Exec(login, id)
	if err != nil {
		uf.Err(err)
		return
	}

	tx.Commit()
}
Beispiel #24
0
func (f *Feed) Delete() {
	if f.HasErr() {
		return
	}

	if err := f.Validate(); err != nil {
		f.Err(err)
		return
	}

	id := f.Data().Id
	if id == 0 {
		f.Err(content.NewValidationError(errors.New("Invalid feed id")))
		return
	}

	f.logger.Infof("Deleting feed %d\n", id)

	tx, err := f.db.Beginx()
	if err != nil {
		f.Err(err)
		return
	}
	defer tx.Rollback()

	stmt, err := tx.Preparex(f.db.SQL().Feed.Delete)
	if err != nil {
		f.Err(err)
		return
	}
	defer stmt.Close()

	_, err = stmt.Exec(id)
	if err != nil {
		f.Err(err)
		return
	}

	tx.Commit()
}
Beispiel #25
0
func (tf *TaggedFeed) Tags(tags ...[]content.Tag) []content.Tag {
	if len(tags) > 0 {
		tf.tags = tags[0]
		tf.initialized = true
		return tf.tags
	}

	if !tf.initialized {
		if err := tf.Validate(); err != nil {
			tf.Err(err)
			return tf.tags
		}

		id := tf.Data().Id
		if id == 0 {
			tf.Err(content.NewValidationError(errors.New("Invalid feed id")))
			return tf.tags
		}

		login := tf.User().Data().Login
		tf.logger.Infof("Getting tags for user %s and feed '%d'\n", login, id)

		var tagData []data.Tag
		if err := tf.db.Select(&tagData, tf.db.SQL().Feed.GetUserTags, login, id); err != nil {
			tf.Err(err)
			return []content.Tag{}
		}

		for _, d := range tagData {
			tag := tf.Repo().Tag(tf.User())
			tag.Data(d)
			tf.tags = append(tf.tags, tag)
		}
		tf.initialized = true
	}

	return tf.tags
}
Beispiel #26
0
func (uf *UserFeed) Query(term string, index bleve.Index, paging ...int) (ua []content.UserArticle) {
	if uf.HasErr() {
		return
	}

	if err := uf.Validate(); err != nil {
		uf.Err(err)
		return
	}

	id := uf.Data().Id
	if id == 0 {
		uf.Err(content.NewValidationError(errors.New("Invalid feed id")))
		return
	}

	var err error

	ua, err = query(term, uf.Highlight(), index, uf.User(), []data.FeedId{id}, paging...)
	uf.Err(err)

	return
}
Beispiel #27
0
func (uf *UserFeed) ScoredArticles(from, to time.Time, paging ...int) (sa []content.ScoredArticle) {
	if uf.HasErr() {
		return
	}

	if err := uf.Validate(); err != nil {
		uf.Err(err)
		return
	}

	u := uf.User()
	id := uf.Data().Id
	if id == 0 {
		uf.Err(content.NewValidationError(errors.New("Invalid feed id")))
		return
	}

	login := u.Data().Login
	uf.logger.Infof("Getting scored articles for user %s feed %d between %v and %v\n", login, id, from, to)

	order := ""
	if uf.Order() == data.DescendingOrder {
		order = " DESC"
	}
	ua := getArticles(u, uf.db, uf.logger, uf, "asco.score",
		"INNER JOIN articles_scores asco ON a.id = asco.article_id",
		"uf.feed_id = $2 AND a.date > $3 AND a.date <= $4", "asco.score"+order,
		[]interface{}{id, from, to}, paging...)

	sa = make([]content.ScoredArticle, len(ua))
	for i := range ua {
		sa[i] = uf.Repo().ScoredArticle()
		sa[i].Data(ua[i].Data())
	}

	return
}
Beispiel #28
0
func (uf *UserFeed) Query(term string, sp content.SearchProvider, paging ...int) (ua []content.UserArticle) {
	if uf.HasErr() {
		return
	}

	if err := uf.Validate(); err != nil {
		uf.Err(err)
		return
	}

	id := uf.Data().Id
	if id == 0 {
		uf.Err(content.NewValidationError(errors.New("Invalid feed id")))
		return
	}

	var err error

	limit, offset := pagingLimit(paging)
	ua, err = sp.Search(term, uf.User(), []data.FeedId{id}, limit, offset)
	uf.Err(err)

	return
}
Beispiel #29
0
func (tf *TaggedFeed) UpdateTags() {
	if tf.HasErr() {
		return
	}

	if err := tf.Validate(); err != nil {
		tf.Err(err)
		return
	}

	id := tf.Data().Id
	s := tf.db.SQL()
	u := tf.User()
	if id == 0 {
		tf.Err(content.NewValidationError(errors.New("Invalid feed id")))
		return
	}

	login := u.Data().Login
	tf.logger.Infof("Deleting all tags for feed %d\n", id)

	tx, err := tf.db.Beginx()
	if err != nil {
		tf.Err(err)
		return
	}
	defer tx.Rollback()

	stmt, err := tx.Preparex(s.Feed.DeleteUserTags)
	if err != nil {
		tf.Err(err)
		return
	}
	defer stmt.Close()

	_, err = stmt.Exec(login, id)
	if err != nil {
		tf.Err(fmt.Errorf("Error deleting user feed tags: %v", err))
		return
	}

	tags := tf.Tags()
	for i := range tags {
		tagData := tags[i].Data()
		if tagData.Id == 0 {
			t := u.TagByValue(tagData.Value)
			if t.HasErr() {
				err := t.Err()
				if err != content.ErrNoContent {
					tf.Err(t.Err())
					return
				}
			} else {
				tagData.Id = t.Data().Id
				tags[i].Data(tagData)
			}
		}
	}

	if len(tags) > 0 {
		id := tf.Data().Id
		tf.logger.Infof("Adding tags for feed %d\n", id)

		stmt, err := tx.Preparex(s.Feed.CreateUserTag)
		if err != nil {
			tf.Err(err)
			return
		}
		defer stmt.Close()

		for i := range tags {
			if err := tags[i].Validate(); err != nil {
				tf.Err(err)
				return
			}

			tagData := tags[i].Data()

			if tagData.Id == 0 {
				tagId, err := tf.db.CreateWithId(tx, s.Tag.Create, tagData.Value)
				if err != nil {
					tf.Err(err)
					return
				}
				tagData.Id = data.TagId(tagId)
			}

			_, err = stmt.Exec(login, id, tagData.Id)
			if err != nil {
				tf.Err(fmt.Errorf("Error adding user feed tag for user %s, feed %d, and tag %s: %v", login, id, tagData.Value, err))
				return
			}
		}
	}

	stmt, err = tx.Preparex(s.Tag.DeleteStale)
	if err != nil {
		tf.Err(err)
		return
	}
	defer stmt.Close()

	_, err = stmt.Exec()
	if err != nil {
		tf.Err(fmt.Errorf("Error deleting stale tags: %v", err))
		return
	}

	tx.Commit()
}
Beispiel #30
0
func (f *Feed) SetNewArticlesUnread() {
	if f.HasErr() {
		return
	}

	if err := f.Validate(); err != nil {
		f.Err(err)
		return
	}

	id := f.Data().Id
	if id == 0 {
		f.Err(content.NewValidationError(errors.New("Invalid feed id")))
		return
	}

	articles := f.NewArticles()
	if len(articles) == 0 {
		return
	}

	var err error
	if readStateInsertFeedTemplate == nil {
		readStateInsertFeedTemplate, err = template.New("read-state-insert-feed-sql").
			Parse(f.db.SQL().Feed.ReadStateInsertTemplate)

		if err != nil {
			f.Err(fmt.Errorf("Error generating read-state-insert-feed template: %v", err))
			return
		}
	}

	f.logger.Infof("Setting new articles from feed %d as unread for all related users\n", id)

	args := make([]interface{}, len(articles)+1)
	placeholders := make([]string, len(articles))

	args[0] = id
	for i := range articles {
		args[i+1] = articles[i].Data().Id
		placeholders[i] = fmt.Sprintf("$%d", i+2)
	}

	buf := util.BufferPool.GetBuffer()
	defer util.BufferPool.Put(buf)

	data := readStateInsertFeedData{NewArticleIds: strings.Join(placeholders, ", ")}

	if err := readStateInsertFeedTemplate.Execute(buf, data); err != nil {
		f.Err(fmt.Errorf("Error executing read-state-insert-feed template: %v", err))
		return
	}

	sql := buf.String()
	f.logger.Debugf("Read state insert feed SQL:\n%s\nArgs:%q\n", sql, args)

	tx, err := f.db.Beginx()
	if err != nil {
		f.Err(err)
		return
	}
	defer tx.Rollback()

	stmt, err := tx.Preparex(sql)
	if err != nil {
		f.Err(err)
		return
	}
	defer stmt.Close()

	_, err = stmt.Exec(args...)
	if err != nil {
		f.Err(err)
		return
	}

	if err := tx.Commit(); err != nil {
		f.Err(err)
	}
}