Codemaru
1.0.0.0
QR 코드, 모바일 랜딩 페이지, vCard 연락처 저장과 명함 디자인을 한 화면에서 제공하는 디지털 명함 서비스입니다.
Toggle main menu visibility
로딩중...
검색중...
일치하는것 없음
SitePreviewService.cs
이 파일의 문서화 페이지로 가기
1
using
System.IO;
2
using
System.Net.Http;
3
using
System.Text.RegularExpressions;
4
using
Microsoft.Extensions.Configuration;
5
using
Microsoft.Extensions.Hosting;
6
using
Microsoft.Extensions.Logging;
7
8
namespace
Codemaru.Services
;
9
18
public
sealed
class
SitePreviewService
: BackgroundService
19
{
28
private
static
readonly
(
string
Key,
string
Url)[] Sites =
29
[
30
(
"dreamine"
,
"https://dreamine.kr/"
),
31
(
"wedding"
,
"https://wedding.codemaru.co.kr"
),
32
(
"thankyou"
,
"https://thankyou.codemaru.co.kr/"
),
33
(
"families"
,
"https://families.codemaru.co.kr"
),
34
(
"portfolio"
,
"https://portfolio.codemaru.co.kr/"
),
35
(
"cctv"
,
"https://cctvviewer.codemaru.co.kr"
),
36
(
"shop"
,
"https://shop.codemaru.co.kr/"
),
37
];
38
47
private
static
readonly
Regex
OgImageRegex
=
new
(
48
@"<meta[^>]+property=[""']og:image[""'][^>]+content=[""']([^""']+)[""']"
,
49
RegexOptions.IgnoreCase | RegexOptions.Compiled);
50
59
private
static
readonly
Regex
OgImageRegex2
=
new
(
60
@"<meta[^>]+content=[""']([^""']+)[""'][^>]+property=[""']og:image[""']"
,
61
RegexOptions.IgnoreCase | RegexOptions.Compiled);
62
71
private
readonly
string
_wwwRoot
;
80
private
readonly
ILogger<SitePreviewService>
_logger
;
89
private
readonly
TimeSpan
_interval
;
98
private
readonly
HttpClient
_http
;
99
124
public
SitePreviewService
(ILogger<SitePreviewService> logger, IConfiguration config)
125
{
126
_logger
= logger;
127
_interval
= TimeSpan.FromHours(config.GetValue(
"SitePreview:RefreshHours"
, 6));
128
_wwwRoot
= Path.Combine(AppContext.BaseDirectory,
"wwwroot"
);
129
_http
=
new
HttpClient(
new
HttpClientHandler { AllowAutoRedirect =
true
});
130
_http
.DefaultRequestHeaders.UserAgent.ParseAdd(
131
"Mozilla/5.0 (compatible; CodemaruBot/1.0; +https://codemaru.co.kr)"
);
132
_http.Timeout = TimeSpan.FromSeconds(15);
133
}
134
159
protected
override
async Task
ExecuteAsync
(CancellationToken stoppingToken)
160
{
161
while
(!stoppingToken.IsCancellationRequested)
162
{
163
await
FetchAllAsync
(stoppingToken);
164
165
try
{ await Task.Delay(
_interval
, stoppingToken); }
166
catch
(OperationCanceledException) {
break
; }
167
}
168
}
169
194
private
async Task
FetchAllAsync
(CancellationToken ct)
195
{
196
var outputDir = Path.Combine(
_wwwRoot
,
"img"
,
"previews"
);
197
Directory.CreateDirectory(outputDir);
198
199
foreach
(var (key, url) in Sites)
200
{
201
if
(ct.IsCancellationRequested)
break
;
202
await
FetchOneAsync
(key, url, outputDir, ct);
203
}
204
}
205
254
private
async Task
FetchOneAsync
(
string
key,
string
siteUrl,
string
outputDir, CancellationToken ct)
255
{
256
var destPath = Path.Combine(outputDir, $
"{key}.jpg"
);
257
var tempPath = destPath +
".tmp"
;
258
259
try
260
{
261
// 1. 사이트 HTML 가져오기
262
var html = await
_http
.GetStringAsync(siteUrl, ct);
263
264
// 2. og:image URL 파싱
265
var match =
OgImageRegex
.Match(html);
266
if
(!match.Success) match =
OgImageRegex2
.Match(html);
267
if
(!match.Success)
268
{
269
_logger
.LogWarning(
"og:image 없음: {Key}"
, key);
270
return
;
271
}
272
273
var imageUrl = match.Groups[1].Value.Trim();
274
275
// 상대 경로면 절대 경로로 변환
276
if
(!imageUrl.StartsWith(
"http"
, StringComparison.OrdinalIgnoreCase))
277
{
278
var base64 =
new
Uri(siteUrl);
279
imageUrl =
new
Uri(base64, imageUrl).ToString();
280
}
281
282
// 3. 이미지 다운로드
283
var imageBytes = await
_http
.GetByteArrayAsync(imageUrl, ct);
284
await File.WriteAllBytesAsync(tempPath, imageBytes, ct);
285
File.Move(tempPath, destPath, overwrite:
true
);
286
287
_logger
.LogInformation(
"OG 이미지 캐시 완료: {Key} ← {ImageUrl}"
, key, imageUrl);
288
}
289
catch
(Exception ex)
290
{
291
_logger
.LogWarning(ex,
"OG 이미지 fetch 실패: {Key} ({Url})"
, key, siteUrl);
292
if
(File.Exists(tempPath)) File.Delete(tempPath);
293
}
294
}
295
304
public
override
void
Dispose
()
305
{
306
_http
.Dispose();
307
base.Dispose();
308
}
309
}
Codemaru.Services
Definition
CardHybridCircuitSession.cs:8
Codemaru.Services.SitePreviewService._interval
readonly TimeSpan _interval
Definition
SitePreviewService.cs:89
Codemaru.Services.SitePreviewService._logger
readonly ILogger< SitePreviewService > _logger
Definition
SitePreviewService.cs:80
Codemaru.Services.SitePreviewService.FetchOneAsync
async Task FetchOneAsync(string key, string siteUrl, string outputDir, CancellationToken ct)
Definition
SitePreviewService.cs:254
Codemaru.Services.SitePreviewService.OgImageRegex
static readonly Regex OgImageRegex
Definition
SitePreviewService.cs:47
Codemaru.Services.SitePreviewService.OgImageRegex2
static readonly Regex OgImageRegex2
Definition
SitePreviewService.cs:59
Codemaru.Services.SitePreviewService.FetchAllAsync
async Task FetchAllAsync(CancellationToken ct)
Definition
SitePreviewService.cs:194
Codemaru.Services.SitePreviewService.ExecuteAsync
override async Task ExecuteAsync(CancellationToken stoppingToken)
Definition
SitePreviewService.cs:159
Codemaru.Services.SitePreviewService.Dispose
override void Dispose()
Definition
SitePreviewService.cs:304
Codemaru.Services.SitePreviewService._http
readonly HttpClient _http
Definition
SitePreviewService.cs:98
Codemaru.Services.SitePreviewService._wwwRoot
readonly string _wwwRoot
Definition
SitePreviewService.cs:71
Codemaru.Services.SitePreviewService.readonly
static readonly(string Key, string Url)[] Sites
Codemaru.Services.SitePreviewService.SitePreviewService
SitePreviewService(ILogger< SitePreviewService > logger, IConfiguration config)
Definition
SitePreviewService.cs:124
Services
SitePreviewService.cs
다음에 의해 생성됨 :
1.17.0