| author | Stephen Paul Weber
<singpolyma@singpolyma.net> 2024-11-19 18:13:20 UTC |
| committer | Stephen Paul Weber
<singpolyma@singpolyma.net> 2024-11-19 18:13:20 UTC |
| parent | 0a826dd3d05b3242ce90b9c552a298251ee00868 |
| snikket/Chat.hx | +38 | -17 |
| snikket/Client.hx | +7 | -7 |
| snikket/Persistence.hx | +1 | -1 |
| snikket/Stanza.hx | +1 | -1 |
| snikket/persistence/Dummy.hx | +1 | -1 |
| snikket/persistence/Sqlite.hx | +1 | -1 |
diff --git a/snikket/Chat.hx b/snikket/Chat.hx index d2d479e..79d692c 100644 --- a/snikket/Chat.hx +++ b/snikket/Chat.hx @@ -892,6 +892,8 @@ class Channel extends Chat { @:allow(snikket) private var disco: Caps = new Caps("", [], ["http://jabber.org/protocol/muc"]); private var inSync = true; + private var sync = null; + private var forceLive = false; @:allow(snikket) private function new(client:Client, stream:GenericStream, persistence:Persistence, chatId:String, uiState = Open, isBlocked = false, extensions = null, readUpToId = null, readUpToBy = null, ?disco: Caps) { @@ -912,16 +914,21 @@ class Channel extends Chat { return; } - stream.sendIq( - new Stanza("iq", { type: "get", to: getFullJid().asString() }) - .tag("ping", { xmlns: "urn:xmpp:ping" }).up(), - (response) -> { - if (response.attr.get("type") == "error") { - final err = response.getChild("error")?.getChild(null, "urn:ietf:params:xml:ns:xmpp-stanzas"); - if (err.name == "service-unavailable" || err.name == "feature-not-implemented") return checkRename(); // Error, success! - if (err.name == "remote-server-not-found" || err.name == "remote-server-timeout") return checkRename(); // Timeout, retry later - if (err.name == "item-not-found") return checkRename(); // Nick was changed? - (shouldRefreshDisco ? refreshDisco : (cb)->cb())(() -> { + (refresh ? refreshDisco : (cb)->cb())(() -> { + if (!disco.features.contains("http://jabber.org/protocol/muc")) { + // Not a MUC, owhat kind of channel is this? + forceLive = true; + return; + } + stream.sendIq( + new Stanza("iq", { type: "get", to: getFullJid().asString() }) + .tag("ping", { xmlns: "urn:xmpp:ping" }).up(), + (response) -> { + if (response.attr.get("type") == "error") { + final err = response.getChild("error")?.getChild(null, "urn:ietf:params:xml:ns:xmpp-stanzas"); + if (err.name == "service-unavailable" || err.name == "feature-not-implemented") return checkRename(); // Error, success! + if (err.name == "remote-server-not-found" || err.name == "remote-server-timeout") return checkRename(); // Timeout, retry later + if (err.name == "item-not-found") return checkRename(); // Nick was changed? presence = []; // About to ask for a fresh set inSync = false; client.trigger("chats/update", [this]); @@ -936,12 +943,14 @@ class Channel extends Chat { return stanza; } ); - }); - } else { - checkRename(); + } else { + inSync = false; + persistence.lastId(client.accountId(), chatId, doSync); + checkRename(); + } } - } - ); + ); + }); } private function checkRename() { @@ -967,15 +976,21 @@ class Channel extends Chat { persistence.lastId(client.accountId(), chatId, doSync); } if (oneTen != null && tripleThree != null) { - selfPing(); + selfPing(true); } } private function doSync(lastId: Null<String>) { + if (!disco.features.contains("urn:xmpp:mam:2")) { + inSync = true; + return; + } + if (sync != null) return; + var threeDaysAgo = Date.format( DateTools.delta(std.Date.now(), DateTools.days(-3)) ); - var sync = new MessageSync( + sync = new MessageSync( client, stream, lastId == null ? { startTime: threeDaysAgo } : { page: { after: lastId } }, @@ -1008,6 +1023,7 @@ class Channel extends Chat { sync.fetchNext(); } else { inSync = true; + sync = null; final lastFromSync = chatMessages[chatMessages.length - 1]; if (lastFromSync != null && (lastMessageTimestamp() == null || Reflect.compare(lastFromSync.timestamp, lastMessageTimestamp()) > 0)) { setLastMessage(lastFromSync); @@ -1024,9 +1040,12 @@ class Channel extends Chat { }); }); sync.onError((stanza) -> { + sync = null; if (lastId != null) { // Gap in sync, out newest message has expired from server doSync(null); + } else { + trace("SYNC failed", chatId, stanza); } }); sync.fetchNext(); @@ -1054,6 +1073,8 @@ class Channel extends Chat { @:allow(snikket) override private function livePresence() { + if (forceLive) return true; + for (nick => p in presence) { for (status in p?.mucUser?.allTags("status") ?? []) { if (status.attr.get("code") == "110") { diff --git a/snikket/Client.hx b/snikket/Client.hx index 80af3c8..ff25060 100644 --- a/snikket/Client.hx +++ b/snikket/Client.hx @@ -109,7 +109,7 @@ class Client extends EventEmitter { }); stream.on("sm/update", (data) -> { - final anySyncHappening = chats.exists(chat -> chat.syncing()); + final anySyncHappening = chats.exists(chat -> chat.uiState != Closed && chat.syncing()); persistence.storeStreamManagement(accountId(), anySyncHappening ? null : data.sm); return EventHandled; }); @@ -147,7 +147,7 @@ class Client extends EventEmitter { if (stanza.attr.get("type") == "error" && from != null) { final chat = getChat(from.asBare().asString()); final channel = Std.downcast(chat, Channel); - if (channel != null) channel.selfPing(); + if (channel != null) channel.selfPing(true); } var fwd = null; @@ -650,7 +650,7 @@ class Client extends EventEmitter { if (fn == null || fn == "" || fn == displayName()) return false; _displayName = fn; persistence.storeLogin(jid.asBare().asString(), stream.clientId ?? jid.resource, fn, null); - pingAllChannels(); + pingAllChannels(false); return true; } @@ -706,7 +706,7 @@ class Client extends EventEmitter { // Set self to online if (sendAvailable) { sendPresence(); - pingAllChannels(); + pingAllChannels(true); } this.trigger("status/online", {}); trace("SYNC: done"); @@ -854,7 +854,7 @@ class Client extends EventEmitter { chats = chats.filter((chat) -> chat.chatId != availableChat.chatId); } else { if (existingChat.uiState == Closed) existingChat.uiState = Open; - channel?.selfPing(); + channel?.selfPing(true); this.trigger("chats/update", [existingChat]); return existingChat; } @@ -1410,10 +1410,10 @@ class Client extends EventEmitter { sync.fetchNext(); } - private function pingAllChannels() { + private function pingAllChannels(refresh: Bool) { for (chat in getChats()) { final channel = Std.downcast(chat, Channel); - channel?.selfPing(channel?.disco == null); + channel?.selfPing(refresh || channel?.disco == null); } } } diff --git a/snikket/Persistence.hx b/snikket/Persistence.hx index 7340f3c..bd07317 100644 --- a/snikket/Persistence.hx +++ b/snikket/Persistence.hx @@ -27,7 +27,7 @@ interface Persistence { public function storeLogin(login:String, clientId:String, displayName:String, token:Null<String>):Void; public function getLogin(login:String, callback:(clientId:Null<String>, token:Null<String>, fastCount: Int, displayName:Null<String>)->Void):Void; public function removeAccount(accountId: String, completely:Bool):Void; - public function storeStreamManagement(accountId:String, data:BytesData):Void; + public function storeStreamManagement(accountId:String, data:Null<BytesData>):Void; public function getStreamManagement(accountId:String, callback: (Null<BytesData>)->Void):Void; public function storeService(accountId:String, serviceId:String, name:Null<String>, node:Null<String>, caps:Caps):Void; @HaxeCBridge.noemit diff --git a/snikket/Stanza.hx b/snikket/Stanza.hx index e7c33ae..92afaeb 100644 --- a/snikket/Stanza.hx +++ b/snikket/Stanza.hx @@ -246,7 +246,7 @@ class Stanza implements NodeInterface { return allText().join(""); } - public function find(path:String):Node { + public function find(path:String): Null<Node> { var pos = 0; var len = path.length; var cursor = this; diff --git a/snikket/persistence/Dummy.hx b/snikket/persistence/Dummy.hx index c343703..bfb178b 100644 --- a/snikket/persistence/Dummy.hx +++ b/snikket/persistence/Dummy.hx @@ -106,7 +106,7 @@ class Dummy implements Persistence { public function removeAccount(accountId:String, completely:Bool) { } @HaxeCBridge.noemit - public function storeStreamManagement(accountId:String, sm:BytesData) { } + public function storeStreamManagement(accountId:String, sm:Null<BytesData>) { } @HaxeCBridge.noemit public function getStreamManagement(accountId:String, callback: (Null<BytesData>)->Void) { diff --git a/snikket/persistence/Sqlite.hx b/snikket/persistence/Sqlite.hx index 0869cbe..ad8d5c9 100644 --- a/snikket/persistence/Sqlite.hx +++ b/snikket/persistence/Sqlite.hx @@ -447,7 +447,7 @@ class Sqlite implements Persistence { } @HaxeCBridge.noemit - public function storeStreamManagement(accountId:String, sm:BytesData) { + public function storeStreamManagement(accountId:String, sm:Null<BytesData>) { // TODO }