<?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>su.percilio.us &#187; Nerdities</title>
	<atom:link href="http://su.percilio.us/category/nerdities/feed/" rel="self" type="application/rss+xml" />
	<link>http://su.percilio.us</link>
	<description>Haughtily disdainful or contemptuous</description>
	<lastBuildDate>Tue, 06 Apr 2010 15:58:28 +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>Setting Locale and Using PECL&#8217;s Imagick Library in PHP</title>
		<link>http://su.percilio.us/2010/04/setting-locale-and-using-pecls-imagick-library-in-php/</link>
		<comments>http://su.percilio.us/2010/04/setting-locale-and-using-pecls-imagick-library-in-php/#comments</comments>
		<pubDate>Mon, 05 Apr 2010 19:13:45 +0000</pubDate>
		<dc:creator>nick</dc:creator>
				<category><![CDATA[Nerdities]]></category>
		<category><![CDATA[imagemagick]]></category>
		<category><![CDATA[imagick]]></category>
		<category><![CDATA[locale]]></category>
		<category><![CDATA[pecl]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://su.percilio.us/?p=179</guid>
		<description><![CDATA[I ran across an interesting issue today. An issue, that when I Googled it, appeared to have been resolved 2 years ago. However, I was using up-to-date versions of PHP, ImageMagick and the Imagick PECL library. So, on to my issue. I have an abstract piece of code that when given the proper variables will [...]]]></description>
			<content:encoded><![CDATA[<p>I ran across an interesting issue today. An issue, that when I Googled it, appeared to have been resolved 2 years ago. However, I was using up-to-date versions of PHP, ImageMagick and the Imagick PECL library. </p>
<p>So, on to my issue. I have an abstract piece of code that when given the proper variables will set set the locale for my application. It sets the locale thusly:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #990000;">setlocale</span><span style="color: #009900;">&#40;</span>LC_ALL<span style="color: #339933;">,</span> <span style="color: #0000ff;">'fr_CA.utf8'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Later in the application, I was trying to draw a rectangle for a gauge that would graph a number against another number. When I tried to call the Imagick rectangle method, all hell broke loose.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$gauge</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ImagickDraw<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$x1</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$config</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">position</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">x1</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$y1</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$config</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">position</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">y1</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$x2</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$config</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">position</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">x2</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$y2</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$config</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">position</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">y2</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$gauge</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">rectangle</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$x1</span><span style="color: #339933;">,</span><span style="color: #000088;">$y1</span><span style="color: #339933;">,</span><span style="color: #000088;">$x2</span><span style="color: #339933;">,</span><span style="color: #000088;">$y2</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>I then got this lovely message:</p>

<div class="wp_syntax"><div class="code"><pre class="log" style="font-family:monospace;">Fatal error: Uncaught exception 'ImagickException' with message 'Non-conforming drawing primitive definition `,' @ draw.c/DrawImage/3123'</pre></div></div>

<p>Googled a bit and everything said this was fixed in the PECL library as of 2007. But it&#8217;s 2010 and I&#8217;m still having the issue!</p>
<p>Turns out if you set &#8220;LC_NUMERIC&#8221; to any French language locale, it can make interpreting floats difficult, because the French use commas (,) instead of periods (.) to delimit their fractions numerically. This caused the &#8220;rectangle&#8221; function of the &#8220;Imagick&#8221; PECL library to go crazy.</p>
<p>My Solution?</p>
<p>I altered my brash locale setting code to be a little more granular:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #990000;">setlocale</span><span style="color: #009900;">&#40;</span>LC_TIME<span style="color: #339933;">,</span> <span style="color: #0000ff;">'fr_CA.utf8'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">setlocale</span><span style="color: #009900;">&#40;</span>LC_MONETARY<span style="color: #339933;">,</span> <span style="color: #0000ff;">'fr_CA.utf8'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Setting locales for &#8220;LC_TIME&#8221; and &#8220;LC_MONETARY&#8221; was enough for me to get the programmatic localization I needed. And it made sure that &#8220;LC_NUMERIC&#8221; did not get set and cause localization on floats to interfere with external libraries.</p>
<p>This is &#8220;bang your head against the wall&#8221; stuff people. I hope this helps someone.</p>
<script type="text/javascript">
  addthis_url    = 'http%3A%2F%2Fsu.percilio.us%2F2010%2F04%2Fsetting-locale-and-using-pecls-imagick-library-in-php%2F';
  addthis_title  = 'Setting+Locale+and+Using+PECL%26%238217%3Bs+Imagick+Library+in+PHP';
  addthis_pub    = '';
</script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12" ></script>
]]></content:encoded>
			<wfw:commentRss>http://su.percilio.us/2010/04/setting-locale-and-using-pecls-imagick-library-in-php/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Developing a Facebook Application on a Virtual Machine</title>
		<link>http://su.percilio.us/2010/03/developing-a-facebook-application-on-a-virtual-machine/</link>
		<comments>http://su.percilio.us/2010/03/developing-a-facebook-application-on-a-virtual-machine/#comments</comments>
		<pubDate>Tue, 16 Mar 2010 20:55:23 +0000</pubDate>
		<dc:creator>nick</dc:creator>
				<category><![CDATA[Nerdities]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[applications]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[virtual machine]]></category>
		<category><![CDATA[vm]]></category>

		<guid isPermaLink="false">http://su.percilio.us/?p=153</guid>
		<description><![CDATA[A high-level, procedural view on a successfully implemented process for developing Facebook applications using a Virtual Development Environment.]]></description>
			<content:encoded><![CDATA[<p>Throughout my many development projects I have produced applications in many different fashions. I&#8217;ve written code by shelling into the production server and editing files that were serving up content to end users in real time (YIKES!). I&#8217;ve developed directly on test machines and SCPed files directly up to production servers (YIKES AGAIN!). In the last few years, however, I&#8217;ve worked with different companies, many of whom have much more formalized development procedures, and I&#8217;ve learned a few things &#8230; to put it lightly.</p>
<p>One of the more profound techniques I&#8217;ve brought away from my tenure as a web software developer, is the use of a Virtual Machine or Virtual Development Environment as the first step in the development process. I won&#8217;t go into the details of how Virtual Machines are utilized in a development procedure (hopefully if you&#8217;re reading you are already using a VM), but I will touch on a few of the basic concepts as I describe my procedure for developing Facebook applications using a VM.</p>
<p>Virtual Machines are great for development. Each engineer gets their very own server to develop on, that mirrors the test and production servers. They can hack away at core code (or installation specific code) in a completely sanitized environment and only add their code back into the shared pool when they&#8217;ve tested it thoroughly themselves. They could even create their own continuous integration server if they wanted to. I say these things only to reinforce the fact that <em>I</em> like to use VMs and even on small-scale projects I implement them. This brings us forward to the point of this post:</p>
<p><strong>Developing a Facebook Application on a Virtual Machine</strong></p>
<p><em><strong>NOTE:</strong> The examples below make some broad assumptions of your level of knowledge, like it assumes you have mod_proxy already enabled and it assumes that you already have your VM user talking successfuly to your test server user. This is just a high-level overview. Hopefully you can use your highly developed inference skills to fill in the gaps.</em></p>
<p>In my most recent incarnation as a &#8220;Web Developer,&#8221; I am the &#8220;Senior Developer&#8221; (read &#8220;Only Developer&#8221;) producing and maintaining a small-scale Facebook application. Please keep in mind that the following procedure is based on my current system at work and to follow it exactly would mean you have to have a similar infrastructure. I have a little Linux test machine on-site. It&#8217;s an old Dell desktop running Ubuntu DESKTOP, so nothing fancy at all. If you&#8217;re using an off-site test machine or Windows servers, you can probably still get some insight from this post, but the specific examples won&#8217;t be of much help.</p>
<p><img class="size-full wp-image-154" title="facebook-logo" src="http://su.percilio.us/wp-content/uploads/2010/03/facebook-logo.png" alt="Facebook Logo" width="300" height="167" /></p>
<p>Now, scale of the project aside, I like VMs, so I implemented one for developing this application. I set it up as a simple LAMP stack using Ubuntu Server 9.10 and turned on all the necessary pieces. I set up my standard framework and put everything into place. &#8220;This is great!&#8221; I thought. &#8220;I have completely streamlined this process! Look at this great little VM I have set up to develop on.&#8221;</p>
<p>Very soon after that I got my first ticket telling me we had to launch a new customer installation of the app. &#8220;All right!&#8221; I exclaimed. &#8220;I get to use the new VM!&#8221; </p>
<p><em><strong>NOTE:</strong> We do a white-label application, so it needs to be completely devoid of our influence. No corporate name or logo apart from the client&#8217;s is allowed to be seen, in doing this we create an  application on Facebook for each customer installation. This way we can have custom logos, description, and canvas page URLs per client. It get a bit unwieldy as we have to create <strong>TWO</strong> applications per client, a production application whose canvas callback URL points at our production system and a test application whose canvas callback URL points at our test server, but it works out well for our size.</em></p>
<p>The first step in launching a new client installation of our app is to create the test application. I log into our Facebook developer account and proceed to begin setting up the application. I get to the &#8220;Canvas Callback URL&#8221; section and a moment of severe disappointment grips me. The VM is completely internal and there is no way for Facebook to talk to it. Unless I&#8217;m willing to create a &#8220;Facebook VM application&#8221; for each of our developers (I know it&#8217;s only me, but I&#8217;m thinking of scalability here, people) and then there&#8217;s the problem of DNS entries, because every VM has an internal IP on our network, which is not visible to Facebook anyway.</p>
<p>BOO. It looked as if continuing to develop code directly on the test server was going to be the only way to test our Facebook application properly.</p>
<p>I wasn&#8217;t satisfied with that conclusion. I liked VMs. I liked sanitized development environments, especially when working with entry level developers. There had to be away around this.</p>
<p>I started down the road of trying to jury rig the application so it could function outside of Facebook. Meaning there didn&#8217;t need to be a Facebook frame around it and there didn&#8217;t have to be a valid Facebook session present. Then we could just access it via an internal IP like: http://192.168.54.75:/facebook-app or if we messed with our host file a bit http://nick-vm/facebook-app.</p>
<p>In the <em>VERY</em> long-term this could have been a viable option. Development would have been simple and the application could have had more breadth as it could have functioned as a standalone website. Due to time constraints, however, this was not going to work. It was surprisingly difficult to add code that could properly spoof a Facebook session and even if I had achieved that goal, it was turning my session code into spaghetti with all sorts of nasty environment based conditionals that added <strong>NO VALUE</strong> (and actually decreased value because of the increasingly unreadable code and creeping file size) to the final product that would live on the production server.</p>
<p>In a stroke of &#8220;genius&#8221; (read &#8220;Nick figuring something out&#8221;) I decided that the way to go about this would be to trick Facebook into thinking the content served to it was coming from the test server, when in fact, it was coming from my VM.</p>
<p>With some tricky BASH scripting and Apache&#8217;s very convenient mod_proxy module, I was able to create an automated check in/check out system that would tell the test server to take Facebook&#8217;s incoming HTTP request and forward it along to an internal machine &#8230; my VM, on a temporary basis. This meant that the content being served to Facebook would be coming from my virtual machine using the test server as the intermediary. </p>
<p>There was a number of things gained by this approach. The canvas callback URL in Facebook could permanently remain as &#8220;http://application.testserver.com/,&#8221; there would not need to be any changes to the application business logic, and core code could be developed by an engineer with no harm coming to code on the test server that was currently powering the test installations.</p>
<p>The check in/check out scripts were superbly easy to write too and were easily executable directly from the VM. Each script, when you boil it right down, needed to accomplish one thing. The &#8220;check out&#8221; script needed to alter the Apache virtual host on the test server to proxy the request through to the virtual machine &#8211; and the &#8220;check in&#8221; script simply needed to reverse this process.</p>
<p>So, the first thing we needed was a vanilla virtual host file that could be used as the proxy template:</p>

<div class="wp_syntax"><div class="code"><pre class="apache" style="font-family:monospace;">&lt;<span style="color: #000000; font-weight:bold;">VirtualHost</span> *:<span style="color: #ff0000;">80</span>&gt;
    <span style="color: #00007f;">ServerName</span> {appname}.testserver.com
    <span style="color: #00007f;">RewriteEngine</span> <span style="color: #0000ff;">On</span>
    <span style="color: #00007f;">RewriteRule</span> ^(.*)$ http://{<span style="color: #00007f;">user</span>}-vm$<span style="color: #ff0000;">1</span> [P]
&lt;/<span style="color: #000000; font-weight:bold;">VirtualHost</span>&gt;</pre></div></div>

<p>Replacing the {appname} and {user} variables using a BASH script, AND making sure that the necessary entries were present in the test server&#8217;s host file, AND ensuring my virtual machine had a static internal IP, AND ensuring that my virtual machine had a virtual host file that accepted the HTTP request &#8220;nick-vm&#8221;, AND ensuring that Apache got bounced on both my virtual machine and the test server &#8230; made everything work perfectly. Facebook never knew the difference.</p>
<p>Here&#8217;s a snippet of the BASH check out script that shows how to edit this file. You&#8217;ll have to visualize in your minds how the variables get populated:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">ssh</span> testserver.com <span style="color: #c20cb9; font-weight: bold;">mv</span> <span style="color: #007800;">$VHOSTDIR</span><span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">$APPNAME</span>.conf <span style="color: #007800;">$VHOSTDIR</span><span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">$APPNAME</span>.conf.checked.out.by.<span style="color: #007800;">$USER</span>
<span style="color: #c20cb9; font-weight: bold;">ssh</span> testserver.com <span style="color: #c20cb9; font-weight: bold;">cp</span> <span style="color: #660033;">-f</span> <span style="color: #007800;">$VHOSTDIR</span><span style="color: #000000; font-weight: bold;">/</span>vhost-checkedout-template.conf <span style="color: #007800;">$VHOSTDIR</span><span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">$APPNAME</span>.conf
<span style="color: #c20cb9; font-weight: bold;">ssh</span> testserver.com <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-i</span> <span style="color: #ff0000;">&quot;s/\{appname\}/<span style="color: #007800;">$NAME</span>/g&quot;</span> <span style="color: #007800;">$VHOSTDIR</span><span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">$APPNAME</span>.conf
<span style="color: #c20cb9; font-weight: bold;">ssh</span> testserver.com <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-i</span> <span style="color: #ff0000;">&quot;s/\{user\}/<span style="color: #007800;">$USER</span>/g&quot;</span> <span style="color: #007800;">$VHOSTDIR</span><span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">$APPNAME</span>.conf
<span style="color: #c20cb9; font-weight: bold;">ssh</span> testserver.com <span style="color: #c20cb9; font-weight: bold;">chmod</span> <span style="color: #000000;">644</span> <span style="color: #007800;">$VHOSTDIR</span><span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">$APPNAME</span>.conf
<span style="color: #c20cb9; font-weight: bold;">ssh</span> testserver.com <span style="color: #c20cb9; font-weight: bold;">chown</span> <span style="color: #007800;">$USER</span>:dev <span style="color: #007800;">$VHOSTDIR</span><span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">$APPNAME</span>.conf</pre></div></div>

<p>That would spit out a vhost that looked like this:</p>

<div class="wp_syntax"><div class="code"><pre class="apache" style="font-family:monospace;">&lt;<span style="color: #000000; font-weight:bold;">VirtualHost</span> *:<span style="color: #ff0000;">80</span>&gt;
    <span style="color: #00007f;">ServerName</span> app1.testserver.com
    <span style="color: #00007f;">RewriteEngine</span> <span style="color: #0000ff;">On</span>
    <span style="color: #00007f;">RewriteRule</span> ^(.*)$ http://nick-vm$<span style="color: #ff0000;">1</span> [P]
&lt;/<span style="color: #000000; font-weight:bold;">VirtualHost</span>&gt;</pre></div></div>

<p>The original virtual host file would be safe and sound &#8211; copied over to a file called &#8220;app1.checked.out.by.nick.&#8221; This would make it instantly apparent just by looking at the file system that the app was being edited by someone. This was also the way the check out script would know it could not check that file out until it was checked back in again.</p>
<p>After bouncing Apache, this virtual host would make sure all requests to app1 from Facebook went through to my virtual machine. Of course, the test server needed to know that &#8220;nick-vm&#8221; pointed to my VM. So, I gave my virtual machine a static IP and made sure the test machine&#8217;s host file had that record:</p>

<div class="wp_syntax"><div class="code"><pre class="ini" style="font-family:monospace;">nick-vm    192.168.54.75</pre></div></div>

<p>This is really the only &#8220;unscalable&#8221; piece of this system. For every engineer you onboard, you need to allocate a unique static internal IP for their VM and add the record to your test server&#8217;s host file. But the onboarding process will include creating accounts for them anyway, so you can just make this part of that procedure.</p>
<p>Once the app was checked out and the necessary code edited, all the check in script had to do was reverse the process:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">ssh</span> testserver.com <span style="color: #c20cb9; font-weight: bold;">mv</span> <span style="color: #007800;">$VHOSTDIR</span><span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">$APPNAME</span>.conf.checked.out.by.<span style="color: #007800;">$USER</span> <span style="color: #007800;">$VHOSTDIR</span><span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">$APPNAME</span>.conf</pre></div></div>

<p>Then bounce Apache on both the test server and the VM. Done and done. </p>
<p>Now, my specific check in/check out scripts did other things like packaging up databases and checking app code out of Subversion. They also fixed permission and did everything needed to properly configure an installation to run on a server. But the key point was it used the Apache virtual host files on the test server to create that connection between Facebook and the virtual machine.</p>
<p>A relatively large caveat to this system is that only one engineer can work on an application at any one time and the virtual machine version of the installation becomes visible to ANYONE in the world who adds the test application to their Facebook account. Since, it&#8217;s only a test application, this isn&#8217;t too big a deal, and can be combated by adding some sort of staging environment to your development process. This will ensure that clients never see test versions of the application, but it will also mean that each application installation will require three Facebook applications instead of two.</p>
<p>In the end I found this to be a pretty elegant solution. Multiple engineers could work on multiple apps and test them directly through Facebook. The biggest gain was that the core application code that was shared between all installations could be edited without ever impacting the stability of the core code on the test server. This meant that if you were changing core functionality, only one app at a time would be affected. This was a HUGELY significant, because clients could be testing their applications on the test server and I could be developing core code on my VM and the integrity of their applications would not be affected.</p>
<p>You may think that this is a bit of overkill for your application, but try to look at it this way: too many applications are not given the serious attention they need at the beginning and wind up being amateurishly written applications that have important jobs to do that they are incapable of doing. If you take some large-scale approaches in the beginning, you can save yourself A LOT of headaches later on. And we all do want our Facebook applications to become the next big thing &#8230; don&#8217;t we?</p>
<p><em><strong>INTERESTING NOTE:</strong> I should add that I have successfully deployed this technique via VPN. So, I can have my VM running on my laptop at home, VPN into my office, and have the test server proxy the HTTP request from Facebook over VPN back to my VM at home. This means you do not even have to be at the office to check out an application installation and work on it. There might be an eensy-weensie loss of performance this way, but that&#8217;s a small price to pay to be able to write software in your skivvies.</em></p>
<script type="text/javascript">
  addthis_url    = 'http%3A%2F%2Fsu.percilio.us%2F2010%2F03%2Fdeveloping-a-facebook-application-on-a-virtual-machine%2F';
  addthis_title  = 'Developing+a+Facebook+Application+on+a+Virtual+Machine';
  addthis_pub    = '';
</script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12" ></script>
]]></content:encoded>
			<wfw:commentRss>http://su.percilio.us/2010/03/developing-a-facebook-application-on-a-virtual-machine/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Convio Web Services in Python and PHP</title>
		<link>http://su.percilio.us/2009/10/convio-web-services-in-python-and-php/</link>
		<comments>http://su.percilio.us/2009/10/convio-web-services-in-python-and-php/#comments</comments>
		<pubDate>Fri, 16 Oct 2009 17:42:20 +0000</pubDate>
		<dc:creator>nick</dc:creator>
				<category><![CDATA[Nerdities]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[convio]]></category>
		<category><![CDATA[cws]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[soap]]></category>
		<category><![CDATA[suds]]></category>

		<guid isPermaLink="false">http://su.percilio.us/?p=137</guid>
		<description><![CDATA[Expanding on my last post about being able to successfully connect to Convio Web Services in three lines, I&#8217;d like to get a little more in depth and actually construct the necessary SOAP headers and make a simple call. I&#8217;ve written a small PHP implementation as well. I was able to make a successful log [...]]]></description>
			<content:encoded><![CDATA[<p>Expanding on my last post about being able to successfully connect to Convio Web Services in three lines, I&#8217;d like to get a little more in depth and actually construct the necessary SOAP headers and make a simple call. I&#8217;ve written a small PHP implementation as well. I was able to make a successful log in to CWS in just <em>2 lines</em> of PHP code!</p>
<div style="text-align: center; margin-bottom: 10px"><img class="size-medium wp-image-117" style="border: 1px solid #ccc; padding: 5px; margin: 0 auto; background: none" src="http://su.percilio.us/wp-content/uploads/2009/10/convio_logo-300x160.gif" alt="Convio Logo" title="Convio Logo" width="300" height="160"  /></div>
<p>Now, as far as CWS goes, Python and PHP may not instantly be an obvious choice as far as languages go, mainly because they are both largely scripting languages. CWS is mainly for robust data syncing operations and those tasks generally go to languages like Java or C#, however, I&#8217;m a high level language guy, so I  go with what I know. Also, Python and PHP both make SOAP exceedingly easy to work with, so there&#8217;s no real reason why you can&#8217;t, with a bit of discipline, write a perfectly excellent and robust data sync operation in either of these languages &#8230; especially Python.</p>
<p>So, here are my examples. They are exceedingly simple and easy once again. The Python example leverages suds once again and the PHP example is using PHP&#8217;s pretty impressive built in SOAP library. Each example shows you how to create the SOAP client using the Convio WSDL, make a successful log in to CWS, create a valid session header for subsequent calls, and how to make a call that grabs the number of constituents that have been added to the Convio database.</p>
<p>If you find either of these examples helpful, please let me know! Keep in mind these are just functional examples. There is no proper error handling or any sort of architecture here; they are just some bare bones examples on how to get data from CWS.</p>
<p><strong>Python</strong></p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> suds.<span style="color: black;">client</span> <span style="color: #ff7700;font-weight:bold;">import</span> Client
&nbsp;
<span style="color: #808080; font-style: italic;"># Load the WSDL                                                                                                                                                                                                                                </span>
client = Client<span style="color: black;">&#40;</span><span style="color: #483d8b;">'https://secureX.convio.net/1.0/CLIENT/wsdl'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Log in to CWS                                                                                                                                                                                                                                </span>
login = client.<span style="color: black;">service</span>.<span style="color: black;">Login</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'apiadmin'</span>, <span style="color: #483d8b;">'password'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Set the session header                                                                                                                                                                                                                       </span>
session = client.<span style="color: black;">factory</span>.<span style="color: black;">create</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Session'</span><span style="color: black;">&#41;</span>
session.<span style="color: black;">SessionId</span> = login.<span style="color: black;">SessionId</span>
client.<span style="color: black;">set_options</span><span style="color: black;">&#40;</span>soapheaders=session<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Get the number of constituents added since last sync                                                                                                                                                                                         </span>
data = <span style="color: #008000;">dict</span><span style="color: black;">&#40;</span>PartitionId=<span style="color: #ff4500;">1001</span>, RecordType=<span style="color: #483d8b;">'Constituent'</span>, PageSize=<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
response = client.<span style="color: black;">service</span>.<span style="color: black;">GetIncrementalInsertsCount</span><span style="color: black;">&#40;</span><span style="color: #66cc66;">**</span>data<span style="color: black;">&#41;</span><span style="color: #66cc66;">;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Show the number of constituents added                                                                                                                                                                                                        </span>
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'%d constituents have been added since the last sync.'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span><span style="color: #008000;">int</span><span style="color: black;">&#40;</span>response.<span style="color: black;">RecordCount</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></div></div>

<p><strong>PHP</strong></p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// Load the WSDL                                                                                                                                                                                                                               </span>
<span style="color: #000088;">$client</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> SoapClient<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'https://secureX.convio.net/1.0/CLIENT/wsdl'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Log in to CWS                                                                                                                                                                                                                               </span>
<span style="color: #000088;">$login</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$client</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">Login</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'UserName'</span><span style="color: #339933;">=&gt;</span><span style="color: #0000ff;">'apiadmin'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Password'</span><span style="color: #339933;">=&gt;</span><span style="color: #0000ff;">'password'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Set the session header                                                                                                                                                                                                                      </span>
<span style="color: #000088;">$headerBody</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'SessionId'</span><span style="color: #339933;">=&gt;</span><span style="color: #000088;">$login</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">Result</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">SessionId</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$header</span>     <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> SoapHeader<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'urn:soap.convio.com'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Session'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$headerBody</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$client</span><span style="color: #339933;">-&gt;</span>__setSoapHeaders<span style="color: #009900;">&#40;</span><span style="color: #000088;">$header</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Get the number of constituents added since last sync                                                                                                                                                                                        </span>
<span style="color: #000088;">$data</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span>
<span style="color: #009900;">&#40;</span>
    <span style="color: #0000ff;">'PartitionId'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">1001</span><span style="color: #339933;">,</span>
    <span style="color: #0000ff;">'RecordType'</span>  <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'Constituent'</span><span style="color: #339933;">,</span>
    <span style="color: #0000ff;">'PageSize'</span>    <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">1</span>
<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$response</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$client</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">GetIncrementalInsertsCount</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$data</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Show the number of constituents added                                                                                                                                                                                                       </span>
<span style="color: #b1b100;">print</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">sprintf</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;<span style="color: #009933; font-weight: bold;">%d</span> constituents have been added since the last sync<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#40;</span>int<span style="color: #009900;">&#41;</span> <span style="color: #000088;">$response</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">Result</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">RecordCount</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<script type="text/javascript">
  addthis_url    = 'http%3A%2F%2Fsu.percilio.us%2F2009%2F10%2Fconvio-web-services-in-python-and-php%2F';
  addthis_title  = 'Convio+Web+Services+in+Python+and+PHP';
  addthis_pub    = '';
</script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12" ></script>
]]></content:encoded>
			<wfw:commentRss>http://su.percilio.us/2009/10/convio-web-services-in-python-and-php/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Log In to Convio Web Services with three lines of Python</title>
		<link>http://su.percilio.us/2009/10/log-in-to-convio-web-services-with-three-lines-of-python/</link>
		<comments>http://su.percilio.us/2009/10/log-in-to-convio-web-services-with-three-lines-of-python/#comments</comments>
		<pubDate>Wed, 14 Oct 2009 19:16:04 +0000</pubDate>
		<dc:creator>nick</dc:creator>
				<category><![CDATA[Nerdities]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[convio]]></category>
		<category><![CDATA[cws]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[soap]]></category>
		<category><![CDATA[suds]]></category>

		<guid isPermaLink="false">http://su.percilio.us/?p=130</guid>
		<description><![CDATA[I was on the look out for a good SOAP library for Python now that I am the new Convio &#8220;API Guy.&#8221; In my search I discovered this library: Suds To test it out I tried making successful connection to Convio Web Services. 1 2 3 from suds.client import Client client = Client&#40;'https://secureX.convio.net/1.0/CLIENT/wsdl'&#41; result = [...]]]></description>
			<content:encoded><![CDATA[<p>I was on the look out for a good SOAP library for Python now that I am the new Convio &#8220;API Guy.&#8221;</p>
<div style="text-align: center; margin-bottom: 10px"><img class="size-medium wp-image-117" style="border: 1px solid #ccc; padding: 5px; margin: 0 auto; background: none" src="http://su.percilio.us/wp-content/uploads/2009/10/convio_logo-300x160.gif" alt="Convio Logo" title="Convio Logo" width="300" height="160"  /></div>
<p>In my search I discovered this library:</p>
<p><a href="https://fedorahosted.org/suds/" target="_blank">Suds</a></p>
<p>To test it out I tried making successful connection to Convio Web Services.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> suds.<span style="color: black;">client</span> <span style="color: #ff7700;font-weight:bold;">import</span> Client
client = Client<span style="color: black;">&#40;</span><span style="color: #483d8b;">'https://secureX.convio.net/1.0/CLIENT/wsdl'</span><span style="color: black;">&#41;</span>
result = client.<span style="color: black;">service</span>.<span style="color: black;">Login</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'apiadmin'</span>, <span style="color: #483d8b;">'password'</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Boom. Straight in, no fuss no muss. Pretty impressive. I&#8217;m going to play with Suds and CWS a bit more to see if there is actually a robust Python based syncing application that can be made here. I&#8217;m led to believe Suds is not great for creating SOAP servers, but it makes for a very &#8220;Pythonic&#8221; and easy to understand way to create a SOAP client.</p>
<script type="text/javascript">
  addthis_url    = 'http%3A%2F%2Fsu.percilio.us%2F2009%2F10%2Flog-in-to-convio-web-services-with-three-lines-of-python%2F';
  addthis_title  = 'Log+In+to+Convio+Web+Services+with+three+lines+of+Python';
  addthis_pub    = '';
</script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12" ></script>
]]></content:encoded>
			<wfw:commentRss>http://su.percilio.us/2009/10/log-in-to-convio-web-services-with-three-lines-of-python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP Library For Convio Open API</title>
		<link>http://su.percilio.us/2009/10/php-library-for-convio-open-api/</link>
		<comments>http://su.percilio.us/2009/10/php-library-for-convio-open-api/#comments</comments>
		<pubDate>Tue, 13 Oct 2009 17:12:08 +0000</pubDate>
		<dc:creator>nick</dc:creator>
				<category><![CDATA[Nerdities]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[convio]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://su.percilio.us/?p=118</guid>
		<description><![CDATA[If any of you out there use Convio for your non-profit&#8217;s on-line presence, ie website, donations, email campaigns, I&#8217;ve created a PHP library for connecting to their Open API. I say it&#8217;s a &#8220;Library&#8221;&#8230; it&#8217;s really just a single wrapper file that aids in connecting to, making call to, and handling responses from, the Convio [...]]]></description>
			<content:encoded><![CDATA[<p>If any of you out there use <a href="http://convio.com" target="_blank">Convio</a> for your non-profit&#8217;s on-line presence, ie website, donations, email campaigns, I&#8217;ve created a PHP library for connecting to their Open API.</p>
<div style="text-align: center; margin-bottom: 10px"><img class="size-medium wp-image-117" style="border: 1px solid #ccc; padding: 5px; margin: 0 auto; background: none" src="http://su.percilio.us/wp-content/uploads/2009/10/convio_logo-300x160.gif" alt="Convio Logo" title="Convio Logo" width="300" height="160"  /></div>
<p>I say it&#8217;s a &#8220;Library&#8221;&#8230; it&#8217;s really just a single wrapper file that aids in connecting to, making call to, and handling responses from, the Convio Open APIs.</p>
<p>There&#8217;s no documentation to speak of, but the two files included in the zip archive are pretty solidly commented, so you will probably be able to get a lot from them. The two files included in the zip are the library file itself and an example of how to implement it.</p>
<p>If you end up using it, let me know what you think!</p>
<p><strong><a href="http://su.percilio.us/files/convio-api-php.zip">Download the PHP Library for Convio Open API</a></strong></p>
<script type="text/javascript">
  addthis_url    = 'http%3A%2F%2Fsu.percilio.us%2F2009%2F10%2Fphp-library-for-convio-open-api%2F';
  addthis_title  = 'PHP+Library+For+Convio+Open+API';
  addthis_pub    = '';
</script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12" ></script>
]]></content:encoded>
			<wfw:commentRss>http://su.percilio.us/2009/10/php-library-for-convio-open-api/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>SXSW Interactive</title>
		<link>http://su.percilio.us/2009/03/sxsw-interactive/</link>
		<comments>http://su.percilio.us/2009/03/sxsw-interactive/#comments</comments>
		<pubDate>Thu, 12 Mar 2009 14:53:09 +0000</pubDate>
		<dc:creator>nick</dc:creator>
				<category><![CDATA[Nerdities]]></category>
		<category><![CDATA[News]]></category>
		<category><![CDATA[sxsw]]></category>

		<guid isPermaLink="false">http://su.percilio.us/?p=75</guid>
		<description><![CDATA[Another year has passed. New lines have formed on my face, my stoop has become a little more pronounced, and another South by Southwest is upon us. Ah, South by Southwest, or SXSW as it&#8217;s more commonly known. Because, of course, how could a music and film festival possibly consider itself trendy unless one boils [...]]]></description>
			<content:encoded><![CDATA[<p>Another year has passed. New lines have formed on my face, my stoop has become a little more pronounced, and another South by Southwest is upon us. Ah, South by Southwest, or SXSW as it&#8217;s more commonly known. Because, of course, how could a music and film festival possibly consider itself trendy unless one boils it down into a soulless, meaningless acronym. OMG SXSW is FAB like ACL.</p>
<p>So, once a year our fair little central Texas city is descended upon by cous-cous eating, cilantro seasoning, south Cali, Apple fan boys for three weeks of self-satisfying, self-appreciating, and self-nauseating fawning over music and film that&#8217;s too smart to be interesting. BTW, Chucks and horn-rimmed glasses aside, this entry has been, so far, largely self-loathing, as I am writing this very entry on a netbook running OSX and have just checked the time and weather on my iPhone. WTF ROFL AFK BRB OK. Oh and I&#8217;ve been listening to nothing but Silversun Pickups and M83, so I&#8217;m just about ready to watch <em>MINE: Taken by Katrina</em>.</p>
<p>Cynicism aside, SXSW brings a lot of interesting people and art to Austin and one of the interesting and less publicized aspects is &#8220;Interactive,&#8221; five days of technology related trade shows, keynotes, and seminars. I have been given the opportunity, by my great employer, sorry, MGE, to attend this year&#8217;s interactive event. Being that this is the first time I&#8217;ll be attending SXSW I&#8217;m excited to see what all the hub-bub is about and what sort of douchebaggery I&#8217;ll be faced with.</p>
<p><em>Editor&#8217;s Note: Firefox underlines all my misspellings. It underlined &#8220;netbook&#8221;, &#8220;iPhone&#8221;, but not &#8220;douchebaggery&#8221; &#8230; awesome.</em></p>
<script type="text/javascript">
  addthis_url    = 'http%3A%2F%2Fsu.percilio.us%2F2009%2F03%2Fsxsw-interactive%2F';
  addthis_title  = 'SXSW+Interactive';
  addthis_pub    = '';
</script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12" ></script>
]]></content:encoded>
			<wfw:commentRss>http://su.percilio.us/2009/03/sxsw-interactive/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JProQuiz: Javascript Quiz Software</title>
		<link>http://su.percilio.us/2008/08/jproquiz-javascript-quiz-software/</link>
		<comments>http://su.percilio.us/2008/08/jproquiz-javascript-quiz-software/#comments</comments>
		<pubDate>Wed, 06 Aug 2008 21:05:43 +0000</pubDate>
		<dc:creator>nick</dc:creator>
				<category><![CDATA[Nerdities]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[prototype]]></category>
		<category><![CDATA[scriptaculous]]></category>

		<guid isPermaLink="false">http://su.percilio.us/?p=43</guid>
		<description><![CDATA[A couple of weeks ago a friend asked me if I&#8217;d be interested doing a little contract work for the company he works for. The project was to come up with an on line quiz, mimicking that of FreeRice.com. Reasonably simple I thought, so I figured it might be good for a laugh and few [...]]]></description>
			<content:encoded><![CDATA[<p>A couple of weeks ago a friend asked me if I&#8217;d be interested doing a little contract work for the company he works for. The project was to come up with an on line quiz, mimicking that of <a title="FreeRice.com" href="http://freerice.com" target="_blank">FreeRice.com</a>. Reasonably simple I thought, so I figured it might be good for a laugh and few pennies. The caveat being, if possible, for it to be entirely browser-side, as his company&#8217;s software did not support server-side code. Now <em>that</em> sounded interesting.</p>
<p>Being the impulsive code-monkey that I am, instead of waiting for the finalization of my contract to come through, I simply went ahead and coded the whole thing. Naturally, they decided to give this to someone internal and not hire me, so their loss is your gain. I didn&#8217;t have anything to do with this software after I&#8217;d written it, so I figured I would publish it here on my blog for the whole world to use.</p>
<p>The software itself is incredibly simple. Actually, I hesitate to call it software at all. It&#8217;s just one Javascript class file, some specifically name HTML elements and a single Javascript call to start the whole thing up. I like the Prototype framework, so I decided to use that to power JProQuiz, hence the &#8220;Pro&#8221; part. I also used the Scriptaculous builder so I wouldn&#8217;t have too much messy HTML in the class file. The entire class file (<a title="quiz.js" href="http://su.percilio.us/examples/jproquiz/inc/quiz.js" target="_blank">quiz.js</a>) is less than 300 lines long and the majority of those are comments. (Can you tell I&#8217;m a little proud of it?)</p>
<p>The basic idea is a single class that acts as an engine and using a JSON configuration file, which contains all the quiz questions, options, and correct answers, drives the entire quiz experience for the user. Now, you&#8217;re probably wondering: &#8220;How do you keep the JSON config file obfuscated so that people can&#8217;t just look at the answers?&#8221; Err&#8230; well&#8230; you can&#8217;t. This quiz is entirely browser-side, so the data has to be available to the front end. The JSON file is sort of buried in the class file, so it&#8217;s definitely not immediately obvious where the questions are coming from. It would take someone who knew their way around Javascript to figure out what was going on. And if someone really wants to dig through your code and find your JSON file and read all the answers so they can get a 100% on your little web quiz, well, boogaloo for them. So, don&#8217;t use JProQuiz to power the new on line SATs, just use it for fun little quizzes.</p>
<p>You can <a title="Download JProQuiz" href="http://su.percilio.us/files/jproquiz.zip" target="_self">download JProQuiz here</a>.</p>
<p>And you can <a title="Example of JProQuiz" href="http://su.percilio.us/examples/jproquiz" target="_blank">see a live example here</a>.</p>
<p>If you use JProQuiz please let me know by commenting below. Or if you have any questions, suggestions, or bugs . . . bring &#8216;em on!</p>
<script type="text/javascript">
  addthis_url    = 'http%3A%2F%2Fsu.percilio.us%2F2008%2F08%2Fjproquiz-javascript-quiz-software%2F';
  addthis_title  = 'JProQuiz%3A+Javascript+Quiz+Software';
  addthis_pub    = '';
</script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12" ></script>
]]></content:encoded>
			<wfw:commentRss>http://su.percilio.us/2008/08/jproquiz-javascript-quiz-software/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Last.FM PHP Image Screen Scraper</title>
		<link>http://su.percilio.us/2008/07/lastfm-php-image-screen-scraper/</link>
		<comments>http://su.percilio.us/2008/07/lastfm-php-image-screen-scraper/#comments</comments>
		<pubDate>Thu, 24 Jul 2008 01:21:24 +0000</pubDate>
		<dc:creator>nick</dc:creator>
				<category><![CDATA[Nerdities]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[last.fm]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://su.percilio.us/?p=32</guid>
		<description><![CDATA[I&#8217;m pretty avid user of Last.FM. I&#8217;m not big on this social networking fad, even if I do work in the industry, but I&#8217;ve found Last.FM very useful, mainly for finding new music. I&#8217;m currently building a web-based media manger in PHP and wanted a way to automatically get images for the artists. I originally [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m pretty avid user of <a title="last.fm" href="http://last.fm" target="_blank">Last.FM</a>. I&#8217;m not big on this social networking fad, even if I do work in the industry, but I&#8217;ve found Last.FM very useful, mainly for finding new music. I&#8217;m currently building a web-based media manger in PHP and wanted a way to automatically get images for the artists.</p>
<p>I originally used the <a title="discogs.com" href="http://discogs.com" target="_blank">discogs.com</a> API and although it was pretty easy to use and reasonably comprehensive, I was really disappointed in the quality of the images, not to mention I was constantly getting back images of electronic and ambient artists who had names similar to the rock bands in my collection, rather than the rock band themselves. I&#8217;m sorry, but when make a call to get images for &#8220;Cream&#8221; I don&#8217;t expect to get back some 14-year-old kid with a turntable and a DAT machine; I want freaking Clapton, Bruce, and Baker.</p>
<p>So, discogs.com left me a bit cold. But I soon learned about Last.FM and was delighted when I discovered their API. The image quality at Last.FM is superb, so I knew I wouldn&#8217;t be disappointed there. I started researching their API and realized that they didn&#8217;t really give me any info I needed other than the images and I didn&#8217;t want to have to sign up for an API key if all I wanted to do was download pictures of bands. Also, they only appear to provide three sizes of images and for many bands they have a whole slew of images available: large, medium, small, smaller, square; I wanted them all, not just the three provided by their API.</p>
<p>So, in the end I decided not to sign up for a Last.FM API key and instead wrote a very simple little PHP screen scraper that would bring back all of the images I wanted. Last.FM actually aided me in my goal by embedding a JSON string with just exactly what I needed right onto the artist page. It worked very well, so I decided to stick with it.</p>
<p>You can <a title="Last.FM PHP Image Screen Scraper" href="http://su.percilio.us/files/lastfm.zip" target="_self">download my simple screen scraper script here</a>. The zip file includes the class file and an example file.</p>
<p>It&#8217; an incredibly simple script. Just a basic class file with only one useable method. It&#8217;s written so it can be expanded, but as Last.FM&#8217;s API is under constant development, it probably won&#8217;t be. But if you just want a simple script to grab artist images from Last.FM, please download my script and let me know if you like it.</p>
<script type="text/javascript">
  addthis_url    = 'http%3A%2F%2Fsu.percilio.us%2F2008%2F07%2Flastfm-php-image-screen-scraper%2F';
  addthis_title  = 'Last.FM+PHP+Image+Screen+Scraper';
  addthis_pub    = '';
</script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12" ></script>
]]></content:encoded>
			<wfw:commentRss>http://su.percilio.us/2008/07/lastfm-php-image-screen-scraper/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>
