Advertisement
Guest User

PopupStatusYoutube_withoutAPI.js

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