irc: Add WHOIS command
patch 8e120e3fd8592748b35ae91c4acbf189036704d9
Author: E. Bosch <presidev@AT@gmail.com>
Date: Sun Feb 7 03:14:36 CET 2021
* irc: Add WHOIS command
diff -rN -u old-irgramd/irc.py new-irgramd/irc.py
--- old-irgramd/irc.py 2024-11-23 01:05:36.502829030 +0100
+++ new-irgramd/irc.py 2024-11-23 01:05:36.506829023 +0100
@@ -30,6 +30,7 @@
IRC_USER_RX = re.compile(PREFIX + r'USER( +|\n)(?P<username>[^ ]+) +[^ ]+ +[^ ]+( +:| +|\n)(?P<realname>[^\n]+|)')
IRC_JOIN_RX = re.compile(PREFIX + r'JOIN( +|\n)(?P<channel>[^ ]+)')
IRC_WHO_RX = re.compile(PREFIX + r'WHO( +:| +|\n)(?P<target>[^\n]+|)')
+IRC_WHOIS_RX = re.compile(PREFIX + r'WHOIS( +:| +|\n)(?P<nicks>[^\n]+|)')
# IRC Handler
@@ -96,6 +97,7 @@
(IRC_USER_RX, self.handle_irc_user, False),
(IRC_JOIN_RX, self.handle_irc_join, True),
(IRC_WHO_RX, self.handle_irc_who, True),
+ (IRC_WHOIS_RX, self.handle_irc_whois, True),
)
self.iid_to_tid = {}
self.irc_channels = collections.defaultdict(set)
@@ -182,6 +184,33 @@
))
await self.reply_code(user, 'RPL_ENDOFWHO', (chan,))
+ async def handle_irc_whois(self, user, nicks):
+ self.logger.debug('Handling WHO: %s', nicks)
+ for nick in nicks.split(','):
+ ni = nick.lower()
+ real_ni = self.users[ni].irc_nick
+ if ni in self.users.keys():
+ usr = self.users[ni]
+ await self.reply_code(user, 'RPL_WHOISUSER', (real_ni, usr.irc_username, usr.address, usr.irc_realname))
+ await self.reply_code(user, 'RPL_WHOISSERVER', (real_ni, self.hostname))
+ chans = usr.get_channels(self)
+ if chans: await self.reply_code(user, 'RPL_WHOISCHANNELS', (real_ni, chans))
+ idle = await self.tg.get_telegram_idle(ni)
+ if idle != None: await self.reply_code(user, 'RPL_WHOISIDLE', (real_ni, idle))
+ if usr.oper: await self.reply_code(user, 'RPL_WHOISOPERATOR', (real_ni,))
+ if usr.stream: await self.reply_code(user, 'RPL_WHOISACCOUNT', (real_ni,
+ '{}!{}@Telegram'.format(self.tg.tg_username, self.tg.id
+ )))
+ if await self.tg.is_bot(ni):
+ await self.reply_code(user, 'RPL_WHOISBOT', (real_ni,))
+ elif usr.tls or not usr.stream:
+ proto = 'TLS' if usr.tls else 'MTProto'
+ server = self.hostname if usr.stream else 'Telegram'
+ await self.reply_code(user, 'RPL_WHOISSECURE', (real_ni, proto, server))
+ await self.reply_code(user, 'RPL_ENDOFWHOIS', (real_ni,))
+ else:
+ await self.reply_code(user, 'ERR_NOSUCHNICK', (nick,))
+
async def handle_irc_privmsg(self, user, nick, message):
self.logger.debug('Handling PRIVMSG: %s, %s', nick, message)
@@ -284,10 +313,20 @@
self.registered = False
self.password = ''
self.recv_pass = ''
+ self.oper = False
+ self.tls = False
+ self.bot = None
def get_irc_mask(self):
return '{}!{}@{}'.format(self.irc_nick, self.irc_username, self.address)
+ def get_channels(self, irc):
+ res = ''
+ for chan in irc.irc_channels.keys():
+ if self.irc_nick in irc.irc_channels[chan]:
+ res += irc.get_irc_op(self.irc_nick, chan) + chan + ' '
+ return res
+
def valid_nick(self, nick):
if len(nick) <= NICK_MAX_LENGTH and nick[0] in VALID_IRC_NICK_FIRST_CHARS:
for x in nick[1:]:
diff -rN -u old-irgramd/irc_replies.py new-irgramd/irc_replies.py
--- old-irgramd/irc_replies.py 2024-11-23 01:05:36.502829030 +0100
+++ new-irgramd/irc_replies.py 2024-11-23 01:05:36.506829023 +0100
@@ -6,12 +6,20 @@
'RPL_CREATED': ('003', ':This server was created {}'),
'RPL_MYINFO': ('004', '{} irgramd-{} o nt'),
'RPL_ISUPPORT': ('005', 'CASEMAPPING=ascii CHANLIMIT=#&+: CHANTYPES=&#+ CHANMODES=,,,nt CHANNELLEN={} NICKLEN={} SAFELIST :are supported by this server'),
+ 'RPL_WHOISUSER': ('311', '{} {} {} * :{}'),
+ 'RPL_WHOISSERVER': ('312', '{} {} :irgramd gateway'),
+ 'RPL_WHOISOPERATOR': ('313', '{} :is an irgramd operator'),
'RPL_ENDOFWHO': ('315', '{} :End of WHO list'),
+ 'RPL_WHOISIDLE': ('317', '{} {} :seconds idle'),
+ 'RPL_ENDOFWHOIS': ('318', '{} :End of WHOIS command'),
+ 'RPL_WHOISCHANNELS': ('319', '{} :{}'),
+ 'RPL_WHOISACCOUNT': ('330', '{} {} :Telegram name'),
+ 'RPL_WHOISBOT': ('335', '{} :is a Telegram bot'),
'RPL_WHOREPLY': ('352', '{} {} {} {} {} H{} :0 {}'),
'RPL_MOTDSTART': ('375', ':- {} Message of the day - '),
'RPL_MOTD': ('372', ':- {}'),
'RPL_ENDOFMOTD': ('376', 'End of MOTD command'),
- 'ERR_NOSUCHNICK': ('401', 'No such nick'),
+ 'ERR_NOSUCHNICK': ('401', '{} :Nick not found'),
'ERR_NOSUCHSERVER': ('402', '{} :Target not found'),
'ERR_NOSUCHCHANNEL': ('403', 'No such channel'),
'ERR_CANNOTSENDTOCHAN': ('404', 'Cannot send to channel'),
@@ -55,4 +63,5 @@
'ERR_NOOPERHOST': ('491', 'No operator host'),
'ERR_UMODEUNKNOWNFLAG': ('501', 'User mode unknown flag'),
'ERR_USERSDONTMATCH': ('502', 'Users don\'t match'),
+ 'RPL_WHOISSECURE': ('671', '{} :is using a secure {} connection with {}'),
}
diff -rN -u old-irgramd/telegram.py new-irgramd/telegram.py
--- old-irgramd/telegram.py 2024-11-23 01:05:36.506829023 +0100
+++ new-irgramd/telegram.py 2024-11-23 01:05:36.506829023 +0100
@@ -1,6 +1,7 @@
import logging
import os
+import datetime
import telethon
from telethon import types as tgty
@@ -157,6 +158,45 @@
return nicks
+ async def get_telegram_idle(self, irc_nick, tid=None):
+ tid = self.get_tid(irc_nick, tid)
+ user = await self.telegram_client.get_entity(tid)
+ if isinstance(user.status,tgty.UserStatusRecently) or \
+ isinstance(user.status,tgty.UserStatusOnline):
+ idle = 0
+ elif isinstance(user.status,tgty.UserStatusOffline):
+ last = user.status.was_online
+ current = datetime.datetime.now(datetime.timezone.utc)
+ idle = int((current - last).total_seconds())
+ elif isinstance(user.status,tgty.UserStatusLastWeek):
+ idle = 604800
+ elif isinstance(user.status,tgty.UserStatusLastMonth):
+ idle = 2678400
+ else:
+ idle = None
+ return idle
+
+ async def is_bot(self, irc_nick, tid=None):
+ if self.irc.users[irc_nick].stream:
+ bot = False
+ else:
+ bot = self.irc.users[irc_nick].bot
+ if bot == None:
+ tid = self.get_tid(irc_nick, tid)
+ user = await self.telegram_client.get_entity(tid)
+ bot = user.bot
+ self.irc.users[irc_nick].bot = bot
+ return bot
+
+ def get_tid(self, irc_nick, tid=None):
+ if tid:
+ pass
+ elif irc_nick in self.irc.iid_to_tid:
+ tid = self.irc.iid_to_tid[irc_nick.lower()]
+ else:
+ tid = self.id
+ return tid
+
async def handle_telegram_message(self, event):
self.logger.debug('Handling Telegram Message: %s', event)