<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>The Troll-Range &#187; project</title>
	<atom:link href="http://blog.trollgod.org.uk/tag/project/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.trollgod.org.uk</link>
	<description>Ghworg&#039;s wibblings and geek projects.</description>
	<lastBuildDate>Mon, 26 Apr 2010 19:31:11 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Twitter to XMPP (Jabber)</title>
		<link>http://blog.trollgod.org.uk/2009/03/twitter-to-xmpp-jabber/</link>
		<comments>http://blog.trollgod.org.uk/2009/03/twitter-to-xmpp-jabber/#comments</comments>
		<pubDate>Sat, 21 Mar 2009 21:23:50 +0000</pubDate>
		<dc:creator>Ghworg</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Internet]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[project]]></category>
		<category><![CDATA[twitter]]></category>
		<category><![CDATA[xmpp]]></category>

		<guid isPermaLink="false">http://blog.trollgod.org.uk/?p=118</guid>
		<description><![CDATA[<p>The other day I noticed that irssi (the IRC client I use) had a XMPP plugin. It occurred to me that since I&#8217;m on IRC a lot it would be really cool to pull microblog feeds into irssi via this plugin.</p> <p>For identi.ca this was a doddle, since laconica supports XMPP natively. Twitter however <span style="color:#777"> . . . &#8594; Read More: <a href="http://blog.trollgod.org.uk/2009/03/twitter-to-xmpp-jabber/">Twitter to XMPP (Jabber)</a></span>]]></description>
			<content:encoded><![CDATA[<p>The other day I noticed that <a href="http://irssi.org/">irssi</a> (the <a href="http://en.wikipedia.org/wiki/Internet_Relay_Chat">IRC</a> client I use) had a <a href="http://cybione.org/~irssi-xmpp/">XMPP plugin</a>.  It occurred to me that since I&#8217;m on IRC a lot it would be really cool to pull microblog feeds into irssi via this plugin.</p>
<p>For <a href="http://identi.ca/ghworg">identi.ca</a> this was a doddle, since <a href="http://laconi.ca/">laconica</a> supports <a href="http://en.wikipedia.org/wiki/Extensible_Messaging_and_Presence_Protocol">XMPP</a> natively.  <a href="http://twitter.com/Ghworg">Twitter</a> however was a problem.  I believe twitter used to support XMPP but they pulled that feature for who knows what reason.</p>
<p>There are a couple of apps that will provided a twitter->XMPP gateway for you.  I looked at <a href="http://dustin.github.com/twitterspy/">twitterspy</a>, but it sounded like a pain to install.  So at first I tried <a href="https://www.tweet.im/">tweet.im</a>, which worked after a fashion.  It got the tweets into irssi, but it did it in some weird way so that irssi didn&#8217;t realise new messages had come in and hence it didn&#8217;t indicate there was activity when I was in a different irssi window.</p>
<p>At this point the little voice in my head that is the bane of my life started saying &#8220;You know, you could probably write your own gateway app.  How hard could it be?&#8221;.  Like a fool I listened to this voice, but for once it didn&#8217;t turn out disastrously.  A few hours later I had a functioning (one-way) twitter->XMPP app, written in python.</p>
<p>I&#8217;ve since learned that twitterspy has been rewritten in python and would have been a doddle to install.  Not only that but there is a public instance of it I could have used.  Still, I&#8217;m not immune to <a href="http://en.wikipedia.org/wiki/Not_Invented_Here">NIH</a> syndrome and having my own app to do it is nice.  If you want a twitter->XMPP gateway of your own though I suggest you try <a href="http://dustin.github.com/twitterspy/">twitterspy</a> first as it is much more capable (and mature) than my noddy little script.</p>
<p>But if you are interested, and because I like to boast about my tiny little achievements, here is twixm (I&#8217;ll give it its own page when I get round to it, but till then it is going to live in this blog post).</p>
<div class="dean_ch" style="white-space: nowrap;">
<p><span class="co1">#!/usr/bin/python -u</span><br />
<span class="co1">#</span><br />
<span class="co1"># This program is free software: you can redistribute it and/or modify</span><br />
<span class="co1"># it under the terms of the GNU General Public License as published by</span><br />
<span class="co1"># the Free Software Foundation, either version 2 of the License, or</span><br />
<span class="co1"># (at your option) any later version.</span><br />
<span class="co1">#</span><br />
<span class="co1"># This program is distributed in the hope that it will be useful,</span><br />
<span class="co1"># but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br />
<span class="co1"># MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. &nbsp;See the</span><br />
<span class="co1"># GNU General Public License for more details.</span><br />
<span class="co1">#</span><br />
<span class="co1"># You should have received a copy of the GNU General Public License</span><br />
<span class="co1"># along with this program. &nbsp;If not, see &lt;http://www.gnu.org/licenses/&gt;.</span><br />
<span class="co1"># </span></p>
<p>__author__ = <span class="st0">&quot;Ghworg&quot;</span><br />
__version__ = <span class="st0">&quot;1.0&quot;</span><br />
__description__ = <span class="st0">&quot;Twitter to XMPP gateway&quot;</span></p>
<p>
<span class="kw1">import</span> <span class="kw3">logging</span>, <span class="kw3">os</span>, <span class="kw3">signal</span>, <span class="kw3">sys</span>, <span class="kw3">threading</span>, <span class="kw3">time</span>, <span class="kw3">urllib</span></p>
<p><span class="kw1">import</span> simplejson</p>
<p><span class="kw1">try</span>:<br />
&nbsp; &nbsp; <span class="kw1">from</span> iniparse.<span class="me1">compat</span> <span class="kw1">import</span> <span class="kw3">ConfigParser</span><br />
<span class="kw1">except</span> <span class="kw2">ImportError</span>:<br />
&nbsp; &nbsp; <span class="kw1">from</span> <span class="kw3">ConfigParser</span> <span class="kw1">import</span> <span class="kw3">ConfigParser</span></p>
<p><span class="kw1">from</span> pyxmpp.<span class="me1">jid</span> <span class="kw1">import</span> JID<br />
<span class="kw1">from</span> pyxmpp.<span class="me1">jabber</span>.<span class="me1">simple</span> <span class="kw1">import</span> send_message</p>
<p>
<span class="kw1">class</span> WebApiOpener<span class="br0">&#40;</span><span class="kw3">urllib</span>.<span class="me1">FancyURLopener</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;<br />
&nbsp; &nbsp; Provides a way for HTTP Basic authentication to take place without<br />
&nbsp; &nbsp; prompting the user for a username and password like FancyURLopener<br />
&nbsp; &nbsp; would.<br />
&nbsp; &nbsp; &quot;</span><span class="st0">&quot;&quot;</span><br />
&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span>, username, password<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">urllib</span>.<span class="me1">FancyURLopener</span>.<span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span>,<span class="br0">&#123;</span><span class="br0">&#125;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">username</span> = username<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">password</span> = password<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span class="kw1">def</span> prompt_user_passwd<span class="br0">&#40;</span><span class="kw2">self</span>, host, realm<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;Handle Basic Auth automatically.&quot;</span><span class="st0">&quot;&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span><span class="kw2">self</span>.<span class="me1">username</span>, <span class="kw2">self</span>.<span class="me1">password</span><span class="br0">&#41;</span></p>
<p>
<span class="kw1">class</span> CaseSensitiveConfigParser<span class="br0">&#40;</span><span class="kw3">ConfigParser</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;Case Sensitive version of ConfigParser&quot;</span><span class="st0">&quot;&quot;</span><br />
&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">ConfigParser</span>.<span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; <span class="kw1">def</span> optionxform<span class="br0">&#40;</span><span class="kw2">self</span>, option<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;Make keys case-sensitive&quot;</span><span class="st0">&quot;&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">str</span><span class="br0">&#40;</span>option<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span class="kw1">def</span> getAndType<span class="br0">&#40;</span><span class="kw2">self</span>, section, option<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;Try to guess variable type and convert to type before returning&quot;</span><span class="st0">&quot;&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; rawVal = <span class="kw2">self</span>.<span class="me1">get</span><span class="br0">&#40;</span>section, option<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; isInt = <span class="kw2">True</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; isFloat = <span class="kw2">True</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> c <span class="kw1">in</span> rawVal:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="kw1">not</span> c.<span class="me1">isdigit</span><span class="br0">&#40;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; isInt = <span class="kw2">False</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> c != <span class="st0">&#8216;.&#8217;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; isFloat = <span class="kw2">False</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> isInt:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">int</span><span class="br0">&#40;</span>rawVal<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">elif</span> isFloat:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">float</span><span class="br0">&#40;</span>rawVal<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> rawVal</p>
<p>
<span class="kw1">def</span> msgToXMPP<span class="br0">&#40;</span>msg<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;Send a message to Jabber (XMPP)&quot;</span><span class="st0">&quot;&quot;</span><br />
&nbsp; &nbsp; jid = JID<span class="br0">&#40;</span>config<span class="br0">&#91;</span><span class="st0">&#8216;jid&#8217;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="kw1">not</span> jid.<span class="kw3">resource</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; jid = JID<span class="br0">&#40;</span>jid.<span class="me1">node</span>, jid.<span class="me1">domain</span>, <span class="st0">&#8216;send_message&#8217;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; recpt = JID<span class="br0">&#40;</span>config<span class="br0">&#91;</span><span class="st0">&#8216;jid&#8217;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw3">logging</span>.<span class="me1">debug</span><span class="br0">&#40;</span><span class="st0">&#8216;Sending to XMPP &nbsp;%s&#8217;</span> % msg<span class="br0">&#41;</span><br />
&nbsp; &nbsp; send_message<span class="br0">&#40;</span>jid, config<span class="br0">&#91;</span><span class="st0">&#8216;XMPPpass&#8217;</span><span class="br0">&#93;</span>, recpt, msg<span class="br0">&#41;</span></p>
<p><span class="kw1">def</span> getTweets<span class="br0">&#40;</span><span class="kw3">site</span>, maxTweets=<span class="nu0">1</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;Read in a list of tweets made since the last check&quot;</span><span class="st0">&quot;&quot;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="kw3">site</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> <span class="kw1">in</span> cache:<br />
&nbsp; &nbsp; &nbsp; &nbsp; url = <span class="st0">&#8216;%s?since_id=%d&#8217;</span> % <span class="br0">&#40;</span><span class="kw3">site</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span>, cache<span class="br0">&#91;</span><span class="kw3">site</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">else</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; url = <span class="st0">&#8216;%s?count=%d&#8217;</span> % <span class="br0">&#40;</span><span class="kw3">site</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span>, maxTweets<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; opener = WebApiOpener<span class="br0">&#40;</span><span class="kw3">site</span><span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span>, <span class="kw3">site</span><span class="br0">&#91;</span><span class="nu0">3</span><span class="br0">&#93;</span><span class="br0">&#41;</span> &nbsp; &nbsp; &nbsp; &nbsp;<br />
&nbsp; &nbsp; <span class="kw1">try</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">logging</span>.<span class="me1">debug</span><span class="br0">&#40;</span><span class="st0">&#8216;Requesting %s&#8217;</span> % url<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; webPage = opener.<span class="kw2">open</span><span class="br0">&#40;</span>url<span class="br0">&#41;</span> &nbsp; &nbsp; &nbsp; &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; jsonData = simplejson.<span class="me1">load</span><span class="br0">&#40;</span>webPage<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="st0">&#8216;error&#8217;</span> <span class="kw1">in</span> jsonData<span class="br0">&#41;</span> <span class="kw1">and</span> <span class="br0">&#40;</span>jsonData<span class="br0">&#91;</span><span class="st0">&#8216;error&#8217;</span><span class="br0">&#93;</span> != <span class="st0">&#8221;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">logging</span>.<span class="me1">warning</span><span class="br0">&#40;</span><span class="st0">&#8216;Error from server %s: %s&#8217;</span> % <span class="br0">&#40;</span>url, jsonData<span class="br0">&#91;</span><span class="st0">&#8216;error&#8217;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; jsonData = <span class="kw2">None</span><br />
&nbsp; &nbsp; <span class="kw1">except</span> <span class="kw2">IOError</span>, e:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">logging</span>.<span class="me1">error</span><span class="br0">&#40;</span>e<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">logging</span>.<span class="me1">error</span><span class="br0">&#40;</span><span class="st0">&#8216;URL = %s&#8217;</span> % src<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">except</span> <span class="kw2">ValueError</span>, e:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">logging</span>.<span class="me1">error</span><span class="br0">&#40;</span>e<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">logging</span>.<span class="me1">error</span><span class="br0">&#40;</span><span class="st0">&#8216;URL = %s&#8217;</span> % src<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; maxID = <span class="nu0">0</span><br />
&nbsp; &nbsp; <span class="kw1">for</span> tweet <span class="kw1">in</span> jsonData:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> tweet<span class="br0">&#91;</span>u<span class="st0">&#8216;id&#8217;</span><span class="br0">&#93;</span> &gt; maxID:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; maxID = tweet<span class="br0">&#91;</span>u<span class="st0">&#8216;id&#8217;</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; msg = <span class="st0">&#8216;%s (%s): %s&#8217;</span> % <span class="br0">&#40;</span>tweet<span class="br0">&#91;</span>u<span class="st0">&#8216;user&#8217;</span><span class="br0">&#93;</span><span class="br0">&#91;</span>u<span class="st0">&#8216;screen_name&#8217;</span><span class="br0">&#93;</span>, <span class="kw3">site</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>, tweet<span class="br0">&#91;</span>u<span class="st0">&#8216;text&#8217;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">logging</span>.<span class="me1">debug</span><span class="br0">&#40;</span><span class="st0">&#8216;Read tweet &nbsp;%s&#8217;</span> % msg<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; msgToXMPP<span class="br0">&#40;</span>msg<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> maxID</p>
<p><span class="kw1">def</span> run<span class="br0">&#40;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;Thread&quot;</span><span class="st0">&quot;&quot;</span><br />
&nbsp; &nbsp; <span class="kw1">while</span> <span class="kw2">True</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; startSignal.<span class="me1">wait</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> quitSignal.<span class="me1">isSet</span><span class="br0">&#40;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; startSignal.<span class="me1">clear</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> <span class="kw3">site</span> <span class="kw1">in</span> config<span class="br0">&#91;</span><span class="st0">&#8216;site&#8217;</span><span class="br0">&#93;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; maxID = getTweets<span class="br0">&#40;</span><span class="kw3">site</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw3">site</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> <span class="kw1">not</span> <span class="kw1">in</span> cache<span class="br0">&#41;</span> <span class="kw1">or</span> <span class="br0">&#40;</span>maxID &gt; cache<span class="br0">&#91;</span><span class="kw3">site</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cache<span class="br0">&#91;</span><span class="kw3">site</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#93;</span> = maxID</p>
<p><span class="kw1">def</span> readConfig<span class="br0">&#40;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;Load config settings&quot;</span><span class="st0">&quot;&quot;</span><br />
&nbsp; &nbsp; config = <span class="br0">&#123;</span><span class="br0">&#125;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; cfgfile = <span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">join</span><span class="br0">&#40;</span><span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">expanduser</span><span class="br0">&#40;</span><span class="st0">&#8216;~&#8217;</span><span class="br0">&#41;</span>, <span class="st0">&#8216;.twixmrc&#8217;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw3">parser</span> = CaseSensitiveConfigParser<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw3">parser</span>.<span class="me1">read</span><span class="br0">&#40;</span>cfgfile<span class="br0">&#41;</span><br />
&nbsp; &nbsp; settings = <span class="br0">&#123;</span><span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="kw1">for</span> section <span class="kw1">in</span> <span class="kw3">parser</span>.<span class="me1">sections</span><span class="br0">&#40;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="st0">&#8216;XMPP&#8217;</span> == section:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> optname <span class="kw1">in</span> <span class="kw3">parser</span>.<span class="me1">options</span><span class="br0">&#40;</span>section<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; config<span class="br0">&#91;</span>optname<span class="br0">&#93;</span> = <span class="kw3">parser</span>.<span class="me1">getAndType</span><span class="br0">&#40;</span>section, optname<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; siteName = section<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; siteUrl = <span class="kw3">parser</span>.<span class="me1">getAndType</span><span class="br0">&#40;</span>section, <span class="st0">&#8216;URL&#8217;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; siteUser = <span class="kw3">parser</span>.<span class="me1">getAndType</span><span class="br0">&#40;</span>section, <span class="st0">&#8216;Username&#8217;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sitePass = <span class="kw3">parser</span>.<span class="me1">getAndType</span><span class="br0">&#40;</span>section, <span class="st0">&#8216;Password&#8217;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">site</span> = <span class="br0">&#40;</span>siteName, siteUrl, siteUser, sitePass<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="st0">&#8216;site&#8217;</span> <span class="kw1">not</span> <span class="kw1">in</span> config:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; config<span class="br0">&#91;</span><span class="st0">&#8216;site&#8217;</span><span class="br0">&#93;</span> = <span class="br0">&#91;</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; config<span class="br0">&#91;</span><span class="st0">&#8216;site&#8217;</span><span class="br0">&#93;</span>.<span class="me1">append</span><span class="br0">&#40;</span><span class="kw3">site</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; config<span class="br0">&#91;</span><span class="st0">&#8216;cycleTime&#8217;</span><span class="br0">&#93;</span> = <span class="nu0">60.0</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span class="co1"># !!! Check for missing config settings and bail out</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span class="kw3">logging</span>.<span class="me1">debug</span><span class="br0">&#40;</span><span class="st0">&#8216;XMPP ID = %s&#8217;</span> % config<span class="br0">&#91;</span><span class="st0">&#8216;jid&#8217;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw3">logging</span>.<span class="me1">debug</span><span class="br0">&#40;</span><span class="st0">&#8216;XMPP Pass = %s&#8217;</span> % config<span class="br0">&#91;</span><span class="st0">&#8216;XMPPpass&#8217;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw3">logging</span>.<span class="me1">debug</span><span class="br0">&#40;</span><span class="st0">&#8216;Cycle Time = %s&#8217;</span> % config<span class="br0">&#91;</span><span class="st0">&#8216;cycleTime&#8217;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">for</span> <span class="kw3">site</span> <span class="kw1">in</span> config<span class="br0">&#91;</span><span class="st0">&#8216;site&#8217;</span><span class="br0">&#93;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">logging</span>.<span class="me1">debug</span><span class="br0">&#40;</span><span class="st0">&#8216;Site: %s&#8217;</span> % <span class="kw3">site</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">logging</span>.<span class="me1">debug</span><span class="br0">&#40;</span><span class="st0">&#8216;<span class="es0">\t</span>URL: %s&#8217;</span> % <span class="kw3">site</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">logging</span>.<span class="me1">debug</span><span class="br0">&#40;</span><span class="st0">&#8216;<span class="es0">\t</span>User: %s&#8217;</span> % <span class="kw3">site</span><span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">logging</span>.<span class="me1">debug</span><span class="br0">&#40;</span><span class="st0">&#8216;<span class="es0">\t</span>Pass: %s&#8217;</span> % <span class="kw3">site</span><span class="br0">&#91;</span><span class="nu0">3</span><span class="br0">&#93;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span class="kw1">return</span> config<br />
&nbsp; &nbsp; &nbsp; &nbsp; </p>
<p><span class="kw1">def</span> setupLogging<span class="br0">&#40;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;Setup python logging to stdout&quot;</span><span class="st0">&quot;&quot;</span><br />
&nbsp; &nbsp; log = <span class="kw3">logging</span>.<span class="me1">getLogger</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; logformat = <span class="st0">&#8216;%(asctime)s %(levelname)s %(message)s&#8217;</span><br />
&nbsp; &nbsp; dateformat = <span class="st0">&#8216;%Y-%m-%d %H:%M:%S&#8217;</span><br />
&nbsp; &nbsp; frmttr = <span class="kw3">logging</span>.<span class="me1">Formatter</span><span class="br0">&#40;</span>logformat, dateformat<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="co1">#if options.logfile:</span><br />
&nbsp; &nbsp; <span class="co1"># &nbsp; &nbsp;fhdlr = logging.FileHandler(options.logfile)</span><br />
&nbsp; &nbsp; <span class="co1"># &nbsp; &nbsp;fhdlr.setFormatter(frmttr)</span><br />
&nbsp; &nbsp; <span class="co1"># &nbsp; &nbsp;log.addHandler(fhdlr)</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="kw3">sys</span>.<span class="me1">stdin</span>.<span class="me1">isatty</span><span class="br0">&#40;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; shdlr = <span class="kw3">logging</span>.<span class="me1">StreamHandler</span><span class="br0">&#40;</span><span class="kw3">sys</span>.<span class="me1">stdout</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; shdlr.<span class="me1">setFormatter</span><span class="br0">&#40;</span>frmttr<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; log.<span class="me1">addHandler</span><span class="br0">&#40;</span>shdlr<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="co1">#log.setLevel(logging.DEBUG)</span><br />
&nbsp; &nbsp; log.<span class="me1">setLevel</span><span class="br0">&#40;</span><span class="kw3">logging</span>.<span class="me1">INFO</span><span class="br0">&#41;</span></p>
<p><span class="kw1">def</span> handler<span class="br0">&#40;</span>signum, frame<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;Handle various termination signals gracefully&quot;</span><span class="st0">&quot;&quot;</span><br />
&nbsp; &nbsp; <span class="kw3">logging</span>.<span class="me1">warning</span><span class="br0">&#40;</span><span class="st0">&#8216;Signal handler called with signal %d&#8217;</span> % signum<span class="br0">&#41;</span><br />
&nbsp; &nbsp; quitSignal.<span class="kw2">set</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; startSignal.<span class="kw2">set</span><span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p>
<span class="co1">###############################################################################</span><br />
<span class="co1"># Main</span><br />
<span class="co1">###############################################################################</span></p>
<p><span class="co1"># Set the signal handlers</span><br />
<span class="kw3">signal</span>.<span class="kw3">signal</span><span class="br0">&#40;</span><span class="kw3">signal</span>.<span class="me1">SIGTERM</span>, handler<span class="br0">&#41;</span><br />
<span class="kw3">signal</span>.<span class="kw3">signal</span><span class="br0">&#40;</span><span class="kw3">signal</span>.<span class="me1">SIGQUIT</span>, handler<span class="br0">&#41;</span><br />
<span class="kw3">signal</span>.<span class="kw3">signal</span><span class="br0">&#40;</span><span class="kw3">signal</span>.<span class="me1">SIGINT</span>, handler<span class="br0">&#41;</span></p>
<p>setupLogging<span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p>config = readConfig<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
cache = <span class="br0">&#123;</span><span class="br0">&#125;</span></p>
<p>
quitSignal = <span class="kw3">threading</span>.<span class="me1">Event</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
startSignal = <span class="kw3">threading</span>.<span class="me1">Event</span><span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p>runThread = <span class="kw3">threading</span>.<span class="me1">Thread</span><span class="br0">&#40;</span>target=run<span class="br0">&#41;</span><br />
runThread.<span class="me1">start</span><span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">while</span> <span class="kw2">False</span> == quitSignal.<span class="me1">isSet</span><span class="br0">&#40;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; startSignal.<span class="kw2">set</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; count = <span class="nu0">0.0</span><br />
&nbsp; &nbsp; <span class="kw1">while</span> count &lt; config<span class="br0">&#91;</span><span class="st0">&#8216;cycleTime&#8217;</span><span class="br0">&#93;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; quitSignal.<span class="me1">wait</span><span class="br0">&#40;</span><span class="nu0">0.5</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; count += <span class="nu0">0.5</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> quitSignal.<span class="me1">isSet</span><span class="br0">&#40;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">break</span><br />
<span class="kw3">logging</span>.<span class="me1">info</span><span class="br0">&#40;</span><span class="st0">&#8216;Exiting&#8217;</span><span class="br0">&#41;</span></p>
<p>&nbsp;</p></div>
<p>Update 2009-11-25:  I have created a page for <a href="/projects/twixm/">twixm</a> now.  Go there for the latest code and info.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.trollgod.org.uk/2009/03/twitter-to-xmpp-jabber/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
