mirror of
https://github.com/minetest/contentdb.git
synced 2024-12-22 14:02:24 +01:00
parent
ee83a7b5ce
commit
5bd97598a8
@ -14,7 +14,9 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from flask import abort, send_file, Blueprint, current_app
|
import re
|
||||||
|
import requests
|
||||||
|
from flask import abort, send_file, Blueprint, current_app, request
|
||||||
import os
|
import os
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
|
||||||
@ -105,3 +107,26 @@ def make_thumbnail(img, level):
|
|||||||
res = send_file(cache_filepath)
|
res = send_file(cache_filepath)
|
||||||
res.headers["Cache-Control"] = "max-age=604800" # 1 week
|
res.headers["Cache-Control"] = "max-age=604800" # 1 week
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route("/thumbnails/youtube/<id_>.jpg")
|
||||||
|
def youtube(id_: str):
|
||||||
|
if not re.match(r"^[A-Za-z0-9\-_]+$", id_):
|
||||||
|
abort(400)
|
||||||
|
|
||||||
|
cache_dir = os.path.join(current_app.config["THUMBNAIL_DIR"], "youtube")
|
||||||
|
os.makedirs(cache_dir, exist_ok=True)
|
||||||
|
cache_filepath = os.path.join(cache_dir, id_ + ".jpg")
|
||||||
|
|
||||||
|
url = f"https://img.youtube.com/vi/{id_}/default.jpg"
|
||||||
|
|
||||||
|
response = requests.get(url, stream=True)
|
||||||
|
if response.status_code != 200:
|
||||||
|
abort(response.status_code)
|
||||||
|
|
||||||
|
with open(cache_filepath, "wb") as file:
|
||||||
|
file.write(response.content)
|
||||||
|
|
||||||
|
res = send_file(cache_filepath)
|
||||||
|
res.headers["Cache-Control"] = "max-age=604800" # 1 week
|
||||||
|
return res
|
||||||
|
@ -392,6 +392,19 @@ class Package(db.Model):
|
|||||||
def donate_url_actual(self):
|
def donate_url_actual(self):
|
||||||
return self.donate_url or self.author.donate_url
|
return self.donate_url or self.author.donate_url
|
||||||
|
|
||||||
|
@property
|
||||||
|
def video_thumbnail_url(self):
|
||||||
|
from app.utils.url import get_youtube_id
|
||||||
|
|
||||||
|
if self.video_url is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
id_ = get_youtube_id(self.video_url)
|
||||||
|
if id_:
|
||||||
|
return url_for("thumbnails.youtube", id_=id_)
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
enable_game_support_detection = db.Column(db.Boolean, nullable=False, default=True)
|
enable_game_support_detection = db.Column(db.Boolean, nullable=False, default=True)
|
||||||
|
|
||||||
translations = db.relationship("PackageTranslation", back_populates="package",
|
translations = db.relationship("PackageTranslation", back_populates="package",
|
||||||
|
@ -52,10 +52,21 @@
|
|||||||
justify-content: center !important;
|
justify-content: center !important;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
|
img {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
object-fit: cover;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
.fa-play {
|
.fa-play {
|
||||||
display: block;
|
display: block;
|
||||||
font-size: 200%;
|
font-size: 200%;
|
||||||
color: #f44;
|
color: #f44;
|
||||||
|
z-index: 20;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
@ -72,6 +83,7 @@
|
|||||||
right: 0.5rem;
|
right: 0.5rem;
|
||||||
color: #555;
|
color: #555;
|
||||||
font-size: 80%;
|
font-size: 80%;
|
||||||
|
z-index: 30;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
<link rel="stylesheet" type="text/css" href="/static/libs/bootstrap.min.css?v=4">
|
<link rel="stylesheet" type="text/css" href="/static/libs/bootstrap.min.css?v=4">
|
||||||
<link rel="stylesheet" type="text/css" href="/static/custom.css?v=51">
|
<link rel="stylesheet" type="text/css" href="/static/custom.css?v=52">
|
||||||
<link rel="search" type="application/opensearchdescription+xml" href="/static/opensearch.xml" title="ContentDB" />
|
<link rel="search" type="application/opensearchdescription+xml" href="/static/opensearch.xml" title="ContentDB" />
|
||||||
|
|
||||||
{% if noindex -%}
|
{% if noindex -%}
|
||||||
|
@ -292,6 +292,10 @@
|
|||||||
{% if package.video_url %}
|
{% if package.video_url %}
|
||||||
<li>
|
<li>
|
||||||
<a href="{{ package.video_url }}" class="video-embed">
|
<a href="{{ package.video_url }}" class="video-embed">
|
||||||
|
{% set thumbnail_url = package.video_thumbnail_url %}
|
||||||
|
{% if thumbnail_url %}
|
||||||
|
<img src="{{ thumbnail_url }}" alt="{{ _('Thumbnail for video') }}" />
|
||||||
|
{% endif %}
|
||||||
<i class="fas fa-play"></i>
|
<i class="fas fa-play"></i>
|
||||||
<div class="label">
|
<div class="label">
|
||||||
<i class="fas fa-external-link-square-alt"></i>
|
<i class="fas fa-external-link-square-alt"></i>
|
||||||
|
@ -31,16 +31,22 @@ def url_get_query(parsed_url: urlparse.ParseResult) -> Dict[str, List[str]]:
|
|||||||
return urlparse.parse_qs(parsed_url.query)
|
return urlparse.parse_qs(parsed_url.query)
|
||||||
|
|
||||||
|
|
||||||
def clean_youtube_url(url: str) -> Optional[str]:
|
def get_youtube_id(url: str) -> Optional[str]:
|
||||||
parsed = urlparse.urlparse(url)
|
parsed = urlparse.urlparse(url)
|
||||||
print(parsed)
|
|
||||||
if (parsed.netloc == "www.youtube.com" or parsed.netloc == "youtube.com") and parsed.path == "/watch":
|
if (parsed.netloc == "www.youtube.com" or parsed.netloc == "youtube.com") and parsed.path == "/watch":
|
||||||
print(url_get_query(parsed))
|
|
||||||
video_id = url_get_query(parsed).get("v", [None])[0]
|
video_id = url_get_query(parsed).get("v", [None])[0]
|
||||||
if video_id:
|
if video_id:
|
||||||
return url_set_query("https://www.youtube.com/watch", {"v": video_id})
|
return video_id
|
||||||
|
|
||||||
elif parsed.netloc == "youtu.be":
|
elif parsed.netloc == "youtu.be":
|
||||||
return url_set_query("https://www.youtube.com/watch", {"v": parsed.path[1:]})
|
return parsed.path[1:]
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def clean_youtube_url(url: str) -> Optional[str]:
|
||||||
|
id_ = get_youtube_id(url)
|
||||||
|
if id_:
|
||||||
|
return url_set_query("https://www.youtube.com/watch", {"v": id_})
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
Loading…
Reference in New Issue
Block a user