diff --git a/.gitignore b/.gitignore index 8b3b73ff..609637bb 100644 --- a/.gitignore +++ b/.gitignore @@ -72,6 +72,7 @@ data/public/avatar/* !data/public/avatar/default.png data/config/* !data/config/.gitkeep +plugin/live2d/model/* http_locations.conf https_locations.conf diff --git a/deploy/entrypoint.sh b/deploy/entrypoint.sh index 627c75a5..96232007 100755 --- a/deploy/entrypoint.sh +++ b/deploy/entrypoint.sh @@ -48,7 +48,7 @@ fi cd $APP/dist if [ ! -z "$STATIC_CDN_HOST" ]; then - find . -name "*.*" -type f -exec sed -i "s/__STATIC_CDN_HOST__/\/$STATIC_CDN_HOST/g" {} \; + find . -name "*.*" -type f -exec sed -i "s/\/$STATIC_CDN_HOST/g" {} \; else find . -name "*.*" -type f -exec sed -i "s/__STATIC_CDN_HOST__\///g" {} \; fi diff --git a/deploy/nginx/nginx.conf b/deploy/nginx/nginx.conf index 81ff345b..b0f5ae7f 100644 --- a/deploy/nginx/nginx.conf +++ b/deploy/nginx/nginx.conf @@ -55,6 +55,18 @@ http { include https_locations.conf; } + + location /api/live2d { + root /plugin/live2d; + index index.html index.htm index.php; + } + location ~ \.php$ { + fastcgi_pass oj-php:9000; + fastcgi_index index.php; + fastcgi_param DOCUMENT_ROOT /plugin/live2d; + fastcgi_param SCRIPT_FILENAME /plugin/live2d$fastcgi_script_name; + include fastcgi.conf + } } diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..9f22af9c --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,15 @@ +version: "3" +services: + oj-rsync-master-dev: + image: registry.cn-hangzhou.aliyuncs.com/onlinejudge/oj_rsync + container_name: oj-rsync-master-dev + volumes: + - $PWD/data/test_case:/test_case:ro + - $PWD/data/rsync_master:/log + environment: + - RSYNC_MODE=master + - RSYNC_USER=ojrsync + - RSYNC_PASSWORD=CHANGE_THIS_PASSWORD + ports: + - "0.0.0.0:873:873" + diff --git a/judge/ide.py b/judge/ide.py index 0eb3e79c..85372a11 100644 --- a/judge/ide.py +++ b/judge/ide.py @@ -7,6 +7,7 @@ import requests from django.db import transaction from django.db.models import F from conf.models import JudgeServer +from conf.models import JudgeServer from options.options import SysOptions from utils.cache import cache from utils.constants import CacheKey diff --git a/plugin/live2d/add/index.php b/plugin/live2d/add/index.php new file mode 100644 index 00000000..82b4a035 --- /dev/null +++ b/plugin/live2d/add/index.php @@ -0,0 +1,33 @@ +get_list(); +$modelList = $modelList['models']; + +foreach ($modelList as $modelName) { + if (!is_array($modelName) && file_exists('../model/'.$modelName.'/textures.cache')) { + + $textures = $texturesNew = array(); + $modelTexturesList = $modelTextures->get_list($modelName); + $modelNameTextures = $modelTextures->get_textures($modelName); + if (is_array($modelTexturesList)) foreach ($modelTexturesList['textures'] as $v) $textures[] = str_replace('\/', '/', json_encode($v)); + if (is_array($modelNameTextures)) foreach ($modelNameTextures as $v) $texturesNew[] = str_replace('\/', '/', json_encode($v)); + + $texturesDiff = array_diff($texturesNew, $textures); + if (empty($textures)) continue; elseif (empty($texturesDiff)) { + echo '

'.$modelName.' / textures.cache / No Update.

'; + } else { + foreach (array_values(array_unique(array_merge($textures, $texturesNew))) as $v) $texturesMerge[] = json_decode($v, 1); + file_put_contents('../model/'.$modelName.'/textures.cache', str_replace('\/', '/', json_encode($texturesMerge))); + echo '

'.$modelName.' / textures.cache / Updated.

'; + } + + } + elseif (is_array($modelName)) continue; + elseif ($modelTextures->get_list($modelName)) echo '

'.$modelName.' / textures.cache / Created.

'; +} diff --git a/plugin/live2d/get/index.php b/plugin/live2d/get/index.php new file mode 100644 index 00000000..741c05b6 --- /dev/null +++ b/plugin/live2d/get/index.php @@ -0,0 +1,54 @@ +id_to_name($modelId); + +if (is_array($modelName)) { + $modelName = $modelTexturesId > 0 ? $modelName[$modelTexturesId-1] : $modelName[0]; + $json = json_decode(file_get_contents('../model/'.$modelName.'/index.json'), 1); +} else { + $json = json_decode(file_get_contents('../model/'.$modelName.'/index.json'), 1); + if ($modelTexturesId > 0) { + $modelTexturesName = $modelTextures->get_name($modelName, $modelTexturesId); + if (isset($modelTexturesName)) $json['textures'] = is_array($modelTexturesName) ? $modelTexturesName : array($modelTexturesName); + } +} + +$textures = json_encode($json['textures']); +$textures = str_replace('texture', '../model/'.$modelName.'/texture', $textures); +$textures = json_decode($textures, 1); +$json['textures'] = $textures; + +$json['model'] = '../model/'.$modelName.'/'.$json['model']; +if (isset($json['pose'])) $json['pose'] = '../model/'.$modelName.'/'.$json['pose']; +if (isset($json['physics'])) $json['physics'] = '../model/'.$modelName.'/'.$json['physics']; + +if (isset($json['motions'])) { + $motions = json_encode($json['motions']); + $motions = str_replace('sounds', '../model/'.$modelName.'/sounds', $motions); + $motions = str_replace('motions', '../model/'.$modelName.'/motions', $motions); + $motions = json_decode($motions, 1); + $json['motions'] = $motions; +} + +if (isset($json['expressions'])) { + $expressions = json_encode($json['expressions']); + $expressions = str_replace('expressions', '../model/'.$modelName.'/expressions', $expressions); + $expressions = json_decode($expressions, 1); + $json['expressions'] = $expressions; +} + +header("Content-type: application/json"); +echo $jsonCompatible->json_encode($json); diff --git a/plugin/live2d/model_list.json b/plugin/live2d/model_list.json new file mode 100644 index 00000000..1694a349 --- /dev/null +++ b/plugin/live2d/model_list.json @@ -0,0 +1,44 @@ +{ + "models": [ + "Potion-Maker/Pio", + "Potion-Maker/Tia", + "bilibili-live/22", + "bilibili-live/33", + [ + "ShizukuTalk/shizuku-48", + "ShizukuTalk/shizuku-pajama" + ], + [ + "HyperdimensionNeptunia/neptune_classic", + "HyperdimensionNeptunia/nepnep", + "HyperdimensionNeptunia/neptune_santa", + "HyperdimensionNeptunia/nepmaid", + "HyperdimensionNeptunia/nepswim", + "HyperdimensionNeptunia/noir_classic", + "HyperdimensionNeptunia/noir", + "HyperdimensionNeptunia/noir_santa", + "HyperdimensionNeptunia/noireswim", + "HyperdimensionNeptunia/blanc_classic", + "HyperdimensionNeptunia/blanc_normal", + "HyperdimensionNeptunia/blanc_swimwear", + "HyperdimensionNeptunia/vert_classic", + "HyperdimensionNeptunia/vert_normal", + "HyperdimensionNeptunia/vert_swimwear", + "HyperdimensionNeptunia/nepgear", + "HyperdimensionNeptunia/nepgear_extra", + "HyperdimensionNeptunia/nepgearswim", + "HyperdimensionNeptunia/histoire", + "HyperdimensionNeptunia/histoirenohover" + ], + "KantaiCollection/murakumo" + ], + "messages": [ + "来自 Potion Maker 的 Pio 酱 ~", + "来自 Potion Maker 的 Tia 酱 ~", + "来自 Bilibili Live 的 22 哦 ~", + "来自 Bilibili Live 的 33 的说", + "Shizuku Talk !这里是 Shizuku ~", + "Nep! Nep! 超次元游戏:海王星 系列", + "艦隊これくしょん / 叢雲(むらくも)" + ] +} \ No newline at end of file diff --git a/plugin/live2d/rand/index.php b/plugin/live2d/rand/index.php new file mode 100644 index 00000000..5d7f2e7b --- /dev/null +++ b/plugin/live2d/rand/index.php @@ -0,0 +1,23 @@ +get_list(); + +$modelRandNewId = true; +while ($modelRandNewId) { + $modelRandId = rand(0, count($modelList['models'])-1)+1; + $modelRandNewId = $modelRandId == $modelId ? true : false; +} + +header("Content-type: application/json"); +echo $jsonCompatible->json_encode(array('model' => array( + 'id' => $modelRandId, + 'name' => $modelList['models'][$modelRandId-1], + 'message' => $modelList['messages'][$modelRandId-1] +))); diff --git a/plugin/live2d/rand_textures/index.php b/plugin/live2d/rand_textures/index.php new file mode 100644 index 00000000..3123f01a --- /dev/null +++ b/plugin/live2d/rand_textures/index.php @@ -0,0 +1,35 @@ +id_to_name($modelId); +$modelTexturesList = is_array($modelName) ? array('textures' => $modelName) : $modelTextures->get_list($modelName); + +if (count($modelTexturesList['textures']) <= 1) { + $modelTexturesNewId = 1; +} else { + $modelTexturesGenNewId = true; + if ($modelTexturesId == 0) $modelTexturesId = 1; + while ($modelTexturesGenNewId) { + $modelTexturesNewId = rand(0, count($modelTexturesList['textures'])-1)+1; + $modelTexturesGenNewId = $modelTexturesNewId == $modelTexturesId ? true : false; + } +} + +header("Content-type: application/json"); +echo $jsonCompatible->json_encode(array('textures' => array( + 'id' => $modelTexturesNewId, + 'name' => $modelTexturesList['textures'][$modelTexturesNewId-1], + 'model' => is_array($modelName) ? $modelName[$modelTexturesNewId-1] : $modelName +))); diff --git a/plugin/live2d/switch/index.php b/plugin/live2d/switch/index.php new file mode 100644 index 00000000..5c3334de --- /dev/null +++ b/plugin/live2d/switch/index.php @@ -0,0 +1,19 @@ +get_list(); +$modelSwitchId = $modelId + 1; +if (!isset($modelList['models'][$modelSwitchId-1])) $modelSwitchId = 1; + +header("Content-type: application/json"); +echo $jsonCompatible->json_encode(array('model' => array( + 'id' => $modelSwitchId, + 'name' => $modelList['models'][$modelSwitchId-1], + 'message' => $modelList['messages'][$modelSwitchId-1] +))); diff --git a/plugin/live2d/switch_textures/index.php b/plugin/live2d/switch_textures/index.php new file mode 100644 index 00000000..371a0bd1 --- /dev/null +++ b/plugin/live2d/switch_textures/index.php @@ -0,0 +1,26 @@ +id_to_name($modelId); +$modelTexturesList = is_array($modelName) ? array('textures' => $modelName) : $modelTextures->get_list($modelName); +$modelTexturesNewId = $modelTexturesId == 0 ? 2 : $modelTexturesId + 1; +if (!isset($modelTexturesList['textures'][$modelTexturesNewId-1])) $modelTexturesNewId = 1; + +header("Content-type: application/json"); +echo $jsonCompatible->json_encode(array('textures' => array( + 'id' => $modelTexturesNewId, + 'name' => $modelTexturesList['textures'][$modelTexturesNewId-1], + 'model' => is_array($modelName) ? $modelName[$modelTexturesNewId-1] : $modelName +))); diff --git a/plugin/live2d/tools/jsonCompatible.php b/plugin/live2d/tools/jsonCompatible.php new file mode 100644 index 00000000..792bc38e --- /dev/null +++ b/plugin/live2d/tools/jsonCompatible.php @@ -0,0 +1,49 @@ +json_pretty_print($json, ' '); + } else return json_encode($json, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); + } + + protected function json_preg_replace($matchs) { + return iconv('UCS-2BE', 'UTF-8', pack('H4', $matchs[1])); + } + + protected function json_pretty_print($json, $indent = "\t") { + $result = ''; + $indentCount = 0; + $inString = false; + $len = strlen($json); + for ($c = 0; $c < $len; $c++) { + $char = $json[$c]; + if ($char === '{' || $char === '[') { + if (!$inString) { + $indentCount++; + if ($char === '[' && $json[$c+1] == "]") $result .= $char . PHP_EOL; + elseif ($char === '{' && $json[$c+1] == "}") $result .= $char . PHP_EOL; + else $result .= $char . PHP_EOL . str_repeat($indent, $indentCount); + } else $result .= $char; + } elseif ($char === '}' || $char === ']') { + if (!$inString) { + $indentCount--; + $result .= PHP_EOL . str_repeat($indent, $indentCount) . $char; + } else $result .= $char; + } elseif ($char === ',') { + if (!$inString) $result .= ',' . PHP_EOL . str_repeat($indent, $indentCount); + else $result .= $char; + } elseif ($char === ':') { + if (!$inString) $result .= ': '; + else $result .= $char; + } elseif ($char === '"') { + if (($c > 0 && $json[$c - 1] !== '\\') || ($c > 1 && $json[$c - 2].$json[$c - 1] === '\\\\')) $inString = !$inString; + $result .= $char; + } else { + $result .= $char; + } + } + return $result; + } +} diff --git a/plugin/live2d/tools/modelList.php b/plugin/live2d/tools/modelList.php new file mode 100644 index 00000000..f4082118 --- /dev/null +++ b/plugin/live2d/tools/modelList.php @@ -0,0 +1,21 @@ + $textures) : false; + } + + /* 获取材质列表 */ + function get_textures($modelName) { + if (file_exists('../model/'.$modelName.'/textures_order.json')) { // 读取材质组合规则 + $tmp = array(); foreach (json_decode(file_get_contents('../model/'.$modelName.'/textures_order.json'), 1) as $k => $v) { + $tmp2 = array(); foreach ($v as $textures_dir) { + $tmp3 = array(); foreach (glob('../model/'.$modelName.'/'.$textures_dir.'/*') as $n => $m) + $tmp3['merge'.$n] = str_replace('../model/'.$modelName.'/', '', $m); + $tmp2 = array_merge_recursive($tmp2, $tmp3); } + foreach ($tmp2 as $v4) $tmp4[$k][] = str_replace('\/', '/', json_encode($v4)); + $tmp = self::array_exhaustive($tmp, $tmp4[$k]); } + foreach ($tmp as $v) $textures[] = json_decode('['.$v.']', 1); return $textures; + } else { + foreach (glob('../model/'.$modelName.'/textures/*') as $v) + $textures[] = str_replace('../model/'.$modelName.'/', '', $v); + return empty($textures) ? null : $textures; + } + } + + /* 数组穷举合并 */ + function array_exhaustive($arr1, $arr2) { + foreach ($arr2 as $k => $v) { + if (empty($arr1)) $out[] = $v; + else foreach ($arr1 as $k2 => $v2) $out[] = str_replace('"["', '","', str_replace('"]"', '","', $v2.$v)); + } return $out; + } + +} diff --git a/plugin/live2d/tools/name-to-lower.php b/plugin/live2d/tools/name-to-lower.php new file mode 100644 index 00000000..0853e847 --- /dev/null +++ b/plugin/live2d/tools/name-to-lower.php @@ -0,0 +1,15 @@ + '.$new_name." ok. \n"; +} +/*-----------------------------------------------------------------*/