diff --git a/gui/slick/images/banner.png b/gui/slick/images/banner.png
index 8ae6c94eec5176b38fb7f895ca02612696fe8089..69f1f0a34fd22691f62bbd2fc4559814e1b9d886 100644
Binary files a/gui/slick/images/banner.png and b/gui/slick/images/banner.png differ
diff --git a/gui/slick/images/flags/ar.png b/gui/slick/images/flags/ar.png
index e5ef8f1fcddb9fa0b89c353430e9640c122445cc..0e5e5d261e87cfe5d1cf178250595ca254b68c27 100644
Binary files a/gui/slick/images/flags/ar.png and b/gui/slick/images/flags/ar.png differ
diff --git a/gui/slick/images/flags/ay.png b/gui/slick/images/flags/ay.png
new file mode 100644
index 0000000000000000000000000000000000000000..5958f6a3961cb7cf6adb1854ed1fd3cb3e38050a
Binary files /dev/null and b/gui/slick/images/flags/ay.png differ
diff --git a/gui/slick/images/flags/bg.png b/gui/slick/images/flags/bg.png
index 0469f0607dc76eb60327c29e04d9585f3ef25dc7..7192aef517958f3062cbabf0cc2d7c4c68530ce6 100644
Binary files a/gui/slick/images/flags/bg.png and b/gui/slick/images/flags/bg.png differ
diff --git a/gui/slick/images/flags/bs.png b/gui/slick/images/flags/bs.png
index 639fa6cfa9c4792d03fb09fa197faf7ae549bfdf..05bb34e8f9ec5f3a330507daa1cbadc6ead569c8 100644
Binary files a/gui/slick/images/flags/bs.png and b/gui/slick/images/flags/bs.png differ
diff --git a/gui/slick/images/flags/ca.png b/gui/slick/images/flags/ca.png
index 1f204193ae58c87efdd88d46700ccb48c2e1d0d8..5d0305a80ed606e093e622d99e0c70bfff1262ff 100644
Binary files a/gui/slick/images/flags/ca.png and b/gui/slick/images/flags/ca.png differ
diff --git a/gui/slick/images/flags/cs.png b/gui/slick/images/flags/cs.png
index 8254790ca72f98d9e79d94bdfcb8839b1fd434ad..311ce520a1021b0799a40a1ed1cc8af9377e7845 100644
Binary files a/gui/slick/images/flags/cs.png and b/gui/slick/images/flags/cs.png differ
diff --git a/gui/slick/images/flags/da.png b/gui/slick/images/flags/da.png
index e2993d3c59ae78855f777c158a6aae6c1fb5c843..2c6dce00a532bbb3fa654373f15ee8bd62c0ef02 100644
Binary files a/gui/slick/images/flags/da.png and b/gui/slick/images/flags/da.png differ
diff --git a/gui/slick/images/flags/de.png b/gui/slick/images/flags/de.png
index ac4a977362738ca7daa20784717f10f9617136b4..8c52b0aa818347c9f0623646769e6145961526b4 100644
Binary files a/gui/slick/images/flags/de.png and b/gui/slick/images/flags/de.png differ
diff --git a/gui/slick/images/flags/el.png b/gui/slick/images/flags/el.png
index 8651ade7cbe030e85efc811a844d8f366c97a50c..5ae98285305309da2b707ec6ccbe58e5bbf5bd19 100644
Binary files a/gui/slick/images/flags/el.png and b/gui/slick/images/flags/el.png differ
diff --git a/gui/slick/images/flags/en.png b/gui/slick/images/flags/en.png
index 10f451fe85c41c6c9a06d543a57114ae2f87ecc1..ba72777157ff3cdb900aaf0fb0de6aeb8c627ba5 100644
Binary files a/gui/slick/images/flags/en.png and b/gui/slick/images/flags/en.png differ
diff --git a/gui/slick/images/flags/eo.png b/gui/slick/images/flags/eo.png
new file mode 100644
index 0000000000000000000000000000000000000000..9b861cde145b1b2cb41cf7e17502991b9833e46b
Binary files /dev/null and b/gui/slick/images/flags/eo.png differ
diff --git a/gui/slick/images/flags/es.png b/gui/slick/images/flags/es.png
index c2de2d7111e3cb59cf6511dd2ab045e824bdb43e..3f755e5e93902b8321a3fde21cfe0de3c53dae4f 100644
Binary files a/gui/slick/images/flags/es.png and b/gui/slick/images/flags/es.png differ
diff --git a/gui/slick/images/flags/et.png b/gui/slick/images/flags/et.png
index 2e893fa056c3d27448b6b9b6579486439ac6e490..d510e7fc26363c08453390243aeb215f00fb2b88 100644
Binary files a/gui/slick/images/flags/et.png and b/gui/slick/images/flags/et.png differ
diff --git a/gui/slick/images/flags/fa.png b/gui/slick/images/flags/fa.png
new file mode 100644
index 0000000000000000000000000000000000000000..9a92b576dbaf11d5ea9ed1261149a232a1f1e842
Binary files /dev/null and b/gui/slick/images/flags/fa.png differ
diff --git a/gui/slick/images/flags/fi.png b/gui/slick/images/flags/fi.png
index 14ec091b802cf24ebd9f8825f81cd2f6e360b46d..4f74d8b2ad17537e8acdcca6ba18e4bbfd219ea7 100644
Binary files a/gui/slick/images/flags/fi.png and b/gui/slick/images/flags/fi.png differ
diff --git a/gui/slick/images/flags/fr.png b/gui/slick/images/flags/fr.png
index 8332c4ec23c853944c29b02d7b32a88033f48a71..cec29aac0016d5e54017364c3df8bb8c359253d0 100644
Binary files a/gui/slick/images/flags/fr.png and b/gui/slick/images/flags/fr.png differ
diff --git a/gui/slick/images/flags/gl.png b/gui/slick/images/flags/gl.png
index ef12a73bf9628ff5a67b81bd980d9c5d2b2c0f05..ca60f6a2ede0b469dd2b6fcf121bdcc51914cadc 100644
Binary files a/gui/slick/images/flags/gl.png and b/gui/slick/images/flags/gl.png differ
diff --git a/gui/slick/images/flags/he.png b/gui/slick/images/flags/he.png
index 31b61bc7a7345cddeecfb0790d3898a1539d6314..0800eb9840fecc68fe5636163a5bf36ce20cdf2d 100644
Binary files a/gui/slick/images/flags/he.png and b/gui/slick/images/flags/he.png differ
diff --git a/gui/slick/images/flags/hi.png b/gui/slick/images/flags/hi.png
new file mode 100644
index 0000000000000000000000000000000000000000..a775c6d4ac2a7cb6ad00ebee42b136029086fe43
Binary files /dev/null and b/gui/slick/images/flags/hi.png differ
diff --git a/gui/slick/images/flags/hr.png b/gui/slick/images/flags/hr.png
index 696b515460ddb670acb7e9de4438aaf21fc5fb77..1f07f09a8fa5ade821f215c40bd34da7216eef92 100644
Binary files a/gui/slick/images/flags/hr.png and b/gui/slick/images/flags/hr.png differ
diff --git a/gui/slick/images/flags/hu.png b/gui/slick/images/flags/hu.png
index 7baafe44ddcaec29ad9f187f759a7fa3a1a5df00..d5cbe53c807137cf7fe70686990a82fe1b7ca824 100644
Binary files a/gui/slick/images/flags/hu.png and b/gui/slick/images/flags/hu.png differ
diff --git a/gui/slick/images/flags/hy.png b/gui/slick/images/flags/hy.png
new file mode 100644
index 0000000000000000000000000000000000000000..f80bcd20d73b75b43f35f1ded11ec0766da4e355
Binary files /dev/null and b/gui/slick/images/flags/hy.png differ
diff --git a/gui/slick/images/flags/id.png b/gui/slick/images/flags/id.png
index c6bc0fafac79403c97c64ba0228d35f250d05b57..e651f2745db84d4a5dbb952c4e5c24bf639b5cff 100644
Binary files a/gui/slick/images/flags/id.png and b/gui/slick/images/flags/id.png differ
diff --git a/gui/slick/images/flags/is.png b/gui/slick/images/flags/is.png
index b8f6d0f06675a9570c2c6e696ee51282097c3876..8e3696e0446cc1bee90789ac6d5cbac381c3956c 100644
Binary files a/gui/slick/images/flags/is.png and b/gui/slick/images/flags/is.png differ
diff --git a/gui/slick/images/flags/it.png b/gui/slick/images/flags/it.png
index 89692f74f051cd43503744c3dab65c8ba773b7e2..b9d078d7efb727e72d6e537b87e4c17fe6ecfe4a 100644
Binary files a/gui/slick/images/flags/it.png and b/gui/slick/images/flags/it.png differ
diff --git a/gui/slick/images/flags/ja.png b/gui/slick/images/flags/ja.png
index 4fbc123814ef5e2b2af77e93591ee53715954319..454b6d64111f98fd55e972ab5bcf22398802b546 100644
Binary files a/gui/slick/images/flags/ja.png and b/gui/slick/images/flags/ja.png differ
diff --git a/gui/slick/images/flags/ka.png b/gui/slick/images/flags/ka.png
new file mode 100644
index 0000000000000000000000000000000000000000..1d31854ebf0762c4d18ba6fb8ea78138b3ba924f
Binary files /dev/null and b/gui/slick/images/flags/ka.png differ
diff --git a/gui/slick/images/flags/kk.png b/gui/slick/images/flags/kk.png
new file mode 100644
index 0000000000000000000000000000000000000000..02780e3de9c80f64a2add48bdd0a70df46110cc1
Binary files /dev/null and b/gui/slick/images/flags/kk.png differ
diff --git a/gui/slick/images/flags/ko.png b/gui/slick/images/flags/ko.png
index c1179b53a0e7dc3b8c66df4856484df009959117..7b7b6b9345fd3698d27c5dd8b81e8ea34030ba49 100644
Binary files a/gui/slick/images/flags/ko.png and b/gui/slick/images/flags/ko.png differ
diff --git a/gui/slick/images/flags/lb.png b/gui/slick/images/flags/lb.png
index d0d452bf868e0cd6417f518f1dbe695f191ef392..d19b0de4f3c6ed7adb3928207b3b184f29c15f20 100644
Binary files a/gui/slick/images/flags/lb.png and b/gui/slick/images/flags/lb.png differ
diff --git a/gui/slick/images/flags/lt.png b/gui/slick/images/flags/lt.png
index c8ef0da0919b1e77ca91232de0cdf0d99dc8d68f..534d28ce4ac9c6941b8e21791a8b2c9cb5cc9057 100644
Binary files a/gui/slick/images/flags/lt.png and b/gui/slick/images/flags/lt.png differ
diff --git a/gui/slick/images/flags/lv.png b/gui/slick/images/flags/lv.png
index 49b69981085ff54568907cd51a56a1e5d8b01ada..0b2d3cbb57462d6e00628ffe9e7b08938ed3df0e 100644
Binary files a/gui/slick/images/flags/lv.png and b/gui/slick/images/flags/lv.png differ
diff --git a/gui/slick/images/flags/mk.png b/gui/slick/images/flags/mk.png
index db173aaff21955d9aed640beb344986335a1d164..30384347c8ee71d4521876cd7663720a3fd91d50 100644
Binary files a/gui/slick/images/flags/mk.png and b/gui/slick/images/flags/mk.png differ
diff --git a/gui/slick/images/flags/ms.png b/gui/slick/images/flags/ms.png
index d4cbb433d8f9fe49f06585dc46ee15593e3e621c..9572ba3d0887bf53b09a327b4bd8f37b568d785b 100644
Binary files a/gui/slick/images/flags/ms.png and b/gui/slick/images/flags/ms.png differ
diff --git a/gui/slick/images/flags/nl.png b/gui/slick/images/flags/nl.png
index fe44791e32b790949b0317ab3c258864b9024ebe..cf9797eb90aebfeaafb31e18cb9a717cd29989c4 100644
Binary files a/gui/slick/images/flags/nl.png and b/gui/slick/images/flags/nl.png differ
diff --git a/gui/slick/images/flags/no.png b/gui/slick/images/flags/no.png
index 160b6b5b79db15e623fa55e5774e5d160b933180..cdc0d5134b738d2b733544ee0c35572cef38028c 100644
Binary files a/gui/slick/images/flags/no.png and b/gui/slick/images/flags/no.png differ
diff --git a/gui/slick/images/flags/oc.png b/gui/slick/images/flags/oc.png
new file mode 100644
index 0000000000000000000000000000000000000000..a589445fdb103f873b162e9f6d376ab29bb0b3ed
Binary files /dev/null and b/gui/slick/images/flags/oc.png differ
diff --git a/gui/slick/images/flags/pb.png b/gui/slick/images/flags/pb.png
index 9b1a5538b264a295021f4f717d4299bb8ed98d98..2fecf539d9ddd9b191efdd0eae3003a1d2c2e37a 100644
Binary files a/gui/slick/images/flags/pb.png and b/gui/slick/images/flags/pb.png differ
diff --git a/gui/slick/images/flags/pl.png b/gui/slick/images/flags/pl.png
index d413d010b5b097c4e0a4604eba86dad79567ed16..80c75ecf241fc61e0ad16576aaeda80b2f8e0e4e 100644
Binary files a/gui/slick/images/flags/pl.png and b/gui/slick/images/flags/pl.png differ
diff --git a/gui/slick/images/flags/pt.png b/gui/slick/images/flags/pt.png
index ece79801506ecf8c42397349b4fa2cfe8176b999..56adb3015c4b0de73a1b053972a0f3635f741cd7 100644
Binary files a/gui/slick/images/flags/pt.png and b/gui/slick/images/flags/pt.png differ
diff --git a/gui/slick/images/flags/ro.png b/gui/slick/images/flags/ro.png
index 57e74a6510dd6a4b29668db181cb94727d1eb4b7..5b0840b4fb374cb9255d22725566de5a8db4ac68 100644
Binary files a/gui/slick/images/flags/ro.png and b/gui/slick/images/flags/ro.png differ
diff --git a/gui/slick/images/flags/ru.png b/gui/slick/images/flags/ru.png
index 47da4214fd9edb383687c1d4f84fe8b42a51ceb2..75b4034ebc1ff0089048d5406883347eb11cb4d5 100644
Binary files a/gui/slick/images/flags/ru.png and b/gui/slick/images/flags/ru.png differ
diff --git a/gui/slick/images/flags/si.png b/gui/slick/images/flags/si.png
index bb1476ff5fe8e0d3af4fc6bd11e513d95fd9cccd..f8a8ebc21442eb677f6ee4353c6a507195323396 100644
Binary files a/gui/slick/images/flags/si.png and b/gui/slick/images/flags/si.png differ
diff --git a/gui/slick/images/flags/sk.png b/gui/slick/images/flags/sk.png
index 7ccbc8274ad8f76f28960b83f2bba2a619029d87..0da9e298f66d9a7143d6c3ffb7f1252c6dc380ca 100644
Binary files a/gui/slick/images/flags/sk.png and b/gui/slick/images/flags/sk.png differ
diff --git a/gui/slick/images/flags/sl.png b/gui/slick/images/flags/sl.png
index 12d812d29fa6ea097743074e4a341ccfc691946a..733347a9c88ed5029579b41e91cf141eb1fd21d7 100644
Binary files a/gui/slick/images/flags/sl.png and b/gui/slick/images/flags/sl.png differ
diff --git a/gui/slick/images/flags/sq.png b/gui/slick/images/flags/sq.png
new file mode 100644
index 0000000000000000000000000000000000000000..67e629ce2dd931f2eac8fa89179a67eb2b7a0a77
Binary files /dev/null and b/gui/slick/images/flags/sq.png differ
diff --git a/gui/slick/images/flags/sr.png b/gui/slick/images/flags/sr.png
index 5eff9271d28cf8bf1cb85378600c4fa4997faa33..02aa99a42944791696a9f99589f8000eb96b8ee1 100644
Binary files a/gui/slick/images/flags/sr.png and b/gui/slick/images/flags/sr.png differ
diff --git a/gui/slick/images/flags/sv.png b/gui/slick/images/flags/sv.png
index 1994653dac1fc1c6ee3c9fcb35c8af97f16eefc7..aed90f2dbb04d668ca6f72dc2b1788ab0edd81fa 100644
Binary files a/gui/slick/images/flags/sv.png and b/gui/slick/images/flags/sv.png differ
diff --git a/gui/slick/images/flags/th.png b/gui/slick/images/flags/th.png
index dd8ba91719ba641502bc7ffda16c25dc71b2066c..758d45fcbc6a9e5af79c0100ec6ae72cd5e11219 100644
Binary files a/gui/slick/images/flags/th.png and b/gui/slick/images/flags/th.png differ
diff --git a/gui/slick/images/flags/tl.png b/gui/slick/images/flags/tl.png
index 77da181e9c57a490c90a99ec08a8718ea8fc0835..ea414aabdf737b1e01e930aabd692ab125b8e7da 100644
Binary files a/gui/slick/images/flags/tl.png and b/gui/slick/images/flags/tl.png differ
diff --git a/gui/slick/images/flags/tr.png b/gui/slick/images/flags/tr.png
index be32f77e9910c0896c1ee8e7ed4f0edf815a517e..bfcdca3e46a644c164870dfd0cb76eb04ecf489e 100644
Binary files a/gui/slick/images/flags/tr.png and b/gui/slick/images/flags/tr.png differ
diff --git a/gui/slick/images/flags/uk.png b/gui/slick/images/flags/uk.png
new file mode 100644
index 0000000000000000000000000000000000000000..6c3b3fb43215b0d3b5cbcf196a6e03a3f7d9a05c
Binary files /dev/null and b/gui/slick/images/flags/uk.png differ
diff --git a/gui/slick/images/flags/un.png b/gui/slick/images/flags/un.png
new file mode 100644
index 0000000000000000000000000000000000000000..035b8b99f7fce7f95ce460653dd1a0d6ac091b7c
Binary files /dev/null and b/gui/slick/images/flags/un.png differ
diff --git a/gui/slick/images/flags/unknown.png b/gui/slick/images/flags/unknown.png
index 41ab4e6ef283765d69c3d2598910710e15449d45..af9249bc317b724a8923e1447c60977dc9a91827 100644
Binary files a/gui/slick/images/flags/unknown.png and b/gui/slick/images/flags/unknown.png differ
diff --git a/gui/slick/images/flags/vi.png b/gui/slick/images/flags/vi.png
index ed26915a3238534bf8f1249b75dd9ddde10db65a..20e00c9b3508eedc0ae3c8a0075be5ac6373603e 100644
Binary files a/gui/slick/images/flags/vi.png and b/gui/slick/images/flags/vi.png differ
diff --git a/gui/slick/images/flags/zh.png b/gui/slick/images/flags/zh.png
index 89144146219e6fbec7eaa89e1bf4b073d299569e..4f12a8461c08478c032e84bbe8e442d1aa9f316b 100644
Binary files a/gui/slick/images/flags/zh.png and b/gui/slick/images/flags/zh.png differ
diff --git a/gui/slick/images/poster.png b/gui/slick/images/poster.png
index 906fb562870499fd5cde7c8d1c605dbcb0b4d337..c280c1849da45425aac8b977920be978ec6381b4 100644
Binary files a/gui/slick/images/poster.png and b/gui/slick/images/poster.png differ
diff --git a/gui/slick/interfaces/default/config_general.tmpl b/gui/slick/interfaces/default/config_general.tmpl
index b098c75ef5387c9d50dd125a09a3cd6c76629bd8..a16527b473adab106b0bd791c8fd06f7db6ecdd1 100644
--- a/gui/slick/interfaces/default/config_general.tmpl
+++ b/gui/slick/interfaces/default/config_general.tmpl
@@ -317,16 +317,6 @@
 
 					<fieldset class="component-group-list">
 
-						<div class="field-pair">
-							<label for="use_api">
-								<span class="component-title">Enable API</span>
-								<span class="component-desc">
-									<input type="checkbox" name="use_api" class="enabler" id="use_api" #if $sickbeard.USE_API then 'checked="checked"' else ''#/>
-									<p>allow the use of the SickRage API</p>
-								</span>
-							</label>
-						</div>
-						<div id="content_use_api">
 						<div class="field-pair">
 							<label for="api_key">
 								<span class="component-title">API key</span>
@@ -337,7 +327,6 @@
 								</span>
 							</label>
 						</div>
-						</div>
 
 						<div class="field-pair">
 							<label for="web_log">
@@ -581,10 +570,10 @@
 
 						<div class="field-pair">
 							<label for="git_reset">
-								<span class="component-title">Git branch reset</span>
+								<span class="component-title">Git reset</span>
 								<span class="component-desc">
 									<input type="checkbox" name="git_reset" id="git_reset" #if True == $sickbeard.GIT_RESET then 'checked="checked"' else ''#/>
-									<p>reset git branch automatically to help resolve update issues</p>
+									<p>removes untracked files and performs a hard reset on git branch automatically to help resolve update issues</p>
 								</span>
 							</label>
 						</div>
diff --git a/gui/slick/interfaces/default/displayShow.tmpl b/gui/slick/interfaces/default/displayShow.tmpl
index f2bfb9a7641b8d1e5477de98f5f539c9c160dc26..26268fd4ebad35bc1f92e36ef7579aa0c276848b 100644
--- a/gui/slick/interfaces/default/displayShow.tmpl
+++ b/gui/slick/interfaces/default/displayShow.tmpl
@@ -474,7 +474,7 @@
 		#if $sickbeard.USE_SUBTITLES and $show.subtitles:
 			<td class="col-subtitles" align="center">
 		#if $epResult["subtitles"]:
-		#for $sub_lang in subliminal.language.language_list($epResult["subtitles"].split(',')):
+		#for $sub_lang in subliminal.language.language_list([x.strip() for x in $epResult["subtitles"].split(',')]):
         #if sub_lang.alpha2 != ""
            	<img src="$sbRoot/images/flags/${sub_lang.alpha2}.png" width="16" height="11" alt="${sub_lang}" />
 		#end if
diff --git a/gui/slick/interfaces/default/editShow.tmpl b/gui/slick/interfaces/default/editShow.tmpl
index c031ec13cc2f63392294b42268af12c12521f4dd..ef959c6b26b1b4238803b2d5212a2a90c3a0523a 100644
--- a/gui/slick/interfaces/default/editShow.tmpl
+++ b/gui/slick/interfaces/default/editShow.tmpl
@@ -133,7 +133,7 @@
 
 <b>Sports: </b>
 <input type="checkbox" name="sports" #if $show.sports == 1 then "checked=\"checked\"" else ""# /><br />
-(check this if the show is a sporting or MMA event)<br />
+(check this if the show is a sporting or MMA event and released as Show.03.02.2010 rather than Show.S02E03)<br />
 <br />
 
 <b>Anime: </b>
diff --git a/gui/slick/interfaces/default/home.tmpl b/gui/slick/interfaces/default/home.tmpl
index 12cf6a9597c71ac8134bbd0f5720b6455c8b5636..ae9d6bba29fd5d40024e750335b6b647e177d331 100644
--- a/gui/slick/interfaces/default/home.tmpl
+++ b/gui/slick/interfaces/default/home.tmpl
@@ -1,4 +1,5 @@
 #import sickbeard
+#import calendar
 #import datetime
 #from sickbeard.common import *
 #from sickbeard import db, sbdatetime, network_timezones
@@ -330,7 +331,7 @@ $myShowList.sort(lambda x, y: cmp(x.name, y.name))
 	
 #set $data_date = '6000000000.0'
 #if $cur_airs_next:
-    #set $data_date = $time.mktime($sbdatetime.sbdatetime.convert_to_setting($network_timezones.parse_date_time($cur_airs_next,$curShow.airs,$curShow.network)).timetuple())
+    #set $data_date = $calendar.timegm($sbdatetime.sbdatetime.convert_to_setting($network_timezones.parse_date_time($cur_airs_next,$curShow.airs,$curShow.network)).timetuple())
 #else if None is not $display_status
     #if 'nded' not in $display_status and 1 == int($curShow.paused)
         #set $data_date = '5000000500.0'
@@ -528,7 +529,7 @@ $myShowList.sort(lambda x, y: cmp(x.name, y.name))
 	
 	#if $cur_airs_next
     #set $ldatetime = $sbdatetime.sbdatetime.convert_to_setting($network_timezones.parse_date_time($cur_airs_next,$curShow.airs,$curShow.network))
-		<td align="center" class="nowrap"><div class="${fuzzydate}">$sbdatetime.sbdatetime.sbfdate($ldatetime)</div><span class="sort_data">$time.mktime($ldatetime.timetuple())</span></td>
+		<td align="center" class="nowrap"><div class="${fuzzydate}">$sbdatetime.sbdatetime.sbfdate($ldatetime)</div><span class="sort_data">$calendar.timegm($ldatetime.timetuple())</span></td>
     #else:
     	<td align="center" class="nowrap"></td>
     #end if
diff --git a/lib/fanart/__init__.py b/lib/fanart/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..8acc7f5cd6034d54c8e83e1dc037bed25a2479bb
--- /dev/null
+++ b/lib/fanart/__init__.py
@@ -0,0 +1,111 @@
+__author__ = 'Andrea De Marco <24erre@gmail.com>'
+__version__ = '1.4.0'
+__classifiers__ = [
+    'Development Status :: 5 - Production/Stable',
+    'Intended Audience :: Developers',
+    'License :: OSI Approved :: Apache Software License',
+    'Operating System :: OS Independent',
+    'Programming Language :: Python',
+    'Topic :: Internet :: WWW/HTTP',
+    'Topic :: Software Development :: Libraries',
+]
+__copyright__ = "2012, %s " % __author__
+__license__ = """
+   Copyright %s.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either expressed or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+""" % __copyright__
+
+__docformat__ = 'restructuredtext en'
+
+__doc__ = """
+:abstract: Python interface to fanart.tv API
+:version: %s
+:author: %s
+:contact: http://z4r.github.com/
+:date: 2012-04-04
+:copyright: %s
+""" % (__version__, __author__, __license__)
+
+
+def values(obj):
+    return [v for k, v in obj.__dict__.iteritems() if not k.startswith('_')]
+
+BASEURL = 'http://webservice.fanart.tv/v3/%s/%s?api_key=%s'
+
+class FORMAT(object):
+    JSON = 'JSON'
+    XML = 'XML'
+    PHP = 'PHP'
+
+
+class WS(object):
+    MUSIC = 'music'
+    MOVIE = 'movies'
+    TV = 'tv'
+
+
+class TYPE(object):
+    ALL = 'all'
+
+    class TV(object):
+        LOGO = 'clearlogo'
+        CHARACTER = 'characterart'
+        BACKGROUND = 'showbackground'
+        HDLOGO = 'hdtvlogo'
+        HDART = 'hdclearart'
+        ART = 'clearart'
+        THUMB = 'tvthumb'
+        POSTER = 'tvposter'
+        BANNER = 'tvbanner'
+        SEASONTHUMB = 'seasonthumb'
+        SEASONPOSTER = 'seasonposter'
+        SEASONBANNER = 'seasonbanner'
+
+    class MUSIC(object):
+        DISC = 'cdart'
+        LOGO = 'musiclogo'
+        BACKGROUND = 'artistbackground'
+        COVER = 'albumcover'
+        THUMB = 'artistthumb'
+
+    class MOVIE(object):
+        ART = 'movieart'
+        LOGO = 'movielogo'
+        DISC = 'moviedisc'
+        POSTER = 'movieposter'
+        BACKGROUND = 'moviebackground'
+        HDLOGO = 'hdmovielogo'
+        HDART = 'hdmovieclearart'
+        BANNER = 'moviebanner'
+        THUMB = 'moviethumb'
+
+
+class SORT(object):
+    POPULAR = 1
+    NEWEST = 2
+    OLDEST = 3
+
+
+class LIMIT(object):
+    ONE = 1
+    ALL = 2
+
+FORMAT_LIST = values(FORMAT)
+WS_LIST = values(WS)
+TYPE_LIST = values(TYPE.MUSIC) + values(TYPE.TV) + values(TYPE.MOVIE) + [TYPE.ALL]
+MUSIC_TYPE_LIST = values(TYPE.MUSIC) + [TYPE.ALL]
+TV_TYPE_LIST = values(TYPE.TV) + [TYPE.ALL]
+MOVIE_TYPE_LIST = values(TYPE.MOVIE) + [TYPE.ALL]
+SORT_LIST = values(SORT)
+LIMIT_LIST = values(LIMIT)
diff --git a/lib/fanart/core.py b/lib/fanart/core.py
new file mode 100644
index 0000000000000000000000000000000000000000..6b3af96d468a04db16daa19e7be25eb1bc08b5b5
--- /dev/null
+++ b/lib/fanart/core.py
@@ -0,0 +1,35 @@
+import requests
+import fanart
+from fanart.errors import RequestFanartError, ResponseFanartError
+
+
+class Request(object):
+    def __init__(self, apikey, id, ws, type=None, sort=None, limit=None):
+        self._apikey = apikey
+        self._id = id
+        self._ws = ws
+        self._type = type or fanart.TYPE.ALL
+        self._sort = sort or fanart.SORT.POPULAR
+        self._limit = limit or fanart.LIMIT.ALL
+        self.validate()
+        self._response = None
+
+    def validate(self):
+        for attribute_name in ('ws', 'type', 'sort', 'limit'):
+            attribute = getattr(self, '_' + attribute_name)
+            choices = getattr(fanart, attribute_name.upper() + '_LIST')
+            if attribute not in choices:
+                raise RequestFanartError('Not allowed {0}: {1} [{2}]'.format(attribute_name, attribute, ', '.join(choices)))
+
+    def __str__(self):
+        return fanart.BASEURL % (self._ws, self._id, self._apikey)
+
+    def response(self):
+        try:
+            response = requests.get(str(self))
+            rjson = response.json()
+            if not isinstance(rjson, dict):
+                raise Exception(response.text)
+            return rjson
+        except Exception as e:
+            raise ResponseFanartError(str(e))
diff --git a/lib/fanart/errors.py b/lib/fanart/errors.py
new file mode 100644
index 0000000000000000000000000000000000000000..95a71e35ed58893ca1f74677d1392179e59b1901
--- /dev/null
+++ b/lib/fanart/errors.py
@@ -0,0 +1,15 @@
+class FanartError(Exception):
+    def __str__(self):
+        return ', '.join(map(str, self.args))
+
+    def __repr__(self):
+        name = self.__class__.__name__
+        return '%s%r' % (name, self.args)
+
+
+class ResponseFanartError(FanartError):
+    pass
+
+
+class RequestFanartError(FanartError):
+    pass
diff --git a/lib/fanart/immutable.py b/lib/fanart/immutable.py
new file mode 100644
index 0000000000000000000000000000000000000000..170de37086eab8dfde19097edaf31c5e6dbd42b9
--- /dev/null
+++ b/lib/fanart/immutable.py
@@ -0,0 +1,46 @@
+class Immutable(object):
+    _mutable = False
+
+    def __setattr__(self, name, value):
+        if self._mutable or name == '_mutable':
+            super(Immutable, self).__setattr__(name, value)
+        else:
+            raise TypeError("Can't modify immutable instance")
+
+    def __delattr__(self, name):
+        if self._mutable:
+            super(Immutable, self).__delattr__(name)
+        else:
+            raise TypeError("Can't modify immutable instance")
+
+    def __eq__(self, other):
+        return hash(self) == hash(other)
+
+    def __hash__(self):
+        return hash(repr(self))
+
+    def __repr__(self):
+        return '%s(%s)' % (
+            self.__class__.__name__,
+            ', '.join(['{0}={1}'.format(k, repr(v)) for k, v in self])
+        )
+
+    def __iter__(self):
+        l = self.__dict__.keys()
+        l.sort()
+        for k in l:
+            if not k.startswith('_'):
+                yield k, getattr(self, k)
+
+    @staticmethod
+    def mutablemethod(f):
+        def func(self, *args, **kwargs):
+            if isinstance(self, Immutable):
+                old_mutable = self._mutable
+                self._mutable = True
+                res = f(self, *args, **kwargs)
+                self._mutable = old_mutable
+            else:
+                res = f(self, *args, **kwargs)
+            return res
+        return func
diff --git a/lib/fanart/items.py b/lib/fanart/items.py
new file mode 100644
index 0000000000000000000000000000000000000000..778e1a1b2ba5e936061deb03e05423468277f4c3
--- /dev/null
+++ b/lib/fanart/items.py
@@ -0,0 +1,68 @@
+import json
+import os
+import requests
+from fanart.core import Request
+from fanart.immutable import Immutable
+
+
+class LeafItem(Immutable):
+    KEY = NotImplemented
+
+    @Immutable.mutablemethod
+    def __init__(self, id, url, likes):
+        self.id = int(id)
+        self.url = url
+        self.likes = int(likes)
+        self._content = None
+
+    @classmethod
+    def from_dict(cls, resource):
+        return cls(**dict([(str(k), v) for k, v in resource.iteritems()]))
+
+    @classmethod
+    def extract(cls, resource):
+        return [cls.from_dict(i) for i in resource.get(cls.KEY, {})]
+
+    @Immutable.mutablemethod
+    def content(self):
+        if not self._content:
+            self._content = requests.get(self.url).content
+        return self._content
+
+    def __str__(self):
+        return self.url
+
+
+class ResourceItem(Immutable):
+    WS = NotImplemented
+    request_cls = Request
+
+    @classmethod
+    def from_dict(cls, map):
+        raise NotImplementedError
+
+    @classmethod
+    def get(cls, id):
+        map = cls.request_cls(
+            apikey=os.environ.get('FANART_APIKEY'),
+            id=id,
+            ws=cls.WS
+        ).response()
+        return cls.from_dict(map)
+
+    def json(self, **kw):
+        return json.dumps(
+            self,
+            default=lambda o: dict([(k, v) for k, v in o.__dict__.items() if not k.startswith('_')]),
+            **kw
+        )
+
+
+class CollectableItem(Immutable):
+    @classmethod
+    def from_dict(cls, key, map):
+        raise NotImplementedError
+
+    @classmethod
+    def collection_from_dict(cls, map):
+        return [cls.from_dict(k, v) for k, v in map.iteritems()]
diff --git a/lib/fanart/movie.py b/lib/fanart/movie.py
new file mode 100644
index 0000000000000000000000000000000000000000..c69e860b1ee458654c0aebc9647619f910826891
--- /dev/null
+++ b/lib/fanart/movie.py
@@ -0,0 +1,103 @@
+import fanart
+from fanart.items import LeafItem, Immutable, ResourceItem
+__all__ = (
+    'ArtItem',
+    'DiscItem',
+    'LogoItem',
+    'PosterItem',
+    'BackgroundItem',
+    'HdLogoItem',
+    'HdArtItem',
+    'BannerItem',
+    'ThumbItem',
+    'Movie',
+)
+
+
+class MovieItem(LeafItem):
+
+    @Immutable.mutablemethod
+    def __init__(self, id, url, likes, lang):
+        super(MovieItem, self).__init__(id, url, likes)
+        self.lang = lang
+
+
+class DiscItem(MovieItem):
+    KEY = fanart.TYPE.MOVIE.DISC
+
+    @Immutable.mutablemethod
+    def __init__(self, id, url, likes, lang, disc, disc_type):
+        super(DiscItem, self).__init__(id, url, likes, lang)
+        self.disc = int(disc)
+        self.disc_type = disc_type
+
+
+class ArtItem(MovieItem):
+    KEY = fanart.TYPE.MOVIE.ART
+
+
+class LogoItem(MovieItem):
+    KEY = fanart.TYPE.MOVIE.LOGO
+
+
+class PosterItem(MovieItem):
+    KEY = fanart.TYPE.MOVIE.POSTER
+
+
+class BackgroundItem(MovieItem):
+    KEY = fanart.TYPE.MOVIE.BACKGROUND
+
+
+class HdLogoItem(MovieItem):
+    KEY = fanart.TYPE.MOVIE.HDLOGO
+
+
+class HdArtItem(MovieItem):
+    KEY = fanart.TYPE.MOVIE.HDART
+
+
+class BannerItem(MovieItem):
+    KEY = fanart.TYPE.MOVIE.BANNER
+
+
+class ThumbItem(MovieItem):
+    KEY = fanart.TYPE.MOVIE.THUMB
+
+
+class Movie(ResourceItem):
+    WS = fanart.WS.MOVIE
+
+    @Immutable.mutablemethod
+    def __init__(self, name, imdbid, tmdbid, arts, logos, discs, posters, backgrounds, hdlogos, hdarts,
+                 banners, thumbs):
+        self.name = name
+        self.imdbid = imdbid
+        self.tmdbid = tmdbid
+        self.arts = arts
+        self.posters = posters
+        self.logos = logos
+        self.discs = discs
+        self.backgrounds = backgrounds
+        self.hdlogos = hdlogos
+        self.hdarts = hdarts
+        self.banners = banners
+        self.thumbs = thumbs
+
+    @classmethod
+    def from_dict(cls, resource):
+        assert len(resource) == 1, 'Bad Format Map'
+        name, resource = resource.items()[0]
+        return cls(
+            name=name,
+            imdbid=resource['imdb_id'],
+            tmdbid=resource['tmdb_id'],
+            arts=ArtItem.extract(resource),
+            logos=LogoItem.extract(resource),
+            discs=DiscItem.extract(resource),
+            posters=PosterItem.extract(resource),
+            backgrounds=BackgroundItem.extract(resource),
+            hdlogos=HdLogoItem.extract(resource),
+            hdarts=HdArtItem.extract(resource),
+            banners=BannerItem.extract(resource),
+            thumbs=ThumbItem.extract(resource),
+        )
diff --git a/lib/fanart/music.py b/lib/fanart/music.py
new file mode 100644
index 0000000000000000000000000000000000000000..9f10309373975f45a81806d764964791b6474ca1
--- /dev/null
+++ b/lib/fanart/music.py
@@ -0,0 +1,80 @@
+from fanart.items import Immutable, LeafItem, ResourceItem, CollectableItem
+import fanart
+__all__ = (
+    'BackgroundItem',
+    'CoverItem',
+    'LogoItem',
+    'ThumbItem',
+    'DiscItem',
+    'Artist',
+    'Album',
+)
+
+
+class BackgroundItem(LeafItem):
+    KEY = fanart.TYPE.MUSIC.BACKGROUND
+
+
+class CoverItem(LeafItem):
+    KEY = fanart.TYPE.MUSIC.COVER
+
+
+class LogoItem(LeafItem):
+    KEY = fanart.TYPE.MUSIC.LOGO
+
+
+class ThumbItem(LeafItem):
+    KEY = fanart.TYPE.MUSIC.THUMB
+
+
+class DiscItem(LeafItem):
+    KEY = fanart.TYPE.MUSIC.DISC
+
+    @Immutable.mutablemethod
+    def __init__(self, id, url, likes, disc, size):
+        super(DiscItem, self).__init__(id, url, likes)
+        self.disc = int(disc)
+        self.size = int(size)
+
+
+class Artist(ResourceItem):
+    WS = fanart.WS.MUSIC
+
+    @Immutable.mutablemethod
+    def __init__(self, name, mbid, albums, backgrounds, logos, thumbs):
+        self.name = name
+        self.mbid = mbid
+        self.albums = albums
+        self.backgrounds = backgrounds
+        self.logos = logos
+        self.thumbs = thumbs
+
+    @classmethod
+    def from_dict(cls, resource):
+        assert len(resource) == 1, 'Bad Format Map'
+        name, resource = resource.items()[0]
+        return cls(
+            name=name,
+            mbid=resource['mbid_id'],
+            albums=Album.collection_from_dict(resource.get('albums', {})),
+            backgrounds=BackgroundItem.extract(resource),
+            thumbs=ThumbItem.extract(resource),
+            logos=LogoItem.extract(resource),
+        )
+
+
+class Album(CollectableItem):
+
+    @Immutable.mutablemethod
+    def __init__(self, mbid, covers, arts):
+        self.mbid = mbid
+        self.covers = covers
+        self.arts = arts
+
+    @classmethod
+    def from_dict(cls, key, resource):
+        return cls(
+            mbid=key,
+            covers=CoverItem.extract(resource),
+            arts=DiscItem.extract(resource),
+        )
diff --git a/lib/fanart/tests/__init__.py b/lib/fanart/tests/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..957cbe388c57468295787d5cde0dad6b381dffbf
--- /dev/null
+++ b/lib/fanart/tests/__init__.py
@@ -0,0 +1,3 @@
+import os
+
+LOCALDIR = os.path.dirname(__file__)
diff --git a/lib/fanart/tests/json/wilfred.json b/lib/fanart/tests/json/wilfred.json
new file mode 100644
index 0000000000000000000000000000000000000000..2065f9cfe054c6c6da717405fa0fc2fb9d33252e
--- /dev/null
+++ b/lib/fanart/tests/json/wilfred.json
@@ -0,0 +1,196 @@
+{
+    "logos": [
+        {
+            "lang": "en",
+            "url": "http://assets.fanart.tv/fanart/tv/239761/clearlogo/wilfred-us-4e04b6495dfd3.png",
+            "likes": 2,
+            "id": 11977
+        },
+        {
+            "lang": "en",
+            "url": "http://assets.fanart.tv/fanart/tv/239761/clearlogo/wilfred-us-517ac36e39f67.png",
+            "likes": 1,
+            "id": 28249
+        },
+        {
+            "lang": "en",
+            "url": "http://assets.fanart.tv/fanart/tv/239761/clearlogo/wilfred-us-51f557082cfde.png",
+            "likes": 0,
+            "id": 31817
+        }
+    ],
+    "arts": [
+        {
+            "lang": "en",
+            "url": "http://assets.fanart.tv/fanart/tv/239761/clearart/wilfred-us-4e05f10e87711.png",
+            "likes": 2,
+            "id": 11987
+        },
+        {
+            "lang": "en",
+            "url": "http://assets.fanart.tv/fanart/tv/239761/clearart/wilfred-us-4e2f151d5ed62.png",
+            "likes": 1,
+            "id": 12470
+        }
+    ],
+    "name": "Wilfred (US)",
+    "hdarts": [
+        {
+            "lang": "en",
+            "url": "http://assets.fanart.tv/fanart/tv/239761/hdclearart/wilfred-us-505f94ed0ba13.png",
+            "likes": 1,
+            "id": 21112
+        },
+        {
+            "lang": "he",
+            "url": "http://assets.fanart.tv/fanart/tv/239761/hdclearart/wilfred-us-52403264aa3ec.png",
+            "likes": 1,
+            "id": 33751
+        }
+    ],
+    "backgrounds": [
+        {
+            "lang": "en",
+            "url": "http://assets.fanart.tv/fanart/tv/239761/showbackground/wilfred-us-5034dbd49115e.jpg",
+            "id": 19965,
+            "season": 0,
+            "likes": 0
+        },
+        {
+            "lang": "en",
+            "url": "http://assets.fanart.tv/fanart/tv/239761/showbackground/wilfred-us-50b0c92db6973.jpg",
+            "id": 23166,
+            "season": 0,
+            "likes": 0
+        },
+        {
+            "lang": "en",
+            "url": "http://assets.fanart.tv/fanart/tv/239761/showbackground/wilfred-us-50b0c92dbb46b.jpg",
+            "id": 23167,
+            "season": 0,
+            "likes": 0
+        },
+        {
+            "lang": "en",
+            "url": "http://assets.fanart.tv/fanart/tv/239761/showbackground/wilfred-us-50b0c92dbb9d1.jpg",
+            "id": 23168,
+            "season": 0,
+            "likes": 0
+        }
+    ],
+    "thumbs": [
+        {
+            "lang": "en",
+            "url": "http://assets.fanart.tv/fanart/tv/239761/tvthumb/wilfred-us-501cf526174fe.jpg",
+            "likes": 1,
+            "id": 19596
+        },
+        {
+            "lang": "en",
+            "url": "http://assets.fanart.tv/fanart/tv/239761/tvthumb/wilfred-us-51bfb4a105904.jpg",
+            "likes": 0,
+            "id": 30060
+        }
+    ],
+    "characters": [],
+    "posters": [
+        {
+            "lang": "he",
+            "url": "http://assets.fanart.tv/fanart/tv/239761/tvposter/wilfred-us-525d893230d7c.jpg",
+            "likes": 1,
+            "id": 34584
+        }
+    ],
+    "seasons": [
+        {
+            "lang": "he",
+            "url": "http://assets.fanart.tv/fanart/tv/239761/seasonthumb/wilfred-us-52403782bab55.jpg",
+            "id": 33752,
+            "season": 1,
+            "likes": 1
+        },
+        {
+            "lang": "he",
+            "url": "http://assets.fanart.tv/fanart/tv/239761/seasonthumb/wilfred-us-5240379335232.jpg",
+            "id": 33753,
+            "season": 2,
+            "likes": 1
+        },
+        {
+            "lang": "he",
+            "url": "http://assets.fanart.tv/fanart/tv/239761/seasonthumb/wilfred-us-524037bc83c7d.jpg",
+            "id": 33754,
+            "season": 3,
+            "likes": 1
+        },
+        {
+            "lang": "en",
+            "url": "http://assets.fanart.tv/fanart/tv/239761/seasonthumb/wilfred-us-501bb0a8e60f9.jpg",
+            "id": 19586,
+            "season": 1,
+            "likes": 0
+        },
+        {
+            "lang": "en",
+            "url": "http://assets.fanart.tv/fanart/tv/239761/seasonthumb/wilfred-us-501bb0b4bf229.jpg",
+            "id": 19587,
+            "season": 2,
+            "likes": 0
+        },
+        {
+            "lang": "en",
+            "url": "http://assets.fanart.tv/fanart/tv/239761/seasonthumb/wilfred-us-501bb144e6a46.jpg",
+            "id": 19588,
+            "season": 0,
+            "likes": 0
+        },
+        {
+            "lang": "en",
+            "url": "http://assets.fanart.tv/fanart/tv/239761/seasonthumb/wilfred-us-51c953105ef77.jpg",
+            "id": 30309,
+            "season": 3,
+            "likes": 0
+        }
+    ],
+    "banners": [
+        {
+            "lang": "he",
+            "url": "http://assets.fanart.tv/fanart/tv/239761/tvbanner/wilfred-us-52403a7185070.jpg",
+            "likes": 1,
+            "id": 33755
+        },
+        {
+            "lang": "en",
+            "url": "http://assets.fanart.tv/fanart/tv/239761/tvbanner/wilfred-us-5265193db51f7.jpg",
+            "likes": 0,
+            "id": 34716
+        }
+    ],
+    "hdlogos": [
+        {
+            "lang": "en",
+            "url": "http://assets.fanart.tv/fanart/tv/239761/hdtvlogo/wilfred-us-505f373be58e6.png",
+            "likes": 1,
+            "id": 21101
+        },
+        {
+            "lang": "en",
+            "url": "http://assets.fanart.tv/fanart/tv/239761/hdtvlogo/wilfred-us-517ac360def17.png",
+            "likes": 1,
+            "id": 28248
+        },
+        {
+            "lang": "he",
+            "url": "http://assets.fanart.tv/fanart/tv/239761/hdtvlogo/wilfred-us-52402df7ed945.png",
+            "likes": 1,
+            "id": 33750
+        },
+        {
+            "lang": "en",
+            "url": "http://assets.fanart.tv/fanart/tv/239761/hdtvlogo/wilfred-us-51f556fb4abd3.png",
+            "likes": 0,
+            "id": 31816
+        }
+    ],
+    "tvdbid": "239761"
+}
diff --git a/lib/fanart/tests/response/50x50.png b/lib/fanart/tests/response/50x50.png
new file mode 100644
index 0000000000000000000000000000000000000000..0ba41614ca1b571daa258e917d1a1e6f5143790c
Binary files /dev/null and b/lib/fanart/tests/response/50x50.png differ
diff --git a/lib/fanart/tests/response/movie_thg.json b/lib/fanart/tests/response/movie_thg.json
new file mode 100644
index 0000000000000000000000000000000000000000..77b6130e9983e5e07922e6ebbf0caed068824740
--- /dev/null
+++ b/lib/fanart/tests/response/movie_thg.json
@@ -0,0 +1,174 @@
+{
+    "The Hunger Games": {
+        "tmdb_id": "70160",
+        "imdb_id": "tt1392170",
+        "movieart": [
+            {
+                "id": "1226",
+                "url": "http://assets.fanart.tv/fanart/movies/70160/movieart/the-hunger-games-4f6dc995edb8f.png",
+                "lang": "en",
+                "likes": "3"
+            },
+            {
+                "id": "1225",
+                "url": "http://assets.fanart.tv/fanart/movies/70160/movieart/the-hunger-games-4f6dc980b4514.png",
+                "lang": "en",
+                "likes": "1"
+            }
+        ],
+        "movielogo": [
+            {
+                "id": "1230",
+                "url": "http://assets.fanart.tv/fanart/movies/70160/movielogo/the-hunger-games-4f6e0e63a9d29.png",
+                "lang": "en",
+                "likes": "2"
+            },
+            {
+                "id": "8020",
+                "url": "http://assets.fanart.tv/fanart/movies/70160/movielogo/the-hunger-games-5018f873b5188.png",
+                "lang": "en",
+                "likes": "1"
+            },
+            {
+                "id": "1224",
+                "url": "http://assets.fanart.tv/fanart/movies/70160/movielogo/the-hunger-games-4f6dc95a08de1.png",
+                "lang": "en",
+                "likes": "0"
+            }
+        ],
+        "moviedisc": [
+            {
+                "id": "8431",
+                "url": "http://assets.fanart.tv/fanart/movies/70160/moviedisc/the-hunger-games-501db4437623f.png",
+                "lang": "en",
+                "likes": "1",
+                "disc": "1",
+                "disc_type": "dvd"
+            },
+            {
+                "id": "9787",
+                "url": "http://assets.fanart.tv/fanart/movies/70160/moviedisc/the-hunger-games-502fd6d695a60.png",
+                "lang": "en",
+                "likes": "1",
+                "disc": "1",
+                "disc_type": "bluray"
+            }
+        ],
+        "moviethumb": [
+            {
+                "id": "10687",
+                "url": "http://assets.fanart.tv/fanart/movies/70160/moviethumb/the-hunger-games-503c88b32cf66.jpg",
+                "lang": "en",
+                "likes": "0"
+            }
+        ],
+        "hdmovielogo": [
+            {
+                "id": "13004",
+                "url": "http://assets.fanart.tv/fanart/movies/70160/hdmovielogo/the-hunger-games-50500118613e3.png",
+                "lang": "en",
+                "likes": "0"
+            }
+        ],
+        "moviebackground": [
+            {
+                "id": "14043",
+                "url": "http://assets.fanart.tv/fanart/movies/70160/moviebackground/the-hunger-games-5057c79ad3c56.jpg",
+                "lang": "en",
+                "likes": "0"
+            },
+            {
+                "id": "14044",
+                "url": "http://assets.fanart.tv/fanart/movies/70160/moviebackground/the-hunger-games-5057c79ad5526.jpg",
+                "lang": "en",
+                "likes": "0"
+            },
+            {
+                "id": "15911",
+                "url": "http://assets.fanart.tv/fanart/movies/70160/moviebackground/the-hunger-games-5071de49311d1.jpg",
+                "lang": "en",
+                "likes": "0"
+            },
+            {
+                "id": "15914",
+                "url": "http://assets.fanart.tv/fanart/movies/70160/moviebackground/the-hunger-games-5071df619b835.jpg",
+                "lang": "en",
+                "likes": "0"
+            },
+            {
+                "id": "15917",
+                "url": "http://assets.fanart.tv/fanart/movies/70160/moviebackground/the-hunger-games-5071e01fee856.jpg",
+                "lang": "en",
+                "likes": "0"
+            },
+            {
+                "id": "15918",
+                "url": "http://assets.fanart.tv/fanart/movies/70160/moviebackground/the-hunger-games-5071e0adcc57a.jpg",
+                "lang": "en",
+                "likes": "0"
+            },
+            {
+                "id": "15919",
+                "url": "http://assets.fanart.tv/fanart/movies/70160/moviebackground/the-hunger-games-5071e12006159.jpg",
+                "lang": "en",
+                "likes": "0"
+            },
+            {
+                "id": "15921",
+                "url": "http://assets.fanart.tv/fanart/movies/70160/moviebackground/the-hunger-games-5071e206aa2ac.jpg",
+                "lang": "en",
+                "likes": "0"
+            },
+            {
+                "id": "15922",
+                "url": "http://assets.fanart.tv/fanart/movies/70160/moviebackground/the-hunger-games-5071e2869d774.jpg",
+                "lang": "en",
+                "likes": "0"
+            },
+            {
+                "id": "15925",
+                "url": "http://assets.fanart.tv/fanart/movies/70160/moviebackground/the-hunger-games-5071e30069b72.jpg",
+                "lang": "en",
+                "likes": "0"
+            },
+            {
+                "id": "15927",
+                "url": "http://assets.fanart.tv/fanart/movies/70160/moviebackground/the-hunger-games-5071e3c4979b7.jpg",
+                "lang": "en",
+                "likes": "0"
+            },
+            {
+                "id": "15930",
+                "url": "http://assets.fanart.tv/fanart/movies/70160/moviebackground/the-hunger-games-5071e5b3f039b.jpg",
+                "lang": "en",
+                "likes": "0"
+            },
+            {
+                "id": "15931",
+                "url": "http://assets.fanart.tv/fanart/movies/70160/moviebackground/the-hunger-games-5071e6369e812.jpg",
+                "lang": "en",
+                "likes": "0"
+            },
+            {
+                "id": "15936",
+                "url": "http://assets.fanart.tv/fanart/movies/70160/moviebackground/the-hunger-games-5071e8749e73a.jpg",
+                "lang": "en",
+                "likes": "0"
+            },
+            {
+                "id": "15937",
+                "url": "http://assets.fanart.tv/fanart/movies/70160/moviebackground/the-hunger-games-5071e9913bfeb.jpg",
+                "lang": "en",
+                "likes": "0"
+            }
+        ],
+        "hdmovieclearart": [
+            {
+                "id": "14104",
+                "url": "http://assets.fanart.tv/fanart/movies/70160/hdmovieclearart/the-hunger-games-50582453b1375.png",
+                "lang": "en",
+                "likes": "0"
+            }
+        ]
+    }
+}
diff --git a/lib/fanart/tests/response/music_a7f.json b/lib/fanart/tests/response/music_a7f.json
new file mode 100644
index 0000000000000000000000000000000000000000..de1a123fca3349dee52157e43d28ca057d458f99
--- /dev/null
+++ b/lib/fanart/tests/response/music_a7f.json
@@ -0,0 +1,171 @@
+{
+    "Avenged Sevenfold": {
+        "mbid_id": "24e1b53c-3085-4581-8472-0b0088d2508c",
+        "artistbackground": [
+            {
+                "id": "3027",
+                "url": "http://assets.fanart.tv/fanart/music/24e1b53c-3085-4581-8472-0b0088d2508c/artistbackground/avenged-sevenfold-4ddd7889a0fcf.jpg",
+                "likes": "0"
+            },
+            {
+                "id": "64046",
+                "url": "http://assets.fanart.tv/fanart/music/24e1b53c-3085-4581-8472-0b0088d2508c/artistbackground/avenged-sevenfold-50c4db9a2c6e2.jpg",
+                "likes": "0"
+            },
+            {
+                "id": "64048",
+                "url": "http://assets.fanart.tv/fanart/music/24e1b53c-3085-4581-8472-0b0088d2508c/artistbackground/avenged-sevenfold-50c4dc653f004.jpg",
+                "likes": "0"
+            }
+        ],
+        "albums": {
+            "180560ee-2d9d-33cf-8de7-cdaaba610739": {
+                "albumcover": [
+                    {
+                        "id": "3028",
+                        "url": "http://assets.fanart.tv/fanart/music/24e1b53c-3085-4581-8472-0b0088d2508c/albumcover/city-of-evil-4ddd79ca0beea.jpg",
+                        "likes": "0"
+                    }
+                ],
+                "cdart": [
+                    {
+                        "id": "9921",
+                        "url": "http://assets.fanart.tv/fanart/music/24e1b53c-3085-4581-8472-0b0088d2508c/cdart/city-of-evil-4e5f7b9f50d37.png",
+                        "likes": "0",
+                        "disc": "1",
+                        "size": "1000"
+                    }
+                ]
+            },
+            "1c7120ae-32b6-3693-8974-599977b01601": {
+                "albumcover": [
+                    {
+                        "id": "3029",
+                        "url": "http://assets.fanart.tv/fanart/music/24e1b53c-3085-4581-8472-0b0088d2508c/albumcover/waking-the-fallen-4ddd79ca1b11e.jpg",
+                        "likes": "0"
+                    }
+                ],
+                "cdart": [
+                    {
+                        "id": "9922",
+                        "url": "http://assets.fanart.tv/fanart/music/24e1b53c-3085-4581-8472-0b0088d2508c/cdart/waking-the-fallen-4e5f7b9f5ebdf.png",
+                        "likes": "0",
+                        "disc": "1",
+                        "size": "1000"
+                    }
+                ]
+            },
+            "94672194-7f42-3965-a489-f2f3cdc1c79e": {
+                "albumcover": [
+                    {
+                        "id": "3030",
+                        "url": "http://assets.fanart.tv/fanart/music/24e1b53c-3085-4581-8472-0b0088d2508c/albumcover/avenged-sevenfold-4ddd79ca1bcd6.jpg",
+                        "likes": "0"
+                    }
+                ],
+                "cdart": [
+                    {
+                        "id": "9923",
+                        "url": "http://assets.fanart.tv/fanart/music/24e1b53c-3085-4581-8472-0b0088d2508c/cdart/avenged-sevenfold-4e5f7b9f5fb7f.png",
+                        "likes": "0",
+                        "disc": "1",
+                        "size": "1000"
+                    }
+                ]
+            },
+            "9d642393-0005-3e89-b3d4-35d89c2f6ad6": {
+                "albumcover": [
+                    {
+                        "id": "3031",
+                        "url": "http://assets.fanart.tv/fanart/music/24e1b53c-3085-4581-8472-0b0088d2508c/albumcover/sounding-the-seventh-trumpet-4ddd79ca1d05e.jpg",
+                        "likes": "0"
+                    }
+                ],
+                "cdart": [
+                    {
+                        "id": "9924",
+                        "url": "http://assets.fanart.tv/fanart/music/24e1b53c-3085-4581-8472-0b0088d2508c/cdart/sounding-the-seventh-trumpet-4e5f7b9f62e47.png",
+                        "likes": "0",
+                        "disc": "1",
+                        "size": "1000"
+                    }
+                ]
+            },
+            "fe4373ed-5e89-46b3-b4c0-31433ce217df": {
+                "albumcover": [
+                    {
+                        "id": "3032",
+                        "url": "http://assets.fanart.tv/fanart/music/24e1b53c-3085-4581-8472-0b0088d2508c/albumcover/nightmare-4ddd79ca1dffe.jpg",
+                        "likes": "0"
+                    }
+                ],
+                "cdart": [
+                    {
+                        "id": "11630",
+                        "url": "http://assets.fanart.tv/fanart/music/24e1b53c-3085-4581-8472-0b0088d2508c/cdart/nightmare-4e8059a3c581c.png",
+                        "likes": "0",
+                        "disc": "1",
+                        "size": "1000"
+                    }
+                ]
+            },
+            "41d1b72b-1eee-3319-937f-c85d6d2fcfbb": {
+                "albumcover": [
+                    {
+                        "id": "61014",
+                        "url": "http://assets.fanart.tv/fanart/music/24e1b53c-3085-4581-8472-0b0088d2508c/albumcover/warmness-on-the-soul-509d2e9150bf4.jpg",
+                        "likes": "0"
+                    }
+                ]
+            }
+        },
+        "musiclogo": [
+            {
+                "id": "5712",
+                "url": "http://assets.fanart.tv/fanart/music/24e1b53c-3085-4581-8472-0b0088d2508c/musiclogo/avenged-sevenfold-4dfc8aee78b49.png",
+                "likes": "0"
+            },
+            {
+                "id": "41835",
+                "url": "http://assets.fanart.tv/fanart/music/24e1b53c-3085-4581-8472-0b0088d2508c/musiclogo/avenged-sevenfold-4ffc75f3a7e54.png",
+                "likes": "0"
+            },
+            {
+                "id": "41836",
+                "url": "http://assets.fanart.tv/fanart/music/24e1b53c-3085-4581-8472-0b0088d2508c/musiclogo/avenged-sevenfold-4ffc75f3a8473.png",
+                "likes": "0"
+            }
+        ],
+        "artistthumb": [
+            {
+                "id": "31109",
+                "url": "http://assets.fanart.tv/fanart/music/24e1b53c-3085-4581-8472-0b0088d2508c/artistthumb/avenged-sevenfold-4fb2b533bc73a.jpg",
+                "likes": "0"
+            },
+            {
+                "id": "64042",
+                "url": "http://assets.fanart.tv/fanart/music/24e1b53c-3085-4581-8472-0b0088d2508c/artistthumb/avenged-sevenfold-50c4d9279d6e9.jpg",
+                "likes": "0"
+            }
+        ],
+        "hdmusiclogo": [
+            {
+                "id": "49644",
+                "url": "http://assets.fanart.tv/fanart/music/24e1b53c-3085-4581-8472-0b0088d2508c/hdmusiclogo/avenged-sevenfold-503fcebece042.png",
+                "likes": "0"
+            },
+            {
+                "id": "49645",
+                "url": "http://assets.fanart.tv/fanart/music/24e1b53c-3085-4581-8472-0b0088d2508c/hdmusiclogo/avenged-sevenfold-503fcebecf17e.png",
+                "likes": "0"
+            }
+        ],
+        "musicbanner": [
+            {
+                "id": "52630",
+                "url": "http://assets.fanart.tv/fanart/music/24e1b53c-3085-4581-8472-0b0088d2508c/musicbanner/avenged-sevenfold-505b2346a559d.jpg",
+                "likes": "0"
+            }
+        ]
+    }
+}
diff --git a/lib/fanart/tests/response/tv_239761.json b/lib/fanart/tests/response/tv_239761.json
new file mode 100644
index 0000000000000000000000000000000000000000..bce4fda2574eeaf78f39b89c3fdaca575a4c7558
--- /dev/null
+++ b/lib/fanart/tests/response/tv_239761.json
@@ -0,0 +1,196 @@
+{
+    "Wilfred (US)": {
+        "hdclearart": [
+            {
+                "url": "http://assets.fanart.tv/fanart/tv/239761/hdclearart/wilfred-us-505f94ed0ba13.png",
+                "lang": "en",
+                "id": "21112",
+                "likes": "1"
+            },
+            {
+                "url": "http://assets.fanart.tv/fanart/tv/239761/hdclearart/wilfred-us-52403264aa3ec.png",
+                "lang": "he",
+                "id": "33751",
+                "likes": "1"
+            }
+        ],
+        "seasonthumb": [
+            {
+                "url": "http://assets.fanart.tv/fanart/tv/239761/seasonthumb/wilfred-us-52403782bab55.jpg",
+                "lang": "he",
+                "id": "33752",
+                "season": "1",
+                "likes": "1"
+            },
+            {
+                "url": "http://assets.fanart.tv/fanart/tv/239761/seasonthumb/wilfred-us-5240379335232.jpg",
+                "lang": "he",
+                "id": "33753",
+                "season": "2",
+                "likes": "1"
+            },
+            {
+                "url": "http://assets.fanart.tv/fanart/tv/239761/seasonthumb/wilfred-us-524037bc83c7d.jpg",
+                "lang": "he",
+                "id": "33754",
+                "season": "3",
+                "likes": "1"
+            },
+            {
+                "url": "http://assets.fanart.tv/fanart/tv/239761/seasonthumb/wilfred-us-501bb0a8e60f9.jpg",
+                "lang": "en",
+                "id": "19586",
+                "season": "1",
+                "likes": "0"
+            },
+            {
+                "url": "http://assets.fanart.tv/fanart/tv/239761/seasonthumb/wilfred-us-501bb0b4bf229.jpg",
+                "lang": "en",
+                "id": "19587",
+                "season": "2",
+                "likes": "0"
+            },
+            {
+                "url": "http://assets.fanart.tv/fanart/tv/239761/seasonthumb/wilfred-us-501bb144e6a46.jpg",
+                "lang": "en",
+                "id": "19588",
+                "season": "0",
+                "likes": "0"
+            },
+            {
+                "url": "http://assets.fanart.tv/fanart/tv/239761/seasonthumb/wilfred-us-51c953105ef77.jpg",
+                "lang": "en",
+                "id": "30309",
+                "season": "3",
+                "likes": "0"
+            }
+        ],
+        "tvbanner": [
+            {
+                "url": "http://assets.fanart.tv/fanart/tv/239761/tvbanner/wilfred-us-52403a7185070.jpg",
+                "lang": "he",
+                "id": "33755",
+                "likes": "1"
+            },
+            {
+                "url": "http://assets.fanart.tv/fanart/tv/239761/tvbanner/wilfred-us-5265193db51f7.jpg",
+                "lang": "en",
+                "id": "34716",
+                "likes": "0"
+            }
+        ],
+        "thetvdb_id": "239761",
+        "clearlogo": [
+            {
+                "url": "http://assets.fanart.tv/fanart/tv/239761/clearlogo/wilfred-us-4e04b6495dfd3.png",
+                "lang": "en",
+                "id": "11977",
+                "likes": "2"
+            },
+            {
+                "url": "http://assets.fanart.tv/fanart/tv/239761/clearlogo/wilfred-us-517ac36e39f67.png",
+                "lang": "en",
+                "id": "28249",
+                "likes": "1"
+            },
+            {
+                "url": "http://assets.fanart.tv/fanart/tv/239761/clearlogo/wilfred-us-51f557082cfde.png",
+                "lang": "en",
+                "id": "31817",
+                "likes": "0"
+            }
+        ],
+        "tvposter": [
+            {
+                "url": "http://assets.fanart.tv/fanart/tv/239761/tvposter/wilfred-us-525d893230d7c.jpg",
+                "lang": "he",
+                "id": "34584",
+                "likes": "1"
+            }
+        ],
+        "showbackground": [
+            {
+                "url": "http://assets.fanart.tv/fanart/tv/239761/showbackground/wilfred-us-5034dbd49115e.jpg",
+                "lang": "en",
+                "id": "19965",
+                "season": "all",
+                "likes": "0"
+            },
+            {
+                "url": "http://assets.fanart.tv/fanart/tv/239761/showbackground/wilfred-us-50b0c92db6973.jpg",
+                "lang": "en",
+                "id": "23166",
+                "season": "all",
+                "likes": "0"
+            },
+            {
+                "url": "http://assets.fanart.tv/fanart/tv/239761/showbackground/wilfred-us-50b0c92dbb46b.jpg",
+                "lang": "en",
+                "id": "23167",
+                "season": "all",
+                "likes": "0"
+            },
+            {
+                "url": "http://assets.fanart.tv/fanart/tv/239761/showbackground/wilfred-us-50b0c92dbb9d1.jpg",
+                "lang": "en",
+                "id": "23168",
+                "season": "all",
+                "likes": "0"
+            }
+        ],
+        "tvthumb": [
+            {
+                "url": "http://assets.fanart.tv/fanart/tv/239761/tvthumb/wilfred-us-501cf526174fe.jpg",
+                "lang": "en",
+                "id": "19596",
+                "likes": "1"
+            },
+            {
+                "url": "http://assets.fanart.tv/fanart/tv/239761/tvthumb/wilfred-us-51bfb4a105904.jpg",
+                "lang": "en",
+                "id": "30060",
+                "likes": "0"
+            }
+        ],
+        "clearart": [
+            {
+                "url": "http://assets.fanart.tv/fanart/tv/239761/clearart/wilfred-us-4e05f10e87711.png",
+                "lang": "en",
+                "id": "11987",
+                "likes": "2"
+            },
+            {
+                "url": "http://assets.fanart.tv/fanart/tv/239761/clearart/wilfred-us-4e2f151d5ed62.png",
+                "lang": "en",
+                "id": "12470",
+                "likes": "1"
+            }
+        ],
+        "hdtvlogo": [
+            {
+                "url": "http://assets.fanart.tv/fanart/tv/239761/hdtvlogo/wilfred-us-505f373be58e6.png",
+                "lang": "en",
+                "id": "21101",
+                "likes": "1"
+            },
+            {
+                "url": "http://assets.fanart.tv/fanart/tv/239761/hdtvlogo/wilfred-us-517ac360def17.png",
+                "lang": "en",
+                "id": "28248",
+                "likes": "1"
+            },
+            {
+                "url": "http://assets.fanart.tv/fanart/tv/239761/hdtvlogo/wilfred-us-52402df7ed945.png",
+                "lang": "he",
+                "id": "33750",
+                "likes": "1"
+            },
+            {
+                "url": "http://assets.fanart.tv/fanart/tv/239761/hdtvlogo/wilfred-us-51f556fb4abd3.png",
+                "lang": "en",
+                "id": "31816",
+                "likes": "0"
+            }
+        ]
+    }
+}
diff --git a/lib/fanart/tests/response/tv_79349.json b/lib/fanart/tests/response/tv_79349.json
new file mode 100644
index 0000000000000000000000000000000000000000..73d1698b9123f30bd5eed4b98d7f13445ba1ccdc
--- /dev/null
+++ b/lib/fanart/tests/response/tv_79349.json
@@ -0,0 +1,756 @@
+{
+    "Dexter": {
+        "thetvdb_id": "79349",
+        "hdtvlogo": [
+            {
+                "id": "20959",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/hdtvlogo/dexter-50575994eb118.png",
+                "lang": "en",
+                "likes": "10"
+            },
+            {
+                "id": "20378",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/hdtvlogo/dexter-503fc2f24d9b3.png",
+                "lang": "en",
+                "likes": "5"
+            }
+        ],
+        "hdclearart": [
+            {
+                "id": "23059",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/hdclearart/dexter-50af98e73b0a5.png",
+                "lang": "en",
+                "likes": "8"
+            },
+            {
+                "id": "24313",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/hdclearart/dexter-50eb4363da522.png",
+                "lang": "en",
+                "likes": "5"
+            },
+            {
+                "id": "20560",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/hdclearart/dexter-504775fd50557.png",
+                "lang": "en",
+                "likes": "4"
+            },
+            {
+                "id": "29495",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/hdclearart/dexter-51aa63100548b.png",
+                "lang": "en",
+                "likes": "3"
+            },
+            {
+                "id": "26712",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/hdclearart/dexter-51400b1672938.png",
+                "lang": "en",
+                "likes": "1"
+            },
+            {
+                "id": "29496",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/hdclearart/dexter-51aa724f0a2ab.png",
+                "lang": "en",
+                "likes": "1"
+            },
+            {
+                "id": "29505",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/hdclearart/dexter-51aab23851368.png",
+                "lang": "en",
+                "likes": "1"
+            },
+            {
+                "id": "29594",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/hdclearart/dexter-51afbcdf38d5e.png",
+                "lang": "en",
+                "likes": "1"
+            },
+            {
+                "id": "29595",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/hdclearart/dexter-51afbcdf3ea8e.png",
+                "lang": "en",
+                "likes": "1"
+            }
+        ],
+        "clearlogo": [
+            {
+                "id": "20958",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/clearlogo/dexter-5057573260826.png",
+                "lang": "en",
+                "likes": "6"
+            },
+            {
+                "id": "2114",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/clearlogo/Dexter-79349-2.png",
+                "lang": "en",
+                "likes": "4"
+            },
+            {
+                "id": "14577",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/clearlogo/dexter-4ecdf0c030189.png",
+                "lang": "en",
+                "likes": "3"
+            },
+            {
+                "id": "16685",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/clearlogo/dexter-4f6879db58edf.png",
+                "lang": "ru",
+                "likes": "1"
+            }
+        ],
+        "characterart": [
+            {
+                "id": "16825",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/characterart/dexter-4f76318ae4410.png",
+                "lang": "en",
+                "likes": "5"
+            },
+            {
+                "id": "29497",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/characterart/dexter-51aa726346bcf.png",
+                "lang": "en",
+                "likes": "3"
+            },
+            {
+                "id": "14981",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/characterart/dexter-4eface5cee809.png",
+                "lang": "en",
+                "likes": "1"
+            },
+            {
+                "id": "16996",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/characterart/dexter-4f8189d220d4b.png",
+                "lang": "en",
+                "likes": "1"
+            },
+            {
+                "id": "26713",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/characterart/dexter-51400b26c65de.png",
+                "lang": "en",
+                "likes": "1"
+            },
+            {
+                "id": "29597",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/characterart/dexter-51afbcf6002a7.png",
+                "lang": "en",
+                "likes": "1"
+            },
+            {
+                "id": "29598",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/characterart/dexter-51afbcf6006e6.png",
+                "lang": "en",
+                "likes": "1"
+            },
+            {
+                "id": "29646",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/characterart/dexter-51b0fc45e0dc0.png",
+                "lang": "en",
+                "likes": "1"
+            }
+        ],
+        "clearart": [
+            {
+                "id": "4980",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/clearart/D_79349 (3).png",
+                "lang": "en",
+                "likes": "4"
+            },
+            {
+                "id": "14579",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/clearart/dexter-4ecdf0db2adf1.png",
+                "lang": "en",
+                "likes": "3"
+            },
+            {
+                "id": "16682",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/clearart/dexter-4f68753540f2d.png",
+                "lang": "ru",
+                "likes": "1"
+            },
+            {
+                "id": "4982",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/clearart/D_79349.png",
+                "lang": "en",
+                "likes": "0"
+            },
+            {
+                "id": "4983",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/clearart/D_79349 (1).png",
+                "lang": "en",
+                "likes": "0"
+            },
+            {
+                "id": "4984",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/clearart/D_79349 (0).png",
+                "lang": "en",
+                "likes": "0"
+            },
+            {
+                "id": "14578",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/clearart/dexter-4ecdf0cf3fb38.png",
+                "lang": "en",
+                "likes": "0"
+            },
+            {
+                "id": "17196",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/clearart/dexter-4f8af83f3bde7.png",
+                "lang": "en",
+                "likes": "0"
+            }
+        ],
+        "showbackground": [
+            {
+                "id": "18467",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/showbackground/dexter-4fc683691dea7.jpg",
+                "lang": "en",
+                "likes": "4",
+                "season": "1"
+            },
+            {
+                "id": "18950",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/showbackground/dexter-4fdf608e2df53.jpg",
+                "lang": "en",
+                "likes": "2",
+                "season": "3"
+            },
+            {
+                "id": "18466",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/showbackground/dexter-4fc6830dc2ccc.jpg",
+                "lang": "en",
+                "likes": "1",
+                "season": "4"
+            },
+            {
+                "id": "18468",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/showbackground/dexter-4fc683a5ab451.jpg",
+                "lang": "en",
+                "likes": "1",
+                "season": "6"
+            },
+            {
+                "id": "21524",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/showbackground/dexter-506bdd9c35771.jpg",
+                "lang": "en",
+                "likes": "1",
+                "season": "all"
+            },
+            {
+                "id": "21526",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/showbackground/dexter-506bddc9f04cb.jpg",
+                "lang": "en",
+                "likes": "1",
+                "season": ""
+            },
+            {
+                "id": "21530",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/showbackground/dexter-506bde2654668.jpg",
+                "lang": "en",
+                "likes": "1",
+                "season": "all"
+            },
+            {
+                "id": "24058",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/showbackground/dexter-50def777ea9c8.jpg",
+                "lang": "en",
+                "likes": "1",
+                "season": "all"
+            },
+            {
+                "id": "18515",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/showbackground/dexter-4fc8eab16803c.jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "all"
+            },
+            {
+                "id": "18947",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/showbackground/dexter-4fdf5e107be0d.jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "5"
+            },
+            {
+                "id": "18949",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/showbackground/dexter-4fdf601385517.jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "all"
+            },
+            {
+                "id": "18952",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/showbackground/dexter-4fdf6386ce1c1.jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "all"
+            },
+            {
+                "id": "21525",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/showbackground/dexter-506bddb3bd3f4.jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "all"
+            },
+            {
+                "id": "21527",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/showbackground/dexter-506bdddc3f476.jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "all"
+            },
+            {
+                "id": "21529",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/showbackground/dexter-506bde113406e.jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "all"
+            },
+            {
+                "id": "24046",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/showbackground/dexter-50de1f84e736f.jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "all"
+            },
+            {
+                "id": "24048",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/showbackground/dexter-50de1f84e7d57.jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "all"
+            },
+            {
+                "id": "24049",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/showbackground/dexter-50de21ac3ae25.jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "all"
+            },
+            {
+                "id": "24054",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/showbackground/dexter-50def777e84d0.jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "all"
+            },
+            {
+                "id": "24055",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/showbackground/dexter-50def777e8dbc.jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "all"
+            },
+            {
+                "id": "24056",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/showbackground/dexter-50def777e9762.jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "all"
+            },
+            {
+                "id": "24986",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/showbackground/dexter-5101fa187c857.jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "all"
+            }
+        ],
+        "seasonthumb": [
+            {
+                "id": "18986",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/seasonthumb/dexter-4fe21b7708ebe.jpg",
+                "lang": "en",
+                "likes": "3",
+                "season": "6"
+            },
+            {
+                "id": "5002",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/seasonthumb/Dexter (6).jpg",
+                "lang": "en",
+                "likes": "1",
+                "season": "3"
+            },
+            {
+                "id": "5003",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/seasonthumb/Dexter (5).jpg",
+                "lang": "en",
+                "likes": "1",
+                "season": "1"
+            },
+            {
+                "id": "17802",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/seasonthumb/dexter-4fa981a7251d7.jpg",
+                "lang": "en",
+                "likes": "1",
+                "season": "5"
+            },
+            {
+                "id": "17823",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/seasonthumb/dexter-4faab0bccbfb6.jpg",
+                "lang": "en",
+                "likes": "1",
+                "season": "6"
+            },
+            {
+                "id": "18980",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/seasonthumb/dexter-4fe21a6955116.jpg",
+                "lang": "en",
+                "likes": "1",
+                "season": "1"
+            },
+            {
+                "id": "18982",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/seasonthumb/dexter-4fe21b0767edb.jpg",
+                "lang": "en",
+                "likes": "1",
+                "season": "2"
+            },
+            {
+                "id": "18983",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/seasonthumb/dexter-4fe21b292d661.jpg",
+                "lang": "en",
+                "likes": "1",
+                "season": "3"
+            },
+            {
+                "id": "18984",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/seasonthumb/dexter-4fe21b42d983d.jpg",
+                "lang": "en",
+                "likes": "1",
+                "season": "4"
+            },
+            {
+                "id": "18985",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/seasonthumb/dexter-4fe21b5847d7b.jpg",
+                "lang": "en",
+                "likes": "1",
+                "season": "5"
+            },
+            {
+                "id": "21883",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/seasonthumb/dexter-5071800d37e80.jpg",
+                "lang": "en",
+                "likes": "1",
+                "season": "7"
+            },
+            {
+                "id": "4989",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/seasonthumb/Dexter (9).jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "all"
+            },
+            {
+                "id": "4990",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/seasonthumb/Dexter (19).jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "4"
+            },
+            {
+                "id": "4991",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/seasonthumb/Dexter (18).jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "4"
+            },
+            {
+                "id": "4992",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/seasonthumb/Dexter (17).jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "3"
+            },
+            {
+                "id": "4993",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/seasonthumb/Dexter (16).jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "2"
+            },
+            {
+                "id": "4994",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/seasonthumb/Dexter (15).jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "1"
+            },
+            {
+                "id": "4995",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/seasonthumb/Dexter (14).jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "all"
+            },
+            {
+                "id": "4996",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/seasonthumb/Dexter (13).jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "4"
+            },
+            {
+                "id": "4997",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/seasonthumb/Dexter (12).jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "3"
+            },
+            {
+                "id": "4998",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/seasonthumb/Dexter (11).jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "2"
+            },
+            {
+                "id": "4999",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/seasonthumb/Dexter (10).jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "1"
+            },
+            {
+                "id": "5000",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/seasonthumb/Dexter (8).jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "2"
+            },
+            {
+                "id": "5001",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/seasonthumb/Dexter (7).jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "4"
+            },
+            {
+                "id": "5004",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/seasonthumb/Dexter.jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "all"
+            },
+            {
+                "id": "5005",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/seasonthumb/Dexter (4).jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "5"
+            },
+            {
+                "id": "5006",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/seasonthumb/Dexter (3).jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "4"
+            },
+            {
+                "id": "5007",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/seasonthumb/Dexter (2).jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "3"
+            },
+            {
+                "id": "5008",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/seasonthumb/Dexter (1).jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "2"
+            },
+            {
+                "id": "5009",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/seasonthumb/Dexter (0).jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "1"
+            },
+            {
+                "id": "17803",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/seasonthumb/dexter-4fa981a7258fb.jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "5"
+            },
+            {
+                "id": "17804",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/seasonthumb/dexter-4fa981a725c14.jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "5"
+            },
+            {
+                "id": "17805",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/seasonthumb/dexter-4fa981c6607e4.jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "0"
+            },
+            {
+                "id": "17807",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/seasonthumb/dexter-4fa98ac2b811d.jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "6"
+            },
+            {
+                "id": "17808",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/seasonthumb/dexter-4fa98ac2b87ab.jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "6"
+            },
+            {
+                "id": "17810",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/seasonthumb/dexter-4fa994697afa3.jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "6"
+            },
+            {
+                "id": "18514",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/seasonthumb/dexter-4fc8e9fa79bf8.jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "7"
+            },
+            {
+                "id": "31022",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/seasonthumb/dexter-51dc720661cb7.jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "8"
+            },
+            {
+                "id": "31023",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/seasonthumb/dexter-51dc72a19a0bb.jpg",
+                "lang": "en",
+                "likes": "0",
+                "season": "8"
+            }
+        ],
+        "tvthumb": [
+            {
+                "id": "5012",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/tvthumb/D_79349 (10).jpg",
+                "lang": "en",
+                "likes": "2"
+            },
+            {
+                "id": "5023",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/tvthumb/D_79349 (0).jpg",
+                "lang": "en",
+                "likes": "2"
+            },
+            {
+                "id": "14580",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/tvthumb/dexter-4ecdf5027a53c.jpg",
+                "lang": "en",
+                "likes": "2"
+            },
+            {
+                "id": "5013",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/tvthumb/D_79349 (9).jpg",
+                "lang": "en",
+                "likes": "1"
+            },
+            {
+                "id": "5016",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/tvthumb/D_79349 (6).jpg",
+                "lang": "en",
+                "likes": "1"
+            },
+            {
+                "id": "5020",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/tvthumb/D_79349 (2).jpg",
+                "lang": "en",
+                "likes": "1"
+            },
+            {
+                "id": "29341",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/tvthumb/dexter-51a338d376b4a.jpg",
+                "lang": "de",
+                "likes": "1"
+            },
+            {
+                "id": "31722",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/tvthumb/dexter-51f27112a2a89.jpg",
+                "lang": "en",
+                "likes": "1"
+            },
+            {
+                "id": "5010",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/tvthumb/D_79349 (12).jpg",
+                "lang": "en",
+                "likes": "0"
+            },
+            {
+                "id": "5011",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/tvthumb/D_79349 (11).jpg",
+                "lang": "en",
+                "likes": "0"
+            },
+            {
+                "id": "5014",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/tvthumb/D_79349 (8).jpg",
+                "lang": "en",
+                "likes": "0"
+            },
+            {
+                "id": "5015",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/tvthumb/D_79349 (7).jpg",
+                "lang": "en",
+                "likes": "0"
+            },
+            {
+                "id": "5017",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/tvthumb/D_79349 (5).jpg",
+                "lang": "en",
+                "likes": "0"
+            },
+            {
+                "id": "5018",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/tvthumb/D_79349 (4).jpg",
+                "lang": "en",
+                "likes": "0"
+            },
+            {
+                "id": "5019",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/tvthumb/D_79349 (3).jpg",
+                "lang": "en",
+                "likes": "0"
+            },
+            {
+                "id": "5021",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/tvthumb/D_79349.jpg",
+                "lang": "en",
+                "likes": "0"
+            },
+            {
+                "id": "5022",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/tvthumb/D_79349 (1).jpg",
+                "lang": "en",
+                "likes": "0"
+            },
+            {
+                "id": "14277",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/tvthumb/dexter-4ead4375923fd.jpg",
+                "lang": "en",
+                "likes": "0"
+            }
+        ],
+        "tvbanner": [
+            {
+                "id": "30062",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/tvbanner/dexter-51bfc857c84fd.jpg",
+                "lang": "en",
+                "likes": "1"
+            },
+            {
+                "id": "30063",
+                "url": "http://assets.fanart.tv/fanart/tv/79349/tvbanner/dexter-51bfc89667267.jpg",
+                "lang": "en",
+                "likes": "1"
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/lib/fanart/tests/test_core.py b/lib/fanart/tests/test_core.py
new file mode 100644
index 0000000000000000000000000000000000000000..2cdb71fbceaea55e9d1828927e26a607c8cfad04
--- /dev/null
+++ b/lib/fanart/tests/test_core.py
@@ -0,0 +1,23 @@
+from unittest import TestCase
+from fanart.core import Request
+from fanart.errors import RequestFanartError, ResponseFanartError
+from httpretty import httprettified, HTTPretty
+
+
+class RequestTestCase(TestCase):
+    def test_valitate_error(self):
+        self.assertRaises(RequestFanartError, Request, 'key', 'id', 'sport')
+
+    @httprettified
+    def test_response_error(self):
+        request = Request('apikey', 'objid', 'series')
+        HTTPretty.register_uri(
+            HTTPretty.GET,
+            'http://api.fanart.tv/webservice/series/apikey/objid/JSON/all/1/2',
+            body='Please specify a valid API key',
+        )
+        try:
+            request.response()
+        except ResponseFanartError as e:
+            self.assertEqual(repr(e), "ResponseFanartError('No JSON object could be decoded',)")
+            self.assertEqual(str(e), 'No JSON object could be decoded')
diff --git a/lib/fanart/tests/test_immutable.py b/lib/fanart/tests/test_immutable.py
new file mode 100644
index 0000000000000000000000000000000000000000..8a0149dbe94c65f899d2e67400a5f130958a9b77
--- /dev/null
+++ b/lib/fanart/tests/test_immutable.py
@@ -0,0 +1,49 @@
+from unittest import TestCase
+from fanart.immutable import Immutable
+
+
+class TestMutable(object):
+    def __init__(self, spam, ham, eggs):
+        self.spam = spam
+        self.ham = ham
+        self.eggs = eggs
+
+    @Immutable.mutablemethod
+    def anyway(self):
+        self.spam = self.ham + self.eggs
+
+
+class TestImmutable(TestMutable, Immutable):
+    @Immutable.mutablemethod
+    def __init__(self, *args, **kwargs):
+        super(TestImmutable, self).__init__(*args, **kwargs)
+
+
+class ImmutableTestCase(TestCase):
+    def setUp(self):
+        self.instance = TestImmutable('spam', 'ham', 'eggs')
+
+    def test_set_raises(self):
+        self.assertRaises(TypeError, self.instance.__setattr__, 'spam', 'ham')
+
+    def test_set(self):
+        self.instance._mutable = True
+        self.instance.spam = 'ham'
+        self.assertEqual(self.instance.spam, 'ham')
+
+    def test_del_raises(self):
+        self.assertRaises(TypeError, self.instance.__delattr__, 'spam')
+
+    def test_del(self):
+        self.instance._mutable = True
+        del self.instance.spam
+        self.assertRaises(AttributeError, self.instance.__getattribute__, 'spam')
+
+    def test_equal(self):
+        new_instance = TestImmutable('spam', 'ham', 'eggs')
+        self.assertEqual(self.instance, new_instance)
+
+    def test_mutable_dec(self):
+        instance = TestMutable('spam', 'ham', 'eggs')
+        instance.anyway()
+        self.assertEqual(instance.spam, 'hameggs')
diff --git a/lib/fanart/tests/test_items.py b/lib/fanart/tests/test_items.py
new file mode 100644
index 0000000000000000000000000000000000000000..e6c304389bba2d00d7b52ba2071e64bff0859f0a
--- /dev/null
+++ b/lib/fanart/tests/test_items.py
@@ -0,0 +1,27 @@
+from unittest import TestCase
+import os
+from fanart.items import LeafItem
+from httpretty import httprettified, HTTPretty
+from fanart.tests import LOCALDIR
+
+
+class LeafItemTestCase(TestCase):
+    def setUp(self):
+        self.leaf = LeafItem(id=11977, likes=2, url='http://test.tv/50x50.txt')
+
+    def test_str(self):
+        self.assertEqual(str(self.leaf), 'http://test.tv/50x50.txt')
+
+    @httprettified
+    def test_content(self):
+        with open(os.path.join(LOCALDIR, 'response/50x50.png')) as fp:
+            body = fp.read()
+        HTTPretty.register_uri(
+            HTTPretty.GET,
+            'http://test.tv/50x50.txt',
+            body=body
+        )
+        self.assertEqual(self.leaf.content(), body)
+        self.assertEqual(len(HTTPretty.latest_requests), 1)
+        self.assertEqual(self.leaf.content(), body)  # Cached
+        self.assertEqual(len(HTTPretty.latest_requests), 1)
diff --git a/lib/fanart/tests/test_movie.py b/lib/fanart/tests/test_movie.py
new file mode 100644
index 0000000000000000000000000000000000000000..f127c28e2a0c417781cac4d3159aa3f1a1be2e0b
--- /dev/null
+++ b/lib/fanart/tests/test_movie.py
@@ -0,0 +1,21 @@
+import os
+import unittest
+from httpretty import HTTPretty, httprettified
+from fanart.movie import *
+from fanart.tests import LOCALDIR
+os.environ['FANART_APIKEY'] = 'e3c7f0d0beeaf45b3a0dd3b9dd8a3338'
+
+
+class TvItemTestCase(unittest.TestCase):
+    @httprettified
+    def test_get(self):
+        with open(os.path.join(LOCALDIR, 'response/movie_thg.json')) as fp:
+            body = fp.read()
+        HTTPretty.register_uri(
+            HTTPretty.GET,
+            'http://api.fanart.tv/webservice/movie/e3c7f0d0beeaf45b3a0dd3b9dd8a3338/70160/JSON/all/1/2',
+            body=body
+        )
+        hunger_games = Movie.get(id=70160)
+        self.assertEqual(hunger_games.tmdbid, '70160')
+        self.assertEqual(hunger_games, eval(repr(hunger_games)))
diff --git a/lib/fanart/tests/test_music.py b/lib/fanart/tests/test_music.py
new file mode 100644
index 0000000000000000000000000000000000000000..8c5d107d8406d93c288ec5236aeb4a8a9460eca9
--- /dev/null
+++ b/lib/fanart/tests/test_music.py
@@ -0,0 +1,22 @@
+import os
+import unittest
+from httpretty import HTTPretty, httprettified
+from fanart.music import *
+from fanart.tests import LOCALDIR
+os.environ['FANART_APIKEY'] = 'e3c7f0d0beeaf45b3a0dd3b9dd8a3338'
+
+
+class ArtistItemTestCase(unittest.TestCase):
+    @httprettified
+    def test_get(self):
+        with open(os.path.join(LOCALDIR, 'response/music_a7f.json')) as fp:
+            body = fp.read()
+        HTTPretty.register_uri(
+            HTTPretty.GET,
+            'http://api.fanart.tv/webservice/artist/e3c7f0d0beeaf45b3a0dd3b9dd8a3338/24e1b53c-3085-4581-8472-0b0088d2508c/JSON/all/1/2',
+            body=body
+        )
+        a7f = Artist.get(id='24e1b53c-3085-4581-8472-0b0088d2508c')
+        self.assertEqual(a7f.mbid, '24e1b53c-3085-4581-8472-0b0088d2508c')
+        self.assertEqual(a7f, eval(repr(a7f)))
+        self.assertEqual(len(a7f.thumbs), 2)
diff --git a/lib/fanart/tests/test_tv.py b/lib/fanart/tests/test_tv.py
new file mode 100644
index 0000000000000000000000000000000000000000..eb5e742576028be765eee84fa132bb4bb9569002
--- /dev/null
+++ b/lib/fanart/tests/test_tv.py
@@ -0,0 +1,46 @@
+import json
+from fanart.errors import ResponseFanartError
+import os
+import unittest
+from httpretty import HTTPretty, httprettified
+from fanart.tv import *
+from fanart.tests import LOCALDIR
+os.environ['FANART_APIKEY'] = 'e3c7f0d0beeaf45b3a0dd3b9dd8a3338'
+
+
+class TvItemTestCase(unittest.TestCase):
+    @httprettified
+    def test_get_wilfred(self):
+        with open(os.path.join(LOCALDIR, 'response/tv_239761.json')) as fp:
+            body = fp.read()
+        HTTPretty.register_uri(
+            HTTPretty.GET,
+            'http://api.fanart.tv/webservice/series/e3c7f0d0beeaf45b3a0dd3b9dd8a3338/239761/JSON/all/1/2',
+            body=body
+        )
+        wilfred = TvShow.get(id=239761)
+        self.assertEqual(wilfred.tvdbid, '239761')
+        with open(os.path.join(LOCALDIR, 'json/wilfred.json')) as fp:
+            self.assertEqual(json.loads(wilfred.json()), json.load(fp))
+
+    @httprettified
+    def test_get_dexter(self):
+        with open(os.path.join(LOCALDIR, 'response/tv_79349.json')) as fp:
+            body = fp.read()
+        HTTPretty.register_uri(
+            HTTPretty.GET,
+            'http://api.fanart.tv/webservice/series/e3c7f0d0beeaf45b3a0dd3b9dd8a3338/79349/JSON/all/1/2',
+            body=body
+        )
+        dexter = TvShow.get(id=79349)
+        self.assertEqual(dexter.tvdbid, '79349')
+        self.assertEqual(dexter, eval(repr(dexter)))
+
+    @httprettified
+    def test_get_null(self):
+        HTTPretty.register_uri(
+            HTTPretty.GET,
+            'http://api.fanart.tv/webservice/series/e3c7f0d0beeaf45b3a0dd3b9dd8a3338/79349/JSON/all/1/2',
+            body='null'
+        )
+        self.assertRaises(ResponseFanartError, TvShow.get, id=79349)
diff --git a/lib/fanart/tv.py b/lib/fanart/tv.py
new file mode 100644
index 0000000000000000000000000000000000000000..beedff621a983ff1971364cadddb966a03cc0813
--- /dev/null
+++ b/lib/fanart/tv.py
@@ -0,0 +1,108 @@
+import fanart
+from fanart.items import LeafItem, Immutable, ResourceItem
+__all__ = (
+    'CharacterItem',
+    'ArtItem',
+    'LogoItem',
+    'BackgroundItem',
+    'SeasonItem',
+    'ThumbItem',
+    'HdLogoItem',
+    'HdArtItem',
+    'PosterItem',
+    'BannerItem',
+    'TvShow',
+)
+
+
+class TvItem(LeafItem):
+    @Immutable.mutablemethod
+    def __init__(self, id, url, likes, lang):
+        super(TvItem, self).__init__(id, url, likes)
+        self.lang = lang
+
+
+class SeasonedTvItem(TvItem):
+    @Immutable.mutablemethod
+    def __init__(self, id, url, likes, lang, season):
+        super(SeasonedTvItem, self).__init__(id, url, likes, lang)
+        self.season = 0 if season == 'all' else int(season or 0)
+
+
+class CharacterItem(TvItem):
+    KEY = fanart.TYPE.TV.CHARACTER
+
+
+class ArtItem(TvItem):
+    KEY = fanart.TYPE.TV.ART
+
+
+class LogoItem(TvItem):
+    KEY = fanart.TYPE.TV.LOGO
+
+
+class BackgroundItem(SeasonedTvItem):
+    KEY = fanart.TYPE.TV.BACKGROUND
+
+
+class SeasonItem(SeasonedTvItem):
+    KEY = fanart.TYPE.TV.SEASONTHUMB
+
+
+class ThumbItem(TvItem):
+    KEY = fanart.TYPE.TV.THUMB
+
+
+class HdLogoItem(TvItem):
+    KEY = fanart.TYPE.TV.HDLOGO
+
+
+class HdArtItem(TvItem):
+    KEY = fanart.TYPE.TV.HDART
+
+
+class PosterItem(TvItem):
+    KEY = fanart.TYPE.TV.POSTER
+
+
+class BannerItem(TvItem):
+    KEY = fanart.TYPE.TV.BANNER
+
+
+class TvShow(ResourceItem):
+    WS = fanart.WS.TV
+
+    @Immutable.mutablemethod
+    def __init__(self, name, tvdbid, backgrounds, characters, arts, logos, seasons, thumbs, hdlogos, hdarts, posters,
+                 banners):
+        self.name = name
+        self.tvdbid = tvdbid
+        self.backgrounds = backgrounds
+        self.characters = characters
+        self.arts = arts
+        self.logos = logos
+        self.seasons = seasons
+        self.thumbs = thumbs
+        self.hdlogos = hdlogos
+        self.hdarts = hdarts
+        self.posters = posters
+        self.banners = banners
+
+    @classmethod
+    def from_dict(cls, resource):
+        assert len(resource) == 1, 'Bad Format Map'
+        name, resource = resource.items()[0]
+        return cls(
+            name=name,
+            tvdbid=resource['thetvdb_id'],
+            backgrounds=BackgroundItem.extract(resource),
+            characters=CharacterItem.extract(resource),
+            arts=ArtItem.extract(resource),
+            logos=LogoItem.extract(resource),
+            seasons=SeasonItem.extract(resource),
+            thumbs=ThumbItem.extract(resource),
+            hdlogos=HdLogoItem.extract(resource),
+            hdarts=HdArtItem.extract(resource),
+            posters=PosterItem.extract(resource),
+            banners=BannerItem.extract(resource),
+        )
diff --git a/lib/tvdb_api/tvdb_api.py b/lib/tvdb_api/tvdb_api.py
index c7843c734a2857f1c59473412ce9cddc5085ed7e..7c7ee02d901a7d052691d40040d9718d331d9a03 100644
--- a/lib/tvdb_api/tvdb_api.py
+++ b/lib/tvdb_api/tvdb_api.py
@@ -736,7 +736,7 @@ class Tvdb:
             return
 
         banners = {}
-        for cur_banner in bannersEt['banner']:
+        for cur_banner in bannersEt['banner'] if isinstance(bannersEt['banner'], list) else [bannersEt['banner']]:
             bid = cur_banner['id']
             btype = cur_banner['bannertype']
             btype2 = cur_banner['bannertype2']
@@ -797,7 +797,7 @@ class Tvdb:
             return
 
         cur_actors = Actors()
-        for cur_actor in actorsEt['actor']:
+        for cur_actor in actorsEt['actor'] if isinstance(actorsEt['actor'], list) else [actorsEt['actor']]:
             curActor = Actor()
             for k, v in cur_actor.items():
                 if k is None or v is None:
diff --git a/sickbeard/__init__.py b/sickbeard/__init__.py
index 9f842a38adef659be9e7c6904e1a7eacee985892..a97434caedfe49aa17978c86ac919611bfd95a9a 100755
--- a/sickbeard/__init__.py
+++ b/sickbeard/__init__.py
@@ -58,7 +58,7 @@ CFG = None
 CONFIG_FILE = None
 
 # This is the version of the config we EXPECT to find
-CONFIG_VERSION = 5
+CONFIG_VERSION = 6
 
 # Default encryption version (0 for None)
 ENCRYPTION_VERSION = 0
@@ -148,7 +148,6 @@ CPU_PRESET = None
 
 ANON_REDIRECT = None
 
-USE_API = False
 API_KEY = None
 API_ROOT = None
 
@@ -472,6 +471,7 @@ CALENDAR_UNPROTECTED = False
 
 TMDB_API_KEY = 'edc5f123313769de83a71e157758030b'
 TRAKT_API_KEY = 'abd806c54516240c76e4ebc9c5ccf394'
+FANART_API_KEY = '9b3afaf26f6241bdb57d6cc6bd798da7'
 
 __INITIALIZED__ = False
 
@@ -484,7 +484,7 @@ def get_backlog_cycle_time():
 def initialize(consoleLogging=True):
     with INIT_LOCK:
 
-        global BRANCH, GIT_RESET, GIT_REMOTE, GIT_REMOTE_URL, CUR_COMMIT_HASH, CUR_COMMIT_BRANCH, ACTUAL_LOG_DIR, LOG_DIR, WEB_PORT, WEB_LOG, ENCRYPTION_VERSION, WEB_ROOT, WEB_USERNAME, WEB_PASSWORD, WEB_HOST, WEB_IPV6, USE_API, API_KEY, API_ROOT, ENABLE_HTTPS, HTTPS_CERT, HTTPS_KEY, \
+        global BRANCH, GIT_RESET, GIT_REMOTE, GIT_REMOTE_URL, CUR_COMMIT_HASH, CUR_COMMIT_BRANCH, ACTUAL_LOG_DIR, LOG_DIR, WEB_PORT, WEB_LOG, ENCRYPTION_VERSION, WEB_ROOT, WEB_USERNAME, WEB_PASSWORD, WEB_HOST, WEB_IPV6, API_KEY, API_ROOT, ENABLE_HTTPS, HTTPS_CERT, HTTPS_KEY, \
             HANDLE_REVERSE_PROXY, USE_NZBS, USE_TORRENTS, NZB_METHOD, NZB_DIR, DOWNLOAD_PROPERS, RANDOMIZE_PROVIDERS, CHECK_PROPERS_INTERVAL, ALLOW_HIGH_PRIORITY, TORRENT_METHOD, \
             SAB_USERNAME, SAB_PASSWORD, SAB_APIKEY, SAB_CATEGORY, SAB_CATEGORY_ANIME, SAB_HOST, \
             NZBGET_USERNAME, NZBGET_PASSWORD, NZBGET_CATEGORY, NZBGET_CATEGORY_ANIME, NZBGET_PRIORITY, NZBGET_HOST, NZBGET_USE_HTTPS, backlogSearchScheduler, \
@@ -658,7 +658,6 @@ def initialize(consoleLogging=True):
 
         SORT_ARTICLE = bool(check_setting_int(CFG, 'General', 'sort_article', 0))
 
-        USE_API = bool(check_setting_int(CFG, 'General', 'use_api', 0))
         API_KEY = check_setting_str(CFG, 'General', 'api_key', '', censor_log=True)
 
         ENABLE_HTTPS = bool(check_setting_int(CFG, 'General', 'enable_https', 0))
@@ -1435,7 +1434,6 @@ def save_config():
     new_config['General']['localhost_ip'] = LOCALHOST_IP
     new_config['General']['cpu_preset'] = CPU_PRESET
     new_config['General']['anon_redirect'] = ANON_REDIRECT
-    new_config['General']['use_api'] = int(USE_API)
     new_config['General']['api_key'] = API_KEY
     new_config['General']['debug'] = int(DEBUG)
     new_config['General']['enable_https'] = int(ENABLE_HTTPS)
diff --git a/sickbeard/classes.py b/sickbeard/classes.py
index 7a0420a5d11a883ddf7ad46090d67c8927d43bf1..d6f643d355d8653c835821bcc31a27198affc80e 100644
--- a/sickbeard/classes.py
+++ b/sickbeard/classes.py
@@ -17,6 +17,7 @@
 # along with SickRage.  If not, see <http://www.gnu.org/licenses/>.
 import re
 import sys
+import traceback
 
 import sickbeard
 
@@ -275,13 +276,6 @@ class UIError():
     """
 
     def __init__(self, message):
-        try:
-            self.title = sys.exc_info()[1].message
-        except:
-            self.title = None
+        self.title = sys.exc_info()[-2]
         self.message = message
-        self.time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
-        try:
-            self.exc_info = sys.exc_info()
-        except:
-            self.exc_info = None
+        self.time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
\ No newline at end of file
diff --git a/sickbeard/config.py b/sickbeard/config.py
index a1927bbf77ed2cee2571f484a9d357b530ff62bf..fd365ef00f13cd2d09f46369c89f66402c178053 100644
--- a/sickbeard/config.py
+++ b/sickbeard/config.py
@@ -457,7 +457,8 @@ class ConfigMigrator():
                                 2: 'Sync backup number with version number',
                                 3: 'Rename omgwtfnzb variables',
                                 4: 'Add newznab catIDs',
-                                5: 'Metadata update'
+                                5: 'Metadata update',
+                                6: 'Convert from XBMC to new KODI variables'
         }
 
     def migrate_config(self):
@@ -673,11 +674,11 @@ class ConfigMigrator():
         new format: 0|0|0|0|0|0|0|0|0|0 -- 10 places
 
         Drop the use of use_banner option.
-        Migrate the poster override to just using the banner option (applies to kodi only).
+        Migrate the poster override to just using the banner option (applies to xbmc only).
         """
 
-        metadata_kodi = check_setting_str(self.config_obj, 'General', 'metadata_kodi', '0|0|0|0|0|0')
-        metadata_kodi_12plus = check_setting_str(self.config_obj, 'General', 'metadata_kodi_12plus', '0|0|0|0|0|0')
+        metadata_xbmc = check_setting_str(self.config_obj, 'General', 'metadata_xbmc', '0|0|0|0|0|0')
+        metadata_xbmc_12plus = check_setting_str(self.config_obj, 'General', 'metadata_xbmc_12plus', '0|0|0|0|0|0')
         metadata_mediabrowser = check_setting_str(self.config_obj, 'General', 'metadata_mediabrowser', '0|0|0|0|0|0')
         metadata_ps3 = check_setting_str(self.config_obj, 'General', 'metadata_ps3', '0|0|0|0|0|0')
         metadata_wdtv = check_setting_str(self.config_obj, 'General', 'metadata_wdtv', '0|0|0|0|0|0')
@@ -698,7 +699,7 @@ class ConfigMigrator():
                 # swap show fanart, show poster
                 cur_metadata[3], cur_metadata[2] = cur_metadata[2], cur_metadata[3]
                 # if user was using use_banner to override the poster, instead enable the banner option and deactivate poster
-                if metadata_name == 'KODI' and use_banner:
+                if metadata_name == 'XBMC' and use_banner:
                     cur_metadata[4], cur_metadata[3] = cur_metadata[3], '0'
                 # write new format
                 metadata = '|'.join(cur_metadata)
@@ -717,10 +718,27 @@ class ConfigMigrator():
 
             return metadata
 
-        sickbeard.METADATA_KODI = _migrate_metadata(metadata_kodi, 'KODI', use_banner)
-        sickbeard.METADATA_KODI_12PLUS = _migrate_metadata(metadata_kodi_12plus, 'KODI 12+', use_banner)
+        sickbeard.METADATA_XBMC = _migrate_metadata(metadata_xbmc, 'XBMC', use_banner)
+        sickbeard.METADATA_XBMC_12PLUS = _migrate_metadata(metadata_xbmc_12plus, 'XBMC 12+', use_banner)
         sickbeard.METADATA_MEDIABROWSER = _migrate_metadata(metadata_mediabrowser, 'MediaBrowser', use_banner)
         sickbeard.METADATA_PS3 = _migrate_metadata(metadata_ps3, 'PS3', use_banner)
         sickbeard.METADATA_WDTV = _migrate_metadata(metadata_wdtv, 'WDTV', use_banner)
         sickbeard.METADATA_TIVO = _migrate_metadata(metadata_tivo, 'TIVO', use_banner)
         sickbeard.METADATA_MEDE8ER = _migrate_metadata(metadata_mede8er, 'Mede8er', use_banner)
+
+    # Migration v6: Convert from XBMC to KODI variables
+    def _migrate_v6(self):
+        sickbeard.USE_KODI = bool(check_setting_int(self.config_obj, 'XBMC', 'use_xbmc', 0))
+        sickbeard.KODI_ALWAYS_ON = bool(check_setting_int(self.config_obj, 'XBMC', 'xbmc_always_on', 1))
+        sickbeard.KODI_NOTIFY_ONSNATCH = bool(check_setting_int(self.config_obj, 'XBMC', 'xbmc_notify_onsnatch', 0))
+        sickbeard.KODI_NOTIFY_ONDOWNLOAD = bool(check_setting_int(self.config_obj, 'XBMC', 'xbmc_notify_ondownload', 0))
+        sickbeard.KODI_NOTIFY_ONSUBTITLEDOWNLOAD = bool(check_setting_int(self.config_obj, 'XBMC', 'xbmc_notify_onsubtitledownload', 0))
+        sickbeard.KODI_UPDATE_LIBRARY = bool(check_setting_int(self.config_obj, 'XBMC', 'xbmc_update_library', 0))
+        sickbeard.KODI_UPDATE_FULL = bool(check_setting_int(self.config_obj, 'XBMC', 'xbmc_update_full', 0))
+        sickbeard.KODI_UPDATE_ONLYFIRST = bool(check_setting_int(self.config_obj, 'XBMC', 'xbmc_update_onlyfirst', 0))
+        sickbeard.KODI_HOST = check_setting_str(self.config_obj, 'XBMC', 'xbmc_host', '')
+        sickbeard.KODI_USERNAME = check_setting_str(self.config_obj, 'XBMC', 'xbmc_username', '', censor_log=True)
+        sickbeard.KODI_PASSWORD = check_setting_str(self.config_obj, 'XBMC', 'xbmc_password', '', censor_log=True)
+        sickbeard.METADATA_KODI = check_setting_str(self.config_obj, 'General', 'metadata_xbmc', '0|0|0|0|0|0|0|0|0|0')
+        sickbeard.METADATA_KODI_12PLUS = check_setting_str(self.config_obj, 'General', 'metadata_xbmc_12plus', '0|0|0|0|0|0|0|0|0|0')
+
diff --git a/sickbeard/db.py b/sickbeard/db.py
index 1d633b08ddc3bf673e3700f414624387d5715fc2..8b119054e1042f77eb7cb2fca089c1600a42f0cc 100644
--- a/sickbeard/db.py
+++ b/sickbeard/db.py
@@ -73,18 +73,9 @@ class DBConnection(object):
             raise
 
     def _execute(self, query, args):
-        def convert(x):
-            if isinstance(x, basestring):
-                try:
-                    x = unicode(x).decode(sickbeard.SYS_ENCODING)
-                except:
-                    pass
-            return x
-
         try:
             if not args:
                 return self.connection.cursor().execute(query)
-            # args = map(convert, args)
             return self.connection.cursor().execute(query, args)
         except Exception as e:
             raise e
@@ -238,7 +229,10 @@ class DBConnection(object):
         return columns
 
     def _unicode_text_factory(self, x):
-        return unicode(x, 'utf-8')
+        try:
+            return unicode(x, 'utf-8')
+        except:
+            return unicode(x, sickbeard.SYS_ENCODING)
 
     def _dict_factory(self, cursor, row):
         d = {}
diff --git a/sickbeard/logger.py b/sickbeard/logger.py
index 2305025041a1063f0f46b1c8cfae3b40e554808c..323c43c91bc51b1b1b6f034368bd3a1e394ed13a 100644
--- a/sickbeard/logger.py
+++ b/sickbeard/logger.py
@@ -45,11 +45,16 @@ reverseNames = {u'ERROR': ERROR,
 
 censoredItems = {}
 
+
 class NullHandler(logging.Handler):
     def emit(self, record):
         pass
 
-class CensoredFormatter(logging.Formatter):
+
+class CensoredFormatter(logging.Formatter, object):
+    def __init__(self, *args, **kwargs):
+        super(CensoredFormatter, self).__init__(*args, **kwargs)
+
     def format(self, record):
         msg = super(CensoredFormatter, self).format(record)
         for k, v in censoredItems.items():
@@ -57,6 +62,7 @@ class CensoredFormatter(logging.Formatter):
                 msg = msg.replace(v, len(v) * '*')
         return msg
 
+
 class Logger(object):
     def __init__(self):
         self.logger = logging.getLogger('sickrage')
@@ -65,7 +71,7 @@ class Logger(object):
             logging.getLogger('sickrage'),
             logging.getLogger('tornado.general'),
             logging.getLogger('tornado.application'),
-            #logging.getLogger('tornado.access'),
+            # logging.getLogger('tornado.access'),
         ]
 
         self.consoleLogging = False
@@ -119,13 +125,14 @@ class Logger(object):
 
         # pass exception information if debugging enabled
 
-        kwargs["exc_info"] = 1 if level == ERROR else 0
-        self.logger.log(level, message, *args, **kwargs)
-
         if level == ERROR:
+            self.logger.exception(message, *args, **kwargs)
             classes.ErrorViewer.add(classes.UIError(message))
-            #if sickbeard.GIT_AUTOISSUES:
+
+            # if sickbeard.GIT_AUTOISSUES:
             #    self.submit_errors()
+        else:
+            self.logger.log(level, message, *args, **kwargs)
 
     def log_error_and_exit(self, error_msg, *args, **kwargs):
         self.log(error_msg, ERROR, *args, **kwargs)
@@ -139,37 +146,33 @@ class Logger(object):
         if not (sickbeard.GIT_USERNAME and sickbeard.GIT_PASSWORD and len(classes.ErrorViewer.errors) > 0):
             return
 
-        title = "[APP SUBMITTED]: "
-
         gh_org = sickbeard.GIT_ORG or 'SiCKRAGETV'
         gh_repo = 'sickrage-issues'
 
-        self.gh_issues = Github(login_or_token=sickbeard.GIT_USERNAME, password=sickbeard.GIT_PASSWORD,
-                                user_agent="SiCKRAGE").get_organization(gh_org).get_repo(gh_repo)
+        gh_issues = Github(login_or_token=sickbeard.GIT_USERNAME, password=sickbeard.GIT_PASSWORD,
+                           user_agent="SiCKRAGE").get_organization(gh_org).get_repo(gh_repo)
 
         try:
+            # read log file
             if self.logFile and os.path.isfile(self.logFile):
                 with ek.ek(open, self.logFile) as f:
                     log_data = f.readlines()
-        except Exception as e:
-            pass
+                log_data = [line for line in reversed(log_data)]
 
-        try:
+            # parse and submit errors to issue tracker
             for curError in sorted(classes.ErrorViewer.errors, key=lambda error: error.time, reverse=True)[:500]:
                 if not curError.title:
                     continue
 
-                regex = "^(%s)\s*([A-Z]+)\s*(.+?)\s*\:\:\s*(.*)$" % curError.time
-
-                maxlines = 50
                 pastebin_url = None
-                for i, x in enumerate(reversed(log_data)):
+                regex = "^(%s)\s*([A-Z]+)\s*(.+?)\s*\:\:\s*(.*)$" % curError.time
+                for i, x in enumerate(log_data):
                     x = ek.ss(x)
                     match = re.match(regex, x)
                     if match:
                         level = match.group(2)
                         if reverseNames[level] == ERROR:
-                            paste_data = "".join(log_data[len(log_data) - i - 50:])
+                            paste_data = "".join(log_data[i:50])
                             pastebin_url = PastebinAPI().paste('f59b8e9fa1fc2d033e399e6c7fb09d19', paste_data)
                             break
 
@@ -187,14 +190,16 @@ class Logger(object):
                 message += u"---\n"
                 message += u"_STAFF NOTIFIED_: @SiCKRAGETV/owners @SiCKRAGETV/moderators"
 
-                issue = self.gh_issues.create_issue(title + curError.title, message)
+                issue = gh_issues.create_issue("[APP SUBMITTED]: " + curError.title, message)
                 if issue:
                     self.log('Your issue ticket #%s was submitted successfully!' % issue.number)
 
-                    if not sickbeard.GIT_AUTOISSUES:
-                        ui.notifications.message('Your issue ticket #%s was submitted successfully!' % issue.number)
-        finally:
-            classes.ErrorViewer.clear()
+                # clear error from error list
+                classes.ErrorViewer.errors.remove(curError)
+
+                return issue
+        except Exception as e:
+            self.log(sickbeard.exceptions.ex(e), ERROR)
 
 
 class Wrapper(object):
@@ -209,5 +214,6 @@ class Wrapper(object):
         except AttributeError:
             return getattr(self.instance, name)
 
+
 _globals = sys.modules[__name__] = Wrapper(sys.modules[__name__])
 
diff --git a/sickbeard/metadata/generic.py b/sickbeard/metadata/generic.py
index c623be2b5d46b0744c7e1fc6551e8f67e5421abf..0133df688e539b16d954ef6d7eaa45839103968e 100644
--- a/sickbeard/metadata/generic.py
+++ b/sickbeard/metadata/generic.py
@@ -26,7 +26,7 @@ import re
 
 import sickbeard
 
-from sickbeard import exceptions, helpers
+from sickbeard import helpers
 from sickbeard.metadata import helpers as metadata_helpers
 from sickbeard import logger
 from sickbeard import encodingKludge as ek
@@ -35,6 +35,8 @@ from sickbeard.show_name_helpers import allPossibleShowNames
 
 from lib.tmdb_api.tmdb_api import TMDB
 
+import fanart
+from fanart.core import Request as fanartRequest
 
 class GenericMetadata():
     """
@@ -616,6 +618,7 @@ class GenericMetadata():
                 continue
 
             result = result + [self._write_image(seasonData, season_poster_file_path)]
+
         if result:
             return all(result)
         else:
@@ -664,6 +667,7 @@ class GenericMetadata():
                 continue
 
             result = result + [self._write_image(seasonData, season_banner_file_path)]
+
         if result:
             return all(result)
         else:
@@ -774,19 +778,27 @@ class GenericMetadata():
         if image_type == 'poster_thumb':
             if getattr(indexer_show_obj, 'poster', None) is not None:
                 image_url = re.sub('posters', '_cache/posters', indexer_show_obj['poster'])
+            if not image_url:
+                # Try and get images from Fanart.TV
+                image_url = self._retrieve_show_images_from_fanart(show_obj, image_type)
+            if not image_url:
+                # Try and get images from TMDB
+                image_url = self._retrieve_show_images_from_tmdb(show_obj, image_type)
         elif image_type == 'banner_thumb':
             if getattr(indexer_show_obj, 'banner', None) is not None:
                 image_url = re.sub('graphical', '_cache/graphical', indexer_show_obj['banner'])
+            if not image_url:
+                # Try and get images from Fanart.TV
+                image_url = self._retrieve_show_images_from_fanart(show_obj, image_type)
         else:
             if getattr(indexer_show_obj, image_type, None) is not None:
                 image_url = indexer_show_obj[image_type]
-
-        # Try and get posters and fanart from TMDB
-        if image_url is None:
-            if image_type in ('poster', 'poster_thumb'):
-                image_url = self._retrieve_show_images_from_tmdb(show_obj, poster=True)
-            elif image_type == 'fanart':
-                image_url = self._retrieve_show_images_from_tmdb(show_obj, backdrop=True)
+            if not image_url:
+                # Try and get images from Fanart.TV
+                image_url = self._retrieve_show_images_from_fanart(show_obj, image_type)
+            if not image_url:
+                # Try and get images from TMDB
+                image_url = self._retrieve_show_images_from_tmdb(show_obj, image_type)
 
         if image_url:
             image_data = metadata_helpers.getShowImage(image_url, which)
@@ -961,7 +973,13 @@ class GenericMetadata():
 
         return (indexer_id, name, indexer)
 
-    def _retrieve_show_images_from_tmdb(self, show, backdrop=False, poster=False):
+    def _retrieve_show_images_from_tmdb(self, show, type):
+        types = {'poster': 'poster_path',
+                 'banner': None,
+                 'fanart': 'backdrop_path',
+                 'poster_thumb': 'poster_path',
+                 'banner_thumb': None}
+
         # get TMDB configuration info
         tmdb = TMDB(sickbeard.TMDB_API_KEY)
         config = tmdb.Configuration()
@@ -977,14 +995,41 @@ class GenericMetadata():
         try:
             search = tmdb.Search()
             for show_name in set(allPossibleShowNames(show)):
-                for result in search.collection({'query': show_name})['results'] + search.tv({'query': show_name})[
-                    'results']:
-                    if backdrop and result['backdrop_path']:
-                        return "{0}{1}{2}".format(base_url, max_size, result['backdrop_path'])
-                    elif poster and result['poster_path']:
-                        return "{0}{1}{2}".format(base_url, max_size, result['poster_path'])
+                for result in search.collection({'query': show_name})['results'] + search.tv({'query': show_name})['results']:
+                    if types[type] and getattr(result, types[type]):
+                        return "{0}{1}{2}".format(base_url, max_size, result[types[type]])
 
-        except Exception, e:
+        except Exception as e:
+            pass
+
+        logger.log(u"Could not find any " + type + " images on TMDB for " + show.name, logger.DEBUG)
+
+    def _retrieve_show_images_from_fanart(self, show, type, thumb=False):
+        types = {'poster': fanart.TYPE.TV.POSTER,
+                 'banner': fanart.TYPE.TV.BANNER,
+                 'poster_thumb': fanart.TYPE.TV.POSTER,
+                 'banner_thumb': fanart.TYPE.TV.BANNER,
+                 'fanart': fanart.TYPE.TV.BACKGROUND,
+        }
+
+        try:
+            indexerid = helpers.mapIndexersToShow(show)[1]
+            if indexerid:
+                request = fanartRequest(
+                    apikey=sickbeard.FANART_API_KEY,
+                    id=indexerid,
+                    ws=fanart.WS.TV,
+                    type=types[type],
+                    sort=fanart.SORT.POPULAR,
+                    limit=fanart.LIMIT.ONE,
+                )
+
+                resp = request.response()
+                url = resp[types[type]][0]['url']
+                if thumb:
+                    url = re.sub('/fanart/', '/preview/', url)
+                return url
+        except Exception as e:
             pass
 
-        logger.log(u"Could not find any posters or background for " + show.name, logger.DEBUG)
+        logger.log(u"Could not find any " + type + " images on Fanart.tv for " + show.name, logger.DEBUG)
\ No newline at end of file
diff --git a/sickbeard/providers/generic.py b/sickbeard/providers/generic.py
index a320c8d055203c993dd80b98520b0941d4303373..9767498248af156a6d4d6888f3c6be102e0af2a5 100644
--- a/sickbeard/providers/generic.py
+++ b/sickbeard/providers/generic.py
@@ -24,6 +24,7 @@ import os
 import re
 import itertools
 import urllib
+
 import sickbeard
 import requests
 
@@ -124,7 +125,9 @@ class GenericProvider:
         if not self._doLogin():
             return
 
-        self.headers.update({'Referer': self.proxy.getProxyURL()})
+        if self.proxy.isEnabled():
+            self.headers.update({'Referer': self.proxy.getProxyURL()})
+
         return helpers.getURL(self.proxy._buildURL(url), post_data=post_data, params=params, headers=self.headers, timeout=timeout,
                               session=self.session, json=json)
 
diff --git a/sickbeard/providers/newznab.py b/sickbeard/providers/newznab.py
index d0199584fd8df15de87b3ce65b1d2b004a5bcf02..a9fc6f2aa0ce4b1dc8489057cd516b0715748f3a 100755
--- a/sickbeard/providers/newznab.py
+++ b/sickbeard/providers/newznab.py
@@ -38,10 +38,6 @@ from sickbeard import logger
 from sickbeard import tvcache
 from sickbeard.exceptions import ex, AuthException
 
-from lib import requests
-from lib.requests import exceptions
-from lib.bencode import bdecode
-
 class NewznabProvider(generic.NZBProvider):
     def __init__(self, name, url, key='', catIDs='5030,5040', search_mode='eponly', search_fallback=False,
                  enable_daily=False, enable_backlog=False):
@@ -118,8 +114,6 @@ class NewznabProvider(generic.NZBProvider):
             return (False, return_categories, "Error getting html for [%s]" % 
                     ("%s/api?%s" % (self.url, '&'.join("%s=%s" % (x,y) for x,y in params.items()) )))
         
-        #xml_categories = helpers.parse_xml(categories)
-        
         if not xml_categories:
             logger.log(u"Error parsing xml for [%s]" % (self.name),
                        logger.DEBUG)
diff --git a/sickbeard/show_queue.py b/sickbeard/show_queue.py
index 1969fa53770d7631cf04fa1380488226a6ec34e1..3b36c9ae7b76d80e6123313b22589ddf94dd23af 100644
--- a/sickbeard/show_queue.py
+++ b/sickbeard/show_queue.py
@@ -320,7 +320,7 @@ class QueueItemAdd(ShowQueueItem):
             return
 
         except exceptions.MultipleShowObjectsException:
-            logger.log(u"The show in " + self.showDir + " is already in your show list, skipping", logger.ERROR)
+            logger.log(u"The show in " + self.showDir + " is already in your show list, skipping", logger.WARNING)
             ui.notifications.error('Show skipped', "The show in " + self.showDir + " is already in your show list")
             self._finishEarly()
             return
@@ -335,7 +335,6 @@ class QueueItemAdd(ShowQueueItem):
         try:
             self.show.loadIMDbInfo()
         except imdb_exceptions.IMDbError, e:
-            #todo Insert UI notification
             logger.log(u" Something wrong on IMDb api: " + ex(e), logger.WARNING)
         except Exception, e:
             logger.log(u"Error loading IMDb info: " + ex(e), logger.ERROR)
diff --git a/sickbeard/tv.py b/sickbeard/tv.py
index bc9e44655a49ab89323c561c52116c42904271b2..df39d1af1e7a6bd095f2622fd144590b70dc6dee 100644
--- a/sickbeard/tv.py
+++ b/sickbeard/tv.py
@@ -1686,8 +1686,8 @@ class TVEpisode(object):
         except (ValueError, IndexError):
             logger.log(u"Malformed air date of " + str(firstaired) + " retrieved from " + sickbeard.indexerApi(
                 self.indexer).name + " for (" + self.show.name + " - " + str(season) + "x" + str(episode) + ")",
-                       logger.ERROR)
-            # if I'm incomplete on TVDB but I once was complete then just delete myself from the DB for now
+                       logger.WARNING)
+            # if I'm incomplete on the indexer but I once was complete then just delete myself from the DB for now
             if self.indexerid != -1:
                 self.deleteEpisode()
             return False
diff --git a/sickbeard/tvcache.py b/sickbeard/tvcache.py
index 283018cd808cb66346f5d2283d4c13ef2d52a777..bd705ec891b173b96eae719824e95218b06e6d42 100644
--- a/sickbeard/tvcache.py
+++ b/sickbeard/tvcache.py
@@ -139,7 +139,8 @@ class TVCache():
             logger.log(traceback.format_exc(), logger.DEBUG)
 
     def getRSSFeed(self, url, post_data=None, items=[]):
-        self.provider.headers.update({'Referer': self.provider.proxy.getProxyURL()})
+        if self.provider.proxy.isEnabled():
+            self.provider.headers.update({'Referer': self.provider.proxy.getProxyURL()})
         return RSSFeeds(self.providerID).getFeed(self.provider.proxy._buildURL(url), post_data, self.provider.headers, items)
 
     def _translateTitle(self, title):
diff --git a/sickbeard/versionChecker.py b/sickbeard/versionChecker.py
index 2e017cc35dd26b0e6b3f9e8169b3c0681185df77..bd15cb2938f64a54a0b90ed76bd59ec249d45275 100644
--- a/sickbeard/versionChecker.py
+++ b/sickbeard/versionChecker.py
@@ -395,6 +395,11 @@ class GitUpdateManager(UpdateManager):
         # update remote origin url
         self.update_remote_origin()
 
+        # remove untracked files and performs a hard reset on git branch to avoid update issues
+        if sickbeard.GIT_RESET:
+            self.clean()
+            self.reset()
+
         if self.branch == self._find_installed_branch():
             output, err, exit_status = self._run_git(self._git_path, 'pull -f %s %s' % (sickbeard.GIT_REMOTE, self.branch))  # @UnusedVariable
         else:
@@ -406,26 +411,26 @@ class GitUpdateManager(UpdateManager):
             # Notify update successful
             if sickbeard.NOTIFY_ON_UPDATE:
                 notifiers.notify_git_update(sickbeard.CUR_COMMIT_HASH if sickbeard.CUR_COMMIT_HASH else "")
+
             return True
-        else:
-            # perform a hard reset to try and resolve the issue
-            if self.reset() and self.update():
-                return True
 
-        return False
+    def clean(self):
+        """
+        Calls git clean to remove all untracked files. Returns a bool depending
+        on the call's success.
+        """
+        output, err, exit_status = self._run_git(self._git_path, 'clean -d -fx ""')  # @UnusedVariable
+        if exit_status == 0:
+            return True
 
     def reset(self):
         """
         Calls git reset --hard to perform a hard reset. Returns a bool depending
         on the call's success.
         """
-        if sickbeard.GIT_RESET:
-            output, err, exit_status = self._run_git(self._git_path, 'reset --hard')  # @UnusedVariable
-
-            if exit_status == 0:
-                return True
-
-        return False
+        output, err, exit_status = self._run_git(self._git_path, 'reset --hard')  # @UnusedVariable
+        if exit_status == 0:
+            return True
 
     def list_remote_branches(self):
         # update remote origin url
diff --git a/sickbeard/webapi.py b/sickbeard/webapi.py
index 6508874805b3394bd5d19a4d3bafbdad6cf58caf..f527192c4f44b8ac385f68baaa43088e148a6e82 100644
--- a/sickbeard/webapi.py
+++ b/sickbeard/webapi.py
@@ -94,13 +94,8 @@ class ApiHandler(RequestHandler):
                               'image': lambda x: x['image'],
         }
 
-        if sickbeard.USE_API is not True:
-            accessMsg = u"API :: " + self.request.remote_ip + " - SB API Disabled. ACCESS DENIED"
-            logger.log(accessMsg, logger.WARNING)
-            return self.finish(outputCallbackDict['default'](_responds(RESULT_DENIED, msg=accessMsg)))
-        else:
-            accessMsg = u"API :: " + self.request.remote_ip + " - gave correct API KEY. ACCESS GRANTED"
-            logger.log(accessMsg, logger.DEBUG)
+        accessMsg = u"API :: " + self.request.remote_ip + " - gave correct API KEY. ACCESS GRANTED"
+        logger.log(accessMsg, logger.DEBUG)
 
         # set the original call_dispatcher as the local _call_dispatcher
         _call_dispatcher = self.call_dispatcher
diff --git a/sickbeard/webserve.py b/sickbeard/webserve.py
index eae29d1a93ba131ab78c484f2ee39abbfba22475..996e3086343ef4203bcbd3fe4b16be9dad08e09e 100644
--- a/sickbeard/webserve.py
+++ b/sickbeard/webserve.py
@@ -3425,7 +3425,7 @@ class ConfigGeneral(Config):
     def saveGeneral(self, log_dir=None, web_port=None, web_log=None, encryption_version=None, web_ipv6=None,
                     update_shows_on_start=None, trash_remove_show=None, trash_rotate_logs=None, update_frequency=None,
                     launch_browser=None, web_username=None,
-                    use_api=None, api_key=None, indexer_default=None, timezone_display=None, cpu_preset=None,
+                    api_key=None, indexer_default=None, timezone_display=None, cpu_preset=None,
                     web_password=None, version_notify=None, enable_https=None, https_cert=None, https_key=None,
                     handle_reverse_proxy=None, sort_article=None, auto_update=None, notify_on_update=None,
                     proxy_setting=None, proxy_indexers=None, anon_redirect=None, git_path=None, git_remote=None,
@@ -3492,7 +3492,6 @@ class ConfigGeneral(Config):
         if not config.change_LOG_DIR(log_dir, web_log):
             results += ["Unable to create directory " + os.path.normpath(log_dir) + ", log directory not changed."]
 
-        sickbeard.USE_API = config.checkbox_to_value(use_api)
         sickbeard.API_KEY = api_key
 
         sickbeard.ENABLE_HTTPS = config.checkbox_to_value(enable_https)
@@ -4713,6 +4712,8 @@ class ErrorLogs(WebRoot):
         if not (sickbeard.GIT_USERNAME and sickbeard.GIT_PASSWORD):
             logger.log(u'Please set your GitHub username and password in the config, unable to submit issue ticket to GitHub!')
         else:
-            logger.submit_errors()
+            issue = logger.submit_errors()
+            if issue:
+                ui.notifications.message('Your issue ticket #%s was submitted successfully!' % issue.number)
 
         return self.redirect("/errorlogs/")
\ No newline at end of file
diff --git a/tests/issue_submitter_tests.py b/tests/issue_submitter_tests.py
new file mode 100644
index 0000000000000000000000000000000000000000..bb3e29dad5c217e0b1149759c885a2dd6444658e
--- /dev/null
+++ b/tests/issue_submitter_tests.py
@@ -0,0 +1,49 @@
+# coding=UTF-8
+# Author: Dennis Lutter <lad1337@gmail.com>
+# URL: http://code.google.com/p/sickbeard/
+#
+# This file is part of SickRage.
+#
+# SickRage is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# SickRage is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with SickRage.  If not, see <http://www.gnu.org/licenses/>.
+
+from __future__ import with_statement
+
+import unittest
+import sys, os.path
+from configobj import ConfigObj
+
+sys.path.append(os.path.abspath('..'))
+sys.path.append(os.path.abspath('../lib'))
+
+import sickbeard
+import test_lib as test
+
+def error():
+    try:
+        raise Exception('FAKE EXCEPTION')
+    except Exception as e:
+        sickbeard.logger.log("FAKE ERROR: " + sickbeard.exceptions.ex(e), sickbeard.logger.ERROR)
+        sickbeard.logger.submit_errors()
+        raise
+
+class IssueSubmitterBasicTests(unittest.TestCase):
+    def test_submitter(self):
+        self.assertRaises(Exception, error)
+
+if __name__ == "__main__":
+    print "=================="
+    print "STARTING - ISSUE SUBMITTER TESTS"
+    print "=================="
+    print "######################################################################"
+    suite = unittest.TestLoader().loadTestsFromTestCase(IssueSubmitterBasicTests)
\ No newline at end of file
diff --git a/tests/test_lib.py b/tests/test_lib.py
index f87d4dc368c17363483f4a158f69ff6e0342ecfe..7f152882d1ab7f4c655124a9764ea849ae43f1c2 100644
--- a/tests/test_lib.py
+++ b/tests/test_lib.py
@@ -25,6 +25,7 @@ import sqlite3
 
 import sys
 import os.path
+from configobj import ConfigObj
 
 sys.path.append(os.path.abspath('..'))
 sys.path.append(os.path.abspath('../lib'))
@@ -54,9 +55,6 @@ FILEDIR = os.path.join(TESTDIR, SHOWNAME)
 FILEPATH = os.path.join(FILEDIR, FILENAME)
 SHOWDIR = os.path.join(TESTDIR, SHOWNAME + " final")
 
-sickbeard.logger.logFile = os.path.join(os.path.join(TESTDIR, 'Logs'), 'test_sickbeard.log')
-sickbeard.logger.initLogging()
-
 #=================
 # prepare env functions
 #=================
@@ -74,6 +72,7 @@ def createTestCacheFolder():
 # sickbeard globals
 #=================
 sickbeard.SYS_ENCODING = 'UTF-8'
+
 sickbeard.showList = []
 sickbeard.QUALITY_DEFAULT = 4  # hdtv
 sickbeard.FLATTEN_FOLDERS_DEFAULT = 0
@@ -90,13 +89,23 @@ sickbeard.providerList = providers.makeProviderList()
 
 sickbeard.PROG_DIR = os.path.abspath('..')
 sickbeard.DATA_DIR = sickbeard.PROG_DIR
+sickbeard.CONFIG_FILE = os.path.join(sickbeard.DATA_DIR, "config.ini")
+sickbeard.CFG = ConfigObj(sickbeard.CONFIG_FILE)
+
+sickbeard.BRANCG = sickbeard.config.check_setting_str(sickbeard.CFG, 'General', 'branch', '')
+sickbeard.CUR_COMMIT_HASH = sickbeard.config.check_setting_str(sickbeard.CFG, 'General', 'cur_commit_hash', '')
+sickbeard.GIT_USERNAME = sickbeard.config.check_setting_str(sickbeard.CFG, 'General', 'git_username', '')
+sickbeard.GIT_PASSWORD = sickbeard.config.check_setting_str(sickbeard.CFG, 'General', 'git_password', '', censor_log=True)
+
 sickbeard.LOG_DIR = os.path.join(TESTDIR, 'Logs')
+sickbeard.logger.logFile = os.path.join(sickbeard.LOG_DIR, 'test_sickbeard.log')
 createTestLogFolder()
-sickbeard.logger.initLogging(False)
 
 sickbeard.CACHE_DIR = os.path.join(TESTDIR, 'cache')
 createTestCacheFolder()
 
+sickbeard.logger.initLogging(False, True)
+
 #=================
 # dummy functions
 #=================
diff --git a/tests/torrent_tests.py b/tests/torrent_tests.py
index b076cb44572d9ed92c3c28bde357c5226906d2a4..f6c84afa5824fbbb0fe0af9e8dd559fc8a85b533 100644
--- a/tests/torrent_tests.py
+++ b/tests/torrent_tests.py
@@ -21,11 +21,11 @@ from __future__ import with_statement
 
 import unittest
 import sys, os.path
-import urlparse
 
 sys.path.append(os.path.abspath('..'))
 sys.path.append(os.path.abspath('../lib'))
 
+import urlparse
 import test_lib as test
 from bs4 import BeautifulSoup
 from sickbeard.helpers import getURL