fork download
  1. //【登録場所】リンク、URLExec
  2. //【ラベル】Youtube動画情報
  3. //【内容】Youtube動画情報のポップアップ
  4. //【コマンド】${SCRIPT:FrxS} PopupStatusYoutube.js
  5. //【URLExec*】https?://(?:\w+\.)?youtube\.(?:\w+|co\.\w+)/.*?v=[\-_\w]{11}.* $& ${V2CSCRIPT:FrxS} PopupStatusYoutube.js
  6. //【URLExec*(短縮URL用)】http://youtu\.be/[\-_\w]{11} $& ${V2CSCRIPT:FrxS} PopupStatusYoutube.js
  7. //【更新日時】2013/09/11 再生できない動画のステータスのyt:state name=processing時にスクリプトエラーが発生するケースの回避コードを追加
  8. //【スクリプト】
  9.  
  10. // 実行時間計測用
  11. // var odate = new Date;
  12.  
  13. // ============ 設定ここから ============
  14. var closePopup = true;// リンククリックでポップアップを閉じるかどうか
  15. var browseExt = false;// リンククリック時、外部ブラウザで開くかどうか(urlExecが優先)
  16. var urlExec = true;// リンククリック時、URLExec.datの設定に従うかどうか
  17. var browserPath = 'C:/Program Files/Internet Explorer/iexplore.exe';//URLEcex.datの設定に従うときに使用する規定のブラウザのパス(「\」は「/」に置換してください)
  18. var zeroDate = true;// 日付の桁揃えをするかどうか
  19. var zeroTime = true;// 時間の桁揃えをするかどうか
  20. var commentMax = 500;// 表示する投稿者コメントの最大文字数(0で無制限)
  21. var formatType = 2;// 数値のフォーマット(0:なし 1:3桁カンマ区切り 2:日本語表記)
  22. var tagSeparater = ' ';//タグの区切り文字(半角スペースは )
  23. var maxPopupWidth = 500;// ポップアップの最大横幅
  24. var closeOnMouseExit = true;// ポップアップからマウスカーソルを外した時、自動的に閉じるかどうか
  25. var errorPopup = true;// エラーの時、エラー内容をポップアップとして表示
  26. var ratingBarWidth = 150;// レーティングバーの長さ(単位pxを想定)
  27. var downloaderPath = '';// ダウンローダのパス(「\」は「/」に置換してください)
  28. var downloaderArgs = '$PSYURL';// ダウンローダに渡す引数($PSYURLを動画URLに置換して渡します)
  29. var popupFocusable = true;// ポップアップの文字列を選択できるようにするかどうか
  30. // ============ 設定ここまで ============
  31.  
  32. var info = [];
  33. v2c.setStatus('PopupStatusYoutubeスクリプト実行中...');
  34. PopupStatusYoutube();
  35.  
  36. // v2c.print( '実行時間:'+ (new Date - odate) + 'msec\n' );
  37.  
  38. // リンククリック時に呼ばれる関数
  39. function redirectURL( u ) {
  40. if ( u ) {
  41. // ポップアップを再度開く
  42. if ( !closePopup ) {
  43. v2c.context.setPopupHTML( html );
  44. v2c.context.setMaxPopupWidth( maxPopupWidth );
  45. v2c.context.setRedirectURL( true );
  46. v2c.context.setPopupID( info.vid );
  47. v2c.context.setPopupFocusable( popupFocusable );
  48. }
  49. // URLExec
  50. if ( urlExec ) {
  51. v2c.println('teste');
  52. var f = openURLExec( u );
  53. if (f) return;
  54. }
  55. // 外部ブラウザで開く
  56. if ( browseExt ) {
  57. v2c.println('teste');
  58. v2c.browseURLExt( u );
  59. }
  60. // JDICがあれば内部ブラウザで開く
  61. else{
  62. v2c.browseURL( u );
  63. }
  64. }
  65. return;
  66. }
  67.  
  68. function formSubmitted ( u, sm, sd ) {
  69. var data = '';
  70. if ( sd.match( /(.+)=.+/i ) ) {
  71. var data = RegExp.$1;
  72. data = decodeURIComponent(data);
  73. switch (data) {
  74. case 'Fix':
  75. v2c.context.closeOriginalPanel();
  76. closePopup = true;
  77. v2c.context.setPopupHTML( html );
  78. v2c.context.setCloseOnLinkClick( false )
  79. v2c.context.setCloseOnMouseExit( false );
  80. v2c.context.setMaxPopupWidth( maxPopupWidth );
  81. v2c.context.setTrapFormSubmission( true );
  82. v2c.context.setRedirectURL( true );
  83. v2c.context.setPopupID( info.vid );
  84. v2c.context.setPopupFocusable( popupFocusable );
  85. break;
  86. case 'DL':
  87. if ( downloaderPath ) {
  88. downloaderArgs = downloaderArgs.replace( /\$PSYURL/, info.url );
  89. v2c.exec( [ downloaderPath, downloaderArgs ] );
  90. } else {
  91. v2c.alert( 'ダウンローダーのパスを設定してください' );
  92. }
  93. break;
  94. case 'Ext':
  95. // 外部ブラウザボタンクリック時、
  96. // ポップアップを閉じない場合はこの下の行をコメントアウト
  97. v2c.context.closeOriginalPanel();
  98. v2c.browseURLExt( info.url );
  99. break;
  100. case 'CopyTitle':
  101. v2c.context.setClipboardText( info.title );
  102. break;
  103. case 'CopyURL':
  104. v2c.context.setClipboardText( info.url );
  105. break;
  106. case 'CopyTytle+URL':
  107. v2c.context.setClipboardText( info.title + '\n' + info.url );
  108. break;
  109. case 'CopyInfo':
  110. var str = info.title + '\n'
  111. + info.url + '\n'
  112. + '再生時間:' + info.time
  113. + '\n投稿者名:' + info.name
  114. + '\n投稿日時:' + info.ye + '/' + info.mo + '/' + info.da + ' ' + info.ho + ':' + info.mi + ':' + info.se
  115. + '\n再生回数:' + info.viewCount
  116. + '回\nお気に入り:' + info.favCount
  117. + '\n評価:高評価 ' + info.like + ' 人、低評価 ' + info.dislike + ' 人';
  118. v2c.context.setClipboardText( str );
  119. break;
  120. }
  121. }
  122. return;
  123. }
  124.  
  125. function PopupStatusYoutube() {
  126. info.vid = ''; // 動画ID
  127. info.url = ''; // 動画URL
  128. info.thumb = ''; // サムネイルURL
  129. info.title = ''; // 動画タイトル
  130. info.date = ''; // 投稿日時
  131. info.ye = ''; // 西暦
  132. info.mo = ''; // 月
  133. info.da = ''; // 日
  134. info.ho = ''; // 時
  135. info.mi = ''; // 分
  136. info.se = ''; // 秒
  137. info.ms = ''; // ミリ秒 ※多分常に0
  138. info.name = ''; // 投稿者名
  139. info.uri = ''; // 投稿者URI
  140. info.keywords = 'なし'; // キーワード(タグ)
  141. info.time = ''; // 再生時間
  142. info.viewCount = '0'; // 再生回数
  143. info.favCount = '0'; // お気に入り数
  144. info.comment = '説明はありません'; // 投稿者コメント
  145. info.like = 0; // 高評価
  146. info.dislike = 0; // 低評価
  147. info.likeWidth = 0; // 高評価バーの長さ
  148. info.state = ''; // エラー情報
  149.  
  150. // ポップアップIDの初期化
  151. var pid = 'idstring';
  152.  
  153. // URLオブジェクトの取得
  154. var url = v2c.context.link;
  155. info.url = url;
  156.  
  157. // URLオブジェクトがあるかどうかの確認
  158. if ( !url ) {
  159. v2c.print( 'URL取得失敗\n\n' );
  160. if ( errorPopup ) onErrorPopup( 'URL取得失敗' );
  161. return;
  162. }
  163.  
  164. // URLがYoutubeかどうか
  165. if ( url.toString().match( /h?t?tps?:\/\/(?:\w+\.)?youtube\.(?:\w+|co\.\w+)\/.*?v=([\-_\w]{11}).*/i ) ) {
  166. info.vid = RegExp.$1;
  167. var xmlUrl = 'http://g...content-available-to-author-only...e.com/feeds/api/videos/' + info.vid;
  168. } else if ( url.toString().match( /h?t?tps?:\/\/youtu\.be\/([\-_\w]{11})/i ) ) {
  169. info.vid = RegExp.$1;
  170. var xmlUrl = 'http://g...content-available-to-author-only...e.com/feeds/api/videos/' + info.vid;
  171. }
  172. else{
  173. if ( errorPopup ) onErrorPopup( 'YoutubeのURLではない' );
  174. v2c.print( 'Error:YoutubeのURLではない\n' );
  175. return;
  176. }
  177.  
  178. // VIDEO_ID取得失敗
  179. if ( !info.vid ) {
  180. v2c.print( 'Error:VIDEO_ID取得失敗\n' + url + '\n' );
  181. if ( errorPopup ) onErrorPopup( 'VIDEO_ID取得失敗' );
  182. return;
  183. }
  184.  
  185. // 同じURLのポップアップを開いていたら終了
  186. if ( v2c.context.getPopupOfID( info.vid ) ) {
  187. v2c.print( 'Error:同じURLのポップアップ\n' );
  188. return;
  189. }
  190.  
  191. // XML DOMオブジェクトの作成
  192. try {
  193. var dbf = javax.xml.parsers.DocumentBuilderFactory.newInstance();
  194. var db = dbf.newDocumentBuilder();
  195. var doc = db.parse( xmlUrl ); // GET
  196. }
  197. catch (e) {
  198. v2c.print( 'Error:XMLの取得に失敗\n' + e + '\n' );
  199. if ( errorPopup ) {
  200. if ( e.toString().indexOf('java.io.FileNotFoundException') != -1 ) {
  201. onErrorPopup( 'この動画は削除されています', info.vid );
  202. } else if ( e.toString().indexOf('Server returned HTTP response code: 403') != -1 ) {
  203. onErrorPopup( '動画情報にアクセス出来ません\nこの動画は非公開等の理由で閲覧できない可能性があります', info.vid );
  204. } else {
  205. onErrorPopup( '動画情報へのアクセスに失敗しました', info.vid );
  206. }
  207. }
  208. return;
  209. }
  210.  
  211. // XML解析
  212. traceNodes( doc );
  213.  
  214. // 投稿日時をUTC→ローカル時間に ISO8601形式 例:2010-01-01T00:00:00.000Z
  215. if( info.date.match( /(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})\.(\d{3})Z/ ) ) {
  216. var dd = new Date( RegExp.$1, RegExp.$2, RegExp.$3, RegExp.$4, RegExp.$5, RegExp.$6, RegExp.$7 );
  217. info.ye = dd.getUTCFullYear().toString();
  218. info.mo = dd.getUTCMonth().toString();
  219. info.da = dd.getUTCDate().toString();
  220. info.ho = dd.getUTCHours().toString();
  221. info.mi = dd.getUTCMinutes().toString();
  222. info.se = dd.getUTCSeconds().toString();
  223. info.ms = dd.getUTCMilliseconds().toString();
  224.  
  225. // 12月=0月?
  226. if ( info.mo==0 ) {
  227. info.mo = '12';
  228. }
  229.  
  230. // 日付の桁揃え
  231. if ( zeroDate ) {
  232. info.mo = zeroPlus( info.mo );
  233. info.da = zeroPlus( info.da );
  234. }
  235.  
  236. // 時間の桁揃え
  237. if ( zeroTime ) {
  238. info.ho = zeroPlus( info.ho );
  239. info.mi = zeroPlus( info.mi );
  240. info.se = zeroPlus( info.se );
  241. }
  242. }
  243.  
  244. // キーワードにリンクを付ける
  245. info.keywords = info.keywords.replace( ' ', '' );
  246. info.keywords = info.keywords.replace( ' ', '' );
  247. tmp = info.keywords.split( ',' );
  248. if ( info.keywords != 'なし' ) {
  249. info.keywords = '';
  250. for ( i = 0; i < tmp.length; i++ ) {
  251. info.keywords = info.keywords
  252. + '<a href="http://w...content-available-to-author-only...e.com/results?search_query='
  253. + encodeURIComponent( tmp[i] ) + '&search=tag">'
  254. + tmp[i] + '</a>' + tagSeparater;
  255. }
  256. }
  257.  
  258. // 再生時間の整形
  259. info.time = zeroPlus( parseInt( info.time / 3600 ) ) + ':'
  260. + zeroPlus( parseInt ( ( info.time % 3600 ) / 60 ) ) + ':'
  261. + zeroPlus( ( info.time % 3600 ) % 60 );
  262.  
  263. // コメントの文字数制限の適用
  264. // コメントをjavascriptのString形式に変換
  265. info.comment += '';
  266. if ( commentMax ) {
  267. tmp = info.comment;
  268. tmp2 = 0;
  269. reg = new RegExp( '(https?:\/\/[\-_\.!~*\'\(\)a-zA-Z0-9;\/\?:\@&=?+\$,%#]+)', 'i' );
  270. // コメント中のURLが途中で切れないようにするための処理
  271. while(1){
  272. if( tmp.match( reg ) ) {
  273. tmp2 = tmp2 + RegExp.leftContext.length + RegExp.$1.length;
  274. if( tmp2 > commentMax ){
  275. commentMax = tmp2;
  276. break;
  277. }
  278. tmp = RegExp.rightContext;
  279. }
  280. else{
  281. break;
  282. }
  283. }
  284. // コメントのカット
  285. if ( info.comment.length > commentMax ) {
  286. info.comment = info.comment.slice( 0, commentMax ) + ' ...';
  287. }
  288. }
  289. // コメントにリンクを付ける
  290. tmp = info.comment;
  291. info.comment = '';
  292. while (1) {
  293. if ( tmp.match( reg ) ) {
  294. info.comment = info.comment + RegExp.leftContext
  295. + '<a href="' + RegExp.$1 + '">' + RegExp.$1 + '</a>';
  296. tmp = RegExp.rightContext;
  297. }
  298. else {
  299. info.comment += tmp;
  300. break;
  301. }
  302. }
  303.  
  304. // 数値の整形
  305. info.viewCount = formatNum( info.viewCount, formatType );
  306. info.favCount = formatNum( info.favCount, formatType );
  307.  
  308. // 置換文字に「$」が入っているとエラーが出る問題の修正
  309. info.title = (info.title+'').replace( /\$/g, '$' );
  310. info.comment = (info.comment+'').replace( /\$/g, '$' );
  311. info.keywords = (info.keywords+'').replace( /\$/g, '$' );
  312.  
  313. // エラーの場合コメントにエラーの理由を設定
  314. if ( !info.thumb && info.state ) {
  315. if ( errorPopup ) onErrorPopup( info.state );
  316. v2c.print( 'Error:' + info.state + '\n' );
  317. return;
  318. }
  319.  
  320. // テンプレートを読み込み
  321. var fs = java.io.File.separator;
  322. html = v2c.readFile( v2c.saveDir + fs + 'script' + fs + 'PopupStatusYoutube'
  323. + fs + 'template.txt' );
  324.  
  325. // デバッグ用 変数出力
  326. //for ( i in info ) { v2c.print( 'info.' + i + ' = ' + info[i] + '\n' ); }
  327.  
  328. // パラメータの置換
  329. html = html.replaceAll( '%vid%', info.vid )
  330. .replaceAll( '%thumb%', info.thumb )
  331. .replaceAll( '%title%', info.title )
  332. .replaceAll( '%ye%', info.ye )
  333. .replaceAll( '%mo%', info.mo )
  334. .replaceAll( '%da%', info.da )
  335. .replaceAll( '%ho%', info.ho )
  336. .replaceAll( '%mi%', info.mi )
  337. .replaceAll( '%comment%', info.comment )
  338. .replaceAll( '%name%', info.name )
  339. .replaceAll( '%uri%', info.uri )
  340. .replaceAll( '%keywords%', info.keywords )
  341. .replaceAll( '%time%', info.time )
  342. .replaceAll( '%viewCount%', info.viewCount )
  343. .replaceAll( '%favCount%', info.favCount )
  344. .replaceAll( '%movie%', url )
  345. .replaceAll( '%like%', info.like )
  346. .replaceAll( '%dislike%', info.dislike )
  347. .replaceAll( '%likeWidth%', info.likeWidth );
  348.  
  349. // ポップアップの設定
  350. v2c.context.setPopupHTML( html );
  351. v2c.context.setMaxPopupWidth( maxPopupWidth );
  352. v2c.context.setCloseOnMouseExit( closeOnMouseExit );
  353. v2c.context.setTrapFormSubmission( true );
  354. v2c.context.setRedirectURL( true );
  355. v2c.context.setPopupID( info.vid );
  356. v2c.context.setPopupFocusable( popupFocusable );
  357. }
  358.  
  359. // 全てのXMLノードを走査
  360. function traceNodes( node ) {
  361. var child = node.getFirstChild();
  362.  
  363. // 子ノードが無くなるまで繰り返し
  364. while ( child != null ) {
  365.  
  366. // ノードが持つ属性(NamedNodeMap)
  367. var attrs = child.getAttributes();
  368.  
  369. // 動画タイトルの取得
  370. if ( child.getNodeName() == 'title' ) {
  371. // テキストノード
  372. info.title = child.getFirstChild().getNodeValue();
  373. }
  374.  
  375. // サムネイルURLの取得
  376. if ( child.getNodeName() == 'media:thumbnail' ) {
  377. var tmp = attrs.getNamedItem( 'url' ).getNodeValue();
  378. if ( tmp.match( /http:\/\/.+?0\.jpg/i ) ) {
  379. info.thumb = tmp;
  380. }
  381. }
  382.  
  383. // 投稿日時の取得 <published>
  384. if ( child.getNodeName() == 'published' ) {
  385. info.date = child.getFirstChild().getNodeValue();
  386. }
  387.  
  388. // 投稿者コメントの取得
  389. if ( child.getNodeName() == 'content' ) {
  390. //存在しない場合もある為、存在チェック
  391. if( child.getFirstChild() ) {
  392. info.comment = child.getFirstChild().getNodeValue();
  393. }
  394. }
  395.  
  396. // 投稿者名の取得
  397. if ( child.getNodeName() == 'name' ) {
  398. info.name = child.getFirstChild().getNodeValue();
  399. info.uri = 'http://w...content-available-to-author-only...e.com/user/' + info.name;
  400. }
  401.  
  402. // 投稿者URLの取得
  403.  
  404. // キーワード(タグ)の取得
  405. if ( child.getNodeName() == 'media:keywords' ) {
  406. // 存在しない場合もある為、存在チェック
  407. if( child.getFirstChild() ) {
  408. info.keywords = child.getFirstChild().getNodeValue();
  409. }
  410. }
  411.  
  412. // 再生時間の取得
  413. if ( child.getNodeName() == 'yt:duration' ) {
  414. // タグの属性として格納されている
  415. if( attrs ) {
  416. // 再生時間(秒)の取得
  417. if( attrs.getNamedItem( 'seconds' ) ) {
  418. info.time = attrs.getNamedItem( 'seconds' ).getNodeValue();
  419. }
  420. }
  421. }
  422.  
  423. // 再生回数、お気に入り数の取得
  424. if ( child.getNodeName() == 'yt:statistics' ) {
  425. if(attrs){
  426. // 再生回数の取得
  427. if( attrs.getNamedItem( 'viewCount' ) ) {
  428. info.viewCount = attrs.getNamedItem('viewCount').getNodeValue();
  429. }
  430. // お気に入り数の取得
  431. if( attrs.getNamedItem( 'favoriteCount' ) ) {
  432. info.favCount = attrs.getNamedItem('favoriteCount').getNodeValue();
  433. }
  434. }
  435. }
  436.  
  437. // 評価の取得
  438. if ( child.getNodeName() == 'gd:rating' ) {
  439. if(attrs){
  440. var average = attrs.getNamedItem('average').getNodeValue();
  441. var numRaters = attrs.getNamedItem('numRaters').getNodeValue();
  442. // ratingは、高評価=5・低評価=1の2種のみとして算出
  443. if ( average && numRaters ) {
  444. info.like = Math.round( numRaters * ( average - 1 ) / 4 );
  445. info.dislike = numRaters - info.like ;
  446. info.likeWidth = Math.round( ratingBarWidth * ( info.like / numRaters ) );
  447. }
  448. }
  449. }
  450.  
  451. // 再生できない動画のステータス
  452. if ( child.getNodeName() == 'yt:state' ) {
  453. if(attrs){
  454. var name = attrs.getNamedItem('name').getNodeValue();
  455. if ( name == 'processing') {
  456. info.state = 'この動画は現在閲覧できません。';
  457. } else {
  458. var reasonCode = attrs.getNamedItem('reasonCode').getNodeValue();
  459. if ( reasonCode ) {
  460. if ( reasonCode == 'requesterRegion' ) info.state = 'この動画はユーザーの地域では利用できません。';
  461. // これ以下は通常403が返る?
  462. else if ( reasonCode == 'private' ) info.state = 'この動画は非公開動画です。';
  463. else if ( reasonCode == 'copyright' ) info.state = '動画が著作権を侵害しています。';
  464. else if ( reasonCode == 'inappropriate' ) info.state = '動画に不適切なコンテンツが含まれています。';
  465. else if ( reasonCode == 'termsOfUse' ) info.state = '動画が利用規約に違反しています。';
  466. else if ( reasonCode == 'suspended' ) info.state = '動画に関連付けられたアカウントは停止されています。';
  467. else if ( reasonCode == 'blocked' ) info.state = '動画がコンテンツの所有者によりブロックされています';
  468. else info.state = '';
  469. }
  470. }
  471. }
  472. }
  473.  
  474.  
  475. // 再帰
  476. traceNodes( child );
  477. child = child.getNextSibling();
  478. }
  479. return;
  480. }
  481.  
  482. // 桁揃え関数
  483. function zeroPlus( str ) {
  484. return ( '0' + str ).slice( -2 );
  485. }
  486.  
  487. // フォーマット関数
  488. function formatNum( num, type ) {
  489. var str = java.lang.String.valueOf(num);
  490. var tmp = new Array();
  491. var mod,i;
  492. // 3桁カンマ区切り
  493. if ( type == 1 ) {
  494. mod = str.length() % 3;
  495. if ( mod ) {
  496. tmp.push( str.substring( 0, mod ) );
  497. }
  498. for ( i = 0; i < parseInt( str.length() / 3 ); i++) {
  499. tmp.push( str.substring( mod, mod + 3 ) );
  500. mod += 3;
  501. }
  502. return tmp.join(',');
  503. }
  504. // 日本語表記、億まで対応
  505. if ( type == 2 ) {
  506. mod = str.length() % 4;
  507. // 億以上
  508. if ( 2 <= parseInt( str.length() / 4 ) ){
  509. if ( mod ) {
  510. tmp.push( str.substring( 0, mod ) + '億' );
  511. }
  512. if ( str.substring( mod, mod + 4 ).match( /0{0,3}([1-9](\d+)?)/ ) ) {
  513. tmp.push( RegExp.$1 + '万' );
  514. }
  515. if ( str.substring( mod + 4, mod + 8 ).match( /0{0,3}([1-9](\d+)?)/ ) ) {
  516. tmp.push( RegExp.$1 );
  517. }
  518. }
  519. // 億未満、万以上
  520. else if ( 1 <= parseInt( str.length() / 4 ) ) {
  521. if ( mod ) {
  522. tmp.push( str.substring( 0, mod ) + '万' );
  523. }
  524. if ( str.substring( mod, mod + 4 ).match( /0{0,3}([1-9](\d+)?)/ ) ) {
  525. tmp.push( RegExp.$1 );
  526. }
  527. }
  528. // 万未満
  529. else {
  530. tmp.push( str );
  531. }
  532. return tmp.join('');
  533. }
  534. // そのまま
  535. else {
  536. return str;
  537. }
  538. }
  539.  
  540. function onErrorPopup( errStr, vid ) {
  541. if ( !vid ) vid = 'None';
  542. v2c.context.setPopupText( errStr );
  543. v2c.context.setMaxPopupWidth( maxPopupWidth );
  544. v2c.context.setCloseOnMouseExit( true );
  545. v2c.context.setTrapFormSubmission( false );
  546. v2c.context.setRedirectURL( false );
  547. v2c.context.setPopupID( 'PSY_' + vid );
  548. }
  549.  
  550. function openURLExec( url ) {
  551. var url = new java.lang.String( url );
  552. var fs = java.io.File.separator;
  553. var tmp = v2c.readFile( v2c.saveDir + fs + 'URLExec.dat', 'Shift-JIS' );
  554. if ( !tmp ) {
  555. v2c.println( 'URLExec.datが見つかりませんでした' );
  556. return false;
  557. }
  558. var lines = tmp.split( '\n' );
  559. var ptn = java.util.regex.Pattern.compile("^(?<!;|'|//)([^\t]+\t){2}[^\t]+$");
  560. for( var i=0,len=lines.length; i<len; i++ ) {
  561. var matcher = ptn.matcher(lines[i]);
  562. if ( matcher.matches() ) {
  563. //v2c.println( '有効行:' + matcher.group(0) );
  564. } else {
  565. //v2c.println( '!無効行:' + lines[i] );
  566. continue;
  567. }
  568.  
  569. var matchFlg = false;
  570. var item = lines[i].split( '\t' );
  571. if ( item.length != 3 ) { // 念のため
  572. v2c.println( 'Tabの数が不正:' + (item.length-1) );
  573. continue;
  574. }
  575. item[1] = (new java.lang.String(item[1])).replaceAll( '\\$&', '\\$0' );
  576.  
  577. try {
  578. var ptn2 = java.util.regex.Pattern.compile(item[0]);
  579. } catch( e ) { // 不正な正規表現を無視
  580. v2c.println( e );
  581. continue;
  582. }
  583. if ( ptn2.matcher(url).find() ) {
  584. matchFlg = true;
  585. url = url.replaceFirst( item[0], item[1] );
  586. break;
  587. }
  588. }
  589. if ( !matchFlg ) {
  590. v2c.println( 'URLExec.dat:マッチなし\n' + url );
  591. return false;
  592. }
  593.  
  594. var cmds = item[2].split( ' ' );
  595. if ( cmds.length == 0 ) {
  596. v2c.println( 'URLExec.dat:コマンドがありません' );
  597. return false;
  598. }
  599. for ( i=0; i<cmds.length; i++ ) {
  600. var matcher = java.util.regex.Pattern.compile('\\$VIEW').matcher(cmds[i]);
  601. if ( matcher.find() ) {
  602. if ( i==0 ){
  603. v2c.println( 'URLExec.dat:無効なキーワード"$VEIW"' );
  604. return false;
  605. }
  606. }
  607.  
  608. // $BROWSER
  609. if ( browserPath ) {
  610. cmds[i] = cmds[i].replaceAll( '\\$BROWSER', browserPath );
  611. } else {
  612. // ブラウザを指定していない場合で、更にURLExec.datのコマンドが、
  613. // ブラウザにURLを渡すだけの場合はデフォルト外部ブラウザで開く(応急処置)
  614. if( item[2].matches( '"?\\$BROWSER"? "?\\$(URL|LINK)"?' ) ) { //完全一致
  615. v2c.browseURLDefExt(url);
  616. v2c.println( 'cmd='+item[2] );
  617. return true;
  618. }
  619. }
  620.  
  621. // $LINK 置換しない場合は、この下の行をコメントアウト
  622. cmds[i] = cmds[i].replaceAll( '\\$LINK', url );
  623.  
  624. // $URL 置換しない場合は、この下行をコメントアウト
  625. cmds[i] = cmds[i].replaceAll( '\\$URL', url );
  626.  
  627. // $BASEPATH
  628. if ( i==0 ) { // コマンドの場合
  629. cmds[i] = cmds[i].replaceAll( '\\$BASEPATH', v2c.saveDir.toString()
  630. .replaceAll( '\\\\', '/' ) + '/' );
  631. } else { // 引数の場合
  632. cmds[i] = cmds[i].replaceAll( '\\$BASEPATH', v2c.saveDir.toString()
  633. .replaceAll( '\\\\', '\\\\\\\\' ) + '\\\\' );
  634. }
  635.  
  636. // $POSX $POSY
  637. var p = v2c.context.mousePos;
  638. if ( p ) {
  639. cmds[i] = cmds[i].replaceAll( '\\$POSX', p.x );
  640. cmds[i] = cmds[i].replaceAll( '\\$POSY', p.y );
  641. }
  642. v2c.println( 'cmd['+i+']='+cmds[i] );
  643. }
  644. v2c.exec(cmds);
  645. return true;
  646. }
Runtime error #stdin #stdout #stderr 0.57s 383232KB
stdin
Standard input is empty
stdout
Standard output is empty
stderr
js: uncaught JavaScript runtime exception: ReferenceError: "v2c" is not defined.