1
0
Fork 0
mirror of https://github.com/Kunsi/pretalx-plugin-broadcast-tools synced 2024-09-29 00:47:13 +00:00

Compare commits

..

30 commits
v2.0.0 ... main

Author SHA1 Message Date
1a5aaa90fc
bump version to 2.2.1 2024-08-20 12:26:13 +02:00
513f3ebe75
Merge pull request #22 from pretalx/main
Compatibility with pretalx v2024.2.x
2024-08-09 19:06:38 +02:00
Tobias Kunze
7c05357067 Fix imports 2024-08-09 11:12:16 +02:00
Tobias Kunze
c9e72db1f7 Fix urls.py 2024-08-09 11:12:11 +02:00
Tobias Kunze
545bdfb966 Code style 2024-08-09 11:12:02 +02:00
Tobias Kunze
6f8c536cb8 Build wheels 2024-08-09 11:04:13 +02:00
Tobias Kunze
d54087b7d0 Use dynamic version 2024-08-09 11:04:09 +02:00
Tobias Kunze
2e2efbff9d Remove duplicate project setup file 2024-08-09 11:03:26 +02:00
3917fa65cf
some more code style 2024-03-16 11:37:26 +01:00
81494bed54
update github actions some more 2024-03-16 11:36:41 +01:00
819e8ea2aa
update github actions to use python 3.12 2024-03-16 11:29:10 +01:00
77148e41f7 release 2.2.0 2023-10-23 08:34:53 +02:00
cb60e02671
github workflows: remove apparently broken packaging check 2023-10-10 16:28:38 +02:00
25d8be0397
apparently, you need a boilerplate setup.py to publish to pypi 2023-10-10 16:16:15 +02:00
af4e3408db
improve placeholder explainations 2023-10-10 16:05:20 +02:00
dabc8e5443
add TRACK_NAME and TRACK_NAME_COLOURED placeholders 2023-10-10 16:00:47 +02:00
341a9c072c
Merge pull request #16 from rixx/category
Add plugin category
2023-10-03 13:08:54 +02:00
Tobias Kunze
98f8374b66 Add pluginc category 2023-10-03 11:22:40 +02:00
2b22f6a155
release 2.1.0 2023-09-30 13:38:31 +02:00
5335e911b7
Merge pull request #15 from rixx/pyproject-toml
Fix pyproject.toml install
2023-09-30 13:21:38 +02:00
Tobias Kunze
210a18f6b3 Fix pyproject.toml install 2023-09-30 13:15:24 +02:00
3063adcc73
move views into dedicated files 2023-09-30 12:41:47 +02:00
8f8f8a90e2
add more information to the json outputs 2023-09-30 12:35:37 +02:00
433f316719 release 2.0.1 2023-08-23 08:13:46 +02:00
ca8a2e3c65 make the linter happy 2023-08-23 08:11:19 +02:00
85893d9c9c migrate to pyproject.toml 2023-08-23 08:08:38 +02:00
c6ceedf041
Merge pull request #13 from rixx/timezone
Safe timezone handling
2023-06-19 10:35:01 +02:00
1ad4c73ed4
Merge pull request #14 from rixx/ugett
Use non-deprecated gettext call
2023-06-19 10:34:10 +02:00
Tobias Kunze
57351a4e1a Use non-deprecated gettext call 2023-06-03 23:07:34 +02:00
Tobias Kunze
190ce8f222 Safe timezone handling 2023-06-03 22:07:13 +02:00
18 changed files with 395 additions and 326 deletions

View file

@ -18,14 +18,14 @@ jobs:
name: isort
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: install gettext
run: sudo apt install gettext
- name: Set up Python 3.8
uses: actions/setup-python@v1
- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: 3.8
- uses: actions/cache@v1
python-version: 3.12
- uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/setup.py') }}
@ -41,14 +41,14 @@ jobs:
name: flake8
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: install gettext
run: sudo apt install gettext
- name: Set up Python 3.8
uses: actions/setup-python@v1
- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: 3.8
- uses: actions/cache@v1
python-version: 3.12
- uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/setup.py') }}
@ -65,14 +65,14 @@ jobs:
name: black
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: install gettext
run: sudo apt install gettext
- name: Set up Python 3.8
uses: actions/setup-python@v1
- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: 3.8
- uses: actions/cache@v1
python-version: 3.12
- uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/setup.py') }}
@ -89,14 +89,14 @@ jobs:
name: docformatter
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: install gettext
run: sudo apt install gettext
- name: Set up Python 3.8
uses: actions/setup-python@v1
- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: 3.8
- uses: actions/cache@v1
python-version: 3.12
- uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/setup.py') }}
@ -113,14 +113,14 @@ jobs:
name: djhtml
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: install gettext
run: sudo apt install gettext
- name: Set up Python 3.8
uses: actions/setup-python@v1
- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: 3.8
- uses: actions/cache@v1
python-version: 3.12
- uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/setup.py') }}
@ -133,34 +133,34 @@ jobs:
- name: Run docformatter
run: find -name "*.html" | xargs djhtml -c
working-directory: .
packaging:
name: packaging
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: install gettext
run: sudo apt install gettext
- name: Set up Python 3.8
uses: actions/setup-python@v1
with:
python-version: 3.8
- uses: actions/cache@v1
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/setup.py') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Install pretalx
run: pip3 install pretalx
- name: Install Dependencies
run: pip3 install twine check-manifest -Ue .
- name: Run check-manifest
run: check-manifest .
working-directory: .
- name: Build package
run: python setup.py sdist
working-directory: .
- name: Check package
run: twine check dist/*
working-directory: .
# packaging:
# name: packaging
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v4
# - name: install gettext
# run: sudo apt install gettext
# - name: Set up Python 3.12
# uses: actions/setup-python@v5
# with:
# python-version: 3.12
# - uses: actions/cache@v4
# with:
# path: ~/.cache/pip
# key: ${{ runner.os }}-pip-${{ hashFiles('**/setup.py') }}
# restore-keys: |
# ${{ runner.os }}-pip-
# - name: Install pretalx
# run: pip3 install pretalx
# - name: Install Dependencies
# run: pip3 install twine check-manifest -Ue .
# - name: Run check-manifest
# run: check-manifest .
# working-directory: .
# - name: Build package
# run: python setup.py sdist
# working-directory: .
# - name: Check package
# run: twine check dist/*
# working-directory: .
#

View file

@ -1,3 +1,22 @@
# 2.2.0
* add plugin category (#16)
* add placeholders `{TRACK_NAME}` and `{TRACK_NAME_COLOURED}`
# 2.1.0
* fixed installation procedure
* add some more information to the json outputs to be able to be compatible
with [scheduled-plugin-pretalx-broadcast-tools](https://github.com/Kunsi/scheduled-plugin-pretalx-broadcast-tools)
(a plugin for [info-beamer hosted](https://info-beamer.com/))
# 2.0.1 (no longer available due to bugs during installation)
* fixes to support pretalx 2023.1.0
* use non-deprecated gettext call
* safe timezone handling
* usage of pyproject.toml
# 2.0.0
* room info page can now show more content on the lower half of the view

View file

@ -59,7 +59,7 @@ Development setup
3. Activate the virtual environment you use for pretalx development.
4. Execute ``python setup.py develop`` within this directory to register
4. Execute ``python -m pip install -e .`` within this directory to register
this application with pretalx's plugin registry.
5. Execute ``make`` within this directory to compile translations.

View file

@ -0,0 +1 @@
__version__ = "2.2.1"

View file

@ -1,6 +1,8 @@
from django.apps import AppConfig
from django.utils.translation import gettext_lazy
from pretalx_broadcast_tools import __version__
class PluginApp(AppConfig):
name = "pretalx_broadcast_tools"
@ -15,7 +17,8 @@ class PluginApp(AppConfig):
"embedded into your broadcasting software"
)
visible = True
version = "2.0.0"
version = __version__
category = "FEATURE"
def ready(self):
from . import signals # NOQA

View file

@ -17,7 +17,7 @@ from reportlab.platypus import (
TableStyle,
)
from .utils.placeholders import placeholders
from pretalx_broadcast_tools.utils.placeholders import placeholders
A4_WIDTH, A4_HEIGHT = A4
PAGE_PADDING = 10 * mm

View file

@ -1,7 +1,7 @@
from django.dispatch import receiver
from django.urls import resolve, reverse
from django.utils.translation import gettext_lazy as _
from django.utils.translation import gettext_noop
from django.utils.translation import ugettext_lazy as _
from i18nfield.strings import LazyI18nString
from pretalx.common.models.settings import hierarkey
from pretalx.common.signals import register_data_exporters

View file

@ -32,19 +32,22 @@
</p>
<dl>
<dt><code>{CODE}</code></dt>
<dd>Use to embed the talk code (<code>MUX9U3</code> for example).</dd>
<dd>talk code (<code>MUX9U3</code> for example) - most useful in combination with pretalx-proposal-redirects or something like that</dd>
<dt><code>{EVENT_SLUG}</code></dt>
<dd>Use to embed the event slug.</dd>
<dd>The event slug (<code>{{ request.event.slug }}</code>)</dd>
<dt><code>{FEEDBACK_URL}</code></dt>
<dd>URL to the talk feedback page.</dd>
<dt><code>{TALK_SLUG}</code></dt>
<dd>Use to embed the talk slug.</dd>
<dd>The talk slug (<code>{{ request.event.slug }}-1-my-super-great-talk</code>)</dd>
<dt><code>{TALK_URL}</code></dt>
<dd>URL to the talk detail page.</dd>
<dt><code>{TRACK_NAME}</code> or <code>{TRACK_NAME_COLOURED}</code></dt>
<dd>Track name in plain text or coloured using the track colour.</dd>
</dl>
<fieldset>

View file

@ -1,42 +1,46 @@
from django.urls import re_path
from pretalx.event.models.event import SLUG_CHARS
from pretalx.event.models.event import SLUG_REGEX
from . import views
from .views.event_info import BroadcastToolsEventInfoView
from .views.orga import BroadcastToolsOrgaView
from .views.qr import BroadcastToolsFeedbackQrCodeSvg, BroadcastToolsPublicQrCodeSvg
from .views.schedule import BroadcastToolsScheduleView
from .views.static_html import BroadcastToolsLowerThirdsView, BroadcastToolsRoomInfoView
urlpatterns = [
re_path(
f"^(?P<event>[{SLUG_CHARS}]+)/p/broadcast-tools/event.json$",
views.BroadcastToolsEventInfoView.as_view(),
rf"^(?P<event>{SLUG_REGEX})/p/broadcast-tools/event.json$",
BroadcastToolsEventInfoView.as_view(),
name="event_info",
),
re_path(
f"^(?P<event>[{SLUG_CHARS}]+)/p/broadcast-tools/schedule.json$",
views.BroadcastToolsScheduleView.as_view(),
f"^(?P<event>{SLUG_REGEX})/p/broadcast-tools/schedule.json$",
BroadcastToolsScheduleView.as_view(),
name="schedule",
),
re_path(
f"^(?P<event>[{SLUG_CHARS}]+)/p/broadcast-tools/lower-thirds/$",
views.BroadcastToolsLowerThirdsView.as_view(),
f"^(?P<event>{SLUG_REGEX})/p/broadcast-tools/lower-thirds/$",
BroadcastToolsLowerThirdsView.as_view(),
name="lowerthirds",
),
re_path(
f"^(?P<event>[{SLUG_CHARS}]+)/p/broadcast-tools/feedback-qr/(?P<talk>[0-9]+).svg$",
views.BroadcastToolsFeedbackQrCodeSvg.as_view(),
f"^(?P<event>{SLUG_REGEX})/p/broadcast-tools/feedback-qr/(?P<talk>[0-9]+).svg$",
BroadcastToolsFeedbackQrCodeSvg.as_view(),
name="feedback_qr_id",
),
re_path(
f"^(?P<event>[{SLUG_CHARS}]+)/p/broadcast-tools/public-qr/(?P<talk>[0-9]+).svg$",
views.BroadcastToolsPublicQrCodeSvg.as_view(),
f"^(?P<event>{SLUG_REGEX})/p/broadcast-tools/public-qr/(?P<talk>[0-9]+).svg$",
BroadcastToolsPublicQrCodeSvg.as_view(),
name="public_qr_id",
),
re_path(
f"^(?P<event>[{SLUG_CHARS}]+)/p/broadcast-tools/room-info/$",
views.BroadcastToolsRoomInfoView.as_view(),
f"^(?P<event>{SLUG_REGEX})/p/broadcast-tools/room-info/$",
BroadcastToolsRoomInfoView.as_view(),
name="room_info",
),
re_path(
f"^orga/event/(?P<event>[{SLUG_CHARS}]+)/settings/p/broadcast-tools/$",
views.BroadcastToolsOrgaView.as_view(),
f"^orga/event/(?P<event>{SLUG_REGEX})/settings/p/broadcast-tools/$",
BroadcastToolsOrgaView.as_view(),
name="orga",
),
]

View file

@ -1,8 +1,10 @@
from django.conf import settings
def placeholders(schedule, talk):
return {
def placeholders(schedule, talk, supports_html_colour=False):
track_name = str(talk.submission.track.name) if talk.submission.track else ""
result = {
"CODE": talk.submission.code,
"EVENT_SLUG": str(schedule.event.slug),
"FEEDBACK_URL": "{}{}".format(
@ -14,4 +16,17 @@ def placeholders(schedule, talk):
schedule.event.custom_domain or settings.SITE_URL,
talk.submission.urls.public,
),
"TRACK_NAME": track_name,
}
if talk.submission.track and supports_html_colour:
result["TRACK_NAME_COLOURED"] = '<span style="color: {}">{}</span>'.format(
talk.submission.track.color, track_name
)
else:
result["TRACK_NAME_COLOURED"] = track_name
# for the americans
result["TRACK_NAME_COLORED"] = result["TRACK_NAME_COLOURED"]
return result

View file

@ -1,199 +0,0 @@
import datetime as dt
from xml.etree import ElementTree as ET
import pytz
import qrcode
import qrcode.image.svg
from django.conf import settings
from django.http import HttpResponse, JsonResponse
from django.urls import reverse
from django.utils.safestring import mark_safe
from django.views import View
from django.views.generic import FormView
from django.views.generic.base import TemplateView
from pretalx.agenda.views.schedule import ScheduleMixin
from pretalx.common.mixins.views import EventPermissionRequired, PermissionRequired
from pretalx.schedule.exporters import ScheduleData
from .forms import BroadcastToolsSettingsForm
from .utils.placeholders import placeholders
class BroadcastToolsLowerThirdsView(TemplateView):
template_name = "pretalx_broadcast_tools/lower_thirds.html"
class BroadcastToolsRoomInfoView(TemplateView):
template_name = "pretalx_broadcast_tools/room_info.html"
class BroadcastToolsOrgaView(PermissionRequired, FormView):
form_class = BroadcastToolsSettingsForm
permission_required = "orga.change_settings"
template_name = "pretalx_broadcast_tools/orga.html"
def get_success_url(self):
return self.request.path
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["localized_rooms"] = [
room.name.localize(self.request.event.locale)
for room in self.request.event.rooms.all()
]
return context
def form_valid(self, form):
form.save()
return super().form_valid(form)
def get_object(self):
return self.request.event
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
return {
"obj": self.request.event,
"attribute_name": "settings",
"locales": self.request.event.locales,
**kwargs,
}
class BroadcastToolsEventInfoView(View):
def get(self, request, *args, **kwargs):
color = self.request.event.primary_color or "#3aa57c"
return JsonResponse(
{
"color": color,
"name": str(self.request.event.name),
"no_talk": str(
self.request.event.settings.broadcast_tools_lower_thirds_no_talk_info
),
"room-info": {
"lower_info": self.request.event.settings.broadcast_tools_room_info_lower_content
or "",
"show_next_talk": True
if self.request.event.settings.broadcast_tools_room_info_show_next_talk
else False,
},
"slug": self.request.event.slug,
},
)
class BroadcastToolsFeedbackQrCodeSvg(View):
def get(self, request, *args, **kwargs):
talk = self.request.event.submissions.filter(id=kwargs["talk"]).first()
domain = request.event.custom_domain or settings.SITE_URL
image = qrcode.make(
f"{domain}{talk.urls.feedback}", image_factory=qrcode.image.svg.SvgImage
)
svg_data = mark_safe(ET.tostring(image.get_image()).decode())
return HttpResponse(svg_data, content_type="image/svg+xml")
class BroadcastToolsPublicQrCodeSvg(View):
def get(self, request, *args, **kwargs):
talk = self.request.event.submissions.filter(id=kwargs["talk"]).first()
domain = request.event.custom_domain or settings.SITE_URL
image = qrcode.make(
f"{domain}{talk.urls.public}", image_factory=qrcode.image.svg.SvgImage
)
svg_data = mark_safe(ET.tostring(image.get_image()).decode())
return HttpResponse(svg_data, content_type="image/svg+xml")
class BroadcastToolsScheduleView(EventPermissionRequired, ScheduleMixin, View):
permission_required = "agenda.view_schedule"
def get(self, request, *args, **kwargs):
schedule = ScheduleData(
event=self.request.event,
schedule=self.schedule,
)
tz = pytz.timezone(schedule.event.timezone)
infoline = str(
schedule.event.settings.broadcast_tools_lower_thirds_info_string or ""
)
try:
return JsonResponse(
{
"rooms": sorted(
{
room["name"].localize(schedule.event.locale)
for day in schedule.data
for room in day["rooms"]
}
),
"talks": [
{
"id": talk.submission.id,
"start": talk.start.astimezone(tz).isoformat(),
"end": (talk.start + dt.timedelta(minutes=talk.duration))
.astimezone(tz)
.isoformat(),
"slug": talk.frab_slug,
"title": talk.submission.title,
"persons": [
person.get_display_name()
for person in talk.submission.speakers.all()
],
"track": {
"color": talk.submission.track.color,
"name": str(talk.submission.track.name),
}
if talk.submission.track
else None,
"room": room["name"].localize(schedule.event.locale),
"infoline": infoline.format(**placeholders(schedule, talk)),
"image_url": talk.submission.image_url,
"urls": {
"feedback": "{}{}".format(
schedule.event.custom_domain or settings.SITE_URL,
talk.submission.urls.feedback,
),
"feedback_qr": reverse(
"plugins:pretalx_broadcast_tools:feedback_qr_id",
kwargs={
"event": schedule.event.slug,
"talk": talk.submission.id,
},
),
"public": "{}{}".format(
schedule.event.custom_domain or settings.SITE_URL,
talk.submission.urls.public,
),
"public_qr": reverse(
"plugins:pretalx_broadcast_tools:public_qr_id",
kwargs={
"event": schedule.event.slug,
"talk": talk.submission.id,
},
),
},
}
for day in schedule.data
for room in day["rooms"]
for talk in room["talks"]
],
},
)
except KeyError as e:
key = str(e)[1:-1]
return JsonResponse(
{
"error": [
f"Could not find value for placeholder {{{key}}} in info line.",
f"If you want to use {{{key}}} without evaluating it, please use as follows: {{{{{key}}}}}",
],
}
)
except Exception as e:
return JsonResponse(
{
"error": [
repr(e),
],
}
)

View file

@ -0,0 +1,30 @@
from django.http import JsonResponse
from django.views import View
class BroadcastToolsEventInfoView(View):
def get(self, request, *args, **kwargs):
color = self.request.event.primary_color or "#3aa57c"
return JsonResponse(
{
"color": color,
"name": self.request.event.name.localize(self.request.event.locale),
"no_talk": str(
self.request.event.settings.broadcast_tools_lower_thirds_no_talk_info
),
"room-info": {
"lower_info": self.request.event.settings.broadcast_tools_room_info_lower_content
or "",
"show_next_talk": (
True
if self.request.event.settings.broadcast_tools_room_info_show_next_talk
else False
),
},
"slug": self.request.event.slug,
"start": self.request.event.date_from.isoformat(),
"end": self.request.event.date_to.isoformat(),
"timezone": str(self.request.event.tz),
"locale": self.request.event.locale,
},
)

View file

@ -0,0 +1,37 @@
from django.views.generic import FormView
from pretalx.common.views.mixins import PermissionRequired
from ..forms import BroadcastToolsSettingsForm
class BroadcastToolsOrgaView(PermissionRequired, FormView):
form_class = BroadcastToolsSettingsForm
permission_required = "orga.change_settings"
template_name = "pretalx_broadcast_tools/orga.html"
def get_success_url(self):
return self.request.path
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["localized_rooms"] = [
room.name.localize(self.request.event.locale)
for room in self.request.event.rooms.all()
]
return context
def form_valid(self, form):
form.save()
return super().form_valid(form)
def get_object(self):
return self.request.event
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
return {
"obj": self.request.event,
"attribute_name": "settings",
"locales": self.request.event.locales,
**kwargs,
}

View file

@ -0,0 +1,30 @@
from xml.etree import ElementTree
import qrcode
import qrcode.image.svg
from django.conf import settings
from django.http import HttpResponse
from django.utils.safestring import mark_safe
from django.views import View
class BroadcastToolsFeedbackQrCodeSvg(View):
def get(self, request, *args, **kwargs):
talk = self.request.event.submissions.filter(id=kwargs["talk"]).first()
domain = request.event.custom_domain or settings.SITE_URL
image = qrcode.make(
f"{domain}{talk.urls.feedback}", image_factory=qrcode.image.svg.SvgImage
)
svg_data = mark_safe(ElementTree.tostring(image.get_image()).decode())
return HttpResponse(svg_data, content_type="image/svg+xml")
class BroadcastToolsPublicQrCodeSvg(View):
def get(self, request, *args, **kwargs):
talk = self.request.event.submissions.filter(id=kwargs["talk"]).first()
domain = request.event.custom_domain or settings.SITE_URL
image = qrcode.make(
f"{domain}{talk.urls.public}", image_factory=qrcode.image.svg.SvgImage
)
svg_data = mark_safe(ElementTree.tostring(image.get_image()).decode())
return HttpResponse(svg_data, content_type="image/svg+xml")

View file

@ -0,0 +1,122 @@
import datetime as dt
from django.conf import settings
from django.http import JsonResponse
from django.urls import reverse
from django.views import View
from pretalx.agenda.views.schedule import ScheduleMixin
from pretalx.common.views.mixins import EventPermissionRequired
from pretalx.schedule.exporters import ScheduleData
from ..utils.placeholders import placeholders
class BroadcastToolsScheduleView(EventPermissionRequired, ScheduleMixin, View):
permission_required = "agenda.view_schedule"
def get(self, request, *args, **kwargs):
schedule = ScheduleData(
event=self.request.event,
schedule=self.schedule,
)
infoline = str(
schedule.event.settings.broadcast_tools_lower_thirds_info_string or ""
)
try:
return JsonResponse(
{
"rooms": sorted(
{
room["name"].localize(schedule.event.locale)
for day in schedule.data
for room in day["rooms"]
}
),
"talks": [
{
"id": talk.submission.id,
"start": talk.start.astimezone(
schedule.event.tz
).isoformat(),
"start_ts": int(talk.start.timestamp()),
"end": (talk.start + dt.timedelta(minutes=talk.duration))
.astimezone(schedule.event.tz)
.isoformat(),
"end_ts": int(
(
talk.start + dt.timedelta(minutes=talk.duration)
).timestamp()
),
"slug": talk.frab_slug,
"title": talk.submission.title,
"persons": [
person.get_display_name()
for person in talk.submission.speakers.all()
],
"track": (
{
"color": talk.submission.track.color,
"name": str(talk.submission.track.name),
}
if talk.submission.track
else None
),
"room": room["name"].localize(schedule.event.locale),
"infoline": infoline.format(
**placeholders(
schedule, talk, supports_html_colour=True
)
),
"image_url": talk.submission.image_url,
"locale": talk.submission.content_locale,
"do_not_record": talk.submission.do_not_record,
"abstract": talk.submission.abstract,
"urls": {
"feedback": "{}{}".format(
schedule.event.custom_domain or settings.SITE_URL,
talk.submission.urls.feedback,
),
"feedback_qr": reverse(
"plugins:pretalx_broadcast_tools:feedback_qr_id",
kwargs={
"event": schedule.event.slug,
"talk": talk.submission.id,
},
),
"public": "{}{}".format(
schedule.event.custom_domain or settings.SITE_URL,
talk.submission.urls.public,
),
"public_qr": reverse(
"plugins:pretalx_broadcast_tools:public_qr_id",
kwargs={
"event": schedule.event.slug,
"talk": talk.submission.id,
},
),
},
}
for day in schedule.data
for room in day["rooms"]
for talk in room["talks"]
],
},
)
except KeyError as e:
key = str(e)[1:-1]
return JsonResponse(
{
"error": [
f"Could not find value for placeholder {{{key}}} in info line.",
f"If you want to use {{{key}}} without evaluating it, please use as follows: {{{{{key}}}}}",
],
}
)
except Exception as e:
return JsonResponse(
{
"error": [
repr(e),
],
}
)

View file

@ -0,0 +1,9 @@
from django.views.generic.base import TemplateView
class BroadcastToolsLowerThirdsView(TemplateView):
template_name = "pretalx_broadcast_tools/lower_thirds.html"
class BroadcastToolsRoomInfoView(TemplateView):
template_name = "pretalx_broadcast_tools/room_info.html"

41
pyproject.toml Normal file
View file

@ -0,0 +1,41 @@
[project]
name = "pretalx-broadcast-tools"
dynamic = ["version"]
description = """
Some tools which can be used for supporting a broadcasting software.
This currently includes a generator for PDF printouts, a 'lower thirds'
endpoint, and a full-screen webpage showing information about the
currently running talk.
"""
readme = "README.rst"
license = {text = "Apache Software License"}
keywords = ["pretalx"]
authors = [
{name = "Franziska Kunsmann", email = "git@kunsmann.eu"},
]
maintainers = [
{name = "Franziska Kunsmann", email = "git@kunsmann.eu"},
]
dependencies = [
]
[project.entry-points."pretalx.plugin"]
pretalx_broadcast_tools = "pretalx_broadcast_tools:PretalxPluginMeta"
[build-system]
build-backend = "setuptools.build_meta"
requires = ["setuptools", "wheel"]
[project.urls]
homepage = "https://github.com/Kunsi/pretalx-plugin-broadcast-tools"
repository = "https://github.com/Kunsi/pretalx-plugin-broadcast-tools.git"
[tool.setuptools]
include-package-data = true
[tool.setuptools.dynamic]
version = {attr = "pretalx_broadcast_tools.__version__"}
[tool.setuptools.packages.find]
include = ["pretalx*"]

View file

@ -1,46 +0,0 @@
import os
from distutils.command.build import build
from django.core import management
from setuptools import find_packages, setup
try:
with open(
os.path.join(os.path.dirname(__file__), "README.rst"), encoding="utf-8"
) as f:
long_description = f.read()
except FileNotFoundError:
long_description = ""
class CustomBuild(build):
def run(self):
management.call_command("compilemessages", verbosity=1)
build.run(self)
cmdclass = {"build": CustomBuild}
setup(
name="pretalx-plugin-broadcast-tools",
version="2.0.0",
description=(
"Some tools which can be used for supporting a broadcasting "
"software, for example a 'lower third' page which can be "
"embedded into your broadcasting software"
),
long_description=long_description,
url="https://github.com/Kunsi/pretalx-plugin-broadcast-tools",
author="kunsi",
author_email="git@kunsmann.eu",
license="Apache Software License",
install_requires=[],
packages=find_packages(exclude=["tests", "tests.*"]),
include_package_data=True,
cmdclass=cmdclass,
entry_points="""
[pretalx.plugin]
pretalx_broadcast_tools=pretalx_broadcast_tools:PretalxPluginMeta
""",
)