/public/lib/stream/streamplugins.js

https://github.com/dotmaster/streamie · JavaScript · 215 lines · 166 code · 21 blank · 28 comment · 13 complexity · 222298e8d1f51e6698cf1625f8073ca9 MD5 · raw file

  1. /*
  2. * List of built in plugins for tweet processing
  3. *
  4. */
  5. require.def("stream/streamplugins",
  6. ["stream/tweet", "stream/twitterRestAPI", "stream/helpers", "text!../templates/tweet.ejs.html"],
  7. function(tweetModule, rest, helpers, templateText) {
  8. var template = _.template(templateText);
  9. var Tweets = {};
  10. var Conversations = {};
  11. var ConversationCounter = 0;
  12. return {
  13. // turns retweets into something similar to tweets
  14. handleRetweet: {
  15. name: "handleRetweet",
  16. func: function (tweet) {
  17. if(tweet.data.retweeted_status) {
  18. var orig = tweet.data;
  19. tweet.data = tweet.data.retweeted_status;
  20. tweet.retweet = orig;
  21. }
  22. this();
  23. }
  24. },
  25. // we only show tweets. No direct messages. For now
  26. tweetsOnly: {
  27. name: "tweetsOnly",
  28. func: function (tweet) {
  29. if(tweet.data.text != null) {
  30. this();
  31. }
  32. }
  33. },
  34. // find all mentions in a tweet. set tweet.mentioned to true if the current user was mentioned
  35. mentions: {
  36. name: "mentions",
  37. func: function (tweet, stream) {
  38. var screen_name = stream.user.screen_name;
  39. tweet.mentions = [];
  40. tweet.data.text.replace(/(^|\W)\@([a-zA-Z0-9_]+)/g, function (match, pre, name) {
  41. if(name == screen_name) {
  42. tweet.mentioned = true;
  43. }
  44. tweet.mentions.push(name);
  45. return match;
  46. });
  47. this();
  48. }
  49. },
  50. // set the tweet template
  51. template: {
  52. name: "template",
  53. func: function (tweet) {
  54. tweet.template = template;
  55. this();
  56. }
  57. },
  58. // render the template (the underscore.js way)
  59. renderTemplate: {
  60. name: "renderTemplate",
  61. func: function (tweet) {
  62. tweet.html = tweet.template({
  63. tweet: tweet,
  64. helpers: helpers
  65. });
  66. this();
  67. }
  68. },
  69. // if a tweet with the name id is in the stream already, do not continue
  70. avoidDuplicates: {
  71. name: "avoidDuplicates",
  72. func: function (tweet, stream) {
  73. var id = tweet.data.id;
  74. if(Tweets[id]) {
  75. // duplicate detected -> do not continue;
  76. } else {
  77. Tweets[id] = tweet;
  78. this();
  79. }
  80. }
  81. },
  82. //
  83. conversations: {
  84. name: "conversations",
  85. func: function (tweet, stream, plugin) {
  86. var id = tweet.data.id;
  87. var in_reply_to = tweet.data.in_reply_to_status_id;
  88. if(Conversations[in_reply_to]) {
  89. tweet.conversation = Conversations[id] = Conversations[in_reply_to];
  90. } else {
  91. tweet.conversation = Conversations[id] = {
  92. index: ConversationCounter++
  93. };
  94. if(in_reply_to) {
  95. Conversations[in_reply_to] = tweet.conversation;
  96. }
  97. }
  98. this();
  99. }
  100. },
  101. // put the tweet into the stream
  102. prepend: {
  103. name: "prepend",
  104. func: function (tweet, stream) {
  105. tweet.node = $(tweet.html);
  106. tweet.node.data("tweet", tweet); // give node access to its tweet
  107. stream.canvas().prepend(tweet.node);
  108. this();
  109. }
  110. },
  111. // htmlencode the text to avoid XSS
  112. htmlEncode: {
  113. name: "htmlEncode",
  114. func: function (tweet, stream) {
  115. var text = tweet.data.text;
  116. text = text.replace(/\&gt\;/g, ">"); // these are preencoded in Twitter tweets
  117. text = text.replace(/\&lt\;/g, "<");
  118. text = helpers.html(text);
  119. tweet.textHTML = text;
  120. this();
  121. }
  122. },
  123. // calculate the age of the tweet and update it
  124. // tweet.created_at now includes an actual Date
  125. age: {
  126. name: "age",
  127. func: function (tweet) {
  128. tweet.created_at = new Date(tweet.data.created_at);
  129. function update () {
  130. tweet.age = (new Date()).getTime() - tweet.created_at.getTime();
  131. tweet.node.find(".created_at").text(Math.round(tweet.age / 1000) + " seconds ago")
  132. }
  133. update();
  134. setInterval(update, 1000)
  135. this();
  136. }
  137. },
  138. // format text to HTML hotlinking, links, things that looks like links, scree names and hash tags
  139. formatTweetText: {
  140. name: "formatTweetText",
  141. func: function (tweet, stream) {
  142. var text = tweet.textHTML;
  143. // links
  144. text = text.replace(/https?:\/\/\S+/ig, function (href) {
  145. return '<a href="'+href+'">'+href+'</a>';
  146. });
  147. // www.google.com style links
  148. text = text.replace(/(^|\s)(www\.\S+)/ig, function (all, pre,www) {
  149. return pre+'<a href="http://'+www+'">'+www+'</a>';
  150. });
  151. // screen names
  152. text = text.replace(/(^|\W)\@([a-zA-Z0-9_]+)/g, function (all, pre, name) {
  153. return pre+'<a href="http://twitter.com/'+name+'" class="user-href">@'+name+'</a>';
  154. });
  155. // hash tags
  156. text = text.replace(/(^|\s)\#(\S+)/g, function (all, pre, tag) {
  157. return pre+'<a href="http://search.twitter.com/search?q='+encodeURIComponent(tag)+'" class="tag">#'+tag+'</a>';
  158. });
  159. tweet.textHTML = text;
  160. this();
  161. }
  162. },
  163. // Trigger a custom event to inform everyone about a new tweet
  164. // Event is not fired for tweet from the prefill
  165. newTweetEvent: {
  166. name: "newTweetEvent",
  167. func: function (tweet) {
  168. // Do not fire for tweets
  169. if(!tweet.data.prefill) {
  170. // { custom-event: tweet:new }
  171. tweet.node.trigger("tweet:new", [tweet])
  172. }
  173. this();
  174. }
  175. },
  176. // when we insert a new tweet
  177. // adjust the scrollTop to show the same thing as before
  178. // we only do this, if the user was not scrolled to the very top
  179. keepScrollState: {
  180. name: "keepScrollState",
  181. func: function (tweet, stream) {
  182. var win = $(window);
  183. var cur = win.scrollTop();
  184. if(cur != 0) {
  185. var next = tweet.node.next()
  186. var top = cur + next.offset().top - tweet.node.offset().top;
  187. win.scrollTop( top );
  188. }
  189. this();
  190. }
  191. }
  192. }
  193. }
  194. );