WIP
This commit is contained in:
parent
d6a846a5f0
commit
a5c4be914b
76
twitch/customEmoteWall.js
Normal file
76
twitch/customEmoteWall.js
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
(function() {
|
||||||
|
|
||||||
|
function getEmotes(event, message){
|
||||||
|
var emotes = event.getTags().get('emotes'),
|
||||||
|
str = message,
|
||||||
|
i;
|
||||||
|
|
||||||
|
if (emotes.length() > 0) {
|
||||||
|
emotes = emotes.replaceAll('[0-9]+:', '').split('/');
|
||||||
|
for (i in emotes) {
|
||||||
|
str = str.replace(getWordAt(message, parseInt(emotes[i].split('-')[0])), '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function sendData(tpe, data) {
|
||||||
|
$.panelsocketserver.sendJSONToAll(JSON.stringify({
|
||||||
|
'eventFamily': 'emote',
|
||||||
|
'eventType': tpe,
|
||||||
|
'data': data
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
$.bind('ircChannelMessage', function(event){
|
||||||
|
var sender = event.getSender(),
|
||||||
|
message = event.getMessage().toLowerCase(),
|
||||||
|
messageLength = message.length(),
|
||||||
|
tags = event.getTags();
|
||||||
|
$.consoleLn(message)
|
||||||
|
$.consoleLn(tags)
|
||||||
|
})
|
||||||
|
|
||||||
|
$.bind('command', function(event) {
|
||||||
|
|
||||||
|
const sender = "" + event.getSender().toLowerCase(),
|
||||||
|
command = event.getCommand(),
|
||||||
|
args = event.getArgs(),
|
||||||
|
action = args[0],
|
||||||
|
value = args[1];
|
||||||
|
|
||||||
|
if (command.equalsIgnoreCase('overlay')) {
|
||||||
|
if (!action) {
|
||||||
|
$.say($.whisperPrefix(sender) + $.lang.get('customOverlay.help', ' Use "!overlay [follow | subscribe | donation | timer] value" to set overlay data.'));
|
||||||
|
} else if (action.equalsIgnoreCase('follow')) {
|
||||||
|
sendData(action, value);
|
||||||
|
} else if (action.equalsIgnoreCase('subscribe')) {
|
||||||
|
sendData(action, value);
|
||||||
|
} else if (action.equalsIgnoreCase('donation')) {
|
||||||
|
sendData(action, value);
|
||||||
|
} else if (action.equalsIgnoreCase('timer')) {
|
||||||
|
sendData(action, new Date(Date.now().getTime()+value*1000*60));
|
||||||
|
} else {
|
||||||
|
$.say($.whisperPrefix(sender) + $.lang.get('customOverlay.help'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$.bind('twitchFollow', function(event) {
|
||||||
|
sendData('follow', event.getFollower());
|
||||||
|
});
|
||||||
|
$.bind('twitchSubscriber', function(event) {
|
||||||
|
sendData('subscribe', event.getSubscriber());
|
||||||
|
});
|
||||||
|
|
||||||
|
$.bind('initReady', function() {
|
||||||
|
$.registerChatCommand('./custom/custom/customOverlay.js', 'overlay');
|
||||||
|
|
||||||
|
$.registerChatSubcommand('overlay', 'follow', 2);
|
||||||
|
$.registerChatSubcommand('overlay', 'subscribe', 2);
|
||||||
|
$.registerChatSubcommand('overlay', 'donation', 2);
|
||||||
|
$.registerChatSubcommand('overlay', 'timer', 2);
|
||||||
|
});
|
||||||
|
|
||||||
|
})();
|
32
web/emotewall/index.html
Normal file
32
web/emotewall/index.html
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>EmoteWall</title>
|
||||||
|
<!-- Load our styles -->
|
||||||
|
<style>body {margin:0;overflow:hidden;}</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<!-- Main body -->
|
||||||
|
<body>
|
||||||
|
<div class="main">
|
||||||
|
<canvas id="wall"></canvas>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- jQuery -->
|
||||||
|
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||||
|
<!-- Load jQuery UI -->
|
||||||
|
<script src="https://code.jquery.com/ui/1.13.1/jquery-ui.min.js"></script>
|
||||||
|
<!-- Load Reconnecting socket -->
|
||||||
|
<script src="/common/reconnecting-websocket/reconnectingWS.min.js"></script>
|
||||||
|
<!-- Load Bot config file -->
|
||||||
|
<script src="/common/js/wsConfig.js"></script>
|
||||||
|
|
||||||
|
<!-- Load functions copied out of panel dir, since can't directly read panel dir (http auth problem) -->
|
||||||
|
<script src="/custom/js/socketWrapper.js"></script>
|
||||||
|
|
||||||
|
<!-- Load our script -->
|
||||||
|
<script src="index.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
258
web/emotewall/index.js
Normal file
258
web/emotewall/index.js
Normal file
@ -0,0 +1,258 @@
|
|||||||
|
$(function () {
|
||||||
|
|
||||||
|
const SEVENTV_GLOBAL_URL = "https://api.7tv.app/v2/emotes/global";
|
||||||
|
const SEVENTV_CHANNEL_URL = "https://api.7tv.app/v2/users/" + "..." + "/emotes";
|
||||||
|
const FFZ_GLOBAL_URL = "https://api.frankerfacez.com/v1/set/global";
|
||||||
|
const FFZ_CHANNEL_URL = "https://api.frankerfacez.com/v1/room/" + "...";
|
||||||
|
const BTTV_GLOBAL_URL = "https://api.betterttv.net/3/cached/emotes/global";
|
||||||
|
const BTTV_CHANNEL_URL = "https://api.betterttv.net/3/cached/users/twitch/" + "...";
|
||||||
|
|
||||||
|
const webSocket = window.socket;
|
||||||
|
const emote_str = ["peepo", 'nod']
|
||||||
|
const emote_url = ['https://cdn.7tv.app/emote/603cac391cd55c0014d989be/2x', 'https://cdn.7tv.app/emote/60ae4bb30e35477634610fda/1x']
|
||||||
|
var img_map = {};
|
||||||
|
|
||||||
|
var lastframe = 0;
|
||||||
|
var preloaded = false, initialized = false;
|
||||||
|
var mode = "rain" || "bounce" || "explosion" || "firework" || "...";
|
||||||
|
|
||||||
|
var particles = [];
|
||||||
|
|
||||||
|
|
||||||
|
const canvas = document.getElementById('wall');
|
||||||
|
const ctx = canvas.getContext('2d');
|
||||||
|
const resizeCanvas = () => {
|
||||||
|
canvas.width = window.innerWidth-8;
|
||||||
|
canvas.height = window.innerHeight-8;
|
||||||
|
}
|
||||||
|
window.addEventListener('resize', resizeCanvas, false);
|
||||||
|
resizeCanvas();
|
||||||
|
|
||||||
|
function loadImages(strs, urls) {
|
||||||
|
let loadcount = 0, loadtotal = urls.length;
|
||||||
|
preloaded = false;
|
||||||
|
var loadedimages = {};
|
||||||
|
for (let i=0; i<urls.length; i++) {
|
||||||
|
var image = new Image();
|
||||||
|
image.onload = function () {
|
||||||
|
loadcount++;
|
||||||
|
if (loadcount == loadtotal) preloaded = true;
|
||||||
|
};
|
||||||
|
image.src = urls[i];
|
||||||
|
loadedimages[strs[i]] = image;
|
||||||
|
}
|
||||||
|
return loadedimages;
|
||||||
|
}
|
||||||
|
img_map = loadImages(emote_str, emote_url)
|
||||||
|
|
||||||
|
|
||||||
|
const part_speed = 50;
|
||||||
|
const part_bounce_el = 0.9
|
||||||
|
|
||||||
|
const tWave = (t) => (t<0 || t>8 )? 0 : (t<2 ? t/2 : (t>6 ? (8-t)/2 : 1))
|
||||||
|
|
||||||
|
class Particle {
|
||||||
|
constructor(emote,data){
|
||||||
|
this.size = 64;
|
||||||
|
this.data = data;
|
||||||
|
this.x = Math.random() * canvas.width - this.size;
|
||||||
|
this.y = Math.random() * canvas.height - this.size;
|
||||||
|
this.vx = this.vy = 0;
|
||||||
|
this.ax = this.ay = 0;
|
||||||
|
this.emote = emote;
|
||||||
|
this.time = 0;
|
||||||
|
particles.push(this);
|
||||||
|
setTimeout(()=>{particles.pop()}, 10000);
|
||||||
|
}
|
||||||
|
|
||||||
|
draw(){
|
||||||
|
ctx.globalAlpha = tWave(this.time);
|
||||||
|
if(img_map[this.emote])
|
||||||
|
ctx.drawImage(img_map[this.emote], this.x, this.y, this.size, this.size);
|
||||||
|
}
|
||||||
|
|
||||||
|
update(tick){
|
||||||
|
this.time += tick;
|
||||||
|
this.vx += tick * this.ax;
|
||||||
|
this.vy += tick * this.ay;
|
||||||
|
this.x += tick * this.vx * part_speed;
|
||||||
|
this.y += tick * this.vy * part_speed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class RainP extends Particle {
|
||||||
|
constructor(emote,data) {
|
||||||
|
super(emote,data)
|
||||||
|
this.x = Math.random() * canvas.width;
|
||||||
|
this.y = - this.size;
|
||||||
|
this.vx = 0;
|
||||||
|
this.vy = 15;
|
||||||
|
this.ax = 0, this.ay = 0;
|
||||||
|
this.time = 2;
|
||||||
|
}
|
||||||
|
update(tick){
|
||||||
|
super.update(tick)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BounceP extends Particle {
|
||||||
|
constructor(emote,data) {
|
||||||
|
super(emote,data)
|
||||||
|
this.x = Math.random() * canvas.width;
|
||||||
|
this.y = Math.random() * canvas.height;
|
||||||
|
this.vx = (Math.random() * 2 - 1) *15;
|
||||||
|
this.vy = (Math.random() * 2 - 1) * 15;
|
||||||
|
this.ax = 0, this.ay = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
update(tick){
|
||||||
|
super.update(tick);
|
||||||
|
if (this.x < 0) {
|
||||||
|
this.vx = this.vx < 0 ? -this.vx * part_bounce_el : this.vx;
|
||||||
|
this.x = 0;
|
||||||
|
} else if (this.x + this.size > canvas.width) {
|
||||||
|
this.vx = this.vx > 0 ? -this.vx * part_bounce_el : this.vx;
|
||||||
|
this.x = canvas.width - this.size;
|
||||||
|
}
|
||||||
|
if (this.y <0) {
|
||||||
|
this.vy = this.vy < 0 ? -this.vy * part_bounce_el : this.vy;
|
||||||
|
this.y = 0;
|
||||||
|
} else if (this.y + this.size > canvas.height) {
|
||||||
|
this.vy = this.vy > 0 ? -this.vy * part_bounce_el : this.vy;
|
||||||
|
this.y = canvas.height - this.size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BounceGP extends BounceP {
|
||||||
|
constructor(emote,data) {
|
||||||
|
super(emote,data)
|
||||||
|
this.x = Math.random() * canvas.width;
|
||||||
|
this.y = Math.random() * canvas.height;
|
||||||
|
this.vx = Math.random() * 20 - 10;
|
||||||
|
this.vy = Math.random() * 20 - 10;
|
||||||
|
this.ax = 0, this.ay = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
update(tick){
|
||||||
|
super.update(tick);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FireworkP extends Particle {
|
||||||
|
constructor(emote,data) {
|
||||||
|
super(emote,data)
|
||||||
|
this.x = canvas.width/2;
|
||||||
|
this.y = canvas.height;
|
||||||
|
this.vx = 0;
|
||||||
|
this.vy = -15;
|
||||||
|
this.ax = 0;
|
||||||
|
this.ay = 0;
|
||||||
|
this.time=4;
|
||||||
|
this.boom = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
update(tick){
|
||||||
|
super.update(tick);
|
||||||
|
if(this.y <= canvas.height/4 && !this.boom){
|
||||||
|
let angle = Math.random() *2 * Math.PI;
|
||||||
|
this.vx = Math.sin(angle) * (Math.random()*4 + 10);
|
||||||
|
this.vy = Math.cos(angle) * (Math.random()*4 + 10);
|
||||||
|
this.ay = 10;
|
||||||
|
this.boom = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
|
||||||
|
new RainP('peepo', {});
|
||||||
|
new RainP('peepo', {});
|
||||||
|
new RainP('peepo', {});
|
||||||
|
new RainP('peepo', {});
|
||||||
|
new RainP('peepo', {});
|
||||||
|
new BounceGP('nod', {});
|
||||||
|
new BounceP('nod', {});
|
||||||
|
new FireworkP('nod', {});
|
||||||
|
new FireworkP('nod', {});
|
||||||
|
new FireworkP('nod', {});
|
||||||
|
new FireworkP('nod', {});
|
||||||
|
new FireworkP('nod', {});
|
||||||
|
new FireworkP('nod', {});
|
||||||
|
new FireworkP('nod', {});
|
||||||
|
new FireworkP('nod', {});
|
||||||
|
new FireworkP('nod', {});
|
||||||
|
new FireworkP('nod', {});
|
||||||
|
new FireworkP('nod', {});
|
||||||
|
new FireworkP('nod', {});
|
||||||
|
new FireworkP('nod', {});
|
||||||
|
new FireworkP('nod', {});
|
||||||
|
new FireworkP('nod', {});
|
||||||
|
new FireworkP('nod', {});
|
||||||
|
new FireworkP('nod', {});
|
||||||
|
new FireworkP('nod', {});
|
||||||
|
new FireworkP('nod', {});
|
||||||
|
new FireworkP('nod', {});
|
||||||
|
new FireworkP('nod', {});
|
||||||
|
main(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function main(tframe) {
|
||||||
|
window.requestAnimationFrame(main);
|
||||||
|
|
||||||
|
var dt = (tframe - lastframe) / 1000;
|
||||||
|
lastframe = tframe;
|
||||||
|
|
||||||
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
|
if (!initialized) {
|
||||||
|
if (preloaded) {
|
||||||
|
setTimeout(function(){initialized = true;}, 1000);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
particles.forEach((particle) => {
|
||||||
|
particle.update(dt);
|
||||||
|
});
|
||||||
|
particles.forEach((particle) => {
|
||||||
|
particle.draw();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init()
|
||||||
|
|
||||||
|
const handleSocketMessage = (e)=>{
|
||||||
|
try {
|
||||||
|
let rawMessage = e.data,
|
||||||
|
message = JSON.parse(rawMessage);
|
||||||
|
|
||||||
|
if(!message.hasOwnProperty('eventFamily') || message.eventFamily != 'emotewall' ||
|
||||||
|
!message.hasOwnProperty('eventType') || !message.hasOwnProperty('data'))
|
||||||
|
return;
|
||||||
|
|
||||||
|
console.log(message.eventType, message.data)
|
||||||
|
if(message.eventType == 'message') {
|
||||||
|
//....
|
||||||
|
}
|
||||||
|
} catch (ex) {
|
||||||
|
console.log(ex)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
jQuery(async ()=>{
|
||||||
|
|
||||||
|
try{
|
||||||
|
socket.addFamilyHandler("overlay", handleSocketMessage);
|
||||||
|
if(socket){
|
||||||
|
while(socket.getReadyState() === 0){
|
||||||
|
await new Promise(r => setTimeout(r, 500));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}catch(e) {console.log(e)}
|
||||||
|
})
|
||||||
|
|
||||||
|
});
|
Loading…
x
Reference in New Issue
Block a user