muck-services 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (818) hide show
  1. data/.document +5 -0
  2. data/.gitignore +5 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +100 -0
  5. data/Rakefile +84 -0
  6. data/VERSION +1 -0
  7. data/app/controllers/admin/muck/feeds_controller.rb +40 -0
  8. data/app/controllers/admin/muck/oai_endpoints_controller.rb +13 -0
  9. data/app/controllers/muck/aggregation_feeds_controller.rb +43 -0
  10. data/app/controllers/muck/aggregations_controller.rb +234 -0
  11. data/app/controllers/muck/entries_controller.rb +102 -0
  12. data/app/controllers/muck/feed_previews_controller.rb +33 -0
  13. data/app/controllers/muck/feeds_controller.rb +157 -0
  14. data/app/controllers/muck/identity_feeds_controller.rb +155 -0
  15. data/app/controllers/muck/oai_endpoints_controller.rb +96 -0
  16. data/app/controllers/muck/recommendations_controller.rb +62 -0
  17. data/app/controllers/muck/topics_controller.rb +162 -0
  18. data/app/controllers/muck/visits_controller.rb +26 -0
  19. data/app/helpers/muck_services_aggregations_helper.rb +32 -0
  20. data/app/helpers/muck_services_feeds_helper.rb +32 -0
  21. data/app/helpers/muck_services_helper.rb +95 -0
  22. data/app/helpers/muck_services_service_helper.rb +117 -0
  23. data/app/models/aggregation.rb +92 -0
  24. data/app/models/aggregation_feed.rb +14 -0
  25. data/app/models/attention.rb +14 -0
  26. data/app/models/click.rb +14 -0
  27. data/app/models/entry.rb +341 -0
  28. data/app/models/feed.rb +224 -0
  29. data/app/models/feed_parent.rb +18 -0
  30. data/app/models/identity_feed.rb +26 -0
  31. data/app/models/oai_endpoint.rb +39 -0
  32. data/app/models/recommendation.rb +15 -0
  33. data/app/models/service.rb +486 -0
  34. data/app/models/service_category.rb +15 -0
  35. data/app/models/services_mailer.rb +25 -0
  36. data/app/models/subject.rb +10 -0
  37. data/app/models/tag_cloud.rb +21 -0
  38. data/app/views/activity_templates/_entry_comment.html.erb +8 -0
  39. data/app/views/activity_templates/_entry_share.html.erb +8 -0
  40. data/app/views/admin/feeds/index.html.erb +35 -0
  41. data/app/views/admin/oai_endpoints/index.html.erb +31 -0
  42. data/app/views/aggregations/_aggregation.html.erb +1 -0
  43. data/app/views/aggregations/_data_source.html.erb +4 -0
  44. data/app/views/aggregations/_data_sources.html.erb +10 -0
  45. data/app/views/aggregations/_feeds.html.erb +1 -0
  46. data/app/views/aggregations/_preview_form.html.erb +12 -0
  47. data/app/views/aggregations/edit.html.erb +65 -0
  48. data/app/views/aggregations/index.html.erb +17 -0
  49. data/app/views/aggregations/index.iphone.erb +0 -0
  50. data/app/views/aggregations/new.html.erb +12 -0
  51. data/app/views/aggregations/preview.html.erb +46 -0
  52. data/app/views/aggregations/preview.iphone.erb +0 -0
  53. data/app/views/aggregations/rss_discovery.html.erb +3 -0
  54. data/app/views/aggregations/show.html.erb +0 -0
  55. data/app/views/default/_language_list.html.erb +5 -0
  56. data/app/views/entries/_related_entry.html.erb +4 -0
  57. data/app/views/entries/_result.html.erb +7 -0
  58. data/app/views/entries/_result_status.html.erb +16 -0
  59. data/app/views/entries/_results.html.erb +3 -0
  60. data/app/views/entries/_tag_cloud.html.erb +18 -0
  61. data/app/views/entries/browse_by_tags.html.erb +16 -0
  62. data/app/views/entries/collections.html.erb +28 -0
  63. data/app/views/entries/details.html.erb +25 -0
  64. data/app/views/entries/index.html.erb +3 -0
  65. data/app/views/entries/search.html.erb +10 -0
  66. data/app/views/entries/show.html.erb +7 -0
  67. data/app/views/entries/track_clicks.html.erb +0 -0
  68. data/app/views/feed_previews/new.html.erb +1 -0
  69. data/app/views/feed_previews/select_feeds.html.erb +6 -0
  70. data/app/views/feeds/_entry.html.erb +1 -0
  71. data/app/views/feeds/_feed.html.erb +28 -0
  72. data/app/views/feeds/_feed_row.html.erb +29 -0
  73. data/app/views/feeds/_feed_selection.html.erb +1 -0
  74. data/app/views/feeds/_form.html.erb +20 -0
  75. data/app/views/feeds/edit.html.erb +107 -0
  76. data/app/views/feeds/harvest_now.html.erb +3 -0
  77. data/app/views/feeds/index.html.erb +34 -0
  78. data/app/views/feeds/new.html.erb +21 -0
  79. data/app/views/feeds/new_extended.html.erb +32 -0
  80. data/app/views/feeds/new_oai_rss.html.erb +50 -0
  81. data/app/views/feeds/show.html.erb +1 -0
  82. data/app/views/feeds/unban.html.erb +3 -0
  83. data/app/views/identity_feeds/_available_service_categories.html.erb +13 -0
  84. data/app/views/identity_feeds/_form.html.erb +20 -0
  85. data/app/views/identity_feeds/_services_for_user.html.erb +25 -0
  86. data/app/views/identity_feeds/edit.html.erb +2 -0
  87. data/app/views/identity_feeds/index.html.erb +32 -0
  88. data/app/views/identity_feeds/new.html.erb +1 -0
  89. data/app/views/oai_endpoints/_form.html.erb +22 -0
  90. data/app/views/oai_endpoints/_oai_endpoint_row.html.erb +25 -0
  91. data/app/views/oai_endpoints/new.html.erb +2 -0
  92. data/app/views/oai_endpoints/show.html.erb +5 -0
  93. data/app/views/parts/_add_feed.html.erb +20 -0
  94. data/app/views/parts/_select_feed.html.erb +4 -0
  95. data/app/views/recommendations/index.html.erb +5 -0
  96. data/app/views/recommendations/index.pjs.erb +44 -0
  97. data/app/views/recommendations/index.rss.builder +37 -0
  98. data/app/views/recommendations/index.xml.builder +36 -0
  99. data/app/views/recommendations/index_js.pjs.erb +39 -0
  100. data/app/views/recommendations/index_real_time.pjs.erb +44 -0
  101. data/app/views/recommendations/index_real_time.xml.builder +25 -0
  102. data/app/views/search/_languages.html.erb +6 -0
  103. data/app/views/search/_result.html.erb +9 -0
  104. data/app/views/search/_search_box.html.erb +9 -0
  105. data/app/views/search/index.html.erb +5 -0
  106. data/app/views/search/results.atom.builder +27 -0
  107. data/app/views/search/results.html.erb +35 -0
  108. data/app/views/search/results.pjs.erb +13 -0
  109. data/app/views/search/results.rdf.builder +24 -0
  110. data/app/views/search/results.rss.builder +31 -0
  111. data/app/views/search/results.xml.builder +19 -0
  112. data/app/views/service_templates/_facebook.html.erb +4 -0
  113. data/app/views/service_templates/_friendfeed.html.erb +2 -0
  114. data/app/views/service_templates/_goodreads.html.erb +2 -0
  115. data/app/views/service_templates/_linkedin.html.erb +2 -0
  116. data/app/views/service_templates/_netflix.html.erb +2 -0
  117. data/app/views/service_templates/_polyvore.html.erb +2 -0
  118. data/app/views/service_templates/_zotero_group.html.erb +2 -0
  119. data/app/views/services/_edit_service.html.erb +1 -0
  120. data/app/views/services/_new_service.html.erb +1 -0
  121. data/app/views/services/_summary.html.erb +5 -0
  122. data/app/views/services/_view_service.html.erb +1 -0
  123. data/app/views/services_mailer/notification_feed_added.text.ar.html.erb +4 -0
  124. data/app/views/services_mailer/notification_feed_added.text.ar.plain.erb +7 -0
  125. data/app/views/services_mailer/notification_feed_added.text.bg.html.erb +4 -0
  126. data/app/views/services_mailer/notification_feed_added.text.bg.plain.erb +7 -0
  127. data/app/views/services_mailer/notification_feed_added.text.ca.html.erb +4 -0
  128. data/app/views/services_mailer/notification_feed_added.text.ca.plain.erb +7 -0
  129. data/app/views/services_mailer/notification_feed_added.text.cs.html.erb +4 -0
  130. data/app/views/services_mailer/notification_feed_added.text.cs.plain.erb +7 -0
  131. data/app/views/services_mailer/notification_feed_added.text.da.html.erb +4 -0
  132. data/app/views/services_mailer/notification_feed_added.text.da.plain.erb +7 -0
  133. data/app/views/services_mailer/notification_feed_added.text.de.html.erb +4 -0
  134. data/app/views/services_mailer/notification_feed_added.text.de.plain.erb +7 -0
  135. data/app/views/services_mailer/notification_feed_added.text.el.html.erb +4 -0
  136. data/app/views/services_mailer/notification_feed_added.text.el.plain.erb +7 -0
  137. data/app/views/services_mailer/notification_feed_added.text.es.html.erb +4 -0
  138. data/app/views/services_mailer/notification_feed_added.text.es.plain.erb +7 -0
  139. data/app/views/services_mailer/notification_feed_added.text.et.html.erb +4 -0
  140. data/app/views/services_mailer/notification_feed_added.text.et.plain.erb +7 -0
  141. data/app/views/services_mailer/notification_feed_added.text.fa.html.erb +4 -0
  142. data/app/views/services_mailer/notification_feed_added.text.fa.plain.erb +7 -0
  143. data/app/views/services_mailer/notification_feed_added.text.fi.html.erb +4 -0
  144. data/app/views/services_mailer/notification_feed_added.text.fi.plain.erb +7 -0
  145. data/app/views/services_mailer/notification_feed_added.text.fr.html.erb +4 -0
  146. data/app/views/services_mailer/notification_feed_added.text.fr.plain.erb +7 -0
  147. data/app/views/services_mailer/notification_feed_added.text.gl.html.erb +4 -0
  148. data/app/views/services_mailer/notification_feed_added.text.gl.plain.erb +7 -0
  149. data/app/views/services_mailer/notification_feed_added.text.hi.html.erb +4 -0
  150. data/app/views/services_mailer/notification_feed_added.text.hi.plain.erb +7 -0
  151. data/app/views/services_mailer/notification_feed_added.text.hr.html.erb +4 -0
  152. data/app/views/services_mailer/notification_feed_added.text.hr.plain.erb +7 -0
  153. data/app/views/services_mailer/notification_feed_added.text.html.erb +4 -0
  154. data/app/views/services_mailer/notification_feed_added.text.hu.html.erb +4 -0
  155. data/app/views/services_mailer/notification_feed_added.text.hu.plain.erb +7 -0
  156. data/app/views/services_mailer/notification_feed_added.text.id.html.erb +4 -0
  157. data/app/views/services_mailer/notification_feed_added.text.id.plain.erb +7 -0
  158. data/app/views/services_mailer/notification_feed_added.text.it.html.erb +4 -0
  159. data/app/views/services_mailer/notification_feed_added.text.it.plain.erb +7 -0
  160. data/app/views/services_mailer/notification_feed_added.text.iw.html.erb +4 -0
  161. data/app/views/services_mailer/notification_feed_added.text.iw.plain.erb +7 -0
  162. data/app/views/services_mailer/notification_feed_added.text.ja.html.erb +4 -0
  163. data/app/views/services_mailer/notification_feed_added.text.ja.plain.erb +7 -0
  164. data/app/views/services_mailer/notification_feed_added.text.ko.html.erb +4 -0
  165. data/app/views/services_mailer/notification_feed_added.text.ko.plain.erb +7 -0
  166. data/app/views/services_mailer/notification_feed_added.text.lt.html.erb +4 -0
  167. data/app/views/services_mailer/notification_feed_added.text.lt.plain.erb +7 -0
  168. data/app/views/services_mailer/notification_feed_added.text.lv.html.erb +4 -0
  169. data/app/views/services_mailer/notification_feed_added.text.lv.plain.erb +7 -0
  170. data/app/views/services_mailer/notification_feed_added.text.mt.html.erb +4 -0
  171. data/app/views/services_mailer/notification_feed_added.text.mt.plain.erb +7 -0
  172. data/app/views/services_mailer/notification_feed_added.text.nl.html.erb +4 -0
  173. data/app/views/services_mailer/notification_feed_added.text.nl.plain.erb +7 -0
  174. data/app/views/services_mailer/notification_feed_added.text.no.html.erb +4 -0
  175. data/app/views/services_mailer/notification_feed_added.text.no.plain.erb +7 -0
  176. data/app/views/services_mailer/notification_feed_added.text.pl.html.erb +4 -0
  177. data/app/views/services_mailer/notification_feed_added.text.pl.plain.erb +7 -0
  178. data/app/views/services_mailer/notification_feed_added.text.plain.erb +7 -0
  179. data/app/views/services_mailer/notification_feed_added.text.pt-PT.html.erb +4 -0
  180. data/app/views/services_mailer/notification_feed_added.text.pt-PT.plain.erb +7 -0
  181. data/app/views/services_mailer/notification_feed_added.text.ro.html.erb +4 -0
  182. data/app/views/services_mailer/notification_feed_added.text.ro.plain.erb +7 -0
  183. data/app/views/services_mailer/notification_feed_added.text.ru.html.erb +4 -0
  184. data/app/views/services_mailer/notification_feed_added.text.ru.plain.erb +7 -0
  185. data/app/views/services_mailer/notification_feed_added.text.sk.html.erb +4 -0
  186. data/app/views/services_mailer/notification_feed_added.text.sk.plain.erb +7 -0
  187. data/app/views/services_mailer/notification_feed_added.text.sl.html.erb +4 -0
  188. data/app/views/services_mailer/notification_feed_added.text.sl.plain.erb +7 -0
  189. data/app/views/services_mailer/notification_feed_added.text.sq.html.erb +4 -0
  190. data/app/views/services_mailer/notification_feed_added.text.sq.plain.erb +7 -0
  191. data/app/views/services_mailer/notification_feed_added.text.sr.html.erb +4 -0
  192. data/app/views/services_mailer/notification_feed_added.text.sr.plain.erb +7 -0
  193. data/app/views/services_mailer/notification_feed_added.text.sv.html.erb +4 -0
  194. data/app/views/services_mailer/notification_feed_added.text.sv.plain.erb +7 -0
  195. data/app/views/services_mailer/notification_feed_added.text.th.html.erb +4 -0
  196. data/app/views/services_mailer/notification_feed_added.text.th.plain.erb +7 -0
  197. data/app/views/services_mailer/notification_feed_added.text.tl.html.erb +4 -0
  198. data/app/views/services_mailer/notification_feed_added.text.tl.plain.erb +7 -0
  199. data/app/views/services_mailer/notification_feed_added.text.tr.html.erb +4 -0
  200. data/app/views/services_mailer/notification_feed_added.text.tr.plain.erb +7 -0
  201. data/app/views/services_mailer/notification_feed_added.text.uk.html.erb +4 -0
  202. data/app/views/services_mailer/notification_feed_added.text.uk.plain.erb +7 -0
  203. data/app/views/services_mailer/notification_feed_added.text.vi.html.erb +4 -0
  204. data/app/views/services_mailer/notification_feed_added.text.vi.plain.erb +7 -0
  205. data/app/views/services_mailer/notification_feed_added.text.zh-CN.html.erb +4 -0
  206. data/app/views/services_mailer/notification_feed_added.text.zh-CN.plain.erb +7 -0
  207. data/app/views/services_mailer/notification_feed_added.text.zh-TW.html.erb +4 -0
  208. data/app/views/services_mailer/notification_feed_added.text.zh-TW.plain.erb +7 -0
  209. data/app/views/services_mailer/notification_feed_added.text.zh.html.erb +4 -0
  210. data/app/views/services_mailer/notification_feed_added.text.zh.plain.erb +7 -0
  211. data/app/views/services_mailer/notification_oai_endpoint_added.text.ar.html.erb +4 -0
  212. data/app/views/services_mailer/notification_oai_endpoint_added.text.ar.plain.erb +4 -0
  213. data/app/views/services_mailer/notification_oai_endpoint_added.text.bg.html.erb +4 -0
  214. data/app/views/services_mailer/notification_oai_endpoint_added.text.bg.plain.erb +4 -0
  215. data/app/views/services_mailer/notification_oai_endpoint_added.text.ca.html.erb +4 -0
  216. data/app/views/services_mailer/notification_oai_endpoint_added.text.ca.plain.erb +4 -0
  217. data/app/views/services_mailer/notification_oai_endpoint_added.text.cs.html.erb +4 -0
  218. data/app/views/services_mailer/notification_oai_endpoint_added.text.cs.plain.erb +4 -0
  219. data/app/views/services_mailer/notification_oai_endpoint_added.text.da.html.erb +4 -0
  220. data/app/views/services_mailer/notification_oai_endpoint_added.text.da.plain.erb +4 -0
  221. data/app/views/services_mailer/notification_oai_endpoint_added.text.de.html.erb +4 -0
  222. data/app/views/services_mailer/notification_oai_endpoint_added.text.de.plain.erb +4 -0
  223. data/app/views/services_mailer/notification_oai_endpoint_added.text.el.html.erb +4 -0
  224. data/app/views/services_mailer/notification_oai_endpoint_added.text.el.plain.erb +4 -0
  225. data/app/views/services_mailer/notification_oai_endpoint_added.text.es.html.erb +4 -0
  226. data/app/views/services_mailer/notification_oai_endpoint_added.text.es.plain.erb +4 -0
  227. data/app/views/services_mailer/notification_oai_endpoint_added.text.et.html.erb +4 -0
  228. data/app/views/services_mailer/notification_oai_endpoint_added.text.et.plain.erb +4 -0
  229. data/app/views/services_mailer/notification_oai_endpoint_added.text.fa.html.erb +4 -0
  230. data/app/views/services_mailer/notification_oai_endpoint_added.text.fa.plain.erb +4 -0
  231. data/app/views/services_mailer/notification_oai_endpoint_added.text.fi.html.erb +4 -0
  232. data/app/views/services_mailer/notification_oai_endpoint_added.text.fi.plain.erb +4 -0
  233. data/app/views/services_mailer/notification_oai_endpoint_added.text.fr.html.erb +4 -0
  234. data/app/views/services_mailer/notification_oai_endpoint_added.text.fr.plain.erb +4 -0
  235. data/app/views/services_mailer/notification_oai_endpoint_added.text.gl.html.erb +4 -0
  236. data/app/views/services_mailer/notification_oai_endpoint_added.text.gl.plain.erb +4 -0
  237. data/app/views/services_mailer/notification_oai_endpoint_added.text.hi.html.erb +4 -0
  238. data/app/views/services_mailer/notification_oai_endpoint_added.text.hi.plain.erb +4 -0
  239. data/app/views/services_mailer/notification_oai_endpoint_added.text.hr.html.erb +4 -0
  240. data/app/views/services_mailer/notification_oai_endpoint_added.text.hr.plain.erb +4 -0
  241. data/app/views/services_mailer/notification_oai_endpoint_added.text.html.erb +4 -0
  242. data/app/views/services_mailer/notification_oai_endpoint_added.text.hu.html.erb +4 -0
  243. data/app/views/services_mailer/notification_oai_endpoint_added.text.hu.plain.erb +4 -0
  244. data/app/views/services_mailer/notification_oai_endpoint_added.text.id.html.erb +4 -0
  245. data/app/views/services_mailer/notification_oai_endpoint_added.text.id.plain.erb +4 -0
  246. data/app/views/services_mailer/notification_oai_endpoint_added.text.it.html.erb +4 -0
  247. data/app/views/services_mailer/notification_oai_endpoint_added.text.it.plain.erb +4 -0
  248. data/app/views/services_mailer/notification_oai_endpoint_added.text.iw.html.erb +4 -0
  249. data/app/views/services_mailer/notification_oai_endpoint_added.text.iw.plain.erb +4 -0
  250. data/app/views/services_mailer/notification_oai_endpoint_added.text.ja.html.erb +4 -0
  251. data/app/views/services_mailer/notification_oai_endpoint_added.text.ja.plain.erb +4 -0
  252. data/app/views/services_mailer/notification_oai_endpoint_added.text.ko.html.erb +4 -0
  253. data/app/views/services_mailer/notification_oai_endpoint_added.text.ko.plain.erb +4 -0
  254. data/app/views/services_mailer/notification_oai_endpoint_added.text.lt.html.erb +4 -0
  255. data/app/views/services_mailer/notification_oai_endpoint_added.text.lt.plain.erb +4 -0
  256. data/app/views/services_mailer/notification_oai_endpoint_added.text.lv.html.erb +4 -0
  257. data/app/views/services_mailer/notification_oai_endpoint_added.text.lv.plain.erb +4 -0
  258. data/app/views/services_mailer/notification_oai_endpoint_added.text.mt.html.erb +4 -0
  259. data/app/views/services_mailer/notification_oai_endpoint_added.text.mt.plain.erb +4 -0
  260. data/app/views/services_mailer/notification_oai_endpoint_added.text.nl.html.erb +4 -0
  261. data/app/views/services_mailer/notification_oai_endpoint_added.text.nl.plain.erb +4 -0
  262. data/app/views/services_mailer/notification_oai_endpoint_added.text.no.html.erb +4 -0
  263. data/app/views/services_mailer/notification_oai_endpoint_added.text.no.plain.erb +4 -0
  264. data/app/views/services_mailer/notification_oai_endpoint_added.text.pl.html.erb +4 -0
  265. data/app/views/services_mailer/notification_oai_endpoint_added.text.pl.plain.erb +4 -0
  266. data/app/views/services_mailer/notification_oai_endpoint_added.text.plain.erb +4 -0
  267. data/app/views/services_mailer/notification_oai_endpoint_added.text.pt-PT.html.erb +4 -0
  268. data/app/views/services_mailer/notification_oai_endpoint_added.text.pt-PT.plain.erb +4 -0
  269. data/app/views/services_mailer/notification_oai_endpoint_added.text.ro.html.erb +4 -0
  270. data/app/views/services_mailer/notification_oai_endpoint_added.text.ro.plain.erb +4 -0
  271. data/app/views/services_mailer/notification_oai_endpoint_added.text.ru.html.erb +4 -0
  272. data/app/views/services_mailer/notification_oai_endpoint_added.text.ru.plain.erb +4 -0
  273. data/app/views/services_mailer/notification_oai_endpoint_added.text.sk.html.erb +4 -0
  274. data/app/views/services_mailer/notification_oai_endpoint_added.text.sk.plain.erb +4 -0
  275. data/app/views/services_mailer/notification_oai_endpoint_added.text.sl.html.erb +4 -0
  276. data/app/views/services_mailer/notification_oai_endpoint_added.text.sl.plain.erb +4 -0
  277. data/app/views/services_mailer/notification_oai_endpoint_added.text.sq.html.erb +4 -0
  278. data/app/views/services_mailer/notification_oai_endpoint_added.text.sq.plain.erb +4 -0
  279. data/app/views/services_mailer/notification_oai_endpoint_added.text.sr.html.erb +4 -0
  280. data/app/views/services_mailer/notification_oai_endpoint_added.text.sr.plain.erb +4 -0
  281. data/app/views/services_mailer/notification_oai_endpoint_added.text.sv.html.erb +4 -0
  282. data/app/views/services_mailer/notification_oai_endpoint_added.text.sv.plain.erb +4 -0
  283. data/app/views/services_mailer/notification_oai_endpoint_added.text.th.html.erb +4 -0
  284. data/app/views/services_mailer/notification_oai_endpoint_added.text.th.plain.erb +4 -0
  285. data/app/views/services_mailer/notification_oai_endpoint_added.text.tl.html.erb +4 -0
  286. data/app/views/services_mailer/notification_oai_endpoint_added.text.tl.plain.erb +4 -0
  287. data/app/views/services_mailer/notification_oai_endpoint_added.text.tr.html.erb +4 -0
  288. data/app/views/services_mailer/notification_oai_endpoint_added.text.tr.plain.erb +4 -0
  289. data/app/views/services_mailer/notification_oai_endpoint_added.text.uk.html.erb +4 -0
  290. data/app/views/services_mailer/notification_oai_endpoint_added.text.uk.plain.erb +4 -0
  291. data/app/views/services_mailer/notification_oai_endpoint_added.text.vi.html.erb +4 -0
  292. data/app/views/services_mailer/notification_oai_endpoint_added.text.vi.plain.erb +4 -0
  293. data/app/views/services_mailer/notification_oai_endpoint_added.text.zh-CN.html.erb +4 -0
  294. data/app/views/services_mailer/notification_oai_endpoint_added.text.zh-CN.plain.erb +4 -0
  295. data/app/views/services_mailer/notification_oai_endpoint_added.text.zh-TW.html.erb +4 -0
  296. data/app/views/services_mailer/notification_oai_endpoint_added.text.zh-TW.plain.erb +4 -0
  297. data/app/views/services_mailer/notification_oai_endpoint_added.text.zh.html.erb +4 -0
  298. data/app/views/services_mailer/notification_oai_endpoint_added.text.zh.plain.erb +4 -0
  299. data/app/views/topics/_entry.html.erb +19 -0
  300. data/app/views/topics/_feed.html.erb +24 -0
  301. data/app/views/topics/_feed_preview.html.erb +18 -0
  302. data/app/views/topics/_form.html.erb +15 -0
  303. data/app/views/topics/_rss_discover.html.erb +1 -0
  304. data/app/views/topics/_simple_entry.html.erb +7 -0
  305. data/app/views/topics/new.html.erb +27 -0
  306. data/app/views/topics/photos.html.erb +14 -0
  307. data/app/views/topics/show.html.erb +80 -0
  308. data/app/views/topics/show.opml.builder +18 -0
  309. data/app/views/topics/videos.html.erb +14 -0
  310. data/app/views/visits/_comments_tool.html.erb +19 -0
  311. data/app/views/visits/_frame_scripts.html.erb +26 -0
  312. data/app/views/visits/_share_tool.html.erb +22 -0
  313. data/app/views/visits/_toolbar.html.erb +25 -0
  314. data/app/views/visits/show.html.erb +7 -0
  315. data/config/muck_services_routes.rb +37 -0
  316. data/config/solr/README.txt +0 -0
  317. data/config/solr/cores/de/conf/protwords.txt +21 -0
  318. data/config/solr/cores/de/conf/schema.xml +81 -0
  319. data/config/solr/cores/de/conf/solrconfig.xml +311 -0
  320. data/config/solr/cores/de/conf/stopwords.txt +341 -0
  321. data/config/solr/cores/de/conf/synonyms.txt +31 -0
  322. data/config/solr/cores/en/conf/protwords.txt +21 -0
  323. data/config/solr/cores/en/conf/schema.xml +83 -0
  324. data/config/solr/cores/en/conf/solrconfig.xml +311 -0
  325. data/config/solr/cores/en/conf/stopwords.txt +341 -0
  326. data/config/solr/cores/en/conf/synonyms.txt +31 -0
  327. data/config/solr/cores/es/conf/protwords.txt +21 -0
  328. data/config/solr/cores/es/conf/schema.xml +81 -0
  329. data/config/solr/cores/es/conf/solrconfig.xml +311 -0
  330. data/config/solr/cores/es/conf/stopwords.txt +206 -0
  331. data/config/solr/cores/es/conf/synonyms.txt +31 -0
  332. data/config/solr/cores/fr/conf/protwords.txt +21 -0
  333. data/config/solr/cores/fr/conf/schema.xml +82 -0
  334. data/config/solr/cores/fr/conf/solrconfig.xml +311 -0
  335. data/config/solr/cores/fr/conf/stopwords.txt +57 -0
  336. data/config/solr/cores/fr/conf/synonyms.txt +31 -0
  337. data/config/solr/cores/ja/conf/protwords.txt +21 -0
  338. data/config/solr/cores/ja/conf/schema.xml +69 -0
  339. data/config/solr/cores/ja/conf/solrconfig.xml +311 -0
  340. data/config/solr/cores/ja/conf/stopwords.txt +341 -0
  341. data/config/solr/cores/ja/conf/synonyms.txt +31 -0
  342. data/config/solr/cores/nl/conf/protwords.txt +21 -0
  343. data/config/solr/cores/nl/conf/schema.xml +78 -0
  344. data/config/solr/cores/nl/conf/solrconfig.xml +311 -0
  345. data/config/solr/cores/nl/conf/stopwords.txt +45691 -0
  346. data/config/solr/cores/nl/conf/synonyms.txt +31 -0
  347. data/config/solr/cores/ru/conf/protwords.txt +21 -0
  348. data/config/solr/cores/ru/conf/schema.xml +78 -0
  349. data/config/solr/cores/ru/conf/solrconfig.xml +311 -0
  350. data/config/solr/cores/ru/conf/stopwords.txt +341 -0
  351. data/config/solr/cores/ru/conf/synonyms.txt +31 -0
  352. data/config/solr/cores/zh/conf/protwords.txt +21 -0
  353. data/config/solr/cores/zh/conf/schema.xml +72 -0
  354. data/config/solr/cores/zh/conf/solrconfig.xml +311 -0
  355. data/config/solr/cores/zh/conf/stopwords.txt +341 -0
  356. data/config/solr/cores/zh/conf/synonyms.txt +31 -0
  357. data/config/solr/solr.xml +50 -0
  358. data/db/bootstrap/attention.yml +6 -0
  359. data/db/bootstrap/feeds.yml +4268 -0
  360. data/db/bootstrap/oai_endpoints.yml +6 -0
  361. data/db/bootstrap/service_categories.yml +52 -0
  362. data/db/bootstrap/services.yml +967 -0
  363. data/db/migrate/20090602191243_create_muck_raker.rb +322 -0
  364. data/db/migrate/20090619211125_create_tag_clouds.rb +19 -0
  365. data/db/migrate/20090623181458_add_grain_size_to_entries.rb +16 -0
  366. data/db/migrate/20090623193525_add_grain_size_to_tag_clouds.rb +12 -0
  367. data/db/migrate/20090703175825_denormalize_entries_subjects.rb +39 -0
  368. data/db/migrate/20090704220055_create_slugs.rb +18 -0
  369. data/db/migrate/20090716035935_change_tag_cloud_grain_sizes.rb +9 -0
  370. data/db/migrate/20090717173900_add_contributor_to_feeds.rb +9 -0
  371. data/db/migrate/20090717175825_normalize_entries_subjects.rb +41 -0
  372. data/db/migrate/20090721043213_change_services_title_to_name.rb +9 -0
  373. data/db/migrate/20090721054927_remove_services_not_null_from_feeds.rb +9 -0
  374. data/db/migrate/20090723050510_create_feed_parents.rb +17 -0
  375. data/db/migrate/20090728165716_add_etag_to_feeds.rb +9 -0
  376. data/db/migrate/20090730045848_add_comment_cache_to_entries.rb +9 -0
  377. data/db/migrate/20090804211240_add_entry_id_to_shares.rb +9 -0
  378. data/db/migrate/20090826220530_change_services_sequence_to_sort.rb +9 -0
  379. data/db/migrate/20090826225652_create_identity_feeds.rb +14 -0
  380. data/db/migrate/20090827005105_add_identity_fields_to_services.rb +13 -0
  381. data/db/migrate/20090827015308_create_service_categories.rb +12 -0
  382. data/db/migrate/20090827221502_add_prompt_and_template_to_services.rb +11 -0
  383. data/db/migrate/20090915041650_aggregations_to_polymorphic.rb +15 -0
  384. data/db/migrate/20090922174200_update_oai_endpoints.rb +13 -0
  385. data/db/migrate/20090922231552_add_dates_to_oai_endpoints.rb +11 -0
  386. data/db/migrate/20090923150807_rename_name_in_aggregation.rb +9 -0
  387. data/db/migrate/20090924200750_add_uri_data_template_to_services.rb +9 -0
  388. data/db/migrate/20091006183742_add_feed_count_to_aggregation.rb +9 -0
  389. data/db/migrate/20091022150615_add_uri_key_to_services.rb +9 -0
  390. data/lib/active_record/acts/muck_aggregation_owner.rb +30 -0
  391. data/lib/active_record/acts/muck_feed_owner.rb +31 -0
  392. data/lib/active_record/acts/muck_feed_parent.rb +23 -0
  393. data/lib/active_record/acts/muck_services_comment.rb +39 -0
  394. data/lib/active_record/acts/muck_services_share.rb +32 -0
  395. data/lib/muck_services.rb +21 -0
  396. data/lib/muck_services/exceptions.rb +5 -0
  397. data/lib/muck_services/initialize_routes.rb +8 -0
  398. data/lib/muck_services/languages.rb +57 -0
  399. data/lib/muck_services/muck_custom_form_builder.rb +22 -0
  400. data/lib/muck_services/services.rb +12 -0
  401. data/lib/muck_services/tasks.rb +97 -0
  402. data/locales/ar.yml +210 -0
  403. data/locales/bg.yml +210 -0
  404. data/locales/ca.yml +210 -0
  405. data/locales/cs.yml +210 -0
  406. data/locales/da.yml +210 -0
  407. data/locales/de.yml +210 -0
  408. data/locales/el.yml +210 -0
  409. data/locales/en.yml +213 -0
  410. data/locales/es.yml +210 -0
  411. data/locales/et.yml +210 -0
  412. data/locales/fa.yml +210 -0
  413. data/locales/fi.yml +210 -0
  414. data/locales/fr.yml +210 -0
  415. data/locales/gl.yml +210 -0
  416. data/locales/hi.yml +210 -0
  417. data/locales/hr.yml +210 -0
  418. data/locales/hu.yml +210 -0
  419. data/locales/id.yml +210 -0
  420. data/locales/it.yml +210 -0
  421. data/locales/iw.yml +210 -0
  422. data/locales/ja.yml +210 -0
  423. data/locales/ko.yml +210 -0
  424. data/locales/lt.yml +210 -0
  425. data/locales/lv.yml +210 -0
  426. data/locales/mt.yml +210 -0
  427. data/locales/nl.yml +210 -0
  428. data/locales/no.yml +211 -0
  429. data/locales/pl.yml +210 -0
  430. data/locales/pt-PT.yml +210 -0
  431. data/locales/ro.yml +210 -0
  432. data/locales/ru.yml +210 -0
  433. data/locales/sk.yml +210 -0
  434. data/locales/sl.yml +210 -0
  435. data/locales/sq.yml +210 -0
  436. data/locales/sr.yml +210 -0
  437. data/locales/sv.yml +210 -0
  438. data/locales/th.yml +210 -0
  439. data/locales/tl.yml +210 -0
  440. data/locales/tr.yml +210 -0
  441. data/locales/uk.yml +210 -0
  442. data/locales/vi.yml +210 -0
  443. data/locales/zh-CN.yml +210 -0
  444. data/locales/zh-TW.yml +210 -0
  445. data/locales/zh.yml +210 -0
  446. data/muck-services.gemspec +891 -0
  447. data/public/images/service_icons/16/amazon.png +0 -0
  448. data/public/images/service_icons/16/ask.png +0 -0
  449. data/public/images/service_icons/16/bibsonomy.png +0 -0
  450. data/public/images/service_icons/16/bing.png +0 -0
  451. data/public/images/service_icons/16/blogger.png +0 -0
  452. data/public/images/service_icons/16/bloglines.png +0 -0
  453. data/public/images/service_icons/16/citeulike.png +0 -0
  454. data/public/images/service_icons/16/clipmarks.png +0 -0
  455. data/public/images/service_icons/16/connotea.png +0 -0
  456. data/public/images/service_icons/16/dailymotion.png +0 -0
  457. data/public/images/service_icons/16/delicious.png +0 -0
  458. data/public/images/service_icons/16/digg.png +0 -0
  459. data/public/images/service_icons/16/diigo.png +0 -0
  460. data/public/images/service_icons/16/facebook.png +0 -0
  461. data/public/images/service_icons/16/feed.png +0 -0
  462. data/public/images/service_icons/16/flickr.png +0 -0
  463. data/public/images/service_icons/16/fotolog.png +0 -0
  464. data/public/images/service_icons/16/friendfeed.png +0 -0
  465. data/public/images/service_icons/16/friendster.png +0 -0
  466. data/public/images/service_icons/16/furl.png +0 -0
  467. data/public/images/service_icons/16/goodreads.png +0 -0
  468. data/public/images/service_icons/16/google.png +0 -0
  469. data/public/images/service_icons/16/googleblog.png +0 -0
  470. data/public/images/service_icons/16/googlenews.png +0 -0
  471. data/public/images/service_icons/16/icerocket.png +0 -0
  472. data/public/images/service_icons/16/identica.png +0 -0
  473. data/public/images/service_icons/16/joost.png +0 -0
  474. data/public/images/service_icons/16/lastfm.png +0 -0
  475. data/public/images/service_icons/16/librarything.png +0 -0
  476. data/public/images/service_icons/16/linkedin.png +0 -0
  477. data/public/images/service_icons/16/livejournal.png +0 -0
  478. data/public/images/service_icons/16/magnolia.png +0 -0
  479. data/public/images/service_icons/16/mendeley.png +0 -0
  480. data/public/images/service_icons/16/metacafe.png +0 -0
  481. data/public/images/service_icons/16/mixx.png +0 -0
  482. data/public/images/service_icons/16/myspace.png +0 -0
  483. data/public/images/service_icons/16/netflix.png +0 -0
  484. data/public/images/service_icons/16/netvibes.png +0 -0
  485. data/public/images/service_icons/16/newsvine.png +0 -0
  486. data/public/images/service_icons/16/oai.png +0 -0
  487. data/public/images/service_icons/16/odeo.png +0 -0
  488. data/public/images/service_icons/16/opml.png +0 -0
  489. data/public/images/service_icons/16/pandora.png +0 -0
  490. data/public/images/service_icons/16/photobucket.png +0 -0
  491. data/public/images/service_icons/16/picasa.png +0 -0
  492. data/public/images/service_icons/16/polyvore.png +0 -0
  493. data/public/images/service_icons/16/pownce.png +0 -0
  494. data/public/images/service_icons/16/reddit.png +0 -0
  495. data/public/images/service_icons/16/simpy.png +0 -0
  496. data/public/images/service_icons/16/smugmug.png +0 -0
  497. data/public/images/service_icons/16/stumbleupon.png +0 -0
  498. data/public/images/service_icons/16/tag.png +0 -0
  499. data/public/images/service_icons/16/technorati.png +0 -0
  500. data/public/images/service_icons/16/tumblr.png +0 -0
  501. data/public/images/service_icons/16/twine.png +0 -0
  502. data/public/images/service_icons/16/twitter.png +0 -0
  503. data/public/images/service_icons/16/vimeo.png +0 -0
  504. data/public/images/service_icons/16/webshots.png +0 -0
  505. data/public/images/service_icons/16/wordpress.png +0 -0
  506. data/public/images/service_icons/16/xanga.png +0 -0
  507. data/public/images/service_icons/16/yahoo.png +0 -0
  508. data/public/images/service_icons/16/yelp.png +0 -0
  509. data/public/images/service_icons/16/youtube.png +0 -0
  510. data/public/images/service_icons/16/zooomr.png +0 -0
  511. data/public/images/service_icons/16/zotero.png +0 -0
  512. data/public/images/service_icons/24/amazon.png +0 -0
  513. data/public/images/service_icons/24/ask.png +0 -0
  514. data/public/images/service_icons/24/bibsonomy.png +0 -0
  515. data/public/images/service_icons/24/bing.png +0 -0
  516. data/public/images/service_icons/24/blogger.png +0 -0
  517. data/public/images/service_icons/24/bloglines.png +0 -0
  518. data/public/images/service_icons/24/citeulike.png +0 -0
  519. data/public/images/service_icons/24/clipmarks.png +0 -0
  520. data/public/images/service_icons/24/connotea.png +0 -0
  521. data/public/images/service_icons/24/dailymotion.png +0 -0
  522. data/public/images/service_icons/24/delicious.png +0 -0
  523. data/public/images/service_icons/24/digg.png +0 -0
  524. data/public/images/service_icons/24/diigo.png +0 -0
  525. data/public/images/service_icons/24/facebook.png +0 -0
  526. data/public/images/service_icons/24/feed.png +0 -0
  527. data/public/images/service_icons/24/flickr.png +0 -0
  528. data/public/images/service_icons/24/fotolog.png +0 -0
  529. data/public/images/service_icons/24/friendfeed.png +0 -0
  530. data/public/images/service_icons/24/friendster.png +0 -0
  531. data/public/images/service_icons/24/furl.png +0 -0
  532. data/public/images/service_icons/24/goodreads.png +0 -0
  533. data/public/images/service_icons/24/google.png +0 -0
  534. data/public/images/service_icons/24/googleblog.png +0 -0
  535. data/public/images/service_icons/24/googlenews.png +0 -0
  536. data/public/images/service_icons/24/icerocket.png +0 -0
  537. data/public/images/service_icons/24/identica.png +0 -0
  538. data/public/images/service_icons/24/joost.png +0 -0
  539. data/public/images/service_icons/24/lastfm.png +0 -0
  540. data/public/images/service_icons/24/librarything.png +0 -0
  541. data/public/images/service_icons/24/linkedin.png +0 -0
  542. data/public/images/service_icons/24/livejournal.png +0 -0
  543. data/public/images/service_icons/24/magnolia.png +0 -0
  544. data/public/images/service_icons/24/mendeley.png +0 -0
  545. data/public/images/service_icons/24/metacafe.png +0 -0
  546. data/public/images/service_icons/24/mixx.png +0 -0
  547. data/public/images/service_icons/24/myspace.png +0 -0
  548. data/public/images/service_icons/24/netflix.png +0 -0
  549. data/public/images/service_icons/24/netvibes.png +0 -0
  550. data/public/images/service_icons/24/newsvine.png +0 -0
  551. data/public/images/service_icons/24/oai.png +0 -0
  552. data/public/images/service_icons/24/odeo.png +0 -0
  553. data/public/images/service_icons/24/opml.png +0 -0
  554. data/public/images/service_icons/24/pandora.png +0 -0
  555. data/public/images/service_icons/24/photobucket.png +0 -0
  556. data/public/images/service_icons/24/picasa.png +0 -0
  557. data/public/images/service_icons/24/polyvore.png +0 -0
  558. data/public/images/service_icons/24/pownce.png +0 -0
  559. data/public/images/service_icons/24/reddit.png +0 -0
  560. data/public/images/service_icons/24/simpy.png +0 -0
  561. data/public/images/service_icons/24/smugmug.png +0 -0
  562. data/public/images/service_icons/24/stumbleupon.png +0 -0
  563. data/public/images/service_icons/24/tag.png +0 -0
  564. data/public/images/service_icons/24/technorati.png +0 -0
  565. data/public/images/service_icons/24/tumblr.png +0 -0
  566. data/public/images/service_icons/24/twine.png +0 -0
  567. data/public/images/service_icons/24/twitter.png +0 -0
  568. data/public/images/service_icons/24/vimeo.png +0 -0
  569. data/public/images/service_icons/24/webshots.png +0 -0
  570. data/public/images/service_icons/24/wordpress.png +0 -0
  571. data/public/images/service_icons/24/xanga.png +0 -0
  572. data/public/images/service_icons/24/yahoo.png +0 -0
  573. data/public/images/service_icons/24/yelp.png +0 -0
  574. data/public/images/service_icons/24/youtube.png +0 -0
  575. data/public/images/service_icons/24/zooomr.png +0 -0
  576. data/public/images/service_icons/24/zotero.png +0 -0
  577. data/public/images/service_icons/48/amazon.png +0 -0
  578. data/public/images/service_icons/48/ask.png +0 -0
  579. data/public/images/service_icons/48/bibsonomy.png +0 -0
  580. data/public/images/service_icons/48/bing.png +0 -0
  581. data/public/images/service_icons/48/blogger.png +0 -0
  582. data/public/images/service_icons/48/bloglines.png +0 -0
  583. data/public/images/service_icons/48/citeulike.png +0 -0
  584. data/public/images/service_icons/48/clipmarks.png +0 -0
  585. data/public/images/service_icons/48/connotea.png +0 -0
  586. data/public/images/service_icons/48/dailymotion.png +0 -0
  587. data/public/images/service_icons/48/delicious.png +0 -0
  588. data/public/images/service_icons/48/digg.png +0 -0
  589. data/public/images/service_icons/48/diigo.png +0 -0
  590. data/public/images/service_icons/48/facebook.png +0 -0
  591. data/public/images/service_icons/48/feed.png +0 -0
  592. data/public/images/service_icons/48/flickr.png +0 -0
  593. data/public/images/service_icons/48/fotolog.png +0 -0
  594. data/public/images/service_icons/48/friendfeed.png +0 -0
  595. data/public/images/service_icons/48/friendster.png +0 -0
  596. data/public/images/service_icons/48/furl.png +0 -0
  597. data/public/images/service_icons/48/goodreads.png +0 -0
  598. data/public/images/service_icons/48/google.png +0 -0
  599. data/public/images/service_icons/48/googleblog.png +0 -0
  600. data/public/images/service_icons/48/googlenews.png +0 -0
  601. data/public/images/service_icons/48/icerocket.png +0 -0
  602. data/public/images/service_icons/48/identica.png +0 -0
  603. data/public/images/service_icons/48/joost.png +0 -0
  604. data/public/images/service_icons/48/lastfm.png +0 -0
  605. data/public/images/service_icons/48/librarything.png +0 -0
  606. data/public/images/service_icons/48/linkedin.png +0 -0
  607. data/public/images/service_icons/48/livejournal.png +0 -0
  608. data/public/images/service_icons/48/magnolia.png +0 -0
  609. data/public/images/service_icons/48/mendeley.png +0 -0
  610. data/public/images/service_icons/48/metacafe.png +0 -0
  611. data/public/images/service_icons/48/mixx.png +0 -0
  612. data/public/images/service_icons/48/myspace.png +0 -0
  613. data/public/images/service_icons/48/netflix.png +0 -0
  614. data/public/images/service_icons/48/netvibes.png +0 -0
  615. data/public/images/service_icons/48/newsvine.png +0 -0
  616. data/public/images/service_icons/48/oai.png +0 -0
  617. data/public/images/service_icons/48/odeo.png +0 -0
  618. data/public/images/service_icons/48/opml.png +0 -0
  619. data/public/images/service_icons/48/pandora.png +0 -0
  620. data/public/images/service_icons/48/photobucket.png +0 -0
  621. data/public/images/service_icons/48/picasa.png +0 -0
  622. data/public/images/service_icons/48/polyvore.png +0 -0
  623. data/public/images/service_icons/48/pownce.png +0 -0
  624. data/public/images/service_icons/48/reddit.png +0 -0
  625. data/public/images/service_icons/48/simpy.png +0 -0
  626. data/public/images/service_icons/48/smugmug.png +0 -0
  627. data/public/images/service_icons/48/stumbleupon.png +0 -0
  628. data/public/images/service_icons/48/tag.png +0 -0
  629. data/public/images/service_icons/48/technorati.png +0 -0
  630. data/public/images/service_icons/48/tumblr.png +0 -0
  631. data/public/images/service_icons/48/twine.png +0 -0
  632. data/public/images/service_icons/48/twitter.png +0 -0
  633. data/public/images/service_icons/48/vimeo.png +0 -0
  634. data/public/images/service_icons/48/webshots.png +0 -0
  635. data/public/images/service_icons/48/wordpress.png +0 -0
  636. data/public/images/service_icons/48/xanga.png +0 -0
  637. data/public/images/service_icons/48/yahoo.png +0 -0
  638. data/public/images/service_icons/48/yelp.png +0 -0
  639. data/public/images/service_icons/48/youtube.png +0 -0
  640. data/public/images/service_icons/48/zooomr.png +0 -0
  641. data/public/images/service_icons/48/zotero.png +0 -0
  642. data/public/images/service_icons/60/amazon.png +0 -0
  643. data/public/images/service_icons/60/ask.png +0 -0
  644. data/public/images/service_icons/60/bibsonomy.png +0 -0
  645. data/public/images/service_icons/60/bing.png +0 -0
  646. data/public/images/service_icons/60/blogger.png +0 -0
  647. data/public/images/service_icons/60/bloglines.png +0 -0
  648. data/public/images/service_icons/60/citeulike.png +0 -0
  649. data/public/images/service_icons/60/clipmarks.png +0 -0
  650. data/public/images/service_icons/60/connotea.png +0 -0
  651. data/public/images/service_icons/60/dailymotion.png +0 -0
  652. data/public/images/service_icons/60/delicious.png +0 -0
  653. data/public/images/service_icons/60/digg.png +0 -0
  654. data/public/images/service_icons/60/diigo.png +0 -0
  655. data/public/images/service_icons/60/facebook.png +0 -0
  656. data/public/images/service_icons/60/feed.png +0 -0
  657. data/public/images/service_icons/60/flickr.png +0 -0
  658. data/public/images/service_icons/60/fotolog.png +0 -0
  659. data/public/images/service_icons/60/friendfeed.png +0 -0
  660. data/public/images/service_icons/60/friendster.png +0 -0
  661. data/public/images/service_icons/60/furl.png +0 -0
  662. data/public/images/service_icons/60/goodreads.png +0 -0
  663. data/public/images/service_icons/60/google.png +0 -0
  664. data/public/images/service_icons/60/googleblog.png +0 -0
  665. data/public/images/service_icons/60/googlenews.png +0 -0
  666. data/public/images/service_icons/60/icerocket.png +0 -0
  667. data/public/images/service_icons/60/identica.png +0 -0
  668. data/public/images/service_icons/60/joost.png +0 -0
  669. data/public/images/service_icons/60/lastfm.png +0 -0
  670. data/public/images/service_icons/60/librarything.png +0 -0
  671. data/public/images/service_icons/60/linkedin.png +0 -0
  672. data/public/images/service_icons/60/livejournal.png +0 -0
  673. data/public/images/service_icons/60/magnolia.png +0 -0
  674. data/public/images/service_icons/60/mendeley.png +0 -0
  675. data/public/images/service_icons/60/metacafe.png +0 -0
  676. data/public/images/service_icons/60/mixx.png +0 -0
  677. data/public/images/service_icons/60/myspace.png +0 -0
  678. data/public/images/service_icons/60/netflix.png +0 -0
  679. data/public/images/service_icons/60/netvibes.png +0 -0
  680. data/public/images/service_icons/60/newsvine.png +0 -0
  681. data/public/images/service_icons/60/oai.png +0 -0
  682. data/public/images/service_icons/60/odeo.png +0 -0
  683. data/public/images/service_icons/60/opml.png +0 -0
  684. data/public/images/service_icons/60/pandora.png +0 -0
  685. data/public/images/service_icons/60/photobucket.png +0 -0
  686. data/public/images/service_icons/60/picasa.png +0 -0
  687. data/public/images/service_icons/60/polyvore.png +0 -0
  688. data/public/images/service_icons/60/pownce.png +0 -0
  689. data/public/images/service_icons/60/reddit.png +0 -0
  690. data/public/images/service_icons/60/simpy.png +0 -0
  691. data/public/images/service_icons/60/smugmug.png +0 -0
  692. data/public/images/service_icons/60/stumbleupon.png +0 -0
  693. data/public/images/service_icons/60/tag.png +0 -0
  694. data/public/images/service_icons/60/technorati.png +0 -0
  695. data/public/images/service_icons/60/tumblr.png +0 -0
  696. data/public/images/service_icons/60/twine.png +0 -0
  697. data/public/images/service_icons/60/twitter.png +0 -0
  698. data/public/images/service_icons/60/vimeo.png +0 -0
  699. data/public/images/service_icons/60/webshots.png +0 -0
  700. data/public/images/service_icons/60/wordpress.png +0 -0
  701. data/public/images/service_icons/60/xanga.png +0 -0
  702. data/public/images/service_icons/60/yahoo.png +0 -0
  703. data/public/images/service_icons/60/yelp.png +0 -0
  704. data/public/images/service_icons/60/youtube.png +0 -0
  705. data/public/images/service_icons/60/zooomr.png +0 -0
  706. data/public/images/service_icons/60/zotero.png +0 -0
  707. data/public/images/service_icons/facebook_friend_links.jpg +0 -0
  708. data/public/images/service_icons/facebook_my_links.jpg +0 -0
  709. data/public/javascripts/muck_services.js +94 -0
  710. data/public/stylesheets/frame.css +56 -0
  711. data/public/stylesheets/muck_services.css +90 -0
  712. data/rails/init.rb +18 -0
  713. data/test/rails_root/app/controllers/application_controller.rb +32 -0
  714. data/test/rails_root/app/controllers/default_controller.rb +7 -0
  715. data/test/rails_root/app/helpers/application_helper.rb +3 -0
  716. data/test/rails_root/app/models/activity.rb +24 -0
  717. data/test/rails_root/app/models/comment.rb +23 -0
  718. data/test/rails_root/app/models/share.rb +20 -0
  719. data/test/rails_root/app/models/user.rb +43 -0
  720. data/test/rails_root/app/models/user_session.rb +2 -0
  721. data/test/rails_root/config/boot.rb +109 -0
  722. data/test/rails_root/config/environment.rb +37 -0
  723. data/test/rails_root/config/environments/cucumber.rb +21 -0
  724. data/test/rails_root/config/environments/development.rb +36 -0
  725. data/test/rails_root/config/environments/production.rb +1 -0
  726. data/test/rails_root/config/environments/test.rb +34 -0
  727. data/test/rails_root/config/initializers/inflections.rb +10 -0
  728. data/test/rails_root/config/initializers/mime_types.rb +5 -0
  729. data/test/rails_root/config/initializers/requires.rb +13 -0
  730. data/test/rails_root/config/initializers/session_store.rb +8 -0
  731. data/test/rails_root/config/routes.rb +11 -0
  732. data/test/rails_root/db/migrate/20090320174818_create_muck_permissions_and_roles.rb +16 -0
  733. data/test/rails_root/db/migrate/20090327231918_create_users.rb +40 -0
  734. data/test/rails_root/db/migrate/20090402033319_add_muck_activities.rb +36 -0
  735. data/test/rails_root/db/migrate/20090402234137_create_languages.rb +18 -0
  736. data/test/rails_root/db/migrate/20090426041056_create_countries.rb +15 -0
  737. data/test/rails_root/db/migrate/20090426041103_create_states.rb +18 -0
  738. data/test/rails_root/db/migrate/20090602191243_create_muck_raker.rb +322 -0
  739. data/test/rails_root/db/migrate/20090613173314_create_comments.rb +24 -0
  740. data/test/rails_root/db/migrate/20090619211125_create_tag_clouds.rb +19 -0
  741. data/test/rails_root/db/migrate/20090623181458_add_grain_size_to_entries.rb +16 -0
  742. data/test/rails_root/db/migrate/20090623193525_add_grain_size_to_tag_clouds.rb +12 -0
  743. data/test/rails_root/db/migrate/20090703175825_denormalize_entries_subjects.rb +39 -0
  744. data/test/rails_root/db/migrate/20090704220055_create_slugs.rb +18 -0
  745. data/test/rails_root/db/migrate/20090716035935_change_tag_cloud_grain_sizes.rb +9 -0
  746. data/test/rails_root/db/migrate/20090717173900_add_contributor_to_feeds.rb +9 -0
  747. data/test/rails_root/db/migrate/20090717175825_normalize_entries_subjects.rb +41 -0
  748. data/test/rails_root/db/migrate/20090721043213_change_services_title_to_name.rb +9 -0
  749. data/test/rails_root/db/migrate/20090721054927_remove_services_not_null_from_feeds.rb +9 -0
  750. data/test/rails_root/db/migrate/20090723050510_create_feed_parents.rb +17 -0
  751. data/test/rails_root/db/migrate/20090728165716_add_etag_to_feeds.rb +9 -0
  752. data/test/rails_root/db/migrate/20090730044139_add_comment_cache.rb +9 -0
  753. data/test/rails_root/db/migrate/20090730045848_add_comment_cache_to_entries.rb +9 -0
  754. data/test/rails_root/db/migrate/20090730154102_allow_null_user.rb +9 -0
  755. data/test/rails_root/db/migrate/20090803185323_create_shares.rb +16 -0
  756. data/test/rails_root/db/migrate/20090804184247_add_comment_count_to_shares.rb +9 -0
  757. data/test/rails_root/db/migrate/20090804211240_add_entry_id_to_shares.rb +9 -0
  758. data/test/rails_root/db/migrate/20090804231857_add_shares_uri_index.rb +9 -0
  759. data/test/rails_root/db/migrate/20090818204527_add_activity_indexes.rb +9 -0
  760. data/test/rails_root/db/migrate/20090819030523_add_attachable_to_activities.rb +13 -0
  761. data/test/rails_root/db/migrate/20090826220530_change_services_sequence_to_sort.rb +9 -0
  762. data/test/rails_root/db/migrate/20090826225652_create_identity_feeds.rb +14 -0
  763. data/test/rails_root/db/migrate/20090827005105_add_identity_fields_to_services.rb +13 -0
  764. data/test/rails_root/db/migrate/20090827015308_create_service_categories.rb +12 -0
  765. data/test/rails_root/db/migrate/20090827221502_add_prompt_and_template_to_services.rb +11 -0
  766. data/test/rails_root/db/migrate/20090915041650_aggregations_to_polymorphic.rb +15 -0
  767. data/test/rails_root/db/migrate/20090922174200_update_oai_endpoints.rb +13 -0
  768. data/test/rails_root/db/migrate/20090922231552_add_dates_to_oai_endpoints.rb +11 -0
  769. data/test/rails_root/db/migrate/20090923150807_rename_name_in_aggregation.rb +9 -0
  770. data/test/rails_root/db/migrate/20090924200750_add_uri_data_template_to_services.rb +9 -0
  771. data/test/rails_root/db/migrate/20091006183742_add_feed_count_to_aggregation.rb +9 -0
  772. data/test/rails_root/db/migrate/20091022150615_add_uri_key_to_services.rb +9 -0
  773. data/test/rails_root/db/schema.rb +474 -0
  774. data/test/rails_root/features/step_definitions/common_steps.rb +93 -0
  775. data/test/rails_root/features/step_definitions/visit_steps.rb +6 -0
  776. data/test/rails_root/features/step_definitions/webrat_steps.rb +128 -0
  777. data/test/rails_root/features/support/env.rb +14 -0
  778. data/test/rails_root/features/support/paths.rb +36 -0
  779. data/test/rails_root/public/dispatch.rb +10 -0
  780. data/test/rails_root/script/create_project.rb +52 -0
  781. data/test/rails_root/test/factories.rb +151 -0
  782. data/test/rails_root/test/functional/admin/feeds_controller_test.rb +37 -0
  783. data/test/rails_root/test/functional/admin/oai_endpoints_controller_test.rb +30 -0
  784. data/test/rails_root/test/functional/aggregation_feeds_controller_test.rb +67 -0
  785. data/test/rails_root/test/functional/aggregations_controller_test.rb +89 -0
  786. data/test/rails_root/test/functional/feed_previews_controller_test.rb +32 -0
  787. data/test/rails_root/test/functional/feeds_controller_test.rb +77 -0
  788. data/test/rails_root/test/functional/identity_feeds_controller_test.rb +110 -0
  789. data/test/rails_root/test/functional/oai_endpoints_controller_test.rb +42 -0
  790. data/test/rails_root/test/functional/topics_controller_test.rb +46 -0
  791. data/test/rails_root/test/functional/visits_controller_test.rb +21 -0
  792. data/test/rails_root/test/shoulda_macros/controller.rb +49 -0
  793. data/test/rails_root/test/shoulda_macros/forms.rb +32 -0
  794. data/test/rails_root/test/shoulda_macros/models.rb +50 -0
  795. data/test/rails_root/test/shoulda_macros/pagination.rb +53 -0
  796. data/test/rails_root/test/shoulda_macros/plugins.rb +34 -0
  797. data/test/rails_root/test/test_helper.rb +85 -0
  798. data/test/rails_root/test/unit/aggregation_feed_test.rb +25 -0
  799. data/test/rails_root/test/unit/aggregation_test.rb +120 -0
  800. data/test/rails_root/test/unit/comment_test.rb +38 -0
  801. data/test/rails_root/test/unit/entry_test.rb +65 -0
  802. data/test/rails_root/test/unit/feed_parent_test.rb +22 -0
  803. data/test/rails_root/test/unit/feed_test.rb +177 -0
  804. data/test/rails_root/test/unit/identity_feed_test.rb +18 -0
  805. data/test/rails_root/test/unit/oai_endpoint_test.rb +40 -0
  806. data/test/rails_root/test/unit/service_category_test.rb +19 -0
  807. data/test/rails_root/test/unit/service_test.rb +331 -0
  808. data/test/rails_root/test/unit/services_mailer_test.rb +35 -0
  809. data/test/rails_root/test/unit/share_test.rb +30 -0
  810. data/test/rails_root/test/unit/tag_cloud_test.rb +23 -0
  811. data/test/rails_root/test/unit/user_test.rb +43 -0
  812. data/test/rails_root/vendor/plugins/jrails/init.rb +1 -0
  813. data/test/rails_root/vendor/plugins/jrails/install.rb +9 -0
  814. data/test/rails_root/vendor/plugins/jrails/lib/jrails.rb +421 -0
  815. data/test/rails_root/vendor/plugins/jrails/rails/init.rb +15 -0
  816. data/test/rails_root/vendor/plugins/ssl_requirement/lib/ssl_requirement.rb +62 -0
  817. data/test/rails_root/vendor/plugins/ssl_requirement/test/ssl_requirement_test.rb +132 -0
  818. metadata +991 -0
@@ -0,0 +1,224 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: feeds
4
+ #
5
+ # id :integer(4) not null, primary key
6
+ # uri :string(2083)
7
+ # display_uri :string(2083)
8
+ # title :string(1000)
9
+ # short_title :string(100)
10
+ # description :text
11
+ # tag_filter :string(1000)
12
+ # top_tags :text
13
+ # priority :integer(4) default(10)
14
+ # status :integer(4) default(1)
15
+ # last_requested_at :datetime default(Wed Jan 01 00:00:00 UTC 1969)
16
+ # last_harvested_at :datetime default(Wed Jan 01 00:00:00 UTC 1969)
17
+ # harvest_interval :integer(4) default(86400)
18
+ # failed_requests :integer(4) default(0)
19
+ # error_message :text
20
+ # service_id :integer(4) default(0)
21
+ # login :string(255)
22
+ # password :string(255)
23
+ # created_at :datetime
24
+ # updated_at :datetime
25
+ # entries_changed_at :datetime
26
+ # harvested_from_display_uri :string(2083)
27
+ # harvested_from_title :string(1000)
28
+ # harvested_from_short_title :string(100)
29
+ # entries_count :integer(4)
30
+ # default_language_id :integer(4) default(0)
31
+ # default_grain_size :string(255) default("unknown")
32
+ # contributor_id :integer(4)
33
+ # etag :string(255)
34
+ #
35
+
36
+ class Feed < ActiveRecord::Base
37
+
38
+ include HTTParty
39
+ format :xml
40
+
41
+ validates_presence_of :uri
42
+
43
+ has_many :feed_parents
44
+ has_many :identity_feeds
45
+ has_many :aggregation_feeds
46
+ has_many :aggregations, :through => :aggregation_feeds
47
+ has_many :entries, :dependent => :destroy
48
+ belongs_to :contributor, :class_name => 'User', :foreign_key => 'contributor_id'
49
+ belongs_to :default_language, :class_name => 'Language', :foreign_key => 'default_language_id'
50
+ belongs_to :service
51
+
52
+ named_scope :banned, :conditions => ["status = ?", MuckServices::Status::BANNED]
53
+ named_scope :valid, :conditions => "status >= 0", :include => [:default_language]
54
+ named_scope :by_title, :order => "title ASC", :include => [:default_language]
55
+ named_scope :recent, lambda { { :conditions => ['created_at > ?', 1.week.ago] } }
56
+ named_scope :by_newest, :order => "created_at DESC", :include => [:default_language]
57
+
58
+ attr_protected :status, :last_requested_at, :last_harvested_at, :harvest_interval, :failed_requests,
59
+ :created_at, :updated_at, :entries_changed_at, :entries_count, :contributor_id
60
+
61
+ # named_scope :ready_to_harvest, lambda { |*args| { :conditions => [ "feeds.last_harvested_at < ?", args.first || 1.day.ago.end_of_day ] } }
62
+
63
+ def banned?
64
+ self.status == MuckServices::Status::BANNED
65
+ end
66
+
67
+ def pending?
68
+ self.status == MuckServices::Status::PENDING
69
+ end
70
+
71
+ def inform_admin
72
+ if GlobalConfig.inform_admin_of_global_feed && global?
73
+ ServicesMailer.deliver_notification_feed_added(self) # Global feed. Email the admin to let them know a feed has been added
74
+ end
75
+ end
76
+
77
+ # harvest_interval is stored in seconds
78
+ # default is 86400 which is one day
79
+ def harvest_interval_hours
80
+ self.harvest_interval/3600
81
+ end
82
+
83
+ # Converts hours into seconds for harvest_interval
84
+ def harvest_interval_hours=(interval)
85
+ self.harvest_interval = interval * 3600
86
+ end
87
+
88
+ def harvest
89
+ # check to see if the feed has changed
90
+ feed = Feedzirra::Feed.fetch_and_parse(self.uri)
91
+ feed.entries
92
+ # updated_feed = Feedzirra::Feed.update(self)
93
+ # if updated_feed.updated?
94
+ # updated_feed.new_entries # get new entries
95
+ # updated_feed.sanitize_entries! # clean up
96
+ # end
97
+ end
98
+
99
+ # provided to make feed quack like a feedzirra feed
100
+ def url
101
+ display_uri
102
+ end
103
+
104
+ # provided to make feed quack like a feedzirra feed
105
+ def feed_url
106
+ uri
107
+ end
108
+
109
+ # provided to make feed quack like a feedzirra feed
110
+ def last_modified
111
+ entries_changed_at
112
+ end
113
+
114
+ # feeds that are not attached to anything become global to the site
115
+ def global?
116
+ self.feed_parents.empty? && self.identity_feeds.empty? && self.aggregations.empty?
117
+ end
118
+
119
+ # Checks to see if there is a reference to the feed in any of the relation tables.
120
+ def in_use?
121
+ feed = FeedParent.find_by_feed_id(self.id)
122
+ return true if feed
123
+ feed = IdentityFeed.find_by_feed_id(self.id)
124
+ return true if feed
125
+ feed = AggregationFeed.find_by_feed_id(self.id)
126
+ return true if feed
127
+ false
128
+ end
129
+
130
+ # This will delete a feed if there are no references to it
131
+ def delete_if_unused(user)
132
+ if user.id == contributor_id && !in_use?
133
+ self.destroy
134
+ else
135
+ false
136
+ end
137
+ end
138
+
139
+ # Gathers all available feed uris from the given uri and parses them into
140
+ # feed objects
141
+ def self.gather_information(uri)
142
+ feeds = []
143
+ @available_feeds = discover_feeds(uri)
144
+ @available_feeds.each do |feed|
145
+ feeds << new_from_feedzirra(fetch_feed(feed.url)) unless feed.blank?
146
+ end
147
+ feeds
148
+ end
149
+
150
+ # Gathers all available feed uris from the given uri and parses them into
151
+ # feed objects
152
+ def self.feeds_from_uri(uri, user = nil)
153
+ feeds = []
154
+ @available_feeds = discover_feeds(uri)
155
+ @available_feeds.each do |feed|
156
+ feeds << create_from_feedzirra(fetch_feed(feed.url), user) unless feed.blank?
157
+ end
158
+ feeds
159
+ end
160
+
161
+ # Fetch a remote feed
162
+ def self.fetch_feed(url)
163
+ return nil if url.blank?
164
+ Feedzirra::Feed.fetch_and_parse(url)
165
+ end
166
+
167
+ # Turns a feed from feedzirra into a muck feed
168
+ def self.new_from_feedzirra(feed)
169
+ return if feed.blank?
170
+ Feed.new(:short_title => feed.title,
171
+ :title => feed.title,
172
+ :display_uri => feed.url,
173
+ :uri => feed.feed_url)
174
+ end
175
+
176
+ # Creates a feed from feedzirra into a muck feed
177
+ def self.create_from_feedzirra(feed, user)
178
+ return if feed.blank?
179
+ Feed.find_or_create(feed.feed_url, feed.title, '', '', Service.find_service_by_uri(feed.url), user, feed.url)
180
+ end
181
+
182
+ # Looks for feeds from a given url
183
+ def self.discover_feeds(uri)
184
+ Feedbag.find(uri)
185
+ end
186
+
187
+ # Finds or creates a feed based on the url. Any give feed uri should only exist once in the system
188
+ def self.find_or_create(uri, title, username, password, service_id, contributor_id, display_uri = nil)
189
+ Feed.find_by_uri(uri) ||
190
+ Feed.create(:uri => uri,
191
+ :harvest_interval => '01:00:00',
192
+ :last_harvested_at => Time.at(0),
193
+ :title => title,
194
+ :login => username,
195
+ :password => password,
196
+ :service_id => service_id,
197
+ :contributor_id => contributor_id,
198
+ :display_uri => display_uri)
199
+ end
200
+
201
+ # Create feeds for the given uris
202
+ # user: User that will be set as the feed contributor
203
+ # uris: An array of uris for which to create feeds
204
+ # service: A default service to be associated with all the feeds.
205
+ def self.create_tag_feeds(user = nil, uris = nil, service = nil)
206
+ return [] if uris.blank?
207
+ service ||= Service.default_service
208
+ uris.collect { |uri| Feed.find_or_create(uri, '', '', '', service.id, user, uri) }
209
+ end
210
+
211
+ # Combines entries in a collection of feeds together and sorts the entries by date
212
+ def self.combine_sort(feeds)
213
+ return [] if feeds.nil? || feeds.blank?
214
+ entries = feeds.collect{|feed| feed.entries}.flatten!
215
+ sort_entries(entries)
216
+ end
217
+
218
+ # Sorts a collection of entries by date
219
+ def self.sort_entries(entries)
220
+ return [] if entries.nil? || entries.blank?
221
+ entries.sort { |a,b| b.published_at <=> a.published_at }
222
+ end
223
+
224
+ end
@@ -0,0 +1,18 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: feed_parents
4
+ #
5
+ # id :integer(4) not null, primary key
6
+ # feed_id :integer(4)
7
+ # ownable_id :integer(4)
8
+ # ownable_type :string(255)
9
+ # created_at :datetime
10
+ # updated_at :datetime
11
+ #
12
+
13
+ class FeedParent < ActiveRecord::Base
14
+ unloadable
15
+
16
+ belongs_to :feed
17
+ belongs_to :ownable, :polymorphic => true
18
+ end
@@ -0,0 +1,26 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: identity_feeds
4
+ #
5
+ # id :integer(4) not null, primary key
6
+ # feed_id :integer(4) not null
7
+ # ownable_id :integer(4) not null
8
+ # ownable_type :string(255) not null
9
+ #
10
+
11
+ class IdentityFeed < ActiveRecord::Base
12
+ belongs_to :ownable, :polymorphic => true
13
+ belongs_to :feed
14
+
15
+ validates_uniqueness_of :feed_id, :scope => [:ownable_id, :ownable_type]
16
+
17
+ # Determines whether or not he given user can edit the identity feed
18
+ def can_edit?(user)
19
+ if ownable == user || user.admin?
20
+ true
21
+ else
22
+ false
23
+ end
24
+ end
25
+
26
+ end
@@ -0,0 +1,39 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: oai_endpoints
4
+ #
5
+ # id :integer(4) not null, primary key
6
+ # uri :string(2083)
7
+ # display_uri :string(2083)
8
+ # metadata_prefix :string(255)
9
+ # title :string(1000)
10
+ # short_title :string(100)
11
+ #
12
+ class OaiEndpoint < ActiveRecord::Base
13
+
14
+ belongs_to :contributor, :class_name => 'User', :foreign_key => 'contributor_id'
15
+ belongs_to :default_language, :class_name => 'Language', :foreign_key => 'default_language_id'
16
+
17
+ validates_presence_of :uri
18
+
19
+ named_scope :banned, :conditions => "status < 0"
20
+ named_scope :valid, :conditions => "status >= 0"
21
+ named_scope :by_title, :order => "title ASC"
22
+ named_scope :recent, lambda { { :conditions => ['created_at > ?', 1.week.ago] } }
23
+ named_scope :by_newest, :order => "created_at DESC", :include => [:default_language]
24
+
25
+ attr_protected :status, :contributor_id
26
+
27
+ def banned?
28
+ self.status == MuckServices::Status::BANNED
29
+ end
30
+
31
+ def pending?
32
+ self.status == MuckServices::Status::PENDING
33
+ end
34
+
35
+ def inform_admin
36
+ ServicesMailer.deliver_notification_feed_added(self)
37
+ end
38
+
39
+ end
@@ -0,0 +1,15 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: recommendations
4
+ #
5
+ # id :integer(4) not null, primary key
6
+ # entry_id :integer(4)
7
+ # dest_entry_id :integer(4)
8
+ # rank :integer(4)
9
+ # relevance :decimal(8, 6) default(0.0)
10
+ # clicks :integer(4) default(0)
11
+ # avg_time_at_dest :integer(4) default(60)
12
+ #
13
+
14
+ class Recommendation < ActiveRecord::Base
15
+ end
@@ -0,0 +1,486 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: services
4
+ #
5
+ # id :integer(4) not null, primary key
6
+ # uri :string(2083) default("")
7
+ # name :string(1000) default("")
8
+ # api_uri :string(2083) default("")
9
+ # uri_template :string(2083) default("")
10
+ # icon :string(2083) default("rss.gif")
11
+ # sort :integer(4)
12
+ # requires_password :boolean(1)
13
+ # use_for :string(255)
14
+ # service_category_id :integer(4)
15
+ # active :boolean(1) default(TRUE)
16
+ # prompt :string(255)
17
+ # template :string(255)
18
+ #
19
+
20
+ class Service < ActiveRecord::Base
21
+
22
+ belongs_to :service_category
23
+ named_scope :sorted_id, :order => "id ASC"
24
+ named_scope :sorted, :order => "sort ASC"
25
+ named_scope :identity_services, :conditions => ['use_for = ?', 'identity']
26
+ named_scope :tag_services, :conditions => ['use_for = ?', 'tags']
27
+ named_scope :photo_services, :conditions => ["service_categories.id = services.service_category_id AND service_categories.name = 'Photos'"], :include => ['service_category']
28
+
29
+ # Indicates whether service is primarily a photo service ie from flick, picasa, etc
30
+ #
31
+ # refresh_services: Optional parameter indicating whether or not to reload values from the database before checking service type
32
+ def photo?(refresh_services = false)
33
+ Service.get_photo_services(refresh_services).include?(self)
34
+ end
35
+
36
+ # Indicates whether service is primarily a video service ie from youtube, etc
37
+ #
38
+ # refresh_services: Optional parameter indicating whether or not to reload values from the database before checking service type
39
+ def video?(refresh_services = false)
40
+ Service.get_video_services(refresh_services).include?(self)
41
+ end
42
+
43
+ # Indicates whether service is primarily a bookmark service ie delicious, etc
44
+ #
45
+ # refresh_services: Optional parameter indicating whether or not to reload values from the database before checking service type
46
+ def bookmark?(refresh_services = false)
47
+ Service.get_bookmark_services(refresh_services).include?(self)
48
+ end
49
+
50
+ # Indicates whether service is primarily music
51
+ #
52
+ # refresh_services: Optional parameter indicating whether or not to reload values from the database before checking service type
53
+ def music?(refresh_services = false)
54
+ Service.get_music_services(refresh_services).include?(self)
55
+ end
56
+
57
+ # Indicates whether service is primarily news
58
+ #
59
+ # refresh_services: Optional parameter indicating whether or not to reload values from the database before checking service type
60
+ def news?(refresh_services = false)
61
+ Service.get_news_services(refresh_services).include?(self)
62
+ end
63
+
64
+ # Indicates whether service is primarily blog related
65
+ #
66
+ # refresh_services: Optional parameter indicating whether or not to reload values from the database before checking service type
67
+ def blog?(refresh_services = false)
68
+ Service.get_blog_services(refresh_services).include?(self)
69
+ end
70
+
71
+ # Indicates whether service is primarily search related
72
+ #
73
+ # refresh_services: Optional parameter indicating whether or not to reload values from the database before checking service type
74
+ def search?(refresh_services = false)
75
+ Service.get_search_services(refresh_services).include?(self)
76
+ end
77
+
78
+ # Indicates whether service is general (ie not video, photo, music or bookmark)
79
+ #
80
+ # refresh_services: Optional parameter indicating whether or not to reload values from the database before checking service type
81
+ def general?(refresh_services = false)
82
+ Service.get_general_services(refresh_services).include?(self)
83
+ end
84
+
85
+ def human_uri(tag)
86
+ generate_tag_template_uri(tag, self.uri_template)
87
+ end
88
+
89
+ # Generate a uri for the current service
90
+ def generate_tag_uri(tag)
91
+ generate_tag_template_uri(tag, self.uri_data_template)
92
+ end
93
+
94
+ def generate_tag_template_uri(tag, uri_template)
95
+ if self.name == 'Flickr'
96
+ uri_template.sub("{tag}", tag.gsub('+',',')) # flickr wants a comma deliminated list of tags
97
+ else
98
+ uri_template.sub("{tag}", tag)
99
+ end
100
+ end
101
+
102
+ # Requires settings in global_config.yml
103
+ # For example:
104
+ # amazon_access_key_id: 'some key from your account'
105
+ # amazon_secret_access_key: 'the secret from your account'
106
+ # amazon_associate_tag: 'optional'
107
+ # ecs_to_rss_wishlist: "http://www.example.com/ecs_to_rss-wishlist.xslt"
108
+ def generate_uris(username = '', password = '', uri = '')
109
+ if self.name == 'Facebook'
110
+ # Facebook can't just use feeds like everyone else.
111
+ params = {}
112
+ pairs = uri.split('?')[1].split('&')
113
+ pairs.each do |pair|
114
+ p = pair.split('=')
115
+ params[p[0].to_sym] = p[1]
116
+ end
117
+ uris = []
118
+ uris << OpenStruct.new(:url => "http://www.facebook.com/feeds/notifications.php?id=#{params[:id]}&viewer=#{params[:id]}&key=#{params[:key]}&format=rss20", :title => I18n.t('muck.services.facebook_notifications'))
119
+ uris << OpenStruct.new(:url => "http://www.facebook.com/feeds/share_posts.php?id=#{params[:id]}&viewer=#{params[:id]}&key=#{params[:key]}&format=rss20", :title => I18n.t('muck.services.facebook_shares'))
120
+ uris << OpenStruct.new(:url => "http://www.facebook.com/feeds/notes.php?id=#{params[:id]}&viewer=#{params[:id]}&key=#{params[:key]}&format=rss20", :title => I18n.t('muck.services.facebook_notes'))
121
+ uris
122
+ elsif self.name == 'Amazon'
123
+ return [] if username.blank?
124
+ # Have to build and sign Amazon wishlist rss feeds
125
+ am = AmazonRequest.new(GlobalConfig.amazon_access_key_id, GlobalConfig.amazon_secret_access_key, GlobalConfig.ecs_to_rss_wishlist, GlobalConfig.amazon_associate_tag)
126
+ results = am.get_amazon_feeds(username) # username needs to be the user's Amazon email
127
+ results.collect { |result| OpenStruct.new(:url => result, :title => 'Amazon Wishlist') }
128
+ elsif !self.uri_data_template.blank? && !username.blank?
129
+ return [] if username.blank?
130
+ uri = self.uri_data_template.sub("{username}", username)
131
+ Feed.discover_feeds(uri)
132
+ elsif !uri.blank?
133
+ return [] if uri.blank?
134
+ Feed.discover_feeds(uri)
135
+ end
136
+ end
137
+
138
+ # Generates uris for 'tag' using all services where 'use_for' is 'tags'
139
+ def self.generate_tag_uris(terms, selected_service_ids = nil)
140
+ split_terms(terms).collect { |tag|
141
+ get_tag_services(selected_service_ids).collect { |service| service.generate_tag_uri(tag) }
142
+ }.flatten!
143
+ end
144
+
145
+ # creates a feed for a service with a username and optional password
146
+ def self.create_tag_feeds_for_service(service, uri, username, password, contributor)
147
+ uris = service.generate_uris(username, password, uri)
148
+ uris.collect{ |u| Feed.find_or_create(u.url, u.title, username, password, service.id, contributor) } if uris
149
+ end
150
+
151
+
152
+
153
+ def self.build_photo_feeds(terms, user, service_ids = nil, refresh_services = false)
154
+ if service_ids.nil?
155
+ service_ids = get_photo_tag_services(refresh_services).map(&:id)
156
+ else
157
+ service_ids = make_int_array(service_ids) & get_photo_tag_services(refresh_services).map(&:id)
158
+ end
159
+ build_tag_feeds(terms, user, service_ids, refresh_services)
160
+ end
161
+
162
+ def self.build_video_feeds(terms, user, service_ids = nil, refresh_services = false)
163
+ if service_ids.nil?
164
+ service_ids = get_video_tag_services(refresh_services).map(&:id)
165
+ else
166
+ service_ids = make_int_array(service_ids) & get_video_tag_services(refresh_services).map(&:id)
167
+ end
168
+ build_tag_feeds(terms, user, service_ids, refresh_services)
169
+ end
170
+
171
+ def self.build_bookmark_feeds(terms, user, service_ids = nil, refresh_services = false)
172
+ if service_ids.nil?
173
+ service_ids = get_bookmark_tag_services(refresh_services).map(&:id)
174
+ else
175
+ service_ids = make_int_array(service_ids) & get_bookmark_tag_services(refresh_services).map(&:id)
176
+ end
177
+ build_tag_feeds(terms, user, service_ids, refresh_services)
178
+ end
179
+
180
+ def self.build_music_feeds(terms, user, service_ids = nil, refresh_services = false)
181
+ if service_ids.nil?
182
+ service_ids = get_music_tag_services(refresh_services).map(&:id)
183
+ else
184
+ service_ids = make_int_array(service_ids) & get_music_tag_services(refresh_services).map(&:id)
185
+ end
186
+ build_tag_feeds(terms, user, service_ids, refresh_services)
187
+ end
188
+
189
+ def self.build_news_feeds(terms, user, service_ids = nil, refresh_services = false)
190
+ if service_ids.nil?
191
+ service_ids = get_news_tag_services(refresh_services).map(&:id)
192
+ else
193
+ service_ids = make_int_array(service_ids) & get_news_tag_services(refresh_services).map(&:id)
194
+ end
195
+ build_tag_feeds(terms, user, service_ids, refresh_services)
196
+ end
197
+
198
+ def self.build_blog_feeds(terms, user, service_ids = nil, refresh_services = false)
199
+ if service_ids.nil?
200
+ service_ids = get_blog_tag_services(refresh_services).map(&:id)
201
+ else
202
+ service_ids = make_int_array(service_ids) & get_blog_tag_services(refresh_services).map(&:id)
203
+ end
204
+ build_tag_feeds(terms, user, service_ids, refresh_services)
205
+ end
206
+
207
+ def self.build_search_feeds(terms, user, service_ids = nil, refresh_services = false)
208
+ if service_ids.nil?
209
+ service_ids = get_search_tag_services(refresh_services).map(&:id)
210
+ else
211
+ service_ids = make_int_array(service_ids) & get_search_tag_services(refresh_services).map(&:id)
212
+ end
213
+ build_tag_feeds(terms, user, service_ids, refresh_services)
214
+ end
215
+
216
+ def self.build_general_feeds(terms, user, service_ids = nil, refresh_services = false)
217
+ if service_ids.nil?
218
+ service_ids = get_general_tag_services(refresh_services).map(&:id)
219
+ else
220
+ service_ids = make_int_array(service_ids) & get_general_tag_services(refresh_services).map(&:id)
221
+ end
222
+ build_tag_feeds(terms, user, service_ids, refresh_services)
223
+ end
224
+
225
+
226
+
227
+ # Get all photo services
228
+ #
229
+ # refresh_services: By default all tag services are cached. Setting this value to true
230
+ # will result in the values being repopulated from the database
231
+ def self.get_photo_services(refresh_services = false)
232
+ @photo_services = nil if refresh_services
233
+ @photo_services ||= get_services(refresh_services).find_all{|service| service.service_category.name == 'Photos' }
234
+ end
235
+
236
+ # Get all video services
237
+ #
238
+ # refresh_services: By default all tag services are cached. Setting this value to true
239
+ # will result in the values being repopulated from the database
240
+ def self.get_video_services(refresh_services = false)
241
+ @video_services = nil if refresh_services
242
+ @video_services ||= get_services(refresh_services).find_all{|service| service.service_category.name == 'Videos' }
243
+ end
244
+
245
+ # Get all bookmark services
246
+ #
247
+ # refresh_services: By default all tag services are cached. Setting this value to true
248
+ # will result in the values being repopulated from the database
249
+ def self.get_bookmark_services(refresh_services = false)
250
+ @bookmark_services = nil if refresh_services
251
+ @bookmark_services ||= get_services(refresh_services).find_all{|service| service.service_category.name == 'Bookmarks' }
252
+ end
253
+
254
+ # Get all music services
255
+ #
256
+ # refresh_services: By default all tag services are cached. Setting this value to true
257
+ # will result in the values being repopulated from the database
258
+ def self.get_music_services(refresh_services = false)
259
+ @music_services = nil if refresh_services
260
+ @music_services ||= get_services(refresh_services).find_all{|service| service.service_category.name == 'Music' }
261
+ end
262
+
263
+ # Get all news services
264
+ #
265
+ # refresh_services: By default all tag services are cached. Setting this value to true
266
+ # will result in the values being repopulated from the database
267
+ def self.get_news_services(refresh_services = false)
268
+ @news_services = nil if refresh_services
269
+ @news_services ||= get_services(refresh_services).find_all{|service| service.service_category.name == 'News' }
270
+ end
271
+
272
+ # Get all blog services
273
+ #
274
+ # refresh_services: By default all tag services are cached. Setting this value to true
275
+ # will result in the values being repopulated from the database
276
+ def self.get_blog_services(refresh_services = false)
277
+ @blog_services = nil if refresh_services
278
+ @blog_services ||= get_services(refresh_services).find_all{|service| service.service_category.name == 'Blogging' }
279
+ end
280
+
281
+ # Get all search services
282
+ #
283
+ # refresh_services: By default all tag services are cached. Setting this value to true
284
+ # will result in the values being repopulated from the database
285
+ def self.get_search_services(refresh_services = false)
286
+ @search_services = nil if refresh_services
287
+ @search_services ||= get_services(refresh_services).find_all{|service| service.service_category.name == 'Search' }
288
+ end
289
+
290
+ # Get all general services. These are all services except photo, video, bookmark and music.
291
+ #
292
+ # refresh_services: By default all tag services are cached. Setting this value to true
293
+ # will result in the values being repopulated from the database
294
+ def self.get_general_services(refresh_services = false)
295
+ @general_services = nil if refresh_services
296
+ @general_services ||= get_services(refresh_services).find_all{|service| !non_general_categories.include?(service.service_category.name) }
297
+ end
298
+
299
+
300
+
301
+ # Get all photo services that are used to generate tag feeds
302
+ #
303
+ # refresh_services: By default all tag services are cached. Setting this value to true
304
+ # will result in the values being repopulated from the database
305
+ def self.get_photo_tag_services(refresh_services = false)
306
+ @photo_services = nil if refresh_services
307
+ @photo_services ||= get_tag_services(nil, refresh_services).find_all{|service| service.service_category.name == 'Photos' }
308
+ end
309
+
310
+ # Get all video services that are used to generate tag feeds
311
+ #
312
+ # refresh_services: By default all tag services are cached. Setting this value to true
313
+ # will result in the values being repopulated from the database
314
+ def self.get_video_tag_services(refresh_services = false)
315
+ @video_services = nil if refresh_services
316
+ @video_services ||= get_tag_services(nil, refresh_services).find_all{|service| service.service_category.name == 'Videos' }
317
+ end
318
+
319
+ # Get all bookmark services that are used to generate tag feeds
320
+ #
321
+ # refresh_services: By default all tag services are cached. Setting this value to true
322
+ # will result in the values being repopulated from the database
323
+ def self.get_bookmark_tag_services(refresh_services = false)
324
+ @bookmark_services = nil if refresh_services
325
+ @bookmark_services ||= get_tag_services(nil, refresh_services).find_all{|service| service.service_category.name == 'Bookmarks' }
326
+ end
327
+
328
+ # Get all music services that are used to generate tag feeds
329
+ #
330
+ # refresh_services: By default all tag services are cached. Setting this value to true
331
+ # will result in the values being repopulated from the database
332
+ def self.get_music_tag_services(refresh_services = false)
333
+ @music_services = nil if refresh_services
334
+ @music_services ||= get_tag_services(nil, refresh_services).find_all{|service| service.service_category.name == 'Music' }
335
+ end
336
+
337
+ # Get all news services that are used to generate tag feeds
338
+ #
339
+ # refresh_services: By default all tag services are cached. Setting this value to true
340
+ # will result in the values being repopulated from the database
341
+ def self.get_news_tag_services(refresh_services = false)
342
+ @news_services = nil if refresh_services
343
+ @news_services ||= get_tag_services(nil, refresh_services).find_all{|service| service.service_category.name == 'News' }
344
+ end
345
+
346
+ # Get all blog services that are used to generate tag feeds
347
+ #
348
+ # refresh_services: By default all tag services are cached. Setting this value to true
349
+ # will result in the values being repopulated from the database
350
+ def self.get_blog_tag_services(refresh_services = false)
351
+ @blog_services = nil if refresh_services
352
+ @blog_services ||= get_tag_services(nil, refresh_services).find_all{|service| service.service_category.name == 'Blogging' }
353
+ end
354
+
355
+ # Get all search services that are used to generate tag feeds
356
+ #
357
+ # refresh_services: By default all tag services are cached. Setting this value to true
358
+ # will result in the values being repopulated from the database
359
+ def self.get_search_tag_services(refresh_services = false)
360
+ @search_services = nil if refresh_services
361
+ @search_services ||= get_tag_services(nil, refresh_services).find_all{|service| service.service_category.name == 'Search' }
362
+ end
363
+
364
+ # Get all general services that are used to generate tag feeds
365
+ #
366
+ # refresh_services: By default all tag services are cached. Setting this value to true
367
+ # will result in the values being repopulated from the database
368
+ def self.get_general_tag_services(refresh_services = false)
369
+ @general_services = nil if refresh_services
370
+ @general_services ||= get_tag_services(nil, refresh_services).find_all{|service| !non_general_categories.include?(service.service_category.name) }
371
+ end
372
+
373
+
374
+
375
+
376
+ # Builds tag based feeds for the given term. Feeds are not saved to the database.
377
+ #
378
+ # terms: Terms for which to generate feeds. This value can be an array, a single string,
379
+ # or a list of items seperated by a comma.
380
+ # user: User to attach the feed to. This is the feed 'contributor.
381
+ # selected_service_ids: ids for services to select.
382
+ # refresh_services: By default all tag services are cached. Setting this value to true
383
+ # will result in the values being repopulated from the database
384
+ def self.build_tag_feeds(terms, user, selected_service_ids = nil, refresh_services = false)
385
+ services = get_tag_services(selected_service_ids, refresh_services)
386
+ split_terms(terms).collect { |tag|
387
+ services.collect { |service| Feed.new(:uri => service.generate_tag_uri(tag),
388
+ :display_uri => service.human_uri(tag),
389
+ :title => I18n.t('muck.services.service_feed_name', :term => CGI.unescape(tag).humanize, :service => service.name),
390
+ :service_id => service.id,
391
+ :contributor_id => user) }
392
+ }.flatten!
393
+ end
394
+
395
+ # Builds feeds (does not save them to the db) for the given term. Note that this
396
+ # method calls the url for each feed created to attempt auto discovery and so it
397
+ # can take a while to run.
398
+ #
399
+ # terms: Terms for which to generate feeds. This value can be an array, a single string,
400
+ # or a list of items seperated by a comma.
401
+ # user: User to attach the feed to. This is the feed 'contributor.
402
+ # selected_service_ids: ids for services to select.
403
+ def self.build_live_tag_feeds(terms, user, selected_service_ids = nil)
404
+ uris = generate_tag_uris(terms, selected_service_ids)
405
+ feed_uris = uris.collect { |uri| Feed.discover_feeds(uri)}
406
+ feed_uris.collect { |feed| Feed.new(:uri => feed.url,
407
+ :title => feed.title,
408
+ :service_id => service.id,
409
+ :contributor_id => user) }
410
+ end
411
+
412
+ # Create feeds for the given terms and save them to the database.
413
+ # terms: Terms for which to generate feeds. This value can be an array, a single string,
414
+ # or a list of items seperated by a comma.
415
+ # user: User to attach the feed to. This is the feed 'contributor.
416
+ # selected_service_ids: ids for services to select.
417
+ # refresh_services: By default all tag services are cached. Setting this value to true
418
+ # will result in the values being repopulated from the database
419
+ def self.create_tag_feeds(terms, user = nil, selected_service_ids = nil, refresh_services = false)
420
+ services = get_tag_services(selected_service_ids, refresh_services)
421
+ split_terms(terms).collect { |tag|
422
+ services.collect { |service| Feed.find_or_create(service.generate_tag_uri(tag), tag, '', '', service.id, user, service.human_uri(tag)) }
423
+ }.flatten!
424
+ end
425
+
426
+ # Splits terms using a comma. This method also URI encodes all resulting terms
427
+ # terms: A string, array or comma delimited string of terms (tags).
428
+ def self.split_terms(terms)
429
+ return '' if terms.blank?
430
+ terms = terms.split(',') unless terms.is_a?(Array)
431
+ terms.collect { |tag| CGI.escape(tag.strip) }
432
+ end
433
+
434
+ # Gets all services with the specified service ids. If selected_service_ids is not
435
+ # provided then this method will get all tag services
436
+ #
437
+ # selected_service_ids: ids for services to select.
438
+ # refresh_services: By default all tag services are cached. Setting this value to true
439
+ # will result in the values being repopulated from the database
440
+ def self.get_tag_services(selected_service_ids = nil, refresh_services = false)
441
+ if selected_service_ids
442
+ selected_service_ids.collect! { |service_id| service_id.to_i } # make sure the ids are ints
443
+ Service.tag_services.find_all { |service| selected_service_ids.include?(service.id) }
444
+ else
445
+ if refresh_services
446
+ @tag_services = Service.tag_services
447
+ else
448
+ @tag_services ||= Service.tag_services
449
+ end
450
+ end
451
+ end
452
+
453
+ # Selects and caches all services from the database.
454
+ #
455
+ # refresh_services: By default all tag services are cached. Setting this value to true
456
+ # will result in the values being repopulated from the database
457
+ def self.get_services(refresh_services = false)
458
+ @all_services = nil if refresh_services
459
+ @all_services ||= Service.all
460
+ end
461
+
462
+ # Attempts to find a service object using a uri
463
+ #
464
+ # uri: Uri to search for. This method will attempt to all services for any part of the provided uri.
465
+ # refresh_services: Forces a refresh of the services. By default the services are cached for the duration of the request.
466
+ def self.find_service_by_uri(uri, refresh_services = false)
467
+ service = get_services(refresh_services).detect { |service| service.uri && service.uri.length > 0 && (uri.include?(service.uri) || service.uri.include?(uri)) }
468
+ service ||= default_service
469
+ service
470
+ end
471
+
472
+ # Turns all items in an array into integers.
473
+ def self.make_int_array(a)
474
+ a.collect{|i| i.to_i}
475
+ end
476
+
477
+ # Default service is RSS
478
+ def self.default_service
479
+ Service.find_by_name('rss') # this will return the default rss service
480
+ end
481
+
482
+ def self.non_general_categories
483
+ ['Photos', 'Videos', 'Bookmarks', 'Music', 'News', 'Blogging', 'Search']
484
+ end
485
+
486
+ end