def on_welcome(self, c: ServerConnection, e: Event) -> None: if len(self.nickserv_password) > 0: msg = 'identify %s' % (self.nickserv_password,) c.privmsg('NickServ', msg) c.join(self.channel) def forward_to_irc(msg: Dict[str, Any]) -> None: not_from_zulip_bot = msg["sender_email"] != self.zulip_client.email if not not_from_zulip_bot: # Do not forward echo return is_a_stream = msg["type"] == "stream" if is_a_stream: in_the_specified_stream = msg["display_recipient"] == self.stream at_the_specified_subject = msg["subject"].casefold() == self.topic.casefold() if in_the_specified_stream and at_the_specified_subject: msg["content"] = ("@**%s**: " % (msg["sender_full_name"],)) + msg["content"] send = lambda x: self.c.privmsg(self.channel, x) else: return else: recipients = [u["short_name"] for u in msg["display_recipient"] if u["email"] != msg["sender_email"]] if len(recipients) == 1: send = lambda x: self.c.privmsg(recipients[0], x) else: send = lambda x: self.c.privmsg_many(recipients, x) for line in msg["content"].split("\n"): send(line) z2i = mp.Process(target=self.zulip_client.call_on_each_message, args=(forward_to_irc,)) z2i.start()
def on_nicknameinuse(self, conn:ServerConnection, event:Event)->str: """ Trigered if username is take. Changes the username by appending 69 to it :param conn: ServerConnection to irc server :param event: Event :return: str containing new username """ conn.nick(conn.get_nickname() + "69")
def on_welcome(self, conn:ServerConnection, event:Event): """ Triggered when a welcome message is received meaning that the server connections has been established. Joins the channel specified by self.channel. :param conn: ServerConnection :param event: Event :return: None """ conn.join(self.channel)
def on_welcome(self, conn: ServerConnection, _: Event): """ The 'welcome' event indicates a successful connection to the server Sends a whois command to find the bot on the server :param conn: The connection :param _: The 'welcome' event :return: None """ self.logger.info("Connected to server") conn.whois(self.pack.bot)
def _send_xdcc_request_message(self, conn: ServerConnection): """ Sends an XDCC request message :param conn: The connection to use :return: None """ msg = self.pack.get_request_message() self.logger.info("Send XDCC Message: " + msg) self.message_sent = True conn.privmsg(self.pack.bot, msg)
def on_dccmsg(self, conn:ServerConnection, event:Event): """ Triggered when a non-chat DCC message has been received. DCC messages are raw bytes so there's potential for using this for file transfer. Currently for testing we merely decode them as text messages :param conn: ServerConnection :param event: Event :return:None """ text = event.arguments[0].decode('utf-8') conn.privmsg("You said: " + text)
def handler(self, connection: ServerConnection, event: Event): if event.arguments: occurrence_key = connection.server, event.target if not self.throttle.is_throttled(*occurrence_key): for pattern, response in self.responses: if pattern.match(event.arguments[0]): if not self.throttle.occurrence(*occurrence_key): if event.type == "privmsg": target = event.source.nick else: target = event.target connection.privmsg(target, response) break
def _send_xdcc_request_message(self, conn: ServerConnection): """ Sends an XDCC request message :param conn: The connection to use :return: None """ self.logger.info("Waiting for {}s before sending message".format( self.wait_time)) time.sleep(self.wait_time) msg = self.pack.get_request_message() self.logger.info("Send XDCC Message: " + msg) self.message_sent = True conn.privmsg(self.pack.bot, msg)
def test_channel_joins(config, bot, nickmask, monkeypatch): class FakeSocket: def getpeername(self): return ('10.0.0.99', 6667) socket = FakeSocket() conn = ServerConnection(None) welcome_event = Event(type='welcome', source=config.server.host, target=config.nickname) def join(self, channel, key=''): join_event = Event(type='join', source=nickmask, target=channel) bot.on_join(conn, join_event) received_signal_data = [] @irc_channel_joined.connect def handle_irc_channel_joined(sender, **data): received_signal_data.append(data) with monkeypatch.context() as mpc: mpc.setattr(ServerConnection, 'socket', socket) mpc.setattr(ServerConnection, 'join', join) bot.on_welcome(conn, welcome_event) assert received_signal_data == [ { 'channel_name': '#one' }, { 'channel_name': '#two' }, ]
def on_whoischannels(self, conn: ServerConnection, event: Event): """ The 'whoischannels' event indicates that a whois request has found channels that the bot is a part of. Channels that the bot has joined will be joined as well. :param conn: The connection :param event: The 'whoischannels' event :return: None """ self.logger.info("WHOIS: " + str(event.arguments)) channels = event.arguments[1].split("#") channels.pop(0) channels = list(map(lambda x: "#" + x.split(" ")[0], channels)) self.channels = channels for channel in self.channels: # Join all channels to avoid only joining a members-only channel conn.join(channel)
def on_endofwhois(self, conn: ServerConnection, _: Event): """ The 'endofwhois' event indicates the end of a whois request. This manually calls on_join in case the bot has not joined any channels. :param conn: The connection :param _: The 'endofwhois' event :return: None """ self.logger.info("WHOIS End") if self.channels is None: if self.fallback_channel is not None: channel = self.fallback_channel if not channel.startswith("#"): channel = "#" + channel conn.join(channel) return else: self.on_join(conn, _, True)
def on_welcome(self, connection: ServerConnection, event: Event): """Callback for when connection has been established Joins the Twitch chat and sends a message to confirm connection. Parameters ---------- connection : ServerConnection Connection to Twitch server event : Event Event object for connection """ for req in ("membership", "tags", "commands"): connection.cap("REQ", f":twitch.tv/{req}") connection.join(self.CHANNEL) self.send_message("Connected") LOG.info( f"Connected user {self.USERNAME} to twitch channel {self.CHANNEL[1:]}." )
def handle_command(self, conn: ServerConnection, channel: str, message: str, tags: TwitchTags) -> None: """Command Handler for the chat bot""" try: command_name, *msg = message[1:].split() command_name = command_name.lower() msg = ' '.join(msg) if command_name == 'me': self._command_manager.store( command_name=tags.user.lower(), message=msg ) conn.privmsg(channel, f'The command !{tags.user.lower()} has been updated!') return command = self._command_manager.get(command_name) if not command: return command.handle(tags.permission, msg) if command and command.response: conn.privmsg(channel, command.response) except Exception as e: print(f"Uh Oh: {e}")
def on_nicknameinuse(self, connection: ServerConnection, event: Event): connection.nick("{}_".format(connection.get_nickname()))
def on_pubmsg(self, conn: ServerConnection, event: Event): if event.arguments[0] == 'test123': conn.privmsg(CHANNEL, '#familyfriendly, bitte!')
def on_nicknameinuse(connection: ServerConnection, *_): connection.nick(connection.nickname + '_')
def on_nicknameinuse(self, c: ServerConnection, e: Event) -> None: c.nick(c.get_nickname().replace("_zulip", "__zulip"))
def on_dccmsg(self, c: ServerConnection, e: Event) -> None: c.privmsg("You said: " + e.arguments[0])
def on_invite(self, connection: ServerConnection, event: Event): if event.target == connection.get_nickname() and event.arguments: if event.arguments[0] not in self.channels: connection.join(event.arguments[0])
def on_kick(self, connection: ServerConnection, event: Event): if event.arguments and connection.get_nickname() in event.arguments: connection.join(event.target)
def on_endofmotd(self, conn: ServerConnection, event: Event): print('Well, we are done here.') conn.join(CHANNEL)
def on_ctcp(self, conn: ServerConnection, event: Event): """ The 'ctcp' event indicates that a CTCP message was received. The downloader receives a CTCP from the bot to initialize the XDCC file transfer. Handles DCC ACCEPT and SEND messages. Other DCC messages will result in a raised InvalidCTCP exception. DCC ACCEPT will only occur when a resume request was sent successfully. DCC SEND will occur when the bot offers a file. :param conn: The connection :param event: The 'ctcp' event :return: None :raise InvalidCTCPException: In case no valid DCC message was received """ def start_download(append: bool = False): """ Helper method that starts the download of an XDCC pack :param append: If set to True, opens the file in append mode :return: None """ self.downloading = True self.xdcc_timestamp = time.time() mode = "ab" if append else "wb" self.logger.info("Starting Download (" + mode + ")") self.xdcc_file = open(self.pack.get_filepath(), mode) self.xdcc_connection = \ self.dcc_connect(self.peer_address, self.peer_port, "raw") self.xdcc_connection.socket.settimeout(5) self.logger.info("CTCP Message: " + str(event.arguments)) if event.arguments[0] == "DCC": payload = shlex.split(event.arguments[1]) if payload[0] == "SEND": filename = payload[1] self.peer_address = ip_numstr_to_quad(payload[2]) self.peer_port = int(payload[3]) self.filesize = int(payload[4]) self.pack.set_filename(filename) if os.path.isfile(self.pack.get_filepath()): position = os.path.getsize(self.pack.get_filepath()) if position >= self.filesize: raise AlreadyDownloadedException(self.pack.filename) self.logger.info("Requesting Resume") self.progress = position bot = event.source.split("!")[0] resume_param = "\"" + filename + "\" " + \ str(self.peer_port) + " " + str(position) conn.ctcp("DCC RESUME", bot, resume_param) else: start_download() elif payload[0] == "ACCEPT": start_download(append=True) else: raise InvalidCTCPException(payload[0])
def on_welcome(self, c: ServerConnection, e: Event): logger.info(f"Successfully joined irc!") c.join(self.channel)
def on_welcome(self, connection: ServerConnection, event: Event): for channel in self.initial_channels: connection.join(channel)
def on_welcome(self, connection: client.ServerConnection, _: client.Event) -> None: if self.capabilities: connection.cap('REQ', *self.capabilities) connection.cap('END') connection.join(self.channel)