Working interface and parsed symfony cast data to a database.

This commit is contained in:
Krzysztof Płaczek
2022-08-23 08:09:14 +02:00
parent 119b94470f
commit a92c75c1dd
22 changed files with 488 additions and 224 deletions

View File

@@ -2,8 +2,6 @@
namespace App\Http\Controllers;
use App\Http\SymfonyCastDl\HtmlParser;
use App\Http\SymfonyCastDl\SymfonyCastDlService;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
@@ -13,8 +11,4 @@ class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
public function index(HtmlParser $htmlParser)
{
$service = new SymfonyCastDlService($htmlParser);
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace App\Http\Controllers;
use App\Http\SymfonyCastDl\HtmlParser;
use App\Http\SymfonyCastDl\SymfonyCastDlService;
use App\Models\Chapter;
use App\Models\Course;
use Illuminate\View\View;
class CourseController extends Controller
{
public function index(Course $course): View
{
return view('course.index', compact('course'));
}
public function chapter(Chapter $chapter, HtmlParser $htmlParser)
{
$service = new SymfonyCastDlService($htmlParser);
$service->videoSize($chapter);
dd($chapter->toArray());
}
}

View File

@@ -0,0 +1,23 @@
<?php
namespace App\Http\Controllers;
use App\Http\SymfonyCastDl\HtmlParser;
use App\Http\SymfonyCastDl\SymfonyCastDlService;
use App\Models\Course;
use Illuminate\Http\Request;
class Index extends Controller
{
public function index()
{
$courses = Course::with('chapters')->withCount('chapters')->get();
return view('index', compact(['courses']));
}
public function download(HtmlParser $htmlParser)
{
$service = new SymfonyCastDlService($htmlParser);
$service->getInfo();
}
}

View File

@@ -2,8 +2,12 @@
namespace App\Http\SymfonyCastDl;
use App\Models\Chapter;
use App\Models\Course;
use Carbon\Carbon;
use DiDom\Document;
use GuzzleHttp\Psr7\Response;
use Illuminate\Support\Collection;
class HtmlParser
{
@@ -13,36 +17,55 @@ class HtmlParser
return $document->first('input[name="_csrf_token"]')->attr('value');
}
public function getCourses(Response $response): array
public function getCourses(Response $response): Collection
{
$courses = [];
$courses = new Collection();
$document = new Document($response->getBody()->getContents());
foreach ($document->find('div.js-course-item') as $courseItem) {
$course = [];
$course['name'] = $courseItem->first('h3')->text();
$course['link'] = $courseItem->first('a')->attr('href');
$course['status'] = $courseItem->attr('data-status');
$course['chapter-count'] = $courseItem->attr('data-chapter-count');
$course['times-watched'] = $courseItem->attr('data-times-watched');
$courses[] = $course;
$courseId = $courseItem->attr('data-id');
$course = Course::firstOrNew(['course_id' => $courseId]);
$course->name = $courseItem->first('h3')->text();
$course->thumbnail = $courseItem->first('img.course-list-item-img')->attr('src');
$course->link = $courseItem->first('a')->attr('href');
$course->status = $courseItem->attr('data-status');
$course->course_id = $courseItem->attr('data-id');
$course->numberofchapters = $courseItem->attr('data-chapter-count');
$course->timeswatched = $courseItem->attr('data-times-watched');
$course->published_at = $courseItem->attr('data-date') > 0 ? Carbon::createFromTimestamp(
$courseItem->attr('data-date')
) : null;
$courses->add($course);
}
return $courses;
}
public function getCourseDetails(Response $response): array
public function getCourseDetails(Response $response, int $courseId): Collection
{
$document = new Document($response->getBody()->getContents());
$info = ['chapters' => []];
foreach ($document->find('ul.chapter-list li') as $chapter) {
$info['chapters'][] = [
'link' => $chapter->first('a')->attr('href'),
'title' => preg_replace('/\v(?:[\v\h]+)/', '', $chapter->first('.col')->text()),
'duration' => $chapter->first('.length-styling')->text(),
];
$chapters = new Collection();
$chapterId = 0;
foreach ($document->find('ul.chapter-list li') as $chapterItem) {
if ($chapterItem->first('.col')) {
$chapterId++;
// if(!$chapterItem->first('.length-styling')){
// dd($chapterItem->html());
// }
$chapter = Chapter::firstOrNew(['course_id' => $courseId, 'order' => $chapterId]);
$chapter->duration = $chapterItem->first('.length-styling')?->text();
$chapter->order = $chapterId;
$chapter->course_id = $courseId;
$chapter->link = config('symfonycast.base_url') . $chapterItem->first('a')->attr('href');
$chapter->video_link = config('symfonycast.base_url') . $chapterItem->first('a')->attr(
'href'
) . '/download/video';
$chapter->title = preg_replace('/\v(?:[\v\h]+)/', '', $chapterItem->first('.col')->text());
$chapter->video_size = 0;
$chapters->add($chapter);
}
}
return $info;
return $chapters;
}
}

View File

@@ -2,39 +2,64 @@
namespace App\Http\SymfonyCastDl;
use App\Models\Chapter;
use App\Models\Course;
use GuzzleHttp\TransferStats;
use DiDom\Document;
use GuzzleHttp\Client;
class SymfonyCastDlService
{
public function __construct(HtmlParser $htmlParser)
public Client $client;
public function __construct(public HtmlParser $htmlParser)
{
$client = new Client([
'base_uri' => "https://symfonycasts.com",
$this->client = new Client([
'base_uri' => config('symfonycast.base_url'),
'cookies' => true
]);
$response = $client->get('login');
$response = $this->client->get('login');
$token = $htmlParser->getCsrfToken($response);
$response = $client->post('login', [
$response = $this->client->post('login', [
'form_params' => [
// 'email' => 'krzysiej@gmail.com',
// 'password' => '',
'email' => config('symfonycast.login'),
'password' => config('symfonycast.password'),
'_csrf_token' => $token
],
'on_stats' => function (TransferStats $stats) use (&$currentUrl) {
$currentUrl = $stats->getEffectiveUri();
}
]);
}
$coursePage = $client->get('courses/filtering');
// dump($htmlParser->getCourses($coursePage));
public function getInfo()
{
$coursePage = $this->client->get('courses/filtering');
$singleCoursePage = $client->get('screencast/api-platform');
dd($htmlParser->getCourseDetails($singleCoursePage));
$courses = $this->htmlParser->getCourses($coursePage);
$courses->each(fn($course) => $course->save());
$singleCoursePage = $this->client->get($courses[3]->link);
/** @var Course $course */
foreach ($courses as $course) {
$singleCoursePage = $this->client->get($course->link);
$chapters = $this->htmlParser->getCourseDetails($singleCoursePage, $course->id);
$chapters->each(fn($chapter) => $this->videoSize($chapter)->save());
}
}
public function videoSize(Chapter $chapter): Chapter
{
try {
$response = $this->client->head($chapter->video_link);
if ($response->hasHeader('Content-Length')) {
$chapter->video_size = $response->getHeader('Content-Length')[0];
}
} catch (\GuzzleHttp\Exception\ClientException $exception) {
}
return $chapter;
}
}