From 73a358c9594f248bec523492443174351afc87bd Mon Sep 17 00:00:00 2001 From: Her Email Date: Sat, 9 Dec 2023 16:25:41 -0500 Subject: [PATCH] fix timeout and other issues --- boofilsic/settings.py | 2 +- catalog/search/external.py | 19 ++++++------------ catalog/views.py | 3 ++- common/utils.py | 34 ++++++++++++++++++++++++++++----- mastodon/api.py | 8 ++++---- takahe/utils.py | 2 +- users/account.py | 2 +- users/data.py | 4 ++-- users/models/apidentity.py | 10 ---------- users/templates/users/data.html | 2 ++ 10 files changed, 48 insertions(+), 38 deletions(-) diff --git a/boofilsic/settings.py b/boofilsic/settings.py index 11afa32d..ece449b8 100644 --- a/boofilsic/settings.py +++ b/boofilsic/settings.py @@ -23,7 +23,7 @@ # ====== List of user configuration variables ====== env = environ.FileAwareEnv( # WARNING: do not run with debug mode turned on in production - NEODB_DEBUG=(bool, True), + NEODB_DEBUG=(bool, False), # WARNING: must use your own key and keep it secret NEODB_SECRET_KEY=(str), # Site information diff --git a/catalog/search/external.py b/catalog/search/external.py index c11a8b97..f16365b1 100644 --- a/catalog/search/external.py +++ b/catalog/search/external.py @@ -51,13 +51,6 @@ def scraped(self): return False -class ProxiedRequest: - @classmethod - def get(cls, url): - u = f"http://api.scraperapi.com?api_key={settings.SCRAPERAPI_KEY}&url={quote_plus(url)}" - return requests.get(u, timeout=10) - - class Goodreads: @classmethod def search(cls, q, page=1): @@ -66,7 +59,7 @@ def search(cls, q, page=1): search_url = ( f"https://www.goodreads.com/search?page={page}&q={quote_plus(q)}" ) - r = requests.get(search_url) + r = requests.get(search_url, timeout=2) if r.url.startswith("https://www.goodreads.com/book/show/"): # Goodreads will 302 if only one result matches ISBN site = SiteManager.get_site_by_url(r.url) @@ -119,7 +112,7 @@ def search(cls, q, page=1): results = [] try: api_url = f"https://www.googleapis.com/books/v1/volumes?country=us&q={quote_plus(q)}&startIndex={SEARCH_PAGE_SIZE*(page-1)}&maxResults={SEARCH_PAGE_SIZE}&maxAllowedMaturityRating=MATURE" - j = requests.get(api_url).json() + j = requests.get(api_url, timeout=2).json() if "items" in j: for b in j["items"]: if "title" not in b["volumeInfo"]: @@ -166,7 +159,7 @@ def search(cls, q, page=1): results = [] try: api_url = f"https://api.themoviedb.org/3/search/multi?query={quote_plus(q)}&page={page}&api_key={settings.TMDB_API3_KEY}&language=zh-CN&include_adult=true" - j = requests.get(api_url).json() + j = requests.get(api_url, timeout=2).json() for m in j["results"]: if m["media_type"] in ["tv", "movie"]: url = f"https://www.themoviedb.org/{m['media_type']}/{m['id']}" @@ -204,7 +197,7 @@ def search(cls, q, page=1): try: api_url = f"https://api.spotify.com/v1/search?q={q}&type=album&limit={SEARCH_PAGE_SIZE}&offset={page*SEARCH_PAGE_SIZE}" headers = {"Authorization": f"Bearer {get_spotify_token()}"} - j = requests.get(api_url, headers=headers).json() + j = requests.get(api_url, headers=headers, timeout=2).json() for a in j["albums"]["items"]: title = a["name"] subtitle = a["release_date"] @@ -234,7 +227,7 @@ def search(cls, q, page=1): results = [] try: search_url = f"https://bandcamp.com/search?from=results&item_type=a&page={page}&q={quote_plus(q)}" - r = requests.get(search_url) + r = requests.get(search_url, timeout=2) h = html.fromstring(r.content.decode("utf-8")) albums = h.xpath('//li[@class="searchresult data-search"]') for c in albums: # type:ignore @@ -268,7 +261,7 @@ def search(cls, q, page=1): results = [] try: search_url = f"https://itunes.apple.com/search?entity=podcast&limit={page*SEARCH_PAGE_SIZE}&term={quote_plus(q)}" - r = requests.get(search_url).json() + r = requests.get(search_url, timeout=2).json() for p in r["results"][(page - 1) * SEARCH_PAGE_SIZE :]: results.append( SearchResultItem( diff --git a/catalog/views.py b/catalog/views.py index 97c61338..c7b32b77 100644 --- a/catalog/views.py +++ b/catalog/views.py @@ -13,7 +13,7 @@ from django.views.decorators.http import require_http_methods from common.config import PAGE_LINK_NUMBER -from common.utils import PageLinksGenerator, get_uuid_or_404 +from common.utils import PageLinksGenerator, get_uuid_or_404, user_identity_required from journal.models import ( Comment, Mark, @@ -65,6 +65,7 @@ def embed(request, item_path, item_uuid): ) +@user_identity_required def retrieve(request, item_path, item_uuid): # item = get_object_or_404(Item, uid=get_uuid_or_404(item_uuid)) item = Item.get_by_url(item_uuid) diff --git a/common/utils.py b/common/utils.py index ef51b34f..b42de4fb 100644 --- a/common/utils.py +++ b/common/utils.py @@ -27,6 +27,23 @@ def __init__(self, *args, **kwargs): status_code = 200 +def user_identity_required(func): # TODO make this a middleware + @functools.wraps(func) + def wrapper(request, *args, **kwargs): + from users.models import APIdentity + + identity = None + if request.user.is_authenticated: + try: + identity = APIdentity.objects.get(user=request.user) + except APIdentity.DoesNotExist: + return HttpResponseRedirect("/account/register") + request.identity = identity + return func(request, *args, **kwargs) + + return wrapper + + def target_identity_required(func): @functools.wraps(func) def wrapper(request, user_name, *args, **kwargs): @@ -38,14 +55,21 @@ def wrapper(request, user_name, *args, **kwargs): except APIdentity.DoesNotExist: return render_user_not_found(request) target_user = target.user + viewer = None if target_user and not target_user.is_active: return render_user_not_found(request) - if not target.is_visible_to_user(request.user): - return render_user_blocked(request) + if request.user.is_authenticated: + try: + viewer = APIdentity.objects.get(user=request.user) + except APIdentity.DoesNotExist: + return HttpResponseRedirect("/account/register") + if request.user != target_user: + if target.is_blocking(viewer) or target.is_blocked_by(viewer): + return render_user_blocked(request) + else: + viewer = None request.target_identity = target - # request.identity = ( - # request.user.identity if request.user.is_authenticated else None - # ) + request.identity = viewer return func(request, user_name, *args, **kwargs) return wrapper diff --git a/mastodon/api.py b/mastodon/api.py index 06de9ff3..d0013ed5 100644 --- a/mastodon/api.py +++ b/mastodon/api.py @@ -253,7 +253,7 @@ def get_related_acct_list(site, token, api): if li[1].strip() == 'rel="next"': url = li[0].strip().replace(">", "").replace("<", "") except Exception as e: - logger.error("Error GET {url} : {e}") + logger.warning(f"Error GET {url} : {e}") url = None return results @@ -270,16 +270,16 @@ def detect_server_info(login_domain) -> tuple[str, str, str]: try: response = get(url, headers={"User-Agent": USER_AGENT}) except Exception as e: - logger.error(f"Error connecting {login_domain}: {e}") + logger.warning(f"Error connecting {login_domain}: {e}") raise Exception(f"无法连接 {login_domain}") if response.status_code != 200: - logger.error(f"Error connecting {login_domain}: {response.status_code}") + logger.warning(f"Error connecting {login_domain}: {response.status_code}") raise Exception(f"实例 {login_domain} 返回错误,代码: {response.status_code}") try: j = response.json() domain = j["uri"].lower().split("//")[-1].split("/")[0] except Exception as e: - logger.error(f"Error connecting {login_domain}: {e}") + logger.warning(f"Error connecting {login_domain}: {e}") raise Exception(f"实例 {login_domain} 返回信息无法识别") server_version = j["version"] api_domain = domain diff --git a/takahe/utils.py b/takahe/utils.py index cf257d95..90884bb8 100644 --- a/takahe/utils.py +++ b/takahe/utils.py @@ -434,7 +434,7 @@ def post_collection(collection: "Collection"): collection.visibility, user.preference.mastodon_publish_public ) if existing_post and visibility != existing_post.visibility: - Takahe.delete_posts([existing_post]) + Takahe.delete_posts([existing_post.pk]) existing_post = None data = { "object": { diff --git a/users/account.py b/users/account.py index c5fa0990..df27ceba 100644 --- a/users/account.py +++ b/users/account.py @@ -323,7 +323,7 @@ def verify_email(request): try: s = TimestampSigner().unsign_object(request.GET.get("c"), max_age=60 * 15) except Exception as e: - logger.error(e) + logger.warning(f"login link invalid {e}") error = _("链接无效或已过期") return render( request, "users/verify_email.html", {"success": False, "error": error} diff --git a/users/data.py b/users/data.py index f94640f8..4c6b4d31 100644 --- a/users/data.py +++ b/users/data.py @@ -133,8 +133,8 @@ def reset_visibility(request): if request.method == "POST": visibility = int(request.POST.get("visibility")) visibility = visibility if visibility >= 0 and visibility <= 2 else 0 - reset_journal_visibility_for_user(request.user, visibility) - reset_social_visibility_for_user(request.user, visibility) + reset_journal_visibility_for_user(request.user.identity, visibility) + reset_social_visibility_for_user(request.user.identity, visibility) messages.add_message(request, messages.INFO, _("已重置。")) return redirect(reverse("users:data")) diff --git a/users/models/apidentity.py b/users/models/apidentity.py index 11ea1842..39d751a3 100644 --- a/users/models/apidentity.py +++ b/users/models/apidentity.py @@ -212,16 +212,6 @@ def is_requested(self, target: "APIdentity"): def is_followed_by(self, target: "APIdentity"): return target.is_following(self) - def is_visible_to_user(self, viewing_user: User): - return ( - (not viewing_user.is_authenticated) - or viewing_user == self.user - or ( - not self.is_blocking(viewing_user.identity) - and not self.is_blocked_by(viewing_user.identity) - ) - ) - @classmethod def get_by_handler(cls, handler: str) -> "APIdentity": """ diff --git a/users/templates/users/data.html b/users/templates/users/data.html index 7c95d798..440b98b8 100644 --- a/users/templates/users/data.html +++ b/users/templates/users/data.html @@ -148,6 +148,7 @@ + {% include "_sidebar.html" with show_profile=1 identity=request.user.identity %}