patch 24aacd1a117ef092876ee5e0bc9522563dcdfd0e
Author: Peter Bui <pbui@bx612.space>
Date: Fri Jul 19 17:21:26 CEST 2019
* Periodically update channel voices
Rather than checking on individual users, simply check the whole channel
periodically... this is much more reliable than depending on messages
for active users.
diff -rN -u old-irgramd/irtelegramd.py new-irgramd/irtelegramd.py
--- old-irgramd/irtelegramd.py 2024-11-22 22:40:51.496687380 +0100
+++ new-irgramd/irtelegramd.py 2024-11-22 22:40:51.496687380 +0100
@@ -17,8 +17,8 @@
# Configuration
-NICK_MAX_LENGTH = 20
-USER_STATUS_DELAY = 300
+NICK_MAX_LENGTH = 20
+UPDATE_CHANNEL_VOICES_DELAY = 300
# Utilities
@@ -102,16 +102,11 @@
self.iid_to_tid = {}
self.irc_channels = collections.defaultdict(set)
self.irc_nick = None
- self.irc_online = set()
+ self.irc_voices = collections.defaultdict(set)
def get_irc_user_mask(self, nick):
return '{}!{}@{}'.format(nick, nick, self.hostname)
- def schedule_irc_mode_update(self, nick, channel, force=False):
- if nick not in self.irc_online or force:
- self.ioloop.call_later(USER_STATUS_DELAY, self.update_irc_mode, nick, channel)
- self.irc_online.add(nick)
-
async def send_irc_command(self, command):
self.logger.debug('Send IRC Command: %s', command)
command = command + '\r\n'
@@ -187,12 +182,7 @@
))
# Update voices
- for user_nick in voices:
- await self.send_irc_command(':{} MODE {} +v {}'.format(
- self.hostname, channel, user_nick,
- ))
-
- self.schedule_irc_mode_update(user_nick, channel)
+ await self.update_channel_voices(channel, voices)
async def part_irc_channel(self, nick, channel):
self.irc_channels[channel].remove(nick)
@@ -200,17 +190,29 @@
self.get_irc_user_mask(nick), channel
))
- async def update_irc_mode(self, nick, channel):
- tid = self.iid_to_tid[nick]
- user = await self.telegram_client.get_entity(tid)
- if isinstance(user.status, telethon.types.UserStatusOnline):
- self.schedule_irc_mode_update(nick, channel, True)
- else:
- self.irc_online.remove(nick)
+ async def update_channel_voices(self, channel, voices=None):
+ # Get voices for channel if not provided
+ if not voices:
+ tid = self.iid_to_tid[channel]
+ _, voices = await self.get_telegram_channel_participants(tid)
+
+ # Add new voices
+ for nick in voices:
+ if nick not in self.irc_voices[channel]:
+ self.irc_voices[channel].add(nick)
+ await self.send_irc_command(':{} MODE {} +v {}'.format(
+ self.hostname, channel, nick,
+ ))
+
+ # Remove old voices
+ for nick in self.irc_voices[channel].difference(voices):
+ self.irc_voices[channel].remove(nick)
await self.send_irc_command(':{} MODE {} -v {}'.format(
self.hostname, channel, nick,
))
+ self.ioloop.call_later(UPDATE_CHANNEL_VOICES_DELAY, self.update_channel_voices, channel)
+
# Telegram
async def initialize_telegram(self):
@@ -279,7 +281,7 @@
async def get_telegram_channel_participants(self, tid):
channel = self.tid_to_iid[tid]
nicks = []
- voices = []
+ voices = set()
async for user in self.telegram_client.iter_participants(tid):
if user.id not in self.tid_to_iid:
user_nick = self.get_telegram_nick(user)
@@ -289,7 +291,7 @@
user_nick = self.tid_to_iid[user.id]
if isinstance(user.status, telethon.types.UserStatusOnline):
- voices.append(user_nick)
+ voices.add(user_nick)
nicks.append(user_nick)
self.irc_channels[channel].add(user_nick)
@@ -342,13 +344,6 @@
elif event.message.media and (event.message.sticker):
messages.insert(0, 'Sticker: {}'.format(event.message.sticker.id))
- # Give voice and schedule IRC mode update
- if nick not in self.irc_online:
- await self.send_irc_command(':{} MODE {} +v {}'.format(
- self.hostname, channel, nick,
- ))
- self.schedule_irc_mode_update(nick, channel)
-
# Send all messages to IRC
for message in messages:
await self.send_irc_command(':{} PRIVMSG {} :{}'.format(
@@ -364,7 +359,7 @@
tid = event.action_message.to_id.chat_id
finally:
irc_channel = self.tid_to_iid[tid]
- await get_telegram_channel_participants(tid)
+ await self.get_telegram_channel_participants(tid)
try: # Join Chats
irc_nick = await self.get_irc_nick_from_telegram_id(event.action_message.action.users[0])