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 }
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 }
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 }
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 }
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 }
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 }
func (ae ArticleExtract) Validate() error { if ae.data.ArticleId == 0 { return content.NewValidationError(errors.New("Article extract has no article id")) } return nil }
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 }
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 }
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 }
func (asc ArticleScores) Validate() error { if asc.data.ArticleId == 0 { return content.NewValidationError(errors.New("Article scores has no article id")) } return nil }
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 }
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 }
func (d Domain) Validate() error { if d.url == nil { return content.NewValidationError(errors.New("No url")) } return nil }
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 }
func (uf UserFeed) Validate() error { if uf.user == nil || uf.user.Data().Login == "" { return content.NewValidationError(errors.New("UserFeed has no user")) } return nil }
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 }
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 }
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 }
func (at ArticleThumbnail) Validate() error { if at.data.ArticleId == 0 { return content.NewValidationError(errors.New("Article thumbnail has no article id")) } return nil }
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() }
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) }
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() }
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() }
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 }
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 }
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 }
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 }
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() }
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) } }