|
@@ -58,25 +58,29 @@ app.add_middleware(
|
|
|
)
|
|
|
SECRET_KEY = "df2f77bd544240801a048bd4293afd8eeb7fff3cb7050e42c791db4b83ebadcd"
|
|
|
ALGORITHM = "HS256"
|
|
|
-ACCESS_TOKEN_EXPIRE_MINUTES = 3000
|
|
|
+ACCESS_TOKEN_EXPIRE_DAYS = 5
|
|
|
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
|
|
|
|
|
|
app.mount("/static", StaticFiles(directory="static"), name="static")
|
|
|
app.mount("/static/img", StaticFiles(directory="static/img"), name="static/img")
|
|
|
-app.mount("/html", StaticFiles(directory="templates"), name="templates")
|
|
|
+app.mount("/templates", StaticFiles(directory="templates"), name="templates")
|
|
|
|
|
|
templates = Jinja2Templates(directory="templates")
|
|
|
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
|
|
|
|
|
|
tmp_video_dir = '../OpenshotService/tmp_video/'
|
|
|
tmp_avatar_dir = '../../face_swap/tmp_avatar/' #change source face path here
|
|
|
-
|
|
|
+resource_server = 'www.choozmo.com:8168/'
|
|
|
+resource_folder = '/var/www/html/'
|
|
|
video_sub_folder = 'ai_anchor_video/'
|
|
|
avatar_sub_folder = 'swap_save/'
|
|
|
tmp_img_sub_folder = 'tmp_img/'
|
|
|
+pttx_sub_folder = 'tmp_pttx/'
|
|
|
img_upload_folder = '/var/www/html/'+tmp_img_sub_folder
|
|
|
video_dest = '/var/www/html/'+video_sub_folder
|
|
|
avatar_dest = '/var/www/html/'+avatar_sub_folder
|
|
|
+pttx_dest = '/var/www/html/'+pttx_sub_folder
|
|
|
+
|
|
|
|
|
|
|
|
|
# @app.get("/index2")
|
|
@@ -90,7 +94,6 @@ async def index2():
|
|
|
# home page
|
|
|
@app.get("/index", response_class=HTMLResponse)
|
|
|
async def get_home_page(request: Request, response: Response):
|
|
|
- return FileResponse('../html/index.html')
|
|
|
return templates.TemplateResponse("index.html", {"request": request, "response": response})
|
|
|
@app.get("/", response_class=HTMLResponse)
|
|
|
async def get_home_page(request: Request, response: Response):
|
|
@@ -98,7 +101,6 @@ async def get_home_page(request: Request, response: Response):
|
|
|
|
|
|
@app.get("/make_video", response_class=HTMLResponse)
|
|
|
async def get_home_page(request: Request, response: Response, Authorize: AuthJWT = Depends()):
|
|
|
- print('make_video'); # test
|
|
|
try:
|
|
|
Authorize.jwt_required()
|
|
|
except Exception as e:
|
|
@@ -127,12 +129,18 @@ async def make_video_slide(request: Request, response: Response, Authorize: Auth
|
|
|
current_user = Authorize.get_jwt_subject()
|
|
|
return templates.TemplateResponse("make_video_slide.html", {"request": request, "response": response})
|
|
|
|
|
|
-@app.get('/user_profile', response_class=HTMLResponse)
|
|
|
-def protected(request: Request, Authorize: AuthJWT = Depends()):
|
|
|
+@app.post('/user_profile', response_class=HTMLResponse)
|
|
|
+async def user_profile(token: str = Depends(oauth2_scheme)):
|
|
|
db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/AI_anchor?charset=utf8mb4')
|
|
|
- Authorize.jwt_required()
|
|
|
- current_user = Authorize.get_jwt_subject()
|
|
|
- user_obj = first(db.query('SELECT * FROM users where username ="'+str(current_user)+'"'))
|
|
|
+ user_id = get_user_id(token)
|
|
|
+ user_obj = first(db.query('SELECT * FROM users where id ="'+str(user_id)+'"'))
|
|
|
+
|
|
|
+ if user_obj is None:
|
|
|
+ raise HTTPException(
|
|
|
+ status_code=status.HTTP_401_UNAUTHORIZED,
|
|
|
+ detail="Missing token",
|
|
|
+ headers={"WWW-Authenticate": "Bearer"},
|
|
|
+ )
|
|
|
video_num = str(first(db.query('SELECT COUNT(*) FROM history_input WHERE user_id ='+str(user_obj['id'])))['COUNT(*)'])
|
|
|
total_sec = str(first(db.query('SELECT SUM(duration) FROM history_input where user_id='+str(user_obj['id'])))['SUM(duration)'])
|
|
|
left_sec = user_obj['left_time']
|
|
@@ -141,7 +149,7 @@ def protected(request: Request, Authorize: AuthJWT = Depends()):
|
|
|
statement = 'SELECT * FROM history_input WHERE user_id='+str(user_obj['id'])
|
|
|
for row in db.query(statement):
|
|
|
video_info_list.append({'id':row['id'],'title':row['name'],'duration':row['duration'],'url':row['url']})
|
|
|
- dic_return = {'user_info':{'userName':current_user,'email':user_obj['email'],'video_num':video_num,'total_sec':total_sec,'left_sec':user_obj['left_time']},'video_info':video_info_list}
|
|
|
+ dic_return = {'user_info':{'userName':user_obj['username'],'email':user_obj['email'],'video_num':video_num,'total_sec':total_sec,'left_sec':user_obj['left_time']},'video_info':video_info_list}
|
|
|
str_return = json.dumps(dic_return)
|
|
|
return str_return
|
|
|
|
|
@@ -160,19 +168,20 @@ async def login_for_access_token(request: Request, form_data: OAuth2PasswordRequ
|
|
|
detail="Incorrect username or password",
|
|
|
headers={"WWW-Authenticate": "Bearer"},
|
|
|
)
|
|
|
- access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
|
|
|
+ access_token_expires = timedelta(days=ACCESS_TOKEN_EXPIRE_DAYS)
|
|
|
access_token = create_access_token(
|
|
|
data={"sub": user.username}, expires_delta=access_token_expires
|
|
|
)
|
|
|
table = db['users']
|
|
|
user.token = access_token
|
|
|
table.update(dict(user), ['username'])
|
|
|
- access_token = Authorize.create_access_token(subject=user.username)
|
|
|
- refresh_token = Authorize.create_refresh_token(subject=user.username)
|
|
|
+ expires = timedelta(days=ACCESS_TOKEN_EXPIRE_DAYS)
|
|
|
+ access_token = Authorize.create_access_token(subject=user.username, expires_time=expires)
|
|
|
+ refresh_token = Authorize.create_refresh_token(subject=user.username, expires_time =expires)
|
|
|
Authorize.set_access_cookies(access_token)
|
|
|
Authorize.set_refresh_cookies(refresh_token)
|
|
|
#return templates.TemplateResponse("index.html", {"request": request, "msg": 'Login'})
|
|
|
- return {"access_token": access_token, "token_type": "bearer", "username": form_data.username}
|
|
|
+ return {"access_token": access_token, "token_type": "bearer"}
|
|
|
|
|
|
|
|
|
@app.post("/token")
|
|
@@ -185,29 +194,44 @@ async def access_token(form_data: OAuth2PasswordRequestForm = Depends(), Authori
|
|
|
detail="Incorrect username or password",
|
|
|
headers={"WWW-Authenticate": "Bearer"},
|
|
|
)
|
|
|
- access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
|
|
|
+ access_token_expires = timedelta(days=ACCESS_TOKEN_EXPIRE_DAYS)
|
|
|
access_token = create_access_token(
|
|
|
data={"sub": user.username}, expires_delta=access_token_expires
|
|
|
)
|
|
|
return {"access_token": access_token, "token_type": "bearer"}
|
|
|
|
|
|
-
|
|
|
-@app.post("/register")
|
|
|
-async def register(request: Request):
|
|
|
+#前後端分離完全實現後拔除
|
|
|
+@app.post("/register_old")
|
|
|
+async def register_old(request: Request):
|
|
|
+ db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/AI_anchor?charset=utf8mb4')
|
|
|
user = models.User(**await request.form())
|
|
|
user_obj = first(db.query('SELECT * FROM users where username ="'+str(user.username)+'"'))
|
|
|
- if user_obj != None:
|
|
|
+ if user_obj == None:
|
|
|
user_register(user)
|
|
|
- return templates.TemplateResponse("login.html", {'request': request,"success": True}, status_code=status.HTTP_302_FOUND)
|
|
|
+ return '註冊成功! 請回到上頁登入帳號'
|
|
|
+ #return templates.TemplateResponse("make_video.html", {"request": request, "success": True},status_code=status.HTTP_302_FOUND)
|
|
|
+ #return templates.TemplateResponse("login.html", {'request': request,"success": True}, status_code=status.HTTP_302_FOUND)
|
|
|
else:
|
|
|
return {'msg':user.username+'重複,請更改'}
|
|
|
|
|
|
+@app.post("/register")
|
|
|
+async def register(request: models.register_req):
|
|
|
+ db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/AI_anchor?charset=utf8mb4')
|
|
|
+ user_obj = first(db.query('SELECT * FROM users where username ="'+str(request.username)+'"'))
|
|
|
+ if user_obj == None:
|
|
|
+ if user_register(request):
|
|
|
+ return {'msg':'ok'}
|
|
|
+ else:
|
|
|
+ return {'msg': '內部錯誤'}
|
|
|
+ else:
|
|
|
+ return {'msg':request.username+':使用者名稱重複,請更改'}
|
|
|
+
|
|
|
|
|
|
@app.get('/logout')
|
|
|
def logout(request: Request, Authorize: AuthJWT = Depends()):
|
|
|
Authorize.jwt_required()
|
|
|
Authorize.unset_jwt_cookies()
|
|
|
- return {"msg": "Successfully logout"}
|
|
|
+ return {"msg": "ok"}
|
|
|
|
|
|
@app.get("/gen_avatar")
|
|
|
async def avatar():
|
|
@@ -226,7 +250,7 @@ async def swapFace(req:models.swap_req):
|
|
|
|
|
|
x = threading.Thread(target=gen_avatar, args=(name_hash,req.imgurl))
|
|
|
x.start()
|
|
|
- return {'msg':'人物生成中,請稍候'}
|
|
|
+ return {'msg':'ok'}
|
|
|
|
|
|
@app.post("/uploadfile/")
|
|
|
async def create_upload_file(file: UploadFile = File(...)):
|
|
@@ -236,20 +260,39 @@ async def create_upload_file(file: UploadFile = File(...)):
|
|
|
async with aiofiles.open(img_upload_folder+img_name+'.mp4', 'wb') as out_file:
|
|
|
content = await file.read()
|
|
|
await out_file.write(content)
|
|
|
- return {"msg": 'www.choozmo.com:8168/'+tmp_img_sub_folder+img_name+'.mp4'}
|
|
|
+ return {"msg": resource_server+tmp_img_sub_folder+img_name+'.mp4'}
|
|
|
else:
|
|
|
contents = await file.read()
|
|
|
image = Image.open(io.BytesIO(contents))
|
|
|
image= image.convert("RGB")
|
|
|
image.save(img_upload_folder+img_name+'.jpg')
|
|
|
- return {"msg": 'www.choozmo.com:8168/'+tmp_img_sub_folder+img_name+'.jpg'}
|
|
|
+ return {"msg": resource_server+tmp_img_sub_folder+img_name+'.jpg'}
|
|
|
except Exception as e:
|
|
|
logging.error(traceback.format_exc())
|
|
|
return {'msg':'檔案無法使用'}
|
|
|
|
|
|
+@app.post("/upload_pttx/")
|
|
|
+async def upload_pttx(file: UploadFile = File(...)):
|
|
|
+ try:
|
|
|
+ if "_" in file.filename:
|
|
|
+ return {'msg':'檔案無法使用檔名不能含有"_"符號'}
|
|
|
+ else:
|
|
|
+ pttx_name = file.filename+'_'+str(time.time()).replace('.','')
|
|
|
+ with open(pttx_dest+pttx_name, "wb+") as file_object:
|
|
|
+ file_object.write(file.file.read())
|
|
|
+ return {"msg": resource_server+pttx_sub_folder+pttx_name}
|
|
|
+ except Exception as e:
|
|
|
+ logging.error(traceback.format_exc())
|
|
|
+ return {'msg':'檔案無法使用'}
|
|
|
+
|
|
|
+
|
|
|
@app.post("/make_anchor_video_gSlide")
|
|
|
async def make_anchor_video_gSlide(req:models.gSlide_req,token: str = Depends(oauth2_scheme)):
|
|
|
- name, text_content, image_urls = gSlide.parse_slide_url(req.slide_url,eng=False)
|
|
|
+ if req.url_type == 0:
|
|
|
+ name, text_content, image_urls = gSlide.parse_slide_url(req.slide_url,eng=False)
|
|
|
+ else :
|
|
|
+ filename = req.slide_url.replace(resource_server+pttx_sub_folder,resource_folder+pttx_sub_folder)
|
|
|
+ name, text_content, image_urls = gSlide.parse_pttx_url(filename,img_upload_folder,resource_server+tmp_img_sub_folder,eng=False)
|
|
|
if len(image_urls) != len(text_content):
|
|
|
return {'msg':'副標題數量、圖片(影片)數量以及台詞數量必須一致'}
|
|
|
for idx in range(len(image_urls)):
|
|
@@ -431,6 +474,7 @@ def user_register(user):
|
|
|
table = db['users']
|
|
|
user.password = get_password_hash(user.password)
|
|
|
table.insert(dict(user))
|
|
|
+ return True
|
|
|
|
|
|
def get_password_hash(password):
|
|
|
return pwd_context.hash(password)
|
|
@@ -445,12 +489,11 @@ def authenticate_user(username: str, password: str):
|
|
|
if not verify_password(password, user.password):
|
|
|
return False
|
|
|
return user
|
|
|
-def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):
|
|
|
+
|
|
|
+def create_access_token(data: dict, expires_delta):
|
|
|
to_encode = data.copy()
|
|
|
- if expires_delta:
|
|
|
- expire = datetime.utcnow() + expires_delta
|
|
|
- else:
|
|
|
- expire = datetime.utcnow() + timedelta(minutes=15)
|
|
|
+
|
|
|
+ expire = datetime.utcnow() + expires_delta
|
|
|
to_encode.update({"exp": expire})
|
|
|
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
|
|
|
return encoded_jwt
|
|
@@ -540,7 +583,7 @@ def gen_video_long_queue(name_hash,name,text_content, image_urls,avatar,multiLan
|
|
|
except Exception as e:
|
|
|
logging.error(traceback.format_exc())
|
|
|
print('video generation error')
|
|
|
- #notify_group('長影片錯誤-測試')
|
|
|
+ notify_group('長影片錯誤-測試')
|
|
|
db['video_queue'].delete(id=top1['id'])
|
|
|
db.query('UPDATE video_queue_status SET status = 0')
|
|
|
|