Commits

Anonymous committed f5e2a1f

Added dccreceive and dccsend example programs.

  • Participants
  • Parent commits 13bd0d3

Comments (0)

Files changed (3)

 
 This library is intended to encapsulate the IRC protocol at a quite
 low level.  It provides an event-driven IRC client framework.  It has
-a fairly thorough support for the basic IRC protocol and CTCP, but DCC
-connection support is not yet implemented.  It actually does CTCP
-parsing exactly as the CTCP specifications describe it -- I've never
-seen another IRC client do that!
+a fairly thorough support for the basic IRC protocol, CTCP and DCC
+connections.
 
 In order to understand how to make an IRC client, I'm afraid you more
 or less must understand the IRC specifications.  They are available
     specification subtilties.
   * A kind of simple, single-server, object-oriented IRC client class
     that dispatches events to instance methods is included.
+  * DCC connection support.
 
 Current limitations:
 
   * The IRC protocol shines through the abstraction a bit too much.
-  * Data is not written asynchronously to the server, i.e. the write()
-    may block if the TCP buffers are stuffed.
-  * There are no support for DCC connections.
+  * Data is not written asynchronously to the server (and DCC peers),
+    i.e. the write() may block if the TCP buffers are stuffed.
   * The author hasn't even read RFC 2810, 2811, 2812 and 2813.
   * Like most projects, documentation is lacking...
 
 
     An example bot that uses the SingleServerIRCBot class from
     ircbot.py.  The bot enters a channel and listens for commands in
-    private messages or channel traffic.
+    private messages or channel traffic.  It also accepts DCC
+    invitations and echos back sent DCC chat messages.
+
+  * dccreceive
+
+    Receives a file over DCC.
+
+  * dccsend
+
+    Sends a file over DCC.
 
 Enjoy.
 
+#! /usr/bin/env python
+#
+# Example program using irclib.py.
+#
+# This program is free without restrictions; do anything you like with
+# it.
+#
+# Joel Rosdahl <joel@rosdahl.net>
+
+import irclib
+import os
+import string
+import struct
+import sys
+
+class DCCReceive(irclib.SimpleIRCClient):
+    def __init__(self):
+        irclib.SimpleIRCClient.__init__(self)
+        self.received_bytes = 0
+
+    def on_ctcp(self, connection, event):
+        args = string.split(event.arguments()[1])
+        if args[0] != "SEND":
+            return
+        self.filename = os.path.basename(args[1])
+        if os.path.exists(self.filename):
+            print "A file named", self.filename,
+            print "already exists. Refusing to save it."
+            self.connection.quit()
+        self.file = open(self.filename, "w")
+        peeraddress = irclib.ip_numstr_to_quad(args[2])
+        peerport = int(args[3])
+        self.dcc = self.dcc_connect(peeraddress, peerport, "raw")
+
+    def on_dccmsg(self, connection, event):
+        data = event.arguments()[0]
+        self.file.write(data)
+        self.received_bytes = self.received_bytes + len(data)
+        self.dcc.privmsg(struct.pack("!I", self.received_bytes))
+
+    def on_dcc_disconnect(self, connection, event):
+        self.file.close()
+        print "Received file %s (%d bytes)." % (self.filename,
+                                                self.received_bytes)
+        self.connection.quit()
+
+    def on_disconnect(self, connection, event):
+        sys.exit(0)
+
+def main():
+    if len(sys.argv) != 3:
+        print "Usage: dccreceive <server[:port]> <nickname>"
+        print "\nReceives one file via DCC and then exits.  The file is stored in the"
+        print "current directory."
+        sys.exit(1)
+
+    s = string.split(sys.argv[1], ":", 1)
+    server = s[0]
+    if len(s) == 2:
+        try:
+            port = int(s[1])
+        except ValueError:
+            print "Error: Erroneous port."
+            sys.exit(1)
+    else:
+        port = 6667
+    nickname = sys.argv[2]
+
+    c = DCCReceive()
+    try:
+        c.connect(server, port, nickname)
+    except irclib.ServerConnectionError, x:
+        print x
+        sys.exit(1)
+    c.start()
+
+if __name__ == "__main__":
+    main()
+#! /usr/bin/env python
+#
+# Example program using irclib.py.
+#
+# This program is free without restrictions; do anything you like with
+# it.
+#
+# Joel Rosdahl <joel@rosdahl.net>
+
+import irclib
+import os
+import string
+import struct
+import sys
+
+class DCCSend(irclib.SimpleIRCClient):
+    def __init__(self, receiver, filename):
+        irclib.SimpleIRCClient.__init__(self)
+        self.receiver = receiver
+        self.filename = filename
+        self.filesize = os.path.getsize(self.filename)
+        self.file = open(filename)
+        self.sent_bytes = 0
+
+    def on_welcome(self, connection, event):
+        self.dcc = self.dcc_listen("raw")
+        self.connection.ctcp("DCC", self.receiver, "SEND %s %s %d %d" % (
+            os.path.basename(self.filename),
+            irclib.ip_quad_to_numstr(self.dcc.localaddress),
+            self.dcc.localport,
+            self.filesize))
+
+    def on_dcc_connect(self, connection, event):
+        if self.filesize == 0:
+            self.dcc.disconnect()
+            return
+        self.send_chunk()
+
+    def on_dcc_disconnect(self, connection, event):
+        print "Sent file %s (%d bytes)." % (self.filename, self.filesize)
+        self.connection.quit()
+
+    def on_dccmsg(self, connection, event):
+        acked = struct.unpack("!I", event.arguments()[0])[0]
+        if acked == self.filesize:
+            self.dcc.disconnect()
+            self.connection.quit()
+        elif acked == self.sent_bytes:
+            self.send_chunk()
+
+    def on_disconnect(self, connection, event):
+        sys.exit(0)
+
+    def on_nosuchnick(self, connection, event):
+        print "No such nickname:", event.arguments()[0]
+        self.connection.quit()
+
+    def send_chunk(self):
+        data = self.file.read(1024)
+        self.dcc.privmsg(data)
+        self.sent_bytes = self.sent_bytes + len(data)
+
+def main():
+    if len(sys.argv) != 5:
+        print "Usage: dccsend <server[:port]> <nickname> <receiver nickname> <filename>"
+        print "\nSends <filename> to <receiver nickname> via DCC and then exits."
+        sys.exit(1)
+
+    s = string.split(sys.argv[1], ":", 1)
+    server = s[0]
+    if len(s) == 2:
+        try:
+            port = int(s[1])
+        except ValueError:
+            print "Error: Erroneous port."
+            sys.exit(1)
+    else:
+        port = 6667
+    nickname = sys.argv[2]
+    receiver = sys.argv[3]
+    filename = sys.argv[4]
+
+    c = DCCSend(receiver, filename)
+    try:
+        c.connect(server, port, nickname)
+    except irclib.ServerConnectionError, x:
+        print x
+        sys.exit(1)
+    c.start()
+
+if __name__ == "__main__":
+    main()