Rewrite how trade offer png's are generated to try to reduce system resources. Only render the specific html code necessary and not the entire trade offer details page.

This commit is contained in:
badblocks 2025-03-28 00:42:41 -07:00
parent 15f8eb7cf4
commit d5f8345581
9 changed files with 239 additions and 85 deletions

View file

@ -599,83 +599,47 @@ class TradeAcceptanceUpdateView(LoginRequiredMixin, FriendCodeRequiredMixin, Upd
class TradeOfferPNGView(View):
"""
Generate a PNG screenshot of the rendered trade offer detail page using Playwright.
This view loads the trade offer detail page, waits for the trade offer element to render,
simulates a click to expand extra badges, and then screenshots only the trade offer element.
This view loads the SVG representation generated by the trade_offer_svg template tag,
wraps it in a minimal HTML document, and converts it to PNG using Playwright.
"""
def get(self, request, *args, **kwargs):
# For demonstration purposes, get the first trade offer.
# In production, you might want to identify the offer via a URL parameter.
trade_offer = TradeOffer.objects.get(pk=kwargs['pk'])
if not trade_offer:
raise Http404("Trade offer not found")
from django.shortcuts import get_object_or_404
trade_offer = get_object_or_404(TradeOffer, pk=kwargs['pk'])
# Get the URL for the trade offer detail view.
detail_url = request.build_absolute_uri(
reverse_lazy("trade_offer_detail", kwargs={"pk": trade_offer.pk})+"?screenshot_mode=true"
from trades.templatetags import trade_offer_tags
# Generate context for the SVG template tag.
tag_context = trade_offer_tags.render_trade_offer_png(
{'request': request}, trade_offer, show_friend_code=True
)
# Use provided dimensions from the context
image_width = tag_context.get('image_width')
image_height = tag_context.get('image_height')
html = render_to_string("templatetags/trade_offer_png.html", tag_context)
# Launch Playwright to render the HTML and capture a screenshot.
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
context = browser.new_context(
viewport={"width": 1280, "height": 800},
browser = p.chromium.launch(
headless=True,
args=[
"--disable-gpu",
"--no-sandbox",
'--disable-setuid-sandbox',
'--disable-dev-shm-usage',
'--disable-accelerated-2d-canvas',
'--no-first-run',
'--disable-gpu'
]
)
# If the request contains a Django session cookie,
# add it to the browser context to bypass the login screen.
session_cookie = request.COOKIES.get(settings.SESSION_COOKIE_NAME)
if session_cookie:
cookie = {
"name": settings.SESSION_COOKIE_NAME,
"value": session_cookie,
"domain": request.get_host().split(':')[0],
"path": "/",
"httpOnly": True,
"secure": not settings.DEBUG,
}
context.add_cookies([cookie])
# Open a new page and navigate to the detail view.
page = context.new_page()
page.goto(detail_url, wait_until="networkidle")
# Inject CSS to force transparency.
page.add_style_tag(content="""
html, body, .bg-base-200 {
background-color: rgba(255, 255, 255, 0) !important;
}
""")
trade_offer_selector = ".trade-offer-card-screenshot"
page.wait_for_selector(trade_offer_selector)
# Simulate a click on the toggle button within the trade offer element
# to force the extra details (e.g., extra badges) to expand.
# We use a selector that targets the first svg with a "cursor-pointer" class inside the trade offer card.
toggle_selector = f"{trade_offer_selector} svg.cursor-pointer"
try:
toggle = page.query_selector(toggle_selector)
if toggle:
toggle.click()
# Wait for the CSS animation to complete (600ms as in your template)
page.wait_for_timeout(600)
except Exception:
# If the toggle is not found or clicking fails, proceed without expansion.
pass
# Locate the element containing the trade offer and capture its screenshot.
element = page.query_selector(trade_offer_selector)
if not element:
browser.close()
raise Http404("Trade offer element not found on page")
png_bytes = element.screenshot(type="png", omit_background=True)
context_browser = browser.new_context(viewport={"width": image_width, "height": image_height})
page = context_browser.new_page()
page.set_content(html, wait_until="networkidle")
element = page.wait_for_selector(".trade-offer-card-screenshot")
screenshot_bytes = element.screenshot(type="png", omit_background=True)
browser.close()
return HttpResponse(png_bytes, content_type="image/png")
return HttpResponse(screenshot_bytes, content_type="image/png")
class TradeOfferCreateConfirmView(LoginRequiredMixin, View):
"""