diff --git a/app/Http/Controllers/tmp/test.png b/app/Http/Controllers/tmp/test.png
index 0f87524..b9f0b72 100644
Binary files a/app/Http/Controllers/tmp/test.png and b/app/Http/Controllers/tmp/test.png differ
diff --git a/public/njum/css/cstms.css b/public/njum/css/cstms.css
index fce362d..71c98a8 100644
--- a/public/njum/css/cstms.css
+++ b/public/njum/css/cstms.css
@@ -1683,6 +1683,11 @@ div.comment_header {
font-size: 1.6rem;
}
+span.laz0r {
+ font-size: 1.6rem;
+ font-weight: bold;
+}
+
@-webkit-keyframes shoop {
0% { top: 16px }
2% { top: 17px }
diff --git a/public/z0mb/js/blahscript.js b/public/z0mb/js/blahscript.js
new file mode 100644
index 0000000..2cb53c8
--- /dev/null
+++ b/public/z0mb/js/blahscript.js
@@ -0,0 +1,1383 @@
+
+
+function escapeHTML(str) {
+ return str.replace(/[&<>"'`=\/]/g, function(s) {
+ return {
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ '"': '"',
+ "'": ''',
+ '/': '/',
+ '`': '`',
+ '=': '='
+ }[s];
+ });
+}
+
+//Pagination
+var paginate = function(pagination, options) {
+ var type = options.hash.type || 'middle';
+ var ret = '';
+ var pageCount = Number(pagination.pageCount);
+ var page = Number(pagination.page);
+ var limit;
+ if (options.hash.limit) limit = +options.hash.limit;
+ //page pageCount
+ var newContext = {};
+ switch (type) {
+ case 'middle':
+ if (typeof limit === 'number') {
+ var i = 0;
+ var leftCount = Math.ceil(limit / 2) - 1;
+ var rightCount = limit - leftCount - 1;
+ if (page + rightCount > pageCount)
+ leftCount = limit - (pageCount - page) - 1;
+ if (page - leftCount < 1)
+ leftCount = page - 1;
+ var start = page - leftCount;
+ while (i < limit && i < pageCount) {
+ newContext = { n: start };
+ if (start === page) newContext.active = true;
+ ret = ret + options.fn(newContext);
+ start++;
+ i++;
+ }
+ }
+ else {
+ for (var i = 1; i <= pageCount; i++) {
+ newContext = { n: i };
+ if (i === page) newContext.active = true;
+ ret = ret + options.fn(newContext);
+ }
+ }
+ break;
+ case 'previous':
+ if (page === 1) {
+ newContext = { disabled: true, n: 1 }
+ }
+ else {
+ newContext = { n: page - 1 }
+ }
+ ret = ret + options.fn(newContext);
+ break;
+ case 'next':
+ newContext = {};
+ if (page === pageCount) {
+ newContext = { disabled: true, n: pageCount }
+ }
+ else {
+ newContext = { n: page + 1 }
+ }
+ ret = ret + options.fn(newContext);
+ break;
+ case 'first':
+ if (page === 1) {
+ newContext = { disabled: true, n: 1 }
+ }
+ else {
+ newContext = { n: 1 }
+ }
+ ret = ret + options.fn(newContext);
+ break;
+ case 'last':
+ if (page === pageCount) {
+ newContext = { disabled: true, n: pageCount }
+ }
+ else {
+ newContext = { n: pageCount }
+ }
+ ret = ret + options.fn(newContext);
+ break;
+ }
+ return ret;
+};
+
+
+class API {
+ static request(post, base, method, params, callback) {
+ $.ajax({
+ url: '/api/' + base + '/' + method,
+ method: post ? 'POST' : 'GET',
+ data: params,
+ success: cb => {
+ if(cb.error === 'null')
+ callback(true, null, cb.warnings, cb);
+ else
+ callback(false, this.responsify(cb.error), cb.warnings, cb);
+ },
+ error: cb => callback(false, null, null, cb)
+ });
+ }
+ static responsify(response) {
+ var r = (type, text) => ({type: type, text: text});
+ return {
+ not_logged_in: r('error', 'Not logged in (✖╭╮✖)'),
+ invalid_request: r('error', 'Invalid request 【ツ】'),
+ video_not_found: r('error', 'Video not found. Perhaps it has already been deleted'),
+ insufficient_permissions: r('error', 'Insufficient permissions ┌∩┐(◣_◢)┌∩┐'),
+ no_tags_specified: r('error', 'No tags specified')
+ }[response];
+ }
+}
+
+//CSRF Token AjaxSetup
+$(function() {
+ $.ajaxSetup({
+ headers: {
+ 'X-CSRF-TOKEN': $('meta[name="_token"]').attr('content')
+ }
+ });
+});
+
+class Video {
+ constructor() {
+ let match = location.href.match(/(\d+)(?!.*\/.)/);
+ if(!match) return;
+ this.id = match[1];
+ this.user = $('.fa-info-circle').next().children().text().trim();
+ this.tags = $.makeArray($('#tag-display').children().children()).map(el => el.innerText).filter(tag => !!tag);
+ this.api = 'video';
+ this.apiBase = this.api + '/' + this.id;
+ }
+ tag(tags, callback) {
+ var _this = this;
+ function preCallback(success, error, warnings, cb) {
+ if(success) {
+ _this.tags = [];
+ _this.tags = cb.tags.map(tag => tag.name);
+ }
+ callback(success, error, warnings, cb);
+ }
+ tags.length ? API.request(true, this.apiBase, 'tag', {tags: tags}, preCallback) : callback(false, API.responsify('no_tags_specified'), null, null);
+ }
+ untag(tag, callback) {
+ var _this = this;
+ function preCallback(success, error, warnings, cb) {
+ if(success) {
+ _this.tags = [];
+ _this.tags = cb.tags.map(tag => tag.name);
+ }
+ callback(success, error, warnings, cb);
+ }
+ tag = tag.trim();
+ !!tag ? API.request(true, this.apiBase, 'untag', {tag: tag}, preCallback) : callback(false, API.responsify('invalid_request'), null, null);
+ }
+ delete(reason, callback) {
+ reason = reason.trim();
+ !!reason ? API.request(true, this.apiBase, 'delete', {reason: reason}, callback) : callback(false, API.responsify('invalid_request'), null, null);
+ }
+}
+
+function flash(type, message) {
+ var html = '
:REPLACE:
';
+ var alerts = $('.flashcontainer > .flash-inner');
+ if(type === 'error') type = 'danger';
+ alerts.append(html.replace(/:TYPE:/, type).replace(/:REPLACE:/, message));
+ alertrm(jQuery);
+}
+
+window.requestAnimFrame = (function(){
+ return window.requestAnimationFrame
+ || window.webkitRequestAnimationFrame
+ || window.mozRequestAnimationFrame
+ || function(callback) { window.setTimeout(callback, 1000 / 60);};
+})();
+
+if (typeof video !== 'undefined') {
+ video = new Video();
+ if(!video.id) video = null;
+ // the variable is defined
+ var videoElem = document.getElementById('video');
+ videoElem.play();
+ videoElem.addEventListener('mouseover', function() { this.controls = true; });
+ videoElem.volume = 0.3;
+ videoElem.volume = localStorage.getItem("volume") || 1;
+ videoElem.addEventListener("volumechange", ev => {
+ localStorage.setItem("volume", ev.target.volume);
+ });
+ if(videoElem !== null) {
+ if(localStorage.getItem('background') == undefined) {
+ localStorage.setItem('background', 'true');
+ }
+/* var background = localStorage.getItem('background') === 'true';
+ var canvas = document.getElementById('bg');
+ var context = canvas.getContext('2d');
+ var cw = canvas.width = canvas.clientWidth | 0;
+ var ch = canvas.height = canvas.clientHeight | 0; */
+
+/* function animationLoop() {
+ if(videoElem.paused || videoElem.ended || !background)
+ return;
+ context.drawImage(videoElem, 0, 0, cw, ch);
+ window.requestAnimFrame(animationLoop);
+ } */
+
+/* videoElem.addEventListener('play', animationLoop); */
+
+ /*$(window).keypress(function(e) {
+ /* if (e.which == 32) {
+ /* if (videoElem.paused)
+ /* videoElem.play();
+ /* else
+ /* videoElem.pause();
+ /* }
+ });*/
+ }
+};
+
+$('#togglebg').on('click', function (e) {
+ e.preventDefault();
+ background = !background;
+ localStorage.setItem('background', background.toString());
+ if(background)
+ $(canvas).addClass( 'fader-in' ).removeClass('fader-out');
+ else
+ $(canvas).addClass( 'fader-out' ).removeClass('fader-in');
+ animationLoop();
+});
+
+$("[data-toggle=popover]").popover({
+ html: true,
+ content: function() {
+ return $('#popover-content').html();
+ }
+});
+
+$('body').on('click', function (e) {
+ $('[data-toggle="popover"]').each(function () {
+ //the 'is' for buttons that trigger popups
+ //the 'has' for icons within a button that triggers a popup
+ if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
+ $(this).popover('hide');
+ }
+ });
+});
+
+(function ($) {
+ function updaterow(ctx, video) {
+ if($('video').length) {
+ var info = [];
+ if(video.interpret) {
+ info.push(' Artist: ' + video.interpret);
+ }
+ if(video.songtitle) {
+ info.push(' Songtitle: ' + video.songtitle);
+ }
+ if(video.imgsource) {
+ info.push(' Video Source: ' + video.imgsource);
+ }
+ if(video.category.name) {
+ info.push(' Category: ' + video.category.name);
+ }
+ $('span.fa-info-circle').attr('data-content', info.join('
'));
+ }
+ else {
+ var row = ctx.parents('tr');
+ row.find('span').show();
+ row.find('input, select').hide();
+ row.find('.vinterpret').html(video.interpret || '');
+ row.find('.vsongtitle').html(video.songtitle || '');
+ row.find('.vimgsource').html(video.imgsource || '');
+ row.find('.vcategory').html('' + video.category.name + '');
+ }
+ }
+
+ var indexform = $('.indexform, #webmedit');
+ $('.indexedit').find('input, select').hide();
+ if(indexform.length) {
+ var row = $('tr');
+ row.on('dblclick touchdown', function(e) {
+ var self = $(this);
+ self.find('input, select').show();
+ self.find('span').hide();
+ });
+ }
+ indexform.on('submit', function (e) {
+ var self = $(this);
+ e.preventDefault();
+ $.ajax({
+ type: 'POST',
+ url: self.attr('action'),
+ data: self.serialize()
+ }).done(function (data) {
+ flash('success', 'Video successfully updated');
+ updaterow(self, data);
+ self.find('#webmeditmodal');
+ }).fail(function(){
+ flash('error', 'Error updating video');
+ self.find('#webmeditmodal');
+ });
+ });
+})(jQuery);
+
+(function ($) {
+ $(':not(form)[data-confirm]').on('click touchdown', function () {
+ return confirm($(this).data('confirm'));
+ });
+})(jQuery);
+
+var alertrm = function ($) {
+ $('.alert').each(function (index) {
+ $(this).delay(3000 + index * 1000).slideUp(300, function() { $(this).remove(); });
+ });
+};
+alertrm(jQuery);
+
+
+//upload
+$(function() {
+ if(!/\/upload/.test(location.href))
+ return;
+ var defaultPreview = $('#dragndrop-text').html();
+ var defaultDragNDropColor = $('#dragndrop').css('color');
+ var defaultDragNDropBorderColor = $('#dragndrop').css('border-left-color');
+ var defaultDragNDropBackgroundColor = $('#dragndrop').css('background-color');
+ var counter = 0;
+ var currentFile;
+ var jqXHR;
+ var tags = $('#tags_upload');
+ var nsfwCheckbox = $('#nsfw');
+ function applyDefaultDragNDropCSS() {
+ $('#dragndrop').css({
+ 'color': defaultDragNDropColor,
+ 'border-color': defaultDragNDropBorderColor,
+ 'background-color': defaultDragNDropBackgroundColor
+ });
+ }
+ function humanFileSize(size) {
+ var i = Math.floor(Math.log(size) / Math.log(1024));
+ return (size / Math.pow(1024, i)).toFixed(2) + ' ' + ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'][i];
+ }
+ function dragndropLinkClickHandler(e) {
+ e.preventDefault();
+ $('input[type="file"]').trigger('click');
+ }
+ function restoreDefaultPreview() {
+ $('#dragndrop-link').on('click', dragndropLinkClickHandler);
+ $('#dragndrop-link').attr('href', '#');
+ $('#dragndrop-text').html(defaultPreview);
+ }
+ function createPreview(file) {
+ $('#dragndrop-link').removeAttr('href').off('click');
+ $('#dragndrop-text').html('' + file.name + ' — ' + humanFileSize(file.size) + ' — ');
+ $('#video_preview').prop('volume', 0);
+ $('#dragndrop-clear').on('click', function(e) {
+ e.preventDefault();
+ e.stopPropagation();
+ currentFile = null;
+ $(this).off('click');
+ applyDefaultDragNDropCSS();
+ restoreDefaultPreview();
+ if(jqXHR && jqXHR.statusText != "abort") {
+ jqXHR.abort();
+ jqXHR = null;
+ }
+ });
+ }
+ function checkFile(file) {
+ var maxFileSize = 1e8;
+ var tooBig = file.size > maxFileSize;
+ var invalid = file.type !== "video/webm";
+ if((tooBig && $('#dragndrop').data('uploadlimit')) || invalid) {
+ flash('error', invalid ? 'Invalid file' : `File too big. Max ${humanFileSize(maxFileSize)}`);
+ applyDefaultDragNDropCSS();
+ return false;
+ }
+ return true;
+ }
+ function submitForm(videotitle, interpret, songtitle, imgsource, category, tags, file) {
+ var lastState = {
+ 'loaded': 0,
+ 'secondsElapsed': 0
+ };
+ var speed = [];
+ var lastSpeedIndex = 0;
+ function interval() {
+ var avgSpeed = 0;
+ var length = speed.length;
+ var i;
+ for(i = lastSpeedIndex; i < length; i++)
+ avgSpeed += speed[i];
+ avgSpeed = avgSpeed / (i - lastSpeedIndex);
+ lastSpeedIndex = i;
+ $('#upload-stats').text('Speed: ' + humanFileSize(Math.floor(avgSpeed)) + '/s Uploaded: ' + humanFileSize(lastState.loaded));
+ }
+ var statsInterval;
+ var formData = new FormData();
+ formData.append('videotitle', videotitle);
+ formData.append('interpret', interpret);
+ formData.append('songtitle', songtitle);
+ formData.append('imgsource', imgsource);
+ formData.append('category', category);
+ formData.append('tags', tags);
+ formData.append('file', file);
+ $('.progress-striped, #upload-stats').css('opacity', 0).slideDown('fast').animate({opacity: 1}, {queue: false, duration: 'fast'});
+ jqXHR = $.ajax({
+ url: '/api/video/upload',
+ type: 'POST',
+ data: formData,
+ processData: false,
+ contentType: false,
+ success: function(cb) {
+ switch(cb.error) {
+ case 'null':
+ if(cb.video_id) {
+ flash('success', 'Upload successful: /' + cb.video_id + '. Redirect in 3 seconds...');
+ setTimeout(function() {
+ location.href = '/' + cb.video_id;
+ }, 3000);
+ }
+ else
+ flash('error', 'Upload failed');
+ break;
+ case 'invalid_request':
+ flash('error', 'Invalid request');
+ break;
+ case 'not_logged_in':
+ flash('error', 'Not logged in');
+ break;
+ case 'uploadlimit_reached':
+ flash('error', 'Uploadlimit reached');
+ break;
+ case 'invalid_file':
+ flash('error', 'Invalid file');
+ break;
+ case 'file_too_big':
+ flash('error', 'File too big. Check the max upload size.');
+ break;
+ case 'already_exists':
+ if(cb.video_id)
+ flash('error', 'Video already exists: /' + cb.video_id + '');
+ else
+ flash('error', 'Video already existed but has been deleted');
+ break;
+ case 'erroneous_file_encoding':
+ flash('error', 'Erroneous file encoding. Try reencoding it');
+ break;
+ default:
+ flash('error', 'Upload failed');
+ break;
+ }
+ if(cb.error != 'null') {
+ $('.progress-bar-custom').css('background-color', 'red');
+ $('.progress-bar-custom').text('Upload failed');
+ }
+ $('#upload-stats').text('Speed: ' + humanFileSize(Math.floor(speed.average())) + '/s Uploaded: ' + humanFileSize(currentFile.size));
+ },
+ error: function(jqXHR, status, error) {
+ jqXHR = null;
+ if(error == 'abort') {
+ flash('info', 'Upload aborted');
+ return;
+ }
+ flash('error', 'Upload failed');
+ $('.progress-bar-custom').css('background-color', 'red');
+ $('.progress-bar-custom').text('Upload failed');
+ },
+ complete: function() {
+ clearInterval(statsInterval);
+ },
+ xhr: function() {
+ var xhr = $.ajaxSettings.xhr();
+ var started_at = new Date();
+ $('.progress-bar-custom').css('background-color', 'rgba(47, 196, 47, 1)');
+ xhr.upload.onprogress = function(e) {
+ var percentage = Math.floor(e.loaded / e.total * 100);
+ var secondsElapsed = (new Date().getTime() - started_at.getTime()) / 1000;
+ var bytesPerSecond = (e.loaded - lastState.loaded) / (secondsElapsed - lastState.secondsElapsed);
+ $('.progress-bar-custom').css('width', percentage + '%');
+ $('.progress-bar-custom').text(percentage + '%');
+ lastState.secondsElapsed = secondsElapsed;
+ lastState.loaded = e.loaded;
+ speed.push(bytesPerSecond);
+ if(!statsInterval) {
+ interval();
+ statsInterval = setInterval(interval, 500);
+ }
+ };
+ return xhr;
+ }
+ });
+ }
+ $('input[type="file"]').on('change', function(e) {
+ if(!this.files.length)
+ return;
+ var file = this.files[0];
+ if(checkFile(file)) {
+ currentFile = file;
+ createPreview(file);
+ }
+ $(this).wrap('