Changeset 549 in code for trunk/msgstore_fs.go


Ignore:
Timestamp:
Jun 2, 2021, 6:32:11 PM (4 years ago)
Author:
contact
Message:

Implement CHATHISTORY TARGETS

References: https://github.com/ircv3/ircv3-specifications/pull/450

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/msgstore_fs.go

    r517 r549  
    77        "os"
    88        "path/filepath"
     9        "sort"
    910        "strings"
    1011        "time"
     
    394395}
    395396
    396 func truncateDay(t time.Time) time.Time {
    397         year, month, day := t.Date()
    398         return time.Date(year, month, day, 0, 0, 0, 0, t.Location())
    399 }
    400 
    401397func (ms *fsMessageStore) LoadLatestID(network *network, entity, id string, limit int) ([]*irc.Message, error) {
    402398        var afterTime time.Time
     
    442438        return history[remaining:], nil
    443439}
     440
     441func (ms *fsMessageStore) ListTargets(network *network, start, end time.Time, limit int) ([]chatHistoryTarget, error) {
     442        rootPath := filepath.Join(ms.root, escapeFilename.Replace(network.GetName()))
     443        root, err := os.Open(rootPath)
     444        if err != nil {
     445                return nil, err
     446        }
     447
     448        // The returned targets are escaped, and there is no way to un-escape
     449        // TODO: switch to ReadDir (Go 1.16+)
     450        targetNames, err := root.Readdirnames(0)
     451        root.Close()
     452        if err != nil {
     453                return nil, err
     454        }
     455
     456        var targets []chatHistoryTarget
     457        for _, target := range targetNames {
     458                // target is already escaped here
     459                targetPath := filepath.Join(rootPath, target)
     460                targetDir, err := os.Open(targetPath)
     461                if err != nil {
     462                        return nil, err
     463                }
     464
     465                entries, err := targetDir.Readdir(0)
     466                targetDir.Close()
     467                if err != nil {
     468                        return nil, err
     469                }
     470
     471                // We use mtime here, which may give imprecise or incorrect results
     472                var t time.Time
     473                for _, entry := range entries {
     474                        if entry.ModTime().After(t) {
     475                                t = entry.ModTime()
     476                        }
     477                }
     478
     479                // The timestamps we get from logs have second granularity
     480                t = truncateSecond(t)
     481
     482                // Filter out targets that don't fullfil the time bounds
     483                if !isTimeBetween(t, start, end) {
     484                        continue
     485                }
     486
     487                targets = append(targets, chatHistoryTarget{
     488                        Name:          target,
     489                        LatestMessage: t,
     490                })
     491        }
     492
     493        // Sort targets by latest message time, backwards or forwards depending on
     494        // the order of the time bounds
     495        sort.Slice(targets, func(i, j int) bool {
     496                t1, t2 := targets[i].LatestMessage, targets[j].LatestMessage
     497                if start.Before(end) {
     498                        return t1.Before(t2)
     499                } else {
     500                        return !t1.Before(t2)
     501                }
     502        })
     503
     504        // Truncate the result if necessary
     505        if len(targets) > limit {
     506                targets = targets[:limit]
     507        }
     508
     509        return targets, nil
     510}
     511
     512func truncateDay(t time.Time) time.Time {
     513        year, month, day := t.Date()
     514        return time.Date(year, month, day, 0, 0, 0, 0, t.Location())
     515}
     516
     517func truncateSecond(t time.Time) time.Time {
     518        year, month, day := t.Date()
     519        return time.Date(year, month, day, t.Hour(), t.Minute(), t.Second(), 0, t.Location())
     520}
     521
     522func isTimeBetween(t, start, end time.Time) bool {
     523        if end.Before(start) {
     524                end, start = start, end
     525        }
     526        return start.Before(t) && t.Before(end)
     527}
Note: See TracChangeset for help on using the changeset viewer.