- Timestamp:
- May 1, 2020, 1:18:14 PM (5 years ago)
- Location:
- trunk
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/db.go
r267 r284 44 44 45 45 type Channel struct { 46 ID int64 47 Name string 48 Key string 46 ID int64 47 Name string 48 Key string 49 Detached bool 49 50 } 50 51 … … 77 78 name VARCHAR(255) NOT NULL, 78 79 key VARCHAR(255), 80 detached INTEGER NOT NULL DEFAULT 0, 79 81 FOREIGN KEY(network) REFERENCES Network(id), 80 82 UNIQUE(network, name) … … 85 87 "", // migration #0 is reserved for schema initialization 86 88 "ALTER TABLE Network ADD COLUMN connect_commands VARCHAR(1023)", 89 "ALTER TABLE Channel ADD COLUMN detached INTEGER NOT NULL DEFAULT 0", 87 90 } 88 91 … … 347 350 defer db.lock.RUnlock() 348 351 349 rows, err := db.db.Query("SELECT id, name, key FROM Channel WHERE network = ?", networkID) 352 rows, err := db.db.Query(`SELECT id, name, key, detached 353 FROM Channel 354 WHERE network = ?`, networkID) 350 355 if err != nil { 351 356 return nil, err … … 357 362 var ch Channel 358 363 var key *string 359 if err := rows.Scan(&ch.ID, &ch.Name, &key ); err != nil {364 if err := rows.Scan(&ch.ID, &ch.Name, &key, &ch.Detached); err != nil { 360 365 return nil, err 361 366 } … … 379 384 if ch.ID != 0 { 380 385 _, err = db.db.Exec(`UPDATE Channel 381 SET network = ?, name = ?, key = ? 382 WHERE id = ?`, networkID, ch.Name, key, ch.ID) 386 SET network = ?, name = ?, key = ?, detached = ? 387 WHERE id = ?`, 388 networkID, ch.Name, key, ch.Detached, ch.ID) 383 389 } else { 384 390 var res sql.Result 385 res, err = db.db.Exec(`INSERT INTO Channel(network, name, key) 386 VALUES (?, ?, ?)`, networkID, ch.Name, key) 391 res, err = db.db.Exec(`INSERT INTO Channel(network, name, key, detached) 392 VALUES (?, ?, ?, ?)`, 393 networkID, ch.Name, key, ch.Detached) 387 394 if err != nil { 388 395 return err -
trunk/doc/soju.1.scd
r270 r284 24 24 the next connection. When registering or authenticating with NickServ, the 25 25 credentials will be saved and automatically used on the next connection if the 26 server supports SASL. 26 server supports SASL. When parting a channel with the reason "detach", the 27 channel will be detached instead of being left. 27 28 28 29 When all clients are disconnected from the bouncer, the user is automatically -
trunk/downstream.go
r279 r284 768 768 dc.forEachUpstream(func(uc *upstreamConn) { 769 769 for _, ch := range uc.channels { 770 if ch.complete { 771 dc.SendMessage(&irc.Message{ 772 Prefix: dc.prefix(), 773 Command: "JOIN", 774 Params: []string{dc.marshalEntity(ch.conn.network, ch.Name)}, 775 }) 776 777 forwardChannel(dc, ch) 778 } 770 if !ch.complete { 771 continue 772 } 773 if record, ok := uc.network.channels[ch.Name]; ok && record.Detached { 774 continue 775 } 776 777 dc.SendMessage(&irc.Message{ 778 Prefix: dc.prefix(), 779 Command: "JOIN", 780 Params: []string{dc.marshalEntity(ch.conn.network, ch.Name)}, 781 }) 782 783 forwardChannel(dc, ch) 779 784 } 780 785 }) … … 794 799 func (dc *downstreamConn) sendNetworkHistory(net *network) { 795 800 for target, history := range net.history { 801 if ch, ok := net.channels[target]; ok && ch.Detached { 802 continue 803 } 804 796 805 seq, ok := history.offlineClients[dc.clientName] 797 806 if !ok { … … 946 955 }) 947 956 948 ch := &Channel{Name: upstreamName, Key: key }957 ch := &Channel{Name: upstreamName, Key: key, Detached: false} 949 958 if err := uc.network.createUpdateChannel(ch); err != nil { 950 959 dc.logger.Printf("failed to create or update channel %q: %v", upstreamName, err) … … 968 977 } 969 978 970 params := []string{upstreamName} 971 if reason != "" { 972 params = append(params, reason) 973 } 974 uc.SendMessage(&irc.Message{ 975 Command: "PART", 976 Params: params, 977 }) 978 979 if err := uc.network.deleteChannel(upstreamName); err != nil { 980 dc.logger.Printf("failed to delete channel %q: %v", upstreamName, err) 979 if strings.EqualFold(reason, "detach") { 980 ch := &Channel{Name: upstreamName, Detached: true} 981 if err := uc.network.createUpdateChannel(ch); err != nil { 982 dc.logger.Printf("failed to detach channel %q: %v", upstreamName, err) 983 } 984 } else { 985 params := []string{upstreamName} 986 if reason != "" { 987 params = append(params, reason) 988 } 989 uc.SendMessage(&irc.Message{ 990 Command: "PART", 991 Params: params, 992 }) 993 994 if err := uc.network.deleteChannel(upstreamName); err != nil { 995 dc.logger.Printf("failed to delete channel %q: %v", upstreamName, err) 996 } 981 997 } 982 998 } -
trunk/upstream.go
r282 r284 1406 1406 // appendHistory appends a message to the history. entity can be empty. 1407 1407 func (uc *upstreamConn) appendHistory(entity string, msg *irc.Message) { 1408 detached := false 1409 if ch, ok := uc.network.channels[entity]; ok { 1410 detached = ch.Detached 1411 } 1412 1408 1413 // If no client is offline, no need to append the message to the buffer 1409 if len(uc.network.offlineClients) == 0 {1414 if len(uc.network.offlineClients) == 0 && !detached { 1410 1415 return 1411 1416 } … … 1421 1426 for clientName, _ := range uc.network.offlineClients { 1422 1427 history.offlineClients[clientName] = 0 1428 } 1429 1430 if detached { 1431 // If the channel is detached, online clients act as offline 1432 // clients too 1433 uc.forEachDownstream(func(dc *downstreamConn) { 1434 history.offlineClients[dc.clientName] = 0 1435 }) 1423 1436 } 1424 1437 } … … 1439 1452 uc.appendHistory(target, msg) 1440 1453 1454 // Don't forward messages if it's a detached channel 1455 if ch, ok := uc.network.channels[target]; ok && ch.Detached { 1456 return 1457 } 1458 1441 1459 uc.forEachDownstream(func(dc *downstreamConn) { 1442 1460 if dc != origin || dc.caps["echo-message"] { -
trunk/user.go
r283 r284 151 151 return err 152 152 } 153 prev := net.channels[ch.Name] 153 154 net.channels[ch.Name] = ch 155 156 if prev != nil && prev.Detached != ch.Detached { 157 history := net.history[ch.Name] 158 if ch.Detached { 159 net.user.srv.Logger.Printf("network %q: detaching channel %q", net.GetName(), ch.Name) 160 net.forEachDownstream(func(dc *downstreamConn) { 161 net.offlineClients[dc.clientName] = struct{}{} 162 if history != nil { 163 history.offlineClients[dc.clientName] = history.ring.Cur() 164 } 165 166 dc.SendMessage(&irc.Message{ 167 Prefix: dc.prefix(), 168 Command: "PART", 169 Params: []string{dc.marshalEntity(net, ch.Name), "Detach"}, 170 }) 171 }) 172 } else { 173 net.user.srv.Logger.Printf("network %q: attaching channel %q", net.GetName(), ch.Name) 174 175 var uch *upstreamChannel 176 if net.conn != nil { 177 uch = net.conn.channels[ch.Name] 178 } 179 180 net.forEachDownstream(func(dc *downstreamConn) { 181 dc.SendMessage(&irc.Message{ 182 Prefix: dc.prefix(), 183 Command: "JOIN", 184 Params: []string{dc.marshalEntity(net, ch.Name)}, 185 }) 186 187 if uch != nil { 188 forwardChannel(dc, uch) 189 } 190 191 if history != nil { 192 dc.sendNetworkHistory(net) 193 } 194 }) 195 } 196 } 197 154 198 return nil 155 199 } … … 343 387 344 388 net.offlineClients[dc.clientName] = struct{}{} 345 for _, history := range net.history { 389 for target, history := range net.history { 390 if ch, ok := net.channels[target]; ok && ch.Detached { 391 continue 392 } 346 393 history.offlineClients[dc.clientName] = history.ring.Cur() 347 394 }
Note:
See TracChangeset
for help on using the changeset viewer.