Advertisement
Guest User

PopupStatusYoutube.js

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