mirror of https://gitlab.com/bashrc2/epicyon
Merge branch 'main' of gitlab.com:bashrc2/epicyon
commit
d209c5c256
20
daemon.py
20
daemon.py
|
@ -403,6 +403,7 @@ from crawlers import blocked_user_agent
|
|||
from crawlers import load_known_web_bots
|
||||
from qrcode import save_domain_qrcode
|
||||
from importFollowing import run_import_following_watchdog
|
||||
from maps import kml_from_tagmaps_path
|
||||
import os
|
||||
|
||||
|
||||
|
@ -14243,6 +14244,7 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
'/statuses/' not in path and \
|
||||
'/emoji/' not in path and \
|
||||
'/tags/' not in path and \
|
||||
'/tagmaps/' not in path and \
|
||||
'/avatars/' not in path and \
|
||||
'/favicons/' not in path and \
|
||||
'/headers/' not in path and \
|
||||
|
@ -17086,6 +17088,24 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
self.server.getreq_busy = False
|
||||
return
|
||||
|
||||
# hashtag map kml
|
||||
if self.path.startswith('/tagmaps/') or \
|
||||
(authorized and '/tagmaps/' in self.path):
|
||||
kml_str = kml_from_tagmaps_path(self.server.base_dir, self.path)
|
||||
if kml_str:
|
||||
msg = kml_str.encode('utf-8')
|
||||
msglen = len(msg)
|
||||
header_type = \
|
||||
'application/vnd.google-earth.kml+xml; charset=utf-8'
|
||||
self._set_headers(header_type, msglen,
|
||||
None, calling_domain, True)
|
||||
self._write(msg)
|
||||
self.server.getreq_busy = False
|
||||
return
|
||||
self._404()
|
||||
self.server.getreq_busy = False
|
||||
return
|
||||
|
||||
fitness_performance(getreq_start_time, self.server.fitness,
|
||||
'_GET', 'hashtag search done',
|
||||
self.server.debug)
|
||||
|
|
File diff suppressed because one or more lines are too long
39
inbox.py
39
inbox.py
|
@ -136,6 +136,10 @@ from content import load_dogwhistles
|
|||
from content import valid_url_lengths
|
||||
from content import remove_script
|
||||
from threads import begin_thread
|
||||
from maps import get_map_links_from_post_content
|
||||
from maps import get_location_from_tags
|
||||
from maps import add_tag_map_links
|
||||
from maps import geocoords_from_map_link
|
||||
|
||||
|
||||
def cache_svg_images(session, base_dir: str, http_prefix: str,
|
||||
|
@ -327,6 +331,32 @@ def store_hash_tags(base_dir: str, nickname: str, domain: str,
|
|||
print('Creating tags directory')
|
||||
os.mkdir(tags_dir)
|
||||
|
||||
# obtain any map links and these can be associated with hashtags
|
||||
# get geolocations from content
|
||||
map_links = []
|
||||
published = None
|
||||
if post_json_object['object'].get('content'):
|
||||
published = post_json_object['object']['published']
|
||||
post_content = post_json_object['object']['content']
|
||||
map_links += get_map_links_from_post_content(post_content)
|
||||
# get geolocation from tags
|
||||
location_str = \
|
||||
get_location_from_tags(post_json_object['object']['tag'])
|
||||
if location_str:
|
||||
if '://' in location_str and '.' in location_str:
|
||||
zoom, latitude, longitude = geocoords_from_map_link(location_str)
|
||||
if latitude and longitude and zoom and \
|
||||
location_str not in map_links:
|
||||
map_links.append(location_str)
|
||||
tag_maps_dir = base_dir + '/tagmaps'
|
||||
if map_links:
|
||||
# add tagmaps directory if it doesn't exist
|
||||
if not os.path.isdir(tag_maps_dir):
|
||||
print('Creating tagmaps directory')
|
||||
os.mkdir(tag_maps_dir)
|
||||
|
||||
post_url = remove_id_ending(post_json_object['id'])
|
||||
post_url = post_url.replace('/', '#')
|
||||
hashtags_ctr = 0
|
||||
for tag in post_json_object['object']['tag']:
|
||||
if not tag.get('type'):
|
||||
|
@ -341,12 +371,13 @@ def store_hash_tags(base_dir: str, nickname: str, domain: str,
|
|||
if not valid_hash_tag(tag_name):
|
||||
continue
|
||||
tags_filename = tags_dir + '/' + tag_name + '.txt'
|
||||
post_url = remove_id_ending(post_json_object['id'])
|
||||
post_url = post_url.replace('/', '#')
|
||||
days_diff = datetime.datetime.utcnow() - datetime.datetime(1970, 1, 1)
|
||||
days_since_epoch = days_diff.days
|
||||
tag_line = \
|
||||
str(days_since_epoch) + ' ' + nickname + ' ' + post_url + '\n'
|
||||
if map_links and published:
|
||||
add_tag_map_links(tag_maps_dir, tag_name, map_links,
|
||||
published, post_url)
|
||||
hashtag_added = False
|
||||
if not os.path.isfile(tags_filename):
|
||||
try:
|
||||
|
@ -366,8 +397,8 @@ def store_hash_tags(base_dir: str, nickname: str, domain: str,
|
|||
content = tag_line + content
|
||||
try:
|
||||
with open(tags_filename, 'w+',
|
||||
encoding='utf-8') as tags_file:
|
||||
tags_file.write(content)
|
||||
encoding='utf-8') as tags_file2:
|
||||
tags_file2.write(content)
|
||||
hashtag_added = True
|
||||
except OSError as ex:
|
||||
print('EX: Failed to write entry to tags file ' +
|
||||
|
|
261
maps.py
261
maps.py
|
@ -9,12 +9,29 @@ __module_group__ = "Core"
|
|||
|
||||
|
||||
import os
|
||||
import datetime
|
||||
from utils import is_float
|
||||
from utils import acct_dir
|
||||
from utils import load_json
|
||||
from utils import save_json
|
||||
|
||||
|
||||
def get_location_from_tags(tags: []) -> str:
|
||||
"""Returns the location from the tags list
|
||||
"""
|
||||
for tag_item in tags:
|
||||
if not tag_item.get('type'):
|
||||
continue
|
||||
if tag_item['type'] != 'Place':
|
||||
continue
|
||||
if not tag_item.get('name'):
|
||||
continue
|
||||
if not isinstance(tag_item['name'], str):
|
||||
continue
|
||||
return tag_item['name'].replace('\n', ' ')
|
||||
return None
|
||||
|
||||
|
||||
def _geocoords_from_osm_link(url: str, osm_domain: str) -> (int, float, float):
|
||||
"""Returns geocoordinates from an OSM map link
|
||||
"""
|
||||
|
@ -103,7 +120,10 @@ def _geocoords_from_gmaps_link(url: str) -> (int, float, float):
|
|||
return None, None, None
|
||||
zoom = coords[2]
|
||||
if not zoom.isdigit():
|
||||
return None, None, None
|
||||
if is_float(str(zoom)):
|
||||
zoom = int(float(str(zoom)))
|
||||
else:
|
||||
return None, None, None
|
||||
latitude = coords[0]
|
||||
if not is_float(latitude):
|
||||
return None, None, None
|
||||
|
@ -360,3 +380,242 @@ def get_map_preferences_coords(base_dir: str,
|
|||
maps_json['longitude'], \
|
||||
maps_json['zoom']
|
||||
return None, None, None
|
||||
|
||||
|
||||
def get_map_links_from_post_content(content: str) -> []:
|
||||
"""Returns a list of map links
|
||||
"""
|
||||
osm_domain = 'openstreetmap.org'
|
||||
sections = content.split('://')
|
||||
map_links = []
|
||||
ctr = 0
|
||||
for link_str in sections:
|
||||
if ctr == 0:
|
||||
ctr += 1
|
||||
continue
|
||||
url = link_str
|
||||
if '"' in url:
|
||||
url = url.split('"')[0]
|
||||
if '<' in url:
|
||||
url = url.split('<')[0]
|
||||
if not url:
|
||||
continue
|
||||
zoom, latitude, longitude = geocoords_from_map_link(url, osm_domain)
|
||||
if not latitude:
|
||||
continue
|
||||
if not longitude:
|
||||
continue
|
||||
if not zoom:
|
||||
continue
|
||||
if url not in map_links:
|
||||
map_links.append(url)
|
||||
ctr += 1
|
||||
return map_links
|
||||
|
||||
|
||||
def add_tag_map_links(tag_maps_dir: str, tag_name: str,
|
||||
map_links: [], published: str, post_url: str) -> None:
|
||||
"""Appends to a hashtag file containing map links
|
||||
This is used to show a map for a particular hashtag
|
||||
"""
|
||||
tag_map_filename = tag_maps_dir + '/' + tag_name + '.txt'
|
||||
post_url = post_url.replace('#', '/')
|
||||
|
||||
# read the existing map links
|
||||
existing_map_links = []
|
||||
if os.path.isfile(tag_map_filename):
|
||||
try:
|
||||
with open(tag_map_filename, 'r', encoding='utf-8') as fp_tag:
|
||||
existing_map_links = fp_tag.read().split('\n')
|
||||
except OSError:
|
||||
print('EX: error reading tag map ' + tag_map_filename)
|
||||
|
||||
# combine map links with the existing list
|
||||
secs_since_epoch = \
|
||||
int((datetime.datetime.strptime(published, '%Y-%m-%dT%H:%M:%SZ') -
|
||||
datetime.datetime(1970, 1, 1)).total_seconds())
|
||||
links_changed = False
|
||||
for link in map_links:
|
||||
line = str(secs_since_epoch) + ' ' + link + ' ' + post_url
|
||||
if line in existing_map_links:
|
||||
continue
|
||||
links_changed = True
|
||||
existing_map_links = [line] + existing_map_links
|
||||
if not links_changed:
|
||||
return
|
||||
|
||||
# sort the list of map links
|
||||
existing_map_links.sort(reverse=True)
|
||||
map_links_str = ''
|
||||
ctr = 0
|
||||
for link in existing_map_links:
|
||||
if not link:
|
||||
continue
|
||||
map_links_str += link + '\n'
|
||||
ctr += 1
|
||||
# don't allow the list to grow indefinitely
|
||||
if ctr >= 2000:
|
||||
break
|
||||
|
||||
# save the tag
|
||||
try:
|
||||
with open(tag_map_filename, 'w+', encoding='utf-8') as fp_tag:
|
||||
fp_tag.write(map_links_str)
|
||||
except OSError:
|
||||
print('EX: error writing tag map ' + tag_map_filename)
|
||||
|
||||
|
||||
def _hashtag_map_to_kml(base_dir: str, tag_name: str,
|
||||
start_hours_since_epoch: int,
|
||||
end_hours_since_epoch: int) -> str:
|
||||
"""Returns the KML for a given hashtag between the given times
|
||||
"""
|
||||
place_ctr = 0
|
||||
osm_domain = 'openstreetmap.org'
|
||||
tag_map_filename = base_dir + '/tagmaps/' + tag_name + '.txt'
|
||||
|
||||
kml_str = '<?xml version="1.0" encoding="UTF-8"?>\n'
|
||||
kml_str += '<kml xmlns="http://www.opengis.net/kml/2.2">\n'
|
||||
kml_str += '<Document>\n'
|
||||
|
||||
if os.path.isfile(tag_map_filename):
|
||||
map_links = []
|
||||
try:
|
||||
with open(tag_map_filename, 'r', encoding='utf-8') as fp_tag:
|
||||
map_links = fp_tag.read().split('\n')
|
||||
except OSError:
|
||||
print('EX: unable to read tag map links ' + tag_map_filename)
|
||||
if map_links:
|
||||
start_secs_since_epoch = int(start_hours_since_epoch * 60 * 60)
|
||||
end_secs_since_epoch = int(end_hours_since_epoch * 60 * 60)
|
||||
for link_line in map_links:
|
||||
link_line = link_line.strip().split(' ')
|
||||
if len(link_line) < 3:
|
||||
continue
|
||||
secs_since_epoch = int(link_line[0])
|
||||
if secs_since_epoch < start_secs_since_epoch or \
|
||||
secs_since_epoch > end_secs_since_epoch:
|
||||
continue
|
||||
map_link = link_line[1]
|
||||
zoom, latitude, longitude = \
|
||||
geocoords_from_map_link(map_link, osm_domain)
|
||||
if not zoom:
|
||||
continue
|
||||
if not latitude:
|
||||
continue
|
||||
if not longitude:
|
||||
continue
|
||||
post_id = link_line[2]
|
||||
place_ctr += 1
|
||||
kml_str += '<Placemark id="' + str(place_ctr) + '">\n'
|
||||
kml_str += ' <name>' + str(place_ctr) + '</name>\n'
|
||||
kml_str += ' <description><![CDATA[\n'
|
||||
kml_str += '<a href="' + post_id + '">' + \
|
||||
post_id + '</a>\n]]>\n'
|
||||
kml_str += ' </description>\n'
|
||||
kml_str += ' <Point>\n'
|
||||
kml_str += ' <coordinates>' + str(longitude) + ',' + \
|
||||
str(latitude) + ',0</coordinates>\n'
|
||||
kml_str += ' </Point>\n'
|
||||
kml_str += '</Placemark>\n'
|
||||
|
||||
kml_str += '</Document>\n'
|
||||
kml_str += '</kml>'
|
||||
if place_ctr == 0:
|
||||
return None
|
||||
return kml_str
|
||||
|
||||
|
||||
def _hashtag_map_kml_within_hours(base_dir: str, tag_name: str,
|
||||
hours: int) -> str:
|
||||
"""Returns kml for a hashtag containing maps for the last number of hours
|
||||
"""
|
||||
secs_since_epoch = \
|
||||
int((datetime.datetime.utcnow() -
|
||||
datetime.datetime(1970, 1, 1)).total_seconds())
|
||||
end_hours_since_epoch = int(secs_since_epoch / (60 * 60))
|
||||
start_hours_since_epoch = end_hours_since_epoch - hours
|
||||
kml_str = \
|
||||
_hashtag_map_to_kml(base_dir, tag_name,
|
||||
start_hours_since_epoch,
|
||||
end_hours_since_epoch)
|
||||
return kml_str
|
||||
|
||||
|
||||
def _get_tagmaps_time_periods() -> {}:
|
||||
"""dict of time periods for map display
|
||||
"""
|
||||
return {
|
||||
"Last hour": -1,
|
||||
"Last 3 hours": -3,
|
||||
"Last 6 hours": -6,
|
||||
"Last 12 hours": -12,
|
||||
"Last day": -24,
|
||||
"Last 2 days": -48,
|
||||
"Last week": -24 * 7,
|
||||
"Last 2 weeks": -24 * 7 * 2,
|
||||
"Last month": -24 * 7 * 4,
|
||||
"Last 6 months": -24 * 7 * 4 * 6,
|
||||
"Last year": -24 * 7 * 4 * 12
|
||||
}
|
||||
|
||||
|
||||
def kml_from_tagmaps_path(base_dir: str, path: str) -> str:
|
||||
"""Returns kml for a given tagmaps path
|
||||
/tagmaps/tagname-time_period
|
||||
"""
|
||||
if '/tagmaps/' not in path:
|
||||
return None
|
||||
time_period = _get_tagmaps_time_periods()
|
||||
tag_name = path.split('/tagmaps/')[1]
|
||||
if '-' in tag_name:
|
||||
tag_name = tag_name.split('-')[0]
|
||||
if not tag_name:
|
||||
return None
|
||||
for period_str, hours in time_period.items():
|
||||
period_str2 = period_str.replace('Last ', '').lower()
|
||||
endpoint_str = \
|
||||
'/tagmaps/' + tag_name + '-' + period_str2.replace(' ', '_')
|
||||
if path == endpoint_str:
|
||||
return _hashtag_map_kml_within_hours(base_dir, tag_name,
|
||||
abs(hours))
|
||||
return None
|
||||
|
||||
|
||||
def html_hashtag_maps(base_dir: str, tag_name: str,
|
||||
translate: {}) -> str:
|
||||
"""Returns html for maps associated with a hashtag
|
||||
"""
|
||||
tag_map_filename = base_dir + '/tagmaps/' + tag_name + '.txt'
|
||||
if not os.path.isfile(tag_map_filename):
|
||||
return ''
|
||||
|
||||
time_period = _get_tagmaps_time_periods()
|
||||
|
||||
html_str = ''
|
||||
kml_str = None
|
||||
for period_str, hours in time_period.items():
|
||||
new_kml_str = \
|
||||
_hashtag_map_kml_within_hours(base_dir, tag_name, abs(hours))
|
||||
if not new_kml_str:
|
||||
continue
|
||||
if new_kml_str == kml_str:
|
||||
continue
|
||||
kml_str = new_kml_str
|
||||
period_str2 = period_str.replace('Last ', '').lower()
|
||||
endpoint_str = \
|
||||
'/tagmaps/' + tag_name + '-' + period_str2.replace(' ', '_')
|
||||
download_filename = \
|
||||
(tag_name + '-' +
|
||||
period_str.lower()).replace(' ', '_') + '.kml'
|
||||
if html_str:
|
||||
html_str += ' '
|
||||
description = period_str
|
||||
if translate.get(period_str):
|
||||
description = translate[period_str]
|
||||
html_str += '<a href="' + endpoint_str + \
|
||||
'" download="' + download_filename + '">' + \
|
||||
description + '</a>'
|
||||
if html_str:
|
||||
html_str = '<center>🌍 ' + html_str + '</center>\n'
|
||||
return html_str
|
||||
|
|
|
@ -40,6 +40,7 @@ from media import replace_you_tube
|
|||
from media import replace_twitter
|
||||
from media import get_media_path
|
||||
from media import create_media_dirs
|
||||
from inbox import store_hash_tags
|
||||
from inbox import inbox_update_index
|
||||
from announce import outbox_announce
|
||||
from announce import outbox_undo_announce
|
||||
|
@ -408,6 +409,10 @@ def post_message_to_outbox(session, translate: {},
|
|||
if message_json['type'] != 'Upgrade':
|
||||
outbox_name = 'outbox'
|
||||
|
||||
store_hash_tags(base_dir, post_to_nickname, domain,
|
||||
http_prefix, domain_full,
|
||||
message_json, translate)
|
||||
|
||||
# if this is a blog post or an event then save to its own box
|
||||
if message_json['type'] == 'Create':
|
||||
if has_object_dict(message_json):
|
||||
|
|
|
@ -1208,7 +1208,7 @@ def _remove_tags_for_nickname(base_dir: str, nickname: str,
|
|||
continue
|
||||
try:
|
||||
tag_filename = os.path.join(directory, filename)
|
||||
except BaseException:
|
||||
except OSError:
|
||||
print('EX: _remove_tags_for_nickname unable to join ' +
|
||||
str(directory) + ' ' + str(filename))
|
||||
continue
|
||||
|
|
27
posts.py
27
posts.py
|
@ -942,7 +942,8 @@ def save_post_to_box(base_dir: str, http_prefix: str, post_id: str,
|
|||
return filename
|
||||
|
||||
|
||||
def _update_hashtags_index(base_dir: str, tag: {}, new_post_id: str) -> None:
|
||||
def _update_hashtags_index(base_dir: str, tag: {}, new_post_id: str,
|
||||
nickname: str) -> None:
|
||||
"""Writes the post url for hashtags to a file
|
||||
This allows posts for a hashtag to be quickly looked up
|
||||
"""
|
||||
|
@ -955,25 +956,37 @@ def _update_hashtags_index(base_dir: str, tag: {}, new_post_id: str) -> None:
|
|||
os.mkdir(tags_dir)
|
||||
tag_name = tag['name']
|
||||
tags_filename = tags_dir + '/' + tag_name[1:] + '.txt'
|
||||
tagline = new_post_id + '\n'
|
||||
|
||||
new_post_id = new_post_id.replace('/', '#')
|
||||
|
||||
if not os.path.isfile(tags_filename):
|
||||
days_diff = datetime.datetime.utcnow() - datetime.datetime(1970, 1, 1)
|
||||
days_since_epoch = days_diff.days
|
||||
tag_line = \
|
||||
str(days_since_epoch) + ' ' + nickname + ' ' + \
|
||||
new_post_id + '\n'
|
||||
# create a new tags index file
|
||||
try:
|
||||
with open(tags_filename, 'w+', encoding='utf-8') as tags_file:
|
||||
tags_file.write(tagline)
|
||||
tags_file.write(tag_line)
|
||||
except OSError:
|
||||
print('EX: _update_hashtags_index unable to write tags file ' +
|
||||
tags_filename)
|
||||
else:
|
||||
# prepend to tags index file
|
||||
if not text_in_file(tagline, tags_filename):
|
||||
if not text_in_file(new_post_id, tags_filename):
|
||||
days_diff = \
|
||||
datetime.datetime.utcnow() - datetime.datetime(1970, 1, 1)
|
||||
days_since_epoch = days_diff.days
|
||||
tag_line = \
|
||||
str(days_since_epoch) + ' ' + nickname + ' ' + \
|
||||
new_post_id + '\n'
|
||||
try:
|
||||
with open(tags_filename, 'r+', encoding='utf-8') as tags_file:
|
||||
content = tags_file.read()
|
||||
if tagline not in content:
|
||||
if tag_line not in content:
|
||||
tags_file.seek(0, 0)
|
||||
tags_file.write(tagline + content)
|
||||
tags_file.write(tag_line + content)
|
||||
except OSError as ex:
|
||||
print('EX: Failed to write entry to tags file ' +
|
||||
tags_filename + ' ' + str(ex))
|
||||
|
@ -1530,7 +1543,7 @@ def _create_post_base(base_dir: str,
|
|||
if not post_tag_exists(tag['type'], tag['name'], tags):
|
||||
tags.append(tag)
|
||||
if is_public:
|
||||
_update_hashtags_index(base_dir, tag, new_post_id)
|
||||
_update_hashtags_index(base_dir, tag, new_post_id, nickname)
|
||||
# print('Content tags: ' + str(tags))
|
||||
|
||||
sensitive, summary = \
|
||||
|
|
48
tests.py
48
tests.py
|
@ -191,6 +191,8 @@ from blocking import add_cw_from_lists
|
|||
from happening import dav_month_via_server
|
||||
from happening import dav_day_via_server
|
||||
from webapp_theme_designer import color_contrast
|
||||
from maps import get_map_links_from_post_content
|
||||
from maps import geocoords_from_map_link
|
||||
|
||||
|
||||
TEST_SERVER_GROUP_RUNNING = False
|
||||
|
@ -7492,6 +7494,51 @@ def _test_combine_lines():
|
|||
assert result == expected
|
||||
|
||||
|
||||
def _test_hashtag_maps():
|
||||
print('hashtag_maps')
|
||||
content = \
|
||||
"<p>This is a test, with a couple of links and a " + \
|
||||
"<a href=\"https://epicyon.libreserver.org/tags/Hashtag\" " + \
|
||||
"class=\"mention hashtag\" rel=\"tag\" tabindex=\"10\">#" + \
|
||||
"<span>Hashtag</span></a><br><br>" + \
|
||||
"<a href=\"https://" + \
|
||||
"www.openstreetmap.org/#map=19/52.90860/-3.59917\" " + \
|
||||
"tabindex=\"10\" rel=\"nofollow noopener noreferrer\" " + \
|
||||
"target=\"_blank\"><span class=\"invisible\">https://" + \
|
||||
"</span><span class=\"ellipsis\">" + \
|
||||
"www.openstreetmap.org/#map=19/52.90860/-</span><span " + \
|
||||
"class=\"invisible\">3.59917</span></a><br><br>" + \
|
||||
"<a href=\"https://" + \
|
||||
"www.google.com/maps/@52.217291,-3.0811865,20.04z\" " + \
|
||||
"tabindex=\"10\" rel=\"nofollow noopener noreferrer\" " + \
|
||||
"target=\"_blank\"><span class=\"invisible\">" + \
|
||||
"https://</span><span class=\"ellipsis\">" + \
|
||||
"www.google.com/maps/@52.217291,-3.081186</span>" + \
|
||||
"<span class=\"invisible\">5,20.04z</span></a><br><br>" + \
|
||||
"<a href=\"https://" + \
|
||||
"epicyon.libreserver.org/tags/AnotherHashtag\" " + \
|
||||
"class=\"mention hashtag\" rel=\"tag\" tabindex=\"10\">#" + \
|
||||
"<span>AnotherHashtag</span></a></p>"
|
||||
map_links = get_map_links_from_post_content(content)
|
||||
link = "www.google.com/maps/@52.217291,-3.0811865,20.04z"
|
||||
assert link in map_links
|
||||
zoom, latitude, longitude = geocoords_from_map_link(link)
|
||||
assert zoom == 20
|
||||
assert latitude
|
||||
assert int(latitude * 1000) == 52217
|
||||
assert longitude
|
||||
assert int(longitude * 1000) == -3081
|
||||
link = "www.openstreetmap.org/#map=19/52.90860/-3.59917"
|
||||
assert link in map_links
|
||||
zoom, latitude, longitude = geocoords_from_map_link(link)
|
||||
assert zoom == 19
|
||||
assert latitude
|
||||
assert int(latitude * 1000) == 52908
|
||||
assert longitude
|
||||
assert int(longitude * 1000) == -3599
|
||||
assert len(map_links) == 2
|
||||
|
||||
|
||||
def run_all_tests():
|
||||
base_dir = os.getcwd()
|
||||
print('Running tests...')
|
||||
|
@ -7509,6 +7556,7 @@ def run_all_tests():
|
|||
_test_checkbox_names()
|
||||
_test_thread_functions()
|
||||
_test_functions()
|
||||
_test_hashtag_maps()
|
||||
_test_combine_lines()
|
||||
_test_text_standardize()
|
||||
_test_dogwhistles()
|
||||
|
|
|
@ -576,5 +576,16 @@
|
|||
"Keep DMs during post expiry": "احتفظ بالرسائل الخاصّة أثناء انتهاء صلاحية النشر",
|
||||
"Notifications": "إشعارات",
|
||||
"ntfy URL": "ntfy URL",
|
||||
"ntfy topic": "موضوع ntfy"
|
||||
"ntfy topic": "موضوع ntfy",
|
||||
"Last hour": "الساعة الأخيرة",
|
||||
"Last 3 hours": "آخر 3 ساعات",
|
||||
"Last 6 hours": "آخر 6 ساعات",
|
||||
"Last 12 hours": "آخر 12 ساعة",
|
||||
"Last day": "بالأمس",
|
||||
"Last 2 days": "آخر يومين",
|
||||
"Last week": "الأسبوع الماضي",
|
||||
"Last 2 weeks": "آخر أسبوعين",
|
||||
"Last month": "الشهر الماضي",
|
||||
"Last 6 months": "آخر 6 أشهر",
|
||||
"Last year": "العام الماضي"
|
||||
}
|
||||
|
|
|
@ -576,5 +576,16 @@
|
|||
"Keep DMs during post expiry": "পোস্টের মেয়াদ শেষ হওয়ার সময় সরাসরি বার্তা রাখুন",
|
||||
"Notifications": "বিজ্ঞপ্তি",
|
||||
"ntfy URL": "ntfy ইউআরএল",
|
||||
"ntfy topic": "ntfy বিষয়"
|
||||
"ntfy topic": "ntfy বিষয়",
|
||||
"Last hour": "শেষ ঘন্টা",
|
||||
"Last 3 hours": "শেষ ৩ ঘন্টা",
|
||||
"Last 6 hours": "শেষ ৬ ঘণ্টা",
|
||||
"Last 12 hours": "শেষ 12 ঘন্টা",
|
||||
"Last day": "শেষ দিন",
|
||||
"Last 2 days": "গত ২ দিন",
|
||||
"Last week": "গত সপ্তাহে",
|
||||
"Last 2 weeks": "গত ২ সপ্তাহ",
|
||||
"Last month": "গত মাসে",
|
||||
"Last 6 months": "গত ৬ মাস",
|
||||
"Last year": "গত বছর"
|
||||
}
|
||||
|
|
|
@ -576,5 +576,16 @@
|
|||
"Keep DMs during post expiry": "Conserveu els missatges directes durant la caducitat posterior",
|
||||
"Notifications": "Notificacions",
|
||||
"ntfy URL": "URL ntfy",
|
||||
"ntfy topic": "tema ntfy"
|
||||
"ntfy topic": "tema ntfy",
|
||||
"Last hour": "Última hora",
|
||||
"Last 3 hours": "Últimes 3 hores",
|
||||
"Last 6 hours": "Últimes 6 hores",
|
||||
"Last 12 hours": "Últimes 12 hores",
|
||||
"Last day": "L'últim dia",
|
||||
"Last 2 days": "2 darrers dies",
|
||||
"Last week": "La setmana passada",
|
||||
"Last 2 weeks": "Últimes 2 setmanes",
|
||||
"Last month": "El mes passat",
|
||||
"Last 6 months": "Últims 6 mesos",
|
||||
"Last year": "L'any passat"
|
||||
}
|
||||
|
|
|
@ -576,5 +576,16 @@
|
|||
"Keep DMs during post expiry": "Cadwch Negeseuon Uniongyrchol pan ddaw'r post i ben",
|
||||
"Notifications": "Hysbysiadau",
|
||||
"ntfy URL": "ntfy URL",
|
||||
"ntfy topic": "pwnc ntfy"
|
||||
"ntfy topic": "pwnc ntfy",
|
||||
"Last hour": "Awr olaf",
|
||||
"Last 3 hours": "3 awr diwethaf",
|
||||
"Last 6 hours": "6 awr diwethaf",
|
||||
"Last 12 hours": "12 awr diwethaf",
|
||||
"Last day": "Diwrnod olaf",
|
||||
"Last 2 days": "2 ddiwrnod diwethaf",
|
||||
"Last week": "Wythnos diwethaf",
|
||||
"Last 2 weeks": "2 wythnos diwethaf",
|
||||
"Last month": "Mis diwethaf",
|
||||
"Last 6 months": "6 mis diwethaf",
|
||||
"Last year": "Blwyddyn diwethaf"
|
||||
}
|
||||
|
|
|
@ -576,5 +576,16 @@
|
|||
"Keep DMs during post expiry": "Bewahren Sie Direktnachrichten während des Ablaufs auf",
|
||||
"Notifications": "Benachrichtigungen",
|
||||
"ntfy URL": "ntfy-URL",
|
||||
"ntfy topic": "ntfy-Thema"
|
||||
"ntfy topic": "ntfy-Thema",
|
||||
"Last hour": "Letzte Stunde",
|
||||
"Last 3 hours": "Die letzten 3 Stunden",
|
||||
"Last 6 hours": "Die letzten 6 Stunden",
|
||||
"Last 12 hours": "Die letzten 12 Stunden",
|
||||
"Last day": "Letzter Tag",
|
||||
"Last 2 days": "Die letzten 2 Tage",
|
||||
"Last week": "Letzte Woche",
|
||||
"Last 2 weeks": "Letzte 2 Wochen",
|
||||
"Last month": "Im vergangenen Monat",
|
||||
"Last 6 months": "Letzte 6 Monate",
|
||||
"Last year": "Vergangenes Jahr"
|
||||
}
|
||||
|
|
|
@ -576,5 +576,16 @@
|
|||
"Keep DMs during post expiry": "Διατηρήστε τα άμεσα μηνύματα κατά τη λήξη της ανάρτησης",
|
||||
"Notifications": "Ειδοποιήσεις",
|
||||
"ntfy URL": "ntfy URL",
|
||||
"ntfy topic": "ntfy θέμα"
|
||||
"ntfy topic": "ntfy θέμα",
|
||||
"Last hour": "Τελευταία ώρα",
|
||||
"Last 3 hours": "Τελευταίες 3 ώρες",
|
||||
"Last 6 hours": "Τελευταίες 6 ώρες",
|
||||
"Last 12 hours": "Τελευταίες 12 ώρες",
|
||||
"Last day": "Τελευταία μέρα",
|
||||
"Last 2 days": "Τελευταίες 2 μέρες",
|
||||
"Last week": "Την προηγούμενη εβδομάδα",
|
||||
"Last 2 weeks": "Τελευταίες 2 εβδομάδες",
|
||||
"Last month": "Τον προηγούμενο μήνα",
|
||||
"Last 6 months": "Τελευταίοι 6 μήνες",
|
||||
"Last year": "Πέρυσι"
|
||||
}
|
||||
|
|
|
@ -576,5 +576,16 @@
|
|||
"Keep DMs during post expiry": "Keep DMs during post expiry",
|
||||
"Notifications": "Notifications",
|
||||
"ntfy URL": "ntfy URL",
|
||||
"ntfy topic": "ntfy topic"
|
||||
"ntfy topic": "ntfy topic",
|
||||
"Last hour": "Last hour",
|
||||
"Last 3 hours": "Last 3 hours",
|
||||
"Last 6 hours": "Last 6 hours",
|
||||
"Last 12 hours": "Last 12 hours",
|
||||
"Last day": "Last day",
|
||||
"Last 2 days": "Last 2 days",
|
||||
"Last week": "Last week",
|
||||
"Last 2 weeks": "Last 2 weeks",
|
||||
"Last month": "Last month",
|
||||
"Last 6 months": "Last 6 months",
|
||||
"Last year": "Last year"
|
||||
}
|
||||
|
|
|
@ -576,5 +576,16 @@
|
|||
"Keep DMs during post expiry": "Conservar los mensajes directos durante el vencimiento de la publicación",
|
||||
"Notifications": "Notificaciones",
|
||||
"ntfy URL": "URL ntfy",
|
||||
"ntfy topic": "tema ntfy"
|
||||
"ntfy topic": "tema ntfy",
|
||||
"Last hour": "Ultima hora",
|
||||
"Last 3 hours": "últimas 3 horas",
|
||||
"Last 6 hours": "últimas 6 horas",
|
||||
"Last 12 hours": "últimas 12 horas",
|
||||
"Last day": "Último día",
|
||||
"Last 2 days": "últimos 2 días",
|
||||
"Last week": "La semana pasada",
|
||||
"Last 2 weeks": "últimas 2 semanas",
|
||||
"Last month": "El mes pasado",
|
||||
"Last 6 months": "últimos 6 meses",
|
||||
"Last year": "El año pasado"
|
||||
}
|
||||
|
|
|
@ -576,5 +576,16 @@
|
|||
"Keep DMs during post expiry": "Conserver les messages directs après l'expiration",
|
||||
"Notifications": "Avis",
|
||||
"ntfy URL": "URL ntfy",
|
||||
"ntfy topic": "sujet ntfy"
|
||||
"ntfy topic": "sujet ntfy",
|
||||
"Last hour": "Dernière heure",
|
||||
"Last 3 hours": "3 dernières heures",
|
||||
"Last 6 hours": "6 dernières heures",
|
||||
"Last 12 hours": "12 dernières heures",
|
||||
"Last day": "Dernier jour",
|
||||
"Last 2 days": "2 derniers jours",
|
||||
"Last week": "La semaine dernière",
|
||||
"Last 2 weeks": "2 dernières semaines",
|
||||
"Last month": "Le mois dernier",
|
||||
"Last 6 months": "6 derniers mois",
|
||||
"Last year": "L'année dernière"
|
||||
}
|
||||
|
|
|
@ -576,5 +576,16 @@
|
|||
"Keep DMs during post expiry": "Coinnigh Teachtaireachtaí Díreacha nuair a rachaidh postáil in éag",
|
||||
"Notifications": "Fógraí",
|
||||
"ntfy URL": "ntfy URL",
|
||||
"ntfy topic": "topaic ntfy"
|
||||
"ntfy topic": "topaic ntfy",
|
||||
"Last hour": "Uair dheireanach",
|
||||
"Last 3 hours": "3 uair an chloig caite",
|
||||
"Last 6 hours": "6 uair an chloig caite",
|
||||
"Last 12 hours": "12 uair an chloig caite",
|
||||
"Last day": "Lá deirneach",
|
||||
"Last 2 days": "2 lá seo caite",
|
||||
"Last week": "An tseachtain seo caite",
|
||||
"Last 2 weeks": "2 sheachtain anuas",
|
||||
"Last month": "An mhí seo caite",
|
||||
"Last 6 months": "6 mhí anuas",
|
||||
"Last year": "Anuraidh"
|
||||
}
|
||||
|
|
|
@ -576,5 +576,16 @@
|
|||
"Keep DMs during post expiry": "समाप्ति के बाद सीधे संदेश रखें",
|
||||
"Notifications": "सूचनाएं",
|
||||
"ntfy URL": "एनटीएफई यूआरएल",
|
||||
"ntfy topic": "एनटीएफई विषय"
|
||||
"ntfy topic": "एनटीएफई विषय",
|
||||
"Last hour": "अंतिम घंटा",
|
||||
"Last 3 hours": "पिछले 3 घंटे",
|
||||
"Last 6 hours": "पिछले 6 घंटे",
|
||||
"Last 12 hours": "पिछले 12 घंटे",
|
||||
"Last day": "आखरी दिन",
|
||||
"Last 2 days": "पिछले 2 दिन",
|
||||
"Last week": "पिछले सप्ताह",
|
||||
"Last 2 weeks": "पिछले 2 सप्ताह",
|
||||
"Last month": "पिछले महीने",
|
||||
"Last 6 months": "पिछले 6 महीने",
|
||||
"Last year": "पिछले साल"
|
||||
}
|
||||
|
|
|
@ -576,5 +576,16 @@
|
|||
"Keep DMs during post expiry": "Conserva i messaggi diretti durante la scadenza successiva",
|
||||
"Notifications": "Notifiche",
|
||||
"ntfy URL": "ntfy URL",
|
||||
"ntfy topic": "argomento ntfy"
|
||||
"ntfy topic": "argomento ntfy",
|
||||
"Last hour": "Ultima ora",
|
||||
"Last 3 hours": "Ultime 3 ore",
|
||||
"Last 6 hours": "Ultime 6 ore",
|
||||
"Last 12 hours": "Ultime 12 ore",
|
||||
"Last day": "Ultimo giorno",
|
||||
"Last 2 days": "Ultimi 2 giorni",
|
||||
"Last week": "La settimana scorsa",
|
||||
"Last 2 weeks": "Ultime 2 settimane",
|
||||
"Last month": "Lo scorso mese",
|
||||
"Last 6 months": "Ultimi 6 mesi",
|
||||
"Last year": "L'anno scorso"
|
||||
}
|
||||
|
|
|
@ -576,5 +576,16 @@
|
|||
"Keep DMs during post expiry": "投稿の有効期限が切れるまでダイレクト メッセージを保持する",
|
||||
"Notifications": "通知",
|
||||
"ntfy URL": "ntfy URL",
|
||||
"ntfy topic": "ntfy トピック"
|
||||
"ntfy topic": "ntfy トピック",
|
||||
"Last hour": "最後の時間",
|
||||
"Last 3 hours": "過去 3 時間",
|
||||
"Last 6 hours": "過去 6 時間",
|
||||
"Last 12 hours": "過去 12 時間",
|
||||
"Last day": "最終日",
|
||||
"Last 2 days": "過去 2 日間",
|
||||
"Last week": "先週",
|
||||
"Last 2 weeks": "過去 2 週間",
|
||||
"Last month": "先月",
|
||||
"Last 6 months": "過去 6 か月",
|
||||
"Last year": "去年"
|
||||
}
|
||||
|
|
|
@ -576,5 +576,16 @@
|
|||
"Keep DMs during post expiry": "만료 후 DM 보관",
|
||||
"Notifications": "알림",
|
||||
"ntfy URL": "ntfy URL",
|
||||
"ntfy topic": "ntfy 주제"
|
||||
"ntfy topic": "ntfy 주제",
|
||||
"Last hour": "지난 시간",
|
||||
"Last 3 hours": "지난 3시간",
|
||||
"Last 6 hours": "지난 6시간",
|
||||
"Last 12 hours": "지난 12시간",
|
||||
"Last day": "마지막 날",
|
||||
"Last 2 days": "지난 2일",
|
||||
"Last week": "지난주",
|
||||
"Last 2 weeks": "지난 2주",
|
||||
"Last month": "지난 달",
|
||||
"Last 6 months": "지난 6개월",
|
||||
"Last year": "작년"
|
||||
}
|
||||
|
|
|
@ -576,5 +576,16 @@
|
|||
"Keep DMs during post expiry": "Di dema qedandina postê de Peyamên Rasterast biparêzin",
|
||||
"Notifications": "Notifications",
|
||||
"ntfy URL": "ntfy URL",
|
||||
"ntfy topic": "mijara ntfy"
|
||||
"ntfy topic": "mijara ntfy",
|
||||
"Last hour": "Saeta dawî",
|
||||
"Last 3 hours": "3 saetên dawî",
|
||||
"Last 6 hours": "6 saetên dawî",
|
||||
"Last 12 hours": "12 saetên dawî",
|
||||
"Last day": "Roja dawî",
|
||||
"Last 2 days": "2 rojên dawî",
|
||||
"Last week": "Hefteya çûyî",
|
||||
"Last 2 weeks": "2 hefteyên dawî",
|
||||
"Last month": "meha borî",
|
||||
"Last 6 months": "6 mehên dawî",
|
||||
"Last year": "Sala borî"
|
||||
}
|
||||
|
|
|
@ -576,5 +576,16 @@
|
|||
"Keep DMs during post expiry": "Directe berichten bewaren tijdens de vervaldatum",
|
||||
"Notifications": "Meldingen",
|
||||
"ntfy URL": "ntfy-URL",
|
||||
"ntfy topic": "ntfy onderwerp"
|
||||
"ntfy topic": "ntfy onderwerp",
|
||||
"Last hour": "Laatste uur",
|
||||
"Last 3 hours": "Laatste 3 uur",
|
||||
"Last 6 hours": "Laatste 6 uur",
|
||||
"Last 12 hours": "Laatste 12 uur",
|
||||
"Last day": "Laatste dag",
|
||||
"Last 2 days": "Laatste 2 dagen",
|
||||
"Last week": "Vorige week",
|
||||
"Last 2 weeks": "Afgelopen 2 weken",
|
||||
"Last month": "Vorige maand",
|
||||
"Last 6 months": "Afgelopen 6 maanden",
|
||||
"Last year": "Afgelopen jaar"
|
||||
}
|
||||
|
|
|
@ -572,5 +572,16 @@
|
|||
"Keep DMs during post expiry": "Keep DMs during post expiry",
|
||||
"Notifications": "Notifications",
|
||||
"ntfy URL": "ntfy URL",
|
||||
"ntfy topic": "ntfy topic"
|
||||
"ntfy topic": "ntfy topic",
|
||||
"Last hour": "Last hour",
|
||||
"Last 3 hours": "Last 3 hours",
|
||||
"Last 6 hours": "Last 6 hours",
|
||||
"Last 12 hours": "Last 12 hours",
|
||||
"Last day": "Last day",
|
||||
"Last 2 days": "Last 2 days",
|
||||
"Last week": "Last week",
|
||||
"Last 2 weeks": "Last 2 weeks",
|
||||
"Last month": "Last month",
|
||||
"Last 6 months": "Last 6 months",
|
||||
"Last year": "Last year"
|
||||
}
|
||||
|
|
|
@ -576,5 +576,16 @@
|
|||
"Keep DMs during post expiry": "Zachowaj bezpośrednie wiadomości po wygaśnięciu",
|
||||
"Notifications": "Powiadomienia",
|
||||
"ntfy URL": "URL ntfy",
|
||||
"ntfy topic": "temat ntfy"
|
||||
"ntfy topic": "temat ntfy",
|
||||
"Last hour": "Ostatnia godzina",
|
||||
"Last 3 hours": "Ostatnie 3 godzin",
|
||||
"Last 6 hours": "Ostatnie 6 godzin",
|
||||
"Last 12 hours": "Ostatnie 12 godzin",
|
||||
"Last day": "Ostatni dzień",
|
||||
"Last 2 days": "Ostatnie 2 dni",
|
||||
"Last week": "Zeszły tydzień",
|
||||
"Last 2 weeks": "Ostatnie 2 tygodnie",
|
||||
"Last month": "W zeszłym miesiącu",
|
||||
"Last 6 months": "Ostatnie 6 miesięcy",
|
||||
"Last year": "Ostatni rok"
|
||||
}
|
||||
|
|
|
@ -576,5 +576,16 @@
|
|||
"Keep DMs during post expiry": "Manter mensagens diretas durante a expiração da postagem",
|
||||
"Notifications": "Notificações",
|
||||
"ntfy URL": "URL ntfy",
|
||||
"ntfy topic": "tópico ntfy"
|
||||
"ntfy topic": "tópico ntfy",
|
||||
"Last hour": "Última hora",
|
||||
"Last 3 hours": "Últimas 3 horas",
|
||||
"Last 6 hours": "Últimas 6 horas",
|
||||
"Last 12 hours": "Últimas 12 horas",
|
||||
"Last day": "Último dia",
|
||||
"Last 2 days": "Últimos 2 dias",
|
||||
"Last week": "Semana Anterior",
|
||||
"Last 2 weeks": "Últimas 2 semanas",
|
||||
"Last month": "Mês passado",
|
||||
"Last 6 months": "Últimos 6 meses",
|
||||
"Last year": "Ano passado"
|
||||
}
|
||||
|
|
|
@ -576,5 +576,16 @@
|
|||
"Keep DMs during post expiry": "Сохраняйте личные сообщения в течение срока действия после истечения срока действия",
|
||||
"Notifications": "Уведомления",
|
||||
"ntfy URL": "URL-адрес ntfy",
|
||||
"ntfy topic": "ntfy тема"
|
||||
"ntfy topic": "ntfy тема",
|
||||
"Last hour": "Последний час",
|
||||
"Last 3 hours": "Последние 3 часов",
|
||||
"Last 6 hours": "Последние 6 часов",
|
||||
"Last 12 hours": "Последние 12 часов",
|
||||
"Last day": "Последний день",
|
||||
"Last 2 days": "Последние 2 дня",
|
||||
"Last week": "Прошлая неделя",
|
||||
"Last 2 weeks": "Последние 2 недели",
|
||||
"Last month": "Прошлый месяц",
|
||||
"Last 6 months": "Последние 6 месяцев",
|
||||
"Last year": "Прошедший год"
|
||||
}
|
||||
|
|
|
@ -576,5 +576,16 @@
|
|||
"Keep DMs during post expiry": "Weka Ujumbe wa Moja kwa Moja wakati wa kuisha kwa chapisho",
|
||||
"Notifications": "Arifa",
|
||||
"ntfy URL": "ntfy URL",
|
||||
"ntfy topic": "mada ya ntfy"
|
||||
"ntfy topic": "mada ya ntfy",
|
||||
"Last hour": "Saa iliyopita",
|
||||
"Last 3 hours": "Saa 3 zilizopita",
|
||||
"Last 6 hours": "Saa 6 zilizopita",
|
||||
"Last 12 hours": "Saa 12 zilizopita",
|
||||
"Last day": "Siku ya mwisho",
|
||||
"Last 2 days": "Siku 2 zilizopita",
|
||||
"Last week": "Wiki iliyopita",
|
||||
"Last 2 weeks": "Wiki 2 zilizopita",
|
||||
"Last month": "Mwezi uliopita",
|
||||
"Last 6 months": "Miezi 6 iliyopita",
|
||||
"Last year": "Mwaka jana"
|
||||
}
|
||||
|
|
|
@ -576,5 +576,16 @@
|
|||
"Keep DMs during post expiry": "Direkt Mesajları sona erme süresi boyunca saklayın",
|
||||
"Notifications": "Bildirimler",
|
||||
"ntfy URL": "ntfy URL'si",
|
||||
"ntfy topic": "ntfy konusu"
|
||||
"ntfy topic": "ntfy konusu",
|
||||
"Last hour": "Son saat",
|
||||
"Last 3 hours": "son 3 saat",
|
||||
"Last 6 hours": "son 6 saat",
|
||||
"Last 12 hours": "son 12 saat",
|
||||
"Last day": "Son gun",
|
||||
"Last 2 days": "son 2 gün",
|
||||
"Last week": "Geçen hafta",
|
||||
"Last 2 weeks": "Son 2 hafta",
|
||||
"Last month": "Geçen ay",
|
||||
"Last 6 months": "Son 6 ay",
|
||||
"Last year": "Geçen yıl"
|
||||
}
|
||||
|
|
|
@ -576,5 +576,16 @@
|
|||
"Keep DMs during post expiry": "Зберігайте прямі повідомлення протягом терміну дії",
|
||||
"Notifications": "Сповіщення",
|
||||
"ntfy URL": "ntfy URL",
|
||||
"ntfy topic": "Тема ntfy"
|
||||
"ntfy topic": "Тема ntfy",
|
||||
"Last hour": "Остання година",
|
||||
"Last 3 hours": "Останні 3 години",
|
||||
"Last 6 hours": "Останні 6 години",
|
||||
"Last 12 hours": "Останні 12 години",
|
||||
"Last day": "Останній день",
|
||||
"Last 2 days": "Останні 2 дні",
|
||||
"Last week": "Минулого тижня",
|
||||
"Last 2 weeks": "Останні 2 тижні",
|
||||
"Last month": "Минулого місяця",
|
||||
"Last 6 months": "Останні 6 місяців",
|
||||
"Last year": "Минулого року"
|
||||
}
|
||||
|
|
|
@ -576,5 +576,16 @@
|
|||
"Keep DMs during post expiry": "האַלטן דירעקט אַרטיקלען בעשאַס פּאָסטן עקספּיירי",
|
||||
"Notifications": "נאָוטאַפאַקיישאַנז",
|
||||
"ntfy URL": "ntfy URL",
|
||||
"ntfy topic": "ntfy טעמע"
|
||||
"ntfy topic": "ntfy טעמע",
|
||||
"Last hour": "לעצטע שעה",
|
||||
"Last 3 hours": "לעצטע 3 שעה",
|
||||
"Last 6 hours": "לעצטע 6 שעה",
|
||||
"Last 12 hours": "לעצטע 12 שעה",
|
||||
"Last day": "לעצטע טאג",
|
||||
"Last 2 days": "לעצטע 2 טעג",
|
||||
"Last week": "לעצטע וואָך",
|
||||
"Last 2 weeks": "לעצטע 2 וואָכן",
|
||||
"Last month": "לעצטע מאנאט",
|
||||
"Last 6 months": "לעצטע 6 חדשים",
|
||||
"Last year": "לעצטע יאר"
|
||||
}
|
||||
|
|
|
@ -576,5 +576,16 @@
|
|||
"Keep DMs during post expiry": "在帖子到期期间保留直接消息",
|
||||
"Notifications": "通知",
|
||||
"ntfy URL": "ntfy 网址",
|
||||
"ntfy topic": "ntfy 主题"
|
||||
"ntfy topic": "ntfy 主题",
|
||||
"Last hour": "上一个小时",
|
||||
"Last 3 hours": "过去 3 小时",
|
||||
"Last 6 hours": "过去 6 小时",
|
||||
"Last 12 hours": "过去 12 小时",
|
||||
"Last day": "最后一天",
|
||||
"Last 2 days": "过去 2 天",
|
||||
"Last week": "上周",
|
||||
"Last 2 weeks": "过去 2 周",
|
||||
"Last month": "上个月",
|
||||
"Last 6 months": "过去 6 个月",
|
||||
"Last year": "去年"
|
||||
}
|
||||
|
|
61
utils.py
61
utils.py
|
@ -1900,6 +1900,35 @@ def delete_cached_html(base_dir: str, nickname: str, domain: str,
|
|||
str(cached_post_filename))
|
||||
|
||||
|
||||
def _remove_post_id_from_tag_index(tag_index_filename: str,
|
||||
post_id: str) -> None:
|
||||
"""Remove post_id from the tag index file
|
||||
"""
|
||||
lines = None
|
||||
with open(tag_index_filename, 'r', encoding='utf-8') as index_file:
|
||||
lines = index_file.readlines()
|
||||
if not lines:
|
||||
return
|
||||
newlines = ''
|
||||
for file_line in lines:
|
||||
if post_id in file_line:
|
||||
# skip over the deleted post
|
||||
continue
|
||||
newlines += file_line
|
||||
if not newlines.strip():
|
||||
# if there are no lines then remove the hashtag file
|
||||
try:
|
||||
os.remove(tag_index_filename)
|
||||
except OSError:
|
||||
print('EX: _delete_hashtags_on_post ' +
|
||||
'unable to delete tag index ' + str(tag_index_filename))
|
||||
else:
|
||||
# write the new hashtag index without the given post in it
|
||||
with open(tag_index_filename, 'w+',
|
||||
encoding='utf-8') as index_file:
|
||||
index_file.write(newlines)
|
||||
|
||||
|
||||
def _delete_hashtags_on_post(base_dir: str, post_json_object: {}) -> None:
|
||||
"""Removes hashtags when a post is deleted
|
||||
"""
|
||||
|
@ -1926,33 +1955,13 @@ def _delete_hashtags_on_post(base_dir: str, post_json_object: {}) -> None:
|
|||
if not tag.get('name'):
|
||||
continue
|
||||
# find the index file for this tag
|
||||
tag_map_filename = base_dir + '/tagmaps/' + tag['name'][1:] + '.txt'
|
||||
if os.path.isfile(tag_map_filename):
|
||||
_remove_post_id_from_tag_index(tag_map_filename, post_id)
|
||||
# find the index file for this tag
|
||||
tag_index_filename = base_dir + '/tags/' + tag['name'][1:] + '.txt'
|
||||
if not os.path.isfile(tag_index_filename):
|
||||
continue
|
||||
# remove post_id from the tag index file
|
||||
lines = None
|
||||
with open(tag_index_filename, 'r', encoding='utf-8') as index_file:
|
||||
lines = index_file.readlines()
|
||||
if not lines:
|
||||
continue
|
||||
newlines = ''
|
||||
for file_line in lines:
|
||||
if post_id in file_line:
|
||||
# skip over the deleted post
|
||||
continue
|
||||
newlines += file_line
|
||||
if not newlines.strip():
|
||||
# if there are no lines then remove the hashtag file
|
||||
try:
|
||||
os.remove(tag_index_filename)
|
||||
except OSError:
|
||||
print('EX: _delete_hashtags_on_post ' +
|
||||
'unable to delete tag index ' + str(tag_index_filename))
|
||||
else:
|
||||
# write the new hashtag index without the given post in it
|
||||
with open(tag_index_filename, 'w+',
|
||||
encoding='utf-8') as index_file:
|
||||
index_file.write(newlines)
|
||||
if os.path.isfile(tag_index_filename):
|
||||
_remove_post_id_from_tag_index(tag_index_filename, post_id)
|
||||
|
||||
|
||||
def _delete_conversation_post(base_dir: str, nickname: str, domain: str,
|
||||
|
|
|
@ -99,22 +99,7 @@ from maps import html_open_street_map
|
|||
from maps import set_map_preferences_coords
|
||||
from maps import set_map_preferences_url
|
||||
from maps import geocoords_from_map_link
|
||||
|
||||
|
||||
def _get_location_from_tags(tags: []) -> str:
|
||||
"""Returns the location from the tags list
|
||||
"""
|
||||
for tag_item in tags:
|
||||
if not tag_item.get('type'):
|
||||
continue
|
||||
if tag_item['type'] != 'Place':
|
||||
continue
|
||||
if not tag_item.get('name'):
|
||||
continue
|
||||
if not isinstance(tag_item['name'], str):
|
||||
continue
|
||||
return tag_item['name'].replace('\n', ' ')
|
||||
return None
|
||||
from maps import get_location_from_tags
|
||||
|
||||
|
||||
def _html_post_metadata_open_graph(domain: str, post_json_object: {},
|
||||
|
@ -2298,7 +2283,7 @@ def individual_post_as_html(signing_priv_key_pem: str,
|
|||
|
||||
# show embedded map if the location contains a map url
|
||||
location_str = \
|
||||
_get_location_from_tags(post_json_object['object']['tag'])
|
||||
get_location_from_tags(post_json_object['object']['tag'])
|
||||
if location_str:
|
||||
if '://' in location_str and '.' in location_str:
|
||||
bounding_box_degrees = 0.001
|
||||
|
|
|
@ -40,6 +40,7 @@ from webapp_utils import html_post_separator
|
|||
from webapp_utils import html_search_result_share
|
||||
from webapp_post import individual_post_as_html
|
||||
from webapp_hashtagswarm import html_hash_tag_swarm
|
||||
from maps import html_hashtag_maps
|
||||
|
||||
|
||||
def html_search_emoji(translate: {}, base_dir: str, search_str: str) -> str:
|
||||
|
@ -824,6 +825,8 @@ def html_hashtag_search(nickname: str, domain: str, port: int,
|
|||
hashtag_search_form += ' </form>\n'
|
||||
hashtag_search_form += '</div>\n'
|
||||
|
||||
hashtag_search_form += html_hashtag_maps(base_dir, hashtag, translate)
|
||||
|
||||
if start_index > 0:
|
||||
# previous page link
|
||||
hashtag_search_form += \
|
||||
|
|
Loading…
Reference in New Issue