This commit is contained in:
+73
-47
@@ -52,30 +52,30 @@ func (s *SearchService) SearchMedia(queries []string) ([]SearchResult, error) {
|
||||
categories string
|
||||
engine string
|
||||
queryBuilder func(string) string
|
||||
match func(string) bool
|
||||
match func(SearchResult) bool
|
||||
}{
|
||||
{
|
||||
name: "Google Video",
|
||||
categories: "videos",
|
||||
engine: s.GoogleVideoEngine,
|
||||
queryBuilder: func(query string) string {
|
||||
return query
|
||||
return buildGoogleVideoQuery(query)
|
||||
},
|
||||
match: func(string) bool { return true },
|
||||
match: isUsefulGoogleVideoResult,
|
||||
},
|
||||
{
|
||||
name: "Envato",
|
||||
categories: "general",
|
||||
engine: s.WebEngine,
|
||||
queryBuilder: buildEnvatoQuery,
|
||||
match: isEnvatoURL,
|
||||
match: isRenderableEnvatoResult,
|
||||
},
|
||||
{
|
||||
name: "Artgrid",
|
||||
categories: "general",
|
||||
engine: s.WebEngine,
|
||||
queryBuilder: buildArtgridQuery,
|
||||
match: func(link string) bool { return strings.Contains(strings.ToLower(link), "artgrid.io") },
|
||||
match: isRenderableArtgridResult,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -88,10 +88,7 @@ func (s *SearchService) SearchMedia(queries []string) ([]SearchResult, error) {
|
||||
continue
|
||||
}
|
||||
for _, source := range sources {
|
||||
searchQuery := query
|
||||
if source.queryBuilder != nil {
|
||||
searchQuery = source.queryBuilder(query)
|
||||
}
|
||||
searchQuery := source.queryBuilder(query)
|
||||
|
||||
items, err := s.search(searchQuery, source.categories, source.engine, source.name)
|
||||
if err != nil {
|
||||
@@ -112,10 +109,7 @@ func (s *SearchService) SearchMedia(queries []string) ([]SearchResult, error) {
|
||||
if item.Link == "" || seen[item.Link] {
|
||||
continue
|
||||
}
|
||||
if source.match != nil && !source.match(item.Link) {
|
||||
continue
|
||||
}
|
||||
if !isRenderableLink(item.Link, item.Source) {
|
||||
if !source.match(item) {
|
||||
continue
|
||||
}
|
||||
seen[item.Link] = true
|
||||
@@ -138,7 +132,7 @@ func (s *SearchService) search(query, categories, engine, source string) ([]Sear
|
||||
values.Set("q", query)
|
||||
values.Set("format", "json")
|
||||
values.Set("safesearch", "0")
|
||||
values.Set("language", "ko-KR")
|
||||
values.Set("language", "en-US")
|
||||
if categories != "" {
|
||||
values.Set("categories", categories)
|
||||
}
|
||||
@@ -189,6 +183,71 @@ func (s *SearchService) search(query, categories, engine, source string) ([]Sear
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func buildGoogleVideoQuery(query string) string {
|
||||
return fmt.Sprintf(`"%s" ("stock footage" OR "b-roll" OR cinematic OR "establishing shot" OR editorial) -tutorial -"how to" -review -reaction -course -podcast -vlog -interview -breakdown -edit -editing`, query)
|
||||
}
|
||||
|
||||
func buildEnvatoQuery(query string) string {
|
||||
return fmt.Sprintf(`"%s" ("stock footage" OR "stock video" OR "motion graphics" OR cinematic OR "b-roll") (site:elements.envato.com OR site:videohive.net/item) -site:elements.envato.com/stock-video -site:elements.envato.com/video-templates -site:elements.envato.com/stock-video/stock-footage`, query)
|
||||
}
|
||||
|
||||
func buildArtgridQuery(query string) string {
|
||||
return fmt.Sprintf(`"%s" ("stock footage" OR "b-roll" OR cinematic OR editorial) site:artgrid.io/clip/`, query)
|
||||
}
|
||||
|
||||
func isUsefulGoogleVideoResult(result SearchResult) bool {
|
||||
text := strings.ToLower(result.Title + " " + result.Snippet)
|
||||
for _, banned := range []string{
|
||||
"tutorial", "how to", "review", "reaction", "podcast", "interview", "walkthrough",
|
||||
"course", "lesson", "edit tutorial", "editing tutorial", "premiere pro", "after effects",
|
||||
"breakdown", "explained", "vlog",
|
||||
} {
|
||||
if strings.Contains(text, banned) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for _, desired := range []string{
|
||||
"b-roll", "stock footage", "cinematic", "footage", "establishing shot", "4k",
|
||||
} {
|
||||
if strings.Contains(text, desired) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
lowerLink := strings.ToLower(result.Link)
|
||||
return strings.Contains(lowerLink, "youtube.com/watch") || strings.Contains(lowerLink, "youtu.be/")
|
||||
}
|
||||
|
||||
func isRenderableEnvatoResult(result SearchResult) bool {
|
||||
parsed, err := url.Parse(result.Link)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
host := strings.ToLower(parsed.Host)
|
||||
path := strings.Trim(parsed.Path, "/")
|
||||
if strings.Contains(host, "videohive.net") {
|
||||
return strings.HasPrefix(path, "item/")
|
||||
}
|
||||
if strings.Contains(host, "elements.envato.com") {
|
||||
if path == "" || strings.Contains(path, "/") {
|
||||
return false
|
||||
}
|
||||
return regexp.MustCompile(`-[A-Z0-9]{6,}$`).MatchString(path)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isRenderableArtgridResult(result SearchResult) bool {
|
||||
parsed, err := url.Parse(result.Link)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
if !strings.Contains(strings.ToLower(parsed.Host), "artgrid.io") {
|
||||
return false
|
||||
}
|
||||
path := strings.Trim(parsed.Path, "/")
|
||||
return regexp.MustCompile(`^clip/[0-9]+/`).MatchString(path)
|
||||
}
|
||||
|
||||
func firstNonEmpty(values ...string) string {
|
||||
for _, value := range values {
|
||||
if strings.TrimSpace(value) != "" {
|
||||
@@ -225,39 +284,6 @@ func inferDisplayLink(link string, parsed []any) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func isEnvatoURL(link string) bool {
|
||||
lower := strings.ToLower(link)
|
||||
return strings.Contains(lower, "envato") || strings.Contains(lower, "videohive.net")
|
||||
}
|
||||
|
||||
func isRenderableLink(link, source string) bool {
|
||||
parsed, err := url.Parse(link)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
path := strings.Trim(parsed.Path, "/")
|
||||
if path == "" {
|
||||
return false
|
||||
}
|
||||
lower := strings.ToLower(link)
|
||||
switch source {
|
||||
case "Envato":
|
||||
return strings.Contains(lower, "/item/") || strings.Contains(lower, "/stock-video/") || strings.Contains(lower, "/video-templates/")
|
||||
case "Artgrid":
|
||||
return strings.Contains(lower, "artgrid.io") && len(strings.Split(path, "/")) >= 2
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
func buildEnvatoQuery(query string) string {
|
||||
return fmt.Sprintf(`%s ("stock video" OR footage OR "video template" OR cinematic) (site:elements.envato.com/stock-video OR site:elements.envato.com/video-templates OR site:videohive.net/item)`, query)
|
||||
}
|
||||
|
||||
func buildArtgridQuery(query string) string {
|
||||
return fmt.Sprintf(`%s ("stock footage" OR "b-roll" OR cinematic OR editorial) (site:artgrid.io)`, query)
|
||||
}
|
||||
|
||||
func deriveThumbnail(link string) string {
|
||||
if videoID := extractYouTubeID(link); videoID != "" {
|
||||
return "https://i.ytimg.com/vi/" + videoID + "/hqdefault.jpg"
|
||||
|
||||
Reference in New Issue
Block a user