forked from TUM-Dev/gocast
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Search through subtitles (TUM-Dev#955)
* search through subtitles * clean up * lint ts * go mod tidy * implement feedback
- Loading branch information
1 parent
e96dba7
commit fc1c3c5
Showing
16 changed files
with
331 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
package tools | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"github.com/asticode/go-astisub" | ||
"github.com/joschahenningsen/TUM-Live/dao" | ||
"github.com/meilisearch/meilisearch-go" | ||
log "github.com/sirupsen/logrus" | ||
"strings" | ||
) | ||
|
||
type MeiliStream struct { | ||
ID uint `json:"ID"` | ||
Name string `json:"name"` | ||
Description string `json:"description"` | ||
CourseName string `json:"courseName"` | ||
Year int `json:"year"` | ||
TeachingTerm string `json:"semester"` | ||
CourseID uint `json:"courseID"` | ||
} | ||
|
||
type MeiliSubtitles struct { | ||
ID string `json:"ID"` // meili id: streamID + timestamp | ||
StreamID uint `json:"streamID"` | ||
Timestamp int64 `json:"timestamp"` | ||
TextPrev string `json:"textPrev"` // the previous subtitle line | ||
Text string `json:"text"` | ||
TextNext string `json:"textNext"` // the next subtitle line | ||
} | ||
|
||
type MeiliExporter struct { | ||
c *meilisearch.Client | ||
d dao.DaoWrapper | ||
} | ||
|
||
func NewMeiliExporter(d dao.DaoWrapper) *MeiliExporter { | ||
c, err := Cfg.GetMeiliClient() | ||
if err != nil && errors.Is(err, ErrMeiliNotConfigured) { | ||
return nil | ||
} else if err != nil { | ||
log.WithError(err).Error("could not get meili client") | ||
return nil | ||
} | ||
|
||
return &MeiliExporter{c, d} | ||
} | ||
|
||
func (m *MeiliExporter) Export() { | ||
if m == nil { | ||
return | ||
} | ||
index := m.c.Index("STREAMS") | ||
_, err := m.c.Index("SUBTITLES").DeleteAllDocuments() | ||
if err != nil { | ||
log.WithError(err).Warn("could not delete all old subtitles") | ||
} | ||
|
||
m.d.StreamsDao.ExecAllStreamsWithCoursesAndSubtitles(func(streams []dao.StreamWithCourseAndSubtitles) { | ||
meilistreams := make([]MeiliStream, len(streams)) | ||
streamIDs := make([]uint, len(streams)) | ||
for i, stream := range streams { | ||
streamIDs[i] = stream.ID | ||
meilistreams[i] = MeiliStream{ | ||
ID: stream.ID, | ||
CourseID: stream.CourseID, | ||
Name: stream.Name, | ||
Description: stream.Description, | ||
CourseName: stream.CourseName, | ||
Year: stream.Year, | ||
TeachingTerm: stream.TeachingTerm, | ||
} | ||
if stream.Subtitles != "" { | ||
meiliSubtitles := make([]MeiliSubtitles, 0) | ||
|
||
vtt, err := astisub.ReadFromWebVTT(strings.NewReader(stream.Subtitles)) | ||
if err != nil { | ||
log.WithError(err).Warn("could not parse subtitles") | ||
continue | ||
} | ||
for i, _ := range vtt.Items { | ||
sub := MeiliSubtitles{ | ||
ID: fmt.Sprintf("%d-%d", stream.ID, vtt.Items[i].StartAt.Milliseconds()), | ||
StreamID: stream.ID, | ||
Timestamp: vtt.Items[i].StartAt.Milliseconds(), | ||
Text: vtt.Items[i].String(), | ||
} | ||
if i > 0 { | ||
sub.TextPrev = meiliSubtitles[i-1].Text | ||
meiliSubtitles[i-1].TextNext = sub.Text | ||
} | ||
|
||
meiliSubtitles = append(meiliSubtitles, sub) | ||
} | ||
|
||
if len(meiliSubtitles) > 0 { | ||
_, err := m.c.Index("SUBTITLES").AddDocuments(&meiliSubtitles, "ID") | ||
if err != nil { | ||
log.WithError(err).Error("issue adding subtitles to meili") | ||
} | ||
} | ||
} | ||
} | ||
_, err := index.AddDocuments(&meilistreams, "ID") | ||
if err != nil { | ||
log.WithError(err).Error("issue adding documents to meili") | ||
} | ||
|
||
}) | ||
} | ||
|
||
func (m *MeiliExporter) SetIndexSettings() { | ||
if m == nil { | ||
return | ||
} | ||
index := m.c.Index("STREAMS") | ||
synonyms := map[string][]string{ | ||
"W": {"Wintersemester", "Winter", "WS", "WiSe"}, | ||
"S": {"Sommersemester", "Sommer", "SS", "SoSe", "Summer"}, | ||
} | ||
_, err := index.UpdateSynonyms(&synonyms) | ||
if err != nil { | ||
log.WithError(err).Error("could not set synonyms for meili index STREAMS") | ||
} | ||
|
||
_, err = m.c.Index("SUBTITLES").UpdateSettings(&meilisearch.Settings{ | ||
FilterableAttributes: []string{"streamID", "courseID"}, | ||
SearchableAttributes: []string{"text"}, | ||
SortableAttributes: []string{"timestamp"}, | ||
}) | ||
if err != nil { | ||
log.WithError(err).Warn("could not set settings for meili index SUBTITLES") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package tools | ||
|
||
import ( | ||
"fmt" | ||
"github.com/meilisearch/meilisearch-go" | ||
log "github.com/sirupsen/logrus" | ||
) | ||
|
||
func SearchSubtitles(q string, streamID uint) *meilisearch.SearchResponse { | ||
c, err := Cfg.GetMeiliClient() | ||
if err != nil { | ||
return nil | ||
} | ||
response, err := c.Index("SUBTITLES").Search(q, &meilisearch.SearchRequest{ | ||
Filter: fmt.Sprintf("streamID = %d", streamID), | ||
Limit: 10, | ||
}) | ||
if err != nil { | ||
log.WithError(err).Error("could not search meili") | ||
return nil | ||
} | ||
return response | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
{{define "search"}} | ||
<div class="grow px-6 text-right hidden md:block" | ||
x-data="{showSearch: false, searcher:undefined}" | ||
x-show="showSearch" | ||
@keyup.escape.window="searcher.closeRes(); $refs.searchInput.blur();" | ||
@togglesearch.window="e => {showSearch=true; searcher=watch.subtitleSearch(e.detail.streamID)}" x-cloak> | ||
<template x-if="searcher!=undefined"> | ||
<input type="search" x-ref="searchInput" | ||
@input="searcher.search($event.target.value)" | ||
@focus="searcher.hits.length > 0 && searcher.openRes()" | ||
class="max-w-xl p-2 bg-transparent rounded-lg border-gray-600 border w-full px-2 font-light text-2" | ||
placeholder="Search in lecture"> | ||
</template> | ||
<template x-if="searcher!=undefined"> | ||
<div x-show="searcher.open" @click.outside="searcher.closeRes()" class="absolute top-24 right-5 z-50 px-4 overflow-x-hidden h-96 bg-gray-100 shadow dark:bg-gray-900/50 rounded-lg text-left text-gray-800 dark:text-gray-200"> | ||
<div class="w-2xl p-3 overflow-y-auto"> | ||
<template x-for="res in searcher.hits"> | ||
<div @click="watch.jumpTo({Ms: res.timestamp});" class="dark:hover:bg-gray-700 hover:outline dark:bg-gray-800 bg-white rounded p-2 my-2 flex" role="button"> | ||
<span class="my-auto p-2 font-semibold" | ||
x-text="global.Time.FromSeconds(res.timestamp/1000).toString()"></span> | ||
<div class="p-2"> | ||
<span class="block text-xs" x-text="res.textPrev"></span> | ||
<span class="block text-sm font-bold" x-text="res.text"></span> | ||
<span class="block text-xs" x-text="res.textNext"></span> | ||
</div> | ||
</div> | ||
</template> | ||
</div> | ||
</div> | ||
</template> | ||
</div> | ||
{{end}} |
Oops, something went wrong.