From 0afcf2a10c298f6a66281a0b14cea898eed95fef Mon Sep 17 00:00:00 2001 From: Your Name Date: Tue, 30 Apr 2024 14:51:36 +0000 Subject: [PATCH] first --- README.md | 47 +++++++++ configs/atexit-cleanup.py | 29 ++++++ configs/chrome-urls.py | 33 ++++++ configs/chromium-flags.py | 139 +++++++++++++++++++++++++ configs/interceptor-cloudflare.py | 56 ++++++++++ configs/interceptor-ytadds.py | 25 +++++ configs/patch-qute3.1.0.py | 166 ++++++++++++++++++++++++++++++ configs/privacy-settings.py | 28 +++++ configs/search-engines.py | 35 +++++++ configs/tab-manager.py | 8 ++ configs/user-agents.py | 21 ++++ 11 files changed, 587 insertions(+) create mode 100644 README.md create mode 100644 configs/atexit-cleanup.py create mode 100644 configs/chrome-urls.py create mode 100644 configs/chromium-flags.py create mode 100644 configs/interceptor-cloudflare.py create mode 100644 configs/interceptor-ytadds.py create mode 100644 configs/patch-qute3.1.0.py create mode 100644 configs/privacy-settings.py create mode 100644 configs/search-engines.py create mode 100644 configs/tab-manager.py create mode 100644 configs/user-agents.py diff --git a/README.md b/README.md new file mode 100644 index 0000000..9500610 --- /dev/null +++ b/README.md @@ -0,0 +1,47 @@ +Define this function in your config.py + +``` +import os +from qutebrowser.api import config as api_config +sCONFIG_DIR = config.configdir +def config_load_configs(lArgs: list|None = None, sDir: str = sCONFIG_DIR) -> None: + i = 0 + if not lArgs: return i + for foo in lArgs: + sFile = os.path.join(sDir, 'configs', foo) + for bar in sFile, sFile+'.py': + if not os.path.exists(bar): continue + try: + # ResourceWarning: unclosed file + oFd = open(bar, 'rt') + sCode = oFd.read() + oFd.close() + exec(sCode) + except Exception as e: + log.init.warning(f'error execing {bar}\n{e}') + log.init.debug(traceback.print_exc()) + else: + log.init.info(f'execed {bar}') + i = i + 1 + return i +``` +Then make a list of configs you want to load: +``` +lCONFIGS = ['chromium-flags', + 'chrome-urls', + 'privacy-settings', + 'tab-manager', + 'search-engines', + 'user-agents', + 'interceptor-cloudflare', + 'interceptor-ytadds', + 'init_custom_plugins', + 'patch-qute3.1.0', + 'atexit-cleanup', +] +``` +Then load the configs: +``` +i = config_load_configs(lCONFIGS) +log.init.info(f'loaded {i} configs') +``` diff --git a/configs/atexit-cleanup.py b/configs/atexit-cleanup.py new file mode 100644 index 0000000..6015c02 --- /dev/null +++ b/configs/atexit-cleanup.py @@ -0,0 +1,29 @@ +# -*- mode: python; python-indent-offset: 4; tab-width: 0; encoding: utf-8-unix -*- +# This should be execed in config.py +import sys +import os +import atexit + +@atexit.register +def atexit_cleanup(): + lDels = [os.path.join(config.datadir, 'cookies'), + os.path.join(config.datadir, 'history.sqlite'), + ] + bidir = os.path.join(config.datadir, 'webengine') + lDels += [os.path.join(bidir, 'Cookies'), + os.path.join(bidir, 'Cookies-journal'), + os.path.join(bidir, 'Favicons'), + os.path.join(bidir, 'Favicons-journal'), + os.path.join(bidir, 'History'), + os.path.join(bidir, 'History-journal'), + os.path.join(bidir, 'Network Persistent State'), + os.path.join(bidir, 'TransportSecurity'), + os.path.join(bidir, 'Visited Links'), + ] + i = 0 + for elt in lDels: + if os.path.exists(elt): + os.unlink(elt) + i += 1 + sys.stderr.write(f"Cleaned up {i} files\n") + diff --git a/configs/chrome-urls.py b/configs/chrome-urls.py new file mode 100644 index 0000000..8778f8a --- /dev/null +++ b/configs/chrome-urls.py @@ -0,0 +1,33 @@ +# -*- mode: python; python-indent-offset: 4; tab-width: 0; encoding: utf-8-unix -*- +# This should be execed in config.py + +# https://cnman.github.io/chrome-urls.html +# not chrome://history/" +config.unbind("cd") # download-clear +config.bind("cA", "open chrome://accessibility/") +config.bind("cB", "open chrome://blob-internals/") +config.bind("cb", "open qute://bindings/") +config.bind("cC", "open chrome://appcache-internals") +config.bind("cD", "open chrome://sandbox") +config.bind("cE", "open chrome://serviceworker-internals/") +config.bind("ce", "open qute://pyeval") +config.bind("cG", "open chrome://gpu/") +config.bind("cH", "open chrome://histograms/") +config.bind("ch", "open qute://help") +config.bind("cI", "open chrome://indexeddb-internals/") +config.bind("cl", "open qute://log") +config.bind("cM", "open chrome://media-internals/") +config.bind("cm", "open qute://bookmarks/") +config.bind("cN", "open chrome://net-internals/") +config.bind("cQ", "open chrome://quota-internals/") +#config.bind("cp", "open qute://process") +#config.bind("cr", "open qute://resource") +config.bind("cs", "open qute://settings") +config.bind("cT", "open chrome://qt") +config.bind("ct", "open qute://start") +config.bind("cU", "open chrome://user-actions/") +config.bind("cv", "open qute://version/") +config.bind("cW", "open chrome://webrtc-internals/") +config.bind("cX", "open chrome://webrtc-logs") +# There does not seem to be a way currently to disable service workers +# the feature in the Chrome browser. diff --git a/configs/chromium-flags.py b/configs/chromium-flags.py new file mode 100644 index 0000000..2266906 --- /dev/null +++ b/configs/chromium-flags.py @@ -0,0 +1,139 @@ +# -*- mode: python; python-indent-offset: 4; tab-width: 0; encoding: utf-8-unix -*- +# This should be execed in config.py + +# Test by visiting https://coveryourtracks.eff.org/ +# https://niek.github.io/chrome-features/ +# https://peter.sh/experiments/chromium-command-line-switches/ + + +# this may interfere wuth some logins +c.content.canvas_reading = False +# just passes --disable-reading-from-canvas + +# Which Chromium process model to use. +# Alternative process models use less resources, but decrease security and robustness. +# - https://www.chromium.org/developers/design-documents/process-models +# - https://doc.qt.io/qt-6/qtwebengine-features.html#process-models +c.qt.chromium.process_model = 'process-per-site' +# passes --process-per-site + +# qutebrowser adds --disable-accelerated-2d-canvas + +# qutebrowser starts with these: +# ['--webEngineArgs', '--enable-features=WebRTCPipeWireCapturer', '--disable-reading-from-canvas', '--touch-events=disabled', '--force-webrtc-ip-handling-policy=disable_non_proxied_udp', '--process-per-site', '--disable-accelerated-2d-canvas'] +enable = ['WebRTCPipeWireCapturer'] +disable = [] + +# I was thinking of tightening up privacy and security by adding some +# well-known flags to qt.args. I broke them up into 4 categories +# and harvested a list of suggestions from the net. + +# Many may be chromium flags not used by QtWebEngine. + +# https://github.com/qutebrowser/qutebrowser/issues/5378 +# https://github.com/qt/qtwebengine/blob/v5.14.2/src/core/web_engine_context.cpp#L478-L690 + +cacheM = 100 +#? are disabled for now +misc = ['log-level=3' + f"disk-cache-size={cacheM}M", + f"media-cache-size={cacheM}M" + ] + +# GPU tuning - YMMV +misc += [ + # https://github.com/qutebrowser/qutebrowser/discussions/7917 + 'use-gl=desktop', # or use-gl=egl on wayland + 'enable-accelerated-video-decode', # may make thing slower + #? enable-features=VaapiVideoDecoder + #? enable-features=VaapiVideoDecodeLinuxGL + #? cast-streaming-force-disable-hardware-h264 + #? cast-streaming-force-disable-hardware-vp8 + #? cast-streaming-force-enable-hardware-h264 + #? cast-streaming-force-enable-hardware-vp8 + ] +#? c.qt.workarounds.disable_accelerated_2d_canvas = 'never' + +## chromium security +## https://clienttest.ssllabs.com:8443/ssltest/viewMyClient.html +# # 'auth-server-whitelist=*.example.com', +security = [ 'ssl-version-min=tls1.3', + 'ssl-version-fallback-min=tls1.2', + ] +disable += ['EnableServiceWorkersForChromeUntrusted'] + +## chromium privacy + +# https://www.reddit.com/r/privacytoolsIO/comments/kgqmnm/how_to_tweak_chrome_flags_for_privacy_and/ +# --disable-plugins-discovery +# --disable-preconnect +# --dns-prefetch-disable +# --no-pings +# --enable-strict-powerful-feature-restrictions +privacy = [ + #? 'use-dns-https-svcb-alpn=disabled', + #? 'show-autofill-type-predictions=disabled', + #? 'back-forward-cache=disabled', + 'disable-plugins-discovery', + 'disable-preconnect', + 'dns-prefetch-disable', + 'no-pings', + #? 'disable-webgl', + #? 'media-route-dial-provider', + #? 'allow-silent-push=disabled', + 'disable-notificatons', + 'webview-force-disable-3pcs', + ] + +# https://www.reddit.com/r/privacytoolsIO/comments/kgqmnm/how_to_tweak_chrome_flags_for_privacy_and/ +privacy += [ + 'strict-origin-isolation', + 'reduced-referrer-granularity' + ] +# Overall, these two should be enough. You can also consider these flags but imo these doesn't add much benefits +#disallow-doc-written-script-loads +#cookies-without-same-site-must-be-secure +#force-empty-CORB-and-CORS-allowlist +#cors-for-content-scripts +#enable-noscript-previews + +disable += ['DnsOverHttps', 'DnsOverHttpsUpgrade'] + +# a matter of taste +# https://nira.com/chrome-flags/ +taste = [ + #? 'proactive-tab-freeze-and-discard=enabled', + #? 'enable-lazy-image-loading=enabled', + #? 'omnibox-ui-hide-steady-state-url-scheme=enabled', + #? 'omnibox-ui-hide-steady-state-url-trivial-subdomains=enabled', + #? 'memory-saver-memory-usage-in-hovercards=enabled', + #? 'block-insecure-private-network-requests=disabled', + #no 'disable-remote-fonts', + 'disable-remote-playback-api', + ] + +if True: + c.qt.args = security + privacy + misc + taste + \ + ['enable-features=' +','.join(enable), + 'disable-features=' +','.join(disable)] + +del security, privacy, misc, taste, enable, disable + +# how to disable these? +# TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013) WEAK 128 +# TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014) WEAK 256 +# TLS_RSA_WITH_AES_128_GCM_SHA256 (0x9c) WEAK 128 +# TLS_RSA_WITH_AES_256_GCM_SHA384 (0x9d) WEAK 256 +# TLS_RSA_WITH_AES_128_CBC_SHA (0x2f) WEAK 128 +# TLS_RSA_WITH_AES_256_CBC_SHA (0x35) WEAK + +# See also the env variables +#QT_LOGGING_RULES=qt.webenginecontext.debug=true +#QT_QUICK_BACKEND or QMLSCENE_DEVICE # string +#QT_OPENGL # ; set or not +#QTWEBENGINE_CHROMIUM_FLAGS # space sep. string +#QTWEBENGINE_DISABLE_SANDBOX # ; set or not +#QTWEBENGINE_DISABLE_GPU_THREAD # ; set or not + +# import os +# export QTWEBENGINE_DICTIONARIES_PATH /usr/share/myspell diff --git a/configs/interceptor-cloudflare.py b/configs/interceptor-cloudflare.py new file mode 100644 index 0000000..59ce497 --- /dev/null +++ b/configs/interceptor-cloudflare.py @@ -0,0 +1,56 @@ +import re +import sys + +try: + import qutebrowser.api + from qutebrowser.api import interceptor + from qutebrowser.extensions.interceptors import Request + from qutebrowser.qt.core import QUrl + from qutebrowser.utils import debug, log +except ImportError: + sys.stderr.write('qutebrowser not imported\n') +else: + # redirect on cloudflare + def filter_cf(thereq: Request) -> None: + """Block given request if necessary + Called by a signal""" + from qutebrowser.utils import objreg + from qutebrowser.mainwindow import mainwindow + url = thereq.request_url + if url.query().startswith('ray='): + log.network.debug(f"filter_cf thereq.first_party_url={thereq.first_party_url} {repr(thereq)}") + + if thereq.is_blocked is False and ( + url.query().startswith('__cf_chl_rt_tk=') or \ + url.host() == 'challenges.cloudflare.com' or \ + url.path().startswith('/cdn-cgi/challenge-platform/h/')): + # b/turnstile/if/ov2/av0/rcv0/0/33izj/ + # g/orchestrate/chl_page/v1 + url.setPath('/web' + '/*/' +thereq.first_party_url.host() + +thereq.first_party_url.path()) + url.setHost('web.archive.org') + # "__cf_chl_rt_tk="[A-Za-z0-9.-]*" + url.setQuery(None) + log.network.info(f"config.filter_cf REDIRECTING to {url}") + thereq.request_url = url + thereq._redirected = True + thereq.is_blocked = True + if False: + # doesn't work at least on PyQt5 linux + thereq.redirect(url) + elif True: + # + thereq.block() + from qutebrowser.config import config + # expanded open_desktopservices_url + target = objreg.last_opened_window() + #? target = config.val.new_instance_open_target + window = mainwindow.get_window(via_ipc=False, target=target) + tab = window.tabbed_browser._current_tab() + window.tabbed_browser.tabopen(url, + background=False, related=True) + # NO window.maybe_raise() + # crimeflare tabs keep refreshing infinitely + window.tabbed_browser.close_tab(tab) + interceptor.register(filter_cf) + log.init.debug(f"loaded filter_cf interceptor") diff --git a/configs/interceptor-ytadds.py b/configs/interceptor-ytadds.py new file mode 100644 index 0000000..e014f4d --- /dev/null +++ b/configs/interceptor-ytadds.py @@ -0,0 +1,25 @@ +import re +import sys + +try: + import qutebrowser.api + from qutebrowser.api import interceptor + from qutebrowser.extensions.interceptors import Request + from qutebrowser.qt.core import QUrl + from qutebrowser.utils import debug, log +except ImportError: + sys.stderr.write('qutebrowser not imported\n') +else: + # Block youtube ads + def filter_yt(info: Request) -> None: + """Block given request if necessary""" + lYT_URLS = ( "www.youtube.com", "youtube.com", "youtu.be" ) + url = info.request_url + if url.host() in lYT_URLS \ + and url.path() == "/get_video_info" \ + and "&adformat=" in url.query(): + log.network.info(f"Blocking to {url}") + info.block() + interceptor.register(filter_yt) + log.init.debug(f"loaded filter_yt interceptor") + diff --git a/configs/patch-qute3.1.0.py b/configs/patch-qute3.1.0.py new file mode 100644 index 0000000..095fffb --- /dev/null +++ b/configs/patch-qute3.1.0.py @@ -0,0 +1,166 @@ +# -*- mode: python; python-indent-offset: 4; tab-width: 0; encoding: utf-8-unix -*- + +import faulthandler +import logging +import sys +from typing import Iterator, Optional + +import qutebrowser +from qutebrowser.qt import core as qtcore +from qutebrowser.utils import log + +from qutebrowser.utils.qtlog import qt_message_handler + +def my_qt_message_handler(msg_type: qtcore.QtMsgType, + context: qtcore.QMessageLogContext, + msg: Optional[str]) -> None: + """Qt message handler to redirect qWarning etc. to the logging system. + + Args: + msg_type: The level of the message. + context: The source code location of the message. + msg: The message text. + """ + # Mapping from Qt logging levels to the matching logging module levels. + # Note we map critical to ERROR as it's actually "just" an error, and fatal + # to critical. + qt_to_logging = { + qtcore.QtMsgType.QtDebugMsg: logging.DEBUG, + qtcore.QtMsgType.QtWarningMsg: logging.WARNING, + qtcore.QtMsgType.QtCriticalMsg: logging.ERROR, + qtcore.QtMsgType.QtFatalMsg: logging.CRITICAL, + qtcore.QtMsgType.QtInfoMsg: logging.INFO, + } + + # Change levels of some well-known messages to debug so they don't get + # shown to the user. + # + # If a message starts with any text in suppressed_msgs, it's not logged as + # error. + suppressed_msgs = [ + # PNGs in Qt with broken color profile + # https://bugreports.qt.io/browse/QTBUG-39788 + ('libpng warning: iCCP: Not recognizing known sRGB profile that has ' + 'been edited'), + 'libpng warning: iCCP: known incorrect sRGB profile', + # Hopefully harmless warning + 'OpenType support missing for script ', + # Error if a QNetworkReply gets two different errors set. Harmless Qt + # bug on some pages. + # https://bugreports.qt.io/browse/QTBUG-30298 + ('QNetworkReplyImplPrivate::error: Internal problem, this method must ' + 'only be called once.'), + # Sometimes indicates missing text, but most of the time harmless + 'load glyph failed ', + # Harmless, see https://bugreports.qt.io/browse/QTBUG-42479 + ('content-type missing in HTTP POST, defaulting to ' + 'application/x-www-form-urlencoded. ' + 'Use QNetworkRequest::setHeader() to fix this problem.'), + # https://bugreports.qt.io/browse/QTBUG-43118 + 'Using blocking call!', + # Hopefully harmless + ('"Method "GetAll" with signature "s" on interface ' + '"org.freedesktop.DBus.Properties" doesn\'t exist'), + ('"Method \\"GetAll\\" with signature \\"s\\" on interface ' + '\\"org.freedesktop.DBus.Properties\\" doesn\'t exist\\n"'), + 'WOFF support requires QtWebKit to be built with zlib support.', + # Weird Enlightment/GTK X extensions + 'QXcbWindow: Unhandled client message: "_E_', + 'QXcbWindow: Unhandled client message: "_ECORE_', + 'QXcbWindow: Unhandled client message: "_GTK_', + # Happens on AppVeyor CI + 'SetProcessDpiAwareness failed:', + # https://bugreports.qt.io/browse/QTBUG-49174 + ('QObject::connect: Cannot connect (null)::stateChanged(' + 'QNetworkSession::State) to ' + 'QNetworkReplyHttpImpl::_q_networkSessionStateChanged(' + 'QNetworkSession::State)'), + # https://bugreports.qt.io/browse/QTBUG-53989 + ("Image of format '' blocked because it is not considered safe. If " + "you are sure it is safe to do so, you can white-list the format by " + "setting the environment variable QTWEBKIT_IMAGEFORMAT_WHITELIST="), + # Installing Qt from the installer may cause it looking for SSL3 or + # OpenSSL 1.0 which may not be available on the system + "QSslSocket: cannot resolve ", + "QSslSocket: cannot call unresolved function ", + # When enabling debugging with QtWebEngine + ("Remote debugging server started successfully. Try pointing a " + "Chromium-based browser to "), + # https://github.com/qutebrowser/qutebrowser/issues/1287 + "QXcbClipboard: SelectionRequest too old", + # https://github.com/qutebrowser/qutebrowser/issues/2071 + 'QXcbWindow: Unhandled client message: ""', + # https://codereview.qt-project.org/176831 + "QObject::disconnect: Unexpected null parameter", + # https://bugreports.qt.io/browse/QTBUG-76391 + "Attribute Qt::AA_ShareOpenGLContexts must be set before " + "QCoreApplication is created.", + # Qt 6.4 beta 1: https://bugreports.qt.io/browse/QTBUG-104741 + "GL format 0 is not supported", + # added + "(python3.11:3510667): Gtk-WARNING ", + + ] + # not using utils.is_mac here, because we can't be sure we can successfully + # import the utils module here. + if sys.platform == 'darwin': + suppressed_msgs += [ + # https://bugreports.qt.io/browse/QTBUG-47154 + ('virtual void QSslSocketBackendPrivate::transmit() SSLRead ' + 'failed with: -9805'), + ] + + if not msg: + msg = "Logged empty message!" + + if any(msg.strip().startswith(pattern) for pattern in suppressed_msgs): + level = logging.DEBUG + elif context.category == "qt.webenginecontext" and ( + msg.strip().startswith("GL Type: ") or # Qt 6.3 + msg.strip().startswith("GLImplementation:") # Qt 6.2 + ): + level = logging.DEBUG + else: + level = qt_to_logging[msg_type] + + if context.line is None: + lineno = -1 # type: ignore[unreachable] + else: + lineno = context.line + + if context.function is None: + func = 'none' # type: ignore[unreachable] + elif ':' in context.function: + func = '"{}"'.format(context.function) + else: + func = context.function + + if context.category is None or context.category == 'default': + name = 'qt' + else: + name = 'qt-' + context.category + if msg.splitlines()[0] == ('This application failed to start because it ' + 'could not find or load the Qt platform plugin ' + '"xcb".'): + # Handle this message specially. + msg += ("\n\nOn Archlinux, this should fix the problem:\n" + " pacman -S libxkbcommon-x11") + faulthandler.disable() + + assert _args is not None + if _args.debug: + try: + stack = ''.join(traceback.format_stack()) + except Exception as e: + log.misc.warn(f"Error formatting stack: {e}") + stack = None + else: + stack = None + + record = log.qt.makeRecord(name=name, level=level, fn=context.file, lno=lineno, + msg=msg, args=(), exc_info=None, func=func, + sinfo=stack) + log.qt.handle(record) + + +qutebrowser.utils.qtlog.qt_message_handler = my_qt_message_handler diff --git a/configs/privacy-settings.py b/configs/privacy-settings.py new file mode 100644 index 0000000..d78df34 --- /dev/null +++ b/configs/privacy-settings.py @@ -0,0 +1,28 @@ +# privacy +c.content.geolocation = False +c.content.dns_prefetch = False +c.content.canvas_reading = False + +c.content.webrtc_ip_handling_policy = 'disable-non-proxied-udp' +c.content.webgl = False + +c.content.tls.certificate_errors = 'ask' +c.content.register_protocol_handler = 'ask' + +c.content.notifications.show_origin = True +c.content.hyperlink_auditing = False + +c.content.plugins = False +# The content.proxy_dns_requests setting is not available with the QtWebEngine backend! +# c.content.proxy_dns_requests = True + +# Allow websites to record audio. +c.content.media.audio_capture = 'ask' +# Allow websites to record audio and video. +c.content.media.audio_video_capture = 'ask' +# Allow websites to record video +c.content.media.video_capture = 'ask' + +# Enable the ad/host blocker +c.content.blocking.enabled = True +c.content.blocking.hosts.block_subdomains = True diff --git a/configs/search-engines.py b/configs/search-engines.py new file mode 100644 index 0000000..d588340 --- /dev/null +++ b/configs/search-engines.py @@ -0,0 +1,35 @@ +# -*- mode: python; python-indent-offset: 4; tab-width: 0; encoding: utf-8-unix -*- +# This should be execed in config.py + +# Search engines which can be used via the address bar. Maps a search +# engine name (such as `DEFAULT`, or `ddg`) to a URL with a `{}` +# placeholder. The placeholder will be replaced by the search term, use +# `{{` and `}}` for literal `{`/`}` braces. The following further +# placeholds are defined to configure how special characters in the +# search terms are replaced by safe characters (called 'quoting'): * +# `{}` and `{semiquoted}` quote everything except slashes; this is the +# most sensible choice for almost all search engines (for the search +# term `slash/and&` this placeholder expands to `slash/and%26amp`). +# * `{quoted}` quotes all characters (for `slash/and&` this +# placeholder expands to `slash%2Fand%26amp`). * `{unquoted}` quotes +# nothing (for `slash/and&` this placeholder expands to +# `slash/and&`). The search engine named `DEFAULT` is used when +# `url.auto_search` is turned on and something else than a URL was +# entered to be opened. Other search engines can be used by prepending +# the search engine name to the search term, e.g. `:open google +# qutebrowser`. +# Type: Dict +c.url.searchengines = { + 'DEFAULT': 'https://www.startpage.com/sp/search?query={}&cat=web&pl=opensearch&language=english', + 'sC': 'http://cht.sh/{}', + 'sD': 'https://duckduckgo.com/html?q={}', + 'sG': 'https://github.com/NYANLAUNCHER?tab=repositories&q={}', + 'sI': 'https://www.dictionary.com/browse/{}', + 'sJ': 'https://mojeek.com/?q={}', + 'sM': 'https://metager.org/meta/meta.ger3?eingabe={}&focus=web&ua=1', + 'sO': 'https://odysee.com/$/search?q={}', + 'sS': 'https://www.startpage.com/sp/search?query={}&cat=web&pl=opensearch&language=english', + 'sX': 'https://searx.tiekoetter.com/?q={}', + 'sY': 'https://www.youtube.com/results?search_query={}', +} + diff --git a/configs/tab-manager.py b/configs/tab-manager.py new file mode 100644 index 0000000..8fb4b26 --- /dev/null +++ b/configs/tab-manager.py @@ -0,0 +1,8 @@ +# -*- mode: python; python-indent-offset: 4; tab-width: 0; encoding: utf-8-unix -*- +# This should be execed in config.py + +config.bind("zA", "spawn --userscript $HOME/.config/qutebrowser/userscripts/tab-manager/tab-manager.py $HOME/.local/share/qutebrowser/sessions/ save-all -o -f") +config.bind("zO", "spawn --userscript $HOME/.config/qutebrowser/userscripts/tab-manager/tab-manager.py $HOME/.local/share/qutebrowser/sessions/ open -f") +config.bind("zS", "spawn --userscript $HOME/.config/qutebrowser/userscripts/tab-manager/tab-manager.py $HOME/.local/share/qutebrowser/sessions/ save -f") +config.bind("zD", "spawn --userscript $HOME/.config/qutebrowser/userscripts/tab-manager/tab-manager.py $HOME/.local/share/qutebrowser/sessions/ delete -f") +config.bind("zH", "spawn --userscript $HOME/.config/qutebrowser/userscripts/tab-manager/tab-manager.py $HOME/.local/share/qutebrowser/sessions/ help") diff --git a/configs/user-agents.py b/configs/user-agents.py new file mode 100644 index 0000000..f01d667 --- /dev/null +++ b/configs/user-agents.py @@ -0,0 +1,21 @@ +# -*- mode: python; python-indent-offset: 4; tab-width: 0; encoding: utf-8-unix -*- +# This should be execed in config.py + +# User agent to send. The following placeholders are defined: * +# `{os_info}`: Something like "X11; Linux x86_64". * `{webkit_version}`: +# The underlying WebKit version (set to a fixed value with +# QtWebEngine). * `{qt_key}`: "Qt" for QtWebKit, "QtWebEngine" for +# QtWebEngine. * `{qt_version}`: The underlying Qt version. * +# `{upstream_browser_key}`: "Version" for QtWebKit, "Chrome" for +# QtWebEngine. * `{upstream_browser_version}`: The corresponding +# Safari/Chrome version. * `{qutebrowser_version}`: The currently +# running qutebrowser version. The default value is equal to the +# unchanged user agent of QtWebKit/QtWebEngine. Note that the value +# read from JavaScript is always the global value. With QtWebEngine +# between 5.12 and 5.14 (inclusive), changing the value exposed to +# JavaScript requires a restart. +# Type: FormatString +config.set('content.headers.user_agent', 'Mozilla/5.0 ({os_info}) AppleWebKit/{webkit_version} (KHTML, like Gecko) {upstream_browser_key}/{upstream_browser_version} Safari/{webkit_version}', 'https://web.whatsapp.com/') +config.set('content.headers.user_agent', 'Mozilla/5.0 ({os_info}; rv:90.0) Gecko/20100101 Firefox/90.0', 'https://accounts.google.com/*') +config.set('content.headers.user_agent', 'Mozilla/5.0 ({os_info}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99 Safari/537.36', 'https://*.slack.com/*') +