Merge pull request #838 from 26F-Studio/ci-api-new

Ci api new close #821
This commit is contained in:
Particle_G
2023-01-23 01:09:58 +08:00
committed by GitHub
18 changed files with 165 additions and 505 deletions

View File

@@ -193,7 +193,7 @@ jobs:
dir: ./libAndroid
- name: Build Android packages
id: build-packages
uses: love-actions/love-actions-android@v1
uses: love-actions/love-actions-android@main
with:
app-name: ${{ needs.get-info.outputs.app-name }}
bundle-id: ${{ steps.process-app-name.outputs.bundle-id }}
@@ -205,6 +205,7 @@ jobs:
love-package: ${{ env.CORE_LOVE_PACKAGE_PATH }}
resource-path: ./.github/build/android/${{ env.BUILD_TYPE }}/res
extra-assets: ./libAndroid/
custom-scheme: studio26f://oauth
product-name: ${{ steps.process-app-name.outputs.product-name }}
version-string: ${{ needs.get-info.outputs.version-string }}
version-code: ${{ needs.get-info.outputs.version-code }}
@@ -681,6 +682,19 @@ jobs:
with:
platform: Windows
dir: ./ColdClear
- name: Update Windows template
shell: python3 {0}
run: |
version_string = "${{ needs.get-info.outputs.version-string }}"
file_version = (f"{version_string.replace('.', ',')},0")
with open("./.github/build/windows/${{ env.BUILD_TYPE }}/template.rc", "r+", encoding="utf8") as file:
data = file.read()
data = data\
.replace("@Version", version_string)\
.replace("@FileVersion", file_version)
file.seek(0)
file.truncate()
file.write(data)
- name: Build Windows packages
id: build-packages
uses: love-actions/love-actions-windows@v1
@@ -691,7 +705,9 @@ jobs:
extra-assets-x86: ./ColdClear/x86/CCloader.dll ./ColdClear/x86/cold_clear.dll
extra-assets-x64: ./ColdClear/x64/CCloader.dll ./ColdClear/x64/cold_clear.dll
product-name: ${{ steps.process-app-name.outputs.product-name }}
version-string: ${{ needs.get-info.outputs.version-string }}
app-id: ${{ secrets.WINDOWS_APP_ID }}
project-website: https://www.studio26f.org/
installer-languages: ChineseSimplified.isl English.isl Japanese.isl French.isl
output-folder: ${{ env.OUTPUT_FOLDER }}
- name: Upload 32-bit artifact
uses: actions/upload-artifact@v3
@@ -703,6 +719,11 @@ jobs:
with:
name: ${{ needs.get-info.outputs.base-name }}_Windows_x64
path: ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_x64.zip
- name: Upload installer artifact
uses: actions/upload-artifact@v3
with:
name: ${{ needs.get-info.outputs.base-name }}_Windows_installer
path: ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_installer.exe
- name: Prepare for release
if: ${{ startsWith(github.ref, 'refs/tags/pre') || startsWith(github.ref, 'refs/tags/v') }}
shell: bash
@@ -710,6 +731,7 @@ jobs:
mkdir -p ${{ env.RELEASE_FOLDER }}
cp ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_x86.zip ${{ env.RELEASE_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_Windows_x86.zip
cp ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_x64.zip ${{ env.RELEASE_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_Windows_x64.zip
cp ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_installer.exe ${{ env.RELEASE_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_Windows_installer.exe
- name: Upload release
if: ${{ startsWith(github.ref, 'refs/tags/pre') || startsWith(github.ref, 'refs/tags/v') }}
uses: ncipollo/release-action@v1
@@ -718,6 +740,7 @@ jobs:
artifacts: |
${{ env.RELEASE_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_Windows_x86.zip
${{ env.RELEASE_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_Windows_x64.zip
${{ env.RELEASE_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_Windows_installer.exe
body: ${{ needs.get-info.outputs.update-note }}
name: ${{ needs.get-info.outputs.update-title }}
prerelease: ${{ startsWith(github.ref, 'refs/tags/pre') }}

View File

@@ -587,10 +587,8 @@ do-- Userdata tables
USER=setmetatable({-- User infomation
__data={
uid=false,
email=false,
password=false,
rToken=false,
aToken=false,
oToken=false,
},
},{
__index=function(self,k)

View File

@@ -744,21 +744,11 @@ return {
music="BGMs",
label="label",
},
login_pw={
login={
title="Sign In",
login_mail="Login with E-mail/Sign Up",
email="Email Address",
password="Password",
showEmail="Show Email",
login="Log In",
},
login_mail={
title="Sign In/Sign Up",
login_pw="Password Sign In",
email="Email Address",
send="Send code",
code="Verification Code",
verify="Verify",
ticket="Auth Ticket",
authorize="Open Authorizing Page",
submit="Submit",
},
reset_password={
title="Reset Password",

View File

@@ -736,21 +736,11 @@ return {
music="BGMs",
label="Etiq.",
},
login_pw={
title="Entrar",
login_mail="Registrarse/Pedir código",
email="Correo Elec.",
password="Contraseña",
showEmail="Mostrar Correo",
login="Entrar",
},
login_mail={
title="Entrar/Registrarse",
login_pw="Ingr. con Contraseña",
email="Correo Elec.",
send="Enviar código",
code="Código de Verif.",
verify="Verificar",
login={
-- title="Sign In",
-- ticket="Auth Ticket",
-- authorize="Open Authorizing Page",
-- submit="Submit",
},
reset_password={
title="Restablecer Contraseña",

View File

@@ -699,21 +699,11 @@ return {
music="Musique",
-- label="label",
},
login_pw={
title="Connexion",
-- login_mail="Login with E-mail/Sign Up",
email="E-mail",
password="Mot de passe",
-- showEmail="Show Email",
login="Connexion",
},
login_mail={
title="Connexion/Enregistrement",
-- login_pw="Password Sign In",
email="E-mail",
-- send="Send code",
-- code="Verification Code",
-- verify="Verify",
login={
-- title="Sign In",
-- ticket="Auth Ticket",
-- authorize="Open Authorizing Page",
-- submit="Submit",
},
reset_password={
-- title="Reset Password",

View File

@@ -745,21 +745,11 @@ return {
music="Musik",
label="label",
},
login_pw={
title="Masuk",
-- login_mail="Login with E-mail/Sign Up",
email="Alamat Email",
password="Password",
showEmail="Tunjukkan Email",
login="Masuk",
},
login_mail={
title="Masuk/Daftar",
-- login_pw="Password Sign In",
email="Alamat Email",
-- send="Send code",
-- code="Verification Code",
-- verify="Verify",
login={
-- title="Sign In",
-- ticket="Auth Ticket",
-- authorize="Open Authorizing Page",
-- submit="Submit",
},
reset_password={
-- title="Reset Password",

View File

@@ -746,21 +746,11 @@ return {
music="",
label="ラベル",
},
login_pw={
title="ログイン",
login_mail="アカウントを登録/パスワードを忘れた",
email="Eメールアドレス",
password="パスワード",
showEmail="Eメールアドレスを表示",
login="ログイン",
},
login_mail={
title="サインイン/サインアップ",
login_pw="パスワードでログイン",
email="Eメールアドレス",
send="認証コード送信",
code="認証コード",
verify="認証",
logi={
-- title="Sign In",
-- ticket="Auth Ticket",
-- authorize="Open Authorizing Page",
-- submit="Submit",
},
reset_password={
title="パスワード再設定",

View File

@@ -734,21 +734,11 @@ return {
-- music="BGMs",
-- label="label",
},
login_pw={
title="Log in",
-- login_mail="Login with E-mail/Sign Up",
email="Endereço De Email",
password="Senha",
-- showEmail="Show Email",
login="Log in",
},
login_mail={
title="Log in/Registrar",
-- login_pw="Password Sign In",
email="Endereço De Email",
-- send="Send code",
-- code="Verification Code",
-- verify="Verify",
login={
-- title="Sign In",
-- ticket="Auth Ticket",
-- authorize="Open Authorizing Page",
-- submit="Submit",
},
reset_password={
-- title="Reset Password",

View File

@@ -485,21 +485,11 @@ return {
music="~~~",
label="...",
},
login_pw={
title="Log in",
-- login_mail="Login with E-mail/Sign Up",
email="@",
password="*",
showEmail="?",
login="",
},
login_mail={
title="Log in/Sign up",
login_pw="*** →",
email="@",
send="",
code="",
verify="!",
login={
title="Sign In",
ticket="***",
authorize="**?",
submit="<!>",
},
reset_password={
title="R ***",

View File

@@ -744,21 +744,11 @@ return {
path="打开存储目录",
save="用户档案管理",
},
login_pw={
login={
title="登录",
login_mail="邮箱登录/注册",
email="邮箱",
password="密码",
showEmail="显示邮箱",
login="登录",
},
login_mail={
title="登录/注册",
login_pw="密码登录",
email="邮箱",
send="发送验证码",
code="验证码",
verify="验证邮箱",
ticket="登录口令",
authorize="去官网获取口令",
submit="登录",
},
reset_password={
title="重置密码",

View File

@@ -693,21 +693,11 @@ return {
path="OpenPath();",
save="DataManagement();",
},
login_pw={
title="LogIn.UI",
login_mail="Login_mail_sign_up()",
email="Email=",
password="Password=",
showEmail="ShowEmail",
login="Login();",
},
login_mail={
title="LogIn_Register.UI",
login_pw="Login_pw();",
email="Email=",
send="Send();",
code="V-code=",
verify="Verify();",
login={
title="SignIn.UI",
ticket="Ticket=",
authorize="Authorize()",
submit="Submit()",
},
reset_password={
title="Reset_Password.UI",

View File

@@ -744,21 +744,11 @@ return {
path="打開存儲目錄",
save="用戶資料管理",
},
login_pw={
login={
title="登錄",
login_mail="電郵登錄/注册",
email="電郵",
password="密碼",
showEmail="顯示郵箱",
login="登錄",
},
login_mail={
title="登錄/註冊",
login_pw="密碼登錄",
email="電郵",
send="發送驗證碼",
code="驗證碼",
verify="驗證郵箱",
ticket="登錄口令",
authorize="去官網獲取口令",
submit="登錄",
},
reset_password={
title="重設密碼",

View File

@@ -119,257 +119,43 @@ local function getMsg(request,timeout)
end
end
end
function NET.getCode(email)
if not TASK.lock('getCode') then return end
function NET.login(auto)
if not TASK.lock('login') then return end
TASK.new(function()
WAIT{
quit=function()
TASK.unlock('getCode')
HTTP.deletePool('getCode')
end,
timeout=12.6,
}
local res=getMsg({
pool='getCode',
path='/techmino/api/v1/auth/verify/email',
body={email=email},
},12.6)
if res and res.code==200 then
MES.new('info',text.checkEmail,5)
end
WAIT.interrupt()
end)
end
function NET.codeLogin(email,code)
if not TASK.lock('codeLogin') then return end
TASK.new(function()
WAIT{
quit=function()
TASK.unlock('codeLogin')
HTTP.deletePool('codeLogin')
end,
timeout=6.26,
}
local res=getMsg({
pool='codeLogin',
path='/techmino/api/v1/auth/login/email',
body={
email=email,
code=code,
},
},6.26)
if res then
if res.code==200 then
USER.rToken=res.data.refreshToken
USER.aToken=res.data.accessToken
saveUser()
NET.ws_connect()
SCN.swapTo('net_menu')
elseif res.code==201 then
USER.rToken=res.data.refreshToken
USER.aToken=res.data.accessToken
saveUser()
SCN.pop()SCN.push('net_menu')
SCN.go('reset_password',nil,code)
end
end
WAIT.interrupt()
end)
end
function NET.setPW(code,pw)
if not TASK.lock('setPW') then return end
TASK.new(function()
WAIT{
quit=function()
TASK.unlock('setPW')
HTTP.deletePool('setPW')
end,
timeout=6.26,
}
local salt do
local res=getMsg({
pool='pwLogin',
path='/techmino/api/v1/auth/seed/email',
body={
email=USER.email,
},
},6.26)
if res and res.code==200 then
salt=res.data
else
WAIT.interrupt()
return
end
end
pw=HASH.pbkdf2(HASH.sha3_256,pw,salt,260)
local res=getMsg({
pool='setPW',
method='PUT',
path='/techmino/api/v1/auth/reset/email',
body={
email=USER.email,
code=code,
newPassword=pw,
},
},6.26)
if res then
if res.code==200 then
USER.password=pw
saveUser()
SCN.back()
end
end
WAIT.interrupt()
end)
end
function NET.autoLogin()
if not TASK.lock('autoLogin') then return end
TASK.new(function()
WAIT{
quit=function()
TASK.unlock('autoLogin')
HTTP.deletePool('autoLogin')
TASK.unlock('login')
HTTP.deletePool('login')
end,
timeout=12.6,
}
if USER.aToken then
local res=getMsg({
pool='autoLogin',
path='/techmino/api/v1/auth/check',
pool='login',
url='cafuuchino1.3322.org:8081',
path='/studio26f/api/v1/auth/check',
headers={["x-access-token"]=USER.aToken},
},6.26)
if res then
if res.code==200 then
USER.uid=res.data
saveUser()
NET.ws_connect()
SCN.go('net_menu')
WAIT.interrupt()
return
end
else
WAIT.interrupt()
return
end
end
if USER.rToken then
local res=getMsg({
pool='autoLogin',
path='/techmino/api/v1/auth/refresh',
headers={["x-refresh-token"]=USER.rToken},
},6.26)
if res then
if res.code==200 then
USER.rToken=res.data.refreshToken
if res and math.floor(res.code/100)==2 then
USER.uid=res.data.playerId
if res.data.accessToken then
USER.aToken=res.data.accessToken
saveUser()
NET.ws_connect()
SCN.go('net_menu')
WAIT.interrupt()
return
end
else
WAIT.interrupt()
return
end
end
if USER.password then
local res=getMsg({
pool='pwLogin',
path='/techmino/api/v1/auth/login/email',
body={
email=USER.email,
password=USER.password,
},
},6.26)
if res then
if res.code==200 then
USER.rToken=res.data.refreshToken
USER.aToken=res.data.accessToken
saveUser()
NET.ws_connect()
SCN.go('net_menu')
WAIT.interrupt()
return
saveUser()
NET.ws_connect()
if not auto then-- Quit login menu
SCN.pop()
end
else
WAIT.interrupt()
end
end
SCN.go('login_pw')
WAIT.interrupt()
end)
end
function NET.pwLogin(email,pw)
if not TASK.lock('pwLogin') then return end
TASK.new(function()
WAIT{
quit=function()
TASK.unlock('pwLogin')
HTTP.deletePool('pwLogin')
end,
timeout=12.6,
}
TEST.yieldT(.26)
local salt do
local res=getMsg({
pool='pwLogin',
path='/techmino/api/v1/auth/seed/email',
body={
email=email,
},
},6.26)
if res and res.code==200 then
salt=res.data
else
SCN.go('net_menu')
WAIT.interrupt()
return
end
end
pw=HASH.pbkdf2(HASH.sha3_256,pw,salt,260)
do
local res=getMsg({
pool='pwLogin',
path='/techmino/api/v1/auth/login/email',
body={
email=email,
password=pw,
},
},6.26)
if res then
if res.code==200 then
USER.email=email
USER.password=pw
USER.rToken=res.data.refreshToken
USER.aToken=res.data.accessToken
saveUser()
NET.ws_connect()
SCN.swapTo('net_menu')
end
end
end
SCN.go('login')
WAIT.interrupt()
end)
end
@@ -377,7 +163,8 @@ function NET.getUserInfo(uid)
TASK.new(function()
local res=getMsg({
pool='getInfo',
path='/techmino/api/v1/player/info?playerId='..uid,
url='cafuuchino1.3322.org:8081',
path='/studio26f/api/v1/player/info?playerId='..uid,
},6.26)
if res and res.code==200 and type(res.data)=='table' then
@@ -389,7 +176,8 @@ function NET.getAvatar(uid)
TASK.new(function()
local res=getMsg({
pool='getInfo',
path='/techmino/api/v1/player/avatar?playerId='..uid,
url='cafuuchino1.3322.org:8081',
path='/studio26f/api/v1/player/avatar?playerId='..uid,
},6.26)
if res and res.code==200 and type(res.data)=='string' then
@@ -759,7 +547,7 @@ end
function NET.ws_connect()
if WS.status('game')=='dead' then
WS.connect('game','',{['x-access-token']=USER.aToken},6)
WS.connect('game','',{['x-access-token']=USER.oToken},6)
TASK.removeTask_code(NET.ws_update)
TASK.new(NET.ws_update)
end
@@ -785,11 +573,15 @@ function NET.ws_update()
local res=getMsg({
pool='getUID',
path='/techmino/api/v1/auth/check',
headers={["x-access-token"]=USER.aToken},
headers={["x-access-token"]=USER.oToken},
},6.26)
if res and res.code==200 then
USER.uid=res.data
if res and math.floor(res.code/100)==2 then
USER.uid=res.data.playerId
if res.data.accessToken then
USER.oToken=res.data.accessToken
end
saveUser()
else
TEST.yieldUntilNextScene()
GAME.playing=false

60
parts/scenes/login.lua Normal file
View File

@@ -0,0 +1,60 @@
local scene={}
local function _authorize()
love.system.openURL("https://dev.studio26f.org/oauth?product=techmino")
end
local function _submit()
local tickets=scene.widgetList.ticket:getText():upper()
if #tickets~=128 then
MES.new('error',text.wrongCode)
else
USER.aToken=tickets:sub(1,64)
USER.oToken=tickets:sub(65)
NET.login()
end
end
local function _paste()
local t=love.system.getClipboardText()
if t then
t=STRING.trim(t)
if #t==128 and t:match("[0-9A-Z]+") then
scene.widgetList.ticket:setText(t)
return
end
end
MES.new('error',text.wrongCode)
end
function scene.enter()
scene.widgetList.ticket:clear()
end
function scene.keyDown(key,rep)
if key=='escape' and not rep then
SCN.back()
elseif key=='return' or key=='kpenter' then
if #scene.widgetList.ticket:getText()==0 then
_authorize()
else
_submit()
end
elseif key=='v' and love.keyboard.isDown('lctrl','rctrl') then
_paste()
else
return true
end
end
scene.widgetList={
WIDGET.newText{name='title', x=80, y=50,font=70,align='L'},
WIDGET.newInputBox{name='ticket', x=280, y=200,w=730,h=320,font=30,regex="[0-9A-Z]",limit=128},
WIDGET.newKey{name='authorize', x=430, y=600,w=300,h=80,font=40,code=_authorize},
WIDGET.newKey{name='submit', x=755, y=600,w=300,h=80,font=40,code=_submit},
WIDGET.newKey{name='paste', x=970, y=600,w=80,font=40,fText=CHAR.icon.import,code=_paste},
WIDGET.newButton{name='back', x=1140,y=640,w=170,h=80,sound='back',font=60,fText=CHAR.icon.back,code=pressKey'escape'},
}
return scene

View File

@@ -1,67 +0,0 @@
local scene={}
local function _getCode()
local email=scene.widgetList.email:getText()
if not STRING.simpEmailCheck(email) then
MES.new('error',text.wrongEmail)
else
USER.email=email
NET.getCode(email)
end
end
local function _codeLogin()
local code=scene.widgetList.code:getText():upper()
if #code~=8 then
MES.new('error',text.wrongCode)
else
NET.codeLogin(USER.email,code)
end
end
local function _paste()
local t=love.system.getClipboardText()
if t then
t=STRING.trim(t)
if #t==8 and t:match("[0-9]+") then
scene.widgetList.code:setText(t)
return
end
end
MES.new('warn',text.wrongCode)
end
function scene.enter()
scene.widgetList.email:setText(USER.email or "")
scene.widgetList.code:clear()
end
function scene.keyDown(key,rep)
if key=='escape' and not rep then
SCN.back()
elseif key=='return' or key=='kpenter' then
if #scene.widgetList.code:getText():upper()==0 then
_getCode()
else
_codeLogin()
end
elseif key=='v' and love.keyboard.isDown('lctrl','rctrl') then
_paste()
else
return true
end
end
scene.widgetList={
WIDGET.newText{name='title', x=80, y=50,font=70,align='L'},
WIDGET.newButton{name='login_pw', x=1080,y=100,w=260,h=80,color='lY',code=function() SCN.swapTo('login_pw','swipeR') end},
WIDGET.newInputBox{name='email', x=380, y=200,w=626,h=60,limit=128},
WIDGET.newKey{name='send', x=640, y=330,w=300,h=80,font=40,code=_getCode},
WIDGET.newInputBox{name='code', x=380, y=400,w=626,h=60,regex="[0-9a-zA-Z]",limit=8},
WIDGET.newKey{name='verify', x=640, y=530,w=300,h=80,font=40,code=_codeLogin},
WIDGET.newKey{name='paste', x=850, y=530,w=80,font=40,fText=CHAR.icon.import,code=_paste},
WIDGET.newButton{name='back', x=1140,y=640,w=170,h=80,sound='back',font=60,fText=CHAR.icon.back,code=pressKey'escape'},
}
return scene

View File

@@ -1,44 +0,0 @@
local emailBox=WIDGET.newInputBox{name='email',x=380,y=200,w=500,h=60,limit=128}
local passwordBox=WIDGET.newInputBox{name='password',x=380,y=300,w=620,h=60,secret=true,regex="[ -~]",limit=64}
local showEmail=true
local function _login()
local email,password=emailBox:getText(),passwordBox:getText()
if not STRING.simpEmailCheck(email) then
MES.new('error',text.wrongEmail) return
elseif #password==0 then
MES.new('error',text.noPassword) return
end
NET.pwLogin(email,password)
end
local scene={}
function scene.enter()
showEmail=false
emailBox.secret=true
emailBox:setText(USER.email)
passwordBox:setText("")
end
function scene.keyDown(key,rep)
if rep then return true end
if key=='return' then
_login()
else
return true
end
end
scene.widgetList={
WIDGET.newText{name='title', x=80, y=50,font=70,align='L'},
WIDGET.newButton{name='login_mail',x=1080,y=100,w=260,h=80,color='lY',code=function() SCN.swapTo('login_mail','swipeL') end},
emailBox,
passwordBox,
WIDGET.newSwitch{name='showEmail', x=550, y=420,disp=function() return showEmail end,code=function() showEmail=not showEmail emailBox.secret=not showEmail end},
WIDGET.newKey{name='login', x=1140,y=540,w=170,h=80,font=40,code=pressKey'return'},
WIDGET.newButton{name='back', x=1140,y=640,w=170,h=80,sound='back',font=60,fText=CHAR.icon.back,code=backScene},
}
return scene

View File

@@ -76,7 +76,7 @@ function scene.keyDown(key,isRep)
end
elseif key=='a' then
if _testButton(3) then
NET.autoLogin()
NET.login(true)
end
elseif key=='z' then
if _testButton(4) then

View File

@@ -18,15 +18,13 @@ scene.widgetList={
WIDGET.newButton{name='league',x=640, y=180,w=350,h=120,font=40,color='D',code=goScene'net_league'},
WIDGET.newButton{name='ffa', x=640, y=360,w=350,h=120,font=40,color='D',code=function() MES.new('warn',text.notFinished)--[[NET.enterRoom({name='ffa'})]] end},
WIDGET.newButton{name='rooms', x=640, y=540,w=350,h=120,font=40,code=goScene'net_rooms'},
WIDGET.newButton{name='resetPW',x=680,y=40,w=180,h=60,color='dG',code=goScene'reset_password'},
WIDGET.newButton{name='logout',x=880, y=40,w=180, h=60,color='dR',
code=function()
if tryBack() then
print('logout')
USER.__data.uid=false
USER.__data.email=false
USER.__data.password=false
USER.__data.rToken=false
USER.__data.aToken=false
USER.__data.oToken=false
love.filesystem.remove('conf/user')
SCN.back()
end