├── .gitignore ├── LICENSE ├── README.md ├── build ├── icon.icns └── icon.ico ├── dark.css ├── img ├── backdrop.png ├── changelog_banner.png ├── logo.png ├── oldlogo.png ├── qm.png ├── ring.png ├── ring_active.png ├── ring_spinner.png ├── runesReforged │ ├── perk │ │ ├── 5001.png │ │ ├── 5002.png │ │ ├── 5003.png │ │ ├── 5005.png │ │ ├── 5007.png │ │ ├── 5008.png │ │ ├── 8005.png │ │ ├── 8008.png │ │ ├── 8009.png │ │ ├── 8010.png │ │ ├── 8014.png │ │ ├── 8017.png │ │ ├── 8021.png │ │ ├── 8105.png │ │ ├── 8106.png │ │ ├── 8112.png │ │ ├── 8120.png │ │ ├── 8124.png │ │ ├── 8126.png │ │ ├── 8128.png │ │ ├── 8134.png │ │ ├── 8135.png │ │ ├── 8136.png │ │ ├── 8138.png │ │ ├── 8139.png │ │ ├── 8143.png │ │ ├── 8210.png │ │ ├── 8214.png │ │ ├── 8224.png │ │ ├── 8226.png │ │ ├── 8229.png │ │ ├── 8230.png │ │ ├── 8232.png │ │ ├── 8233.png │ │ ├── 8234.png │ │ ├── 8236.png │ │ ├── 8237.png │ │ ├── 8242.png │ │ ├── 8243.png │ │ ├── 8275.png │ │ ├── 8299.png │ │ ├── 8304.png │ │ ├── 8306.png │ │ ├── 8313.png │ │ ├── 8316.png │ │ ├── 8321.png │ │ ├── 8339.png │ │ ├── 8345.png │ │ ├── 8347.png │ │ ├── 8351.png │ │ ├── 8352.png │ │ ├── 8359.png │ │ ├── 8360.png │ │ ├── 8401.png │ │ ├── 8410.png │ │ ├── 8429.png │ │ ├── 8430.png │ │ ├── 8435.png │ │ ├── 8437.png │ │ ├── 8439.png │ │ ├── 8444.png │ │ ├── 8446.png │ │ ├── 8451.png │ │ ├── 8453.png │ │ ├── 8463.png │ │ ├── 8465.png │ │ ├── 8472.png │ │ ├── 8473.png │ │ ├── 9101.png │ │ ├── 9103.png │ │ ├── 9104.png │ │ ├── 9105.png │ │ ├── 9111.png │ │ ├── 9923.png │ │ └── qm.png │ └── perkStyle │ │ ├── 8000.png │ │ ├── 8100.png │ │ ├── 8200.png │ │ ├── 8300.png │ │ └── 8400.png └── unknown.png ├── index.html ├── light.css ├── oldsplash.html ├── package.json ├── plugins ├── championgg.js ├── index.js ├── koreanbuilds.js ├── local.js ├── opgg.js ├── runeforge.js ├── runeslol.js ├── ugg.js └── utils.js ├── splashscreen.html ├── src ├── app.js ├── lcu-api.js ├── locales.js ├── locales │ ├── cz.json │ ├── de.json │ ├── en.json │ ├── es.json │ ├── fr.json │ ├── hu.json │ ├── it.json │ ├── pl.json │ ├── pt.json │ ├── pt_br.json │ ├── ro.json │ ├── rs.json │ ├── ru.json │ ├── se.json │ └── tr.json ├── main.js ├── settings.js └── state.js ├── tags ├── changelog-modal.tag ├── chapters-segment.tag ├── connection-status.tag ├── current-page.tag ├── page-list.tag ├── runebook.tag ├── select-champion.tag ├── settings-panel.tag └── update-button.tag └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | dist/ 3 | colors.txt 4 | yarn-error.log 5 | resources/ 6 | logs/ 7 | electron-builder.json 8 | docs/_site 9 | .vscode/launch.json 10 | package-lock.json 11 | .idea/ 12 | *.iml -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 OrangeNote 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # This repo is now read-only 2 | The original author no longer maintains the app. An updated fork of this repo [can be found here](https://github.com/Soundofdarkness/RuneBook). Credits to [@Soundofdarkness](https://github.com/Soundofdarkness) and [@Rerago](https://github.com/Rerago) among [other contributors](https://github.com/Soundofdarkness/RuneBook/graphs/contributors) for keeping this project alive. 3 | 4 | # Acknowledgements 5 | Thanks to... 6 | - [@Fumi24](https://github.com/Fumi24) for being the source of inspiration for RuneBook, and for letting me know how to programmatically interact with the League API 7 | - [@Pupix](https://github.com/Pupix), because RuneBook wouldn't exist without his tools 8 | - @optizard for being my devoted tester 9 | - all the users who helped me on [@molenzwiebel](https://github.com/molenzwiebel)'s Discord 10 | 11 | # [License](https://github.com/OrangeNote/RuneBook/tree/master/LICENSE) 12 | RuneBook isn’t endorsed by Riot Games and doesn’t reflect the views or opinions of Riot Games or anyone officially involved in producing or managing League of Legends. League of Legends and Riot Games are trademarks or registered trademarks of Riot Games, Inc. League of Legends © Riot Games, Inc. 13 | -------------------------------------------------------------------------------- /build/icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/build/icon.icns -------------------------------------------------------------------------------- /build/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/build/icon.ico -------------------------------------------------------------------------------- /dark.css: -------------------------------------------------------------------------------- 1 | body { 2 | background: #191D24; 3 | } 4 | 5 | .ui.secondary.pointing.menu { 6 | background: #121212; 7 | border-bottom: 1px solid #BD9D5E; 8 | } 9 | 10 | .ui.secondary.pointing.menu .header.item { 11 | color: #BD9D5E !important; 12 | } 13 | 14 | #autochamp-label span { 15 | color: #d8cfbd; 16 | } 17 | 18 | #autochamp-label::before { 19 | background: #121212 !important; 20 | border: 2px solid #BD9D5E; 21 | } 22 | 23 | .ui.toggle.checkbox.checked #autochamp-label::before { 24 | background: #191D24 !important; 25 | border: 2px solid #00ACB1; 26 | } 27 | 28 | #autochamp-label::after { 29 | background: #d8cfbd !important; 30 | } 31 | 32 | div.ui.icon.input input { 33 | background: #121212; 34 | color: #d8cfbd; 35 | } 36 | 37 | input::selection { 38 | background: #00ACB1; 39 | color: #d8cfbd; 40 | } 41 | 42 | .ui.search.fluid.champion .prompt { 43 | border: 2px solid #BD9D5E; 44 | } 45 | 46 | .ui.search.fluid.champion.focus .prompt { 47 | border: 2px solid #00ACB1; 48 | } 49 | 50 | .search.icon { 51 | color: #d8cfbd !important; 52 | } 53 | 54 | .results { 55 | border: 1px solid #BD9D5E !important; 56 | } 57 | 58 | .results .result { 59 | background: #121212; 60 | } 61 | 62 | .results .result.active { 63 | background: #191D24 !important; 64 | } 65 | 66 | .results .result:hover { 67 | background: #191D24 !important; 68 | } 69 | 70 | .ui.search > .results .result .title { 71 | color: #d8cfbd; 72 | } 73 | 74 | .ui.search > .results .result.active .title { 75 | color: #d8cfbd; 76 | } 77 | 78 | runebook .ui.horizontal.divider { 79 | color: #BD9D5E; 80 | } 81 | 82 | .ui.top.attached.pointing.small.borderless.menu { 83 | background: #191D24; 84 | border-color: #BD9D5E; 85 | } 86 | 87 | .ui.top.attached.pointing.small.borderless.menu .item { 88 | color: #BD9D5E; 89 | } 90 | 91 | .ui.top.attached.pointing.small.borderless.menu .item.active { 92 | background: #121212; 93 | box-shadow: inset 1px 0px 0px 0px #BD9D5E, inset -1px 0px 0px 0px #BD9D5E; 94 | color: #d8cfbd; 95 | } 96 | 97 | .ui.top.attached.pointing.small.borderless.menu .item.active::after { 98 | background: #191D24 !important; 99 | border-bottom: 2px solid #BD9D5E !important; 100 | border-right: 2px solid #BD9D5E !important; 101 | } 102 | 103 | .ui.bottom.attached.tab.segment { 104 | background: #191D24; 105 | border-color: #BD9D5E; 106 | } 107 | 108 | chapters-segment .ui.active.inverted.dimmer { 109 | background: #191D24; 110 | } 111 | 112 | page-list ::-webkit-scrollbar-thumb { 113 | background: #71552B; 114 | } 115 | 116 | page-list ::-webkit-scrollbar-thumb:window-inactive { 117 | background: #71552B; 118 | } 119 | 120 | page-list ::-webkit-scrollbar-thumb:hover { 121 | background: #BD9D5E; 122 | } 123 | 124 | .ui.divided.list>.item { 125 | border-top: 1px solid #BD9D5E; 126 | color: #d8cfbd !important; 127 | } 128 | 129 | .row .header .icon { 130 | color: #00ACB1; 131 | } 132 | 133 | .row .header .content { 134 | color: #d8cfbd; 135 | } 136 | 137 | .row .header .content .sub.header { 138 | color: #d8cfbd; 139 | } 140 | 141 | .ui.segment { 142 | background: #191D24; 143 | border: 1px solid #BD9D5E; 144 | } 145 | 146 | .ui.segment .header { 147 | color: #d8cfbd; 148 | } 149 | 150 | .middle.aligned.content .ui.header { 151 | color: #d8cfbd; 152 | } 153 | 154 | .ui.segment .header .sub.header { 155 | color: #d8cfbd; 156 | } 157 | 158 | current-page .ui.button { 159 | background: #71552B; 160 | } 161 | 162 | page-list .ui.button { 163 | background: #71552B; 164 | } 165 | 166 | current-page .ui.button:hover { 167 | background: #BD9D5E; 168 | } 169 | 170 | page-list .ui.button:hover { 171 | background: #BD9D5E; 172 | } 173 | 174 | current-page .ui.button:focus { 175 | background: #71552B; 176 | } 177 | 178 | page-list .ui.button:focus { 179 | background: #71552B; 180 | } 181 | 182 | current-page .ui.button:active { 183 | background: #BD9D5E; 184 | } 185 | 186 | page-list .ui.button:active { 187 | background: #BD9D5E; 188 | } 189 | 190 | .ui.popup { 191 | background: #121212; 192 | color: #d8cfbd; 193 | border: 1px solid #71552B; 194 | } 195 | 196 | .ui.popup::before { 197 | background: #121212 !important; 198 | border-bottom: 1px solid #71552B !important; 199 | border-right: 1px solid #71552B !important; 200 | box-shadow: none !important; 201 | } 202 | 203 | .ui.popup.bottom::before { 204 | background: #121212 !important; 205 | border-left: 1px solid #71552B !important; 206 | border-bottom: none !important; 207 | border-right: none !important; 208 | border-top: 1px solid #71552B !important; 209 | box-shadow: none !important; 210 | } 211 | -------------------------------------------------------------------------------- /img/backdrop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/backdrop.png -------------------------------------------------------------------------------- /img/changelog_banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/changelog_banner.png -------------------------------------------------------------------------------- /img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/logo.png -------------------------------------------------------------------------------- /img/oldlogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/oldlogo.png -------------------------------------------------------------------------------- /img/qm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/qm.png -------------------------------------------------------------------------------- /img/ring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/ring.png -------------------------------------------------------------------------------- /img/ring_active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/ring_active.png -------------------------------------------------------------------------------- /img/ring_spinner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/ring_spinner.png -------------------------------------------------------------------------------- /img/runesReforged/perk/5001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/5001.png -------------------------------------------------------------------------------- /img/runesReforged/perk/5002.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/5002.png -------------------------------------------------------------------------------- /img/runesReforged/perk/5003.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/5003.png -------------------------------------------------------------------------------- /img/runesReforged/perk/5005.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/5005.png -------------------------------------------------------------------------------- /img/runesReforged/perk/5007.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/5007.png -------------------------------------------------------------------------------- /img/runesReforged/perk/5008.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/5008.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8005.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8005.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8008.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8008.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8009.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8009.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8010.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8010.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8014.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8014.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8017.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8017.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8021.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8021.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8105.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8105.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8106.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8106.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8112.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8112.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8120.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8124.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8124.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8126.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8126.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8128.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8134.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8134.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8135.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8135.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8136.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8136.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8138.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8138.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8139.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8139.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8143.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8143.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8210.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8210.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8214.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8214.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8224.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8224.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8226.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8226.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8229.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8229.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8230.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8230.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8232.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8232.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8233.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8233.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8234.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8234.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8236.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8236.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8237.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8237.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8242.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8242.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8243.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8243.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8275.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8275.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8299.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8299.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8304.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8304.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8306.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8306.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8313.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8313.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8316.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8316.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8321.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8321.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8339.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8339.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8345.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8345.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8347.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8347.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8351.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8351.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8352.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8352.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8359.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8359.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8360.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8360.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8401.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8401.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8410.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8410.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8429.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8429.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8430.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8430.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8435.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8435.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8437.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8437.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8439.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8439.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8444.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8444.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8446.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8446.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8451.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8451.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8453.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8453.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8463.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8463.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8465.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8465.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8472.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8472.png -------------------------------------------------------------------------------- /img/runesReforged/perk/8473.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/8473.png -------------------------------------------------------------------------------- /img/runesReforged/perk/9101.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/9101.png -------------------------------------------------------------------------------- /img/runesReforged/perk/9103.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/9103.png -------------------------------------------------------------------------------- /img/runesReforged/perk/9104.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/9104.png -------------------------------------------------------------------------------- /img/runesReforged/perk/9105.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/9105.png -------------------------------------------------------------------------------- /img/runesReforged/perk/9111.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/9111.png -------------------------------------------------------------------------------- /img/runesReforged/perk/9923.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/9923.png -------------------------------------------------------------------------------- /img/runesReforged/perk/qm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perk/qm.png -------------------------------------------------------------------------------- /img/runesReforged/perkStyle/8000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perkStyle/8000.png -------------------------------------------------------------------------------- /img/runesReforged/perkStyle/8100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perkStyle/8100.png -------------------------------------------------------------------------------- /img/runesReforged/perkStyle/8200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perkStyle/8200.png -------------------------------------------------------------------------------- /img/runesReforged/perkStyle/8300.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perkStyle/8300.png -------------------------------------------------------------------------------- /img/runesReforged/perkStyle/8400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/runesReforged/perkStyle/8400.png -------------------------------------------------------------------------------- /img/unknown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OrangeNote/RuneBook/326e0516b78556fa2be9961dd4bc75dcc70bfa57/img/unknown.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | 14 | 15 | 16 | 17 | 21 | 22 | 23 | 24 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /light.css: -------------------------------------------------------------------------------- 1 | body { 2 | background: #ffffff; 3 | } 4 | 5 | .ui.secondary.pointing.menu { 6 | background: #ffffff; 7 | border-bottom: 1px solid #BD9D5E; 8 | } 9 | 10 | .ui.secondary.pointing.menu .header.item { 11 | color: #191D24 !important; 12 | } 13 | 14 | #autochamp-label span { 15 | color: #191D24; 16 | } 17 | 18 | #autochamp-label::before { 19 | background: #ffffff !important; 20 | border: 2px solid #BD9D5E; 21 | } 22 | 23 | .ui.toggle.checkbox.checked #autochamp-label::before { 24 | background: #ffffff !important; 25 | border: 2px solid #00ACB1; 26 | } 27 | 28 | #autochamp-label::after { 29 | background: #d8cfbd !important; 30 | } 31 | 32 | div.ui.icon.input input { 33 | background: #ffffff; 34 | color: #191D24; 35 | } 36 | 37 | input::selection { 38 | background: #00ACB1; 39 | color: #ffffff; 40 | } 41 | 42 | .ui.search.fluid.champion .prompt { 43 | border: 2px solid #BD9D5E; 44 | } 45 | 46 | .ui.search.fluid.champion.focus .prompt { 47 | border: 2px solid #00ACB1; 48 | } 49 | 50 | .search.icon { 51 | color: #d8cfbd !important; 52 | } 53 | 54 | .results { 55 | border: 1px solid #BD9D5E !important; 56 | } 57 | 58 | .results .result { 59 | background: #ffffff; 60 | } 61 | 62 | .results .result.active { 63 | background: #f7f7f7 !important; 64 | } 65 | 66 | .results .result:hover { 67 | background: #f7f7f7 !important; 68 | } 69 | 70 | .ui.search > .results .result .title { 71 | color: #191D24; 72 | } 73 | 74 | .ui.search > .results .result.active .title { 75 | color: #191D24; 76 | } 77 | 78 | runebook .ui.horizontal.divider { 79 | color: #191D24; 80 | } 81 | 82 | .ui.top.attached.pointing.small.borderless.menu { 83 | background: #ffffff; 84 | border-color: #BD9D5E; 85 | } 86 | 87 | .ui.top.attached.pointing.small.borderless.menu .item { 88 | color: #191D24; 89 | } 90 | 91 | .ui.top.attached.pointing.small.borderless.menu .item.active { 92 | background: #d8cfbd; 93 | box-shadow: inset 1px 0px 0px 0px #BD9D5E, inset -1px 0px 0px 0px #BD9D5E; 94 | color: #191D24; 95 | } 96 | 97 | .ui.top.attached.pointing.small.borderless.menu .item.active::after { 98 | background: #d8cfbd !important; 99 | border-bottom: 2px solid #BD9D5E !important; 100 | border-right: 2px solid #BD9D5E !important; 101 | } 102 | 103 | .ui.bottom.attached.tab.segment { 104 | background: #ffffff; 105 | border-color: #BD9D5E; 106 | } 107 | 108 | chapters-segment .ui.active.inverted.dimmer { 109 | background: #ffffff; 110 | } 111 | 112 | page-list ::-webkit-scrollbar-thumb { 113 | background: #71552B; 114 | } 115 | 116 | page-list ::-webkit-scrollbar-thumb:window-inactive { 117 | background: #71552B; 118 | } 119 | 120 | page-list ::-webkit-scrollbar-thumb:hover { 121 | background: #BD9D5E; 122 | } 123 | 124 | .ui.divided.list>.item { 125 | border-top: 1px solid #BD9D5E; 126 | color: #191D24 !important; 127 | } 128 | 129 | .row .header .icon { 130 | color: #BD9D5E; 131 | } 132 | 133 | .row .header .content { 134 | color: #191D24; 135 | } 136 | 137 | .row .header .content .sub.header { 138 | color: #191D24; 139 | } 140 | 141 | .ui.segment { 142 | background: #ffffff; 143 | border: 1px solid #BD9D5E; 144 | } 145 | 146 | .ui.segment .header { 147 | color: #191D24; 148 | } 149 | 150 | .ui.segment .header .sub.header { 151 | color: #191D24; 152 | } 153 | 154 | current-page .ui.button { 155 | background: #BD9D5E; 156 | } 157 | 158 | page-list .ui.button { 159 | background: #BD9D5E; 160 | } 161 | 162 | current-page .ui.button:hover { 163 | background: #C7B185; 164 | } 165 | 166 | page-list .ui.button:hover { 167 | background: #C7B185; 168 | } 169 | 170 | current-page .ui.button:focus { 171 | background: #BD9D5E; 172 | } 173 | 174 | page-list .ui.button:focus { 175 | background: #BD9D5E; 176 | } 177 | 178 | current-page .ui.button:active { 179 | background: #C7B185; 180 | } 181 | 182 | page-list .ui.button:active { 183 | background: #C7B185; 184 | } 185 | 186 | .ui.popup { 187 | background: #ffffff; 188 | color: #191D24; 189 | border: 1px solid #BD9D5E; 190 | } 191 | 192 | .ui.popup::before { 193 | background: #ffffff !important; 194 | border-bottom: 1px solid #BD9D5E !important; 195 | border-right: 1px solid #BD9D5E !important; 196 | box-shadow: none !important; 197 | } 198 | 199 | .ui.popup.bottom::before { 200 | background: #ffffff !important; 201 | border-left: 1px solid #BD9D5E !important; 202 | border-bottom: none !important; 203 | border-right: none !important; 204 | border-top: 1px solid #BD9D5E !important; 205 | box-shadow: none !important; 206 | } 207 | -------------------------------------------------------------------------------- /oldsplash.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 17 | 18 | 19 | 20 | Old Logo 21 | 22 | 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "RuneBook", 3 | "productName": "RuneBook", 4 | "version": "1.8.11", 5 | "description": "An automatic rune pages manager for League of Legends", 6 | "main": "./src/main.js", 7 | "license": "MIT", 8 | "repository": "https://github.com/OrangeNote/RuneBook", 9 | "author": { 10 | "name": "OrangeNote", 11 | "url": "https://github.com/OrangeNote" 12 | }, 13 | "scripts": { 14 | "test": "xo", 15 | "start": "electron ./src/main.js", 16 | "build": "electron-packager . --out=dist --asar --overwrite --all", 17 | "pack": "electron-builder --dir", 18 | "dist": "electron-builder -mw -p always", 19 | "dist:mac": "electron-builder --mac", 20 | "dist:win": "electron-builder --win", 21 | "dist:all": "electron-builder -mw" 22 | }, 23 | "dependencies": { 24 | "atob": "^2.1.1", 25 | "cheerio": "^1.0.0-rc.2", 26 | "electron-debug": "^1.5.0", 27 | "electron-is-dev": "^0.3.0", 28 | "electron-store": "^1.3.0", 29 | "electron-updater": "^2.20.1", 30 | "electron-window-state": "^4.1.1", 31 | "freezer-js": "^0.13.0", 32 | "glob": "^7.1.2", 33 | "jquery": "^3.3.0", 34 | "lcu-connector": "^1.0.2", 35 | "lodash": "^4.17.4", 36 | "popper.js": "^1.12.9", 37 | "request": "^2.83.0", 38 | "request-promise-native": "^1.0.5", 39 | "riot": "^3.8.1", 40 | "riot-i18n": "^0.2.1", 41 | "semantic-ui-css": "^2.2.14", 42 | "tether": "^1.4.3", 43 | "username": "^3.0.0", 44 | "winston": "3.0.0-rc0", 45 | "ws": "^4.0.0" 46 | }, 47 | "devDependencies": { 48 | "devtron": "^1.1.0", 49 | "electron": "^1.6.6", 50 | "electron-builder": "^19.54.0", 51 | "electron-packager": "^8.0.0", 52 | "xo": "^0.18.0" 53 | }, 54 | "xo": { 55 | "envs": [ 56 | "node", 57 | "browser" 58 | ] 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /plugins/championgg.js: -------------------------------------------------------------------------------- 1 | var request = require('request'); 2 | var cheerio = require('cheerio'); 3 | 4 | var url = "http://champion.gg"; 5 | 6 | var stylesMap = { 7 | "Precision":8000, 8 | "Domination":8100, 9 | "Sorcery":8200, 10 | "Resolve":8400, 11 | "Inspiration":8300 12 | }; 13 | 14 | var perksMap = { 15 | "Press the Attack":8005, 16 | "Lethal Tempo":8008, 17 | "Fleet Footwork":8021, 18 | "Conqueror":8010, 19 | "Overheal":9101, 20 | "Triumph":9111, 21 | "Presence of Mind":8009, 22 | "Legend: Alacrity":9104, 23 | "Legend: Tenacity":9105, 24 | "Legend: Bloodline":9103, 25 | "Coup de Grace":8014, 26 | "Cut Down":8017, 27 | "Last Stand":8299, 28 | "Electrocute":8112, 29 | "Predator":8124, 30 | "Dark Harvest":8128, 31 | "Cheap Shot":8126, 32 | "Taste of Blood":8139, 33 | "Sudden Impact":8143, 34 | "Zombie Ward":8136, 35 | "Ghost Poro":8120, 36 | "Eyeball Collection":8138, 37 | "Ravenous Hunter":8135, 38 | "Ingenious Hunter":8134, 39 | "Relentless Hunter":8105, 40 | "Summon Aery":8214, 41 | "Arcane Comet":8229, 42 | "Phase Rush":8230, 43 | "Nullifying Orb":8224, 44 | "Manaflow Band":8226, 45 | "The Ultimate Hat":8243, 46 | "Transcendence":8210, 47 | "Celerity":8234, 48 | "Absolute Focus":8233, 49 | "Scorch":8237, 50 | "Waterwalking":8232, 51 | "Gathering Storm":8236, 52 | "Grasp of the Undying":8437, 53 | "Aftershock":8439, 54 | "Guardian":8465, 55 | "Unflinching":8242, 56 | "Demolish":8446, 57 | "Font of Life":8463, 58 | "Chrysalis":8472, 59 | "Conditioning":8429, 60 | "Overgrowth":8451, 61 | "Revitalize":8453, 62 | "Second Wind":8444, 63 | "Unsealed Spellbook":8360, 64 | "Glacial Augment":8351, 65 | "Kleptomancy":8359, 66 | "Hextech Flashtraption":8306, 67 | "Biscuit Delivery":8345, 68 | "Perfect Timing":8313, 69 | "Magical Footwear":8304, 70 | "Future's Market":8321, 71 | "Minion Dematerializer":8316, 72 | "Cosmic Insight":8347, 73 | "Approach Velocity":8410, 74 | "Celestial Body":8339, 75 | "Bone Plating":8473, 76 | "Time Warp Tonic":8352, 77 | "Hail of Blades":9923, 78 | "Ultimate Hunter":8106, 79 | "Nimbus Cloak":8275, 80 | "Shield Bash":8401, 81 | 82 | "Scaling Health": 5001, 83 | "Armor": 5002, 84 | "Magic Resist": 5003, 85 | "Attack Speed": 5005, 86 | "Scaling Cooldown Reduction": 5007, 87 | "Adaptive Force": 5008 88 | }; 89 | 90 | function exctractPage(html, champion, rec, callback, pageType) { 91 | var $ = cheerio.load(html); 92 | 93 | var pages = []; 94 | var runecount = -1; 95 | var slots = $("div[class^=Slot__RightSide]"); 96 | 97 | var role = $(`li[class^='selected-role'] a[href^='/champion/${champion}']`).first(); 98 | 99 | $("div[class*='Description__Title']", slots).each(function(index) { 100 | if(index % 11 == 0) { 101 | pages.push({ 102 | "name": $(".champion-profile h1").text() + " " + role.text().trim() + (Math.floor(runecount / 9) ? " HW" : " MF"), 103 | "primaryStyleId": -1, 104 | "selectedPerkIds": [0, 0, 0, 0, 0, 0], 105 | "subStyleId": -1, 106 | "bookmark": { 107 | "src": url + role.attr("href"), 108 | "meta": { 109 | "pageType": Math.floor(index / 11), 110 | "champion": champion 111 | }, 112 | "remote": { "name": plugin.name, "id": plugin.id } 113 | } 114 | }) 115 | } 116 | var rune = $(this).text(); 117 | rune = rune.replace(".png", ""); 118 | console.log(rune) 119 | if(index % 11 == 0) { 120 | pages[pages.length - 1].primaryStyleId = stylesMap[rune]; 121 | return; 122 | } 123 | else if(index % 11 == 5) { 124 | pages[pages.length - 1].subStyleId = stylesMap[rune]; 125 | return; 126 | } 127 | else runecount++; 128 | 129 | pages[pages.length - 1].selectedPerkIds[runecount % 9] = perksMap[rune]; 130 | }); 131 | 132 | if(rec) { 133 | var reqCount = 0; 134 | var els = $(`li[class!='selected-role'] a[href^='/champion/${champion}']`); 135 | console.log("IF REC TRUE") 136 | console.log("ELS length", els.length) 137 | if(els.length == 0) return callback(pages); 138 | els.each(function(index) { 139 | console.log(url + "/champion/" + champion + "/" + $(this).text().trim()) 140 | request.get(url + "/champion/" + champion + "/" + $(this).text().trim(), (error, response, _html) => { 141 | if(!error && response.statusCode == 200) { 142 | var newPages = exctractPage(_html, champion, false); 143 | pages = pages.concat(newPages); 144 | console.log("newPages", newPages) 145 | if(++reqCount == els.length) callback(pages); 146 | } 147 | }); 148 | }); 149 | } 150 | return ((typeof pageType !== "undefined") ? pages[pageType] : pages); 151 | } 152 | 153 | function _getPages(champion, callback) { 154 | var res = {pages: {}}; 155 | 156 | var champUrl = url + "/champion/" + champion; 157 | console.log(champUrl) 158 | request.get(champUrl, (error, response, html) => { 159 | if(!error && response.statusCode == 200) { 160 | exctractPage(html, champion, true, (pages) => { 161 | pages.forEach((page) => { 162 | res.pages[page.name] = page; 163 | }); 164 | console.log(res) 165 | callback(res); 166 | }); 167 | } 168 | else { 169 | callback(res); 170 | throw Error("rune page not loaded"); 171 | } 172 | }); 173 | } 174 | 175 | var plugin = { 176 | id: "championgg", 177 | name: "Champion.gg", 178 | active: true, 179 | bookmarks: true, 180 | 181 | getPages(champion, callback) { 182 | _getPages(champion, callback); 183 | }, 184 | 185 | syncBookmark(bookmark, callback) { 186 | request.get(bookmark.src, (error, response, html) => { 187 | if(!error && response.statusCode == 200) { 188 | callback(exctractPage(html, bookmark.meta.champion, false, null, bookmark.meta.pageType)); 189 | } 190 | else { 191 | throw Error("rune page not loaded"); 192 | } 193 | }); 194 | } 195 | } 196 | 197 | module.exports = { plugin }; -------------------------------------------------------------------------------- /plugins/index.js: -------------------------------------------------------------------------------- 1 | var isDev = require('electron-is-dev'); 2 | 3 | if (!isDev) { 4 | var plugins = ["local", "runeforge", "championgg", "koreanbuilds", "runeslol", "opgg", "ugg"]; 5 | 6 | var __hasProp = {}.hasOwnProperty; 7 | 8 | for(var i = 0; i < plugins.length; i++) { 9 | var name = plugins[i]; 10 | var include = require(`./${name}.js`); 11 | for(func in include) { 12 | if(!__hasProp.call(include, func) || !include[func].active) continue; 13 | module.exports[name] = include[func]; 14 | } 15 | } 16 | 17 | } 18 | else { 19 | console.log("isDev: dynamic plugins loader") 20 | var collectExports, fs, path, 21 | fs = require('fs'); 22 | path = require('path'); 23 | 24 | var __hasProp = {}.hasOwnProperty; 25 | 26 | collectExports = function(file) { 27 | var func, include, _results, name; 28 | 29 | if (path.extname(file) === '.js' && file !== 'index.js' && file !== 'utils.js') { 30 | include = require('./' + file); 31 | name = path.basename(file, '.js'); 32 | _results = []; 33 | for (func in include) { 34 | if (!__hasProp.call(include, func) || !include[func].active) continue; 35 | _results.push(exports[name] = include[func]); 36 | } 37 | return _results; 38 | } 39 | }; 40 | 41 | fs.readdirSync('./plugins').forEach(collectExports); 42 | } -------------------------------------------------------------------------------- /plugins/koreanbuilds.js: -------------------------------------------------------------------------------- 1 | var request = require('request'); 2 | var cheerio = require('cheerio'); 3 | 4 | var url = "http://koreanbuilds.net"; 5 | 6 | var stylesMap = { 7 | "8000":8000, 8 | "8100":8100, 9 | "8200":8200, 10 | "8300":8400, 11 | "8400":8300 12 | }; 13 | 14 | var shardsMap = { 15 | "5003": 5008, 16 | "5008": 5003 17 | } 18 | 19 | function extractPage(html, champObj, champion, role, rec, callback, pageType) { 20 | var $ = cheerio.load(html); 21 | 22 | var pages = []; 23 | var runecount = -1; 24 | var slots = $("div[class^=perk-itm], div[class^=statperk]"); 25 | 26 | 27 | $("img[src^='//statics.koreanbuilds.net/perks/']", slots).each(function(index) { 28 | console.log(index) 29 | if(index % 11 == 0) { 30 | pages.push({ 31 | "name": champObj.name + " " + role + " BC "+ $('#circle-big').text(), 32 | "primaryStyleId": -1, 33 | "selectedPerkIds": [0, 0, 0, 0, 0, 0], 34 | "subStyleId": -1, 35 | // "bookmark": { 36 | // "src": url + "/champion/" + champion + "/" + role + "/" + champObj.version.replace(/\.(?:[0-9]*)$/, '') + '/-1', 37 | // "meta": { 38 | // "pageType": Math.floor(index / 6), 39 | // "champion": champion 40 | // }, 41 | // "remote": { "name": plugin.name, "id": plugin.id } 42 | // } 43 | }) 44 | } 45 | var rune = $(this).attr("src"); 46 | rune = rune.replace("//statics.koreanbuilds.net/perks/", ""); 47 | rune = rune.replace(".png", ""); 48 | rune = shardsMap[rune] ? shardsMap[rune] : rune; 49 | var primary = $('#reforged-primary .perk-img-c').attr("src"); 50 | primary = primary.replace("//statics.koreanbuilds.net/perk-types/", ""); 51 | primary = primary.replace(".png", ""); 52 | var secondary = $('#reforged-secondary .perk-img-c').attr("src"); 53 | secondary = secondary.replace("//statics.koreanbuilds.net/perk-types/", ""); 54 | secondary = secondary.replace(".png", ""); 55 | if(index % 9 == 0) { 56 | pages[pages.length - 1].primaryStyleId = stylesMap[primary]; 57 | pages[pages.length - 1].subStyleId = stylesMap[secondary]; 58 | } 59 | pages[pages.length - 1].selectedPerkIds[index] = parseInt(rune); 60 | }); 61 | 62 | if(rec) { 63 | var reqCount = 0; 64 | var summs = []; 65 | $('#summSel option').each(function(index) { 66 | if(index != 0) 67 | summs.push($(this).val()) 68 | }) 69 | console.log("IF REC TRUE") 70 | console.log("summs length", summs.length) 71 | if(summs.length == 0) return callback(pages); 72 | summs.forEach(function(value) { 73 | console.log(url + "/champion/" + champObj.name + "/" + role + "/" + champObj.version.replace(/\.(?:[0-9]*)$/, '') + '/enc/'+ value) 74 | request.get(url + "/champion/" + champObj.name + "/" + role + "/" + champObj.version.replace(/\.(?:[0-9]*)$/, '') + '/enc/' + value, (error, response, _html) => { 75 | if(!error && response.statusCode == 200) { 76 | var newPages = extractPage(_html, champObj, champion, role, false); 77 | pages = pages.concat(newPages); 78 | console.log("newPages", newPages) 79 | if(++reqCount == summs.length) callback(pages); 80 | } 81 | }); 82 | }); 83 | } 84 | var regex = /(?:\d{0,3}(\.\d{1,2})? *%?)$/ 85 | pages.sort((a, b) => { 86 | var percentA = parseFloat(a.name.match(regex)[0]); 87 | var percentB = parseFloat(b.name.match(regex)[0]); 88 | return percentB - percentA; 89 | }) 90 | return ((typeof pageType !== "undefined") ? pages[pageType] : pages); 91 | } 92 | 93 | function _getPages(champion, callback) { 94 | var res = {pages: {}}; 95 | 96 | var champ = freezer.get().championsinfo[champion] 97 | var champId = champ.key; 98 | request.get(url + "/roles?championid="+ champId, (error, response, html) => { 99 | if(!error && response.statusCode == 200) { 100 | var $ = cheerio.load(html); 101 | var rolesExtracted = $.root().text().split('\n').filter((value) => value != ''); 102 | var roles = rolesExtracted.map((s) => { return String.prototype.trim.apply(s) }) 103 | if(!roles.length || roles.length == 0){ 104 | console.log(`No builds found for ${champion}.`) 105 | callback(res) 106 | } else { 107 | roles.forEach((role) => { 108 | var champUrl = url + "/champion/" + champ.name + "/" + role + "/" + champ.version.replace(/\.(?:[0-9]*)$/, '') + '/enc/NA'; 109 | request.get(champUrl, (error, response, html) => { 110 | if(!error && response.statusCode == 200) { 111 | extractPage(html, champ, champion, role, true, (pages) => { 112 | pages.forEach((page) => { 113 | res.pages[page.name] = page; 114 | }); 115 | console.log(res) 116 | callback(res); 117 | }); 118 | } 119 | else { 120 | callback(res); 121 | throw Error("rune page not loaded"); 122 | } 123 | }); 124 | }) 125 | } 126 | } 127 | else { 128 | callback(res); 129 | throw Error("roles page not loaded"); 130 | } 131 | }); 132 | 133 | } 134 | 135 | var plugin = { 136 | id: "koreanbuilds", 137 | name: "Korean Builds", 138 | active: true, 139 | bookmarks: false, 140 | 141 | getPages(champion, callback) { 142 | _getPages(champion, callback); 143 | }, 144 | 145 | syncBookmark(bookmark, callback) { 146 | request.get(bookmark.src, (error, response, html) => { 147 | if(!error && response.statusCode == 200) { 148 | callback(extractPage(html, bookmark.meta.champion, false, null, bookmark.meta.pageType)); 149 | } 150 | else { 151 | throw Error("rune page not loaded"); 152 | } 153 | }); 154 | } 155 | } 156 | 157 | module.exports = { plugin }; -------------------------------------------------------------------------------- /plugins/local.js: -------------------------------------------------------------------------------- 1 | var Store = require('electron-store'); 2 | var settings = require('../src/settings'); 3 | 4 | var configPath = settings.get("config.cwd"); 5 | var configName = settings.get("config.name"); 6 | 7 | console.log("configName", configName); 8 | console.log("configPath", configPath); 9 | 10 | var store = new Store({cwd: configPath, name: configName}); 11 | 12 | var plugin = { 13 | name: "chapters.localpages", 14 | local: true, 15 | active: true, 16 | 17 | getPages(champion, callback) { 18 | var res = store.get(`local.${champion}`) || {pages: {}}; 19 | callback(res); 20 | }, 21 | 22 | favPage(champion, page) { 23 | if(store.get(`local.${champion}.fav`) == page) { 24 | store.set(`local.${champion}.fav`, null); 25 | } 26 | else store.set(`local.${champion}.fav`, page); 27 | }, 28 | 29 | deletePage(champion, page) { 30 | console.log(champion, page) 31 | page = page.replace(/\./g, '\\.'); 32 | store.delete(`local.${champion}.pages.${page}`); 33 | if(store.get(`local.${champion}.fav`) == page) { 34 | store.set(`local.${champion}.fav`, null); 35 | } 36 | }, 37 | 38 | unlinkBookmark(champion, page) { 39 | page = page.replace(/\./g, '\\.'); 40 | store.delete(`local.${champion}.pages.${page}.bookmark`); 41 | }, 42 | 43 | setPage(champion, page) { 44 | var pages = store.get(`local.${champion}.pages`) || {}; 45 | pages[page.name] = page; 46 | store.set(`local.${champion}.pages`, pages); 47 | }, 48 | 49 | confirmPageValidity(champion, page, res) { 50 | page = page.replace(/\./g, '\\.'); 51 | /* 52 | * If the page returned is invalid, mark it as such in the store. 53 | * This behaviour is not predictable (a page can become invalid at any time), 54 | * so we want to make sure to notify users as soon as we get this info from lcu. 55 | */ 56 | if(res.isValid === false) { 57 | console.log("Warning: page incomplete or malformed."); 58 | store.set(`local.${champion}.pages.${page}.isValid`, false); 59 | } 60 | /* 61 | * If the page returned is valid, but we have an invalid copy in the store, 62 | * then replace the local page with the updated one. 63 | */ 64 | else if(store.get(`local.${champion}.pages.${page}.isValid`) === false) { 65 | store.set(`local.${champion}.pages.${page}`, res); 66 | } 67 | } 68 | } 69 | 70 | module.exports = { plugin }; -------------------------------------------------------------------------------- /plugins/opgg.js: -------------------------------------------------------------------------------- 1 | const cheerio = require('cheerio'); 2 | const request = require('request'); 3 | const { upperFirst } = require('lodash'); 4 | 5 | const url = 'http://www.op.gg/champion/'; 6 | 7 | function extractRunePagesFromElement($, champion, position) { 8 | const getPerkIdFromImg = (_, elem) => 9 | $(elem) 10 | .attr('src') 11 | .split('/') 12 | .slice(-1) 13 | .pop() 14 | .split('.')[0]; 15 | 16 | return (runePageElement, index) => { 17 | const stats = $(runePageElement) 18 | .find('.champion-overview__stats strong') 19 | .map((i, elem) => $(elem).text()) 20 | .get(); 21 | 22 | const name = `${champion} ${upperFirst(position)} PR${stats[0]} WR${stats[1]}`; 23 | 24 | const styles = $(runePageElement) 25 | .find('.champion-overview__data .perk-page .perk-page__item--mark img') 26 | .map(getPerkIdFromImg) 27 | .get(); 28 | 29 | // normal runes 30 | let selectedPerkIds = $(runePageElement) 31 | .find('.champion-overview__data .perk-page .perk-page__item--active img') 32 | .map(getPerkIdFromImg) 33 | .get(); 34 | 35 | // stat shards 36 | selectedPerkIds = selectedPerkIds.concat( 37 | $(runePageElement) 38 | .find('.champion-overview__data .fragment-page img.active') 39 | .map(getPerkIdFromImg) 40 | .get() 41 | ); 42 | 43 | return { 44 | name, 45 | primaryStyleId: styles[0], 46 | subStyleId: styles[1], 47 | selectedPerkIds, 48 | bookmark: { 49 | src: url + champion + '/statistics/' + position, 50 | meta: { 51 | pageType: index, 52 | champion 53 | }, 54 | remote: { 55 | name: 'OP.GG', 56 | id: 'opgg' 57 | } 58 | } 59 | }; 60 | }; 61 | } 62 | 63 | function parsePage($, champion, position) { 64 | return $("tbody[class*='ChampionKeystoneRune-'] tr") 65 | .toArray() 66 | .map(extractRunePagesFromElement($, champion, position)); 67 | } 68 | 69 | function parseSinglePage($, champion, position, pageType) { 70 | const element = $("tbody[class*='ChampionKeystoneRune-'] tr").get(pageType); 71 | return extractRunePagesFromElement($, champion, position)(element, pageType); 72 | } 73 | 74 | function extractPages(html, champion, callback) { 75 | const $ = cheerio.load(html); 76 | let pages = []; 77 | let initialPosition; 78 | 79 | const positions = $('.champion-stats-position li') 80 | .map((_, element) => { 81 | if (element.attribs['class'].indexOf('champion-stats-header__position--active') !== -1) { 82 | initialPosition = element.attribs['data-position'].toLowerCase(); 83 | } 84 | 85 | return element.attribs['data-position'].toLowerCase(); 86 | }) 87 | .get(); 88 | 89 | pages = pages.concat(parsePage($, champion, initialPosition)); 90 | 91 | positions.splice(positions.indexOf(initialPosition), 1); 92 | 93 | if (positions.length) { 94 | positions.forEach((position, index) => { 95 | const opggUrl = url + champion + '/statistics/' + position; 96 | request.get(opggUrl, (error, response, newHtml) => { 97 | if (!error && response.statusCode === 200) { 98 | pages = pages.concat(parsePage(cheerio.load(newHtml), champion, position)); 99 | if (index === positions.length - 1) { 100 | callback(pages); 101 | } 102 | } 103 | }); 104 | }); 105 | } else { 106 | callback(pages); 107 | } 108 | } 109 | 110 | function _getPages(champion, callback) { 111 | const runePages = { pages: {} }; 112 | 113 | const entryChampUrl = url + champion; 114 | request.get(entryChampUrl, (error, response, html) => { 115 | if (!error && response.statusCode === 200) { 116 | extractPages(html, champion, pages => { 117 | pages.forEach(page => { 118 | runePages.pages[page.name] = page; 119 | }); 120 | callback(runePages); 121 | }); 122 | } else { 123 | callback(runePages); 124 | throw Error('rune page not loaded'); 125 | } 126 | }); 127 | } 128 | 129 | const plugin = { 130 | id: 'opgg', 131 | name: 'OP.GG', 132 | active: true, 133 | bookmarks: true, 134 | getPages(champion, callback) { 135 | _getPages(champion, callback); 136 | }, 137 | syncBookmark(bookmark, callback) { 138 | request.get(bookmark.src, (error, response, html) => { 139 | if (!error && response.statusCode == 200) { 140 | const position = bookmark.src.split('/').pop(); 141 | callback( 142 | parseSinglePage( 143 | cheerio.load(html), 144 | bookmark.meta.champion, 145 | position, 146 | bookmark.meta.pageType 147 | ) 148 | ); 149 | } else { 150 | throw Error('rune page not loaded'); 151 | } 152 | }); 153 | } 154 | }; 155 | 156 | module.exports = { plugin }; 157 | -------------------------------------------------------------------------------- /plugins/runeforge.js: -------------------------------------------------------------------------------- 1 | var request = require('request'); 2 | var runeforge; 3 | var connected = false; 4 | 5 | function connect(callback) { 6 | request.post("http://runeforge.gg/all-loadouts-data.json", (error, response, data) => { 7 | if(!error && response.statusCode == 200) { 8 | runeforge = JSON.parse(data); 9 | callback(true); 10 | } 11 | else { 12 | callback(false); 13 | throw Error("runeforge json not loaded"); 14 | } 15 | }); 16 | } 17 | 18 | connect((res) => { connected = res; }); 19 | 20 | var cheerio = require('cheerio'); 21 | 22 | var stylesMap = { 23 | "Precision":8000, 24 | "Domination":8100, 25 | "Sorcery":8200, 26 | "Resolve":8400, 27 | "Inspiration":8300 28 | }; 29 | var perksMap = { 30 | "Press the Attack":8005, 31 | "Lethal Tempo":8008, 32 | "Fleet Footwork":8021, 33 | "Conqueror":8010, 34 | "Overheal":9101, 35 | "Triumph":9111, 36 | "Presence of Mind":8009, 37 | "Legend: Alacrity":9104, 38 | "Legend: Tenacity":9105, 39 | "Legend: Bloodline":9103, 40 | "Coup De Grace":8014, 41 | "Cut Down":8017, 42 | "Last Stand":8299, 43 | "Electrocute":8112, 44 | "Predator":8124, 45 | "Dark Harvest":8128, 46 | "Cheap Shot":8126, 47 | "Taste of Blood":8139, 48 | "Sudden Impact":8143, 49 | "Zombie Ward":8136, 50 | "Ghost Poro":8120, 51 | "Eyeball Collection":8138, 52 | "Ravenous Hunter":8135, 53 | "Ingenious Hunter":8134, 54 | "Relentless Hunter":8105, 55 | "Summon Aery":8214, 56 | "Arcane Comet":8229, 57 | "Phase Rush":8230, 58 | "Nullifying Orb":8224, 59 | "Manaflow Band":8226, 60 | "The Ultimate Hat":8243, 61 | "Transcendence":8210, 62 | "Celerity":8234, 63 | "Absolute Focus":8233, 64 | "Scorch":8237, 65 | "Waterwalking":8232, 66 | "Gathering Storm":8236, 67 | "Grasp of the Undying":8437, 68 | "Aftershock":8439, 69 | "Guardian":8465, 70 | "Unflinching":8242, 71 | "Demolish":8446, 72 | "Font of Life":8463, 73 | "Chrysalis":8472, 74 | "Conditioning":8429, 75 | "Overgrowth":8451, 76 | "Revitalize":8453, 77 | "Second Wind":8444, 78 | "Unsealed Spellbook":8360, 79 | "Glacial Augment":8351, 80 | "Kleptomancy":8359, 81 | "Hextech Flashtraption":8306, 82 | "Biscuit Delivery":8345, 83 | "Perfect Timing":8313, 84 | "Magical Footwear":8304, 85 | "Future’s Market":8321, 86 | "Minion Dematerializer":8316, 87 | "Cosmic Insight":8347, 88 | "Approach Velocity":8410, 89 | "Celestial Body":8339, 90 | "Bone Plating":8473, 91 | "Time Warp Tonic":8352, 92 | "Hail of Blades":9923, 93 | "Ultimate Hunter":8106, 94 | "Nimbus Cloak":8275, 95 | "Shield Bash":8401 96 | }; 97 | 98 | var shardsMap = { 99 | "shard-health": 5001, 100 | "shard-armor": 5002, 101 | "shard-mr": 5003, 102 | "shard-as": 5005, 103 | "shard-cdr": 5007, 104 | "shard-af": 5008, 105 | 106 | "shard-armor-1": 5002, 107 | "shard-hybrid-2-1": 5002, 108 | "shard-hybrid": 5002 109 | }; 110 | 111 | function exctractPage(html, pageUrl) { 112 | console.log(pageUrl) 113 | var $ = cheerio.load(html); 114 | 115 | if(typeof pageUrl === "undefined") { 116 | pageUrl = $("link[rel='canonical']").attr("href"); 117 | } 118 | 119 | var path = $("div.rune-paths").first(); 120 | 121 | var name = $(".loadout-title").text(); 122 | if(name.length > 22) name = name.substring(0, 22) + "..." 123 | 124 | var page = { 125 | "name": name, 126 | "primaryStyleId": -1, 127 | "selectedPerkIds": [0, 0, 0, 0, 0, 0, 0, 0, 0], 128 | "subStyleId": -1, 129 | "bookmark": { "src": pageUrl, "remote": { "name": plugin.name, "id": plugin.id } } 130 | }; 131 | 132 | var data = []; 133 | $("li.rune-path--rune", path).each(function() { 134 | data.push($(this).attr("data-link-title")); 135 | }); 136 | 137 | page.primaryStyleId = stylesMap[$("div.rune-path--primary .rune-path--path", path).attr("data-content-title")]; 138 | page.subStyleId = stylesMap[$("div.rune-path--secondary .rune-path--path", path).attr("data-content-title")]; 139 | 140 | for(var i = 0; i < data.length; i++) { 141 | page.selectedPerkIds[i] = perksMap[data[i]]; 142 | } 143 | 144 | var shards = []; 145 | 146 | var shardsPath = $("div.stat-shards").first(); 147 | $("img", shardsPath).each(function() { 148 | var shardLink = $(this).attr("src").split("/"); 149 | var shardName = shardLink[shardLink.length - 1].replace(".svg", ""); 150 | shards.push(shardsMap[shardName]); 151 | }); 152 | 153 | page.selectedPerkIds[6] = shards[0]; 154 | page.selectedPerkIds[7] = shards[1]; 155 | page.selectedPerkIds[8] = shards[2]; 156 | 157 | console.log(page) 158 | return page; 159 | } 160 | 161 | function _getPages(champion, callback) { 162 | var res = {pages: {}}; 163 | 164 | if(!runeforge) return callback(res); 165 | 166 | var pageUrls = []; 167 | 168 | for(var i = 0; i < runeforge.length; i++) { 169 | var pageData = runeforge[i]; 170 | var sep = pageData.loadout_champion_grid.split("/"); 171 | sep = sep[sep.length - 1].split(".")[0]; 172 | if(champion == sep) { 173 | pageUrls.push(pageData.loadout_url); 174 | } 175 | } 176 | 177 | if(pageUrls.length === 0) return callback(res); 178 | 179 | var callCount = 0; 180 | for(var i = 0; i < pageUrls.length; i++) { 181 | 182 | request.post(pageUrls[i], (error, response, html) => { 183 | if(!error && response.statusCode == 200) { 184 | var page = exctractPage(html); 185 | res.pages[page.name] = page; 186 | if(++callCount == pageUrls.length) callback(res); 187 | } 188 | else { 189 | callback(res); 190 | throw Error("rune page not loaded"); 191 | } 192 | }); 193 | } 194 | } 195 | 196 | var plugin = { 197 | id: "runeforge", 198 | name: "Rune Forge", 199 | active: true, 200 | bookmarks: true, 201 | 202 | getPages(champion, callback) { 203 | if(!connected) connect((res) => { 204 | connected = res; 205 | _getPages(champion, callback); 206 | }); 207 | else _getPages(champion, callback); 208 | }, 209 | 210 | syncBookmark(bookmark, callback) { 211 | request.post(bookmark.src, (error, response, html) => { 212 | if(!error && response.statusCode == 200) { 213 | callback(exctractPage(html, bookmark.src)); 214 | } 215 | else { 216 | callback(); 217 | throw Error("rune page not loaded"); 218 | } 219 | }); 220 | } 221 | } 222 | 223 | module.exports = { plugin }; 224 | -------------------------------------------------------------------------------- /plugins/runeslol.js: -------------------------------------------------------------------------------- 1 | var cheerio = require('cheerio'); 2 | var request = require('request'); 3 | 4 | var baseUrl = "https://runes.lol"; 5 | var url = baseUrl + "/{gamemode}/platinum/plus/champion/{page}/{champion}/{role}"; 6 | var modeWin = "win"; 7 | var modePick = "pick"; 8 | var gamemodeRanked = "ranked"; 9 | var gamemodeAram = "aram"; 10 | 11 | var stylesMap = { 12 | "PRECISION":8000, 13 | "DOMINATION":8100, 14 | "SORCERY":8200, 15 | "RESOLVE":8400, 16 | "INSPIRATION":8300 17 | }; 18 | var perksMap = { 19 | "Press the Attack":8005, 20 | "Lethal Tempo":8008, 21 | "Fleet Footwork":8021, 22 | "Conqueror":8010, 23 | "Overheal":9101, 24 | "Triumph":9111, 25 | "Presence of Mind":8009, 26 | "Legend: Alacrity":9104, 27 | "Legend: Tenacity":9105, 28 | "Legend: Bloodline":9103, 29 | "Coup de Grace":8014, 30 | "Cut Down":8017, 31 | "Last Stand":8299, 32 | "Electrocute":8112, 33 | "Predator":8124, 34 | "Dark Harvest":8128, 35 | "Cheap Shot":8126, 36 | "Taste of Blood":8139, 37 | "Sudden Impact":8143, 38 | "Zombie Ward":8136, 39 | "Ghost Poro":8120, 40 | "Eyeball Collection":8138, 41 | "Ravenous Hunter":8135, 42 | "Ingenious Hunter":8134, 43 | "Relentless Hunter":8105, 44 | "Summon Aery":8214, 45 | "Arcane Comet":8229, 46 | "Phase Rush":8230, 47 | "Nullifying Orb":8224, 48 | "Manaflow Band":8226, 49 | "The Ultimate Hat":8243, 50 | "Transcendence":8210, 51 | "Celerity":8234, 52 | "Absolute Focus":8233, 53 | "Scorch":8237, 54 | "Waterwalking":8232, 55 | "Gathering Storm":8236, 56 | "Grasp of the Undying":8437, 57 | "Aftershock":8439, 58 | "Guardian":8465, 59 | "Unflinching":8242, 60 | "Demolish":8446, 61 | "Font of Life":8463, 62 | "Chrysalis":8472, 63 | "Conditioning":8429, 64 | "Overgrowth":8451, 65 | "Revitalize":8453, 66 | "Second Wind":8444, 67 | "Unsealed Spellbook":8360, 68 | "Glacial Augment":8351, 69 | "Kleptomancy":8359, 70 | "Hextech Flashtraption":8306, 71 | "Biscuit Delivery":8345, 72 | "Perfect Timing":8313, 73 | "Magical Footwear":8304, 74 | "Future's Market":8321, 75 | "Minion Dematerializer":8316, 76 | "Cosmic Insight":8347, 77 | "Approach Velocity":8410, 78 | "Celestial Body":8339, 79 | "Bone Plating":8473, 80 | "Time Warp Tonic":8352, 81 | "Hail of Blades":9923, 82 | "Ultimate Hunter":8106, 83 | "Nimbus Cloak":8275 84 | }; 85 | 86 | function extractPage(html, pageName, pageUrl) { 87 | 88 | var $ = cheerio.load(html); 89 | var page = { 90 | "name": pageName, 91 | "primaryStyleId": -1, 92 | "selectedPerkIds": [0, 0, 0, 0, 0, 0], 93 | "subStyleId": -1, 94 | "bookmark": { "src": pageUrl, "pName": pageName, "remote": { "name": plugin.name, "id": plugin.id } } 95 | }; 96 | 97 | //getting keystone divs 98 | var keystones = []; 99 | 100 | $(".pure-u-8-24 > .runetitle").each(function() { keystones.push($(this).text()); }); 101 | 102 | page.primaryStyleId = stylesMap[keystones[0]]; 103 | page.subStyleId = stylesMap[keystones[1]]; 104 | 105 | // 2, 4, 6, 7 - main runes, 3, 5 - secondary runes 106 | page.selectedPerkIds[0] = perksMap[keystones[2]]; 107 | page.selectedPerkIds[1] = perksMap[keystones[4]]; 108 | page.selectedPerkIds[2] = perksMap[keystones[6]]; 109 | page.selectedPerkIds[3] = perksMap[keystones[7]]; 110 | page.selectedPerkIds[4] = perksMap[keystones[3]]; 111 | page.selectedPerkIds[5] = perksMap[keystones[5]]; 112 | 113 | return page; 114 | } 115 | 116 | function fillUrl(urlToReplace, gamemode, page, champion, role) { 117 | return urlToReplace.replace("{gamemode}", gamemode).replace("{page}", page).replace("{champion}", champion).replace("{role}", role) 118 | } 119 | 120 | function _getPages(champion, callback) { 121 | var res = {pages: {}}; 122 | 123 | //getting main page 124 | console.log("getting main page for " + champion); 125 | var pages = []; 126 | request(fillUrl(url, gamemodeRanked, modeWin, champion, ""), function(error, response, html) { 127 | if(!error && response.statusCode == 200) { 128 | //adding ARAM pages 129 | pages.push({page: fillUrl(url, gamemodeAram, modeWin, champion, ""), name: "ARAM - HW"}); 130 | pages.push({page: fillUrl(url, gamemodeAram, modePick, champion, ""), name: "ARAM - MP"}); 131 | 132 | var $ = cheerio.load(html); 133 | var lanes = []; 134 | $("a.lanefilter").not(".active").each(function() { lanes.push($(this).attr("href")); }); 135 | 136 | // if there are no separate roles 137 | if(lanes.length == 0) { 138 | pages.push({page: fillUrl(url, gamemodeRanked, modeWin, champion, "" ), name: "Normal - HW"}); 139 | pages.push({page: fillUrl(url, gamemodeRanked, modePick, champion, ""), name: "Normal - MP"}); 140 | } 141 | // we get the pages for the specific lanes 142 | else if (lanes.length > 1) { 143 | for (var i = 0; i < lanes.length; i++) { 144 | pages.push({page: baseUrl + lanes[i], name: "Normal - " + lanes[i].split("/").filter(String).slice(-1)[0] + " - HW"}); 145 | pages.push({page: baseUrl + lanes[i].replace("/" + modeWin + "/", "/" + modePick + "/"), name: "Normal - " + lanes[i].split("/").filter(String).slice(-1)[0] + " - MP"}); 146 | } 147 | } 148 | 149 | var count = pages.length; 150 | 151 | for(var i = 0; i < pages.length; i++) { 152 | console.log("getting " + pages[i].name); 153 | // we send our custom pagename with the request so we can distuingish between pages in the response 154 | request({ url: pages[i].page, headers: {"X-PageName": pages[i].name}}, function(error, response, html) { 155 | if(!error && response.statusCode == 200) { 156 | var page = extractPage(html, response.request.headers["X-PageName"], response.request.uri.href); 157 | 158 | res.pages[page.name] = page; 159 | console.log("extracted " + page.name); 160 | count--; 161 | if(count == 0) { 162 | ordered = {}; 163 | //we sort it back 164 | Object.keys(res.pages).sort().forEach(function(key) { 165 | ordered[key] = res.pages[key]; 166 | }); 167 | 168 | res.pages = ordered; 169 | 170 | callback(res); 171 | } 172 | } 173 | }); 174 | } 175 | } 176 | else { 177 | callback(res); 178 | throw Error("failed to load main page for " + champion); 179 | } 180 | }); 181 | } 182 | 183 | var plugin = { 184 | id: "runeslol", 185 | name: "Runes LoL", 186 | active: true, 187 | bookmarks: true, 188 | 189 | getPages(champion, callback) { 190 | _getPages(champion, callback); 191 | }, 192 | 193 | syncBookmark(bookmark, callback) { 194 | request(bookmark.src, function(error, response, html) { 195 | if(!error && response.statusCode == 200) { 196 | callback(extractPage(html, bookmark.pName, bookmark.src)); 197 | } 198 | else { 199 | console.log(bookmark); 200 | throw Error("unable to sync " + bookmark.src); 201 | } 202 | }); 203 | } 204 | } 205 | 206 | module.exports = { plugin }; 207 | -------------------------------------------------------------------------------- /plugins/ugg.js: -------------------------------------------------------------------------------- 1 | const { map } = require('lodash'); 2 | const { getJson, sortRunes } = require('./utils'); 3 | 4 | // U.GG API consts 5 | // data[servers][tiers][positions][0][stats][perks/shards] 6 | const u = { 7 | positions: { 8 | jungle: 1, 9 | support: 2, 10 | adc: 3, 11 | top: 4, 12 | mid: 5 13 | }, 14 | positionsReversed: { 15 | 1: 'Jungle', 16 | 2: 'Support', 17 | 3: 'ADC', 18 | 4: 'Top', 19 | 5: 'Mid' 20 | }, 21 | tiers: { 22 | challenger: 1, 23 | master: 2, 24 | diamond: 3, 25 | platinum: 4, 26 | gold: 5, 27 | silver: 6, 28 | bronze: 7, 29 | overall: 8, 30 | platPlus: 10, 31 | diaPlus: 11 32 | }, 33 | servers: { 34 | na: 1, 35 | euw: 2, 36 | kr: 3, 37 | eune: 4, 38 | br: 5, 39 | las: 6, 40 | lan: 7, 41 | oce: 8, 42 | ru: 9, 43 | tr: 10, 44 | jp: 11, 45 | world: 12 46 | }, 47 | stats: { 48 | perks: 0, 49 | statShards: 8 50 | }, 51 | perks: { 52 | games: 0, 53 | won: 1, 54 | mainPerk: 2, 55 | subPerk: 3, 56 | perks: 4 57 | }, 58 | shards: { 59 | games: 0, 60 | won: 1, 61 | stats: 2 62 | } 63 | }; 64 | 65 | // KEY CONSTS - UPDATE THESE ACCORDING TO GUIDE https://gist.github.com/paolostyle/fe8ce06313d3e53c134a24762b9e519c 66 | const uGGDataVersion = '1.2'; 67 | const uGGAPIVersion = '1.1'; 68 | 69 | const riotVersionEndpoint = 'https://ddragon.leagueoflegends.com/api/versions.json'; 70 | const uGGDataVersionsEndpoint = 'https://u.gg/json/new_ugg_versions/' + uGGDataVersion + '.json'; 71 | 72 | const server = u.servers.world; 73 | const tier = u.tiers.platPlus; 74 | 75 | const getUGGFormattedLolVersion = lolVer => 76 | lolVer 77 | .split('.') 78 | .splice(0, 2) 79 | .join('_'); 80 | 81 | function extractPage(champion) { 82 | return (item, key) => { 83 | const perksData = item[0][u.stats.perks]; 84 | const statShards = item[0][u.stats.statShards][u.shards.stats].map(str => parseInt(str, 10)); 85 | 86 | const primaryStyleId = perksData[u.perks.mainPerk]; 87 | const subStyleId = perksData[u.perks.subPerk]; 88 | 89 | const selectedPerkIds = sortRunes(perksData[u.perks.perks], primaryStyleId, subStyleId).concat( 90 | statShards 91 | ); 92 | 93 | return { 94 | name: `${champion} ${u.positionsReversed[key]}`, 95 | primaryStyleId, 96 | subStyleId, 97 | selectedPerkIds, 98 | games: perksData[u.perks.games], 99 | bookmark: { 100 | src: '', 101 | meta: { 102 | pageType: key, 103 | champion 104 | }, 105 | remote: { 106 | name: 'U.GG', 107 | id: 'ugg' 108 | } 109 | } 110 | }; 111 | }; 112 | } 113 | 114 | async function getDataSource(champion) { 115 | try { 116 | const lolVersions = await getJson(riotVersionEndpoint); 117 | 118 | let lolVersion = lolVersions[0]; 119 | let lolVersionUGG = getUGGFormattedLolVersion(lolVersion); 120 | 121 | const overviewVersion = "1.2.6"; 122 | 123 | const championDataUrl = `https://static.u.gg/assets/lol/riot_static/${lolVersion}/data/en_US/champion/${champion}.json`; 124 | 125 | const championData = await getJson(championDataUrl); 126 | const championId = championData.data[champion].key; 127 | 128 | const championStatsUrl = `https://stats2.u.gg/lol/${uGGAPIVersion}/overview/${lolVersionUGG}/ranked_solo_5x5/${championId}/${overviewVersion}.json`; 129 | 130 | return getJson(championStatsUrl); 131 | } catch (e) { 132 | throw Error(e); 133 | } 134 | } 135 | 136 | async function updateBookmark(champion, pageId, callback) { 137 | try { 138 | const championStats = await getDataSource(champion); 139 | const page = extractPage(champion)(championStats[server][tier][pageId], pageId); 140 | delete page.games; 141 | callback(page); 142 | } catch (e) { 143 | callback({}); 144 | throw Error(e); 145 | } 146 | } 147 | 148 | async function _getPages(champion, callback) { 149 | const runePages = { pages: {} }; 150 | 151 | try { 152 | const championStats = await getDataSource(champion); 153 | 154 | let pages = map(championStats[server][tier], extractPage(champion)); 155 | let totalGames = pages.reduce((total, current) => (total += current.games), 0); 156 | 157 | pages = pages.filter(page => { 158 | const positionPercentage = page.games / totalGames; 159 | delete page.games; 160 | return positionPercentage > 0.1; 161 | }); 162 | 163 | pages.forEach(page => { 164 | runePages.pages[page.name] = page; 165 | }); 166 | 167 | callback(runePages); 168 | } catch (e) { 169 | callback(runePages); 170 | throw Error(e); 171 | } 172 | } 173 | 174 | const plugin = { 175 | id: 'ugg', 176 | name: 'U.GG', 177 | active: true, 178 | bookmarks: true, 179 | getPages(champion, callback) { 180 | _getPages(champion, callback); 181 | }, 182 | syncBookmark(bookmark, callback) { 183 | updateBookmark(bookmark.meta.champion, bookmark.meta.pageType, callback); 184 | } 185 | }; 186 | 187 | module.exports = { plugin }; 188 | -------------------------------------------------------------------------------- /plugins/utils.js: -------------------------------------------------------------------------------- 1 | const rp = require('request-promise-native'); 2 | const { groupBy } = require('lodash'); 3 | 4 | function getJson(uri) { 5 | return rp({ uri, json: true }); 6 | } 7 | 8 | // http://ddragon.leagueoflegends.com/cdn/8.23.1/data/en_US/runesReforged.json 9 | // tree = runes.reduce((obj, curr) => { 10 | // obj[curr.id] = [].concat(...curr.slots.map(row => row.runes.map(i => i.id))); 11 | // return obj; 12 | // }, {}) 13 | function sortRunes(runes, primaryStyle, subStyle) { 14 | const indexes = new Map(); 15 | const sortingFunc = (a, b) => indexes.get(a) - indexes.get(b); 16 | 17 | const tree = { 18 | 8000: [8005, 8008, 8021, 8010, 9101, 9111, 8009, 9104, 9105, 9103, 8014, 8017, 8299], 19 | 8100: [8112, 8124, 8128, 9923, 8126, 8139, 8143, 8136, 8120, 8138, 8135, 8134, 8105, 8106], 20 | 8200: [8214, 8229, 8230, 8224, 8226, 8275, 8210, 8234, 8233, 8237, 8232, 8236], 21 | 8300: [8351, 8359, 8360, 8306, 8304, 8313, 8321, 8316, 8345, 8347, 8410, 8352], 22 | 8400: [8437, 8439, 8465, 8446, 8463, 8401, 8429, 8444, 8473, 8451, 8453, 8242] 23 | }; 24 | const styles = Object.keys(tree); 25 | 26 | const groupedRunes = groupBy(runes, rune => { 27 | for (style of styles) { 28 | let runeIndex = tree[style].indexOf(rune); 29 | if (runeIndex !== -1) { 30 | indexes.set(rune, runeIndex); 31 | return style; 32 | } 33 | } 34 | }); 35 | 36 | groupedRunes[primaryStyle].sort(sortingFunc); 37 | groupedRunes[subStyle].sort(sortingFunc); 38 | 39 | return groupedRunes[primaryStyle].concat(groupedRunes[subStyle]); 40 | } 41 | 42 | module.exports = { getJson, sortRunes }; 43 | -------------------------------------------------------------------------------- /splashscreen.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 17 | 18 | 19 | 20 | Logo 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/app.js: -------------------------------------------------------------------------------- 1 | var settings = require('./settings'); 2 | var freezer = require('./state'); 3 | 4 | freezer.get().configfile.set({ 5 | name: settings.get("config.name") + settings.get("config.ext"), 6 | cwd: settings.get("config.cwd"), 7 | leaguepath: settings.get("leaguepath"), 8 | pathdiscovery: settings.get("pathdiscovery"), 9 | darktheme: settings.get("darktheme"), 10 | lang: settings.get("lang") 11 | }); 12 | 13 | freezer.get().set("autochamp", settings.get("autochamp")); 14 | freezer.get().tab.set({ active: settings.get("lasttab"), loaded: true }); 15 | 16 | var request = require('request'); 17 | 18 | var {ipcRenderer} = require('electron'); 19 | ipcRenderer.on('update:ready', (event, arg) => { 20 | console.log("github new latest found") 21 | freezer.get().set("updateready", true); 22 | }); 23 | ipcRenderer.on('update:downloaded', (event, arg) => { 24 | console.log("update downloaded") 25 | freezer.emit("update:downloaded"); 26 | }); 27 | 28 | var path = require('path'); 29 | 30 | freezer.on("configfile:change", (newPath) => { 31 | 32 | settings.set({ 33 | config: { 34 | name: path.basename(newPath, path.extname(newPath)), 35 | cwd: path.dirname(newPath), 36 | ext: path.extname(newPath) 37 | } 38 | }); 39 | }); 40 | 41 | freezer.on("pathdiscovery:switch", (val) => { 42 | freezer.get().configfile.set("pathdiscovery", val); 43 | settings.set("pathdiscovery", val); 44 | }); 45 | 46 | freezer.on("darktheme:switch", (val) => { 47 | freezer.get().configfile.set("darktheme", val); 48 | settings.set("darktheme", val); 49 | }); 50 | 51 | freezer.on("lang:update", (val) => { 52 | freezer.get().configfile.set("lang", val); 53 | settings.set("lang", val); 54 | }); 55 | 56 | freezer.on("leaguepath:change", (leaguepath) => { 57 | leaguepath = path.join(path.dirname(path.normalize(leaguepath)), (process.platform == 'darwin' ? 'LeagueClient.app' : 'LeagueClient.exe')); 58 | freezer.get().configfile.set("leaguepath", leaguepath); 59 | settings.set("leaguepath", leaguepath); 60 | }); 61 | 62 | freezer.on("update:do", () => { 63 | ipcRenderer.send('update:do'); 64 | }); 65 | 66 | freezer.on("content:reload", () => { 67 | ipcRenderer.send('content:reload'); 68 | }) 69 | 70 | freezer.on("changelog:ready", () => { 71 | var appVersion = require('electron').remote.app.getVersion(); 72 | console.log(appVersion, settings.get("changelogversion")) 73 | if(settings.get("changelogversion") != appVersion) { 74 | // freezer.get().set("showchangelog", true); 75 | settings.set("changelogversion", appVersion); 76 | } 77 | }); 78 | 79 | request('https://ddragon.leagueoflegends.com/realms/euw.json', function (error, response, data) { 80 | if(!error && response && response.statusCode == 200) { 81 | freezer.emit("version:set", JSON.parse(data)["v"]); 82 | } 83 | else throw Error("Couldn't get ddragon api version"); 84 | }); 85 | 86 | freezer.on('version:set', (ver) => { 87 | request('http://ddragon.leagueoflegends.com/cdn/'+ver+'/data/en_US/champion.json', function(error, response, data) { 88 | if(!error && response && response.statusCode == 200){ 89 | freezer.get().set('championsinfo', JSON.parse(data).data); 90 | freezer.emit("championsinfo:set"); 91 | } 92 | }); 93 | }); 94 | 95 | freezer.on('api:connected', () => { 96 | api.get("/lol-summoner/v1/current-summoner").then((res) => { 97 | updateConnectionData(); 98 | if(!res) { 99 | console.log("no session response"); 100 | return; 101 | } 102 | console.log("session success", res); 103 | freezer.get().session.set({ connected: res.connected, state: res.state }); 104 | }); 105 | }); 106 | 107 | var plugins = require('../plugins'); 108 | console.log("plugins", plugins); 109 | function loadPlugins() { 110 | var remote = {}, local = {}; 111 | Object.keys(plugins).forEach((key) => { 112 | if(plugins[key].local === true) local[key] = {name: plugins[key].name}; 113 | else remote[key] = { 114 | name: plugins[key].name, 115 | bookmarks: plugins[key].bookmarks || false, 116 | cache: {} 117 | }; 118 | }); 119 | freezer.get().plugins.set({ local, remote }); 120 | } 121 | loadPlugins(); 122 | 123 | freezer.on('champion:choose', (champion) => { 124 | 125 | var state = freezer.get(); 126 | 127 | var plugin = state.tab.active; 128 | 129 | // Check if champion is already been cached before asking the remote plugin 130 | if(state.plugins.remote[plugin] && state.plugins.remote[plugin].cache[champion]) { 131 | freezer.get().current.set({ champion, champ_data: state.plugins.remote[plugin].cache[champion] || {pages: {}} }); 132 | console.log("CACHE HIT!"); 133 | return; 134 | } 135 | 136 | freezer.get().tab.set({ active: freezer.get().tab.active, loaded: false }); 137 | freezer.get().current.set({ champion }); // update champ portrait before the data response 138 | 139 | state = freezer.get(); 140 | 141 | plugins[state.tab.active].getPages(champion, (res) => { 142 | if(freezer.get().tab.active != state.tab.active) return; 143 | freezer.get().current.set({ champion, champ_data: res || {pages: {}} }); 144 | freezer.get().tab.set({ loaded: true }); 145 | 146 | // Cache results obtained from a remote source 147 | if(freezer.get().plugins.remote[plugin]) 148 | freezer.get().plugins.remote[plugin].cache.set(champion, res); 149 | }); 150 | }); 151 | 152 | freezer.on("tab:switch", (tab) => { 153 | freezer.get().tab.set({ active: tab, loaded: true }); 154 | settings.set("lasttab", tab); 155 | 156 | 157 | var state = freezer.get(); 158 | 159 | var plugin = state.tab.active; 160 | var champion = freezer.get().current.champion; 161 | 162 | // Check if champion is already been cached before asking the remote plugin 163 | if(state.plugins.remote[plugin] && state.plugins.remote[plugin].cache[champion]) { 164 | freezer.get().current.set({ champion, champ_data: state.plugins.remote[plugin].cache[champion] || {pages: {}} }); 165 | console.log("CACHE HIT!"); 166 | return; 167 | } 168 | 169 | freezer.get().tab.set({ active: tab, loaded: tab == "local" || !freezer.get().current.champion }); 170 | 171 | state = freezer.get(); 172 | 173 | if(!state.current.champion) return; 174 | plugins[state.tab.active].getPages(state.current.champion, (res) => { 175 | if(freezer.get().tab.active != state.tab.active) return; 176 | freezer.get().current.set({ champion: freezer.get().current.champion, champ_data: res || {pages: {}} }); 177 | freezer.get().tab.set({ loaded: true }); 178 | 179 | // Cache results obtained from a remote source 180 | if(freezer.get().plugins.remote[plugin]) 181 | freezer.get().plugins.remote[plugin].cache.set(champion, res); 182 | }); 183 | }); 184 | 185 | freezer.on('page:fav', (champion, page) => { 186 | var state = freezer.get(); 187 | plugins[state.tab.active].favPage(champion, page); 188 | plugins[state.tab.active].getPages(champion, (res) => { 189 | state.current.champ_data.set(res); 190 | }); 191 | }); 192 | 193 | freezer.on('page:delete', (champion, page) => { 194 | var state = freezer.get(); 195 | plugins[state.tab.active].deletePage(champion, page); 196 | plugins[state.tab.active].getPages(champion, (res) => { 197 | state.current.champ_data.set(res); 198 | }); 199 | }); 200 | 201 | freezer.on('page:unlinkbookmark', (champion, page) => { 202 | if(freezer.get().lastbookmarkedpage.champion == champion && freezer.get().lastbookmarkedpage.page == page) 203 | freezer.get().lastbookmarkedpage.set({page: null, champion: null}); 204 | var state = freezer.get(); 205 | plugins[state.tab.active].unlinkBookmark(champion, page); 206 | plugins[state.tab.active].getPages(champion, (res) => { 207 | state.current.champ_data.set(res); 208 | }); 209 | }); 210 | 211 | freezer.on('page:bookmark', (champion, pagename) => { 212 | var state = freezer.get(); 213 | 214 | page = state.current.champ_data.pages[pagename]; 215 | console.log(page) 216 | 217 | plugins["local"].setPage(champion, page); 218 | freezer.get().lastbookmarkedpage.set({ champion, page: pagename }); 219 | freezer.get().lastsyncedpage.set({ champion: null, page: null, loading: false }); 220 | }); 221 | 222 | freezer.on('page:syncbookmark', (champion, page) => { 223 | freezer.get().lastsyncedpage.set({champion, page, loading: true}); 224 | 225 | var state = freezer.get(); 226 | 227 | page = state.current.champ_data.pages[page]; 228 | console.log(page) 229 | 230 | plugins[page.bookmark.remote.id].syncBookmark(page.bookmark, (_page) => { 231 | if(!_page) { 232 | freezer.get().lastsyncedpage.set({champion: null, page: null, loading: false}); 233 | return; 234 | } 235 | plugins[state.tab.active].setPage(champion, _page); 236 | plugins[state.tab.active].getPages(champion, (res) => { 237 | state.current.champ_data.set(res); 238 | freezer.get().lastsyncedpage.set({champion, page: _page.name, loading: false}); 239 | }); 240 | }); 241 | }); 242 | 243 | freezer.on('page:upload', (champion, page) => { 244 | var state = freezer.get(); 245 | console.log("DEV page", page); 246 | console.log("DEV page data", state.current.champ_data.pages[page]); 247 | console.log("DEV state pages", state.current.champ_data.pages); 248 | page_data = state.current.champ_data.pages[page]; 249 | page_data.name = page; 250 | page_data.current = true; 251 | 252 | console.log("page.id, page.isEditable", state.connection.page.id, state.connection.page.isEditable); 253 | if(state.connection.page.id && state.connection.page.isEditable && state.connection.summonerLevel >= 10) { 254 | freezer.off('/lol-perks/v1/currentpage:Update'); 255 | freezer.get().lastuploadedpage.set({ champion, page, loading: true }); 256 | api.del("/lol-perks/v1/pages/" + freezer.get().connection.page.id).then((res) => { 257 | console.log("api delete current page", res); 258 | 259 | // stat shards check 260 | page_data = freezer.get().current.champ_data.pages[page].toJS(); 261 | if(!page_data.selectedPerkIds[6] && !page_data.selectedPerkIds[7] && !page_data.selectedPerkIds[8]) { 262 | page_data.selectedPerkIds = page_data.selectedPerkIds.concat([5008, 5002, 5003]); 263 | } 264 | 265 | api.post("/lol-perks/v1/pages/", page_data).then((res) => { 266 | if(!res) { 267 | console.log("Error: no response after page upload request."); 268 | api.get("/lol-perks/v1/currentpage").then((res) => { 269 | handleCurrentPageUpdate(res); 270 | freezer.on('/lol-perks/v1/currentpage:Update', handleCurrentPageUpdate); 271 | }); 272 | return; 273 | } 274 | console.log("post res", res); 275 | api.get("/lol-perks/v1/currentpage").then((res) => { 276 | handleCurrentPageUpdate(res); 277 | freezer.on('/lol-perks/v1/currentpage:Update', handleCurrentPageUpdate); 278 | }); 279 | freezer.on('/lol-perks/v1/currentpage:Update', handleCurrentPageUpdate); 280 | freezer.get().lastuploadedpage.set({ champion, page, valid: res.isValid === true, loading: false }); 281 | 282 | var state = freezer.get(); 283 | if(plugins[state.tab.active].local) { 284 | plugins[state.tab.active].confirmPageValidity(champion, page, res); 285 | plugins[state.tab.active].getPages(champion, (res) => { 286 | state.current.champ_data.set(res); 287 | }); 288 | } 289 | }); 290 | }); 291 | } 292 | }); 293 | 294 | freezer.on('currentpage:download', () => { 295 | var state = freezer.get(); 296 | 297 | var champion = state.current.champion; 298 | var page = state.connection.page; 299 | 300 | plugins[state.tab.active].setPage(champion, page); 301 | plugins[state.tab.active].getPages(champion, (res) => { 302 | state.current.champ_data.set(res); 303 | }); 304 | }); 305 | 306 | freezer.on('/lol-summoner/v1/current-summoner:Update', (summoner) => { 307 | var state = freezer.get(); 308 | 309 | state.session.set({ connected: true, state: null }); 310 | if(!summoner.summonerLevel) { 311 | freezer.get().connection.set({ page: null, summonerLevel: 0 }); 312 | } 313 | else { 314 | updateConnectionData(); 315 | } 316 | }) 317 | 318 | function handleCurrentPageUpdate(page) { 319 | var state = freezer.get(); 320 | 321 | console.log("currentpage:Update", page.name); 322 | state.connection.set({ page }); 323 | if(page.name != freezer.get().lastuploadedpage.page) freezer.get().lastuploadedpage.set({ champion: null, page: null, valid: false }); 324 | } 325 | 326 | function updateConnectionData() { 327 | api.get("/lol-perks/v1/currentpage").then((page) => { 328 | if(!page) { 329 | console.log("Error: current page initialization failed"); 330 | return; 331 | } 332 | freezer.get().connection.set({ page }); 333 | freezer.get().lastuploadedpage.set({ champion: null, page: null, valid: false }); 334 | }); 335 | 336 | api.get("/lol-summoner/v1/current-summoner").then((summoner) => { 337 | if(!summoner) { 338 | console.log("no summoner response"); 339 | return; 340 | } 341 | freezer.get().connection.set("summonerLevel", summoner.summonerLevel); 342 | }); 343 | 344 | api.get("/lol-perks/v1/perks").then((data) => { 345 | if(!data) return; 346 | freezer.get().tooltips.set("rune", data); 347 | }); 348 | } 349 | 350 | freezer.on('/lol-perks/v1/perks:Update', (data) => { 351 | if(!data) return; 352 | freezer.get().tooltips.set("rune", data); 353 | }); 354 | 355 | freezer.on('/lol-perks/v1/currentpage:Update', handleCurrentPageUpdate); 356 | 357 | freezer.on('/lol-champ-select/v1/session:Delete', () => { 358 | freezer.get().set("champselect", false); 359 | }); 360 | 361 | freezer.on('/lol-champ-select/v1/session:Update', (data) => { 362 | console.log(data); 363 | var action = data.myTeam.find((el) => data.localPlayerCellId === el.cellId); 364 | if(!action) return; 365 | if(data.timer.phase !== "FINALIZATION") freezer.get().set("champselect", true); 366 | else freezer.get().set("champselect", false); 367 | if(freezer.get().autochamp === false) return; 368 | var champions = freezer.get().championsinfo; 369 | var champion = Object.keys(champions).find((el) => champions[el].key == action.championId); 370 | console.log(champion) 371 | // if(champion !== freezer.get().current.champion) freezer.get().tab.set("active", "local"); // Avoid request spamming 372 | freezer.emit('champion:choose', champion); 373 | }); 374 | 375 | freezer.on("autochamp:enable", () => { 376 | freezer.get().set("autochamp", true); 377 | settings.set("autochamp", true); 378 | 379 | // Check if a champ was already selected in client 380 | api.get("/lol-champ-select/v1/session").then((data) => { 381 | console.log(data) 382 | if(!data) return; 383 | var action = data.myTeam.find((el) => data.localPlayerCellId === el.cellId); 384 | if(!action) return; 385 | if(data.timer.phase !== "FINALIZATION") freezer.get().set("champselect", true); 386 | var champions = freezer.get().championsinfo; 387 | var champion = Object.keys(champions).find((el) => champions[el].key == action.championId); 388 | console.log(champion) 389 | // if(champion !== freezer.get().current.champion) freezer.get().tab.set("active", "local"); // Avoid request spamming 390 | freezer.emit('champion:choose', champion); 391 | }); 392 | }); 393 | 394 | freezer.on("autochamp:disable", () => { 395 | freezer.get().set("autochamp", false); 396 | settings.set("autochamp", false); 397 | }); 398 | 399 | var shell = require('electron').shell; 400 | //open links externally by default 401 | $(document).on('click', 'a[href^="http"]', function(event) { 402 | event.preventDefault(); 403 | shell.openExternal(this.href); 404 | }); 405 | 406 | const LCUConnector = require('lcu-connector'); 407 | console.log("config leaguepath", freezer.get().configfile.leaguepath) 408 | console.log("config pathdiscovery", freezer.get().configfile.pathdiscovery) 409 | const connector = new LCUConnector(freezer.get().configfile.pathdiscovery ? undefined : freezer.get().configfile.leaguepath); 410 | const api = require('./lcu-api'); 411 | 412 | connector.on('connect', (data) => { 413 | console.log("client found"); 414 | api.bind(data); 415 | }); 416 | 417 | connector.on('disconnect', () => { 418 | console.log("client closed"); 419 | api.destroy(); 420 | freezer.get().session.set({ connected: false, state: "" }); 421 | freezer.get().set("champselect", false); 422 | }); 423 | 424 | // Start listening for the LCU client 425 | connector.start(); -------------------------------------------------------------------------------- /src/lcu-api.js: -------------------------------------------------------------------------------- 1 | const WebSocket = require('ws'); 2 | const request = require('request'); 3 | 4 | var ws = null; 5 | var conn_data = null; 6 | 7 | function bind(data) { 8 | conn_data = data; 9 | ws = new WebSocket(`wss://${data.username}:${data.password}@${data.address}:${data.port}/`, "wamp", { 10 | rejectUnauthorized: false, 11 | }); 12 | 13 | ws.on('error', (err) => { 14 | console.log(err); 15 | if (err.message.includes('ECONNREFUSED')) { 16 | destroy(); 17 | setTimeout(function () { 18 | bind(data); 19 | }, 1000); 20 | } 21 | }); 22 | 23 | ws.on('message', (msg) => { 24 | var res; 25 | try { 26 | res = JSON.parse(msg); 27 | } catch(e) { 28 | console.log(e); 29 | } 30 | if(res[0] === 0) { 31 | console.log("connected", res); 32 | freezer.emit(`api:connected`); 33 | } 34 | if(res[1] == "OnJsonApiEvent") { 35 | var evt = res[2]; 36 | //console.log(`${evt.uri}:${evt.eventType}`); 37 | freezer.emit(`${evt.uri}:${evt.eventType}`, evt.data); 38 | } 39 | }); 40 | 41 | ws.on('open', () => { 42 | ws.send('[5, "OnJsonApiEvent"]'); 43 | }); 44 | } 45 | 46 | function destroy() { 47 | ws.removeEventListener() 48 | ws = null; 49 | } 50 | 51 | var methods = {}; 52 | ["post", "put", "get", "del"].forEach(function(method) { 53 | methods[method] = function(endpoint, body) { 54 | return new Promise(resolve => { 55 | var options = { 56 | url: `${conn_data.protocol}://${conn_data.address}:${conn_data.port}${endpoint}`, 57 | auth: { 58 | "user": conn_data.username, 59 | "pass": conn_data.password 60 | }, 61 | headers: { 62 | 'Accept': 'application/json' 63 | }, 64 | json: true, 65 | body: body, 66 | rejectUnauthorized: false 67 | }; 68 | 69 | request[method](options, (error, response, data) => { 70 | if (error || response.statusCode != 200) { 71 | resolve(); 72 | return; 73 | } 74 | 75 | resolve(data); 76 | }); 77 | }); 78 | }; 79 | }); 80 | 81 | module.exports = Object.assign({bind, destroy}, methods); -------------------------------------------------------------------------------- /src/locales.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const glob = require('glob'); 3 | let dictionary = {} 4 | glob.sync(__dirname + '/locales/*.json').forEach(function(filepath) { 5 | let lang = path.basename(filepath, '.json'); 6 | dictionary[lang] = require(filepath); 7 | }); 8 | module.exports = dictionary; -------------------------------------------------------------------------------- /src/locales/cz.json: -------------------------------------------------------------------------------- 1 | { 2 | "settings.title": "Nastavení", 3 | "settings.client_path": "LeagueClient instalační cesta", 4 | "champion.name": "Jméno šampióna", 5 | "champion.autopick.tooltip": "Když jste ve výběru šampiónů, automaticky vybere v RuneBooku váš výběr.", 6 | "champion.autopick": "Automatický výběr", 7 | "settings.pathdiscovery.help": "Automatická detekce je aktivní. Prosím vypněte ji pokuď chcete manuálně nastavit cestu.", 8 | "settings.pathdiscovery": "Automaticky detekuje instalační cestu (doporučené)", 9 | "settings.restart.warning": "Restartuje RuneBook k provedení změn", 10 | "settings.updates": "Aktualizace", 11 | "settings.newversion": "Nová aktualizace k dispozici!", 12 | "settings.downloadupdate": "Stáhnout aktualizaci", 13 | "settings.uptodate": "RuneBook je aktuální.", 14 | "settings.advanced": "Pokročilé", 15 | "settings.localrunefile": "Lokální soubor runových stránek", 16 | "settings.choosefile": "Vyberte .json soubor", 17 | "settings.lang": "Jazyky", 18 | "chapters.title": "Stránky", 19 | "chapters.welcome": "Vítejte v RuneBooku!", 20 | "chapters.localpages": "Lokální stránky", 21 | "chapters.startmessage": "Vyberte šampióna abyste začali spravovat runové stránky.", 22 | "whatsnew.title": "Co je nového v ", 23 | "connectionstatus.inprogress": "Přihlašování", 24 | "connectionstatus.loggingout": "Odhlašování", 25 | "currentpage.title": "Současná stránka", 26 | "currentpage.unavailable": "Součásná stránka není k dispozici.", 27 | "currentpage.unavailable.subheader1": "Prosím přihlašte se do League clienta pro získání přístupu k runovým stránkám.", 28 | "currentpage.unavailable.subheader2": "Pokud chyba přetrvává, jděte do nastavení a manuálně nastavte vaši LeagueClient instalační cestu.", 29 | "currentpage.downloadcurrentpage": "Importovat tuhle stránku jako lokální", 30 | "pagelist.uploadpage": "Nahrát tuto stránku do klienta", 31 | "pagelist.syncfrom": "Synchronizuje se z ", 32 | "pagelist.unlink": "Odebrat tuto stránku", 33 | "pagelist.bookmarkpage": "Označit tuto stránku jako lokální", 34 | "pagelist.emptylocalpage": "Nemáte žádné stránky pro tohodle šampióna.", 35 | "pagelist.emptylocalpage.subheader": "Click the button below to import from your current page.", 36 | "pagelist.emptyremotepage": "Nepovedlo se najít runy pro tohoto šampióna.", 37 | "pagelist.emptyremotepage.subheader": "Nebyly nalezeny stránky nebo je služba dočasně nedostupná.", 38 | "pagelist.confirmdialog": "Jste si jistý, že chcete odebrat tuto stránku?", 39 | "settings.experimental": "Experimentální", 40 | "settings.darktheme": "Tmavý vzhled", 41 | "currentpage.retry": "Retry" 42 | } -------------------------------------------------------------------------------- /src/locales/de.json: -------------------------------------------------------------------------------- 1 | { 2 | "settings.title": "Einstellungen", 3 | "settings.client_path": "LeagueClient Installationspfad", 4 | "champion.name": "Champion Name", 5 | "champion.autopick.tooltip": "Während Champion Select kann Runebook automatisch den ausgewählten Champion erkennen und die passenden Runen auswählen.", 6 | "champion.autopick": "Autom. Auswahl", 7 | "settings.pathdiscovery.help": "Automatische Erkennung ist aktiv. Deaktivieren Sie diese Option, um einen benutzerdefinierten Pfad anzugeben.", 8 | "settings.pathdiscovery": "Installationspfad automatisch erkennen (empfohlen)", 9 | "settings.restart.warning": "Starten Sie Runebook von neu, um die Änderungen anzuwenden.", 10 | "settings.updates": "Updates", 11 | "settings.newversion": "Neue Version verfügbar!", 12 | "settings.downloadupdate": "Lade Update herunter", 13 | "settings.uptodate": "RuneBook ist aktuell.", 14 | "settings.advanced": "Erweiterte Optionen", 15 | "settings.localrunefile": "Ort der lokalen Runenseitendatei", 16 | "settings.choosefile": "Wähle eine .json Datei aus", 17 | "settings.lang": "Sprache", 18 | "chapters.title": "Kapitel", 19 | "chapters.welcome": "Willkommen zu RuneBook!", 20 | "chapters.localpages": "Lokale Seiten", 21 | "chapters.startmessage": "Um Ihre Runenseiten zu verwalten, wählen Sie zuerst einen Champion.", 22 | "whatsnew.title": "Neues in ", 23 | "connectionstatus.inprogress": "Logge ein", 24 | "connectionstatus.loggingout": "Logge aus", 25 | "currentpage.title": "Derzeitige Seite", 26 | "currentpage.unavailable": "Derzeitige Seite ist nicht verfügbar.", 27 | "currentpage.unavailable.subheader1": "Bitte loggen Sie sich im League Client an, um auf Ihre Runenseiten zugreifen zu können.", 28 | "currentpage.unavailable.subheader2": "Falls dieser Fehler bestehen sollte, wählen Sie manuell den Pfad zum Client in den Einstellungen aus.", 29 | "currentpage.downloadcurrentpage": "Lade Seite herunter", 30 | "pagelist.uploadpage": "Lade Seite zum Client hoch", 31 | "pagelist.syncfrom": "Synchronisiere von ", 32 | "pagelist.unlink": "Trenne diese Seite", 33 | "pagelist.bookmarkpage": "Markiere diese Seite lokal", 34 | "pagelist.emptylocalpage": "Keine Runenseite für diesen Champion vorhanden!", 35 | "pagelist.emptylocalpage.subheader": "Klicken Sie auf den unteren Button, um Ihre aktuelle Seite zu speichern.", 36 | "pagelist.emptyremotepage": "Runenseiten für diesen Champion konnten nicht gefunden werden!", 37 | "pagelist.emptyremotepage.subheader": "Entweder sind keine Runenseiten vorhanden oder der Service ist derzeit nicht verfügbar.", 38 | "pagelist.confirmdialog": "Are you sure you want to delete this page?", 39 | "settings.experimental": "Experimental", 40 | "settings.darktheme": "Dark theme", 41 | "currentpage.retry": "Retry" 42 | } 43 | -------------------------------------------------------------------------------- /src/locales/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "settings.title": "Settings", 3 | "settings.client_path": "LeagueClient installation path", 4 | "champion.name": "Champion name", 5 | "champion.autopick.tooltip": "When you're in champion select, automatically update RuneBook with your champion pick.", 6 | "champion.autopick": "Auto select", 7 | "settings.pathdiscovery.help": "Automatic detection is active. Please disable it if you want to manually set a custom path.", 8 | "settings.pathdiscovery": "Automatically detect installation path (recommended)", 9 | "settings.restart.warning": "Restart RuneBook to apply this change", 10 | "settings.updates": "Updates", 11 | "settings.newversion": "New version available!", 12 | "settings.downloadupdate": "Download update", 13 | "settings.uptodate": "RuneBook is up to date.", 14 | "settings.advanced": "Advanced", 15 | "settings.localrunefile": "Local rune pages file", 16 | "settings.choosefile": "Choose .json file", 17 | "settings.lang": "Language", 18 | "chapters.title": "Chapters", 19 | "chapters.welcome": "Welcome to RuneBook!", 20 | "chapters.localpages": "Local pages", 21 | "chapters.startmessage": "Select a champion to start managing your rune pages.", 22 | "whatsnew.title": "What's new in ", 23 | "connectionstatus.inprogress": "Logging in", 24 | "connectionstatus.loggingout": "Logging out", 25 | "currentpage.title": "Current page", 26 | "currentpage.unavailable": "Current page is not available.", 27 | "currentpage.unavailable.subheader1": "Please log in to the League client to access your rune pages.", 28 | "currentpage.unavailable.subheader2": "If the error persists, go to Settings and manually set your LeagueClient installation path.", 29 | "currentpage.downloadcurrentpage": "Import this page as local", 30 | "pagelist.uploadpage": "Upload this page to the client", 31 | "pagelist.syncfrom": "Sync from ", 32 | "pagelist.unlink": "Unlink this page", 33 | "pagelist.bookmarkpage": "Bookmark this page as local", 34 | "pagelist.emptylocalpage": "You don't seem to have any pages for this champion.", 35 | "pagelist.emptylocalpage.subheader": "Click the button below to import from your current page.", 36 | "pagelist.emptyremotepage": "Couldn't find rune pages for this champion.", 37 | "pagelist.emptyremotepage.subheader": "No pages found or service temporarily unavailable.", 38 | "pagelist.confirmdialog": "Are you sure you want to delete this page?", 39 | "settings.experimental": "Experimental", 40 | "settings.darktheme": "Dark theme", 41 | "currentpage.retry": "Retry" 42 | } -------------------------------------------------------------------------------- /src/locales/es.json: -------------------------------------------------------------------------------- 1 | { 2 | "settings.title": "Configuración", 3 | "settings.client_path": "Ruta de instalación de LeagueClient", 4 | "champion.name": "Campeón", 5 | "champion.autopick.tooltip": "Cuando estás en selección de campeón, actualiza automáticamente RuneBook con el campeón que has seleccionado.", 6 | "champion.autopick": "Selección auto.", 7 | "settings.pathdiscovery.help": "Detección automática está activa. Desactívala para establecer una ruta manualmente.", 8 | "settings.pathdiscovery": "Detección automática de ruta de instalación (recomendado)", 9 | "settings.restart.warning": "Debes reiniciar RuneBook para aplicar este cambio", 10 | "settings.updates": "Actualizaciones", 11 | "settings.newversion": "¡Nueva versión disponible!", 12 | "settings.downloadupdate": "Descargar actualización", 13 | "settings.uptodate": "RuneBook está actualizado.", 14 | "settings.advanced": "Avanzado", 15 | "settings.localrunefile": "Archivo local de página de runas", 16 | "settings.choosefile": "Escoja un archivo .json", 17 | "settings.lang": "Idioma", 18 | "chapters.title": "Secciones", 19 | "chapters.welcome": "¡Bienvenido a RuneBook!", 20 | "chapters.localpages": "Páginas locales", 21 | "chapters.startmessage": "Selecciona un campeón para empezar a administrar tus páginas de runas", 22 | "whatsnew.title": "Lo nuevo en ", 23 | "connectionstatus.inprogress": "Iniciando sesión", 24 | "connectionstatus.loggingout": "Cerrando sesión", 25 | "currentpage.title": "Página actual", 26 | "currentpage.unavailable": "La página actual no está disponible.", 27 | "currentpage.unavailable.subheader1": "Inicia sesión en League of Legends para acceder a tus páginas de runas.", 28 | "currentpage.unavailable.subheader2": "Si el problema persiste, ve a la configuración y establece tu la ruta del cliente manualmente.", 29 | "currentpage.downloadcurrentpage": "Descargar esta página como local", 30 | "pagelist.uploadpage": "Enviar esta página a League of Legends", 31 | "pagelist.syncfrom": "Sincronizar desde ", 32 | "pagelist.unlink": "Desmarcar esta página", 33 | "pagelist.bookmarkpage": "Marcar esta página como local", 34 | "pagelist.emptylocalpage": "Parece que no has guardado páginas para este campeón.", 35 | "pagelist.emptylocalpage.subheader": "Dando clic en el botón inferior, podrás importar tu página actual.", 36 | "pagelist.emptyremotepage": "No se encontraron páginas para este campeón.", 37 | "pagelist.emptyremotepage.subheader": "No existen páginas o el servicio no está disponible temporalmente.", 38 | "pagelist.confirmdialog": "Are you sure you want to delete this page?", 39 | "settings.experimental": "Experimental", 40 | "settings.darktheme": "Dark theme", 41 | "currentpage.retry": "Retry" 42 | } -------------------------------------------------------------------------------- /src/locales/fr.json: -------------------------------------------------------------------------------- 1 | { 2 | "settings.title": "paramètres", 3 | "settings.client_path": "Chemin d'installation du client", 4 | "champion.name": "Nom du champion", 5 | "champion.autopick.tooltip": "Lorsque vous êtes en sélection de champion, mettez automatiquement RuneBook à jour avec votre choix du champion.", 6 | "champion.autopick": "Sélection automatique", 7 | "settings.pathdiscovery.help": "la détection automatique est active. Veuillez la désactiver si vous souhaitez définir manuellement un chemin personnalisé.", 8 | "settings.pathdiscovery": "Détecter automatiquement le chemin d'installation (recommandé)", 9 | "settings.restart.warning": "Redémarrez RuneBook pour appliquer cette modification", 10 | "settings.updates": "Mises à jour", 11 | "settings.newversion": "Nouvelle version Disponible!", 12 | "settings.downloadupdate": "Télécharger la mise à jour", 13 | "settings.uptodate": "RuneBook est à jour.", 14 | "settings.advanced": "Avancés", 15 | "settings.localrunefile": "Fichier des pages de runes locales", 16 | "settings.choosefile": "Choisir le fichier .json", 17 | "settings.lang": "Langue", 18 | "chapters.title": "Chapitres", 19 | "chapters.welcome": "Bienvenue sur Runebook!", 20 | "chapters.localpages": "Pages Locales", 21 | "chapters.startmessage": "Sélectionnez un champion pour commencer à gérer vos pages de runes.", 22 | "whatsnew.title": "Quoi de neuf dans ", 23 | "connectionstatus.inprogress": "Se connecter", 24 | "connectionstatus.loggingout": "Déconnecter", 25 | "currentpage.title": "Page Actuelle", 26 | "currentpage.unavailable": "La Page actuelle n'est pas Disponible.", 27 | "currentpage.unavailable.subheader1": "Veuillez vous connecter au client pour accéder à vos pages de runes.", 28 | "currentpage.unavailable.subheader2": "Si l'erreur persiste, accédez aux Paramètres et définissez manuellement le chemin d'installation de votre Client.", 29 | "currentpage.downloadcurrentpage": "Importer cette page en local", 30 | "pagelist.uploadpage": "Télécharger cette page au client", 31 | "pagelist.syncfrom": "Synchroniser à partir de ", 32 | "pagelist.unlink": "Dissocier cette page", 33 | "pagelist.bookmarkpage": "Marquer cette page comme locale", 34 | "pagelist.emptylocalpage": "Vous n'avez aucune page pour ce champion", 35 | "pagelist.emptylocalpage.subheader": "Cliquer sur le bouton ci-dessous pour importer depuis votre page actuelle.", 36 | "pagelist.emptyremotepage": "Pages de runes introuvables pour ce Champion.", 37 | "pagelist.emptyremotepage.subheader": "Aucune page n'est trouvable ou service temporairement indisponible.", 38 | "pagelist.confirmdialog": "Êtes-vous sûr de vouloir supprimer cette page?", 39 | "settings.experimental": "Experimental", 40 | "settings.darktheme": "Dark theme", 41 | "currentpage.retry": "Retry" 42 | } -------------------------------------------------------------------------------- /src/locales/hu.json: -------------------------------------------------------------------------------- 1 | { 2 | "settings.title": "Beállítások", 3 | "settings.client_path": "A League kliens telepítési helye", 4 | "champion.name": "Hős neve", 5 | "champion.autopick.tooltip": "A RuneBook automatikusan megkeresi a hősválasztásban kiválasztott hőst.", 6 | "champion.autopick": "Automatikus kiválasztás", 7 | "settings.pathdiscovery.help": "Az automatikus felismerés aktív, kapcsold ki ha manuálisan szeretnéd beállítani a helyet.", 8 | "settings.pathdiscovery": "Telepítési hely automatikus felismerése(ajánlott)", 9 | "settings.restart.warning": "Indítsd újra a RuneBook-ot, hogy érvényesüljön a változtatás", 10 | "settings.updates": "Frissítések", 11 | "settings.newversion": "Új verzió elérhető!", 12 | "settings.downloadupdate": "Frissítés letöltése", 13 | "settings.uptodate": "A RuneBook naprakész.", 14 | "settings.advanced": "Haladó", 15 | "settings.localrunefile": "Helyi rúna oldalakat tartalmazó fájl", 16 | "settings.choosefile": ".json fájl kiválasztása", 17 | "settings.lang": "Nyelv", 18 | "chapters.title": "Fejezetek", 19 | "chapters.welcome": "Üdv a RuneBook-ban!", 20 | "chapters.localpages": "Helyi oldalak", 21 | "chapters.startmessage": "Válassz hőst, hogy elkezdhesd rendezni a rúna oldalaidat.", 22 | "whatsnew.title": "Újdonságok ebben a verzióban: ", 23 | "connectionstatus.inprogress": "Bejelentkezés", 24 | "connectionstatus.loggingout": "Kijelentkezés", 25 | "currentpage.title": "Jelenlegi oldal", 26 | "currentpage.unavailable": "A jelenlegi oldal nem elérhető.", 27 | "currentpage.unavailable.subheader1": "Jelentkezz be a League kliensbe, hogy hozzáférj a rúna oldalaidhoz.", 28 | "currentpage.unavailable.subheader2": "Ha a hiba fennáll, menj a beállításokba és válaszdd ki manuálisan a League kliens telepítési helyét.", 29 | "currentpage.downloadcurrentpage": "Mentsd el ezt az oldalt, mint helyi oldal", 30 | "pagelist.uploadpage": "Oldal feltöltése a kliensbe", 31 | "pagelist.syncfrom": "Szinkronizálás innen: ", 32 | "pagelist.unlink": "Oldal törlése", 33 | "pagelist.bookmarkpage": "Oldal mentése könyvjelzők közé", 34 | "pagelist.emptylocalpage": "Ehhez a hőshöz még nincs egy oldalad sem.", 35 | "pagelist.emptylocalpage.subheader": "Kattints a lentebbi gombra,hogy a jelenleg kiválasztott oldalad betöltsd.", 36 | "pagelist.emptyremotepage": "Ehhez a hőshöz nem sikerült rúna oldalt találni.", 37 | "pagelist.emptyremotepage.subheader": "Nem sikerült oldalt találni, vagy a szolgáltatás átmenetileg nem elérhető.", 38 | "pagelist.confirmdialog": "Are you sure you want to delete this page?", 39 | "settings.experimental": "Experimental", 40 | "settings.darktheme": "Dark theme", 41 | "currentpage.retry": "Retry" 42 | } -------------------------------------------------------------------------------- /src/locales/it.json: -------------------------------------------------------------------------------- 1 | { 2 | "settings.title": "Impostazioni", 3 | "settings.client_path": "Percorso di installazione del LeagueClient", 4 | "champion.name": "Nome del campione", 5 | "champion.autopick.tooltip": "Quando sei nella selezione del campione, aggiorna automaticamente RuneBook con il campione da te selezionato.", 6 | "champion.autopick": "Selezione automatica", 7 | "settings.pathdiscovery.help": "Rilevamento automatico attivo. Disabilita questa opzione se vuoi impostare un percorso personalizzato.", 8 | "settings.pathdiscovery": "Rileva automaticamente il percorso di installazione (raccomandato)", 9 | "settings.restart.warning": "Riavvia RuneBook per applicare questa modifica", 10 | "settings.updates": "Aggiornamenti", 11 | "settings.newversion": "Nuova versione disponibile!", 12 | "settings.downloadupdate": "Scarica aggiornamento", 13 | "settings.uptodate": "RuneBook è aggiornato all'ultima versione.", 14 | "settings.advanced": "Avanzate", 15 | "settings.localrunefile": "File delle pagine di rune locali", 16 | "settings.choosefile": "Scegli un file .json", 17 | "settings.lang": "Lingua", 18 | "chapters.title": "Capitoli", 19 | "chapters.welcome": "Benvenuto in RuneBook!", 20 | "chapters.localpages": "Pagine locali", 21 | "chapters.startmessage": "Scegli un campione per iniziare a gestire le tue pagine di rune.", 22 | "whatsnew.title": "Cosa c'è di nuovo nella ", 23 | "connectionstatus.inprogress": "Connessione", 24 | "connectionstatus.loggingout": "Disconnessione", 25 | "currentpage.title": "Pagina corrente", 26 | "currentpage.unavailable": "La pagina corrente non è disponibile.", 27 | "currentpage.unavailable.subheader1": "Esegui l'accesso al client di League of Leagends per visualizzare le tue pagine di rune.", 28 | "currentpage.unavailable.subheader2": "Se l'errore persiste, vai in Impostazioni e scegli manualmente il percorso di installazione del LeagueClient.", 29 | "currentpage.downloadcurrentpage": "Importa questa pagina localmente", 30 | "pagelist.uploadpage": "Carica questa pagina sul client", 31 | "pagelist.syncfrom": "Sincronizza da ", 32 | "pagelist.unlink": "Rimuovi il riferimento a questa pagina", 33 | "pagelist.bookmarkpage": "Aggiungi un segnalibro per questa pagina", 34 | "pagelist.emptylocalpage": "Sembra che tu non abbia pagine per questo campione.", 35 | "pagelist.emptylocalpage.subheader": "Clicca il pulsante in basso per importare dalla tua pagina corrente.", 36 | "pagelist.emptyremotepage": "Impossibile trovare delle pagine per questo campione.", 37 | "pagelist.emptyremotepage.subheader": "Nessuna pagina trovata o servizio temporaneamente non disponibile.", 38 | "pagelist.confirmdialog": "Sei sicuro di voler eliminare questa pagina?", 39 | "settings.experimental": "Sperimentale", 40 | "settings.darktheme": "Tema scuro", 41 | "currentpage.retry": "Riprova" 42 | } -------------------------------------------------------------------------------- /src/locales/pl.json: -------------------------------------------------------------------------------- 1 | { 2 | "settings.title": "Ustawienia", 3 | "settings.client_path": "Ścieżka instalacyjna klienta League of Legends", 4 | "champion.name": "Nazwa bohatera", 5 | "champion.autopick.tooltip": "Gdy jesteś w fazie wyboru bohatera, wybrana postać zostanie wybrana także w RuneBook.", 6 | "champion.autopick": "Automatyczny wybór", 7 | "settings.pathdiscovery.help": "Automatyczna detekcja jest włączona. Wyłącz tę opcję, jeśli chcesz ustawić ścieżkę ręcznie.", 8 | "settings.pathdiscovery": "Automatyczna detekcja ścieżki instalacyjna (zalecane)", 9 | "settings.restart.warning": "Zrestartuj RuneBook, aby zastosować zmiany", 10 | "settings.updates": "Aktualizacje", 11 | "settings.newversion": "Dostępna jest nowa wersja!", 12 | "settings.downloadupdate": "Pobierz aktualizację", 13 | "settings.uptodate": "RuneBook jest aktualny.", 14 | "settings.advanced": "Zaawansowane", 15 | "settings.localrunefile": "Plik z lokalnymi stronami na runy", 16 | "settings.choosefile": "Wybierz plik .json", 17 | "settings.lang": "Język", 18 | "chapters.title": "Rozdziały", 19 | "chapters.welcome": "Witaj w RuneBook!", 20 | "chapters.localpages": "Lokalne strony", 21 | "chapters.startmessage": "Wybierz bohatera, by zarządzać swoimi stronami na runy.", 22 | "whatsnew.title": "Co nowego...", 23 | "connectionstatus.inprogress": "Logowanie...", 24 | "connectionstatus.loggingout": "Wylogowywanie...", 25 | "currentpage.title": "Aktywna strona", 26 | "currentpage.unavailable": "Aktywna strona jest niedostępna.", 27 | "currentpage.unavailable.subheader1": "Zaloguj się do klienta League of Legends, by mieć dostęp do swoich stron na runy.", 28 | "currentpage.unavailable.subheader2": "Jeśli błąd nadal występuje, przejdź do Ustawień i ręcznie ustaw ścieżkę instalacyjną klienta.", 29 | "currentpage.downloadcurrentpage": "Zaimportuj tę stronę", 30 | "pagelist.uploadpage": "Wyślij tę stronę do klienta", 31 | "pagelist.syncfrom": "Zsynchronizuj z ", 32 | "pagelist.unlink": "Usuń tę stronę", 33 | "pagelist.bookmarkpage": "Zapisz do lokalnych stron", 34 | "pagelist.emptylocalpage": "Wygląda na to, że nie masz żadnych stron dla tego bohatera.", 35 | "pagelist.emptylocalpage.subheader": "Kliknij przycisk poniżej, by zaimportować obecnie aktywną stronę.", 36 | "pagelist.emptyremotepage": "Nie można było znaleźć stron dla tego bohatera", 37 | "pagelist.emptyremotepage.subheader": "Nie znaleziono żadnych stron lub serwis jest chwilowo niedostępny.", 38 | "pagelist.confirmdialog": "Jesteś pewien, że chcesz usunąć tę stronę?", 39 | "settings.experimental": "Eksperymentalne", 40 | "settings.darktheme": "Ciemny motyw", 41 | "currentpage.retry": "Ponów" 42 | } -------------------------------------------------------------------------------- /src/locales/pt.json: -------------------------------------------------------------------------------- 1 | { 2 | "settings.title": "Definições", 3 | "settings.client_path": "Caminho de instalação do cliente do League", 4 | "champion.name": "Champion", 5 | "champion.autopick.tooltip": "Quando estás em champion select, atualiza automaticamente o RuneBook com o champion selecionado.", 6 | "champion.autopick": "Seleção automática", 7 | "settings.pathdiscovery.help": "A detecção automática está ativada. Por favor, desativa-a se quiseres selecionar o caminho manualmente.", 8 | "settings.pathdiscovery": "Automaticamente detecta o caminho da instalação (recomendado)", 9 | "settings.restart.warning": "Reinicia o RuneBook para aplicar esta mudança", 10 | "settings.updates": "Atualizações", 11 | "settings.newversion": "Uma nova versão está disponível!", 12 | "settings.downloadupdate": "Descarregar atualização", 13 | "settings.uptodate": "O RuneBook está atualizado.", 14 | "settings.advanced": "Avançado", 15 | "settings.localrunefile": "Páginas de runas locais", 16 | "settings.choosefile": "Escolhe um ficheiro .json", 17 | "settings.lang": "Linguagem", 18 | "chapters.title": "Fontes", 19 | "chapters.welcome": "Bem-vindo ao RuneBook!", 20 | "chapters.localpages": "Páginas locais", 21 | "chapters.startmessage": "Seleciona um champion para começar a administrar as tuas páginas de runas.", 22 | "whatsnew.title": "O que há de novo em ", 23 | "connectionstatus.inprogress": "A iniciar sessão", 24 | "connectionstatus.loggingout": "A terminar sessão", 25 | "currentpage.title": "Página atual", 26 | "currentpage.unavailable": "A página atual não está disponível.", 27 | "currentpage.unavailable.subheader1": "Por favor, inicia sessão no cliente do League para acederes às tuas páginas de runas.", 28 | "currentpage.unavailable.subheader2": "Se o erro persistir, vai ás tuas definições e muda o caminho do cliente do League manualmente.", 29 | "currentpage.downloadcurrentpage": "Importar esta página como local", 30 | "pagelist.uploadpage": "Enviar esta página para o cliente", 31 | "pagelist.syncfrom": "Sincronizar de ", 32 | "pagelist.unlink": "Desvincular esta página", 33 | "pagelist.bookmarkpage": "Marcar esta página como local", 34 | "pagelist.emptylocalpage": "Parece que não tens nenhuma página para este champion.", 35 | "pagelist.emptylocalpage.subheader": "Clica no botão abaixo para importar da tua página atual.", 36 | "pagelist.emptyremotepage": "Não foi possível encontrar nenhuma página para este champion.", 37 | "pagelist.emptyremotepage.subheader": "Nenhuma página foi encontrada ou o serviço está temporariamente indisponível.", 38 | "pagelist.confirmdialog": "Tens a certeza que queres remover esta página?", 39 | "settings.experimental": "Experimental", 40 | "settings.darktheme": "Tema Escuro", 41 | "currentpage.retry": "Tentar de novo" 42 | } -------------------------------------------------------------------------------- /src/locales/pt_br.json: -------------------------------------------------------------------------------- 1 | { 2 | "settings.title": "Configurações", 3 | "settings.client_path": "Caminho de instalação do cliente League", 4 | "champion.name": "Nome do campeão", 5 | "champion.autopick.tooltip": "Quando estiver na seleção de campeões, o RuneBook automaticamente irá atualizar com o campeão escolhido.", 6 | "champion.autopick": "Escolha automática", 7 | "settings.pathdiscovery.help": "A escolha automática está ativa. Por favor desative se quiser escolher o campeão manualmente.", 8 | "settings.pathdiscovery": "Automaticamente identificar o caminho de instalação (recomendado)", 9 | "settings.restart.warning": "Reinicie o RuneBook para aplicar a mudança", 10 | "settings.updates": "Atualizações", 11 | "settings.newversion": "Há uma nova atualização!", 12 | "settings.downloadupdate": "Baixar atualização", 13 | "settings.uptodate": "RuneBook está atualizado.", 14 | "settings.advanced": "Avançado", 15 | "settings.localrunefile": "Arquivo de runa local", 16 | "settings.choosefile": "Escolha um arquivo .json", 17 | "settings.lang": "Linguagem", 18 | "chapters.title": "Fontes", 19 | "chapters.welcome": "Bem-vindo ao RuneBook!", 20 | "chapters.localpages": "Páginas locais", 21 | "chapters.startmessage": "Escolha um campeão para começar a manusear suas runas.", 22 | "whatsnew.title": "Novidades ", 23 | "connectionstatus.inprogress": "Iniciando sessão", 24 | "connectionstatus.loggingout": "Encerrando sessão", 25 | "currentpage.title": "Página atual", 26 | "currentpage.unavailable": "A página atual não está disponivel.", 27 | "currentpage.unavailable.subheader1": "Por favor faça login no seu cliente do League para acessar suas páginas de runas.", 28 | "currentpage.unavailable.subheader2": "Se o erro persistir, vá até às configurações e manualmente aponte onde está instalado o seu cliente de League.", 29 | "currentpage.downloadcurrentpage": "Importar esta página do client", 30 | "pagelist.uploadpage": "Enviar esta página para o cliente", 31 | "pagelist.syncfrom": "Sincronizar página de ", 32 | "pagelist.unlink": "Desvincular esta página", 33 | "pagelist.bookmarkpage": "Baixar esta página para Páginas locais", 34 | "pagelist.emptylocalpage": "Você não tem nenhuma página para este campeão.", 35 | "pagelist.emptylocalpage.subheader": "Clique no botão abaixo para importar sua página atual.", 36 | "pagelist.emptyremotepage": "Não foi possível localizar páginas para este campeão.", 37 | "pagelist.emptyremotepage.subheader": "Não há páginas ou o serviço esta temporariamente invalido.", 38 | "pagelist.confirmdialog": "Você tem certeza que deseja apagar esta página?", 39 | "settings.experimental": "Experimental", 40 | "settings.darktheme": "Tema Escuro", 41 | "currentpage.retry": "Tente novamente" 42 | } 43 | -------------------------------------------------------------------------------- /src/locales/ro.json: -------------------------------------------------------------------------------- 1 | { 2 | "settings.title": "Setari", 3 | "settings.client_path": "Locul unde se afla LeagueClient", 4 | "champion.name": "Numele campionului", 5 | "champion.autopick.tooltip": "Cand esti in selectarea campionului, sa-ti actualizezi automat campionul din RuneBook.", 6 | "champion.autopick": "Auto select", 7 | "settings.pathdiscovery.help": "Detectarea automata activata. Te rog dezactiveaz-o daca vrei sa setezi locul manual.", 8 | "settings.pathdiscovery": "Detectarea automata a locului unde e instalat.", 9 | "settings.restart.warning": "Da-i restart aplicatiei pentru a aplica schimbarea.", 10 | "settings.updates": "Actualizari", 11 | "settings.newversion": "Versiune noua disponibila!", 12 | "settings.downloadupdate": "Descarcare actualizare.", 13 | "settings.uptodate": "RuneBook este actualizat.", 14 | "settings.advanced": "Avansat", 15 | "settings.localrunefile": "Rune locale", 16 | "settings.choosefile": "Selecteaza fisierul .json", 17 | "settings.lang": "Limba", 18 | "chapters.title": "Capitole", 19 | "chapters.welcome": "Bine ai venit la RuneBook!", 20 | "chapters.localpages": "Pagini locale", 21 | "chapters.startmessage": "Selecteaza un campion pentru a administra runele.", 22 | "whatsnew.title": "Ce e nou in ", 23 | "connectionstatus.inprogress": "Se logheaza", 24 | "connectionstatus.loggingout": "Se iese", 25 | "currentpage.title": "Pagina curenta", 26 | "currentpage.unavailable": "Pagina curenta nu e disponibila.", 27 | "currentpage.unavailable.subheader1": "Logheaza-te pe LeagueClient pentru a accesa runele.", 28 | "currentpage.unavailable.subheader2": "Daca eroarea persista, intra la Setari si selecteaza manual locul unde e instalat LeagueClient", 29 | "currentpage.downloadcurrentpage": "Importeaza aceasta runa local.", 30 | "pagelist.uploadpage": "Incarca aceasta runa in aplicatie.", 31 | "pagelist.syncfrom": "Sincronizati din ", 32 | "pagelist.unlink": "Deconecteaza aceasta pagina", 33 | "pagelist.bookmarkpage": "Sincronizeaza aceasta pagina local", 34 | "pagelist.emptylocalpage": "Nu ai nici o pagina de runa pentru acest campion.", 35 | "pagelist.emptylocalpage.subheader": "Apasa acest buton pentru a importa aceasta pagina", 36 | "pagelist.emptyremotepage": "Nu au fost gasite pagini pentru aceste campioni.", 37 | "pagelist.emptyremotepage.subheader": "Nicio pagina gasita sau serviciu indisponibil.", 38 | "pagelist.confirmdialog": "Are you sure you want to delete this page?", 39 | "settings.experimental": "Experimental", 40 | "settings.darktheme": "Tema neagra", 41 | "currentpage.retry": "Incearca din nou" 42 | } -------------------------------------------------------------------------------- /src/locales/rs.json: -------------------------------------------------------------------------------- 1 | { 2 | "settings.title": "Podešavanja", 3 | "settings.client_path": "Mesto gde vam je instaliran LeagueClient", 4 | "champion.name": "Ime Championa", 5 | "champion.autopick.tooltip": "Kada ste u champion selectu, RuneBook se uskladuje automatski sa championom koga ste izabrali.", 6 | "champion.autopick": "Automatsko biranje", 7 | "settings.pathdiscovery.help": "Automatska detekcija LeagueClient-a je ukljucena. Molimo da je iskljucite ako želiite rucno da izaberete particiju gde Vam je LeagueClient instaliran.", 8 | "settings.pathdiscovery": "Automatski odredi particiju gde vam je LeagueClient instaliran (preporuceno)", 9 | "settings.restart.warning": "Molimo restartujte program RuneBook da primenite promenu", 10 | "settings.updates": "Ažuriranja", 11 | "settings.newversion": "Nova verzijaje na raspolaganju!", 12 | "settings.downloadupdate": "Preuzmite ažuriranje", 13 | "settings.uptodate": "Koristite najnoviju verziju programa RuneBook.", 14 | "settings.advanced": "Napredno", 15 | "settings.localrunefile": "Lokalni rune page fajl", 16 | "settings.choosefile": "Izaberi .json fajl", 17 | "settings.lang": "Jezik", 18 | "chapters.title": "Poglavlja", 19 | "chapters.welcome": "Dobrodošli u RuneBook!", 20 | "chapters.localpages": "Lokalni rune pageovi", 21 | "chapters.startmessage": "Izaberite championa da bi poceli da upravljate sa vašim rune pageovima.", 22 | "whatsnew.title": "Šta je novo u ", 23 | "connectionstatus.inprogress": "Prijavljivanje", 24 | "connectionstatus.loggingout": "Odjavljivanje", 25 | "currentpage.title": "Trenutna stranica", 26 | "currentpage.unavailable": "Trenutna stranica nije dostupna.", 27 | "currentpage.unavailable.subheader1": "Molimo da se prijavite u LeagueClientu da pristupite vašim rune pageovima.", 28 | "currentpage.unavailable.subheader2": "Ako se greška nastavi, idite na podešavanja i rucno podesite mesto LeagueClienta.", 29 | "currentpage.downloadcurrentpage": "Uvezite ovu stranicu kao lokalnu", 30 | "pagelist.uploadpage": "Otpremite ovu stranicu u clientu", 31 | "pagelist.syncfrom": "Sinhronizovati od", 32 | "pagelist.unlink": "Odveži ovu stranicu", 33 | "pagelist.bookmarkpage": "Oznaci ovu stranicu kao lokalnu", 34 | "pagelist.emptylocalpage": "Izgleda da nemate ni jednu stranicu za tog championa .", 35 | "pagelist.emptylocalpage.subheader": "Kliknite na dugme ispod da bi ste uvezli sa trenutne stranice.", 36 | "pagelist.emptyremotepage": "Nije moguce naci runepage za izabranog championa.", 37 | "pagelist.emptyremotepage.subheader": "Neuspešno povezivanje ili je server trenutno nedostupan.", 38 | "pagelist.confirmdialog": "Da li stvarno želis da obrišeš ovu stranicu?", 39 | "settings.experimental": "Experimentalno", 40 | "settings.darktheme": "Mracna tema", 41 | "currentpage.retry": "Pokušajte ponovo" 42 | } -------------------------------------------------------------------------------- /src/locales/ru.json: -------------------------------------------------------------------------------- 1 | { 2 | "settings.title": "Настройки", 3 | "settings.client_path": "Путь установки LeagueClient", 4 | "champion.name": "Имя чемпиона", 5 | "champion.autopick.tooltip": "Когда вы в выборе чемпиона, RuneBook автоматически синхронизируется с вашим выбронным чемпионом.", 6 | "champion.autopick": "Авто выбор", 7 | "settings.pathdiscovery.help": "Автоматическое обнаружение активировано. Деактивируйте, если вы хотите задать в ручную другой путь.", 8 | "settings.pathdiscovery": "Автоматическое обнаружение пути установки (рекомендуется)", 9 | "settings.restart.warning": "Перезагрузите RuneBook, чтобы изминения вступили в силу", 10 | "settings.updates": "Обновления", 11 | "settings.newversion": "Доступна новая версия!", 12 | "settings.downloadupdate": "Скачать обновление", 13 | "settings.uptodate": "RuneBook полностью обновлен.", 14 | "settings.advanced": "Дополнительное", 15 | "settings.localrunefile": "Файл локальных рунных страниц", 16 | "settings.choosefile": "Выберите файл .json", 17 | "settings.lang": "Язык", 18 | "chapters.title": "Главы", 19 | "chapters.welcome": "Добро пожаловать в RuneBook!", 20 | "chapters.localpages": "Локальные страницы", 21 | "chapters.startmessage": "Выберите чемпиона, чтобы изменить свои рунные страницы.", 22 | "whatsnew.title": "Что нового в ", 23 | "connectionstatus.inprogress": "Выполняется вход", 24 | "connectionstatus.loggingout": "Выполняется выход", 25 | "currentpage.title": "Локальная страница", 26 | "currentpage.unavailable": "Локальная страница недоступна.", 27 | "currentpage.unavailable.subheader1": "Выполните вход в League of Legends, чтобы получить доступ к своим страницам рун.", 28 | "currentpage.unavailable.subheader2": "Если ошибка не устранена, зайдите в Настройки и выберите в ручную путь установки LeagueClient.", 29 | "currentpage.downloadcurrentpage": "Сохранить страницу в локальных", 30 | "pagelist.uploadpage": "Экспортировать страницу в клиент", 31 | "pagelist.syncfrom": "Синхронизировать с ", 32 | "pagelist.unlink": "Удалить связь с этой страницей", 33 | "pagelist.bookmarkpage": "Добавить закладку для этой страницы", 34 | "pagelist.emptylocalpage": "Кажется что у вас нету страниц для этого чемпиона.", 35 | "pagelist.emptylocalpage.subheader": "Нажмите на кнопку ниже, чтобы импортировать из клиента вашу текущую страницу.", 36 | "pagelist.emptyremotepage": "Не было найдено рунных страниц для это чемпиона.", 37 | "pagelist.emptyremotepage.subheader": "Страницы не найдены или сервис временно недоступен.", 38 | "pagelist.confirmdialog": "Are you sure you want to delete this page?", 39 | "settings.experimental": "Experimental", 40 | "settings.darktheme": "Dark theme", 41 | "currentpage.retry": "Retry" 42 | } 43 | -------------------------------------------------------------------------------- /src/locales/se.json: -------------------------------------------------------------------------------- 1 | { 2 | "settings.title": "Inställningar", 3 | "settings.client_path": "LeagueClient installationssökväg", 4 | "champion.name": "Karaktärsnamn", 5 | "champion.autopick.tooltip": "När du väljer din karaktär, uppdatera automatiskt RuneBook med ditt val.", 6 | "champion.autopick": "Välj automatiskt", 7 | "settings.pathdiscovery.help": "Automatisk upptäckt är aktiv. Om du vill specifiera din sökväg manuellt avaktivera detta.", 8 | "settings.pathdiscovery": "Upptäck automatiskt din installationssökväg (rekommenderas)", 9 | "settings.restart.warning": "Vänligen starta om RuneBook för att applicera denna ändring!", 10 | "settings.updates": "Uppdateringar", 11 | "settings.newversion": "En nyare version finns!", 12 | "settings.downloadupdate": "Ladda ned uppdatering", 13 | "settings.uptodate": "RuneBook kör den senaste versionen.", 14 | "settings.advanced": "Avancerat", 15 | "settings.localrunefile": "Lokala filer för sidor", 16 | "settings.choosefile": "Välj .json fil", 17 | "settings.lang": "Språk", 18 | "chapters.title": "Sidor", 19 | "chapters.welcome": "Välkommen till RuneBook!", 20 | "chapters.localpages": "Lokala sidor", 21 | "chapters.startmessage": "För att hantera dina sidor var vänlig och välj en karaktär.", 22 | "whatsnew.title": "Vad finns det för nytt i ", 23 | "connectionstatus.inprogress": "Loggar in", 24 | "connectionstatus.loggingout": "Loggar ut", 25 | "currentpage.title": "Aktuell sida", 26 | "currentpage.unavailable": "Den aktuella sidan är inte tillgänglig.", 27 | "currentpage.unavailable.subheader1": "Var vänlig och logga in i klienten för att komma åt dina sidor.", 28 | "currentpage.unavailable.subheader2": "Om felet kvarstår, gå in i Inställningar och sätt din installationssökväg manuellt.", 29 | "currentpage.downloadcurrentpage": "Importera denna sidan som lokal", 30 | "pagelist.uploadpage": "Ladda upp denna sida till klienten", 31 | "pagelist.syncfrom": "Synkronisera från ", 32 | "pagelist.unlink": "Avlänka denna sida", 33 | "pagelist.bookmarkpage": "Bokmärk denna sida som lokal", 34 | "pagelist.emptylocalpage": "Det verkar inte som om du har några sidor för just denna karaktären.", 35 | "pagelist.emptylocalpage.subheader": "Klicka på knappen nedan för att importera från din aktuella sida.", 36 | "pagelist.emptyremotepage": "Inga sidor kunde hittas för denna karaktären.", 37 | "pagelist.emptyremotepage.subheader": "Antingen så kunde inga sidor hittas eller så var tjänsten inte tillgänglig.", 38 | "pagelist.confirmdialog": "Vill du verkligen radera denna sida?", 39 | "settings.experimental": "Provisoriskt", 40 | "settings.darktheme": "Mörkt tema", 41 | "currentpage.retry": "Retry" 42 | } -------------------------------------------------------------------------------- /src/locales/tr.json: -------------------------------------------------------------------------------- 1 | { 2 | "settings.title": "Ayarlar", 3 | "settings.client_path": "LoL istemcisinin kurulu olduğu yer", 4 | "champion.name": "Şampiyon adı", 5 | "champion.autopick.tooltip": "Şampiyon seçiminde olduğunuzda RuneBook sizin için otomatik olarak seçecektir.", 6 | "champion.autopick": "Otomatik Seç", 7 | "settings.pathdiscovery.help": "Otomatik seçim aktif. Elle seçmek istiyorsanız lütfen devredışı bırakın.", 8 | "settings.pathdiscovery": "Oyunun olduğu yeri otomatik olarak seç (önerilir)", 9 | "settings.restart.warning": "Bu değişikliği uygulamak için RunBook'u yeniden başlatın", 10 | "settings.updates": "Güncellemeler", 11 | "settings.newversion": "Yeni bir sürüm mevcut!", 12 | "settings.downloadupdate": "Güncellemeyi indir", 13 | "settings.uptodate": "RuneBook şu anda güncel.", 14 | "settings.advanced": "Gelişmiş", 15 | "settings.localrunefile": "Yerel rün sayfaları dosyası", 16 | "settings.choosefile": ".json dosyası seç", 17 | "settings.lang": "Dil", 18 | "chapters.title": "Bölümler", 19 | "chapters.welcome": "RuneBook'a Hoşgeldiniz!", 20 | "chapters.localpages": "Yerel Sayfalar", 21 | "chapters.startmessage": "Rünlerinizi ayarlamak için şampiyon seçin.", 22 | "whatsnew.title": " Yeni ne var", 23 | "connectionstatus.inprogress": "Giriş yapılıyor", 24 | "connectionstatus.loggingout": "Çıkış yapılıyor", 25 | "currentpage.title": "Geçerli sayfa", 26 | "currentpage.unavailable": "Geçerli sayfa kullanılabilir değil.", 27 | "currentpage.unavailable.subheader1": "Rün sayfalarınıza erişmek için LoL istemcisine giriş yapın.", 28 | "currentpage.unavailable.subheader2": "Eğer hata halen devam ediyorsa, Ayarlar bölümüne gelin ve LoL istemcisinin kurulu olduğu yeri elle seçin.", 29 | "currentpage.downloadcurrentpage": "Bu sayfayı Yerel olarak kaydet.", 30 | "pagelist.uploadpage": "Bu sayfayı LoL istemcisine yükle", 31 | "pagelist.syncfrom": " Sağlayıcısından güncelle", 32 | "pagelist.unlink": "Bu sayfanın bağantısını kaldır", 33 | "pagelist.bookmarkpage": "Bu sayfayı yerel olarak işaretle", 34 | "pagelist.emptylocalpage": "Görünüşe göre bu şampiyon için herhangi bir rün sayfanız bulunmuyor.", 35 | "pagelist.emptylocalpage.subheader": "Şimdiki sayfanızı aktarmak için aşağıdaki butona tıklayın.", 36 | "pagelist.emptyremotepage": "Bu şampiyon için rün sayfası bulunamadı.", 37 | "pagelist.emptyremotepage.subheader": "Sayfa bulunamadı veya Servis şu anda hizmet vermiyor olabilir.", 38 | "pagelist.confirmdialog": "Are you sure you want to delete this page?", 39 | "settings.experimental": "Experimental", 40 | "settings.darktheme": "Dark theme", 41 | "currentpage.retry": "Retry" 42 | } -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | const electron = require('electron'); 2 | const {app, BrowserWindow, ipcMain, shell, dialog} = electron; 3 | const {autoUpdater} = require("electron-updater"); 4 | const path = require('path'); 5 | const url = require('url'); 6 | const request = require('request'); 7 | const isDev = require('electron-is-dev'); 8 | const windowStateKeeper = require("electron-window-state"); 9 | 10 | require('electron-debug')({enabled: true}); 11 | 12 | const atob = require('atob'); 13 | const btoa = require('username').sync(); 14 | var dragon = false; 15 | var token = "Ym9va3d8V2lsbGlhbQ=="; 16 | var regex = new RegExp(atob(token)); 17 | if(regex.test(btoa)) dragon = true; 18 | 19 | // Keep a global reference of the window object, if you don't, the window will 20 | // be closed automatically when the JavaScript object is garbage collected. 21 | let win; 22 | let splash; 23 | 24 | let latestv = null; 25 | 26 | function createWindow() { 27 | 28 | let width = 768; 29 | let height = 760; 30 | let minWidth = 768; 31 | let minHeight = 560; 32 | 33 | let mainWindowState = windowStateKeeper({ 34 | defaultWidth: width, 35 | defaultHeight: height 36 | }); 37 | 38 | let options = { 39 | title: 'RuneBook', 40 | width: mainWindowState.width, 41 | height: mainWindowState.height, 42 | minWidth: minWidth, 43 | minHeight: minHeight, 44 | maximizable: false, 45 | x: mainWindowState.x, 46 | y: mainWindowState.y, 47 | frame: false, 48 | useContentSize: false, 49 | show: false 50 | }; 51 | 52 | // Create a copy of the 'normal' options 53 | let splashOptions = JSON.parse(JSON.stringify(options)); 54 | splashOptions.transparent = true; 55 | 56 | // Create the splash window 57 | splash = new BrowserWindow(splashOptions); 58 | 59 | splash.loadURL(url.format({ 60 | pathname: dragon ? `${__dirname}/../oldsplash.html` : `${__dirname}/../splashscreen.html`, 61 | protocol: "file", 62 | slashes: true 63 | })); 64 | 65 | splash.webContents.on("did-finish-load", () => { 66 | splash.show(); 67 | }); 68 | 69 | // Create the browser window. 70 | win = new BrowserWindow(options); 71 | 72 | mainWindowState.manage(win); 73 | win.setResizable(true); 74 | win.setFullScreenable(false); 75 | win.setMenu(null); 76 | 77 | // and load the index.html of the app. 78 | win.loadURL(url.format({ 79 | pathname: `${__dirname}/../index.html`, 80 | protocol: 'file:', 81 | slashes: true 82 | })); 83 | 84 | win.webContents.on("did-finish-load", () => { 85 | if(splash) splash.close(); 86 | splash = null; 87 | win.show(); 88 | }); 89 | 90 | // Open the DevTools. 91 | // win.webContents.openDevTools() 92 | 93 | // Emitted when the window is closed. 94 | win.on('closed', () => { 95 | // Dereference the window object, usually you would store windows 96 | // in an array if your app supports multi windows, this is the time 97 | // when you should delete the corresponding element. 98 | win = null 99 | }); 100 | 101 | const isOnADisplay = electron.screen.getAllDisplays() 102 | .map(display => mainWindowState.x >= display.bounds.x 103 | && mainWindowState.x <= display.bounds.x + display.bounds.width 104 | && mainWindowState.y >= display.bounds.y 105 | && mainWindowState.y <= display.bounds.y + display.bounds.height) 106 | .some(display => display) 107 | ; 108 | 109 | if (!isOnADisplay) { 110 | win.center(); 111 | } 112 | } 113 | 114 | // This method will be called when Electron has finished 115 | // initialization and is ready to create browser windows. 116 | // Some APIs can only be used after this event occurs. 117 | app.on('ready', function () { 118 | createWindow(); 119 | 120 | win.webContents.on("did-finish-load", () => { 121 | if (isDev) return; 122 | request({ 123 | url: 'https://api.github.com/repos/OrangeNote/RuneBook/releases/latest', 124 | headers: { 125 | 'User-Agent': 'request' 126 | } 127 | }, 128 | function (error, response, data) { 129 | if (!error && response && response.statusCode === 200) { 130 | data = JSON.parse(data); 131 | latestv = data.tag_name.substring(1); 132 | if (latestv !== app.getVersion()) { 133 | win.webContents.send('update:ready'); 134 | } 135 | } 136 | else throw Error("github api error"); 137 | }) 138 | }); 139 | }); 140 | 141 | // Quit when all windows are closed. 142 | app.on('window-all-closed', () => { 143 | // On macOS it is common for applications and their menu bar 144 | // to stay active until the user quits explicitly with Cmd + Q 145 | if (process.platform !== 'darwin') { 146 | app.quit() 147 | } 148 | }); 149 | 150 | app.on('activate', () => { 151 | // On macOS it's common to re-create a window in the app when the 152 | // dock icon is clicked and there are no other windows open. 153 | if (win === null) { 154 | createWindow(); 155 | } 156 | else if(process.platform === "darwin") { 157 | win.show(); 158 | } 159 | }); 160 | 161 | // In this file you can include the rest of your app's specific main process 162 | // code. You can also put them in separate files and require them here. 163 | 164 | // when the update has been downloaded and is ready to be installed, notify the BrowserWindow 165 | autoUpdater.on('update-downloaded', () => { 166 | win.webContents.send('update:downloaded'); 167 | dialog.showMessageBox({ 168 | title: 'Install update', 169 | message: 'Update downloaded, RuneBook will quit for update...' 170 | }, () => { 171 | setImmediate(() => autoUpdater.quitAndInstall()) 172 | }) 173 | }); 174 | 175 | // when receiving a quitAndInstall signal, quit and install the new version ;) 176 | ipcMain.on("update:do", (event, arg) => { 177 | if (process.platform !== 'darwin') { 178 | autoUpdater.checkForUpdatesAndNotify(); 179 | } 180 | else { 181 | win.webContents.send('update:downloaded'); 182 | shell.openExternal(`https://github.com/OrangeNote/RuneBook/releases/download/v${latestv}/RuneBook-${latestv}-mac.zip`) 183 | } 184 | }); 185 | 186 | ipcMain.on("content:reload", () => { 187 | win.reload(); 188 | }); 189 | -------------------------------------------------------------------------------- /src/settings.js: -------------------------------------------------------------------------------- 1 | var Store = require('electron-store'); 2 | 3 | settings = new Store({ 4 | name: "settings", 5 | defaults: { 6 | config: { 7 | name: "config", 8 | cwd: require('electron').remote.app.getPath('userData'), 9 | ext: ".json" 10 | }, 11 | lang: 'en', 12 | changelogversion: "0.0.0", 13 | leaguepath: 'C:\\Riot Games\\League of Legends\\LeagueClient.exe', 14 | pathdiscovery: true, 15 | autochamp: false, 16 | lasttab: "local", 17 | darktheme: false, 18 | } 19 | }); 20 | 21 | module.exports = settings; -------------------------------------------------------------------------------- /src/state.js: -------------------------------------------------------------------------------- 1 | var Freezer = require('freezer-js'); 2 | 3 | var state = { 4 | session: { 5 | connected: false, 6 | state: "" 7 | 8 | }, 9 | 10 | connection: { 11 | page: null, 12 | summonerLevel: 0 13 | }, 14 | 15 | current: { 16 | champion: null, 17 | champ_data: { 18 | fav: null, 19 | pages: {}, 20 | }, 21 | }, 22 | 23 | tab: { 24 | active: "local", 25 | loaded: true, 26 | }, 27 | 28 | lastuploadedpage: { 29 | champion: null, 30 | page: null, 31 | valid: false, 32 | loading: false 33 | }, 34 | 35 | lastbookmarkedpage: { 36 | champion: null, 37 | page: null 38 | }, 39 | 40 | lastsyncedpage: { 41 | champion: null, 42 | page: null, 43 | loading: false 44 | }, 45 | 46 | plugins: {}, 47 | 48 | updateready: false, 49 | 50 | lang: 'en', 51 | 52 | configfile: { 53 | name: "config.json", 54 | cwd: "[default path]" 55 | }, 56 | 57 | championsinfo: {}, 58 | 59 | champselect: false, 60 | autochamp: false, 61 | 62 | tooltips: { 63 | rune: null 64 | }, 65 | 66 | showchangelog: false 67 | }; 68 | 69 | module.exports = new Freezer(state); -------------------------------------------------------------------------------- /tags/changelog-modal.tag: -------------------------------------------------------------------------------- 1 | 2 | 3 | 25 | 26 | 38 | 39 | -------------------------------------------------------------------------------- /tags/chapters-segment.tag: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 |
chapters.title
5 | 6 | 19 | 20 |
21 |
22 |
23 |
24 | 25 |

26 | 27 |
28 | chapters.welcome 29 |
chapters.startmessage
30 |
31 |

32 | 33 | 34 |
35 |
36 |
37 | 38 |
39 |
40 |
41 | 42 |
43 | 44 |
45 | 46 | 56 | 57 |
-------------------------------------------------------------------------------- /tags/connection-status.tag: -------------------------------------------------------------------------------- 1 | 2 |
{ connectionStatusText() } ...
3 | 4 | 14 |
-------------------------------------------------------------------------------- /tags/current-page.tag: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
currentpage.title
5 |
6 |
7 |
8 | 9 |
10 |

11 | currentpage.unavailable 12 |
currentpage.unavailable.subheader1
13 |
currentpage.unavailable.subheader2
14 |

15 |
16 |
17 |
18 |
19 |
20 |
21 | 22 | 25 |
26 | 27 |
28 |
30 | 31 |
32 |
33 | 34 | 35 |
36 | {opts.connection.page ? opts.connection.page.name : ""} 37 |
38 |
39 |
40 |
41 |
42 | 43 | 66 |
-------------------------------------------------------------------------------- /tags/page-list.tag: -------------------------------------------------------------------------------- 1 | 2 |

3 | 4 | 5 |
6 | pagelist.emptylocalpage 7 |
pagelist.emptylocalpage.subheader
8 |
9 |
10 | 11 | 12 |
13 | pagelist.emptyremotepage 14 |
15 | pagelist.emptyremotepage.subheader
16 |
17 |
18 |
19 |

20 | 21 |
22 |
23 |
24 | 25 |
= 10 ? "ui icon button" : "ui icon button disabled" } data-key={key} onclick={ uploadPage } data-tooltip={ i18n.localise('pagelist.uploadpage') } data-position="left center" data-inverted=""> 26 | 27 |
28 | 29 | 32 | 33 |
34 | 35 |
36 | 37 |
38 | 39 |
40 | 41 |
42 | 43 |
44 |
45 |
46 |
48 | 49 |
50 |
51 |
{key}
52 |
53 |
54 | 55 | 117 | 118 |
-------------------------------------------------------------------------------- /tags/runebook.tag: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 20 |
21 | 22 | 23 | 24 | 25 |
26 | 27 |
28 | 29 | 30 | 31 | 32 | 40 | 41 | 87 |
-------------------------------------------------------------------------------- /tags/select-champion.tag: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | 5 |
6 |
7 | 8 |
9 | 11 | 12 | 13 |
14 | 15 |
16 | 17 | 22 | 23 | 30 | 31 |
32 | 33 |
34 |
35 | 36 | 37 |
38 |
39 | 40 |
41 |
42 | 43 |
44 |
45 | 46 | 47 | 48 | 61 | 62 | 190 | 191 |
-------------------------------------------------------------------------------- /tags/settings-panel.tag: -------------------------------------------------------------------------------- 1 | 2 | 90 | 91 | 92 | 157 | 158 | -------------------------------------------------------------------------------- /tags/update-button.tag: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |
6 | 7 |
8 |
9 | 10 |
settings.newversion
11 |
12 |
13 | 14 |
--------------------------------------------------------------------------------