Added API for managing job of updating videos
This commit is contained in:
parent
a7c5878a04
commit
28de8f1279
48
YTManager/Controllers/AdminController.cs
Normal file
48
YTManager/Controllers/AdminController.cs
Normal file
@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using YTManager;
|
||||
using YTManager.Models;
|
||||
using Hangfire.Storage;
|
||||
|
||||
namespace YTManager.Controllers {
|
||||
[Produces("application/json")]
|
||||
[Route("api/Admin")]
|
||||
public class AdminController : Controller {
|
||||
// POST api/Admin/refreshytvids
|
||||
// Force a general youtube channel update.
|
||||
[HttpPost("job_update")]
|
||||
public void Post_forcejobupdate() {
|
||||
Hangfire.RecurringJob.Trigger(Startup.periodicupdatejobID);
|
||||
}
|
||||
|
||||
// POST api/Admin/job_periodicupdate/YTChannelID
|
||||
// Force a YT Channel update.
|
||||
[HttpPost("job_update/{id}")]
|
||||
public void Post_forcejobupdateID([FromRoute] string id) {
|
||||
Hangfire.BackgroundJob.Enqueue(() => YTManager.Tasks.FetchVideos.run(id));
|
||||
}
|
||||
|
||||
// POST api/Admin/job_periodicupdate
|
||||
// Ensures that the background YT Channel update API is running.
|
||||
[HttpPost("job_periodicupdate")]
|
||||
public void Post_periodicupdatejob() {
|
||||
Hangfire.RecurringJob.AddOrUpdate(
|
||||
Startup.periodicupdatejobID,
|
||||
() => YTManager.Tasks.FetchVideos.run(""),
|
||||
Hangfire.Cron.Hourly);
|
||||
}
|
||||
|
||||
// GET api/Admin/job_periodicupdate
|
||||
// Check if the periodic update job is enqued.
|
||||
[HttpGet("job_periodicupdate")]
|
||||
public IActionResult Get_periodicupdatejob() {
|
||||
bool exists = Hangfire.JobStorage.Current.GetConnection().GetRecurringJobs().Count(j => j.Id == Startup.periodicupdatejobID) > 0;
|
||||
return Ok(exists ? "true" : "false");
|
||||
}
|
||||
}
|
||||
}
|
@ -7,16 +7,6 @@ using Newtonsoft.Json.Linq;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace YTManager.Controllers {
|
||||
[Produces("application/json")]
|
||||
[Route("api/Admin")]
|
||||
public class AdminController : Controller {
|
||||
// POST api/Admin/refreshytvids
|
||||
[HttpPost("refreshytvids")]
|
||||
public void Post() {
|
||||
Hangfire.BackgroundJob.Enqueue(() => YTManager.Tasks.FetchVideos.run());
|
||||
}
|
||||
}
|
||||
|
||||
[Produces("application/json")]
|
||||
[Route("api/Channels")]
|
||||
public class ChannelsController : Controller {
|
||||
@ -71,6 +61,11 @@ namespace YTManager.Controllers {
|
||||
// Seems good, so add it.
|
||||
_context.Channels.Add(posted);
|
||||
_context.SaveChanges();
|
||||
|
||||
// Get all new videos for the channel.
|
||||
Hangfire.RecurringJob.Trigger(Startup.periodicupdatejobID);
|
||||
|
||||
// And all is well.
|
||||
return Ok();
|
||||
}
|
||||
|
||||
|
@ -13,10 +13,8 @@ using Hangfire.PostgreSql;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace YTManager {
|
||||
public class Startup
|
||||
{
|
||||
public Startup(IConfiguration configuration)
|
||||
{
|
||||
public class Startup {
|
||||
public Startup(IConfiguration configuration) {
|
||||
Configuration = configuration;
|
||||
}
|
||||
|
||||
@ -25,21 +23,20 @@ namespace YTManager {
|
||||
// String used for connecting to the database server.
|
||||
public static string dbstr { get; } = "Host=192.168.1.130;Database=postgres;Username=postgres;Password=pass";
|
||||
|
||||
// ID for periodic job to update all channels.
|
||||
public static string periodicupdatejobID { get; } = "2013066213";
|
||||
|
||||
// This method gets called by the runtime. Use this method to add services to the container.
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
public void ConfigureServices(IServiceCollection services) {
|
||||
services.AddMvc();
|
||||
services.AddHangfire(x => x.UsePostgreSqlStorage(dbstr));
|
||||
services.AddDbContext<MediaDB>(options => options.UseNpgsql(dbstr));
|
||||
}
|
||||
|
||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
|
||||
{
|
||||
public void Configure(IApplicationBuilder app, IHostingEnvironment env) {
|
||||
if (env.IsDevelopment())
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
|
||||
app.UseDefaultFiles();
|
||||
app.UseStaticFiles();
|
||||
|
@ -9,7 +9,7 @@ namespace YTManager.Tasks
|
||||
{
|
||||
public class FetchVideos
|
||||
{
|
||||
public static void run()
|
||||
public static void run(string youtubechannelIDstr = "")
|
||||
{
|
||||
// YT API access key
|
||||
var youtubeService = new YouTubeService(new Google.Apis.Services.BaseClientService.Initializer()
|
||||
@ -22,7 +22,12 @@ namespace YTManager.Tasks
|
||||
var ops = new DbContextOptionsBuilder<MediaDB>();
|
||||
ops.UseNpgsql(YTManager.Startup.dbstr);
|
||||
using (var dbcontext = new MediaDB(ops.Options)) {
|
||||
var channels = dbcontext.Channels.ToList();
|
||||
// Get all the potential relevant channels.
|
||||
List<Models.Channel> channels;
|
||||
if (youtubechannelIDstr == "")
|
||||
channels = dbcontext.Channels.ToList();
|
||||
else
|
||||
channels = dbcontext.Channels.Where(c => c.YTChannelID == youtubechannelIDstr).ToList();
|
||||
|
||||
// Get all the most recent videos for each channel.
|
||||
channels.ForEach(ch => {
|
||||
@ -35,7 +40,7 @@ namespace YTManager.Tasks
|
||||
// Get all videos which aren't already in the DB.
|
||||
var notindb = response.Items
|
||||
.Where(i => i.Id.Kind == "youtube#video")
|
||||
.Where(i => !dbcontext.Videos.Any(dbvid => dbvid.YTVideoID != i.Id.VideoId))
|
||||
.Where(i => !dbcontext.Videos.Any(dbvid => dbvid.YTVideoID == i.Id.VideoId))
|
||||
.Select(newvid =>
|
||||
new Models.Video {
|
||||
Title = newvid.Snippet.Title,
|
||||
|
@ -12,6 +12,8 @@
|
||||
<div class="pageheader">
|
||||
<h1>Dumb YT Manager</h1>
|
||||
<p>Youtube banned my account and refuses to say why, taking all my subscribed channels with it. This is a simple scrubscribed channel manager, showing recent releases from each channel and finally proper sub-catagory functionality!</p>
|
||||
|
||||
<div id="apistatus-0"></div>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
@ -67,8 +67,6 @@ var addchanel0 = new Vue({
|
||||
this.entry.thumbnailURL = "";
|
||||
this.expanded = false;
|
||||
tbody0.retrieve();
|
||||
|
||||
axios.post('/api/admin/refreshytvids');
|
||||
setTimeout(() => videostb.retrieve(), 1000);
|
||||
}.bind(this))
|
||||
.catch(function (error) {
|
||||
@ -129,6 +127,7 @@ var tbody0 = new Vue({
|
||||
<th>Title</th>
|
||||
<th>Description</th>
|
||||
<th>ID</th>
|
||||
<th>Update</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -137,6 +136,7 @@ var tbody0 = new Vue({
|
||||
<td class="tinytext12px">{{entry.title}}</td>
|
||||
<td class="tinytext12px">{{entry.description}}</td>
|
||||
<td class="tinytext12px">{{entry.channelId}}</td>
|
||||
<td><i class="fa fa-refresh" aria-hidden="true" :id="entry.ytChannelID" @click="forcerefresh"/></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@ -159,6 +159,49 @@ var tbody0 = new Vue({
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
forcerefresh: function (event) {
|
||||
console.log("Refreshing for ID: " + event.target.id);
|
||||
axios
|
||||
.post('/api/Admin/job_update/' + event.target.id)
|
||||
.catch(function (error) { console.log(error); });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Bind to our table of entries.
|
||||
var apistatus = new Vue({
|
||||
el: '#apistatus-0',
|
||||
data: {
|
||||
apiaccessible: false,
|
||||
updatingjobactive: false
|
||||
},
|
||||
template: `
|
||||
<div class="grid-x">
|
||||
<div class="medium-1 cell">API Status</div>
|
||||
<div class="medium-1 cell">
|
||||
<i class="fa fa-thumbs-o-up apistatusicon fa-2x" aria-hidden="true" v-if="apiaccessible"></i>
|
||||
<i class="fa fa-thumbs-o-down apistatusicon fa-2x" aria-hidden="true" v-else></i>
|
||||
</div>
|
||||
<div class="medium-7 cell"></div>
|
||||
<div class="medium-2 cell">Video Fetching Status</div>
|
||||
<div class="medium-1 cell">
|
||||
<i class="fa fa-thumbs-o-up apistatusicon fa-2x" aria-hidden="true" v-if="updatingjobactive"></i>
|
||||
<i class="fa fa-thumbs-o-down apistatusicon fa-2x" aria-hidden="true" v-else></i>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
methods: {
|
||||
update: function (event) {
|
||||
axios.get('/api/Admin/job_periodicupdate')
|
||||
.then(function (response) {
|
||||
this.apiaccessible = (response.status == 200);
|
||||
this.updatingjobactive = (response.data != "false")
|
||||
}.bind(this)
|
||||
)
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -215,6 +258,7 @@ var videostb = new Vue({
|
||||
});
|
||||
|
||||
window.addEventListener('load', function () {
|
||||
apistatus.update();
|
||||
tbody0.retrieve();
|
||||
videostb.retrieve();
|
||||
});
|
||||
|
@ -47,3 +47,20 @@
|
||||
.fade-enter, .fade-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.apistatusicon {
|
||||
animation-duration: 1s;
|
||||
animation-name: spinny;
|
||||
animation-iteration-count: infinite;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
|
||||
@keyframes spinny {
|
||||
from {
|
||||
transform: rotate(-15deg);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: rotate(15deg);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user