This commit is contained in:
hellcat 2025-11-12 17:57:30 +08:00
commit ac91e1fbe4
22744 changed files with 3791757 additions and 0 deletions

18
laravel/.editorconfig Normal file
View File

@ -0,0 +1,18 @@
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
[*.{yml,yaml}]
indent_size = 2
[docker-compose.yml]
indent_size = 4

66
laravel/.env.example Normal file
View File

@ -0,0 +1,66 @@
APP_NAME=Laravel
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_TIMEZONE=UTC
APP_URL=http://localhost
APP_LOCALE=en
APP_FALLBACK_LOCALE=en
APP_FAKER_LOCALE=en_US
APP_MAINTENANCE_DRIVER=file
# APP_MAINTENANCE_STORE=database
PHP_CLI_SERVER_WORKERS=4
BCRYPT_ROUNDS=12
LOG_CHANNEL=stack
LOG_STACK=single
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
DB_CONNECTION=sqlite
# DB_HOST=127.0.0.1
# DB_PORT=3306
# DB_DATABASE=laravel
# DB_USERNAME=root
# DB_PASSWORD=
SESSION_DRIVER=database
SESSION_LIFETIME=120
SESSION_ENCRYPT=false
SESSION_PATH=/
SESSION_DOMAIN=null
BROADCAST_CONNECTION=log
FILESYSTEM_DISK=local
QUEUE_CONNECTION=database
CACHE_STORE=database
CACHE_PREFIX=
MEMCACHED_HOST=127.0.0.1
REDIS_CLIENT=phpredis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_MAILER=log
MAIL_SCHEME=null
MAIL_HOST=127.0.0.1
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_FROM_ADDRESS="hello@example.com"
MAIL_FROM_NAME="${APP_NAME}"
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false
VITE_APP_NAME="${APP_NAME}"

1
laravel/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
.env

22
laravel/README.md Executable file
View File

@ -0,0 +1,22 @@
//// 原
$oResult = make("xxx");
$aResult = aa();
if (Flow::isFailResult($aResult)) {
return $oResult->fail()->fetch();
}
return $oResult->done();
//// 新
$oResult = makeR("xxx");
$oResult = aa();
if ($oResult->isFail()) {
return $oRsult->fetch();
}

View File

@ -0,0 +1,204 @@
<?php
namespace App\Http\Controllers\Api;
use App\Services\TomTool\Flow;
use App\Services\TomTool\HttpV2;
use App\Services\TomTool\Telegram\Slave as TeleSlave;
use App\Services\TomTool\ThrowableHandler;
class ArticleController
{
public $sCmd = '';
public $sValue = '';
public $sArticleCode = '';
public $sSiteCode = '';
public $sKey = '';
public $aConfig = [];
public $aArg = [];
public $sDate = '';
public $aNewPath = [];
public function receiveSchema()
{
$oFlow = Flow::start("receiveSachema");
try {
$sArg = file_get_contents('php://input');
$aArg = json_decode($sArg, true);
$this->aArg = $aArg;
$this->sDate = $aArg["date"] ?? '';
$this->sCmd = $aArg["cmd"] ?? '';
$this->sValue = $aArg["value"] ?? '';
$this->sArticleCode = $aArg["article_code"] ?? '';
$this->sSiteCode = $aArg["site_code"] ?? '';
$this->sKey = $aArg["key"] ?? '';
$this->aConfig = $aArg["config"] ?? '';
if ($this->sCmd == "new") {
$this->cmd_new();
} else {
$sMsg = "未找到cmd的对应处理".$this->sCmd;
echo $sMsg;
throw new \Exception($sMsg);
}
$this->_npmBuild();
$arr["aNewPath"] = $this->aNewPath;
echo json_encode($oFlow->setDataA($arr)->done()->getResult());
exit;
} catch (\Throwable $e) {
TeleSlave::warn()->enableSlaveQueue(false)->send($e->getMessage());
echo json_encode($oFlow->fail($e->getMessage())->getResult());
exit;
}
}
private function _npmBuild()
{
$sVuePathNode = $_ENV['vue_path_node'];
$sVuePath = base_path();
$sVuePath = dirname($sVuePath);
$sVuePath .= "/vuepress";
$sCmd = "cd {$sVuePath} && {$sVuePathNode} ./node_modules/.bin/vuepress build docs";
exec($sCmd . " 2>&1", $output, $returnVar);
$logFile = $sVuePath . "/build.log";
file_put_contents($logFile, implode("\n", $output) . "\n", FILE_APPEND);
if ($returnVar === 0) {
// echo " - VuePress 构建成功!静态文件已生成在 docs/.vuepress/dist\n";
} else {
$sMsg = "VuePress构建失败请查看日志: ".json_encode($output);
throw new \Exception($sMsg);
}
}
public function cmd_new()
{
$aCategory = $this->aConfig["category"] ?? ["⚠️ 未得到category"];
$aTag = $this->aConfig["tag"] ?? ["⚠️ 未得到tag"];
$sTitle = $this->aArg["article"]["title"] ?? "⚠️ 未得到title";
$sContent = $this->aArg["article"]["content"] ?? "⚠️ 未得到content";
$sEnter = "
";
list(, $iCode) = explode("-", $this->sArticleCode);
foreach ($aCategory as $sCategoryRow) {
$sHead = "---";
$sHead .= $sEnter;
$sHead .= "title: ".$sTitle;
$sHead .= $sEnter;
$sHead .= "tags: ";
$sHead .= $sEnter;
foreach ($aTag as $sTagRow){
$sHead .= " - ".$sTagRow;
$sHead .= $sEnter;
}
$sHead .= "createTime: ".$this->sDate;
$sHead .= $sEnter;
$sTmp = "/{$sCategoryRow}/".$iCode."/";
$this->aNewPath[] = $sTitle." -> new https://".$_ENV["APP_URL"].$sTmp;
$sHead .= "permalink: ".$sTmp;
$sHead .= $sEnter;
$sHead .= "---";
$sArticleFull = $sHead;
$sArticleFull .= $sContent;
$sFileDir = "../../vuepress/docs/{$sCategoryRow}/";
$sFileName = $this->sArticleCode.".md";
$sFilePath = $sFileDir.$sFileName;
if (!file_exists($sFileDir)) {
if (mkdir($sFileDir, 0777, true)) {
// $oFlow->step("文件夹创建成功:$sFileDir\n");
} else {
$sMsg = "创建失败,请检查权限。\n";
echo $sMsg;
throw new \Exception($sMsg);
}
}
$fileHandle = fopen($sFilePath, 'w');
if ($fileHandle === false) {
$sMsg = "错误:无法打开或创建文件 $sFilePath。";
echo $sMsg;
throw new \Exception($sMsg);
} else {
fwrite($fileHandle, $sArticleFull);
fclose($fileHandle);
}
}
}
}
//---
//title: 自定义组件
//tags:
// - 预览
// - 组件
//createTime: 2025/10/19 17:47:57
//permalink: /demo/zzyg5nqpwh/
//---
//array(8) {
// ["site_code"]=>
// string(4) "ttcp"
// ["cmd"]=>
// string(3) "new"
// ["value"]=>
// string(0) ""
// ["date"]=>
// string(19) "2025-11-09 17:30:33"
// ["key"]=>
// string(28) "|jccp_a|ttcp|20251109173033|"
// ["article_code"]=>
// string(24) "ffq_tg_a::20251105175210"
// ["config"]=>
// array(2) {
// ["category"]=>
// array(2) {
// [0]=>
// string(12) "每日测速"
// [1]=>
// string(6) "测评"
// }
// ["tag"]=>
// array(2) {
// [0]=>
// string(2) "xx"
// [1]=>
// string(2) "cc"
// }
// }
// ["article"]=>
// array(2) {
// ["title"]=>
// string(37) "CPP Zone 机场第6次测评 & 测速"
// ["content"]=>
// string(2897) "CPP Zone"
// }
//}

View File

@ -0,0 +1,153 @@
<?php
declare(strict_types=1);
namespace App\Http\Controllers\Api\Tg;
//use App\Models\Article;
use App\Services\TomTool\Http;
use App\Services\Tg\Http as TGHttp;
use App\Models\Hook as ModelHook;
use App\Services\TomTool\ThrowableHandler;
//use App\Services\TomTool\TelegramVdb;
use App\Services\TomTool\Telegram\Slave as TelegramSlave;
final class HookController
{
private $sCustomText = '';
public function cmd_ffq_article()
{
$sUpdate = file_get_contents("php://input");
$aUpdate = json_decode($sUpdate, true);
$sText = &$aUpdate["message"]["text"] ?? "没有text";
if (!str_starts_with($sText, '/')) {
// $this->sCustomCmd = "article";
// $this->sCustomFunc = "cache";
// $this->aCustomOption[1] = "ffq";
$this->sCustomText = "/article#cache__ffq_tg"." ".$sText;
}
return $this->cmd();
}
public function cmd()
{
try {
$oTGHttp = new TGHttp();
$oTGHttp->sApiToken = env('telegram_token');
$oTGHttp->sApiChatId = env('telegram_chatid');
$sUpdate = file_get_contents("php://input");
$aUpdate = json_decode($sUpdate, true);
// @file_put_contents('/www/_tg/bot_log.txt', json_encode($aUpdate, JSON_PRETTY_PRINT));
$aData['chatId'] = (string) $aUpdate["message"]["chat"]["id"];
$aData['fromId'] = (string) $aUpdate["message"]["from"]["id"];
if (!isset($aUpdate["message"]["text"])) {
throw new \Exception(json_encode($aUpdate));
}
if ($this->sCustomText) {
$sText = $this->sCustomText;
} else {
$sText = &$aUpdate["message"]["text"] ?? "没有text";
}
// hook优先
// 非is_hook并且首字符非/
if ((!isset($aUpdate["is_hook"]) || $aUpdate["is_hook"] == false) && substr($sText, 0, 1) !== "/") {
$sHookKey = ModelHook::where("tg_user_id", $aData["fromId"])->first()?->key;
if ($sHookKey) {
if ($sText == "run") {
$sText = $sHookKey;
} else {
$sText = $sHookKey.$sText;
}
$aUpdate["is_hook"] = true;
}
}
@$aArg = explode(" ", $sText) ?? [];
@$aOption = explode("__", $aArg[0]) ?? [];
$sCmd = $this->cleanCmd($aOption[0]);
// 大于3个说明是hook或dove之类
$aCmd = explode("#", $sCmd);
// if (count($aCmd) >= 3) {
// $sHook = $aCmd[0];
// $sClass = $sHook;
// $sFunc = "go";
// } else {
$sClass = $aCmd[0] ?? false;
$sFunc = $aCmd[1] ?? false;
// }
if (strpos($sClass, "dove$") !== false) {
$sClass = "dove";
$sFunc = "go";
}
$sUClass = ucfirst($sClass);
$sUFunc = ucfirst($sFunc);
unset($aOption[0]);
unset($aArg[0]);
$aParams = [];
$aParams['aOption'] = $aOption;
$aParams['aArg'] = $aArg;
$sClassPath = "App\\Services\\Tg\\Hook\\Mod\\".$sClass;
$sUClassPath = "App\\Services\\Tg\\Hook\\Mod\\".$sUClass;
$oInstans = new $sUClassPath($aUpdate);
$r = $oInstans->$sFunc($aParams, $aUpdate);
$oTGHttp->send($r, $aUpdate);
echo $r;
} catch (\Throwable $e) {
$aDataTg = ThrowableHandler::make($e)->enableTrace()->fetch();
// TelegramVdb::make()->sData($aDataTg)->save();
TelegramSlave::fail()->setMsgA($aDataTg)->send();
$aDataCmd = $aDataTg;
$sDataCmd = json_encode($aDataCmd, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
$sDataCmd = str_replace("\\n", "<br>", $sDataCmd);
echo $sDataCmd;
exit;
// old
// $sMessage = "错误(文件: " . $e->getFile() . ",行: " . $e->getLine() . ": " . $e->getMessage();
// $oTGHttp->send($sMessage, $sUpdate);
// //Http::response(200, 'error'); 注释的
// old end
}
}
private function cleanCmd($input) {
$input = str_replace('\\', '', $input);
$input = str_replace('/', '', $input);
return $input;
}
}

View File

@ -0,0 +1,22 @@
<?php
namespace App\Http\Controllers;
//use Illuminate\Http\Request;
//use App\Models\ArticleList;
//use App\Services\Time;
//use voku\helper\AntiXSS;
//use App\Models\Tags;
//use App\Services\TomTool\Http;
class HelloController
{
public function index()
{
echo "hello";
exit;
}
}

7
laravel/app/Http/Kernel.php Executable file
View File

@ -0,0 +1,7 @@
<?php
protected $routeMiddleware = [
// 其他中间件...
// 'test' => \App\Http\Middleware\Test::class,
];
?>

View File

@ -0,0 +1,21 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
//use voku\helper\AntiXSS;
class Test
{
public function handle(Request $request, Closure $next): Response
{
$sSearch = request('search');
// echo $sSearch;exit;
return $next($request);
}
}

View File

@ -0,0 +1,51 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class DogOption extends Model
{
protected $table = 'dog_option';
public $timestamps = false;
public static function _hit($sDogName, $k)
{
$v = self::where("dog_name", $sDogName)->where("k", $k)->first()?->v;
// tomd($sDogName);
return $v;
}
public static function _list($sDogName)
{
$oSelf = self::where("dog_name", $sDogName)->get();
return self::_filterList($oSelf);
}
// public static function _limit($sDogName, $iSkip, $iTake)
// {
// $oSelf = self::where("dog_name", $sDogName)->skip($iSkip)->take($iTake)->get();
//
// return self::__filterList($oSelf);
// }
public static function _filter($oOption)
{
$arr = [];
$arr[$oOption->dog_name."#".$oOption->k] = $oOption->v;
return $arr;
}
public static function _filterList($oOption)
{
$arr = [];
foreach ($oOption as $oOptionRow) {
$arr[] = self::_filter($oOptionRow);
}
return $arr;
}
}

View File

@ -0,0 +1,15 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class HttpQueue extends Model
{
protected $table = 'http_queue';
public $timestamps = false;
}

19
laravel/app/Models/Me.php Executable file
View File

@ -0,0 +1,19 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Me extends Model
{
protected $table = 'me';
public $timestamps = false;
protected $fillable = [
'rag',
'class',
];
// public static function
}

47
laravel/app/Models/Option.php Executable file
View File

@ -0,0 +1,47 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Option extends Model
{
protected $table = 'option';
public $timestamps = false;
protected $primaryKey = 'k';
public $incrementing = false;
protected $keyType = 'string';
public static function _hit($k)
{
$v = self::where("k", $k)->first()?->v;
return $v;
}
public static function _list()
{
$oSelf = self::get();
return self::_filterList($oSelf);
}
public static function _filter($oOption)
{
$arr = [];
$arr[$oOption->k] = $oOption->v;
return $arr;
}
public static function _filterList($oOption)
{
$arr = [];
foreach ($oOption as $oOptionRow) {
$arr[] = self::_filter($oOptionRow);
}
return $arr;
}
}

View File

@ -0,0 +1,24 @@
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*/
public function register(): void
{
//
}
/**
* Bootstrap any application services.
*/
public function boot(): void
{
//
}
}

View File

@ -0,0 +1,59 @@
<?php
declare(strict_types=1);
namespace App\Services;
use App\Services\Cron\HttpQueue as CronHttpQueue;
final class Cron
{
public bool $bIsTest = false;
public ?int $iTestH = null;
public ?int $iTestI = null;
public ?int $iTestS = null;
public function run(): void
{
$h = (int) date("H");
$i = (int) date("i");
$s = (int) date("s");
if ($this->bIsTest) {
$h = (int) ($this->iTestH ?? $h);
$i = (int) ($this->iTestI ?? $i);
$s = (int) ($this->iTestS ?? $s);
}
if ($i % 5 === 0) {
CronHttpQueue::pop();
}
if ($i === 0) {
// ReportSender::handle();
}
}
public function setTestH(int $h): void
{
$this->enableTestMode();
$this->iTestH = $h;
}
public function setTestI(int $i): void
{
$this->enableTestMode();
$this->iTestI = $i;
}
public function setTestS(int $s): void
{
$this->enableTestMode();
$this->iTestS = $s;
}
public function enableTestMode(bool $enable = true): void
{
$this->bIsTest = $enable;
}
}

View File

@ -0,0 +1,79 @@
<?php
declare(strict_types=1);
namespace App\Services\Cron;
//use App\Services\Cron;
use App\Models\HttpQueue as ModelHttpQueue;
use App\Services\TomTool\Telegram\Master as TelegramMaster;
use App\Services\TomTool\Telegram\Slave as TelegramSlave;
use App\Services\TomTool\HttpV2;
use Telegram\Bot\Api;
//use Telegram\Bot\Exceptions\TelegramSDKException;
use Telegram\Bot\Exceptions\TelegramSDKException;
use Telegram\Bot\Exceptions\TelegramResponse;
final class HttpQueue
{
public static function pop()
{
echo "\nhttpQueue::pop - 开始\n";
$oHttpQueue = ModelHttpQueue::where("status", 1)->get();
foreach ($oHttpQueue as $oHttpQueueRow) {
$aArg = json_decode($oHttpQueueRow->arg, true);
$sBotCode = $aArg["sBotCode"] ?? '';
$sChatCode = $aArg["sChatCode"] ?? '';
$sBotToken = $aArg["sBotToken"] ?? '';
$iChatId = $aArg["iChatId"] ?? 0;
$sMsg = $aArg["sMsg"] ?? '';
$enableMaster = $aArg["enableMaster"] ?? null;
if ($enableMaster) {
$oTgSlave = TelegramSlave::start()
->enableMaster(true)
->enableAsync(false)
->enableSlaveQueue(false)
->setBotCode($sBotCode)
->setChatCode($sChatCode)
->setBotToken($sBotToken)
->setChatId($iChatId)
->setMsgS($sMsg)
->send();
if ($oTgSlave->isFail()) {
echo "失败从telegram_local发送到master失败\n";
var_dump($oTgSlave->getResult());
continue;
}
echo "发送到master成功";
} else { // 直接发送到tg必须有token和id
$oTgSlave = TelegramSlave::start()
->enableMaster(false)
->setBotCode($sBotCode)
->setChatCode($sChatCode)
->setBotToken($sBotToken)
->setChatId($iChatId)
->setMsgS($sMsg)
->send();
if ($oTgSlave->isFail()) {
echo "失败从telegram_local发送到tg失败\n";
var_dump($oTgSlave->getResult());
continue;
}
echo "发送到tg成功";
}
$oHttpQueueRow->delete();
}
}
}

View File

@ -0,0 +1,55 @@
<?php
declare(strict_types=1);
namespace App\Services;
use App\Models\HttpQueue as ModelHttpQueue;
use App\Services\TomTool\Flow;
final class HttpQueue
{
public $sName;
public $aArg = [];
public $sUrl;
public static function start(string $sName = ''): self
{
$oInstance = new self();
$oInstance->sName = $sName;
return $oInstance;
}
public function url($sUrl)
{
$this->sUrl = $sUrl;
return $this;
}
public function arg($aArg)
{
$this->aArg = $aArg;
return $this;
}
public function save(): Flow
{
$oResult = Flow::start("httpQueue");
$oModelHttpQueue = new ModelHttpQueue();
$oModelHttpQueue->name = $this->sName;
$oModelHttpQueue->url = $this->sUrl;
$oModelHttpQueue->arg = json_encode($this->aArg, JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR);
$r = $oModelHttpQueue->save();
if (!$r) {
return $oResult->fail("进入队列失败");
}
return $oResult->done("成功");
}
}

View File

@ -0,0 +1,66 @@
<?php
declare(strict_types=1);
namespace App\Services\OpenApi;
use Illuminate\Http\Request;
//use App\Services\TomTool\TelegramV2;
use App\Services\TomTool\Flow;
use App\Services\TomTool\Telegram\Master as TeleMaster;
//use App\Services\TomTool\Telegram\Slave as TeleSlave;
use Telegram\Bot\Api;
use Telegram\Bot\Exceptions\TelegramSDKException;
final class Telegram
{
public function post()
{
$oFlow = Flow::make("master::tgpost");
$sArg = file_get_contents('php://input');
$aArg = json_decode($sArg, true);
$sBotCode = $aArg["sBotCode"] ?? '';
$sChatCode = $aArg["sChatCode"] ?? '';
$sBotToken = $aArg["sBotToken"] ?? '';
$iChatId = (int) ($aArg["iChatId"] ?? 0);
$enableMasterQueue = $aArg["enableMasterQueue"] ?? false; // 用不着了
$sMsg = $aArg["sMsg"] ?? '';
$r = TeleMaster::start()
->setBotCode($sBotCode)
->setChatCode($sChatCode)
->setBotToken($sBotToken)
->setChatId($iChatId)
->send($sMsg);
return $oFlow->done();
}
public function queueAdd_meiyong(Request $oRequest)
{
$oResult = Flow::make("master::queueAdd");
$sArg = $oRequest->post("arg");
if (!$sArg) {
return $oResult->fail("没有arg");
}
$oHttpQueue = new ModelHttpQueue();
$oHttpQueue->name = "telegram";
$oHttpQueue->arg = $sArg;
$r = $oHttpQueue->save();
if (!$r) {
return $oResult->fail("进入队列失败");
}
return $oResult->done();
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,57 @@
<?php
namespace App\Services\Tg\Hook\Mod;
//use App\Services\TomTool\Http;
//use App\Models\Article as ModelArticle;
use App\Services\TomTool\Http;
use App\Services\Tg\Http as TGHttp;
class Base {
public function __construct() {
$this->oHttp = new Http();
$this->oTGHttp = new TGHttp();
// $this->oTGHttp->sApiToken = env("telegram_token");
// $this->oTGHttp->sApiChatId = env("telegram_chatid");
}
public function toJson($aData)
{
return json_encode($aData, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
}
public function eachSendTg($aData)
{
foreach ($aData as $row) {
$this->oTGHttp->sendToTG(json_encode($row, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
}
$this->oHttp::response(200, 'ok');
}
// protected function cmdGood($sCmd) {
//
// $sCmdNew = "";
// switch ($sCmd) {
// case "user":
// $sCmdNew = "user_name";
// break;
// case "project":
// $sCmdNew = "project_name";
// break;
// case "code":
// $sCmdNew = "sale_code";
// break;
// case "condition":
// $sCmdNew = "cron_condition";
// break;
// default:
// $sCmdNew = $sCmd;
// break;
// }
//
// return $sCmdNew;
//
// }
}

View File

@ -0,0 +1,66 @@
<?php
namespace App\Services\Tg\Hook\Mod;
use App\Services\TomTool\Http;
use App\Services\Cron as ServicesCron;
use App\Services\Cron\HttpQueue as CronHttpQueue;
class Cron extends Base {
public function httpQueuePop()
{
$r = CronHttpQueue::pop();
return $r;
}
public function test($aParam)
{
$sType = $aParam["aOption"][1] ?? "i";
$sValue = $aParam["aArg"][1] ?? 5;
if (!$sType) {
return "需要his之一";
}
if (!$sValue) {
return "需要value";
}
if ($sValue == "?") {
return "#test__[his] [value]";
}
$oServicesCron = new ServicesCron();
if ($sType == "h") {
$oServicesCron->setTestH($sValue);
} else if ($sType == "i") {
$oServicesCron->setTestI($sValue);
} else if ($sType == "s") {
$oServicesCron->setTestS($sValue);
}
return $oServicesCron->run();
}
public function testOld($aParam)
{
$sType = $aParam["aArg"][1] ?? false;
$sValue = $aParam["aArg"][2] ?? false;
$oHttp = new Http();
$oHttp->sMethod = "get";
$oHttp->bIsJson = true;
$oHttp->sToUrl = env("APP_URL")."/cron";
if ($sType && $sValue) {
$oHttp->aData = ["k" => $sType, "v" => $sValue];
}
$r = $oHttp->send();
return $r;
}
}

View File

@ -0,0 +1,44 @@
<?php
namespace App\Services\Tg\Hook\Mod;
//use App\Models\Article as ModelArticle;
class Db extends Base {
public function sql($aParam)
{
if ($aParam["aArg"][1] == "?") {
return "/db#sql {value}";
}
$aValue = $aParam["aArg"];
$sValue = implode(" ", $aValue);
$r = \DB::statement($sValue);
return $r;
}
public function me()
{
$str = "
添加字段ALTER TABLE `ship` ADD `good_test` TEXT DEFAULT NULL AFTER `api_huodong`
删除字段ALTER TABLE `ship` DROP COLUMN `good_test`
修改字段ALTER TABLE `ship` MODIFY `good_test` VARCHAR(255) DEFAULT NULL
";
return $str;
}
public function showCreateTable($aParam)
{
$sValue = $aParam["aArg"][1] ?? false;
$columns = \DB::select("SHOW CREATE TABLE `{$sValue}`");
return $columns[0]->{"Create Table"};
}
}

View File

@ -0,0 +1,69 @@
<?php
namespace App\Services\Tg\Hook\Mod;
use App\Models\BladeJctj as ModelBladeJctj;
use App\Services\Tg\Hook\Dog;
use App\Services\TomTool\Flow;
use App\Services\TomTool\HttpV2;
use App\Services\Article;
use App\Services\SlaveMap;
use App\Services\ArticleCmd;
use App\Services\TomTool\Telegram\Slave as TeleSlave;
class Dev extends Base {
private $oDog;
public function __construct($aUpdate)
{
$this->oDog = new Dog(new ModelBladeJctj());
$this->oDog->_setDogName("jctj"); // 必须me用正常就是类名只不过后期没准改名所以就这里写死
$this->oDog->_setPrimaryKey("id"); // 可选默认id
$this->oDog->_setStrField(["content"]); // 可选,指定长文本字段
}
public function __call($sName, $aArg)
{
return $this->oDog->$sName($aArg[0]);
}
public function test2()
{
// $r = TeleSlave::warn()->enableSlaveQueue(false)->send("xxxx");
$r = TeleSlave::warn()->enableSlaveQueue(true)->send("mmmmmmm");
return $r->getResult();
}
public function test1()
{
// $oArticleCmd = new ArticleCmd("ffq_tg::20251028163931");
// $r = ArticleCmd::make("ffq_tg::20251028163931")->reset();
// $r = ArticleCmd::start("ffq_tg::20251028163931")->setSiteGroupCode("cp-a")->setSiteCode("ttcp")->save("zzz", "xxx");
// $r = ArticleCmd::start("ffq_tg::20251028163931")->setSiteGroupCode("cp-a")->set("qusi", "buyao");
$r = ArticleCmd::start("ffq_tg::20251028163931")->moveToLog("|cp-a|ttcp|20251101182406|");
// $r = ArticleCmd::start("ffq_tg::20251028163931")->setCmd("ooo")->reset();
// $r = ArticleCmd::start("ffq_tg::20251028163931")->clear();
// $r = ArticleCmd::start("ffq_tg::20251028163931")->set("aaa", 111);
tomd($r, 1);
exit;
// $oArticle = new Article();
$r = SlaveMap::siteTreeByArticleGroup("ffq_tg_a");
tomd($r, 1);
exit;
$oArticle = new Article();
$r = $oArticle->syncChange("ffq_tg::20251029190433", "new");
tomd($r, 1);
}
}

View File

@ -0,0 +1,49 @@
<?php
namespace App\Services\Tg\Hook\Mod;
use App\Models\Option as ModelOption;
use App\Services\Tg\Hook\Dog;
class Option extends Base {
private $oDog;
public function __construct($aUpdate = [])
{
$this->oDog = new Dog(new ModelOption());
$this->oDog->_setPrimaryKey("k"); // 可选默认id
$this->oDog->_setDogName("option"); // 必须
}
public function __call($sName, $aArg)
{
return $this->oDog->$sName($aArg[0]);
}
// public function Pause($aParam)
// {
// $v = $aParam['aArg'][1];
//
// // 获取第一个匹配的选项
// $oOption = ModelOption::where("type", "pause")->first();
//
// // 检查是否找到了选项
// if ($oOption) {
// $oOption->value = $v;
//
// // 保存并返回结果
// return json_encode($oOption->save());
// }
//
// // 如果没有找到选项,返回一个错误信息
// return json_encode(['error' => 'Option not found']);
// }
//
// public function List()
// {
// $aOptionList = ModelOption::all()->toArray();
//
// return json_encode($aOptionList, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
// }
}

View File

@ -0,0 +1,53 @@
<?php
namespace App\Services\Tg\Hook\Mod;
use App\Models\BladeJctj as ModelBladeJctj;
use App\Services\Tg\Hook\Dog;
use App\Services\TomTool\Flow;
use App\Services\TomTool\HttpV2;
use App\Services\UrlMap;
class Test extends Base {
private $oDog;
public function __construct($aUpdate)
{
$this->oDog = new Dog(new ModelBladeJctj());
$this->oDog->_setDogName("jctj"); // 必须me用正常就是类名只不过后期没准改名所以就这里写死
$this->oDog->_setPrimaryKey("id"); // 可选默认id
$this->oDog->_setStrField(["content"]); // 可选,指定长文本字段
}
public function __call($sName, $aArg)
{
return $this->oDog->$sName($aArg[0]);
}
public function httpJson($aParam)
{
$sUrl = $aParam["aOption"][1] ?? '';
$aDataJson = $aParam["aArg"] ?? [];
$sDataJson = implode(" ", $aDataJson);
$r = HttpV2::make($sUrl)->enableJsonAs()->setDataX($sDataJson)->send();
return $r;
}
public function http($aParam)
{
$sUrl = $aParam["aOption"][1] ?? '';
$aDataJson = $aParam["aArg"] ?? [];
$sDataJson = implode(" ", $aDataJson);
$r = HttpV2::make($sUrl)->setDataX($sDataJson)->send();
return $r;
}
}

View File

@ -0,0 +1,76 @@
<?php
namespace App\Services\Tg\Hook\Mod;
//use App\Models\Box as ModelShip;
//use App\Services\TomTool\Http;
//use App\Models\BoxGithubTag as GithubTag;
class Tool extends Base {
public function Ref($aParam)
{
$sClassName = $aParam["aArg"][1] ?? false;
$sLike = $aParam["aArg"][2] ?? false;
if (!$sClassName) {
return "需要arg[1],类名。";
}
$sClassName = ucfirst($sClassName);
$sClassPath = "App\\Services\\TG\\Hook\\Mod\\".$sClassName;
$oRef = new \ReflectionClass($sClassPath);
$oMetHods = $oRef->getMethods();
$str = "";
foreach ($oMetHods as $oMetHodsRow) {
if ($oMetHodsRow->class == $sClassPath) {
// 有like时只提取like到的无like时得到所有
if ($sLike) {
$string = "Hello, world!";
$character = "o";
if (stripos($oMetHodsRow->name, $sLike) !== false) {
$str .= "\n\n";
$str .= $oMetHodsRow->name;
}
} else {
$str .= "\n\n";
$str .= $oMetHodsRow->name;
}
}
}
return $str;
}
public function refLike($aParam)
{
$sClassName = $aParam["aArg"][1] ?? false;
$sLike = $aParam["aArg"][2] ?? false;
if (!$sClassName) {
return "需要arg[1],类名。";
}
if (!$sLike) {
return "需要arg[2]like。";
}
return $this->Ref($aParam);
}
// public function ref()
// {
// $oRef = new \ReflectionClass($this);
// $oMetHods = $oRef->getMethods();
//
// tomd($oMetHods, 1);
// }
}

View File

@ -0,0 +1,108 @@
<?php
namespace App\Services\Tg;
use App\Services\TomTool\Http as TomHttp;
class Http {
public $sApiToken;
public $sApiChatId;
function __construct()
{
$this->sApiToken = env('telegram_token');
$this->sApiChatId = env('telegram_chatid');
}
public function send($sMsg = "msg空", $aUpdate = [])
{
$bSendTg = true;
$sShell = $aUpdate["shell"] ?? false;
$bIsDove = $aUpdate["is_dove"] ?? false;
if ($sShell == "cmd") {
$bSendTg = false;
}
if ($bIsDove == true) {
$bSendTg = false;
}
if (env("is_loc") == true) {
$bSendTg = false;
}
if (is_array($sMsg)) {
if ($bSendTg) {
foreach ($sMsg as $sMsgRow) {
$this->sendTg($sMsgRow);
}
} else {
echo json_encode($sMsg, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
}
} else {
if ($bSendTg) {
$this->sendTg($sMsg);
} else {
echo $sMsg;
}
}
if ($bSendTg) {
TomHttp::response(200);
} else {
exit;
}
}
private function sendTg($sMsg)
{
$oHttp = new TomHttp();
$oHttp->sMethod = "post";
$oHttp->sToUrl = "https://api.telegram.org/bot$this->sApiToken/sendMessage";
// $oHttp->bIsJson = true;
$oHttp->aData = [
"chat_id" => $this->sApiChatId,
"text" => $sMsg
];
$oHttp->send();
}
public function sendToTG($sMsg, $aUpdate = [])
{
if (isset($aUpdate["shell"]) && $aUpdate["shell"] == "cmd") {
echo $sMsg;
} else if (isset($aUpdate["is_dove"]) && $aUpdate["is_dove"] == true) {
echo $sMsg;
} else {
if (env("is_loc") == true) {
echo $sMsg;
} else {
$oHttp = new TomHttp();
$oHttp->sMethod = "post";
$oHttp->sToUrl = "https://api.telegram.org/bot$this->sApiToken/sendMessage";
// $oHttp->bIsJson = true;
$oHttp->aData = [
"chat_id" => $this->sApiChatId,
"text" => $sMsg
];
$oHttp->send();
}
}
}
}

View File

@ -0,0 +1,412 @@
<?php
declare(strict_types=1);
namespace App\Services\TomTool;
use App\Services\TomTool\TelegramVdb;
/**
默认:
name:none
isDone:false
new:
$oResult = Flow::make("name");
快速:
Flow::make("name")->fail("kkkkkkk");
进阶:
Flow::make("name")->noDone()->msg("哟哟哟哟哟哟")->sendTg()->fetch();
业务:
step()
msg()
data()
aData()
jData()
sData()
code()
put()
merge()
toDone()
noDone()
step("start")
action:
reset()
done(?$msg)
fail(?$msg, ?$aParentResult)
sendTg() 伪action
fetch() or get()
fetchAll() or geAll()
set
enableTg();
parent($aParentResult);
with:
withTraceId();
withTimestamp();
withStep();
判断:
::isDone($aResult);
::isFail($aResult);
*/
class Flow
{
protected array $aStep = [];
protected array $aParent = [];
protected bool $isToTg = false;
protected bool $isToTgOne = false;
protected array $aResult = [
'isDone' => false,
];
protected string $sName;
private bool $isChain = false;
public function __construct(string $name = 'none')
{
$this->sName = $name;
$this->aStep[] = "{$this->sName}::start";
}
// new
public static function make(string $name = 'none'): self
{
return new self($name);
}
// new
public static function start($sName = 'none')
{
$oInstance = new self($sName);
$oInstance->isChain = true;
return $oInstance;
}
// option
public function enableTg(bool $flag = true): self
{
$this->isToTg = $flag;
return $this;
}
// option
public function enableTgOne(bool $flag = true): self
{
$this->enableTg(true);
$this->isToTgOne = $flag;
return $this;
}
// option
public function parent(array $aParentResult): self
{
$this->aParent = $aParentResult;
return $this;
}
// data
public function step(string $step): self
{
$this->aStep[] = "{$this->sName}::{$step}";
return $this;
}
// data
public function msg(string $msg): self
{
$this->put('sMsg', $msg);
return $this;
}
// data
public function aData(array $data): self
{
$this->put('aData', $data);
return $this;
}
// data
public function aDataPut($k, $v)
{
$this->aResult["aData"][$k] = $v;
return $this;
}
// data
public function sData(string $data): self
{
$this->put('sData', $data);
return $this;
}
// data
public function code(string $code): self
{
$this->put('sCode', $code);
return $this;
}
// data
public function put(string $key, mixed $value, $sDataKey = ''): self
{
if ($sDataKey) {
$this->aResult[$sDataKey][$key] = $value;
} else {
$this->aResult[$key] = $value;
}
return $this;
}
// data
public function merge(array $data): self
{
foreach ($data as $k => $v) {
$this->put($k, $v);
}
return $this;
}
// data
public function setDone(bool $b = true): self
{
$this->aResult['isDone'] = $b;
return $this;
}
// data
public function setFail(string $step = ''): self
{
if ($step) {
$this->step($step);
}
$this->aResult['isDone'] = false;
return $this;
}
// with
public function withTraceId(string $id = null): self
{
$this->aResult['sTraceId'] = $id ?? uniqid('trace_', true);
return $this;
}
// with
public function withTimestamp(): self
{
$this->aResult['sTimestamp'] = (new \DateTime())->format(\DateTime::ATOM);
return $this;
}
// with
public function withStep(bool $flag = true): self
{
if ($flag) {
$this->withParentStep();
$this->aResult['aStep'] = $this->aStep;
} else {
unset($this->aResult['aStep']);
}
return $this;
}
// action
public function reset(): self
{
$this->aStep = [$this->sName . '::start'];
$this->aParent = [];
$this->isToTg = false;
$this->isToTgOne = false;
$this->aResult = ['isDone' => false];
return $this;
}
// action
public function done(mixed $msg = null)
{
$this->setDone();
if ($msg) {
$this->msg($msg);
}
return $this->get();
}
// action
public function fail(mixed $msg = null, array $aParentResult = [])
{
$this->setFail('fail');
if ($aParentResult) {
$this->aParent = $aParentResult;
}
if ($msg) {
$this->msg($msg);
}
return $this->getFull();
}
// action
// public function sendTg() // 伪装成非set
// {
// $this->enableTgOne();
// return $this;
// }
// action
public function sendTg($sBotCode = 'base', $sChatCode = 'base')
{
}
public function getDataA()
{
return $this->aResult["aData"] ?? [];
}
public function getDataS()
{
return (string) $this->aResult["sData"] ?? '';
}
public function getDataI()
{
return (int) $this->aResult["iData"] ?? 0;
}
public function getDataB()
{
return (bool) $this->aResult["bData"] ?? false;
}
public function getDataX()
{
return $this->aResult["xData"] ?? '';
}
public function setDataA(array $aData): self
{
$this->aData($aData);
return $this;
}
public function setDataB(bool $bData): self
{
$this->aResult["bData"] = $bData;
return $this;
}
public function setDataS(string $sData): self
{
$this->aResult["sData"] = $sData;
return $this;
}
public function setDataI(int $iData): self
{
$this->aResult["iData"] = $iData;
return $this;
}
public function setDataX($xData): self
{
$this->aResult["xData"] = $xData;
return $this;
}
public function getResult(): array
{
return $this->aResult;
}
// action
public function get()
{
if ($this->isToTg) {
$this->_sendTg();
}
if ($this->isToTgOne) {
$this->isToTg = false;
$this->isToTgOne = false;
}
if ($this->isChain) {
return $this;
}
return $this->aResult;
}
// action
public function getFull()
{
$this->withStep();
return $this->get();
}
// action
public function toArray()
{
return $this->aResult;
}
// helper
public function isDone()
{
return $this->aResult["isDone"] ?? false;
}
// helper
public function isFail()
{
return !$this->isDone();
}
// helper
public static function isDoneResult(array $aResult): bool
{
return $aResult['isDone'] ?? false;
}
// helper
public static function isFailResult(array $aResult): bool
{
return !self::isDoneResult($aResult);
}
// shell
public function fetch()
{
return $this->get();
}
// shell
public function fetchAll()
{
return $this->getFull();
}
private function _sendTg()
{
TelegramVdb::make()->dataArr($this->aResult)->save();
}
protected function addStepParent(): void
{
$this->aStep[] = $this->aParent;
}
protected function withParentStep(): void
{
if ($this->aParent) {
$this->addStepParent();
}
}
}

View File

@ -0,0 +1,253 @@
<?php
declare(strict_types=1);
namespace App\Services\TomTool;
use App\Services\TomTool\Flow;
use Exception;
/**
默认:
method:post
new:
HttpV2::make($url)
基本:
HttpV2::make($url)->send()
进阶:
HttpV2::make($url)->aData($aData)->setJsonAs()->setAsync()->setMethod("get")->send();
action:
send()
data:
xData()
sData()
jData()
sData()
set:
optMethod()
enableJsonAs()
enableJsonSend()
enableJsonReturn()
@note:
默认关闭 SSL 验证(适用于开发环境),生产环境建议开启
异步模式下不会返回响应内容,仅快速触发请求
*/
class HttpV2
{
protected string $method;
protected $data = [];
protected string $url;
protected bool $sendJson = false;
protected bool $returnJson = false;
protected bool $async = false;
// private bool $isChain = false;
// private array $aResult = [
// "isDone" = false
// ];
public static function make(string $url, string $method = 'post'): self
{
$instance = new self();
$instance->url = $url;
$instance->optMethod($method);
return $instance;
}
// public static function start(string $sUrl, string $sMethod = 'post'): self
// {
// $oInstance = new self();
// $oInstance->url = $sUrl;
// $oInstance->method = $sMethod;
// $oInstance->isChain = true;
// return $oInstance;
// }
//
// public function isDone()
// {
// return $this->aResult["isDone"] ?? false;
// }
//
// public function isFail()
// {
// return !$this->isDone();
// }
// public function getResult()
// {
// return $this->aResult;
// }
public function optMethod(string $method): self
{
$this->method = strtolower($method);
return $this;
}
public function setDataX($xData)
{
$this->setData($xData);
return $this;
}
public function setDataA($aData)
{
$this->setData($aData);
return $this;
}
public function setData($xData)
{
// if (is_array($xData)) {
// json_encode($xData)
// }
$this->data = $xData;
return $this;
}
// public function aData($aData = [])
// {
// $this->data($aData);
// return $this;
// }
//
// public function sData($sData = '')
// {
// $this->data($sData);
// return $this;
// }
//
// public function jData($jData = '')
// {
// $this->data($jData);
// return $this;
// }
//
// public function xData($xData = '')
// {
// $this->data($xData);
// return $this;
// }
//
// public function data($data = ''): self
// {
// $this->data = $data;
// return $this;
// }
public function enableJsonSend(bool $flag = true): self
{
$this->sendJson = $flag;
return $this;
}
public function enableJsonReturn(bool $flag = true): self
{
$this->returnJson = $flag;
return $this;
}
public function enableJsonAs(): self
{
$this->sendJson = true;
$this->returnJson = true;
return $this;
}
public function enableAsync(bool $flag = true): self
{
$this->async = $flag;
return $this;
}
public function send(): string
{
$oFlow = Flow::make("HttpV2::send");
$ch = curl_init();
$headers = [];
// 构建 URL 和请求体
if ($this->method === 'get') {
$url = $this->url . '?' . http_build_query($this->data);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPGET, true);
} else {
curl_setopt($ch, CURLOPT_URL, $this->url);
$payload = $this->sendJson ? json_encode($this->data) : http_build_query($this->data);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
if ($this->method === 'post') {
curl_setopt($ch, CURLOPT_POST, true);
} else {
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, strtoupper($this->method));
}
if ($this->sendJson) {
$headers[] = 'Content-Type: application/json';
$headers[] = 'Content-Length: ' . strlen($payload);
}
}
if ($this->returnJson) {
$headers[] = 'Accept: application/json';
}
if (!empty($headers)) {
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
}
// SSL 设置
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
// 异步发送
if ($this->async) {
curl_setopt($ch, CURLOPT_TIMEOUT_MS, 200);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, 200);
curl_setopt($ch, CURLOPT_NOSIGNAL, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, false);
curl_exec($ch);
curl_close($ch);
return 'sent';
}
// 阻塞执行
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
if (curl_errno($ch)) {
$error = curl_error($ch);
curl_close($ch);
throw new Exception("cURL Error: {$error}");
}
curl_close($ch);
return $response;
// $this->aResult = $oFlow->sData($response)->done();
//
// if ($this->isChain) {
// return $this;
// }
//
// return $this->aResult;
}
// public static function response(int $code, string $message = ''): void
// {
// http_response_code($code);
// echo $message;
// exit;
// }
}

View File

@ -0,0 +1,139 @@
<?php
declare(strict_types=1);
namespace App\Services\TomTool\Telegram;
use App\Services\HttpQueue as ServiceHttpQueue;
use App\Services\TomTool\Flow;
use App\Services\TomTool\Telegram\Sdk as ServiceTelegramSdk;
use App\Models\TelegramKey as ModelTelegramKey;
/**
注意是master服务器端专用的这里会对code找mapslave不会。
new:
start(?$sBodeCode, ?$sChatCode)
set:
setBotCode()
setChatCode()
setBotToken()
setChatId()
setMsgS()
action:
send()
*/
final class Master
{
public string $sBotCode = "base";
public string $sChatCode = "base";
public string $sBotToken = '';
public int $iChatId = 0;
public string $sMsg = '';
public bool $enableQueue = false; // 应该用不到了
public bool $bKeyBegin = false;
public static function start($sBotCode = 'base', $sChatCode = 'base'): self
{
$oInstance = new self();
$oInstance->sBotCode = $sBotCode;
$oInstance->sChatCode = $sChatCode;
return $oInstance;
}
public function setBotCode(string $sBotCode): self
{
$this->sBotCode = $sBotCode;
return $this;
}
public function setChatCode(string $sChatCode): self
{
$this->sChatCode = $sChatCode;
return $this;
}
public function setBotToken(string $sBotToken): self
{
$this->sBotToken = $sBotToken;
return $this;
}
public function setChatId(int $iChatId): self
{
$this->iChatId = $iChatId;
return $this;
}
public function setMsgS(string $sMsg): self
{
$this->sMsg = $sMsg;
return $this;
}
public function send($sMsg = ''): Flow
{
if ($sMsg) {
$this->sMsg = $sMsg;
}
if (!$this->sMsg) {
throw new \Exception("未设置msg");
}
$this->keyBegin();
if ($this->enableQueue) {
$aData = $this->buildDataTom();
$oFlow = ServiceHttpQueue::start("telegram_local")->arg($aData)->save();
} else {
$oFlow = ServiceTelegramSdk::start()
->setBotToken($this->sBotToken)
->setChatId($this->iChatId)
->setMsgS($this->sMsg)
->send();
}
return $oFlow;
}
private function keyBegin()
{
if (!$this->bKeyBegin) {
if (!$this->sBotToken) {
$this->sBotToken = ModelTelegramKey::botTokenByCode($this->sBotCode);
}
if (!$this->iChatId) {
$this->iChatId = ModelTelegramKey::chatIdByCode($this->sChatCode);
}
if (!$this->sBotToken || !$this->iChatId) {
throw new \RuntimeException("botToken或chatId没找到botCode={$this->sBotCode}chatCode={$this->sChatCode}");
}
$this->bKeyBegin = true;
}
}
private function buildDataTom(): array
{
return [
"sBotCode" => $this->sBotCode ?? '',
"sChatCode" => $this->sChatCode ?? '',
"sBotToken" => $this->sBotToken ?? '',
"iChatId" => $this->iChatId ?? '',
"sMsg" => $this->sMsg ?? '',
];
}
}

View File

@ -0,0 +1,134 @@
<?php
declare(strict_types=1);
namespace App\Services\TomTool\Telegram;
use Telegram\Bot\Api;
use Telegram\Bot\Exceptions\TelegramSDKException;
use App\Services\TomTool\Flow;
class Sdk
{
public $sMsgFormat = [];
public $sMsgFormatType = 'none';
public $sBotToken = '';
public $iChatId = 0;
public $sMsg;
public $oApi;
private const ALLOWED_FORMATS = ['none', 'html', 'markdown', 'markdownV2'];
public static function start()
{
$oInstance = new self();
return $oInstance;
}
public function setBotToken($sBotToken)
{
$this->oApi = new Api($sBotToken);
$this->sBotToken = $sBotToken;
return $this;
}
public function setChatId($iChatId)
{
$this->iChatId = $iChatId;
return $this;
}
public function setMsgS($sMsg = '')
{
$this->sMsg = $sMsg;
return $this;
}
public function send()
{
$oFlow = Flow::start("tg_sdk_send");
$this->msgFormat();
try {
$r = $this->oApi->sendMessage($this->sMsgFormat);
if (!$r->isOk()) {
return $oFlow->fail();
}
} catch (TelegramSDKException $e) {
return $oFlow->fail(['error' => $e->getMessage()]);
}
return $oFlow->done();
}
public function getMsgFormat()
{
$this->msgFormat();
return $this->sMsgFormat;
}
public function msgFormat()
{
if (!in_array($this->sMsgFormatType, self::ALLOWED_FORMATS, true)) {
throw new \RuntimeException("不支持的格式类型: {$this->sMsgFormatType}");
}
$method = 'msgFormat_' . $this->sMsgFormatType;
$this->sMsgFormat = $this->$method();
return $this;
}
private function msgFormat_none()
{
return [
'chat_id' => $this->iChatId,
'text' => $this->sMsg,
'parse_mode' => '',
'disable_web_page_preview' => false,
'reply_to_message_id' => null,
'reply_markup' => null,
];
}
private function msgFormat_html()
{
return [
'chat_id' => $this->iChatId,
'text' => strip_tags($this->sMsg, [
'b', 'strong', 'i', 'em', 'u', 'ins', 's', 'strike', 'del', 'span', 'tg-spoiler', 'a', 'tg-emoji',
'code', 'pre',
]),
'parse_mode' => 'HTML',
'disable_web_page_preview' => false,
'reply_to_message_id' => null,
'reply_markup' => null,
];
}
private function msgFormat_markdown()
{
return [
'chat_id' => $this->iChatId,
'text' => $this->sMsg,
'parse_mode' => 'Markdown',
'disable_web_page_preview' => false,
'reply_to_message_id' => null,
'reply_markup' => null,
];
}
private function msgFormat_markdownV2()
{
return [
'chat_id' => $this->iChatId,
'text' => $this->sMsg,
'parse_mode' => 'MarkdownV2',
'disable_web_page_preview' => false,
'reply_to_message_id' => null,
'reply_markup' => null,
];
}
}

View File

@ -0,0 +1,312 @@
<?php
declare(strict_types=1);
namespace App\Services\TomTool\Telegram;
use App\Services\TomTool\HttpV2;
use App\Services\TomTool\Telegram\Sdk as ServiceTelegramSdk;
use App\Services\TomTool\Flow;
use App\Services\HttpQueue as ServiceHttpQueue;
/**
提醒:
master自身已经没有队列了收到slave消息直接转发
默认:
走本地队列发送到master
走异步
new:
start()
log()
warn()
fail()
notify()
opt:
enableMaster(:true)
enableMasterQueue(:true)
enableSlaveQueue(:true)
enableDetail(:true)
set:
setMsgS()
setMsgA()
setBotCode()
setChatCode()
setBotToken()
setChatId()
action:
send()
sendMaster()
sendLocal()
*/
class Slave
{
public string $sBotCode;
public string $sChatCode;
public string $sBotToken = '';
public int $iChatId = 0;
public string $sMsg = '';
public bool $enableMaster = true;
public bool $enableMasterQueue = false; // 这里之前想错了不会有master队列只在slave有master转发就行了
public bool $enableSlaveQueue = true;
public bool $enableDetail = true;
public bool $enableAsync = true;
// new
public static function start(string $sBotCode = 'base', string $sChatCode = 'base'): self
{
$oInstance = new self;
$oInstance->sBotCode = $sBotCode;
$oInstance->sChatCode = $sChatCode;
return $oInstance;
}
// new
public static function log(string $sChatCode = 'admin'): self
{
return self::start("log", $sChatCode);
}
// new
public static function warn(string $sChatCode = 'admin'): self
{
return self::start("warn", $sChatCode);
}
// new
public static function fail(string $sChatCode = 'admin'): self
{
return self::start("fail", $sChatCode);
}
// new
public static function notify(string $sChatCode = 'admin'): self
{
return self::start("fail", $sChatCode);
}
// opt
public function enableAsync(bool $b = true): self
{
$this->enableAsync = $b;
return $this;
}
// opt
public function enableDetail(bool $b = true): self
{
$this->enableDetail = $b;
return $this;
}
// opt
public function enableSlaveQueue(bool $b = true): self
{
$this->enableSlaveQueue = $b;
return $this;
}
// opt
public function enableMaster(bool $b = true): self
{
$this->enableMaster = $b;
return $this;
}
// opt
public function enableMasterQueue(bool $b = true): self
{
$this->enableMasterQueue = $b;
return $this;
}
// set
public function setMsgS(string $sMsg = ''): self
{
if ($this->enableDetail) {
$sMsg = "[".$this->getEnvSiteCode()."|".date("Y-m-d H:i:s")."] ".$sMsg;
}
$this->sMsg = $sMsg;
return $this;
}
// set
public function setMsgA(array $aMsg = []): self
{
$aMsgNew = $aMsg;
if ($this->enableDetail) {
$aMsgNew = [];
$aMsgNew["site_code"] = $this->getEnvSiteCode();
$aMsgNew["date"] = date("Y-m-d H:i:s");
$aMsgNew["data"] = $aMsg;
}
$this->sMsg = json_encode($aMsgNew, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
return $this;
}
// set
public function setBotCode(string $sBotCode): self
{
$this->sBotCode = $sBotCode;
return $this;
}
// set
public function setChatCode(string $sChatCode): self
{
$this->sChatCode = $sChatCode;
return $this;
}
// set
public function setBotToken(string $sBotToken): self
{
$this->sBotToken = $sBotToken;
return $this;
}
// set
public function setChatId(int $iChatId): self
{
$this->iChatId = $iChatId;
return $this;
}
// action
public function send($xMsg = ''): Flow
{
if ($xMsg) {
if (is_array($xMsg)) {
$this->setMsgA($xMsg);
} else {
$this->setMsgS($xMsg);
}
}
if (!$this->sMsg) {
throw new Exception("未设置msg");
}
if ($this->enableMaster) {
$oFlow = $this->_send_master();
} else {
$oFlow = $this->_send_local();
}
return $oFlow;
}
// action
public function sendMaster($xMsg = ''): Flow
{
$this->enableMaster(true);
return $this->send($xMsg);
}
// action
public function sendLocal($xMsg = ''): Flow
{
$this->enableMaster(false);
return $this->send($xMsg);
}
private function _send_master(): Flow
{
$aData = $this->buildDataTom();
if ($this->enableSlaveQueue) {
$oFlow = ServiceHttpQueue::start("telegram_master")->arg($aData)->save();
} else {
$oFlow = Flow::start("_send_master");
$sUrlMaSterBase = $_ENV["url_master_base"];
if (!$sUrlMaSterBase) {
throw new Exception("未设置env的url_master_base");
}
$sUrlMasterPost = "https://".$sUrlMaSterBase."/api/telegram/post";
try {
$oHttpV2 = HttpV2::make($sUrlMasterPost);
if ($this->enableAsync) {
$oHttpV2 = $oHttpV2->enableAsync();
}
$r = $oHttpV2->enableJsonAs()->setData($aData)->send();
if ($this->enableAsync) {
return $oFlow->sData("async")->done("async");
} else {
$a = json_decode($r, true);
$isDone = $a["isDone"] ?? false;
if ($isDone) {
return $oFlow->done();
} else {
return $oFlow->fail($r);
}
}
} catch (\Throwable $e) {
$oFlow = $oFlow->fail($e->getMessage());
}
}
return $oFlow;
}
private function _send_local(): Flow
{
if ($this->enableSlaveQueue) {
$aData = $this->buildDataTom();
$oFlow = ServiceHttpQueue::start("telegram_local")->arg($aData)->save();
} else {
$oFlow = ServiceTelegramSdk::start($this->sBotToken, $this->iChatId)->setMsgS($this->sMsg)->send();
}
return $oFlow;
}
private function buildDataTom(): array
{
return [
"sBotCode" => $this->sBotCode ?? '',
"sChatCode" => $this->sChatCode ?? '',
"sBotToken" => $this->sBotToken ?? '',
"iChatId" => $this->iChatId ?? '',
"enableMasterQueue" => $this->enableMasterQueue ?? '',
"enableMaster" => $this->enableMaster,
"sMsg" => $this->sMsg ?? '',
];
}
private function getEnvSiteCode(): string
{
$sEnvSiteCode = $_ENV["site_code"] ?? "未设置env的site_code";
return $sEnvSiteCode;
}
}

View File

@ -0,0 +1,130 @@
<?php
declare(strict_types=1);
namespace App\Services\TomTool;
use Throwable as ThrowableBase;
use Illuminate\Database\QueryException;
use App\Services\TomTool\TelegramVdb;
/**
new:
$oThrowableHandler = ThrowableHandler::make($e);
快速:
$aResult = ThrowableHandler::make($e)->toArr();
action
fetch() or get()
set:
enableTg()
enableTrace()
setMaxDepth()
*/
class ThrowableHandler
{
protected bool $tgEnable = false;
protected bool $showTrace = false;
protected int $maxDepth = 3;
protected ThrowableBase $e;
public static function make(ThrowableBase $e): self
{
$oInstance = new self();
$oInstance->e = $e;
return $oInstance;
}
public function fetch()
{
return $this->get();
}
public function get(): array
{
$data = $this->buildExceptionData($this->e, 0);
if ($this->tgEnable) {
$this->sendTelegram($data);
}
return $data;
}
public function toArr(): array
{
return $this->get();
}
public function toJson(): string
{
return json_encode($this->get(), JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
}
public function enableTg(bool $enable = true): self
{
$this->tgEnable = $enable;
return $this;
}
public function enableTrace(bool $enable = true): self
{
$this->showTrace = $enable;
return $this;
}
public function setMaxDepth(int $depth): self
{
$this->maxDepth = max(1, $depth);
return $this;
}
protected function buildExceptionData(ThrowableBase $e, int $depth): array
{
$data = [
'message' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
];
$code = $e->getCode();
if ($code !== null && $code !== 0) {
$data['code'] = $code;
}
if ($this->showTrace) {
$filteredTrace = array_filter($e->getTrace(), function ($frame) {
return empty($frame['file']) || !str_contains($frame['file'], '/vendor/');
});
$traceLines = [];
foreach ($filteredTrace as $frame) {
$file = $frame['file'] ?? '[internal]';
$line = $frame['line'] ?? '';
$func = isset($frame['class'], $frame['function'])
? "{$frame['class']}{$frame['type']}{$frame['function']}"
: ($frame['function'] ?? '[unknown]');
$traceLines[] = "{$file}:{$line} {$func}()";
}
$data['trace'] = implode("\n", $traceLines);
}
if ($depth < $this->maxDepth && $e->getPrevious() instanceof ThrowableBase) {
$data['previous'] = $this->buildExceptionData($e->getPrevious(), $depth + 1);
}
return $data;
}
protected function sendTelegram(array $data): void
{
TelegramVdb::make()->aData($data)->save();
}
}

View File

@ -0,0 +1,21 @@
<?php
declare(strict_types=1);
namespace App\Services\TomTool;
class Tom
{
public static function toJson($aData)
{
return json_encode($aData, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
}
public static function toJsonBr($aData)
{
$sData = self::toJson($aData);
$sData = str_replace("\\n", "<br>", $sData);
return $sData;
}
}

15
laravel/artisan Executable file
View File

@ -0,0 +1,15 @@
#!/usr/bin/env php
<?php
use Symfony\Component\Console\Input\ArgvInput;
define('LARAVEL_START', microtime(true));
// Register the Composer autoloader...
require __DIR__.'/vendor/autoload.php';
// Bootstrap Laravel and handle the command...
$status = (require_once __DIR__.'/bootstrap/app.php')
->handleCommand(new ArgvInput);
exit($status);

24
laravel/bootstrap/app.php Executable file
View File

@ -0,0 +1,24 @@
<?php
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: __DIR__.'/../routes/web.php',
commands: __DIR__.'/../routes/console.php',
health: '/up',
)
->withMiddleware(function (Middleware $middleware) {
$middleware->alias([
//'test' => \App\Http\Middleware\Test::class,
]);
$middleware->validateCsrfTokens(except: [
'api/*',
'cmd/*',
]);
})
->withExceptions(function (Exceptions $exceptions) {
//
})->create();

2
laravel/bootstrap/cache/.gitignore vendored Executable file
View File

@ -0,0 +1,2 @@
*
!.gitignore

View File

@ -0,0 +1,5 @@
<?php
return [
App\Providers\AppServiceProvider::class,
];

1
laravel/build.log Normal file
View File

@ -0,0 +1 @@
sh: npm: command not found

74
laravel/composer.json Executable file
View File

@ -0,0 +1,74 @@
{
"$schema": "https://getcomposer.org/schema.json",
"name": "laravel/laravel",
"type": "project",
"description": "The skeleton application for the Laravel framework.",
"keywords": ["laravel", "framework"],
"license": "MIT",
"require": {
"php": "^8.2",
"guzzlehttp/guzzle": "^7.9",
"irazasyed/telegram-bot-sdk": "^3.15",
"laravel/framework": "^11.31",
"laravel/tinker": "^2.9",
"voku/anti-xss": "^4.1"
},
"require-dev": {
"fakerphp/faker": "^1.23",
"laravel/pail": "^1.1",
"laravel/pint": "^1.13",
"laravel/sail": "^1.26",
"mockery/mockery": "^1.6",
"nunomaduro/collision": "^8.1",
"phpunit/phpunit": "^11.0.1"
},
"autoload": {
"psr-4": {
"App\\": "app/",
"Database\\Factories\\": "database/factories/",
"Database\\Seeders\\": "database/seeders/"
}
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
},
"scripts": {
"post-autoload-dump": [
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
"@php artisan package:discover --ansi"
],
"post-update-cmd": [
"@php artisan vendor:publish --tag=laravel-assets --ansi --force"
],
"post-root-package-install": [
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
],
"post-create-project-cmd": [
"@php artisan key:generate --ansi",
"@php -r \"file_exists('database/database.sqlite') || touch('database/database.sqlite');\"",
"@php artisan migrate --graceful --ansi"
],
"dev": [
"Composer\\Config::disableProcessTimeout",
"npx concurrently -c \"#93c5fd,#c4b5fd,#fb7185,#fdba74\" \"php artisan serve\" \"php artisan queue:listen --tries=1\" \"php artisan pail --timeout=0\" \"npm run dev\" --names=server,queue,logs,vite"
]
},
"extra": {
"laravel": {
"dont-discover": []
}
},
"config": {
"optimize-autoloader": true,
"preferred-install": "dist",
"sort-packages": true,
"allow-plugins": {
"pestphp/pest-plugin": true,
"php-http/discovery": true
}
},
"minimum-stability": "stable",
"prefer-stable": true
}

8556
laravel/composer.lock generated Executable file

File diff suppressed because it is too large Load Diff

126
laravel/config/app.php Executable file
View File

@ -0,0 +1,126 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Application Name
|--------------------------------------------------------------------------
|
| This value is the name of your application, which will be used when the
| framework needs to place the application's name in a notification or
| other UI elements where an application name needs to be displayed.
|
*/
'name' => env('APP_NAME', 'Laravel'),
/*
|--------------------------------------------------------------------------
| Application Environment
|--------------------------------------------------------------------------
|
| This value determines the "environment" your application is currently
| running in. This may determine how you prefer to configure various
| services the application utilizes. Set this in your ".env" file.
|
*/
'env' => env('APP_ENV', 'production'),
/*
|--------------------------------------------------------------------------
| Application Debug Mode
|--------------------------------------------------------------------------
|
| When your application is in debug mode, detailed error messages with
| stack traces will be shown on every error that occurs within your
| application. If disabled, a simple generic error page is shown.
|
*/
'debug' => (bool) env('APP_DEBUG', false),
/*
|--------------------------------------------------------------------------
| Application URL
|--------------------------------------------------------------------------
|
| This URL is used by the console to properly generate URLs when using
| the Artisan command line tool. You should set this to the root of
| the application so that it's available within Artisan commands.
|
*/
'url' => env('APP_URL', 'http://localhost'),
/*
|--------------------------------------------------------------------------
| Application Timezone
|--------------------------------------------------------------------------
|
| Here you may specify the default timezone for your application, which
| will be used by the PHP date and date-time functions. The timezone
| is set to "UTC" by default as it is suitable for most use cases.
|
*/
'timezone' => env('APP_TIMEZONE', 'UTC'),
/*
|--------------------------------------------------------------------------
| Application Locale Configuration
|--------------------------------------------------------------------------
|
| The application locale determines the default locale that will be used
| by Laravel's translation / localization methods. This option can be
| set to any locale for which you plan to have translation strings.
|
*/
'locale' => env('APP_LOCALE', 'en'),
'fallback_locale' => env('APP_FALLBACK_LOCALE', 'en'),
'faker_locale' => env('APP_FAKER_LOCALE', 'en_US'),
/*
|--------------------------------------------------------------------------
| Encryption Key
|--------------------------------------------------------------------------
|
| This key is utilized by Laravel's encryption services and should be set
| to a random, 32 character string to ensure that all encrypted values
| are secure. You should do this prior to deploying the application.
|
*/
'cipher' => 'AES-256-CBC',
'key' => env('APP_KEY'),
'previous_keys' => [
...array_filter(
explode(',', env('APP_PREVIOUS_KEYS', ''))
),
],
/*
|--------------------------------------------------------------------------
| Maintenance Mode Driver
|--------------------------------------------------------------------------
|
| These configuration options determine the driver used to determine and
| manage Laravel's "maintenance mode" status. The "cache" driver will
| allow maintenance mode to be controlled across multiple machines.
|
| Supported drivers: "file", "cache"
|
*/
'maintenance' => [
'driver' => env('APP_MAINTENANCE_DRIVER', 'file'),
'store' => env('APP_MAINTENANCE_STORE', 'database'),
],
];

115
laravel/config/auth.php Executable file
View File

@ -0,0 +1,115 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Authentication Defaults
|--------------------------------------------------------------------------
|
| This option defines the default authentication "guard" and password
| reset "broker" for your application. You may change these values
| as required, but they're a perfect start for most applications.
|
*/
'defaults' => [
'guard' => env('AUTH_GUARD', 'web'),
'passwords' => env('AUTH_PASSWORD_BROKER', 'users'),
],
/*
|--------------------------------------------------------------------------
| Authentication Guards
|--------------------------------------------------------------------------
|
| Next, you may define every authentication guard for your application.
| Of course, a great default configuration has been defined for you
| which utilizes session storage plus the Eloquent user provider.
|
| All authentication guards have a user provider, which defines how the
| users are actually retrieved out of your database or other storage
| system used by the application. Typically, Eloquent is utilized.
|
| Supported: "session"
|
*/
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
],
/*
|--------------------------------------------------------------------------
| User Providers
|--------------------------------------------------------------------------
|
| All authentication guards have a user provider, which defines how the
| users are actually retrieved out of your database or other storage
| system used by the application. Typically, Eloquent is utilized.
|
| If you have multiple user tables or models you may configure multiple
| providers to represent the model / table. These providers may then
| be assigned to any extra authentication guards you have defined.
|
| Supported: "database", "eloquent"
|
*/
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => env('AUTH_MODEL', App\Models\User::class),
],
// 'users' => [
// 'driver' => 'database',
// 'table' => 'users',
// ],
],
/*
|--------------------------------------------------------------------------
| Resetting Passwords
|--------------------------------------------------------------------------
|
| These configuration options specify the behavior of Laravel's password
| reset functionality, including the table utilized for token storage
| and the user provider that is invoked to actually retrieve users.
|
| The expiry time is the number of minutes that each reset token will be
| considered valid. This security feature keeps tokens short-lived so
| they have less time to be guessed. You may change this as needed.
|
| The throttle setting is the number of seconds a user must wait before
| generating more password reset tokens. This prevents the user from
| quickly generating a very large amount of password reset tokens.
|
*/
'passwords' => [
'users' => [
'provider' => 'users',
'table' => env('AUTH_PASSWORD_RESET_TOKEN_TABLE', 'password_reset_tokens'),
'expire' => 60,
'throttle' => 60,
],
],
/*
|--------------------------------------------------------------------------
| Password Confirmation Timeout
|--------------------------------------------------------------------------
|
| Here you may define the amount of seconds before a password confirmation
| window expires and users are asked to re-enter their password via the
| confirmation screen. By default, the timeout lasts for three hours.
|
*/
'password_timeout' => env('AUTH_PASSWORD_TIMEOUT', 10800),
];

108
laravel/config/cache.php Executable file
View File

@ -0,0 +1,108 @@
<?php
use Illuminate\Support\Str;
return [
/*
|--------------------------------------------------------------------------
| Default Cache Store
|--------------------------------------------------------------------------
|
| This option controls the default cache store that will be used by the
| framework. This connection is utilized if another isn't explicitly
| specified when running a cache operation inside the application.
|
*/
'default' => env('CACHE_STORE', 'database'),
/*
|--------------------------------------------------------------------------
| Cache Stores
|--------------------------------------------------------------------------
|
| Here you may define all of the cache "stores" for your application as
| well as their drivers. You may even define multiple stores for the
| same cache driver to group types of items stored in your caches.
|
| Supported drivers: "array", "database", "file", "memcached",
| "redis", "dynamodb", "octane", "null"
|
*/
'stores' => [
'array' => [
'driver' => 'array',
'serialize' => false,
],
'database' => [
'driver' => 'database',
'connection' => env('DB_CACHE_CONNECTION'),
'table' => env('DB_CACHE_TABLE', 'cache'),
'lock_connection' => env('DB_CACHE_LOCK_CONNECTION'),
'lock_table' => env('DB_CACHE_LOCK_TABLE'),
],
'file' => [
'driver' => 'file',
'path' => storage_path('framework/cache/data'),
'lock_path' => storage_path('framework/cache/data'),
],
'memcached' => [
'driver' => 'memcached',
'persistent_id' => env('MEMCACHED_PERSISTENT_ID'),
'sasl' => [
env('MEMCACHED_USERNAME'),
env('MEMCACHED_PASSWORD'),
],
'options' => [
// Memcached::OPT_CONNECT_TIMEOUT => 2000,
],
'servers' => [
[
'host' => env('MEMCACHED_HOST', '127.0.0.1'),
'port' => env('MEMCACHED_PORT', 11211),
'weight' => 100,
],
],
],
'redis' => [
'driver' => 'redis',
'connection' => env('REDIS_CACHE_CONNECTION', 'cache'),
'lock_connection' => env('REDIS_CACHE_LOCK_CONNECTION', 'default'),
],
'dynamodb' => [
'driver' => 'dynamodb',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
'table' => env('DYNAMODB_CACHE_TABLE', 'cache'),
'endpoint' => env('DYNAMODB_ENDPOINT'),
],
'octane' => [
'driver' => 'octane',
],
],
/*
|--------------------------------------------------------------------------
| Cache Key Prefix
|--------------------------------------------------------------------------
|
| When utilizing the APC, database, memcached, Redis, and DynamoDB cache
| stores, there might be other applications using the same cache. For
| that reason, you may prefix every cache key to avoid collisions.
|
*/
'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_cache_'),
];

173
laravel/config/database.php Executable file
View File

@ -0,0 +1,173 @@
<?php
use Illuminate\Support\Str;
return [
/*
|--------------------------------------------------------------------------
| Default Database Connection Name
|--------------------------------------------------------------------------
|
| Here you may specify which of the database connections below you wish
| to use as your default connection for database operations. This is
| the connection which will be utilized unless another connection
| is explicitly specified when you execute a query / statement.
|
*/
'default' => env('DB_CONNECTION', 'sqlite'),
/*
|--------------------------------------------------------------------------
| Database Connections
|--------------------------------------------------------------------------
|
| Below are all of the database connections defined for your application.
| An example configuration is provided for each database system which
| is supported by Laravel. You're free to add / remove connections.
|
*/
'connections' => [
'sqlite' => [
'driver' => 'sqlite',
'url' => env('DB_URL'),
'database' => env('DB_DATABASE', database_path('database.sqlite')),
'prefix' => '',
'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),
'busy_timeout' => null,
'journal_mode' => null,
'synchronous' => null,
],
'mysql' => [
'driver' => 'mysql',
'url' => env('DB_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'laravel'),
'username' => env('DB_USERNAME', 'root'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => env('DB_CHARSET', 'utf8mb4'),
'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'),
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => null,
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
],
'mariadb' => [
'driver' => 'mariadb',
'url' => env('DB_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'laravel'),
'username' => env('DB_USERNAME', 'root'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => env('DB_CHARSET', 'utf8mb4'),
'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'),
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => null,
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
],
'pgsql' => [
'driver' => 'pgsql',
'url' => env('DB_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '5432'),
'database' => env('DB_DATABASE', 'laravel'),
'username' => env('DB_USERNAME', 'root'),
'password' => env('DB_PASSWORD', ''),
'charset' => env('DB_CHARSET', 'utf8'),
'prefix' => '',
'prefix_indexes' => true,
'search_path' => 'public',
'sslmode' => 'prefer',
],
'sqlsrv' => [
'driver' => 'sqlsrv',
'url' => env('DB_URL'),
'host' => env('DB_HOST', 'localhost'),
'port' => env('DB_PORT', '1433'),
'database' => env('DB_DATABASE', 'laravel'),
'username' => env('DB_USERNAME', 'root'),
'password' => env('DB_PASSWORD', ''),
'charset' => env('DB_CHARSET', 'utf8'),
'prefix' => '',
'prefix_indexes' => true,
// 'encrypt' => env('DB_ENCRYPT', 'yes'),
// 'trust_server_certificate' => env('DB_TRUST_SERVER_CERTIFICATE', 'false'),
],
],
/*
|--------------------------------------------------------------------------
| Migration Repository Table
|--------------------------------------------------------------------------
|
| This table keeps track of all the migrations that have already run for
| your application. Using this information, we can determine which of
| the migrations on disk haven't actually been run on the database.
|
*/
'migrations' => [
'table' => 'migrations',
'update_date_on_publish' => true,
],
/*
|--------------------------------------------------------------------------
| Redis Databases
|--------------------------------------------------------------------------
|
| Redis is an open source, fast, and advanced key-value store that also
| provides a richer body of commands than a typical key-value system
| such as Memcached. You may define your connection settings here.
|
*/
'redis' => [
'client' => env('REDIS_CLIENT', 'phpredis'),
'options' => [
'cluster' => env('REDIS_CLUSTER', 'redis'),
'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'),
],
'default' => [
'url' => env('REDIS_URL'),
'host' => env('REDIS_HOST', '127.0.0.1'),
'username' => env('REDIS_USERNAME'),
'password' => env('REDIS_PASSWORD'),
'port' => env('REDIS_PORT', '6379'),
'database' => env('REDIS_DB', '0'),
],
'cache' => [
'url' => env('REDIS_URL'),
'host' => env('REDIS_HOST', '127.0.0.1'),
'username' => env('REDIS_USERNAME'),
'password' => env('REDIS_PASSWORD'),
'port' => env('REDIS_PORT', '6379'),
'database' => env('REDIS_CACHE_DB', '1'),
],
],
];

77
laravel/config/filesystems.php Executable file
View File

@ -0,0 +1,77 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Default Filesystem Disk
|--------------------------------------------------------------------------
|
| Here you may specify the default filesystem disk that should be used
| by the framework. The "local" disk, as well as a variety of cloud
| based disks are available to your application for file storage.
|
*/
'default' => env('FILESYSTEM_DISK', 'local'),
/*
|--------------------------------------------------------------------------
| Filesystem Disks
|--------------------------------------------------------------------------
|
| Below you may configure as many filesystem disks as necessary, and you
| may even configure multiple disks for the same driver. Examples for
| most supported storage drivers are configured here for reference.
|
| Supported drivers: "local", "ftp", "sftp", "s3"
|
*/
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app/private'),
'serve' => true,
'throw' => false,
],
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
'throw' => false,
],
's3' => [
'driver' => 's3',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION'),
'bucket' => env('AWS_BUCKET'),
'url' => env('AWS_URL'),
'endpoint' => env('AWS_ENDPOINT'),
'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),
'throw' => false,
],
],
/*
|--------------------------------------------------------------------------
| Symbolic Links
|--------------------------------------------------------------------------
|
| Here you may configure the symbolic links that will be created when the
| `storage:link` Artisan command is executed. The array keys should be
| the locations of the links and the values should be their targets.
|
*/
'links' => [
public_path('storage') => storage_path('app/public'),
],
];

132
laravel/config/logging.php Executable file
View File

@ -0,0 +1,132 @@
<?php
use Monolog\Handler\NullHandler;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\SyslogUdpHandler;
use Monolog\Processor\PsrLogMessageProcessor;
return [
/*
|--------------------------------------------------------------------------
| Default Log Channel
|--------------------------------------------------------------------------
|
| This option defines the default log channel that is utilized to write
| messages to your logs. The value provided here should match one of
| the channels present in the list of "channels" configured below.
|
*/
'default' => env('LOG_CHANNEL', 'stack'),
/*
|--------------------------------------------------------------------------
| Deprecations Log Channel
|--------------------------------------------------------------------------
|
| This option controls the log channel that should be used to log warnings
| regarding deprecated PHP and library features. This allows you to get
| your application ready for upcoming major versions of dependencies.
|
*/
'deprecations' => [
'channel' => env('LOG_DEPRECATIONS_CHANNEL', 'null'),
'trace' => env('LOG_DEPRECATIONS_TRACE', false),
],
/*
|--------------------------------------------------------------------------
| Log Channels
|--------------------------------------------------------------------------
|
| Here you may configure the log channels for your application. Laravel
| utilizes the Monolog PHP logging library, which includes a variety
| of powerful log handlers and formatters that you're free to use.
|
| Available drivers: "single", "daily", "slack", "syslog",
| "errorlog", "monolog", "custom", "stack"
|
*/
'channels' => [
'stack' => [
'driver' => 'stack',
'channels' => explode(',', env('LOG_STACK', 'single')),
'ignore_exceptions' => false,
],
'single' => [
'driver' => 'single',
'path' => storage_path('logs/laravel.log'),
'level' => env('LOG_LEVEL', 'debug'),
'replace_placeholders' => true,
],
'daily' => [
'driver' => 'daily',
'path' => storage_path('logs/laravel.log'),
'level' => env('LOG_LEVEL', 'debug'),
'days' => env('LOG_DAILY_DAYS', 14),
'replace_placeholders' => true,
],
'slack' => [
'driver' => 'slack',
'url' => env('LOG_SLACK_WEBHOOK_URL'),
'username' => env('LOG_SLACK_USERNAME', 'Laravel Log'),
'emoji' => env('LOG_SLACK_EMOJI', ':boom:'),
'level' => env('LOG_LEVEL', 'critical'),
'replace_placeholders' => true,
],
'papertrail' => [
'driver' => 'monolog',
'level' => env('LOG_LEVEL', 'debug'),
'handler' => env('LOG_PAPERTRAIL_HANDLER', SyslogUdpHandler::class),
'handler_with' => [
'host' => env('PAPERTRAIL_URL'),
'port' => env('PAPERTRAIL_PORT'),
'connectionString' => 'tls://'.env('PAPERTRAIL_URL').':'.env('PAPERTRAIL_PORT'),
],
'processors' => [PsrLogMessageProcessor::class],
],
'stderr' => [
'driver' => 'monolog',
'level' => env('LOG_LEVEL', 'debug'),
'handler' => StreamHandler::class,
'formatter' => env('LOG_STDERR_FORMATTER'),
'with' => [
'stream' => 'php://stderr',
],
'processors' => [PsrLogMessageProcessor::class],
],
'syslog' => [
'driver' => 'syslog',
'level' => env('LOG_LEVEL', 'debug'),
'facility' => env('LOG_SYSLOG_FACILITY', LOG_USER),
'replace_placeholders' => true,
],
'errorlog' => [
'driver' => 'errorlog',
'level' => env('LOG_LEVEL', 'debug'),
'replace_placeholders' => true,
],
'null' => [
'driver' => 'monolog',
'handler' => NullHandler::class,
],
'emergency' => [
'path' => storage_path('logs/laravel.log'),
],
],
];

116
laravel/config/mail.php Executable file
View File

@ -0,0 +1,116 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Default Mailer
|--------------------------------------------------------------------------
|
| This option controls the default mailer that is used to send all email
| messages unless another mailer is explicitly specified when sending
| the message. All additional mailers can be configured within the
| "mailers" array. Examples of each type of mailer are provided.
|
*/
'default' => env('MAIL_MAILER', 'log'),
/*
|--------------------------------------------------------------------------
| Mailer Configurations
|--------------------------------------------------------------------------
|
| Here you may configure all of the mailers used by your application plus
| their respective settings. Several examples have been configured for
| you and you are free to add your own as your application requires.
|
| Laravel supports a variety of mail "transport" drivers that can be used
| when delivering an email. You may specify which one you're using for
| your mailers below. You may also add additional mailers if needed.
|
| Supported: "smtp", "sendmail", "mailgun", "ses", "ses-v2",
| "postmark", "resend", "log", "array",
| "failover", "roundrobin"
|
*/
'mailers' => [
'smtp' => [
'transport' => 'smtp',
'scheme' => env('MAIL_SCHEME'),
'url' => env('MAIL_URL'),
'host' => env('MAIL_HOST', '127.0.0.1'),
'port' => env('MAIL_PORT', 2525),
'username' => env('MAIL_USERNAME'),
'password' => env('MAIL_PASSWORD'),
'timeout' => null,
'local_domain' => env('MAIL_EHLO_DOMAIN', parse_url(env('APP_URL', 'http://localhost'), PHP_URL_HOST)),
],
'ses' => [
'transport' => 'ses',
],
'postmark' => [
'transport' => 'postmark',
// 'message_stream_id' => env('POSTMARK_MESSAGE_STREAM_ID'),
// 'client' => [
// 'timeout' => 5,
// ],
],
'resend' => [
'transport' => 'resend',
],
'sendmail' => [
'transport' => 'sendmail',
'path' => env('MAIL_SENDMAIL_PATH', '/usr/sbin/sendmail -bs -i'),
],
'log' => [
'transport' => 'log',
'channel' => env('MAIL_LOG_CHANNEL'),
],
'array' => [
'transport' => 'array',
],
'failover' => [
'transport' => 'failover',
'mailers' => [
'smtp',
'log',
],
],
'roundrobin' => [
'transport' => 'roundrobin',
'mailers' => [
'ses',
'postmark',
],
],
],
/*
|--------------------------------------------------------------------------
| Global "From" Address
|--------------------------------------------------------------------------
|
| You may wish for all emails sent by your application to be sent from
| the same address. Here you may specify a name and address that is
| used globally for all emails that are sent by your application.
|
*/
'from' => [
'address' => env('MAIL_FROM_ADDRESS', 'hello@example.com'),
'name' => env('MAIL_FROM_NAME', 'Example'),
],
];

112
laravel/config/queue.php Executable file
View File

@ -0,0 +1,112 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Default Queue Connection Name
|--------------------------------------------------------------------------
|
| Laravel's queue supports a variety of backends via a single, unified
| API, giving you convenient access to each backend using identical
| syntax for each. The default queue connection is defined below.
|
*/
'default' => env('QUEUE_CONNECTION', 'database'),
/*
|--------------------------------------------------------------------------
| Queue Connections
|--------------------------------------------------------------------------
|
| Here you may configure the connection options for every queue backend
| used by your application. An example configuration is provided for
| each backend supported by Laravel. You're also free to add more.
|
| Drivers: "sync", "database", "beanstalkd", "sqs", "redis", "null"
|
*/
'connections' => [
'sync' => [
'driver' => 'sync',
],
'database' => [
'driver' => 'database',
'connection' => env('DB_QUEUE_CONNECTION'),
'table' => env('DB_QUEUE_TABLE', 'jobs'),
'queue' => env('DB_QUEUE', 'default'),
'retry_after' => (int) env('DB_QUEUE_RETRY_AFTER', 90),
'after_commit' => false,
],
'beanstalkd' => [
'driver' => 'beanstalkd',
'host' => env('BEANSTALKD_QUEUE_HOST', 'localhost'),
'queue' => env('BEANSTALKD_QUEUE', 'default'),
'retry_after' => (int) env('BEANSTALKD_QUEUE_RETRY_AFTER', 90),
'block_for' => 0,
'after_commit' => false,
],
'sqs' => [
'driver' => 'sqs',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'),
'queue' => env('SQS_QUEUE', 'default'),
'suffix' => env('SQS_SUFFIX'),
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
'after_commit' => false,
],
'redis' => [
'driver' => 'redis',
'connection' => env('REDIS_QUEUE_CONNECTION', 'default'),
'queue' => env('REDIS_QUEUE', 'default'),
'retry_after' => (int) env('REDIS_QUEUE_RETRY_AFTER', 90),
'block_for' => null,
'after_commit' => false,
],
],
/*
|--------------------------------------------------------------------------
| Job Batching
|--------------------------------------------------------------------------
|
| The following options configure the database and table that store job
| batching information. These options can be updated to any database
| connection and table which has been defined by your application.
|
*/
'batching' => [
'database' => env('DB_CONNECTION', 'sqlite'),
'table' => 'job_batches',
],
/*
|--------------------------------------------------------------------------
| Failed Queue Jobs
|--------------------------------------------------------------------------
|
| These options configure the behavior of failed queue job logging so you
| can control how and where failed jobs are stored. Laravel ships with
| support for storing failed jobs in a simple file or in a database.
|
| Supported drivers: "database-uuids", "dynamodb", "file", "null"
|
*/
'failed' => [
'driver' => env('QUEUE_FAILED_DRIVER', 'database-uuids'),
'database' => env('DB_CONNECTION', 'sqlite'),
'table' => 'failed_jobs',
],
];

38
laravel/config/services.php Executable file
View File

@ -0,0 +1,38 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Third Party Services
|--------------------------------------------------------------------------
|
| This file is for storing the credentials for third party services such
| as Mailgun, Postmark, AWS and more. This file provides the de facto
| location for this type of information, allowing packages to have
| a conventional file to locate the various service credentials.
|
*/
'postmark' => [
'token' => env('POSTMARK_TOKEN'),
],
'ses' => [
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
],
'resend' => [
'key' => env('RESEND_KEY'),
],
'slack' => [
'notifications' => [
'bot_user_oauth_token' => env('SLACK_BOT_USER_OAUTH_TOKEN'),
'channel' => env('SLACK_BOT_USER_DEFAULT_CHANNEL'),
],
],
];

217
laravel/config/session.php Executable file
View File

@ -0,0 +1,217 @@
<?php
use Illuminate\Support\Str;
return [
/*
|--------------------------------------------------------------------------
| Default Session Driver
|--------------------------------------------------------------------------
|
| This option determines the default session driver that is utilized for
| incoming requests. Laravel supports a variety of storage options to
| persist session data. Database storage is a great default choice.
|
| Supported: "file", "cookie", "database", "apc",
| "memcached", "redis", "dynamodb", "array"
|
*/
'driver' => env('SESSION_DRIVER', 'database'),
/*
|--------------------------------------------------------------------------
| Session Lifetime
|--------------------------------------------------------------------------
|
| Here you may specify the number of minutes that you wish the session
| to be allowed to remain idle before it expires. If you want them
| to expire immediately when the browser is closed then you may
| indicate that via the expire_on_close configuration option.
|
*/
'lifetime' => env('SESSION_LIFETIME', 120),
'expire_on_close' => env('SESSION_EXPIRE_ON_CLOSE', false),
/*
|--------------------------------------------------------------------------
| Session Encryption
|--------------------------------------------------------------------------
|
| This option allows you to easily specify that all of your session data
| should be encrypted before it's stored. All encryption is performed
| automatically by Laravel and you may use the session like normal.
|
*/
'encrypt' => env('SESSION_ENCRYPT', false),
/*
|--------------------------------------------------------------------------
| Session File Location
|--------------------------------------------------------------------------
|
| When utilizing the "file" session driver, the session files are placed
| on disk. The default storage location is defined here; however, you
| are free to provide another location where they should be stored.
|
*/
'files' => storage_path('framework/sessions'),
/*
|--------------------------------------------------------------------------
| Session Database Connection
|--------------------------------------------------------------------------
|
| When using the "database" or "redis" session drivers, you may specify a
| connection that should be used to manage these sessions. This should
| correspond to a connection in your database configuration options.
|
*/
'connection' => env('SESSION_CONNECTION'),
/*
|--------------------------------------------------------------------------
| Session Database Table
|--------------------------------------------------------------------------
|
| When using the "database" session driver, you may specify the table to
| be used to store sessions. Of course, a sensible default is defined
| for you; however, you're welcome to change this to another table.
|
*/
'table' => env('SESSION_TABLE', 'sessions'),
/*
|--------------------------------------------------------------------------
| Session Cache Store
|--------------------------------------------------------------------------
|
| When using one of the framework's cache driven session backends, you may
| define the cache store which should be used to store the session data
| between requests. This must match one of your defined cache stores.
|
| Affects: "apc", "dynamodb", "memcached", "redis"
|
*/
'store' => env('SESSION_STORE'),
/*
|--------------------------------------------------------------------------
| Session Sweeping Lottery
|--------------------------------------------------------------------------
|
| Some session drivers must manually sweep their storage location to get
| rid of old sessions from storage. Here are the chances that it will
| happen on a given request. By default, the odds are 2 out of 100.
|
*/
'lottery' => [2, 100],
/*
|--------------------------------------------------------------------------
| Session Cookie Name
|--------------------------------------------------------------------------
|
| Here you may change the name of the session cookie that is created by
| the framework. Typically, you should not need to change this value
| since doing so does not grant a meaningful security improvement.
|
*/
'cookie' => env(
'SESSION_COOKIE',
Str::slug(env('APP_NAME', 'laravel'), '_').'_session'
),
/*
|--------------------------------------------------------------------------
| Session Cookie Path
|--------------------------------------------------------------------------
|
| The session cookie path determines the path for which the cookie will
| be regarded as available. Typically, this will be the root path of
| your application, but you're free to change this when necessary.
|
*/
'path' => env('SESSION_PATH', '/'),
/*
|--------------------------------------------------------------------------
| Session Cookie Domain
|--------------------------------------------------------------------------
|
| This value determines the domain and subdomains the session cookie is
| available to. By default, the cookie will be available to the root
| domain and all subdomains. Typically, this shouldn't be changed.
|
*/
'domain' => env('SESSION_DOMAIN'),
/*
|--------------------------------------------------------------------------
| HTTPS Only Cookies
|--------------------------------------------------------------------------
|
| By setting this option to true, session cookies will only be sent back
| to the server if the browser has a HTTPS connection. This will keep
| the cookie from being sent to you when it can't be done securely.
|
*/
'secure' => env('SESSION_SECURE_COOKIE'),
/*
|--------------------------------------------------------------------------
| HTTP Access Only
|--------------------------------------------------------------------------
|
| Setting this value to true will prevent JavaScript from accessing the
| value of the cookie and the cookie will only be accessible through
| the HTTP protocol. It's unlikely you should disable this option.
|
*/
'http_only' => env('SESSION_HTTP_ONLY', true),
/*
|--------------------------------------------------------------------------
| Same-Site Cookies
|--------------------------------------------------------------------------
|
| This option determines how your cookies behave when cross-site requests
| take place, and can be used to mitigate CSRF attacks. By default, we
| will set this value to "lax" to permit secure cross-site requests.
|
| See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#samesitesamesite-value
|
| Supported: "lax", "strict", "none", null
|
*/
'same_site' => env('SESSION_SAME_SITE', 'lax'),
/*
|--------------------------------------------------------------------------
| Partitioned Cookies
|--------------------------------------------------------------------------
|
| Setting this value to true will tie the cookie to the top-level site for
| a cross-site context. Partitioned cookies are accepted by the browser
| when flagged "secure" and the Same-Site attribute is set to "none".
|
*/
'partitioned' => env('SESSION_PARTITIONED_COOKIE', false),
];

1
laravel/database/.gitignore vendored Executable file
View File

@ -0,0 +1 @@
*.sqlite*

View File

@ -0,0 +1,44 @@
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\User>
*/
class UserFactory extends Factory
{
/**
* The current password being used by the factory.
*/
protected static ?string $password;
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'name' => fake()->name(),
'email' => fake()->unique()->safeEmail(),
'email_verified_at' => now(),
'password' => static::$password ??= Hash::make('password'),
'remember_token' => Str::random(10),
];
}
/**
* Indicate that the model's email address should be unverified.
*/
public function unverified(): static
{
return $this->state(fn (array $attributes) => [
'email_verified_at' => null,
]);
}
}

View File

@ -0,0 +1,49 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
Schema::create('password_reset_tokens', function (Blueprint $table) {
$table->string('email')->primary();
$table->string('token');
$table->timestamp('created_at')->nullable();
});
Schema::create('sessions', function (Blueprint $table) {
$table->string('id')->primary();
$table->foreignId('user_id')->nullable()->index();
$table->string('ip_address', 45)->nullable();
$table->text('user_agent')->nullable();
$table->longText('payload');
$table->integer('last_activity')->index();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('users');
Schema::dropIfExists('password_reset_tokens');
Schema::dropIfExists('sessions');
}
};

View File

@ -0,0 +1,35 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('cache', function (Blueprint $table) {
$table->string('key')->primary();
$table->mediumText('value');
$table->integer('expiration');
});
Schema::create('cache_locks', function (Blueprint $table) {
$table->string('key')->primary();
$table->string('owner');
$table->integer('expiration');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('cache');
Schema::dropIfExists('cache_locks');
}
};

View File

@ -0,0 +1,57 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('jobs', function (Blueprint $table) {
$table->id();
$table->string('queue')->index();
$table->longText('payload');
$table->unsignedTinyInteger('attempts');
$table->unsignedInteger('reserved_at')->nullable();
$table->unsignedInteger('available_at');
$table->unsignedInteger('created_at');
});
Schema::create('job_batches', function (Blueprint $table) {
$table->string('id')->primary();
$table->string('name');
$table->integer('total_jobs');
$table->integer('pending_jobs');
$table->integer('failed_jobs');
$table->longText('failed_job_ids');
$table->mediumText('options')->nullable();
$table->integer('cancelled_at')->nullable();
$table->integer('created_at');
$table->integer('finished_at')->nullable();
});
Schema::create('failed_jobs', function (Blueprint $table) {
$table->id();
$table->string('uuid')->unique();
$table->text('connection');
$table->text('queue');
$table->longText('payload');
$table->longText('exception');
$table->timestamp('failed_at')->useCurrent();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('jobs');
Schema::dropIfExists('job_batches');
Schema::dropIfExists('failed_jobs');
}
};

View File

@ -0,0 +1,23 @@
<?php
namespace Database\Seeders;
use App\Models\User;
// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*/
public function run(): void
{
// User::factory(10)->create();
User::factory()->create([
'name' => 'Test User',
'email' => 'test@example.com',
]);
}
}

17
laravel/package.json Executable file
View File

@ -0,0 +1,17 @@
{
"private": true,
"type": "module",
"scripts": {
"build": "vite build",
"dev": "vite"
},
"devDependencies": {
"autoprefixer": "^10.4.20",
"axios": "^1.7.4",
"concurrently": "^9.0.1",
"laravel-vite-plugin": "^1.0",
"postcss": "^8.4.47",
"tailwindcss": "^3.4.13",
"vite": "^6.0"
}
}

33
laravel/phpunit.xml Executable file
View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="vendor/autoload.php"
colors="true"
>
<testsuites>
<testsuite name="Unit">
<directory>tests/Unit</directory>
</testsuite>
<testsuite name="Feature">
<directory>tests/Feature</directory>
</testsuite>
</testsuites>
<source>
<include>
<directory>app</directory>
</include>
</source>
<php>
<env name="APP_ENV" value="testing"/>
<env name="APP_MAINTENANCE_DRIVER" value="file"/>
<env name="BCRYPT_ROUNDS" value="4"/>
<env name="CACHE_STORE" value="array"/>
<!-- <env name="DB_CONNECTION" value="sqlite"/> -->
<!-- <env name="DB_DATABASE" value=":memory:"/> -->
<env name="MAIL_MAILER" value="array"/>
<env name="PULSE_ENABLED" value="false"/>
<env name="QUEUE_CONNECTION" value="sync"/>
<env name="SESSION_DRIVER" value="array"/>
<env name="TELESCOPE_ENABLED" value="false"/>
</php>
</phpunit>

6
laravel/postcss.config.js Executable file
View File

@ -0,0 +1,6 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};

29
laravel/public/index.php Executable file
View File

@ -0,0 +1,29 @@
<?php
use Illuminate\Http\Request;
define('LARAVEL_START', microtime(true));
function tomd($aData, $iType = 0) {
if (env("is_loc") == 1) {
echo "<pre>";
var_dump($aData);
if ($iType == 1) {
exit;
}
}
}
// Determine if the application is in maintenance mode...
if (file_exists($maintenance = __DIR__.'/../storage/framework/maintenance.php')) {
require $maintenance;
}
// Register the Composer autoloader...
require __DIR__.'/../vendor/autoload.php';
// Bootstrap Laravel and handle the request...
(require_once __DIR__.'/../bootstrap/app.php')
->handleRequest(Request::capture());

2
laravel/public/js/jquery.min.js vendored Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Some files were not shown because too many files have changed in this diff Show More