Sleazy Fork is available in English.

CoomerBtn

Adds a small button next to username handles on Onlyfans and Fansly that points to that users profile at Coomer.su

  1. // ==UserScript==
  2. // @name CoomerBtn
  3. // @namespace http://tampermonkey.net/
  4. // @version 2024-06-18
  5. // @description Adds a small button next to username handles on Onlyfans and Fansly that points to that users profile at Coomer.su
  6. // @author You
  7. // @match https://onlyfans.com/*
  8. // @match https://fansly.com/*
  9. // @icon https://www.google.com/s2/favicons?sz=64&domain=coomer.su
  10. // @grant none
  11. // @license MIT
  12. // ==/UserScript==
  13.  
  14. (function() {
  15. 'use strict';
  16.  
  17. if(location.host !== 'onlyfans.com' && location.host !== 'fansly.com') return;
  18.  
  19. const ofUsernameSelector = '.g-user-username';
  20. const fanslyUsernameSelector = 'span.user-name';
  21. const selector = location.host === 'onlyfans.com' ? ofUsernameSelector : fanslyUsernameSelector
  22. const baseURL = location.host === 'onlyfans.com' ? 'https://coomer.su/onlyfans/user/' : 'https://coomer.su/fansly/user/';
  23. const fanslyUIDCache = [];
  24.  
  25. const addButton = async el => {
  26. if(el.querySelector('.coomer-btn')) return;
  27.  
  28. const img = document.createElement('img');
  29. img.setAttribute('src', 'https://coomer.su/favicon.ico');
  30. img.height = 20;
  31. img.width = 20;
  32.  
  33. const link = document.createElement('a');
  34. link.setAttribute('class', 'coomer-btn');
  35. link.appendChild(img);
  36. el.appendChild(link);
  37.  
  38. let username = el.textContent.trim().slice(1).toLowerCase();
  39.  
  40. if(location.host === 'fansly.com'){
  41. try{
  42. username = await getFanslyUID(username);
  43. }catch(err) {
  44. console.error('CoomerBtn', err); // will still fall back to the username, although coomer.su will likely 404.
  45. }
  46. }
  47.  
  48. link.setAttribute('href', baseURL + username);
  49. }
  50.  
  51. const getFanslyUID = async username => {
  52. const cached = fanslyUIDCache.find(user => user.username === username);
  53.  
  54. if(cached){
  55. return cached.uid;
  56. }
  57.  
  58. const res = await fetch('https://apiv3.fansly.com/api/v1/account?usernames=' + username + '&ngsw-bypass=true');
  59. const json = await res.json();
  60.  
  61. console.log(json);
  62.  
  63. const uid = json.response[0].id
  64. fanslyUIDCache.push({username, uid})
  65.  
  66. return uid;
  67. }
  68.  
  69. const observer = new MutationObserver(muts => {
  70. muts.forEach(mut => {
  71. if(mut.target.matches(selector)){
  72. addButton(mut.target);
  73. }
  74.  
  75. mut.addedNodes && mut.addedNodes.forEach(node => {
  76. if(node.matches && node.matches(selector))
  77. addButton(node)
  78. else{
  79. if(node.nodeType === Node.TEXT_NODE || node.nodeType === Node.COMMENT_NODE) return;
  80. const final = node.querySelectorAll(selector);
  81. final.forEach(child => addButton(child));
  82. }
  83. });
  84. })
  85. });
  86.  
  87.  
  88.  
  89. observer.observe(document, {childList: true, subtree: true});
  90. })();