clients.html   [plain text]


<?xml version="1.0"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en"><head><title>Twisted Documentation: Writing Clients</title><link href="../howto/stylesheet.css" type="text/css" rel="stylesheet" /></head><body bgcolor="white"><h1 class="title">Writing Clients</h1><div class="toc"><ol><li><a href="#auto0">Overview</a></li><li><a href="#auto1">Protocol</a></li><li><a href="#auto2">ClientFactory</a></li><ul><li><a href="#auto3">Reconnection</a></li></ul><li><a href="#auto4">A Higher-Level Example: ircLogBot</a></li><ul><li><a href="#auto5">Overview of ircLogBot</a></li><li><a href="#auto6">Persistent Data in the Factory</a></li></ul></ol></div><div class="content"><span></span><h2>Overview<a name="auto0"></a></h2><p>Twisted is a framework designed to be very flexible, and let you write
    powerful clients.  The cost of this flexibility is a few layers in the way
    to writing your client. This document covers creating clients that can
    be used for TCP, SSL and Unix sockets, UDP is covered <a href="udp.html">in
    a different document</a>.</p><p>At the base, the place where you actually implement the protocol parsing
    and handling, is the Protocol class. This class will usually be decended
    from <code class="API"><a href="http://twistedmatrix.com/documents/TwistedDocs/TwistedDocs-1.3.0/api/twisted.internet.protocol.Protocol.html" title="twisted.internet.protocol.Protocol">twisted.internet.protocol.Protocol</a></code>. Most
    protocol handlers inherit either from this class or from one of its
    convenience children. An instance of the protocol class will be
    instantiated when you connect to the server, and will go away when the
    connection is finished.  This means that persistent configuration is not
    saved in the Protocol.</p><p>The persistent configuration is kept in a Factory class, which usually
    inherits from <code class="API"><a href="http://twistedmatrix.com/documents/TwistedDocs/TwistedDocs-1.3.0/api/twisted.internet.protocol.ClientFactory.html" title="twisted.internet.protocol.ClientFactory">twisted.internet.protocol.ClientFactory</a></code>. The
    default factory class just instantiate the Protocol, and then sets on it an
    attribute called <code>factory</code> which points to itself. This let the
    Protocol access, and possibly modify, the persistent configuration.</p><h2>Protocol<a name="auto1"></a></h2><p>As mentioned above, this, and auxiliary classes and functions, is where
    most of the code is. A Twisted protocol handles data in an asynchronous
    manner. What this means is that the protocol never waits for an event, but
    rather responds to events as they arrive from the network.</p><p>Here is a simple example:</p><pre class="python">
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span><span class="py-src-op">.</span><span class="py-src-variable">internet</span><span class="py-src-op">.</span><span class="py-src-variable">protocol</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">Protocol</span><span class="py-src-newline">
</span><span class="py-src-keyword">from</span> <span class="py-src-variable">sys</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">stdout</span><span class="py-src-newline">
</span><span class="py-src-keyword">class</span> <span class="py-src-identifier">Echo</span><span class="py-src-op">(</span><span class="py-src-parameter">Protocol</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span>    <span class="py-src-nl">
</span><span class="py-src-indent">    </span><span class="py-src-keyword">def</span> <span class="py-src-identifier">dataReceived</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">,</span> <span class="py-src-parameter">data</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-variable">stdout</span><span class="py-src-op">.</span><span class="py-src-variable">write</span><span class="py-src-op">(</span><span class="py-src-variable">data</span><span class="py-src-op">)</span><span class="py-src-newline">
</span><span class="py-src-dedent"></span><span class="py-src-dedent"></span><span class="py-src-endmarker"></span></pre><p>This is one of the simplest protocols.  It simply writes to standard
    output whatever it reads from the connection.  There are many events it
    does not respond to.  Here is an example of a Protocol responding to
    another event.</p><pre class="python">
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span><span class="py-src-op">.</span><span class="py-src-variable">internet</span><span class="py-src-op">.</span><span class="py-src-variable">protocol</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">Protocol</span><span class="py-src-newline">
</span><span class="py-src-keyword">class</span> <span class="py-src-identifier">WelcomeMessage</span><span class="py-src-op">(</span><span class="py-src-parameter">Protocol</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span>    <span class="py-src-nl">
</span><span class="py-src-indent">    </span><span class="py-src-keyword">def</span> <span class="py-src-identifier">connectionMade</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">transport</span><span class="py-src-op">.</span><span class="py-src-variable">write</span><span class="py-src-op">(</span><span class="py-src-string">&quot;Hello server, I am the client!\r\n&quot;</span><span class="py-src-op">)</span><span class="py-src-newline">
</span>        <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">transport</span><span class="py-src-op">.</span><span class="py-src-variable">loseConnection</span><span class="py-src-op">(</span><span class="py-src-op">)</span><span class="py-src-newline">
</span><span class="py-src-dedent"></span><span class="py-src-dedent"></span><span class="py-src-endmarker"></span></pre><p>This protocol connects to the server, sends it a welcome message, and
    then terminates the connection.</p><p>The connectionMade event is usually where set up of the Protocol object
    happens, as well as any initial greetings (as in the WelcomeMessage
    protocol above).  Any tearing down of Protocol-specific objects is done in
    connectionLost.</p><h2>ClientFactory<a name="auto2"></a></h2><p>We use reactor.connect* and a ClientFactory.
    The ClientFactory is in charge of creating the Protocol, and also receives
    events relating to the connection state.  This allows it to do things like
    reconnect on the event of a connection error.  Here is an example of a
    simple ClientFactory that uses the Echo protocol (above) and also prints
    what state the connection is in.</p><pre class="python">
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span><span class="py-src-op">.</span><span class="py-src-variable">internet</span><span class="py-src-op">.</span><span class="py-src-variable">protocol</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">Protocol</span><span class="py-src-op">,</span> <span class="py-src-variable">ClientFactory</span><span class="py-src-newline">
</span><span class="py-src-keyword">from</span> <span class="py-src-variable">sys</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">stdout</span><span class="py-src-newline">
</span><span class="py-src-keyword">class</span> <span class="py-src-identifier">Echo</span><span class="py-src-op">(</span><span class="py-src-parameter">Protocol</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span><span class="py-src-indent">    </span><span class="py-src-keyword">def</span> <span class="py-src-identifier">dataReceived</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">,</span> <span class="py-src-parameter">data</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-variable">stdout</span><span class="py-src-op">.</span><span class="py-src-variable">write</span><span class="py-src-op">(</span><span class="py-src-variable">data</span><span class="py-src-op">)</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span><span class="py-src-dedent"></span><span class="py-src-dedent"></span><span class="py-src-keyword">class</span> <span class="py-src-identifier">EchoClientFactory</span><span class="py-src-op">(</span><span class="py-src-parameter">ClientFactory</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span>    <span class="py-src-nl">
</span><span class="py-src-indent">    </span><span class="py-src-keyword">def</span> <span class="py-src-identifier">startedConnecting</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">,</span> <span class="py-src-parameter">connector</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-keyword">print</span> <span class="py-src-string">'Started to connect.'</span><span class="py-src-newline">
</span>    <span class="py-src-nl">
</span>    <span class="py-src-dedent"></span><span class="py-src-keyword">def</span> <span class="py-src-identifier">buildProtocol</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">,</span> <span class="py-src-parameter">addr</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-keyword">print</span> <span class="py-src-string">'Connected.'</span><span class="py-src-newline">
</span>        <span class="py-src-keyword">return</span> <span class="py-src-variable">Echo</span><span class="py-src-op">(</span><span class="py-src-op">)</span><span class="py-src-newline">
</span>    <span class="py-src-nl">
</span>    <span class="py-src-dedent"></span><span class="py-src-keyword">def</span> <span class="py-src-identifier">clientConnectionLost</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">,</span> <span class="py-src-parameter">connector</span><span class="py-src-op">,</span> <span class="py-src-parameter">reason</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-keyword">print</span> <span class="py-src-string">'Lost connection.  Reason:'</span><span class="py-src-op">,</span> <span class="py-src-variable">reason</span><span class="py-src-newline">
</span>    <span class="py-src-nl">
</span>    <span class="py-src-dedent"></span><span class="py-src-keyword">def</span> <span class="py-src-identifier">clientConnectionFailed</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">,</span> <span class="py-src-parameter">connector</span><span class="py-src-op">,</span> <span class="py-src-parameter">reason</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-keyword">print</span> <span class="py-src-string">'Connection failed. Reason:'</span><span class="py-src-op">,</span> <span class="py-src-variable">reason</span><span class="py-src-newline">
</span><span class="py-src-dedent"></span><span class="py-src-dedent"></span><span class="py-src-endmarker"></span></pre><p>To connect this EchoClientFactory to a server, you could use this code:</p><pre class="python">
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span><span class="py-src-op">.</span><span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">reactor</span><span class="py-src-newline">
</span><span class="py-src-variable">reactor</span><span class="py-src-op">.</span><span class="py-src-variable">connectTCP</span><span class="py-src-op">(</span><span class="py-src-variable">host</span><span class="py-src-op">,</span> <span class="py-src-variable">port</span><span class="py-src-op">,</span> <span class="py-src-variable">EchoClientFactory</span><span class="py-src-op">(</span><span class="py-src-op">)</span><span class="py-src-op">)</span><span class="py-src-newline">
</span><span class="py-src-variable">reactor</span><span class="py-src-op">.</span><span class="py-src-variable">run</span><span class="py-src-op">(</span><span class="py-src-op">)</span><span class="py-src-newline">
</span><span class="py-src-endmarker"></span></pre><p>Note that <code class="API"><a href="http://twistedmatrix.com/documents/TwistedDocs/TwistedDocs-1.3.0/api/twisted.internet.protocol.ClientFactory.clientConnectionFailed.html" title="twisted.internet.protocol.ClientFactory.clientConnectionFailed">clientConnectionFailed</a></code>
    is called when a connection could not be established, and that <code class="API"><a href="http://twistedmatrix.com/documents/TwistedDocs/TwistedDocs-1.3.0/api/twisted.internet.protocol.ClientFactory.clientConnectionLost.html" title="twisted.internet.protocol.ClientFactory.clientConnectionLost">clientConnectionLost</a></code>
    is called when a connection was made and then disconnected.</p><h3>Reconnection<a name="auto3"></a></h3><p>Many times, the connection of a client will be lost unintentionally due
    to network errors. One way to reconnect after a disconnection would be to
    call <code class="python">connector.connect()</code> when the
    connection is lost:
    </p><pre class="python">
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span><span class="py-src-op">.</span><span class="py-src-variable">internet</span><span class="py-src-op">.</span><span class="py-src-variable">protocol</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">ClientFactory</span><span class="py-src-newline">
</span><span class="py-src-keyword">class</span> <span class="py-src-identifier">EchoClientFactory</span><span class="py-src-op">(</span><span class="py-src-parameter">ClientFactory</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span>    <span class="py-src-nl">
</span><span class="py-src-indent">    </span><span class="py-src-keyword">def</span> <span class="py-src-identifier">clientConnectionLost</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">,</span> <span class="py-src-parameter">connector</span><span class="py-src-op">,</span> <span class="py-src-parameter">reason</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-variable">connector</span><span class="py-src-op">.</span><span class="py-src-variable">connect</span><span class="py-src-op">(</span><span class="py-src-op">)</span><span class="py-src-newline">
</span><span class="py-src-dedent"></span><span class="py-src-dedent"></span><span class="py-src-endmarker"></span></pre><p>The connector passed as the first
    argument is the interface between a connection and a protocol.  When the
    connection fails and the factory receives the clientConnectionLost event,
    the factory can call <code class="python">connector.connect()</code> to
    start the connection over again from scratch.</p><p>
    However, most programs that want this functionality should implement <code class="API"><a href="http://twistedmatrix.com/documents/TwistedDocs/TwistedDocs-1.3.0/api/twisted.internet.protocol.ReconnectingClientFactory.html" title="twisted.internet.protocol.ReconnectingClientFactory">ReconnectingClientFactory</a></code> instead,
    which tries to reconnect if a connection is lost or fails, and which
    exponentially delays repeated reconnect attempts.
    </p><p>
    Here is the Echo protocol implemented with a ReconnectingClientFactory:
    </p><pre class="python">
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span><span class="py-src-op">.</span><span class="py-src-variable">internet</span><span class="py-src-op">.</span><span class="py-src-variable">protocol</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">Protocol</span><span class="py-src-op">,</span> <span class="py-src-variable">ReconnectingClientFactory</span><span class="py-src-newline">
</span><span class="py-src-keyword">from</span> <span class="py-src-variable">sys</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">stdout</span><span class="py-src-newline">
</span><span class="py-src-keyword">class</span> <span class="py-src-identifier">Echo</span><span class="py-src-op">(</span><span class="py-src-parameter">Protocol</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span>                                                                                                                                                            <span class="py-src-nl">
</span><span class="py-src-indent">    </span><span class="py-src-keyword">def</span> <span class="py-src-identifier">dataReceived</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">,</span> <span class="py-src-parameter">data</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-variable">stdout</span><span class="py-src-op">.</span><span class="py-src-variable">write</span><span class="py-src-op">(</span><span class="py-src-variable">data</span><span class="py-src-op">)</span><span class="py-src-newline">
</span>                                                                                                                                                            <span class="py-src-nl">
</span><span class="py-src-dedent"></span><span class="py-src-dedent"></span><span class="py-src-keyword">class</span> <span class="py-src-identifier">EchoClientFactory</span><span class="py-src-op">(</span><span class="py-src-parameter">ReconnectingClientFactory</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span>                                                                                                                                                            <span class="py-src-nl">
</span><span class="py-src-indent">    </span><span class="py-src-keyword">def</span> <span class="py-src-identifier">startedConnecting</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">,</span> <span class="py-src-parameter">connector</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-keyword">print</span> <span class="py-src-string">'Started to connect.'</span><span class="py-src-newline">
</span>                                                                                                                                                            <span class="py-src-nl">
</span>    <span class="py-src-dedent"></span><span class="py-src-keyword">def</span> <span class="py-src-identifier">buildProtocol</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">,</span> <span class="py-src-parameter">addr</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-keyword">print</span> <span class="py-src-string">'Connected.'</span><span class="py-src-newline">
</span>        <span class="py-src-keyword">print</span> <span class="py-src-string">'Resetting reconnection delay'</span><span class="py-src-newline">
</span>        <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">resetDelay</span><span class="py-src-op">(</span><span class="py-src-op">)</span><span class="py-src-newline">
</span>        <span class="py-src-keyword">return</span> <span class="py-src-variable">Echo</span><span class="py-src-op">(</span><span class="py-src-op">)</span><span class="py-src-newline">
</span>                                                                                                                                                            <span class="py-src-nl">
</span>    <span class="py-src-dedent"></span><span class="py-src-keyword">def</span> <span class="py-src-identifier">clientConnectionLost</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">,</span> <span class="py-src-parameter">connector</span><span class="py-src-op">,</span> <span class="py-src-parameter">reason</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-keyword">print</span> <span class="py-src-string">'Lost connection.  Reason:'</span><span class="py-src-op">,</span> <span class="py-src-variable">reason</span><span class="py-src-newline">
</span>        <span class="py-src-variable">ReconnectingClientFactory</span><span class="py-src-op">.</span><span class="py-src-variable">clientConnectionLost</span><span class="py-src-op">(</span><span class="py-src-variable">self</span><span class="py-src-op">,</span> <span class="py-src-variable">connector</span><span class="py-src-op">,</span> <span class="py-src-variable">reason</span><span class="py-src-op">)</span><span class="py-src-newline">
</span>                                                                                                                                                            <span class="py-src-nl">
</span>    <span class="py-src-dedent"></span><span class="py-src-keyword">def</span> <span class="py-src-identifier">clientConnectionFailed</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">,</span> <span class="py-src-parameter">connector</span><span class="py-src-op">,</span> <span class="py-src-parameter">reason</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-keyword">print</span> <span class="py-src-string">'Connection failed. Reason:'</span><span class="py-src-op">,</span> <span class="py-src-variable">reason</span><span class="py-src-newline">
</span>        <span class="py-src-variable">ReconnectingClientFactory</span><span class="py-src-op">.</span><span class="py-src-variable">clientConnectionFailed</span><span class="py-src-op">(</span><span class="py-src-variable">self</span><span class="py-src-op">,</span><span class="py-src-nl">
</span>                <span class="py-src-variable">connector</span><span class="py-src-op">,</span> <span class="py-src-variable">reason</span><span class="py-src-op">)</span><span class="py-src-newline">
</span><span class="py-src-dedent"></span><span class="py-src-dedent"></span><span class="py-src-endmarker"></span></pre><h2>A Higher-Level Example: ircLogBot<a name="auto4"></a></h2><h3>Overview of ircLogBot<a name="auto5"></a></h3><p>The clients so far have been fairly simple.  A more complicated
    example comes with Twisted in the doc/examples directory.</p><div class="py-listing"><pre>
<span class="py-src-string">&quot;&quot;&quot;An example IRC log bot - logs a channel's events to a file.

If someone says the bot's name in the channel followed by a ':',
e.g.

  &lt;foo&gt; logbot: hello!

the bot will reply:

  &lt;logbot&gt; foo: I am a log bot

Run this script with two arguments, the channel name the bot should
connect to, and file to log to, e.g.:

  $ python ircLogBot.py test test.log

will log channel #test to the file 'test.log'.
&quot;&quot;&quot;</span>   <span class="py-src-newline">
</span><span class="py-src-nl">
</span><span class="py-src-nl">
</span><span class="py-src-comment"># twisted imports
</span><span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span><span class="py-src-op">.</span><span class="py-src-variable">protocols</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">irc</span><span class="py-src-newline">
</span><span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span><span class="py-src-op">.</span><span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">reactor</span><span class="py-src-op">,</span> <span class="py-src-variable">protocol</span><span class="py-src-newline">
</span><span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span><span class="py-src-op">.</span><span class="py-src-variable">python</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">log</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span><span class="py-src-comment"># system imports
</span><span class="py-src-keyword">import</span> <span class="py-src-variable">time</span><span class="py-src-op">,</span> <span class="py-src-variable">sys</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span><span class="py-src-nl">
</span><span class="py-src-keyword">class</span> <span class="py-src-identifier">MessageLogger</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">    </span><span class="py-src-string">&quot;&quot;&quot;
    An independant logger class (because separation of application
    and protocol logic is a good thing).
    &quot;&quot;&quot;</span>       <span class="py-src-newline">
</span>    <span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">,</span> <span class="py-src-parameter">file</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">file</span> <span class="py-src-op">=</span> <span class="py-src-variable">file</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span>    <span class="py-src-dedent"></span><span class="py-src-keyword">def</span> <span class="py-src-identifier">log</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">,</span> <span class="py-src-parameter">message</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-string">&quot;&quot;&quot;Write a message to the file.&quot;&quot;&quot;</span><span class="py-src-newline">
</span>        <span class="py-src-variable">timestamp</span> <span class="py-src-op">=</span> <span class="py-src-variable">time</span><span class="py-src-op">.</span><span class="py-src-variable">strftime</span><span class="py-src-op">(</span><span class="py-src-string">&quot;[%H:%M:%S]&quot;</span><span class="py-src-op">,</span> <span class="py-src-variable">time</span><span class="py-src-op">.</span><span class="py-src-variable">localtime</span><span class="py-src-op">(</span><span class="py-src-variable">time</span><span class="py-src-op">.</span><span class="py-src-variable">time</span><span class="py-src-op">(</span><span class="py-src-op">)</span><span class="py-src-op">)</span><span class="py-src-op">)</span><span class="py-src-newline">
</span>        <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">file</span><span class="py-src-op">.</span><span class="py-src-variable">write</span><span class="py-src-op">(</span><span class="py-src-string">'%s %s\n'</span> <span class="py-src-op">%</span> <span class="py-src-op">(</span><span class="py-src-variable">timestamp</span><span class="py-src-op">,</span> <span class="py-src-variable">message</span><span class="py-src-op">)</span><span class="py-src-op">)</span><span class="py-src-newline">
</span>        <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">file</span><span class="py-src-op">.</span><span class="py-src-variable">flush</span><span class="py-src-op">(</span><span class="py-src-op">)</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span>    <span class="py-src-dedent"></span><span class="py-src-keyword">def</span> <span class="py-src-identifier">close</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">file</span><span class="py-src-op">.</span><span class="py-src-variable">close</span><span class="py-src-op">(</span><span class="py-src-op">)</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span><span class="py-src-nl">
</span><span class="py-src-dedent"></span><span class="py-src-dedent"></span><span class="py-src-keyword">class</span> <span class="py-src-identifier">LogBot</span><span class="py-src-op">(</span><span class="py-src-parameter">irc</span><span class="py-src-op">.</span><span class="py-src-parameter">IRCClient</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">    </span><span class="py-src-string">&quot;&quot;&quot;A logging IRC bot.&quot;&quot;&quot;</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span>    <span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">nickname</span> <span class="py-src-op">=</span> <span class="py-src-string">&quot;twistedbot&quot;</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span>    <span class="py-src-dedent"></span><span class="py-src-keyword">def</span> <span class="py-src-identifier">connectionMade</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-variable">irc</span><span class="py-src-op">.</span><span class="py-src-variable">IRCClient</span><span class="py-src-op">.</span><span class="py-src-variable">connectionMade</span><span class="py-src-op">(</span><span class="py-src-variable">self</span><span class="py-src-op">)</span><span class="py-src-newline">
</span>        <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">logger</span> <span class="py-src-op">=</span> <span class="py-src-variable">MessageLogger</span><span class="py-src-op">(</span><span class="py-src-variable">open</span><span class="py-src-op">(</span><span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">factory</span><span class="py-src-op">.</span><span class="py-src-variable">filename</span><span class="py-src-op">,</span> <span class="py-src-string">&quot;a&quot;</span><span class="py-src-op">)</span><span class="py-src-op">)</span><span class="py-src-newline">
</span>        <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">logger</span><span class="py-src-op">.</span><span class="py-src-variable">log</span><span class="py-src-op">(</span><span class="py-src-string">&quot;[connected at %s]&quot;</span> <span class="py-src-op">%</span><span class="py-src-nl">
</span>                        <span class="py-src-variable">time</span><span class="py-src-op">.</span><span class="py-src-variable">asctime</span><span class="py-src-op">(</span><span class="py-src-variable">time</span><span class="py-src-op">.</span><span class="py-src-variable">localtime</span><span class="py-src-op">(</span><span class="py-src-variable">time</span><span class="py-src-op">.</span><span class="py-src-variable">time</span><span class="py-src-op">(</span><span class="py-src-op">)</span><span class="py-src-op">)</span><span class="py-src-op">)</span><span class="py-src-op">)</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span>    <span class="py-src-dedent"></span><span class="py-src-keyword">def</span> <span class="py-src-identifier">connectionLost</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">,</span> <span class="py-src-parameter">reason</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-variable">irc</span><span class="py-src-op">.</span><span class="py-src-variable">IRCClient</span><span class="py-src-op">.</span><span class="py-src-variable">connectionLost</span><span class="py-src-op">(</span><span class="py-src-variable">self</span><span class="py-src-op">,</span> <span class="py-src-variable">reason</span><span class="py-src-op">)</span><span class="py-src-newline">
</span>        <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">logger</span><span class="py-src-op">.</span><span class="py-src-variable">log</span><span class="py-src-op">(</span><span class="py-src-string">&quot;[disconnected at %s]&quot;</span> <span class="py-src-op">%</span><span class="py-src-nl">
</span>                        <span class="py-src-variable">time</span><span class="py-src-op">.</span><span class="py-src-variable">asctime</span><span class="py-src-op">(</span><span class="py-src-variable">time</span><span class="py-src-op">.</span><span class="py-src-variable">localtime</span><span class="py-src-op">(</span><span class="py-src-variable">time</span><span class="py-src-op">.</span><span class="py-src-variable">time</span><span class="py-src-op">(</span><span class="py-src-op">)</span><span class="py-src-op">)</span><span class="py-src-op">)</span><span class="py-src-op">)</span><span class="py-src-newline">
</span>        <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">logger</span><span class="py-src-op">.</span><span class="py-src-variable">close</span><span class="py-src-op">(</span><span class="py-src-op">)</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span><span class="py-src-nl">
</span>    <span class="py-src-comment"># callbacks for events
</span><span class="py-src-nl">
</span>    <span class="py-src-dedent"></span><span class="py-src-keyword">def</span> <span class="py-src-identifier">signedOn</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-string">&quot;&quot;&quot;Called when bot has succesfully signed on to server.&quot;&quot;&quot;</span><span class="py-src-newline">
</span>        <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">join</span><span class="py-src-op">(</span><span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">factory</span><span class="py-src-op">.</span><span class="py-src-variable">channel</span><span class="py-src-op">)</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span>    <span class="py-src-dedent"></span><span class="py-src-keyword">def</span> <span class="py-src-identifier">joined</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">,</span> <span class="py-src-parameter">channel</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-string">&quot;&quot;&quot;This will get called when the bot joins the channel.&quot;&quot;&quot;</span><span class="py-src-newline">
</span>        <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">logger</span><span class="py-src-op">.</span><span class="py-src-variable">log</span><span class="py-src-op">(</span><span class="py-src-string">&quot;[I have joined %s]&quot;</span> <span class="py-src-op">%</span> <span class="py-src-variable">channel</span><span class="py-src-op">)</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span>    <span class="py-src-dedent"></span><span class="py-src-keyword">def</span> <span class="py-src-identifier">privmsg</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">,</span> <span class="py-src-parameter">user</span><span class="py-src-op">,</span> <span class="py-src-parameter">channel</span><span class="py-src-op">,</span> <span class="py-src-parameter">msg</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-string">&quot;&quot;&quot;This will get called when the bot receives a message.&quot;&quot;&quot;</span><span class="py-src-newline">
</span>        <span class="py-src-variable">user</span> <span class="py-src-op">=</span> <span class="py-src-variable">user</span><span class="py-src-op">.</span><span class="py-src-variable">split</span><span class="py-src-op">(</span><span class="py-src-string">'!'</span><span class="py-src-op">,</span> <span class="py-src-number">1</span><span class="py-src-op">)</span><span class="py-src-op">[</span><span class="py-src-number">0</span><span class="py-src-op">]</span><span class="py-src-newline">
</span>        <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">logger</span><span class="py-src-op">.</span><span class="py-src-variable">log</span><span class="py-src-op">(</span><span class="py-src-string">&quot;&lt;%s&gt; %s&quot;</span> <span class="py-src-op">%</span> <span class="py-src-op">(</span><span class="py-src-variable">user</span><span class="py-src-op">,</span> <span class="py-src-variable">msg</span><span class="py-src-op">)</span><span class="py-src-op">)</span><span class="py-src-newline">
</span>        <span class="py-src-keyword">if</span> <span class="py-src-variable">msg</span><span class="py-src-op">.</span><span class="py-src-variable">startswith</span><span class="py-src-op">(</span><span class="py-src-string">&quot;%s:&quot;</span> <span class="py-src-op">%</span> <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">nickname</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span>            <span class="py-src-comment"># someone is talking to me, lets respond:
</span><span class="py-src-indent">            </span><span class="py-src-variable">msg</span> <span class="py-src-op">=</span> <span class="py-src-string">&quot;%s: I am a log bot&quot;</span> <span class="py-src-op">%</span> <span class="py-src-variable">user</span><span class="py-src-newline">
</span>            <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">say</span><span class="py-src-op">(</span><span class="py-src-variable">channel</span><span class="py-src-op">,</span> <span class="py-src-variable">msg</span><span class="py-src-op">)</span><span class="py-src-newline">
</span>            <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">logger</span><span class="py-src-op">.</span><span class="py-src-variable">log</span><span class="py-src-op">(</span><span class="py-src-string">&quot;&lt;%s&gt; %s&quot;</span> <span class="py-src-op">%</span> <span class="py-src-op">(</span><span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">nickname</span><span class="py-src-op">,</span> <span class="py-src-variable">msg</span><span class="py-src-op">)</span><span class="py-src-op">)</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span>    <span class="py-src-dedent"></span><span class="py-src-dedent"></span><span class="py-src-keyword">def</span> <span class="py-src-identifier">action</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">,</span> <span class="py-src-parameter">user</span><span class="py-src-op">,</span> <span class="py-src-parameter">channel</span><span class="py-src-op">,</span> <span class="py-src-parameter">msg</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-string">&quot;&quot;&quot;This will get called when the bot sees someone do an action.&quot;&quot;&quot;</span><span class="py-src-newline">
</span>        <span class="py-src-variable">user</span> <span class="py-src-op">=</span> <span class="py-src-variable">user</span><span class="py-src-op">.</span><span class="py-src-variable">split</span><span class="py-src-op">(</span><span class="py-src-string">'!'</span><span class="py-src-op">,</span> <span class="py-src-number">1</span><span class="py-src-op">)</span><span class="py-src-op">[</span><span class="py-src-number">0</span><span class="py-src-op">]</span><span class="py-src-newline">
</span>        <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">logger</span><span class="py-src-op">.</span><span class="py-src-variable">log</span><span class="py-src-op">(</span><span class="py-src-string">&quot;* %s %s&quot;</span> <span class="py-src-op">%</span> <span class="py-src-op">(</span><span class="py-src-variable">user</span><span class="py-src-op">,</span> <span class="py-src-variable">msg</span><span class="py-src-op">)</span><span class="py-src-op">)</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span>    <span class="py-src-comment"># irc callbacks
</span><span class="py-src-nl">
</span>    <span class="py-src-dedent"></span><span class="py-src-keyword">def</span> <span class="py-src-identifier">irc_NICK</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">,</span> <span class="py-src-parameter">prefix</span><span class="py-src-op">,</span> <span class="py-src-parameter">params</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-string">&quot;&quot;&quot;Called when an IRC user changes their nickname.&quot;&quot;&quot;</span><span class="py-src-newline">
</span>        <span class="py-src-variable">old_nick</span> <span class="py-src-op">=</span> <span class="py-src-variable">prefix</span><span class="py-src-op">.</span><span class="py-src-variable">split</span><span class="py-src-op">(</span><span class="py-src-string">'!'</span><span class="py-src-op">)</span><span class="py-src-op">[</span><span class="py-src-number">0</span><span class="py-src-op">]</span><span class="py-src-newline">
</span>        <span class="py-src-variable">new_nick</span> <span class="py-src-op">=</span> <span class="py-src-variable">params</span><span class="py-src-op">[</span><span class="py-src-number">0</span><span class="py-src-op">]</span><span class="py-src-newline">
</span>        <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">logger</span><span class="py-src-op">.</span><span class="py-src-variable">log</span><span class="py-src-op">(</span><span class="py-src-string">&quot;%s is now known as %s&quot;</span> <span class="py-src-op">%</span> <span class="py-src-op">(</span><span class="py-src-variable">old_nick</span><span class="py-src-op">,</span> <span class="py-src-variable">new_nick</span><span class="py-src-op">)</span><span class="py-src-op">)</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span><span class="py-src-nl">
</span><span class="py-src-dedent"></span><span class="py-src-dedent"></span><span class="py-src-keyword">class</span> <span class="py-src-identifier">LogBotFactory</span><span class="py-src-op">(</span><span class="py-src-parameter">protocol</span><span class="py-src-op">.</span><span class="py-src-parameter">ClientFactory</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">    </span><span class="py-src-string">&quot;&quot;&quot;A factory for LogBots.

    A new protocol instance will be created each time we connect to the server.
    &quot;&quot;&quot;</span>       <span class="py-src-newline">
</span><span class="py-src-nl">
</span>    <span class="py-src-comment"># the class of the protocol to build when new connection is made
</span>    <span class="py-src-variable">protocol</span> <span class="py-src-op">=</span> <span class="py-src-variable">LogBot</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span>    <span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">,</span> <span class="py-src-parameter">channel</span><span class="py-src-op">,</span> <span class="py-src-parameter">filename</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">channel</span> <span class="py-src-op">=</span> <span class="py-src-variable">channel</span><span class="py-src-newline">
</span>        <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">filename</span> <span class="py-src-op">=</span> <span class="py-src-variable">filename</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span>    <span class="py-src-dedent"></span><span class="py-src-keyword">def</span> <span class="py-src-identifier">clientConnectionLost</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">,</span> <span class="py-src-parameter">connector</span><span class="py-src-op">,</span> <span class="py-src-parameter">reason</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-string">&quot;&quot;&quot;If we get disconnected, reconnect to server.&quot;&quot;&quot;</span><span class="py-src-newline">
</span>        <span class="py-src-variable">connector</span><span class="py-src-op">.</span><span class="py-src-variable">connect</span><span class="py-src-op">(</span><span class="py-src-op">)</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span>    <span class="py-src-dedent"></span><span class="py-src-keyword">def</span> <span class="py-src-identifier">clientConnectionFailed</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">,</span> <span class="py-src-parameter">connector</span><span class="py-src-op">,</span> <span class="py-src-parameter">reason</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-keyword">print</span> <span class="py-src-string">&quot;connection failed:&quot;</span><span class="py-src-op">,</span> <span class="py-src-variable">reason</span><span class="py-src-newline">
</span>        <span class="py-src-variable">reactor</span><span class="py-src-op">.</span><span class="py-src-variable">stop</span><span class="py-src-op">(</span><span class="py-src-op">)</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span><span class="py-src-nl">
</span><span class="py-src-dedent"></span><span class="py-src-dedent"></span><span class="py-src-keyword">if</span> <span class="py-src-variable">__name__</span> <span class="py-src-op">==</span> <span class="py-src-string">'__main__'</span><span class="py-src-op">:</span><span class="py-src-newline">
</span>    <span class="py-src-comment"># initialize logging
</span><span class="py-src-indent">    </span><span class="py-src-variable">log</span><span class="py-src-op">.</span><span class="py-src-variable">startLogging</span><span class="py-src-op">(</span><span class="py-src-variable">sys</span><span class="py-src-op">.</span><span class="py-src-variable">stdout</span><span class="py-src-op">)</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span>    <span class="py-src-comment"># create factory protocol and application
</span>    <span class="py-src-variable">f</span> <span class="py-src-op">=</span> <span class="py-src-variable">LogBotFactory</span><span class="py-src-op">(</span><span class="py-src-variable">sys</span><span class="py-src-op">.</span><span class="py-src-variable">argv</span><span class="py-src-op">[</span><span class="py-src-number">1</span><span class="py-src-op">]</span><span class="py-src-op">,</span> <span class="py-src-variable">sys</span><span class="py-src-op">.</span><span class="py-src-variable">argv</span><span class="py-src-op">[</span><span class="py-src-number">2</span><span class="py-src-op">]</span><span class="py-src-op">)</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span>    <span class="py-src-comment"># connect factory to this host and port
</span>    <span class="py-src-variable">reactor</span><span class="py-src-op">.</span><span class="py-src-variable">connectTCP</span><span class="py-src-op">(</span><span class="py-src-string">&quot;irc.freenode.net&quot;</span><span class="py-src-op">,</span> <span class="py-src-number">6667</span><span class="py-src-op">,</span> <span class="py-src-variable">f</span><span class="py-src-op">)</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span>    <span class="py-src-comment"># run bot
</span>    <span class="py-src-variable">reactor</span><span class="py-src-op">.</span><span class="py-src-variable">run</span><span class="py-src-op">(</span><span class="py-src-op">)</span><span class="py-src-newline">
</span><span class="py-src-dedent"></span><span class="py-src-endmarker"></span></pre><div class="caption">Source listing - <a href="../examples/ircLogBot.py"><span class="filename">../examples/ircLogBot.py</span></a></div></div><p>ircLogBot.py connects to an IRC server, joins a channel, and logs all
    traffic on it to a file.  It demonstrates some of the connection-level logic
    of reconnecting on a lost connection, as well as storing persistent data in
    the Factory.</p><h3>Persistent Data in the Factory<a name="auto6"></a></h3><p>Since the Protocol instance is recreated each time the connection is
    made, the client needs some way to keep track of data that should be
    persisted.  In the case of the logging bot, it needs to know which channel
    it is logging, and where to log it to.</p><pre class="python">
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span><span class="py-src-op">.</span><span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">protocol</span><span class="py-src-newline">
</span><span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span><span class="py-src-op">.</span><span class="py-src-variable">protocols</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">irc</span><span class="py-src-newline">
</span><span class="py-src-keyword">class</span> <span class="py-src-identifier">LogBot</span><span class="py-src-op">(</span><span class="py-src-parameter">irc</span><span class="py-src-op">.</span><span class="py-src-parameter">IRCClient</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span>    <span class="py-src-nl">
</span><span class="py-src-indent">    </span><span class="py-src-keyword">def</span> <span class="py-src-identifier">connectionMade</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-variable">irc</span><span class="py-src-op">.</span><span class="py-src-variable">IRCClient</span><span class="py-src-op">.</span><span class="py-src-variable">connectionMade</span><span class="py-src-op">(</span><span class="py-src-variable">self</span><span class="py-src-op">)</span><span class="py-src-newline">
</span>        <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">logger</span> <span class="py-src-op">=</span> <span class="py-src-variable">MessageLogger</span><span class="py-src-op">(</span><span class="py-src-variable">open</span><span class="py-src-op">(</span><span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">factory</span><span class="py-src-op">.</span><span class="py-src-variable">filename</span><span class="py-src-op">,</span> <span class="py-src-string">&quot;a&quot;</span><span class="py-src-op">)</span><span class="py-src-op">)</span><span class="py-src-newline">
</span>        <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">logger</span><span class="py-src-op">.</span><span class="py-src-variable">log</span><span class="py-src-op">(</span><span class="py-src-string">&quot;[connected at %s]&quot;</span> <span class="py-src-op">%</span><span class="py-src-nl">
</span>                        <span class="py-src-variable">time</span><span class="py-src-op">.</span><span class="py-src-variable">asctime</span><span class="py-src-op">(</span><span class="py-src-variable">time</span><span class="py-src-op">.</span><span class="py-src-variable">localtime</span><span class="py-src-op">(</span><span class="py-src-variable">time</span><span class="py-src-op">.</span><span class="py-src-variable">time</span><span class="py-src-op">(</span><span class="py-src-op">)</span><span class="py-src-op">)</span><span class="py-src-op">)</span><span class="py-src-op">)</span><span class="py-src-newline">
</span>    <span class="py-src-nl">
</span>    <span class="py-src-dedent"></span><span class="py-src-keyword">def</span> <span class="py-src-identifier">signedOn</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">join</span><span class="py-src-op">(</span><span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">factory</span><span class="py-src-op">.</span><span class="py-src-variable">channel</span><span class="py-src-op">)</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span>    <span class="py-src-nl">
</span><span class="py-src-dedent"></span><span class="py-src-dedent"></span><span class="py-src-keyword">class</span> <span class="py-src-identifier">LogBotFactory</span><span class="py-src-op">(</span><span class="py-src-parameter">protocol</span><span class="py-src-op">.</span><span class="py-src-parameter">ClientFactory</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span>    <span class="py-src-nl">
</span><span class="py-src-indent">    </span><span class="py-src-variable">protocol</span> <span class="py-src-op">=</span> <span class="py-src-variable">LogBot</span><span class="py-src-newline">
</span>    <span class="py-src-nl">
</span>    <span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">,</span> <span class="py-src-parameter">channel</span><span class="py-src-op">,</span> <span class="py-src-parameter">filename</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">channel</span> <span class="py-src-op">=</span> <span class="py-src-variable">channel</span><span class="py-src-newline">
</span>        <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">filename</span> <span class="py-src-op">=</span> <span class="py-src-variable">filename</span><span class="py-src-newline">
</span><span class="py-src-dedent"></span><span class="py-src-dedent"></span><span class="py-src-endmarker"></span></pre><p>When the protocol is created, it gets a reference to the factory as
    self.factory.  It can then access attributes of the factory in its logic.
    In the case of LogBot, it opens the file and connects to the channel stored
    in the factory.</p></div><p><a href="../howto/index.html">Index</a></p><span class="version">Version: 1.3.0</span></body></html>