mirror of https://gitlab.com/bashrc2/epicyon
merge-requests/30/head
commit
cd5350744f
10
blog.py
10
blog.py
|
@ -35,6 +35,7 @@ from utils import load_json
|
||||||
from utils import first_paragraph_from_string
|
from utils import first_paragraph_from_string
|
||||||
from utils import get_actor_property_url
|
from utils import get_actor_property_url
|
||||||
from utils import acct_dir
|
from utils import acct_dir
|
||||||
|
from utils import escape_text
|
||||||
from posts import create_blogs_timeline
|
from posts import create_blogs_timeline
|
||||||
from newswire import rss2header
|
from newswire import rss2header
|
||||||
from newswire import rss2footer
|
from newswire import rss2footer
|
||||||
|
@ -375,12 +376,13 @@ def _html_blog_post_rss2(domain: str, post_json_object: {},
|
||||||
post_json_object['object'].get('published'):
|
post_json_object['object'].get('published'):
|
||||||
published = post_json_object['object']['published']
|
published = post_json_object['object']['published']
|
||||||
pub_date = datetime.strptime(published, "%Y-%m-%dT%H:%M:%SZ")
|
pub_date = datetime.strptime(published, "%Y-%m-%dT%H:%M:%SZ")
|
||||||
title_str = post_json_object['object']['summary']
|
title_str = escape_text(post_json_object['object']['summary'])
|
||||||
rss_date_str = pub_date.strftime("%a, %d %b %Y %H:%M:%S UT")
|
rss_date_str = pub_date.strftime("%a, %d %b %Y %H:%M:%S UT")
|
||||||
content = \
|
content = \
|
||||||
get_base_content_from_post(post_json_object,
|
get_base_content_from_post(post_json_object,
|
||||||
system_language)
|
system_language)
|
||||||
description = first_paragraph_from_string(content)
|
description = first_paragraph_from_string(content)
|
||||||
|
description = escape_text(description)
|
||||||
rss_str = ' <item>'
|
rss_str = ' <item>'
|
||||||
rss_str += ' <title>' + title_str + '</title>'
|
rss_str += ' <title>' + title_str + '</title>'
|
||||||
rss_str += ' <link>' + message_link + '</link>'
|
rss_str += ' <link>' + message_link + '</link>'
|
||||||
|
@ -542,7 +544,7 @@ def html_blog_page(authorized: bool, session,
|
||||||
timeline_json = \
|
timeline_json = \
|
||||||
create_blogs_timeline(base_dir,
|
create_blogs_timeline(base_dir,
|
||||||
nickname, domain, port, http_prefix,
|
nickname, domain, port, http_prefix,
|
||||||
no_of_items, False, page_number, '')
|
no_of_items, False, page_number)
|
||||||
|
|
||||||
if not timeline_json:
|
if not timeline_json:
|
||||||
return blog_str + html_footer()
|
return blog_str + html_footer()
|
||||||
|
@ -631,7 +633,7 @@ def html_blog_page_rss2(base_dir: str, http_prefix: str, translate: {},
|
||||||
nickname, domain, port,
|
nickname, domain, port,
|
||||||
http_prefix,
|
http_prefix,
|
||||||
no_of_items, False,
|
no_of_items, False,
|
||||||
page_number, '')
|
page_number)
|
||||||
|
|
||||||
if not timeline_json:
|
if not timeline_json:
|
||||||
if include_header:
|
if include_header:
|
||||||
|
@ -670,7 +672,7 @@ def html_blog_page_rss3(base_dir: str, http_prefix: str,
|
||||||
timeline_json = \
|
timeline_json = \
|
||||||
create_blogs_timeline(base_dir,
|
create_blogs_timeline(base_dir,
|
||||||
nickname, domain, port, http_prefix,
|
nickname, domain, port, http_prefix,
|
||||||
no_of_items, False, page_number, '')
|
no_of_items, False, page_number)
|
||||||
|
|
||||||
if not timeline_json:
|
if not timeline_json:
|
||||||
return blog_rss3
|
return blog_rss3
|
||||||
|
|
7
feeds.py
7
feeds.py
|
@ -8,6 +8,9 @@ __status__ = "Production"
|
||||||
__module_group__ = "RSS Feeds"
|
__module_group__ = "RSS Feeds"
|
||||||
|
|
||||||
|
|
||||||
|
from utils import escape_text
|
||||||
|
|
||||||
|
|
||||||
def rss2tag_header(hashtag: str, http_prefix: str, domain_full: str) -> str:
|
def rss2tag_header(hashtag: str, http_prefix: str, domain_full: str) -> str:
|
||||||
"""Header for rss 2
|
"""Header for rss 2
|
||||||
"""
|
"""
|
||||||
|
@ -15,9 +18,9 @@ def rss2tag_header(hashtag: str, http_prefix: str, domain_full: str) -> str:
|
||||||
"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" + \
|
"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" + \
|
||||||
"<rss version=\"2.0\">" + \
|
"<rss version=\"2.0\">" + \
|
||||||
'<channel>' + \
|
'<channel>' + \
|
||||||
' <title>#' + hashtag + '</title>' + \
|
' <title>#' + escape_text(hashtag) + '</title>' + \
|
||||||
' <link>' + http_prefix + '://' + domain_full + \
|
' <link>' + http_prefix + '://' + domain_full + \
|
||||||
'/tags/rss2/' + hashtag + '</link>'
|
'/tags/rss2/' + escape_text(hashtag) + '</link>'
|
||||||
|
|
||||||
|
|
||||||
def rss2tag_footer() -> str:
|
def rss2tag_footer() -> str:
|
||||||
|
|
24
newswire.py
24
newswire.py
|
@ -39,6 +39,8 @@ from utils import remove_html
|
||||||
from utils import is_account_dir
|
from utils import is_account_dir
|
||||||
from utils import acct_dir
|
from utils import acct_dir
|
||||||
from utils import local_actor_url
|
from utils import local_actor_url
|
||||||
|
from utils import escape_text
|
||||||
|
from utils import unescaped_text
|
||||||
from blocking import is_blocked_domain
|
from blocking import is_blocked_domain
|
||||||
from blocking import is_blocked_hashtag
|
from blocking import is_blocked_hashtag
|
||||||
from filters import is_filtered
|
from filters import is_filtered
|
||||||
|
@ -76,8 +78,9 @@ def rss2header(http_prefix: str,
|
||||||
' <link>' + http_prefix + '://' + domain_full + \
|
' <link>' + http_prefix + '://' + domain_full + \
|
||||||
'/blog/rss.xml' + '</link>'
|
'/blog/rss.xml' + '</link>'
|
||||||
else:
|
else:
|
||||||
|
title_str = escape_text(translate[title])
|
||||||
rss_str += \
|
rss_str += \
|
||||||
' <title>' + translate[title] + '</title>' + \
|
' <title>' + title_str + '</title>' + \
|
||||||
' <link>' + \
|
' <link>' + \
|
||||||
local_actor_url(http_prefix, nickname, domain_full) + \
|
local_actor_url(http_prefix, nickname, domain_full) + \
|
||||||
'/rss.xml' + '</link>'
|
'/rss.xml' + '</link>'
|
||||||
|
@ -407,12 +410,14 @@ def _xml2str_to_hashtag_categories(base_dir: str, xml_str: str,
|
||||||
continue
|
continue
|
||||||
category_str = rss_item.split('<title>')[1]
|
category_str = rss_item.split('<title>')[1]
|
||||||
category_str = category_str.split('</title>')[0].strip()
|
category_str = category_str.split('</title>')[0].strip()
|
||||||
|
category_str = unescaped_text(category_str)
|
||||||
if not category_str:
|
if not category_str:
|
||||||
continue
|
continue
|
||||||
if 'CDATA' in category_str:
|
if 'CDATA' in category_str:
|
||||||
continue
|
continue
|
||||||
hashtag_list_str = rss_item.split('<description>')[1]
|
hashtag_list_str = rss_item.split('<description>')[1]
|
||||||
hashtag_list_str = hashtag_list_str.split('</description>')[0].strip()
|
hashtag_list_str = hashtag_list_str.split('</description>')[0].strip()
|
||||||
|
hashtag_list_str = unescaped_text(hashtag_list_str)
|
||||||
if not hashtag_list_str:
|
if not hashtag_list_str:
|
||||||
continue
|
continue
|
||||||
if 'CDATA' in hashtag_list_str:
|
if 'CDATA' in hashtag_list_str:
|
||||||
|
@ -766,17 +771,20 @@ def _xml2str_to_dict(base_dir: str, domain: str, xml_str: str,
|
||||||
|
|
||||||
title = rss_item.split('<title>')[1]
|
title = rss_item.split('<title>')[1]
|
||||||
title = _remove_cdata(title.split('</title>')[0])
|
title = _remove_cdata(title.split('</title>')[0])
|
||||||
|
title = unescaped_text(title)
|
||||||
title = remove_html(title)
|
title = remove_html(title)
|
||||||
|
|
||||||
description = ''
|
description = ''
|
||||||
if '<description>' in rss_item and '</description>' in rss_item:
|
if '<description>' in rss_item and '</description>' in rss_item:
|
||||||
description = rss_item.split('<description>')[1]
|
description = rss_item.split('<description>')[1]
|
||||||
description = remove_html(description.split('</description>')[0])
|
description = remove_html(description.split('</description>')[0])
|
||||||
|
description = unescaped_text(description)
|
||||||
else:
|
else:
|
||||||
if '<media:description>' in rss_item and \
|
if '<media:description>' in rss_item and \
|
||||||
'</media:description>' in rss_item:
|
'</media:description>' in rss_item:
|
||||||
description = rss_item.split('<media:description>')[1]
|
description = rss_item.split('<media:description>')[1]
|
||||||
description = description.split('</media:description>')[0]
|
description = description.split('</media:description>')[0]
|
||||||
|
description = unescaped_text(description)
|
||||||
description = remove_html(description)
|
description = remove_html(description)
|
||||||
|
|
||||||
proxy_type = None
|
proxy_type = None
|
||||||
|
@ -874,16 +882,19 @@ def _xml1str_to_dict(base_dir: str, domain: str, xml_str: str,
|
||||||
continue
|
continue
|
||||||
title = rss_item.split('<title>')[1]
|
title = rss_item.split('<title>')[1]
|
||||||
title = _remove_cdata(title.split('</title>')[0])
|
title = _remove_cdata(title.split('</title>')[0])
|
||||||
|
title = unescaped_text(title)
|
||||||
title = remove_html(title)
|
title = remove_html(title)
|
||||||
description = ''
|
description = ''
|
||||||
if '<description>' in rss_item and '</description>' in rss_item:
|
if '<description>' in rss_item and '</description>' in rss_item:
|
||||||
description = rss_item.split('<description>')[1]
|
description = rss_item.split('<description>')[1]
|
||||||
description = remove_html(description.split('</description>')[0])
|
description = remove_html(description.split('</description>')[0])
|
||||||
|
description = unescaped_text(description)
|
||||||
else:
|
else:
|
||||||
if '<media:description>' in rss_item and \
|
if '<media:description>' in rss_item and \
|
||||||
'</media:description>' in rss_item:
|
'</media:description>' in rss_item:
|
||||||
description = rss_item.split('<media:description>')[1]
|
description = rss_item.split('<media:description>')[1]
|
||||||
description = description.split('</media:description>')[0]
|
description = description.split('</media:description>')[0]
|
||||||
|
description = unescaped_text(description)
|
||||||
description = remove_html(description)
|
description = remove_html(description)
|
||||||
|
|
||||||
proxy_type = None
|
proxy_type = None
|
||||||
|
@ -969,16 +980,19 @@ def _atom_feed_to_dict(base_dir: str, domain: str, xml_str: str,
|
||||||
continue
|
continue
|
||||||
title = atom_item.split('<title>')[1]
|
title = atom_item.split('<title>')[1]
|
||||||
title = _remove_cdata(title.split('</title>')[0])
|
title = _remove_cdata(title.split('</title>')[0])
|
||||||
|
title = unescaped_text(title)
|
||||||
title = remove_html(title)
|
title = remove_html(title)
|
||||||
description = ''
|
description = ''
|
||||||
if '<summary>' in atom_item and '</summary>' in atom_item:
|
if '<summary>' in atom_item and '</summary>' in atom_item:
|
||||||
description = atom_item.split('<summary>')[1]
|
description = atom_item.split('<summary>')[1]
|
||||||
description = remove_html(description.split('</summary>')[0])
|
description = remove_html(description.split('</summary>')[0])
|
||||||
|
description = unescaped_text(description)
|
||||||
else:
|
else:
|
||||||
if '<media:description>' in atom_item and \
|
if '<media:description>' in atom_item and \
|
||||||
'</media:description>' in atom_item:
|
'</media:description>' in atom_item:
|
||||||
description = atom_item.split('<media:description>')[1]
|
description = atom_item.split('<media:description>')[1]
|
||||||
description = description.split('</media:description>')[0]
|
description = description.split('</media:description>')[0]
|
||||||
|
description = unescaped_text(description)
|
||||||
description = remove_html(description)
|
description = remove_html(description)
|
||||||
|
|
||||||
proxy_type = None
|
proxy_type = None
|
||||||
|
@ -1184,15 +1198,18 @@ def _atom_feed_yt_to_dict(base_dir: str, domain: str, xml_str: str,
|
||||||
continue
|
continue
|
||||||
title = atom_item.split('<title>')[1]
|
title = atom_item.split('<title>')[1]
|
||||||
title = _remove_cdata(title.split('</title>')[0])
|
title = _remove_cdata(title.split('</title>')[0])
|
||||||
|
title = unescaped_text(title)
|
||||||
description = ''
|
description = ''
|
||||||
if '<media:description>' in atom_item and \
|
if '<media:description>' in atom_item and \
|
||||||
'</media:description>' in atom_item:
|
'</media:description>' in atom_item:
|
||||||
description = atom_item.split('<media:description>')[1]
|
description = atom_item.split('<media:description>')[1]
|
||||||
description = description.split('</media:description>')[0]
|
description = description.split('</media:description>')[0]
|
||||||
|
description = unescaped_text(description)
|
||||||
description = remove_html(description)
|
description = remove_html(description)
|
||||||
elif '<summary>' in atom_item and '</summary>' in atom_item:
|
elif '<summary>' in atom_item and '</summary>' in atom_item:
|
||||||
description = atom_item.split('<summary>')[1]
|
description = atom_item.split('<summary>')[1]
|
||||||
description = description.split('</summary>')[0]
|
description = description.split('</summary>')[0]
|
||||||
|
description = unescaped_text(description)
|
||||||
description = remove_html(description)
|
description = remove_html(description)
|
||||||
|
|
||||||
link, _ = get_link_from_rss_item(atom_item, None, None)
|
link, _ = get_link_from_rss_item(atom_item, None, None)
|
||||||
|
@ -1382,9 +1399,10 @@ def get_rs_sfrom_dict(base_dir: str, newswire: {},
|
||||||
continue
|
continue
|
||||||
rss_str += \
|
rss_str += \
|
||||||
'<item>\n' + \
|
'<item>\n' + \
|
||||||
' <title>' + fields[0] + '</title>\n'
|
' <title>' + escape_text(fields[0]) + '</title>\n'
|
||||||
description = remove_html(first_paragraph_from_string(fields[4]))
|
description = remove_html(first_paragraph_from_string(fields[4]))
|
||||||
rss_str += ' <description>' + description + '</description>\n'
|
rss_str += \
|
||||||
|
' <description>' + escape_text(description) + '</description>\n'
|
||||||
url = fields[1]
|
url = fields[1]
|
||||||
if '://' not in url:
|
if '://' not in url:
|
||||||
if domain_full not in url:
|
if domain_full not in url:
|
||||||
|
|
|
@ -1071,7 +1071,7 @@ def person_box_json(recent_posts_cache: {},
|
||||||
if boxname == 'tlblogs':
|
if boxname == 'tlblogs':
|
||||||
return create_blogs_timeline(base_dir, nickname, domain, port,
|
return create_blogs_timeline(base_dir, nickname, domain, port,
|
||||||
http_prefix, no_of_items, header_only,
|
http_prefix, no_of_items, header_only,
|
||||||
page_number, first_post_id)
|
page_number)
|
||||||
if boxname == 'outbox':
|
if boxname == 'outbox':
|
||||||
return create_outbox(base_dir, nickname, domain, port,
|
return create_outbox(base_dir, nickname, domain, port,
|
||||||
http_prefix,
|
http_prefix,
|
||||||
|
|
5
posts.py
5
posts.py
|
@ -3626,12 +3626,11 @@ def create_replies_timeline(recent_posts_cache: {},
|
||||||
|
|
||||||
def create_blogs_timeline(base_dir: str, nickname: str, domain: str,
|
def create_blogs_timeline(base_dir: str, nickname: str, domain: str,
|
||||||
port: int, http_prefix: str, items_per_page: int,
|
port: int, http_prefix: str, items_per_page: int,
|
||||||
header_only: bool, page_number: int,
|
header_only: bool, page_number: int) -> {}:
|
||||||
first_post_id: str) -> {}:
|
|
||||||
return _create_box_indexed({}, base_dir, 'tlblogs', nickname,
|
return _create_box_indexed({}, base_dir, 'tlblogs', nickname,
|
||||||
domain, port, http_prefix,
|
domain, port, http_prefix,
|
||||||
items_per_page, header_only, True,
|
items_per_page, header_only, True,
|
||||||
0, False, 0, page_number, first_post_id)
|
0, False, 0, page_number)
|
||||||
|
|
||||||
|
|
||||||
def create_features_timeline(base_dir: str,
|
def create_features_timeline(base_dir: str,
|
||||||
|
|
30
utils.py
30
utils.py
|
@ -36,7 +36,7 @@ VALID_HASHTAG_CHARS = \
|
||||||
# both incoming and outgoing.
|
# both incoming and outgoing.
|
||||||
# Could include dubious clacks or admin dogwhistles
|
# Could include dubious clacks or admin dogwhistles
|
||||||
INVALID_CHARACTERS = (
|
INVALID_CHARACTERS = (
|
||||||
'卐', '卍', '࿕', '࿖', '࿗', '࿘', 'ϟϟ', '🏳️🌈🚫', '⚡⚡'
|
'卐', '卍', '࿕', '࿖', '࿗', '࿘', 'ϟϟ', '🏳️🌈🚫', '⚡⚡', ''
|
||||||
)
|
)
|
||||||
|
|
||||||
INVALID_ACTOR_URL_CHARACTERS = (
|
INVALID_ACTOR_URL_CHARACTERS = (
|
||||||
|
@ -4226,3 +4226,31 @@ def license_link_from_name(license: str) -> str:
|
||||||
else:
|
else:
|
||||||
value = 'https://creativecommons.org/publicdomain/zero/1.0'
|
value = 'https://creativecommons.org/publicdomain/zero/1.0'
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
def _get_escaped_chars() -> {}:
|
||||||
|
"""Returns escaped characters
|
||||||
|
"""
|
||||||
|
return {
|
||||||
|
"&": "&",
|
||||||
|
"<": "<",
|
||||||
|
">": ">",
|
||||||
|
'"': """,
|
||||||
|
"'": "'"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def escape_text(txt: str) -> str:
|
||||||
|
"""Escape text for inclusion in xml/rss
|
||||||
|
"""
|
||||||
|
for orig, replacement in _get_escaped_chars().items():
|
||||||
|
txt = txt.replace(orig, replacement)
|
||||||
|
return txt
|
||||||
|
|
||||||
|
|
||||||
|
def unescaped_text(txt: str) -> str:
|
||||||
|
"""Escape text for inclusion in xml/rss
|
||||||
|
"""
|
||||||
|
for orig, replacement in _get_escaped_chars().items():
|
||||||
|
txt = txt.replace(replacement, orig)
|
||||||
|
return txt
|
||||||
|
|
|
@ -11,6 +11,7 @@ import os
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from utils import get_nickname_from_actor
|
from utils import get_nickname_from_actor
|
||||||
from utils import get_config_param
|
from utils import get_config_param
|
||||||
|
from utils import escape_text
|
||||||
from categories import get_hashtag_categories
|
from categories import get_hashtag_categories
|
||||||
from categories import get_hashtag_category
|
from categories import get_hashtag_category
|
||||||
from webapp_utils import set_custom_background
|
from webapp_utils import set_custom_background
|
||||||
|
@ -41,7 +42,7 @@ def get_hashtag_categories_feed(base_dir: str,
|
||||||
for category_str, hashtag_list in hashtag_categories.items():
|
for category_str, hashtag_list in hashtag_categories.items():
|
||||||
rss_str += \
|
rss_str += \
|
||||||
'<item>\n' + \
|
'<item>\n' + \
|
||||||
' <title>' + category_str + '</title>\n'
|
' <title>' + escape_text(category_str) + '</title>\n'
|
||||||
list_str = ''
|
list_str = ''
|
||||||
for hashtag in hashtag_list:
|
for hashtag in hashtag_list:
|
||||||
if ':' in hashtag:
|
if ':' in hashtag:
|
||||||
|
@ -50,7 +51,8 @@ def get_hashtag_categories_feed(base_dir: str,
|
||||||
continue
|
continue
|
||||||
list_str += hashtag + ' '
|
list_str += hashtag + ' '
|
||||||
rss_str += \
|
rss_str += \
|
||||||
' <description>' + list_str.strip() + '</description>\n' + \
|
' <description>' + \
|
||||||
|
escape_text(list_str.strip()) + '</description>\n' + \
|
||||||
' <link/>\n' + \
|
' <link/>\n' + \
|
||||||
' <pubDate>' + rss_date_str + '</pubDate>\n' + \
|
' <pubDate>' + rss_date_str + '</pubDate>\n' + \
|
||||||
'</item>\n'
|
'</item>\n'
|
||||||
|
|
|
@ -26,6 +26,7 @@ from utils import search_box_posts
|
||||||
from utils import get_alt_path
|
from utils import get_alt_path
|
||||||
from utils import acct_dir
|
from utils import acct_dir
|
||||||
from utils import local_actor_url
|
from utils import local_actor_url
|
||||||
|
from utils import escape_text
|
||||||
from skills import no_of_actor_skills
|
from skills import no_of_actor_skills
|
||||||
from skills import get_skills_from_list
|
from skills import get_skills_from_list
|
||||||
from categories import get_hashtag_category
|
from categories import get_hashtag_category
|
||||||
|
@ -1133,12 +1134,13 @@ def rss_hashtag_search(nickname: str, domain: str, port: int,
|
||||||
if post_json_object['object'].get('summary'):
|
if post_json_object['object'].get('summary'):
|
||||||
hashtag_feed += \
|
hashtag_feed += \
|
||||||
' <title>' + \
|
' <title>' + \
|
||||||
post_json_object['object']['summary'] + \
|
escape_text(post_json_object['object']['summary']) + \
|
||||||
'</title>'
|
'</title>'
|
||||||
description = \
|
description = \
|
||||||
get_base_content_from_post(post_json_object,
|
get_base_content_from_post(post_json_object,
|
||||||
system_language)
|
system_language)
|
||||||
description = first_paragraph_from_string(description)
|
description = first_paragraph_from_string(description)
|
||||||
|
description = escape_text(description)
|
||||||
hashtag_feed += \
|
hashtag_feed += \
|
||||||
' <description>' + description + '</description>'
|
' <description>' + description + '</description>'
|
||||||
hashtag_feed += \
|
hashtag_feed += \
|
||||||
|
|
|
@ -1072,8 +1072,9 @@ def html_timeline(default_timeline: str,
|
||||||
if item_ctr > 0:
|
if item_ctr > 0:
|
||||||
# if showing the page down icon then remove the last item so that
|
# if showing the page down icon then remove the last item so that
|
||||||
# firstpost does not overlap on the next timeline
|
# firstpost does not overlap on the next timeline
|
||||||
if last_item_str:
|
if last_item_str and first_post_id != last_post_id:
|
||||||
tl_str = tl_str.replace(last_item_str, '')
|
if item_ctr > items_per_page / 2:
|
||||||
|
tl_str = tl_str.replace(last_item_str, '')
|
||||||
tl_str += text_mode_separator
|
tl_str += text_mode_separator
|
||||||
first_post = ''
|
first_post = ''
|
||||||
if last_post_id:
|
if last_post_id:
|
||||||
|
|
Loading…
Reference in New Issue