{
  config,
  lib,
  pkgs,
  ...
}:
with lib;
  mkIf (elem "emacs::elfeed" config.machine.pkgs) {
    programs.emacs.init.usePackage = {
      elfeed = let
        pyEnv = pkgs.python3.withPackages (ps: with ps; [beautifulsoup4 lxml requests]);
        pyScript = pkgs.writeScript "elfeedFetcher.py" ''
          #!${pyEnv}/bin/python3
          import sys
          from requests import get
          from bs4 import BeautifulSoup

          header_agent = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:75.0) Gecko/20100101 Firefox/75.0'}
          with get(sys.argv[1], headers=header_agent) as r:
              soup = BeautifulSoup(r.text, 'lxml')
              abstract = soup.find('dd', {"id": "abstract"}).text.replace('"', '\\"')
              article = '\n\n'.join(
                  [soup.find('p',  {"id": "first"}, class_="lead").text] +
                  [
                  p.text for p in
                  soup.find('div', {"id": "text"}).findAll('p')
              ]).replace('"', '\\"')
          print(f"(setq abstract \"{abstract}\") (setq article \"{article}\")")
        '';
      in {
        enable = true;
        hook = [''(elfeed-new-entry . elfeed-content-fetcher)''];
        config = ''
          (load-file "~/.emacs.d/elfeed.el")

          (defun elfeed-play-with-mpv (entry)
            "Play entry link with mpv."
            (interactive (elfeed-search-selected :single))
             (start-process "elfeed-mpv" nil "mpv" "--ytdl-format=[height<=1080]" (elfeed-entry-link entry)))

          (defun elfeed-search-show-entry-custom (entry)
            "Custom actions for various sources."
            (interactive (list (elfeed-search-selected :ignore-region)))
            (if (equal (car (elfeed-entry-id entry)) "www.youtube.com") (elfeed-play-with-mpv entry)
            (elfeed-show-entry entry)))
          (define-key elfeed-search-mode-map [remap elfeed-search-show-entry] 'elfeed-search-show-entry-custom)

          (defun elfeed-get-yt-description (url)
            (shell-command-to-string (format "${pkgs.youtube-dl}/bin/youtube-dl --get-description \"%s\" 2> /dev/null" url)))

          (defun elfeed-get-sd-article (url)
            (eval-string (shell-command-to-string (format "${pyEnv}/bin/python3 ${pyScript} \"%s\" 2> /dev/null" url))))

          (defun eval-string (string)
            (eval (car (read-from-string (format "(progn %s)" string)))))

          (defun elfeed-content-fetcher (entry)
            "Fetches content for various entries (currently only sciencedaily)."
            (interactive (list (elfeed-search-selected :ignore-region)))

            (let ((url (elfeed-entry-link entry))
                  (feed-id (elfeed-deref (elfeed-entry-feed-id entry)))
                 )
              (when (equal (car (elfeed-entry-id entry)) "www.sciencedaily.com")
                (elfeed-get-sd-article (cdr (elfeed-entry-id entry)))
                ;; (setf (elfeed-entry-content entry) (elfeed-ref article))
                (setf (elfeed-meta entry :content) (elfeed-ref article))
                (setf (elfeed-meta entry :abstract) abstract)
                (makunbound 'abstract)
                (makunbound 'article))))

          (defun elfeed-show-refresh--mail-style ()
            "Update the buffer to match the selected entry, using a mail-style."
            (interactive)
            (let* ((inhibit-read-only t)
                   (title (elfeed-entry-title elfeed-show-entry))
                   (date (seconds-to-time (elfeed-entry-date elfeed-show-entry)))
                   (authors (elfeed-meta elfeed-show-entry :authors))
                   (link (elfeed-entry-link elfeed-show-entry))
                   (tags (elfeed-entry-tags elfeed-show-entry))
                   (tagsstr (mapconcat #'symbol-name tags ", "))
                   (nicedate (format-time-string "%a, %e %b %Y %T %Z" date))
                   (content (if (elfeed-meta elfeed-show-entry :content) (elfeed-deref (elfeed-meta elfeed-show-entry :content)) (elfeed-deref (elfeed-entry-content elfeed-show-entry))))
                   (type (elfeed-entry-content-type elfeed-show-entry))
                   (feed (elfeed-entry-feed elfeed-show-entry))
                   (feed-title (elfeed-feed-title feed))
                   (base (and feed (elfeed-compute-base (elfeed-feed-url feed)))))
              (erase-buffer)
              (insert (format (propertize "Title: %s\n" 'face 'message-header-name)
                              (propertize title 'face 'message-header-subject)))
              (when elfeed-show-entry-author
                (dolist (author authors)
                  (let ((formatted (elfeed--show-format-author author)))
                    (insert
                     (format (propertize "Author: %s\n" 'face 'message-header-name)
                             (propertize formatted 'face 'message-header-to))))))
              (insert (format (propertize "Date: %s\n" 'face 'message-header-name)
                              (propertize nicedate 'face 'message-header-other)))
              (insert (format (propertize "Feed: %s\n" 'face 'message-header-name)
                              (propertize feed-title 'face 'message-header-other)))
              (when tags
                (insert (format (propertize "Tags: %s\n" 'face 'message-header-name)
                                (propertize tagsstr 'face 'message-header-other))))
              (insert (propertize "Link: " 'face 'message-header-name))
              (elfeed-insert-link link link)
              (insert "\n")
              (cl-loop for enclosure in (elfeed-entry-enclosures elfeed-show-entry)
                       do (insert (propertize "Enclosure: " 'face 'message-header-name))
                       do (elfeed-insert-link (car enclosure))
                       do (insert "\n"))
              (insert "\n")
              (if content
                  (if (eq type 'html)
                      (elfeed-insert-html content base)
                    (insert content))
                (insert (propertize "(empty)\n" 'face 'italic)))
              (goto-char (point-min))))


          (defun elfeed-db-gc (&optional stats-p)
            "Clean up unused content from the content database.
          If STATS is true, return the space cleared in bytes."
            (elfeed-db-gc-empty-feeds)
            (let* ((data (expand-file-name "data" elfeed-db-directory))
                   (dirs (directory-files data t "^[0-9a-z]\\{2\\}$"))
                   (ids (cl-mapcan (lambda (d) (directory-files d nil nil t)) dirs))
                   (table (make-hash-table :test 'equal)))
              (dolist (id ids)
                (setf (gethash id table) nil))
              (with-elfeed-db-visit (entry _)
                (let ((content (elfeed-entry-content entry))
                      (meta-content (elfeed-meta entry :content)))
                  (when (elfeed-ref-p content)
                    (setf (gethash (elfeed-ref-id content) table) t))
                  (when (elfeed-ref-p (meta-content))
                    (setf (gethash (elfeed-ref-id meta-content) table) t))))
              (cl-loop for id hash-keys of table using (hash-value used)
                       for used-p = (or used (member id '("." "..")))
                       when (and (not used-p) stats-p)
                       sum (let* ((ref (elfeed-ref--create :id id))
                                  (file (elfeed-ref--file ref)))
                             (* 1.0 (nth 7 (file-attributes file))))
                       unless used-p
                       do (elfeed-ref-delete (elfeed-ref--create :id id))
                       finally (cl-loop for dir in dirs
                                        when (elfeed-directory-empty-p dir)
                                        do (delete-directory dir)))))
        '';
      };
    };
  }