rename app, change api url, fix media op path

This commit is contained in:
jb-alvarado 2020-05-03 21:11:25 +02:00
parent 64f49414ec
commit fe62710f76
25 changed files with 82 additions and 140 deletions

View File

@ -1,5 +0,0 @@
from django.apps import AppConfig
class ApiConfig(AppConfig):
name = 'api'

View File

@ -1,28 +0,0 @@
# Generated by Django 3.0.5 on 2020-04-16 09:27
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='GuiSettings',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('player_url', models.CharField(max_length=255)),
('playout_config', models.CharField(default='/etc/ffplayout/ffplayout.yml', max_length=255)),
('net_interface', models.CharField(choices=[('lo', 'lo'), ('br0', 'br0'), ('virbr0', 'virbr0'), ('eno1', 'eno1'), ('virbr0-nic', 'virbr0-nic')], default=None, max_length=20)),
('media_disk', models.CharField(default='/', help_text='should be a mount point, for statistics', max_length=255)),
('extra_extensions', models.CharField(blank=True, default='', help_text='file extensions, that are only visible in GUI', max_length=255, null=True)),
],
options={
'verbose_name_plural': 'guisettings',
},
),
]

View File

@ -1,32 +0,0 @@
# Generated by Django 3.0.5 on 2020-04-28 13:47
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('api', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='MessengePresets',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(help_text='the preset name', max_length=255)),
('message', models.CharField(blank=True, default='', max_length=1024, null=True)),
('x', models.CharField(blank=True, default='', max_length=512, null=True)),
('y', models.CharField(blank=True, default='', max_length=512, null=True)),
('font_size', models.IntegerField(default=24)),
('font_spacing', models.IntegerField(default=4)),
('font_color', models.CharField(default='#ffffff', max_length=12)),
('font_alpha', models.FloatField(default=1.0)),
('show_box', models.BooleanField(default=True)),
('box_color', models.CharField(default='#000000', max_length=12)),
('box_alpha', models.FloatField(default=0.8)),
('border_width', models.IntegerField(default=4)),
('overall_alpha', models.CharField(blank=True, default='', max_length=255, null=True)),
],
),
]

View File

@ -1,7 +1,6 @@
from api_player.models import GuiSettings
from django.contrib import admin from django.contrib import admin
from api.models import GuiSettings
class GuiSettingsAdmin(admin.ModelAdmin): class GuiSettingsAdmin(admin.ModelAdmin):

View File

@ -0,0 +1,5 @@
from django.apps import AppConfig
class ApiPlayerConfig(AppConfig):
name = 'api_player'

View File

@ -1,9 +1,7 @@
from api_player.models import GuiSettings, MessengePresets
from django.contrib.auth.models import User from django.contrib.auth.models import User
from rest_framework import serializers from rest_framework import serializers
from api.models import GuiSettings, MessengePresets
class UserSerializer(serializers.ModelSerializer): class UserSerializer(serializers.ModelSerializer):
new_password = serializers.CharField(write_only=True, required=False) new_password = serializers.CharField(write_only=True, required=False)

View File

@ -0,0 +1,26 @@
from django.urls import include, path, re_path
from rest_framework import routers
from . import views
router = routers.DefaultRouter()
router.register(r'users', views.UserViewSet)
router.register(r'guisettings', views.GuiSettingsViewSet, 'guisettings')
router.register(r'messenger', views.MessengerViewSet, 'messenger')
app_name = 'api_player'
urlpatterns = [
path('player/', include(router.urls)),
path('player/config/', views.Config.as_view()),
path('player/system/', views.SystemCtl.as_view()),
path('player/playlist/', views.Playlist.as_view()),
path('player/stats/', views.Statistics.as_view()),
path('player/log/', views.LogReader.as_view()),
path('player/current/user/', views.CurrentUserView.as_view()),
path('player/media/', views.Media.as_view()),
path('player/send/', views.MessegeSender.as_view()),
re_path(r'^player/media/upload/(?P<filename>[^/]+)$',
views.FileUpload.as_view()),
path('player/media/op/', views.FileOperations.as_view()),
]

View File

@ -1,17 +1,17 @@
import json import json
import os import os
from platform import uname from platform import uname
from subprocess import run, PIPE, STDOUT from subprocess import PIPE, STDOUT, run
from time import sleep from time import sleep
import psutil import psutil
import yaml import yaml
import zmq import zmq
from api_player.models import GuiSettings
from django.conf import settings from django.conf import settings
from pymediainfo import MediaInfo
from api.models import GuiSettings
from natsort import natsorted from natsort import natsorted
from pymediainfo import MediaInfo
def read_yaml(): def read_yaml():
@ -244,8 +244,6 @@ def get_media_path(extensions, dir=None):
media_dir = media_path.split('/')[-1] media_dir = media_path.split('/')[-1]
media_root = os.path.dirname(media_path) media_root = os.path.dirname(media_path)
if not dir: if not dir:
if not os.path.isdir(media_path):
return ''
dir = media_path dir = media_path
else: else:
if '/..' in dir: if '/..' in dir:
@ -257,7 +255,8 @@ def get_media_path(extensions, dir=None):
if dir.startswith(media_dir): if dir.startswith(media_dir):
dir = dir[len(media_dir):] dir = dir[len(media_dir):]
dir = os.path.join(media_root, media_dir, os.path.abspath('/' + dir).strip('/')) dir = os.path.join(
media_root, media_dir, os.path.abspath('/' + dir).strip('/'))
for root, dirs, files in os.walk(dir, topdown=True): for root, dirs, files in os.walk(dir, topdown=True):
root = root.rstrip('/') root = root.rstrip('/')

View File

@ -2,9 +2,9 @@ import os
import shutil import shutil
from urllib.parse import unquote from urllib.parse import unquote
from api.models import GuiSettings, MessengePresets from api_player.models import GuiSettings, MessengePresets
from api.serializers import (GuiSettingsSerializer, MessengerSerializer, from api_player.serializers import (GuiSettingsSerializer, MessengerSerializer,
UserSerializer) UserSerializer)
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django_filters import rest_framework as filters from django_filters import rest_framework as filters
from rest_framework import viewsets from rest_framework import viewsets
@ -13,7 +13,7 @@ from rest_framework.response import Response
from rest_framework.views import APIView from rest_framework.views import APIView
from .utils import (PlayoutService, SystemStats, get_media_path, read_json, from .utils import (PlayoutService, SystemStats, get_media_path, read_json,
read_yaml, write_json, write_yaml, read_log, send_message) read_log, read_yaml, send_message, write_json, write_yaml)
class CurrentUserView(APIView): class CurrentUserView(APIView):
@ -71,7 +71,7 @@ class MessegeSender(APIView):
class Config(APIView): class Config(APIView):
""" """
read and write config from ffplayout engine read and write config from ffplayout engine
for reading endpoint is: http://127.0.0.1:8000/api/config/?config for reading endpoint is: http://127.0.0.1:8000/api/player/config/?config
""" """
parser_classes = [JSONParser] parser_classes = [JSONParser]
@ -148,7 +148,8 @@ class LogReader(APIView):
class Playlist(APIView): class Playlist(APIView):
""" """
read and write config from ffplayout engine read and write config from ffplayout engine
for reading endpoint: http://127.0.0.1:8000/api/playlist/?date=2020-04-12 for reading endpoint:
http://127.0.0.1:8000/api/player/playlist/?date=2020-04-12
""" """
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
@ -176,7 +177,7 @@ class Playlist(APIView):
class Statistics(APIView): class Statistics(APIView):
""" """
get system statistics: cpu, ram, etc. get system statistics: cpu, ram, etc.
for reading, endpoint is: http://127.0.0.1:8000/api/stats/?stats=all for reading, endpoint is: http://127.0.0.1:8000/api/player/stats/?stats=all
""" """
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
@ -192,7 +193,7 @@ class Statistics(APIView):
class Media(APIView): class Media(APIView):
""" """
get folder/files tree, for building a file explorer get folder/files tree, for building a file explorer
for reading, endpoint is: http://127.0.0.1:8000/api/media/?path for reading, endpoint is: http://127.0.0.1:8000/api/player/media/?path
""" """
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):

Binary file not shown.

View File

@ -29,7 +29,7 @@ INSTALLED_APPS = [
'django_filters', 'django_filters',
'rest_framework', 'rest_framework',
'corsheaders', 'corsheaders',
'api' 'api_player'
] ]
MIDDLEWARE = [ MIDDLEWARE = [

View File

@ -14,34 +14,13 @@ Including another URLconf
2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
""" """
from django.contrib import admin from django.contrib import admin
from django.urls import include, path, re_path from django.urls import include, path
from rest_framework_simplejwt.views import (TokenObtainPairView,
from rest_framework import routers TokenRefreshView)
from api import views
from rest_framework_simplejwt.views import (
TokenObtainPairView,
TokenRefreshView,
)
router = routers.DefaultRouter()
router.register(r'users', views.UserViewSet)
router.register(r'guisettings', views.GuiSettingsViewSet, 'guisettings')
router.register(r'messenger', views.MessengerViewSet, 'messenger')
urlpatterns = [ urlpatterns = [
path('admin/', admin.site.urls), path('admin/', admin.site.urls),
path('api/', include(router.urls)), path('api/', include('api_player.urls', namespace='api_player')),
path('api/config/', views.Config.as_view()),
path('api/system/', views.SystemCtl.as_view()),
path('api/playlist/', views.Playlist.as_view()),
path('api/stats/', views.Statistics.as_view()),
path('api/log/', views.LogReader.as_view()),
path('api/current/user/', views.CurrentUserView.as_view()),
path('api/media/', views.Media.as_view()),
path('api/send/', views.MessegeSender.as_view()),
re_path(r'^api/media/upload/(?P<filename>[^/]+)$', views.FileUpload.as_view()),
path('api/media/op/', views.FileOperations.as_view()),
path('api-auth/', include( path('api-auth/', include(
'rest_framework.urls', namespace='rest_framework')), 'rest_framework.urls', namespace='rest_framework')),
path('auth/token/', TokenObtainPairView.as_view(), path('auth/token/', TokenObtainPairView.as_view(),

View File

@ -210,13 +210,13 @@ export default {
}, },
async sysStats () { async sysStats () {
const response = await this.$axios.get('api/stats/?stats=all') const response = await this.$axios.get('api/player/stats/?stats=all')
this.stat = response.data this.stat = response.data
if (process.browser) { if (process.browser) {
this.interval = setInterval(async () => { this.interval = setInterval(async () => {
await this.$store.dispatch('auth/inspectToken') await this.$store.dispatch('auth/inspectToken')
const response = await this.$axios.get('api/stats/?stats=all') const response = await this.$axios.get('api/player/stats/?stats=all')
this.stat = response.data this.stat = response.data
}, 2000) }, 2000)
} }

View File

@ -75,7 +75,7 @@ export default {
methods: { methods: {
async getLog (type) { async getLog (type) {
await this.$store.dispatch('auth/inspectToken') await this.$store.dispatch('auth/inspectToken')
const response = await this.$axios.get(`api/log/?type=${type}`) const response = await this.$axios.get(`api/player/log/?type=${type}`)
if (response.data.log) { if (response.data.log) {
this.currentLog = response.data.log this.currentLog = response.data.log
@ -83,7 +83,7 @@ export default {
}, },
async getSystemLog () { async getSystemLog () {
await this.$store.dispatch('auth/inspectToken') await this.$store.dispatch('auth/inspectToken')
const response = await this.$axios.post('api/system/', { run: 'log' }) const response = await this.$axios.post('api/player/system/', { run: 'log' })
if (response.data.data) { if (response.data.data) {
this.currentLog = response.data.data this.currentLog = response.data.data

View File

@ -36,7 +36,7 @@
</b-link> </b-link>
</b-col> </b-col>
<b-col v-if="folder !== '..'" cols="1" class="folder-delete"> <b-col v-if="folder !== '..'" cols="1" class="folder-delete">
<b-link @click="showDeleteModal('Folder', `/${folderTree.tree[0]}/${folder}`)"> <b-link @click="showDeleteModal('Folder', `${folderTree.tree[0]}/${folder}`)">
<b-icon-x-circle-fill /> <b-icon-x-circle-fill />
</b-link> </b-link>
</b-col> </b-col>
@ -70,7 +70,7 @@
{{ file.file }} {{ file.file }}
</b-col> </b-col>
<b-col cols="1" class="browser-play-col"> <b-col cols="1" class="browser-play-col">
<b-link @click="showPreviewModal(`/${folderTree.tree[0]}/${file.file}`)"> <b-link @click="showPreviewModal(`${folderTree.tree[0]}/${file.file}`)">
<b-icon-play-fill /> <b-icon-play-fill />
</b-link> </b-link>
</b-col> </b-col>
@ -78,7 +78,7 @@
<span class="duration">{{ file.duration | toMin }}</span> <span class="duration">{{ file.duration | toMin }}</span>
</b-col> </b-col>
<b-col cols="1" class="text-center"> <b-col cols="1" class="text-center">
<b-link @click="showDeleteModal('File', `/${folderTree.tree[0]}/${file.file}`)"> <b-link @click="showDeleteModal('File', `${folderTree.tree[0]}/${file.file}`)">
<b-icon-x-circle-fill /> <b-icon-x-circle-fill />
</b-link> </b-link>
</b-col> </b-col>
@ -276,7 +276,7 @@ export default {
await this.$store.dispatch('auth/inspectToken') await this.$store.dispatch('auth/inspectToken')
await this.$axios.post( await this.$axios.post(
'api/media/op/', 'api/player/media/op/',
{ folder: this.folderName, path: this.crumbs.map(e => e.text).join('/') } { folder: this.folderName, path: this.crumbs.map(e => e.text).join('/') }
) )
@ -322,7 +322,7 @@ export default {
} }
await this.$axios.put( await this.$axios.put(
`api/media/upload/${encodeURIComponent(file.name)}?path=${encodeURIComponent(this.crumbs.map(e => e.text).join('/'))}`, `api/player/media/upload/${encodeURIComponent(file.name)}?path=${encodeURIComponent(this.crumbs.map(e => e.text).join('/'))}`,
file, file,
config config
) )
@ -403,7 +403,7 @@ export default {
pathName = this.deleteSource pathName = this.deleteSource
} }
await this.$axios.delete(`api/media/op/?file=${encodeURIComponent(file)}&path=${encodeURIComponent(pathName)}`) await this.$axios.delete(`api/player/media/op/?file=${encodeURIComponent(file)}&path=${encodeURIComponent(pathName)}`)
.catch(err => console.log(err)) .catch(err => console.log(err))
this.$root.$emit('bv::hide::modal', 'delete-modal') this.$root.$emit('bv::hide::modal', 'delete-modal')

View File

@ -281,7 +281,7 @@ export default {
if (preset) { if (preset) {
req = `?name=${preset}` req = `?name=${preset}`
} }
const response = await this.$axios.get(`api/messenger/${req}`) const response = await this.$axios.get(`api/player/messenger/${req}`)
if (response.data && !preset) { if (response.data && !preset) {
for (const item of response.data) { for (const item of response.data) {
@ -333,7 +333,7 @@ export default {
overall_alpha: this.form.overallAlpha overall_alpha: this.form.overallAlpha
} }
const response = await this.$axios.post('api/messenger/', preset) const response = await this.$axios.post('api/player/messenger/', preset)
if (response.status === 201) { if (response.status === 201) {
this.success = true this.success = true
@ -365,7 +365,7 @@ export default {
overall_alpha: this.form.overallAlpha overall_alpha: this.form.overallAlpha
} }
const response = await this.$axios.put(`api/messenger/${this.form.id}/`, preset) const response = await this.$axios.put(`api/player/messenger/${this.form.id}/`, preset)
if (response.status === 200) { if (response.status === 200) {
this.success = true this.success = true
@ -385,7 +385,7 @@ export default {
async deletePreset () { async deletePreset () {
await this.$store.dispatch('auth/inspectToken') await this.$store.dispatch('auth/inspectToken')
if (this.selected) { if (this.selected) {
await this.$axios.delete(`api/messenger/${this.form.id}/`) await this.$axios.delete(`api/player/messenger/${this.form.id}/`)
} }
this.$bvModal.hide('delete-modal') this.$bvModal.hide('delete-modal')
@ -411,7 +411,7 @@ export default {
boxborderw: this.form.border boxborderw: this.form.border
} }
const response = await this.$axios.post('api/send/', { data: obj }) const response = await this.$axios.post('api/player/send/', { data: obj })
if (response.data && response.data.status.Success && response.data.status.Success === '0 Success') { if (response.data && response.data.status.Success && response.data.status.Success === '0 Success') {
this.success = true this.success = true

View File

@ -372,7 +372,7 @@ export default {
async getStatus () { async getStatus () {
await this.$store.dispatch('auth/inspectToken') await this.$store.dispatch('auth/inspectToken')
const status = await this.$axios.post('api/system/', { run: 'status' }) const status = await this.$axios.post('api/player/system/', { run: 'status' })
if (status.data.data && status.data.data === 'active') { if (status.data.data && status.data.data === 'active') {
this.isPlaying = 'is-playing' this.isPlaying = 'is-playing'
@ -382,7 +382,7 @@ export default {
}, },
async playoutControl (state) { async playoutControl (state) {
await this.$store.dispatch('auth/inspectToken') await this.$store.dispatch('auth/inspectToken')
await this.$axios.post('api/system/', { run: state }) await this.$axios.post('api/player/system/', { run: state })
setTimeout(() => { this.getStatus() }, 1000) setTimeout(() => { this.getStatus() }, 1000)
}, },
@ -447,7 +447,7 @@ export default {
const saveList = this.playlist.map(({ begin, ...item }) => item) const saveList = this.playlist.map(({ begin, ...item }) => item)
await this.$axios.post( await this.$axios.post(
'api/playlist/', 'api/player/playlist/',
{ data: { channel: this.$store.state.playlist.playlistChannel, date: this.listDate, program: saveList } } { data: { channel: this.$store.state.playlist.playlistChannel, date: this.listDate, program: saveList } }
) )
} }

View File

@ -6,7 +6,7 @@ export default function ({ $axios, store, redirect }) {
} }
// disable progress on auth and stats // disable progress on auth and stats
if (config.url.includes('stats') || config.url.includes('auth')) { if (config.url.includes('stats') || config.url.includes('auth') || config.url.includes('system')) {
config.progress = false config.progress = false
} }
}) })

View File

@ -26,8 +26,8 @@ export const mutations = {
export const actions = { export const actions = {
async getGuiConfig ({ commit, state }) { async getGuiConfig ({ commit, state }) {
const options = await this.$axios.options('api/guisettings/') const options = await this.$axios.options('api/player/guisettings/')
const response = await this.$axios.get('api/guisettings/') const response = await this.$axios.get('api/player/guisettings/')
if (options.data) { if (options.data) {
const choices = options.data.actions.POST.net_interface.choices.map(function (obj) { const choices = options.data.actions.POST.net_interface.choices.map(function (obj) {
@ -46,12 +46,12 @@ export const actions = {
async setGuiConfig ({ commit, state }, obj) { async setGuiConfig ({ commit, state }, obj) {
const stringObj = JSON.parse(JSON.stringify(obj)) const stringObj = JSON.parse(JSON.stringify(obj))
stringObj.extra_extensions = obj.extra_extensions.join(' ') stringObj.extra_extensions = obj.extra_extensions.join(' ')
const update = await this.$axios.put('api/guisettings/1/', stringObj) const update = await this.$axios.put('api/player/guisettings/1/', stringObj)
return update return update
}, },
async getPlayoutConfig ({ commit, state }) { async getPlayoutConfig ({ commit, state }) {
const response = await this.$axios.get('api/config/?configPlayout') const response = await this.$axios.get('api/player/config/?configPlayout')
if (response.data) { if (response.data) {
commit('UPDATE_PLAYLOUT_CONFIG', response.data) commit('UPDATE_PLAYLOUT_CONFIG', response.data)
@ -59,13 +59,13 @@ export const actions = {
}, },
async setPlayoutConfig ({ commit, state }, obj) { async setPlayoutConfig ({ commit, state }, obj) {
const update = await this.$axios.post('api/config/?configPlayout', { data: obj }) const update = await this.$axios.post('api/player/config/?configPlayout', { data: obj })
return update return update
}, },
async getUserConfig ({ commit, state }) { async getUserConfig ({ commit, state }) {
const user = await this.$axios.get('api/current/user/') const user = await this.$axios.get('api/player/current/user/')
const response = await this.$axios.get(`api/users/?username=${user.data.username}`) const response = await this.$axios.get(`api/player/users/?username=${user.data.username}`)
if (user.data) { if (user.data) {
commit('SET_CURRENT_USER', user.data.username) commit('SET_CURRENT_USER', user.data.username)
@ -76,7 +76,7 @@ export const actions = {
}, },
async setUserConfig ({ commit, state }, obj) { async setUserConfig ({ commit, state }, obj) {
const update = await this.$axios.put(`api/users/${obj.id}/`, obj) const update = await this.$axios.put(`api/player/users/${obj.id}/`, obj)
return update return update
} }
} }

View File

@ -20,7 +20,7 @@ export const actions = {
async getTree ({ commit, dispatch, state }, { extensions, path }) { async getTree ({ commit, dispatch, state }, { extensions, path }) {
const crumbs = [] const crumbs = []
let root = '/' let root = '/'
const response = await this.$axios.get(`api/media/?extensions=${extensions}&path=${path}`) const response = await this.$axios.get(`api/player/media/?extensions=${extensions}&path=${path}`)
if (response.data.tree) { if (response.data.tree) {
const pathArr = response.data.tree[0].split('/') const pathArr = response.data.tree[0].split('/')

View File

@ -46,7 +46,7 @@ export const mutations = {
export const actions = { export const actions = {
async getPlaylist ({ commit, dispatch, state }, { dayStart, date }) { async getPlaylist ({ commit, dispatch, state }, { dayStart, date }) {
const response = await this.$axios.get(`api/playlist/?date=${date}`) const response = await this.$axios.get(`api/player/playlist/?date=${date}`)
if (response.data && response.data.program) { if (response.data && response.data.program) {
commit('UPDATE_PLAYLIST_CHANNEL', response.data.channel) commit('UPDATE_PLAYLIST_CHANNEL', response.data.channel)