sensitivecontent.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. window.buildAttachmentHTML = function (attachments) {
  2. let attachmentHTML = '';
  3. let oembedHTML = '';
  4. const quotedNotices = [];
  5. let attachmentNum = 0;
  6. let oembedNum = 0;
  7. const urlsToHide = [];
  8. if (typeof attachments != "undefined") {
  9. $.each(attachments, function () {
  10. // quoted notices
  11. if (typeof this.quoted_notice != 'undefined') {
  12. let quotedContent = this.quoted_notice.content;
  13. // quoted notice's attachments' thumb urls
  14. let quotedAttachmentsHTML = '';
  15. let quotedAttachmentsHTMLbefore = '';
  16. let quotedAttachmentsHTMLafter = '';
  17. if (typeof this.quoted_notice.attachments != 'undefined' && this.quoted_notice.attachments.length > 0) {
  18. quotedAttachmentsHTML += '<div class="quoted-notice-attachments quoted-notice-attachments-num-' + this.quoted_notice.attachments.length + '">';
  19. $.each(this.quoted_notice.attachments, function (k, qAttach) {
  20. quotedAttachmentsHTML += '<div class="quoted-notice-img-container" style="background-image:url(\'' + qAttach.thumb_url + '\')"><img class="quoted-notice-img" src="' + qAttach.thumb_url + '" /></div>';
  21. // remove attachment string from content
  22. quotedContent = quotedContent.split(window.siteInstanceURL + 'attachment/' + qAttach.attachment_id).join('');
  23. });
  24. quotedAttachmentsHTML += '</div>';
  25. // if there is only one attachment, it goes before, otherwise after
  26. if (this.quoted_notice.attachments.length == 1) {
  27. quotedAttachmentsHTMLbefore = quotedAttachmentsHTML;
  28. } else {
  29. quotedAttachmentsHTMLafter = quotedAttachmentsHTML;
  30. }
  31. }
  32. const quotedNoticeHTML = quotedAttachmentsHTMLbefore + '\
  33. <div class="quoted-notice-header">\
  34. <span class="quoted-notice-author-fullname">' + this.quoted_notice.fullname + '</span>\
  35. <span class="quoted-notice-author-nickname">' + this.quoted_notice.nickname + '</span>\
  36. </div>\
  37. <div class="quoted-notice-body">' + $.trim(quotedContent) + '</div>\
  38. ' + quotedAttachmentsHTMLafter;
  39. quotedNotices.push({
  40. url: this.url,
  41. html: quotedNoticeHTML,
  42. href: window.siteInstanceURL + 'notice/' + this.quoted_notice.id,
  43. class: 'quoted-notice'
  44. });
  45. }
  46. // if we have Twitter oembed data, we add is as quotes
  47. else if (typeof this.oembed != 'undefined'
  48. && this.oembed !== false
  49. && this.oembed.provider == 'Twitter') {
  50. const twitterHTML = '<div class="oembed-item-header">\
  51. <span class="oembed-item-title">' + this.oembed.author_name + '</span>\
  52. <span class="oembed-username">' + this.oembed.title + '</span>\
  53. </div>\
  54. <div class="oembed-item-body">' + this.oembed.oembedHTML + '</div>\
  55. <div class="oembed-item-footer">\
  56. <span class="oembed-item-provider">' + this.oembed.provider + '</span>\
  57. </div>';
  58. quotedNotices.push({
  59. url: this.url,
  60. html: twitterHTML,
  61. href: this.url,
  62. class: 'oembed-item'
  63. });
  64. }
  65. // if we have other oembed data (but not for photos and youtube, we handle those later)
  66. else if (typeof this.oembed != 'undefined'
  67. && this.oembed !== false
  68. && this.oembed.title !== null
  69. && this.oembed.provider != 'YouTube'
  70. && this.oembed.provider != 'Vimeo'
  71. && this.oembed.type != 'photo') {
  72. let oembedImage = '';
  73. // only local images
  74. if (typeof this.thumb_url != 'undefined'
  75. && this.thumb_url !== null
  76. && isLocalURL(this.thumb_url)) {
  77. oembedImage = '<div class="oembed-img-container" style="background-image:url(\'' + this.thumb_url + '\')"><img class="oembed-img" src="' + this.thumb_url + '" /></div>';
  78. }
  79. let oembedBody = '';
  80. // don't add body if html it's too similar (80%) to the title (wordpress does this..)
  81. if (this.oembed.oembedHTML !== null
  82. && this.oembed.oembedHTML.length > 0) {
  83. if (this.oembed.oembedHTML.length > 200) {
  84. this.oembed.oembedHTML = this.oembed.oembedHTML.substring(0, 200) + '…';
  85. }
  86. if (stringSimilarity(this.oembed.oembedHTML, this.oembed.title.substring(0, 200)) < 80) {
  87. oembedBody = this.oembed.oembedHTML;
  88. }
  89. }
  90. if (this.oembed.provider === null) {
  91. var oembedProvider = this.url;
  92. var oembedProviderURL = '';
  93. } else {
  94. var oembedProvider = this.oembed.provider;
  95. var oembedProviderURL = removeProtocolFromUrl(this.oembed.provider_url);
  96. // remove trailing /
  97. if (oembedProviderURL.slice(-1) == '/') {
  98. oembedProviderURL = oembedProviderURL.slice(0, -1);
  99. }
  100. }
  101. // If the oembed data is generated by Qvitter, we know a better way of showing the title
  102. const oembedTitle = this.oembed.title;
  103. let oembedTitleHTML = '<span class="oembed-item-title">' + oembedTitle + '</span>';
  104. if (oembedTitle.slice(-10) == ' (Qvitter)') {
  105. const oembedTimePosted = parseTwitterLongDate(oembedTitle.slice(0, -10));
  106. const oembedGNUsocialUsername = this.oembed.author_name.substring(this.oembed.author_name.lastIndexOf('(') + 1, this.oembed.author_name.lastIndexOf(')'));
  107. const oembedGNUsocialFullname = this.oembed.author_name.slice(0, -(oembedGNUsocialUsername.length + 3));
  108. oembedTitleHTML = '<span class="oembed-item-title">' + oembedGNUsocialFullname + '</span>\
  109. <span class="oembed-username">@' + oembedGNUsocialUsername + '</span>';
  110. }
  111. oembedHTML += '<a href="' + this.url + '" class="oembed-item">\
  112. ' + oembedImage + '\
  113. <div class="oembed-item-header">\
  114. ' + oembedTitleHTML + '\
  115. </div>\
  116. <div class="oembed-item-body">' + oembedBody + '</div>\
  117. <div class="oembed-item-footer">\
  118. <span class="oembed-item-provider">' + oembedProvider + '</span>\
  119. <span class="oembed-item-provider-url">' + oembedProviderURL + '</span>\
  120. </div>\
  121. </a>';
  122. oembedNum++;
  123. }
  124. // if there's a local thumb_url we assume this is a image or video
  125. else if (typeof this.thumb_url != 'undefined'
  126. && this.thumb_url !== null
  127. && isLocalURL(this.thumb_url)) {
  128. let bigThumbW = 1000;
  129. let bigThumbH = 3000;
  130. if (bigThumbW > window.siteMaxThumbnailSize) {
  131. bigThumbW = window.siteMaxThumbnailSize;
  132. }
  133. if (bigThumbH > window.siteMaxThumbnailSize) {
  134. bigThumbH = window.siteMaxThumbnailSize;
  135. }
  136. // very long landscape images should not have background-size:cover
  137. let noCoverClass = '';
  138. if (this.width / this.height > 2) {
  139. noCoverClass = ' no-cover';
  140. }
  141. // play button for videos and animated gifs
  142. let playButtonClass = '';
  143. if (typeof this.animated != 'undefined' && this.animated === true
  144. || (this.url.indexOf('://www.youtube.com') > -1 || this.url.indexOf('://youtu.be') > -1)
  145. || this.url.indexOf('://vimeo.com') > -1) {
  146. playButtonClass = ' play-button';
  147. }
  148. // gif-class
  149. var animatedGifClass = '';
  150. if (typeof this.animated != 'undefined' && this.animated === true) {
  151. var animatedGifClass = ' animated-gif';
  152. }
  153. // animated gifs always get default small non-animated thumbnail
  154. if (this.animated === true) {
  155. var img_url = this.thumb_url;
  156. }
  157. // if no dimensions are set, go with default thumb
  158. else if (this.width === null && this.height === null) {
  159. var img_url = this.thumb_url;
  160. }
  161. // large images get large thumbnail
  162. else if (this.width > 1000) {
  163. var img_url = this.large_thumb_url;
  164. }
  165. // no thumbnails for small local images
  166. else if (this.url.indexOf(window.siteInstanceURL) === 0) {
  167. var img_url = this.url;
  168. }
  169. // small thumbnail for small remote images
  170. else {
  171. var img_url = this.thumb_url;
  172. }
  173. var urlToHide = window.siteInstanceURL + 'attachment/' + this.id;
  174. attachmentHTML += '<a data-local-attachment-url="' + urlToHide + '" style="background-image:url(\'' + img_url + '\')" class="thumb-container' + noCoverClass + playButtonClass + animatedGifClass + ' ' + CSSclassNameByHostFromURL(this.url) + '" href="' + this.url + '"><img class="attachment-thumb" data-mime-type="' + this.mimetype + '" src="' + img_url + '"/ data-width="' + this.width + '" data-height="' + this.height + '" data-full-image-url="' + this.url + '" data-thumb-url="' + img_url + '"></a>';
  175. urlsToHide.push(urlToHide); // hide this attachment url from the queet text
  176. attachmentNum++;
  177. } else if (this.mimetype == 'image/svg+xml') {
  178. var urlToHide = window.siteInstanceURL + 'attachment/' + this.id;
  179. attachmentHTML += '<a data-local-attachment-url="' + urlToHide + '" style="background-image:url(\'' + this.url + '\')" class="thumb-container" href="' + this.url + '"><img class="attachment-thumb" data-mime-type="' + this.mimetype + '" src="' + this.url + '"/></a>';
  180. urlsToHide.push(urlToHide); // hide this attachment url from the queet text
  181. attachmentNum++;
  182. }
  183. });
  184. }
  185. return {
  186. html: '<div class="oembed-data oembed-num-' + oembedNum + '">' + oembedHTML + '</div><div class="queet-thumbs thumb-num-' + attachmentNum + '"><div class="sensitive-blocker">&nbsp;</div>' + attachmentHTML + '</div>',
  187. urlsToHide: urlsToHide,
  188. quotedNotices: quotedNotices
  189. };
  190. };
  191. window.sensitiveContentOriginalBuildQueetHtml = window.buildQueetHtml;
  192. window.buildQueetHtml = function (obj, idInStream, extraClasses, requeeted_by, isConversation) {
  193. //add tags to json if they don't exit
  194. if (obj.tags && obj.tags.length > 0) {
  195. for (let tagI = 0; tagI < obj.tags.length; ++tagI) {
  196. extraClasses += (' data-tag-' + obj.tags[tagI]);
  197. if (window.loggedIn.hide_sensitive && obj.tags[tagI] === 'nsfw') extraClasses += ' sensitive-notice';
  198. }
  199. }
  200. return window.sensitiveContentOriginalBuildQueetHtml(obj, idInStream, extraClasses, requeeted_by, isConversation);
  201. };