root/trunk/website/org/sweettweets/shrinkURL.cfc

Revision 5, 19.2 kB (checked in by DanWilson, 17 years ago)

Initial Commit Of ModelGlue? Website (upgrade to blogcfc 511)

Line 
1<!---
2        Name: shrinkURL
3        Author: Andy Matthews
4        Website: http://www.andyMatthews.net || http://shrinkurl.riaforge.org
5        Created: 1/16/2009
6        Last Updated: 1/16/2009
7        History:
8                        1/16/2009 - Initial creation
9                        1/25/2009 - Added support for Cligs, added error trapping on shrinkSnurl method, added better regex for validating URLs
10                                                        All thanks to Adam Tuttle over at FusionGrokker (http://fusiongrokker.com/)
11        Purpose: Quick access to short url creation via various open APIs
12        Version: 0.3
13
14        TODO:
15                + add additional services
16                        zi.ma (http://zi.ma/api)
17                + get rid of specific app methods in favor of a generic method
18                        possibly use the services "definition" variable to auto generate
19                        methods at run time?
20--->
21<cfcomponent hint="CFC allowing users to create short URLS via various URL shortening services" displayname="shrinkURL">
22
23        <cfscript>
24                VARIABLES.services = structNew();
25                VARIABLES.services['Snurl'] = structNew();
26                VARIABLES.services['Snurl'].method = 'POST';
27                VARIABLES.services['Snurl'].url = 'http://snipurl.com/site/getsnip';
28                VARIABLES.services['Snurl'].docs = 'http://www.snurl.com/site/help?go=api';
29                VARIABLES.services['Snurl'].parameters = structNew();
30                VARIABLES.services['Snurl'].parameters['snipapi'] = '<apikey>';
31                VARIABLES.services['Snurl'].parameters['snipuser'] = '<username>';
32
33                VARIABLES.services['IsGD'] = structNew();
34                VARIABLES.services['IsGD'].method = 'GET';
35                VARIABLES.services['IsGD'].url = 'http://is.gd/api.php';
36                VARIABLES.services['IsGD'].docs = 'http://is.gd/api_info.php';
37                VARIABLES.services['IsGD'].parameters = structNew();
38                VARIABLES.services['IsGD'].parameters['longurl'] = '<url>';
39
40                VARIABLES.services['TinyURL'] = structNew();
41                VARIABLES.services['TinyURL'].method = 'GET';
42                VARIABLES.services['TinyURL'].url = 'http://tinyurl.com/api-create.php';
43                VARIABLES.services['TinyURL'].docs = 'http://www.scripting.com/stories/2007/06/27/tinyurlHasAnApi.html';
44                VARIABLES.services['TinyURL'].parameters = structNew();
45                VARIABLES.services['TinyURL'].parameters['url'] = '<url>';
46
47                VARIABLES.services['BitLy'] = structNew();
48                VARIABLES.services['BitLy'].method = 'GET';
49                VARIABLES.services['BitLy'].url = 'http://api.bit.ly/shorten';
50                VARIABLES.services['BitLy'].docs = 'http://code.google.com/p/bitly-api/wiki/ApiDocumentation';
51                VARIABLES.services['BitLy'].parameters = structNew();
52                VARIABLES.services['BitLy'].parameters['login'] = '<login>';
53                VARIABLES.services['BitLy'].parameters['apiKey'] = '<apiKey>';
54                VARIABLES.services['BitLy'].parameters['longUrl'] = '<url>';
55                VARIABLES.services['BitLy'].parameters['version'] = '2.0.1';
56                VARIABLES.services['BitLy'].parameters['format'] = 'xml';
57
58                VARIABLES.services['Twurl'] = structNew();
59                VARIABLES.services['Twurl'].method = 'POST';
60                VARIABLES.services['Twurl'].url = 'http://tweetburner.com/links';
61                VARIABLES.services['Twurl'].docs = 'http://tweetburner.com/api';
62                VARIABLES.services['Twurl'].parameters = structNew();
63                VARIABLES.services['Twurl'].parameters['link[url]'] = '<url>';
64
65                VARIABLES.services['Hexio'] = structNew();
66                VARIABLES.services['Hexio'].method = 'GET';
67                VARIABLES.services['Hexio'].url = 'http://hex.io/api-create.php';
68                VARIABLES.services['Hexio'].docs = 'http://hex.io/';
69                VARIABLES.services['Hexio'].parameters = structNew();
70                VARIABLES.services['Hexio'].parameters['url'] = '<url>';
71
72                VARIABLES.services['POPrl'] = structNew();
73                VARIABLES.services['POPrl'].method = 'POST';
74                VARIABLES.services['POPrl'].url = 'http://poprl.com/api/post';
75                VARIABLES.services['POPrl'].docs = 'http://poprl.com/api_ref';
76                VARIABLES.services['POPrl'].parameters = structNew();
77                VARIABLES.services['POPrl'].parameters['url'] = '<url>';
78
79                //ajat 2009-01-24 -- added for cligs support
80                VARIABLES.services['Cligs'] = structNew();
81                VARIABLES.services['Cligs'].method = 'GET';
82                VARIABLES.services['Cligs'].url = 'http://cli.gs/api/v1/cligs/create';
83                VARIABLES.services['Cligs'].docs = 'http://blog.cli.gs/api';
84                VARIABLES.services['Cligs'].parameters = structNew();
85                VARIABLES.services['Cligs'].parameters['url'] = '<url>';
86                VARIABLES.services['Cligs'].parameters['appid'] = 'shrinkURL';
87        </cfscript>
88
89        <cffunction name="init" returntype="shrinkURL" hint="Initializes shrinkURL" access="public">
90                <cfreturn THIS>
91        </cffunction>
92
93        <cffunction name="listServices" returntype="struct" hint="Returns a list of services offered by shrinkURL" access="public">
94                <cfreturn VARIABLES.services>
95        </cffunction>
96
97        <cffunction name="verifyURL" returntype="boolean" hint="Validates a URL" access="private">
98                <cfargument name="url" type="string" required="true">
99                <cfset var regex = '^(ht|f)tp(s?)://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$'>
100                <cfset testURL = reFindNoCaseAll(regex, ARGUMENTS.url)>
101                <cfreturn ArrayLen(testURL.len)>
102        </cffunction>
103
104        <cffunction name="shrink" returntype="string" output="false" access="remote">
105                <cfargument name="service" type="string" required="true">
106                <cfargument name="url" type="string" required="true">
107                <cfargument name="parameters" required="false" type="struct" default="#StructNew()#" hint="Additional packet of information required by each individual service">
108
109                <!--- parameterize the url string variable --->
110                <cfset var newURL = ''>
111
112                <!--- does this URL pass validation? --->
113                <cfif NOT verifyURL(ARGUMENTS.url)>
114                        <!--- it doesn't, to let's provide a message --->
115                        <cfset newURL = 'URL appears to be invalid, please try again.'>
116
117                <cfelse>
118
119                        <!--- determine which service the user wants to use --->
120                        <cfswitch expression="#ARGUMENTS.service#">
121                                <cfcase value="Snurl">
122                                        <!--- make sure that the parameters struct exists, and has the keys we need. --->
123                                        <cfif StructKeyExists(ARGUMENTS,'parameters')
124                                                AND (StructKeyExists(ARGUMENTS.parameters,'snipuser') AND ARGUMENTS.parameters.snipuser NEQ '')
125                                                AND (StructKeyExists(ARGUMENTS.parameters,'snipapi') AND  ARGUMENTS.parameters.snipapi NEQ '')>
126                                                <!--- add the URL into the parameters structure --->
127                                                <cfset StructInsert(ARGUMENTS.parameters,'sniplink',ARGUMENTS.url)>
128                                                <!--- shrink the URL --->
129                                                <cfset newURL = snurlShrink(ARGUMENTS.parameters)>
130                                        <cfelse>
131                                                <!--- return an error if the user doesn't prove the username and API key --->
132                                                <cfset newURL = 'Parameters missing, likely username or password.'>
133                                        </cfif>
134                                </cfcase>
135                                <cfcase value="isGD">
136                                        <!--- make sure that the parameters struct exists, and has the keys we need. --->
137                                        <cfif StructKeyExists(ARGUMENTS,'parameters')>
138                                                <!--- add the URL into the parameters structure --->
139                                                <cfset StructInsert(ARGUMENTS.parameters,'longurl',ARGUMENTS.url)>
140                                                <!--- shrink the URL --->
141                                                <cfset newURL = isGDShrink(ARGUMENTS.parameters)>
142                                        <cfelse>
143                                                <!--- return an error if the user doesn't prove the username and API key --->
144                                                <cfset newURL = 'An unknown error occurred'>
145                                        </cfif>
146                                </cfcase>
147                                <cfcase value="TinyURL">
148                                        <!--- make sure that the parameters struct exists, and has the keys we need. --->
149                                        <cfif StructKeyExists(ARGUMENTS,'parameters')>
150                                                <!--- add the URL into the parameters structure --->
151                                                <cfset StructInsert(ARGUMENTS.parameters,'url',ARGUMENTS.url)>
152                                                <!--- shrink the URL --->
153                                                <cfset newURL = tuShrink(ARGUMENTS.parameters)>
154                                        <cfelse>
155                                                <!--- return an error if the user doesn't prove the username and API key --->
156                                                <cfset newURL = 'An unknown error occurred'>
157                                        </cfif>
158                                </cfcase>
159                                <cfcase value="BitLy">
160                                        <!--- make sure that the parameters struct exists, and has the keys we need. --->
161                                        <cfif StructKeyExists(ARGUMENTS,'parameters')
162                                                AND (StructKeyExists(ARGUMENTS.parameters,'login') AND ARGUMENTS.parameters.login NEQ '')
163                                                AND (StructKeyExists(ARGUMENTS.parameters,'apiKey') AND ARGUMENTS.parameters.apiKey NEQ '')>
164                                                <!--- add the URL into the parameters structure --->
165                                                <cfset StructInsert(ARGUMENTS.parameters,'longUrl',ARGUMENTS.url)>
166                                                <cfset StructInsert(ARGUMENTS.parameters,'version',VARIABLES.services['BitLy'].parameters['version'])>
167                                                <cfset StructInsert(ARGUMENTS.parameters,'format',VARIABLES.services['BitLy'].parameters['format'])>
168                                                <!--- shrink the URL --->
169                                                <cfset newURL = bitlyShrink(ARGUMENTS.parameters)>
170                                        <cfelse>
171                                                <!--- return an error if the user doesn't prove the username and API key --->
172                                                <cfset newURL = 'Parameters missing, likely username or password.'>
173                                        </cfif>
174                                </cfcase>
175                                <cfcase value="Twurl">
176                                        <!--- make sure that the parameters struct exists, and has the keys we need. --->
177                                        <cfif StructKeyExists(ARGUMENTS,'parameters')>
178                                                <!--- add the URL into the parameters structure --->
179                                                <cfset StructInsert(ARGUMENTS.parameters,'link[url]',ARGUMENTS.url)>
180                                                <!--- shrink the URL --->
181                                                <cfset newURL = twurlShrink(ARGUMENTS.parameters)>
182                                        <cfelse>
183                                                <!--- return an error if the user doesn't prove the username and API key --->
184                                                <cfset newURL = 'An unknown error occurred'>
185                                        </cfif>
186                                </cfcase>
187                                <cfcase value="Hexio">
188                                        <!--- make sure that the parameters struct exists, and has the keys we need. --->
189                                        <cfif StructKeyExists(ARGUMENTS,'parameters')>
190                                                <!--- add the URL into the parameters structure --->
191                                                <cfset StructInsert(ARGUMENTS.parameters,'url',ARGUMENTS.url)>
192                                                <!--- shrink the URL --->
193                                                <cfset newURL = hexioShrink(ARGUMENTS.parameters)>
194                                        <cfelse>
195                                                <!--- return an error if the user doesn't prove the username and API key --->
196                                                <cfset newURL = 'An unknown error occurred'>
197                                        </cfif>
198                                </cfcase>
199                                <cfcase value="POPrl">
200                                        <!--- make sure that the parameters struct exists, and has the keys we need. --->
201                                        <cfif StructKeyExists(ARGUMENTS,'parameters')>
202                                                <!--- add the URL into the parameters structure --->
203                                                <cfset StructInsert(ARGUMENTS.parameters,'url',ARGUMENTS.url)>
204                                                <!--- shrink the URL --->
205                                                <cfset newURL = poprlShrink(ARGUMENTS.parameters)>
206                                        <cfelse>
207                                                <!--- return an error if the user doesn't prove the username and API key --->
208                                                <cfset newURL = 'An unknown error occurred'>
209                                        </cfif>
210                                </cfcase>
211                                <cfcase value="Cligs">
212                                        <!--- make sure that the parameters struct exists, and has the keys we need. --->
213                                        <cfif StructKeyExists(ARGUMENTS,'parameters')>
214                                                <!--- add the URL into the parameters structure --->
215                                                <cfset StructInsert(ARGUMENTS.parameters,'url',ARGUMENTS.url)>
216                                                <!--- replace missing appid with shrinkUrl --->
217                                                <cfif not structKeyExists(ARGUMENTS.parameters,'appid')>
218                                                        <cfset ARGUMENTS.parameters.appid = VARIABLES.services['Cligs'].parameters['appid']>
219                                                </cfif>
220                                                <!--- shrink the URL --->
221                                                <cfset newURL = cligsShrink(ARGUMENTS.parameters)>
222                                        <cfelse>
223                                                <!--- return an error if the user doesn't prove the username and API key --->
224                                                <cfset newURL = 'An unknown error occurred'>
225                                        </cfif>
226                                </cfcase>
227                                <cfcase value="Zima">
228                                        <!--- make sure that the parameters struct exists, and has the keys we need. --->
229                                        <cfif StructKeyExists(ARGUMENTS,'parameters')>
230                                                <!--- add the URL into the parameters structure --->
231                                                <cfset StructInsert(ARGUMENTS.parameters,'url',ARGUMENTS.url)>
232                                                <cfset StructInsert(ARGUMENTS.parameters,'file','Add')>
233                                                <cfset StructInsert(ARGUMENTS.parameters,'module','ShortURL')>
234                                                <!--- shrink the URL --->
235                                                <cfset newURL = zimaShrink(ARGUMENTS.parameters)>
236                                        <cfelse>
237                                                <!--- return an error if the user doesn't prove the username and API key --->
238                                                <cfset newURL = 'An unknown error occurred'>
239                                        </cfif>
240                                </cfcase>
241                        </cfswitch>
242                </cfif>
243
244                <cfreturn newURL>
245        </cffunction>
246
247        <cffunction name="callAPI" returntype="string" output="false" access="private">
248                <cfargument name="url" type="string" required="true">
249                <cfargument name="method" type="string" required="true">
250                <cfargument name="parameters" required="no" type="struct" default="#StructNew()#" hint="Name / value pairs of data to be sent to service">
251
252                <cfset var cfhttp = ''>
253                <cfset var name = ''>
254
255                <!--- jat 2009-02-03 -- in Railo, <CFHTTPPARAM type=FormField> isn't valid for GET requests --->
256                <cfif lcase(arguments.method) eq "get">
257                        <cfloop collection="#arguments.parameters#" item="name">
258                                <cfif not findNoCase("?",arguments.url)>
259                                        <cfset arguments.url = arguments.url & "?#name#=#urlEncodedFormat(arguments.parameters[name])#"/>
260                                <cfelse>
261                                        <cfset arguments.url = arguments.url & "&#name#=#urlEncodedFormat(arguments.parameters[name])#"/>
262                                </cfif>
263                        </cfloop>
264                </cfif>
265               
266                <cfhttp url="#ARGUMENTS.url#" method="#ARGUMENTS.method#" timeout="20">
267                        <cfif lcase(arguments.method) neq "get">
268                                <cfloop collection="#ARGUMENTS.parameters#" item="name">
269                                        <cfhttpparam name="#name#" type="formfield" value="#ARGUMENTS.parameters[name]#">
270                                </cfloop>
271                        </cfif>
272                </cfhttp>
273
274                <cfreturn cfhttp.filecontent>
275        </cffunction>
276
277        <cffunction name="snurlShrink" returntype="string" hint="shrinks a URL using the snurl service" access="private">
278                <cfargument name="parameters" type="struct" required="true">
279
280                <cfset var cfhttp = ''>
281                <cfset var accessURL = VARIABLES.services['Snurl'].url>
282                <cfset var xmlReturn = ''>
283                <cftry>
284                        <cfset xmlReturn = XMLParse(callAPI(accessURL,VARIABLES.services['Snurl'].method,ARGUMENTS.parameters))>
285
286                        <cfif StructKeyExists(xmlReturn,'snip')>
287                                <cfreturn xmlReturn.snip.id.xmltext>
288                        <cfelse>
289                                <cfreturn 'An error occurred. Most likely due to an invalid or incomplete URL. Please try again.'>
290                        </cfif>
291                        <cfcatch>
292                                <cfreturn 'An error occurred. Most likely due to incorrect username or password.'/>
293                        </cfcatch>
294                </cftry>
295        </cffunction>
296
297        <cffunction name="isGDShrink" returntype="string" hint="shrinks a URL using the Is.gd service" access="private">
298                <cfargument name="parameters" type="struct" required="true">
299
300                <cfset var cfhttp = ''>
301                <cfset var accessURL = VARIABLES.services['IsGD'].url>
302                <cfset var xmlReturn = callAPI(accessURL,VARIABLES.services['IsGD'].method,ARGUMENTS.parameters)>
303
304                <!--- if the URL was invalid, return an error --->
305                <cfif FindNoCase('Error',xmlReturn)>
306                        <cfreturn 'An error occurred. Most likely due to an invalid or incomplete URL. Please try again.'>
307                <cfelse>
308                        <cfreturn xmlReturn>
309                </cfif>
310        </cffunction>
311
312        <cffunction name="tuShrink" returntype="string" hint="shrinks a URL using the TinyURL service" access="private">
313                <cfargument name="parameters" type="struct" required="true">
314
315                <cfset var cfhttp = ''>
316                <cfset var accessURL = VARIABLES.services['TinyURL'].url>
317                <cfset var xmlReturn = callAPI(accessURL,VARIABLES.services['TinyURL'].method,ARGUMENTS.parameters)>
318
319                <!--- if the URL was invalid, return an error --->
320                <cfif FindNoCase('Error',xmlReturn)>
321                        <cfreturn 'An error occurred. Most likely due to an invalid or incomplete URL. Please try again.'>
322                <cfelse>
323                        <cfreturn xmlReturn>
324                </cfif>
325        </cffunction>
326
327        <cffunction name="bitlyShrink" returntype="string" hint="shrinks a URL using the Bit.ly service" access="private">
328                <cfargument name="parameters" type="struct" required="true">
329
330                <cfset var cfhttp = ''>
331                <cfset var accessURL = VARIABLES.services['BitLy'].url>
332                <cfset var xmlReturn = ''>
333                <cftry>
334                        <cfset xmlReturn = XMLParse(callAPI(accessURL,VARIABLES.services['BitLy'].method,ARGUMENTS.parameters))>
335
336                        <!--- if the URL was invalid, return an error --->
337                        <cfif StructKeyExists(xmlReturn.bitly.results.nodeKeyVal.shortUrl,'xmlText')>
338                                <cfreturn xmlReturn.bitly.results.nodeKeyVal.shortUrl.xmlText>
339                        <cfelse>
340                                <cfreturn 'An error occurred. Most likely due to an invalid or incomplete URL. Please try again.'>
341                        </cfif>
342                        <cfcatch>
343                                <cfreturn 'An error occurred. Most likely due incorrect username or password.'>
344                        </cfcatch>
345                </cftry>
346        </cffunction>
347
348        <cffunction name="twurlShrink" returntype="string" hint="shrinks a URL using the Twurl service" access="private">
349                <cfargument name="parameters" type="struct" required="true">
350
351                <cfset var cfhttp = ''>
352                <cfset var accessURL = VARIABLES.services['Twurl'].url>
353                <cfset var xmlReturn = callAPI(accessURL,VARIABLES.services['Twurl'].method,ARGUMENTS.parameters)>
354
355                <cfreturn xmlReturn>
356        </cffunction>
357
358        <cffunction name="hexioShrink" returntype="string" hint="shrinks a URL using the Hexio service" access="private">
359                <cfargument name="parameters" type="struct" required="true">
360
361                <cfset var cfhttp = ''>
362                <cfset var accessURL = VARIABLES.services['Hexio'].url>
363                <cfset var xmlReturn = callAPI(accessURL,VARIABLES.services['Hexio'].method,ARGUMENTS.parameters)>
364
365                <cfreturn xmlReturn>
366        </cffunction>
367
368        <cffunction name="poprlShrink" returntype="string" hint="shrinks a URL using the POPrl service" access="private">
369                <cfargument name="parameters" type="struct" required="true">
370
371                <cfset var cfhttp = ''>
372                <cfset var accessURL = VARIABLES.services['POPrl'].url>
373                <cfset var xmlReturn = callAPI(accessURL,VARIABLES.services['POPrl'].method,ARGUMENTS.parameters)>
374
375                <cfreturn xmlReturn>
376        </cffunction>
377
378        <!--- jat 2009-01-24 -- added cligsShrink function for cligs compatability --->
379        <cffunction name="cligsShrink" returntype="string" hint="shrinks a URL using the Cligs service" access="private">
380                <cfargument name="parameters" type="struct" required="true">
381
382                <cfset var cfhttp = ''>
383                <cfset var accessURL = VARIABLES.services['Cligs'].url>
384                <cfset var xmlReturn = callAPI(accessURL,VARIABLES.services['Cligs'].method,ARGUMENTS.parameters)>
385
386                <cfreturn xmlReturn>
387        </cffunction>
388
389        <cffunction name="zimaShrink" returntype="string" hint="shrinks a URL using the Zi.ma service" access="private">
390                <cfargument name="parameters" type="struct" required="true">
391
392                <cfset var cfhttp = ''>
393                <cfset var accessURL = VARIABLES.services['Zima'].url>
394                <!--- <cfset var xmlReturn = callAPI(accessURL,VARIABLES.services['Zima'].method,ARGUMENTS.parameters)> --->
395
396                <cfdump var="#VARIABLES.services['Zima']#">
397                <cfdump var="#ARGUMENTS.parameters#">
398                <cfabort>
399
400                <cfreturn xmlReturn>
401        </cffunction>
402
403        <!---
404        http://cflib.org/udf/reFindNoCaseAll
405        Returns all the matches (case insensitive) of a regular expression within a string. This is simular to reGet(),
406        but more closely matches the result set of reFind.
407
408        @param regex      Regular expression. (Required)
409        @param text      String to search. (Required)
410        @return Returns an array.
411        @author Ben Forta (ben@forta.com)
412        @version 1, November 17, 2003
413        --->
414        <cffunction name="reFindNoCaseAll" output="true" returntype="struct">
415                <cfargument name="regex" type="string" required="yes">
416                <cfargument name="text" type="string" required="yes">
417                <!--- Define local variables --->
418                <cfset var results=structNew()>
419                <cfset var pos=1>
420                <cfset var subex="">
421                <cfset var done=false>
422                <!--- Initialize results structure --->
423                <cfset results.len=arraynew(1)>
424                <cfset results.pos=arraynew(1)>
425                <!--- Loop through text --->
426                <cfloop condition="not done">
427                        <!--- Perform search --->
428                        <cfset subex=reFindNoCase(arguments.regex, arguments.text, pos, true)>
429                        <!--- Anything matched? --->
430                        <cfif subex.len[1] is 0>
431                                <!--- Nothing found, outta here --->
432                                <cfset done=true>
433                        <cfelse>
434                                <!--- Got one, add to arrays --->
435                                <cfset arrayappend(results.len, subex.len[1])>
436                                <cfset arrayappend(results.pos, subex.pos[1])>
437                                <!--- Reposition start point --->
438                                <cfset pos=subex.pos[1]+subex.len[1]>
439                        </cfif>
440                </cfloop>
441                <!--- If no matches, add 0 to both arrays --->
442                <cfif arraylen(results.len) is 0>
443                        <cfset arrayappend(results.len, 0)>
444                        <cfset arrayappend(results.pos, 0)>
445                </cfif>
446                <!--- and return results --->
447                <cfreturn results>
448        </cffunction>
449</cfcomponent>
Note: See TracBrowser for help on using the browser.