Files
AudioBookRequest/docs/_print/index.html
2025-07-01 17:54:33 +00:00

1288 lines
62 KiB
HTML

<!doctype html>
<html itemscope itemtype="http://schema.org/WebPage" lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="canonical" type="text/html" href="https://markbeep.github.io/AudioBookRequest/docs/">
<link rel="alternate" type="application/rss&#43;xml" href="https://markbeep.github.io/AudioBookRequest/docs/index.xml">
<meta name="robots" content="noindex, nofollow">
<link rel="shortcut icon" href="/AudioBookRequest/favicons/favicon.ico" >
<link rel="apple-touch-icon" href="/AudioBookRequest/favicons/apple-touch-icon-180x180.png" sizes="180x180">
<link rel="icon" type="image/png" href="/AudioBookRequest/favicons/favicon-16x16.png" sizes="16x16">
<link rel="icon" type="image/png" href="/AudioBookRequest/favicons/favicon-32x32.png" sizes="32x32">
<link rel="icon" type="image/png" href="/AudioBookRequest/favicons/android-36x36.png" sizes="36x36">
<link rel="icon" type="image/png" href="/AudioBookRequest/favicons/android-48x48.png" sizes="48x48">
<link rel="icon" type="image/png" href="/AudioBookRequest/favicons/android-72x72.png" sizes="72x72">
<link rel="icon" type="image/png" href="/AudioBookRequest/favicons/android-96x96.png" sizes="96x96">
<link rel="icon" type="image/png" href="/AudioBookRequest/favicons/android-144x144.png" sizes="144x144">
<link rel="icon" type="image/png" href="/AudioBookRequest/favicons/android-192x192.png" sizes="192x192">
<title>Documentation | AudioBookRequest Docs</title>
<meta name="description" content="Welcome to the documentation for AudioBookRequest.">
<meta property="og:url" content="https://markbeep.github.io/AudioBookRequest/docs/">
<meta property="og:site_name" content="AudioBookRequest Docs">
<meta property="og:title" content="Documentation">
<meta property="og:description" content="Welcome to the documentation for AudioBookRequest.">
<meta property="og:locale" content="en">
<meta property="og:type" content="website">
<meta itemprop="name" content="Documentation">
<meta itemprop="description" content="Welcome to the documentation for AudioBookRequest.">
<meta itemprop="dateModified" content="2025-07-01T19:53:36+02:00">
<meta itemprop="wordCount" content="245">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Documentation">
<meta name="twitter:description" content="Welcome to the documentation for AudioBookRequest.">
<link href="/AudioBookRequest/scss/main.css" rel="stylesheet">
<script
src="https://code.jquery.com/jquery-3.7.1.min.js"
integrity="sha512-v2CJ7UaYy4JwqLDIrZUI/4hqeoQieOmAZNXBeQyjo21dadnwR+8ZaIJVT8EE2iyI61OV8e6M8PP2/4hpQINQ/g=="
crossorigin="anonymous"></script>
</head>
<body class="td-section">
<header>
<nav class="td-navbar js-navbar-scroll" data-bs-theme="dark">
<div class="container-fluid flex-column flex-md-row">
<a class="navbar-brand" href="/AudioBookRequest/"><span class="navbar-brand__logo navbar-logo"><svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 500 500" style="enable-background:new 0 0 500 500"><g><path style="fill:#fff" d="M116.8525 421.9722c-5.7041.0-10.3442-4.3127-10.3442-9.6129V88.183c0-5.3002 4.6401-9.6117 10.3442-9.6117H320.858c3.0347.0 9.3959.5498 11.7506 2.6302l.3545.3442 58.905 63.2912c2.3101 2.491 2.9202 8.4928 2.9202 11.3184v256.2039c0 5.3002-4.6407 9.6129-10.3436 9.6129H116.8525z"/><g><g><g><path style="fill:#767676" d="M384.4445 423.2066H116.852c-6.3839.0-11.5786-4.8658-11.5786-10.8474V88.1831c0-5.9804 5.1947-10.8461 11.5786-10.8461h204.0062c.377.0 9.2786.0329 12.568 2.9389l.3947.3833 58.9508 63.337c3.2135 3.4652 3.2514 11.7924 3.2514 12.1593v256.2036C396.0231 418.3408 390.8284 423.2066 384.4445 423.2066zM116.5079 411.9189c.0848.0278.1999.0531.3441.0531h267.5925c.1442.0.2581-.0253.3441-.0531V156.1556c-.0076-.9033-.3593-3.7347-.7034-5.0037l-57.6527-61.9416c-1.4651-.3176-4.4533-.6389-5.5742-.6389H116.852c-.143.0-.2594.024-.3441.0531V411.9189zm267.4533-261.149zM327.0321 89.371v.0013V89.371z"/></g></g></g><g><g><path style="fill:#5b7fc0" d="M189.0874 210.1754l.0012-.0012c7.7751.0012 15.0295 4.1862 18.932 10.9234 1.9177 3.3159 2.9305 7.1011 2.9293 10.9378.0 5.8394-2.2733 11.3304-6.4032 15.4604-4.1288 4.1288-9.6186 6.4032-15.458 6.4032s-11.328-2.2733-15.458-6.4032-6.4032-9.6186-6.4056-15.4628c.0012-6.025 2.454-11.4897 6.4116-15.4473C177.5953 212.627 183.0601 210.1742 189.0874 210.1754zm7.993 21.8576c.0012-1.4042-.3687-2.7868-1.063-3.9887-1.4293-2.4684-4.0833-3.9995-6.9299-4.0019-4.4077.0024-7.993 3.5877-7.993 7.993.0 2.1356.832 4.1431 2.3427 5.6539 1.5083 1.5083 3.5159 2.3403 5.6503 2.3415 2.1356.0 4.1443-.8308 5.6539-2.3403S197.0816 234.1722 197.0804 232.033z"/><path style="opacity:.3;fill:#fff" d="M189.0898 210.176c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3136 2.9377 7.0988 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8066-21.8612-21.8613.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 212.6276 183.0612 210.176 189.0898 210.176zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 236.239 197.0839 234.2399 197.0839 232.0372z"/><g><defs><path id="SVGID_1_" d="M194.7376 237.6875c-1.4461 1.4461-3.4452 2.3439-5.6479 2.3439-4.4077-.0024-7.9918-3.5865-7.9942-7.9942.0024-4.4125 3.5937-7.999 7.9942-7.9942 2.8443.0 5.497 1.5323 6.924 3.9983.6991 1.2067 1.0702 2.5881 1.0702 3.9959C197.0839 234.2399 196.1861 236.239 194.7376 237.6875z"/></defs><clipPath id="SVGID_2_"><use xlink:href="#SVGID_1_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_2_);fill:#fff" d="M190.0704 225.0237c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9546.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.663-2.8588-6.116.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C193.7885 225.7247 191.9774 225.0237 190.0704 225.0237z"/><path style="opacity:.13;clip-path:url(#SVGID_2_);fill:#020202" d="M190.0704 225.0237c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9546.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.663-2.8588-6.116.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C193.7885 225.7247 191.9774 225.0237 190.0704 225.0237z"/></g><g><defs><path id="SVGID_3_" d="M189.0898 210.176c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3136 2.9377 7.0988 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8066-21.8612-21.8613.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 212.6276 183.0612 210.176 189.0898 210.176zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 236.239 197.0839 234.2399 197.0839 232.0372z"/></defs><clipPath id="SVGID_4_"><use xlink:href="#SVGID_3_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_4_);fill:#5b7fc0" d="M172.6595 215.6045c-3.96 3.96-6.4116 9.4235-6.4116 15.452-.0024 12.0547 9.8066 21.8636 21.8613 21.8612 12.0547.0024 21.8636-9.797 21.8613-21.8612.0024-3.8475-1.0151-7.6326-2.9353-10.9462-3.8977-6.7324-11.1497-10.9151-18.926-10.9151C182.0806 209.1953 176.6171 211.647 172.6595 215.6045z"/></g></g><rect x="198.8952" y="225.1043" style="fill:#5b7fc0" width="122.6266" height="13.8671"/></g><g><path style="fill:#d95140" d="M189.0874 155.7611l.0012-.0012c7.7751.0012 15.0295 4.1862 18.932 10.9234 1.9177 3.3159 2.9305 7.1011 2.9293 10.9378.0 5.8394-2.2733 11.3304-6.4032 15.4604-4.1288 4.1288-9.6186 6.4032-15.458 6.4032s-11.328-2.2733-15.458-6.4032-6.4032-9.6186-6.4056-15.4628c.0012-6.0249 2.454-11.4897 6.4116-15.4473C177.5953 158.2128 183.0601 155.7599 189.0874 155.7611zm7.993 21.8577c.0012-1.4042-.3687-2.7868-1.063-3.9887-1.4293-2.4684-4.0833-3.9995-6.9299-4.0019-4.4077.0024-7.993 3.5877-7.993 7.993.0 2.1356.832 4.1431 2.3427 5.6539 1.5083 1.5083 3.5159 2.3403 5.6503 2.3415 2.1356.0 4.1443-.8308 5.6539-2.3403C196.2508 181.7667 197.0816 179.758 197.0804 177.6188z"/><path style="opacity:.3;fill:#fff" d="M189.0898 155.7617c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3135 2.9377 7.0987 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8066-21.8612-21.8613.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 158.2134 183.0612 155.7617 189.0898 155.7617zm7.9941 21.8613c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 181.8248 197.0839 179.8256 197.0839 177.623z"/><g><defs><path id="SVGID_5_" d="M194.7376 183.2733c-1.4461 1.4461-3.4452 2.3439-5.6479 2.3439-4.4077-.0024-7.9918-3.5865-7.9942-7.9942.0024-4.4125 3.5937-7.9989 7.9942-7.9942 2.8443.0 5.497 1.5323 6.924 3.9983.6991 1.2067 1.0702 2.5881 1.0702 3.9959C197.0839 179.8256 196.1861 181.8248 194.7376 183.2733z"/></defs><clipPath id="SVGID_6_"><use xlink:href="#SVGID_5_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_6_);fill:#fff" d="M190.0704 170.6095c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9546.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.663-2.8588-6.116.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C193.7885 171.3104 191.9774 170.6095 190.0704 170.6095z"/><path style="opacity:.13;clip-path:url(#SVGID_6_);fill:#020202" d="M190.0704 170.6095c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9546.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.663-2.8588-6.116.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C193.7885 171.3104 191.9774 170.6095 190.0704 170.6095z"/></g><g><defs><path id="SVGID_7_" d="M189.0898 155.7617c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3135 2.9377 7.0987 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8066-21.8612-21.8613.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 158.2134 183.0612 155.7617 189.0898 155.7617zm7.9941 21.8613c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 181.8248 197.0839 179.8256 197.0839 177.623z"/></defs><clipPath id="SVGID_8_"><use xlink:href="#SVGID_7_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_8_);fill:#d95140" d="M172.6595 161.1903c-3.96 3.96-6.4116 9.4235-6.4116 15.452-.0024 12.0547 9.8066 21.8636 21.8613 21.8613 12.0547.0024 21.8636-9.797 21.8613-21.8613.0024-3.8474-1.0151-7.6326-2.9353-10.9462-3.8977-6.7324-11.1497-10.9151-18.926-10.9151C182.0806 154.7811 176.6171 157.2327 172.6595 161.1903z"/></g><rect x="198.8952" y="170.69" style="fill:#d95140" width="122.6266" height="13.8671"/></g><g><g><path style="fill:#56a55c" d="M189.5379 264.6147l.0012-.0012c7.7751.0012 15.0294 4.1862 18.932 10.9235 1.9177 3.3159 2.9305 7.1011 2.9293 10.9378.0 5.8394-2.2733 11.3304-6.4032 15.4604-4.1288 4.1288-9.6186 6.4032-15.458 6.4032-5.8394.0-11.3281-2.2733-15.458-6.4032-4.13-4.13-6.4032-9.6186-6.4056-15.4628.0012-6.0249 2.454-11.4897 6.4116-15.4472C178.0458 267.0663 183.5105 264.6135 189.5379 264.6147zm7.993 21.8576c.0012-1.4042-.3687-2.7868-1.063-3.9887-1.4293-2.4684-4.0833-3.9995-6.9299-4.0019-4.4077.0024-7.993 3.5877-7.993 7.993.0 2.1356.832 4.1431 2.3427 5.6538 1.5083 1.5083 3.5159 2.3403 5.6503 2.3415 2.1356.0 4.1443-.8308 5.6539-2.3403C196.7013 290.6202 197.5321 288.6115 197.5309 286.4723z"/><path style="opacity:.3;fill:#fff" d="M189.5403 264.6153c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3135 2.9377 7.0987 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8065-21.8612-21.8613.0-6.0285 2.4516-11.492 6.4116-15.452C178.0482 267.0669 183.5117 264.6153 189.5403 264.6153zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9941.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.6366 290.6783 197.5344 288.6792 197.5344 286.4765z"/><g><defs><path id="SVGID_9_" d="M195.1881 292.1268c-1.4461 1.4461-3.4452 2.3439-5.6479 2.3439-4.4077-.0024-7.9918-3.5865-7.9942-7.9942.0024-4.4125 3.5937-7.9989 7.9942-7.9941 2.8443.0 5.497 1.5323 6.924 3.9983.6991 1.2067 1.0702 2.5881 1.0702 3.9959C197.5344 288.6792 196.6366 290.6783 195.1881 292.1268z"/></defs><clipPath id="SVGID_10_"><use xlink:href="#SVGID_9_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_10_);fill:#fff" d="M190.5209 279.463c-4.4005-.0048-7.9918 3.5817-7.9942 7.9941.0011 1.9547.7088 3.7452 1.8782 5.1354-1.7446-1.4674-2.8575-3.6631-2.8588-6.1161.0024-4.4125 3.5936-7.999 7.9942-7.9941 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C194.239 280.164 192.4279 279.463 190.5209 279.463z"/><path style="opacity:.13;clip-path:url(#SVGID_10_);fill:#020202" d="M190.5209 279.463c-4.4005-.0048-7.9918 3.5817-7.9942 7.9941.0011 1.9547.7088 3.7452 1.8782 5.1354-1.7446-1.4674-2.8575-3.6631-2.8588-6.1161.0024-4.4125 3.5936-7.999 7.9942-7.9941 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C194.239 280.164 192.4279 279.463 190.5209 279.463z"/></g><g><defs><path id="SVGID_11_" d="M189.5403 264.6153c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3135 2.9377 7.0987 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8065-21.8612-21.8613.0-6.0285 2.4516-11.492 6.4116-15.452C178.0482 267.0669 183.5117 264.6153 189.5403 264.6153zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9941.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.6366 290.6783 197.5344 288.6792 197.5344 286.4765z"/></defs><clipPath id="SVGID_12_"><use xlink:href="#SVGID_11_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_12_);fill:#56a55c" d="M173.11 270.0439c-3.96 3.96-6.4116 9.4235-6.4116 15.452-.0024 12.0547 9.8066 21.8636 21.8613 21.8613 12.0547.0024 21.8636-9.797 21.8613-21.8613.0024-3.8474-1.0151-7.6326-2.9353-10.9462-3.8977-6.7325-11.1497-10.9151-18.926-10.9151C182.5311 263.6346 177.0676 266.0863 173.11 270.0439z"/></g></g><rect x="199.3456" y="279.5436" style="fill:#56a55c" width="122.6266" height="13.8671"/></g><g><g><path style="fill:#f1bc42" d="M189.0874 318.7208l.0012-.0012c7.7751.0012 15.0295 4.1862 18.932 10.9234 1.9177 3.3159 2.9305 7.1011 2.9293 10.9378.0 5.8394-2.2733 11.3305-6.4032 15.4604-4.1288 4.1288-9.6186 6.4032-15.458 6.4032s-11.328-2.2733-15.458-6.4032-6.4032-9.6186-6.4056-15.4628c.0012-6.025 2.454-11.4897 6.4116-15.4472C177.5953 321.1724 183.0601 318.7196 189.0874 318.7208zm7.993 21.8576c.0012-1.4042-.3687-2.7868-1.063-3.9887-1.4293-2.4684-4.0833-3.9995-6.9299-4.0019-4.4077.0024-7.993 3.5877-7.993 7.993.0 2.1356.832 4.1431 2.3427 5.6539 1.5083 1.5083 3.5159 2.3403 5.6503 2.3415 2.1356.0 4.1443-.8308 5.6539-2.3403S197.0816 342.7176 197.0804 340.5784z"/><path style="opacity:.3;fill:#fff" d="M189.0898 318.7214c7.7763.0 15.0283 4.1826 18.926 10.915 1.9201 3.3136 2.9377 7.0988 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8612-12.0547.0024-21.8636-9.8065-21.8612-21.8612.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 321.173 183.0612 318.7214 189.0898 318.7214zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 344.7844 197.0839 342.7853 197.0839 340.5826z"/><g><defs><path id="SVGID_13_" d="M194.7376 346.2329c-1.4461 1.4461-3.4452 2.3439-5.6479 2.3439-4.4077-.0024-7.9918-3.5865-7.9942-7.9942.0024-4.4125 3.5937-7.999 7.9942-7.9942 2.8443.0 5.497 1.5323 6.924 3.9983.6991 1.2067 1.0702 2.5881 1.0702 3.9959C197.0839 342.7853 196.1861 344.7844 194.7376 346.2329z"/></defs><clipPath id="SVGID_14_"><use xlink:href="#SVGID_13_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_14_);fill:#fff" d="M190.0704 333.5691c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9547.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.6631-2.8588-6.1161.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0834 6.1218 2.8788C193.7885 334.2701 191.9774 333.5691 190.0704 333.5691z"/><path style="opacity:.13;clip-path:url(#SVGID_14_);fill:#020202" d="M190.0704 333.5691c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9547.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.6631-2.8588-6.1161.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0834 6.1218 2.8788C193.7885 334.2701 191.9774 333.5691 190.0704 333.5691z"/></g><g><defs><path id="SVGID_15_" d="M189.0898 318.7214c7.7763.0 15.0283 4.1826 18.926 10.915 1.9201 3.3136 2.9377 7.0988 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8612-12.0547.0024-21.8636-9.8065-21.8612-21.8612.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 321.173 183.0612 318.7214 189.0898 318.7214zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 344.7844 197.0839 342.7853 197.0839 340.5826z"/></defs><clipPath id="SVGID_16_"><use xlink:href="#SVGID_15_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_16_);fill:#f1bc42" d="M172.6595 324.15c-3.96 3.96-6.4116 9.4235-6.4116 15.452-.0024 12.0547 9.8066 21.8636 21.8613 21.8612 12.0547.0024 21.8636-9.797 21.8613-21.8612.0024-3.8474-1.0151-7.6327-2.9353-10.9462-3.8977-6.7324-11.1497-10.9151-18.926-10.9151C182.0806 317.7407 176.6171 320.1924 172.6595 324.15z"/></g></g><rect x="198.8952" y="333.6497" style="fill:#f1bc42" width="122.6266" height="13.8671"/></g></g></svg></span><span class="navbar-brand__name">AudioBookRequest Docs</span></a>
<div class="td-navbar-nav-scroll ms-md-auto" id="main_navbar">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link active" href="/AudioBookRequest/docs/"><span>Documentation</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="/AudioBookRequest/community/"><span>Community</span></a>
</li>
<li class="td-light-dark-menu nav-item dropdown">
<svg xmlns="http://www.w3.org/2000/svg" class="d-none">
<symbol id="check2" viewBox="0 0 16 16">
<path d="M13.854 3.646a.5.5 0 0 1 0 .708l-7 7a.5.5 0 0 1-.708 0l-3.5-3.5a.5.5 0 1 1 .708-.708L6.5 10.293l6.646-6.647a.5.5 0 0 1 .708 0z"/>
</symbol>
<symbol id="circle-half" viewBox="0 0 16 16">
<path d="M8 15A7 7 0 1 0 8 1v14zm0 1A8 8 0 1 1 8 0a8 8 0 0 1 0 16z"/>
</symbol>
<symbol id="moon-stars-fill" viewBox="0 0 16 16">
<path d="M6 .278a.768.768 0 0 1 .08.858 7.208 7.208 0 0 0-.878 3.46c0 4.021 3.278 7.277 7.318 7.277.527 0 1.04-.055 1.533-.16a.787.787 0 0 1 .81.316.733.733 0 0 1-.031.893A8.349 8.349 0 0 1 8.344 16C3.734 16 0 12.286 0 7.71 0 4.266 2.114 1.312 5.124.06A.752.752 0 0 1 6 .278z"/>
<path d="M10.794 3.148a.217.217 0 0 1 .412 0l.387 1.162c.173.518.579.924 1.097 1.097l1.162.387a.217.217 0 0 1 0 .412l-1.162.387a1.734 1.734 0 0 0-1.097 1.097l-.387 1.162a.217.217 0 0 1-.412 0l-.387-1.162A1.734 1.734 0 0 0 9.31 6.593l-1.162-.387a.217.217 0 0 1 0-.412l1.162-.387a1.734 1.734 0 0 0 1.097-1.097l.387-1.162zM13.863.099a.145.145 0 0 1 .274 0l.258.774c.115.346.386.617.732.732l.774.258a.145.145 0 0 1 0 .274l-.774.258a1.156 1.156 0 0 0-.732.732l-.258.774a.145.145 0 0 1-.274 0l-.258-.774a1.156 1.156 0 0 0-.732-.732l-.774-.258a.145.145 0 0 1 0-.274l.774-.258c.346-.115.617-.386.732-.732L13.863.1z"/>
</symbol>
<symbol id="sun-fill" viewBox="0 0 16 16">
<path d="M8 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM8 0a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 0zm0 13a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 13zm8-5a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2a.5.5 0 0 1 .5.5zM3 8a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2A.5.5 0 0 1 3 8zm10.657-5.657a.5.5 0 0 1 0 .707l-1.414 1.415a.5.5 0 1 1-.707-.708l1.414-1.414a.5.5 0 0 1 .707 0zm-9.193 9.193a.5.5 0 0 1 0 .707L3.05 13.657a.5.5 0 0 1-.707-.707l1.414-1.414a.5.5 0 0 1 .707 0zm9.193 2.121a.5.5 0 0 1-.707 0l-1.414-1.414a.5.5 0 0 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .707zM4.464 4.465a.5.5 0 0 1-.707 0L2.343 3.05a.5.5 0 1 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .708z"/>
</symbol>
</svg>
<button class="btn btn-link nav-link dropdown-toggle d-flex align-items-center"
id="bd-theme"
type="button"
aria-expanded="false"
data-bs-toggle="dropdown"
data-bs-display="static"
aria-label="Toggle theme (auto)">
<svg class="bi my-1 theme-icon-active"><use href="#circle-half"></use></svg>
</button>
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="bd-theme-text">
<li>
<button type="button" class="dropdown-item d-flex align-items-center" data-bs-theme-value="light" aria-pressed="false">
<svg class="bi me-2 opacity-50"><use href="#sun-fill"></use></svg>
Light
<svg class="bi ms-auto d-none"><use href="#check2"></use></svg>
</button>
</li>
<li>
<button type="button" class="dropdown-item d-flex align-items-center" data-bs-theme-value="dark" aria-pressed="false">
<svg class="bi me-2 opacity-50"><use href="#moon-stars-fill"></use></svg>
Dark
<svg class="bi ms-auto d-none"><use href="#check2"></use></svg>
</button>
</li>
<li>
<button type="button" class="dropdown-item d-flex align-items-center active" data-bs-theme-value="auto" aria-pressed="true">
<svg class="bi me-2 opacity-50"><use href="#circle-half"></use></svg>
Auto
<svg class="bi ms-auto d-none"><use href="#check2"></use></svg>
</button>
</li>
</ul>
</li>
</ul>
</div>
<div class="d-none d-lg-block">
<div class="td-search">
<div class="td-search__icon"></div>
<input type="search" class="td-search__input form-control td-search-input" placeholder="Search this site…" aria-label="Search this site…" autocomplete="off">
</div>
</div>
</div>
</nav>
</header>
<div class="container-fluid td-outer">
<div class="td-main">
<div class="row flex-xl-nowrap">
<main class="col-12 col-md-9 col-xl-8 ps-md-5" role="main">
<div class="td-content">
<div class="pageinfo pageinfo-primary d-print-none">
<p>
This is the multi-page printable view of this section.
<a href="#" onclick="print();return false;">Click here to print</a>.
</p><p>
<a href="/AudioBookRequest/docs/">Return to the regular view of this page</a>.
</p>
</div>
<h1 class="title">Documentation</h1>
<div class="lead">Welcome to the documentation for AudioBookRequest.</div>
<ul>
<li>1: <a href="#pg-17b09a9dc5200475d8a306f18e63a0f9">Getting Started</a></li>
<ul>
<li>1.1: <a href="#pg-a691501dfcc5f3c49a37c71cc3bc328c">Running the app</a></li>
<ul>
<li>1.1.1: <a href="#pg-56f160650d9ae8a1d51d83a2385ca883">Docker</a></li>
<li>1.1.2: <a href="#pg-2016a378b2772b1d4cb4b3b667daef42">Docker Compose</a></li>
<li>1.1.3: <a href="#pg-30980cef34b7434306b41404b74d95d8">Kubernetes</a></li>
<li>1.1.4: <a href="#pg-b0367b929f44cfb5a3742b2580ae37fa">Bare Metal</a></li>
</ul>
<li>1.2: <a href="#pg-adb41a14461f8e9f8c644d46e6993994">First Login</a></li>
<ul>
</ul>
</ul>
<li>2: <a href="#pg-68ec2370d0409cc27325be36693f9368">Tutorials</a></li>
<ul>
<li>2.1: <a href="#pg-e6c24feb23bd7b96e22e8ed3e8a6d652">Notifications</a></li>
<ul>
<li>2.1.1: <a href="#pg-9c98a220907242f8cb8a1c6a42049e67">Discord</a></li>
</ul>
<li>2.2: <a href="#pg-70cac3f21ec9ace937ed903becc9f4ca">OpenID Connect</a></li>
<ul>
</ul>
</ul>
<li>3: <a href="#pg-dd948255948d6b59b32c471abcb62997">Concepts</a></li>
<ul>
<li>3.1: <a href="#pg-a73d3b4396cb5ebf2945eadbf85659c8">Environment Variables</a></li>
</ul>
<li>4: <a href="#pg-ca560d86eea09e7d79614b77b0c381c8">Local Development</a></li>
<ul>
</ul>
<li>5: <a href="#pg-54889070d33ff8ba421707b96841ef23">Contribution Guidelines</a></li>
</ul>
<div class="content">
<h2 id="what-is-it">What is it?<a class="td-heading-self-link" href="#what-is-it" aria-label="Heading self-link"></a></h2>
<p>AudioBookRequest is a tool that can be used in combination with media servers
like plex/audiobookserver/jellyfin/etc. to easily set up a pipeline for creating
a wishlist of audiobooks you want to listen to.</p>
<h2 id="why-do-i-want-it">Why do I want it?<a class="td-heading-self-link" href="#why-do-i-want-it" aria-label="Heading self-link"></a></h2>
<p>Help your user know if your project will help them. Useful information can
include:</p>
<ul>
<li>
<p><strong>What is it good for?</strong>: If you have multiple people using your ABS instance
and you don&rsquo;t want them to always have to message you for new books or you
don&rsquo;t want to give them access to something like Readarr/Prowlarr, you can use
AudioBookRequest to allow them to easily request any books they want to listen
to and have it notify and/or automatically start any required downloads.</p>
</li>
<li>
<p><strong>What is it not good for?</strong>: AudioBookRequest is <strong>not</strong> a full replacement
for Readarr, nor is that the plan. Readarr does a lot of things, but it is
also currently in a very messy state development-wise. ABR does not currently
keep track of your library, while automatically downloading new releases and
trying to upgrade the quality of already existing audiobooks. These are
features that are less relevant with audiobooks.</p>
</li>
<li>
<p><strong>What is it <em>not yet</em> good for?</strong>: AudioBookRequest is currently unable to
move any downloads, add metadata to files, or rename files according to some
structure.</p>
</li>
</ul>
<h2 id="where-should-i-go-next">Where should I go next?<a class="td-heading-self-link" href="#where-should-i-go-next" aria-label="Heading self-link"></a></h2>
<p>Head on over to the following sections to learn more about AudioBookRequest:</p>
<ul>
<li><a href="/AudioBookRequest/docs/getting-started/">Getting Started</a>: Get started with AudioBookRequest</li>
<li><a href="/AudioBookRequest/docs/tutorials/notifications/">Notifications</a>: Check out some example code!</li>
</ul>
</div>
</div>
<div class="td-content" style="page-break-before: always">
<h1 id="pg-17b09a9dc5200475d8a306f18e63a0f9">1 - Getting Started</h1>
<div class="lead">What does your user need to know to try your project?</div>
<h2 id="prerequisites">Prerequisites<a class="td-heading-self-link" href="#prerequisites" aria-label="Heading self-link"></a></h2>
<p>AudioBookRequest has been packaged as a <a href="https://www.docker.com/">Docker</a> image
to make it easy to deploy and run on servers. While it is possible to run ABR
without Docker, that option should be avoided if possible and only used for
local development, as a lot of things can change from version to version.</p>
<h2 id="setup">Setup<a class="td-heading-self-link" href="#setup" aria-label="Heading self-link"></a></h2>
<p>Head to <a href="/AudioBookRequest/docs/getting-started/running-the-app/">Running the app</a> for instructions on how to run ABR.</p>
</div>
<div class="td-content" style="page-break-before: always">
<h1 id="pg-a691501dfcc5f3c49a37c71cc3bc328c">1.1 - Running the app</h1>
<div class="lead">Getting AudioBookRequest up and running.</div>
<p>The app has a docker image that simplifies the deployment. The preferred methods
of running the application all revolve around running the Docker image in
different ways.</p>
<p>Select the method you want to use to deploy below or if your tool is not listed
(for example Portainer), head to the <a href="/AudioBookRequest/docs/getting-started/running-the-app/docker/">docker</a> page.</p>
</div>
<div class="td-content" style="page-break-before: always">
<h1 id="pg-56f160650d9ae8a1d51d83a2385ca883">1.1.1 - Docker</h1>
<div class="lead">How to get started using Docker.</div>
<p>If you prefer to run the app manually with docker, you can simply run the
following command:</p>
<div class="highlight"><pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker run -p 8000:8000 -v <span style="color:#c678dd">$(</span><span style="color:#ef8383">pwd</span><span style="color:#c678dd">)</span>/config:/config markbeep/audiobookrequest:1
</span></span></code></pre></div><p>This will start the container on port 8000 and create the <code>config/</code> directory in
your current working directory.</p>
<p>The above command might break on Windows. Instead, use
<code>${PWD}\config:/config ...</code> in PowerShell or <code>%cd%\config:/config ...</code> in
Windows Command Prompt.</p>
<div class="alert alert-primary" role="alert">
<h4 class="alert-heading">Versions</h4>
<p>The <code>:1</code> at the end denotes the image version.
Check <a href="https://hub.docker.com/r/markbeep/audiobookrequest/tags">dockerhub</a> for
any other versions you can use instead.</p>
<p>The <code>:latest</code> tag will give you the last non-nightly release, but it is not
recommended incase of changes that are not backwards compatible.</p>
<p>For experimental builds (latest commits in the <code>main</code> branch of the repository),
the <code>:nightly</code> version tag can be used.</p>
</div>
</div>
<div class="td-content" style="page-break-before: always">
<h1 id="pg-2016a378b2772b1d4cb4b3b667daef42">1.1.2 - Docker Compose</h1>
<div class="lead">How to get started using Docker-Compose.</div>
<p>Docker-compose works the similar way as <a href="/AudioBookRequest/docs/getting-started/running-the-app/docker/">Docker</a>.</p>
<p>The basic docker compose file is as follows:</p>
<div class="highlight"><pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#e06c75">services</span>:
</span></span><span style="display:flex;"><span> <span style="color:#e06c75">web</span>:
</span></span><span style="display:flex;"><span> <span style="color:#e06c75">image</span>: <span style="color:#98c379">markbeep/audiobookrequest:1</span>
</span></span><span style="display:flex;"><span> <span style="color:#e06c75">ports</span>:
</span></span><span style="display:flex;"><span> - <span style="color:#98c379">&#39;8000:8000&#39;</span>
</span></span><span style="display:flex;"><span> <span style="color:#e06c75">volumes</span>:
</span></span><span style="display:flex;"><span> - <span style="color:#98c379">./config:/config</span>
</span></span></code></pre></div><p>If you want to add any environment variables, you can add them as explained
<a href="https://docs.docker.com/compose/how-tos/environment-variables/set-environment-variables/">here</a>.
It would look along the lines of this:</p>
<div class="highlight"><pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#e06c75">services</span>:
</span></span><span style="display:flex;"><span> <span style="color:#e06c75">web</span>:
</span></span><span style="display:flex;"><span> <span style="color:#e06c75">image</span>: <span style="color:#98c379">markbeep/audiobookrequest:1</span>
</span></span><span style="display:flex;"><span> <span style="color:#e06c75">ports</span>:
</span></span><span style="display:flex;"><span> - <span style="color:#98c379">&#39;8000:5432&#39;</span>
</span></span><span style="display:flex;"><span> <span style="color:#e06c75">volumes</span>:
</span></span><span style="display:flex;"><span> - <span style="color:#98c379">./config:/config</span>
</span></span><span style="display:flex;"><span> <span style="color:#e06c75">environment</span>:
</span></span><span style="display:flex;"><span> <span style="color:#e06c75">ABR_APP__PORT</span>: <span style="color:#d19a66">5432</span>
</span></span><span style="display:flex;"><span> <span style="color:#e06c75">ABR_APP__OPENAPI_ENABLED</span>: <span style="color:#b756ff;font-weight:bold">true</span>
</span></span></code></pre></div>
</div>
<div class="td-content" style="page-break-before: always">
<h1 id="pg-30980cef34b7434306b41404b74d95d8">1.1.3 - Kubernetes</h1>
<div class="lead">How to get started using Kubernetes.</div>
<p>Here&rsquo;s an example for a kubernetes deployment file you&rsquo;d use:</p>
<div class="highlight"><pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#e06c75">apiVersion</span>: <span style="color:#98c379">apps/v1</span>
</span></span><span style="display:flex;"><span><span style="color:#e06c75">kind</span>: <span style="color:#98c379">Deployment</span>
</span></span><span style="display:flex;"><span><span style="color:#e06c75">metadata</span>:
</span></span><span style="display:flex;"><span> <span style="color:#e06c75">name</span>: <span style="color:#98c379">audiobookrequest</span>
</span></span><span style="display:flex;"><span> <span style="color:#e06c75">labels</span>:
</span></span><span style="display:flex;"><span> <span style="color:#e06c75">app</span>: <span style="color:#98c379">audiobookrequest</span>
</span></span><span style="display:flex;"><span><span style="color:#e06c75">spec</span>:
</span></span><span style="display:flex;"><span> <span style="color:#e06c75">replicas</span>: <span style="color:#d19a66">1</span>
</span></span><span style="display:flex;"><span> <span style="color:#e06c75">selector</span>:
</span></span><span style="display:flex;"><span> <span style="color:#e06c75">matchLabels</span>:
</span></span><span style="display:flex;"><span> <span style="color:#e06c75">app</span>: <span style="color:#98c379">audiobookrequest</span>
</span></span><span style="display:flex;"><span> <span style="color:#e06c75">template</span>:
</span></span><span style="display:flex;"><span> <span style="color:#e06c75">metadata</span>:
</span></span><span style="display:flex;"><span> <span style="color:#e06c75">labels</span>:
</span></span><span style="display:flex;"><span> <span style="color:#e06c75">app</span>: <span style="color:#98c379">audiobookrequest</span>
</span></span><span style="display:flex;"><span> <span style="color:#e06c75">spec</span>:
</span></span><span style="display:flex;"><span> <span style="color:#e06c75">containers</span>:
</span></span><span style="display:flex;"><span> - <span style="color:#e06c75">name</span>: <span style="color:#98c379">audiobookrequest</span>
</span></span><span style="display:flex;"><span> <span style="color:#e06c75">image</span>: <span style="color:#98c379">markbeep/audiobookrequest:1</span>
</span></span><span style="display:flex;"><span> <span style="color:#e06c75">imagePullPolicy</span>: <span style="color:#98c379">Always</span>
</span></span><span style="display:flex;"><span> <span style="color:#e06c75">volumeMounts</span>:
</span></span><span style="display:flex;"><span> - <span style="color:#e06c75">mountPath</span>: <span style="color:#98c379">/config</span>
</span></span><span style="display:flex;"><span> <span style="color:#e06c75">name</span>: <span style="color:#98c379">abr-config</span>
</span></span><span style="display:flex;"><span> <span style="color:#e06c75">ports</span>:
</span></span><span style="display:flex;"><span> - <span style="color:#e06c75">name</span>: <span style="color:#98c379">http-request</span>
</span></span><span style="display:flex;"><span> <span style="color:#e06c75">containerPort</span>: <span style="color:#d19a66">8000</span>
</span></span><span style="display:flex;"><span> <span style="color:#e06c75">volumes</span>:
</span></span><span style="display:flex;"><span> - <span style="color:#e06c75">name</span>: <span style="color:#98c379">abr-config</span>
</span></span><span style="display:flex;"><span> <span style="color:#e06c75">hostPath</span>:
</span></span><span style="display:flex;"><span> <span style="color:#e06c75">path</span>: <span style="color:#98c379">/mnt/disk/AudioBookRequest/</span>
</span></span></code></pre></div><p>For the volume you can assign it a host path on a node, or assign it to a PVC.</p>
</div>
<div class="td-content" style="page-break-before: always">
<h1 id="pg-b0367b929f44cfb5a3742b2580ae37fa">1.1.4 - Bare Metal</h1>
<div class="lead">How to get started <strong>without</strong> Docker.</div>
<div class="alert alert-warning" role="alert">
<h4 class="alert-heading">Warning</h4>
<p>The bare metal approach should
only be the last option. Try to get it working with Docker or get support on the
Discord server before trying to set ABR up for a bare metal deployment.</p>
<p>There are no guarantees that if one version works locally that it won&rsquo;t suddenly
break in the next because of a new dependency, new file structure or something
else.</p>
</div>
<p>To run ABR locally without Docker, the same steps as for the
<a href="/AudioBookRequest/docs/local-development/">local development</a> have to be followed. First, follow
the instructions to get local development working.</p>
<p>Once local development works, there are a few adjustments that have to be made
to run the app in production mode instead of debug/local mode.</p>
<ol>
<li>Delete the <code>.env.local</code> file or delete all contents in it.</li>
<li>Run the python script to fetch and download all required javascript files:
<code>uv run python /app/util/fetch_js.py</code>. This should populate your <code>static/</code>
directory with some new js files.</li>
<li>Instead of running <code>fastapi dev</code> you want to execute <code>fastapi start</code> to start
the webserver.</li>
<li>Create a file called <code>.env</code> and place any environment variables you want to
set in there.</li>
<li>If you intend to change the port (documented as the env variable
<code>ABR_APP__PORT</code>), you&rsquo;ll have to run fastapi with the <code>--port &lt;PORT&gt;</code> flag:
<div class="highlight"><pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>fastapi run --port <span style="color:#d19a66">5432</span>
</span></span></code></pre></div></li>
</ol>
<p>With these changes your deployment will be running in production mode.</p>
</div>
<div class="td-content" style="page-break-before: always">
<h1 id="pg-adb41a14461f8e9f8c644d46e6993994">1.2 - First Login</h1>
<div class="lead">Logging in the first time</div>
<p>Once you get AudioBookRequest running, you&rsquo;ll be greeted with an initialization
page when you visit the website.</p>
<p><img src="/AudioBookRequest/docs/getting-started/first-login/login.png" alt="Login Page"></p>
<p>On this page you have to set the type of login you want to use for the app and
then create the login details for the root admin. You can choose from 3 login
types on this page:</p>
<ul>
<li><strong>Basic Auth:</strong> This is the most simple form of login. Your browser will show
a popup login dialog which will then be used to log in to the site. Password
managers usually don&rsquo;t work for this type of login, but because it is very
simple you can also easily send authenticated requests in scripts.
<a href="https://en.wikipedia.org/wiki/Basic_access_authentication">Read more here</a>.</li>
<li><strong>Forms:</strong> This is the standard type of login where you fill out a login-form.
Password managers usually work with this.</li>
<li><strong>None:</strong> This turns off all authentication. This is best if you have a proxy
and are the only user or you don&rsquo;t mind everyone having root access to the
site.</li>
</ul>
<div class="alert alert-primary" role="alert">
<h4 class="alert-heading">OpenID Connect</h4>
AudioBookRequest supports logging in with
OpenID Connect. You&rsquo;ll have to first select one of the login-types above to be
able to adjust the OIDC settings. Head to the
<a href="../../tutorials/oidc">OIDC Tutorial</a> for more info.
</div>
<div class="alert alert-warning" role="alert">
<h4 class="alert-heading">Warning</h4>
Even if you intend to turn off all
authentication or want to later use OIDC, you should take note of the
username/password you set. You&rsquo;ll need them once you decide to ever change the
login type.
</div>
</div>
<div class="td-content" style="page-break-before: always">
<h1 id="pg-68ec2370d0409cc27325be36693f9368">2 - Tutorials</h1>
<div class="lead">Tutorials about how to setup certain features with more detail.</div>
</div>
<div class="td-content" style="">
<h1 id="pg-e6c24feb23bd7b96e22e8ed3e8a6d652">2.1 - Notifications</h1>
<div class="lead">How to send notifications.</div>
<div class="alert alert-primary" role="alert">
<h4 class="alert-heading">Todo</h4>
</div>
</div>
<div class="td-content" style="">
<h1 id="pg-9c98a220907242f8cb8a1c6a42049e67">2.1.1 - Discord</h1>
<div class="lead">Sending notifications to Discord.</div>
<div class="alert alert-primary" role="alert">
<h4 class="alert-heading">Todo</h4>
</div>
</div>
<div class="td-content" style="page-break-before: always">
<h1 id="pg-70cac3f21ec9ace937ed903becc9f4ca">2.2 - OpenID Connect</h1>
<div class="lead">Setting up OIDC login</div>
<p>OIDC allows you to use the same login across multiple apps. This guide will show
you how to set up OIDC with Authentik, but the concepts are the same or similar
for other providers.</p>
<h2 id="setup-a-provider-on-authentik">Setup a provider on Authentik<a class="td-heading-self-link" href="#setup-a-provider-on-authentik" aria-label="Heading self-link"></a></h2>
<ol>
<li>
<p>You want to first create an application on Authentik. The settings here
don&rsquo;t play a role for AudioBookRequest though.</p>
</li>
<li>
<p>You then want to create an OAuth2/OpenID Provider:</p>
<p><img src="/AudioBookRequest/docs/tutorials/oidc/authentik-oidc.png" alt="Authentik OIDC"></p>
</li>
<li>
<p>Configure the settings as preferred. The important two values are the
<code>Client ID</code> and <code>Client Secret</code>. Take note of those. You should also set the
redirect URL that the OIDC provider will redirect you to after a succesful
login. This has to be the domain of your ABR instance with <code>/auth/oidc</code>
appended.</p>
<p><img src="/AudioBookRequest/docs/tutorials/oidc/authentik-provider.png" alt="Authentik Provider"></p>
<div class="alert alert-warning" role="alert">
<h4 class="alert-heading">Warning</h4>
Make sure you correctly set
<code>http</code> or <code>https</code> in the redirect URL. This depends on how you access
AudioBookRequest.
</div>
</li>
<li>
<p>Set the scopes that ABR can get access to. You should always allow for the
<code>openid</code> scope. Any other scopes are optional. You&rsquo;ll have to check with
your OIDC provider to see what what scopes are required to get a
name/username and groups. &ldquo;Subject mode&rdquo; is a unique identifier for the
user. This can be used as the username on ABR.</p>
<p><img src="/AudioBookRequest/docs/tutorials/oidc/authentik-scopes.png" alt="Authentik Scopes"></p>
</li>
<li>
<p>Assign your newly created provider to the ABR application.</p>
</li>
</ol>
<h2 id="setup-settings-in-abr">Setup settings in ABR<a class="td-heading-self-link" href="#setup-settings-in-abr" aria-label="Heading self-link"></a></h2>
<ol>
<li>On AudioBookRequest, head to <code>Settings&gt;Security</code> and set the &ldquo;Login Type&rdquo; to
&ldquo;OpenID Connect&rdquo;.</li>
<li>Paste the &ldquo;Client ID&rdquo; and &ldquo;Client Secret&rdquo; into the respective fields.</li>
<li>Your &ldquo;OIDC Configuration Endpoint&rdquo; depends on the OIDC provider you use. For
Authentik, it&rsquo;s usually along the lines of
<a href="https://domain.com/application/o/audiobookrequest/.well-known/openid-configuration">https://domain.com/application/o/audiobookrequest/.well-known/openid-configuration</a>.
You&rsquo;ll have to find that for your own provider. Visiting the url should give
you a JSON-formatted object with different endpoints and details given.</li>
<li>The &ldquo;OIDC Scopes&rdquo; are the ones defined above separated by a space. <code>openid</code>
is always required. Any other scopes like <code>email</code> or <code>group</code> are only
required if you intend to use the email for the username or respectively
extract the group of the user.</li>
<li>&ldquo;OIDC Username Claim&rdquo; <strong>has to be a unique identifier</strong> which is used as the
username for the user. <code>sub</code> is always available, but you might prefere to
use <code>email</code> or <code>username</code> (with the correctly added scope).</li>
<li>Depending on what you used above for the redirect URL, set <code>http</code> or <code>https</code>.
<div class="alert alert-warning" role="alert">
<h4 class="alert-heading">Warning</h4>
<code>http/s</code> has to match-up with
what protocol your redirect-url uses. Providers <em>will</em> reject logins if this
does not match up.
</div>
</li>
<li><em>Optional</em>: The &ldquo;OIDC Logout URL&rdquo; is where you&rsquo;re redirected if you select to
log out in ABR. OIDC Providers allow you to invalidate the session on this
URL. While this value is optional, not adding it might break logging out
slightly because the session can&rsquo;t properly be invalidated.</li>
</ol>
<h2 id="groups">Groups<a class="td-heading-self-link" href="#groups" aria-label="Heading self-link"></a></h2>
<p>&ldquo;OIDC Group Claim&rdquo; is optional, but allows you to handle the role distribution
of users in your OIDC provider instead of in ABR. The exact claim that sends
along the information depends on your OIDC provider. The OIDC provider can
provide a single string or list of strings.</p>
<p>The groups have to be named exactly one of <code>untrusted</code>, <code>trusted</code>, or <code>admin</code>.
The letter case does not matter.</p>
<div class="alert alert-primary" role="alert">
For Authentik, the group claim name is <code>groups</code> and requires the
<code>profile</code> scope. If you assign a user to a group named <code>trusted</code>, that user will
receive the <code>Trusted</code> role once they login to AudioBookRequest.
</div>
</div>
<div class="td-content" style="page-break-before: always">
<h1 id="pg-dd948255948d6b59b32c471abcb62997">3 - Concepts</h1>
<div class="lead">Concepts used in ABR in more detail.</div>
</div>
<div class="td-content" style="">
<h1 id="pg-a73d3b4396cb5ebf2945eadbf85659c8">3.1 - Environment Variables</h1>
<div class="lead">List of the environment variables that can be set.</div>
<table>
<thead>
<tr>
<th>ENV</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>ABR_APP__PORT</code></td>
<td>The port to run the server on.</td>
<td>8000</td>
</tr>
<tr>
<td><code>ABR_APP__DEBUG</code></td>
<td>If to enable debug mode. Not recommended for production.</td>
<td>false</td>
</tr>
<tr>
<td><code>ABR_APP__OPENAPI_ENABLED</code></td>
<td>If set to <code>true</code>, enables an OpenAPI specs page on <code>/docs</code>.</td>
<td>false</td>
</tr>
<tr>
<td><code>ABR_APP__CONFIG_DIR</code></td>
<td>The directory path where persistant data and configuration is stored. If ran using Docker or Kubernetes, this is the location a volume should be mounted to.</td>
<td>/config</td>
</tr>
<tr>
<td><code>ABR_APP__LOG_LEVEL</code></td>
<td>One of <code>DEBUG</code>, <code>INFO</code>, <code>WARN</code>, <code>ERROR</code>.</td>
<td>INFO</td>
</tr>
<tr>
<td><code>ABR_APP__BASE_URL</code></td>
<td>Defines the base url the website is hosted at. If the website is accessed at <code>example.org/abr/</code>, set the base URL to <code>/abr/</code></td>
<td></td>
</tr>
<tr>
<td><code>ABR_DB__SQLITE_PATH</code></td>
<td>If relative, path and name of the sqlite database in relation to <code>ABR_APP__CONFIG_DIR</code>. If absolute (path starts with <code>/</code>), the config dir is ignored and only the absolute path is used.</td>
<td>db.sqlite</td>
</tr>
</tbody>
</table>
<div class="alert alert-primary" role="alert">
<h4 class="alert-heading">Note</h4>
There are two underscores (<code>__</code>) between the first
and second part of each environment variable like between <code>ABR_APP</code> and <code>PORT</code>.
</div>
</div>
<div class="td-content" style="page-break-before: always">
<h1 id="pg-ca560d86eea09e7d79614b77b0c381c8">4 - Local Development</h1>
<div class="lead">How to set up the project for local development.</div>
<h2 id="requirements">Requirements<a class="td-heading-self-link" href="#requirements" aria-label="Heading self-link"></a></h2>
<ul>
<li>Python &gt;3.12</li>
<li><a href="https://docs.astral.sh/uv/">uv</a>. Used as the package manager</li>
<li>node.js. Exact version is not too important. Too old versions might fail when
installing packages.</li>
</ul>
<h2 id="setup">Setup<a class="td-heading-self-link" href="#setup" aria-label="Heading self-link"></a></h2>
<p>Virtual environments help isolate any installed packages to this directory.
Project was made with <code>Python 3.12</code> and uses new generics introduced in 3.12.
Older python versions might not work or could have incorrect typing.</p>
<p>For improved dependency management, <code>uv</code> is used instead of <code>pip</code>.</p>
<div class="highlight"><pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span><span style="color:#8a93a5;font-style:italic"># This creates the venv as well as installs all dependencies</span>
</span></span><span style="display:flex;"><span>uv sync
</span></span></code></pre></div><p>For local development, environment variables can be added to <code>.env.local</code> and
they&rsquo;ll be used wherever required. This file is not used in production.</p>
<h2 id="initialize-database">Initialize Database<a class="td-heading-self-link" href="#initialize-database" aria-label="Heading self-link"></a></h2>
<p><a href="https://alembic.sqlalchemy.org/en/latest/">Alembic</a> is used to create database
migrations. Run the following before starting up the application for the first
time. It will initialize the directory if non-existant, create the database file
as well as execute any required migrations.</p>
<div class="highlight"><pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>uv run alembic upgrade heads
</span></span></code></pre></div><p><em>In case of any model changes, remember to create migrations using
<code>alembic revision --autogenerate -m &quot;&lt;message&gt;&quot;</code>.</em></p>
<h2 id="generate-the-css-files">Generate the CSS files<a class="td-heading-self-link" href="#generate-the-css-files" aria-label="Heading self-link"></a></h2>
<p><a href="https://tailwindcss.com/">Tailwindcss</a> is used to style elements using CSS. On
top of that, <a href="https://daisyui.com/">daisyUI</a> is for easy and consistent
component styling.</p>
<p>Install daisyUI and start Tailwindcss watcher. Required for any CSS styling.</p>
<div class="highlight"><pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>npm i
</span></span><span style="display:flex;"><span>uv run tailwindcss -i static/tw.css -o static/globals.css --watch
</span></span><span style="display:flex;"><span><span style="color:#8a93a5;font-style:italic"># Alternatively npx can be used to run tailwindcss</span>
</span></span><span style="display:flex;"><span>npx @tailwindcss/cli@4 -i static/tw.css -o static/globals.css --watch
</span></span></code></pre></div><p>Tailwind has to run anytime something is changed in the HTML template files.</p>
<h2 id="run-the-app">Run the app<a class="td-heading-self-link" href="#run-the-app" aria-label="Heading self-link"></a></h2>
<p>Running the application is best done in multiple terminals:</p>
<ol>
<li>
<p>Start FastAPI dev mode:</p>
<div class="highlight"><pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>uv run fastapi dev
</span></span></code></pre></div><p>Website can be visited at http://localhost:8000.</p>
</li>
<li>
<p><em>Optional:</em> Start browser-sync. This hot reloads the website when the html
template or python files are modified:</p>
</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>browser-sync http://localhost:8000 --files templates/** --files app/**
</span></span></code></pre></div><p><strong>NOTE</strong>: Website has to be visited at http://localhost:3000 instead.</p>
<h2 id="docker-compose">Docker Compose<a class="td-heading-self-link" href="#docker-compose" aria-label="Heading self-link"></a></h2>
<p>The docker compose can also be used to run the app locally. Any services that
are required can be added to it for easy testing:</p>
<div class="highlight"><pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker compose up --build
</span></span></code></pre></div><p>The local context (ABR) is in a docker compose profile called <code>local</code>, which is
only run if explicitly stated as follows:</p>
<div class="highlight"><pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker compose --profile <span style="color:#ef8383">local</span> up
</span></span></code></pre></div>
</div>
<div class="td-content" style="page-break-before: always">
<h1 id="pg-54889070d33ff8ba421707b96841ef23">5 - Contribution Guidelines</h1>
<div class="lead">How to contribute to the docs.</div>
<p>We use <a href="https://gohugo.io/">Hugo</a> to format and generate our website, the
<a href="https://github.com/google/docsy">Docsy</a> theme for styling and site structure,
and <a href="https://pages.github.com/">Github Pages</a> to manage the deployment of the
site. Hugo is an open-source static site generator that provides us with
templates, content organisation in a standard directory structure, and a website
generation engine. You write the pages in Markdown (or HTML if you want), and
Hugo wraps them up into a website.</p>
<p>All submissions require review. We use GitHub pullas requests for this purpose.
Consult <a href="https://help.github.com/articles/about-pull-requests/">GitHub Help</a> for
more information on using pull requests.</p>
<h2 id="quick-start-with-hugo">Quick start with Hugo<a class="td-heading-self-link" href="#quick-start-with-hugo" aria-label="Heading self-link"></a></h2>
<p>Here&rsquo;s a quick guide to updating the docs. It assumes you&rsquo;re familiar with the
GitHub workflow and you&rsquo;re happy to use the automated preview of your doc
updates:</p>
<ol>
<li>Fork the
<a href="https://github.com/markbeep/AudioBookRequest">AudioBookRequest repo</a> on
GitHub.</li>
<li>Make your changes and send a pull request (PR).</li>
<li>If you&rsquo;re not yet ready for a review, add &ldquo;WIP&rdquo; to the PR name to indicate
it&rsquo;s a work in progress. (<strong>Don&rsquo;t</strong> add the Hugo property &ldquo;draft = true&rdquo; to
the page front matter, because that prevents the auto-deployment of the
content preview described in the next point.)</li>
<li>When you&rsquo;re ready for a review, add a comment to the PR, and remove any &ldquo;WIP&rdquo;
markers.</li>
</ol>
<h2 id="updating-a-single-page">Updating a single page<a class="td-heading-self-link" href="#updating-a-single-page" aria-label="Heading self-link"></a></h2>
<p>If you&rsquo;ve just spotted something you&rsquo;d like to change while using the docs,
Docsy has a shortcut for you:</p>
<ol>
<li>Click <strong>Edit this page</strong> in the top right hand corner of the page.</li>
<li>If you don&rsquo;t already have an up to date fork of the project repo, you are
prompted to get one - click <strong>Fork this repository and propose changes</strong> or
<strong>Update your Fork</strong> to get an up to date version of the project to edit. The
appropriate page in your fork is displayed in edit mode.</li>
<li>Follow the rest of the <a href="/AudioBookRequest/docs/contribution-guidelines/#quick-start-with-hugo">Quick start with Hugo</a>
process above to make, preview, and propose your changes.</li>
</ol>
<h2 id="previewing-your-changes-locally">Previewing your changes locally<a class="td-heading-self-link" href="#previewing-your-changes-locally" aria-label="Heading self-link"></a></h2>
<p>If you want to run your own local Hugo server to preview your changes as you
work:</p>
<ol>
<li>
<p>Follow the instructions in <a href="../getting-started/docs">Getting started</a> to
install Hugo and any other tools you need. You&rsquo;ll need at least <strong>Hugo
version 0.146.0</strong> (we recommend using the most recent available version), and
it must be the <strong>extended</strong> version, which supports SCSS.</p>
</li>
<li>
<p>Fork the
<a href="https://github.com/markbeep/AudioBookRequest">AudioBookRequest repo</a> into
your own project, then create a local copy using <code>git clone</code>.</p>
<pre tabindex="0"><code>git clone --branch v0.12.0 --depth 1 https://github.com/markbeep/AudioBookRequest.git
</code></pre></li>
<li>
<p>Run <code>hugo server</code> in the site root directory. By default your site will be
available at http://localhost:1313/. Now that you&rsquo;re serving your site
locally, Hugo will watch for changes to the content and automatically refresh
your site.</p>
</li>
<li>
<p>Continue with the usual GitHub workflow to edit files, commit them, push the
changes up to your fork, and create a pull request.</p>
</li>
</ol>
<h2 id="creating-an-issue">Creating an issue<a class="td-heading-self-link" href="#creating-an-issue" aria-label="Heading self-link"></a></h2>
<p>If you&rsquo;ve found a problem in the docs, but you&rsquo;re not sure how to fix it
yourself, please create an issue in the
<a href="https://github.com/markbeep/AudioBookRequest/issues">AudioBookRequest repo</a>.
You can also create an issue about a specific page by clicking the <strong>Create
Issue</strong> button in the top right hand corner of the page.</p>
<h2 id="useful-resources">Useful resources<a class="td-heading-self-link" href="#useful-resources" aria-label="Heading self-link"></a></h2>
<ul>
<li><a href="https://www.docsy.dev/docs/">Docsy user guide</a>: All about Docsy, including
how it manages navigation, look and feel, and multi-language support.</li>
<li><a href="https://gohugo.io/documentation/">Hugo documentation</a>: Comprehensive
reference for Hugo.</li>
<li><a href="https://guides.github.com/activities/hello-world/">Github Hello World!</a>: A
basic introduction to GitHub concepts and workflow.</li>
</ul>
</div>
</main>
</div>
</div>
<footer class="td-footer row d-print-none">
<div class="container-fluid">
<div class="row mx-md-2">
<div class="td-footer__left col-6 col-sm-4 order-sm-1">
<ul class="td-footer__links-list">
<li class="td-footer__links-item" data-bs-toggle="tooltip" title="Discord" aria-label="Discord">
<a target="_blank" rel="noopener" href="https://discord.gg/SsFRXWMg7s" aria-label="Discord">
<i class="fab fa-discord"></i>
</a>
</li>
</ul>
</div><div class="td-footer__right col-6 col-sm-4 order-sm-3">
<ul class="td-footer__links-list">
<li class="td-footer__links-item" data-bs-toggle="tooltip" title="GitHub" aria-label="GitHub">
<a target="_blank" rel="noopener" href="https://github.com/google/docsy" aria-label="GitHub">
<i class="fab fa-github"></i>
</a>
</li>
</ul>
</div><div class="td-footer__center col-12 col-sm-4 py-2 order-sm-2">
<span class="td-footer__copyright">&copy;
2025&ndash;2025
<span class="td-footer__authors">markbeep | <a href="https://creativecommons.org/licenses/by/4.0">CC BY 4.0</a> |</span></span><span class="td-footer__all_rights_reserved">All Rights Reserved</span>
</div>
</div>
</div>
</footer>
</div>
<script src="/AudioBookRequest/js/main.js"></script>
<script defer src="/AudioBookRequest/js/click-to-copy.js" crossorigin="anonymous"></script>
<script src='/AudioBookRequest/js/tabpane-persist.js'></script>
</body>
</html>