Compare commits

..

8 Commits

Author SHA1 Message Date
Ventilaar
ac0243a783 Quick key rename title_slug 2024-04-17 12:24:14 +02:00
Ventilaar
bb78c97d52 Do not store websub posted raw data as str 2024-04-10 11:25:05 +02:00
Ventilaar
7ccb827a9c hotfix the hotfix of the hotfix 2024-04-09 13:01:23 +02:00
Ventilaar
9c0e4fb63c Hotfix the websub hotfix. Add button to easily monitor websub callbacks. Clean stuck websub requests after 3 days 2024-04-09 12:56:57 +02:00
Ventilaar
75d42ad3cd Websub callback domain hotfix 2024-04-09 12:16:47 +02:00
Ventilaar
4fa0ee2c68 Hotfix channel sorting 2024-04-09 12:11:14 +02:00
Ventilaar
7e06c8673b Update PyJWT requirement 2024-04-06 23:27:18 +02:00
Ventilaar
96565e9e2b Add small time difference leeway 2024-04-06 23:23:32 +02:00
12 changed files with 35 additions and 19 deletions

View File

@@ -48,7 +48,7 @@ Extra functionality for further development of features.
- [x] Video reporting functionality - [x] Video reporting functionality
- [x] Ability (for external applications) to queue up video ids for download - [x] Ability (for external applications) to queue up video ids for download
- [x] Add websub requesting and receiving ability. (not fully usable yet without celery tasks) - [x] Add websub requesting and receiving ability. (not fully usable yet without celery tasks)
- [] OIDC or Webauthn logins instead of static argon2 passwords - [x] OIDC or Webauthn logins instead of static argon2 passwords
### Stage 3 ### Stage 3
Mainly focused on retiring the cronjob based scripts and moving it to celery based tasks Mainly focused on retiring the cronjob based scripts and moving it to celery based tasks

View File

@@ -33,7 +33,7 @@ def websub(cap):
return challenge return challenge
if get_nosql().websub_existsCallback(cap): if get_nosql().websub_existsCallback(cap):
if not get_nosql().websub_savePost(cap, str(request.data)): if not get_nosql().websub_savePost(cap, request.data):
return abort(500) return abort(500)
return '', 202 return '', 202

View File

@@ -34,7 +34,7 @@ def channel(channelId):
for videoId in videoIds: for videoId in videoIds:
videos.append(get_nosql().get_video_info(videoId, limited=True)) videos.append(get_nosql().get_video_info(videoId, limited=True))
videos = sorted(videos, key=lambda x: x.get('upload_date'), reverse=True) videos = sorted(videos, key=lambda x: x.get('upload_date', '19700101'), reverse=True)
return render_template('channel/channel.html', channel=channelInfo, videos=videos) return render_template('channel/channel.html', channel=channelInfo, videos=videos)

View File

@@ -216,7 +216,7 @@ class Mango:
def get_video_info(self, videoId, limited=False): def get_video_info(self, videoId, limited=False):
if limited: if limited:
projection = {'_id': 1, 'id': 1, 'title': 1, 'upload_date': 1, 'description': 1, 'channel_id': 1, 'uploader': 1, 'epoch': 1, 'title_slug': 1} projection = {'_id': 1, 'id': 1, 'title': 1, 'upload_date': 1, 'description': 1, 'channel_id': 1, 'uploader': 1, 'epoch': 1, '_title_slug': 1}
else: else:
projection = {} projection = {}
@@ -347,10 +347,24 @@ class Mango:
def websub_savePost(self, callbackId, data): def websub_savePost(self, callbackId, data):
return self.websub_data.insert_one({'callback_id': callbackId, 'state': 'unprocessed', 'received_time': current_time(object=True), 'raw_data': data}).inserted_id return self.websub_data.insert_one({'callback_id': callbackId, 'state': 'unprocessed', 'received_time': current_time(object=True), 'raw_data': data}).inserted_id
def websub_getFirstPostData(self):
data = self.websub_data.find_one({'state': 'unprocessed'}, {'_id': 1, 'raw_data': 1}, sort=[('received_time', 1)])
if not data:
return None
self.websub_data.update_one({'_id': data['_id']}, {'$set': {'state': 'processing'}})
return (data.get('_id'), data.get('raw_data'))
def websub_deletePostProcessing(self, _id):
self.websub_data.delete_one({'_id': _id})
def websub_cleanRetired(self, days=3): def websub_cleanRetired(self, days=3):
days = self.datetime.utcnow() - self.timedelta(days=days) days = self.datetime.utcnow() - self.timedelta(days=days)
self.websub_callbacks.delete_many({'status': 'retired', 'retired_time': {'$lt': days}}) self.websub_callbacks.delete_many({'status': 'retired', 'retired_time': {'$lt': days}})
self.websub_callbacks.delete_many({'status': 'requesting', 'requesting_time': {'$lt': days}})
return True return True

View File

@@ -114,8 +114,10 @@ class OIDC():
algorithms=jwt.algorithms.get_default_algorithms(), algorithms=jwt.algorithms.get_default_algorithms(),
issuer=self.provider, issuer=self.provider,
require=['aud', 'client_id', 'exp', 'iat', 'iss', 'rat', 'sub'], require=['aud', 'client_id', 'exp', 'iat', 'iss', 'rat', 'sub'],
audience=self.client_id) audience=self.client_id,
except: leeway=5)
except Exception as e:
print(e, flush=True)
return False return False
# double check if given token is really requested by us # double check if given token is really requested by us

View File

@@ -10,7 +10,7 @@ def subscribe_websub_callback(channelId):
url = 'https://pubsubhubbub.appspot.com/subscribe' url = 'https://pubsubhubbub.appspot.com/subscribe'
data = { data = {
'hub.callback': f'https://{current_app.config["DOMAIN"]}/api/websub//{callbackId}', 'hub.callback': f'{current_app.config["DOMAIN"]}/api/websub/{callbackId}',
'hub.topic': f'https://www.youtube.com/xml/feeds/videos.xml?channel_id={channelId}', 'hub.topic': f'https://www.youtube.com/xml/feeds/videos.xml?channel_id={channelId}',
'hub.verify': 'async', 'hub.verify': 'async',
'hub.mode': 'subscribe', 'hub.mode': 'subscribe',
@@ -32,7 +32,7 @@ def unsubscribe_websub_callback(callbackId, channelId):
from .nosql import get_nosql from .nosql import get_nosql
url = 'https://pubsubhubbub.appspot.com/subscribe' url = 'https://pubsubhubbub.appspot.com/subscribe'
data = {'hub.callback': f'https://{current_app.config["DOMAIN"]}/api/websub/{callbackId}', data = {'hub.callback': f'{current_app.config["DOMAIN"]}/api/websub/{callbackId}',
'hub.topic': f'https://www.youtube.com/xml/feeds/videos.xml?channel_id={channelId}', 'hub.topic': f'https://www.youtube.com/xml/feeds/videos.xml?channel_id={channelId}',
'hub.verify': 'async', 'hub.verify': 'async',
'hub.mode': 'unsubscribe' 'hub.mode': 'unsubscribe'

View File

@@ -50,6 +50,7 @@
{% for callback in callbacks %} {% for callback in callbacks %}
<tr class="filterable"> <tr class="filterable">
<td> <td>
<a target="_blank" rel="noopener noreferrer" href="https://pubsubhubbub.appspot.com/subscription-details?hub.callback={{ config['DOMAIN'] }}/api/websub/{{ callbacks[callback].get('id') }}&hub.topic=https://www.youtube.com/xml/feeds/videos.xml?channel_id={{ callbacks[callback].get('channel') }}"><button class="btn-small waves-effect waves-light" title="Information on Pubsubhubbub (external link)"></button></a>
<form method="post"> <form method="post">
<input type="text" value="{{ callbacks[callback].get('id') }}" name="value" hidden> <input type="text" value="{{ callbacks[callback].get('id') }}" name="value" hidden>
<button class="btn-small waves-effect waves-light" type="submit" name="task" value="unsubscribe" title="Send unsubscribe request to hub" {% if callbacks[callback].get('status') != 'active' %}disabled{% endif %}>🗑️</button> <button class="btn-small waves-effect waves-light" type="submit" name="task" value="unsubscribe" title="Send unsubscribe request to hub" {% if callbacks[callback].get('status') != 'active' %}disabled{% endif %}>🗑️</button>

View File

@@ -25,7 +25,7 @@
<div class="card medium black-text"> <div class="card medium black-text">
<a href="{{ url_for('watch.base') }}?v={{ video.get('id') }}"> <a href="{{ url_for('watch.base') }}?v={{ video.get('id') }}">
<div class="card-image"> <div class="card-image">
<img loading="lazy" src="https://archive.ventilaar.net/videos/automatic/{{ video.get('channel_id') }}/{{ video.get('id') }}/{{ video.get('title_slug') }}.jpg"> <img loading="lazy" src="https://archive.ventilaar.net/videos/automatic/{{ video.get('channel_id') }}/{{ video.get('id') }}/{{ video.get('_title_slug') }}.jpg">
</div> </div>
</a> </a>
<div class="card-content activator"> <div class="card-content activator">

View File

@@ -25,7 +25,7 @@
<div class="card medium black-text"> <div class="card medium black-text">
<a href="{{ url_for('watch.base') }}?v={{ video.get('id') }}"> <a href="{{ url_for('watch.base') }}?v={{ video.get('id') }}">
<div class="card-image"> <div class="card-image">
<img loading="lazy" src="https://archive.ventilaar.net/videos/automatic/{{ video.get('channel_id') }}/{{ video.get('id') }}/{{ video.get('title_slug') }}.jpg"> <img loading="lazy" src="https://archive.ventilaar.net/videos/automatic/{{ video.get('channel_id') }}/{{ video.get('id') }}/{{ video.get('_title_slug') }}.jpg">
</div> </div>
</a> </a>
<div class="card-content activator"> <div class="card-content activator">

View File

@@ -25,7 +25,7 @@
<div class="card medium black-text"> <div class="card medium black-text">
<a href="{{ url_for('watch.base') }}?v={{ video.get('id') }}"> <a href="{{ url_for('watch.base') }}?v={{ video.get('id') }}">
<div class="card-image"> <div class="card-image">
<img loading="lazy" src="https://archive.ventilaar.net/videos/automatic/{{ video.get('channel_id') }}/{{ video.get('id') }}/{{ video.get('title_slug') }}.jpg"> <img loading="lazy" src="https://archive.ventilaar.net/videos/automatic/{{ video.get('channel_id') }}/{{ video.get('id') }}/{{ video.get('_title_slug') }}.jpg">
</div> </div>
</a> </a>
<div class="card-content activator"> <div class="card-content activator">

View File

@@ -14,8 +14,8 @@
<div class="row"> <div class="row">
<div class="col s12 mt-4 center-align"> <div class="col s12 mt-4 center-align">
<video controls class="responsive-video"> <video controls class="responsive-video">
<source src="https://archive.ventilaar.net/videos/automatic/{{ render.get('info').get('channel_id') }}/{{ render.get('info').get('id') }}/{{ render.get('info').get('title_slug') }}.mp4"> <source src="https://archive.ventilaar.net/videos/automatic/{{ render.get('info').get('channel_id') }}/{{ render.get('info').get('id') }}/{{ render.get('info').get('_title_slug') }}.mp4">
<source src="https://archive.ventilaar.net/videos/automatic/{{ render.get('info').get('channel_id') }}/{{ render.get('info').get('id') }}/{{ render.get('info').get('title_slug') }}.webm"> <source src="https://archive.ventilaar.net/videos/automatic/{{ render.get('info').get('channel_id') }}/{{ render.get('info').get('id') }}/{{ render.get('info').get('_title_slug') }}.webm">
Your browser does not support the video tag. Your browser does not support the video tag.
</video> </video>
</div> </div>

View File

@@ -5,8 +5,7 @@ flask-caching
flask-limiter flask-limiter
pymongo pymongo
yt-dlp yt-dlp
argon2-cffi
gunicorn gunicorn
celery celery
sqlalchemy sqlalchemy
pyjwt pyjwt[crypto]