diff --git a/backend/app.js b/backend/app.js
index 6c378e3..5ba74a3 100644
--- a/backend/app.js
+++ b/backend/app.js
@@ -48,6 +48,125 @@ app.get('/using-encryption', function(req, res) {
res.end("yes");
});
+// objects
+
+function File(id, title, thumbnailURL, isAudio, duration) {
+ this.id = id;
+ this.title = title;
+ this.thumbnailURL = thumbnailURL;
+ this.isAudio = isAudio;
+ this.duration = duration;
+}
+
+// actual functions
+
+function getThumbnailMp3(name)
+{
+ var obj = getJSONMp3(name);
+ var thumbnailLink = obj.thumbnail;
+ return thumbnailLink;
+}
+
+function getThumbnailMp4(name)
+{
+ var obj = getJSONMp4(name);
+ var thumbnailLink = obj.thumbnail;
+ return thumbnailLink;
+}
+
+function getFileSizeMp3(name)
+{
+ var jsonPath = audioPath+name+".mp3.info.json";
+
+ if (fs.existsSync(jsonPath))
+ var obj = JSON.parse(fs.readFileSync(jsonPath, 'utf8'));
+ else
+ var obj = 0;
+
+ return obj.filesize;
+}
+
+function getFileSizeMp4(name)
+{
+ var jsonPath = videoPath+name+".info.json";
+ var filesize = 0;
+ if (fs.existsSync(jsonPath))
+ {
+ var obj = JSON.parse(fs.readFileSync(jsonPath, 'utf8'));
+ var format = obj.format.substring(0,3);
+ for (i = 0; i < obj.formats.length; i++)
+ {
+ if (obj.formats[i].format_id == format)
+ {
+ filesize = obj.formats[i].filesize;
+ }
+ }
+ }
+
+ return filesize;
+}
+
+function getJSONMp3(name)
+{
+ var jsonPath = audioPath+name+".mp3.info.json";
+ if (fs.existsSync(jsonPath))
+ var obj = JSON.parse(fs.readFileSync(jsonPath, 'utf8'));
+ else
+ var obj = 0;
+
+ return obj;
+}
+
+function getJSONMp4(name)
+{
+ var jsonPath = videoPath+name+".info.json";
+ if (fs.existsSync(jsonPath))
+ {
+ var obj = JSON.parse(fs.readFileSync(jsonPath, 'utf8'));
+ return obj;
+ }
+ else return 0;
+}
+
+function getAmountDownloadedMp3(name)
+{
+ var partPath = audioPath+name+".mp3.part";
+ if (fs.existsSync(partPath))
+ {
+ const stats = fs.statSync(partPath);
+ const fileSizeInBytes = stats.size;
+ return fileSizeInBytes;
+ }
+ else
+ return 0;
+}
+
+
+
+function getAmountDownloadedMp4(name)
+{
+ var format = getVideoFormatID(name);
+ var partPath = videoPath+name+".f"+format+".mp4.part";
+ if (fs.existsSync(partPath))
+ {
+ const stats = fs.statSync(partPath);
+ const fileSizeInBytes = stats.size;
+ return fileSizeInBytes;
+ }
+ else
+ return 0;
+}
+
+function getVideoFormatID(name)
+{
+ var jsonPath = videoPath+name+".info.json";
+ if (fs.existsSync(jsonPath))
+ {
+ var obj = JSON.parse(fs.readFileSync(jsonPath, 'utf8'));
+ var format = obj.format.substring(0,3);
+ return format;
+ }
+}
app.post('/tomp3', function(req, res) {
var url = req.body.url;
@@ -81,76 +200,6 @@ app.post('/tomp3', function(req, res) {
res.end("yes");
});
-function getFileSizeMp3(name)
-{
- var jsonPath = audioPath+name+".mp3.info.json";
-
- if (fs.existsSync(jsonPath))
- var obj = JSON.parse(fs.readFileSync(jsonPath, 'utf8'));
- else
- var obj = 0;
-
- return obj.filesize;
-}
-
-function getAmountDownloadedMp3(name)
-{
- var partPath = audioPath+name+".mp3.part";
- if (fs.existsSync(partPath))
- {
- const stats = fs.statSync(partPath);
- const fileSizeInBytes = stats.size;
- return fileSizeInBytes;
- }
- else
- return 0;
-}
-
-function getFileSizeMp4(name)
-{
- var jsonPath = videoPath+name+".info.json";
- var filesize = 0;
- if (fs.existsSync(jsonPath))
- {
- var obj = JSON.parse(fs.readFileSync(jsonPath, 'utf8'));
- var format = obj.format.substring(0,3);
- for (i = 0; i < obj.formats.length; i++)
- {
- if (obj.formats[i].format_id == format)
- {
- filesize = obj.formats[i].filesize;
- }
- }
- }
-
- return filesize;
-}
-
-function getAmountDownloadedMp4(name)
-{
- var format = getVideoFormatID(name);
- var partPath = videoPath+name+".f"+format+".mp4.part";
- if (fs.existsSync(partPath))
- {
- const stats = fs.statSync(partPath);
- const fileSizeInBytes = stats.size;
- return fileSizeInBytes;
- }
- else
- return 0;
-}
-
-function getVideoFormatID(name)
-{
- var jsonPath = videoPath+name+".info.json";
- if (fs.existsSync(jsonPath))
- {
- var obj = JSON.parse(fs.readFileSync(jsonPath, 'utf8'));
- var format = obj.format.substring(0,3);
- return format;
- }
-}
-
app.post('/tomp4', function(req, res) {
var url = req.body.url;
var date = Date.now();
@@ -168,7 +217,8 @@ app.post('/tomp4', function(req, res) {
res.end("yes");
});
-app.post('/mp3fileexists', function(req, res) {
+// gets the status of the mp3 file that's being downloaded
+app.post('/fileStatusMp3', function(req, res) {
var name = req.body.name + "";
var exists = "";
var fullpath = audioPath + name + ".mp3";
@@ -189,7 +239,8 @@ app.post('/mp3fileexists', function(req, res) {
res.end("yes");
});
-app.post('/mp4fileexists', function(req, res) {
+// gets the status of the mp4 file that's being downloaded
+app.post('/fileStatusMp4', function(req, res) {
var name = req.body.name;
var exists = "";
var fullpath = videoPath + name + ".mp4";
@@ -210,6 +261,113 @@ app.post('/mp4fileexists', function(req, res) {
res.end("yes");
});
+// gets all download mp3s
+app.post('/getMp3s', function(req, res) {
+ var mp3s = [];
+ var fullpath = audioPath;
+ var files = fs.readdirSync(audioPath);
+
+ for (var i in files)
+ {
+ var nameLength = path.basename(files[i]).length;
+ var ext = path.basename(files[i]).substring(nameLength-4, nameLength);
+ if (ext == ".mp3")
+ {
+ var jsonobj = getJSONMp3(path.basename(files[i]).substring(0, path.basename(files[i]).length-4));
+ var id = path.basename(files[i]).substring(0, path.basename(files[i]).length-4);
+ var title = jsonobj.title;
+
+ if (title.length > 14) // edits title if it's too long
+ {
+ title = title.substring(0,12) + "...";
+ }
+
+ var thumbnail = jsonobj.thumbnail;
+ var duration = jsonobj.duration;
+ var isaudio = true;
+ var file = new File(id, title, thumbnail, isaudio, duration);
+ mp3s.push(file);
+ }
+ }
+
+ res.send(mp3s);
+ res.end("yes");
+});
+
+// gets all download mp4s
+app.post('/getMp4s', function(req, res) {
+ var mp4s = [];
+ var fullpath = videoPath;
+ var files = fs.readdirSync(videoPath);
+
+ for (var i in files)
+ {
+ var nameLength = path.basename(files[i]).length;
+ var ext = path.basename(files[i]).substring(nameLength-4, nameLength);
+ if (ext == ".mp4")
+ {
+ var jsonobj = getJSONMp4(path.basename(files[i]).substring(0, path.basename(files[i]).length-4));
+ var id = path.basename(files[i]).substring(0, path.basename(files[i]).length-4);
+ var title = jsonobj.title;
+
+ if (title.length > 14) // edits title if it's too long
+ {
+ title = title.substring(0,12) + "...";
+ }
+
+ var thumbnail = jsonobj.thumbnail;
+ var duration = jsonobj.duration;
+ var isaudio = false;
+ var file = new File(id, title, thumbnail, isaudio, duration);
+ mp4s.push(file);
+ }
+ }
+
+ res.send(mp4s);
+ res.end("yes");
+});
+
+// deletes mp3 file
+app.post('/deleteMp3', function(req, res) {
+ var name = req.body.name;
+ var fullpath = audioPath + name + ".mp3";
+ var wasDeleted = false;
+ if (fs.existsSync(fullpath))
+ {
+ fs.unlink(fullpath);
+ wasDeleted = true;
+ res.send(wasDeleted);
+ res.end("yes");
+ }
+ else
+ {
+ wasDeleted = false;
+ res.send(wasDeleted);
+ res.end("yes");
+ }
+});
+
+// deletes mp4 file
+app.post('/deleteMp4', function(req, res) {
+ var name = req.body.name;
+ var fullpath = videoPath + name + ".mp4";
+ var wasDeleted = false;
+ if (fs.existsSync(fullpath))
+ {
+ fs.unlink(fullpath);
+ wasDeleted = true;
+ res.send(wasDeleted);
+ res.end("yes");
+ }
+ else
+ {
+ wasDeleted = false;
+ res.send(wasDeleted);
+ res.end("yes");
+ }
+});
+
+
app.get('/video/:id', function(req , res){
var head;
const path = "video/" + req.params.id + ".mp4";
diff --git a/src/app/app.component.html b/src/app/app.component.html
index 1ede66b..6696f72 100644
--- a/src/app/app.component.html
+++ b/src/app/app.component.html
@@ -1,14 +1,14 @@
-
- |
- |
-
- {{topBarTitle}}
- |
-
-
- |
-
+
+ |
+ |
+
+ {{topBarTitle}}
+ |
+
+
+ |
+
@@ -27,19 +27,66 @@
Only Audio
-
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+ Audio
+
+
+ Your audio files are here
+
+
+ 0;else nomp3s">
+
+
+
+
+
+
+
+
+
+
+
+ Video
+
+
+ Your video files are here
+
+
+ 0;else nomp4s">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index 8b7413e..2dbc0eb 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -1,5 +1,6 @@
import { Component, OnInit } from '@angular/core';
import {PostsService} from './posts.services';
+import {FileCardComponent} from './file-card/file-card.component';
import { Observable } from 'rxjs/Observable';
import {FormControl, Validators} from '@angular/forms';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
@@ -23,6 +24,10 @@ export class AppComponent {
exists: string = "";
topBarTitle: string = "Youtube Downloader";
percentDownloaded: number;
+
+ mp3s: any[] = [];
+ mp4s: any[] = [];
+
constructor(private postsService: PostsService, public snackBar: MatSnackBar) {
this.audioOnly = true;
@@ -35,10 +40,14 @@ export class AppComponent {
this.postsService.path = backendUrl;
this.postsService.startPath = backendUrl;
this.postsService.startPathSSL = backendUrl;
+
+ this.getMp3s();
+ this.getMp4s();
},
error => {
console.log(error);
});
+
}
urlForm = new FormControl('', [Validators.required]);
@@ -67,6 +76,48 @@ export class AppComponent {
});
}
+ getMp3s() {
+ this.postsService.getMp3s().subscribe(result => {
+ var mp3s = result;
+ this.mp3s = mp3s;
+ },
+ error => {
+ console.log(error);
+ });
+ }
+
+ getMp4s() {
+ this.postsService.getMp4s().subscribe(result => {
+ var mp4s = result;
+ this.mp4s = mp4s;
+ },
+ error => {
+ console.log(error);
+ });
+ }
+
+ public removeFromMp3(name: string)
+ {
+ for (var i = 0; i < this.mp3s.length; i++)
+ {
+ if (this.mp3s[i].id == name)
+ {
+ this.mp3s.splice(i,1);
+ }
+ }
+ }
+
+ public removeFromMp4(name: string)
+ {
+ for (var i = 0; i < this.mp4s.length; i++)
+ {
+ if (this.mp4s[i].id == name)
+ {
+ this.mp4s.splice(i,1);
+ }
+ }
+ }
+
ngOnInit() {
}
@@ -167,7 +218,7 @@ export class AppComponent {
return re.test(str);
}
- openSnackBar(message: string, action: string) {
+ public openSnackBar(message: string, action: string) {
this.snackBar.open(message, action, {
duration: 2000,
});
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index cdfeed1..8056bc3 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -1,8 +1,9 @@
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import {MatNativeDateModule, MatRadioModule, MatInputModule, MatButtonModule, MatSidenavModule, MatIconModule, MatListModule,
- MatSnackBarModule, MatCardModule, MatSelectModule, MatToolbarModule, MatCheckboxModule,
- MatProgressBarModule } from '@angular/material';
+ MatSnackBarModule, MatCardModule, MatSelectModule, MatToolbarModule, MatCheckboxModule, MatGridListModule,
+ MatProgressBarModule, MatExpansionModule,
+ MatGridList} from '@angular/material';
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
import { AppComponent } from './app.component';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
@@ -10,10 +11,12 @@ import { HttpModule } from '@angular/http';
import { HttpClientModule } from '@angular/common/http';
import { PostsService } from 'app/posts.services';
import {APP_BASE_HREF} from '@angular/common';
+import { FileCardComponent } from './file-card/file-card.component';
@NgModule({
declarations: [
- AppComponent
+ AppComponent,
+ FileCardComponent
],
imports: [
BrowserModule,
@@ -34,6 +37,8 @@ import {APP_BASE_HREF} from '@angular/common';
MatSidenavModule,
MatIconModule,
MatListModule,
+ MatGridListModule,
+ MatExpansionModule,
MatProgressBarModule
],
providers: [PostsService],
diff --git a/src/app/file-card/file-card.component.css b/src/app/file-card/file-card.component.css
new file mode 100644
index 0000000..87e1049
--- /dev/null
+++ b/src/app/file-card/file-card.component.css
@@ -0,0 +1,33 @@
+.example-card {
+ width: 150px;
+ height: 125px;
+ padding: 0px;
+}
+
+.deleteButton {
+ top:-5px;
+ right:-5px;
+ position:absolute;
+}
+
+/* Coerce the icon container away from display:inline */
+.mat-icon-button .mat-button-wrapper {
+ display: flex;
+ justify-content: center;
+}
+
+.image {
+ max-width:100%;
+ max-height:100%;
+}
+
+.example-full-width-height {
+ width: 100%;
+ height: 100%
+}
+
+.centered {
+ margin: 0 auto;
+ top: 50%;
+ left: 50%;
+}
\ No newline at end of file
diff --git a/src/app/file-card/file-card.component.html b/src/app/file-card/file-card.component.html
new file mode 100644
index 0000000..4579676
--- /dev/null
+++ b/src/app/file-card/file-card.component.html
@@ -0,0 +1,13 @@
+
+
+
+ {{title}}
+
+ ID: {{name}}
+
+
+
+
+
+
+
diff --git a/src/app/file-card/file-card.component.spec.ts b/src/app/file-card/file-card.component.spec.ts
new file mode 100644
index 0000000..722eee2
--- /dev/null
+++ b/src/app/file-card/file-card.component.spec.ts
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { FileCardComponent } from './file-card.component';
+
+describe('FileCardComponent', () => {
+ let component: FileCardComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ FileCardComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(FileCardComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/file-card/file-card.component.ts b/src/app/file-card/file-card.component.ts
new file mode 100644
index 0000000..c0b6c51
--- /dev/null
+++ b/src/app/file-card/file-card.component.ts
@@ -0,0 +1,48 @@
+import { Component, OnInit, Input } from '@angular/core';
+import {PostsService} from '../posts.services';
+import {MatSnackBar} from '@angular/material';
+import {AppComponent} from '../app.component';
+
+@Component({
+ selector: 'app-file-card',
+ templateUrl: './file-card.component.html',
+ styleUrls: ['./file-card.component.css']
+})
+export class FileCardComponent implements OnInit {
+
+ @Input() title:string;
+ @Input() length:string;
+ @Input() name:string;
+ @Input() thumbnailURL: string;
+ @Input() isAudio: boolean = true;
+
+ constructor(private postsService: PostsService, public snackBar: MatSnackBar, private appComponent: AppComponent) { }
+
+ ngOnInit() {
+ }
+
+ deleteFile()
+ {
+ this.postsService.deleteFile(this.name, this.isAudio).subscribe(result => {
+ if (result == true)
+ {
+ this.openSnackBar("Delete success!", "OK.");
+ if (this.isAudio)
+ this.appComponent.removeFromMp3(name);
+ else
+ this.appComponent.removeFromMp4(name);
+ }
+ else
+ {
+ this.openSnackBar("Delete failed!", "OK.");
+ }
+ });
+ }
+
+ public openSnackBar(message: string, action: string) {
+ this.snackBar.open(message, action, {
+ duration: 2000,
+ });
+ }
+
+}
diff --git a/src/app/posts.services.ts b/src/app/posts.services.ts
index 5f31bf5..b1da4fd 100644
--- a/src/app/posts.services.ts
+++ b/src/app/posts.services.ts
@@ -56,12 +56,12 @@ export class PostsService {
}
getFileStatusMp3(name: string): Observable {
- return this.http.post(this.path + "mp3fileexists",{name: name})
+ return this.http.post(this.path + "fileStatusMp3",{name: name})
.map(res => res.json());
}
getFileStatusMp4(name: string): Observable {
- return this.http.post(this.path + "mp4fileexists",{name: name})
+ return this.http.post(this.path + "fileStatusMp4",{name: name})
.map(res => res.json());
}
@@ -70,6 +70,32 @@ export class PostsService {
return this.http.get(window.location.href + "backend/config/default.json")
.map(res => res.json());
}
+
+ deleteFile(name: string, isAudio: boolean)
+ {
+ if (isAudio)
+ {
+ return this.http.post(this.path + "deleteMp3",{name: name})
+ .map(res => res.json());
+ }
+ else
+ {
+ return this.http.post(this.path + "deleteMp4",{name: name})
+ .map(res => res.json());
+ }
+ }
+
+ getMp3s()
+ {
+ return this.http.post(this.path + "getMp3s", {})
+ .map(res => res.json());
+ }
+
+ getMp4s()
+ {
+ return this.http.post(this.path + "getMp4s", {})
+ .map(res => res.json());
+ }
}