Changeset 19 in code for trunk


Ignore:
Timestamp:
Feb 6, 2020, 6:22:04 PM (5 years ago)
Author:
contact
Message:

Join channels on upstream servers

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/cmd/jounce/main.go

    r10 r19  
    2525                        Username: "jounce",
    2626                        Realname: "jounce",
     27                        Channels: []string{"#jounce"},
    2728                }},
    2829        }
  • trunk/server.go

    r13 r19  
    1818        Username string
    1919        Realname string
     20        Channels []string
    2021}
    2122
  • trunk/upstream.go

    r18 r19  
    66        "io"
    77        "net"
     8        "strconv"
    89        "strings"
     10        "time"
    911
    1012        "gopkg.in/irc.v3"
     
    1214
    1315const (
    14         rpl_localusers  = "265"
    15         rpl_globalusers = "266"
     16        rpl_localusers   = "265"
     17        rpl_globalusers  = "266"
     18        rpl_topicwhotime = "333"
    1619)
    1720
     
    5558}
    5659
     60type channelStatus byte
     61
     62const (
     63        channelPublic  channelStatus = '='
     64        channelSecret  channelStatus = '@'
     65        channelPrivate channelStatus = '*'
     66)
     67
     68func parseChannelStatus(s string) (channelStatus, error) {
     69        if len(s) > 1 {
     70                return 0, fmt.Errorf("invalid channel status %q: more than one character", s)
     71        }
     72        switch cs := channelStatus(s[0]); cs {
     73        case channelPublic, channelSecret, channelPrivate:
     74                return cs, nil
     75        default:
     76                return 0, fmt.Errorf("invalid channel status %q: unknown status", s)
     77        }
     78}
     79
     80type membership byte
     81
     82const (
     83        membershipFounder   membership = '~'
     84        membershipProtected membership = '&'
     85        membershipOperator  membership = '@'
     86        membershipHalfOp    membership = '%'
     87        membershipVoice     membership = '+'
     88)
     89
     90const stdMembershipPrefixes = "~&@%+"
     91
     92func parseMembershipPrefix(s string) (prefix membership, nick string) {
     93        // TODO: any prefix from PREFIX RPL_ISUPPORT
     94        if strings.IndexByte(stdMembershipPrefixes, s[0]) >= 0 {
     95                return membership(s[0]), s[1:]
     96        } else {
     97                return 0, s
     98        }
     99}
     100
     101type upstreamChannel struct {
     102        Name      string
     103        Topic     string
     104        TopicWho  string
     105        TopicTime time.Time
     106        Status    channelStatus
     107        Members   map[string]membership
     108}
     109
    57110type upstreamConn struct {
    58         upstream   *Upstream
    59         net        net.Conn
    60         irc        *irc.Conn
    61         srv        *Server
    62         registered bool
    63         modes      modeSet
     111        upstream *Upstream
     112        net      net.Conn
     113        irc      *irc.Conn
     114        srv      *Server
    64115
    65116        serverName            string
     
    67118        availableChannelModes string
    68119        channelModesWithParam string
     120
     121        registered bool
     122        modes      modeSet
     123        channels   map[string]*upstreamChannel
     124}
     125
     126func (c *upstreamConn) getChannel(name string) (*upstreamChannel, error) {
     127        ch, ok := c.channels[name]
     128        if !ok {
     129                return nil, fmt.Errorf("unknown channel %q", name)
     130        }
     131        return ch, nil
    69132}
    70133
     
    90153                c.registered = true
    91154                c.srv.Logger.Printf("Connection to %q registered", c.upstream.Addr)
     155
     156                for _, ch := range c.upstream.Channels {
     157                        err := c.irc.WriteMessage(&irc.Message{
     158                                Command: "JOIN",
     159                                Params:  []string{ch},
     160                        })
     161                        if err != nil {
     162                                return err
     163                        }
     164                }
    92165        case irc.RPL_MYINFO:
    93166                if len(msg.Params) < 5 {
     
    100173                        c.channelModesWithParam = msg.Params[5]
    101174                }
     175        case "JOIN":
     176                if len(msg.Params) < 1 {
     177                        return newNeedMoreParamsError(msg.Command)
     178                }
     179                for _, ch := range strings.Split(msg.Params[0], ",") {
     180                        c.srv.Logger.Printf("Joined channel %q", ch)
     181                        c.channels[ch] = &upstreamChannel{
     182                                Name:    ch,
     183                                Members: make(map[string]membership),
     184                        }
     185                }
     186        case irc.RPL_TOPIC, irc.RPL_NOTOPIC:
     187                if len(msg.Params) < 3 {
     188                        return newNeedMoreParamsError(msg.Command)
     189                }
     190                ch, err := c.getChannel(msg.Params[1])
     191                if err != nil {
     192                        return err
     193                }
     194                if msg.Command == irc.RPL_TOPIC {
     195                        ch.Topic = msg.Params[2]
     196                } else {
     197                        ch.Topic = ""
     198                }
     199        case "TOPIC":
     200                if len(msg.Params) < 1 {
     201                        return newNeedMoreParamsError(msg.Command)
     202                }
     203                ch, err := c.getChannel(msg.Params[0])
     204                if err != nil {
     205                        return err
     206                }
     207                if len(msg.Params) > 1 {
     208                        ch.Topic = msg.Params[1]
     209                } else {
     210                        ch.Topic = ""
     211                }
     212        case rpl_topicwhotime:
     213                if len(msg.Params) < 4 {
     214                        return newNeedMoreParamsError(msg.Command)
     215                }
     216                ch, err := c.getChannel(msg.Params[1])
     217                if err != nil {
     218                        return err
     219                }
     220                ch.TopicWho = msg.Params[2]
     221                sec, err := strconv.ParseInt(msg.Params[3], 10, 64)
     222                if err != nil {
     223                        return fmt.Errorf("failed to parse topic time: %v", err)
     224                }
     225                ch.TopicTime = time.Unix(sec, 0)
     226        case irc.RPL_NAMREPLY:
     227                if len(msg.Params) < 4 {
     228                        return newNeedMoreParamsError(msg.Command)
     229                }
     230                ch, err := c.getChannel(msg.Params[2])
     231                if err != nil {
     232                        return err
     233                }
     234
     235                status, err := parseChannelStatus(msg.Params[1])
     236                if err != nil {
     237                        return err
     238                }
     239                ch.Status = status
     240
     241                for _, s := range strings.Split(msg.Params[3], " ") {
     242                        membership, nick := parseMembershipPrefix(s)
     243                        ch.Members[nick] = membership
     244                }
     245        case irc.RPL_ENDOFNAMES:
     246                // TODO
    102247        case irc.RPL_YOURHOST, irc.RPL_CREATED:
    103248                // Ignore
     
    129274                irc:      irc.NewConn(netConn),
    130275                srv:      s,
     276                channels: make(map[string]*upstreamChannel),
    131277        }
    132278        defer netConn.Close()
Note: See TracChangeset for help on using the changeset viewer.