278 lines
14 KiB
C#
278 lines
14 KiB
C#
using Dapper;
|
||
using Dapper.Contrib.Extensions;
|
||
using Newtonsoft.Json;
|
||
using NPOI.XSSF.UserModel;
|
||
using Org.BouncyCastle.Asn1.Ocsp;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Data.SqlClient;
|
||
using System.Diagnostics;
|
||
using System.Linq;
|
||
using System.Threading;
|
||
using System.Threading.Tasks;
|
||
using System.Text;
|
||
using System.Web;
|
||
using static DbTableClass;
|
||
using Org.BouncyCastle.Crypto.Operators;
|
||
using System.Globalization;
|
||
|
||
public class youtubeUpdateClass : IHostedService, IDisposable
|
||
{
|
||
static Timer _timer;
|
||
private int execCount = 0;
|
||
DbConn dbConn = new DbConn();
|
||
SqlConnection conn = new SqlConnection(GlobalClass.appsettings("ConnectionStrings:SQLConnectionString"));
|
||
|
||
public youtubeUpdateClass() { }
|
||
|
||
public Task StartAsync(CancellationToken cancellationToken)
|
||
{
|
||
_timer = new Timer(DoWork, null,
|
||
TimeSpan.Zero,
|
||
TimeSpan.FromSeconds(60 * 60));
|
||
return Task.CompletedTask;
|
||
}
|
||
|
||
public async void DoWork(object state) {
|
||
conn.Execute("insert into schedule (schedule_type, schedule_log) values ('YouTube', '執行DoWork')");
|
||
|
||
//利用 Interlocked 計數防止重複執行
|
||
Interlocked.Increment(ref execCount);
|
||
if (execCount == 1) {
|
||
conn.Execute("insert into schedule (schedule_type, schedule_log) values ('YouTube', '執行DoWork,execCount == 1時執行更新工作')");
|
||
|
||
//撈出Youtube頻道清單
|
||
List<kolMedia> kolMedias = conn.Query<kolMedia>("select * from kolMedia where option_uid = 'media' and optionItem_uid = 'media003' ").ToList();
|
||
|
||
foreach(kolMedia mediaItem in kolMedias)
|
||
{
|
||
string overDate = DateTime.Now.AddDays(int.Parse(GlobalClass.appsettings("UpdateByDay")) * -1).ToString("yyyy/MM/dd HH:mm:ss");
|
||
|
||
updateLog objLog = conn.QueryFirstOrDefault<updateLog>("select * from updateLog where updateLog_type = 'YouTube' and updateLog_result = 'success' and updateLog_kol_uid = @kol_uid and updateLog_kolMedia_uid = @kolMedia_uid and updateLog_updateTime >= @overDate ", new { kol_uid = mediaItem.kol_uid, kolMedia_uid = mediaItem.kolMedia_uid, overDate = overDate });
|
||
|
||
if (objLog == null) {
|
||
|
||
|
||
//撈取youtube帳號訂閱數
|
||
string youtubeChannelsApi = "https://www.googleapis.com/youtube/v3/channels?part=statistics,snippet,contentDetails&forHandle=" + mediaItem.kolMedia_accountName + "&key=" + GlobalClass.appsettings("GoogleKey");
|
||
string channelsStatus = "";
|
||
string channel_id = "";
|
||
using (var httpClient = new HttpClient())
|
||
{
|
||
using (var response = await httpClient.GetAsync(youtubeChannelsApi))
|
||
{
|
||
channelsStatus = await response.Content.ReadAsStringAsync();
|
||
}
|
||
}
|
||
|
||
dynamic channelsObj;
|
||
channelsObj = JsonConvert.DeserializeObject(channelsStatus);
|
||
|
||
if (channelsObj.items != null)
|
||
{
|
||
channel_id = channelsObj.items[0].id;
|
||
|
||
string subscriberCount = channelsObj.items[0].statistics.subscriberCount;
|
||
|
||
mediaItem.kolMedia_fansNum = (int)channelsObj.items[0].statistics.subscriberCount;
|
||
|
||
string youtube_uid = GlobalClass.CreateRandomCode(32);
|
||
|
||
youtube newYoutube = new youtube();
|
||
newYoutube.youtube_uid = youtube_uid;
|
||
newYoutube.kol_uid = mediaItem.kol_uid;
|
||
newYoutube.kolMedia_uid = mediaItem.kolMedia_uid;
|
||
newYoutube.youtube_account = mediaItem.kolMedia_accountName;
|
||
newYoutube.youtube_name = channelsObj.items[0].snippet.title;
|
||
newYoutube.youtube_photo = channelsObj.items[0].snippet.thumbnails.high.url;
|
||
newYoutube.youtube_revoke = "N";
|
||
newYoutube.youtube_subscriberCount = (int)channelsObj.items[0].statistics.subscriberCount;
|
||
newYoutube.youtube_viewCount = (int)channelsObj.items[0].statistics.viewCount;
|
||
newYoutube.youtube_json = channelsStatus;
|
||
|
||
//取得上傳影片的playlist id
|
||
string playlist_id = channelsObj.items[0].contentDetails.relatedPlaylists.uploads;
|
||
|
||
string youtubePlaylistApi = "https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&maxResults=5&key=" + GlobalClass.appsettings("GoogleKey") + "&playlistId=" + playlist_id;
|
||
string youtubePlaylistJson = "";
|
||
|
||
using (var httpClient = new HttpClient())
|
||
{
|
||
using (var response = await httpClient.GetAsync(youtubePlaylistApi))
|
||
{
|
||
youtubePlaylistJson = await response.Content.ReadAsStringAsync();
|
||
}
|
||
}
|
||
|
||
|
||
|
||
try
|
||
{
|
||
dynamic youtubePlaylistObj;
|
||
youtubePlaylistObj = JsonConvert.DeserializeObject(youtubePlaylistJson);
|
||
string videoIdList = "";
|
||
|
||
foreach (var item in youtubePlaylistObj.items)
|
||
{
|
||
videoIdList += item.snippet.resourceId.videoId + ",";
|
||
}
|
||
|
||
videoIdList = videoIdList.TrimEnd(',');
|
||
|
||
if (videoIdList == "")
|
||
{
|
||
updateLog failedLog = new updateLog();
|
||
failedLog.updateLog_text = "此Youtube帳號 " + mediaItem.kolMedia_accountName + "(" + mediaItem.kolMedia_displayName + ") Google Youtube Data Api 的Video數量 回傳0個!";
|
||
failedLog.updateLog_kolMedia_uid = mediaItem.kolMedia_uid;
|
||
failedLog.updateLog_kolMedia_accountName = mediaItem.kolMedia_accountName;
|
||
failedLog.updateLog_kolMedia_displayName = mediaItem.kolMedia_displayName;
|
||
failedLog.updateLog_kol_uid = mediaItem.kol_uid;
|
||
failedLog.updateLog_type = "YouTube";
|
||
failedLog.updateLog_result = "failed";
|
||
|
||
conn.Insert(failedLog);
|
||
}
|
||
else
|
||
{
|
||
string youtubeVideoApi = "https://www.googleapis.com/youtube/v3/videos?part=statistics,snippet&key=" + GlobalClass.appsettings("GoogleKey") + "&id=" + videoIdList;
|
||
string youtubeVideoJson = "";
|
||
|
||
using (var httpClient = new HttpClient())
|
||
{
|
||
using (var response = await httpClient.GetAsync(youtubeVideoApi))
|
||
{
|
||
youtubeVideoJson = await response.Content.ReadAsStringAsync();
|
||
}
|
||
}
|
||
|
||
dynamic youtubeVideoObj;
|
||
youtubeVideoObj = JsonConvert.DeserializeObject(youtubeVideoJson);
|
||
int totalViewNum = 0;
|
||
int videosNum = 0;
|
||
List<youtubeDetail> youtubeDetailList = new List<youtubeDetail>();
|
||
|
||
foreach (var item in youtubeVideoObj.items)
|
||
{
|
||
|
||
|
||
try
|
||
{
|
||
totalViewNum += (int)item.statistics.viewCount;
|
||
videosNum++;
|
||
youtubeDetail objDetail = new youtubeDetail();
|
||
objDetail.youtube_uid = youtube_uid;
|
||
objDetail.youtubeDetail_uid = "ytd_" + GlobalClass.CreateRandomCode(16);
|
||
objDetail.youtubeDetail_title = item.snippet.title;
|
||
objDetail.youtubeDetail_description = item.snippet.description;
|
||
|
||
string publishedAt = item.snippet.publishedAt;
|
||
|
||
var published = DateTime.Parse(publishedAt, null, DateTimeStyles.None);
|
||
|
||
objDetail.youtubeDetail_publishedAt = published;
|
||
objDetail.youtubeDetail_commentCount = (int)item.statistics.commentCount;
|
||
objDetail.youtubeDetail_viewCount = (int)item.statistics.viewCount;
|
||
objDetail.youtubeDetail_likeCount = (int)item.statistics.likeCount;
|
||
objDetail.youtubeDetail_favoriteCount = (int)item.statistics.favoriteCount;
|
||
|
||
try
|
||
{
|
||
objDetail.youtubeDetail_thumbnails = item.snippet.thumbnails.maxres.url;
|
||
}
|
||
catch { objDetail.youtubeDetail_thumbnails = ""; }
|
||
|
||
|
||
|
||
objDetail.youtubeDetail_videoId = item.id;
|
||
objDetail.youtubeDetail_json = JsonConvert.SerializeObject(item);
|
||
|
||
youtubeDetailList.Add(objDetail);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
|
||
}
|
||
|
||
|
||
|
||
}
|
||
|
||
double avg = ((totalViewNum / videosNum) + 0.5);
|
||
|
||
newYoutube.youtube_avgViewCount = (int)System.Math.Floor(avg);
|
||
|
||
//conn.Execute("update youtube set youtube_revoke = 'Y' where kol_uid = @kol_uid and kolMedia_uid = @kolMedia_uid", new { kol_uid = mediaItem.kol_uid, kolMedia_uid = mediaItem.kolMedia_uid });
|
||
conn.Execute("update youtube set youtube_revoke = 'Y' where kol_uid = @kol_uid ", new { kol_uid = mediaItem.kol_uid });
|
||
|
||
conn.Insert(youtubeDetailList);
|
||
conn.Insert(newYoutube);
|
||
|
||
}
|
||
|
||
|
||
updateLog successLog = new updateLog();
|
||
successLog.updateLog_text = "此Youtube帳號 " + mediaItem.kolMedia_accountName + "(" + mediaItem.kolMedia_displayName + ") Youtube資料更新成功";
|
||
successLog.updateLog_kolMedia_uid = mediaItem.kolMedia_uid;
|
||
successLog.updateLog_kolMedia_accountName = mediaItem.kolMedia_accountName;
|
||
successLog.updateLog_kolMedia_displayName = mediaItem.kolMedia_displayName;
|
||
successLog.updateLog_kol_uid = mediaItem.kol_uid;
|
||
successLog.updateLog_type = "YouTube";
|
||
successLog.updateLog_result = "success";
|
||
successLog.updateLog_uid = channel_id;
|
||
|
||
conn.Insert(successLog);
|
||
}
|
||
catch (Exception ex) {
|
||
updateLog successLog = new updateLog();
|
||
successLog.updateLog_text = "此Youtube帳號 " + mediaItem.kolMedia_accountName + "(" + mediaItem.kolMedia_displayName + ") Youtube資料更新失敗,失敗原因 " + ex.Message;
|
||
successLog.updateLog_kolMedia_uid = mediaItem.kolMedia_uid;
|
||
successLog.updateLog_kolMedia_accountName = mediaItem.kolMedia_accountName;
|
||
successLog.updateLog_kolMedia_displayName = mediaItem.kolMedia_displayName;
|
||
successLog.updateLog_kol_uid = mediaItem.kol_uid;
|
||
successLog.updateLog_type = "YouTube";
|
||
successLog.updateLog_result = "failed";
|
||
successLog.updateLog_uid = channel_id;
|
||
|
||
conn.Insert(successLog);
|
||
}
|
||
|
||
|
||
}
|
||
else {
|
||
updateLog failedLog = new updateLog();
|
||
failedLog.updateLog_text = "此Youtube帳號 " + mediaItem.kolMedia_accountName + "(" + mediaItem.kolMedia_displayName + ") Google Youtube Data Api回傳Null值!";
|
||
failedLog.updateLog_kolMedia_uid = mediaItem.kolMedia_uid;
|
||
failedLog.updateLog_kolMedia_accountName = mediaItem.kolMedia_accountName;
|
||
failedLog.updateLog_kolMedia_displayName = mediaItem.kolMedia_displayName;
|
||
failedLog.updateLog_kol_uid = mediaItem.kol_uid;
|
||
failedLog.updateLog_type = "YouTube";
|
||
failedLog.updateLog_result = "failed";
|
||
|
||
conn.Insert(failedLog);
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
conn.Update(kolMedias);
|
||
|
||
conn.Execute("insert into schedule (schedule_type, schedule_log) values ('YouTube', '執行DoWork,執行更新工作結束')");
|
||
}
|
||
|
||
Interlocked.Decrement(ref execCount);
|
||
conn.Execute("insert into schedule (schedule_type, schedule_log) values ('YouTube', '執行DoWork,execCount減1')");
|
||
}
|
||
|
||
public Task StopAsync(CancellationToken cancellationToken)
|
||
{
|
||
//調整Timer為永不觸發,停用定期排程
|
||
_timer?.Change(Timeout.Infinite, 0);
|
||
return Task.CompletedTask;
|
||
}
|
||
|
||
public void Dispose()
|
||
{
|
||
_timer?.Dispose();
|
||
}
|
||
} |