fork download
  1. //【登録場所】 リンク(レス表示,選択テキストだと最初のリンク)、URLExec.dat(T20100813以降)
  2. //【ラベル】 ニコニコ動画のステータスを表示
  3. //【コマンド】 ${SCRIPT:Frx} PopupStatusNicovideo.js
  4. // URLExec.datの場合は ${V2CSCRIPT:Frx} PopupStatusNicovideo.js
  5. //【内容】 ニコニコ動画のステータスをポップアップする
  6. //【スクリプト】 "PopupStatusNicovideo.js"と"PopupStatusNicovideo"フォルダをV2C保存用フォルダのscriptフォルダに入れる
  7. //
  8. //設定
  9. var closeOnLinkClicked = true;//外部リンクをクリックした場合、ポップアップを閉じる
  10. var closeOnMouseExit = true;//ポップアップ上から離れた場合、ポップアップを閉じる
  11. var browseExt = false;//外部ブラウザで開く(falseだとJDICがあれば内部ブラウザで開く)
  12. var maxPopupWidth = 429;//ポップアップの最大横サイズ[px]、本来のhtmlサイズ調整用(0で調整なし、この場合、右に余分なスペース有)
  13. var addLinkNicoDic = false;//タグの後に、ニコニコ大百科のリンクを付加 ※ポップアップまでに時間がかかる場合があります(この場合、ステータスバーに「取得中...」が表示)
  14. var urlExec = true;// リンククリック時、URLExec.datの設定に従うかどうか
  15. var browserPath = false;//URLEcex.datの設定に従うときに使用する規定のブラウザのパス(「\」は「/」に置換してください)
  16.  
  17. //実行
  18. var vcx = v2c.context;
  19. var nvstream = '';
  20. GetStatus();
  21.  
  22. function redirectURL(u) {
  23. if (u) {
  24. if(!(urlExec && openURLExec(u)))
  25. browseExt ? v2c.browseURLExt(u) : v2c.browseURL(u);
  26. if(!closeOnLinkClicked){
  27. vcx.setPopupHTML(nvstream);
  28. if(closeOnMouseExit) vcx.setCloseOnMouseExit(true);
  29. if(maxPopupWidth) vcx.setMaxPopupWidth(maxPopupWidth);
  30. vcx.setRedirectURL(true);
  31. }
  32. }
  33. return;
  34. }
  35. function replaceStr(str,nl){
  36. /*
  37.  * Available HTML tags. -> <font ( color,size ) > , <br> , <b> , <i> , <s> , <u>
  38.  * These letters must be in HTML Form. -> & = &amp; , " = &quot; , < = &lt; , > = &gt; , ' = &#039;
  39.  */
  40. str = str
  41. // タグとしての'<'は"&lt;"、文字としては"&amp;lt;"となっている。
  42. // <br>が連続している場合は1つにする。
  43. .replace(/(?:&lt;br(?:\s*\/)&gt;)+/ig, "<br/>")
  44. // <(font|b|i|s|u)>は無視してテキストだけ取り出す。
  45. // それ以外のタグはニコニコ側ではサポートされていないため、タグのつもりではない(生文字列)と判断。
  46. .replace(/&lt;((?:font|b|i|s|u))(\s+.*?)&gt;(.*?)&lt;\/\1&gt;/ig,
  47. function(str, tag, attributes, value) {
  48. return value;
  49. })
  50. .replace(/&amp;/ig, "&")
  51. .replace(/&apos;/ig, "&#039;"); // &apos;はpopup時に解釈してくれないので置換
  52.  
  53. if(nl) {
  54. str = str.replace(/((?:mylist|user)\/\d+)/ig, '<a href="http://w...content-available-to-author-only...o.jp/$1">$1</a>');
  55. str = str.replace(/([sn]{1}m\d+)/ig, '<a href="http://w...content-available-to-author-only...o.jp/watch/$1">$1</a>');
  56. }
  57. return str;
  58. }
  59. function replaceNum(num){
  60. return num = num.replace(/(\d)(?=(\d{3})+(?!\d))/g,"$1,");
  61. }
  62. // 正規表現を用いない replaceAll()
  63. function replaceAll(s, oldValue, newValue) {
  64. return (s + '').split(oldValue).join(newValue);
  65. }
  66. function GetStatus(){
  67. //選択文字列のチェック
  68. var ss = (v2c.getSelectedText() || vcx.link || vcx.res.message)+"";
  69. if(ss){
  70. ss = ss.replace(/^\s+|\s+$/g, "");
  71. }
  72. if(!ss||(ss.length==0)){
  73. v2c.alert('テキスト取得失敗');
  74. return;
  75. }
  76.  
  77. //選択文字列からIDを抽出
  78. //”sm”などを含む以降の数値をIDとする
  79. var rgex = new RegExp('(?:\\?|/|#|)((?:[a-z]{2})\\d+)');
  80. //var rgex = new RegExp('(?:(?:www|tw|es|de|m)\\.nicovideo.jp/watch|nico.ms)/(\\w{2}\\d+)');
  81. var video_id = (ss.match(rgex) || [])[1];
  82. if(!video_id){
  83. v2c.alert('ID取得失敗');
  84. return;
  85. }
  86.  
  87. var prefixIdPattern = {
  88. supported: /^(?:ax|c[adw]|c[dw]|f[xz]|ig|n[alm]|om|s[dkm]|y[ko]|z[a-e]|so)\d+/,
  89. unsupported: /^(?:lv|im|co|ar|mg|bk|nw)\d+/
  90. };
  91. if(0 <= video_id.search(prefixIdPattern.unsupported)) {
  92. v2c.println('動画ではないか、既知のサポートされていないIDです。 ' + video_id);
  93. return;
  94. }
  95. else if(video_id.search(prefixIdPattern.supported) < 0) {
  96. v2c.println('未知のIDです。取得を試みます。 ' + video_id);
  97. }
  98.  
  99. if (vcx.getPopupOfID(video_id)) {
  100. vcx.closeOriginalPanel();
  101. return;
  102. }
  103. var url = 'http://e...content-available-to-author-only...o.jp/api/getthumbinfo/' + video_id;
  104. v2c.setStatus('動画情報、取得中...');
  105. var source = readURL(url);
  106. v2c.setStatus('');
  107. if (!source) {
  108. v2c.alert('ページを取得できませんでした。');
  109. return;
  110. } else if (source.indexOf('nicovideo_thumb_response status="fail"') > -1){
  111. if(source.indexOf('<code>DELETED</code>') > -1) {
  112. v2c.alert('この動画は削除されました。');
  113. } else {
  114. v2c.alert('動画を取得できませんでした。');
  115. }
  116. return;
  117. }
  118. //ステータスの変数宣言
  119. var title = " - ";
  120. var description = " - ";
  121. var all_description = " - ";
  122. var thumbnail_url = " - ";
  123. var first_retrieve = " - ";
  124. var length = " - ";
  125. var movie_type = " - ";
  126. var size_high = " - ";
  127. var kB_size_high = " - ";
  128. var MB_size_high = " - ";
  129. var size_low = " - ";
  130. var kB_size_low= " - ";
  131. var MB_size_low= " - ";
  132. var view_counter = " - ";
  133. var comment_num = " - ";
  134. var mulist_counter = " - ";
  135. var last_res_body = " - ";
  136. var watch_url = " - ";
  137. var thumb_type = " - ";
  138. var embeddable = "ー";
  139. var live_play = "ー";
  140. var jp_category_tag = "";
  141. var jp_lock_tag = "";
  142. var jp_free_tag = "";
  143. var jp_tag = "";
  144. var tw_tag = "";
  145. var de_tag = "";
  146. var es_tag = "";
  147. var user_id = "";
  148.  
  149. //タイトル取得
  150. if(source.match(/title>(.+?)<\/title>/i)){
  151. title = replaceStr(RegExp.$1);
  152. }
  153. //説明取得
  154. if(source.match(/description>(.+?)<\/description>/i)){
  155. var rawDescription = RegExp.$1;
  156. description = replaceStr(rawDescription);
  157. all_description = replaceStr(rawDescription,true);
  158. if (description.length > 100) description = description.substring(0, 100)+'..';
  159. }
  160. //サムネイルのURL取得
  161. if(source.match(/thumbnail_url>(.+?)<\/thumbnail_url>/i)){
  162. thumbnail_url = RegExp.$1;
  163. }
  164. //投稿時間取得
  165. if(source.match(/first_retrieve>(.+?)<\/first_retrieve>/i)){
  166. var d= (RegExp.$1).match(/\d{2}/g);
  167. first_retrieve = d[1]+'/'+d[2]+'/'+d[3]+' '+d[4]+':'+d[5];
  168. }
  169. //再生時間取得
  170. if(source.match(/length>(.+?)<\/length>/i)){
  171. length = RegExp.$1;
  172. }
  173. //形式取得
  174. if(source.match(/movie_type>(.+?)<\/movie_type>/i)){
  175. movie_type = RegExp.$1;
  176. }
  177. //サイズ(高画質)取得
  178. if(source.match(/size_high>(.+?)<\/size_high>/i)){
  179. size_high = RegExp.$1;
  180. kB_size_high = (parseInt(size_high)/1024).toFixed(1);
  181. MB_size_high = (parseInt(kB_size_high)/1024).toFixed(2);
  182. }
  183. //サイズ(低画質)取得
  184. if(source.match(/size_low>(.+?)<\/size_low>/i)){
  185. size_low = RegExp.$1;
  186. kB_size_low = (parseInt(size_low)/1024).toFixed(1);
  187. MB_size_low = (parseInt(kB_size_low)/1024).toFixed(2);
  188. }
  189. //再生数取得
  190. if(source.match(/view_counter>(.+?)<\/view_counter>/i)){
  191. view_counter = replaceNum(RegExp.$1);
  192. }
  193. //コメント数取得
  194. if(source.match(/comment_num>(.+?)<\/comment_num>/i)){
  195. comment_num = replaceNum(RegExp.$1);
  196. }
  197. //マイリスト数取得
  198. if(source.match(/mylist_counter>(.+?)<\/mylist_counter>/i)){
  199. mylist_counter = replaceNum(RegExp.$1);
  200. }
  201. //最近のコメント取得
  202. if(source.match(/last_res_body>(.+?)<\/last_res_body>/i)){
  203. last_res_body = replaceStr(RegExp.$1);
  204. }
  205. //動画のURL取得
  206. if(source.match(/watch_url>(.+?)<\/watch_url>/i)){
  207. watch_url = RegExp.$1;
  208. }
  209. //通常かマイメモリか取得
  210. if(source.match(/thumb_type>(.+?)<\/thumb_type>/i)){
  211. thumb_type = RegExp.$1;
  212. }
  213. //外部からの埋め込み再生可否取得
  214. if(source.match(/embeddable>(.+?)<\/embeddable>/i)){
  215. embeddable = RegExp.$1 == "1" ? "○" : "×";
  216. }
  217. //生放送の引用可否取得
  218. if(source.match(/live_play>(.+?)<\/no_live_play>/i)){
  219. live_play = RegExp.$1 == "1" ? "×" : "○";
  220. }
  221. //日本タグ取得
  222. rgex = new RegExp('<tag.*?>([^><]+)','ig');
  223. rgex.lastIndex = source.indexOf('<tags domain="jp">')+1;
  224. var readDicApi = function( kw ) {
  225. v2c.setStatus('タグの大百科有無、取得中...');
  226. var dic = kw ? readURL('http://a...content-available-to-author-only...c.jp/e/n/' + kw) + '' : '';
  227. v2c.setStatus('');
  228. if(dic && dic.indexOf('1') > 0) {
  229. return '&nbsp;' + '<a href="http://d...content-available-to-author-only...o.jp/a/' + kw
  230. + '" class="dic_on">百</a>' + ' ';
  231. // + '"><img src="http://r...content-available-to-author-only...g.jp/img/common/icon/dic_on.png" alt="大百科" border="0"></a>' + ' '; //↑行と置換でアイコン表示、ただポップサイズが崩れる
  232. } else {
  233. return '&nbsp;' + '<a href="http://d...content-available-to-author-only...o.jp/a/' + kw
  234. + '" class="dic_off">?</a>' + ' ';
  235. // + '"><img src="http://r...content-available-to-author-only...g.jp/img/common/icon/dic_off.png" alt="大百科" border="0"></a>' + ' '; //↑行と置換でアイコン表示、ただポップサイズが崩れる
  236. }
  237. }
  238. var keyword = '';
  239. while(rgex.exec(source) != null){
  240. if(RegExp.lastMatch.indexOf('category') > -1) {
  241. keyword = encodeURIComponent(RegExp.lastParen);
  242. jp_category_tag += '<a href = "http://w...content-available-to-author-only...o.jp/tag/'
  243. + keyword + '" class="category_tag">' + RegExp.lastParen + '</a>';
  244. jp_category_tag += addLinkNicoDic ? readDicApi( keyword ) : ' ';
  245. } else if(RegExp.lastMatch.indexOf('lock') > -1) {
  246. keyword = encodeURIComponent(RegExp.lastParen);
  247. jp_lock_tag += '<a href = "http://w...content-available-to-author-only...o.jp/tag/'
  248. + keyword + '" class="lock_tag">' + RegExp.lastParen + '</a>';
  249. jp_lock_tag += addLinkNicoDic ? readDicApi( keyword ) : ' ';
  250. } else {
  251. keyword = encodeURIComponent(RegExp.lastParen);
  252. jp_free_tag += '<a href = "http://w...content-available-to-author-only...o.jp/tag/'
  253. + keyword + '" class="free_tag">' + RegExp.lastParen + '</a>';
  254. jp_free_tag += addLinkNicoDic ? readDicApi( keyword ) : ' ';
  255. }
  256. if(RegExp.rightContext.search(/^<\/tag>\n<\/tags>/i) == 0) break;
  257. }
  258. if(jp_category_tag == "") jp_category_tag = replaceStr(jp_category_tag);
  259. if(jp_lock_tag == "") jp_lock_tag = replaceStr(jp_lock_tag);
  260. if(jp_free_tag == "") jp_free_tag = replaceStr(jp_free_tag);
  261. jp_tag = jp_category_tag + jp_lock_tag + jp_free_tag;
  262. //台湾タグ取得
  263. rgex = new RegExp('<tag.*?>([^><]+)','ig');
  264. rgex.lastIndex = source.indexOf('<tags domain="tw">')+1;
  265. while(rgex.exec(source) != null){
  266. tw_tag += '<a href = "http://t...content-available-to-author-only...o.jp/tag/'
  267. + encodeURIComponent(RegExp.lastParen) + '">' + RegExp.lastParen + '</a>';
  268. if(RegExp.rightContext.search(/^<\/tag>\n<\/tags>/i) == 0) break;
  269. tw_tag += "&nbsp;";
  270. }
  271. //ドイツタグ取得
  272. rgex = new RegExp('<tag.*?>([^><]+)','ig');
  273. rgex.lastIndex = source.indexOf('<tags domain="de">')+1;
  274. while(rgex.exec(source) != null){
  275. de_tag += '<a href = "http://d...content-available-to-author-only...o.jp/tag/'
  276. + encodeURIComponent(RegExp.lastParen) + '">' + RegExp.lastParen + '</a>';
  277. if(RegExp.rightContext.search(/^<\/tag>\n<\/tags>/i) == 0) break;
  278. de_tag += "&nbsp;";
  279. }
  280. de_tag = replaceStr(de_tag);
  281. //スペインタグ取得
  282. rgex = new RegExp('<tag.*?>([^><]+)','ig');
  283. rgex.lastIndex = source.indexOf('<tags domain="es">')+1;
  284. while(rgex.exec(source) != null){
  285. es_tag += '<a href = "http://e...content-available-to-author-only...o.jp/tag/'
  286. + encodeURIComponent(RegExp.lastParen) + '">' + RegExp.lastParen + '</a>';
  287. if(RegExp.rightContext.search(/^<\/tag>\n<\/tags>/i) == 0) break;
  288. es_tag += "&nbsp;";
  289. }
  290. es_tag = replaceStr(es_tag);
  291. //ユーザーID取得
  292. if(source.match(/user_id>(.+?)<\/user_id>/i)){
  293. user_id = RegExp.$1;
  294. }
  295.  
  296. //htmlテンプレートの読み込み
  297. var fs = java.io.File.separator;
  298. nvstream = v2c.readFile(v2c.saveDir
  299. +fs+fs+'script'+fs+fs+'PopupStatusNicovideo'+fs+fs+'template.txt');
  300.  
  301. //パラメータの置換
  302. nvstream = replaceAll(nvstream,"%video_id%",video_id);
  303. nvstream = replaceAll(nvstream,"%title%",title);
  304. nvstream = replaceAll(nvstream,"%description%",description);
  305. nvstream = replaceAll(nvstream,"%all_description%",all_description);
  306. nvstream = replaceAll(nvstream,"%thumbnail_url%",thumbnail_url);
  307. nvstream = replaceAll(nvstream,"%first_retrieve%",first_retrieve);
  308. nvstream = replaceAll(nvstream,"%length%",length);
  309. nvstream = replaceAll(nvstream,"%movie_type%",movie_type);
  310. nvstream = replaceAll(nvstream,"%size_high%",size_high);
  311. nvstream = replaceAll(nvstream,"%kB_size_high%",kB_size_high);
  312. nvstream = replaceAll(nvstream,"%MB_size_high%",MB_size_high);
  313. nvstream = replaceAll(nvstream,"%size_low%",size_low);
  314. nvstream = replaceAll(nvstream,"%kB_size_low%",kB_size_low);
  315. nvstream = replaceAll(nvstream,"%MB_size_low%",MB_size_low);
  316. nvstream = replaceAll(nvstream,"%view_counter%",view_counter);
  317. nvstream = replaceAll(nvstream,"%comment_num%",comment_num);
  318. nvstream = replaceAll(nvstream,"%mylist_counter%",mylist_counter);
  319. nvstream = replaceAll(nvstream,"%movie_type%",movie_type);
  320. nvstream = replaceAll(nvstream,"%last_res_body%",last_res_body);
  321. nvstream = replaceAll(nvstream,"%watch_url%",watch_url);
  322. nvstream = replaceAll(nvstream,"%thumb_type%",thumb_type);
  323. nvstream = replaceAll(nvstream,"%embeddable%",embeddable);
  324. nvstream = replaceAll(nvstream,"%live_play%",live_play);
  325. nvstream = replaceAll(nvstream,"%jp_category_tag%",jp_category_tag);
  326. nvstream = replaceAll(nvstream,"%jp_lock_tag%",jp_lock_tag);
  327. nvstream = replaceAll(nvstream,"%jp_free_tag%",jp_free_tag);
  328. nvstream = replaceAll(nvstream,"%jp_tag%",jp_tag);
  329. nvstream = replaceAll(nvstream,"%tw_tag%",tw_tag);
  330. nvstream = replaceAll(nvstream,"%de_tag%",de_tag);
  331. nvstream = replaceAll(nvstream,"%es_tag%",es_tag);
  332. nvstream = replaceAll(nvstream,"%user_id%",user_id);
  333.  
  334. //ポップアップ表示
  335. vcx.setPopupHTML(nvstream);
  336. if(closeOnMouseExit) vcx.setCloseOnMouseExit(true);
  337. if(maxPopupWidth) vcx.setMaxPopupWidth(maxPopupWidth);
  338. vcx.setRedirectURL(true);
  339. vcx.setPopupID(video_id);
  340. return;
  341. }
  342.  
  343. function openURLExec( url ) {
  344. var url = new java.lang.String( url );
  345. var fs = java.io.File.separator;
  346. var tmp = v2c.readFile( v2c.saveDir + fs + 'URLExec.dat', 'Shift-JIS' );
  347. if ( !tmp ) {
  348. v2c.println( 'URLExec.datが見つかりませんでした' );
  349. return false;
  350. }
  351. var lines = tmp.split( '\r\n' );
  352. var ptn = java.util.regex.Pattern.compile("^(?<!;|'|//)([^\t]+\t){2}[^\t]+$");
  353. for( var i=0,len=lines.length; i<len; i++ ) {
  354. var matcher = ptn.matcher(lines[i]);
  355. if ( matcher.matches() ) {
  356. //v2c.println( '有効行:' + matcher.group(0) );
  357. } else {
  358. //v2c.println( '!無効行:' + lines[i] );
  359. continue;
  360. }
  361.  
  362. var matchFlg = false;
  363. var item = lines[i].split( '\t' );
  364. if ( item.length != 3 ) { // 念のため
  365. v2c.println( 'Tabの数が不正:' + (item.length-1) );
  366. continue;
  367. }
  368. item[1] = (new java.lang.String(item[1])).replaceAll( '\\$&', '\\$0' );
  369.  
  370. try {
  371. var ptn2 = java.util.regex.Pattern.compile(item[0]);
  372. } catch( e ) { // 不正な正規表現を無視
  373. v2c.println( e );
  374. continue;
  375. }
  376. if ( ptn2.matcher(url).find() ) {
  377. matchFlg = true;
  378. url = url.replaceFirst( item[0], item[1] );
  379. break;
  380. }
  381. }
  382. if ( !matchFlg ) {
  383. v2c.println( 'URLExec.dat:マッチなし\n' + url );
  384. return false;
  385. }
  386.  
  387. var cmds = item[2].split( ' ' );
  388. if ( cmds.length == 0 ) {
  389. v2c.println( 'URLExec.dat:コマンドがありません' );
  390. return false;
  391. }
  392. for ( i=0; i<cmds.length; i++ ) {
  393. var matcher = java.util.regex.Pattern.compile('\\$VIEW').matcher(cmds[i]);
  394. if ( matcher.find() ) {
  395. if ( i==0 ){
  396. v2c.println( 'URLExec.dat:無効なキーワード"$VEIW"' );
  397. return false;
  398. }
  399. }
  400.  
  401. // $BROWSER
  402. if ( browserPath ) {
  403. cmds[i] = cmds[i].replaceAll( '\\$BROWSER', browserPath );
  404. } else {
  405. // ブラウザを指定していない場合で、更にURLExec.datのコマンドが、
  406. // ブラウザにURLを渡すだけの場合はデフォルト外部ブラウザで開く(応急処置)
  407. if( item[2].matches( '"?\\$BROWSER"? "?\\$(URL|LINK)"?' ) ) { //完全一致
  408. v2c.browseURLDefExt(url);
  409. v2c.println( 'cmd='+item[2] );
  410. return true;
  411. }
  412. }
  413.  
  414. // $LINK 置換しない場合は、この下の行をコメントアウト
  415. cmds[i] = cmds[i].replaceAll( '\\$LINK', url );
  416.  
  417. // $URL 置換しない場合は、この下行をコメントアウト
  418. cmds[i] = cmds[i].replaceAll( '\\$URL', url );
  419.  
  420. // $BASEPATH
  421. if ( i==0 ) { // コマンドの場合
  422. cmds[i] = cmds[i].replaceAll( '\\$BASEPATH', v2c.saveDir.toString()
  423. .replaceAll( '\\\\', '/' ) + '/' );
  424. } else { // 引数の場合
  425. cmds[i] = cmds[i].replaceAll( '\\$BASEPATH', v2c.saveDir.toString()
  426. .replaceAll( '\\\\', '\\\\\\\\' ) + '\\\\' );
  427. }
  428.  
  429. // $POSX $POSY
  430. var p = v2c.context.mousePos;
  431. if ( p ) {
  432. cmds[i] = cmds[i].replaceAll( '\\$POSX', p.x );
  433. cmds[i] = cmds[i].replaceAll( '\\$POSY', p.y );
  434. }
  435. v2c.println( 'cmd['+i+']='+cmds[i] );
  436. }
  437.  
  438. v2c.exec(cmds);
  439. return true;
  440. }
  441. function readURL(url) {
  442. var req = v2c.createHttpRequest(url);
  443. var res = req.getContentsAsString();
  444. if(req.responseCode != 200) {
  445. return null;
  446. }
  447. return res;
  448. }
Runtime error #stdin #stdout #stderr 0.53s 383168KB
stdin
Standard input is empty
stdout
Standard output is empty
stderr
js: uncaught JavaScript runtime exception: ReferenceError: "v2c" is not defined.