Compare commits

..

1382 Commits

Author SHA1 Message Date
Kasper Rynning-Tønnesen
96e0c31bf9 Fixed sizing issue of playlistitems in client 2018-04-30 18:43:18 +02:00
Kasper Rynning-Tønnesen
b2f51c4682 Updates for channel-user-password modal and channel-info input-fields 2018-04-30 16:05:09 +02:00
Kasper Rynning-Tønnesen
902cc9df11 Not only 'jomedia' channel 2018-04-28 01:45:16 +02:00
Kasper Rynning-Tønnesen
72ba01d34b Fixed query-element in url issue 2018-04-28 01:41:22 +02:00
Kasper Rynning-Tønnesen
6b69001b03 Transitions you say 2018-04-27 15:14:00 +02:00
Kasper Rynning-Tønnesen
3e06af930f Toasts shouldn't be turned 2018-04-27 15:09:01 +02:00
Kasper Rynning-Tønnesen
a80ab6721a inverting is cool 2018-04-27 15:07:58 +02:00
Kasper Rynning-Tønnesen
ffc324fab9 Changed element to be affected 2018-04-27 15:01:13 +02:00
Kasper Rynning-Tønnesen
87bfb443fe Added a cool thing 2018-04-27 14:57:28 +02:00
Kasper Rynning-Tønnesen
3f4662d90e Update in refreshing viewers in playlist 2018-04-27 13:25:37 +02:00
Kasper Rynning-Tønnesen
1c4834211d Fixed small issue with pausing player with spacebar 2018-04-27 13:17:15 +02:00
Kasper Rynning-Tønnesen
1e53f371f6 updated gulp-file 2018-04-27 12:57:47 +02:00
Kasper Rynning-Tønnesen
9b3f2d00c5 Merge branch 'master' of github.com:zoff-music/zoff 2018-04-27 12:57:08 +02:00
Kasper Rynning-Tønnesen
e8208c32ea Fixed listeners-issue on embedded player 2018-04-27 12:56:47 +02:00
Kasper Rynning-Tønnesen
ceaaf540a1 Merge pull request #340 from zoff-music/fix/jquery-less-cross-browser-issues
Fixed issue with volume-control not being styled correctly
2018-04-26 23:14:05 +02:00
Kasper Rynning-Tønnesen
fd83f09b3c Fixed issue with volume-control not being styled correctly 2018-04-26 23:13:47 +02:00
Kasper Rynning-Tønnesen
69d118d511 Merge pull request #339 from zoff-music/fix/jquery-less-cross-browser-issues
Fixed small issue with context-menu
2018-04-26 17:18:11 +02:00
Kasper Rynning-Tønnesen
3cdb6c756d Fixed small issue with context-menu 2018-04-26 17:17:35 +02:00
Kasper Rynning-Tønnesen
4e093c3377 Merge pull request #338 from zoff-music/fix/jquery-less-cross-browser-issues
Fix/jquery less cross browser issues
2018-04-26 17:15:43 +02:00
Kasper Rynning-Tønnesen
fc182882a0 Fix for firefox not working 2018-04-26 17:15:16 +02:00
Kasper Rynning-Tønnesen
64da529ec2 Started fixing of cross-browser errors that came with removing jQuery 2018-04-26 16:11:59 +02:00
Kasper Rynning-Tønnesen
6b926ca92e Fireplace-player same size as other player 2018-04-26 15:30:53 +02:00
Kasper Rynning-Tønnesen
be6f91f17e Spacebar to pause video again 2018-04-26 13:49:40 +02:00
Kasper Rynning-Tønnesen
abee56d2ce Fixed issue with local-mode tooltip of position in song not showing up 2018-04-26 13:31:19 +02:00
Kasper Rynning-Tønnesen
a95828843b Fixed issue with playlist being loaded incorrectly 2018-04-26 13:15:45 +02:00
Kasper Rynning-Tønnesen
5478b6a6e2 Fixed suggestions notifier error 2018-04-26 13:07:48 +02:00
Kasper Rynning-Tønnesen
58ccdada3b Fixed list-populate error
- Fixed issue where updating a list would cause it to be empty visually on update for users
2018-04-26 12:24:54 +02:00
Kasper Rynning-Tønnesen
61647e96c7 Removed channel-name tap-target 2018-04-26 11:20:29 +02:00
Kasper Rynning-Tønnesen
6777ace942 Updated readme and about to remove jQuery mentions 2018-04-25 23:52:47 +02:00
Kasper Rynning-Tønnesen
a157daf7ec Trying without error-catcher 2018-04-25 23:37:07 +02:00
Kasper Rynning-Tønnesen
e4bafbc0e5 Fixed issue when closing player from frontpage 2018-04-25 23:29:06 +02:00
Kasper Rynning-Tønnesen
4d25db31df Parent is not a function 2018-04-25 23:25:43 +02:00
Kasper Rynning-Tønnesen
78c2f57679 Fixed parentIssue 2018-04-25 23:24:30 +02:00
Kasper Rynning-Tønnesen
ae827d295d Merge pull request #337 from zoff-music/refactor/no-jquery
Refactor/no jquery
2018-04-25 23:20:43 +02:00
Kasper Rynning-Tønnesen
15eeb3cc60 Working without jQuery 2018-04-25 23:19:49 +02:00
Kasper Rynning-Tønnesen
8cb8c46f2f Working results 2018-04-25 17:11:58 +02:00
Kasper Rynning-Tønnesen
e01bef2ace Completely removed jQuery
- Missing results/search not working properly
2018-04-25 16:59:40 +02:00
Kasper Rynning-Tønnesen
f540f10cca Working onepage_load without jQuery elements 2018-04-24 19:01:40 +02:00
Kasper Rynning-Tønnesen
93cffa9ded Created dynamic listeners, and functions to add/remove listeners 2018-04-24 16:05:15 +02:00
Kasper Rynning-Tønnesen
f3be9dbb91 Merge branch 'master' into refactor/no-jquery 2018-04-24 14:57:23 +02:00
Kasper Rynning-Tønnesen
5e563110e3 Fixed results error 2018-04-24 14:57:15 +02:00
Kasper Rynning-Tønnesen
000239514b Merge branch 'master' into refactor/no-jquery 2018-04-24 14:51:26 +02:00
Kasper Rynning-Tønnesen
5cc4cfaf55 overflow of controls 2018-04-24 14:51:03 +02:00
Kasper Rynning-Tønnesen
c29f4fc390 Merge branch 'master' into refactor/no-jquery 2018-04-24 14:48:46 +02:00
Kasper Rynning-Tønnesen
6a3851a765 Fixed issues with sidenav accordion 2018-04-24 14:48:31 +02:00
Kasper Rynning-Tønnesen
a5134928b5 migrated much of the listeners 2018-04-24 14:47:31 +02:00
Kasper Rynning-Tønnesen
30885e332b Removed 300 or something jquery references so far 2018-04-24 12:05:57 +02:00
Kasper Rynning-Tønnesen
529e8f2f38 Merge branch 'master' into refactor/no-jquery 2018-04-24 10:19:48 +02:00
Kasper Rynning-Tønnesen
3662e90e28 Removed some logs 2018-04-24 10:19:35 +02:00
Kasper Rynning-Tønnesen
a5231b42b5 Merge branch 'master' into refactor/no-jquery 2018-04-24 10:18:42 +02:00
Kasper Rynning-Tønnesen
af384de79e Fixed issue with slider not working properly on mobile 2018-04-24 10:17:29 +02:00
Kasper Rynning-Tønnesen
eb45eb48fc Small changes 2018-04-24 09:49:38 +02:00
Kasper Rynning-Tønnesen
a6e91ce590 Started migration from jquery 2018-04-23 17:53:07 +02:00
Kasper Rynning-Tønnesen
6dabe2963e using correct api-token on live 2018-04-23 16:49:44 +02:00
Kasper Rynning-Tønnesen
089471cd14 Fixed issue with slider_values lingering 2018-04-23 16:48:15 +02:00
Kasper Rynning-Tønnesen
88f18240df Merge pull request #336 from zoff-music/feature/no-jquery-ui
Stopped using jQuery UI
2018-04-23 16:43:11 +02:00
Kasper Rynning-Tønnesen
daa5f16945 Stopped using jQuery UI 2018-04-23 16:42:43 +02:00
Kasper Rynning-Tønnesen
5adf770af0 White text in find-form 2018-04-19 15:53:48 +02:00
Kasper Rynning-Tønnesen
9a00c426c6 Fixed issue where filter was filtering bad words someplaces, and somewhere it doesnt 2018-04-19 12:00:44 +02:00
Kasper Rynning-Tønnesen
dd8aac577a Fixed password-lock position 2018-04-11 16:46:36 +02:00
Kasper Rynning-Tønnesen
fc0f03e171 Updated jquery-ui 2018-04-11 14:56:17 +02:00
Kasper Rynning-Tønnesen
1535ac7251 Embed-controls position was 1 pixel off 2018-04-11 11:23:38 +02:00
Kasper Rynning-Tønnesen
d395648f2d Unique ids 2018-04-10 13:18:15 +02:00
Kasper Rynning-Tønnesen
0cfb1b6389 Fixed sizing of player 2018-04-10 13:06:54 +02:00
Kasper Rynning-Tønnesen
9273576fe6 Fixed issue with mobile-client on password-protected list 2018-04-08 17:41:24 +02:00
Kasper Rynning-Tønnesen
58362f14bb Fixed crashing 2018-04-06 17:59:40 +02:00
Kasper Rynning-Tønnesen
6bac97c15f Fixed issue with localmode 2018-04-06 17:50:25 +02:00
Kasper Rynning-Tønnesen
a44856eb57 Solid background loading on mobile 2018-04-06 17:46:40 +02:00
Kasper Rynning-Tønnesen
5a2cb39454 Better counter 2018-04-06 17:43:25 +02:00
Kasper Rynning-Tønnesen
88b1426bb1 Not showing suggested on mobileload 2018-04-06 17:39:47 +02:00
Kasper Rynning-Tønnesen
3fbca854d7 Not showing suggested either 2018-04-06 17:29:33 +02:00
Kasper Rynning-Tønnesen
2a8ee0673d Fixed issue with navigating on mobile 2018-04-06 17:17:30 +02:00
Kasper Rynning-Tønnesen
c8bfe33253 Pointer for nav-btns 2018-04-06 16:55:28 +02:00
Kasper Rynning-Tønnesen
6be0fceb78 Removed a dead file, and fixed some styling 2018-04-06 16:54:03 +02:00
Kasper Rynning-Tønnesen
435fb23fd3 Fixed issues with client 2018-04-06 16:51:04 +02:00
Kasper Rynning-Tønnesen
1d9b3a42b1 Merge pull request #334 from zoff-music/feature/materializecss-beta
Changed to materlializeCSS beta-1, that doesn't use jQuery
2018-04-06 15:52:17 +02:00
Kasper Rynning-Tønnesen
bd9b42fd9e Changed to materlializeCSS beta-1, that doesn't use jQuery 2018-04-06 15:51:04 +02:00
Kasper Rynning-Tønnesen
9164541750 Small fix for variable not defined crashing server 2018-04-06 13:23:52 +02:00
Kasper Rynning-Tønnesen
1394d6420d Tooltip on channel-name 2018-04-06 13:19:45 +02:00
Kasper Rynning-Tønnesen
c245ec80ff Removed some dependencies 2018-04-06 13:16:10 +02:00
Kasper Rynning-Tønnesen
d8ecd34960 Updated socket.io version 2018-04-06 12:51:31 +02:00
Kasper Rynning-Tønnesen
37ffa194e2 Featured channel-changes
- Tooltip for better info
- Removed pin from all other frontpage cards
2018-04-06 12:42:22 +02:00
Kasper Rynning-Tønnesen
7fde03e88e Updates for better handling of deleting list and inserting full playlist 2018-04-05 13:52:05 +02:00
Kasper Rynning-Tønnesen
72f204825e Better colorthief handling
- Moved colorthief handling to api, making it easier to controll where the requests comes from
2018-04-03 16:40:34 +02:00
Kasper Rynning-Tønnesen
02667f4348 Imageblob only from allowed origin 2018-04-03 16:19:11 +02:00
Kasper Rynning-Tønnesen
355926ddff Returning on imageblob error 2018-04-03 16:11:25 +02:00
Kasper Rynning-Tønnesen
20922fb494 No tap-target in client-mode
- some minor restructuring of if/unless
2018-04-03 16:09:16 +02:00
Kasper Rynning-Tønnesen
c710fb56e2 SameSite for cookies 2018-03-30 10:57:12 +02:00
Kasper Rynning-Tønnesen
d15c5c9e89 Fixed issue with channelnames with weird characters not working 2018-03-26 14:48:03 +02:00
Kasper Rynning-Tønnesen
e5460bf605 Both client and mobile send ajax at the beginning when socket disconnected 2018-03-23 18:40:08 +01:00
Kasper Rynning-Tønnesen
bb59378a2d Adding a log 2018-03-23 18:20:25 +01:00
Kasper Rynning-Tønnesen
c03d85b83f Trying fix for vote/add on mobile-client 2018-03-23 18:18:24 +01:00
Kasper Rynning-Tønnesen
a02cdbcf88 Forgot to add to embed.js 2018-03-23 17:55:17 +01:00
Kasper Rynning-Tønnesen
3048527635 Fixed issue with client vote/add and such 2018-03-23 17:54:43 +01:00
Kasper Rynning-Tønnesen
264948a88a Removed unused variable 2018-03-22 16:01:14 +01:00
Kasper Rynning-Tønnesen
9ccdcf7aec Better YouTube importing, and auth-form prettier 2018-03-22 15:53:55 +01:00
Kasper Rynning-Tønnesen
f518a06ed2 Changed functionality for adding playlists
dquote> - Sending event for addPlaylist, and sending the whole list instead of one-by one
2018-03-21 21:10:08 +01:00
Kasper Rynning-Tønnesen
4e87a6309f Uncommented 2018-03-21 20:29:35 +01:00
Kasper Rynning-Tønnesen
25f515ffa7 Fixed issue with not incrementing on adding from other channel 2018-03-21 20:29:15 +01:00
Kasper Rynning-Tønnesen
2794ff7234 Fix for elements with weird collectionnames in mongodb 2018-03-21 15:10:36 +01:00
Kasper Rynning-Tønnesen
859062204c Added functionality to add songs from another channel 2018-03-21 15:01:14 +01:00
Kasper Rynning-Tønnesen
8d14b14c65 Fixed issue with .replace of boolean 2018-03-20 08:07:00 +01:00
Kasper Rynning-Tønnesen
1da48a7f1a Fixed issue with crashing server 2018-03-19 23:48:11 +01:00
Kasper Rynning-Tønnesen
910ad7ed76 onepage_load not working twice 2018-03-19 15:08:29 +01:00
Kasper Rynning-Tønnesen
a9d82566ef Fixed padding-issue on mobile 2018-03-19 14:52:55 +01:00
Kasper Rynning-Tønnesen
4d3d61b887 Added update to the offline service-worker file 2018-03-19 14:51:42 +01:00
Kasper Rynning-Tønnesen
b6b7118fd8 margin for viewers instead of padding 2018-03-19 13:22:31 +01:00
Kasper Rynning-Tønnesen
701ff55588 Replacing without crashing 2018-03-19 13:17:39 +01:00
Kasper Rynning-Tønnesen
2a9f5dc434 Moved context-menu to work from frontpage also 2018-03-19 12:06:59 +01:00
Kasper Rynning-Tønnesen
95d518d42f More fixed positions on mobile 2018-03-18 18:47:07 +01:00
Kasper Rynning-Tønnesen
f70cf00fd1 Fixed issue with channels having spaces 2018-03-18 18:19:42 +01:00
Kasper Rynning-Tønnesen
2e29f8e20f Update to embed-css 2018-03-18 14:25:14 +01:00
Kasper Rynning-Tønnesen
5786e84974 Moved some scripts around to try and reduce render-blocking 2018-03-18 14:06:13 +01:00
Kasper Rynning-Tønnesen
83683b497f Results and padding for playlist sizing 2018-03-17 20:10:05 +01:00
Kasper Rynning-Tønnesen
a26bf00634 Changes to fit the sizing of channelname and title 2018-03-17 20:05:17 +01:00
Kasper Rynning-Tønnesen
a81e21fd99 Moved some db things to db file
- Changed some visuals on scaling website
2018-03-17 19:55:02 +01:00
Kasper Rynning-Tønnesen
b0dfa2e5b7 Fixed issue with chromecast-framework loading 2018-03-17 12:37:58 +01:00
Kasper Rynning-Tønnesen
e9c7f63d5d Adding another test and fix for lists with multiple now-playing videos 2018-03-16 17:30:54 +01:00
Kasper Rynning-Tønnesen
7412837739 trying to fix issues with mobile-navigation with sockets 2018-03-16 17:06:11 +01:00
Kasper Rynning-Tønnesen
8d07cfa772 Not setting name on empty input 2018-03-16 10:49:57 +01:00
Kasper Rynning-Tønnesen
053ca27abe Fixed issue with setting limit of api-token 2018-03-16 10:47:34 +01:00
Kasper Rynning-Tønnesen
c4d20da02e Showing origin in adminpanel also 2018-03-16 10:41:34 +01:00
Kasper Rynning-Tønnesen
088ba1babd Forgot how logic works 2018-03-16 10:36:34 +01:00
Kasper Rynning-Tønnesen
372eb8439a Opening for subdomain also 2018-03-16 10:33:33 +01:00
Kasper Rynning-Tønnesen
90292762c9 Updated token-info 2018-03-16 10:29:57 +01:00
Kasper Rynning-Tønnesen
dbba54c7ad Origin for api-tokens 2018-03-16 10:28:10 +01:00
Kasper Rynning-Tønnesen
6ea96c769a Fixed sizing of playlist and sizing of chat-tabs 2018-03-16 09:50:24 +01:00
Kasper Rynning-Tønnesen
b4dc90c3ea Only removing channel-load on when loaded on mobile 2018-03-15 15:52:33 +01:00
Kasper Rynning-Tønnesen
e6d9143fa8 Fixed issue with suggested-badge showing up 2018-03-15 15:47:44 +01:00
Kasper Rynning-Tønnesen
fba021aeff Not showing badge on empty suggestions 2018-03-15 15:44:05 +01:00
Kasper Rynning-Tønnesen
a4ebe56254 Updated how suggestions work and display
- Always showing suggested tab in tablist
- Fixed issue with contextmenu going all wonky when opened on suggested elements
2018-03-15 15:38:08 +01:00
Kasper Rynning-Tønnesen
6d97345719 Better namechange-setter initally 2018-03-15 14:26:05 +01:00
Kasper Rynning-Tønnesen
572df5a8e5 Fixed api-issues 2018-03-15 13:42:51 +01:00
Kasper Rynning-Tønnesen
27233c2272 Fixed issue where description and thumbnail fields not showing up on logged in 2018-03-15 11:43:48 +01:00
Kasper Rynning-Tønnesen
c1a83648d3 Handling cookie-ids somewhat diferrently on chromecasts 2018-03-15 08:43:57 +01:00
Kasper Rynning-Tønnesen
1abced50ca Updates 2018-03-14 22:42:19 +01:00
Kasper Rynning-Tønnesen
a5248f0f39 Fixed service-worker issues 2018-03-14 22:13:03 +01:00
Kasper Rynning-Tønnesen
15532d8f9a no more serviceworker until cookies and referrers are handled 2018-03-14 21:59:46 +01:00
Kasper Rynning-Tønnesen
0fdd491bfd Fixed issue where login-with cookie didn't work as expected 2018-03-14 15:06:44 +01:00
Kasper Rynning-Tønnesen
4fc0151e9f Secure usercookie 2018-03-14 13:43:43 +01:00
Kasper Rynning-Tønnesen
8974e8cde0 Readded serviceworker, and fixed namechange error 2018-03-14 13:31:52 +01:00
Kasper Rynning-Tønnesen
e73ce3a702 Removing correct amount of events from socket 2018-03-13 21:20:43 +01:00
Kasper Rynning-Tønnesen
7755060c6a Reverted remove of jquery-touch-punch 2018-03-13 21:00:24 +01:00
Kasper Rynning-Tønnesen
714b885dc5 Removing more dependencies 2018-03-13 20:59:01 +01:00
Kasper Rynning-Tønnesen
f566a19857 Trying to enable cors for api 2018-03-13 18:51:52 +01:00
Kasper Rynning-Tønnesen
d5376799cf Trying to force a channel-change/remove 2018-03-13 18:20:35 +01:00
Kasper Rynning-Tønnesen
be94303365 Removing listener on client move 2018-03-13 18:18:02 +01:00
Kasper Rynning-Tønnesen
c3e982ee8a Fixed issue where userpass not existing 2018-03-13 18:16:08 +01:00
Kasper Rynning-Tønnesen
ed38c213ac Fixed issue with login-in 2018-03-13 17:55:56 +01:00
Kasper Rynning-Tønnesen
eb69e1e67b Merge pull request #333 from zoff-music/feature/session-logins
Feature/session logins
2018-03-13 17:44:40 +01:00
Kasper Rynning-Tønnesen
c0400d7999 More fixes 2018-03-13 17:44:16 +01:00
Kasper Rynning-Tønnesen
6de7391be3 Client working 2018-03-13 17:06:40 +01:00
Kasper Rynning-Tønnesen
82140ace20 Started work for having session-logins instead of sending passwords back and forth 2018-03-13 16:26:51 +01:00
Kasper Rynning-Tønnesen
8c1c0011a2 Removed some aes/sha256 from dependencies on clientside 2018-03-13 12:39:24 +01:00
Kasper Rynning-Tønnesen
dba60cd866 bumped jquery up 2018-03-12 22:00:49 +01:00
Kasper Rynning-Tønnesen
f87527c7c0 Added help for client-mode 2018-03-12 20:00:52 +01:00
Kasper Rynning-Tønnesen
63f6c438ee Trying fix for load-error and volume chromecast 2018-03-12 19:54:30 +01:00
Kasper Rynning-Tønnesen
897553f127 Forcing a disconnect 2018-03-12 19:47:16 +01:00
Kasper Rynning-Tønnesen
f337ad3197 Trying a better disconnect event 2018-03-12 19:44:37 +01:00
Kasper Rynning-Tønnesen
0df26727da Added button on frontpage for accessing client-version 2018-03-12 19:33:19 +01:00
Kasper Rynning-Tønnesen
8180b284af Staying on client if on client subdomain 2018-03-12 19:23:15 +01:00
Kasper Rynning-Tønnesen
b6439a679b Fallback if userpass is undefined for channel 2018-03-12 19:18:59 +01:00
Kasper Rynning-Tønnesen
3f0f8eb5d9 Updating channel to fetch prettier 2018-03-12 19:17:01 +01:00
Kasper Rynning-Tønnesen
1d7331cb86 Trying fix for ajax request 2018-03-12 17:12:57 +01:00
Kasper Rynning-Tønnesen
631c13bb2d Merge pull request #332 from zoff-music/feature/own-small-player
Modified rest, and added client-version
2018-03-12 17:07:33 +01:00
Kasper Rynning-Tønnesen
c21eee838a Modified rest, and added client-version 2018-03-12 17:06:47 +01:00
Kasper Rynning-Tønnesen
79fa8805b2 Fixed http2 issue 2018-03-09 18:22:41 +01:00
Kasper Rynning-Tønnesen
9b7be4224a Trying some more fixes for the unknown error for .id undefined 2018-03-09 15:57:46 +01:00
Kasper Rynning-Tønnesen
82e643140e Better error-logging 2018-03-09 14:48:46 +01:00
Kasper Rynning-Tønnesen
8a3b2113f8 No more http2 2018-03-09 14:05:31 +01:00
Kasper Rynning-Tønnesen
cddce88207 Merge branch 'master' of github.com:zoff-music/zoff 2018-03-09 14:01:49 +01:00
Kasper Rynning-Tønnesen
913382c7f2 Trying with http2 2018-03-09 14:01:40 +01:00
Kasper Rynning-Tønnesen
68fb72aa9f Update EVENTS.md 2018-03-07 11:12:55 +01:00
Kasper Rynning-Tønnesen
ee085bcf07 Added customizable notify-mail-to 2018-03-06 16:04:44 +01:00
Kasper Rynning-Tønnesen
1774efd26c Idle players now changing song when they need to, to keep up with the channel 2018-03-06 15:52:45 +01:00
Kasper Rynning-Tønnesen
2fef90d375 Never sending position-request on offline 2018-03-06 15:29:12 +01:00
Kasper Rynning-Tønnesen
0dcdd617c3 Fixed issue where getting current-position returned update_required 2018-03-06 14:58:10 +01:00
Kasper Rynning-Tønnesen
01480b74de Redirecting /api/help to correct readme file 2018-03-06 14:08:48 +01:00
Kasper Rynning-Tønnesen
b68fc778f1 Fixed color-issue on entering a channel 2018-03-06 14:07:24 +01:00
Kasper Rynning-Tønnesen
259ef0fe7e Updated get-history to include channel-password if exists 2018-03-06 13:39:49 +01:00
Kasper Rynning-Tønnesen
64e4a84012 Merge pull request #331 from zoff-music/feature/more-info-error
Feature/more info error
2018-03-06 13:03:44 +01:00
Kasper Rynning-Tønnesen
57abb0b28f Added separate markdown files for events and rest 2018-03-06 13:03:13 +01:00
Kasper Rynning-Tønnesen
d757b95b44 Added more info on faulty input
- Sent in the results on REST
- Sent in the update_required msg on socket.io connection
2018-03-06 13:02:53 +01:00
Kasper Rynning-Tønnesen
43af39c03a Aligning toasts better on embed 2018-03-05 15:42:40 +01:00
Kasper Rynning-Tønnesen
19a5dc9c27 Prettier embedded-player on startup 2018-03-05 15:39:24 +01:00
Kasper Rynning-Tønnesen
fd8df5041a Localhost to zoff.me 2018-03-05 15:34:27 +01:00
Kasper Rynning-Tønnesen
421482ec3a Fixed embedded-version 2018-03-05 15:33:36 +01:00
Kasper Rynning-Tønnesen
25004f1a7a Fixed crashing issue in chat 2018-03-05 10:28:31 +01:00
Kasper Rynning-Tønnesen
2a0c2b276a Merge branch 'master' of github.com:zoff-music/zoff 2018-03-05 10:19:36 +01:00
Kasper Rynning-Tønnesen
5e7b74ef46 Made oauth window prettier with a loader 2018-03-05 10:19:28 +01:00
Kasper Rynning-Tønnesen
88f7813a3f Update README.md 2018-03-04 22:59:03 +01:00
Kasper Rynning-Tønnesen
924cc44a20 More typechecking 2018-03-04 22:57:27 +01:00
Kasper Rynning-Tønnesen
ad8bd1bff4 Fix for non-selectable API-code
- Fixed issue where API-code couldn't be selected
- Added view to see if the api-key has been fetched or not
- Added option to try again with the same email if the previous link has timed-out after a day
2018-03-04 22:29:59 +01:00
Kasper Rynning-Tønnesen
bdf014b4ff Paused, embed and includes
- Fixed issue with paused video playing on changing song for others
- Fixed more embedoptions
- cueVideoById is a neat function that I should have used earlier
- Added smaller jquery.ui files
2018-03-04 20:56:41 +01:00
Kasper Rynning-Tønnesen
57c64d8e29 Fixed issue with header in token-view not linking to frontpage 2018-03-04 20:21:07 +01:00
Kasper Rynning-Tønnesen
a34f7570cc Moved embed.html to handlebars-file, and fixed toast-wordbreaks 2018-03-04 20:13:07 +01:00
Kasper Rynning-Tønnesen
e3469875c2 Fixed modal z-index for google recaptcha 2018-03-04 14:35:49 +01:00
Kasper Rynning-Tønnesen
ed8fd2bc89 Merge branch 'master' of github.com:zoff-music/zoff 2018-03-04 14:09:28 +01:00
Kasper Rynning-Tønnesen
3bbc627473 Fixed API token-timeout fix 2018-03-04 14:09:12 +01:00
Kasper Rynning-Tønnesen
91be64626f Update README.md 2018-03-04 13:28:48 +01:00
Kasper Rynning-Tønnesen
552cd5eb9e Fix for clearing api-token-list in adminpanel on refresh 2018-03-04 13:27:09 +01:00
Kasper Rynning-Tønnesen
946bbb1c65 fixed rest-api issue with token not being checked correctly 2018-03-04 13:22:59 +01:00
Kasper Rynning-Tønnesen
2192b340c9 Pageview on api-apply also 2018-03-04 13:19:13 +01:00
Kasper Rynning-Tønnesen
b2801794ea Spelling again... 2018-03-04 12:41:16 +01:00
Kasper Rynning-Tønnesen
b863afaa1a Merge branch 'master' of github.com:zoff-music/zoff 2018-03-04 12:39:09 +01:00
Kasper Rynning-Tønnesen
c80e049844 Spelling-fixes and selectable 2018-03-04 12:37:00 +01:00
Kasper Rynning-Tønnesen
e2fe15f09f Update README.md 2018-03-04 12:17:26 +01:00
Kasper Rynning-Tønnesen
991d8a6e6f Fixed issue where token are not being built on deployment 2018-03-04 12:13:53 +01:00
Kasper Rynning-Tønnesen
786a6e0b5a Removed token.min.js from github, fixed issue with embedded player playing even when not supposed to, and fixed faulty error-message when applying to get a token 2018-03-04 12:10:48 +01:00
Kasper Rynning-Tønnesen
99f737d0b3 Merge pull request #330 from zoff-music/feature/api-token-apply
Added url for applying for api-tokens
2018-03-04 11:26:50 +01:00
Kasper Rynning-Tønnesen
0d333ac83a Limit is set to 100 automatically 2018-03-04 11:26:16 +01:00
Kasper Rynning-Tønnesen
76e7001e51 Added url for applying for api-tokens 2018-03-04 11:24:44 +01:00
Kasper Rynning-Tønnesen
785813b842 Fixed issue with new lists 2018-03-04 10:31:46 +01:00
Kasper Rynning-Tønnesen
ceebba6253 Adding option to name api-keys and removing them 2018-03-03 18:16:49 +01:00
Kasper Rynning-Tønnesen
e6eb066911 Timeouting wrong tokens 2018-03-03 16:41:24 +01:00
Kasper Rynning-Tønnesen
7d10360c81 Added error-message if trying to send token that doesn't exist 2018-03-03 16:39:18 +01:00
Kasper Rynning-Tønnesen
dea93456b0 Updated readme 2018-03-03 16:34:01 +01:00
Kasper Rynning-Tønnesen
a6b63be03b Fixed authorization issue with token 2018-03-03 16:32:45 +01:00
Kasper Rynning-Tønnesen
78ffcec66d Updated RESTApi to have tokens also 2018-03-03 16:24:57 +01:00
Kasper Rynning-Tønnesen
731f26e3d4 Fix for crashes 2018-03-03 16:17:11 +01:00
Kasper Rynning-Tønnesen
5c1e91467f Fix for list without conf 2018-03-03 15:51:11 +01:00
Kasper Rynning-Tønnesen
76776cdcd4 Fix for crashing server 2018-03-03 15:30:08 +01:00
Kasper Rynning-Tønnesen
740cf021f8 Fixed issue with correct title not returning result 2018-03-03 12:12:32 +01:00
Kasper Rynning-Tønnesen
fa7071ecb6 Correct output for output on post without auth 2018-03-02 13:23:32 +01:00
Kasper Rynning-Tønnesen
b9bc22d1d2 Fixed local-mode issues 2018-03-02 13:04:56 +01:00
Kasper Rynning-Tønnesen
5e9e682932 Correct error-message on song-get on protected list 2018-03-02 11:40:39 +01:00
Kasper Rynning-Tønnesen
1e00cbb9e7 README.md update 2018-03-02 11:35:42 +01:00
Kasper Rynning-Tønnesen
c9353e0236 Added frontpage-lists GET example 2018-03-02 11:17:37 +01:00
Kasper Rynning-Tønnesen
89d87a143d README update 2018-03-02 11:10:27 +01:00
Kasper Rynning-Tønnesen
e0ee2142b5 Fixed now-playing not being sent correctly from API 2018-03-02 11:07:54 +01:00
Kasper Rynning-Tønnesen
a7948d97c6 Merge pull request #328 from zoff-music/refactor/prettier-json-api
Refactor/prettier json api
2018-03-02 10:54:10 +01:00
Kasper Rynning-Tønnesen
ec9b9676fb Added fix for ga not being present on localhost 2018-03-02 10:52:43 +01:00
Kasper Rynning-Tønnesen
7aad759c26 Cleaned up admin.js some 2018-03-02 10:48:15 +01:00
Kasper Rynning-Tønnesen
c70b6a0ea9 Prettier returing on API
- Prettier returns on API
- Upped to version 4
2018-03-02 10:47:06 +01:00
Kasper Rynning-Tønnesen
7fda70965f Fixed issue with suggested being duplicated and RESTApi posting 2018-03-02 09:23:07 +01:00
Kasper Rynning-Tønnesen
e720776365 Updating to have type always 2018-03-02 08:50:17 +01:00
Kasper Rynning-Tønnesen
af947d3fd2 Added request-answers 2018-03-01 19:17:06 +01:00
Kasper Rynning-Tønnesen
151cbcd49f Updated README to be correct 2018-03-01 19:15:14 +01:00
Kasper Rynning-Tønnesen
92a7c88e42 More RESTApi explanation in README and more endpoints 2018-03-01 19:11:20 +01:00
Kasper Rynning-Tønnesen
557bc521a5 Validating song-info on add by api 2018-03-01 16:14:24 +01:00
Kasper Rynning-Tønnesen
c6ec847306 Merge branch 'master' of github.com:zoff-music/zoff 2018-03-01 15:55:28 +01:00
Kasper Rynning-Tønnesen
ec128823d9 Redirecting /api/help to github 2018-03-01 15:55:02 +01:00
Kasper Rynning-Tønnesen
e97d4c5f68 Update README.md 2018-03-01 15:47:56 +01:00
Kasper Rynning-Tønnesen
0401d824eb RESTApi is timed for 2 seconds 2018-03-01 15:44:17 +01:00
Kasper Rynning-Tønnesen
76d8973509 Shuffling is limited per channel instead of client 2018-03-01 15:42:09 +01:00
Kasper Rynning-Tønnesen
f678576a1a Updated README.md 2018-03-01 15:26:03 +01:00
Kasper Rynning-Tønnesen
7aa4b2d22a Limiting on how much you can shuffle 2018-03-01 15:20:26 +01:00
Kasper Rynning-Tønnesen
adc1b2bf31 Merge pull request #327 from zoff-music/feature/timeout-api
Timeout api, and fixes it lead to
2018-03-01 14:55:45 +01:00
Kasper Rynning-Tønnesen
9839c0bdda Timeout api, and fixes it lead to
- timeout on api-calls with Retry-After present in header
- Fixed issue where when server restarts you are sometimes logged out for some reason
- README updates
2018-03-01 14:55:23 +01:00
Kasper Rynning-Tønnesen
724fca9fec Merge pull request #326 from zoff-music/fix/userpass-emits
Added fixes for player not starting on youtubevideos that has already…
2018-03-01 13:11:32 +01:00
Kasper Rynning-Tønnesen
a63b2a41e0 Merge pull request #325 from zoff-music/feature/rest-api
REST-endpoints and readme
2018-03-01 13:11:12 +01:00
Kasper Rynning-Tønnesen
a6083d3402 Added fixes for player not starting on youtubevideos that has already been played by the client
Fix for userpass not being set correctly
Fix for emit function not being used everywhere it needs to be used
2018-03-01 13:10:51 +01:00
Kasper Rynning-Tønnesen
97e06e3726 REST-endpoints and readme 2018-03-01 13:09:44 +01:00
Kasper Rynning-Tønnesen
2e8ef6739c Added a try-again for commands with password if there exists an adminass saved 2018-02-28 15:40:55 +01:00
Kasper Rynning-Tønnesen
7b66575ea8 Locking down some paths not meant to be seen with url 2018-02-28 14:25:33 +01:00
Kasper Rynning-Tønnesen
9268db4bcc More errormessages 2018-02-27 15:33:34 +01:00
Kasper Rynning-Tønnesen
ded7fa9a14 Added test for start or end lower than 0 2018-02-27 15:28:06 +01:00
Kasper Rynning-Tønnesen
0383c035f4 Forcing int 2018-02-27 15:25:37 +01:00
Kasper Rynning-Tønnesen
8614ba0731 Updated so start can't be after end 2018-02-27 15:24:36 +01:00
Kasper Rynning-Tønnesen
dad95b3fd2 Informing about the new update 2018-02-27 11:41:53 +01:00
Kasper Rynning-Tønnesen
9f94a828d1 Merge pull request #324 from zoff-music/refactor/own-config
Conf error for api
2018-02-27 11:37:18 +01:00
Kasper Rynning-Tønnesen
31cadc18a6 Conf error for api 2018-02-27 11:36:59 +01:00
Kasper Rynning-Tønnesen
eb78e1e769 Merge pull request #323 from zoff-music/refactor/own-config
Refactor/own config
2018-02-27 11:34:11 +01:00
Kasper Rynning-Tønnesen
0c2298524c Rewriting for own settings collections for more consistency of documents 2018-02-27 11:32:22 +01:00
Kasper Rynning-Tønnesen
d2b3759913 Rewriting stuff 2018-02-27 11:26:31 +01:00
Kasper Rynning-Tønnesen
370e9ae72b Updating to use different collection for channelsettings 2018-02-27 11:11:29 +01:00
Kasper Rynning-Tønnesen
3efefb51d9 Merge pull request #322 from zoff-music/feature/chromecast
More metadatasending
2018-02-26 19:13:48 +01:00
Kasper Rynning-Tønnesen
8326c1b5f9 More metadatasending 2018-02-26 19:13:06 +01:00
Kasper Rynning-Tønnesen
9516460d02 Merge pull request #321 from zoff-music/feature/chromecast
Fixed issue with faulty player_overlay image on casting
2018-02-26 18:54:40 +01:00
Kasper Rynning-Tønnesen
836b80ea67 Fixed issue with faulty player_overlay image on casting 2018-02-26 18:54:12 +01:00
Kasper Rynning-Tønnesen
d970522b31 Merge pull request #320 from zoff-music/feature/chromecast
Fixed previous error with ,
2018-02-26 18:48:19 +01:00
Kasper Rynning-Tønnesen
cde92696ca Fixed previous error with , 2018-02-26 18:48:01 +01:00
Kasper Rynning-Tønnesen
16edaab2c6 Merge pull request #319 from zoff-music/feature/chromecast
More chromecastfeatures
2018-02-26 18:45:47 +01:00
Kasper Rynning-Tønnesen
ce656b97bc More chromecastfeatures
- Click on player pauses/plays video
- Receives event on play/pause
- Some indentationfixes
- Not showing Join Channel modal when chromecast connected
2018-02-26 18:45:17 +01:00
Kasper Rynning-Tønnesen
78fad1bbe0 About year fix 2018-02-26 15:23:28 +01:00
Kasper Rynning-Tønnesen
f84b1d55d3 Prettier helper.log 2018-02-26 14:58:45 +01:00
Kasper Rynning-Tønnesen
45fe704285 Added gulp to pm2 and updated pm2 + readme 2018-02-26 14:34:58 +01:00
Kasper Rynning-Tønnesen
c341edc33a Adminpanel now connects to current domain instead of zoff.me 2018-02-26 14:31:01 +01:00
Kasper Rynning-Tønnesen
e623e067ac Merge pull request #318 from zoff-music/refactor/helper-log
Refactor/helper log
2018-02-26 14:23:30 +01:00
Kasper Rynning-Tønnesen
181fd93e69 Error-reporting over mail also 2018-02-26 14:22:59 +01:00
Kasper Rynning-Tønnesen
86f8a936fc Better Helper.log and view 2018-02-26 12:56:43 +01:00
Kasper Rynning-Tønnesen
21692a9c71 Merge pull request #317 from zoff-music/refactor/hide-api-keys
Moved api-keys out of 'sight', and added analytics as optional
2018-02-26 12:36:57 +01:00
Kasper Rynning-Tønnesen
973a4f6fa9 Moved api-keys out of 'sight', and added analytics as optional 2018-02-26 12:35:11 +01:00
Kasper Rynning-Tønnesen
78adcf1caf Merge pull request #316 from zoff-music/fix/mobile-results
Fix for visuals of mobile results
2018-02-26 11:40:26 +01:00
Kasper Rynning-Tønnesen
8bd4effe9b Fix for visuals of mobile results
- Fix for no results being appended infinitely
- Loader on search input bar instead of interferring
2018-02-26 11:39:50 +01:00
Kasper Rynning-Tønnesen
c71234d71e Added a better truncate on channelname 2018-02-26 11:21:37 +01:00
Kasper Rynning-Tønnesen
bc13e83f90 Fixed player_overlay showing on mobile 2018-02-26 11:08:18 +01:00
Kasper Rynning-Tønnesen
9848da5608 Forgot how helper.log works 2018-02-25 22:56:25 +01:00
Kasper Rynning-Tønnesen
371414d1e0 Removing empty-checker counter debug log 2018-02-25 22:54:43 +01:00
Kasper Rynning-Tønnesen
8f696b574f Added some debuglogs for hostcontroller 2018-02-25 22:53:21 +01:00
Kasper Rynning-Tønnesen
c6b5bfb7f0 Merge pull request #315 from zoff-music/feature/ga-events
Google Analytics events
2018-02-25 22:43:15 +01:00
Kasper Rynning-Tønnesen
5aadb5ab4f Google Analytics events 2018-02-25 22:42:53 +01:00
Kasper Rynning-Tønnesen
48cd95a11e Merge pull request #314 from zoff-music/fix/redis-load
Redis-load start issue fix
2018-02-25 15:58:48 +01:00
Kasper Rynning-Tønnesen
9a877fa18e Fixed issue where clients without redis struggled with starting the server 2018-02-25 15:58:02 +01:00
Kasper Rynning-Tønnesen
df1dc29735 Merge pull request #313 from zoff-music/fix/mobile-chromecasting-fixes
Better loading on chromecast-loading for mobile
2018-02-25 15:53:14 +01:00
Kasper Rynning-Tønnesen
b407da74ff Better loading on chromecast-loading for mobile 2018-02-25 15:52:37 +01:00
Kasper Rynning-Tønnesen
afb6ab1c09 Merge pull request #312 from zoff-music/fix/mobile-chromecasting-fixes
Showing play-pause buttons
2018-02-25 15:21:46 +01:00
Kasper Rynning-Tønnesen
29a07ca099 Showing play-pause buttons 2018-02-25 14:53:24 +01:00
Kasper Rynning-Tønnesen
7f2557ba7b Merge pull request #311 from zoff-music/fix/mobile-chromecasting-fixes
Trying fixes for mobile chromecasting and visuals
2018-02-25 14:40:39 +01:00
Kasper Rynning-Tønnesen
90735948bb Trying fixes for mobile chromecasting and visuals 2018-02-25 14:39:03 +01:00
Kasper Rynning-Tønnesen
69abf6961a Hiding generatebutton mobile 2018-02-21 10:46:05 +01:00
Kasper Rynning-Tønnesen
52143238f0 Merge pull request #310 from zoff-music/feature/generate-channel-name
Added button for generating channelname in frontpage
2018-02-21 10:30:40 +01:00
Kasper Rynning-Tønnesen
c7e43762b4 Added button for generating channelname in frontpage 2018-02-21 10:30:10 +01:00
Kasper Rynning-Tønnesen
5011a3cf10 Fixed error in embed 2018-02-19 16:09:19 +01:00
Kasper Rynning-Tønnesen
6bf2e3a5eb Trying fix for dead mobile listeners 2018-02-19 09:46:37 +01:00
Kasper Rynning-Tønnesen
1da45805f6 Removed faulty logs 2018-02-15 12:41:44 +01:00
Kasper Rynning-Tønnesen
3c8f43a575 Stopping listening on more listeners on navigation and removed a title on hover 2018-02-15 12:40:48 +01:00
Kasper Rynning-Tønnesen
0c2ec57ed0 Fixed not closing brackets 2018-02-15 12:35:56 +01:00
Kasper Rynning-Tønnesen
6a51292016 Merge pull request #309 from zoff-music/fix/preloader-color
Better colors for preloader
2018-02-15 12:32:56 +01:00
Kasper Rynning-Tønnesen
1faf89e474 Merge pull request #308 from zoff-music/feature/prettier-PiP
Feature/prettier pi p
2018-02-15 12:32:35 +01:00
Kasper Rynning-Tønnesen
95ee5f7a35 Better colors for preloader 2018-02-15 12:32:12 +01:00
Kasper Rynning-Tønnesen
1c222b3812 Closeplayer button doesn't navigate to channel anymore 2018-02-15 12:31:43 +01:00
Kasper Rynning-Tønnesen
a369fed608 Prettier PiP for frontpage, with a hover 2018-02-15 12:22:44 +01:00
Kasper Rynning-Tønnesen
5c1d0b4096 Merge pull request #307 from zoff-music/fix/faster-mobile-load
Fixed removeAllListeners to be working
2018-02-15 11:17:35 +01:00
Kasper Rynning-Tønnesen
a45b82f9b9 Fixed removeAllListeners to be working 2018-02-15 11:17:09 +01:00
Kasper Rynning-Tønnesen
e713d80487 Merge pull request #306 from zoff-music/fix/faster-mobile-load
Trying to speed up mobile-loading for channels
2018-02-15 10:27:02 +01:00
Kasper Rynning-Tønnesen
1b52a06029 Trying to speed up mobile-loading for channels 2018-02-15 10:25:10 +01:00
Kasper Rynning-Tønnesen
cd90affedf Merge pull request #305 from zoff-music/feature/persistent-admin
Added expires option for mongo_configs
2018-02-14 14:00:38 +01:00
Kasper Rynning-Tønnesen
a4fd6f380e Added expires option for mongo_configs 2018-02-14 14:00:15 +01:00
Kasper Rynning-Tønnesen
ef21083c33 Merge pull request #304 from zoff-music/feature/persistent-admin
Started using persistance login for admin-panel
2018-02-14 13:57:56 +01:00
Kasper Rynning-Tønnesen
c3b8b53c6c Started using persistance login for admin-panel 2018-02-14 13:57:34 +01:00
Kasper Rynning-Tønnesen
958710440c Merge pull request #303 from zoff-music/fix/hostcontroller
Possible fix for remotecontroller not being enabled
2018-02-13 11:55:32 +01:00
Kasper Rynning-Tønnesen
df681c295e Possible fix for remotecontroller not being enabled 2018-02-13 11:55:01 +01:00
Kasper Rynning-Tønnesen
062e3630a3 Showing disabled configs when slow internet until config is fetched 2018-02-13 11:18:59 +01:00
Kasper Rynning-Tønnesen
fcecdade1a Merge pull request #302 from zoff-music/fix/pause-change
Fixed issue with player start playing when paused
2018-02-09 11:12:23 +01:00
Kasper Rynning-Tønnesen
7adc036dcd Fixed issue with player start playing when paused 2018-02-09 11:12:02 +01:00
Kasper Rynning-Tønnesen
bceda13245 Fixed result-buttons 2018-02-09 10:54:34 +01:00
Kasper Rynning-Tønnesen
306bfaf0eb Merge pull request #301 from zoff-music/feature/video-only-embed
Added video-only option for embedded channel
2018-02-07 16:13:12 +01:00
Kasper Rynning-Tønnesen
9f5159afb7 Added video-only option for embedded channel 2018-02-07 16:12:15 +01:00
Kasper Rynning-Tønnesen
0449442783 Fixed fullscreen-open-issue 2018-02-07 15:56:44 +01:00
Kasper Rynning-Tønnesen
d04f12fb7b Enabled help-modal for remote-page 2018-02-07 14:14:28 +01:00
Kasper Rynning-Tønnesen
77d7fb9eb5 Merge pull request #300 from zoff-music/fix/admin-panel
Fixed parameter and token issues
2018-02-06 15:15:29 +01:00
Kasper Rynning-Tønnesen
b047ccd9ef Fixed parameter and token issues 2018-02-06 15:15:07 +01:00
Kasper Rynning-Tønnesen
69b4aa4b33 Fixed issue with admin-panel login 2018-02-06 15:08:02 +01:00
Kasper Rynning-Tønnesen
c1d56ebb55 Removed some logs 2018-02-06 15:01:06 +01:00
Kasper Rynning-Tønnesen
fe722acacc Merge pull request #299 from zoff-music/fix/duplicates-and-play
Fixed issue with duplicates and player
2018-02-06 14:49:46 +01:00
Kasper Rynning-Tønnesen
47d5889c33 Fixed issue with duplicates and player
- Fixed issue where duplicates sometimes shows up in playlist
- Fixed issue where player starts playing when server is restarted and the user has paused the song
2018-02-06 14:49:23 +01:00
Kasper Rynning-Tønnesen
8eb9e99924 Merge pull request #298 from zoff-music/fix/loading-mail
Updated looks when sending a mail
2018-02-06 14:16:01 +01:00
Kasper Rynning-Tønnesen
c5f86108c7 Updated looks when sending a mail 2018-02-06 14:15:38 +01:00
Kasper Rynning-Tønnesen
c9d1b5312f Merge pull request #297 from zoff-music/fix/new-mailing
Using zoff.me instead of zoff.no for mailing now
2018-02-06 14:10:10 +01:00
Kasper Rynning-Tønnesen
626a6acb5f Using zoff.me instead of zoff.no for mailing now 2018-02-06 14:09:48 +01:00
Kasper Rynning-Tønnesen
0b2819649c Merge pull request #296 from zoff-music/feature/join-link-chromecast
Clicking on channel-name when casting zoff, join link opens up for 15…
2018-02-06 13:29:04 +01:00
Kasper Rynning-Tønnesen
aa724d3af9 Clicking on channel-name when casting zoff, join link opens up for 15seconds 2018-02-06 13:28:38 +01:00
Kasper Rynning-Tønnesen
47b7b27376 Merge pull request #295 from zoff-music/refactor/moving
Moved files, and shortened some
2018-02-05 23:44:30 +01:00
Kasper Rynning-Tønnesen
62944eb976 Moved files, and shortened some 2018-02-05 23:43:56 +01:00
Kasper Rynning-Tønnesen
4bca663bb3 Moved admin and client to apps folder 2018-02-05 21:22:23 +01:00
Kasper Rynning-Tønnesen
40d3fd3a21 Numprocesses set to 1 in non-redis environment 2018-02-05 21:03:35 +01:00
Kasper Rynning-Tønnesen
fca61a82eb Merge pull request #294 from zoff-music/refactor/adminpanel
Refactor/adminpanel
2018-02-05 20:53:55 +01:00
Kasper Rynning-Tønnesen
fedaedca8c Working adminpanel hopefully 2018-02-05 20:53:26 +01:00
Kasper Rynning-Tønnesen
2645a9b9dc Trying a fix for adminpanelserver 2018-02-05 20:21:00 +01:00
Kasper Rynning-Tønnesen
bcbfeed151 No more redirecting 2018-02-05 20:19:09 +01:00
Kasper Rynning-Tønnesen
00e9083d09 Merge pull request #293 from zoff-music/refactor/adminpanel
Trying to fix error
2018-02-05 20:00:04 +01:00
Kasper Rynning-Tønnesen
4fb88537cb Trying to fix error 2018-02-05 19:59:41 +01:00
Kasper Rynning-Tønnesen
3d2bd86284 Merge pull request #292 from zoff-music/refactor/adminpanel
Refactor/adminpanel
2018-02-05 19:55:37 +01:00
Kasper Rynning-Tønnesen
367f63e94e Added secret to mongo-config 2018-02-05 19:55:17 +01:00
Kasper Rynning-Tønnesen
c0a2e3331f fixed error 2018-02-05 19:54:53 +01:00
Kasper Rynning-Tønnesen
db7f993c18 Merge pull request #291 from zoff-music/refactor/adminpanel
Added adminpanel to this repo
2018-02-05 19:46:57 +01:00
Kasper Rynning-Tønnesen
01a42c7d68 Added adminpanel to this repo 2018-02-05 19:46:03 +01:00
Kasper Rynning-Tønnesen
38bceb1a53 Merge pull request #290 from zoff-music/fix/cors-anywhere-no
Removed cors-anywhere dependency
2018-02-05 18:09:22 +01:00
Kasper Rynning-Tønnesen
8169e2dd07 Removed cors-anywhere dependency 2018-02-05 18:06:53 +01:00
Kasper Rynning-Tønnesen
2cec9f92ab Fixed wss error 2018-02-05 15:18:57 +01:00
Kasper Rynning-Tønnesen
587eddfff5 Updated pm2 configuration 2018-02-05 15:05:11 +01:00
Kasper Rynning-Tønnesen
9c965c83b1 Forgot to move cors_proxy out 2018-02-05 15:02:26 +01:00
Kasper Rynning-Tønnesen
0a9b439368 Merge pull request #289 from zoff-music/refactor/app-js-refactoring
Added a way to check if redis exists, and open for non-redis-users
2018-02-05 15:00:21 +01:00
Kasper Rynning-Tønnesen
1ef809d062 Added a way to check if redis exists, and open for non-redis-users 2018-02-05 14:59:43 +01:00
Kasper Rynning-Tønnesen
132944e176 Updated API to include now_playing 2018-02-05 14:25:39 +01:00
Kasper Rynning-Tønnesen
93005c895b Small fixes, and removing unused variables 2018-02-05 14:18:47 +01:00
Kasper Rynning-Tønnesen
0c0e455336 Merge pull request #288 from zoff-music/test/cluster-mode
Test/cluster mode
2018-02-05 14:12:33 +01:00
Kasper Rynning-Tønnesen
cd491441f0 More trying and failing 2018-02-05 14:01:53 +01:00
Kasper Rynning-Tønnesen
c9446e151c Trying clustering 2018-02-05 12:56:10 +01:00
Kasper Rynning-Tønnesen
c5ef3404b7 Merge pull request #287 from zoff-music/fix/pagination-buttons
Improvements for pagination buttons
2018-02-05 12:17:39 +01:00
Kasper Rynning-Tønnesen
c39f71f64c Improvements for pagination buttons 2018-02-05 12:17:18 +01:00
Kasper Rynning-Tønnesen
72ad1a546b Donation-fixes 2018-02-02 16:11:21 +01:00
Kasper Rynning-Tønnesen
ae68d41a90 Merge pull request #286 from zoff-music/feature/join-link-qr
FeatureDiscovery of new QR code not showing on mobile anymore
2018-02-02 14:08:41 +01:00
Kasper Rynning-Tønnesen
99fbd85c95 FeatureDiscovery of new QR code not showing on mobile anymore 2018-02-02 14:08:06 +01:00
Kasper Rynning-Tønnesen
2f6f12e3e3 Update README.md 2018-02-02 13:36:29 +01:00
Kasper Rynning-Tønnesen
38c280dc05 Merge pull request #285 from zoff-music/feature/join-link-qr
Added a prettier QR-code link for joining on a channel
2018-02-02 13:34:39 +01:00
Kasper Rynning-Tønnesen
a2a78c1a87 Added a prettier QR-code link for joining on a channel 2018-02-02 13:34:12 +01:00
Kasper Rynning-Tønnesen
41ee83d6ea Merge pull request #284 from zoff-music/fix/analytics
Fixed analytics pageview being sent on localhost
2018-02-02 12:38:01 +01:00
Kasper Rynning-Tønnesen
ea0a18e5dd Fixed analytics pageview being sent on localhost 2018-02-02 12:37:27 +01:00
Kasper Rynning-Tønnesen
6d53455d41 Merge pull request #283 from zoff-music/feature/minimum-song-count-frontpage
Avoid frontpagelists not being to few
2018-01-31 11:48:02 +01:00
Kasper Rynning-Tønnesen
664b6c473f Avoid frontpagelists not being to few 2018-01-31 11:47:30 +01:00
Kasper Rynning-Tønnesen
e36fa619ae Merge pull request #282 from zoff-music/feature/minimum-song-count-frontpage
Put minimum song-count on list to display on the frontpage to 5
2018-01-31 11:46:00 +01:00
Kasper Rynning-Tønnesen
0f68967044 Put minimum song-count on list to display on the frontpage to 5 2018-01-31 11:45:29 +01:00
Kasper Rynning-Tønnesen
c9a2b9367c Merge pull request #281 from zoff-music/fix/listeners
Small fix for listener-counter
2018-01-31 11:39:07 +01:00
Kasper Rynning-Tønnesen
dcb01e5034 Small fix for listener-counter 2018-01-31 11:38:44 +01:00
Kasper Rynning-Tønnesen
8cef8df219 Merge pull request #280 from zoff-music/refactor/less-large-files
Refactored to have more files, but less long files
2018-01-31 11:29:05 +01:00
Kasper Rynning-Tønnesen
fd6db734f4 Refactored to have more files, but less long files 2018-01-31 11:28:35 +01:00
Kasper Rynning-Tønnesen
379f0ecb31 Merge pull request #279 from zoff-music/fix/offline-reset
Fixed issue where offline listeners not decreasing when leaving channel
2018-01-30 16:41:04 +01:00
Kasper Rynning-Tønnesen
fa5bdac1be Fixed issue where offline listeners not decreasing when leaving channel 2018-01-30 16:40:38 +01:00
Kasper Rynning-Tønnesen
8d57fd4774 Merge pull request #278 from zoff-music/fix/offline-listeners-fix
Fix for offline-listeners overflooding total viewers
2018-01-29 13:58:28 +01:00
Kasper Rynning-Tønnesen
05980fe33c Fix for offline-listeners overflooding total viewers 2018-01-29 13:57:54 +01:00
Kasper Rynning-Tønnesen
a6e87696b8 Merge pull request #277 from zoff-music/feature/notification
Sending mail when description or thumbnail is requested
2018-01-29 13:16:54 +01:00
Kasper Rynning-Tønnesen
26fcc9f6cb Sending mail when description or thumbnail is requested 2018-01-29 13:16:06 +01:00
Kasper Rynning-Tønnesen
6c437ba258 Merge pull request #276 from zoff-music/feature/recaptcha-mail
Implemented recaptcha
2018-01-29 12:59:45 +01:00
Kasper Rynning-Tønnesen
d5a2a75ddc Implemented recaptcha 2018-01-29 12:59:02 +01:00
Kasper Rynning-Tønnesen
aaab4e2bbb Merge pull request #275 from zoff-music/fix/offline-crash
Syntax
2018-01-29 09:55:46 +01:00
Kasper Rynning-Tønnesen
c3f7ed891f Syntax 2018-01-29 09:55:19 +01:00
Kasper Rynning-Tønnesen
d45829ed61 Merge pull request #274 from zoff-music/fix/offline-crash
Fixed issue where users was 0
2018-01-29 09:53:58 +01:00
Kasper Rynning-Tønnesen
f0bf000f4a Fixed issue where users was 0 2018-01-29 09:53:33 +01:00
Kasper Rynning-Tønnesen
2da1002d38 Merge pull request #273 from zoff-music/feature/embed-fixes
last and first page buttons for embedded version
2018-01-25 10:02:43 +01:00
Kasper Rynning-Tønnesen
2403646488 last and first page buttons for embedded version 2018-01-25 10:01:45 +01:00
Kasper Rynning-Tønnesen
99af0e8339 Merge pull request #272 from zoff-music/feature/start-end-mobile
Enabled setting start and end for a song on mobile
2018-01-24 12:53:28 +01:00
Kasper Rynning-Tønnesen
81b935cadf Enabled setting start and end for a song on mobile 2018-01-24 12:53:04 +01:00
Kasper Rynning-Tønnesen
bf395b061f Analytics pageview on navigation 2018-01-23 15:15:43 +01:00
Kasper Rynning-Tønnesen
79eb814677 Merge branch 'master' of github.com:zoff-music/zoff 2018-01-23 14:35:33 +01:00
Kasper Rynning-Tønnesen
cbd8872569 Transition on color for controls 2018-01-23 14:35:14 +01:00
Kasper Rynning-Tønnesen
cc96eb150c Merge pull request #269 from zoff-music/fix/area-click-options
Bigger optionsbutton on songs
2018-01-23 11:03:50 +01:00
Kasper Rynning-Tønnesen
8c4f23dc56 Bigger optionsbutton on songs 2018-01-23 11:03:28 +01:00
Kasper Rynning-Tønnesen
6fb415bc32 Merge pull request #268 from zoff-music/fix/name-loop
Trying to get a fix for looping namechanges
2018-01-22 15:07:41 +01:00
Kasper Rynning-Tønnesen
96e29f6856 Trying to get a fix for looping namechanges 2018-01-22 15:06:27 +01:00
Kasper Rynning-Tønnesen
ec515baca2 Update README.md 2018-01-22 08:39:18 +01:00
Kasper Rynning-Tønnesen
7eaec006fa Merge pull request #267 from zoff-music/fix/spotify-import
Fix for spotify import url
2018-01-22 08:38:21 +01:00
Kasper Rynning-Tønnesen
6968e0cdff Fix for spotify import url 2018-01-22 08:38:08 +01:00
Kasper Rynning-Tønnesen
24ba522cfb Merge pull request #266 from zoff-music/fix/footer-buttons-mobile
Better sizing of buttons on mobile
2018-01-18 15:01:06 +01:00
Kasper Rynning-Tønnesen
5777966d82 Better sizing of buttons on mobile 2018-01-18 15:00:41 +01:00
Kasper Rynning-Tønnesen
ab820b963a Merge pull request #265 from zoff-music/fix/donation-text
Added ethereum text
2018-01-18 12:21:09 +01:00
Kasper Rynning-Tønnesen
30d2b8f394 Added ethereum text 2018-01-18 12:18:40 +01:00
Kasper Rynning-Tønnesen
34512e34dd Merge pull request #264 from zoff-music/feature/complementary-bar
Improved colors for more faded
2018-01-17 15:19:06 +01:00
Kasper Rynning-Tønnesen
08195afdcb Improved colors for more faded 2018-01-17 15:18:29 +01:00
Kasper Rynning-Tønnesen
12c70f7afd Merge pull request #263 from zoff-music/feature/complementary-bar
Added other color to playbar for more fun
2018-01-17 14:16:31 +01:00
Kasper Rynning-Tønnesen
7135c594e3 Added other color to playbar for more fun 2018-01-17 14:16:05 +01:00
Kasper Rynning-Tønnesen
0606b22c39 Merge pull request #262 from zoff-music/fix/general_bug_fixes
Added pause effect on clicking zoff-image on embedded version
2018-01-17 09:23:56 +01:00
Kasper Rynning-Tønnesen
aa9f57cab1 Added pause effect on clicking zoff-image on embedded version 2018-01-17 09:23:22 +01:00
Kasper Rynning-Tønnesen
a7bb74f8af Merge pull request #261 from zoff-music/fix/general_bug_fixes
Fixed issue with title not being decoded correctly
2018-01-17 09:02:47 +01:00
Kasper Rynning-Tønnesen
817ec47a20 Fixed issue with title not being decoded correctly 2018-01-17 09:02:23 +01:00
Kasper Rynning-Tønnesen
68c8827630 Merge pull request #260 from zoff-music/fix/general_bug_fixes
Fixed player issue, and viewer issue on new channels
2018-01-12 13:46:54 +01:00
Kasper Rynning-Tønnesen
dbbd518978 Fixed player issue, and viewer issue on new channels 2018-01-12 13:46:21 +01:00
Kasper Rynning-Tønnesen
f6e94162cb Merge pull request #259 from zoff-music/fix/year
Updated year to update automatically
2018-01-11 08:49:59 +01:00
Kasper Rynning-Tønnesen
8e146e52f6 Updated year to update automatically 2018-01-11 08:49:41 +01:00
Kasper Rynning-Tønnesen
0cb3de6fae Merge pull request #258 from zoff-music/refactor/version-file
Moved versionnumber out to own file instead of defining it two places
2017-12-27 17:51:22 +01:00
Kasper Rynning-Tønnesen
65f0fcd4f9 Removed a whitespace 2017-12-27 17:50:39 +01:00
Kasper Rynning-Tønnesen
4afcbda9db Moved versionnumber out to own file instead of defining it two places 2017-12-27 17:47:43 +01:00
Kasper Rynning-Tønnesen
6df3af6978 Merge pull request #257 from zoff-music/fix/playlist-size
Fixed some playlist elements
2017-12-27 17:38:50 +01:00
Kasper Rynning-Tønnesen
a0ab993ffb Fixed some playlist elements
- Fixed issue with full song not being shown on mobile always
- Fixed issue where navigationbuttons are placed weirdly on desktop and mobile
- Fixed weird positioning issue on embedded player of songs
- Added navigationbuttons to embedded player
2017-12-27 17:38:11 +01:00
Kasper Rynning-Tønnesen
505e2ef47b Merge pull request #256 from zoff-music/feature/ethereum-donate
Added ethereum donate option
2017-12-22 13:45:35 +01:00
Kasper Rynning-Tønnesen
956dfaef6b Added ethereum donate option 2017-12-22 13:45:04 +01:00
Kasper Rynning-Tønnesen
2c442b4e60 Merge pull request #255 from zoff-music/refactor/qr-code-footer
Removed qr code from footer
2017-12-04 14:19:24 +01:00
Kasper Rynning-Tønnesen
19717de985 Removed qr code from footer 2017-12-04 14:18:57 +01:00
Kasper Rynning-Tønnesen
b6e0d28017 Merge pull request #254 from zoff-music/feature/scroll-chat
Closes #234
2017-12-04 13:07:39 +01:00
Kasper Rynning-Tønnesen
7f89cf80a7 Closes #234 2017-12-04 13:07:15 +01:00
Kasper Rynning-Tønnesen
e6b8064d23 Merge pull request #253 from zoff-music/feature/spotify-list-image
Fixed issue with wrong base64 image
2017-12-01 11:57:31 +01:00
Kasper Rynning-Tønnesen
6319b06608 Fixed issue with wrong base64 image 2017-12-01 11:57:07 +01:00
Kasper Rynning-Tønnesen
e62fbe7d21 Merge pull request #252 from zoff-music/feature/spotify-list-image
images not added for some reason..
2017-12-01 11:51:37 +01:00
Kasper Rynning-Tønnesen
8d7252c0f9 More general address for fetching image 2017-12-01 11:51:20 +01:00
Kasper Rynning-Tønnesen
e344b9615a images not added for some reason.. 2017-12-01 11:50:26 +01:00
Kasper Rynning-Tønnesen
f319238567 Merge pull request #251 from zoff-music/feature/spotify-list-image
Feature/spotify list image
2017-12-01 11:47:59 +01:00
Kasper Rynning-Tønnesen
8f49e4c1ee Removed logs 2017-12-01 11:47:26 +01:00
Kasper Rynning-Tønnesen
fe728ad3c2 Added spotify playlist image on exportation 2017-12-01 11:47:04 +01:00
Kasper Rynning-Tønnesen
03db8aa60a Merge pull request #250 from zoff-music/fix/donations
Better mobile handling
2017-11-29 20:19:15 +01:00
Kasper Rynning-Tønnesen
2aaa461e30 Better mobile handling 2017-11-29 20:05:56 +01:00
Kasper Rynning-Tønnesen
e7cddf00f9 Merge pull request #249 from zoff-music/fix/donations
Moved modals some round, and added donation-modal
2017-11-29 20:03:41 +01:00
Kasper Rynning-Tønnesen
8d7d3ebabc Moved modals some round, and added donation-modal 2017-11-29 20:02:42 +01:00
Kasper Rynning-Tønnesen
41f71a2f95 Merge pull request #248 from zoff-music/fix/offline-listeners
Offline-toggling fix
2017-11-22 17:41:25 +01:00
Kasper Rynning-Tønnesen
bab88edd10 Offline-toggling fix
- Fixed issue where offline-toggling incremented listener number, infine
2017-11-22 17:40:42 +01:00
Kasper Rynning-Tønnesen
77023e65e2 Merge pull request #247 from zoff-music/refactor/pagebuttons
Changed how pagebuttons are added/initialized
2017-11-22 17:05:00 +01:00
Kasper Rynning-Tønnesen
65d1b9cd61 Changed how pagebuttons are added/initialized 2017-11-22 17:04:38 +01:00
Kasper Rynning-Tønnesen
b94fa58db6 Minor change 2017-11-22 14:49:49 +01:00
Kasper Rynning-Tønnesen
3897923840 Merge pull request #246 from zoff-music/fix/margins-navbar
Fixed margins
2017-11-22 14:48:15 +01:00
Kasper Rynning-Tønnesen
8cc5963ce0 Fixed margins 2017-11-22 14:47:43 +01:00
Kasper Rynning-Tønnesen
fda32fe306 Merge pull request #245 from zoff-music/fix/overflow-body
Fixed issue where overflow is hidden on empty search
2017-11-22 12:20:11 +01:00
Kasper Rynning-Tønnesen
047dd256f0 Fixed issue where overflow is hidden on empty search 2017-11-22 12:19:48 +01:00
Kasper Rynning-Tønnesen
4e6d8cc5c4 Merge pull request #244 from zoff-music/refactor/general
Added two new events in README.md, and how zoff is pronounced (README…
2017-11-22 10:46:08 +01:00
Kasper Rynning-Tønnesen
f0d44b76f8 Added two new events in README.md, and how zoff is pronounced (README.md and about-modal) 2017-11-22 10:45:32 +01:00
Kasper Rynning-Tønnesen
9b1d1429a3 Merge pull request #243 from zoff-music/refactor/general
Refactored how menu-buttons are placed in playlist
2017-11-22 10:29:47 +01:00
Kasper Rynning-Tønnesen
181d9741e2 Refactored how menu-buttons are placed in playlist 2017-11-22 10:29:20 +01:00
Kasper Rynning-Tønnesen
48f85e9b69 Merge pull request #242 from zoff-music/refactor/general
Controls on mobile, and dragging
2017-11-21 17:48:48 +01:00
Kasper Rynning-Tønnesen
d4a2798dc8 Controls on mobile, and dragging
- Not using #playbar anymore, since the default controls work on mobile
- Removed List.dragging code, not in use anymore
2017-11-21 17:48:25 +01:00
Kasper Rynning-Tønnesen
e719dc632b Merge pull request #241 from zoff-music/fix/truncate-channel-name
Fixed issue where channel-name and url was truncated
2017-11-21 17:00:05 +01:00
Kasper Rynning-Tønnesen
9652abf10b Fixed issue where channel-name and url was truncated 2017-11-21 16:59:40 +01:00
Kasper Rynning-Tønnesen
572c63f011 Merge pull request #240 from zoff-music/fix/clipping-songs
Added fix for clipping songs on hover on small player
2017-11-21 16:18:16 +01:00
Kasper Rynning-Tønnesen
0578863317 Added fix for clipping songs on hover on small player 2017-11-21 16:17:42 +01:00
Kasper Rynning-Tønnesen
bdf531f80e Merge pull request #239 from zoff-music/fix/volume-slider-resize-hide
Fixed issue with volumeslider being hidden on window-resize
2017-11-21 15:12:01 +01:00
Kasper Rynning-Tønnesen
76aa1d1417 Fixed issue with volumeslider being hidden on window-resize 2017-11-21 15:11:32 +01:00
Kasper Rynning-Tønnesen
2fee4b359b Merge pull request #238 from zoff-music/fix/view-counter
Fixed issue with viewercounter being below 0
2017-11-21 11:27:21 +01:00
Kasper Rynning-Tønnesen
789a3cc1e7 Fixed issue with viewercounter being below 0 2017-11-21 11:27:01 +01:00
Kasper Rynning-Tønnesen
b92ff8146a Temporarily deactive self_ping 2017-11-20 15:04:38 +01:00
Kasper Rynning-Tønnesen
3afb93a21a Forgot to format logging correctly 2017-11-20 09:33:09 +01:00
Kasper Rynning-Tønnesen
31b47cac1d Added logs for error-checker 2017-11-20 09:30:58 +01:00
Kasper Rynning-Tønnesen
748f329f38 Show player bottom always 2017-11-14 15:34:14 +01:00
Kasper Rynning-Tønnesen
324b0438f4 Fixed video-container sizing issue on mobile 2017-11-14 15:20:10 +01:00
Kasper Rynning-Tønnesen
4505e2df1e Better transition of colors 2017-11-14 14:58:12 +01:00
Kasper Rynning-Tønnesen
8b1737df91 Merge pull request #237 from zoff-music/feature/mobile-desktop-search
Desktop and mobile use the same search
2017-11-14 14:52:36 +01:00
Kasper Rynning-Tønnesen
fdfe832ef9 Desktop and mobile use the same search 2017-11-14 14:48:52 +01:00
Kasper Rynning-Tønnesen
035f47d6c1 Merge pull request #236 from zoff-music/fix/404
Fixed 404 status not being sent
2017-11-14 12:43:28 +01:00
Kasper Rynning-Tønnesen
8219c25e42 Fixed 404 status not being sent 2017-11-14 12:42:53 +01:00
Kasper Rynning-Tønnesen
0ebd18de16 Merge pull request #235 from zoff-music/fix/404
Added a funny 404 page
2017-11-14 12:26:08 +01:00
Kasper Rynning-Tønnesen
1adff62a45 Added a funny 404 page 2017-11-14 12:24:09 +01:00
Kasper Rynning-Tønnesen
7b0d3c3232 Small adjustement to sending next song 2017-11-13 14:39:43 +01:00
Kasper Rynning-Tønnesen
8cc9a66948 Fix for errornous ending a song and sending many messages if slow internet 2017-11-13 14:32:06 +01:00
Kasper Rynning-Tønnesen
a43d9a327f Merge branch 'master' of github.com:zoff-music/zoff 2017-11-13 11:38:06 +01:00
Kasper Rynning-Tønnesen
b2f38b21e1 Testing if autopull works 2017-11-13 11:37:47 +01:00
Kasper Rynning-Tønnesen
4064e60976 Merge pull request #233 from zoff-music/fix/better-exporting
Better exporting, and small issues with sizing in panel
2017-11-11 16:16:57 +01:00
Kasper Rynning-Tønnesen
23ad15e662 Better exporting, and small issues with sizing in panel 2017-11-11 16:16:34 +01:00
Kasper Rynning-Tønnesen
527904d49b Fixed positioning of searchloader on mobile 2017-11-11 13:00:59 +01:00
Kasper Rynning-Tønnesen
82047a5e2d Small correction on volume-container-cast 2017-11-10 19:13:26 +01:00
Kasper Rynning-Tønnesen
a8190faebc Merge pull request #232 from zoff-music/fix/smaller-error-startup
Smaller error on startup in localhost mode
2017-11-10 16:51:23 +01:00
Kasper Rynning-Tønnesen
15b6c2788f Smaller error on startup in localhost mode 2017-11-10 16:51:01 +01:00
Kasper Rynning-Tønnesen
68a72befcd Merge pull request #231 from zoff-music/feature/mailrequirement
Feature/mailrequirement
2017-11-10 16:47:58 +01:00
Kasper Rynning-Tønnesen
dc7a347802 Made changes accordingly to readme.md 2017-11-10 16:47:37 +01:00
Kasper Rynning-Tønnesen
96c4cb443a Merge branch 'master' into feature/mailrequirement 2017-11-10 16:46:16 +01:00
Kasper Rynning-Tønnesen
adf72fa296 Don't require the mailconfig, but log out in the console that it wont be enabled. 2017-11-10 16:45:59 +01:00
Kasper Rynning-Tønnesen
c4168b6c07 Fixed issue in README.md 2017-11-10 16:41:06 +01:00
Kasper Rynning-Tønnesen
4e58c0a77f Updated README.md
- Added info about the config files
2017-11-10 16:40:27 +01:00
Kasper Rynning-Tønnesen
3462879cf9 Merge pull request #230 from zoff-music/fix/ensure-number
Ensuring that the start and end is a number
2017-11-10 16:35:00 +01:00
Kasper Rynning-Tønnesen
59e7edb5e3 Ensuring that the start and end is a number 2017-11-10 16:34:40 +01:00
Kasper Rynning-Tønnesen
9c4342c57e Merge pull request #229 from zoff-music/fix/errors-missing-configs
Added more error-messages on crashing because of missing files.
2017-11-10 16:25:50 +01:00
Kasper Rynning-Tønnesen
12c8ea2299 Merge pull request #228 from zoff-music/fix/end-of-video-fix
Fixed issue with player not changing song when the song is over defin…
2017-11-10 16:24:26 +01:00
Kasper Rynning-Tønnesen
814e1eaac9 Added more error-messages on crashing because of missing files. Closes #227 2017-11-10 16:23:45 +01:00
Kasper Rynning-Tønnesen
f047ae1e1f Fixed issue with player not changing song when the song is over defined by the endSeconds 2017-11-10 16:22:51 +01:00
Kasper Rynning-Tønnesen
521dfe2f2c Merge pull request #226 from zoff-music/fix/chat-select
Able to select in chat
2017-11-10 14:57:05 +01:00
Kasper Rynning-Tønnesen
2d4939f14c Able to select in chat 2017-11-10 14:56:44 +01:00
Kasper Rynning-Tønnesen
4b70d862de Merge pull request #225 from zoff-music/fix/improved-import-export
Improved import/export functions, started using levenshtein distance …
2017-11-10 14:03:57 +01:00
Kasper Rynning-Tønnesen
b66888ada0 Improved import/export functions, started using levenshtein distance as a supplement 2017-11-10 14:03:11 +01:00
Kasper Rynning-Tønnesen
721b1d1a25 Merge pull request #224 from zoff-music/fix/offline-fixes
Fixed start and end not being sent on add
2017-11-10 11:49:44 +01:00
Kasper Rynning-Tønnesen
28e822fbb1 Fixed start and end not being sent on add 2017-11-10 11:49:18 +01:00
Kasper Rynning-Tønnesen
e8a2a34e21 Merge pull request #223 from zoff-music/fix/offline-fixes
Dragging and loading
2017-11-10 11:36:32 +01:00
Kasper Rynning-Tønnesen
47e4cecdef Dragging and loading
- Fixed searching in offline
- Fixed load on mobile in offline
2017-11-10 11:36:06 +01:00
Kasper Rynning-Tønnesen
88585b793e Merge pull request #222 from zoff-music/fix/improved-finding-errorsongs
Fixed small } error
2017-11-10 11:16:38 +01:00
Kasper Rynning-Tønnesen
1debe715d4 Fixed small } error 2017-11-10 11:16:09 +01:00
Kasper Rynning-Tønnesen
fd585bcfbf Merge pull request #221 from zoff-music/fix/improved-finding-errorsongs
Fix/improved finding errorsongs
2017-11-10 11:14:11 +01:00
Kasper Rynning-Tønnesen
dc8290ff28 Removed log 2017-11-10 11:13:31 +01:00
Kasper Rynning-Tønnesen
9bcf20269a Improved finding errorounus songs, and fix error with embedded player 2017-11-10 11:13:01 +01:00
Kasper Rynning-Tønnesen
845d0a423e Merge pull request #220 from zoff-music/feature/song2
Setting a timed run of the song-testing
2017-11-09 21:00:55 +01:00
Kasper Rynning-Tønnesen
b9811a5391 Setting a timed run of the song-testing 2017-11-09 20:59:58 +01:00
Kasper Rynning-Tønnesen
6745c50d6b Merge pull request #219 from zoff-music/feature/song2
Feature/song2
2017-11-09 20:16:38 +01:00
Kasper Rynning-Tønnesen
ddfb94be01 Merge branch 'master' into feature/song2 2017-11-09 20:15:23 +01:00
Kasper Rynning-Tønnesen
375046d270 Trying a new approach 2017-11-09 20:08:15 +01:00
Kasper Rynning-Tønnesen
1b9b21bacd Merge pull request #218 from zoff-music/revert-217-feature/song-replacement
Revert "Feature/song replacement"
2017-11-09 19:51:42 +01:00
Kasper Rynning-Tønnesen
7a62057a30 Revert "Feature/song replacement" 2017-11-09 19:51:32 +01:00
Kasper Rynning-Tønnesen
5a08358f62 Merge pull request #217 from zoff-music/feature/song-replacement
Feature/song replacement
2017-11-09 19:48:15 +01:00
Kasper Rynning-Tønnesen
b03213d61a Got automatic detection working for changing song when they are similar enough (higher than 0.75) 2017-11-09 19:47:31 +01:00
Kasper Rynning-Tønnesen
3050d56bf8 Everything except img error handling working 2017-11-09 17:14:19 +01:00
Kasper Rynning-Tønnesen
c73f70d99c Merge pull request #216 from zoff-music/feature/song-validation
Feature/song validation
2017-11-09 16:13:21 +01:00
Kasper Rynning-Tønnesen
f86a5382f0 Forgot to add the files 2017-11-09 16:12:29 +01:00
Kasper Rynning-Tønnesen
e5013599c8 Added test serverside to ensure that title is correct + duration isn't insanely much higher that it should be 2017-11-09 16:11:57 +01:00
Kasper Rynning-Tønnesen
dd357ce7e3 Quick fix for enabling start and end seconds on chromecast 2017-11-09 08:07:49 +01:00
Kasper Rynning-Tønnesen
120006c866 Fixed margin error 2017-11-08 19:42:23 +01:00
Kasper Rynning-Tønnesen
62934c10c0 Small fix to ensure close button for sidenav stays there on desktop 2017-11-08 16:07:10 +01:00
Kasper Rynning-Tønnesen
f6fc3b4c81 Update README.md 2017-11-08 15:51:46 +01:00
Kasper Rynning-Tønnesen
92438a301e Merge pull request #214 from zoff-music/fix/duration-fix
Fixed issue with duration not working on songs without a start and en…
2017-11-08 15:45:23 +01:00
Kasper Rynning-Tønnesen
f90af8d2e1 Fixed issue with duration not working on songs without a start and end set 2017-11-08 15:44:48 +01:00
Kasper Rynning-Tønnesen
2e58559407 Merge pull request #213 from zoff-music/fix/sizing-results
Fixed issue with buttons on results
2017-11-08 15:40:33 +01:00
Kasper Rynning-Tønnesen
016f95052a Fixed issue with buttons on results 2017-11-08 15:40:14 +01:00
Kasper Rynning-Tønnesen
79c3844d6e Merge pull request #212 from zoff-music/fix/deleted-empty
Fixed issue with deleting a song in a list with 2 elements, it thinks…
2017-11-08 15:37:09 +01:00
Kasper Rynning-Tønnesen
6f28e10041 Fixed issue with deleting a song in a list with 2 elements, it thinks it is empty 2017-11-08 15:36:47 +01:00
Kasper Rynning-Tønnesen
736ae6abea Merge pull request #211 from zoff-music/feature/start-end-song
Added functionality for setting start and end on a song
2017-11-08 15:35:38 +01:00
Kasper Rynning-Tønnesen
47a1668cd5 Added functionality for setting start and end on a song 2017-11-08 15:33:50 +01:00
Kasper Rynning-Tønnesen
605468e891 No scroll on search 2017-11-07 16:44:24 +01:00
Kasper Rynning-Tønnesen
9ede1f8d2b Quickfix for initSlider not being run on reentering channel 2017-11-07 15:38:19 +01:00
Kasper Rynning-Tønnesen
1e7dcd7188 Merge pull request #209 from zoff-music/fix/volume-slider-resize
Fixed small issue with volume-slider being faulty initiated sometimes
2017-11-07 15:09:51 +01:00
Kasper Rynning-Tønnesen
847c42220e Fixed small issue with volume-slider being faulty initiated sometimes 2017-11-07 15:09:23 +01:00
Kasper Rynning-Tønnesen
7606f91480 Merge pull request #208 from zoff-music/fix/volume-slider-resize
Fixed issue with volumeslider being messed up on windowresize
2017-11-07 14:55:25 +01:00
Kasper Rynning-Tønnesen
c86372b0fc Fixed issue with volumeslider being messed up on windowresize 2017-11-07 14:54:44 +01:00
Kasper Rynning-Tønnesen
4175eaa271 Merge pull request #207 from zoff-music/fix/readme-update
Readme updates
2017-11-06 16:05:43 +01:00
Kasper Rynning-Tønnesen
d02de27ff5 Readme updates 2017-11-06 16:05:22 +01:00
Kasper Rynning-Tønnesen
66a4ba19f7 Merge pull request #206 from zoff-music/feature/pagination_search
Search pagination and animations
2017-11-06 16:00:25 +01:00
Kasper Rynning-Tønnesen
7bf551dfce Search pagination and animations
- Added previous and next button at the end of searches, and styled the buttons
- Added so buttons only work when there are a previous or next page, depending on what is clicked
- Added a pretty and better way of showing the search with animations
2017-11-06 15:59:57 +01:00
Kasper Rynning-Tønnesen
532bc851c0 Merge pull request #205 from zoff-music/fix/errors
Changed cursor of toast
2017-11-06 14:54:41 +01:00
Kasper Rynning-Tønnesen
124ab116e7 Changed cursor of toast 2017-11-06 14:54:07 +01:00
Kasper Rynning-Tønnesen
b00fe9a33e Merge pull request #204 from zoff-music/fix/errors
Fixed errors appearing in log
2017-11-06 14:51:52 +01:00
Kasper Rynning-Tønnesen
98149e1fe5 Fixed errors appearing in log
- Fixed Uncaught TypeError: Cannot read property 'removeChild' of null error
- Fixed Uncaught TypeError: Cannot read property 'tweensContainer' of undefined

first error was a problem with toasts, and how they were removed
second error was problem with playlist tabs, and trying to set the selected_tab after the tabscontainer was removed
2017-11-06 14:51:30 +01:00
Kasper Rynning-Tønnesen
01c95f90f5 Merge pull request #203 from zoff-music/fix/update-helper-modal
updated help modal in channel
2017-11-03 16:02:20 +01:00
Kasper Rynning-Tønnesen
c00e92c6f4 updated help modal in channel 2017-11-03 16:01:51 +01:00
Kasper Rynning-Tønnesen
2d0d8d5a50 Merge pull request #202 from zoff-music/fix/no-snow-channel
No snow on channel
2017-11-02 17:04:00 +01:00
Kasper Rynning-Tønnesen
1bf34d0bdb No snow on channel 2017-11-02 17:03:38 +01:00
Kasper Rynning-Tønnesen
1b51bf9389 Merge pull request #201 from zoff-music/fix/snow-fix
Fixed issue with snow not dissapearing
2017-11-02 13:15:31 +01:00
Kasper Rynning-Tønnesen
a81bd8600a Fixed issue with snow not dissapearing 2017-11-02 13:14:52 +01:00
Kasper Rynning-Tønnesen
09316e6363 Merge pull request #200 from zoff-music/feature/delete-all-songs-confirmation
Added confirmationprompt on delete all songs
2017-11-02 13:12:14 +01:00
Kasper Rynning-Tønnesen
3fef6379dc Added confirmationprompt on delete all songs 2017-11-02 13:11:39 +01:00
Kasper Rynning-Tønnesen
8765f72641 Merge pull request #199 from zoff-music/feature/snow-channel
Snow in channel also on video
2017-11-02 11:45:43 +01:00
Kasper Rynning-Tønnesen
c3183e746c Snow in channel also on video 2017-11-02 11:45:21 +01:00
Kasper Rynning-Tønnesen
56d7db4257 Merge pull request #198 from zoff-music/fix/password-set-fix
Fixed issue where setting password was faulty on entering channel a s…
2017-11-02 11:38:21 +01:00
Kasper Rynning-Tønnesen
084550d84c Fixed issue where setting password was faulty on entering channel a second time 2017-11-02 11:38:02 +01:00
Kasper Rynning-Tønnesen
95f6ae4b57 Merge pull request #197 from zoff-music/refactor/api-own-file
Added api to own file
2017-11-01 12:53:56 +01:00
Kasper Rynning-Tønnesen
795686df05 Merge pull request #196 from zoff-music/fix/pausefix
Fixed skipping/pause issues
2017-11-01 12:53:41 +01:00
Kasper Rynning-Tønnesen
b776e03da8 Added api to own file 2017-11-01 12:53:15 +01:00
Kasper Rynning-Tønnesen
d7677a5f7a Fixed skipping/pause issues 2017-11-01 12:52:38 +01:00
Kasper Rynning-Tønnesen
5145b8d03c Removed unused files 2017-11-01 12:18:03 +01:00
Kasper Rynning-Tønnesen
48971cb7d3 Merge pull request #195 from zoff-music/revert-194-refactor/combinejs
Revert "Trying to concat libs"
2017-11-01 11:59:46 +01:00
Kasper Rynning-Tønnesen
787ea6f1e4 Revert "Trying to concat libs" 2017-11-01 11:59:37 +01:00
Kasper Rynning-Tønnesen
fab74f236a Merge pull request #194 from zoff-music/refactor/combinejs
Trying to concat libs
2017-11-01 11:57:52 +01:00
Kasper Rynning-Tønnesen
35e2460773 Trying to concat libs 2017-11-01 11:57:31 +01:00
Kasper Rynning-Tønnesen
57faabd8dd Merge branch 'master' of github.com:zoff-music/zoff 2017-10-31 14:54:44 +01:00
Kasper Rynning-Tønnesen
4850d3558c Added background-color to match footer for overscroll on mac 2017-10-31 14:54:22 +01:00
Kasper Rynning-Tønnesen
135b78df1f Merge pull request #193 from zoff-music/fix/scaling-w3c
Scaling rule removed for better w3c validator
2017-10-31 14:04:22 +01:00
Kasper Rynning-Tønnesen
a64d2d8bc8 Scaling rule removed for better w3c validator 2017-10-31 14:04:02 +01:00
Kasper Rynning-Tønnesen
5304feaebb Merge pull request #192 from zoff-music/fix/polyfill-color-sizing
Fixed small issues with sizing of polyfill container
2017-10-31 13:58:58 +01:00
Kasper Rynning-Tønnesen
de007073bc Fixed small issues with sizing of polyfill container 2017-10-31 13:58:37 +01:00
Kasper Rynning-Tønnesen
8de842f154 Merge pull request #191 from zoff-music/feature/polyfill-color
Feature/polyfill color
2017-10-31 13:55:55 +01:00
Kasper Rynning-Tønnesen
c501b162e8 Styled polyfill window for colorpicker to match rest of site 2017-10-31 13:55:22 +01:00
Kasper Rynning-Tønnesen
a31cc6c759 Added colorpicker polyfill 2017-10-31 13:34:12 +01:00
Kasper Rynning-Tønnesen
bfcfb6d140 Merge pull request #190 from zoff-music/fix/cleared_channel
Fixed issue with added a playlist to a recently cleared channel
2017-10-30 12:26:44 +01:00
Kasper Rynning-Tønnesen
e08c72f98c Fixed issue with added a playlist to a recently cleared channel 2017-10-30 12:26:15 +01:00
Kasper Rynning-Tønnesen
bbce393a5f Merge pull request #189 from zoff-music/fix/chat-skip
Fixed issue where name of person skipping not being correctly sent
2017-10-18 17:03:52 +02:00
Kasper Rynning-Tønnesen
3b8e4ce952 Fixed issue where name of person skipping not being correctly sent 2017-10-18 17:03:24 +02:00
Kasper Rynning-Tønnesen
1dbf9931ea Merge pull request #188 from zoff-music/fix/html-markup-fix
Fixed issue from html validator with li not being inside ul
2017-10-17 21:18:36 +02:00
Kasper Rynning-Tønnesen
96e46fdbbb Fixed issue from html validator with li not being inside ul 2017-10-17 21:17:56 +02:00
Kasper Rynning-Tønnesen
d62bd31aa9 Merge pull request #187 from zoff-music/fix/panel-refactorfix
Refactored in more files, and fixed issues with panel markup
2017-10-17 20:51:36 +02:00
Kasper Rynning-Tønnesen
2e685ef9dd Refactored in more files, and fixed issues with panel markup 2017-10-17 20:50:34 +02:00
Kasper Rynning-Tønnesen
074ae2bdaf Merge pull request #186 from zoff-music/fix/readme-typos
Receives is types receives not recieves
2017-10-17 20:21:56 +02:00
Kasper Rynning-Tønnesen
ceb5ed309e Receives is types receives not recieves 2017-10-17 20:21:27 +02:00
Kasper Rynning-Tønnesen
a588bffb17 Merge pull request #185 from zoff-music/fix/hostcontroller
Fixed versionissue in hostcontroller.js
2017-10-17 20:20:11 +02:00
Kasper Rynning-Tønnesen
84c5981e60 Merge pull request #184 from zoff-music/fix/readme-logs
Fix/readme logs
2017-10-17 20:19:59 +02:00
Kasper Rynning-Tønnesen
0a17e736e8 Fixed versionissue in hostcontroller.js 2017-10-17 20:19:40 +02:00
Kasper Rynning-Tønnesen
68a18ef869 Updated events being sent 2017-10-17 20:18:58 +02:00
Kasper Rynning-Tønnesen
f351b6bb99 Started working on README.md events 2017-10-17 16:12:50 +02:00
Kasper Rynning-Tønnesen
a5fccb3a5e Removed previous logs 2017-10-17 16:01:45 +02:00
Kasper Rynning-Tønnesen
68b6317f1a Log added now maybe? 2017-10-17 15:57:43 +02:00
Kasper Rynning-Tønnesen
1504496219 Trying testcommand for building purposes 2017-10-17 15:55:58 +02:00
Kasper Rynning-Tønnesen
4eb4fe995e Merge pull request #182 from zoff-music/fix/chat_names
Trying a fix for chat names crashing the server
2017-10-17 15:53:25 +02:00
Kasper Rynning-Tønnesen
0be7813428 Trying a fix for chat names crashing the server 2017-10-17 15:52:51 +02:00
Kasper Rynning-Tønnesen
9a4df38122 Merge pull request #181 from zoff-music/refactor/cdns
Fixed relative issue
2017-10-17 15:48:25 +02:00
Kasper Rynning-Tønnesen
a7f147eb1f Fixed relative issue 2017-10-17 15:47:24 +02:00
Kasper Rynning-Tønnesen
90ee089b37 Merge pull request #180 from zoff-music/refactor/cdns
Personalized jquery-ui-min
2017-10-17 15:44:27 +02:00
Kasper Rynning-Tønnesen
f53a6ecedd Personalized jquery-ui-min 2017-10-17 15:44:02 +02:00
Kasper Rynning-Tønnesen
831f163ea9 Merge pull request #179 from zoff-music/refactor/cdns
Trying to use cdns
2017-10-17 15:39:37 +02:00
Kasper Rynning-Tønnesen
6a3f945ce5 Trying to use cdns 2017-10-17 15:38:56 +02:00
Kasper Rynning-Tønnesen
c90253993b Merge pull request #178 from zoff-music/refactor/ignoring
Refactor/ignoring
2017-10-17 15:18:41 +02:00
Kasper Rynning-Tønnesen
aa0d35c854 Removed old files 2017-10-17 15:17:38 +02:00
Kasper Rynning-Tønnesen
5830c4c06b Merged 2017-10-17 15:16:28 +02:00
Kasper Rynning-Tønnesen
f5facd0b70 Removed cached version 2017-10-17 15:13:47 +02:00
Kasper Rynning-Tønnesen
acadfb5b19 Added minified to ignorelist 2017-10-17 15:11:01 +02:00
Kasper Rynning-Tønnesen
3b4cfe2af7 Merge pull request #176 from zoff-music/feature/auto-pull
updated gulpfile
2017-10-17 14:55:53 +02:00
Kasper Rynning-Tønnesen
1fa7a7e439 updated gulpfile 2017-10-17 14:53:39 +02:00
Kasper Rynning-Tønnesen
fb35851cc5 Merge pull request #175 from zoff-music/fix/chat-icons
Fixed chat icons
2017-10-17 14:44:45 +02:00
Kasper Rynning-Tønnesen
6e3ca04fe8 Fixed chat icons 2017-10-17 14:39:09 +02:00
Kasper Rynning-Tønnesen
2a1bcc51ba Merge pull request #174 from zoff-music/refactor/folders
Moved files to config folders, and updated pm2 command
2017-10-17 14:21:10 +02:00
Kasper Rynning-Tønnesen
70360f3760 Moved files to config folders, and updated pm2 command 2017-10-17 14:12:49 +02:00
Kasper Rynning-Tønnesen
c7816f5d15 Merge pull request #173 from zoff-music/refactor/move
Moved to more partials
2017-10-17 14:00:25 +02:00
Kasper Rynning-Tønnesen
73c73fbcff Merge pull request #172 from zoff-music/fix/examples
Added examplefiles
2017-10-17 14:00:12 +02:00
Kasper Rynning-Tønnesen
a9b3adb368 Added examplefiles 2017-10-17 13:59:38 +02:00
Kasper Rynning-Tønnesen
3fbfb6c12f Moved to more partials 2017-10-17 13:56:46 +02:00
Kasper Rynning-Tønnesen
0f6e9f8161 Trying to support fb.zoff.me 2017-10-16 22:35:46 +02:00
Kasper Rynning-Tønnesen
f8bbf7a278 CORS 2017-10-16 22:31:44 +02:00
Kasper Rynning-Tønnesen
4933b6f8b9 cors 2017-10-16 22:27:51 +02:00
Kasper Rynning-Tønnesen
89a5c3b485 Included fb.zoff.me 2017-10-16 22:19:15 +02:00
Kasper Rynning-Tønnesen
f2e7c67457 Trying a log 2017-10-16 22:07:13 +02:00
Kasper Rynning-Tønnesen
3d0ed3aeb5 Fixed urls 2017-10-16 22:05:48 +02:00
Kasper Rynning-Tønnesen
296327ba7d Removed unused variables and trying to fix frontpage error on fb.zoff.me 2017-10-16 22:03:33 +02:00
Kasper Rynning-Tønnesen
b25ca4eadd Moved certificates and stuff 2017-10-16 21:56:48 +02:00
Kasper Rynning-Tønnesen
e0c17676cd Updated certificate 2017-10-16 21:53:39 +02:00
Kasper Rynning-Tønnesen
b1b3ed4f28 Better aligning of volume-slider and chromecast button on mobile 2017-10-16 12:05:05 +02:00
Kasper Rynning-Tønnesen
e3ce00ca18 Margin readded, looked weird without 2017-10-14 13:24:04 +02:00
Kasper Rynning-Tønnesen
a65ae66e03 Fixed coloring of volume-slider on mobile 2017-10-14 13:22:28 +02:00
Kasper Rynning-Tønnesen
5b0b779530 More aligning and prettified playbar somewhat 2017-10-14 13:20:23 +02:00
Kasper Rynning-Tønnesen
47974a4711 Aligned skip buttons better 2017-10-14 13:08:45 +02:00
Kasper Rynning-Tønnesen
6daf87ceaf Removed futura 2017-10-13 20:20:24 +02:00
Kasper Rynning-Tønnesen
d789118aa7 Fixed issue with snow-images 2017-10-13 16:08:10 +02:00
Kasper Rynning-Tønnesen
d8c1abfba9 10 minutes chat history, limit of 20 messages 2017-10-13 13:47:13 +02:00
Kasper Rynning-Tønnesen
3b50d84af8 Better icon-handling 2017-10-12 17:23:49 +02:00
Kasper Rynning-Tønnesen
520558166b Minor change to how image is added 2017-10-11 18:34:17 +02:00
Kasper Rynning-Tønnesen
5d51159832 Sizing 2017-10-11 18:30:03 +02:00
Kasper Rynning-Tønnesen
2daa9607d2 Images for admins and stuff 2017-10-11 18:24:54 +02:00
Kasper Rynning-Tønnesen
94d7d50789 Only sending namechange if userstarted, and fixed visual chat on mobile 2017-10-11 15:07:49 +02:00
Kasper Rynning-Tønnesen
f38b5ad3e9 More contrast in chat, and fixed skipbutton highlight bug on mobile 2017-10-11 14:45:19 +02:00
Kasper Rynning-Tønnesen
80c37d9cba Easier to see where people chat from 2017-10-11 14:39:22 +02:00
Kasper Rynning-Tønnesen
ec2ea167b3 Case insensitive 2017-10-11 12:27:31 +02:00
Kasper Rynning-Tønnesen
c04614e95b Names reimplemented, just a little better 2017-10-11 12:22:08 +02:00
Kasper Rynning-Tønnesen
f13ba939a4 playbarbutton class 2017-10-11 10:00:49 +02:00
Kasper Rynning-Tønnesen
1a84051252 more aligning 2017-10-11 09:57:15 +02:00
Kasper Rynning-Tønnesen
c873e85a1c Fixed issue with skip and prev button being misaligned 2017-10-11 09:55:16 +02:00
Kasper Rynning-Tønnesen
fd47f9ca8b Animated hamburger menu working 2017-10-11 09:38:47 +02:00
Kasper Rynning-Tønnesen
1a52a9f769 Shufflebutton visible on mobile 2017-10-09 10:13:20 +02:00
Kasper Rynning-Tønnesen
f88d53b132 Fixed local issue with infinite users 2017-10-09 08:42:07 +02:00
Kasper Rynning-Tønnesen
2339327a6e Offline previous song 2017-10-08 22:31:59 +02:00
Kasper Rynning-Tønnesen
9fd9cd301b Moved skip-button down 2017-10-08 21:51:43 +02:00
Kasper Rynning-Tønnesen
b55598b5d9 Embed changed 2017-10-04 12:43:39 +02:00
Kasper Rynning-Tønnesen
a810e3365e Fixed dragging error on mobile 2017-10-04 12:37:56 +02:00
Kasper Rynning-Tønnesen
ac6a07b9b2 Updated readme 2017-10-03 17:02:53 +02:00
Kasper Rynning-Tønnesen
3aadcbd9e8 Deleted a package.json 2017-10-03 16:58:59 +02:00
Kasper Rynning-Tønnesen
17c65267d5 Update README.md 2017-10-03 16:50:09 +02:00
Kasper Rynning-Tønnesen
31e2681e2f precomposed correctly 2017-10-03 16:42:19 +02:00
Kasper Rynning-Tønnesen
811d8f0737 reverting to using shortname 2017-10-03 16:38:26 +02:00
Kasper Rynning-Tønnesen
4a3dbd3aef sending precomposed instead of apple-touch 2017-10-03 16:36:38 +02:00
Kasper Rynning-Tønnesen
f71d641f8f precomposed image also present 2017-10-03 16:34:45 +02:00
Kasper Rynning-Tønnesen
94004af00c trying fix for safari-pinned-tab 2017-10-03 16:31:03 +02:00
Kasper Rynning-Tønnesen
2535da4e40 Fixed safari-pinned-tab 2017-10-03 16:27:28 +02:00
Kasper Rynning-Tønnesen
0570bfd45a Trying to get realfavicon working 2017-10-03 16:25:31 +02:00
Kasper Rynning-Tønnesen
ef329b9b71 Used realfavicongenerator.net to generate new favicons 2017-10-03 16:14:39 +02:00
Kasper Rynning-Tønnesen
c14c9717b7 Fixing weird visual bug on frontpage for firefox 2017-10-03 15:38:49 +02:00
Kasper Rynning-Tønnesen
e0ca8eab68 Different color on chat time 2017-09-28 12:24:57 +02:00
Kasper Rynning-Tønnesen
0ee6a9fde7 Time on chat 2017-09-28 12:04:36 +02:00
Kasper Rynning-Tønnesen
182ebeca50 Prefix for icon 2017-09-28 11:33:35 +02:00
Kasper Rynning-Tønnesen
a41a1c1728 Trying to fix for firefox.. 2017-09-28 11:13:43 +02:00
Kasper Rynning-Tønnesen
c2c0cfcc58 Fixed issue with lock being placed weird on firefox 2017-09-28 11:09:42 +02:00
Kasper Rynning-Tønnesen
41488aecf4 Removed tooltipped as class 2017-09-27 11:27:26 +02:00
Kasper Rynning-Tønnesen
70f9eda634 Removed tooltips from mobile 2017-09-27 11:23:18 +02:00
Kasper Rynning-Tønnesen
b246c2029f Added more api 2017-09-26 16:54:42 +02:00
Kasper Rynning-Tønnesen
733ced2697 half to the right 2017-09-25 22:14:15 +02:00
Kasper Rynning-Tønnesen
55e50edca7 Better background and positioning of the volumeslider for mobile 2017-09-25 22:12:53 +02:00
Kasper Rynning-Tønnesen
bb40c21f97 Styling on volumebar 2017-09-25 21:59:30 +02:00
Kasper Rynning-Tønnesen
bc397c1ef1 More volumecontrol for chromecasting 2017-09-25 21:49:38 +02:00
Kasper Rynning-Tønnesen
5c78119a3a Hopefully fixed to crashpoints 2017-09-25 16:54:50 +02:00
Kasper Rynning-Tønnesen
9372bf3bf0 More indentation 2017-09-22 11:45:54 +02:00
Kasper Rynning-Tønnesen
68d243c93a Removed some old functions and indented code 2017-09-22 11:42:26 +02:00
Kasper Rynning-Tønnesen
758f7cebc4 Made improvement to admin-site 2017-09-19 14:43:56 +02:00
Kasper Rynning-Tønnesen
34633c6e33 Removing tooltips from channel on navigating back to frontpage 2017-09-18 17:40:56 +02:00
Kasper Rynning-Tønnesen
36d56828f0 Updated images on README.md 2017-09-18 15:11:55 +02:00
Kasper Rynning-Tønnesen
7a89defb3b Removed github from bottom 2017-09-18 15:08:21 +02:00
Kasper Rynning-Tønnesen
c4967ae120 Updated .gitignore and npm scripts 2017-09-18 15:01:48 +02:00
Kasper Rynning-Tønnesen
5f1c6549c9 Updated gulpfile, and sending total # of users 2017-09-18 14:51:09 +02:00
Kasper Rynning-Tønnesen
77c374f9b7 Returned to refactored state 2017-09-18 14:47:24 +02:00
Kasper Rynning-Tønnesen
52c7552b67 Fixed issue with unique id crashing server 2017-09-18 13:27:12 +02:00
Kasper Rynning-Tønnesen
130538f462 Fixed errors in code 2017-09-18 12:45:34 +02:00
Kasper Rynning-Tønnesen
440d5dc677 Trying to improve cpu on server.. 2017-09-18 12:30:16 +02:00
Kasper Rynning-Tønnesen
71f5be88df Trying to deactivate send_ping 2017-09-17 22:23:48 +02:00
Kasper Rynning-Tønnesen
c3935c993b Fixed issue with autocomplete not appearing 2017-09-17 22:16:43 +02:00
Kasper Rynning-Tønnesen
78bf0f6750 Fixed issue with viewing all channels on the frontpage 2017-09-17 22:15:04 +02:00
Kasper Rynning-Tønnesen
4db99a148e important to be imortant 2017-09-17 22:11:51 +02:00
Kasper Rynning-Tønnesen
9663898e9b Moved text somewhat up on frontpage 2017-09-17 22:10:59 +02:00
Kasper Rynning-Tønnesen
76ece66b66 Trying to deactivate cache 2017-09-17 22:00:11 +02:00
Kasper Rynning-Tønnesen
de92bae7f5 Trying to use rest to fetch frontpagelists 2017-09-17 21:39:30 +02:00
Kasper Rynning-Tønnesen
1f342c4090 Set up api for frontpages 2017-09-17 21:29:22 +02:00
Kasper Rynning-Tønnesen
0be7816edc Trying to move frontpage back to io.js 2017-09-17 21:23:41 +02:00
Kasper Rynning-Tønnesen
7d2cecd6be Trying to not use greater than 2017-09-17 21:14:08 +02:00
Kasper Rynning-Tønnesen
733d839b85 Fixed namechange error 2017-09-17 11:35:18 +02:00
Kasper Rynning-Tønnesen
850be93973 Trying to improve frontpage fetching 2017-09-17 11:33:01 +02:00
Kasper Rynning-Tønnesen
5bbde84a7c Trying to get server to understand 2017-09-14 12:02:41 +02:00
Kasper Rynning-Tønnesen
d0e53ec1f5 Fixed issue with fb.zoff.me not being able to connect 2017-09-14 12:00:12 +02:00
Kasper Rynning-Tønnesen
f241243d28 Updated templates a bit, and improved frontpage sorting 2017-09-13 22:38:28 +02:00
Kasper Rynning-Tønnesen
a6d238e4df Forgot to flush names 2017-09-13 19:42:32 +02:00
Kasper Rynning-Tønnesen
c8e8e841e6 Fixed issue with errorounououoesess coll on linje 106 in chat 2017-09-13 19:39:24 +02:00
Kasper Rynning-Tønnesen
bc71e67ca4 Deactivated usernames for now, until it is more stabil 2017-09-13 19:35:56 +02:00
Kasper Rynning-Tønnesen
22b62e36cd Starting to work on some better pinging for usernames 2017-09-13 18:36:12 +02:00
Kasper Rynning-Tønnesen
2931dfc99b Fixed embed and spotifycallback issue 2017-09-13 15:48:31 +02:00
Kasper Rynning-Tønnesen
165ca4ad32 Fixed typo 2017-09-13 15:46:44 +02:00
Kasper Rynning-Tønnesen
a42b746abf Fixed issue with lists not being sorted properly on the frontpage 2017-09-13 15:46:04 +02:00
Kasper Rynning-Tønnesen
a8fa6a2901 Fixed issue with frontpagelists image not being saved on 404 2017-09-13 15:22:39 +02:00
Kasper Rynning-Tønnesen
5be5934ea2 Merge branch 'master' of github.com:zoff-music/zoff 2017-09-13 15:11:28 +02:00
Kasper Rynning-Tønnesen
e629f70906 Fixed issue with channelname not being changed 2017-09-13 15:10:58 +02:00
Kasper Rynning-Tønnesen
26e4214a50 Update server.js 2017-09-13 13:05:42 +02:00
Kasper Rynning-Tønnesen
be5056f712 Update chat.js 2017-09-13 13:03:27 +02:00
Kasper Rynning-Tønnesen
62250f890a Chromecast backendfix 2017-09-13 09:05:04 +02:00
Kasper Rynning-Tønnesen
a2e7bb7ffb Updated socket.id for chromecastlistening on mobile 2017-09-12 20:19:13 +02:00
Kasper Rynning-Tønnesen
a6a7c86975 Sending some info to adminpanel 2017-09-12 17:53:04 +02:00
Kasper Rynning-Tønnesen
4d9db5cba8 Made temporary fix for adminpanel crashing server 2017-09-12 17:50:38 +02:00
Kasper Rynning-Tønnesen
253b5d75d9 Trying small fix for null-viewers bug 2017-09-12 17:43:31 +02:00
Kasper Rynning-Tønnesen
e8ed8fa815 Fixed issue with leaving and joining a channel on the same computer made you not able to speak in chat 2017-09-12 17:37:21 +02:00
Kasper Rynning-Tønnesen
e606361371 Merge pull request #168 from zoff-music/refactoring
Refactoring
2017-09-12 16:57:45 +02:00
Kasper Rynning-Tønnesen
7c4e56b00c Merged with master 2017-09-12 16:53:15 +02:00
Kasper Rynning-Tønnesen
02081d9bb5 Fixed issue with toasts acting weird 2017-09-12 16:52:04 +02:00
Kasper Rynning-Tønnesen
977d3846f4 refactored and moved a lot of code around to separate files 2017-09-12 16:50:26 +02:00
Kasper Rynning-Tønnesen
657ace250a Names fixed 2017-09-12 14:12:24 +02:00
Kasper Rynning-Tønnesen
9efe6ab34e names working 2017-09-12 13:14:33 +02:00
Kasper Rynning-Tønnesen
ce4d49cc8f Skippedtimes 2017-09-12 10:48:41 +02:00
Kasper Rynning-Tønnesen
43af2219d1 Unique id via DB 2017-09-12 10:22:07 +02:00
Kasper Rynning-Tønnesen
bf8563bd74 Fixed issue with skip not working 2017-09-12 10:05:23 +02:00
Kasper Rynning-Tønnesen
8f1a8f60e3 not sending empty lists 2017-09-11 20:00:33 +02:00
Kasper Rynning-Tønnesen
cbdacf299b Fixing issue with too many total viewers 2017-09-11 18:49:58 +02:00
Kasper Rynning-Tønnesen
a7d213630c Removed condition where in_list was set whenever frontpage lists where fetched 2017-09-11 16:56:50 +02:00
Kasper Rynning-Tønnesen
0fecac6cca Added upsert to two fields 2017-09-11 16:45:49 +02:00
Kasper Rynning-Tønnesen
fd71c4406e Typo 2017-09-11 16:29:22 +02:00
Kasper Rynning-Tønnesen
546baa09cc Fixed some issues with multi-db 2017-09-11 16:27:45 +02:00
Kasper Rynning-Tønnesen
05ce8923e6 Fixed issue with infinate counter 2017-09-11 16:24:13 +02:00
Kasper Rynning-Tønnesen
7e96a1e584 selftest 2017-09-11 16:15:36 +02:00
Kasper Rynning-Tønnesen
2b07dccc39 Trying to move connected users and such from in-memory to db 2017-09-11 15:50:43 +02:00
Kasper Rynning-Tønnesen
d99ef644ad Trying to fix issue with total viewer count 2017-09-11 10:57:29 +02:00
Kasper Rynning-Tønnesen
e27e547f8d Fixing issue with dead listeners on server restart 2017-09-11 10:44:39 +02:00
Kasper Rynning-Tønnesen
b79e38af34 Trying caching in express-handlebars 2017-09-11 10:35:51 +02:00
Kasper Rynning-Tønnesen
f1f374763c not showing lists with 0 songs 2017-09-11 09:57:19 +02:00
Kasper Rynning-Tønnesen
052cdc229a Improved performance on server on frontpage a bit 2017-09-11 09:52:58 +02:00
Kasper Rynning-Tønnesen
2673892974 UPPERCASE FUCK 2017-09-11 09:02:21 +02:00
Kasper Rynning-Tønnesen
d55680425b Ensuring version is sent before testing the value of it 2017-09-11 09:01:33 +02:00
Kasper Rynning-Tønnesen
29c7af98f2 Fixed issue with frontpage crashing server 2017-09-11 08:59:23 +02:00
Kasper Rynning-Tønnesen
2afacf6408 Added a way of ensuring correct versions between server and client 2017-09-11 08:57:31 +02:00
Kasper Rynning-Tønnesen
7ccb9298c0 Channel fix 2017-09-08 15:44:17 +02:00
Kasper Rynning-Tønnesen
7f5d52ca30 Sending current server to chromecast also 2017-09-08 15:39:19 +02:00
Kasper Rynning-Tønnesen
4c7b8e17e1 Updated embed to accommodate the new changees for dead listeners 2017-09-08 14:59:54 +02:00
Kasper Rynning-Tønnesen
0483250196 Merge pull request #167 from zoff-music/fix/dead_listeners
Trying fix for dead listeners
2017-09-08 15:52:17 +03:00
Kasper Rynning-Tønnesen
94e041e002 Trying fix for dead listeners 2017-09-08 14:51:47 +02:00
Kasper Rynning-Tønnesen
5702b4cf8a Merge pull request #166 from zoff-music/tooltips
tooltips thingy
2017-09-08 15:38:17 +03:00
Kasper Rynning-Tønnesen
93424424eb tooltips thingy 2017-09-06 16:07:54 +02:00
Kasper Rynning-Tønnesen
b429f646f3 Made improvements to find 2017-09-06 14:07:03 +02:00
Kasper Rynning-Tønnesen
95a15f4b6e Updated find-div to say how many were found, and the current found in the array.
- Fixed bug where updating the searchtext when CTRL+F (find) didn't reset the search in the list
- Fixed bug where using the find function when a song is changed didn't reset the search
2017-09-06 12:39:24 +02:00
Kasper Rynning-Tønnesen
84cbdfaba0 Improved way of showing playbuttom somewhat 2017-08-28 19:24:29 +02:00
Kasper Rynning-Tønnesen
47e018bb99 Fixed issue with mobile not playing 2017-08-28 19:20:41 +02:00
Kasper Rynning-Tønnesen
8041de8e56 Updated materializecss 2017-08-28 11:15:56 +02:00
Kasper Rynning-Tønnesen
c010bcc4df Fixed issue with Toasts, and temporarily disabled drag-to-delete on mobile 2017-08-11 20:16:20 +02:00
Kasper Rynning-Tønnesen
b92949fd18 Moved names around, and added some text to the contact field 2017-08-08 15:57:40 +02:00
Kasper Rynning-Tønnesen
26cd2feb1b Fixed issue with some modals, and showing a toast on wrong list password 2017-07-22 18:56:59 +02:00
Kasper Rynning-Tønnesen
f05f061d89 Updated to materializecss v0.100.1 2017-07-22 15:09:46 +02:00
Kasper Rynning-Tønnesen
09d858486d Fixed issue with channelloader going indefinetly on empty channel 2017-07-22 14:38:56 +02:00
Kasper Rynning-Tønnesen
a5bb390479 Fixed issue with importing playlist on passwordprotected playlist didnt inform the user 2017-07-22 14:23:43 +02:00
Kasper Rynning-Tønnesen
7298df62a9 Fix for find and apuse 2017-07-19 08:35:35 +02:00
Kasper Rynning-Tønnesen
8427c1bd70 Fixing issue with decodeURIComponent 2017-07-09 23:14:53 +02:00
Kasper Rynning-Tønnesen
3830279f69 Trying to fix issue with dragging 2017-06-23 16:42:38 +02:00
Kasper Rynning-Tønnesen
f204f5d341 Forgot to save style.css 2017-06-23 16:35:02 +02:00
Kasper Rynning-Tønnesen
f618fabfda Smaller player on mobile handle delete button better 2017-06-23 16:33:36 +02:00
Kasper Rynning-Tønnesen
2bae0af081 Adding some logs to the server for debugging purposes 2017-06-22 23:16:17 +02:00
Kasper Rynning-Tønnesen
e6c7682380 fixed issue with player not always showing up with a video, and skipping to fast not always changing the video 2017-06-19 23:21:25 +02:00
Kasper Rynning-Tønnesen
bd950fc1e7 Smoother drag on element 2017-06-19 07:21:31 +02:00
Kasper Rynning-Tønnesen
9a721102c0 Lower cases on entering enw channel 2017-06-18 21:43:46 +02:00
Kasper Rynning-Tønnesen
11d473373d Fixed issue with empty playlists 2017-06-18 21:40:30 +02:00
Kasper Rynning-Tønnesen
51dcb53aa5 Setting limit for 10px before new way of deleting is triggered 2017-06-18 21:33:45 +02:00
Kasper Rynning-Tønnesen
49dab75c35 New way of deleting songs on mobile 2017-06-18 21:03:15 +02:00
Kasper Rynning-Tønnesen
24432e0d0d Centering inputfields 2017-06-16 20:19:37 +02:00
Kasper Rynning-Tønnesen
4595a70239 Buttons more matching throughout the site 2017-06-16 20:17:18 +02:00
Kasper Rynning-Tønnesen
67ab79aa68 Zoff logo now shows as button 2017-06-16 19:23:22 +02:00
Kasper Rynning-Tønnesen
6ac548ee37 Added some tooltips and made noselect even more noselect 2017-06-16 16:20:22 +02:00
Kasper Rynning-Tønnesen
2f60f92dbd Adding song and removing song comes from two different sides now 2017-06-16 16:08:14 +02:00
Kasper Rynning-Tønnesen
7e8136752b Animation on song remove, song add 2017-06-16 15:42:07 +02:00
Kasper Rynning-Tønnesen
083cc921a1 Embedding sending correct title 2017-06-15 19:01:11 +02:00
Kasper Rynning-Tønnesen
e320dca191 Updated embedded version 2017-06-15 18:56:14 +02:00
Kasper Rynning-Tønnesen
a025953f3f More fixes for current playing, and enabling remotecontroller if specified 2017-06-15 18:42:18 +02:00
Kasper Rynning-Tønnesen
e76f9f59b5 Full path instead of relative for assets on chat 2017-06-15 13:52:43 +02:00
Kasper Rynning-Tønnesen
2a87d4f10e Fixed issue where chat-blinking pointed to a dead local link 2017-06-15 13:51:13 +02:00
Kasper Rynning-Tønnesen
7e0b1d9034 Updated embedded player to send now playing and next sooner 2017-06-15 12:59:50 +02:00
Kasper Rynning-Tønnesen
a0c1fa293a Moved toast container somewhat on mobile 2017-06-13 15:56:49 +02:00
Kasper Rynning-Tønnesen
df99dd2b92 More mobile castbutton fixes 2017-06-13 15:54:56 +02:00
Kasper Rynning-Tønnesen
5bb185e181 updated style for castbutton on mobile 2017-06-13 15:54:00 +02:00
Kasper Rynning-Tønnesen
e106d3defd Fixed issue with next song not being sent to embedder 2017-06-09 01:20:52 +02:00
Kasper Rynning-Tønnesen
0458d93d96 Now sending duration event, and next song event to listening embedder 2017-06-09 01:10:51 +02:00
Kasper Rynning-Tønnesen
cb16d2186e even elements in chat list, darker color 2017-06-07 02:25:50 +02:00
Kasper Rynning-Tønnesen
b992baf136 Animated chromecast-icon 2017-06-07 01:27:34 +02:00
Kasper Rynning-Tønnesen
9a57ad1b59 Fixed issue where chromecast button not showing up when navigating back and forth from channels 2017-06-07 00:49:46 +02:00
Kasper Rynning-Tønnesen
991e093b8d Incrementing down, not up.. 2017-06-07 00:42:49 +02:00
Kasper Rynning-Tønnesen
b11b0faf0e Fixing issue with removeafter play not being incremented on the frontpage 2017-06-07 00:36:23 +02:00
Kasper Rynning-Tønnesen
26d558c725 Fixed truncate on card-reveal for description, and removing player when closing the player from the frontpage 2017-06-07 00:23:03 +02:00
Kasper Rynning-Tønnesen
9df7c1802a Prettier chromecast icon on phone 2017-06-05 19:02:23 +02:00
Kasper Rynning-Tønnesen
03e608b1b1 Improvements to look and feel of embedded player 2017-06-05 15:26:44 +02:00
Kasper Rynning-Tønnesen
946b646822 Iframe instead of embed 2017-06-05 14:59:24 +02:00
Kasper Rynning-Tønnesen
3b0d7df4df Moved find-div to front 2017-06-05 10:58:51 +02:00
Kasper Rynning-Tønnesen
b79bea899c Trying again to update frontpagelist.. 2017-06-05 10:55:36 +02:00
Kasper Rynning-Tønnesen
b6bcad56e1 Count fix deleted songs 2017-06-05 10:52:31 +02:00
Kasper Rynning-Tønnesen
d2ce406088 Fixed issue where deleteing all songs didnt clear the frontpage info 2017-06-05 10:47:34 +02:00
Kasper Rynning-Tønnesen
d8bae1142b Fixed delete all button 2017-06-05 10:43:56 +02:00
Kasper Rynning-Tønnesen
947cf6df0d Got chromecast discoveryworking 2017-06-04 23:11:47 +02:00
Kasper Rynning-Tønnesen
10934c53e0 Forgot to remove a log 2017-06-04 22:47:15 +02:00
Kasper Rynning-Tønnesen
7383c8731d Fix for chromecast feature-discovery not showing up 2017-06-04 22:45:31 +02:00
Kasper Rynning-Tønnesen
4757bf263c Fixed issue with viewers not updating 2017-06-04 14:03:05 +02:00
Kasper Rynning-Tønnesen
b6f7a834d8 Started using the more options button on the suggested videos also, to ensure similarity through the page 2017-06-04 10:45:27 +02:00
Kasper Rynning-Tønnesen
a20f454642 Merge pull request #165 from zoff-music/mobilehack
Updated embedded to allow for showing only video
2017-06-03 22:34:43 +02:00
Kasper Rynning-Tønnesen
bbf3f884be Updated embedded to allow for showing only video 2017-06-03 22:33:56 +02:00
Kasper Rynning-Tønnesen
b17615bb11 Merge pull request #164 from zoff-music/mobilehack
Mobilehack
2017-06-03 21:15:04 +02:00
Kasper Rynning-Tønnesen
5500e89579 Opening for better integration with fetching and sending title-events 2017-06-03 21:14:18 +02:00
Kasper Rynning-Tønnesen
57b1b68fb3 Listener update for chromecast 2017-06-03 19:55:42 +02:00
Kasper Rynning-Tønnesen
aa3679737b Chromecast now joining correct namespace 2017-06-02 15:07:46 +02:00
Kasper Rynning-Tønnesen
568a141b21 Fix for github-commit-fetch 2017-06-02 13:05:51 +02:00
Kasper Rynning-Tønnesen
7f13a71771 Mobile 'hack' 2017-06-02 11:03:00 +02:00
Kasper Rynning-Tønnesen
a85623dbbf Delete all songs button added. DANGER 2017-06-01 13:30:12 +02:00
Kasper Rynning-Tønnesen
558deadd45 Updating certificates 2017-05-31 23:08:35 +02:00
Kasper Rynning-Tønnesen
eb3085a23c Github commit fix 2017-05-31 20:54:28 +02:00
Kasper Rynning-Tønnesen
c93957bb18 Target fix 2017-05-31 20:47:30 +02:00
Kasper Rynning-Tønnesen
9379297be1 no fireplace on mobile 2017-05-31 17:27:38 +02:00
Kasper Rynning-Tønnesen
4dbfbe262e Removing deprecationnotice in console 2017-05-31 15:48:47 +02:00
Kasper Rynning-Tønnesen
6cf5577907 Better handling of removing service-worker 2017-05-31 15:45:36 +02:00
Kasper Rynning-Tønnesen
19c0c45433 Song-title widt 2017-05-31 15:43:45 +02:00
Kasper Rynning-Tønnesen
dfc8519e28 Spacebar also unpauses now 2017-05-31 14:07:11 +02:00
Kasper Rynning-Tønnesen
2de4f4f8b6 Play button now functions on song changed 2017-05-31 14:05:26 +02:00
Kasper Rynning-Tønnesen
7a3c2b7c86 Adding tap-target for chromecast-button when first time seeing the chromecast available icon 2017-05-31 12:57:08 +02:00
Kasper Rynning-Tønnesen
daabc07268 Options menu on playlist elements 2017-05-30 19:48:49 +02:00
Kasper Rynning-Tønnesen
1257075c03 Removing song from results when clicked add many button 2017-05-30 17:51:33 +02:00
Kasper Rynning-Tønnesen
52218cafaf Waves-effeeeect 2017-05-30 17:34:38 +02:00
Kasper Rynning-Tønnesen
7678ce5dbe Added open in YouTube button on search, and setting start/endtime of YouTube video.
- Opening for further development with userset end/starttime
2017-05-29 22:20:05 +02:00
Kasper Rynning-Tønnesen
c10477f4e0 Fixing double playlist error 2017-05-28 18:43:40 +02:00
Kasper Rynning-Tønnesen
e8adcafecc Update close-settings button 2017-05-28 18:22:51 +02:00
Kasper Rynning-Tønnesen
44fc43d5c6 More spacebar pausefixes 2017-05-28 18:20:08 +02:00
Kasper Rynning-Tønnesen
5c49e8d7bc No pause on video on sending mail also 2017-05-28 18:17:00 +02:00
Kasper Rynning-Tønnesen
4901c46457 Fixed issue with typing password and such tried to pause video 2017-05-28 18:15:31 +02:00
Kasper Rynning-Tønnesen
03433f0329 Font size on viewers for mobile 2017-05-28 17:51:13 +02:00
Kasper Rynning-Tønnesen
d7eecc5de8 Footer fixes 2017-05-27 22:50:45 +02:00
Kasper Rynning-Tønnesen
fb9572c6cf Trying to fix error where results sometimes end up as undefined when searching 2017-05-27 22:42:53 +02:00
Kasper Rynning-Tønnesen
f17ac8728b Added spacebar pause 2017-05-27 20:18:10 +02:00
Kasper Rynning-Tønnesen
94c6ac091f Showing viewers on mobile 2017-05-27 13:41:50 +02:00
Kasper Rynning-Tønnesen
cfecbbf3e2 Updates to playlist sizing on screen width 2017-05-27 13:31:03 +02:00
Kasper Rynning-Tønnesen
39797f82ab Padding on playlist 2017-05-26 14:40:55 +02:00
Kasper Rynning-Tønnesen
9273e61cb4 Trying update of socket.io to 2.0.1 2017-05-26 14:35:40 +02:00
Kasper Rynning-Tønnesen
2cbf055fe2 Pointer events on controls 2017-05-26 14:28:13 +02:00
Kasper Rynning-Tønnesen
696afe722f Controls on bottom when too small 2017-05-26 13:56:29 +02:00
Kasper Rynning-Tønnesen
14d84f821f hd also 2017-05-24 19:48:38 +02:00
Kasper Rynning-Tønnesen
f8a3c5ede9 Spotify exports 2017-05-24 19:44:46 +02:00
Kasper Rynning-Tønnesen
2aa9af8778 Updated way of exporting, now doesn't crash when trying again and removed a searchword 2017-05-24 19:36:36 +02:00
Kasper Rynning-Tønnesen
f43b3b50e5 Buttonnames.. 2017-05-23 18:41:12 +02:00
Kasper Rynning-Tønnesen
f9359636a3 Renaming private mode to local mode 2017-05-23 18:37:07 +02:00
Kasper Rynning-Tønnesen
a9edf426e9 No animation on delete 2017-05-23 11:15:52 +02:00
Kasper Rynning-Tønnesen
2caa7b1487 Update on the pinging to try and keep the client alive 2017-05-20 19:23:17 +02:00
Kasper Rynning-Tønnesen
d86cb764ab Added google-play badge and link 2017-05-20 12:44:15 +02:00
Kasper Rynning-Tønnesen
0ffe14cbdf Embedded is now also ajour 2017-05-16 17:26:22 +02:00
Kasper Rynning-Tønnesen
7e83116a61 Fixed issues regarding forcing restarts, and userpasswords not working correctly 2017-05-16 16:44:48 +02:00
Kasper Rynning-Tønnesen
0db90fe416 Major update on cryptosystem, all passwords now obsolete.. 2017-05-16 15:15:47 +02:00
Kasper Rynning-Tønnesen
b6b19cc8b7 Autohiding copy-link 2017-05-14 15:10:28 +02:00
Kasper Rynning-Tønnesen
b9349d53a0 Removed scripts and added from github 2017-05-14 14:13:10 +02:00
Kasper Rynning-Tønnesen
b6c6600f1f Removed a simple log 2017-05-14 14:06:24 +02:00
Kasper Rynning-Tønnesen
e72f9a635c Copying video link now working 2017-05-14 14:06:01 +02:00
Kasper Rynning-Tønnesen
c8cc177bbe Deleting correct song on error 2017-05-14 13:13:04 +02:00
Kasper Rynning-Tønnesen
54d33022b3 Skipping on error 2017-05-14 13:04:36 +02:00
Kasper Rynning-Tønnesen
8605ac49cd Trying fix for skip on error 2017-05-14 13:02:27 +02:00
Kasper Rynning-Tønnesen
1ded3c391c Fixed shadowtransition bug 2017-05-13 18:39:29 +02:00
Kasper Rynning-Tønnesen
6dead53184 Fixed donationhash 2017-05-13 15:21:29 +02:00
Kasper Rynning-Tønnesen
a16ec66017 Added another test for voting 2017-05-12 23:41:11 +02:00
Kasper Rynning-Tønnesen
4102c85f5f No select 2017-05-11 13:29:14 +02:00
Kasper Rynning-Tønnesen
3f0ff5d40f Updated some minor server stuff 2017-05-11 11:15:47 +02:00
Kasper Rynning-Tønnesen
e84c8695ab Fixed error when adding a new song to an empty playlist in private mode 2017-05-11 11:01:40 +02:00
Kasper Rynning-Tønnesen
adc5f9438a Updated link from remote-site 2017-05-11 10:39:40 +02:00
Kasper Rynning-Tønnesen
c426bd1da3 Fixing issue with skipping too fast 2017-05-09 23:35:53 +02:00
Kasper Rynning-Tønnesen
d40fed6213 Added a failsafe for servercrash 2017-05-09 13:32:31 +02:00
Kasper Rynning-Tønnesen
c581c11d04 Removed serviceworker, yet again 2017-05-09 12:55:06 +02:00
Kasper Rynning-Tønnesen
f240877928 Service-worker 2017-05-09 12:49:28 +02:00
Kasper Rynning-Tønnesen
a0d245b818 Re added service-worker 2017-05-09 12:45:05 +02:00
Kasper Rynning-Tønnesen
2d00c1df13 Removed serviceworker completely 2017-05-09 12:28:56 +02:00
Kasper Rynning-Tønnesen
4851a8a4ed Removed restrictions 2017-05-06 15:11:54 +02:00
Kasper Rynning-Tønnesen
a84f338534 indentations on server.js 2017-05-06 13:46:17 +02:00
Kasper Rynning-Tønnesen
627719a967 More indentationfixes 2017-05-06 13:29:23 +02:00
Kasper Rynning-Tønnesen
f1d4b80636 Fixed a lot of indentations 2017-05-06 13:21:39 +02:00
Kasper Rynning-Tønnesen
60a7610a28 Fixed authentication issue with chat 2017-05-06 11:37:46 +02:00
Kasper Rynning-Tønnesen
417c928b77 Removing channelpassword from cookies on delete 2017-05-06 11:27:31 +02:00
Kasper Rynning-Tønnesen
92ba3f1a82 Fixed critical crash issue with shuffling 2017-05-05 23:30:37 +02:00
Kasper Rynning-Tønnesen
1a2513920b Another list issue fix 2017-05-05 18:10:42 +02:00
Kasper Rynning-Tønnesen
a680b3ce0a Updated issue with 'pos' 2017-05-05 18:07:41 +02:00
Kasper Rynning-Tønnesen
22c8743aa8 Forgot to revert embedded target 2017-05-05 18:03:33 +02:00
Kasper Rynning-Tønnesen
267ac9a86e Updated frontpage-rotation somewhat, to prevent more than one timer to be active at any given time 2017-05-05 17:59:56 +02:00
Kasper Rynning-Tønnesen
f71dcb51e9 Made major improvements to embedded player, added option for making server force clients to fully refresh, and added some more failsafes for the server 2017-05-05 17:35:27 +02:00
Kasper Rynning-Tønnesen
b9aa04f360 Fixed issue with event trying to fire without existing 2017-05-05 16:45:37 +02:00
Kasper Rynning-Tønnesen
611bee8a99 Trying fix for serviceworker 2017-05-05 16:35:26 +02:00
Kasper Rynning-Tønnesen
7f09c1a999 Fixed issue with playeroverlay 2017-05-05 16:18:07 +02:00
Kasper Rynning-Tønnesen
aa1ca995f0 Fixed issue with toasts comming in the background 2017-05-05 15:58:04 +02:00
Kasper Rynning-Tønnesen
7714729093 Fixed issue with password not being set correctly 2017-05-05 15:53:13 +02:00
Kasper Rynning-Tønnesen
9d06c2bda7 Update server.js 2017-05-05 12:02:42 +02:00
Kasper Rynning-Tønnesen
f8ec4cd888 Update server.js 2017-05-05 10:48:10 +02:00
Kasper Rynning-Tønnesen
eee681a5a5 Update service-worker.js 2017-05-05 09:34:16 +02:00
Kasper Rynning-Tønnesen
c980ca3ae4 Update service-worker.js 2017-05-05 09:33:54 +02:00
Kasper Rynning-Tønnesen
554912a18f Update server.js 2017-05-05 09:25:15 +02:00
Kasper Rynning-Tønnesen
c3ca04a747 Update server.js 2017-05-05 09:16:18 +02:00
Kasper Rynning-Tønnesen
5186bbd4f1 Merge pull request #163 from zoff-music/listpasswords
Listpasswords
2017-05-04 23:36:52 +02:00
Kasper Rynning-Tønnesen
adbd1bb88d Added list-passwords for regular users 2017-05-04 23:36:25 +02:00
Kasper Rynning-Tønnesen
fa38f69f75 Locked password alert shows up correctly 2017-05-04 18:01:05 +02:00
Kasper Rynning-Tønnesen
01bb2c02e6 Started implementation 2017-05-04 13:32:24 +02:00
Kasper Rynning-Tønnesen
49734b935d updated title 2017-05-03 19:37:00 +02:00
Kasper Rynning-Tønnesen
e57dc9867d Updated robots.txt 2017-05-03 19:34:54 +02:00
Kasper Rynning-Tønnesen
da2711e307 Updated cacheversion 2017-05-03 19:29:27 +02:00
Kasper Rynning-Tønnesen
730cf0d724 Changed .gitignore, and started using service-worker again 2017-05-03 19:26:02 +02:00
Kasper Rynning-Tønnesen
c9af861073 Gulpfile format 2017-05-03 19:08:51 +02:00
Kasper Rynning-Tønnesen
5f8984d2d1 fixed background error 2017-05-03 19:00:42 +02:00
Kasper Rynning-Tønnesen
ef6d3af3a9 fixed port redirect issue 2017-05-03 18:47:57 +02:00
Kasper Rynning-Tønnesen
84dd2d7b9f Updated routing somewhat, so it should be possible to run the server without being in the correct folder 2017-05-03 18:37:16 +02:00
Kasper Rynning-Tønnesen
a5257c62f6 updatd manifest.json 2017-05-03 18:11:11 +02:00
Kasper Rynning-Tønnesen
de6a3cc2ca updated package and created pm2 runfile 2017-05-03 16:43:28 +02:00
Kasper Rynning-Tønnesen
743870d2fb Update README.md 2017-05-03 12:31:28 +02:00
Kasper Rynning-Tønnesen
9bc885ceab Moved where events are in the readme 2017-05-02 21:05:03 +02:00
Kasper Rynning-Tønnesen
a53b484fad Added a new mailservice 2017-05-02 20:56:29 +02:00
Kasper Rynning-Tønnesen
ffe5a70f01 Changed php to express in readme 2017-05-02 20:15:38 +02:00
Kasper Rynning-Tønnesen
b6e578015c Updated README 2017-05-02 20:12:14 +02:00
Kasper Rynning-Tønnesen
0685003d9c Fixed issue with player height on mobile 2017-05-02 19:59:56 +02:00
Kasper Rynning-Tønnesen
566367d8ba updated so background ahs transiton 2017-05-02 19:39:12 +02:00
Kasper Rynning-Tønnesen
df5565caae Removed php text 2017-05-02 19:37:37 +02:00
Kasper Rynning-Tønnesen
c05a49028c Merge pull request #160 from zoff-music/nodejsserver
Nodejsserver
2017-05-02 19:36:06 +02:00
Kasper Rynning-Tønnesen
dd322529c4 forgot to change the port 2017-05-02 19:30:08 +02:00
Kasper Rynning-Tønnesen
8c17f7c711 forgot to remove some server_2 2017-05-02 19:29:31 +02:00
Kasper Rynning-Tønnesen
a3e3a6a950 Reverting some https 2017-05-02 19:26:26 +02:00
Kasper Rynning-Tønnesen
9461488dec No console 2017-05-02 18:39:21 +02:00
Kasper Rynning-Tønnesen
5300959499 Fixing remotecontroller 2017-05-02 18:34:59 +02:00
Kasper Rynning-Tønnesen
228b8b1928 Updated way of setting color 2017-05-02 18:31:08 +02:00
Kasper Rynning-Tønnesen
380a6cd60e Fixed issue with trying to access private list 2017-05-02 18:28:39 +02:00
Kasper Rynning-Tønnesen
0a16370ba7 Fixed redirecting 2017-05-02 18:25:24 +02:00
Kasper Rynning-Tønnesen
f366b9a0dc Made change to both functions 2017-05-02 18:06:31 +02:00
Kasper Rynning-Tønnesen
f8e5d63fba Updated some routing 2017-05-02 18:05:51 +02:00
Kasper Rynning-Tønnesen
1d97e9b37e updated protocol enforcing 2017-05-02 18:03:14 +02:00
Kasper Rynning-Tønnesen
e3fba808b1 Portchange 2017-05-02 17:59:04 +02:00
Kasper Rynning-Tønnesen
c523f44cd9 Trying some small fixes 2017-05-02 17:57:59 +02:00
Kasper Rynning-Tønnesen
cef9af4d2d Fixed issue with mongodb 2017-05-02 17:29:28 +02:00
Kasper Rynning-Tønnesen
d40e0d0080 Working handlebars 2017-05-02 17:25:21 +02:00
Kasper Rynning-Tønnesen
9f3e2fddb9 NodeJS server instead of PHP 2017-05-01 23:51:02 +02:00
Kasper Rynning-Tønnesen
824e061996 Updated way of deleting song when not exist 2017-05-01 16:54:58 +02:00
Kasper Rynning-Tønnesen
53cf85046b Height of video 2017-05-01 12:07:26 +02:00
Kasper Rynning-Tønnesen
3c2603b33f Added privatemode for mobile 2017-04-29 21:36:47 +02:00
Kasper Rynning-Tønnesen
c97fc41399 Fixed issue with closebutton not working on frontpage 2017-04-29 17:58:19 +02:00
Kasper Rynning-Tønnesen
7942c8b121 Updated player_overlay 2017-04-29 17:11:19 +02:00
Kasper Rynning-Tønnesen
2a9eeda325 Updated player_overlay height 2017-04-29 17:08:53 +02:00
Kasper Rynning-Tønnesen
36592d55f9 Fixed bug where you can't change viewing channels on frontpage when navigating back and forth 2017-04-29 16:46:31 +02:00
Kasper Rynning-Tønnesen
ee846b7dff Fixed emptychannel placehodler 2017-04-29 16:38:46 +02:00
Kasper Rynning-Tønnesen
4055b52ba0 updated where to remove select programmatically 2017-04-29 16:12:02 +02:00
Kasper Rynning-Tønnesen
407e3a67d0 Updated text for disabled in select on frontpage 2017-04-29 16:10:22 +02:00
Kasper Rynning-Tønnesen
8bb17343bf added option for showing all channels on frontpage, will probably crash stuff 2017-04-29 16:02:56 +02:00
Kasper Rynning-Tønnesen
66987b9339 Delete LICENSE 2017-04-29 15:10:00 +02:00
Kasper Rynning-Tønnesen
fa7a8a0e0f Create LICENSE 2017-04-29 15:08:35 +02:00
Kasper Rynning-Tønnesen
4c9a17208c Update README.md 2017-04-29 15:00:07 +02:00
Kasper Rynning-Tønnesen
cc61a0cb89 Added another failsafe for video not always starting from 0 2017-04-29 14:37:29 +02:00
Kasper Rynning-Tønnesen
f2a98d6bae Firelace in the front, always 2017-04-29 14:24:50 +02:00
Kasper Rynning-Tønnesen
0b082b8484 Updated jquery-ui to only contain things we need, and reverted materialize.min.js to its original state 2017-04-29 14:10:34 +02:00
Kasper Rynning-Tønnesen
aff12c0f7e Fixed issues with mobileplayer 2017-04-29 13:16:42 +02:00
Kasper Rynning-Tønnesen
7998ffb906 Updated delete-button font-size 2017-04-29 13:03:06 +02:00
Kasper Rynning-Tønnesen
b738589414 overlay fix on video-container 2017-04-29 12:58:21 +02:00
Kasper Rynning-Tønnesen
151dbd5b47 More improvements to moving video-container 2017-04-29 12:51:49 +02:00
Kasper Rynning-Tønnesen
0236493e53 using transform instead of position for moving the videoplayer around2 2017-04-29 12:33:10 +02:00
Kasper Rynning-Tønnesen
d503d3a41b Removed a lot of dead elements when navigating back and forth, and added transition on videoplayer 2017-04-29 11:35:19 +02:00
Kasper Rynning-Tønnesen
2b531039c0 updating mailscript 2017-04-28 17:43:48 +02:00
Kasper Rynning-Tønnesen
ebd0fe64af Added dragging variable to embed to fix bar bug 2017-04-28 17:36:35 +02:00
Kasper Rynning-Tønnesen
49031905c8 SSL not being sent on embed... 2017-04-28 17:34:44 +02:00
Kasper Rynning-Tønnesen
ab863addd0 SSL for embed 2017-04-28 17:33:01 +02:00
Kasper Rynning-Tønnesen
1a028a1fbf Changing position of next-prev buttons on playlist in embedded version 2017-04-28 17:23:39 +02:00
Kasper Rynning-Tønnesen
195176e04a more tweaks to the embedded version 2017-04-28 17:20:01 +02:00
Kasper Rynning-Tønnesen
ca524be461 Fixed some dragging issues, and updated the embedded version 2017-04-28 17:05:57 +02:00
Kasper Rynning-Tønnesen
f1f0659899 Added dragging to the duration while in private-mode 2017-04-28 16:36:50 +02:00
Kasper Rynning-Tønnesen
7e2d16ed20 Updated qr-code link to a div 2017-04-28 16:23:36 +02:00
Kasper Rynning-Tønnesen
8068b2eb68 Updated materializeCSS to 0.98.2 2017-04-28 15:19:01 +02:00
Kasper Rynning-Tønnesen
f39426686e Removed fullscreen button from mobile 2017-04-28 15:04:42 +02:00
Kasper Rynning-Tønnesen
750623ea55 Removed materializeCSS slider 2017-04-13 12:35:26 +02:00
Kasper Rynning-Tønnesen
61b2e42472 Updated HSL 2017-04-13 12:32:58 +02:00
Kasper Rynning-Tønnesen
fdb9cd7b43 Updated materializeCSS to 0.98.1 2017-04-13 12:30:40 +02:00
Kasper Rynning-Tønnesen
d8d14dd77c Updated so the placeholder on the frontpage changes 2017-03-22 12:22:17 +01:00
Kasper Rynning-Tønnesen
82723e101f Removed redirect in javascript 2017-03-16 15:27:41 +01:00
Kasper Rynning-Tønnesen
bd298544bd updated frontpage again 2017-03-16 14:44:53 +01:00
Kasper Rynning-Tønnesen
17b3450deb Updated frontpage redirecting 2017-03-16 14:42:54 +01:00
Kasper Rynning-Tønnesen
9ae2634ec8 Trying small fix for redirecting and such 2017-03-16 14:37:53 +01:00
Kasper Rynning-Tønnesen
18e6c82e28 Trying to update serviceworker 2017-03-15 12:45:28 +01:00
Kasper Rynning-Tønnesen
a1f42d8646 Chromecast fixes 2017-03-15 10:41:50 +01:00
Kasper Rynning-Tønnesen
f00071ce3c Fix for skipping in offline mode on chromecast 2017-03-15 10:39:32 +01:00
Kasper Rynning-Tønnesen
4afc7dd0bd Trying fix for get_values 2017-03-14 23:32:57 +01:00
Kasper Rynning-Tønnesen
d1f0dd3323 more relatives 2017-03-14 23:21:33 +01:00
Kasper Rynning-Tønnesen
3b27913da3 reverting 2017-03-14 23:20:02 +01:00
Kasper Rynning-Tønnesen
6372b946bd Trying fix for weird get-requests 2017-03-14 23:18:12 +01:00
Kasper Rynning-Tønnesen
5694a8d484 Updated so suggestions get cleared 2017-03-03 11:27:14 +01:00
Kasper Rynning-Tønnesen
a57826201a Static imagesize on result image, and fixed way of adding suggested number 2017-03-03 11:08:42 +01:00
Kasper Rynning-Tønnesen
f6211944be Hiding suggested notifier when none notified 2017-03-03 10:59:32 +01:00
Kasper Rynning-Tønnesen
d2820f942e forcing flex on suggested-link 2017-03-03 10:57:31 +01:00
Kasper Rynning-Tønnesen
cbe270594d Fixed some positioning of the notification of suggestions 2017-03-03 10:55:43 +01:00
Kasper Rynning-Tønnesen
df44f83341 Way of notifying admins of suggested songs, closes #140 2017-03-03 10:49:06 +01:00
Kasper Rynning-Tønnesen
60b2016fdf Updated some private mode information 2017-03-03 10:18:59 +01:00
Kasper Rynning-Tønnesen
1fbbc31ff0 Working seekto on chromecast also 2017-03-03 08:26:14 +01:00
Kasper Rynning-Tønnesen
95c7ca62ff reverting 2017-03-02 21:57:42 +01:00
Kasper Rynning-Tønnesen
77cae92007 changed back to non socket.zoff.me 2017-03-02 21:55:12 +01:00
Kasper Rynning-Tønnesen
835ffb7f39 Trying new way of connecting to socketio 2017-03-02 21:36:39 +01:00
Kasper Rynning-Tønnesen
c8901a7c1b Updated so users can seekto position in song 2017-03-02 21:15:20 +01:00
Kasper Rynning-Tønnesen
82d734f96e Trying some changes for fb canvas 2017-03-01 16:16:46 +01:00
Kasper Rynning-Tønnesen
744ca2c219 Trying a fix for facebookcanvas 2017-03-01 14:55:16 +01:00
Kasper Rynning-Tønnesen
d6d31ffb14 added some testing stuff 2017-03-01 14:48:40 +01:00
Kasper Rynning-Tønnesen
8754511c64 Updated last-commit 2017-03-01 14:28:16 +01:00
Kasper Rynning-Tønnesen
48bd42a795 Fixed issue with last commit linking to api.github instead of commit itself 2017-03-01 14:22:02 +01:00
Kasper Rynning-Tønnesen
c26f1d67e4 Embed css ubdate 2017-02-28 19:40:41 +01:00
Kasper Rynning-Tønnesen
11459c45c2 Merged 2017-02-28 19:38:11 +01:00
Kasper Rynning-Tønnesen
492236376c Updated vote-button 2017-02-28 19:37:25 +01:00
Kasper Rynning-Tønnesen
f46790b7f0 Merge pull request #159 from zoff-music/medomain
Medomain
2017-02-28 19:27:56 +01:00
Kasper Rynning-Tønnesen
55b13366b5 Updated some frontpage styling 2017-02-28 19:25:51 +01:00
Kasper Rynning-Tønnesen
67ae9159bc More .me redirects 2017-02-28 19:22:29 +01:00
Kasper Rynning-Tønnesen
9a4004a166 .htaccess update 2017-02-28 18:50:35 +01:00
Kasper Rynning-Tønnesen
0cab9db135 More changes made 2017-02-28 18:40:12 +01:00
Kasper Rynning-Tønnesen
5baf8772cc Updates for change to .me 2017-02-28 18:38:49 +01:00
Kasper Rynning-Tønnesen
d67d85781b changed from .no to .me 2017-02-28 18:37:03 +01:00
Kasper Rynning-Tønnesen
0756da0293 Changed name to zoff instead of zöff 2017-02-28 18:35:51 +01:00
Kasper Rynning-Tønnesen
815c757367 Removed truncate on last commit 2017-02-24 16:50:22 +01:00
Kasper Rynning-Tønnesen
157cb80c93 Fixed issue with client trying to destroy fireplace when it already was destroyed 2017-02-24 16:43:31 +01:00
Kasper Rynning-Tønnesen
7053132cfc Removing fireplace on channel exit 2017-02-24 12:49:32 +01:00
Kasper Rynning-Tønnesen
9d6022a0b2 Forgot to remove fireplace on channel-change.. 2017-02-24 12:45:59 +01:00
Kasper Rynning-Tønnesen
6e71c57079 Pointer events none fireplace 2017-02-24 12:43:12 +01:00
Kasper Rynning-Tønnesen
e13aee068e Clearing search on adding fireplace 2017-02-24 12:33:04 +01:00
Kasper Rynning-Tønnesen
cbc2a26eac Added 'hidden' fireplace player 2017-02-24 12:29:43 +01:00
Kasper Rynning-Tønnesen
7ea5f6e81c Updated latest-commit to show from all repos 2017-02-23 19:49:35 +01:00
Kasper Rynning-Tønnesen
4f1372c38c Moved footer around a bit 2017-02-23 19:40:51 +01:00
Kasper Rynning-Tønnesen
6348f0bec8 Removed all rights reserved, it looked stupid 2017-02-23 14:36:24 +01:00
Kasper Rynning-Tønnesen
afbea29b36 Fixed issue with duration not being added 2017-02-23 14:17:43 +01:00
Kasper Rynning-Tønnesen
7f23474b6d Removing toasts when new toasts appear, and added a small fix for w3cvalidator 2017-02-22 22:55:30 +01:00
Kasper Rynning-Tønnesen
4efa995599 Using vector instead of lowres image 2017-02-22 21:36:08 +01:00
Kasper Rynning-Tønnesen
7774626ec3 Fixed issue with showing removebutton 2017-02-22 14:34:45 +01:00
Kasper Rynning-Tønnesen
14939ae97b Fixed issue with not 'skipping' to right position 2017-02-22 14:32:35 +01:00
Kasper Rynning-Tønnesen
30757fa0ec Removed some logs 2017-02-22 12:37:02 +01:00
Kasper Rynning-Tønnesen
c6118d50ff Merged 2017-02-22 12:34:45 +01:00
Kasper Rynning-Tønnesen
f14bfefdf4 Updated mobile-looks 2017-02-22 12:34:16 +01:00
Kasper Rynning-Tønnesen
a746cbc889 Merge pull request #158 from zoff-music/mongoose
Working mongoose version
2017-02-21 18:19:31 +01:00
Kasper Rynning-Tønnesen
87d74c0100 Working mongoose version 2017-02-21 17:07:42 +01:00
Kasper Rynning-Tønnesen
3006237805 Upper first case export 2017-02-16 23:11:00 +01:00
Kasper Rynning-Tønnesen
4d6dffc35d Fixed issue with not all songs being added on export to YouTube 2017-02-16 23:07:13 +01:00
Kasper Rynning-Tønnesen
96070e2591 Matching durations along both suggested and regular 2017-02-16 12:16:28 +01:00
Kasper Rynning-Tønnesen
efcd71cb02 Fixed padding on nav-button in channel 2017-02-15 17:01:40 +01:00
Kasper Rynning-Tønnesen
5dfa27518e Moved duration left and above ::after 2017-02-15 16:56:07 +01:00
Kasper Rynning-Tønnesen
770753e1f8 Fixed issue with player not showing up on ipad 2017-02-15 16:51:32 +01:00
Kasper Rynning-Tønnesen
aa92447e4e Update way of showing play button on android and iPhone 2017-02-15 16:45:47 +01:00
Kasper Rynning-Tønnesen
c76e765904 Fixed search 2017-02-15 15:44:45 +01:00
Kasper Rynning-Tønnesen
ab7c0ecfe8 Added style for admin-panel badges 2017-02-15 15:19:58 +01:00
Kasper Rynning-Tønnesen
131139f6af Fixed issue with no duration shown on suggested 2017-02-15 14:55:38 +01:00
Kasper Rynning-Tønnesen
b1d1b0764d Added duration to songs 2017-02-15 14:49:43 +01:00
Kasper Rynning-Tønnesen
41b14437cf Waves-effect on chat-btn 2017-02-15 13:17:54 +01:00
Kasper Rynning-Tønnesen
76166ee719 Fixed touch error on iphone/ipad 2017-02-15 12:38:44 +01:00
Kasper Rynning-Tønnesen
6b94159cce Fixed tooltip for viewers 2017-02-15 12:31:12 +01:00
Kasper Rynning-Tønnesen
db1c25c2f3 Temporary fix for autocomplete with materializeCSS 2017-02-15 12:21:12 +01:00
Kasper Rynning-Tønnesen
9d4bb0b68b More functioning 'autocomplete' 2017-02-14 21:35:59 +01:00
Kasper Rynning-Tønnesen
35a428b801 Fixed issue with hiding/showing the last video on resize 2017-02-12 17:17:32 +01:00
Kasper Rynning-Tønnesen
5ff69f557b Updated style for admin-panel 2017-02-12 15:56:26 +01:00
Kasper Rynning-Tønnesen
480b3b040d fixed issue with remove-button not hiding on switching from private mode to online-mode, and added help function in chat2 2017-02-12 15:50:25 +01:00
Kasper Rynning-Tønnesen
86d977bb74 Tooltips for private-mode 2017-02-10 16:57:19 +01:00
Kasper Rynning-Tønnesen
ca659e18e5 Description appear fix 2017-02-10 15:34:30 +01:00
Kasper Rynning-Tønnesen
1db3928c2a More delay on frontpage descriptions 2017-02-10 15:30:21 +01:00
Kasper Rynning-Tønnesen
70a301ecf5 Added chat-send button 2017-02-10 15:17:11 +01:00
Kasper Rynning-Tønnesen
4047cce1cd Updating tabs 2017-02-10 12:18:47 +01:00
Kasper Rynning-Tønnesen
4a3cc246dc More descriptive about how many messages have appeared 2017-02-10 11:27:27 +01:00
Kasper Rynning-Tønnesen
0ccdda4815 Charactercount now dynamic 2017-02-09 18:41:52 +01:00
Kasper Rynning-Tønnesen
4eec51e271 Added lengthcounter to description 2017-02-09 18:38:20 +01:00
Kasper Rynning-Tønnesen
88d0eb2ef6 Fixed error with label for inputfield not working as intended on mobile 2017-02-09 18:31:49 +01:00
Kasper Rynning-Tønnesen
e264c18b7c Not showing descriptions on mobile 2017-02-09 17:34:38 +01:00
Kasper Rynning-Tønnesen
d0b6553251 Improved performance for showing searchloader 2017-02-09 15:24:33 +01:00
Kasper Rynning-Tønnesen
9b7a8a00e3 White loader on channel-search 2017-02-09 15:16:08 +01:00
Kasper Rynning-Tønnesen
c4afbfb2ed updated info-icon 2017-02-09 15:11:13 +01:00
Kasper Rynning-Tønnesen
5549434132 Improved frontpage descriptions 2017-02-09 14:40:17 +01:00
Kasper Rynning-Tønnesen
53b4bb81cb Better autocomplete for channelsearch + descriptions on frontpage 2017-02-09 14:17:59 +01:00
Kasper Rynning-Tønnesen
f2ca6da200 Material icons on embeded also 2017-02-08 15:26:49 +01:00
Kasper Rynning-Tønnesen
350ab85143 Updated embedded version 2017-02-08 15:25:27 +01:00
Kasper Rynning-Tønnesen
82a3a42c07 Added default description text 2017-02-08 13:27:42 +01:00
Kasper Rynning-Tønnesen
26be5df1e9 Added max width and max-height for picture 2017-02-08 13:26:24 +01:00
Kasper Rynning-Tønnesen
cc61d70218 Added descriptions and thumbnails, and fixed issue with pagination on add song 2017-02-08 13:18:19 +01:00
Kasper Rynning-Tønnesen
4eb3ac6f10 Added two classes 2017-02-07 14:34:02 +01:00
Kasper Rynning-Tønnesen
132aeb3e5c Added style for admin-site 2017-02-07 13:12:05 +01:00
Kasper Rynning-Tønnesen
e460ed34c2 Not submitting password if no password on channel 2017-02-07 12:16:23 +01:00
Kasper Rynning-Tønnesen
40cb7d5597 Music category on spotify import 2017-02-07 08:56:58 +01:00
Kasper Rynning-Tønnesen
970709d2ef pagination buttons 2017-02-06 13:19:32 +01:00
Kasper Rynning-Tønnesen
0fa7ec8cea Updated help section on channel 2017-02-02 14:29:41 +01:00
Kasper Rynning-Tønnesen
1649756f29 Merge pull request #157 from zoff-music/header_same
More similar header on mobile
2017-02-01 23:21:41 +01:00
Kasper Rynning-Tønnesen
9a52e5f7dd More similar header on mobile 2017-02-01 23:21:10 +01:00
Kasper Rynning-Tønnesen
3b3a984689 Styled volumeslider on mobileremote to match other 2017-02-01 21:18:27 +01:00
Kasper Rynning-Tønnesen
ab2a1b0942 More material style for volumeslider 2017-02-01 15:53:45 +01:00
Kasper Rynning-Tønnesen
01e1cefc70 More material volumeslider, and new order of hiding for the the pagination-buttons 2017-02-01 15:43:57 +01:00
Kasper Rynning-Tønnesen
3dc7a89718 Changed color of bar 2017-02-01 14:39:10 +01:00
Kasper Rynning-Tønnesen
cf3289048a Changed modals 2017-02-01 13:34:47 +01:00
Kasper Rynning-Tønnesen
857c39e872 Updated socket.io to 1.7.2 2017-02-01 12:41:18 +01:00
Kasper Rynning-Tønnesen
0ca90f223e More mobilecheck 2017-02-01 12:25:28 +01:00
Kasper Rynning-Tønnesen
d6e90896ec More channels on frontpage 2017-01-31 18:24:02 +01:00
Kasper Rynning-Tønnesen
470064500c Transitionssss 2017-01-31 16:33:38 +01:00
Kasper Rynning-Tønnesen
f7f2d3252a Overflow hidden on card 2017-01-31 10:14:55 +01:00
Kasper Rynning-Tønnesen
dd7ac82527 Pin position 2017-01-30 11:40:56 +01:00
Kasper Rynning-Tønnesen
d09a05fc5f Using boolean to display chromecast button 2017-01-30 11:35:23 +01:00
Kasper Rynning-Tønnesen
581b1eea4d Fixing issues with chromecastbutton 2017-01-28 19:52:58 +01:00
Kasper Rynning-Tønnesen
1bcf63f84e Updated to dynamic tooltips 2017-01-28 19:50:20 +01:00
Kasper Rynning-Tønnesen
def2846e97 Changed way of backdrop rotation 2017-01-28 19:41:13 +01:00
Kasper Rynning-Tønnesen
6563f0c09f Fixed casesensitive issue with pagenumber 2017-01-28 18:25:08 +01:00
Kasper Rynning-Tønnesen
ce50a53d33 Merge pull request #156 from zoff-music/materialv098
Updated materialize to v0.98 and made changes accordingly
2017-01-28 18:17:57 +01:00
Kasper Rynning-Tønnesen
3d4ed9b66c Updated materialize to v0.98 and made changes accordingly
- Made improvements to how the remotecontroller on mobile looks
- Added thumbnails some places
- Started using googles new material font because of materializecss
2017-01-28 18:16:57 +01:00
Kasper Rynning-Tønnesen
da45f27cd1 Showing number of viewers no matter how many there are 2017-01-28 13:17:57 +01:00
Kasper Rynning-Tønnesen
75a713dfbb Changed way viewers are showed 2017-01-28 13:12:12 +01:00
Kasper Rynning-Tønnesen
2f8e2f285b Made minor improvements to connection_options 2017-01-27 23:39:02 +01:00
Kasper Rynning-Tønnesen
303849ea43 Fixed issue on cast image/title 2017-01-27 19:41:58 +01:00
Kasper Rynning-Tønnesen
2fbdf66783 Fixed isse when disconnecting chromecast on private modde 2017-01-27 18:28:34 +01:00
Kasper Rynning-Tønnesen
ee34c88276 Chromcast listener 2017-01-27 15:41:38 +01:00
Kasper Rynning-Tønnesen
a4a06838c2 Chromecast next private fix 2017-01-27 15:33:38 +01:00
Kasper Rynning-Tønnesen
156d3e8c50 Merged 2017-01-27 11:13:50 +01:00
Kasper Rynning-Tønnesen
84aa951149 Votes and shuffled lists remain the same if the user navigates from a frontpage, and back to the same list in private mode 2017-01-27 11:11:47 +01:00
Kasper Rynning-Tønnesen
7641ba0fa8 Update README.md 2017-01-26 22:25:10 +01:00
Kasper Rynning-Tønnesen
5953b4a538 Fixed positioning of frontpage .mega-class 2017-01-26 21:45:46 +01:00
Kasper Rynning-Tønnesen
948b4a6692 Positioning of header-buttons 2017-01-26 21:40:44 +01:00
Kasper Rynning-Tønnesen
d1cb1bfe98 Removed a unnecessary log 2017-01-26 21:07:08 +01:00
Kasper Rynning-Tønnesen
a06ecd9d17 Private mode not picking up shuffling from others 2017-01-26 16:53:15 +01:00
Kasper Rynning-Tønnesen
0f86a3197e Fixing list not updating on change in private mode 2017-01-26 15:51:01 +01:00
Kasper Rynning-Tønnesen
cff94a3a60 Fixed missing break in switch-case 2017-01-26 15:15:07 +01:00
Kasper Rynning-Tønnesen
09c75ed8b6 Fixed issue on serverrestart, stocking over the playlist regardless if the player is in private mode or not 2017-01-26 14:59:42 +01:00
Kasper Rynning-Tønnesen
c72c2c9a3a Limiting number of lists in inputfield to only those with more than 5 songs, and accessed within the last 7 days 2017-01-26 14:51:47 +01:00
Kasper Rynning-Tønnesen
d665b59c7a Added shufflefunction for when in offline 2017-01-26 13:34:46 +01:00
Kasper Rynning-Tønnesen
0790002b6a Updated header for remote controll 2017-01-26 13:24:20 +01:00
Kasper Rynning-Tønnesen
f54119b8da Removed some excessive buttons in header 2017-01-26 13:22:20 +01:00
Kasper Rynning-Tønnesen
4508099fb5 Fixed wrapper height, and issues with empty channel 2017-01-26 12:35:50 +01:00
Kasper Rynning-Tønnesen
31d661acd1 Fixed player not starting in private mode when empty playlist, and added import/export to mobile 2017-01-26 11:38:40 +01:00
Kasper Rynning-Tønnesen
eeb99f2c7b Hiding chromecast button on desktop browsers thats not chrome, but showing on mobile 2017-01-25 21:56:27 +01:00
Kasper Rynning-Tønnesen
3f8c8380e4 Hiding chromecast button from browsers that isnt chrome(ium) 2017-01-25 21:43:44 +01:00
Kasper Rynning-Tønnesen
885e9e15ed When in private mode, all votes are reset 2017-01-25 19:51:31 +01:00
Kasper Rynning-Tønnesen
68a70a5687 Showing votes again, to easier understand how the songs behave 2017-01-25 19:44:02 +01:00
Kasper Rynning-Tønnesen
6459c3543c Fixed sizing and positioning of voting thumb 2017-01-25 19:37:59 +01:00
Kasper Rynning-Tønnesen
ee9d42da37 Added missing variables in embed 2017-01-25 19:18:14 +01:00
Kasper Rynning-Tønnesen
01d4a38353 Updated embedded player to work with the new offline functions 2017-01-25 19:17:24 +01:00
Kasper Rynning-Tønnesen
02b946448f Voting now functioning better in private mode 2017-01-25 18:14:44 +01:00
Kasper Rynning-Tønnesen
2697315ed9 Fixed issue with adding song when logged in on private 2017-01-25 16:50:41 +01:00
Kasper Rynning-Tønnesen
c35ef1bc96 Can now add songs in private mode even if its admin-locked 2017-01-25 16:06:53 +01:00
Kasper Rynning-Tønnesen
3633df97cd Changed icon of private mode 2017-01-25 15:28:31 +01:00
Kasper Rynning-Tønnesen
ee9f8831c3 Changed offline-mode name to private-mode 2017-01-25 15:24:58 +01:00
Kasper Rynning-Tønnesen
49bcec5fb7 Update README.md 2017-01-25 15:18:01 +01:00
Kasper Rynning-Tønnesen
a40921668c Added info about offline to the help modal 2017-01-25 14:13:17 +01:00
Kasper Rynning-Tønnesen
d23ee61082 Voting now only affects online players 2017-01-25 14:09:33 +01:00
Kasper Rynning-Tønnesen
2b3bf29ee6 Merge pull request #155 from zoff-music/localplay
Now fetching full playlist fresh on changing back to online-mode
2017-01-25 14:06:19 +01:00
Kasper Rynning-Tønnesen
fa9abe7b63 Now fetching full playlist fresh on changing back to online-mode 2017-01-25 14:05:09 +01:00
Kasper Rynning-Tønnesen
9b2772ccb9 Merge pull request #154 from zoff-music/localplay
Added functionality for offline playing
2017-01-25 13:58:42 +01:00
Kasper Rynning-Tønnesen
1305dd3072 Added functionality for offline playing 2017-01-25 13:57:24 +01:00
Kasper Rynning-Tønnesen
275d1a95b2 Updated ç year 2017-01-24 14:16:23 +01:00
Kasper Rynning-Tønnesen
870e805743 Fixed width of titlebar of songs 2017-01-24 14:09:12 +01:00
Kasper Rynning-Tønnesen
9d21e059f7 Improving showing/hiding of chromecastbutton 2017-01-24 12:15:53 +01:00
Kasper Rynning-Tønnesen
e515915ec8 Updated chromecast sender
- Trying to get YouTube thumbnail to show up in the notificationbar
 - Trying to get YouTube title to show up in the notificationbar
2017-01-24 11:54:12 +01:00
Kasper Rynning-Tønnesen
8561b715e4 Hiding frontpage player on close 2017-01-24 10:35:36 +01:00
Kasper Rynning-Tønnesen
f8e8d0c99b Changing background-color on mobile 2017-01-23 14:18:45 +01:00
Kasper Rynning-Tønnesen
7e650d73f8 Truncating playlist-suggested-chat tabs 2017-01-23 14:01:37 +01:00
Kasper Rynning-Tønnesen
06223bcef1 Spotify export improvements 2017-01-23 13:45:42 +01:00
Kasper Rynning-Tønnesen
91f15abc11 Improved exporting to spotify 2017-01-23 13:41:33 +01:00
Kasper Rynning-Tønnesen
211e29bcc4 Changed nochan to frontpage, and made changes accordingly 2017-01-23 12:26:05 +01:00
Kasper Rynning-Tønnesen
aa7ed10522 Trying to get iphone playbutton to work 2017-01-22 17:35:08 +01:00
Kasper Rynning-Tønnesen
0c1353b660 Fixed issue with song dissapearing on voting, and added player to iphone 2017-01-22 17:25:06 +01:00
Kasper Rynning-Tønnesen
5ecb4f36bc Fixed issue with chromecast button not showing up 2017-01-20 20:45:25 +01:00
Kasper Rynning-Tønnesen
73759e1200 Updated way of playbutton is showed on mobile 2017-01-20 10:39:49 +01:00
Kasper Rynning-Tønnesen
a5703d33d3 Fixed error where mobile couldn't skip videos if no video was playing 2017-01-19 18:27:24 +01:00
Kasper Rynning-Tønnesen
b920b6d100 Multiplying with correct can_fit number 2017-01-19 18:10:14 +01:00
Kasper Rynning-Tønnesen
9bba760d9b Taking the floor of a division 2017-01-19 18:08:00 +01:00
Kasper Rynning-Tønnesen
02938c7b01 Trying to push again 2017-01-19 18:05:13 +01:00
Kasper Rynning-Tønnesen
c4b016366b Added a search in list function on CTRL/cmd + F 2017-01-19 18:00:48 +01:00
Kasper Rynning-Tønnesen
8bb9f88037 Only using secure cookies if https protocol 2017-01-19 16:52:10 +01:00
Kasper Rynning-Tønnesen
107092277e Changed timing of when snow appears 2017-01-19 16:45:29 +01:00
Kasper Rynning-Tønnesen
6274ba6d5b Changed width of results in resultlist 2017-01-13 15:36:24 +01:00
Kasper Rynning-Tønnesen
b4c2d75f00 Updated the way dynamic content is added 2017-01-13 12:38:32 +01:00
Kasper Rynning-Tønnesen
1c65b6d035 Ignoring studio version also 2017-01-07 17:42:24 +01:00
Kasper Rynning-Tønnesen
70ff818b43 Logging retry-after 2017-01-07 17:37:37 +01:00
Kasper Rynning-Tønnesen
d66c07bd46 Fixed error with searchSpotify not defined 2017-01-07 17:35:53 +01:00
Kasper Rynning-Tønnesen
7f1d3dd51c Rule for dot at the end 2017-01-07 17:32:36 +01:00
Kasper Rynning-Tønnesen
cbf73d3d7c Small change with dashes 2017-01-07 17:28:55 +01:00
Kasper Rynning-Tønnesen
1b802a1d87 Trying to add retry-after field 2017-01-07 17:25:20 +01:00
Kasper Rynning-Tønnesen
a63f74d9ac Added exporting to spotify from zöff playlist 2017-01-07 17:02:01 +01:00
Kasper Rynning-Tønnesen
62390e168c Updated YouTube sizing 2017-01-07 12:31:26 +01:00
Kasper Rynning-Tønnesen
bb8dbafa9c Changing ports 2017-01-05 14:45:56 +01:00
Kasper Rynning-Tønnesen
4a4184ae3a Hiding chromecast button if no chromecast 2016-12-25 01:15:55 +01:00
Kasper Rynning-Tønnesen
0f9c1f8d17 Reimplemented resizable 2016-12-15 16:07:29 +01:00
Kasper Rynning-Tønnesen
06b96f827e Updated resiable and width of overlay 2016-12-15 16:06:35 +01:00
Kasper Rynning-Tønnesen
a7e16c7680 Updated mobile caster 2016-12-15 13:55:52 +01:00
Kasper Rynning-Tønnesen
171c01f1f3 Fixed error with script being wrongly placed 2016-12-14 19:31:32 +01:00
Kasper Rynning-Tønnesen
f9012e75e8 Updated width of overlay 2016-12-14 19:20:11 +01:00
Kasper Rynning-Tønnesen
813401f481 Small mobile fix? 2016-12-14 19:14:19 +01:00
Kasper Rynning-Tønnesen
7a5b273cb3 Updated chromecast sender 2016-12-14 19:11:58 +01:00
Kasper Rynning-Tønnesen
1306b9eb0e Merged 2016-12-14 17:01:27 +01:00
Kasper Rynning-Tønnesen
58d0cbc7fa Updated slidebars on the sidebar 2016-12-14 17:00:42 +01:00
Kasper Rynning-Tønnesen
198578a5c9 Delete bot.php 2016-12-12 18:51:41 +01:00
Kasper Rynning-Tønnesen
8e11bc30a2 Delete update_lists.php 2016-12-12 18:51:33 +01:00
Kasper Rynning-Tønnesen
66570a6813 Updated to seekto if currentduration is wrong 2016-12-12 17:23:38 +01:00
Kasper Rynning-Tønnesen
ccf6f7cc8a Fixed error with embedded player linking 2016-12-12 17:01:06 +01:00
Kasper Rynning-Tønnesen
e0993e5ec9 Reverted 2016-12-12 16:42:47 +01:00
Kasper Rynning-Tønnesen
26f88721c3 Updated logo 2016-12-12 16:40:29 +01:00
Kasper Rynning-Tønnesen
4331082903 Updating imageblob 2016-12-12 16:22:50 +01:00
Kasper Rynning-Tønnesen
1b9f80072c More rules 2016-12-12 16:14:52 +01:00
Kasper Rynning-Tønnesen
6e9e8eb544 not so full path 2016-12-12 16:13:29 +01:00
Kasper Rynning-Tønnesen
982f81bdb2 Trying to fix remote error 2016-12-12 16:12:48 +01:00
Kasper Rynning-Tønnesen
74761dcc07 Updated mailscript 2016-12-12 16:08:28 +01:00
Kasper Rynning-Tønnesen
c5d9b2f0d1 Renaming and fixing some filestructure 2016-12-12 16:07:06 +01:00
Kasper Rynning-Tønnesen
d35a6599c2 Destroying resizable 2016-12-11 19:36:22 +01:00
Kasper Rynning-Tønnesen
b3908781c3 Merge branch 'master' of github.com:zoff-music/Zoff 2016-12-11 17:31:18 +01:00
Kasper Rynning-Tønnesen
62a7a91f9b Mobile fix for playbutton 2016-12-11 17:31:02 +01:00
Kasper Rynning-Tønnesen
50ce96f4f2 Mobile fix for playbutton 2016-12-11 17:27:56 +01:00
Kasper Rynning-Tønnesen
9fd0d5e786 Max res 2016-12-11 01:05:50 +01:00
Kasper Rynning-Tønnesen
ee06ff94b7 Fixed pausing on chromecast 2016-12-11 00:46:56 +01:00
Kasper Rynning-Tønnesen
4c3d8246ef Fixing position of logo 2016-12-10 21:12:06 +01:00
Kasper Rynning-Tønnesen
a372494f55 Updated chromecast view, volume now changes volume on chromecast 2016-12-10 21:08:43 +01:00
Kasper Rynning-Tønnesen
dd6fdc493c Updated so that errors on video now skips on chromecast also 2016-12-10 00:09:49 +01:00
Kasper Rynning-Tønnesen
236e813e89 Trying mailfix 2016-12-09 16:28:19 +01:00
Kasper Rynning-Tønnesen
5fc125b117 Added spotify and YouTube logo for import-buttons, and fixed so the spinning thingy moves when exporting playlist 2016-12-09 14:40:58 +01:00
Kasper Rynning-Tønnesen
3e68196cf1 Fixed embedded player a bit 2016-11-30 17:30:22 +01:00
Kasper Rynning-Tønnesen
3cd0018a2d Updated embedding css 2016-11-30 17:15:31 +01:00
Kasper Rynning-Tønnesen
91af9ad701 Now able to change color of list on embed 2016-11-30 17:12:27 +01:00
Kasper Rynning-Tønnesen
ce35ec42e3 Font-sizing suggested 2016-11-30 15:44:53 +01:00
Kasper Rynning-Tønnesen
1d1d68fb6f Suggested height fix 2016-11-30 15:43:13 +01:00
Kasper Rynning-Tønnesen
a87bbe778f Clickthrough only on mobile 2016-11-30 15:16:17 +01:00
Kasper Rynning-Tønnesen
b442645dd1 clickthrough 2016-11-30 14:42:10 +01:00
Kasper Rynning-Tønnesen
5c577272f2 Fixed placing of border on delete button 2016-11-30 14:19:20 +01:00
Kasper Rynning-Tønnesen
28306908c2 Updated shufflehandling and styling of deletebutton 2016-11-30 14:14:47 +01:00
Kasper Rynning-Tønnesen
fb89ac2fe8 Updated styling of vote-images 2016-11-30 14:00:28 +01:00
Kasper Rynning-Tønnesen
57c8f72e65 Fixed error with pagination on songchange 2016-11-30 13:17:36 +01:00
Kasper Rynning-Tønnesen
ce5f9bc086 Moved receiver to other repository 2016-11-23 15:36:00 +01:00
Kasper Rynning-Tønnesen
ccfea3fa5d Safari fix for channelname 2016-11-23 15:22:32 +01:00
Kasper Rynning-Tønnesen
05b28db083 Updated listener to look more for chromecastAvailable 2016-11-22 18:58:10 +01:00
Kasper Rynning-Tønnesen
f866aa8a48 updated embed.min.js 2016-11-22 18:23:25 +01:00
Kasper Rynning-Tønnesen
104aa85b65 Forgot embed cant use localhost.. 2016-11-22 18:22:26 +01:00
Kasper Rynning-Tønnesen
4592f4d7f9 Updated embedded player, and fixes for chromecast on mobile 2016-11-22 18:20:55 +01:00
Kasper Rynning-Tønnesen
db2887c610 Added pointer events none to snow 2016-11-22 17:32:04 +01:00
Kasper Rynning-Tønnesen
66dde0c2e0 Updated snowfall 2016-11-22 17:29:55 +01:00
Kasper Rynning-Tønnesen
35bc7f5177 Added index and nofollow on nochan.php only. Doesn't allow indexing or following on index.php 2016-11-22 14:39:51 +01:00
Kasper Rynning-Tønnesen
ec6f4ae436 Added facebook app_id 2016-11-22 14:34:04 +01:00
Kasper Rynning-Tønnesen
da9565bf63 Using codepen https://codepen.io/NickyCDK/pen/AIonk for snow on frontpage 2016-11-22 11:15:15 +01:00
Kasper Rynning-Tønnesen
1a968715d9 Added images locally 2016-11-22 11:14:30 +01:00
Kasper Rynning-Tønnesen
4682d7dca6 Better snowfall 2016-11-22 11:09:30 +01:00
Kasper Rynning-Tønnesen
fb07076d25 Winter 2016-11-22 11:04:04 +01:00
Kasper Rynning-Tønnesen
65375765bc Resizing now changes to first page if there are too many elements 2016-11-22 10:21:01 +01:00
Kasper Rynning-Tønnesen
bbb0d6b7a6 Trying fix for mobile 2016-11-22 10:17:51 +01:00
Kasper Rynning-Tønnesen
2e34170a82 Removed notifications from mobile 2016-11-21 19:22:23 +01:00
Kasper Rynning-Tønnesen
dd7e9ecd7a Trying to fix errors with mobile chromecasting 2016-11-21 19:09:34 +01:00
Kasper Rynning-Tønnesen
2377031c91 Fixing first page button being hidden on wrong instances 2016-11-21 16:00:52 +01:00
Kasper Rynning-Tønnesen
7192e34bbe Updated positioning of zöff logo on receiver 2016-11-21 14:54:10 +01:00
Kasper Rynning-Tønnesen
9d3cc12724 Disabled doubleclick fullscreen to prevent player being stuck in fullscreen 2016-11-21 13:02:41 +01:00
Kasper Rynning-Tønnesen
8ac79898b8 Secure cookies now in use 2016-11-21 12:55:04 +01:00
Kasper Rynning-Tønnesen
b1a41ca74a Added fix for frontpage listener not being initiated 2016-11-21 12:46:05 +01:00
Kasper Rynning-Tønnesen
8bb0f3f886 Better cursor on resizable col 2016-11-21 10:30:24 +01:00
Kasper Rynning-Tønnesen
bfbba70685 Fix nav-error 2016-11-21 09:45:17 +01:00
Kasper Rynning-Tønnesen
5536fbda96 Added first/last page buttons 2016-11-21 09:41:41 +01:00
Kasper Rynning-Tønnesen
3efc7109f5 Removed loop 2016-11-20 15:37:56 +01:00
Kasper Rynning-Tønnesen
fe1fe6f4a8 Updated some sizing 2016-11-20 15:29:34 +01:00
Kasper Rynning-Tønnesen
6d52617fab Fixed error with wrong positioning on newly voted song 2016-11-20 15:12:26 +01:00
Kasper Rynning-Tønnesen
fbb03c0e65 Fixed error with wrong song being shown 2016-11-20 15:08:08 +01:00
Kasper Rynning-Tønnesen
3c9b29c29e Changed placing of deletebutton 2016-11-20 14:58:36 +01:00
Kasper Rynning-Tønnesen
7e950ea734 Trying some new sizing of playlist, removing scroll form playlist, only pagination 2016-11-20 14:55:51 +01:00
Kasper Rynning-Tønnesen
d52c169873 Logging some more 2016-11-20 12:52:00 +01:00
Kasper Rynning-Tønnesen
42ce8a4067 Case sensitivity 2016-11-20 12:43:47 +01:00
Kasper Rynning-Tønnesen
64fc093bbc Added some logs to try and find out whats wrong with the frontpage 2016-11-20 12:42:44 +01:00
Kasper Rynning-Tønnesen
be007299d5 Updated search to remove lazyload 2016-11-19 15:12:25 +01:00
Kasper Rynning-Tønnesen
c4bd1f31f7 Merge branch 'master' of github.com:zoff-music/Zoff 2016-11-19 12:21:29 +01:00
Kasper Rynning-Tønnesen
c09930e079 Closing player on frontpage now disconnects chromecast if chromecast is connected 2016-11-19 12:20:56 +01:00
Kasper Rynning-Tønnesen
1220947601 Update README.md 2016-11-18 22:15:05 +01:00
Kasper Rynning-Tønnesen
8e738a4500 Fixed issue with not moving duration chromecast 2016-11-18 22:07:06 +01:00
Kasper Rynning-Tønnesen
fc27388534 forgot videoId of chromecast on end 2016-11-18 21:58:01 +01:00
Kasper Rynning-Tønnesen
3e5eed4af5 Trying delayed start event 2016-11-18 21:34:39 +01:00
Kasper Rynning-Tønnesen
e0a1045252 ABORTING LOOP 2016-11-18 21:31:50 +01:00
Kasper Rynning-Tønnesen
ffc977157c Chromecast app working 2016-11-18 21:29:52 +01:00
Kasper Rynning-Tønnesen
0ccf943934 added mute/unmute functionality 2016-11-18 21:26:16 +01:00
Kasper Rynning-Tønnesen
4eaedfe621 Forgot to added type 2016-11-18 20:44:01 +01:00
Kasper Rynning-Tønnesen
4c90e62569 Button positioning 2016-11-18 20:41:30 +01:00
Kasper Rynning-Tønnesen
4a53bc4a85 Some pointers and buttons 2016-11-18 20:36:14 +01:00
Kasper Rynning-Tønnesen
450ad44550 Fixed deletionthingy 2016-11-18 20:31:55 +01:00
Kasper Rynning-Tønnesen
73bf5feec8 I AM A STUPID MAN 2016-11-18 20:24:45 +01:00
Kasper Rynning-Tønnesen
48f14c644e Stopping a range of functions 2016-11-18 20:18:36 +01:00
Kasper Rynning-Tønnesen
05a24e63ba Fixing for more seeking/loading 2016-11-18 20:13:37 +01:00
Kasper Rynning-Tønnesen
88dafeb561 I am a stupid person 2016-11-18 20:09:05 +01:00
Kasper Rynning-Tønnesen
b648316b51 Stringifyyy 2016-11-18 20:02:38 +01:00
Kasper Rynning-Tønnesen
9aebd4445c Fix on json 2016-11-18 19:53:14 +01:00
Kasper Rynning-Tønnesen
ced8db7de1 Flexing 2016-11-18 19:43:51 +01:00
Kasper Rynning-Tønnesen
692b0361c6 Showing next song 2016-11-18 19:39:17 +01:00
Kasper Rynning-Tønnesen
2080de37fe Updated a lot 2016-11-18 19:37:11 +01:00
Kasper Rynning-Tønnesen
97ad0e3d2b Listener now prints 2016-11-18 19:22:25 +01:00
Kasper Rynning-Tønnesen
4261eee360 So much pushing and pulling.. 2016-11-18 19:21:44 +01:00
Kasper Rynning-Tønnesen
47d68814dc Stupid thing 2016-11-18 19:17:51 +01:00
Kasper Rynning-Tønnesen
066e6dac81 Logging 2016-11-18 19:16:11 +01:00
Kasper Rynning-Tønnesen
7606fa5810 Data not json object.. 2016-11-18 19:15:05 +01:00
Kasper Rynning-Tønnesen
0d3ac5c6d6 Updated to listener even though api says listner 2016-11-18 19:13:04 +01:00
Kasper Rynning-Tønnesen
f88142abc1 Updated some logging 2016-11-18 19:11:14 +01:00
Kasper Rynning-Tønnesen
673f9a7a0e Now sending next video to chromecast 2016-11-18 15:26:58 +01:00
Kasper Rynning-Tønnesen
37ee42fab5 removed some logging functions, and made lsitening on chromecast better 2016-11-18 15:13:53 +01:00
Kasper Rynning-Tønnesen
071744440d Updated receiver to work more properly with the current player, and added a picture 2016-11-18 15:07:58 +01:00
Kasper Rynning-Tønnesen
8854f1d687 Working? 2016-11-18 13:19:13 +01:00
Kasper Rynning-Tønnesen
5206144d06 Receiver 2016-11-18 13:16:53 +01:00
Kasper Rynning-Tønnesen
f4c3a4a321 Receiver 2016-11-18 13:14:29 +01:00
Kasper Rynning-Tønnesen
e74e188bd9 Update to get videoId 2016-11-18 13:10:27 +01:00
Kasper Rynning-Tønnesen
40b552dc49 Updating receiver 2016-11-18 13:06:29 +01:00
Kasper Rynning-Tønnesen
a4a41f1e59 receiver 2016-11-18 12:57:28 +01:00
Kasper Rynning-Tønnesen
e6d7404660 Namespace higher up 2016-11-18 12:56:15 +01:00
Kasper Rynning-Tønnesen
fece31e31a More updates receiver 2016-11-18 12:54:22 +01:00
Kasper Rynning-Tønnesen
c12db4c3bf Upading receiver 2016-11-18 12:22:43 +01:00
Kasper Rynning-Tønnesen
342268c399 Reverting to old version of receiver 2016-11-18 11:06:31 +01:00
Kasper Rynning-Tønnesen
6a5350e648 fixing error with remote 2016-11-18 10:57:47 +01:00
Kasper Rynning-Tønnesen
9d9f7f3d4d Starting add of custom receiver app 2016-11-18 10:42:55 +01:00
Kasper Rynning-Tønnesen
8d7f987ccb Sizing and position of castbutton mobile 2016-11-18 00:17:12 +01:00
Kasper Rynning-Tønnesen
4cac15cf97 Font size for castbutton on mobile 2016-11-18 00:15:18 +01:00
Kasper Rynning-Tønnesen
6e7c4caa62 Added chromecastbutton 2016-11-17 23:29:48 +01:00
Kasper Rynning-Tønnesen
b43bf1664d Fixed height of videoplayer 2016-11-17 20:53:35 +01:00
Kasper Rynning-Tønnesen
524b8ada86 Moved close button outside of trigger of opening channel-settings 2016-11-17 20:50:10 +01:00
Kasper Rynning-Tønnesen
d5c9008d3e Fixed header issues 2016-11-17 20:29:38 +01:00
Kasper Rynning-Tønnesen
6ceb241170 Added robots.txt and robots metatag 2016-11-17 20:27:52 +01:00
Kasper Rynning-Tønnesen
8037fdd233 Trying to fix some w3c validator issues 2016-11-17 20:20:24 +01:00
Kasper Rynning-Tønnesen
2c4ca881be Fixed error when logging out and in, and made the next/prev buttons more button'y 2016-11-17 19:33:02 +01:00
Kasper Rynning-Tønnesen
3629d82499 Preventing default action on modal-close 2016-11-17 18:04:18 +01:00
Kasper Rynning-Tønnesen
d3bd4c5db9 Centeraligning pagebuttons on embed 2016-11-17 16:33:53 +01:00
Kasper Rynning-Tønnesen
b44ef845db Removed lazyload completely, and updated embedding 2016-11-17 16:31:26 +01:00
Kasper Rynning-Tønnesen
8c218d1086 Hopefully fixed error with 'reloading every click' 2016-11-17 15:58:52 +01:00
Kasper Rynning-Tønnesen
90f8a8f1a6 Added 'pagination' emulation. Hopefully this will fix some of the major lag caused by the bigger lists 2016-11-17 15:54:48 +01:00
Kasper Rynning-Tønnesen
31d6da3c85 placeholder fix 2016-11-09 23:30:11 +01:00
Kasper Rynning-Tønnesen
0a94c3079f Updated frontpage to fix backdrop issue 2016-11-09 23:26:10 +01:00
Kasper Rynning-Tønnesen
36933f1bab drag target no pointer events
- users can now drag the scrollbar
2016-10-14 12:27:39 +02:00
Kasper Rynning-Tønnesen
2355bc10bc Fixed how the channels are sent from the server 2016-09-23 12:31:25 +02:00
Kasper Rynning-Tønnesen
eebd1113c3 Fixed some http/https issues 2016-09-23 12:06:08 +02:00
Kasper Rynning-Tønnesen
814252375a Removed spotify and fixed error with panel 2016-09-09 15:56:48 +02:00
Kasper Rynning-Tønnesen
38817162b3 Forgot to add callback-files 2016-09-06 14:49:51 +02:00
Kasper Rynning-Tønnesen
9a291c065c Fixed user-suggested songs 2016-09-05 14:51:59 +02:00
Kasper Rynning-Tønnesen
1f25aaedfc Fixed error with adding new song 2016-09-05 14:31:16 +02:00
Kasper Rynning-Tønnesen
c6d6270c4a Added export to youtube and improved importing from YouTube 2016-09-05 13:36:21 +02:00
Kasper Rynning-Tønnesen
d5acdb2161 Improved look of all messages being sent back and forth 2016-09-02 21:45:19 +02:00
Kasper Rynning-Tønnesen
f3778ae260 Improved embedded version 2016-09-01 22:15:39 +02:00
Kasper Rynning-Tønnesen
5bfdd25962 Added Helper.log and error message on connection failure 2016-09-01 20:06:05 +02:00
Kasper Rynning-Tønnesen
bded7f726e Removed a simple log 2016-09-01 15:19:32 +02:00
Kasper Rynning-Tønnesen
5469c00cfa Fixed spotify import even better 2016-09-01 15:16:04 +02:00
Kasper Rynning-Tønnesen
e78937ae35 added another field to sort on, for better consistency 2016-08-31 19:17:54 +02:00
Kasper Rynning-Tønnesen
f67340dc84 Fixed error with only localhost with spotify inport 2016-08-31 15:42:02 +02:00
Kasper Rynning-Tønnesen
c9dc08fe52 Improved spotify list importing 2016-08-31 13:10:38 +02:00
Kasper Rynning-Tønnesen
d6e9278a30 Removed viewers from title of title of song 2016-08-31 12:40:29 +02:00
Kasper Rynning-Tønnesen
8b162b3069 Hopefully improved spotify import 2016-08-31 12:37:20 +02:00
Kasper Rynning-Tønnesen
febebb2b0e Fixed scrollbar disapearing on modal, and added width+height adjustment for embed, along with fixing error in position of controls of embed 2016-08-31 12:03:44 +02:00
Kasper Rynning-Tønnesen
7c8be00c9a Update spotify 2016-08-27 15:47:28 +02:00
Kasper Rynning-Tønnesen
1f5e071767 Forgot to add zoff.no to htaccessrewrite 2016-08-27 15:46:25 +02:00
Kasper Rynning-Tønnesen
93ed57e720 Improved all list importing, and added error-messages for faulty url/ids 2016-08-27 15:44:34 +02:00
Kasper Rynning-Tønnesen
a0fd178eca Improved how importing from spotify works 2016-08-27 15:34:58 +02:00
Kasper Rynning-Tønnesen
13bb52cded Added spotify import, somewhat still in beta 2016-08-26 15:48:02 +02:00
Kasper Rynning-Tønnesen
5956090c9f Fixed errors with navigating from and to a channel, and some mobile looks 2016-08-16 19:02:35 +02:00
Kasper Rynning-Tønnesen
892f00e2f4 Updated embedfile, removed unecessary font and fixed error where zöff name doesn't show up in header 2016-08-16 18:29:24 +02:00
Kasper Rynning-Tønnesen
f6b373cb79 No select 2016-08-16 13:37:09 +02:00
Kasper Rynning-Tønnesen
172ab7edc8 Forgot to update minified scripts 2016-08-16 11:19:30 +02:00
Kasper Rynning-Tønnesen
01989bc39a Updated mobile look, and fixed error where leaving channel before player initialized crashes 2016-08-16 11:17:45 +02:00
Kasper Rynning-Tønnesen
63f6e19fc0 Better working serviceworker and message to enduser 2016-08-16 10:55:37 +02:00
Kasper Rynning-Tønnesen
70576ce0c9 Updated offline site and new serivce-worker to reflect that 2016-08-15 21:53:26 +02:00
Kasper Rynning-Tønnesen
85081497aa Updated what to cache, and updated offline-page 2016-08-15 16:05:21 +02:00
Kasper Rynning-Tønnesen
3f152acc57 Updated offline page 2016-08-15 11:52:48 +02:00
Kasper Rynning-Tønnesen
436ccf88d5 Re-added serviceworker, hopefully it works 2016-08-15 11:48:13 +02:00
Kasper Rynning-Tønnesen
b96e566d61 Updated manifest.json 2016-08-15 11:37:09 +02:00
Kasper Rynning-Tønnesen
3a36fafdc6 Removed please 2016-08-13 18:51:10 +02:00
Kasper Rynning-Tønnesen
cdca1f136e Hopefully removed serviceworker completely 2016-08-13 18:45:51 +02:00
Kasper Rynning-Tønnesen
4b11cb18cf Unregistering serviceworker 2016-08-13 18:37:31 +02:00
Kasper Rynning-Tønnesen
0600486bd8 reenabling serviceworker hopefully 2016-08-13 17:49:03 +02:00
Kasper Rynning-Tønnesen
c3189d6e30 Updated and removed serviceworker. Will add again shortly 2016-08-13 17:45:05 +02:00
Kasper Rynning-Tønnesen
970395a4d7 Updated service-worker some 2016-08-13 16:10:46 +02:00
Kasper Rynning-Tønnesen
a9a02b56ba Updated how adding playlists works. 2016-08-13 13:33:17 +02:00
Kasper Rynning-Tønnesen
4359144925 Thingy 2016-08-03 10:29:19 +02:00
232 changed files with 27424 additions and 21597 deletions

17
.gitignore vendored
View File

@@ -1,3 +1,18 @@
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/public/assets/dist/callback.min.js
server/public/assets/dist/token.min.js
server/public/assets/dist/embed.min.js
server/public/assets/dist/main.min.js
server/public/assets/dist/remote.min.js
*/node_modules
node_modules/
scripts/
.DS_Store
npm-debug.log
server/npm-debug.log

View File

@@ -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

113
README.md
View File

@@ -1,17 +1,48 @@
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 based radio service, built upon the YouTube API, with integrated casting with Chromecast.
##### Config
## Install
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)
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/```.
If you have run the server before the table-structures where added, please run ```node server/apps/rewrite.js```. This will fix any crashes that occurs because of faulty document-collectionnames due to moving channel-settings to a separate collection.
Run
```
db.chat_logs.createIndex({ "createdAt": 1 }, { expireAfterSeconds: X });
db.timeout_api.createIndex({ "createdAt": 1 }, { expireAfterSeconds: Y });
db.api_links.createIndex({ "createdAt": 1 }, { expireAfterSeconds: 86400 });
```
in mongo to have chat_logs and api be deleted after X and Y seconds.
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
ff is a shared (free) YouTube based radio service, built upon the YouTube API.
Zöff is mainly a webbased service. The website uses <a href="https://nodejs.org/">NodeJS</a> with <a href="http://socket.io/">Socket.IO</a>, <a href="https://www.mongodb.org/">MongoDB</a> and PHP on the backend, with JavaScript, jQuery and <a href="http://materializecss.com/">Materialize</a> on the frontend.
Zoff is mainly a webbased service. The website uses <a href="https://nodejs.org/">NodeJS</a> with <a href="http://socket.io/">Socket.IO</a>, <a href="https://www.mongodb.org/">MongoDB</a> and express on the backend, with JavaScript and <a href="http://materializecss.com/">Materialize</a> on the frontend.
The team consists of Kasper Rynning-Tønnesen and Nicolas Almagro Tonne, and the project has been worked on since late 2014.
@@ -19,66 +50,32 @@ The team consists of Kasper Rynning-Tønnesen and Nicolas Almagro Tonne, and the
The team can be reached on <a href="mailto:contact@zoff.no?Subject=Contact%20Zoff">contact@zoff.no</a>
###Screenshots of desktop version:
### Screenshots of desktop version:
![Frontpage desktop](http://i.imgur.com/f9MoSDN.png)
![Frontpage desktop](https://puu.sh/xCI8P/bbfbdd694c.png)
![Channel desktop](http://puu.sh/ivYKz/b1b65b339c.jpg)
![Channel desktop](https://puu.sh/xCHXj/3f7d826329.png)
![Channel desktop 2](http://puu.sh/ivYVo/9036795b95.jpg)
![Channel join](https://puu.sh/zf1Ap/16587c0749.png)
![Channel search desktop](https://puu.sh/yhuVE/b50c6bbe1b.png)
### Screenshots of the mobile version:
![Frontpage mobile](http://lh5.googleusercontent.com/-_rATUkLCLH8/VUKTzZ19TqI/AAAAAAAABLc/ab9ZiJtLy4g/w330-h586-no/Screenshot_2015-04-30-22-30-43.png) ![Channel mobile](http://lh5.googleusercontent.com/-YaH8pUMzjRM/VUKTpr7ZpdI/AAAAAAAABLQ/ABOOB-1RWcw/w330-h586-no/Screenshot_2015-04-30-22-39-44.png) ![Channel mobile 2](http://lh5.googleusercontent.com/-wVKAxHBwIAI/VUKToHhHxgI/AAAAAAAABLI/RyCteTkdvDY/w330-h586-no/Screenshot_2015-04-30-22-36-00.png)
### Android exclusive screens:
<div style="text-align:center;">
<img src="http://i.imgur.com/2LMOnUe.png" alt="android1" height="600px">
<img src="http://i.imgur.com/mIOrtng.png" alt="android2" height="400px">
<img src="http://i.imgur.com/aWlEmIx.png" alt="frontpage" height="600px">
<br>
<img src="https://puu.sh/xCI6X/1aead5e1b6.png" alt="channel" height="600px">
<img src="https://puu.sh/yg5y5/2e0f202d6d.png" alt="channel search" height="600px">
</div>
### Events
Emitted events between the server and client
```
socket.emit("end", VIDEO_ID); Tells the server the song is clientside
socket.emit("pos"); Asks server where in the song it should be
socket.emit('list', CHANNEL_NAME); Tells the server the client wants the list
socket.emit("add", [VIDEO_ID, VIDEO_TITLE, sha256(PASSWORD), VIDEO_DURATION]); Sends info about a song the client wants to add
socket.emit("change_channel"); Tells the server to disconnect the user from the current channel, is used for remote controlling on the host side
socket.emit("all,chat", TEXT); Sends chat text to all chat
socket.emit("chat", TEXT); Sends chat text to channelchat
socket.emit('vote', [CHANNEL_NAME, VIDEO_ID, VOTE_TYPE, PASSWORD]); Sends info about song the user wants to vote on. If VOTE_TYPE is del, its deleting the song, if its pos, its just voting
socket.emit('skip', [CHANNEL_NAME, PASSWORD]); Sends skip message to server
socket.emit("password", [PASSWORD, CHANNEL_NAME]); Sends password for instant log in to server
socket.emit('frontpage_lists'); Tells the server the client wants frontpage lists
socket.emit("id", [CHANNEL_ID, "play", "mock"]); Sends message to the host channel for play
socket.emit("id", [CHANNEL_ID, "pause", "mock"]); Sends message to the host channel for pause
socket.emit("id", [CHANNEL_ID, "skip", "mock"]); Sends message to the host channel for skip
socket.emit("id", [CHANNEL_ID, "volume", VALUE]); Sends message to the host channel to change volume
socket.emit("id", [CHANNEL_ID, "channel", NEW_CHANNEL_NAME]); Sends message to the host channel to change channel
socket.on("toast", STRING) Recieves a string from server for what type of toast to be triggered
socket.on("pw", STRING) Recieves the password for the channel if the user sent the right in the first place
socket.on("conf", [ARRAY]) Recieves configuration array from server
socket.on("chat.all", [CLIENT_NAME, STRING, CLIENT_CHANNEL_NAME]) Recieves chat message from allchat
socket.on("chat", [CLIENT_NAME, STRING]) Recieves chat message from channelchat
socket.on("id", STRING) Recieves the ID of the current client, used for remote listening
socket.on(id, [ARRAY]) Recieves the messages sent on CHANNEL_ID above
socket.on("channel", [TYPE, [TYPE_SPECIFIC_VALUE]]) Recieves updates from channel. [0] is one of the following: list, added, deleted, vote, song_change
socket.on("get_list") Recieves message from the server that its ready to send the playlist and info
socket.on('playlists', [ARRAY]) Recieves the playlists for the frontpage
socket.on("np", [NOW_PLAYING, CONFIGURATION, SERVER_TIME]) Recieves array of now playing song. Is triggered on song-change
socket.on("viewers", VALUE) Recieves number of viewers on the current channel
```
### Legal
Copyright © 2016
Nicolas Almagro Tonne and Kasper Rynning-Tønnesen
Creative Commons License
Zöff is licensed under a
<a href="http://creativecommons.org/licenses/by-nc-nd/3.0/no/">Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Norway License.</a>.
Do not redistribute without permission from the developers.
Zoff is licensed under a
<a href="http://creativecommons.org/licenses/by-nc-nd/3.0/no/">Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Norway License.</a>.
Do not redistribute without permission from the developers.
Copyright © 2018
Kasper Rynning-Tønnesen and Nicolas Almagro Tonne

View File

@@ -1,22 +0,0 @@
<html>
<head>
<meta name="author" content="Nicolas 'Nixo' Almagro Tonne &amp; 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">&nbsp;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>

View File

@@ -4,53 +4,69 @@ var gulp = require('gulp'),
concat = require('gulp-concat');
gulp.task('js', function () {
gulp.src(['static/js/*.js', '!static/js/embed*', '!static/js/remotecontroller.js'])
gulp.src(['server/VERSION.js', 'server/config/api_key.js', 'server/public/assets/js/*.js', '!server/public/assets/js/embed*', '!server/public/assets/js/token*', '!server/public/assets/js/remotecontroller.js', '!server/public/assets/js/callback.js'])
.pipe(uglify({
mangle: true,
compress: true,
enclose: true
}))
.pipe(concat('main.min.js'))
.pipe(gulp.dest('static/dist'));
.pipe(gulp.dest('server/public/assets/dist'));
});
gulp.task('embed', function () {
gulp.src(['static/js/player.js', 'static/js/helpers.js', 'static/js/playercontrols.js', 'static/js/list.js', 'static/js/embed.js', '!static/js/nochan*', '!static/js/remotecontroller.js'])
gulp.src(['server/VERSION.js', 'server/config/api_key.js', 'server/public/assets/js/player.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(uglify({
mangle: true,
compress: true,
enclose: true
}))
.pipe(concat('embed.min.js'))
.pipe(gulp.dest('static/dist'));
.pipe(gulp.dest('server/public/assets/dist'));
});
/*
gulp.task('nochan', function () {
gulp.src(['static/js/nochan.js', 'static/js/helpers.js'])
gulp.task('token', function() {
gulp.src(['server/public/assets/js/token*', 'server/public/assets/js/helpers.js'])
.pipe(uglify({
mangle: true,
compress: true,
enclose: true
}))
.pipe(concat('frontpage.min.js'))
.pipe(gulp.dest('static/dist'));
});*/
.pipe(concat('token.min.js'))
.pipe(gulp.dest('server/public/assets/dist'));
})
gulp.task('callback', function () {
gulp.src(['server/VERSION.js', 'server/config/api_key.js', 'server/public/assets/js/callback.js'])
.pipe(uglify({
mangle: true,
compress: true,
enclose: true
}))
.pipe(concat('callback.min.js'))
.pipe(gulp.dest('server/public/assets/dist'));
});
gulp.task('build', function() {
gulp.run(['js', 'embed', 'remotecontroller', 'callback', 'token']);
})
gulp.task('remotecontroller', function () {
gulp.src(['static/js/remotecontroller.js'])
gulp.src(['server/VERSION.js', 'server/config/api_key.js', 'server/public/assets/js/remotecontroller.js', 'server/public/assets/js/helpers.js'])
.pipe(uglify({
mangle: true,
compress: true,
enclose: true
}))
.pipe(concat('remote.min.js'))
.pipe(gulp.dest('static/dist'));
.pipe(gulp.dest('server/public/assets/dist'));
});
gulp.task('default', function(){
gulp.watch('static/js/*.js', ['js']);
gulp.watch('static/js/*.js', ['embed']);
//gulp.watch('static/js/*.js', ['nochan']);
gulp.watch('static/js/remotecontroller.js', ['remotecontroller']);
});
gulp.watch(['server/VERSION.js', 'server/public/assets/js/*.js'], ['js']);
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
View File

@@ -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">&nbsp;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>

View File

@@ -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"
}

4936
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

61
package.json Normal file
View File

@@ -0,0 +1,61 @@
{
"name": "zoff",
"version": "2.0.2",
"description": "Zoff, the shared YouTube based radio services",
"main": "server/app.js",
"scripts": {
"start": "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-util": "~3.0.6",
"gulp": "~3.9.0",
"gulp-concat": "~2.6.0",
"gulp-uglifyjs": "~0.6.2"
},
"homepage": "https://github.com/zoff-music/zoff#readme",
"dependencies": {
"bad-words": "^1.6.1",
"bcrypt-nodejs": "0.0.3",
"body-parser": "^1.17.1",
"color-thief-jimp": "^2.0.2",
"cookie-parser": "^1.4.3",
"cors": "^2.8.4",
"express": "^4.16.3",
"express-handlebars": "^3.0.0",
"express-recaptcha": "^3.0.1",
"express-session": "^1.15.6",
"express-sessions": "^1.0.6",
"gulp": "^3.9.1",
"gulp-concat": "^2.6.1",
"gulp-uglifyjs": "^0.6.2",
"gulp-util": "^3.0.8",
"helmet": "^3.12.0",
"jimp": "^0.2.28",
"mongodb": "^2.2.35",
"mongojs": "^2.5.0",
"mongoose": "^5.0.16",
"mpromise": "^0.5.5",
"nodemailer": "^4.6.4",
"passport": "^0.4.0",
"passport-local": "^1.0.0",
"redis": "^2.8.0",
"request": "^2.85.0",
"socket.io": "^2.1.0",
"socket.io-redis": "^5.2.0",
"sticky-session": "^1.1.2",
"uniqid": "^4.1.1"
}
}

View File

@@ -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>

View File

@@ -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>

View File

@@ -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&nbsp;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; ?>&amp;text=Check%20out%20this%20playlist%20<?php echo ucfirst($list); ?>%20on%20Z&ouml;ff!&amp;via=zoffmusic" target="popup" onclick="window.open('http://twitter.com/intent/tweet?url=http://<?php echo $_SERVER['HTTP_HOST'].'/'.$list; ?>&amp;text=Check%20out%20this%20playlist%20<?php echo ucfirst($list); ?>%20on%20Z&ouml;ff!&amp;via=zoffmusic','Share Playlist','width=600,height=300')">
<img class="left" src="/static/images/twitter.png" alt="Share on Twitter" />Share on&nbsp;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&amp;cht=qr&amp;chl=http://<?php echo $_SERVER['HTTP_HOST'].'/'.$list; ?>&amp;choe=UTF-8&amp;chld=L%7C1" >
<img id="qr-code-image-link" class="card rounded" src="//chart.googleapis.com/chart?chs=150x150&amp;cht=qr&amp;chl=http://<?php echo $_SERVER['HTTP_HOST'].'/'.$list; ?>&amp;choe=UTF-8&amp;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">
&copy; <?php echo date("Y"); ?>
<a href="http://nixo.no">Nixo</a> &amp;
<a href="http://kasperrt.no">KasperRT</a>
&nbsp;&nbsp;All Rights Reserved.
</div>
</div>
</footer>

View File

@@ -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 &amp; 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>

View File

@@ -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);
?>

View File

@@ -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";
}
}
?>

View File

@@ -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 &lt;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 &amp; 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:&nbsp;</span>
<span class="chan-views"></span>
<br>
<span class="highlighted">Songs:&nbsp;</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>

View File

@@ -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&amp;cht=qr&amp;choe=UTF-8&amp;chld=L%7C1&amp;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>
-->

View File

@@ -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>

16
pm2.json Normal file
View File

@@ -0,0 +1,16 @@
{
"apps" : [
{
"name" : "zoff",
"script" : "./server/app.js",
"watch" : true,
"ignore_watch": ["./node_modules", "./server/public/assets/images/thumbnails"],
},
{
"name" : "gulp",
"script" : "./gulpfile.js",
"watch" : true,
"ignore_watch": ["./node_modules", "./server/"],
}
]
}

224
server/EVENTS.md Normal file
View 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
View 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)

190
server/REST.md Normal file
View File

@@ -0,0 +1,190 @@
## 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
}
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
View File

@@ -0,0 +1,5 @@
VERSION = 5;
try {
module.exports = VERSION;
} catch(e) {}

130
server/app.js Normal file
View File

@@ -0,0 +1,130 @@
var cluster = require('cluster'),
net = require('net'),
path = require('path'),
//publicPath = path.join(__dirname, 'public'),
http = require('http'),
port = 8080,
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;
startClustered(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;
startClustered(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) {
console.log('respawning worker', i);
spawn(i);
});
};
for (var i = 0; i < num_processes; i++) {
spawn(i);
}
var worker_index = function(ip, len) {
var s = '';
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.remoteAddress, 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');
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);
}
}

45
server/apps/addtype.js Normal file
View File

@@ -0,0 +1,45 @@
path = require('path'),
pathThumbnails = __dirname;
db = require(pathThumbnails + '/../handlers/db.js');
var usual = [];
var settings = [];
db.getCollectionNames(function(err, docs) {
for(var i = 0; i < docs.length; i++) {
//console.log(docs[i] == "");
if(docs[i].indexOf("_settings") == -1 && docs[i].substring(0,1) != "." && docs[i].substring(docs[i].length - 1, docs[i].length) != ".") {
t(docs[i]);
}
}
/*for(var i = 0; i < docs.length; i++) {
if(docs[i].indexOf("_settings") > -1) {
settings.push(docs[0]);
} else {
usual.push(docs[0]);
}
//addType(docs[i]);
}
for(var i = 0; i < usual.length; i++) {
if(settings.indexOf(usual + "_settings") < 0) {
console.log(usual);
}
}*/
})
function t(docs) {
db.collection(docs).find({id: {$exists: true}}, function(e, _docs) {
if(_docs.length > 0) {
db.collection(docs).createIndex({id: 1}, {unique: true}, function(e,d){
console.log(docs);
});
}
})
}
function addType(name) {
if(name.indexOf("_settings") > -1) {
db.collection(name).update({views: {$exists: true}}, {$set: { id: "config" }}, {multi: true}, function(err, doc) {
console.log(name);
});
}
}

219
server/apps/admin.js Normal file
View File

@@ -0,0 +1,219 @@
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 api = require(pathThumbnails + '/routing/admin/api.js');
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.enable('view cache');
app.set('views', publicPath);
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(session({
secret: mongo_db_cred.secret,
resave: true,
saveUninitialized: true,
store: new (require('express-sessions'))({
storage: 'mongodb',
instance: mongoose,
host: mongo_db_cred.host,
port: 27017,
collection: 'sessions',
expire: 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', // 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;

135
server/apps/client.js Executable file
View File

@@ -0,0 +1,135 @@
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 exphbs = require('express-handlebars');
var cors = require('cors');
var hbs = exphbs.create({
defaultLayout: publicPath + '/layouts/client/main',
layoutsDir: publicPath + '/layouts/client',
partialsDir: publicPath + '/partials'
});
uniqid = require('uniqid');
app.engine('handlebars', hbs.engine);
app.set('view engine', 'handlebars');
app.enable('view cache');
app.set('views', publicPath);
var bodyParser = require('body-parser');
var cookieParser = require("cookie-parser");
var helmet = require('helmet')
app.use(helmet({
frameguard: false
}));
app.use( bodyParser.json() ); // to support JSON-encoded bodies
app.use(bodyParser.urlencoded({ // to support URL-encoded bodies
extended: true
}));
app.use(cookieParser());
/* Starting DB and socketio */
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*")});
});
db = require(pathThumbnails + '/handlers/db.js');
var socketIO = require(pathThumbnails +'/handlers/io.js');
socketIO();
app.socketIO = io;
request = require('request');
/* Globally needed "libraries" and files */
Functions = require(pathThumbnails + '/handlers/functions.js');
ListChange = require(pathThumbnails + '/handlers/list_change.js');
Chat = require(pathThumbnails + '/handlers/chat.js');
List = require(pathThumbnails + '/handlers/list.js');
Suggestions = require(pathThumbnails + '/handlers/suggestions.js');
ListSettings = require(pathThumbnails + '/handlers/list_settings.js');
Frontpage = require(pathThumbnails + '/handlers/frontpage.js');
Notifications = require(pathThumbnails + '/handlers/notifications.js');
Search = require(pathThumbnails + '/handlers/search.js');
crypto = require('crypto');
emojiStrip = Functions.removeEmojis;
Filter = require('bad-words');
filter = new Filter({ placeHolder: 'x'});
var router = require(pathThumbnails + '/routing/client/router.js');
var api = require(pathThumbnails + '/routing/client/api.js');
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;
if (cookie === undefined) {
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 {
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;

23
server/apps/rewrite.js Normal file
View File

@@ -0,0 +1,23 @@
path = require('path'),
pathThumbnails = __dirname;
db = require(pathThumbnails + '/../handlers/db.js');
db.getCollectionNames(function(err, docs) {
for(var i = 0; i < docs.length; i++) {
makeNewAndDelete(docs[i]);
}
})
function makeNewAndDelete(name) {
db.collection(name).find({views: {$exists: true}}, function(err, doc) {
if(doc.length == 0) {
} else if(doc.length == 1) {
db.collection(name + "_settings").insert(doc[0], function(err, result){
console.log("Result insert", result);
db.collection(name).remove({views: {$exists: true}}, function(err, result_del) {
console.log("Result delete", result_del);
});
});
}
});
}

View File

@@ -0,0 +1,3 @@
var analytics = "xxxx";
module.exports = analytics;

View File

@@ -0,0 +1,5 @@
var api_key = "xxxx";
try {
module.exports = api_key;
} catch(e) {}

View File

@@ -0,0 +1,7 @@
var cert = {
privateKey: 'XX',
certificate: 'XX',
ca: 'XX'
}
module.exports = cert;

View 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;

View File

@@ -0,0 +1,10 @@
var mongo_config = {
config: 'mydb',
secret: 'secret',
users: 'users',
host: 'localhost',
port: '27017',
expire: 86400,
};
module.exports = mongo_config;

View File

@@ -0,0 +1,6 @@
var recaptcha = {
site: "xxxx",
key: "xxxxx",
}
module.exports = recaptcha;

296
server/handlers/chat.js Normal file
View File

@@ -0,0 +1,296 @@
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;
}
db.collection(channel + "_settings").find({id: "config"}, function(err, conf) {
if(conf.length > 0) {
if(conf[0].userpass == "" || conf[0].userpass == crypto.createHash('sha256').update(Functions.decrypt_string(pass)).digest('base64')) {
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 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 = emojiStrip(coll).toLowerCase();
coll = filter.clean(coll);
Functions.getSessionAdminUser(Functions.getSession(socket), coll, function(userpass) {
if(userpass != "" || msg.pass == undefined) {
msg.pass = userpass;
}
db.collection(coll + "_settings").find(function(err, docs){
if(docs.length > 0 && (docs[0].userpass == undefined || docs[0].userpass == "" || (msg.hasOwnProperty('pass') && docs[0].userpass == crypto.createHash('sha256').update(Functions.decrypt_string(msg.pass)).digest("base64")))) {
var data = msg.data;
Functions.check_inlist(coll, guid, socket, offline);
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: 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});
}
});
}
} 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 = emojiStrip(coll).toLowerCase();
coll = filter.clean(coll);
Functions.check_inlist(coll, guid, socket, offline);
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});
}
});
}
}
function namechange(data, guid, socket, tried) {
/*if(!data.hasOwnProperty("channel") ||
typeof(data.channel) != "string") return;*/
var pw = "";
var new_password;
var first = false;
Functions.getSessionChatPass(Functions.getSession(socket), function(name, pass) {
if(data.hasOwnProperty("first") && data.first) {
pw = pass;
name = name;
data.name = name;
data.password = pass;
new_password = false;
if(name == "" || pass == "") {
return;
}
} 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);
}
}
if(name == "") {
return;
}
var password = Functions.decrypt_string(pw);
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) {
return;
}
accepted_password = true;
Functions.setSessionChatPass(Functions.getSession(socket), name.toLowerCase(), data.password, function() {
db.collection("registered_users").update({"_id": name.toLowerCase()}, {$set: {password: Functions.hash_pass(password)}}, {upsert: true}, function() {});
});
} else if(docs[0].password == Functions.hash_pass(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: Functions.hash_pass(password)}, {$set: {password: Functions.hash_pass(new_password)}}, function() {});
});
} else {
Functions.setSessionChatPass(Functions.getSession(socket), name.toLowerCase(), data.password, function() {
});
}
}
if(accepted_password) {
db.collection("user_names").find({"guid": guid}, function(err, names) {
if(names.length > 0) {
var old_name = names[0].name;
db.collection("user_names").update({"_id": "all_names"}, {$pull: {names: old_name}}, function() {});
db.collection("user_names").update({"guid": guid}, {$set: {name: name, icon: icon}}, 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) {
if(data.hasOwnProperty("channel") && typeof(data.channel) == "string") {
io.to(data.channel.replace(/ /g,'')).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});
}
}
});
});
} 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});
});
}
});
});
}
function removename(guid, coll, socket) {
coll = coll.replace(/ /g,'');
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});
});
});
});
}
});
}
function generate_name(guid, announce_payload, second) {
var tmp_name = Functions.rndName(second ? second : guid, 8);
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") && n == 1)) {
db.collection("user_names").update({"guid": guid}, {$set: {name: tmp_name, icon: false}}, {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 {
Chat.generate_name(guid, announce_payload, tmp_name);
}
})
} else {
Chat.generate_name(guid, announce_payload, tmp_name);
}
})
}
function get_name(guid, announce_payload, first) {
db.collection("user_names").find({"guid": guid}, function(err, docs) {
if(docs.length == 0) {
Chat.generate_name(guid, announce_payload);
} else {
name = docs[0].name;
}
})
}
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;

39
server/handlers/db.js Normal file
View File

@@ -0,0 +1,39 @@
var path = require('path');
try {
var mongo_config = require(path.join(path.join(__dirname, '../config/'), 'mongo_config.js'));
} catch(e) {
console.log("Error - missing file");
console.log("Seems you forgot to create the file mongo_config.js in /server/config/. Have a look at mongo_config.example.js.");
process.exit();
}
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: 5 }, 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;

View File

@@ -0,0 +1,32 @@
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 update_frontpage(coll, id, title, callback) {
coll = coll.replace(/ /g,'');
db.collection("frontpage_lists").update({_id: coll}, {$set: {
id: id,
title: title,
accessed: Functions.get_time()}
},{upsert: true}, function(err, returnDocs){
if(typeof(callback) == "function") callback();
});
}
module.exports.frontpage_lists = frontpage_lists;
module.exports.update_frontpage = update_frontpage;

View File

@@ -0,0 +1,295 @@
var path = require('path');
try {
var mongo_config = require(path.join(path.join(__dirname, '../config/'), 'mongo_config.js'));
} catch(e) {
console.log("Error - missing file");
console.log("Seems you forgot to create the file mongo_config.js in /server/config/. Have a look at mongo_config.example.js.");
process.exit();
}
var mongojs = require('mongojs');
var connected_db = mongojs('mongodb://' + mongo_config.host + '/user_credentials');
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, name) {
db.collection("user_names").update({"_id": "all_names"}, {$pull: {names: name}}, function(err, updated) {
db.collection("user_names").remove({"guid": guid}, function(err, removed) { });
});
}
function getSession(socket) {
try {
/*var cookieParser = require("cookie-parser");
var cookie = require("cookie");
var parsedCookies = cookie.parse(socket.handshake.headers.cookie);
return parsedCookies["_uI"];*/
return socket.cookie_id;
} catch(e) {
return "empty";
}
}
function remove_from_array(array, element){
if(Functions.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)
{
if(coll == undefined) 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);
}
db.collection("user_names").find({"guid": guid}, function(err, docs) {
if(docs.length == 1) {
socket.broadcast.to(coll).emit('chat', {from: docs[0].name, msg: " joined"});
}
});
db.collection("connected_users").update({"_id": "total_users"}, {$addToSet: {total_users: guid + coll}}, function(err, docs){});
});
});
} else {
db.collection("connected_users").find({"_id": coll}, function(err, new_doc) {
io.to(coll).emit("viewers", new_doc[0].users.length);
});
}
});
} 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) {});
}
}
}
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;
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)];
}
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(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: adminpass}}, {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 setSessionUserPass(id, userpass, list, callback) {
try {
if(id == "empty" || id == 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].userpass != undefined) userpass = d[0].userpass;
if(d[0].adminpass != undefined) adminpass = d[0].adminpass;
}
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).remove({_id: channel}, function() {
callback();
return;
});
}
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;

599
server/handlers/io.js Normal file
View File

@@ -0,0 +1,599 @@
var cookieParser = require("cookie-parser");
var cookie = require("cookie");
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 = 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});
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("?"));
}
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('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") {
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) {
socket.cookie_id = msg.guid;
guid = msg.guid;
socketid = msg.socket_id;
socket.zoff_id = socketid;
coll = msg.channel.toLowerCase().replace(/ /g,'');
coll = emojiStrip(coll).toLowerCase();
coll = filter.clean(coll);
if(coll.indexOf("?") > -1){
coll = coll.substring(0, coll.indexOf("?"));
}
in_list = true;
chromecast_object = true;
socket.join(coll);
}
});
}
} catch(e) {
return;
}
});
socket.on("get_id", function() {
socket.emit("id_chromecast", Functions.getSession(socket));
});
socket.on("error_video", function(msg) {
try {
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 = emojiStrip(_list).toLowerCase();
coll = coll.replace(/_/g, "");
coll = filter.clean(coll);
} catch(e) {
return;
}
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;
}
Suggestions.thumbnail(msg, coll.replace(/ /g,''), 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;
}
Suggestions.description(msg, coll.replace(/ /g,''), 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;
}
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(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('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 = emojiStrip(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}}, 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, name);
});
}
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);
});
}
});
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.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.replace(/ /g,''), 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;
}
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;
}
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;
}
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;
}
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(typeof(arr) == 'object')
io.to(arr.id).emit(arr.id.toLowerCase(), {type: arr.type, value: arr.value});
});
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;
}
try {
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 = emojiStrip(_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(coll === undefined) {
try {
coll = obj.channel.toLowerCase().replace(/ /g,'');
if(coll.length == 0) return;
coll = emojiStrip(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;
}
ListChange.addPlaylist(arr, guid, offline, socket);
})
socket.on('add', function(arr)
{
if(arr.hasOwnProperty("channel") && arr.channel.indexOf("?") > -1){
var _list = arr.channel.substring(0, arr.channel.indexOf("?"));
arr.channel = _list;
}
if(coll !== undefined) {
try {
coll = arr.list.replace(/ /g,'');
if(coll.length == 0) return;
coll = emojiStrip(coll).toLowerCase();
coll = coll.replace(/_/g, "");
coll = filter.clean(coll);
} catch(e) {
return;
}
}
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;
}
coll = msg.channel.toLowerCase().replace(/ /g,'');
if(coll.length == 0) return;
coll = emojiStrip(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(coll !== undefined) {
try {
coll = msg.channel.toLowerCase().replace(/ /g,'');
if(coll.length == 0) return;
coll = emojiStrip(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(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;
}
List.skip(list, guid, coll.replace(/ /g,''), 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;
}
ListSettings.conf_function(conf, coll.replace(/ /g,''), 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(coll !== undefined) {
try {
coll = msg.channel.toLowerCase().replace(/ /g,'');
if(coll.length == 0) return;
coll = emojiStrip(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.channel = coll;
} else if(obj.hasOwnProperty("channel") && obj.channel.indexOf("?") > -1){
var _list = obj.channel.substring(0, obj.channel.indexOf("?"));
obj.channel = _list;
}
if(coll === undefined && obj !== undefined && obj.channel !== undefined){
try {
coll = obj.channel.toLowerCase().replace(/ /g,'');
if(coll.length == 0) return;
coll = emojiStrip(coll).toLowerCase();
coll = coll.replace(/_/g, "");
coll = filter.clean(coll);
} catch(e) {
return;
}
}
List.left_channel(coll, guid, short_id, in_list, socket, true);
in_list = false;
});
socket.on('disconnect', function()
{
List.left_channel(coll, guid, short_id, in_list, socket, false);
});
socket.on('disconnected', function()
{
List.left_channel(coll, guid, short_id, in_list, socket, false);
});
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 != "" && typeof(msg.channel) == "string") {
coll = msg.channel.replace(/ /g,'');
coll = emojiStrip(coll).toLowerCase();
coll = filter.clean(coll);
List.left_channel(coll, guid, short_id, in_list, socket, false);
}
})
socket.on('reconnect_failed', function()
{
List.left_channel(coll, guid, short_id, in_list, socket, false);
});
socket.on('connect_timeout', function()
{
List.left_channel(coll, guid, short_id, in_list, socket, false);
});
socket.on('error', function()
{
List.left_channel(coll, guid, short_id, in_list, socket, false);
});
socket.on('pos', 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") || typeof(obj.channel) != "string")
if(coll !== undefined) {
try {
coll = obj.channel.toLowerCase().replace(/ /g,'');
if(coll.length == 0) return;
coll = emojiStrip(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;
}
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;
}
if(docs.length > 0 && (docs[0].userpass == undefined || docs[0].userpass == "" || (obj.hasOwnProperty('pass') && docs[0].userpass == crypto.createHash('sha256').update(Functions.decrypt_string(obj.pass)).digest("base64")))) {
Functions.check_inlist(coll, guid, socket, offline);
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);
});
});
});
}*/

732
server/handlers/list.js Normal file
View File

@@ -0,0 +1,732 @@
var ColorThief = require('color-thief-jimp');
var Jimp = require('jimp');
function now_playing(list, fn, socket) {
if(typeof(list) !== 'string' || typeof(fn) !== 'function') {
socket.emit('update_required');
return;
}
db.collection(list).find({now_playing:true}, function(err, docs){
if(docs.length === 0){
fn("No song currently playing");
return;
}
var title = docs[0].title;
if(title === undefined) fn("No song currently playing");
else fn(title);
});
}
function list(msg, guid, coll, offline, socket) {
var socketid = socket.zoff_id;
if(typeof(msg) === 'object' && msg !== undefined && msg !== null)
{
Functions.getSessionAdminUser(Functions.getSession(socket), coll, function(userpass, adminpass, gotten) {
if(gotten && userpass != "" && !msg.hasOwnProperty("pass")) {
msg.pass = userpass;
}
if(!msg.hasOwnProperty('version') || !msg.hasOwnProperty("channel") ||
msg.version != VERSION || msg.version == undefined ||
typeof(msg.channel) != "string") {
var result = {
channel: {
expected: "string",
got: msg.hasOwnProperty("channel") ? typeof(msg.channel) : undefined,
},
version: {
expected: VERSION,
got: msg.version,
},
pass: {
expected: "string",
got: msg.hasOwnProperty("pass") ? typeof(msg.pass) : undefined,
},
};
socket.emit('update_required', result);
return;
}
coll = msg.channel.toLowerCase().replace(/ /g,'');
coll = emojiStrip(coll).toLowerCase();
coll = filter.clean(coll);
var pass = crypto.createHash('sha256').update(Functions.decrypt_string(msg.pass)).digest("base64");
db.collection('frontpage_lists').find({"_id": coll}, function(err, frontpage_lists){
if(frontpage_lists.length == 1) {
db.collection(coll + "_settings").find(function(err, docs) {
if(docs.length == 0 || (docs.length > 0 && (docs[0].userpass == undefined || docs[0].userpass == "" || docs[0].userpass == pass))) {
if(docs.length > 0 && docs[0].hasOwnProperty('userpass') && docs[0].userpass != "" && docs[0].userpass == pass) {
Functions.setSessionUserPass(Functions.getSession(socket), msg.pass, coll, function(){})
socket.emit("auth_accepted", {value: true});
}
if(docs.length > 0 && docs[0].hasOwnProperty("adminpass") && docs[0].adminpass != "" && docs[0].adminpass == Functions.hash_pass(Functions.hash_pass(Functions.decrypt_string(adminpass), true))) {
socket.emit("pw", true);
}
in_list = true;
socket.join(coll);
Functions.check_inlist(coll, guid, socket, offline);
if(frontpage_lists.viewers != undefined){
io.to(coll).emit("viewers", frontpage_lists.viewers);
} else {
io.to(coll).emit("viewers", 1);
}
List.send_list(coll, socket, true, false, true);
} else {
socket.emit("auth_required");
}
});
} else {
db.createCollection(coll, function(err, docs){
db.collection(coll).createIndex({ id: 1}, {unique: true}, function(e, d) {
var configs = {"addsongs":false, "adminpass":"", "allvideos":true, "frontpage":true, "longsongs":false, "removeplay": false, "shuffle": true, "skip": false, "skips": [], "startTime":Functions.get_time(), "views": [], "vote": false, "desc": "", userpass: "", id: "config"};
db.collection(coll + "_settings").insert(configs, function(err, docs){
socket.join(coll);
List.send_list(coll, socket, true, false, true);
db.collection("frontpage_lists").insert({"_id": coll, "count" : 0, "frontpage": true, "accessed": Functions.get_time(), "viewers": 1});
Functions.check_inlist(coll, guid, socket, offline);
});
});
});
}
});
});
} else {
var result = {
msg: {
expected: "object",
got: typeof(msg)
},
};
socket.emit('update_required', result);
}
}
function skip(list, guid, coll, offline, socket) {
var socketid = socket.zoff_id;
if(list !== undefined && list !== null && list !== "")
{
if(coll == undefined && list.hasOwnProperty('channel')) coll = list.channel.toLowerCase();
if(coll !== undefined) {
try {
coll = list.channel.toLowerCase().replace(/ /g,'');
if(coll.length == 0) return;
coll = emojiStrip(coll).toLowerCase();
coll = coll.replace(/_/g, "");
coll = filter.clean(coll);
} catch(e) {
return;
}
}
if(!list.hasOwnProperty("id") || !list.hasOwnProperty("channel") ||
typeof(list.id) != "string" || typeof(list.channel) != "string") {
var result = {
channel: {
expected: "string",
got: list.hasOwnProperty("channel") ? typeof(list.channel) : undefined,
},
pass: {
expected: "string",
got: list.hasOwnProperty("pass") ? typeof(list.pass) : undefined,
},
userpass: {
expected: "string",
got: list.hasOwnProperty("userpass") ? typeof(list.userpass) : undefined,
},
id: {
expected: "string",
got: list.hasOwnProperty("id") ? typeof(list.id) : undefined,
},
};
socket.emit('update_required', result);
return;
}
Functions.getSessionAdminUser(Functions.getSession(socket), coll, function(userpass, adminpass) {
if(adminpass != "" || list.pass == undefined) {
list.pass = adminpass;
}
if(userpass != "" || list.userpass == undefined) {
list.userpass = userpass;
}
db.collection(coll + "_settings").find(function(err, docs){
if(docs.length > 0 && (docs[0].userpass == undefined || docs[0].userpass == "" || (list.hasOwnProperty('userpass') && docs[0].userpass == crypto.createHash('sha256').update(Functions.decrypt_string(list.userpass)).digest("base64")))) {
Functions.check_inlist(coll, guid, socket, offline);
adminpass = "";
video_id = list.id;
err = list.error;
var error = false;
var video_id;
if(err != "5" && err != "100" && err != "101" && err != "150")
{
adminpass = list.pass;
}else if(err == "5" || err == "100" || err == "101" || err == "150"){
error = true;
}
if(adminpass !== undefined && adminpass !== null && adminpass !== "")
hash = Functions.hash_pass(Functions.hash_pass(Functions.decrypt_string(adminpass),true));
else
hash = "";
db.collection(coll + "_settings").find(function(err, docs){
if(docs !== null && docs.length !== 0)
{
if(!docs[0].skip || (docs[0].adminpass == hash && docs[0].adminpass !== "") || error)
{
db.collection("frontpage_lists").find({"_id": coll}, function(err, frontpage_viewers){
if((frontpage_viewers[0].viewers/2 <= docs[0].skips.length+1 && !Functions.contains(docs[0].skips, guid) && frontpage_viewers[0].viewers != 2) ||
(frontpage_viewers[0].viewers == 2 && docs[0].skips.length+1 == 2 && !Functions.contains(docs[0].skips, guid)) ||
(docs[0].adminpass == hash && docs[0].adminpass !== "" && docs[0].skip))
{
List.change_song(coll, error, video_id);
socket.emit("toast", "skip");
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;
}
io.to(coll).emit('chat', {from: docs[0].name, icon: icon, msg: " skipped"});
});
}
});
}else if(!Functions.contains(docs[0].skips, guid)){
db.collection(coll + "_settings").update({ id: "config" }, {$push:{skips:guid}}, function(err, d){
if(frontpage_viewers[0].viewers == 2)
to_skip = 1;
else
to_skip = (Math.ceil(frontpage_viewers[0].viewers/2) - docs[0].skips.length-1);
socket.emit("toast", to_skip + " more are needed to skip!");
socket.to(coll).emit('chat', {from: name, msg: " voted to skip"});
});
}else{
socket.emit("toast", "alreadyskip");
}
});
}else
socket.emit("toast", "noskip");
}
});
} else {
socket.emit("auth_required");
}
});
});
} else {
var result = {
msg: {
expected: "object",
got: typeof(list),
},
};
socket.emit("update_required", result);
}
}
function change_song(coll, error, id, callback, socket) {
coll = coll.replace(/ /g,'');
db.collection(coll + "_settings").find(function(err, docs){
var startTime = docs[0].startTime;
if(docs !== null && docs.length !== 0)
{
db.collection(coll).aggregate([{
$match:{
views:{
$exists: false
},
type:{
$ne: "suggested"
}
}
}, {
$sort:{
now_playing: -1,
votes:-1,
added:1,
title: 1
}
}, {
$limit:2
}], function(err, now_playing_doc){
if((id && id == now_playing_doc[0].id) || !id) {
if(error){
request('http://img.youtube.com/vi/'+now_playing_doc[0].id+'/mqdefault.jpg', function (err, response, body) {
if (err || response.statusCode == 404) {
db.collection(coll).remove({now_playing:true, id:id}, function(err, docs){
var next_song;
if(now_playing_doc.length == 2) next_song = now_playing_doc[1].id;
List.change_song_post(coll, next_song, callback, socket);
if(!callback) {
io.to(coll).emit("channel", {type: "deleted", value: now_playing_doc[0].id, removed: true});
}
db.collection("frontpage_lists").update({_id: coll, count: {$gt: 0}}, {$inc: {count: -1}, $set:{accessed: Functions.get_time()}}, {upsert: true}, function(err, docs){});
});
} else {
if((docs[0].skipped_time != undefined && docs[0].skipped_time != Functions.get_time()) || docs[0].skipped_time == undefined) {
db.collection(coll + "_settings").update({id: "config"}, {$set: {skipped_time: Functions.get_time()}}, function(err, updated){
db.collection(coll).update({now_playing:true, id:id}, {
$set:{
now_playing:false,
votes:0,
guids:[]
}
},{multi:true}, function(err, docs){
var next_song;
if(now_playing_doc.length == 2) next_song = now_playing_doc[1].id;
if(docs.n >= 1) List.change_song_post(coll, next_song, callback, socket);
});
});
}
}
});
} else if(docs[0].removeplay === true){
db.collection(coll).remove({now_playing:true, id:id}, function(err, docs){
var next_song;
if(now_playing_doc.length == 2) next_song = now_playing_doc[1].id;
List.change_song_post(coll, next_song, callback, socket);
if(!callback) {
io.to(coll).emit("channel", {type: "deleted", value: now_playing_doc[0].id, removed: true});
}
db.collection("frontpage_lists").update({_id: coll, count: {$gt: 0}}, {$inc: {count: -1}, $set:{accessed: Functions.get_time()}}, {upsert: true}, function(err, docs){});
});
} else {
if((docs[0].skipped_time != undefined && docs[0].skipped_time != Functions.get_time()) || docs[0].skipped_time == undefined) {
db.collection(coll).update({now_playing:true, id:id}, {
$set:{
now_playing:false,
votes:0,
guids:[]
}
},{multi:true}, function(err, docs){
var next_song;
if(now_playing_doc.length == 2) next_song = now_playing_doc[1].id;
List.change_song_post(coll, next_song, callback, socket);
});
}
}
} else {
if(now_playing_doc[0].now_playing == true && now_playing_doc.length > 1 && now_playing_doc[1].id == id) {
db.collection(coll).update({id: now_playing_doc[0].id}, {$set: {now_playing: false}}, function(e, d) {
change_song(coll, error, id, callback, socket);
})
} else {
return;
}
}
});
}
});
}
function change_song_post(coll, next_song, callback, socket) {
coll = coll.replace(/ /g,'');
db.collection(coll).aggregate([{
$match:{
now_playing:false,
type:{
$ne: "suggested"
}
}
}, {
$sort:{
votes:-1,
added:1,
title: 1
}
}, {
$limit:2
}], function(err, docs){
if(docs !== null && docs.length > 0){
var id = docs[0].id;
if(next_song && next_song != id) {
if((docs.length == 2 && next_song == docs[1].id)) {
id = docs[1].id;
} else {
return;
}
}
db.collection(coll).update({id:id},{
$set:{
now_playing:true,
votes:0,
guids:[],
added:Functions.get_time()
}
}, function(err, returnDocs){
db.collection(coll + "_settings").update({id: "config"}, {
$set:{
startTime:Functions.get_time(),
skips:[]
}
}, function(err, returnDocs){
db.collection(coll + "_settings").find({id: "config"}, function(err, conf){
if(!callback) {
io.to(coll).emit("channel", {type: "song_change", time: Functions.get_time(), remove: conf[0].removeplay});
List.send_play(coll);
} else {
socket.to(coll).emit("channel", {type: "song_change", time: Functions.get_time(), remove: conf[0].removeplay});
List.send_play(coll, socket, true);
callback();
}
Frontpage.update_frontpage(coll, docs[0].id, docs[0].title);
});
});
});
}
});
}
function send_list(coll, socket, send, list_send, configs, shuffled)
{
coll = coll.replace(/ /g,'');
db.collection(coll + "_settings").find({id: "config"}, function(err, _conf){
var conf = _conf;
if(conf.length == 0) {
var conf = {"id": "config", "addsongs":false, "adminpass":"", "allvideos":true, "frontpage":true, "longsongs":false, "removeplay": false, "shuffle": true, "skip": false, "skips": [], "startTime":Functions.get_time(), "views": [], "vote": false, "desc": "", userpass: ""};
db.collection(coll + "_settings").update({id: "config"}, conf, {upsert: true}, function(err, docs) {
send_list(coll, socket, send, list_send, configs, shuffled);
});
} else {
db.collection(coll).find({type: {$ne: "suggested"}}, function(err, docs)
{
if(docs.length > 0) {
db.collection(coll).find({now_playing: true}, function(err, np_docs) {
if(np_docs.length == 0) {
db.collection(coll).aggregate([{
$match:{
views:{
$exists: false
},
type:{
$ne: "suggested"
}
}
}, {
$sort:{
now_playing: -1,
votes:-1,
added:1,
title: 1
}
}, {
$limit:1
}], function(err, now_playing_doc){
if(now_playing_doc[0].now_playing == false) {
db.collection(coll).update({id:now_playing_doc[0].id}, {
$set:{
now_playing:true,
votes:0,
guids:[],
added:Functions.get_time()
}
}, function(err, returnDocs){
db.collection(coll + "_settings").update({ id: "config" }, {
$set:{
startTime: Functions.get_time(),
skips:[]
}
}, function(err, returnDocs){
Frontpage.update_frontpage(coll, now_playing_doc[0].id, now_playing_doc[0].title);
List.send_list(coll, socket, send, list_send, configs, shuffled);
});
});
}
});
} else if(np_docs.length > 1) {
db.collection(coll).aggregate([{
$match:{
now_playing: true
}
}, {
$sort:{
now_playing: -1,
votes:-1,
added:1,
title: 1
}
}], function(e, docs) {
var real_now_playing = docs[docs.length - 1];
db.collection(coll).update({now_playing: true, id: {$ne: real_now_playing.id}}, {$set: {now_playing: false}}, {multi: true}, function(e, d) {
send_list(coll, socket, send, list_send, configs, shuffled);
})
})
} else {
if(Functions.get_time()-conf[0].startTime > np_docs[0].duration){
List.change_song(coll, false, np_docs[0].id, function() {
List.send_list(coll, socket, send, list_send, configs, shuffled);
}, socket);
} else {
if(list_send) {
io.to(coll).emit("channel", {type: "list", playlist: docs, shuffled: shuffled});
} else if(!list_send) {
socket.emit("channel", {type: "list", playlist: docs, shuffled: shuffled});
}
if(socket === undefined && send) {
List.send_play(coll);
} else if(send) {
List.send_play(coll, socket);
}
}
}
});
} else {
if(list_send) {
io.to(coll).emit("channel", {type: "list", playlist: docs, shuffled: shuffled});
} else if(!list_send) {
socket.emit("channel", {type: "list", playlist: docs, shuffled: shuffled});
}
if(socket === undefined && send) {
List.send_play(coll);
} else if(send) {
List.send_play(coll, socket);
}
}
});
if(configs)
{
if(conf.length > 0) {
if(conf[0].adminpass !== "") conf[0].adminpass = true;
if(conf[0].hasOwnProperty("userpass") && conf[0].userpass != "") conf[0].userpass = true;
else conf[0].userpass = false;
io.to(coll).emit("conf", conf);
} else if(conf.length == 0 && docs.length > 0) {
var conf = {"id": "config", "addsongs":false, "adminpass":"", "allvideos":true, "frontpage":true, "longsongs":false, "removeplay": false, "shuffle": true, "skip": false, "skips": [], "startTime":Functions.get_time(), "views": [], "vote": false, "desc": "", userpass: ""};
db.collection(coll + "_settings").update({id: "config"}, conf, {upsert: true}, function(err, docs) {
io.to(coll).emit("conf", conf);
});
}
}
}
});
if(socket){
db.collection(coll).find({type:"suggested"}).sort({added: 1}, function(err, sugg){
socket.emit("suggested", sugg);
});
}
}
function end(obj, coll, guid, offline, socket) {
var socketid = socket.zoff_id;
if(typeof(obj) !== 'object') {
return;
}
id = obj.id;
if(id !== undefined && id !== null && id !== "") {
if(!obj.hasOwnProperty("id") || !obj.hasOwnProperty("channel") ||
typeof(obj.id) != "string" || 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,
},
id: {
expected: "string",
got: obj.hasOwnProperty("id") ? typeof(obj.id) : undefined,
},
};
socket.emit("update_required", result);
return;
}
coll = coll.replace(/ /g,'');
Functions.getSessionAdminUser(Functions.getSession(socket), coll, function(userpass) {
if(userpass != "" || obj.pass == undefined) {
obj.pass = userpass;
}
db.collection(coll + "_settings").find(function(err, docs){
if(docs.length > 0 && (docs[0].userpass == undefined || docs[0].userpass == "" || (obj.hasOwnProperty('pass') && docs[0].userpass == crypto.createHash('sha256').update(Functions.decrypt_string(obj.pass)).digest("base64")))) {
Functions.check_inlist(coll, guid, socket, offline);
db.collection(coll).find({now_playing:true}, function(err, np){
if(err !== null) console.log(err);
if(np !== null && np !== undefined && np.length == 1 && np[0].id == id){
db.collection(coll + "_settings").find(function(err, docs){
var startTime = docs[0].startTime;
if(docs[0].removeplay === true && startTime+parseInt(np[0].duration)<=Functions.get_time()+5)
{
db.collection(coll).remove({now_playing:true}, function(err, docs){
List.change_song_post(coll);
db.collection("frontpage_lists").update({_id:coll, count: {$gt: 0}}, {$inc:{count:-1}, $set:{accessed: Functions.get_time()}}, {upsert:true}, function(err, docs){});
});
}else{
if(startTime+parseInt(np[0].duration)<=Functions.get_time()+5)
{
List.change_song(coll, false, id);
}
}
});
}
});
} else {
socket.emit("auth_required");
}
});
});
} else {
var result = {
msg: {
expected: "object",
got: typeof(obj)
},
};
socket.emit("update_required", result);
}
}
function send_play(coll, socket, broadcast) {
coll = coll.replace(/ /g,'');
db.collection(coll).find({now_playing:true}, function(err, np){
db.collection(coll + "_settings").find(function(err, conf){
if(err !== null) console.log(err);
try{
if(Functions.get_time()-conf[0].startTime > np[0].duration){
List.change_song(coll, false, np[0].id);
} else if(conf !== null && conf !== undefined && conf.length !== 0)
{
if(conf[0].adminpass !== "") conf[0].adminpass = true;
if(conf[0].hasOwnProperty("userpass") && conf[0].userpass != "") conf[0].userpass = true;
else conf[0].userpass = false;
if(!np.hasOwnProperty("start")) np.start = 0;
if(!np.hasOwnProperty("end")) np.end = np.duration;
toSend = {np: np, conf: conf, time: Functions.get_time()};
if(socket === undefined) {
io.to(coll).emit("np", toSend);
//
List.getNextSong(coll)
sendColor(coll, false, np[0].id);
} else {
sendColor(coll, socket, np[0].id);
if(broadcast) {
socket.to(coll).emit("np", toSend);
return;
}
socket.emit("np", toSend);
}
}
} catch(e){
if(socket) {
if(broadcast) {
socket.to(coll).emit("np", {});
return;
}
socket.emit("np", {});
} else {
io.to(coll).emit("np", {});
}
}
});
});
}
function sendColor(coll, socket, id, ajax, res) {
if(coll != undefined && typeof(coll) == "string") {
coll = coll.replace(/ /g,'');
}
var url = 'https://img.youtube.com/vi/'+id+'/mqdefault.jpg';
Jimp.read(url).then(function (image) {
var c = ColorThief.getColor(image);
if(ajax) {
res.header({"Content-Type": "application/json"});
res.status(200).send(c);
return;
} else {
if(socket) {
socket.emit("color", {color: c, only: true});
} else {
io.to(coll).emit("color", {color: c, only: false});
}
}
});
}
function getNextSong(coll, callback) {
coll = coll.replace(/ /g,'');
db.collection(coll).aggregate([{
$match:{
views:{
$exists: false
},
type:{
$ne: "suggested"
}
}
}, {
$sort:{
now_playing: 1,
votes:-1,
added:1,
title: 1
}
}, {
$limit:1
}], function(err, doc) {
if(doc.length == 1) {
io.to(coll).emit("next_song", {videoId: doc[0].id, title: doc[0].title});
}
if(typeof(callback) == "function") callback();
});
}
function left_channel(coll, guid, short_id, in_list, socket, change) {
if(!coll) 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").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) {
io.to(coll).emit('chat', {from: docs[0].name, msg: " left"});
}
});
io.to(coll).emit("viewers", new_doc[0].users.length);
socket.leave(coll);
});
db.collection("connected_users").update({"_id": "total_users"}, {$pull: {total_users: guid + coll}}, function(err, updated){});
if(!change) {
Functions.remove_name_from_db(guid, name);
}
});
} 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){});
}
});
}
});
Functions.remove_unique_id(short_id);
}
module.exports.sendColor = sendColor;
module.exports.now_playing = now_playing;
module.exports.list = list;
module.exports.skip = skip;
module.exports.change_song = change_song;
module.exports.change_song_post = change_song_post;
module.exports.send_list = send_list;
module.exports.end = end;
module.exports.send_play = send_play;
module.exports.getNextSong = getNextSong;
module.exports.left_channel = left_channel;

View File

@@ -0,0 +1,724 @@
function addFromOtherList(arr, guid, offline, socket) {
var socketid = socket.zoff_id;
if(typeof(arr) == "object") {
if(!arr.hasOwnProperty("channel") || !arr.hasOwnProperty("new_channel")
|| typeof(arr.channel) != "string" || typeof(arr.new_channel) != "string") {
var result = {
channel: {
expected: "string",
got: arr.hasOwnProperty("channel") ? typeof(arr.channel) : undefined
},
new_channel: {
expected: "string",
got: arr.hasOwnProperty("new_channel") ? typeof(arr.new_channel) : undefined
}
};
socket.emit('update_required', result);
return;
}
var channel = arr.channel.replace(/ /g,'').toLowerCase();
var new_channel = arr.new_channel.replace(/ /g, '').toLowerCase();
db.collection("frontpage_lists").find({_id: new_channel}, function(err, fp) {
if(fp.length == 0) {
socket.emit("toast", "nolist");
return;
}
Functions.getSessionAdminUser(Functions.getSession(socket), channel, function(userpass, adminpass) {
if(userpass != "" || arr.userpass == undefined) {
arr.userpass = userpass;
}
if(adminpass != "" || arr.adminpass == undefined) {
arr.adminpass = adminpass;
}
Functions.getSessionAdminUser(Functions.getSession(socket), new_channel, function(userpass) {
var otheruser = "";
if(userpass != "") {
otheruser = userpass;
}
db.collection(channel).find({now_playing: true}, function(e, np) {
var project_object = {
"id": 1,
"added": 1,
"guids": { "$literal": [] },
"now_playing": 1,
"title": 1,
"votes": { "$literal": 0 },
"start": 1,
"duration": 1,
"end": 1,
"type": 1
};
var to_set_np = true;
if(np.length > 0) {
project_object.now_playing = { "$literal": false };
to_set_np = false;
}
db.collection(new_channel + "_settings").find({id: "config"}, function(e, new_conf) {
if(new_conf.length > 0 && (new_conf[0].userpass == "" || !new_conf[0].userpass || new_conf[0].userpass == crypto.createHash('sha256').update(Functions.decrypt_string(otheruser)).digest("base64"))) {
db.collection(channel + "_settings").find({id: "config"}, function(e, this_conf) {
var hash = Functions.hash_pass(Functions.hash_pass(Functions.decrypt_string(arr.adminpass), true));
if((this_conf[0].userpass == "" || !this_conf[0].userpass || this_conf[0].userpass == crypto.createHash('sha256').update(Functions.decrypt_string(arr.userpass)).digest("base64"))) {
if(((this_conf[0].addsongs === true && (hash == this_conf[0].adminpass || this_conf[0].adminpass === "")) ||
this_conf[0].addsongs === false)) {
db.collection(new_channel).aggregate([
{
"$match": { type: "video" }
},
{
"$project": project_object
}
], function(e, docs) {
var path = require('path');
var mongo_config = require(path.join(path.join(__dirname, '../config/'), 'mongo_config.js'));
var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://" + mongo_config.host + ":" + mongo_config.port + "/";
MongoClient.connect(url, function(err, _db) {
var dbo = _db.db(mongo_config.config);
dbo.collection(channel).insertMany(docs, {ordered: false}, function(err, res) {
db.collection(channel + "_settings").update({id: "config"}, {$set: {startTime: Functions.get_time()}}, function(e,d) {
if(to_set_np) {
var to_change = {
_id: channel,
count: res.nInserted != undefined ? res.nInserted : res.insertedCount,
frontpage: true,
accessed: Functions.get_time(),
}
db.collection(channel).find({now_playing: true}, function(e, np_docs) {
to_change.id = np_docs[0].id;
to_change.title = np_docs[0].title;
db.collection("frontpage_lists").update({_id: channel}, {$set: to_change}, function(e, d) {
List.send_list(channel, undefined, false, true, false);
List.send_play(channel, undefined);
socket.emit("toast", "addedplaylist");
_db.close();
});
});
} else {
db.collection("frontpage_lists").update({_id: channel}, {$inc: {count: res.nInserted != undefined ? res.nInserted : res.insertedCount}}, function(e, d) {
List.send_list(channel, undefined, false, true, false);
List.send_play(channel, undefined);
socket.emit("toast", "addedplaylist");
_db.close();
})
}
});
});
});
});
} else {
socket.emit("toast", "listhaspass");
return;
}
} else {
socket.emit("auth_required");
return;
}
})
} else {
socket.emit("toast", "other_list_pass");
return;
}
})
});
});
});
});
}
}
function addPlaylist(arr, guid, offline, socket) {
var socketid = socket.zoff_id;
if(typeof(arr) == "object") {
if(!arr.hasOwnProperty("channel") || !arr.hasOwnProperty("songs")
|| typeof(arr.channel) != "string" || typeof(arr.songs) != "object") {
var result = {
channel: {
expected: "string",
got: arr.hasOwnProperty("channel") ? typeof(arr.channel) : undefined
},
songs: {
expected: "object",
got: arr.hasOwnProperty("songs") ? typeof(arr.songs) : undefined
}
};
socket.emit('update_required', result);
return;
}
var channel = arr.channel.replace(/ /g,'').toLowerCase();
db.collection("frontpage_lists").find({_id: channel}, function(err, fp) {
if(fp.length == 0) {
socket.emit("toast", "nolist");
return;
}
Functions.getSessionAdminUser(Functions.getSession(socket), channel, function(userpass, adminpass) {
if(userpass != "" || arr.userpass == undefined) {
arr.userpass = userpass;
}
if(adminpass != "" || arr.adminpass == undefined) {
arr.adminpass = adminpass;
}
db.collection(channel).find({now_playing: true}, function(e, np) {
var now_playing = false;
if(np.length == 0) now_playing = true;
db.collection(channel + "_settings").find({id: "config"}, function(e, conf) {
if(arr.length == 0) {
socket.emit("toast", "Empty list..");
return;
}
if(conf.length > 0) {
var hash = Functions.hash_pass(Functions.hash_pass(Functions.decrypt_string(arr.adminpass), true));
if((conf[0].userpass == "" || !conf[0].userpass || conf[0].userpass == crypto.createHash('sha256').update(Functions.decrypt_string(arr.userpass)).digest("base64"))) {
if(((conf[0].addsongs === true && (hash == conf[0].adminpass || conf[0].adminpass === "")) ||
conf[0].addsongs === false)) {
var path = require('path');
var mongo_config = require(path.join(path.join(__dirname, '../config/'), 'mongo_config.js'));
var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://" + mongo_config.host + ":" + mongo_config.port + "/";
MongoClient.connect(url, function(err, _db) {
var dbo = _db.db(mongo_config.config);
var number_elements = arr.songs.length + 1;
var time = Functions.get_time() - number_elements;
var to_set_np = now_playing;
var bulk = dbo.collection(channel).initializeUnorderedBulkOp({useLegacyOps: true});
for(var i = 0; i < arr.songs.length; i++) {
var this_element = arr.songs[i];
if(!this_element.hasOwnProperty("duration") || !this_element.hasOwnProperty("id") || !this_element.hasOwnProperty("title")) {
continue;
}
this_element.added = time;
this_element.now_playing = now_playing;
this_element.votes = 0;
this_element.guids = [];
if(!this_element.hasOwnProperty("start")) this_element.start = 0;
if(!this_element.hasOwnProperty("end")) this_element.end = this_element.duration;
this_element.start = parseInt(this_element.start);
this_element.end = parseInt(this_element.end);
this_element.type = "video";
this_element.duration = parseInt(this_element.duration);
if(this_element.start > this_element.end) {
this_element.start = 0;
}
if(now_playing) {
now_playing = false;
}
bulk.insert(this_element);
}
bulk.execute(function(err, results) {
db.collection(channel + "_settings").update({id: "config"}, {$set: {startTime: Functions.get_time()}}, function(e,d) {
if(to_set_np) {
var to_change = {
_id: channel,
count: results.nInserted,
frontpage: true,
accessed: Functions.get_time(),
}
db.collection(channel).find({now_playing: true}, function(e, np_docs) {
to_change.id = np_docs[0].id;
to_change.title = np_docs[0].title;
db.collection("frontpage_lists").update({_id: channel}, {$set: to_change}, function(e, d) {
List.send_list(channel, undefined, false, true, false);
List.send_play(channel, undefined);
socket.emit("toast", "addedplaylist");
_db.close();
});
});
} else {
db.collection("frontpage_lists").update({_id: channel}, {$inc: {count: results.nInserted != undefined ? results.nInserted : results.insertedCount}}, function(e, d) {
List.send_list(channel, undefined, false, true, false);
List.send_play(channel, undefined);
socket.emit("toast", "addedplaylist");
_db.close();
})
}
});
});
});
} else {
socket.emit("toast", "listhaspass");
return;
}
} else {
socket.emit("auth_required");
return;
}
} else {
socket.emit("toast", "nolist");
return;
}
})
});
});
});
}
}
function add_function(arr, coll, guid, offline, socket) {
var socketid = socket.zoff_id;
if(typeof(arr) === 'object' && arr !== undefined && arr !== null && arr !== "" && !isNaN(parseInt(arr.duration)))
{
if(coll == "" || coll == undefined || coll == null ||
!arr.hasOwnProperty("start") || !arr.hasOwnProperty("end")) {
var result = {
start: {
expected: "number or string that can be cast to int",
got: arr.hasOwnProperty("start") ? typeof(arr.start) : undefined
},
end: {
expected: "number or string that can be cast to int",
got: arr.hasOwnProperty("end") ? typeof(arr.end) : undefined
}
};
socket.emit('update_required', result);
return;
}
try {
var start = parseInt(arr.start);
var end = parseInt(arr.end);
if(start < 0) {
socket.emit("toast", "faulty_start_end");
return;
}
if(end < 0) {
socket.emit("toast", "faulty_start_end");
return;
}
if(start >= end) {
start = 0;
arr.duration = end - start;
}
} catch(e) {
return;
}
if(typeof(arr.id) != "string" || typeof(arr.start) != "number" ||
typeof(arr.end) != "number" || typeof(arr.title) != "string" ||
typeof(arr.list) != "string" || typeof(arr.duration) != "number") {
var result = {
start: {
expected: "number or string that can be cast to int",
got: arr.hasOwnProperty("start") ? typeof(arr.start) : undefined
},
end: {
expected: "number or string that can be cast to int",
got: arr.hasOwnProperty("end") ? typeof(arr.end) : undefined
},
title: {
expected: "string",
got: arr.hasOwnProperty("title") ? typeof(arr.title) : undefined
},
list: {
expected: "string",
got: arr.hasOwnProperty("list") ? typeof(arr.list) : undefined
},
duration: {
expected: "number or string that can be cast to int",
got: arr.hasOwnProperty("duration") ? typeof(arr.duration) : undefined
},
pass: {
expected: "string",
got: arr.hasOwnProperty("pass") ? typeof(arr.pass) : undefined
},
adminpass: {
expected: "string",
got: arr.hasOwnProperty("adminpass") ? typeof(arr.adminpass) : undefined
}
};
socket.emit('update_required', result);
return;
}
coll = coll.replace(/ /g,'');
Functions.getSessionAdminUser(Functions.getSession(socket), coll, function(userpass, adminpass) {
if(adminpass != "" || arr.adminpass == undefined) {
arr.adminpass = adminpass;
}
if(userpass != "" || arr.userpass == undefined) {
arr.userpass = userpass;
}
db.collection(coll + "_settings").find(function(err, docs){
if(docs.length > 0 && (docs[0].userpass == undefined || docs[0].userpass == "" || (arr.hasOwnProperty('pass') && docs[0].userpass == crypto.createHash('sha256').update(Functions.decrypt_string(arr.pass)).digest("base64")))) {
Functions.check_inlist(coll, guid, socket, offline);
var id = arr.id;
var title = arr.title;
var hash = Functions.hash_pass(Functions.hash_pass(Functions.decrypt_string(arr.adminpass), true));
var duration = parseInt(arr.duration);
/*db.collection(coll + "_settings").find(function(err, docs)
{*/
conf = docs;
if(docs !== null && docs.length !== 0 && ((docs[0].addsongs === true && (hash == docs[0].adminpass || docs[0].adminpass === "")) ||
docs[0].addsongs === false)) {
db.collection(coll).find({id:id, type:{$ne:"suggested"}}, function(err, docs){
if(docs !== null && docs.length === 0) {
var guids = [guid];
var added = Functions.get_time();
var votes = 1;
db.collection(coll).find({now_playing:true}, function(err, docs){
if((docs !== null && docs.length === 0)){
np = true;
} else {
np = false;
}
var new_song = {"added": added,"guids":guids,"id":id,"now_playing":np,"title":title,"votes":votes, "duration":duration, "start": parseInt(start), "end": parseInt(end), "type": "video"};
db.collection(coll).update({id: id}, new_song, {upsert: true}, function(err, docs){
new_song._id = "asd";
if(np) {
List.send_list(coll, undefined, false, true, false);
db.collection(coll + "_settings").update({ id: "config" }, {$set:{startTime: Functions.get_time()}});
List.send_play(coll, undefined);
Frontpage.update_frontpage(coll, id, title);
Search.get_correct_info(new_song, coll, false);
} else {
io.to(coll).emit("channel", {type: "added", value: new_song});
Search.get_correct_info(new_song, coll, true);
}
db.collection("frontpage_lists").update({_id:coll}, {$inc:{count:1}, $set:{accessed: Functions.get_time()}}, {upsert:true}, function(err, docs){});
List.getNextSong(coll);
});
socket.emit("toast", "addedsong");
});
} else {
ListChange.vote(coll, id, guid, socket);
}
});
} else {
db.collection(coll).find({id: id}, function(err, docs) {
if(docs.length === 0) {
db.collection(coll).update({id: id}, {$set:{
"added":Functions.get_time(),
"guids": [guid],
"id":id,
"now_playing": false,
"title":title,
"votes":1,
"duration":duration,
"start": start,
"end": end,
"type":"suggested"}
},
{upsert:true}, function(err, docs){
socket.emit("toast", "suggested");
io.to(coll).emit("suggested", {id: id, title: title, duration: duration});
});
} else if(docs[0].now_playing === true){
socket.emit("toast", "alreadyplay");
} else{
if(conf[0].vote === false) ListChange.vote(coll, id, guid, socket);
else socket.emit("toast", "listhaspass");
}
});
}
//});
} else {
socket.emit("auth_required");
}
});
});
} else {
var result = {
arr: {
expected: "object",
got: typeof(arr)
},
duration: {
expected: "number or string that can be cast to int",
got: arr.hasOwnProperty("duration") ? typeof(arr.duration) : undefined,
}
};
socket.emit('update_required', result);
}
}
function voteUndecided(msg, coll, guid, offline, socket) {
var socketid = socket.zoff_id;
if(typeof(msg) === 'object' && msg !== undefined && msg !== null){
if(!msg.hasOwnProperty("channel") || !msg.hasOwnProperty("id") ||
!msg.hasOwnProperty("type") || typeof(msg.channel) != "string" ||
typeof(msg.id) != "string" || typeof(msg.type) != "string") {
var result = {
channel: {
expected: "string",
got: msg.hasOwnProperty("channel") ? typeof(msg.channel) : undefined,
},
id: {
expected: "string",
got: msg.hasOwnProperty("id") ? typeof(msg.id) : undefined,
},
type: {
expected: "string",
got: msg.hasOwnProperty("type") ? typeof(msg.type) : undefined,
},
adminpass: {
expected: "adminpass",
got: msg.hasOwnProperty("adminpass") ? typeof(msg.adminpass) : undefined,
},
pass: {
expected: "string",
got: msg.hasOwnProperty("pass") ? typeof(msg.pass) : undefined,
},
};
socket.emit('update_required', result);
return;
}
coll = msg.channel.toLowerCase().replace(/ /g,'');
coll = emojiStrip(coll).toLowerCase();
coll = filter.clean(coll);
Functions.getSessionAdminUser(Functions.getSession(socket), coll, function(userpass, adminpass) {
if(adminpass != "" || msg.adminpass == undefined) {
msg.adminpass = adminpass;
}
if(userpass != "" || msg.pass == undefined) {
msg.pass = userpass;
}
db.collection(coll + "_settings").find({id: "config"}, function(err, docs){
if(docs.length > 0 && (docs[0].userpass == undefined || docs[0].userpass == "" || (msg.hasOwnProperty('pass') && docs[0].userpass == crypto.createHash('sha256').update(Functions.decrypt_string(msg.pass)).digest("base64")))) {
Functions.check_inlist(coll, guid, socket, offline);
if(msg.type == "del") {
ListChange.del(msg, socket, socketid);
} else {
var id = msg.id;
var hash = Functions.hash_pass(Functions.hash_pass(Functions.decrypt_string(msg.adminpass), true));
if(docs !== null && docs.length !== 0 && ((docs[0].vote === true && (hash == docs[0].adminpass || docs[0].adminpass === "")) ||
docs[0].vote === false)) {
ListChange.vote(coll, id, guid, socket);
} else {
socket.emit("toast", "listhaspass");
}
}
} else {
socket.emit("auth_required");
}
});
});
} else {
var result = {
msg: {
expected: "object",
got: typeof(msg)
}
};
socket.emit('update_required', result);
}
}
function shuffle(msg, coll, guid, offline, socket) {
var socketid = socket.zoff_id;
if(!msg.hasOwnProperty("channel") || typeof(msg.channel) != "string") {
var result = {
channel: {
expected: "string",
got: msg.hasOwnProperty("channel") ? typeof(msg.channel) : undefined,
},
adminpass: {
expected: "string",
got: msg.hasOwnProperty("adminpass") ? typeof(msg.adminpass) : undefined,
},
pass: {
expected: "string",
got: msg.hasOwnProperty("pass") ? typeof(msg.pass) : undefined,
},
};
socket.emit('update_required', result);
return;
}
coll = msg.channel.toLowerCase().replace(/ /g,'');
coll = emojiStrip(coll).toLowerCase();
coll = filter.clean(coll);
Functions.getSessionAdminUser(Functions.getSession(socket), coll, function(userpass, adminpass) {
if(adminpass != "" || msg.adminpass == undefined) {
msg.adminpass = adminpass;
}
if(userpass != "" || msg.pass == undefined) {
msg.pass = userpass;
}
db.collection("timeout_api").find({
type: "shuffle",
guid: coll,
}, function(err, docs) {
if(docs.length > 0) {
var date = new Date(docs[0].createdAt);
date.setSeconds(date.getSeconds() + 5);
var now = new Date();
var retry_in = (date.getTime() - now.getTime()) / 1000;
if(retry_in > 0) {
socket.emit("toast", "wait_longer");
return;
}
}
var now_date = new Date();
db.collection("timeout_api").update({type: "shuffle", guid: coll}, {
$set: {
"createdAt": now_date,
type: "shuffle",
guid: coll,
},
}, {upsert: true}, function(err, docs) {
Functions.check_inlist(coll, guid, socket, offline);
var hash;
if(msg.adminpass === "") hash = msg.adminpass;
else hash = Functions.hash_pass(Functions.hash_pass(Functions.decrypt_string(msg.adminpass),true));
db.collection(coll + "_settings").find(function(err, docs){
if(docs.length > 0 && (docs[0].userpass == undefined || docs[0].userpass == "" || (msg.hasOwnProperty('pass') && docs[0].userpass == crypto.createHash('sha256').update(Functions.decrypt_string(msg.pass)).digest("base64")))) {
if(docs !== null && docs.length !== 0 && ((docs[0].adminpass == hash || docs[0].adminpass === "") || docs[0].shuffle === false))
{
db.collection(coll).find({now_playing:false}).forEach(function(err, docs){
if(!docs){
List.send_list(coll, undefined, false, true, false, true);
socket.emit("toast", "shuffled");
return;
}else{
num = Math.floor(Math.random()*1000000);
db.collection(coll).update({id:docs.id}, {$set:{added:num}});
}
});
}else
socket.emit("toast", "wrongpass");
} else {
socket.emit("auth_required");
}
});
var complete = function(tot, curr){
if(tot == curr)
{
List.send_list(coll, undefined, false, true, false);
List.getNextSong(coll);
}
};
});
});
});
}
function del(params, socket, socketid) {
if(params.id){
var coll = emojiStrip(params.channel).toLowerCase();
coll = coll.replace(/_/g, "").replace(/ /g,'');
coll = filter.clean(coll);
db.collection(coll + "_settings").find(function(err, docs){
if(docs !== null && docs.length !== 0 && docs[0].adminpass == Functions.hash_pass(Functions.hash_pass(Functions.decrypt_string(params.adminpass),true)))
{
db.collection(coll).find({id:params.id}, function(err, docs){
var dont_increment = false;
if(docs[0]){
if(docs[0].type == "suggested"){
dont_increment = true;
}
db.collection(coll).remove({id:params.id}, function(err, docs){
socket.emit("toast", "deletesong");
io.to(coll).emit("channel", {type:"deleted", value: params.id});
if(!dont_increment) db.collection("frontpage_lists").update({_id: coll, count: {$gt: 0}}, {$inc: {count: -1}, $set:{accessed: Functions.get_time()}}, {upsert: true}, function(err, docs){});
});
}
});
}
});
}
}
function delete_all(msg, coll, guid, offline, socket) {
var socketid = socket.zoff_id;
if(typeof(msg) == 'object' ) {
if(!msg.hasOwnProperty('channel') || typeof(msg.channel) != "string") {
var result = {
channel: {
expected: "string",
got: msg.hasOwnProperty("channel") ? typeof(msg.channel) : undefined,
},
adminpass: {
expected: "adminpass",
got: msg.hasOwnProperty("adminpass") ? typeof(msg.adminpass) : undefined,
},
pass: {
expected: "string",
got: msg.hasOwnProperty("pass") ? typeof(msg.pass) : undefined,
},
};
socket.emit('update_required', result);
return;
}
if(coll == undefined) {
coll = msg.channel;
}
coll = coll.replace(/ /g,'');
coll = emojiStrip(coll).toLowerCase();
coll = filter.clean(coll);
Functions.getSessionAdminUser(Functions.getSession(socket), coll, function(userpass, adminpass, gotten) {
if(adminpass != "" || msg.adminpass == undefined) {
msg.adminpass = adminpass;
}
if(userpass != "" || msg.pass == undefined) {
msg.pass = userpass;
}
var hash = Functions.hash_pass(Functions.hash_pass(Functions.decrypt_string(msg.adminpass),true));
var hash_userpass = crypto.createHash('sha256').update(Functions.decrypt_string(msg.pass)).digest("base64");
db.collection(coll + "_settings").find(function(err, conf) {
if(conf.length == 1 && conf) {
conf = conf[0];
if(conf.adminpass == hash && conf.adminpass != "" && (conf.userpass == "" || conf.userpass == undefined || (conf.userpass != "" && conf.userpass != undefined && conf.pass == hash_userpass))) {
db.collection(coll).remove({views: {$exists: false}}, {multi: true}, function(err, succ) {
List.send_list(coll, false, true, true, true);
db.collection("frontpage_lists").update({_id: coll}, {$set: {count: 0, accessed: Functions.get_time()}}, {upsert: true}, function(err, docs) {});
socket.emit("toast", "deleted_songs");
});
} else {
socket.emit("toast", "listhaspass");
}
}
});
});
} else {
var result = {
msg: {
expected: "object",
got: typeof(msg)
},
};
socket.emit('update_required', result);
return;
}
}
function vote(coll, id, guid, socket) {
coll = coll.replace(/ /g,'');
db.collection(coll).find({id:id, now_playing: false, type:"video"}, function(err, docs){
if(docs !== null && docs.length > 0 && !Functions.contains(docs[0].guids, guid))
{
db.collection(coll).update({id:id}, {$inc:{votes:1}, $set:{added:Functions.get_time()}, $push :{guids: guid}}, function(err, docs)
{
socket.emit("toast", "voted");
io.to(coll).emit("channel", {type: "vote", value: id, time: Functions.get_time()});
List.getNextSong(coll);
});
}else
{
socket.emit("toast", "alreadyvoted");
}
});
}
module.exports.addPlaylist = addPlaylist;
module.exports.addFromOtherList = addFromOtherList;
module.exports.add_function = add_function;
module.exports.voteUndecided = voteUndecided;
module.exports.shuffle = shuffle;
module.exports.del = del;
module.exports.delete_all = delete_all;
module.exports.vote = vote;

View File

@@ -0,0 +1,246 @@
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(iinp.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 = emojiStrip(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);
Functions.getSessionAdminUser(sessionId, coll, function(userpass, 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 == Functions.hash_pass(Functions.hash_pass(Functions.decrypt_string(adminpass), true))) {
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 = emojiStrip(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);
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 !== "") {
hash = Functions.hash_pass(Functions.hash_pass(Functions.decrypt_string(adminpass), true));
} else {
hash = adminpass;
}
if(userpass != "") {
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.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), params.userpass, coll, function() {
db.collection(coll + "_settings").find(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;

View File

@@ -0,0 +1,39 @@
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("Mail is not configured and wont work");
console.log("Seems you forgot to create a mailconfig.js in /server/config/. Have a look at the mailconfig.example.js.");
}
}
module.exports.requested_change = requested_change;

213
server/handlers/search.js Normal file
View File

@@ -0,0 +1,213 @@
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 key = require(path.join(__dirname, '../config/api_key.js'));
} 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();
}
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&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;
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,
}
}, 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 {
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;
}
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(e);
}
});
}
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.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_error_video = check_error_video;
module.exports.get_correct_info = get_correct_info;

View File

@@ -0,0 +1,111 @@
function thumbnail(msg, coll, guid, offline, socket) {
if(msg.thumbnail != undefined && msg.channel && msg.channel != undefined){
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.userpass == undefined) {
msg.userpass = userpass;
}
if(adminpass != "" || msg.adminpass == undefined) {
msg.adminpass = adminpass;
}
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 = Functions.hash_pass(Functions.hash_pass(Functions.decrypt_string(msg.adminpass),true));
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 == crypto.createHash('sha256').update(Functions.decrypt_string(msg.pass)).digest("base64")))) {
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.userpass == undefined) {
msg.userpass = userpass;
}
if(adminpass != "" || msg.adminpass == undefined) {
msg.adminpass = adminpass;
}
var channel = msg.channel.toLowerCase();
var hash = Functions.hash_pass(Functions.hash_pass(Functions.decrypt_string(msg.adminpass), true));
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 == crypto.createHash('sha256').update(Functions.decrypt_string(msg.pass)).digest("base64")))) {
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");
}
}
module.exports.thumbnail = thumbnail;
module.exports.description = description;

24
server/models/user.js Normal file
View 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);

View File

@@ -0,0 +1,687 @@
var connection_options = {
'sync disconnect on unload':true,
'secure': true,
'force new connection': true
};
var socket = io.connect(window.location.protocol + '//' + window.location.hostname + ':8080', connection_options);
var api_token_list;
$(document).ready(function(){
$('ul.tabs').tabs();
api_token_list = $("#api_token_list").clone();
$("#api_token_list").remove();
loaded();
});
$(document).on("click", "#refresh_all", function(e){
e.preventDefault();
$("#descriptions_cont").empty();
$("#thumbnails_cont").empty();
$(".api_token_container").remove();
$.ajax({
type: "GET",
url: "/api/api_token",
success: function(response) {
if(response.length == 0) {
if(!$(".header-api-fields").hasClass("hide")) {
$(".header-api-fields").addClass("hide");
}
return;
}
$(".header-api-fields").removeClass("hide");
for(var i = 0; i < response.length; i++) {
var to_add = api_token_list.clone();
to_add.find(".api_token_limit").val(response[i].limit);
to_add.attr("id", response[i]._id);
to_add.find(".api_token_name").text(response[i].name);
to_add.find(".api_token_origin").text(response[i].origin);
to_add.find(".api_token_usage").text(response[i].usage);
to_add.find(".update_api_token").attr("id", response[i]._id + "-update");
to_add.find(".api_token_limit").attr("id", response[i]._id + "-limit");
to_add.find(".delete_api_token").attr("id", response[i]._id + "-delete");
to_add.find(".delete_api_token").attr("data-id", response[i]._id);
to_add.find(".update_api_token").attr("data-id", response[i]._id);
if(response[i].active) {
to_add.find(".check").removeClass("hide");
} else {
to_add.find(".uncheck").removeClass("hide");
}
$("#api_keys").append(to_add);
}
},
error: function(err) {
}
});
if(!$(".channel_things").hasClass("hide")) {
$(".channel_things").addClass("hide")
}
$(".preloader-wrapper").removeClass("hide");
$.ajax({
type: "GET",
url: "/api/lists",
success: function(response){
var output_pinned = '<option value="" disabled>Channels</option>';
var output_delete = '<option value="" disabled>Channels</option>';
for(var x = 0; x < response.length; x++){
if(response[x].count > 5){
output_pinned += "<option class='" + response[x]._id + "' value='" + response[x]._id + "'>" + response[x]._id + "</option>";
}
output_delete += "<option class='" + response[x]._id + "' value='" + response[x]._id + "'>" + response[x]._id + "</option>";
}
$("#frontpage_pinned").html(output_pinned);
$("#remove_thumbnail").html(output_delete);
$("#remove_description").html(output_delete);
$("#delete_list_name").html(output_delete);
$("#delete_userpass_name").html(output_delete);
$("#delete_channel_name").html(output_delete);
$("select").material_select();
$(".channel_things").removeClass("hide");
if(!$(".preloader-wrapper").hasClass("hide")) {
$(".preloader-wrapper").addClass("hide");
}
}
});
$.ajax({
type: "GET",
url: "/api/thumbnails",
success: function(response){
if(response.length > 0){
$(".thumbnails-badge").removeClass("hide");
$(".thumbnails-badge").text(response.length);
}
add_to_tab("thumbnails", response);
}
});
$.ajax({
type: "GET",
url: "/api/descriptions",
success: function(response){
if(response.length > 0){
$(".descriptions-badge").removeClass("hide");
$(".descriptions-badge").text(response.length);
}
add_to_tab("descriptions", response);
}
});
$("#listeners").empty();
socket.emit("get_spread");
});
socket.on("spread_listeners", function(obj){
$("#listeners").append("<p>Private listeners: " + obj.offline + "</p>");
$("#listeners").append("<p>Total listeners: " + obj.total + "</p>");
$("#listeners").append("<hr>");
for(var x in obj.online_users){
if(obj.online_users[x]._id != "total_users" && obj.online_users[x].hasOwnProperty("users") && obj.online_users[x].users.length > 0){
$("#listeners").append("<p>" + obj.online_users[x]._id + ": " + obj.online_users[x].users.length + "</p>");
}
}
});
if(!$(".channel_things").hasClass("hide")) {
$(".channel_things").addClass("hide")
}
$(".preloader-wrapper").removeClass("hide");
$(document).on("click", ".update_api_token", function(e) {
e.preventDefault();
var id = $(this).attr("data-id");
var limit = $("#" + id + "-limit").val();
var that = this;
$(that).toggleClass("disabled");
$("#" + id + "-delete").toggleClass("disabled");
$.ajax({
type: "PUT",
url: "api/api_token",
data: {
id: id,
limit: limit,
},
success: function(response) {
if(response == "OK") {
Materialize.toast("Updated limit!", 2000, "green lighten");
} else {
Materialize.toast("Something went wrong...", 2000, "red lighten");
}
$(that).toggleClass("disabled");
$("#" + id + "-delete").toggleClass("disabled");
}
});
});
$(document).on("click", ".delete_api_token", function(e) {
e.preventDefault();
var id = $(this).attr("data-id");
var that = this;
$(that).toggleClass("disabled");
$("#" + id + "-limit").toggleClass("disabled");
$.ajax({
type: "DELETE",
url: "api/api_token",
data: {
id: id
},
success: function(response) {
if(response == "success") {
Materialize.toast("Removed token!", 2000, "green lighten");
$("#" + id).remove();
} else {
Materialize.toast("Something went wrong...", 2000, "red lighten");
$(that).toggleClass("disabled");
$("#" + id + "-limit").toggleClass("disabled");
}
},
});
});
function loaded() {
$.ajax({
type: "GET",
url: "/api/api_token",
success: function(response) {
if(response.length == 0) {
if(!$(".header-api-fields").hasClass("hide")) {
$(".header-api-fields").addClass("hide");
}
return;
}
$(".header-api-fields").removeClass("hide");
for(var i = 0; i < response.length; i++) {
var to_add = api_token_list.clone();
to_add.find(".api_token_limit").val(response[i].limit);
to_add.attr("id", response[i]._id);
to_add.find(".api_token_name").text(response[i].name);
to_add.find(".api_token_usage").text(response[i].usage);
to_add.find(".api_token_origin").text(response[i].origin);
to_add.find(".update_api_token").attr("id", response[i]._id + "-update");
to_add.find(".api_token_limit").attr("id", response[i]._id + "-limit");
to_add.find(".delete_api_token").attr("id", response[i]._id + "-delete");
to_add.find(".delete_api_token").attr("data-id", response[i]._id);
to_add.find(".update_api_token").attr("data-id", response[i]._id);
if(response[i].active) {
to_add.find(".check").removeClass("hide");
} else {
to_add.find(".uncheck").removeClass("hide");
}
$("#api_keys").append(to_add);
}
},
error: function(err) {
}
});
$.ajax({
type: "GET",
url: "/api/lists",
success: function(response){
var output_pinned = '<option value="" disabled selected>Channels</option>';
var output_delete = '<option value="" disabled selected>Channels</option>';
for(var x = 0; x < response.length; x++){
if(response[x].count > 5){
output_pinned += "<option class='" + response[x]._id + "' value='" + response[x]._id + "'>" + response[x]._id + "</option>";
}
output_delete += "<option class='" + response[x]._id + "' value='" + response[x]._id + "'>" + response[x]._id + "</option>";
}
$("#frontpage_pinned").html(output_pinned);
$("#remove_thumbnail").html(output_delete);
$("#remove_description").html(output_delete);
$("#delete_list_name").html(output_delete);
$("#delete_userpass_name").html(output_delete);
$("#delete_channel_name").html(output_delete);
$("select").material_select();
if(!$(".preloader-wrapper").hasClass("hide")) {
$(".preloader-wrapper").addClass("hide")
}
$(".channel_things").removeClass("hide");
}
});
$.ajax({
type: "GET",
url: "/api/names",
success: function(response) {
for(var i = 0; i < response.length; i++) {
var icon = "";
if(response[i].icon && response[i].icon != "") {
icon = "<img class='chat-icon' src='" + response[i].icon + "' alt='" + response[i]._id + "'>";
}
$(".names-container").append("<div class='col s12'><div class='name-chat col s3'>" + icon + response[i]._id + "</div><input type='text' class='" + response[i]._id + "_input col s7'><a class='btn green waves-effect col s2 m1 approve_name' href='#' data-name='" + response[i]._id + "'><i class='material-icons'>check</i></a></div>");
}
},
});
$.ajax({
type: "GET",
url: "/api/thumbnails",
success: function(response){
if(response.length > 0){
$(".thumbnails-badge").removeClass("hide");
$(".thumbnails-badge").text(response.length);
}
add_to_tab("thumbnails", response);
}
});
$.ajax({
type: "GET",
url: "/api/descriptions",
success: function(response){
if(response.length > 0){
$(".descriptions-badge").removeClass("hide");
$(".descriptions-badge").text(response.length);
}
add_to_tab("descriptions", response);
}
});
}
$(document).on("click", ".approve_name", function(e) {
var that = this;
var name = $(that).attr("data-name");
var value = $("." + name + "_input").val();
$.ajax({
type: "POST",
url: "/api/names",
data: {
icon: value,
name: name,
},
success: function(resp) {
if(resp == true) {
Materialize.toast("Approved image!", 2000, "green lighten");
} else {
Materialize.toast("Something went wrong...", 2000, "red lighten");
}
}
});
});
$(document).on("click", ".thumbnail_link", function(e) {
e.preventDefault();
window.open("https:" + this.value,'_blank');
});
function add_to_tab(dest, resp){
for(var x = 0; x < resp.length; x++){
if(dest == "thumbnails"){
$("#" + dest + "_cont").append("<div><div class='col s4 m3'>" + resp[x].channel + "</div><input type='text' readonly class='col s4 m6 thumbnail_link' value='" + resp[x].thumbnail + "'><a class='btn green waves-effect col s2 m1 approve_" + dest + "' href='#' data-channel='" + resp[x].channel + "'><i class='material-icons'>check</i></a><a class='btn red waves-effect col s2 m1 deny_" + dest + "' href='#' data-channel='" + resp[x].channel + "'>X</a></div>");
} else {
$("#" + dest + "_cont").append("<div><div class='col s4 m3'>" + resp[x].channel + "</div><input type='text' readonly class='col s4 m6' value='" + resp[x].description + "'><a class='btn green waves-effect col s2 m1 approve_" + dest + "' href='#' data-channel='" + resp[x].channel + "'><i class='material-icons'>check</i></a><a class='btn red waves-effect col s2 m1 deny_" + dest + "' href='#' data-channel='" + resp[x].channel + "'>X</a></div>");
}
}
}
$(document).on("click", "#get_token", function(e){
e.preventDefault();
$.ajax({
type: "GET",
url: "/api/token",
success: function(response){
if(response != false){
$("#new_token").val(response.token);
$("#get_token").toggleClass("hide");
$("#remove_token").toggleClass("hide");
}
}
})
});
$(document).on("click", "#get_api_token", function(e){
e.preventDefault();
var name = $("#new_api_token_name").val();
if(name == "") {
Materialize.toast("Empty name..!", 2000, "red lighten");
return;
}
$("#new_api_token_name").val("");
$("#get_api_token").toggleClass("disabled");
$.ajax({
type: "POST",
url: "/api/api_token",
data: {
name: name,
},
success: function(response){
if(response != false){
Materialize.toast("Gotten token", 2000, "green lighten");
$("#new_api_token").val(response.token);
$("#get_api_token").toggleClass("disabled");
var to_add = api_token_list;
to_add.attr("id", response._id);
to_add.find(".api_token_name").text(name);
to_add.find(".api_token_usage").text(0);
to_add.find("#delete_api_token").attr("data-id", response._id);
$(".channel_things").append(to_add);
}
}
})
});
$(document).on("click", ".approve_thumbnails", function(e){
e.preventDefault();
var channel = $(this).attr("data-channel");
if(!channel) {
Materialize.toast("Something went wrong...", 2000, "red lighten");
return;
}
var that = this;
$.ajax({
type: "POST",
url: "/api/approve_thumbnail",
data: {
channel: channel
},
success: function(response){
if(response){
$(that).parent().remove();
var length = parseInt($(".thumbnails-badge").text());
length = length - 1;
$(".thumbnails-badge").text(length);
if(length <= 0 && !$(".thumbnails-badge").hasClass("hide")){
$(".thumbnails-badge").addClass("hide");
}
Materialize.toast("Approved Thumbnail!", 2000, "green lighten");
} else {
Materialize.toast("Something went wrong...", 2000, "red lighten");
}
}
});
});
$(document).on("click", ".deny_thumbnails", function(e){
e.preventDefault();
var channel = $(this).attr("data-channel");
if(!channel) {
Materialize.toast("Something went wrong...", 2000, "red lighten");
return;
}
var that = this;
$.ajax({
type: "POST",
url: "/api/deny_thumbnail",
data: {
channel: channel
},
success: function(response){
if(response){
$(that).parent().remove();
var length = parseInt($(".thumbnails-badge").text());
length = length - 1;
$(".thumbnails-badge").text(length);
if(length <= 0 && !$(".thumbnails-badge").hasClass("hide")){
$(".thumbnails-badge").addClass("hide");
}
Materialize.toast("Denied thumbnail!", 2000, "green lighten");
} else {
Materialize.toast("Something went wrong...", 2000, "red lighten");
}
}
});
});
$(document).on("click", ".approve_descriptions", function(e){
e.preventDefault();
var channel = $(this).attr("data-channel");
if(!channel) {
Materialize.toast("Something went wrong...", 2000, "red lighten");
return;
}
var that = this;
$.ajax({
type: "POST",
url: "/api/approve_description",
data: {
channel: channel
},
success: function(response){
if(response){
$(that).parent().remove();
var length = parseInt($(".descriptions-badge").text());
length = length - 1;
$(".descriptions-badge").text(length);
if(length <= 0 && !$(".descriptions-badge").hasClass("hide")){
$(".descriptions-badge").addClass("hide");
}
Materialize.toast("Approved description!", 2000, "green lighten");
} else {
Materialize.toast("Something went wrong...", 2000, "red lighten");
}
}
});
});
$(document).on("click", ".deny_descriptions", function(e){
e.preventDefault();
var channel = $(this).attr("data-channel");
if(!channel) {
Materialize.toast("Something went wrong...", 2000, "red lighten");
return;
}
var that = this;
$.ajax({
type: "POST",
url: "/api/deny_description",
data: {
channel: channel
},
success: function(response){
if(response){
$(that).parent().remove();
var length = parseInt($(".descriptions-badge").text());
length = length - 1;
$(".descriptions-badge").text(length);
if(length <= 0 && !$(".descriptions-badge").hasClass("hide")){
$(".descriptions-badge").addClass("hide");
}
Materialize.toast("Denied description!", 2000, "green lighten");
} else {
Materialize.toast("Something went wrong...", 2000, "red lighten");
}
}
});
});
$(document).on("click", "#remove_description_button", function(e){
e.preventDefault();
var channel = $("#remove_description").val();
if(!channel) {
Materialize.toast("Something went wrong...", 2000, "red lighten");
return;
}
var that = this;
$.ajax({
type: "POST",
url: "/api/remove_description",
data: {
channel: channel
},
success: function(response){
if(response){
Materialize.toast("Removed description!", 2000, "green lighten");
} else {
Materialize.toast("Something went wrong...", 2000, "red lighten");
}
}
});
});
$(document).on("click", "#remove_thumbnail_button", function(e){
e.preventDefault();
var channel = $("#remove_thumbnail").val();
if(!channel) {
Materialize.toast("Something went wrong...", 2000, "red lighten");
return;
}
var that = this;
$.ajax({
type: "POST",
url: "/api/remove_thumbnail",
data: {
channel: channel
},
success: function(response){
if(response){
Materialize.toast("Removed thumbnail!", 2000, "green lighten");
} else {
Materialize.toast("Something went wrong...", 2000, "red lighten");
}
}
});
});
$(document).on("submit", "#delete_channel", function(e){
e.preventDefault();
var to_delete = $("#delete_channel_name").val();
if(!to_delete) {
Materialize.toast("Something went wrong...", 2000, "red lighten");
return;
}
var r = confirm("Delete list " + to_delete + "?");
if (r == true) {
$.ajax({
type: "POST",
url: "/api/delete",
data: {
_id: to_delete
},
success: function(response){
if(response == true){
$.ajax({
type: "GET",
url: "/api/lists",
success: function(response){
var output_pinned = "";
var output_delete = "";
for(var x = 0; x < response.length; x++){
if(response[x].count > 5){
output_pinned += "<option class='" + response[x]._id + "' value='" + response[x]._id + "'>" + response[x]._id + "</option>";
}
output_delete += "<option class='" + response[x]._id + "' value='" + response[x]._id + "'>" + response[x]._id + "</option>";
}
$("#frontpage_pinned").html(output_pinned);
$("#delete_list_name").html(output_delete);
$("#delete_userpass_name").html(output_delete);
$("#delete_channel_name").html(output_delete);
$("select").material_select();
}
});
Materialize.toast("Deleted channel!", 2000, "green lighten");
} else {
Materialize.toast("Something went wrong...", 2000, "red lighten");
}
}
})
}
});
$(document).on("click", "#delete_channel_button", function(e){
e.preventDefault();
$("#delete_channel").submit();
});
$(document).on("click", "#remove_token", function(e){
e.preventDefault();
$.ajax({
type: "GET",
url: "/api/remove_token",
success: function(response){
if(response != false){
$("#new_token").val("");
$("#get_token").toggleClass("hide");
$("#remove_token").toggleClass("hide");
}
}
})
});
$(document).on("submit", "#change_pinned", function(e){
e.preventDefault();
var to_pin = $("#frontpage_pinned").val();
if(!to_pin) {
Materialize.toast("Something went wrong...", 2000, "red lighten");
return;
}
$.ajax({
type: "POST",
url: "/api/pinned",
data: {
_id: to_pin
},
success: function(response){
if(response == true){
Materialize.toast("Pinned channel!", 2000, "green lighten");
} else {
Materialize.toast("Something went wrong...", 2000, "red lighten");
}
}
})
});
$(document).on("click", "#change_pinned_button", function(){
$("#change_pinned").submit();
});
$(document).on("click", "#delete_admin_button", function(){
$("#delete_list").submit();
});
$(document).on("click", "#delete_userpass_button", function(){
$("#delete_userpass").submit();
});
$(document).on("submit", "#delete_list", function(e){
e.preventDefault();
var to_remove_password = $("#delete_list_name").val();
if(!to_remove_password) {
Materialize.toast("Something went wrong...", 2000, "red lighten");
return;
}
$.ajax({
type: "POST",
url: "/api/admin",
data: {
_id: to_remove_password
},
success: function(response){
if(response == true){
Materialize.toast("Removed admin password!", 2000, "green lighten");
} else {
Materialize.toast("Something went wrong...", 2000, "red lighten");
}
}
})
});
$(document).on("submit", "#delete_userpass", function(e){
e.preventDefault();
var to_remove_password = $("#delete_userpass_name").val();
if(!to_remove_password) {
Materialize.toast("Something went wrong...", 2000, "red lighten");
return;
}
$.ajax({
type: "POST",
url: "/api/userpass",
data: {
_id: to_remove_password
},
success: function(response){
if(response == true){
Materialize.toast("Removed userpass password!", 2000, "green lighten");
} else {
Materialize.toast("Something went wrong...", 2000, "red lighten");
}
}
})
});
socket.emit("get_spread");

View File

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View File

Before

Width:  |  Height:  |  Size: 697 B

After

Width:  |  Height:  |  Size: 697 B

View File

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 56 KiB

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 66 KiB

View File

Before

Width:  |  Height:  |  Size: 786 B

After

Width:  |  Height:  |  Size: 786 B

View File

Before

Width:  |  Height:  |  Size: 299 B

After

Width:  |  Height:  |  Size: 299 B

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View File

Before

Width:  |  Height:  |  Size: 980 B

After

Width:  |  Height:  |  Size: 980 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

@@ -0,0 +1,18 @@
$(document).on("click", "#login_button", function(e){
e.preventDefault();
$("#login_form").submit();
})
$(document).ready(function(){
if(window.location.pathname == "/signup/" || window.location.pathname == "/signup"){
$("#login_form").prepend("<input type='text' name='token' placeholder='Token' required autocomplete='off' />");
$("#login_form").attr("action", "/signup");
}
});
$(document).on("submit", "#login_form", function(e){
if(this.password.value == "" || this.username.value == ""){
e.preventDefault();
}
})

View File

@@ -0,0 +1,512 @@
.card-image{
height: 100px;
width: 100px;
background-position: center;
background-size: 180%;
height: 100% !important;
}
.side_away {
-webkit-transition: all .3s !important;
-moz-transition: all .3s !important;
-o-transition: all .3s !important;
transition: all .3s !important;
}
.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:50vw;
height: calc(100vh - 32px);
}
#pageButtons{
text-align: center;
padding-top:15px;
display: flex;
justify-content: space-around;
}
#pageButtons, #pageButtons a{
color:white !important;
}
.prev_page, .next_page{
cursor: pointer;
}
#wrapper{
height:calc(100% - 56px);
}
.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 .3s;
transition: all .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 .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 .3s;
-moz-transition:height .3s;
-o-transition:height .3s;
transition:height .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{
/*background-color:grey;*/
height:100vh;
width:50vw;
overflow:hidden;
}
#zoffbutton{
cursor:pointer;
position: absolute;
bottom: 35px;
left: 10px;
background-image: url('/assets/images/z.svg');
width: 50px;
height: 50px;
background-position: center;
background-size: 135%;
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:50vw;
color:white;
margin-top:-5px;
}
#playpause, #duration, #volume-button
{
float:left;
color:white;
}
#playpause, #volume-button
{
margin-left:10px;
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:5px;
}
#viewers{
float: right;
display: flex;
align-items: center;
}
#play, #pause, #volume-button, #fullscreen
{
font-size:20px;
cursor:pointer;
}
.ui-slider-vertical {
width: .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: .7em;
display: block;
border: 0;
background-position: 0 0;
}
.ui-slider-vertical .ui-slider-handle {
left: -.3em;
margin-left: 0;
margin-bottom: -.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: .7em;
display: block;
border: 0;
background-position: 0 0;
}
.ui-slider-horizontal .ui-slider-handle {
top: -.3em;
margin-left: -.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;
}
#pageNumber{
cursor: default;
color: white;
padding:0;
display: inline-flex;
align-items: center;
height: 36px;
justify-content: center;
}
.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;
}
.prev_page_hide, .prev_page, .first_page, .first_page_hide{
padding:0 1px;
}
.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,.7);
color: white;
padding: 0 5px;
}
/*
.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;
}
}

3795
server/public/assets/css/style.css Executable file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

Before

Width:  |  Height:  |  Size: 322 KiB

After

Width:  |  Height:  |  Size: 322 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,176 @@
<!DOCTYPE html>
<html>
<head>
<title>Zoff OAuth Callback</title>
<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>

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

View 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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 697 B

Some files were not shown because too many files have changed in this diff Show More