Skip to content

Commit

Permalink
Update logic to fetch soon starting streams (#1417)
Browse files Browse the repository at this point in the history
* Fix typo in token page and update links to docs

* Update stream query to prioritize soon starting streams and update go.work.sum

* Update GetSoonStartingStreamInfo

* Update streams.go

* Update docs links to new domain

* Update links to use wikiURL and disable new self streaming for lecturers
  • Loading branch information
carlobortolan authored Jan 10, 2025
1 parent 70d099a commit 99bca41
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 19 deletions.
27 changes: 17 additions & 10 deletions dao/streams.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package dao
import (
"context"
"fmt"
"log/slog"
"strconv"
"strings"
"time"
Expand Down Expand Up @@ -318,20 +317,21 @@ func (d streamsDao) GetStreamsWithWatchState(courseID uint, userID uint) (stream

// GetSoonStartingStreamInfo returns the stream key, course slug and course name of an upcoming stream.
func (d streamsDao) GetSoonStartingStreamInfo(user *model.User, slug string, year int, term string) (string, string, error) {
var result struct {
var results []struct {
CourseID uint
StreamKey string
ID string
Slug string
Start time.Time
End time.Time
}
now := time.Now()
query := DB.Table("streams").
Select("streams.course_id, streams.stream_key, streams.id, courses.slug").
Select("streams.course_id, streams.stream_key, streams.id, courses.slug, streams.start, streams.end").
Joins("JOIN course_admins ON course_admins.course_id = streams.course_id").
Joins("JOIN courses ON courses.id = course_admins.course_id").
Where("courses.slug != 'TESTCOURSE' AND streams.deleted_at IS NULL AND courses.deleted_at IS NULL AND course_admins.user_id = ? AND (streams.start <= ? AND streams.end >= ?)", user.ID, now.Add(15*time.Minute), now). // Streams starting in the next 15 minutes or currently running
Or("courses.slug != 'TESTCOURSE' AND streams.deleted_at IS NULL AND courses.deleted_at IS NULL AND course_admins.user_id = ? AND (streams.end >= ? AND streams.end <= ?)", user.ID, now.Add(-15*time.Minute), now). // Streams that just finished in the last 15 minutes
Order("streams.start ASC")
Or("courses.slug != 'TESTCOURSE' AND streams.deleted_at IS NULL AND courses.deleted_at IS NULL AND course_admins.user_id = ? AND (streams.end >= ? AND streams.end <= ?)", user.ID, now.Add(-15*time.Minute), now) // Streams that just finished in the last 15 minutes

if slug != "" {
query = query.Where("courses.slug = ?", slug)
Expand All @@ -343,19 +343,26 @@ func (d streamsDao) GetSoonStartingStreamInfo(user *model.User, slug string, yea
query = query.Where("courses.teaching_term = ?", term)
}

err := query.Limit(1).Scan(&result).Error
if err == gorm.ErrRecordNotFound || result.StreamKey == "" || result.ID == "" || result.Slug == "" {
err := query.Order("streams.start ASC").Find(&results).Error
if err != nil {
return "", "", err
}

if len(results) == 0 {
stream, course, err := d.CreateOrGetTestStreamAndCourse(user)
if err != nil {
return "", "", err
}
return stream.StreamKey, fmt.Sprintf("%s-%d", course.Slug, stream.ID), nil
}
if err != nil {
logger.Error("Error getting soon starting stream: %v", slog.String("err", err.Error()))
return "", "", err

for _, result := range results {
if now.After(result.Start) && now.Before(result.End) {
return result.StreamKey, fmt.Sprintf("%s-%s", result.Slug, result.ID), nil
}
}

result := results[0]
return result.StreamKey, fmt.Sprintf("%s-%s", result.Slug, result.ID), nil
}

Expand Down
11 changes: 11 additions & 0 deletions go.work.sum
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ github.com/alecthomas/kingpin/v2 v2.3.2 h1:H0aULhgmSzN8xQ3nX1uxtdlTHYoPLu5AhHxWr
github.com/alecthomas/kingpin/v2 v2.3.2/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE=
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc=
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA=
github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss=
github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU=
Expand Down Expand Up @@ -348,6 +349,7 @@ github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w=
github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg=
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw=
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1 h1:QbL/5oDUmRBzO9/Z7Seo6zf912W/a6Sr4Eu0G/3Jho0=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4 h1:WtGNWLvXpe6ZudgnXrq0barxBImvnnJoMEhXAzcbM0I=
Expand All @@ -373,6 +375,7 @@ github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/K
github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
github.com/google/flatbuffers v2.0.8+incompatible h1:ivUb1cGomAB101ZM1T0nOiWz9pSrTMoa9+EiY7igmkM=
Expand Down Expand Up @@ -488,6 +491,7 @@ github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNf
github.com/matryer/try v0.0.0-20161228173917-9ac251b645a2 h1:JAEbJn3j/FrhdWA9jW8B5ajsLIjeuEHLi8xE4fk997o=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mediocregopher/radix/v3 v3.8.0 h1:HI8EgkaM7WzsrFpYAkOXIgUKbjNonb2Ne7K6Le61Pmg=
Expand Down Expand Up @@ -571,6 +575,7 @@ github.com/tdewolff/minify/v2 v2.12.4 h1:kejsHQMM17n6/gwdw53qsi6lg0TGddZADVyQOz1
github.com/tdewolff/parse/v2 v2.6.4 h1:KCkDvNUMof10e3QExio9OPZJT8SbdKojLBumw8YZycQ=
github.com/tdewolff/test v1.0.7 h1:8Vs0142DmPFW/bQeHRP3MV19m1gvndjUb1sn8yy74LM=
github.com/ugorji/go v1.2.7 h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo=
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/urfave/negroni v1.0.0 h1:kIimOitoypq34K7TG7DUaJ9kq/N4Ofuwi1sjz0KipXc=
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
Expand Down Expand Up @@ -632,6 +637,7 @@ go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95a
go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8=
go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
Expand All @@ -648,12 +654,14 @@ 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/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
Expand All @@ -677,7 +685,9 @@ golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0=
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE=
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
Expand Down Expand Up @@ -728,6 +738,7 @@ google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 h1:M1YKkFIboKNieVO5DLUEVzQf
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
Expand Down
18 changes: 11 additions & 7 deletions web/template/admin/admin.gohtml
Original file line number Diff line number Diff line change
Expand Up @@ -92,26 +92,28 @@
class="mb-3 lg:mb-3 uppercase tracking-wide font-semibold text-sm lg:text-xs text-2">
Streaming</h5>
<ul>
<!-- Disable new self-streaming for lecturers, until https://github.com/TUM-Dev/gocast/issues/1418 is resolved
<li>
<a class="px-3 py-2 transition-colors duration-200 {{if eq $page "users"}}text-1{{else}}text-5{{end}} relative block"
href="/admin/token"><span
class="rounded-md absolute inset-0 bg-cyan-50 opacity-0"></span><span
class="relative">Token Management</span>
</a>
</li>
-->
<li>
<a class="px-3 py-2 transition-colors duration-200 {{if eq $page "users"}}text-1{{else}}text-5{{end}} relative block"
href="https://docs.live.rbg.tum.de/docs/usage/02-self-streaming/" target="_blank" rel="noopener noreferrer">
href="{{.IndexData.WikiURL}}/docs/usage/self-streaming/" target="_blank" rel="noopener noreferrer">
<span class="rounded-md absolute inset-0 bg-cyan-50 opacity-0"></span>
<span class="relative">Self-Streaming Guide</span>
<svg class="inline-block ml-1 w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 9l3 3m0 0l-3 3m3-3H3m18 0a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>
</a>
</li>
<li>
<a class="px-3 py-2 transition-colors duration-200 {{if eq $page "users"}}text-1{{else}}text-5{{end}} relative block"
href="https://docs.live.rbg.tum.de/" target="_blank" rel="noopener noreferrer">
href="https://github.com/TUM-Dev/gocast/issues/new/choose" target="_blank" rel="noopener noreferrer">
<span class="rounded-md absolute inset-0 bg-cyan-50 opacity-0"></span>
<span class="relative">Need Help?</span>
<span class="relative">Report an issue</span>
<svg class="inline-block ml-1 w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 9l3 3m0 0l-3 3m3-3H3m18 0a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>
</a>
</li>
Expand Down Expand Up @@ -240,26 +242,28 @@
class="mb-3 lg:mb-3 uppercase tracking-wide font-semibold text-sm lg:text-xs text-2">
Streaming</h5>
<ul>
<!-- Disable new self-streaming for lecturers, until https://github.com/TUM-Dev/gocast/issues/1418 is resolved
<li>
<a class="px-3 py-2 transition-colors duration-200 {{if eq $page "token"}}text-1{{else}}text-5{{end}} relative block"
href="/admin/token"><span
class="rounded-md absolute inset-0 bg-cyan-50 opacity-0"></span><span
class="relative">Token Management</span>
</a>
</li>
-->
<li>
<a class="px-3 py-2 transition-colors duration-200 text-5 relative block"
href="https://docs.live.rbg.tum.de/docs/usage/02-self-streaming/" target="_blank" rel="noopener noreferrer">
href="{{.IndexData.WikiURL}}/docs/usage/self-streaming/" target="_blank" rel="noopener noreferrer">
<span class="rounded-md absolute inset-0 bg-cyan-50 opacity-0"></span>
<span class="relative">Self-Streaming Guide</span>
<svg class="inline-block ml-1 w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 9l3 3m0 0l-3 3m3-3H3m18 0a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>
</a>
</li>
<li>
<a class="px-3 py-2 transition-colors duration-200 text-5 relative block"
href="https://docs.live.rbg.tum.de/" target="_blank" rel="noopener noreferrer">
href="https://github.com/TUM-Dev/gocast/issues/new/choose" target="_blank" rel="noopener noreferrer">
<span class="rounded-md absolute inset-0 bg-cyan-50 opacity-0"></span>
<span class="relative">Need Help?</span>
<span class="relative">Report an Issue</span>
<svg class="inline-block ml-1 w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 9l3 3m0 0l-3 3m3-3H3m18 0a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>
</a>
</li>
Expand Down Expand Up @@ -338,7 +342,7 @@
{{else if and (eq $curUser.Role 1) (eq .Page "courseImport")}}
{{template "course-import" .}}
{{else if and (or (eq $curUser.Role 1) (eq $curUser.Role 2)) (eq .Page "token")}}
{{template "token" dict "Tokens" .Tokens "Role" $curUser.Role}}
{{template "token" dict "Tokens" .Tokens "Role" $curUser.Role "WikiURL" .IndexData.WikiURL}}
{{else if and (eq $curUser.Role 1) (eq .Page "info-pages")}}
{{template "info-pages" .InfoPages}}
{{else if and (eq $curUser.Role 1) (eq .Page "notifications")}}
Expand Down
4 changes: 2 additions & 2 deletions web/template/admin/admin_tabs/token.gohtml
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@
</div>
<div x-show="tab === 'Teams'" class="p-4 border-t border-gray-200 dark:border-gray-700">
<ol class="list-decimal list-inside">
<li class="mb-2">Open Microsoft Teams and oin the meeting or webinar you wish to live stream.</li>
<li class="mb-2">Open Microsoft Teams and join the meeting or webinar you wish to live stream.</li>
<li class="mb-2">Add the <strong>Custom Streaming</strong> app to the meeting.</li>
<li class="mb-2">Click <strong>Add</strong> and <strong>Save</strong>.</li>
<li class="mb-2">In the right-hand panel that opens, paste the <strong>Stream URL</strong> and <strong>Stream Key</strong> from below.</li>
Expand All @@ -142,7 +142,7 @@
<p class="text-sm text-5 px-4">You can start streaming from 15 minutes before the lecture starts and up to 15 minutes after the lecture ends - TUMLive automatically finds the lecture you want to stream.</p>
<p class="text-sm text-5 px-4">To test your setup, you can start streaming while not in a lecture and a private test stream will be created.</p>
</div>
<p class="mt-4 italic">For more information, please refer to the <a href="https://docs.live.rbg.tum.de/docs/usage/02-self-streaming/" target="_blank" rel="noopener noreferrer" class="text-blue-500 dark:text-blue-400 hover:text-blue-700 underline">self-streaming guide</a>.</p>
<p class="mt-4 italic">For more information, please refer to the <a href="{{.WikiURL}}/docs/beta/usage/self-streaming/" target="_blank" rel="noopener noreferrer" class="text-blue-500 dark:text-blue-400 hover:text-blue-700 underline">self-streaming guide</a>.</p>
</div>
</div>
</form>
Expand Down

0 comments on commit 99bca41

Please sign in to comment.