├── YAPO
├── __init__.py
├── wsgi.py
├── pagination.py
├── urls.py
└── settings.py
├── videos
├── __init__.py
├── migrations
│ ├── __init__.py
│ ├── 0008_actor_description.py
│ ├── 0020_auto_20160627_1418.py
│ ├── 0033_scene_framerate.py
│ ├── 0009_auto_20160616_2134.py
│ ├── 0010_auto_20160617_1443.py
│ ├── 0012_auto_20160617_1933.py
│ ├── 0015_actor_last_lookup.py
│ ├── 0028_auto_20160710_1627.py
│ ├── 0035_scene_description.py
│ ├── 0031_auto_20160720_0319.py
│ ├── 0036_folder_path_with_ids.py
│ ├── 0018_auto_20160624_1602.py
│ ├── 0024_folder_last_folder_name_only.py
│ ├── 0034_auto_20160730_1623.py
│ ├── 0006_auto_20160615_1729.py
│ ├── 0026_auto_20160707_1349.py
│ ├── 0030_auto_20160717_1622.py
│ ├── 0025_auto_20160704_1756.py
│ ├── 0029_auto_20160716_1538.py
│ ├── 0017_auto_20160624_1551.py
│ ├── 0023_auto_20160630_1736.py
│ ├── 0002_auto_20160613_2041.py
│ ├── 0011_auto_20160617_1453.py
│ ├── 0013_auto_20160621_2129.py
│ ├── 0007_auto_20160615_2009.py
│ ├── 0005_auto_20160615_1534.py
│ ├── 0003_auto_20160613_2043.py
│ ├── 0027_auto_20160708_1403.py
│ ├── 0021_auto_20160627_1454.py
│ ├── 0032_auto_20160727_1734.py
│ ├── 0004_auto_20160613_2048.py
│ ├── 0019_folder.py
│ ├── 0014_auto_20160622_0639.py
│ ├── 0016_auto_20160623_1527.py
│ ├── 0022_auto_20160630_1713.py
│ └── 0001_initial.py
├── templatetags
│ ├── __init__.py
│ └── my_filters.py
├── static
│ ├── js
│ │ └── app
│ │ │ ├── nav-bar
│ │ │ ├── nav-bar.module.js
│ │ │ ├── nav-bar.template.html
│ │ │ └── nav-bar.component.js
│ │ │ ├── settings
│ │ │ ├── settings.module.js
│ │ │ ├── settings.template.html
│ │ │ └── settings.component.js
│ │ │ ├── app.constant.js
│ │ │ ├── pagination
│ │ │ ├── pagination.module.js
│ │ │ ├── pagination.template.html
│ │ │ └── pagination.component.js
│ │ │ ├── core
│ │ │ ├── actor
│ │ │ │ ├── actor.module.js
│ │ │ │ └── actor.service.js
│ │ │ ├── scene
│ │ │ │ ├── scene.module.js
│ │ │ │ └── scene.service.js
│ │ │ ├── website
│ │ │ │ ├── website.module.js
│ │ │ │ └── website.service.js
│ │ │ ├── actor-tag
│ │ │ │ ├── actor-tag.module.js
│ │ │ │ └── acotr-tag.service.js
│ │ │ ├── db-folder
│ │ │ │ ├── db-folder.module.js
│ │ │ │ └── db-folder.service.js
│ │ │ ├── playlist
│ │ │ │ ├── playlist.module.js
│ │ │ │ └── playlist.service.js
│ │ │ ├── scene-tag
│ │ │ │ ├── scene-tag.module.js
│ │ │ │ └── scene-tag.service.js
│ │ │ ├── actor-alias
│ │ │ │ ├── actor-alias.module.js
│ │ │ │ └── actor-alias.service.js
│ │ │ ├── infinite-scroll
│ │ │ │ └── infinite-scroll.config.js
│ │ │ ├── core.module.js
│ │ │ └── checkmark
│ │ │ │ └── checkmark.filter.js
│ │ │ ├── actor-list
│ │ │ ├── actor-list.module.js
│ │ │ ├── actor-list-grid.template.html
│ │ │ ├── actor-list-grid-popover.template.html
│ │ │ ├── actor-list-row.template.html
│ │ │ └── actor-list.template.html
│ │ │ ├── db-folder-tree
│ │ │ ├── db-folder-tree.module.js
│ │ │ └── db-folder-tree.template.html
│ │ │ ├── detail-profile-image
│ │ │ ├── detail-profile-image.module.js
│ │ │ ├── detail-profile-image.component.js
│ │ │ ├── detail-profile-image.template.html
│ │ │ └── modal-content.html
│ │ │ ├── add-items
│ │ │ ├── add-items.module.js
│ │ │ ├── add-items.component.js
│ │ │ └── add-items.template.html
│ │ │ ├── playlist-list
│ │ │ ├── playlist-list.module.js
│ │ │ ├── playlist-list.template.html
│ │ │ └── playlist-list.component.js
│ │ │ ├── scene-list
│ │ │ ├── scene-list.module.js
│ │ │ ├── scene-list-grid-popover.template.html
│ │ │ └── scene-list-grid.template.html
│ │ │ ├── playlist-detail
│ │ │ ├── playlist-detail.module.js
│ │ │ ├── playlist-detail.template.html
│ │ │ └── playlist-detail.component.js
│ │ │ ├── section-list-wrapper
│ │ │ ├── section-list-wrapper.module.js
│ │ │ └── section-wrapper.template.html
│ │ │ ├── scene-detail
│ │ │ └── scene-detail.module.js
│ │ │ ├── website-list
│ │ │ ├── website-list.module.js
│ │ │ ├── website-list.template.html
│ │ │ └── website-list.component.js
│ │ │ ├── actor-tag-list
│ │ │ ├── actor-tag-list.module.js
│ │ │ ├── actor-tag-list.template.html
│ │ │ └── actor-tag-list.component.js
│ │ │ ├── async-typeahead
│ │ │ ├── async-typeahead.module.js
│ │ │ ├── async-typeaead-popup.template.html
│ │ │ └── async-typeahead.template.html
│ │ │ ├── scene-tag-list
│ │ │ ├── scene-tag-list.module.js
│ │ │ ├── scene-tag-list.template.html
│ │ │ └── scene-tag-list.component.js
│ │ │ ├── website-detail
│ │ │ ├── website-detail.module.js
│ │ │ ├── website-detail.template.html
│ │ │ └── website-detail.component.js
│ │ │ ├── actor-tag-detail
│ │ │ ├── actor-tag-detail.module.js
│ │ │ ├── actor-tag-detail.template.html
│ │ │ └── actor-tag-detail.component.js
│ │ │ ├── scene-tag-detail
│ │ │ ├── scene-tag-detail.module.js
│ │ │ ├── scene-tag-detail.component.js
│ │ │ └── scene-tag-detail.template.html
│ │ │ ├── actor-alias-list
│ │ │ ├── actor-alias-list.module.js
│ │ │ ├── actor-alias-list.template.html
│ │ │ └── actor-alias-list.component.js
│ │ │ ├── actor-detail
│ │ │ └── actor-detail.module.js
│ │ │ ├── app.run.js
│ │ │ ├── app.module.js
│ │ │ ├── app.upload.js
│ │ │ ├── app.controller.js
│ │ │ └── app.config.js
│ ├── favicon.ico
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── apple-touch-icon.png
│ ├── mstile-144x144.png
│ ├── mstile-150x150.png
│ ├── android-chrome-192x192.png
│ ├── fonts
│ │ ├── glyphicons-halflings-regular.eot
│ │ ├── glyphicons-halflings-regular.ttf
│ │ ├── glyphicons-halflings-regular.woff
│ │ └── glyphicons-halflings-regular.woff2
│ ├── manifest.json
│ ├── browserconfig.xml
│ ├── partials
│ │ └── popover-templates
│ │ │ ├── popover-playlist.template.html
│ │ │ ├── popover-website.template.html
│ │ │ ├── popover-actor.template.html
│ │ │ └── popover-tag.template.html
│ ├── css
│ │ ├── actors-style.css
│ │ ├── actor-details-style.css
│ │ ├── angular
│ │ │ ├── animations.css
│ │ │ └── styles.css
│ │ ├── nav-bar-style.css
│ │ └── style.css
│ ├── bower
│ │ └── bower.json
│ └── safari-pinned-tab.svg
├── ffmpeg
│ └── ffmpeg.txt
├── tests.py
├── media
│ └── images
│ │ └── actor
│ │ └── Unknown
│ │ └── profile
│ │ └── profile.jpg
├── apps.py
├── const.py
├── templates
│ └── videos
│ │ └── angular
│ │ └── index.html
├── misc_functions.py
├── aux_functions.py
├── urls.py
└── tmdb_search.py
├── README.md
├── requirements.txt
├── manage.py
└── CHANGELOG.md
/YAPO/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/videos/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/videos/migrations/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/videos/templatetags/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/videos/static/js/app/nav-bar/nav-bar.module.js:
--------------------------------------------------------------------------------
1 | angular.module('navBar', []);
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # YAPO
2 | YAPO - Yet Another Porn Organizer
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/videos/ffmpeg/ffmpeg.txt:
--------------------------------------------------------------------------------
1 | On windows ffmpeg.exe and ffprobe.exe go in this folder.
--------------------------------------------------------------------------------
/videos/static/js/app/settings/settings.module.js:
--------------------------------------------------------------------------------
1 | angular.module('settings', []);
--------------------------------------------------------------------------------
/videos/static/js/app/app.constant.js:
--------------------------------------------------------------------------------
1 | var app = angular.module('yapoApp', []);
2 |
3 |
--------------------------------------------------------------------------------
/videos/static/js/app/pagination/pagination.module.js:
--------------------------------------------------------------------------------
1 | angular.module('pagination', []);
--------------------------------------------------------------------------------
/videos/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/videos/static/js/app/core/actor/actor.module.js:
--------------------------------------------------------------------------------
1 | angular.module('core.actor', ['ngResource']);
--------------------------------------------------------------------------------
/videos/static/js/app/core/scene/scene.module.js:
--------------------------------------------------------------------------------
1 | angular.module('core.scene', ['ngResource']);
--------------------------------------------------------------------------------
/videos/static/js/app/actor-list/actor-list.module.js:
--------------------------------------------------------------------------------
1 | angular.module('actorList', ['core.actor']);
--------------------------------------------------------------------------------
/videos/static/js/app/core/website/website.module.js:
--------------------------------------------------------------------------------
1 | angular.module('core.website', ['ngResource']);
--------------------------------------------------------------------------------
/videos/static/js/app/core/actor-tag/actor-tag.module.js:
--------------------------------------------------------------------------------
1 | angular.module('core.actorTag', ['ngResource']);
--------------------------------------------------------------------------------
/videos/static/js/app/core/db-folder/db-folder.module.js:
--------------------------------------------------------------------------------
1 | angular.module('core.dbFolder', ['ngResource']);
--------------------------------------------------------------------------------
/videos/static/js/app/core/playlist/playlist.module.js:
--------------------------------------------------------------------------------
1 | angular.module('core.playlist', ['ngResource']);
--------------------------------------------------------------------------------
/videos/static/js/app/core/scene-tag/scene-tag.module.js:
--------------------------------------------------------------------------------
1 | angular.module('core.sceneTag', ['ngResource']);
--------------------------------------------------------------------------------
/videos/static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/curtwagner1984/YAPO/HEAD/videos/static/favicon.ico
--------------------------------------------------------------------------------
/videos/static/js/app/core/actor-alias/actor-alias.module.js:
--------------------------------------------------------------------------------
1 | angular.module('core.actorAlias', ['ngResource']);
--------------------------------------------------------------------------------
/videos/static/js/app/db-folder-tree/db-folder-tree.module.js:
--------------------------------------------------------------------------------
1 | angular.module('dbFolderTree', ['core.dbFolder']);
--------------------------------------------------------------------------------
/videos/static/js/app/detail-profile-image/detail-profile-image.module.js:
--------------------------------------------------------------------------------
1 | angular.module('detailProfileImage', []);
--------------------------------------------------------------------------------
/videos/static/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/curtwagner1984/YAPO/HEAD/videos/static/favicon-16x16.png
--------------------------------------------------------------------------------
/videos/static/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/curtwagner1984/YAPO/HEAD/videos/static/favicon-32x32.png
--------------------------------------------------------------------------------
/videos/static/js/app/add-items/add-items.module.js:
--------------------------------------------------------------------------------
1 | // Define the `phoneList` module
2 | angular.module('addItems', []);
--------------------------------------------------------------------------------
/videos/static/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/curtwagner1984/YAPO/HEAD/videos/static/apple-touch-icon.png
--------------------------------------------------------------------------------
/videos/static/mstile-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/curtwagner1984/YAPO/HEAD/videos/static/mstile-144x144.png
--------------------------------------------------------------------------------
/videos/static/mstile-150x150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/curtwagner1984/YAPO/HEAD/videos/static/mstile-150x150.png
--------------------------------------------------------------------------------
/videos/static/js/app/playlist-list/playlist-list.module.js:
--------------------------------------------------------------------------------
1 | // Define the `phoneList` module
2 | angular.module('playlistList', []);
--------------------------------------------------------------------------------
/videos/static/js/app/scene-list/scene-list.module.js:
--------------------------------------------------------------------------------
1 | // Define the `phoneList` module
2 | angular.module('sceneList', ['core.scene']);
--------------------------------------------------------------------------------
/videos/static/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/curtwagner1984/YAPO/HEAD/videos/static/android-chrome-192x192.png
--------------------------------------------------------------------------------
/videos/static/js/app/playlist-detail/playlist-detail.module.js:
--------------------------------------------------------------------------------
1 | // Define the `phoneList` module
2 | angular.module('playlistDetail', []);
--------------------------------------------------------------------------------
/videos/static/js/app/section-list-wrapper/section-list-wrapper.module.js:
--------------------------------------------------------------------------------
1 | angular.module('sectionListWrapper', ['core.actor', 'actorList']);
--------------------------------------------------------------------------------
/videos/static/js/app/core/infinite-scroll/infinite-scroll.config.js:
--------------------------------------------------------------------------------
1 | angular.module('infinite-scroll').value('THROTTLE_MILLISECONDS', 10000);
--------------------------------------------------------------------------------
/videos/static/js/app/scene-detail/scene-detail.module.js:
--------------------------------------------------------------------------------
1 | // Define the `phoneList` module
2 | angular.module('sceneDetail', ['core.scene']);
--------------------------------------------------------------------------------
/videos/static/js/app/website-list/website-list.module.js:
--------------------------------------------------------------------------------
1 | // Define the `phoneList` module
2 | angular.module('websiteList', ['core.website']);
--------------------------------------------------------------------------------
/videos/static/js/app/actor-tag-list/actor-tag-list.module.js:
--------------------------------------------------------------------------------
1 | // Define the `phoneList` module
2 | angular.module('actorTagList', ['core.actorTag']);
--------------------------------------------------------------------------------
/videos/static/js/app/async-typeahead/async-typeahead.module.js:
--------------------------------------------------------------------------------
1 | angular.module('asyncTypeahead', [
2 | 'xeditable',
3 | 'ui.bootstrap'
4 | ]);
--------------------------------------------------------------------------------
/videos/static/js/app/scene-tag-list/scene-tag-list.module.js:
--------------------------------------------------------------------------------
1 | // Define the `phoneList` module
2 | angular.module('sceneTagList', ['core.sceneTag']);
--------------------------------------------------------------------------------
/videos/static/js/app/website-detail/website-detail.module.js:
--------------------------------------------------------------------------------
1 | // Define the `phoneList` module
2 | angular.module('websiteDetail', ['core.website']);
--------------------------------------------------------------------------------
/videos/static/js/app/actor-tag-detail/actor-tag-detail.module.js:
--------------------------------------------------------------------------------
1 | angular.module('actorTagDetail', [
2 | 'ngRoute',
3 | 'core.actor'
4 |
5 | ]);
--------------------------------------------------------------------------------
/videos/static/js/app/scene-tag-detail/scene-tag-detail.module.js:
--------------------------------------------------------------------------------
1 | // Define the `phoneList` module
2 | angular.module('sceneTagDetail', ['core.sceneTag']);
--------------------------------------------------------------------------------
/videos/static/js/app/actor-alias-list/actor-alias-list.module.js:
--------------------------------------------------------------------------------
1 | // Define the `phoneList` module
2 | angular.module('actorAliasList', ['core.actorAlias']);
--------------------------------------------------------------------------------
/videos/media/images/actor/Unknown/profile/profile.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/curtwagner1984/YAPO/HEAD/videos/media/images/actor/Unknown/profile/profile.jpg
--------------------------------------------------------------------------------
/videos/static/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/curtwagner1984/YAPO/HEAD/videos/static/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/videos/static/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/curtwagner1984/YAPO/HEAD/videos/static/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/videos/static/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/curtwagner1984/YAPO/HEAD/videos/static/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/videos/static/fonts/glyphicons-halflings-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/curtwagner1984/YAPO/HEAD/videos/static/fonts/glyphicons-halflings-regular.woff2
--------------------------------------------------------------------------------
/videos/static/js/app/actor-detail/actor-detail.module.js:
--------------------------------------------------------------------------------
1 | angular.module('actorDetail', [
2 | 'ngRoute',
3 | 'core.actor',
4 | 'core.actorAlias',
5 |
6 | ]);
--------------------------------------------------------------------------------
/videos/templatetags/my_filters.py:
--------------------------------------------------------------------------------
1 | from django import template
2 |
3 | register = template.Library()
4 |
5 |
6 | @register.filter(name='times')
7 | def times(number):
8 | return range(number)
9 |
--------------------------------------------------------------------------------
/videos/static/js/app/app.run.js:
--------------------------------------------------------------------------------
1 | var app = angular.module('yapoApp', ['xeditable','$rootScope']);
2 |
3 |
4 | app.run(function (editableOptions) {
5 | editableOptions.theme = 'bs3';
6 | });
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | python_dateutil==2.5.3
2 | Django==1.9.6
3 | djangorestframework==3.4.1
4 | django_mptt==0.8.5
5 | django_autocomplete_light==3.1.6
6 | requests==2.5.3
7 | tmdbsimple==1.3.0
8 | beautifulsoup4==4.5.0
9 |
10 |
--------------------------------------------------------------------------------
/videos/static/js/app/async-typeahead/async-typeaead-popup.template.html:
--------------------------------------------------------------------------------
1 |
3 |
5 |
6 |
--------------------------------------------------------------------------------
/videos/static/js/app/core/core.module.js:
--------------------------------------------------------------------------------
1 | angular.module('core', [
2 | 'core.actor',
3 | 'core.scene',
4 | 'core.actorTag',
5 | 'core.sceneTag',
6 | 'core.actorAlias',
7 | 'core.dbFolder',
8 | 'core.website',
9 | 'core.playlist'
10 | ]);
--------------------------------------------------------------------------------
/videos/static/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "YAPO",
3 | "icons": [
4 | {
5 | "src": "\/android-chrome-192x192.png",
6 | "sizes": "192x192",
7 | "type": "image\/png"
8 | }
9 | ],
10 | "theme_color": "#ffffff",
11 | "display": "standalone"
12 | }
13 |
--------------------------------------------------------------------------------
/videos/static/browserconfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | #9f00a7
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/videos/apps.py:
--------------------------------------------------------------------------------
1 | from __future__ import unicode_literals
2 | import json
3 | # from videos import const, aux_functions
4 | from django.apps import AppConfig
5 | import datetime
6 | # from videos.models import ActorTag, SceneTag
7 |
8 |
9 | class VideosConfig(AppConfig):
10 | name = 'videos'
11 |
--------------------------------------------------------------------------------
/videos/static/js/app/core/checkmark/checkmark.filter.js:
--------------------------------------------------------------------------------
1 | angular.module('core').filter('checkmark', function () {
2 | return function (input) {
3 | if (input === 'M') {
4 | return '\u2642'
5 | } else {
6 | return '\u2640'
7 |
8 | }
9 |
10 | };
11 | });
--------------------------------------------------------------------------------
/videos/const.py:
--------------------------------------------------------------------------------
1 |
2 |
3 | UNKNOWN_PERSON_IMAGE_PATH = 'media/images/actor/Unknown/profile/profile.jpg'
4 | MEDIA_PATH = 'videos/media/'
5 | TEMP_PATH = 'videos/ffmpeg/temp/'
6 | VLC_PATH = ""
7 | LAST_ALL_SCENE_TAG = None
8 | SETTINGS_VERSION = 3
9 |
10 | if __name__ == "__main__":
11 | print("this is main")
12 |
--------------------------------------------------------------------------------
/videos/static/js/app/pagination/pagination.template.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/videos/static/js/app/playlist-detail/playlist-detail.template.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
--------------------------------------------------------------------------------
/videos/static/partials/popover-templates/popover-playlist.template.html:
--------------------------------------------------------------------------------
1 |
2 |
Add playlist
3 |
10 |
--------------------------------------------------------------------------------
/videos/static/partials/popover-templates/popover-website.template.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/videos/static/partials/popover-templates/popover-actor.template.html:
--------------------------------------------------------------------------------
1 |
4 |
5 |
--------------------------------------------------------------------------------
/videos/static/partials/popover-templates/popover-tag.template.html:
--------------------------------------------------------------------------------
1 |
4 |
5 |
--------------------------------------------------------------------------------
/YAPO/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for YAPO project.
3 |
4 | It exposes the WSGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/1.9/howto/deployment/wsgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.wsgi import get_wsgi_application
13 |
14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "YAPO.settings")
15 |
16 | application = get_wsgi_application()
17 |
--------------------------------------------------------------------------------
/videos/templates/videos/angular/index.html:
--------------------------------------------------------------------------------
1 | {% load staticfiles %}
2 |
3 |
4 |
5 |
6 |
7 | {% include 'videos/angular/index-head.html' %}
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | {% verbatim %}
20 |
21 | {% endverbatim %}
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/videos/static/css/actors-style.css:
--------------------------------------------------------------------------------
1 |
2 | #actor-male {
3 | background: blue;
4 | width: 200px;
5 | float: left;
6 | }
7 |
8 | /*#actor-female {*/
9 | /*background: red;*/
10 | /*width: 200px;*/
11 | /*float: left;*/
12 | /*}*/
13 |
14 | #actor-trans {
15 | background: yellow;
16 | width: 200px;
17 | float: left;
18 | }
19 |
20 | #actor-gender-none {
21 | width: 200px;
22 | float: left;
23 | }
24 |
--------------------------------------------------------------------------------
/videos/migrations/0008_actor_description.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-06-16 11:58
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('videos', '0007_auto_20160615_2009'),
12 | ]
13 |
14 | operations = [
15 | migrations.AddField(
16 | model_name='actor',
17 | name='description',
18 | field=models.TextField(default=''),
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/videos/migrations/0020_auto_20160627_1418.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-06-27 11:18
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('videos', '0019_folder'),
12 | ]
13 |
14 | operations = [
15 | migrations.AlterField(
16 | model_name='scene',
17 | name='path_to_file',
18 | field=models.CharField(max_length=500, unique=True),
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/videos/migrations/0033_scene_framerate.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-07-27 15:39
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('videos', '0032_auto_20160727_1734'),
12 | ]
13 |
14 | operations = [
15 | migrations.AddField(
16 | model_name='scene',
17 | name='framerate',
18 | field=models.FloatField(blank=True, null=True),
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/videos/migrations/0009_auto_20160616_2134.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-06-16 18:34
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('videos', '0008_actor_description'),
12 | ]
13 |
14 | operations = [
15 | migrations.AlterField(
16 | model_name='actor',
17 | name='description',
18 | field=models.TextField(blank=True, default=''),
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/videos/migrations/0010_auto_20160617_1443.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-06-17 11:43
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('videos', '0009_auto_20160616_2134'),
12 | ]
13 |
14 | operations = [
15 | migrations.AlterField(
16 | model_name='actor',
17 | name='date_of_birth',
18 | field=models.DateField(blank=True, null=True),
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/videos/migrations/0012_auto_20160617_1933.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-06-17 16:33
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('videos', '0011_auto_20160617_1453'),
12 | ]
13 |
14 | operations = [
15 | migrations.AlterField(
16 | model_name='actortag',
17 | name='name',
18 | field=models.CharField(max_length=50, unique=True),
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/videos/migrations/0015_actor_last_lookup.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-06-22 07:56
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('videos', '0014_auto_20160622_0639'),
12 | ]
13 |
14 | operations = [
15 | migrations.AddField(
16 | model_name='actor',
17 | name='last_lookup',
18 | field=models.DateTimeField(blank=True, null=True),
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/videos/migrations/0028_auto_20160710_1627.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-07-10 13:27
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('videos', '0027_auto_20160708_1403'),
12 | ]
13 |
14 | operations = [
15 | migrations.AlterField(
16 | model_name='actor',
17 | name='extra_text',
18 | field=models.TextField(blank=True, default=''),
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/videos/migrations/0035_scene_description.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-07-31 18:38
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('videos', '0034_auto_20160730_1623'),
12 | ]
13 |
14 | operations = [
15 | migrations.AddField(
16 | model_name='scene',
17 | name='description',
18 | field=models.TextField(blank=True, default=''),
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/videos/migrations/0031_auto_20160720_0319.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-07-20 00:19
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('videos', '0030_auto_20160717_1622'),
12 | ]
13 |
14 | operations = [
15 | migrations.AlterField(
16 | model_name='actor',
17 | name='tattoos',
18 | field=models.CharField(blank=True, max_length=600, null=True),
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/videos/migrations/0036_folder_path_with_ids.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-07-31 18:46
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('videos', '0035_scene_description'),
12 | ]
13 |
14 | operations = [
15 | migrations.AddField(
16 | model_name='folder',
17 | name='path_with_ids',
18 | field=models.CharField(blank=True, max_length=900, null=True),
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/videos/migrations/0018_auto_20160624_1602.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-06-24 13:02
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('videos', '0017_auto_20160624_1551'),
12 | ]
13 |
14 | operations = [
15 | migrations.AlterField(
16 | model_name='scene',
17 | name='scene_tags',
18 | field=models.ManyToManyField(blank=True, null=True, to='videos.SceneTag'),
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/videos/migrations/0024_folder_last_folder_name_only.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-06-30 15:36
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('videos', '0023_auto_20160630_1736'),
12 | ]
13 |
14 | operations = [
15 | migrations.AddField(
16 | model_name='folder',
17 | name='last_folder_name_only',
18 | field=models.CharField(max_length=100, null=True),
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import os
3 | import sys
4 | from videos import *
5 | import YAPO.settings
6 |
7 | if __name__ == "__main__":
8 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "YAPO.settings")
9 |
10 | from videos import apps
11 | from YAPO import pagination
12 |
13 | a = apps
14 | a = pagination
15 |
16 | print("Static files dir is: {}".format(YAPO.settings.STATIC_ROOT))
17 | print("Media files dir is: {}".format(YAPO.settings.MEDIA_ROOT))
18 |
19 | from django.core.management import execute_from_command_line
20 |
21 | execute_from_command_line(sys.argv)
22 |
--------------------------------------------------------------------------------
/videos/migrations/0034_auto_20160730_1623.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-07-30 13:23
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('videos', '0033_scene_framerate'),
12 | ]
13 |
14 | operations = [
15 | migrations.AlterField(
16 | model_name='folder',
17 | name='scenes',
18 | field=models.ManyToManyField(null=True, related_name='folders_in_tree', to='videos.Scene'),
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/videos/migrations/0006_auto_20160615_1729.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-06-15 14:29
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('videos', '0005_auto_20160615_1534'),
12 | ]
13 |
14 | operations = [
15 | migrations.AlterField(
16 | model_name='actor',
17 | name='gender',
18 | field=models.CharField(choices=[('M', 'Male'), ('F', 'Female'), ('T', 'Transgender')], max_length=15),
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/videos/migrations/0026_auto_20160707_1349.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-07-07 10:49
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('videos', '0025_auto_20160704_1756'),
12 | ]
13 |
14 | operations = [
15 | migrations.AlterField(
16 | model_name='actor',
17 | name='actor_tags',
18 | field=models.ManyToManyField(blank=True, null=True, related_name='actors', to='videos.ActorTag'),
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/videos/static/js/app/core/db-folder/db-folder.service.js:
--------------------------------------------------------------------------------
1 | angular.module('core.dbFolder').factory('DbFolder', ['$resource', 'helperService',
2 | function ($resource, helperService) {
3 | return $resource('api/folder/:dbFolderId/', {}, {
4 | query: {
5 | method: 'GET',
6 | isArray: true,
7 | transformResponse: function (data, headers) {
8 | console.log("we are in db-folder service");
9 |
10 | return helperService.packageDataAndHeaders(data, headers);
11 | }
12 |
13 | }
14 | });
15 | }
16 | ]);
--------------------------------------------------------------------------------
/videos/migrations/0030_auto_20160717_1622.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-07-17 13:22
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('videos', '0029_auto_20160716_1538'),
12 | ]
13 |
14 | operations = [
15 | migrations.AlterField(
16 | model_name='website',
17 | name='scene_tags',
18 | field=models.ManyToManyField(blank=True, null=True, related_name='websites', to='videos.SceneTag'),
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/videos/migrations/0025_auto_20160704_1756.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-07-04 14:56
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('videos', '0024_folder_last_folder_name_only'),
12 | ]
13 |
14 | operations = [
15 | migrations.AlterField(
16 | model_name='actor',
17 | name='actor_aliases',
18 | field=models.ManyToManyField(blank=True, null=True, related_name='actors', to='videos.ActorAlias'),
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/videos/migrations/0029_auto_20160716_1538.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-07-16 12:38
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('videos', '0028_auto_20160710_1627'),
12 | ]
13 |
14 | operations = [
15 | migrations.AlterField(
16 | model_name='actor',
17 | name='gender',
18 | field=models.CharField(blank=True, choices=[('M', 'Male'), ('F', 'Female'), ('T', 'Transgender')], max_length=15),
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/videos/static/js/app/detail-profile-image/detail-profile-image.component.js:
--------------------------------------------------------------------------------
1 | // Register `phoneList` component, along with its associated controller and template
2 | angular.module('detailProfileImage').component('detailProfileImage', {
3 | // Note: The URL is relative to our `index.html` file
4 | templateUrl: 'static/js/app/detail-profile-image/detail-profile-image.template.html',
5 | bindings: {
6 | pk: '=',
7 | actor: '='
8 | },
9 | controller: ['$scope',
10 | function DetailProfileImageController($scope) {
11 | $scope.modelContent = this.actor;
12 | }]
13 | });
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/videos/static/js/app/async-typeahead/async-typeahead.template.html:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 | No Results Found
15 |
--------------------------------------------------------------------------------
/videos/static/js/app/core/actor-alias/actor-alias.service.js:
--------------------------------------------------------------------------------
1 | angular.module('core.actorAlias').factory('ActorAlias', ['$resource', 'helperService',
2 | function ($resource, helperService) {
3 | return $resource('/api/actor-alias/:actorAliasId/', {}, {
4 | query: {
5 | method: 'GET',
6 | isArray: true,
7 | transformResponse: function (data, headers) {
8 |
9 | return helperService.packageDataAndHeaders(data, headers);
10 | }
11 |
12 | },
13 | update: {
14 | method: 'PUT'
15 | }
16 |
17 | });
18 | }
19 | ]);
--------------------------------------------------------------------------------
/videos/static/js/app/core/actor-tag/acotr-tag.service.js:
--------------------------------------------------------------------------------
1 | angular.module('core.actorTag').factory('ActorTag', ['$resource', 'helperService',
2 | function ($resource, helperService) {
3 | return $resource('api/actor-tag/:actorTagId/', {}, {
4 | query: {
5 | method: 'GET',
6 | isArray: true,
7 | transformResponse: function (data, headers) {
8 |
9 | return helperService.packageDataAndHeaders(data, headers);
10 | }
11 |
12 | }, update: {
13 | method: 'PUT'
14 | },
15 | patch: {
16 | method: 'PATCH'
17 | }
18 | });
19 | }
20 | ]);
--------------------------------------------------------------------------------
/videos/migrations/0017_auto_20160624_1551.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-06-24 12:51
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('videos', '0016_auto_20160623_1527'),
12 | ]
13 |
14 | operations = [
15 | migrations.RemoveField(
16 | model_name='actor',
17 | name='scenes',
18 | ),
19 | migrations.AddField(
20 | model_name='scene',
21 | name='actors',
22 | field=models.ManyToManyField(blank=True, null=True, to='videos.Actor'),
23 | ),
24 | ]
25 |
--------------------------------------------------------------------------------
/videos/static/js/app/core/website/website.service.js:
--------------------------------------------------------------------------------
1 | angular.module('core.website').factory('Website', ['$resource', 'helperService',
2 | function ($resource, helperService) {
3 | return $resource('api/website/:websiteId/', {}, {
4 | query: {
5 | method: 'GET',
6 | isArray: true,
7 | transformResponse: function (data, headers) {
8 |
9 | return helperService.packageDataAndHeaders(data, headers);
10 | }
11 |
12 | },
13 | update: {
14 | method: 'PUT'
15 | },
16 | patch: {
17 | method: 'PATCH'
18 | }
19 | });
20 | }
21 | ]);
--------------------------------------------------------------------------------
/videos/static/js/app/playlist-list/playlist-list.template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
20 |
21 |
--------------------------------------------------------------------------------
/videos/static/js/app/core/actor/actor.service.js:
--------------------------------------------------------------------------------
1 | angular.module('core.actor').factory('Actor', ['$resource', 'helperService',
2 | function ($resource, helperService) {
3 | return $resource('api/actor/:actorId/', {}, {
4 | query: {
5 | method: 'GET',
6 | isArray: true,
7 | transformResponse: function (data, headers) {
8 |
9 | return helperService.packageDataAndHeaders(data, headers);
10 | }
11 |
12 | },
13 |
14 | update: {
15 | method: 'PUT'
16 | },
17 | patch: {
18 | method: 'PATCH'
19 | }
20 |
21 |
22 | });
23 | }
24 | ]);
--------------------------------------------------------------------------------
/videos/static/js/app/core/scene-tag/scene-tag.service.js:
--------------------------------------------------------------------------------
1 | angular.module('core.sceneTag').factory('SceneTag', ['$resource', 'helperService',
2 | function ($resource, helperService) {
3 | return $resource('api/scene-tag/:sceneTagId/', {}, {
4 | query: {
5 | method: 'GET',
6 | isArray: true,
7 | transformResponse: function (data, headers) {
8 |
9 | return helperService.packageDataAndHeaders(data, headers);
10 | }
11 |
12 | },
13 | update: {
14 | method: 'PUT'
15 | },
16 | patch: {
17 | method: 'PATCH'
18 | }
19 | });
20 | }
21 | ]);
--------------------------------------------------------------------------------
/videos/static/js/app/core/scene/scene.service.js:
--------------------------------------------------------------------------------
1 | angular.module('core.scene').factory('Scene', ['$resource', 'helperService',
2 | function ($resource, helperService) {
3 | return $resource('api/scene/:sceneId/', {}, {
4 | query: {
5 | method: 'GET',
6 | isArray: true,
7 | transformResponse: function (data, headers) {
8 |
9 | return helperService.packageDataAndHeaders(data, headers);
10 | }
11 |
12 | },
13 |
14 | update: {
15 | method: 'PUT'
16 | },
17 |
18 | patch: {
19 | method: 'PATCH'
20 | }
21 |
22 |
23 | });
24 | }
25 | ]);
--------------------------------------------------------------------------------
/videos/static/js/app/scene-list/scene-list-grid-popover.template.html:
--------------------------------------------------------------------------------
1 |
2 | {{ scene.name }}
3 |
4 |
5 | Websites:
6 | {{ site.name }}{{$last ? '' : ', '}}
7 |
8 |
9 |
10 |
11 | Tags:
12 | {{ tag.name }}{{$last ? '' : ', '}}
13 |
14 |
15 |
16 | Actors:
17 | {{ actor.name }}{{$last ? '' : ', '}}
18 |
19 |
20 |
21 | Path: {{ scene.path_to_file }}
22 |
--------------------------------------------------------------------------------
/videos/migrations/0023_auto_20160630_1736.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-06-30 14:36
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('videos', '0022_auto_20160630_1713'),
12 | ]
13 |
14 | operations = [
15 | migrations.RemoveField(
16 | model_name='actor',
17 | name='actor_aliases',
18 | ),
19 | migrations.AddField(
20 | model_name='actor',
21 | name='actor_aliases',
22 | field=models.ManyToManyField(blank=True, null=True, to='videos.ActorAlias'),
23 | ),
24 | ]
25 |
--------------------------------------------------------------------------------
/videos/static/js/app/core/playlist/playlist.service.js:
--------------------------------------------------------------------------------
1 | angular.module('core.playlist').factory('Playlist', ['$resource', 'helperService',
2 | function ($resource, helperService) {
3 | return $resource('api/playlist/:playlistId/', {}, {
4 | query: {
5 | method: 'GET',
6 | isArray: true,
7 | transformResponse: function (data, headers) {
8 |
9 | return helperService.packageDataAndHeaders(data, headers);
10 | }
11 |
12 | },
13 |
14 | update: {
15 | method: 'PUT'
16 | },
17 |
18 | patch: {
19 | method: 'PATCH'
20 | }
21 |
22 |
23 | });
24 | }
25 | ]);
--------------------------------------------------------------------------------
/videos/static/css/actor-details-style.css:
--------------------------------------------------------------------------------
1 | .image-and-text {
2 | text-align: justify;
3 | width: 256px;
4 | position: absolute;
5 | right: 20px;
6 | margin: 20px;
7 |
8 | }
9 |
10 | .image-and-text img {
11 | display: block;
12 | border: 25px gray;
13 | margin-right: 10px;
14 |
15 | }
16 |
17 | .headline {
18 | text-align: center;
19 | }
20 |
21 | #wrapper {
22 | width: 1080px;
23 | margin: 0 auto;
24 | }
25 |
26 | #leftcolumn, #rightcolumn {
27 | border: 1px solid white;
28 | float: left;
29 | min-height: 450px;
30 | color: black;
31 | }
32 |
33 | #leftcolumn {
34 | width: 600px;
35 |
36 | /* # background-color: #111; */
37 | }
38 |
39 | #rightcolumn {
40 |
41 | width: 300px;
42 |
43 | /* # background-color: #777; */
44 | }
--------------------------------------------------------------------------------
/videos/static/js/app/website-list/website-list.template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
--------------------------------------------------------------------------------
/videos/static/js/app/scene-list/scene-list-grid.template.html:
--------------------------------------------------------------------------------
1 |
2 |
20 |
21 |
--------------------------------------------------------------------------------
/videos/static/bower/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "yapo",
3 | "homepage": "https://github.com/curtwagner1984/YAPO",
4 | "authors": [
5 | "Curt Wagner "
6 | ],
7 | "description": "Yet Another Porn Organizer",
8 | "main": "app.config.js",
9 | "license": "MIT",
10 | "private": true,
11 | "ignore": [
12 | "**/.*",
13 | "node_modules",
14 | "bower_components",
15 | "test",
16 | "tests"
17 | ],
18 | "dependencies": {
19 | "jquery": "^3.1.0",
20 | "bootstrap": "^3.3.7",
21 | "angular": "^1.5.8",
22 | "angular-resource": "^1.5.8",
23 | "angular-route": "^1.5.8",
24 | "angular-animate": "^1.5.8",
25 | "angular-xeditable": "^0.2.0",
26 | "ngstorage": "^0.3.11",
27 | "angular-bootstrap": "^2.0.1",
28 | "angular-img-cropper": "^1.1.0"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/videos/static/js/app/actor-list/actor-list-grid.template.html:
--------------------------------------------------------------------------------
1 |
2 |
20 |
21 |
--------------------------------------------------------------------------------
/videos/static/js/app/actor-list/actor-list-grid-popover.template.html:
--------------------------------------------------------------------------------
1 |
2 | {{ actor.name }}
3 |
4 |
5 |
6 | -
7 | Rating {{ actor.rating }}
8 |
9 | -
10 | Ethnicity {{ actor.ethnicity }}
11 |
12 | -
13 | Weight {{ actor.weight }} Kg
14 |
15 | -
16 | Height {{ actor.height }} cm
17 |
18 | -
19 | Measurements {{ actor.measurements }}
20 |
21 | -
22 | Country Of Origin {{ actor.country_of_origin }}
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/videos/static/js/app/actor-tag-detail/actor-tag-detail.template.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
12 |
13 | This tag is used {{$ctrl.actorTag.actors.length}} times
14 |
15 |
16 |
17 |
18 |
19 |
20 | {{$ctrl.actorTag.description}}
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/videos/static/js/app/detail-profile-image/detail-profile-image.template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
![]()
9 |
10 |
11 |
12 |
18 |
Selection from a modal: {{ selected }}
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/videos/static/safari-pinned-tab.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
19 |
--------------------------------------------------------------------------------
/videos/static/js/app/actor-alias-list/actor-alias-list.template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
23 |
--------------------------------------------------------------------------------
/videos/migrations/0002_auto_20160613_2041.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-06-13 17:41
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('videos', '0001_initial'),
12 | ]
13 |
14 | operations = [
15 | migrations.AlterField(
16 | model_name='scene',
17 | name='date_fav',
18 | field=models.DateTimeField(blank=True, null=True),
19 | ),
20 | migrations.AlterField(
21 | model_name='scene',
22 | name='date_runner_up',
23 | field=models.DateTimeField(blank=True, null=True),
24 | ),
25 | migrations.AlterField(
26 | model_name='scene',
27 | name='thumbnail',
28 | field=models.CharField(max_length=500, null=True),
29 | ),
30 | ]
31 |
--------------------------------------------------------------------------------
/videos/migrations/0011_auto_20160617_1453.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-06-17 11:53
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('videos', '0010_auto_20160617_1443'),
12 | ]
13 |
14 | operations = [
15 | migrations.AddField(
16 | model_name='actor',
17 | name='imdb_id',
18 | field=models.CharField(blank=True, max_length=25, null=True),
19 | ),
20 | migrations.AddField(
21 | model_name='actor',
22 | name='official_pages',
23 | field=models.TextField(blank=True, default=''),
24 | ),
25 | migrations.AddField(
26 | model_name='actor',
27 | name='tmdb_id',
28 | field=models.CharField(blank=True, max_length=25, null=True),
29 | ),
30 | ]
31 |
--------------------------------------------------------------------------------
/videos/static/js/app/app.module.js:
--------------------------------------------------------------------------------
1 | // Define the `phonecatApp` module
2 | var app = angular.module('yapoApp', [
3 | // ...which depends on the `phoneList` module
4 | 'ngRoute',
5 | // 'djangoRESTResources',
6 | 'xeditable',
7 | 'actorList',
8 | 'actorDetail',
9 | 'sceneList',
10 | 'sceneDetail',
11 | 'actorTagList',
12 | 'actorTagDetail',
13 | 'sceneTagList',
14 | 'sceneTagDetail',
15 | 'websiteList',
16 | 'websiteDetail',
17 | 'dbFolderTree',
18 | // 'ui.tree',
19 | 'actorAliasList',
20 | 'ui.bootstrap',
21 | 'ngAnimate',
22 | 'angular-img-cropper',
23 | 'detailProfileImage',
24 | 'fileUpload',
25 | 'helper',
26 | 'asyncTypeahead',
27 | 'sectionListWrapper',
28 | 'navBar',
29 | 'pager',
30 | 'scopeWatch',
31 | 'pagination',
32 | 'ngStorage',
33 | // 'mgcrea.ngStrap',
34 | 'core',
35 | 'addItems',
36 | 'settings',
37 | 'playlistList',
38 | 'playlistDetail'
39 |
40 |
41 | ]);
--------------------------------------------------------------------------------
/videos/migrations/0013_auto_20160621_2129.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-06-21 18:29
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('videos', '0012_auto_20160617_1933'),
12 | ]
13 |
14 | operations = [
15 | migrations.RemoveField(
16 | model_name='actortag',
17 | name='actors',
18 | ),
19 | migrations.RemoveField(
20 | model_name='scenetag',
21 | name='scenes',
22 | ),
23 | migrations.AddField(
24 | model_name='actor',
25 | name='actor_tags',
26 | field=models.ManyToManyField(null=True, to='videos.ActorTag'),
27 | ),
28 | migrations.AddField(
29 | model_name='scene',
30 | name='scene_tags',
31 | field=models.ManyToManyField(null=True, to='videos.SceneTag'),
32 | ),
33 | ]
34 |
--------------------------------------------------------------------------------
/videos/migrations/0007_auto_20160615_2009.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-06-15 17:09
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 | import django.db.models.deletion
7 |
8 |
9 | class Migration(migrations.Migration):
10 |
11 | dependencies = [
12 | ('videos', '0006_auto_20160615_1729'),
13 | ]
14 |
15 | operations = [
16 | migrations.CreateModel(
17 | name='ActorAlias',
18 | fields=[
19 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
20 | ('name', models.CharField(max_length=50)),
21 | ],
22 | ),
23 | migrations.AlterField(
24 | model_name='actor',
25 | name='name',
26 | field=models.CharField(max_length=50, unique=True),
27 | ),
28 | migrations.AddField(
29 | model_name='actoralias',
30 | name='actor',
31 | field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='videos.Actor'),
32 | ),
33 | ]
34 |
--------------------------------------------------------------------------------
/YAPO/pagination.py:
--------------------------------------------------------------------------------
1 | from rest_framework import pagination
2 | from rest_framework.response import Response
3 |
4 |
5 | class HeaderLimitOffsetPagination(pagination.LimitOffsetPagination):
6 | def get_paginated_response(self, data):
7 | next_url = self.get_next_link()
8 | previous_url = self.get_previous_link()
9 | count = self.count
10 | page_size = self.limit
11 |
12 | if next_url is not None and previous_url is not None:
13 | link = '<{next_url}>; rel="next", <{previous_url}>; rel="prev" ,<{count}>; rel="count", <{page_size}>; rel="page_size"'
14 | elif next_url is not None:
15 | link = '<{next_url}>; rel="next", <{count}>; rel="count", <{page_size}>; rel="page_size"'
16 | elif previous_url is not None:
17 | link = '<{previous_url}>; rel="prev", <{count}>; rel="count", <{page_size}>; rel="page_size"'
18 | else:
19 | link = ''
20 |
21 | link = link.format(next_url=next_url, previous_url=previous_url, count=count, page_size=page_size)
22 | headers = {'Link': link} if link else {}
23 |
24 | return Response(data, headers=headers)
25 |
--------------------------------------------------------------------------------
/videos/migrations/0005_auto_20160615_1534.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-06-15 12:34
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('videos', '0004_auto_20160613_2048'),
12 | ]
13 |
14 | operations = [
15 | migrations.AddField(
16 | model_name='actor',
17 | name='date_of_birth',
18 | field=models.DateTimeField(blank=True, null=True),
19 | ),
20 | migrations.AlterField(
21 | model_name='actor',
22 | name='gender',
23 | field=models.IntegerField(default=-1),
24 | ),
25 | migrations.AlterField(
26 | model_name='actor',
27 | name='scenes',
28 | field=models.ManyToManyField(blank=True, null=True, to='videos.Scene'),
29 | ),
30 | migrations.AlterField(
31 | model_name='scenetag',
32 | name='scenes',
33 | field=models.ManyToManyField(blank=True, null=True, to='videos.Scene'),
34 | ),
35 | ]
36 |
--------------------------------------------------------------------------------
/videos/migrations/0003_auto_20160613_2043.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-06-13 17:43
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('videos', '0002_auto_20160613_2041'),
12 | ]
13 |
14 | operations = [
15 | migrations.AlterField(
16 | model_name='actor',
17 | name='thumbnail',
18 | field=models.CharField(blank=True, max_length=500, null=True),
19 | ),
20 | migrations.AlterField(
21 | model_name='actortag',
22 | name='thumbnail',
23 | field=models.CharField(blank=True, max_length=500, null=True),
24 | ),
25 | migrations.AlterField(
26 | model_name='scene',
27 | name='thumbnail',
28 | field=models.CharField(blank=True, max_length=500, null=True),
29 | ),
30 | migrations.AlterField(
31 | model_name='scenetag',
32 | name='thumbnail',
33 | field=models.CharField(blank=True, max_length=500, null=True),
34 | ),
35 | ]
36 |
--------------------------------------------------------------------------------
/videos/static/js/app/scene-tag-detail/scene-tag-detail.component.js:
--------------------------------------------------------------------------------
1 | angular.module('sceneTagDetail').component('sceneTagDetail', {
2 | templateUrl: 'static/js/app/scene-tag-detail/scene-tag-detail.template.html',
3 | controller: ['$routeParams', 'SceneTag', 'scopeWatchService', '$rootScope', '$scope',
4 | function SceneTagDetailController($routeParams, SceneTag, scopeWatchService, $rootScope, $scope) {
5 | var self = this;
6 | var gotPromise = false;
7 | self.sceneTag = SceneTag.get({sceneTagId: $routeParams.sceneTagId}).$promise.then(function (res) {
8 | scopeWatchService.sceneTagLoaded(res);
9 | self.sceneTag = res;
10 | // alert(res.name);
11 | $rootScope.title = res.name;
12 | gotPromise = true
13 | });
14 |
15 | $scope.$on("didSceneTagLoad", function (event, sceneTag) {
16 | if (gotPromise){
17 | scopeWatchService.sceneTagLoaded(self.sceneTag);
18 | }
19 | });
20 |
21 | self.update = function () {
22 | SceneTag.update({sceneTagId: self.sceneTag.id}, self.sceneTag)
23 | }
24 |
25 | }
26 | ]
27 | });
--------------------------------------------------------------------------------
/videos/migrations/0027_auto_20160708_1403.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-07-08 11:03
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('videos', '0026_auto_20160707_1349'),
12 | ]
13 |
14 | operations = [
15 | migrations.AlterField(
16 | model_name='scene',
17 | name='actors',
18 | field=models.ManyToManyField(blank=True, null=True, related_name='scenes', to='videos.Actor'),
19 | ),
20 | migrations.AlterField(
21 | model_name='scene',
22 | name='scene_tags',
23 | field=models.ManyToManyField(blank=True, null=True, related_name='scenes', to='videos.SceneTag'),
24 | ),
25 | migrations.AlterField(
26 | model_name='scene',
27 | name='websites',
28 | field=models.ManyToManyField(blank=True, null=True, related_name='scenes', to='videos.Website'),
29 | ),
30 | migrations.AlterField(
31 | model_name='website',
32 | name='scene_tags',
33 | field=models.ManyToManyField(null=True, related_name='websites', to='videos.SceneTag'),
34 | ),
35 | ]
36 |
--------------------------------------------------------------------------------
/videos/static/css/angular/animations.css:
--------------------------------------------------------------------------------
1 | .phone-list-item.ng-enter,
2 | .phone-list-item.ng-leave,
3 | .phone-list-item.ng-move {
4 | transition: 0.5s linear all;
5 | }
6 |
7 | .phone-list-item.ng-enter,
8 | .phone-list-item.ng-move {
9 | height: 0;
10 | opacity: 0;
11 | overflow: hidden;
12 | }
13 |
14 | .phone-list-item.ng-enter.ng-enter-active,
15 | .phone-list-item.ng-move.ng-move-active {
16 | height: 120px;
17 | opacity: 1;
18 | }
19 |
20 | .phone-list-item.ng-leave {
21 | opacity: 1;
22 | overflow: hidden;
23 | }
24 |
25 | .phone-list-item.ng-leave.ng-leave-active {
26 | height: 0;
27 | opacity: 0;
28 | padding-bottom: 0;
29 | padding-top: 0;
30 | }
31 |
32 | .view-frame.ng-enter,
33 | .view-frame.ng-leave {
34 | background: white;
35 | left: 0;
36 | position: absolute;
37 | right: 0;
38 | top: 0;
39 | }
40 |
41 | .view-frame.ng-enter {
42 | animation: 1s fade-in;
43 | z-index: 100;
44 | }
45 |
46 | .view-frame.ng-leave {
47 | animation: 1s fade-out;
48 | z-index: 99;
49 | }
50 |
51 | @keyframes fade-in {
52 | from {
53 | opacity: 0;
54 | }
55 | to {
56 | opacity: 1;
57 | }
58 | }
59 |
60 | @keyframes fade-out {
61 | from {
62 | opacity: 1;
63 | }
64 | to {
65 | opacity: 0;
66 | }
67 | }
--------------------------------------------------------------------------------
/videos/static/js/app/detail-profile-image/modal-content.html:
--------------------------------------------------------------------------------
1 |
4 |
5 |
![]()
6 |
7 |
8 |
9 |
10 |
11 |
12 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
33 |
--------------------------------------------------------------------------------
/videos/static/js/app/actor-tag-detail/actor-tag-detail.component.js:
--------------------------------------------------------------------------------
1 | angular.module('actorTagDetail').component('actorTagDetail', {
2 | templateUrl: 'static/js/app/actor-tag-detail/actor-tag-detail.template.html',
3 | controller: ['$routeParams', 'ActorTag', '$rootScope', 'scopeWatchService', '$scope',
4 | function ActorTagDetailController($routeParams, ActorTag, $rootScope, scopeWatchService, $scope) {
5 | var self = this;
6 | var gotPromise = false;
7 |
8 | self.actorTag = ActorTag.get({actorTagId: $routeParams.actorTagId});
9 |
10 | self.actorTag.$promise.then(function (result) {
11 |
12 | self.actorPks = result.actors.toString();
13 |
14 | scopeWatchService.actorTagLoaded(result);
15 |
16 | $rootScope.title = result.name;
17 | gotPromise = true;
18 |
19 | // alert(self.actorPks)
20 | });
21 |
22 | $scope.$on("didActorTagLoad", function (event, scene) {
23 |
24 | if (gotPromise){
25 | scopeWatchService.actorTagLoaded(self.actorTag)
26 | }
27 |
28 | });
29 |
30 | self.update = function () {
31 | ActorTag.update({actorTagId: self.actorTag.id}, self.actorTag)
32 | }
33 |
34 | }
35 | ]
36 | });
--------------------------------------------------------------------------------
/videos/static/js/app/actor-list/actor-list-row.template.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/videos/static/css/nav-bar-style.css:
--------------------------------------------------------------------------------
1 | ul#nav-bar {
2 | list-style-type: none;
3 | margin: 0;
4 | padding: 0;
5 | overflow: hidden;
6 | background-color: #333;
7 | }
8 |
9 | li#nav-bar-list-item {
10 | float: left;
11 | }
12 |
13 | li#nav-bar-list-item a, .dropbtn {
14 | display: inline-block;
15 | color: white;
16 | text-align: center;
17 | padding: 14px 16px;
18 | text-decoration: none;
19 | }
20 |
21 | li#nav-bar-list-item a:hover, .dropdown:hover .dropbtn {
22 | background-color: red;
23 | }
24 |
25 | li.dropdown {
26 | display: inline-block;
27 | }
28 |
29 | .dropdown-content {
30 | display: none;
31 | position: absolute;
32 | background-color: #f9f9f9;
33 | min-width: 160px;
34 | box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
35 | }
36 |
37 | .dropdown-content a {
38 | color: black;
39 | padding: 12px 16px;
40 | text-decoration: none;
41 | display: block;
42 | text-align: left;
43 | }
44 |
45 | .dropdown-content a:hover {
46 | background-color: #f1f1f1
47 | }
48 |
49 | .dropdown:hover .dropdown-content {
50 | display: block;
51 | }
52 |
--------------------------------------------------------------------------------
/videos/migrations/0021_auto_20160627_1454.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-06-27 11:54
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('videos', '0020_auto_20160627_1418'),
12 | ]
13 |
14 | operations = [
15 | migrations.CreateModel(
16 | name='LocalSceneFolders',
17 | fields=[
18 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
19 | ('name', models.CharField(max_length=500, unique=True)),
20 | ],
21 | ),
22 | migrations.AddField(
23 | model_name='actor',
24 | name='is_exempt_from_one_word_search',
25 | field=models.BooleanField(default=False),
26 | ),
27 | migrations.AddField(
28 | model_name='actoralias',
29 | name='is_exempt_from_one_word_search',
30 | field=models.BooleanField(default=False),
31 | ),
32 | migrations.AlterField(
33 | model_name='actoralias',
34 | name='name',
35 | field=models.CharField(max_length=50, unique=True),
36 | ),
37 | migrations.AlterField(
38 | model_name='folder',
39 | name='name',
40 | field=models.CharField(max_length=300, unique=True),
41 | ),
42 | ]
43 |
--------------------------------------------------------------------------------
/videos/static/js/app/scene-tag-detail/scene-tag-detail.template.html:
--------------------------------------------------------------------------------
1 |
7 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/videos/migrations/0032_auto_20160727_1734.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-07-27 14:34
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('videos', '0031_auto_20160720_0319'),
12 | ]
13 |
14 | operations = [
15 | migrations.AddField(
16 | model_name='scene',
17 | name='bit_rate',
18 | field=models.IntegerField(blank=True, null=True),
19 | ),
20 | migrations.AddField(
21 | model_name='scene',
22 | name='codec_name',
23 | field=models.CharField(blank=True, max_length=20, null=True),
24 | ),
25 | migrations.AddField(
26 | model_name='scene',
27 | name='duration',
28 | field=models.IntegerField(blank=True, null=True),
29 | ),
30 | migrations.AddField(
31 | model_name='scene',
32 | name='height',
33 | field=models.IntegerField(blank=True, null=True),
34 | ),
35 | migrations.AddField(
36 | model_name='scene',
37 | name='size',
38 | field=models.IntegerField(blank=True, null=True),
39 | ),
40 | migrations.AddField(
41 | model_name='scene',
42 | name='width',
43 | field=models.IntegerField(blank=True, null=True),
44 | ),
45 | ]
46 |
--------------------------------------------------------------------------------
/videos/migrations/0004_auto_20160613_2048.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-06-13 17:48
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('videos', '0003_auto_20160613_2043'),
12 | ]
13 |
14 | operations = [
15 | migrations.AddField(
16 | model_name='actortag',
17 | name='date_fav',
18 | field=models.DateTimeField(blank=True, null=True),
19 | ),
20 | migrations.AddField(
21 | model_name='actortag',
22 | name='date_runner_up',
23 | field=models.DateTimeField(blank=True, null=True),
24 | ),
25 | migrations.AddField(
26 | model_name='scenetag',
27 | name='date_fav',
28 | field=models.DateTimeField(blank=True, null=True),
29 | ),
30 | migrations.AddField(
31 | model_name='scenetag',
32 | name='date_runner_up',
33 | field=models.DateTimeField(blank=True, null=True),
34 | ),
35 | migrations.AlterField(
36 | model_name='actor',
37 | name='date_fav',
38 | field=models.DateTimeField(blank=True, null=True),
39 | ),
40 | migrations.AlterField(
41 | model_name='actor',
42 | name='date_runner_up',
43 | field=models.DateTimeField(blank=True, null=True),
44 | ),
45 | ]
46 |
--------------------------------------------------------------------------------
/videos/static/js/app/scene-tag-list/scene-tag-list.template.html:
--------------------------------------------------------------------------------
1 |
23 |
24 |
25 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/videos/migrations/0019_folder.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-06-26 15:52
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 | import django.db.models.deletion
7 | import django.db.models.manager
8 | import mptt.fields
9 |
10 |
11 | class Migration(migrations.Migration):
12 |
13 | dependencies = [
14 | ('videos', '0018_auto_20160624_1602'),
15 | ]
16 |
17 | operations = [
18 | migrations.CreateModel(
19 | name='Folder',
20 | fields=[
21 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
22 | ('name', models.CharField(max_length=200, unique=True)),
23 | ('lft', models.PositiveIntegerField(db_index=True, editable=False)),
24 | ('rght', models.PositiveIntegerField(db_index=True, editable=False)),
25 | ('tree_id', models.PositiveIntegerField(db_index=True, editable=False)),
26 | ('level', models.PositiveIntegerField(db_index=True, editable=False)),
27 | ('parent', mptt.fields.TreeForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='children', to='videos.Folder')),
28 | ('scenes', models.ManyToManyField(null=True, to='videos.Scene')),
29 | ],
30 | options={
31 | 'abstract': False,
32 | },
33 | managers=[
34 | ('_default_manager', django.db.models.manager.Manager()),
35 | ],
36 | ),
37 | ]
38 |
--------------------------------------------------------------------------------
/videos/static/js/app/db-folder-tree/db-folder-tree.template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
12 |
13 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/videos/misc_functions.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import unicode_literals
3 |
4 | import os
5 |
6 | import django
7 |
8 | django.setup()
9 |
10 | from videos.models import *
11 | import videos.const as const
12 |
13 |
14 | # coding=
15 |
16 |
17 | def strip_char(objects, char_to_strip):
18 | for o in objects:
19 | if char_to_strip in o.name:
20 | print ("Before: " + o.name)
21 | o.name = o.name.replace(char_to_strip, "")
22 | print ("After: " + o.name)
23 | o.save()
24 |
25 |
26 | def fix_profile_images(actors):
27 | for actor in actors:
28 | path_to_check = os.path.join(os.path.abspath("E:\\djangoProject\\YAPO\\videos\\static\\images\\actor"),
29 | actor.name, "profile\\profile.jpg")
30 | print (path_to_check)
31 | if os.path.isfile(path_to_check):
32 | rel_path = os.path.relpath(path_to_check, "E:\\djangoProject\\YAPO\\videos\\")
33 | print (rel_path)
34 | rel_path = rel_path.replace("\\", "/")
35 | print (rel_path)
36 | actor.thumbnail = rel_path
37 | actor.save()
38 | else:
39 | print ("No Image")
40 | actor.thumbnail = const.UNKNOWN_PERSON_IMAGE_PATH
41 | actor.save()
42 |
43 |
44 | def main():
45 | print ("hello")
46 | #
47 | # actor_tags = ActorTag.objects.all()
48 | # strip_char(actor_tags, )
49 | actors = Actor.objects.all()
50 |
51 | fix_profile_images(actors)
52 |
53 |
54 | if __name__ == "__main__":
55 | # clean_taling_spaces()
56 | main()
57 |
--------------------------------------------------------------------------------
/videos/migrations/0014_auto_20160622_0639.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-06-22 03:39
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('videos', '0013_auto_20160621_2129'),
12 | ]
13 |
14 | operations = [
15 | migrations.AddField(
16 | model_name='actor',
17 | name='country_of_origin',
18 | field=models.CharField(max_length=30, null=True),
19 | ),
20 | migrations.AddField(
21 | model_name='actor',
22 | name='ethnicity',
23 | field=models.CharField(max_length=30, null=True),
24 | ),
25 | migrations.AddField(
26 | model_name='actor',
27 | name='extra_text',
28 | field=models.TextField(default=''),
29 | ),
30 | migrations.AddField(
31 | model_name='actor',
32 | name='height',
33 | field=models.CharField(max_length=30, null=True),
34 | ),
35 | migrations.AddField(
36 | model_name='actor',
37 | name='measurements',
38 | field=models.CharField(max_length=30, null=True),
39 | ),
40 | migrations.AddField(
41 | model_name='actor',
42 | name='tattoos',
43 | field=models.CharField(max_length=200, null=True),
44 | ),
45 | migrations.AddField(
46 | model_name='actor',
47 | name='weight',
48 | field=models.CharField(max_length=30, null=True),
49 | ),
50 | ]
51 |
--------------------------------------------------------------------------------
/videos/static/js/app/actor-tag-list/actor-tag-list.template.html:
--------------------------------------------------------------------------------
1 |
25 |
26 |
27 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/videos/static/js/app/playlist-list/playlist-list.component.js:
--------------------------------------------------------------------------------
1 | angular.module('playlistList').component('playlistList', {
2 | // Note: The URL is relative to our `index.html` file
3 | templateUrl: ['$element', '$attrs', function ($element, $attrs) {
4 |
5 | // if ($attrs.viewStyle == 'grid') {
6 | // return 'static/js/app/scene-list/scene-list-grid.template.html'
7 | // } else {
8 | return 'static/js/app/playlist-list/playlist-list.template.html';
9 | // }
10 |
11 |
12 | }],
13 | bindings: {
14 | mainPage: '=',
15 | treeFolder: '='
16 | },
17 | controller: ['$scope', '$http', '$rootScope', 'Playlist', 'helperService',
18 | function PlaylistListController($scope, $http, $rootScope, Playlist, helperService) {
19 |
20 | var self = this;
21 |
22 |
23 |
24 |
25 | $http.get('api/playlist/', {}).then(function (response) {
26 | // alert(angular.toJson(response));
27 | self.playlists = response.data;
28 | self.response = response;
29 | // alert("Got response from server: " + self.pathToFolderToAdd);
30 | }, function errorCallback(response) {
31 | alert("Something went wrong!");
32 | });
33 |
34 |
35 | self.removePlaylist = function (playlistToRemove) {
36 |
37 | Playlist.remove({playlistId: playlistToRemove.id});
38 |
39 | var found = helperService.getObjectIndexFromArrayOfObjects(playlistToRemove,self.playlists);
40 |
41 | if(found != null){
42 | self.playlists.splice(found,1)
43 | }
44 |
45 |
46 |
47 | }
48 |
49 | }]
50 | });
--------------------------------------------------------------------------------
/videos/migrations/0016_auto_20160623_1527.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-06-23 12:27
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('videos', '0015_actor_last_lookup'),
12 | ]
13 |
14 | operations = [
15 | migrations.AlterField(
16 | model_name='actor',
17 | name='actor_tags',
18 | field=models.ManyToManyField(blank=True, null=True, to='videos.ActorTag'),
19 | ),
20 | migrations.AlterField(
21 | model_name='actor',
22 | name='country_of_origin',
23 | field=models.CharField(blank=True, max_length=30, null=True),
24 | ),
25 | migrations.AlterField(
26 | model_name='actor',
27 | name='ethnicity',
28 | field=models.CharField(blank=True, max_length=30, null=True),
29 | ),
30 | migrations.AlterField(
31 | model_name='actor',
32 | name='height',
33 | field=models.CharField(blank=True, max_length=30, null=True),
34 | ),
35 | migrations.AlterField(
36 | model_name='actor',
37 | name='measurements',
38 | field=models.CharField(blank=True, max_length=30, null=True),
39 | ),
40 | migrations.AlterField(
41 | model_name='actor',
42 | name='tattoos',
43 | field=models.CharField(blank=True, max_length=200, null=True),
44 | ),
45 | migrations.AlterField(
46 | model_name='actor',
47 | name='weight',
48 | field=models.CharField(blank=True, max_length=30, null=True),
49 | ),
50 | ]
51 |
--------------------------------------------------------------------------------
/videos/static/js/app/playlist-detail/playlist-detail.component.js:
--------------------------------------------------------------------------------
1 | angular.module('playlistDetail').component('playlistDetail', {
2 | // Note: The URL is relative to our `index.html` file
3 | templateUrl: ['$element', '$attrs', function ($element, $attrs) {
4 |
5 | // if ($attrs.viewStyle == 'grid') {
6 | // return 'static/js/app/scene-list/scene-list-grid.template.html'
7 | // } else {
8 | return 'static/js/app/playlist-detail/playlist-detail.template.html';
9 | // }
10 |
11 |
12 | }],
13 | bindings: {
14 | mainPage: '='
15 | },
16 | controller: ['$scope', '$http', '$rootScope', '$routeParams', 'scopeWatchService', 'Playlist',
17 | function PlaylistListController($scope, $http, $rootScope, $routeParams, scopeWatchService, Playlist) {
18 |
19 | var self = this;
20 |
21 | var routParam = $routeParams.playlistId;
22 | var gotPromise = false;
23 |
24 |
25 | $http.get('api/playlist/' + routParam, {}).then(function (response) {
26 | // alert(angular.toJson(response));
27 | self.playlist = response.data;
28 | scopeWatchService.playlistLoaded(self.playlist);
29 | gotPromise = true;
30 |
31 | // alert("Got response from server: " + self.pathToFolderToAdd);
32 | }, function errorCallback(response) {
33 | alert("Something went wrong!");
34 | });
35 |
36 | $scope.$on("didPlaylistLoad", function (event, actor) {
37 |
38 | if (gotPromise) {
39 |
40 | scopeWatchService.playlistLoaded(self.playlist);
41 |
42 |
43 |
44 | }
45 | });
46 |
47 | self.update = function () {
48 | Playlist.update({playlistId: self.playlist.id}, self.playlist)
49 | }
50 |
51 |
52 |
53 |
54 |
55 | }]
56 | });
--------------------------------------------------------------------------------
/videos/static/js/app/section-list-wrapper/section-wrapper.template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/videos/static/js/app/app.upload.js:
--------------------------------------------------------------------------------
1 | // https://uncorkedstudios.com/blog/multipartformdata-file-upload-with-angularjs
2 |
3 | var myApp = angular.module('fileUpload', []);
4 |
5 | myApp.directive('fileModel', ['$parse', function ($parse) {
6 | return {
7 | restrict: 'A',
8 | link: function (scope, element, attrs) {
9 | var model = $parse(attrs.fileModel);
10 | var modelSetter = model.assign;
11 |
12 | element.bind('change', function () {
13 | scope.$apply(function () {
14 | modelSetter(scope, element[0].files[0]);
15 | });
16 | });
17 | }
18 | };
19 | }]);
20 |
21 | myApp.service('fileUpload', ['$http', function ($http) {
22 | this.uploadFileToUrl = function (file, uploadingObject, uploadingObjectID) {
23 | var fd = new FormData();
24 | fd.append('file', file);
25 | fd.append('type', uploadingObject);
26 | fd.append('id', uploadingObjectID);
27 | $http.post('/upload/', fd, {
28 | transformRequest: angular.identity,
29 | headers: {'Content-Type': undefined}
30 | })
31 | .success(function () {
32 | })
33 | .error(function () {
34 | });
35 | }
36 | }]);
37 |
38 | myApp.controller('myCtrl', ['$scope', '$rootScope', 'fileUpload', function ($scope, $rootScope, fileUpload) {
39 |
40 | $rootScope.uploadFile = function (uploadingObject) {
41 | // console.log("Is cropper in scope?" + $scope.cropper.croppedImage)
42 | // var file = $scope.myFile;
43 | var file = $rootScope.cropper.croppedImage;
44 | console.log('file is ');
45 | console.dir(file);
46 | // var uploadingObject = $scope.modelContent;
47 | var uploadingObjectID = $scope.modelContent.id;
48 | fileUpload.uploadFileToUrl(file, uploadingObject, uploadingObjectID);
49 | };
50 |
51 |
52 | $scope.edit = function () {
53 | $rootScope.cropper.sourceImage = $scope.modelContent.thumbnail
54 | }
55 |
56 | }]);
57 |
--------------------------------------------------------------------------------
/videos/static/js/app/nav-bar/nav-bar.template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
15 |
16 |
30 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/videos/static/js/app/pagination/pagination.component.js:
--------------------------------------------------------------------------------
1 | angular.module('pagination').component('pagination', {
2 | templateUrl: 'static/js/app/pagination/pagination.template.html',
3 | bindings: {
4 | pageType: '='
5 | },
6 | controller: ['$routeParams', 'Scene', 'helperService', '$scope', 'SceneTag', 'Actor', 'Website', '$http', '$rootScope', 'scopeWatchService',
7 | function PaginationController($routeParams, Scene, helperService, $scope, SceneTag, Actor, Website, $http, $rootScope, scopeWatchService) {
8 |
9 | var self = this;
10 |
11 |
12 | // self.itemsPerPage = 50;
13 |
14 |
15 | if (helperService.getNumberOfItemsPerPaige() == undefined) {
16 | self.itemsPerPage = 50;
17 | helperService.setNumberOfItemsPerPaige(self.itemsPerPage)
18 | } else {
19 | self.itemsPerPage = helperService.getNumberOfItemsPerPaige()
20 | }
21 |
22 | self.bigCurrentPage = "";
23 | self.maxSize = "";
24 | self.totalItems = "";
25 | self.onePageOnly = true;
26 |
27 |
28 | self.pageChange = function () {
29 | // alert(self.bigCurrentPage);
30 |
31 |
32 | var ans = {
33 | pageType: this.pageType,
34 | page: self.bigCurrentPage
35 | };
36 |
37 | scopeWatchService.paginationChange(ans);
38 |
39 |
40 | };
41 |
42 |
43 | function getMaxPageFromLinkHeader(linkHeader) {
44 |
45 |
46 | self.totalItems = parseInt(linkHeader.replace(/.*<(\d+)>; rel="count".*/, '$1'));
47 |
48 |
49 | }
50 |
51 |
52 | $scope.$on("paginationInit", function (event, pageInfo) {
53 | if (pageInfo.pageType == self.pageType) {
54 | if (pageInfo.pageInfo != '-6') {
55 | self.onePageOnly = false;
56 | getMaxPageFromLinkHeader(pageInfo.pageInfo);
57 | } else {
58 | self.onePageOnly = true;
59 | }
60 | }
61 |
62 |
63 | });
64 |
65 |
66 | }]
67 | });
--------------------------------------------------------------------------------
/videos/migrations/0022_auto_20160630_1713.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-06-30 14:13
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 | import django.db.models.deletion
7 |
8 |
9 | class Migration(migrations.Migration):
10 |
11 | dependencies = [
12 | ('videos', '0021_auto_20160627_1454'),
13 | ]
14 |
15 | operations = [
16 | migrations.CreateModel(
17 | name='Website',
18 | fields=[
19 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
20 | ('name', models.CharField(max_length=50, unique=True)),
21 | ('date_added', models.DateTimeField(auto_now_add=True)),
22 | ('play_count', models.IntegerField(default=0)),
23 | ('date_fav', models.DateTimeField(blank=True, null=True)),
24 | ('date_runner_up', models.DateTimeField(blank=True, null=True)),
25 | ('is_fav', models.BooleanField(default=False)),
26 | ('is_runner_up', models.BooleanField(default=False)),
27 | ('rating', models.IntegerField(default=0)),
28 | ('thumbnail', models.CharField(blank=True, max_length=500, null=True)),
29 | ],
30 | ),
31 | migrations.RemoveField(
32 | model_name='actoralias',
33 | name='actor',
34 | ),
35 | migrations.AddField(
36 | model_name='actor',
37 | name='actor_aliases',
38 | field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='videos.ActorAlias'),
39 | ),
40 | migrations.AlterField(
41 | model_name='scenetag',
42 | name='name',
43 | field=models.CharField(max_length=50, unique=True),
44 | ),
45 | migrations.AddField(
46 | model_name='website',
47 | name='scene_tags',
48 | field=models.ManyToManyField(null=True, to='videos.SceneTag'),
49 | ),
50 | migrations.AddField(
51 | model_name='scene',
52 | name='websites',
53 | field=models.ManyToManyField(blank=True, null=True, to='videos.Website'),
54 | ),
55 | ]
56 |
--------------------------------------------------------------------------------
/videos/static/js/app/website-detail/website-detail.template.html:
--------------------------------------------------------------------------------
1 |
7 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/videos/static/js/app/add-items/add-items.component.js:
--------------------------------------------------------------------------------
1 | angular.module('addItems').component('addItems', {
2 | // Note: The URL is relative to our `index.html` file
3 | templateUrl: 'static/js/app/add-items/add-items.template.html',
4 | controller: ['$scope', 'ActorTag', 'pagerService', 'scopeWatchService', 'helperService', '$http',
5 | function AddItemsController($scope, ActorTag, pagerService, scopeWatchService, helperService, $http) {
6 |
7 | var self = this;
8 |
9 | //Input areas:
10 | self.textareaInputContent = "";
11 | self.folderInputContent = "";
12 |
13 | var foldersToAdd = "";
14 |
15 | var actorsToAdd = "";
16 |
17 | var sceneTagsToAdd = "";
18 |
19 | var websitesToAdd = "";
20 |
21 | self.createSampleVideo = false;
22 |
23 | var httpRequest = function () {
24 | return $http.get('add-items/', {
25 | params: {
26 | actorsToAdd: actorsToAdd,
27 | sceneTagsToAdd: sceneTagsToAdd,
28 | websitesToAdd: websitesToAdd,
29 | folderToAddPath: foldersToAdd,
30 | createSampleVideo: self.createSampleVideo
31 |
32 | }
33 | }).then(function (response) {
34 | // alert(angular.toJson(response))
35 | // alert("Adding folders and files inside: " + self.pathToFolderToAdd);
36 | }, function errorCallback(response) {
37 | alert("Something went wrong!");
38 | });
39 | };
40 |
41 | var clearFields = function () {
42 | foldersToAdd = "";
43 |
44 | actorsToAdd = "";
45 |
46 | sceneTagsToAdd = "";
47 |
48 | websitesToAdd = "";
49 |
50 | };
51 |
52 | self.addFolderClicked = function () {
53 | clearFields();
54 | foldersToAdd = self.folderInputContent;
55 | httpRequest();
56 |
57 | };
58 |
59 | self.addActorsClicked = function () {
60 | clearFields();
61 | actorsToAdd = self.textareaInputContent;
62 | httpRequest();
63 |
64 | };
65 |
66 | self.addSceneTagsClicked = function () {
67 | clearFields();
68 | sceneTagsToAdd = self.textareaInputContent;
69 | httpRequest();
70 | };
71 |
72 | self.websitesToAddClicked = function () {
73 | clearFields();
74 | websitesToAdd = self.textareaInputContent;
75 | httpRequest();
76 | }
77 | }
78 | ]
79 | });
80 |
81 |
82 |
--------------------------------------------------------------------------------
/videos/static/js/app/add-items/add-items.template.html:
--------------------------------------------------------------------------------
1 |
2 | (supports multiple folders separated by commas EX: C:\folder1, D:\folder2) Folder added here can be rescanned under the "settings" menue :
3 |
5 |
11 |
17 |
18 |
19 |
20 |
21 |
22 | (Can be a single item)
24 |
25 |
31 |
32 |
38 |
39 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/videos/static/js/app/app.controller.js:
--------------------------------------------------------------------------------
1 | // image crop controller from https://github.com/AllanBishop/angular-img-cropper
2 |
3 |
4 | angular.module('yapoApp').controller("ImageCropperCtrl", ['$scope', '$rootScope', function ($scope, $rootScope) {
5 | $rootScope.cropper = {};
6 | $rootScope.cropper.sourceImage = null;
7 | $rootScope.cropper.croppedImage = null;
8 | $rootScope.bounds = {};
9 | $rootScope.bounds.left = 0;
10 | $rootScope.bounds.right = 0;
11 | $rootScope.bounds.top = 0;
12 | $rootScope.bounds.bottom = 0;
13 | }]);
14 |
15 |
16 | // Modal controller from angular bootstrap https://angular-ui.github.io/bootstrap/
17 | angular.module('yapoApp').controller('ModalCtrl', function ($scope, $uibModal, $log, helperService) {
18 |
19 | $scope.items = ['item1', 'item2', 'item3'];
20 |
21 | // $scope.actor2 = undefined;
22 |
23 |
24 | $scope.animationsEnabled = true;
25 |
26 | $scope.open = function (size) {
27 |
28 | // console.log(angular.toJson($scope.items));
29 | // console.log(angular.toJson($scope.actor));
30 | // console.log(angular.toJson($scope.actor.name));
31 | //
32 | // $scope.items.push($scope.actor.name);
33 | // $scope.actor2 = $scope.actor;
34 |
35 |
36 | var modalInstance = $uibModal.open({
37 | animation: $scope.animationsEnabled,
38 | templateUrl: 'static/js/app/detail-profile-image/modal-content.html',
39 | controller: 'ModalInstanceCtrl',
40 | size: size,
41 | resolve: {
42 | items: function () {
43 | return $scope.items;
44 | },
45 | modelContent: function () {
46 | console.log("app-controller: ModalCtrl: modelContent is " + angular.toJson(helperService.get2()));
47 | return helperService.get2();
48 |
49 | }
50 | }
51 | });
52 |
53 | modalInstance.result.then(function (selectedItem) {
54 | $scope.selected = selectedItem;
55 | }, function () {
56 | $log.info('Modal dismissed at: ' + new Date());
57 | });
58 | };
59 |
60 | $scope.toggleAnimation = function () {
61 | $scope.animationsEnabled = !$scope.animationsEnabled;
62 | };
63 |
64 | });
65 |
66 | // Please note that $uibModalInstance represents a modal window (instance) dependency.
67 | // It is not the same as the $uibModal service used above.
68 |
69 | angular.module('yapoApp').controller('ModalInstanceCtrl', function ($scope, $rootScope, $uibModalInstance, items, modelContent) {
70 |
71 | $scope.items = items;
72 | $scope.modelContent = modelContent;
73 | $scope.selected = {
74 | item: $scope.items[0]
75 | };
76 |
77 | $scope.ok = function (uploadingObject) {
78 | $rootScope.uploadFile(uploadingObject);
79 | $uibModalInstance.close();
80 | };
81 |
82 | $scope.cancel = function () {
83 | $uibModalInstance.dismiss('cancel');
84 | };
85 |
86 |
87 | });
--------------------------------------------------------------------------------
/videos/aux_functions.py:
--------------------------------------------------------------------------------
1 | import os
2 | import videos.const
3 | import urllib.request
4 | from videos.models import Actor
5 |
6 |
7 | def save_actor_profile_image_from_web(image_link, actor, force):
8 | save_path = os.path.join(videos.const.MEDIA_PATH,
9 | 'actor/' + str(actor.id) + '/profile/')
10 |
11 | if not os.path.exists(save_path):
12 | os.makedirs(save_path)
13 |
14 | save_file_name = os.path.join(save_path, 'profile.jpg')
15 | if not os.path.isfile(save_file_name) or force:
16 | urllib.request.urlretrieve(image_link, save_file_name)
17 |
18 | rel_path = os.path.relpath(save_file_name, start='videos')
19 | as_uri = urllib.request.pathname2url(rel_path)
20 |
21 | actor.thumbnail = as_uri
22 |
23 |
24 | def actor_folder_from_name_to_id():
25 | actors = Actor.objects.all()
26 |
27 | for actor in actors:
28 | rel_path = os.path.relpath(
29 | os.path.join(videos.const.MEDIA_PATH, 'actor', str(actor.id), 'profile', 'profile.jpg'), start='videos')
30 |
31 | as_uri = urllib.request.pathname2url(rel_path)
32 |
33 | print("Actor {} thumb path is: {} \n and it should be {}".format(actor.name, actor.thumbnail, as_uri))
34 | print(actor.thumbnail != as_uri)
35 | if (actor.thumbnail != videos.const.UNKNOWN_PERSON_IMAGE_PATH) and \
36 | (actor.thumbnail != as_uri):
37 | try:
38 | os.rename(os.path.join(videos.const.MEDIA_PATH, 'actor', actor.name),
39 | os.path.join(videos.const.MEDIA_PATH, 'actor', str(actor.id)))
40 |
41 | print("Renamed {} to {}".format(os.path.join(videos.const.MEDIA_PATH, 'actor', actor.name),
42 | os.path.join(videos.const.MEDIA_PATH, 'actor', str(actor.id))))
43 | except FileNotFoundError:
44 |
45 | if os.path.isfile(
46 | os.path.join(videos.const.MEDIA_PATH, 'actor', str(actor.id), 'profile', 'profile.jpg')):
47 |
48 | rel_path_changed = os.path.relpath(
49 | os.path.join(videos.const.MEDIA_PATH, 'actor', str(actor.id), 'profile', 'profile.jpg'),
50 | start='videos')
51 | as_uri_changed = urllib.request.pathname2url(rel_path_changed)
52 | actor.thumbnail = as_uri_changed
53 | actor.save()
54 | print("Changed {} thumb in database to {}".format(actor.name, as_uri_changed))
55 | else:
56 | print("File {} not found!".format(os.path.join(videos.const.MEDIA_PATH, 'actor', actor.name)))
57 |
58 | rel_path_changed = os.path.relpath(
59 | os.path.join(videos.const.MEDIA_PATH, 'actor', str(actor.id), 'profile', 'profile.jpg'), start='videos')
60 | as_uri_changed = urllib.request.pathname2url(rel_path_changed)
61 | actor.thumbnail = as_uri_changed
62 | actor.save()
63 |
64 | print("Changed {} thumb in database to {}".format(actor.name, as_uri_changed))
65 |
66 | return True
67 |
68 |
69 | if __name__ == "__main__":
70 | print("this is main")
71 |
--------------------------------------------------------------------------------
/videos/static/js/app/app.config.js:
--------------------------------------------------------------------------------
1 | app.config(['$sceProvider', '$locationProvider', '$routeProvider', '$httpProvider', '$resourceProvider',
2 | function config($sceProvider, $locationProvider, $routeProvider, $httpProvider, $resourceProvider) {
3 |
4 | // disable SCE completely (https://docs.angularjs.org/api/ng/service/$sce)
5 | $sceProvider.enabled(false);
6 |
7 | $locationProvider.hashPrefix('!');
8 |
9 |
10 | $routeProvider.when('/actor', {
11 | template: ''
12 | }).when('/actor/:actorId', {
13 | template: ''
14 | }).when('/scene/', {
15 | template: ''
16 | }).when('/scene/:sceneId', {
17 | template: ''
18 | }).when('/actor-tag/', {
19 | template: ''
20 | }).when('/actor-tag/:actorTagId', {
21 | template: ''
22 | }).when('/scene-tag/', {
23 | template: ''
24 | }).when('/scene-tag/:sceneTagId', {
25 | template: ''
26 | }).when('/website/', {
27 | template: ''
28 | }).when('/website/:websiteId', {
29 | template: ''
30 | }).when('/folder/', {
31 | template: ''
32 | // template: ''
33 | }).when('/folder/:parentId', {
34 | template: ''
35 | // template: ''
36 | }).when('/add/', {
37 | template: ''
38 | }).when('/settings/', {
39 | template: ''
40 | }).when('/playlist/', {
41 | template: ''
42 | }).when('/playlist/:playlistId', {
43 | template: ''
44 | }).otherwise('/'), {
45 | template: '
This is temp index
'
46 |
47 | };
48 | //
49 | // // disable SCE completely (https://docs.angularjs.org/api/ng/service/$sce)
50 | // $sceProvider.enabled(false);
51 |
52 | // CSRF Support
53 | $httpProvider.defaults.xsrfCookieName = 'csrftoken';
54 | $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
55 |
56 | // This only works in angular 3!
57 | // It makes dealing with Django slashes at the end of everything easier.
58 |
59 | $resourceProvider.defaults.stripTrailingSlashes = false;
60 | }
61 |
62 | ]);
63 |
64 | app.run(function (editableOptions) {
65 | editableOptions.theme = 'bs3';
66 | });
67 |
--------------------------------------------------------------------------------
/videos/static/js/app/actor-alias-list/actor-alias-list.component.js:
--------------------------------------------------------------------------------
1 | // Register `phoneList` component, along with its associated controller and template
2 | angular.module('actorAliasList').component('actorAliasList', {
3 | // Note: The URL is relative to our `index.html` file
4 | templateUrl: 'static/js/app/actor-alias-list/actor-alias-list.template.html',
5 | bindings: {
6 | pk: '='
7 | },
8 | controller: ['$scope', 'ActorAlias', 'pagerService', 'scopeWatchService','helperService',
9 | function ActorAliasListController($scope, ActorAlias, pagerService, scopeWatchService, helperService) {
10 | var self = this;
11 | var counter = 0;
12 | // self.aliases = [];
13 | self.pageType = 'ActorAlias';
14 |
15 |
16 |
17 |
18 |
19 | self.nextPage = function (currentPage) {
20 |
21 |
22 | var input = {
23 | currentPage: currentPage,
24 | pageType: self.pageType,
25 | actor: self.actor
26 |
27 |
28 | };
29 |
30 | self.actorsToadd = pagerService.getNextPage(input);
31 | if (self.actorsToadd != undefined) {
32 | self.actorsToadd.$promise.then(function (res) {
33 |
34 | // self.actorsToadd = res[0];
35 |
36 | var paginationInfo = {
37 | pageType: input.pageType,
38 | pageInfo: res[1]
39 | };
40 |
41 | scopeWatchService.paginationInit(paginationInfo);
42 |
43 | self.aliases = helperService.resourceToArray(res[0]);
44 |
45 |
46 | });
47 | }
48 |
49 | };
50 |
51 |
52 | $scope.$on("actorLoaded", function (event, actor) {
53 | self.actor = actor;
54 | self.nextPage(0);
55 |
56 |
57 | });
58 |
59 | $scope.$on("paginationChange", function (event, pageInfo) {
60 | if (pageInfo.pageType == self.pageType){
61 | self.nextPage(pageInfo.page)
62 | }
63 |
64 |
65 | });
66 |
67 |
68 | $scope.$on("addAliasToList", function (event, alias) {
69 | self.aliases.push(alias);
70 |
71 | });
72 |
73 |
74 | self.deleteAlias = function (aliasToDelete) {
75 | // alert(aliasToDelete.id + aliasToDelete.name)
76 |
77 | // alert(self.pk.indexOf(aliasToDelete.id));
78 | // console.log("actor-alias-list.componenet: newValue is: " + )
79 | ActorAlias.remove({actorAliasId: aliasToDelete.id});
80 |
81 | var resId = [];
82 | var resObjects = [];
83 |
84 | for (var i = 0 ; i < self.aliases.length; i++) {
85 | if (self.aliases[i].id != aliasToDelete.id) {
86 |
87 | resId.push(self.aliases[i].id);
88 | resObjects.push(self.aliases[i]);
89 |
90 |
91 |
92 | }
93 | }
94 |
95 | self.aliases = resObjects;
96 |
97 |
98 | };
99 | self.isOneWord = function (alias) {
100 |
101 | return !(alias.name.indexOf(' ') > -1)
102 |
103 | };
104 |
105 | self.updateActorAlias = function (object) {
106 |
107 | //
108 | // var id = object.id + '/';
109 | // alert(id);
110 |
111 | ActorAlias.update({actorAliasId: object.id}, object);
112 | // return alert(object.id + ' ' + object.name + ' input: ' + input);
113 | };
114 | }
115 | ]
116 | });
--------------------------------------------------------------------------------
/videos/migrations/0001_initial.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-06-13 17:27
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | initial = True
11 |
12 | dependencies = [
13 | ]
14 |
15 | operations = [
16 | migrations.CreateModel(
17 | name='Actor',
18 | fields=[
19 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
20 | ('name', models.CharField(max_length=50)),
21 | ('date_added', models.DateTimeField(auto_now_add=True)),
22 | ('date_fav', models.DateTimeField(null=True)),
23 | ('date_runner_up', models.DateTimeField(null=True)),
24 | ('play_count', models.IntegerField(default=0)),
25 | ('is_fav', models.BooleanField(default=False)),
26 | ('is_runner_up', models.BooleanField(default=False)),
27 | ('rating', models.IntegerField(default=0)),
28 | ('thumbnail', models.CharField(max_length=500)),
29 | ('gender', models.NullBooleanField()),
30 | ],
31 | ),
32 | migrations.CreateModel(
33 | name='ActorTag',
34 | fields=[
35 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
36 | ('name', models.CharField(max_length=50)),
37 | ('date_added', models.DateTimeField(auto_now_add=True)),
38 | ('play_count', models.IntegerField(default=0)),
39 | ('is_fav', models.BooleanField(default=False)),
40 | ('is_runner_up', models.BooleanField(default=False)),
41 | ('rating', models.IntegerField(default=0)),
42 | ('thumbnail', models.CharField(max_length=500)),
43 | ('actors', models.ManyToManyField(to='videos.Actor')),
44 | ],
45 | ),
46 | migrations.CreateModel(
47 | name='Scene',
48 | fields=[
49 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
50 | ('name', models.CharField(max_length=500)),
51 | ('path_to_file', models.CharField(max_length=500)),
52 | ('path_to_dir', models.CharField(max_length=500)),
53 | ('date_added', models.DateTimeField(auto_now_add=True)),
54 | ('date_fav', models.DateTimeField(null=True)),
55 | ('date_runner_up', models.DateTimeField(null=True)),
56 | ('play_count', models.IntegerField(default=0)),
57 | ('is_fav', models.BooleanField(default=False)),
58 | ('is_runner_up', models.BooleanField(default=False)),
59 | ('rating', models.IntegerField(default=0)),
60 | ('thumbnail', models.CharField(max_length=500)),
61 | ],
62 | ),
63 | migrations.CreateModel(
64 | name='SceneTag',
65 | fields=[
66 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
67 | ('name', models.CharField(max_length=50)),
68 | ('date_added', models.DateTimeField(auto_now_add=True)),
69 | ('play_count', models.IntegerField(default=0)),
70 | ('is_fav', models.BooleanField(default=False)),
71 | ('is_runner_up', models.BooleanField(default=False)),
72 | ('rating', models.IntegerField(default=0)),
73 | ('thumbnail', models.CharField(max_length=500)),
74 | ('scenes', models.ManyToManyField(to='videos.Scene')),
75 | ],
76 | ),
77 | migrations.AddField(
78 | model_name='actor',
79 | name='scenes',
80 | field=models.ManyToManyField(to='videos.Scene'),
81 | ),
82 | ]
83 |
--------------------------------------------------------------------------------
/videos/static/css/style.css:
--------------------------------------------------------------------------------
1 |
2 |
3 | .top-buffer { margin-top:20px; }
4 |
5 | .base-top-buffer {margin-top: 80px}
6 |
7 | .float-right-nav{
8 | float:right;
9 | }
10 |
11 | ul.enlarge {
12 | list-style-type: none; /*remove the bullet point*/
13 | }
14 |
15 | ul.enlarge li {
16 | display: inline-block; /*places the images in a line*/
17 | position: relative; /*allows precise positioning of the popup image when used with position:absolute - see support section */
18 | z-index: 0; /*resets the stack order of the list items - we'll increase in step 4. See support section for more info*/
19 | margin: 10px 40px 0 20px; /*space between the images*/
20 | }
21 |
22 | /***In the HTML in step one we placed the large image inside a , now we move it off the page until it's required***/
23 | ul.enlarge span {
24 | position: absolute; /*see support section for more info on positioning*/
25 | left: -9999px; /*moves the span off the page, effectively hidding it from view*/
26 | }
27 |
28 | /***Note: This styling will apply to both the thumbnail and popup image, unless you override these styles in step five***/
29 | ul.enlarge img {
30 | /*give the thumbnails a frame*/
31 | background-color: #eae9d4; /*frame colour*/
32 | padding: 6px; /*frame size*/
33 | /*add a drop shadow to the frame*/
34 | -webkit-box-shadow: 0 0 6px rgba(132, 132, 132, .75);
35 | -moz-box-shadow: 0 0 6px rgba(132, 132, 132, .75);
36 | box-shadow: 0 0 6px rgba(132, 132, 132, .75);
37 | /*and give the corners a small curve*/
38 | -webkit-border-radius: 4px;
39 | -moz-border-radius: 4px;
40 | border-radius: 4px;
41 | }
42 |
43 | ul.enlarge li:hover {
44 | z-index: 50; /*places the popups infront of the thumbnails, which we gave a z-index of 0 in step 1*/
45 | cursor: pointer; /*changes the cursor to a hand*/
46 | }
47 |
48 | /***We bring the large image back onto the page by reducing left from -9999px (set in step 2) to figures below***/
49 | /*ul.enlarge li:hover span{ !*positions the when the (which contains the thumbnail) is hovered*!*/
50 | /*top: 0%; !*the distance from the bottom of the thumbnail to the top of the popup image*!*/
51 | /*left: 50%; !*distance from the left of the thumbnail to the left of the popup image*!*/
52 | /*}*/
53 | /*!***To make it look neater we used :nth-child to set a different left distance for each image***!*/
54 | /*ul.enlarge li:hover:nth-child(2) span{*/
55 | /*left: -100px;*/
56 | /*}*/
57 | /*ul.enlarge li:hover:nth-child(3) span{*/
58 | /*left: -200px;*/
59 | /*}*/
60 |
61 | /***Override the styling of images set in step 3 to make the frame smaller and the background darker***/
62 | ul.enlarge span img {
63 | padding: 2px; /*size of the frame*/
64 | background: #ccc; /*colour of the frame*/
65 | }
66 |
67 | /***Style the containing the framed images and the caption***/
68 | ul.enlarge span {
69 | /**Style the frame**/
70 | padding: 10px; /*size of the frame*/
71 | background: #eae9d4; /*colour of the frame*/
72 | /*add a drop shadow to the frame*/
73 | -webkit-box-shadow: 0 0 20px rgba(0, 0, 0, .75);
74 | -moz-box-shadow: 0 0 20px rgba(0, 0, 0, .75);
75 | box-shadow: 0 0 20px rgba(0, 0, 0, .75);
76 | /*give the corners a curve*/
77 | -webkit-border-radius: 8px;
78 | -moz-border-radius: 8px;
79 | border-radius: 8px;
80 | /**Style the caption**/
81 | font-family: 'Droid Sans', sans-serif; /*Droid Sans is available from Google fonts*/
82 | font-size: .9em;
83 | text-align: center;
84 | color: #495a62;
85 | }
86 |
87 | .thumbnail-div {
88 | width: 50%;
89 | /*/ / or you could use percentage value for responsive layout height: 50 %;*/
90 | overflow: hidden;
91 | }
92 |
93 | .thumb1 {
94 | /*background: url(http://i.stack.imgur.com/jGlzr.png) 50% 50% no-repeat; !* 50% 50% centers image in div *!*/
95 | width: 250px;
96 | height: 250px;
97 | }
98 |
99 | .thumb a {
100 | display: block;
101 | width: 250px;
102 | height: 250px;
103 | }
104 |
105 | .thumb a:hover {
106 |
107 | }
108 |
109 |
--------------------------------------------------------------------------------
/videos/static/js/app/website-detail/website-detail.component.js:
--------------------------------------------------------------------------------
1 | angular.module('websiteDetail').component('websiteDetail', {
2 | templateUrl: 'static/js/app/website-detail/website-detail.template.html',
3 | controller: ['$routeParams', 'Website', 'scopeWatchService', '$rootScope', '$scope', 'helperService',
4 | function WebsiteDetailController($routeParams, Website, scopeWatchService, $rootScope, $scope, helperService) {
5 | var self = this;
6 | var gotPromise = false;
7 | self.website = Website.get({websiteId: $routeParams.websiteId}).$promise.then(function (res) {
8 |
9 | scopeWatchService.websiteLoaded(res);
10 | self.website = res;
11 | // alert(res.name);
12 | $rootScope.title = res.name;
13 | gotPromise = true;
14 | });
15 |
16 | $scope.$on("didWebsiteLoad", function (event, website) {
17 | if (gotPromise) {
18 | scopeWatchService.websiteLoaded(self.website);
19 | }
20 | });
21 |
22 |
23 | $scope.$on("sceneTagSelected", function (event, object) {
24 |
25 | if (object['sendingObjectType'] == 'Website-Detail') {
26 |
27 | var originalObject = object['originalObject'];
28 | var selectedObject = object['selectedObject'];
29 | // alert(angular.toJson(object));
30 |
31 | var patchContent = {'scene_tags': ''};
32 | // Means the selected item does not exist in the db
33 | if (selectedObject.id == '-1') {
34 | var newItem = $rootScope.createNewItem("scene_tags", selectedObject.value);
35 |
36 | newItem.$save().then(function (res) {
37 | self.website.scene_tags_with_names.push(res);
38 | self.website.scene_tags.push(res.id);
39 |
40 | patchContent['scene_tags'] = self.website.scene_tags;
41 | Website.patch({websiteId: self.website.id}, patchContent)
42 | })
43 | } else {
44 |
45 | var objectIndex = helperService.getObjectIndexFromArrayOfObjects(selectedObject, self.website.scene_tags_with_names);
46 |
47 | if (objectIndex == null) {
48 | self.website.scene_tags_with_names.push(selectedObject);
49 | self.website.scene_tags.push(selectedObject.id);
50 | patchContent['scene_tags'] = self.website.scene_tags;
51 | Website.patch({websiteId: self.website.id}, patchContent)
52 |
53 | }
54 | }
55 |
56 |
57 | }
58 |
59 |
60 | // self.sceneTagSelect(sceneTag['selectedObject']);
61 | });
62 |
63 |
64 | self.modifyWebsiteAlias = function (website) {
65 |
66 | var patchContent = {'website_alias': website.website_alias};
67 | alert(angular.toJson(patchContent));
68 | patchWebsite(website, patchContent)
69 |
70 |
71 | };
72 |
73 | var patchWebsite = function (website_to_patch, patchContent) {
74 | Website.patch({websiteId: website_to_patch.id}, patchContent)
75 | };
76 |
77 |
78 | self.removeSceneTag = function (sceneTag) {
79 |
80 | var ans = helperService.removeObjectFromArrayOfObjects(sceneTag,self.website.scene_tags_with_names);
81 | var patchContent = {'scene_tags': ans['resId']};
82 | self.website.scene_tags_with_names = ans['resObject'];
83 |
84 | Website.patch({websiteId: self.website.id}, patchContent)
85 |
86 |
87 |
88 |
89 | };
90 |
91 | self.update = function () {
92 | Website.update({websiteId: self.website.id}, self.website)
93 | }
94 |
95 | }
96 | ]
97 | });
--------------------------------------------------------------------------------
/videos/static/js/app/settings/settings.template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
11 |
12 |
13 |
21 |
22 |
30 |
39 |
40 |
41 |
50 |
51 |
52 |
53 |
62 |
63 |
64 | Current Root Media Paths:
65 |
75 |
76 |
77 | - {{ folder.name }}
78 |
88 |
98 |
99 |
100 |
101 |
--------------------------------------------------------------------------------
/videos/static/js/app/actor-list/actor-list.template.html:
--------------------------------------------------------------------------------
1 |
22 |
23 |
24 |
25 |
26 |
101 |
102 |
120 |
121 |
122 |
123 |
124 |
--------------------------------------------------------------------------------
/videos/static/js/app/scene-tag-list/scene-tag-list.component.js:
--------------------------------------------------------------------------------
1 | // Register `phoneList` component, along with its associated controller and template
2 | angular.module('sceneTagList').component('sceneTagList', {
3 | // Note: The URL is relative to our `index.html` file
4 | templateUrl: 'static/js/app/scene-tag-list/scene-tag-list.template.html',
5 | bindings: {
6 | mainPage: '='
7 | },
8 | controller: ['$scope', 'SceneTag', 'scopeWatchService', 'pagerService', 'helperService',
9 | function SceneTagListController($scope, SceneTag, scopeWatchService, pagerService, helperService) {
10 |
11 | var self = this;
12 | var didSectionListWrapperLoad = false;
13 | // self.tags = [];
14 | self.pageType = 'SceneTag';
15 |
16 |
17 |
18 | self.nextPage = function (currentPage) {
19 |
20 |
21 | var input = {
22 | currentPage: currentPage,
23 | pageType: self.pageType,
24 | scene: self.scene,
25 | searchTerm: self.searchTerm,
26 | searchField: self.searchField,
27 | sortBy: self.sortBy
28 |
29 | };
30 |
31 | self.actorsToadd = pagerService.getNextPage(input);
32 |
33 | self.actorsToadd.$promise.then(function (res) {
34 |
35 | // self.actorsToadd = res[0];
36 |
37 | var paginationInfo = {
38 | pageType: input.pageType,
39 | pageInfo: res[1]
40 | };
41 |
42 | scopeWatchService.paginationInit(paginationInfo);
43 |
44 | self.tags = helperService.resourceToArray(res[0]);
45 |
46 |
47 | });
48 |
49 |
50 | };
51 |
52 |
53 | // if (self.mainPage) {
54 | // console.log("main page is true! + " + self.mainPage);
55 | // self.nextPage(0);
56 | // }
57 |
58 | $scope.$on("sceneLoaded", function (event, scene) {
59 | self.scene = scene;
60 | self.nextPage(0);
61 |
62 |
63 | });
64 |
65 | $scope.$on("paginationChange", function (event, pageInfo) {
66 | if (pageInfo.pageType == self.pageType){
67 | self.nextPage(pageInfo.page)
68 | }
69 |
70 |
71 | });
72 |
73 |
74 | $scope.$on("addSceneTagToList", function (event, sceneTag) {
75 | self.tags.push(sceneTag)
76 | });
77 |
78 | $scope.$on("searchTermChanged", function (event, searchTerm) {
79 | if (searchTerm['sectionType'] == 'SceneTagList'){
80 | self.tags = [];
81 | self.searchTerm = searchTerm['searchTerm'];
82 | self.searchField = searchTerm['searchField'];
83 | self.nextPage(0);
84 | }
85 |
86 |
87 | });
88 |
89 | $scope.$on("sortOrderChanged", function (event, sortOrder) {
90 | if (sortOrder['sectionType'] == 'SceneTagList'){
91 | console.log("Sort Order Changed!");
92 | self.tags = [];
93 | self.sortBy = sortOrder['sortBy'];
94 | if (sortOrder.mainPage == undefined || sortOrder.mainPage == true ) {
95 | self.nextPage(0);
96 | }
97 | didSectionListWrapperLoad = true;
98 | }
99 |
100 | });
101 |
102 | if (!didSectionListWrapperLoad) {
103 | scopeWatchService.didSectionListWrapperLoaded('SceneTagList')
104 | }
105 |
106 |
107 | self.deleteSceneTag = function (tagToDelete) {
108 | // alert("delete scene tag was clicked!");
109 | if (angular.isObject(self.scene)) {
110 | // self.pk.splice(self.pk.indexOf(aliasToDelete.id), 1);
111 | // alert(angular.toJson(self.actor.actor_tags));
112 | // alert(angular.toJson(tagToDelete));
113 | // alert(angular.toJson(self.actor.actor_tags.indexOf(tagToDelete.id)));
114 |
115 | var res = helperService.removeObjectFromArrayOfObjects(tagToDelete,self.tags);
116 |
117 | console.log(res['resId']);
118 | self.scene.scene_tags = res['resId'];
119 | scopeWatchService.sceneChanged(self.scene);
120 |
121 | self.tags = res['resObject'];
122 |
123 |
124 | // self.actor.actor_tags.splice(self.actor.actor_tags.indexOf(tagToDelete.id,1));
125 | // alert(angular.toJson(self.actor.actor_tags));
126 | }
127 | };
128 |
129 | self.deleteSceneTagFromDb = function (tagToDelete) {
130 |
131 | SceneTag.remove({sceneTagId: tagToDelete.id});
132 |
133 | var ans = helperService.removeObjectFromArrayOfObjects(tagToDelete,self.tags);
134 |
135 | self.tags = ans['resObject'];
136 |
137 | }
138 |
139 | }
140 | ]
141 | });
--------------------------------------------------------------------------------
/videos/static/js/app/website-list/website-list.component.js:
--------------------------------------------------------------------------------
1 | // Register `phoneList` component, along with its associated controller and template
2 | angular.module('websiteList').component('websiteList', {
3 | // Note: The URL is relative to our `index.html` file
4 | templateUrl: 'static/js/app/website-list/website-list.template.html',
5 | bindings: {
6 | mainPage: '='
7 | },
8 | controller: ['Website', '$scope', 'pagerService', 'scopeWatchService', 'helperService',
9 |
10 | function websiteListController(Website, $scope, pagerService, scopeWatchService, helperService) {
11 | // this.websites = Website.query();
12 | // this.orderProp = 'name';
13 |
14 |
15 | var self = this;
16 | var didSectionListWrapperLoad = false;
17 | self.pageType = 'Website';
18 |
19 |
20 | self.nextPage = function (currentPage) {
21 |
22 |
23 | var input = {
24 | currentPage: currentPage,
25 | pageType: self.pageType,
26 | scene: self.scene,
27 | searchTerm: self.searchTerm,
28 | searchField: self.searchField,
29 | sortBy: self.sortBy
30 | };
31 |
32 | self.actorsToadd = pagerService.getNextPage(input);
33 | if (self.actorsToadd != undefined) {
34 | self.actorsToadd.$promise.then(function (res) {
35 |
36 | // self.actorsToadd = res[0];
37 |
38 | var paginationInfo = {
39 | pageType: input.pageType,
40 | pageInfo: res[1]
41 | };
42 |
43 | scopeWatchService.paginationInit(paginationInfo);
44 |
45 | self.websites = helperService.resourceToArray(res[0]);
46 |
47 |
48 | });
49 | }
50 |
51 | };
52 |
53 |
54 | // if (self.mainPage) {
55 | // console.log("main page is true! + " + self.mainPage);
56 | // self.nextPage(0);
57 | // }
58 |
59 | $scope.$on("sceneLoaded", function (event, scene) {
60 | self.scene = scene;
61 | self.nextPage(0);
62 |
63 |
64 | });
65 |
66 | $scope.$on("paginationChange", function (event, pageInfo) {
67 | if (pageInfo.pageType == self.pageType){
68 | self.nextPage(pageInfo.page)
69 | }
70 | });
71 |
72 | $scope.$on("addWebsiteToList", function (event, website) {
73 | self.websites.push(website)
74 |
75 |
76 | });
77 |
78 | $scope.$on("searchTermChanged", function (event, searchTerm) {
79 | if (searchTerm['sectionType'] == 'WebsiteList'){
80 | self.websites = [];
81 | self.searchTerm = searchTerm['searchTerm'];
82 | self.searchField = searchTerm['searchField'];
83 | self.nextPage(0);
84 | }
85 |
86 |
87 |
88 | });
89 |
90 | $scope.$on("sortOrderChanged", function (event, sortOrder) {
91 | if (sortOrder['sectionType'] == 'WebsiteList'){
92 | console.log("Sort Order Changed!");
93 | self.websites = [];
94 | self.sortBy = sortOrder['sortBy'];
95 | if (sortOrder.mainPage == undefined || sortOrder.mainPage == true ) {
96 | self.nextPage(0);
97 | }
98 | didSectionListWrapperLoad = true;
99 | }
100 |
101 | });
102 |
103 | if (!didSectionListWrapperLoad) {
104 | scopeWatchService.didSectionListWrapperLoaded('WebsiteList')
105 | }
106 |
107 |
108 | self.removeWebsiteFromScene = function (siteToDelete) {
109 | if (angular.isObject(self.scene)) {
110 | // self.pk.splice(self.pk.indexOf(aliasToDelete.id), 1);
111 | // alert(angular.toJson(self.actor.actor_tags));
112 | // alert(angular.toJson(tagToDelete));
113 | // alert(angular.toJson(self.actor.actor_tags.indexOf(tagToDelete.id)));
114 | var res = helperService.removeObjectFromArrayOfObjects(siteToDelete, self.websites);
115 |
116 | self.scene.websites = res['resId'];
117 | self.websites = res['resObject'];
118 |
119 | scopeWatchService.sceneChanged(self.scene);
120 |
121 | // self.actor.actor_tags.splice(self.actor.actor_tags.indexOf(tagToDelete.id,1));
122 | // alert(angular.toJson(self.actor.actor_tags));
123 | }
124 | };
125 |
126 | self.deleteWebsiteFromDb = function (siteToDelete) {
127 |
128 | Website.remove({websiteId: siteToDelete.id});
129 |
130 | var ans = helperService.removeObjectFromArrayOfObjects(siteToDelete,self.websites);
131 |
132 | self.websites = ans['resObject'];
133 |
134 | }
135 |
136 | }
137 | ]
138 | });
--------------------------------------------------------------------------------
/videos/urls.py:
--------------------------------------------------------------------------------
1 | from django.conf.urls import url
2 |
3 | from . import views
4 | from .models import Actor
5 |
6 | # REST FRAMEWORK IMPORTS
7 | from rest_framework.urlpatterns import format_suffix_patterns
8 |
9 |
10 | app_name = 'videos'
11 |
12 | urlpatterns = [
13 | # /videos/
14 | # url(r'^$', views.index, name='index'),
15 | #
16 | # # /videos/scenes
17 | # url(r'^scenes/$', views.scenes, name='scenes'),
18 | #
19 | # # /videos/actors
20 | # url(r'^actors/$', views.actors, name='actors'),
21 | #
22 | # # /videos/scenes/[id]
23 | # url(r'^scenes/(?P[0-9]+)/$', views.SceneDetails.as_view(), name='scene-details'),
24 | #
25 | # # /videos/actors/[id]
26 | # url(r'^actors/(?P[0-9]+)/$', views.ActorDetails.as_view(), name='actor-details'),
27 | #
28 | # # /videos/actors/[id]/tags
29 | # url(r'^actors/(?P[0-9]+)/tag/$', views.actor_add_tag, name='actor-add-tag'),
30 | #
31 | # # /videos/scenes/add
32 | # url(r'^scenes/add/$', views.add_scenes, name='scenes-add'),
33 | #
34 | # # /videos/scenes/add/form
35 | # url(r'^scenes/add/form$', views.scenes_add_walker, name='scenes-add-walker'),
36 | #
37 | # # /videos/actors/add/form
38 | # url(r'^actors/add-actor/form$', views.ActorAdd.as_view(model=Actor, success_url="/videos/actors"),
39 | # name='actors-add-form'),
40 | #
41 | # # /videos/actors/add/
42 | # url(r'^actors/add$', views.actors_add, name='actors-add'),
43 | # # /videos/actors/add/logic
44 | # url(r'^a/actors/add/logic$', views.actors_add_logic, name='actors-add-logic'),
45 | #
46 | # # /videos/actors/tags/
47 | # url(r'^actors/tags$', views.actors_tags, name='actors-tags'),
48 | #
49 | # # /videos/actors/tags/
50 | # url(r'^scene/tags$', views.scene_tags, name='scenes-tags'),
51 | #
52 | # # /videos/websites/
53 | # url(r'^websites/$', views.websites, name='websites'),
54 | #
55 | # # /videos/websites/details/id
56 | # url(r'^websites/details/(?P[0-9]+)/$', views.website_details, name='websites-details'),
57 | #
58 | # # /videos/actors/tags//details
59 | # url(r'^actors/tags/(?P[0-9]+)/details/$', views.actors_tag_details, name='actor-tag-details'),
60 | #
61 | # # /videos/actors/tags//details
62 | # url(r'^scenes/tags/(?P[0-9]+)/details/$', views.scenes_tag_details, name='scene-tag-details'),
63 | #
64 | # # /vidoes/scenes/[id]/add-actor-to-scene
65 | # url(r'^scenes/(?P[0-9]+)/add_actor$', views.scene_details, name='scene-add-actor'),
66 | #
67 | # # /vidoes/ (actor autocomplete)
68 | # url(r'^actor-autocomplete/$', views.ActorAutocomplete.as_view(create_field='name'), name='actor-autocomplete'),
69 | #
70 | # url(r'^actor-alias-autocomplete/$', views.ActorAliasAutocomplete.as_view(create_field='name'),
71 | # name='actor-alias-autocomplete'),
72 | #
73 | # # /vidoes/ (actor tag autocomplete)
74 | # url(r'^actor-tag-autocomplete/$', views.ActorTagsAutocomplete.as_view(create_field='name'),
75 | # name='actor-tag-autocomplete'),
76 | #
77 | # # /vidoes/ (scene tag autocomplete)
78 | # url(r'^scene-tag-autocomplete/$', views.SceneTagsAutocomplete.as_view(create_field='name'),
79 | # name='scene-tag-autocomplete'),
80 | #
81 | # # /vidoes/ (website autocomplete)
82 | # url(r'^website-autocomplete/$', views.WebsiteAutocomplete.as_view(create_field='name'),
83 | # name='website-autocomplete'),
84 | #
85 | # # /scrape/tmdb/ scrape actor with tmdb
86 | # url(r'^scrape/tmdb/(?P[0-9]+)/$', views.scrape_actor_tmdb,
87 | # name='scrape-actor-tmdb'),
88 | #
89 | # # /scrape/freeones/ scrape actor with tmdb
90 | # url(r'^scrape/freeones/(?P[0-9]+)/$', views.scrape_actor_freeones,
91 | # name='scrape-actor-freeones'),
92 | #
93 | # url(r'^play/scene/(?P[0-9]+)/$', views.play_scene,
94 | # name='play-scene'),
95 | #
96 | # url(r'^clean-library/$', views.clean_library,
97 | # name='clean-library'),
98 | #
99 | # url(r'^settings/$', views.settings, name='settings'),
100 | #
101 | # url(r'^scan-all-scenes/$', views.scan_all_scenes, name='scan_all_scenes'),
102 | #
103 | # url(r'^folders/$', views.folder_view_tree, name='folder-view-tree'),
104 | #
105 | # url(r'^folder/(?P-{0,1}[0-9]+)/$', views.folder_view, name='folder-view'),
106 |
107 | # REST-FRAMEWORK-VIEWS
108 | #
109 | # url(r'^rest/$', views.api_root),
110 | #
111 | # url(r'^rest/actor-alias/',
112 | # views.ActorAliasListRest.as_view(),
113 | # name='actor-alias-list-rest'),
114 | #
115 | # url(r'^rest/actors/',
116 | # views.ActorListRest.as_view(),
117 | # name='actors-list-rest'),
118 | #
119 | # url(r'^rest/actor-alias/details/(?P[0-9]+)/', views.ActorAliasDetailsRest.as_view(),
120 | # name='actor-alias-details-rest'),
121 | #
122 | # url(r'^rest/actor/details/(?P[0-9]+)/$',
123 | # views.ActorDetailsRest.as_view(),
124 | # name='actor-details-rest'),
125 | # url(r'^rest/actor-alias/details/(?P[0-9]+)/html',
126 | # views.ActorAliasHTMLRest.as_view(),
127 | # name='actor-alias-details-rest'),
128 |
129 | ]
130 |
131 | urlpatterns = format_suffix_patterns(urlpatterns)
132 |
--------------------------------------------------------------------------------
/videos/static/js/app/actor-tag-list/actor-tag-list.component.js:
--------------------------------------------------------------------------------
1 | // Register `phoneList` component, along with its associated controller and template
2 | angular.module('actorTagList').component('actorTagList', {
3 | // Note: The URL is relative to our `index.html` file
4 | templateUrl: 'static/js/app/actor-tag-list/actor-tag-list.template.html',
5 | bindings: {
6 | mainPage: '='
7 | },
8 | controller: ['$scope', 'ActorTag', 'pagerService', 'scopeWatchService', 'helperService',
9 | function ActorTagListController($scope, ActorTag, pagerService, scopeWatchService, helperService) {
10 |
11 | // this.tags = ActorTag.query();
12 |
13 |
14 | var self = this;
15 | var didSectionListWrapperLoad = false;
16 | self.pageType = 'ActorTag';
17 |
18 |
19 | self.nextPage = function (currentPage) {
20 |
21 |
22 | var input = {
23 | currentPage: currentPage,
24 | pageType: self.pageType,
25 | actor: self.actor,
26 | searchTerm: self.searchTerm,
27 | searchField: self.searchField,
28 | sortBy: self.sortBy
29 | };
30 |
31 | self.actorsToadd = pagerService.getNextPage(input);
32 | if (self.actorsToadd != undefined) {
33 | self.actorsToadd.$promise.then(function (res) {
34 |
35 | // self.actorsToadd = res[0];
36 |
37 | var paginationInfo = {
38 | pageType: input.pageType,
39 | pageInfo: res[1]
40 | };
41 |
42 | scopeWatchService.paginationInit(paginationInfo);
43 |
44 | self.tags = helperService.resourceToArray(res[0]);
45 |
46 |
47 | });
48 | }
49 |
50 | };
51 |
52 | // if (self.mainPage) {
53 | // console.log("main page is true! + " + self.mainPage);
54 | // self.nextPage(0);
55 | // }
56 |
57 |
58 | $scope.$on("actorLoaded", function (event, actor) {
59 | self.actor = actor;
60 |
61 | self.nextPage(0);
62 |
63 |
64 | });
65 |
66 | $scope.$on("paginationChange", function (event, pageInfo) {
67 | if (pageInfo.pageType == self.pageType) {
68 | self.nextPage(pageInfo.page)
69 | }
70 |
71 |
72 | });
73 |
74 | $scope.$on("addActorTagToList", function (event, actorTag) {
75 | self.tags.push(actorTag)
76 |
77 |
78 | });
79 |
80 | $scope.$on("searchTermChanged", function (event, searchTerm) {
81 | if (searchTerm['sectionType'] == 'ActorTagList') {
82 | self.tags = [];
83 | self.searchTerm = searchTerm['searchTerm'];
84 | self.searchField = searchTerm['searchField'];
85 | self.nextPage(0);
86 | }
87 |
88 | });
89 |
90 | $scope.$on("sortOrderChanged", function (event, sortOrder) {
91 | if (sortOrder['sectionType'] == 'ActorTagList') {
92 | console.log("Sort Order Changed!");
93 | self.tags = [];
94 | self.sortBy = sortOrder['sortBy'];
95 | if (sortOrder.mainPage == undefined || sortOrder.mainPage == true) {
96 | self.nextPage(0);
97 | }
98 | didSectionListWrapperLoad = true;
99 | }
100 |
101 | });
102 |
103 | if (!didSectionListWrapperLoad) {
104 | scopeWatchService.didSectionListWrapperLoaded('ActorTagList')
105 | }
106 |
107 |
108 | self.deleteActorTag = function (tagToDelete) {
109 |
110 | if (angular.isObject(self.actor)) {
111 | // self.pk.splice(self.pk.indexOf(aliasToDelete.id), 1);
112 | // alert(angular.toJson(self.actor.actor_tags));
113 | // alert(angular.toJson(tagToDelete));
114 | // alert(angular.toJson(self.actor.actor_tags.indexOf(tagToDelete.id)));
115 |
116 |
117 | var res = helperService.removeObjectFromArrayOfObjects(tagToDelete, self.tags);
118 |
119 | // var resId = [];
120 | // var resObject = [];
121 | // for (i = 0; i < self.tags.length; i++) {
122 | // if (self.tags[i].id != tagToDelete.id) {
123 | // resId.push(self.tags[i].id);
124 | // resObject.push(self.tags[i]);
125 | // }
126 | // }
127 |
128 | self.actor.actor_tags = res['resId'];
129 |
130 |
131 | scopeWatchService.actorChaned(self.actor);
132 |
133 | self.tags = res['resObject'];
134 |
135 |
136 | // self.actor.actor_tags.splice(self.actor.actor_tags.indexOf(tagToDelete.id,1));
137 | // alert(angular.toJson(self.actor.actor_tags));
138 | }
139 | };
140 |
141 | self.deleteActorTagFromDb = function (tagToDelete) {
142 |
143 | // var index = helperService.getObjectIndexFromArrayOfObjects(tagToDelete,self.tags);
144 |
145 | ActorTag.remove({actorTagId: tagToDelete.id});
146 |
147 | var ans = helperService.removeObjectFromArrayOfObjects(tagToDelete, self.tags);
148 |
149 | self.tags = ans['resObject'];
150 |
151 |
152 | }
153 |
154 |
155 | }
156 | ]
157 | });
--------------------------------------------------------------------------------
/videos/tmdb_search.py:
--------------------------------------------------------------------------------
1 | import os
2 | import urllib
3 | from datetime import datetime
4 |
5 | import django
6 | import tmdbsimple as tmdb
7 | import urllib.request as urllib
8 | import videos.const as const
9 | import videos.aux_functions as aux
10 | from django.utils import timezone
11 | django.setup()
12 |
13 | from videos.models import Actor, ActorAlias
14 |
15 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "YAPO.settings")
16 |
17 | tmdb.API_KEY = '04308f6d1c14608e9f373b84ad0e4e4c'
18 |
19 | MEDIA_PATH = os.path.join('videos', 'media')
20 |
21 |
22 | def search_person(actor_in_question, alias, force):
23 | sucesss = False
24 | print("Looking for: " + actor_in_question.name)
25 | search = tmdb.Search()
26 | # response = search.person(query="Harmony Rose", include_adult='true')
27 | if not alias:
28 | response = search.person(query=actor_in_question.name, include_adult='true')
29 | else:
30 | response = search.person(query=alias.name, include_adult='true')
31 |
32 | for s in search.results:
33 | if s['adult']:
34 | sucesss = True
35 | # save image locally
36 | # urllib.urlretrieve("https://image.tmdb.org/t/p/original/" +
37 | # s['profile_path'], person_name + "Profile.jpg")
38 |
39 | if actor_in_question.id is None:
40 | actor_in_question.save()
41 | person = tmdb.People(str(s['id']))
42 | person_info = person.info()
43 |
44 | person_aka = person_info['also_known_as']
45 | if person_info['biography'] is not None:
46 | actor_in_question.description = person_info['biography']
47 | print("Added Description to: " + actor_in_question.name)
48 | else:
49 | actor_in_question.description = ""
50 | if not person_info['birthday'] == "":
51 | actor_in_question.date_of_birth = person_info['birthday']
52 | print("Added Birthday to: " + actor_in_question.name)
53 | if not actor_in_question.gender:
54 | person_gender = person_info['gender']
55 | if person_gender == 2:
56 | actor_in_question.gender = 'M'
57 | print("Added Gender to: " + actor_in_question.name)
58 | elif person_gender == 1:
59 | actor_in_question.gender = 'F'
60 | print("Added Gender to: " + actor_in_question.name)
61 | if person_info['homepage']:
62 | actor_in_question.official_pages = person_info['homepage']
63 | print("Added Homepage to: " + actor_in_question.name)
64 |
65 | actor_in_question.tmdb_id = person_info['id']
66 | actor_in_question.imdb_id = person_info['imdb_id']
67 |
68 | if actor_in_question.thumbnail == const.UNKNOWN_PERSON_IMAGE_PATH or force:
69 | if person_info['profile_path'] is not None:
70 |
71 | picture_link = "https://image.tmdb.org/t/p/original/" + person_info['profile_path']
72 |
73 | aux.save_actor_profile_image_from_web(picture_link,actor_in_question,force)
74 |
75 | # save_path = os.path.join(MEDIA_PATH,
76 | # 'actor/' + actor_in_question.name + '/profile/')
77 | # if not os.path.exists(save_path):
78 | # os.makedirs(save_path)
79 | #
80 | # save_file_name = os.path.join(save_path, 'profile.jpg')
81 | # if not os.path.isfile(save_file_name):
82 | # urllib.urlretrieve(picture_link, save_file_name)
83 | #
84 | # rel_path = os.path.relpath(save_file_name, start='videos')
85 | # as_uri = urllib.pathname2url(rel_path)
86 | #
87 | # actor_in_question.thumbnail = as_uri
88 |
89 | for aka in person_aka:
90 | aka = aka.lstrip()
91 | aka = aka.rstrip()
92 | alias = ActorAlias()
93 | alias.name = aka
94 | # alias.actor = actor_in_question
95 | if not actor_in_question.actor_aliases.filter(name=aka):
96 | try:
97 | alias.save()
98 | actor_in_question.actor_aliases.add(alias)
99 | except django.db.IntegrityError as e:
100 | print(e)
101 |
102 | actor_in_question.save()
103 | actor_in_question.last_lookup = datetime.now()
104 | actor_in_question.save()
105 | break
106 |
107 | if not sucesss:
108 | print ("Actor: {} could not be found on TMDb".format(actor_in_question.name))
109 | return sucesss
110 |
111 |
112 | def search_alias(actor_in_question, alias, force):
113 | success = False
114 | if force:
115 | success = search_person(actor_in_question, alias,force)
116 | elif not actor_in_question.last_lookup:
117 | success = search_person(actor_in_question, alias,force)
118 | return success
119 |
120 |
121 | def search_person_with_force_flag(actor_in_question, force):
122 | success = False
123 | print("Looking for: " + actor_in_question.name)
124 | if force:
125 | print("Force flag is true, ignoring last lookup")
126 | success = search_person(actor_in_question, None, force)
127 | elif not actor_in_question.last_lookup:
128 | print("Actor: " + actor_in_question.name + " was not yet searched... Searching now!")
129 | success = search_person(actor_in_question, None, force)
130 |
131 | return success
132 |
133 |
134 | def main():
135 | # os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myproject.settings")
136 | actors = Actor.objects.all()
137 | for actor in actors:
138 | actor.name = actor.name.rstrip()
139 |
140 | search_person_with_force_flag(actor, False)
141 |
142 |
143 | if __name__ == "__main__":
144 | main()
145 |
--------------------------------------------------------------------------------
/YAPO/urls.py:
--------------------------------------------------------------------------------
1 | """YAPO URL Configuration
2 |
3 | The `urlpatterns` list routes URLs to views. For more information please see:
4 | https://docs.djangoproject.com/en/1.9/topics/http/urls/
5 | Examples:
6 | Function views
7 | 1. Add an import: from my_app import views
8 | 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
9 | Class-based views
10 | 1. Add an import: from other_app.views import Home
11 | 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
12 | Including another URLconf
13 | 1. Import the include() function: from django.conf.urls import url, include
14 | 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
15 | """
16 | from django.conf.urls import url, include
17 | from django.contrib import admin
18 | from rest_framework.routers import DefaultRouter
19 | from django.views.static import serve
20 |
21 | from videos import views
22 | from django.conf import settings
23 | from django.conf.urls.static import static
24 | import json
25 | from rest_framework.urlpatterns import format_suffix_patterns
26 |
27 | from videos.models import ActorTag, SceneTag
28 |
29 | from datetime import datetime
30 | import videos.const
31 | import videos.aux_functions
32 | import YAPO.settings
33 |
34 | # actor_alias_list = ActorAliasViewSet.as_view({
35 | # 'get': 'list',
36 | # 'post': 'create'
37 | # })
38 | #
39 | #
40 | # actor_alias_detail = ActorAliasViewSet.as_view({
41 | # 'get': 'retrieve',
42 | # 'put': 'update',
43 | # 'patch': 'partial_update',
44 | # 'delete': 'destroy'
45 | # })
46 | #
47 | # actor_list = ActorViewSet.as_view({
48 | # 'get': 'list',
49 | # 'post': 'create'
50 | # })
51 | #
52 | # actor_detail = ActorViewSet.as_view({
53 | # 'get': 'retrieve',
54 | # 'put': 'update',
55 | # 'patch': 'partial_update',
56 | # 'delete': 'destroy'
57 | # })
58 |
59 |
60 |
61 | # Create a router and register our viewsets with it.
62 | router = DefaultRouter()
63 | router.register(r'actor-alias', views.ActorAliasViewSet)
64 | router.register(r'actor', views.ActorViewSet)
65 | router.register(r'actor-tag', views.ActorTagViewSet)
66 | router.register(r'scene', views.SceneViewSet)
67 | router.register(r'scene-tag', views.SceneTagViewSet)
68 | router.register(r'website', views.WebsiteViewSet)
69 | router.register(r'folder', views.FolderViewSet)
70 | router.register(r'folder-local', views.LocalSceneFoldersViewSet)
71 | router.register(r'playlist', views.PlaylistViewSet)
72 | # router.register(r'^upload/(?P[^/]+)', views.FileUploadView.as_view())
73 |
74 |
75 | urlpatterns = [
76 | url(r'^admin/', admin.site.urls),
77 | url(r'^videos/', include('videos.urls')),
78 | url(r'^api/', include(router.urls)),
79 | url(r'^$', views.angualr_index, name='angular-index'),
80 | url(r'^upload/', views.AssetAdd.as_view()),
81 | url(r'^scrape-actor/', views.ScrapeActor.as_view()),
82 | url(r'^play-scene/', views.play_in_vlc),
83 | url(r'^open-folder/', views.OpenFolder.as_view()),
84 | url(r'^add-items/', views.AddItems.as_view()),
85 | url(r'^settings/', views.settings),
86 | url(r'^ffmpeg/', views.ffmpeg),
87 | url(r'^tag-multiple-items/', views.tag_multiple_items),
88 |
89 |
90 |
91 | ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
92 |
93 | # urlpatterns = format_suffix_patterns(urlpatterns, allowed=['json'])
94 |
95 | # Startup script checks settings.json and creates it if it doesn't exist
96 | setting_version = videos.const.SETTINGS_VERSION
97 | current_setting_version = 0
98 |
99 | default_dict = {'settings_version': setting_version, 'vlc_path': "", 'last_all_scene_tag': ""}
100 | need_update = False
101 |
102 | try:
103 | f = open('settings.json', 'r')
104 | x = f.read()
105 |
106 | if x == "":
107 | need_update = True
108 | f.close()
109 | print("Setting.json is empty")
110 | f = open('settings.json', 'w')
111 | f.write(json.dumps(default_dict))
112 | f.close()
113 |
114 | else:
115 | # print(x)
116 |
117 | settings_content = json.loads(x)
118 | f.close()
119 |
120 | if ('settings_version' not in settings_content) or (
121 | int(settings_content['settings_version']) < setting_version):
122 |
123 | current_setting_version = int(settings_content['settings_version'])
124 | if current_setting_version < 2:
125 | need_update = True
126 | for x in settings_content:
127 | if x in default_dict:
128 | default_dict[x] = settings_content[x]
129 |
130 | # default_dict['settings_version'] = SETTINGS_VERSION
131 |
132 | f = open('settings.json', 'w')
133 | f.write(json.dumps(default_dict))
134 | f.close()
135 |
136 | f = open('settings.json', 'r')
137 | x = f.read()
138 | settings_content = json.loads(x)
139 |
140 | print(settings_content['vlc_path'])
141 | videos.const.VLC_PATH = settings_content['vlc_path']
142 | if settings_content['last_all_scene_tag'] != "":
143 | # 2016-08-14 18:03:10.153443
144 | videos.const.LAST_ALL_SCENE_TAG = datetime.strptime(settings_content['last_all_scene_tag'],
145 | "%Y-%m-%d %H:%M:%S")
146 | print("Last full scene tagging : {}".format(videos.const.LAST_ALL_SCENE_TAG))
147 |
148 | f.close()
149 |
150 | except FileNotFoundError:
151 | f = open('settings.json', 'w')
152 | f.close()
153 |
154 | f = open('settings.json', 'w')
155 | f.write(json.dumps(default_dict))
156 | f.close()
157 |
158 | if need_update:
159 | if videos.aux_functions.actor_folder_from_name_to_id():
160 | f = open('settings.json', 'r')
161 | x = f.read()
162 | settings_content = json.loads(x)
163 | f.close()
164 | settings_content['settings_version'] = setting_version
165 |
166 | f = open('settings.json', 'w')
167 | f.write(json.dumps(settings_content))
168 | f.close()
169 |
--------------------------------------------------------------------------------
/videos/static/css/angular/styles.css:
--------------------------------------------------------------------------------
1 | body {
2 | padding-top: 20px;
3 | }
4 |
5 | #actor-list-row{
6 | white-space: nowrap;
7 | list-style: none;
8 |
9 | }
10 |
11 | #actor-list-row ul{
12 | white-space: nowrap;
13 | list-style: none;
14 | align-content: center;
15 | overflow-y: visible;
16 | float: left;
17 | }
18 | #actor-list-row li{
19 | display: inline-block;
20 | list-style: none;
21 | margin: 1em;
22 |
23 |
24 | }
25 |
26 | #actor-list-grid img{
27 | border: solid black 2px;
28 |
29 |
30 | }
31 |
32 | #scene-list-grid img{
33 | border: solid black 2px;
34 | margin: 0.5em;
35 |
36 |
37 | }
38 |
39 |
40 |
41 |
42 |
43 | .actor-detail {
44 |
45 | clear: both;
46 | border-spacing: 0.2em;
47 | float: right;
48 | width: 40%;
49 | margin: 2em;
50 | background: whitesmoke;
51 |
52 | }
53 |
54 |
55 |
56 | .actor-detail li {
57 | text-align: right;
58 | list-style-position: outside;
59 | list-style: none;
60 |
61 | }
62 |
63 | .actor-detail table,tr, th, td {
64 | /*border: 1px solid black;*/
65 | border-collapse: collapse;
66 | }
67 |
68 | .actor-detail th, td {
69 | padding: 15px;
70 | }
71 |
72 | .alright {
73 | text-align: right;
74 | }
75 |
76 | .alcenter{
77 |
78 | text-align: center;
79 |
80 | }
81 |
82 | .actor-dsc {
83 | margin: 50px;
84 | float: left;
85 | }
86 |
87 | .actors {
88 | list-style: none;
89 | }
90 |
91 | .actors li {
92 | clear: both;
93 | height: 150px;
94 | padding-top: 15px;
95 | }
96 |
97 | .scenes {
98 | list-style: none;
99 | }
100 |
101 | .scenes li {
102 | clear: both;
103 | height: 250px;
104 | padding-top: 15px;
105 | }
106 |
107 | /* View: Phone detail */
108 | .sample-video {
109 | /*background-color: white;*/
110 | /*border: 1px solid black;*/
111 | float: right;
112 | /*height: 400px;*/
113 | /*margin-bottom: 2em;*/
114 | margin-right: 3em;
115 | /*padding: 2em;*/
116 | /*width: 720px;*/
117 | }
118 |
119 | .actor-thumb {
120 | /*background-color: white;*/
121 | border: 2px solid black;
122 |
123 | /*height: 400px;*/
124 | margin: auto;
125 | /*margin-bottom: 2em;*/
126 | /*margin-right: 3em;*/
127 | /*padding: 2em;*/
128 | margin-top: 1.0em;
129 | /*width: 400px;*/
130 | /*padding: 10px;*/
131 | /*float: left;*/
132 | }
133 |
134 | .dbFolders {
135 | border: 1px solid black;
136 | padding: 1em;
137 | background-color: #b2dba1;
138 | }
139 |
140 | .scene-list {
141 | /*height: 1900px;*/
142 | /*border: 1px solid black;*/
143 | padding: 1em;
144 | margin-left: 3em;
145 | max-height: 60em;
146 | width: 85%;
147 | float: inherit;
148 |
149 | /*background-color: aquamarine;*/
150 | }
151 |
152 | .scene-info {
153 |
154 | }
155 |
156 | .actor-bio {
157 | /*border: 0.1em solid black;*/
158 | /*background: whitesmoke;*/
159 | /*margin: 2em;*/
160 | /*width: 35.5em;*/
161 | text-align: justify;
162 | /*overflow: scroll;*/
163 | /*float: right;*/
164 | /*padding: 1.1em;*/
165 |
166 | /*height: 20em;*/
167 | }
168 |
169 | /*.actor-thumbs {*/
170 | /*list-style: none;*/
171 | /*margin: 0;*/
172 | /*}*/
173 |
174 | .thumb {
175 | float: left;
176 | height: 100px;
177 | margin: -0.5em 1em 1.5em 0;
178 | padding-bottom: 1em;
179 | width: 100px;
180 | }
181 |
182 | .thumb-wide {
183 | float: left;
184 | /*height: 240px;*/
185 | /*padding-right: 1em;*/
186 | height: 180px;
187 | width: 320px;
188 |
189 | border: 0.2em solid black;
190 | }
191 |
192 |
193 | .on-hover-red-cursor-pointer:hover {
194 | color: red;
195 | cursor: pointer;
196 | }
197 |
198 | .on-hover-red-cursor-pointer a {
199 | /*text-decoration: none;*/
200 | color: black;
201 | }
202 |
203 | .on-hover-red-cursor-pointer a:link {
204 | text-decoration: none;
205 |
206 | }
207 |
208 | .on-hover-red-cursor-pointer a:hover {
209 | color: red;
210 |
211 | }
212 |
213 |
214 |
215 |
216 |
217 | .glyphicon-remove:hover {
218 | color: red;
219 | cursor: pointer;
220 | }
221 |
222 | .glyphicon-plus:hover {
223 | color: green;
224 | cursor: hand;
225 | }
226 |
227 | #right {
228 | overflow-y: scroll;
229 | }
230 |
231 | #big-scroll-item {
232 | height: 55em;
233 | overflow-y: scroll;
234 | }
235 |
236 | /* The square +/- buttons */
237 | .btn-xs {
238 | padding: 1px 5px;
239 | font-size: 12px;
240 | line-height: 1.5;
241 | border-radius: 3px;
242 | margin-bottom: 0.5em;
243 | }
244 |
245 | /*toggle button*/
246 | /* The switch - the box around the slider */
247 | .switch {
248 | position: relative;
249 | display: inline-block;
250 | width: 30px;
251 | height: 17px;
252 | /*left: 1em;*/
253 | bottom: -0.3em;
254 | margin-left: 0em;
255 | }
256 |
257 | .switch-header {
258 | position: relative;
259 | display: inline-block;
260 | width: 30px;
261 | height: 17px;
262 | /*left: 1em;*/
263 | bottom: -0.55em;
264 | margin-left: 0em;
265 | }
266 |
267 | /* Hide default HTML checkbox */
268 | .switch input {
269 | display: none;
270 | }
271 |
272 | .hidden-box {
273 | display: none;
274 | }
275 |
276 | /* The slider */
277 | .slider {
278 | position: absolute;
279 | cursor: pointer;
280 | top: 0;
281 | left: 0;
282 | right: 0;
283 | bottom: 0;
284 | background-color: #ccc;
285 | -webkit-transition: .4s;
286 | transition: .4s;
287 | }
288 |
289 | .slider:before {
290 | position: absolute;
291 | content: "";
292 | height: 12px;
293 | width: 12px;
294 | left: 2px;
295 | bottom: 2.5px;
296 | background-color: white;
297 | -webkit-transition: .4s;
298 | transition: .4s;
299 | }
300 |
301 | input:checked + .slider {
302 | background-color: #2196F3;
303 | }
304 |
305 | input:focus + .slider {
306 | box-shadow: 0 0 1px #2196F3;
307 | }
308 |
309 | input:checked + .slider:before {
310 | -webkit-transform: translateX(13px);
311 | -ms-transform: translateX(13px);
312 | transform: translateX(13px);
313 | }
314 |
315 | /* Rounded sliders */
316 | .slider.round {
317 | border-radius: 17px;
318 | }
319 |
320 | .slider.round:before {
321 | border-radius: 50%;
322 | }
323 |
324 | .video-box {
325 | float: right;
326 | }
--------------------------------------------------------------------------------
/videos/static/js/app/nav-bar/nav-bar.component.js:
--------------------------------------------------------------------------------
1 | angular.module('navBar', []).component('navBar', {
2 | // Note: The URL is relative to our `index.html` file
3 | templateUrl: 'static/js/app/nav-bar/nav-bar.template.html',
4 | bindings: {},
5 | controller: ['$scope', '$rootScope', 'Actor', 'SceneTag', 'Website', 'ActorTag', 'helperService', '$http','Playlist',
6 | function NavBarController($scope, $rootScope, Actor, SceneTag, Website, ActorTag, helperService, $http, Playlist ) {
7 |
8 | // Global function to create new item
9 | $rootScope.createNewItem = function (typeOfItemToAdd, newItemName) {
10 | var newItem;
11 | if (typeOfItemToAdd == 'actors') {
12 | newItem = new Actor();
13 | newItem.thumbnail = 'media/images/actor/Unknown/profile/profile.jpg'; //need to change this to a constant!
14 | newItem.scenes = [];
15 | } else if (typeOfItemToAdd == 'scene_tags') {
16 | newItem = new SceneTag();
17 | newItem.scenes = [];
18 | newItem.websites = [];
19 | } else if (typeOfItemToAdd == 'websites') {
20 | newItem = new Website;
21 | newItem.scenes = [];
22 | } else if (typeOfItemToAdd == 'actor_tags'){
23 | newItem = new ActorTag;
24 | newItem.actors = [];
25 | } else if (typeOfItemToAdd == 'playlists'){
26 | newItem = new Playlist;
27 | newItem.scenes = []
28 | }
29 |
30 | newItem.name = newItemName;
31 |
32 | return newItem
33 | };
34 |
35 | $rootScope.patchEntity = function (entityToPatchType, entityToPatchId, patchType, patchData, addOrRemove,
36 | multiple, permDelete, selectedScenes) {
37 |
38 | var type = {};
39 | type[patchType] = patchData;
40 |
41 | var itemsToUpdate = [];
42 | if (multiple) {
43 | itemsToUpdate = selectedScenes
44 | } else {
45 | itemsToUpdate.push(entityToPatchId)
46 | }
47 |
48 |
49 | // if (multiple) {
50 |
51 | $http.post('tag-multiple-items/', {
52 | params: {
53 | type: entityToPatchType,
54 | patchType: patchType,
55 | patchData: patchData,
56 | itemsToUpdate: itemsToUpdate,
57 | addOrRemove: addOrRemove,
58 | permDelete: permDelete
59 | }
60 | }).then(function (response) {
61 | console.log("Update finished successfully")
62 | }, function errorCallback(response) {
63 | alert("Something went wrong!");
64 | });
65 | };
66 |
67 | $rootScope.addItemToScene = function (scene, itemToAdd, typeOfItemToAdd) {
68 |
69 | if (scene[typeOfItemToAdd] == undefined) {
70 | scene[typeOfItemToAdd] = [];
71 | }
72 |
73 | var found = helperService.getObjectIndexFromArrayOfObjects(itemToAdd, scene[typeOfItemToAdd]);
74 |
75 | if (found == null) {
76 | scene[typeOfItemToAdd].push(itemToAdd);
77 | }
78 |
79 | if (typeOfItemToAdd == 'websites' && itemToAdd.scene_tags_with_names.length > 0) {
80 | for (var i = 0; i < itemToAdd.scene_tags_with_names.length; i++) {
81 | $rootScope.addItemToScene(scene, itemToAdd.scene_tags_with_names[i], 'scene_tags')
82 | }
83 | }
84 |
85 | if (typeOfItemToAdd == 'actors' && itemToAdd.actor_tags.length > 0) {
86 | for (var z = 0; z < itemToAdd.actor_tags.length; z++) {
87 | if (itemToAdd.actor_tags[z].scene_tags.length > 0){
88 | $rootScope.addItemToScene(scene, itemToAdd.actor_tags[z].scene_tags[0], 'scene_tags')
89 | }
90 |
91 | }
92 | }
93 |
94 | return scene
95 |
96 | };
97 |
98 | $rootScope.removeItemFromScene = function (scene, itemToRemove, typeOfItemToRemove) {
99 | var resId = [];
100 | var resObj = [];
101 |
102 | if (scene[typeOfItemToRemove] == undefined){
103 | scene[typeOfItemToRemove] = [];
104 | }
105 |
106 | for (var i = 0; i < scene[typeOfItemToRemove].length; i++) {
107 | if (itemToRemove.id != scene[typeOfItemToRemove][i].id) {
108 | resId.push(scene[typeOfItemToRemove][i].id);
109 | resObj.push(scene[typeOfItemToRemove][i]);
110 | }
111 | }
112 |
113 | scene[typeOfItemToRemove] = resObj;
114 |
115 | resObj = [];
116 |
117 |
118 | if (typeOfItemToRemove == 'websites' && itemToRemove.scene_tags_with_names.length > 0) {
119 | for (var k = 0; k < itemToRemove.scene_tags_with_names.length; k++) {
120 | $rootScope.removeItemFromScene(scene, itemToRemove.scene_tags_with_names[k], 'scene_tags')
121 | }
122 | }
123 |
124 | if (typeOfItemToRemove == 'actors' && itemToRemove.actor_tags.length > 0) {
125 | for (var z = 0; z < itemToRemove.actor_tags.length; z++) {
126 | if (itemToRemove.actor_tags[z].scene_tags.length > 0){
127 | $rootScope.removeItemFromScene(scene, itemToRemove.actor_tags[z].scene_tags[0], 'scene_tags')
128 | }
129 |
130 | }
131 | }
132 |
133 | return scene
134 | };
135 |
136 |
137 | }]
138 | });
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
--------------------------------------------------------------------------------
/YAPO/settings.py:
--------------------------------------------------------------------------------
1 | """
2 | Django settings for YAPO project.
3 |
4 | Generated by 'django-admin startproject' using Django 1.9.6.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/1.9/topics/settings/
8 |
9 | For the full list of settings and their values, see
10 | https://docs.djangoproject.com/en/1.9/ref/settings/
11 | """
12 |
13 | import os
14 | import json
15 | import videos.const
16 | # import videos.aux_functions
17 | from datetime import datetime
18 |
19 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
20 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
21 |
22 | # Quick-start development settings - unsuitable for production
23 | # See https://docs.djangoproject.com/en/1.9/howto/deployment/checklist/
24 |
25 | # SECURITY WARNING: keep the secret key used in production secret!
26 | SECRET_KEY = '0px^lshd1lsf6uq#%90lre3$iqkz9=i7a0ko2_83b$n@=&(*d5'
27 |
28 | # SECURITY WARNING: don't run with debug turned on in production!
29 | DEBUG = True
30 |
31 | ALLOWED_HOSTS = []
32 |
33 | # Application definition
34 |
35 | INSTALLED_APPS = [
36 | # 'dal',
37 | # 'dal_select2',
38 | 'django.contrib.admin',
39 | 'django.contrib.auth',
40 | 'django.contrib.contenttypes',
41 | 'django.contrib.sessions',
42 | 'django.contrib.messages',
43 | 'django.contrib.staticfiles',
44 | # 'selectable',
45 | 'videos.apps.VideosConfig',
46 | 'mptt',
47 | 'rest_framework'
48 | ]
49 |
50 | MIDDLEWARE_CLASSES = [
51 | 'django.middleware.security.SecurityMiddleware',
52 | 'django.contrib.sessions.middleware.SessionMiddleware',
53 | 'django.middleware.common.CommonMiddleware',
54 | 'django.middleware.csrf.CsrfViewMiddleware',
55 | 'django.contrib.auth.middleware.AuthenticationMiddleware',
56 | 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
57 | 'django.contrib.messages.middleware.MessageMiddleware',
58 | 'django.middleware.clickjacking.XFrameOptionsMiddleware',
59 | ]
60 |
61 | ROOT_URLCONF = 'YAPO.urls'
62 |
63 | TEMPLATES = [
64 | {
65 | 'BACKEND': 'django.template.backends.django.DjangoTemplates',
66 | 'DIRS': [],
67 | 'APP_DIRS': True,
68 | 'OPTIONS': {
69 | 'context_processors': [
70 | 'django.template.context_processors.debug',
71 | 'django.template.context_processors.request',
72 | 'django.contrib.auth.context_processors.auth',
73 | 'django.contrib.messages.context_processors.messages',
74 | 'django.template.context_processors.media',
75 | ],
76 | 'libraries': {
77 | # Adding this section should work around the issue. (https://github.com/pyinstaller/pyinstaller/issues/1717)
78 | # (This is for pyinstaller to recognize staticfiles tag
79 | 'staticfiles': 'django.templatetags.static',
80 | 'i18n': 'django.templatetags.i18n',
81 |
82 | },
83 | },
84 | },
85 | ]
86 |
87 | WSGI_APPLICATION = 'YAPO.wsgi.application'
88 |
89 | # Database
90 | # https://docs.djangoproject.com/en/1.9/ref/settings/#databases
91 |
92 | DATABASES = {
93 | 'default': {
94 | 'ENGINE': 'django.db.backends.sqlite3',
95 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
96 | }
97 | }
98 |
99 | # Password validation
100 | # https://docs.djangoproject.com/en/1.9/ref/settings/#auth-password-validators
101 |
102 | AUTH_PASSWORD_VALIDATORS = [
103 | {
104 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
105 | },
106 | {
107 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
108 | },
109 | {
110 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
111 | },
112 | {
113 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
114 | },
115 | ]
116 |
117 | # Internationalization
118 | # https://docs.djangoproject.com/en/1.9/topics/i18n/
119 |
120 | LANGUAGE_CODE = 'en-us'
121 |
122 | # TIME_ZONE = 'UTC'
123 |
124 | USE_I18N = True
125 |
126 | USE_L10N = True
127 |
128 | # USE_TZ = True
129 |
130 | # Static files (CSS, JavaScript, Images)
131 | # https://docs.djangoproject.com/en/1.9/howto/static-files/
132 |
133 | STATIC_ROOT = os.path.abspath(os.path.join(BASE_DIR, "videos/static"))
134 | STATIC_URL = '/static/'
135 |
136 |
137 | MEDIA_ROOT = os.path.abspath(os.path.join(BASE_DIR, 'videos/media'))
138 | MEDIA_URL = '/media/'
139 |
140 | # APPEND_SLASH = True
141 |
142 | REST_FRAMEWORK = {
143 | # Use Django's standard `django.contrib.auth` permissions,
144 | # or allow read-only access for unauthenticated users.
145 | # 'DEFAULT_PERMISSION_CLASSES': [
146 | # 'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
147 | # ]
148 | # 'PAGE_SIZE': 10
149 |
150 | #
151 | 'DEFAULT_PAGINATION_CLASS': 'YAPO.pagination.HeaderLimitOffsetPagination',
152 | 'PAGE_SIZE': 500
153 | }
154 | #
155 | # SETTINGS_VERSION = 1
156 | # default_dict = {'settings_version': '1', 'vlc_path': "", 'last_all_scene_tag': ""}
157 | # need_update = False
158 | # try:
159 | # f = open('settings.json', 'r')
160 | # x = f.read()
161 | #
162 | # if x == "":
163 | # need_update = True
164 | # f.close()
165 | # print("Setting.json is empty")
166 | #
167 | #
168 | #
169 | # f = open('settings.json', 'w')
170 | # f.write(json.dumps(default_dict))
171 | # f.close()
172 | #
173 | # else:
174 | # # print(x)
175 | #
176 | # settings_content = json.loads(x)
177 | # f.close()
178 | #
179 | # if ('settings_version' not in settings_content) or (
180 | # int(settings_content['settings_version']) < SETTINGS_VERSION):
181 | # need_update = True
182 | # for x in settings_content:
183 | # if x in default_dict:
184 | # default_dict[x] = settings_content[x]
185 | #
186 | # f = open('settings.json', 'w')
187 | # f.write(json.dumps(default_dict))
188 | # f.close()
189 | #
190 | # f = open('settings.json', 'r')
191 | # x = f.read()
192 | # settings_content = json.loads(x)
193 | #
194 | # print(settings_content['vlc_path'])
195 | # videos.const.VLC_PATH = settings_content['vlc_path']
196 | # if settings_content['last_all_scene_tag'] != "":
197 | # # 2016-08-14 18:03:10.153443
198 | # videos.const.LAST_ALL_SCENE_TAG = datetime.strptime(settings_content['last_all_scene_tag'], "%Y-%m-%d %H:%M:%S")
199 | # print("Last full scene tagging : {}".format(videos.const.LAST_ALL_SCENE_TAG))
200 | #
201 | # f.close()
202 | #
203 | # except FileNotFoundError:
204 | # f = open('settings.json', 'w')
205 | # f.close()
206 | #
207 | # f = open('settings.json', 'w')
208 | # f.write(json.dumps(default_dict))
209 | # f.close()
210 |
211 | # if need_update:
212 | # videos.aux_functions.actor_folder_from_name_to_id()
213 |
214 |
215 |
216 |
217 | # with open('settings.json', 'r+') as f:
218 | # print("contetns of setting.json" + f.read())
219 | # print(f.read())
220 | # print(f.readline())
221 | # # f.write("test")
222 | # f.close()
223 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 |
4 | ## 0.1.3 (2016-09-09)
5 |
6 | ### New
7 |
8 | * Folders added to Yapo in the 'add' menu are now logged and can be rescanned for new files in the 'settings' menu. This is not retroactive so folders added before this update will not be present in the settings menu. They will if one was to re-add them. [Curt Wagner]
9 |
10 | * Added option to bulk add comma separated websites and scene tags in the add page. [Curt Wagner]
11 |
12 | ### Changes
13 |
14 | * New experimental layout for Scene Detail page. [Shaun Clayton]
15 |
16 |
17 |
18 | ## 0.1.2 (2016-09-07)
19 |
20 | ### New
21 |
22 | * Added 'playlist' category. Scenes can now be added to custom lists, multiple scenes can be added in one go. Also same scene can be in multiple lists. Random play works with playlists. In addition to help keep track of randomly played scenes [Issue #43] every time the random play button is used, the played scene is added to an auto generated playlist called 'random plays'. [Curt Wagner]
23 |
24 | ### Changes
25 |
26 | * Added missing confirmation to delete scene(s) from disk function. [Shaun Clayton]
27 |
28 | Delete scenes from disk function now has secondary reminder confirmation for added prevention of accidental file deletion.
29 |
30 | ### Fix
31 |
32 | * [Issue #31] Fixed bug where incorrect input params were fed to the removeItem function in scene-list.component.js. [Curt Wagner]
33 |
34 |
35 |
36 | ## 0.1.1 (2016-09-05)
37 |
38 | ### New
39 |
40 | * Added play_count logging for scene_tags, actors and website upon playing a scene. Also added order by play count options for them. [Curt Wagner]
41 |
42 | ### Changes
43 |
44 | * Deprecated CHANGELOG.rst in favour of CHANGELOG.md. [Shaun Clayton]
45 |
46 |
47 | ## 0.1.0 (2016-09-04)
48 |
49 | ### New
50 |
51 | * Updated CHANGELOG.rst. [Shaun Clayton]
52 |
53 | * Added stub for CHANGELOG.rst. [Shaun Clayton]
54 |
55 | ### Older
56 |
57 | * Hopefully fixed the problem that prevent `makemigrations` from executing. [Curt Wagner]
58 |
59 | * [Issue #42] Added 'usage_count' to actor\scene tags website and actors. Also added option to sort by usage count. [Curt Wagner]
60 |
61 | * [Issue #43] Added 'play_count' and 'date_last_played' sorting options to scenes that will help track down scenes recently watched. Also added play count as a search option. [Curt Wagner]
62 |
63 | * [Issue #30] Added 'scene_tags' to 'website' also added 'scene_tags' to 'actor_tags'. Now whenever a website/actor added to scenes their tags are added as well. (When they are removed the tags are removed). EX: Adding 'Stoya' who is tagged with 'eye.color.green' will tag the scene with 'eye.color.green'. and removing 'Stoya' will remove 'eye.color.green' tag. [Curt Wagner]
64 |
65 | * Corrected formatting of scraper popup message. [Shaun Clayton]
66 |
67 | * Added missing tooltip for scene tag aliases input - Added code to strip leading/trailing spaces from scene/website aliases. [Shaun Clayton]
68 |
69 | * [Issue #30] Added 'aliases' to scenes tags and websites. Also added 'date modified' to almost all models. This will require migrating. [Curt Wagner]
70 |
71 | * [Issue #11] Made it so 'order by' option is retained for actors,scenes,websites,tags and folders. Also added 'Random' option in folder view Also added "Date_added" field to folders. Will require to makemigrations and migrate. [Curt Wagner]
72 |
73 | * Made it so scenes that can't be ffprobed won't be added. [Curt Wagner]
74 |
75 | * Added conversion for weight and height to Imperial #20. [Shaun Clayton]
76 |
77 | * Partially Implemented -- "[Feature Request] Add confirmation for removing/deleting items from database or disk #31" [Shaun Clayton]
78 |
79 | * Fixed issue with timezone offset affecting birth date display. [Shaun Clayton]
80 |
81 | Added change to correct timezone offset changing the birthday being displayed on Actor detail page.
82 |
83 | * Partially implemented ''[Feature Request] Add button to play random scene #27'. Play random scene works with scene, actors, websites and scenetags but only when the search term is blank. [Curt Wagner]
84 |
85 | * Fixed issue '[Bug] Not all Actors displayed after Items Per Page set #28' [Curt Wagner]
86 |
87 | * Clean db now also deletes folders in /media/ of actors\scenes that are no longer in the database. [Curt Wagner]
88 |
89 | * Updated favicons images. [Shaun Clayton]
90 |
91 | New style and bolder icon
92 |
93 | * Added MKV to accepted extensions. [Curt Wagner]
94 |
95 | * Corrected spelling and formatting. [Shaun Clayton]
96 |
97 | * Changed how grid view works, it now should keep current query results. Also in actor detail view, when switching to grid view will automatically hide actor info. [Curt Wagner]
98 |
99 | * Made DOB of actors to work. [Curt Wagner]
100 |
101 | * Creating sample when adding scenes should work now (Really) [Curt Wagner]
102 |
103 | * Added favicon images. [Shaun Clayton]
104 |
105 | * Added option to delete actor\scene tags and websites from database. [Curt Wagner]
106 |
107 | * Removed unnecessary buttons from the upload profile image interface. Added functuanality to crop existing images. [Curt Wagner]
108 |
109 | * Added OS detection to ffmpeg_process.py. [Shaun Clayton]
110 |
111 | Added detection of which platform we are running under so that the paths can be adjusted accordingly.
112 |
113 | * Fixed formatting - removed redundant double label for Height and Weight. [Shaun Clayton]
114 |
115 | * Strip trailing and leading spaces from Actors inserted into database. [Shaun Clayton]
116 |
117 | Fixes the potential issue of leaving a space after a comma when importing a bulk list of Actors, was causing scraping errors as it was scraping the Actor name with the spaces included.
118 |
119 | * Added clean database option in settings (Now also removes aliases without actors) [Curt Wagner]
120 |
121 | * Added option to delete scenes from disk. [Curt Wagner]
122 |
123 | * Added option to remove scene from database. [Curt Wagner]
124 |
125 | * Made grid option persistent using ngStorage. [Curt Wagner]
126 |
127 | * Added rating and runner up toggle to actor list. [Curt Wagner]
128 |
129 | * Added more search options and filters. [Curt Wagner]
130 |
131 | * Freeones scraper will now search for alias if it failed to find the main name. [Curt Wagner]
132 |
133 | * Added rating bar to scene list view, also added settings.json versioning and 'last lookup' field for all scenes in settings.json. [Curt Wagner]
134 |
135 | * Added toggleable recursion option to folder view. Now it's possible to view scenes that are inside of the current folder only or view scenes inside the current folder and all of it's subfolders. [Curt Wagner]
136 |
137 | * Made scenes in Actor, Scene Tags, and websites searchable, also added applicable order options to each one of them. [Curt Wagner]
138 |
139 | * Added 'Runner Up', and 'Play Scene' to scene list options. [Curt Wagner]
140 |
141 | * Made actor name editable. [Curt Wagner]
142 |
143 | * Added (x years old) to actor details if date of birth exists. [Curt Wagner]
144 |
145 | * Added 'Google Image Search' to actor details. [Curt Wagner]
146 |
147 | * Added "is_exempt_from_one_word_search" to actor details. [Curt Wagner]
148 |
149 | * Added unknown person image. [Curt Wagner]
150 |
151 |
--------------------------------------------------------------------------------
/videos/static/js/app/settings/settings.component.js:
--------------------------------------------------------------------------------
1 | angular.module('settings').component('settings', {
2 | // Note: The URL is relative to our `index.html` file
3 | templateUrl: 'static/js/app/settings/settings.template.html',
4 | controller: ['$scope', '$rootScope', 'scopeWatchService', '$http','helperService',
5 | function SettingsController($scope, $rootScope, scopeWatchService, $http, helperService) {
6 |
7 | var self = this;
8 | self.response = "";
9 | self.ignore_last_lookup = false;
10 |
11 | // self.pathToVLC = "";
12 |
13 | self.itemsPerPage = 50;
14 | self.mediaRootFolders = null;
15 |
16 |
17 | var x = helperService.getNumberOfItemsPerPaige();
18 | if (helperService.getNumberOfItemsPerPaige() != undefined){
19 | self.itemsPerPage = helperService.getNumberOfItemsPerPaige()
20 | }
21 |
22 | self.changeNumberOfItemsPerPage = function () {
23 | helperService.setNumberOfItemsPerPaige(self.itemsPerPage);
24 | // scopeWatchService.numberOfItemsPerPageChanged('a');
25 | };
26 |
27 |
28 | self.settings = $http.get('settings/', {
29 | params: {
30 | pathToVlc: ""
31 | }
32 | }).then(function (response) {
33 | // alert(angular.toJson(response));
34 | self.response = response.data.vlc_path;
35 | self.pathToVLC = response.data.vlc_path;
36 | // alert("Got response from server: " + self.pathToFolderToAdd);
37 | }, function errorCallback(response) {
38 | alert("Something went wrong!");
39 | });
40 |
41 |
42 | self.updateVlcPath = function () {
43 |
44 | $http.get('settings/', {
45 | params: {
46 | pathToVlc: self.pathToVLC
47 | }
48 |
49 | }).then(function (response) {
50 | // alert(angular.toJson(response));
51 | self.response = response.data.vlc_path;
52 | self.pathToVLC = response.data.vlc_path;
53 | // alert("Got response from server: " + self.pathToFolderToAdd);
54 | }, function errorCallback(response) {
55 | alert("Something went wrong!");
56 | });
57 | };
58 |
59 | self.scrapAllActors = function () {
60 | $http.get('settings/', {
61 | params: {
62 | scrapAllActor: 'True'
63 | }
64 |
65 | }).then(function (response) {
66 | // alert(angular.toJson(response));
67 | // self.response = response.data.vlc_path;
68 | // self.pathToVLC = response.data.vlc_path;
69 | // alert("Got response from server: " + self.pathToFolderToAdd);
70 | }, function errorCallback(response) {
71 | alert("Something went wrong!");
72 | });
73 | };
74 |
75 |
76 | self.tagAllScenes = function () {
77 | $http.get('settings/', {
78 | params: {
79 | tagAllScenes: 'true',
80 | ignoreLastLookup: self.ignore_last_lookup
81 | }
82 |
83 | }).then(function (response) {
84 | // alert(angular.toJson(response));
85 | // self.response = response.data.vlc_path;
86 | // self.pathToVLC = response.data.vlc_path;
87 | // alert("Got response from server: " + self.pathToFolderToAdd);
88 | }, function errorCallback(response) {
89 | alert("Something went wrong!");
90 | });
91 |
92 | };
93 |
94 |
95 | self.cleanDatabase = function () {
96 | $http.get('settings/', {
97 | params: {
98 | cleanDatabase: true
99 |
100 | }
101 |
102 | }).then(function (response) {
103 | // alert(angular.toJson(response));
104 | // self.response = response.data.vlc_path;
105 | // self.pathToVLC = response.data.vlc_path;
106 | // alert("Got response from server: " + self.pathToFolderToAdd);
107 | }, function errorCallback(response) {
108 | alert("Something went wrong!" + angular.toJson(response));
109 | });
110 |
111 | };
112 |
113 |
114 | var getRootMediaPaths = function () {
115 | $http.get('/api/folder-local/', {
116 | }).then(function (response) {
117 |
118 | self.mediaRootFolders = response.data;
119 | // alert(angular.toJson(response));
120 | // self.response = response.data.vlc_path;
121 | // self.pathToVLC = response.data.vlc_path;
122 | // alert("Got response from server: " + self.pathToFolderToAdd);
123 | }, function errorCallback(response) {
124 | alert("Something went wrong!" + angular.toJson(response));
125 | });
126 | };
127 |
128 | getRootMediaPaths();
129 |
130 |
131 | self.removeFolderFromList = function (folder) {
132 |
133 | var index = helperService.getObjectIndexFromArrayOfObjects(folder,self.mediaRootFolders);
134 |
135 | if (index != null){
136 | self.mediaRootFolders.splice(index,1);
137 | }
138 |
139 | $http.delete('/api/folder-local/' + folder.id, {
140 | }).then(function (response) {
141 | // alert(angular.toJson(response));
142 | // self.response = response.data.vlc_path;
143 | // self.pathToVLC = response.data.vlc_path;
144 | // alert("Got response from server: " + self.pathToFolderToAdd);
145 | }, function errorCallback(response) {
146 | alert("Something went wrong!" + angular.toJson(response));
147 | });
148 |
149 |
150 | };
151 |
152 |
153 | self.rescanFolders = function (folder) {
154 |
155 | if (folder != ''){
156 | folder = folder.id
157 | }
158 |
159 | $http.get('settings/', {
160 | params: {
161 | folderToScan: folder
162 |
163 | }
164 |
165 | }).then(function (response) {
166 | // alert(angular.toJson(response));
167 | // self.response = response.data.vlc_path;
168 | // self.pathToVLC = response.data.vlc_path;
169 | // alert("Got response from server: " + self.pathToFolderToAdd);
170 | }, function errorCallback(response) {
171 | alert("Something went wrong!" + angular.toJson(response));
172 | });
173 |
174 | }
175 |
176 |
177 |
178 | }
179 | ]
180 | }
181 | );
--------------------------------------------------------------------------------