TrackRepository.php 15.2 KB
<?php

namespace App\Repositories;

use App\Helpers\Constants;
use App\Models\CrawlerListen;
use App\Models\Track;
use Sunra\PhpSimple\HtmlDomParser;
use Yangqi\Htmldom\Htmldom;

class TrackRepository extends BaseRepository
{
    public function __construct()
    {

    }

    /**
     * Lấy ds bài hát đã insert
     *
     * doanpv - 24/03/2020
     *
     * @param string $pluck_by_field
     * @param string $type
     * @param array $select_fields
     *
     * @return array
     */
    public function getTrackInserted($pluck_by_field='all', $type='original', array $select_fields)
    {
        if (count($select_fields) == 0) $select_fields = ['id', 'title', 'slug'];

        $query = Track::select($select_fields);

        if ($pluck_by_field == 'all') {
            return $query->get()->toArray();
        }

        switch ($type) {
            case 'upper':
                return $query->pluck($pluck_by_field)->map(function ($item){
                    return strtoupper($item);
                })->all();
                break;
            case 'lower':
                return $query->pluck($pluck_by_field)->map(function ($item){
                    return strtolower($item);
                })->all();
                break;
            default: return $query->pluck($pluck_by_field)->toArray();

        }
    }

    /**
     * Lấy ds bài hát chưa có ảnh đại diện (trường art: null)
     *
     * doanpv - 24/03/2020
     *
     * @return array
     */
    public function getTrackImageEmpty($limit=200)
    {
        $query = Track::select(['id', 'art', 'id_zing', 'id_nct', 'id_keeng', 'src_thumbnail_medium'])
            ->whereNull('art')
            ->whereNotNull('src_thumbnail_medium')
            ->take($limit);

        return $query->get()->toArray();
    }

    /**
     * Crawler thông tin bài hát từ url top 100: https://www.nhaccuatui.com/top100/top-100-nhac-tre.m3liaiy6vVsF.html
     * Nhưng URL này không lấy được link của bài hát và thời lượng
     * Sử dụng link dạng playlist của top 100 thì lấy được link và thời lượng
     * URL playlist của top 100: https://www.nhaccuatui.com/playlist/top-100-nhac-tre-hay-nhat-va.m3liaiy6vVsF.html?st=1
     * Sử dụng composer package "sunra/php-simple-html-dom-parser"
     *
     * @param $url
     * @return array
     */
    public function processNctGetTrackInfoFromTop100($url)
    {
        $tracks = [];
        $dom = getDom($url);

        /* Lấy tên bài hát ------------------------------------------------------------------------------------------ */
        $element_track_title = 'div.box_info_field h3.h3 a';
        foreach ($dom->find($element_track_title) as $data) {
            $tracks['title'][] = str_replace([], [], $data->innertext);
        }

        /* Lấy đường dẫn ảnh của bài hát ---------------------------------------------------------------------------- */
        $element_track_img = 'div.box_info_field a img';
        foreach ($dom->find($element_track_img) as $data) {
            $tracks['img'][] = str_replace([], [], $data->{"data-src"});
        }

        /* Lấy link bài hát ----------------------------------------------------------------------------------------- */
        $element_track_link = 'div.box_info_field h3.h3 a';
        foreach ($dom->find($element_track_link) as $data) {
            $link = str_replace([], [], $data->href);
            $tracks['link'][] = $link;
        }

        /* Lấy tên ca sĩ hát ---------------------------------------------------------------------------------------- */
        $element_track_singer = 'div.box_info_field h4.list_name_singer a';
        foreach ($dom->find($element_track_singer) as $data) {
            $tracks['singer'][] = str_replace([], [], $data->innertext);
        }

        /* Lấy url thông tin cá nhân ca sĩ -------------------------------------------------------------------------- */
        $element_singer_profile = 'div.box_info_field h4.list_name_singer a';
        foreach ($dom->find($element_singer_profile) as $data) {
            $tracks['url_profile'][] = str_replace([], [], $data->href);
        }

        /* Lấy ID dạng chuỗi của bài hát ---------------------------------------------------------------------------- */
        $element_track_id_str = 'div.box_song_action a.button_add_playlist';
        foreach ($dom->find($element_track_id_str) as $data) {
            $tracks['id_nct_str'][] = str_replace(['btnShowBoxPlaylist_', '</h2>'], ['', ''], $data->id);
        }

        /* Lấy ID dạng số của bài hát ------------------------------------------------------------------------------- */
        $element_track_id = 'div.box_info_field';
        $start = '<span class=\"export_listen\" id="NCTCounter__';
        $end = '">0<\/span>';
        $rule = "/$start(.*)$end/msU";
        foreach ($dom->find($element_track_id) as $data) {
            $data_crawler = str_replace(['<!--', '-->'], ['', ''], $data);
            preg_match($rule, $data_crawler, $result);
            if (is_array($result) && count($result) == 2) {
                $tracks['id_nct'][] = $result[1];
            }
        }

        /* Tổng hợp dữ liệu thành mảng ------------------------------------------------------------------------------ */
        $result = [];
        for($i=0; $i < count($tracks['title']); $i++) {
            $result[$i]['id_nct_str'] = $tracks['id_nct_str'][$i];
            $result[$i]['id_nct'] = $tracks['id_nct'][$i];
            $result[$i]['title'] = $tracks['title'][$i];
            $result[$i]['link'] = $tracks['link'][$i];
            $result[$i]['img'] = $tracks['img'][$i];
        }

        return $result;
    }

    /**
     * Lấy link và thời lượng của bài hát từ link playlist của top 100
     * URL: https://www.nhaccuatui.com/playlist/top-100-nhac-tre-hay-nhat-va.m3liaiy6vVsF.html?st=1
     * Sử dụng composer package "yangqi/htmldom"
     *
     * @param $url
     * @return array
     */
    public function processNctGetTrackInfoFromTop100Playlist($url)
    {
        $tracks = [];
        $dom = new Htmldom($url);

        /* Lấy ID dạng chuỗi của bài hát ---------------------------------------------------------------------------- */
        $element_track_id_str = 'li';
        foreach ($dom->find($element_track_id_str) as $data) {
            if (isset($data->key)) {
                $tracks['id_nct_str'][] = str_replace([], [], $data->key);
            }
        }

        /* Lấy link bài hát ----------------------------------------------------------------------------------------- */
        $element_track_link = 'li a';
        foreach ($dom->find($element_track_link) as $data) {
            if (isset($data->class) && $data->class == 'button_new_window') {
                $tracks['link'][] = str_replace([], [], $data->href);
            }
        }

        /* Lấy ID dạng số ------------------------------------------------------------------------------------------- */
        $element_track_id = 'li span';
        foreach ($dom->find($element_track_id) as $data) {
            if (isset($data->id) && isset($data->class) && $data->class == 'icon_listen') {
                $tracks['id_nct'][] = str_replace(['NCTCounter_sg_', 'NCTCounter_pn_'], ['', ''], $data->id);
            }
        }

        /* Lấy thời gian của bài hát từ thẻ <meta content="PT3M51S" itemprop="duration" /> -------------------------- */
        $element_track_duration = 'li meta';
        foreach ($dom->find($element_track_duration) as $data) {
            if (isset($data->content) && isset($data->itemprop) && $data->itemprop == 'duration') {
                $duration_str = str_replace(['PT', 'M', 'S'], ['', ':', ''], $data->content);
                $duration_array = explode(':', $duration_str);
                if (count($duration_array) == 2) {
                    $tracks['duration'][] = intval($duration_array[0])*60 + intval($duration_array[1]);
                } else {
                    $tracks['duration'][] = 0;
                }
            }
        }

        /* Tổng hợp dữ liệu thành mảng ------------------------------------------------------------------------------ */
        $result = [];
        for($i=0; $i < count($tracks['id_nct_str']); $i++) {
            $result[$i]['id_nct_str'] = $tracks['id_nct_str'][$i];
            $result[$i]['id_nct'] = $tracks['id_nct'][$i];
            $result[$i]['link'] = $tracks['link'][$i];
            $result[$i]['duration'] = $tracks['duration'][$i];
        }

        return $result;
    }

    /**
     * Hàm lấy ds bài hát chưa có ảnh sau khi lấy từ NCT về
     *
     * @return array
     */
    public function getNctTrackLinkEmpty()
    {
        $query = Track::select(['id', 'link_nct', 'id_zing', 'id_nct', 'id_keeng', 'src_thumbnail_medium'])
            ->whereNull('art')
            ->whereNotNull('src_thumbnail_medium');

        return $query->get()->toArray();
    }

    public function processNhacVnGetTrackInfoFromTop20($url)
    {
        $tracks = [];
        $dom = getDom($url);

        /* Lấy ID bài hát ------------------------------------------------------------------------------------------ */
        $element_track_id = 'ul li a.addsongtmpl';
        foreach ($dom->find($element_track_id) as $data) {
            $tracks['id'][] = str_replace([], [], $data->id);
        }

        /* Lấy tên bài hát ------------------------------------------------------------------------------------------ */
        $element_track_title = 'h3.over-text a';
        foreach ($dom->find($element_track_title) as $data) {
            $tracks['title'][] = str_replace([], [], $data->innertext);
        }

        /* Lấy đường dẫn ảnh của bài hát ---------------------------------------------------------------------------- */
        $element_track_img = 'ul.bxh_song_list li a img';
        foreach ($dom->find($element_track_img) as $data) {
            $tracks['img'][] = str_replace([], [], $data->src);
        }

        /* Lấy link bài hát ----------------------------------------------------------------------------------------- */
        $element_track_link = 'h3.over-text a';
        foreach ($dom->find($element_track_link) as $data) {
            $link = str_replace([], [], $data->href);
            $tracks['link'][] = $link;
        }

        /* Lấy tên ca sĩ hát ---------------------------------------------------------------------------------------- */
        $element_track_singer = 'ul.bxh_song_list li a img';
        foreach ($dom->find($element_track_singer) as $data) {
            $tracks['singer'][] = str_replace([], [], $data->alt);
        }

        /* Lấy url thông tin cá nhân ca sĩ -------------------------------------------------------------------------- */
        $element_singer_list = 'p.over-text a.singer';
        foreach ($dom->find($element_singer_list) as $data) {
            $tracks['singer_list'][] = [
                'name' => str_replace([], [], $data->innertext),
                'url' => str_replace([], [], $data->href)
            ];
        }

        /* Tổng hợp dữ liệu thành mảng ------------------------------------------------------------------------------ */
        $result = [];
        for($i=0; $i < count($tracks['title']); $i++) {
            $result[$i]['id_nhacvn'] = $tracks['id'][$i];
            $result[$i]['title'] = $tracks['title'][$i];
            $result[$i]['img'] = $tracks['img'][$i];
            $result[$i]['link'] = $tracks['link'][$i];
            $result[$i]['singer'] = $tracks['singer'][$i];
        }

        return $result;
    }

    /**
     * Lấy ds bài hát chưa lấy lượt nghe trong ngày theo từng hệ thống nhạc
     * Bài nào đã lấy rồi thì sẽ ko lấy nữa
     * Mỗi lần quét 500 bài cho đến hết
     *
     * @param string $src
     * @param $crawlered
     * @param int $limit
     *
     * @return array
     */
    public function getTrackBySource($src='zing', $crawlered, $limit = Constants::CRAWLER_LISTEN_LIMIT)
    {
        $query = Track::select(['id', 'id_zing', 'id_nct', 'id_nhacvn', 'id_keeng', 'title']);

        if (is_array($crawlered) && count($crawlered) > 0) {
            $query->whereNotIn('id', $crawlered);
        }

        switch ($src) {
            case 'zing': $query->whereNotNull('id_zing')->where('id_zing', '<>', ''); break;
            case 'nct': $query->whereNotNull('id_nct')->where('id_nct', '<>', ''); break;
            case 'nhacvn': $query->whereNotNull('id_nhacvn')->where('id_nhacvn', '<>', ''); break;
            case 'keeng': $query->whereNotNull('id_keeng')->where('id_keeng', '<>', ''); break;
        }

        if ($limit > 0) {
            $query->take($limit);
        }

        return $query->get()->toArray();

    }

    /**
     * Lấy ds những bài hát đã lấy lượt nghe trong ngày, để lần quét sau sẽ bỏ qua
     * Mỗi lần quét 300-500 bài trong tracks và bỏ qua những bài đã lấy lượt nghe trong ngày ở bảng crawler_listens
     * Lấy những bài hát có lượng nghe trong ngày = 0 để cập nhật lại
     * Có thể tùy biến thêm ($is_update_all): cập nhật toàn bộ hoặc chỉ cập nhập những bài chưa lấy lượt nghe
     *
     * @param string $src
     * @param boolean $is_update_all
     *
     * @return array
     */
    public function getCrawlerListenInserted($src='zing', $is_update_all=false)
    {
        $min_date = date('Y-m-d 00:00:00');
        $max_date = date('Y-m-d 23:59:59');

        if ($is_update_all) {
            $min_date = date('Y-m-d 00:00:00', time() + 86400);
            $max_date = date('Y-m-d 23:59:59', time() + 86400);
        }

        $query = CrawlerListen::select(['id', 'track_id']);

        switch ($src) {
            case 'zing':
                $query->where('zing_crawler_at', '>=', $min_date)
                    ->where('zing_crawler_at', '<=', $max_date)
                    ->where('today_zing', '>' ,0);
                break;
            case 'nct':
                $query->where('nct_crawler_at', '>=', $min_date)
                    ->where('nct_crawler_at', '<=', $max_date)
                    ->where('today_nct', '>' ,0);
                    break;
            case 'nhacvn':
                $query->where('nhacvn_crawler_at', '>=', $min_date)
                    ->where('nhacvn_crawler_at', '<=', $max_date)
                    ->where('today_nhacvn', '>' ,0);
                break;
            case 'keeng':
                $query->where('keeng_crawler_at', '>=', $min_date)
                    ->where('keeng_crawler_at', '<=', $max_date)
                    ->where('today_keeng', '>' ,0);
                break;
        }

        $result = $query->get();

        return collect($result)->map(function ($item) { return $item->track_id; })->all();
    }

    public function getCrawlerListenNotYetMoved($max_date=null)
    {
        if (empty($max_date)) {
            $max_date = date('Y-m-d 00:00:00');
        } else {
            $max_date = date('Y-m-d 23:59:59', strtotime($max_date));
        }

        return CrawlerListen::select('*')
            ->where('date_moved_at', '<=', $max_date)
            ->orWhereNull('date_moved_at')
            ->take(5000)
            ->get();
    }


}