//【登録場所】 "V2C\script\system\getdat.js"
//【内容】 スレッドのログが取得出来ない場合、指定するURLから過去ログを取得する。
// 1. http://m...content-available-to-author-only...n.to/ のhtmltodat 0.10.2(925k byte)をダウンロードする
// 2. ダウンロードした圧縮ファイルを解凍して、フォルダ名を「htmltodat0.9.0」に変更する
// 3. フォルダごとV2Cのログ・設定保存用フォルダにコピーする。保存用フォルダの場所がわからなければV2C起動して 設定→ランチャー(L)… を見ればわかる
//【コマンド】外部コマンドの設定→スクリプト→getdat.jsのパーミッションを初期値の「S」から「SF」に変更する
//【更新日時】2013/11/26 ログ速の仕様変更への対応
// TIPS: ふたばdatのスレ移動リンクはReplaceStr.txtに
// <rx2>http://(\w+)\.2chan\.net/(\w+)/res/(\d+)\.htm $0<br>└( http://$1.2chan.net/test/read.cgi/$2/$3/ ) msg
// の1行追加で移動できるようになります
//【スクリプト】
(function() { this.HTMLtoDAT = _HTMLtoDAT; this.LOGSOKUtoDAT = _LOGSOKUtoDAT; this.FUTABAtoDAT = _FUTABAtoDAT;
// -----------------------------設定項目-----------------------------------
// htmltodatのフォルダパスを指定 (フォルダの区切りは「 \\ 」ではなく「 / 」で、末尾のも「 / 」を記入すること)
var htmltodatDir = v2c.saveDir + '/htmltodat0.9.0/';
// DAT変換定義 (name = 表示名, src = 2chスレURLへの正規表現, dst = srcの正規表現の置換パターン, obj: DAT変換用のクラス(HTMLtoDAT or HTMLtoDAT互換モード or LOGSOKUtoDAT))
// 全部使うと遅いので必要な項目だけコメント(行頭の//のこと)を外すこと
this.services = [
{ name: 'FUTABAtoDAT', obj: new FUTABAtoDAT()},
{ name: 'offlaw2', src: new RegExp("^^http://([^/]+)/test/[^/]+/(\\w+)/(\\d+).*"), dst: "http://$1/test/offlaw2.so?shiro=kuma&bbs=$2&key=$3" },
{ name: 'mimizun', src: new RegExp("^http://([^/]+)/test/[^/]+/(\\w+)/(\\d+).*"), dst: "http://m...content-available-to-author-only...n.com/log/2ch/$2/$3.dat" },
{ name: 'logsoku (LOGSOKUtoDAT)', obj: new LOGSOKUtoDAT() },
// { name: 'unkar' , src: new RegExp("^http://([^/]+)/test/[^/]+/(\\w+)/(\\d+).*"), dst: "http://u...content-available-to-author-only...r.org/convert.php/$2/$3/" },
// {name: 'ヴァルタ', src: new RegExp("^http://([^/]+)/test/[^/]+/(\\w+)/(((\\d+)\\d)\\d{5}).*"), dst: "http://v...content-available-to-author-only...2.com/log/2ch/$2/$1/$2/kako/$5/$4/$3.dat" },
// { name: 'logsoku (htmltodat CompatibleMode)', obj: new HTMLtoDAT(htmltodatDir + 'ログ速.prm', true) },
// { name: 'logsoku (htmltodat)', obj: new HTMLtoDAT(htmltodatDir + 'ログ速.prm') },
// { name: '暇つぶし2ch', obj: new HTMLtoDAT(htmltodatDir + '暇つぶし2ch.prm', true) },
];
// -----------------------------設定項目ここまで---------------------------
// getdat.jsの設定用サブフォルダ(V2C/script/system/getdat/)取得用
//フォルダパス取得の為のダミーなのでdummy.txtは実際に存在しなくても問題ない
var SubFile = v2c.getScriptSubFile('dummy.txt');
if (!SubFile.exists()) {
v2c.writeStringToFile(SubFile, 'dummy');
}
var scriptSubDir = SubFile.getParent();
function _FUTABAtoDAT()
{
this.getURL = function(thread)
{
return thread.url.toString().replaceAll('^http:\\/\\/(.+\\.2chan\\.net)\\/test\\/read.cgi\\/(\\w+)\\/(\\d+).*', 'http://$1/$2/res/$3.htm');
};
this.exec = function(thread)
{
var url = this.getURL(thread);
if (url.toString().indexOf('2chan') < 0) { printlnLog('ふたばURLではないのでスキップします。'); return false; }
var html = null;
html = getThreadLog(url);
if (!html) { printlnLog('ふたば☆ちゃんねるログが取得できませんでした。'); return ''; }
var dat = new java.lang.StringBuilder();
var parser = new HTMLParser(String(html));
var matches = [];
// タイトルの抽出
var title = '';
if (!(title = parser.Parse('<title>', ' - '))) {
title = 'タイトルなし';
}
// レス部分のみ抽出
var cutkey = {start:'</iframe></div>画像ファイル名:', end:'<div style="clear:left"></div>'};
parser.Cut(cutkey.start, cutkey.end);
// スレ立て画像の取得
var thImgKey = {start:'<a href="', end:'" target='};
var thImg = parser.Parse(thImgKey.start, thImgKey.end);
// 1のレスの取得
var artkey = {start:'value=delete id=delcheck', end:'</blockquote></td></tr></table>'};
var infoKey = {start: 'value=delete id=delcheck', end:'</blockquote>'};
var idRegex = new RegExp('(\\d+/\\d+/\\d+\\(.\\)\\d+:\\d+:\\d+)(?:<!--[^>]+>)? ((?:(?:ID|IP):[^ ]+ )?No\\.\\d+)', 'i');
var titleRegex = new RegExp('<font color=\'#cc1105\'><b>([^<]+)</b>', 'i');
var nameRegex = new RegExp('<font color=\'#117743\'><b>([^<]+)</b>', 'i');
var mailRegex = new RegExp('<a href="mailto:([^"]+)">', 'i');
var mesRegex = new RegExp('<blockquote[^>]*>(.*)</blockquote>', 'i');
var imgRegex = new RegExp('<a href="([^"]+)" target=["\']_blank["\']>', 'i');
{
var rName = '', rMail = '', rId = '', rDate = '', rMes = '';
var tmp = parser.Parse(infoKey.start, infoKey.end, true, true);
if (matches = idRegex.exec(tmp)) {
rDate = (matches[1]) ? '20' + matches[1] : '';
rDate = rDate.split(')').join(') ');
rId = matches[2];
}
rName = (matches = nameRegex.exec(tmp)) ? matches[1] : '';
rMail = (matches = mailRegex.exec(tmp)) ? matches[1] : '';
rMes = (matches = mesRegex.exec(tmp)) ? matches[1] : '';
dat.append(rName + '<>' + rMail + '<>' + rDate + ' ' + rId + '<> ' + rMes + ' <br> ' + thImg + ' <>'+title+'\n');
}
// それ以降のレスの取得
while (parser.MoveNext(artkey.start, artkey.end, true, false)) {
var rName = '', rMail = '', rId = '', rDate = '', rMes = '', rImg = '';
var tmp = parser.Parse(infoKey.start, infoKey.end, true, true);
if (matches = idRegex.exec(tmp)) {
rDate = (matches[1]) ? '20' + matches[1] : '';
rDate = rDate.split(')').join(') ');
rId = matches[2];
}
rName = (matches = nameRegex.exec(tmp)) ? matches[1] : '';
rMail = (matches = mailRegex.exec(tmp)) ? matches[1] : '';
rMes = (matches = mesRegex.exec(tmp)) ? matches[1] : '';
rImg = (matches = imgRegex.exec(tmp)) ? matches[1] : '';
if (rImg) {
rMes += ' <br> ' + rImg;
}
dat.append(rName + '<>' + rMail + '<>' + rDate + ' ' + rId + '<> ' + rMes + ' <>\n');
}
return dat.toString();
};
}
function _HTMLtoDAT(prm /* CompatibleMode = false */)
{
var prmFile = new java.io.File(prm);
if (!prmFile.exists()) {
printlnLog('ファイルが見つかりません。 ({0})', prmFile.getPath());
return false;
}
var CompatibleMode = (arguments.length > 1) ? arguments[1] : false;
var prmPath = prm;
var prmBuffer = v2c.readLinesFromFile(prmFile);
var URLRegex = PropertyGenerate('URLの変換', ''); // prmファイルフォーマットは複数行だけど1行しか使わないっぽいのでこれで
var BeforeRegexArr = ConvertRegex(PropertyGenerate('前処理', '', true));
var AfterRegexArr = ConvertRegex(PropertyGenerate('後処理', '', true));
var MatchString = PropertyGenerate('変換結果式', '');
var ResRegex = ConvertRegex(PropertyGenerate('正規表現', ''));
/* CompatibleMode用 以下のプロパティはとりあえず非対応。必要に応じて対応 */
/*
var isProxy = PropertyGenerate('Proxyを使う', false);
var ProxyAddress = PropertyGenerate('Proxyアドレス', '');
var AdditionalHTTPHeaderArr = PropertyGenerate('HTTPヘッダの追加', '', true);
var Server = PropertyGenerate('$server', '');
var Board = PropertyGenerate('$board', '');
var isConvertDisabled = PropertyGenerate('dat変換をしない', '');
var isAnchorRemoved = PropertyGenerate('アンカー削除', '');
var isBECodeRemoved = PropertyGenerate('beコード削除', '');
var isAboneReplaced = PropertyGenerate('透明あぼーんを補う', '');
*/
this.getURL = function(thread)
{
var arr = URLRegex.split('#');
return thread.url.toString().replaceAll(arr[1], arr[2]);
};
this.CompatibleExec = function(thread)
{
var logsoku_url = this.getURL(thread);
if (logsoku_url === String(thread.url.toString())) return '';
var html = '';
var local = (arguments.length > 1) ? arguments[1] : false;
if (local) {
html = local;
} else {
html = getThreadLog(logsoku_url);
}
if (!html) return '';
html = String(html).split('\r\n').join('').split('\n').join('');
//前変換
for (var i = 0; i < BeforeRegexArr.length; i++) {
html = html.replace(BeforeRegexArr[i].regex, BeforeRegexArr[i].match);
}
var title = /<title>(.*?)<\/title>/i.exec(html)[1];
//DAT変換
var dat = [];
var resre = new RegExp(ResRegex[0].regex.source, "ig");
var item;
while ((item = resre.exec(html)) !== null) {
var tmp = MatchString;
for (var i = 1; i < item.length; i++) {
tmp = tmp.replace('$'+ i.toString(), (item[i])? item[i] : '');
}
if (title) {
tmp += title;
title = '';
}
dat.push(tmp);
}
dat = dat.join('\n');
dat += '\n';
//後変換
for (var i = 0; i < AfterRegexArr.length; i++) {
dat = dat.replace(AfterRegexArr[i].regex, AfterRegexArr[i].match);
}
return new java.lang.String(dat);
};
this.exec = function(thread)
{
var OS = java.lang.System.getProperty("os.name").toLowerCase();
if (OS.indexOf('win') < 0) {
printlnLog('HTMLtoDATはWindows以外では動きません。HTMLtoDATCompatibleを使用します。');
return this.CompatibleExec(thread);
}
// V2Cログ・設定保存用フォルダにhtmltodat0.9.0フォルダを入れる。フォルダ名等が違う場合は便宜変更。
var exe = htmltodatDir + 'htmltodat.exe';
if (!(new java.io.File(exe)).exists()) {
printlnLog('htmltodat.exeがなかったので実行できませんでした。({0})',exe);
return '';
}
var tmpPath = scriptSubDir + '/tmp_' + Math.floor(Math.random() * 1000).toString() + (new Date()).getTime().toString() + '.dat';
if (!URLRegex) {
var endl = java.lang.System.getProperty("line.separator");
printlnLog('prmファイルにURLの変換を記述して下さい。以下はログ速の場合の記述例です。');
v2c.println('URLの変換:' + endl + 's#http://(.+?)/test/read\\.cgi/(.+?)/(\\d+)/?.*#http://l...content-available-to-author-only...u.com/thread/$1/$2/$3/#' + endl + '[ここに空行を1行必ず入れること]');
return '';
}
v2c.println(exe + " " + prmPath + " " + tmpPath);
v2c.exec([exe, thread.url.toString(), prmPath, tmpPath]);
java.lang.Thread.sleep(300);
while (isProcessRunning('htmltodat.exe')) {
java.lang.Thread.sleep(1000);
}
var f = new java.io.File(tmpPath);
var dat = v2c.readStringFromFile(f);
f["delete"]();
return dat;
};
if (CompatibleMode) {
this.exec = this.CompatibleExec;
}
function ConvertRegex(regexes)
{
var ret = [];
var regs = regexes;
if (!(regexes instanceof Array)) {
regs = (String(regexes)).replace(/\r\n?/g, '\n').split('\n');
}
for (var i = 0; i < regs.length; i++) {
var arr = (String(regs[i])).split('#');
var opt = '';
var num = (arr[0] === 'm')? 2 : 3;
if (arr[num]) {
if (arr[num].indexOf('g') >= 0) opt += 'g';
if (arr[num].indexOf('i') >= 0) opt += 'i';
if (arr[num].indexOf('m') >= 0) opt += 'm';
}
var re = new RegExp(arr[1], opt);
ret.push({regex: re, match: arr[2]});
}
return ret;
}
function PropertyGenerate(propName, initValue /* isMultiLine = false */)
{
var isMultiLine = (arguments.length > 2) ? arguments[2] : false;
var fileext = (arguments.length > 3) ? arguments[3] : false;
var ret = [];
var idx = -1;
var p = java.util.regex.Pattern.compile('^'+propName+'.*?');
for (var i = 0; i < prmBuffer.length; i++) {
if (prmBuffer[i].length() > 0) {
if (p.matcher(prmBuffer[i]).matches()) {
idx = i;
break;
}
}
}
if (idx < 0) { return initValue; }
var idx2 = 0;
if (-1 != (idx2 = prmBuffer[idx].indexOf('='))) {
// 外部ファイル指定された場合 ログ・設定保存用フォルダ/htmltodat0.9.0/フォルダ内のファイルを読み込む
ret = prmBuffer[idx].substring(idx2 + 1);
switch (propName) {
case '変換結果式' : ret += '.cvr'; break;
case '後処理' : ret += '.acv'; break;
case '前処理' : ret += '.bcv'; break;
case 'URLの変換' : ret += '.ucv'; break;
case 'HTTPヘッダの追加' : ret += '.hdr'; break;
case 'Proxyアドレス' : ret += '.txt'; break;
default: break;
}
var f = new java.io.File(htmltodatDir + ret);
if (!f.exists()) {
printlnLog('ファイルが見つかりません。 ({0})', f.getPath());
}
ret = v2c.readLinesFromFile(f);
if ((ret instanceof Array) && ret.length == 1) {
ret = ret[0];
}
}
else {
// prmファイルに記述されてる場合
idx++;
while (prmBuffer[idx].length() <= 0) { idx++; }
while ((idx < prmBuffer.length) && (prmBuffer[idx].length() > 0)) {
if (isMultiLine) {
ret.push(prmBuffer[idx++]);
} else {
ret = prmBuffer[idx];
break;
}
}
}
if (ret instanceof Array) {
for (var i = 0; i < ret.length; i++) {
if (ret[i].charAt(0) === '#'.charCodeAt(0)) {
ret.splice(i--, 1);
}
}
}
if (ret.length == 0) {
ret = initValue;
}
return ret;
}
}
function HTMLParser(html)
{
var doc = html;
this.index = 0;
this.endIndex = doc.length;
this.getHtml = function() { return doc; };
this.Parse = function(startkey, endkey /* isStartKey = false, isEndKey = false */)
{
var ret = '';
var ix1,ix2;
var isStartKey = (arguments.length > 2) ? arguments[2] : false;
var isEndKey = (arguments.length > 3) ? arguments[3] : false;
if (-1 == (ix1 = doc.indexOf(startkey, this.index)))
return ret;
if (!isStartKey)
ix1 += startkey.length;
if (-1 == (ix2 = doc.indexOf(endkey, ix1)))
return ret;
if (isEndKey)
ix2 += endkey.length;
if (ix2 > this.endIndex)
return ret;
ret = doc.substring(ix1, ix2);
this.index = ix2;
return ret;
};
this.ParseLine = function()
{
var ret = '';
var end = doc.indexOf('\n', this.index);
if ((end > 0) && (end <= this.endIndex)) {
ret = doc.substring(this.index, end);
this.index = end;
}
return ret;
};
this.ParseShift = function(startkey, endkey)
{
var ret = this.Parse(startkey, endkey);
this.Shift();
return ret;
};
this.Shift = function()
{
doc = doc.substr(this.index);
this.endIndex -= this.index;
this.index = 0;
};
this.MoveNext = function(key, endIdxKey /* isStartKey = false, isEndKey = false */)
{
var isStartKey = (arguments.length > 2) ? arguments[2] : false;
var isEndKey = (arguments.length > 3) ? arguments[3] : false;
var ix1, ix2;
if ((ix1 = doc.indexOf(key, this.index)) == -1)
return false;
if (!isStartKey)
ix1 += key.length;
if ((ix2 = doc.indexOf(endIdxKey, ix1)) == -1)
return false;
if (ix1 == ix2)
return false;
this.index = ix1;
if (isEndKey)
this.endIndex = ix2;
return this.index;
};
this.Cut = function(startkey, endkey)
{
this.index = doc.indexOf(startkey, this.index) + startkey.length;
doc = doc.substring(this.index, doc.lastIndexOf(endkey));
this.index = 0;
this.endIndex = doc.length;
return doc;
};
}
// 仕様:
// 以下のログ速の仕様のためオリジナルdatとのバイナリ一致は不可能
// >1などアンカミスを>>1にしてしまう
// 2chURLが全てrogsokuのURLに置換されてるのでh抜き等に対応できない(全てhttp://で書きだす)
// また同様に2chURLのホスト名が不明なので現サーバーのホスト名で2chURLを生成している(ログ速のapiを叩けば拾えるがdat生成が遅くなるのと相手先に負荷がかかるため実装しない)
function _LOGSOKUtoDAT()
{
this.getURL = function(thread)
{
return thread.url.toString().replaceAll('^http:\\/\\/(.+\\.2ch\\.net)\\/test\\/read[^/]+\\/(.+?)\\/(\\d+).*', 'http://l...content-available-to-author-only...u.com/thread/$1/$2/$3/');
};
this.exec = function(thread)
{
var logsoku_url = this.getURL(thread);
if (logsoku_url === String(thread.url.toString()) || logsoku_url.indexOf('bbspink') != -1) {
printlnLog("指定されたスレッドはログ速が非対応のBBSPINKのスレッドなので取得できませんでした。");
return '';
}
if (logsoku_url.toString().indexOf('2chan') >= 0) { printlnLog('ログ速が非対応なふたばスレッドのURLなのでスキップします。'); return false; }
var html = '';
var local = (arguments.length > 1) ? arguments[1] : false;
if (local) {
html = local;
} else {
html = getThreadLog(logsoku_url);
}
if (!html) {
printlnLog("ログ速のHTMLが取得できませんでした。");
return '';
}
var dat = new java.lang.StringBuilder();
var title = '';
var parser = new HTMLParser(String(html));
// タイトルの取得
var keyword = {start :'og:title" content="', end :' | ログ速"/>'};
if (!(title = parser.Parse(keyword.start, keyword.end))) {
printlnLog("ログ速のHTMLからスレッドタイトルが取得できませんでした。(仕様変更?)");
return '';
}
// レス部分だけ抜き出し
keyword.start = '<div id="comments">';
keyword.end = '</div> <hr class="divider"';
parser.Cut(keyword.start, keyword.end);
var nkey = {start :'em"> <b>', end :'</b></span>'}; // 名前欄
var mkey = {start :'[', end :']'}; // メール欄
var tkey = {start :'投稿日:', end :' <a href="/id/'}; // 日時
var idkey = {start : '<a href="/id/', end :'<div class="comment">'}; // ID
var meskey = {start :'<div class="comment"> ', end :'</div>'}; // 本文欄
var artkey = {start :'<div id="', end :'</div> </div>'}; // 単レスのタグ範囲指定
var bdkey = thread.board.key;
var thkey = thread.key;
var thumbRegex = /<br\/><(iframe|img class).+<br\/>/g; // ニコニコとYoutubeのサムネ用のタグ削除
var tagRegex = /(<|(\[))("[^"]*"|'[^']*'|[^'">])*[>\])]/g; // ID,BE,株主らへんのタグ削除+発言回数削除
var kabRegex = /^ (.+?) /; // 株の1文字表記のみリンク化
var ssspRegex = /<img src="http:\/\/cdn\.logsoku\.com\/(.+)">/g; // BEアイコンのURL修正及びタグ削除
var linkRegex = /<a href[^>]+target="_blank"[^>]*>(.+?)<\/a>/g; // その他リンクタグ削除
var thLinkRegex= /<a href="\/r\/[^>]+>http:\/\/www\.logsoku\.com\/r\/([^\/]+)\/([^<]+)<\/a>/g; // 他スレッドへのリンクタグを平文に置換
var anchorRegex= /<a href=".*data-pop-res="(\d+)"[^>]*>/g; // アンカーのURL修正
var playerRegex = /<\/?(div|img)[^>]*>/g; // Youtubeプレイヤーの除去
while (parser.MoveNext(artkey.start, artkey.end)) {
var name = parser.Parse(nkey.start, nkey.end);
var mail = parser.Parse(mkey.start, mkey.end);
var date = parser.Parse(tkey.start, tkey.end);
parser.index++; // 日時とIDの間の半角スペースを飛ばす
var mes = '';
if (date) {
var idset = parser.Parse(idkey.start, idkey.end, true, false);
if (idset) {
idset = idset.replace(tagRegex, '');
idset = idset.replace(kabRegex, ' <a href="http://2...content-available-to-author-only...h.se/">$1</a> ');
date += ' ' + idset;
}
mes = parser.Parse(meskey.start, meskey.end);
mes = mes.replace(thumbRegex, '');
if (mes.indexOf('<') >= 0) {
mes = mes.replace(ssspRegex, 'sssp://$1');
mes = mes.replace(linkRegex, '$1');
mes = mes.replace(anchorRegex, '<a href="../test/read.cgi/'+ bdkey + '/' + thkey + '/$1" target="_blank">');
mes = mes.replace(thLinkRegex, function(whole, m1, m2) {
return 'http://' + v2c.bbs2ch.getBoard(m1).url.host + '/test/read.cgi/' + m1 + '/' + m2;
});
mes = mes.replace(playerRegex, '');
}
mes = mes.split("<br/>").join('<br>');
} else {
date = 'Over 1000 Thread';
var mArr = parser.Parse(meskey.start, meskey.end).split("<br/>"); // <br/> → <br>にするついでに<br>以外のタグを削除
for (var i = 0; i < mArr.length; i++) {
mArr[i] = mArr[i].replace(/<.+?>/g, '');
}
mes = mArr.join('<br>');
mes = mes.split('>').join('>').split('<').join('<').split('"').join('"'); // 1001ではHTMLエンコードされないようだ
}
if (dat.length() == 0) {
dat.append(name + '<>' + mail + '<>' + date + '<> ' + mes + ' <>'+title+'\n');
} else {
dat.append(name + '<>' + mail + '<>' + date + '<> ' + mes + ' <>\n');
}
}
return dat.toString();
};
}
this.isProcessRunning = function(processName)
{
var cnt = 0;
try {
var runtime = java.lang.Runtime.getRuntime();
var p;
var OS = java.lang.System.getProperty("os.name").toLowerCase();
if (OS.indexOf('win') >= 0) {
p = runtime.exec(['cmd.exe', '/c', 'tasklist | findstr "' +processName + '"']);
} else {
p = runtime.exec(['/bin/sh', '-c', 'ps ux | pgrep -lf "' + processName + '"']);
}
var is = p.getInputStream();
var isr = new java.io.InputStreamReader(is);
var br = new java.io.BufferedReader(isr);
while (br.readLine()) { cnt++; }
br.close();
isr.close();
is.close();
} catch (e) {
if (e.javaException) {
printlnLog('プロセス名の取得に失敗しました。 ({0})', e.javaException);
} else {
printlnLog('プロセス名の取得に失敗しました。 (e={0})', e);
}
}
return (cnt)? true : false;
};
this.getThreadLog = function(url)
{
var req = v2c.createHttpRequest(url);
req.setRequestProperty('Accept-Encoding', 'gzip');
var content = req.getContentsAsString();
if (req.responseCode==200 || req.responseCode==302) {
if (req.responseCode == 302) {
var newUrl = req.getResponseHeader('Location');
content = v2c.readURL(newUrl);
}
} else {
return null;
}
if(!content) {
return null;
}
return content;
};
this.printlnLog = function(format /*, ...*/)
{
var args = arguments;
var message = format.replace(/\{(\d)\}/g, function(m, c) { return args[parseInt(c) + 1]; });
v2c.println("[getdat.js] " + message);
};
this.getFormatString = function(/*format, ...*/)
{
var args = (arguments[0] instanceof Array)? arguments[0] : arguments;
return String(args[0]).replace(/\{(\d)\}/g, function(m, c) { return args[parseInt(c) + 1]; });
}
})();
function getDat(thread)
{
if (!(thread.bbs.is2ch || (thread.url.toString().indexOf('2chan') >= 0))) {
return null;
}
var retrievedResCount = thread.localResCount;
var dat = null;
for(var i = 0; retrievedResCount < 1001 && i < services.length; i++)
{
v2c.setStatus("過去ログを取得中........( ´∀`)つ旦 " + services[i].name);
var content = '';
var url = '';
if (services[i].obj) {
url = services[i].obj.getURL(thread);
content = services[i].obj.exec(thread);
} else if (services[i].src && services[i].dst) {
url = (String(thread.url.toString())).replace(services[i].src, services[i].dst);
content = getThreadLog(url);
}
if (v2c.interupted) { return null; }
if(!content)
continue;
var resCount = content.split("\n").length;
if ((resCount == 1) && (content.split("\n")[0].match(/unkar\.org/))) continue;
printlnLog("{0} ({1}): {2}", services[i].name, resCount, url);
if(retrievedResCount < resCount)
{
dat = { service: services[i], content: content };
retrievedResCount = resCount;
}
}
var found = dat ? "retrieved from " + dat.service.name : "not found";
printlnLog("{0}: {1} (+{2})", found, thread.title, retrievedResCount - thread.localResCount);
return dat ? dat.content : null;
}