Greasy Fork is available in English.

Tellonym.me Guest

Load tellonym.me Tells without Login

  1. // ==UserScript==
  2. // @name Tellonym.me Guest
  3. // @name:de Tellonym.me Gast
  4. // @version 1.1.0
  5. // @description Load tellonym.me Tells without Login
  6. // @description:de Lade tellonym.me Tells ohne Anmeldung
  7. // @icon https://www2.tellonym.me/assets/img/icon64x64.png
  8. // @author TalkLounge (https://github.com/TalkLounge)
  9. // @namespace https://github.com/TalkLounge/tellonym.me-guest
  10. // @supportURL https://github.com/TalkLounge/tellonym.me-guest/issues
  11. // @license MIT
  12. // @match https://tellonym.me/*
  13. // @require https://cdn.jsdelivr.net/npm/axios@0.24.0/dist/axios.min.js
  14. // @require https://cdn.jsdelivr.net/npm/luxon@2.3.0/build/global/luxon.min.js
  15. // @grant none
  16. // ==/UserScript==
  17.  
  18. /*
  19. Text Examples:
  20.  
  21. Context, Comments & Sender: https://tellonym.me/avgx.wvmx/answer/4468890875
  22. Image: https://tellonym.me/avgx.wvmx/answer/4196788015
  23. */
  24.  
  25. (function () {
  26. 'use strict';
  27. let initInterval, ul, user, pos, scrollLoading, initTimeout, scrollEnded, url;
  28.  
  29. async function loadTells() {
  30. let data = await axios.get(`https://api.tellonym.me/profiles/name/${user}?limit=25&pos=${pos}`);
  31. data = data.data;
  32. const answers = data.answers;
  33.  
  34. if (!answers.length) {
  35. scrollEnded = true;
  36. return;
  37. }
  38.  
  39. for (let i = 0; i < answers.length; i++) {
  40. if (answers[i].type == "AD") { // Do not display ads
  41. continue;
  42. }
  43.  
  44. console.log("[Tellonym.me Guest]", answers[i]);
  45.  
  46. pos++;
  47. ul.insertAdjacentHTML("beforeend", `<div style="background-color: white; padding: 16px; border-radius: 8px; margin-bottom: 8px" id="${answers[i].id}">
  48. <a style="float: right; text-decoration: none; color: black" href="https://tellonym.me/${user}/answer/${answers[i].id}" target="_blank">
  49. <i class="icon-share"></i>
  50. </a>
  51. <div style="display: flex; align-items: center">
  52. <div>
  53. <img style="height: 38px; border-radius: 8px" src="https://userimg.tellonym.me/xs-v2/${data.avatarFileName}">
  54. </div>
  55. <div style="margin-left: 12px">
  56. <span style="font-weight: bold; font-size: 14px">${user}</span>
  57. ${(() => { // Verified
  58. if (data.isVerified) {
  59. return `<img style="filter: invert(39%) sepia(88%) saturate(1949%) hue-rotate(191deg) brightness(100%) contrast(105%); height: 12px" src="https://www2.tellonym.me/assets/img/verified.png">`;
  60. }
  61.  
  62. return "";
  63. })()}
  64. <br>
  65. <span style="color: grey; font-size: 12px">${luxon.DateTime.fromISO(answers[i].createdAt).toRelative()}</span>
  66. </div>
  67. </div>
  68. ${(() => { // Context
  69. if (answers[i].parent) {
  70. return `<div style="margin-top: 12px" class="context">
  71. <a style="background-color: rgb(243, 243, 243); border-radius: 10px; padding: 2px 10px; font-size: 12px; text-decoration: none; color: black; display: block; max-width: 150px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; width: min-content" href="https://tellonym.me/${user}/answer/${answers[i].parent.id}" target="_blank">${answers[i].parent.content}</a>
  72. </div>`;
  73. }
  74.  
  75. return "";
  76. })()}
  77. <div style="border-left: 3px solid rgb(136, 137, 143); margin-top: 12px">
  78. <div style="margin-left: 12px; display: flex">
  79. ${(() => { // Sender
  80. if (answers[i].sender?.username) {
  81. return `<a style="text-decoration: none; color: black; margin-top: 1px" href="https://tellonym.me/${answers[i].sender.username}" target="_blank">
  82. <div style="display: inline-block">
  83. <img style="height: 16px; border-radius: 4px; margin-right: 4px" src="https://userimg.tellonym.me/xs-v2/${answers[i].sender.avatarFileName}">
  84. </div>
  85. <span style="font-weight: bold; font-size: 14px; margin-right: 4px; vertical-align: top">${answers[i].sender.username}</span>
  86. </a>`;
  87. }
  88.  
  89. return "";
  90. })()}
  91. <span>${answers[i].tell}</span>
  92. </div>
  93. </div>
  94. <div style="margin-top: 12px">
  95. <span>${answers[i].answer}</span>
  96. </div>
  97. ${(() => { // Media
  98. let inject = "";
  99.  
  100. for (let j = 0; j < answers[i].media.length; j++) {
  101. if (answers[i].media[j].type == 0) {
  102. inject += `<div style="margin-top: 12px">
  103. <a href="${answers[i].media[j].url}" target="_blank">
  104. <img src="${answers[i].media[j].thumbUrl}">
  105. </a>
  106. </div>`;
  107. }
  108.  
  109. if (answers[i].media[j].type != 0 || !answers[i].media[j].url.endsWith(".jpg")) {
  110. alert("[Tellonym.me Guest Userscript]\n\nCongratulations, you have found a tell with media files that the userscript doesn't currently support.\nWith your help I can implement this in the userscript.\nTherefore I kindly ask you to report this URL\n\nhttps://tellonym.me/${user}/answer/${answers[i].id}\n\nto one of these:\n\nhttps://github.com/TalkLounge/tellonym.me-guest/issues\n\nhttps://greatest.deepsurf.us/de/scripts/438008-tellonym-me-guest/feedback\n\nMail to talklounge@yahoo.de\n\n\nThank you so much!");
  111. }
  112. }
  113.  
  114. return inject;
  115. })()}
  116. <div style="margin-top: 12px">
  117. <div style="width: 32px; display: inline-block">
  118. <img style="height: 22px" src="https://www2.tellonym.me/assets/img/reactions/heart_unfilled.png">
  119. </div>
  120. <div style="width: 32px; display: inline-block">
  121. <img style="height: 22px" src="https://www2.tellonym.me/assets/img/reactions/crying_unfilled.png">
  122. </div>
  123. <div style="width: 32px; display: inline-block">
  124. <img style="height: 22px" src="https://www2.tellonym.me/assets/img/reactions/laugh_unfilled.png">
  125. </div>
  126. </div>
  127. ${(() => { // Comments
  128. let comments = "";
  129.  
  130. if (answers[i].comments?.previews?.length) {
  131. for (let j = 0; j < answers[i].comments.previews.length; j++) {
  132. comments += `<div style="margin-top: 12px; display: flex; align-items: center">
  133. <a style="text-decoration: none; color: black; display: flex; margin-top: 1px" href="https://tellonym.me/${answers[i].comments.previews[j].user.username}" target="_blank">
  134. <div style="height: 22px">
  135. <img style="height: 22px; border-radius: 4px; margin-right: 8px" src="https://userimg.tellonym.me/xs-v2/${answers[i].comments.previews[j].user.avatarFileName}">
  136. </div>
  137. <span style="font-weight: bold; font-size: 14px; align-self: center">${answers[i].comments.previews[j].user.username}</span>
  138. </a>
  139. <span style="margin-left: 4px">${answers[i].comments.previews[j].content}</span>
  140. </div>`;
  141. }
  142. }
  143.  
  144. return comments;
  145. })()}
  146. </div>`);
  147.  
  148. [...document.querySelectorAll(`.context a[href^="https://tellonym.me/${user}/answer/${answers[i].id}"]`)].forEach(item => { item.href = `#${answers[i].id}`; item.target = ""; }); // Skip to context instead of opening, when loaded already
  149.  
  150. if (answers[i].likesCount || answers[i].likes?.count) {
  151. alert(`[Tellonym.me Guest Userscript]\n\nCongratulations, you have found a tell with likes that the userscript doesn't currently support.\nWith your help I can implement this in the userscript.\nTherefore I kindly ask you to report this URL\n\nhttps://tellonym.me/${user}/answer/${answers[i].id}\n\nto one of these:\n\nhttps://github.com/TalkLounge/tellonym.me-guest/issues\n\nhttps://greatest.deepsurf.us/de/scripts/438008-tellonym-me-guest/feedback\n\nMail to talklounge@yahoo.de\n\n\nThank you so much!`);
  152. }
  153. }
  154. }
  155.  
  156. async function onScroll() { // Load new tells, if near page end
  157. const last10 = ul.childNodes[ul.childNodes.length - 10]; // 10th last child
  158. if (last10.getBoundingClientRect().top <= document.body.clientHeight && !scrollLoading && !scrollEnded) {
  159. scrollLoading = true;
  160.  
  161. await loadTells();
  162.  
  163. scrollLoading = undefined;
  164. }
  165. }
  166.  
  167. async function init() {
  168. ul = [...document.querySelectorAll("img[src^='https://user']")].reverse()[0]; // Last custom profile picture in tell
  169. ul = ul || [...document.querySelectorAll("svg[height='38']")].reverse()[0]?.parentNode; // Last generic profile picture in tell
  170.  
  171. if (!ul) {
  172. initTimeout++;
  173.  
  174. if (initTimeout >= 20) { // Timeout after 5 seconds (4 per second * 5 = 20)
  175. console.log("[Tellonym.me Guest]", "Page Timeout");
  176. window.clearInterval(initInterval);
  177. }
  178.  
  179. return;
  180. }
  181.  
  182. window.clearInterval(initInterval);
  183.  
  184. ul = ul.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode;
  185. console.log(ul);
  186.  
  187. await new Promise(r => setTimeout(r, 250)); // Thanks to https://stackoverflow.com/a/39914235
  188. [...ul.childNodes].splice(1).forEach(item => item.remove()); // Remove initial loaded tells
  189.  
  190. user = window.location.pathname.split("/")[1];
  191.  
  192. await loadTells();
  193.  
  194. window.addEventListener("scroll", onScroll);
  195.  
  196. for (let i = 0; i < 20; i++) {
  197. document.querySelector("img[src*=appstore]")?.parentNode.parentNode.parentNode.parentNode.parentNode.remove(); // Remove Appstore Banner
  198. await new Promise(r => setTimeout(r, 500));
  199. }
  200. }
  201.  
  202. function checkNavigate() {
  203. if (url == window.location.origin + window.location.pathname) { // Not navigated
  204. return;
  205. }
  206.  
  207. url = window.location.origin + window.location.pathname;
  208.  
  209. if (["/search", "/login"].includes(window.location.pathname)) { // Not a user profile
  210. return;
  211. }
  212.  
  213. // Reset variables
  214. pos = 0;
  215. scrollLoading = undefined;
  216. initTimeout = 0;
  217. scrollEnded = undefined;
  218.  
  219. initInterval = window.setInterval(init, 250);
  220. }
  221.  
  222. checkNavigate();
  223. window.setInterval(checkNavigate, 1000);
  224. })();