diff --git a/client/package-lock.json b/client/package-lock.json
index f86236d..1ecf354 100644
--- a/client/package-lock.json
+++ b/client/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "pod-noms.web",
- "version": "0.13.0",
+ "version": "0.16.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -522,14 +522,6 @@
"moment": "2.21.0"
}
},
- "angulartics2": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/angulartics2/-/angulartics2-5.1.2.tgz",
- "integrity": "sha512-ZTmSXH6t7Set8TT4oY6HcCLr7bIbK56oJnUVlDJNXSnCTS2DeZW0lP/4pcGpdELCTAF5xfosjar+DM+7kqWiPQ==",
- "requires": {
- "tslib": "1.9.0"
- }
- },
"ansi-html": {
"version": "0.0.7",
"resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz",
diff --git a/client/package.json b/client/package.json
index 199949d..6e342e9 100644
--- a/client/package.json
+++ b/client/package.json
@@ -1,6 +1,6 @@
{
"name": "pod-noms.web",
- "version": "0.15.0",
+ "version": "0.16.0",
"license": "MIT",
"scripts": {
"ng": "ng",
diff --git a/client/src/app/app.component.ts b/client/src/app/app.component.ts
index 0a23796..1a7e742 100644
--- a/client/src/app/app.component.ts
+++ b/client/src/app/app.component.ts
@@ -2,7 +2,6 @@ import { GlobalsService } from './services/globals.service';
import { Component, HostBinding } from '@angular/core';
import { Store } from '@ngrx/store';
import { AuthService } from 'app/services/auth.service';
-import { Angulartics2GoogleAnalytics } from 'angulartics2/ga';
@Component({
selector: 'app-root',
diff --git a/client/src/app/app.module.ts b/client/src/app/app.module.ts
index 8d9fa91..3448dfb 100644
--- a/client/src/app/app.module.ts
+++ b/client/src/app/app.module.ts
@@ -48,6 +48,7 @@ import { ResetComponent } from './components/reset/reset.component';
import { ProfileComponent } from './components/profile/profile.component';
import { AboutComponent } from './components/about/about.component';
import { FooterComponent } from './components/footer/footer.component';
+import { JobsService } from 'app/services/jobs.service';
export function authHttpServiceFactory(http: Http, options: RequestOptions) {
return new AuthHttp(
@@ -122,6 +123,7 @@ export function authHttpServiceFactory(http: Http, options: RequestOptions) {
PodcastService,
ImageService,
DebugService,
+ JobsService,
GlobalsService
],
bootstrap: [AppComponent]
diff --git a/client/src/app/components/debug/debug.component.html b/client/src/app/components/debug/debug.component.html
index 5385721..b175847 100644
--- a/client/src/app/components/debug/debug.component.html
+++ b/client/src/app/components/debug/debug.component.html
@@ -20,6 +20,17 @@
+
+
+
+
+
+
+
+
@@ -30,11 +41,11 @@
- API Host: {{apiHost}}
- SignalR Host: {{signalrHost}}
+ API Host: {{apiHost}}
+ SignalR Host: {{signalrHost}}
Ping: {{pingPong}}
-
\ No newline at end of file
+
diff --git a/client/src/app/components/debug/debug.component.ts b/client/src/app/components/debug/debug.component.ts
index d51a37d..16eab78 100644
--- a/client/src/app/components/debug/debug.component.ts
+++ b/client/src/app/components/debug/debug.component.ts
@@ -3,6 +3,7 @@ import { SignalRService } from 'app/services/signalr.service';
import { Component, OnInit } from '@angular/core';
import { DebugService } from 'app/services/debug.service';
import { environment } from 'environments/environment';
+import { JobsService } from 'app/services/jobs.service';
@Component({
selector: 'app-debug',
@@ -18,7 +19,8 @@ export class DebugComponent implements OnInit {
signalrHost = environment.SIGNALR_HOST;
pingPong = '';
- constructor(private _debugService: DebugService, private _signalrService: SignalRService) {}
+ constructor(private _debugService: DebugService, private _jobsService: JobsService,
+ private _signalrService: SignalRService) {}
ngOnInit() {
this._signalrService
.init(`${environment.SIGNALR_HOST}hubs/debug`)
@@ -41,4 +43,9 @@ export class DebugComponent implements OnInit {
doSomething() {
alert('doSomething was did');
}
+
+ processOrphans(){
+ this._jobsService.processOrphans()
+ .subscribe(e => console.log('debug.component.ts', 'processOrphans', e));
+ }
}
diff --git a/client/src/app/components/navbar/navbar.component.html b/client/src/app/components/navbar/navbar.component.html
index 69922c9..81014ec 100644
--- a/client/src/app/components/navbar/navbar.component.html
+++ b/client/src/app/components/navbar/navbar.component.html
@@ -4,6 +4,9 @@
Add Podcast
+
-
\ No newline at end of file
+
diff --git a/client/src/app/components/podcast/podcast-add-url-form/podcast-add-url-form.component.ts b/client/src/app/components/podcast/podcast-add-url-form/podcast-add-url-form.component.ts
index 7e110f2..7cf7740 100644
--- a/client/src/app/components/podcast/podcast-add-url-form/podcast-add-url-form.component.ts
+++ b/client/src/app/components/podcast/podcast-add-url-form/podcast-add-url-form.component.ts
@@ -17,6 +17,7 @@ import { PodcastService } from 'app/services/podcast.service';
export class PodcastAddUrlFormComponent implements AfterViewInit {
@Input() podcast: PodcastModel;
@Output() onUrlAddComplete: EventEmitter = new EventEmitter();
+ @Output() onUploadDeferred: EventEmitter = new EventEmitter();
newEntrySourceUrl: string;
errorText: string;
isPosting: boolean = false;
@@ -36,20 +37,23 @@ export class PodcastAddUrlFormComponent implements AfterViewInit {
this.errorText = '';
if (this.isValidURL(urlToCheck)) {
this.isPosting = true;
- const entry = new PodcastEntryModel(
- this.podcast.id,
- urlToCheck
- );
- this._service.addEntry(entry)
- .subscribe(e => {
+ const entry = new PodcastEntryModel(this.podcast.id, urlToCheck);
+ this._service.addEntry(entry).subscribe(
+ e => {
if (e) {
- this.onUrlAddComplete.emit(e);
+ if (e.ProcessingStatus == 6) {
+ this.onUploadDeferred.emit(e);
+ } else {
+ this.onUrlAddComplete.emit(e);
+ }
}
- }, (err) => {
+ },
+ err => {
this.isPosting = false;
this.errorText = 'This does not look like a valid URL';
this.newEntrySourceUrl = urlToCheck;
- });
+ }
+ );
} else {
this.isPosting = false;
this.errorText = 'This does not look like a valid URL';
diff --git a/client/src/app/components/podcast/podcast.component.html b/client/src/app/components/podcast/podcast.component.html
index bd0bb75..7ffbc20 100644
--- a/client/src/app/components/podcast/podcast.component.html
+++ b/client/src/app/components/podcast/podcast.component.html
@@ -45,7 +45,8 @@
+ (onUrlAddComplete)="onUrlAddComplete($event)"
+ (onUploadDeferred)="onEntryUploadDeferred($event)">
diff --git a/client/src/app/components/podcast/podcast.component.ts b/client/src/app/components/podcast/podcast.component.ts
index e042ad1..5882e4d 100644
--- a/client/src/app/components/podcast/podcast.component.ts
+++ b/client/src/app/components/podcast/podcast.component.ts
@@ -7,7 +7,7 @@ import { AppComponent } from 'app/app.component';
import { Store } from '@ngrx/store';
import { ApplicationState } from 'app/store';
import { HostListener } from '@angular/core';
-import {Location} from '@angular/common';
+import { Location } from '@angular/common';
import { UpdateAction, AddAction } from 'app/actions/entries.actions';
import * as fromPodcast from 'app/reducers';
@@ -34,7 +34,11 @@ export class PodcastComponent {
}
}
- constructor(private _store: Store, route: ActivatedRoute, private _location: Location) {
+ constructor(
+ private _store: Store,
+ route: ActivatedRoute,
+ private _location: Location
+ ) {
this.selectedPodcast$ = _store.select(fromPodcast.getSelectedPodcast);
this.entries$ = _store.select(fromPodcast.getEntries);
@@ -48,8 +52,12 @@ export class PodcastComponent {
this.selectedPodcast$.subscribe(r => {
if (r) {
slug = r.slug;
- _store.dispatch(new fromEntriesActions.LoadAction(slug));
- _store.dispatch(new fromPodcastActions.SelectAction(slug));
+ _store.dispatch(
+ new fromEntriesActions.LoadAction(slug)
+ );
+ _store.dispatch(
+ new fromPodcastActions.SelectAction(slug)
+ );
this._location.go('/podcasts/' + slug);
}
@@ -79,6 +87,9 @@ export class PodcastComponent {
// so do a funky success/update dance
this._store.dispatch(new fromEntriesActions.AddSuccessAction(entry));
this._store.dispatch(new fromEntriesActions.UpdateAction(entry));
+ }
+ onEntryUploadDeferred($event) {
+
}
onUrlAddComplete(entry: PodcastEntryModel) {
this.urlMode = false;
diff --git a/client/src/app/models/podcasts.models.ts b/client/src/app/models/podcasts.models.ts
old mode 100755
new mode 100644
diff --git a/client/src/app/models/profile.model.ts b/client/src/app/models/profile.model.ts
old mode 100755
new mode 100644
diff --git a/client/src/app/services/auth.guard.ts b/client/src/app/services/auth.guard.ts
old mode 100755
new mode 100644
diff --git a/client/src/app/services/auth.service.ts b/client/src/app/services/auth.service.ts
old mode 100755
new mode 100644
diff --git a/client/src/app/services/jobs.service.ts b/client/src/app/services/jobs.service.ts
new file mode 100644
index 0000000..12f52e2
--- /dev/null
+++ b/client/src/app/services/jobs.service.ts
@@ -0,0 +1,14 @@
+import { Injectable } from '@angular/core';
+import { Response } from '@angular/http';
+import { AuthHttp } from 'angular2-jwt';
+import { Observable } from 'rxjs/Observable';
+import { environment } from 'environments/environment';
+
+@Injectable()
+export class JobsService {
+ constructor(private _http: AuthHttp) {}
+
+ processOrphans(): Observable {
+ return this._http.get(environment.API_HOST + '/job/processorphans');
+ }
+}
diff --git a/client/src/app/services/profile.service.ts b/client/src/app/services/profile.service.ts
old mode 100755
new mode 100644
diff --git a/client/src/app/services/pusher.service.ts b/client/src/app/services/pusher.service.ts
old mode 100755
new mode 100644
diff --git a/client/src/assets/img/logo-icon.png b/client/src/assets/img/logo-icon.png
old mode 100755
new mode 100644
diff --git a/client/src/assets/img/robothand.jpg b/client/src/assets/img/robothand.jpg
old mode 100755
new mode 100644
diff --git a/client/src/environments/environment.prod.ts b/client/src/environments/environment.prod.ts
old mode 100755
new mode 100644
diff --git a/client/src/environments/environment.ts b/client/src/environments/environment.ts
old mode 100755
new mode 100644
diff --git a/client/upgrade_cli b/client/upgrade_cli
old mode 100755
new mode 100644
diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml
old mode 100755
new mode 100644
index 15fb312..b3eb6b5
--- a/docker/docker-compose.yml
+++ b/docker/docker-compose.yml
@@ -1,7 +1,7 @@
version: '2'
services:
nginx:
- restart: "always"
+ # restart: "always"
build: ./nginx/
ports:
- "80:80"
diff --git a/docker/letsencrypt.sh b/docker/letsencrypt.sh
old mode 100755
new mode 100644
index cb6df75..b00b435
--- a/docker/letsencrypt.sh
+++ b/docker/letsencrypt.sh
@@ -13,6 +13,19 @@ if [[ $web == "Y" || $web == "y" ]]; then
fi
echo \n
+read -n1 -p "Renew api? [y,n]" api
+if [[ $api == "Y" || $api == "y" ]]; then
+ docker run -it --rm -p 443:443 -p 80:80 --name certbot \
+ -v "/etc/letsencrypt:/etc/letsencrypt" \
+ -v "/var/lib/letsencrypt:/var/lib/letsencrypt" \
+ certbot/certbot certonly \
+ --agree-tos \
+ --renew-by-default \
+ -d api.podnoms.com \
+ -m fergal.moran@gmail.com
+fi
+echo \n
+
read -n1 -p "Renew realtime? [y,n]" rt
if [[ $rt == "Y" || $rt == "y" ]]; then
docker run -it --rm -p 443:443 -p 80:80 --name certbot \
diff --git a/docker/nginx/conf.d/podnoms.conf b/docker/nginx/conf.d/podnoms.conf
index e6feece..f8424d6 100644
--- a/docker/nginx/conf.d/podnoms.conf
+++ b/docker/nginx/conf.d/podnoms.conf
@@ -42,6 +42,31 @@ server {
}
}
+server {
+ listen 80;
+ listen 443 ssl;
+
+ server_name api.podnoms.com;
+
+ ssl_certificate /etc/letsencrypt/live/api.podnoms.com/fullchain.pem;
+ ssl_certificate_key /etc/letsencrypt/live/api.podnoms.com/privkey.pem;
+ ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
+ ssl_prefer_server_ciphers on;
+ ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
+
+ if ($ssl_protocol = "") {
+ rewrite ^((?!/rss/).) https://$server_name$request_uri? permanent;
+ }
+
+ location / {
+ proxy_pass http://api:5000/;
+
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection "upgrade";
+ }
+}
+
server {
listen 80;
listen 443 ssl;
@@ -79,7 +104,7 @@ server {
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
location / {
- proxy_pass http://api:5000/hangfire;
+ proxy_pass http://api:5000/;
}
}
diff --git a/server/.gitignore b/server/.gitignore
old mode 100755
new mode 100644
diff --git a/server/Controllers/EntryController.cs b/server/Controllers/EntryController.cs
index f0d953e..cd2d8dd 100644
--- a/server/Controllers/EntryController.cs
+++ b/server/Controllers/EntryController.cs
@@ -11,6 +11,7 @@ using Microsoft.Extensions.Options;
using PodNoms.Api.Models;
using PodNoms.Api.Models.ViewModels;
using PodNoms.Api.Persistence;
+using PodNoms.Api.Services;
using PodNoms.Api.Services.Processor;
using PodNoms.Api.Services.Storage;
@@ -67,18 +68,24 @@ namespace PodNoms.Api.Controllers {
// first check url is valid
var entry = _mapper.Map(item);
var podcast = await _podcastRepository.GetAsync(item.PodcastId);
- if (podcast != null && await _processor.GetInformation(entry)) {
- if (entry.ProcessingStatus == ProcessingStatus.Processing) {
- if (string.IsNullOrEmpty(entry.ImageUrl)) {
- entry.ImageUrl = $"{_storageSettings.CdnUrl}static/images/default-entry.png";
+ if (podcast != null) {
+ var status = await _processor.GetInformation(entry);
+ if (status == AudioType.Valid) {
+ if (entry.ProcessingStatus == ProcessingStatus.Processing) {
+ if (string.IsNullOrEmpty(entry.ImageUrl)) {
+ entry.ImageUrl = $"{_storageSettings.CdnUrl}static/images/default-entry.png";
+ }
+ entry.Podcast = podcast;
+ entry.Processed = false;
+ await _repository.AddOrUpdateAsync(entry);
+ await _unitOfWork.CompleteAsync();
+ _processEntry(entry);
+ var result = _mapper.Map(entry);
+ return result;
}
- entry.Podcast = podcast;
- entry.Processed = false;
- await _repository.AddOrUpdateAsync(entry);
- await _unitOfWork.CompleteAsync();
- _processEntry(entry);
- var result = _mapper.Map(entry);
- return result;
+ } else if (status == AudioType.Playlist) {
+ entry.ProcessingStatus = ProcessingStatus.Deferred;
+ return Accepted(entry);
}
}
return BadRequest();
diff --git a/server/Controllers/PodcastController.cs b/server/Controllers/PodcastController.cs
old mode 100755
new mode 100644
diff --git a/server/Controllers/ProfileController.cs b/server/Controllers/ProfileController.cs
old mode 100755
new mode 100644
diff --git a/server/Controllers/RssController.cs b/server/Controllers/RssController.cs
old mode 100755
new mode 100644
diff --git a/server/Dockerfile b/server/Dockerfile
old mode 100755
new mode 100644
diff --git a/server/Models/AppSettings.cs b/server/Models/AppSettings.cs
old mode 100755
new mode 100644
diff --git a/server/Models/BaseModel.cs b/server/Models/BaseModel.cs
old mode 100755
new mode 100644
diff --git a/server/Models/Podcast.cs b/server/Models/Podcast.cs
old mode 100755
new mode 100644
diff --git a/server/Models/PodcastEntry.cs b/server/Models/PodcastEntry.cs
old mode 100755
new mode 100644
index 69c9b79..e992a50
--- a/server/Models/PodcastEntry.cs
+++ b/server/Models/PodcastEntry.cs
@@ -7,7 +7,8 @@ namespace PodNoms.Api.Models {
Processing, //2
Uploading, //3
Processed, //4
- Failed //5
+ Failed, //5
+ Deferred //6
}
public class PodcastEntry : BaseModel {
diff --git a/server/Models/User.cs b/server/Models/User.cs
old mode 100755
new mode 100644
diff --git a/server/Models/ViewModels/ProfileViewModel.cs b/server/Models/ViewModels/ProfileViewModel.cs
old mode 100755
new mode 100644
diff --git a/server/Models/ViewModels/RssViewModels/PodcastRssViewModel.cs b/server/Models/ViewModels/RssViewModels/PodcastRssViewModel.cs
old mode 100755
new mode 100644
diff --git a/server/Persistence/IPodcastRepository.cs b/server/Persistence/IPodcastRepository.cs
old mode 100755
new mode 100644
diff --git a/server/Persistence/IUserRepository.cs b/server/Persistence/IUserRepository.cs
old mode 100755
new mode 100644
diff --git a/server/Persistence/PodcastRepository.cs b/server/Persistence/PodcastRepository.cs
old mode 100755
new mode 100644
diff --git a/server/Persistence/PodnomsContext.cs b/server/Persistence/PodnomsContext.cs
old mode 100755
new mode 100644
diff --git a/server/Persistence/UserRepository.cs b/server/Persistence/UserRepository.cs
old mode 100755
new mode 100644
diff --git a/server/Resources/podcast.xml b/server/Resources/podcast.xml
old mode 100755
new mode 100644
diff --git a/server/Services/Auth/AuthenticationMiddleware.cs b/server/Services/Auth/AuthenticationMiddleware.cs
old mode 100755
new mode 100644
diff --git a/server/Services/Downloader/AudioDownloader.cs b/server/Services/Downloader/AudioDownloader.cs
index 370f5ed..8a99654 100644
--- a/server/Services/Downloader/AudioDownloader.cs
+++ b/server/Services/Downloader/AudioDownloader.cs
@@ -13,6 +13,7 @@ using static NYoutubeDL.Helpers.Enums;
namespace PodNoms.Api.Services.Downloader {
public class AudioDownloader {
+
private readonly string _url;
private readonly string _downloader;
public VideoDownloadInfo Properties { get; private set; }
@@ -49,17 +50,22 @@ namespace PodNoms.Api.Services.Downloader {
return $"{{\"Error\": \"{ex.Message}\"}}";
}
}
- public async Task GetInfo() {
- var ret = false;
+ public async Task GetInfo() {
+ var ret = AudioType.Invalid;
await Task.Run(() => {
var youtubeDl = new YoutubeDL();
youtubeDl.VideoUrl = this._url;
- var info = youtubeDl.GetDownloadInfo() as VideoDownloadInfo;
- ret = (
- info != null &&
- info is VideoDownloadInfo && //make sure it's not a playlist
- (info.Errors.Count == 0 || info.VideoSize != null));
- if (ret) this.Properties = info;
+ DownloadInfo info = youtubeDl.GetDownloadInfo();
+
+ if (info != null &&
+ (info.Errors.Count == 0 || info.VideoSize != null)) {
+ if (info is PlaylistDownloadInfo) {
+ ret = AudioType.Playlist;
+ } else if (info is VideoDownloadInfo) {
+ ret = AudioType.Valid;
+ this.Properties = (VideoDownloadInfo)info;
+ }
+ }
});
return ret;
}
diff --git a/server/Services/Jobs/ClearOrphanAudioJob.cs b/server/Services/Jobs/ClearOrphanAudioJob.cs
index effff73..4bdddfc 100644
--- a/server/Services/Jobs/ClearOrphanAudioJob.cs
+++ b/server/Services/Jobs/ClearOrphanAudioJob.cs
@@ -7,18 +7,15 @@ using Microsoft.WindowsAzure.Storage.Blob;
using PodNoms.Api.Models;
using PodNoms.Api.Persistence;
-namespace PodNoms.Api.Services.Jobs
-{
- public class ClearOrphanAudioJob : IJob
- {
+namespace PodNoms.Api.Services.Jobs {
+ public class ClearOrphanAudioJob : IJob {
public readonly IEntryRepository _entryRepository;
public readonly StorageSettings _storageSettings;
public readonly AudioFileStorageSettings _audioStorageSettings;
private readonly ILogger _logger;
public ClearOrphanAudioJob(IEntryRepository entryRepository, IOptions storageSettings,
- IOptions audioStorageSettings, ILoggerFactory logger)
- {
+ IOptions audioStorageSettings, ILoggerFactory logger) {
this._storageSettings = storageSettings.Value;
this._audioStorageSettings = audioStorageSettings.Value;
this._entryRepository = entryRepository;
@@ -26,38 +23,28 @@ namespace PodNoms.Api.Services.Jobs
this._logger = logger.CreateLogger();
}
- public async Task Execute()
- {
- try
- {
+ public async Task Execute() {
+ try {
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(_storageSettings.ConnectionString);
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference(_audioStorageSettings.ContainerName);
var blobs = await container.ListBlobsSegmentedAsync(null);
- foreach (CloudBlockBlob blob in blobs.Results)
- {
- try
- {
+ foreach (CloudBlockBlob blob in blobs.Results) {
+ try {
Console.WriteLine(blob.StorageUri);
var guid = blob.Name.Split('.')[0];
- if (!string.IsNullOrEmpty(guid))
- {
+ if (!string.IsNullOrEmpty(guid)) {
var entry = await _entryRepository.GetByUidAsync(guid);
- if (entry == null)
- {
+ if (entry == null) {
await blob.DeleteIfExistsAsync();
}
}
- }
- catch (Exception e)
- {
+ } catch (Exception e) {
_logger.LogWarning($"Error processing blob {blob.Uri}\n{e.Message}");
}
}
- }
- catch (Exception ex)
- {
+ } catch (Exception ex) {
_logger.LogError($"Error clearing orphans\n{ex.Message}");
}
}
diff --git a/server/Services/Jobs/JobBootstrapper.cs b/server/Services/Jobs/JobBootstrapper.cs
new file mode 100644
index 0000000..8c6dcc1
--- /dev/null
+++ b/server/Services/Jobs/JobBootstrapper.cs
@@ -0,0 +1,13 @@
+using Hangfire;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+using PodNoms.Api.Models;
+using PodNoms.Api.Persistence;
+
+namespace PodNoms.Api.Services.Jobs {
+ public static class JobBootstrapper {
+ public static void BootstrapJobs() {
+ RecurringJob.AddOrUpdate(x => x.Execute(), Cron.Daily(1));
+ }
+ }
+}
\ No newline at end of file
diff --git a/server/Services/Processor/IUrlProcessService.cs b/server/Services/Processor/IUrlProcessService.cs
index ad3b585..0319122 100644
--- a/server/Services/Processor/IUrlProcessService.cs
+++ b/server/Services/Processor/IUrlProcessService.cs
@@ -3,8 +3,9 @@ using PodNoms.Api.Models;
namespace PodNoms.Api.Services.Processor {
public interface IUrlProcessService {
- Task GetInformation (int entryId);
- Task GetInformation (PodcastEntry entry);
- Task DownloadAudio (int entryId);
+
+ Task GetInformation(int entryId);
+ Task GetInformation(PodcastEntry entry);
+ Task DownloadAudio(int entryId);
}
}
\ No newline at end of file
diff --git a/server/Services/Processor/UrlProcessService.cs b/server/Services/Processor/UrlProcessService.cs
index ec74206..2a3e7e0 100644
--- a/server/Services/Processor/UrlProcessService.cs
+++ b/server/Services/Processor/UrlProcessService.cs
@@ -37,23 +37,23 @@ namespace PodNoms.Api.Services.Processor {
uid,
e);
}
- public async Task GetInformation(int entryId) {
+ public async Task GetInformation(int entryId) {
var entry = await _repository.GetAsync(entryId);
if (entry == null || string.IsNullOrEmpty(entry.SourceUrl)) {
_logger.LogError("Unable to process item");
- return false;
+ return AudioType.Invalid;
}
if (entry.SourceUrl.EndsWith(".mp3") || entry.SourceUrl.EndsWith(".wav") || entry.SourceUrl.EndsWith(".aif")) {
- return true;
+ return AudioType.Valid;
}
return await GetInformation(entry);
}
- public async Task GetInformation(PodcastEntry entry) {
+ public async Task GetInformation(PodcastEntry entry) {
var downloader = new AudioDownloader(entry.SourceUrl, _applicationsSettings.Downloader);
- await downloader.GetInfo();
- if (downloader.Properties != null) {
+ var ret = await downloader.GetInfo();
+ if (ret == AudioType.Valid) {
entry.Title = downloader.Properties?.Title;
entry.Description = downloader.Properties?.Description;
entry.ImageUrl = downloader.Properties?.Thumbnail;
@@ -68,11 +68,8 @@ namespace PodNoms.Api.Services.Processor {
_logger.LogDebug("***DOWNLOAD INFO RETRIEVED****\n");
_logger.LogDebug($"Title: {entry.Title}\nDescription: {entry.Description}\nAuthor: {entry.Author}\n");
-
- // var pusherResult = await _sendProcessCompleteMessage(entry);
- return true;
}
- return false;
+ return ret;
}
public async Task DownloadAudio(int entryId) {
var entry = await _repository.GetAsync(entryId);
diff --git a/server/Services/RemoteAudioTypes.cs b/server/Services/RemoteAudioTypes.cs
new file mode 100644
index 0000000..36c0159
--- /dev/null
+++ b/server/Services/RemoteAudioTypes.cs
@@ -0,0 +1,7 @@
+namespace PodNoms.Api.Services {
+ public enum AudioType {
+ Invalid,
+ Valid,
+ Playlist
+ }
+}
\ No newline at end of file
diff --git a/server/Startup.cs b/server/Startup.cs
index 217a2d1..5e31c15 100644
--- a/server/Startup.cs
+++ b/server/Startup.cs
@@ -39,61 +39,61 @@ namespace PodNoms.Api {
public class Startup {
public IConfiguration Configuration { get; }
- public Startup (IConfiguration configuration) {
+ public Startup(IConfiguration configuration) {
Configuration = configuration;
}
- public void ConfigureProductionServices (IServiceCollection services) {
- ConfigureServices (services);
- services.AddHangfire (config => {
- config.UseSqlServerStorage (Configuration["ConnectionStrings:DefaultConnection"]);
+ public void ConfigureProductionServices(IServiceCollection services) {
+ ConfigureServices(services);
+ services.AddHangfire(config => {
+ config.UseSqlServerStorage(Configuration["ConnectionStrings:DefaultConnection"]);
});
}
- public void ConfigureDevelopmentServices (IServiceCollection services) {
- ConfigureServices (services);
- services.AddHangfire (config => {
- config.UseMemoryStorage ();
+ public void ConfigureDevelopmentServices(IServiceCollection services) {
+ ConfigureServices(services);
+ services.AddHangfire(config => {
+ config.UseMemoryStorage();
});
}
- public void ConfigureServices (IServiceCollection services) {
- Console.WriteLine ($"Configuring services: {Configuration.ToString()}");
+ public void ConfigureServices(IServiceCollection services) {
+ Console.WriteLine($"Configuring services: {Configuration.ToString()}");
- services.AddDbContext (options =>
- options.UseSqlServer (Configuration.GetConnectionString ("DefaultConnection")));
+ services.AddDbContext(options =>
+ options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
- services.AddOptions ();
- services.Configure (Configuration.GetSection ("App"));
- services.Configure (Configuration.GetSection ("Storage"));
- services.Configure (Configuration.GetSection ("ApplicationsSettings"));
- services.Configure (Configuration.GetSection ("ImageFileStorageSettings"));
- services.Configure (Configuration.GetSection ("AudioFileStorageSettings"));
- services.Configure (options => {
+ services.AddOptions();
+ services.Configure(Configuration.GetSection("App"));
+ services.Configure(Configuration.GetSection("Storage"));
+ services.Configure(Configuration.GetSection("ApplicationsSettings"));
+ services.Configure(Configuration.GetSection("ImageFileStorageSettings"));
+ services.Configure(Configuration.GetSection("AudioFileStorageSettings"));
+ services.Configure(options => {
options.ValueCountLimit = 10;
options.ValueLengthLimit = int.MaxValue;
options.MemoryBufferThreshold = Int32.MaxValue;
options.MultipartBodyLengthLimit = long.MaxValue;
});
- services.AddAutoMapper (e => {
- e.AddProfile (new MappingProvider (Configuration));
+ services.AddAutoMapper(e => {
+ e.AddProfile(new MappingProvider(Configuration));
});
- services.AddAuthentication (options => {
+ services.AddAuthentication(options => {
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultSignInScheme = JwtBearerDefaults.AuthenticationScheme;
- }).AddJwtBearer (options => {
+ }).AddJwtBearer(options => {
options.Audience = Configuration["auth0:clientId"];
options.Authority = $"https://{Configuration["auth0:domain"]}/";
options.TokenValidationParameters = new TokenValidationParameters {
NameClaimType = "name"
};
- options.Events = new JwtBearerEvents () {
+ options.Events = new JwtBearerEvents() {
OnTokenValidated = AuthenticationMiddleware.OnTokenValidated
};
options.Events.OnMessageReceived = context => {
StringValues token;
- if (context.Request.Path.Value.StartsWith ("/hubs/") && context.Request.Query.TryGetValue ("token", out token)) {
+ if (context.Request.Path.Value.StartsWith("/hubs/") && context.Request.Query.TryGetValue("token", out token)) {
context.Token = token;
}
@@ -102,107 +102,107 @@ namespace PodNoms.Api {
});
var defaultPolicy =
- new AuthorizationPolicyBuilder ()
- .AddAuthenticationSchemes ("Bearer")
- .RequireAuthenticatedUser ()
- .Build ();
+ new AuthorizationPolicyBuilder()
+ .AddAuthenticationSchemes("Bearer")
+ .RequireAuthenticatedUser()
+ .Build();
- services.AddAuthorization (j => {
+ services.AddAuthorization(j => {
j.DefaultPolicy = defaultPolicy;
});
- services.AddMvc (options => {
- options.OutputFormatters.Add (new XmlSerializerOutputFormatter ());
- options.OutputFormatters
- .OfType ()
- .Single ().SupportedMediaTypes.Add ("text/html");
- })
- .SetCompatibilityVersion (CompatibilityVersion.Version_2_1)
- .AddJsonOptions (options => {
- options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver ();
+ services.AddMvc(options => {
+ options.OutputFormatters.Add(new XmlSerializerOutputFormatter());
+ options.OutputFormatters
+ .OfType()
+ .Single().SupportedMediaTypes.Add("text/html");
+ })
+ .SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
+ .AddJsonOptions(options => {
+ options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;
})
- .AddXmlSerializerFormatters ();
+ .AddXmlSerializerFormatters();
- services.Configure (x => {
+ services.Configure(x => {
x.ValueLengthLimit = int.MaxValue;
x.MultipartBodyLengthLimit = int.MaxValue; // In case of multipart
});
- services.AddSignalR (config => { });
+ services.AddSignalR(config => { });
- services.AddCors (options => {
- options.AddPolicy ("AllowAllOrigins",
+ services.AddCors(options => {
+ options.AddPolicy("AllowAllOrigins",
builder => builder
- .AllowAnyOrigin ()
- .AllowAnyMethod ()
- .AllowAnyHeader ()
- .AllowCredentials ());
+ .AllowAnyOrigin()
+ .AllowAnyMethod()
+ .AllowAnyHeader()
+ .AllowCredentials());
});
- services.AddTransient ();
- services.AddTransient ();
- services.AddScoped ();
- services.AddScoped ();
- services.AddScoped ();
- services.AddScoped ();
- services.AddScoped ();
- services.AddScoped ();
+ services.AddTransient();
+ services.AddTransient();
+ services.AddScoped();
+ services.AddScoped();
+ services.AddScoped();
+ services.AddScoped();
+ services.AddScoped();
+ services.AddScoped();
- services.AddSingleton (typeof (HubLifetimeManager),
- typeof (DebugHubLifetimeManager));
+ services.AddSingleton(typeof(HubLifetimeManager),
+ typeof(DebugHubLifetimeManager));
//register the codepages (required for slugify)
var instance = CodePagesEncodingProvider.Instance;
- Encoding.RegisterProvider (instance);
+ Encoding.RegisterProvider(instance);
}
- public void Configure (IApplicationBuilder app, IHostingEnvironment env,
+ public void Configure(IApplicationBuilder app, IHostingEnvironment env,
ILoggerFactory loggerFactory, IServiceProvider serviceProvider) {
- if (env.IsDevelopment ()) {
- app.UseDeveloperExceptionPage ();
+ if (env.IsDevelopment()) {
+ app.UseDeveloperExceptionPage();
} else {
- app.UseExceptionHandler ("/Home/Error");
+ app.UseExceptionHandler("/Home/Error");
}
- Console.WriteLine ("Performing migrations");
+ Console.WriteLine("Performing migrations");
//TODO: Fix this when EF sucks less
// using (var context = new PodnomsDbContext(
// app.ApplicationServices.GetRequiredService>()))
// {
// context.Database.Migrate();
// }
- Console.WriteLine ("Successfully migrated");
+ Console.WriteLine("Successfully migrated");
// app.UseHsts();
// app.UseHttpsRedirection();
- app.UseStaticFiles ();
+ app.UseStaticFiles();
- GlobalConfiguration.Configuration.UseActivator (new ServiceProviderActivator (serviceProvider));
+ GlobalConfiguration.Configuration.UseActivator(new ServiceProviderActivator(serviceProvider));
- if ((env.IsProduction () || true)) {
- app.UseHangfireServer ();
- app.UseHangfireDashboard ("/hangfire", new DashboardOptions {
- Authorization = new [] { new HangFireAuthorizationFilter () }
+ if ((env.IsProduction() || true)) {
+ app.UseHangfireServer();
+ app.UseHangfireDashboard("/hangfire", new DashboardOptions {
+ Authorization = new[] { new HangFireAuthorizationFilter() }
});
}
- app.UseCors ("AllowAllOrigins");
+ app.UseCors("AllowAllOrigins");
- app.UseSignalR (routes => {
- routes.MapHub ("/hubs/audioprocessing");
- routes.MapHub ("/hubs/debug");
+ app.UseSignalR(routes => {
+ routes.MapHub("/hubs/audioprocessing");
+ routes.MapHub("/hubs/debug");
});
- app.UseMvc (routes => {
- routes.MapRoute (
+ app.UseMvc(routes => {
+ routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
//start hangfire jobs
- //RecurringJob.AddOrUpdate(x => x.Execute(), Cron.Hourly);
+ JobBootstrapper.BootstrapJobs();
}
}
}
\ No newline at end of file
diff --git a/server/Utils/Crypt/HMACGenerator.cs b/server/Utils/Crypt/HMACGenerator.cs
old mode 100755
new mode 100644
diff --git a/server/Utils/Crypt/MD5Generator.cs b/server/Utils/Crypt/MD5Generator.cs
old mode 100755
new mode 100644
diff --git a/server/Utils/DateUtils.cs b/server/Utils/DateUtils.cs
old mode 100755
new mode 100644
diff --git a/server/Utils/Extensions/DateTime.cs b/server/Utils/Extensions/DateTime.cs
old mode 100755
new mode 100644
diff --git a/server/Utils/Extensions/String.cs b/server/Utils/Extensions/String.cs
old mode 100755
new mode 100644
diff --git a/server/Utils/HttpUtils.cs b/server/Utils/HttpUtils.cs
old mode 100755
new mode 100644
diff --git a/server/Utils/HumanFriendlyInteger.cs b/server/Utils/HumanFriendlyInteger.cs
old mode 100755
new mode 100644
diff --git a/server/Utils/ImageUtils.cs b/server/Utils/ImageUtils.cs
old mode 100755
new mode 100644
diff --git a/server/Utils/Randomisers.cs b/server/Utils/Randomisers.cs
old mode 100755
new mode 100644
diff --git a/server/Utils/ResourceReader.cs b/server/Utils/ResourceReader.cs
old mode 100755
new mode 100644
diff --git a/server/appsettings.json b/server/appsettings.json
index 828e75b..8d28750 100644
--- a/server/appsettings.json
+++ b/server/appsettings.json
@@ -8,7 +8,7 @@
}
},
"App": {
- "Version": "0.15.0"
+ "Version": "0.16.0"
},
"ConnectionStrings": {
"DefaultConnection": "server=localhost;database=PodNoms;user id=sa;password=cTXu1nJLCpC/c"
diff --git a/server/publish.sh b/server/publish.sh
index 25d27b5..ce66001 100755
--- a/server/publish.sh
+++ b/server/publish.sh
@@ -3,3 +3,4 @@ unset DOCKER_HOST
unset DOCKER_TLS_VERIFY
docker build --rm -f Dockerfile -t fergalmoran/podnoms.api . && docker push fergalmoran/podnoms.api
+docker push fergalmoran/podnoms.api
diff --git a/server/rebuild.sh b/server/rebuild.sh
old mode 100755
new mode 100644
diff --git a/server/resetdb.sh b/server/resetdb.sh
old mode 100755
new mode 100644