1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
diff --git i/heisenbridge/__main__.py w/heisenbridge/__main__.py
index d59febd..4898955 100644
--- i/heisenbridge/__main__.py
+++ w/heisenbridge/__main__.py
@@ -28,6 +28,7 @@ from mautrix.errors import MUserInUse
from mautrix.types import EventType
from mautrix.types import JoinRule
from mautrix.types import Membership
+from mautrix.types import PresenceState
from mautrix.util.bridge_state import BridgeState
from mautrix.util.bridge_state import BridgeStateEvent
from mautrix.util.config import yaml
@@ -192,6 +193,19 @@ class BridgeAppService(AppService):
return ret
+ def set_user_state(self, user_id, away, status=None):
+ if user_id not in self._users:
+ return
+
+ presence = PresenceState.ONLINE
+ if away:
+ presence = PresenceState.UNAVAILABLE
+
+ async def later():
+ await self.az.intent.user(user_id).set_presence(presence=presence, status=status)
+
+ asyncio.ensure_future(later())
+
async def cache_user(self, user_id, displayname):
# start by caching that the user_id exists without a displayname
if user_id not in self._users:
diff --git i/heisenbridge/channel_room.py w/heisenbridge/channel_room.py
index 119dad0..3e0651d 100644
--- i/heisenbridge/channel_room.py
+++ w/heisenbridge/channel_room.py
@@ -478,6 +478,9 @@ class ChannelRoom(PrivateRoom):
asyncio.ensure_future(autocmd(self))
+ # Run a WHO on the channel to get initial away status
+ self.network.conn.who(target=event.target)
+
return
# ensure, append, invite and join
diff --git i/heisenbridge/network_room.py w/heisenbridge/network_room.py
index 3c20654..2758462 100644
--- i/heisenbridge/network_room.py
+++ w/heisenbridge/network_room.py
@@ -139,7 +139,7 @@ class NetworkRoom(Room):
self.tls_cert = None
self.rejoin_invite = True
self.rejoin_kick = False
- self.caps = ["message-tags", "chghost", "znc.in/self-message"]
+ self.caps = ["message-tags", "chghost", "znc.in/self-message", "away-notify"]
self.forward = False
self.backoff = 0
self.backoff_task = None
@@ -1378,6 +1378,7 @@ class NetworkRoom(Room):
self.conn.add_global_handler("338", self.on_whoisrealhost) # is actually using host
self.conn.add_global_handler("away", self.on_away)
self.conn.add_global_handler("endofwhois", self.on_endofwhois)
+ self.conn.add_global_handler("whoreply", self.on_whoreply)
# tags
self.conn.add_global_handler("tagmsg", self.on_pass_or_ignore)
@@ -1936,9 +1937,34 @@ class NetworkRoom(Room):
data = self.whois_data[event.arguments[0].lower()]
data["realhost"] = event.arguments[1]
+ def on_whoreply(self, conn, event) -> None:
+ data = self.whois_data[event.arguments[4].lower()]
+ data["nick"] = event.arguments[4]
+ data["user"] = event.arguments[1]
+ data["host"] = event.arguments[2]
+ if "G" in event.arguments[5]:
+ data["away"] = True
+ elif "H" in event.arguments[5]:
+ data["away"] = False
+ # data["realname"] = event.arguments[4]
+
+ nick, mode = self.serv.strip_nick(data["nick"])
+ irc_user_id = self.serv.irc_user_id(self.name, data["nick"])
+ self.serv.set_user_state(irc_user_id, data["away"])
+
def on_away(self, conn, event) -> None:
+ nick, mode = self.serv.strip_nick(event.arguments[0])
+ irc_user_id = self.serv.irc_user_id(self.name, event.arguments[0])
+
if event.arguments[0].lower() in self.whois_data:
- self.whois_data[event.arguments[0].lower()]["away"] = event.arguments[1]
+ if len(event.arguments) > 1:
+ self.whois_data[event.arguments[0].lower()]["away"] = True
+ self.whois_data[event.arguments[0].lower()]["awaymsg"] = event.arguments[1]
+ self.serv.set_user_state(irc_user_id, True, event.arguments[1])
+ else:
+ self.whois_data[event.arguments[0].lower()]["away"] = False
+ self.whois_data[event.arguments[0].lower()]["awaymsg"] = ""
+ self.serv.set_user_state(irc_user_id, False)
else:
self.send_notice(f"{event.arguments[0]} is away: {event.arguments[1]}")
|