해당 프로그램 소스는 다음과 같습니다. 필요에 의해 즉흥적으로 만든 것이기에 테스트 과정은 별도로 없습니다. 필요 시 수정 및 보완하셔서 사용하세요.
- m_redirectUri => 블로그 주소를 입력합니다.
- m_blogName => 서브도메인을 입력합니다.
using AdsJumboWinForm;
using BeomCore;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
namespace BeomStory.View
{
public partial class ViewBeomSang : Window
{
const string g_beomAdsId_BeomStory = "";
const string c_authorizationEndpoint = "https://www.tistory.com/oauth/authorize";
const string c_accessTokenEndpoint = "https://www.tistory.com/oauth/access_token";
const string c_postListEndpoint = "https://www.tistory.com/apis/post/list";
string m_redirectUri = "beomsang.tistory.com";
string m_blogName = "beomsang";
string m_clientId = string.Empty;
string m_clientSecret = string.Empty;
string m_accessToken = string.Empty;
string m_code = string.Empty;
public ViewBeomSang()
{
InitializeComponent();
ShowBannerAds();
GetInfo(false);
if (txtPathGoo.Text == string.Empty)
txtPathGoo.Text = @"C:\Users\BEOMSANG\Desktop\테이블.csv";
if (txtPathTis.Text == string.Empty)
txtPathTis.Text = @"C:\Users\BEOMSANG\Desktop\beomsang_beomstory_get_list.txt";
if (txtPathRes.Text == string.Empty)
txtPathRes.Text = @"C:\Users\BEOMSANG\Desktop\beomsang_beomstory_get_list_result.txt";
}
private void ShowBannerAds()
{
if (Debugger.IsAttached)
((BannerAds)adsHost.Child).ShowAd(468, 60, "#ID#");
else
((BannerAds)adsHost.Child).ShowAd(468, 60, g_beomAdsId_BeomStory);
}
private void GetInfo(bool isSet)
{
try
{
string file = "BeomStoryBaseInfo!.txt";
if (isSet)
{
StringBuilder s = new StringBuilder();
s.AppendLine($"BlogName={txtBlogName.Text}");
s.AppendLine($"RedirectUri={txtRedirectUri.Text}");
s.AppendLine($"ClientId={txtClientId.Text}");
s.AppendLine($"SecretKey={txtSecretKey.Text}");
s.AppendLine($"PathGoo={txtPathGoo.Text}");
s.AppendLine($"PathTis={txtPathTis.Text}");
s.AppendLine($"PathRes={txtPathRes.Text}");
using (StreamWriter writer = File.CreateText(file))
{
writer.Write(s.ToString());
}
MessageBox.Show("저장하였습니다.");
}
else
{
if (File.Exists(file))
{
using (StreamReader reader = new StreamReader(file))
{
while (!reader.EndOfStream)
{
string line = reader.ReadLine();
string[] data = line.Split('=');
TextBox t = null;
switch (data[0])
{
case "BlogName":
t = txtBlogName;
break;
case "RedirectUri":
t = txtRedirectUri;
break;
case "ClientId":
t = txtClientId;
break;
case "SecretKey":
t = txtSecretKey;
break;
case "PathGoo":
t = txtPathGoo;
break;
case "PathTis":
t = txtPathTis;
break;
case "PathRes":
t = txtPathRes;
break;
}
if (t != null)
{
t.Text = data[1].Trim();
}
}
}
}
}
}
catch (Exception ex)
{
throw ex;
}
}
private void BeomSang_SearchConsole()
{
List<string> gooUrls = new List<string>();
List<string> noGooUrls = new List<string>();
List<string> tisUrls = new List<string>();
List<string> noTisUrls = new List<string>();
string addStr = string.Empty;
using (StreamReader reader = new StreamReader(txtPathGoo.Text))
{
while (!reader.EndOfStream)
{
string[] data = reader.ReadLine().Split(',');
if (data[0].StartsWith("http"))
{
addStr = string.Empty;
foreach (char ca in data[0].ToCharArray())
{
if (Regex.IsMatch(ca.ToString(), "[ㄱ-ㅎ가-힣]"))
{
string hx = CoreBeomSang.StrToHex(ca.ToString());
addStr += hx;
}
else
{
addStr += ca;
}
}
gooUrls.Add(addStr);
}
else
{
noGooUrls.Add(data[0]);
}
}
}
using (StreamReader reader = new StreamReader(txtPathTis.Text))
{
while (!reader.EndOfStream)
{
string line = reader.ReadLine();
string[] data = line.Split(',');
data.ToList().ForEach(delegate (string item) {
if (item.StartsWith($@"https://{m_blogName}.tistory.com/entry/"))
tisUrls.Add(item);
else
noTisUrls.Add(item);
});
}
}
tisUrls = tisUrls.OrderBy(x => x).ToList();
List<string> a = tisUrls.Except(gooUrls).ToList();
List<string> c = tisUrls.Intersect(gooUrls).ToList();
List<string> b = gooUrls.Except(tisUrls).ToList();
var wr = string.Join(Environment.NewLine, a);
using (StreamWriter writer = File.CreateText(txtPathRes.Text))
{
writer.Write(wr);
}
}
public struct TPostList
{
public struct Tistory
{
public struct Item
{
public struct Post
{
public string id { get; set; }
public string title { get; set; }
public string postUrl { get; set; }
public string visibility { get; set; }
public string categoryId { get; set; }
public string comments { get; set; }
public string trackbacks { get; set; }
public string date { get; set; }
}
public string url { get; set; }
public string secondaryUrl { get; set; }
public string page { get; set; }
public string count { get; set; }
public string totalCount { get; set; }
public List<Post> posts { get; set; }
}
public string status { get; set; }
public Item item { get; set; }
}
public Tistory tistory { get; set; }
}
void BeomSang4_GetList()
{
string requestString = string.Empty;
string urls = string.Empty;
string urlsDat = string.Empty;
string noUrls = string.Empty;
string noUrlsDat = string.Empty;
List<JObject> objs = new List<JObject>();
int i = 0;
do
{
i++;
requestString = string.Format("{0}?{1}&output={2}&blogName={3}&page={4}",
c_postListEndpoint,
m_accessToken,
"json",
m_blogName,
i);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestString);
using (WebResponse response = request.GetResponse())
{
using (Stream stream = response.GetResponseStream())
{
using (StreamReader reader = new StreamReader(stream))
{
string p = reader.ReadToEnd();
var op = JObject.Parse(p);
var li = op.ToObject<TPostList>();
if (li.tistory.item.posts == null)
{
break;
}
else
{
li.tistory.item.posts.ForEach(delegate (TPostList.Tistory.Item.Post _post)
{
var a1 = Convert.ToDateTime(_post.date).ToString("yyyyMMdd");
var b1 = DateTime.Today.ToString("yyyyMMdd");
if (a1.CompareTo(b1) > 0)
{
noUrls += $",{_post.postUrl}";
noUrlsDat += $",{_post.date}";
}
else
{
urls += $",{_post.postUrl}";
urlsDat += $",{_post.date}";
}
});
Thread.Sleep(1000);
}
}
}
}
} while (true);
urls = urls.TrimStart(',');
using (StreamWriter writer = File.CreateText(txtPathTis.Text))
{
writer.Write(urls);
lblComp.Content = "완료";
}
}
void BeomSang3_GetAccessToken()
{
string requestString = string.Format("{0}?client_id={1}&client_secret={2}&redirect_uri={3}&code={4}&grant_type=authorization_code",
c_accessTokenEndpoint,
m_clientId,
m_clientSecret,
Uri.EscapeDataString(m_redirectUri),
m_code);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestString);
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
using (Stream stream = response.GetResponseStream())
{
using (StreamReader reader = new StreamReader(stream))
{
m_accessToken = reader.ReadToEnd();
lblAc.Content = m_accessToken;
}
}
}
}
void BeomSang2_GetAuthorizationCode()
{
string uri = Clipboard.GetText();
Match match = Regex.Match(uri, "\\?code=(?<code>.*)&");
if (match.Success)
{
m_code = match.Groups["code"].Value;
lblCode.Content = m_code;
}
else
{
lblCode.Content = string.Empty;
}
}
void BeomSang1_Authorize()
{
//초기화
m_code = string.Empty;
m_accessToken = string.Empty;
//
lblAc.Content = m_accessToken;
lblCode.Content = string.Empty;
//
m_clientId = string.Empty;
m_clientSecret = string.Empty;
m_clientId = txtClientId.Text;
m_clientSecret = txtSecretKey.Text;
if (m_clientId == string.Empty
|| m_clientSecret == string.Empty)
{
MessageBox.Show("아이디, 키를 입력해 주세요.");
return;
}
string state = CoreBeomSang.GetRandomDataBase64url(32);
string requestString = string.Format("{0}?client_id={1}&redirect_uri={2}&response_type=code&state={3}",
c_authorizationEndpoint,
m_clientId,
Uri.EscapeDataString(m_redirectUri),
state);
Process.Start(requestString);
//var httpListener = new HttpListener();
//httpListener.Prefixes.Add(m_redirectUri);
//httpListener.Start();
//HttpListenerContext context = await httpListener.GetContextAsync();
//var response = context.Response;
//string responseString = $"<html><head><meta http-equiv='refresh' content='10;url=beomsang.tistory.com' charset='UTF-8'></head><body><p>인증절차를 종료하였습니다.</p><p>애플리케이션으로 돌아가 주세요!</p><p>감사합니다.</p><p>범상 드림.</p></body></html>";
//var buffer = Encoding.UTF8.GetBytes(responseString);
//response.ContentLength64 = buffer.Length;
//var responseOutput = response.OutputStream;
//Task responseTask = responseOutput.WriteAsync(buffer, 0, buffer.Length).ContinueWith((task) =>
//{
// responseOutput.Close();
// httpListener.Stop();
// Debug.WriteLine("HTTP 리스너 중단");
//});
//if (context.Request.QueryString.Get("error") != null)
//{
// Debug.WriteLine($"오류 발생 : {context.Request.QueryString.Get("error")}");
// return;
//}
//if (context.Request.QueryString.Get("code") == null)
//{
// Debug.WriteLine($"잘못된 응답 양식 (code가 없음) : {context.Request.QueryString}");
// return;
//}
//if (state != context.Request.QueryString.Get("state"))
//{
// Debug.WriteLine($"(선택옵션)사이트간 요청 위조가 발생한 것 같습니다. 요청state : {state}, 응답state : {context.Request.QueryString.Get("state")}");
// return;
//}
//m_code = context.Request.QueryString.Get("code");
}
private void btn_Click(object sender, RoutedEventArgs e)
{
lblComp.Content = string.Empty;
if (sender == btn1)
BeomSang1_Authorize();
else if (sender == btn2)
BeomSang2_GetAuthorizationCode();
else if (sender == btn3)
BeomSang3_GetAccessToken();
else if (sender == btn4)
BeomSang4_GetList();
else if (sender == btnResult)
BeomSang_SearchConsole();
else if (sender == btnSaveInfo)
GetInfo(true);
}
private void SetPath(string _fileName, object _sender)
{
if (_sender == txtPathGoo)
txtPathGoo.Text = _fileName;
else if (_sender == txtPathTis)
txtPathTis.Text = _fileName;
else if (_sender == txtPathRes)
txtPathRes.Text = _fileName;
}
private void TextBox_Drop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
string[] data = (string[])e.Data.GetData(DataFormats.FileDrop);
SetPath(data[0], sender);
}
}
private void TextBox_PreviewDragOver(object sender, DragEventArgs e)
{
e.Handled = true;
}
}
}