/// <summary>
/// オンラインで板一覧を更新 ([BBS MENU for 2ch]に対応)
/// </summary>
/// <param name="url">更新先URL</param>
/// <param name="callback">板が移転していた場合に呼ばれるコールバック</param>
public void OnlineUpdate(string url, BoardUpdateEventHandler callback)
{
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
req.Headers.Add("Pragma", "no-cache");
req.Headers.Add("Cache-Control", "no-cache");
HttpWebResponse res = (HttpWebResponse)req.GetResponse();
try
{
IBoardTable newTable = new KatjuBoardTable();
string htmlData;
using (StreamReader sr = new StreamReader(res.GetResponseStream(), Encoding.GetEncoding("Shift_Jis")))
htmlData = sr.ReadToEnd();
res.Close();
res = null;
/* 2012/12/02のbbsmenu.html変更で板情報が取れなくなってしまった
// カテゴリ開始の前に改行を挿入し、処理しやすくする
htmlData = Regex.Replace(htmlData, "<br><b>", "\r\n<br><b>", RegexOptions.IgnoreCase);
string[] lines = Regex.Split(htmlData, "\r\n|\r|\n");
// カテゴリ名を検索するための正規表現
Regex regex1 = new Regex("<br><b>(?<category>.+?)</b><br>",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
// URL、サーバー名、ディレクトリ名、表示名を検索するための正規表現
Regex regex2 = new Regex(@"<a href=(?<url>[^\s>]+).*?>(?<subj>.+?)</a>",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
for (int i = 0; i < lines.Length; )
{
// カテゴリを検索
Match matchCate = regex1.Match(lines[i++]);
if (matchCate.Success)
{
// カテゴリを作成
Category category = new Category(
matchCate.Groups["category"].Value);
while (i < lines.Length)
{
if (lines[i] == String.Empty)
break;
// ボードを検索
Match matchBrd = regex2.Match(lines[i++]);
if (matchBrd.Success)
{
// ボード情報を作成
BoardInfo newBoard = URLParser.ParseBoard(matchBrd.Groups["url"].Value);
if (newBoard != null)
{
newBoard.Name = matchBrd.Groups["subj"].Value;
category.Children.Add(newBoard);
if (callback != null)
{
// 新板&移転チェック
BoardInfo old = FromName(newBoard.Name, newBoard.DomainPath);
BoardUpdateEventArgs args = null;
// 見つからなければ新板と判断
if (old == null)
{
args = new BoardUpdateEventArgs(BoardUpdateEvent.New, null, newBoard);
}
// 見つかったが板のURLが違う場合は移転と判断
else if (old.Server != newBoard.Server)
{
args = new BoardUpdateEventArgs(BoardUpdateEvent.Change, old, newBoard);
}
if (args != null)
callback(this, args);
}
}
}
}
if (category.Children.Count > 0)
newTable.Items.Add(category);
}
}
*/
// 2012/12/05 Mizutama実装
// 板情報を抽出
// <BR><BR><B>カテゴリ名</B><BR>
// <A HREF=http://[サーバー]/[板名]/>名前</A>
MatchCollection cats = Regex.Matches
(
htmlData ,
@"<BR><BR><B>(?<cat>.+?)</B><BR>(?<brds>.+?)(?=\<BR\>\<BR\>\<B\>)" ,
RegexOptions.Singleline|RegexOptions.IgnoreCase
);
foreach ( Match m in cats )
{
Category category = new Category( m.Groups["cat"].Value );
MatchCollection brds = Regex.Matches
(
m.Groups["brds"].Value ,
@"<A HREF=(?<url>[^\s>]+).*?>(?<subj>.+?)</A>" ,
RegexOptions.Singleline|RegexOptions.IgnoreCase
);
foreach ( Match matchBrd in brds )
{
// ボード情報を作成
BoardInfo newBoard = URLParser.ParseBoard( matchBrd.Groups["url"].Value );
if ( newBoard != null )
{
newBoard.Name = matchBrd.Groups["subj"].Value;
category.Children.Add( newBoard );
if ( callback != null )
{
// 新板&移転チェック
BoardInfo old = FromName( newBoard.Name , newBoard.DomainPath );
BoardUpdateEventArgs args = null;
// 見つからなければ新板と判断
if ( old == null )
{
args = new BoardUpdateEventArgs( BoardUpdateEvent.New , null , newBoard );
}
// 見つかったが板のURLが違う場合は移転と判断
else if ( old.Server != newBoard.Server )
{
args = new BoardUpdateEventArgs( BoardUpdateEvent.Change , old , newBoard );
}
if ( args != null )
callback( this , args );
}
}
}
if ( category.Children.Count > 0 )
{
newTable.Items.Add( category );
}
}
if (newTable.Items.Count > 0)
{
// 新しい板一覧を設定
Items.Clear();
Items.AddRange(newTable.Items);
}
else
{
throw new ApplicationException("板一覧の更新に失敗しました");
}
}
catch (ThreadAbortException)
{
if (callback != null)
callback(this, new BoardUpdateEventArgs(BoardUpdateEvent.Cancelled, null, null));
}
catch (Exception ex)
{
TwinDll.ShowOutput(ex);
}
finally
{
if (res != null)
res.Close();
}
}