fix bugs, update the example interface, and rewrite the example PictureMaker

This commit is contained in:
p23 2025-04-28 19:10:26 +08:00
parent d03e0c8e82
commit 1fc619fe06
15 changed files with 745 additions and 61 deletions

7
.gitignore vendored
View file

@ -7,3 +7,10 @@ backend/db/id2igid.db
test
testfiles
test.py
# for sljh
utils/sljh
PictureMaker/sljh.py
interface/sljh.py
frontend/sljh

View file

@ -4,7 +4,15 @@ WORKDIR /app
# apt install
RUN apt-get update && \
DEBAIN_FRONTEND=noninteractive apt-get install -qy ffmpeg libpq-dev libmagic1 libmagic-dev
DEBAIN_FRONTEND=noninteractive apt-get install -qy ffmpeg libpq-dev libmagic1 libmagic-dev locales
# locale
COPY ./env/locale.gen /env/locale.gen
RUN locale-gen
COPY ./env/locale.conf /env/locale.conf
# timezone
COPY ./env/timezone /etc/timezone
# pip3 install
COPY ./requirements.txt /app/requirements.txt
@ -13,4 +21,8 @@ COPY ./ffmpeg_python-0.2.0-py3-none-any.whl /app/ffmpeg_python-0.2.0-py3-none-an
RUN pip3 install ffmpeg_python-0.2.0-py3-none-any.whl
RUN pip3 install -r /app/requirements.txt
# install playwright
RUN playwright install-deps
RUN playwright install
EXPOSE 50051

126
PictureMaker/default.py Normal file
View file

@ -0,0 +1,126 @@
import datetime
import os
import hashlib
import time
from playwright.sync_api import sync_playwright
from jinja2 import Template
from config.config import TMP
# configuration
TIMEZONE = 8
IMAGE_WIDTH = 1280
IMAGE_HEIGHT = 1280
def render(text, filename, width=IMAGE_WIDTH, height=IMAGE_HEIGHT, font_size=60, text_color="black", margin=50) -> int:
err = 0
browser = None
page = None
context = None
try:
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
context = browser.new_context()
page = context.new_page()
# template
template = Template("{{ text }}")
processed_text = template.render(text=text)
html_content = f"""
<html>
<head>
<style>
body {{
margin: 0;
background-size: {width}px {height}px;
width: {width}px;
height: {height}px;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
}}
.text-container {{
font-size: {font_size}px;
color: {text_color};
width: calc(100% - {2 * margin}px);
text-align: center;
line-height: 1.2;
white-space: pre-wrap;
overflow-wrap: break-word;
}}
</style>
</head>
<body>
<div class="text-container">{processed_text}</div>
</body>
</html>
"""
page.set_content(html_content)
# set window size
page.set_viewport_size({"width": width, "height": height})
# screenshot
page.screenshot(path=filename)
except Exception as e:
# exception
print(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 err
def gen(context:dict) -> str | None:
"""
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
filename = TMP + hashlib.sha512( str(time.time()).encode() ).hexdigest() + ".jpg"
filename = os.path.abspath(filename)
err = render(content, filename, width=IMAGE_WIDTH, height=IMAGE_HEIGHT)
if err:
return None
return filename
def gen_caption(context:dict) -> str:
"""
Generate caption of the IG post.
Args:
context (dict): data of a post
Returns:
str: caption.
"""
caption = f"""[TCIVS Niming #{context["id"]}]
{context["content"]["text"]}
"""
return caption

View file

@ -41,5 +41,5 @@ def gen(context:dict) -> str | None:
# 文案生成
def gentext(context:dict) -> str:
def gen_caption(context:dict) -> str:
return context["content"]["text"]

3
TODO
View file

@ -1,4 +1,7 @@
[ ] 改善Traceback的收集
[ ] GIF Support
[ ] api: ID查IGIDIGID反查ID
[ ] api: 返回錯誤處理紀錄
[V] 本地儲存ID對IGID表
[ ] 測試

6
app.py
View file

@ -2,6 +2,7 @@ import importlib.util
import logging
import threading
import os
import time
from backend import backend
from backend.ig import IG
@ -76,5 +77,10 @@ def main():
# end
loaderlog.info("Loaded")
# infinity waiting - prevent main thread from exiting
while True:
time.sleep(60)
if __name__ == "__main__":
main()

View file

@ -86,10 +86,10 @@ def upload_media(context:str, paths:List[str]) -> dict | None:
if len(paths) == 0:
return None
elif len(paths) == 1:
content = ld_picturemaker.picture_maker.gentext(context)
content = ld_picturemaker.picture_maker.gen_caption(context)
media = cl.photo_upload(path=paths[0], caption=content).dict()
else:
content = ld_picturemaker.picture_maker.gentext(context)
content = ld_picturemaker.picture_maker.gen_caption(context)
media = cl.album_upload(paths=paths, caption=content).dict()
return media

View file

@ -26,38 +26,23 @@ def upload(aid:int) -> Tuple[str, int]:
# multimedia -> tmp file
tmp_path = []
for m in article["content"]["media"]:
_binary = m.read()
# check mime type
mime = magic.Magic(mime=True)
tp = mime.from_buffer(m.read())
tp = mime.from_buffer(_binary)
# save file
filename, err = fileProcessor.file_saver(tp, m.read())
filename, err = fileProcessor.file_saver(tp, _binary)
if err:
clean(tmp_path)
return "Error while saving file", 1
return "Error while saving file : %s"%filename, 1
tmp_path.append(filename)
article["content"]["media"] = []
"""
# 抓取檔案
files = []
for k in article["files_hash"]:
f, code = s3helper.solo_file_fetcher(fnhash=k)
if code:
return "File not found", 1
else:
files.append(f)
# 轉出暫存檔案
tmp_path:list = []
for t in files:
filename, err = fileProcessor.file_saver(t.get("mime"), t.get("binary"))
if err: # 如果錯誤
return filename, 1
tmp_path.append(filename)
"""
# 合成文字圖
proma_file = ld_picturemaker.picture_maker.gen(article)
if proma_file is None:
clean(tmp_path)
return "Error while generating proma_file", 1
tmp_path = [proma_file] + tmp_path
# 送交 IG 上傳

View file

@ -9,7 +9,7 @@ services:
volumes:
- ".:/app"
ports:
- "50051:50051"
- "50050:50050" # frontend.grpc
restart: unless-stopped
working_dir: /app
command: python3 ./app.py

1
env/locale.conf vendored Normal file
View file

@ -0,0 +1 @@
LANG="en_US.UTF-8"

515
env/locale.gen vendored Normal file
View file

@ -0,0 +1,515 @@
# This file lists locales that you wish to have built. You can find a list
# of valid supported locales at /usr/share/i18n/SUPPORTED, and you can add
# user defined locales to /usr/local/share/i18n/SUPPORTED. If you change
# this file, you need to rerun locale-gen.
C.UTF-8 UTF-8
# aa_DJ ISO-8859-1
# aa_DJ.UTF-8 UTF-8
# aa_ER UTF-8
# aa_ET UTF-8
# af_ZA ISO-8859-1
# af_ZA.UTF-8 UTF-8
# agr_PE UTF-8
# ak_GH UTF-8
# am_ET UTF-8
# an_ES ISO-8859-15
# an_ES.UTF-8 UTF-8
# anp_IN UTF-8
# ar_AE ISO-8859-6
# ar_AE.UTF-8 UTF-8
# ar_BH ISO-8859-6
# ar_BH.UTF-8 UTF-8
# ar_DZ ISO-8859-6
# ar_DZ.UTF-8 UTF-8
# ar_EG ISO-8859-6
# ar_EG.UTF-8 UTF-8
# ar_IN UTF-8
# ar_IQ ISO-8859-6
# ar_IQ.UTF-8 UTF-8
# ar_JO ISO-8859-6
# ar_JO.UTF-8 UTF-8
# ar_KW ISO-8859-6
# ar_KW.UTF-8 UTF-8
# ar_LB ISO-8859-6
# ar_LB.UTF-8 UTF-8
# ar_LY ISO-8859-6
# ar_LY.UTF-8 UTF-8
# ar_MA ISO-8859-6
# ar_MA.UTF-8 UTF-8
# ar_OM ISO-8859-6
# ar_OM.UTF-8 UTF-8
# ar_QA ISO-8859-6
# ar_QA.UTF-8 UTF-8
# ar_SA ISO-8859-6
# ar_SA.UTF-8 UTF-8
# ar_SD ISO-8859-6
# ar_SD.UTF-8 UTF-8
# ar_SS UTF-8
# ar_SY ISO-8859-6
# ar_SY.UTF-8 UTF-8
# ar_TN ISO-8859-6
# ar_TN.UTF-8 UTF-8
# ar_YE ISO-8859-6
# ar_YE.UTF-8 UTF-8
# as_IN UTF-8
# ast_ES ISO-8859-15
# ast_ES.UTF-8 UTF-8
# ayc_PE UTF-8
# az_AZ UTF-8
# az_IR UTF-8
# be_BY CP1251
# be_BY.UTF-8 UTF-8
# be_BY@latin UTF-8
# bem_ZM UTF-8
# ber_DZ UTF-8
# ber_MA UTF-8
# bg_BG CP1251
# bg_BG.UTF-8 UTF-8
# bhb_IN.UTF-8 UTF-8
# bho_IN UTF-8
# bho_NP UTF-8
# bi_VU UTF-8
# bn_BD UTF-8
# bn_IN UTF-8
# bo_CN UTF-8
# bo_IN UTF-8
# br_FR ISO-8859-1
# br_FR.UTF-8 UTF-8
# br_FR@euro ISO-8859-15
# brx_IN UTF-8
# bs_BA ISO-8859-2
# bs_BA.UTF-8 UTF-8
# byn_ER UTF-8
# ca_AD ISO-8859-15
# ca_AD.UTF-8 UTF-8
# ca_ES ISO-8859-1
# ca_ES.UTF-8 UTF-8
# ca_ES@euro ISO-8859-15
# ca_ES@valencia UTF-8
# ca_FR ISO-8859-15
# ca_FR.UTF-8 UTF-8
# ca_IT ISO-8859-15
# ca_IT.UTF-8 UTF-8
# ce_RU UTF-8
# chr_US UTF-8
# ckb_IQ UTF-8
# cmn_TW UTF-8
# crh_RU UTF-8
# crh_UA UTF-8
# cs_CZ ISO-8859-2
# cs_CZ.UTF-8 UTF-8
# csb_PL UTF-8
# cv_RU UTF-8
# cy_GB ISO-8859-14
# cy_GB.UTF-8 UTF-8
# da_DK ISO-8859-1
# da_DK.UTF-8 UTF-8
# de_AT ISO-8859-1
# de_AT.UTF-8 UTF-8
# de_AT@euro ISO-8859-15
# de_BE ISO-8859-1
# de_BE.UTF-8 UTF-8
# de_BE@euro ISO-8859-15
# de_CH ISO-8859-1
# de_CH.UTF-8 UTF-8
# de_DE ISO-8859-1
# de_DE.UTF-8 UTF-8
# de_DE@euro ISO-8859-15
# de_IT ISO-8859-1
# de_IT.UTF-8 UTF-8
# de_LI.UTF-8 UTF-8
# de_LU ISO-8859-1
# de_LU.UTF-8 UTF-8
# de_LU@euro ISO-8859-15
# doi_IN UTF-8
# dsb_DE UTF-8
# dv_MV UTF-8
# dz_BT UTF-8
# el_CY ISO-8859-7
# el_CY.UTF-8 UTF-8
# el_GR ISO-8859-7
# el_GR.UTF-8 UTF-8
# el_GR@euro ISO-8859-7
# en_AG UTF-8
# en_AU ISO-8859-1
# en_AU.UTF-8 UTF-8
# en_BW ISO-8859-1
# en_BW.UTF-8 UTF-8
# en_CA ISO-8859-1
# en_CA.UTF-8 UTF-8
# en_DK ISO-8859-1
# en_DK.ISO-8859-15 ISO-8859-15
# en_DK.UTF-8 UTF-8
# en_GB ISO-8859-1
# en_GB.ISO-8859-15 ISO-8859-15
# en_GB.UTF-8 UTF-8
# en_HK ISO-8859-1
# en_HK.UTF-8 UTF-8
# en_IE ISO-8859-1
# en_IE.UTF-8 UTF-8
# en_IE@euro ISO-8859-15
# en_IL UTF-8
# en_IN UTF-8
# en_NG UTF-8
# en_NZ ISO-8859-1
# en_NZ.UTF-8 UTF-8
# en_PH ISO-8859-1
# en_PH.UTF-8 UTF-8
# en_SC.UTF-8 UTF-8
# en_SG ISO-8859-1
# en_SG.UTF-8 UTF-8
# en_US ISO-8859-1
# en_US.ISO-8859-15 ISO-8859-15
en_US.UTF-8 UTF-8
# en_ZA ISO-8859-1
# en_ZA.UTF-8 UTF-8
# en_ZM UTF-8
# en_ZW ISO-8859-1
# en_ZW.UTF-8 UTF-8
# eo UTF-8
# eo_US.UTF-8 UTF-8
# es_AR ISO-8859-1
# es_AR.UTF-8 UTF-8
# es_BO ISO-8859-1
# es_BO.UTF-8 UTF-8
# es_CL ISO-8859-1
# es_CL.UTF-8 UTF-8
# es_CO ISO-8859-1
# es_CO.UTF-8 UTF-8
# es_CR ISO-8859-1
# es_CR.UTF-8 UTF-8
# es_CU UTF-8
# es_DO ISO-8859-1
# es_DO.UTF-8 UTF-8
# es_EC ISO-8859-1
# es_EC.UTF-8 UTF-8
# es_ES ISO-8859-1
# es_ES.UTF-8 UTF-8
# es_ES@euro ISO-8859-15
# es_GT ISO-8859-1
# es_GT.UTF-8 UTF-8
# es_HN ISO-8859-1
# es_HN.UTF-8 UTF-8
# es_MX ISO-8859-1
# es_MX.UTF-8 UTF-8
# es_NI ISO-8859-1
# es_NI.UTF-8 UTF-8
# es_PA ISO-8859-1
# es_PA.UTF-8 UTF-8
# es_PE ISO-8859-1
# es_PE.UTF-8 UTF-8
# es_PR ISO-8859-1
# es_PR.UTF-8 UTF-8
# es_PY ISO-8859-1
# es_PY.UTF-8 UTF-8
# es_SV ISO-8859-1
# es_SV.UTF-8 UTF-8
# es_US ISO-8859-1
# es_US.UTF-8 UTF-8
# es_UY ISO-8859-1
# es_UY.UTF-8 UTF-8
# es_VE ISO-8859-1
# es_VE.UTF-8 UTF-8
# et_EE ISO-8859-1
# et_EE.ISO-8859-15 ISO-8859-15
# et_EE.UTF-8 UTF-8
# eu_ES ISO-8859-1
# eu_ES.UTF-8 UTF-8
# eu_ES@euro ISO-8859-15
# eu_FR ISO-8859-1
# eu_FR.UTF-8 UTF-8
# eu_FR@euro ISO-8859-15
# fa_IR UTF-8
# ff_SN UTF-8
# fi_FI ISO-8859-1
# fi_FI.UTF-8 UTF-8
# fi_FI@euro ISO-8859-15
# fil_PH UTF-8
# fo_FO ISO-8859-1
# fo_FO.UTF-8 UTF-8
# fr_BE ISO-8859-1
# fr_BE.UTF-8 UTF-8
# fr_BE@euro ISO-8859-15
# fr_CA ISO-8859-1
# fr_CA.UTF-8 UTF-8
# fr_CH ISO-8859-1
# fr_CH.UTF-8 UTF-8
# fr_FR ISO-8859-1
# fr_FR.UTF-8 UTF-8
# fr_FR@euro ISO-8859-15
# fr_LU ISO-8859-1
# fr_LU.UTF-8 UTF-8
# fr_LU@euro ISO-8859-15
# fur_IT UTF-8
# fy_DE UTF-8
# fy_NL UTF-8
# ga_IE ISO-8859-1
# ga_IE.UTF-8 UTF-8
# ga_IE@euro ISO-8859-15
# gbm_IN UTF-8
# gd_GB ISO-8859-15
# gd_GB.UTF-8 UTF-8
# gez_ER UTF-8
# gez_ER@abegede UTF-8
# gez_ET UTF-8
# gez_ET@abegede UTF-8
# gl_ES ISO-8859-1
# gl_ES.UTF-8 UTF-8
# gl_ES@euro ISO-8859-15
# gu_IN UTF-8
# gv_GB ISO-8859-1
# gv_GB.UTF-8 UTF-8
# ha_NG UTF-8
# hak_TW UTF-8
# he_IL ISO-8859-8
# he_IL.UTF-8 UTF-8
# hi_IN UTF-8
# hif_FJ UTF-8
# hne_IN UTF-8
# hr_HR ISO-8859-2
# hr_HR.UTF-8 UTF-8
# hsb_DE ISO-8859-2
# hsb_DE.UTF-8 UTF-8
# ht_HT UTF-8
# hu_HU ISO-8859-2
# hu_HU.UTF-8 UTF-8
# hy_AM UTF-8
# hy_AM.ARMSCII-8 ARMSCII-8
# ia_FR UTF-8
# id_ID ISO-8859-1
# id_ID.UTF-8 UTF-8
# ig_NG UTF-8
# ik_CA UTF-8
# is_IS ISO-8859-1
# is_IS.UTF-8 UTF-8
# it_CH ISO-8859-1
# it_CH.UTF-8 UTF-8
# it_IT ISO-8859-1
# it_IT.UTF-8 UTF-8
# it_IT@euro ISO-8859-15
# iu_CA UTF-8
# ja_JP.EUC-JP EUC-JP
ja_JP.UTF-8 UTF-8
# ka_GE GEORGIAN-PS
# ka_GE.UTF-8 UTF-8
# kab_DZ UTF-8
# kk_KZ PT154
# kk_KZ.RK1048 RK1048
# kk_KZ.UTF-8 UTF-8
# kl_GL ISO-8859-1
# kl_GL.UTF-8 UTF-8
# km_KH UTF-8
# kn_IN UTF-8
# ko_KR.EUC-KR EUC-KR
ko_KR.UTF-8 UTF-8
# kok_IN UTF-8
# ks_IN UTF-8
# ks_IN@devanagari UTF-8
# ku_TR ISO-8859-9
# ku_TR.UTF-8 UTF-8
# kv_RU UTF-8
# kw_GB ISO-8859-1
# kw_GB.UTF-8 UTF-8
# ky_KG UTF-8
# lb_LU UTF-8
# lg_UG ISO-8859-10
# lg_UG.UTF-8 UTF-8
# li_BE UTF-8
# li_NL UTF-8
# lij_IT UTF-8
# ln_CD UTF-8
# lo_LA UTF-8
# lt_LT ISO-8859-13
# lt_LT.UTF-8 UTF-8
# lv_LV ISO-8859-13
# lv_LV.UTF-8 UTF-8
# lzh_TW UTF-8
# mag_IN UTF-8
# mai_IN UTF-8
# mai_NP UTF-8
# mfe_MU UTF-8
# mg_MG ISO-8859-15
# mg_MG.UTF-8 UTF-8
# mhr_RU UTF-8
# mi_NZ ISO-8859-13
# mi_NZ.UTF-8 UTF-8
# miq_NI UTF-8
# mjw_IN UTF-8
# mk_MK ISO-8859-5
# mk_MK.UTF-8 UTF-8
# ml_IN UTF-8
# mn_MN UTF-8
# mni_IN UTF-8
# mnw_MM UTF-8
# mr_IN UTF-8
# ms_MY ISO-8859-1
# ms_MY.UTF-8 UTF-8
# mt_MT ISO-8859-3
# mt_MT.UTF-8 UTF-8
# my_MM UTF-8
# nan_TW UTF-8
# nan_TW@latin UTF-8
# nb_NO ISO-8859-1
# nb_NO.UTF-8 UTF-8
# nds_DE UTF-8
# nds_NL UTF-8
# ne_NP UTF-8
# nhn_MX UTF-8
# niu_NU UTF-8
# niu_NZ UTF-8
# nl_AW UTF-8
# nl_BE ISO-8859-1
# nl_BE.UTF-8 UTF-8
# nl_BE@euro ISO-8859-15
# nl_NL ISO-8859-1
# nl_NL.UTF-8 UTF-8
# nl_NL@euro ISO-8859-15
# nn_NO ISO-8859-1
# nn_NO.UTF-8 UTF-8
# nr_ZA UTF-8
# nso_ZA UTF-8
# oc_FR ISO-8859-1
# oc_FR.UTF-8 UTF-8
# om_ET UTF-8
# om_KE ISO-8859-1
# om_KE.UTF-8 UTF-8
# or_IN UTF-8
# os_RU UTF-8
# pa_IN UTF-8
# pa_PK UTF-8
# pap_AW UTF-8
# pap_CW UTF-8
# pl_PL ISO-8859-2
# pl_PL.UTF-8 UTF-8
# ps_AF UTF-8
# pt_BR ISO-8859-1
# pt_BR.UTF-8 UTF-8
# pt_PT ISO-8859-1
# pt_PT.UTF-8 UTF-8
# pt_PT@euro ISO-8859-15
# quz_PE UTF-8
# raj_IN UTF-8
# rif_MA UTF-8
# ro_RO ISO-8859-2
# ro_RO.UTF-8 UTF-8
# ru_RU ISO-8859-5
# ru_RU.CP1251 CP1251
# ru_RU.KOI8-R KOI8-R
ru_RU.UTF-8 UTF-8
# ru_UA KOI8-U
# ru_UA.UTF-8 UTF-8
# rw_RW UTF-8
# sa_IN UTF-8
# sah_RU UTF-8
# sat_IN UTF-8
# sc_IT UTF-8
# sd_IN UTF-8
# sd_IN@devanagari UTF-8
# sd_PK UTF-8
# se_NO UTF-8
# sgs_LT UTF-8
# shn_MM UTF-8
# shs_CA UTF-8
# si_LK UTF-8
# sid_ET UTF-8
# sk_SK ISO-8859-2
# sk_SK.UTF-8 UTF-8
# sl_SI ISO-8859-2
# sl_SI.UTF-8 UTF-8
# sm_WS UTF-8
# so_DJ ISO-8859-1
# so_DJ.UTF-8 UTF-8
# so_ET UTF-8
# so_KE ISO-8859-1
# so_KE.UTF-8 UTF-8
# so_SO ISO-8859-1
# so_SO.UTF-8 UTF-8
# sq_AL ISO-8859-1
# sq_AL.UTF-8 UTF-8
# sq_MK UTF-8
# sr_ME UTF-8
# sr_RS UTF-8
# sr_RS@latin UTF-8
# ss_ZA UTF-8
# ssy_ER UTF-8
# st_ZA ISO-8859-1
# st_ZA.UTF-8 UTF-8
# su_ID UTF-8
# sv_FI ISO-8859-1
# sv_FI.UTF-8 UTF-8
# sv_FI@euro ISO-8859-15
# sv_SE ISO-8859-1
# sv_SE.ISO-8859-15 ISO-8859-15
# sv_SE.UTF-8 UTF-8
# sw_KE UTF-8
# sw_TZ UTF-8
# syr UTF-8
# szl_PL UTF-8
# ta_IN UTF-8
# ta_LK UTF-8
# tcy_IN.UTF-8 UTF-8
# te_IN UTF-8
# tg_TJ KOI8-T
# tg_TJ.UTF-8 UTF-8
# th_TH TIS-620
th_TH.UTF-8 UTF-8
# the_NP UTF-8
# ti_ER UTF-8
# ti_ET UTF-8
# tig_ER UTF-8
# tk_TM UTF-8
# tl_PH ISO-8859-1
# tl_PH.UTF-8 UTF-8
# tn_ZA UTF-8
# to_TO UTF-8
# tok UTF-8
# tpi_PG UTF-8
# tr_CY ISO-8859-9
# tr_CY.UTF-8 UTF-8
# tr_TR ISO-8859-9
# tr_TR.UTF-8 UTF-8
# ts_ZA UTF-8
# tt_RU UTF-8
# tt_RU@iqtelif UTF-8
# ug_CN UTF-8
# ug_CN@latin UTF-8
# uk_UA KOI8-U
# uk_UA.UTF-8 UTF-8
# unm_US UTF-8
# ur_IN UTF-8
# ur_PK UTF-8
# uz_UZ ISO-8859-1
# uz_UZ.UTF-8 UTF-8
# uz_UZ@cyrillic UTF-8
# ve_ZA UTF-8
# vi_VN UTF-8
# wa_BE ISO-8859-1
# wa_BE.UTF-8 UTF-8
# wa_BE@euro ISO-8859-15
# wae_CH UTF-8
# wal_ET UTF-8
# wo_SN UTF-8
# xh_ZA ISO-8859-1
# xh_ZA.UTF-8 UTF-8
# yi_US CP1255
# yi_US.UTF-8 UTF-8
# yo_NG UTF-8
# yue_HK UTF-8
# yuw_PG UTF-8
# zgh_MA UTF-8
# zh_CN GB2312
# zh_CN.GB18030 GB18030
# zh_CN.GBK GBK
zh_CN.UTF-8 UTF-8
# zh_HK BIG5-HKSCS
# zh_HK.UTF-8 UTF-8
# zh_SG GB2312
# zh_SG.GBK GBK
# zh_SG.UTF-8 UTF-8
# zh_TW BIG5
# zh_TW.EUC-TW EUC-TW
zh_TW.UTF-8 UTF-8
# zu_ZA ISO-8859-1
# zu_ZA.UTF-8 UTF-8

1
env/timezone vendored Normal file
View file

@ -0,0 +1 @@
Asia/Taipei

View file

@ -7,6 +7,9 @@ from backend import api
from frontend.grpc.protobuf import igapi_pb2_grpc, igapi_pb2
from frontend.grpc.protobuf.igapi_pb2 import Request, Reply
# configuration
PORT = 50050
# logging
grpclog = logging.getLogger("frontend.grpc")
grpclog.setLevel(level=logging.INFO)
@ -77,9 +80,9 @@ async def serve() -> None:
igapi_pb2_grpc.add_IGAPIServicer_to_server(
IGAPI_Server(), server
)
server.add_insecure_port("[::]:50051")
server.add_insecure_port(f"[::]:{PORT}")
await server.start()
grpclog.info("gRPC Server listening on 0.0.0.0:50051")
grpclog.info(f"gRPC Server listening on 0.0.0.0:{PORT}")
await server.wait_for_termination()

View file

@ -1,50 +1,46 @@
from hashlib import sha512
import secrets
import time
import datetime
import requests
import io
from config.config import TMP
"""
Interface
# define
an_example_of_context = {
"id": int,
"metadata": {
"create_time": int,
"author": str,
"tags": list[str],
"category": str
},
"content": {
"text": str,
"media": [
io.BytesIO
]
}
}
The bridge between web application(niming) and igapi.
An interface should have a get() function.
"""
def get(index:int, media:bool=True) -> dict | None:
"""
Every interface should have this function.
Backend calls this function to get data of a post.
Args:
index (int): ID of the post
media (bool): Send media or not
Returns:
dict: Data of a post. Formatted as shown in Note 1 (an_example_of_context)
None: An error occurred, and nothing was returned.
"""
# get data
## fake server in localhost
### where is the api of web application?
res = requests.get("http://localhost:5000/article/%d?media_count=1"%index)
if res.status_code != 200:
return None
rj = res.json()
media = []
bytesio = 0
# get media
if media:
for m in rj["media"]:
_m = requests.get(m)
if _m.status_code == 200:
#if bytesio: # save in memory
media.append(io.BytesIO(_m.content))
#else: # save in file
# filename = sha512( (str(time.time())+secrets.token_urlsafe(nbytes=16)).encode() ).hexdigest()
# filename = f"./{TMP}/{filename}"
# with open(filename, "wb") as f:
# f.write(_m.content)
# media.append(filename)
# return
result = {
"id": rj["id"],
"metadata": {
@ -60,3 +56,21 @@ def get(index:int, media:bool=True) -> dict | None:
}
return result
# Note 1
an_example_of_context = {
"id": int,
"metadata": {
"create_time": int | datetime.datetime,
"author": str,
"tags": list[str],
"category": str
},
"content": {
"text": str,
"media": [
io.BytesIO
]
}
}

View file

@ -1,11 +1,22 @@
# backend
moviepy==1.0.3
instagrapi
sqlalchemy
sqlalchemy_utils
protobuf==5.28.3
Pillow
pillow-heif
asyncio
grpcio
cachetools
python-magic
# frontend.grpc
grpcio
protobuf==5.28.3
# PictureMaker
playwright
jinja2
# other
#pymysql
#cryptography