支持主动导入弹幕
This commit is contained in:
parent
cece95a5a4
commit
474b97a40a
71
app/Http/Controllers/DanmakuConstructController.php
Normal file
71
app/Http/Controllers/DanmakuConstructController.php
Normal file
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\VideoDanmakus;
|
||||
use App\Models\Videos;
|
||||
use App\Util\DanmakuUtil;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Controller as BaseController;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class DanmakuConstructController extends BaseController
|
||||
{
|
||||
public function page(Request $request)
|
||||
{
|
||||
$view = view("danmaku.construct.batch_import");
|
||||
if ($request->has("video_bvid")) {
|
||||
$bvid = $request->get("video_bvid");
|
||||
$video = Videos::query()->where("bvid", "=", $bvid)->first();
|
||||
if ($video == null) {
|
||||
$view->withErrors([
|
||||
"video_bvid" => "系统无此对应视频",
|
||||
]);
|
||||
} else {
|
||||
$request->session()->flashInput([
|
||||
"video_bvid" => $bvid
|
||||
]);
|
||||
}
|
||||
}
|
||||
return $view;
|
||||
}
|
||||
|
||||
public function do_import(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'video_bvid' => ['required'],
|
||||
'platform_id' => ['required', 'int'],
|
||||
'file' => ['required']
|
||||
]);
|
||||
$payload = $request->only(["video_bvid", "platform_id"]);
|
||||
$files = $request->file("file");
|
||||
if (!is_array($files)) {
|
||||
$files = [$files];
|
||||
}
|
||||
$video = Videos::query()->where("bvid", "=", $payload["video_bvid"])->first();
|
||||
if ($video == null) {
|
||||
return back()->withInput()->withErrors([
|
||||
"video_bvid" => "系统无此对应视频",
|
||||
]);
|
||||
}
|
||||
foreach ($files as $file) {
|
||||
$danmakus = DanmakuUtil::parse_danmaku($file->getFileInfo());
|
||||
DB::beginTransaction();
|
||||
try {
|
||||
foreach ($danmakus as &$danmaku) {
|
||||
$danmaku['video_bvid'] = $video->bvid;
|
||||
$danmaku['platform_id'] = $payload["platform_id"];
|
||||
unset($danmaku);
|
||||
}
|
||||
VideoDanmakus::insert($danmakus);
|
||||
DB::commit();
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
return back()->withInput()->withErrors([
|
||||
"file" => "文件导入异常:" . $e->getMessage(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
return redirect("/danmakus/" . $payload["video_bvid"]);
|
||||
}
|
||||
}
|
@ -6,8 +6,14 @@ use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class VideoDanmakus extends Model
|
||||
{
|
||||
protected $guarded = [];
|
||||
protected $table = "video_danmakus";
|
||||
protected $dateFormat = 'U';
|
||||
public $timestamps = false;
|
||||
protected $casts = [
|
||||
'created_at' => 'datetime:Y-m-d H:i:s',
|
||||
];
|
||||
protected $fillable = ["from", "from_mid", "content"];
|
||||
public function video(): \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Videos::class, "video_bvid", "bvid");
|
||||
|
32
app/Util/DanmakuUtil.php
Normal file
32
app/Util/DanmakuUtil.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Util;
|
||||
|
||||
use SplFileInfo;
|
||||
|
||||
class DanmakuUtil
|
||||
{
|
||||
public static function parse_danmaku(SplFileInfo $file): array
|
||||
{
|
||||
$document = new \DOMDocument();
|
||||
$document->load($file->getRealPath());
|
||||
$danmaku_items = $document->getElementsByTagName("d");
|
||||
$result = [];
|
||||
/** @var \DOMNode $item */
|
||||
foreach ($danmaku_items as $item) {
|
||||
$paramsNode = $item->attributes->getNamedItem("p");
|
||||
$param_list = mb_split(",", $paramsNode->value);
|
||||
if (sizeof($param_list) < 7) {
|
||||
throw new \Exception("弹幕格式异常");
|
||||
}
|
||||
$userNode = $item->attributes->getNamedItem("user");
|
||||
$result[] = [
|
||||
"from" => $userNode->value,
|
||||
"from_mid" => $param_list[6],
|
||||
"content" => $item->textContent,
|
||||
"created_at" => intval($param_list[4])/1000,
|
||||
];
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": "^7.3|^8.0",
|
||||
"ext-dom": "*",
|
||||
"ext-json": "*",
|
||||
"ext-mbstring": "*",
|
||||
"fruitcake/laravel-cors": "^2.0",
|
||||
|
@ -21,7 +21,7 @@
|
||||
<a class="{{ (request()->is('danmakus', 'danmakus/*')) ? 'bg-gray-900 text-white' : 'text-gray-700 hover:bg-gray-700 hover:text-white' }} px-3 py-2 rounded-md text-sm font-medium" href="/danmakus">稿件查询</a>
|
||||
<a class="{{ (request()->is('programs', '/', 'programs/*/video')) ? 'bg-gray-900 text-white' : 'text-gray-700 hover:bg-gray-700 hover:text-white' }} px-3 py-2 rounded-md text-sm font-medium" href="/programs" title="数据不全,待补充">节目查询</a>
|
||||
@auth("web")
|
||||
<a class="{{ (request()->is('programs/construct', 'programs/construct/*')) ? 'bg-gray-900 text-white' : 'text-gray-700 hover:bg-gray-700 hover:text-white' }} px-3 py-2 rounded-md text-sm font-medium" href="/programs/construct">节目建设</a>
|
||||
<a class="{{ (request()->is('construct/*')) ? 'bg-gray-900 text-white' : 'text-gray-700 hover:bg-gray-700 hover:text-white' }} px-3 py-2 rounded-md text-sm font-medium" href="/construct/programs">节目建设</a>
|
||||
@endauth
|
||||
</div>
|
||||
</div>
|
||||
@ -50,7 +50,7 @@
|
||||
<a class="{{ (request()->is('danmakus', 'danmakus/*')) ? 'bg-gray-900 text-white' : 'text-gray-700 hover:bg-gray-700 hover:text-white' }} block px-3 py-2 rounded-md text-base font-medium" href="/danmakus">稿件查询</a>
|
||||
<a class="{{ (request()->is('programs', '/', 'programs/*/video')) ? 'bg-gray-900 text-white' : 'text-gray-700 hover:bg-gray-700 hover:text-white' }} block px-3 py-2 rounded-md text-base font-medium" href="/programs" title="数据不全,待补充">节目查询</a>
|
||||
@auth("web")
|
||||
<a class="{{ (request()->is('programs/construct', 'programs/construct/*')) ? 'bg-gray-900 text-white' : 'text-gray-700 hover:bg-gray-700 hover:text-white' }} block px-3 py-2 rounded-md text-base font-medium" href="/programs/construct">节目建设</a>
|
||||
<a class="{{ (request()->is('construct/*')) ? 'bg-gray-900 text-white' : 'text-gray-700 hover:bg-gray-700 hover:text-white' }} block px-3 py-2 rounded-md text-base font-medium" href="/construct/programs">节目建设</a>
|
||||
@endauth
|
||||
</div>
|
||||
</div>
|
||||
|
35
resources/views/danmaku/construct/batch_import.blade.php
Normal file
35
resources/views/danmaku/construct/batch_import.blade.php
Normal file
@ -0,0 +1,35 @@
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>弹幕导入</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link href="{{ mix('/css/app.css') }}" rel="stylesheet"/>
|
||||
</head>
|
||||
<body>
|
||||
@include("common.header")
|
||||
<form class="w-full lg:w-1/2 lg:ml-6 border-2" action="" method="post" enctype="multipart/form-data">
|
||||
@csrf
|
||||
<label class="block my-2">
|
||||
BVID
|
||||
<input class="form-input border-0 border-b-2 w-full" type="text" name="video_bvid" required value="{{ old('video_bvid') }}">
|
||||
</label>
|
||||
<label class="block my-2">
|
||||
弹幕类型
|
||||
<span class="block form-input border-0 border-b-2 w-full">
|
||||
<input type="radio" value="1" name="platform_id" checked>B站
|
||||
<input type="radio" value="2" name="platform_id" disabled>西瓜
|
||||
<input type="radio" value="3" name="platform_id" disabled>抖音
|
||||
</span>
|
||||
</label>
|
||||
<label class="block my-2">
|
||||
弹幕文件
|
||||
<input class="form-input border-0 border-b-2 w-full" multiple type="file" name="file[]" accept="text/xml">
|
||||
</label>
|
||||
@include("common.form_error")
|
||||
<div class="block my-2 text-center">
|
||||
<input class="px-6 py-2 inline-block rounded-full bg-cyan-600 text-white" type="submit">
|
||||
</div>
|
||||
</form>
|
||||
@include("common.footer")
|
||||
</body>
|
||||
</html>
|
@ -68,6 +68,9 @@
|
||||
@if(sizeof($video_pivots) === 0 && $comment)
|
||||
<a href="{{ url(route("program.construct.from_comment", ["comment"=>$comment->id])) }}" class="px-6 py-2 inline-block rounded-full bg-cyan-600 text-white">一键导入评论中的节目单</a>
|
||||
@endif
|
||||
@if($video->danmakus->count() === 0)
|
||||
<a href="{{ url(route("danmaku.construct.batch_import", ["video_bvid"=>$video->bvid])) }}" class="px-6 py-2 inline-block rounded-full bg-cyan-600 text-white">导入直播弹幕</a>
|
||||
@endif
|
||||
@endauth
|
||||
@include("common.footer")
|
||||
</body>
|
||||
|
@ -31,8 +31,10 @@ Route::post("/login/webauthn/", ["\\App\\Http\\Controllers\\UserWebAuthnControll
|
||||
Route::get('/register', ["\\App\\Http\\Controllers\\UserController", "register_page"])->name("register");
|
||||
Route::post('/register', ["\\App\\Http\\Controllers\\UserController", "register"])->name("register.submit");
|
||||
Route::get('/logout', ["\\App\\Http\\Controllers\\UserController", "logout"])->name("logout");
|
||||
// 弹幕建设
|
||||
// 建设部分
|
||||
Route::prefix("/programs/construct")->middleware("auth:web")->group(function (Router $router) {
|
||||
Route::prefix("/construct")->middleware("auth:web")->group(function (Router $router) {
|
||||
Route::prefix("/programs")->group(function (Router $router) {
|
||||
// 节目建设
|
||||
$router->get('/', ["\\App\\Http\\Controllers\\ProgramConstructController","index"])->name("program.construct.list");
|
||||
$router->get('/add', ["\\App\\Http\\Controllers\\ProgramConstructController","add"])->name("program.construct.add");
|
||||
@ -61,6 +63,12 @@ Route::prefix("/programs/construct")->middleware("auth:web")->group(function (Ro
|
||||
$router->get('/append/broadcast_list', ["\\App\\Http\\Controllers\\ProgramAppendConstructController", "broadcast_list"])->name("program.construct.append.broadcast_list");
|
||||
$router->get('/append/{append}', ["\\App\\Http\\Controllers\\ProgramAppendConstructController","edit"])->name("program.construct.append.edit");
|
||||
$router->post('/append/{append}', ["\\App\\Http\\Controllers\\ProgramAppendConstructController","submit"])->name("program.construct.append.submit");
|
||||
});
|
||||
// 弹幕维护
|
||||
Route::prefix("/danmaku")->group(function (Router $router) {
|
||||
$router->get("/batch_import", ["\\App\\Http\\Controllers\\DanmakuConstructController", "page"])->name("danmaku.construct.batch_import.page");
|
||||
$router->post("/batch_import", ["\\App\\Http\\Controllers\\DanmakuConstructController", "do_import"])->name("danmaku.construct.batch_import");
|
||||
});
|
||||
});
|
||||
Route::prefix("/user")->middleware("auth:web")->group(function (Router $router) {
|
||||
$router->post("/webauthn/options", ["\\App\\Http\\Controllers\\UserWebAuthnController", "register_options"])->name("user.webauthn.bind.options");
|
||||
|
Loading…
x
Reference in New Issue
Block a user