diff --git a/app/Http/Controllers/Api/ProjectController.php b/app/Http/Controllers/Api/ProjectController.php
index cffbba6a3..82878556b 100755
--- a/app/Http/Controllers/Api/ProjectController.php
+++ b/app/Http/Controllers/Api/ProjectController.php
@@ -22,6 +22,7 @@ use App\Models\WebSocketDialog;
use App\Module\Base;
use App\Module\BillExport;
use App\Module\BillMultipleExport;
+use App\Module\Doo;
use App\Module\TimeRange;
use Carbon\Carbon;
use Illuminate\Support\Arr;
@@ -2082,12 +2083,12 @@ class ProjectController extends AbstractController
if ($task_id === 0) {
$log->projectTask?->cancelAppend();
}
- $log->detail = Base::Lang($log->detail);
+ $log->detail = Doo::translate($log->detail);
$log->time = [
'ymd' => date(date("Y", $timestamp) == date("Y", Base::time()) ? "m-d" : "Y-m-d", $timestamp),
'hi' => date("h:i", $timestamp) ,
- 'week' => Base::Lang("周" . Base::getTimeWeek($timestamp)),
- 'segment' => Base::Lang(Base::getTimeDayeSegment($timestamp)),
+ 'week' => Doo::translate("周" . Base::getTimeWeek($timestamp)),
+ 'segment' => Doo::translate(Base::getTimeDayeSegment($timestamp)),
];
return $log;
});
diff --git a/app/Http/Controllers/Api/ReportController.php b/app/Http/Controllers/Api/ReportController.php
index db479bbb5..ec1e9c1de 100755
--- a/app/Http/Controllers/Api/ReportController.php
+++ b/app/Http/Controllers/Api/ReportController.php
@@ -9,6 +9,7 @@ use App\Models\Report;
use App\Models\ReportReceive;
use App\Models\User;
use App\Module\Base;
+use App\Module\Doo;
use App\Tasks\PushTask;
use Carbon\Carbon;
use Hhxsv5\LaravelS\Swoole\Task\Task;
@@ -306,7 +307,7 @@ class ReportController extends AbstractController
if ($complete_task->isNotEmpty()) {
foreach ($complete_task as $task) {
$complete_at = Carbon::parse($task->complete_at);
- $pre = $type == Report::WEEKLY ? ('[' . Base::Lang('周' . ['日', '一', '二', '三', '四', '五', '六'][$complete_at->dayOfWeek]) . '] ') : '';
+ $pre = $type == Report::WEEKLY ? ('[' . Doo::translate('周' . ['日', '一', '二', '三', '四', '五', '六'][$complete_at->dayOfWeek]) . '] ') : '';
$completeContent .= "
{$pre}[{$task->project->name}] {$task->name}";
}
} else {
@@ -327,7 +328,7 @@ class ReportController extends AbstractController
if ($unfinished_task->isNotEmpty()) {
foreach ($unfinished_task as $task) {
empty($task->end_at) || $end_at = Carbon::parse($task->end_at);
- $pre = (!empty($end_at) && $end_at->lt($now_dt)) ? '[' . Base::Lang('超期') . '] ' : '';
+ $pre = (!empty($end_at) && $end_at->lt($now_dt)) ? '[' . Doo::translate('超期') . '] ' : '';
$unfinishedContent .= "{$pre}[{$task->project->name}] {$task->name}";
}
} else {
@@ -341,12 +342,12 @@ class ReportController extends AbstractController
$title = $user->nickname . "的日报[" . $start_time->format("Y/m/d") . "]";
}
// 生成内容
- $content = '' . Base::Lang('已完成工作') . '
' .
+ $content = '' . Doo::translate('已完成工作') . '
' .
$completeContent . '
' .
- Base::Lang('未完成的工作') . '
' .
+ Doo::translate('未完成的工作') . '' .
$unfinishedContent . '
';
if ($type === Report::WEEKLY) {
- $content .= "" . Base::Lang("下周拟定计划") . "[" . $start_time->addWeek()->format("m/d") . "-" . $end_time->addWeek()->format("m/d") . "]
-
";
+ $content .= "" . Doo::translate("下周拟定计划") . "[" . $start_time->addWeek()->format("m/d") . "-" . $end_time->addWeek()->format("m/d") . "]
-
";
}
$data = [
"time" => $start_time->toDateTimeString(),
diff --git a/app/Http/Controllers/Api/UsersController.php b/app/Http/Controllers/Api/UsersController.php
index dc157a311..95a860f9c 100755
--- a/app/Http/Controllers/Api/UsersController.php
+++ b/app/Http/Controllers/Api/UsersController.php
@@ -19,6 +19,7 @@ use App\Models\WebSocketDialog;
use App\Models\WebSocketDialogMsg;
use App\Module\AgoraIO\AgoraTokenGenerator;
use App\Module\Base;
+use App\Module\Doo;
use Arr;
use Cache;
use Captcha;
@@ -135,8 +136,8 @@ class UsersController extends AbstractController
//
if (!Project::withTrashed()->whereUserid($user->userid)->wherePersonal(1)->exists()) {
Project::createProject([
- 'name' => Base::Lang('个人项目'),
- 'desc' => Base::Lang('注册时系统自动创建项目,你可以自由删除。'),
+ 'name' => Doo::translate('个人项目'),
+ 'desc' => Doo::translate('注册时系统自动创建项目,你可以自由删除。'),
'personal' => 1,
], $user->userid);
}
@@ -530,13 +531,13 @@ class UsersController extends AbstractController
return preg_match("/\(M\)$/", $item);
});
if ($dep) {
- $tags[] = preg_replace("/\(M\)$/", "", trim($dep[0])) . Base::Lang("负责人");
+ $tags[] = preg_replace("/\(M\)$/", "", trim($dep[0])) . Doo::translate("负责人");
}
if ($userInfo->isAdmin()) {
- $tags[] = Base::Lang("系统管理员");
+ $tags[] = Doo::translate("系统管理员");
}
if ($userInfo->isTemp()) {
- $tags[] = Base::Lang("临时帐号");
+ $tags[] = Doo::translate("临时帐号");
}
$userInfo->tags = $tags;
//
diff --git a/app/Http/Middleware/WebApi.php b/app/Http/Middleware/WebApi.php
index 77168c009..cc6083e53 100644
--- a/app/Http/Middleware/WebApi.php
+++ b/app/Http/Middleware/WebApi.php
@@ -4,6 +4,7 @@ namespace App\Http\Middleware;
@error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING);
+use App\Module\Doo;
use Closure;
use Request;
@@ -31,6 +32,7 @@ class WebApi
if (in_array(strtolower($APP_SCHEME), ['https', 'on', 'ssl', '1', 'true', 'yes'], true)) {
$request->setTrustedProxies([$request->getClientIp()], $request::HEADER_X_FORWARDED_PROTO);
}
+ Doo::init();
return $next($request);
}
diff --git a/app/Models/UserBot.php b/app/Models/UserBot.php
index 520b7bdfe..9444711fc 100644
--- a/app/Models/UserBot.php
+++ b/app/Models/UserBot.php
@@ -2,7 +2,7 @@
namespace App\Models;
-use App\Module\Base;
+use App\Module\Doo;
use App\Module\Extranet;
use Cache;
use Carbon\Carbon;
@@ -47,43 +47,43 @@ class UserBot extends AbstractModel
'check-in@bot.system' => [
[
'key' => 'checkin',
- 'label' => Base::Lang('我要签到')
+ 'label' => Doo::translate('我要签到')
], [
'key' => 'it',
- 'label' => Base::Lang('IT资讯')
+ 'label' => Doo::translate('IT资讯')
], [
'key' => '36ke',
- 'label' => Base::Lang('36氪')
+ 'label' => Doo::translate('36氪')
], [
'key' => '60s',
- 'label' => Base::Lang('60s读世界')
+ 'label' => Doo::translate('60s读世界')
], [
'key' => 'joke',
- 'label' => Base::Lang('开心笑话')
+ 'label' => Doo::translate('开心笑话')
], [
'key' => 'soup',
- 'label' => Base::Lang('心灵鸡汤')
+ 'label' => Doo::translate('心灵鸡汤')
]
],
'anon-msg@bot.system' => [
[
'key' => 'help',
- 'label' => Base::Lang('使用说明')
+ 'label' => Doo::translate('使用说明')
], [
'key' => 'privacy',
- 'label' => Base::Lang('隐私说明')
+ 'label' => Doo::translate('隐私说明')
],
],
'bot-manager@bot.system' => [
[
'key' => '/help',
- 'label' => Base::Lang('帮助指令')
+ 'label' => Doo::translate('帮助指令')
], [
'key' => '/api',
- 'label' => Base::Lang('Api接口文档')
+ 'label' => Doo::translate('Api接口文档')
], [
'key' => '/list',
- 'label' => Base::Lang('我的机器人')
+ 'label' => Doo::translate('我的机器人')
],
],
default => [],
diff --git a/app/Models/WebSocketDialog.php b/app/Models/WebSocketDialog.php
index 337934209..38be79c03 100644
--- a/app/Models/WebSocketDialog.php
+++ b/app/Models/WebSocketDialog.php
@@ -4,6 +4,7 @@ namespace App\Models;
use App\Exceptions\ApiException;
use App\Module\Base;
+use App\Module\Doo;
use App\Tasks\PushTask;
use Cache;
use Carbon\Carbon;
@@ -147,7 +148,7 @@ class WebSocketDialog extends AbstractModel
}
break;
case 'all':
- $this->name = Base::Lang('全体成员');
+ $this->name = Doo::translate('全体成员');
$this->all_group_mute = Base::settingFind('system', 'all_group_mute');
break;
}
@@ -181,7 +182,7 @@ class WebSocketDialog extends AbstractModel
&& $mention_id = intval($builder->clone()->whereMention(1)->orderByDesc('msg_id')->value('msg_id'))) {
$array[] = [
'msg_id' => $mention_id,
- 'label' => Base::Lang('@我的消息'),
+ 'label' => Doo::translate('@我的消息'),
];
}
// 最早一条未读消息
@@ -374,7 +375,7 @@ class WebSocketDialog extends AbstractModel
$name = \DB::table('project_tasks')->where('dialog_id', $this->id)->value('name');
break;
case 'all':
- $name = Base::Lang('全体成员');
+ $name = Doo::translate('全体成员');
break;
}
}
diff --git a/app/Module/Base.php b/app/Module/Base.php
index 3f2f86f71..9961a4682 100755
--- a/app/Module/Base.php
+++ b/app/Module/Base.php
@@ -1458,73 +1458,6 @@ class Base
}
}
- /**
- * 国际化(替换国际语言)
- * @param $val
- * @return mixed
- */
- public static function Lang($val)
- {
- $data = self::langData();
- if (isset($data[$val])) {
- return $data[$val] ?: $val;
- }
- foreach ($data as $key => $item) {
- if (str_contains($key, "(*)")) {
- $regex = str_replace("(*)", "~%~", $key);
- $regex = preg_quote($regex);
- $regex = str_replace("~%~", "(.*?)", $regex);
- $regex = "/^" . $regex . "$/";
- if (preg_match($regex, $val)) {
- $r = $item ?: $key;
- return preg_replace_callback($regex, function($m) use ($r) {
- $i = 0;
- foreach ($m as $v) {
- if ($i > 0) {
- $r = preg_replace("/\(\*\)/", $v, $r, 1);
- }
- $i++;
- }
- return $r;
- }, $val);
- }
- }
- }
- //
- $undefinedPath = base_path('language/undefined-api.txt');
- if (self::$undefinedLang === null) {
- self::$undefinedLang = [];
- if (file_exists($undefinedPath)) {
- self::$undefinedLang = explode("\n", file_get_contents($undefinedPath));
- self::$undefinedLang = array_values(array_filter(array_unique(self::$undefinedLang)));
- }
- }
- if (!in_array($val, self::$undefinedLang)) {
- self::$undefinedLang[] = $val;
- @file_put_contents(base_path('language/undefined-api.txt'), "$val\n", FILE_APPEND);
- }
- return $val;
- }
- private static $undefinedLang = null;
-
- /**
- * 加载语言数据
- * @return array
- */
- public static function langData()
- {
- global $_A;
- $language = trim(self::headerOrInput('language'));
- if (!isset($_A["__static_langdata_" . $language])) {
- $_A["__static_langdata_" . $language] = [];
- $langpath = public_path('language/api/' . $language . '.json');
- if (file_exists($langpath) && $data = Base::json2array(file_get_contents($langpath))) {
- $_A["__static_langdata_" . $language] = $data;
- }
- }
- return $_A["__static_langdata_" . $language];
- }
-
/**
* JSON返回
* @param $param
@@ -1552,7 +1485,7 @@ class Base
{
return [
'ret' => $ret,
- 'msg' => self::Lang($msg),
+ 'msg' => Doo::translate($msg),
'data' => $data
];
}
@@ -1568,7 +1501,7 @@ class Base
{
return [
'ret' => $ret,
- 'msg' => self::Lang($msg),
+ 'msg' => Doo::translate($msg),
'data' => $data
];
}
diff --git a/app/Module/Doo.php b/app/Module/Doo.php
new file mode 100644
index 000000000..ba826b26d
--- /dev/null
+++ b/app/Module/Doo.php
@@ -0,0 +1,170 @@
+initialize();
+ $doo->setWorkDir("/var/www");
+ $doo->setDefaultLanguage(Base::headerOrInput('language'));
+ $doo->setUserToken(Base::getToken());
+ self::$doo = $doo;
+ }
+ return self::$doo;
+ }
+
+ /**
+ * char转为字符串
+ * @param $text
+ * @return string
+ */
+ public static function string($text)
+ {
+ return FFI::string($text);
+ }
+
+ /**
+ * License
+ * @return array
+ */
+ public static function license()
+ {
+ $array = Base::json2array(self::string(self::init()->license()));
+
+ $ips = explode(",", $array['ip']);
+ $array['ip'] = [];
+ foreach ($ips as $ip) {
+ if (Base::is_ipv4($ip)) {
+ $array['ip'][] = $ip;
+ }
+ }
+
+ $domains = explode(",", $array['domain']);
+ $array['domain'] = [];
+ foreach ($domains as $domain) {
+ if (Base::is_domain($domain)) {
+ $array['domain'][] = $domain;
+ }
+ }
+
+ $emails = explode(",", $array['email']);
+ $array['email'] = [];
+ foreach ($emails as $email) {
+ if (Base::isEmail($email)) {
+ $array['email'][] = $email;
+ }
+ }
+
+ return $array;
+ }
+
+ /**
+ * 当前会员ID(来自请求的token)
+ * @return int
+ */
+ public static function userId()
+ {
+ return self::init()->userId();
+ }
+
+ /**
+ * token是否过期(来自请求的token)
+ * @return bool
+ */
+ public static function userExpired()
+ {
+ return Carbon::parse(self::string(self::init()->userExpiredAt()))->isBefore(Carbon::now());
+ }
+
+ /**
+ * 当前会员邮箱地址(来自请求的token)
+ * @return string
+ */
+ public static function userEmail()
+ {
+ return self::string(self::init()->userEmail());
+ }
+
+ /**
+ * 当前会员token(来自请求的token)
+ * @return string
+ */
+ public static function userToken()
+ {
+ return self::string(self::init()->userToken());
+ }
+
+ /**
+ * 生成token(编码token)
+ * @param $userid
+ * @param $email
+ * @param $encrypt
+ * @param int $days 有效时间(天)
+ * @return string
+ */
+ public static function tokenEncode($userid, $email, $encrypt, $days = 7)
+ {
+ return self::string(self::init()->tokenEncode($userid, $email, $encrypt, $days));
+ }
+
+ /**
+ * 解码token
+ * @param $token
+ * @return array
+ */
+ public static function tokenDecode($token)
+ {
+ $array = Base::json2array(self::string(self::init()->tokenDecode($token)));
+ $array['is_expired'] = Carbon::parse($array['expired_at'])->isBefore(Carbon::now());
+ return $array;
+ }
+
+
+ /**
+ * 翻译
+ * @param string $text
+ * @param string|null $type
+ * @return string
+ */
+ public static function translate($text, $type = null)
+ {
+ if ($type) {
+ $test = self::init()->translateSpecified($text, $type);
+ } else {
+ $test = self::init()->translate($text);
+ }
+ return self::string($test);
+ }
+}
diff --git a/app/Module/Lib/doo.h b/app/Module/Lib/doo.h
new file mode 100644
index 000000000..f5e9f49d4
--- /dev/null
+++ b/app/Module/Lib/doo.h
@@ -0,0 +1,93 @@
+/* Code generated by cmd/cgo; DO NOT EDIT. */
+
+/* package command-line-arguments */
+
+
+#line 1 "cgo-builtin-export-prolog"
+
+#include
+
+#ifndef GO_CGO_EXPORT_PROLOGUE_H
+#define GO_CGO_EXPORT_PROLOGUE_H
+
+#ifndef GO_CGO_GOSTRING_TYPEDEF
+typedef struct { const char *p; ptrdiff_t n; } _GoString_;
+#endif
+
+#endif
+
+/* Start of preamble from import "C" comments. */
+
+
+
+
+/* End of preamble from import "C" comments. */
+
+
+/* Start of boilerplate cgo prologue. */
+#line 1 "cgo-gcc-export-header-prolog"
+
+#ifndef GO_CGO_PROLOGUE_H
+#define GO_CGO_PROLOGUE_H
+
+typedef signed char GoInt8;
+typedef unsigned char GoUint8;
+typedef short GoInt16;
+typedef unsigned short GoUint16;
+typedef int GoInt32;
+typedef unsigned int GoUint32;
+typedef long long GoInt64;
+typedef unsigned long long GoUint64;
+typedef GoInt64 GoInt;
+typedef GoUint64 GoUint;
+typedef size_t GoUintptr;
+typedef float GoFloat32;
+typedef double GoFloat64;
+#ifdef _MSC_VER
+#include
+typedef _Fcomplex GoComplex64;
+typedef _Dcomplex GoComplex128;
+#else
+typedef float _Complex GoComplex64;
+typedef double _Complex GoComplex128;
+#endif
+
+/*
+ static assertion to make sure the file is being used on architecture
+ at least with matching size of GoInt.
+*/
+typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1];
+
+#ifndef GO_CGO_GOSTRING_TYPEDEF
+typedef _GoString_ GoString;
+#endif
+typedef void *GoMap;
+typedef void *GoChan;
+typedef struct { void *t; void *v; } GoInterface;
+typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;
+
+#endif
+
+/* End of boilerplate cgo prologue. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void initialize();
+extern void setWorkDir(char* val);
+extern void setDefaultLanguage(char* val);
+extern void setUserToken(char* token);
+extern char* license();
+extern int userId();
+extern char* userExpiredAt();
+extern char* userEmail();
+extern char* userToken();
+extern char* tokenEncode(int userid, char* email, char* encrypt, int days);
+extern char* tokenDecode(char* token);
+extern char* translate(char* text);
+extern char* translateSpecified(char* text, char* langType);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/app/Module/Lib/doo.so b/app/Module/Lib/doo.so
new file mode 100644
index 000000000..537e9ce3e
Binary files /dev/null and b/app/Module/Lib/doo.so differ
diff --git a/docker-compose.yml b/docker-compose.yml
index 0e11ff1fc..7c530ec6e 100755
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -3,7 +3,7 @@ version: '3'
services:
php:
container_name: "dootask-php-${APP_ID}"
- image: "kuaifan/php:swoole-8.0.rc2"
+ image: "kuaifan/php:swoole-8.0.rc3"
shm_size: "1024m"
volumes:
- ./docker/crontab/crontab.conf:/etc/supervisor/conf.d/crontab.conf