├── .gitignore
├── Gemfile
├── Gemfile.lock
├── LICENSE
├── README.md
├── _config.yml
├── _includes
├── disqus_comments.html
├── footer.html
├── google-analytics.html
├── head.html
├── header.html
├── icon-github.html
├── icon-github.svg
├── icon-twitter.html
└── icon-twitter.svg
├── _layouts
├── default.html
└── page.html
├── _sass
├── minima
│ ├── _base.scss
│ ├── _layout.scss
│ └── _syntax-highlighting.scss
└── player.scss
├── about.md
├── assets
├── clippy.svg
├── logo.svg
└── thumbnail.png
├── css
├── bootstrap.css
└── main.scss
├── favicon.png
├── feed.xml
├── index.html
├── js
├── bootstrap.min.js
├── bundle.js
├── clipboard.min.js
├── kudosplease-min.js
├── main.js
└── webtorrent.js
└── package.json
/.gitignore:
--------------------------------------------------------------------------------
1 | _site/
2 | .sass-cache/
3 | .jekyll-metadata
4 |
5 | node_modules/
6 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source "https://rubygems.org"
2 | ruby RUBY_VERSION
3 |
4 | # Hello! This is where you manage which Jekyll version is used to run.
5 | # When you want to use a different version, change it below, save the
6 | # file and run `bundle install`. Run Jekyll with `bundle exec`, like so:
7 | #
8 | # bundle exec jekyll serve
9 | #
10 | # This will help ensure the proper Jekyll version is running.
11 | # Happy Jekylling!
12 | gem "jekyll", "4.2.2"
13 |
14 | # This is the default theme for new Jekyll sites. You may change this to anything you like.
15 | gem "minima"
16 |
17 | # If you want to use GitHub Pages, remove the "gem "jekyll"" above and
18 | # uncomment the line below. To upgrade, run `bundle update github-pages`.
19 | # gem "github-pages", group: :jekyll_plugins
20 |
21 | # If you have any plugins, put them here!
22 | # group :jekyll_plugins do
23 | # gem "jekyll-github-metadata", "~> 1.0"
24 | # end
25 |
26 | # Required after upgrading from Ruby v2 to v3
27 | # (see https://stackoverflow.com/a/67048226/2047110)
28 | gem "webrick" #, "~> 1.7"
29 |
--------------------------------------------------------------------------------
/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: https://rubygems.org/
3 | specs:
4 | addressable (2.8.0)
5 | public_suffix (>= 2.0.2, < 5.0)
6 | colorator (1.1.0)
7 | concurrent-ruby (1.1.10)
8 | em-websocket (0.5.3)
9 | eventmachine (>= 0.12.9)
10 | http_parser.rb (~> 0)
11 | eventmachine (1.2.7)
12 | ffi (1.15.5)
13 | forwardable-extended (2.6.0)
14 | http_parser.rb (0.8.0)
15 | i18n (1.10.0)
16 | concurrent-ruby (~> 1.0)
17 | jekyll (4.2.2)
18 | addressable (~> 2.4)
19 | colorator (~> 1.0)
20 | em-websocket (~> 0.5)
21 | i18n (~> 1.0)
22 | jekyll-sass-converter (~> 2.0)
23 | jekyll-watch (~> 2.0)
24 | kramdown (~> 2.3)
25 | kramdown-parser-gfm (~> 1.0)
26 | liquid (~> 4.0)
27 | mercenary (~> 0.4.0)
28 | pathutil (~> 0.9)
29 | rouge (~> 3.0)
30 | safe_yaml (~> 1.0)
31 | terminal-table (~> 2.0)
32 | jekyll-feed (0.16.0)
33 | jekyll (>= 3.7, < 5.0)
34 | jekyll-sass-converter (2.2.0)
35 | sassc (> 2.0.1, < 3.0)
36 | jekyll-seo-tag (2.8.0)
37 | jekyll (>= 3.8, < 5.0)
38 | jekyll-watch (2.2.1)
39 | listen (~> 3.0)
40 | kramdown (2.4.0)
41 | rexml
42 | kramdown-parser-gfm (1.1.0)
43 | kramdown (~> 2.0)
44 | liquid (4.0.3)
45 | listen (3.7.1)
46 | rb-fsevent (~> 0.10, >= 0.10.3)
47 | rb-inotify (~> 0.9, >= 0.9.10)
48 | mercenary (0.4.0)
49 | minima (2.5.1)
50 | jekyll (>= 3.5, < 5.0)
51 | jekyll-feed (~> 0.9)
52 | jekyll-seo-tag (~> 2.1)
53 | pathutil (0.16.2)
54 | forwardable-extended (~> 2.6)
55 | public_suffix (4.0.7)
56 | rb-fsevent (0.11.1)
57 | rb-inotify (0.10.1)
58 | ffi (~> 1.0)
59 | rexml (3.2.5)
60 | rouge (3.29.0)
61 | safe_yaml (1.0.5)
62 | sassc (2.4.0)
63 | ffi (~> 1.9)
64 | terminal-table (2.0.0)
65 | unicode-display_width (~> 1.1, >= 1.1.1)
66 | unicode-display_width (1.8.0)
67 | webrick (1.7.0)
68 |
69 | PLATFORMS
70 | ruby
71 |
72 | DEPENDENCIES
73 | jekyll (= 4.2.2)
74 | minima
75 | webrick
76 |
77 | RUBY VERSION
78 | ruby 3.1.2p20
79 |
80 | BUNDLED WITH
81 | 2.3.16
82 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 Henrique Ferrolho
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 | # Magnet Player
2 |
3 | **Magnet Player** is a site where anyone can stream torrents directly from their browser.
4 |
5 | It uses **[WebTorrent](https://webtorrent.io/)** - the first torrent client that works in the browser. **WebTorrent** uses **[WebRTC](https://webrtc.org/)** for true peer-to-peer transport. No browser plugin, extension, or installation is required.
6 |
7 | ---
8 |
9 | ### Note
10 |
11 | *In the browser, WebTorrent can only download torrents that are seeded by a WebRTC-capable torrent client.*
12 |
13 | > What does that mean?
14 |
15 | It means that, for now, not every torrent will work on this site.
16 |
17 | > Why??
18 |
19 | Because most people use native torrent clients like *BitTorrent*, *Transmission*, *μTorrent*, etc. which do not use the [WebRTC](https://en.wikipedia.org/wiki/WebRTC) transport protocol, but the [TCP](https://en.wikipedia.org/wiki/Transmission_Control_Protocol)/[uTP](https://en.wikipedia.org/wiki/Micro_Transport_Protocol).
20 |
21 | > Will I be able to stream more torrents in the future?
22 |
23 | **Yes!** It is just a matter of time until developers add WebTorrent support for the most popular native torrent clients. **[Vuze](http://www.vuze.com/)** [already has support](https://wiki.vuze.com/w/WebTorrent) for WebTorrent!
24 |
25 | You can subscribe to [this issue](https://github.com/feross/webtorrent/issues/369) for updates on this matter.
26 |
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | # Welcome to Jekyll!
2 | #
3 | # This config file is meant for settings that affect your whole blog, values
4 | # which you are expected to set up once and rarely edit after that. If you find
5 | # yourself editing these this file very often, consider using Jekyll's data files
6 | # feature for the data you need to update frequently.
7 | #
8 | # For technical reasons, this file is *NOT* reloaded automatically when you use
9 | # 'jekyll serve'. If you change this file, please restart the server process.
10 |
11 | # Site settings
12 | # These are used to personalize your new site. If you look in the HTML files,
13 | # you will see them accessed via {{ site.title }}, {{ site.email }}, and so on.
14 | # You can create any custom variable you would like, and they will be accessible
15 | # in the templates via {{ site.myvariable }}.
16 | title: Magnet Player
17 | author: Henrique Ferrolho
18 | email: henrique.ferrolho@gmail.com
19 | description: > # this means to ignore newlines until "baseurl:"
20 | A place for streaming torrents directly from your browser.
21 | baseurl: "/magnet-player" # the subpath of your site, e.g. /blog
22 | url: "http://ferrolho.github.io" # the base hostname & protocol for your site
23 | twitter_username: hferrolho
24 | github_username: ferrolho
25 |
26 | # Build settings
27 | markdown: kramdown
28 | theme: minima
29 |
--------------------------------------------------------------------------------
/_includes/disqus_comments.html:
--------------------------------------------------------------------------------
1 | {% if page.comments != false and jekyll.environment == "production" %}
2 | {% if site.url %}
3 | {% assign disqus_url = page.url | prepend: site.url %}
4 | {% elsif site.github.url %}
5 | {% assign disqus_url = page.url | prepend: site.github.url %}
6 | {% endif %}
7 |
8 |
9 |
24 | Please enable JavaScript to view the comments powered by Disqus.
25 | {% endif %}
26 |
--------------------------------------------------------------------------------
/_includes/footer.html:
--------------------------------------------------------------------------------
1 |
47 |
--------------------------------------------------------------------------------
/_includes/google-analytics.html:
--------------------------------------------------------------------------------
1 |
11 |
12 |
--------------------------------------------------------------------------------
/_includes/head.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | {% if page.title %}{{ page.title | escape }}{% else %}{{ site.title | escape }}{% endif %}
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | {% if jekyll.environment == 'production' and site.google_analytics %}
27 | {% include google-analytics.html %}
28 | {% endif %}
29 |
30 |
--------------------------------------------------------------------------------
/_includes/header.html:
--------------------------------------------------------------------------------
1 |
2 | Fork me on GitHub
3 |
4 |
33 |
--------------------------------------------------------------------------------
/_includes/icon-github.html:
--------------------------------------------------------------------------------
1 | {% include icon-github.svg %} {{ include.username }}
2 |
--------------------------------------------------------------------------------
/_includes/icon-github.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/_includes/icon-twitter.html:
--------------------------------------------------------------------------------
1 | {{ include.username }}
2 |
--------------------------------------------------------------------------------
/_includes/icon-twitter.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/_layouts/default.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {% include head.html %}
5 |
6 |
7 |
8 | {% include header.html %}
9 |
10 |
11 |
12 | {{ content }}
13 |
14 |
15 |
16 | {% include footer.html %}
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/_layouts/page.html:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | ---
4 |
5 |
6 |
7 |
10 |
11 |
12 | {{ content }}
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/_sass/minima/_base.scss:
--------------------------------------------------------------------------------
1 | /**
2 | * Reset some basic elements
3 | */
4 | body, h1, h2, h3, h4, h5, h6,
5 | p, blockquote, pre, hr,
6 | dl, dd, ol, ul, figure {
7 | margin: 0;
8 | padding: 0;
9 | }
10 |
11 |
12 |
13 | /**
14 | * Basic styling
15 | */
16 | body {
17 | font: $base-font-weight #{$base-font-size}/#{$base-line-height} $base-font-family;
18 | color: $text-color;
19 | background-color: $background-color;
20 | -webkit-text-size-adjust: 100%;
21 | -webkit-font-feature-settings: "kern" 1;
22 | -moz-font-feature-settings: "kern" 1;
23 | -o-font-feature-settings: "kern" 1;
24 | font-feature-settings: "kern" 1;
25 | font-kerning: normal;
26 | overflow-x: hidden;
27 | }
28 |
29 |
30 |
31 | /**
32 | * Set `margin-bottom` to maintain vertical rhythm
33 | */
34 | h1, h2, h3, h4, h5, h6,
35 | p, blockquote, pre,
36 | ul, ol, dl, figure,
37 | %vertical-rhythm {
38 | margin-bottom: $spacing-unit / 2;
39 | }
40 |
41 | hr {
42 | background-image: linear-gradient(to right, rgba(51, 77, 92, 0), rgba(51, 77, 92, 0.75), rgba(51, 77, 92, 0));
43 | border: 0;
44 | height: 1px;
45 | margin: 5% 0;
46 | }
47 |
48 |
49 |
50 | /**
51 | * Images
52 | */
53 | img {
54 | max-width: 100%;
55 | vertical-align: middle;
56 | }
57 |
58 |
59 |
60 | /**
61 | * Figures
62 | */
63 | figure > img {
64 | display: block;
65 | }
66 |
67 | figcaption {
68 | font-size: $small-font-size;
69 | }
70 |
71 |
72 |
73 | /**
74 | * Lists
75 | */
76 | ul, ol {
77 | margin-left: $spacing-unit;
78 | }
79 |
80 | li {
81 | > ul,
82 | > ol {
83 | margin-bottom: 0;
84 | }
85 | }
86 |
87 |
88 |
89 | /**
90 | * Headings
91 | */
92 | h1, h2, h3, h4, h5, h6 {
93 | font-weight: $base-font-weight;
94 | }
95 |
96 |
97 |
98 | /**
99 | * Links
100 | */
101 | a {
102 | color: $brand-color;
103 | text-decoration: none;
104 |
105 | &:visited {
106 | color: darken($brand-color, 15%);
107 | }
108 |
109 | &:hover {
110 | color: $text-color;
111 | text-decoration: underline;
112 | }
113 | }
114 |
115 |
116 |
117 | /**
118 | * Blockquotes
119 | */
120 | blockquote {
121 | color: $blue;
122 | border-left: 4px solid $yellow-1;
123 | padding-left: $spacing-unit / 2;
124 | font-size: 18px;
125 | letter-spacing: -1px;
126 | font-style: italic;
127 |
128 | > :last-child {
129 | margin-bottom: 0;
130 | }
131 | }
132 |
133 |
134 |
135 | /**
136 | * Code formatting
137 | */
138 | pre,
139 | code {
140 | font-size: 15px;
141 | border: 1px solid $blue;
142 | border-radius: 3px;
143 | background-color: $white;
144 | }
145 |
146 | code {
147 | padding: 1px 5px;
148 | }
149 |
150 | pre {
151 | padding: 8px 12px;
152 | overflow-x: auto;
153 |
154 | > code {
155 | border: 0;
156 | padding-right: 0;
157 | padding-left: 0;
158 | }
159 | }
160 |
161 |
162 |
163 | /**
164 | * Wrapper
165 | */
166 | .wrapper {
167 | max-width: -webkit-calc(#{$content-width} - (#{$spacing-unit} * 2));
168 | max-width: calc(#{$content-width} - (#{$spacing-unit} * 2));
169 | margin-right: auto;
170 | margin-left: auto;
171 | padding-right: $spacing-unit;
172 | padding-left: $spacing-unit;
173 | @extend %clearfix;
174 |
175 | @include media-query($on-laptop) {
176 | max-width: -webkit-calc(#{$content-width} - (#{$spacing-unit}));
177 | max-width: calc(#{$content-width} - (#{$spacing-unit}));
178 | padding-right: $spacing-unit / 2;
179 | padding-left: $spacing-unit / 2;
180 | }
181 | }
182 |
183 |
184 |
185 | /**
186 | * Clearfix
187 | */
188 | %clearfix:after {
189 | content: "";
190 | display: table;
191 | clear: both;
192 | }
193 |
194 |
195 |
196 | /**
197 | * Icons
198 | */
199 | .icon > svg {
200 | display: inline-block;
201 | vertical-align: middle;
202 |
203 | path {
204 | fill: $blue;
205 | }
206 | }
207 |
--------------------------------------------------------------------------------
/_sass/minima/_layout.scss:
--------------------------------------------------------------------------------
1 | /**
2 | * Site header
3 | */
4 | .site-header {
5 | background-color: $blue;
6 | border-top: 5px solid $red-2;
7 | border-bottom: 1px solid $yellow-4;
8 | min-height: 56px;
9 |
10 | // Positioning context for the mobile navigation icon
11 | position: relative;
12 | }
13 |
14 | .site-title {
15 | font-size: 26px;
16 | font-weight: 300;
17 | line-height: 56px;
18 | letter-spacing: -1px;
19 | margin-bottom: 0;
20 | float: left;
21 |
22 | &,
23 | &:visited {
24 | color: $white;
25 | }
26 | }
27 |
28 | .site-nav {
29 | float: right;
30 | line-height: 56px;
31 |
32 | .menu-icon {
33 | display: none;
34 | }
35 |
36 | .page-link {
37 | color: $white;
38 | line-height: $base-line-height;
39 |
40 | // Gaps between nav items, but not on the last one
41 | &:not(:last-child) {
42 | margin-right: 20px;
43 | }
44 | }
45 |
46 | @include media-query($on-palm) {
47 | position: absolute;
48 | top: 9px;
49 | right: $spacing-unit / 2;
50 | background-color: $background-color;
51 | border: 1px solid $blue;
52 | border-radius: 5px;
53 | text-align: right;
54 |
55 | .menu-icon {
56 | display: block;
57 | float: right;
58 | width: 36px;
59 | height: 26px;
60 | line-height: 0;
61 | padding-top: 10px;
62 | text-align: center;
63 |
64 | > svg path {
65 | fill: $blue;
66 | }
67 | }
68 |
69 | .trigger {
70 | clear: both;
71 | display: none;
72 | }
73 |
74 | &:hover .trigger {
75 | display: block;
76 | padding-bottom: 5px;
77 | }
78 |
79 | .page-link {
80 | color: $blue;
81 | display: block;
82 | padding: 5px 10px;
83 |
84 | &:not(:last-child) {
85 | margin-right: 0;
86 | }
87 | margin-left: 20px;
88 | }
89 | }
90 | }
91 |
92 |
93 |
94 | /**
95 | * Site footer
96 | */
97 | .site-footer {
98 | border-top: 1px solid $yellow-4;
99 | padding: $spacing-unit 0;
100 | }
101 |
102 | .footer-heading {
103 | font-size: 18px;
104 | margin-bottom: $spacing-unit / 2;
105 | }
106 |
107 | .contact-list,
108 | .social-media-list {
109 | list-style: none;
110 | margin-left: 0;
111 | }
112 |
113 | .footer-col-wrapper {
114 | font-size: 15px;
115 | color: $blue;
116 | margin-left: -$spacing-unit / 2;
117 | @extend %clearfix;
118 | }
119 |
120 | .footer-col {
121 | float: left;
122 | margin-bottom: $spacing-unit / 2;
123 | padding-left: $spacing-unit / 2;
124 | }
125 |
126 | .footer-col-1 {
127 | width: -webkit-calc(35% - (#{$spacing-unit} / 2));
128 | width: calc(35% - (#{$spacing-unit} / 2));
129 | }
130 |
131 | .footer-col-2 {
132 | width: -webkit-calc(20% - (#{$spacing-unit} / 2));
133 | width: calc(20% - (#{$spacing-unit} / 2));
134 | }
135 |
136 | .footer-col-3 {
137 | width: -webkit-calc(45% - (#{$spacing-unit} / 2));
138 | width: calc(45% - (#{$spacing-unit} / 2));
139 | }
140 |
141 | @include media-query($on-laptop) {
142 | .footer-col-1,
143 | .footer-col-2 {
144 | width: -webkit-calc(50% - (#{$spacing-unit} / 2));
145 | width: calc(50% - (#{$spacing-unit} / 2));
146 | }
147 |
148 | .footer-col-3 {
149 | width: -webkit-calc(100% - (#{$spacing-unit} / 2));
150 | width: calc(100% - (#{$spacing-unit} / 2));
151 | }
152 | }
153 |
154 | @include media-query($on-palm) {
155 | .footer-col {
156 | float: none;
157 | width: -webkit-calc(100% - (#{$spacing-unit} / 2));
158 | width: calc(100% - (#{$spacing-unit} / 2));
159 | }
160 | }
161 |
162 |
163 |
164 | /**
165 | * Page content
166 | */
167 | .page-content {
168 | padding: $spacing-unit 0;
169 | }
170 |
171 | .page-heading {
172 | font-size: 20px;
173 | }
174 |
175 | .post-list {
176 | margin-left: 0;
177 | list-style: none;
178 |
179 | > li {
180 | margin-bottom: $spacing-unit;
181 | }
182 | }
183 |
184 | .post-meta {
185 | font-size: $small-font-size;
186 | color: $blue;
187 | }
188 |
189 | .post-link {
190 | display: block;
191 | font-size: 24px;
192 | }
193 |
194 |
195 |
196 | /**
197 | * Custom
198 | */
199 | .github-fork-ribbon {
200 | &:before {
201 | background-color: $red-1;
202 | }
203 |
204 | @include media-query($on-palm) {
205 | display: none;
206 | }
207 | }
208 |
209 | #home-banner {
210 | text-align: center;
211 | }
212 |
213 | #home-logo {
214 | margin-bottom: 4%;
215 | width: 30%;
216 | }
217 |
218 |
219 |
220 | /**
221 | * Inputs
222 | */
223 |
224 | input {
225 | outline: none;
226 | }
227 |
228 | #magnet-input {
229 | margin-bottom: $spacing-unit / 2;
230 | text-align: center;
231 |
232 | input,
233 | button {
234 | border: 1px solid $red-2;
235 | }
236 |
237 | input {
238 | padding: 12px;
239 | }
240 |
241 | button {
242 | background-color: $red-1;
243 | color: $yellow-1;
244 | padding: 12px 20px;
245 | margin-left: -1px;
246 | }
247 | }
248 |
249 |
250 |
251 | /**
252 | * Clipboard.js
253 | */
254 | .clippy {
255 | margin-top: -4px;
256 | width: 15px;
257 | }
258 |
259 | #share-clipboard {
260 | p {
261 | margin-bottom: 0;
262 | }
263 |
264 | input,
265 | button {
266 | background-color: $white;
267 | border: 1px solid $blue;
268 | padding: 8px;
269 | }
270 |
271 | button {
272 | background-color: $yellow-1;
273 | margin-left: -1px;
274 | }
275 | }
276 |
--------------------------------------------------------------------------------
/_sass/minima/_syntax-highlighting.scss:
--------------------------------------------------------------------------------
1 | /**
2 | * Syntax highlighting styles
3 | */
4 | .highlight {
5 | background: #fff;
6 | @extend %vertical-rhythm;
7 |
8 | .highlighter-rouge & {
9 | background: #eef;
10 | }
11 |
12 | .c { color: #998; font-style: italic } // Comment
13 | .err { color: #a61717; background-color: #e3d2d2 } // Error
14 | .k { font-weight: bold } // Keyword
15 | .o { font-weight: bold } // Operator
16 | .cm { color: #998; font-style: italic } // Comment.Multiline
17 | .cp { color: #999; font-weight: bold } // Comment.Preproc
18 | .c1 { color: #998; font-style: italic } // Comment.Single
19 | .cs { color: #999; font-weight: bold; font-style: italic } // Comment.Special
20 | .gd { color: #000; background-color: #fdd } // Generic.Deleted
21 | .gd .x { color: #000; background-color: #faa } // Generic.Deleted.Specific
22 | .ge { font-style: italic } // Generic.Emph
23 | .gr { color: #a00 } // Generic.Error
24 | .gh { color: #999 } // Generic.Heading
25 | .gi { color: #000; background-color: #dfd } // Generic.Inserted
26 | .gi .x { color: #000; background-color: #afa } // Generic.Inserted.Specific
27 | .go { color: #888 } // Generic.Output
28 | .gp { color: #555 } // Generic.Prompt
29 | .gs { font-weight: bold } // Generic.Strong
30 | .gu { color: #aaa } // Generic.Subheading
31 | .gt { color: #a00 } // Generic.Traceback
32 | .kc { font-weight: bold } // Keyword.Constant
33 | .kd { font-weight: bold } // Keyword.Declaration
34 | .kp { font-weight: bold } // Keyword.Pseudo
35 | .kr { font-weight: bold } // Keyword.Reserved
36 | .kt { color: #458; font-weight: bold } // Keyword.Type
37 | .m { color: #099 } // Literal.Number
38 | .s { color: #d14 } // Literal.String
39 | .na { color: #008080 } // Name.Attribute
40 | .nb { color: #0086B3 } // Name.Builtin
41 | .nc { color: #458; font-weight: bold } // Name.Class
42 | .no { color: #008080 } // Name.Constant
43 | .ni { color: #800080 } // Name.Entity
44 | .ne { color: #900; font-weight: bold } // Name.Exception
45 | .nf { color: #900; font-weight: bold } // Name.Function
46 | .nn { color: #555 } // Name.Namespace
47 | .nt { color: #000080 } // Name.Tag
48 | .nv { color: #008080 } // Name.Variable
49 | .ow { font-weight: bold } // Operator.Word
50 | .w { color: #bbb } // Text.Whitespace
51 | .mf { color: #099 } // Literal.Number.Float
52 | .mh { color: #099 } // Literal.Number.Hex
53 | .mi { color: #099 } // Literal.Number.Integer
54 | .mo { color: #099 } // Literal.Number.Oct
55 | .sb { color: #d14 } // Literal.String.Backtick
56 | .sc { color: #d14 } // Literal.String.Char
57 | .sd { color: #d14 } // Literal.String.Doc
58 | .s2 { color: #d14 } // Literal.String.Double
59 | .se { color: #d14 } // Literal.String.Escape
60 | .sh { color: #d14 } // Literal.String.Heredoc
61 | .si { color: #d14 } // Literal.String.Interpol
62 | .sx { color: #d14 } // Literal.String.Other
63 | .sr { color: #009926 } // Literal.String.Regex
64 | .s1 { color: #d14 } // Literal.String.Single
65 | .ss { color: #990073 } // Literal.String.Symbol
66 | .bp { color: #999 } // Name.Builtin.Pseudo
67 | .vc { color: #008080 } // Name.Variable.Class
68 | .vg { color: #008080 } // Name.Variable.Global
69 | .vi { color: #008080 } // Name.Variable.Instance
70 | .il { color: #099 } // Literal.Number.Integer.Long
71 | }
72 |
--------------------------------------------------------------------------------
/_sass/player.scss:
--------------------------------------------------------------------------------
1 | #hero {
2 | background-color: $blue;
3 | display: none;
4 | text-align: center;
5 | }
6 |
7 | #output video {
8 | width: 100%;
9 | }
10 |
11 | #progressBar {
12 | height: 5px;
13 | width: 0%;
14 | background-color: $red-1;
15 | transition: width .4s ease-in-out;
16 | }
17 |
18 | #status {
19 | color: $white;
20 | padding: $spacing-unit / 2;
21 |
22 | > div {
23 | margin-bottom: $spacing-unit / 2;
24 | }
25 |
26 | > div:first-child {
27 | overflow-x: auto;
28 | }
29 |
30 | .tooltip {
31 | margin: initial;
32 | }
33 | }
34 |
35 | #status code {
36 | color: $blue;
37 | }
38 |
39 | body.is-seed .show-seed {
40 | display: inline;
41 | }
42 |
43 | body.is-seed .show-leech {
44 | display: none;
45 | }
46 |
47 | .show-seed {
48 | display: none;
49 | }
50 |
51 | .is-seed #hero {
52 | transition: .5s .5s background-color ease-in-out;
53 | }
54 |
--------------------------------------------------------------------------------
/about.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: page
3 | title: About
4 | permalink: /about/
5 | ---
6 |
7 | **Magnet Player** is a site where anyone can stream torrents directly from their browser.
8 |
9 | It uses **[WebTorrent](https://webtorrent.io/)** - the first torrent client that works in the browser. **WebTorrent** uses **[WebRTC](https://webrtc.org/)** for true peer-to-peer transport. No browser plugin, extension, or installation is required.
10 |
11 | ---
12 |
13 | ### Note
14 |
15 | *In the browser, WebTorrent can only download torrents that are seeded by a WebRTC-capable torrent client.*
16 |
17 | > What does that mean?
18 |
19 | It means that, for now, not every torrent will work on this site.
20 |
21 | > Why??
22 |
23 | Because most people use native torrent clients like *BitTorrent*, *Transmission*, *μTorrent*, etc. which do not use the [WebRTC](https://en.wikipedia.org/wiki/WebRTC) transport protocol, but the [TCP](https://en.wikipedia.org/wiki/Transmission_Control_Protocol)/[uTP](https://en.wikipedia.org/wiki/Micro_Transport_Protocol).
24 |
25 | > Will I be able to stream more torrents in the future?
26 |
27 | **Yes!** It is just a matter of time until developers add WebTorrent support for the most popular native torrent clients. **[Vuze](http://www.vuze.com/)** [already has support](https://wiki.vuze.com/w/WebTorrent) for WebTorrent!
28 |
29 | You can subscribe to [this issue](https://github.com/feross/webtorrent/issues/369) for updates on this matter.
30 |
--------------------------------------------------------------------------------
/assets/clippy.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/assets/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | image/svg+xml
--------------------------------------------------------------------------------
/assets/thumbnail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ferrolho/magnet-player/982f6c96a452ed8cc1e69d1113bc2a4a750309e8/assets/thumbnail.png
--------------------------------------------------------------------------------
/css/bootstrap.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap v3.3.7 (http://getbootstrap.com)
3 | * Copyright 2011-2016 Twitter, Inc.
4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
5 | */
6 |
7 | /*!
8 | * Generated using the Bootstrap Customizer (http://getbootstrap.com/customize/?id=da4a322ddaee8f2658555461739c3a29)
9 | * Config saved to config.json and https://gist.github.com/da4a322ddaee8f2658555461739c3a29
10 | */
11 | /*!
12 | * Bootstrap v3.3.7 (http://getbootstrap.com)
13 | * Copyright 2011-2016 Twitter, Inc.
14 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
15 | */
16 | /*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */
17 | button,
18 | html input[type="button"],
19 | input[type="reset"],
20 | input[type="submit"] {
21 | -webkit-appearance: button;
22 | cursor: pointer;
23 | }
24 | [role="button"] {
25 | cursor: pointer;
26 | }
27 | .tooltip {
28 | position: absolute;
29 | z-index: 1070;
30 | display: block;
31 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
32 | font-style: normal;
33 | font-weight: normal;
34 | letter-spacing: normal;
35 | line-break: auto;
36 | line-height: 1.42857143;
37 | text-align: left;
38 | text-align: start;
39 | text-decoration: none;
40 | text-shadow: none;
41 | text-transform: none;
42 | white-space: normal;
43 | word-break: normal;
44 | word-spacing: normal;
45 | word-wrap: normal;
46 | font-size: 12px;
47 | opacity: 0;
48 | filter: alpha(opacity=0);
49 | }
50 | .tooltip.in {
51 | opacity: 0.9;
52 | filter: alpha(opacity=90);
53 | }
54 | .tooltip.top {
55 | margin-top: -3px;
56 | padding: 5px 0;
57 | }
58 | .tooltip.right {
59 | margin-left: 3px;
60 | padding: 0 5px;
61 | }
62 | .tooltip.bottom {
63 | margin-top: 3px;
64 | padding: 5px 0;
65 | }
66 | .tooltip.left {
67 | margin-left: -3px;
68 | padding: 0 5px;
69 | }
70 | .tooltip-inner {
71 | max-width: 200px;
72 | padding: 3px 8px;
73 | color: #ffffff;
74 | text-align: center;
75 | background-color: #000000;
76 | border-radius: 4px;
77 | }
78 | .tooltip-arrow {
79 | position: absolute;
80 | width: 0;
81 | height: 0;
82 | border-color: transparent;
83 | border-style: solid;
84 | }
85 | .tooltip.top .tooltip-arrow {
86 | bottom: 0;
87 | left: 50%;
88 | margin-left: -5px;
89 | border-width: 5px 5px 0;
90 | border-top-color: #000000;
91 | }
92 | .tooltip.top-left .tooltip-arrow {
93 | bottom: 0;
94 | right: 5px;
95 | margin-bottom: -5px;
96 | border-width: 5px 5px 0;
97 | border-top-color: #000000;
98 | }
99 | .tooltip.top-right .tooltip-arrow {
100 | bottom: 0;
101 | left: 5px;
102 | margin-bottom: -5px;
103 | border-width: 5px 5px 0;
104 | border-top-color: #000000;
105 | }
106 | .tooltip.right .tooltip-arrow {
107 | top: 50%;
108 | left: 0;
109 | margin-top: -5px;
110 | border-width: 5px 5px 5px 0;
111 | border-right-color: #000000;
112 | }
113 | .tooltip.left .tooltip-arrow {
114 | top: 50%;
115 | right: 0;
116 | margin-top: -5px;
117 | border-width: 5px 0 5px 5px;
118 | border-left-color: #000000;
119 | }
120 | .tooltip.bottom .tooltip-arrow {
121 | top: 0;
122 | left: 50%;
123 | margin-left: -5px;
124 | border-width: 0 5px 5px;
125 | border-bottom-color: #000000;
126 | }
127 | .tooltip.bottom-left .tooltip-arrow {
128 | top: 0;
129 | right: 5px;
130 | margin-top: -5px;
131 | border-width: 0 5px 5px;
132 | border-bottom-color: #000000;
133 | }
134 | .tooltip.bottom-right .tooltip-arrow {
135 | top: 0;
136 | left: 5px;
137 | margin-top: -5px;
138 | border-width: 0 5px 5px;
139 | border-bottom-color: #000000;
140 | }
141 | .clearfix:before,
142 | .clearfix:after {
143 | content: " ";
144 | display: table;
145 | }
146 | .clearfix:after {
147 | clear: both;
148 | }
149 | .center-block {
150 | display: block;
151 | margin-left: auto;
152 | margin-right: auto;
153 | }
154 | .pull-right {
155 | float: right !important;
156 | }
157 | .pull-left {
158 | float: left !important;
159 | }
160 | .hide {
161 | display: none !important;
162 | }
163 | .show {
164 | display: block !important;
165 | }
166 | .invisible {
167 | visibility: hidden;
168 | }
169 | .text-hide {
170 | font: 0/0 a;
171 | color: transparent;
172 | text-shadow: none;
173 | background-color: transparent;
174 | border: 0;
175 | }
176 | .hidden {
177 | display: none !important;
178 | }
179 | .affix {
180 | position: fixed;
181 | }
182 |
--------------------------------------------------------------------------------
/css/main.scss:
--------------------------------------------------------------------------------
1 | ---
2 | # Only the main Sass file needs front matter (the dashes are enough)
3 | ---
4 | @charset "utf-8";
5 |
6 | // Define defaults for each variable.
7 | $base-font-family: "Helvetica Neue", Helvetica, Arial, sans-serif !default;
8 | $base-font-size: 16px !default;
9 | $base-font-weight: 400 !default;
10 | $small-font-size: $base-font-size * 0.875 !default;
11 | $base-line-height: 1.5 !default;
12 |
13 | $spacing-unit: 30px !default;
14 |
15 | // theme colors (taken from the icon)
16 | $blue: #334d5c;
17 | $white: #e5ddd7;
18 | $red-1: #ea4949;
19 | $red-2: #bf1717;
20 | $yellow-1: #f9e595;
21 | $yellow-2: #efd35b;
22 | $yellow-3: #edc92f;
23 | $yellow-4: #e2ba13;
24 |
25 | $text-color: $blue !default;
26 | $background-color: $yellow-2 !default;
27 | $brand-color: $red-1 !default;
28 |
29 | // Width of the content area
30 | $content-width: 800px !default;
31 |
32 | $on-palm: 600px !default;
33 | $on-laptop: 800px !default;
34 |
35 | // Use media queries like this:
36 | // @include media-query($on-palm) {
37 | // .wrapper {
38 | // padding-right: $spacing-unit / 2;
39 | // padding-left: $spacing-unit / 2;
40 | // }
41 | // }
42 | @mixin media-query($device) {
43 | @media screen and (max-width: $device) {
44 | @content;
45 | }
46 | }
47 |
48 | // Import partials.
49 | @import
50 | "minima/base",
51 | "minima/layout",
52 | "minima/syntax-highlighting",
53 | "player"
54 | ;
55 |
--------------------------------------------------------------------------------
/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ferrolho/magnet-player/982f6c96a452ed8cc1e69d1113bc2a4a750309e8/favicon.png
--------------------------------------------------------------------------------
/feed.xml:
--------------------------------------------------------------------------------
1 | ---
2 | layout: null
3 | ---
4 |
5 |
6 |
7 | {{ site.title | xml_escape }}
8 | {{ site.description | xml_escape }}
9 | {{ site.url }}{{ site.baseurl }}/
10 |
11 | {{ site.time | date_to_rfc822 }}
12 | {{ site.time | date_to_rfc822 }}
13 | Jekyll v{{ jekyll.version }}
14 | {% for post in site.posts limit:10 %}
15 | -
16 |
{{ post.title | xml_escape }}
17 | {{ post.content | xml_escape }}
18 | {{ post.date | date_to_rfc822 }}
19 | {{ post.url | prepend: site.baseurl | prepend: site.url }}
20 | {{ post.url | prepend: site.baseurl | prepend: site.url }}
21 | {% for tag in post.tags %}
22 | {{ tag | xml_escape }}
23 | {% endfor %}
24 | {% for cat in post.categories %}
25 | {{ cat | xml_escape }}
26 | {% endfor %}
27 |
28 | {% endfor %}
29 |
30 |
31 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | ---
4 |
5 |
6 |
7 |
8 |
Stream torrents directly from your browser
9 |
10 |
11 |
12 |
13 |
16 |
17 |
18 |
22 |
23 |
24 |
25 |
26 | Downloading
27 | Seeding
28 |
29 | from
30 | to
31 | 0 peers
32 |
33 |
34 |
35 |
of
-
36 |
37 |
38 |
39 | ↓ 0 b/s
/ 0 b/s
↑
40 |
41 |
42 |
43 |
Share this video:
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | What should I write in the input box above?
53 |
54 |
55 | Find a torrent you want to watch, then copy-paste one of the following into the input box:
56 |
57 |
58 | magnet uri (string)
59 | torrent file (buffer)
60 | info hash (hex string or buffer)
61 | parsed torrent (from parse-torrent)
62 | http/https url to a torrent file (string)
63 |
64 |
65 |
66 | Can you give an example?
67 |
68 |
69 | Sure! Try copy-pasting this https url of a torrent to the input box:
70 |
71 | https://webtorrent.io/torrents/sintel.torrent
72 |
73 |
74 | How can I say thanks?
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/js/bootstrap.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap v3.3.7 (http://getbootstrap.com)
3 | * Copyright 2011-2016 Twitter, Inc.
4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
5 | */
6 |
7 | /*!
8 | * Generated using the Bootstrap Customizer (http://getbootstrap.com/customize/?id=da4a322ddaee8f2658555461739c3a29)
9 | * Config saved to config.json and https://gist.github.com/da4a322ddaee8f2658555461739c3a29
10 | */
11 | if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(t){"use strict";var e=t.fn.jquery.split(" ")[0].split(".");if(e[0]<2&&e[1]<9||1==e[0]&&9==e[1]&&e[2]<1||e[0]>3)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4")}(jQuery),+function(t){"use strict";function e(e){return this.each(function(){var o=t(this),n=o.data("bs.tooltip"),s="object"==typeof e&&e;!n&&/destroy|hide/.test(e)||(n||o.data("bs.tooltip",n=new i(this,s)),"string"==typeof e&&n[e]())})}var i=function(t,e){this.type=null,this.options=null,this.enabled=null,this.timeout=null,this.hoverState=null,this.$element=null,this.inState=null,this.init("tooltip",t,e)};i.VERSION="3.3.7",i.TRANSITION_DURATION=150,i.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},i.prototype.init=function(e,i,o){if(this.enabled=!0,this.type=e,this.$element=t(i),this.options=this.getOptions(o),this.$viewport=this.options.viewport&&t(t.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var n=this.options.trigger.split(" "),s=n.length;s--;){var r=n[s];if("click"==r)this.$element.on("click."+this.type,this.options.selector,t.proxy(this.toggle,this));else if("manual"!=r){var a="hover"==r?"mouseenter":"focusin",l="hover"==r?"mouseleave":"focusout";this.$element.on(a+"."+this.type,this.options.selector,t.proxy(this.enter,this)),this.$element.on(l+"."+this.type,this.options.selector,t.proxy(this.leave,this))}}this.options.selector?this._options=t.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},i.prototype.getDefaults=function(){return i.DEFAULTS},i.prototype.getOptions=function(e){return e=t.extend({},this.getDefaults(),this.$element.data(),e),e.delay&&"number"==typeof e.delay&&(e.delay={show:e.delay,hide:e.delay}),e},i.prototype.getDelegateOptions=function(){var e={},i=this.getDefaults();return this._options&&t.each(this._options,function(t,o){i[t]!=o&&(e[t]=o)}),e},i.prototype.enter=function(e){var i=e instanceof this.constructor?e:t(e.currentTarget).data("bs."+this.type);return i||(i=new this.constructor(e.currentTarget,this.getDelegateOptions()),t(e.currentTarget).data("bs."+this.type,i)),e instanceof t.Event&&(i.inState["focusin"==e.type?"focus":"hover"]=!0),i.tip().hasClass("in")||"in"==i.hoverState?void(i.hoverState="in"):(clearTimeout(i.timeout),i.hoverState="in",i.options.delay&&i.options.delay.show?void(i.timeout=setTimeout(function(){"in"==i.hoverState&&i.show()},i.options.delay.show)):i.show())},i.prototype.isInStateTrue=function(){for(var t in this.inState)if(this.inState[t])return!0;return!1},i.prototype.leave=function(e){var i=e instanceof this.constructor?e:t(e.currentTarget).data("bs."+this.type);return i||(i=new this.constructor(e.currentTarget,this.getDelegateOptions()),t(e.currentTarget).data("bs."+this.type,i)),e instanceof t.Event&&(i.inState["focusout"==e.type?"focus":"hover"]=!1),i.isInStateTrue()?void 0:(clearTimeout(i.timeout),i.hoverState="out",i.options.delay&&i.options.delay.hide?void(i.timeout=setTimeout(function(){"out"==i.hoverState&&i.hide()},i.options.delay.hide)):i.hide())},i.prototype.show=function(){var e=t.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(e);var o=t.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(e.isDefaultPrevented()||!o)return;var n=this,s=this.tip(),r=this.getUID(this.type);this.setContent(),s.attr("id",r),this.$element.attr("aria-describedby",r),this.options.animation&&s.addClass("fade");var a="function"==typeof this.options.placement?this.options.placement.call(this,s[0],this.$element[0]):this.options.placement,l=/\s?auto?\s?/i,p=l.test(a);p&&(a=a.replace(l,"")||"top"),s.detach().css({top:0,left:0,display:"block"}).addClass(a).data("bs."+this.type,this),this.options.container?s.appendTo(this.options.container):s.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var h=this.getPosition(),f=s[0].offsetWidth,u=s[0].offsetHeight;if(p){var c=a,d=this.getPosition(this.$viewport);a="bottom"==a&&h.bottom+u>d.bottom?"top":"top"==a&&h.top-ud.width?"left":"left"==a&&h.left-fr.top+r.height&&(n.top=r.top+r.height-l)}else{var p=e.left-s,h=e.left+s+i;pr.right&&(n.left=r.left+r.width-h)}return n},i.prototype.getTitle=function(){var t,e=this.$element,i=this.options;return t=e.attr("data-original-title")||("function"==typeof i.title?i.title.call(e[0]):i.title)},i.prototype.getUID=function(t){do t+=~~(1e6*Math.random());while(document.getElementById(t));return t},i.prototype.tip=function(){if(!this.$tip&&(this.$tip=t(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},i.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},i.prototype.enable=function(){this.enabled=!0},i.prototype.disable=function(){this.enabled=!1},i.prototype.toggleEnabled=function(){this.enabled=!this.enabled},i.prototype.toggle=function(e){var i=this;e&&(i=t(e.currentTarget).data("bs."+this.type),i||(i=new this.constructor(e.currentTarget,this.getDelegateOptions()),t(e.currentTarget).data("bs."+this.type,i))),e?(i.inState.click=!i.inState.click,i.isInStateTrue()?i.enter(i):i.leave(i)):i.tip().hasClass("in")?i.leave(i):i.enter(i)},i.prototype.destroy=function(){var t=this;clearTimeout(this.timeout),this.hide(function(){t.$element.off("."+t.type).removeData("bs."+t.type),t.$tip&&t.$tip.detach(),t.$tip=null,t.$arrow=null,t.$viewport=null,t.$element=null})};var o=t.fn.tooltip;t.fn.tooltip=e,t.fn.tooltip.Constructor=i,t.fn.tooltip.noConflict=function(){return t.fn.tooltip=o,this}}(jQuery);
--------------------------------------------------------------------------------
/js/clipboard.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * clipboard.js v1.5.12
3 | * https://zenorocha.github.io/clipboard.js
4 | *
5 | * Licensed MIT © Zeno Rocha
6 | */
7 | !function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,e.Clipboard=t()}}(function(){var t,e,n;return function t(e,n,o){function i(a,c){if(!n[a]){if(!e[a]){var s="function"==typeof require&&require;if(!c&&s)return s(a,!0);if(r)return r(a,!0);var l=new Error("Cannot find module '"+a+"'");throw l.code="MODULE_NOT_FOUND",l}var u=n[a]={exports:{}};e[a][0].call(u.exports,function(t){var n=e[a][1][t];return i(n?n:t)},u,u.exports,t,e,n,o)}return n[a].exports}for(var r="function"==typeof require&&require,a=0;ao;o++)n[o].fn.apply(n[o].ctx,e);return this},off:function(t,e){var n=this.e||(this.e={}),o=n[t],i=[];if(o&&e)for(var r=0,a=o.length;a>r;r++)o[r].fn!==e&&o[r].fn._!==e&&i.push(o[r]);return i.length?n[t]=i:delete n[t],this}},e.exports=o},{}],8:[function(e,n,o){!function(i,r){if("function"==typeof t&&t.amd)t(["module","select"],r);else if("undefined"!=typeof o)r(n,e("select"));else{var a={exports:{}};r(a,i.select),i.clipboardAction=a.exports}}(this,function(t,e){"use strict";function n(t){return t&&t.__esModule?t:{"default":t}}function o(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}var i=n(e),r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol?"symbol":typeof t},a=function(){function t(t,e){for(var n=0;n 0)
49 | downloadTorrent(torrentId)
50 | })
51 |
52 | // Download by URL hash
53 | onHashChange()
54 | window.addEventListener('hashchange', onHashChange)
55 | function onHashChange () {
56 | var hash = decodeURIComponent(window.location.hash.substring(1)).trim()
57 | if (hash !== '') downloadTorrent(hash)
58 | }
59 |
60 | function downloadTorrent(torrentId) {
61 | console.log('Downloading torrent from ' + torrentId)
62 | client.add(torrentId, onTorrent)
63 | }
64 |
65 | function onTorrent(torrent) {
66 | torrent.on('warning', console.log)
67 | torrent.on('error', console.log)
68 |
69 | console.log('Got torrent metadata!')
70 |
71 | // Find largest file
72 | var largestFile = torrent.files[0]
73 | for (var i = 1; i < torrent.files.length; i++) {
74 | if (torrent.files[i].length > largestFile.length)
75 | largestFile = torrent.files[i]
76 | }
77 |
78 | // Display name of the file being streamed
79 | $streamedFileName.html(largestFile.name)
80 |
81 | // Update clipboard share url
82 | $('#share-url').val('https://ferrolho.github.io/magnet-player/#' + torrent.infoHash);
83 |
84 | // Stream the file in the browser
85 | largestFile.appendTo('#output')
86 |
87 | // hide magnet input
88 | $('#magnet-input').slideUp()
89 |
90 | // show player
91 | $('#hero').slideDown()
92 |
93 | // Trigger statistics refresh
94 | torrent.on('done', onDone)
95 | setInterval(onProgress, 500)
96 | onProgress()
97 |
98 | // Statistics
99 | function onProgress () {
100 | // Peers
101 | $numPeers.html(torrent.numPeers + (torrent.numPeers === 1 ? ' peer' : ' peers'))
102 |
103 | // Progress
104 | var percent = Math.round(torrent.progress * 100 * 100) / 100
105 | $progressBar.width(percent + '%')
106 | $downloaded.html(prettyBytes(torrent.downloaded))
107 | $total.html(prettyBytes(torrent.length))
108 |
109 | // Remaining time
110 | var remaining
111 | if (torrent.done) {
112 | remaining = 'Done'
113 | } else {
114 | remaining = moment.duration(torrent.timeRemaining / 1000, 'seconds').humanize()
115 | remaining = remaining[0].toUpperCase() + remaining.substring(1) + ' remaining'
116 | }
117 | $remaining.html(remaining)
118 |
119 | // Speed rates
120 | $downloadSpeed.html(prettyBytes(torrent.downloadSpeed) + '/s')
121 | $uploadSpeed.html(prettyBytes(torrent.uploadSpeed) + '/s')
122 | }
123 |
124 | function onDone () {
125 | $body.addClass('is-seed')
126 | onProgress()
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "magnet-player",
3 | "description": "Video streaming directly from your browser",
4 | "version": "1.0.1",
5 | "author": {
6 | "name": "Henrique Ferrolho",
7 | "email": "henrique.ferrolho@gmail.com",
8 | "url": "http://ferrolho.github.io/"
9 | },
10 | "bugs": {
11 | "url": "https://github.com/ferrolho/magnet-player/issues"
12 | },
13 | "dependencies": {
14 | "clipboard": "^1.5.12",
15 | "moment": "^2.15.0",
16 | "pretty-bytes": "^4.0.2"
17 | },
18 | "homepage": "https://ferrolho.github.io/magnet-player/",
19 | "keywords": [
20 | "data channel",
21 | "file transfer",
22 | "p2p",
23 | "webrtc"
24 | ],
25 | "license": "MIT"
26 | }
27 |
--------------------------------------------------------------------------------