Example #1
0
// Translated from nzedb Binaries.php and pynab handling
// Save all messages that match a basic regex as segments and
func saveOverviewBatch(dbh *db.Handle, group string, overviews []nntp.MessageOverview, missed types.MessageNumberSet) error {
	parts := map[string]*types.Part{}

	for _, o := range overviews {
		//TODO: make this a function call
		if blacklistRegexp.MatchString(o.Subject) {
			continue
		}
		m := segmentRegexp.FindStringSubmatch(o.Subject)
		if m != nil {
			subj := m[1]
			if !yencRegexp.MatchString(subj) {
				subj += " yEnc"
			}
			segNum, _ := strconv.Atoi(m[2])
			segTotal, _ := strconv.Atoi(m[3])

			hash := hashOverview(subj, o.From, group, segTotal)
			seg := types.Segment{
				MessageID: o.MessageID,
				Segment:   segNum,
				Size:      int64(o.Bytes),
			}
			if part, ok := parts[hash]; ok {
				part.Segments = append(part.Segments, seg)
			} else {
				parts[hash] = &types.Part{
					Hash:          hash,
					Subject:       subj,
					Posted:        o.Date,
					From:          o.From,
					GroupName:     group,
					TotalSegments: segTotal,
					Xref:          o.Xref(),
					Segments:      []types.Segment{seg},
				}
			}
		}
	}
	mm := make([]types.MissedMessage, missed.Cardinality())
	i := 0
	for id := range missed.Iter() {
		mm[i] = types.MissedMessage{
			MessageNumber: int64(id),
			GroupName:     group,
			Attempts:      1,
		}
		i++
	}
	logrus.Debugf("Found %d new parts, %d missed messages", len(parts), len(mm))
	return dbh.SavePartsAndMissedMessages(parts, mm)
}
Example #2
0
// GroupScanForward looks for new messages in a particular Group.
// Returns the number of articles scanned and if an error was encountered
func (n *NNTPClient) GroupScanForward(dbh *db.Handle, group string, limit int) (int, error) {
	ctxLogger := logrus.WithFields(
		logrus.Fields{
			"group": group,
		},
	)
	nntpGroup, err := n.c.Group(group)
	if err != nil {
		return 0, err
	}
	g, err := dbh.FindGroupByName(group)
	if err != nil {
		return 0, err
	}
	if g.First == 0 {
		ctxLogger.Infof("DB Group First not set, setting to lowest message in group: %d", nntpGroup.Low)
		g.First = nntpGroup.Low
	}
	if g.Last == 0 {
		if limit > 0 {
			ctxLogger.Infof("DB Group Last seen not set, setting to most recent message minus max to fetch: %d", nntpGroup.High-int64(limit))
			g.Last = nntpGroup.High - int64(limit)
		} else {
			ctxLogger.Infof("DB Group Last seen not set and no limit given, using default of %d", defaultMaxOverview)
			g.Last = nntpGroup.High - defaultMaxOverview
			if g.Last < nntpGroup.Low {
				g.Last = nntpGroup.Low
			}
		}
	}
	if g.First < nntpGroup.Low {
		ctxLogger.Infof("Group %s first article was older than first on server (%d < %d), resetting to %d", g.Name, g.First, nntpGroup.Low, nntpGroup.Low)
		g.First = nntpGroup.Low
	}
	if g.Last > nntpGroup.High {
		ctxLogger.Errorf("Group %s last article is newer than on server (%d > %d), resetting to %d.", g.Name, g.Last, nntpGroup.High, nntpGroup.High)
		g.Last = nntpGroup.High
	}
	err = dbh.DB.Save(g).Error
	if err != nil {
		return 0, err
	}

	newMessages := nntpGroup.High - g.Last
	var maxToGet int64
	if limit > 0 {
		maxToGet = g.Last + int64(limit)
	} else {
		maxToGet = nntpGroup.High
	}
	if maxToGet > nntpGroup.High {
		maxToGet = nntpGroup.High
	}
	if newMessages < 1 {
		ctxLogger.Info("No new articles")
		return 0, nil
	}
	ctxLogger.Infof("%d new articles limited to getting just %d (%d - %d) in %d article chunks", newMessages, maxToGet-g.Last, g.Last, maxToGet, n.MaxScan)
	begin := g.Last + 1
	totalArticles := 0
	missedMessages := 0
	remaining := newMessages
	for begin < maxToGet {
		toGet := begin + int64(n.MaxScan) - 1
		if toGet > maxToGet {
			toGet = maxToGet
		}
		if toGet < begin {
			toGet = begin
		}
		remaining = remaining - toGet
		ctxLogger.Debugf("Getting %d-%d (%d remaining)", begin, toGet, remaining)
		overviews, err := n.c.Overview(begin, toGet)
		if err != nil {
			return len(overviews), err
		}
		var mm types.MessageNumberSet
		if n.SaveMissed {
			mm = findMissingMessages(begin, toGet, overviews)
			missedMessages = missedMessages + mm.Cardinality()
			ctxLogger.Debugf("Got %d messages and %d missed messages", len(overviews), mm.Cardinality())
		} else {
			ctxLogger.Debugf("Got %d messages", len(overviews))
		}
		totalArticles = totalArticles + len(overviews)
		ctxLogger.Debugf("Saving parts and messages to db.")
		err = saveOverviewBatch(dbh, g.Name, overviews, mm)
		if err != nil {
			return len(overviews), err
		}
		begin = toGet + 1
		g.Last = toGet

		err = dbh.DB.Save(g).Error
		if err != nil {
			return 0, err
		}
	}
	if n.SaveMissed {
		ctxLogger.Infof("Got %d messages and %d missed messages", totalArticles, missedMessages)
	} else {
		ctxLogger.Debugf("Got %d messages", totalArticles)
	}
	err = dbh.DB.Save(g).Error
	if err != nil {
		return 0, err
	}

	return totalArticles, nil
}