emacs-detubifier

Replace enshittified URLs like https://youtube.com/ and https://reddit.com/ with nonenshittified front ends.
git clone https://kaka.farm/~git/emacs-detubifier/ or https://codeberg.org/kakafarm/emacs-detubifier/
Log | Files | Refs | LICENSE

detubifier.el (8943B)


      1 ;;; detubifier.el --- Kill text and replace youtube.com and youtu.be or whatever domain with whatever the fuck you want.  -*- lexical-binding: t; -*-
      2 
      3 ;; Copyright (C) 2024  Yuval Langer
      4 
      5 ;; Author: Yuval Langer <yuval.langer@gmail.com>
      6 ;; Version: 0.3.0
      7 ;; Keywords: web, youtube
      8 ;; URL: https://codebarg.org/kakafarm/emacs-detubifier-mode/
      9 
     10 
     11 ;; This program is free software: you can redistribute it and/or modify
     12 ;; it under the terms of the GNU Affero General Public License as
     13 ;; published by the Free Software Foundation, either version 3 of the
     14 ;; License, or (at your option) any later version.
     15 
     16 ;; This program is distributed in the hope that it will be useful,
     17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
     18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     19 ;; GNU Affero General Public License for more details.
     20 
     21 ;; You should have received a copy of the GNU Affero General Public License
     22 ;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
     23 
     24 ;;; Commentary:
     25 
     26 ;; Usage:
     27 ;;
     28 ;; Let's say you have the text
     29 ;; "https://twitter.com/Nadav_Eyal/status/1809975194926055629" and
     30 ;; would rather have something like
     31 ;; "https://nitter.poast.org/Nadav_Eyal/status/1809975194926055629"
     32 ;; instead.  A possible solution is to:
     33 ;;
     34 ;; 0. Set up `detubifier-regexp-replacement-pairs'.
     35 ;; 1. Mark that text.
     36 ;; 2. Kill it.
     37 ;; 3. Run `detubifier-regexp-replacement-pairs'.
     38 ;; 4. Yank it in your chat room.
     39 
     40 ;;; Code:
     41 
     42 (require 'browse-url)
     43 
     44 (defgroup detubifier '()
     45   "Replace the usual enshittified suspects with nonenshittified front end services."
     46   :group 'communcation)
     47 
     48 (defcustom detubifier-regexp-replacement-pairs
     49   `((,(rx "https://www.youtube.com/") . "https://invidious.jing.rocks/")
     50     (,(rx "https://youtube.com/") . "https://invidious.jing.rocks/")
     51     (,(rx "https://youtu.be/") . "https://invidious.jing.rocks/watch?v=")
     52     (,(rx "https://twitter.com/") . "https://nitter.poast.org/")
     53     (,(rx "https://x.com/") . "https://farside.link/"))
     54   "List of pairs, each with a regexp and its replacement."
     55   :type '(repeat (cons regexp string))
     56   :group 'detubifier
     57   )
     58 
     59 (defcustom detubifier-farside-url
     60   "https://farside.link/"
     61   "Base address to the farside service."
     62   :type 'string
     63   :group 'detubifier
     64   )
     65 
     66 (defcustom detubifier-detubifying-method
     67   'farside
     68   "Method of detubifying."
     69   :type '(radio (symbol farside)
     70                 (symbol custom))
     71   :group 'detubifier
     72   )
     73 
     74 (defcustom detubifier-enshittified-urls
     75   '(
     76     "https://reddit.com/"
     77     "https://twitter.com/"
     78     "https://www.reddit.com/"
     79     "https://www.twitter.com/"
     80     "https://www.youtube.com/"
     81     "https://x.com/"
     82     "https://youtu.be/"
     83     "https://youtube.com/"
     84     "https://github.com"
     85     )
     86   "URLs of enshittified services."
     87   :type '(repeat string)
     88   :group 'detubifier
     89   )
     90 
     91 ;;;###autoload
     92 (defun detubifier-browse-url (url &rest args)
     93   "Open URL using `browse-url' with the usual suspect URLs replaced.
     94 
     95 Replace the usual suspect URLs with the method chosen by the
     96 `detubifier-detubifying-method' custom variable.
     97 
     98 ARGS is passed as the ARGS of `browse-url'.
     99 
    100 TODO: What are args in `browse-url'?"
    101 
    102   (interactive (browse-url-interactive-arg "URL: "))
    103 
    104   (pcase detubifier-detubifying-method
    105     ('farside (browse-url (detubifier-farsidify-string url) args))
    106     ('custom (browse-url (detubifier-custom-detubify-string url) args))))
    107 
    108 ;;;###autoload
    109 (defun detubifier-custom-detubify-region (beg end)
    110   "Replace the usual suspect URLs in region.
    111 
    112 Region is defined either by (region-beginning) and (region-end),
    113 or, if provided, between between BEG and END.
    114 
    115 Use custom variable `detubifier-regexp-replacement-pairs' to do so."
    116 
    117   (interactive (list (region-beginning)
    118                      (region-end)))
    119 
    120   (save-excursion
    121     (pcase-dolist (`(,current-regexp . ,current-replacement)
    122                    detubifier-regexp-replacement-pairs)
    123       (replace-regexp-in-region current-regexp
    124                                 current-replacement
    125                                 beg
    126                                 end))))
    127 
    128 ;;;###autoload
    129 (defun detubifier-custom-detubify-string (str)
    130   "Replace the usual suspect URLs in string STR.
    131 
    132 Use custom variable `detubifier-regexp-replacement-pairs' to do so."
    133 
    134   (let ((str str))
    135     (pcase-dolist (`(,current-regexp . ,current-replacement)
    136                    detubifier-regexp-replacement-pairs)
    137       (setq str (replace-regexp-in-string current-regexp
    138                                           current-replacement
    139                                           str)))
    140     str))
    141 
    142 ;;;###autoload
    143 (defun detubifier-detubify-top-kill ()
    144   "Replace all occurances of the usual suspects in the top of the kill ring.
    145 
    146 Use the method chosen by the `detubifier-detubifying-method' custom variable."
    147 
    148   (interactive)
    149 
    150   (save-excursion
    151     (with-temp-buffer
    152       (yank)
    153       (goto-char (point-min))
    154       (pcase detubifier-detubifying-method
    155         ('farside (detubifier-farsidify-region (point-min) (point-max)))
    156         ('custom (detubifier-custom-detubify-region (point-min) (point-max))))
    157       (kill-region (point-min) (point-max))))
    158   )
    159 
    160 ;;;###autoload
    161 (defun detubifier-farsidify-region (beg end)
    162   "Prefix `detubifier-farside-url' the usual suspect URLs in a region.
    163 
    164 Region is defined either by (region-beginning) and (region-end),
    165 or, if provided, between between BEG and END.
    166 
    167 The usual suspects are replaced in this way:
    168 
    169   example.com/blah/blah
    170 
    171 is replaced with:
    172 
    173   https://farside.link/example.com/blah/blah"
    174 
    175   (interactive (list (region-beginning)
    176                      (region-end)))
    177 
    178   (save-excursion
    179     (save-restriction ;; Save narrowing setting and revert to it when finishing.
    180       (narrow-to-region beg end)
    181       (rx-let-eval `((urls () (group (or ,@detubifier-enshittified-urls))))
    182         (let ((r (rx-to-string '(urls))))
    183           (replace-regexp-in-region r
    184                                     (concat detubifier-farside-url "\\1")
    185                                     beg
    186                                     end))))))
    187 
    188 ;;;###autoload
    189 (defun detubifier-farsidify-string (str)
    190   "Prefix `detubifier-farside-url' the usual suspects URLs in string STR."
    191 
    192   (rx-let-eval `((urls () (group (or ,@detubifier-enshittified-urls))))
    193     (replace-regexp-in-string (rx-to-string '(urls))
    194                               (concat detubifier-farside-url "\\1")
    195                               str))
    196   )
    197 
    198 (define-obsolete-function-alias
    199   'detubifier-replace-contents
    200   'detubifier-detubify-top-kill
    201   "2024-09-25")
    202 
    203 ;;; Testing:
    204 
    205 (ert-deftest test-detubifier-farsidify-string ()
    206   "Test `detubifier-farsidify-string'."
    207   (should (equal (detubifier-farsidify-string "sdfljdsf sdfkjl https://youtube.com/moo
    208 https://twitter.com/blah")
    209                  (concat "sdfljdsf sdfkjl "
    210                          detubifier-farside-url
    211                          "https://youtube.com/moo
    212 "
    213                          detubifier-farside-url
    214                          "https://twitter.com/blah"))))
    215 
    216 (ert-deftest test-detubifier-farsidify-region ()
    217   "Test `detubifier-farsidify-region'."
    218   (with-temp-buffer
    219     (should (equal (let ()
    220                      (insert "sdfljdsf sdfkjl https://youtube.com/moo
    221 https://twitter.com/blah")
    222                      (detubifier-farsidify-region (point-min)
    223                                                   (point-max))
    224                      (buffer-substring-no-properties (point-min)
    225                                                      (point-max)))
    226                    (concat "sdfljdsf sdfkjl "
    227                            detubifier-farside-url
    228                            "https://youtube.com/moo
    229 "
    230                            detubifier-farside-url
    231                            "https://twitter.com/blah")))))
    232 
    233 (ert-deftest test-detubifier-custom-detubify-string ()
    234   "Test `detubifier-custom-detubify-string'.
    235 
    236 TODO: Test only works with the default `detubifier-regexp-replacement-pairs'.
    237 Make it work in general!"
    238   (should (equal (detubifier-custom-detubify-string "sdfljdsf sdfkjl https://youtube.com/moo
    239 https://twitter.com/blah")
    240                  (concat "sdfljdsf sdfkjl https://invidious.jing.rocks/moo
    241 https://nitter.poast.org/blah"))))
    242 
    243 (ert-deftest test-detubifier-custom-detubify-region ()
    244   "Test `detubifier-custom-detubify-region'.
    245 
    246 TODO: Test only works with the default `detubifier-regexp-replacement-pairs'.
    247 Make it work in general!"
    248   (with-temp-buffer
    249     (should (equal (let ()
    250                      (insert "sdfljdsf sdfkjl https://youtube.com/moo
    251 https://twitter.com/blah")
    252                      (detubifier-custom-detubify-region (point-min)
    253                                                         (point-max))
    254                      (buffer-substring-no-properties (point-min)
    255                                                      (point-max)))
    256                    (concat "sdfljdsf sdfkjl https://invidious.jing.rocks/moo
    257 https://nitter.poast.org/blah")))))
    258 
    259 (provide 'detubifier)
    260 ;;; detubifier.el ends here