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 (8918B)


      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     )
     85   "URLs of enshittified services."
     86   :type '(repeat string)
     87   :group 'detubifier
     88   )
     89 
     90 ;;;###autoload
     91 (defun detubifier-browse-url (url &rest args)
     92   "Open URL using `browse-url' with the usual suspect URLs replaced.
     93 
     94 Replace the usual suspect URLs with the method chosen by the
     95 `detubifier-detubifying-method' custom variable.
     96 
     97 ARGS is passed as the ARGS of `browse-url'.
     98 
     99 TODO: What are args in `browse-url'?"
    100 
    101   (interactive (browse-url-interactive-arg "URL: "))
    102 
    103   (pcase detubifier-detubifying-method
    104     ('farside (browse-url (detubifier-farsidify-string url) args))
    105     ('custom (browse-url (detubifier-custom-detubify-string url) args))))
    106 
    107 ;;;###autoload
    108 (defun detubifier-custom-detubify-region (beg end)
    109   "Replace the usual suspect URLs in region.
    110 
    111 Region is defined either by (region-beginning) and (region-end),
    112 or, if provided, between between BEG and END.
    113 
    114 Use custom variable `detubifier-regexp-replacement-pairs' to do so."
    115 
    116   (interactive (list (region-beginning)
    117                      (region-end)))
    118 
    119   (save-excursion
    120     (pcase-dolist (`(,current-regexp . ,current-replacement)
    121                    detubifier-regexp-replacement-pairs)
    122       (replace-regexp-in-region current-regexp
    123                                 current-replacement
    124                                 beg
    125                                 end))))
    126 
    127 ;;;###autoload
    128 (defun detubifier-custom-detubify-string (str)
    129   "Replace the usual suspect URLs in string STR.
    130 
    131 Use custom variable `detubifier-regexp-replacement-pairs' to do so."
    132 
    133   (let ((str str))
    134     (pcase-dolist (`(,current-regexp . ,current-replacement)
    135                    detubifier-regexp-replacement-pairs)
    136       (setq str (replace-regexp-in-string current-regexp
    137                                           current-replacement
    138                                           str)))
    139     str))
    140 
    141 ;;;###autoload
    142 (defun detubifier-detubify-top-kill ()
    143   "Replace all occurances of the usual suspects in the top of the kill ring.
    144 
    145 Use the method chosen by the `detubifier-detubifying-method' custom variable."
    146 
    147   (interactive)
    148 
    149   (save-excursion
    150     (with-temp-buffer
    151       (yank)
    152       (goto-char (point-min))
    153       (pcase detubifier-detubifying-method
    154         ('farside (detubifier-farsidify-region (point-min) (point-max)))
    155         ('custom (detubifier-custom-detubify-region (point-min) (point-max))))
    156       (kill-region (point-min) (point-max))))
    157   )
    158 
    159 ;;;###autoload
    160 (defun detubifier-farsidify-region (beg end)
    161   "Prefix `detubifier-farside-url' the usual suspect URLs in a region.
    162 
    163 Region is defined either by (region-beginning) and (region-end),
    164 or, if provided, between between BEG and END.
    165 
    166 The usual suspects are replaced in this way:
    167 
    168   example.com/blah/blah
    169 
    170 is replaced with:
    171 
    172   https://farside.link/example.com/blah/blah"
    173 
    174   (interactive (list (region-beginning)
    175                      (region-end)))
    176 
    177   (save-excursion
    178     (save-restriction ;; Save narrowing setting and revert to it when finishing.
    179       (narrow-to-region beg end)
    180       (rx-let-eval `((urls () (group (or ,@detubifier-enshittified-urls))))
    181         (let ((r (rx-to-string '(urls))))
    182           (replace-regexp-in-region r
    183                                     (concat detubifier-farside-url "\\1")
    184                                     beg
    185                                     end))))))
    186 
    187 ;;;###autoload
    188 (defun detubifier-farsidify-string (str)
    189   "Prefix `detubifier-farside-url' the usual suspects URLs in string STR."
    190 
    191   (rx-let-eval `((urls () (group (or ,@detubifier-enshittified-urls))))
    192     (replace-regexp-in-string (rx-to-string '(urls))
    193                               (concat detubifier-farside-url "\\1")
    194                               str))
    195   )
    196 
    197 (define-obsolete-function-alias
    198   'detubifier-replace-contents
    199   'detubifier-detubify-top-kill
    200   "2024-09-25")
    201 
    202 ;;; Testing:
    203 
    204 (ert-deftest test-detubifier-farsidify-string ()
    205   "Test `detubifier-farsidify-string'."
    206   (should (equal (detubifier-farsidify-string "sdfljdsf sdfkjl https://youtube.com/moo
    207 https://twitter.com/blah")
    208                  (concat "sdfljdsf sdfkjl "
    209                          detubifier-farside-url
    210                          "https://youtube.com/moo
    211 "
    212                          detubifier-farside-url
    213                          "https://twitter.com/blah"))))
    214 
    215 (ert-deftest test-detubifier-farsidify-region ()
    216   "Test `detubifier-farsidify-region'."
    217   (with-temp-buffer
    218     (should (equal (let ()
    219                      (insert "sdfljdsf sdfkjl https://youtube.com/moo
    220 https://twitter.com/blah")
    221                      (detubifier-farsidify-region (point-min)
    222                                                   (point-max))
    223                      (buffer-substring-no-properties (point-min)
    224                                                      (point-max)))
    225                    (concat "sdfljdsf sdfkjl "
    226                            detubifier-farside-url
    227                            "https://youtube.com/moo
    228 "
    229                            detubifier-farside-url
    230                            "https://twitter.com/blah")))))
    231 
    232 (ert-deftest test-detubifier-custom-detubify-string ()
    233   "Test `detubifier-custom-detubify-string'.
    234 
    235 TODO: Test only works with the default `detubifier-regexp-replacement-pairs'.
    236 Make it work in general!"
    237   (should (equal (detubifier-custom-detubify-string "sdfljdsf sdfkjl https://youtube.com/moo
    238 https://twitter.com/blah")
    239                  (concat "sdfljdsf sdfkjl https://invidious.jing.rocks/moo
    240 https://nitter.poast.org/blah"))))
    241 
    242 (ert-deftest test-detubifier-custom-detubify-region ()
    243   "Test `detubifier-custom-detubify-region'.
    244 
    245 TODO: Test only works with the default `detubifier-regexp-replacement-pairs'.
    246 Make it work in general!"
    247   (with-temp-buffer
    248     (should (equal (let ()
    249                      (insert "sdfljdsf sdfkjl https://youtube.com/moo
    250 https://twitter.com/blah")
    251                      (detubifier-custom-detubify-region (point-min)
    252                                                         (point-max))
    253                      (buffer-substring-no-properties (point-min)
    254                                                      (point-max)))
    255                    (concat "sdfljdsf sdfkjl https://invidious.jing.rocks/moo
    256 https://nitter.poast.org/blah")))))
    257 
    258 (provide 'detubifier)
    259 ;;; detubifier.el ends here