summaryrefslogblamecommitdiff
path: root/game/irc.rpy
blob: 870bc1cf46c68faf0f915d539cb687a4658b63c0 (plain) (tree)




































































































































































































































                                                                                                                
#################################################################################
#     This file is part of Spheres.
#     Copyright (C) 2019  Jesusalva

#     This library is free software; you can redistribute it and/or
#     modify it under the terms of the GNU Lesser General Public
#     License as published by the Free Software Foundation; either
#     version 2.1 of the License, or (at your option) any later version.

#     This library is distributed in the hope that it will be useful,
#     but WITHOUT ANY WARRANTY; without even the implied warranty of
#     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
#     Lesser General Public License for more details.

#     You should have received a copy of the GNU Lesser General Public
#     License along with this library; if not, write to the Free Software
#     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
#################################################################################
# Chat controller
# TODO: Pub interface, using irc_send() and irc_buffer

init python:
    irc=None
    irc_online=False

    def irc_open():
        if not persistent.irc_enable:
            return

        global irc, irc_buffer, irc_nick, irc_auth, irc_channel, irc_online
        import socket, sys, random

        reload(sys)
        sys.setdefaultencoding('utf8')

        irc_online=False
        server = "irc.freenode.org"
        irc_channel = "#tmw2-spheres"
        # TODO: Replace this with some uuid4()?
        irc_nick = "GS_" + get_token()[:3] + str(random.randint(1, 10000))
        irc_auth=IRC_AUTH_NONE
        irc_buffer=[]
        irc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        stdout("\nConnecting to:" + server)
        irc.connect((server, 6667))
        return

    def irc_receive(raw):
        global irc_buffer
        sender="IRC"

        # Control buffer length
        if (len(irc_buffer) >= MAX_IRC_BUFFER):
            nil=irc_buffer.pop(0)
            del nil

        # Find sender if not supplied
        try:
            p1=raw.find('<')+1
            p2=raw.find('>')
            if p2 <= p1:
                raise Exception("Invalid sender")
            sender=raw[p1:p2]
        except:
            try:
                p1=raw.find("!")
                sender="IRC."+raw[1:p1]
            except:
                sender="IRC"

        # Extract message
        try:
            p1=raw.find(" :") # Perhaps we're looking for ">" instead
            msg=raw[p1:]
        except:
            msg="Unparseable"

        # UNIX format
        msg=msg.replace('\r', '')
        irc_buffer.append((sender, msg))
        return

    def irc_send(sender, msg):
        global irc, irc_channel, irc_online
        if not irc_online:
            return False
        try:
            irc.send("PRIVMSG %s :<%s> %s\n" % (irc_channel, sender, msg))
            irc_buffer.append((sender, msg))
            return True
        except:
            return False

    def irc_kill():
        global irc, irc_online
        if irc_online:
            irc.send("QUIT :I have to go for now!\n")
            stdout("[IRC] Closing connection normally...")
            irc.shutdown(2)
            irc.close()
            irc_online=False
            stdout("[IRC] IRC Bridge is now Offline.")
        #del irc
        irc=None
        return

    def irc_loop():
        if not persistent.irc_enable:
            return

        global irc, irc_buffer, irc_nick, irc_auth, irc_channel, irc_online

        if irc is None:
            irc_open()

        try:
            while 1:
                text = irc.recv(2048)
                if len(text) > 0:
                    if debug:
                        stdout("[IRC] %s" % text)
                else:
                    continue

                # Handle ping requests
                if text.find("PING") != -1:
                    irc.send("PONG " + text.split()[1] + "\n")

                # Authentication: Step 1
                if irc_auth == IRC_AUTH_NONE:
                    irc.send("USER " + irc_nick + " " + irc_nick + " " + irc_nick + " :This is a fun bot\n")
                    irc_auth=IRC_AUTH_USER
                    continue

                # Authentication: Step 2
                if irc_auth == IRC_AUTH_USER:
                    irc.send("NICK " + irc_nick + "\n")
                    irc_auth=IRC_AUTH_NICK
                    continue

                # Authentication: Step 3
                if text.find("255 " + irc_nick) != -1:
                    irc.send("JOIN " + irc_channel + "\n")

                if text.find("376 " + irc_nick) != -1:
                    if irc_auth == IRC_AUTH_NICK:
                        irc_auth=IRC_AUTH_CHAN
                        irc_online=True
                    else:
                        stdout("[IRC] Erroneous Authentication on 376 message")
                        irc_online=True

                if irc_auth == IRC_AUTH_CHAN:
                    # IRC Syntax
                    # :nick!hostname PRIVMSG #tmw2-spheres :<nickname> msg
                    # We should use <nickname>, not :nick!

                    # TODO: Handle CTCP ACTION
                    if text.find(irc_channel) != -1:
                        if "PRIVMSG" in text:
                            irc_receive(text)

                    # Handle disconnections
                    if not irc_online:
                        raise Exception("Connection terminated.")

        finally:
            try:
                irc.send("QUIT :I have to go for now!\n")
                irc.shutdown(2)
                irc.close()
            except:
                stdout("[IRC] [ERROR] Connection was already closed.")
            stdout("\n")
            stdout("Closing IRC connection...")
            irc=None

        return

screen pub():
    frame:
        background Frame("gui/frame.png", 0, 0)
        xalign 0.5
        yalign 0.5
        ymargin 15
        ypadding 10
        xmargin 10
        vbox:
            spacing 30
            textbutton _("Exit") action Return("")
            label _("PUB RAID - NOT YET IMPLEMENTED")
            null height 20
            viewport:
                #child_size (0.4, 0.8)
                mousewheel True
                draggable True
                arrowkeys True
                xfill False
                scrollbars "vertical"

                vbox:
                    xalign 0.5
                    spacing 5
                    label _("%s" % persistent.nickname)
                    null height 40

                    showif irc_online:
                        for chat in irc_buffer:
                            label _("%s: {size=22}%s{/size}" % (chat[0], chat[1].replace("<%s>" % chat[0], "")))

                        null height 40
                        input:
                            id "msgmsg"
                            color ((128, 128, 128, 220))
                            italic True
                            size 26
                            copypaste True
                            allow "qwertyuiopasdfghjklzxcvbnm QWERTYUIOPASDFGHJKKLZXCVBNM,.?!+-=:;'()"
                        textbutton _("Send") action None # Function(irc_send)
                    else:
                        if persistent.irc_enable:
                            label _("Connecting...")
                        else:
                            label _("IRC Integration is not active.")
                        # FIXME inform if IRC is disabled
                        # Ask user to comply with Freenode TOS etc.

    timer 1.0 action Function(renpy.restart_interaction) repeat True