This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import mimetypes
import re
from types import SimpleNamespace
from urllib.parse import parse_qs, urlparse
import bleach
import emoji
import requests
from app.cache import time_cache
from bs4 import BeautifulSoup
from jinja2 import TemplateSyntaxError, nodes
from jinja2.ext import Extension
from jinja2.nodes import Const
emoji.EMOJI_DATA['<img src="/emoji/snek1.gif" />'] = {
"en": ":snek1:",
"status": 2,
"E": 0.6,
"alias": [":snek1:"],
}
emoji.EMOJI_DATA[
"""
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣠⣤⡴⠶⢶⣞⣛⣛⡳⣳⠶⣶⡶⢶⢶⣦⣤⣄⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⣤⠶⠚⣫⣴⣬⠐⣶⣿⣿⣏⣽⣿⣿⣇⢿⣯⣿⣿⣻⣿⣿⣾⣮⣹⣿⢶⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣴⢾⣻⣽⣾⡇⢡⣿⣿⣇⡟⣿⣿⣿⣼⣿⣿⣿⣿⢸⣿⣟⣿⣷⢻⣿⣿⣿⣷⡽⣧⣹⡻⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⠟⣫⣶⣿⣟⣾⡿⠀⣾⣿⣿⢹⢿⣿⣿⣏⣿⣿⣿⣿⣿⣺⣿⡏⣿⣿⣏⣿⣿⣿⣿⣿⣞⣿⣿⣯⡻⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡀⠀⠀⠀⠀⠀⠀⠀⣠⡴⣛⣵⣻⣟⣿⢯⣿⢟⡆⣀⣿⣿⣿⣿⣾⣿⣿⢹⣿⣿⣿⣿⣿⢸⣿⣿⣿⣿⣿⣸⣿⣿⣿⣿⣿⡾⣿⣻⣿⣮⠻⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⡀⠀⠀⠀⢀⣠⡾⣻⣾⡿⣳⡟⣾⢿⣿⢯⣿⡇⢸⣿⣿⣿⣇⣿⣿⡿⣿⣿⣿⣿⣿⣿⣾⣿⣿⣿⣿⣿⢿⣿⣿⣿⣿⣿⣿⢻⣏⣿⣿⡵⣝⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢻⣟⢧⣤⣶⢾⣻⣿⣾⣿⣿⢳⣿⢻⣏⣿⢿⣿⡿⠀⣾⣿⣿⣿⢹⣿⣿⣗⣿⣿⣿⣿⣿⢏⣿⣿⠋⣿⣿⡟⡈⣿⣿⣿⠸⣿⣿⣹⣿⢸⣿⣧⢻⣮⢿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠛⠿⠿⠿⢿⡟⣿⣿⣿⢧⣿⣟⡟⣾⣯⣿⡿⣽⡇⣿⣿⣿⣿⣸⣿⣿⠹⣿⡿⢻⡿⢣⣿⡿⣳⣖⣿⣿⢱⣿⢹⣿⣿⠀⣿⣿⠘⣿⡞⣿⣿⡸⣿⣯⢿⣦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣼⣿⣿⡿⣼⣿⣿⢧⣿⣼⣿⣻⣿⡃⣿⣿⣿⣿⣿⣿⣿⣀⣿⢧⠘⣣⢸⡿⣻⣿⣿⡘⠟⣿⣿⡘⠿⠟⣟⣻⡿⣀⢿⡇⢻⣿⡇⣿⣿⢸⣿⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣏⣿⣿⣿⢳⣿⣿⣿⣸⢷⣿⢷⣿⢟⢨⣿⣿⣿⣿⣿⣿⣯⣿⣦⠖⠘⡛⣡⠬⠭⠭⠛⠂⠰⣿⣿⡇⠀⣰⡏⢛⣴⣿⡏⢸⣼⡿⠇⣿⣿⣧⣿⣿⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⣹⣿⣿⡏⣿⣿⣿⡇⣿⣾⣯⣿⣯⡿⢸⣿⣿⣿⣿⣿⢿⡃⣽⣶⣿⣿⣿⣿⣿⣿⣿⣷⣤⣗⠊⣻⣿⣶⣿⣶⣿⣿⣿⡇⣾⠏⡁⠀⣿⣿⣧⣹⣿⣿⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⣧⣿⣿⣿⣹⣿⣿⣿⡇⣿⡿⣾⠳⠋⣄⣼⣿⣿⣿⣻⣾⣿⢹⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣫⣤⣄⣀⣿⠇⣿⣿⣿⣻⡌⣿⣿⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⣸⣿⣿⣏⣿⣿⣿⣿⣿⣿⣷⣇⢀⣾⡋⣽⣿⣿⣿⣿⣿⣿⢹⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⣱⣿⣿⣿⣿⣿⡇⣬⣻⣿⣽⡇⠸⣿⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⣇⣿⣿⣿⣹⣿⣿⢏⣅⢀⠲⣤⣙⠼⢿⡇⣿⣿⣿⣿⣿⡿⠿⠻⠟⠻⠿⠿⣷⣽⡻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣵⣿⣿⣿⣿⣿⣿⡇⣿⣧⣿⢾⡇⠀⢿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⢸⣿⣿⡿⣾⣿⣏⣾⠇⠈⠀⠈⢻⣿⣷⡁⣿⣿⣿⣿⣿⣧⣤⣴⣶⠀⠀⠀⠀⣊⡙⠻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠟⣻⣿⡇⣿⣿⣿⣻⡇⠀⢸⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡏⣿⣿⣿⡗⣿⣿⢸⡟⣼⣀⠏⠁⡀⢿⣿⡇⣹⣿⣿⣿⣿⣿⡇⢿⣯⠀⡄⠀⠁⠉⠙⣿⣮⡝⣿⣿⣿⣿⣿⣿⣿⣿⡿⠟⠁⠀⣀⣀⡀⠁⢿⣻⣿⣿⡇⠀⠈⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⢣⣿⣿⣿⢸⣿⣏⢾⡧⡿⠋⠉⢁⣡⣿⣿⣧⣿⣿⣿⣿⣿⣿⣃⣷⣝⣀⣽⣤⣧⣤⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡀⣀⠀⠀⠉⢩⣿⡇⣶⣳⣿⣽⡇⠀⢠⡿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⣸⣿⣿⡿⣼⣿⣷⠸⠃⢻⡜⢿⣿⢟⣿⣿⣿⣿⣿⣿⣿⣿⣿⢀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⣿⣷⣥⣤⣥⣤⣿⣿⡅⣿⣿⣿⣿⡇⠀⣼⣿⡏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡇⣿⣿⣿⣿⣿⣿⣿⣄⢷⣄⣉⠮⠉⠙⢿⣿⣿⣿⣿⣿⣿⣿⣿⢼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⢹⣿⣿⣿⣿⣿⣿⣿⡇⣿⣿⣿⣿⡇⢼⣿⡟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⢧⣿⣿⣿⣿⣿⣿⣿⣿⣮⢿⣿⣿⣷⣦⡈⢿⣿⣿⣿⣿⣿⣿⣿⢻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⢇⣿⣿⣿⣿⣿⣿⣿⣇⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣵⡝⢿⣿⣿⣿⣶⣍⣿⣿⣿⣿⣿⣿⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⢉⣾⣿⣿⣿⣿⣿⣿⣿⢹⣿⣿⣿⢿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠰⡟⣾⣿⣿⣿⣿⣿⣿⣿⣿⡟⣿⢻⢳⢸⢩⣟⣛⠓⣿⣿⣿⣿⣿⣿⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣿⣿⣿⣿⣿⣿⣿⣿⡿⢸⣿⣿⣿⣼⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡇⣿⣿⣿⣿⣿⠇⣿⣿⣿⠇⣿⢸⢸⣸⡇⢸⣿⠇⣿⣿⣿⣿⣿⣿⢹⣿⣯⣽⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⢿⢿⠛⢻⣿⣿⣿⣿⣿⣿⣿⠃⢸⣿⣿⣿⢾⡃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣷⣿⣿⣿⣿⣿⠀⣿⣻⣿⢹⣿⣸⠘⡿⡇⢸⣿⡄⢿⣿⣿⣿⣿⣿⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⢛⣵⣶⣶⣬⠀⢠⣿⣿⣿⣿⣿⣿⣿⠏⢄⣸⣿⣿⣿⣿⡁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⢸⣿⣿⣿⣿⡟⢸⡿⣿⣿⢸⡇⡖⡄⠇⣇⢸⣿⡓⢻⣿⣿⣿⣿⣿⢺⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⣿⣿⣿⣿⣿⢧⣿⣿⣿⣿⣿⣿⣿⠋⢨⠀⣿⣿⣿⣏⣿⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⡏⣾⣿⣿⣿⣿⠃⣼⣷⣿⡏⣿⣿⠇⢹⢸⣿⢺⣿⣿⢸⣿⣿⣿⣿⣿⠸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣄⣙⡛⣛⢡⣾⣿⠻⢿⣿⣿⣟⣱⡆⠨⠀⣿⣿⢿⡗⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⣹⣿⣿⣿⣿⣿⠀⣼⣹⣿⢣⣿⣿⢠⣸⣼⣿⡞⣿⣿⣾⣿⣿⣿⣿⣿⢸⣦⣟⢿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣷⣾⢿⣿⣿⠈⢷⡝⢻⡊⠁⣧⠀⠃⣿⣿⡆⢋⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⢯⣿⣿⣿⣿⣿⣿⡄⣿⣿⣿⣸⣿⣿⣸⢻⣿⣿⡗⣿⣿⡏⣿⣿⣿⣿⣿⠈⣿⣿⣬⣙⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣾⣿⣿⡆⢨⣁⣘⣷⣄⣿⠀⢠⣿⣿⣣⣈⣿⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣟⣿⣿⣿⣿⣿⣿⣿⢀⠯⣿⡏⣿⣿⡇⢻⣽⣿⣿⣟⣻⣿⡇⣿⣿⡏⣿⣿⣰⡼⢺⡾⣏⣿⣨⡟⠿⣿⣿⣿⣿⣿⣿⣿⢟⡉⡆⡎⠿⣿⣿⣮⡻⡇⢸⣿⣏⢿⣿⣞⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣟⣾⣿⣿⢇⣾⣿⣿⢋⣠⢰⣿⢿⣿⣿⢰⢸⢹⣿⣿⣿⣸⣿⣧⣿⣿⡇⣿⣿⢼⣿⣦⡹⢹⡜⣇⢿⣹⣶⣍⡛⠻⠿⣫⡖⡟⣠⣱⣧⣿⣞⣻⣿⣿⣦⡸⣿⣿⡜⣿⣿⣯⢿⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⢟⣾⣿⣿⢏⣾⣿⣿⡏⣾⡏⢸⣿⣾⣿⡇⠆⣿⢸⣿⣿⣿⡏⣿⣷⢹⣿⣷⣿⣿⢸⣿⣿⣿⣦⡻⡸⡞⣧⢿⠧⣇⠙⠿⣿⣼⢣⠃⢋⠃⣿⠈⠳⣝⢿⣿⣿⣮⣝⢿⡼⣿⣿⣷⡩⣽⣻⢶⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⢯⣿⣿⡿⣳⣿⣿⣿⡿⢸⣿⠇⣺⣿⢯⣿⡝⣸⡿⡘⣽⣿⣿⣗⢿⣿⢸⣿⣿⣿⣿⠦⣿⣿⣿⣿⣿⣶⣭⣘⠎⠘⢣⣷⡆⠂⠥⠁⣂⡟⠟⢿⣀⠀⠉⠳⣝⢿⣿⣿⣿⣦⣙⣿⣿⣿⣎⣿⣷⣝⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⡾⣵⣿⣿⣏⢼⣿⣽⣿⡿⣁⣿⡿⠸⠹⢫⣿⣟⣼⣿⠃⣵⣿⡿⢸⣿⠘⣿⠘⣿⡏⣿⣿⡇⣿⣿⣿⣿⣿⣿⣿⣿⣿⢲⣸⡿⣳⣮⣝⡿⣿⣿⣿⣾⣿⣿⣿⣶⣿⣷⡎⠻⣿⣿⣿⣿⣷⣿⡻⢸⡿⣿⣿⣽⣧⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⢟⣼⡿⣯⡿⣯⣿⢳⣿⣿⠗⡋⠁⠀⠀⠈⠒⢦⣝⠻⣷⣿⡿⢟⡥⣼⣿⠀⠹⢀⣿⡿⣿⣿⡏⢹⣿⣿⣿⣿⣿⣿⣿⣿⠸⢺⡇⡇⣿⢸⣿⡆⣭⣛⠿⢿⣿⣿⣿⣿⣿⣿⣿⣿⣶⣾⣿⣿⣿⣿⡼⡇⣿⣿⣿⣯⢷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⡾⣣⡿⢋⡾⠋⣼⢳⣿⢿⠟⠡⢈⣥⠶⠟⠛⠿⠷⣦⣽⣷⣤⡐⢾⣿⣷⣿⢏⣀⡀⠀⣿⣷⣿⣿⣿⢨⢿⣿⣿⣿⣿⣿⣿⣿⢸⠾⡧⣿⢿⣸⣿⣶⢸⣿⣿⡗⠶⢯⣭⣛⡻⡿⠿⢿⣿⣿⣿⣭⣝⣻⡇⣻⣿⣻⢿⣿⣧⠙⢷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣟⣽⢟⣵⠟⠀⢰⡿⣾⡿⢉⣶⡾⠋⠁⠀⠀⠀⠀⠀⠀⠉⠙⠿⣿⣦⠈⠉⠠⠀⠻⣿⠀⣿⣿⣿⣿⣿⣺⣟⣿⣿⣿⣿⣿⣿⡇⢸⣶⡟⢿⡼⠇⠿⣱⠘⣿⣧⣷⠀⠀⢀⣩⡇⠿⣟⣃⣬⣿⣿⣿⣿⣿⡇⣿⢸⣿⣷⣽⣿⣯⡨⠻⣦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⢿⣾⣷⠟⠁⠀⠀⣾⢿⣿⠃⡞⣩⣶⣿⣿⣿⣿⣷⣦⡄⠀⠀⠀⠀⣠⣼⣷⡀⠀⢣⠀⠘⠃⣿⣿⣿⣿⣿⣏⣿⣞⣿⣿⣿⣿⣿⡇⠀⠈⠑⠾⢧⣾⡞⣵⣷⢻⣿⠻⣶⣟⣿⣽⣶⣿⣿⣿⣿⣿⣿⣿⣽⣿⡇⣿⠈⣿⣿⣿⣿⣻⣧⢱⣜⢿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⡿⠁⠀⠀⠀⢸⡟⣿⠇⢀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡄⠀⠀⣴⣿⣿⣿⣿⣄⠀⣃⠀⠀⣿⣿⢹⣿⣿⣇⢿⣿⣞⢿⣿⣿⣿⡇⢠⣤⣤⣄⡀⢤⣬⠁⠈⠁⣿⣾⣿⣿⡿⢿⣻⢛⣭⣿⢏⣼⣿⣿⣿⣿⠇⣮⣤⣿⣿⣿⣿⣿⣿⣇⢿⣎⢿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠛⠋⠀⠀⠀⠀⢀⣿⢻⡟⢠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠀⠀⣼⣿⣿⣿⣿⣿⣿⣦⠘⡇⡀⣿⣿⢸⣿⣿⣿⠸⣿⣿⣾⣿⣿⣿⡇⢰⣬⣝⡻⢿⣇⣂⣬⣤⣙⡋⠭⢥⣀⣀⠈⠙⠃⣫⣷⣿⣿⣿⣿⣭⣿⢢⣿⣿⣿⣿⣿⣿⣿⣿⣿⠈⣿⣎⢿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⡟⣾⢁⣾⣿⠉⠙⣿⣿⣿⣿⣿⣿⡿⠁⠀⣼⣿⣿⣿⣿⡿⠿⣿⣿⡇⢁⣿⢹⣿⣾⣿⣿⣿⡄⣜⢿⣿⣿⣿⣿⣿⠀⠻⣿⣿⣶⣍⠻⣿⣿⣿⣿⡿⢃⣾⠏⣠⣴⣿⣿⡿⠿⣛⢩⡜⢿⢏⢼⣿⣿⣿⣿⣿⣾⢿⣿⣿⠀⣿⢻⣎⣿⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⢹⡟⣸⣿⡇⠀⠀⠈⢿⣿⣿⡿⠋⠀⠀⢠⣿⡿⠟⠉⠁⣠⡾⢋⣿⣧⠘⠻⢸⣿⣏⣿⣿⣿⣧⢉⣓⣈⢛⡿⠿⣿⣦⣶⣿⣿⣿⠿⣂⣤⡽⣿⠏⣴⡿⢋⣾⡿⠟⠋⠐⣾⣿⣿⡄⠻⣶⢿⣣⣮⣝⢿⣿⣿⣿⣷⡻⣿⠀⡟⠈⣿⡜⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣾⡏⣿⡇⣿⣿⠃⠀⠀⠀⠀⠙⠉⠀⠀⠀⠀⠘⠉⠀⣀⣴⡾⢋⣵⣿⣿⣧⡄⠀⢸⣿⣿⣿⣿⣿⣿⡄⠙⠛⢓⣙⢿⣷⣾⣿⣿⣿⣵⣾⣿⣿⣧⣄⣸⠋⢤⡬⠥⠀⠀⢶⡄⠈⠹⣿⣇⢀⠈⢝⣿⣿⣿⣿⡽⣿⣿⣿⡿⠁⢠⡇⠀⢻⣿⣹⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⡿⣸⣿⣷⠸⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⣴⣾⠟⣩⣶⣿⣿⣿⣿⣿⣿⠀⢸⣿⣿⣿⣿⣿⣿⣧⠸⠛⣛⣯⣤⣿⡻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⣔⢶⣶⣷⡀⢻⣄⠀⠙⠿⣎⠀⠈⠻⣿⣿⣿⣿⣟⣿⢿⠁⠀⣼⠀⠀⠘⣿⣧⢻⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⢣⣿⣿⣿⡇⠃⠀⠀⠀⠀⠀⠀⠀⣀⣤⣾⣿⡿⢛⣥⣾⣿⣿⣿⣿⣿⣿⣿⡟⠀⢸⣿⣿⣿⣿⣿⣿⣿⡄⢶⣭⣙⡛⠿⢿⣾⣝⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⡻⢿⣀⠙⠂⠀⣀⠈⠑⠀⠀⠀⢠⣮⠍⡉⢠⡌⠁⠀⠇⢀⣤⡀⢻⡟⢏⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣏⣿⣿⣿⣿⣠⠈⠀⠀⢀⣠⣴⣾⣿⣿⣿⠟⣋⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟⠁⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⡀⠉⡛⢿⣷⣦⣬⣉⠓⢮⡻⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣝⠦⠀⠂⠙⣷⣄⡀⠀⠀⠀⠀⠀⠐⠀⠀⠀⣶⠀⣸⣿⡇⠸⣇⠘⡜⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⡟⣼⣿⣿⣿⡏⣿⢰⣶⣿⠛⠛⠛⠉⠉⠁⢠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⢻⣿⣧⠀⢹⣷⣮⠛⣿⣿⣿⣦⡌⠐⡝⢻⣿⣿⣿⣶⣽⣿⣿⣿⣿⣿⣷⡄⠀⢠⢹⣿⣿⣷⡄⠀⠀⠀⠀⠀⠀⣼⠃⠀⠘⣿⠃⠀⣭⠀⢻⠙⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⢳⣿⣿⣿⣿⣷⣿⡆⣿⠃⠀⠀⠀⠀⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⠀⢠⡇⢰⠂⣿⣿⣿⣿⣿⣿⡈⢿⣿⡄⠈⣿⣿⣷⣤⡉⠛⠿⣿⣷⣦⣔⡙⠻⣿⣿⣿⣿⣝⢿⣿⣿⣿⣿⣦⡀⢈⢻⣿⣿⣿⣄⢤⣀⠀⢀⣴⠏⠀⠀⠀⠀⠀⣾⣿⡇⢸⣧⢻⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣾⢯⣿⣿⣿⣿⣿⣿⣿⡇⣇⢀⣀⣤⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⣡⠄⠀⣼⡇⢺⠁⣿⣿⣧⣿⣿⣿⡇⠈⢿⣿⡀⢹⣿⣿⣿⣿⣯⣻⣶⣯⣽⣿⠿⣿⣾⣽⣻⢿⣿⣿⣽⣿⢿⣿⣿⣿⣞⣇⢙⢿⣿⣿⣯⣻⣿⣶⣤⣀⠀⠀⠀⠀⠀⢻⡿⠁⠈⣿⣧⢻⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⣏⣿⣿⣿⣿⢿⣿⣿⡿⢃⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏⠁⢹⣿⣿⣿⣿⡟⠀⣸⣿⡇⠈⠀⣿⣿⣿⣿⡏⣿⣧⠀⠀⠻⣷⡜⣿⣿⣿⣿⣿⣿⣷⣽⡻⣿⣿⣷⣿⣽⣛⡿⢾⣽⣛⢿⣿⣾⣝⡿⣿⣯⡃⢣⡻⣿⣿⣷⡽⣿⣿⣿⣷⣦⣀⠀⠀⠀⠀⠀⠀⢿⣿⣧⢻⡄⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣟⣿⣿⢯⣿⢏⣾⣿⣿⢃⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠁⠀⣠⣿⣿⣿⣿⣿⠀⣸⣿⣿⡇⠀⠀⣿⣿⢹⣿⡇⢻⣿⠀⠀⢠⡌⠿⣜⢿⣿⣿⣿⣿⣿⣿⣿⣾⣝⡿⣿⣿⣿⣿⣿⣶⣯⣝⣊⠽⢛⠿⣷⣝⢷⣤⠳⡜⢿⣿⣿⣝⣿⣿⣿⣿⣿⣷⣄⠀⠀⠀⠀⢸⣿⣿⢸⡇⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⡟⣾⣿⣯⣿⢣⣾⣿⣿⣿⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⣠⣼⣿⣿⣿⣿⣿⠃⣰⣿⣿⣿⡇⡄⠀⣿⣿⢸⣿⡇⠈⢿⡇⠀⣿⠇⣷⣯⣃⣙⣛⣛⣵⣿⣿⣿⣿⣿⣿⣾⣝⡻⣿⣿⣿⣿⣿⣿⣿⣷⣮⣄⡈⠳⢜⠃⠘⢎⢿⣿⣿⣞⢿⣿⣿⣿⣿⣿⣷⣆⡀⠀⠘⣿⡟⢸⡇⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣟⣽⣿⣯⣿⣣⣿⣿⣿⣿⣿⡄⢿⣿⣿⣿⣿⣿⣿⡿⠟⣡⣾⣿⣿⣿⣿⣿⣿⡏⣰⣿⣿⡿⢹⡇⣾⠀⣿⣿⣾⣿⡇⠀⠈⢷⢰⣿⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣽⣻⢿⣿⣿⣿⣿⣿⣿⣿⣷⣦⣦⣀⡀⠈⠛⠻⢿⣎⢿⣿⣿⣿⣿⣿⣿⣷⣄⠀⣿⡇⠘⣧⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣴⢟⣾⣿⣻⡿⣵⣿⣿⣿⣿⣟⣾⣯⠌⠛⠛⠛⠛⠉⠁⢠⣾⣿⣿⣿⣿⣿⣿⡿⠏⣰⣿⣿⡿⠁⢸⡇⢿⠀⣿⣿⣿⣿⡇⠀⠠⠈⠂⢃⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣾⣿⣻⡿⣿⣿⣿⣿⣿⣿⣿⡇⡄⠾⣲⣾⣿⣌⢿⣿⣿⣿⣿⣿⣿⣿⣧⡙⠇⠀⢻⡄⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠛⠚⠛⠛⠛⠚⠛⠛⠛⠛⠛⠚⠛⠛⠓⠚⠒⠛⠒⠛⠛⠛⠛⠛⠛⠛⠛⠛⠛⠛⠚⠛⠛⠛⠛⠓⠛⠛⠛⠓⠛⠛⠛⠛⠓⠚⠛⠛⠓⠚⠛⠛⠛⠛⠛⠛⠛⠛⠛⠛⠛⠛⠛⠛⠛⠛⠛⠛⠛⠛⠛⠛⠛⠛⠛⠚⠛⠛⠛⠛⠛⠛⠓⠛⠚⠛⠛⠛⠛⠓⠛⠛⠛⠛⠛⠛⠛⠛⠛⠒⠚⠚⠁⠀⠀⠀⠀⠀⠀⠀
"""
] = {"en": ":a1:", "status": 2, "E": 0.6, "alias": [":a1:"]}
ALLOWED_TAGS = list(bleach.sanitizer.ALLOWED_TAGS) + [
"img",
"video",
"audio",
"source",
"iframe",
"picture",
"span",
]
ALLOWED_ATTRIBUTES = {
**bleach.sanitizer.ALLOWED_ATTRIBUTES,
"img": ["src", "alt", "title", "width", "height"],
"a": ["href", "title", "target", "rel", "referrerpolicy", "class"],
"iframe": [
"src",
"width",
"height",
"frameborder",
"allow",
"allowfullscreen",
"title",
"referrerpolicy",
"style",
],
"video": ["src", "controls", "width", "height"],
"audio": ["src", "controls"],
"source": ["src", "type"],
"span": ["class"],
"picture": [],
}
def sanitize_html(value):
return bleach.clean(
value,
tags=ALLOWED_TAGS,
attributes=ALLOWED_ATTRIBUTES,
protocols=bleach.sanitizer.ALLOWED_PROTOCOLS + ["data"],
strip=True,
)
def set_link_target_blank(text):
soup = BeautifulSoup(text, "html.parser")
for element in soup.find_all("a"):
element.attrs["target"] = "_blank"
element.attrs["rel"] = "noopener noreferrer"
element.attrs["referrerpolicy"] = "no-referrer"
element.attrs["href"] = element.attrs["href"].strip(".").strip(",")
return str(soup)
SAFE_ATTRIBUTES = {
"href",
"src",
"alt",
"title",
"width",
"height",
"style",
"id",
"class",
"rel",
"type",
"name",
"value",
"placeholder",
"aria-hidden",
"aria-label",
"srcset",
}
def whitelist_attributes(html):
soup = BeautifulSoup(html, "html.parser")
for tag in soup.find_all():
if hasattr(tag, "attrs"):
if tag.name in ["script", "form", "input"]:
tag.replace_with("")
continue
attrs = dict(tag.attrs)
for attr in list(attrs):
# Check if attribute is in the safe list or is a data-* attribute
if not (attr in SAFE_ATTRIBUTES or attr.startswith("data-")):
del tag.attrs[attr]
return str(soup)
def embed_youtube(text):
soup = BeautifulSoup(text, "html.parser")
for element in soup.find_all("a"):
# Check if the link is a YouTube link
url = urlparse(element["href"])
if (
url.hostname in ["www.youtu.be", "youtu.be"]
or url.hostname
in [
"www.youtube.com",
"music.youtube.com",
"youtube.com",
"www.youtube-nocookie.com",
"youtube-nocookie.com",
]
and any(url.path.startswith(p) for p in ["/watch", "/embed"])
):
queries = parse_qs(url.query)
if "v" in queries:
video_name = queries["v"][0]
else:
video_name = url.path.split("/")[-1]
queries.pop("v", None)
start_time = queries.get("t", None)
if start_time:
queries.pop("t", None)
queries["start"] = []
for t in start_time:
if t.endswith("s"):
t = t[:-1]
if t.isdigit():
queries["start"].append(t)
else:
queries["start"].append(
str(
sum(
int(x) * 60**i
for i, x in enumerate(reversed(t.split(":")))
)
)
)
new_queries = "&".join(
[f"{key}={v}" for key, value in queries.items() for v in value]
)
base_url = (
"youtube-nocookie.com"
if "youtube-nocookie" in url.hostname
else "youtube.com"
)
embed_template = f'<iframe width="560" height="315" style="display:block" src="https://www.{base_url}/embed/{video_name}?{new_queries}" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>'
element.replace_with(BeautifulSoup(embed_template, "html.parser"))
return str(soup)
def embed_image(text):
soup = BeautifulSoup(text, "html.parser")
for element in soup.find_all("a"):
file_mime = mimetypes.guess_type(element.attrs["href"])[0]
if (
file_mime
and file_mime.startswith("image/")
or any(
ext in element.attrs["href"].lower()
for ext in [
".png",
".jpg",
".jpeg",
".gif",
".webp",
".svg",
".bmp",
".tiff",
".ico",
".heif",
".heic",
]
)
):
embed_template = f'<img src="{element.attrs["href"]}" title="{element.attrs["href"]}?width=420" alt="{element.attrs["href"]}" />'
element.replace_with(BeautifulSoup(embed_template, "html.parser"))
return str(soup)
def enrich_image_rendering(text):
soup = BeautifulSoup(text, "html.parser")
for element in soup.find_all("img"):
if element.attrs["src"].startswith("/"):
element.attrs["src"] += "?width=240&height=240"
picture_template = f"""
<picture>
<source srcset="{element.attrs["src"]}" type="{mimetypes.guess_type(element.attrs["src"])[0]}" />
<source srcset="{element.attrs["src"]}&format=webp" type="image/webp" />
<img src="{element.attrs["src"]}&format=png" title="{element.attrs["src"]}" alt="{element.attrs["src"]}" />
</picture>"""
element.replace_with(BeautifulSoup(picture_template, "html.parser"))
return str(soup)
def embed_media(text):
soup = BeautifulSoup(text, "html.parser")
for element in soup.find_all("a"):
for extension in [
".mp4",
".mp3",
".wav",
".ogg",
".webm",
".flac",
".aac",
".mpg",
".avi",
".wmv",
]:
if extension in element.attrs["href"].lower():
embed_template = f'<video controls> <source src="{element.attrs["href"]}">Your browser does not support the video tag.</video>'
element.replace_with(BeautifulSoup(embed_template, "html.parser"))
return str(soup)
def linkify_https(text):
if "https://" not in text:
return text
url_pattern = r'(?<!["\'])\bhttps://[^\s<>()]+(?<!\.)'
soup = BeautifulSoup(text, "html.parser")
for element in soup.find_all(text=True):
parent = element.parent
if parent.name in ["a", "script", "style"]:
continue
new_text = re.sub(url_pattern, r'<a href="\g<0>">\g<0></a>', element)
element.replace_with(BeautifulSoup(new_text, "html.parser"))
return set_link_target_blank(str(soup))
@time_cache(timeout=60 * 60)
def get_url_content(url):
try:
response = requests.get(url, timeout=5)
response.raise_for_status()
return response.text
except Exception as e:
print(f"Error fetching {url}: {e}")
return None
def embed_url(text):
soup = BeautifulSoup(text, "html.parser")
attachments = {}
for element in soup.find_all("a"):
if "href" in element.attrs and element.attrs["href"].startswith("http") and ("data-noembed" not in element.attrs):
page_url = urlparse(element.attrs["href"])
page = get_url_content(element.attrs["href"])
if page:
parsed_page = BeautifulSoup(page, "html.parser")
head_info = parsed_page.find("head")
if head_info:
def get_element_options(
elem=None, meta=None, ograph=None, twitter=None
):
if twitter:
tw_tag = head_info.find(
"meta", attrs={"name": "twitter:" + twitter}
) or head_info.find(
"meta", attrs={"property": "twitter:" + twitter}
)
if tw_tag:
return tw_tag.get("content", tw_tag.get("value", None))
if ograph:
og_tag = head_info.find(
"meta", attrs={"property": "og:" + ograph}
) or head_info.find("meta", attrs={"name": "og:" + ograph})
if og_tag:
return og_tag.get("content", og_tag.get("value", None))
if meta:
meta_tag = head_info.find(
"meta", attrs={"name": meta}
) or head_info.find("meta", attrs={"property": meta})
if meta_tag:
return meta_tag.get(
"content", meta_tag.get("value", None)
)
if elem:
elem_tag = head_info.find(elem)
if elem_tag:
return elem_tag.text
return None
original_link_name = element.attrs["href"]
if original_link_name in attachments:
continue
page_name = (
get_element_options("title", "title", "title", "title")
or page_url.netloc
)
page_site = (
get_element_options(None, "site", "site", "site")
or page_url.netloc
)
page_description = get_element_options(
None, "description", "description", "description"
)
page_image = get_element_options(None, "image", "image", "image")
page_image_alt = get_element_options(
None, "image:alt", "image:alt", "image:alt"
)
page_video = get_element_options(None, "video", "video", "video")
page_audio = get_element_options(None, "audio", "audio", "audio")
(
get_element_options(None, None, None, "card")
or "summary_large_image"
)
attachment_base = BeautifulSoup(str(element), "html.parser")
attachments[original_link_name] = attachment_base
attachment = next(attachment_base.children)
attachment.clear()
attachment.attrs["class"] = "embed-url-link"
render_element = attachment
if page_image:
image_template = f'<span><img src="{page_image}" alt="{page_image_alt or page_name}" title="{page_name}" width="420" height="240" /></span>'
render_element.append(
BeautifulSoup(image_template, "html.parser")
)
if page_video:
video_template = f'<video controls><source src="{page_video}">Your browser does not support the video tag.</video>'
render_element.append(
BeautifulSoup(video_template, "html.parser")
)
if page_audio:
audio_template = f'<audio controls><source src="{page_audio}">Your browser does not support the audio tag.</audio>'
render_element.append(
BeautifulSoup(audio_template, "html.parser")
)
description_element_base = BeautifulSoup(
"<span class='description'></span>", "html.parser"
)
description_element = next(description_element_base.children)
description_element.append(
BeautifulSoup(
f'<p class="page-site">{page_site}</p>',
"html.parser",
)
)
description_element.append(
BeautifulSoup(
f'<strong class="page-name">{page_name}</strong>',
"html.parser",
)
)
description_element.append(
BeautifulSoup(
f"<p class='page-description'>{page_description or "No description available."}</p>",
"html.parser",
)
)
description_element.append(
BeautifulSoup(
f"<p class='page-original-link'>{original_link_name}</p>",
"html.parser",
)
)
render_element.append(description_element_base)
for attachment in attachments.values():
soup.append(attachment)
return str(soup)
class EmojiExtension(Extension):
tags = {"emoji"}
def parse(self, parser):
line_number = next(parser.stream).lineno
md_file = [Const("")]
body = ""
try:
md_file = [parser.parse_expression()]
except TemplateSyntaxError:
body = parser.parse_statements(["name:endemoji"], drop_needle=True)
return nodes.CallBlock(
self.call_method("_to_html", md_file), [], [], body
).set_lineno(line_number)
def _to_html(self, md_file, caller):
return emoji.emojize(caller(), language="alias")
class LinkifyExtension(Extension):
tags = {"linkify"}
def __init__(self, environment):
self.app = SimpleNamespace(jinja2_env=environment)
super(LinkifyExtension, self).__init__(environment)
def parse(self, parser):
line_number = next(parser.stream).lineno
md_file = [Const("")]
body = ""
try:
md_file = [parser.parse_expression()]
except TemplateSyntaxError:
body = parser.parse_statements(["name:endlinkify"], drop_needle=True)
return nodes.CallBlock(
self.call_method("_to_html", md_file), [], [], body
).set_lineno(line_number)
def _to_html(self, md_file, caller):
result = linkify_https(caller())
result = embed_media(result)
result = embed_image(result)
result = embed_youtube(result)
result = enrich_image_rendering(result)
result = embed_url(result)
return result
class PythonExtension(Extension):
tags = {"py3"}
def parse(self, parser):
line_number = next(parser.stream).lineno
md_file = [Const("")]
body = ""
try:
md_file = [parser.parse_expression()]
except TemplateSyntaxError:
body = parser.parse_statements(["name:endpy3"], drop_needle=True)
return nodes.CallBlock(
self.call_method("_to_html", md_file), [], [], body
).set_lineno(line_number)
def _to_html(self, md_file, caller):
def fn(source):
import subprocess
def system(command):
if isinstance(command):
command = command.split(" ")
from io import StringIO
stdout = StringIO()
subprocess.run(command, stderr=stdout, stdout=stdout, text=True)
return stdout.getvalue()
to_write = []
def render(text):
global to_write
to_write.append(text)
exec(source)
return "".join(to_write)
return str(fn(caller()))