Changeset 516 in code


Ignore:
Timestamp:
May 18, 2021, 8:44:10 AM (4 years ago)
Author:
hubert
Message:

Implement CHATHISTORY BETWEEN

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/downstream.go

    r515 r516  
    18021802                        return err
    18031803                }
    1804                 var target, criteria, limitStr string
    1805                 if err := parseMessageParams(msg, nil, &target, &criteria, &limitStr); err != nil {
     1804                var target, limitStr string
     1805                var boundsStr [2]string
     1806                switch subcommand {
     1807                case "AFTER", "BEFORE":
     1808                        if err := parseMessageParams(msg, nil, &target, &boundsStr[0], &limitStr); err != nil {
     1809                                return err
     1810                        }
     1811                case "BETWEEN":
     1812                        if err := parseMessageParams(msg, nil, &target, &boundsStr[0], &boundsStr[1], &limitStr); err != nil {
     1813                                return err
     1814                        }
     1815                default:
     1816                        // TODO: support LATEST, AROUND
    18061817                        return ircError{&irc.Message{
    18071818                                Command: "FAIL",
    1808                                 Params:  []string{"CHATHISTORY", "NEED_MORE_PARAMS", subcommand, "Missing parameters"},
     1819                                Params:  []string{"CHATHISTORY", "INVALID_PARAMS", subcommand, "Unknown command"},
    18091820                        }}
    18101821                }
     
    18251836
    18261837                // TODO: support msgid criteria
    1827                 criteriaParts := strings.SplitN(criteria, "=", 2)
    1828                 if len(criteriaParts) != 2 || criteriaParts[0] != "timestamp" {
     1838                var bounds [2]time.Time
     1839                bounds[0] = parseChatHistoryBound(boundsStr[0])
     1840                if bounds[0].IsZero() {
    18291841                        return ircError{&irc.Message{
    18301842                                Command: "FAIL",
    1831                                 Params:  []string{"CHATHISTORY", "INVALID_PARAMS", subcommand, criteria, "Unknown criteria"},
     1843                                Params:  []string{"CHATHISTORY", "INVALID_PARAMS", subcommand, boundsStr[0], "Invalid first bound"},
    18321844                        }}
    18331845                }
    18341846
    1835                 timestamp, err := time.Parse(serverTimeLayout, criteriaParts[1])
    1836                 if err != nil {
    1837                         return ircError{&irc.Message{
    1838                                 Command: "FAIL",
    1839                                 Params:  []string{"CHATHISTORY", "INVALID_PARAMS", subcommand, criteria, "Invalid criteria"},
    1840                         }}
     1847                if boundsStr[1] != "" {
     1848                        bounds[1] = parseChatHistoryBound(boundsStr[1])
     1849                        if bounds[1].IsZero() {
     1850                                return ircError{&irc.Message{
     1851                                        Command: "FAIL",
     1852                                        Params:  []string{"CHATHISTORY", "INVALID_PARAMS", subcommand, boundsStr[1], "Invalid second bound"},
     1853                                }}
     1854                        }
    18411855                }
    18421856
     
    18521866                switch subcommand {
    18531867                case "BEFORE":
    1854                         history, err = store.LoadBeforeTime(uc.network, entity, timestamp, limit)
     1868                        history, err = store.LoadBeforeTime(uc.network, entity, bounds[0], time.Time{}, limit)
    18551869                case "AFTER":
    1856                         history, err = store.LoadAfterTime(uc.network, entity, timestamp, limit)
    1857                 default:
    1858                         // TODO: support LATEST, BETWEEN
    1859                         return ircError{&irc.Message{
    1860                                 Command: "FAIL",
    1861                                 Params:  []string{"CHATHISTORY", "UNKNOWN_COMMAND", subcommand, "Unknown command"},
    1862                         }}
     1870                        history, err = store.LoadAfterTime(uc.network, entity, bounds[0], time.Now(), limit)
     1871                case "BETWEEN":
     1872                        if bounds[0].Before(bounds[1]) {
     1873                                history, err = store.LoadAfterTime(uc.network, entity, bounds[0], bounds[1], limit)
     1874                        } else {
     1875                                history, err = store.LoadBeforeTime(uc.network, entity, bounds[0], bounds[1], limit)
     1876                        }
    18631877                }
    18641878                if err != nil {
  • trunk/irc.go

    r498 r516  
    55        "sort"
    66        "strings"
     7        "time"
    78        "unicode"
    89        "unicode/utf8"
     
    638639        }
    639640}
     641
     642// parseChatHistoryBound parses the given CHATHISTORY parameter as a bound.
     643// The zero time is returned on error.
     644func parseChatHistoryBound(param string) time.Time {
     645        parts := strings.SplitN(param, "=", 2)
     646        if len(parts) != 2 {
     647                return time.Time{}
     648        }
     649        switch parts[0] {
     650        case "timestamp":
     651                timestamp, err := time.Parse(serverTimeLayout, parts[1])
     652                if err != nil {
     653                        return time.Time{}
     654                }
     655                return timestamp
     656        default:
     657                return time.Time{}
     658        }
     659}
  • trunk/msgstore.go

    r488 r516  
    2727        messageStore
    2828
    29         LoadBeforeTime(network *network, entity string, t time.Time, limit int) ([]*irc.Message, error)
    30         LoadAfterTime(network *network, entity string, t time.Time, limit int) ([]*irc.Message, error)
     29        // LoadBeforeTime loads up to limit messages before start down to end. The
     30        // returned messages must be between and excluding the provided bounds.
     31        // end is before start.
     32        LoadBeforeTime(network *network, entity string, start, end time.Time, limit int) ([]*irc.Message, error)
     33        // LoadBeforeTime loads up to limit messages after start up to end. The
     34        // returned messages must be between and excluding the provided bounds.
     35        // end is after start.
     36        LoadAfterTime(network *network, entity string, start, end time.Time, limit int) ([]*irc.Message, error)
    3137}
    3238
  • trunk/msgstore_fs.go

    r515 r516  
    258258}
    259259
    260 func (ms *fsMessageStore) parseMessagesBefore(network *network, entity string, ref time.Time, limit int, afterOffset int64) ([]*irc.Message, error) {
     260func (ms *fsMessageStore) parseMessagesBefore(network *network, entity string, ref time.Time, end time.Time, limit int, afterOffset int64) ([]*irc.Message, error) {
    261261        path := ms.logPath(network, entity, ref)
    262262        f, err := os.Open(path)
     
    285285                if err != nil {
    286286                        return nil, err
    287                 } else if msg == nil {
     287                } else if msg == nil || !t.After(end) {
    288288                        continue
    289289                } else if !t.Before(ref) {
     
    314314}
    315315
    316 func (ms *fsMessageStore) parseMessagesAfter(network *network, entity string, ref time.Time, limit int) ([]*irc.Message, error) {
     316func (ms *fsMessageStore) parseMessagesAfter(network *network, entity string, ref time.Time, end time.Time, limit int) ([]*irc.Message, error) {
    317317        path := ms.logPath(network, entity, ref)
    318318        f, err := os.Open(path)
     
    333333                } else if msg == nil || !t.After(ref) {
    334334                        continue
     335                } else if !t.Before(end) {
     336                        break
    335337                }
    336338
     
    344346}
    345347
    346 func (ms *fsMessageStore) LoadBeforeTime(network *network, entity string, t time.Time, limit int) ([]*irc.Message, error) {
     348func (ms *fsMessageStore) LoadBeforeTime(network *network, entity string, start time.Time, end time.Time, limit int) ([]*irc.Message, error) {
    347349        history := make([]*irc.Message, limit)
    348350        remaining := limit
    349351        tries := 0
    350         for remaining > 0 && tries < fsMessageStoreMaxTries {
    351                 buf, err := ms.parseMessagesBefore(network, entity, t, remaining, -1)
     352        for remaining > 0 && tries < fsMessageStoreMaxTries && end.Before(start) {
     353                buf, err := ms.parseMessagesBefore(network, entity, start, end, remaining, -1)
    352354                if err != nil {
    353355                        return nil, err
     
    360362                copy(history[remaining-len(buf):], buf)
    361363                remaining -= len(buf)
    362                 year, month, day := t.Date()
    363                 t = time.Date(year, month, day, 0, 0, 0, 0, t.Location()).Add(-1)
     364                year, month, day := start.Date()
     365                start = time.Date(year, month, day, 0, 0, 0, 0, start.Location()).Add(-1)
    364366        }
    365367
     
    367369}
    368370
    369 func (ms *fsMessageStore) LoadAfterTime(network *network, entity string, t time.Time, limit int) ([]*irc.Message, error) {
     371func (ms *fsMessageStore) LoadAfterTime(network *network, entity string, start time.Time, end time.Time, limit int) ([]*irc.Message, error) {
    370372        var history []*irc.Message
    371373        remaining := limit
    372374        tries := 0
    373         now := time.Now()
    374         for remaining > 0 && tries < fsMessageStoreMaxTries && t.Before(now) {
    375                 buf, err := ms.parseMessagesAfter(network, entity, t, remaining)
     375        for remaining > 0 && tries < fsMessageStoreMaxTries && start.Before(end) {
     376                buf, err := ms.parseMessagesAfter(network, entity, start, end, remaining)
    376377                if err != nil {
    377378                        return nil, err
     
    384385                history = append(history, buf...)
    385386                remaining -= len(buf)
    386                 year, month, day := t.Date()
    387                 t = time.Date(year, month, day+1, 0, 0, 0, 0, t.Location())
     387                year, month, day := start.Date()
     388                start = time.Date(year, month, day+1, 0, 0, 0, 0, start.Location())
    388389        }
    389390        return history, nil
     
    421422                }
    422423
    423                 buf, err := ms.parseMessagesBefore(network, entity, t, remaining, offset)
     424                buf, err := ms.parseMessagesBefore(network, entity, t, time.Time{}, remaining, offset)
    424425                if err != nil {
    425426                        return nil, err
Note: See TracChangeset for help on using the changeset viewer.