diff options
Diffstat (limited to 'mediagoblin/plugins')
9 files changed, 523 insertions, 60 deletions
diff --git a/mediagoblin/plugins/metadata_display/templates/mediagoblin/plugins/metadata_display/metadata_table.html.orig b/mediagoblin/plugins/metadata_display/templates/mediagoblin/plugins/metadata_display/metadata_table.html.orig deleted file mode 100644 index 2bd1a14c..00000000 --- a/mediagoblin/plugins/metadata_display/templates/mediagoblin/plugins/metadata_display/metadata_table.html.orig +++ /dev/null @@ -1,60 +0,0 @@ -{# -# GNU MediaGoblin -- federated, autonomous media hosting -# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -#} - -<<<<<<< HEAD:mediagoblin/templates/mediagoblin/utils/metadata_table.html -{%- macro render_table(request, media_entry, format_predicate) %} - {%- set metadata=media_entry.media_metadata %} - {%- set metadata_context=metadata['@context'] %} - {%- if metadata %} - <h3>{% trans %}Metadata Information{% endtrans %}</h3> - <table class="metadata_info"> - {%- for key, value in metadata.iteritems() if ( - not key=='@context' and value) %} - <tr {% if loop.index%2 == 1 %}class="highlight"{% endif %}> - <th>{{ format_predicate(key) }}</th> - <td property="{{ key }}"> - {{ value }}</td> - </tr> - {%- endfor %} - </table> - {% endif %} - {% if request.user and request.user.has_privilege('admin') %} - <a href="{{ request.urlgen('mediagoblin.edit.metadata', - user=media_entry.get_uploader.username, - media_id=media_entry.id) }}"> - {% trans %}Edit Metadata{% endtrans %}</a> - {% endif %} -{%- endmacro %} -======= -{%- set metadata=media.media_metadata %} -{%- set metadata_context=metadata['@context'] %} -{%- if metadata %} - {#- NOTE: In some smart future where the context is more extensible, - we will need to add to the prefix here-#} - <table> - {%- for key, value in metadata.iteritems() if not key=='@context' %} - {% if value -%} - <tr> - <td>{{ rdfa_to_readable(key) }}</td> - <td property="{{ key }}">{{ value }}</td> - </tr> - {%- endif -%} - {%- endfor %} - </table> -{% endif %} ->>>>>>> acfcaf6366bd4695c1c37c7aa8ff5a176b412e2a:mediagoblin/plugins/metadata_display/templates/mediagoblin/plugins/metadata_display/metadata_table.html diff --git a/mediagoblin/plugins/subtitles/__init__.py b/mediagoblin/plugins/subtitles/__init__.py new file mode 100644 index 00000000..78f207dc --- /dev/null +++ b/mediagoblin/plugins/subtitles/__init__.py @@ -0,0 +1,50 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2016 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +from mediagoblin.tools import pluginapi +import os + +PLUGIN_DIR = os.path.dirname(__file__) + +def setup_plugin(): + config = pluginapi.get_config('mediagoblin.plugins.subtitles') + + routes = [ + ('mediagoblin.plugins.subtitles.customize', + '/u/<string:user>/m/<int:media_id>/customize/<int:id>', + 'mediagoblin.plugins.subtitles.views:custom_subtitles'), + ('mediagoblin.plugins.subtitles.subtitles', + '/u/<string:user>/m/<int:media_id>/subtitles/', + 'mediagoblin.plugins.subtitles.views:edit_subtitles'), + ('mediagoblin.plugins.subtitles.delete_subtitles', + '/u/<string:user>/m/<int:media_id>/delete/<int:id>', + 'mediagoblin.plugins.subtitles.views:delete_subtitles')] + + pluginapi.register_routes(routes) + + # Register the template path. + pluginapi.register_template_path(os.path.join(PLUGIN_DIR, 'templates')) + + pluginapi.register_template_hooks( + {"customize_subtitles": "mediagoblin/plugins/subtitles/custom_subtitles.html", + "add_subtitles": "mediagoblin/plugins/subtitles/subtitles.html", + "subtitle_sidebar": "mediagoblin/plugins/subtitles/subtitle_media_block.html"}) + + + +hooks = { + 'setup': setup_plugin + } diff --git a/mediagoblin/plugins/subtitles/forms.py b/mediagoblin/plugins/subtitles/forms.py new file mode 100644 index 00000000..de8ffbcd --- /dev/null +++ b/mediagoblin/plugins/subtitles/forms.py @@ -0,0 +1,29 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2016 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import wtforms + +class CustomizeSubtitlesForm(wtforms.Form): + subtitle = wtforms.TextAreaField( + ('Subtitle'), + [wtforms.validators.Optional()], + description=("")) + +class EditSubtitlesForm(wtforms.Form): + subtitle_language = wtforms.StringField( + 'Language') + subtitle_file = wtforms.FileField( + 'File') diff --git a/mediagoblin/plugins/subtitles/models.py b/mediagoblin/plugins/subtitles/models.py new file mode 100644 index 00000000..f71fb173 --- /dev/null +++ b/mediagoblin/plugins/subtitles/models.py @@ -0,0 +1,49 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2016 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +from sqlalchemy import Column, Integer, Unicode, ForeignKey +from sqlalchemy.orm import relationship + +from mediagoblin.db.models import User +from mediagoblin.db.base import Base,MediaEntry + +class MediaSubtitleFile(Base): + __tablename__ = "core__subtitle_files" + + id = Column(Integer, primary_key=True) + media_entry = Column( + Integer, ForeignKey(MediaEntry.id), + nullable=False) + name = Column(Unicode, nullable=False) + filepath = Column(PathTupleWithSlashes) + created = Column(DateTime, nullable=False, default=datetime.datetime.utcnow) + + @property + def dict_view(self): + """A dict like view on this object""" + return DictReadAttrProxy(self) + + subtitle_files_helper = relationship("MediaSubtitleFile", + cascade="all, delete-orphan", + order_by="MediaSubtitleFile.created" + ) + subtitle_files = association_proxy("subtitle_files_helper", "dict_view", + creator=lambda v: MediaSubtitleFile( + name=v["name"], filepath=v["filepath"]) + ) + +MODELS = [ + MediaSubtitleFile +] diff --git a/mediagoblin/plugins/subtitles/templates/mediagoblin/plugins/subtitles/custom_subtitles.html b/mediagoblin/plugins/subtitles/templates/mediagoblin/plugins/subtitles/custom_subtitles.html new file mode 100644 index 00000000..a62325ca --- /dev/null +++ b/mediagoblin/plugins/subtitles/templates/mediagoblin/plugins/subtitles/custom_subtitles.html @@ -0,0 +1,48 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2016 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +#} +{% extends "mediagoblin/base.html" %} + +{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %} + +{% block title -%} +{%- endblock %} + + +{% block mediagoblin_content %} +<link href="{{ + request.staticdirect('/css/subtitles.css') }}" + rel="stylesheet"> + + <form action="{{ request.urlgen('mediagoblin.plugins.subtitles.customize', + user=media.get_actor.username, + media_id=media.id, + id=id) }}" method="POST" enctype="multipart/form-data"> + <div class="form_box edit_box"> + {{ wtforms_util.render_divs(form) }} + <div class="form_submit_buttons"> + {% set delete_url = request.urlgen('mediagoblin.plugins.subtitles.delete_subtitles', + user= media.get_actor.username, + media_id=media.id, + id=id) %} + <a class="button_action button_warning" href="{{ delete_url }}">{% trans %}Delete Subtitle{% endtrans %}</a> + <input type="submit" value="{% trans %}Save changes{% endtrans %}" class="button_form" /> + {{ csrf_token }} + </div> + </div> + </form> +{% endblock %} diff --git a/mediagoblin/plugins/subtitles/templates/mediagoblin/plugins/subtitles/subtitle_media_block.html b/mediagoblin/plugins/subtitles/templates/mediagoblin/plugins/subtitles/subtitle_media_block.html new file mode 100644 index 00000000..34c9c16f --- /dev/null +++ b/mediagoblin/plugins/subtitles/templates/mediagoblin/plugins/subtitles/subtitle_media_block.html @@ -0,0 +1,50 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2016 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +#} + +{% block subtitle_block %} +{% if "video.html" in media.media_manager.display_template or "audio.html" in media.media_manager.display_template %} + {%- if media.subtitle_files|count %} + <h3>{% trans %}Subtitles{% endtrans %}</h3> + <ul> + {%- for subtitle in media.subtitle_files %} + <li> + <a href="{{ request.urlgen('mediagoblin.plugins.subtitles.customize', + user=media.get_actor.username, + media_id=media.id, + id=subtitle.id ) }}"> + {{- subtitle.name -}} + </li> + {%- endfor %} + </ul> + {%- endif %} + {%- if request.user + and (media.actor == request.user.id + or request.user.has_privilege('admin')) %} + {%- if not media.subtitle_files|count %} + <h3>{% trans %}Subtitles{% endtrans %}</h3> + {%- endif %} + <p> + <a href="{{ request.urlgen('mediagoblin.plugins.subtitles.subtitles', + user=media.get_actor.username, + media_id=media.id) }}"> + {%- trans %}Add subtitle {% endtrans -%} + </a> + </p> + {%- endif %} + {% endif %} +{% endblock %} diff --git a/mediagoblin/plugins/subtitles/templates/mediagoblin/plugins/subtitles/subtitles.html b/mediagoblin/plugins/subtitles/templates/mediagoblin/plugins/subtitles/subtitles.html new file mode 100644 index 00000000..5b249403 --- /dev/null +++ b/mediagoblin/plugins/subtitles/templates/mediagoblin/plugins/subtitles/subtitles.html @@ -0,0 +1,69 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2016 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +#} +{%- extends "mediagoblin/base.html" %} + +{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %} + +{% block title -%} + {% trans media_title=media.title -%} + Editing subtitles for {{ media_title }} + {%- endtrans %} — {{ super() }} +{%- endblock %} + +{% block mediagoblin_content %} + <form action="{{ request.urlgen('mediagoblin.plugins.subtitles.subtitles', + user= media.get_actor.username, + media_id=media.id) }}" + method="POST" enctype="multipart/form-data"> + <div class="form_box"> + <h1> + {%- trans media_title=media.title -%} + Editing subtitles for {{ media_title }} + {%- endtrans -%} + </h1> + <div style="text-align: center;" > + <img src="{{ media.thumb_url }}" /> + </div> + + {% if media.subtitle_files|count %} + <h2>{% trans %}subtitles{% endtrans %}</h2> + <ul> + {%- for subtitle in media.subtitle_files %} + <li> + <a target="_blank" href="{{ request.app.public_store.file_url( + subtitle['filepath']) }}"> + {{- subtitle.name -}} + </a> + </li> + {%- endfor %} + </ul> + {% endif %} + + <h2>{% trans %}Add subtitle{% endtrans %}</h2> + {{- wtforms_util.render_divs(form) }} + <div class="form_submit_buttons"> + <a class="button_action" href="{{ media.url_for_self(request.urlgen) }}"> + {%- trans %}Cancel{% endtrans -%} + </a> + <input type="submit" value="{% trans %}Save changes{% endtrans %}" + class="button_form" /> + {{ csrf_token }} + </div> + </div> + </form> +{% endblock %} diff --git a/mediagoblin/plugins/subtitles/tools.py b/mediagoblin/plugins/subtitles/tools.py new file mode 100644 index 00000000..43f5bd6a --- /dev/null +++ b/mediagoblin/plugins/subtitles/tools.py @@ -0,0 +1,42 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2016 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +from mediagoblin import mg_globals +import os + +def open_subtitle(path): + status = True + subtitle_public_filepath = path + try: + with mg_globals.public_store.get_file( + subtitle_public_filepath, 'rb') as subtitle_public_file: + text = subtitle_public_file.read().decode('utf-8','ignore') + return (text,status) + except: + status = False + return ('',status) + +def save_subtitle(path,text): + status = True + subtitle_public_filepath = path + try: + with mg_globals.public_store.get_file( + subtitle_public_filepath, 'wb') as subtitle_public_file: + subtitle_public_file.write(text.encode('utf-8','ignore')) + return status + except: + status = False + return (status) diff --git a/mediagoblin/plugins/subtitles/views.py b/mediagoblin/plugins/subtitles/views.py new file mode 100644 index 00000000..46b844af --- /dev/null +++ b/mediagoblin/plugins/subtitles/views.py @@ -0,0 +1,186 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2016 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import six + +from datetime import datetime + +from itsdangerous import BadSignature +from werkzeug.exceptions import Forbidden +from werkzeug.utils import secure_filename + +from mediagoblin import messages +from mediagoblin import mg_globals + +from mediagoblin.plugins.subtitles import forms +from mediagoblin.decorators import (require_active_login, active_user_from_url, + get_media_entry_by_id, user_may_delete_media) +from mediagoblin.tools.metadata import (compact_and_validate, DEFAULT_CHECKER, + DEFAULT_SCHEMA) +from mediagoblin.tools.response import (render_to_response, + redirect, redirect_obj, render_404) + +import mimetypes + +from mediagoblin.plugins.subtitles.tools import open_subtitle,save_subtitle + +UNSAFE_MIMETYPES = [ + 'text/html', + 'text/svg+xml'] + +@get_media_entry_by_id +@user_may_delete_media +@require_active_login +def edit_subtitles(request, media): + allowed_extensions = ['aqt','gsub','jss','sub','ttxt','pjs','psb', + 'rt','smi','stl','ssf','srt','ssa','ass','usf','vtt','lrc'] + form = forms.EditSubtitlesForm(request.form) + + # Add any subtitles + if 'subtitle_file' in request.files \ + and request.files['subtitle_file']: + if mimetypes.guess_type( + request.files['subtitle_file'].filename)[0] in \ + UNSAFE_MIMETYPES: + public_filename = secure_filename('{0}.notsafe'.format( + request.files['subtitle_file'].filename)) + else: + public_filename = secure_filename( + request.files['subtitle_file'].filename) + filepath = request.files['subtitle_file'].filename + if filepath.split('.')[-1] not in allowed_extensions : + messages.add_message( + request, + messages.ERROR, + ("Invalid subtitle file")) + + return redirect(request, + location=media.url_for_self(request.urlgen)) + subtitle_public_filepath = mg_globals.public_store.get_unique_filepath( + ['media_entries', six.text_type(media.id), 'subtitle', + public_filename]) + + with mg_globals.public_store.get_file( + subtitle_public_filepath, 'wb') as subtitle_public_file: + subtitle_public_file.write( + request.files['subtitle_file'].stream.read()) + request.files['subtitle_file'].stream.close() + + media.subtitle_files.append(dict( + name=form.subtitle_language.data \ + or request.files['subtitle_file'].filename, + filepath=subtitle_public_filepath, + created=datetime.utcnow(), + )) + + media.save() + + messages.add_message( + request, + messages.SUCCESS, + ("You added the subtitle %s!") % + (form.subtitle_language.data or + request.files['subtitle_file'].filename)) + + return redirect(request, + location=media.url_for_self(request.urlgen)) + return render_to_response( + request, + 'mediagoblin/plugins/subtitles/subtitles.html', + {'media': media, + 'form': form}) + + +@require_active_login +@get_media_entry_by_id +@user_may_delete_media +def custom_subtitles(request,media,id=None): + id = request.matchdict['id'] + path = "" + for subtitle in media.subtitle_files: + if subtitle["id"] == id: + path = subtitle["filepath"] + text = "" + value = open_subtitle(path) + text, status = value[0], value[1] + if status == True : + form = forms.CustomizeSubtitlesForm(request.form, + subtitle=text) + if request.method == 'POST' and form.validate(): + subtitle_data = form.subtitle.data + status = save_subtitle(path,subtitle_data) + if status == True: + messages.add_message( + request, + messages.SUCCESS, + ("Subtitle file changed!!!")) + return redirect(request, + location=media.url_for_self(request.urlgen)) + else : + messages.add_message( + request, + messages.ERROR, + ("Couldn't edit the subtitles!!!")) + return redirect(request, + location=media.url_for_self(request.urlgen)) + + return render_to_response( + request, + "mediagoblin/plugins/subtitles/custom_subtitles.html", + {"id": id, + "media": media, + "form": form }) + else: + index = 0 + for subtitle in media.subtitle_files: + if subtitle["id"] == id: + delete_container = index + media.subtitle_files.pop(delete_container) + media.save() + break + index += 1 + messages.add_message( + request, + messages.ERROR, + ("File link broken! Upload the subtitle again")) + return redirect(request, + location=media.url_for_self(request.urlgen)) + + +@require_active_login +@get_media_entry_by_id +@user_may_delete_media +def delete_subtitles(request,media): + id = request.matchdict['id'] + delete_container = None + index = 0 + for subtitle in media.subtitle_files: + if subtitle["id"] == id: + path = subtitle["filepath"] + mg_globals.public_store.delete_file(path) + delete_container = index + media.subtitle_files.pop(delete_container) + media.save() + break + index += 1 + + messages.add_message( + request, + messages.SUCCESS, + ("Subtitle file deleted!!!")) + + return redirect(request, + location=media.url_for_self(request.urlgen)) |