Compare commits

..

No commits in common. 'develop' and 'gek/admin-api-disable-cors' have entirely different histories.

  1. 2
      .github/workflows/auto-comment-on-label.yaml
  2. 2
      .github/workflows/browser-testing.yml
  3. 6
      .github/workflows/codeql-analysis.yml
  4. 2
      .github/workflows/go-lint.yml
  5. 4
      .github/workflows/go-tests.yaml
  6. 2
      .github/workflows/hls-tests.yml
  7. 2
      .github/workflows/javascript-format-build.yml
  8. 2
      .github/workflows/screenshots.yml
  9. 2
      .github/workflows/shellcheck.yml
  10. 4
      config/constants.go
  11. 47
      controllers/hls.go
  12. 36
      controllers/index.go
  13. 17
      core/storageproviders/s3Storage.go
  14. 18
      go.mod
  15. 62
      go.sum
  16. 27
      main.go
  17. 8
      router/middleware/auth.go
  18. 101
      router/router.go
  19. 2
      static/web/404.html
  20. 2
      static/web/404/index.html
  21. 1
      static/web/_next/static/7FO45oyNxons-CT00qbSN/_buildManifest.js
  22. 1
      static/web/_next/static/YI8_oqtLGnf9C9rRplixa/_buildManifest.js
  23. 0
      static/web/_next/static/YI8_oqtLGnf9C9rRplixa/_ssgManifest.js
  24. 2
      static/web/_next/static/chunks/1024-c1d97a020e4f8ed2.js
  25. 2
      static/web/_next/static/chunks/1051-8a5ca8b5f9f98bb1.js
  26. 2
      static/web/_next/static/chunks/1700-dce7a9059374b420.js
  27. 2
      static/web/_next/static/chunks/1749-797abf8460ff31f5.js
  28. 2
      static/web/_next/static/chunks/1869.ba2b5785504648d0.js
  29. 2
      static/web/_next/static/chunks/2122-616c9b060e9a17fe.js
  30. 2
      static/web/_next/static/chunks/2130-877795ab1b81dcae.js
  31. 2
      static/web/_next/static/chunks/2474-0fb59d6b3117ab83.js
  32. 2
      static/web/_next/static/chunks/2891-2558c60aab79fabe.js
  33. 2
      static/web/_next/static/chunks/3068-03c5c6410150c24e.js
  34. 2
      static/web/_next/static/chunks/3595-6ecb023807c38df1.js
  35. 2
      static/web/_next/static/chunks/3942-48366093b3b60cf4.js
  36. 2
      static/web/_next/static/chunks/4060-34a83a0cf0d9ebea.js
  37. 2
      static/web/_next/static/chunks/4104-586602c027ce22f8.js
  38. 2
      static/web/_next/static/chunks/4281-8d6901fb475aebae.js
  39. 2
      static/web/_next/static/chunks/4680-b1fbead3ac6081fd.js
  40. 2
      static/web/_next/static/chunks/4749-e09a7722eb2edf7f.js
  41. 2
      static/web/_next/static/chunks/4938-7c5f68df37885201.js
  42. 2
      static/web/_next/static/chunks/4ad82c5e-c823a06c208c0a68.js
  43. 1
      static/web/_next/static/chunks/5056-c58a7fe44a122c7d.js
  44. 1
      static/web/_next/static/chunks/5056-d229a49abadc86bd.js
  45. 2
      static/web/_next/static/chunks/5283-6f7b07a8e8569a2b.js
  46. 2
      static/web/_next/static/chunks/5485.f113dbbc741e3a39.js
  47. 2
      static/web/_next/static/chunks/5560-fb30897479c6d750.js
  48. 2
      static/web/_next/static/chunks/5578-d6de74db6520302a.js
  49. 2
      static/web/_next/static/chunks/5596-c57e0f6790463985.js
  50. 4
      static/web/_next/static/chunks/583-26b1e49e1cef0623.js
  51. 2
      static/web/_next/static/chunks/5849.9f23ac5f98896080.js
  52. 2
      static/web/_next/static/chunks/5891-f2b8c2ff83489659.js
  53. 2
      static/web/_next/static/chunks/6017-4077566221f4f92e.js
  54. 2
      static/web/_next/static/chunks/6108-458c185100f66a9b.js
  55. 2
      static/web/_next/static/chunks/6300-ca6bc9c2dc41661b.js
  56. 2
      static/web/_next/static/chunks/6627-6a1c9fee3f22b50a.js
  57. 2
      static/web/_next/static/chunks/6697-852bf5b11eb4e8a6.js
  58. 2
      static/web/_next/static/chunks/686-ac60207e0485593c.js
  59. 2
      static/web/_next/static/chunks/7230.32ac2396d502f20d.js
  60. 2
      static/web/_next/static/chunks/7423-09d0caf0464c43f7.js
  61. 2
      static/web/_next/static/chunks/7752-75428f02423c669f.js
  62. 2
      static/web/_next/static/chunks/8187-7d97c7eb895d7141.js
  63. 2
      static/web/_next/static/chunks/8215-2c70ec180381f278.js
  64. 2
      static/web/_next/static/chunks/8465-8fa0e08d5a9b953d.js
  65. 2
      static/web/_next/static/chunks/8469-45255ca99c58c379.js
  66. 2
      static/web/_next/static/chunks/8531-75eee38d06e50ddf.js
  67. 2
      static/web/_next/static/chunks/8966-2232fb44d049be60.js
  68. 2
      static/web/_next/static/chunks/9219.bedb75cd0ae0a042.js
  69. 14
      static/web/_next/static/chunks/9403-d2fe7733db580beb.js
  70. 2
      static/web/_next/static/chunks/971-93bd05bd3795eb04.js
  71. 2
      static/web/_next/static/chunks/9798.35019e1f27a83aba.js
  72. 22
      static/web/_next/static/chunks/d6e1aeb5-146f3f0d7ca8a5da.js
  73. 27
      static/web/_next/static/chunks/d6e1aeb5-396a9de05acb5fd6.js
  74. 2
      static/web/_next/static/chunks/pages/admin-3dfb998a1a416eb7.js
  75. 2
      static/web/_next/static/chunks/pages/admin/access-tokens-6a1040b0c09575fb.js
  76. 2
      static/web/_next/static/chunks/pages/admin/actions-93fb7cdcbfc7f23a.js
  77. 2
      static/web/_next/static/chunks/pages/admin/chat/emojis-632d4ca9faca588b.js
  78. 2
      static/web/_next/static/chunks/pages/admin/chat/messages-e345f6f5ab052cc9.js
  79. 2
      static/web/_next/static/chunks/pages/admin/chat/users-110bc51b3e586c1f.js
  80. 2
      static/web/_next/static/chunks/pages/admin/config-chat-3ac359bab5f5b93c.js
  81. 2
      static/web/_next/static/chunks/pages/admin/config-federation-a485afb49d6dbb17.js
  82. 2
      static/web/_next/static/chunks/pages/admin/config-social-items-35396e0f6958a252.js
  83. 2
      static/web/_next/static/chunks/pages/admin/config-video-49377987a1ea18f7.js
  84. 2
      static/web/_next/static/chunks/pages/admin/config/server-f2ec8492d84ced6c.js
  85. 2
      static/web/_next/static/chunks/pages/admin/federation/actions-0148e9955e9dbfd7.js
  86. 2
      static/web/_next/static/chunks/pages/admin/logs-195c7f07bfedb5ac.js
  87. 2
      static/web/_next/static/chunks/pages/admin/stream-health-14afdc0c67b9057e.js
  88. 2
      static/web/_next/static/chunks/pages/admin/viewer-info-b1ad67e3afbddfb8.js
  89. 2
      static/web/_next/static/chunks/pages/admin/webhooks-581479a456b32d95.js
  90. 2
      static/web/_next/static/chunks/pages/embed/chat/readwrite-a3467928d3f96b8b.js
  91. 2
      static/web/_next/static/chunks/pages/embed/video-408b2c71a24bf46f.js
  92. 2
      static/web/_next/static/chunks/pages/index-838931cb561b7571.js
  93. 2
      static/web/_next/static/chunks/webpack-15ada3522eb71b9b.js
  94. 1
      static/web/_next/static/css/0e2be447772fbc9c.css
  95. 1
      static/web/_next/static/css/998fec20b3dbbcec.css
  96. 2
      static/web/admin/access-tokens/index.html
  97. 2
      static/web/admin/actions/index.html
  98. 2
      static/web/admin/chat/emojis/index.html
  99. 2
      static/web/admin/chat/messages/index.html
  100. 2
      static/web/admin/chat/users/index.html
  101. Some files were not shown because too many files have changed in this diff Show More

2
.github/workflows/auto-comment-on-label.yaml

@ -11,7 +11,7 @@ jobs: @@ -11,7 +11,7 @@ jobs:
issues: write
steps:
- name: Add comment
uses: peter-evans/create-or-update-comment@0f44b017d10caeea6a4c1b410ba0521ad8a02815
uses: peter-evans/create-or-update-comment@83d7ae329db28c00a7f6909acb9081cfe31244ee
with:
issue-number: ${{ github.event.issue.number }}
body: |

2
.github/workflows/browser-testing.yml

@ -38,7 +38,7 @@ jobs: @@ -38,7 +38,7 @@ jobs:
${{ runner.os }}-build-
${{ runner.os }}-
- uses: actions/setup-go@v5
- uses: actions/setup-go@v4
with:
go-version: '1.21'
cache: true

6
.github/workflows/codeql-analysis.yml

@ -41,7 +41,7 @@ jobs: @@ -41,7 +41,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
config-file: ./.github/codeql/${{ matrix.language }}.yml
@ -53,7 +53,7 @@ jobs: @@ -53,7 +53,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v3
uses: github/codeql-action/autobuild@v2
# ℹ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
@ -67,4 +67,4 @@ jobs: @@ -67,4 +67,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
uses: github/codeql-action/analyze@v2

2
.github/workflows/go-lint.yml

@ -26,7 +26,7 @@ jobs: @@ -26,7 +26,7 @@ jobs:
with:
fetch-depth: 0
- uses: actions/setup-go@v5
- uses: actions/setup-go@v4
with:
go-version: '1.21'
cache: true

4
.github/workflows/go-tests.yaml

@ -28,7 +28,7 @@ jobs: @@ -28,7 +28,7 @@ jobs:
go-test-
- name: Install go
uses: actions/setup-go@v5
uses: actions/setup-go@v4
with:
go-version: '^1'
cache: true
@ -59,7 +59,7 @@ jobs: @@ -59,7 +59,7 @@ jobs:
go-test-
- name: Install go
uses: actions/setup-go@v5
uses: actions/setup-go@v4
with:
go-version: '^1'
cache: true

2
.github/workflows/hls-tests.yml

@ -25,7 +25,7 @@ jobs: @@ -25,7 +25,7 @@ jobs:
with:
concurrent_skipping: 'same_content_newer'
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
- uses: actions/setup-go@v4
with:
go-version: '1.21'
cache: true

2
.github/workflows/javascript-format-build.yml

@ -39,7 +39,7 @@ jobs: @@ -39,7 +39,7 @@ jobs:
- name: Get changed files
id: changed-files-yaml
uses: tj-actions/changed-files@v41
uses: tj-actions/changed-files@v40
with:
path: 'web'
files_ignore: |

2
.github/workflows/screenshots.yml

@ -15,7 +15,7 @@ jobs: @@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
- uses: actions/setup-go@v4
with:
go-version: '1.21'
cache: true

2
.github/workflows/shellcheck.yml

@ -18,7 +18,7 @@ jobs: @@ -18,7 +18,7 @@ jobs:
env:
LANG: C.UTF-8
container:
image: docker.io/ubuntu:24.04
image: docker.io/ubuntu:23.10
steps:
- uses: actions/checkout@v4

4
config/constants.go

@ -30,4 +30,8 @@ var ( @@ -30,4 +30,8 @@ var (
// PublicFilesPath is the optional directory for hosting public files.
PublicFilesPath = filepath.Join(DataDirectory, "public")
// DisableResponseCaching will disable caching of API and resource
// responses. Disable this feature to turn off the optimizations.
DisableResponseCaching = false
)

47
controllers/hls.go

@ -6,6 +6,7 @@ import ( @@ -6,6 +6,7 @@ import (
"path/filepath"
"strconv"
"strings"
"time"
"github.com/owncast/owncast/config"
"github.com/owncast/owncast/core"
@ -13,8 +14,24 @@ import ( @@ -13,8 +14,24 @@ import (
"github.com/owncast/owncast/models"
"github.com/owncast/owncast/router/middleware"
"github.com/owncast/owncast/utils"
log "github.com/sirupsen/logrus"
cache "github.com/victorspringer/http-cache"
"github.com/victorspringer/http-cache/adapter/memory"
)
var (
hlsCacheAdapter *cache.Adapter
hlsResponseCache *cache.Client
)
type FileServerHandler struct {
HLSPath string
}
func (fsh *FileServerHandler) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
http.ServeFile(rw, r, fsh.HLSPath)
}
// HandleHLSRequest will manage all requests to HLS content.
func HandleHLSRequest(w http.ResponseWriter, r *http.Request) {
// Sanity check to limit requests to HLS file types.
@ -23,6 +40,32 @@ func HandleHLSRequest(w http.ResponseWriter, r *http.Request) { @@ -23,6 +40,32 @@ func HandleHLSRequest(w http.ResponseWriter, r *http.Request) {
return
}
if hlsCacheAdapter == nil {
ca, err := memory.NewAdapter(
memory.AdapterWithAlgorithm(memory.LRU),
memory.AdapterWithCapacity(50),
memory.AdapterWithStorageCapacity(104_857_600),
)
hlsCacheAdapter = &ca
if err != nil {
log.Warn("unable to create web cache", err)
}
}
// Since HLS segments cannot be changed once they're rendered, we can cache
// individual segments for a long time.
if hlsResponseCache == nil {
rc, err := cache.NewClient(
cache.ClientWithAdapter(*hlsCacheAdapter),
cache.ClientWithTTL(30*time.Second),
cache.ClientWithExpiresHeader(),
)
hlsResponseCache = rc
if err != nil {
log.Warn("unable to create web cache client", err)
}
}
requestedPath := r.URL.Path
relativePath := strings.Replace(requestedPath, "/hls/", "", 1)
fullPath := filepath.Join(config.HLSStoragePath, relativePath)
@ -48,6 +91,10 @@ func HandleHLSRequest(w http.ResponseWriter, r *http.Request) { @@ -48,6 +91,10 @@ func HandleHLSRequest(w http.ResponseWriter, r *http.Request) {
} else {
cacheTime := utils.GetCacheDurationSecondsForPath(relativePath)
w.Header().Set("Cache-Control", "public, max-age="+strconv.Itoa(cacheTime))
fileServer := &FileServerHandler{HLSPath: fullPath}
hlsResponseCache.Middleware(fileServer).ServeHTTP(w, r)
return
}
middleware.EnableCors(w)

36
controllers/index.go

@ -7,6 +7,7 @@ import ( @@ -7,6 +7,7 @@ import (
"net/url"
"path/filepath"
"strings"
"time"
"github.com/owncast/owncast/config"
"github.com/owncast/owncast/core"
@ -16,12 +17,45 @@ import ( @@ -16,12 +17,45 @@ import (
"github.com/owncast/owncast/static"
"github.com/owncast/owncast/utils"
log "github.com/sirupsen/logrus"
cache "github.com/victorspringer/http-cache"
"github.com/victorspringer/http-cache/adapter/memory"
)
var (
indexCacheAdapter *cache.Adapter
indexBotSearchCache *cache.Client
)
// IndexHandler handles the default index route.
func IndexHandler(w http.ResponseWriter, r *http.Request) {
middleware.EnableCors(w)
if indexCacheAdapter == nil {
ca, err := memory.NewAdapter(
memory.AdapterWithAlgorithm(memory.LFU),
memory.AdapterWithCapacity(50),
memory.AdapterWithStorageCapacity(104_857_600),
)
indexCacheAdapter = &ca
if err != nil {
log.Warn("unable to create web cache", err)
}
}
if indexBotSearchCache == nil {
rc, err := cache.NewClient(
cache.ClientWithAdapter(*indexCacheAdapter),
cache.ClientWithTTL(30*time.Second),
cache.ClientWithExpiresHeader(),
cache.ClientWithRefreshKey("bot-search-page"),
cache.ClientWithExpiresHeader(),
)
indexBotSearchCache = rc
if err != nil {
log.Warn("unable to create web cache client", err)
}
}
isIndexRequest := r.URL.Path == "/" || filepath.Base(r.URL.Path) == "index.html" || filepath.Base(r.URL.Path) == ""
if utils.IsUserAgentAPlayer(r.UserAgent()) && isIndexRequest {
@ -32,7 +66,7 @@ func IndexHandler(w http.ResponseWriter, r *http.Request) { @@ -32,7 +66,7 @@ func IndexHandler(w http.ResponseWriter, r *http.Request) {
// For search engine bots and social scrapers return a special
// server-rendered page.
if utils.IsUserAgentABot(r.UserAgent()) && isIndexRequest {
handleScraperMetadataPage(w, r)
indexBotSearchCache.Middleware(http.HandlerFunc(handleScraperMetadataPage))
return
}

17
core/storageproviders/s3Storage.go

@ -8,7 +8,6 @@ import ( @@ -8,7 +8,6 @@ import (
"path/filepath"
"sort"
"strings"
"sync"
"time"
"github.com/owncast/owncast/core/data"
@ -27,29 +26,26 @@ import ( @@ -27,29 +26,26 @@ import (
// S3Storage is the s3 implementation of a storage provider.
type S3Storage struct {
// If we try to upload a playlist but it is not yet on disk
// then keep a reference to it here.
queuedPlaylistUpdates map[string]string
sess *session.Session
s3Client *s3.S3
uploader *s3manager.Uploader
sess *session.Session
s3Secret string
// If we try to upload a playlist but it is not yet on disk
// then keep a reference to it here.
queuedPlaylistUpdates map[string]string
s3Bucket string
s3Region string
s3ServingEndpoint string
s3AccessKey string
s3Secret string
s3ACL string
s3PathPrefix string
s3Endpoint string
host string
lock sync.Mutex
s3ForcePathStyle bool
}
@ -57,7 +53,6 @@ type S3Storage struct { @@ -57,7 +53,6 @@ type S3Storage struct {
func NewS3Storage() *S3Storage {
return &S3Storage{
queuedPlaylistUpdates: make(map[string]string),
lock: sync.Mutex{},
}
}
@ -131,8 +126,6 @@ func (s *S3Storage) VariantPlaylistWritten(localFilePath string) { @@ -131,8 +126,6 @@ func (s *S3Storage) VariantPlaylistWritten(localFilePath string) {
// We are uploading the variant playlist after uploading the segment
// to make sure we're not referring to files in a playlist that don't
// yet exist. See SegmentWritten.
s.lock.Lock()
defer s.lock.Unlock()
if _, ok := s.queuedPlaylistUpdates[localFilePath]; ok {
if _, err := s.Save(localFilePath, 0); err != nil {
log.Errorln(err)

18
go.mod

@ -3,14 +3,14 @@ module github.com/owncast/owncast @@ -3,14 +3,14 @@ module github.com/owncast/owncast
go 1.21
require (
github.com/aws/aws-sdk-go v1.49.6
github.com/aws/aws-sdk-go v1.47.9
github.com/go-fed/activity v1.0.1-0.20210803212804-d866ba75dd0f
github.com/go-fed/httpsig v1.1.0
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/gorilla/websocket v1.5.1
github.com/gorilla/websocket v1.5.0
github.com/grafov/m3u8 v0.12.0
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible
github.com/mattn/go-sqlite3 v1.14.19
github.com/mattn/go-sqlite3 v1.14.17
github.com/microcosm-cc/bluemonday v1.0.26
github.com/nareix/joy5 v0.0.0-20210317075623-2c912ca30590
github.com/oschwald/geoip2-golang v1.9.0
@ -20,7 +20,7 @@ require ( @@ -20,7 +20,7 @@ require (
github.com/teris-io/shortid v0.0.0-20220617161101-71ec9f2aa569
github.com/yuin/goldmark v1.6.0
golang.org/x/mod v0.14.0
golang.org/x/time v0.5.0
golang.org/x/time v0.4.0
)
require (
@ -31,9 +31,9 @@ require ( @@ -31,9 +31,9 @@ require (
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
github.com/yusufpapurcu/wmi v1.2.3 // indirect
golang.org/x/crypto v0.17.0 // indirect
golang.org/x/net v0.19.0
golang.org/x/sys v0.15.0 // indirect
golang.org/x/crypto v0.15.0 // indirect
golang.org/x/net v0.18.0
golang.org/x/sys v0.14.0 // indirect
)
require github.com/prometheus/client_golang v1.17.0
@ -55,7 +55,7 @@ require ( @@ -55,7 +55,7 @@ require (
require (
github.com/nakabonne/tstorage v0.3.6
github.com/shirou/gopsutil/v3 v3.23.11
github.com/shirou/gopsutil/v3 v3.23.10
)
require github.com/SherClockHolmes/webpush-go v1.3.0
@ -69,6 +69,7 @@ require ( @@ -69,6 +69,7 @@ require (
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/oschwald/maxminddb-golang v1.11.0 // indirect
github.com/shoenig/go-m1cpu v0.1.6 // indirect
github.com/victorspringer/http-cache v0.0.0-20231006141456-6446fe59efba // indirect
)
require (
@ -78,6 +79,7 @@ require ( @@ -78,6 +79,7 @@ require (
github.com/yuin/goldmark-emoji v1.0.2
gopkg.in/evanphx/json-patch.v5 v5.7.0
mvdan.cc/xurls v1.1.0
mvdan.cc/xurls/v2 v2.5.0
)
replace github.com/go-fed/activity => github.com/owncast/activity v1.0.1-0.20211229051252-7821289d4026

62
go.sum

@ -6,8 +6,10 @@ github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/ @@ -6,8 +6,10 @@ github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss=
github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU=
github.com/aws/aws-sdk-go v1.49.6 h1:yNldzF5kzLBRvKlKz1S0bkvc2+04R1kt13KfBWQBfFA=
github.com/aws/aws-sdk-go v1.49.6/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.46.6 h1:6wFnNC9hETIZLMf6SOTN7IcclrOGwp/n9SLp8Pjt6E8=
github.com/aws/aws-sdk-go v1.46.6/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.47.9 h1:rarTsos0mA16q+huicGx0e560aYRtOucV5z2Mw23JRY=
github.com/aws/aws-sdk-go v1.47.9/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
@ -37,13 +39,13 @@ github.com/google/brotli/go/cbrotli v0.0.0-20230829110029-ed738e842d2f h1:jopqB+ @@ -37,13 +39,13 @@ github.com/google/brotli/go/cbrotli v0.0.0-20230829110029-ed738e842d2f h1:jopqB+
github.com/google/brotli/go/cbrotli v0.0.0-20230829110029-ed738e842d2f/go.mod h1:nOPhAkwVliJdNTkj3gXpljmWhjc4wCaVqbMJcPKWP4s=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grafov/m3u8 v0.12.0 h1:T6iTwTsSEtMcwkayef+FJO8kj+Sglr4Lh81Zj8Ked/4=
github.com/grafov/m3u8 v0.12.0/go.mod h1:nqzOkfBiZJENr52zTVd/Dcl03yzphIMbJqkXGu+u080=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
@ -64,8 +66,8 @@ github.com/lestrrat-go/strftime v1.0.4/go.mod h1:E1nN3pCbtMSu1yjSVeyuRFVm/U0xoR7 @@ -64,8 +66,8 @@ github.com/lestrrat-go/strftime v1.0.4/go.mod h1:E1nN3pCbtMSu1yjSVeyuRFVm/U0xoR7
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/mattn/go-sqlite3 v1.14.7/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.19 h1:fhGleo2h1p8tVChob4I9HpmVFIAkKGpiukdrgQbWfGI=
github.com/mattn/go-sqlite3 v1.14.19/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM=
github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58=
@ -105,8 +107,10 @@ github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5 h1:mZHayPoR0lNmnH @@ -105,8 +107,10 @@ github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5 h1:mZHayPoR0lNmnH
github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5/go.mod h1:GEXHk5HgEKCvEIIrSpFI3ozzG5xOKA2DVlEX/gGnewM=
github.com/schollz/sqlite3dump v1.3.1 h1:QXizJ7XEJ7hggjqjZ3YRtF3+javm8zKtzNByYtEkPRA=
github.com/schollz/sqlite3dump v1.3.1/go.mod h1:mzSTjZpJH4zAb1FN3iNlhWPbbdyeBpOaTW0hukyMHyI=
github.com/shirou/gopsutil/v3 v3.23.11 h1:i3jP9NjCPUz7FiZKxlMnODZkdSIp2gnzfrvsu9CuWEQ=
github.com/shirou/gopsutil/v3 v3.23.11/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM=
github.com/shirou/gopsutil/v3 v3.23.9 h1:ZI5bWVeu2ep4/DIxB4U9okeYJ7zp/QLTO4auRb/ty/E=
github.com/shirou/gopsutil/v3 v3.23.9/go.mod h1:x/NWSb71eMcjFIO0vhyGW5nZ7oSIgVjrCnADckb85GA=
github.com/shirou/gopsutil/v3 v3.23.10 h1:/N42opWlYzegYaVkWejXWJpbzKv2JDy3mrgGzKsh9hM=
github.com/shirou/gopsutil/v3 v3.23.10/go.mod h1:JIE26kpucQi+innVlAUnIEOSBhBUkirr5b44yr55+WE=
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
@ -134,6 +138,8 @@ github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9f @@ -134,6 +138,8 @@ github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9f
github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/valyala/gozstd v1.20.1 h1:xPnnnvjmaDDitMFfDxmQ4vpx0+3CdTg2o3lALvXTU/g=
github.com/valyala/gozstd v1.20.1/go.mod h1:y5Ew47GLlP37EkTB+B4s7r6A5rdaeB7ftbl9zoYiIPQ=
github.com/victorspringer/http-cache v0.0.0-20231006141456-6446fe59efba h1:+oqDKQIOdkkvro1psUKtI4oH9WBeKkGY2S8h9/lo288=
github.com/victorspringer/http-cache v0.0.0-20231006141456-6446fe59efba/go.mod h1:D1AD6nlXv7HkIfTVd8ZWK1KQEiXYNy/LbLkx8H9tIQw=
github.com/yuin/goldmark v1.3.7/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yuin/goldmark v1.6.0 h1:boZcn2GTjpsynOsC0iJHnBWa4Bi0qzfJjthwauItG68=
@ -147,10 +153,14 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk @@ -147,10 +153,14 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA=
golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@ -158,11 +168,14 @@ golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR @@ -158,11 +168,14 @@ golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -177,28 +190,38 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc @@ -177,28 +190,38 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.4.0 h1:Z81tqI5ddIoXDPvVQ7/7CC9TnLM7ubaFG2qXYd5BbYY=
golang.org/x/time v0.4.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
@ -220,3 +243,4 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= @@ -220,3 +243,4 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
mvdan.cc/xurls v1.1.0 h1:kj0j2lonKseISJCiq1Tfk+iTv65dDGCl0rTbanXJGGc=
mvdan.cc/xurls v1.1.0/go.mod h1:TNWuhvo+IqbUCmtUIb/3LJSQdrzel8loVpgFm0HikbI=
mvdan.cc/xurls/v2 v2.5.0/go.mod h1:yQgaGQ1rFtJUzkmKiHYSSfuQxqfYmd//X6PxvholpeE=

27
main.go

@ -17,17 +17,18 @@ import ( @@ -17,17 +17,18 @@ import (
)
var (
dbFile = flag.String("database", "", "Path to the database file.")
logDirectory = flag.String("logdir", "", "Directory where logs will be written to")
backupDirectory = flag.String("backupdir", "", "Directory where backups will be written to")
enableDebugOptions = flag.Bool("enableDebugFeatures", false, "Enable additional debugging options.")
enableVerboseLogging = flag.Bool("enableVerboseLogging", false, "Enable additional logging.")
restoreDatabaseFile = flag.String("restoreDatabase", "", "Restore an Owncast database backup")
newAdminPassword = flag.String("adminpassword", "", "Set your admin password")
newStreamKey = flag.String("streamkey", "", "Set a temporary stream key for this session")
webServerPortOverride = flag.String("webserverport", "", "Force the web server to listen on a specific port")
webServerIPOverride = flag.String("webserverip", "", "Force web server to listen on this IP address")
rtmpPortOverride = flag.Int("rtmpport", 0, "Set listen port for the RTMP server")
dbFile = flag.String("database", "", "Path to the database file.")
logDirectory = flag.String("logdir", "", "Directory where logs will be written to")
backupDirectory = flag.String("backupdir", "", "Directory where backups will be written to")
enableDebugOptions = flag.Bool("enableDebugFeatures", false, "Enable additional debugging options.")
enableVerboseLogging = flag.Bool("enableVerboseLogging", false, "Enable additional logging.")
restoreDatabaseFile = flag.String("restoreDatabase", "", "Restore an Owncast database backup")
newAdminPassword = flag.String("adminpassword", "", "Set your admin password")
newStreamKey = flag.String("streamkey", "", "Set a temporary stream key for this session")
webServerPortOverride = flag.String("webserverport", "", "Force the web server to listen on a specific port")
webServerIPOverride = flag.String("webserverip", "", "Force web server to listen on this IP address")
rtmpPortOverride = flag.Int("rtmpport", 0, "Set listen port for the RTMP server")
disableResponseCaching = flag.Bool("disableResponseCaching", false, "Do not optimize performance by caching of web responses")
)
// nolint:cyclop
@ -42,6 +43,10 @@ func main() { @@ -42,6 +43,10 @@ func main() {
config.BackupDirectory = *backupDirectory
}
if *disableResponseCaching {
config.DisableResponseCaching = *disableResponseCaching
}
// Create the data directory if needed
if !utils.DoesFileExists("data") {
if err := os.Mkdir("./data", 0o700); err != nil {

8
router/middleware/auth.go

@ -25,9 +25,11 @@ func RequireAdminAuth(handler http.HandlerFunc) http.HandlerFunc { @@ -25,9 +25,11 @@ func RequireAdminAuth(handler http.HandlerFunc) http.HandlerFunc {
password := data.GetAdminPassword()
realm := "Owncast Authenticated Request"
// Alow CORS only for localhost:3000 to support Owncast development.
validAdminHost := "http://localhost:3000"
w.Header().Set("Access-Control-Allow-Origin", validAdminHost)
// The following line is kind of a work around.
// If you want HTTP Basic Auth + Cors it requires _explicit_ origins to be provided in the
// Access-Control-Allow-Origin header. So we just pull out the origin header and specify it.
// If we want to lock down admin APIs to not be CORS accessible for anywhere, this is where we would do that.
w.Header().Set("Access-Control-Allow-Origin", r.Header.Get("Origin"))
w.Header().Set("Access-Control-Allow-Credentials", "true")
w.Header().Set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization")

101
router/router.go

@ -24,10 +24,45 @@ import ( @@ -24,10 +24,45 @@ import (
"github.com/owncast/owncast/router/middleware"
"github.com/owncast/owncast/utils"
"github.com/owncast/owncast/yp"
cache "github.com/victorspringer/http-cache"
"github.com/victorspringer/http-cache/adapter/memory"
)
// Start starts the router for the http, ws, and rtmp.
func Start() error {
// Setup a web response cache
enableCache := !config.DisableResponseCaching
responseCache, err := memory.NewAdapter(
memory.AdapterWithAlgorithm(memory.LRU),
memory.AdapterWithCapacity(50),
)
if err != nil {
log.Warn("unable to create web cache", err)
}
superShortCacheClient, err := cache.NewClient(
cache.ClientWithAdapter(responseCache),
cache.ClientWithTTL(3*time.Second),
)
if err != nil {
log.Warn("unable to create web cache client", err)
}
reasonableDurationCacheClient, err := cache.NewClient(
cache.ClientWithAdapter(responseCache),
cache.ClientWithTTL(8*time.Second),
)
if err != nil {
log.Warn("unable to create web cache client", err)
}
longerDurationCacheClient, err := cache.NewClient(
cache.ClientWithAdapter(responseCache),
cache.ClientWithTTL(3*time.Minute),
)
if err != nil {
log.Warn("unable to create web cache client", err)
}
// The primary web app.
http.HandleFunc("/", controllers.IndexHandler)
@ -35,41 +70,79 @@ func Start() error { @@ -35,41 +70,79 @@ func Start() error {
http.HandleFunc("/admin/", middleware.RequireAdminAuth(controllers.IndexHandler))
// Images
http.HandleFunc("/thumbnail.jpg", controllers.GetThumbnail)
http.HandleFunc("/preview.gif", controllers.GetPreview)
http.HandleFunc("/logo", controllers.GetLogo)
http.HandleFunc("/thumbnail.jpg", func(rw http.ResponseWriter, r *http.Request) {
superShortCacheClient.Middleware(http.HandlerFunc(controllers.GetThumbnail)).ServeHTTP(rw, r)
})
http.HandleFunc("/preview.gif", func(rw http.ResponseWriter, r *http.Request) {
superShortCacheClient.Middleware(http.HandlerFunc(controllers.GetPreview)).ServeHTTP(rw, r)
})
http.HandleFunc("/logo", func(rw http.ResponseWriter, r *http.Request) {
longerDurationCacheClient.Middleware(http.HandlerFunc(controllers.GetLogo)).ServeHTTP(rw, r)
})
// Custom Javascript
http.HandleFunc("/customjavascript", controllers.ServeCustomJavascript)
http.HandleFunc("/customjavascript", func(rw http.ResponseWriter, r *http.Request) {
longerDurationCacheClient.Middleware(http.HandlerFunc(controllers.ServeCustomJavascript)).ServeHTTP(rw, r)
})
// Return a single emoji image.
http.HandleFunc(config.EmojiDir, controllers.GetCustomEmojiImage)
http.HandleFunc(config.EmojiDir, func(rw http.ResponseWriter, r *http.Request) {
longerDurationCacheClient.Middleware(http.HandlerFunc(controllers.GetCustomEmojiImage)).ServeHTTP(rw, r)
})
// return the logo
// return a logo that's compatible with external social networks
http.HandleFunc("/logo/external", controllers.GetCompatibleLogo)
http.HandleFunc("/logo/external", func(rw http.ResponseWriter, r *http.Request) {
longerDurationCacheClient.Middleware(http.HandlerFunc(controllers.GetCompatibleLogo)).ServeHTTP(rw, r)
})
// robots.txt
http.HandleFunc("/robots.txt", controllers.GetRobotsDotTxt)
http.HandleFunc("/robots.txt", func(rw http.ResponseWriter, r *http.Request) {
longerDurationCacheClient.Middleware(http.HandlerFunc(controllers.GetRobotsDotTxt)).ServeHTTP(rw, r)
})
// status of the system
http.HandleFunc("/api/status", controllers.GetStatus)
if enableCache {
http.HandleFunc("/api/status", func(rw http.ResponseWriter, r *http.Request) {
superShortCacheClient.Middleware(http.HandlerFunc(controllers.GetStatus)).ServeHTTP(rw, r)
})
} else {
http.HandleFunc("/api/status", controllers.GetStatus)
}
// custom emoji supported in the chat
http.HandleFunc("/api/emoji", controllers.GetCustomEmojiList)
http.HandleFunc("/api/emoji", func(rw http.ResponseWriter, r *http.Request) {
reasonableDurationCacheClient.Middleware(http.HandlerFunc(controllers.GetCustomEmojiList)).ServeHTTP(rw, r)
})
// chat rest api
http.HandleFunc("/api/chat", middleware.RequireUserAccessToken(controllers.GetChatMessages))
if enableCache {
http.HandleFunc("/api/chat", func(rw http.ResponseWriter, r *http.Request) {
superShortCacheClient.Middleware(middleware.RequireUserAccessToken(controllers.GetChatMessages))
})
} else {
http.HandleFunc("/api/chat", middleware.RequireUserAccessToken(controllers.GetChatMessages))
}
// web config api
http.HandleFunc("/api/config", controllers.GetWebConfig)
if enableCache {
http.HandleFunc("/api/config", func(rw http.ResponseWriter, r *http.Request) {
superShortCacheClient.Middleware(http.HandlerFunc(controllers.GetWebConfig)).ServeHTTP(rw, r)
})
} else {
http.HandleFunc("/api/config", controllers.GetWebConfig)
}
// return the YP protocol data
http.HandleFunc("/api/yp", yp.GetYPResponse)
// list of all social platforms
http.HandleFunc("/api/socialplatforms", controllers.GetAllSocialPlatforms)
http.HandleFunc("/api/socialplatforms", func(rw http.ResponseWriter, r *http.Request) {
reasonableDurationCacheClient.Middleware(http.HandlerFunc(controllers.GetAllSocialPlatforms)).ServeHTTP(rw, r)
})
// return the list of video variants available
http.HandleFunc("/api/video/variants", controllers.GetVideoStreamOutputVariants)
@ -84,7 +157,9 @@ func Start() error { @@ -84,7 +157,9 @@ func Start() error {
http.HandleFunc("/api/remotefollow", controllers.RemoteFollow)
// return followers
http.HandleFunc("/api/followers", middleware.HandlePagination(controllers.GetFollowers))
http.HandleFunc("/api/followers", func(rw http.ResponseWriter, r *http.Request) {
reasonableDurationCacheClient.Middleware(middleware.HandlePagination(controllers.GetFollowers)).ServeHTTP(rw, r)
})
// save client video playback metrics
http.HandleFunc("/api/metrics/playback", controllers.ReportPlaybackMetrics)

2
static/web/404.html vendored

File diff suppressed because one or more lines are too long

2
static/web/404/index.html vendored

File diff suppressed because one or more lines are too long

1
static/web/_next/static/7FO45oyNxons-CT00qbSN/_buildManifest.js

File diff suppressed because one or more lines are too long

1
static/web/_next/static/YI8_oqtLGnf9C9rRplixa/_buildManifest.js

File diff suppressed because one or more lines are too long

0
static/web/_next/static/7FO45oyNxons-CT00qbSN/_ssgManifest.js → static/web/_next/static/YI8_oqtLGnf9C9rRplixa/_ssgManifest.js

2
static/web/_next/static/chunks/1024-faaa4acbddb23dd0.js → static/web/_next/static/chunks/1024-c1d97a020e4f8ed2.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/1051-7acbe6da096aedde.js → static/web/_next/static/chunks/1051-8a5ca8b5f9f98bb1.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/1700-f64e4d4b4c10a28e.js → static/web/_next/static/chunks/1700-dce7a9059374b420.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/1749-7f5f8db163a0f08e.js → static/web/_next/static/chunks/1749-797abf8460ff31f5.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/1869.c19f35c0d87b210c.js → static/web/_next/static/chunks/1869.ba2b5785504648d0.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/2122-1d1e4848a54fdf7b.js → static/web/_next/static/chunks/2122-616c9b060e9a17fe.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/2130-9ec12e2d38878d52.js → static/web/_next/static/chunks/2130-877795ab1b81dcae.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/2474-0496a35db517cb95.js → static/web/_next/static/chunks/2474-0fb59d6b3117ab83.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/2891-2dd6ee9ab9a30745.js → static/web/_next/static/chunks/2891-2558c60aab79fabe.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/3068-3519d19ebe2d40ce.js → static/web/_next/static/chunks/3068-03c5c6410150c24e.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/3595-89e7109b465446da.js → static/web/_next/static/chunks/3595-6ecb023807c38df1.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/3942-79f1eb34d4fe5e35.js → static/web/_next/static/chunks/3942-48366093b3b60cf4.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/4060-39a9e9218b01ab83.js → static/web/_next/static/chunks/4060-34a83a0cf0d9ebea.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/4104-d8d32a2df6881332.js → static/web/_next/static/chunks/4104-586602c027ce22f8.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/4281-d23bb3c81529f11d.js → static/web/_next/static/chunks/4281-8d6901fb475aebae.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/4680-bde22ae7ecd0f9e5.js → static/web/_next/static/chunks/4680-b1fbead3ac6081fd.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/4749-25fc2a7bdcbc2d1d.js → static/web/_next/static/chunks/4749-e09a7722eb2edf7f.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/4938-b9d7558f6bdd8e05.js → static/web/_next/static/chunks/4938-7c5f68df37885201.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/4ad82c5e-07e2b5e369c24812.js → static/web/_next/static/chunks/4ad82c5e-c823a06c208c0a68.js vendored

File diff suppressed because one or more lines are too long

1
static/web/_next/static/chunks/5056-c58a7fe44a122c7d.js vendored

File diff suppressed because one or more lines are too long

1
static/web/_next/static/chunks/5056-d229a49abadc86bd.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/5283-25a80df7d4ae6ca0.js → static/web/_next/static/chunks/5283-6f7b07a8e8569a2b.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/5485.6461977e3aed6ecd.js → static/web/_next/static/chunks/5485.f113dbbc741e3a39.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/5560-e034e41ef44c88b6.js → static/web/_next/static/chunks/5560-fb30897479c6d750.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/5578-ef484ea3ca7188fe.js → static/web/_next/static/chunks/5578-d6de74db6520302a.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/5596-be17aada391ab1f5.js → static/web/_next/static/chunks/5596-c57e0f6790463985.js vendored

File diff suppressed because one or more lines are too long

4
static/web/_next/static/chunks/583-94062279e26da0c5.js → static/web/_next/static/chunks/583-26b1e49e1cef0623.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/5849.53c94487f97629c2.js → static/web/_next/static/chunks/5849.9f23ac5f98896080.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/5891-7720023fba1e9d2f.js → static/web/_next/static/chunks/5891-f2b8c2ff83489659.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/6017-8435e7f00f81ca9a.js → static/web/_next/static/chunks/6017-4077566221f4f92e.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/6108-b3ede449fada2ff1.js → static/web/_next/static/chunks/6108-458c185100f66a9b.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/6300-d570b3fb537b122d.js → static/web/_next/static/chunks/6300-ca6bc9c2dc41661b.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/6627-196719e8a1464d15.js → static/web/_next/static/chunks/6627-6a1c9fee3f22b50a.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/6697-4646cb5e2e92b9fc.js → static/web/_next/static/chunks/6697-852bf5b11eb4e8a6.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/686-0605995aff231843.js → static/web/_next/static/chunks/686-ac60207e0485593c.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/7230.0eeb5c6c87281d97.js → static/web/_next/static/chunks/7230.32ac2396d502f20d.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/7423-c11d24dc5b6c43e0.js → static/web/_next/static/chunks/7423-09d0caf0464c43f7.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/7752-866d25bef570cd45.js → static/web/_next/static/chunks/7752-75428f02423c669f.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/8187-20fe7d0a25ada08f.js → static/web/_next/static/chunks/8187-7d97c7eb895d7141.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/8215-44a5bae5c71f6fbe.js → static/web/_next/static/chunks/8215-2c70ec180381f278.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/8465-7818c7d73d5a0711.js → static/web/_next/static/chunks/8465-8fa0e08d5a9b953d.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/8469-473da9c7a5574e69.js → static/web/_next/static/chunks/8469-45255ca99c58c379.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/8531-e48150c7d6a7e29c.js → static/web/_next/static/chunks/8531-75eee38d06e50ddf.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/8966-229fba6866dbee0f.js → static/web/_next/static/chunks/8966-2232fb44d049be60.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/9219.56438c79dc74d089.js → static/web/_next/static/chunks/9219.bedb75cd0ae0a042.js vendored

File diff suppressed because one or more lines are too long

14
static/web/_next/static/chunks/9403-dfcd21877b95224c.js → static/web/_next/static/chunks/9403-d2fe7733db580beb.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/971-9cb5d51bf33ba527.js → static/web/_next/static/chunks/971-93bd05bd3795eb04.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/9798.1436759392f40078.js → static/web/_next/static/chunks/9798.35019e1f27a83aba.js vendored

File diff suppressed because one or more lines are too long

22
static/web/_next/static/chunks/d6e1aeb5-146f3f0d7ca8a5da.js vendored

File diff suppressed because one or more lines are too long

27
static/web/_next/static/chunks/d6e1aeb5-396a9de05acb5fd6.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/pages/admin-41eb1b705bdc2df3.js → static/web/_next/static/chunks/pages/admin-3dfb998a1a416eb7.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/pages/admin/access-tokens-3289e3745c703245.js → static/web/_next/static/chunks/pages/admin/access-tokens-6a1040b0c09575fb.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/pages/admin/actions-fecc6f55f14ffc2f.js → static/web/_next/static/chunks/pages/admin/actions-93fb7cdcbfc7f23a.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/pages/admin/chat/emojis-d876c65624a8f531.js → static/web/_next/static/chunks/pages/admin/chat/emojis-632d4ca9faca588b.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/pages/admin/chat/messages-e031b48d6368badc.js → static/web/_next/static/chunks/pages/admin/chat/messages-e345f6f5ab052cc9.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/pages/admin/chat/users-d0b8ff3ef00f15b8.js → static/web/_next/static/chunks/pages/admin/chat/users-110bc51b3e586c1f.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/pages/admin/config-chat-fe989dbb02c07095.js → static/web/_next/static/chunks/pages/admin/config-chat-3ac359bab5f5b93c.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/pages/admin/config-federation-b752ee00184d96db.js → static/web/_next/static/chunks/pages/admin/config-federation-a485afb49d6dbb17.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/pages/admin/config-social-items-5640568a1db3bdca.js → static/web/_next/static/chunks/pages/admin/config-social-items-35396e0f6958a252.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/pages/admin/config-video-7f6464694d61165c.js → static/web/_next/static/chunks/pages/admin/config-video-49377987a1ea18f7.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/pages/admin/config/server-08a32c1dfd7dbf07.js → static/web/_next/static/chunks/pages/admin/config/server-f2ec8492d84ced6c.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/pages/admin/federation/actions-d8efc8dc265b1bf5.js → static/web/_next/static/chunks/pages/admin/federation/actions-0148e9955e9dbfd7.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/pages/admin/logs-9b319846a54399a4.js → static/web/_next/static/chunks/pages/admin/logs-195c7f07bfedb5ac.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/pages/admin/stream-health-d2e0493cb4ef76a9.js → static/web/_next/static/chunks/pages/admin/stream-health-14afdc0c67b9057e.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/pages/admin/viewer-info-38e9a835767cd1e0.js → static/web/_next/static/chunks/pages/admin/viewer-info-b1ad67e3afbddfb8.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/pages/admin/webhooks-83660189c4cd8251.js → static/web/_next/static/chunks/pages/admin/webhooks-581479a456b32d95.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/pages/embed/chat/readwrite-3f2e049c19cc89ec.js → static/web/_next/static/chunks/pages/embed/chat/readwrite-a3467928d3f96b8b.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/pages/embed/video-0dbad33707e66577.js → static/web/_next/static/chunks/pages/embed/video-408b2c71a24bf46f.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/pages/index-4a444a85adf2d7ce.js → static/web/_next/static/chunks/pages/index-838931cb561b7571.js vendored

File diff suppressed because one or more lines are too long

2
static/web/_next/static/chunks/webpack-4ec01962f0f8cef1.js → static/web/_next/static/chunks/webpack-15ada3522eb71b9b.js vendored

File diff suppressed because one or more lines are too long

1
static/web/_next/static/css/0e2be447772fbc9c.css vendored

File diff suppressed because one or more lines are too long

1
static/web/_next/static/css/998fec20b3dbbcec.css vendored

File diff suppressed because one or more lines are too long

2
static/web/admin/access-tokens/index.html vendored

File diff suppressed because one or more lines are too long

2
static/web/admin/actions/index.html vendored

File diff suppressed because one or more lines are too long

2
static/web/admin/chat/emojis/index.html vendored

File diff suppressed because one or more lines are too long

2
static/web/admin/chat/messages/index.html vendored

File diff suppressed because one or more lines are too long

2
static/web/admin/chat/users/index.html vendored

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save