Compare commits
2451 Commits
2.5.1
...
dependabot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fef8ad5215 | ||
|
|
938dac703e | ||
|
|
8ca0b2b4dd | ||
|
|
49fceb761c | ||
|
|
bc3328db2b | ||
|
|
9d9c783244 | ||
|
|
ad96e147b1 | ||
|
|
eb0cd96995 | ||
|
|
41a2964533 | ||
|
|
dcf581bb06 | ||
|
|
5e938e8bb2 | ||
|
|
612a76ebf6 | ||
|
|
d228cf223d | ||
|
|
f5d9272a42 | ||
|
|
50694e32db | ||
|
|
ff37946397 | ||
|
|
df353968a6 | ||
|
|
dc7435b4c1 | ||
|
|
82f6e5ed12 | ||
|
|
29c8d2c84b | ||
|
|
b47e38dce4 | ||
|
|
89c4a59ca4 | ||
|
|
116cb3f68d | ||
|
|
13bc8cb0ba | ||
|
|
9ed72c0cc0 | ||
|
|
ad8bc0c05b | ||
|
|
9993a377b8 | ||
|
|
0213c5fe0a | ||
|
|
d820b2daba | ||
|
|
3739a15049 | ||
|
|
cba874510b | ||
|
|
b3a7b95fd6 | ||
|
|
f9b05c11e0 | ||
|
|
e8d49c77df | ||
|
|
bd9815927b | ||
|
|
07164153b0 | ||
|
|
116a1e8905 | ||
|
|
206321a46f | ||
|
|
4b0680e366 | ||
|
|
bcb5641f90 | ||
|
|
460d0138f0 | ||
|
|
6289f73844 | ||
|
|
4d96763545 | ||
|
|
6ed67ffee6 | ||
|
|
d3e72202ce | ||
|
|
6369c55252 | ||
|
|
74b18b99a0 | ||
|
|
c144119395 | ||
|
|
384d3bb6c6 | ||
|
|
d65fa07ce1 | ||
|
|
1594bafb60 | ||
|
|
9d6a07dbec | ||
|
|
5a769810c0 | ||
|
|
9e6f302d45 | ||
|
|
ba98375bf9 | ||
|
|
17a998fcbc | ||
|
|
6cfab8aebc | ||
|
|
7b002c528e | ||
|
|
684c49c7c6 | ||
|
|
d7d1416c9c | ||
|
|
4301c989f0 | ||
|
|
725c8e5385 | ||
|
|
a5174c9b92 | ||
|
|
702c585bb8 | ||
|
|
0b3357e752 | ||
|
|
e59f332689 | ||
|
|
72cfbe26c1 | ||
|
|
39d10745a1 | ||
|
|
632bcef2ef | ||
|
|
4106b30ac4 | ||
|
|
7941614ae7 | ||
|
|
cfd0dc88fd | ||
|
|
76dea850a6 | ||
|
|
1e7153b995 | ||
|
|
80db2f7068 | ||
|
|
7bab1fac16 | ||
|
|
50704be17b | ||
|
|
9725f1d7f1 | ||
|
|
580ab99a72 | ||
|
|
b3c8540bd6 | ||
|
|
7b0e6a0fdf | ||
|
|
54c7009fda | ||
|
|
4fab433f61 | ||
|
|
e2b2801728 | ||
|
|
212eeedf02 | ||
|
|
9e8eed8dab | ||
|
|
449e7cc8d1 | ||
|
|
86fe2ba6c9 | ||
|
|
a97aa6d3e3 | ||
|
|
4c3bb9b436 | ||
|
|
d95ce57910 | ||
|
|
f3547cc028 | ||
|
|
8123c71185 | ||
|
|
dc3bd12f69 | ||
|
|
c8614bef52 | ||
|
|
dfc49156f5 | ||
|
|
7c57dfaf98 | ||
|
|
017ecc0b94 | ||
|
|
1ea1221a76 | ||
|
|
2f3edfb64c | ||
|
|
a8363ebbd2 | ||
|
|
55a0b678d6 | ||
|
|
b703a6ae76 | ||
|
|
bdcd8a197c | ||
|
|
e58f569f80 | ||
|
|
cff3faf820 | ||
|
|
d5c39b467e | ||
|
|
ad06f3c9d7 | ||
|
|
c22a7cf32b | ||
|
|
1c05a1c3b2 | ||
|
|
af92dd0e3a | ||
|
|
73b971cab2 | ||
|
|
ba7c5f4f54 | ||
|
|
1921090255 | ||
|
|
23954faa86 | ||
|
|
066480458d | ||
|
|
4ba9d0bca3 | ||
|
|
f5a992dde0 | ||
|
|
db89a5c55b | ||
|
|
b3dc00abb1 | ||
|
|
c3bfac72c6 | ||
|
|
1a66320029 | ||
|
|
6c0c110b68 | ||
|
|
c66d6efa76 | ||
|
|
46f0882a63 | ||
|
|
e111c9e2ca | ||
|
|
c8fec1894b | ||
|
|
8970092017 | ||
|
|
a6e064072c | ||
|
|
991b8f9ef2 | ||
|
|
903532b2fd | ||
|
|
4589299f52 | ||
|
|
b7eeefa634 | ||
|
|
436732dd39 | ||
|
|
9b79242246 | ||
|
|
d359c8e0c2 | ||
|
|
9bd4fcdf32 | ||
|
|
e830a4143b | ||
|
|
8bd3f123a5 | ||
|
|
3dcae3f2fd | ||
|
|
b9113a905d | ||
|
|
57b1f3b818 | ||
|
|
ab6f1648e6 | ||
|
|
dd9a58f810 | ||
|
|
3f8f6fc12e | ||
|
|
61aec92617 | ||
|
|
5f3c7890a0 | ||
|
|
6e4d5d0249 | ||
|
|
34bb46c4af | ||
|
|
49ddf5d2c0 | ||
|
|
07e44ec947 | ||
|
|
6385971d3b | ||
|
|
1ff0de31bc | ||
|
|
770e25a88a | ||
|
|
21988a2883 | ||
|
|
b9b71ff7db | ||
|
|
d28e14448a | ||
|
|
bcd00aa93e | ||
|
|
03ca6a9f77 | ||
|
|
b2e9050960 | ||
|
|
697c7fa88f | ||
|
|
b0e3532845 | ||
|
|
d1bcf3ec14 | ||
|
|
5086fb56e6 | ||
|
|
f3aabc3db1 | ||
|
|
9051b5b99f | ||
|
|
d8bf064c50 | ||
|
|
3f63b580ed | ||
|
|
2a06329235 | ||
|
|
69c2dc6a33 | ||
|
|
dbee7398bb | ||
|
|
9a1a341bfa | ||
|
|
664a5de46d | ||
|
|
cad2292269 | ||
|
|
14d8ef51bb | ||
|
|
ef1fed0410 | ||
|
|
ddb55baa3b | ||
|
|
a88da7ccf2 | ||
|
|
69f0007e6d | ||
|
|
932bd6b9f2 | ||
|
|
be4a3dcdc7 | ||
|
|
1849727ff8 | ||
|
|
10f9ff87da | ||
|
|
e21865422d | ||
|
|
e4ca2bb8cf | ||
|
|
77d215f89f | ||
|
|
810c2fe24b | ||
|
|
ae17ae92be | ||
|
|
c679a3ae42 | ||
|
|
cbba57ba05 | ||
|
|
f8ca3ce2a5 | ||
|
|
39449c5f48 | ||
|
|
e8ca18d98e | ||
|
|
866d6a9b26 | ||
|
|
7ec8884fce | ||
|
|
e85c2ce390 | ||
|
|
496c1cdeb2 | ||
|
|
98f6f9b6fb | ||
|
|
03935eb958 | ||
|
|
949de761a3 | ||
|
|
e16135d616 | ||
|
|
be9d74d271 | ||
|
|
2003383967 | ||
|
|
22ee6b6fcf | ||
|
|
6ba4c86ccf | ||
|
|
59dce08075 | ||
|
|
8aeb80dfe5 | ||
|
|
d684efe405 | ||
|
|
f0fc0ed424 | ||
|
|
d4628c6e8f | ||
|
|
dde0586ca3 | ||
|
|
3998817b62 | ||
|
|
d315851667 | ||
|
|
73cec39de0 | ||
|
|
6443974c7a | ||
|
|
6cbf7a211e | ||
|
|
4dcd03d042 | ||
|
|
bb4b21581d | ||
|
|
d53beee004 | ||
|
|
c4211bcab5 | ||
|
|
0aa6910f25 | ||
|
|
1a7ff97e7e | ||
|
|
a898f418a7 | ||
|
|
dbce64547f | ||
|
|
c81fde167f | ||
|
|
cef50a07ef | ||
|
|
269c1cadb7 | ||
|
|
67b98d12ad | ||
|
|
5a352a875e | ||
|
|
9229fc07cf | ||
|
|
9b0f84fbe4 | ||
|
|
082282dd23 | ||
|
|
8e1e28f219 | ||
|
|
f80dbb9d80 | ||
|
|
8376148195 | ||
|
|
4b571b65f0 | ||
|
|
a649f3835a | ||
|
|
112eb1e939 | ||
|
|
d44f93faa8 | ||
|
|
8d7ce5b7c1 | ||
|
|
20e7dbb4fc | ||
|
|
4f26163cdf | ||
|
|
fcea76fd01 | ||
|
|
e2de81e412 | ||
|
|
d7b4cbcbd1 | ||
|
|
10cca16415 | ||
|
|
f0e1e26cc3 | ||
|
|
ceb70a0996 | ||
|
|
8f09eb8d66 | ||
|
|
d74a6694a8 | ||
|
|
a6e49995e6 | ||
|
|
57674c17e7 | ||
|
|
00a2740406 | ||
|
|
2b020ad4c2 | ||
|
|
2f62b40ce4 | ||
|
|
351daf74c5 | ||
|
|
e41b98fbdb | ||
|
|
74d5f958e5 | ||
|
|
8f985d5da0 | ||
|
|
71f1826435 | ||
|
|
8f46eabbaf | ||
|
|
03f68d3131 | ||
|
|
fb4e190b6e | ||
|
|
32a741b147 | ||
|
|
88bb45f390 | ||
|
|
a42e340819 | ||
|
|
7ef4ea7079 | ||
|
|
00641806c8 | ||
|
|
048255cb1d | ||
|
|
3c1a485f83 | ||
|
|
2e8da96706 | ||
|
|
5333b4bc13 | ||
|
|
f3c079726a | ||
|
|
8e3a3f679e | ||
|
|
90538377fb | ||
|
|
f34ac9699e | ||
|
|
b802a0af3d | ||
|
|
7ca8d91a0e | ||
|
|
aa74a10305 | ||
|
|
b537aa1af6 | ||
|
|
bed3febcfa | ||
|
|
a57b3eb8be | ||
|
|
cb8ae6ba2c | ||
|
|
ee2eea789c | ||
|
|
645edee211 | ||
|
|
a08ad36d86 | ||
|
|
81dd783609 | ||
|
|
ab8e53d1e0 | ||
|
|
7e75af57eb | ||
|
|
8faac03fb4 | ||
|
|
d5a1858765 | ||
|
|
106eff4f24 | ||
|
|
8f1a67a513 | ||
|
|
0ccdcd2845 | ||
|
|
d3d03fdb15 | ||
|
|
642f8c273d | ||
|
|
ac5ed63cb9 | ||
|
|
695a4f3648 | ||
|
|
ae05344aa1 | ||
|
|
2563b3c4f1 | ||
|
|
b3825bd093 | ||
|
|
3053e61985 | ||
|
|
1ad6272331 | ||
|
|
ea6ba9e1c1 | ||
|
|
b792f48523 | ||
|
|
5ab5f0f079 | ||
|
|
c0abda2e73 | ||
|
|
de619211fc | ||
|
|
693e30f273 | ||
|
|
3102893e15 | ||
|
|
0a11ff09d9 | ||
|
|
0c86b0e9ee | ||
|
|
e26d277460 | ||
|
|
4aff6360c0 | ||
|
|
a52d355456 | ||
|
|
b152209f05 | ||
|
|
0b3e7177b1 | ||
|
|
5a84a4bc70 | ||
|
|
1f3c98a91b | ||
|
|
f8d06c1744 | ||
|
|
473dde44f1 | ||
|
|
fe727c075f | ||
|
|
6996472854 | ||
|
|
34616c2d53 | ||
|
|
2686074b66 | ||
|
|
5878f57b64 | ||
|
|
de9a43c653 | ||
|
|
c0d36b368c | ||
|
|
2117f839ac | ||
|
|
c0864b3311 | ||
|
|
510ba13b32 | ||
|
|
e1781c4f11 | ||
|
|
24ca0832ba | ||
|
|
6740da6d5c | ||
|
|
c12e633729 | ||
|
|
d501e645f6 | ||
|
|
c136199269 | ||
|
|
7ab5d4f399 | ||
|
|
f19992060e | ||
|
|
8d3dd93436 | ||
|
|
16dd0e34ad | ||
|
|
4a79ae1b7d | ||
|
|
f08f63edfc | ||
|
|
58bc3d138f | ||
|
|
0bef149269 | ||
|
|
4e874b79fb | ||
|
|
9e18b85218 | ||
|
|
f1b3ccad98 | ||
|
|
d843ee0993 | ||
|
|
0965060ce3 | ||
|
|
751b5008fb | ||
|
|
c86509b899 | ||
|
|
6f1689ccb0 | ||
|
|
ce3ed5f191 | ||
|
|
7ced63c98d | ||
|
|
e24711ea1c | ||
|
|
742ecfaa1d | ||
|
|
82c6910e62 | ||
|
|
9d0c5173c4 | ||
|
|
39a2fc6532 | ||
|
|
e5221ad88b | ||
|
|
e050e19c5f | ||
|
|
febbc0cfdc | ||
|
|
9cb1ec72db | ||
|
|
ec90e9332c | ||
|
|
83bb97b2f3 | ||
|
|
3e3ef4d6d2 | ||
|
|
c32ccc63eb | ||
|
|
ef30540756 | ||
|
|
dd5f8b6a4b | ||
|
|
12d3e0ddc9 | ||
|
|
82b69350c7 | ||
|
|
db9a63be48 | ||
|
|
54a9a0ed4f | ||
|
|
e92d4ed61a | ||
|
|
38b1a1330c | ||
|
|
498e8e4676 | ||
|
|
0b197dca64 | ||
|
|
a499fa9001 | ||
|
|
26bfca1bb9 | ||
|
|
eb379e6f5c | ||
|
|
06f960e3d4 | ||
|
|
ced5e52223 | ||
|
|
aa871e80e2 | ||
|
|
b121151240 | ||
|
|
990966b18e | ||
|
|
58e5def473 | ||
|
|
fa189967e7 | ||
|
|
1fef8a9831 | ||
|
|
df2bb4809e | ||
|
|
1d061e213f | ||
|
|
f5e9424161 | ||
|
|
5593c5272a | ||
|
|
ce7c821082 | ||
|
|
9e6d8be32e | ||
|
|
a107a740fe | ||
|
|
8e714c838f | ||
|
|
40e40ad298 | ||
|
|
47e40ccb13 | ||
|
|
07bce2c87b | ||
|
|
d791273b15 | ||
|
|
c133b60f19 | ||
|
|
f629c4b362 | ||
|
|
5eade73f54 | ||
|
|
4e9b9d63c3 | ||
|
|
5aa5c2b572 | ||
|
|
21ff54c070 | ||
|
|
7f729c22fd | ||
|
|
31f53e6e32 | ||
|
|
6f5532c37e | ||
|
|
0a205ed714 | ||
|
|
a426cd4ea5 | ||
|
|
9f1e7ca347 | ||
|
|
dde755a2a7 | ||
|
|
0c3ced98f2 | ||
|
|
c3bb5c133e | ||
|
|
0cfa24af2f | ||
|
|
99a03d2314 | ||
|
|
4b7bb87ebf | ||
|
|
ee5337be3d | ||
|
|
2572b42294 | ||
|
|
05c4f4b920 | ||
|
|
0a7ea9f0b2 | ||
|
|
297cc10691 | ||
|
|
62ae1ee802 | ||
|
|
25c7f85203 | ||
|
|
ffc1725535 | ||
|
|
09f3214ad6 | ||
|
|
2255ce861c | ||
|
|
2244c45be3 | ||
|
|
77da0ca1d8 | ||
|
|
7fdcbfe9ff | ||
|
|
e7bb000d47 | ||
|
|
b172e39097 | ||
|
|
ea01cc082a | ||
|
|
3f9c989b6a | ||
|
|
36175fbdf9 | ||
|
|
a9dd4e512b | ||
|
|
e17d3a5bf3 | ||
|
|
fbecb2ccd2 | ||
|
|
2add5d4aae | ||
|
|
c26c490e4e | ||
|
|
0c6a871a46 | ||
|
|
48dfd24400 | ||
|
|
90c62505a6 | ||
|
|
7b6b54e0c9 | ||
|
|
5018c509a3 | ||
|
|
555d0dbe1c | ||
|
|
f89dd49b4b | ||
|
|
6ef1a5e064 | ||
|
|
12efbbcd99 | ||
|
|
d50dacdc76 | ||
|
|
b1412d9fc3 | ||
|
|
e80ce8bdc9 | ||
|
|
0dd5496b71 | ||
|
|
74f7b51742 | ||
|
|
7646f5183b | ||
|
|
0fd4c43ba5 | ||
|
|
836f96f7b2 | ||
|
|
dec569d50d | ||
|
|
3055d53f27 | ||
|
|
d7a2595cf5 | ||
|
|
8c1985bb1a | ||
|
|
690b8f789a | ||
|
|
52fedde073 | ||
|
|
845ef64805 | ||
|
|
0f8f175aa0 | ||
|
|
4048b1346b | ||
|
|
410b255874 | ||
|
|
9d24d389e3 | ||
|
|
7466ef7f61 | ||
|
|
f75a2f0104 | ||
|
|
ef369f6ca6 | ||
|
|
e7517b810e | ||
|
|
1a735e6557 | ||
|
|
3c44a9a879 | ||
|
|
f39a063037 | ||
|
|
c21cdb6046 | ||
|
|
1b86ae514b | ||
|
|
424e4e374c | ||
|
|
4a23770fe3 | ||
|
|
2a8c5fa825 | ||
|
|
2d3ca3acc7 | ||
|
|
cec9575dcc | ||
|
|
4874d468fe | ||
|
|
82be3a6425 | ||
|
|
cc84a02cd2 | ||
|
|
8cd9f8fa5d | ||
|
|
c0bd3de5af | ||
|
|
5dc5590c67 | ||
|
|
d661d99776 | ||
|
|
8a68f798a7 | ||
|
|
3101792420 | ||
|
|
b3ef5834c8 | ||
|
|
e2dc9888ba | ||
|
|
c84af5dfc7 | ||
|
|
950455a688 | ||
|
|
ba8eade984 | ||
|
|
6cf484fa4e | ||
|
|
d7a5b96274 | ||
|
|
d86e403222 | ||
|
|
d060a1c955 | ||
|
|
d6cd183db3 | ||
|
|
1a0abe9cfe | ||
|
|
4c73b411d3 | ||
|
|
fc272a56b8 | ||
|
|
ce15d4e0f3 | ||
|
|
5ffe816106 | ||
|
|
f66611780d | ||
|
|
41814af41b | ||
|
|
cbbbd14c18 | ||
|
|
a6c525cf18 | ||
|
|
aade371c56 | ||
|
|
9d2590e10c | ||
|
|
f3e23bb2cc | ||
|
|
e567fe127b | ||
|
|
47e45c5b19 | ||
|
|
59576d6246 | ||
|
|
6d361db3ad | ||
|
|
10198225f1 | ||
|
|
05d009c1ce | ||
|
|
5568936996 | ||
|
|
cb111fa9f8 | ||
|
|
08017634f9 | ||
|
|
f36a6b23ee | ||
|
|
f5064fe843 | ||
|
|
5f07a8e751 | ||
|
|
02d749e089 | ||
|
|
fe55b4dd63 | ||
|
|
88da20eb18 | ||
|
|
327e69076c | ||
|
|
0c738ffd12 | ||
|
|
2fe0410645 | ||
|
|
dfaa2c7bb3 | ||
|
|
5895352240 | ||
|
|
8d4b01b4a5 | ||
|
|
6de4927298 | ||
|
|
ebf15bc59c | ||
|
|
e5696fcc49 | ||
|
|
78387fc475 | ||
|
|
a3b794c7bf | ||
|
|
82dbc33142 | ||
|
|
35ef8a54b0 | ||
|
|
a7f25ab4a5 | ||
|
|
19a38162be | ||
|
|
752472547e | ||
|
|
20b745d78e | ||
|
|
fc6a58ebb5 | ||
|
|
49f6c7218d | ||
|
|
5610382c01 | ||
|
|
b43527a6af | ||
|
|
1c0294bfb6 | ||
|
|
85de9944a5 | ||
|
|
249855e09b | ||
|
|
4c11618087 | ||
|
|
fa51a5f3b6 | ||
|
|
b8470dcba8 | ||
|
|
7a6d34677d | ||
|
|
c07dadadfa | ||
|
|
a14053c7fc | ||
|
|
185d5ef0b6 | ||
|
|
566decfaea | ||
|
|
9f35001bde | ||
|
|
207b2d9bb3 | ||
|
|
d98121b47e | ||
|
|
2e55bb0fdf | ||
|
|
1a4ba7ee1c | ||
|
|
b9fd06f072 | ||
|
|
45fa9ce233 | ||
|
|
5898c7fbb8 | ||
|
|
f35802e55b | ||
|
|
83943c4f73 | ||
|
|
f290812f6d | ||
|
|
e3a220243c | ||
|
|
ce27b65991 | ||
|
|
78319c2072 | ||
|
|
8e9a76eb48 | ||
|
|
c20dfef95f | ||
|
|
6e09c6d59f | ||
|
|
236d4cd1ec | ||
|
|
b66f70415c | ||
|
|
8a5c425579 | ||
|
|
b135c1390c | ||
|
|
e885640156 | ||
|
|
46996881cb | ||
|
|
861580b383 | ||
|
|
9852da491b | ||
|
|
51876479a3 | ||
|
|
f9a2169f51 | ||
|
|
0b33129851 | ||
|
|
0dd8155447 | ||
|
|
e654390e6d | ||
|
|
f8711c78d1 | ||
|
|
8fa1df9c0a | ||
|
|
a205972fff | ||
|
|
d3dfd0fb82 | ||
|
|
1a21297cd3 | ||
|
|
ef337e9634 | ||
|
|
c6232aa407 | ||
|
|
8227c5a7e3 | ||
|
|
171165e0d3 | ||
|
|
27f030661b | ||
|
|
44b065672d | ||
|
|
049a91ad40 | ||
|
|
c699db6769 | ||
|
|
2d3929b999 | ||
|
|
cc60c48cc4 | ||
|
|
d4957b52f0 | ||
|
|
0a8194263a | ||
|
|
a5048f13a0 | ||
|
|
643fa6bd9b | ||
|
|
ee1c9620ad | ||
|
|
f0afa0dd5d | ||
|
|
5d54e97adf | ||
|
|
0bd654364a | ||
|
|
6fc4db03f6 | ||
|
|
29cb942630 | ||
|
|
096a5acd98 | ||
|
|
be4c48f0ab | ||
|
|
2dcc69d367 | ||
|
|
9a1d39ea24 | ||
|
|
606e283a05 | ||
|
|
0337a17168 | ||
|
|
589c690871 | ||
|
|
c20da5db3b | ||
|
|
458226c7cf | ||
|
|
6d0acaefcb | ||
|
|
dfbce195a0 | ||
|
|
8c29c31449 | ||
|
|
7d6a54ae10 | ||
|
|
689bc85a62 | ||
|
|
1255940682 | ||
|
|
5cd8cd5864 | ||
|
|
b79b0cc168 | ||
|
|
08055bca72 | ||
|
|
3f207e3038 | ||
|
|
debcd787f9 | ||
|
|
836ad10500 | ||
|
|
09f9072ec1 | ||
|
|
caeed28433 | ||
|
|
9f641c4c96 | ||
|
|
6b7bf9f58a | ||
|
|
5af081dc9f | ||
|
|
67356b62d9 | ||
|
|
1a27945752 | ||
|
|
5c12c2f261 | ||
|
|
5fd67867de | ||
|
|
795146af88 | ||
|
|
8e3149c2ee | ||
|
|
f03c53ce2a | ||
|
|
f527f4fa83 | ||
|
|
1aafdf2d86 | ||
|
|
7f22ff2b1d | ||
|
|
65698b02a0 | ||
|
|
f4dfdb32df | ||
|
|
a190e66c23 | ||
|
|
c7de4bd5e3 | ||
|
|
96a56c158d | ||
|
|
f021808d8b | ||
|
|
e20dd72116 | ||
|
|
1e6e507362 | ||
|
|
a550138eef | ||
|
|
2219e14f86 | ||
|
|
e8fb72caf2 | ||
|
|
dea78ffd41 | ||
|
|
eca63eaa8d | ||
|
|
8638685e19 | ||
|
|
1de7341e6e | ||
|
|
b3da558336 | ||
|
|
865ba4ce80 | ||
|
|
4dfe5e061f | ||
|
|
514d45d0bf | ||
|
|
c75537d4b8 | ||
|
|
05860096cd | ||
|
|
73d31021d2 | ||
|
|
4090277c6b | ||
|
|
d3e6af4643 | ||
|
|
d7522cad73 | ||
|
|
061b3832ae | ||
|
|
609f07449e | ||
|
|
0d5eec7b07 | ||
|
|
e4f90e20fd | ||
|
|
3ca6dea8e1 | ||
|
|
9b1876c426 | ||
|
|
9a66bc85ef | ||
|
|
3e2f9e8c8e | ||
|
|
8b9069b8be | ||
|
|
470a31d092 | ||
|
|
8b513f5582 | ||
|
|
42efd8cc8e | ||
|
|
1cb88fa999 | ||
|
|
ba9d96f1eb | ||
|
|
f8edd7c01a | ||
|
|
773b910b98 | ||
|
|
11509d9fbc | ||
|
|
02efd01b87 | ||
|
|
a9358ce360 | ||
|
|
69f29c6157 | ||
|
|
37aea96a95 | ||
|
|
3058e678a8 | ||
|
|
ac8693e650 | ||
|
|
f76f7ae776 | ||
|
|
8703adad14 | ||
|
|
04594ccce2 | ||
|
|
6fa293aba4 | ||
|
|
28f7b36730 | ||
|
|
cf68d52afb | ||
|
|
1881703fd8 | ||
|
|
815a71b2d0 | ||
|
|
4acdcf40b3 | ||
|
|
ece739a481 | ||
|
|
d352f76162 | ||
|
|
4cfcd6a8a2 | ||
|
|
932cb54a09 | ||
|
|
5af7fe2d37 | ||
|
|
526bb36d99 | ||
|
|
8139f786ec | ||
|
|
ec8dd98ccb | ||
|
|
f9fe694987 | ||
|
|
a9eaa282a5 | ||
|
|
1995c20f4e | ||
|
|
6f58e9514c | ||
|
|
23b36b1736 | ||
|
|
6e39f322f2 | ||
|
|
ef92068ea6 | ||
|
|
f7df44d070 | ||
|
|
3ef8a43c3c | ||
|
|
b46e125ff1 | ||
|
|
48099e93d8 | ||
|
|
b79527d681 | ||
|
|
58d26e4197 | ||
|
|
d5244c5162 | ||
|
|
43d5231231 | ||
|
|
893e622ba6 | ||
|
|
fc26aea9d0 | ||
|
|
d879962465 | ||
|
|
181576a0ce | ||
|
|
67ede75ff6 | ||
|
|
2b42ba58d1 | ||
|
|
2f6d68279c | ||
|
|
65fda10d64 | ||
|
|
1ee8fce902 | ||
|
|
7fd4ff0f34 | ||
|
|
28e48c59d6 | ||
|
|
38acd4db1c | ||
|
|
37f71d5f69 | ||
|
|
adb5993ff7 | ||
|
|
25e2cdc707 | ||
|
|
bc13ba9353 | ||
|
|
49f7e5876b | ||
|
|
a97336ea07 | ||
|
|
5826ad60a9 | ||
|
|
c917740d37 | ||
|
|
a6c96a5e78 | ||
|
|
8039ad1da3 | ||
|
|
8459923409 | ||
|
|
f4336bdb6a | ||
|
|
5cfeaa8917 | ||
|
|
1e016ef317 | ||
|
|
d41db9cc76 | ||
|
|
3b5b302a16 | ||
|
|
820dfdb377 | ||
|
|
779e93cca8 | ||
|
|
14ff4b1d81 | ||
|
|
058b235eb7 | ||
|
|
f3db3701c9 | ||
|
|
ddbd2a6381 | ||
|
|
0abae82868 | ||
|
|
319125eab4 | ||
|
|
c620bfd8d6 | ||
|
|
6587f371de | ||
|
|
a858995efb | ||
|
|
3475ec87c7 | ||
|
|
1688c1ae11 | ||
|
|
6636c8481a | ||
|
|
d23386b245 | ||
|
|
476f44c7e2 | ||
|
|
b91a7f17f1 | ||
|
|
8d314e150f | ||
|
|
408f9b4698 | ||
|
|
9eed4b5955 | ||
|
|
832f27922d | ||
|
|
800d63be17 | ||
|
|
e8e04192e7 | ||
|
|
028782d1d4 | ||
|
|
4bc32235df | ||
|
|
c134ccc058 | ||
|
|
da3d3ea83b | ||
|
|
48bb88d8e0 | ||
|
|
51f7477d1a | ||
|
|
9a4ffdc57c | ||
|
|
9c1eeb17d4 | ||
|
|
15112141e0 | ||
|
|
38f7ccc06b | ||
|
|
87aa720ea5 | ||
|
|
ad65119b79 | ||
|
|
25aca3eed3 | ||
|
|
55bc1593af | ||
|
|
031af8fe84 | ||
|
|
f9c95efe5d | ||
|
|
ea8f98ea07 | ||
|
|
a3aea4902b | ||
|
|
07494a6406 | ||
|
|
88a3ecd108 | ||
|
|
b55607ec1d | ||
|
|
2560450a6d | ||
|
|
afde001e8e | ||
|
|
abe6d1f5bb | ||
|
|
9268e5e2e4 | ||
|
|
764abdd19b | ||
|
|
e873ab5406 | ||
|
|
1476c8b0bc | ||
|
|
b1c7d26605 | ||
|
|
c4bacf5663 | ||
|
|
bddb623787 | ||
|
|
051d5df1ac | ||
|
|
3bfc7555e4 | ||
|
|
94182ddaf7 | ||
|
|
bc16ce4398 | ||
|
|
4e77585a27 | ||
|
|
dde19f2225 | ||
|
|
394b73e5d0 | ||
|
|
200ec58773 | ||
|
|
36cb2cd55a | ||
|
|
2b6aee218f | ||
|
|
a44869a3cd | ||
|
|
82d8c0c300 | ||
|
|
36618e34d4 | ||
|
|
89add8c90e | ||
|
|
3bc0aa885f | ||
|
|
0cca053abe | ||
|
|
b6c2a14445 | ||
|
|
5bb3731323 | ||
|
|
c38ec389ac | ||
|
|
0cf6ff51fa | ||
|
|
d5c8aa3dae | ||
|
|
6797cf1a50 | ||
|
|
2ebb35f377 | ||
|
|
077e7de1b8 | ||
|
|
ed55f0768a | ||
|
|
a5b55aa692 | ||
|
|
3720cea40f | ||
|
|
b0a24d9946 | ||
|
|
8bc5d1821e | ||
|
|
7234867531 | ||
|
|
32d0d4f193 | ||
|
|
72a0e7d6b0 | ||
|
|
b8d04d9534 | ||
|
|
9a6ee1baa2 | ||
|
|
c7938f010d | ||
|
|
9912e57148 | ||
|
|
f952f037e8 | ||
|
|
fdc8943260 | ||
|
|
cd0060f565 | ||
|
|
0a1f800659 | ||
|
|
e8dc0d8c2d | ||
|
|
21947a2717 | ||
|
|
99c1b1bd99 | ||
|
|
ee6497db0b | ||
|
|
f3dd0b0063 | ||
|
|
aace2b6549 | ||
|
|
102b15bde5 | ||
|
|
799bd1a223 | ||
|
|
04b44ccda3 | ||
|
|
e574d7542f | ||
|
|
8d7feec269 | ||
|
|
9727ef2039 | ||
|
|
fdbe0c6e92 | ||
|
|
b2a88014ba | ||
|
|
4a9bad6b11 | ||
|
|
f6fd8caa7e | ||
|
|
2463ad3952 | ||
|
|
a5c984f2e0 | ||
|
|
ff4397487a | ||
|
|
37764a4201 | ||
|
|
d8ad959ac5 | ||
|
|
f7664ac32b | ||
|
|
b387250c2d | ||
|
|
ded625ae25 | ||
|
|
a3448e443b | ||
|
|
4bdf9447f1 | ||
|
|
4cc91362db | ||
|
|
a4e73c8392 | ||
|
|
7543ae8414 | ||
|
|
96e61d7e6c | ||
|
|
d8c211c4d3 | ||
|
|
82ac25c5d2 | ||
|
|
9d10397fe5 | ||
|
|
e3c15431c5 | ||
|
|
ea8fedbe46 | ||
|
|
b971074788 | ||
|
|
3c40e8960c | ||
|
|
68c24b6317 | ||
|
|
65f7f50c18 | ||
|
|
fcaa50cfd4 | ||
|
|
db62d92d1c | ||
|
|
aceaa64920 | ||
|
|
5b056f1d15 | ||
|
|
637006ab73 | ||
|
|
084411d591 | ||
|
|
803ecb6a5b | ||
|
|
a920e321c8 | ||
|
|
adc55ee420 | ||
|
|
ee546ade01 | ||
|
|
51a5cc2b13 | ||
|
|
a0c6156852 | ||
|
|
90c8ba353d | ||
|
|
35ff48a15c | ||
|
|
4c26fff033 | ||
|
|
554b936f4d | ||
|
|
80ee5084a9 | ||
|
|
7b9670ac3c | ||
|
|
a0d01484ae | ||
|
|
70d8c19e09 | ||
|
|
120b3a0676 | ||
|
|
2174d9bfd7 | ||
|
|
0531c65ee2 | ||
|
|
b2a5901a11 | ||
|
|
b3fbd88a44 | ||
|
|
757062bb5a | ||
|
|
dacddf6cd7 | ||
|
|
7df2bbe5b9 | ||
|
|
de2607c403 | ||
|
|
9f7f78db51 | ||
|
|
aefafa5527 | ||
|
|
242f6d8363 | ||
|
|
c25b45c314 | ||
|
|
d326cb9e25 | ||
|
|
9db975e9e8 | ||
|
|
4e0e44e365 | ||
|
|
c11927de51 | ||
|
|
7ae17b85e7 | ||
|
|
d93c4eb2e7 | ||
|
|
a1aadaa86c | ||
|
|
0f22647c9c | ||
|
|
6a9b9f4a91 | ||
|
|
0a73c922c3 | ||
|
|
b2d0d08cd7 | ||
|
|
1bd1676f82 | ||
|
|
f4c9371593 | ||
|
|
1fd6427f31 | ||
|
|
49216d54bc | ||
|
|
627155cb04 | ||
|
|
16268c1202 | ||
|
|
4e33e50955 | ||
|
|
31b75ab26e | ||
|
|
8e5624be17 | ||
|
|
c8920be95c | ||
|
|
ee19212c81 | ||
|
|
268ccc9dae | ||
|
|
a0ae20b2fe | ||
|
|
35014d6a05 | ||
|
|
1233c8bb67 | ||
|
|
52fbf7a5b1 | ||
|
|
3f2b26c375 | ||
|
|
a3c945ab42 | ||
|
|
b060d74a5e | ||
|
|
ac8371e949 | ||
|
|
0710036ada | ||
|
|
e6a4fe500b | ||
|
|
93f9109848 | ||
|
|
6b54c8766a | ||
|
|
1d889d5a3d | ||
|
|
c029bb3887 | ||
|
|
38def13577 | ||
|
|
6d0717d385 | ||
|
|
f45dbe3b98 | ||
|
|
f82ac79852 | ||
|
|
653bebf8c1 | ||
|
|
43a1630966 | ||
|
|
59fcc35a47 | ||
|
|
2672aa8490 | ||
|
|
4d4479e067 | ||
|
|
d154d80036 | ||
|
|
3f1c45f65d | ||
|
|
6c3fecbcbd | ||
|
|
ee6454d626 | ||
|
|
c5a79e718a | ||
|
|
22b1e81cba | ||
|
|
800731f09f | ||
|
|
c7a75f2f72 | ||
|
|
4c35b7c447 | ||
|
|
1f921c3c34 | ||
|
|
ec1e65372b | ||
|
|
1c987514b3 | ||
|
|
96bae0ac75 | ||
|
|
ca2e73b00b | ||
|
|
9d2d56190e | ||
|
|
b84ee96907 | ||
|
|
e0b1ee9329 | ||
|
|
b886878c43 | ||
|
|
192548d26d | ||
|
|
fe01bcbe29 | ||
|
|
9f1b882335 | ||
|
|
3d1ec18cbd | ||
|
|
5b554fc328 | ||
|
|
0d1c3139cb | ||
|
|
ddab34cf4f | ||
|
|
723e163e80 | ||
|
|
ea6457dd77 | ||
|
|
8a64fc816a | ||
|
|
31904a2f84 | ||
|
|
d4e3a8afde | ||
|
|
8083efa676 | ||
|
|
05422252c7 | ||
|
|
b5aac4cb8b | ||
|
|
658096b663 | ||
|
|
e574c86119 | ||
|
|
1c5b2ad3df | ||
|
|
a256477750 | ||
|
|
ee3f178333 | ||
|
|
6cde9f4674 | ||
|
|
588abcea2a | ||
|
|
e71fe4cf26 | ||
|
|
25349ff6de | ||
|
|
e3729ee960 | ||
|
|
d9283a33b5 | ||
|
|
6412d0a478 | ||
|
|
f9b56858fe | ||
|
|
6a265e2415 | ||
|
|
dfe37df77c | ||
|
|
7b91a5e5b5 | ||
|
|
2531f7caef | ||
|
|
5c79497b4f | ||
|
|
f5bdaadff5 | ||
|
|
42056e6de6 | ||
|
|
2a4b7380e4 | ||
|
|
b87791ef7f | ||
|
|
54a42548cf | ||
|
|
2db07b0040 | ||
|
|
1a170c6509 | ||
|
|
31f466d2f2 | ||
|
|
2c449e628d | ||
|
|
4557430ac2 | ||
|
|
6e4f844fea | ||
|
|
2afb6ea64f | ||
|
|
829c31b268 | ||
|
|
bebf397687 | ||
|
|
fc7966a008 | ||
|
|
d40c2503cd | ||
|
|
3c87a148e1 | ||
|
|
c5e77500a2 | ||
|
|
06fb8d7046 | ||
|
|
4e189d5c94 | ||
|
|
3e1473caf8 | ||
|
|
1bf0b0e5c0 | ||
|
|
78be2aa820 | ||
|
|
e4cdd8427d | ||
|
|
2df793abb1 | ||
|
|
f56fa3f4de | ||
|
|
d6b7301464 | ||
|
|
a597530613 | ||
|
|
9442a2093b | ||
|
|
b3231bf54f | ||
|
|
a095e23db0 | ||
|
|
c1b905612d | ||
|
|
00e4f70c36 | ||
|
|
08f72e1003 | ||
|
|
3b1a87f14d | ||
|
|
7747e29158 | ||
|
|
7d9873efd8 | ||
|
|
9a4fdda011 | ||
|
|
2e404e6a61 | ||
|
|
602f66c03b | ||
|
|
9b1e91783e | ||
|
|
e94c024413 | ||
|
|
93fc30dada | ||
|
|
a66eb49b2b | ||
|
|
3d3d6eb29b | ||
|
|
96e0c31bf9 | ||
|
|
b2f51c4682 | ||
|
|
902cc9df11 | ||
|
|
72ba01d34b | ||
|
|
6b69001b03 | ||
|
|
3e06af930f | ||
|
|
a80ab6721a | ||
|
|
ffc324fab9 | ||
|
|
87bfb443fe | ||
|
|
3f4662d90e | ||
|
|
1c4834211d | ||
|
|
1e53f371f6 | ||
|
|
9b3f2d00c5 | ||
|
|
e8208c32ea | ||
|
|
ceaaf540a1 | ||
|
|
fd83f09b3c | ||
|
|
69d118d511 | ||
|
|
3cdb6c756d | ||
|
|
4e093c3377 | ||
|
|
fc182882a0 | ||
|
|
64da529ec2 | ||
|
|
6b926ca92e | ||
|
|
be6f91f17e | ||
|
|
abee56d2ce | ||
|
|
a95828843b | ||
|
|
5478b6a6e2 | ||
|
|
58ccdada3b | ||
|
|
61647e96c7 | ||
|
|
6777ace942 | ||
|
|
a157daf7ec | ||
|
|
e4bafbc0e5 | ||
|
|
4d25db31df | ||
|
|
78c2f57679 | ||
|
|
ae827d295d | ||
|
|
15eeb3cc60 | ||
|
|
8cb8c46f2f | ||
|
|
e01bef2ace | ||
|
|
f540f10cca | ||
|
|
93cffa9ded | ||
|
|
f3be9dbb91 | ||
|
|
5e563110e3 | ||
|
|
000239514b | ||
|
|
5cc4cfaf55 | ||
|
|
c29f4fc390 | ||
|
|
6a3851a765 | ||
|
|
a5134928b5 | ||
|
|
30885e332b | ||
|
|
529e8f2f38 | ||
|
|
3662e90e28 | ||
|
|
a5231b42b5 | ||
|
|
af384de79e | ||
|
|
eb45eb48fc | ||
|
|
a6e91ce590 | ||
|
|
6dabe2963e | ||
|
|
089471cd14 | ||
|
|
88f18240df | ||
|
|
daa5f16945 | ||
|
|
5adf770af0 | ||
|
|
9a00c426c6 | ||
|
|
dd8aac577a | ||
|
|
fc0f03e171 | ||
|
|
1535ac7251 | ||
|
|
d395648f2d | ||
|
|
0cfb1b6389 | ||
|
|
9273576fe6 | ||
|
|
58362f14bb | ||
|
|
6bac97c15f | ||
|
|
a44856eb57 | ||
|
|
5a2cb39454 | ||
|
|
88b1426bb1 | ||
|
|
3fbca854d7 | ||
|
|
2a8ee0673d | ||
|
|
c8bfe33253 | ||
|
|
6be0fceb78 | ||
|
|
435fb23fd3 | ||
|
|
1d9b3a42b1 | ||
|
|
bd9b42fd9e | ||
|
|
9164541750 | ||
|
|
1394d6420d | ||
|
|
c245ec80ff | ||
|
|
d8ecd34960 | ||
|
|
37ffa194e2 | ||
|
|
7fde03e88e | ||
|
|
72f204825e | ||
|
|
02667f4348 | ||
|
|
355926ddff | ||
|
|
20922fb494 | ||
|
|
c710fb56e2 | ||
|
|
d15c5c9e89 | ||
|
|
e5460bf605 | ||
|
|
bb59378a2d | ||
|
|
c03d85b83f | ||
|
|
a02cdbcf88 | ||
|
|
3048527635 | ||
|
|
264948a88a | ||
|
|
9ccdcf7aec | ||
|
|
f518a06ed2 | ||
|
|
4e87a6309f | ||
|
|
25f515ffa7 | ||
|
|
2794ff7234 | ||
|
|
859062204c | ||
|
|
8d14b14c65 | ||
|
|
1da48a7f1a | ||
|
|
910ad7ed76 | ||
|
|
a9d82566ef | ||
|
|
4d3d61b887 | ||
|
|
b6b7118fd8 | ||
|
|
701ff55588 | ||
|
|
2a9f5dc434 | ||
|
|
95d518d42f | ||
|
|
f70cf00fd1 | ||
|
|
2e29f8e20f | ||
|
|
5786e84974 | ||
|
|
83683b497f | ||
|
|
a26bf00634 | ||
|
|
a81e21fd99 | ||
|
|
b0dfa2e5b7 | ||
|
|
e9c7f63d5d | ||
|
|
7412837739 | ||
|
|
8d07cfa772 | ||
|
|
053ca27abe | ||
|
|
c4d20da02e | ||
|
|
088ba1babd | ||
|
|
372eb8439a | ||
|
|
90292762c9 | ||
|
|
dbba54c7ad | ||
|
|
6ea96c769a | ||
|
|
b4dc90c3ea | ||
|
|
e6d9143fa8 | ||
|
|
fba021aeff | ||
|
|
a4ebe56254 | ||
|
|
6d97345719 | ||
|
|
572df5a8e5 | ||
|
|
27233c2272 | ||
|
|
c1a83648d3 | ||
|
|
1abced50ca | ||
|
|
a5248f0f39 | ||
|
|
15532d8f9a | ||
|
|
0fdd491bfd | ||
|
|
4fc0151e9f | ||
|
|
8974e8cde0 | ||
|
|
e73ce3a702 | ||
|
|
7755060c6a | ||
|
|
714b885dc5 | ||
|
|
f566a19857 | ||
|
|
d5376799cf | ||
|
|
be94303365 | ||
|
|
c3e982ee8a | ||
|
|
ed38c213ac | ||
|
|
eb69e1e67b | ||
|
|
c0400d7999 | ||
|
|
6de7391be3 | ||
|
|
82140ace20 | ||
|
|
8c1c0011a2 | ||
|
|
dba60cd866 | ||
|
|
f87527c7c0 | ||
|
|
63f6c438ee | ||
|
|
897553f127 | ||
|
|
f337ad3197 | ||
|
|
0df26727da | ||
|
|
8180b284af | ||
|
|
b6439a679b | ||
|
|
3f0f8eb5d9 | ||
|
|
1d7331cb86 | ||
|
|
631c13bb2d | ||
|
|
c21eee838a | ||
|
|
79fa8805b2 | ||
|
|
9b7be4224a | ||
|
|
82e643140e | ||
|
|
8a3b2113f8 | ||
|
|
cddce88207 | ||
|
|
913382c7f2 | ||
|
|
68fb72aa9f | ||
|
|
ee085bcf07 | ||
|
|
1774efd26c | ||
|
|
2fef90d375 | ||
|
|
0dcdd617c3 | ||
|
|
01480b74de | ||
|
|
b68fc778f1 | ||
|
|
259ef0fe7e | ||
|
|
64e4a84012 | ||
|
|
57abb0b28f | ||
|
|
d757b95b44 | ||
|
|
43af39c03a | ||
|
|
19a5dc9c27 | ||
|
|
fd8df5041a | ||
|
|
421482ec3a | ||
|
|
25004f1a7a | ||
|
|
2a0c2b276a | ||
|
|
5e7b74ef46 | ||
|
|
88f7813a3f | ||
|
|
924cc44a20 | ||
|
|
ad8bd1bff4 | ||
|
|
bdf014b4ff | ||
|
|
57c64d8e29 | ||
|
|
a34f7570cc | ||
|
|
e3469875c2 | ||
|
|
ed8fd2bc89 | ||
|
|
3bbc627473 | ||
|
|
91be64626f | ||
|
|
552cd5eb9e | ||
|
|
946bbb1c65 | ||
|
|
2192b340c9 | ||
|
|
b2801794ea | ||
|
|
b863afaa1a | ||
|
|
c80e049844 | ||
|
|
e2fe15f09f | ||
|
|
991d8a6e6f | ||
|
|
786a6e0b5a | ||
|
|
99f737d0b3 | ||
|
|
0d333ac83a | ||
|
|
76e7001e51 | ||
|
|
785813b842 | ||
|
|
ceebba6253 | ||
|
|
e6eb066911 | ||
|
|
7d10360c81 | ||
|
|
dea93456b0 | ||
|
|
a6b63be03b | ||
|
|
78ffcec66d | ||
|
|
731f26e3d4 | ||
|
|
5c1e91467f | ||
|
|
76776cdcd4 | ||
|
|
740cf021f8 | ||
|
|
fa7071ecb6 | ||
|
|
b9bc22d1d2 | ||
|
|
5e9e682932 | ||
|
|
1e00cbb9e7 | ||
|
|
c9353e0236 | ||
|
|
89d87a143d | ||
|
|
e0ee2142b5 | ||
|
|
a7948d97c6 | ||
|
|
ec9b9676fb | ||
|
|
7aad759c26 | ||
|
|
c70b6a0ea9 | ||
|
|
7fda70965f | ||
|
|
e720776365 | ||
|
|
af947d3fd2 | ||
|
|
151cbcd49f | ||
|
|
92a7c88e42 | ||
|
|
557bc521a5 | ||
|
|
c6ec847306 | ||
|
|
ec128823d9 | ||
|
|
e97d4c5f68 | ||
|
|
0401d824eb | ||
|
|
76d8973509 | ||
|
|
f678576a1a | ||
|
|
7aa4b2d22a | ||
|
|
adc1b2bf31 | ||
|
|
9839c0bdda | ||
|
|
724fca9fec | ||
|
|
a63b2a41e0 | ||
|
|
a6083d3402 | ||
|
|
97e06e3726 | ||
|
|
2e8ef6739c | ||
|
|
7b66575ea8 | ||
|
|
9268db4bcc | ||
|
|
ded7fa9a14 | ||
|
|
0383c035f4 | ||
|
|
8614ba0731 | ||
|
|
dad95b3fd2 | ||
|
|
9f94a828d1 | ||
|
|
31cadc18a6 | ||
|
|
eb78e1e769 | ||
|
|
0c2298524c | ||
|
|
d2b3759913 | ||
|
|
370e9ae72b | ||
|
|
3efefb51d9 | ||
|
|
8326c1b5f9 | ||
|
|
9516460d02 | ||
|
|
836b80ea67 | ||
|
|
d970522b31 | ||
|
|
cde92696ca | ||
|
|
16edaab2c6 | ||
|
|
ce656b97bc | ||
|
|
78fad1bbe0 | ||
|
|
f84b1d55d3 | ||
|
|
45fe704285 | ||
|
|
c341edc33a | ||
|
|
e623e067ac | ||
|
|
181fd93e69 | ||
|
|
86f8a936fc | ||
|
|
21692a9c71 | ||
|
|
973a4f6fa9 | ||
|
|
78adcf1caf | ||
|
|
8bd4effe9b | ||
|
|
c71234d71e | ||
|
|
bc13e83f90 | ||
|
|
9848da5608 | ||
|
|
371414d1e0 | ||
|
|
8f696b574f | ||
|
|
c6b5bfb7f0 | ||
|
|
5aadb5ab4f | ||
|
|
48cd95a11e | ||
|
|
9a877fa18e | ||
|
|
df1dc29735 | ||
|
|
b407da74ff | ||
|
|
afb6ab1c09 | ||
|
|
29a07ca099 | ||
|
|
7f2557ba7b | ||
|
|
90735948bb | ||
|
|
69abf6961a | ||
|
|
52143238f0 | ||
|
|
c7e43762b4 | ||
|
|
5011a3cf10 | ||
|
|
6bf2e3a5eb | ||
|
|
1da45805f6 | ||
|
|
3c8f43a575 | ||
|
|
0c2ec57ed0 | ||
|
|
6a51292016 | ||
|
|
1faf89e474 | ||
|
|
95ee5f7a35 | ||
|
|
1c222b3812 | ||
|
|
a369fed608 | ||
|
|
5c1d0b4096 | ||
|
|
a45b82f9b9 | ||
|
|
e713d80487 | ||
|
|
1b52a06029 | ||
|
|
cd90affedf | ||
|
|
a4fd6f380e | ||
|
|
ef21083c33 | ||
|
|
c3b8b53c6c | ||
|
|
958710440c | ||
|
|
df681c295e | ||
|
|
062e3630a3 | ||
|
|
fcecdade1a | ||
|
|
7adc036dcd | ||
|
|
bceda13245 | ||
|
|
306bfaf0eb | ||
|
|
9f5159afb7 | ||
|
|
0449442783 | ||
|
|
d04f12fb7b | ||
|
|
77d7fb9eb5 | ||
|
|
b047ccd9ef | ||
|
|
69b4aa4b33 | ||
|
|
c1d56ebb55 | ||
|
|
fe722acacc | ||
|
|
47d5889c33 | ||
|
|
8eb9e99924 | ||
|
|
c5f86108c7 | ||
|
|
c9d1b5312f | ||
|
|
626a6acb5f | ||
|
|
0b2819649c | ||
|
|
aa724d3af9 | ||
|
|
47b7b27376 | ||
|
|
62944eb976 | ||
|
|
4bca663bb3 | ||
|
|
40d3fd3a21 | ||
|
|
fca61a82eb | ||
|
|
fedaedca8c | ||
|
|
2645a9b9dc | ||
|
|
bcbfeed151 | ||
|
|
00e9083d09 | ||
|
|
4fb88537cb | ||
|
|
3d2bd86284 | ||
|
|
367f63e94e | ||
|
|
c0a2e3331f | ||
|
|
db7f993c18 | ||
|
|
01a42c7d68 | ||
|
|
38bceb1a53 | ||
|
|
8169e2dd07 | ||
|
|
2cec9f92ab | ||
|
|
587eddfff5 | ||
|
|
9c965c83b1 | ||
|
|
0a9b439368 | ||
|
|
1ef809d062 | ||
|
|
132944e176 | ||
|
|
93005c895b | ||
|
|
0c0e455336 | ||
|
|
cd491441f0 | ||
|
|
c9446e151c | ||
|
|
c5ef3404b7 | ||
|
|
c39f71f64c | ||
|
|
72ad1a546b | ||
|
|
ae68d41a90 | ||
|
|
99fbd85c95 | ||
|
|
2f6f12e3e3 | ||
|
|
38c280dc05 | ||
|
|
a2a78c1a87 | ||
|
|
41ee83d6ea | ||
|
|
ea0a18e5dd | ||
|
|
6d53455d41 | ||
|
|
664b6c473f | ||
|
|
e36fa619ae | ||
|
|
0f68967044 | ||
|
|
c9a2b9367c | ||
|
|
dcb01e5034 | ||
|
|
8cef8df219 | ||
|
|
fd6db734f4 | ||
|
|
379f0ecb31 | ||
|
|
fa5bdac1be | ||
|
|
8d57fd4774 | ||
|
|
05980fe33c | ||
|
|
a6e87696b8 | ||
|
|
26fcc9f6cb | ||
|
|
6c437ba258 | ||
|
|
d5a2a75ddc | ||
|
|
aaab4e2bbb | ||
|
|
c3f7ed891f | ||
|
|
d45829ed61 | ||
|
|
f0bf000f4a | ||
|
|
2da1002d38 | ||
|
|
2403646488 | ||
|
|
99af0e8339 | ||
|
|
81b935cadf | ||
|
|
bf395b061f | ||
|
|
79eb814677 | ||
|
|
cbd8872569 | ||
|
|
cc96eb150c | ||
|
|
8c4f23dc56 | ||
|
|
6fb415bc32 | ||
|
|
96e29f6856 | ||
|
|
ec515baca2 | ||
|
|
7eaec006fa | ||
|
|
6968e0cdff | ||
|
|
24ba522cfb | ||
|
|
5777966d82 | ||
|
|
ab820b963a | ||
|
|
30d2b8f394 | ||
|
|
34512e34dd | ||
|
|
08195afdcb | ||
|
|
12c70f7afd | ||
|
|
7135c594e3 | ||
|
|
0606b22c39 | ||
|
|
aa9f57cab1 | ||
|
|
a7bb74f8af | ||
|
|
817ec47a20 | ||
|
|
68c8827630 | ||
|
|
dbbd518978 | ||
|
|
f6e94162cb | ||
|
|
8e146e52f6 | ||
|
|
0cb3de6fae | ||
|
|
65f0fcd4f9 | ||
|
|
4afcbda9db | ||
|
|
6df3af6978 | ||
|
|
a0ab993ffb | ||
|
|
505e2ef47b | ||
|
|
956dfaef6b | ||
|
|
2c442b4e60 | ||
|
|
19717de985 | ||
|
|
b6e0d28017 | ||
|
|
7f89cf80a7 | ||
|
|
e6b8064d23 | ||
|
|
6319b06608 | ||
|
|
e62fbe7d21 | ||
|
|
8d7252c0f9 | ||
|
|
e344b9615a | ||
|
|
f319238567 | ||
|
|
8f49e4c1ee | ||
|
|
fe728ad3c2 | ||
|
|
03db8aa60a | ||
|
|
2aaa461e30 | ||
|
|
e7cddf00f9 | ||
|
|
8d7d3ebabc | ||
|
|
41f71a2f95 | ||
|
|
bab88edd10 | ||
|
|
77023e65e2 | ||
|
|
65d1b9cd61 | ||
|
|
b94fa58db6 | ||
|
|
3897923840 | ||
|
|
8cc5963ce0 | ||
|
|
fda32fe306 | ||
|
|
047dd256f0 | ||
|
|
4e6d8cc5c4 | ||
|
|
f0d44b76f8 | ||
|
|
9b1d1429a3 | ||
|
|
181d9741e2 | ||
|
|
48f85e9b69 | ||
|
|
d4a2798dc8 | ||
|
|
e719dc632b | ||
|
|
9652abf10b | ||
|
|
572c63f011 | ||
|
|
0578863317 | ||
|
|
bdf531f80e | ||
|
|
76aa1d1417 | ||
|
|
2fee4b359b | ||
|
|
789a3cc1e7 | ||
|
|
b92ff8146a | ||
|
|
3afb93a21a | ||
|
|
31b47cac1d | ||
|
|
748f329f38 | ||
|
|
324b0438f4 | ||
|
|
4505e2df1e | ||
|
|
8b1737df91 | ||
|
|
fdfe832ef9 | ||
|
|
035f47d6c1 | ||
|
|
8219c25e42 | ||
|
|
0ebd18de16 | ||
|
|
1adff62a45 | ||
|
|
7b0d3c3232 | ||
|
|
8cc9a66948 | ||
|
|
a43d9a327f | ||
|
|
b2f38b21e1 | ||
|
|
4064e60976 | ||
|
|
23ad15e662 | ||
|
|
527904d49b | ||
|
|
82047a5e2d | ||
|
|
a8190faebc | ||
|
|
15b6c2788f | ||
|
|
68a72befcd | ||
|
|
dc7a347802 | ||
|
|
96c4cb443a | ||
|
|
adf72fa296 | ||
|
|
c4168b6c07 | ||
|
|
4e58c0a77f | ||
|
|
3462879cf9 | ||
|
|
59e7edb5e3 | ||
|
|
9c4342c57e | ||
|
|
12c8ea2299 | ||
|
|
814e1eaac9 | ||
|
|
f047ae1e1f | ||
|
|
521dfe2f2c | ||
|
|
2d4939f14c | ||
|
|
4b70d862de | ||
|
|
b66888ada0 | ||
|
|
721b1d1a25 | ||
|
|
28e822fbb1 | ||
|
|
e8a2a34e21 | ||
|
|
47e4cecdef | ||
|
|
88585b793e | ||
|
|
1debe715d4 | ||
|
|
fd585bcfbf | ||
|
|
dc8290ff28 | ||
|
|
9bcf20269a | ||
|
|
845d0a423e | ||
|
|
b9811a5391 | ||
|
|
6745c50d6b | ||
|
|
ddfb94be01 | ||
|
|
375046d270 | ||
|
|
1b9b21bacd | ||
|
|
7a62057a30 | ||
|
|
5a08358f62 | ||
|
|
b03213d61a | ||
|
|
3050d56bf8 | ||
|
|
c73f70d99c | ||
|
|
f86a5382f0 | ||
|
|
e5013599c8 | ||
|
|
dd357ce7e3 | ||
|
|
120006c866 | ||
|
|
62934c10c0 | ||
|
|
f6fc3b4c81 | ||
|
|
92438a301e | ||
|
|
f90af8d2e1 | ||
|
|
2e58559407 | ||
|
|
016f95052a | ||
|
|
79c3844d6e | ||
|
|
6f28e10041 | ||
|
|
736ae6abea | ||
|
|
47a1668cd5 | ||
|
|
605468e891 | ||
|
|
9ede1f8d2b | ||
|
|
1e7dcd7188 | ||
|
|
847c42220e | ||
|
|
7606f91480 | ||
|
|
c86372b0fc | ||
|
|
4175eaa271 | ||
|
|
d02de27ff5 | ||
|
|
66a4ba19f7 | ||
|
|
7bf551dfce | ||
|
|
532bc851c0 | ||
|
|
124ab116e7 | ||
|
|
b00fe9a33e | ||
|
|
98149e1fe5 | ||
|
|
01c95f90f5 | ||
|
|
c00e92c6f4 | ||
|
|
2d0d8d5a50 | ||
|
|
1bf34d0bdb | ||
|
|
1b51bf9389 | ||
|
|
a81bd8600a | ||
|
|
09316e6363 | ||
|
|
3fef6379dc | ||
|
|
8765f72641 | ||
|
|
c3183e746c | ||
|
|
56d7db4257 | ||
|
|
084550d84c | ||
|
|
95f6ae4b57 | ||
|
|
795686df05 | ||
|
|
b776e03da8 | ||
|
|
d7677a5f7a | ||
|
|
5145b8d03c | ||
|
|
48971cb7d3 | ||
|
|
787ea6f1e4 | ||
|
|
fab74f236a | ||
|
|
35e2460773 | ||
|
|
57faabd8dd | ||
|
|
4850d3558c | ||
|
|
135b78df1f | ||
|
|
a64d2d8bc8 | ||
|
|
5304feaebb | ||
|
|
de007073bc | ||
|
|
8de842f154 | ||
|
|
c501b162e8 | ||
|
|
a31cc6c759 | ||
|
|
bfcfb6d140 | ||
|
|
e08c72f98c | ||
|
|
bbce393a5f | ||
|
|
3b8e4ce952 | ||
|
|
1dbf9931ea | ||
|
|
96e46fdbbb | ||
|
|
d62bd31aa9 | ||
|
|
2e685ef9dd | ||
|
|
074ae2bdaf | ||
|
|
ceb5ed309e | ||
|
|
a588bffb17 | ||
|
|
84c5981e60 | ||
|
|
0a17e736e8 | ||
|
|
68a18ef869 | ||
|
|
f351b6bb99 | ||
|
|
a5fccb3a5e | ||
|
|
68b6317f1a | ||
|
|
1504496219 | ||
|
|
4eb4fe995e | ||
|
|
0be7813428 | ||
|
|
9a4df38122 | ||
|
|
a7f147eb1f | ||
|
|
90ee089b37 | ||
|
|
f53a6ecedd | ||
|
|
831f163ea9 | ||
|
|
6a3f945ce5 | ||
|
|
c90253993b | ||
|
|
aa0d35c854 | ||
|
|
5830c4c06b | ||
|
|
f5facd0b70 | ||
|
|
acadfb5b19 | ||
|
|
3b4cfe2af7 | ||
|
|
1fa7a7e439 | ||
|
|
fb35851cc5 | ||
|
|
6e3ca04fe8 | ||
|
|
2a1bcc51ba | ||
|
|
70360f3760 | ||
|
|
c7816f5d15 | ||
|
|
73c73fbcff | ||
|
|
a9b3adb368 | ||
|
|
3fbfb6c12f | ||
|
|
0f6e9f8161 | ||
|
|
f8bbf7a278 | ||
|
|
4933b6f8b9 | ||
|
|
89a5c3b485 | ||
|
|
f2e7c67457 | ||
|
|
3d0ed3aeb5 | ||
|
|
296327ba7d | ||
|
|
b25ca4eadd | ||
|
|
e0c17676cd | ||
|
|
b1b3ed4f28 | ||
|
|
e3ce00ca18 | ||
|
|
a65ae66e03 | ||
|
|
5b0b779530 | ||
|
|
47974a4711 | ||
|
|
6daf87ceaf | ||
|
|
d789118aa7 | ||
|
|
d8c1abfba9 | ||
|
|
3b50d84af8 | ||
|
|
520558166b | ||
|
|
5d51159832 | ||
|
|
2daa9607d2 | ||
|
|
94d7d50789 | ||
|
|
f38b5ad3e9 | ||
|
|
80c37d9cba | ||
|
|
ec2ea167b3 | ||
|
|
c04614e95b | ||
|
|
f13ba939a4 | ||
|
|
1a84051252 | ||
|
|
c873e85a1c | ||
|
|
fd47f9ca8b | ||
|
|
1a52a9f769 | ||
|
|
f88d53b132 | ||
|
|
2339327a6e | ||
|
|
9fd9cd301b | ||
|
|
b55598b5d9 | ||
|
|
a810e3365e | ||
|
|
ac6a07b9b2 | ||
|
|
3aadcbd9e8 | ||
|
|
17c65267d5 | ||
|
|
31e2681e2f | ||
|
|
811d8f0737 | ||
|
|
4a3dbd3aef | ||
|
|
f71d641f8f | ||
|
|
94004af00c | ||
|
|
2535da4e40 | ||
|
|
0570bfd45a | ||
|
|
ef329b9b71 | ||
|
|
c14c9717b7 | ||
|
|
e0ca8eab68 | ||
|
|
0ee6a9fde7 | ||
|
|
182ebeca50 | ||
|
|
a41a1c1728 | ||
|
|
c2c0cfcc58 | ||
|
|
41488aecf4 | ||
|
|
70f9eda634 | ||
|
|
b246c2029f | ||
|
|
733ced2697 | ||
|
|
55e50edca7 | ||
|
|
bb40c21f97 | ||
|
|
bc397c1ef1 | ||
|
|
5c78119a3a | ||
|
|
9372bf3bf0 | ||
|
|
68d243c93a | ||
|
|
758f7cebc4 | ||
|
|
34633c6e33 | ||
|
|
36d56828f0 | ||
|
|
7a89defb3b | ||
|
|
c4967ae120 | ||
|
|
5f1c6549c9 | ||
|
|
77c374f9b7 | ||
|
|
52c7552b67 | ||
|
|
130538f462 | ||
|
|
440d5dc677 | ||
|
|
71f5be88df | ||
|
|
c3935c993b | ||
|
|
78bf0f6750 | ||
|
|
4db99a148e | ||
|
|
9663898e9b | ||
|
|
76ece66b66 | ||
|
|
de92bae7f5 | ||
|
|
1f342c4090 | ||
|
|
0be7816edc | ||
|
|
7d2cecd6be | ||
|
|
733d839b85 | ||
|
|
850be93973 | ||
|
|
5bbde84a7c | ||
|
|
d0e53ec1f5 | ||
|
|
f241243d28 | ||
|
|
a6d238e4df | ||
|
|
c8e8e841e6 | ||
|
|
bc71e67ca4 | ||
|
|
22b62e36cd | ||
|
|
2931dfc99b | ||
|
|
165ca4ad32 | ||
|
|
a42b746abf | ||
|
|
a8fa6a2901 | ||
|
|
5be5934ea2 | ||
|
|
e629f70906 | ||
|
|
26e4214a50 | ||
|
|
be5056f712 | ||
|
|
62250f890a | ||
|
|
a2e7bb7ffb | ||
|
|
a6a7c86975 | ||
|
|
4d9db5cba8 | ||
|
|
253b5d75d9 | ||
|
|
e8ed8fa815 | ||
|
|
e606361371 | ||
|
|
7c4e56b00c | ||
|
|
02081d9bb5 | ||
|
|
977d3846f4 | ||
|
|
657ace250a | ||
|
|
9efe6ab34e | ||
|
|
ce4d49cc8f | ||
|
|
43af2219d1 | ||
|
|
bf8563bd74 | ||
|
|
8f1a8f60e3 | ||
|
|
cbdacf299b | ||
|
|
a7d213630c | ||
|
|
0fecac6cca | ||
|
|
fd71c4406e | ||
|
|
546baa09cc | ||
|
|
05ce8923e6 | ||
|
|
7e96a1e584 | ||
|
|
2b07dccc39 | ||
|
|
d99ef644ad | ||
|
|
e27e547f8d | ||
|
|
b79e38af34 | ||
|
|
f1f374763c | ||
|
|
052cdc229a | ||
|
|
2673892974 | ||
|
|
d55680425b | ||
|
|
29c7af98f2 | ||
|
|
2afacf6408 | ||
|
|
7ccb9298c0 | ||
|
|
7f5d52ca30 | ||
|
|
4c7b8e17e1 | ||
|
|
0483250196 | ||
|
|
94e041e002 | ||
|
|
5702b4cf8a | ||
|
|
93424424eb | ||
|
|
b429f646f3 | ||
|
|
95a15f4b6e | ||
|
|
84cbdfaba0 | ||
|
|
47e018bb99 | ||
|
|
8041de8e56 | ||
|
|
c010bcc4df | ||
|
|
b92949fd18 | ||
|
|
26cd2feb1b | ||
|
|
f05f061d89 | ||
|
|
09d858486d | ||
|
|
a5bb390479 | ||
|
|
7298df62a9 | ||
|
|
8427c1bd70 | ||
|
|
3830279f69 | ||
|
|
f204f5d341 | ||
|
|
f618fabfda | ||
|
|
2bae0af081 | ||
|
|
e6c7682380 | ||
|
|
bd950fc1e7 | ||
|
|
9a721102c0 | ||
|
|
11d473373d | ||
|
|
51dcb53aa5 | ||
|
|
49dab75c35 | ||
|
|
24432e0d0d | ||
|
|
4595a70239 | ||
|
|
67ab79aa68 | ||
|
|
6ac548ee37 | ||
|
|
2f60f92dbd | ||
|
|
7e8136752b | ||
|
|
083cc921a1 | ||
|
|
e320dca191 | ||
|
|
a025953f3f | ||
|
|
e76f9f59b5 | ||
|
|
2a87d4f10e | ||
|
|
7e0b1d9034 | ||
|
|
a0c1fa293a | ||
|
|
df99dd2b92 | ||
|
|
5bb185e181 | ||
|
|
e106d3defd | ||
|
|
0458d93d96 | ||
|
|
cb16d2186e | ||
|
|
b992baf136 | ||
|
|
9a57ad1b59 | ||
|
|
991e093b8d | ||
|
|
b11b0faf0e | ||
|
|
26d558c725 | ||
|
|
9df7c1802a | ||
|
|
03e608b1b1 | ||
|
|
946b646822 | ||
|
|
3b0d7df4df | ||
|
|
b79bea899c | ||
|
|
b6bcad56e1 | ||
|
|
d2ce406088 | ||
|
|
d8bae1142b | ||
|
|
947cf6df0d | ||
|
|
10934c53e0 | ||
|
|
7383c8731d | ||
|
|
4757bf263c | ||
|
|
b6f7a834d8 | ||
|
|
a20f454642 | ||
|
|
bbf3f884be | ||
|
|
b17615bb11 | ||
|
|
5500e89579 | ||
|
|
57b1b68fb3 | ||
|
|
aa3679737b | ||
|
|
568a141b21 | ||
|
|
7f13a71771 | ||
|
|
a85623dbbf | ||
|
|
558deadd45 | ||
|
|
eb3085a23c | ||
|
|
c93957bb18 | ||
|
|
9379297be1 | ||
|
|
4dbfbe262e | ||
|
|
6cf5577907 | ||
|
|
19c0c45433 | ||
|
|
dfc8519e28 | ||
|
|
2de4f4f8b6 | ||
|
|
7a3c2b7c86 | ||
|
|
daabc07268 | ||
|
|
1257075c03 | ||
|
|
52218cafaf | ||
|
|
7678ce5dbe | ||
|
|
c10477f4e0 | ||
|
|
e8adcafecc | ||
|
|
44fc43d5c6 | ||
|
|
5c49e8d7bc | ||
|
|
4901c46457 | ||
|
|
03433f0329 | ||
|
|
d7eecc5de8 | ||
|
|
fb9572c6cf | ||
|
|
f17ac8728b | ||
|
|
94c6ac091f | ||
|
|
cfecbbf3e2 | ||
|
|
39797f82ab | ||
|
|
9273e61cb4 | ||
|
|
2cbf055fe2 | ||
|
|
696afe722f | ||
|
|
14d84f821f | ||
|
|
f8a3c5ede9 | ||
|
|
2aa9af8778 | ||
|
|
f43b3b50e5 | ||
|
|
f9359636a3 | ||
|
|
a9edf426e9 | ||
|
|
2caa7b1487 | ||
|
|
d86cb764ab | ||
|
|
0ffe14cbdf | ||
|
|
7e83116a61 | ||
|
|
0db90fe416 | ||
|
|
b6b19cc8b7 | ||
|
|
b9349d53a0 | ||
|
|
b6c6600f1f | ||
|
|
e72f9a635c | ||
|
|
c8cc177bbe | ||
|
|
54d33022b3 | ||
|
|
8605ac49cd | ||
|
|
1ded3c391c | ||
|
|
6dead53184 | ||
|
|
a16ec66017 | ||
|
|
4102c85f5f | ||
|
|
3f0ff5d40f | ||
|
|
e84c8695ab | ||
|
|
adc5f9438a | ||
|
|
c426bd1da3 | ||
|
|
d40fed6213 | ||
|
|
c581c11d04 | ||
|
|
f240877928 | ||
|
|
a0d245b818 | ||
|
|
2d00c1df13 | ||
|
|
4851a8a4ed | ||
|
|
a84f338534 | ||
|
|
627719a967 | ||
|
|
f1d4b80636 | ||
|
|
60a7610a28 | ||
|
|
417c928b77 | ||
|
|
92ba3f1a82 | ||
|
|
1a2513920b | ||
|
|
a680b3ce0a | ||
|
|
22c8743aa8 | ||
|
|
267ac9a86e | ||
|
|
f71dcb51e9 | ||
|
|
b9aa04f360 | ||
|
|
611bee8a99 | ||
|
|
7f09c1a999 | ||
|
|
aa1ca995f0 | ||
|
|
7714729093 | ||
|
|
9d06c2bda7 | ||
|
|
f8ec4cd888 | ||
|
|
eee681a5a5 | ||
|
|
c980ca3ae4 | ||
|
|
554912a18f | ||
|
|
c3ca04a747 | ||
|
|
5186bbd4f1 | ||
|
|
adbd1bb88d | ||
|
|
fa38f69f75 | ||
|
|
01bb2c02e6 | ||
|
|
49734b935d | ||
|
|
e57dc9867d | ||
|
|
da2711e307 | ||
|
|
730cf0d724 | ||
|
|
c9af861073 | ||
|
|
5f8984d2d1 | ||
|
|
ef6d3af3a9 | ||
|
|
84dd2d7b9f | ||
|
|
a5257c62f6 | ||
|
|
de6a3cc2ca | ||
|
|
743870d2fb | ||
|
|
9bc885ceab | ||
|
|
a53b484fad | ||
|
|
ffe5a70f01 | ||
|
|
b6e578015c | ||
|
|
0685003d9c | ||
|
|
566367d8ba | ||
|
|
df5565caae | ||
|
|
c05a49028c | ||
|
|
dd322529c4 | ||
|
|
8c17f7c711 | ||
|
|
a3e3a6a950 | ||
|
|
9461488dec | ||
|
|
5300959499 | ||
|
|
228b8b1928 | ||
|
|
380a6cd60e | ||
|
|
0a16370ba7 | ||
|
|
f366b9a0dc | ||
|
|
f8e5d63fba | ||
|
|
1d97e9b37e | ||
|
|
e3fba808b1 | ||
|
|
c523f44cd9 | ||
|
|
cef9af4d2d | ||
|
|
d40e0d0080 | ||
|
|
9f3e2fddb9 | ||
|
|
824e061996 | ||
|
|
53cf85046b | ||
|
|
3c2603b33f | ||
|
|
c97fc41399 | ||
|
|
7942c8b121 | ||
|
|
2a9eeda325 | ||
|
|
36592d55f9 | ||
|
|
ee846b7dff | ||
|
|
4055b52ba0 | ||
|
|
407e3a67d0 | ||
|
|
8bb17343bf | ||
|
|
66987b9339 | ||
|
|
fa7a8a0e0f | ||
|
|
4c9a17208c | ||
|
|
cc61a0cb89 | ||
|
|
f2a98d6bae | ||
|
|
0b082b8484 | ||
|
|
aff12c0f7e | ||
|
|
7998ffb906 | ||
|
|
b738589414 | ||
|
|
151dbd5b47 | ||
|
|
0236493e53 | ||
|
|
d503d3a41b | ||
|
|
2b531039c0 | ||
|
|
ebd0fe64af | ||
|
|
49031905c8 | ||
|
|
ab863addd0 | ||
|
|
1a028a1fbf | ||
|
|
195176e04a | ||
|
|
ca524be461 | ||
|
|
f1f0659899 | ||
|
|
7e2d16ed20 | ||
|
|
8068b2eb68 | ||
|
|
f39426686e | ||
|
|
750623ea55 | ||
|
|
61b2e42472 | ||
|
|
fdb9cd7b43 | ||
|
|
d8d14dd77c | ||
|
|
82723e101f | ||
|
|
bd298544bd | ||
|
|
17b3450deb | ||
|
|
9ae2634ec8 | ||
|
|
18e6c82e28 | ||
|
|
a1f42d8646 | ||
|
|
f00071ce3c | ||
|
|
4afc7dd0bd | ||
|
|
d1f0dd3323 | ||
|
|
3b27913da3 | ||
|
|
6372b946bd | ||
|
|
5694a8d484 | ||
|
|
a57826201a | ||
|
|
f6211944be | ||
|
|
d2820f942e | ||
|
|
cbe270594d | ||
|
|
df44f83341 | ||
|
|
60b2016fdf | ||
|
|
1fbbc31ff0 | ||
|
|
95c7ca62ff | ||
|
|
77cae92007 | ||
|
|
835ffb7f39 | ||
|
|
c8901a7c1b | ||
|
|
82d734f96e | ||
|
|
744ca2c219 | ||
|
|
d6d31ffb14 | ||
|
|
8754511c64 | ||
|
|
48bd42a795 | ||
|
|
c26f1d67e4 | ||
|
|
11459c45c2 | ||
|
|
492236376c | ||
|
|
f46790b7f0 | ||
|
|
55b13366b5 | ||
|
|
67ae9159bc | ||
|
|
9a4004a166 | ||
|
|
0cab9db135 | ||
|
|
5baf8772cc | ||
|
|
d67d85781b | ||
|
|
0756da0293 | ||
|
|
815c757367 | ||
|
|
157cb80c93 | ||
|
|
7053132cfc | ||
|
|
9d6022a0b2 | ||
|
|
6e71c57079 | ||
|
|
e13aee068e | ||
|
|
cbc2a26eac | ||
|
|
7ea5f6e81c | ||
|
|
4f1372c38c | ||
|
|
6348f0bec8 | ||
|
|
afbea29b36 | ||
|
|
7f23474b6d | ||
|
|
4efa995599 | ||
|
|
7774626ec3 | ||
|
|
14939ae97b | ||
|
|
30757fa0ec | ||
|
|
c6118d50ff | ||
|
|
f14bfefdf4 | ||
|
|
a746cbc889 | ||
|
|
87d74c0100 | ||
|
|
3006237805 | ||
|
|
4d6dffc35d | ||
|
|
96070e2591 | ||
|
|
efcd71cb02 | ||
|
|
5dfa27518e | ||
|
|
770753e1f8 | ||
|
|
aa92447e4e | ||
|
|
c76e765904 | ||
|
|
ab7c0ecfe8 | ||
|
|
131139f6af | ||
|
|
b1d1b0764d | ||
|
|
41b14437cf | ||
|
|
76166ee719 | ||
|
|
6b94159cce | ||
|
|
db1c25c2f3 | ||
|
|
9d4bb0b68b | ||
|
|
35a428b801 | ||
|
|
5ff69f557b | ||
|
|
480b3b040d | ||
|
|
86d977bb74 | ||
|
|
ca659e18e5 | ||
|
|
1db3928c2a | ||
|
|
70a301ecf5 | ||
|
|
4047cce1cd | ||
|
|
4a3cc246dc | ||
|
|
0ccdda4815 | ||
|
|
4eec51e271 | ||
|
|
88d0eb2ef6 | ||
|
|
e264c18b7c | ||
|
|
d0b6553251 | ||
|
|
9b7a8a00e3 | ||
|
|
c4afbfb2ed | ||
|
|
5549434132 | ||
|
|
53b4bb81cb | ||
|
|
f2ca6da200 | ||
|
|
350ab85143 | ||
|
|
82a3a42c07 | ||
|
|
26be5df1e9 | ||
|
|
cc61d70218 | ||
|
|
4eb3ac6f10 | ||
|
|
132aeb3e5c | ||
|
|
e460ed34c2 | ||
|
|
40cb7d5597 | ||
|
|
970709d2ef | ||
|
|
0fa7ec8cea | ||
|
|
1649756f29 | ||
|
|
9a52e5f7dd | ||
|
|
3b3a984689 | ||
|
|
ab2a1b0942 | ||
|
|
01e1cefc70 | ||
|
|
3dc7a89718 | ||
|
|
cf3289048a | ||
|
|
857c39e872 | ||
|
|
0ca90f223e | ||
|
|
d6e90896ec | ||
|
|
470064500c | ||
|
|
f7f2d3252a | ||
|
|
dd7ac82527 | ||
|
|
d09a05fc5f | ||
|
|
581b1eea4d | ||
|
|
1bcf63f84e | ||
|
|
def2846e97 | ||
|
|
6563f0c09f | ||
|
|
ce50a53d33 | ||
|
|
3d4ed9b66c | ||
|
|
da45f27cd1 | ||
|
|
75a713dfbb | ||
|
|
2f8e2f285b | ||
|
|
303849ea43 | ||
|
|
2fbdf66783 | ||
|
|
ee34c88276 | ||
|
|
a4a06838c2 | ||
|
|
156d3e8c50 | ||
|
|
84aa951149 | ||
|
|
7641ba0fa8 | ||
|
|
5953b4a538 | ||
|
|
948b4a6692 | ||
|
|
d1cb1bfe98 | ||
|
|
a06ecd9d17 | ||
|
|
0f86a3197e | ||
|
|
cff94a3a60 | ||
|
|
09c75ed8b6 | ||
|
|
c72c2c9a3a | ||
|
|
d665b59c7a | ||
|
|
0790002b6a | ||
|
|
f54119b8da | ||
|
|
4508099fb5 | ||
|
|
31d661acd1 | ||
|
|
eeb99f2c7b | ||
|
|
3f8c8380e4 | ||
|
|
885e9e15ed | ||
|
|
68a70a5687 | ||
|
|
6459c3543c | ||
|
|
ee9d42da37 | ||
|
|
01d4a38353 | ||
|
|
02b946448f | ||
|
|
2697315ed9 | ||
|
|
c35ef1bc96 | ||
|
|
3633df97cd | ||
|
|
ee9f8831c3 | ||
|
|
49bcec5fb7 | ||
|
|
a40921668c | ||
|
|
d23ee61082 | ||
|
|
2b3bf29ee6 | ||
|
|
fa9abe7b63 | ||
|
|
9b2772ccb9 | ||
|
|
1305dd3072 | ||
|
|
275d1a95b2 | ||
|
|
870e805743 | ||
|
|
9d21e059f7 | ||
|
|
e515915ec8 | ||
|
|
8561b715e4 | ||
|
|
f8e8d0c99b | ||
|
|
7e650d73f8 | ||
|
|
06223bcef1 | ||
|
|
91f15abc11 | ||
|
|
211e29bcc4 | ||
|
|
aa7ed10522 | ||
|
|
0c1353b660 | ||
|
|
5ecb4f36bc | ||
|
|
73759e1200 | ||
|
|
a5703d33d3 | ||
|
|
b920b6d100 | ||
|
|
9bba760d9b | ||
|
|
02938c7b01 | ||
|
|
c4b016366b | ||
|
|
8bb9f88037 | ||
|
|
107092277e | ||
|
|
6274ba6d5b | ||
|
|
b4c2d75f00 | ||
|
|
1c65b6d035 | ||
|
|
70ff818b43 | ||
|
|
d66c07bd46 | ||
|
|
7f1d3dd51c | ||
|
|
cbf73d3d7c | ||
|
|
1b802a1d87 | ||
|
|
a63f74d9ac | ||
|
|
62390e168c | ||
|
|
bb8dbafa9c | ||
|
|
4a4184ae3a | ||
|
|
0f9c1f8d17 | ||
|
|
06b96f827e | ||
|
|
a7e16c7680 | ||
|
|
171c01f1f3 | ||
|
|
f9012e75e8 | ||
|
|
813401f481 | ||
|
|
7a5b273cb3 | ||
|
|
1306b9eb0e | ||
|
|
58d0cbc7fa | ||
|
|
198578a5c9 | ||
|
|
8e11bc30a2 | ||
|
|
66570a6813 | ||
|
|
ccf6f7cc8a | ||
|
|
e0993e5ec9 | ||
|
|
26f88721c3 | ||
|
|
4331082903 | ||
|
|
1b9f80072c | ||
|
|
6e9e8eb544 | ||
|
|
982f81bdb2 | ||
|
|
74761dcc07 | ||
|
|
c5d9b2f0d1 | ||
|
|
d35a6599c2 | ||
|
|
b3908781c3 | ||
|
|
62a7a91f9b | ||
|
|
50ce96f4f2 | ||
|
|
9fd0d5e786 | ||
|
|
ee06ff94b7 | ||
|
|
4c3d8246ef | ||
|
|
a372494f55 | ||
|
|
dd6fdc493c | ||
|
|
236e813e89 | ||
|
|
5fc125b117 | ||
|
|
3e68196cf1 | ||
|
|
3cd0018a2d | ||
|
|
91af9ad701 | ||
|
|
ce35ec42e3 | ||
|
|
1d1d68fb6f | ||
|
|
a87bbe778f | ||
|
|
b442645dd1 | ||
|
|
5c577272f2 | ||
|
|
28306908c2 | ||
|
|
fb89ac2fe8 | ||
|
|
57c8f72e65 | ||
|
|
ce5f9bc086 | ||
|
|
ccfea3fa5d | ||
|
|
05b28db083 | ||
|
|
f866aa8a48 | ||
|
|
104aa85b65 | ||
|
|
4592f4d7f9 | ||
|
|
db2887c610 | ||
|
|
66dde0c2e0 | ||
|
|
35bc7f5177 | ||
|
|
ec6f4ae436 | ||
|
|
da9565bf63 | ||
|
|
1a968715d9 | ||
|
|
4682d7dca6 | ||
|
|
fb07076d25 | ||
|
|
65375765bc | ||
|
|
bbb0d6b7a6 | ||
|
|
2e34170a82 | ||
|
|
dd7e9ecd7a | ||
|
|
2377031c91 | ||
|
|
7192e34bbe | ||
|
|
9d3cc12724 | ||
|
|
8ac79898b8 | ||
|
|
b1a41ca74a | ||
|
|
8bb0f3f886 | ||
|
|
bfbba70685 | ||
|
|
5536fbda96 | ||
|
|
3efc7109f5 | ||
|
|
fe1fe6f4a8 | ||
|
|
6d52617fab | ||
|
|
fbb03c0e65 | ||
|
|
3c9b29c29e | ||
|
|
7e950ea734 | ||
|
|
d52c169873 | ||
|
|
42ce8a4067 | ||
|
|
64fc093bbc | ||
|
|
be007299d5 | ||
|
|
c4bd1f31f7 | ||
|
|
c09930e079 | ||
|
|
1220947601 | ||
|
|
8e738a4500 | ||
|
|
fc27388534 | ||
|
|
3e5eed4af5 | ||
|
|
e0a1045252 | ||
|
|
ffc977157c | ||
|
|
0ccf943934 | ||
|
|
4eaedfe621 | ||
|
|
4c90e62569 | ||
|
|
4a53bc4a85 | ||
|
|
450ad44550 | ||
|
|
73bf5feec8 | ||
|
|
48f14c644e | ||
|
|
05a24e63ba | ||
|
|
88dafeb561 | ||
|
|
b648316b51 | ||
|
|
9aebd4445c | ||
|
|
ced8db7de1 | ||
|
|
692b0361c6 | ||
|
|
2080de37fe | ||
|
|
97ad0e3d2b | ||
|
|
4261eee360 | ||
|
|
47d68814dc | ||
|
|
066e6dac81 | ||
|
|
7606fa5810 | ||
|
|
0d3ac5c6d6 | ||
|
|
f88142abc1 | ||
|
|
673f9a7a0e | ||
|
|
37ee42fab5 | ||
|
|
071744440d | ||
|
|
8854f1d687 | ||
|
|
5206144d06 | ||
|
|
f4c3a4a321 | ||
|
|
e74e188bd9 | ||
|
|
40b552dc49 | ||
|
|
a4a41f1e59 | ||
|
|
e6d7404660 | ||
|
|
fece31e31a | ||
|
|
c12db4c3bf | ||
|
|
342268c399 | ||
|
|
6a5350e648 | ||
|
|
9d9f7f3d4d | ||
|
|
8d7f987ccb | ||
|
|
4cac15cf97 | ||
|
|
6e7c4caa62 | ||
|
|
b43bf1664d | ||
|
|
524b8ada86 | ||
|
|
d5c9008d3e | ||
|
|
6ceb241170 | ||
|
|
8037fdd233 | ||
|
|
2c4ca881be | ||
|
|
3629d82499 | ||
|
|
d3bd4c5db9 | ||
|
|
b44ef845db | ||
|
|
8c218d1086 | ||
|
|
90f8a8f1a6 | ||
|
|
31d6da3c85 | ||
|
|
0a94c3079f | ||
|
|
36933f1bab | ||
|
|
2355bc10bc | ||
|
|
eebd1113c3 | ||
|
|
814252375a | ||
|
|
38817162b3 | ||
|
|
9a291c065c | ||
|
|
1f25aaedfc | ||
|
|
c6d6270c4a | ||
|
|
d5acdb2161 | ||
|
|
f3778ae260 | ||
|
|
5bfdd25962 | ||
|
|
bded7f726e | ||
|
|
5469c00cfa | ||
|
|
e78937ae35 | ||
|
|
f67340dc84 | ||
|
|
c9dc08fe52 | ||
|
|
d6e9278a30 | ||
|
|
8b162b3069 | ||
|
|
febebb2b0e | ||
|
|
7c8be00c9a | ||
|
|
1f5e071767 | ||
|
|
93ed57e720 | ||
|
|
a0fd178eca | ||
|
|
13bb52cded | ||
|
|
5956090c9f | ||
|
|
892f00e2f4 | ||
|
|
f6b373cb79 | ||
|
|
172ab7edc8 | ||
|
|
01989bc39a | ||
|
|
63f6e19fc0 | ||
|
|
70576ce0c9 | ||
|
|
85081497aa | ||
|
|
3f152acc57 | ||
|
|
436ccf88d5 | ||
|
|
b96e566d61 | ||
|
|
3a36fafdc6 | ||
|
|
cdca1f136e | ||
|
|
4b11cb18cf | ||
|
|
0600486bd8 | ||
|
|
c3189d6e30 | ||
|
|
970395a4d7 | ||
|
|
a9a02b56ba | ||
|
|
4359144925 |
21
.gitignore
vendored
@@ -1,3 +1,22 @@
|
||||
static/images/thumbnails/
|
||||
server/public/assets/images/thumbnails/
|
||||
server/config/mailconfig.js
|
||||
server/config/api_key.js
|
||||
server/config/mongo_config.js
|
||||
server/config/cert_config.js
|
||||
server/config/recaptcha.js
|
||||
server/config/analytics.js
|
||||
server/config/google.js
|
||||
server/config/allowed_api.js
|
||||
server/public/assets/dist/maps/
|
||||
server/public/assets/dist/callback.min.js
|
||||
server/public/assets/dist/token.min.js
|
||||
server/public/assets/dist/embed.min.js
|
||||
server/public/assets/dist/main.min.js
|
||||
server/public/assets/dist/remote.min.js
|
||||
*/node_modules
|
||||
node_modules/
|
||||
scripts/
|
||||
.DS_Store
|
||||
npm-debug.log
|
||||
server/npm-debug.log
|
||||
server/public/assets/dist/
|
||||
|
||||
43
.htaccess
@@ -1,43 +0,0 @@
|
||||
Options +FollowSymLinks
|
||||
RewriteEngine on
|
||||
RewriteBase /
|
||||
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
|
||||
RewriteCond %{HTTPS} !=on
|
||||
RewriteRule ^(.*)$ https://%1/$1 [L]
|
||||
|
||||
RewriteCond %{HTTP_HOST} ^(.*zoff.no.*)$
|
||||
RewriteCond %{HTTPS} !=on
|
||||
RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [L]
|
||||
|
||||
RewriteCond %{HTTP_HOST} ^remote.zoff.no
|
||||
RewriteCond %{REQUEST_URI} !/static
|
||||
RewriteRule ^(.*)$ php/controller.php [L,NC,QSA]
|
||||
|
||||
RewriteCond %{HTTP_HOST} ^bot.zoff.no
|
||||
RewriteCond %{REQUEST_URI} !/static
|
||||
RewriteRule ^(.*)$ php/bot.php [L,NC,QSA]
|
||||
|
||||
#RewriteCond %{HTTP_HOST} ^(remote\.)?zoff\.no
|
||||
#RewriteCond %{REQUEST_URI} !remote/
|
||||
#RewriteRule ^(.*)$ remote/$1 [L]
|
||||
|
||||
#RewriteCond %{HTTP_HOST} ^(www\.)?etys\.no
|
||||
#RewriteCond %{REQUEST_URI} !etys/
|
||||
#RewriteRule ^(.*)$ etys/$1 [L]
|
||||
|
||||
#Comment out the two folling lines when running server locally to fix issues with localhost
|
||||
#RewriteCond %{HTTPS} !=on
|
||||
#RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L]
|
||||
|
||||
|
||||
#RewriteRule (?i)^remote/(.*) php/controller.php?id=$1 [L]
|
||||
#RewriteRule (?i)^remote php/controller.php [L]
|
||||
|
||||
RewriteCond %{REQUEST_URI} !(/$|\.)
|
||||
RewriteRule (.*) %{REQUEST_URI}/ [R=301,L]
|
||||
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteRule /(.*)$ /$1 [L]
|
||||
|
||||
Options -Indexes
|
||||
2
FUNDING.yml
Normal file
@@ -0,0 +1,2 @@
|
||||
github: [kasperrt]
|
||||
custom: ["https://www.paypal.me/zoffmusic"]
|
||||
121
README.md
@@ -1,84 +1,87 @@
|
||||
Zöff
|
||||
Zoff
|
||||
====
|
||||
|
||||
##### The server-side is required for this website, and it's found at: <a href="https://github.com/zoff-music/zoff-server">here</a>
|
||||
Zoff (pronounced __søff__) is a shared (free) YouTube and SoundCloud based radio service, built upon the YouTube API, and SoundCloud API, with integrated casting with Chromecast.
|
||||
|
||||
##### Config
|
||||
Zoff supports importing YouTube, SoundCloud and Spotify playlists, and has functionality that (tries to) export to YouTube, SoundCloud and Spotify.
|
||||
|
||||
To get the website to run as intended, please enabled mod_rewrite for apache2, and add ```AllowOverride All``` to the directory containing the webserver in Apache2 (it's usually /etc/apache2/sites-enabled/000-default.conf)
|
||||
<a href="https://zoff.me"><img height="80" src="https://puu.sh/BlSwW/57061de17b.png"></a><a class="android-image-link" href="https://play.google.com/store/apps/details?id=zoff.me.zoff&hl=no&pcampaignid=MKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1"><img alt="Get it on Google Play" height="65" src="https://puu.sh/BcWup/f560259c3f.png"></a>
|
||||
<a style="padding-bottom:20px;" class="apple-image-link" href="https://itunes.apple.com/us/app/zoff/id1402037061?ls=1&mt=8"><img height="65" alt="Get it on the AppStore" src="https://puu.sh/BcWvt/09002407c3.png"></a>
|
||||
|
||||
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
Prerequisites:
|
||||
|
||||
```
|
||||
MongoDB : https://www.mongodb.org/
|
||||
NodeJS : https://nodejs.org/en/
|
||||
npm : https://www.npmjs.com/
|
||||
```
|
||||
|
||||
Clone this repository into a folder, and navigate to it. Use ```$ npm install``` in the project folder.
|
||||
|
||||
For the server to run, you have to have the files
|
||||
|
||||
```
|
||||
api_key.js
|
||||
mongo_config.js
|
||||
```
|
||||
|
||||
in ```/server/config```. There are ```*.example.js``` files for all the ones mentioned above. If you're going to deploy the server with a certificate, you also need to create the ```cert_config.js``` in ```/server/config/```. If you want the mailing to work, take a look at ```mailconfig.example.js``` and ```recaptcha.example.js```. You'll need ```mailconfig.js``` and ```recaptcha.js``` for this to work.
|
||||
|
||||
If you want to use Google Analytics, have a look at ```analytics.example.js``` in ```server/config/```.
|
||||
|
||||
Use ```$ npm start``` to start the server. (Alternative you can use the ```pm2.json``` in the project-root, if you prefer pm2 for running the apps.)
|
||||
|
||||
More info in <a href="https://github.com/zoff-music/zoff/blob/master/server/README.md">server/ README</a>
|
||||
|
||||
### About
|
||||
|
||||
Zöff is a shared (free) YouTube based radio service, built upon the YouTube API.
|
||||
|
||||
Zöff is mainly a webbased service. The website uses <a href="https://nodejs.org/">NodeJS</a> with <a href="http://socket.io/">Socket.IO</a>, <a href="https://www.mongodb.org/">MongoDB</a> and PHP on the backend, with JavaScript, jQuery and <a href="http://materializecss.com/">Materialize</a> on the frontend.
|
||||
Zoff is mainly a webbased service. The website uses <a href="https://nodejs.org/">NodeJS</a> with <a href="http://socket.io/">Socket.IO</a>, <a href="https://www.mongodb.org/">MongoDB</a> and express on the backend, with JavaScript and <a href="http://materializecss.com/">Materialize</a> on the frontend.
|
||||
|
||||
The team consists of Kasper Rynning-Tønnesen and Nicolas Almagro Tonne, and the project has been worked on since late 2014.
|
||||
|
||||
### Contact
|
||||
|
||||
The team can be reached on <a href="mailto:contact@zoff.no?Subject=Contact%20Zoff">contact@zoff.no</a>
|
||||
The team can be reached on <a href="mailto:contact@zoff.me?Subject=Contact%20Zoff">contact@zoff.me</a>
|
||||
|
||||
###Screenshots of desktop version:
|
||||
### Screenshots of desktop version:
|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
### Embedded player:
|
||||
|
||||

|
||||
|
||||
### Screenshots of the mobile version:
|
||||
|
||||
  
|
||||
|
||||
### Android exclusive screens:
|
||||
|
||||
<div style="text-align:center;">
|
||||
<img src="http://i.imgur.com/2LMOnUe.png" alt="android1" height="600px">
|
||||
<img src="http://i.imgur.com/mIOrtng.png" alt="android2" height="400px">
|
||||
<img src="http://i.imgur.com/aWlEmIx.png" alt="frontpage" height="600px">
|
||||
<br>
|
||||
<img src="https://puu.sh/xCI6X/1aead5e1b6.png" alt="channel" height="600px">
|
||||
|
||||
<img src="https://puu.sh/AhKUE/f93daa8a46.png" alt="channel search" height="600px">
|
||||
</div>
|
||||
|
||||
### Events
|
||||
|
||||
Emitted events between the server and client
|
||||
```
|
||||
socket.emit("end", VIDEO_ID); Tells the server the song is clientside
|
||||
socket.emit("pos"); Asks server where in the song it should be
|
||||
socket.emit('list', CHANNEL_NAME); Tells the server the client wants the list
|
||||
socket.emit("add", [VIDEO_ID, VIDEO_TITLE, sha256(PASSWORD), VIDEO_DURATION]); Sends info about a song the client wants to add
|
||||
socket.emit("change_channel"); Tells the server to disconnect the user from the current channel, is used for remote controlling on the host side
|
||||
socket.emit("all,chat", TEXT); Sends chat text to all chat
|
||||
socket.emit("chat", TEXT); Sends chat text to channelchat
|
||||
socket.emit('vote', [CHANNEL_NAME, VIDEO_ID, VOTE_TYPE, PASSWORD]); Sends info about song the user wants to vote on. If VOTE_TYPE is del, its deleting the song, if its pos, its just voting
|
||||
socket.emit('skip', [CHANNEL_NAME, PASSWORD]); Sends skip message to server
|
||||
socket.emit("password", [PASSWORD, CHANNEL_NAME]); Sends password for instant log in to server
|
||||
socket.emit('frontpage_lists'); Tells the server the client wants frontpage lists
|
||||
socket.emit("id", [CHANNEL_ID, "play", "mock"]); Sends message to the host channel for play
|
||||
socket.emit("id", [CHANNEL_ID, "pause", "mock"]); Sends message to the host channel for pause
|
||||
socket.emit("id", [CHANNEL_ID, "skip", "mock"]); Sends message to the host channel for skip
|
||||
socket.emit("id", [CHANNEL_ID, "volume", VALUE]); Sends message to the host channel to change volume
|
||||
socket.emit("id", [CHANNEL_ID, "channel", NEW_CHANNEL_NAME]); Sends message to the host channel to change channel
|
||||
|
||||
socket.on("toast", STRING) Recieves a string from server for what type of toast to be triggered
|
||||
socket.on("pw", STRING) Recieves the password for the channel if the user sent the right in the first place
|
||||
socket.on("conf", [ARRAY]) Recieves configuration array from server
|
||||
socket.on("chat.all", [CLIENT_NAME, STRING, CLIENT_CHANNEL_NAME]) Recieves chat message from allchat
|
||||
socket.on("chat", [CLIENT_NAME, STRING]) Recieves chat message from channelchat
|
||||
socket.on("id", STRING) Recieves the ID of the current client, used for remote listening
|
||||
socket.on(id, [ARRAY]) Recieves the messages sent on CHANNEL_ID above
|
||||
socket.on("channel", [TYPE, [TYPE_SPECIFIC_VALUE]]) Recieves updates from channel. [0] is one of the following: list, added, deleted, vote, song_change
|
||||
socket.on("get_list") Recieves message from the server that its ready to send the playlist and info
|
||||
socket.on('playlists', [ARRAY]) Recieves the playlists for the frontpage
|
||||
socket.on("np", [NOW_PLAYING, CONFIGURATION, SERVER_TIME]) Recieves array of now playing song. Is triggered on song-change
|
||||
socket.on("viewers", VALUE) Recieves number of viewers on the current channel
|
||||
```
|
||||
|
||||
### Legal
|
||||
|
||||
Copyright © 2016
|
||||
Nicolas Almagro Tonne and Kasper Rynning-Tønnesen
|
||||
|
||||
Creative Commons License
|
||||
Zöff is licensed under a
|
||||
<a href="http://creativecommons.org/licenses/by-nc-nd/3.0/no/">Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Norway License.</a>.
|
||||
Do not redistribute without permission from the developers.
|
||||
Zoff is licensed under a
|
||||
<a href="http://creativecommons.org/licenses/by-nc-nd/3.0/no/">Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Norway License.</a>.
|
||||
Do not redistribute without permission from the developers.
|
||||
|
||||
Copyright © 2019
|
||||
Kasper Rynning-Tønnesen and Nicolas Almagro Tonne
|
||||
|
||||
22
embed.html
@@ -1,22 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta name="author" content="Nicolas 'Nixo' Almagro Tonne & Kasper 'KasperRT' Rynning-Tønnesen"/>
|
||||
<meta name="description" content="The Shared (free) YouTube radio. Being built around the YouTube search and video API it enables the creation of collaborative and shared live playlists, with billions of videos and songs to choose from, all for free and without registration. Enjoy!"/>
|
||||
<meta charset="UTF-8"/>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
function receiveMessage(event)
|
||||
{
|
||||
if(event.data == "lower") {
|
||||
window.setVolume(10);
|
||||
}else if(event.data == "reset") {
|
||||
window.setVolume(100);
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("message", receiveMessage, false);
|
||||
</script>
|
||||
<div id="song-title"></div><div id="container" style="display:inline-flex;"><div id="player-container"><div id="player"></div><div id="controls" class="noselect"><div id="zoffbutton" title="Visit the channel!"></div><div id="playpause"><i id="play" class="mdi-av-play-arrow hide"></i><i id="pause" class="mdi-av-pause"></i></div><div id="duration">00:00 / 00:00</div><div id="volume-button"><i id="v-mute" class="mdi-av-volume-off"></i><i id="v-low" class="mdi-av-volume-mute"></i><i id="v-medium" class="mdi-av-volume-down"></i><i id="v-full" class="mdi-av-volume-up"></i></div><div id="volume"></div><div id="viewers"></div><div id="bar"></div></div></div><div id="playlist"><div id="wrapper"><div id="preloader" class="progress channel_preloader"><div class="indeterminate"></div></div><div id="list-song-html"><div id="list-song" class="card left-align list-song"><span class="clickable vote-container" title="Vote!"><a class="clickable center-align votebg"><div class="lazy card-image cardbg list-image" style=""></div></a><span class="card-content"><span class="flow-text truncate list-title"></span><span class="vote-span"><span class="list-votes"></span><span class="highlighted vote-text"> votes</span></span></span></span></div></div></div></div></div><script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script><script type="text/javascript" src="//cdn.socket.io/socket.io-1.3.5.js"></script><script src="static/dist/embed.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
226
gulpfile.js
@@ -1,56 +1,184 @@
|
||||
var gulp = require('gulp'),
|
||||
gutil = require('gulp-util'),
|
||||
uglify = require('gulp-uglifyjs'),
|
||||
concat = require('gulp-concat');
|
||||
var gulp = require("gulp"),
|
||||
uglify = require("gulp-uglify"),
|
||||
//sourcemaps = require('gulp-sourcemaps'),
|
||||
concat = require("gulp-concat"),
|
||||
cleanCSS = require("gulp-clean-css");
|
||||
|
||||
gulp.task('js', function () {
|
||||
gulp.src(['static/js/*.js', '!static/js/embed*', '!static/js/remotecontroller.js'])
|
||||
.pipe(uglify({
|
||||
mangle: true,
|
||||
compress: true,
|
||||
enclose: true
|
||||
}))
|
||||
.pipe(concat('main.min.js'))
|
||||
.pipe(gulp.dest('static/dist'));
|
||||
gulp.task("css", function() {
|
||||
return gulp
|
||||
.src([
|
||||
"server/public/assets/css/style.css",
|
||||
"server/public/assets/css/globals.css",
|
||||
"server/public/assets/css/animations.css",
|
||||
"server/public/assets/css/mobile.css"
|
||||
])
|
||||
.pipe(concat("style.css"))
|
||||
.pipe(cleanCSS({ compatibility: "ie8" }))
|
||||
.pipe(gulp.dest("server/public/assets/dist"));
|
||||
});
|
||||
|
||||
gulp.task('embed', function () {
|
||||
gulp.src(['static/js/player.js', 'static/js/helpers.js', 'static/js/playercontrols.js', 'static/js/list.js', 'static/js/embed.js', '!static/js/nochan*', '!static/js/remotecontroller.js'])
|
||||
.pipe(uglify({
|
||||
mangle: true,
|
||||
compress: true,
|
||||
enclose: true
|
||||
}))
|
||||
.pipe(concat('embed.min.js'))
|
||||
.pipe(gulp.dest('static/dist'));
|
||||
gulp.task("css-embed", function() {
|
||||
return gulp
|
||||
.src("server/public/assets/css/embed.css")
|
||||
.pipe(cleanCSS({ compatibility: "ie8" }))
|
||||
.pipe(gulp.dest("server/public/assets/dist"));
|
||||
});
|
||||
|
||||
/*
|
||||
gulp.task('nochan', function () {
|
||||
gulp.src(['static/js/nochan.js', 'static/js/helpers.js'])
|
||||
.pipe(uglify({
|
||||
mangle: true,
|
||||
compress: true,
|
||||
enclose: true
|
||||
}))
|
||||
.pipe(concat('frontpage.min.js'))
|
||||
.pipe(gulp.dest('static/dist'));
|
||||
});*/
|
||||
|
||||
gulp.task('remotecontroller', function () {
|
||||
gulp.src(['static/js/remotecontroller.js'])
|
||||
.pipe(uglify({
|
||||
mangle: true,
|
||||
compress: true,
|
||||
enclose: true
|
||||
}))
|
||||
.pipe(concat('remote.min.js'))
|
||||
.pipe(gulp.dest('static/dist'));
|
||||
gulp.task("js", function() {
|
||||
return (
|
||||
gulp
|
||||
.src([
|
||||
"server/VERSION.js",
|
||||
"server/config/api_key.js",
|
||||
"server/public/assets/js/*.js",
|
||||
"!server/public/assets/js/embed*",
|
||||
"!server/public/assets/js/token*",
|
||||
"!server/public/assets/js/remotecontroller.js",
|
||||
"!server/public/assets/js/callback.js"
|
||||
])
|
||||
//.pipe(sourcemaps.init())
|
||||
.pipe(concat("main.min.js"))
|
||||
.pipe(
|
||||
uglify({
|
||||
mangle: true,
|
||||
compress: true,
|
||||
enclose: true
|
||||
})
|
||||
)
|
||||
//.pipe(sourcemaps.write('maps'))
|
||||
.pipe(gulp.dest("server/public/assets/dist"))
|
||||
);
|
||||
});
|
||||
|
||||
gulp.task('default', function(){
|
||||
gulp.watch('static/js/*.js', ['js']);
|
||||
gulp.watch('static/js/*.js', ['embed']);
|
||||
//gulp.watch('static/js/*.js', ['nochan']);
|
||||
gulp.watch('static/js/remotecontroller.js', ['remotecontroller']);
|
||||
});
|
||||
gulp.task("embed", function() {
|
||||
return (
|
||||
gulp
|
||||
.src([
|
||||
"server/VERSION.js",
|
||||
"server/config/api_key.js",
|
||||
"server/public/assets/js/player.js",
|
||||
"server/public/assets/js/functions.js",
|
||||
"server/public/assets/js/helpers.js",
|
||||
"server/public/assets/js/playercontrols.js",
|
||||
"server/public/assets/js/list.js",
|
||||
"server/public/assets/js/embed.js",
|
||||
"!server/public/assets/js/frontpage*",
|
||||
"!server/public/assets/js/remotecontroller.js",
|
||||
"server/public/assets/js/hostcontroller.js"
|
||||
])
|
||||
//.pipe(sourcemaps.init())
|
||||
.pipe(concat("embed.min.js"))
|
||||
.pipe(
|
||||
uglify({
|
||||
mangle: true,
|
||||
compress: true,
|
||||
enclose: true
|
||||
})
|
||||
)
|
||||
//.pipe(sourcemaps.write('maps'))
|
||||
.pipe(gulp.dest("server/public/assets/dist"))
|
||||
);
|
||||
});
|
||||
|
||||
gulp.task("token", function() {
|
||||
return (
|
||||
gulp
|
||||
.src([
|
||||
"server/public/assets/js/token*",
|
||||
"server/public/assets/js/helpers.js"
|
||||
])
|
||||
//.pipe(sourcemaps.init())
|
||||
.pipe(concat("token.min.js"))
|
||||
.pipe(
|
||||
uglify({
|
||||
mangle: true,
|
||||
compress: true,
|
||||
enclose: true
|
||||
})
|
||||
)
|
||||
//.pipe(sourcemaps.write('maps'))
|
||||
.pipe(gulp.dest("server/public/assets/dist"))
|
||||
);
|
||||
});
|
||||
|
||||
gulp.task("callback", function() {
|
||||
return (
|
||||
gulp
|
||||
.src([
|
||||
"server/VERSION.js",
|
||||
"server/config/api_key.js",
|
||||
"server/public/assets/js/callback.js"
|
||||
])
|
||||
//.pipe(sourcemaps.init())
|
||||
.pipe(concat("callback.min.js"))
|
||||
.pipe(
|
||||
uglify({
|
||||
mangle: true,
|
||||
compress: true,
|
||||
enclose: true
|
||||
})
|
||||
)
|
||||
//.pipe(sourcemaps.write('maps'))
|
||||
.pipe(gulp.dest("server/public/assets/dist"))
|
||||
);
|
||||
});
|
||||
|
||||
gulp.task("build", done => {
|
||||
gulp.series(
|
||||
"css",
|
||||
"css-embed",
|
||||
"js",
|
||||
"embed",
|
||||
"remotecontroller",
|
||||
"callback",
|
||||
"token"
|
||||
)();
|
||||
done();
|
||||
});
|
||||
|
||||
gulp.task("remotecontroller", function() {
|
||||
return (
|
||||
gulp
|
||||
.src([
|
||||
"server/VERSION.js",
|
||||
"server/config/api_key.js",
|
||||
"server/public/assets/js/remotecontroller.js",
|
||||
"server/public/assets/js/helpers.js"
|
||||
])
|
||||
////.pipe(sourcemaps.init())
|
||||
.pipe(concat("remote.min.js"))
|
||||
.pipe(
|
||||
uglify({
|
||||
mangle: true,
|
||||
compress: true,
|
||||
enclose: true
|
||||
})
|
||||
)
|
||||
//.pipe(sourcemaps.write('maps'))
|
||||
.pipe(gulp.dest("server/public/assets/dist"))
|
||||
);
|
||||
});
|
||||
|
||||
gulp.task("default", function() {
|
||||
gulp.watch(["server/VERSION.js", "server/public/assets/js/*.js"], ["js"]);
|
||||
gulp.watch(["server/public/assets/css/*.css"], ["css"]);
|
||||
gulp.watch(["server/public/assets/css/*.css"], ["css-embed"]);
|
||||
gulp.watch(
|
||||
["server/public/assets/js/token*.js", "server/public/assets/js/helpers.js"],
|
||||
["token"]
|
||||
);
|
||||
gulp.watch(["server/VERSION.js", "server/public/assets/js/*.js"], ["embed"]);
|
||||
gulp.watch(
|
||||
[
|
||||
"server/VERSION.js",
|
||||
"server/public/assets/js/callback.js",
|
||||
"server/public/assets/js/helpers.js"
|
||||
],
|
||||
["callback"]
|
||||
);
|
||||
//gulp.watch('server/public/assets/js/*.js', ['nochan']);
|
||||
gulp.watch(
|
||||
["server/VERSION.js", "server/public/assets/js/remotecontroller.js"],
|
||||
["remotecontroller"]
|
||||
);
|
||||
});
|
||||
|
||||
278
index.php
@@ -1,278 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<?php
|
||||
$guid=substr(base64_encode(crc32($_SERVER['HTTP_USER_AGENT'].$_SERVER['REMOTE_ADDR'].$_SERVER['HTTP_ACCEPT_LANGUAGE'])), 0, 8);
|
||||
if(isset($_GET['chan'])) {header('Location: '.$_GET['chan']); exit;}
|
||||
$list = explode("/", htmlspecialchars(strtolower($_SERVER["REQUEST_URI"])));
|
||||
if($list[1]==""||!isset($list[1])||count($list)<=1){$list="";include('php/nochan.php');die();}
|
||||
else $list=preg_replace("/[^A-Za-z0-9 ]/", '', $list[1]);
|
||||
?>
|
||||
<html lang="en">
|
||||
<head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb#">
|
||||
<?php include("php/header.php"); ?>
|
||||
<script type="text/javascript" src="/static/dist/main.min.js"></script>
|
||||
</head>
|
||||
<body id="channelpage" class="noselect cursor-default">
|
||||
<header>
|
||||
<div class="navbar-fixed">
|
||||
<nav id="nav">
|
||||
<div class="nav-wrapper">
|
||||
<a href="/" class="brand-logo brand-logo-navigate hide-on-med-and-down noselect">
|
||||
<img id="zicon" src="static/images/squareicon_small.png" alt="zöff" title="Zöff" />
|
||||
</a>
|
||||
<div class="brand-logo truncate zbrand">
|
||||
<a href="/" class="hide-on-large-only brand-logo-navigate">Zöff</a>
|
||||
<span class="hide-on-large-only">/</span>
|
||||
<span id="chan" class="chan clickable" title="Show big URL"><?php echo(ucfirst($list));?></span>
|
||||
</div>
|
||||
|
||||
<ul class="title-container">
|
||||
<li class="song-title cursor-pointer truncate" id="song-title">
|
||||
Loading...
|
||||
</li>
|
||||
<li class="search-container hide" id="search-wrapper">
|
||||
<input id="search" class="search_input" type="text" title="Search for songs..." placeholder="Find song on YouTube..." onsubmit="null;" autocomplete="off" />
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul class="right control-list noselect">
|
||||
<li id="search_loader" class="valign-wrapper hide">
|
||||
<div class="valign">
|
||||
<div class="preloader-wrapper small active">
|
||||
<div class="spinner-layer spinner-blue">
|
||||
<div class="circle-clipper left">
|
||||
<div class="circle"></div>
|
||||
</div><div class="gap-patch">
|
||||
<div class="circle"></div>
|
||||
</div><div class="circle-clipper right">
|
||||
<div class="circle"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="spinner-layer spinner-red">
|
||||
<div class="circle-clipper left">
|
||||
<div class="circle"></div>
|
||||
</div><div class="gap-patch">
|
||||
<div class="circle"></div>
|
||||
</div><div class="circle-clipper right">
|
||||
<div class="circle"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="spinner-layer spinner-yellow">
|
||||
<div class="circle-clipper left">
|
||||
<div class="circle"></div>
|
||||
</div><div class="gap-patch">
|
||||
<div class="circle"></div>
|
||||
</div><div class="circle-clipper right">
|
||||
<div class="circle"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="spinner-layer spinner-green">
|
||||
<div class="circle-clipper left">
|
||||
<div class="circle"></div>
|
||||
</div><div class="gap-patch">
|
||||
<div class="circle"></div>
|
||||
</div><div class="circle-clipper right">
|
||||
<div class="circle"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<a class="nav-btn" href="#find" id="search-btn">
|
||||
<i class="mdi-action-search"></i>
|
||||
<span class="hover-text">Find</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="nav-btn" href="#skip" id="skip">
|
||||
<i class="mdi-av-skip-next"></i>
|
||||
<span class="hover-text">Skip</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="nav-btn hide-on-small-only" href="#stir" id="shuffle">
|
||||
<i class="mdi-av-shuffle"></i>
|
||||
<span class="hover-text">Stir</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="nav-btn" href="#settings" data-activates="settings-bar" id="settings">
|
||||
<i class="mdi-action-settings"></i>
|
||||
<span class="hover-text">Conf</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="side-nav" id="settings-bar">
|
||||
<?php include("php/panel.php");?>
|
||||
</ul>
|
||||
<div id="results" class="search_results hide">
|
||||
<div id="temp-results-container">
|
||||
<div id="temp-results" class="result-object">
|
||||
<div id="result" class="result">
|
||||
<img class="thumb" src="/static/images/loading.png" alt="Thumb"/>
|
||||
|
||||
<div class="search-title truncate"></div>
|
||||
<span class="result_info"></span>
|
||||
|
||||
<div class="waves-effect waves-orange btn-flat" id="add-many" title="Add several videos">
|
||||
<i class="mdi-av-playlist-add"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="empty-results-container">
|
||||
<div id='empty-results' class='valign-wrapper'>
|
||||
<span class='valign'>No results found..</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
<div id="help" class="modal">
|
||||
<div class="modal-content">
|
||||
<h4>So you need help?</h4>
|
||||
<p>When listening on a channel, there are some different buttons you can click.</p>
|
||||
<p>If you click the cogwheel, you'll open the settings panel. Here you can change channel settings, decide if you want the computer you're on can be remote-controlled, and import playlists from YouTube.</p>
|
||||
<p>The search-icon, opens up a search inputfield. If you start typing here, the site will automagically search for your input!</p>
|
||||
<p>If you click the button next to the search icon, you'll skip on a song. The one next to that one, is shuffleling of the list. Next one there again is to open the chat.</p>
|
||||
<p>Clicking a song in the playlist, gives it a vote. If you're logged in, you'll have a delete button at your disposal.</p>
|
||||
<p>Also, whenever you're logged in, you'll have two tabs in the top of the playlist thats called "Playlist" and "Suggested". The playlist obviously shows the playlist. But the suggested tab, shows 5 songs that YouTube recommends based on the current song. There might also be user recommended songs. To add any of these, just click them as you'd click a song to vote.</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a href="#!" class=" modal-action modal-close waves-effect waves-green btn-flat">Close</a>
|
||||
</div>
|
||||
</div>
|
||||
<div id="embed" class="modal">
|
||||
<div class="modal-content">
|
||||
<h4>Embed code</h4>
|
||||
<p>Copy the code in the textarea, and paste on your website.</p>
|
||||
<p>
|
||||
<input type="checkbox" id="autoplay" checked="checked" />
|
||||
<label for="autoplay">Autoplay</label>
|
||||
</p>
|
||||
<textarea id="embed-area"></textarea>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a href="#!" class=" modal-action modal-close waves-effect waves-green btn-flat">Close</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<div id="channel-load" class="progress">
|
||||
<div class="indeterminate" id="channel-load-move"></div>
|
||||
</div>
|
||||
<main class="container center-align main">
|
||||
<div id="main-row" class="row">
|
||||
<div id="video-container" class="col s12 m9 video-container no-opacity click-through">
|
||||
<!--
|
||||
width: calc(100% - 261px);
|
||||
display: inline;
|
||||
-->
|
||||
<div id="player" class="ytplayer"></div>
|
||||
<div id="main_components">
|
||||
<div id="player_overlay" class="hide valign-wrapper">
|
||||
<div id="player_overlay_text" class="valign center-align">
|
||||
Waiting for Video
|
||||
</div>
|
||||
</div>
|
||||
<div id="controls" class="noselect">
|
||||
<div id="playpause">
|
||||
<i id="play" class="mdi-av-play-arrow hide"></i>
|
||||
<i id="pause" class="mdi-av-pause"></i>
|
||||
</div>
|
||||
<div id="duration"></div>
|
||||
<div id="fullscreen">
|
||||
<i class="mdi-navigation-fullscreen"></i>
|
||||
</div>
|
||||
<div id="volume-button">
|
||||
<i id="v-mute" class="mdi-av-volume-off"></i>
|
||||
<i id="v-low" class="mdi-av-volume-mute"></i>
|
||||
<i id="v-medium" class="mdi-av-volume-down"></i>
|
||||
<i id="v-full" class="mdi-av-volume-up"></i>
|
||||
</div>
|
||||
<div id="volume"></div>
|
||||
<div id="viewers"></div>
|
||||
<div id="bar"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="playlist" class="col s12 m3">
|
||||
<div id="top-button" title="Scroll to the top" class="rounded-bottom hide top-button-with-tabs hide-on-small-only">Top</div>
|
||||
<div id="bottom-button" title="Scroll to the bottom" class="rounded-top hide hide-on-small-only">Bottom</div>
|
||||
<ul class="tabs playlist-tabs" style="width:96%">
|
||||
<li class="tab col s3"><a class="playlist-tab-links playlist-link active" href="#wrapper">Playlist</a></li>
|
||||
<li class="tab col s3"><a class="playlist-tab-links chat-link" href="#chat">Chat</a></li>
|
||||
</ul>
|
||||
<ul class="tabs playlist-tabs-loggedIn hide" style="width: 96%;">
|
||||
<li class="tab col s3"><a class="playlist-tab-links playlist-link active" href="#wrapper">Playlist</a></li>
|
||||
<li class="tab col s3"><a class="playlist-tab-links suggested-link" href="#suggestions">Suggested</a></li>
|
||||
<li class="tab col s3"><a class="playlist-tab-links chat-link" href="#chat">Chat</a></li>
|
||||
</ul>
|
||||
<div id="wrapper" class="tabs_height">
|
||||
<div id="list-song-html">
|
||||
<div id="list-song" class="card left-align list-song">
|
||||
<div class="clickable vote-container" title="Vote!">
|
||||
<a class="clickable center-align votebg">
|
||||
<span class="lazy card-image cardbg list-image" style="background-image:url('/static/images/loading.png');"></span>
|
||||
</a>
|
||||
<span class="card-content">
|
||||
<span class="flow-text truncate list-title"></span>
|
||||
<span class="vote-span">
|
||||
<span class="list-votes"></span>
|
||||
<span class="highlighted vote-text"> votes</span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="card-action center-align list-remove hide">
|
||||
<a title="Remove song" id="del" class="waves-effect btn-flat clickable">Delete</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="suggestions" class="tabs_height" style="display:none;">
|
||||
<p class="suggest-title-info">YouTube Suggests:</p>
|
||||
<div class="suggest_bar" id="suggest-song-html">
|
||||
</div>
|
||||
<p class="suggest-title-info" id="user_suggests">Users Suggests:</p>
|
||||
<div class="suggest_bar" id="user-suggest-html">
|
||||
</div>
|
||||
</div>
|
||||
<div id="chatPlaylist" class="tabs_height" style="display:none;">
|
||||
<ul class="" id="chat-bar">
|
||||
<li id="chat-log">
|
||||
<ul class="inherit-height">
|
||||
<li class="active inherit-height">
|
||||
<!--<ul id="chat inherit-height">-->
|
||||
<div class="row inherit-height">
|
||||
<div class="col s12">
|
||||
<ul class="tabs chatTabs">
|
||||
<li class="tab col s3 chat-tab-li"><a class="active chat-tab truncate" href="#channelchat"><?php echo $list; ?></a></li>
|
||||
<li class="tab col s3 chat-tab-li"><a class="chat-tab" href="#all_chat">All</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="channelchat" class="col s12 inherit-height"><ul id="chatchannel" class="inherit-height"></ul></div>
|
||||
<div id="all_chat" class="col s12 inherit-height"><ul id="chatall" class="inherit-height"></ul></div>
|
||||
</div>
|
||||
<!--</ul>-->
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li id="chat-input">
|
||||
<form action="#" id="chatForm">
|
||||
<input id="text-chat-input" name="input" type="text" autocomplete="off" placeholder="Chat" maxlength="150" />
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="playbar">
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php include("php/footer.php"); ?>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"short_name": "Zöff",
|
||||
"name": "Zöff",
|
||||
"icons": [
|
||||
{
|
||||
"src": "static/images/144x144.png",
|
||||
"sizes": "144x144",
|
||||
"type": "image/png"
|
||||
}
|
||||
],
|
||||
"start_url": "/",
|
||||
"display": "standalone",
|
||||
"orientation": "portrait"
|
||||
}
|
||||
6367
package-lock.json
generated
Normal file
64
package.json
Normal file
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"name": "zoff",
|
||||
"version": "2.0.2",
|
||||
"description": "Zoff, the shared YouTube based radio services",
|
||||
"main": "server/app.js",
|
||||
"scripts": {
|
||||
"start": "npm install --only=dev && npm install && $(npm bin)/gulp build && node server/app.js",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/zoff-music/zoff.git"
|
||||
},
|
||||
"author": {
|
||||
"name": "Kasper Rynning Tønnesen",
|
||||
"email": "kasper@kasperrt.no"
|
||||
},
|
||||
"license": "ISC",
|
||||
"bugs": {
|
||||
"url": "https://github.com/zoff-music/zoff/issues"
|
||||
},
|
||||
"devDependencies": {
|
||||
"gulp": "^4.0.0",
|
||||
"gulp-concat": "^2.6.1",
|
||||
"gulp-uglify": "^3.0.2"
|
||||
},
|
||||
"homepage": "https://github.com/zoff-music/zoff#readme",
|
||||
"dependencies": {
|
||||
"bad-words": "^1.6.5",
|
||||
"bcrypt-nodejs": "0.0.3",
|
||||
"body-parser": "^1.18.3",
|
||||
"color-thief-jimp": "^2.0.2",
|
||||
"compression": "^1.7.3",
|
||||
"connect-mongo": "^2.0.3",
|
||||
"cookie-parser": "^1.4.4",
|
||||
"cors": "^2.8.5",
|
||||
"express": "^4.16.4",
|
||||
"express-handlebars": "^3.0.2",
|
||||
"express-recaptcha": "^3.0.1",
|
||||
"express-session": "^1.15.6",
|
||||
"farmhash": "^3.0.0",
|
||||
"feature-policy": "^0.2.0",
|
||||
"gulp-clean-css": "^4.2.0",
|
||||
"gulp-sourcemaps": "^2.6.5",
|
||||
"gulp-uglify-es": "^1.0.4",
|
||||
"helmet": "^3.21.1",
|
||||
"jimp": "^0.2.28",
|
||||
"mongodb": "^2.2.36",
|
||||
"mongojs": "^2.6.0",
|
||||
"mongojs-paginate": "^1.2.0",
|
||||
"mongoose": "^5.7.5",
|
||||
"mpromise": "^0.5.5",
|
||||
"nodemailer": "^4.7.0",
|
||||
"passport": "^0.4.0",
|
||||
"passport-local": "^1.0.0",
|
||||
"redis": "^2.8.0",
|
||||
"referrer-policy": "^1.1.0",
|
||||
"request": "^2.88.0",
|
||||
"socket.io": "^2.2.0",
|
||||
"socket.io-redis": "^5.2.0",
|
||||
"sticky-session": "^1.1.2",
|
||||
"uniqid": "5.0.3"
|
||||
}
|
||||
}
|
||||
93
php/bot.php
@@ -1,93 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb#">
|
||||
<?php include("header.php"); ?>
|
||||
<link rel="chrome-webstore-item" href="https://chrome.google.com/webstore/detail/jemjlblambcgjmmhheaklfnphncdmfmb" />
|
||||
</head>
|
||||
<body class="noselect cursor-default">
|
||||
<header>
|
||||
<nav id="fp-nav">
|
||||
<div class="nav-wrapper">
|
||||
<a href="//zoff.no" class="brand-logo hide-on-small-only">
|
||||
<img id="zicon" src="/static/images/squareicon_small.png" alt="zöff" title="Zöff" />
|
||||
</a>
|
||||
<a href="//zoff.no" class="brand-logo hide-on-med-and-up">Zöff</a>
|
||||
<ul id="nav-mobile" class="right hide-on-med-and-down">
|
||||
<li><a class="modal-trigger waves-effect waves-red" title="Need help with the site?" onclick="$('#help').openModal()">Help</a></li>
|
||||
<li><a class="waves-effect green" title="Remote control a Zöff player" href="https://remote.zoff.no">Remote</a></li>
|
||||
<li><a class="modal-trigger waves-effect waves-orange" onclick="$('#about').openModal()">About</a></li>
|
||||
<li><a class="modal-trigger waves-effect waves-yellow" onclick="$('#legal').openModal()">Legal</a></li>
|
||||
<li><a class="waves-effect waves-purple" href="https://github.com/zoff-music/">GitHub</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
<div id="legal" class="modal">
|
||||
<div class="modal-content">
|
||||
<h4>Legal</h4>
|
||||
<p>Copyright © 2015 <br>Nicolas Almagro Tonne and Kasper Rynning-Tønnesen
|
||||
<br><br>
|
||||
Creative Commons License<br>
|
||||
Zöff is licensed under a <br><a href="http://creativecommons.org/licenses/by-nc-nd/3.0/no/">Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Norway License.</a>
|
||||
<br>
|
||||
Do not redistribute without permission from the developers.
|
||||
<br>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a href="#!" class=" modal-action modal-close waves-effect waves-green btn-flat">Close</a>
|
||||
</div>
|
||||
</div>
|
||||
<div id="about" class="modal">
|
||||
<div class="modal-content">
|
||||
<h4>About</h4>
|
||||
<p>Zöff is a shared (free) YouTube based radio service, built upon the YouTube API. <br><br>
|
||||
Zöff is mainly a webbased service. The website uses <a href="https://nodejs.org/">NodeJS</a> with <a href="http://socket.io/">Socket.IO</a>, <a href="https://www.mongodb.org/">MongoDB</a> and PHP on the backend, with JavaScript, jQuery and <a href="http://materializecss.com/">Materialize</a> on the frontend. More about the project itself can be found on <a href="https://github.com/zoff-music/Zoff">GitHub</a><br><br>
|
||||
The team consists of Kasper Rynning-Tønnesen and Nicolas Almagro Tonne, and the project has been worked on since late 2014.<br><br>
|
||||
The team can be reached on <a href="mailto:contact@zoff.no?Subject=Contact%20Zoff">contact@zoff.no</a>
|
||||
</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a href="#!" class=" modal-action modal-close waves-effect waves-green btn-flat">Close</a>
|
||||
</div>
|
||||
</div>
|
||||
<div id="help" class="modal">
|
||||
<div class="modal-content">
|
||||
<h4>So you need help?</h4>
|
||||
<p>To remote-controll a computer, just type in the ID for that computer. (This can be found in the settings panel on the computer you want to remote controll. There is also a QR code for you to scan.</p>
|
||||
<p>When you've entered the ID for the computer you want to controll, you'll be able to change the volume, have the controlled computer vote for skipping, pause the video or play the video.</p>
|
||||
<p>The inputfield you used to enter the ID (if you entered it), has now changed some. If you type in something here now, the controlled computer will change channel!</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a href="#!" class=" modal-action modal-close waves-effect waves-green btn-flat">Close</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="center-align container remote-container">
|
||||
<div class="section">
|
||||
<h3 id="remote-text">Twitch Bot</h3>
|
||||
<div class="row">
|
||||
<div class="col s6">
|
||||
<p>
|
||||
Commands
|
||||
</p>
|
||||
<p>
|
||||
join
|
||||
</p>
|
||||
<p>
|
||||
leave
|
||||
</p>
|
||||
<p>
|
||||
np
|
||||
</p>
|
||||
</div>
|
||||
<div class="col s6">Sign up</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php include("footer.php"); ?>
|
||||
|
||||
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jqueryui-touch-punch/0.2.3/jquery.ui.touch-punch.min.js"></script>
|
||||
<!--<script type="text/javascript" src="/static/dist/remote.min.js"></script>-->
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,117 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb#">
|
||||
<?php include("header.php"); ?>
|
||||
<link rel="chrome-webstore-item" href="https://chrome.google.com/webstore/detail/jemjlblambcgjmmhheaklfnphncdmfmb" />
|
||||
</head>
|
||||
<body class="noselect cursor-default">
|
||||
<header>
|
||||
<nav id="fp-nav">
|
||||
<div class="nav-wrapper">
|
||||
<a href="//zoff.no" class="brand-logo hide-on-small-only">
|
||||
<img id="zicon" src="/static/images/squareicon_small.png" alt="zöff" title="Zöff" />
|
||||
</a>
|
||||
<a href="//zoff.no" class="brand-logo hide-on-med-and-up">Zöff</a>
|
||||
<ul id="nav-mobile" class="right hide-on-med-and-down">
|
||||
<li><a class="modal-trigger waves-effect waves-red" title="Need help with the site?" onclick="$('#help').openModal()">Help</a></li>
|
||||
<li><a class="waves-effect green" title="Remote control a Zöff player" href="https://remote.zoff.no">Remote</a></li>
|
||||
<li><a class="modal-trigger waves-effect waves-orange" onclick="$('#about').openModal()">About</a></li>
|
||||
<li><a class="modal-trigger waves-effect waves-yellow" onclick="$('#legal').openModal()">Legal</a></li>
|
||||
<li><a class="waves-effect waves-purple" href="https://github.com/zoff-music/">GitHub</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
<div id="legal" class="modal">
|
||||
<div class="modal-content">
|
||||
<h4>Legal</h4>
|
||||
<p>Copyright © 2015 <br>Nicolas Almagro Tonne and Kasper Rynning-Tønnesen
|
||||
<br><br>
|
||||
Creative Commons License<br>
|
||||
Zöff is licensed under a <br><a href="http://creativecommons.org/licenses/by-nc-nd/3.0/no/">Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Norway License.</a>
|
||||
<br>
|
||||
Do not redistribute without permission from the developers.
|
||||
<br>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a href="#!" class=" modal-action modal-close waves-effect waves-green btn-flat">Close</a>
|
||||
</div>
|
||||
</div>
|
||||
<div id="about" class="modal">
|
||||
<div class="modal-content">
|
||||
<h4>About</h4>
|
||||
<p>Zöff is a shared (free) YouTube based radio service, built upon the YouTube API. <br><br>
|
||||
Zöff is mainly a web-based service. The website uses <a href="https://nodejs.org/">NodeJS</a> with <a href="http://socket.io/">Socket.IO</a>, <a href="https://www.mongodb.org/">MongoDB</a> and PHP on the backend, with JavaScript, jQuery and <a href="http://materializecss.com/">Materialize</a> on the frontend. More about the project itself can be found on <a href="https://github.com/zoff-music/Zoff">GitHub</a><br><br>
|
||||
The team consists of Kasper Rynning-Tønnesen and Nicolas Almagro Tonne, and the project has been worked on since late 2014.<br><br>
|
||||
The team can be reached on <a href="mailto:contact@zoff.no?Subject=Contact%20Zoff">contact@zoff.no</a>
|
||||
</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a href="#!" class=" modal-action modal-close waves-effect waves-green btn-flat">Close</a>
|
||||
</div>
|
||||
</div>
|
||||
<div id="help" class="modal">
|
||||
<div class="modal-content">
|
||||
<h4>So you need help?</h4>
|
||||
<p>To remote-control a computer, just type in the ID for that computer. (This can be found in the settings panel on the computer you want to remote control. There is also a QR code for you to scan.</p>
|
||||
<p>When you've entered the ID for the computer you want to control, you'll be able to change the volume, have the controled computer vote for skipping, pause the video or play the video.</p>
|
||||
<p>The input field you used to enter the ID (if you entered it), has now changed some. If you type in something here now, the controled computer will change channel!</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a href="#!" class=" modal-action modal-close waves-effect waves-green btn-flat">Close</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="center-align container remote-container">
|
||||
<div class="section">
|
||||
<h3 id="remote-text">Remote Controller</h3>
|
||||
</div>
|
||||
<div class="section">
|
||||
<form action="#" class="row" id="remoteform">
|
||||
<div class="input-field col s12">
|
||||
<input
|
||||
class="input-field"
|
||||
type="text"
|
||||
id="search"
|
||||
name="chan"
|
||||
title="Type channel name here to create or listen to a channel. Only alphanumerical chars. [a-zA-Z0-9]+"
|
||||
autocomplete="off"
|
||||
spellcheck="false"
|
||||
maxlength="10"
|
||||
data-length="10"
|
||||
/>
|
||||
<label for="search" id="forsearch">Type ID of host to be controlled</label>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="rc" id="remote-controls">
|
||||
<a id="playbutton" class="remote-button chan-link waves-effect btn green">
|
||||
<i id="remote_play" class="mdi-av-play-arrow"></i>
|
||||
</a>
|
||||
<a id="pausebutton" class="remote-button chan-link waves-effect btn gray">
|
||||
<i id="remote_pause" class="mdi-av-pause"></i>
|
||||
</a>
|
||||
<a id="skipbutton" class="remote-button chan-link waves-effect btn blue">
|
||||
<i id="remote_skip" class="mdi-av-skip-next"></i>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<i class="mdi-av-volume-up slider-vol rc"></i>
|
||||
<div class="rc" id="volume-control" title="Volume"></div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="section about-remote">
|
||||
<b>Here you can control another Zöff player from any device.</b>
|
||||
<br>
|
||||
To find the ID of your player, click the Conf <i class="mdi-action-settings"></i> icon on the top right of the player page, then "Remote Control".
|
||||
<br>You can either scan the QR code or type the ID manually.
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php include("footer.php"); ?>
|
||||
|
||||
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jqueryui-touch-punch/0.2.3/jquery.ui.touch-punch.min.js"></script>
|
||||
<script type="text/javascript" src="/static/dist/remote.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
138
php/footer.php
@@ -1,138 +0,0 @@
|
||||
<div id="contact" class="modal">
|
||||
<div class="modal-content">
|
||||
<h4>Want to contact us?</h4>
|
||||
<div id="contact-container">
|
||||
<form id="contact-form" method="post" onsubmit="return false;">
|
||||
<div class="input-field">
|
||||
<input id="contact-form-from" name="from" type="email" autocomplete="off" class="validate" />
|
||||
<label for="contact-form-from" class="noselect">Email</label>
|
||||
</div>
|
||||
<div class="input-field">
|
||||
<input id="contact-form-message" name="message" type="text" autocomplete="off">
|
||||
<label for="contact-form-message" class="noselect">Message</label>
|
||||
</div>
|
||||
<button class="contact-button-submit" action="submit" id="submit-contact-form">Send</button>
|
||||
<div class="valign hide" id="send-loader">
|
||||
<div class="preloader-wrapper small active">
|
||||
<div class="spinner-layer spinner-blue">
|
||||
<div class="circle-clipper left">
|
||||
<div class="circle"></div>
|
||||
</div><div class="gap-patch">
|
||||
<div class="circle"></div>
|
||||
</div><div class="circle-clipper right">
|
||||
<div class="circle"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="spinner-layer spinner-red">
|
||||
<div class="circle-clipper left">
|
||||
<div class="circle"></div>
|
||||
</div><div class="gap-patch">
|
||||
<div class="circle"></div>
|
||||
</div><div class="circle-clipper right">
|
||||
<div class="circle"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="spinner-layer spinner-yellow">
|
||||
<div class="circle-clipper left">
|
||||
<div class="circle"></div>
|
||||
</div><div class="gap-patch">
|
||||
<div class="circle"></div>
|
||||
</div><div class="circle-clipper right">
|
||||
<div class="circle"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="spinner-layer spinner-green">
|
||||
<div class="circle-clipper left">
|
||||
<div class="circle"></div>
|
||||
</div><div class="gap-patch">
|
||||
<div class="circle"></div>
|
||||
</div><div class="circle-clipper right">
|
||||
<div class="circle"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a href="#!" class=" modal-action modal-close waves-effect waves-green btn-flat">Close</a>
|
||||
</div>
|
||||
</div>
|
||||
<footer class="page-footer cursor-default">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col l6 s12">
|
||||
<h5 class="white-text">Zöff</h5>
|
||||
<p class="grey-text text-lighten-4">The shared YouTube radio</p>
|
||||
<p class="grey-text text-lighten-4">
|
||||
Being built around the YouTube search and video API
|
||||
it enables the creation of collaborative and shared live playlists,
|
||||
with billions of videos and songs to choose from, all for free and without registration.
|
||||
<br />
|
||||
Enjoy!
|
||||
</p>
|
||||
<ul id="footer-buttons">
|
||||
<li>
|
||||
<a class="modal-trigger waves-effect cyan darken-2 btn help-button-footer" title="Need help with the site?" onclick="$('#help').openModal()">
|
||||
<i class="material-icons left footer-button-icon">info_outline</i>HELP
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="modal-trigger waves-effect blue-grey darken-2 btn help-button-footer hide-on-small-only" id="embed-button" title="Want to embed this channel?" onclick="$('#embed').openModal()">
|
||||
<i class="material-icons left footer-button-icon">code</i>EMBED
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="modal-trigger waves-effect red darken-2 btn help-button-footer" id="contact-button" title="Contact us" onclick="$('#contact').openModal()">
|
||||
<i class="mdi-communication-email left footer-button-icon"></i>CONTACT
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<p id="latest-commit" class="grey-text text-lighten-4 truncate"></p>
|
||||
</div>
|
||||
<div class="col l4 offset-l2 s12 valign-wrapper">
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://github.com/zoff-music/">
|
||||
<img title="Contribute on GitHub" src="/static/images/GitHub_Logo.png" alt="GitHub" />
|
||||
</a>
|
||||
<p>
|
||||
<a id="facebook-code-link" class="waves-effect waves-light btn light-blue share shareface" href="https://www.facebook.com/sharer/sharer.php?u=http://<?php echo $_SERVER['HTTP_HOST'].'/'.$list; ?>" target="popup" onclick="window.open('https://www.facebook.com/sharer/sharer.php?u=http://<?php echo $_SERVER['HTTP_HOST'].'/'.$list; ?>','Share Playlist','width=600,height=300')">
|
||||
<img class="left" src="/static/images/facebook.png" alt="Share on Facebook" />Share on Facebook
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
<a id="twitter-code-link" class="waves-effect waves-light btn light-blue share" href="http://twitter.com/intent/tweet?url=http://<?php echo $_SERVER['HTTP_HOST'].'/'.$list; ?>&text=Check%20out%20this%20playlist%20<?php echo ucfirst($list); ?>%20on%20Zöff!&via=zoffmusic" target="popup" onclick="window.open('http://twitter.com/intent/tweet?url=http://<?php echo $_SERVER['HTTP_HOST'].'/'.$list; ?>&text=Check%20out%20this%20playlist%20<?php echo ucfirst($list); ?>%20on%20Zöff!&via=zoffmusic','Share Playlist','width=600,height=300')">
|
||||
<img class="left" src="/static/images/twitter.png" alt="Share on Twitter" />Share on Twitter
|
||||
</a>
|
||||
</p>
|
||||
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_blank" id="donate_form">
|
||||
<input type="hidden" name="cmd" value="_s-xclick">
|
||||
<input type="hidden" name="hosted_button_id" value="JEXDYP59N5VWE">
|
||||
<a title="Like what we made? Help us by donating (a) beer!" class="waves-effect waves-light btn orange light-blue share" onclick="document.getElementById('donate_form').submit();">
|
||||
<i class="mdi-action-payment left footer-button-icon"></i>Donate
|
||||
</a>
|
||||
</form>
|
||||
<p class="hide-on-small-only">
|
||||
<a id="qr-code-link" target="_blank" href="//chart.googleapis.com/chart?chs=500x500&cht=qr&chl=http://<?php echo $_SERVER['HTTP_HOST'].'/'.$list; ?>&choe=UTF-8&chld=L%7C1" >
|
||||
<img id="qr-code-image-link" class="card rounded" src="//chart.googleapis.com/chart?chs=150x150&cht=qr&chl=http://<?php echo $_SERVER['HTTP_HOST'].'/'.$list; ?>&choe=UTF-8&chld=L%7C1" alt="QRCode for link" title="QR code for this page, for easy sharing!" />
|
||||
</a>
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer-copyright">
|
||||
<div class="container">
|
||||
© <?php echo date("Y"); ?>
|
||||
<a href="http://nixo.no">Nixo</a> &
|
||||
<a href="http://kasperrt.no">KasperRT</a>
|
||||
All Rights Reserved.
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
@@ -1,45 +0,0 @@
|
||||
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
| Zöff |
|
||||
| Project is on github: https://github.com/zoff-music/Zoff |
|
||||
| Made by: Nicolas Almagro Tonne and Kasper Rynning-Tønnesen |
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||
|
||||
<title>Zöff</title>
|
||||
<meta name="author" content="Nicolas 'Nixo' Almagro Tonne & Kasper 'KasperRT' Rynning-Tønnesen"/>
|
||||
<meta name="description" content="The Shared (free) YouTube radio. Being built around the YouTube search and video API it enables the creation of collaborative and shared live playlists, with billions of videos and songs to choose from, all for free and without registration. Enjoy!"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no"/>
|
||||
<meta charset="UTF-8"/>
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="mobile-web-app-capable" content="yes">
|
||||
<meta name="theme-color" content="#2D2D2D" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
<meta property="og:image" content="/static/images/favicon.png" />
|
||||
<meta property="og:title" content="Zöff"/>
|
||||
<meta property="og:description" content="The Shared (free) YouTube radio. Being built around the YouTube search and video API it enables the creation of collaborative and shared live playlists, with billions of videos and songs to choose from, all for free and without registration. Enjoy!"/>
|
||||
<meta property="og:type" content="website"/>
|
||||
<link rel="manifest" href="/manifest.json">
|
||||
<link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.min.css">
|
||||
<link tyle="text/css" rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />
|
||||
<link type="text/css" rel="stylesheet" href="/static/css/materialize.min.css" />
|
||||
<link rel="stylesheet" type="text/css" href="/static/css/style.css" title="Default" />
|
||||
<link rel="icon" id="favicon" type="image/png" href="/static/images/favicon.png"/>
|
||||
<script>
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
ga('create', '***REMOVED***', 'auto');
|
||||
ga('send', 'pageview');
|
||||
|
||||
</script>
|
||||
|
||||
<script type="text/javascript" src="/static/dist/lib/jquery-2.1.3.min.js"></script>
|
||||
<script type="text/javascript" src="/static/dist/lib/jquery-ui-1.10.3.min.js"></script>
|
||||
<script type="text/javascript" src="/static/dist/lib/materialize.min.js"></script>
|
||||
<script type="text/javascript" src="/static/dist/lib/socket.io-1.4.5.js"></script>
|
||||
<script type="text/javascript" src="/static/dist/lib/jquery.lazyload.js"></script>
|
||||
<script type="text/javascript" src="/static/dist/lib/color-thief.js"></script>
|
||||
<script type="text/javascript" src="/static/dist/lib/sha256.js"></script>
|
||||
<script type="text/javascript" src="/static/dist/lib/aes.js"></script>
|
||||
@@ -1,18 +0,0 @@
|
||||
<?php
|
||||
|
||||
$url = file_get_contents("https://img.youtube.com/vi/".$_POST['id']."/mqdefault.jpg");
|
||||
|
||||
$image = new Imagick();
|
||||
$image->readImageBlob($url);
|
||||
|
||||
|
||||
$image->blurImage(30,50);
|
||||
|
||||
$output = $image->getimageblob();
|
||||
|
||||
$image->setImageFormat("jpeg");
|
||||
|
||||
file_put_contents ("../static/images/thumbnails/".$_POST['id'].".jpg", $image);
|
||||
|
||||
echo base64_encode($output);
|
||||
?>
|
||||
22
php/mail.php
@@ -1,22 +0,0 @@
|
||||
<?php
|
||||
|
||||
if(isset($_POST['from']) && isset($_POST['message'])){
|
||||
|
||||
$from = htmlspecialchars($_POST['from']);
|
||||
$message = htmlspecialchars($_POST['message']);
|
||||
$headers = "From: " . $from . "\r\n";
|
||||
|
||||
if(filter_var($from, FILTER_VALIDATE_EMAIL) && $message != ""){
|
||||
$result = mail("contact@zoff.no", "Contact from form", $message, $headers);
|
||||
|
||||
if($result == FALSE){
|
||||
echo "failure";
|
||||
}else{
|
||||
echo "success";
|
||||
}
|
||||
}else{
|
||||
echo "failure";
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
177
php/nochan.php
@@ -1,177 +0,0 @@
|
||||
<?php
|
||||
|
||||
if(isset($_GET['chan'])){
|
||||
$chan = htmlspecialchars($_GET['chan']);
|
||||
header('Location: '.$chan);
|
||||
}
|
||||
|
||||
?>
|
||||
<html lang="en">
|
||||
<head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb#">
|
||||
<?php include("header.php"); ?>
|
||||
<script type="text/javascript" src="/static/dist/main.min.js"></script>
|
||||
</head>
|
||||
<body class="noselect cursor-default">
|
||||
<header>
|
||||
<nav id="fp-nav">
|
||||
<div class="nav-wrapper">
|
||||
<a href="#" class="brand-logo hide-on-small-only noselect">
|
||||
<img id="zicon" src="static/images/squareicon_small.png" alt="zöff" title="Zöff" />
|
||||
</a>
|
||||
<span id="frontpage-viewer-counter" class="hide-on-small-only noselect" title="Divided among all channels. Hidden or not"></span>
|
||||
<a href="//zoff.no" class="brand-logo brand-mobile hide-on-med-and-up">Zöff</a>
|
||||
<ul id="nav-mobile" class="right hide-on-med-and-down">
|
||||
<li><a class="modal-trigger waves-effect waves-red" title="Need help with the site?" onclick="$('#help').openModal()">Help</a></li>
|
||||
<li><a class="waves-effect green" title="Remote control a Zöff player" href="https://remote.zoff.no">Remote</a></li>
|
||||
<li><a class="modal-trigger waves-effect waves-orange" onclick="$('#about').openModal()">About</a></li>
|
||||
<li><a class="modal-trigger waves-effect waves-yellow" onclick="$('#legal').openModal()">Legal</a></li>
|
||||
<li><a class="waves-effect waves-purple" href="https://github.com/zoff-music/">GitHub</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
<div id="legal" class="modal">
|
||||
<div class="modal-content">
|
||||
<h4>Legal</h4>
|
||||
<p>Copyright © 2015 <br>Nicolas Almagro Tonne and Kasper Rynning-Tønnesen
|
||||
<br><br>
|
||||
Creative Commons License<br>
|
||||
Zöff is licensed under a <br><a href="http://creativecommons.org/licenses/by-nc-nd/3.0/no/">Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Norway License.</a>
|
||||
<br>
|
||||
Do not redistribute without permission from the developers.
|
||||
<br>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a href="#" class="modal-action modal-close waves-effect waves-green btn-flat">Close</a>
|
||||
</div>
|
||||
</div>
|
||||
<div id="about" class="modal">
|
||||
<div class="modal-content">
|
||||
<h4>About</h4>
|
||||
<p>Zöff is a shared (free) YouTube based radio service, built upon the YouTube API. <br><br>
|
||||
Zöff is mainly a web-based service. The website uses <a href="https://nodejs.org/">NodeJS</a> with <a href="http://socket.io/">Socket.IO</a>, <a href="https://www.mongodb.org/">MongoDB</a> and PHP on the backend, with JavaScript, jQuery and <a href="http://materializecss.com/">Materialize</a> on the frontend. More about the project itself can be found on <a href="https://github.com/zoff-music/Zoff">GitHub</a><br><br>
|
||||
The team consists of Kasper Rynning-Tønnesen and Nicolas Almagro Tonne, and the project has been worked on since late 2014.<br><br>
|
||||
The team can be reached on <a href="mailto:contact@zoff.no?Subject=Contact%20Zoff">contact@zoff.no</a><br><br>
|
||||
</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a href="#" class="modal-action modal-close waves-effect waves-green btn-flat">Close</a>
|
||||
</div>
|
||||
</div>
|
||||
<div id="donation" class="modal">
|
||||
<div class="modal-content">
|
||||
<h4>Thanks!</h4>
|
||||
<p>Thanks for your donation, we love you <3
|
||||
<br><br>
|
||||
We will use the money for something awesome, just you wait and see!
|
||||
<br><br>
|
||||
We might also add your name somewhere in the code as a sign of gratitude, see if you can find it! (Might take a day or two for us to see the donation and implement it..)
|
||||
</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a href="#" class="modal-action modal-close waves-effect waves-green btn-flat">I'm awesome! (Close)</a>
|
||||
</div>
|
||||
</div>
|
||||
<div id="help" class="modal">
|
||||
<div class="modal-content">
|
||||
<h4>So you need help?</h4>
|
||||
<p>At the center of the site, you'll see a input field. This is meant to navigate to new or existing channels. If you input something here that already doesn't exist, a new channel will be create at the blink of an eye! Remember to put a password on the list you've created, so no one else takes it from you! (It's on a first come, first serve basis). When you're ready to proceed, just click the listen button!</p>
|
||||
<p>Underneath the input fields, there are several tiles. These are channels that already exists, and they can be clicked! To enter one of these channels and listen to it's content, it is just to click the tile.</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a href="#" class=" modal-action modal-close waves-effect waves-green btn-flat">Close</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</header>
|
||||
|
||||
<div class="section mega">
|
||||
<div id="mega-background"></div>
|
||||
<h5>Create a radio channel, collaborate and listen</h5>
|
||||
<form class="channel-finder" onsubmit="return false;">
|
||||
<p class="prething">zoff.no/</p>
|
||||
<input
|
||||
class="input-field room-namer"
|
||||
type="text"
|
||||
id="searchFrontpage"
|
||||
name="chan"
|
||||
placeholder="chill"
|
||||
title="Type channel name here to create or listen to a channel. Only alphanumerical chars. [a-zA-Z0-9]+"
|
||||
autocomplete="off"
|
||||
autofocus=""
|
||||
list="searches"
|
||||
required
|
||||
pattern="[a-zA-Z0-9]+"
|
||||
spellcheck="false"
|
||||
maxlength="18"
|
||||
/>
|
||||
<datalist id="searches"></datalist>
|
||||
<button class="listen-button" action="submit">Listen</button>
|
||||
</form>
|
||||
<div class="pitch outline">
|
||||
<div>Live & democratic playlists with YouTube Music</div>
|
||||
<div>Play everywhere — No login required</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section mobile-search">
|
||||
<form class="row" id="base" method="get" onsubmit="return false;">
|
||||
<div class="input-field col s12">
|
||||
<input
|
||||
class="input-field"
|
||||
type="text"
|
||||
id="search-mobile"
|
||||
name="chan"
|
||||
title="Type channel name here to create or listen to a channel. Only alphanumerical chars. [a-zA-Z0-9]+"
|
||||
autocomplete="off"
|
||||
list="searches"
|
||||
required pattern="[a-zA-Z0-9]+"
|
||||
spellcheck="false"
|
||||
maxlength="18"
|
||||
data-length="18"
|
||||
/>
|
||||
<label for="search-mobile" class="noselect">Find or create radio channel</label>
|
||||
<datalist id="searches">
|
||||
</datalist>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div id="channel-load" class="progress">
|
||||
<div class="indeterminate" id="channel-load-move"></div>
|
||||
</div>
|
||||
<main class="center-align container">
|
||||
<div id="main_section_frontpage" class="section">
|
||||
<div id="preloader" class="progress">
|
||||
<div class="indeterminate"></div>
|
||||
</div>
|
||||
<div id="channel-list-container">
|
||||
<ul class="row" id="channels">
|
||||
<li id="chan-card" class="col s12 m4 l3">
|
||||
<div class="card">
|
||||
<a class="chan-link">
|
||||
<div class="chan-bg card-image cardbg"></div>
|
||||
<div class="card-content">
|
||||
<i class="mdi-action-star-rate pin"></i>
|
||||
<p class="left-align">
|
||||
<span class="chan-name flow-text truncate"></span>
|
||||
<br>
|
||||
<span class="highlighted">Viewers: </span>
|
||||
<span class="chan-views"></span>
|
||||
<br>
|
||||
<span class="highlighted">Songs: </span>
|
||||
<span class="chan-songs"></span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="card-action noselect">
|
||||
<a class="chan-link waves-effect waves-orange btn-flat">Listen</a>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php include("php/footer.php"); ?>
|
||||
</body>
|
||||
</html>
|
||||
204
php/panel.php
@@ -1,204 +0,0 @@
|
||||
<li class="no-padding">
|
||||
<ul class="collapsible collapsible-accordion">
|
||||
<li>
|
||||
<a class="col s9 collapsible-header bold waves-effect admin-settings">
|
||||
Channel Settings
|
||||
<i class="mdi-image-tune"></i>
|
||||
<div class="nav-btn close-settings clickable" title="Close" id="closeSettings">
|
||||
<i class="mdi-navigation-close auto-margin"></i>
|
||||
</div>
|
||||
</a>
|
||||
<div class="collapsible-body">
|
||||
<form action="#" id="adminForm" onsubmit="return false;">
|
||||
<ul>
|
||||
<li class="white-bg">
|
||||
<div class="input-field field-settings">
|
||||
<i id="admin-lock" class="mdi-action-lock" title="Click to log out"></i>
|
||||
<input placeholder="Enter channel password" id="password" type="password" class="validate" />
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<span class="switch-text">
|
||||
Add songs
|
||||
</span>
|
||||
<div class="switch"><label>
|
||||
Anyone
|
||||
<input name="addsongs" type="checkbox" class="conf" /><span class="lever"></span>
|
||||
Admin
|
||||
</label></div></li>
|
||||
|
||||
<li>
|
||||
<span class="switch-text">
|
||||
Vote
|
||||
</span>
|
||||
<div class="switch"><label>
|
||||
Anyone
|
||||
<input name="vote" type="checkbox" class="conf" /><span class="lever"></span>
|
||||
Admin
|
||||
</label></div></li>
|
||||
|
||||
<li><span class="switch-text">
|
||||
Shuffle
|
||||
</span>
|
||||
<div class="switch"><label>
|
||||
Anyone
|
||||
<input name="shuffle" type="checkbox" class="conf" /><span class="lever"></span>
|
||||
Admin
|
||||
</label></div></li>
|
||||
|
||||
<li><span class="switch-text">
|
||||
Skip
|
||||
</span>
|
||||
<div class="switch"><label>
|
||||
Anyone
|
||||
<input name="skip" type="checkbox" class="conf" /><span class="lever"></span>
|
||||
Admin
|
||||
</label></div></li>
|
||||
|
||||
<li><span class="switch-text">
|
||||
Song length
|
||||
</span>
|
||||
<div class="switch"><label>
|
||||
Any
|
||||
<input name="longsongs" type="checkbox" class="conf" /><span class="lever"></span>
|
||||
Short
|
||||
</label></div></li>
|
||||
|
||||
<li><span class="switch-text">
|
||||
Type
|
||||
</span>
|
||||
<div class="switch"><label>
|
||||
Any
|
||||
<input name="allvideos" type="checkbox" class="conf" /><span class="lever"></span>
|
||||
Song
|
||||
</label></div></li>
|
||||
|
||||
|
||||
<li><span class="switch-text">
|
||||
Frontpage
|
||||
</span>
|
||||
<div class="switch"><label>
|
||||
Hide
|
||||
<input name="frontpage" type="checkbox" class="conf" /><span class="lever"></span>
|
||||
Display
|
||||
</label></div></li>
|
||||
|
||||
<li><span class="switch-text">
|
||||
After play
|
||||
</span>
|
||||
<div class="switch"><label>
|
||||
Keep
|
||||
<input name="removeplay" type="checkbox" class="conf" /><span class="lever"></span>
|
||||
Remove
|
||||
</label></div></li>
|
||||
|
||||
|
||||
</ul>
|
||||
</form>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="no-padding remote-panel">
|
||||
<ul class="collapsible collapsible-accordion">
|
||||
<li>
|
||||
<a class="collapsible-header bold waves-effect">Remote Control
|
||||
<i class="material-icons">settings_remote</i>
|
||||
</a>
|
||||
<div class="collapsible-body">
|
||||
<ul>
|
||||
<li>
|
||||
<span class="switch-text">
|
||||
Enable Remote
|
||||
</span>
|
||||
<div class="switch"><label>
|
||||
Disabled
|
||||
<input name="remote_switch" type="checkbox" class="remote_switch_class" checked /><span class="lever"></span>
|
||||
Enabled
|
||||
</label>
|
||||
</div>
|
||||
<a id="code-link" target="_blank">
|
||||
<img id="code-qr" alt="QR code for control" title="Link to control this Zöff player" src="https://chart.googleapis.com/chart?chs=221x221&cht=qr&choe=UTF-8&chld=L%7C1&chl=http://zoff.no" />
|
||||
<h4 id="code-text">ABBADUR</h4>
|
||||
</a>
|
||||
<a>
|
||||
You can control this Zöff instance from another device by going to <b>https://remote.zoff.no/</b>
|
||||
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="no-padding remote-panel">
|
||||
<ul class="collapsible collapsible-accordion">
|
||||
<li>
|
||||
<a class="collapsible-header bold waves-effect import-a">Import Playlist
|
||||
<i class="mdi-communication-import-export"></i>
|
||||
</a>
|
||||
<div class="collapsible-body">
|
||||
<ul>
|
||||
<li class="white-bg">
|
||||
<div class="input-field field-settings">
|
||||
<form action="#" id="listImport" onsubmit="return false;">
|
||||
<i class="mdi-av-playlist-add import-icon"></i>
|
||||
<input title="Input YouTube-playlist id here!" placeholder="Enter YouTube-list ID" id="import" type="text" class="validate" autocomplete="off" />
|
||||
</form>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="no-padding show-only-mobile">
|
||||
<ul class="collapsible collapsible-accordion">
|
||||
<li>
|
||||
<a class="collapsible-header bold waves-effect import-a">Remote Controller
|
||||
<i class="material-icons">settings_remote</i>
|
||||
</a>
|
||||
<div class="collapsible-body">
|
||||
<ul id="remote-mobile-container">
|
||||
<li class="white-bg">
|
||||
<p id="remote_header">Control another client</p>
|
||||
<form action="#" class="row" id="remoteform">
|
||||
<div class="input-field col s12">
|
||||
<input
|
||||
class="input-field"
|
||||
type="text"
|
||||
id="remote_channel"
|
||||
name="chan"
|
||||
autocomplete="off"
|
||||
spellcheck="false"
|
||||
maxlength="10"
|
||||
data-length="10"
|
||||
placeholder="ID to remotecontroll"
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
<button id="playbutton_remote" class="remote-button waves-effect btn green" disabled>
|
||||
<i id="remote_play" class="mdi-av-play-arrow"></i>
|
||||
</button>
|
||||
<button id="pausebutton_remote" class="remote-button waves-effect btn gray" disabled>
|
||||
<i id="remote_pause" class="mdi-av-pause"></i></button>
|
||||
<button id="skipbutton_remote" class="remote-button waves-effect btn blue" disabled>
|
||||
<i id="remote_skip" class="mdi-av-skip-next"></i>
|
||||
</button>
|
||||
<i class="mdi-av-volume-up slider-vol"></i>
|
||||
<div class="" id="volume-control-remote" title="Volume"></div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<!--
|
||||
<li class="no-padding">
|
||||
<h5 id="desc-title">List description</h5>
|
||||
<span id="description"></span>
|
||||
</li>
|
||||
-->
|
||||
@@ -1,37 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>promp</title>
|
||||
</head>
|
||||
<body>
|
||||
<?php
|
||||
$files = scandir('../oldFiles/');
|
||||
foreach($files as $list) {
|
||||
if($list != "." && $list != "..")
|
||||
{
|
||||
$file = file_get_contents("../oldFiles/".$list);
|
||||
$data = json_decode($file);
|
||||
if(count($data) > 0)
|
||||
{
|
||||
$array = array("nowPlaying" => array(), "songs" => array(), "conf" => array("startTime" => time(), "views" => 0, "skips" => array()));
|
||||
for($i = 0; $i < count($data[0]); $i++)
|
||||
{
|
||||
if($i > 0)
|
||||
{
|
||||
|
||||
$arr = "songs";
|
||||
}
|
||||
else{
|
||||
$arr = "nowPlaying";
|
||||
}
|
||||
$array[$arr][$data[0][0]] = array("id" => $data[0][0], "title" => str_replace("\"", "\'", $data[3][0]), "votes" => 0, "added" => time(), "guids" => array());
|
||||
array_shift($data[0]);
|
||||
array_shift($data[3]);
|
||||
}
|
||||
file_put_contents("../oldFiles/".$list, json_encode($array));
|
||||
echo $list."\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
</body>
|
||||
</html>
|
||||
15
pm2.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"apps": [
|
||||
{
|
||||
"name": "zoff",
|
||||
"script": "./server/pm2.js",
|
||||
"watch": true,
|
||||
"instances": "max",
|
||||
"exec_mode": "cluster",
|
||||
"ignore_watch": [
|
||||
"./node_modules",
|
||||
"./server/public/assets/images/thumbnails"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
224
server/EVENTS.md
Normal file
@@ -0,0 +1,224 @@
|
||||
## Events
|
||||
|
||||
### To server
|
||||
```
|
||||
// Tells the server the song is over
|
||||
'end', {
|
||||
id: video_id,
|
||||
channel: channel_name,
|
||||
pass: Base64(channel_pass)
|
||||
}
|
||||
|
||||
// Asks server where in the song it should be
|
||||
'pos', {
|
||||
channel: channel_name,
|
||||
pass: Base64(hannel_pass)
|
||||
}
|
||||
|
||||
// Tells the server the client wants the list
|
||||
'list', {
|
||||
channel: channel_name,
|
||||
pass: Base64(channel_pass),
|
||||
version: system_version (can be checked in VERSION.js)
|
||||
}
|
||||
|
||||
// Sends info about a song the client wants to add
|
||||
'add', {
|
||||
id: VIDEO_ID,
|
||||
title: VIDEO_TITLE,
|
||||
adminpass: Base64(PASSWORD),
|
||||
duration: VIDEO_DURATION,
|
||||
list: channel_name,
|
||||
pass: Base64(channel_pass)
|
||||
}
|
||||
|
||||
'addPlaylist', {
|
||||
channel: CHANNEL_NAME,
|
||||
userpass: Base64(CHANNEL_PASSWORD),
|
||||
adminpass: Base64(PASSWORD),
|
||||
songs: [
|
||||
{
|
||||
id: song_id,
|
||||
title: song_title,
|
||||
duration: song_duration
|
||||
}, ... { ... }
|
||||
]
|
||||
}
|
||||
|
||||
// Imports songs from another zoff-channel
|
||||
'import_zoff', {
|
||||
channel: CHANNELNAME,
|
||||
new_channel: CHANNELNAME-TO-IMPORT-FROM,
|
||||
adminpass: Base64(PASSWORD),
|
||||
userpass: Bse64(CHANNEL_PASSWORD)
|
||||
}
|
||||
|
||||
// Tells the server to disconnect the user from the current channel, is used for remote controlling on the host side
|
||||
'change_channel', {
|
||||
channel: channel_name
|
||||
}
|
||||
|
||||
// Sends chat text to all chat
|
||||
'all,chat', {
|
||||
channel: channel_name,
|
||||
data: input
|
||||
}
|
||||
|
||||
// Sends chat text to channelchat
|
||||
'chat',{
|
||||
channel: channel_name,
|
||||
data: input,
|
||||
pass: Base64(channel_pass)
|
||||
}
|
||||
|
||||
// Sends info about song the user wants to vote on. If VOTE_TYPE is del, its deleting the song, if its pos, its just voting
|
||||
'vote', {
|
||||
channel: CHANNEL_NAME,
|
||||
id: VIDEO_ID,
|
||||
type: VOTE_TYPE,
|
||||
adminpass: Base64(PASSWORD)
|
||||
}
|
||||
|
||||
// Sends shuffle to the server (Only works every 5 seconds per list)
|
||||
'shuffle', {
|
||||
adminpass: Base64(PASSWORD),
|
||||
channel: CHANNELNAME,
|
||||
pass: Base64(USER_PASSWORD)
|
||||
}
|
||||
|
||||
// Sends skip message to server
|
||||
'skip', {
|
||||
pass: Base64(PASSWORD),
|
||||
id:video_id,
|
||||
channel: chan,
|
||||
userpass: Base64(channel_pass)
|
||||
}
|
||||
|
||||
// Sends password for instant log in to server
|
||||
'password', {
|
||||
password: Base64(PASSWORD),
|
||||
channel: CHANNEL_NAME,
|
||||
oldpass: Base64(old_pass_if_changing_password)
|
||||
}
|
||||
|
||||
// Sends message to the host channel for play
|
||||
'id', {
|
||||
id: CHANNEL_ID,
|
||||
type: "play",
|
||||
value: "mock"
|
||||
}
|
||||
|
||||
// Sends message to the host channel for pause
|
||||
'id', {
|
||||
id: CHANNEL_ID,
|
||||
type: "pause",
|
||||
value: "mock"
|
||||
}
|
||||
|
||||
// Sends message to the host channel for skip
|
||||
'id', {
|
||||
id: CHANNEL_ID,
|
||||
type: "skip",
|
||||
value: "mock"
|
||||
}
|
||||
|
||||
// Sends message to the host channel to change volume
|
||||
'id', {
|
||||
id: CHANNEL_ID,
|
||||
type: "volume",
|
||||
value: VALUE
|
||||
}
|
||||
|
||||
// Sends message to the host channel to change channel
|
||||
'id', {
|
||||
id: CHANNEL_ID,
|
||||
type: "channel",
|
||||
value: NEW_CHANNEL_NAME
|
||||
}
|
||||
|
||||
// Sends a video that triggered an error
|
||||
'error_video', {
|
||||
channel: CHANNEL_NAME,
|
||||
id: VIDEO_ID,
|
||||
title: VIDEO_TITLE
|
||||
}
|
||||
|
||||
// Requests chat-history from the last 10 minutes
|
||||
'get_history', {
|
||||
channel: CHANNEL_NAME,
|
||||
all: BOOLEAN (if true, it requests for all-chat),
|
||||
pass: Base64(USERPASS)
|
||||
}
|
||||
```
|
||||
|
||||
### From server
|
||||
```
|
||||
// Receives a string from server for what type of toast to be triggered
|
||||
'toast', STRING
|
||||
|
||||
// Receives a boolean if the password was correct
|
||||
'pw', BOOLEAN
|
||||
|
||||
// Receives configuration array from server
|
||||
'conf', [ARRAY]
|
||||
|
||||
// Receives chat message from allchat
|
||||
'chat.all', {
|
||||
from: name,
|
||||
msg: message,
|
||||
channel: channel,
|
||||
icon: icon_src
|
||||
}
|
||||
|
||||
// Receives chat-history for all and for current channel
|
||||
'chat_history', {
|
||||
all: BOOLEAN (if true, it is for all-chat),
|
||||
data: CHAT_HISTORY
|
||||
}
|
||||
|
||||
// Receives chat message from channelchat
|
||||
'chat', {
|
||||
from: name,
|
||||
msg: message,
|
||||
icon: icon_src
|
||||
}
|
||||
|
||||
// Receives the ID of the current client, used for remote listening
|
||||
'id', STRING
|
||||
|
||||
// Receives the messages sent on CHANNEL_ID above
|
||||
id, {
|
||||
type: STRING,
|
||||
value: VALUE
|
||||
}
|
||||
|
||||
// Receives updates from channel. type is one of the following: list, added, deleted, vote, song_change, changed_values (see further down for better explanation here)
|
||||
'channel', {
|
||||
type: TYPE,
|
||||
value: value,
|
||||
time: time_of_occurence
|
||||
}
|
||||
|
||||
// Receives message from the server that its ready to send the playlist and info
|
||||
'get_list'
|
||||
|
||||
// Receives array of now playing song. Is triggered on song-change
|
||||
'np', {
|
||||
np: NOW_PLAYING,
|
||||
conf: CONFIGURATION,
|
||||
time: SERVER_TIME
|
||||
}
|
||||
|
||||
// Receives number of viewers on the current channel
|
||||
'viewers', VALUE
|
||||
|
||||
// Receives a newly updated video, that was checked for errors (song_generated contains .id which is the current id of the video, and a .new_id for the new video to change the video to)
|
||||
'channel', {
|
||||
type: "changed_values",
|
||||
value: song_generated
|
||||
}
|
||||
|
||||
'update_required', {
|
||||
description of what is wrong as an object
|
||||
}
|
||||
```
|
||||
12
server/README.md
Normal file
@@ -0,0 +1,12 @@
|
||||
## Apps
|
||||
|
||||
Under ``` /server/apps/ ```, there are two files, ``` admin.js ``` and ``` client.js ```.``` admin.js ``` are for the adminpanel, and ``` client.js ``` are for zoff itself.
|
||||
|
||||
|
||||
## REST
|
||||
|
||||
[Rest API info](REST.md)
|
||||
|
||||
## Events
|
||||
|
||||
[Events sent form the server/to the server info](EVENTS.md)
|
||||
192
server/REST.md
Normal file
@@ -0,0 +1,192 @@
|
||||
## REST
|
||||
|
||||
All PUT, DELETE and POST endpoints have a 1-second waitlimit for each command per client. You'll get a response with Retry-After header for how long you have to wait. Shuffling in a player has a 5-second waitlimit, but per channel instead of per client.
|
||||
|
||||
If you want to skip the wait-times, create a token at <a href="https://zoff.me/api/apply">https://zoff.me/api/apply</a>. Tokens are added to all the POST, PUT, DELETE, requests as ``` token: TOKEN ```.
|
||||
|
||||
All requests return things on this form (results field is added if successful.)
|
||||
|
||||
```
|
||||
{
|
||||
status: STATUSCODE,
|
||||
error: MESSAGE,
|
||||
success: IF_SUCCESSFULL,
|
||||
results: [RESULTS] (if something went wrong, there is one element in this array. This tells you what is wrong with the request, and what was expected)
|
||||
}
|
||||
```
|
||||
|
||||
Add song
|
||||
|
||||
```
|
||||
POST /api/list/:channel_name/:video_id
|
||||
{
|
||||
"title": TITLE,
|
||||
"duration": END_TIME - START_TIME,
|
||||
"end_time": END_TIME,
|
||||
"start_time": START_TIME,
|
||||
"adminpass": PASSWORD, (leave this blank if there is no password/you don't know the password)
|
||||
"userpass": USER_PASSWORD
|
||||
"source": Either "youtube" or "soundcloud"
|
||||
("thumbnail": thumbnail url for soundcloud elements (only used when source == "soundcloud"))
|
||||
}
|
||||
|
||||
Returns 400 for bad request
|
||||
Returns 403 for bad authentication (but will return a song object, with the type == "suggested", and the song will show up in the suggested tab for channel-admins)
|
||||
Returns 409 if the song exists
|
||||
Returns 429 if you're doing too much of this request, with a Retry-After int value in the header.
|
||||
Returns 200 and the added song object if successful
|
||||
```
|
||||
|
||||
Delete song
|
||||
```
|
||||
DELETE /api/list/:channel_name/:video_id
|
||||
{
|
||||
"adminpass": PASSWORD,
|
||||
"userpass": USER_PASSWORD
|
||||
}
|
||||
|
||||
Returns 400 for bad request
|
||||
Returns 403 for bad authentication
|
||||
Returns 404 if the song doesnt exist or is the currently playing song
|
||||
Returns 429 if you're doing too much of this request, with a Retry-After int value in the header.
|
||||
Returns 200 if successful
|
||||
```
|
||||
|
||||
Vote on song
|
||||
```
|
||||
PUT /api/list/:channel_name/:video_id
|
||||
{
|
||||
"adminpass": PASSWORD,
|
||||
"userpass": USER_PASSWORD
|
||||
}
|
||||
|
||||
Returns 400 for bad request
|
||||
Returns 403 for bad authentication
|
||||
Returns 404 if the song doesnt exist
|
||||
Returns 409 if you've already voted on that song
|
||||
Returns 429 if you're doing too much of this request, with a Retry-After int value in the header.
|
||||
Returns 200 and the added song object if successful
|
||||
```
|
||||
|
||||
Change channel configurations
|
||||
```
|
||||
PUT /api/conf/:channel_name
|
||||
{
|
||||
"userpass": USER_PASSWORD,
|
||||
"adminpass": PASSWORD,
|
||||
"vote": BOOLEAN,
|
||||
"addsongs": BOOLEAN,
|
||||
"longsongs": BOOLEAN,
|
||||
"frontpage": BOOLEAN (if you want to set userpassword, this MUST be false for it to work),
|
||||
"allvideos": BOOLEAN,
|
||||
"removeplay": BOOLEAN,
|
||||
"skip": BOOLEAN,
|
||||
"shuffle": BOOLEAN,
|
||||
"userpass_changed": BOOLEAN (this must be true if you want to keep the userpassword you're sending)
|
||||
}
|
||||
|
||||
Returns 400 for bad request
|
||||
Returns 403 for bad authentication
|
||||
Returns 404 if the list doesn't exist
|
||||
Returns 429 if you're doing too much of this request, with a Retry-After int value in the header.
|
||||
Returns 200 and the newly added configuration if successful
|
||||
```
|
||||
|
||||
Get song in channel
|
||||
```
|
||||
GET /api/list/:channel_name/:video_id
|
||||
|
||||
Returns 403 for bad authentication (if you get this, the channel is protected, try getting the full channel with POST, and search through the object)
|
||||
Returns 404 if the song doesn't exist
|
||||
Returns 200 and the song
|
||||
```
|
||||
|
||||
Get song in channel (protected)
|
||||
```
|
||||
// Important fetch_song is present, or else the request will try to add a song to the channel
|
||||
POST /api/list/:channel_name/:video_id
|
||||
{
|
||||
"fetch_song": ANYTHING_HERE,
|
||||
"userpass": USERPASS
|
||||
}
|
||||
|
||||
Returns 400 for bad request
|
||||
Returns 403 for bad authentication
|
||||
Returns 404 if the song doesn't exist
|
||||
Returns 200 and the song
|
||||
```
|
||||
|
||||
Get list
|
||||
```
|
||||
GET /api/list/:channel_name/
|
||||
|
||||
Returns 403 for bad authentication (if you get this, the channel is protected, try getting the full channel with POST, and search through the object)
|
||||
Returns 404 if the song doesn't exist
|
||||
Returns 200 and the song
|
||||
```
|
||||
|
||||
Get list (protected)
|
||||
```
|
||||
// Important fetch_song is present, or else the request will try to add a song to the channel
|
||||
POST /api/list/:channel_name/
|
||||
{
|
||||
"userpass": USERPASS
|
||||
}
|
||||
|
||||
Returns 400 for bad request
|
||||
Returns 403 for bad authentication
|
||||
Returns 404 if the list doesn't exist
|
||||
Returns 200 and the song
|
||||
```
|
||||
|
||||
Get channelsettings
|
||||
```
|
||||
GET /api/conf/:channel_name/
|
||||
|
||||
Returns 403 for bad authentication (if you get this, try POST with userpassword attached)
|
||||
Returns 404 if the channel doesn't exist
|
||||
Returns 200 and the objects in the channel
|
||||
```
|
||||
|
||||
Get channelsettings (protected)
|
||||
```
|
||||
POST /api/conf/:channel_name/
|
||||
{
|
||||
"userpass": USERPASS
|
||||
}
|
||||
|
||||
Returns 400 for bad request
|
||||
Returns 403 for bad authentication
|
||||
Returns 404 if the channel doesn't exist
|
||||
Returns 200 and the objects in the channel
|
||||
```
|
||||
|
||||
Get now playing song
|
||||
```
|
||||
GET /api/list/:channel_name/__np__
|
||||
|
||||
Returns 400 for bad request
|
||||
Returns 403 for bad authentication (if you get this, try POST with userpassword attached)
|
||||
Returns 404 if the channel doesn't exist
|
||||
Returns 200 and the now playing object
|
||||
```
|
||||
|
||||
Get now playing song (protected)
|
||||
```
|
||||
POST /api/list/:channel_name/__np__
|
||||
{
|
||||
"userpass": USERPASS
|
||||
}
|
||||
|
||||
Returns 400 for bad request
|
||||
Returns 403 for bad authentication (if you get this, try POST with userpassword attached)
|
||||
Returns 404 if the channel doesn't exist
|
||||
Returns 200 and the now playing object
|
||||
```
|
||||
|
||||
Get all lists
|
||||
```
|
||||
GET /api/frontpages
|
||||
|
||||
Returns 200 and the frontpage-lists
|
||||
```
|
||||
5
server/VERSION.js
Normal file
@@ -0,0 +1,5 @@
|
||||
VERSION = 6;
|
||||
|
||||
try {
|
||||
module.exports = VERSION;
|
||||
} catch (e) {}
|
||||
157
server/app.js
Normal file
@@ -0,0 +1,157 @@
|
||||
var cluster = require("cluster"),
|
||||
net = require("net"),
|
||||
path = require("path"),
|
||||
//publicPath = path.join(__dirname, 'public'),
|
||||
http = require("http"),
|
||||
port = 8080,
|
||||
farmhash = require("farmhash"),
|
||||
uniqid = require("uniqid"),
|
||||
num_processes = require("os").cpus().length;
|
||||
|
||||
publicPath = path.join(__dirname, "public");
|
||||
pathThumbnails = __dirname;
|
||||
|
||||
try {
|
||||
var redis = require("redis");
|
||||
var client = redis.createClient({ host: "localhost", port: 6379 });
|
||||
client.on("error", function(err) {
|
||||
console.log("Couldn't connect to redis-server, assuming non-clustered run");
|
||||
num_processes = 1;
|
||||
startSingle(false, false);
|
||||
client.quit();
|
||||
});
|
||||
client.on("connect", function() {
|
||||
startClustered(true);
|
||||
client.quit();
|
||||
});
|
||||
} catch (e) {
|
||||
console.log("Couldn't connect to redis-server, assuming non-clustered run");
|
||||
num_processes = 1;
|
||||
startSingle(false, false);
|
||||
}
|
||||
|
||||
function startClustered(redis_enabled) {
|
||||
//Found https://stackoverflow.com/questions/40885592/use-node-js-cluster-with-socket-io-chat-application
|
||||
if (cluster.isMaster) {
|
||||
var workers = [];
|
||||
var spawn = function(i) {
|
||||
workers[i] = cluster.fork();
|
||||
workers[i].on("exit", function(code, signal) {
|
||||
if (code == 1) {
|
||||
process.exit(1);
|
||||
return;
|
||||
}
|
||||
console.log("respawning worker", i);
|
||||
spawn(i);
|
||||
});
|
||||
};
|
||||
|
||||
for (var i = 0; i < num_processes; i++) {
|
||||
spawn(i);
|
||||
}
|
||||
|
||||
var worker_index = function(ip, len) {
|
||||
//console.log(ip);
|
||||
var s = "";
|
||||
if (ip !== undefined) {
|
||||
return farmhash.fingerprint32(ip) % len;
|
||||
}
|
||||
ip = uniqid.time();
|
||||
for (var i = 0, _len = ip.length; i < _len; i++) {
|
||||
if (!isNaN(ip[i])) {
|
||||
s += ip[i];
|
||||
}
|
||||
}
|
||||
return Number(s) % len;
|
||||
};
|
||||
|
||||
var server = net
|
||||
.createServer({ pauseOnConnect: true }, function(connection, a) {
|
||||
var worker =
|
||||
workers[worker_index(connection.address().address, num_processes)];
|
||||
worker.send("sticky-session:connection", connection);
|
||||
})
|
||||
.listen(port);
|
||||
} else {
|
||||
startSingle(true, redis_enabled);
|
||||
}
|
||||
}
|
||||
|
||||
function startSingle(clustered, redis_enabled) {
|
||||
var server;
|
||||
var client = require("./apps/client.js");
|
||||
try {
|
||||
var cert_config = require(path.join(
|
||||
path.join(__dirname, "config"),
|
||||
"cert_config.js"
|
||||
));
|
||||
var fs = require("fs");
|
||||
var privateKey = fs.readFileSync(cert_config.privateKey).toString();
|
||||
var certificate = fs.readFileSync(cert_config.certificate).toString();
|
||||
var ca = fs.readFileSync(cert_config.ca).toString();
|
||||
var credentials = {
|
||||
key: privateKey,
|
||||
cert: certificate,
|
||||
ca: ca
|
||||
};
|
||||
var https = require("https");
|
||||
server = https.Server(credentials, routingFunction);
|
||||
} catch (err) {
|
||||
console.log("Starting without https (probably on localhost)");
|
||||
server = http.createServer(routingFunction);
|
||||
}
|
||||
|
||||
if (clustered) {
|
||||
server.listen(onListen);
|
||||
} else {
|
||||
server.listen(port, onListen);
|
||||
}
|
||||
|
||||
var socketIO = client.socketIO;
|
||||
|
||||
if (redis_enabled) {
|
||||
var redis = require("socket.io-redis");
|
||||
try {
|
||||
socketIO.adapter(redis({ host: "localhost", port: 6379 }));
|
||||
} catch (e) {
|
||||
console.log("No redis-server to connect to..");
|
||||
}
|
||||
}
|
||||
socketIO.listen(server);
|
||||
|
||||
process.on("message", function(message, connection) {
|
||||
if (message !== "sticky-session:connection") {
|
||||
return;
|
||||
}
|
||||
server.emit("connection", connection);
|
||||
connection.resume();
|
||||
});
|
||||
}
|
||||
|
||||
function onListen() {
|
||||
console.log("Started with pid [" + process.pid + "]");
|
||||
}
|
||||
|
||||
function routingFunction(req, res, next) {
|
||||
var client = require("./apps/client.js");
|
||||
var admin = require("./apps/admin.js");
|
||||
try {
|
||||
var url = req.headers["x-forwarded-host"]
|
||||
? req.headers["x-forwarded-host"]
|
||||
: req.headers.host.split(":")[0];
|
||||
var subdomain = req.headers["x-forwarded-host"]
|
||||
? req.headers["x-forwarded-host"].split(".")
|
||||
: req.headers.host.split(":")[0].split(".");
|
||||
|
||||
if (subdomain.length > 1 && subdomain[0] == "admin") {
|
||||
admin(req, res, next);
|
||||
} else {
|
||||
client(req, res, next);
|
||||
}
|
||||
} catch (e) {
|
||||
console.log("Bad request for " + req.headers.host + req.url, e);
|
||||
res.statusCode = 500;
|
||||
res.write("Bad request"); //write a response to the client
|
||||
res.end(); //end the response
|
||||
}
|
||||
}
|
||||
270
server/apps/admin.js
Normal file
@@ -0,0 +1,270 @@
|
||||
var express = require("express");
|
||||
var app = express();
|
||||
|
||||
const path = require("path");
|
||||
const publicPath = path.join(__dirname + "", "../public");
|
||||
var exphbs = require("express-handlebars");
|
||||
var hbs = exphbs.create({
|
||||
defaultLayout: publicPath + "/layouts/admin/main",
|
||||
layoutsDir: publicPath + "/layouts",
|
||||
partialsDir: publicPath + "/partials"
|
||||
});
|
||||
|
||||
var passport = require("passport");
|
||||
var mpromise = require("mpromise");
|
||||
var LocalStrategy = require("passport-local").Strategy;
|
||||
var mongoose = require("mongoose");
|
||||
var mongo_db_cred = require(pathThumbnails + "/config/mongo_config.js");
|
||||
var mongojs = require("mongojs");
|
||||
var db = mongojs(mongo_db_cred.config);
|
||||
var token_db = mongojs("tokens");
|
||||
var bodyParser = require("body-parser");
|
||||
var session = require("express-session");
|
||||
var MongoStore = require("connect-mongo")(session);
|
||||
var api = require(pathThumbnails + "/routing/admin/api.js");
|
||||
|
||||
var compression = require("compression");
|
||||
var User = require(pathThumbnails + "/models/user.js");
|
||||
var url = "mongodb://" + mongo_db_cred.host + "/" + mongo_db_cred.users;
|
||||
mongoose.connect(url);
|
||||
|
||||
app.engine("handlebars", hbs.engine);
|
||||
app.set("view engine", "handlebars");
|
||||
app.use(compression({ filter: shouldCompress }));
|
||||
|
||||
function shouldCompress(req, res) {
|
||||
if (req.headers["x-no-compression"]) {
|
||||
// don't compress responses with this request header
|
||||
return false;
|
||||
}
|
||||
|
||||
// fallback to standard filter function
|
||||
return compression.filter(req, res);
|
||||
}
|
||||
app.set("trust proxy", "127.0.0.1");
|
||||
|
||||
var bodyParser = require("body-parser");
|
||||
var cookieParser = require("cookie-parser");
|
||||
var referrerPolicy = require("referrer-policy");
|
||||
var helmet = require("helmet");
|
||||
var featurePolicy = require("feature-policy");
|
||||
app.use(
|
||||
featurePolicy({
|
||||
features: {
|
||||
fullscreen: ["*"],
|
||||
//vibrate: ["'none'"],
|
||||
payment: ["'none'"],
|
||||
microphone: ["'none'"],
|
||||
camera: ["'none'"],
|
||||
speaker: ["*"],
|
||||
syncXhr: ["'self'"]
|
||||
//notifications: ["'self'"]
|
||||
}
|
||||
})
|
||||
);
|
||||
app.use(
|
||||
helmet({
|
||||
frameguard: false
|
||||
})
|
||||
);
|
||||
app.use(referrerPolicy({ policy: "origin-when-cross-origin" }));
|
||||
app.enable("view cache");
|
||||
app.set("views", publicPath);
|
||||
app.use(bodyParser.json()); // to support JSON-encoded bodies
|
||||
app.use(
|
||||
bodyParser.urlencoded({
|
||||
extended: true
|
||||
})
|
||||
);
|
||||
app.use(
|
||||
session({
|
||||
secret: mongo_db_cred.secret,
|
||||
resave: true,
|
||||
saveUninitialized: true,
|
||||
store: new MongoStore({
|
||||
url: url,
|
||||
useNewUrlParser: true,
|
||||
collection: "sessions",
|
||||
ttl: mongo_db_cred.expire
|
||||
})
|
||||
})
|
||||
); // session secret
|
||||
app.use(passport.initialize());
|
||||
app.use(passport.session()); // persistent login sessions
|
||||
|
||||
//app.use('/assets', express.static(publicPath + '/assets'));
|
||||
|
||||
passport.serializeUser(function(user, done) {
|
||||
done(null, user.id);
|
||||
});
|
||||
|
||||
// used to deserialize the user
|
||||
passport.deserializeUser(function(id, done) {
|
||||
User.findById(id, function(err, user) {
|
||||
done(err, user);
|
||||
});
|
||||
});
|
||||
|
||||
passport.use(
|
||||
"local-signup",
|
||||
new LocalStrategy(
|
||||
{
|
||||
// by default, local strategy uses username and password, we will override with username
|
||||
usernameField: "username",
|
||||
passwordField: "password",
|
||||
passReqToCallback: true // allows us to pass back the entire request to the callback
|
||||
},
|
||||
function(req, username, password, done) {
|
||||
// asynchronous
|
||||
// User.findOne wont fire unless data is sent back
|
||||
process.nextTick(function() {
|
||||
// find a user whose username is the same as the forms username
|
||||
// we are checking to see if the user trying to login already exists
|
||||
var token = req.body.token;
|
||||
token_db
|
||||
.collection("tokens")
|
||||
.find({ token: token }, function(err, docs) {
|
||||
if (docs.length == 1) {
|
||||
token_db
|
||||
.collection("tokens")
|
||||
.remove({ token: token }, function(err, docs) {
|
||||
User.findOne({ username: username }, function(err, user) {
|
||||
// if there are any errors, return the error
|
||||
if (err) return done(err);
|
||||
|
||||
// check to see if theres already a user with that username
|
||||
if (user) {
|
||||
return done(null, false);
|
||||
} else {
|
||||
// if there is no user with that username
|
||||
// create the user
|
||||
var newUser = new User();
|
||||
|
||||
// set the user's local credentials
|
||||
newUser.username = username;
|
||||
newUser.password = newUser.generateHash(password);
|
||||
|
||||
// save the user
|
||||
newUser.save(function(err) {
|
||||
if (err) throw err;
|
||||
return done(null, newUser);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
return done(null, false);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
passport.use(
|
||||
"local-login",
|
||||
new LocalStrategy(
|
||||
{
|
||||
// by default, local strategy uses username and password, we will override with email
|
||||
usernameField: "username",
|
||||
passwordField: "password",
|
||||
passReqToCallback: true // allows us to pass back the entire request to the callback
|
||||
},
|
||||
function(req, username, password, done) {
|
||||
// callback with email and password from our form
|
||||
|
||||
// find a user whose email is the same as the forms email
|
||||
// we are checking to see if the user trying to login already exists
|
||||
User.findOne({ username: username }, function(err, user) {
|
||||
// if there are any errors, return the error before anything else
|
||||
if (err) return done(err);
|
||||
|
||||
// if no user is found, return the message
|
||||
if (!user) return done(null, false); // req.flash is the way to set flashdata using connect-flash
|
||||
|
||||
// if the user is found but the password is wrong
|
||||
if (!user.validPassword(password)) return done(null, false); // create the loginMessage and save it to session as flashdata
|
||||
|
||||
// all is well, return successful user
|
||||
|
||||
return done(null, user);
|
||||
});
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
app.post(
|
||||
"/signup",
|
||||
passport.authenticate("local-signup", {
|
||||
successRedirect: "/", // redirect to the secure profile section
|
||||
failureRedirect: "/signup", // redirect back to the signup page if there is an error
|
||||
failureFlash: true // allow flash messages
|
||||
})
|
||||
);
|
||||
|
||||
app.post(
|
||||
"/login",
|
||||
passport.authenticate("local-login", {
|
||||
successRedirect: "/", // redirect to the secure profile section
|
||||
failureRedirect: "/login#failed", // redirect back to the signup page if there is an error
|
||||
failureFlash: true // allow flash messages
|
||||
})
|
||||
);
|
||||
|
||||
app.use("/login", isLoggedInTryingToLogIn, function(req, res) {
|
||||
var data = {
|
||||
where_get: "not_authenticated"
|
||||
};
|
||||
|
||||
res.render("layouts/admin/not_authenticated", data);
|
||||
});
|
||||
|
||||
app.use("/signup", isLoggedInTryingToLogIn, function(req, res) {
|
||||
var data = {
|
||||
where_get: "not_authenticated"
|
||||
};
|
||||
|
||||
res.render("layouts/admin/not_authenticated", data);
|
||||
});
|
||||
|
||||
app.use("/", api);
|
||||
|
||||
app.use("/logout", function(req, res) {
|
||||
req.logout();
|
||||
res.redirect("/login");
|
||||
});
|
||||
|
||||
app.use("/assets/admin/authenticated", function(req, res, next) {
|
||||
if (!req.isAuthenticated()) {
|
||||
res.sendStatus(403);
|
||||
return;
|
||||
}
|
||||
return next();
|
||||
});
|
||||
|
||||
app.use("/assets", express.static(publicPath + "/assets"));
|
||||
|
||||
app.use("/", isLoggedIn, function(req, res) {
|
||||
var data = {
|
||||
where_get: "authenticated",
|
||||
year: new Date().getYear() + 1900
|
||||
};
|
||||
|
||||
res.render("layouts/admin/authenticated", data);
|
||||
});
|
||||
|
||||
function isLoggedInTryingToLogIn(req, res, next) {
|
||||
if (!req.isAuthenticated()) {
|
||||
return next();
|
||||
}
|
||||
res.redirect("/");
|
||||
}
|
||||
|
||||
function isLoggedIn(req, res, next) {
|
||||
if (req.isAuthenticated()) return next();
|
||||
res.redirect("/login");
|
||||
}
|
||||
|
||||
//app.listen(default_port);
|
||||
|
||||
module.exports = app;
|
||||
207
server/apps/client.js
Executable file
@@ -0,0 +1,207 @@
|
||||
VERSION = require(pathThumbnails + "/VERSION.js");
|
||||
var secure = false;
|
||||
var path = require("path");
|
||||
try {
|
||||
var cert_config = require(path.join(
|
||||
path.join(__dirname, "../config/"),
|
||||
"cert_config.js"
|
||||
));
|
||||
var fs = require("fs");
|
||||
var privateKey = fs.readFileSync(cert_config.privateKey).toString();
|
||||
var certificate = fs.readFileSync(cert_config.certificate).toString();
|
||||
var ca = fs.readFileSync(cert_config.ca).toString();
|
||||
var credentials = {
|
||||
key: privateKey,
|
||||
cert: certificate,
|
||||
ca: ca
|
||||
};
|
||||
secure = true;
|
||||
} catch (err) {}
|
||||
|
||||
var add = "";
|
||||
var express = require("express");
|
||||
var app = express();
|
||||
var compression = require("compression");
|
||||
var exphbs = require("express-handlebars");
|
||||
var cors = require("cors");
|
||||
var Functions = require(pathThumbnails + "/handlers/functions.js");
|
||||
|
||||
var hbs = exphbs.create({
|
||||
defaultLayout: publicPath + "/layouts/client/main",
|
||||
layoutsDir: publicPath + "/layouts/client",
|
||||
partialsDir: publicPath + "/partials",
|
||||
helpers: {
|
||||
if_equal: function(a, b, opts) {
|
||||
if (a == b) {
|
||||
return opts.fn(this);
|
||||
} else {
|
||||
return opts.inverse(this);
|
||||
}
|
||||
},
|
||||
decodeString: function(s) {
|
||||
if (s == undefined) return s;
|
||||
return Functions.decodeChannelName(s);
|
||||
}
|
||||
}
|
||||
});
|
||||
var uniqid = require("uniqid");
|
||||
app.use(compression({ filter: shouldCompress }));
|
||||
|
||||
function shouldCompress(req, res) {
|
||||
if (req.headers["x-no-compression"]) {
|
||||
// don't compress responses with this request header
|
||||
return false;
|
||||
}
|
||||
|
||||
// fallback to standard filter function
|
||||
return compression.filter(req, res);
|
||||
}
|
||||
|
||||
app.engine("handlebars", hbs.engine);
|
||||
app.set("view engine", "handlebars");
|
||||
app.enable("view cache");
|
||||
app.set("views", publicPath);
|
||||
app.set("trust proxy", "127.0.0.1");
|
||||
|
||||
var bodyParser = require("body-parser");
|
||||
var cookieParser = require("cookie-parser");
|
||||
var referrerPolicy = require("referrer-policy");
|
||||
var helmet = require("helmet");
|
||||
var featurePolicy = require("feature-policy");
|
||||
app.use(
|
||||
featurePolicy({
|
||||
features: {
|
||||
fullscreen: ["*"],
|
||||
//vibrate: ["'none'"],
|
||||
payment: ["'none'"],
|
||||
microphone: ["'none'"],
|
||||
camera: ["'none'"],
|
||||
speaker: ["*"],
|
||||
syncXhr: ["'self'"]
|
||||
//notifications: ["'self'"]
|
||||
}
|
||||
})
|
||||
);
|
||||
app.use(
|
||||
helmet({
|
||||
frameguard: false
|
||||
})
|
||||
);
|
||||
app.use(referrerPolicy({ policy: "origin-when-cross-origin" }));
|
||||
app.use(bodyParser.json()); // to support JSON-encoded bodies
|
||||
app.use(
|
||||
bodyParser.urlencoded({
|
||||
// to support URL-encoded bodies
|
||||
extended: true
|
||||
})
|
||||
);
|
||||
app.use(cookieParser());
|
||||
//app.set('json spaces', 2);
|
||||
|
||||
io = require("socket.io")({
|
||||
pingTimeout: 25000
|
||||
//path: '/zoff',
|
||||
//"origins": ("https://zoff.me:443*,https://zoff.me:8080*,zoff.me:8080*,https://remote.zoff.me:443*,https://remote.zoff.me:8080*,https://fb.zoff.me:443*,https://fb.zoff.me:8080*,https://admin.zoff.me:443*,https://admin.zoff.me:8080*, http://localhost:8080*")});
|
||||
});
|
||||
|
||||
var socketIO = require(pathThumbnails + "/handlers/io.js");
|
||||
socketIO();
|
||||
|
||||
app.socketIO = io;
|
||||
|
||||
/* Globally needed "libraries" and files */
|
||||
var router = require(pathThumbnails + "/routing/client/router.js");
|
||||
var api_file = require(pathThumbnails + "/routing/client/api.js");
|
||||
var api = api_file.router;
|
||||
api_file.sIO = app.socketIO;
|
||||
var ico_router = require(pathThumbnails + "/routing/client/icons_routing.js");
|
||||
|
||||
app.get("/robots.txt", function(req, res) {
|
||||
res.type("text/plain");
|
||||
res.send("User-agent: *\nAllow: /$\nDisallow: /");
|
||||
});
|
||||
|
||||
app.use(function(req, res, next) {
|
||||
var cookie = req.cookies._uI;
|
||||
var skipElements = [
|
||||
"/_embed",
|
||||
"/assets/manifest.json",
|
||||
"/apple-touch-icon.png"
|
||||
];
|
||||
if (skipElements.indexOf(req.originalUrl) > -1) {
|
||||
res.header("Access-Control-Allow-Origin", "*");
|
||||
res.header(
|
||||
"Access-Control-Allow-Headers",
|
||||
"Origin, X-Requested-With, Content-Type, Accept"
|
||||
);
|
||||
next();
|
||||
} else {
|
||||
if (req.originalUrl.split("/").length > 3) {
|
||||
res.header("Access-Control-Allow-Origin", "*");
|
||||
res.header(
|
||||
"Access-Control-Allow-Headers",
|
||||
"Origin, X-Requested-With, Content-Type, Accept"
|
||||
);
|
||||
next();
|
||||
} else {
|
||||
if (cookie === undefined) {
|
||||
try {
|
||||
//console.error((new Date), "originalUrl", req.originalUrl);
|
||||
//console.error((new Date), "couldn't fetch cookie for some reason, maybe no cookie exists?", req.get('origin'), "couldn't fetch cookie for some reason, maybe no cookie exists?");
|
||||
} catch (e) {
|
||||
//console.error((new Date), "couldn't fetch origin");
|
||||
}
|
||||
var user_name = Functions.hash_pass(
|
||||
Functions.rndName(uniqid.time(), 15)
|
||||
);
|
||||
res.cookie("_uI", user_name, {
|
||||
maxAge: 365 * 10000 * 3600000,
|
||||
httpOnly: true,
|
||||
secure: secure
|
||||
//sameSite: true,
|
||||
});
|
||||
} else {
|
||||
//process.stderr.write((new Date), "couldn't fetch cookie for some reason, maybe no cookie exists?", req, "couldn't fetch cookie for some reason, maybe no cookie exists?");
|
||||
res.cookie("_uI", cookie, {
|
||||
maxAge: 365 * 10000 * 3600000,
|
||||
httpOnly: true,
|
||||
secure: secure
|
||||
//sameSite: true,
|
||||
});
|
||||
}
|
||||
res.header("Access-Control-Allow-Origin", "*");
|
||||
res.header(
|
||||
"Access-Control-Allow-Headers",
|
||||
"Origin, X-Requested-With, Content-Type, Accept"
|
||||
);
|
||||
next();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
app.use("/service-worker.js", function(req, res) {
|
||||
res.sendFile(publicPath + "/service-worker.js");
|
||||
});
|
||||
|
||||
app.use("/", ico_router);
|
||||
app.use("/", api);
|
||||
app.use("/", cors(), router);
|
||||
|
||||
app.use("/assets/js", function(req, res, next) {
|
||||
res.sendStatus(403);
|
||||
return;
|
||||
});
|
||||
|
||||
app.use("/assets/admin", function(req, res, next) {
|
||||
res.sendStatus(403);
|
||||
return;
|
||||
});
|
||||
|
||||
app.use("/assets", express.static(publicPath + "/assets"));
|
||||
|
||||
app.use(function(req, res, next) {
|
||||
res.status(404);
|
||||
res.redirect("/404");
|
||||
});
|
||||
|
||||
module.exports = app;
|
||||
74
server/apps/genre_generator.js
Normal file
@@ -0,0 +1,74 @@
|
||||
var path = require('path');
|
||||
var publicPath = path.join(__dirname, 'public');
|
||||
var pathThumbnail = __dirname;
|
||||
pathThumbnails = __dirname + "/../";
|
||||
var time_regex = /P((([0-9]*\.?[0-9]*)Y)?(([0-9]*\.?[0-9]*)M)?(([0-9]*\.?[0-9]*)W)?(([0-9]*\.?[0-9]*)D)?)?(T(([0-9]*\.?[0-9]*)H)?(([0-9]*\.?[0-9]*)M)?(([0-9]*\.?[0-9]*)S)?)?/;
|
||||
try {
|
||||
var keys = require(path.join(__dirname, '../config/api_key.js'));
|
||||
var key = keys.youtube;
|
||||
var soundcloudKey = keys.soundcloud;
|
||||
} catch(e) {
|
||||
console.log("Error - missing file");
|
||||
console.log("Seems you forgot to create the file api_key.js in /server/config/. Have a look at api_key.example.js.");
|
||||
process.exit(1);
|
||||
}
|
||||
var Search = require(pathThumbnail + '/../handlers/search.js');
|
||||
var request = require('request');
|
||||
var db = require(pathThumbnail + '/../handlers/db.js');
|
||||
var currentList = 0;
|
||||
var listNames = [];
|
||||
db.getCollectionNames(function(e, d) {
|
||||
for(var i = 0; i < d.length; i++) {
|
||||
if(d[i].indexOf("_") < 0) {
|
||||
if(d[i].length > 0) {
|
||||
if(d[i].substring(0, 1) == "." || d[i].substring(d[i].length - 1) == ".") continue;
|
||||
}
|
||||
listNames.push(d[i]);
|
||||
}
|
||||
}
|
||||
console.log("Number of lists is " + listNames.length);
|
||||
/*for(var i = 0; i < listNames.length; i++) {
|
||||
getListItems(d[i]);
|
||||
if(i > 1000) return;
|
||||
}*/
|
||||
recursivifyListLooping(listNames, 0);
|
||||
});
|
||||
|
||||
function filterFunction(el) {
|
||||
return el != null &&
|
||||
el != "" &&
|
||||
el != undefined &&
|
||||
el.trim() != ''
|
||||
}
|
||||
|
||||
function recursivifyListLooping(listNames, i) {
|
||||
if(i > listNames.length) {
|
||||
console.log("Done");
|
||||
return;
|
||||
}
|
||||
console.log("List " + i + " of " + listNames.length);
|
||||
getListItems(listNames, 0, function() {
|
||||
console.log("done");
|
||||
});
|
||||
}
|
||||
|
||||
function getListItems(arr, i, callback) {
|
||||
console.log("List " + i + " of " + listNames.length + " - " + arr[i]);
|
||||
if(i >= arr.length) {
|
||||
if(typeof(callback) == "function") callback();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
db.collection(arr[i]).find(function(e, d) {
|
||||
if(d.length > 0) {
|
||||
Search.get_genres_list_recursive(d, arr[i], function(){
|
||||
getListItems(arr, i + 1, callback);
|
||||
});
|
||||
} else {
|
||||
getListItems(arr, i + 1, callback);
|
||||
}
|
||||
});
|
||||
} catch(e) {
|
||||
getListItems(arr, i + 1, callback);
|
||||
}
|
||||
}
|
||||
3
server/config/allowed_api.example.js
Normal file
@@ -0,0 +1,3 @@
|
||||
var key = [""];
|
||||
|
||||
module.exports = key;
|
||||
8
server/config/api_key.example.js
Normal file
@@ -0,0 +1,8 @@
|
||||
var api_key = {
|
||||
youtube: "xxxx",
|
||||
soundcloud: "xx" // This can be excluded if you don't have a soundcloud key
|
||||
};
|
||||
|
||||
try {
|
||||
module.exports = api_key;
|
||||
} catch (e) {}
|
||||
7
server/config/cert_config.example.js
Normal file
@@ -0,0 +1,7 @@
|
||||
var cert = {
|
||||
privateKey: 'XX',
|
||||
certificate: 'XX',
|
||||
ca: 'XX'
|
||||
}
|
||||
|
||||
module.exports = cert;
|
||||
6
server/config/google.example.js
Normal file
@@ -0,0 +1,6 @@
|
||||
var google = {
|
||||
"analytics": "xxxx",
|
||||
"adsense": "xxxx",
|
||||
}
|
||||
|
||||
module.exports = google;
|
||||
24
server/config/mailconfig.example.js
Normal file
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
*
|
||||
* Have a look at nodemailer's config on how to set this up https://nodemailer.com/about/
|
||||
*
|
||||
*/
|
||||
|
||||
var mail_config = {
|
||||
port: 587,
|
||||
host: 'smtp.example.com',
|
||||
auth: {
|
||||
user: 'ex@amp.le',
|
||||
pass: 'example'
|
||||
},
|
||||
secure: true,
|
||||
authMethod: 'PLAIN',
|
||||
tls: {
|
||||
ciphers:'SSLv3'
|
||||
},
|
||||
from: 'no-reply@zoff.me',
|
||||
to: 'contact@zoff.me'
|
||||
notify_mail: 'notify@mail.example',
|
||||
};
|
||||
|
||||
module.exports = mail_config;
|
||||
10
server/config/mongo_config.example.js
Normal file
@@ -0,0 +1,10 @@
|
||||
var mongo_config = {
|
||||
config: 'mydb',
|
||||
secret: 'secret',
|
||||
users: 'users',
|
||||
host: 'localhost',
|
||||
port: '27017',
|
||||
expire: 86400,
|
||||
};
|
||||
|
||||
module.exports = mongo_config;
|
||||
6
server/config/recaptcha.example.js
Normal file
@@ -0,0 +1,6 @@
|
||||
var recaptcha = {
|
||||
site: "xxxx",
|
||||
key: "xxxxx",
|
||||
}
|
||||
|
||||
module.exports = recaptcha;
|
||||
65
server/handlers/aggregates.js
Normal file
@@ -0,0 +1,65 @@
|
||||
var toShowConfig = {
|
||||
addsongs: true,
|
||||
adminpass: 1,
|
||||
allvideos: 1,
|
||||
frontpage: 1,
|
||||
longsongs: 1,
|
||||
removeplay: 1,
|
||||
shuffle: 1,
|
||||
skip: 1,
|
||||
startTime: 1,
|
||||
userpass: 1,
|
||||
vote: 1,
|
||||
toggleChat: { $ifNull: ["$toggleChat", true] },
|
||||
strictSkip: { $ifNull: ["$strictSkip", false] },
|
||||
strictSkipNumber: { $ifNull: ["$strictSkipNumber", 10] },
|
||||
description: { $ifNull: ["$description", ""] },
|
||||
thumbnail: { $ifNull: ["$thumbnail", ""] },
|
||||
rules: { $ifNull: ["$rules", ""] },
|
||||
_id: 0
|
||||
};
|
||||
|
||||
var project_object = {
|
||||
_id: 0,
|
||||
id: 1,
|
||||
added: 1,
|
||||
now_playing: 1,
|
||||
title: 1,
|
||||
votes: 1,
|
||||
start: 1,
|
||||
duration: 1,
|
||||
end: 1,
|
||||
type: 1,
|
||||
added_by: { $ifNull: ["$added_by", "Anonymous"] },
|
||||
source: { $ifNull: ["$source", "youtube"] },
|
||||
thumbnail: {
|
||||
$ifNull: [
|
||||
"$thumbnail",
|
||||
{
|
||||
$concat: ["https://img.youtube.com/vi/", "$id", "/mqdefault.jpg"]
|
||||
}
|
||||
]
|
||||
},
|
||||
tags: { $ifNull: ["$tags", []] }
|
||||
};
|
||||
|
||||
var toShowChannel = {
|
||||
start: 1,
|
||||
end: 1,
|
||||
added: 1,
|
||||
id: 1,
|
||||
title: 1,
|
||||
votes: 1,
|
||||
duration: 1,
|
||||
type: 1,
|
||||
_id: 0,
|
||||
tags: 1,
|
||||
now_playing: 1,
|
||||
type: 1,
|
||||
source: 1,
|
||||
thumbnail: 1
|
||||
};
|
||||
|
||||
module.exports.project_object = project_object;
|
||||
module.exports.toShowConfig = toShowConfig;
|
||||
module.exports.toShowChannel = toShowChannel;
|
||||
929
server/handlers/chat.js
Normal file
@@ -0,0 +1,929 @@
|
||||
var Functions = require(pathThumbnails + "/handlers/functions.js");
|
||||
var crypto = require("crypto");
|
||||
var Filter = require("bad-words");
|
||||
var filter = new Filter({ placeHolder: "x" });
|
||||
/*var filter = {
|
||||
clean: function(str) {
|
||||
return str;
|
||||
}
|
||||
}*/
|
||||
var db = require(pathThumbnails + "/handlers/db.js");
|
||||
|
||||
function get_history(channel, all, socket) {
|
||||
var query = {};
|
||||
if (all) {
|
||||
query = {
|
||||
all: true
|
||||
};
|
||||
} else {
|
||||
query = {
|
||||
all: false,
|
||||
channel: channel
|
||||
};
|
||||
}
|
||||
//channel = channel.replace(/ /g,'');
|
||||
var pass = "";
|
||||
if (!query.all) {
|
||||
Functions.getSessionAdminUser(
|
||||
Functions.getSession(socket),
|
||||
channel,
|
||||
function(userpass) {
|
||||
if (userpass != "" || pass == undefined) {
|
||||
pass = userpass;
|
||||
} else {
|
||||
pass = crypto
|
||||
.createHash("sha256")
|
||||
.update(Functions.decrypt_string(pass))
|
||||
.digest("base64");
|
||||
}
|
||||
db.collection(channel + "_settings").find({ id: "config" }, function(
|
||||
err,
|
||||
conf
|
||||
) {
|
||||
if (conf.length > 0) {
|
||||
if (conf[0].userpass == "" || conf[0].userpass == pass) {
|
||||
getAndSendLogs(channel, all, socket, pass, query);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
} else {
|
||||
getAndSendLogs(channel, all, socket, pass, query);
|
||||
}
|
||||
}
|
||||
|
||||
function getAndSendLogs(channel, all, socket, pass, query) {
|
||||
//channel = channel.replace(/ /g,'');
|
||||
db.collection("chat_logs")
|
||||
.find(query, {
|
||||
from: 1,
|
||||
createdAt: 1,
|
||||
all: 1,
|
||||
channel: 1,
|
||||
msg: 1,
|
||||
icon: 1,
|
||||
_id: 0
|
||||
})
|
||||
.sort({ createdAt: 1 })
|
||||
.limit(20, function(err, docs) {
|
||||
socket.emit("chat_history", { all: all, data: docs });
|
||||
});
|
||||
}
|
||||
|
||||
function getUserNameByGuid(guid, callback) {
|
||||
db.collection("user_names").find({ guid: guid }, function(err, usernames) {
|
||||
if (usernames.length == 1) {
|
||||
callback(usernames[0].name);
|
||||
return;
|
||||
}
|
||||
callback("Anonymous");
|
||||
});
|
||||
}
|
||||
|
||||
function chat(msg, guid, offline, socket) {
|
||||
if (
|
||||
typeof msg !== "object" ||
|
||||
!msg.hasOwnProperty("data") ||
|
||||
!msg.hasOwnProperty("channel") ||
|
||||
typeof msg.data != "string" ||
|
||||
typeof msg.channel != "string"
|
||||
) {
|
||||
var result = {
|
||||
data: {
|
||||
expected: "string",
|
||||
got: msg.hasOwnProperty("data") ? typeof msg.data : undefined
|
||||
},
|
||||
channel: {
|
||||
expected: "string",
|
||||
got: msg.hasOwnProperty("channel") ? typeof msg.channel : undefined
|
||||
},
|
||||
pass: {
|
||||
expected: "string",
|
||||
got: msg.hasOwnProperty("pass") ? typeof msg.pass : undefined
|
||||
}
|
||||
};
|
||||
socket.emit("update_required", result);
|
||||
return;
|
||||
}
|
||||
var coll = msg.channel.toLowerCase(); //.replace(/ /g,'');
|
||||
coll = Functions.removeEmojis(coll).toLowerCase();
|
||||
//coll = filter.clean(coll);
|
||||
|
||||
checkIfUserIsBanned(coll, socket, guid, function() {
|
||||
Functions.getSessionAdminUser(Functions.getSession(socket), coll, function(
|
||||
userpass,
|
||||
adminpass
|
||||
) {
|
||||
if (userpass != "" || msg.pass == undefined) {
|
||||
msg.pass = userpass;
|
||||
} else {
|
||||
msg.pass = crypto
|
||||
.createHash("sha256")
|
||||
.update(Functions.decrypt_string(msg.pass))
|
||||
.digest("base64");
|
||||
}
|
||||
db.collection(coll + "_settings").find(function(err, conf) {
|
||||
if (
|
||||
conf.length > 0 &&
|
||||
(conf[0].hasOwnProperty("toggleChat") && !conf[0].toggleChat)
|
||||
) {
|
||||
socket.emit("chat", {
|
||||
from: "System",
|
||||
msg: ": Chat for this channel has been disabled.",
|
||||
icon: "https://zoff.me/assets/images/favicon-32x32.png"
|
||||
});
|
||||
return;
|
||||
} else if (
|
||||
conf.length > 0 &&
|
||||
(conf[0].userpass == undefined ||
|
||||
conf[0].userpass == "" ||
|
||||
(msg.hasOwnProperty("pass") && conf[0].userpass == msg.pass))
|
||||
) {
|
||||
var data = msg.data;
|
||||
|
||||
Functions.check_inlist(
|
||||
coll,
|
||||
guid,
|
||||
socket,
|
||||
offline,
|
||||
function() {
|
||||
if (data == "/who") {
|
||||
db.collection("user_names").distinct(
|
||||
"name",
|
||||
{ channels: coll },
|
||||
function(err, docs) {
|
||||
var userAdd = "s";
|
||||
if (docs.length == 1) userAdd = "";
|
||||
socket.emit("chat", {
|
||||
from: "System",
|
||||
msg:
|
||||
": User" +
|
||||
userAdd +
|
||||
" in channel are: " +
|
||||
docs.join(", "),
|
||||
icon: "https://zoff.me/assets/images/favicon-32x32.png"
|
||||
});
|
||||
}
|
||||
);
|
||||
} else if (
|
||||
data !== "" &&
|
||||
data !== undefined &&
|
||||
data !== null &&
|
||||
data.length < 151 &&
|
||||
data.replace(/\s/g, "").length
|
||||
) {
|
||||
db.collection("user_names").find({ guid: guid }, function(
|
||||
err,
|
||||
docs
|
||||
) {
|
||||
if (docs.length == 1) {
|
||||
var splitData = data.split(" ");
|
||||
if (
|
||||
(data.startsWith("/ban") && splitData.length >= 3) ||
|
||||
(data.startsWith("/unban") && splitData.length >= 2)
|
||||
) {
|
||||
if (splitData[1].length > 0) {
|
||||
var passToCompare = Functions.hash_pass(adminpass);
|
||||
if (passToCompare == conf[0].adminpass) {
|
||||
db.collection("user_names").find(
|
||||
{ name: splitData[1] },
|
||||
function(err, name) {
|
||||
if (name.length == 1) {
|
||||
if (
|
||||
data.startsWith("/ban") &&
|
||||
splitData.length >= 3
|
||||
) {
|
||||
var reason = splitData
|
||||
.slice(2, splitData.length)
|
||||
.join(" ");
|
||||
var connection_id = name[0].connection_id;
|
||||
var yourSelf = Functions.hash_pass(
|
||||
socket.handshake.headers["user-agent"] +
|
||||
socket.handshake.address +
|
||||
socket.handshake.headers[
|
||||
"accept-language"
|
||||
]
|
||||
);
|
||||
if (connection_id != yourSelf) {
|
||||
db.collection(coll + "_banned_chat").update(
|
||||
{
|
||||
connection_id: connection_id
|
||||
},
|
||||
{
|
||||
connection_id: connection_id,
|
||||
by: docs[0].name,
|
||||
reason: reason
|
||||
},
|
||||
{
|
||||
upsert: true
|
||||
},
|
||||
function(err, results) {
|
||||
io.to(coll).emit("chat", {
|
||||
from: "System",
|
||||
msg:
|
||||
": " +
|
||||
docs[0].name +
|
||||
" has banned " +
|
||||
splitData[1] +
|
||||
" for: " +
|
||||
reason,
|
||||
icon:
|
||||
"https://zoff.me/assets/images/favicon-32x32.png"
|
||||
});
|
||||
return;
|
||||
}
|
||||
);
|
||||
} else {
|
||||
socket.emit("chat", {
|
||||
from: "System",
|
||||
msg:
|
||||
": I'm sorry but you can't ban yourself..",
|
||||
icon:
|
||||
"https://zoff.me/assets/images/favicon-32x32.png"
|
||||
});
|
||||
return;
|
||||
}
|
||||
} else if (data.startsWith("/unban")) {
|
||||
db.collection(coll + "_banned_chat").remove(
|
||||
{ connection_id: name[0].connection_id },
|
||||
function(err, results) {
|
||||
if (
|
||||
results.hasOwnProperty("n") &&
|
||||
results.n == 1 &&
|
||||
results.hasOwnProperty(
|
||||
"deletedCount"
|
||||
) &&
|
||||
results.deletedCount == 1
|
||||
) {
|
||||
io.to(coll).emit("chat", {
|
||||
from: "System",
|
||||
msg:
|
||||
": " +
|
||||
docs[0].name +
|
||||
" has unbanned " +
|
||||
splitData[1],
|
||||
icon:
|
||||
"https://zoff.me/assets/images/favicon-32x32.png"
|
||||
});
|
||||
return;
|
||||
} else {
|
||||
socket.emit("chat", {
|
||||
from: "System",
|
||||
msg:
|
||||
": Cannot find anyone with that username in this chat.",
|
||||
icon:
|
||||
"https://zoff.me/assets/images/favicon-32x32.png"
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
);
|
||||
} else if (
|
||||
data.startsWith("/ban") &&
|
||||
splitData.length < 3
|
||||
) {
|
||||
socket.emit("chat", {
|
||||
from: "System",
|
||||
msg:
|
||||
": You are doing that command wrong. its /ban USERNAME",
|
||||
icon:
|
||||
"https://zoff.me/assets/images/favicon-32x32.png"
|
||||
});
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
socket.emit("chat", {
|
||||
from: "System",
|
||||
msg: ": No user by that name.",
|
||||
icon:
|
||||
"https://zoff.me/assets/images/favicon-32x32.png"
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
);
|
||||
} else {
|
||||
socket.emit("chat", {
|
||||
from: "System",
|
||||
msg:
|
||||
": You are not logged in as an admin to the channel, don't try any funnybusiness.",
|
||||
icon:
|
||||
"https://zoff.me/assets/images/favicon-32x32.png"
|
||||
});
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
socket.emit("chat", {
|
||||
from: "System",
|
||||
msg:
|
||||
": You are doing that command wrong. its /ban USERNAME REASON or /unban USERNAME",
|
||||
icon:
|
||||
"https://zoff.me/assets/images/favicon-32x32.png"
|
||||
});
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
db.collection("registered_users").find(
|
||||
{ _id: docs[0].name },
|
||||
function(err, n) {
|
||||
var icon = false;
|
||||
if (n.length > 0 && n[0].icon) {
|
||||
icon = n[0].icon;
|
||||
}
|
||||
db.collection("chat_logs").insert({
|
||||
createdAt: new Date(),
|
||||
all: false,
|
||||
channel: coll,
|
||||
from: docs[0].name,
|
||||
msg: ": " + data,
|
||||
icon: icon
|
||||
});
|
||||
io.to(coll).emit("chat", {
|
||||
from: docs[0].name,
|
||||
msg: ": " + data,
|
||||
icon: icon
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
} else if (docs.length == 0) {
|
||||
get_name(guid, {
|
||||
announce: false,
|
||||
channel: coll,
|
||||
message: data,
|
||||
all: false,
|
||||
socket: socket
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
"place 1"
|
||||
);
|
||||
} else {
|
||||
socket.emit("auth_required");
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function all_chat(msg, guid, offline, socket) {
|
||||
if (
|
||||
typeof msg !== "object" ||
|
||||
!msg.hasOwnProperty("channel") ||
|
||||
!msg.hasOwnProperty("data") ||
|
||||
typeof msg.data != "string" ||
|
||||
typeof msg.channel != "string"
|
||||
) {
|
||||
var result = {
|
||||
data: {
|
||||
expected: "string",
|
||||
got: msg.hasOwnProperty("data") ? typeof msg.data : undefined
|
||||
},
|
||||
channel: {
|
||||
expected: "string",
|
||||
got: msg.hasOwnProperty("channel") ? typeof msg.channel : undefined
|
||||
}
|
||||
};
|
||||
socket.emit("update_required", result);
|
||||
return;
|
||||
}
|
||||
var coll = msg.channel.toLowerCase(); //.replace(/ /g,'');
|
||||
var data = msg.data;
|
||||
coll = Functions.removeEmojis(coll).toLowerCase();
|
||||
//coll = filter.clean(coll);
|
||||
Functions.check_inlist(
|
||||
coll,
|
||||
guid,
|
||||
socket,
|
||||
offline,
|
||||
function() {
|
||||
if (
|
||||
data !== "" &&
|
||||
data !== undefined &&
|
||||
data !== null &&
|
||||
data.length < 151 &&
|
||||
data.replace(/\s/g, "").length
|
||||
) {
|
||||
db.collection("user_names").find({ guid: guid }, function(err, docs) {
|
||||
if (docs.length == 1) {
|
||||
db.collection("registered_users").find(
|
||||
{ _id: docs[0].name },
|
||||
function(err, n) {
|
||||
var icon = false;
|
||||
if (n.length > 0 && n[0].icon) {
|
||||
icon = n[0].icon;
|
||||
}
|
||||
db.collection("chat_logs").insert(
|
||||
{
|
||||
createdAt: new Date(),
|
||||
all: true,
|
||||
channel: coll,
|
||||
from: docs[0].name,
|
||||
msg: ": " + data,
|
||||
icon: icon
|
||||
},
|
||||
function(err, docs) {}
|
||||
);
|
||||
io.sockets.emit("chat.all", {
|
||||
from: docs[0].name,
|
||||
msg: ": " + data,
|
||||
channel: coll,
|
||||
icon: icon
|
||||
});
|
||||
}
|
||||
);
|
||||
} else if (docs.length == 0) {
|
||||
get_name(guid, {
|
||||
announce: false,
|
||||
channel: coll,
|
||||
message: data,
|
||||
all: true,
|
||||
socket: socket
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
"place 2"
|
||||
);
|
||||
}
|
||||
|
||||
function checkIfChatEnabled(channel, socket, callback) {
|
||||
if (channel == "" || channel == undefined) callback();
|
||||
else {
|
||||
db.collection(channel + "_settings").find(function(err, docs) {
|
||||
if (
|
||||
docs.length > 0 &&
|
||||
(docs[0].hasOwnProperty("toggleChat") && !docs[0].toggleChat)
|
||||
) {
|
||||
socket.emit("chat", {
|
||||
from: "System",
|
||||
msg: ": Chat for this channel has been disabled.",
|
||||
icon: "https://zoff.me/assets/images/favicon-32x32.png"
|
||||
});
|
||||
callback(false);
|
||||
} else {
|
||||
callback(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function checkIfUserIsBanned(channel, socket, guid, callback, callback_error) {
|
||||
var connection_id = Functions.hash_pass(
|
||||
socket.handshake.headers["user-agent"] +
|
||||
socket.handshake.address +
|
||||
socket.handshake.headers["accept-language"]
|
||||
);
|
||||
db.collection(channel + "_banned_chat").find(
|
||||
{ $or: [{ connection_id: connection_id }, { connection_id: guid }] },
|
||||
function(err, docs) {
|
||||
if (docs.length == 0) callback();
|
||||
else {
|
||||
db.collection("user_names").findAndModify(
|
||||
{
|
||||
query: { guid, guid },
|
||||
update: { $addToSet: { channels: channel } }
|
||||
},
|
||||
function(e, d) {
|
||||
socket.emit("chat", {
|
||||
from: "System",
|
||||
msg:
|
||||
": You can't chat in this channel, you are banned. The reason is: " +
|
||||
docs[0].reason,
|
||||
icon: "https://zoff.me/assets/images/favicon-32x32.png"
|
||||
});
|
||||
if (typeof callback_error == "function") callback_error();
|
||||
else return;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function namechange(data, guid, socket, tried, callback) {
|
||||
checkIfChatEnabled(data.channel, socket, function(enabled) {
|
||||
if (!enabled) {
|
||||
callback(false);
|
||||
return;
|
||||
}
|
||||
checkIfUserIsBanned(
|
||||
data.channel,
|
||||
socket,
|
||||
guid,
|
||||
function() {
|
||||
var pw = "";
|
||||
var new_password;
|
||||
var first = false;
|
||||
Functions.getSessionChatPass(Functions.getSession(socket), function(
|
||||
name,
|
||||
pass
|
||||
) {
|
||||
var fetched = false;
|
||||
if (data.hasOwnProperty("first") && data.first) {
|
||||
pw = pass;
|
||||
name = name;
|
||||
data.name = name;
|
||||
data.password = pass;
|
||||
new_password = false;
|
||||
if (name == "" || pass == "") {
|
||||
if (typeof callback == "function") callback(true);
|
||||
return;
|
||||
}
|
||||
fetched = true;
|
||||
password = pw;
|
||||
} else {
|
||||
var name = data.name;
|
||||
if (data.hasOwnProperty("first")) {
|
||||
first = data.first;
|
||||
}
|
||||
if (data.hasOwnProperty("password")) {
|
||||
pw = data.password;
|
||||
new_password = false;
|
||||
} else if (
|
||||
data.hasOwnProperty("new_password") &&
|
||||
data.hasOwnProperty("old_password")
|
||||
) {
|
||||
pw = data.old_password;
|
||||
new_password = Functions.decrypt_string(data.new_password);
|
||||
}
|
||||
password = Functions.decrypt_string(pw);
|
||||
password = Functions.hash_pass(password);
|
||||
doubled = true;
|
||||
}
|
||||
|
||||
if (name == "") {
|
||||
if (typeof callback == "function") callback(true);
|
||||
return;
|
||||
}
|
||||
|
||||
db.collection("registered_users").find(
|
||||
{ _id: name.toLowerCase() },
|
||||
function(err, docs) {
|
||||
var accepted_password = false;
|
||||
var icon = false;
|
||||
if (docs.length == 0) {
|
||||
if (new_password) {
|
||||
if (typeof callback == "function") callback(true);
|
||||
return;
|
||||
}
|
||||
accepted_password = true;
|
||||
Functions.setSessionChatPass(
|
||||
Functions.getSession(socket),
|
||||
name.toLowerCase(),
|
||||
data.password,
|
||||
function() {
|
||||
db.collection("registered_users").update(
|
||||
{ _id: name.toLowerCase() },
|
||||
{ $set: { password: password } },
|
||||
{ upsert: true },
|
||||
function() {}
|
||||
);
|
||||
}
|
||||
);
|
||||
} else if (docs[0].password == password) {
|
||||
if (docs[0].icon) {
|
||||
icon = docs[0].icon;
|
||||
}
|
||||
accepted_password = true;
|
||||
if (new_password) {
|
||||
Functions.setSessionChatPass(
|
||||
Functions.getSession(socket),
|
||||
name.toLowerCase(),
|
||||
data.new_password,
|
||||
function() {
|
||||
db.collection("registered_users").update(
|
||||
{ _id: name.toLowerCase(), password: password },
|
||||
{
|
||||
$set: { password: Functions.hash_pass(new_password) }
|
||||
},
|
||||
function() {}
|
||||
);
|
||||
}
|
||||
);
|
||||
} else {
|
||||
Functions.setSessionChatPass(
|
||||
Functions.getSession(socket),
|
||||
name.toLowerCase(),
|
||||
fetched
|
||||
? data.password
|
||||
: Functions.hash_pass(
|
||||
Functions.decrypt_string(data.password)
|
||||
),
|
||||
function() {}
|
||||
);
|
||||
}
|
||||
}
|
||||
if (accepted_password) {
|
||||
db.collection("user_names").find({ guid: guid }, function(
|
||||
err,
|
||||
names
|
||||
) {
|
||||
if (
|
||||
names.length > 0 ||
|
||||
(docs.length != 0 && docs[0].password == password)
|
||||
) {
|
||||
var no_name = false;
|
||||
if (names.length == 0) no_name = true;
|
||||
if (!no_name) {
|
||||
var old_name = names[0].name;
|
||||
db.collection("user_names").update(
|
||||
{ _id: "all_names" },
|
||||
{ $pull: { names: old_name } },
|
||||
function() {}
|
||||
);
|
||||
}
|
||||
var connection_id = Functions.hash_pass(
|
||||
socket.handshake.headers["user-agent"] +
|
||||
socket.handshake.address +
|
||||
socket.handshake.headers["accept-language"]
|
||||
);
|
||||
var updateElement = {
|
||||
$set: {
|
||||
name: name,
|
||||
icon: icon,
|
||||
connection_id: connection_id
|
||||
}
|
||||
};
|
||||
if (data.hasOwnProperty("channel") && data.channel != "") {
|
||||
updateElement["$addToSet"] = { channels: data.channel };
|
||||
}
|
||||
db.collection("user_names").update(
|
||||
{ guid: guid },
|
||||
updateElement,
|
||||
{ upsert: true },
|
||||
function(err, docs) {
|
||||
db.collection("user_names").update(
|
||||
{ _id: "all_names" },
|
||||
{ $addToSet: { names: name } },
|
||||
function(err, docs) {
|
||||
//socket.emit('name', {type: "name", accepted: true});
|
||||
if (old_name != name && !first && !no_name) {
|
||||
if (
|
||||
data.hasOwnProperty("channel") &&
|
||||
typeof data.channel == "string"
|
||||
) {
|
||||
io.to(data.channel).emit("chat", {
|
||||
from: old_name,
|
||||
msg: " changed name to " + name
|
||||
});
|
||||
io.sockets.emit("chat.all", {
|
||||
from: old_name,
|
||||
msg: " changed name to " + name,
|
||||
channel: data.channel
|
||||
});
|
||||
}
|
||||
}
|
||||
if (
|
||||
callback != undefined &&
|
||||
typeof callback == "function"
|
||||
)
|
||||
callback(true);
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
} else {
|
||||
if (tried < 3 || tried == undefined) {
|
||||
if (tried == undefined) {
|
||||
tried = 1;
|
||||
}
|
||||
namechange(data, guid, socket, tried + 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Functions.removeSessionChatPass(
|
||||
Functions.getSession(socket),
|
||||
function() {
|
||||
socket.emit("name", { type: "name", accepted: false });
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
},
|
||||
callback
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function removename(guid, coll, socket) {
|
||||
//coll = coll.replace(/ /g,'');
|
||||
checkIfChatEnabled(coll, socket, function(enabled) {
|
||||
if (!enabled) return;
|
||||
db.collection("user_names").find({ guid: guid }, function(err, docs) {
|
||||
if (docs.length == 1) {
|
||||
var old_name = docs[0].name;
|
||||
Functions.removeSessionChatPass(
|
||||
Functions.getSession(socket),
|
||||
function() {
|
||||
db.collection("user_names").update(
|
||||
{ _id: "all_names" },
|
||||
{ $pull: { names: old_name } },
|
||||
function(err, updated) {
|
||||
db.collection("user_names").remove({ guid: guid }, function(
|
||||
err,
|
||||
removed
|
||||
) {
|
||||
get_name(guid, {
|
||||
announce: true,
|
||||
old_name: old_name,
|
||||
channel: coll,
|
||||
socket: socket
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function generate_name(guid, announce_payload, second, round, channel) {
|
||||
if (round == undefined) round = 0;
|
||||
var tmp_name = Functions.rndName(
|
||||
second ? second : guid,
|
||||
Math.floor(8 + round)
|
||||
);
|
||||
db.collection("registered_users").find({ _id: tmp_name }, function(
|
||||
err,
|
||||
docs
|
||||
) {
|
||||
if (docs.length == 0) {
|
||||
db.collection("user_names").update(
|
||||
{ _id: "all_names" },
|
||||
{ $addToSet: { names: tmp_name } },
|
||||
{ upsert: true },
|
||||
function(err, updated) {
|
||||
if (
|
||||
updated.nModified == 1 ||
|
||||
(updated.hasOwnProperty("upserted") &&
|
||||
updated.hasOwnProperty("n") &&
|
||||
updated.n == 1)
|
||||
) {
|
||||
var connection_id = Functions.hash_pass(
|
||||
announce_payload.socket.handshake.headers["user-agent"] +
|
||||
announce_payload.socket.handshake.address +
|
||||
announce_payload.socket.handshake.headers["accept-language"]
|
||||
);
|
||||
var updateElement = {
|
||||
$set: {
|
||||
name: tmp_name,
|
||||
icon: false,
|
||||
connection_id: connection_id
|
||||
}
|
||||
};
|
||||
if (channel != undefined && channel != "") {
|
||||
updateElement["$addToSet"] = { channels: channel };
|
||||
}
|
||||
if (
|
||||
announce_payload.hasOwnProperty("channel") &&
|
||||
announce_payload.channel != ""
|
||||
) {
|
||||
updateElement["$addToSet"] = {
|
||||
channels: announce_payload.channel
|
||||
};
|
||||
}
|
||||
db.collection("user_names").update(
|
||||
{ guid: guid },
|
||||
updateElement,
|
||||
{ upsert: true },
|
||||
function(err, update) {
|
||||
name = tmp_name;
|
||||
if (announce_payload.announce) {
|
||||
io.to(announce_payload.channel).emit("chat", {
|
||||
from: announce_payload.old_name,
|
||||
msg: " changed name to " + name
|
||||
});
|
||||
io.sockets.emit("chat.all", {
|
||||
from: announce_payload.old_name,
|
||||
msg: " changed name to " + name,
|
||||
channel: announce_payload.channel
|
||||
});
|
||||
} else if (announce_payload.message && !announce_payload.all) {
|
||||
io.to(announce_payload.channel).emit("chat", {
|
||||
from: name,
|
||||
msg: ": " + announce_payload.message
|
||||
});
|
||||
} else if (announce_payload.message && announce_payload.all) {
|
||||
io.sockets.emit("chat.all", {
|
||||
from: name,
|
||||
msg: ": " + announce_payload.message,
|
||||
channel: announce_payload.channel
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
} else {
|
||||
generate_name(
|
||||
guid,
|
||||
announce_payload,
|
||||
tmp_name,
|
||||
round + 0.25,
|
||||
channel
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
} else {
|
||||
generate_name(guid, announce_payload, tmp_name, round + 0.25, channel);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function get_name(guid, announce_payload, first) {
|
||||
if (!announce_payload.announce && announce_payload.hasOwnProperty("socket")) {
|
||||
Functions.getSessionChatPass(
|
||||
Functions.getSession(announce_payload.socket),
|
||||
function(name, pass) {
|
||||
if (name == "" || pass == "") {
|
||||
get_name_generate(
|
||||
guid,
|
||||
announce_payload,
|
||||
first,
|
||||
announce_payload.channel
|
||||
);
|
||||
return;
|
||||
}
|
||||
db.collection("registered_users").find(
|
||||
{ _id: name.toLowerCase() },
|
||||
function(err, docs) {
|
||||
if (
|
||||
docs[0].password ==
|
||||
Functions.hash_pass(Functions.decrypt_string(pass))
|
||||
) {
|
||||
var icon = false;
|
||||
if (docs[0].icon) {
|
||||
icon = docs[0].icon;
|
||||
}
|
||||
Functions.setSessionChatPass(
|
||||
Functions.getSession(announce_payload.socket),
|
||||
name.toLowerCase(),
|
||||
pass,
|
||||
function() {}
|
||||
);
|
||||
var connection_id = Functions.hash_pass(
|
||||
announce_payload.socket.handshake.headers["user-agent"] +
|
||||
announce_payload.socket.handshake.address +
|
||||
announce_payload.socket.handshake.headers["accept-language"]
|
||||
);
|
||||
var updateElement = {
|
||||
$set: { name: name, icon: icon, connection_id: connection_id }
|
||||
};
|
||||
if (
|
||||
announce_payload.hasOwnProperty("channel") &&
|
||||
announce_payload.channel != ""
|
||||
)
|
||||
updateElement["$addToSet"] = {
|
||||
channel: announce_payload.channel
|
||||
};
|
||||
db.collection("user_names").update(
|
||||
{ guid: guid },
|
||||
updateElement,
|
||||
{ upsert: true },
|
||||
function(err, docs) {
|
||||
db.collection("user_names").update(
|
||||
{ _id: "all_names" },
|
||||
{ $addToSet: { names: name } },
|
||||
function(err, docs) {
|
||||
name = name;
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
} else {
|
||||
get_name_generate(guid, announce_payload, first, announce_payload.channel);
|
||||
}
|
||||
}
|
||||
|
||||
function get_name_generate(guid, announce_payload, first, channel) {
|
||||
db.collection("user_names").find({ guid: guid }, function(err, docs) {
|
||||
if (docs.length == 0) {
|
||||
generate_name(guid, announce_payload, undefined);
|
||||
} else {
|
||||
name = docs[0].name;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
module.exports.getUserNameByGuid = getUserNameByGuid;
|
||||
module.exports.get_history = get_history;
|
||||
module.exports.chat = chat;
|
||||
module.exports.all_chat = all_chat;
|
||||
module.exports.namechange = namechange;
|
||||
module.exports.removename = removename;
|
||||
module.exports.generate_name = generate_name;
|
||||
module.exports.get_name = get_name;
|
||||
84
server/handlers/db.js
Normal file
@@ -0,0 +1,84 @@
|
||||
var path = require("path");
|
||||
try {
|
||||
var mongo_config = require(path.join(
|
||||
path.join(__dirname, "../config/"),
|
||||
"mongo_config.js"
|
||||
));
|
||||
} catch (e) {
|
||||
console.log(
|
||||
"(!) Missing file - /config/mongo_config.js. Have a look at /config/mongo_config.example.js. The server won't run without this existing."
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
var mongojs = require("mongojs");
|
||||
var db = mongojs("mongodb://" + mongo_config.host + "/" + mongo_config.config);
|
||||
var connected_db = mongojs(
|
||||
"mongodb://" + mongo_config.host + "/user_credentials"
|
||||
);
|
||||
var ObjectId = mongojs.ObjectId;
|
||||
|
||||
db.collection("chat_logs").createIndex(
|
||||
{ createdAt: 1 },
|
||||
{ expireAfterSeconds: 600 },
|
||||
function() {}
|
||||
);
|
||||
db.collection("timeout_api").createIndex(
|
||||
{ createdAt: 1 },
|
||||
{ expireAfterSeconds: 120 },
|
||||
function() {}
|
||||
);
|
||||
db.collection("api_links").createIndex(
|
||||
{ createdAt: 1 },
|
||||
{ expireAfterSeconds: 86400 },
|
||||
function() {}
|
||||
);
|
||||
db.on("connected", function(err) {
|
||||
console.log("connected");
|
||||
});
|
||||
|
||||
db.on("error", function(err) {
|
||||
console.log("\n" + new Date().toString() + "\n Database error: ", err);
|
||||
});
|
||||
|
||||
db.on("error", function(err) {
|
||||
console.log("\n" + new Date().toString() + "\n Database error: ", err);
|
||||
});
|
||||
|
||||
/* Resetting usernames, and connected users */
|
||||
db.collection("unique_ids").update(
|
||||
{ _id: "unique_ids" },
|
||||
{ $set: { unique_ids: [] } },
|
||||
{ multi: true, upsert: true },
|
||||
function(err, docs) {}
|
||||
);
|
||||
db.collection("user_names").remove(
|
||||
{ guid: { $exists: true } },
|
||||
{ multi: true, upsert: true },
|
||||
function(err, docs) {}
|
||||
);
|
||||
db.collection("user_names").update(
|
||||
{ _id: "all_names" },
|
||||
{ $set: { names: [] } },
|
||||
{ multi: true, upsert: true },
|
||||
function(err, docs) {}
|
||||
);
|
||||
db.collection("connected_users").update(
|
||||
{ users: { $exists: true } },
|
||||
{ $set: { users: [] } },
|
||||
{ multi: true, upsert: true },
|
||||
function(err, docs) {}
|
||||
);
|
||||
db.collection("connected_users").update(
|
||||
{ _id: "total_users" },
|
||||
{ $set: { total_users: [] } },
|
||||
{ multi: true, upsert: true },
|
||||
function(err, docs) {}
|
||||
);
|
||||
db.collection("frontpage_lists").update(
|
||||
{ viewers: { $ne: 0 } },
|
||||
{ $set: { viewers: 0 } },
|
||||
{ multi: true, upsert: true },
|
||||
function(err, docs) {}
|
||||
);
|
||||
|
||||
module.exports = db;
|
||||
145
server/handlers/frontpage.js
Normal file
@@ -0,0 +1,145 @@
|
||||
var Functions = require(pathThumbnails + "/handlers/functions.js");
|
||||
var db = require(pathThumbnails + "/handlers/db.js");
|
||||
function frontpage_lists(msg, socket) {
|
||||
if (
|
||||
msg == undefined ||
|
||||
!msg.hasOwnProperty("version") ||
|
||||
msg.version != VERSION ||
|
||||
msg.version == undefined
|
||||
) {
|
||||
var result = {
|
||||
version: {
|
||||
expected: VERSION,
|
||||
got: msg.hasOwnProperty("version") ? msg.version : undefined
|
||||
}
|
||||
};
|
||||
socket.emit("update_required", result);
|
||||
return;
|
||||
}
|
||||
|
||||
db.collection("frontpage_lists").find({ frontpage: true }, function(
|
||||
err,
|
||||
docs
|
||||
) {
|
||||
db.collection("connected_users").find({ _id: "total_users" }, function(
|
||||
err,
|
||||
tot
|
||||
) {
|
||||
socket
|
||||
.compress(true)
|
||||
.emit("playlists", {
|
||||
channels: docs,
|
||||
viewers: tot[0].total_users.length
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function get_frontpage_lists(callback) {
|
||||
var project_object = {
|
||||
_id: 1,
|
||||
count: 1,
|
||||
frontpage: 1,
|
||||
id: 1,
|
||||
title: 1,
|
||||
viewers: 1,
|
||||
accessed: 1,
|
||||
pinned: { $ifNull: ["$pinned", 0] },
|
||||
description: {
|
||||
$ifNull: [
|
||||
{
|
||||
$cond: {
|
||||
if: {
|
||||
$or: [
|
||||
{ $eq: ["$description", ""] },
|
||||
{ $eq: ["$description", null] },
|
||||
{ $eq: ["$description", undefined] }
|
||||
]
|
||||
},
|
||||
then: "This list has no description",
|
||||
else: "$description"
|
||||
}
|
||||
},
|
||||
"This list has no description"
|
||||
]
|
||||
},
|
||||
thumbnail: {
|
||||
$ifNull: [
|
||||
{
|
||||
$cond: {
|
||||
if: {
|
||||
$or: [
|
||||
{ $eq: ["$thumbnail", ""] },
|
||||
{ $eq: ["$thumbnail", null] },
|
||||
{ $eq: ["$thumbnail", undefined] }
|
||||
]
|
||||
},
|
||||
then: {
|
||||
$concat: ["https://img.youtube.com/vi/", "$id", "/mqdefault.jpg"]
|
||||
},
|
||||
else: "$thumbnail"
|
||||
}
|
||||
},
|
||||
{ $concat: ["https://img.youtube.com/vi/", "$id", "/mqdefault.jpg"] }
|
||||
]
|
||||
}
|
||||
};
|
||||
db.collection("frontpage_lists").aggregate(
|
||||
[
|
||||
{
|
||||
$match: {
|
||||
frontpage: true,
|
||||
count: { $gt: 3 }
|
||||
}
|
||||
},
|
||||
{
|
||||
$project: project_object
|
||||
},
|
||||
{
|
||||
$sort: {
|
||||
pinned: -1,
|
||||
viewers: -1,
|
||||
accessed: -1,
|
||||
count: -1,
|
||||
title: 1
|
||||
}
|
||||
}
|
||||
],
|
||||
callback
|
||||
);
|
||||
}
|
||||
|
||||
function update_frontpage(coll, id, title, thumbnail, source, callback) {
|
||||
//coll = coll.replace(/ /g,'');
|
||||
db.collection("frontpage_lists").find({ _id: coll }, function(e, doc) {
|
||||
var updateObject = {
|
||||
id: id,
|
||||
title: title,
|
||||
accessed: Functions.get_time()
|
||||
};
|
||||
if (
|
||||
doc.length > 0 &&
|
||||
((doc[0].thumbnail != "" &&
|
||||
doc[0].thumbnail != undefined &&
|
||||
(doc[0].thumbnail.indexOf("https://i1.sndcdn.com") > -1 ||
|
||||
doc[0].thumbnail.indexOf("https://w1.sndcdn.com") > -1 ||
|
||||
doc[0].thumbnail.indexOf("https://img.youtube.com") > -1)) ||
|
||||
(doc[0].thumbnail == "" || doc[0].thumbnail == undefined))
|
||||
) {
|
||||
updateObject.thumbnail = thumbnail;
|
||||
if (thumbnail == undefined) updateObject.thumbnail = "";
|
||||
}
|
||||
db.collection("frontpage_lists").update(
|
||||
{ _id: coll },
|
||||
{ $set: updateObject },
|
||||
{ upsert: true },
|
||||
function(err, returnDocs) {
|
||||
if (typeof callback == "function") callback();
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports.get_frontpage_lists = get_frontpage_lists;
|
||||
module.exports.frontpage_lists = frontpage_lists;
|
||||
module.exports.update_frontpage = update_frontpage;
|
||||
710
server/handlers/functions.js
Normal file
@@ -0,0 +1,710 @@
|
||||
var path = require("path");
|
||||
try {
|
||||
var mongo_config = require(path.join(
|
||||
path.join(__dirname, "../config/"),
|
||||
"mongo_config.js"
|
||||
));
|
||||
} catch (e) {
|
||||
console.log(
|
||||
"(!) Missing file - /config/mongo_config.js. Have a look at /config/mongo_config.example.js. The server won't run without this existing."
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
var mongojs = require("mongojs");
|
||||
var connected_db = mongojs(
|
||||
"mongodb://" + mongo_config.host + "/user_credentials"
|
||||
);
|
||||
var crypto = require("crypto");
|
||||
var db = require(pathThumbnails + "/handlers/db.js");
|
||||
var uniqid = require("uniqid");
|
||||
var Filter = require("bad-words");
|
||||
var filter = new Filter({ placeHolder: "x" });
|
||||
|
||||
var Chat = require(pathThumbnails + "/handlers/chat.js");
|
||||
|
||||
function encodeChannelName(str) {
|
||||
var _fn = encodeURIComponent;
|
||||
str = filter.clean(str);
|
||||
var toReturn = _fn(str);
|
||||
toReturn = toReturn.replace(/_/g, "%5F");
|
||||
toReturn = toReturn.replace(/'/g, "%27");
|
||||
toReturn = toReturn.replace(/%26amp%3B/g, "%26").replace(/%26amp%3b/g, "%26");
|
||||
toReturn = toReturn.toLowerCase();
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
function decodeChannelName(str) {
|
||||
var _fn = decodeURIComponent;
|
||||
str = str.toUpperCase();
|
||||
var toReturn = _fn(str.replace(/%5F/g, "_").replace(/%27/g, "'"));
|
||||
toReturn = filter.clean(toReturn);
|
||||
return toReturn.toLowerCase();
|
||||
}
|
||||
|
||||
function remove_unique_id(short_id) {
|
||||
db.collection("unique_ids").update(
|
||||
{ _id: "unique_ids" },
|
||||
{ $pull: { unique_ids: short_id } },
|
||||
function(err, docs) {}
|
||||
);
|
||||
}
|
||||
|
||||
function remove_name_from_db(guid, channel) {
|
||||
// Use temporary, with caution. Can bottleneck in large quantity of users.
|
||||
//
|
||||
// Find a way of indexing users in lists in a clever way, to avoid the search here
|
||||
db.collection("connected_users").find({ _id: "total_users" }, function(
|
||||
err,
|
||||
all_users
|
||||
) {
|
||||
var hasOne = all_users[0].total_users.some(function(v) {
|
||||
return v.indexOf(guid) >= 0;
|
||||
});
|
||||
if (!hasOne) {
|
||||
db.collection("user_names").find({ guid: guid }, function(err, user) {
|
||||
if (user.length == 1) {
|
||||
db.collection("user_names").update(
|
||||
{ _id: "all_names" },
|
||||
{ $pull: { names: user[0].name } },
|
||||
function(err, updated) {
|
||||
db.collection("user_names").remove({ guid: guid }, function(
|
||||
err,
|
||||
removed
|
||||
) {});
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (channel == undefined || channel == "") return;
|
||||
db.collection("user_names").update(
|
||||
{ guid: guid },
|
||||
{ $pull: { channels: channel } },
|
||||
function(err, docs) {
|
||||
//console.log("Pulled user from current channel");
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function isUrl(str) {
|
||||
var pattern = new RegExp(
|
||||
"\\b(((ht|f)tp(s?)\\:\\/\\/|~\\/|\\/)|www.)" +
|
||||
"(\\w+:\\w+@)?(([-\\w]+\\.)+(com|org|net|gov" +
|
||||
"|mil|biz|info|mobi|name|aero|jobs|museum" +
|
||||
"|travel|[a-z]{2}))(:[\\d]{1,5})?" +
|
||||
"(((\\/([-\\w~!$+|.,=]|%[a-f\\d]{2})+)+|\\/)+|\\?|#)?" +
|
||||
"((\\?([-\\w~!$+|.,*:]|%[a-f\\d{2}])+=?" +
|
||||
"([-\\w~!$+|.,*:=]|%[a-f\\d]{2})*)" +
|
||||
"(&(?:[-\\w~!$+|.,*:]|%[a-f\\d{2}])+=?" +
|
||||
"([-\\w~!$+|.,*:=]|%[a-f\\d]{2})*)*)*" +
|
||||
"(#([-\\w~!$+|.,*:=]|%[a-f\\d]{2})*)?\\b"
|
||||
);
|
||||
if (!pattern.test(str)) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function getSession(socket) {
|
||||
try {
|
||||
/*var cookieParser = require("cookie-parser");
|
||||
var cookie = require("cookie");
|
||||
var parsedCookies = cookie.parse(socket.handshake.headers.cookie);
|
||||
return parsedCookies["_uI"];*/
|
||||
if (socket.cookie_id == undefined) throw "Undefined error";
|
||||
return socket.cookie_id;
|
||||
} catch (e) {
|
||||
// Returning "sessiong"-based on place of connection
|
||||
return hash_pass(
|
||||
socket.handshake.headers["user-agent"] +
|
||||
socket.handshake.address +
|
||||
socket.handshake.headers["accept-language"]
|
||||
);
|
||||
//return "empty";
|
||||
}
|
||||
}
|
||||
|
||||
function remove_from_array(array, element) {
|
||||
if (contains(array, element)) {
|
||||
var index = array.indexOf(element);
|
||||
if (index != -1) array.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
function generate_channel_name(res) {
|
||||
var trying_id = uniqid.time().toLowerCase();
|
||||
db.collection("frontpage_lists").find(
|
||||
{ frontpage: { $exists: true }, _id: trying_id },
|
||||
{ _id: 1 },
|
||||
function(err, docs) {
|
||||
if (docs.length == 0) {
|
||||
res.send(trying_id);
|
||||
return;
|
||||
}
|
||||
generate_channel_name(res);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function get_short_id(socket) {
|
||||
var new_short_id = uniqid.time().toLowerCase();
|
||||
|
||||
socket.join(new_short_id);
|
||||
socket.emit("id", new_short_id);
|
||||
}
|
||||
|
||||
function check_inlist(coll, guid, socket, offline, callback, double_check) {
|
||||
if (coll == undefined) {
|
||||
if (typeof callback == "function") callback();
|
||||
return;
|
||||
}
|
||||
//coll = coll.replace(/ /g,'');
|
||||
if (!offline && coll != undefined) {
|
||||
db.collection("connected_users").update(
|
||||
{ _id: coll },
|
||||
{ $addToSet: { users: guid } },
|
||||
{ upsert: true },
|
||||
function(err, updated) {
|
||||
if (updated.nModified > 0 || updated.upserted != undefined) {
|
||||
db.collection("connected_users").find({ _id: coll }, function(
|
||||
err,
|
||||
new_doc
|
||||
) {
|
||||
db.collection("frontpage_lists").update(
|
||||
{ _id: coll },
|
||||
{ $set: { viewers: new_doc[0].users.length } },
|
||||
function() {
|
||||
if (
|
||||
new_doc[0].users == undefined ||
|
||||
new_doc[0].users.length == undefined
|
||||
) {
|
||||
io.to(coll).emit("viewers", 1);
|
||||
} else {
|
||||
io.to(coll).emit("viewers", new_doc[0].users.length);
|
||||
}
|
||||
Chat.namechange(
|
||||
{ initial: true, first: true, channel: coll },
|
||||
guid,
|
||||
socket,
|
||||
false,
|
||||
function(enabled) {
|
||||
db.collection("user_names").find({ guid: guid }, function(
|
||||
err,
|
||||
docs
|
||||
) {
|
||||
if (docs.length == 1) {
|
||||
var icon = "";
|
||||
if (docs[0].icon != undefined) icon = docs[0].icon;
|
||||
db.collection("user_names").update(
|
||||
{ guid: guid },
|
||||
{ $addToSet: { channels: coll } },
|
||||
function(err, doc) {}
|
||||
);
|
||||
if (enabled) {
|
||||
socket.broadcast.to(coll).emit("chat", {
|
||||
from: docs[0].name,
|
||||
icon: icon,
|
||||
msg: " joined"
|
||||
});
|
||||
}
|
||||
} else if (docs.length == 0) {
|
||||
//console.log("User doesn't have a name for some reason.");
|
||||
//console.log("guid", guid);
|
||||
//console.log("channel", coll);
|
||||
//console.log("Trying to get a chat-name");
|
||||
Chat.get_name(guid, {
|
||||
announce: false,
|
||||
socket: socket,
|
||||
channel: coll
|
||||
});
|
||||
}
|
||||
});
|
||||
db.collection("connected_users").update(
|
||||
{ _id: "total_users" },
|
||||
{ $addToSet: { total_users: guid + coll } },
|
||||
function(err, docs) {
|
||||
if (
|
||||
callback != undefined &&
|
||||
typeof callback == "function"
|
||||
)
|
||||
callback();
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
} else {
|
||||
db.collection("connected_users").find({ _id: coll }, function(
|
||||
err,
|
||||
new_doc
|
||||
) {
|
||||
io.to(coll).emit("viewers", new_doc[0].users.length);
|
||||
});
|
||||
if (callback != undefined && typeof callback == "function")
|
||||
callback();
|
||||
}
|
||||
}
|
||||
);
|
||||
} else {
|
||||
if (offline) {
|
||||
db.collection("connected_users").update(
|
||||
{ _id: "offline_users" },
|
||||
{ $addToSet: { users: guid } },
|
||||
function(err, docs) {}
|
||||
);
|
||||
} else {
|
||||
db.collection("connected_users").update(
|
||||
{ _id: coll },
|
||||
{ $addToSet: { users: guid } },
|
||||
function(err, docs) {}
|
||||
);
|
||||
}
|
||||
//
|
||||
if (coll != undefined && coll != "") {
|
||||
db.collection("connected_users").update(
|
||||
{ _id: "total_users" },
|
||||
{ $addToSet: { total_users: guid + coll } },
|
||||
function(err, docs) {}
|
||||
);
|
||||
}
|
||||
if (callback != undefined && typeof callback == "function") callback();
|
||||
}
|
||||
}
|
||||
|
||||
function rndName(seed, len) {
|
||||
var vowels = ["a", "e", "i", "o", "u"];
|
||||
consts = [
|
||||
"b",
|
||||
"c",
|
||||
"d",
|
||||
"f",
|
||||
"g",
|
||||
"h",
|
||||
"j",
|
||||
"k",
|
||||
"l",
|
||||
"m",
|
||||
"n",
|
||||
"p",
|
||||
"r",
|
||||
"s",
|
||||
"t",
|
||||
"v",
|
||||
"w",
|
||||
"x",
|
||||
"y"
|
||||
];
|
||||
len = Math.floor(len);
|
||||
word = "";
|
||||
is_vowel = false;
|
||||
var arr;
|
||||
try {
|
||||
for (var i = 0; i < len; i++) {
|
||||
if (is_vowel) arr = vowels;
|
||||
else arr = consts;
|
||||
is_vowel = !is_vowel;
|
||||
word += arr[(seed[i % seed.length].charCodeAt() + i) % (arr.length - 1)];
|
||||
}
|
||||
} catch (e) {
|
||||
return rndName(uniqid.time().toLowerCase(), len);
|
||||
}
|
||||
return word;
|
||||
}
|
||||
|
||||
function removeEmojis(string) {
|
||||
//https://stackoverflow.com/a/41164278/4266467
|
||||
var regex = /(?:[\u2700-\u27bf]|(?:\ud83c[\udde6-\uddff]){2}|[\ud800-\udbff][\udc00-\udfff]|[\u0023-\u0039]\ufe0f?\u20e3|\u3299|\u3297|\u303d|\u3030|\u24c2|\ud83c[\udd70-\udd71]|\ud83c[\udd7e-\udd7f]|\ud83c\udd8e|\ud83c[\udd91-\udd9a]|\ud83c[\udde6-\uddff]|\ud83c[\ude01-\ude02]|\ud83c\ude1a|\ud83c\ude2f|\ud83c[\ude32-\ude3a]|\ud83c[\ude50-\ude51]|\u203c|\u2049|[\u25aa-\u25ab]|\u25b6|\u25c0|[\u25fb-\u25fe]|\u00a9|\u00ae|\u2122|\u2139|\ud83c\udc04|[\u2600-\u26FF]|\u2b05|\u2b06|\u2b07|\u2b1b|\u2b1c|\u2b50|\u2b55|\u231a|\u231b|\u2328|\u23cf|[\u23e9-\u23f3]|[\u23f8-\u23fa]|\ud83c\udccf|\u2934|\u2935|[\u2190-\u21ff])/g;
|
||||
return string.replace(regex, "");
|
||||
}
|
||||
|
||||
function decrypt_string(pw) {
|
||||
try {
|
||||
return Buffer.from(pw, "base64").toString("ascii");
|
||||
} catch (e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
function get_time() {
|
||||
var d = new Date();
|
||||
var time = Math.floor(d.getTime() / 1000);
|
||||
return time;
|
||||
}
|
||||
|
||||
function contains(a, obj) {
|
||||
try {
|
||||
var i = a.length;
|
||||
while (i--) {
|
||||
if (a[i] === obj) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function hash_pass(adminpass, hex) {
|
||||
if (adminpass == undefined || adminpass == "") return "";
|
||||
if (hex)
|
||||
return crypto
|
||||
.createHash("sha256")
|
||||
.update(adminpass)
|
||||
.digest("hex");
|
||||
return crypto
|
||||
.createHash("sha256")
|
||||
.update(adminpass)
|
||||
.digest("base64");
|
||||
}
|
||||
|
||||
function setSessionAdminPass(id, adminpass, list, callback) {
|
||||
try {
|
||||
if (id == "empty" || id == undefined) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
||||
connected_db
|
||||
.collection(id)
|
||||
.update(
|
||||
{ _id: list },
|
||||
{ $set: { adminpass: hash_pass(decrypt_string(adminpass), true) } },
|
||||
{ upsert: true },
|
||||
function(e, d) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
);
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
function setSessionChatPass(id, name, pass, callback) {
|
||||
try {
|
||||
if (id == "empty" || id == undefined) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
connected_db
|
||||
.collection(id)
|
||||
.update(
|
||||
{ _id: "_chat_" },
|
||||
{ $set: { password: pass, name: name } },
|
||||
{ upsert: true },
|
||||
function(e) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
);
|
||||
} catch (e) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function getSessionChatPass(id, callback) {
|
||||
try {
|
||||
if (id == "empty" || id == undefined) {
|
||||
callback("", "", false);
|
||||
return;
|
||||
}
|
||||
|
||||
connected_db.collection(id).find({ _id: "_chat_" }, function(e, d) {
|
||||
if (d.length > 0) {
|
||||
var name = "";
|
||||
var pass = "";
|
||||
if (d[0].name != undefined) name = d[0].name;
|
||||
if (d[0].password != undefined) pass = d[0].password;
|
||||
callback(name, pass);
|
||||
return;
|
||||
} else {
|
||||
callback("", "", false);
|
||||
return;
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function setChromecastHost(id, other_id, list, callback) {
|
||||
try {
|
||||
if (
|
||||
id == "empty" ||
|
||||
id == undefined ||
|
||||
other_id == "empty" ||
|
||||
other_id == undefined
|
||||
) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
connected_db
|
||||
.collection(id)
|
||||
.update(
|
||||
{ _id: list },
|
||||
{ chromecast: true, id: other_id },
|
||||
{ upsert: true },
|
||||
function(e, docs) {
|
||||
callback(true);
|
||||
return;
|
||||
}
|
||||
);
|
||||
} catch (e) {
|
||||
callback(false);
|
||||
}
|
||||
}
|
||||
|
||||
function setSessionUserPass(id, userpass, list, callback) {
|
||||
try {
|
||||
if (id == "empty" || id == undefined || userpass == undefined) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
||||
connected_db
|
||||
.collection(id)
|
||||
.update(
|
||||
{ _id: list },
|
||||
{ $set: { userpass: userpass } },
|
||||
{ upsert: true },
|
||||
function(e, d) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
);
|
||||
} catch (e) {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
function getSessionAdminUser(id, list, callback) {
|
||||
try {
|
||||
if (id == "empty" || id == undefined) {
|
||||
callback("", "", false);
|
||||
return;
|
||||
}
|
||||
connected_db.collection(id).find({ _id: list }, function(e, d) {
|
||||
var userpass = "";
|
||||
var adminpass = "";
|
||||
if (d.length > 0) {
|
||||
if (d[0].hasOwnProperty("chromecast") && d[0].chromecast) {
|
||||
getSessionAdminUser(d[0].id, list, callback);
|
||||
} else {
|
||||
if (d[0].userpass != undefined) userpass = d[0].userpass;
|
||||
if (d[0].adminpass != undefined) adminpass = d[0].adminpass;
|
||||
callback(userpass, adminpass, true);
|
||||
}
|
||||
} else {
|
||||
callback(userpass, adminpass, true);
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
callback("", "", false);
|
||||
}
|
||||
}
|
||||
|
||||
function removeSessionChatPass(id, callback) {
|
||||
if (id == "empty" || id == undefined) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
connected_db.collection(id).remove({ _id: "_chat_" }, function() {
|
||||
callback();
|
||||
return;
|
||||
});
|
||||
}
|
||||
|
||||
function removeSessionAdminPass(id, channel, callback) {
|
||||
if (id == "empty" || id == undefined) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
connected_db
|
||||
.collection(id)
|
||||
.update({ _id: channel }, { $set: { adminpass: "" } }, function() {
|
||||
callback();
|
||||
return;
|
||||
});
|
||||
}
|
||||
|
||||
function remove_from_chat_channel(coll, guid) {
|
||||
db.collection("user_names").update(
|
||||
{ guid: guid },
|
||||
{ $pull: { channels: coll } },
|
||||
function(err, docs) {}
|
||||
);
|
||||
}
|
||||
|
||||
function left_channel(coll, guid, short_id, in_list, socket, change, caller) {
|
||||
if (!coll) {
|
||||
if (!change) {
|
||||
remove_name_from_db(guid, coll);
|
||||
} else {
|
||||
remove_from_chat_channel(coll, guid);
|
||||
}
|
||||
return;
|
||||
}
|
||||
//coll = coll.replace(/ /g,'');
|
||||
db.collection("connected_users").update(
|
||||
{ _id: coll },
|
||||
{ $pull: { users: guid } },
|
||||
function(err, updated) {
|
||||
if (updated.nModified > 0) {
|
||||
db.collection("connected_users").update(
|
||||
{ _id: "total_users" },
|
||||
{ $pull: { total_users: guid + coll } },
|
||||
function(err, updated) {}
|
||||
);
|
||||
db.collection("connected_users").find({ _id: coll }, function(
|
||||
err,
|
||||
new_doc
|
||||
) {
|
||||
db.collection("frontpage_lists").update(
|
||||
{ _id: coll, viewers: { $gt: 0 } },
|
||||
{ $inc: { viewers: -1 } },
|
||||
function(err, doc) {
|
||||
db.collection("user_names").find({ guid: guid }, function(
|
||||
err,
|
||||
docs
|
||||
) {
|
||||
if (docs.length == 1) {
|
||||
var icon = "";
|
||||
if (docs[0].icon != undefined) icon = docs[0].icon;
|
||||
io.to(coll).emit("chat", {
|
||||
from: docs[0].name,
|
||||
icon: icon,
|
||||
msg: " left"
|
||||
});
|
||||
}
|
||||
});
|
||||
io.to(coll).emit("viewers", new_doc[0].users.length);
|
||||
socket.leave(coll);
|
||||
if (!change) {
|
||||
remove_name_from_db(guid, coll);
|
||||
} else {
|
||||
remove_from_chat_channel(coll, guid);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
} else {
|
||||
db.collection("connected_users").update(
|
||||
{ _id: "offline_users" },
|
||||
{ $pull: { users: guid } },
|
||||
function(err, updated) {
|
||||
//if(updated.nModified > 0) {
|
||||
db.collection("connected_users").update(
|
||||
{ _id: "total_users" },
|
||||
{ $pull: { total_users: guid + coll } },
|
||||
function(err, updated) {}
|
||||
);
|
||||
if (!change) {
|
||||
remove_name_from_db(guid, coll);
|
||||
} else {
|
||||
remove_from_chat_channel(coll, guid);
|
||||
}
|
||||
//}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
remove_unique_id(short_id);
|
||||
}
|
||||
|
||||
function checkTimeout(
|
||||
type,
|
||||
timeout,
|
||||
channel,
|
||||
guid,
|
||||
conf_pass,
|
||||
this_pass,
|
||||
socket,
|
||||
callback,
|
||||
error_message,
|
||||
error_callback
|
||||
) {
|
||||
if (conf_pass != "" && conf_pass == this_pass) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
db.collection("timeout_api").find(
|
||||
{
|
||||
type: type,
|
||||
guid: guid
|
||||
},
|
||||
function(err, docs) {
|
||||
if (docs.length > 0) {
|
||||
var date = new Date(docs[0].createdAt);
|
||||
date.setSeconds(date.getSeconds() + timeout);
|
||||
var now = new Date();
|
||||
|
||||
var retry_in = (date.getTime() - now.getTime()) / 1000;
|
||||
if (retry_in > 0) {
|
||||
if (typeof error_callback == "function") {
|
||||
error_callback();
|
||||
} else if (error_message) {
|
||||
var sOrNot =
|
||||
Math.ceil(retry_in) > 1 || Math.ceil(retry_in) == 0 ? "s" : "";
|
||||
socket.emit(
|
||||
"toast",
|
||||
error_message + Math.ceil(retry_in) + " second" + sOrNot + "."
|
||||
);
|
||||
} else {
|
||||
socket.emit("toast", "wait_longer");
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
var now_date = new Date();
|
||||
db.collection("timeout_api").update(
|
||||
{ type: type, guid: guid },
|
||||
{
|
||||
$set: {
|
||||
createdAt: now_date,
|
||||
type: type,
|
||||
guid: guid
|
||||
}
|
||||
},
|
||||
{ upsert: true },
|
||||
function(err, docs) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
module.exports.checkTimeout = checkTimeout;
|
||||
module.exports.left_channel = left_channel;
|
||||
module.exports.setChromecastHost = setChromecastHost;
|
||||
module.exports.decodeChannelName = decodeChannelName;
|
||||
module.exports.encodeChannelName = encodeChannelName;
|
||||
module.exports.isUrl = isUrl;
|
||||
module.exports.removeEmojis = removeEmojis;
|
||||
module.exports.getSessionChatPass = getSessionChatPass;
|
||||
module.exports.setSessionChatPass = setSessionChatPass;
|
||||
module.exports.removeSessionAdminPass = removeSessionAdminPass;
|
||||
module.exports.removeSessionChatPass = removeSessionChatPass;
|
||||
module.exports.setSessionAdminPass = setSessionAdminPass;
|
||||
module.exports.setSessionUserPass = setSessionUserPass;
|
||||
module.exports.getSessionAdminUser = getSessionAdminUser;
|
||||
module.exports.getSession = getSession;
|
||||
module.exports.generate_channel_name = generate_channel_name;
|
||||
module.exports.remove_unique_id = remove_unique_id;
|
||||
module.exports.remove_name_from_db = remove_name_from_db;
|
||||
module.exports.remove_from_array = remove_from_array;
|
||||
module.exports.get_short_id = get_short_id;
|
||||
module.exports.check_inlist = check_inlist;
|
||||
module.exports.rndName = rndName;
|
||||
module.exports.decrypt_string = decrypt_string;
|
||||
module.exports.get_time = get_time;
|
||||
module.exports.contains = contains;
|
||||
module.exports.hash_pass = hash_pass;
|
||||
946
server/handlers/io.js
Normal file
@@ -0,0 +1,946 @@
|
||||
var cookieParser = require("cookie-parser");
|
||||
var cookie = require("cookie");
|
||||
|
||||
var Functions = require(pathThumbnails + "/handlers/functions.js");
|
||||
var ListChange = require(pathThumbnails + "/handlers/list_change.js");
|
||||
var Chat = require(pathThumbnails + "/handlers/chat.js");
|
||||
var List = require(pathThumbnails + "/handlers/list.js");
|
||||
var Suggestions = require(pathThumbnails + "/handlers/suggestions.js");
|
||||
var ListSettings = require(pathThumbnails + "/handlers/list_settings.js");
|
||||
var Frontpage = require(pathThumbnails + "/handlers/frontpage.js");
|
||||
var Search = require(pathThumbnails + "/handlers/search.js");
|
||||
var crypto = require("crypto");
|
||||
var Filter = require("bad-words");
|
||||
var filter = new Filter({ placeHolder: "x" });
|
||||
/*var filter = {
|
||||
clean: function(str) {
|
||||
return str;
|
||||
}
|
||||
}*/
|
||||
var db = require(pathThumbnails + "/handlers/db.js");
|
||||
|
||||
module.exports = function() {
|
||||
io.on("connection", function(socket) {
|
||||
try {
|
||||
var parsedCookies = cookie.parse(socket.handshake.headers.cookie);
|
||||
socket.cookie_id = parsedCookies["_uI"];
|
||||
//return socket.guid;
|
||||
} catch (e) {
|
||||
socket.cookie_id = "empty";
|
||||
}
|
||||
socket.zoff_id = socket.id;
|
||||
socket.emit("get_list");
|
||||
var guid = socket.cookie_id;
|
||||
if (guid == "empty" || guid == null || guid == undefined)
|
||||
guid = Functions.hash_pass(
|
||||
socket.handshake.headers["user-agent"] +
|
||||
socket.handshake.address +
|
||||
socket.handshake.headers["accept-language"]
|
||||
);
|
||||
|
||||
socket.guid = guid;
|
||||
socket.on("close", function() {});
|
||||
|
||||
socket.on("pinging", function() {
|
||||
socket.emit("ok");
|
||||
});
|
||||
|
||||
var ping_timeout;
|
||||
var socketid = socket.zoff_id;
|
||||
var coll;
|
||||
var in_list = false;
|
||||
var name = "";
|
||||
var short_id;
|
||||
Chat.get_name(guid, { announce: false, socket: socket });
|
||||
var offline = false;
|
||||
var chromecast_object = false;
|
||||
|
||||
socket.emit("guid", guid);
|
||||
|
||||
socket.on("self_ping", function(msg) {
|
||||
var channel = msg.channel;
|
||||
if (channel.indexOf("?") > -1) {
|
||||
channel = channel.substring(0, channel.indexOf("?"));
|
||||
}
|
||||
if (msg.hasOwnProperty("channel")) {
|
||||
msg.channel = Functions.encodeChannelName(msg.channel);
|
||||
}
|
||||
//channel = channel.replace(/ /g,'');
|
||||
if (offline) {
|
||||
db.collection("connected_users").update(
|
||||
{ _id: "offline_users" },
|
||||
{ $addToSet: { users: guid } },
|
||||
{ upsert: true },
|
||||
function(err, docs) {}
|
||||
);
|
||||
} else {
|
||||
db.collection("connected_users").update(
|
||||
{ _id: channel },
|
||||
{ $addToSet: { users: guid } },
|
||||
{ upsert: true },
|
||||
function(err, docs) {
|
||||
db.collection("frontpage_lists").update(
|
||||
{ _id: channel },
|
||||
{ $inc: { viewers: 1 } },
|
||||
{ upsert: true },
|
||||
function() {}
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
if (channel != "" && channel != undefined) {
|
||||
db.collection("connected_users").update(
|
||||
{ _id: "total_users" },
|
||||
{ $addToSet: { total_users: guid + channel } },
|
||||
{ upsert: true },
|
||||
function(err, docs) {}
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
socket.on("logout", function() {
|
||||
Functions.removeSessionAdminPass(
|
||||
Functions.getSession(socket),
|
||||
coll,
|
||||
function() {}
|
||||
);
|
||||
});
|
||||
|
||||
socket.on("next_song", function(obj) {
|
||||
if (obj == undefined || !obj.hasOwnProperty("channel")) return;
|
||||
db.collection(obj.channel + "_settings").find(function(e, docs) {
|
||||
if (docs.length == 0) return;
|
||||
var pass = "";
|
||||
if (obj.hasOwnProperty("pass")) {
|
||||
pass = crypto
|
||||
.createHash("sha256")
|
||||
.update(Functions.decrypt_string(obj.pass))
|
||||
.digest("base64");
|
||||
}
|
||||
if (
|
||||
docs.length > 0 &&
|
||||
(docs[0].userpass == undefined ||
|
||||
docs[0].userpass == "" ||
|
||||
docs[0].userpass == pass)
|
||||
) {
|
||||
List.getNextSong(obj.channel, socket);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
socket.on("chromecast", function(msg) {
|
||||
try {
|
||||
if (
|
||||
typeof msg == "object" &&
|
||||
msg.hasOwnProperty("guid") &&
|
||||
msg.hasOwnProperty("socket_id") &&
|
||||
msg.hasOwnProperty("channel") &&
|
||||
typeof msg.guid == "string" &&
|
||||
typeof msg.channel == "string" &&
|
||||
typeof msg.socket_id == "string" &&
|
||||
msg.channel != ""
|
||||
) {
|
||||
if (msg.hasOwnProperty("channel")) {
|
||||
msg.channel = Functions.encodeChannelName(msg.channel);
|
||||
}
|
||||
db.collection("connected_users").find({ _id: msg.channel }, function(
|
||||
err,
|
||||
connected_users_channel
|
||||
) {
|
||||
if (
|
||||
connected_users_channel.length > 0 &&
|
||||
connected_users_channel[0].users.indexOf(msg.guid) > -1
|
||||
) {
|
||||
coll = msg.channel.toLowerCase(); //.replace(/ /g,'');
|
||||
coll = Functions.removeEmojis(coll).toLowerCase();
|
||||
//coll = filter.clean(coll);
|
||||
if (coll.indexOf("?") > -1) {
|
||||
coll = coll.substring(0, coll.indexOf("?"));
|
||||
}
|
||||
Functions.setChromecastHost(
|
||||
socket.cookie_id,
|
||||
msg.socket_id,
|
||||
msg.channel,
|
||||
function(results) {}
|
||||
);
|
||||
//socket.cookie_id = msg.guid;
|
||||
guid = msg.guid;
|
||||
socketid = msg.socket_id;
|
||||
socket.zoff_id = socketid;
|
||||
|
||||
in_list = true;
|
||||
chromecast_object = true;
|
||||
socket.join(coll);
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
socket.on("get_id", function() {
|
||||
socket.emit("id_chromecast", {
|
||||
cookie_id: Functions.getSession(socket),
|
||||
guid: guid
|
||||
});
|
||||
});
|
||||
|
||||
socket.on("error_video", function(msg) {
|
||||
try {
|
||||
msg.channel = Functions.encodeChannelName(msg.channel);
|
||||
var _list = msg.channel; //.replace(/ /g,'');
|
||||
if (_list.length == 0) return;
|
||||
if (_list.indexOf("?") > -1) {
|
||||
_list = _list.substring(0, _list.indexOf("?"));
|
||||
msg.channel = _list;
|
||||
}
|
||||
coll = Functions.removeEmojis(_list).toLowerCase();
|
||||
//coll = coll.replace(/_/g, "");
|
||||
|
||||
//coll = filter.clean(coll);
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
if (msg.hasOwnProperty("channel")) {
|
||||
msg.channel = Functions.encodeChannelName(msg.channel);
|
||||
}
|
||||
Search.check_error_video(msg, coll);
|
||||
});
|
||||
|
||||
socket.on("get_spread", function() {
|
||||
db.collection("connected_users").find({ _id: "total_users" }, function(
|
||||
err,
|
||||
tot
|
||||
) {
|
||||
db.collection("connected_users").find(
|
||||
{ _id: "offline_users" },
|
||||
function(err, off) {
|
||||
db.collection("connected_users").find(
|
||||
{ _id: { $ne: "total_users" }, _id: { $ne: "offline_users" } },
|
||||
function(err, users_list) {
|
||||
if (tot.length > 0 && off.length == 0) {
|
||||
socket.emit("spread_listeners", {
|
||||
offline: 0,
|
||||
total: tot[0].total_users.length,
|
||||
online_users: users_list
|
||||
});
|
||||
} else if (tot.length > 0 && off.length > 0) {
|
||||
socket.emit("spread_listeners", {
|
||||
offline: off[0].users.length,
|
||||
total: tot[0].total_users.length,
|
||||
online_users: users_list
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
socket.on("suggest_thumbnail", function(msg) {
|
||||
if (msg.hasOwnProperty("channel") && msg.channel.indexOf("?") > -1) {
|
||||
var _list = msg.channel.substring(0, msg.channel.indexOf("?"));
|
||||
msg.channel = _list;
|
||||
}
|
||||
if (msg.hasOwnProperty("channel")) {
|
||||
msg.channel = Functions.encodeChannelName(msg.channel);
|
||||
}
|
||||
Suggestions.thumbnail(msg, coll, guid, offline, socket);
|
||||
});
|
||||
|
||||
socket.on("suggest_description", function(msg) {
|
||||
if (msg.hasOwnProperty("channel") && msg.channel.indexOf("?") > -1) {
|
||||
var _list = msg.channel.substring(0, msg.channel.indexOf("?"));
|
||||
msg.channel = _list;
|
||||
}
|
||||
if (msg.hasOwnProperty("channel")) {
|
||||
msg.channel = Functions.encodeChannelName(msg.channel);
|
||||
}
|
||||
Suggestions.description(msg, coll, guid, offline, socket);
|
||||
});
|
||||
|
||||
socket.on("suggest_rules", function(msg) {
|
||||
if (msg.hasOwnProperty("channel") && msg.channel.indexOf("?") > -1) {
|
||||
var _list = msg.channel.substring(0, msg.channel.indexOf("?"));
|
||||
msg.channel = _list;
|
||||
}
|
||||
if (msg.hasOwnProperty("channel")) {
|
||||
msg.channel = Functions.encodeChannelName(msg.channel);
|
||||
}
|
||||
Suggestions.rules(msg, coll, guid, offline, socket);
|
||||
});
|
||||
|
||||
socket.on("namechange", function(msg) {
|
||||
if (msg.hasOwnProperty("channel") && msg.channel.indexOf("?") > -1) {
|
||||
var _list = msg.channel.substring(0, msg.channel.indexOf("?"));
|
||||
msg.channel = _list;
|
||||
}
|
||||
if (msg.hasOwnProperty("channel")) {
|
||||
msg.channel = Functions.encodeChannelName(msg.channel);
|
||||
}
|
||||
Chat.namechange(msg, guid, socket);
|
||||
});
|
||||
|
||||
socket.on("removename", function(msg) {
|
||||
if (msg.hasOwnProperty("channel") && msg.channel.indexOf("?") > -1) {
|
||||
var _list = msg.channel.substring(0, msg.channel.indexOf("?"));
|
||||
msg.channel = _list;
|
||||
}
|
||||
if (msg.hasOwnProperty("channel")) {
|
||||
msg.channel = Functions.encodeChannelName(msg.channel);
|
||||
}
|
||||
if (typeof msg != "object" || !msg.hasOwnProperty("channel")) {
|
||||
var result = {
|
||||
channel: {
|
||||
expected: "string",
|
||||
got: msg.hasOwnProperty("channel") ? typeof msg.channel : undefined
|
||||
}
|
||||
};
|
||||
socket.emit("update_required", result);
|
||||
return;
|
||||
}
|
||||
Chat.removename(guid, msg.channel, socket);
|
||||
});
|
||||
|
||||
socket.on("offline", function(msg) {
|
||||
if (msg.hasOwnProperty("channel") && msg.channel.indexOf("?") > -1) {
|
||||
var _list = msg.channel.substring(0, msg.channel.indexOf("?"));
|
||||
msg.channel = _list;
|
||||
}
|
||||
if (msg.hasOwnProperty("channel")) {
|
||||
msg.channel = Functions.encodeChannelName(msg.channel);
|
||||
}
|
||||
if (
|
||||
!msg.hasOwnProperty("status") ||
|
||||
!msg.hasOwnProperty("channel") ||
|
||||
typeof msg.status != "boolean" ||
|
||||
typeof msg.channel != "string"
|
||||
) {
|
||||
var result = {
|
||||
status: {
|
||||
expected: "boolean",
|
||||
got: msg.hasOwnProperty("status") ? typeof msg.status : undefined
|
||||
},
|
||||
channel: {
|
||||
expected: "string",
|
||||
got: msg.hasOwnProperty("channel") ? typeof msg.channel : undefined
|
||||
}
|
||||
};
|
||||
socket.emit("update_required", result);
|
||||
return;
|
||||
}
|
||||
var status = msg.status;
|
||||
var channel = msg.channel; //.replace(/ /g,'');
|
||||
if (status) {
|
||||
in_list = false;
|
||||
offline = true;
|
||||
if (channel != "") coll = channel;
|
||||
if (coll !== undefined) {
|
||||
coll = Functions.removeEmojis(coll).toLowerCase();
|
||||
//coll = filter.clean(coll);
|
||||
db.collection("connected_users").findAndModify(
|
||||
{
|
||||
query: { _id: coll },
|
||||
update: { $pull: { users: guid } },
|
||||
upsert: true
|
||||
},
|
||||
function(err, updated, d) {
|
||||
if (d.n == 1) {
|
||||
var num = 0;
|
||||
if (updated && updated.users) {
|
||||
num = updated.users.length;
|
||||
}
|
||||
io.to(coll).emit("viewers", num);
|
||||
db.collection("frontpage_lists").update(
|
||||
{ _id: coll, viewers: { $gt: 0 } },
|
||||
{ $inc: { viewers: -1 } },
|
||||
function(err, docs) {}
|
||||
);
|
||||
db.collection("connected_users").update(
|
||||
{ _id: "total_users" },
|
||||
{ $pull: { total_users: guid + coll } },
|
||||
function(err, docs) {
|
||||
db.collection("connected_users").update(
|
||||
{ _id: "offline_users" },
|
||||
{ $addToSet: { users: guid } },
|
||||
{ upsert: true },
|
||||
function(err, docs) {
|
||||
if (
|
||||
docs.nModified == 1 &&
|
||||
(coll != undefined && coll != "")
|
||||
) {
|
||||
db.collection("connected_users").update(
|
||||
{ _id: "total_users" },
|
||||
{ $addToSet: { total_users: guid + coll } },
|
||||
function(err, docs) {}
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
Functions.remove_name_from_db(guid, coll);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
Functions.remove_unique_id(short_id);
|
||||
} else {
|
||||
offline = false;
|
||||
db.collection("connected_users").update(
|
||||
{ _id: "offline_users" },
|
||||
{ $pull: { users: guid } },
|
||||
function(err, docs) {
|
||||
Functions.check_inlist(
|
||||
coll,
|
||||
guid,
|
||||
socket,
|
||||
offline,
|
||||
undefined,
|
||||
"place 3"
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
socket.on("get_history", function(msg) {
|
||||
if (msg.hasOwnProperty("channel") && msg.channel.indexOf("?") > -1) {
|
||||
var _list = msg.channel.substring(0, msg.channel.indexOf("?"));
|
||||
msg.channel = _list;
|
||||
}
|
||||
if (msg.hasOwnProperty("channel")) {
|
||||
msg.channel = Functions.encodeChannelName(msg.channel);
|
||||
}
|
||||
if (
|
||||
!msg.hasOwnProperty("channel") ||
|
||||
!msg.hasOwnProperty("all") ||
|
||||
typeof msg.channel != "string" ||
|
||||
typeof msg.all != "boolean"
|
||||
) {
|
||||
var result = {
|
||||
all: {
|
||||
expected: "boolean",
|
||||
got: msg.hasOwnProperty("all") ? typeof msg.all : undefined
|
||||
},
|
||||
channel: {
|
||||
expected: "string",
|
||||
got: msg.hasOwnProperty("channel") ? typeof msg.channel : undefined
|
||||
},
|
||||
pass: {
|
||||
expected: "string",
|
||||
got: msg.hasOwnProperty("pass") ? typeof msg.pass : undefined
|
||||
}
|
||||
};
|
||||
socket.emit("update_required", result);
|
||||
return;
|
||||
}
|
||||
Chat.get_history(msg.channel, msg.all, socket);
|
||||
});
|
||||
|
||||
socket.on("chat", function(msg) {
|
||||
if (msg.hasOwnProperty("channel") && msg.channel.indexOf("?") > -1) {
|
||||
var _list = msg.channel.substring(0, msg.channel.indexOf("?"));
|
||||
msg.channel = _list;
|
||||
}
|
||||
if (msg.hasOwnProperty("channel")) {
|
||||
msg.channel = Functions.encodeChannelName(msg.channel);
|
||||
}
|
||||
Chat.chat(msg, guid, offline, socket);
|
||||
});
|
||||
|
||||
socket.on("all,chat", function(data) {
|
||||
if (data.hasOwnProperty("channel") && data.channel.indexOf("?") > -1) {
|
||||
var _list = data.channel.substring(0, data.channel.indexOf("?"));
|
||||
data.channel = _list;
|
||||
}
|
||||
if (data.hasOwnProperty("channel")) {
|
||||
data.channel = Functions.encodeChannelName(data.channel);
|
||||
}
|
||||
Chat.all_chat(data, guid, offline, socket);
|
||||
});
|
||||
|
||||
socket.on("frontpage_lists", function(msg) {
|
||||
if (msg.hasOwnProperty("channel") && msg.channel.indexOf("?") > -1) {
|
||||
var _list = msg.channel.substring(0, msg.channel.indexOf("?"));
|
||||
msg.channel = _list;
|
||||
}
|
||||
if (msg.hasOwnProperty("channel")) {
|
||||
msg.channel = Functions.encodeChannelName(msg.channel);
|
||||
}
|
||||
Frontpage.frontpage_lists(msg, socket);
|
||||
});
|
||||
|
||||
socket.on("import_zoff", function(msg) {
|
||||
if (msg.hasOwnProperty("channel") && msg.channel.indexOf("?") > -1) {
|
||||
var _list = msg.channel.substring(0, msg.channel.indexOf("?"));
|
||||
msg.channel = _list;
|
||||
}
|
||||
if (msg.hasOwnProperty("channel")) {
|
||||
msg.channel = Functions.encodeChannelName(msg.channel);
|
||||
}
|
||||
ListChange.addFromOtherList(msg, guid, offline, socket);
|
||||
});
|
||||
|
||||
socket.on("now_playing", function(list, fn) {
|
||||
List.now_playing(list, fn, socket);
|
||||
});
|
||||
|
||||
socket.on("id", function(arr) {
|
||||
if (arr.hasOwnProperty("channel") && arr.channel.indexOf("?") > -1) {
|
||||
var _list = arr.channel.substring(0, arr.channel.indexOf("?"));
|
||||
arr.channel = _list;
|
||||
}
|
||||
if (arr.hasOwnProperty("channel")) {
|
||||
arr.channel = Functions.encodeChannelName(arr.channel);
|
||||
}
|
||||
if (typeof arr == "object")
|
||||
io.to(arr.id).emit(arr.id.toLowerCase(), {
|
||||
type: arr.type,
|
||||
value: arr.value
|
||||
});
|
||||
});
|
||||
|
||||
socket.on("join_silent", function(msg) {
|
||||
if (msg.hasOwnProperty("channel") && msg.channel.indexOf("?") > -1) {
|
||||
var _list = msg.channel.substring(0, msg.channel.indexOf("?"));
|
||||
msg.channel = _list;
|
||||
}
|
||||
if (msg.hasOwnProperty("channel")) {
|
||||
msg.channel = Functions.encodeChannelName(msg.channel);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
List.join_silent(msg, socket);
|
||||
});
|
||||
|
||||
socket.on("list", function(msg) {
|
||||
if (msg.hasOwnProperty("channel") && msg.channel.indexOf("?") > -1) {
|
||||
var _list = msg.channel.substring(0, msg.channel.indexOf("?"));
|
||||
msg.channel = _list;
|
||||
}
|
||||
if (msg.hasOwnProperty("channel")) {
|
||||
msg.channel = Functions.encodeChannelName(msg.channel);
|
||||
}
|
||||
try {
|
||||
//var _list = msg.channel.replace(/ /g,'');
|
||||
var _list = msg.channel;
|
||||
if (_list.length == 0) return;
|
||||
if (_list.indexOf("?") > -1) {
|
||||
_list = _list.substring(0, _list.indexOf("?"));
|
||||
msg.channel = _list;
|
||||
}
|
||||
coll = Functions.removeEmojis(_list).toLowerCase();
|
||||
//coll = coll.replace(/_/g, "");
|
||||
//
|
||||
//coll = filter.clean(coll);
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg.hasOwnProperty("offline") && msg.offline) {
|
||||
offline = true;
|
||||
}
|
||||
List.list(msg, guid, coll, offline, socket);
|
||||
Functions.get_short_id(socket);
|
||||
});
|
||||
|
||||
socket.on("end", function(obj) {
|
||||
if (obj.hasOwnProperty("channel") && obj.channel.indexOf("?") > -1) {
|
||||
var _list = obj.channel.substring(0, obj.channel.indexOf("?"));
|
||||
obj.channel = _list;
|
||||
}
|
||||
if (obj.hasOwnProperty("channel")) {
|
||||
obj.channel = Functions.encodeChannelName(obj.channel);
|
||||
try {
|
||||
coll = obj.channel.toLowerCase(); //.replace(/ /g,'');
|
||||
if (coll.length == 0) return;
|
||||
coll = Functions.removeEmojis(coll).toLowerCase();
|
||||
//coll = coll.replace(/_/g, "");
|
||||
|
||||
//coll = filter.clean(coll);
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
List.end(obj, coll, guid, offline, socket);
|
||||
});
|
||||
|
||||
socket.on("addPlaylist", function(arr) {
|
||||
if (arr.hasOwnProperty("channel") && arr.channel.indexOf("?") > -1) {
|
||||
var _list = arr.channel.substring(0, arr.channel.indexOf("?"));
|
||||
arr.channel = _list;
|
||||
}
|
||||
if (arr.hasOwnProperty("channel")) {
|
||||
arr.channel = Functions.encodeChannelName(arr.channel);
|
||||
}
|
||||
ListChange.addPlaylist(arr, guid, offline, socket);
|
||||
});
|
||||
|
||||
socket.on("add", function(arr) {
|
||||
if (arr.hasOwnProperty("list") && arr.list.indexOf("?") > -1) {
|
||||
var _list = arr.list.substring(0, arr.list.indexOf("?"));
|
||||
arr.list = _list;
|
||||
}
|
||||
if (arr.hasOwnProperty("list")) {
|
||||
arr.list = Functions.encodeChannelName(arr.list);
|
||||
}
|
||||
if (
|
||||
coll !== undefined &&
|
||||
((arr.hasOwnProperty("offsiteAdd") && !arr.offsiteAdd) ||
|
||||
!arr.hasOwnProperty("offsiteAdd"))
|
||||
) {
|
||||
try {
|
||||
coll = arr.list; //.replace(/ /g,'');
|
||||
if (coll.length == 0) return;
|
||||
coll = Functions.removeEmojis(coll).toLowerCase();
|
||||
//coll = coll.replace(/_/g, "");
|
||||
|
||||
//coll = filter.clean(coll);
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
} else if (arr.hasOwnProperty("offsiteAdd") && arr.offsiteAdd) {
|
||||
arr.list = Functions.removeEmojis(arr.list).toLowerCase();
|
||||
}
|
||||
ListChange.add_function(arr, coll, guid, offline, socket);
|
||||
});
|
||||
|
||||
socket.on("delete_all", function(msg) {
|
||||
try {
|
||||
if (msg.hasOwnProperty("channel") && msg.channel.indexOf("?") > -1) {
|
||||
var _list = msg.channel.substring(0, msg.channel.indexOf("?"));
|
||||
msg.channel = _list;
|
||||
}
|
||||
if (msg.hasOwnProperty("channel")) {
|
||||
msg.channel = Functions.encodeChannelName(msg.channel);
|
||||
}
|
||||
coll = msg.channel.toLowerCase(); //.replace(/ /g,'');
|
||||
if (coll.length == 0) return;
|
||||
coll = Functions.removeEmojis(coll).toLowerCase();
|
||||
//coll = coll.replace(/_/g, "");
|
||||
|
||||
//coll = filter.clean(coll);
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
|
||||
ListChange.delete_all(msg, coll, guid, offline, socket);
|
||||
});
|
||||
|
||||
socket.on("vote", function(msg) {
|
||||
if (msg.hasOwnProperty("channel") && msg.channel.indexOf("?") > -1) {
|
||||
var _list = msg.channel.substring(0, msg.channel.indexOf("?"));
|
||||
msg.channel = _list;
|
||||
}
|
||||
if (msg.hasOwnProperty("channel")) {
|
||||
msg.channel = Functions.encodeChannelName(msg.channel);
|
||||
}
|
||||
if (coll !== undefined) {
|
||||
try {
|
||||
coll = msg.channel.toLowerCase(); //.replace(/ /g,'');
|
||||
if (coll.length == 0) return;
|
||||
coll = Functions.removeEmojis(coll).toLowerCase();
|
||||
//coll = coll.replace(/_/g, "");
|
||||
|
||||
//coll = filter.clean(coll);
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
ListChange.voteUndecided(msg, coll, guid, offline, socket);
|
||||
});
|
||||
|
||||
socket.on("password", function(inp) {
|
||||
if (inp.hasOwnProperty("channel") && inp.channel.indexOf("?") > -1) {
|
||||
var _list = inp.channel.substring(0, inp.channel.indexOf("?"));
|
||||
inp.channel = _list;
|
||||
}
|
||||
if (inp.hasOwnProperty("channel")) {
|
||||
inp.channel = Functions.encodeChannelName(inp.channel);
|
||||
}
|
||||
//if(coll != undefined) coll.replace(/ /g,'');
|
||||
ListSettings.password(inp, coll, guid, offline, socket);
|
||||
});
|
||||
|
||||
socket.on("skip", function(list) {
|
||||
if (list.hasOwnProperty("channel") && list.channel.indexOf("?") > -1) {
|
||||
var _list = list.channel.substring(0, list.channel.indexOf("?"));
|
||||
list.channel = _list;
|
||||
coll = list.channel;
|
||||
}
|
||||
if (list.hasOwnProperty("channel")) {
|
||||
list.channel = Functions.encodeChannelName(list.channel);
|
||||
}
|
||||
//if(coll != undefined) coll.replace(/ /g,'');
|
||||
List.skip(list, guid, coll, offline, socket);
|
||||
});
|
||||
|
||||
socket.on("conf", function(conf) {
|
||||
if (conf.hasOwnProperty("channel") && conf.channel.indexOf("?") > -1) {
|
||||
var _list = conf.channel.substring(0, conf.channel.indexOf("?"));
|
||||
conf.channel = _list;
|
||||
coll = conf.channel;
|
||||
}
|
||||
if (conf.hasOwnProperty("channel")) {
|
||||
conf.channel = Functions.encodeChannelName(conf.channel);
|
||||
coll = conf.channel;
|
||||
}
|
||||
//if(coll != undefined) coll.replace(/ /g,'');
|
||||
ListSettings.conf_function(conf, coll, guid, offline, socket);
|
||||
});
|
||||
|
||||
socket.on("shuffle", function(msg) {
|
||||
if (msg.hasOwnProperty("channel") && msg.channel.indexOf("?") > -1) {
|
||||
var _list = msg.channel.substring(0, msg.channel.indexOf("?"));
|
||||
msg.channel = _list;
|
||||
}
|
||||
if (msg.hasOwnProperty("channel")) {
|
||||
msg.channel = Functions.encodeChannelName(msg.channel);
|
||||
}
|
||||
try {
|
||||
coll = msg.channel.toLowerCase(); //.replace(/ /g,'');
|
||||
if (coll.length == 0) return;
|
||||
coll = Functions.removeEmojis(coll).toLowerCase();
|
||||
//coll = coll.replace(/_/g, "");
|
||||
|
||||
//coll = filter.clean(coll);
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
|
||||
ListChange.shuffle(msg, coll, guid, offline, socket);
|
||||
});
|
||||
|
||||
socket.on("change_channel", function(obj) {
|
||||
if (obj == undefined && coll != undefined) {
|
||||
obj = {};
|
||||
obj.channel = coll;
|
||||
} else if (
|
||||
obj != undefined &&
|
||||
obj.hasOwnProperty("channel") &&
|
||||
obj.channel.indexOf("?") > -1
|
||||
) {
|
||||
var _list = obj.channel.substring(0, obj.channel.indexOf("?"));
|
||||
obj.channel = _list;
|
||||
}
|
||||
if (obj == undefined && coll == undefined) {
|
||||
return;
|
||||
}
|
||||
if (obj.hasOwnProperty("channel")) {
|
||||
obj.channel = Functions.encodeChannelName(obj.channel);
|
||||
}
|
||||
if (
|
||||
coll === undefined &&
|
||||
obj !== undefined &&
|
||||
obj.channel !== undefined
|
||||
) {
|
||||
try {
|
||||
coll = obj.channel.toLowerCase(); //.replace(/ /g,'');
|
||||
if (coll.length == 0) return;
|
||||
coll = Functions.removeEmojis(coll).toLowerCase();
|
||||
//coll = coll.replace(/_/g, "");
|
||||
|
||||
//coll = filter.clean(coll);
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
Functions.left_channel(
|
||||
coll,
|
||||
guid,
|
||||
short_id,
|
||||
in_list,
|
||||
socket,
|
||||
true,
|
||||
"left 1"
|
||||
);
|
||||
in_list = false;
|
||||
});
|
||||
|
||||
socket.on("disconnect", function() {
|
||||
Functions.left_channel(
|
||||
coll,
|
||||
guid,
|
||||
short_id,
|
||||
in_list,
|
||||
socket,
|
||||
false,
|
||||
"left 2"
|
||||
);
|
||||
});
|
||||
|
||||
socket.on("disconnected", function() {
|
||||
Functions.left_channel(
|
||||
coll,
|
||||
guid,
|
||||
short_id,
|
||||
in_list,
|
||||
socket,
|
||||
false,
|
||||
"left 3"
|
||||
);
|
||||
});
|
||||
|
||||
socket.on("left_channel", function(msg) {
|
||||
if (msg.hasOwnProperty("channel") && msg.channel.indexOf("?") > -1) {
|
||||
var _list = msg.channel.substring(0, msg.channel.indexOf("?"));
|
||||
msg.channel = _list;
|
||||
}
|
||||
if (msg.hasOwnProperty("channel")) {
|
||||
msg.channel = Functions.encodeChannelName(msg.channel);
|
||||
}
|
||||
if (
|
||||
msg.hasOwnProperty("channel") &&
|
||||
msg.channel != "" &&
|
||||
typeof msg.channel == "string"
|
||||
) {
|
||||
coll = msg.channel; //.replace(/ /g,'');
|
||||
coll = Functions.removeEmojis(coll).toLowerCase();
|
||||
//coll = filter.clean(coll);
|
||||
Functions.left_channel(
|
||||
coll,
|
||||
guid,
|
||||
short_id,
|
||||
in_list,
|
||||
socket,
|
||||
false,
|
||||
"left 4"
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
socket.on("reconnect_failed", function() {
|
||||
Functions.left_channel(
|
||||
coll,
|
||||
guid,
|
||||
short_id,
|
||||
in_list,
|
||||
socket,
|
||||
false,
|
||||
"left 5"
|
||||
);
|
||||
});
|
||||
|
||||
socket.on("connect_timeout", function() {
|
||||
Functions.left_channel(
|
||||
coll,
|
||||
guid,
|
||||
short_id,
|
||||
in_list,
|
||||
socket,
|
||||
false,
|
||||
"left 6"
|
||||
);
|
||||
});
|
||||
|
||||
socket.on("error", function() {
|
||||
Functions.left_channel(
|
||||
coll,
|
||||
guid,
|
||||
short_id,
|
||||
in_list,
|
||||
socket,
|
||||
false,
|
||||
"left 7"
|
||||
);
|
||||
});
|
||||
|
||||
socket.on("pos", function(obj) {
|
||||
if (
|
||||
obj != undefined &&
|
||||
obj.hasOwnProperty("channel") &&
|
||||
obj.channel.indexOf("?") > -1
|
||||
) {
|
||||
var _list = obj.channel.substring(0, obj.channel.indexOf("?"));
|
||||
obj.channel = _list;
|
||||
}
|
||||
if (obj != undefined && obj.hasOwnProperty("channel")) {
|
||||
obj.channel = Functions.encodeChannelName(obj.channel);
|
||||
}
|
||||
if (obj == undefined && coll == undefined) {
|
||||
return;
|
||||
}
|
||||
if (coll !== undefined) {
|
||||
try {
|
||||
coll = obj.channel.toLowerCase(); //.replace(/ /g,'');
|
||||
if (coll.length == 0) return;
|
||||
coll = Functions.removeEmojis(coll).toLowerCase();
|
||||
//coll = coll.replace(/_/g, "");
|
||||
|
||||
//coll = filter.clean(coll);
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!obj.hasOwnProperty("channel") || typeof obj.channel != "string") {
|
||||
var result = {
|
||||
channel: {
|
||||
expected: "string",
|
||||
got: obj.hasOwnProperty("channel") ? typeof obj.channel : undefined
|
||||
},
|
||||
pass: {
|
||||
expected: "string",
|
||||
got: obj.hasOwnProperty("pass") ? typeof obj.pass : undefined
|
||||
}
|
||||
};
|
||||
socket.emit("update_required", result);
|
||||
return;
|
||||
}
|
||||
if (coll == undefined) return;
|
||||
db.collection(coll + "_settings").find(function(err, docs) {
|
||||
Functions.getSessionAdminUser(
|
||||
Functions.getSession(socket),
|
||||
coll,
|
||||
function(userpass, adminpass) {
|
||||
if (userpass != "" || obj.pass == undefined) {
|
||||
obj.pass = userpass;
|
||||
} else {
|
||||
obj.pass = crypto
|
||||
.createHash("sha256")
|
||||
.update(Functions.decrypt_string(obj.pass))
|
||||
.digest("base64");
|
||||
}
|
||||
if (
|
||||
docs.length > 0 &&
|
||||
(docs[0].userpass == undefined ||
|
||||
docs[0].userpass == "" ||
|
||||
(obj.hasOwnProperty("pass") && docs[0].userpass == obj.pass))
|
||||
) {
|
||||
Functions.check_inlist(
|
||||
coll,
|
||||
guid,
|
||||
socket,
|
||||
offline,
|
||||
undefined,
|
||||
"place 4"
|
||||
);
|
||||
List.send_play(coll, socket);
|
||||
} else {
|
||||
socket.emit("auth_required");
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
//send_ping();
|
||||
};
|
||||
|
||||
/*
|
||||
function send_ping() {
|
||||
db.collection("connected_users").update({users: {$exists: true}}, {$set: {users: []}}, {multi: true}, function(err, docs){
|
||||
db.collection("connected_users").update({"_id": "total_users"}, {$add: {total_users: 0}}, {multi: true}, function(err, docs){
|
||||
db.collection("frontpage_lists").update({viewers: {$ne: 0}}, {$set: {"viewers": 0}}, {multi: true}, function(err, docs) {
|
||||
io.emit("self_ping");
|
||||
setTimeout(send_ping, 25000);
|
||||
});
|
||||
});
|
||||
});
|
||||
}*/
|
||||
1293
server/handlers/list.js
Normal file
1412
server/handlers/list_change.js
Normal file
396
server/handlers/list_settings.js
Normal file
@@ -0,0 +1,396 @@
|
||||
var Functions = require(pathThumbnails + "/handlers/functions.js");
|
||||
var crypto = require("crypto");
|
||||
var Filter = require("bad-words");
|
||||
var filter = new Filter({ placeHolder: "x" });
|
||||
/*var filter = {
|
||||
clean: function(str) {
|
||||
return str;
|
||||
}
|
||||
}*/
|
||||
var projects = require(pathThumbnails + "/handlers/aggregates.js");
|
||||
var db = require(pathThumbnails + "/handlers/db.js");
|
||||
|
||||
function password(inp, coll, guid, offline, socket) {
|
||||
var sessionId = Functions.getSession(socket);
|
||||
if (sessionId == "") sessionId = "empty";
|
||||
if (inp !== undefined && inp !== null && inp !== "") {
|
||||
if (
|
||||
!inp.hasOwnProperty("password") ||
|
||||
!inp.hasOwnProperty("channel") ||
|
||||
typeof inp.password != "string" ||
|
||||
typeof inp.channel != "string"
|
||||
) {
|
||||
var result = {
|
||||
channel: {
|
||||
expected: "string",
|
||||
got: inp.hasOwnProperty("channel") ? typeof inp.channel : undefined
|
||||
},
|
||||
password: {
|
||||
expected: "password",
|
||||
got: inp.hasOwnProperty("password") ? typeof inp.password : undefined
|
||||
}
|
||||
};
|
||||
socket.emit("update_required", result);
|
||||
return;
|
||||
}
|
||||
pw = inp.password;
|
||||
try {
|
||||
coll = inp.channel;
|
||||
if (coll.length == 0) return;
|
||||
coll = Functions.removeEmojis(coll).toLowerCase();
|
||||
//coll = coll.replace(/_/g, "");
|
||||
|
||||
//coll = filter.clean(coll);
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
//coll = coll.replace(/ /g,'');
|
||||
uncrypted = pw;
|
||||
pw = Functions.hash_pass(Functions.decrypt_string(pw), true);
|
||||
Functions.check_inlist(coll, guid, socket, offline, undefined, "place 8");
|
||||
Functions.getSessionAdminUser(sessionId, coll, function(
|
||||
userpass,
|
||||
adminpass
|
||||
) {
|
||||
adminpass = Functions.hash_pass(adminpass);
|
||||
db.collection(coll + "_settings").find(function(err, docs) {
|
||||
if (docs !== null && docs.length !== 0) {
|
||||
if (
|
||||
docs[0].adminpass === "" ||
|
||||
docs[0].adminpass == Functions.hash_pass(pw)
|
||||
) {
|
||||
Functions.setSessionAdminPass(
|
||||
sessionId,
|
||||
inp.password,
|
||||
coll,
|
||||
function() {
|
||||
db.collection(coll + "_settings").update(
|
||||
{ id: "config" },
|
||||
{ $set: { adminpass: Functions.hash_pass(pw) } },
|
||||
function(err, docs) {
|
||||
if (adminpass != pw && adminpass != "") {
|
||||
socket.emit("toast", "changedpass");
|
||||
} else {
|
||||
socket.emit("toast", "correctpass");
|
||||
}
|
||||
socket.emit("pw", true);
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
} else if (
|
||||
docs[0].adminpass === "" ||
|
||||
docs[0].adminpass == adminpass
|
||||
) {
|
||||
Functions.setSessionAdminPass(
|
||||
sessionId,
|
||||
inp.password,
|
||||
coll,
|
||||
function() {
|
||||
db.collection(coll + "_settings").update(
|
||||
{ id: "config" },
|
||||
{ $set: { adminpass: Functions.hash_pass(pw) } },
|
||||
function(err, docs) {
|
||||
if (adminpass != pw) {
|
||||
socket.emit("toast", "changedpass");
|
||||
}
|
||||
socket.emit("pw", true);
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
} else {
|
||||
Functions.setSessionAdminPass(
|
||||
Functions.getSession(socket),
|
||||
"",
|
||||
coll,
|
||||
function() {
|
||||
socket.emit("toast", "wrongpass");
|
||||
socket.emit("pw", false);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
var result = {
|
||||
inp: {
|
||||
expected: "string",
|
||||
got: typeof inpt
|
||||
}
|
||||
};
|
||||
socket.emit("update_required", result);
|
||||
}
|
||||
}
|
||||
|
||||
function conf_function(params, coll, guid, offline, socket) {
|
||||
if (params !== undefined && params !== null && params !== "") {
|
||||
if (coll !== undefined) {
|
||||
try {
|
||||
coll = params.channel; //.replace(/ /g,'');
|
||||
if (coll.length == 0) return;
|
||||
coll = Functions.removeEmojis(coll).toLowerCase();
|
||||
//coll = coll.replace(/_/g, "");
|
||||
|
||||
//coll = filter.clean(coll);
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (coll == "" || coll == undefined || coll == null) {
|
||||
socket.emit("update_required");
|
||||
return;
|
||||
}
|
||||
|
||||
Functions.check_inlist(coll, guid, socket, offline, undefined, "place 9");
|
||||
|
||||
Functions.getSessionAdminUser(Functions.getSession(socket), coll, function(
|
||||
userpass,
|
||||
adminpass,
|
||||
gotten
|
||||
) {
|
||||
if (gotten) {
|
||||
params.adminpass = adminpass;
|
||||
if (!params.userpass_changed) params.userpass = userpass;
|
||||
}
|
||||
if (
|
||||
!params.hasOwnProperty("voting") ||
|
||||
!params.hasOwnProperty("addsongs") ||
|
||||
!params.hasOwnProperty("longsongs") ||
|
||||
!params.hasOwnProperty("frontpage") ||
|
||||
!params.hasOwnProperty("allvideos") ||
|
||||
!params.hasOwnProperty("removeplay") ||
|
||||
!params.hasOwnProperty("adminpass") ||
|
||||
!params.hasOwnProperty("skipping") ||
|
||||
!params.hasOwnProperty("shuffling") ||
|
||||
!params.hasOwnProperty("channel") ||
|
||||
typeof params.userpass != "string" ||
|
||||
typeof params.adminpass != "string" ||
|
||||
typeof params.voting != "boolean" ||
|
||||
typeof params.addsongs != "boolean" ||
|
||||
typeof params.longsongs != "boolean" ||
|
||||
typeof params.frontpage != "boolean" ||
|
||||
typeof params.allvideos != "boolean" ||
|
||||
typeof params.removeplay != "boolean" ||
|
||||
typeof params.skipping != "boolean" ||
|
||||
typeof params.shuffling != "boolean" ||
|
||||
typeof params.userpass_changed != "boolean"
|
||||
) {
|
||||
var result = {
|
||||
adminpass: {
|
||||
expected: "string",
|
||||
got: params.hasOwnProperty("adminpass")
|
||||
? typeof params.adminpass
|
||||
: undefined
|
||||
},
|
||||
userpass: {
|
||||
expected: "string",
|
||||
got: params.hasOwnProperty("userpass")
|
||||
? typeof params.userpass
|
||||
: undefined
|
||||
},
|
||||
vote: {
|
||||
expected: "boolean",
|
||||
got: params.hasOwnProperty("vote") ? typeof params.vote : undefined
|
||||
},
|
||||
addsongs: {
|
||||
expected: "boolean",
|
||||
got: params.hasOwnProperty("addsongs")
|
||||
? typeof params.addsongs
|
||||
: undefined
|
||||
},
|
||||
longsongs: {
|
||||
expected: "boolean",
|
||||
got: params.hasOwnProperty("longsongs")
|
||||
? typeof params.longsongs
|
||||
: undefined
|
||||
},
|
||||
frontpage: {
|
||||
expected: "boolean",
|
||||
got: params.hasOwnProperty("frontpage")
|
||||
? typeof params.frontpage
|
||||
: undefined
|
||||
},
|
||||
skipping: {
|
||||
expected: "boolean",
|
||||
got: params.hasOwnProperty("skipping")
|
||||
? typeof params.skipping
|
||||
: undefined
|
||||
},
|
||||
shuffling: {
|
||||
expected: "boolean",
|
||||
got: params.hasOwnProperty("shuffling")
|
||||
? typeof params.shuffling
|
||||
: undefined
|
||||
},
|
||||
userpass_changed: {
|
||||
expected: "boolean",
|
||||
got: params.hasOwnProperty("userpass_changed")
|
||||
? typeof params.userpass_changed
|
||||
: undefined
|
||||
}
|
||||
};
|
||||
socket.emit("update_required", result);
|
||||
return;
|
||||
}
|
||||
var voting = params.voting;
|
||||
var addsongs = params.addsongs;
|
||||
var longsongs = params.longsongs;
|
||||
var frontpage = params.frontpage;
|
||||
var allvideos = params.allvideos;
|
||||
var removeplay = params.removeplay;
|
||||
var adminpass = params.adminpass;
|
||||
var skipping = params.skipping;
|
||||
var shuffling = params.shuffling;
|
||||
var userpass = Functions.decrypt_string(params.userpass);
|
||||
if (
|
||||
(!params.userpass_changed && frontpage) ||
|
||||
(params.userpass_changed && userpass == "")
|
||||
) {
|
||||
userpass = "";
|
||||
} else if (params.userpass_changed && userpass != "") {
|
||||
frontpage = false;
|
||||
}
|
||||
var description = "";
|
||||
var hash;
|
||||
if (params.description) description = params.description;
|
||||
if (adminpass !== "" && !gotten) {
|
||||
hash = Functions.hash_pass(
|
||||
Functions.hash_pass(Functions.decrypt_string(adminpass), true)
|
||||
);
|
||||
} else if (adminpass !== "" && gotten) {
|
||||
hash = Functions.hash_pass(adminpass);
|
||||
} else {
|
||||
hash = adminpass;
|
||||
}
|
||||
if (userpass != "") {
|
||||
if (!params.userpass_changed && gotten) {
|
||||
} else {
|
||||
userpass = crypto
|
||||
.createHash("sha256")
|
||||
.update(userpass)
|
||||
.digest("base64");
|
||||
}
|
||||
}
|
||||
db.collection(coll + "_settings").find({ id: "config" }, function(
|
||||
err,
|
||||
docs
|
||||
) {
|
||||
if (
|
||||
docs !== null &&
|
||||
docs.length !== 0 &&
|
||||
(docs[0].adminpass === "" || docs[0].adminpass == hash)
|
||||
) {
|
||||
var obj = {
|
||||
addsongs: addsongs,
|
||||
allvideos: allvideos,
|
||||
frontpage: frontpage,
|
||||
skip: skipping,
|
||||
vote: voting,
|
||||
removeplay: removeplay,
|
||||
shuffle: shuffling,
|
||||
longsongs: longsongs,
|
||||
adminpass: hash,
|
||||
desc: description
|
||||
};
|
||||
if (
|
||||
params.hasOwnProperty("toggleChat") &&
|
||||
docs[0].adminpass != "" &&
|
||||
docs[0].adminpass != undefined &&
|
||||
docs[0].adminpass == hash
|
||||
) {
|
||||
obj.toggleChat = params.toggleChat;
|
||||
}
|
||||
if (
|
||||
params.hasOwnProperty("strictSkip") &&
|
||||
docs[0].adminpass != "" &&
|
||||
docs[0].adminpass != undefined &&
|
||||
docs[0].adminpass == hash
|
||||
) {
|
||||
obj.strictSkip = params.strictSkip;
|
||||
}
|
||||
if (
|
||||
params.hasOwnProperty("strictSkipNumber") &&
|
||||
docs[0].adminpass != "" &&
|
||||
docs[0].adminpass != undefined &&
|
||||
docs[0].adminpass == hash
|
||||
) {
|
||||
try {
|
||||
obj.strictSkipNumber = parseInt(params.strictSkipNumber);
|
||||
} catch (e) {}
|
||||
}
|
||||
if (params.userpass_changed) {
|
||||
obj["userpass"] = userpass;
|
||||
} else if (frontpage) {
|
||||
obj["userpass"] = "";
|
||||
}
|
||||
db.collection(coll + "_settings").update(
|
||||
{ id: "config" },
|
||||
{
|
||||
$set: obj
|
||||
},
|
||||
function(err, docs) {
|
||||
Functions.setSessionUserPass(
|
||||
Functions.getSession(socket),
|
||||
obj["userpass"],
|
||||
coll,
|
||||
function() {
|
||||
db.collection(coll + "_settings").aggregate(
|
||||
[
|
||||
{
|
||||
$match: {
|
||||
id: "config"
|
||||
}
|
||||
},
|
||||
{
|
||||
$project: projects.toShowConfig
|
||||
}
|
||||
],
|
||||
function(err, docs) {
|
||||
if (docs[0].adminpass !== "") docs[0].adminpass = true;
|
||||
if (
|
||||
docs[0].hasOwnProperty("userpass") &&
|
||||
docs[0].userpass != ""
|
||||
)
|
||||
docs[0].userpass = true;
|
||||
else docs[0].userpass = false;
|
||||
io.to(coll).emit("conf", docs);
|
||||
socket.emit("toast", "savedsettings");
|
||||
|
||||
db.collection("frontpage_lists").update(
|
||||
{ _id: coll },
|
||||
{
|
||||
$set: {
|
||||
frontpage: frontpage,
|
||||
accessed: Functions.get_time()
|
||||
}
|
||||
},
|
||||
{ upsert: true },
|
||||
function(err, docs) {}
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
} else {
|
||||
socket.emit("toast", "wrongpass");
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
var result = {
|
||||
params: {
|
||||
expected: "object",
|
||||
got: typeof params
|
||||
}
|
||||
};
|
||||
socket.emit("update_required", result);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.password = password;
|
||||
module.exports.conf_function = conf_function;
|
||||
47
server/handlers/notifications.js
Normal file
@@ -0,0 +1,47 @@
|
||||
var path = require("path");
|
||||
|
||||
function requested_change(type, string, channel) {
|
||||
try {
|
||||
//channel = channel.replace(/ /g,'');
|
||||
var nodemailer = require("nodemailer");
|
||||
var mailconfig = require(path.join(__dirname, "../config/mailconfig.js"));
|
||||
|
||||
let transporter = nodemailer.createTransport(mailconfig);
|
||||
|
||||
transporter.verify(function(error, success) {
|
||||
if (error) {
|
||||
return;
|
||||
} else {
|
||||
var message =
|
||||
"A " +
|
||||
type +
|
||||
" change was requested on <b>" +
|
||||
channel +
|
||||
"</b><br><br>New supposed value is: <br><br><b>" +
|
||||
string +
|
||||
"</b><br><br><br> \
|
||||
Go to <a href='https://admin.zoff.me/'>https://admin.zoff.me/</a> to accept or decline the request.";
|
||||
var msg = {
|
||||
from: mailconfig.from,
|
||||
to: mailconfig.notify_mail,
|
||||
subject: "ZOFF: Requested new " + type,
|
||||
text: message,
|
||||
html: message
|
||||
};
|
||||
transporter.sendMail(msg, (error, info) => {
|
||||
if (error) {
|
||||
transporter.close();
|
||||
return;
|
||||
}
|
||||
transporter.close();
|
||||
});
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
console.log(
|
||||
"(!) Missing file - /config/mailconfig.js Have a look at /config/mailconfig.example.js. "
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.requested_change = requested_change;
|
||||
674
server/handlers/search.js
Normal file
@@ -0,0 +1,674 @@
|
||||
var path = require("path");
|
||||
var time_regex = /P((([0-9]*\.?[0-9]*)Y)?(([0-9]*\.?[0-9]*)M)?(([0-9]*\.?[0-9]*)W)?(([0-9]*\.?[0-9]*)D)?)?(T(([0-9]*\.?[0-9]*)H)?(([0-9]*\.?[0-9]*)M)?(([0-9]*\.?[0-9]*)S)?)?/;
|
||||
try {
|
||||
var keys = require(path.join(__dirname, "../config/api_key.js"));
|
||||
var key = keys.youtube;
|
||||
var soundcloudKey = keys.soundcloud;
|
||||
} catch (e) {
|
||||
console.log(
|
||||
"(!) Missing file - /config/api_key.js Have a look at /config/api_key.example.js. The server won't run without this existing."
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
var request = require("request");
|
||||
var db = require(pathThumbnails + "/handlers/db.js");
|
||||
var countryCodes = ["US", "NO", "SE", "DK", "CA", "EU", "UK"];
|
||||
|
||||
function check_if_error_or_blocked(id, channel, errored, callback) {
|
||||
if (!errored) {
|
||||
callback(false);
|
||||
return;
|
||||
}
|
||||
db.collection(channel).find({ id: id, now_playing: true }, function(
|
||||
err,
|
||||
song
|
||||
) {
|
||||
if (song.length == 0) {
|
||||
callback(false);
|
||||
return;
|
||||
}
|
||||
var song_info = song[0];
|
||||
if (song_info.source != "soundcloud") {
|
||||
request(
|
||||
{
|
||||
type: "GET",
|
||||
url:
|
||||
"https://www.googleapis.com/youtube/v3/videos?part=id,status,contentDetails&key=" +
|
||||
key +
|
||||
"&id=" +
|
||||
song_info.id
|
||||
},
|
||||
function(error, response, body) {
|
||||
try {
|
||||
var resp = JSON.parse(body);
|
||||
if (resp.pageInfo.totalResults == 0) {
|
||||
callback(true);
|
||||
return;
|
||||
} else if (!resp.items[0].status.embeddable) {
|
||||
callback(true);
|
||||
return;
|
||||
} else if (
|
||||
resp.items[0].contentDetails.hasOwnProperty("licensedContent") &&
|
||||
resp.items[0].contentDetails.licensedContent
|
||||
) {
|
||||
callback(true);
|
||||
return;
|
||||
} else if (
|
||||
resp.items[0].contentDetails.hasOwnProperty(
|
||||
"regionRestriction"
|
||||
) &&
|
||||
resp.items[0].contentDetails.regionRestriction.hasOwnProperty(
|
||||
"blocked"
|
||||
) &&
|
||||
resp.items[0].contentDetails.regionRestriction.blocked.length > 0
|
||||
) {
|
||||
var any = resp.items[0].contentDetails.blocked.some(function(
|
||||
element
|
||||
) {
|
||||
return countryCodes.indexOf(element) > -1;
|
||||
});
|
||||
if (any) {
|
||||
callback(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
callback(false);
|
||||
return;
|
||||
} catch (e) {
|
||||
callback(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
);
|
||||
} else {
|
||||
request(
|
||||
{
|
||||
type: "GET",
|
||||
url:
|
||||
"http://api.soundcloud.com/tracks/" +
|
||||
song_info.id +
|
||||
"?client_id=" +
|
||||
soundcloudKey
|
||||
},
|
||||
function(error, response, body) {
|
||||
try {
|
||||
var resp = JSON.parse(body);
|
||||
if (resp.sharing != "public" || resp.embeddable_by != "all") {
|
||||
callback(true);
|
||||
return;
|
||||
}
|
||||
callback(false);
|
||||
return;
|
||||
} catch (e) {
|
||||
callback(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function filterFunction(el) {
|
||||
return el != null && el != "" && el != undefined && el.trim() != "";
|
||||
}
|
||||
|
||||
function get_genres_soundcloud(song, channel) {
|
||||
request(
|
||||
"http://api.soundcloud.com/tracks/" +
|
||||
song.id +
|
||||
"?client_id=" +
|
||||
soundcloudKey,
|
||||
function(err, response, body) {
|
||||
if (err) {
|
||||
console.log("error start", err, song, "error end");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
var object = JSON.parse(body);
|
||||
if (
|
||||
!object.hasOwnProperty("genre") ||
|
||||
!object.hasOwnProperty("tag_list")
|
||||
)
|
||||
return;
|
||||
var genre = object.genre + ",";
|
||||
genre = genre
|
||||
.toLowerCase()
|
||||
.split(",")
|
||||
.concat(object.tag_list.toLowerCase().split('"'));
|
||||
genre = genre.filter(filterFunction);
|
||||
|
||||
db.collection(channel).update(
|
||||
{ id: song.id },
|
||||
{
|
||||
$set: {
|
||||
tags: genre
|
||||
}
|
||||
},
|
||||
function(e, d) {}
|
||||
);
|
||||
} catch (e) {
|
||||
console.log("errored 2", e);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function get_genres_list(list, channel) {
|
||||
var youtube_array = "";
|
||||
var i = 0;
|
||||
try {
|
||||
for (var i = 0; i < list.length; i++) {
|
||||
if (!list[i].hasOwnProperty("id")) continue;
|
||||
if (list[i].source == undefined || list[i].source == "youtube") {
|
||||
youtube_array += list[i].id + ",";
|
||||
} else if (
|
||||
list[i].source != undefined &&
|
||||
list[i].source == "soundcloud"
|
||||
) {
|
||||
get_genres_soundcloud(list[i], channel);
|
||||
}
|
||||
}
|
||||
if (youtube_array.length > 0) {
|
||||
if (youtube_array > 49) {
|
||||
var subList = [];
|
||||
for (var i = 0; i < youtube_array.length; i++) {
|
||||
subList.push(youtube_array[i]);
|
||||
if (subList.length > 49) {
|
||||
get_genres_youtube(subList.join(","), channel);
|
||||
subList = [];
|
||||
}
|
||||
}
|
||||
get_genres_youtube(subList.join(","), channel);
|
||||
subList = [];
|
||||
} else {
|
||||
get_genres_youtube(youtube_array, channel);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.log("errored", e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function start_soundcloud_get(arr, channel, callback) {
|
||||
get_genres_soundcloud_recursive(arr, channel, 0, callback);
|
||||
}
|
||||
|
||||
function get_genres_soundcloud_recursive(arr, channel, i, callback) {
|
||||
if (i >= arr.length) {
|
||||
if (typeof callback == "function") callback();
|
||||
return;
|
||||
}
|
||||
var song = arr[i];
|
||||
request(
|
||||
"http://api.soundcloud.com/tracks/" +
|
||||
song.id +
|
||||
"?client_id=" +
|
||||
soundcloudKey,
|
||||
function(err, response, body) {
|
||||
if (err) {
|
||||
console.log("error start", err, song, "error end");
|
||||
get_genres_soundcloud_recursive(arr, channel, i + 1, callback);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
var object = JSON.parse(body);
|
||||
if (
|
||||
!object.hasOwnProperty("genre") ||
|
||||
!object.hasOwnProperty("tag_list")
|
||||
) {
|
||||
get_genres_soundcloud_recursive(arr, channel, i + 1, callback);
|
||||
return;
|
||||
}
|
||||
var genre = object.genre + ",";
|
||||
genre = genre
|
||||
.toLowerCase()
|
||||
.split(",")
|
||||
.concat(object.tag_list.toLowerCase().split('"'));
|
||||
genre = genre.filter(filterFunction);
|
||||
|
||||
db.collection(channel).update(
|
||||
{ id: song.id },
|
||||
{
|
||||
$set: {
|
||||
tags: genre
|
||||
}
|
||||
},
|
||||
function(e, d) {
|
||||
get_genres_soundcloud_recursive(arr, channel, i + 1, callback);
|
||||
}
|
||||
);
|
||||
} catch (e) {
|
||||
console.log("errored 2", e);
|
||||
get_genres_soundcloud_recursive(arr, channel, i + 1, callback);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function get_genres_list_recursive(list, channel, callback) {
|
||||
var youtube_array = [];
|
||||
var soundcloud_array = [];
|
||||
for (var i = 0; i < list.length; i++) {
|
||||
if (!list[i].hasOwnProperty("id")) continue;
|
||||
if (list[i].source == undefined || list[i].source == "youtube") {
|
||||
youtube_array.push(list[i]);
|
||||
} else if (list[i].source != undefined && list[i].source == "soundcloud") {
|
||||
soundcloud_array.push(list[i]);
|
||||
}
|
||||
}
|
||||
start_youtube_get(youtube_array, channel, function() {
|
||||
start_soundcloud_get(soundcloud_array, channel, function() {
|
||||
if (typeof callback == "function") callback();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function start_youtube_get(arr, channel, callback) {
|
||||
get_genres_youtube_recursive(arr, channel, 0, callback);
|
||||
}
|
||||
|
||||
function get_genres_youtube_recursive(arr, channel, i, callback) {
|
||||
if (i >= arr.length) {
|
||||
if (typeof callback == "function") callback();
|
||||
return;
|
||||
}
|
||||
var ids = [];
|
||||
for (var y = i; y < arr.length; y++) {
|
||||
if (ids.length >= 48) {
|
||||
break;
|
||||
}
|
||||
ids.push(arr[y].id);
|
||||
}
|
||||
request(
|
||||
{
|
||||
type: "GET",
|
||||
url:
|
||||
"https://www.googleapis.com/youtube/v3/videos?part=contentDetails,snippet,id,topicDetails&key=" +
|
||||
key +
|
||||
"&id=" +
|
||||
ids.join(",")
|
||||
},
|
||||
function(error, response, body) {
|
||||
if (error) {
|
||||
get_genres_youtube_recursive(arr, channel, i + ids.length, callback);
|
||||
return;
|
||||
}
|
||||
var resp = JSON.parse(body);
|
||||
if (!resp.hasOwnProperty("items")) {
|
||||
get_genres_youtube_recursive(arr, channel, i + ids.length, callback);
|
||||
return;
|
||||
}
|
||||
if (resp.items.length > 0) {
|
||||
for (var z = 0; z < resp.items.length; z++) {
|
||||
if (!resp.items[z].hasOwnProperty("topicDetails")) continue;
|
||||
var genre = resp.items[z].topicDetails.topicCategories;
|
||||
genre = genre.join(",");
|
||||
genre = genre.replace(
|
||||
new RegExp("https://en.wikipedia.org/wiki/", "g"),
|
||||
""
|
||||
);
|
||||
genre = genre
|
||||
.replace(/_/g, " ")
|
||||
.toLowerCase()
|
||||
.split(",");
|
||||
genre = genre.filter(filterFunction);
|
||||
//console.log(resp.items[i].id + " - ", genre);
|
||||
db.collection(channel).update(
|
||||
{ id: resp.items[z].id },
|
||||
{
|
||||
$set: {
|
||||
tags: genre
|
||||
}
|
||||
},
|
||||
function(e, d) {}
|
||||
);
|
||||
}
|
||||
get_genres_youtube_recursive(arr, channel, i + ids.length, callback);
|
||||
} else {
|
||||
get_genres_youtube_recursive(arr, channel, i + ids.length, callback);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function get_genres_youtube(ids, channel) {
|
||||
request(
|
||||
{
|
||||
type: "GET",
|
||||
url:
|
||||
"https://www.googleapis.com/youtube/v3/videos?part=contentDetails,snippet,id,topicDetails&key=" +
|
||||
key +
|
||||
"&id=" +
|
||||
ids
|
||||
},
|
||||
function(error, response, body) {
|
||||
if (error) {
|
||||
return;
|
||||
}
|
||||
var resp = JSON.parse(body);
|
||||
if (!resp.hasOwnProperty("items")) {
|
||||
return;
|
||||
}
|
||||
if (resp.items.length > 0) {
|
||||
for (var i = 0; i < resp.items.length; i++) {
|
||||
if (!resp.items[i].hasOwnProperty("topicDetails")) continue;
|
||||
var genre = resp.items[i].topicDetails.topicCategories;
|
||||
genre = genre.join(",");
|
||||
genre = genre.replace(
|
||||
new RegExp("https://en.wikipedia.org/wiki/", "g"),
|
||||
""
|
||||
);
|
||||
genre = genre
|
||||
.replace(/_/g, " ")
|
||||
.toLowerCase()
|
||||
.split(",");
|
||||
genre = genre.filter(filterFunction);
|
||||
//console.log(resp.items[i].id + " - ", genre);
|
||||
db.collection(channel).update(
|
||||
{ id: resp.items[i].id },
|
||||
{
|
||||
$set: {
|
||||
tags: genre
|
||||
}
|
||||
},
|
||||
function(e, d) {}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function get_correct_info(song_generated, channel, broadcast, callback) {
|
||||
//channel = channel.replace(/ /g,'');
|
||||
request(
|
||||
{
|
||||
type: "GET",
|
||||
url:
|
||||
"https://www.googleapis.com/youtube/v3/videos?part=contentDetails,snippet,id,topicDetails&key=" +
|
||||
key +
|
||||
"&id=" +
|
||||
song_generated.id
|
||||
},
|
||||
function(error, response, body) {
|
||||
try {
|
||||
var resp = JSON.parse(body);
|
||||
if (resp.items.length == 1) {
|
||||
var duration = parseInt(
|
||||
durationToSeconds(resp.items[0].contentDetails.duration)
|
||||
);
|
||||
var title = resp.items[0].snippet.localized.title;
|
||||
var genre = resp.items[0].topicDetails.topicCategories;
|
||||
genre = genre.join(",");
|
||||
genre = genre.replace(
|
||||
new RegExp("https://en.wikipedia.org/wiki/", "g"),
|
||||
""
|
||||
);
|
||||
genre = genre
|
||||
.replace(/_/g, " ")
|
||||
.toLowerCase()
|
||||
.split(",");
|
||||
genre = genre.filter(filterFunction);
|
||||
//console.log(genre + " - ", song_generated.id);
|
||||
if (
|
||||
title != song_generated.title ||
|
||||
duration < parseInt(song_generated.duration)
|
||||
) {
|
||||
if (title != song_generated.title) {
|
||||
song_generated.title = title;
|
||||
}
|
||||
if (duration < parseInt(song_generated.duration)) {
|
||||
song_generated.duration = duration;
|
||||
song_generated.start = 0;
|
||||
song_generated.end = duration;
|
||||
}
|
||||
db.collection(channel).update(
|
||||
{ id: song_generated.id },
|
||||
{
|
||||
$set: {
|
||||
duration: song_generated.duration,
|
||||
start: song_generated.start,
|
||||
end: song_generated.end,
|
||||
title: song_generated.title,
|
||||
tags: genre
|
||||
}
|
||||
},
|
||||
function(err, docs) {
|
||||
if (broadcast && docs.nModified == 1) {
|
||||
song_generated.new_id = song_generated.id;
|
||||
//if(song_generated.type == "video")
|
||||
if (typeof callback == "function") {
|
||||
callback(song_generated, true);
|
||||
} else {
|
||||
io.to(channel).emit("channel", {
|
||||
type: "changed_values",
|
||||
value: song_generated
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (typeof callback == "function") {
|
||||
callback(song_generated, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
} else {
|
||||
db.collection(channel).update(
|
||||
{ id: song_generated.id },
|
||||
{
|
||||
$set: {
|
||||
tags: genre
|
||||
}
|
||||
},
|
||||
function(e, d) {
|
||||
if (typeof callback == "function") {
|
||||
callback(song_generated, true);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
} else {
|
||||
findSimilar(song_generated, channel, broadcast, callback);
|
||||
}
|
||||
} catch (e) {
|
||||
if (typeof callback == "function") {
|
||||
callback({}, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function check_error_video(msg, channel) {
|
||||
if (
|
||||
!msg.hasOwnProperty("id") ||
|
||||
!msg.hasOwnProperty("title") ||
|
||||
typeof msg.id != "string" ||
|
||||
typeof msg.title != "string"
|
||||
) {
|
||||
var result = {
|
||||
id: {
|
||||
expected: "string",
|
||||
got: msg.hasOwnProperty("id") ? typeof msg.id : undefined
|
||||
},
|
||||
title: {
|
||||
expected: "string",
|
||||
got: msg.hasOwnProperty("title") ? typeof msg.title : undefined
|
||||
}
|
||||
};
|
||||
return;
|
||||
}
|
||||
if (msg.source == "soundcloud") return;
|
||||
//channel = channel.replace(/ /g,'');
|
||||
request(
|
||||
{
|
||||
type: "GET",
|
||||
url:
|
||||
"https://www.googleapis.com/youtube/v3/videos?part=id&key=" +
|
||||
key +
|
||||
"&id=" +
|
||||
msg.id
|
||||
},
|
||||
function(error, response, body) {
|
||||
try {
|
||||
var resp = JSON.parse(body);
|
||||
if (resp.pageInfo.totalResults == 0) {
|
||||
findSimilar(msg, channel, true, undefined);
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(msg.id, key, e, body);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function findSimilar(msg, channel, broadcast, callback) {
|
||||
//channel = channel.replace(/ /g,'');
|
||||
var yt_url =
|
||||
"https://www.googleapis.com/youtube/v3/search?key=" +
|
||||
key +
|
||||
"&videoEmbeddable=true&part=id&type=video&order=viewCount&safeSearch=none&maxResults=5&q=" +
|
||||
encodeURIComponent(msg.title);
|
||||
request(
|
||||
{
|
||||
method: "GET",
|
||||
url: yt_url
|
||||
},
|
||||
function(error, response, body) {
|
||||
var resp = JSON.parse(body);
|
||||
if (resp.items.length > 0) {
|
||||
var vid_url =
|
||||
"https://www.googleapis.com/youtube/v3/videos?part=contentDetails,snippet,id&key=" +
|
||||
key +
|
||||
"&id=";
|
||||
for (var i = 0; i < resp.items.length; i++) {
|
||||
vid_url += resp.items[i].id.videoId + ",";
|
||||
}
|
||||
request(
|
||||
{
|
||||
type: "GET",
|
||||
url: vid_url
|
||||
},
|
||||
function(error, response, body) {
|
||||
var resp = JSON.parse(body);
|
||||
var found = false;
|
||||
var element = {};
|
||||
for (var i = 0; i < resp.items.length; i++) {
|
||||
if (
|
||||
similarity(resp.items[i].snippet.localized.title, msg.title) >
|
||||
0.75
|
||||
) {
|
||||
found = true;
|
||||
element = {
|
||||
title: resp.items[i].snippet.localized.title,
|
||||
duration: parseInt(
|
||||
durationToSeconds(resp.items[i].contentDetails.duration)
|
||||
),
|
||||
id: resp.items[i].id,
|
||||
start: 0,
|
||||
end: parseInt(
|
||||
durationToSeconds(resp.items[i].contentDetails.duration)
|
||||
)
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
db.collection(channel).update(
|
||||
{ id: msg.id },
|
||||
{
|
||||
$set: element
|
||||
},
|
||||
function(err, docs) {
|
||||
if (
|
||||
docs &&
|
||||
docs.hasOwnProperty("nModified") &&
|
||||
docs.nModified == 1 &&
|
||||
broadcast
|
||||
) {
|
||||
element.new_id = element.id;
|
||||
element.id = msg.id;
|
||||
if (!callback) {
|
||||
io.to(channel).emit("channel", {
|
||||
type: "changed_values",
|
||||
value: element
|
||||
});
|
||||
}
|
||||
}
|
||||
if (typeof callback == "function") {
|
||||
msg.title = element.title;
|
||||
msg.id = element.id;
|
||||
msg.duration = element.duration;
|
||||
msg.start = element.start;
|
||||
msg.end = element.end;
|
||||
callback(msg, true);
|
||||
}
|
||||
}
|
||||
);
|
||||
} else if (typeof callback == "function") {
|
||||
callback({}, false);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function similarity(s1, s2) {
|
||||
var longer = s1;
|
||||
var shorter = s2;
|
||||
if (s1.length < s2.length) {
|
||||
longer = s2;
|
||||
shorter = s1;
|
||||
}
|
||||
var longerLength = longer.length;
|
||||
if (longerLength == 0) {
|
||||
return 1.0;
|
||||
}
|
||||
return (
|
||||
(longerLength - editDistance(longer, shorter)) / parseFloat(longerLength)
|
||||
);
|
||||
}
|
||||
|
||||
function editDistance(s1, s2) {
|
||||
s1 = s1.toLowerCase();
|
||||
s2 = s2.toLowerCase();
|
||||
|
||||
var costs = new Array();
|
||||
for (var i = 0; i <= s1.length; i++) {
|
||||
var lastValue = i;
|
||||
for (var j = 0; j <= s2.length; j++) {
|
||||
if (i == 0) costs[j] = j;
|
||||
else {
|
||||
if (j > 0) {
|
||||
var newValue = costs[j - 1];
|
||||
if (s1.charAt(i - 1) != s2.charAt(j - 1))
|
||||
newValue = Math.min(Math.min(newValue, lastValue), costs[j]) + 1;
|
||||
costs[j - 1] = lastValue;
|
||||
lastValue = newValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (i > 0) costs[s2.length] = lastValue;
|
||||
}
|
||||
return costs[s2.length];
|
||||
}
|
||||
|
||||
function durationToSeconds(duration) {
|
||||
var matches = duration.match(time_regex);
|
||||
hours = parseInt(matches[12]) || 0;
|
||||
minutes = parseInt(matches[14]) || 0;
|
||||
seconds = parseInt(matches[16]) || 0;
|
||||
return hours * 60 * 60 + minutes * 60 + seconds;
|
||||
}
|
||||
|
||||
module.exports.check_if_error_or_blocked = check_if_error_or_blocked;
|
||||
module.exports.get_genres_list_recursive = get_genres_list_recursive;
|
||||
module.exports.get_genres_soundcloud = get_genres_soundcloud;
|
||||
module.exports.get_genres_youtube = get_genres_youtube;
|
||||
module.exports.get_genres_list = get_genres_list;
|
||||
module.exports.check_error_video = check_error_video;
|
||||
module.exports.get_correct_info = get_correct_info;
|
||||
284
server/handlers/suggestions.js
Normal file
@@ -0,0 +1,284 @@
|
||||
var Functions = require(pathThumbnails + "/handlers/functions.js");
|
||||
var Notifications = require(pathThumbnails + "/handlers/notifications.js");
|
||||
var crypto = require("crypto");
|
||||
var db = require(pathThumbnails + "/handlers/db.js");
|
||||
|
||||
function thumbnail(msg, coll, guid, offline, socket) {
|
||||
if (
|
||||
msg.thumbnail != undefined &&
|
||||
msg.channel &&
|
||||
msg.channel != undefined &&
|
||||
Functions.isUrl(msg.thumbnail)
|
||||
) {
|
||||
if (typeof msg.channel != "string" || typeof msg.thumbnail != "string") {
|
||||
var result = {
|
||||
channel: {
|
||||
expected: "string",
|
||||
got: msg.hasOwnProperty("channel") ? typeof msg.channel : undefined
|
||||
},
|
||||
pass: {
|
||||
expected: "string",
|
||||
got: msg.hasOwnProperty("pass") ? typeof msg.pass : undefined
|
||||
},
|
||||
thumbnail: {
|
||||
expected: "string",
|
||||
got: msg.hasOwnProperty("thumbnail")
|
||||
? typeof msg.thumbnail
|
||||
: undefined
|
||||
},
|
||||
adminpass: {
|
||||
expected: "string",
|
||||
got: msg.hasOwnProperty("adminpass")
|
||||
? typeof msg.adminpass
|
||||
: undefined
|
||||
}
|
||||
};
|
||||
socket.emit("update_required", result);
|
||||
return;
|
||||
}
|
||||
//coll = coll.replace(/ /g,'');
|
||||
Functions.getSessionAdminUser(Functions.getSession(socket), coll, function(
|
||||
userpass,
|
||||
adminpass
|
||||
) {
|
||||
if (userpass != "" || msg.pass == undefined) {
|
||||
msg.pass = userpass;
|
||||
} else if (msg.hasOwnProperty("pass")) {
|
||||
msg.pass = crypto
|
||||
.createHash("sha256")
|
||||
.update(Functions.decrypt_string(msg.pass))
|
||||
.digest("base64");
|
||||
}
|
||||
if (adminpass != "" || msg.adminpass == undefined) {
|
||||
msg.adminpass = Functions.hash_pass(adminpass);
|
||||
} else {
|
||||
msg.adminpass = Functions.hash_pass(
|
||||
Functions.hash_pass(Functions.decrypt_string(msg.adminpass), true)
|
||||
);
|
||||
}
|
||||
if (msg.thumbnail != "") {
|
||||
msg.thumbnail = msg.thumbnail.replace(/^https?\:\/\//i, "");
|
||||
if (msg.thumbnail.substring(0, 2) != "//")
|
||||
msg.thumbnail = "//" + msg.thumbnail;
|
||||
}
|
||||
var channel = msg.channel.toLowerCase();
|
||||
var hash = msg.adminpass;
|
||||
db.collection(channel + "_settings").find({ id: "config" }, function(
|
||||
err,
|
||||
docs
|
||||
) {
|
||||
if (
|
||||
docs.length > 0 &&
|
||||
(docs[0].userpass == undefined ||
|
||||
docs[0].userpass == "" ||
|
||||
(msg.hasOwnProperty("pass") && docs[0].userpass == msg.pass))
|
||||
) {
|
||||
if (
|
||||
docs !== null &&
|
||||
docs.length !== 0 &&
|
||||
docs[0].adminpass !== "" &&
|
||||
docs[0].adminpass == hash
|
||||
) {
|
||||
db.collection("suggested_thumbnails").update(
|
||||
{ channel: channel },
|
||||
{ $set: { thumbnail: msg.thumbnail } },
|
||||
{ upsert: true },
|
||||
function(err, docs) {
|
||||
Notifications.requested_change(
|
||||
"thumbnail",
|
||||
msg.thumbnail,
|
||||
channel
|
||||
);
|
||||
socket.emit("toast", "suggested_thumbnail");
|
||||
}
|
||||
);
|
||||
}
|
||||
} else {
|
||||
socket.emit("auth_required");
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
socket.emit("toast", "thumbnail_denied");
|
||||
}
|
||||
}
|
||||
|
||||
function description(msg, coll, guid, offline, socket) {
|
||||
if (msg.description && msg.channel && msg.description.length < 100) {
|
||||
if (typeof msg.channel != "string" || typeof msg.description != "string") {
|
||||
var result = {
|
||||
channel: {
|
||||
expected: "string",
|
||||
got: msg.hasOwnProperty("channel") ? typeof msg.channel : undefined
|
||||
},
|
||||
pass: {
|
||||
expected: "string",
|
||||
got: msg.hasOwnProperty("pass") ? typeof msg.pass : undefined
|
||||
},
|
||||
description: {
|
||||
expected: "string",
|
||||
got: msg.hasOwnProperty("description")
|
||||
? typeof msg.description
|
||||
: undefined
|
||||
},
|
||||
adminpass: {
|
||||
expected: "string",
|
||||
got: msg.hasOwnProperty("adminpass")
|
||||
? typeof msg.adminpass
|
||||
: undefined
|
||||
}
|
||||
};
|
||||
socket.emit("update_required", result);
|
||||
return;
|
||||
}
|
||||
//coll = coll.replace(/ /g,'');
|
||||
Functions.getSessionAdminUser(Functions.getSession(socket), coll, function(
|
||||
userpass,
|
||||
adminpass,
|
||||
gotten
|
||||
) {
|
||||
if (userpass != "" || msg.pass == undefined) {
|
||||
msg.pass = userpass;
|
||||
} else if (msg.hasOwnProperty("pass")) {
|
||||
msg.pass = crypto
|
||||
.createHash("sha256")
|
||||
.update(Functions.decrypt_string(msg.pass))
|
||||
.digest("base64");
|
||||
}
|
||||
if (adminpass != "" || msg.adminpass == undefined) {
|
||||
msg.adminpass = Functions.hash_pass(adminpass);
|
||||
} else {
|
||||
msg.adminpass = Functions.hash_pass(
|
||||
Functions.hash_pass(Functions.decrypt_string(msg.adminpass), true)
|
||||
);
|
||||
}
|
||||
var channel = msg.channel.toLowerCase();
|
||||
var hash = msg.adminpass;
|
||||
db.collection(channel + "_settings").find({ id: "config" }, function(
|
||||
err,
|
||||
docs
|
||||
) {
|
||||
if (
|
||||
docs.length > 0 &&
|
||||
(docs[0].userpass == undefined ||
|
||||
docs[0].userpass == "" ||
|
||||
(msg.hasOwnProperty("pass") && docs[0].userpass == msg.pass))
|
||||
) {
|
||||
if (
|
||||
docs !== null &&
|
||||
docs.length !== 0 &&
|
||||
docs[0].adminpass !== "" &&
|
||||
docs[0].adminpass == hash
|
||||
) {
|
||||
db.collection("suggested_descriptions").update(
|
||||
{ channel: channel },
|
||||
{ $set: { description: msg.description } },
|
||||
{ upsert: true },
|
||||
function(err, docs) {
|
||||
Notifications.requested_change(
|
||||
"description",
|
||||
msg.description,
|
||||
channel
|
||||
);
|
||||
socket.emit("toast", "suggested_description");
|
||||
}
|
||||
);
|
||||
}
|
||||
} else {
|
||||
socket.emit("auth_required");
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
socket.emit("toast", "description_denied");
|
||||
}
|
||||
}
|
||||
|
||||
function rules(msg, coll, guid, offline, socket) {
|
||||
if (msg.rules && msg.channel && msg.rules.length < 250) {
|
||||
if (typeof msg.channel != "string" || typeof msg.rules != "string") {
|
||||
var result = {
|
||||
channel: {
|
||||
expected: "string",
|
||||
got: msg.hasOwnProperty("channel") ? typeof msg.channel : undefined
|
||||
},
|
||||
pass: {
|
||||
expected: "string",
|
||||
got: msg.hasOwnProperty("pass") ? typeof msg.pass : undefined
|
||||
},
|
||||
rules: {
|
||||
expected: "string",
|
||||
got: msg.hasOwnProperty("rules") ? typeof msg.rules : undefined
|
||||
},
|
||||
adminpass: {
|
||||
expected: "string",
|
||||
got: msg.hasOwnProperty("adminpass")
|
||||
? typeof msg.adminpass
|
||||
: undefined
|
||||
}
|
||||
};
|
||||
socket.emit("update_required", result);
|
||||
return;
|
||||
}
|
||||
//coll = coll.replace(/ /g,'');
|
||||
Functions.getSessionAdminUser(Functions.getSession(socket), coll, function(
|
||||
userpass,
|
||||
adminpass,
|
||||
gotten
|
||||
) {
|
||||
if (userpass != "" || msg.pass == undefined) {
|
||||
msg.pass = userpass;
|
||||
} else if (msg.hasOwnProperty("pass")) {
|
||||
msg.pass = crypto
|
||||
.createHash("sha256")
|
||||
.update(Functions.decrypt_string(msg.pass))
|
||||
.digest("base64");
|
||||
}
|
||||
if (adminpass != "" || msg.adminpass == undefined) {
|
||||
msg.adminpass = Functions.hash_pass(adminpass);
|
||||
} else {
|
||||
msg.adminpass = Functions.hash_pass(
|
||||
Functions.hash_pass(Functions.decrypt_string(msg.adminpass), true)
|
||||
);
|
||||
}
|
||||
var channel = msg.channel.toLowerCase();
|
||||
var hash = msg.adminpass;
|
||||
db.collection(channel + "_settings").find({ id: "config" }, function(
|
||||
err,
|
||||
docs
|
||||
) {
|
||||
if (
|
||||
docs.length > 0 &&
|
||||
(docs[0].userpass == undefined ||
|
||||
docs[0].userpass == "" ||
|
||||
(msg.hasOwnProperty("pass") && docs[0].userpass == msg.pass))
|
||||
) {
|
||||
if (
|
||||
docs !== null &&
|
||||
docs.length !== 0 &&
|
||||
docs[0].adminpass !== "" &&
|
||||
docs[0].adminpass == hash
|
||||
) {
|
||||
db.collection("suggested_rules").update(
|
||||
{ channel: channel },
|
||||
{ $set: { rules: msg.rules } },
|
||||
{ upsert: true },
|
||||
function(err, docs) {
|
||||
Notifications.requested_change("rules", msg.rules, channel);
|
||||
socket.emit("toast", "suggested_rules");
|
||||
}
|
||||
);
|
||||
}
|
||||
} else {
|
||||
socket.emit("auth_required");
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
socket.emit("toast", "rules_denied");
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.thumbnail = thumbnail;
|
||||
module.exports.description = description;
|
||||
module.exports.rules = rules;
|
||||
24
server/models/user.js
Normal file
@@ -0,0 +1,24 @@
|
||||
// app/models/user.js
|
||||
// load the things we need
|
||||
var mongoose = require("mongoose");
|
||||
var bcrypt = require("bcrypt-nodejs");
|
||||
|
||||
// define the schema for our user model
|
||||
var userSchema = mongoose.Schema({
|
||||
username: String,
|
||||
password: String
|
||||
});
|
||||
|
||||
// methods ======================
|
||||
// generating a hash
|
||||
userSchema.methods.generateHash = function(password) {
|
||||
return bcrypt.hashSync(password, bcrypt.genSaltSync(8), null);
|
||||
};
|
||||
|
||||
// checking if password is valid
|
||||
userSchema.methods.validPassword = function(password) {
|
||||
return bcrypt.compareSync(password, this.password);
|
||||
};
|
||||
|
||||
// create the model for users and expose it to our app
|
||||
module.exports = mongoose.model("User", userSchema);
|
||||
82
server/pm2.js
Normal file
@@ -0,0 +1,82 @@
|
||||
var cluster = require("cluster"),
|
||||
net = require("net"),
|
||||
path = require("path"),
|
||||
//publicPath = path.join(__dirname, 'public'),
|
||||
http = require("http"),
|
||||
port = 8080,
|
||||
//farmhash = require('farmhash'),
|
||||
uniqid = require("uniqid"),
|
||||
num_processes = require("os").cpus().length;
|
||||
|
||||
publicPath = path.join(__dirname, "public");
|
||||
pathThumbnails = __dirname;
|
||||
|
||||
var redis = require("redis");
|
||||
var client = redis.createClient({ host: "localhost", port: 6379 });
|
||||
|
||||
startSingle(true, true);
|
||||
|
||||
function startSingle(clustered, redis_enabled) {
|
||||
var server;
|
||||
var client = require("./apps/client.js");
|
||||
try {
|
||||
var cert_config = require(path.join(
|
||||
path.join(__dirname, "config"),
|
||||
"cert_config.js"
|
||||
));
|
||||
var fs = require("fs");
|
||||
var privateKey = fs.readFileSync(cert_config.privateKey).toString();
|
||||
var certificate = fs.readFileSync(cert_config.certificate).toString();
|
||||
var ca = fs.readFileSync(cert_config.ca).toString();
|
||||
var credentials = {
|
||||
key: privateKey,
|
||||
cert: certificate,
|
||||
ca: ca
|
||||
};
|
||||
var https = require("https");
|
||||
server = https.Server(credentials, routingFunction);
|
||||
} catch (err) {
|
||||
console.log("Starting without https (probably on localhost)");
|
||||
server = http.createServer(routingFunction);
|
||||
}
|
||||
|
||||
server.listen(port, onListen);
|
||||
|
||||
var socketIO = client.socketIO;
|
||||
|
||||
var redis = require("socket.io-redis");
|
||||
try {
|
||||
socketIO.adapter(redis({ host: "localhost", port: 6379 }));
|
||||
} catch (e) {
|
||||
console.log("No redis-server to connect to..");
|
||||
}
|
||||
socketIO.listen(server);
|
||||
}
|
||||
|
||||
function onListen() {
|
||||
console.log("Started with pid [" + process.pid + "]");
|
||||
}
|
||||
|
||||
function routingFunction(req, res, next) {
|
||||
var client = require("./apps/client.js");
|
||||
var admin = require("./apps/admin.js");
|
||||
try {
|
||||
var url = req.headers["x-forwarded-host"]
|
||||
? req.headers["x-forwarded-host"]
|
||||
: req.headers.host.split(":")[0];
|
||||
var subdomain = req.headers["x-forwarded-host"]
|
||||
? req.headers["x-forwarded-host"].split(".")
|
||||
: req.headers.host.split(":")[0].split(".");
|
||||
|
||||
if (subdomain.length > 1 && subdomain[0] == "admin") {
|
||||
admin(req, res, next);
|
||||
} else {
|
||||
client(req, res, next);
|
||||
}
|
||||
} catch (e) {
|
||||
console.log("Bad request for " + req.headers.host + req.url, e);
|
||||
res.statusCode = 500;
|
||||
res.write("Bad request"); //write a response to the client
|
||||
res.end(); //end the response
|
||||
}
|
||||
}
|
||||
1302
server/public/assets/admin/authenticated/js/main.js
Normal file
37
server/public/assets/admin/not_authenticated/js/main.js
Normal file
@@ -0,0 +1,37 @@
|
||||
window.addEventListener("DOMContentLoaded", function() {
|
||||
document
|
||||
.getElementById("login_button")
|
||||
.addEventListener("click", function(event) {
|
||||
event.preventDefault();
|
||||
document.querySelector("#login_form").submit();
|
||||
});
|
||||
|
||||
document
|
||||
.getElementById("login_form")
|
||||
.addEventListener("submit", function(event) {
|
||||
if (this.password.value == "" || this.username.value == "") {
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
if (
|
||||
window.location.pathname == "/signup/" ||
|
||||
window.location.pathname == "/signup"
|
||||
) {
|
||||
document
|
||||
.querySelector("#login_form")
|
||||
.insertAdjacentHTML(
|
||||
"afterbegin",
|
||||
"<input type='text' name='token' placeholder='Token' required autocomplete='off' />"
|
||||
);
|
||||
document.querySelector("#login_form").setAttribute("action", "/signup");
|
||||
}
|
||||
if (window.location.hash == "#failed") {
|
||||
window.location.hash = "";
|
||||
M.toast({
|
||||
html: "Couldn't find a user with that username or password..",
|
||||
displayLength: 4000,
|
||||
classes: "red lighten"
|
||||
});
|
||||
}
|
||||
});
|
||||
63
server/public/assets/css/animations.css
Normal file
@@ -0,0 +1,63 @@
|
||||
@keyframes snow {
|
||||
0% {
|
||||
background-position: 0px 0px, 0px 0px, 0px 0px;
|
||||
}
|
||||
100% {
|
||||
background-position: 500px 500px, 400px 400px, 300px 300px;
|
||||
}
|
||||
}
|
||||
@-moz-keyframes snow {
|
||||
0% {
|
||||
background-position: 0px 0px, 0px 0px, 0px 0px;
|
||||
}
|
||||
100% {
|
||||
background-position: 500px 500px, 400px 400px, 300px 300px;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes snow {
|
||||
0% {
|
||||
background-position: 0px 0px, 0px 0px, 0px 0px;
|
||||
}
|
||||
100% {
|
||||
background-position: 500px 500px, 400px 400px, 300px 300px;
|
||||
}
|
||||
}
|
||||
@-ms-keyframes snow {
|
||||
0% {
|
||||
background-position: 0px 0px, 0px 0px, 0px 0px;
|
||||
}
|
||||
100% {
|
||||
background-position: 500px 500px, 400px 400px, 300px 300px;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
* Source: https://codepen.io/NickyCDK/pen/AIonk
|
||||
*
|
||||
*/
|
||||
|
||||
#snow {
|
||||
pointer-events: none;
|
||||
background: none;
|
||||
font-family: Androgyne;
|
||||
background-image: url("/assets/images/s1.png"), url("/assets/images/s2.png"),
|
||||
url("/assets/images/s3.png");
|
||||
height: 100%;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
z-index: 1;
|
||||
-webkit-animation: snow 10s linear infinite;
|
||||
-moz-animation: snow 10s linear infinite;
|
||||
-ms-animation: snow 10s linear infinite;
|
||||
animation: snow 10s linear infinite;
|
||||
}
|
||||
|
||||
#snow.snow-channel {
|
||||
z-index: 9999;
|
||||
width: calc(100% - 0.75rem);
|
||||
height: calc(100% - 32px);
|
||||
}
|
||||
716
server/public/assets/css/embed.css
Executable file
@@ -0,0 +1,716 @@
|
||||
.card-image {
|
||||
height: 100px;
|
||||
width: 100px;
|
||||
background-position: center;
|
||||
background-size: 180%;
|
||||
height: 100% !important;
|
||||
}
|
||||
|
||||
.side_away {
|
||||
-webkit-transition: all 0.3s !important;
|
||||
-moz-transition: all 0.3s !important;
|
||||
-o-transition: all 0.3s !important;
|
||||
transition: all 0.3s !important;
|
||||
}
|
||||
|
||||
.prev.playbar,
|
||||
.skip.playbar {
|
||||
float: left;
|
||||
font-size: 24px;
|
||||
cursor: pointer;
|
||||
height: 32px;
|
||||
line-height: 31px;
|
||||
padding-top: 3px;
|
||||
}
|
||||
|
||||
.site_loader {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
margin: auto;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 9;
|
||||
}
|
||||
|
||||
.prev,
|
||||
.skip {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#playpause,
|
||||
.prev.playbar,
|
||||
.skip.playbar {
|
||||
padding: 0 2.5px;
|
||||
}
|
||||
.playbar-btn:hover {
|
||||
background-color: rgba(0, 0, 0, 0.6);
|
||||
color: hsla(0, 0%, 100%, 0.5);
|
||||
}
|
||||
|
||||
.hide {
|
||||
display: none !important;
|
||||
}
|
||||
.playbar-btn {
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
#controls,
|
||||
.playbar {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
#player_loader_container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#player_overlay {
|
||||
position: relative;
|
||||
height: calc(100% - 32px);
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
width: 60vw;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.soundcloud_info_container {
|
||||
position: absolute;
|
||||
bottom: 20px;
|
||||
right: 0px;
|
||||
padding-left: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
}
|
||||
|
||||
.soundcloud_info_container a {
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
.card {
|
||||
cursor: pointer;
|
||||
background-color: rgba(255, 255, 255, 0.04) !important;
|
||||
}
|
||||
|
||||
#empty-channel-message {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
color: white;
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
.noselect {
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.video_only {
|
||||
width: 100vw !important;
|
||||
height: 100vh !important;
|
||||
}
|
||||
|
||||
#player {
|
||||
width: 60vw;
|
||||
height: calc(100vh - 32px);
|
||||
padding-top: 51px;
|
||||
}
|
||||
|
||||
#pageButtons {
|
||||
text-align: center;
|
||||
padding-top: 15px;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.prev_page,
|
||||
.next_page {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#wrapper {
|
||||
height: calc(100% - 46px);
|
||||
}
|
||||
|
||||
.prev_page_hide,
|
||||
.next_page_hide {
|
||||
visibility: visible !important;
|
||||
color: gray;
|
||||
}
|
||||
|
||||
.list-song {
|
||||
background-color: rgba(255, 255, 255, 0.04) !important;
|
||||
}
|
||||
|
||||
#list-song-html {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#song-title {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#zoffchannel {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.list-image,
|
||||
.list-suggested-image {
|
||||
width: 34%;
|
||||
height: 66px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.list-image:after {
|
||||
-webkit-transition: all 0.3s;
|
||||
transition: all 0.3s;
|
||||
font-family: "Material Icons";
|
||||
content: "thumb_up";
|
||||
speak: none;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-variant: normal;
|
||||
text-transform: none;
|
||||
text-rendering: auto;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
color: white;
|
||||
font-size: -webkit-xxx-large;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
opacity: 0;
|
||||
/* transition: all .1s ease; */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.list-suggested-image:after {
|
||||
font-family: "Material-Design-Icons";
|
||||
speak: none;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-variant: normal;
|
||||
text-transform: none;
|
||||
text-rendering: auto;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
content: "\e625"; /*"\e800";*/
|
||||
color: white;
|
||||
font-size: 65px;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
opacity: 0;
|
||||
transition: all 0.1s ease;
|
||||
}
|
||||
|
||||
.vote-container:hover .list-image:after,
|
||||
.add-suggested:hover .list-suggested-image:after {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.vote-span {
|
||||
opacity: 0.7;
|
||||
padding: 0 0 0 10px;
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.list-song {
|
||||
background-color: rgba(255, 255, 255, 0.04);
|
||||
color: white;
|
||||
font: 12px Arial, sans-serif;
|
||||
-webkit-transition: height 0.3s;
|
||||
-moz-transition: height 0.3s;
|
||||
-o-transition: height 0.3s;
|
||||
transition: height 0.3s;
|
||||
height: 66px;
|
||||
width: 100%;
|
||||
}
|
||||
.list-song .card-content {
|
||||
padding: 0;
|
||||
}
|
||||
.list-title {
|
||||
font-size: 13px !important;
|
||||
display: block;
|
||||
color: white;
|
||||
font-size: 1em;
|
||||
text-align: left;
|
||||
padding: 0 10px 0 10px;
|
||||
line-height: 2.6rem;
|
||||
}
|
||||
.card-image {
|
||||
cursor: pointer;
|
||||
}
|
||||
.card {
|
||||
margin: 2.5px 0 2.5px 0 !important;
|
||||
}
|
||||
.card:hover {
|
||||
box-shadow: 0 5px 5px 0 rgba(0, 0, 0, 0.16), 0 5px 10px 0 rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
#playlist {
|
||||
height: 100vh;
|
||||
width: 40vw;
|
||||
overflow: hidden;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
padding-top: 5px;
|
||||
}
|
||||
|
||||
#zoffbutton {
|
||||
cursor: pointer;
|
||||
background-image: url(/assets/images/z.svg);
|
||||
width: 90px;
|
||||
height: 50px;
|
||||
background-position: 50%;
|
||||
background-size: 85%;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.progress {
|
||||
background-color: rgba(0, 0, 0, 0) !important;
|
||||
}
|
||||
|
||||
.indeterminate {
|
||||
background-color: white !important;
|
||||
}
|
||||
|
||||
#controls {
|
||||
background: inherit;
|
||||
|
||||
position: relative;
|
||||
opacity: 0;
|
||||
height: 32px;
|
||||
width: 60vw;
|
||||
color: white;
|
||||
margin-top: -5px;
|
||||
}
|
||||
|
||||
#playpause,
|
||||
#duration,
|
||||
#volume-button {
|
||||
float: left;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.margin-playbar {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
#seekToDuration {
|
||||
position: absolute;
|
||||
background: #2d2d2d;
|
||||
color: white;
|
||||
padding: 10px 8px;
|
||||
z-index: 2000;
|
||||
background-color: #2d2d2d;
|
||||
border-radius: 2px;
|
||||
color: #fff;
|
||||
min-height: 36px;
|
||||
text-align: center;
|
||||
max-width: calc(100% - 4px);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#playpause,
|
||||
#volume-button {
|
||||
font-size: 23px;
|
||||
}
|
||||
|
||||
#playpause:hover,
|
||||
#volume-button:hover,
|
||||
#fullscreen:hover {
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
#fullscreen {
|
||||
float: right;
|
||||
color: white;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
#duration,
|
||||
#viewers {
|
||||
margin-top: 5px;
|
||||
font-family: "Roboto", sans-serif;
|
||||
font-weight: 300;
|
||||
margin-left: 15px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.channel-info-container {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
position: absolute;
|
||||
bottom: 50px;
|
||||
left: 0px;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
padding-left: 5px;
|
||||
padding-right: 25px;
|
||||
}
|
||||
|
||||
.channel-title {
|
||||
margin-left: -20px;
|
||||
}
|
||||
|
||||
#viewers {
|
||||
float: right;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#play,
|
||||
#pause,
|
||||
#volume-button,
|
||||
#fullscreen {
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.ui-slider-vertical {
|
||||
width: 0.8em;
|
||||
height: 100px;
|
||||
}
|
||||
.ui-slider {
|
||||
position: relative;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.ui-slider-vertical .ui-slider-range-min {
|
||||
bottom: 0;
|
||||
}
|
||||
.ui-slider-vertical .ui-slider-range {
|
||||
left: 0;
|
||||
width: 100%;
|
||||
border-radius: 0px !important;
|
||||
}
|
||||
.ui-slider .ui-slider-range {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
font-size: 0.7em;
|
||||
display: block;
|
||||
border: 0;
|
||||
background-position: 0 0;
|
||||
}
|
||||
|
||||
.ui-slider-vertical .ui-slider-handle {
|
||||
left: -0.3em;
|
||||
margin-left: 0;
|
||||
margin-bottom: -0.6em;
|
||||
}
|
||||
.ui-slider .ui-slider-handle {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
width: 1.2em;
|
||||
height: 1.2em;
|
||||
cursor: default;
|
||||
-ms-touch-action: none;
|
||||
touch-action: none;
|
||||
}
|
||||
|
||||
.ui-slider-horizontal .ui-slider-range-min {
|
||||
left: 0;
|
||||
}
|
||||
.ui-slider-horizontal .ui-slider-range {
|
||||
top: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.ui-slider .ui-slider-range {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
font-size: 0.7em;
|
||||
display: block;
|
||||
border: 0;
|
||||
background-position: 0 0;
|
||||
}
|
||||
|
||||
.ui-slider-horizontal .ui-slider-handle {
|
||||
top: -0.3em;
|
||||
margin-left: -0.6em;
|
||||
}
|
||||
#volume {
|
||||
border-radius: 10px;
|
||||
cursor: pointer;
|
||||
float: left;
|
||||
position: relative;
|
||||
left: 10px;
|
||||
margin: 13px auto;
|
||||
height: 5px;
|
||||
width: 75px;
|
||||
/*background-color:rgba(0, 0, 0, 0.5);*/
|
||||
background: rgba(0, 0, 0, 0.5) 50% 50% repeat-x;
|
||||
border: none;
|
||||
outline: none;
|
||||
/*border-radius: 2px;*/
|
||||
}
|
||||
|
||||
#volume.vertical {
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
#volume .volume-slid {
|
||||
border-radius: 10px;
|
||||
background: white;
|
||||
height: 5px;
|
||||
width: 0%;
|
||||
}
|
||||
|
||||
#volume .volume-slid.vertical {
|
||||
width: 100%;
|
||||
height: 0%;
|
||||
border-radius: 0px;
|
||||
bottom: 0px;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
#volume .volume-handle {
|
||||
height: 15px;
|
||||
width: 15px;
|
||||
background: white;
|
||||
border-radius: 15px;
|
||||
border: 1px solid lightgrey;
|
||||
margin-top: -9.75px;
|
||||
position: absolute;
|
||||
left: 0%;
|
||||
margin-left: -5.75px;
|
||||
transition: background 0.2s ease, box-shadow 0.2s ease;
|
||||
}
|
||||
|
||||
#volume .volume-handle.vertical {
|
||||
bottom: 0%;
|
||||
display: none;
|
||||
}
|
||||
#volume .volume-handle.ui-state-active {
|
||||
box-shadow: 0 1px 3px 1px rgba(0, 0, 0, 0.01),
|
||||
0 0 0 7px rgba(255, 255, 255, 0.3);
|
||||
position: absolute;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
border-radius: 21px;
|
||||
background: #dadada;
|
||||
}
|
||||
|
||||
#toast-container {
|
||||
left: 2%;
|
||||
cursor: pointer;
|
||||
width: 70vw;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: baseline;
|
||||
/*pointer-events:none;*/
|
||||
}
|
||||
|
||||
.toast {
|
||||
word-break: normal;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.play {
|
||||
background-size: auto;
|
||||
width: 55px;
|
||||
height: 27px;
|
||||
}
|
||||
|
||||
.pause {
|
||||
background-size: auto;
|
||||
width: 55px;
|
||||
height: 27px;
|
||||
}
|
||||
|
||||
.hide {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
#bar {
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
html {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#pageButtons {
|
||||
background: inherit;
|
||||
}
|
||||
|
||||
#pageButtons,
|
||||
#pageButtons a {
|
||||
color: white !important;
|
||||
width: 100%;
|
||||
justify-content: space-evenly;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#pageButtons a,
|
||||
#pageButtons span {
|
||||
padding-left: 1px;
|
||||
padding-right: 1px;
|
||||
}
|
||||
|
||||
#pageNumber {
|
||||
cursor: default;
|
||||
color: white;
|
||||
padding: 0;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
height: 36px;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.prev_page,
|
||||
.next_page,
|
||||
.last_page,
|
||||
.first_page {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.prev_page_hide,
|
||||
.next_page_hide,
|
||||
.last_page_hide,
|
||||
.first_page_hide {
|
||||
visibility: visible !important;
|
||||
color: gray;
|
||||
cursor: default;
|
||||
height: 32px;
|
||||
line-height: 36px;
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.prev_page_hide,
|
||||
.prev_page,
|
||||
.first_page,
|
||||
.first_page_hide {
|
||||
padding: 0 1px;
|
||||
height: 32px;
|
||||
line-height: 36px;
|
||||
}
|
||||
|
||||
.next_page_hide,
|
||||
.next_page,
|
||||
.last_page,
|
||||
.last_page_hide {
|
||||
padding: 0 0px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.first_page,
|
||||
.first_page_hide {
|
||||
padding: 0 0 0 10px;
|
||||
}
|
||||
|
||||
.last_page,
|
||||
.last_page_hide {
|
||||
padding: 0 10px 0 0;
|
||||
}
|
||||
|
||||
body {
|
||||
background: #2d2d2d;
|
||||
}
|
||||
|
||||
.vote-container {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.card-duration {
|
||||
border-top-right-radius: 4px;
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
color: white;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
#song-title {
|
||||
position: absolute;
|
||||
z-index: 9;
|
||||
color: white;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
font-size: 1.5rem;
|
||||
padding: 10px;
|
||||
width: 60vw;
|
||||
}
|
||||
|
||||
/*
|
||||
.last_page, .last_page_hide, .first_page, .first_page_hide{
|
||||
display: none !important;
|
||||
}
|
||||
*/
|
||||
#wrapper {
|
||||
background: inherit;
|
||||
/*height: 94%;*/
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 992px) and (min-width: 601px) {
|
||||
#toast-container {
|
||||
bottom: 90px;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 736px) and (max-width: 500px),
|
||||
only screen and (max-device-width: 736px) and (orientation: landscape) {
|
||||
#player-container {
|
||||
/*display: none;*/
|
||||
position: absolute;
|
||||
width: 100vw;
|
||||
height: 200px;
|
||||
bottom: 0px;
|
||||
}
|
||||
#controls {
|
||||
width: 100vw;
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
#player {
|
||||
width: 100vw;
|
||||
height: 170px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
#player_overlay {
|
||||
position: relative;
|
||||
width: 100vw;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
#playlist {
|
||||
width: 100vw;
|
||||
height: calc(100vh - 208px);
|
||||
}
|
||||
|
||||
#toast-container {
|
||||
min-width: 96%;
|
||||
bottom: auto;
|
||||
}
|
||||
|
||||
#song-title {
|
||||
width: 100vw;
|
||||
font-size: 1.2rem;
|
||||
top: calc(100vh - 200px);
|
||||
}
|
||||
}
|
||||
58
server/public/assets/css/globals.css
Normal file
@@ -0,0 +1,58 @@
|
||||
.material-icons {
|
||||
display: none;
|
||||
width: 24px;
|
||||
}
|
||||
|
||||
html {
|
||||
background: #2d2d2d;
|
||||
}
|
||||
|
||||
body {
|
||||
background: white;
|
||||
}
|
||||
|
||||
a {
|
||||
outline: 0 !important;
|
||||
}
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
min-height: 100vh;
|
||||
flex-direction: column;
|
||||
overflow-x: hidden;
|
||||
-webkit-transition: background-color 1s;
|
||||
-moz-transition: background-color 1s;
|
||||
-ms-transition: background-color 1s;
|
||||
-o-transition: background-color 1s;
|
||||
transition: background-color 1s;
|
||||
overflow-y: scroll !important;
|
||||
}
|
||||
|
||||
input[type="text"]:focus:not([readonly]),
|
||||
input[type="password"]:focus:not([readonly]),
|
||||
input[type="email"]:focus:not([readonly]),
|
||||
input[type="url"]:focus:not([readonly]),
|
||||
input[type="time"]:focus:not([readonly]),
|
||||
input[type="date"]:focus:not([readonly]),
|
||||
input[type="datetime-local"]:focus:not([readonly]),
|
||||
input[type="tel"]:focus:not([readonly]),
|
||||
input[type="number"]:focus:not([readonly]),
|
||||
input[type="search"]:focus:not([readonly]),
|
||||
textarea.materialize-textarea:focus:not([readonly]) {
|
||||
border-bottom: 1px solid #9d9d9d;
|
||||
box-shadow: 0 1px 0 0 #9d9d9d;
|
||||
}
|
||||
|
||||
nav ul li:hover,
|
||||
nav ul li.active {
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.full-height {
|
||||
height:100vh;
|
||||
}
|
||||
|
||||
* {
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
-moz-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
858
server/public/assets/css/mobile.css
Normal file
@@ -0,0 +1,858 @@
|
||||
@media only screen and (min-width: 993px) {
|
||||
.toast {
|
||||
float: left;
|
||||
}
|
||||
|
||||
nav .zbrand {
|
||||
left: 0px !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (-webkit-min-device-pixel-ratio: 0) {
|
||||
#wrapper {
|
||||
padding-right: 0vh !important;
|
||||
width: 100% !important;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 992px) {
|
||||
nav .brand-logo {
|
||||
left: 0%;
|
||||
transform: translateX(0%);
|
||||
-webkit-transform: translateX(0%);
|
||||
padding-left: 0px;
|
||||
}
|
||||
|
||||
.zbrand {
|
||||
/*max-width: 35%;*/
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 600px),
|
||||
(min-width: 961px),
|
||||
(min-width: 1025px),
|
||||
(min-width: 1281px) {
|
||||
#controls {
|
||||
background: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 736px) and (max-width: 600px),
|
||||
only screen and (max-device-width: 736px) and (orientation: landscape) {
|
||||
.autocomplete-content.dropdown-content {
|
||||
width: 95vw !important;
|
||||
}
|
||||
|
||||
.mobile-overflow {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.footer-buttons,
|
||||
.footer-buttons li a {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#main-row {
|
||||
margin-right: -3px !important;
|
||||
background: inherit;
|
||||
}
|
||||
|
||||
.admin_panel {
|
||||
margin-top: 25px !important;
|
||||
}
|
||||
|
||||
#suggestions {
|
||||
height: auto !important;
|
||||
/*padding-bottom: 0px;*/
|
||||
}
|
||||
|
||||
.margin-playbar {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
#chat-container {
|
||||
height: calc(100vh - 48px - 64px - 120px);
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
|
||||
#player_bottom_overlay {
|
||||
top: 7px;
|
||||
}
|
||||
|
||||
.mobile-delete {
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 60px;
|
||||
top: 0px;
|
||||
right: -60px;
|
||||
/* overflow: visible; */
|
||||
z-index: -99999999;
|
||||
}
|
||||
|
||||
#main-container {
|
||||
/*padding-bottom: 20px;*/
|
||||
}
|
||||
|
||||
#fireplace_player {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.addedJoinBox {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#playbar {
|
||||
display: block;
|
||||
position: fixed;
|
||||
bottom: 0px;
|
||||
z-index: 1000;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.list-title {
|
||||
width: 66%;
|
||||
}
|
||||
|
||||
.hamburger-sidenav {
|
||||
margin: 20px 10px 12px 10px;
|
||||
}
|
||||
|
||||
#main_section_frontpage {
|
||||
margin-top: -20px;
|
||||
padding-top: 0px;
|
||||
}
|
||||
|
||||
.delete_button,
|
||||
.del_suggested,
|
||||
.del_user_suggested {
|
||||
bottom: -9px;
|
||||
/* line-height: inherit; */
|
||||
height: auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-top: none;
|
||||
padding: 0px !important;
|
||||
margin: 0px !important;
|
||||
}
|
||||
|
||||
.vote-container:hover .list-image:after,
|
||||
.add-suggested:hover .list-suggested-image:after {
|
||||
opacity: 1;
|
||||
content: "thumb_up";
|
||||
}
|
||||
|
||||
.list-image:after,
|
||||
.list-suggested-image:after {
|
||||
content: none;
|
||||
}
|
||||
|
||||
.delete_button .material-icons,
|
||||
.del_suggested .material-icons,
|
||||
.del_user_suggested .material-icons {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
|
||||
#remote-sidebar-buttons-container {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.slider-vol-mobile {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
#frontpage-viewer-counter {
|
||||
right: 56px;
|
||||
width: 62px;
|
||||
left: inherit;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.brand-logo {
|
||||
left: 0 !important;
|
||||
padding-left: 0px !important;
|
||||
-webkit-transform: translateX(0%) !important;
|
||||
-moz-transform: translateX(0%) !important;
|
||||
-ms-transform: translateX(0%) !important;
|
||||
-o-transform: translateX(0%) !important;
|
||||
transform: translateX(0%) !important;
|
||||
}
|
||||
|
||||
#player_overlay {
|
||||
height: calc(30vh);
|
||||
bottom: -33px !important;
|
||||
top: 7px;
|
||||
width: 100vw;
|
||||
height: 200px;
|
||||
pointer-events: all;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#wrapper {
|
||||
min-height: 75px;
|
||||
}
|
||||
|
||||
.click-through {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.zicon {
|
||||
height: 100%;
|
||||
}
|
||||
/*.list-remove{
|
||||
margin-top:-68px;
|
||||
}*/
|
||||
|
||||
#settings-bar {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
#remote-mobile-container {
|
||||
margin-left: -7px;
|
||||
}
|
||||
|
||||
#remote_channel {
|
||||
color: #2d2d2d;
|
||||
/*width:90%;*/
|
||||
}
|
||||
.show-only-mobile {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#volume-control-remote {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#remote_header {
|
||||
color: #2d2d2d;
|
||||
font-size: 1.5em;
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#all_chat,
|
||||
#channelchat {
|
||||
height: calc(100vh - 352px);
|
||||
}
|
||||
|
||||
#fp-nav {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#search-wrapper {
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
#search-wrapper:hover,
|
||||
#song-title:hover {
|
||||
/*background: inherit;*/
|
||||
}
|
||||
|
||||
#toast-container {
|
||||
left: 0% !important;
|
||||
width: 100vw;
|
||||
bottom: 55px;
|
||||
}
|
||||
|
||||
.empty-inner-results {
|
||||
height: 100vh !important;
|
||||
}
|
||||
|
||||
#empty-results {
|
||||
height: calc(100vh - 112px);
|
||||
}
|
||||
|
||||
.search_input {
|
||||
padding-right: 50px;
|
||||
width: calc(100vw - 78px);
|
||||
}
|
||||
|
||||
.playlist-tabs-loggedIn,
|
||||
.playlist-tabs {
|
||||
width: calc(100%) !important;
|
||||
}
|
||||
|
||||
#wrapper.tabs_height {
|
||||
height: calc(100vh - 48px - 64px - 134px);
|
||||
overflow: initial;
|
||||
}
|
||||
|
||||
.client-wrapper {
|
||||
height: calc(100vh - 48px - 64px - 36px) !important;
|
||||
}
|
||||
|
||||
/*.client-results-height {
|
||||
margin-top: 50px !important;
|
||||
}*/
|
||||
|
||||
.client-pagination-height {
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
.brand-mobile {
|
||||
padding-left: 0px !important;
|
||||
}
|
||||
|
||||
#player {
|
||||
height: calc(100%);
|
||||
display: none;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.pointer-events-all-mobile {
|
||||
pointer-events: all !important;
|
||||
}
|
||||
|
||||
.small-display {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.small-display-hide {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.hide-on-small-only {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#controls {
|
||||
/*opacity: 1;*/
|
||||
overflow: initial;
|
||||
background-color: rgb(70, 70, 70);
|
||||
height: 50px;
|
||||
margin-top: inherit;
|
||||
bottom: 0px;
|
||||
position: fixed;
|
||||
pointer-events: all;
|
||||
-webkit-transition: background-color 0.5s ease;
|
||||
-moz-transition: background-color 0.5s ease;
|
||||
-o-transition: background-color 0.5s ease;
|
||||
transition: background-color 0.5s ease;
|
||||
}
|
||||
|
||||
#chat-container {
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
#play,
|
||||
#pause,
|
||||
#volume-button i,
|
||||
#fullscreen i,
|
||||
.castButton-unactive i,
|
||||
.castButton-active i,
|
||||
.playbar-btn i {
|
||||
font-size: 31px;
|
||||
font-size: 31px !important;
|
||||
margin-top: 8px;
|
||||
line-height: 31px;
|
||||
}
|
||||
|
||||
.skip.playbar,
|
||||
.prev.playbar,
|
||||
#playpause {
|
||||
padding-top: 0px;
|
||||
height: 51px;
|
||||
}
|
||||
|
||||
.castButton-unactive,
|
||||
.castButton-active {
|
||||
margin-right: 10px;
|
||||
padding-right: 10px;
|
||||
padding-left: 0px;
|
||||
}
|
||||
|
||||
/*#volume{
|
||||
display: none;
|
||||
}*/
|
||||
|
||||
.volume-container {
|
||||
position: absolute;
|
||||
right: 0%;
|
||||
width: 37px;
|
||||
top: -127px;
|
||||
height: 127px;
|
||||
left: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: inherit;
|
||||
}
|
||||
|
||||
.volume-container-cast {
|
||||
right: 39px;
|
||||
}
|
||||
|
||||
#volume {
|
||||
width: 10px;
|
||||
height: 100px;
|
||||
left: 0px;
|
||||
}
|
||||
|
||||
.ui-widget-header {
|
||||
background: rgb(255, 255, 255);
|
||||
}
|
||||
|
||||
#viewers {
|
||||
margin-top: 8px;
|
||||
font-size: 20px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.footer-copyright {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#duration {
|
||||
font-size: 20px;
|
||||
font-weight: 400;
|
||||
margin-top: 9px;
|
||||
letter-spacing: -0.7px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
#volume-button {
|
||||
float: right;
|
||||
/* margin-right: 5px; */
|
||||
padding-right: 3px;
|
||||
margin-left: 0px;
|
||||
padding-left: 3px;
|
||||
height: 51px;
|
||||
padding-top: 0px;
|
||||
width: 37px;
|
||||
}
|
||||
|
||||
#fullscreen {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.castButton {
|
||||
width: 39px;
|
||||
height: 51px;
|
||||
padding-top: 0em;
|
||||
}
|
||||
|
||||
.label-for-mobile-frontpage {
|
||||
display: initial;
|
||||
width: auto !important;
|
||||
margin-left: auto !important;
|
||||
}
|
||||
|
||||
.mega {
|
||||
background: white;
|
||||
}
|
||||
#bar {
|
||||
background-color: rgba(0, 0, 0, 1);
|
||||
}
|
||||
|
||||
.channel-finder .input-field {
|
||||
padding: 0 0.75rem;
|
||||
}
|
||||
|
||||
.mega form {
|
||||
display: block;
|
||||
width: auto;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.mega input {
|
||||
color: black;
|
||||
text-shadow: none;
|
||||
margin-left: 0px !important;
|
||||
padding-left: 0px !important;
|
||||
}
|
||||
|
||||
.room-namer.autocomplete {
|
||||
margin-left: 0px !important;
|
||||
margin-top: auto !important;
|
||||
}
|
||||
|
||||
#channel-share-modal {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#autocomplete-input {
|
||||
width: 100%;
|
||||
border-bottom: 1px solid #9e9e9e !important;
|
||||
}
|
||||
|
||||
#autocomplete-input::-webkit-input-placeholder {
|
||||
/* WebKit browsers */
|
||||
color: #fff;
|
||||
}
|
||||
#autocomplete-input:-moz-placeholder {
|
||||
/* Mozilla Firefox 4 to 18 */
|
||||
color: #fff;
|
||||
opacity: 1;
|
||||
}
|
||||
#autocomplete-input::-moz-placeholder {
|
||||
/* Mozilla Firefox 19+ */
|
||||
color: #fff;
|
||||
opacity: 1;
|
||||
}
|
||||
#autocomplete-input:-ms-input-placeholder {
|
||||
/* Internet Explorer 10+ */
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.room-namer::-webkit-input-placeholder {
|
||||
/*color:rgb(155, 155, 155) !important;*/
|
||||
-webkit-transition: opacity 0.5s;
|
||||
color: transparent !important;
|
||||
}
|
||||
|
||||
#mega-background,
|
||||
.mega h5,
|
||||
#snow,
|
||||
.pitch,
|
||||
.channel-finder .input-field .prefix,
|
||||
.listen-button {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.channel-finder .input-field {
|
||||
display: initial;
|
||||
/* width: 69%; */
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/*.mega {display:none;}*/
|
||||
.mobile-search {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.toast {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.remote-panel {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.navbar-fixed,
|
||||
#nav {
|
||||
/*position: relative;*/
|
||||
}
|
||||
|
||||
.navbar-fixed {
|
||||
height: 100px;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
.control-list {
|
||||
position: absolute !important;
|
||||
/*width: 120px;*/
|
||||
}
|
||||
|
||||
.client-control-list {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.page-footer {
|
||||
padding-top: 40px !important;
|
||||
}
|
||||
|
||||
.padding-bottom-novideo {
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
|
||||
.padding-bottom-extra {
|
||||
padding-bottom: 210px;
|
||||
}
|
||||
|
||||
.main,
|
||||
#main-row,
|
||||
.video-container,
|
||||
#playlist {
|
||||
height: auto !important;
|
||||
margin-bottom: 2px;
|
||||
margin-top: -6px;
|
||||
}
|
||||
|
||||
.main {
|
||||
max-width: 99%;
|
||||
background: inherit;
|
||||
}
|
||||
|
||||
#pageButtons {
|
||||
margin-left: -11px;
|
||||
width: 100vw;
|
||||
position: relative;
|
||||
padding-bottom: 3px;
|
||||
}
|
||||
|
||||
#search_loader {
|
||||
height: 56px;
|
||||
}
|
||||
|
||||
#playlist {
|
||||
/*margin-left: 10px;*/
|
||||
background: inherit;
|
||||
width: calc(100% - 10px);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#player {
|
||||
pointer-events: none;
|
||||
margin-top: 7px;
|
||||
}
|
||||
|
||||
.search-container,
|
||||
.song-title {
|
||||
background: inherit;
|
||||
}
|
||||
|
||||
.row .col.s12 {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
#main-row.row #video-container.video-container {
|
||||
position: fixed;
|
||||
display: block !important;
|
||||
width: 106vw !important;
|
||||
height: 200px !important;
|
||||
z-index: 10;
|
||||
bottom: 55px;
|
||||
}
|
||||
|
||||
#video-container.video-container.frontpage-player {
|
||||
width: auto !important;
|
||||
}
|
||||
|
||||
.chan {
|
||||
text-shadow: 0px 0px 0px rgba(0, 0, 0, 0.42);
|
||||
width: calc(100vw - 170px) !important;
|
||||
max-width: calc(100% - 87.5px - 130px);
|
||||
font-size: 2rem;
|
||||
padding-right: 0px;
|
||||
overflow: hidden;
|
||||
/* display: block; */
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.chan-client {
|
||||
max-width: calc(100% - 87.5px - 170px);
|
||||
}
|
||||
|
||||
.control-list li a {
|
||||
min-width: 0px;
|
||||
width: 37px;
|
||||
padding: 0 0 0 0px;
|
||||
}
|
||||
|
||||
nav .zbrand {
|
||||
-webkit-transform: initial;
|
||||
transform: initial;
|
||||
display: flex;
|
||||
max-width: initial;
|
||||
width: 100vw;
|
||||
-webkit-box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14),
|
||||
0 1px 5px 0 rgba(0, 0, 0, 0.12), 0 3px 1px -2px rgba(0, 0, 0, 0.2);
|
||||
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12),
|
||||
0 3px 1px -2px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.title-container {
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
display: block;
|
||||
top: 56px !important;
|
||||
width: 100vw;
|
||||
background: #2d2d2d;
|
||||
}
|
||||
.title-container li {
|
||||
/*width: 100%;*/
|
||||
}
|
||||
|
||||
#inner-results {
|
||||
height: calc(100vh - 54px - 64px - 123px);
|
||||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.thumb-and-info {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.result_info {
|
||||
opacity: 0.8;
|
||||
margin-top: 0px;
|
||||
height: 21px;
|
||||
margin-right: 0px;
|
||||
padding: 0px;
|
||||
line-height: initial;
|
||||
border-top-right-radius: 3px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 55px;
|
||||
margin-left: 10px;
|
||||
margin-top: -16px;
|
||||
}
|
||||
|
||||
.search_results {
|
||||
margin-top: 45px;
|
||||
background: #000;
|
||||
}
|
||||
|
||||
.results-tabs .indicator {
|
||||
margin-top: 50px;
|
||||
}
|
||||
|
||||
#results,
|
||||
#results_soundcloud {
|
||||
background-color: #000;
|
||||
margin-top: -8px;
|
||||
}
|
||||
|
||||
#results {
|
||||
max-height: calc(100vh - 165px);
|
||||
}
|
||||
|
||||
#results_soundcloud {
|
||||
height: calc(100vh - 64px - 54px);
|
||||
}
|
||||
|
||||
#results_soundcloud #inner-results {
|
||||
height: calc(100vh - 54px - 64px - 47px);
|
||||
}
|
||||
|
||||
.result {
|
||||
margin: 0;
|
||||
width: 99%;
|
||||
}
|
||||
|
||||
.result-get-more-info {
|
||||
background: black;
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 45px;
|
||||
}
|
||||
|
||||
.result-info-no-buttons {
|
||||
width: calc(100% - 200px);
|
||||
}
|
||||
|
||||
.result-object {
|
||||
-webkit-transform: translateX(0%);
|
||||
transform: translateX(0%);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.result {
|
||||
-webkit-transition: margin 0.5s;
|
||||
-moz-transition: margin 0.5s;
|
||||
transition: margin 0.5s;
|
||||
}
|
||||
|
||||
#user_password {
|
||||
width: 80% !important;
|
||||
}
|
||||
|
||||
#addToListInput {
|
||||
top: -85px;
|
||||
right: 35px;
|
||||
}
|
||||
|
||||
#addToOtherList {
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.result-object-slid {
|
||||
/*-webkit-transform: translateX(calc(-100% + 45px)) !important;
|
||||
transform: translateX(calc(-100% + 45px)) !important;*/
|
||||
margin-left: -94%;
|
||||
}
|
||||
|
||||
.result-start-end-container {
|
||||
/*visibility: hidden;
|
||||
pointer-events: none;*/
|
||||
margin-left: 120%;
|
||||
position: relative;
|
||||
top: -10px;
|
||||
}
|
||||
|
||||
.result-info-buttons {
|
||||
margin-top: 20px;
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
.result .search-title {
|
||||
white-space: nowrap;
|
||||
width: calc(100vw - 165px);
|
||||
margin-top: -5px;
|
||||
z-index: 9999;
|
||||
}
|
||||
.result img {
|
||||
margin: -3px 10px;
|
||||
height: 50px;
|
||||
width: 88.88px;
|
||||
}
|
||||
.result .add-many {
|
||||
margin-top: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-device-width: 736px) and (orientation: landscape) {
|
||||
.video-container {
|
||||
width: 315px !important;
|
||||
/* height: auto !important; */
|
||||
right: -5px;
|
||||
bottom: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 768px) {
|
||||
#results {
|
||||
background-color: #000;
|
||||
/*margin-top:56px;*/
|
||||
}
|
||||
|
||||
.title-container {
|
||||
top: 64px;
|
||||
top: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 769px) {
|
||||
.navbar-fixed {
|
||||
height: 64px;
|
||||
}
|
||||
nav .zbrand {
|
||||
/*display: inline-block;*/
|
||||
/*top:-22px;*/
|
||||
/*left:100px;*/
|
||||
}
|
||||
|
||||
.title-container li {
|
||||
/*width: 71%;*/
|
||||
}
|
||||
|
||||
#wrapper {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
opacity: 1;
|
||||
overflow: hidden;
|
||||
padding-right: 0.5rem !important;
|
||||
}
|
||||
|
||||
#playlist {
|
||||
/*padding:0px 15px;*/
|
||||
height: 90%;
|
||||
height: calc(100vh - 64px);
|
||||
overflow: hidden;
|
||||
padding-right: 0px;
|
||||
/*padding-right: 0px;*/
|
||||
/*padding:0px 0px 0px 0px;*/
|
||||
}
|
||||
}
|
||||
3434
server/public/assets/css/style.css
Executable file
175
server/public/assets/html/callback.html
Executable file
@@ -0,0 +1,175 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Zoff OAuth Callback</title>
|
||||
<script src="https://connect.soundcloud.com/sdk/sdk-3.3.0.js"></script>
|
||||
<script type="text/javascript" src="/assets/dist/callback.min.js"></script>
|
||||
<meta charset="UTF-8" />
|
||||
<style>
|
||||
@-webkit-keyframes uil-ring-anim {
|
||||
0% {
|
||||
-ms-transform: rotate(0deg);
|
||||
-moz-transform: rotate(0deg);
|
||||
-webkit-transform: rotate(0deg);
|
||||
-o-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
-ms-transform: rotate(360deg);
|
||||
-moz-transform: rotate(360deg);
|
||||
-webkit-transform: rotate(360deg);
|
||||
-o-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes uil-ring-anim {
|
||||
0% {
|
||||
-ms-transform: rotate(0deg);
|
||||
-moz-transform: rotate(0deg);
|
||||
-webkit-transform: rotate(0deg);
|
||||
-o-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
-ms-transform: rotate(360deg);
|
||||
-moz-transform: rotate(360deg);
|
||||
-webkit-transform: rotate(360deg);
|
||||
-o-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@-moz-keyframes uil-ring-anim {
|
||||
0% {
|
||||
-ms-transform: rotate(0deg);
|
||||
-moz-transform: rotate(0deg);
|
||||
-webkit-transform: rotate(0deg);
|
||||
-o-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
-ms-transform: rotate(360deg);
|
||||
-moz-transform: rotate(360deg);
|
||||
-webkit-transform: rotate(360deg);
|
||||
-o-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@-ms-keyframes uil-ring-anim {
|
||||
0% {
|
||||
-ms-transform: rotate(0deg);
|
||||
-moz-transform: rotate(0deg);
|
||||
-webkit-transform: rotate(0deg);
|
||||
-o-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
-ms-transform: rotate(360deg);
|
||||
-moz-transform: rotate(360deg);
|
||||
-webkit-transform: rotate(360deg);
|
||||
-o-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@-moz-keyframes uil-ring-anim {
|
||||
0% {
|
||||
-ms-transform: rotate(0deg);
|
||||
-moz-transform: rotate(0deg);
|
||||
-webkit-transform: rotate(0deg);
|
||||
-o-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
-ms-transform: rotate(360deg);
|
||||
-moz-transform: rotate(360deg);
|
||||
-webkit-transform: rotate(360deg);
|
||||
-o-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes uil-ring-anim {
|
||||
0% {
|
||||
-ms-transform: rotate(0deg);
|
||||
-moz-transform: rotate(0deg);
|
||||
-webkit-transform: rotate(0deg);
|
||||
-o-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
-ms-transform: rotate(360deg);
|
||||
-moz-transform: rotate(360deg);
|
||||
-webkit-transform: rotate(360deg);
|
||||
-o-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@-o-keyframes uil-ring-anim {
|
||||
0% {
|
||||
-ms-transform: rotate(0deg);
|
||||
-moz-transform: rotate(0deg);
|
||||
-webkit-transform: rotate(0deg);
|
||||
-o-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
-ms-transform: rotate(360deg);
|
||||
-moz-transform: rotate(360deg);
|
||||
-webkit-transform: rotate(360deg);
|
||||
-o-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@keyframes uil-ring-anim {
|
||||
0% {
|
||||
-ms-transform: rotate(0deg);
|
||||
-moz-transform: rotate(0deg);
|
||||
-webkit-transform: rotate(0deg);
|
||||
-o-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
-ms-transform: rotate(360deg);
|
||||
-moz-transform: rotate(360deg);
|
||||
-webkit-transform: rotate(360deg);
|
||||
-o-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
.uil-ring-css {
|
||||
background: none;
|
||||
width: 190px;
|
||||
height: 190px;
|
||||
transform: scale(1);
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: auto;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
.uil-ring-css > div {
|
||||
position: absolute;
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
border: 20px solid black;
|
||||
border-radius: 50%;
|
||||
border-bottom-color: transparent;
|
||||
border-left-color: transparent;
|
||||
transform: rotate(-45deg);'
|
||||
-ms-animation: uil-ring-anim 1s linear infinite;
|
||||
-moz-animation: uil-ring-anim 1s linear infinite;
|
||||
-webkit-animation: uil-ring-anim 1s linear infinite;
|
||||
-o-animation: uil-ring-anim 1s linear infinite;
|
||||
animation: uil-ring-anim 1s linear infinite;
|
||||
}
|
||||
h4 {
|
||||
text-align: center;
|
||||
font-family: sans-serif;
|
||||
font-size: 2rem;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h4>Loading..</h4>
|
||||
<div class="uil-ring-css"><div></div></div>
|
||||
</body>
|
||||
</html>
|
||||
61
server/public/assets/html/offline.html
Executable file
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
BIN
server/public/assets/images/android-chrome-192x192.png
Normal file
|
After Width: | Height: | Size: 7.2 KiB |
BIN
server/public/assets/images/android-chrome-512x512.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
server/public/assets/images/apple-touch-icon-precomposed.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
server/public/assets/images/apple-touch-icon.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
46
server/public/assets/images/appstore.svg
Executable file
@@ -0,0 +1,46 @@
|
||||
<svg id="livetype" xmlns="http://www.w3.org/2000/svg" width="119.66407" height="40" viewBox="0 0 119.66407 40">
|
||||
<title>Download_on_the_App_Store_Badge_US-UK_RGB_blk_4SVG_092917</title>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<path d="M110.13477,0H9.53468c-.3667,0-.729,0-1.09473.002-.30615.002-.60986.00781-.91895.0127A13.21476,13.21476,0,0,0,5.5171.19141a6.66509,6.66509,0,0,0-1.90088.627A6.43779,6.43779,0,0,0,1.99757,1.99707,6.25844,6.25844,0,0,0,.81935,3.61816a6.60119,6.60119,0,0,0-.625,1.90332,12.993,12.993,0,0,0-.1792,2.002C.00587,7.83008.00489,8.1377,0,8.44434V31.5586c.00489.3105.00587.6113.01515.9219a12.99232,12.99232,0,0,0,.1792,2.0019,6.58756,6.58756,0,0,0,.625,1.9043A6.20778,6.20778,0,0,0,1.99757,38.001a6.27445,6.27445,0,0,0,1.61865,1.1787,6.70082,6.70082,0,0,0,1.90088.6308,13.45514,13.45514,0,0,0,2.0039.1768c.30909.0068.6128.0107.91895.0107C8.80567,40,9.168,40,9.53468,40H110.13477c.3594,0,.7246,0,1.084-.002.3047,0,.6172-.0039.9219-.0107a13.279,13.279,0,0,0,2-.1768,6.80432,6.80432,0,0,0,1.9082-.6308,6.27742,6.27742,0,0,0,1.6172-1.1787,6.39482,6.39482,0,0,0,1.1816-1.6143,6.60413,6.60413,0,0,0,.6191-1.9043,13.50643,13.50643,0,0,0,.1856-2.0019c.0039-.3106.0039-.6114.0039-.9219.0078-.3633.0078-.7246.0078-1.0938V9.53613c0-.36621,0-.72949-.0078-1.09179,0-.30664,0-.61426-.0039-.9209a13.5071,13.5071,0,0,0-.1856-2.002,6.6177,6.6177,0,0,0-.6191-1.90332,6.46619,6.46619,0,0,0-2.7988-2.7998,6.76754,6.76754,0,0,0-1.9082-.627,13.04394,13.04394,0,0,0-2-.17676c-.3047-.00488-.6172-.01074-.9219-.01269-.3594-.002-.7246-.002-1.084-.002Z" style="fill: #a6a6a6"/>
|
||||
<path d="M8.44483,39.125c-.30468,0-.602-.0039-.90429-.0107a12.68714,12.68714,0,0,1-1.86914-.1631,5.88381,5.88381,0,0,1-1.65674-.5479,5.40573,5.40573,0,0,1-1.397-1.0166,5.32082,5.32082,0,0,1-1.02051-1.3965,5.72186,5.72186,0,0,1-.543-1.6572,12.41351,12.41351,0,0,1-.1665-1.875c-.00634-.2109-.01464-.9131-.01464-.9131V8.44434S.88185,7.75293.8877,7.5498a12.37039,12.37039,0,0,1,.16553-1.87207,5.7555,5.7555,0,0,1,.54346-1.6621A5.37349,5.37349,0,0,1,2.61183,2.61768,5.56543,5.56543,0,0,1,4.01417,1.59521a5.82309,5.82309,0,0,1,1.65332-.54394A12.58589,12.58589,0,0,1,7.543.88721L8.44532.875H111.21387l.9131.0127a12.38493,12.38493,0,0,1,1.8584.16259,5.93833,5.93833,0,0,1,1.6709.54785,5.59374,5.59374,0,0,1,2.415,2.41993,5.76267,5.76267,0,0,1,.5352,1.64892,12.995,12.995,0,0,1,.1738,1.88721c.0029.2832.0029.5874.0029.89014.0079.375.0079.73193.0079,1.09179V30.4648c0,.3633,0,.7178-.0079,1.0752,0,.3252,0,.6231-.0039.9297a12.73126,12.73126,0,0,1-.1709,1.8535,5.739,5.739,0,0,1-.54,1.67,5.48029,5.48029,0,0,1-1.0156,1.3857,5.4129,5.4129,0,0,1-1.3994,1.0225,5.86168,5.86168,0,0,1-1.668.5498,12.54218,12.54218,0,0,1-1.8692.1631c-.2929.0068-.5996.0107-.8974.0107l-1.084.002Z"/>
|
||||
</g>
|
||||
<g id="_Group_" data-name="<Group>">
|
||||
<g id="_Group_2" data-name="<Group>">
|
||||
<g id="_Group_3" data-name="<Group>">
|
||||
<path id="_Path_" data-name="<Path>" d="M24.76888,20.30068a4.94881,4.94881,0,0,1,2.35656-4.15206,5.06566,5.06566,0,0,0-3.99116-2.15768c-1.67924-.17626-3.30719,1.00483-4.1629,1.00483-.87227,0-2.18977-.98733-3.6085-.95814a5.31529,5.31529,0,0,0-4.47292,2.72787c-1.934,3.34842-.49141,8.26947,1.3612,10.97608.9269,1.32535,2.01018,2.8058,3.42763,2.7533,1.38706-.05753,1.9051-.88448,3.5794-.88448,1.65876,0,2.14479.88448,3.591.8511,1.48838-.02416,2.42613-1.33124,3.32051-2.66914a10.962,10.962,0,0,0,1.51842-3.09251A4.78205,4.78205,0,0,1,24.76888,20.30068Z" style="fill: #fff"/>
|
||||
<path id="_Path_2" data-name="<Path>" d="M22.03725,12.21089a4.87248,4.87248,0,0,0,1.11452-3.49062,4.95746,4.95746,0,0,0-3.20758,1.65961,4.63634,4.63634,0,0,0-1.14371,3.36139A4.09905,4.09905,0,0,0,22.03725,12.21089Z" style="fill: #fff"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<path d="M42.30227,27.13965h-4.7334l-1.13672,3.35645H34.42727l4.4834-12.418h2.083l4.4834,12.418H43.438ZM38.0591,25.59082h3.752l-1.84961-5.44727h-.05176Z" style="fill: #fff"/>
|
||||
<path d="M55.15969,25.96973c0,2.81348-1.50586,4.62109-3.77832,4.62109a3.0693,3.0693,0,0,1-2.84863-1.584h-.043v4.48438h-1.8584V21.44238H48.4302v1.50586h.03418a3.21162,3.21162,0,0,1,2.88281-1.60059C53.645,21.34766,55.15969,23.16406,55.15969,25.96973Zm-1.91016,0c0-1.833-.94727-3.03809-2.39258-3.03809-1.41992,0-2.375,1.23047-2.375,3.03809,0,1.82422.95508,3.0459,2.375,3.0459C52.30227,29.01563,53.24953,27.81934,53.24953,25.96973Z" style="fill: #fff"/>
|
||||
<path d="M65.12453,25.96973c0,2.81348-1.50586,4.62109-3.77832,4.62109a3.0693,3.0693,0,0,1-2.84863-1.584h-.043v4.48438h-1.8584V21.44238H58.395v1.50586h.03418A3.21162,3.21162,0,0,1,61.312,21.34766C63.60988,21.34766,65.12453,23.16406,65.12453,25.96973Zm-1.91016,0c0-1.833-.94727-3.03809-2.39258-3.03809-1.41992,0-2.375,1.23047-2.375,3.03809,0,1.82422.95508,3.0459,2.375,3.0459C62.26711,29.01563,63.21438,27.81934,63.21438,25.96973Z" style="fill: #fff"/>
|
||||
<path d="M71.71047,27.03613c.1377,1.23145,1.334,2.04,2.96875,2.04,1.56641,0,2.69336-.80859,2.69336-1.91895,0-.96387-.67969-1.541-2.28906-1.93652l-1.60937-.3877c-2.28027-.55078-3.33887-1.61719-3.33887-3.34766,0-2.14258,1.86719-3.61426,4.51855-3.61426,2.624,0,4.42285,1.47168,4.4834,3.61426h-1.876c-.1123-1.23926-1.13672-1.9873-2.63379-1.9873s-2.52148.75684-2.52148,1.8584c0,.87793.6543,1.39453,2.25488,1.79l1.36816.33594c2.54785.60254,3.60645,1.626,3.60645,3.44238,0,2.32324-1.85059,3.77832-4.79395,3.77832-2.75391,0-4.61328-1.4209-4.7334-3.667Z" style="fill: #fff"/>
|
||||
<path d="M83.34621,19.2998v2.14258h1.72168v1.47168H83.34621v4.99121c0,.77539.34473,1.13672,1.10156,1.13672a5.80752,5.80752,0,0,0,.61133-.043v1.46289a5.10351,5.10351,0,0,1-1.03223.08594c-1.833,0-2.54785-.68848-2.54785-2.44434V22.91406H80.16262V21.44238H81.479V19.2998Z" style="fill: #fff"/>
|
||||
<path d="M86.065,25.96973c0-2.84863,1.67773-4.63867,4.29395-4.63867,2.625,0,4.29492,1.79,4.29492,4.63867,0,2.85645-1.66113,4.63867-4.29492,4.63867C87.72609,30.6084,86.065,28.82617,86.065,25.96973Zm6.69531,0c0-1.9541-.89551-3.10742-2.40137-3.10742s-2.40039,1.16211-2.40039,3.10742c0,1.96191.89453,3.10645,2.40039,3.10645S92.76027,27.93164,92.76027,25.96973Z" style="fill: #fff"/>
|
||||
<path d="M96.18606,21.44238h1.77246v1.541h.043a2.1594,2.1594,0,0,1,2.17773-1.63574,2.86616,2.86616,0,0,1,.63672.06934v1.73828a2.59794,2.59794,0,0,0-.835-.1123,1.87264,1.87264,0,0,0-1.93652,2.083v5.37012h-1.8584Z" style="fill: #fff"/>
|
||||
<path d="M109.3843,27.83691c-.25,1.64355-1.85059,2.77148-3.89844,2.77148-2.63379,0-4.26855-1.76465-4.26855-4.5957,0-2.83984,1.64355-4.68164,4.19043-4.68164,2.50488,0,4.08008,1.7207,4.08008,4.46582v.63672h-6.39453v.1123a2.358,2.358,0,0,0,2.43555,2.56445,2.04834,2.04834,0,0,0,2.09082-1.27344Zm-6.28223-2.70215h4.52637a2.1773,2.1773,0,0,0-2.2207-2.29785A2.292,2.292,0,0,0,103.10207,25.13477Z" style="fill: #fff"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="_Group_4" data-name="<Group>">
|
||||
<g>
|
||||
<path d="M37.82619,8.731a2.63964,2.63964,0,0,1,2.80762,2.96484c0,1.90625-1.03027,3.002-2.80762,3.002H35.67092V8.731Zm-1.22852,5.123h1.125a1.87588,1.87588,0,0,0,1.96777-2.146,1.881,1.881,0,0,0-1.96777-2.13379h-1.125Z" style="fill: #fff"/>
|
||||
<path d="M41.68068,12.44434a2.13323,2.13323,0,1,1,4.24707,0,2.13358,2.13358,0,1,1-4.24707,0Zm3.333,0c0-.97607-.43848-1.54687-1.208-1.54687-.77246,0-1.207.5708-1.207,1.54688,0,.98389.43457,1.55029,1.207,1.55029C44.57522,13.99463,45.01369,13.42432,45.01369,12.44434Z" style="fill: #fff"/>
|
||||
<path d="M51.57326,14.69775h-.92187l-.93066-3.31641h-.07031l-.92676,3.31641h-.91309l-1.24121-4.50293h.90137l.80664,3.436h.06641l.92578-3.436h.85254l.92578,3.436h.07031l.80273-3.436h.88867Z" style="fill: #fff"/>
|
||||
<path d="M53.85354,10.19482H54.709v.71533h.06641a1.348,1.348,0,0,1,1.34375-.80225,1.46456,1.46456,0,0,1,1.55859,1.6748v2.915h-.88867V12.00586c0-.72363-.31445-1.0835-.97168-1.0835a1.03294,1.03294,0,0,0-1.0752,1.14111v2.63428h-.88867Z" style="fill: #fff"/>
|
||||
<path d="M59.09377,8.437h.88867v6.26074h-.88867Z" style="fill: #fff"/>
|
||||
<path d="M61.21779,12.44434a2.13346,2.13346,0,1,1,4.24756,0,2.1338,2.1338,0,1,1-4.24756,0Zm3.333,0c0-.97607-.43848-1.54687-1.208-1.54687-.77246,0-1.207.5708-1.207,1.54688,0,.98389.43457,1.55029,1.207,1.55029C64.11232,13.99463,64.5508,13.42432,64.5508,12.44434Z" style="fill: #fff"/>
|
||||
<path d="M66.4009,13.42432c0-.81055.60352-1.27783,1.6748-1.34424l1.21973-.07031v-.38867c0-.47559-.31445-.74414-.92187-.74414-.49609,0-.83984.18213-.93848.50049h-.86035c.09082-.77344.81836-1.26953,1.83984-1.26953,1.12891,0,1.76563.562,1.76563,1.51318v3.07666h-.85547v-.63281h-.07031a1.515,1.515,0,0,1-1.35254.707A1.36026,1.36026,0,0,1,66.4009,13.42432Zm2.89453-.38477v-.37646l-1.09961.07031c-.62012.0415-.90137.25244-.90137.64941,0,.40527.35156.64111.835.64111A1.0615,1.0615,0,0,0,69.29543,13.03955Z" style="fill: #fff"/>
|
||||
<path d="M71.34816,12.44434c0-1.42285.73145-2.32422,1.86914-2.32422a1.484,1.484,0,0,1,1.38086.79h.06641V8.437h.88867v6.26074h-.85156v-.71143h-.07031a1.56284,1.56284,0,0,1-1.41406.78564C72.0718,14.772,71.34816,13.87061,71.34816,12.44434Zm.918,0c0,.95508.4502,1.52979,1.20313,1.52979.749,0,1.21191-.583,1.21191-1.52588,0-.93848-.46777-1.52979-1.21191-1.52979C72.72121,10.91846,72.26613,11.49707,72.26613,12.44434Z" style="fill: #fff"/>
|
||||
<path d="M79.23,12.44434a2.13323,2.13323,0,1,1,4.24707,0,2.13358,2.13358,0,1,1-4.24707,0Zm3.333,0c0-.97607-.43848-1.54687-1.208-1.54687-.77246,0-1.207.5708-1.207,1.54688,0,.98389.43457,1.55029,1.207,1.55029C82.12453,13.99463,82.563,13.42432,82.563,12.44434Z" style="fill: #fff"/>
|
||||
<path d="M84.66945,10.19482h.85547v.71533h.06641a1.348,1.348,0,0,1,1.34375-.80225,1.46456,1.46456,0,0,1,1.55859,1.6748v2.915H87.605V12.00586c0-.72363-.31445-1.0835-.97168-1.0835a1.03294,1.03294,0,0,0-1.0752,1.14111v2.63428h-.88867Z" style="fill: #fff"/>
|
||||
<path d="M93.51516,9.07373v1.1416h.97559v.74854h-.97559V13.2793c0,.47168.19434.67822.63672.67822a2.96657,2.96657,0,0,0,.33887-.02051v.74023a2.9155,2.9155,0,0,1-.4834.04541c-.98828,0-1.38184-.34766-1.38184-1.21582v-2.543h-.71484v-.74854h.71484V9.07373Z" style="fill: #fff"/>
|
||||
<path d="M95.70461,8.437h.88086v2.48145h.07031a1.3856,1.3856,0,0,1,1.373-.80664,1.48339,1.48339,0,0,1,1.55078,1.67871v2.90723H98.69v-2.688c0-.71924-.335-1.0835-.96289-1.0835a1.05194,1.05194,0,0,0-1.13379,1.1416v2.62988h-.88867Z" style="fill: #fff"/>
|
||||
<path d="M104.76125,13.48193a1.828,1.828,0,0,1-1.95117,1.30273A2.04531,2.04531,0,0,1,100.73,12.46045a2.07685,2.07685,0,0,1,2.07617-2.35254c1.25293,0,2.00879.856,2.00879,2.27V12.688h-3.17969v.0498a1.1902,1.1902,0,0,0,1.19922,1.29,1.07934,1.07934,0,0,0,1.07129-.5459Zm-3.126-1.45117h2.27441a1.08647,1.08647,0,0,0-1.1084-1.1665A1.15162,1.15162,0,0,0,101.63527,12.03076Z" style="fill: #fff"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 11 KiB |
9
server/public/assets/images/browserconfig.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<browserconfig>
|
||||
<msapplication>
|
||||
<tile>
|
||||
<square150x150logo src="/assets/images/mstile-150x150.png"/>
|
||||
<TileColor>#2d2d2d</TileColor>
|
||||
</tile>
|
||||
</msapplication>
|
||||
</browserconfig>
|
||||
BIN
server/public/assets/images/btcdonate.png
Normal file
|
After Width: | Height: | Size: 9.7 KiB |
BIN
server/public/assets/images/ethdonate.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 697 B After Width: | Height: | Size: 697 B |
BIN
server/public/assets/images/favicon-16x16.png
Normal file
|
After Width: | Height: | Size: 726 B |
BIN
server/public/assets/images/favicon-32x32.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
server/public/assets/images/favicon.ico
Normal file
|
After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 6.5 KiB |
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 786 B After Width: | Height: | Size: 786 B |
BIN
server/public/assets/images/mstile-150x150.png
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
BIN
server/public/assets/images/s1.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
server/public/assets/images/s2.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
server/public/assets/images/s3.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
59
server/public/assets/images/safari-pinned-tab.svg
Normal file
@@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="1024.000000pt" height="1024.000000pt" viewBox="0 0 1024.000000 1024.000000" preserveAspectRatio="xMidYMid meet">
|
||||
<g transform="translate(0.000000,1024.000000) scale(0.100000,-0.100000)"
|
||||
fill="#000000" stroke="none">
|
||||
<path d="M4855 10233 c-394 -26 -679 -71 -1020 -158 -1295 -331 -2412 -1169
|
||||
-3115 -2335 -83 -138 -254 -475 -314 -620 -161 -385 -269 -757 -335 -1155 -19
|
||||
-117 -23 -146 -36 -270 -4 -33 -9 -71 -11 -85 -24 -154 -24 -766 0 -970 2 -14
|
||||
7 -56 11 -95 4 -38 8 -77 10 -85 1 -8 6 -40 9 -70 4 -30 11 -77 16 -105 5 -27
|
||||
12 -66 15 -85 3 -19 22 -106 41 -194 54 -241 111 -432 219 -726 34 -95 135
|
||||
-321 203 -455 276 -547 649 -1040 1108 -1465 79 -74 256 -224 320 -271 32 -24
|
||||
61 -46 64 -49 11 -13 182 -132 291 -203 351 -231 772 -433 1191 -571 237 -78
|
||||
556 -156 783 -191 113 -17 352 -45 445 -51 205 -15 757 -8 858 10 9 2 46 7 82
|
||||
11 98 10 201 24 305 41 66 11 276 57 389 85 636 160 1269 465 1808 871 325
|
||||
245 606 515 892 858 127 153 329 446 452 655 389 662 622 1424 681 2226 14
|
||||
199 7 727 -12 842 -2 12 -9 67 -15 122 -35 308 -117 677 -222 990 -212 637
|
||||
-535 1207 -982 1730 -586 685 -1383 1220 -2251 1510 -373 125 -793 212 -1150
|
||||
240 -44 4 -91 9 -105 11 -27 6 -560 11 -625 7z"/>
|
||||
</g>
|
||||
<path id="letterZ"
|
||||
fill="white" stroke="none" stroke-width="1"
|
||||
d="M 424.00,88.47
|
||||
C 448.68,98.55 455.10,132.92 436.83,151.91
|
||||
427.76,161.34 418.44,163.14 406.00,163.00
|
||||
389.20,162.80 374.05,150.57 370.52,134.00
|
||||
369.82,130.73 369.99,126.41 370.00,123.00
|
||||
370.03,104.41 381.95,90.48 400.00,86.46
|
||||
407.48,85.43 416.95,85.60 424.00,88.47 Z
|
||||
M 652.00,88.47
|
||||
C 676.68,98.55 683.10,132.92 664.83,151.91
|
||||
655.76,161.34 646.44,163.14 634.00,163.00
|
||||
617.20,162.80 602.05,150.57 598.52,134.00
|
||||
597.82,130.73 597.99,126.41 598.00,123.00
|
||||
598.03,104.41 609.95,90.48 628.00,86.46
|
||||
635.48,85.43 644.95,85.60 652.00,88.47 Z
|
||||
M 750.00,231.00
|
||||
C 750.00,231.00 750.00,275.00 750.00,275.00
|
||||
749.98,285.27 746.65,286.97 740.63,295.00
|
||||
740.63,295.00 723.13,318.00 723.13,318.00
|
||||
723.13,318.00 643.88,422.00 643.88,422.00
|
||||
643.88,422.00 445.88,682.00 445.88,682.00
|
||||
445.88,682.00 378.88,770.00 378.88,770.00
|
||||
378.88,770.00 345.00,814.00 345.00,814.00
|
||||
345.00,814.00 753.00,814.00 753.00,814.00
|
||||
753.00,814.00 753.00,865.00 753.00,865.00
|
||||
753.00,865.00 270.00,865.00 270.00,865.00
|
||||
270.00,865.00 270.00,821.00 270.00,821.00
|
||||
270.02,810.30 274.03,808.20 280.35,800.00
|
||||
280.35,800.00 297.87,777.00 297.87,777.00
|
||||
297.87,777.00 379.35,670.00 379.35,670.00
|
||||
379.35,670.00 581.12,405.00 581.12,405.00
|
||||
581.12,405.00 648.12,317.00 648.12,317.00
|
||||
648.12,317.00 674.00,283.00 674.00,283.00
|
||||
674.00,283.00 304.00,283.00 304.00,283.00
|
||||
304.00,283.00 304.00,231.00 304.00,231.00
|
||||
304.00,231.00 750.00,231.00 750.00,231.00 Z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.4 KiB |
1
server/public/assets/images/small-square.base64.txt
Normal file
BIN
server/public/assets/images/small-square.jpg
Normal file
|
After Width: | Height: | Size: 8.9 KiB |
BIN
server/public/assets/images/spotify.png
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 37 KiB |
BIN
server/public/assets/images/squareicon_small.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 980 B After Width: | Height: | Size: 980 B |
BIN
server/public/assets/images/youtube.png
Normal file
|
After Width: | Height: | Size: 6.0 KiB |
92
server/public/assets/images/z.svg
Normal file
@@ -0,0 +1,92 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
width="1600" height="1024"
|
||||
viewBox="0 0 1600 1024">
|
||||
<path id="letterZ"
|
||||
fill="white" stroke="none" stroke-width="1"
|
||||
d="M 424.00,88.47
|
||||
C 448.68,98.55 455.10,132.92 436.83,151.91
|
||||
427.76,161.34 418.44,163.14 406.00,163.00
|
||||
389.20,162.80 374.05,150.57 370.52,134.00
|
||||
369.82,130.73 369.99,126.41 370.00,123.00
|
||||
370.03,104.41 381.95,90.48 400.00,86.46
|
||||
407.48,85.43 416.95,85.60 424.00,88.47 Z
|
||||
M 652.00,88.47
|
||||
C 676.68,98.55 683.10,132.92 664.83,151.91
|
||||
655.76,161.34 646.44,163.14 634.00,163.00
|
||||
617.20,162.80 602.05,150.57 598.52,134.00
|
||||
597.82,130.73 597.99,126.41 598.00,123.00
|
||||
598.03,104.41 609.95,90.48 628.00,86.46
|
||||
635.48,85.43 644.95,85.60 652.00,88.47 Z
|
||||
M 750.00,231.00
|
||||
C 750.00,231.00 750.00,275.00 750.00,275.00
|
||||
749.98,285.27 746.65,286.97 740.63,295.00
|
||||
740.63,295.00 723.13,318.00 723.13,318.00
|
||||
723.13,318.00 643.88,422.00 643.88,422.00
|
||||
643.88,422.00 445.88,682.00 445.88,682.00
|
||||
445.88,682.00 378.88,770.00 378.88,770.00
|
||||
378.88,770.00 345.00,814.00 345.00,814.00
|
||||
345.00,814.00 753.00,814.00 753.00,814.00
|
||||
753.00,814.00 753.00,865.00 753.00,865.00
|
||||
753.00,865.00 270.00,865.00 270.00,865.00
|
||||
270.00,865.00 270.00,821.00 270.00,821.00
|
||||
270.02,810.30 274.03,808.20 280.35,800.00
|
||||
280.35,800.00 297.87,777.00 297.87,777.00
|
||||
297.87,777.00 379.35,670.00 379.35,670.00
|
||||
379.35,670.00 581.12,405.00 581.12,405.00
|
||||
581.12,405.00 648.12,317.00 648.12,317.00
|
||||
648.12,317.00 674.00,283.00 674.00,283.00
|
||||
674.00,283.00 304.00,283.00 304.00,283.00
|
||||
304.00,283.00 304.00,231.00 304.00,231.00
|
||||
304.00,231.00 750.00,231.00 750.00,231.00 Z" />
|
||||
<path id="shadeZ"
|
||||
fill="black" stroke="none" style="fill-opacity:0.3;" stroke-width="1"
|
||||
d="M 465.00,125.00
|
||||
C 465.00,125.00 506.00,166.00 506.00,166.00
|
||||
506.00,166.00 547.00,207.00 547.00,207.00
|
||||
547.00,207.00 569.00,230.00 569.00,230.00
|
||||
569.00,230.00 463.00,230.00 463.00,230.00
|
||||
460.91,230.00 457.94,230.12 456.00,229.40
|
||||
452.15,227.98 444.26,219.26 441.00,216.00
|
||||
441.00,216.00 406.00,181.00 406.00,181.00
|
||||
398.41,173.41 380.82,156.95 375.70,149.00
|
||||
372.76,144.44 369.02,137.43 371.00,132.00
|
||||
372.13,138.21 374.82,143.10 378.82,147.96
|
||||
393.72,166.06 420.54,167.00 436.56,149.83
|
||||
445.06,140.72 448.84,128.30 446.53,116.00
|
||||
445.68,111.45 443.46,107.35 442.00,103.00
|
||||
442.00,103.00 465.00,125.00 465.00,125.00 Z
|
||||
M 1586.67,1021.33
|
||||
C 1586.67,1021.33 426.33,1024.00 426.33,1024.00
|
||||
426.33,1024.00 270.00,864.00 270.00,864.00
|
||||
270.00,864.00 753.00,864.00 753.00,864.00
|
||||
753.00,864.00 753.00,813.00 753.00,813.00
|
||||
753.00,813.00 345.00,813.00 345.00,813.00
|
||||
345.00,813.00 372.63,776.00 372.63,776.00
|
||||
372.63,776.00 436.63,692.00 436.63,692.00
|
||||
436.63,692.00 644.37,419.00 644.37,419.00
|
||||
644.37,419.00 722.87,316.00 722.87,316.00
|
||||
722.87,316.00 740.37,293.00 740.37,293.00
|
||||
746.87,284.35 749.98,283.01 750.00,272.00
|
||||
750.00,272.00 750.00,230.00 750.00,230.00
|
||||
750.00,230.00 691.00,230.00 691.00,230.00
|
||||
688.91,230.00 685.94,230.12 684.00,229.40
|
||||
680.15,227.98 672.26,219.26 669.00,216.00
|
||||
669.00,216.00 629.00,176.00 629.00,176.00
|
||||
621.24,168.24 607.66,155.97 602.46,147.00
|
||||
599.98,142.71 597.21,136.91 599.00,132.00
|
||||
600.13,138.21 602.82,143.10 606.82,147.96
|
||||
621.72,166.06 648.54,167.00 664.56,149.83
|
||||
673.06,140.72 676.84,128.30 674.53,116.00
|
||||
673.68,111.45 671.46,107.35 670.00,103.00
|
||||
676.59,107.72 1586.66,1019.24 1586.67,1021.33 Z
|
||||
M 675.00,281.00
|
||||
C 675.00,281.00 638.37,330.00 638.37,330.00
|
||||
638.37,330.00 561.58,431.00 561.58,431.00
|
||||
561.58,431.00 514.00,494.00 514.00,494.00
|
||||
514.00,494.00 304.00,281.00 304.00,281.00
|
||||
304.00,281.00 675.00,281.00 675.00,281.00 Z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.6 KiB |
351
server/public/assets/js/admin.js
Executable file
@@ -0,0 +1,351 @@
|
||||
var Admin = {
|
||||
beginning: true,
|
||||
logged_in: false,
|
||||
|
||||
update_strict_skip: function(value) {
|
||||
var form = document.getElementById("adminSettingsForm");
|
||||
form.strictSkipNumber = value;
|
||||
Admin.submitAdmin(form, false);
|
||||
},
|
||||
|
||||
pw: function(msg) {
|
||||
Admin.logged_in = msg;
|
||||
if (!msg) return;
|
||||
w_p = false;
|
||||
M.Modal.init(document.getElementById("channel_info"));
|
||||
if (Admin.logged_in) {
|
||||
Helper.removeClass(".info_change_li", "hide");
|
||||
Helper.removeClass("#user_suggests", "hide");
|
||||
Helper.removeClass("#user-suggest-html", "hide");
|
||||
if (
|
||||
Helper.html(".suggested-badge") != "0" &&
|
||||
Helper.html(".suggested-badge") != ""
|
||||
) {
|
||||
Helper.removeClass(".suggested-badge", "hide");
|
||||
}
|
||||
if (conf != undefined && conf.strictSkip) {
|
||||
Helper.removeClass(".strict-skip-input", "hide");
|
||||
}
|
||||
} else {
|
||||
Admin.hideUserSuggested();
|
||||
Helper.addClass(".strict-skip-input", "hide");
|
||||
}
|
||||
Helper.removeClass(".delete-context-menu", "context-menu-disabled");
|
||||
names = [
|
||||
"vote",
|
||||
"addsongs",
|
||||
"longsongs",
|
||||
"frontpage",
|
||||
"allvideos",
|
||||
"removeplay",
|
||||
"skip",
|
||||
"shuffle",
|
||||
"userpass",
|
||||
"toggleChat",
|
||||
"strictSkip"
|
||||
];
|
||||
//Crypt.set_pass(chan.toLowerCase(), Crypt.tmp_pass);
|
||||
|
||||
for (var i = 0; i < names.length; i++) {
|
||||
document.getElementsByName(names[i])[0].removeAttribute("disabled");
|
||||
}
|
||||
|
||||
Helper.removeClass(".card-action", "hide");
|
||||
Helper.addClass("#admin-lock", "clickable");
|
||||
document.getElementById("admin-lock").innerHTML = "lock_open";
|
||||
if (!Helper.mobilecheck()) {
|
||||
Helper.tooltip("#admin-lock", {
|
||||
delay: 5,
|
||||
position: "left",
|
||||
html: "Logout"
|
||||
});
|
||||
}
|
||||
document.getElementById("password").value = "";
|
||||
document
|
||||
.getElementById("password")
|
||||
.setAttribute("placeholder", "Change admin password");
|
||||
Helper.removeClass(".user-password-li", "hide");
|
||||
Helper.removeClass(".chat-toggle-li", "hide");
|
||||
Helper.removeClass(".delete-all", "hide");
|
||||
if (document.getElementsByClassName("password_protected")[0].checked) {
|
||||
Helper.removeClass(".change_user_pass", "hide");
|
||||
}
|
||||
|
||||
if (Helper.html("#admin-lock") != "lock_open") {
|
||||
Helper.addClass("#admin-lock", "clickable");
|
||||
document.getElementById("admin-lock").innerHTML = "lock_open";
|
||||
if (!Helper.mobilecheck()) {
|
||||
Helper.tooltip("#admin-lock", {
|
||||
delay: 5,
|
||||
position: "left",
|
||||
html: "Logout"
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
hideUserSuggested: function() {
|
||||
Helper.addClass("#user_suggests", "hide");
|
||||
Helper.addClass("#user-suggest-html", "hide");
|
||||
Helper.addClass(".suggested-badge", "hide");
|
||||
},
|
||||
|
||||
conf: function(msg) {
|
||||
if (msg[0].adminpass == "") {
|
||||
////Crypt.remove_pass(chan.toLowerCase());
|
||||
}
|
||||
Admin.set_conf(msg[0]);
|
||||
if (msg[0].adminpass !== "" && Admin.beginning) {
|
||||
//emit("password", {password: Crypt.crypt_pass(Crypt.get_pass(chan.toLowerCase())), channel: chan.toLowerCase()});
|
||||
Admin.beginning = false;
|
||||
}
|
||||
},
|
||||
|
||||
pass_save: function() {
|
||||
if (!w_p) {
|
||||
//emit('password', {password: Crypt.crypt_pass(CryptoJS.SHA256(document.getElementById("password").value).toString()), channel: chan.toLowerCase(), oldpass: Crypt.crypt_pass(Crypt.get_pass(chan.toLowerCase()))});
|
||||
emit("password", {
|
||||
password: Crypt.crypt_pass(document.getElementById("password").value),
|
||||
channel: chan.toLowerCase()
|
||||
});
|
||||
} else {
|
||||
//emit('password', {password: Crypt.crypt_pass(CryptoJS.SHA256(document.getElementById("password").value).toString()), channel: chan.toLowerCase()});
|
||||
emit("password", {
|
||||
password: Crypt.crypt_pass(document.getElementById("password").value),
|
||||
channel: chan.toLowerCase()
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
log_out: function() {
|
||||
before_toast();
|
||||
/*if(Crypt.get_pass(chan.toLowerCase())) {*/
|
||||
//Crypt.remove_pass(chan.toLowerCase());
|
||||
if (Admin.logged_in) {
|
||||
socket.emit("logout");
|
||||
M.toast({ html: "Logged out", displayLength: 4000 });
|
||||
Admin.display_logged_out();
|
||||
} else {
|
||||
M.toast({ html: "Not logged in", displayLength: 4000 });
|
||||
}
|
||||
},
|
||||
|
||||
display_logged_out: function() {
|
||||
Admin.logged_in = false;
|
||||
w_p = true;
|
||||
adminpass = "";
|
||||
names = [
|
||||
"vote",
|
||||
"addsongs",
|
||||
"longsongs",
|
||||
"frontpage",
|
||||
"allvideos",
|
||||
"removeplay",
|
||||
"skip",
|
||||
"shuffle",
|
||||
"toggleChat",
|
||||
"strictSkip"
|
||||
];
|
||||
document.getElementById("password").value = "";
|
||||
Helper.addClass(".info_change_li", "hide");
|
||||
for (i = 0; i < names.length; i++) {
|
||||
document.getElementsByName(names[i])[0].setAttribute("disabled", true);
|
||||
}
|
||||
|
||||
if (Helper.html("#admin-lock") != "lock") {
|
||||
if (!Helper.mobilecheck()) {
|
||||
Helper.tooltip("#admin-lock", "destroy");
|
||||
}
|
||||
Helper.removeClass("#admin-lock", "clickable");
|
||||
document.getElementById("admin-lock").innerHTML = "lock";
|
||||
}
|
||||
|
||||
Helper.addClass(".strict-skip-input", "hide");
|
||||
Helper.addClass(".user-password-li", "hide");
|
||||
Helper.addClass(".chat-toggle-li", "hide");
|
||||
Helper.addClass(".delete-all", "hide");
|
||||
|
||||
if (document.getElementsByClassName("password_protected")[0].checked) {
|
||||
Helper.removeClass(".change_user_pass", "hide");
|
||||
}
|
||||
|
||||
Helper.addClass(".change_user_pass", "hide");
|
||||
Admin.hideUserSuggested();
|
||||
|
||||
Helper.removeClass("#admin-lock", "clickable");
|
||||
document
|
||||
.getElementById("password")
|
||||
.setAttribute("placeholder", "Enter admin password");
|
||||
Helper.addClass(".delete-context-menu", "context-menu-disabled");
|
||||
},
|
||||
|
||||
save: function(userpass) {
|
||||
Admin.submitAdmin(
|
||||
document.getElementById("adminSettingsForm").elements,
|
||||
userpass
|
||||
);
|
||||
},
|
||||
|
||||
set_conf: function(conf_array) {
|
||||
conf = conf_array;
|
||||
music = conf_array.allvideos;
|
||||
longsongs = conf_array.longsongs;
|
||||
names = [
|
||||
"vote",
|
||||
"addsongs",
|
||||
"longsongs",
|
||||
"frontpage",
|
||||
"allvideos",
|
||||
"removeplay",
|
||||
"skip",
|
||||
"shuffle",
|
||||
"userpass",
|
||||
"toggleChat",
|
||||
"strictSkip"
|
||||
];
|
||||
if (!conf.hasOwnProperty("toggleChat")) conf.toggleChat = true;
|
||||
toggleChat = conf.toggleChat;
|
||||
hasadmin = conf_array.adminpass != "";
|
||||
var show_disabled = true;
|
||||
if ((hasadmin && Admin.logged_in) || !hasadmin) {
|
||||
show_disabled = false;
|
||||
}
|
||||
|
||||
for (var i = 0; i < names.length; i++) {
|
||||
document.getElementsByName(names[i])[0].checked =
|
||||
conf_array[names[i]] === true;
|
||||
if (show_disabled) {
|
||||
document
|
||||
.getElementsByName(names[i])[0]
|
||||
.setAttribute("disabled", show_disabled);
|
||||
} else {
|
||||
document.getElementsByName(names[i])[0].removeAttribute("disabled");
|
||||
}
|
||||
}
|
||||
document.getElementById("strict-input-number").value =
|
||||
conf.strictSkipNumber;
|
||||
if (hasadmin && !Admin.logged_in) {
|
||||
if (Helper.html("#admin-lock") != "lock") Admin.display_logged_out();
|
||||
} else if (!hasadmin) {
|
||||
document
|
||||
.getElementById("password")
|
||||
.setAttribute("placeholder", "Create admin password");
|
||||
} else {
|
||||
if (document.getElementsByClassName("password_protected")[0].checked) {
|
||||
Helper.removeClass(".change_user_pass", "hide");
|
||||
}
|
||||
}
|
||||
if (Admin.logged_in) {
|
||||
if (conf != undefined && conf.strictSkip) {
|
||||
Helper.removeClass(".strict-skip-input", "hide");
|
||||
}
|
||||
}
|
||||
if (conf != undefined && !conf.strictSkip) {
|
||||
Helper.addClass(".strict-skip-input", "hide");
|
||||
}
|
||||
if (!document.getElementsByClassName("password_protected")[0].checked) {
|
||||
Helper.addClass(".change_user_pass", "hide");
|
||||
//Crypt.remove_userpass(chan.toLowerCase());
|
||||
}
|
||||
var updated = false;
|
||||
|
||||
if (conf_array.thumbnail != undefined && conf_array.thumbnail != "") {
|
||||
document.getElementById("thumbnail_image").innerHTML =
|
||||
"<img id='thumbnail_image_channel' src='" +
|
||||
conf_array.thumbnail +
|
||||
"' alt='thumbnail' />";
|
||||
document.getElementById("thumbnail_input").value = conf_array.thumbnail;
|
||||
updated = true;
|
||||
}
|
||||
|
||||
if (conf_array.description != undefined && conf_array.description != "") {
|
||||
document.getElementById("description_area").innerHTML =
|
||||
conf_array.description;
|
||||
document.getElementById("description_input").value =
|
||||
conf_array.description;
|
||||
updated = true;
|
||||
}
|
||||
|
||||
if (conf_array.rules != undefined && conf_array.rules != "") {
|
||||
var existingRules = document.querySelector(".rules-container");
|
||||
if (existingRules) existingRules.remove();
|
||||
var rules = conf_array.rules.split("\n");
|
||||
var elementToAdd =
|
||||
"<li class='rules-container'><div class='row'><div class='col s10 offset-s1'><h4 class='center-align'>Rules</h4>";
|
||||
for (var i = 0; i < rules.length; i++) {
|
||||
elementToAdd += "<p class='initial-line-height'>" + rules[i] + "</p>";
|
||||
}
|
||||
elementToAdd += "</div></div>";
|
||||
document
|
||||
.querySelector(".channel_info_container")
|
||||
.insertAdjacentHTML("afterend", elementToAdd);
|
||||
document.getElementById("rules_input").value = conf_array.rules;
|
||||
updated = true;
|
||||
}
|
||||
if (updated) M.updateTextFields();
|
||||
},
|
||||
|
||||
submitAdmin: function(form, userpass_changed) {
|
||||
voting = form.vote.checked;
|
||||
addsongs = form.addsongs.checked;
|
||||
longsongs = form.longsongs.checked;
|
||||
frontpage = form.frontpage.checked;
|
||||
allvideos = form.allvideos.checked;
|
||||
removeplay = form.removeplay.checked;
|
||||
skipping = form.skip.checked;
|
||||
shuffling = form.shuffle.checked;
|
||||
toggleChat = form.toggleChat.checked;
|
||||
strictSkip = form.strictSkip.checked;
|
||||
|
||||
if (form.strictSkipNumber) {
|
||||
strictSkipNumber = form.strictSkipNumber;
|
||||
} else {
|
||||
strictSkipNumber = conf.strictSkipNumber;
|
||||
}
|
||||
|
||||
var pass_send = userpass_changed && !form.userpass.checked ? "" : userpass;
|
||||
configs = {
|
||||
channel: chan.toLowerCase(),
|
||||
voting: voting,
|
||||
addsongs: addsongs,
|
||||
longsongs: longsongs,
|
||||
frontpage: frontpage,
|
||||
allvideos: allvideos,
|
||||
removeplay: removeplay,
|
||||
adminpass: adminpass == "" ? "" : Crypt.crypt_pass(adminpass),
|
||||
skipping: skipping,
|
||||
shuffling: shuffling,
|
||||
toggleChat: toggleChat,
|
||||
strictSkip: strictSkip,
|
||||
userpass: Crypt.crypt_pass(pass_send),
|
||||
userpass_changed: userpass_changed,
|
||||
strictSkipNumber: strictSkipNumber
|
||||
};
|
||||
|
||||
emit("conf", configs);
|
||||
},
|
||||
|
||||
hide_settings: function() {
|
||||
var sidenavElem = document.getElementsByClassName("sidenav")[0];
|
||||
M.Sidenav.getInstance(sidenavElem).close();
|
||||
},
|
||||
|
||||
shuffle: function() {
|
||||
if (!offline) {
|
||||
//var u = Crypt.crypt_pass(Crypt.get_userpass(chan.toLowerCase()), true);
|
||||
//if(u == undefined) u = "";
|
||||
emit("shuffle", { channel: chan.toLowerCase() });
|
||||
} else {
|
||||
for (var x = 0; x < full_playlist.length; x++) {
|
||||
var num = Math.floor(Math.random() * 1000000);
|
||||
full_playlist[x].added = num;
|
||||
}
|
||||
List.sortList();
|
||||
List.populate_list(full_playlist);
|
||||
}
|
||||
},
|
||||
|
||||
get_admin: function() {
|
||||
return [w_p, hasadmin];
|
||||
}
|
||||
};
|
||||
120
server/public/assets/js/callback.js
Executable file
@@ -0,0 +1,120 @@
|
||||
window.addEventListener("load", function() {
|
||||
var query = getQueryHash(window.location.hash);
|
||||
var redirect =
|
||||
window.location.protocol + "//" + window.location.hostname + "/api/oauth";
|
||||
var client_id;
|
||||
var response;
|
||||
var scope;
|
||||
|
||||
if (query.spotify) {
|
||||
client_id = "b934ecdd173648f5bcd38738af529d58";
|
||||
response = "token";
|
||||
scope =
|
||||
"playlist-read-private ugc-image-upload playlist-read-collaborative user-read-private playlist-modify-public playlist-modify-private";
|
||||
state = query.nonce;
|
||||
window.location.href =
|
||||
"https://accounts.spotify.com/authorize?client_id=" +
|
||||
client_id +
|
||||
"&scope=" +
|
||||
scope +
|
||||
"&show_dialog=false&response_type=" +
|
||||
response +
|
||||
"&redirect_uri=" +
|
||||
redirect +
|
||||
"&state=" +
|
||||
state;
|
||||
} else if (query.youtube) {
|
||||
client_id =
|
||||
"944988770273-butsmlr1aotlsskk8lmgvh0etqqekigf.apps.googleusercontent.com";
|
||||
response = "token";
|
||||
scope = "https://www.googleapis.com/auth/youtube";
|
||||
state = query.nonce;
|
||||
|
||||
//window.opener.callback(query);
|
||||
window.location.href =
|
||||
"https://accounts.google.com/o/oauth2/v2/auth?client_id=" +
|
||||
client_id +
|
||||
"&response_type=" +
|
||||
response +
|
||||
"&state=" +
|
||||
state +
|
||||
"&redirect_uri=" +
|
||||
redirect +
|
||||
"&scope=" +
|
||||
scope;
|
||||
} else if (query.soundcloud) {
|
||||
/*
|
||||
SC.initialize({
|
||||
client_id: api_key.soundcloud,
|
||||
redirect_uri: 'https://zoff.me/api/oauth'
|
||||
});
|
||||
|
||||
// initiate auth popup
|
||||
console.log("asd ok", api_key.soundcloud);
|
||||
SC.connect().then(function() {
|
||||
return SC.get('/me');
|
||||
}).then(function(me) {
|
||||
console.log(me);
|
||||
//alert('Hello, ' + me.username);
|
||||
}).catch(function(e) {
|
||||
console.log(e);
|
||||
});*/
|
||||
|
||||
var redirect_uri = encodeURIComponent("https://zoff.me/api/oauth");
|
||||
var response_type = "code";
|
||||
var scope = "non-expiring";
|
||||
var state = query.nonce;
|
||||
var url =
|
||||
"https://soundcloud.com/connect?client_id=" +
|
||||
api_key.soundcloud +
|
||||
"&redirect_uri=" +
|
||||
redirect_uri +
|
||||
"&state=" +
|
||||
state +
|
||||
"&display=page&response_type=code&scope=" +
|
||||
scope;
|
||||
//console.log(url);
|
||||
window.location.href = url;
|
||||
} else {
|
||||
var query_parameters;
|
||||
if (window.location.search.length > 0) {
|
||||
query_parameters = getQueryHash(window.location.search);
|
||||
} else {
|
||||
query_parameters = getQueryHash(window.location.hash);
|
||||
}
|
||||
try {
|
||||
window.opener.callback(query_parameters);
|
||||
} catch (e) {
|
||||
window.setTimeout(window.opener.SC_player.connectCallback, 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function getQueryHash(url) {
|
||||
if (window.location.search.length > 0) {
|
||||
if (url.substring(url.length - 1) == "#") {
|
||||
url = url.substring(0, url.length - 1);
|
||||
}
|
||||
var temp_arr = url.substring(1).split("&");
|
||||
var done_obj = {};
|
||||
var splitted;
|
||||
for (var i in temp_arr) {
|
||||
splitted = temp_arr[i].split("=");
|
||||
if (splitted.length == 2) {
|
||||
done_obj[splitted[0]] = splitted[1];
|
||||
}
|
||||
}
|
||||
return done_obj;
|
||||
} else {
|
||||
var temp_arr = url.substring(1).split("&");
|
||||
var done_obj = {};
|
||||
var splitted;
|
||||
for (var i in temp_arr) {
|
||||
splitted = temp_arr[i].split("=");
|
||||
if (splitted.length == 2) {
|
||||
done_obj[splitted[0]] = splitted[1];
|
||||
}
|
||||
}
|
||||
return done_obj;
|
||||
}
|
||||
}
|
||||
925
server/public/assets/js/channel.js
Normal file
@@ -0,0 +1,925 @@
|
||||
var Channel = {
|
||||
init: function() {
|
||||
if (window.location.hash == "#small" || inIframe()) {
|
||||
small_player = true;
|
||||
document.querySelector("footer").style.display = "none";
|
||||
}
|
||||
if (client) {
|
||||
Helper.addClass(".tabs", "hide");
|
||||
Helper.removeClass("#wrapper", "tabs_height");
|
||||
Helper.addClass("#wrapper", "client-wrapper");
|
||||
if (!Helper.mobilecheck()) {
|
||||
Helper.tooltip(".skip_next_client", {
|
||||
delay: 5,
|
||||
position: "bottom",
|
||||
html: "Skip"
|
||||
});
|
||||
}
|
||||
Helper.addClass("#chan", "chan-client");
|
||||
Helper.addClass("#results", "client-results-height");
|
||||
Helper.addClass(".pagination-results", "client-pagination-height");
|
||||
Helper.addClass(".control-list", "client-control-list");
|
||||
} else {
|
||||
if (!api_key.hasOwnProperty("soundcloud")) soundcloud_enabled = false;
|
||||
|
||||
if (cast_ready_connect || chromecastAvailable || chromecastReady) {
|
||||
Helper.addClass(".volume-container", "volume-container-cast");
|
||||
}
|
||||
if (!embed) {
|
||||
document
|
||||
.querySelector("#main-container")
|
||||
.insertAdjacentHTML(
|
||||
"beforeend",
|
||||
"<a id='hide-playlist' class='hide-on-small-only hide-playlist-button' href='#!'><i class='material-icons'>keyboard_arrow_right</i></div>"
|
||||
);
|
||||
document.querySelector("#hide-playlist").style.left =
|
||||
document.querySelector("#video-container").offsetWidth -
|
||||
document.querySelector("#hide-playlist").offsetWidth +
|
||||
"px";
|
||||
}
|
||||
//Player.soundcloud_player = document.querySelector("#soundcloud_player");
|
||||
}
|
||||
List.calculate_song_heights();
|
||||
Admin.logged_in = false;
|
||||
Admin.display_logged_out();
|
||||
number_suggested = 0;
|
||||
var no_socket = true;
|
||||
|
||||
//chan = Helper.decodeChannelName(Helper.html("#chan"));
|
||||
var _p = window.location.pathname;
|
||||
if (_p.substring(0, 1) == "/") _p = _p.substring(1);
|
||||
if (_p.substring(_p.length - 1) == "/") _p = _p.substring(0, _p.length - 1);
|
||||
chan = Helper.decodeChannelName(_p);
|
||||
|
||||
mobile_beginning = Helper.mobilecheck();
|
||||
var side = Helper.mobilecheck() ? "left" : "right";
|
||||
|
||||
if (window.location.hostname != "localhost") {
|
||||
var page = window.location.pathname;
|
||||
if (page.substring(page.length - 1) != "/") page += "/";
|
||||
ga("send", "pageview", page);
|
||||
}
|
||||
|
||||
window.onpopstate = function(e) {
|
||||
Channel.onepage_load();
|
||||
};
|
||||
|
||||
if (window.location.hostname == "fb.zoff.me") {
|
||||
Helper.addClass("footer", "hide");
|
||||
}
|
||||
|
||||
if (window.location.hostname != "fb.zoff.me") Channel.share_link_modifier();
|
||||
if (
|
||||
window.location.hostname == "zoff.me" ||
|
||||
window.location.hostname == "fb.zoff.me"
|
||||
)
|
||||
add = "https://zoff.me";
|
||||
else add = window.location.hostname;
|
||||
|
||||
if (Player !== undefined && !client) {
|
||||
Player.stopInterval = false;
|
||||
}
|
||||
|
||||
if (!client) {
|
||||
//Helper.tabs('.playlist-tabs');
|
||||
Helper.tabs(".playlist-tabs-loggedIn", {
|
||||
onShow: function(e) {
|
||||
if (this.index == 2) {
|
||||
document.getElementById("text-chat-input").focus();
|
||||
Chat.channel_received = 0;
|
||||
Chat.all_received = 0;
|
||||
Helper.addClass(
|
||||
document.querySelector(".chat-link span.badge.new.white"),
|
||||
"hide"
|
||||
);
|
||||
document
|
||||
.getElementById("favicon")
|
||||
.setAttribute("href", "/assets/images/favicon.png");
|
||||
|
||||
chat_active = true;
|
||||
unseen = false;
|
||||
chat_unseen = false;
|
||||
document
|
||||
.getElementsByClassName("chat-link")[0]
|
||||
.setAttribute("style", "color: white !important;");
|
||||
blinking = false;
|
||||
//Helper.css("#chat-container", "display", "block");
|
||||
//Helper.css("#wrapper", "display", "none");
|
||||
//Helper.css("#suggestions", "display", "none");
|
||||
document.getElementById("text-chat-input").focus();
|
||||
Helper.css("#pageButtons", "display", "none");
|
||||
scrollChat();
|
||||
window.scrollTo(0, 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (window.location.hash == "#chat-container") {
|
||||
M.Tabs.getInstance(
|
||||
document.querySelector(".playlist-tabs-loggedIn")
|
||||
).select("chat-container");
|
||||
} else if (window.location.hash == "#suggestions") {
|
||||
M.Tabs.getInstance(
|
||||
document.querySelector(".playlist-tabs-loggedIn")
|
||||
).select("suggestions");
|
||||
} else if (window.location.hash == "#wrapper") {
|
||||
M.Tabs.getInstance(
|
||||
document.querySelector(".playlist-tabs-loggedIn")
|
||||
).select("wrapper");
|
||||
}
|
||||
|
||||
Helper.tabs(".chatTabs");
|
||||
}
|
||||
Helper.tabs(".results-tabs");
|
||||
var sidenavElem = document.getElementsByClassName("sidenav")[0];
|
||||
M.Sidenav.init(sidenavElem, {
|
||||
menuWidth: 310,
|
||||
edge: side,
|
||||
closeOnClick: false,
|
||||
draggable: Helper.mobilecheck(),
|
||||
onOpenStart: function(el) {
|
||||
Helper.addClass(".hamburger-sidenav", "open");
|
||||
},
|
||||
onCloseStart: function(el) {
|
||||
Helper.removeClass(".hamburger-sidenav", "open");
|
||||
}
|
||||
});
|
||||
M.Collapsible.init(
|
||||
document.getElementsByClassName("settings-collapsible")[0],
|
||||
{
|
||||
accordion: true
|
||||
}
|
||||
);
|
||||
|
||||
if (!client) {
|
||||
M.Modal.init(document.getElementById("embed"), {
|
||||
onCloseStart: function() {
|
||||
document.querySelector(".embed-preview").innerHTML = "";
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Helper.removeElement("#embed");
|
||||
Helper.removeElement(".embed-button-footer");
|
||||
Helper.removeElement(".tabs");
|
||||
}
|
||||
M.Modal.init(document.getElementById("advanced_filter"), {
|
||||
onCloseEnd: function() {
|
||||
document.querySelector(".filter-results").innerHTML = "";
|
||||
document.getElementById("filtersearch_input").value = "";
|
||||
document.getElementById("filtersearch_input").blur();
|
||||
},
|
||||
onOpenEnd: function() {
|
||||
document.getElementById("filtersearch_input").focus();
|
||||
}
|
||||
});
|
||||
|
||||
M.FormSelect.init(document.querySelector(".category-advanced-select"));
|
||||
M.Modal.init(document.getElementById("help"));
|
||||
M.Modal.init(document.getElementById("contact"));
|
||||
M.Modal.init(document.getElementById("channel-share-modal"));
|
||||
M.Modal.init(document.getElementById("delete_song_alert"), {
|
||||
dismissible: false
|
||||
});
|
||||
M.Modal.init(document.getElementById("user_password"), {
|
||||
dismissible: false
|
||||
});
|
||||
|
||||
Channel.spotify_is_authenticated(spotify_authenticated);
|
||||
|
||||
result_html = document.getElementById("temp-results-container");
|
||||
pagination_buttons_html =
|
||||
"<div class='pagination-results'>" +
|
||||
document.getElementsByClassName("pagination-results")[0].cloneNode(true)
|
||||
.innerHTML +
|
||||
"</div>";
|
||||
empty_results_html = Helper.html("#empty-results-container");
|
||||
not_import_html = Helper.html(".not-imported-container");
|
||||
not_export_html = Helper.html(".not-exported-container");
|
||||
Helper.setHtml(".not-imported-container", "");
|
||||
Helper.setHtml(".not-exported-container", "");
|
||||
|
||||
if (socket === undefined) {
|
||||
no_socket = false;
|
||||
if (window.location.port != "") {
|
||||
add = add + ":" + window.location.port + "/";
|
||||
}
|
||||
socket = io.connect(
|
||||
"" + add,
|
||||
connection_options
|
||||
);
|
||||
socket.on("update_required", function(msg) {
|
||||
if (window.location.hostname == "localhost") {
|
||||
console.error(msg);
|
||||
return;
|
||||
}
|
||||
window.location.reload(true);
|
||||
});
|
||||
}
|
||||
|
||||
Crypt.init();
|
||||
|
||||
setup_auth_listener();
|
||||
|
||||
if (Crypt.get_offline()) {
|
||||
document.getElementsByClassName("offline_switch_class")[0].checked = true;
|
||||
change_offline(true, offline);
|
||||
}
|
||||
if (
|
||||
!Helper.mobilecheck() &&
|
||||
(document.querySelectorAll("#alreadychannel").length === 0 ||
|
||||
!Hostcontroller.old_id ||
|
||||
document.getElementById("code-text").innerText.toUpperCase() ==
|
||||
"ABBADUR")
|
||||
)
|
||||
setup_host_initialization();
|
||||
setup_suggested_listener();
|
||||
if (!Helper.mobilecheck()) {
|
||||
showOnSmallNotMobile();
|
||||
}
|
||||
if (
|
||||
document.querySelectorAll("#alreadychannel").length === 0 ||
|
||||
Helper.mobilecheck()
|
||||
) {
|
||||
setup_now_playing_listener();
|
||||
get_list_listener();
|
||||
|
||||
if (!client) {
|
||||
setup_viewers_listener();
|
||||
}
|
||||
} else {
|
||||
Helper.css("#channel-load", "display", "none");
|
||||
Helper.css("#player", "opacity", "1");
|
||||
Helper.css("#controls", "opacity", "1");
|
||||
Helper.css(".playlist", "opacity", "1");
|
||||
if (!client) {
|
||||
Player.readyLooks();
|
||||
Playercontrols.initYoutubeControls(Player.player);
|
||||
Playercontrols.initSlider();
|
||||
if (player_ready) {
|
||||
try {
|
||||
Player.player.setVolume(Crypt.get_volume());
|
||||
} catch (e) {}
|
||||
try {
|
||||
if (scUsingWidget)
|
||||
Player.soundcloud_player.setVolume(
|
||||
embed ? 1 : Crypt.get_volume()
|
||||
);
|
||||
else
|
||||
Player.soundcloud_player.setVolume(
|
||||
embed ? 1 : Crypt.get_volume() / 100
|
||||
);
|
||||
} catch (e) {}
|
||||
}
|
||||
Helper.removeClass(".video-container", "no-opacity");
|
||||
var codeURL = "https://remote." + window.location.hostname + "/" + id;
|
||||
Helper.setHtml("#code-text", id);
|
||||
document
|
||||
.getElementById("code-qr")
|
||||
.setAttribute(
|
||||
"src",
|
||||
"https://chart.googleapis.com/chart?chs=221x221&cht=qr&choe=UTF-8&chld=L|1&chl=" +
|
||||
codeURL
|
||||
);
|
||||
document.getElementById("code-link").setAttribute("href", codeURL);
|
||||
}
|
||||
}
|
||||
|
||||
if (!client) {
|
||||
if (!Helper.mobilecheck()) {
|
||||
var port = window.location.port;
|
||||
if (port != "") port = ":" + port;
|
||||
var shareCodeUrl =
|
||||
window.location.protocol +
|
||||
"//client." +
|
||||
window.location.hostname +
|
||||
port +
|
||||
"/r/" +
|
||||
btoa(encodeURIComponent(chan.toLowerCase()));
|
||||
document
|
||||
.getElementById("share-join-qr")
|
||||
.setAttribute(
|
||||
"src",
|
||||
"https://chart.googleapis.com/chart?chs=221x221&cht=qr&choe=UTF-8&chld=L|1&chl=" +
|
||||
shareCodeUrl
|
||||
);
|
||||
Helper.setHtml(
|
||||
"#channel-name-join",
|
||||
"client." +
|
||||
window.location.hostname +
|
||||
port +
|
||||
"/" +
|
||||
encodeURIComponent(chan.toLowerCase())
|
||||
);
|
||||
}
|
||||
} else {
|
||||
Helper.removeElement(".video-container");
|
||||
Helper.removeElement(".offline-panel");
|
||||
Helper.removeElement(".remote-panel");
|
||||
Helper.removeElement(".mobile-remote-panel");
|
||||
Helper.removeElement(".import-panel");
|
||||
Helper.removeElement(".export-panel");
|
||||
}
|
||||
if (no_socket || Helper.mobilecheck()) {
|
||||
emit_list();
|
||||
}
|
||||
|
||||
if (!Helper.mobilecheck()) {
|
||||
if (!client) {
|
||||
Helper.tooltip("#chan", {
|
||||
delay: 5,
|
||||
position: "bottom",
|
||||
html: "Show join URL"
|
||||
});
|
||||
}
|
||||
|
||||
Helper.tooltip("#viewers", {
|
||||
delay: 5,
|
||||
position: "top",
|
||||
html: "Viewers"
|
||||
});
|
||||
|
||||
Helper.tooltip("#addToOtherList", {
|
||||
delay: 5,
|
||||
position: "top",
|
||||
html: "Add to other playlist"
|
||||
});
|
||||
|
||||
Helper.tooltip("#fullscreen", {
|
||||
delay: 5,
|
||||
position: "top",
|
||||
html: "Fullscreen"
|
||||
});
|
||||
|
||||
Helper.tooltip(".search-btn-container", {
|
||||
delay: 5,
|
||||
position: "bottom",
|
||||
html: "Search"
|
||||
});
|
||||
|
||||
Helper.tooltip(".shuffle-btn-container", {
|
||||
delay: 5,
|
||||
position: "bottom",
|
||||
html: "Shuffle"
|
||||
});
|
||||
|
||||
Helper.tooltip("#settings", {
|
||||
delay: 5,
|
||||
position: "bottom",
|
||||
html: "Settings"
|
||||
});
|
||||
}
|
||||
|
||||
if (!client) {
|
||||
window.onYouTubeIframeAPIReady = Player.onYouTubeIframeAPIReady;
|
||||
if (
|
||||
Player.player === "" ||
|
||||
Player.player === undefined ||
|
||||
Helper.mobilecheck()
|
||||
)
|
||||
Player.loadPlayer();
|
||||
} else {
|
||||
Player.loadSoundCloudPlayer();
|
||||
}
|
||||
//}
|
||||
|
||||
if (Helper.mobilecheck()) {
|
||||
if (!client) {
|
||||
Mobile_remote.initiate_volume();
|
||||
}
|
||||
Helper.addClass(".close-settings", "hide");
|
||||
} else {
|
||||
if (!client) {
|
||||
Channel.window_width_volume_slider();
|
||||
}
|
||||
}
|
||||
|
||||
setup_admin_listener();
|
||||
setup_list_listener();
|
||||
if (!client) {
|
||||
setup_chat_listener();
|
||||
get_history();
|
||||
}
|
||||
if (client || Helper.mobilecheck()) {
|
||||
get_list_ajax();
|
||||
get_np_ajax();
|
||||
}
|
||||
|
||||
try {
|
||||
if (
|
||||
!Helper.msieversion() &&
|
||||
!Helper.mobilecheck() &&
|
||||
!client &&
|
||||
Notification != undefined
|
||||
)
|
||||
Notification.requestPermission();
|
||||
} catch (e) {}
|
||||
document.getElementsByClassName("search_input")[0].focus();
|
||||
|
||||
Helper.sample();
|
||||
if (!Helper.mobilecheck() && !client) {
|
||||
Helper.tooltip(".castButton", {
|
||||
delay: 5,
|
||||
position: "top",
|
||||
html: "Cast Zoff to TV"
|
||||
});
|
||||
}
|
||||
|
||||
addListener("click", ".sp-choose-link", function(e) {
|
||||
event.preventDefault();
|
||||
document.getElementsByClassName("sp-choose")[0].click();
|
||||
});
|
||||
|
||||
//$("#results" ).hover( function() { Helper.removeClass(".result", "hoverResults"); i = 0; }, function(){ });
|
||||
document.getElementById("search").focus();
|
||||
Helper.css("#embed-button", "display", "inline-block");
|
||||
document.getElementById("search").setAttribute("placeholder", "Search...");
|
||||
|
||||
if (!client) {
|
||||
Helper.addClass("footer", "padding-bottom-novideo");
|
||||
document.getElementById("embed-area").value = embed_code(
|
||||
embed_autoplay,
|
||||
embed_width,
|
||||
embed_height,
|
||||
color,
|
||||
embed_videoonly,
|
||||
embed_localmode
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
!/chrom(e|ium)/.test(navigator.userAgent.toLowerCase()) &&
|
||||
!Helper.mobilecheck() &&
|
||||
!client
|
||||
) {
|
||||
Helper.css(".castButton", "display", "none");
|
||||
}
|
||||
|
||||
Helper.log([
|
||||
"chromecastAvailable " + chromecastAvailable,
|
||||
"chromecastReady " + chromecastReady
|
||||
]);
|
||||
|
||||
if (chromecastAvailable && !client) {
|
||||
hide_native(1);
|
||||
} else if (chromecastReady && !client) {
|
||||
initializeCastApi();
|
||||
} else if (!client) {
|
||||
window["__onGCastApiAvailable"] = function(loaded, errorInfo) {
|
||||
if (loaded) {
|
||||
setTimeout(function() {
|
||||
chromecastReady = true;
|
||||
initializeCastApi();
|
||||
}, 1000);
|
||||
} else {
|
||||
chromecastReady = true;
|
||||
}
|
||||
};
|
||||
}
|
||||
Channel.listeners(true);
|
||||
Channel.add_context_menu();
|
||||
|
||||
if (!Helper.mobilecheck() && navigator.userAgent.match(/iPad/i) == null) {
|
||||
setTimeout(function() {
|
||||
Channel.set_title_width();
|
||||
}, 100);
|
||||
}
|
||||
},
|
||||
|
||||
set_title_width: function(start) {
|
||||
if (window.innerWidth > 600) {
|
||||
var add_width = document.getElementsByClassName("brand-logo")[0]
|
||||
.offsetWidth;
|
||||
if (start) {
|
||||
add_width = window.innerWidth * 0.15;
|
||||
}
|
||||
var test_against_width =
|
||||
window.innerWidth -
|
||||
document.getElementsByClassName("control-list")[0].offsetWidth -
|
||||
add_width -
|
||||
11;
|
||||
title_width = test_against_width;
|
||||
document.getElementsByClassName("title-container")[0].style.width =
|
||||
title_width + "px";
|
||||
} else {
|
||||
document.getElementsByClassName("title-container")[0].style.width =
|
||||
"100%";
|
||||
}
|
||||
},
|
||||
|
||||
spotify_is_authenticated: function(bool) {
|
||||
if (bool) {
|
||||
Helper.log([
|
||||
"Spotify is authenticated",
|
||||
"access_token: " + access_token_data.access_token,
|
||||
"token_type:" + access_token_data.token_type,
|
||||
"expires_in: " + access_token_data.expires_in
|
||||
]);
|
||||
|
||||
Helper.css(".spotify_authenticated", "display", "block");
|
||||
Helper.css(".spotify_unauthenticated", "display", "none");
|
||||
} else {
|
||||
Helper.log(["Spotify is not authenticated"]);
|
||||
Helper.css(".spotify_authenticated", "display", "none");
|
||||
Helper.css(".spotify_unauthenticated", "display", "flex");
|
||||
}
|
||||
},
|
||||
|
||||
add_context_menu: function() {
|
||||
addListener("contextmenu", ".vote-container", function(e) {
|
||||
if (hostMode) {
|
||||
return;
|
||||
}
|
||||
this.preventDefault();
|
||||
this.preventDefault();
|
||||
var that = this;
|
||||
contextListener(e, that);
|
||||
});
|
||||
|
||||
addListener("contextmenu", ".add-suggested", function(e) {
|
||||
this.preventDefault();
|
||||
var that = this;
|
||||
contextListener(e, that);
|
||||
});
|
||||
|
||||
addListener("click", ".list-remove", function(e) {
|
||||
this.preventDefault();
|
||||
var that = this;
|
||||
contextListener(e, that);
|
||||
});
|
||||
},
|
||||
|
||||
share_link_modifier: function() {
|
||||
document
|
||||
.getElementById("facebook-code-link")
|
||||
.setAttribute(
|
||||
"href",
|
||||
"https://www.facebook.com/sharer/sharer.php?u=https://zoff.me/" +
|
||||
chan.toLowerCase()
|
||||
);
|
||||
document
|
||||
.getElementById("facebook-code-link")
|
||||
.setAttribute(
|
||||
"onclick",
|
||||
"window.open('https://www.facebook.com/sharer/sharer.php?u=https://zoff.me/" +
|
||||
chan.toLowerCase() +
|
||||
"', 'Share Playlist','width=600,height=300'); return false;"
|
||||
);
|
||||
document
|
||||
.getElementById("twitter-code-link")
|
||||
.setAttribute(
|
||||
"href",
|
||||
"https://twitter.com/intent/tweet?url=https://zoff.me/" +
|
||||
chan.toLowerCase() +
|
||||
"&text=Check%20out%20this%20playlist%20" +
|
||||
chan.toLowerCase() +
|
||||
"%20on%20Zoff!&via=zoffmusic"
|
||||
);
|
||||
document
|
||||
.getElementById("twitter-code-link")
|
||||
.setAttribute(
|
||||
"onclick",
|
||||
"window.open('https://twitter.com/intent/tweet?url=https://zoff.me/" +
|
||||
chan.toLowerCase() +
|
||||
"/&text=Check%20out%20this%20playlist%20" +
|
||||
chan.toLowerCase() +
|
||||
"%20on%20Zoff!&via=zoffmusic','Share Playlist','width=600,height=300'); return false;"
|
||||
);
|
||||
},
|
||||
|
||||
window_width_volume_slider: function() {
|
||||
if (window.innerWidth <= 600 && slider_type == "horizontal") {
|
||||
slider_type = "vertical";
|
||||
Playercontrols.initSlider();
|
||||
} else if (window.innerWidth > 600 && slider_type == "vertical") {
|
||||
slider_type = "horizontal";
|
||||
Playercontrols.initSlider();
|
||||
Helper.removeClass(".volume-container", "hide");
|
||||
}
|
||||
},
|
||||
|
||||
listeners: function(on) {
|
||||
var scrollListener = function(e) {
|
||||
if (!programscroll) {
|
||||
userscroll = true;
|
||||
if (
|
||||
document.getElementById("chatchannel").scrollTop +
|
||||
document.getElementById("chatchannel").offsetHeight >=
|
||||
document.getElementById("chatchannel").scrollHeight
|
||||
) {
|
||||
userscroll = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
var scrollAllListener = function(e) {
|
||||
if (!programscroll) {
|
||||
userscroll = true;
|
||||
if (
|
||||
document.getElementById("chatall").scrollTop +
|
||||
document.getElementById("chatall").offsetHeight >=
|
||||
document.getElementById("chatall").scrollHeight
|
||||
) {
|
||||
userscroll = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
if (!client) {
|
||||
if (on) {
|
||||
document
|
||||
.getElementById("chatchannel")
|
||||
.addEventListener("scroll", scrollListener);
|
||||
document
|
||||
.getElementById("chatall")
|
||||
.addEventListener("scroll", scrollListener);
|
||||
} else {
|
||||
document
|
||||
.getElementById("chatchannel")
|
||||
.removeEventListener("scroll", scrollListener);
|
||||
document
|
||||
.getElementById("chatall")
|
||||
.removeEventListener("scroll", scrollAllListener);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onepage_load: function() {
|
||||
if (changing_to_frontpage) return;
|
||||
if (user_auth_started) {
|
||||
clearTimeout(durationTimeout);
|
||||
Player.stopInterval = true;
|
||||
user_auth_avoid = true;
|
||||
if (!Helper.mobilecheck()) {
|
||||
Helper.tooltip(".castButton", "destroy");
|
||||
Helper.tooltip("#viewers", "destroy");
|
||||
Helper.tooltip("#addToOtherList", "destroy");
|
||||
//$('.castButton-unactive').tooltip("destroy");
|
||||
Helper.tooltip("#offline-mode", "destroy");
|
||||
Helper.tooltip("#admin-lock", "destroy");
|
||||
}
|
||||
}
|
||||
var url_split = window.location.href.split("/");
|
||||
if (
|
||||
url_split[3].substr(0, 1) != "#!" &&
|
||||
url_split[3] !== "" &&
|
||||
!(url_split.length == 5 && url_split[4].substr(0, 1) == "#")
|
||||
) {
|
||||
socket.emit("change_channel", {
|
||||
channel: channel_before_move
|
||||
});
|
||||
Admin.beginning = true;
|
||||
|
||||
chan = url_split[3].replace("#", "");
|
||||
document.getElementById("chan").innerHTML = Helper.upperFirst(chan);
|
||||
var add = "";
|
||||
w_p = true;
|
||||
//if(private_channel) add = Crypt.getCookie("_uI") + "_";
|
||||
socket.emit("list", {
|
||||
version: parseInt(_VERSION),
|
||||
channel: add + chan.toLowerCase()
|
||||
});
|
||||
} else if (url_split[3] === "") {
|
||||
Admin.display_logged_out();
|
||||
if (hostMode) {
|
||||
Helper.removeClass("#main-row", "fullscreened");
|
||||
document.querySelector(".host_switch_class").checked = false;
|
||||
enable_host_mode(false);
|
||||
}
|
||||
var channel_before_move = chan.toLowerCase();
|
||||
clearTimeout(timed_remove_check);
|
||||
changing_to_frontpage = true;
|
||||
user_change_password = false;
|
||||
clearTimeout(width_timeout);
|
||||
if (fireplace_initiated) {
|
||||
fireplace_initiated = false;
|
||||
Player.fireplace.destroy();
|
||||
Helper.css("#fireplace_player", "display", "none");
|
||||
}
|
||||
Helper.css("#channel-load", "display", "block");
|
||||
window.scrollTo(0, 0);
|
||||
|
||||
//Player.stopInterval = true;
|
||||
Admin.beginning = true;
|
||||
began = false;
|
||||
durationBegun = false;
|
||||
|
||||
Helper.css("#embed-button", "display", "none");
|
||||
if (!Helper.mobilecheck()) {
|
||||
Helper.tooltip(".castButton", "destroy");
|
||||
Helper.tooltip("#addToOtherList", "destroy");
|
||||
Helper.tooltip("#viewers", "destroy");
|
||||
Helper.tooltip("#offline-mode", "destroy");
|
||||
Helper.tooltip("search-btn", "destroy");
|
||||
Helper.tooltip("#fullscreen", "destroy");
|
||||
if (
|
||||
M.Tooltip.getInstance(document.getElementById("admin-lock")) !=
|
||||
undefined
|
||||
) {
|
||||
Helper.tooltip("#admin-lock", "destroy");
|
||||
}
|
||||
Helper.tooltip(".search-btn-container", "destroy");
|
||||
Helper.tooltip(".shuffle-btn-container", "destroy");
|
||||
Helper.tooltip("#settings", "destroy");
|
||||
}
|
||||
Helper.removeElement("#seekToDuration");
|
||||
|
||||
M.Sidenav.getInstance(
|
||||
document.getElementsByClassName("sidenav")[0]
|
||||
).destroy();
|
||||
if (!client) {
|
||||
if (!Helper.mobilecheck()) {
|
||||
Helper.tooltip("#chan", "destroy");
|
||||
}
|
||||
var tap_1 = document.querySelectorAll(".tap-target");
|
||||
if (tap_1.length > 0 && M.TapTarget.getInstance(tap_1[0])) {
|
||||
M.TapTarget.getInstance(tap_1[0]).close();
|
||||
}
|
||||
}
|
||||
clearTimeout(tap_target_timeout);
|
||||
//before_toast();
|
||||
if (Helper.mobilecheck() || user_auth_avoid || client) {
|
||||
Helper.log(["Removing all listeners"]);
|
||||
//socket.emit("change_channel");
|
||||
//removeAllListeners();
|
||||
//socket.removeEventListener(id);
|
||||
socket.emit("left_channel", {
|
||||
channel: channel_before_move
|
||||
});
|
||||
socket.emit("change_channel", {
|
||||
channel: channel_before_move
|
||||
});
|
||||
chan = "";
|
||||
socket.removeEventListener("np");
|
||||
socket.removeEventListener("id");
|
||||
socket.removeEventListener(id);
|
||||
//socket.disconnect();
|
||||
}
|
||||
socket.removeEventListener("chat.all");
|
||||
socket.removeEventListener("chat");
|
||||
socket.removeEventListener("conf");
|
||||
socket.removeEventListener("pw");
|
||||
socket.removeEventListener("toast");
|
||||
//socket.removeEventListener("id");
|
||||
socket.removeEventListener("channel");
|
||||
socket.removeEventListener("auth_required");
|
||||
socket.removeEventListener("auth_accepted");
|
||||
socket.removeEventListener("suggested");
|
||||
socket.removeEventListener("color");
|
||||
socket.removeEventListener("chat_history");
|
||||
Helper.ajax({
|
||||
url: "/",
|
||||
method: "GET",
|
||||
success: function(e) {
|
||||
if (!client) {
|
||||
document.querySelector("#hide-playlist").remove();
|
||||
if (hiddenPlaylist)
|
||||
document.querySelector("main").style.maxWidth = "";
|
||||
hiddenPlaylist = false;
|
||||
document
|
||||
.getElementById("volume-button")
|
||||
.removeEventListener("click", Playercontrols.mute_video);
|
||||
document
|
||||
.getElementById("playpause")
|
||||
.removeEventListener("click", Playercontrols.play_pause);
|
||||
document
|
||||
.getElementById("fullscreen")
|
||||
.removeEventListener("click", Playercontrols.fullscreen);
|
||||
}
|
||||
Channel.listeners(false);
|
||||
if (Helper.mobilecheck() || user_auth_avoid) {
|
||||
video_id = "";
|
||||
song_title = "";
|
||||
}
|
||||
|
||||
document
|
||||
.querySelectorAll("meta[name=theme-color]")[0]
|
||||
.setAttribute("content", "#2D2D2D");
|
||||
|
||||
if (!Helper.mobilecheck() && !user_auth_avoid) {
|
||||
Helper.removeElement("#playbar");
|
||||
Helper.removeElement("#main_components");
|
||||
Helper.addClass("#player_overlay", "player_bottom");
|
||||
Helper.addClass("#player", "player_bottom");
|
||||
Helper.addClass(".video-container", "frontpage-player");
|
||||
Helper.addClass("#main-row", "frontpage_modified_heights");
|
||||
Helper.css("#player", "opacity", "1");
|
||||
Helper.removeClass("#video-container", "no-opacity");
|
||||
document
|
||||
.getElementById("main-row")
|
||||
.insertAdjacentHTML(
|
||||
"afterbegin",
|
||||
"<div id='player_bottom_overlay' class='player player_bottom'></div>"
|
||||
);
|
||||
document
|
||||
.getElementById("player_bottom_overlay")
|
||||
.insertAdjacentHTML(
|
||||
"afterbegin",
|
||||
"<a id='closePlayer' title='Close Player'><i class='material-icons'>close</i></a>"
|
||||
);
|
||||
document
|
||||
.getElementById("player_bottom_overlay")
|
||||
.setAttribute("data-channel", channel_before_move.toLowerCase());
|
||||
Helper.removeElement("#playlist");
|
||||
} else {
|
||||
try {
|
||||
Player.player.destroy();
|
||||
} catch (error) {}
|
||||
try {
|
||||
Player.soundcloud_dead = true;
|
||||
Player.soundcloud_player.kill();
|
||||
} catch (error) {}
|
||||
Player.player = "";
|
||||
document.title = "Zoff";
|
||||
}
|
||||
|
||||
var response = document.createElement("div");
|
||||
response.innerHTML = e;
|
||||
|
||||
var newList = response.querySelector("#lists-script").innerHTML;
|
||||
newList = newList
|
||||
.trim()
|
||||
.replace("window.lists = ", "")
|
||||
.replace("window.lists=", "");
|
||||
newList = newList.substring(0, newList.length);
|
||||
window.lists = JSON.parse(newList);
|
||||
|
||||
response.querySelector("#lists-script").remove();
|
||||
Helper.removeElement("#sidenav-overlay");
|
||||
document.getElementsByTagName("main")[0].className =
|
||||
"center-align container";
|
||||
Helper.removeClass("#main-container", "channelpage");
|
||||
document.getElementById("main-container").setAttribute("style", "");
|
||||
document.getElementsByTagName(
|
||||
"header"
|
||||
)[0].innerHTML = response.querySelectorAll("header")[0].outerHTML;
|
||||
|
||||
document
|
||||
.getElementsByTagName("header")[0]
|
||||
.insertAdjacentHTML(
|
||||
"afterend",
|
||||
response.querySelectorAll(".section.mega")[0].outerHTML
|
||||
);
|
||||
//document.getElementsByTagName("header")[0].insertAdjacentHTML("afterend", response.querySelectorAll(".section.mobile-search")[0].innerHTML);
|
||||
if (Helper.mobilecheck() || user_auth_avoid) {
|
||||
document.getElementsByTagName(
|
||||
"main"
|
||||
)[0].innerHTML = response.querySelectorAll("main")[0].innerHTML;
|
||||
} else {
|
||||
document
|
||||
.getElementsByTagName("main")[0]
|
||||
.insertAdjacentHTML(
|
||||
"beforeend",
|
||||
response.querySelectorAll("#main_section_frontpage")[0]
|
||||
.outerHTML
|
||||
);
|
||||
}
|
||||
Helper.removeClass(".page-footer", "padding-bottom-extra");
|
||||
Helper.removeClass(".page-footer", "padding-bottom-novideo");
|
||||
document
|
||||
.getElementById("favicon")
|
||||
.setAttribute("href", "/assets/images/favicon-32x32.png");
|
||||
|
||||
Helper.log(["Socket", socket]);
|
||||
if (document.querySelectorAll("#alreadyfp").length == 1) {
|
||||
Frontpage.init();
|
||||
} else {
|
||||
fromChannel = true;
|
||||
frontpage = true;
|
||||
Frontpage.init();
|
||||
}
|
||||
|
||||
changing_to_frontpage = false;
|
||||
|
||||
if (
|
||||
document.querySelectorAll("#alreadychannel").length === 0 &&
|
||||
!user_auth_avoid
|
||||
) {
|
||||
document
|
||||
.getElementsByTagName("head")[0]
|
||||
.insertAdjacentHTML(
|
||||
"beforeend",
|
||||
"<div id='alreadychannel'></div"
|
||||
);
|
||||
} else if (user_auth_avoid) {
|
||||
Helper.removeElement("#alreadychannel");
|
||||
}
|
||||
Helper.css("#channel-load", "display", "none");
|
||||
user_auth_avoid = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function get_history() {
|
||||
if (socket && socket.id) {
|
||||
/*var p = Crypt.get_userpass();
|
||||
if(p == undefined) p = "";
|
||||
var c = Crypt.crypt_pass(p, true);
|
||||
if(c == undefined) c = "";*/
|
||||
socket.emit("get_history", { channel: chan.toLowerCase(), all: false });
|
||||
socket.emit("get_history", { channel: chan.toLowerCase(), all: true });
|
||||
} else {
|
||||
setTimeout(function() {
|
||||
get_history();
|
||||
}, 50);
|
||||
}
|
||||
}
|
||||
311
server/public/assets/js/chat.js
Executable file
@@ -0,0 +1,311 @@
|
||||
var Chat = {
|
||||
channel_received: 0,
|
||||
all_received: 0,
|
||||
chat_admin_help: [
|
||||
"/ban USERNAME REASON to ban user",
|
||||
"/unban USERNAME to unban a user"
|
||||
],
|
||||
chat_help: [
|
||||
"/login <new name> <password> to register and save a password for a nickname, or to log in with a password on a name.",
|
||||
"/login <name> <new_password> <old_password> to change the password on a nickname",
|
||||
"/logout to logout",
|
||||
"/who to see the names of the people in the channel",
|
||||
"Want your own icon besides your name? If you donate 5$ or more, we'll add a picture of your choosing (following our guidelines) besides your name!"
|
||||
],
|
||||
|
||||
namechange: function(data, first, initial) {
|
||||
var input = data.split(" ");
|
||||
if (input.length == 2) {
|
||||
var name = input[0];
|
||||
var password = input[1];
|
||||
|
||||
password = Crypt.crypt_chat_pass(password);
|
||||
socket.emit("namechange", {
|
||||
name: name,
|
||||
channel: chan.toLowerCase(),
|
||||
password: password,
|
||||
first: first
|
||||
});
|
||||
} else if (input.length == 3) {
|
||||
var name = input[0];
|
||||
var new_password = input[1];
|
||||
var old_password = input[2];
|
||||
|
||||
new_password = Crypt.crypt_chat_pass(new_password);
|
||||
old_password = Crypt.crypt_chat_pass(old_password);
|
||||
|
||||
socket.emit("namechange", {
|
||||
name: name,
|
||||
channel: chan.toLowerCase(),
|
||||
new_password: new_password,
|
||||
old_password: old_password
|
||||
});
|
||||
} else if (first) {
|
||||
var to_send = { initial: initial, first: true };
|
||||
if (chan != undefined && chan != "") {
|
||||
to_send.channel = chan.toLowerCase();
|
||||
}
|
||||
socket.emit("namechange", to_send);
|
||||
}
|
||||
},
|
||||
|
||||
removename: function() {
|
||||
socket.emit("removename", { channel: chan.toLowerCase() });
|
||||
Crypt.remove_name();
|
||||
},
|
||||
|
||||
chat: function(data) {
|
||||
if (data.value.length > 150) return;
|
||||
if (
|
||||
data.value.startsWith("/name ") ||
|
||||
data.value.startsWith("/removename")
|
||||
) {
|
||||
data.value = "/help";
|
||||
Chat.chat(data);
|
||||
return;
|
||||
} else if (data.value.startsWith("/login ")) {
|
||||
Chat.namechange(data.value.substring(7), false);
|
||||
} else if (data.value.startsWith("/help")) {
|
||||
var add = "";
|
||||
if (
|
||||
document.querySelector(".chat-tab-li a.active").getAttribute("href") ==
|
||||
"#all_chat"
|
||||
) {
|
||||
if (document.querySelector("#chatall").children.length > 100) {
|
||||
document.querySelector("#chatall").children[0].remove();
|
||||
}
|
||||
add = "chatall";
|
||||
} else {
|
||||
if (document.querySelector("#chatchannel").children.length > 100) {
|
||||
document.querySelector("#chatchannel").children[0].remove();
|
||||
}
|
||||
add = "chatchannel";
|
||||
}
|
||||
var help = Chat.chat_help;
|
||||
if (Admin.logged_in) help = help.concat(Chat.chat_admin_help);
|
||||
for (var x = 0; x < help.length; x++) {
|
||||
var color = Helper.intToARGB(Helper.hashCode("System"));
|
||||
if (color.length < 6) {
|
||||
for (x = color.length; x < 6; x++) {
|
||||
color = "0" + color;
|
||||
}
|
||||
}
|
||||
var _time = new Date();
|
||||
var time =
|
||||
Helper.pad(_time.getHours()) + ":" + Helper.pad(_time.getMinutes());
|
||||
color = Helper.hexToRgb(color.substring(0, 6));
|
||||
var color_temp = Helper.rgbToHsl([color.r, color.g, color.b], false);
|
||||
document
|
||||
.querySelector("#" + add)
|
||||
.insertAdjacentHTML(
|
||||
"beforeend",
|
||||
"<li title='Zoff''><span class='time_color'>" +
|
||||
time +
|
||||
"</span> <img class='chat-icon' src='https://zoff.me/assets/images/favicon-32x32.png' alt='System'><span style='color:" +
|
||||
color_temp +
|
||||
";'>System</span>: </li>"
|
||||
);
|
||||
var in_text = document.createTextNode(help[x]);
|
||||
document
|
||||
.querySelector("#" + add)
|
||||
.children[
|
||||
document.querySelector("#" + add).children.length - 1
|
||||
].appendChild(in_text);
|
||||
document.getElementById("" + add).scrollTop = document.getElementById(
|
||||
"" + add
|
||||
).scrollHeight;
|
||||
}
|
||||
} else if (data.value.startsWith("/logout")) {
|
||||
Chat.removename();
|
||||
} else if (
|
||||
document.querySelector(".chat-tab-li a.active").getAttribute("href") ==
|
||||
"#all_chat"
|
||||
) {
|
||||
socket.emit("all,chat", {
|
||||
channel: chan.toLowerCase(),
|
||||
data: data.value
|
||||
});
|
||||
} else {
|
||||
socket.emit("chat", { channel: chan.toLowerCase(), data: data.value });
|
||||
}
|
||||
data.value = "";
|
||||
return;
|
||||
},
|
||||
|
||||
createChatElement: function(
|
||||
allchat,
|
||||
channel,
|
||||
time,
|
||||
icon,
|
||||
color,
|
||||
from,
|
||||
message
|
||||
) {
|
||||
var liElement = document.createElement("li");
|
||||
liElement.innerHTML +=
|
||||
"<span class='time_color'>" + time + "</span> " + icon;
|
||||
var nameElement = document.createElement("span");
|
||||
nameElement.innerText = from;
|
||||
nameElement.style.color = color;
|
||||
liElement.appendChild(nameElement);
|
||||
if (allchat) {
|
||||
liElement.title = channel;
|
||||
liElement.innerHTML +=
|
||||
"<span class='channel-info-all-chat'> " + channel + "</span>";
|
||||
}
|
||||
var in_text = document.createTextNode(message);
|
||||
liElement.appendChild(in_text);
|
||||
return liElement;
|
||||
},
|
||||
|
||||
allchat: function(inp, time_sent, disable_blink) {
|
||||
if (inp.msg.substring(0, 1) == ":" && !chat_active && !disable_blink) {
|
||||
Chat.all_received += 1;
|
||||
document
|
||||
.querySelector("#favicon")
|
||||
.getAttribute("href", "/assets/images/highlogo.png");
|
||||
unseen = true;
|
||||
chat_unseen = true;
|
||||
Helper.removeClass(
|
||||
document.querySelector(".chat-link span.badge.new.white"),
|
||||
"hide"
|
||||
);
|
||||
var to_display =
|
||||
Chat.channel_received + Chat.all_received > 9
|
||||
? "9+"
|
||||
: Chat.channel_received + Chat.all_received;
|
||||
Helper.setHtml(
|
||||
document.querySelector(".chat-link span.badge.new.white"),
|
||||
to_display
|
||||
);
|
||||
}
|
||||
|
||||
if (document.hidden) {
|
||||
document
|
||||
.getElementById("favicon")
|
||||
.setAttribute("href", "/assets/images/highlogo.png");
|
||||
}
|
||||
|
||||
if (document.querySelector("#chatall").children.length > 100) {
|
||||
document.querySelector("#chatall").children[0].remove();
|
||||
}
|
||||
var color = Helper.intToARGB(Helper.hashCode(inp.from));
|
||||
if (color.length < 6) {
|
||||
for (x = color.length; x < 6; x++) {
|
||||
color = "0" + color;
|
||||
}
|
||||
}
|
||||
var icon_add = "";
|
||||
if (inp.hasOwnProperty("icon") && inp.icon !== false && inp.icon != "") {
|
||||
icon_add =
|
||||
"<img class='chat-icon' src='" + inp.icon + "' alt='" + inp.from + "'>";
|
||||
}
|
||||
|
||||
color = Helper.hexToRgb(color.substring(0, 6));
|
||||
var color_temp = Helper.rgbToHsl([color.r, color.g, color.b], false);
|
||||
var _time = new Date();
|
||||
if (time_sent) {
|
||||
_time = new Date(time_sent);
|
||||
}
|
||||
var time =
|
||||
Helper.pad(_time.getHours()) + ":" + Helper.pad(_time.getMinutes());
|
||||
var element = Chat.createChatElement(
|
||||
true,
|
||||
Helper.decodeChannelName(inp.channel),
|
||||
time,
|
||||
icon_add,
|
||||
color_temp,
|
||||
inp.from,
|
||||
inp.msg
|
||||
);
|
||||
//document.querySelector("#chatall").insertAdjacentHTML("beforeend", element);
|
||||
document.querySelector("#chatall").appendChild(element);
|
||||
if (!userscroll) {
|
||||
programscroll = true;
|
||||
document.getElementById("chatall").scrollTop = document.getElementById(
|
||||
"chatall"
|
||||
).scrollHeight;
|
||||
programscroll = false;
|
||||
}
|
||||
},
|
||||
|
||||
channelchat: function(data, time_sent, disable_blink) {
|
||||
if (
|
||||
data.msg.substring(0, 1) == ":" &&
|
||||
!chat_active &&
|
||||
!disable_blink &&
|
||||
data.from.toLowerCase() != "system"
|
||||
) {
|
||||
document
|
||||
.querySelector("#favicon")
|
||||
.setAttribute("href", "/assets/images/highlogo.png");
|
||||
unseen = true;
|
||||
chat_unseen = true;
|
||||
Chat.channel_received += 1;
|
||||
//blink_interval = setTimeout(Chat.chat_blink, 1000);
|
||||
Helper.removeClass(
|
||||
document.querySelector(".chat-link span.badge.new.white"),
|
||||
"hide"
|
||||
);
|
||||
var to_display =
|
||||
Chat.channel_received + Chat.all_received > 9
|
||||
? "9+"
|
||||
: Chat.channel_received + Chat.all_received;
|
||||
Helper.setHtml(
|
||||
document.querySelector(".chat-link span.badge.new.white"),
|
||||
to_display
|
||||
);
|
||||
}
|
||||
|
||||
if (document.querySelector("#chatchannel").children.length > 100) {
|
||||
document.querySelector("#chatchannel").children[0].remove();
|
||||
}
|
||||
|
||||
var icon_add = "";
|
||||
if (data.hasOwnProperty("icon") && data.icon !== false && data.icon != "") {
|
||||
icon_add =
|
||||
"<img class='chat-icon' src='" +
|
||||
data.icon +
|
||||
"' alt='" +
|
||||
data.from +
|
||||
"'>";
|
||||
}
|
||||
|
||||
var color = Helper.intToARGB(Helper.hashCode(data.from));
|
||||
if (color.length < 6) {
|
||||
for (x = color.length; x < 6; x++) {
|
||||
color = "0" + color;
|
||||
}
|
||||
}
|
||||
color = Helper.hexToRgb(color.substring(0, 6));
|
||||
var color_temp = Helper.rgbToHsl([color.r, color.g, color.b], false);
|
||||
var _time = new Date();
|
||||
if (time_sent) {
|
||||
_time = new Date(time_sent);
|
||||
}
|
||||
var time =
|
||||
Helper.pad(_time.getHours()) + ":" + Helper.pad(_time.getMinutes());
|
||||
//document.querySelector("#chatchannel").insertAdjacentHTML("beforeend", "<li><span class='time_color'>" + time + "</span> " + icon_add + "<span style='color:"+color_temp+";'>"+data.from+"</span></li>");
|
||||
//var in_text = document.createTextNode(data.msg);
|
||||
//document.querySelector("#chatchannel").children[document.querySelector("#chatchannel").children.length - 1].appendChild(in_text);
|
||||
var element = Chat.createChatElement(
|
||||
false,
|
||||
null,
|
||||
time,
|
||||
icon_add,
|
||||
color_temp,
|
||||
data.from,
|
||||
data.msg
|
||||
);
|
||||
//document.querySelector("#chatall").insertAdjacentHTML("beforeend", element);
|
||||
document.querySelector("#chatchannel").appendChild(element);
|
||||
|
||||
if (!userscroll) {
|
||||
programscroll = true;
|
||||
document.getElementById(
|
||||
"chatchannel"
|
||||
).scrollTop = document.getElementById("chatchannel").scrollHeight;
|
||||
programscroll = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
358
server/public/assets/js/crypt.js
Executable file
@@ -0,0 +1,358 @@
|
||||
var Crypt = {
|
||||
conf_pass: undefined,
|
||||
user_pass: undefined,
|
||||
tmp_pass_user: "",
|
||||
tmp_pass: "",
|
||||
|
||||
init: function() {
|
||||
if (window.location.pathname != "/") {
|
||||
if (location.protocol != "https:") {
|
||||
document.cookie =
|
||||
chan.toLowerCase() +
|
||||
"=;path=/" +
|
||||
chan.toLowerCase() +
|
||||
";expires=" +
|
||||
new Date(0).toUTCString();
|
||||
} else {
|
||||
document.cookie =
|
||||
chan.toLowerCase() +
|
||||
"=;path=/" +
|
||||
chan.toLowerCase() +
|
||||
";secure;expires=" +
|
||||
new Date(0).toUTCString();
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
conf_arr = Crypt.decrypt(Crypt.getCookie("_opt"), "_opt");
|
||||
} catch (err) {
|
||||
conf_arr = Crypt.decrypt(Crypt.create_cookie("_opt"), "_opt");
|
||||
}
|
||||
|
||||
if (window.location.pathname != "/") {
|
||||
change_intelligent(Crypt.get_intelligent_list_enabled());
|
||||
if (!conf_arr.hasOwnProperty("color")) {
|
||||
Crypt.set_background_color("dynamic", true);
|
||||
} else {
|
||||
document.querySelector(".backround_switch_class").checked =
|
||||
conf_arr.color == "dynamic";
|
||||
if (conf_arr.color != "dynamic") {
|
||||
Helper.removeClass(".background_color_container", "hide");
|
||||
document.querySelector("#background_color_choser").value =
|
||||
conf_arr.color;
|
||||
}
|
||||
}
|
||||
Hostcontroller.change_enabled(conf_arr.remote);
|
||||
if (conf_arr.width != 100) Player.set_width(conf_arr.width);
|
||||
}
|
||||
},
|
||||
|
||||
set_background_color: function(value, first) {
|
||||
conf_arr.color = value;
|
||||
if (value != "dynamic" && !first) {
|
||||
Helper.css("#main-container", "background-color", value);
|
||||
Helper.css("#nav", "background-color", value);
|
||||
Helper.css(".title-container", "background-color", value);
|
||||
document
|
||||
.querySelector("meta[name=theme-color]")
|
||||
.setAttribute("content", value);
|
||||
Helper.css("#controls", "background", value);
|
||||
} else if (!first) {
|
||||
var url = "https://img.youtube.com/vi/" + Player.np.id + "/mqdefault.jpg";
|
||||
if (videoSource == "soundcloud") url = Player.np.thumbnail;
|
||||
getColor(url);
|
||||
}
|
||||
Crypt.encrypt(conf_arr, "_opt");
|
||||
},
|
||||
|
||||
get_background_color: function(value) {
|
||||
if (!conf_arr.hasOwnProperty("color")) {
|
||||
Crypt.set_background_color("dynamic");
|
||||
}
|
||||
return conf_arr.color;
|
||||
},
|
||||
|
||||
get_intelligent_list_enabled: function() {
|
||||
if (conf_arr.hasOwnProperty("intelligent")) {
|
||||
return conf_arr.intelligent;
|
||||
} else {
|
||||
conf_arr.intelligent = false;
|
||||
Crypt.encrypt(conf_arr, "_opt");
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
set_intelligent_list_enabled: function(enabled) {
|
||||
conf_arr.intelligent = enabled;
|
||||
if (Helper.mobilecheck()) {
|
||||
intelligentList = enabled;
|
||||
}
|
||||
Crypt.encrypt(conf_arr, "_opt");
|
||||
},
|
||||
|
||||
decrypt: function(cookie, name) {
|
||||
if (Crypt.getCookie(name) === undefined) {
|
||||
cookie = Crypt.create_cookie(name);
|
||||
}
|
||||
if (cookie == undefined && name == "_opt")
|
||||
return {
|
||||
volume: 100,
|
||||
width: 100,
|
||||
remote: true,
|
||||
name: "",
|
||||
offline: false
|
||||
};
|
||||
/*var key = btoa("0103060703080703080701") + btoa("0103060703080703080701");
|
||||
key = key.substring(0,32);
|
||||
key = btoa(key);
|
||||
var decrypted = CryptoJS.AES.decrypt(
|
||||
cookie,key,
|
||||
{
|
||||
mode: CryptoJS.mode.CBC,
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
}
|
||||
);*/
|
||||
|
||||
//return $.parseJSON(decrypted.toString(CryptoJS.enc.Utf8));
|
||||
return JSON.parse(atob(cookie));
|
||||
},
|
||||
|
||||
decrypt_pass: function(pass) {
|
||||
if (socket) {
|
||||
/*var key = btoa(socket.id) + btoa(socket.id);
|
||||
key = key.substring(0,32);
|
||||
key = btoa(key);
|
||||
var decrypted = CryptoJS.AES.decrypt(
|
||||
pass,key,
|
||||
{
|
||||
mode: CryptoJS.mode.CBC,
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
}
|
||||
);
|
||||
return decrypted.toString(CryptoJS.enc.Utf8);*/
|
||||
return atob(pass);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
encrypt: function(json_formated, cookie) {
|
||||
var to_encrypt = JSON.stringify(json_formated);
|
||||
/*var key = btoa("0103060703080703080701") + btoa("0103060703080703080701");
|
||||
key = key.substring(0,32);
|
||||
key = btoa(key);
|
||||
var encrypted = CryptoJS.AES.encrypt(
|
||||
to_encrypt,
|
||||
key,
|
||||
{
|
||||
mode: CryptoJS.mode.CBC,
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
}
|
||||
);*/
|
||||
var encrypted = btoa(to_encrypt);
|
||||
var CookieDate = new Date();
|
||||
CookieDate.setFullYear(CookieDate.getFullYear() + 1);
|
||||
if (location.protocol != "https:") {
|
||||
document.cookie =
|
||||
cookie +
|
||||
"=" +
|
||||
encrypted.toString() +
|
||||
";expires=" +
|
||||
CookieDate.toGMTString() +
|
||||
";path=/;";
|
||||
} else {
|
||||
document.cookie =
|
||||
cookie +
|
||||
"=" +
|
||||
encrypted.toString() +
|
||||
";secure;expires=" +
|
||||
CookieDate.toGMTString() +
|
||||
";path=/;";
|
||||
}
|
||||
},
|
||||
|
||||
get_volume: function() {
|
||||
return Crypt.decrypt(Crypt.getCookie("_opt"), "_opt").volume;
|
||||
//return conf_arr.volume;
|
||||
},
|
||||
|
||||
get_offline: function() {
|
||||
var temp_offline = Crypt.decrypt(Crypt.getCookie("_opt"), "_opt").offline;
|
||||
if (temp_offline != undefined) {
|
||||
return Crypt.decrypt(Crypt.getCookie("_opt"), "_opt").offline;
|
||||
} else {
|
||||
Crypt.set_offline(false);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
set_volume: function(val) {
|
||||
conf_arr.volume = val;
|
||||
Crypt.encrypt(conf_arr, "_opt");
|
||||
},
|
||||
|
||||
create_cookie: function(name) {
|
||||
if (name == "_opt")
|
||||
cookie_object = {
|
||||
volume: 100,
|
||||
width: 100,
|
||||
remote: true,
|
||||
name: "",
|
||||
offline: false
|
||||
};
|
||||
else cookie_object = { passwords: {} };
|
||||
|
||||
var string_it = JSON.stringify(cookie_object);
|
||||
/*var key = btoa("0103060703080703080701") + btoa("0103060703080703080701");
|
||||
key = key.substring(0,32);
|
||||
key = btoa(key);
|
||||
var encrypted = CryptoJS.AES.encrypt(
|
||||
string_it,
|
||||
key,
|
||||
{
|
||||
mode: CryptoJS.mode.CBC,
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
}
|
||||
);*/
|
||||
var encrypted = btoa(string_it);
|
||||
|
||||
var CookieDate = new Date();
|
||||
CookieDate.setFullYear(CookieDate.getFullYear() + 1);
|
||||
|
||||
if (location.protocol != "https:") {
|
||||
document.cookie =
|
||||
name +
|
||||
"=" +
|
||||
encrypted.toString() +
|
||||
";expires=" +
|
||||
CookieDate.toGMTString() +
|
||||
";path=/;";
|
||||
} else {
|
||||
document.cookie =
|
||||
name +
|
||||
"=" +
|
||||
encrypted.toString() +
|
||||
";secure;expires=" +
|
||||
CookieDate.toGMTString() +
|
||||
";path=/;";
|
||||
}
|
||||
//document.cookie = name+"="+encrypted.toString()+";expires="+CookieDate.toGMTString()+";path=/;"
|
||||
//document.cookie = na"="+encrypted.toString()+";expires="+CookieDate.toGMTString()+";path=/;"
|
||||
return Crypt.getCookie(name);
|
||||
},
|
||||
|
||||
/*set_pass: function(chan, pass) {
|
||||
Crypt.conf_pass.passwords[chan] = pass;
|
||||
Crypt.encrypt(Crypt.conf_pass, chan);
|
||||
},
|
||||
|
||||
remove_pass:function(chan) {
|
||||
delete Crypt.conf_pass.passwords[chan];
|
||||
Crypt.encrypt(Crypt.conf_pass, chan.toLowerCase());
|
||||
},
|
||||
|
||||
set_userpass: function(chan, pass) {
|
||||
Crypt.conf_pass.passwords["userpass"] = pass;
|
||||
Crypt.encrypt(Crypt.conf_pass, chan);
|
||||
},
|
||||
|
||||
remove_userpass:function(chan) {
|
||||
delete Crypt.conf_pass.passwords["userpass"];
|
||||
Crypt.encrypt(Crypt.conf_pass, chan.toLowerCase());
|
||||
},*/
|
||||
|
||||
set_name: function(name, pass) {
|
||||
conf_arr.name = encodeURIComponent(name).replace(/\W/g, "");
|
||||
conf_arr.chat_pass = pass;
|
||||
Crypt.encrypt(conf_arr, "_opt");
|
||||
},
|
||||
|
||||
set_offline: function(enabled) {
|
||||
conf_arr.offline = enabled;
|
||||
Crypt.encrypt(conf_arr, "_opt");
|
||||
},
|
||||
|
||||
remove_name: function() {
|
||||
conf_arr.name = "";
|
||||
conf_arr.chat_pass = "";
|
||||
Crypt.encrypt(conf_arr, "_opt");
|
||||
},
|
||||
|
||||
get_pass: function(chan) {
|
||||
if (Crypt.conf_pass !== undefined) return Crypt.conf_pass.passwords[chan];
|
||||
return undefined;
|
||||
},
|
||||
|
||||
get_userpass: function(chan) {
|
||||
if (Crypt.conf_pass !== undefined)
|
||||
return Crypt.conf_pass.passwords["userpass"];
|
||||
return "";
|
||||
},
|
||||
|
||||
set_remote: function(val) {
|
||||
conf_arr.remote = val;
|
||||
Crypt.encrypt(conf_arr, "_opt");
|
||||
},
|
||||
|
||||
get_remote: function(val) {
|
||||
return conf_arr.remote;
|
||||
},
|
||||
|
||||
crypt_chat_pass: function(pass) {
|
||||
/*var key = btoa(socket.id) + btoa(socket.id);
|
||||
key = key.substring(0,32);
|
||||
key = btoa(key);
|
||||
var iv = btoa(Crypt.makeiv());
|
||||
var encrypted = CryptoJS.AES.encrypt(
|
||||
pass,
|
||||
CryptoJS.enc.Base64.parse(key),
|
||||
{
|
||||
mode: CryptoJS.mode.CBC,
|
||||
padding: CryptoJS.pad.Pkcs7,
|
||||
iv: CryptoJS.enc.Base64.parse(iv),
|
||||
}
|
||||
);*/
|
||||
//window.encrypted = encrypted;
|
||||
return btoa(pass);
|
||||
//return encrypted.toString() + "$" + iv;
|
||||
},
|
||||
|
||||
crypt_pass: function(pass, userpass) {
|
||||
if (userpass) {
|
||||
Crypt.tmp_pass_user = pass;
|
||||
} else {
|
||||
Crypt.tmp_pass = pass;
|
||||
}
|
||||
//return Crypt.crypt_chat_pass(pass);
|
||||
return btoa(pass);
|
||||
},
|
||||
|
||||
makeiv: function() {
|
||||
var text = "";
|
||||
var possible =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
|
||||
for (var i = 0; i < 16; i++)
|
||||
text += possible.charAt(Math.floor(Math.random() * possible.length));
|
||||
|
||||
return text;
|
||||
},
|
||||
|
||||
get_width: function() {
|
||||
return conf_arr.width;
|
||||
},
|
||||
|
||||
set_width: function(val) {
|
||||
conf_arr.width = val;
|
||||
Crypt.encrypt(conf_arr, "_opt");
|
||||
},
|
||||
|
||||
getCookie: function(name) {
|
||||
var value = "; " + document.cookie;
|
||||
var parts = value.split("; " + name + "=");
|
||||
if (parts.length == 2)
|
||||
return parts
|
||||
.pop()
|
||||
.split(";")
|
||||
.shift();
|
||||
}
|
||||
};
|
||||
534
server/public/assets/js/embed.js
Executable file
@@ -0,0 +1,534 @@
|
||||
var slider_type = "horizontal";
|
||||
var timed_remove_check;
|
||||
var gotten_np = false;
|
||||
var song_title = "";
|
||||
var paused = false;
|
||||
var intelligentList = false;
|
||||
var client = false;
|
||||
var _VERSION;
|
||||
try {
|
||||
_VERSION = localStorage.getItem("VERSION");
|
||||
if (_VERSION == null || _VERSION == undefined) throw "Some error";
|
||||
} catch (e) {
|
||||
_VERSION = 6;
|
||||
}
|
||||
var SC_widget;
|
||||
var scUsingWidget = false;
|
||||
var zoff_api_token = "DwpnKVkaMH2HdcpJT2YPy783SY33byF5/32rbs0+xdU=";
|
||||
if (
|
||||
window.location.hostname == "localhost" ||
|
||||
window.location.hostname == "client.localhost"
|
||||
) {
|
||||
var zoff_api_token = "AhmC4Yg2BhaWPZBXeoWK96DAiAVfbou8TUG2IXtD3ZQ=";
|
||||
}
|
||||
var SC_player;
|
||||
var durationTimeout;
|
||||
var intelligentQueue = [];
|
||||
var deleted_elements = 0;
|
||||
var sc_need_initialization = true;
|
||||
var sc_initialized = false;
|
||||
var startTime = 0;
|
||||
var small = false;
|
||||
var small_player = false;
|
||||
var full_playlist = [];
|
||||
var hostMode = false;
|
||||
var soundcloud_enabled = true;
|
||||
var socket_connected = false;
|
||||
var dynamicListeners = {};
|
||||
var player_ready = false;
|
||||
var previousSoundcloud;
|
||||
var buffering = false;
|
||||
var prev_chan_list = "";
|
||||
var local_new_channel = false;
|
||||
var empty_clear = false;
|
||||
var fix_too_far = false;
|
||||
var beginning = false;
|
||||
var soundcloud_loading = false;
|
||||
var videoSource = "";
|
||||
var list_html = document.getElementById("list-song-html").innerHTML;
|
||||
var w_p = true;
|
||||
var lazy_load = false;
|
||||
var end_programmatically = false;
|
||||
var embed = true;
|
||||
var vol = 100;
|
||||
var adminpass = "";
|
||||
var mobile_beginning = false;
|
||||
var durationBegun = false;
|
||||
var chromecastAvailable = false;
|
||||
var private_channel = false;
|
||||
var was_stopped = false;
|
||||
var offline = false;
|
||||
var began = false;
|
||||
var seekTo;
|
||||
var socket;
|
||||
var video_id;
|
||||
var embedOptions = getSearch(window.location.search);
|
||||
var chan = Helper.decodeChannelName(embedOptions["channel"]);
|
||||
var autoplay = embedOptions["autoplay"];
|
||||
var videoonly = embedOptions["videoonly"];
|
||||
var color = "#" + embedOptions["color"];
|
||||
var localmode = embedOptions["localmode"];
|
||||
var dragging = false;
|
||||
var user_auth_started = false;
|
||||
var user_auth_avoid = false;
|
||||
|
||||
var connection_options = {
|
||||
"sync disconnect on unload": true,
|
||||
secure: true,
|
||||
"force new connection": true
|
||||
};
|
||||
|
||||
var Crypt = {
|
||||
crypt_pass: function(pass) {
|
||||
return pass;
|
||||
},
|
||||
get_background_color: function() {
|
||||
return "dynamic";
|
||||
}
|
||||
};
|
||||
|
||||
function receiveMessage(event) {
|
||||
if (event.data == "parent") {
|
||||
window.parentWindow = event.source;
|
||||
window.parentOrigin = event.origin;
|
||||
}
|
||||
if (event.data == "lower") {
|
||||
window.setVolume(10);
|
||||
} else if (event.data == "reset") {
|
||||
window.setVolume(100);
|
||||
} else if (event.data == "get_info") {
|
||||
window.parentWindow.postMessage(
|
||||
{ type: "np", title: song_title },
|
||||
window.parentOrigin
|
||||
);
|
||||
window.parentWindow.postMessage(
|
||||
{ type: "controller", id: Hostcontroller.old_id },
|
||||
window.parentOrigin
|
||||
);
|
||||
try {
|
||||
if (full_playlist.length > 0) {
|
||||
Player.sendNext({
|
||||
title: full_playlist[0].title,
|
||||
videoId: full_playlist[0].id
|
||||
});
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("message", receiveMessage, false);
|
||||
window.addEventListener("DOMContentLoaded", function() {});
|
||||
|
||||
var Channel = {
|
||||
set_title_width: function() {},
|
||||
window_width_volume_slider: function() {}
|
||||
};
|
||||
|
||||
function getSearch(elem) {
|
||||
var result = {};
|
||||
var search = window.location.search.split("&");
|
||||
for (var i = 0; i < search.length; i++) {
|
||||
var currElement = search[i].split("=");
|
||||
var key = currElement[0].replace("?", "");
|
||||
var value = currElement[1];
|
||||
if (value == "true") value = true;
|
||||
else if (value == "false") value = false;
|
||||
result[key] = value;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
window.addEventListener("load", function() {
|
||||
if (autoplay) {
|
||||
Helper.css("#player", "visibility", "hidden");
|
||||
}
|
||||
if (videoonly) {
|
||||
Helper.addClass("#wrapper", "hide");
|
||||
Helper.addClass("#controls", "hide");
|
||||
Helper.addClass("#player", "video_only");
|
||||
Helper.addClass("#player_overlay", "video_only");
|
||||
Helper.css("#zoffbutton", "bottom", "0px");
|
||||
Helper.css("#song-title", "width", "100vw");
|
||||
}
|
||||
|
||||
M.Modal.init(document.getElementById("locked_channel"), {
|
||||
dismissible: false
|
||||
});
|
||||
|
||||
add = "https://zoff.me";
|
||||
//if(window.location.hostname == "localhost") add = "localhost";
|
||||
//add = "localhost";
|
||||
socket = io.connect(
|
||||
"" + add,
|
||||
connection_options
|
||||
);
|
||||
|
||||
if (localmode) {
|
||||
change_offline(true, false);
|
||||
}
|
||||
|
||||
socket.on("auth_required", function() {
|
||||
M.Modal.getInstance(document.getElementById("locked_channel")).open();
|
||||
});
|
||||
|
||||
document.querySelector(".channel-info-container").href =
|
||||
"https://zoff.me/" + chan.toLowerCase();
|
||||
document.querySelector(".channel-title").innerText = "/" + chan.toLowerCase();
|
||||
|
||||
socket.on("get_list", function() {
|
||||
socket_connected = true;
|
||||
setTimeout(function() {
|
||||
socket.emit("list", {
|
||||
version: VERSION,
|
||||
channel: chan.toLowerCase(),
|
||||
pass: ""
|
||||
});
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
socket.on("self_ping", function() {
|
||||
if (chan != undefined && chan.toLowerCase() != "") {
|
||||
socket.emit("self_ping", { channel: chan.toLowerCase() });
|
||||
}
|
||||
});
|
||||
|
||||
socket.on("viewers", function(view) {
|
||||
viewers = view;
|
||||
|
||||
if (song_title !== undefined) Player.getTitle(song_title, viewers);
|
||||
});
|
||||
|
||||
Player.loadPlayer();
|
||||
setup_host_initialization();
|
||||
setup_now_playing_listener();
|
||||
setup_list_listener();
|
||||
|
||||
if (autoplay) {
|
||||
startWaitTimerPlay();
|
||||
}
|
||||
|
||||
List.calculate_song_heights();
|
||||
|
||||
window.onYouTubeIframeAPIReady = Player.onYouTubeIframeAPIReady;
|
||||
socket.on("toast", toast);
|
||||
|
||||
Playercontrols.initSlider();
|
||||
document
|
||||
.getElementById("playpause")
|
||||
.addEventListener("click", Playercontrols.play_pause);
|
||||
window.setVolume = setVolume;
|
||||
//Helper.css("#controls", "background-color", color);
|
||||
|
||||
document.querySelector("body").style.backgroundColor = color;
|
||||
if (embedOptions.hasOwnProperty("control") && embedOptions.control) {
|
||||
Hostcontroller.change_enabled(true);
|
||||
} else {
|
||||
Hostcontroller.change_enabled(false);
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener("resize", function() {
|
||||
resizeFunction();
|
||||
});
|
||||
|
||||
function resizePlaylistPlaying() {}
|
||||
|
||||
function startWaitTimerPlay() {
|
||||
setTimeout(function() {
|
||||
if (videoSource == "youtube") {
|
||||
Player.player.playVideo();
|
||||
} else if (videoSource == "soundcloud") {
|
||||
Player.soundcloud_player.play();
|
||||
}
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
function setup_host_listener(id) {
|
||||
socket.on(id, Hostcontroller.host_on_action);
|
||||
}
|
||||
|
||||
function setup_host_initialization() {
|
||||
socket.on("id", Hostcontroller.host_listener);
|
||||
}
|
||||
|
||||
function setup_now_playing_listener() {
|
||||
socket.on("np", Player.now_playing_listener);
|
||||
}
|
||||
|
||||
function setup_list_listener() {
|
||||
socket.on("channel", function(msg) {
|
||||
Helper.addClass(".site_loader", "hide");
|
||||
List.channel_function(msg);
|
||||
});
|
||||
}
|
||||
|
||||
function setVolume(val) {
|
||||
Playercontrols.visualVolume(val);
|
||||
Playercontrols.setVolume(val);
|
||||
}
|
||||
|
||||
function updateChromecastMetadata() {}
|
||||
function loadChromecastVideo() {}
|
||||
|
||||
function toast(msg) {
|
||||
switch (msg) {
|
||||
case "suggested_thumbnail":
|
||||
if (embed) return;
|
||||
msg = "The thumbnail has been suggested!";
|
||||
break;
|
||||
case "faulty_start_end":
|
||||
if (embed) return;
|
||||
break;
|
||||
case "wait_longer":
|
||||
if (embed) return;
|
||||
break;
|
||||
case "suggested_description":
|
||||
if (embed) return;
|
||||
break;
|
||||
case "thumbnail_denied":
|
||||
if (embed) return;
|
||||
break;
|
||||
case "description_denied":
|
||||
if (embed) return;
|
||||
break;
|
||||
case "addedsong":
|
||||
if (embed) return;
|
||||
break;
|
||||
case "addedplaylist":
|
||||
if (embed) return;
|
||||
break;
|
||||
case "savedsettings":
|
||||
if (embed) return;
|
||||
break;
|
||||
case "wrongpass":
|
||||
if (embed) return;
|
||||
break;
|
||||
case "deleted_songs":
|
||||
if (embed) return;
|
||||
break;
|
||||
case "shuffled":
|
||||
if (embed) return;
|
||||
break;
|
||||
case "deletesong":
|
||||
if (embed) return;
|
||||
break;
|
||||
case "voted":
|
||||
msg = Helper.rnd([
|
||||
"You voted!",
|
||||
"You vote like a boss",
|
||||
"Voting is the key to democracy",
|
||||
"May you get your song to the very top!",
|
||||
"I love that song! I vouch for you.",
|
||||
"Only you vote that good",
|
||||
"I like the way you vote...",
|
||||
"Up the video goes!",
|
||||
"Voted Zoff for president",
|
||||
"Only 999 more to go!"
|
||||
]);
|
||||
break;
|
||||
case "alreadyvoted":
|
||||
msg = Helper.rnd([
|
||||
"You can't vote twice on that song!",
|
||||
"I see you have voted on that song before",
|
||||
"One vote per person!",
|
||||
"I know you want to hear your song, but have patience!",
|
||||
"I'm sorry, but I can't let you vote twice, Dave."
|
||||
]);
|
||||
break;
|
||||
case "skip":
|
||||
if (embed) return;
|
||||
break;
|
||||
case "listhaspass":
|
||||
if (embed) return;
|
||||
break;
|
||||
case "noskip":
|
||||
if (embed) return;
|
||||
break;
|
||||
case "alreadyskip":
|
||||
if (embed) return;
|
||||
break;
|
||||
case "notyetskip":
|
||||
if (embed) return;
|
||||
break;
|
||||
case "correctpass":
|
||||
if (embed) return;
|
||||
break;
|
||||
case "changedpass":
|
||||
if (embed) return;
|
||||
break;
|
||||
case "suggested":
|
||||
if (embed) return;
|
||||
break;
|
||||
case "alreadyplay":
|
||||
if (embed) return;
|
||||
break;
|
||||
}
|
||||
before_toast();
|
||||
M.toast({ html: msg, displayLength: 4000 });
|
||||
}
|
||||
|
||||
function emit() {
|
||||
if (!embed) {
|
||||
lastCommand = [];
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
lastCommand.push(arguments[i]);
|
||||
}
|
||||
}
|
||||
if (arguments.length == 1) {
|
||||
socket.emit(arguments[0]);
|
||||
} else {
|
||||
socket.emit(arguments[0], arguments[1]);
|
||||
}
|
||||
}
|
||||
|
||||
function change_offline(enabled, already_offline) {
|
||||
offline = enabled;
|
||||
socket.emit("offline", {
|
||||
status: enabled,
|
||||
channel: chan != undefined ? chan.toLowerCase() : ""
|
||||
});
|
||||
if (!Helper.mobilecheck()) {
|
||||
if (
|
||||
document.querySelectorAll("#offline-mode").length == 1 &&
|
||||
M.Tooltip.getInstance(document.getElementById("offline-mode"))
|
||||
) {
|
||||
Helper.tooltip("#offline-mode", "destroy");
|
||||
}
|
||||
}
|
||||
|
||||
var mouseEnter = function(e) {
|
||||
Helper.removeClass("#seekToDuration", "hide");
|
||||
};
|
||||
|
||||
var mouseLeave = function(e) {
|
||||
dragging = false;
|
||||
Helper.addClass("#seekToDuration", "hide");
|
||||
};
|
||||
|
||||
var mouseDown = function(e) {
|
||||
var acceptable = ["bar", "controls", "duration"];
|
||||
if (acceptable.indexOf(e.target.id) >= 0) {
|
||||
dragging = true;
|
||||
}
|
||||
};
|
||||
|
||||
var mouseUp = function(e) {
|
||||
dragging = false;
|
||||
};
|
||||
if (enabled) {
|
||||
Helper.addClass("#viewers", "hide");
|
||||
Helper.removeClass(".margin-playbar", "margin-playbar");
|
||||
Helper.addClass(".prev playbar", "margin-playbar");
|
||||
Helper.removeClass(".prev playbar", "hide");
|
||||
|
||||
if (window.location.pathname != "/") {
|
||||
document
|
||||
.getElementById("controls")
|
||||
.addEventListener("mouseenter", mouseEnter, false);
|
||||
document
|
||||
.getElementById("controls")
|
||||
.addEventListener("mouseleave", mouseLeave, false);
|
||||
document
|
||||
.getElementById("controls")
|
||||
.addEventListener("mousedown", mouseDown, false);
|
||||
document
|
||||
.getElementById("controls")
|
||||
.addEventListener("mouseup", mouseUp, false);
|
||||
document
|
||||
.getElementById("controls")
|
||||
.addEventListener("mousemove", seekToMove);
|
||||
document
|
||||
.getElementById("controls")
|
||||
.addEventListener("click", seekToClick);
|
||||
|
||||
document
|
||||
.querySelector("#main_components")
|
||||
.insertAdjacentHTML(
|
||||
"beforeend",
|
||||
"<div id='seekToDuration' class='hide'>00:00/01:00</div>"
|
||||
);
|
||||
var controlElement = document.querySelector("#controls");
|
||||
Helper.css("#seekToDuration", "bottom", "50px");
|
||||
Helper.addClass("#controls", "ewresize");
|
||||
}
|
||||
if (
|
||||
full_playlist != undefined &&
|
||||
!already_offline &&
|
||||
full_playlist.length > 0
|
||||
) {
|
||||
for (var x = 0; x < full_playlist.length; x++) {
|
||||
full_playlist[x].votes = 0;
|
||||
}
|
||||
|
||||
List.sortList();
|
||||
List.populate_list(full_playlist);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function before_toast() {
|
||||
/*if($('.toast').length > 0) {
|
||||
var toastElement = $('.toast').first()[0];
|
||||
var toastInstance = toastElement.M_Toast;
|
||||
toastInstance.remove();
|
||||
}*/
|
||||
M.Toast.dismissAll();
|
||||
//Materialize.Toast.removeAll();
|
||||
}
|
||||
|
||||
document.addEventListener(
|
||||
"click",
|
||||
function(e) {
|
||||
handleEvent(e, e.target, false, "click");
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
addListener("click", ".channel-info-container", function(e) {
|
||||
this.preventDefault();
|
||||
Player.pauseVideo();
|
||||
window.open("https://zoff.me/" + chan.toLowerCase() + "/", "_blank");
|
||||
});
|
||||
|
||||
addListener("click", ".vote-container", function(e) {
|
||||
var that = e;
|
||||
var id = that.getAttribute("data-video-id");
|
||||
|
||||
List.vote(id, "pos");
|
||||
});
|
||||
|
||||
addListener("click", ".prev_page", function(e) {
|
||||
event.preventDefault();
|
||||
List.dynamicContentPage(-1);
|
||||
});
|
||||
|
||||
addListener("click", "#player_overlay", function(event) {
|
||||
if (videoSource == "soundcloud") Playercontrols.play_pause();
|
||||
});
|
||||
|
||||
addListener("click", ".next_page", function(e) {
|
||||
event.preventDefault();
|
||||
List.dynamicContentPage(1);
|
||||
});
|
||||
|
||||
addListener("click", ".prev", function(event) {
|
||||
this.preventDefault();
|
||||
if (!offline) return;
|
||||
List.skip(false);
|
||||
});
|
||||
|
||||
addListener("click", ".skip", function(event) {
|
||||
this.preventDefault();
|
||||
//if(!offline) return;
|
||||
List.skip(true);
|
||||
});
|
||||
|
||||
addListener("click", ".last_page", function(e) {
|
||||
event.preventDefault();
|
||||
List.dynamicContentPage(10);
|
||||
});
|
||||
|
||||
addListener("click", ".first_page", function(e) {
|
||||
event.preventDefault();
|
||||
List.dynamicContentPage(-10);
|
||||
});
|
||||
699
server/public/assets/js/frontpage.js
Executable file
@@ -0,0 +1,699 @@
|
||||
var channel_list;
|
||||
var frontpage = true;
|
||||
var socket;
|
||||
var rotation_timeout;
|
||||
|
||||
var Frontpage = {
|
||||
blob_list: [],
|
||||
|
||||
winter: new Date().getMonth() >= 10 ? true : false,
|
||||
pride: function() {
|
||||
return new Date().getMonth() == 5;
|
||||
},
|
||||
|
||||
times_rotated: 0,
|
||||
|
||||
all_channels: [],
|
||||
|
||||
frontpage_function: function() {
|
||||
frontpage = true;
|
||||
|
||||
Helper.log(["Frontpage fetch", msg]);
|
||||
|
||||
Frontpage.all_channels = window.lists;
|
||||
var msg = window.lists;
|
||||
delete window.lists;
|
||||
window.lists = undefined;
|
||||
//document.querySelector("#lists-script").remove();
|
||||
if (msg.length == 0) {
|
||||
//Helper.css("#preloader", "display", "none");
|
||||
document
|
||||
.getElementById("channel-list-container")
|
||||
.insertAdjacentHTML("beforeend", "<p>No channels yet</p>");
|
||||
} else {
|
||||
Frontpage.populate_channels(msg, true, false);
|
||||
}
|
||||
//Frontpage.set_viewers(msg.viewers);
|
||||
},
|
||||
|
||||
populate_channels: function(lists, popular, set) {
|
||||
//document.getElementById("channels").innerHTML = "";
|
||||
|
||||
var num = 0;
|
||||
if (!set) Frontpage.add_backdrop(lists, 0);
|
||||
else if (set) {
|
||||
document.getElementById("channels").innerHTML = "";
|
||||
if (popular) {
|
||||
lists = lists.sort(
|
||||
Helper.predicate(
|
||||
{
|
||||
name: "pinned",
|
||||
reverse: true
|
||||
},
|
||||
{
|
||||
name: "viewers",
|
||||
reverse: true
|
||||
},
|
||||
{
|
||||
name: "accessed",
|
||||
reverse: true
|
||||
},
|
||||
{
|
||||
name: "count",
|
||||
reverse: true
|
||||
}
|
||||
)
|
||||
);
|
||||
} else {
|
||||
lists = lists.sort(
|
||||
Helper.predicate(
|
||||
{
|
||||
name: "viewers",
|
||||
reverse: true
|
||||
},
|
||||
{
|
||||
name: "count",
|
||||
reverse: true
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (!Helper.mobilecheck()) {
|
||||
clearTimeout(rotation_timeout);
|
||||
Frontpage.add_backdrop(lists, 0);
|
||||
}
|
||||
|
||||
pre_card = channel_list;
|
||||
|
||||
Helper.log(["Pre_card: ", pre_card]);
|
||||
|
||||
for (var x in lists) {
|
||||
var chan = Helper.decodeChannelName(lists[x]._id);
|
||||
if (num < 12 || !popular) {
|
||||
var id = lists[x].id;
|
||||
var viewers = lists[x].viewers;
|
||||
var description = lists[x].description;
|
||||
var img;
|
||||
img =
|
||||
"background-image:url('https://img.youtube.com/vi/" +
|
||||
id +
|
||||
"/hqdefault.jpg');";
|
||||
if (lists[x].thumbnail && lists[x].thumbnail != "") {
|
||||
img = "background-image:url('" + lists[x].thumbnail + "');";
|
||||
}
|
||||
|
||||
var song_count = lists[x].count;
|
||||
var card = document.createElement("div");
|
||||
card.innerHTML += pre_card;
|
||||
//card.innerHTML = card.children[0];
|
||||
if (song_count > 3) {
|
||||
if (lists[x].pinned == 1) {
|
||||
card
|
||||
.querySelector(".pin")
|
||||
.setAttribute("style", "display:block;");
|
||||
//card.find(".card").attr("title", "Featured list");
|
||||
} else {
|
||||
/*card.find(".pin").attr("style", "display:none;");
|
||||
card.find(".card").attr("title", "");
|
||||
card.querySelector(".pin").remove();*/
|
||||
}
|
||||
card.querySelector(".chan-name").innerText = chan;
|
||||
card.querySelector(".chan-name").setAttribute("title", chan);
|
||||
card.querySelector(".chan-views").innerText = viewers;
|
||||
card.querySelector(".chan-songs").innerText = song_count;
|
||||
card.querySelector(".chan-bg").setAttribute("style", img);
|
||||
card.querySelector(".chan-link").setAttribute("href", chan + "/");
|
||||
|
||||
if (
|
||||
description != "" &&
|
||||
description != undefined &&
|
||||
!Helper.mobilecheck() &&
|
||||
description != "This list has no description"
|
||||
) {
|
||||
card.querySelector(".card-title").innerText = chan;
|
||||
card.querySelector(".description_text").innerText = description;
|
||||
description = "";
|
||||
} else {
|
||||
card.querySelector(".card-reveal").remove();
|
||||
Helper.removeClass(card.querySelector(".card"), "sticky-action");
|
||||
}
|
||||
|
||||
document
|
||||
.getElementById("channels")
|
||||
.insertAdjacentHTML("beforeend", card.children[0].innerHTML);
|
||||
} else {
|
||||
num--;
|
||||
}
|
||||
}
|
||||
num++;
|
||||
}
|
||||
}
|
||||
|
||||
var options_list = lists.slice();
|
||||
|
||||
options_list = options_list.sort(Frontpage.sortFunction_active);
|
||||
var data = {};
|
||||
for (var x in options_list) {
|
||||
data[Helper.decodeChannelName(options_list[x]._id)] = null;
|
||||
}
|
||||
if (
|
||||
document.querySelectorAll(".pin").length == 1 &&
|
||||
!Helper.mobilecheck()
|
||||
) {
|
||||
Helper.tooltip(
|
||||
document.querySelectorAll(".pin")[0].parentElement.parentElement
|
||||
.parentElement,
|
||||
{
|
||||
delay: 5,
|
||||
position: "top",
|
||||
html: "Featured playlist"
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
var to_autocomplete = document.querySelectorAll("input.autocomplete")[0];
|
||||
//if(Helper.mobilecheck()) to_autocomplete = "input.mobile-search";
|
||||
|
||||
M.Autocomplete.init(to_autocomplete, {
|
||||
data: data,
|
||||
limit: 5, // The max amount of results that can be shown at once. Default: Infinity.
|
||||
onAutocomplete: function(val) {
|
||||
Frontpage.to_channel(Helper.encodeChannelName(val), false);
|
||||
}
|
||||
});
|
||||
|
||||
//document.getElementById("preloader").style.display = "none";
|
||||
document.getElementById("channels").style.display = "block";
|
||||
//Materialize.fadeInImage('#channels');
|
||||
//$("#channels").fadeIn(800);
|
||||
//document.getElementById("autocomplete-input").focus();
|
||||
num = 0;
|
||||
},
|
||||
|
||||
sortFunction: function(a, b) {
|
||||
var o1 = a.viewers;
|
||||
var o2 = b.viewers;
|
||||
|
||||
var p1 = a.count;
|
||||
var p2 = b.count;
|
||||
|
||||
if (o1 < o2) return 1;
|
||||
if (o1 > o2) return -1;
|
||||
if (p1 < p2) return 1;
|
||||
if (p1 > p2) return -1;
|
||||
return 0;
|
||||
},
|
||||
|
||||
sortFunction_active: function(a, b) {
|
||||
var o1 = a.accessed;
|
||||
var o2 = b.accessed;
|
||||
|
||||
var p1 = a.count;
|
||||
var p2 = b.count;
|
||||
|
||||
if (o1 < o2) return 1;
|
||||
if (o1 > o2) return -1;
|
||||
if (p1 < p2) return 1;
|
||||
if (p1 > p2) return -1;
|
||||
return 0;
|
||||
},
|
||||
|
||||
getCookie: function(cname) {
|
||||
var name = cname + "=";
|
||||
var ca = document.cookie.split(";");
|
||||
for (var i = 0; i < ca.length; i++) {
|
||||
var c = ca[i];
|
||||
while (c.charAt(0) == " ") c = c.substring(1);
|
||||
if (c.indexOf(name) === 0) return c.substring(name.length, c.length);
|
||||
}
|
||||
return "";
|
||||
},
|
||||
|
||||
add_backdrop: function(list, i) {
|
||||
if (i >= list.length || i >= 20) i = 0;
|
||||
if (list[i] == undefined) return;
|
||||
var id = list[i].id;
|
||||
if (Frontpage.blob_list[i] !== undefined) {
|
||||
//$(".room-namer").css("opacity", 0);
|
||||
setTimeout(function() {
|
||||
if (frontpage) {
|
||||
Helper.css(
|
||||
"#mega-background",
|
||||
"background",
|
||||
"url(data:image/png;base64," + Frontpage.blob_list[i] + ")"
|
||||
);
|
||||
Helper.css("#mega-background", "background-size", "cover");
|
||||
Helper.css("#mega-background", "background-repeat", "no-repeat");
|
||||
Helper.css("#mega-background", "opacity", 1);
|
||||
document
|
||||
.querySelector(".autocomplete")
|
||||
.setAttribute("placeholder", Helper.decodeChannelName(list[i]._id));
|
||||
//$(".room-namer").css("opacity", 1);
|
||||
}
|
||||
}, 500);
|
||||
} else {
|
||||
var img = new Image();
|
||||
img.src = "/assets/images/thumbnails/" + id + ".jpg";
|
||||
|
||||
img.onerror = function(e) {
|
||||
// Failed to load
|
||||
var add = "";
|
||||
if (window.location.hostname == "fb.zoff.me") {
|
||||
add = "https://zoff.me";
|
||||
}
|
||||
Helper.ajax({
|
||||
type: "POST",
|
||||
data: { id: id },
|
||||
url: add + "/api/imageblob",
|
||||
headers: { "Content-Type": "application/json;charset=UTF-8" },
|
||||
success: function(data) {
|
||||
setTimeout(function() {
|
||||
try {
|
||||
Helper.css(
|
||||
"#mega-background",
|
||||
"background",
|
||||
"url(/assets/images/thumbnails/" + data + ")"
|
||||
);
|
||||
Helper.css("#mega-background", "background-size", "cover");
|
||||
Helper.css(
|
||||
"#mega-background",
|
||||
"background-repeat",
|
||||
"no-repeat"
|
||||
);
|
||||
Helper.css("#mega-background", "opacity", 1);
|
||||
document
|
||||
.querySelector(".autocomplete")
|
||||
.setAttribute(
|
||||
"placeholder",
|
||||
Helper.decodeChannelName(list[i]._id)
|
||||
);
|
||||
} catch (e) {}
|
||||
}, 500);
|
||||
},
|
||||
error: function() {
|
||||
try {
|
||||
document
|
||||
.querySelector(".autocomplete")
|
||||
.setAttribute(
|
||||
"placeholder",
|
||||
Helper.decodeChannelName(list[i]._id)
|
||||
);
|
||||
} catch (e) {
|
||||
console.log("This is a weird error...", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
img.onload = function() {
|
||||
// Loaded successfully
|
||||
try {
|
||||
Helper.css("#mega-background", "background", "url(" + img.src + ")");
|
||||
Helper.css("#mega-background", "background-size", "cover");
|
||||
Helper.css("#mega-background", "background-repeat", "no-repeat");
|
||||
Helper.css("#mega-background", "opacity", 1);
|
||||
document
|
||||
.querySelector(".autocomplete")
|
||||
.setAttribute("placeholder", Helper.decodeChannelName(list[i]._id));
|
||||
} catch (e) {}
|
||||
};
|
||||
}
|
||||
rotation_timeout = setTimeout(function() {
|
||||
if (Frontpage.times_rotated == 50 && frontpage) {
|
||||
Frontpage.times_rotated = 0;
|
||||
i = 0;
|
||||
//Frontpage.get_frontpage_lists();
|
||||
} else if (frontpage) {
|
||||
Frontpage.times_rotated += 1;
|
||||
Frontpage.add_backdrop(list, i + 1);
|
||||
}
|
||||
}, 6000);
|
||||
},
|
||||
|
||||
get_frontpage_lists: function() {
|
||||
var add = "";
|
||||
if (window.location.hostname == "fb.zoff.me") {
|
||||
add = "https://zoff.me";
|
||||
}
|
||||
Frontpage.frontpage_function();
|
||||
/*Helper.ajax({
|
||||
url: add + "/api/frontpages",
|
||||
method: "POST",
|
||||
data: {
|
||||
token: zoff_api_token,
|
||||
},
|
||||
success: function(response){
|
||||
response = JSON.parse(response);
|
||||
Frontpage.frontpage_function(response.results);
|
||||
},
|
||||
error: function() {
|
||||
M.toast({html: "Couldn't fetch lists, trying again in 3 seconds..", displayLength: 3000, classes: "red lighten connect_error"});
|
||||
retry_frontpage = setTimeout(function(){
|
||||
Frontpage.get_frontpage_lists();
|
||||
}, 3000);
|
||||
},
|
||||
});*/
|
||||
},
|
||||
|
||||
start_snowfall: function() {
|
||||
setTimeout(function() {
|
||||
var x = Math.floor(Math.random() * window.innerWidth + 1);
|
||||
var snow = document.createElement("div");
|
||||
var parent = document.getElementsByClassName("mega")[0];
|
||||
|
||||
snow.className = "snow";
|
||||
//snow.attr("left", x);
|
||||
snow.style.left = x + "px";
|
||||
snow.style.top = "0px";
|
||||
parent.appendChild(snow);
|
||||
Frontpage.fall_snow(snow);
|
||||
Frontpage.start_snowfall();
|
||||
}, 800);
|
||||
},
|
||||
|
||||
fall_snow: function(corn) {
|
||||
corn.style.top = parseInt(corn.style.top.replace("px", "")) + 2 + "px";
|
||||
if (
|
||||
parseInt(corn.style.top.replace("px", "")) <
|
||||
document.getElementById("mega-background").offsetHeight - 2.5
|
||||
) {
|
||||
setTimeout(function() {
|
||||
Frontpage.fall_snow(corn);
|
||||
}, 50);
|
||||
} else {
|
||||
corn.remove();
|
||||
}
|
||||
},
|
||||
|
||||
set_viewers: function(viewers) {
|
||||
document.querySelector("#frontpage-viewer-counter").innerHTML =
|
||||
"<i class='material-icons frontpage-viewers'>visibility</i>" + viewers;
|
||||
},
|
||||
|
||||
to_channel: function(new_channel, popstate) {
|
||||
Helper.css("#channel-load", "display", "block");
|
||||
window.scrollTo(0, 0);
|
||||
frontpage = false;
|
||||
new_channel = new_channel.toLowerCase();
|
||||
clearTimeout(rotation_timeout);
|
||||
if (Helper.mobilecheck()) {
|
||||
Helper.log(["removing all listeners"]);
|
||||
removeAllListeners();
|
||||
}
|
||||
Helper.css("#main-container", "background-color", "#2d2d2d");
|
||||
if (!Helper.mobilecheck()) {
|
||||
Helper.tooltip("#frontpage-viewer-counter", "destroy");
|
||||
Helper.tooltip(".generate-channel-name", "destroy");
|
||||
Helper.tooltip("#offline-mode", "destroy");
|
||||
Helper.tooltip("#client-mode-button", "destroy");
|
||||
if (document.querySelectorAll(".pin").length == 1) {
|
||||
Helper.tooltip(
|
||||
document.querySelectorAll(".pin")[0].parentElement.parentElement
|
||||
.parentElement,
|
||||
"destroy"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
currently_showing_channels = 1;
|
||||
clearTimeout(retry_frontpage);
|
||||
Helper.ajax({
|
||||
url: "/" + new_channel,
|
||||
method: "get",
|
||||
data: { channel: new_channel },
|
||||
success: function(e) {
|
||||
if (Player.player !== "") {
|
||||
//Player.player.destroy();
|
||||
socket.emit("change_channel", { channel: chan.toLowerCase() });
|
||||
}
|
||||
var _player = document.querySelectorAll("#frontpage_player");
|
||||
if (_player.length > 0) _player[0].innerHTML = "";
|
||||
if (Helper.mobilecheck()) {
|
||||
//Helper.log("disconnecting");
|
||||
//socket.disconnect();
|
||||
socket.removeAllListeners();
|
||||
}
|
||||
var old_chan = chan;
|
||||
if (!popstate) {
|
||||
window.history.pushState(
|
||||
"to the channel!",
|
||||
"Title",
|
||||
"/" + new_channel
|
||||
);
|
||||
if (prev_chan_list == "") prev_chan_list = new_channel;
|
||||
if (prev_chan_player == "") prev_chan_player = new_channel;
|
||||
chan = new_channel;
|
||||
}
|
||||
|
||||
var response = document.createElement("div");
|
||||
response.innerHTML = e;
|
||||
|
||||
M.FormSelect.getInstance(
|
||||
document.querySelector("#view_channels_select")
|
||||
).destroy();
|
||||
//$('select').formSelect('destroy');
|
||||
Helper.removeElement(".mega");
|
||||
Helper.removeElement(".mobile-search");
|
||||
document.getElementsByTagName("main")[0].className =
|
||||
"container center-align main";
|
||||
Helper.addClass("#main-container", "channelpage");
|
||||
|
||||
document.getElementsByTagName(
|
||||
"header"
|
||||
)[0].innerHTML = response.querySelectorAll("header")[0].innerHTML;
|
||||
|
||||
if (
|
||||
document.querySelectorAll("#alreadychannel").length === 0 ||
|
||||
Helper.mobilecheck() ||
|
||||
Player.player === undefined
|
||||
) {
|
||||
document.getElementsByTagName(
|
||||
"main"
|
||||
)[0].innerHTML = response.querySelectorAll("main")[0].innerHTML;
|
||||
} else {
|
||||
document
|
||||
.getElementById("main-row")
|
||||
.insertAdjacentHTML(
|
||||
"beforeend",
|
||||
response.querySelectorAll("#playlist")[0].outerHTML
|
||||
);
|
||||
if (!client)
|
||||
document
|
||||
.getElementById("video-container")
|
||||
.insertAdjacentHTML(
|
||||
"beforeend",
|
||||
response.querySelectorAll("#main_components")[0].outerHTML
|
||||
);
|
||||
document
|
||||
.getElementById("main-row")
|
||||
.insertAdjacentHTML("beforeend", "<div id='playbar'></div>");
|
||||
Helper.removeClass("#player", "player_bottom");
|
||||
Helper.removeClass("#player_overlay", "player_bottom");
|
||||
Helper.removeClass(".video-container", "frontpage-player");
|
||||
Helper.removeClass("#main-row", "frontpage_modified_heights");
|
||||
Helper.removeElement("#main_section_frontpage");
|
||||
Helper.removeElement("#closePlayer");
|
||||
Helper.removeElement("#player_bottom_overlay");
|
||||
}
|
||||
document
|
||||
.getElementById("search")
|
||||
.setAttribute("placeholder", "Search...");
|
||||
Helper.addClass(".page-footer", "padding-bottom-novideo");
|
||||
from_frontpage = true;
|
||||
//Player.stopInterval =true;
|
||||
//clearTimeout(durationTimeout);
|
||||
if (document.querySelectorAll("#alreadychannel").length == 1) {
|
||||
if (old_chan != new_channel) local_new_channel = true;
|
||||
Channel.init();
|
||||
} else {
|
||||
fromFront = true;
|
||||
Channel.init();
|
||||
}
|
||||
if (document.querySelectorAll("#alreadyfp").length === 0)
|
||||
document
|
||||
.getElementsByTagName("head")[0]
|
||||
.insertAdjacentHTML("beforeend", "<div id='alreadyfp'></div>");
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
init: function() {
|
||||
var date = new Date();
|
||||
Frontpage.blob_list = [];
|
||||
if (date.getMonth() == 3 && date.getDate() == 1) {
|
||||
Helper.css(".mega", "-webkit-transform", "rotate(180deg)");
|
||||
Helper.css(".mega", "-moz-transform", "rotate(180deg)");
|
||||
//Materialize.toast('<p id="aprilfools">We suck at pranks..<a class="waves-effect waves-light btn light-green" style="pointer-events:none;">Agreed</a></p>', 100000);
|
||||
}
|
||||
|
||||
if (window.location.hostname != "localhost") {
|
||||
var page = window.location.pathname;
|
||||
if (page.substring(page.length - 1) != "/") page += "/";
|
||||
ga("send", "pageview", page);
|
||||
}
|
||||
|
||||
window.onpopstate = function(e) {
|
||||
var url_split = window.location.href.split("/");
|
||||
if (url_split[3] !== "" && url_split[3].substring(0, 1) != "#") {
|
||||
Frontpage.to_channel(url_split[3], true);
|
||||
}
|
||||
};
|
||||
|
||||
if (window.location.hostname == "fb.zoff.me") {
|
||||
Helper.addClass("footer", "hide");
|
||||
}
|
||||
|
||||
channel_list = document
|
||||
.querySelector(".hidden-channel-list")
|
||||
.cloneNode(true).innerHTML;
|
||||
try {
|
||||
document.querySelector(".hidden-channel-list").remove();
|
||||
} catch (e) {}
|
||||
|
||||
Frontpage.share_link_modifier();
|
||||
|
||||
if (
|
||||
window.location.hostname == "zoff.me" ||
|
||||
window.location.hostname == "fb.zoff.me"
|
||||
)
|
||||
add = "https://zoff.me";
|
||||
else add = window.location.hostname;
|
||||
if (socket === undefined) {
|
||||
no_socket = false;
|
||||
if (window.location.port != "") {
|
||||
add = add + ":" + window.location.port + "/";
|
||||
}
|
||||
socket = io.connect(
|
||||
"" + add,
|
||||
connection_options
|
||||
);
|
||||
socket.on("update_required", function(msg) {
|
||||
if (window.location.hostname == "localhost") {
|
||||
console.log(msg);
|
||||
return;
|
||||
}
|
||||
window.location.reload(true);
|
||||
});
|
||||
}
|
||||
if (
|
||||
document.querySelectorAll("#alreadyfp").length === 0 ||
|
||||
Helper.mobilecheck() ||
|
||||
!socket._callbacks.$playlists ||
|
||||
user_auth_avoid
|
||||
) {
|
||||
setup_playlist_listener();
|
||||
}
|
||||
|
||||
/*M.Modal.init(document.getElementById("about"));
|
||||
M.Modal.init(document.getElementById("help"));
|
||||
M.Modal.init(document.getElementById("contact"));*/
|
||||
var elem = document.querySelector("select");
|
||||
document.querySelector(".no-jump-select").remove();
|
||||
M.FormSelect.init(elem);
|
||||
|
||||
Helper.log(["Sending frontpage_lists", "Socket"]);
|
||||
|
||||
Crypt.init();
|
||||
if (Crypt.get_offline()) {
|
||||
change_offline(true, offline);
|
||||
} else {
|
||||
if (!Helper.mobilecheck()) {
|
||||
Helper.tooltip("#offline-mode", {
|
||||
delay: 5,
|
||||
position: "bottom",
|
||||
html: "Enable local mode"
|
||||
});
|
||||
}
|
||||
}
|
||||
if (!Helper.mobilecheck()) {
|
||||
Helper.tooltip("#frontpage-viewer-counter", {
|
||||
delay: 5,
|
||||
position: "bottom",
|
||||
html: "Total Viewers"
|
||||
});
|
||||
Helper.tooltip("#client-mode-button", {
|
||||
delay: 5,
|
||||
position: "bottom",
|
||||
html: "Client mode"
|
||||
});
|
||||
Helper.tooltip(".generate-channel-name", {
|
||||
delay: 5,
|
||||
position: "bottom",
|
||||
html: "Generate name"
|
||||
});
|
||||
}
|
||||
Frontpage.get_frontpage_lists();
|
||||
|
||||
Helper.css("#channel-load", "display", "none");
|
||||
//Materialize.toast("<a href='/remote' style='color:white;'>Try out our new feature, remote!</a>", 8000)
|
||||
if (window.location.hash == "#donation") {
|
||||
window.location.hash = "#";
|
||||
M.Modal.init(document.getElementById("donation"));
|
||||
M.Modal.getInstance(document.getElementById("donation")).open();
|
||||
}
|
||||
|
||||
//var pad = 0;
|
||||
|
||||
/*$(".zicon").on("click", function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
pad += 10;
|
||||
Helper.css(".zicon", "padding-left", pad + "vh");
|
||||
if(pad >= 80)
|
||||
window.location.href = 'http://etys.no';
|
||||
});*/
|
||||
|
||||
if (!Helper.mobilecheck() && Frontpage.winter) {
|
||||
document
|
||||
.getElementsByClassName("mega")[0]
|
||||
.insertAdjacentHTML("afterbegin", '<div id="snow"></div>');
|
||||
}
|
||||
if (Frontpage.pride()) {
|
||||
Helper.addClass("#fp-nav", "pride-background");
|
||||
}
|
||||
|
||||
if (Helper.mobilecheck()) {
|
||||
//$('input#autocomplete-input').characterCounter();
|
||||
}
|
||||
|
||||
window["__onGCastApiAvailable"] = function(loaded, errorInfo) {
|
||||
if (loaded) {
|
||||
chromecastReady = true;
|
||||
} else {
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
share_link_modifier: function() {
|
||||
document
|
||||
.getElementById("facebook-code-link")
|
||||
.setAttribute(
|
||||
"href",
|
||||
"https://www.facebook.com/sharer/sharer.php?u=https://zoff.me/"
|
||||
);
|
||||
document
|
||||
.getElementById("facebook-code-link")
|
||||
.setAttribute(
|
||||
"onclick",
|
||||
"window.open('https://www.facebook.com/sharer/sharer.php?u=https://zoff.me/', 'Share Zoff','width=600,height=300'); return false;"
|
||||
);
|
||||
document
|
||||
.getElementById("twitter-code-link")
|
||||
.setAttribute(
|
||||
"href",
|
||||
"https://twitter.com/intent/tweet?url=https://zoff.me/&text=Check%20out%20Zoff!&via=zoffmusic"
|
||||
);
|
||||
document
|
||||
.getElementById("twitter-code-link")
|
||||
.setAttribute(
|
||||
"onclick",
|
||||
"window.open('https://twitter.com/intent/tweet?url=https://zoff.me/&text=Check%20out%20Zoff!&via=zoffmusic','Share Playlist','width=600,height=300'); return false;"
|
||||
);
|
||||
//$("#qr-code-link").attr("href", "//chart.googleapis.com/chart?chs=500x500&cht=qr&chl=https://zoff.me/&choe=UTF-8&chld=L%7C1");
|
||||
//$("#qr-code-image-link").attr("src", "//chart.googleapis.com/chart?chs=150x150&cht=qr&chl=https://zoff.me/&choe=UTF-8&chld=L%7C1");
|
||||
}
|
||||
};
|
||||
|
||||
String.prototype.capitalizeFirstLetter = function() {
|
||||
return this.charAt(0).toUpperCase() + this.slice(1);
|
||||
};
|
||||