-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This patch adds a simple user interface to schedule a new event starting right now on the pyCA capture agent. This easily allows users to quickly schedule test or last-minute events with no need for going through Opencast's admin interface.
- Loading branch information
Showing
8 changed files
with
262 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
# -*- coding: utf-8 -*- | ||
''' | ||
python-capture-agent | ||
~~~~~~~~~~~~~~~~~~~~ | ||
:copyright: 2014-2022, Lars Kiesow <[email protected]> | ||
:license: LGPL – see license.lgpl for more details. | ||
''' | ||
|
||
from xml.sax.saxutils import escape as xml_escape | ||
from pyca.config import config | ||
from pyca.utils import http_request, service | ||
from datetime import datetime, timedelta | ||
import logging | ||
import random | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
DUBLINCORE = '''<?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||
<dublincore xmlns="http://www.opencastproject.org/xsd/1.0/dublincore/" | ||
xmlns:dcterms="http://purl.org/dc/terms/" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> | ||
<dcterms:creator>{creator}</dcterms:creator> | ||
<dcterms:created xsi:type="dcterms:W3CDTF">{start}</dcterms:created> | ||
<dcterms:temporal xsi:type="dcterms:Period">start={start}; end={end}; scheme=W3C-DTF;</dcterms:temporal> | ||
<dcterms:language>demo</dcterms:language> | ||
<dcterms:spatial>{agent_name}</dcterms:spatial> | ||
<dcterms:title>{title}</dcterms:title> | ||
</dublincore>''' # noqa | ||
|
||
|
||
def schedule(title='pyCA Recording', duration=60, creator=None): | ||
'''Schedule a recording for this capture agent with the given title, | ||
creator and duration starting 10 seconds from now. | ||
:param title: Title of the event to schedule | ||
:type title: string | ||
:param creator: Creator of the event to schedule | ||
:type creator: string | ||
:param duration: Duration of the event to schedule in seconds | ||
:type creator: int | ||
''' | ||
if not creator: | ||
creator = config('ui', 'username') | ||
|
||
# Select ingest service | ||
# The ingest service to use is selected at random from the available | ||
# ingest services to ensure that not every capture agent uses the same | ||
# service at the same time | ||
service_url = service('ingest', force_update=True) | ||
service_url = service_url[random.randrange(0, len(service_url))] | ||
logger.info('Selecting ingest service for scheduling: ' + service_url) | ||
|
||
# create media package | ||
logger.info('Creating new media package') | ||
mediapackage = http_request(service_url + '/createMediaPackage') | ||
|
||
# add dublin core catalog | ||
start = datetime.utcnow() + timedelta(seconds=10) | ||
end = start + timedelta(seconds=duration) | ||
dublincore = DUBLINCORE.format( | ||
agent_name=xml_escape(config('agent', 'name')), | ||
start=start.strftime('%Y-%m-%dT%H:%M:%SZ'), | ||
end=end.strftime('%Y-%m-%dT%H:%M:%SZ'), | ||
title=xml_escape(title), | ||
creator=xml_escape(creator)) | ||
logger.info('Adding Dublin Core catalog for scheduling') | ||
fields = [('mediaPackage', mediapackage), | ||
('flavor', 'dublincore/episode'), | ||
('dublinCore', dublincore)] | ||
mediapackage = http_request(service_url + '/addDCCatalog', fields) | ||
|
||
# schedule event | ||
logger.info('Scheduling recording') | ||
fields = [('mediaPackage', mediapackage)] | ||
mediapackage = http_request(service_url + '/schedule', fields) | ||
|
||
# Update status | ||
logger.info('Event successfully scheduled') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
''' | ||
Tests for basic capturing | ||
''' | ||
|
||
import unittest | ||
|
||
from pyca.ui import opencast_commands | ||
|
||
|
||
class TestPycaIngest(unittest.TestCase): | ||
|
||
def setUp(self): | ||
opencast_commands.http_request = lambda x, y=False: b'xxx' | ||
opencast_commands.service = lambda x, force_update=False: [''] | ||
|
||
def test_schedule_defaults(self): | ||
opencast_commands.schedule() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
<template> | ||
<div> | ||
<form v-if='!this.active' id=schedule v-on:submit=schedule> | ||
<label for=title>Title</label> | ||
<input id=title type=text placeholder='pyCA Recording' v-model=title required /> | ||
<br /> | ||
<label for=creator>Creator</label> | ||
<input id=creator type=text placeholder=Administrator v-model=creator required /> | ||
<br /> | ||
<label for=duration>Duration (min)</label> | ||
<input id=duration type=number placeholder=30 v-model.number=duration required /> | ||
<br /> | ||
<input type=submit value=Start /> | ||
</form> | ||
<div v-if='this.active' style='color: green;padding: 15px'> | ||
Event is being scheduled… | ||
</div> | ||
</div> | ||
</template> | ||
|
||
<script> | ||
export default { | ||
data() { | ||
return { | ||
active: false, | ||
title: 'pyCA Recording', | ||
creator: 'Administrator', | ||
duration: 5, | ||
}}, | ||
methods: { | ||
schedule: function(event) { | ||
event.preventDefault(); | ||
this.active = true; | ||
let requestOptions = { | ||
method: 'POST', | ||
headers: { 'Content-Type': 'application/vnd.api+json' }, | ||
body: JSON.stringify( | ||
{'data': [{ | ||
'title': this.title, | ||
'creator': this.creator, | ||
'duration': this.duration * 60 | ||
}]}) | ||
}; | ||
fetch('/api/schedule', requestOptions) | ||
.then(response => { | ||
if (response.status == 409) { | ||
alert('Conflict: A scheduled recording exists during this time.'); | ||
throw 'Error: Scheduling conflict'; | ||
} else if (response.status != 200) { | ||
throw 'Error: request failed'; | ||
} | ||
}) | ||
.catch(function(error) { | ||
console.log(error); | ||
}) | ||
.finally(() => { | ||
this.active = false; | ||
}) | ||
} | ||
} | ||
}; | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters