//【登録場所】お気に入り、ツールバー
//【ラベル】検索キーワード名@板名 など
//【コマンド】${SCRIPT:SFRx} getFutabaCatalog.js $BOARD(板URL)
//【アクション】スレ一覧で開く ←※忘れやすいんで設定し忘れに注意
//【更新日】2013/12/12 初回実行時に板を自動的に作成するようになりました (ユーザー定義に板を作成する必要がなくなった) パーミッションが SFRxに変わります
// 2012/12/12 rev.2 カタログにタイトルがない場合スレからタイトルを取得する処理の追加
// 2012/12/12 rev.3 $BOARDでのカタログ取得時にソート指定できるようにした
//例:${SCRIPT:SFRx} getFutabaCatalog.js $BOARD(http://d...content-available-to-author-only...n.net/b/)
//例:${SCRIPT:SFRx} getFutabaCalalog.js $NIJIRAN(DEC)
// ↑二次元裏(Dec)からカタログをスレ一覧に変換して取得する
//【内容】
// 0.※getFutabaCatalog.jsとgetdat.jsが必要
// 1. お気に入り一覧かツールバーのボタン登録領域に上記例のようなコマンドのボタンを作成する(登録領域の場所がわからない場合wikiのfindThreadsMod.jsの詳細を参照)
// 2. 作成したボタンを押すとカタログがスレ一覧に表示される
// 3.板が作成されてなければ再起動し、再度スレ一覧を開いてスレを選択しスレが表示されれば成功
//【コマンドの書式】
// ${SCRIPT:SFRx} getFutabaCatalog.js 引数1 引数2 引数3 ... (以下の引数を半角スペースを空けて連続して書く。)
// $BOARD(板URL) = 板URL(http://d...content-available-to-author-only...n.net/b/みたいな) ※必須・複数回定義不可
// $NIJIRAN(板KEY) = 板KEY(IDやDECみたいな) ※BOARDと両方指定は不可
// $SORT(0 or 1 or 2 or 3 or 4) = $BOARD使用時のカタログの並び替え順序を指定します 0=既定,1=新順, 2=古順, 3=多順, 4=少順
//【スクリプト】
function getThreads(cx) {
if (!v2c.online) { cx.skip = true; return null; }
var catHtml = null;
var bd = null;
var thl = [];
if (v2c.context.args.length > 0) {
var tmp = String(v2c.context.argLine);
var matches = [];
var sort = 0;
if (matches = /\$SORT\((.*)\) *\$|\$SORT\((.*)\) *$/i.exec(tmp)) {
sort = parseInt(matches[2]);
}
if (matches = /\$NIJIRAN\((.*)\) *\$|\$NIJIRAN\((.*)\) *$/i.exec(tmp)) {
var server = matches[2].toUpperCase();
var nranUrl = 'http://f...content-available-to-author-only...b.net/nijiran/fCatalog_' + server + '.html';
catHtml = v2c.readURL(nranUrl);
if (!catHtml) { statusLog('カタログの取得に失敗 ({0})', nranUrl); return null; }
if (matches = /<a href="([^"]+)" id="reload_b" target="_blank">本家へ<\/a>/i.exec(catHtml)) {
bd = v2c.getBoard(matches[1]);
if (!bd) {
var bdnames = {
'DIS' : '東日本大震災@ふたば',
'ATM' : '発電@ふたば',
'DEC' : '二次裏@ふたば',
'MAY' : '二次裏@ふたば',
'ID' : '二次裏@ふたば',
'JUN' : '二次裏@ふたば',
'NOV' : '二次裏@ふたば',
'IMG' : '二次裏@ふたば',
'DAT' : '二次裏@ふたば',
'MRC' : '東方@ふたば',
'MRU' : '東方裏@ふたば',
'MKI' : '模型@ふたば',
'MKU' : '模型裏@ふたば',
'LIV' : '二次元実況@ふたば',
'LIVU': '二次元実況裏@ふたば',
'L3D' : '三次実況@ふたば',
'GOV' : '政治@ふたば',
'GRU' : 'グロ裏@ふたば',
'LAY' : 'レイアウト@ふたば',
'DECT': 'decてすと@ふたば',
'TJUN': 'てすとjun@ふたば'
};
var bdn = bdnames[server];
if (bdn.indexOf('二次裏@ふたば') >= 0) {
bdn += ' (' + server + ')';
}
insertTreeCode(matches[1], bdn);
}
} else {
statusLog('虹覧カタログから本家URLの取得失敗。'); return null;
}
thl = nijiranCat(catHtml, bd);
}
else if (matches = /\$BOARD\((.*)\) *\$|\$BOARD\((.*)\) *$/i.exec(tmp)) {
if (typeof matches[2] === 'undefined' || matches[2].length == 0) { statusLog('$BOARD(板URL)の「板URL」に何も入力されていません。'); return null; }
var catUrl = matches[2];
var urltmp = catUrl + "futaba.php?mode=cat";
if (sort > 0) {
urltmp += '&sort=' + sort;
}
catHtml = v2c.readURL(urltmp);
if (!catHtml) { statusLog('カタログの取得に失敗。({0})', catUrl); return null; }
if (matches = /<title>([^>]+)<\/title>/ig.exec(catHtml)) {
bd = v2c.getBoard(catUrl, matches[1]);
if (!bd) {
insertTreeCode(catUrl, matches[1]);
}
} else {
statusLog('カタログのタイトル取得に失敗。'); return null;
}
thl = futabaCat(catHtml, bd);
}
}
return thl;
}
function insertTreeCode(url, title)
{
var f = new java.io.File(v2c.saveDir + '/BBS/UserDefined/bbstree.txt');
var tmp = String(v2c.readStringFromFile(f));
var treecode = '2,' + url + ',' + title + '\r\n';
if (tmp.indexOf(treecode) < 0) {
if (tmp.indexOf('1,C,ふたば☆ちゃんねる') >= 0) {
tmp = tmp.split('1,C,ふたば☆ちゃんねる\r\n').join('1,C,ふたば☆ちゃんねる\r\n' + treecode);
} else {
tmp += treecode;
}
v2c.writeStringToFile(f, tmp, "UTF-8");
v2c.alert('『' + title + '』板を作成しました。V2Cを再起動します。');
v2c.restart();
}
}
function nijiranCat(catHtml, bd)
{
var html = catHtml.split('↓隔離されたスレ')[0];
html = html.split('<div style="text-align: center;"><table class="nom" cellspacing="0">')[1];
var cat2thReg = /<a href="http:\/\/\w+\.2chan\.net\/\w+\/res\/(\d+)\.htm" target="_blank"><span class="cat"><img[^>]+><br><\/span>([^<]+)<br><\/a><[^>]+>(\d+)<\/span>/ig;
var matches = [];
var thl = [];
while (matches = cat2thReg.exec(html)) {
var k, t, n;
if (!matches[1]) continue;
k = matches[1];
t = matches[2];
n = matches[3];
var th = bd.getThread(k, null, t, n);
thl.push(th);
}
return thl;
}
function futabaCat(catHtml, bd)
{
var cat2thReg = new RegExp("<td><a href='res/([^']+)\\.htm'.+<small>([^<]+)</small><br><font size=2>([^<]+)</font>", "i");
var cat2thReg2 = new RegExp("<td><a href='res/([^']+)\\.htm'.+<br><font size=2>([^<]+)</font>", "i");
var thl = [];
var tmp = catHtml.split("\n");
var matches = [];
for (var i = 0; i < tmp.length; i++) {
if (matches = cat2thReg.exec(tmp[i])) {
var k, t, n;
if (!matches[1]) continue;
else k = matches[1];
t = (!matches[2]) ? "タイトルなし" : matches[2];
n = (!matches[3]) ? 0 : parseInt(matches[3], 10);
var th = bd.getThread(k, null, t, n);
thl.push(th);
} else if (matches = cat2thReg2.exec(tmp[i])) {
if (!matches[1]) continue;
else k = matches[1];
var tmp2 = v2c.readURL(bd.url + 'res/' + matches[1] + '.htm');
t = "タイトルなし";
n = (!matches[3]) ? 0 : parseInt(matches[2], 10);
if (/<title>(.*?) -/i.exec(tmp2)) {
t = RegExp.$1;
}
var th = bd.getThread(k, null, t, n);
thl.push(th);
}
}
return thl;
}
function statusLog(format /*, ...*/)
{
var args = arguments;
var message = format.replace(/\{(\d)\}/g, function(m, c) { return args[parseInt(c) + 1] });
v2c.context.setStatusBarText("[getFutabaCatalog.js] " + message);
}
function printlnLog(format /*, ...*/)
{
var args = arguments;
var message = format.replace(/\{(\d)\}/g, function(m, c) { return args[parseInt(c) + 1] });
v2c.println("[getFutabaCatalog.js] " + message);
}