├── .gitignore ├── screenshot.png ├── dist ├── css │ └── main.css └── js │ └── main.js ├── src ├── js │ ├── main.js │ ├── search.js │ └── analysis.js └── scss │ └── main.scss ├── README.md ├── package.json ├── gulpfile.js ├── LICENSE └── index.html /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imfangli/baidu-music-downloader/HEAD/screenshot.png -------------------------------------------------------------------------------- /dist/css/main.css: -------------------------------------------------------------------------------- 1 | .search-form { 2 | margin-bottom: 20px; } 3 | 4 | .list-group-item:hover { 5 | cursor: pointer; 6 | background: #F5F5F5; } 7 | -------------------------------------------------------------------------------- /src/js/main.js: -------------------------------------------------------------------------------- 1 | /* 2 | * 百度无损音乐下载器入口文件 3 | * By Felix - imfangli@126.com 4 | */ 5 | 6 | require("./search.js")(); // 搜索音乐相关 7 | require("./analysis.js")(); // 分析音乐详情相关 -------------------------------------------------------------------------------- /src/scss/main.scss: -------------------------------------------------------------------------------- 1 | .search-form { 2 | margin-bottom: 20px; 3 | } 4 | 5 | .list-group-item { 6 | &:hover { 7 | cursor: pointer; 8 | background: #F5F5F5; 9 | } 10 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 百度无损音乐下载器 2 | 3 | ## Demo 4 | 5 | [在线演示](http://imfangli.github.io/baidu-music-downloader/) 6 | 7 | ## 介绍 8 | 9 | 看了[armsword](http://armsword.com/2014/08/09/download-baidu-music/)的博文受到了一些启发,然后又自己研究了一下百度的接口,做了这个小工具。 10 | 11 | ![screenshot](screenshot.png "百度无损音乐下载器") 12 | 13 | ## TODO 14 | 15 | ~~本程序在本地直接用浏览器打开 index.html 运行良好,但是放到服务器上下载有问题,初步判断是百度监测 Referer 而做了权限的限制,空了找下解决方法。~~ 16 | [参考](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/meta) -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "baidu-music-downloader", 3 | "version": "1.0.0", 4 | "description": "百度无损音乐下载器", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "Felix", 10 | "license": "MIT", 11 | "devDependencies": { 12 | "gulp": "^3.9.0", 13 | "gulp-browserify": "^0.5.1", 14 | "gulp-rename": "^1.2.2", 15 | "gulp-sass": "^2.1.0", 16 | "gulp-uglify": "^1.5.1" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | var gulp = require("gulp"); 2 | var sass = require("gulp-sass"); 3 | var browserify = require('gulp-browserify'); 4 | 5 | // Compile SCSS into CSS 6 | gulp.task("sass", function() { 7 | gulp.src("./src/scss/**/*.scss") 8 | .pipe(sass().on("error", sass.logError)) 9 | .pipe(gulp.dest("./dist/css")); 10 | }); 11 | 12 | // Watch SCSS files & Compile 13 | gulp.task("sass:watch", function () { 14 | gulp.watch("./src/scss/*.scss", ["sass"]); 15 | }); 16 | 17 | // Browserify JS 18 | gulp.task('js', function() { 19 | // Single entry point to browserify 20 | gulp.src('src/js/main.js') 21 | .pipe(browserify({ 22 | insertGlobals : false, 23 | debug : true 24 | })) 25 | .pipe(gulp.dest('./dist/js')) 26 | }); 27 | 28 | // Watch JS files & Browserify 29 | gulp.task("js:watch", function () { 30 | gulp.watch("src/js/*.js", ["js"]); 31 | }); 32 | 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Felix Fang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /src/js/search.js: -------------------------------------------------------------------------------- 1 | /* 2 | * 音乐搜索相关逻辑 3 | */ 4 | 5 | module.exports = function () { 6 | 7 | var $searchInput = $("#search-input"); 8 | 9 | // 搜索框添加 keyup 时间,实时刷新搜索数据 10 | $searchInput.on("keyup", function () { 11 | var $this = $(this), 12 | keyword = $this.val(); 13 | $.ajax({ 14 | type: "get", 15 | url: "http://sug.music.baidu.com/info/suggestion", 16 | dataType: "jsonp", 17 | data: { 18 | word: keyword, 19 | version: 2, 20 | from: 0 21 | }, 22 | success: function(data) { 23 | var arrSong = data.data.song || []; 24 | var $musicList = $("#search-items"); 25 | 26 | $musicList.empty(); 27 | 28 | // 搜索到结果后,输出 名称-艺术家 29 | if (arrSong.length) { 30 | for (var i = 0; i < arrSong.length; i++) { 31 | var $musicItem = $('
  • ' + arrSong[i].songname + ' - ' + arrSong[i].artistname + '
  • '); 32 | $musicItem.attr("data-songid", arrSong[i].songid); // 为搜索列表项添加音乐 ID 33 | $musicList.append($musicItem); 34 | } 35 | } else { // 没有搜索到结果 36 | var $musicItem = $('
  • 暂无结果
  • '); 37 | $musicList.append($musicItem); 38 | } 39 | } 40 | }); 41 | }); 42 | }; 43 | -------------------------------------------------------------------------------- /src/js/analysis.js: -------------------------------------------------------------------------------- 1 | /* 2 | * 音乐详细信息相关逻辑 3 | */ 4 | 5 | module.exports = function () { 6 | 7 | // 搜索项添加点击事件 8 | $("#search-items").on("click", "li", function () { 9 | var songid = $(this).data("songid"); 10 | analysis(songid); 11 | }); 12 | 13 | var analysis = function(songid){ 14 | $.ajax({ 15 | type: "get", 16 | url: "http://music.baidu.com/data/music/fmlink", 17 | dataType: "jsonp", 18 | data: { 19 | songIds: songid, 20 | type: "flac" 21 | }, 22 | success: function(data) { 23 | 24 | var songData = data.data.songList[0] || {}; 25 | 26 | var $musicDetail = $("#music-detail"); 27 | 28 | $musicDetail.empty(); 29 | 30 | // 构造音乐详情 HTML 结构 31 | var $itemDetail = $('
    ' + 32 | '
    ' + 33 | '' + 34 | '' + 35 | '' + 36 | '
    ' + 37 | '
    ' + 38 | '

    ' + songData.songName + ' - ' + songData.artistName + '

    ' + 39 | '

    文件格式: ' + songData.format + '

    ' + 40 | '

    下载

    ' + 41 | '
    ' + 42 | '
    '); 43 | 44 | // 如果没有链接则在下载按钮上添加 disabled 类 45 | if (!songData.songLink) { 46 | $itemDetail.find(".btn").addClass("disabled"); 47 | } 48 | 49 | $musicDetail.append($itemDetail); 50 | 51 | // 显示 JSON 信息 52 | $musicDetail.append($('
    ' + JSON.stringify(songData) + '
    ')); 53 | } 54 | }); 55 | }; 56 | 57 | }; 58 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 百度无损音乐下载器 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
    14 | 17 |
    18 |
    19 |
    20 |

    本工具优先查找 flac 无损格式音乐,如果没有无损音乐信息则显示 mp3 格式,还有可能啥都木有 -_-

    21 |
    22 |
    23 |
    24 |
    25 | 26 |
    27 |
    28 | 输入关键字搜索 29 | 30 |
    31 |
    32 | 33 |
    34 |
    35 |
    36 |

    搜索结果

    37 |
    38 |
      39 |
    • 暂无结果
    • 40 |
    41 |
    42 | 43 |
    44 | 45 |
    46 |
    47 |
    48 |

    音乐详情

    49 |
    50 |
    51 |

    暂无信息

    52 |
    53 |
    54 |
    55 |
    56 |
    57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /dist/js/main.js: -------------------------------------------------------------------------------- 1 | (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o' + 33 | '
    ' + 34 | '' + 35 | '' + 36 | '' + 37 | '
    ' + 38 | '
    ' + 39 | '

    ' + songData.songName + ' - ' + songData.artistName + '

    ' + 40 | '

    文件格式: ' + songData.format + '

    ' + 41 | '

    下载

    ' + 42 | '
    ' + 43 | ''); 44 | 45 | // 如果没有链接则在下载按钮上添加 disabled 类 46 | if (!songData.songLink) { 47 | $itemDetail.find(".btn").addClass("disabled"); 48 | } 49 | 50 | $musicDetail.append($itemDetail); 51 | 52 | // 显示 JSON 信息 53 | $musicDetail.append($('
    ' + JSON.stringify(songData) + '
    ')); 54 | } 55 | }); 56 | }; 57 | 58 | }; 59 | 60 | },{}],2:[function(require,module,exports){ 61 | /* 62 | * 百度无损音乐下载器入口文件 63 | * By Felix - imfangli@126.com 64 | */ 65 | 66 | require("./search.js")(); // 搜索音乐相关 67 | require("./analysis.js")(); // 分析音乐详情相关 68 | },{"./analysis.js":1,"./search.js":3}],3:[function(require,module,exports){ 69 | /* 70 | * 音乐搜索相关逻辑 71 | */ 72 | 73 | module.exports = function () { 74 | 75 | var $searchInput = $("#search-input"); 76 | 77 | // 搜索框添加 keyup 时间,实时刷新搜索数据 78 | $searchInput.on("keyup", function () { 79 | var $this = $(this), 80 | keyword = $this.val(); 81 | $.ajax({ 82 | type: "get", 83 | url: "http://sug.music.baidu.com/info/suggestion", 84 | dataType: "jsonp", 85 | data: { 86 | word: keyword, 87 | version: 2, 88 | from: 0 89 | }, 90 | success: function(data) { 91 | var arrSong = data.data.song || []; 92 | var $musicList = $("#search-items"); 93 | 94 | $musicList.empty(); 95 | 96 | // 搜索到结果后,输出 名称-艺术家 97 | if (arrSong.length) { 98 | for (var i = 0; i < arrSong.length; i++) { 99 | var $musicItem = $('
  • ' + arrSong[i].songname + ' - ' + arrSong[i].artistname + '
  • '); 100 | $musicItem.attr("data-songid", arrSong[i].songid); // 为搜索列表项添加音乐 ID 101 | $musicList.append($musicItem); 102 | } 103 | } else { // 没有搜索到结果 104 | var $musicItem = $('
  • 暂无结果
  • '); 105 | $musicList.append($musicItem); 106 | } 107 | } 108 | }); 109 | }); 110 | }; 111 | 112 | },{}]},{},[2]) 113 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9Vc2Vycy9GZWxpeC9Qcm9qZWN0L2Zyb250RW5kL2JhaWR1LW11c2ljLWRvd25sb2FkZXIvbm9kZV9tb2R1bGVzL2d1bHAtYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvYnJvd3Nlci1wYWNrL19wcmVsdWRlLmpzIiwiL1VzZXJzL0ZlbGl4L1Byb2plY3QvZnJvbnRFbmQvYmFpZHUtbXVzaWMtZG93bmxvYWRlci9zcmMvanMvYW5hbHlzaXMuanMiLCIvVXNlcnMvRmVsaXgvUHJvamVjdC9mcm9udEVuZC9iYWlkdS1tdXNpYy1kb3dubG9hZGVyL3NyYy9qcy9mYWtlXzhjZGM3MGM2LmpzIiwiL1VzZXJzL0ZlbGl4L1Byb2plY3QvZnJvbnRFbmQvYmFpZHUtbXVzaWMtZG93bmxvYWRlci9zcmMvanMvc2VhcmNoLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ05BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24gZSh0LG4scil7ZnVuY3Rpb24gcyhvLHUpe2lmKCFuW29dKXtpZighdFtvXSl7dmFyIGE9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtpZighdSYmYSlyZXR1cm4gYShvLCEwKTtpZihpKXJldHVybiBpKG8sITApO3Rocm93IG5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIrbytcIidcIil9dmFyIGY9bltvXT17ZXhwb3J0czp7fX07dFtvXVswXS5jYWxsKGYuZXhwb3J0cyxmdW5jdGlvbihlKXt2YXIgbj10W29dWzFdW2VdO3JldHVybiBzKG4/bjplKX0sZixmLmV4cG9ydHMsZSx0LG4scil9cmV0dXJuIG5bb10uZXhwb3J0c312YXIgaT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2Zvcih2YXIgbz0wO288ci5sZW5ndGg7bysrKXMocltvXSk7cmV0dXJuIHN9KSIsIi8qXG4gKiAg6Z+z5LmQ6K+m57uG5L+h5oGv55u45YWz6YC76L6RXG4gKi9cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoKSB7XG5cbiAgICAvLyDmkJzntKLpobnmt7vliqDngrnlh7vkuovku7ZcbiAgICAkKFwiI3NlYXJjaC1pdGVtc1wiKS5vbihcImNsaWNrXCIsIFwibGlcIiwgZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgc29uZ2lkID0gJCh0aGlzKS5kYXRhKFwic29uZ2lkXCIpO1xuICAgICAgICBhbmFseXNpcyhzb25naWQpO1xuICAgIH0pO1xuXG4gICAgdmFyIGFuYWx5c2lzID0gZnVuY3Rpb24oc29uZ2lkKXtcbiAgICAgICAgJC5hamF4KHtcbiAgICAgICAgICAgIHR5cGU6IFwiZ2V0XCIsXG4gICAgICAgICAgICB1cmw6IFwiaHR0cDovL211c2ljLmJhaWR1LmNvbS9kYXRhL211c2ljL2ZtbGlua1wiLFxuICAgICAgICAgICAgZGF0YVR5cGU6IFwianNvbnBcIixcbiAgICAgICAgICAgIGRhdGE6IHtcbiAgICAgICAgICAgICAgICBzb25nSWRzOiBzb25naWQsXG4gICAgICAgICAgICAgICAgdHlwZTogXCJmbGFjXCJcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzdWNjZXNzOiBmdW5jdGlvbihkYXRhKSB7XG5cbiAgICAgICAgICAgICAgICB2YXIgc29uZ0RhdGEgPSBkYXRhLmRhdGEuc29uZ0xpc3RbMF0gfHwge307XG5cbiAgICAgICAgICAgICAgICB2YXIgJG11c2ljRGV0YWlsID0gJChcIiNtdXNpYy1kZXRhaWxcIik7XG5cbiAgICAgICAgICAgICAgICAkbXVzaWNEZXRhaWwuZW1wdHkoKTtcblxuICAgICAgICAgICAgICAgIC8vIOaehOmAoOmfs+S5kOivpuaDhSBIVE1MIOe7k+aehFxuICAgICAgICAgICAgICAgIHZhciAkaXRlbURldGFpbCA9ICQoJzxkaXYgY2xhc3M9XCJtZWRpYVwiPicgK1xuICAgICAgICAgICAgICAgICAgICAnPGRpdiBjbGFzcz1cIm1lZGlhLWxlZnRcIj4nICtcbiAgICAgICAgICAgICAgICAgICAgJzxhIGhyZWY9XCIjXCI+JyArXG4gICAgICAgICAgICAgICAgICAgICc8aW1nIGNsYXNzPVwibWVkaWEtb2JqZWN0XCIgc3JjPVwiJyArIHNvbmdEYXRhLnNvbmdQaWNTbWFsbCArICdcIj4nICtcbiAgICAgICAgICAgICAgICAgICAgJzwvYT4nICtcbiAgICAgICAgICAgICAgICAgICAgJzwvZGl2PicgK1xuICAgICAgICAgICAgICAgICAgICAnPGRpdiBjbGFzcz1cIm1lZGlhLWJvZHlcIj4nICtcbiAgICAgICAgICAgICAgICAgICAgJzxoNCBjbGFzcz1cIm1lZGlhLWhlYWRpbmdcIj4nICsgc29uZ0RhdGEuc29uZ05hbWUgKyAnIC0gJyArIHNvbmdEYXRhLmFydGlzdE5hbWUgKyAnPC9oND4nICtcbiAgICAgICAgICAgICAgICAgICAgJzxwPuaWh+S7tuagvOW8j++8miAnICsgc29uZ0RhdGEuZm9ybWF0ICsgJzwvcD4nICtcbiAgICAgICAgICAgICAgICAgICAgJzxwPjxhIGNsYXNzPVwiYnRuIGJ0bi1zdWNjZXNzXCIgaHJlZj1cIicgKyBzb25nRGF0YS5zb25nTGluayArICdcIj48aSBjbGFzcz1cImdseXBoaWNvbiBnbHlwaGljb24tY2xvdWQtZG93bmxvYWRcIj48L2k+IOS4i+i9vTwvYT48L3A+JyArXG4gICAgICAgICAgICAgICAgICAgICc8L2Rpdj4nICtcbiAgICAgICAgICAgICAgICAgICAgJzwvZGl2PicpO1xuXG4gICAgICAgICAgICAgICAgLy8g5aaC5p6c5rKh5pyJ6ZO+5o6l5YiZ5Zyo5LiL6L295oyJ6ZKu5LiK5re75YqgIGRpc2FibGVkIOexu1xuICAgICAgICAgICAgICAgIGlmICghc29uZ0RhdGEuc29uZ0xpbmspIHtcbiAgICAgICAgICAgICAgICAgICAgJGl0ZW1EZXRhaWwuZmluZChcIi5idG5cIikuYWRkQ2xhc3MoXCJkaXNhYmxlZFwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAkbXVzaWNEZXRhaWwuYXBwZW5kKCRpdGVtRGV0YWlsKTtcblxuICAgICAgICAgICAgICAgIC8vIOaYvuekuiBKU09OIOS/oeaBr1xuICAgICAgICAgICAgICAgICRtdXNpY0RldGFpbC5hcHBlbmQoJCgnPHByZT4nICsgSlNPTi5zdHJpbmdpZnkoc29uZ0RhdGEpICsgJzwvcHJlPicpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfTtcblxufTtcbiIsIi8qXG4gKiAg55m+5bqm5peg5o2f6Z+z5LmQ5LiL6L295Zmo5YWl5Y+j5paH5Lu2XG4gKiAgQnkgRmVsaXggLSBpbWZhbmdsaUAxMjYuY29tXG4gKi9cblxucmVxdWlyZShcIi4vc2VhcmNoLmpzXCIpKCk7ICAvLyDmkJzntKLpn7PkuZDnm7jlhbNcbnJlcXVpcmUoXCIuL2FuYWx5c2lzLmpzXCIpKCk7ICAvLyDliIbmnpDpn7PkuZDor6bmg4Xnm7jlhbMiLCIvKlxuICogIOmfs+S5kOaQnOe0ouebuOWFs+mAu+i+kVxuICovXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKCkge1xuXG4gICAgdmFyICRzZWFyY2hJbnB1dCA9ICQoXCIjc2VhcmNoLWlucHV0XCIpO1xuXG4gICAgLy8g5pCc57Si5qGG5re75YqgIGtleXVwIOaXtumXtO+8jOWunuaXtuWIt+aWsOaQnOe0ouaVsOaNrlxuICAgICRzZWFyY2hJbnB1dC5vbihcImtleXVwXCIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyICR0aGlzID0gJCh0aGlzKSxcbiAgICAgICAgICAgIGtleXdvcmQgPSAkdGhpcy52YWwoKTtcbiAgICAgICAgJC5hamF4KHtcbiAgICAgICAgICAgIHR5cGU6IFwiZ2V0XCIsXG4gICAgICAgICAgICB1cmw6IFwiaHR0cDovL3N1Zy5tdXNpYy5iYWlkdS5jb20vaW5mby9zdWdnZXN0aW9uXCIsXG4gICAgICAgICAgICBkYXRhVHlwZTogXCJqc29ucFwiLFxuICAgICAgICAgICAgZGF0YToge1xuICAgICAgICAgICAgICAgIHdvcmQ6IGtleXdvcmQsXG4gICAgICAgICAgICAgICAgdmVyc2lvbjogMixcbiAgICAgICAgICAgICAgICBmcm9tOiAwXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc3VjY2VzczogZnVuY3Rpb24oZGF0YSkge1xuICAgICAgICAgICAgICAgIHZhciBhcnJTb25nID0gZGF0YS5kYXRhLnNvbmcgfHwgW107XG4gICAgICAgICAgICAgICAgdmFyICRtdXNpY0xpc3QgPSAkKFwiI3NlYXJjaC1pdGVtc1wiKTtcblxuICAgICAgICAgICAgICAgICRtdXNpY0xpc3QuZW1wdHkoKTtcblxuICAgICAgICAgICAgICAgIC8vIOaQnOe0ouWIsOe7k+aenOWQju+8jOi+k+WHuiDlkI3np7DvvI3oibrmnK/lrrZcbiAgICAgICAgICAgICAgICBpZiAoYXJyU29uZy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhcnJTb25nLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgJG11c2ljSXRlbSA9ICQoJzxsaSBjbGFzcz1cImxpc3QtZ3JvdXAtaXRlbVwiPicgKyBhcnJTb25nW2ldLnNvbmduYW1lICsgJyAtICcgKyBhcnJTb25nW2ldLmFydGlzdG5hbWUgKyAnPC9saT4nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICRtdXNpY0l0ZW0uYXR0cihcImRhdGEtc29uZ2lkXCIsIGFyclNvbmdbaV0uc29uZ2lkKTsgIC8vIOS4uuaQnOe0ouWIl+ihqOmhuea3u+WKoOmfs+S5kCBJRFxuICAgICAgICAgICAgICAgICAgICAgICAgJG11c2ljTGlzdC5hcHBlbmQoJG11c2ljSXRlbSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgeyAgLy8g5rKh5pyJ5pCc57Si5Yiw57uT5p6cXG4gICAgICAgICAgICAgICAgICAgIHZhciAkbXVzaWNJdGVtID0gJCgnPGxpIGNsYXNzPVwibGlzdC1ncm91cC1pdGVtXCI+5pqC5peg57uT5p6cPC9saT4nKTtcbiAgICAgICAgICAgICAgICAgICAgJG11c2ljTGlzdC5hcHBlbmQoJG11c2ljSXRlbSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9KTtcbn07XG4iXX0= 114 | --------------------------------------------------------------------------------