func AddFeed(transaction mysql.Transaction, uri string) (uint64, error) { doc := xmlx.New() if err := doc.LoadUriClient(uri, http.DefaultClient, CharsetReader); err != nil { return 0, errors.New("Unable to load URI: " + uri) } getTitle := func() string { title := doc.Root.S("*", "title") if title == "" { title = doc.SelectNode("*", "channel").S("*", "title") } return title } getDescription := func() string { description := doc.Root.S("*", "subtitle") if description == "" { description = doc.SelectNode("*", "channel").S("*", "description") } return description } getLink := func() string { link := "" for _, node := range doc.SelectNodes("*", "link") { if node.As("", "rel") == "alternate" { link = node.As("", "href") } } if link == "" { link = doc.SelectNode("*", "channel").S("*", "link") } return link } _, res, err := transaction.Query("INSERT INTO `feed`(`title`,`description`,`link`,`last_update`,`feedURL`) VALUES ('%s','%s','%s',0,'%s')", getTitle(), getDescription(), getLink(), uri) if err != nil { return 0, err } feedId := res.InsertId() if err := UpdateFeedDocument(transaction, feedId, doc); err != nil { return 0, err } return feedId, nil }
// Begin begins a transaction and calls f to complete it . // If f returns an error and IsNetErr(error) == true it reconnects and calls // f up to MaxRetries times. If error is of type *mysql.Error it tries rollback // the transaction. func (c *Conn) Begin(f func(mysql.Transaction, ...interface{}) error, args ...interface{}) error { err := c.connectIfNotConnected() if err != nil { return err } nn := 0 for { var tr mysql.Transaction if tr, err = c.Raw.Begin(); err == nil { if err = f(tr, args...); err == nil { return nil } } if c.reconnectIfNetErr(&nn, &err); err != nil { if _, ok := err.(*mysql.Error); ok && tr.IsValid() { tr.Rollback() } return err } } panic(nil) }
func updatePriorities(transaction mysql.Transaction, userId int, newPriorities map[string]GroupInfo) error { for feedIdStr, priority := range newPriorities { feedId, err := strconv.ParseInt(feedIdStr, 10, 64) if err != nil { return err } _, _, err = transaction.Query("UPDATE `user_feed` SET `priority`=%d, `group`='%s' WHERE feed_id=%d AND user_id=%d", priority.Priority, gConn.Escape(priority.Group), feedId, userId) if err != nil { return err } } return nil }
func UpdateFeedDocument(transaction mysql.Transaction, feedId uint64, doc *xmlx.Document) (retErr error) { defer func() { if e := recover(); e != nil { retErr = e.(error) } }() const ns = "*" findFeedEntry := func(title string, content string, date string, guid string) bool { search := "" if len(guid) > 0 { search = fmt.Sprintf("`guid`='%s'", gConn.Escape(guid)) } else { where := make([]string, 0) if len(date) > 0 { where = append(where, fmt.Sprintf("`published`='%s'", gConn.Escape(date))) } if len(content) > 0 { where = append(where, fmt.Sprintf("`content`='%s'", gConn.Escape(content))) } if len(title) > 0 { where = append(where, fmt.Sprintf("`title`='%s'", gConn.Escape(title))) } if len(where) == 0 { panic(fmt.Sprintf("Can not search item! %s", title)) } search = strings.Join(where, " OR ") } rows, _, err := transaction.Query("SELECT `id` FROM `feed_entry` WHERE `feed_id`=%d AND (%s)", feedId, search) if err != nil { panic(err) } if len(rows) > 1 { ids := make([]string, len(rows)) for i, row := range rows { ids[i] = row.Str(0) } err := fmt.Sprintf("Found more than one answer! (%s)", strings.Join(ids, ",")) panic(errors.New(err)) } return len(rows) == 1 } findItems(doc.Root, func(node *xmlx.Node) { content := getContent(node) link := getLink(node) author := getAuthor(node) guid := getGUID(node) title := node.S(ns, "title") published := node.S(ns, "pubDate") if len(published) == 0 { published = node.S(ns, "published") } parsedTime, err := parseTime(published) if err != nil { fmt.Printf("Warning: Failed to parse (%s)\n", published) } if parsedTime.After(time.Now()) { parsedTime = time.Now() } //Thanks VGCats! You have no content! http://www.vgcats.com/vgcats.rdf.xml //if content == "" { // panic(errors.New("Could not find content")) //} if findFeedEntry(title, content, published, guid) { return } _, _, err = transaction.Query("INSERT INTO `feed_entry`(`feed_id`,`title`,`content`,`published`,`updated`,`author`,`link`,`guid`) VALUES (%d,'%s','%s','%s',%d,'%s','%s','%s')", feedId, gConn.Escape(title), gConn.Escape(content), gConn.Escape(published), parsedTime.Unix(), gConn.Escape(author), gConn.Escape(link), gConn.Escape(guid)) if err != nil { panic(err) } _, _, err = transaction.Query("UPDATE `user_feed` SET `unread_items`=`unread_items`+1 WHERE `feed_id`=%d", feedId) if err != nil { panic(err) } }) return nil }