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 ( ) ) )