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/
|
node_modules/
|
||||||
scripts/
|
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
|
### About
|
||||||
|
|
||||||
Zöff is a shared (free) YouTube based radio service, built upon the YouTube API.
|
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.
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
The team consists of Kasper Rynning-Tønnesen and Nicolas Almagro Tonne, and the project has been worked on since late 2014.
|
The team consists of Kasper Rynning-Tønnesen and Nicolas Almagro Tonne, and the project has been worked on since late 2014.
|
||||||
|
|
||||||
### Contact
|
### 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:
|
### Screenshots of the mobile version:
|
||||||
|
|
||||||
  
|
|
||||||
|
|
||||||
### Android exclusive screens:
|
|
||||||
|
|
||||||
<div style="text-align:center;">
|
<div style="text-align:center;">
|
||||||
<img src="http://i.imgur.com/2LMOnUe.png" alt="android1" height="600px">
|
<img src="http://i.imgur.com/aWlEmIx.png" alt="frontpage" height="600px">
|
||||||
<img src="http://i.imgur.com/mIOrtng.png" alt="android2" height="400px">
|
<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>
|
</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
|
### Legal
|
||||||
|
|
||||||
Copyright © 2016
|
|
||||||
Nicolas Almagro Tonne and Kasper Rynning-Tønnesen
|
|
||||||
|
|
||||||
Creative Commons License
|
Creative Commons License
|
||||||
Zöff is licensed under a
|
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>.
|
<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.
|
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'),
|
var gulp = require("gulp"),
|
||||||
gutil = require('gulp-util'),
|
uglify = require("gulp-uglify"),
|
||||||
uglify = require('gulp-uglifyjs'),
|
//sourcemaps = require('gulp-sourcemaps'),
|
||||||
concat = require('gulp-concat');
|
concat = require("gulp-concat"),
|
||||||
|
cleanCSS = require("gulp-clean-css");
|
||||||
|
|
||||||
gulp.task('js', function () {
|
gulp.task("css", function() {
|
||||||
gulp.src(['static/js/*.js', '!static/js/embed*', '!static/js/remotecontroller.js'])
|
return gulp
|
||||||
.pipe(uglify({
|
.src([
|
||||||
mangle: true,
|
"server/public/assets/css/style.css",
|
||||||
compress: true,
|
"server/public/assets/css/globals.css",
|
||||||
enclose: true
|
"server/public/assets/css/animations.css",
|
||||||
}))
|
"server/public/assets/css/mobile.css"
|
||||||
.pipe(concat('main.min.js'))
|
])
|
||||||
.pipe(gulp.dest('static/dist'));
|
.pipe(concat("style.css"))
|
||||||
|
.pipe(cleanCSS({ compatibility: "ie8" }))
|
||||||
|
.pipe(gulp.dest("server/public/assets/dist"));
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('embed', function () {
|
gulp.task("css-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'])
|
return gulp
|
||||||
.pipe(uglify({
|
.src("server/public/assets/css/embed.css")
|
||||||
mangle: true,
|
.pipe(cleanCSS({ compatibility: "ie8" }))
|
||||||
compress: true,
|
.pipe(gulp.dest("server/public/assets/dist"));
|
||||||
enclose: true
|
|
||||||
}))
|
|
||||||
.pipe(concat('embed.min.js'))
|
|
||||||
.pipe(gulp.dest('static/dist'));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/*
|
gulp.task("js", function() {
|
||||||
gulp.task('nochan', function () {
|
return (
|
||||||
gulp.src(['static/js/nochan.js', 'static/js/helpers.js'])
|
gulp
|
||||||
.pipe(uglify({
|
.src([
|
||||||
mangle: true,
|
"server/VERSION.js",
|
||||||
compress: true,
|
"server/config/api_key.js",
|
||||||
enclose: true
|
"server/public/assets/js/*.js",
|
||||||
}))
|
"!server/public/assets/js/embed*",
|
||||||
.pipe(concat('frontpage.min.js'))
|
"!server/public/assets/js/token*",
|
||||||
.pipe(gulp.dest('static/dist'));
|
"!server/public/assets/js/remotecontroller.js",
|
||||||
});*/
|
"!server/public/assets/js/callback.js"
|
||||||
|
])
|
||||||
gulp.task('remotecontroller', function () {
|
//.pipe(sourcemaps.init())
|
||||||
gulp.src(['static/js/remotecontroller.js'])
|
.pipe(concat("main.min.js"))
|
||||||
.pipe(uglify({
|
.pipe(
|
||||||
mangle: true,
|
uglify({
|
||||||
compress: true,
|
mangle: true,
|
||||||
enclose: true
|
compress: true,
|
||||||
}))
|
enclose: true
|
||||||
.pipe(concat('remote.min.js'))
|
})
|
||||||
.pipe(gulp.dest('static/dist'));
|
)
|
||||||
|
//.pipe(sourcemaps.write('maps'))
|
||||||
|
.pipe(gulp.dest("server/public/assets/dist"))
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('default', function(){
|
gulp.task("embed", function() {
|
||||||
gulp.watch('static/js/*.js', ['js']);
|
return (
|
||||||
gulp.watch('static/js/*.js', ['embed']);
|
gulp
|
||||||
//gulp.watch('static/js/*.js', ['nochan']);
|
.src([
|
||||||
gulp.watch('static/js/remotecontroller.js', ['remotecontroller']);
|
"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);
|
||||||
|
};
|
||||||