136 lines
No EOL
3.9 KiB
Python
136 lines
No EOL
3.9 KiB
Python
import os
|
|
import hashlib
|
|
import time
|
|
from typing import List
|
|
import secrets
|
|
|
|
from playwright.sync_api import sync_playwright
|
|
from jinja2 import Environment, FileSystemLoader, StrictUndefined
|
|
from jinja2.sandbox import SandboxedEnvironment
|
|
|
|
from config.config import TMP, TZINFO
|
|
from utils.err import easyExceptionHandler
|
|
|
|
# configuration
|
|
IMAGE_WIDTH = 1080
|
|
IMAGE_HEIGHT = 1350
|
|
TEMPLATE_DIR = "./PictureMaker/templates"
|
|
TARGET_COMMENT_SYSTEM = True # set this to False if your platform not have comment system
|
|
|
|
def render(post_context:dict) -> tuple[list[str], int]:
|
|
err = 0
|
|
|
|
browser = None
|
|
page = None
|
|
context = None
|
|
|
|
fnlist = []
|
|
try:
|
|
with sync_playwright() as p:
|
|
# open a browser
|
|
browser = p.chromium.launch(headless=True)
|
|
context = browser.new_context()
|
|
page = context.new_page()
|
|
|
|
# render template
|
|
env = SandboxedEnvironment( # sandbox -> 降低SSTI的影響範圍
|
|
loader=FileSystemLoader(TEMPLATE_DIR),
|
|
autoescape=True # auto escape -> prevent xss
|
|
)
|
|
env.undefined = StrictUndefined
|
|
|
|
template = env.get_template('index.jinja2')
|
|
main = {
|
|
"id": post_context["id"],
|
|
"content": post_context["content"]["text"],
|
|
"time": post_context["metadata"]["create_time"].astimezone(tz=TZINFO).strftime("%Y-%m-%d %H:%M:%S")
|
|
}
|
|
## (optional) parent article of comment
|
|
parent = None
|
|
if TARGET_COMMENT_SYSTEM:
|
|
from backend.utils import ld_interface
|
|
parent_id = post_context["metadata"]["parent"]
|
|
if parent_id is not None:
|
|
parent_context = ld_interface.inf.get(index=parent_id, media=False)
|
|
parent = {
|
|
"id": parent_context["id"],
|
|
"content": parent_context["content"]["text"]
|
|
}
|
|
|
|
rendered_html = template.render(main=main, parent=parent)
|
|
#print(rendered_html)
|
|
|
|
page.set_content(rendered_html)
|
|
|
|
# set window size
|
|
page.set_viewport_size({"width": IMAGE_WIDTH, "height": IMAGE_HEIGHT})
|
|
|
|
# screen shot
|
|
time.sleep(0.1)
|
|
while True:
|
|
filename = TMP + hashlib.sha512( (str(time.time()) + secrets.token_urlsafe(nbytes=24)).encode() ).hexdigest() + ".jpg"
|
|
filename = os.path.abspath(filename)
|
|
page.screenshot(path=filename)
|
|
fnlist.append(filename)
|
|
|
|
result = page.evaluate("scrollPage()")
|
|
if result == 1:
|
|
break
|
|
except Exception as e:
|
|
# exception
|
|
easyExceptionHandler(e)
|
|
err = 1
|
|
finally:
|
|
if page:
|
|
try: page.close()
|
|
except: pass
|
|
if context:
|
|
try: context.close()
|
|
except: pass
|
|
if browser:
|
|
try: browser.close()
|
|
except: pass
|
|
|
|
return fnlist, err
|
|
|
|
|
|
def gen(context:dict) -> List[str]:
|
|
"""
|
|
Generate a image that has the content of the post in it.
|
|
|
|
Args:
|
|
context (dict): data of a post
|
|
|
|
Returns:
|
|
str: filename of the generated image.
|
|
None: An error occurred, and nothing was returned.
|
|
"""
|
|
|
|
# data preparation
|
|
# content = context["content"]["text"]
|
|
|
|
# generate image
|
|
files, err = render(context)
|
|
if err:
|
|
return []
|
|
|
|
return files
|
|
|
|
|
|
def gen_caption(context:dict) -> str:
|
|
"""
|
|
Generate caption of the IG post.
|
|
|
|
Args:
|
|
context (dict): data of a post
|
|
|
|
Returns:
|
|
str: caption.
|
|
"""
|
|
|
|
caption = f"""中工匿名#{context["id"]} 🔧 {context["content"]["text"]}
|
|
|
|
發布匿名貼文 > niming.tcivs.live
|
|
"""
|
|
|
|
return caption |