Added search ability
This commit is contained in:
parent
9b89df3d4b
commit
2709154cee
@ -1,6 +1,8 @@
|
|||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.Xml;
|
||||||
using Microsoft.AspNetCore.Cors;
|
using Microsoft.AspNetCore.Cors;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
@ -75,6 +77,102 @@ namespace YTManager.Controllers {
|
|||||||
return Ok(converted);
|
return Ok(converted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Search_Query
|
||||||
|
{
|
||||||
|
// Tags.
|
||||||
|
public List<Models.Tag> Tags;
|
||||||
|
|
||||||
|
// What the duration type is.
|
||||||
|
public enum _Duration_Type { LessThan, GreaterThan, Unset };
|
||||||
|
public _Duration_Type Duration_Type;
|
||||||
|
|
||||||
|
// What the expected duration of the videos are.
|
||||||
|
public TimeSpan Duration;
|
||||||
|
|
||||||
|
// Remaining tokens.
|
||||||
|
public List<String> Remaining_Tokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Searches for videos using the specified tag(s).
|
||||||
|
[HttpGet("search/{searchstr}")]
|
||||||
|
public async Task<IActionResult> Search([FromRoute] string searchstr) {
|
||||||
|
// What to use for searching videos with.
|
||||||
|
var parsed_query = new Search_Query();
|
||||||
|
|
||||||
|
// Assume the search string is comma seperated.
|
||||||
|
parsed_query.Remaining_Tokens = searchstr.Split(',').Select(t => t.Trim().ToLower()).ToList();
|
||||||
|
|
||||||
|
// Find a potential single video duration.
|
||||||
|
List<string> greaterthan = parsed_query.Remaining_Tokens.Where(token => token.StartsWith('>')).ToList();
|
||||||
|
List<string> lessthan = parsed_query.Remaining_Tokens.Where(token => token.StartsWith('<')).ToList();
|
||||||
|
if (greaterthan.Count() + lessthan.Count() > 1)
|
||||||
|
return BadRequest();
|
||||||
|
if (greaterthan.Count() == 1) parsed_query.Duration_Type = Search_Query._Duration_Type.GreaterThan;
|
||||||
|
else if (lessthan.Count() == 1) parsed_query.Duration_Type = Search_Query._Duration_Type.LessThan;
|
||||||
|
else parsed_query.Duration_Type = Search_Query._Duration_Type.Unset;
|
||||||
|
greaterthan.ForEach(g => parsed_query.Remaining_Tokens.Remove(g));
|
||||||
|
lessthan.ForEach(l => parsed_query.Remaining_Tokens.Remove(l));
|
||||||
|
|
||||||
|
// Attempt to parse it using ISO8601 duration.
|
||||||
|
if (parsed_query.Duration_Type != Search_Query._Duration_Type.Unset) {
|
||||||
|
string timingstr = "PT" + greaterthan
|
||||||
|
.Concat(lessthan)
|
||||||
|
.Select(s => s.TrimStart(new char[] { '<', '>' }))
|
||||||
|
.First();
|
||||||
|
|
||||||
|
try {
|
||||||
|
parsed_query.Duration = XmlConvert.ToTimeSpan(timingstr.ToUpper());
|
||||||
|
} catch (Exception) {
|
||||||
|
return BadRequest("Failed to parse duration.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find which tokens are explicit tags
|
||||||
|
parsed_query.Tags = await db.Tags
|
||||||
|
.Where(t => parsed_query.Remaining_Tokens.Any(token => token == t.Name.ToLower()))
|
||||||
|
.ToListAsync();
|
||||||
|
parsed_query.Tags.ForEach(tag => parsed_query.Remaining_Tokens.Remove(tag.Name.ToLower()));
|
||||||
|
|
||||||
|
// Get from the database all videos which satisfy the query via
|
||||||
|
// AND'ing all the queries.
|
||||||
|
var dbquery = db.Videos.Select(v => v);
|
||||||
|
|
||||||
|
// Get all videos that satisfy the time duration.
|
||||||
|
if (parsed_query.Duration_Type == Search_Query._Duration_Type.GreaterThan)
|
||||||
|
dbquery = dbquery.Where(v => v.Duration >= parsed_query.Duration);
|
||||||
|
else if (parsed_query.Duration_Type == Search_Query._Duration_Type.LessThan)
|
||||||
|
dbquery = dbquery.Where(v => v.Duration <= parsed_query.Duration);
|
||||||
|
|
||||||
|
// Match videos where the tag matches.
|
||||||
|
parsed_query.Tags.ForEach(tag => dbquery = dbquery.Where(V => V.Tags.Any(vt => vt.Name == tag.Name)));
|
||||||
|
|
||||||
|
// Get all videos that match their title, description, or channel name
|
||||||
|
// with the remaining tokens.
|
||||||
|
parsed_query.Remaining_Tokens.ForEach(token => {
|
||||||
|
dbquery = dbquery.Where(v =>
|
||||||
|
v.Channel.Title.ToLower().Contains(token) ||
|
||||||
|
v.Title.ToLower().Contains(token) ||
|
||||||
|
v.Description.ToLower().Contains(token));
|
||||||
|
});
|
||||||
|
|
||||||
|
// Get all the relevant videos.
|
||||||
|
var vids = await dbquery
|
||||||
|
.OrderByDescending(i => i.AddedToYT)
|
||||||
|
.Take(max_per_query)
|
||||||
|
.Include(v => v.Channel)
|
||||||
|
.Include(v => v.Tags)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
// Convert them to what we will send out.
|
||||||
|
var converted = vids
|
||||||
|
.Select(v => new Video_ForAPI(v))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
// Convert all the videos to what we will send back.
|
||||||
|
return Ok(converted);
|
||||||
|
}
|
||||||
|
|
||||||
// Returns the most recent videos of a channel.
|
// Returns the most recent videos of a channel.
|
||||||
[HttpGet("fromchannel/{channelName}")]
|
[HttpGet("fromchannel/{channelName}")]
|
||||||
public async Task<IActionResult> Get_Channel_Videos([FromRoute] string channelName) {
|
public async Task<IActionResult> Get_Channel_Videos([FromRoute] string channelName) {
|
||||||
|
Loading…
Reference in New Issue
Block a user