init commit

This commit is contained in:
zino
2021-02-16 23:07:41 +01:00
parent ec3fc78e0f
commit 12b4ef5db4
5000 changed files with 2596132 additions and 0 deletions

View File

@@ -0,0 +1,162 @@
/* CSS that always load even with a dark/light theme. */
.loader {
position: absolute;
left: 50%;
top: 50%;
z-index: 1;
margin: -75px 0 0 -75px;
border: 16px solid #f2f2f2;
border-radius: 50%;
border-top: 16px solid #6441A4;
width: 120px;
height: 120px;
-webkit-animation: spin 2s linear infinite;
animation: spin 2s linear infinite;
}
.load-ajax {
text-align: center;
}
.load-ajax-text {
margin-top: -40px;
}
.spinner,
.spinner:after {
border-radius: 50%;
width: 5em;
height: 5em;
}
.spinner {
margin: 60px auto;
font-size: 10px;
position: relative;
text-indent: -9999em;
border-top: 1.1em solid rgba(100,65,165, 0.2);
border-right: 1.1em solid rgba(100,65,165, 0.2);
border-bottom: 1.1em solid rgba(100,65,165, 0.2);
border-left: 1.1em solid #6441a5;
-webkit-transform: translateZ(0);
-ms-transform: translateZ(0);
transform: translateZ(0);
-webkit-animation: load8 1.1s infinite linear;
animation: load8 1.1s infinite linear;
}
@-webkit-keyframes load8 {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes load8 {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
.resize-drag {
background-color: #29e;
color: white;
font-size: 20px;
font-family: sans-serif;
border-radius: 8px;
padding: 20px;
margin: 30px 20px;
touch-action: none;
width: 120px;
/* This makes things *much* easier */
box-sizing: border-box;
}
.resize-container {
display: inline-block;
width: 100%;
height: 240px;
}
#stream-game {
border-radius: 0;
}
.easy-autocomplete,
.easy-autocomplete input {
width: 100% !important;
box-shadow: none !important;
}
.easy-autocomplete-container ul {
max-height: 130px;
border-bottom-color: #000;
overflow-y: scroll;
overflow-x: hidden;
}
@-webkit-keyframes spin {
0% {
-webkit-transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
}
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
/* width */
::-webkit-scrollbar {
width: 10px;
}
/* Track */
::-webkit-scrollbar-track {
background: #f1f1f1;
}
/* Handle */
::-webkit-scrollbar-thumb {
background: #888;
}
/* Handle on hover */
::-webkit-scrollbar-thumb:hover {
background: #555;
}
select {
cursor: pointer;
}
/* Auto cut long text */
.auto-cut {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
/* Remove bold on sidebar label */
.control-sidebar-subheading > label:not([class]) {
font-weight: unset;
}

View File

@@ -0,0 +1 @@
@-webkit-keyframes load8{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes load8{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg)}to{-webkit-transform:rotate(360deg)}}@keyframes spin{0%{transform:rotate(0deg)}to{transform:rotate(360deg)}}.loader{position:absolute;left:50%;top:50%;z-index:1;margin:-75px 0 0 -75px;border:16px solid #f2f2f2;border-radius:50%;border-top:16px solid #6441a4;width:120px;height:120px;-webkit-animation:spin 2s linear infinite;animation:spin 2s linear infinite}.load-ajax{text-align:center}.load-ajax-text{margin-top:-40px}.spinner,.spinner:after{border-radius:50%;width:5em;height:5em}.spinner{margin:60px auto;font-size:10px;position:relative;text-indent:-9999em;border-top:1.1em solid rgba(100,65,165,.2);border-right:1.1em solid rgba(100,65,165,.2);border-bottom:1.1em solid rgba(100,65,165,.2);border-left:1.1em solid #6441a5;-webkit-transform:translateZ(0);-ms-transform:translateZ(0);transform:translateZ(0);-webkit-animation:load8 1.1s infinite linear;animation:load8 1.1s infinite linear}.resize-drag{background-color:#29e;color:#fff;font-size:20px;font-family:sans-serif;border-radius:8px;padding:20px;margin:30px 20px;touch-action:none;width:120px;box-sizing:border-box}.resize-container{display:inline-block;width:100%;height:240px}#stream-game{border-radius:0}.easy-autocomplete,.easy-autocomplete input{width:100%!important;box-shadow:none!important}.easy-autocomplete-container ul{max-height:130px;border-bottom-color:#000;overflow-y:scroll;overflow-x:hidden}::-webkit-scrollbar{width:10px}::-webkit-scrollbar-track{background:#f1f1f1}::-webkit-scrollbar-thumb{background:#888}::-webkit-scrollbar-thumb:hover{background:#555}select{cursor:pointer}.auto-cut{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.control-sidebar-subheading>label:not([class]){font-weight:unset}

View File

@@ -0,0 +1,285 @@
textarea {
resize: vertical;
max-height: 300px;
min-height: 50px;
}
a:hover,
a:active,
a:focus {
color: #333333;
}
label {
font-weight: bold;
}
.pretty.p-icon .state .icon:before {
color: #fff !important;
}
/* Fix large icon on dashboard number panels */
.small-box .icon-override {
font-size: 85px !important;
}
.small-box:hover .icon-override {
font-size: 90px !important;
}
.content-wrapper {
background-color: #f1f1f1;
}
.wrapper {
overflow: hidden;
}
/* Switch */
.switch {
top: 7px;
margin-right: 5px;
position: relative;
display: inline-block;
width: 30px;
height: 16px;
}
.switch input {
display: none;
}
.slider {
border-radius: 24px;
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
border-radius: 40%;
position: absolute;
content: "";
height: 8px;
width: 8px;
left: 4px;
bottom: 4px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
input:checked+.slider {
background-color: #6441a5;
}
input:focus+.slider {
box-shadow: 0 0 1px #2196F3;
}
input:checked+.slider:before {
-webkit-transform: translateX(26px);
-ms-transform: translateX(26px);
transform: translateX(13px);
}
/* Event log */
.event-log {
height: 150px;
overflow: auto;
position: relative;
}
ul.recent-events {
padding: 0;
}
ul.recent-events li {
list-style: none;
margin-bottom: 5px;
line-height: 20px;
}
ul.recent-events li p {
font-size: 14px;
margin-bottom: 0;
}
ul.recent-events li p span {
margin-right: 3px;
}
span.event-date {
color: #999;
}
/* Datatables */
.default-table {
width: 46px;
min-width: 46px;
}
.default-table-large {
width: 47px;
min-width: 47px;
}
.datatables_filter,
.dataTables_filter {
float: left;
text-align: left;
}
.pagination>.active>a {
background-color: #6441a5;
border-color: #4b3671;
}
.pagination>.active>a:focus,
.pagination>.active>a:hover,
.pagination>.active>span,
.pagination>.active>span:focus,
.pagination>.active>span:hover {
background-color: #6441a5;
border-color: #4b3671;
}
.dataTable th,
.dataTable td {
max-width: 25px;
overflow: hidden !important;
text-overflow: ellipsis;
white-space: nowrap !important;
}
/* disabled class */
.off {
display: none;
}
/* Buttons */
.btn:hover,
.btn-box-tool:hover {
background-color: transparent !important;
}
li.disabled {
cursor: not-allowed;
}
a.disabled {
pointer-events: none;
}
.panel,
.panel-default,
.panel-group {
border-radius: 0 !important;
}
/* Sweetalert */
.swal-modal {
border-radius: 0;
}
.swal-button--cancel,
.swal-button--cancel:focus,
.swal-button--cancel:active {
background-color: #f4f4f4;
color: #444;
border: 1px solid #ddd;
border-radius: 0;
}
.swal-button--cancel:hover {
background-color: #e7e7e7;
color: #444;
border: 1px solid #ddd;
border-radius: 0;
}
.swal-button--danger,
.swal-button--danger:focus,
.swal-button--danger:active {
background-color: #dd4b39 !important;
border: 1px solid #d73925 !important;
border-radius: 0;
}
.swal-button--danger:hover {
background-color: #d73925 !important;
border: 1px solid #d73925 !important;
border-radius: 0;
}
.swal-button--confirm,
.swal-button--confirm:focus,
.swal-button--confirm:active {
background-color: #6441a5;
text-decoration: none;
border: 1px solid #2f098c;
border-radius: 0;
}
.swal-button--confirm:hover {
background-color: #6b49ab;
text-decoration: none;
border: 1px solid #2f098c;
border-radius: 0;
}
.swal-button {
height: 34px;
padding: 6px 12px;
font-size: 14px;
font-weight: 400;
text-align: center;
box-shadow: none;
}
.swal-button:focus {
box-shadow: none;
}
/* Tooltips */
.tooltip-inner {
background-color: #2e2e2e;
color: #eee;
border-radius: 0;
}
.tooltip.top .tooltip-arrow {
border-top-color: #2e2e2e;
border-radius: 0;
}
.tooltip.right .tooltip-arrow {
border-right-color: #2e2e2e;
border-radius: 0;
}
.tooltip.bottom .tooltip-arrow {
border-bottom-color: #2e2e2e;
border-radius: 0;
}
.tooltip.left .tooltip-arrow {
border-left-color: #2e2e2e;
border-radius: 0;
}
#toast-container>div {
border-radius: 0;
}

View File

@@ -0,0 +1,351 @@
textarea {
resize: vertical;
max-height: 300px;
min-height: 50px;
}
a:hover,
a:active,
a:focus {
color: #734eb9;
}
label {
font-weight: bold;
}
.easy-autocomplete-container ul {
background-color: #1b1b1b !important;
}
.easy-autocomplete-container ul li, .easy-autocomplete-container ul .eac-category {
border-color: #1b1b1b !important;
}
.easy-autocomplete-container ul li.selected {
background: none repeat scroll 0 0 #383737;
cursor: pointer;
}
/* Fix large icon on dashboard number panels */
.small-box .icon-override {
font-size: 85px !important;
}
.small-box:hover .icon-override {
font-size: 90px !important;
}
.content-wrapper {
background-color: #1b1b1b;
}
.wrapper {
overflow: hidden;
}
/* Switch */
.switch {
top: 7px;
margin-right: 5px;
position: relative;
display: inline-block;
width: 30px;
height: 16px;
}
.switch input {
display: none;
}
.slider {
border-radius: 24px;
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #424242;
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
border-radius: 40%;
position: absolute;
content: "";
height: 8px;
width: 8px;
left: 4px;
bottom: 4px;
background-color: #1f1f1f;
-webkit-transition: .4s;
transition: .4s;
}
input:checked+.slider {
background-color: #6441a5;
}
input:focus+.slider {
box-shadow: 0 0 1px #2196F3;
}
input:checked+.slider:before {
-webkit-transform: translateX(26px);
-ms-transform: translateX(26px);
transform: translateX(13px);
}
/* Event log */
.event-log {
height: 150px;
overflow: auto;
position: relative;
background-color: #212121;
}
ul.recent-events {
padding: 0;
}
ul.recent-events li {
list-style: none;
margin-bottom: 5px;
line-height: 20px;
}
ul.recent-events li p {
font-size: 14px;
margin-bottom: 0;
}
ul.recent-events li p span {
margin-right: 3px;
}
span.event-date {
color: #999;
}
/* Datatables */
.default-table {
width: 46px;
min-width: 46px;
}
.default-table-large {
width: 47px;
min-width: 47px;
}
.datatables_filter,
.dataTables_filter {
float: left;
text-align: left;
}
.pagination>.active>a {
background-color: #6441a5;
border-color: #4b3671;
}
.pagination>.active>a:focus,
.pagination>.active>a:hover,
.pagination>.active>span,
.pagination>.active>span:focus,
.pagination>.active>span:hover {
background-color: #6441a5;
border-color: #4b3671;
}
.dataTable th,
.dataTable td {
max-width: 25px;
overflow: hidden !important;
text-overflow: ellipsis;
white-space: nowrap !important;
}
.table-hover tbody tr:hover td, .table-hover tbody tr:hover th {
background-color: #171717 !important;
}
/* disabled class */
.off {
display: none;
}
/* Buttons */
.btn:hover,
.btn-box-tool:hover {
background-color: transparent !important;
}
li.disabled {
cursor: not-allowed;
}
a.disabled {
pointer-events: none;
}
.panel,
.panel-default,
.panel-group {
border-radius: 0 !important;
background-color: #1b1b1b;
border-color: #424242;
}
.panel-default>.panel-heading {
color: #ccc;
background-color: #1b1b1b;
border-color: #424242;
}
.panel-default>.panel-heading+.panel-collapse>.panel-body {
border-top-color: #424242;
}
/* Tooltips */
.tooltip-inner {
background-color: #4a4848;
color: #eee;
border-radius: 0;
}
.tooltip.top .tooltip-arrow {
border-top-color: #4a4848;
border-radius: 0;
}
.tooltip.right .tooltip-arrow {
border-right-color: #4a4848;
border-radius: 0;
}
.tooltip.bottom .tooltip-arrow {
border-bottom-color: #4a4848;
border-radius: 0;
}
.tooltip.left .tooltip-arrow {
border-left-color: #4a4848;
border-radius: 0;
}
#toast-container>div {
border-radius: 0;
}
/* Modals */
.modal-header .close {
color: #ccc !important;
}
/* Sweetalert */
.swal-modal {
border-radius: 0;
background-color: #1a1a1a;
}
.swal-title,
.swal-text {
color: #ccc;
}
.swal-icon--success:after {
background-color: #1a1a1a;
}
.swal-icon--success:before {
background-color: #1a1a1a;
left: -25px;
}
.swal-icon--success__hide-corners {
background-color: #1a1a1a;
}
.swal-button--cancel,
.swal-button--cancel:focus,
.swal-button--cancel:active {
background-color: #313131;
color: #fff;
border: 1px solid #272727;
border-radius: 0;
}
.swal-button--cancel:hover {
background-color: #272727;
color: #fff;
border: 1px solid #1f1f1f;
border-radius: 0;
}
.swal-button--danger,
.swal-button--danger:focus,
.swal-button--danger:active {
background-color: #dd4b39 !important;
border: 1px solid #d73925 !important;
border-radius: 0;
}
.swal-button--danger:hover {
background-color: #d73925 !important;
border: 1px solid #d73925 !important;
border-radius: 0;
}
.swal-button--confirm,
.swal-button--confirm:focus,
.swal-button--confirm:active {
background-color: #6441a5;
text-decoration: none;
border: 1px solid #2f098c;
border-radius: 0;
}
.swal-button--confirm:hover {
background-color: #6b49ab;
text-decoration: none;
border: 1px solid #2f098c;
border-radius: 0;
}
.swal-button {
height: 34px;
padding: 6px 12px;
font-size: 14px;
font-weight: 400;
text-align: center;
box-shadow: none;
}
.swal-button:focus {
box-shadow: none;
}
.input-group,
.input-group-addon {
border-color: #313131 !important;
background-color: #2e2e2e !important;
color: #ccc !important;
}
.table-custom>thead>tr>th,
.table-custom>tbody>tr>th,
.table-custom>tfoot>tr>th,
.table-custom>thead>tr>td,
.table-custom>tbody>tr>td,
.table-custom>tfoot>tr>td {
border-top: 1px solid #424242 !important;
}

View File

@@ -0,0 +1 @@
textarea{resize:vertical;max-height:300px;min-height:50px}a:active,a:focus,a:hover{color:#734eb9}lable{font-weight:700}.easy-autocomplete-container ul{background-color:#1b1b1b!important}.easy-autocomplete-container ul .eac-category,.easy-autocomplete-container ul li{border-color:#1b1b1b!important}.easy-autocomplete-container ul li.selected{background:#383737;cursor:pointer}.small-box .icon-override{font-size:85px!important}.small-box:hover .icon-override{font-size:90px!important}.content-wrapper{background-color:#1b1b1b}.wrapper{overflow:hidden}.switch{top:7px;margin-right:5px;position:relative;display:inline-block;width:30px;height:16px}.off,.switch input{display:none}.slider{border-radius:24px;position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#424242;-webkit-transition:.4s;transition:.4s}.slider:before{border-radius:40%;position:absolute;content:"";height:8px;width:8px;left:4px;bottom:4px;background-color:#1f1f1f;-webkit-transition:.4s;transition:.4s}input:checked+.slider{background-color:#6441a5}input:focus+.slider{box-shadow:0 0 1px #2196F3}.swal-button,.swal-button:focus{box-shadow:none}input:checked+.slider:before{-webkit-transform:translateX(26px);-ms-transform:translateX(26px);transform:translateX(13px)}.event-log{height:150px;overflow:auto;position:relative;background-color:#212121}ul.recent-events{padding:0}ul.recent-events li{list-style:none;margin-bottom:5px;line-height:20px}ul.recent-events li p{font-size:14px;margin-bottom:0}ul.recent-events li p span{margin-right:3px}span.event-date{color:#999}.default-table{width:46px;min-width:46px}.default-table-large{width:47px;min-width:47px}.dataTables_filter,.datatables_filter{float:left;text-align:left}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{background-color:#6441a5;border-color:#4b3671}.dataTable td,.dataTable th{max-width:25px;overflow:hidden!important;text-overflow:ellipsis;white-space:nowrap!important}.table-hover tbody tr:hover td,.table-hover tbody tr:hover th{background-color:#171717!important}.btn-box-tool:hover, .btn:hover{background-color:transparent!important}li.disabled{cursor:not-allowed}a.disabled{pointer-events:none}.panel,.panel-default,.panel-group{border-radius:0!important;background-color:#1b1b1b;border-color:#424242}.panel-default>.panel-heading{color:#ccc;background-color:#1b1b1b;border-color:#424242}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#424242}.tooltip-inner{background-color:#4a4848;color:#eee;border-radius:0}.swal-icon--success:after,.swal-icon--success__hide-corners,.swal-modal{background-color:#1a1a1a}.tooltip.top .tooltip-arrow{border-top-color:#4a4848;border-radius:0}.tooltip.right .tooltip-arrow{border-right-color:#4a4848;border-radius:0}.tooltip.bottom .tooltip-arrow{border-bottom-color:#4a4848;border-radius:0}.tooltip.left .tooltip-arrow{border-left-color:#4a4848;border-radius:0}#toast-container>div{border-radius:0}.modal-header .close{color:#ccc!important}.swal-modal{border-radius:0}.swal-text,.swal-title{color:#ccc}.swal-icon--success:before{background-color:#1a1a1a;left:-25px}.swal-button--cancel,.swal-button--cancel:active,.swal-button--cancel:focus{background-color:#313131;color:#fff;border:1px solid #272727;border-radius:0}.swal-button--cancel:hover{background-color:#272727;color:#fff;border:1px solid #1f1f1f;border-radius:0}.swal-button--danger,.swal-button--danger:active,.swal-button--danger:focus{background-color:#dd4b39!important;border:1px solid #d73925!important;border-radius:0}.swal-button--danger:hover{background-color:#d73925!important;border:1px solid #d73925!important;border-radius:0}.swal-button--confirm,.swal-button--confirm:active,.swal-button--confirm:focus{background-color:#6441a5;text-decoration:none;border:1px solid #2f098c;border-radius:0}.swal-button--confirm:hover{background-color:#6b49ab;text-decoration:none;border:1px solid #2f098c;border-radius:0}.swal-button{height:34px;padding:6px 12px;font-size:14px;font-weight:400;text-align:center}.input-group,.input-group-addon{border-color:#313131!important;background-color:#2e2e2e!important;color:#ccc!important}.table-custom>tbody>tr>td,.table-custom>tbody>tr>th,.table-custom>tfoot>tr>td,.table-custom>tfoot>tr>th,.table-custom>thead>tr>td,.table-custom>thead>tr>th{border-top:1px solid #424242!important}

View File

@@ -0,0 +1 @@
textarea{resize:vertical;max-height:300px;min-height:50px}a:active,a:focus,a:hover{color:#333}lable{font-weight:700}.pretty.p-icon .state .icon:before{color:#fff!important}.small-box .icon-override{font-size:85px!important}.small-box:hover .icon-override{font-size:90px!important}.content-wrapper{background-color:#f1f1f1}.wrapper{overflow:hidden}.switch{top:7px;margin-right:5px;position:relative;display:inline-block;width:30px;height:16px}.off,.switch input{display:none}.slider{border-radius:24px;position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#ccc;-webkit-transition:.4s;transition:.4s}.slider:before{border-radius:40%;position:absolute;content:"";height:8px;width:8px;left:4px;bottom:4px;background-color:#fff;-webkit-transition:.4s;transition:.4s}input:checked+.slider{background-color:#6441a5}input:focus+.slider{box-shadow:0 0 1px #2196F3}.swal-button,.swal-button:focus{box-shadow:none}input:checked+.slider:before{-webkit-transform:translateX(26px);-ms-transform:translateX(26px);transform:translateX(13px)}.event-log{height:150px;overflow:auto;position:relative}ul.recent-events{padding:0}ul.recent-events li{list-style:none;margin-bottom:5px;line-height:20px}ul.recent-events li p{font-size:14px;margin-bottom:0}ul.recent-events li p span{margin-right:3px}span.event-date{color:#999}.default-table{width:46px;min-width:46px}.default-table-large{width:47px;min-width:47px}.dataTables_filter,.datatables_filter{float:left;text-align:left}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{background-color:#6441a5;border-color:#4b3671}.dataTable td,.dataTable th{max-width:25px;overflow:hidden!important;text-overflow:ellipsis;white-space:nowrap!important}.btn-box-tool:hover, .btn:hover{background-color:transparent!important}li.disabled{cursor:not-allowed}a.disabled{pointer-events:none}.panel,.panel-default,.panel-group{border-radius:0!important}.swal-modal{border-radius:0}.swal-button--cancel,.swal-button--cancel:active,.swal-button--cancel:focus{background-color:#f4f4f4;color:#444;border:1px solid #ddd;border-radius:0}.swal-button--cancel:hover{background-color:#e7e7e7;color:#444;border:1px solid #ddd;border-radius:0}.swal-button--danger,.swal-button--danger:active,.swal-button--danger:focus{background-color:#dd4b39!important;border:1px solid #d73925!important;border-radius:0}.swal-button--danger:hover{background-color:#d73925!important;border:1px solid #d73925!important;border-radius:0}.swal-button--confirm,.swal-button--confirm:active,.swal-button--confirm:focus{background-color:#6441a5;text-decoration:none;border:1px solid #2f098c;border-radius:0}.swal-button--confirm:hover{background-color:#6b49ab;text-decoration:none;border:1px solid #2f098c;border-radius:0}.swal-button{height:34px;padding:6px 12px;font-size:14px;font-weight:400;text-align:center}.tooltip-inner{background-color:#2e2e2e;color:#eee;border-radius:0}.tooltip.top .tooltip-arrow{border-top-color:#2e2e2e;border-radius:0}.tooltip.right .tooltip-arrow{border-right-color:#2e2e2e;border-radius:0}.tooltip.bottom .tooltip-arrow{border-bottom-color:#2e2e2e;border-radius:0}.tooltip.left .tooltip-arrow{border-left-color:#2e2e2e;border-radius:0}#toast-container>div{border-radius:0}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View File

@@ -0,0 +1,528 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Set the default charset -->
<meta charset="utf-8">
<!-- Tell IE to use the latest render engine -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- Main title -->
<title>PhantomBot Dashboard</title>
<!-- Tell the browser to be responsive to screen width -->
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
<!-- Font Awesome -->
<link rel="stylesheet" href="/panel/vendors/font-awesome/css/font-awesome.min.css">
<!-- Discord Icon -->
<link rel="stylesheet" href="/panel/vendors/font-awesome/css/discord.min.css">
<!-- Bootstrap 3.3.7 -->
<link rel="stylesheet" href="/panel/vendors/bootstrap/css/bootstrap.min.css">
<!-- Datatables -->
<link rel="stylesheet" href="/panel/vendors/datatables.net-bs/css/dataTables.bootstrap.min.css">
<!-- Toastr -->
<link rel="stylesheet" href="/panel/vendors/toastr/toastr.min.css">
<!-- Pace theme -->
<link rel="stylesheet" href="/panel/vendors/PACE/pace.min.css">
<!-- Pretty Checkbox -->
<link rel="stylesheet" href="/panel/vendors/pretty-checkbox/pretty-checkbox.min.css">
<!-- Easy auto comeplete -->
<link rel="stylesheet" href="/panel/vendors/EasyAutocomplete-1.3.5/easy-autocomplete.min.css">
<!-- Loader -->
<link rel="stylesheet" href="/panel/css/main.min.css">
<!-- Google Font -->
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,300italic,400italic,600italic">
<!-- More css is loaded via JavaScript -->
</head>
<!-- Main body -->
<body class="hold-transition skin-purple sidebar-mini">
<!-- Page loader -->
<div class="loader"></div>
<!-- Pace -->
<div class="pace pace-inactive">
<div class="pace-activity"></div>
</div>
<div class="main" style="display: none;">
<!-- Header -->
<div class="wrapper">
<header class="main-header">
<!-- Logo -->
<div class="logo">
<span class="logo-mini"><b>P</b>B</span>
<span class="logo-lg"><b>Phantom</b>Bot</span>
</div>
<!-- Sidebar toggle -->
<nav class="navbar navbar-static-top">
<a href="javascript:void(0);" class="sidebar-toggle" data-toggle="push-menu" role="button">
<span class="sr-only">Toggle navigation</span>
</a>
<!-- Panel settings -->
<div class="navbar-custom-menu">
<ul class="nav navbar-nav">
<!-- Notification warning -->
<li class="dropdown notifications-menu">
<a href="javascript:void(0);" class="dropdown-toggle" data-toggle="dropdown"><i class="fa fa-bell-o"></i>
<span class="label label-warning" id="notifications-amount" style="display: none;">1</span>
</a>
<ul class="dropdown-menu">
<li class="header">You have <span id="notifications-total" data-isset="false">0</span> notification(s)</li>
<li>
<ul class="menu" id="notifications-menu-ul">
<!-- New notifications added in JavaScript. -->
</ul>
</li>
</ul>
</li>
<!-- Panel user -->
<li class="dropdown user user-menu">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
<img src="/panel/img/logo.jpeg" alt="User Avatar" class="user-image">
<span class="hidden-xs" id="main-name">PhantomBot</span>
</a>
<ul class="dropdown-menu">
<!-- User image -->
<li class="user-header" style="background-color: #6441a5; height: auto;">
<img src="/panel/img/logo.jpeg" alt="Logo" class="img-circle">
<p class="panel-admin" id="second-name">
PhantomBot
</p>
</li>
<!-- Menu Footer-->
<li class="user-footer">
<div class="pull-right">
<a href="#" class="btn btn-primary btn-flat" id="sign-out-btn">Sign out</a>
</div>
</li>
</ul>
</li>
<!-- Settings button -->
<li>
<a href="javascript:void(0);" data-toggle="control-sidebar"><i class="fa fa-gears"></i></a>
</li>
</ul>
</div>
</nav>
</header>
<!-- Left side column. contains the logo and sidebar -->
<aside class="main-sidebar">
<section class="sidebar">
<!-- List of all tabs. No new tabs should be added. -->
<!-- Everything else should be put in the extra tab (for the main build) thanks <3 -->
<ul class="sidebar-menu" data-widget="tree">
<!-- Devider -->
<li class="header">MAIN NAVIGATION</li>
<!-- Main dashboard tab -->
<li class="treeview active">
<a href="#dashboard.html" data-folder="dashboard">
<i class="fa fa-dashboard"></i> <span> Dashboard</span>
</a>
</li>
<!-- Commands tab -->
<li class="treeview">
<a href="#">
<i class="fa fa-exclamation" style="padding-left: 3px;"></i> <span> Commands</span>
<span class="pull-right-container">
<i class="fa fa-angle-left pull-right"></i>
</span>
</a>
<ul class="treeview-menu">
<li><a href="#custom.html" data-folder="commands"><i class="fa fa-circle-o"></i> Custom</a></li>
<li><a href="#aliases.html" data-folder="commands"><i class="fa fa-circle-o"></i> Aliases</a></li>
<li><a href="#default.html" data-folder="commands"><i class="fa fa-circle-o"></i> Default</a></li>
</ul>
</li>
<!-- Moderation tab -->
<li class="treeview">
<a href="#">
<i class="fa fa-shield"></i> <span> Moderation</span>
<span class="pull-right-container">
<i class="fa fa-angle-left pull-right"></i>
</span>
</a>
<ul class="treeview-menu">
<li><a href="#filters.html" data-folder="moderation"><i class="fa fa-circle-o"></i> Filters</a></li>
<li><a href="#whitelist.html" data-folder="moderation"><i class="fa fa-circle-o"></i> Whitelist</a></li>
<li><a href="#blacklist.html" data-folder="moderation"><i class="fa fa-circle-o"></i> Blacklist</a></li>
</ul>
</li>
<!-- Permission tab -->
<li class="treeview">
<a href="#permissions.html" data-folder="permissions">
<i class="fa fa-lock"></i> <span> Permissions</span>
</a>
</li>
<!-- Timers tab -->
<li class="treeview">
<a href="#timers.html" data-folder="timers">
<i class="fa fa-clock-o"></i> <span> Timers</span>
</a>
</li>
<!-- Alerts tab -->
<li class="treeview">
<a href="#alerts.html" data-folder="alerts">
<i class="fa fa-bullhorn"></i> <span> Alerts</span>
</a>
</li>
<!-- Soon -->
<!-- <li class="treeview">
<a href="#">
<i class="fa fa-bullhorn"></i> <span> Alerts</span>
<span class="pull-right-container">
<i class="fa fa-angle-left pull-right"></i>
</span>
</a>
<ul class="treeview-menu">
<li><a href="#alerts.html" data-folder="alerts"><i class="fa fa-circle-o"></i> Chat</a></li>
<li><a href="#stream.html" data-folder="alerts"><i class="fa fa-circle-o"></i> Stream</a></li>
</ul>
</li> -->
<!-- Loyalty tab -->
<li class="treeview">
<a href="#">
<i class="fa fa-star"></i> <span> Loyalty</span>
<span class="pull-right-container">
<i class="fa fa-angle-left pull-right"></i>
</span>
</a>
<ul class="treeview-menu">
<li><a href="#currency.html" data-folder="loyalty"><i class="fa fa-circle-o"></i> Currency</a></li>
<li><a href="#loyalty.html" data-folder="loyalty"><i class="fa fa-circle-o"></i> Loyalty</a></li>
<li><a href="#leaderboard.html" data-folder="loyalty"><i class="fa fa-circle-o"></i> Leaderboard</a></li>
</ul>
</li>
<!-- Ranking tab -->
<li class="treeview">
<a href="#">
<i class="fa fa-user"></i> <span> Ranking</span>
<span class="pull-right-container">
<i class="fa fa-angle-left pull-right"></i>
</span>
</a>
<ul class="treeview-menu">
<li><a href="#globalRanks.html" data-folder="ranking"><i class="fa fa-circle-o"></i> Global</a></li>
<li><a href="#customRanks.html" data-folder="ranking"><i class="fa fa-circle-o"></i> Custom</a></li>
</ul>
</li>
<!-- Quotes tab -->
<li class="treeview">
<a href="#quotes.html" data-folder="quotes">
<i class="fa fa-quote-right"></i> <span> Quotes</span>
</a>
</li>
<!-- Keywords tab -->
<li class="treeview">
<a href="#keywords.html" data-folder="keywords">
<i class="fa fa-key"></i> <span> Keywords</span>
</a>
</li>
<!-- Games tab -->
<li class="treeview">
<a href="#games.html" data-folder="games">
<i class="fa fa-gamepad"></i> <span> Games</span>
</a>
</li>
<!-- Giveaways tab -->
<li class="treeview">
<a href="#">
<i class="fa fa-gift"></i> <span> Giveaways</span>
<span class="pull-right-container">
<i class="fa fa-angle-left pull-right"></i>
</span>
</a>
<ul class="treeview-menu">
<li><a href="#raffle.html" data-folder="giveaways"><i class="fa fa-circle-o"></i> Raffle</a></li>
<li><a href="#ticketRaffle.html" data-folder="giveaways"><i class="fa fa-circle-o"></i> Ticket Raffle</a></li>
<li><a href="#auction.html" data-folder="giveaways"><i class="fa fa-circle-o"></i> Auction</a></li>
</ul>
</li>
<!-- Discord tab -->
<li class="treeview" id="discord_index_tab">
<a href="#">
<i class="demo-icon icon-discord"></i> <span> Discord</span>
<span class="pull-right-container">
<i class="fa fa-angle-left pull-right"></i>
</span>
</a>
<ul class="treeview-menu">
<li class="treeview">
<a href="#"><i class="fa fa-circle-o"></i> Commands
<span class="pull-right-container">
<i class="fa fa-angle-left pull-right"></i>
</span>
</a>
<ul class="treeview-menu">
<li><a href="#discordCustomCommands.html" data-folder="discord"><i class="fa fa-circle-o"></i> Custom</a></li>
<li><a href="#discordDefaultCommands.html" data-folder="discord"><i class="fa fa-circle-o"></i> Default</a></li>
</ul>
</li>
<!-- For IO and his promotion system:
From what I saw, you might need multiple tabs like the one above, since you
allow a "blacklist" of users. -->
<!-- <li><a href="#discordPromotion.html" data-folder="discord"><i class="fa fa-circle-o"></i> Promotion</a></li> -->
<li><a href="#discordAlerts.html" data-folder="discord"><i class="fa fa-circle-o"></i> Alerts</a></li>
<li><a href="#discordLogs.html" data-folder="discord"><i class="fa fa-circle-o"></i> Logging</a></li>
<li><a href="#discordKeywords.html" data-folder="discord"><i class="fa fa-circle-o"></i> Keywords</a></li>
<li><a href="#discordGames.html" data-folder="discord"><i class="fa fa-circle-o"></i> Games</a></li>
</ul>
</li>
<!-- Hisotry tab -->
<li class="treeview">
<a href="#">
<i class="fa fa-history"></i> <span> History</span>
<span class="pull-right-container">
<i class="fa fa-angle-left pull-right"></i>
</span>
</a>
<ul class="treeview-menu">
<li><a href="#tipsHistory.html" data-folder="history"><i class="fa fa-circle-o"></i> Tips</a></li>
<li><a href="#hostHistory.html" data-folder="history"><i class="fa fa-circle-o"></i> Hosts</a></li>
<li><a href="#raidHistory.html" data-folder="history"><i class="fa fa-circle-o"></i> Raids</a></li>
</ul>
</li>
<!-- Extra tab -->
<li class="treeview">
<a href="#">
<i class="fa fa-magic"></i> <span> Extra</span>
<span class="pull-right-container">
<i class="fa fa-angle-left pull-right"></i>
</span>
</a>
<ul class="treeview-menu">
<li><a href="#commercials.html" data-folder="extra"><i class="fa fa-circle-o"></i> Automatic Commercials</a></li>
<li><a href="#dualstream.html" data-folder="extra"><i class="fa fa-circle-o"></i> Dual Stream</a></li>
<li><a href="#deathcounter.html" data-folder="extra"><i class="fa fa-circle-o"></i> Death Counter</a></li>
<li><a href="#highlights.html" data-folder="extra"><i class="fa fa-circle-o"></i> Highlights</a></li>
<li><a href="#betting.html" data-folder="extra"><i class="fa fa-circle-o"></i> Betting</a></li>
<li><a href="#polls.html" data-folder="extra"><i class="fa fa-circle-o"></i> Polls</a></li>
<li><a href="#queue.html" data-folder="extra"><i class="fa fa-circle-o"></i> Queue</a></li>
</ul>
</li>
<!-- Audio tab -->
<li class="treeview">
<a href="#">
<i class="fa fa-music"></i> <span> Audio</span>
<span class="pull-right-container">
<i class="fa fa-angle-left pull-right"></i>
</span>
</a>
<ul class="treeview-menu">
<li><a href="#audioHooks.html" data-folder="audio"><i class="fa fa-circle-o"></i> Audio Hooks</a></li>
<!-- For now, as long as the YouTube player module hasn't gotten a rewrite, we will redirect to the player. -->
<li><a href="/ytplayer" target="_blank"><i class="fa fa-circle-o"></i> Song Requests</a></li>
</ul>
</li>
<!-- Settings tab -->
<li class="treeview">
<a href="#">
<i class="fa fa-cog"></i> <span> Settings</span>
<span class="pull-right-container">
<i class="fa fa-angle-left pull-right"></i>
</span>
</a>
<ul class="treeview-menu">
<li><a href="#botSettings.html" data-folder="settings"><i class="fa fa-circle-o"></i> Bot</a></li>
<li><a href="#commandSettings.html" data-folder="settings"><i class="fa fa-circle-o"></i> Commands</a></li>
<li><a href="#moduleList.html" data-folder="settings"><i class="fa fa-circle-o"></i> Modules</a></li>
<li><a href="#localization.html" data-folder="settings"><i class="fa fa-circle-o"></i> Localization</a></li>
</ul>
</li>
<!-- Devider -->
<li class="header">HELP &#38; SUPPORT</li>
<!-- Help tab -->
<li class="treeview">
<a href="#help.html" data-folder="help">
<i class="fa fa-life-ring"></i> <span>Help</span>
</a>
</li>
</ul>
</section>
</aside>
<!-- Content Wrapper. Contains page content -->
<aside class="content-wrapper">
<div id="page-content"></div>
</aside>
</div>
<!-- Control Sidebar -->
<aside class="control-sidebar control-sidebar-dark">
<ul class="nav nav-tabs nav-justified control-sidebar-tabs">
<!-- First tab -->
<li class="active">
<a href="#main-side-tab" data-toggle="tab" aria-expanded="true"><i class="fa fa-wrench"></i></a>
</li>
<!-- Second tab -->
<li>
<a href="#second-side-tab" data-toggle="tab" aria-expanded="true"><i class="fa fa-home"></i></a>
</li>
<!-- Third tab -->
<li class="disabled">
<a class="disabled" href="#third-side-tab" data-toggle="tab" aria-expanded="true"><i class="fa fa-cogs"></i></a>
</li>
</ul>
<!-- Tab content -->
<div class="tab-content">
<!-- First tab. -->
<div id="main-side-tab" class="tab-pane active">
<h4 class="control-sidebar-heading">Layout Options</h4>
<div class="form-group">
<div class="control-sidebar-subheading">
<div class="pretty p-icon pull-right" style="margin-right: 0;">
<input type="checkbox" id="dark-mode-toggle"/>
<div class="state p-default">
<i class="icon fa fa-check"></i>
<label></label>
</div>
</div>
<label for="dark-mode-toggle">Dark Mode</label>
</div>
<p>Activate the panel's dark mode.</p>
</div>
</div>
<!-- Middle tab -->
<div id="second-side-tab" class="tab-pane">
<h4 class="control-sidebar-heading">Dashboard Page</h4>
<div class="form-group">
<div class="control-sidebar-subheading">
<div class="pretty p-icon pull-right" style="margin-right: 0;">
<input type="checkbox" id="toggle-chat"/>
<div class="state p-default">
<i class="icon fa fa-check"></i>
<label></label>
</div>
</div>
<label for="toggle-chat">Show Twitch Chat</label>
</div>
<p>Show or hide Twitch chat.</p>
</div>
<div class="form-group">
<div class="control-sidebar-subheading">
<div class="pretty p-icon pull-right" style="margin-right: 0;">
<input type="checkbox" data-layout="fixed" id="toggle-player"/>
<div class="state p-default">
<i class="icon fa fa-check"></i>
<label></label>
</div>
</div>
<label for="toggle-player">Show Twitch Player</label>
</div>
<p>Show or hide the player.</p>
</div>
<div class="form-group">
<div class="control-sidebar-subheading">
<div class="pretty p-icon pull-right" style="margin-right: 0;">
<input type="checkbox" id="toggle-reverse-events"/>
<div class="state p-default">
<i class="icon fa fa-check"></i>
<label></label>
</div>
</div>
<label for="toggle-reverse-events">Reverse Sort Events</label>
</div>
<p>Show events in reverse order.</p>
</div>
</div>
<!-- Last tab -->
<div id="third-side-tab" class="tab-pane">
<h4 class="control-sidebar-heading">General Settings</h4>
<div class="form-group">
</div>
</div>
</div>
</aside>
<!-- Sidebar control. This is required to fill it the side of the screen. -->
<div class="control-sidebar-bg"></div>
</div>
<!-- jQuery 3 -->
<script src="/panel/vendors/jquery/jquery.min.js"></script>
<!-- Bootstrap 3.3.7 -->
<script src="/panel/vendors/bootstrap/js/bootstrap.min.js"></script>
<!-- Pace -->
<script src="/panel/vendors/PACE/pace.min.js"></script>
<!-- Toastr -->
<script src="/panel/vendors/toastr/toastr.min.js"></script>
<!-- AdminLTE App -->
<script src="/panel/vendors/adminlte/js/adminlte.min.js"></script>
<!-- Select2 -->
<script src="/panel/vendors/select2/select2.full.min.js"></script>
<!-- Sweetalert -->
<script src="/panel/vendors/sweetalert/sweetalert.min.js"></script>
<!-- Datatables -->
<script src="/panel/vendors/datatables.net-bs/js/jquery.dataTables.min.js"></script>
<script src="/panel/vendors/datatables.net-bs/js/dataTables.bootstrap.min.js"></script>
<!-- Easy auto comeplete -->
<script src="/panel/vendors/EasyAutocomplete-1.3.5/jquery.easy-autocomplete.min.js"></script>
<!-- Panel config script -->
<script src="/panel/js/utils/panelConfig.js"></script>
<!-- Helpers -->
<script src="/panel/js/utils/helpers.js"></script>
<!-- Ajax page loader -->
<script src="/panel/js/utils/ajaxLoader.js"></script>
<!-- Reconnecting socket. -->
<script src="/common/reconnecting-websocket/reconnectingWS.min.js"></script>
<!-- Main js file -->
<script src="/panel/js/index.js"></script>
</body>
</html>

View File

@@ -0,0 +1,563 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Main socket and functions.
$(function() {
var webSocket = new ReconnectingWebSocket((getProtocol() === 'https://' || window.location.protocol === 'https:' ? 'wss://' : 'ws://') + window.location.host + '/ws/panel', null, { reconnectInterval: 500 }),
callbacks = [],
listeners = [],
socket = {};
/*
* @function Used to send messages to the socket. This should be private to this script.
*
* @param {Object} message
*/
var sendToSocket = function(message) {
try {
let json = JSON.stringify(message);
webSocket.send(json);
// Make sure to not show the user's token.
if (json.indexOf('authenticate') !== -1) {
helpers.log('sendToSocket:: ' + json.substring(0, json.length - 20) + '.."}', helpers.LOG_TYPE.DEBUG);
} else {
helpers.log('sendToSocket:: ' + json, helpers.LOG_TYPE.DEBUG);
}
} catch (e) {
helpers.logError('Failed to send message to socket: ' + e.message, helpers.LOG_TYPE.DEBUG);
}
};
/*
* @function Generates a callback
*
* @param {String} id
* @param {Array} tables
* @param {Boolean} isUpdate
* @param {Function} callback
* @param {Boolean} storeKey
*/
var generateCallBack = function(id, tables, isUpdate, isArray, callback, storeKey) {
if (callbacks[id] !== undefined) {
helpers.logError('Callback with id "' + id + '" exists already. Aborting update.', helpers.LOG_TYPE.FORCE);
} else {
helpers.log('Created callback with id ' + id, helpers.LOG_TYPE.DEBUG);
callbacks[id] = {
await: (tables.length === 0 ? 1 : tables.length),
isUpdate: isUpdate,
isArray: isArray,
func: function(e) {
try {
callback(e);
} catch (ex) {
// Line number won't be accurate, function will by anonymous, but we get the stack so it should be fine.
helpers.logError('Failed to run callback: ' + ex.stack, helpers.LOG_TYPE.FORCE);
}
},
storeKey: storeKey,
queryData: []
};
}
};
/*
* @function Adds a listener for the socket.
*
* @param {String} listener_id
* @param {Function} callback
*/
socket.addListener = function(listener_id, callback) {
if (listeners[listener_id] === undefined) {
helpers.log('Added listener with id ' + id);
listeners[listener_id] = function(e) {
try {
callback(e);
} catch (ex) {
// Line number won't be accurate, function will by anonymous, but we get the stack so it should be fine.
helpers.logError('Failed to run listener: ' + ex.stack, helpers.LOG_TYPE.FORCE);
}
};
}
};
/*
* @function Removes a listener from the socket.
*
* @param {String} listener_id
*/
socket.removeListener = function(listener_id) {
if (listeners[listener_id] !== undefined) {
delete listeners[listener_id];
}
};
/*
* @function Runs a bot commands as the bot in async, thus returning right away.
*
* @param {String} callback_id
* @param {String} command
* @param {Function} callback
*/
socket.sendCommand = function(callback_id, command, callback) {
// Genetate a callback.
generateCallBack(callback_id, [], true, false, callback);
// Send the command.
sendToSocket({
command: String(command),
query_id: callback_id
});
};
/*
* @function Sends a raw request to the socket.
*
* @param {String} callback_id
* @param {Function} callback
*/
socket.getBotVersion = function(callback_id, callback) {
// Genetate a callback.
generateCallBack(callback_id, [], true, false, callback);
// Send the request.
sendToSocket({
version: callback_id
});
};
/*
* @function Runs a bot commands as the bot.
*
* @param {String} callback_id
* @param {String} command
* @param {Function} callback
*/
socket.sendCommandSync = function(callback_id, command, callback) {
// Genetate a callback.
generateCallBack(callback_id, [], true, false, callback);
// Send the command.
sendToSocket({
command_sync: String(command),
query_id: callback_id
});
};
/*
* @function Sends the websocket event.
*
* @param {String} callback_id
* @param {String} script
* @param {String} argsString
* @param {Array} args
* @param {Function} callback
*/
socket.wsEvent = function(callback_id, script, argsString, args, callback) {
// Genetate a callback.
generateCallBack(callback_id, [], true, false, callback);
// Send event.
sendToSocket({
socket_event: callback_id,
script: script,
args: {
arguments: String(argsString),
args: args
}
});
};
/*
* @function Updates a value in the database of the bot.
*
* @param {String} callback_id
* @param {String} table
* @param {String} key
* @param {String} value
* @param {Function} callback
*/
socket.updateDBValue = function(callback_id, table, key, value, callback) {
// Genetate a callback.
generateCallBack(callback_id, [], true, false, callback);
// Update the value.
sendToSocket({
dbupdate: callback_id,
update: {
table: String(table),
key: String(key),
value: String(value)
}
});
};
/*
* @function Updates values in the database of the bot.
*
* @param {String} callback_id
* @param {Object} dataObj {tables: [], keys: [], values: }
* @param {Function} callback
*/
socket.updateDBValues = function(callback_id, dataObj, callback) {
// Genetate a callback.
generateCallBack(callback_id, dataObj.tables, true, false, callback);
// Start sending the updates to the socket.
for (let i = 0; i < dataObj.tables.length; i++) {
sendToSocket({
dbupdate: callback_id,
update: {
table: String(dataObj.tables[i]),
key: String(dataObj.keys[i]),
value: String(dataObj.values[i])
}
});
}
};
/*
* @function Increases a value in the database.
*
* @param {String} callback_id
* @param {String} table
* @param {String} key
* @param {String} value
* @param {Function} callback
*/
socket.incrDBValue = function(callback_id, table, key, value, callback) {
// Genetate a callback.
generateCallBack(callback_id, [], true, false, callback);
// Update the value.
sendToSocket({
dbincr: callback_id,
incr: {
table: table,
key: key,
value: value
}
});
};
/*
* @function Decreases a value in the database.
*
* @param {String} callback_id
* @param {String} table
* @param {String} key
* @param {String} value
* @param {Function} callback
*/
socket.decrDBValue = function(callback_id, table, key, value, callback) {
// Genetate a callback.
generateCallBack(callback_id, [], true, false, callback);
// Update the value.
sendToSocket({
dbdecr: callback_id,
decr: {
table: table,
key: key,
value: value
}
});
};
/*
* @function Gets a value from the database
*
* @param {String} callback_id
* @param {String} table
* @param {String} key
* @param {Function} callback
*/
socket.getDBValue = function(callback_id, table, key, callback) {
// Genetate a callback.
generateCallBack(callback_id, [], false, false, callback);
// Query database.
sendToSocket({
dbquery: callback_id,
query: {
table: String(table),
key: String(key)
}
});
};
/*
* @function Gets values from the database
*
* @param {String} callback_id
* @param {Object} dataObj {tables: [], keys: []}
* @param {Function} callback
* @param {Boolean} storeKey - Store the value with the key name from the DB. Default stores it as the table, thus making it only possible to query the table once.
*/
socket.getDBValues = function(callback_id, dataObj, storeKey, callback) {
callback = (callback === undefined ? storeKey : callback);
// Genetate a callback.
generateCallBack(callback_id, dataObj.tables, false, false, callback, (typeof storeKey !== 'function'));
// Start sending the updates to the socket.
for (let i = 0; i < dataObj.tables.length; i++) {
sendToSocket({
dbquery: callback_id,
query: {
table: String(dataObj.tables[i]),
key: String(dataObj.keys[i])
}
});
}
};
/*
* @function Gets values from the database by an order.
*
* @param {String} callback_id
* @param {String} table
* @param {Number} limit
* @param {Number} offset
* @param {String} order
* @param {Function} callback
*/
socket.getDBTableValuesByOrder = function(callback_id, table, limit, offset, order, isNumber, callback) {
// Genetate a callback.
generateCallBack(callback_id, [], false, true, callback);
// Query database.
sendToSocket({
dbvaluesbyorder: callback_id,
query: {
table: table,
limit: String(limit),
offset: String(offset),
order: order,
number: String(isNumber)
}
});
};
/*
* @function Gets all keys and values from a database table.
*
* @param {String} callback_id
* @param {String} table
* @param {Function} callback
*/
socket.getDBTableValues = function(callback_id, table, callback) {
// Genetate a callback.
generateCallBack(callback_id, [], false, true, callback);
// Query database.
sendToSocket({
dbkeys: callback_id,
query: {
table: String(table)
}
});
};
/*
* @function Gets all keys and values from multiple database table.
*
* @param {String} callback_id
* @param {Array Object} tables [{table: 'a'}, {table: 'b'}]
* @param {Function} callback
*/
socket.getDBTablesValues = function(callback_id, tables, callback) {
// Genetate a callback.
generateCallBack(callback_id, [], false, true, callback);
// Query database.
sendToSocket({
dbkeyslist: callback_id,
query: tables
});
};
/*
* @function Removes the data from the database.
*
* @param {String} callback_id
* @param {String} table
* @param {String} key
* @param {Function} callback
*/
socket.removeDBValue = function(callback_id, table, key, callback) {
// Genetate a callback.
generateCallBack(callback_id, [], false, true, callback);
// Send the event.
sendToSocket({
dbdelkey: callback_id,
delkey: {
table: String(table),
key: String(key)
}
});
};
/*
* @function Removes the data from the database.
*
* @param {String} callback_id
* @param {Object} dataObj {tables: [], keys: []}
* @param {Function} callback
*/
socket.removeDBValues = function(callback_id, dataObj, callback) {
// Genetate a callback.
generateCallBack(callback_id, dataObj.tables, false, true, callback);
for (let i = 0; i < dataObj.tables.length; i++) {
// Send the event.
sendToSocket({
dbdelkey: callback_id,
delkey: {
table: String(dataObj.tables[i]),
key: String(dataObj.keys[i])
}
});
}
};
// WebSocket events.
/*
* @function Called when the socket opens.
*/
webSocket.onopen = function() {
helpers.log('Connection established with the websocket.', helpers.LOG_TYPE.FORCE);
// Restart Pace.
Pace.restart();
// Remove all alerts.
toastr.remove();
// Auth with the socket.
sendToSocket({
authenticate: getAuth()
});
};
/*
* @function Socket calls when it closes
*/
webSocket.onclose = function() {
helpers.logError('Connection lost with the websocket.', helpers.LOG_TYPE.FORCE);
// Add error toast.
toastr.error('Connection lost with the websocket.', '', { timeOut: 0 });
};
/*
* @function Socket calls when it gets message.
*/
webSocket.onmessage = function(e) {
try {
helpers.log('Message from socket: ' + e.data, helpers.LOG_TYPE.DEBUG);
if (e.data === 'PING') {
webSocket.send('PONG');
return;
}
let message = JSON.parse(e.data);
// Check this message here before doing anything else.
if (message.authresult !== undefined) {
if (message.authresult === 'false') {
helpers.logError('Failed to auth with the socket.', helpers.LOG_TYPE.FORCE);
toastr.error('Failed to auth with the socket.', '', { timeOut: 0 });
} else {
// This is to stop a reconnect loading the main page.
if (helpers.isAuth === true) {
return;
} else {
helpers.isAuth = true;
}
// Load the main page.
$.loadPage('dashboard', 'dashboard.html');
}
return;
}
// Make sure this isn't a version request.
if (message.versionresult !== undefined) {
// Call the callback.
callbacks[message.versionresult].func(message);
// Delete the callback.
delete callbacks[message.versionresult];
} else {
// Handle callbacks.
let callback = callbacks[message.query_id],
listener = listeners[message.query_id];
if (callback !== undefined) {
// Add our data to the callback array.
if (!callback.isUpdate) {
if (callback.isArray) {
callback.queryData = message.results;
} else if (callback.storeKey === true) {
callback.queryData[Object.keys(message.results)[1]] = message.results.value;
} else {
callback.queryData[message.results.table] = message.results.value;
}
}
// If we got all the data, run the callback.
if (--callback.await === 0) {
// Run the function and send the query data with it.
callback.func(callback.queryData);
// Log this.
helpers.log('Called callback with id: ' + message.query_id, helpers.LOG_TYPE.DEBUG);
// Remove the callback from the array.
delete callbacks[message.query_id];
// Remove any active spinners.
if (message.query_id !== 'get_bot_updates' && message.query_id.indexOf('get') !== -1) {
// Remove any active spinners.
$('.load-ajax').remove();
}
if (message.query_id.indexOf('module_toggle') !== -1 || message.query_id.indexOf('module_status') !== -1
|| message.query_id.endsWith('module')) {
if (message.results.value == 'false') {
$('.load-ajax').remove();
}
}
} else {
helpers.log('Awaiting for data (' + callback.await + ' left) before calling callback with id: ' + message.query_id, helpers.LOG_TYPE.DEBUG);
}
} else if (listener !== undefined) {
// Call the listener.
listener(message.results);
}
}
} catch (ex) {
// Line number won't be accurate, function will by anonymous, but we get the stack so it should be fine.
helpers.logError('Failed to parse message from socket: ' + ex.stack + '\n\n' + e.data, helpers.LOG_TYPE.FORCE);
}
};
// Make this a global object.
window.socket = socket;
// Store all timers in here so we can destroy them.
window.timers = [];
});

View File

@@ -0,0 +1,849 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Function that querys all of the data we need.
$(function() {
// Get all module toggles.
socket.getDBValues('alerts_get_modules', {
tables: ['modules', 'modules', 'modules', 'modules', 'modules', 'modules', 'modules', 'modules', 'modules', 'modules', 'modules'],
keys: ['./handlers/followHandler.js', './handlers/subscribeHandler.js', './handlers/hostHandler.js', './handlers/bitsHandler.js', './handlers/clipHandler.js',
'./systems/greetingSystem.js', './handlers/donationHandler.js', './handlers/raidHandler.js', './handlers/tipeeeStreamHandler.js',
'./handlers/streamElementsHandler.js', './handlers/twitterHandler.js']
}, true, function(e) {
// Handle the settings button.
let keys = Object.keys(e),
module = '',
i;
for (i = 0; i < keys.length; i++) {
// Handle the status of the buttons.
if (e[keys[i]] === 'false') {
module = keys[i].substring(keys[i].lastIndexOf('/') + 1).replace('.js', '');
// Handle the switch.
$('#' + module + 'Toggle').prop('checked', false);
// Handle the settings button.
$('#' + module + 'Settings').prop('disabled', true);
}
}
});
});
// Function that handlers the loading of events.
$(function() {
// Toggle for the alert modules.
$('[data-alert-toggle]').on('change', function() {
let name = $(this).attr('id'),
checked = $(this).is(':checked');
// Handle the module.
socket.sendCommandSync('alerts_module_toggle', 'module ' + (checked ? 'enablesilent' : 'disablesilent') + ' ' + $(this).data('alert-toggle'), function() {
// Toggle the settings button.
$('#' + name.replace('Toggle', 'Settings')).prop('disabled', !checked);
// Alert the user.
toastr.success('Successfully ' + (checked ? 'enabled' : 'disabled') + ' the alert module!');
});
});
// Follow handler settings.
$('#followHandlerSettings').on('click', function() {
socket.getDBValues('alerts_follow_get_settings', {
tables: ['settings', 'settings', 'settings', 'settings'],
keys: ['followToggle', 'followReward', 'followMessage', 'followDelay']
}, true, function(e) {
helpers.getModal('follow-alert', 'Follower Alert Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Add the toggle for follow alerts.
.append(helpers.getDropdownGroup('follow-toggle', 'Enable Follow Alerts', (e.followToggle === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If a message should be said in the channel when someone follows. This also toggles the reward.'))
// Add the the text area for the follow message.
.append(helpers.getTextAreaGroup('follow-message', 'text', 'Follow Message', '', e.followMessage,
'Message said when someone follows the channel. Tags: (name), (alert), (playsound), and (reward)', false))
// Add the the box for the reward.
.append(helpers.getInputGroup('follow-reward', 'number', 'Follow Reward', '', e.followReward,
'Reward given to users who follow the channel.'))
// Add the the box for the reward
.append(helpers.getInputGroup('follow-delay', 'number', 'Follow Delay (Seconds)', '', e.followDelay,
'Delay between the follow messages posted in the channel. Minimum is 5 seconds.')),
function() { // Callback once the user clicks save.
let followToggle = $('#follow-toggle').find(':selected').text() === 'Yes',
followMessage = $('#follow-message'),
followReward = $('#follow-reward'),
followDelay = $('#follow-delay');
// Make sure everything has been filled it correctly.
switch (false) {
case helpers.handleInputString(followMessage):
case helpers.handleInputNumber(followReward, 0):
case helpers.handleInputNumber(followDelay, 5):
break;
default:
// Update settings.
socket.updateDBValues('alerts_follow_update_settings', {
tables: ['settings', 'settings', 'settings', 'settings',],
keys: ['followToggle', 'followReward', 'followMessage', 'followDelay'],
values: [followToggle, followReward.val(), followMessage.val(), followDelay.val()]
}, function() {
socket.sendCommand('alerts_follow_update_settings_cmd', 'followerpanelupdate', function() {
// Close the modal.
$('#follow-alert').modal('toggle');
// Alert the user.
toastr.success('Successfully updated the follower alert settings!');
});
});
}
}).modal('toggle');
});
});
// Subscribe handler settings.
$('#subscribeHandlerSettings').on('click', function() {
socket.getDBValues('alerts_subscribe_get_settings', {
tables: ['subscribeHandler', 'subscribeHandler', 'subscribeHandler', 'subscribeHandler', 'subscribeHandler', 'subscribeHandler', 'subscribeHandler', 'subscribeHandler',
'subscribeHandler', 'subscribeHandler', 'subscribeHandler', 'subscribeHandler', 'subscribeHandler', 'subscribeHandler', 'subscribeHandler', 'subscribeHandler',
'subscribeHandler', 'subscribeHandler', 'subscribeHandler', 'subscribeHandler', 'subscribeHandler', 'subscribeHandler'],
keys: ['subscribeMessage', 'primeSubscribeMessage', 'reSubscribeMessage', 'giftSubMessage', 'subscriberWelcomeToggle', 'primeSubscriberWelcomeToggle',
'reSubscriberWelcomeToggle', 'giftSubWelcomeToggle', 'subscribeReward', 'reSubscribeReward', 'giftSubReward', 'resubEmote', 'subPlan1000', 'subPlan2000', 'subPlan3000',
'massGiftSubWelcomeToggle', 'massGiftSubMessage', 'massGiftSubReward', 'giftAnonSubMessage', 'massAnonGiftSubMessage', 'giftAnonSubWelcomeToggle', 'massAnonGiftSubWelcomeToggle']
}, true, function(e) {
helpers.getModal('subscribe-alert', 'Subscribe Alert Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Add the div for the col boxes.
.append($('<div/>', {
'class': 'panel-group',
'id': 'accordion'
})
// Append first collapsible accordion.
.append(helpers.getCollapsibleAccordion('main-1', 'Subscription Settings', $('<form/>', {
'role': 'form'
})
// Add toggle for normal subscriptions.
.append(helpers.getDropdownGroup('sub-toggle', 'Enable Subscription Alerts', (e.subscriberWelcomeToggle === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If a message should be said in the channel when someone subscribes. This also toggles the reward.'))
// Append message box for the message
.append(helpers.getTextAreaGroup('sub-msg', 'text', 'Subscription Message', '', e.subscribeMessage,
'Message said when someone subscribes to the channel. Tags: (name), (alert), (playsound), (plan), and (reward)', false))
// Appen the reward box
.append(helpers.getInputGroup('sub-reward', 'number', 'Subscription Reward', '', e.subscribeReward,
'Reward given to the user when they subscribe to the channel or get a gifted subscription, subscribe with Twitch Prime.'))))
// Append second collapsible accordion.
.append(helpers.getCollapsibleAccordion('main-2', 'Prime Subscription Settings', $('<form/>', {
'role': 'form'
})
// Add toggle for prime subscriptions.
.append(helpers.getDropdownGroup('primesub-toggle', 'Enable Prime Subscription Alerts', (e.primeSubscriberWelcomeToggle === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If a message should be said in the channel when someone subscribes with Twitch Prime. This also toggles the reward.'))
// Append message box for the message
.append(helpers.getTextAreaGroup('primesub-msg', 'text', 'Prime Subscription Message', '', e.primeSubscribeMessage,
'Message said when someone subscribes to the channel with Twitch Prime. Tags: (name), (alert), (playsound), (plan), and (reward)', false))))
// Append third collapsible accordion.
.append(helpers.getCollapsibleAccordion('main-3', 'Re-subscription Settings', $('<form/>', {
'role': 'form'
})
// Add toggle for resubscriptions.
.append(helpers.getDropdownGroup('resub-toggle', 'Enable Re-subscription Alerts', (e.reSubscriberWelcomeToggle === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If a message should be said in the channel when someone resubscribes. This also toggles the reward.'))
// Append message box for the message
.append(helpers.getTextAreaGroup('resub-msg', 'text', 'Re-subscription Message', '', e.reSubscribeMessage,
'Message said when someone resubscribes to the channel. Tags: (name), (alert), (playsound), (plan), (months), (customemote), and (reward)', false))
// Appen the reward box
.append(helpers.getInputGroup('resub-reward', 'number', 'Re-subscription Reward', '', e.reSubscribeReward,
'Reward given to the user when they resubscribe to the channel.'))
// Appen the emotes box
.append(helpers.getInputGroup('resub-emote', 'text', 'Re-subscription Emote', '', e.resubEmote,
'Emote that will replace (customemote) for the number of months the user has subscribed for.'))))
// Append forth collapsible accordion.
.append(helpers.getCollapsibleAccordion('main-4', 'Gifted Subscription Settings', $('<form/>', {
'role': 'form'
})
// Add toggle for gifted subscriptions.
.append(helpers.getDropdownGroup('gifsub-toggle', 'Enable Gift Subscription Alerts', (e.giftSubWelcomeToggle === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If a message should be said in the channel when someone gifts a subscription. This also toggles the reward.'))
// Append message box for the message
.append(helpers.getTextAreaGroup('gifsub-msg', 'text', 'Gift Subscription Message', '', e.giftSubMessage,
'Message said when someone gifts a subscription to the channel. Tags: (name), (alert), (playsound), (recipient), (plan), (months), and (reward)', false))
// Appen the reward box
.append(helpers.getInputGroup('gifsub-reward', 'number', 'Gift Subscription Reward', '', e.giftSubReward,
'Reward given to the user who bought the subscription.'))))
// Append forth collapsible accordion.
.append(helpers.getCollapsibleAccordion('main-5', 'Mystery Gift Subscription Settings', $('<form/>', {
'role': 'form'
})
// Add toggle for gifted subscriptions.
.append(helpers.getDropdownGroup('mass-gifsub-toggle', 'Enable Mystery Gift Subscription Alerts', (e.massGiftSubWelcomeToggle === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If a message should be said in the channel when someone gifts multiple subscriptions. This also toggles the reward.'))
// Append message box for the message
.append(helpers.getTextAreaGroup('mass-gifsub-msg', 'text', 'Mystery Gift Subscription Message', '', e.massGiftSubMessage,
'Message said when someone gifts multiple subscriptions to the channel. Tags: (name), (alert), (playsound), (amount), and (reward)', false))
// Appen the reward box
.append(helpers.getInputGroup('mass-gifsub-reward', 'number', 'Mystery Gift Subscription Reward', '', e.massGiftSubReward,
'Reward given to the user who bought the subscription. This is a multiplier. (reward * amount gifted)'))))
// Append sixth collapsible accordion.
.append(helpers.getCollapsibleAccordion('main-6', 'Anonymous Gift Subscription Settings', $('<form/>', {
'role': 'form'
})
// Add toggle for gifted subscriptions.
.append(helpers.getDropdownGroup('anon-gifsub-toggle', 'Enable Anonymous Gift Subscription Alerts', (e.giftAnonSubWelcomeToggle === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If a message should be said in the channel when someone gifts an anonymous subscription. This also toggles the reward.'))
// Append message box for the message
.append(helpers.getTextAreaGroup('anon-gifsub-msg', 'text', 'Anonymous Gift Subscription Message', '', e.giftAnonSubMessage,
'Message said when someone anonymously gifts a subscription to the channel. Tags: (name), (alert), (playsound), (plan), (amount), and (reward)', false))
// Appen the reward box
.append(helpers.getInputGroup('anon-gifsub-reward', 'number', 'Anonymous Gift Subscription Reward', '', e.subscribeReward,
'Reward given to the user who the subscription was gifted to. This is the same as the normal subscriptions reward', true))))
// Append sixth collapsible accordion.
.append(helpers.getCollapsibleAccordion('main-7', 'Anonymous Mystery Gift Subscription Settings', $('<form/>', {
'role': 'form'
})
// Add toggle for gifted subscriptions.
.append(helpers.getDropdownGroup('anon-mass-gifsub-toggle', 'Enable Anonymous Mystery Gift Subscription Alerts', (e.massAnonGiftSubWelcomeToggle === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If a message should be said in the channel when an anonymous user gifts multiple subscriptions. This also toggles the reward.'))
// Append message box for the message
.append(helpers.getTextAreaGroup('anon-mass-gifsub-msg', 'text', 'Anonymous Gift Mystery Subscription Message', '', e.massAnonGiftSubMessage,
'Message said when someone anonymously mass gifts subscriptions to the channel. Tags: (name), and (amount)', false))))
// Tier settings
.append(helpers.getCollapsibleAccordion('main-8', 'Tier Settings', $('<form/>', {
'role': 'form'
})
// Append first sub plan name
.append(helpers.getInputGroup('sub-1000', 'text', 'Subscription Plan Name 1', '', e.subPlan1000, 'Name given to the tier one plan.'))
// Append first sub plan name
.append(helpers.getInputGroup('sub-2000', 'text', 'Subscription Plan Name 2', '', e.subPlan2000, 'Name given to the tier two plan.'))
// Append first sub plan name
.append(helpers.getInputGroup('sub-3000', 'text', 'Subscription Plan Name 3', '', e.subPlan3000, 'Name given to the tier three plan.'))))),
function() { // Callback once the user clicks save.
let subToggle = $('#sub-toggle').find(':selected').text() === 'Yes',
subMsg = $('#sub-msg'),
subReward = $('#sub-reward'),
primeSubToggle = $('#primesub-toggle').find(':selected').text() === 'Yes',
primeSubMsg = $('#primesub-msg'),
reSubToggle = $('#resub-toggle').find(':selected').text() === 'Yes',
reSubMsg = $('#resub-msg'),
reSubReward = $('#resub-reward'),
reSubEmote = $('#resub-emote'),
gifSubToggle = $('#gifsub-toggle').find(':selected').text() === 'Yes',
gifSubMsg = $('#gifsub-msg'),
anonGifSubToggle = $('#anon-gifsub-toggle').find(':selected').text() === 'Yes',
anonGifSubMsg = $('#anon-gifsub-msg'),
gifSubReward = $('#gifsub-reward'),
massGiftSubToggle = $('#mass-gifsub-toggle').find(':selected').text() === 'Yes',
massGiftSubMsg = $('#mass-gifsub-msg'),
anonMassGiftSubToggle = $('#anon-mass-gifsub-toggle').find(':selected').text() === 'Yes',
anonMassGiftSubMsg = $('#anon-mass-gifsub-msg'),
massGiftSubReward = $('#mass-gifsub-reward'),
tierOne = $('#sub-1000'),
tierTwo = $('#sub-2000'),
tierThree = $('#sub-3000');
// Make sure the user has someone in each box.
switch (false) {
case helpers.handleInputString(subMsg):
case helpers.handleInputNumber(subReward, 0):
case helpers.handleInputString(primeSubMsg):
case helpers.handleInputString(reSubMsg):
case helpers.handleInputNumber(reSubReward, 0):
case helpers.handleInputString(gifSubMsg):
case helpers.handleInputString(anonGifSubMsg):
case helpers.handleInputNumber(gifSubReward, 0):
case helpers.handleInputString(massGiftSubMsg):
case helpers.handleInputString(anonMassGiftSubMsg):
case helpers.handleInputNumber(massGiftSubReward, 0):
case helpers.handleInputString(tierOne):
case helpers.handleInputString(tierTwo):
case helpers.handleInputString(tierThree):
break;
default:
socket.updateDBValues('alerts_subscribe_update_settings', {
tables: ['subscribeHandler', 'subscribeHandler', 'subscribeHandler', 'subscribeHandler', 'subscribeHandler', 'subscribeHandler', 'subscribeHandler', 'subscribeHandler',
'subscribeHandler', 'subscribeHandler', 'subscribeHandler', 'subscribeHandler', 'subscribeHandler', 'subscribeHandler', 'subscribeHandler', 'subscribeHandler',
'subscribeHandler', 'subscribeHandler', 'subscribeHandler', 'subscribeHandler', 'subscribeHandler', 'subscribeHandler'],
keys: ['subscribeMessage', 'primeSubscribeMessage', 'reSubscribeMessage', 'giftSubMessage', 'subscriberWelcomeToggle', 'primeSubscriberWelcomeToggle',
'reSubscriberWelcomeToggle', 'giftSubWelcomeToggle', 'subscribeReward', 'reSubscribeReward', 'giftSubReward', 'resubEmote', 'subPlan1000', 'subPlan2000', 'subPlan3000',
'massGiftSubWelcomeToggle', 'massGiftSubMessage', 'massGiftSubReward', 'giftAnonSubMessage', 'massAnonGiftSubMessage', 'giftAnonSubWelcomeToggle', 'massAnonGiftSubWelcomeToggle'],
values: [subMsg.val(), primeSubMsg.val(), reSubMsg.val(), gifSubMsg.val(), subToggle, primeSubToggle, reSubToggle, gifSubToggle, subReward.val(), reSubReward.val(),
gifSubReward.val(), reSubEmote.val(), tierOne.val(), tierTwo.val(), tierThree.val(), massGiftSubToggle, massGiftSubMsg.val(), massGiftSubReward.val(),
anonGifSubMsg.val(), anonMassGiftSubMsg.val(), anonGifSubToggle, anonMassGiftSubToggle]
}, function() {
socket.sendCommand('alerts_subscribe_update_settings_cmd', 'subscriberpanelupdate', function() {
// Close the modal.
$('#subscribe-alert').modal('toggle');
// Alert the user.
toastr.success('Successfully updated subscription alert settings!');
});
});
}
}).modal('toggle');
});
});
// Host settings button.
$('#hostHandlerSettings').on('click', function() {
socket.getDBValues('alerts_get_host_settings', {
tables: ['settings', 'settings', 'settings', 'settings', 'settings', 'settings', 'settings', 'settings', 'settings'],
keys: ['hostReward', 'autoHostReward', 'hostMinViewerCount', 'hostMinCount', 'hostMessage', 'autoHostMessage', 'hostHistory', 'hostToggle', 'autoHostToggle']
}, true, function(e) {
helpers.getModal('host-alert', 'Host Alert Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Add the div for the col boxes.
.append($('<div/>', {
'class': 'panel-group',
'id': 'accordion'
})
// Append first collapsible accordion.
.append(helpers.getCollapsibleAccordion('main-1', 'Host Settings', $('<form/>', {
'role': 'form'
})
// Add toggle for normal hosts
.append(helpers.getDropdownGroup('host-toggle', 'Enable Host Alerts', (e.hostToggle === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If a message should be said in the channel when someone hosts the channel.'))
// Append message box for the message
.append(helpers.getTextAreaGroup('host-msg', 'text', 'Host Message', '', e.hostMessage,
'Message said when someone Hosts the channel. Tags: (name), (alert), (playsound), (reward), and (viewers)', false))
// Appen the reward box
.append(helpers.getInputGroup('host-reward', 'number', 'Host Reward', '', e.hostReward,
'Reward given to the user when they hosts to the channel.'))))
// Append second collapsible accordion.
.append(helpers.getCollapsibleAccordion('main-2', 'Auto-Host Settings', $('<form/>', {
'role': 'form'
})
// Add toggle for normal hosts
.append(helpers.getDropdownGroup('autohost-toggle', 'Enable Auto-Host Alerts', (e.autoHostToggle === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If a message should be said in the channel when someone auto-hosts the channel.'))
// Append message box for the message
.append(helpers.getTextAreaGroup('autohost-msg', 'text', 'Auto-Host Message', '', e.autoHostMessage,
'Message said when someone auto-hosts the channel. Tags: (name), (alert), (playsound), (reward), and (viewers)', false))
// Appen the reward box
.append(helpers.getInputGroup('autohost-reward', 'number', 'Auto-Host Reward', '', e.autoHostReward,
'Reward given to the user when they auto-hosts the channel.'))))
// Append third collapsible accordion.
.append(helpers.getCollapsibleAccordion('main-3', 'Extra Settings', $('<form/>', {
'role': 'form'
})
// Add toggle for host history.
.append(helpers.getDropdownGroup('host-history', 'Enable Host History', (e.hostHistory === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If all hosts should be logged for future viewing.'))
// Min host box reward.
.append(helpers.getInputGroup('host-minpoint', 'number', 'Minimum Viewers for Host Reward', '', e.hostMinViewerCount,
'Minimum amount of viewers the users has to host with to get a reward.'))
// Min host box alert.
.append(helpers.getInputGroup('host-minalert', 'number', 'Minimum Viewers for Host Alert', '', e.hostMinCount,
'Minimum amount of viewers the users has to host with to trigger the alert.'))))),
function() { // Callback once the user clicks save.
let hostToggle = $('#host-toggle').find(':selected').text() === 'Yes',
hostMsg = $('#host-msg'),
hostReward = $('#host-reward'),
autoHostToggle = $('#autohost-toggle').find(':selected').text() === 'Yes',
autoHostMsg = $('#autohost-msg'),
autoHostReward = $('#autohost-reward'),
hostHistory = $('#host-history').find(':selected').text() === 'Yes',
hostMinPoints = $('#host-minpoint'),
hostMinAlert = $('#host-minalert');
// Make sure the user has someone in each box.
switch (false) {
case helpers.handleInputString(hostMsg):
case helpers.handleInputNumber(hostReward, 0):
case helpers.handleInputString(autoHostMsg):
case helpers.handleInputNumber(autoHostReward, 0):
case helpers.handleInputNumber(hostMinPoints, 0):
case helpers.handleInputNumber(hostMinAlert, 0):
break;
default:
socket.updateDBValues('alerts_update_host_settings', {
tables: ['settings', 'settings', 'settings', 'settings', 'settings', 'settings', 'settings',
'settings', 'settings'],
keys: ['hostReward', 'autoHostReward', 'hostMinViewerCount', 'hostMinCount', 'hostMessage',
'autoHostMessage', 'hostHistory', 'hostToggle', 'autoHostToggle'],
values: [hostReward.val(), autoHostReward.val(), hostMinPoints.val(), hostMinAlert.val(),
hostMsg.val(), autoHostMsg.val(), hostHistory, hostToggle, autoHostToggle]
}, function() {
socket.sendCommand('alerts_update_host_settings_cmd', 'reloadhost', function() {
// Close the modal.
$('#host-alert').modal('toggle');
// Alert the user.
toastr.success('Successfully updated host alert settings!');
});
});
}
}).modal('toggle');
});
});
// Bits alert settings.
$('#bitsHandlerSettings').on('click', function() {
socket.getDBValues('alerts_get_bits_settings', {
tables: ['bitsSettings', 'bitsSettings', 'bitsSettings'],
keys: ['toggle', 'message', 'minimum']
}, true, function(e) {
helpers.getModal('bits-alert', 'Bits Alert Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Add the toggle for bits alerts.
.append(helpers.getDropdownGroup('bits-toggle', 'Enable Bits Alerts', (e.toggle === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If a message should be said in the channel when someone cheers.'))
// Add the the text area for the bits message.
.append(helpers.getTextAreaGroup('bits-message', 'text', 'Bits Message', '', e.message,
'Message said when someone cheers in the the channel. Tags: (name), (alert), (playsound), (message), and (amount)', false))
// Add the box for the reward.
.append(helpers.getInputGroup('bits-minimum', 'number', 'Bits Minimum', '', e.minimum, 'Amount of bits needed to trigger the alert.')),
function() { // Callback once the user clicks save.
let bitsToggle = $('#bits-toggle').find(':selected').text() === 'Yes',
bitsMsg = $('#bits-message'),
bitsMin = $('#bits-minimum');
// Make sure the user has someone in each box.
switch (false) {
case helpers.handleInputString(bitsMsg):
case helpers.handleInputNumber(bitsMin):
break;
default:
socket.updateDBValues('alerts_update_bits_settings', {
tables: ['bitsSettings', 'bitsSettings', 'bitsSettings'],
keys: ['toggle', 'message', 'minimum'],
values: [bitsToggle, bitsMsg.val(), bitsMin.val()]
}, function() {
socket.sendCommand('alerts_update_bits_settings_cmd', 'reloadbits', function() {
// Close the modal.
$('#bits-alert').modal('toggle');
// Alert the user.
toastr.success('Successfully updated Bits alert settings!');
});
});
}
}).modal('toggle');
});
});
// Clip alert settings.
$('#clipHandlerSettings').on('click', function() {
socket.getDBValues('alerts_get_clip_settings', {
tables: ['clipsSettings', 'clipsSettings'],
keys: ['toggle', 'message']
}, true, function(e) {
helpers.getModal('clip-alert', 'Clip Alert Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Add the toggle for clip alerts.
.append(helpers.getDropdownGroup('clip-toggle', 'Enable Clip Alerts', (e.toggle === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If a message should be said in the channel when someone creates a clip.'))
// Add the text area for the clips message.
.append(helpers.getTextAreaGroup('clip-message', 'text', 'Clip Message', '', e.message,
'Message said when someone creates a clip. Tags: (name), (alert), (playsound), (title), and (url)', false)),
function() { // Callback once the user clicks save.
let clipToggle = $('#clip-toggle').find(':selected').text() === 'Yes',
clipMsg = $('#clip-message');
// Make sure the user has someone in each box.
switch (false) {
case helpers.handleInputString(clipMsg):
break;
default:
socket.updateDBValues('alerts_update_clip_settings', {
tables: ['clipsSettings', 'clipsSettings'],
keys: ['toggle', 'message'],
values: [clipToggle, clipMsg.val()]
}, function() {
socket.sendCommand('alerts_update_clip_settings_cmd', 'reloadclip', function() {
// Close the modal.
$('#clip-alert').modal('toggle');
// Alert the user.
toastr.success('Successfully updated Clip alert settings!');
});
});
}
}).modal('toggle');
});
});
// Raid settings.
$('#raidHandlerSettings').on('click', function() {
socket.getDBValues('alerts_get_raid_settings', {
tables: ['raidSettings', 'raidSettings', 'raidSettings', 'raidSettings', 'raidSettings', 'raidSettings'],
keys: ['raidToggle', 'newRaidIncMessage', 'raidIncMessage', 'raidReward', 'raidOutMessage', 'raidOutSpam']
}, true, function(e) {
helpers.getModal('raid-alert', 'Raid Alert Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Add the div for the col boxes.
.append($('<div/>', {
'class': 'panel-group',
'id': 'accordion'
})
// Append first collapsible accordion.
.append(helpers.getCollapsibleAccordion('main-1', 'Incoming Raid Settings', $('<form/>', {
'role': 'form'
})
// Add the toggle for raid alerts.
.append(helpers.getDropdownGroup('raid-toggle', 'Enable Raid Alerts', (e.raidToggle === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If people who raid your channel should be noticed by the bot with a message.'))
// Add the text area for the new raid message.
.append(helpers.getTextAreaGroup('new-raid-message', 'text', 'New Raider Message', '', e.newRaidIncMessage,
'Message said when someone raids your channel for the first time. Tags: (username), (alert), (playsound), (viewers), (url), (reward) and (game)', false))
// Add the text area for the raid message.
.append(helpers.getTextAreaGroup('raid-message', 'text', 'Raider Message', '', e.raidIncMessage,
'Message said when someone raids your channel. Tags: (username), (alert), (playsound), (viewers), (url), (times), (reward) and (game)', false))
// Appen the reward box
.append(helpers.getInputGroup('raid-reward', 'number', 'Raid Reward', '', e.raidReward,
'Reward given to the users who raid your channel.'))))
// Append second collapsible accordion.
.append(helpers.getCollapsibleAccordion('main-2', 'Outgoing Raid Settings', $('<form/>', {
'role': 'form'
})
// Add the text area for the new raid message.
.append(helpers.getTextAreaGroup('out-raid-message', 'text', 'Raiding Message', '', e.raidOutMessage,
'Message said in chat when you use the !raid command to raid a channel. Tags: (username) and (url)', false))
// Appen the spam box
.append(helpers.getInputGroup('raid-spam', 'number', 'Raiding Message Spam', '', e.raidOutSpam,
'How many times the message when using the !raid command will be said in the chat. Maximum is 10 times.'))))),
function() {
let raidToggle = $('#raid-toggle').find(':selected').text() === 'Yes',
raidNewMsg = $('#new-raid-message'),
raidMsg = $('#raid-message'),
raidReward = $('#raid-reward'),
raidOutMsg = $('#out-raid-message'),
raidMsgSpam = $('#raid-spam');
switch (false) {
case helpers.handleInputString(raidNewMsg):
case helpers.handleInputString(raidMsg):
case helpers.handleInputNumber(raidReward, 0):
case helpers.handleInputString(raidOutMsg):
case helpers.handleInputNumber(raidMsgSpam, 1, 10):
break;
default:
socket.updateDBValues('raid_setting_update', {
tables: ['raidSettings', 'raidSettings', 'raidSettings', 'raidSettings', 'raidSettings', 'raidSettings'],
keys: ['raidToggle', 'newRaidIncMessage', 'raidIncMessage', 'raidReward', 'raidOutMessage', 'raidOutSpam'],
values: [raidToggle, raidNewMsg.val(), raidMsg.val(), raidReward.val(), raidOutMsg.val(), raidMsgSpam.val()]
}, function() {
socket.sendCommand('raid_setting_update_cmd', 'reloadraid', function() {
// Alert the user.
toastr.success('Successfully updated the raid settings!');
// Close the modal.
$('#raid-alert').modal('toggle');
});
});
}
}).modal('toggle');
});
});
// Greeting settings.
$('#greetingSystemSettings').on('click', function() {
socket.getDBValues('alerts_get_greeting_settings', {
tables: ['greeting', 'greeting'],
keys: ['autoGreetEnabled', 'cooldown']
}, true, function(e) {
helpers.getModal('greeting-alert', 'Greeting Alert Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Add the toggle for greeting alerts.
.append(helpers.getDropdownGroup('greeting-toggle', 'Enable Greeting Alerts', (e.autoGreetEnabled === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If users should be allowed to set a message for when they join the channel.'))
// Add the input for the greeting reward.
.append(helpers.getInputGroup('greeting-cooldown', 'number', 'Greeting Cooldown (Hours)', '', (parseInt(e.cooldown) / 36e5),
'How long the greeting message per user will be in hours. Minimum is 5 hours.')),
function() { // Callback once the user clicks save.
let greetingToggle = $('#greeting-toggle').find(':selected').text() === 'Yes',
greetingCooldown = $('#greeting-cooldown');
// Make sure the user has someone in each box.
switch (false) {
case helpers.handleInputNumber(greetingCooldown, 5):
break;
default:
socket.updateDBValues('alerts_update_greeting_settings', {
tables: ['greeting', 'greeting'],
keys: ['autoGreetEnabled', 'cooldown'],
values: [greetingToggle, (parseInt(greetingCooldown.val()) * 36e5)]
}, function() {
socket.sendCommand('alerts_update_greeting_settings_cmd', 'greetingspanelupdate', function() {
// Close the modal.
$('#greeting-alert').modal('toggle');
// Alert the user.
toastr.success('Successfully updated greeting alert settings!');
});
});
}
}).modal('toggle');
});
});
// StreamLabs settings.
$('#donationHandlerSettings').on('click', function() {
socket.getDBValues('alerts_get_streamlabs_settings', {
tables: ['donations', 'donations', 'donations'],
keys: ['announce', 'reward', 'message']
}, true, function(e) {
helpers.getModal('streamlabs-alert', 'StreamLabs Alert Settings', 'Save', $('<form/>', {
'role': 'form'
})
/// Add the toggle for streamlabs alerts.
.append(helpers.getDropdownGroup('streamlabs-toggle', 'Enable StreamLabs Alerts', (e.announce === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If StreamLabs tips should be posted in the chat.'))
// Add the the text area for the tip message.
.append(helpers.getTextAreaGroup('streamlabs-message', 'text', 'Tip Message', '', e.message,
'Message posted in the channel when someone tips with StreamLabs. Tags: (name), (amount), (amount.toFixed(0)), (points), (pointname), (currency), and (message)'))
// Add the the box for the tip reward
.append(helpers.getInputGroup('streamlabs-reward', 'number', 'Tip Reward Multiplier', '', e.reward, 'Reward multiplier for the reward.')),
function() { // Callback once the user clicks save.
let tipToggle = $('#streamlabs-toggle').find(':selected').text() === 'Yes',
tipMessage = $('#streamlabs-message'),
tipReward = $('#streamlabs-reward');
// Make sure the user has someone in each box.
switch (false) {
case helpers.handleInputString(tipMessage):
case helpers.handleInputNumber(tipReward, 0):
break;
default:
socket.updateDBValues('alerts_update_streamlabs_settings', {
tables: ['donations', 'donations', 'donations'],
keys: ['announce', 'reward', 'message'],
values: [tipToggle, tipReward.val(), tipMessage.val()]
}, function() {
socket.sendCommand('alerts_update_streamlabs_settings_cmd', 'donationpanelupdate', function() {
// Close the modal.
$('#streamlabs-alert').modal('toggle');
// Alert the user.
toastr.success('Successfully updated StreamLabs alert settings!');
});
});
}
}).modal('toggle');
});
});
// TipeeeStream settings.
$('#tipeeeStreamHandlerSettings').on('click', function() {
socket.getDBValues('alerts_get_tipeeestream_settings', {
tables: ['tipeeeStreamHandler', 'tipeeeStreamHandler', 'tipeeeStreamHandler'],
keys: ['toggle', 'reward', 'message']
}, true, function(e) {
helpers.getModal('tipeeestream-alert', 'TipeeeStream Alert Settings', 'Save', $('<form/>', {
'role': 'form'
})
/// Add the toggle for streamlabs alerts.
.append(helpers.getDropdownGroup('tipeeestream-toggle', 'Enable TipeeeStream Alerts', (e.toggle === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If TipeeeStream tips should be posted in the chat.'))
// Add the the text area for the tip message.
.append(helpers.getTextAreaGroup('tipeeestream-message', 'text', 'Tip Message', '', e.message,
'Message posted in the channel when someone tips with TipeeeStream. Tags: (name), (amount), (reward), (formattedamount), and (message)'))
// Add the the box for the tip reward
.append(helpers.getInputGroup('tipeeestream-reward', 'number', 'Tip Reward Multiplier', '', e.reward, 'Reward multiplier for the reward.')),
function() { // Callback once the user clicks save.
let tipToggle = $('#tipeeestream-toggle').find(':selected').text() === 'Yes',
tipMessage = $('#tipeeestream-message'),
tipReward = $('#tipeeestream-reward');
// Make sure the user has someone in each box.
switch (false) {
case helpers.handleInputString(tipMessage):
case helpers.handleInputNumber(tipReward, 0):
break;
default:
socket.updateDBValues('alerts_update_tipeeestream_settings', {
tables: ['tipeeeStreamHandler', 'tipeeeStreamHandler', 'tipeeeStreamHandler'],
keys: ['toggle', 'reward', 'message'],
values: [tipToggle, tipReward.val(), tipMessage.val()]
}, function() {
socket.sendCommand('alerts_update_tipeeestream_settings_cmd', 'tipeeestreamreload', function() {
// Close the modal.
$('#tipeeestream-alert').modal('toggle');
// Alert the user.
toastr.success('Successfully updated TipeeeStream alert settings!');
});
});
}
}).modal('toggle');
});
});
// StreamElements settings.
$('#streamElementsHandlerSettings').on('click', function() {
socket.getDBValues('alerts_get_streamelements_settings', {
tables: ['streamElementsHandler', 'streamElementsHandler', 'streamElementsHandler'],
keys: ['toggle', 'reward', 'message']
}, true, function(e) {
helpers.getModal('streamelements-alert', 'StreamElements Alert Settings', 'Save', $('<form/>', {
'role': 'form'
})
/// Add the toggle for streamelements alerts.
.append(helpers.getDropdownGroup('streamelements-toggle', 'Enable StreamElements Alerts', (e.toggle === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If StreamElements tips should be posted in the chat.'))
// Add the the text area for the tip message.
.append(helpers.getTextAreaGroup('streamelements-message', 'text', 'Tip Message', '', e.message,
'Message posted in the channel when someone tips with StreamElements. Tags: (name), (amount), (reward), (currency), and (message)'))
// Add the the box for the tip reward
.append(helpers.getInputGroup('streamelements-reward', 'number', 'Tip Reward Multiplier', '', e.reward, 'Reward multiplier for the reward.')),
function() { // Callback once the user clicks save.
let tipToggle = $('#streamelements-toggle').find(':selected').text() === 'Yes',
tipMessage = $('#streamelements-message'),
tipReward = $('#streamelements-reward');
// Make sure the user has someone in each box.
switch (false) {
case helpers.handleInputString(tipMessage):
case helpers.handleInputNumber(tipReward, 0):
break;
default:
socket.updateDBValues('alerts_update_streamelements_settings', {
tables: ['streamElementsHandler', 'streamElementsHandler', 'streamElementsHandler'],
keys: ['toggle', 'reward', 'message'],
values: [tipToggle, tipReward.val(), tipMessage.val()]
}, function() {
socket.sendCommand('alerts_update_streamelements_settings_cmd', 'streamelementsreload', function() {
// Close the modal.
$('#streamelements-alert').modal('toggle');
// Alert the user.
toastr.success('Successfully updated StreamElements alert settings!');
});
});
}
}).modal('toggle');
});
});
// Twitter settings.
$('#twitterHandlerSettings').on('click', function() {
socket.getDBValues('alerts_get_twitter_settings', {
tables: ['twitter', 'twitter', 'twitter', 'twitter', 'twitter', 'twitter', 'twitter', 'twitter', 'twitter', 'twitter',
'twitter', 'twitter', 'twitter', 'twitter', 'twitter', 'twitter', 'twitter', 'twitter', 'twitter'],
keys: ['message_online', 'message_gamechange', 'message_update', 'polldelay_mentions', 'polldelay_retweets', 'polldelay_hometimeline', 'polldelay_usertimeline', 'postdelay_update',
'reward_points', 'reward_cooldown', 'poll_mentions', 'poll_retweets', 'poll_hometimeline', 'poll_usertimeline', 'post_online', 'post_gamechange', 'post_update', 'reward_toggle', 'reward_announce']
}, true, function(e) {
helpers.getModal('twitter-alert', 'Twitter Alert Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Add the div for the col boxes.
.append($('<div/>', {
'class': 'panel-group',
'id': 'accordion'
})
// Append first collapsible accordion.
.append(helpers.getCollapsibleAccordion('main-1', 'Twitter Configuration', $('<form/>', {
'role': 'form'
})
// Add the toggle for mentions
.append(helpers.getDropdownGroup('poll-mentions', 'Query Mentions', (e.poll_mentions === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If PhantomBot should look for mentions on your timeline and post them in chat.'))
// Add the toggle for retweets
.append(helpers.getDropdownGroup('poll-retweets', 'Query Retweets', (e.poll_retweets === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If PhantomBot should look for your retweets and post them in chat.'))
// Add the toggle for home timeline
.append(helpers.getDropdownGroup('poll-home', 'Query Home Timeline', (e.poll_hometimeline === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If PhantomBot should look for anything on your timeline and post it in chat.'))
// Add the toggle for user timeline
.append(helpers.getDropdownGroup('poll-user', 'Query User Timeline', (e.poll_usertimeline === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If PhantomBot should look for anything on your timeline posted by you and post it in chat.'))
// Query interval for mentions
.append(helpers.getInputGroup('query-mentions', 'number', 'Query Interval for Mentions (Seconds)', '', e.polldelay_mentions, 'How often the bot looks for mentions. Minimum is 60 seconds.'))
// Query interval for retweets
.append(helpers.getInputGroup('query-retweets', 'number', 'Query Interval for Retweets (Seconds)', '', e.polldelay_retweets, 'How often the bot looks for retweets. Minimum is 60 seconds.'))
// Query interval for mentions
.append(helpers.getInputGroup('query-home', 'number', 'Query Interval for Home TimeLine (Seconds)', '', e.polldelay_hometimeline, 'How often the bot looks for home timeline. Minimum is 60 seconds.'))
// Query interval for mentions
.append(helpers.getInputGroup('query-user', 'number', 'Query Interval for User TimeLine (Seconds)', '', e.polldelay_usertimeline, 'How often the bot looks for user timeline. Minimum is 15 seconds.'))))
// Append second collapsible accordion.
.append(helpers.getCollapsibleAccordion('main-2', 'Twitter Retweet Configuration', $('<form/>', {
'role': 'form'
})
// Add the toggle for mentions
.append(helpers.getDropdownGroup('retweet-toggle', 'Enable Retweet Rewards', (e.reward_toggle === 'true' ? 'Yes' : 'No'), ['Yes', 'No'], 'If PhantomBot should reward users who Retweet your Tweets.'))
// Add the toggle for retweets
.append(helpers.getDropdownGroup('retweet-toggle-msg', 'Enable Retweet Rewards Announcements', (e.reward_announce === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If PhantomBot should announce that it rewarded a user for Reetweeting your Tweets.'))
// Query interval for mentions
.append(helpers.getInputGroup('retweet-reward', 'number', 'Retweet Reward', '', e.reward_points, 'Reward given to user you Retweet your Tweets.'))
// Query interval for mentions
.append(helpers.getInputGroup('retweet-cooldown', 'number', 'Retweet Cooldown (Hours)', '', e.reward_cooldown, 'Cooldown for how many times the bot can reward a user for Retweets.'))))
// Append third collapsible accordion.
.append(helpers.getCollapsibleAccordion('main-3', 'Alert Settings', $('<form/>', {
'role': 'form'
})
// Add the toggle for the online Tweet.
.append(helpers.getDropdownGroup('online-toggle', 'Enable Online Tweet', (e.post_online === 'true' ? 'Yes' : 'No'), ['Yes', 'No'], 'Let the bot Tweet for you when you go live.'))
// Add the toggle for the game Tweet.
.append(helpers.getDropdownGroup('game-toggle', 'Enable Game Change Tweet', (e.post_gamechange === 'true' ? 'Yes' : 'No'), ['Yes', 'No'], 'Let the bot Tweet for you when you switch games.'))
// Add the toggle for the timed Tweet.
.append(helpers.getDropdownGroup('timed-toggle', 'Enable Timed Online Tweet', (e.post_update === 'true' ? 'Yes' : 'No'), ['Yes', 'No'], 'Let the bot Tweet for you every X hours saying that you\'re still live.'))
// Add the the text area for online message
.append(helpers.getTextAreaGroup('online-msg', 'text', 'Online Tweet', '', e.message_online, 'Message that will be Tweeted out when you go line. Tags: (title), (game), and (twitchurl)', false))
// Add the the text area for online message
.append(helpers.getTextAreaGroup('game-msg', 'text', 'Game Change Tweet', '', e.message_gamechange, 'Message that will be Tweeted out when you switch games. Tags: (title), (game), and (twitchurl)', false))
// Add the the text area for online message
.append(helpers.getTextAreaGroup('timed-msg', 'text', 'Timed Online Tweet', '', e.message_update, 'Message that will be Tweeted out every so often. Tags: (title), (game), (uptime), and (twitchurl)', false))
// timed message minutes.
.append(helpers.getInputGroup('timed-msg-time', 'number', 'Timed Message Interval (Minutes)', '', e.postdelay_update, 'How often in minutes the online timed message gets posted. Minimum is 180 minutes.'))))),
function() { // Callback once the user clicks save.
let onlineToggle = $('#online-toggle').find(':selected').text() === 'Yes',
gameToggle = $('#game-toggle').find(':selected').text() === 'Yes',
timedToggle = $('#timed-toggle').find(':selected').text() === 'Yes',
onlineMsg = $('#online-msg'),
gameMsg = $('#game-msg'),
timedMsg = $('#timed-msg'),
timedTime = $('#timed-msg-time'),
mentionToggle = $('#poll-mentions').find(':selected').text() === 'Yes',
rtToggle = $('#poll-retweets').find(':selected').text() === 'Yes',
homeToggle = $('#poll-home').find(':selected').text() === 'Yes',
userToggle = $('#poll-user').find(':selected').text() === 'Yes',
mentionTime = $('#query-mentions'),
rtTime = $('#query-retweets'),
homeTime = $('#query-home'),
userTime = $('#query-user'),
rtRewardToggle = $('#retweet-toggle').find(':selected').text() === 'Yes',
rtRewardToggleMsg = $('#retweet-toggle-msg').find(':selected').text() === 'Yes',
rtReward = $('#retweet-reward'),
rtCooldown = $('#retweet-cooldown');
// Make sure the user filled in everything.
switch (false) {
case helpers.handleInputString(onlineMsg):
case helpers.handleInputString(gameMsg):
case helpers.handleInputString(timedMsg):
case helpers.handleInputNumber(timedTime, 180):
case helpers.handleInputNumber(mentionTime, 60):
case helpers.handleInputNumber(rtTime, 60):
case helpers.handleInputNumber(homeTime, 60):
case helpers.handleInputNumber(userTime, 15):
case helpers.handleInputNumber(rtReward, 0):
case helpers.handleInputNumber(rtCooldown, 0):
break;
default:
socket.updateDBValues('alerts_get_twitter_settings', {
tables: ['twitter', 'twitter', 'twitter', 'twitter', 'twitter', 'twitter', 'twitter', 'twitter', 'twitter', 'twitter',
'twitter', 'twitter', 'twitter', 'twitter', 'twitter', 'twitter', 'twitter', 'twitter', 'twitter'],
keys: ['message_online', 'message_gamechange', 'message_update', 'polldelay_mentions', 'polldelay_retweets', 'polldelay_hometimeline', 'polldelay_usertimeline', 'postdelay_update',
'reward_points', 'reward_cooldown', 'poll_mentions', 'poll_retweets', 'poll_hometimeline', 'poll_usertimeline', 'post_online', 'post_gamechange', 'post_update', 'reward_toggle', 'reward_announce'],
values: [onlineMsg.val(), gameMsg.val(), timedMsg.val(), mentionTime.val(), rtTime.val(), homeTime.val(), userTime.val(), timedTime.val(), rtReward.val(), rtCooldown.val(), mentionToggle,
rtToggle, homeToggle, userToggle, onlineToggle, gameToggle, timedToggle, rtRewardToggle, rtRewardToggleMsg]
}, function() {
// Close the modal.
$('#twitter-alert').modal('toggle');
// Alert the user.
toastr.success('Successfully updated the Twitter alert settings!');
});
}
}).modal('toggle');
});
});
});

View File

@@ -0,0 +1,466 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Function that querys all of the data we need.
$(run = function() {
// Check if the module is enabled.
socket.getDBValue('audio_module', 'modules', './systems/audioPanelSystem.js', function(e) {
// If the module is off, don't load any data.
if (!helpers.handleModuleLoadUp('audioHookModule', e.modules)) {
// Disable the tab selection.
$('#audiohooks_t, #audiocommands_t').addClass('disabled').parent().addClass('disabled');
return;
} else {
// Enable the tab selection.
$('#audiohooks_t, #audiocommands_t').removeClass('disabled').parent().removeClass('disabled');
}
// Get all audio hooks.
socket.getDBTableValues('get_audio_hooks', 'audio_hooks', function(results) {
let tableData = [];
for (let i = 0; i < results.length; i++) {
tableData.push([
results[i].key,
$('<div/>', {
'class': 'btn-group'
}).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-danger',
'style': 'float: right',
'data-audio': results[i].key,
'html': $('<i/>', {
'class': 'fa fa-trash'
})
})).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-success',
'style': 'float: right',
'data-toggle': 'tooltip',
'title': 'This plays the audio hooks through the panel and not the browser source.',
'data-audio': results[i].value,
'html': $('<i/>', {
'class': 'fa fa-play'
})
})).html()
]);
}
// if the table exists, destroy it.
if ($.fn.DataTable.isDataTable('#audioHooksTable')) {
$('#audioHooksTable').DataTable().destroy();
// Remove all of the old events.
$('#audioHooksTable').off();
}
// Create table.
let table = $('#audioHooksTable').DataTable({
'searching': true,
'autoWidth': false,
'lengthChange': false,
'data': tableData,
'columnDefs': [
{ 'className': 'default-table', 'orderable': false, 'targets': 1 }
],
'columns': [
{ 'title': 'Audio Hook' },
{ 'title': 'Actions' }
]
});
// On play button.
table.on('click', '.btn-success', function() {
let audioHook = $(this).data('audio'),
soundPath = '/config/audio-hooks/';
// Load the audio.
let audio = new Audio(soundPath + audioHook);
// Set the volume.
audio.volume = '0.8';
// Add event handler.
$(audio).on('ended', function() {
audio.currentTime = 0;
});
// Play it!
audio.play();
});
// On delete button.
table.on('click', '.btn-danger', function() {
let audioHookName = $(this).data('audio'),
row = $(this).parents('tr');
// Ask the user if he wants to delete the audio hook.
helpers.getConfirmDeleteModal('audio_modal_remove', 'Are you sure you want to remove the audio hook "' + audioHookName + '"?', true,
'The audio hook "' + audioHookName + '" has been successfully removed!', function() { // Callback if the user clicks delete.
socket.sendCommand('audio_hook_rm_cmd', 'panelremoveaudiohook ' + audioHookName, function() {
// Remove the table row.
table.row(row).remove().draw(false);
});
});
});
});
// Get audio commands.
socket.getDBTableValues('audio_hooks_get_cmds', 'audioCommands', function(results) {
let tableData = [];
for (let i = 0; i < results.length; i++) {
tableData.push([
'!' + results[i].key,
results[i].value,
$('<div/>', {
'class': 'btn-group'
}).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-danger',
'style': 'float: right',
'data-command': results[i].key,
'html': $('<i/>', {
'class': 'fa fa-trash'
})
})).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-warning',
'style': 'float: right',
'data-command': results[i].key,
'html': $('<i/>', {
'class': 'fa fa-edit'
})
})).html()
]);
}
// if the table exists, destroy it.
if ($.fn.DataTable.isDataTable('#audioHookCommandsTable')) {
$('#audioHookCommandsTable').DataTable().destroy();
// Remove all of the old events.
$('#audioHookCommandsTable').off();
}
// Create table.
let table = $('#audioHookCommandsTable').DataTable({
'searching': true,
'autoWidth': false,
'lengthChange': false,
'data': tableData,
'columnDefs': [
{ 'className': 'default-table', 'orderable': false, 'targets': 2 },
{ 'width': '45%', 'targets': 0 }
],
'columns': [
{ 'title': 'Command' },
{ 'title': 'Audio Hook' },
{ 'title': 'Actions' }
]
});
// On delete button.
table.on('click', '.btn-danger', function() {
let command = $(this).data('command'),
row = $(this).parents('tr');
// Ask the user if he want to remove the command.
helpers.getConfirmDeleteModal('rm_audio_command_cmd_modal', 'Are you sure you want to remove command !' + command + '?', true,
'The command !' + command + ' has been successfully removed!', function() {
socket.removeDBValue('rm_audio_command', 'audioCommands', command, function() {
socket.sendCommand('rm_audio_command_cmd', 'panelloadaudiohookcmds ' + command, function() {
// Remove the table row.
table.row(row).remove().draw(false);
});
});
});
});
// On edit button.
table.on('click', '.btn-warning', function() {
let command = $(this).data('command'),
t = $(this);
// Get all the info about the command.
socket.getDBValues('audio_command_edit', {
tables: ['audioCommands', 'permcom', 'cooldown', 'pricecom', 'paycom'],
keys: [command, command, command, command, command]
}, function(e) {
let cooldownJson = (e.cooldown === null ? { isGlobal: 'true', seconds: 0 } : JSON.parse(e.cooldown));
// Get advance modal from our util functions in /utils/helpers.js
helpers.getAdvanceModal('edit-audio-command', 'Edit Audio Command', 'Save', $('<form/>', {
'role': 'form'
})
// Append input box for the command name. This one is disabled.
.append(helpers.getInputGroup('command-name', 'text', 'Command', '', '!' + command, 'Name of the command. This cannot be edited.', true))
// Append input box for the command audio. This one is disabled.
.append(helpers.getInputGroup('command-audio', 'text', 'Audio Hook', '', e.audioCommands, 'Audio to be played. This cannot be edited.', true))
// Append a select option for the command permission.
.append(helpers.getDropdownGroup('command-permission', 'User Level', helpers.getGroupNameById(e.permcom),
['Caster', 'Administrators', 'Moderators', 'Subscribers', 'Donators', 'VIPs', 'Regulars', 'Viewers']))
// Add an advance section that can be opened with a button toggle.
.append($('<div/>', {
'class': 'collapse',
'id': 'advance-collapse',
'html': $('<form/>', {
'role': 'form'
})
// Append input box for the command cost.
.append(helpers.getInputGroup('command-cost', 'number', 'Cost', '0', helpers.getDefaultIfNullOrUndefined(e.pricecom, '0'),
'Cost in points that will be taken from the user when running the command.'))
// Append input box for the command reward.
.append(helpers.getInputGroup('command-reward', 'number', 'Reward', '0', helpers.getDefaultIfNullOrUndefined(e.paycom, '0'),
'Reward in points the user will be given when running the command.'))
// Append input box for the command cooldown.
.append(helpers.getInputGroup('command-cooldown', 'number', 'Cooldown (Seconds)', '5', cooldownJson.seconds,
'Cooldown of the command in seconds.')
// Append checkbox for if the cooldown is global or per-user.
.append(helpers.getCheckBox('command-cooldown-global', cooldownJson.isGlobal === 'true', 'Global',
'If checked the cooldown will be applied to everyone in the channel. When not checked, the cooldown is applied per-user.')))
})), function() {
let commandPermission = $('#command-permission'),
commandCost = $('#command-cost'),
commandReward = $('#command-reward'),
commandCooldown = $('#command-cooldown'),
commandCooldownGlobal = $('#command-cooldown-global').is(':checked');
// Handle each input to make sure they have a value.
switch (false) {
case helpers.handleInputNumber(commandCost):
case helpers.handleInputNumber(commandReward):
case helpers.handleInputNumber(commandCooldown):
break;
default:
// Save command information here and close the modal.
socket.updateDBValues('custom_command_edit', {
tables: ['pricecom', 'permcom', 'paycom'],
keys: [command, command, command],
values: [commandCost.val(), helpers.getGroupIdByName(commandPermission.find(':selected').text(), true), commandReward.val()]
}, function() {
// Add the cooldown to the cache.
socket.wsEvent('audio_command_edit_cooldown_ws', './core/commandCoolDown.js', null,
['add', command, commandCooldown.val(), String(commandCooldownGlobal)], function() {
// Update command permission.
socket.sendCommand('edit_command_permission_cmd', 'permcomsilent ' + command + ' ' +
helpers.getGroupIdByName(commandPermission.find(':selected').text(), true), function() {
// Close modal.
$('#edit-audio-command').modal('toggle');
// Alert the user.
toastr.success('Successfully edit audio command!');
});
});
});
}
}).modal('toggle');
});
});
});
// Welcome the user to the new page.
socket.getDBValue('get_audio_hook_warning', 'panelData', 'audioHookNewUser', function(e) {
if (e.panelData !== 'true') {
alert('Hi there! \nWelcome to PhantomBot\'s audio hook page! This page allows you to test, listen, and add audio commands. \n' +
'If you\'ve used the old panel before, audio hooks used to play on this page when a user ran an audio command. This is no longer a feature. ' +
'Now, all audio hooks are sent through PhantomBot\'s alert page which can be used as a browser source in OBS. \n' +
'Click the settings button to access the browser source URL.');
socket.updateDBValue('audio_hook_warning_set', 'panelData', 'audioHookNewUser', 'true', new Function());
}
});
});
});
// Function that handlers the loading of events.
$(function() {
// Toggle for the module.
$('#audioHookModuleToggle').on('change', function() {
// Enable the module then query the data.
socket.sendCommandSync('audio_module_toggle_cmd', 'module ' + ($(this).is(':checked') ? 'enablesilent' : 'disablesilent') + ' ./systems/audioPanelSystem.js', run);
});
// Reload audio hooks button.
$('#reload-audio-hooks').on('click', function() {
socket.sendCommandSync('reload_audio_hooks_cmd', 'reloadaudiopanelhooks', function() {
// Load new audio hooks.
run();
// Alert the user.
toastr.success('Successfully refreshed audio hooks!');
});
});
// Audio hooks settings.
$('#audio-hooks-settings').on('click', function() {
// Create custom modal for this module.
helpers.getModal('audio-settings', 'Browser Source Settings', 'Ok', $('<form/>', {
'role': 'form'
})
// Main div for the browser source link.
.append($('<div/>', {
'class': 'form-group',
})
// Append the lable.
.append($('<label/>', {
'text': 'Browser Source Link'
}))
.append($('<div/>', {
'class': 'input-group'
})
// Add client widget URL.
.append($('<input/>', {
'type': 'text',
'class': 'form-control',
'id': 'audio-url',
'readonly': 'readonly',
'value': window.location.protocol + '//' + window.location.host + '/alerts?allow-audio-hooks=true&allow-alerts=false&audio-hook-volume=0.8',
'style': 'color: transparent !important; text-shadow: 0 0 5px hsla(0, 0%, 100%, .5);',
'data-toggle': 'tooltip',
'title': 'Clicking this box will show the link.',
'click': function() {
// Reset styles.
$(this).prop('style', '');
},
'blur': function() {
// Reset styles.
$(this).prop('style', 'color: transparent !important; text-shadow: 0 0 5px hsla(0, 0%, 100%, .5);');
}
})).append($('<span/>', {
'class': 'input-group-btn',
'style': 'color: transparent !important; text-shadow: 0 0 5px hsla(0, 0%, 100%, .5);',
'html': $('<button/>', {
'type': 'button',
'class': 'btn btn-primary btn-flat',
'html': 'Copy',
'click': function() {
// Select URL.
$('#audio-url').select().blur();
// Copy the URL.
document.execCommand('Copy');
// Close the modal.
$('#audio-settings').removeClass('fade').modal('hide');
// Alert the user.
toastr.success('Copied browser source URL!');
}
})
})))), function() {
// Close the modal.
$('#audio-settings').modal('toggle');
}).modal('toggle');
});
// Audio hooks command settings.
$('#audio-hooks-cmd-settings').on('click', function() {
helpers.getModal('add-audio-settings-cmd', 'Audio Hook Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Append command name.
.append(helpers.getInputGroup('cooldown-hooks', 'number', 'Master Cooldown (Seconds)', '30', '', 'Set a master cooldown for audio hooks, this cooldown is applied to all commands, if one command is sent, another can only be sent after this cooldown.')), function() {
// Code.
}).modal('toggle');
});
// Add audio command.
$('#audio-hooks-cmd-add').on('click', function() {
socket.getDBTableValues('get_all_audio_hooks', 'audio_hooks', function(results) {
let audioNames = [];
for (let i = 0; i < results.length; i++) {
audioNames.push(results[i].key);
}
helpers.getAdvanceModal('add-audio-cmd', 'Add Audio Command', 'Save', $('<form/>', {
'role': 'form'
})
// Append command name.
.append(helpers.getInputGroup('command-name', 'text', 'Command', '!boo', '', 'Command that will trigger the audio hook.'))
// All audio hooks in a list.
.append(helpers.getDropdownGroup('command-audio', 'Audio Hook', 'Select an Audio Hook', audioNames, 'Audio hook to be played when the command is ran.'))
// Append a select option for the command permission.
.append(helpers.getDropdownGroup('command-permission', 'User Level', 'Viewers',
['Caster', 'Administrators', 'Moderators', 'Subscribers', 'Donators', 'VIPs', 'Regulars', 'Viewers'], 'Users who can run the command.'))
// Add an advance section that can be opened with a button toggle.
.append($('<div/>', {
'class': 'collapse',
'id': 'advance-collapse',
'html': $('<form/>', {
'role': 'form'
})
// Append input box for the command cost.
.append(helpers.getInputGroup('command-cost', 'number', 'Cost', '0', '0',
'Cost in points that will be taken from the user when running the command.'))
// Append input box for the command reward.
.append(helpers.getInputGroup('command-reward', 'number', 'Reward', '0', '0',
'Reward in points the user will be given when running the command.'))
// Append input box for the command cooldown.
.append(helpers.getInputGroup('command-cooldown', 'number', 'Cooldown (Seconds)', '0', '5',
'Cooldown of the command in seconds.')
// Append checkbox for if the cooldown is global or per-user.
.append(helpers.getCheckBox('command-cooldown-global', true, 'Global',
'If checked the cooldown will be applied to everyone in the channel. When not checked, the cooldown is applied per-user.')))
})), function() {
let commandName = $('#command-name'),
commandAudio = $('#command-audio'),
commandPermission = $('#command-permission'),
commandCost = $('#command-cost'),
commandReward = $('#command-reward'),
commandCooldown = $('#command-cooldown'),
commandCooldownGlobal = $('#command-cooldown-global').is(':checked');
// Remove the ! and spaces.
commandName.val(commandName.val().replace(/(\!|\s)/g, '').toLowerCase());
// Handle each input to make sure they have a value.
switch (false) {
case helpers.handleInputString(commandName):
case helpers.handleInputNumber(commandCost):
case helpers.handleInputNumber(commandReward):
case helpers.handleInputNumber(commandCooldown):
break;
default:
if (commandAudio.val() === null) {
toastr.error('Please select a valid audio hook to be played.');
} else {
// Make sure the command doesn't exist already.
socket.getDBValue('audio_command_exists', 'permcom', commandName.val(), function(e) {
// If the command exists we stop here.
if (e.permcom !== null) {
toastr.error('Failed to add command as it already exists.');
return;
}
// Add the command.
socket.updateDBValues('add_audio_command', {
tables: ['pricecom', 'permcom', 'paycom', 'audioCommands'],
keys: [commandName.val(), commandName.val(), commandName.val(), commandName.val()],
values: [commandCost.val(), helpers.getGroupIdByName(commandPermission.find(':selected').text()), commandReward.val(), commandAudio.val()]
}, function() {
socket.wsEvent('audio_command_add_cooldown_ws', './core/commandCoolDown.js', null,
['add', commandName.val(), commandCooldown.val(), String(commandCooldownGlobal)], function() {
socket.sendCommandSync('add_audio_command_cmd', 'panelloadaudiohookcmds', function() {
// Reload the table
run();
// Close the modal.
$('#add-audio-cmd').modal('toggle');
// Alert the user.
toastr.success('Successfully added the audio command!');
});
});
});
});
}
}
}).modal('toggle');
});
});
});

View File

@@ -0,0 +1,192 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Function that querys all of the data we need.
$(run = function() {
// Check if the module is enabled.
socket.getDBValue('alias_command_module', 'modules', './commands/customCommands.js', function(e) {
// If the module is off, don't load any data.
if (!helpers.handleModuleLoadUp('aliasesModule', e.modules)) {
return;
}
// Query aliases.
socket.getDBTableValues('commands_get_aliases', 'aliases', function(results) {
let tableData = [];
for (let i = 0; i < results.length; i++) {
tableData.push([
'!' + results[i].key,
'!' + results[i].value,
$('<div/>', {
'class': 'btn-group'
}).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-danger',
'style': 'float: right',
'data-alias': results[i].key,
'html': $('<i/>', {
'class': 'fa fa-trash'
})
})).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-warning',
'style': 'float: right',
'data-alias': results[i].key,
'html': $('<i/>', {
'class': 'fa fa-edit'
})
})).html()
]);
}
// if the table exists, destroy it.
if ($.fn.DataTable.isDataTable('#aliasesTable')) {
$('#aliasesTable').DataTable().destroy();
// Remove all of the old events.
$('#aliasesTable').off();
}
// Create table.
let table = $('#aliasesTable').DataTable({
'searching': true,
'autoWidth': false,
'lengthChange': false,
'data': tableData,
'columnDefs': [
{ 'className': 'default-table', 'orderable': false, 'targets': 2 },
{ 'width': '45%', 'targets': 0 }
],
'columns': [
{ 'title': 'Alias' },
{ 'title': 'Command' },
{ 'title': 'Actions' }
]
});
// On delete button.
table.on('click', '.btn-danger', function() {
let alias = $(this).data('alias'),
row = $(this).parents('tr');
// Ask the user if he wants to delete the alias.
helpers.getConfirmDeleteModal('custom_alias_modal_remove', 'Are you sure you want to remove the alias !' + alias + '?', true,
'The alias !' + alias + ' has been successfully removed!', function() { // Callback if the user clicks delete.
// Delete all information about the alias.
socket.removeDBValue('alias_remove', 'aliases', alias, function() {
socket.sendCommand('alias_remove_cmd', 'reloadcommand ' + alias, function() {
// Remove the table row.
table.row(row).remove().draw(false);
});
});
});
});
// On edit button.
table.on('click', '.btn-warning', function() {
let alias = $(this).data('alias'),
t = $(this);
socket.getDBValue('alias_name_get', 'aliases', alias, function(e) {
helpers.getModal('edit-alias', 'Edit Alias', 'Save', $('<form/>', {
'role': 'form'
})
// Append alias name.
.append(helpers.getInputGroup('alias-name', 'text', 'Alias', '', '!' + alias, 'Name of the alias. This cannot be edited.', true))
// Append alias.
.append(helpers.getInputGroup('alias-cmd', 'text', 'Command', '', '!' + e.aliases, 'Command to be ran by the alias.')), function() {// Callback once we click the save button.
let aliasCmd = $('#alias-cmd');
// Remove the ! and spaces.
aliasCmd.val(aliasCmd.val().replace(/(\!|\s)/g, '').toLowerCase());
// Handle each input to make sure they have a value.
switch (false) {
case helpers.handleInputString(aliasCmd):
break;
default:
// Update the alias.
socket.updateDBValue('update_command_alias', 'aliases', alias, aliasCmd.val(), function() {
// Update the table.
t.parents('tr').find('td:eq(1)').text('!' + aliasCmd.val());
// Close the modal.
$('#edit-alias').modal('hide');
// Alert the user.
toastr.success('Successfully edited alias !' + alias);
});
}
}).modal('toggle');
});
});
});
});
});
// Function that handlers the loading of events.
$(function() {
// Toggle for the module.
$('#aliasesModuleToggle').on('change', function() {
// Enable the module then query the data.
socket.sendCommandSync('aliases_commands_module_toggle_cmd', 'module ' + ($(this).is(':checked') ? 'enablesilent' : 'disablesilent') + ' ./commands/customCommands.js', run);
});
// Add alias button.
$('#aliascom-button').on('click', function() {
helpers.getModal('add-alias', 'Add Alias', 'Save', $('<form/>', {
'role': 'form'
})
// Append alias name.
.append(helpers.getInputGroup('alias-name', 'text', 'Alias', '!cmds', '', 'Name of the alias.'))
// Append alias.
.append(helpers.getInputGroup('alias-cmd', 'text', 'Command', '!commands', '', 'Command to be ran by the alias.')), function() {// Callback once we click the save button.
let aliasName = $('#alias-name'),
aliasCmd = $('#alias-cmd');
// Remove the ! and spaces.
aliasName.val(aliasName.val().replace(/(\!|\s)/g, '').toLowerCase());
aliasCmd.val(aliasCmd.val().replace(/\!/g, '').toLowerCase());
// Handle each input to make sure they have a value.
switch (false) {
case helpers.handleInputString(aliasName):
case helpers.handleInputString(aliasCmd):
break;
default:
// Make sure the alias doesn't exit already.
socket.getDBValue('alias_exists', 'aliases', aliasName.val(), function(e) {
// If the command exists we stop here.
if (e.aliases !== null) {
toastr.error('Failed to add alias as it already exists.');
return;
}
// Add the alias.
socket.updateDBValue('add_command_alias', 'aliases', aliasName.val(), aliasCmd.val(), function() {
socket.sendCommand('alias_add_cmd', 'reloadcommand', function() {
// Reload the table.
run();
// Close the modal.
$('#add-alias').modal('hide');
// Alert the user.
toastr.success('Successfully added alias !' + aliasName.val());
});
});
});
}
}).modal('toggle');
});
});

View File

@@ -0,0 +1,349 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Function that querys all of the data we need.
$(run = function() {
// Check if the module is enabled.
socket.getDBValue('custom_command_module', 'modules', './commands/customCommands.js', function(e) {
// If the module is off, don't load any data.
if (!helpers.handleModuleLoadUp('customCommandsModule', e.modules)) {
return;
}
// Query custom commands.
socket.getDBTableValues('commands_get_custom', 'command', function(results) {
let tableData = [];
for (let i = 0; i < results.length; i++) {
tableData.push([
'!' + results[i].key,
results[i].value,
$('<div/>', {
'class': 'btn-group'
}).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-danger',
'style': 'float: right',
'data-command': results[i].key,
'html': $('<i/>', {
'class': 'fa fa-trash'
})
})).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-warning',
'style': 'float: right',
'data-command': results[i].key,
'html': $('<i/>', {
'class': 'fa fa-edit'
})
})).html()
]);
}
// if the table exists, destroy it.
if ($.fn.DataTable.isDataTable('#customCommandsTable')) {
$('#customCommandsTable').DataTable().destroy();
// Remove all of the old events.
$('#customCommandsTable').off();
}
// Create table.
let table = $('#customCommandsTable').DataTable({
'searching': true,
'autoWidth': false,
'lengthChange': false,
'data': tableData,
'columnDefs': [
{ 'className': 'default-table', 'orderable': false, 'targets': 2 },
{ 'width': '15%', 'targets': 0 }
],
'columns': [
{ 'title': 'Command' },
{ 'title': 'Response' },
{ 'title': 'Actions' }
]
});
// On delete button.
table.on('click', '.btn-danger', function() {
let command = $(this).data('command'),
row = $(this).parents('tr');
// Ask the user if he want to remove the command.
helpers.getConfirmDeleteModal('custom_command_modal_remove', 'Are you sure you want to remove command !' + command + '?', true,
'The command !' + command + ' has been successfully removed!', function() {
// Delete all information about the command.
socket.removeDBValues('custom_command_remove', {
tables: ['command', 'permcom', 'cooldown', 'aliases', 'pricecom', 'paycom', 'commandtoken'],
keys: [command, command, command, command, command, command, command]
}, function() {
socket.wsEvent('custom_command_remove_ws', './commands/customCommands.js', null, ['remove', String(command)], function() {
// Remove the table row.
table.row(row).remove().draw(false);
});
});
});
});
// On edit button.
table.on('click', '.btn-warning', function() {
let command = $(this).data('command'),
t = $(this);
// Get all the info about the command.
socket.getDBValues('custom_command_edit', {
tables: ['command', 'permcom', 'cooldown', 'pricecom', 'paycom'],
keys: [command, command, command, command, command]
}, function(e) {
let cooldownJson = (e.cooldown === null ? { isGlobal: 'true', seconds: 0 } : JSON.parse(e.cooldown));
let tokenButton = '';
if (e.command.match(/\(customapi/gi) !== null) {
tokenButton = $('<button/>', {
'type': 'button',
'class': 'btn',
'style': 'float: right; position: relative; bottom: 6px;',
'data-command': command,
'click': function() {
tokenEditModal($(this).data('command'));
},
'text': 'Add/Edit Command Token'
});
}
// Get advance modal from our util functions in /utils/helpers.js
helpers.getAdvanceModal('edit-command', 'Edit Command', 'Save', $('<form/>', {
'role': 'form'
})
// Append input box for the command name. This one is disabled.
.append(helpers.getInputGroup('command-name', 'text', 'Command', '', '!' + command, 'Name of the command. This cannot be edited.', true))
// Append a text box for the command response.
.append(helpers.getTextAreaGroup('command-response', 'text', 'Response', '', e.command, 'Response of the command. Use enter for multiple chat lines maximum is 5.'))
.append(tokenButton)
// Append a select option for the command permission.
.append(helpers.getDropdownGroup('command-permission', 'User Level', helpers.getGroupNameById(e.permcom),
['Caster', 'Administrators', 'Moderators', 'Subscribers', 'Donators', 'VIPs', 'Regulars', 'Viewers']))
// Add an advance section that can be opened with a button toggle.
.append($('<div/>', {
'class': 'collapse',
'id': 'advance-collapse',
'html': $('<form/>', {
'role': 'form'
})
// Append input box for the command cost.
.append(helpers.getInputGroup('command-cost', 'number', 'Cost', '0', helpers.getDefaultIfNullOrUndefined(e.pricecom, '0'),
'Cost in points that will be taken from the user when running the command.'))
// Append input box for the command reward.
.append(helpers.getInputGroup('command-reward', 'number', 'Reward', '0', helpers.getDefaultIfNullOrUndefined(e.paycom, '0'),
'Reward in points the user will be given when running the command.'))
// Append input box for the command cooldown.
.append(helpers.getInputGroup('command-cooldown', 'number', 'Cooldown (Seconds)', '5', cooldownJson.seconds,
'Cooldown of the command in seconds.')
// Append checkbox for if the cooldown is global or per-user.
.append(helpers.getCheckBox('command-cooldown-global', cooldownJson.isGlobal === 'true', 'Global',
'If checked the cooldown will be applied to everyone in the channel. When not checked, the cooldown is applied per-user.')))
// Callback function to be called once we hit the save button on the modal.
})), function() {
let commandName = $('#command-name'),
commandResponse = $('#command-response'),
commandPermission = $('#command-permission'),
commandCost = $('#command-cost'),
commandReward = $('#command-reward'),
commandCooldown = $('#command-cooldown'),
commandCooldownGlobal = $('#command-cooldown-global').is(':checked');
// Remove the ! and spaces.
commandName.val(commandName.val().replace(/(\!|\s)/g, '').toLowerCase());
// Handle each input to make sure they have a value.
switch (false) {
case helpers.handleInputString(commandName):
case helpers.handleInputString(commandResponse):
case helpers.handleInputNumber(commandCost):
case helpers.handleInputNumber(commandReward):
case helpers.handleInputNumber(commandCooldown):
break;
default:
// Save command information here and close the modal.
socket.updateDBValues('custom_command_edit', {
tables: ['pricecom', 'permcom', 'paycom', 'command'],
keys: [commandName.val(), commandName.val(), commandName.val(), commandName.val()],
values: [commandCost.val(), helpers.getGroupIdByName(commandPermission.find(':selected').text(), true),
commandReward.val(), commandResponse.val()]
}, function() {
// Register the custom command with the cache.
socket.wsEvent('custom_command_edit_ws', './commands/customCommands.js', null, ['edit', String(commandName.val()),
commandResponse.val()], function() {
// Add the cooldown to the cache.
socket.wsEvent('custom_command_edit_cooldown_ws', './core/commandCoolDown.js', null,
['add', commandName.val(), commandCooldown.val(), String(commandCooldownGlobal)], function() {
// Update command permission.
socket.sendCommand('edit_command_permission_cmd', 'permcomsilent ' + commandName.val() + ' ' +
helpers.getGroupIdByName(commandPermission.find(':selected').text(), true), function() {
// Update the command response
t.parents('tr').find('td:eq(1)').text(commandResponse.val());
// Close the modal.
$('#edit-command').modal('hide');
// Tell the user the command was edited.
toastr.success('Successfully edited command !' + commandName.val());
});
});
});
});
}
}).modal('toggle');
});
});
});
});
});
// Function that handlers the loading of events.
$(function() {
// Toggle for the module.
$('#customCommandsModuleToggle').on('change', function() {
// Enable the module then query the data.
socket.sendCommandSync('custom_commands_module_toggle_cmd', 'module ' + ($(this).is(':checked') ? 'enablesilent' : 'disablesilent') + ' ./commands/customCommands.js', run);
});
// Add command button.
$('#addcom-button').on('click', function() {
// Get advance modal from our util functions in /utils/helpers.js
helpers.getAdvanceModal('add-command', 'Add Command', 'Save', $('<form/>', {
'role': 'form'
})
// Append input box for the command name.
.append(helpers.getInputGroup('command-name', 'text', 'Command', '!example'))
// Append a text box for the command response.
.append(helpers.getTextAreaGroup('command-response', 'text', 'Response', 'Response example! Use enter for multiple chat lines maximum is 5.'))
// Append a select option for the command permission.
.append(helpers.getDropdownGroup('command-permission', 'User Level', 'Viewers',
['Caster', 'Administrators', 'Moderators', 'Subscribers', 'Donators', 'VIPs', 'Regulars', 'Viewers']))
// Add an advance section that can be opened with a button toggle.
.append($('<div/>', {
'class': 'collapse',
'id': 'advance-collapse',
'html': $('<form/>', {
'role': 'form'
})
// Append input box for the command cost.
.append(helpers.getInputGroup('command-cost', 'number', 'Cost', '0', '0',
'Cost in points that will be taken from the user when running the command.'))
// Append input box for the command reward.
.append(helpers.getInputGroup('command-reward', 'number', 'Reward', '0', '0',
'Reward in points the user will be given when running the command.'))
// Append input box for the command cooldown.
.append(helpers.getInputGroup('command-cooldown', 'number', 'Cooldown (Seconds)', '0', '5',
'Cooldown of the command in seconds.')
// Append checkbox for if the cooldown is global or per-user.
.append(helpers.getCheckBox('command-cooldown-global', true, 'Global',
'If checked the cooldown will be applied to everyone in the channel. When not checked, the cooldown is applied per-user.')))
// Callback function to be called once we hit the save button on the modal.
})), function() {
let commandName = $('#command-name'),
commandResponse = $('#command-response'),
commandPermission = $('#command-permission'),
commandCost = $('#command-cost'),
commandReward = $('#command-reward'),
commandCooldown = $('#command-cooldown'),
commandCooldownGlobal = $('#command-cooldown-global').is(':checked');
// Remove the ! and spaces.
commandName.val(commandName.val().replace(/(\!|\s)/g, '').toLowerCase());
// Handle each input to make sure they have a value.
switch (false) {
case helpers.handleInputString(commandName):
case helpers.handleInputString(commandResponse):
case helpers.handleInputNumber(commandCost):
case helpers.handleInputNumber(commandReward):
case helpers.handleInputNumber(commandCooldown):
break;
default:
// Make sure the command doesn't exist already.
socket.getDBValue('custom_command_exists', 'permcom', commandName.val(), function(e) {
// If the command exists we stop here.
if (e.permcom !== null) {
toastr.error('Failed to add command as it already exists.');
return;
}
// Save command information here and close the modal.
socket.updateDBValues('custom_command_add', {
tables: ['pricecom', 'permcom', 'paycom', 'command'],
keys: [commandName.val(), commandName.val(), commandName.val(), commandName.val()],
values: [commandCost.val(), helpers.getGroupIdByName(commandPermission.find(':selected').text(), true), commandReward.val(), commandResponse.val()]
}, function() {
// Register the custom command with the cache.
socket.wsEvent('custom_command_add_ws', './commands/customCommands.js', null,
['add', commandName.val(), commandResponse.val()], function() {
// Add the cooldown to the cache.
socket.wsEvent('custom_command_cooldown_ws', './core/commandCoolDown.js', null,
['add', commandName.val(), commandCooldown.val(), String(commandCooldownGlobal)], function() {
// Reload the table.
run();
// Close the modal.
$('#add-command').modal('hide');
// Tell the user the command was added.
toastr.success('Successfully added command !' + commandName.val());
});
});
});
});
}
}).modal('toggle');
});
// On token button.
tokenEditModal = function(command) {
// Get modal from our util functions in /utils/helpers.js
helpers.getModal('token-command', 'Set Command Token', 'Save', $('<form/>', {
'role': 'form'
})
.append('This dialog stores a user/pass or API key to be replaced into a (customapi) tag.\n\
<br /> NOTE: This is only useful if you place a (token) subtag into the URL of a (customapi) or (customapijson) command tag.\n\
<br /> Example (using the bot\s chat commands for demonstration purposes):\n\
<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;!addcom myapicommand (customapi http://(token)@example.com/myapi)\n\
<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;!tokencom myapicommand myuser:mypass\n\
<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i>The command now effectively calls http://myuser:mypass@example.com/myapi while reducing exposure of your user/pass</i>')
// Append input box for the command name. This one is disabled.
.append(helpers.getInputGroup('command-tname', 'text', 'Command', '', '!' + command, 'Name of the command. This cannot be edited.', true))
// Append a text box for the command token.
.append(helpers.getInputGroup('command-token', 'text', 'Token', '', 'The token value for the command.')), function() {
let commandName = $('#command-tname'),
commandToken = $('#command-token');
// Remove the ! and spaces.
commandName.val(commandName.val().replace(/(\!|\s)/g, '').toLowerCase());
// Handle each input to make sure they have a value.
switch (false) {
case helpers.handleInputString(commandName):
break;
default:
// Update command token.
socket.sendCommand('command_settoken_cmd', 'tokencom silent@' + commandName.val() + ' ' + commandToken.val(), function() {
// Close the modal.
$('#token-command').modal('hide');
// Tell the user the command was edited.
toastr.success('Successfully changed token for command !' + commandName.val());
});
}
}).modal('toggle');
};
});

View File

@@ -0,0 +1,185 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Function that querys all of the data we need.
$(function() {
// Query all commands.
socket.getDBTableValues('commands_get_all', 'permcom', function(results) {
socket.getDBTableValues('custom_commands_get_all', 'command', function(customCommands) {
let tableData = [],
cmds = [];
for (let i = 0; i < customCommands.length; i++) {
cmds.push(customCommands[i].key);
}
for (let i = 0; i < results.length; i++) {
if (cmds.indexOf(results[i].key) !== -1) {
continue;
}
tableData.push([
'!' + results[i].key,
helpers.getGroupNameById(results[i].value),
$('<div/>', {
'class': 'btn-group'
}).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-danger',
'style': 'float: right',
'data-toggle': 'tooltip',
'title': 'Deletes the command permission and resets it to default on startup. This does not remove the command unless it doesn\'t exist anymore.',
'data-command': results[i].key,
'html': $('<i/>', {
'class': 'fa fa-refresh'
})
})).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-warning',
'style': 'float: right',
'data-command': results[i].key,
'html': $('<i/>', {
'class': 'fa fa-edit'
})
})).html()
]);
}
// if the table exists, destroy it.
if ($.fn.DataTable.isDataTable('#defaultCommandsTable')) {
$('#defaultCommandsTable').DataTable().destroy();
// Remove all of the old events.
$('#defaultCommandsTable').off();
}
// Create table.
let table = $('#defaultCommandsTable').DataTable({
'searching': true,
'autoWidth': false,
'data': tableData,
'columnDefs': [
{ 'className': 'default-table-large', 'orderable': false, 'targets': 2 },
{ 'width': '45%', 'targets': 0 }
],
'columns': [
{ 'title': 'Command' },
{ 'title': 'User Level' },
{ 'title': 'Actions' }
]
});
// On delete button.
table.on('click', '.btn-danger', function() {
let command = $(this).data('command'),
row = $(this).parents('tr'),
t = $(this);
// Ask the user if he want to reset the command.
helpers.getConfirmDeleteModal('default_command_modal_remove', 'Are you sure you want to reset the command\'s permission?', false,
'The command\'s permission has been reset!', function() {
socket.removeDBValue('permcom_temp_del', 'permcom', command, function(e) {
// Hide tooltip.
t.tooltip('hide');
// Remove the table row.
table.row(row).remove().draw(false);
});
});
});
// On edit button.
table.on('click', '.btn-warning', function() {
let command = $(this).data('command'),
t = $(this);
// Get all the info about the command.
socket.getDBValues('default_command_edit', {
tables: ['permcom', 'cooldown', 'pricecom', 'paycom'],
keys: [command, command, command, command]
}, function(e) {
let cooldownJson = (e.cooldown === null ? { isGlobal: 'true', seconds: 0 } : JSON.parse(e.cooldown));
// Get advance modal from our util functions in /utils/helpers.js
helpers.getAdvanceModal('edit-command', 'Edit Command', 'Save', $('<form/>', {
'role': 'form'
})
// Append input box for the command name. This one is disabled.
.append(helpers.getInputGroup('command-name', 'text', 'Command', '', '!' + command, 'Name of the command. This cannot be edited.', true))
// Append a select option for the command permission.
.append(helpers.getDropdownGroup('command-permission', 'User Level', helpers.getGroupNameById(e.permcom),
['Caster', 'Administrators', 'Moderators', 'Subscribers', 'Donators', 'VIPs', 'Regulars', 'Viewers']))
// Add an advance section that can be opened with a button toggle.
.append($('<div/>', {
'class': 'collapse',
'id': 'advance-collapse',
'html': $('<form/>', {
'role': 'form'
})
// Append input box for the command cost.
.append(helpers.getInputGroup('command-cost', 'number', 'Cost', '0', helpers.getDefaultIfNullOrUndefined(e.pricecom, '0'),
'Cost in points that will be taken from the user when running the command.'))
// Append input box for the command reward.
.append(helpers.getInputGroup('command-reward', 'number', 'Reward', '0', helpers.getDefaultIfNullOrUndefined(e.paycom, '0'),
'Reward in points the user will be given when running the command.'))
// Append input box for the command cooldown.
.append(helpers.getInputGroup('command-cooldown', 'number', 'Cooldown (Seconds)', '5', cooldownJson.seconds,
'Cooldown of the command in seconds.')
// Append checkbox for if the cooldown is global or per-user.
.append(helpers.getCheckBox('command-cooldown-global', cooldownJson.isGlobal === 'true', 'Global',
'If checked the cooldown will be applied to everyone in the channel. When not checked, the cooldown is applied per-user.')))
// Callback function to be called once we hit the save button on the modal.
})), function() {
let commandPermission = $('#command-permission'),
commandCost = $('#command-cost'),
commandReward = $('#command-reward'),
commandCooldown = $('#command-cooldown'),
commandCooldownGlobal = $('#command-cooldown-global').is(':checked');
// Handle each input to make sure they have a value.
switch (false) {
case helpers.handleInputNumber(commandCost):
case helpers.handleInputNumber(commandReward):
case helpers.handleInputNumber(commandCooldown):
break;
default:
// Save command information here and close the modal.
socket.updateDBValues('custom_command_edit', {
tables: ['pricecom', 'paycom'],
keys: [command, command],
values: [commandCost.val(), commandReward.val()]
}, function() {
// Add the cooldown to the cache.
socket.wsEvent('default_command_edit_cooldown_ws', './core/commandCoolDown.js', null,
['add', command, commandCooldown.val(), String(commandCooldownGlobal)], function() {
// Edit the command permission.
socket.sendCommand('default_command_permisison_update', 'permcomsilent ' + command + ' ' +
helpers.getGroupIdByName(commandPermission.find(':selected').text(), true), function() {
// Update user level value.
t.parents('tr').find('td:eq(1)').text(commandPermission.find(':selected').text());
// Close the modal.
$('#edit-command').modal('hide');
// Tell the user the command was edited.
toastr.success('Successfully edited command !' + command);
});
});
});
}
}).modal('toggle');
});
});
});
});
});

View File

@@ -0,0 +1,515 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// If we can sroll the event log or not.
var canScroll = true;
// Function that querys all of the data we need.
$(function() {
// Query our panel settings first.
socket.getDBValues('panel_get_settings', {
tables: ['panelData', 'panelData', 'modules'],
keys: ['isDark', 'isReverseSortEvents', './systems/commercialSystem.js']
}, true, function(e) {
helpers.isDark = e.isDark === 'true';
helpers.isReverseSortEvents = e.isReverseSortEvents === 'true';
// Handle the dark mode skins.
helpers.handleDarkMode(helpers.isDark, true);
// Handle the dark mode toggle.
$('#dark-mode-toggle').prop('checked', helpers.isDark);
// Update event toggle.
$('#toggle-reverse-events').prop('checked', helpers.isReverseSortEvents);
// Disable isntant commercials if the module is disabled
if (e['./systems/commercialSystem.js'] !== 'true') {
$('#grp-instant-commercial').addClass('hidden');
} else {
$('#instant-commercial-length').select2({
placeholder: 'Commercial length, in seconds.',
width: '100%'
}).tooltip('disable');
}
// Query recent events.
socket.getDBValue('dashboard_get_events', 'panelData', 'data', function(e) {
if (e.panelData !== null && e.panelData.length > 0) {
let events = JSON.parse(e.panelData);
// This should never be null unless the user removes the DB table.
if (events !== null) {
// Sort events if needed.
if (helpers.isReverseSortEvents) {
events.sort(function(a, b) {
return b.date - a.date;
});
} else {
events.sort(function(a, b) {
return a.date - b.date;
});
}
let htmlEvents = $('<ul/>', {
'class': 'recent-events'
});
for (let i = 0; i < events.length; i++) {
let p = $('<p/>');
// Append date.
p.append($('<span/>', {
'class': 'event-date',
'html': helpers.getPaddedDateString(new Date(events[i].date).toLocaleString()) + ' '
}));
// Append type.
p.append($('<span/>', {
'class': 'label',
'style': helpers.getEventColor(events[i].type),
'html': events[i].type
}))
// Append message.
p.append($('<span/>', {
'html': ' ' + helpers.getEventMessage(events[i])
}));
// Append to list.
htmlEvents.append(p);
}
// Append the information to the main div.
htmlEvents.appendTo($('.event-log'));
}
}
// Query panel information.
socket.getDBValue('dashboard_get_data', 'panelData', 'stream', function(e) {
if (e.panelData === null) {
alert('Please allow the bot to generate the data needed to load this page. Try again in 60 seconds...');
return;
}
// Parse our object.
e = JSON.parse(e.panelData);
// Temp data.
const tempData = e;
// Set stream title.
$('#stream-title').val(e.title);
// Set stream game.
$('#stream-game').val(e.game);
// Set uptime.
if (e.isLive) {
$('#dashboard-uptime').html(e.uptime);
$('#bg-uptime').removeClass('bg-red').addClass('bg-green');
} else {
$('#dashboard-uptime').html('Offline');
$('#bg-uptime').removeClass('bg-green').addClass('bg-red');
}
// Query panel commands.
socket.getDBTableValues('dashboard_get_commands', 'command', function(e) {
// Sort commands.
e.sort(function(a, b) {
return a.key.localeCompare(b.key);
});
// Generate command list.
for (let i = 0; i < e.length; i++) {
$('#custom-command-run').append($('<option/>', {
'text': '!' + e[i].key
}));
}
// Enable the select2 dropdown.
$('#custom-command-run').select2({
placeholder: 'Select a Command to Run'
}).tooltip('disable');
// Don't load chat or the player in debug mode.
// Twitch prints a bunch of errors in the iframe, so it gets confusing.
if (helpers.DEBUG_STATE === helpers.DEBUG_STATES.DEBUG) {
// This will be called once the css and everything is loaded.
$(document).ready(function() {
// Done loading, show main page.
$.showPage();
// Scroll to bottom of event log.
$('.event-log').scrollTop((helpers.isReverseSortEvents ? ($('.event-log').scrollTop() - $('.recent-events').height()) : $('.recent-events').height()));
// Disable chat and the player.
$('#twitch-chat-box').addClass('off');
$('#twitch-player-box').addClass('off');
// Set views if not hidden.
helpers.handlePanelSetInfo($('#dashboard-views').data('number', helpers.parseNumber(tempData.views)), 'dashboard-views', helpers.fixNumber(tempData.views));
// Set viewers.
helpers.handlePanelSetInfo($('#dashboard-viewers').data('number', helpers.parseNumber(tempData.viewers)), 'dashboard-viewers', helpers.fixNumber(tempData.viewers));
// Set followers.
helpers.handlePanelSetInfo($('#dashboard-followers').data('number', helpers.parseNumber(tempData.followers)), 'dashboard-followers', helpers.fixNumber(tempData.followers));
});
} else {
socket.getDBValues('dashboard_get_panel_toggles', {
tables: ['panelData', 'panelData'],
keys: ['hasChat', 'hasPlayer']
}, true, function(e) {
e.hasChat = (e.hasChat === 'true' || e.hasChat === null);
e.hasPlayer = (e.hasPlayer === 'true' || e.hasPlayer === null);
// Handle adding the chat.
if (e.hasChat && location.protocol.toLowerCase().startsWith('https') && !(location.port > 0 && location.port !== 443)) {
$('#twitch-chat-iframe').html($('<iframe/>', {
'frameborder': '0',
'scrolling': 'no',
'style': 'width: 100%; height: 450px; margin-bottom: -5px;',
'src': 'https://www.twitch.tv/embed/' + getChannelName() + '/chat' + (helpers.isDark ? '?darkpopout&' : '?') + 'parent=' + location.hostname
}));
} else if (e.hasChat) {
$('#twitch-chat-iframe').html('Due to changes by Twitch, the chat panel can no longer be displayed unless you enable SSL on the PhantomBot Panel and change the baseport to 443. This may not work without root privileges.<br /><br />Alternatively, you can login using the GitHub version of the panel at <a href="https://phantombot.github.io/PhantomBot/">PhantomBot - GitHub.io</a> which gets around this issue.<br /><br />For help setting up SSL, please see <a href="https://phantombot.github.io/PhantomBot/guides/#guide=content/integrations/twitchembeds">this guide</a>.');
$('#twitch-chat-iframe').addClass('box-body');
} else {
$('#twitch-chat-box').addClass('off');
}
// Handle adding the player.
if (e.hasPlayer && location.protocol.toLowerCase().startsWith('https') && !(location.port > 0 && location.port !== 443)) {
// Add the player.
$('#twitch-player-iframe').html($('<iframe/>', {
'frameborder': '0',
'scrolling': 'no',
'style': 'width: 100%; height: 450px; margin-bottom: -5px;',
'src': 'https://player.twitch.tv/?channel=' + getChannelName() + '&muted=true&autoplay=false' + '&parent=' + location.hostname
}));
} else if (e.hasPlayer) {
$('#twitch-player-iframe').html('Due to changes by Twitch, the live feed panel can no longer be displayed unless you enable SSL on the PhantomBot Panel and change the baseport to 443. This may not work without root privileges.<br /><br />Alternatively, you can login using the GitHub version of the panel at <a href="https://phantombot.github.io/PhantomBot/">PhantomBot - GitHub.io</a> which gets around this issue.<br /><br />For help setting up SSL, please see <a href="https://phantombot.github.io/PhantomBot/guides/#guide=content/integrations/twitchembeds">this guide</a>.');
$('#twitch-player-iframe').addClass('box-body');
} else {
$('#twitch-player-box').addClass('off');
}
// Handle box sizes.
$('#twitch-chat-box').prop('class', (!e.hasPlayer ? 'col-md-12' : 'col-md-6'));
$('#twitch-player-box').prop('class', (!e.hasChat ? 'col-md-12' : 'col-md-6'));
// Handle toggles.
$('#toggle-chat').prop('checked', e.hasChat);
$('#toggle-player').prop('checked', e.hasPlayer);
// This will be called once the css and everything is loaded.
$(document).ready(function() {
// Done loading, show main page.
$.showPage();
// Scroll to bottom of event log.
$('.event-log').scrollTop((helpers.isReverseSortEvents ? ($('.event-log').scrollTop() - $('.recent-events').height()) : $('.recent-events').height()));
// Set views if not hidden.
helpers.handlePanelSetInfo($('#dashboard-views').data('number', helpers.parseNumber(tempData.views)), 'dashboard-views', helpers.fixNumber(tempData.views));
// Set viewers.
helpers.handlePanelSetInfo($('#dashboard-viewers').data('number', helpers.parseNumber(tempData.viewers)), 'dashboard-viewers', helpers.fixNumber(tempData.viewers));
// Set followers.
helpers.handlePanelSetInfo($('#dashboard-followers').data('number', helpers.parseNumber(tempData.followers)), 'dashboard-followers', helpers.fixNumber(tempData.followers));
});
});
}
});
});
});
});
});
// Function that handlers the loading of events.
$(function() {
// handle auto complete.
$('#stream-game').easyAutocomplete({
'url': function (game) {
return '/games?webauth=' + getAuth() + '&search=' + game;
},
'getValue': 'game',
'requestDelay': 300,
'list': {
'match': {
'enabled': true
}
}
});
// Input check for strings.
$('input[data-str="text"]').on('input', function() {
helpers.handleInputString($(this));
});
// Handle the hidding of the dashboard panels.
$('#dashboard-views, #dashboard-followers, #dashboard-viewers').on('click', function(e) {
helpers.handlePanelToggleInfo($(this), e.target.id);
});
$(window).resize(function() {
let isSmall = $('.small-box').width() < 230;
$('.small-box').each(function() {
const h3 = $(this).find('h3');
if (h3.attr('id') != 'dashboard-uptime') {
helpers.handlePanelSetInfo(h3, h3.attr('id'), h3.data('parsed'));
}
});
});
// Handle updating the title, game.
$('#dashboard-btn-update').on('click', function() {
// Update title.
socket.sendCommand('update_title', 'settitlesilent ' + $('#stream-title').val(), function() {
// Update game.
socket.sendCommand('update_game', 'setgamesilent ' + $('#stream-game').val(), function() {
toastr.success('Successfully updated stream information!');
});
});
});
// Handle user action button.
$('.user-action').on('click', function() {
let action = $(this).find('a').html().toLowerCase(),
username = $('#user-action-user').val(),
command;
if (username.length < 1) {
return;
}
switch (action) {
case 'permit':
command = 'permit ' + username;
break;
case 'shoutout':
command = 'shoutout ' + username;
break;
case 'raid':
command = 'raid ' + username;
break;
case 'host':
command = 'host ' + username;
break;
}
// Run the command.
socket.sendCommand('user_action_cmd', command, function() {
// Clear the input.
$('#user-action-user').val('');
// Let the user know.
toastr.success('Successfully ran action on ' + username + '!');
});
});
// Handle custom command run.
$('#custom-command-run').on('select2:select', function(e) {
socket.sendCommand('send_command', e.params.data.text.substr(1), function() {
// Alert user.
toastr.success('Successfully ran command ' + e.params.data.text);
// Clear input.
$('#custom-command-run').val('').trigger('change');
});
});
// Handle running a commercial.
$('#dashboard-btn-instant-commercial').on('click', function() {
if ($('#instant-commercial-length').val() === "") {
toastr.error('Please select a commercial length');
return;
}
socket.sendCommand('instant_commercial', 'commercial ' + $('#instant-commercial-length').val() + ($('#instant-commercial-silent').is(':checked') ? ' silent' : ''), function() {
toastr.success('Successfully ran a commercial!');
});
});
// Handle sending as bot.
$('#dashboard-btn-msg-bot').on('click', function() {
if ($('#msg-bot').val() === "") {
toastr.error('Please enter a message');
return;
}
socket.sendCommand('msg-bot', 'echo ' + $('#msg-bot').val(), function() {
toastr.success('Successfully sent a message as the bot!');
});
});
// Mouse hover/leave event log.
$('.event-log').on('mouseenter mouseleave', function(event) {
canScroll = event.type === 'mouseleave';
});
// Handle player toggle
$('#toggle-player').off().on('click', function() {
let checked = $(this).is(':checked');
// Update the toggle.
socket.updateDBValue('panel_chat_toggle', 'panelData', 'hasPlayer', checked, function() {
if (checked && location.protocol.toLowerCase().startsWith('https') && !(location.port > 0 && location.port !== 443)) {
$('#twitch-player-iframe').html($('<iframe/>', {
'frameborder': '0',
'scrolling': 'no',
'style': 'width: 100%; height: 450px; margin-bottom: -5px;',
'src': 'https://player.twitch.tv/?channel=' + getChannelName() + '&muted=true&autoplay=false' + '&parent=' + location.hostname
}));
// Handle the box size.
if ($('#twitch-chat-iframe').html().length > 0) {
$('#twitch-player-box').prop('class', 'col-md-6').removeClass('off');
$('#twitch-chat-box').prop('class', 'col-md-6');
} else {
$('#twitch-player-box').prop('class', 'col-md-12');
}
} else if (checked) {
$('#twitch-player-iframe').html('Due to changes by Twitch, the live feed panel can no longer be displayed unless you enable SSL on the PhantomBot Panel and change the baseport to 443. This may not work without root privileges.<br /><br />Alternatively, you can login using the GitHub version of the panel at <a href="https://phantombot.github.io/PhantomBot/">PhantomBot - GitHub.io</a> which gets around this issue.<br /><br />For help setting up SSL, please see <a href="https://phantombot.github.io/PhantomBot/guides/#guide=content/integrations/twitchembeds">this guide</a>.');
$('#twitch-player-iframe').addClass('box-body');
// Handle the box size.
if ($('#twitch-chat-iframe').html().length > 0) {
$('#twitch-player-box').prop('class', 'col-md-6').removeClass('off');
$('#twitch-chat-box').prop('class', 'col-md-6');
} else {
$('#twitch-player-box').prop('class', 'col-md-12');
}
} else {
$('#twitch-player-iframe').html('');
$('#twitch-player-box').addClass('off');
$('#twitch-chat-box').prop('class', 'col-md-12');
}
});
});
// Handle chat toggle.
$('#toggle-chat').off().on('click', function() {
let checked = $(this).is(':checked');
// Update the toggle.
socket.updateDBValue('panel_chat_toggle', 'panelData', 'hasChat', checked, function() {
if (checked && location.protocol.toLowerCase().startsWith('https') && !(location.port > 0 && location.port !== 443)) {
$('#twitch-chat-iframe').html($('<iframe/>', {
'frameborder': '0',
'scrolling': 'no',
'style': 'width: 100%; height: 450px; margin-bottom: -5px;',
'src': 'https://www.twitch.tv/embed/' + getChannelName() + '/chat' + (helpers.isDark ? '?darkpopout&' : '?') + 'parent=' + location.hostname
}));
// Handle the box size.
if ($('#twitch-player-iframe').html().length > 0) {
$('#twitch-chat-box').prop('class', 'col-md-6').removeClass('off');
$('#twitch-player-box').prop('class', 'col-md-6');
} else {
$('#twitch-chat-box').prop('class', 'col-md-12');
}
} else if (checked) {
$('#twitch-chat-iframe').html('Due to changes by Twitch, the chat panel can no longer be displayed unless you enable SSL on the PhantomBot Panel and change the baseport to 443. This may not work without root privileges.<br /><br />Alternatively, you can login using the GitHub version of the panel at <a href="https://phantombot.github.io/PhantomBot/">PhantomBot - GitHub.io</a> which gets around this issue.<br /><br />For help setting up SSL, please see <a href="https://phantombot.github.io/PhantomBot/guides/#guide=content/integrations/twitchembeds">this guide</a>.');
$('#twitch-chat-iframe').addClass('box-body');
// Handle the box size.
if ($('#twitch-player-iframe').html().length > 0) {
$('#twitch-chat-box').prop('class', 'col-md-6').removeClass('off');
$('#twitch-player-box').prop('class', 'col-md-6');
} else {
$('#twitch-chat-box').prop('class', 'col-md-12');
}
} else {
$('#twitch-chat-iframe').html('');
$('#twitch-chat-box').addClass('off');
$('#twitch-player-box').prop('class', 'col-md-12');
}
});
});
// Event sorting toggle.
$('#toggle-reverse-events').off().on('click', function() {
socket.updateDBValue('event_sort_update', 'panelData', 'isReverseSortEvents', $(this).is(':checked'), function() {
window.location.reload();
});
});
// Set an interval that updates basic panel info every 10 seconds.
helpers.setInterval(function() {
helpers.log('Refreshing dashboard data.', helpers.LOG_TYPE.INFO);
// Query stream data.
socket.getDBValue('dashboard_get_data_refresh', 'panelData', 'stream', function(e) {
// Parse our object.
e = JSON.parse(e.panelData);
// Set views if not hidden.
helpers.handlePanelSetInfo($('#dashboard-views').data('number', helpers.parseNumber(e.views)), 'dashboard-views', helpers.fixNumber(e.views));
// Set viewers.
helpers.handlePanelSetInfo($('#dashboard-viewers').data('number', helpers.parseNumber(e.viewers)), 'dashboard-viewers', helpers.fixNumber(e.viewers));
// Set followers.
helpers.handlePanelSetInfo($('#dashboard-followers').data('number', helpers.parseNumber(e.followers)), 'dashboard-followers', helpers.fixNumber(e.followers));
// Set uptime.
if (e.isLive) {
$('#dashboard-uptime').html(e.uptime);
$('#bg-uptime').removeClass('bg-red').addClass('bg-green');
} else {
$('#dashboard-uptime').html('Offline');
$('#bg-uptime').removeClass('bg-green').addClass('bg-red');
}
});
// Query event log.
socket.getDBValue('dashboard_get_events_refresh', 'panelData', 'data', function(e) {
if (e.panelData !== null && e.panelData.length > 0) {
let events = JSON.parse(e.panelData);
// This should never be null unless the user removes the DB table.
if (events !== null) {
// Sort events if needed.
if (helpers.isReverseSortEvents) {
events.sort(function(a, b) {
return b.date - a.date;
});
} else {
events.sort(function(a, b) {
return a.date - b.date;
});
}
let htmlEvents = $('<ul/>', {
'class': 'recent-events'
});
for (let i = 0; i < events.length; i++) {
let p = $('<p/>');
// Append date.
p.append($('<span/>', {
'class': 'event-date',
'html': helpers.getPaddedDateString(new Date(events[i].date).toLocaleString()) + ' '
}));
// Append type.
p.append($('<span/>', {
'class': 'label',
'style': helpers.getEventColor(events[i].type),
'html': events[i].type
}))
// Append message.
p.append($('<span/>', {
'html': ' ' + helpers.getEventMessage(events[i])
}));
// Append to list.
htmlEvents.append(p);
}
// Append the information to the main div.
$('.event-log').html(htmlEvents);
// Scroll to bottom of event log if the user isn't checking it.
if (canScroll) {
$('.event-log').scrollTop((helpers.isReverseSortEvents ? ($('.event-log').scrollTop() - $('.recent-events').height()) : $('.recent-events').height()));
}
}
}
});
}, 1e4);
});

View File

@@ -0,0 +1,715 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Main function that gets all of our data.
$(function() {
// Get all module toggles.
socket.getDBValues('alerts_get_modules', {
tables: ['modules', 'modules', 'modules', 'modules', 'modules', 'modules', 'modules', 'modules', 'modules', 'modules', 'modules', 'modules'],
keys: ['./discord/handlers/followHandler.js', './discord/handlers/subscribeHandler.js', './discord/handlers/hostHandler.js',
'./discord/handlers/bitsHandler.js', './discord/handlers/clipHandler.js', './discord/systems/greetingsSystem.js', './discord/handlers/streamlabsHandler.js',
'./discord/handlers/raidHandler.js', './discord/handlers/tipeeeStreamHandler.js', './discord/handlers/streamElementsHandler.js',
'./discord/handlers/twitterHandler.js', './discord/handlers/streamHandler.js']
}, true, function(e) {
// Handle the settings button.
let keys = Object.keys(e),
module = '',
i;
for (i = 0; i < keys.length; i++) {
module = keys[i].substring(keys[i].lastIndexOf('/') + 1).replace('.js', '');
// Handle the status of the buttons.
if (e[keys[i]] === 'false') {
// Handle the switch.
$('#' + module + 'Toggle').prop('checked', false);
// Handle the settings button.
$('#discord' + (module.charAt(0).toUpperCase() + module.substring(1)) + 'Settings').prop('disabled', true);
}
}
});
});
// Function that handles events
$(function() {
// Toggle for the alert modules.
$('[data-alert-toggle]').on('change', function() {
let name = $(this).attr('id'),
checked = $(this).is(':checked');
// Handle the module.
socket.sendCommandSync('discord_alerts_module_toggle', 'module '
+ (checked ? 'enablesilent' : 'disablesilent') + ' ' + $(this).data('alert-toggle'), function() {
name = name.replace('Toggle', 'Settings');
// Toggle the settings button.
$('#discord' + name.charAt(0).toUpperCase() + name.substring(1)).prop('disabled', !checked);
// Alert the user.
toastr.success('Successfully ' + (checked ? 'enabled' : 'disabled') + ' the alert module!');
});
});
// Follower alert.
$('#discordFollowHandlerSettings').on('click', function() {
socket.getDBValues('discord_alerts_follow_get_settings', {
tables: ['discordSettings', 'discordSettings', 'discordSettings'],
keys: ['followToggle', 'followMessage', 'followChannel']
}, true, function(e) {
helpers.getModal('follow-alert', 'Follower Alert Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Add the toggle for follow alerts.
.append(helpers.getDropdownGroup('follow-toggle', 'Enable Follow Alerts', (e.followToggle === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If a message should be said in the channel when someone follows.'))
// Add the the text area for the follow message.
.append(helpers.getTextAreaGroup('follow-message', 'text', 'Follow Message', '', e.followMessage,
'Message said when someone follows the channel. Tag: (name)', false))
// Add the the box for the reward.
.append(helpers.getInputGroup('follow-channel', 'text', 'Alert Channel', '#alerts', e.followChannel,
'Channel where all alerts should go too.')),
function() { // Callback once the user clicks save.
let followToggle = $('#follow-toggle').find(':selected').text() === 'Yes',
followMessage = $('#follow-message'),
followChannel = $('#follow-channel');
// Make sure everything has been filled it correctly.
switch (false) {
case helpers.handleInputString(followMessage):
case helpers.handleInputString(followChannel):
break;
default:
// Update settings.
socket.updateDBValues('discord_alerts_follow_update_settings', {
tables: ['discordSettings', 'discordSettings', 'discordSettings'],
keys: ['followToggle', 'followMessage', 'followChannel'],
values: [followToggle, followMessage.val(), followChannel.val()]
}, function() {
socket.wsEvent('discord', './discord/handlers/followHandler.js', '', [], function() {
// Close the modal.
$('#follow-alert').modal('toggle');
// Alert the user.
toastr.success('Successfully updated the follower alert settings!');
});
});
}
}).modal('toggle');
});
});
// Subscriber alerts.
$('#discordSubscribeHandlerSettings').on('click', function() {
socket.getDBValues('discord_alerts_subscribe_get_settings', {
tables: ['discordSettings', 'discordSettings', 'discordSettings', 'discordSettings', 'discordSettings', 'discordSettings', 'discordSettings', 'discordSettings', 'discordSettings'],
keys: ['subMessage', 'primeMessage', 'resubToggle', 'giftsubMessage', 'subToggle', 'primeToggle', 'resubMessage', 'giftsubToggle', 'subChannel']
}, true, function(e) {
helpers.getModal('subscribe-alert', 'Subscriber Alert Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Add the div for the col boxes.
.append($('<div/>', {
'class': 'panel-group',
'id': 'accordion'
})
// Append first collapsible accordion.
.append(helpers.getCollapsibleAccordion('main-1', 'Subscription Settings', $('<form/>', {
'role': 'form'
})
// Add toggle for normal subscriptions.
.append(helpers.getDropdownGroup('sub-toggle', 'Enable Subscription Alerts', (e.subToggle === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If a message should be said in a channel when someone subscribes.'))
// Append message box for the message
.append(helpers.getTextAreaGroup('sub-msg', 'text', 'Subscription Message', '', e.subMessage,
'Message said when someone subscribes to the channel. Tags: (name) and (plan)', false))))
// Append second collapsible accordion.
.append(helpers.getCollapsibleAccordion('main-2', 'Prime Subscription Settings', $('<form/>', {
'role': 'form'
})
// Add toggle for prime subscriptions.
.append(helpers.getDropdownGroup('primesub-toggle', 'Enable Prime Subscription Alerts', (e.primeToggle === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If a message should be said in the channel when someone subscribes with Twitch Prime.'))
// Append message box for the message
.append(helpers.getTextAreaGroup('primesub-msg', 'text', 'Prime Subscription Message', '', e.primeMessage,
'Message said when someone subscribes to the channel with Twitch Prime. Tags: (name) and (plan)', false))))
// Append third collapsible accordion.
.append(helpers.getCollapsibleAccordion('main-3', 'Re-subscription Settings', $('<form/>', {
'role': 'form'
})
// Add toggle for resubscriptions.
.append(helpers.getDropdownGroup('resub-toggle', 'Enable Re-subscription Alerts', (e.resubToggle === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If a message should be said in the channel when someone resubscribes.'))
// Append message box for the message
.append(helpers.getTextAreaGroup('resub-msg', 'text', 'Re-subscription Message', '', e.resubMessage,
'Message said when someone resubscribes to the channel. Tags: (name), (plan), and (months)', false))))
// Append forth collapsible accordion.
.append(helpers.getCollapsibleAccordion('main-4', 'Gifted Subscription Settings', $('<form/>', {
'role': 'form'
})
// Add toggle for gifted subscriptions.
.append(helpers.getDropdownGroup('gifsub-toggle', 'Enable Gifted Subscription Alerts', (e.giftsubToggle === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If a message should be said in the channel when someone gifts a subscription. This also toggles the reward.'))
// Append message box for the message
.append(helpers.getTextAreaGroup('gifsub-msg', 'text', 'Gifted Subscription Message', '', e.giftsubMessage,
'Message said when someone resubscribes to the channel. Tags: (name), (recipient), (plan), and (months)', false))))
// Append fifth collapsible accordion.
.append(helpers.getCollapsibleAccordion('main-5', 'Alert Channel Settings', $('<form/>', {
'role': 'form'
})
// Add channel box.
.append(helpers.getInputGroup('channel-alert', 'text', 'Alert Channel', '#alerts', e.subChannel,
'Channel where all alerts should go too.'))))),
function() { // Callback once the user clicks save.
let subToggle = $('#sub-toggle').find(':selected').text() === 'Yes',
subMsg = $('#sub-msg'),
primeSubToggle = $('#primesub-toggle').find(':selected').text() === 'Yes',
primeSubMsg = $('#primesub-msg'),
reSubToggle = $('#resub-toggle').find(':selected').text() === 'Yes',
reSubMsg = $('#resub-msg'),
gifSubToggle = $('#gifsub-toggle').find(':selected').text() === 'Yes',
gifSubMsg = $('#gifsub-msg'),
subChannel = $('#channel-alert'),
gifSubReward = $('#gifsub-reward');
// Make sure the user has someone in each box.
switch (false) {
case helpers.handleInputString(subMsg):
case helpers.handleInputString(primeSubMsg):
case helpers.handleInputString(reSubMsg):
case helpers.handleInputString(gifSubMsg):
break;
default:
socket.updateDBValues('discord_alerts_subscribe_update_settings', {
tables: ['discordSettings', 'discordSettings', 'discordSettings', 'discordSettings', 'discordSettings', 'discordSettings', 'discordSettings', 'discordSettings', 'discordSettings'],
keys: ['subMessage', 'primeMessage', 'resubMessage', 'giftsubMessage', 'subToggle', 'primeToggle', 'resubToggle', 'giftsubToggle', 'subChannel'],
values: [subMsg.val(), primeSubMsg.val(), reSubMsg.val(), gifSubMsg.val(), subToggle, primeSubToggle, reSubToggle, gifSubToggle, subChannel.val()]
}, function() {
socket.wsEvent('discord', './discord/handlers/subscribeHandler.js', '', [], function() {
// Close the modal.
$('#subscribe-alert').modal('toggle');
// Alert the user.
toastr.success('Successfully updated subscription alert settings!');
});
});
}
}).modal('toggle');
});
});
// Host settings button.
$('#discordHostHandlerSettings').on('click', function() {
socket.getDBValues('alerts_get_host_settings', {
tables: ['discordSettings', 'discordSettings', 'discordSettings', 'discordSettings'],
keys: ['hostToggle', 'hostMessage', 'autohostMessage', 'hostChannel']
}, true, function(e) {
helpers.getModal('host-alert', 'Host Alert Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Add the div for the col boxes.
.append($('<div/>', {
'class': 'panel-group',
'id': 'accordion'
})
// Add the toggle for host alerts.
.append(helpers.getDropdownGroup('host-toggle', 'Enable Host Alerts', (e.hostToggle === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If a message should be said in the channel when someone follows.'))
// Add the the text area for the host message.
.append(helpers.getTextAreaGroup('host-message', 'text', 'Host Message', '', e.hostMessage,
'Message said when someone hosts the channel. Tag: (name) and (viewers)', false))
// Add the the text area for the auto host message.
.append(helpers.getTextAreaGroup('auto-host-message', 'text', 'Auto host Message', '', e.autohostMessage,
'Message said when someone auto-hosts the channel. Tag: (name) and (viewers)', false))
// Add the the box for the reward.
.append(helpers.getInputGroup('host-channel', 'text', 'Alert Channel', '#alerts', e.hostChannel,
'Channel where all alerts should go too.'))),
function() { // Callback once the user clicks save.
let hostToggle = $('#host-toggle').find(':selected').text() === 'Yes',
hostMsg = $('#host-message'),
autoHostMsg = $('#auto-host-message'),
hostChannel = $('#host-channel');
// Make sure the user has someone in each box.
switch (false) {
case helpers.handleInputString(hostMsg):
case helpers.handleInputString(autoHostMsg):
break;
default:
socket.updateDBValues('alerts_update_host_settings', {
tables: ['discordSettings', 'discordSettings', 'discordSettings', 'discordSettings'],
keys: ['hostToggle', 'hostMessage', 'autohostMessage', 'hostChannel'],
values: [hostToggle, hostMsg.val(), autoHostMsg.val(), hostChannel.val()]
}, function() {
socket.wsEvent('discord', './discord/handlers/hostHandler.js', '', [], function() {
// Close the modal.
$('#host-alert').modal('toggle');
// Alert the user.
toastr.success('Successfully updated host alert settings!');
});
});
}
}).modal('toggle');
});
});
// Bits settings.
$('#discordBitsHandlerSettings').on('click', function() {
socket.getDBValues('discord_alerts_get_bits_settings', {
tables: ['discordSettings', 'discordSettings', 'discordSettings'],
keys: ['bitsToggle', 'bitsMessage', 'bitsChannel']
}, true, function(e) {
helpers.getModal('bits-alert', 'Bits Alert Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Add the toggle for bits alerts.
.append(helpers.getDropdownGroup('bits-toggle', 'Enable Bits Alerts', (e.bitsToggle === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If a message should be said in the channel when someone cheers.'))
// Add the the text area for the bits message.
.append(helpers.getTextAreaGroup('bits-message', 'text', 'Bits Message', '', e.bitsMessage,
'Message said when someone cheers in the the channel. Tags: (name), (message), and (amount)', false))
// Add the box for the reward.
.append(helpers.getInputGroup('bits-channel', 'text', 'Alert Channel', '#alerts', e.bitsChannel,
'The channel the bits message is sent in.')),
function() { // Callback once the user clicks save.
let bitsToggle = $('#bits-toggle').find(':selected').text() === 'Yes',
bitsMsg = $('#bits-message'),
bitsChan = $('#bits-channel');
// Make sure the user has someone in each box.
switch (false) {
case helpers.handleInputString(bitsMsg):
break;
default:
socket.updateDBValues('alerts_update_bits_settings', {
tables: ['discordSettings', 'discordSettings', 'discordSettings'],
keys: ['bitsToggle', 'bitsMessage', 'bitsChannel'],
values: [bitsToggle, bitsMsg.val(), bitsChan.val()]
}, function() {
socket.wsEvent('discord', './discord/handlers/bitsHandler.js', '', [], function() {
// Close the modal.
$('#bits-alert').modal('toggle');
// Alert the user.
toastr.success('Successfully updated Bits alert settings!');
});
});
}
}).modal('toggle');
});
});
// Clips handler.
$('#discordClipHandlerSettings').on('click', function() {
socket.getDBValues('alerts_get_clip_settings', {
tables: ['discordSettings', 'discordSettings', 'discordSettings'],
keys: ['clipsToggle', 'clipsMessage', 'clipsChannel']
}, true, function(e) {
helpers.getModal('clip-alert', 'Clip Alert Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Add the toggle for clip alerts.
.append(helpers.getDropdownGroup('clip-toggle', 'Enable Clip Alerts', (e.clipsToggle === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If a message should be said in the channel when someone creates a clip.'))
// Add the text area for the clips message.
.append(helpers.getTextAreaGroup('clip-message', 'text', 'Clip Message', '', e.clipsMessage,
'Message said when someone creates a clip. Tags: (name), (embedurl) - to be used as the entire message, and (url)', false))
// Add the text area for the clips channel.
.append(helpers.getInputGroup('clip-channel', 'text', 'Alert Channel', '#alerts', e.clipsChannel,
'The channel where clips will be posted.')),
function() { // Callback once the user clicks save.
let clipToggle = $('#clip-toggle').find(':selected').text() === 'Yes',
clipMsg = $('#clip-message'),
clipsChan = $('#clip-channel');
// Make sure the user has someone in each box.
switch (false) {
case helpers.handleInputString(clipMsg):
break;
default:
socket.updateDBValues('alerts_update_clip_settings', {
tables: ['discordSettings', 'discordSettings', 'discordSettings'],
keys: ['clipsToggle', 'clipsMessage', 'clipsChannel'],
values: [clipToggle, clipMsg.val(), clipsChan.val()]
}, function() {
socket.wsEvent('discord', './discord/handlers/clipHandler.js', '', [], function() {
// Close the modal.
$('#clip-alert').modal('toggle');
// Alert the user.
toastr.success('Successfully updated Clip alert settings!');
});
});
}
}).modal('toggle');
});
});
// Stream Alert settings.
$('#discordStreamHandlerSettings').on('click', function() {
socket.getDBValues('alerts_get_stream_settings', {
tables: ['discordSettings', 'discordSettings', 'discordSettings', 'discordSettings',
'discordSettings', 'discordSettings', 'discordSettings', 'discordSettings',
'discordSettings'],
keys: ['onlineToggle', 'onlineMessage', 'offlineToggle', 'offlineMessage',
'gameToggle', 'gameMessage', 'botGameToggle', 'onlineChannel', 'deleteMessageToggle']
}, true, function(e) {
helpers.getModal('stream-alert', 'Stream Alert Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Add the div for the col boxes.
.append($('<div/>', {
'class': 'panel-group',
'id': 'accordion'
})
// Append first collapsible accordion.
.append(helpers.getCollapsibleAccordion('main-1', 'Online Settings', $('<form/>', {
'role': 'form'
})
// Add the toggle for online alerts.
.append(helpers.getDropdownGroup('online-toggle', 'Enable Online Alerts', (e.onlineToggle === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If a message should be said in the channel when you go live on Twitch.'))
// Add the toggle for auto bot streaming status
.append(helpers.getDropdownGroup('online-status', 'Enable Bot Status', (e.botGameToggle === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'Show your bot as streaming when you go live.'))
// Add the text area for the online message.
.append(helpers.getTextAreaGroup('online-message', 'text', 'Online Message', '', e.onlineMessage,
'Message said when you go live. This message is in an embed style. Tags: (name)', false))))
// Append second collapsible accordion.
.append(helpers.getCollapsibleAccordion('main-2', 'Offline Settings', $('<form/>', {
'role': 'form'
})
// Add the toggle for offline alerts.
.append(helpers.getDropdownGroup('offline-toggle', 'Enable Offline Alerts', (e.offlineToggle === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If a message should be said in the channel when you go offline on Twitch.'))
// Add the text area for the offline message.
.append(helpers.getTextAreaGroup('offline-message', 'text', 'Offline Message', '', e.offlineMessage,
'Message said when you go offline. This message is in an embed style. Tags: (name)', false))))
// Append third collapsible accordion.
.append(helpers.getCollapsibleAccordion('main-3', 'Game Change Settings', $('<form/>', {
'role': 'form'
})
// Add the toggle for offline alerts.
.append(helpers.getDropdownGroup('game-toggle', 'Enable Game Change Alerts', (e.gameToggle === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If a message should be said in the channel when you switch games on Twitch.'))
// Add the text area for the offline message.
.append(helpers.getTextAreaGroup('game-message', 'text', 'Game Change Message', '', e.gameMessage,
'Message said when you change games on Twitch. Tags: (name)', false))))
// Append forth collapsible accordion.
.append(helpers.getCollapsibleAccordion('main-4', 'Alert Channel Settings', $('<form/>', {
'role': 'form'
})
// Add channel box.
.append(helpers.getInputGroup('channel-alert', 'text', 'Alert Channel', '#alerts', e.onlineChannel,
'Channel where all alerts should go too.'))
// Add the toggle for auto bot streaming status
.append(helpers.getDropdownGroup('delete-message', 'Delete alerts automatically', (e.deleteMessageToggle === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'Automatically delete the online message after the stream ends and the offline message when a new stream starts.'))))),
function() {
let onlineToggle = $('#online-toggle').find(':selected').text() === 'Yes',
statusToggle = $('#online-status').find(':selected').text() === 'Yes',
onlineMessage = $('#online-message'),
offlineToggle = $('#offline-toggle').find(':selected').text() === 'Yes',
offlineMessage = $('#offline-message'),
gameToggle = $('#game-toggle').find(':selected').text() === 'Yes',
gameMessage = $('#game-message'),
channel = $('#channel-alert'),
deleteMessageToggle = $('#delete-message').find(':selected').text() === 'Yes';
switch (false) {
case helpers.handleInputString(onlineMessage):
case helpers.handleInputString(offlineMessage):
case helpers.handleInputString(gameMessage):
break;
default:
socket.updateDBValues('discord_stream_alerts_updater', {
tables: ['discordSettings', 'discordSettings', 'discordSettings', 'discordSettings',
'discordSettings', 'discordSettings', 'discordSettings', 'discordSettings',
'discordSettings',],
keys: ['onlineToggle', 'onlineMessage', 'offlineToggle', 'offlineMessage',
'gameToggle', 'gameMessage', 'botGameToggle', 'onlineChannel', 'deleteMessageToggle'],
values: [onlineToggle, onlineMessage.val(), offlineToggle, offlineMessage.val(),
gameToggle, gameMessage.val(), statusToggle, channel.val(), deleteMessageToggle]
}, function() {
socket.wsEvent('discord', './discord/handlers/streamHandler.js', '', [], function() {
// Close the modal.
$('#stream-alert').modal('toggle');
// Alert the user.
toastr.success('Successfully updated stream alert settings!');
});
});
}
}).modal('toggle');
});
});
// Greetings alerts.
$('#discordGreetingsSystemSettings').on('click', function() {
socket.getDBValues('alerts_get_greetings_settings', {
tables: ['discordSettings', 'discordSettings', 'discordSettings', 'discordSettings',
'discordSettings', 'discordSettings'],
keys: ['joinToggle', 'partToggle', 'joinMessage', 'partMessage', 'greetingsChannel',
'greetingsDefaultGroup']
}, true, function(e) {
helpers.getModal('greeting-alert', 'Greetings Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Add the div for the col boxes.
.append($('<div/>', {
'class': 'panel-group',
'id': 'accordion'
})
// Append first collapsible accordion.
.append(helpers.getCollapsibleAccordion('main-1', 'Join Settings', $('<form/>', {
'role': 'form'
})
// Add the toggle for alert
.append(helpers.getDropdownGroup('join-toggle', 'Enable Join Messages', (e.joinToggle === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If a message should be said in the channel when someone joins your Discord.'))
// Add a box for the join role.
.append(helpers.getInputGroup('join-role', 'text', 'Join Role', 'Newbie', e.greetingsDefaultGroup,
'Default role applied to new users who join your Discord.'))
// Add the text area for the message.
.append(helpers.getTextAreaGroup('join-message', 'text', 'Join Message', '', e.joinMessage,
'Message said when someone joins your Discord. Tags: (name) and (@name)', false))))
// Append second collapsible accordion.
.append(helpers.getCollapsibleAccordion('main-2', 'Part Settings', $('<form/>', {
'role': 'form'
})
// Add the toggle for part alerts.
.append(helpers.getDropdownGroup('part-toggle', 'Enable Part Messages', (e.partToggle === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If a message should be said in the channel when someone leaves your Discord.'))
// Add the text area for the part message.
.append(helpers.getTextAreaGroup('part-message', 'text', 'Part Message', '', e.partMessage,
'Message said when someone leaves your Discord. Tags: (name) and (@name)', false))))
// Append third collapsible accordion.
.append(helpers.getCollapsibleAccordion('main-3', 'Alert Channel Settings', $('<form/>', {
'role': 'form'
})
// Add channel box.
.append(helpers.getInputGroup('channel-alert', 'text', 'Alert Channel', '#alerts', e.greetingsChannel,
'Channel where all alerts should go too.'))))),
function() {
let joinToggle = $('#join-toggle').find(':selected').text() === 'Yes',
partToggle = $('#part-toggle').find(':selected').text() === 'Yes',
partMessage = $('#part-message'),
joinMessage = $('#join-message'),
joinRole = $('#join-role'),
channel = $('#channel-alert');
switch (false) {
case helpers.handleInputString(joinMessage):
case helpers.handleInputString(partMessage):
case helpers.handleInputString(channel):
break;
default:
socket.updateDBValues('discord_greetings_alerts_updater', {
tables: ['discordSettings', 'discordSettings', 'discordSettings', 'discordSettings',
'discordSettings', 'discordSettings'],
keys: ['joinToggle', 'partToggle', 'joinMessage', 'partMessage', 'greetingsChannel',
'greetingsDefaultGroup'],
values: [joinToggle, partToggle, joinMessage.val(), partMessage.val(),
channel.val(), joinRole.val()]
}, function() {
socket.wsEvent('discord', './discord/systems/greetingsSystem.js', '', [], function() {
// Close the modal.
$('#greeting-alert').modal('toggle');
// Alert the user.
toastr.success('Successfully updated greetings alert settings!');
});
});
}
}).modal('toggle');
});
});
// StreamLabs settings.
$('#discordStreamlabsHandlerSettings').on('click', function() {
socket.getDBValues('discord_alerts_streamlabs_get_settings', {
tables: ['discordSettings', 'discordSettings', 'discordSettings'],
keys: ['streamlabsToggle', 'streamlabsMessage', 'streamlabsChannel']
}, true, function(e) {
helpers.getModal('streamlabs-alert', 'StreamLabs Alert Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Add the toggle for follow alerts.
.append(helpers.getDropdownGroup('streamlabs-toggle', 'Enable StreamLabs Alerts', (e.streamlabsToggle === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If a message should be said in the channel when someone tips.'))
// Add the the text area for the follow message.
.append(helpers.getTextAreaGroup('streamlabs-message', 'text', 'Tip Message', '', e.streamlabsMessage,
'Message said when someone tips the channel. Tag: (name), (amount), (currency), and (message)', false))
// Add the the box for the reward.
.append(helpers.getInputGroup('streamlabs-channel', 'text', 'Alert Channel', '#alerts', e.streamlabsChannel,
'Channel where all alerts should go too.')),
function() { // Callback once the user clicks save.
let streamLabsToggle = $('#streamlabs-toggle').find(':selected').text() === 'Yes',
streamLabsMessage = $('#streamlabs-message'),
streamLabsChannel = $('#streamlabs-channel');
// Make sure everything has been filled it correctly.
switch (false) {
case helpers.handleInputString(streamLabsMessage):
case helpers.handleInputString(streamLabsChannel):
break;
default:
// Update settings.
socket.updateDBValues('discord_alerts_streamlabs_update_settings', {
tables: ['discordSettings', 'discordSettings', 'discordSettings'],
keys: ['streamlabsToggle', 'streamlabsMessage', 'streamlabsChannel'],
values: [streamLabsToggle, streamLabsMessage.val(), streamLabsChannel.val()]
}, function() {
socket.wsEvent('discord', './discord/handlers/streamlabsHandler.js', '', [], function() {
// Close the modal.
$('#streamlabs-alert').modal('toggle');
// Alert the user.
toastr.success('Successfully updated the StreamLabs alert settings!');
});
});
}
}).modal('toggle');
});
});
// TipeeeStream settings.
$('#discordTipeeeStreamHandlerSettings').on('click', function() {
socket.getDBValues('discord_alerts_tipeeestream_get_settings', {
tables: ['discordSettings', 'discordSettings', 'discordSettings'],
keys: ['tipeeestreamToggle', 'tipeeestreamMessage', 'tipeeestreamChannel']
}, true, function(e) {
helpers.getModal('tipeeestream-alert', 'TipeeeStream Alert Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Add the toggle for follow alerts.
.append(helpers.getDropdownGroup('tipeeestream-toggle', 'Enable TipeeeStream Alerts', (e.tipeeestreamToggle === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If a message should be said in the channel when someone tips.'))
// Add the the text area for the follow message.
.append(helpers.getTextAreaGroup('tipeeestream-message', 'text', 'Tip Message', '', e.tipeeestreamMessage,
'Message said when someone tips the channel. Tag: (name), (amount), (currency), and (message)', false))
// Add the the box for the reward.
.append(helpers.getInputGroup('tipeeestream-channel', 'text', 'Alert Channel', '#alerts', e.tipeeestreamChannel,
'Channel where all alerts should go too.')),
function() { // Callback once the user clicks save.
let tipeeeStreamToggle = $('#tipeeestream-toggle').find(':selected').text() === 'Yes',
tipeeeStreamMessage = $('#tipeeestream-message'),
tipeeeStreamChannel = $('#tipeeestream-channel');
// Make sure everything has been filled it correctly.
switch (false) {
case helpers.handleInputString(tipeeeStreamMessage):
case helpers.handleInputString(tipeeeStreamChannel):
break;
default:
// Update settings.
socket.updateDBValues('discord_alerts_tipeeestream_update_settings', {
tables: ['discordSettings', 'discordSettings', 'discordSettings'],
keys: ['tipeeestreamToggle', 'tipeeestreamMessage', 'tipeeestreamChannel'],
values: [tipeeeStreamToggle, tipeeeStreamMessage.val(), tipeeeStreamChannel.val()]
}, function() {
socket.wsEvent('discord', './discord/handlers/tipeeeStreamHandler.js', '', [], function() {
// Close the modal.
$('#tipeeestream-alert').modal('toggle');
// Alert the user.
toastr.success('Successfully updated the TipeeeStream alert settings!');
});
});
}
}).modal('toggle');
});
});
// StreamElements settings.
$('#discordStreamElementsHandlerSettings').on('click', function() {
socket.getDBValues('discord_alerts_streamelements_get_settings', {
tables: ['discordSettings', 'discordSettings', 'discordSettings'],
keys: ['streamelementsToggle', 'streamelementsMessage', 'streamelementsChannel']
}, true, function(e) {
helpers.getModal('streamelements-alert', 'StreamElements Alert Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Add the toggle for follow alerts.
.append(helpers.getDropdownGroup('streamelements-toggle', 'Enable StreamElements Alerts', (e.streamelementsToggle === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If a message should be said in the channel when someone tips.'))
// Add the the text area for the follow message.
.append(helpers.getTextAreaGroup('streamelements-message', 'text', 'Tip Message', '', e.streamelementsMessage,
'Message said when someone tips the channel. Tag: (name), (amount), (currency), and (message)', false))
// Add the the box for the reward.
.append(helpers.getInputGroup('streamelements-channel', 'text', 'Alert Channel', '#alerts', e.streamelementsChannel,
'Channel where all alerts should go too.')),
function() { // Callback once the user clicks save.
let streamElementsToggle = $('#streamelements-toggle').find(':selected').text() === 'Yes',
streamElementsMessage = $('#streamelements-message'),
streamElementsChannel = $('#streamelements-channel');
// Make sure everything has been filled it correctly.
switch (false) {
case helpers.handleInputString(streamElementsMessage):
case helpers.handleInputString(streamElementsChannel):
break;
default:
// Update settings.
socket.updateDBValues('discord_alerts_streamelements_update_settings', {
tables: ['discordSettings', 'discordSettings', 'discordSettings'],
keys: ['streamelementsToggle', 'streamelementsMessage', 'streamelementsChannel'],
values: [streamElementsToggle, streamElementsMessage.val(), streamElementsChannel.val()]
}, function() {
socket.wsEvent('discord', './discord/handlers/streamElementsHandler.js', '', [], function() {
// Close the modal.
$('#streamelements-alert').modal('toggle');
// Alert the user.
toastr.success('Successfully updated the StreamElements alert settings!');
});
});
}
}).modal('toggle');
});
});
// Twitter settings.
$('#discordTwitterHandlerSettings').on('click', function() {
socket.getDBValues('discord_alerts_twitter_get_settings', {
tables: ['discordSettings', 'discordSettings'],
keys: ['twitterToggle', 'twitterChannel']
}, true, function(e) {
helpers.getModal('twitter-alert', 'Twitter Alert Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Add the toggle for follow alerts.
.append(helpers.getDropdownGroup('twitter-toggle', 'Enable Twitter Alerts', (e.twitterToggle === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If your Tweets should be posted in Discord. Please note that the Twitch Twitter module needs to be setup for this to work.'))
// Add the the box for the reward.
.append(helpers.getInputGroup('twitter-channel', 'text', 'Alert Channel', '#alerts', e.twitterChannel,
'Channel where all alerts should go too.')),
function() { // Callback once the user clicks save.
let twitterToggle = $('#twitter-toggle').find(':selected').text() === 'Yes',
twitterChannel = $('#twitter-channel');
// Make sure everything has been filled it correctly.
switch (false) {
case helpers.handleInputString(twitterChannel):
break;
default:
// Update settings.
socket.updateDBValues('discord_alerts_twitter_update_settings', {
tables: ['discordSettings', 'discordSettings'],
keys: ['twitterToggle', 'twitterChannel'],
values: [twitterToggle, twitterChannel.val()]
}, function() {
socket.wsEvent('discord', './discord/handlers/twitterHandler.js', '', [], function() {
// Close the modal.
$('#twitter-alert').modal('toggle');
// Alert the user.
toastr.success('Successfully updated the Twitter alert settings!');
});
});
}
}).modal('toggle');
});
});
});

View File

@@ -0,0 +1,390 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
$(run = function() {
// Check if the module is enabled.
socket.getDBValue('discord_custom_command_module', 'modules', './discord/commands/customCommands.js', function(e) {
// If the module is off, don't load any data.
if (!helpers.handleModuleLoadUp('discordCustomCommandsModule', e.modules)) {
return;
}
// Query custom commands.
socket.getDBTableValues('discord_commands_get_custom', 'discordCommands', function(results) {
const tableData = [];
for (let i = 0; i < results.length; i++) {
tableData.push([
'!' + results[i].key,
results[i].value,
$('<div/>', {
'class': 'btn-group'
}).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-danger',
'style': 'float: right',
'data-command': results[i].key,
'html': $('<i/>', {
'class': 'fa fa-trash'
})
})).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-warning',
'style': 'float: right',
'data-command': results[i].key,
'html': $('<i/>', {
'class': 'fa fa-edit'
})
})).html()
]);
}
// if the table exists, destroy it.
if ($.fn.DataTable.isDataTable('#discordCustomCommandsTable')) {
$('#discordCustomCommandsTable').DataTable().destroy();
// Remove all of the old events.
$('#discordCustomCommandsTable').off();
}
// Create table.
const table = $('#discordCustomCommandsTable').DataTable({
'searching': true,
'autoWidth': false,
'lengthChange': false,
'data': tableData,
'columnDefs': [
{ 'className': 'default-table', 'orderable': false, 'targets': 2 },
{ 'width': '15%', 'targets': 0 }
],
'columns': [
{ 'title': 'Command' },
{ 'title': 'Response' },
{ 'title': 'Actions' }
]
});
// On delete button.
table.on('click', '.btn-danger', function() {
const command = $(this).data('command'),
row = $(this).parents('tr');
// Ask the user if he want to remove the command.
helpers.getConfirmDeleteModal('custom_command_modal_remove', 'Are you sure you want to remove command !' + command + '?', true,
'The command !' + command + ' has been successfully removed!', function() {
socket.removeDBValues('rm_discord_command', {
tables: ['discordCommands', 'discordPermcom', 'discordCooldown', 'discordChannelcom', 'discordPricecom', 'discordAliascom'],
keys: [command, command, command, command, command, command]
}, function() {
socket.wsEvent('discord', './discord/commands/customCommands.js', 'remove', [command], function() {
// Remove the table row.
table.row(row).remove().draw(false);
});
});
});
});
// On edit button.
table.on('click', '.btn-warning', function() {
const command = $(this).data('command'),
t = $(this);
// Get all the info about the command.
socket.getDBValues('custom_command_edit', {
tables: ['discordPricecom', 'discordPermcom', 'discordAliascom', 'discordChannelcom', 'discordCommands', 'discordCooldown', 'discordPermsObj'],
keys: [command, command, command, command, command, command, 'obj']
}, function(e) {
let cooldownJson = (e.discordCooldown === null ? { isGlobal: 'true', seconds: 0 } : JSON.parse(e.discordCooldown));
let perm = JSON.parse(e.discordPermcom);
let perms = JSON.parse(e.discordPermsObj);
// Get advance modal from our util functions in /utils/helpers.js
helpers.getAdvanceModal('edit-command', 'Edit Command', 'Save', $('<form/>', {
'role': 'form'
})
// Append input box for the command name. This one is disabled.
.append(helpers.getInputGroup('command-name', 'text', 'Command', '', '!' + command, 'Name of the command. This cannot be edited.', true))
// Append a text box for the command response.
.append(helpers.getTextAreaGroup('command-response', 'text', 'Response', '', e.discordCommands, 'Response of the command.'))
// Append a select option for the command permission.
.append(helpers.getMultiDropdownGroup('command-permission', 'Allowed Roles and Permissions', [
{
'title': 'Permissions',
'options': perm.permissions
},
{
'title': 'Roles',
'selected': perm.roles,
'options': perms.roles
}
], 'Which roles are allowed to run this command. The Administrator permission is people with the Administrator permission selected on their role in Discord'))
// Add an advance section that can be opened with a button toggle.
.append($('<div/>', {
'class': 'collapse',
'id': 'advance-collapse',
'html': $('<form/>', {
'role': 'form'
})
// Append input box for the command cost.
.append(helpers.getInputGroup('command-cost', 'number', 'Cost', '0', helpers.getDefaultIfNullOrUndefined(e.discordPricecom, '0'),
'Cost in points that will be taken from the user when running the command.'))
// Append input box for the command channel.
.append(helpers.getInputGroup('command-channel', 'text', 'Channel', '#commands', helpers.getDefaultIfNullOrUndefined(e.discordChannelcom, ''),
'Channel you want this command to work in. Seperate with commas (no spaces) for multiple. If left empty, the command will work in all channels.'))
// Append input box for the command alias.
.append(helpers.getInputGroup('command-alias', 'text', 'Alias', '!ex', helpers.getDefaultIfNullOrUndefined(e.discordAliascom, ''),
'Another command name that will also trigger this command.'))
// Append input box for the command cooldown.
.append(helpers.getInputGroup('command-cooldown', 'number', 'Cooldown (Seconds)', '0', helpers.getDefaultIfNullOrUndefined(cooldownJson.seconds, '0'),
'Cooldown of the command in seconds.')
// Append checkbox for if the cooldown is global or per-user.
.append(helpers.getCheckBox('command-cooldown-global', cooldownJson.isGlobal === 'true', 'Global',
'If checked the cooldown will be applied to everyone in the channel. When not checked, the cooldown is applied per-user.')))
// Callback function to be called once we hit the save button on the modal.
})), function() {
let commandName = $('#command-name'),
commandResponse = $('#command-response'),
commandPermissions = $('#command-permission option'),
commandCost = $('#command-cost'),
commandChannel = $('#command-channel'),
commandAlias = $('#command-alias'),
commandCooldown = $('#command-cooldown'),
commandCooldownGlobal = $('#command-cooldown-global').is(':checked');
// Remove the ! and spaces.
commandName.val(commandName.val().replace(/(\!|\s)/g, '').toLowerCase());
commandAlias.val(commandAlias.val().replace(/(\!|\s)/g, '').toLowerCase());
// Generate all permissions.
const permObj = {
'roles': [],
'permissions': []
};
commandPermissions.each(function() {
var section = $(this).parent().attr('label');
// This is a permission.
if (section == 'Permissions') {
permObj.permissions.push({
'name': $(this).html(),
'selected': $(this).is(':selected').toString()
});
} else if ($(this).is(':selected')) {
permObj.roles.push($(this).attr('id'));
}
});
// Handle each input to make sure they have a value.
switch (false) {
case helpers.handleInputString(commandName):
case helpers.handleInputString(commandResponse):
case helpers.handleInputNumber(commandCooldown):
break;
default:
// Save command information here and close the modal.
socket.updateDBValues('custom_command_add', {
tables: ['discordPricecom', 'discordPermcom', 'discordCommands', 'discordCooldown'],
keys: [commandName.val(), commandName.val(), commandName.val(), commandName.val()],
values: [commandCost.val(), JSON.stringify(permObj), commandResponse.val(), JSON.stringify({command: String(commandName.val()), seconds: String(commandCooldown.val()), isGlobal: String(commandCooldownGlobal)})]
}, function() {
if (commandChannel.val().length > 0) {
socket.updateDBValue('discord_channel_command_cmd', 'discordChannelcom', commandName.val(), commandChannel.val(), new Function());
} else {
socket.removeDBValue('discord_channel_command_cmd', 'discordChannelcom', commandName.val(), new Function());
}
if (commandAlias.val().length > 0) {
socket.updateDBValue('discord_alias_command_cmd', 'discordAliascom', commandName.val(), commandAlias.val(), new Function());
} else {
socket.removeDBValue('discord_alias_command_cmd', 'discordAliascom', commandName.val(), new Function());
}
// Reload the table.
run();
// Close the modal.
$('#edit-command').modal('hide');
// Tell the user the command was added.
toastr.success('Successfully edited command !' + commandName.val());
// I hate doing this, but the logic is fucked anyways.
helpers.setTimeout(function() {
// Add the cooldown to the cache.
socket.wsEvent('discord', './discord/commands/customCommands.js', '',
[commandName.val(), JSON.stringify(permObj),
commandChannel.val(), commandAlias.val(), commandCost.val()], new Function());
}, 5e2);
});
}
}).on('shown.bs.modal', function(e) {
$('#command-permission').select2();
}).modal('toggle');
});
});
});
});
});
// Function that handlers the loading of events.
$(function() {
// Toggle for the module.
$('#discordCustomCommandsModuleToggle').on('change', function() {
// Enable the module then query the data.
socket.sendCommandSync('discord_custom_commands_module_toggle_cmd',
'module ' + ($(this).is(':checked') ? 'enablesilent' : 'disablesilent') + ' ./discord/commands/customCommands.js', run);
});
// Add command button.
$('#discord-addcom-button').on('click', function() {
socket.getDBValue('discord_custom_cmds_roles', 'discordPermsObj', 'obj', function(permObj) {
let perms = JSON.parse(permObj.discordPermsObj);
// Get advance modal from our util functions in /utils/helpers.js
helpers.getAdvanceModal('add-command', 'Add Command', 'Save', $('<form/>', {
'role': 'form'
})
// Append input box for the command name.
.append(helpers.getInputGroup('command-name', 'text', 'Command', '!example'))
// Append a text box for the command response.
.append(helpers.getTextAreaGroup('command-response', 'text', 'Response', 'Response example!'))
// Append a select option for the command permission.
.append(helpers.getMultiDropdownGroup('command-permission', 'Allowed Roles and Permissions', [
{
'title': 'Permissions',
'options': [{
'name': 'Administrators',
'selected': 'true'
}]
},
{
'title': 'Roles',
'options': perms.roles
}
], 'Which roles are allowed to run this command. The Administrator permission is people with the Administrator permission selected on their role in Discord'))
// Add an advance section that can be opened with a button toggle.
.append($('<div/>', {
'class': 'collapse',
'id': 'advance-collapse',
'html': $('<form/>', {
'role': 'form'
})
// Append input box for the command cost.
.append(helpers.getInputGroup('command-cost', 'number', 'Cost', '0', '0',
'Cost in points that will be taken from the user when running the command.'))
// Append input box for the command channel.
.append(helpers.getInputGroup('command-channel', 'text', 'Channel', '#commands', '',
'Channel you want this command to work in. Seperate with a space and comma for multiple. If left empty, the command will work in all channels.'))
// Append input box for the command alias.
.append(helpers.getInputGroup('command-alias', 'text', 'Alias', '!ex', '',
'Another command name that will also trigger this command.'))
// Append input box for the command cooldown.
.append(helpers.getInputGroup('command-cooldown', 'number', 'Cooldown (Seconds)', '0', '5',
'Cooldown of the command in seconds.')
// Append checkbox for if the cooldown is global or per-user.
.append(helpers.getCheckBox('command-cooldown-global', true, 'Global',
'If checked the cooldown will be applied to everyone in the channel. When not checked, the cooldown is applied per-user.')))
// Callback function to be called once we hit the save button on the modal.
})), function() {
let commandName = $('#command-name'),
commandResponse = $('#command-response'),
commandPermissions = $('#command-permission option'),
commandCost = $('#command-cost'),
commandChannel = $('#command-channel'),
commandAlias = $('#command-alias'),
commandCooldown = $('#command-cooldown'),
commandCooldownGlobal = $('#command-cooldown-global').is(':checked');
// Remove the ! and spaces.
commandName.val(commandName.val().replace(/(\!|\s)/g, '').toLowerCase());
commandAlias.val(commandAlias.val().replace(/(\!|\s)/g, '').toLowerCase());
// Handle each input to make sure they have a value.
switch (false) {
case helpers.handleInputString(commandName):
case helpers.handleInputString(commandResponse):
case helpers.handleInputNumber(commandCooldown):
break;
default:
// Make sure the command doesn't exist already.
socket.getDBValue('custom_command_exists', 'discordPermcom', commandName.val(), function(e) {
// If the command exists we stop here.
if (e.discordPermcom !== null) {
toastr.error('Failed to add command as it already exists.');
return;
}
// Generate all permissions.
const permObj = {
'roles': [],
'permissions': []
};
commandPermissions.each(function() {
var section = $(this).parent().attr('label');
// This is a permission.
if (section == 'Permissions') {
permObj.permissions.push({
'name': $(this).html(),
'selected': $(this).is(':selected').toString()
});
} else if ($(this).is(':selected')) {
permObj.roles.push($(this).attr('id'));
}
});
// Save command information here and close the modal.
socket.updateDBValues('custom_command_add', {
tables: ['discordPricecom', 'discordPermcom', 'discordCommands', 'discordCooldown'],
keys: [commandName.val(), commandName.val(), commandName.val(), commandName.val()],
values: [commandCost.val(), JSON.stringify(permObj), commandResponse.val(), JSON.stringify({command: String(commandName.val()), seconds: String(commandCooldown.val()), isGlobal: String(commandCooldownGlobal)})]
}, function() {
if (commandChannel.val().length > 0) {
socket.updateDBValue('discord_channel_command_cmd', 'discordChannelcom', commandName.val(), commandChannel.val(), new Function());
} else {
socket.removeDBValue('discord_channel_command_cmd', 'discordChannelcom', commandName.val(), new Function());
}
if (commandAlias.val().length > 0) {
socket.updateDBValue('discord_alias_command_cmd', 'discordAliascom', commandName.val(), commandAlias.val(), new Function());
} else {
socket.removeDBValue('discord_alias_command_cmd', 'discordAliascom', commandName.val(), new Function());
}
// Reload the table.
run();
// Close the modal.
$('#add-command').modal('hide');
// Tell the user the command was added.
toastr.success('Successfully added command !' + commandName.val());
// I hate doing this, but the logic is fucked anyways.
helpers.setTimeout(function() {
// Add the cooldown to the cache.
socket.wsEvent('discord', './discord/commands/customCommands.js', '',
[commandName.val(), JSON.stringify(permObj),
commandChannel.val(), commandAlias.val(), commandCost.val()], new Function());
}, 5e2);
});
});
}
}).on('shown.bs.modal', function(e) {
$('#command-permission').select2();
}).modal('toggle');
});
});
});

View File

@@ -0,0 +1,263 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Function that querys all of the data we need.
$(run = function() {
// Query all commands.
socket.getDBTableValues('discord_commands_get_all', 'discordPermcom', function(results) {
socket.getDBTableValues('discord_custom_commands_get_all', 'discordCommands', function(customCommands) {
socket.getDBValue('discord_default_cmds_roles', 'discordPermsObj', 'obj', function(permObj) {
let tableData = [],
cmds = [];
permObj = JSON.parse(permObj.discordPermsObj);
// Get all custom commands.
for (let i = 0; i < customCommands.length; i++) {
cmds.push(customCommands[i].key);
}
for (let i = 0; i < results.length; i++) {
if (cmds.indexOf(results[i].key) !== -1 || results[i].key.indexOf(' ') !== -1) {
continue;
}
// Get all permissions for commands, this is slow, might need to make it better later.
let permJson = JSON.parse(results[i].value);
let perms = {
'permissions': [],
'roles': []
}
for (let j = 0; j < permObj.roles.length; j++) {
if (permJson.roles.indexOf(permObj.roles[j]._id) > -1) {
perms.roles.push(permObj.roles[j].name);
}
}
// No loop needed here since there's just one permission for now.
if (permJson.permissions[0].selected == 'true') {
perms.permissions.push(permJson.permissions[0].name);
}
tableData.push([
'!' + results[i].key,
(perms.roles.length > 0 ? perms.roles.join(', ') : 'None'),
(perms.permissions.length > 0 ? perms.permissions.join(', ') : 'None'),
$('<div/>', {
'class': 'btn-group'
}).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-danger',
'style': 'float: right',
'data-toggle': 'tooltip',
'title': 'Deletes the command permission and resets it to default on startup. This does not remove the command unless it doesn\'t exist anymore.',
'data-command': results[i].key,
'html': $('<i/>', {
'class': 'fa fa-refresh'
})
})).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-warning',
'style': 'float: right',
'data-command': results[i].key,
'html': $('<i/>', {
'class': 'fa fa-edit'
})
})).html()
]);
}
// if the table exists, destroy it.
if ($.fn.DataTable.isDataTable('#discordDefaultCommandsTable')) {
$('#discordDefaultCommandsTable').DataTable().destroy();
// Remove all of the old events.
$('#discordDefaultCommandsTable').off();
}
// Create table.
const table = $('#discordDefaultCommandsTable').DataTable({
'searching': true,
'autoWidth': false,
'data': tableData,
'columnDefs': [
{ 'className': 'default-table-large', 'orderable': false, 'targets': 3 },
{ 'width': '45%', 'targets': 0 }
],
'columns': [
{ 'title': 'Command' },
{ 'title': 'Allowed Roles' },
{ 'title': 'Allowed Permissions' },
{ 'title': 'Actions' }
]
});
// On delete button.
table.on('click', '.btn-danger', function() {
let command = $(this).data('command'),
row = $(this).parents('tr'),
t = $(this);
// Ask the user if he want to reset the command.
helpers.getConfirmDeleteModal('discord_default_command_modal_remove', 'Are you sure you want to reset the command\'s permission?', false,
'The command\'s permission has been reset!', function() {
socket.removeDBValue('discord_permcom_temp_del', 'discordPermcom', command, function(e) {
// Hide tooltip.
t.tooltip('hide');
// Remove the table row.
table.row(row).remove().draw(false);
});
});
});
// On edit button.
table.on('click', '.btn-warning', function() {
let command = $(this).data('command'),
t = $(this);
// Get all the info about the command.
socket.getDBValues('default_command_edit', {
tables: ['discordPricecom', 'discordPermcom', 'discordAliascom', 'discordChannelcom', 'discordCooldown', 'discordPermsObj'],
keys: [command, command, command, command, command, 'obj']
}, function(e) {
let cooldownJson = (e.discordCooldown === null ? { isGlobal: 'true', seconds: 0 } : JSON.parse(e.discordCooldown));
let perm = JSON.parse(e.discordPermcom);
let perms = JSON.parse(e.discordPermsObj);
// Get advance modal from our util functions in /utils/helpers.js
helpers.getAdvanceModal('edit-command', 'Edit Command', 'Save', $('<form/>', {
'role': 'form'
})
// Append input box for the command name. This one is disabled.
.append(helpers.getInputGroup('command-name', 'text', 'Command', '', '!' + command, 'Name of the command. This cannot be edited.', true))
// Append a select option for the command permission.
.append(helpers.getMultiDropdownGroup('command-permission', 'Allowed Roles and Permissions', [
{
'title': 'Permissions',
'options': perm.permissions
},
{
'title': 'Roles',
'selected': perm.roles,
'options': perms.roles
}
], 'Which roles are allowed to run this command. The Administrator permission is people with the Administrator permission selected on their role in Discord'))
// Add an advance section that can be opened with a button toggle.
.append($('<div/>', {
'class': 'collapse',
'id': 'advance-collapse',
'html': $('<form/>', {
'role': 'form'
})
// Append input box for the command cost.
.append(helpers.getInputGroup('command-cost', 'number', 'Cost', '0', helpers.getDefaultIfNullOrUndefined(e.discordPricecom, '0'),
'Cost in points that will be taken from the user when running the command.'))
// Append input box for the command channel.
.append(helpers.getInputGroup('command-channel', 'text', 'Channel', '#commands', helpers.getDefaultIfNullOrUndefined(e.discordChannelcom, ''),
'Channel you want this command to work in. Seperate with a space and comma for multiple. If left empty, the command will work in all channels.'))
// Append input box for the command alias.
.append(helpers.getInputGroup('command-alias', 'text', 'Alias', '!ex', helpers.getDefaultIfNullOrUndefined(e.discordAliascom, ''),
'Another command name that will also trigger this command.'))
// Append input box for the command cooldown.
.append(helpers.getInputGroup('command-cooldown', 'number', 'Cooldown (Seconds)', '0', helpers.getDefaultIfNullOrUndefined(cooldownJson.seconds, '0'),
'Cooldown of the command in seconds.')
// Append checkbox for if the cooldown is global or per-user.
.append(helpers.getCheckBox('command-cooldown-global', cooldownJson.isGlobal === 'true', 'Global',
'If checked the cooldown will be applied to everyone in the channel. When not checked, the cooldown is applied per-user.')))
// Callback function to be called once we hit the save button on the modal.
})), function() {
let commandName = $('#command-name'),
commandPermissions = $('#command-permission option'),
commandCost = $('#command-cost'),
commandChannel = $('#command-channel'),
commandAlias = $('#command-alias'),
commandCooldown = $('#command-cooldown'),
commandCooldownGlobal = $('#command-cooldown-global').is(':checked');
// Remove the ! and spaces.
commandName.val(commandName.val().replace(/\!/g, '').toLowerCase());
commandAlias.val(commandAlias.val().replace(/(\!|\s)/g, '').toLowerCase());
// Generate all permissions.
const permObj = {
'roles': [],
'permissions': []
};
commandPermissions.each(function() {
var section = $(this).parent().attr('label');
// This is a permission.
if (section == 'Permissions') {
permObj.permissions.push({
'name': $(this).html(),
'selected': $(this).is(':selected').toString()
});
} else if ($(this).is(':selected')) {
permObj.roles.push($(this).attr('id'));
}
});
// Handle each input to make sure they have a value.
switch (false) {
case helpers.handleInputString(commandName):
case helpers.handleInputNumber(commandCooldown):
break;
default:
// Save command information here and close the modal.
socket.updateDBValues('custom_command_add', {
tables: ['discordPricecom', 'discordPermcom', 'discordCooldown'],
keys: [commandName.val(), commandName.val(), commandName.val()],
values: [commandCost.val(), JSON.stringify(permObj), JSON.stringify({command: String(commandName.val()), seconds: String(commandCooldown.val()), isGlobal: String(commandCooldownGlobal)})]
}, function() {
if (commandChannel.val().length > 0) {
socket.updateDBValue('discord_channel_command_cmd', 'discordChannelcom', commandName.val(), commandChannel.val(), new Function());
} else {
socket.removeDBValue('discord_channel_command_cmd', 'discordChannelcom', commandName.val(), new Function());
}
if (commandAlias.val().length > 0) {
socket.updateDBValue('discord_alias_command_cmd', 'discordAliascom', commandName.val(), commandAlias.val(), new Function());
} else {
socket.removeDBValue('discord_alias_command_cmd', 'discordAliascom', commandName.val(), new Function());
}
// Reload the table.
run();
// Close the modal.
$('#edit-command').modal('hide');
// Tell the user the command was added.
toastr.success('Successfully edited command !' + commandName.val());
// I hate doing this, but the logic is fucked anyways.
helpers.setTimeout(function() {
// Add the cooldown to the cache.
socket.wsEvent('discord', './discord/commands/customCommands.js', '',
[commandName.val(), JSON.stringify(permObj),
commandChannel.val(), commandAlias.val(), commandCost.val()], new Function());
}, 5e2);
});
}
}).on('shown.bs.modal', function(e) {
$('#command-permission').select2();
}).modal('toggle');
});
});
});
});
});
});

View File

@@ -0,0 +1,247 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Function that querys all of the data we need.
$(function() {
// Get all module toggles.
socket.getDBValues('discord_games_get_modules', {
tables: ['modules', 'modules', 'modules', 'modules', 'modules', 'modules', 'modules'],
keys: ['./discord/games/gambling.js', './discord/games/kill.js', './discord/games/random.js',
'./discord/games/roll.js', './discord/games/roulette.js', './discord/games/slotMachine.js',
'./discord/games/8ball.js']
}, true, function(results) {
// Handle the settings button.
let keys = Object.keys(results),
module = '',
i;
for (i = 0; i < keys.length; i++) {
// Handle the status of the buttons.
if (results[keys[i]] === 'false') {
module = keys[i].substring(keys[i].lastIndexOf('/') + 1).replace('.js', '');
// Handle the switch.
$('#discord_' + module + 'Toggle').prop('checked', false);
// Handle the settings button.
$('#discord_' + module + 'Settings').prop('disabled', true);
}
}
});
});
// Function that handlers the loading of events.
$(function() {
// Module toggle for games.
$('[data-game-toggle]').on('change', function() {
let name = $(this).attr('id'),
checked = $(this).is(':checked');
// Handle the module.
socket.sendCommandSync('discord_game_module_toggle', 'module ' + (checked ? 'enablesilent' : 'disablesilent') + ' ' + $(this).data('game-toggle'), function() {
// Toggle the settings button.
$('#' + name.replace('Toggle', 'Settings')).prop('disabled', !checked);
// Alert the user.
toastr.success('Successfully ' + (checked ? 'enabled' : 'disabled') + ' the game module!');
});
});
// Role settings.
$('#discord_rollSettings').on('click', function() {
socket.getDBValues('discord_get_roll_settings', {
tables: ['discordRollReward', 'discordRollReward', 'discordRollReward',
'discordRollReward', 'discordRollReward', 'discordRollReward'],
keys: ['rewards_0', 'rewards_1', 'rewards_2', 'rewards_3', 'rewards_4', 'rewards_5']
}, true, function(e) {
helpers.getModal('roll-settings', 'Dice Roll Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Add the reward 1.
.append(helpers.getInputGroup('reward-1', 'number', 'Double 1s Reward', '', e.rewards_0, 'Reward for rolling double 1s.'))
// Add the reward 2.
.append(helpers.getInputGroup('reward-2', 'number', 'Double 2s Reward', '', e.rewards_1, 'Reward for rolling double 2s.'))
// Add the reward 3.
.append(helpers.getInputGroup('reward-3', 'number', 'Double 3s Reward', '', e.rewards_2, 'Reward for rolling double 3s.'))
// Add the reward 4.
.append(helpers.getInputGroup('reward-4', 'number', 'Double 4s Reward', '', e.rewards_3, 'Reward for rolling double 4s.'))
// Add the reward 5.
.append(helpers.getInputGroup('reward-5', 'number', 'Double 5s Reward', '', e.rewards_4, 'Reward for rolling double 5s.'))
// Add the reward 6.
.append(helpers.getInputGroup('reward-6', 'number', 'Double 6s Reward', '', e.rewards_5, 'Reward for rolling double 6s.')),
function() { // Callback for when the user clicks save.
let values = [];
// Get all rewards
for (let i = 1; i <= 6; i++) {
let valObj = $('#reward-' + i);
if (!helpers.handleInputNumber(valObj, 0)) {
return;
}
values.push(valObj.val());
}
// Update the rewards.
socket.updateDBValues('roll_update_settings', {
tables: ['discordRollReward', 'discordRollReward', 'discordRollReward', 'discordRollReward',
'discordRollReward', 'discordRollReward'],
keys: ['rewards_0', 'rewards_1', 'rewards_2', 'rewards_3', 'rewards_4', 'rewards_5'],
values: values
}, function() {
// Close the modal.
$('#roll-settings').modal('toggle');
// Alert the user.
toastr.success('Successfully updated the dice roll settings!');
});
}).modal('toggle');
});
});
// Slot machine settings.
$('#discord_slotMachineSettings').on('click', function() {
socket.getDBValues('get_slot_machine_settings', {
tables: ['discordSlotMachineReward', 'discordSlotMachineReward', 'discordSlotMachineReward', 'discordSlotMachineReward',
'discordSlotMachineReward', 'discordSlotMachineEmojis', 'discordSlotMachineEmojis', 'discordSlotMachineEmojis',
'discordSlotMachineEmojis', 'discordSlotMachineEmojis'],
keys: ['reward_0', 'reward_1', 'reward_2', 'reward_3', 'reward_4', 'emoji_0', 'emoji_1', 'emoji_2', 'emoji_3', 'emoji_4']
}, true, function(e) {
helpers.getModal('slotmachine-game', 'Slot Machine Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Add the div for the col boxes.
.append($('<div/>', {
'class': 'panel-group',
'id': 'accordion'
})
// Append first collapsible accordion.
.append(helpers.getCollapsibleAccordion('main-1', 'Reward Settings', $('<form/>', {
'role': 'form'
})
// Add the reward 1 slot.
.append(helpers.getInputGroup('reward-1', 'number', 'Slot Reward One', '', e.reward_0, 'Reward for the first slot.'))
// Add the reward 2 slot.
.append(helpers.getInputGroup('reward-2', 'number', 'Slot Reward Two', '', e.reward_1, 'Reward for the second slot.'))
// Add the reward 3 slot.
.append(helpers.getInputGroup('reward-3', 'number', 'Slot Reward Three', '', e.reward_2, 'Reward for the third slot.'))
// Add the reward 4 slot.
.append(helpers.getInputGroup('reward-4', 'number', 'Slot Reward Four', '', e.reward_3, 'Reward for the forth slot.'))
// Add the reward 5 slot.
.append(helpers.getInputGroup('reward-5', 'number', 'Slot Reward Five', '', e.reward_4, 'Reward for the fifth slot.'))))
// Append second collapsible accordion.
.append(helpers.getCollapsibleAccordion('main-2', 'Emoji Settings', $('<form/>', {
'role': 'form'
})
// Add the emoji 1 slot.
.append(helpers.getInputGroup('emoji-1', 'text', 'Slot emoji One', '', e.emoji_0, 'emoji for the first slot.'))
// Add the emoji 2 slot.
.append(helpers.getInputGroup('emoji-2', 'text', 'Slot emoji Two', '', e.emoji_1, 'emoji for the second slot.'))
// Add the emoji 3 slot.
.append(helpers.getInputGroup('emoji-3', 'text', 'Slot emoji Three', '', e.emoji_2, 'emoji for the third slot.'))
// Add the emoji 4 slot.
.append(helpers.getInputGroup('emoji-4', 'text', 'Slot emoji Four', '', e.emoji_3, 'emoji for the forth slot.'))
// Add the emoji 5 slot.
.append(helpers.getInputGroup('emoji-5', 'text', 'Slot emoji Five', '', e.emoji_4, 'emoji for the fifth slot.'))))),
function() { // Callback for when the user clicks save.
let values = [];
// Get all prices.
for (let i = 1; i <= 5; i++) {
let valObj = $('#reward-' + i);
if (!helpers.handleInputNumber(valObj, 0)) {
return;
}
values.push(valObj.val());
}
// Get all emojis.
for (let i = 1; i <= 5; i++) {
let valObj = $('#emoji-' + i);
if (!helpers.handleInputString(valObj)) {
return;
}
values.push(valObj.val());
}
// Update settings.
socket.updateDBValues('update_slot_settings', {
tables: ['discordSlotMachineReward', 'discordSlotMachineReward', 'discordSlotMachineReward', 'discordSlotMachineReward',
'discordSlotMachineReward', 'discordSlotMachineEmojis', 'discordSlotMachineEmojis',
'discordSlotMachineEmojis', 'discordSlotMachineEmojis', 'discordSlotMachineEmojis'],
keys: ['reward_0', 'reward_1', 'reward_2', 'reward_3', 'reward_4', 'emoji_0', 'emoji_1', 'emoji_2', 'emoji_3', 'emoji_4'],
values: values
}, function() {
// Close the modal.
$('#slotmachine-game').modal('toggle');
// Alert the user.
toastr.success('Successfully updated the slot machine settings!');
});
}).modal('toggle');
});
});
// Gambling settings.
$('#discord_gamblingSettings').on('click', function() {
socket.getDBValues('get_gambling_settings', {
tables: ['discordGambling', 'discordGambling', 'discordGambling', 'discordGambling'],
keys: ['winGainPercent', 'winRange', 'max', 'min']
}, true, function(e) {
helpers.getModal('gambling-settings', 'Gambling Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Add the gambling gain percent.
.append(helpers.getInputGroup('gambling-gain', 'number', 'Gambling Gain Percent', '', e.winGainPercent,
'How many points are given based on what the user gambled. The gambled amount is always given back.'))
// Add the gambling win range.
.append(helpers.getInputGroup('gambling-range', 'number', 'Gambling Winning Range', '', e.winRange,
'The winning range of the gambling game. Anything gambled below this number will be a lost. Maximum is 100.'))
// Add the gambling max.
.append(helpers.getInputGroup('gambling-max', 'number', 'Gambling Maximum Amount', '', e.max,
'The maximum amount of points that can be gambled at once.'))
// Add the gambling min.
.append(helpers.getInputGroup('gambling-min', 'number', 'Gambling Minimum Amount', '', e.min,
'The minimum amount of points that can be gambled at once.')),
function() { // Callback once the user clicks save.
let winGain = $('#gambling-gain'),
winRange = $('#gambling-range'),
max = $('#gambling-max'),
min = $('#gambling-min');
switch (false) {
case helpers.handleInputNumber(winGain, 1, 100):
case helpers.handleInputNumber(winRange, 1, 100):
case helpers.handleInputNumber(max, 1):
case helpers.handleInputNumber(min, 1):
break;
default:
socket.updateDBValues('update_gambling_settings', {
tables: ['discordGambling', 'discordGambling', 'discordGambling', 'discordGambling'],
keys: ['winGainPercent', 'winRange', 'max', 'min'],
values: [winGain.val(), winRange.val(), max.val(), min.val()]
}, function() {
socket.wsEvent('update_gambling_settings_cmd', './discord/games/gambling.js', '', [], function() {
// Close the modal.
$('#gambling-settings').modal('toggle');
// Alert the user.
toastr.success('Successfully updated gambling settings!');
});
});
}
}).modal('toggle');
});
});
});

View File

@@ -0,0 +1,171 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Function that querys all of the data we need.
$(run = function() {
// Check if the module is enabled.
socket.getDBValue('discord_keyword_module', 'modules', './discord/handlers/keywordHandler.js', function(e) {
// If the module is off, don't load any data.
if (!helpers.handleModuleLoadUp('discordKeywordsModule', e.modules)) {
return;
}
// Get all keywords.
socket.getDBTableValues('keywords_get_all', 'discordKeywords', function(results) {
const tableData = [];
for (let i = 0; i < results.length; i++) {
tableData.push([
results[i].key,
results[i].value,
$('<div/>', {
'class': 'btn-group'
}).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-danger',
'style': 'float: right',
'data-keyword': results[i].key,
'html': $('<i/>', {
'class': 'fa fa-trash'
})
})).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-warning',
'style': 'float: right',
'data-keyword': results[i].key,
'html': $('<i/>', {
'class': 'fa fa-edit'
})
})).html()
]);
}
// if the table exists, destroy it.
if ($.fn.DataTable.isDataTable('#discordKeywordTable')) {
$('#discordKeywordTable').DataTable().destroy();
// Remove all of the old events.
$('#discordKeywordTable').off();
}
// Create table.
const table = $('#discordKeywordTable').DataTable({
'searching': true,
'autoWidth': false,
'lengthChange': false,
'data': tableData,
'columnDefs': [
{ 'className': 'default-table', 'orderable': false, 'targets': 2 },
{ 'width': '35%', 'targets': 0 }
],
'columns': [
{ 'title': 'Keyword' },
{ 'title': 'Response' },
{ 'title': 'Actions' }
]
});
// On delete button.
table.on('click', '.btn-danger', function() {
const keyword = $(this).data('keyword'),
row = $(this).parents('tr');
// Ask the user if he want to remove the command.
helpers.getConfirmDeleteModal('custom_command_modal_remove', 'Are you sure you want to remove this keyword?', true,
'The keyword has been successfully removed!', function() {
socket.removeDBValue('discord_keyword_remove', 'discordKeywords', keyword, function() {
// Remove the table row.
table.row(row).remove().draw(false);
});
});
});
// On edit button.
table.on('click', '.btn-warning', function() {
const keyword = $(this).data('keyword'),
t = $(this);
socket.getDBValue('keyword_discord_name_get', 'discordKeywords', keyword, function(e) {
helpers.getModal('edit-keyword', 'Edit Keyword', 'Save', $('<form/>', {
'role': 'form'
})
// Append keyword.
.append(helpers.getInputGroup('keyword-name', 'text', 'Keyword', '', keyword, 'The keyword to trigger the response. This cannot be edited.', true))
// Append response.
.append(helpers.getTextAreaGroup('keyword-response', 'text', 'Response', '', e.discordKeywords, 'Keyword response.')), function() {
const keyword = $('#keyword-name'),
response = $('#keyword-response');
switch (false) {
case helpers.handleInputString(response):
break;
default:
// Update the keyword.
socket.updateDBValue('update_discord_keyword', 'discordKeywords', keyword.val(), response.val(), function() {
// Update the table.
t.parents('tr').find('td:eq(1)').text(response.val());
// Close the modal.
$('#edit-keyword').modal('hide');
// Alert the user.
toastr.success('Successfully edited the keyword!');
});
}
}).modal('toggle');
});
});
});
});
});
// Function that handlers the loading of events.
$(function() {
// Toggle for the module.
$('#discordKeywordsModuleToggle').on('change', function() {
// Enable the module then query the data.
socket.sendCommandSync('discord_keywords_module_toggle_cmd', 'module ' +
($(this).is(':checked') ? 'enablesilent' : 'disablesilent') + ' ./discord/handlers/keywordHandler.js', run);
});
// Add keyword button.
$('#discord-addkey-button').on('click', function() {
helpers.getModal('add-keyword', 'Add Keyword', 'Save', $('<form/>', {
'role': 'form'
})
// Append keyword.
.append(helpers.getInputGroup('keyword-name', 'text', 'Keyword', 'hi', '', 'Keyword that will trigger the response. Regex is allowed.'))
// Append response.
.append(helpers.getTextAreaGroup('keyword-response', 'text', 'Response', 'Hi there!', '', 'Response of the keyword.')), function() {// Callback once we click the save button.
const keyword = $('#keyword-name'),
response = $('#keyword-response');
switch (false) {
case helpers.handleInputString(keyword):
case helpers.handleInputString(response):
break;
default:
// Set the keyword.
socket.updateDBValue('set_discord_keyword', 'discordKeywords', keyword.val(), response.val(), function() {
// Reload the table.
run();
// Close the modal.
$('#add-keyword').modal('hide');
// Alert the user.
toastr.success('Successfully added the keyword!');
});
}
}).modal('toggle');
});
});

View File

@@ -0,0 +1,62 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Function that querys all of the data we need.
$(function() {
// Get Discord logging settings.
socket.getDBValues('get_discord_logging_settings', {
tables: ['discordSettings', 'discordSettings', 'discordSettings'],
keys: ['modLogs', 'customCommandLogs', 'modLogChannel']
}, true, function(e) {
// Mod toggle.
$('#twitch-mod-log').val((e['modLogs'] === 'true' ? 'Yes' : 'No'));
// Commands toggle.
$('#twitch-command-log').val((e['customCommandLogs'] === 'true' ? 'Yes' : 'No'));
// Log channels
$('#twitch-mod-channel, #twitch-command-channel').val((e['modLogChannel'] == null ? '' : e['modLogChannel']));
});
});
// Function that handles events.
$(function() {
// Save button.
$('#discord-logging-save').on('click', function() {
let moderationLogs = $('#twitch-mod-log').find(':selected').text() === 'Yes',
customCommandLog = $('#twitch-command-log').find(':selected').text() === 'Yes',
logChannel = $('#twitch-mod-channel');
// Make sure all settings are entered corretly.
switch (false) {
case helpers.handleInputString(logChannel):
break;
default:
socket.updateDBValues('discord_logs_update', {
tables: ['discordSettings', 'discordSettings', 'discordSettings', 'chatModerator'],
keys: ['modLogs', 'customCommandLogs', 'modLogChannel', 'moderationLogs'],
values: [moderationLogs, customCommandLog, logChannel.val(), moderationLogs]
}, function() {
// Update the scripts variables.
socket.wsEvent('discord_logs', './core/logging.js', '', [], function() {
socket.sendCommand('moderation_reload_settings', 'reloadmoderation', function () {
// Alert the user.
toastr.success('Successfully updated the logs settings!');
});
});
});
}
});
});

View File

@@ -0,0 +1,316 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Function that querys all of the data we need.
$(function () {
// Chart configs. This should not be changed.
let chartConfig = {"type": "doughnut", "data": {"datasets": [{"data": [], "backgroundColor": []}], "labels": []}, "options": {"responsive": false, "title": {"display": true}}},
chartContext = $('#betting-chart').get(0).getContext('2d'),
chart = new Chart(chartContext, chartConfig),
isActive = false;
/*
* @function Inits the chart.
*/
const initChart = function () {
socket.getDBValues('get_betting_options', {
tables: ['bettingPanel', 'bettingPanel'],
keys: ['options', 'title']
}, true, function (e) {
if (e.options !== null) {
socket.getDBTableValues('get_betting_votes', 'bettingVotes', function (votes) {
// Set the chart title.
chartConfig.options.title.text = e.title;
// Set the labels.
chartConfig.data.labels = e.options.split('%space_option%');
// Get all the data.
let ops = e.options.split('%space_option%');
for (let i = 0; i < ops.length; i++) {
if (ops[i].indexOf(' ') !== -1) {
ops[i] = ops[i].split(' ').join('%space_option%');
}
for (let j = 0; j < votes.length; j++) {
if (votes[j].key === ops[i]) {
chartConfig.data.datasets[0].data.push(parseInt(votes[j].value));
chartConfig.data.datasets[0].backgroundColor.push(helpers.getRandomRgbColor());
}
}
}
// Update the chart.
chart.update();
// Mark as active.
isActive = true;
});
}
});
};
initChart();
/*
* @function Updates the chart during a bet.
*/
const updateChart = function () {
socket.getDBValue('get_betting_active_update', 'bettingPanel', 'isActive', function (e) {
if (e.bettingPanel === 'false' || e.bettingPanel === null) {
isActive = false;
return;
} else if (chartConfig.data.datasets[0].backgroundColor.length !== 0 && isActive === false) {
resetChart();
}
// No current chart is done, start a new one.
if (chartConfig.data.datasets[0].backgroundColor.length === 0) {
initChart();
return;
}
socket.getDBValue('get_betting_options_update', 'bettingPanel', 'options', function (e) {
socket.getDBTableValues('get_betting_votes_update', 'bettingVotes', function (votes) {
// Get all the data.
let ops = e.bettingPanel.split('%space_option%');
// Remove current data.
chartConfig.data.datasets[0].data = [];
for (let i = 0; i < ops.length; i++) {
if (ops[i].indexOf(' ') !== -1) {
ops[i] = ops[i].split(' ').join('%space_option%');
}
for (let j = 0; j < votes.length; j++) {
if (votes[j].key === ops[i]) {
chartConfig.data.datasets[0].data.push(parseInt(votes[j].value));
}
}
}
// Update the chart.
chart.update();
});
});
});
};
/*
* @function Resets the bet.
*
* @param {Function} callback
*/
const resetBet = function (callback) {
socket.removeDBValues('reset_betting_options', {
tables: ['bettingPanel', 'bettingPanel'],
keys: ['options', 'isActive']
}, function () {
// Reset the chart.
resetChart();
// Update the chart.
chart.update();
// Alert the user.
toastr.success('Successfully reset the bet.');
// Callback if possible.
if (typeof callback === 'function') {
callback();
}
});
};
/*
* @function Resets the chart.
*/
const resetChart = function () {
// Mark as not acive.
isActive = false;
// Reset the title.
chartConfig.options.title.text = '';
// Reset lables.
chartConfig.data.labels = [];
// Reset the data.
chartConfig.data.datasets[0].data = [];
// Reset the colors.
chartConfig.data.datasets[0].backgroundColor = [];
};
// Reset bet button.
$('#reset-betting').on('click', function () {
helpers.getModal('betting-reset', 'Reset Bet', 'Reset', $('<form/>', {
'role': 'form'
})
// Add refund option
.append(helpers.getCheckBox('bet-refund', false, 'Refund all bets',
'if everyone who placed a bet should get their points back.')),
function () {
resetBet();
if (isActive) {
socket.sendCommand('reset_end_bet_cmd', 'bet reset' + ($('#bet-refund').prop('checked') === true ? ' -refund' : ''), new Function());
isActive = false;
}
$('#betting-reset').modal('toggle');
}).modal('toggle');
});
// Close bet button
$('#close-betting').on('click', function () {
helpers.getModal('betting-close', 'Close Bet', 'Close', $('<form/>', {
'role': 'form'
})
// Append options.
.append(helpers.getInputGroup('bet-winning', 'text', 'Winning Option', 'Option that won the bet. Leave this empty to just close the bet and pick a winning option later.', '',
'Option that won the bet. Leave this empty to just close the bet and pick a winning option later.')),
function () {
socket.sendCommand('close_bet_cmd', 'bet close ' + $('#bet-winning').val(), function () {
toastr.success('Successfully closed the bet.');
$('#betting-close').modal('toggle');
});
}).modal('toggle');
});
// Open bet button.
$('#open-betting').on('click', function () {
helpers.getModal('betting-open', 'Open Bet', 'Open', $('<form/>', {
'role': 'form'
})
// Append bet title.
.append(helpers.getTextAreaGroup('bet-title', 'text', 'Title', 'Which team is going to win?', '', 'Title of the bet.'))
// Append options.
.append(helpers.getInputGroup('bet-options', 'text', 'Options', 'Red, Blue', '',
'Options to be betted on. Each option should be seperated with a comma and space.'))
// Append min bet.
.append(helpers.getInputGroup('bet-min', 'number', 'Minimum Bet', '', '1',
'What is the minimum amount of points users can bet on an option.'))
// Append max bet.
.append(helpers.getInputGroup('bet-max', 'number', 'Maximum Bet', '', '0',
'What is the maximum amount of points users can bet on an option. 0 removes the limit.'))
// Append min bet.
.append(helpers.getInputGroup('bet-timer', 'number', 'Timer (Minutes)', '', '0',
'Timer in minutes of how long the bet will be opened for. 0 means until closed.')),
function () {
let title = $('#bet-title'),
options = $('#bet-options'),
minBet = $('#bet-min'),
maxBet = $('#bet-max'),
timer = $('#bet-timer');
switch (false) {
case helpers.handleInputString(title):
case helpers.handleInputString(options):
case helpers.handleInputNumber(minBet, 1):
case helpers.handleInputNumber(maxBet, 0):
case helpers.handleInputNumber(timer, 0):
break;
default:
socket.sendCommandSync('bet_open_cmd', 'bet open "' + title.val() + '" "' + options.val() + '" ' +
minBet.val() + ' ' + maxBet.val() + ' ' + timer.val(), function () {
// Alert the user.
toastr.success('Successfully opened the bet!');
// Close the modal.
$('#betting-open').modal('toggle');
// Update the chart.
updateChart();
});
}
}).modal('toggle');
});
// Settings button.
$('#settings-betting').on('click', function () {
socket.getDBValues('get_bet_settings', {
tables: ['bettingSettings', 'bettingSettings', 'bettingSettings', 'bettingSettings'],
keys: ['gain', 'save', 'format', 'warningMessages']
}, true, function (e) {
helpers.getModal('betting-settings', 'Bet Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Append a select option for the save option
.append(helpers.getDropdownGroup('save-bets', 'Save Bets', (e.save === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If past bets should be saved.'))
// Append a select option for the warning messages
.append(helpers.getDropdownGroup('warning-bets', 'Warning Messages', (e.warningMessages === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If warning messages should be said in chat when users bet.'))
// Save format
.append(helpers.getInputGroup('bet-format', 'text', 'Save Format', '', e.format,
'In which date format should bets be saved.'))
// Save format
.append(helpers.getInputGroup('bet-gain', 'text', 'Winning Gain (Percent)', '', e.gain,
'The percent of points the user gets from the entire amount of points betted on the winning option. The amount betted is always returned.')),
function () {
let saveBets = $('#save-bets').find(':selected').text() === 'Yes',
warningMessages = $('#warning-bets').find(':selected').text() === 'Yes',
gain = $('#bet-gain'),
format = $('#bet-format');
switch (false) {
case helpers.handleInputNumber(gain, 1, 100):
case helpers.handleInputString(format):
break;
default:
socket.updateDBValues('bet_settings_update', {
tables: ['bettingSettings', 'bettingSettings', 'bettingSettings', 'bettingSettings'],
keys: ['gain', 'save', 'format', 'warningMessages'],
values: [gain.val(), saveBets, format.val(), warningMessages]
}, function () {
socket.sendCommand('bet_settings_update_cmd', 'reloadbet', function () {
// Alert user.
toastr.success('Successfully updated bet settings!');
// Close modal.
$('#betting-settings').modal('toggle');
})
});
}
}).modal('toggle');
});
});
// Module toggle.
$('#bettingSystemModuleToggle').on('change', function () {
socket.sendCommandSync('betting_system_module_toggle_cmd',
'module ' + ($(this).is(':checked') ? 'enablesilent' : 'disablesilent') + ' ./systems/bettingSystem.js', run);
});
// Update the chart every 5 seconds.
helpers.setInterval(updateChart, 5e3);
});
// Handles the module toggle.
$(run = function () {
socket.getDBValue('betting_module_status', 'modules', './systems/bettingSystem.js', function (e) {
if (!helpers.handleModuleLoadUp('bettingSystemModule', e.modules)) {
// Remove the chat.
$('#twitch-chat-betting').find('iframe').remove();
return;
}
if (location.protocol.toLowerCase().startsWith('https') && !(location.port > 0 && location.port !== 443)) {
// Add Twitch chat.
$('#twitch-chat-betting').html($('<iframe/>', {
'frameborder': '0',
'scrolling': 'no',
'style': 'width: 100%; height: 561px; margin-bottom: -5px;',
'src': 'https://www.twitch.tv/embed/' + getChannelName() + '/chat' + (helpers.isDark ? '?darkpopout&' : '?') + 'parent=' + location.hostname
}));
} else {
$('#twitch-chat-betting').html('Due to changes by Twitch, the chat panel can no longer be displayed unless you enable SSL on the PhantomBot Panel and change the baseport to 443. This may not work without root privileges.<br /><br />Alternatively, you can login using the GitHub version of the panel at <a href="https://phantombot.github.io/PhantomBot/">PhantomBot - GitHub.io</a> which gets around this issue.<br /><br />For help setting up SSL, please see <a href="https://phantombot.github.io/PhantomBot/guides/#guide=content/integrations/twitchembeds">this guide</a>.');
$('#twitch-chat-betting').addClass('box-body');
}
});
});

View File

@@ -0,0 +1,85 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Function that querys all of the data we need.
$(run = function() {
// Check if the module is enabled.
socket.getDBValues('commercials_module', {
tables: ['modules', 'commercialSettings', 'commercialSettings', 'commercialSettings', 'commercialSettings'],
keys: ['./systems/commercialSystem.js', 'commercialtimer', 'length', 'interval', 'message']
}, true, function(e) {
if (!helpers.handleModuleLoadUp('commercialsModule', e['./systems/commercialSystem.js'], 'commercialsModuleToggle')) {
return;
}
if (e['commercialtimer'] === 'true') {
$('#commercials-autotimer-on').html($('<i/>', {
'class': 'fa fa-check'
})).append('&nbsp; Update Autotimer');
$('#commercials-autotimer-off').removeClass('hidden');
}
$('#commercial-interval').val(e['interval']);
$('#commercial-length').val(e['length']);
$('#commercial-message').val(e['message']);
});
});
// Function that handlers the loading of events.
$(function() {
const COMMERCIAL_SCRIPT = './systems/commercialSystem.js';
// Toggle for the module.
$('#commercialsModuleToggle').on('change', function() {
// Toggle the module
socket.sendCommandSync('commercial_module_toggle_cmd',
'module ' + ($(this).is(':checked') ? 'enablesilent' : 'disablesilent') + ' ./systems/commercialSystem.js', run);
});
// Set/Update autotimer button.
$('#commercials-autotimer-on').on('click', function() {
let cinterval = $('#commercial-interval'),
clength = $('#commercial-length').find(':selected').text(),
cmessage = $('#commercial-message');
switch (false) {
case helpers.handleInputNumber(cinterval, 8):
break;
default:
socket.wsEvent('commercials_setautotimer_ws', COMMERCIAL_SCRIPT, null, ['setautotimer', cinterval.val(), clength, cmessage.val()], function() {
toastr.success('Successfully set the autotimer!');
// Update the button.
$('#commercials-autotimer-on').html($('<i/>', {
'class': 'fa fa-check'
})).append('&nbsp; Update Autotimer');
$('#commercials-autotimer-off').removeClass('hidden');
});
}
});
// Disable autotimer button.
$('#commercials-autotimer-off').on('click', function() {
socket.wsEvent('commercials_autotimeroff_ws', COMMERCIAL_SCRIPT, null, ['autotimeroff'], function() {
toastr.success('Successfully turned off autotimer!');
// Update the button.
$('#commercials-autotimer-on').html($('<i/>', {
'class': 'fa fa-check'
})).append('&nbsp; Set Autotimer');
$('#commercials-autotimer-off').addClass('hidden');
});
});
});

View File

@@ -0,0 +1,186 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Function that querys all of the data we need.
$(run = function() {
// Check if the module is enabled.
socket.getDBValue('death_counter_module', 'modules', './commands/deathctrCommand.js', function(e) {
// If the module is off, don't load any data.
if (!helpers.handleModuleLoadUp('deathCounterModule', e.modules)) {
return;
}
// Get current game.
socket.getDBValue('get_current_stream_info', 'panelData', 'stream', function(e) {
socket.getDBValue('get_death_count', 'deaths', JSON.parse(e.panelData).game, function(e) {
$('#death-number').html(helpers.parseNumber(helpers.getDefaultIfNullOrUndefined(e.deaths, '0')));
});
});
});
});
// Function that handlers the loading of events.
$(function() {
var canUpdate = true;
// Toggle for the module.
$('#deathCounterModuleToggle').on('change', function() {
let toggle = $(this).is(':checked');
canUpdate = toggle;
// Enable the module then query the data.
socket.sendCommandSync('death_counter_module_toggle_cmd',
'module ' + (toggle ? 'enablesilent' : 'disablesilent') + ' ./commands/deathctrCommand.js', run);
});
// Increase death button.
$('#incr-deaths-button').on('click', function() {
// Don't update deaths until new value is set.
canUpdate = false;
// Get current game.
socket.getDBValue('get_current_stream_info', 'panelData', 'stream', function(e) {
// Increase the deaths.
socket.incrDBValue('incr_deaths_1', 'deaths', JSON.parse(e.panelData).game, '1', function() {
// Set the new number.
$('#death-number').html(helpers.parseNumber(parseInt($('#death-number').html().replace(/,/g, '')) + 1));
// New value is set so we can let the updates work.
canUpdate = true;
});
});
});
// Increase death button.
$('#decr-deaths-button').on('click', function() {
// Don't update deaths until new value is set.
canUpdate = false;
let deaths = parseInt($('#death-number').html().replace(/,/g, ''));
// Make sure we don't go into the negatives.
if (deaths < 1) {
return;
}
// Get current game.
socket.getDBValue('get_current_stream_info', 'panelData', 'stream', function(e) {
// Decrease the deaths.
socket.decrDBValue('decr_deaths_1', 'deaths', JSON.parse(e.panelData).game, '1', function() {
// Set the new number
$('#death-number').html(helpers.parseNumber(deaths - 1));
// New value is set so we can let the updates work.
canUpdate = true;
});
});
});
// Reset button.
$('#reset-deaths-button').on('click', function() {
// Don't update deaths until new value is set.
canUpdate = false;
// Get current game.
socket.getDBValue('get_current_stream_info', 'panelData', 'stream', function(e) {
// Delete deaths.
socket.removeDBValue('rm_deaths_game', 'deaths', JSON.parse(e.panelData).game, function() {
// Set the new number.
$('#death-number').html('0');
// New value is set so we can let the updates work.
canUpdate = true;
});
});
});
// Settings button.
$('#settings-deaths-button').on('click', function() {
// Create custom modal for this module.
helpers.getModal('death-settings', 'Death Counter Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Main div for the browser source link.
.append($('<div/>', {
'class': 'form-group',
})
// Append the lable.
.append($('<label/>', {
'text': 'Browser Source Link'
}))
.append($('<div/>', {
'class': 'input-group'
})
// Add client widget URL.
.append($('<input/>', {
'type': 'text',
'class': 'form-control',
'id': 'death-url',
'readonly': 'readonly',
'value': window.location.protocol + '//' + window.location.host + '/addons/deathctr/deathctr.txt?refresh=true&webauth=' + getAuth(),
'style': 'color: transparent !important; text-shadow: 0 0 5px hsla(0, 0%, 100%, .5);',
'data-toggle': 'tooltip',
'title': 'Clicking this box will show the link. DO NOT share this link with anyone as it has sensitive information.',
'click': function() {
// Reset styles.
$(this).prop('style', '');
}
})).append($('<span/>', {
'class': 'input-group-btn',
'html': $('<button/>', {
'type': 'button',
'class': 'btn btn-primary btn-flat',
'html': 'Copy',
'click': function() {
// Select URL.
$('#death-url').select();
// Copy the URL.
document.execCommand('Copy');
}
})
}))))
// Append box with current deaths.
.append(helpers.getInputGroup('deaths-t', 'number', 'Death Total', '',
$('#death-number').html().replace(/,/g, ''), 'How many deaths to set on the counter.')),
function() { // callback.
let deaths = $('#deaths-t');
switch (false) {
case helpers.handleInputNumber(deaths, 0):
break;
default:
// Update the death number.
$('#death-number').html(helpers.parseNumber(deaths.val()));
// Get current game.
socket.getDBValue('get_current_stream_info', 'panelData', 'stream', function(e) {
// Delete deaths.
socket.updateDBValue('update_deaths_game', 'deaths', JSON.parse(e.panelData).game, deaths.val(), function() {
// Close the modal.
$('#death-settings').modal('toggle');
// Alert the user.
toastr.success('Successfully updated death counter settings!');
});
});
}
}).modal('toggle');
});
// Timer that updates deaths every 10 seconds.
helpers.setInterval(function() {
if (canUpdate) {
run();
}
}, 10e3);
});

View File

@@ -0,0 +1,126 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Function that querys all of the data we need.
$(run = function() {
// Check if the module is enabled.
socket.getDBValue('dual_stream_command_module', 'modules', './commands/dualstreamCommand.js', function(e) {
// If the module is off, don't load any data.
if (!helpers.handleModuleLoadUp('dualStreamModule', e.modules)) {
return;
}
// Get the URL.
socket.getDBValue('get_multi_link', 'dualStreamCommand', 'otherChannels', function(e) {
let channels = e.dualStreamCommand;
if (channels.indexOf('Channel-1') === -1) {
$('#multi-channels').val(channels.split(' ').join('/'));
}
$('#multi-main').html('https://multistre.am/' + getChannelName() + '/');
});
});
});
// Function that handlers the loading of events.
$(function() {
// Toggle for the module.
$('#dualStreamModuleToggle').on('change', function() {
// Enable the module then query the data.
socket.sendCommandSync('dual_stream_command_module_toggle_cmd',
'module ' + ($(this).is(':checked') ? 'enablesilent' : 'disablesilent') + ' ./commands/dualstreamCommand.js', run);
});
// Clip url update.
$('#multi-channels').on('focusout', function() {
let channels = $('#multi-channels').val();
// If the box is empty, set the default channels.
if (channels.length < 1) {
channels = 'Channel-1 Channel-2';
} else {
channels = channels.split('/').join(' ');
}
// Update the channels.
socket.updateDBValue('update_multi_channels', 'dualStreamCommand', 'otherChannels', channels, function() {
socket.sendCommand('update_multi_channels_cmd', 'reloadmulti', function() {
toastr.success('Successfully updated the multi channels!');
});
});
});
// Copy button.
$('#dualstream-copy-btn').on('click', function() {
let old = $('#multi-channels').val();
// Copy text.
$('#multi-channels').val('https://multistre.am/' + getChannelName() + '/' + old).select();
// Copy the text.
document.execCommand('Copy');
// Set back the old text.
$('#multi-channels').val(old);
});
// Settings button.
$('#dualstream-settings-button').on('click', function() {
socket.getDBValues('get_multi_settings', {
tables: ['dualStreamCommand', 'dualStreamCommand', 'dualStreamCommand'],
keys: ['timerToggle', 'timerInterval', 'reqMessages']
}, true, function(e) {
helpers.getModal('dualstream-settings', 'Dual Stream Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Append a select option for the toggle.
.append(helpers.getDropdownGroup('multi-toggle', 'Enable Multi Timer',
(e.timerToggle === 'true' ? 'Yes' : 'No'), ['Yes', 'No']))
// Timer interval.
.append(helpers.getInputGroup('multi-interval', 'text', 'Timer Interval (Minutes)',
'', e.timerInterval, 'How often to post the multi link in the channel.'))
// Req messages.
.append(helpers.getInputGroup('multi-req', 'text', 'Required Messages',
'', e.reqMessages, 'How many messages along with the timer required to trigger the multi link.')),
function() { // Callback for when the user clicks save.
let timerToggle = $('#multi-toggle').find(':selected').text() === 'Yes',
timerInterval = $('#multi-interval'),
timerReq = $('#multi-req');
switch (false) {
case helpers.handleInputNumber(timerInterval, 1):
case helpers.handleInputNumber(timerReq, 1):
break;
default:
socket.updateDBValues('update_multi_settings', {
tables: ['dualStreamCommand', 'dualStreamCommand', 'dualStreamCommand'],
keys: ['timerToggle', 'timerInterval', 'reqMessages'],
values: [timerToggle, timerInterval.val(), timerReq.val()]
}, function() {
socket.sendCommand('update_multi_settings_cmd', 'reloadmulti', function() {
// Close the modal.
$('#dualstream-settings').modal('toggle');
// Alert the user.
toastr.success('Successfully updated multi settings!');
});
});
}
}).modal('toggle');
});
});
});

View File

@@ -0,0 +1,187 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Function that querys all of the data we need.
$(run = function() {
// Check if the module is enabled.
socket.getDBValue('highlight_command_module', 'modules', './commands/highlightCommand.js', function(e) {
// If the module is off, don't load any data.
if (!helpers.handleModuleLoadUp('highlightsModule', e.modules)) {
return;
}
// Get all highlights.
socket.getDBTableValues('get_highlights', 'highlights', function(results) {
let tableData = [];
for (let i = 0; i < results.length; i++) {
let date = new Date(helpers.getEpochFromDate(results[i].key.substring(0, results[i].key.indexOf(' ')), true)),
url = results[i].value.substring(0, results[i].value.indexOf(' :')),
comment = results[i].value.substring(results[i].value.indexOf(': ') + 2, results[i].value.length);
tableData.push([
date.toLocaleDateString(),
$('<a/>', {
'text': url,
'href': url,
'target': '_blank'
})[0].outerHTML,
comment,
$('<div/>', {
'class': 'btn-group'
}).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-danger',
'style': 'float: right',
'data-key': results[i].key,
'html': $('<i/>', {
'class': 'fa fa-trash'
})
})).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-warning',
'style': 'float: right',
'data-key': results[i].key,
'html': $('<i/>', {
'class': 'fa fa-edit'
})
})).html()
]);
}
// if the table exists, destroy it.
if ($.fn.DataTable.isDataTable('#highlightsTable')) {
$('#highlightsTable').DataTable().destroy();
// Remove all of the old events.
$('#highlightsTable').off();
}
// Create table.
let table = $('#highlightsTable').DataTable({
'searching': true,
'autoWidth': false,
'lengthChange': false,
'data': tableData,
'columnDefs': [
{ 'className': 'default-table', 'orderable': false, 'targets': 3 },
{ 'width': '7%', 'targets': 0 },
{ 'width': '25%', 'targets': 1 }
],
'columns': [
{ 'title': 'Date' },
{ 'title': 'URL' },
{ 'title': 'Comment' },
{ 'title': 'Actions' }
]
});
// On delete button.
table.on('click', '.btn-danger', function() {
let key = $(this).data('key'),
row = $(this).parents('tr');
// Ask the user if he wants to delete the highlight.
helpers.getConfirmDeleteModal('highlight_modal_remove', 'Are you sure you want to remove this highlight?', true,
'The highlight has been successfully removed!', function() { // Callback if the user clicks delete.
// Remove the highlight.
socket.removeDBValue('highlight_remove', 'highlights', key, function() {
// Remove the table row.
table.row(row).remove().draw(false);
});
});
});
// On edit button.
table.on('click', '.btn-warning', function() {
let key = $(this).data('key'),
t = $(this);
socket.getDBValue('get_highlight_edit', 'highlights', key, function(e) {
let spl = e.highlights.replace(/\s/, '').split(': ');
helpers.getModal('edit-highlight', 'Edit Highlight', 'Save', $('<form/>', {
'role': 'form'
})
// Append highlight text box.
.append(helpers.getTextAreaGroup('highlight-text', 'text', 'Highlight', '', spl[1],
'Comment to give to the current highlight.', false)),
function() {
let highlight = $('#highlight-text');
switch (false) {
case helpers.handleInputString(highlight):
break;
default:
spl[1] = highlight.val();
socket.updateDBValue('update_highlight', 'highlights', key, spl.join(' : '), function() {
// Update the table.
t.parents('tr').find('td:eq(2)').text(spl[1]);
// Close the modal.
$('#edit-highlight').modal('toggle');
// Alert the user.
toastr.success('Successfully edited the highlight.');
});
}
}).modal('toggle');
});
});
});
});
});
// Function that handlers the loading of events.
$(function() {
// Toggle for the module.
$('#highlightsModuleToggle').on('change', function() {
// Enable the module then query the data.
socket.sendCommandSync('highlight_module_toggle_cmd',
'module ' + ($(this).is(':checked') ? 'enablesilent' : 'disablesilent') + ' ./commands/highlightCommand.js', run);
});
// Delete all highlights button.
$('#delete-highlights-button').on('click', function() {
// Ask the user if he want to remove all highlights.
helpers.getConfirmDeleteModal('highlights_modal_remove', 'Are you sure you want to remove all highlights?', false,
'Successfully remove all highlights!', function() {
socket.sendCommandSync('rm_all_highlights_cmd', 'clearhighlightspanel', run);
});
});
// Add highlight.
$('#add-highlight-button').on('click', function() {
helpers.getModal('add-highlight', 'Add Highlight', 'Save', $('<form/>', {
'role': 'form'
})
// Append highlight text box.
.append(helpers.getTextAreaGroup('highlight-text', 'text', 'Highlight', 'PogChamp moment.', '',
'Comment to give to the current highlight. This only works while the stream is online.', false)),
function() { // Callback for when the user clicks save.
let highlight = $('#highlight-text');
switch (false) {
case helpers.handleInputString(highlight):
break;
default:
socket.sendCommandSync('add_highlight_cmd', 'highlight ' + highlight.val(), function() {
toastr.success('Successfully created a new highlight!');
});
$('#add-highlight').modal('toggle');
}
}).modal('toggle');
});
});

View File

@@ -0,0 +1,241 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Function that querys all of the data we need.
$(function () {
// Chart configs. This should not be changed.
let chartConfig = {"type": "pie", "data": {"datasets": [{"data": [], "backgroundColor": []}], "labels": []}, "options": {"responsive": false, "title": {"display": true}}},
chartContext = $('#poll-chart').get(0).getContext('2d'),
chart = new Chart(chartContext, chartConfig),
isActive = false;
/*
* @function Inits the chart.
*/
const initChart = function () {
socket.getDBValues('get_poll_options', {
tables: ['pollPanel', 'pollPanel'],
keys: ['options', 'title']
}, true, function (e) {
if (e.options !== null) {
socket.getDBTableValues('get_poll_votes', 'pollVotes', function (votes) {
// Set the chart title.
chartConfig.options.title.text = e.title;
// Set the labels.
chartConfig.data.labels = e.options.split(',');
// Get all the data.
let ops = e.options.split(',');
for (let i = 0; i < ops.length; i++) {
for (let j = 0; j < votes.length; j++) {
if (votes[j].key === ops[i]) {
chartConfig.data.datasets[0].data.push(parseInt(votes[j].value));
chartConfig.data.datasets[0].backgroundColor.push(helpers.getRandomRgbColor());
}
}
}
// Update the chart.
chart.update();
// Mark as active.
isActive = true;
});
}
});
};
// Init the chart here.
initChart();
/*
* @function Updates the chart during a poll.
*/
const updateChart = function () {
socket.getDBValue('get_poll_active_update', 'pollPanel', 'isActive', function (e) {
if (e.pollPanel === 'false' || e.pollPanel === null) {
isActive = false;
return;
} else if (chartConfig.data.datasets[0].backgroundColor.length !== 0 && isActive === false) {
resetChart();
}
// No current chart is done, start a new one.
if (chartConfig.data.datasets[0].backgroundColor.length === 0) {
initChart();
return;
}
socket.getDBValue('get_poll_options_update', 'pollPanel', 'options', function (e) {
socket.getDBTableValues('get_poll_votes_update', 'pollVotes', function (votes) {
// Get all the data.
let ops = e.pollPanel.split(',');
// Remove current data.
chartConfig.data.datasets[0].data = [];
for (let i = 0; i < ops.length; i++) {
for (let j = 0; j < votes.length; j++) {
if (votes[j].key === ops[i]) {
chartConfig.data.datasets[0].data.push(parseInt(votes[j].value));
}
}
}
// Update the chart.
chart.update();
});
});
});
};
/*
* @function Resets the poll.
*
* @param {Function} callback
*/
const resetPoll = function (callback) {
socket.removeDBValues('reset_poll_options', {
tables: ['pollPanel', 'pollPanel'],
keys: ['options', 'isActive']
}, function () {
// Reset the chart.
resetChart();
// Update the chart.
chart.update();
// Alert the user.
toastr.success('Successfully reset the poll.');
// Callback if possible.
if (typeof callback === 'function') {
callback();
}
});
};
/*
* @function Resets the chart.
*/
const resetChart = function () {
// Mark as not acive.
isActive = false;
// Reset the title.
chartConfig.options.title.text = '';
// Reset lables.
chartConfig.data.labels = [];
// Reset the data.
chartConfig.data.datasets[0].data = [];
// Reset the colors.
chartConfig.data.datasets[0].backgroundColor = [];
};
// Reset poll button.
$('#reset-poll').on('click', function () {
resetPoll();
if (isActive) {
socket.sendCommand('reset_end_poll_cmd', 'poll close', new Function());
isActive = false;
}
});
// Close poll button.
$('#close-poll').on('click', function () {
socket.sendCommand('end_poll_cmd', 'poll close', function () {
// Mark as not acive.
isActive = false;
// Alert the user.
toastr.success('Successfully ended the poll.');
});
});
// Open poll button.
$('#open-poll').on('click', function () {
helpers.getModal('poll-open', 'Open Poll', 'Open', $('<form/>', {
'role': 'form'
})
// Append poll title.
.append(helpers.getTextAreaGroup('poll-title', 'text', 'Title', 'What is your favorite color?', '', 'Title of the poll.'))
// Append options.
.append(helpers.getInputGroup('poll-options', 'text', 'Options', 'Red, Green, Blue', '',
'Options to be voted on. Each option should be seperated with a comma and space.'))
// Append timer.
.append(helpers.getInputGroup('poll-timer', 'number', 'Timer (Seconds)', '', '0',
'How long in seconds the poll will be opened for. Default is until closed.'))
// Append min votes.
.append(helpers.getInputGroup('poll-votes', 'number', 'Minimum Votes', '', '1',
'How many votes it takes to choose a winning option. Default is one.')),
function () { // callback function.
let title = $('#poll-title'),
options = $('#poll-options'),
timer = $('#poll-timer'),
votes = $('#poll-votes');
switch (false) {
case helpers.handleInputString(title):
case helpers.handleInputString(options):
case helpers.handleInputNumber(timer, 0):
case helpers.handleInputNumber(votes, 1):
break;
default:
// Reset the chart.
resetChart();
// Open the poll.
socket.sendCommand('open_poll_cmd',
'poll open "' + title.val() + '" "' + options.val() + '" ' + timer.val() + ' ' + votes.val(), function () {
// Close the modal.
$('#poll-open').modal('toggle');
// Alert the user.
toastr.success('Successfully opened the poll!');
});
}
}).modal('toggle');
});
// Module toggle.
$('#pollSystemModuleToggle').on('change', function () {
socket.sendCommandSync('poll_system_module_toggle_cmd',
'module ' + ($(this).is(':checked') ? 'enablesilent' : 'disablesilent') + ' ./systems/pollSystem.js', run);
});
// Update the chart every 5 seconds.
helpers.setInterval(updateChart, 5e3);
});
// Handles the module toggle.
$(run = function () {
socket.getDBValue('poll_module_status', 'modules', './systems/pollSystem.js', function (e) {
if (!helpers.handleModuleLoadUp('pollSystemModule', e.modules)) {
// Remove the chat.
$('#twitch-chat-poll').find('iframe').remove();
return;
}
if (location.protocol.toLowerCase().startsWith('https') && !(location.port > 0 && location.port !== 443)) {
// Add Twitch chat.
$('#twitch-chat-poll').html($('<iframe/>', {
'frameborder': '0',
'scrolling': 'no',
'style': 'width: 100%; height: 561px; margin-bottom: -5px;',
'src': 'https://www.twitch.tv/embed/' + getChannelName() + '/chat' + (helpers.isDark ? '?darkpopout&' : '?') + 'parent=' + location.hostname
}));
} else {
$('#twitch-chat-poll').html('Due to changes by Twitch, the chat panel can no longer be displayed unless you enable SSL on the PhantomBot Panel and change the baseport to 443. This may not work without root privileges.<br /><br />Alternatively, you can login using the GitHub version of the panel at <a href="https://phantombot.github.io/PhantomBot/">PhantomBot - GitHub.io</a> which gets around this issue.<br /><br />For help setting up SSL, please see <a href="https://phantombot.github.io/PhantomBot/guides/#guide=content/integrations/twitchembeds">this guide</a>.');
$('#twitch-chat-poll').addClass('box-body');
}
});
});

View File

@@ -0,0 +1,229 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Function that querys all of the data we need.
$(run = function () {
// Check if the module is enabled.
socket.getDBValues('queue_module', {
tables: ['modules', 'queueSettings'],
keys: ['./systems/queueSystem.js', 'isActive']
}, true, function (e) {
// If the module is off, don't load any data.
if (!helpers.handleModuleLoadUp(['queueModule', 'queueListModule'], e['./systems/queueSystem.js'], 'queueModuleToggle')) {
// Remove the chat.
$('#queue-chat').find('iframe').remove();
return;
} else {
if (location.protocol.toLowerCase().startsWith('https') && !(location.port > 0 && location.port !== 443)) {
// Add Twitch chat.
$('#queue-chat').html($('<iframe/>', {
'frameborder': '0',
'scrolling': 'no',
'style': 'width: 100%; height: 532px;',
'src': 'https://www.twitch.tv/embed/' + getChannelName() + '/chat' + (helpers.isDark ? '?darkpopout&' : '?') + 'parent=' + location.hostname
}));
} else {
$('#queue-chat').html('Due to changes by Twitch, the chat panel can no longer be displayed unless you enable SSL on the PhantomBot Panel and change the baseport to 443. This may not work without root privileges.<br /><br />Alternatively, you can login using the GitHub version of the panel at <a href="https://phantombot.github.io/PhantomBot/">PhantomBot - GitHub.io</a> which gets around this issue.<br /><br />For help setting up SSL, please see <a href="https://phantombot.github.io/PhantomBot/guides/#guide=content/integrations/twitchembeds">this guide</a>.');
$('#queue-chat').addClass('box-body');
}
}
// Update the open button to close if the queue is active.
if (e['isActive'] === 'true') {
$('#open-or-close-queue').html($('<i/>', {
'class': 'fa fa-lock'
})).append('&nbsp; Close').removeClass('btn-success').addClass('btn-warning');
}
// Function that updates the queue list.
helpers.temp.updateQueueList = function () {
// Get queue list.
socket.getDBTableValues('get_queue_list', 'queue', function (results) {
const table = $('#queue-table');
const trim = function (username) {
if (username.length > 15) {
return username.substr(0, 15) + '...';
} else {
return username;
}
};
// Sort.
results.sort(function (a, b) {
return parseInt(JSON.parse(a.value).position) - parseInt(JSON.parse(b.value).position);
});
// Remove current data content.
table.find('tr:gt(0)').remove();
for (let i = 0; i < results.length; i++) {
const json = JSON.parse(results[i].value),
tr = $('<tr/>');
// Add position.
tr.append($('<td/>', {
'html': json.position
}));
// Add name.
tr.append($('<td/>', {
'html': trim(json.username),
'data-toggle': 'tooltip',
'title': json.username
}));
// Add gamer tag.
tr.append($('<td/>', {
'html': (json.tag.length === 0 ? 'None' : trim(json.tag)),
'data-toggle': 'tooltip',
'title': (json.tag.length === 0 ? 'None' : json.tag)
}));
// Add the del button.
tr.append($('<td/>', {
'html': $('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-danger',
'style': 'float: right',
'html': $('<i/>', {
'class': 'fa fa-trash'
}),
'click': function () {
socket.wsEvent('rm_queue_user', './systems/queueSystem.js', null,
['remove', results[i].key], helpers.temp.updateQueueList);
}
})
}));
// Add to the table.
table.append(tr);
}
});
};
helpers.temp.updateQueueList();
});
});
// Function that handlers the loading of events.
$(function () {
const QUEUE_SCRIPT = './systems/queueSystem.js';
let canUpdate = true;
/*
* @function Clears the input boxes of the queue.
*/
const clearQueueInput = function () {
$('#queue-title').val('');
$('#queue-cost, #queue-size').val('0');
$('#queue-permission').val('Viewers');
};
// Toggle for the module.
$('#queueModuleToggle').on('change', function () {
// Enable the module then query the data.
socket.sendCommandSync('queue_module_toggle_cmd',
'module ' + ($(this).is(':checked') ? 'enablesilent' : 'disablesilent') + ' ./systems/queueSystem.js', run);
});
// Queue open/close button.
$('#open-or-close-queue').on('click', function () {
if ($(this)[0].innerText.trim() === 'Open') {
let title = $('#queue-title'),
cost = $('#queue-cost'),
size = $('#queue-size'),
permission = $('#queue-permission').find(':selected').text();
switch (false) {
case helpers.handleInputString(title):
case helpers.handleInputNumber(cost, 0):
case helpers.handleInputNumber(size, 0):
break;
default:
socket.sendCommand('queue_permisison_update', 'permcomsilent joinqueue ' + helpers.getGroupIdByName(permission, true), function () {
socket.updateDBValue('queue_command_cost', 'pricecom', 'joinqueue', cost.val(), function () {
socket.wsEvent('queue_open_ws', QUEUE_SCRIPT, null, ['open', size.val(), title.val()], function () {
toastr.success('Successfully opened the queue!');
// Update the button.
$('#open-or-close-queue').html($('<i/>', {
'class': 'fa fa-lock'
})).append('&nbsp; Close').removeClass('btn-success').addClass('btn-warning');
});
});
});
}
} else {
socket.wsEvent('close_queue_ws', QUEUE_SCRIPT, null, ['close'], function () {
toastr.success('Successfully closed the queue!');
clearQueueInput();
// Update the button.
$('#open-or-close-queue').html($('<i/>', {
'class': 'fa fa-unlock-alt'
})).append('&nbsp; Open').removeClass('btn-warning').addClass('btn-success');
});
}
});
// Clear queue command.
$('#reset-queue').on('click', function () {
socket.wsEvent('clear_queue_ws', QUEUE_SCRIPT, null, ['clear'], function () {
toastr.success('Successfully cleared the queue!');
clearQueueInput();
helpers.temp.updateQueueList();
});
});
// Draw users command.
$('#draw-queue').on('click', function () {
helpers.getModal('queue-draw-users', 'Draw Users', 'Draw', $('<form/>', {
'role': 'form'
})
// Append amount to draw
.append(helpers.getInputGroup('draw-amount', 'number', 'Number of Users to Pick', '', '1', 'The amount of users to be drawn from the queue.')),
// Callback.
function () {
let amount = $('#draw-amount');
switch (false) {
case helpers.handleInputNumber(amount, 1, 5):
break;
default:
socket.wsEvent('draw_queue_users', QUEUE_SCRIPT, null, ['pick', amount.val()], function () {
// Alert the user.
toastr.success('Drew ' + amount.val() + ' users from the queue!');
// Update the list.
helpers.temp.updateQueueList();
// Close the modal.
$('#queue-draw-users').modal('toggle');
});
}
}).modal('toggle');
});
// Handle mouse over on queue list.
$('#queueTable').on('mouseenter mouseleave', function (event) {
canUpdate = event.type === 'mouseleave';
});
// Update every 5 seconds.
helpers.setInterval(function () {
if (canUpdate) {
helpers.temp.updateQueueList();
}
}, 5e3);
});

View File

@@ -0,0 +1,391 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Function that querys all of the data we need.
$(function() {
// Get all module toggles.
socket.getDBValues('games_get_modules', {
tables: ['modules', 'modules', 'modules', 'modules', 'modules', 'modules', 'modules', 'modules'],
keys: ['./games/adventureSystem.js', './games/gambling.js', './games/killCommand.js', './games/random.js', './games/roll.js',
'./games/roulette.js', './games/slotMachine.js', './games/8ball.js']
}, true, function(results) {
// Handle the settings button.
let keys = Object.keys(results),
module = '',
i;
for (i = 0; i < keys.length; i++) {
// Handle the status of the buttons.
if (results[keys[i]] === 'false') {
module = keys[i].substring(keys[i].lastIndexOf('/') + 1).replace('.js', '');
// Handle the switch.
$('#' + module + 'Toggle').prop('checked', false);
// Handle the settings button.
$('#' + module + 'Settings').prop('disabled', true);
}
}
});
});
// Function that handlers the loading of events.
$(function() {
// Module toggle for games.
$('[data-game-toggle]').on('change', function() {
let name = $(this).attr('id'),
checked = $(this).is(':checked');
// Handle the module.
socket.sendCommandSync('game_module_toggle', 'module ' + (checked ? 'enablesilent' : 'disablesilent') + ' ' + $(this).data('game-toggle'), function() {
// Toggle the settings button.
$('#' + name.replace('Toggle', 'Settings')).prop('disabled', !checked);
// Alert the user.
toastr.success('Successfully ' + (checked ? 'enabled' : 'disabled') + ' the game module!');
});
});
// Adventure settings.
$('#adventureSystemSettings').on('click', function() {
socket.getDBValues('get_adventure_settings', {
tables: ['adventureSettings', 'adventureSettings', 'adventureSettings', 'adventureSettings', 'adventureSettings', 'adventureSettings',
'adventureSettings', 'adventureSettings'],
keys: ['joinTime', 'coolDown', 'gainPercent', 'minBet', 'maxBet', 'enterMessage', 'warningMessage', 'coolDownAnnounce']
}, true, function(e) {
helpers.getModal('adventure-settings', 'Adventure Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Add the toggle the entry messages.
.append(helpers.getDropdownGroup('entry-messages', 'Enable Adventure Entry Messages', (e.enterMessage === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If a message should be said when a user joins the adventure.'))
// Add the toggle the entry messages.
.append(helpers.getDropdownGroup('user-messages', 'Enable Adventure Warning Messages', (e.warningMessage === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If a message when a user already entered should be displayed in chat.'))
// Add the toggle the cooldown message.
.append(helpers.getDropdownGroup('cooldown-message', 'Enable Adventure Off Cooldown Message', (e.coolDownAnnounce === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If a message should be said when the adventure is no longer on cooldown.'))
// Add the the box for the join time.
.append(helpers.getInputGroup('join-time', 'number', 'Adventure Join Time (Seconds)', '', e.joinTime, 'How long in seconds users have to join the adventure.'))
// Add the the box for the cooldown.
.append(helpers.getInputGroup('cooldown-time', 'number', 'Adventure Cooldown (Seconds)', '', e.coolDown,
'How long users have to wait in seconds before starting a new adventure after one is over.'))
// Add the the box for gain.
.append(helpers.getInputGroup('gain', 'number', 'Adventure Gain Percent', '', e.gainPercent,
'How many points a user will get based on the amount they joined with. The join amount is always given back.'))
// Add the the box for min bet.
.append(helpers.getInputGroup('min-bet', 'number', 'Adventure Minimum Bet', '', e.minBet, 'The minimum amount of points a user can join an adventure with.'))
// Add the the box for max bet.
.append(helpers.getInputGroup('max-bet', 'number', 'Adventure Maximum Bet', '', e.maxBet, 'The maximum amount of points a user can join an adventure with.')),
function() { // Callback once the user clicks save.
let entryMessages = $('#entry-messages').find(':selected').text() === 'Yes',
userMessages = $('#user-messages').find(':selected').text() === 'Yes',
cooldownMessage = $('#cooldown-message').find(':selected').text() === 'Yes',
joinTime = $('#join-time'),
cooldownTime = $('#cooldown-time'),
gainPercent = $('#gain'),
minBet = $('#min-bet'),
maxBet = $('#max-bet');
// Make sure everything has been filled in.
switch (false) {
case helpers.handleInputNumber(joinTime, 30):
case helpers.handleInputNumber(cooldownTime, 10):
case helpers.handleInputNumber(gainPercent, 1):
case helpers.handleInputNumber(minBet, 1):
case helpers.handleInputNumber(maxBet, 1):
break;
default:
socket.updateDBValues('adventure_update_settings', {
tables: ['adventureSettings', 'adventureSettings', 'adventureSettings', 'adventureSettings', 'adventureSettings', 'adventureSettings',
'adventureSettings', 'adventureSettings'],
keys: ['joinTime', 'coolDown', 'gainPercent', 'minBet', 'maxBet', 'enterMessage', 'warningMessage', 'coolDownAnnounce'],
values: [joinTime.val(), cooldownTime.val(), gainPercent.val(), minBet.val(), maxBet.val(), entryMessages, userMessages, cooldownMessage]
}, function() {
socket.sendCommand('adventure_update_settings_cmd', 'reloadadventure', function() {
// Close the modal.
$('#adventure-settings').modal('toggle');
// Alert the user.
toastr.success('Successfully updated the adventure settings!');
});
});
}
}).modal('toggle');
});
});
// Roulette settings.
$('#rouletteSettings').on('click', function() {
socket.getDBValue('get_roulette_settings', 'roulette', 'timeoutTime', function(e) {
helpers.getModal('roulette-settings', 'Roulette Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Add the box timeout time
.append(helpers.getInputGroup('timeout-time', 'number', 'Roulette Timeout Time (Seconds)', '', e.roulette, 'How long in seconds a user gets timed-out when losing.')),
function() { // Callback once the user clicks save.
let timeoutTime = $('#timeout-time');
switch (false) {
case helpers.handleInputNumber(timeoutTime, 1):
break;
default:
socket.updateDBValue('update_roulette_settings', 'roulette', 'timeoutTime', timeoutTime.val(), function() {
socket.sendCommand('update_roulette_settings_cmd', 'reloadroulette', function() {
// Close the modal.
$('#roulette-settings').modal('toggle');
// Alert the user.
toastr.success('Successfully updated the roulette settings!');
});
});
}
}).modal('toggle');
});
});
// Slot machine settings.
$('#slotMachineSettings').on('click', function() {
socket.getDBValues('get_slot_machine_settings', {
tables: ['slotmachine', 'slotmachine', 'slotmachine', 'slotmachine', 'slotmachine', 'slotmachineemotes', 'slotmachineemotes', 'slotmachineemotes',
'slotmachineemotes', 'slotmachineemotes'],
keys: ['prizes_0', 'prizes_1', 'prizes_2', 'prizes_3', 'prizes_4', 'emote_0', 'emote_1', 'emote_2', 'emote_3', 'emote_4']
}, true, function(e) {
helpers.getModal('slotmachine-game', 'Slot Machine Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Add the div for the col boxes.
.append($('<div/>', {
'class': 'panel-group',
'id': 'accordion'
})
// Append first collapsible accordion.
.append(helpers.getCollapsibleAccordion('main-1', 'Reward Settings', $('<form/>', {
'role': 'form'
})
// Add the reward 1 slot.
.append(helpers.getInputGroup('reward-1', 'number', 'Slot Reward One', '', e.prizes_0, 'Reward for the first slot.'))
// Add the reward 2 slot.
.append(helpers.getInputGroup('reward-2', 'number', 'Slot Reward Two', '', e.prizes_1, 'Reward for the second slot.'))
// Add the reward 3 slot.
.append(helpers.getInputGroup('reward-3', 'number', 'Slot Reward Three', '', e.prizes_2, 'Reward for the third slot.'))
// Add the reward 4 slot.
.append(helpers.getInputGroup('reward-4', 'number', 'Slot Reward Four', '', e.prizes_3, 'Reward for the forth slot.'))
// Add the reward 5 slot.
.append(helpers.getInputGroup('reward-5', 'number', 'Slot Reward Five', '', e.prizes_4, 'Reward for the fifth slot.'))))
// Append second collapsible accordion.
.append(helpers.getCollapsibleAccordion('main-2', 'Emote Settings', $('<form/>', {
'role': 'form'
})
// Add the emote 1 slot.
.append(helpers.getInputGroup('emote-1', 'text', 'Slot Emote One', '', e.emote_0, 'Emote for the first slot.'))
// Add the emote 2 slot.
.append(helpers.getInputGroup('emote-2', 'text', 'Slot Emote Two', '', e.emote_1, 'Emote for the second slot.'))
// Add the emote 3 slot.
.append(helpers.getInputGroup('emote-3', 'text', 'Slot Emote Three', '', e.emote_2, 'Emote for the third slot.'))
// Add the emote 4 slot.
.append(helpers.getInputGroup('emote-4', 'text', 'Slot Emote Four', '', e.emote_3, 'Emote for the forth slot.'))
// Add the emote 5 slot.
.append(helpers.getInputGroup('emote-5', 'text', 'Slot Emote Five', '', e.emote_4, 'Emote for the fifth slot.'))))),
function() { // Callback for when the user clicks save.
let values = [];
// Get all prices.
for (let i = 1; i <= 5; i++) {
let valObj = $('#reward-' + i);
if (!helpers.handleInputNumber(valObj, 0)) {
return;
}
values.push(valObj.val());
}
// Get all emotes.
for (let i = 1; i <= 5; i++) {
let valObj = $('#emote-' + i);
if (!helpers.handleInputString(valObj)) {
return;
}
values.push(valObj.val());
}
// Update settings.
socket.updateDBValues('update_slot_settings', {
tables: ['slotmachine', 'slotmachine', 'slotmachine', 'slotmachine', 'slotmachine', 'slotmachineemotes', 'slotmachineemotes',
'slotmachineemotes', 'slotmachineemotes', 'slotmachineemotes'],
keys: ['prizes_0', 'prizes_1', 'prizes_2', 'prizes_3', 'prizes_4', 'emote_0', 'emote_1', 'emote_2', 'emote_3', 'emote_4'],
values: values
}, function() {
// Close the modal.
$('#slotmachine-game').modal('toggle');
// Alert the user.
toastr.success('Successfully updated the slot machine settings!');
});
}).modal('toggle');
});
});
// Role settings.
$('#rollSettings').on('click', function() {
socket.getDBValues('get_roll_settings', {
tables: ['rollprizes', 'rollprizes', 'rollprizes', 'rollprizes', 'rollprizes', 'rollprizes'],
keys: ['prizes_0', 'prizes_1', 'prizes_2', 'prizes_3', 'prizes_4', 'prizes_5']
}, true, function(e) {
helpers.getModal('roll-settings', 'Dice Roll Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Add the reward 1.
.append(helpers.getInputGroup('reward-1', 'number', 'Double 1s Reward', '', e.prizes_0, 'Reward for rolling double 1s.'))
// Add the reward 2.
.append(helpers.getInputGroup('reward-2', 'number', 'Double 2s Reward', '', e.prizes_1, 'Reward for rolling double 2s.'))
// Add the reward 3.
.append(helpers.getInputGroup('reward-3', 'number', 'Double 3s Reward', '', e.prizes_2, 'Reward for rolling double 3s.'))
// Add the reward 4.
.append(helpers.getInputGroup('reward-4', 'number', 'Double 4s Reward', '', e.prizes_3, 'Reward for rolling double 4s.'))
// Add the reward 5.
.append(helpers.getInputGroup('reward-5', 'number', 'Double 5s Reward', '', e.prizes_4, 'Reward for rolling double 5s.'))
// Add the reward 6.
.append(helpers.getInputGroup('reward-6', 'number', 'Double 6s Reward', '', e.prizes_5, 'Reward for rolling double 6s.')),
function() { // Callback for when the user clicks save.
let values = [];
// Get all rewards
for (let i = 1; i <= 6; i++) {
let valObj = $('#reward-' + i);
if (!helpers.handleInputNumber(valObj, 0)) {
return;
}
values.push(valObj.val());
}
// Update the rewards.
socket.updateDBValues('roll_update_settings', {
tables: ['rollprizes', 'rollprizes', 'rollprizes', 'rollprizes', 'rollprizes', 'rollprizes'],
keys: ['prizes_0', 'prizes_1', 'prizes_2', 'prizes_3', 'prizes_4', 'prizes_5'],
values: values
}, function() {
// Close the modal.
$('#roll-settings').modal('toggle');
// Alert the user.
toastr.success('Successfully updated the dice roll settings!');
});
}).modal('toggle');
});
});
// Gambling settings.
$('#gamblingSettings').on('click', function() {
socket.getDBValues('get_gambling_settings', {
tables: ['gambling', 'gambling', 'gambling', 'gambling'],
keys: ['winGainPercent', 'winRange', 'max', 'min']
}, true, function(e) {
helpers.getModal('gambling-settings', 'Gambling Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Add the gambling gain percent.
.append(helpers.getInputGroup('gambling-gain', 'number', 'Gambling Gain Percent', '', e.winGainPercent,
'How many points are given based on what the user gambled. The gambled amount is always given back.'))
// Add the gambling win range.
.append(helpers.getInputGroup('gambling-range', 'number', 'Gambling Winning Range', '', e.winRange,
'The winning range of the gambling game. Anything gambled below this number will be a lost. Maximum is 100.'))
// Add the gambling max.
.append(helpers.getInputGroup('gambling-max', 'number', 'Gambling Maximum Amount', '', e.max,
'The maximum amount of points that can be gambled at once.'))
// Add the gambling min.
.append(helpers.getInputGroup('gambling-min', 'number', 'Gambling Minimum Amount', '', e.min,
'The minimum amount of points that can be gambled at once.')),
function() { // Callback once the user clicks save.
let winGain = $('#gambling-gain'),
winRange = $('#gambling-range'),
max = $('#gambling-max'),
min = $('#gambling-min');
switch (false) {
case helpers.handleInputNumber(winGain, 1, 100):
case helpers.handleInputNumber(winRange, 1, 100):
case helpers.handleInputNumber(max, 1):
case helpers.handleInputNumber(min, 1):
break;
default:
socket.updateDBValues('update_gambling_settings', {
tables: ['gambling', 'gambling', 'gambling', 'gambling'],
keys: ['winGainPercent', 'winRange', 'max', 'min'],
values: [winGain.val(), winRange.val(), max.val(), min.val()]
}, function() {
socket.sendCommand('update_gambling_settings_cmd', 'reloadgamble', function() {
// Close the modal.
$('#gambling-settings').modal('toggle');
// Alert the user.
toastr.success('Successfully updated gambling settings!');
});
});
}
}).modal('toggle');
});
});
// Kill settings.
$('#killCommandSettings').on('click', function() {
socket.getDBValue('get_kill_settings', 'settings', 'killTimeoutTime', function(e) {
helpers.getModal('killcmd-settings', 'Kill Command Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Add the kill timeout.
.append(helpers.getInputGroup('kill-timeout', 'number', 'Kill Timeout Time (Seconds)', '', e.settings,
'How long the user will get timed-out if they get cought by the cops.')),
function() { // Callback once the user clicks save.
let killTimeout = $('#kill-timeout');
switch (false) {
case helpers.handleInputNumber(killTimeout, 1):
break;
default:
socket.updateDBValue('update_kill_settings', 'settings', 'killTimeoutTime', killTimeout.val(), function() {
socket.sendCommand('update_kill_settings_cmd', 'reloadkill', function() {
// Close the modal.
$('#killcmd-settings').modal('toggle');
// Alert the user.
toastr.success('Successfully updated the kill command settings!');
});
});
}
}).modal('toggle');
});
});
// Random command settings.
$('#randomSettings').on('click', function() {
socket.getDBValue('get_random_settings', 'randomSettings', 'pg13toggle', function(e) {
helpers.getModal('random-settings', 'Random Command Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Add the toggle the entry messages.
.append(helpers.getDropdownGroup('pg-mode', 'Enable PG13 Mode', (e.randomSettings === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If the random command should have PG13 phrases.')),
function() { // Callback once the user clicks save.
let toggle = $('#pg-mode').find(':selected').text() === 'Yes';
socket.updateDBValue('update_random_settings', 'randomSettings', 'pg13toggle', toggle, function() {
socket.wsEvent('update_random_settings_ws', './games/random.js', null, [], function() {
// Close the modal.
$('#random-settings').modal('toggle');
// Alert the user.
toastr.success('Successfully updated the random command settings!');
});
});
}).modal('toggle');
});
});
});

View File

@@ -0,0 +1,135 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Function that querys all of the data we need.
$(run = function () {
socket.getDBValues('auction_module_status_toggle', {
tables: ['modules', 'auctionSettings'],
keys: ['./systems/auctionSystem.js', 'isActive']
}, true, function (e) {
if (!helpers.handleModuleLoadUp(['auctionOptions'], e['./systems/auctionSystem.js'], 'auctionSystemModuleToggle')) {
// Remove the chat.
$('#twitch-chat-auction').find('iframe').remove();
return;
}
// Update the open button to close if the raffle is active.
if (e['isActive'] === 'true') {
$('#open-or-close-auction').html($('<i/>', {
'class': 'fa fa-lock'
})).append('&nbsp; Close').removeClass('btn-success').addClass('btn-warning');
}
if (location.protocol.toLowerCase().startsWith('https') && !(location.port > 0 && location.port !== 443)) {
// Add Twitch chat.
$('#twitch-chat-auction').html($('<iframe/>', {
'frameborder': '0',
'scrolling': 'no',
'style': 'min-width: 100%; min-height: 493px;',
'src': 'https://www.twitch.tv/embed/' + getChannelName() + '/chat' + (helpers.isDark ? '?darkpopout&' : '?') + 'parent=' + location.hostname
}));
} else {
$('#twitch-chat-auction').html('Due to changes by Twitch, the chat panel can no longer be displayed unless you enable SSL on the PhantomBot Panel and change the baseport to 443. This may not work without root privileges.<br /><br />Alternatively, you can login using the GitHub version of the panel at <a href="https://phantombot.github.io/PhantomBot/">PhantomBot - GitHub.io</a> which gets around this issue.<br /><br />For help setting up SSL, please see <a href="https://phantombot.github.io/PhantomBot/guides/#guide=content/integrations/twitchembeds">this guide</a>.');
$('#twitch-chat-auction').addClass('box-body');
}
// Add temp function.
helpers.temp.updateStats = function () {
socket.getDBValues('auction_module_status_toggle', {
tables: ['auctionresults', 'auctionresults'],
keys: ['winner', 'amount']
}, true, function (e) {
if (e['winner'] != null) {
$('#auction-top-bidder').html(e['winner']);
$('#auction-points').html(e['amount']);
}
});
};
// Set a timer to auto load the raffle list.
helpers.setInterval(function () {
helpers.temp.updateStats();
}, 3e3);
});
});
// Function that handlers the loading of events.
$(function () {
// Module toggle.
$('#auctionSystemModuleToggle').on('change', function () {
socket.sendCommandSync('auction_system_module_toggle_cmd',
'module ' + ($(this).is(':checked') ? 'enablesilent' : 'disablesilent') + ' ./systems/auctionSystem.js', run);
});
// Open/Close button.
$('#open-or-close-auction').on('click', function () {
if ($(this)[0].innerText.trim() === 'Open') {
const commandLevel = $('#auction-perm').find(':selected').text(),
minBet = $('#auction-bet'),
incre = $('#auction-inc'),
timer = $('#auction-timer');
// Make sure the user entered everything right.
switch (false) {
case helpers.handleInputNumber(minBet, 1):
case helpers.handleInputNumber(incre, 1):
case helpers.handleInputNumber(timer, 0):
break;
default:
socket.sendCommandSync('auction_command_permisison_update', 'permcomsilent bid ' + helpers.getGroupIdByName(commandLevel, true), function () {
socket.sendCommand('auction_open_cmd', 'auction open ' + incre.val() + ' ' + minBet.val() + ' ' + timer.val(), function () {
// Alert the user.
toastr.success('Successfully opened the auction!');
// Update the button.
$('#open-or-close-auction').html($('<i/>', {
'class': 'fa fa-lock'
})).append('&nbsp; Close').removeClass('btn-success').addClass('btn-warning');
});
});
}
} else {
socket.sendCommandSync('close_auction_cmd', 'auction close', function () {
// Alert the user.
toastr.success('Successfully closed the auction!');
// Reload to remove the winner.
helpers.temp.updateStats();
// Update the button.
$('#open-or-close-auction').html($('<i/>', {
'class': 'fa fa-unlock-alt'
})).append('&nbsp; Open').removeClass('btn-warning').addClass('btn-success');
});
}
});
// Warn auction.
$('#warn-auction').on('click', function () {
socket.sendCommand('auction_warn_cmd', 'auction warn', function () {
toastr.success('Warning users that the auction is about to close.');
});
});
// Warn reset.
$('#reset-auction').on('click', function () {
socket.sendCommand('auction_reset_cmd', 'auction reset', function () {
toastr.success('The auction has been reset.');
$('#open-or-close-auction').html($('<i/>', {
'class': 'fa fa-unlock-alt'
})).append('&nbsp; Open').removeClass('btn-warning').addClass('btn-success');
});
});
});

View File

@@ -0,0 +1,246 @@
3/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Function that querys all of the data we need.
$(run = function () {
socket.getDBValues('raffle_module_status_toggle', {
tables: ['modules', 'raffleSettings'],
keys: ['./systems/raffleSystem.js', 'isActive']
}, true, function (e) {
if (!helpers.handleModuleLoadUp(['raffleListModule', 'raffleModal'], e['./systems/raffleSystem.js'], 'raffleModuleToggle')) {
// Remove the chat.
$('#raffle-chat').find('iframe').remove();
return;
}
// Update the open button to close if the raffle is active.
if (e['isActive'] === 'true') {
$('#open-or-close-raffle').html($('<i/>', {
'class': 'fa fa-lock'
})).append('&nbsp; Close').removeClass('btn-success').addClass('btn-warning');
}
/**
* @function Loads the raffle list.
*/
helpers.temp.loadRaffleList = function () {
socket.getDBTableValues('get_raffle_list', 'raffleList', function (results) {
const table = $('#raffle-table');
// Remove current data content.
table.find('tr:gt(0)').remove();
for (let i = 0; i < results.length; i++) {
const tr = $('<tr/>');
tr.append($('<td/>', {
'html': results[i].key
}));
table.append(tr);
}
});
};
if (location.protocol.toLowerCase().startsWith('https') && !(location.port > 0 && location.port !== 443)) {
// Add Twitch chat.
$('#raffle-chat').html($('<iframe/>', {
'frameborder': '0',
'scrolling': 'no',
'style': 'width: 100%; height: 610px;',
'src': 'https://www.twitch.tv/embed/' + getChannelName() + '/chat' + (helpers.isDark ? '?darkpopout&' : '?') + 'parent=' + location.hostname
}));
} else {
$('#raffle-chat').html('Due to changes by Twitch, the chat panel can no longer be displayed unless you enable SSL on the PhantomBot Panel and change the baseport to 443. This may not work without root privileges.<br /><br />Alternatively, you can login using the GitHub version of the panel at <a href="https://phantombot.github.io/PhantomBot/">PhantomBot - GitHub.io</a> which gets around this issue.<br /><br />For help setting up SSL, please see <a href="https://phantombot.github.io/PhantomBot/guides/#guide=content/integrations/twitchembeds">this guide</a>.');
$('#raffle-chat').addClass('box-body');
}
// Load the raffle list.
helpers.temp.loadRaffleList();
// Set a timer to auto load the raffle list.
helpers.setInterval(function () {
helpers.temp.loadRaffleList();
}, 5e3);
});
});
// Function that handlers the loading of events.
$(function () {
// Module toggle.
$('#raffleModuleToggle').on('change', function () {
socket.sendCommandSync('raffle_system_module_toggle_cmd',
'module ' + ($(this).is(':checked') ? 'enablesilent' : 'disablesilent') + ' ./systems/raffleSystem.js', run);
});
// Title update
$('#raffle-req').on('change', function () {
if ($(this).val() === '-usetime') {
$('#raffle-cost-title').html('Minimum Time (Minutes)');
} else {
$('#raffle-cost-title').html('Cost');
}
})
// Open/close raffle button.
$('#open-or-close-raffle').on('click', function () {
if ($(this)[0].innerText.trim() === 'Open') {
const keyword = $('#raffle-keyword'),
cost = $('#raffle-cost'),
costType = $('#raffle-req').val(),
elegibility = $('#raffle-perm').val(),
timer = $('#raffle-timer'),
regLuck = $('#raffle-reg'),
subLuck = $('#raffle-sub');
// Make sure the user entered everything right.
switch (false) {
case helpers.handleInputString(keyword):
case helpers.handleInputNumber(cost, 0):
case helpers.handleInputNumber(timer, 0):
case helpers.handleInputNumber(regLuck, 1, 10):
case helpers.handleInputNumber(subLuck, 1, 10):
break;
default:
socket.updateDBValues('update_raffle_settings', {
tables: ['raffleSettings', 'raffleSettings'],
keys: ['subscriberBonusRaffle', 'regularBonusRaffle'],
values: [subLuck.val(), regLuck.val()]
}, function () {
socket.sendCommandSync('raffle_reload', 'reloadraffle', function () {
socket.sendCommand('open_raffle_cmd', 'raffle open ' + cost.val() + ' ' + keyword.val() +
' ' + timer.val() + ' ' + costType + ' ' + elegibility, function () {
// Alert the user.
toastr.success('Successfully opened the raffle!');
// Update the button.
$('#open-or-close-raffle').html($('<i/>', {
'class': 'fa fa-lock'
})).append('&nbsp; Close').removeClass('btn-success').addClass('btn-warning');
});
})
});
}
} else {
socket.sendCommandSync('close_raffle_cmd', 'raffle close', function () {
// Alert the user.
toastr.success('Successfully closed the raffle!');
// Reload to remove the winner.
helpers.temp.loadRaffleList();
// Update the button.
$('#open-or-close-raffle').html($('<i/>', {
'class': 'fa fa-unlock-alt'
})).append('&nbsp; Open').removeClass('btn-warning').addClass('btn-success');
});
}
});
// Draw raffle button.
$('#draw-raffle').on('click', function () {
socket.sendCommandSync('draw_raffle_cmd', 'raffle draw', function () {
// Alert the user.
toastr.success('Successfully drew a winner!');
// Reload to remove the winner.
helpers.temp.loadRaffleList();
});
});
// Reset raffle button.
$('#reset-raffle').on('click', function () {
// Reset values.
$('#raffle-keyword').val('');
$('#raffle-cost, #raffle-timer').val('0');
$('#raffle-cost-title').html('Cost');
$('#raffle-req').val('-usepoints');
$('#raffle-reg, #raffle-sub').val('1');
$('#raffle-table').find('tr:gt(0)').remove();
$('#open-or-close-raffle').html($('<i/>', {
'class': 'fa fa-unlock-alt'
})).append('&nbsp; Open').removeClass('btn-warning').addClass('btn-success');
// Close raffle but don't pick a winner.
socket.sendCommand('reset_raffle_cmd', 'raffle reset', function () {
toastr.success('Successfully reset the raffle!');
});
});
// Raffle settings button.
$('#raffle-settings').on('click', function () {
socket.getDBValues('get_raffle_settings', {
tables: ['raffleSettings', 'raffleSettings', 'raffleSettings', 'raffleSettings', 'raffleSettings'],
keys: ['raffleMSGToggle', 'raffleWhisperWinner', 'noRepickSame', 'raffleMessage', 'raffleMessageInterval']
}, true, function (e) {
helpers.getModal('raffle-settings-modal', 'Raffle Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Add the div for the col boxes.
.append($('<div/>', {
'class': 'panel-group',
'id': 'accordion'
})
// Append first collapsible accordion.
.append(helpers.getCollapsibleAccordion('main-1', 'Timed Message Settings', $('<form/>', {
'role': 'form'
})
// Append interval box for the message
.append(helpers.getInputGroup('msg-timer', 'number', 'Message Interval (Minutes)', '', e['raffleMessageInterval'],
'How often the raffle message is said in chat while a raffle is active.'))
// Append message box for the message
.append(helpers.getTextAreaGroup('msg-msg', 'text', 'Raffle Message', '', e['raffleMessage'],
'What message is said at every interval while the raffle is active. Tags: (keyword) and (entries)'))))
// Append second collapsible accordion.
.append(helpers.getCollapsibleAccordion('main-2', 'Extra Settings', $('<form/>', {
'role': 'form'
})
// Add toggle for warning messages.
.append(helpers.getDropdownGroup('warning-msg', 'Enable Warning Messages', (e['raffleMSGToggle'] === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If warning messages should be said in chat when a user already entered, or doesn\'t have enough points.'))
// Add toggle for repicks
.append(helpers.getDropdownGroup('draw-toggle', 'Allow Multiple Draws', (e['noRepickSame'] === 'false' ? 'Yes' : 'No'), ['Yes', 'No'],
'If a user can be drawn multiple times for one raffle.'))
// Add toggle for repicks
.append(helpers.getDropdownGroup('whisper-toggle', 'Whisper The Winner', (e['raffleWhisperWinner'] === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If the winner of the raffle should get a whisper saying they won.'))))),
function () {
let raffleTimer = $('#msg-timer'),
raffleMessage = $('#msg-msg'),
warningMsg = $('#warning-msg').find(':selected').text() === 'Yes',
drawToggle = $('#draw-toggle').find(':selected').text() !== 'Yes',
whisperWinner = $('#whisper-toggle').find(':selected').text() === 'Yes';
switch (false) {
case helpers.handleInputNumber(raffleTimer):
case helpers.handleInputString(raffleMessage):
break;
default:
socket.updateDBValues('update_raffle_settings_2', {
tables: ['raffleSettings', 'raffleSettings', 'raffleSettings', 'raffleSettings', 'raffleSettings'],
keys: ['raffleMSGToggle', 'raffleWhisperWinner', 'noRepickSame', 'raffleMessage', 'raffleMessageInterval'],
values: [warningMsg, whisperWinner, drawToggle, raffleMessage.val(), raffleTimer.val()]
}, function () {
socket.sendCommand('raffle_reload_cmd', 'reloadraffle', function () {
// Close the modal.
$('#raffle-settings-modal').modal('toggle');
// Warn the user.
toastr.success('Successfully updated raffle settings!');
});
});
}
}).modal('toggle');
});
});
});

View File

@@ -0,0 +1,218 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
$(run = function () {
socket.getDBValues('traffle_module_status_toggle', {
tables: ['modules', 'traffleSettings'],
keys: ['./systems/ticketraffleSystem.js', 'isActive']
}, true, function (e) {
if (!helpers.handleModuleLoadUp(['ticketRaffleListModule', 'ticketRaffleModal'], e['./systems/ticketraffleSystem.js'], 'ticketRaffleModuleToggle')) {
// Remove the chat.
$('#ticket-raffle-chat').find('iframe').remove();
return;
}
// Update the open button to close if the raffle is active.
if (e['isActive'] === 'true') {
$('#ticket-open-or-close-raffle').html($('<i/>', {
'class': 'fa fa-lock'
})).append('&nbsp; Close').removeClass('btn-success').addClass('btn-warning');
}
/**
* @function Loads the raffle list.
*/
helpers.temp.loadRaffleList = function () {
socket.getDBTableValues('get_traffle_list', 'ticketsList', function (results) {
const table = $('#ticket-raffle-table');
// Remove current data content.
table.find('tr:gt(0)').remove();
for (let i = 0; i < results.length; i++) {
const tr = $('<tr/>');
tr.append($('<td/>', {
'html': results[i].key
}));
tr.append($('<td/>', {
'html': results[i].value
}));
table.append(tr);
}
});
};
if (location.protocol.toLowerCase().startsWith('https') && !(location.port > 0 && location.port !== 443)) {
// Add Twitch chat.
$('#ticket-raffle-chat').html($('<iframe/>', {
'frameborder': '0',
'scrolling': 'no',
'style': 'width: 100%; height: 610px;',
'src': 'https://www.twitch.tv/embed/' + getChannelName() + '/chat' + (helpers.isDark ? '?darkpopout&' : '?') + 'parent=' + location.hostname
}));
} else {
$('#ticket-raffle-chat').html('Due to changes by Twitch, the chat panel can no longer be displayed unless you enable SSL on the PhantomBot Panel and change the baseport to 443. This may not work without root privileges.<br /><br />Alternatively, you can login using the GitHub version of the panel at <a href="https://phantombot.github.io/PhantomBot/">PhantomBot - GitHub.io</a> which gets around this issue.<br /><br />For help setting up SSL, please see <a href="https://phantombot.github.io/PhantomBot/guides/#guide=content/integrations/twitchembeds">this guide</a>.');
$('#ticket-raffle-chat').addClass('box-body');
}
// Load the raffle list.
helpers.temp.loadRaffleList();
// Set a timer to auto load the raffle list.
helpers.setInterval(function () {
helpers.temp.loadRaffleList();
}, 5e3);
});
});
// Function that handlers the loading of events.
$(function () {
// Module toggle.
$('#ticketRaffleModuleToggle').on('change', function () {
socket.sendCommandSync('traffle_system_module_toggle_cmd',
'module ' + ($(this).is(':checked') ? 'enablesilent' : 'disablesilent') + ' ./systems/ticketraffleSystem.js', run);
});
// Open/close raffle button.
$('#ticket-open-or-close-raffle').on('click', function () {
if ($(this)[0].innerText.trim() === 'Open') {
const cost = $('#ticket-raffle-cost'),
maxTicket = $('#ticket-raffle-max'),
elegibility = $('#ticket-raffle-perm').val(),
regLuck = $('#ticket-raffle-reg'),
subLuck = $('#ticket-raffle-sub');
// Make sure the user entered everything right.
switch (false) {
case helpers.handleInputNumber(cost, 1):
case helpers.handleInputNumber(maxTicket, 1):
case helpers.handleInputNumber(regLuck, 1, 10):
case helpers.handleInputNumber(subLuck, 1, 10):
break;
default:
socket.sendCommand('open_traffle_cmd', 'traffle open ' + maxTicket.val() + ' ' + regLuck.val() + ' ' + subLuck.val() + ' ' + cost.val() + ' ' + elegibility, function () {
// Alert the user.
toastr.success('Successfully opened the ticket raffle!');
// Update the button.
$('#ticket-open-or-close-raffle').html($('<i/>', {
'class': 'fa fa-lock'
})).append('&nbsp; Close').removeClass('btn-success').addClass('btn-warning');
});
}
} else {
socket.sendCommandSync('close_traffle_cmd', 'traffle close', function () {
// Alert the user.
toastr.success('Successfully closed the ticket raffle!');
// Reload to remove the winner.
helpers.temp.loadRaffleList();
// Update the button.
$('#ticket-open-or-close-raffle').html($('<i/>', {
'class': 'fa fa-unlock-alt'
})).append('&nbsp; Open').removeClass('btn-warning').addClass('btn-success');
});
}
});
// Draw raffle button.
$('#ticket-draw-raffle').on('click', function () {
socket.sendCommandSync('draw_rraffle_cmd', 'traffle draw', function () {
// Alert the user.
toastr.success('Successfully drew a winner!');
// Reload to remove the winner.
helpers.temp.loadRaffleList();
});
});
// Reset raffle button.
$('#ticket-reset-raffle').on('click', function () {
// Reset values.
$('#ticket-raffle-max').val('100');
$('#ticket-raffle-cost').val('1');
$('#ticket-raffle-reg, #ticket-raffle-sub').val('1');
$('#ticket-raffle-table').find('tr:gt(0)').remove();
$('#ticket-open-or-close-raffle').html($('<i/>', {
'class': 'fa fa-unlock-alt'
})).append('&nbsp; Open').removeClass('btn-warning').addClass('btn-success');
// Close raffle but don't pick a winner.
socket.sendCommand('reset_traffle_cmd', 'traffle reset', function () {
toastr.success('Successfully reset the ticket raffle!');
});
});
// Raffle settings button.
$('#ticket-raffle-settings').on('click', function () {
socket.getDBValues('get_traffle_settings', {
tables: ['settings', 'settings', 'settings'],
keys: ['tRaffleMSGToggle', 'traffleMessage', 'traffleMessageInterval']
}, true, function (e) {
helpers.getModal('traffle-settings-modal', 'Ticket Raffle Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Add the div for the col boxes.
.append($('<div/>', {
'class': 'panel-group',
'id': 'accordion'
})
// Append first collapsible accordion.
.append(helpers.getCollapsibleAccordion('main-1', 'Timed Message Settings', $('<form/>', {
'role': 'form'
})
// Append interval box for the message
.append(helpers.getInputGroup('msg-timer', 'number', 'Message Interval (Minutes)', '', e['traffleMessageInterval'],
'How often the raffle message is said in chat while a raffle is active.'))
// Append message box for the message
.append(helpers.getTextAreaGroup('msg-msg', 'text', 'Raffle Message', '', e['traffleMessage'],
'What message is said at every interval while the raffle is active. Tags: (amount) and (entries)'))))
// Append second collapsible accordion.
.append(helpers.getCollapsibleAccordion('main-2', 'Extra Settings', $('<form/>', {
'role': 'form'
})
// Add toggle for warning messages.
.append(helpers.getDropdownGroup('warning-msg', 'Enable Warning Messages', (e['tRaffleMSGToggle'] === 'true' ? 'Yes' : 'No'), ['Yes', 'No'],
'If warning messages should be said in chat when a user already entered, or doesn\'t have enough points.'))))),
function () {
let raffleTimer = $('#msg-timer'),
raffleMessage = $('#msg-msg'),
warningMsg = $('#warning-msg').find(':selected').text() === 'Yes';
switch (false) {
case helpers.handleInputNumber(raffleTimer):
case helpers.handleInputString(raffleMessage):
break;
default:
socket.updateDBValues('update_traffle_settings_2', {
tables: ['settings', 'settings', 'settings'],
keys: ['tRaffleMSGToggle', 'traffleMessage', 'traffleMessageInterval'],
values: [warningMsg, raffleMessage.val(), raffleTimer.val()]
}, function () {
socket.sendCommand('raffle_reload_cmd', 'reloadtraffle', function () {
// Close the modal.
$('#traffle-settings-modal').modal('toggle');
// Warn the user.
toastr.success('Successfully updated ticket raffle settings!');
});
});
}
}).modal('toggle');
});
});
});

View File

@@ -0,0 +1,84 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Script that handles all of the global things.
$(function() {
// Dark mode toggle.
$('#dark-mode-toggle').on('click', function() {
// Update the toggle.
socket.updateDBValue('panel_dark_mode_toggle', 'panelData', 'isDark', $(this).is(':checked'), function() {
window.location.reload();
});
});
// the button that signs out.
$('#sign-out-btn').on('click', function() {
$.ajax({
'type': 'GET',
'url': window.location.pathname,
'username': 'log',
'password': 'out'
}).done(function() {
window.location = '/panel/login?logout=true';
}).fail(function() {
// We logged out. We want a 401, this means the old password was dumped (The good one).
window.location = '/';
});
});
// Load the display name.
$(function() {
$('#main-name, #second-name').text(getDisplayName());
});
// Check if Discord is enabled.
socket.getDBValue('get_discord_status_index', 'panelData', 'hasDiscord', function(e) {
// Remove the tab if we are not using Discord.
if (e.panelData !== 'true') {
$('#discord_index_tab').remove();
return;
}
});
// Get bot updates.
socket.getDBValue('get_bot_updates', 'settings', 'newrelease_info', function(e) {
if (e.settings !== null) {
e.settings = e.settings.split('|');
helpers.handleNewBotUpdate(e.settings[0], e.settings[1]);
}
// Check for updates every 30 seconds.
if (helpers.isDoUpdateLoop === undefined) {
helpers.isDoUpdateLoop = true;
// This timer is global and will never get killed.
setInterval(function() {
helpers.log('Running bot version check.', helpers.LOG_TYPE.INFO);
socket.getDBValue('get_bot_updates', 'settings', 'newrelease_info', function(e) {
if (e.settings !== null) {
e.settings = e.settings.split('|');
helpers.handleNewBotUpdate(e.settings[0], e.settings[1]);
}
});
}, 3e4);
}
});
});

View File

@@ -0,0 +1,31 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Function that querys all of the data we need.
$(function() {
// Get the version
socket.getBotVersion('get_panel_info_version', function(e) {
// Set bot version
$('#panel-bot-version').html(e['version'].substring(20));
// Set the java version.
$('#panel-java-version').html(e['java-version']);
// Set the OS version.
$('#panel-os-version').html(e['os-version']);
// Set the panel version.
$('#panel-version-number').html(helpers.PANEL_VERSION);
});
});

View File

@@ -0,0 +1,50 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Function that querys all of the data we need.
$(function() {
socket.getDBTableValues('get_all_hosts', 'hosthistory', function(results) {
let hosts = [];
for (let i = 0; i < results.length; i++) {
let json = JSON.parse(results[i].value);
hosts.push([
json.host,
new Date(parseInt(json.time)).toLocaleString(),
helpers.getDefaultIfNullOrUndefined(json.viewers, 'N/A'),
parseInt(json.time)
]);
}
// Create table.
$('#hostHistoryTable').DataTable({
'searching': true,
'autoWidth': false,
'data': hosts,
'columnDefs': [
{ 'width': '35%', 'targets': 0 }
],
'columns': [
{ 'title': 'Username' },
{ 'title': 'Date', 'orderData': [3] },
{ 'title': 'Viewers' },
{ 'visible': false }
]
});
});
});

View File

@@ -0,0 +1,101 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Function that querys all of the data we need.
$(function() {
socket.getDBTableValues('get_all_raids', 'incoming_raids', function(results) {
let raids = [];
for (let i = 0; i < results.length; i++) {
let json = JSON.parse(results[i].value);
raids.push([
results[i].key,
new Date(parseInt(json.lastRaidTime)).toLocaleString(),
helpers.getDefaultIfNullOrUndefined(json.lastRaidViewers, '0'),
helpers.getDefaultIfNullOrUndefined(json.totalRaids, '1'),
helpers.getDefaultIfNullOrUndefined(json.totalViewers, '0'),
parseInt(json.lastRaidTime)
]);
}
// if the table exists, destroy it.
if ($.fn.DataTable.isDataTable('#raidHistoryTable')) {
$('#raidHistoryTable').DataTable().destroy();
// Remove all of the old events.
$('#raidHistoryTable').off();
}
// Create table.
$('#raidHistoryTable').DataTable({
'searching': true,
'autoWidth': false,
'data': raids,
'columnDefs': [
{ 'width': '20%', 'targets': 0 }
],
'columns': [
{ 'title': 'Username' },
{ 'title': 'Last Raid', 'orderData': [5] },
{ 'title': 'Viewers' },
{ 'title': 'Total Raids' },
{ 'title': 'Total Viewers' },
{ 'visible': false }
]
});
});
socket.getDBTableValues('get_all_out_raids', 'outgoing_raids', function(results) {
let raids = [];
for (let i = 0; i < results.length; i++) {
let json = JSON.parse(results[i].value);
raids.push([
results[i].key,
new Date(parseInt(json.lastRaidTime)).toLocaleString(),
helpers.getDefaultIfNullOrUndefined(json.lastRaidViewers, '0'),
helpers.getDefaultIfNullOrUndefined(json.totalRaids, '1'),
helpers.getDefaultIfNullOrUndefined(json.totalViewers, '0'),
]);
}
// if the table exists, destroy it.
if ($.fn.DataTable.isDataTable('#outRaidHistoryTable')) {
$('#outRaidHistoryTable').DataTable().destroy();
// Remove all of the old events.
$('#outRaidHistoryTable').off();
}
// Create table.
$('#outRaidHistoryTable').DataTable({
'searching': true,
'autoWidth': false,
'data': raids,
'columnDefs': [
{ 'width': '20%', 'targets': 0 }
],
'columns': [
{ 'title': 'Username' },
{ 'title': 'Last Raid', 'orderData': [1] },
{ 'title': 'Viewers' },
{ 'title': 'Total Raids' },
{ 'title': 'Total Viewers' }
]
});
});
});

View File

@@ -0,0 +1,95 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Function that querys all of the data we need.
$(function() {
socket.getDBTableValues('get_all_tips', 'donations', function(results) {
let tips = [];
for (let i = 0; i < results.length; i++) {
let value = results[i].value;
// Make sure that it's a json object.
if (value.startsWith('{') && value.endsWith('}')) {
// Just to be safe, we'll add a try catch.
try {
let json = JSON.parse(value);
// Since we don't store what service the tip came from.
// We have to guess.
switch (true) {
case json.currency !== undefined && json.name !== undefined:
tips.push([
json.name,
helpers.getPaddedDateString(new Date(parseInt(json.created_at) * 1e3).toLocaleString()),
json.currency + ' ' + parseFloat(json.amount).toFixed(2),
'StreamLabs',
parseInt(json.created_at) * 1e3
]);
break;
case json.parameters !== undefined:
tips.push([
json.parameters.username,
helpers.getPaddedDateString(new Date(json.created_at.substring(0, json.created_at.indexOf('+'))).toLocaleString()), // We remove the +0200 because Safari doesn't like it.
json.parameters.currency + ' ' + parseFloat(json.parameters.amount).toFixed(2),
'TipeeeStream',
new Date(json.created_at.substring(0, json.created_at.indexOf('+'))).getTime()
]);
break;
case json.createdAt !== undefined && json.donation !== undefined:
tips.push([
json.donation.user.username,
helpers.getPaddedDateString(new Date(json.createdAt).toLocaleString()),
json.donation.currency + ' ' + parseFloat(json.donation.amount).toFixed(2),
'StreamElements',
new Date(json.createdAt).getTime()
]);
break;
case json.user !== undefined && json.user.name !== undefined:
tips.push([
json.user.name,
helpers.getPaddedDateString(new Date(json.date).toLocaleString()),
json.currencyCode + ' ' + parseFloat(json.amount).toFixed(2),
'StreamTip',
new Date(json.date).getTime()
]);
break;
}
} catch (ex) {
helpers.logError('Failed to parse tip [' + value + ']: ' + ex.stack, helpers.LOG_TYPE.FORCE);
}
}
}
// Create table.
$('#tipsHistoryTable').DataTable({
'searching': true,
'autoWidth': false,
'data': tips,
'columnDefs': [
{ 'width': '30%', 'targets': 0 }
],
'columns': [
{ 'title': 'Username' },
{ 'title': 'Date', 'orderData': [4] },
{ 'title': 'Amount' },
{ 'title': 'Tipping Service' },
{ 'visible': false }
]
});
});
});

View File

@@ -0,0 +1,275 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Function that querys all of the data we need.
$(run = function() {
// Check if the module is enabled.
socket.getDBValue('keyword_module', 'modules', './handlers/keywordHandler.js', function(e) {
// If the module is off, don't load any data.
if (!helpers.handleModuleLoadUp('keywordModule', e.modules)) {
return;
}
// Get all keywords.
socket.getDBTableValues('keywords_get_all', 'keywords', function(results) {
let tableData = [];
for (let i = 0; i < results.length; i++) {
let json = JSON.parse(results[i].value);
tableData.push([
json.keyword,
json.response,
$('<div/>', {
'class': 'btn-group'
}).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-danger',
'style': 'float: right',
'data-keyword': results[i].key,
'html': $('<i/>', {
'class': 'fa fa-trash'
})
})).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-warning',
'style': 'float: right',
'data-keyword': results[i].key,
'html': $('<i/>', {
'class': 'fa fa-edit'
})
})).html()
]);
}
// if the table exists, destroy it.
if ($.fn.DataTable.isDataTable('#keywordsTable')) {
$('#keywordsTable').DataTable().destroy();
// Remove all of the old events.
$('#keywordsTable').off();
}
// Create table.
let table = $('#keywordsTable').DataTable({
'searching': true,
'autoWidth': false,
'lengthChange': false,
'data': tableData,
'columnDefs': [
{ 'className': 'default-table', 'orderable': false, 'targets': 2 },
{ 'width': '35%', 'targets': 0 }
],
'columns': [
{ 'title': 'Keyword' },
{ 'title': 'Response' },
{ 'title': 'Actions' }
]
});
// On delete button.
table.on('click', '.btn-danger', function() {
let keyword = $(this).data('keyword'),
row = $(this).parents('tr');
helpers.getConfirmDeleteModal('keyword_modal_remove', 'Are you sure you want to remove the keyword "' + keyword + '"?', true,
'You\'ve successfully removed the keyword "' + keyword + '"!', function() {
// Delete all of the info about the keyword.
socket.removeDBValues('rm_keyword', {
tables: ['keywords', 'coolkey'],
keys: [keyword, keyword]
}, function() {
socket.wsEvent('rm_keyword_ws', './handlers/keywordHandler.js', null, [], function() {
// Remove the table row.
table.row(row).remove().draw(false);
});
});
});
});
// On edit button.
table.on('click', '.btn-warning', function() {
let keyword = $(this).data('keyword'),
t = $(this);
socket.getDBValues('edit_keyword', {
tables: ['keywords', 'coolkey'],
keys: [keyword, keyword]
}, function(e) {
e.keywords = JSON.parse(e.keywords);
// Get advance modal from our util functions in /utils/helpers.js
helpers.getAdvanceModal('edit-keyword', 'Edit Keyword', 'Save', $('<form/>', {
'role': 'form'
})
// Append a text box for keyword
.append(helpers.getTextAreaGroup('keyword-keyword', 'text', 'Keyword', '',
e.keywords.keyword, 'Keyword that can trigger a response.', true)
// Append checkbox for if the keyword is regex.
.append(helpers.getCheckBox('keyword-regex', e.keywords.isRegex, 'Regex', 'If the keyword is using regex.'))
// Append checkbox for it the keyword should be matched case-sensitive
.append(helpers.getCheckBox('keyword-case-sensitive', e.keywords.isCaseSensitive, 'Case-Sensitive', 'If the keyword/regex should only match if the capitalization matches.'))
)
// Append a text box for the keyword response.
.append(helpers.getTextAreaGroup('keyword-response', 'text', 'Response', '', e.keywords.response, 'Response of the keyword.'))
// Add an advance section that can be opened with a button toggle.
.append($('<div/>', {
'class': 'collapse',
'id': 'advance-collapse',
'html': $('<form/>', {
'role': 'form'
})
// Append input box for keyword cooldown
.append(helpers.getInputGroup('cooldown-count', 'number', 'Cooldown (Seconds)', '',
helpers.getDefaultIfNullOrUndefined(e.coolkey, 5), 'The cooldown of the keyword in seconds. Minimum is 5 seconds.'))
// Append input box for keyword count
.append(helpers.getInputGroup('keyword-count', 'number', 'Count', '',
helpers.getDefaultIfNullOrUndefined(e.keywords.count, 0), 'Count of the keyword. This increases when the keyword has the variable (keywordcount).'))
})), function() {
let keywordKey = $('#keyword-keyword'),
keywordResponse = $('#keyword-response'),
isRegex = $('#keyword-regex').is(':checked'),
isCaseSensitive = $('#keyword-case-sensitive').is(':checked'),
keywordCooldown = $('#cooldown-count'),
keywordCount = $('#keyword-count');
// Make sure everything was filled in.
switch (false) {
case helpers.handleInputString(keywordKey):
case helpers.handleInputString(keywordResponse):
case helpers.handleInputNumber(keywordCooldown, 5):
case helpers.handleInputNumber(keywordCount):
break;
default:
// Remove the old keyword.
socket.removeDBValue('edit_keyword_rm', 'keywords', keyword, function() {
// Update the values.
socket.updateDBValues('edit_keyword', {
tables: ['keywords', 'coolkey'],
keys: [keywordKey.val(), keywordKey.val()],
values: [JSON.stringify({
keyword: keywordKey.val(),
response: keywordResponse.val(),
isRegex: isRegex,
isCaseSensitive: isCaseSensitive,
count: keywordCount.val()
}), keywordCooldown.val()]
}, function() {
// Reload the keywords in the scripts.
socket.wsEvent('rm_keyword_ws', './handlers/keywordHandler.js', null, [], function() {
// Update the table.
t.parents('tr').find('td:eq(0)').text(keywordKey.val());
// Update the table.
t.parents('tr').find('td:eq(1)').text(keywordResponse.val());
// Update the edit and delete buttons
t.parents('tr').find('td:eq(2) button.btn').data('keyword', keywordKey.val());
// Close the modal.
$('#edit-keyword').modal('hide');
// Alert the user.
toastr.success('Successfully edited the keyword!');
});
});
});
}
}).modal('toggle');
});
});
});
});
});
// Function that handlers the loading of events.
$(function() {
// Handle module toggle.
$('#keywordModuleToggle').on('change', function() {
// Enable the module then query the data.
socket.sendCommandSync('keywords_module_toggle_cmd',
'module ' + ($(this).is(':checked') ? 'enablesilent' : 'disablesilent') + ' ./handlers/keywordHandler.js', run);
});
// Add keyword button.
$('#keywordadd-button').on('click', function() {
// Get advance modal from our util functions in /utils/helpers.js
helpers.getAdvanceModal('add-keyword', 'Add Keyword', 'Save', $('<form/>', {
'role': 'form'
})
// Append a text box for keyword
.append(helpers.getTextAreaGroup('keyword-keyword', 'text', 'Keyword', 'PhantomBot', '', 'Keyword that can trigger a response.', true)
// Append checkbox for if the keyword is regex.
.append(helpers.getCheckBox('keyword-regex', false, 'Regex', 'If the keyword is using regex.'))
// Append checkbox for it the keyword should be matched case-sensitive
.append(helpers.getCheckBox('keyword-case-sensitive', false, 'Case-Sensitive', 'If the keyword/regex should only match if the capitalization matches.'))
)
// Append a text box for the keyword response.
.append(helpers.getTextAreaGroup('keyword-response', 'text', 'Response',
'Checkout PhantomBot, it\'s a great free and open source bot!', '', 'Response of the keyword.'))
// Add an advance section that can be opened with a button toggle.
.append($('<div/>', {
'class': 'collapse',
'id': 'advance-collapse',
'html': $('<form/>', {
'role': 'form'
})
// Append input box for keyword cooldown
.append(helpers.getInputGroup('cooldown-count', 'number', 'Cooldown (Seconds)', '', '5',
'The cooldown of the keyword in seconds. Minimum is 5 seconds.'))
// Append input box for keyword count
.append(helpers.getInputGroup('keyword-count', 'number', 'Count', '', '0',
'Count of the keyword. This increases when the keyword has the variable (keywordcount).'))
})), function() {
let keywordKey = $('#keyword-keyword'),
keywordResponse = $('#keyword-response'),
isRegex = $('#keyword-regex').is(':checked'),
isCaseSensitive = $('#keyword-case-sensitive').is(':checked'),
keywordCooldown = $('#cooldown-count'),
keywordCount = $('#keyword-count');
// Make sure everything was filled in.
switch (false) {
case helpers.handleInputString(keywordKey):
case helpers.handleInputString(keywordResponse):
case helpers.handleInputNumber(keywordCooldown, 5):
case helpers.handleInputNumber(keywordCount):
break;
default:
// Update the values.
socket.updateDBValues('add_keyword', {
tables: ['keywords', 'coolkey'],
keys: [keywordKey.val(), keywordKey.val()],
values: [JSON.stringify({
keyword: keywordKey.val(),
response: keywordResponse.val(),
isRegex: isRegex,
isCaseSensitive: isCaseSensitive,
count: keywordCount.val()
}), keywordCooldown.val()]
}, function() {
// Reload the keywords in the scripts.
socket.wsEvent('add_keyword_ws', './handlers/keywordHandler.js', null, [], function() {
// Update the table.
run();
// Close the modal.
$('#add-keyword').modal('hide');
// Alert the user.
toastr.success('Successfully added the keyword!');
});
});
}
}).modal('toggle');
});
});

View File

@@ -0,0 +1,306 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Function that querys all of the data we need.
$(run = function() {
// Get module status.
socket.getDBValue('get_points_module_status', 'modules', './systems/pointSystem.js', function(e) {
// If the module is off, don't load any data.
if (!helpers.handleModuleLoadUp('pointsModule', e.modules)) {
return;
}
// Get points settings.
socket.getDBValues('get_points_settings', {
tables: ['pointSettings', 'pointSettings', 'pointSettings', 'pointSettings', 'pointSettings', 'pointSettings', 'pointSettings', 'pointSettings', 'settings'],
keys: ['onlineGain', 'offlineGain', 'onlinePayoutInterval', 'offlinePayoutInterval', 'activeBonus', 'pointNameSingle', 'pointNameMultiple', 'pointsMessage', 'topListAmountPoints']
}, true, function(e) {
// Set the points message.
$('#points-message').val(e.pointsMessage);
// Set the currency name single.
$('#points-name-single').val(e.pointNameSingle);
// Set the currency name multiple.
$('#points-name-multiple').val(e.pointNameMultiple);
// Set online interval.
$('#points-interval-online').val(e.onlinePayoutInterval);
// Set offline interval.
$('#points-interval-offline').val(e.offlinePayoutInterval);
// Set online payout.
$('#points-payout-online').val(e.onlineGain);
// Set offline payout.
$('#points-payout-offline').val(e.offlineGain);
// Set active bonus.
$('#points-active').val(e.activeBonus);
// Set top list.
$('#points-top').val(e.topListAmountPoints);
});
// Get online group payout.
socket.getDBTableValues('get_points_online_group_payout', 'grouppoints', function(results) {
for (let i = 0; i < results.length; i++) {
$('#points-payout-' + results[i].key.toLowerCase() + '-on').val(results[i].value);
}
});
// Get offline group payout.
socket.getDBTableValues('get_points_offline_group_payout', 'grouppointsoffline', function(results) {
for (let i = 0; i < results.length; i++) {
$('#points-payout-' + results[i].key.toLowerCase() + '-off').val(results[i].value);
}
});
});
});
// Function that handlers the loading of events.
$(function() {
// Module toggle.
$('#pointsModuleToggle').on('change', function() {
// Enable the module then query the data.
socket.sendCommand('points_module_toggle_cmd', 'module ' + ($(this).is(':checked') ? 'enablesilent' : 'disablesilent') + ' ./systems/pointSystem.js', run);
});
// Get user points button.
$('#points-get-user').on('click', function() {
let username = $('#points-username').val().toLowerCase();
if (username.length > 0) {
socket.getDBValue('points_get_user_total', 'points', username, function(e) {
$('#points-username-points').val((e.points === null ? '0' : e.points));
});
}
});
// Save user points.
$('#points-save-user').on('click', function() {
let username = $('#points-username'),
points = $('#points-username-points');
// Make sure both input have something.
switch (false) {
case helpers.handleInputString(username):
case helpers.handleInputNumber(points):
break;
default:
// Save user points.
socket.updateDBValue('points_update_user', 'points', username.val().toLowerCase(), points.val(), function() {
// Alert the user.
toastr.success('Successfully updated user points!');
// Reset box values.
username.val('');
points.val('');
});
}
});
// Handle penalty button.
$('#points-panalty-btn').on('click', function() {
let username = $('#points-panalty-user'),
time = $('#points-panalty-time');
// Make sure both input have something.
switch (false) {
case helpers.handleInputString(username):
case helpers.handleInputNumber(time):
break;
default:
// Set penalty.
socket.sendCommand('set_penalty_user', 'penalty ' + username.val().toLowerCase() + ' ' + time.val(), function() {
// Alert the user.
toastr.success('Successfully set penalty on user!');
// Reset box values.
username.val('');
time.val('');
});
}
});
// Handle points bonus button.
$('#points-bonus-btn').on('click', function() {
let amount = $('#points-bonus-amount'),
time = $('#points-bonus-time');
// Make sure both input have something.
switch (false) {
case helpers.handleInputNumber(amount):
case helpers.handleInputNumber(time):
break;
default:
// Set bonus.
socket.sendCommand('set_bonus_all', 'pointsbonuspanel ' + amount.val() + ' ' + time.val(), function() {
// Alert the user.
toastr.success('Successfully set the points bonus!');
// Reset box values.
amount.val('');
time.val('');
});
}
});
// Handle make it rain button.
$('#points-makeitrain-btn').on('click', function() {
let amount = $('#points-bonus-amount');
// Make sure both input have something.
switch (false) {
case helpers.handleInputNumber(amount):
break;
default:
// Set bonus.
socket.sendCommand('main_it_rain_all', 'makeitrain ' + amount.val(), function() {
// Alert the user.
toastr.success('Successfully made it rain!');
// Reset box values.
amount.val('');
});
}
});
// Handle give all button.
$('#points-giveall-btn').on('click', function() {
let amount = $('#points-bonus-amount');
// Make sure both input have something.
switch (false) {
case helpers.handleInputNumber(amount):
break;
default:
// Set bonus.
socket.sendCommand('set_give_all', 'pointsallpanel ' + amount.val(), function() {
// Alert the user.
toastr.success('Successfully gave everyone points!');
// Reset box values.
amount.val('');
});
}
});
// Handle take all button.
$('#points-takeall-btn').on('click', function() {
let amount = $('#points-bonus-amount');
// Make sure both input have something.
switch (false) {
case helpers.handleInputNumber(amount):
break;
default:
// Set bonus.
socket.sendCommand('set_give_all', 'pointstakepanel ' + amount.val(), function() {
// Alert the user.
toastr.success('Successfully took points from everyone!');
// Reset box values.
amount.val('');
});
}
});
// Button that reloads the points top 100.
$('#currency-reload').on('click', function() {
// Reload all.
run();
toastr.success('Successfully updated the top 100 table.');
});
// Save all points settings.
$('#points-save-all').on('click', function() {
// Save either advanced settings or normal depending on which tab is active.
if ($('#main-settings').hasClass('active')) {
let pointsMessage = $('#points-message'),
pointsSingle = $('#points-name-single'),
pointsMultiple = $('#points-name-multiple'),
pointsOnlineInt = $('#points-interval-online'),
pointsOfflineInt = $('#points-interval-offline'),
pointsOnlinePay = $('#points-payout-online'),
pointsOfflinePay = $('#points-payout-offline'),
pointsActive = $('#points-active'),
topList = $('#points-top');
// Make sure both input have something.
switch (false) {
case helpers.handleInputString(pointsMessage):
case helpers.handleInputString(pointsSingle):
case helpers.handleInputString(pointsMultiple):
case helpers.handleInputNumber(pointsOnlineInt):
case helpers.handleInputNumber(pointsOfflineInt):
case helpers.handleInputNumber(pointsOnlinePay):
case helpers.handleInputNumber(pointsOfflinePay):
case helpers.handleInputNumber(pointsActive):
case helpers.handleInputNumber(topList):
break;
default:
// Update the settings.
socket.updateDBValues('update_points_settings', {
tables: ['pointSettings', 'pointSettings', 'pointSettings', 'pointSettings', 'pointSettings', 'pointSettings', 'pointSettings', 'pointSettings', 'settings'],
keys: ['onlineGain', 'offlineGain', 'onlinePayoutInterval', 'offlinePayoutInterval', 'activeBonus', 'pointNameSingle', 'pointNameMultiple', 'pointsMessage', 'topListAmountPoints'],
values: [pointsOnlinePay.val(), pointsOfflinePay.val(), pointsOnlineInt.val(), pointsOfflineInt.val(), pointsActive.val(), pointsSingle.val(), pointsMultiple.val(), pointsMessage.val(), (parseInt(topList.val()) > 15 ? '15': topList.val())]
}, function() {
socket.sendCommand('update_points_settings_cmd', 'reloadpoints', function() {
toastr.success('Successfully updated points settings!');
});
});
}
} else {
let groups = ['caster', 'administrator', 'moderator', 'subscriber', 'donator', 'regular', 'viewer'],
temp = [];
// Make sure that all groups have a value.
for (let i = 0; i < groups.length; i++) {
// Check for the online value.
if (!helpers.handleInputString($('#points-payout-' + groups[i] + '-on'))) {
return;
}
// Check for the offline value.
if (!helpers.handleInputString($('#points-payout-' + groups[i] + '-off'))) {
return;
}
}
// Get all values for online.
for (let i = 0; i < groups.length; i++) {
temp.push($('#points-payout-' + groups[i] + '-on').val());
}
// Update the DB.
socket.updateDBValues('update_group_payout_online', {
tables: ['grouppoints', 'grouppoints', 'grouppoints', 'grouppoints', 'grouppoints', 'grouppoints', 'grouppoints'],
keys: ['Caster', 'Administrator', 'Moderator', 'Subscriber', 'Donator', 'Regular', 'Viewer'],
values: temp
}, function() {
temp = [];
// Get all values offline online.
for (let i = 0; i < groups.length; i++) {
temp.push($('#points-payout-' + groups[i] + '-off').val());
}
// Update the DB.
socket.updateDBValues('update_group_payout_offline', {
tables: ['grouppointsoffline', 'grouppointsoffline', 'grouppointsoffline', 'grouppointsoffline', 'grouppointsoffline', 'grouppointsoffline', 'grouppointsoffline'],
keys: ['Caster', 'Administrator', 'Moderator', 'Subscriber', 'Donator', 'Regular', 'Viewer'],
values: temp
}, function() {
toastr.success('Successfully updated advanced points settings!');
});
});
}
});
});

View File

@@ -0,0 +1,169 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Function that querys all of the data we need.
$(function() {
// Get top points.
socket.getDBTableValuesByOrder('points_top_get_order', 'points', 100, 0, 'DESC', true, function(results) {
let tableData = [];
for (let i = 0; i < results.length; i++) {
tableData.push([
(i + 1),
results[i].key,
helpers.parseNumber(results[i].value)
]);
}
// if the table exists, destroy it.
if ($.fn.DataTable.isDataTable('#leaderboard-points')) {
$('#leaderboard-points').DataTable().destroy();
// Remove all of the old events.
$('#leaderboard-points').off();
}
// Create table.
$('#leaderboard-points').DataTable({
'searching': true,
'autoWidth': false,
'lengthChange': false,
'data': tableData,
'pageLength': 15,
'columnDefs': [
{ 'width': '15%', 'targets': 0 }
],
'columns': [
{ 'title': 'Position' },
{ 'title': 'Username' },
{ 'title': 'Currency' }
]
});
// Set the title again in case this is a reload.
$('#currency-top-title').html('Top 100 Currency');
});
// Get top time.
socket.getDBTableValuesByOrder('time_top_get_order', 'time', 100, 0, 'DESC', true, function(results) {
let tableData = [];
for (let i = 0; i < results.length; i++) {
tableData.push([
(i + 1),
results[i].key,
helpers.parseNumber(results[i].value),
helpers.parseNumber(Math.floor(parseInt(results[i].value) / 3600))
]);
}
// if the table exists, destroy it.
if ($.fn.DataTable.isDataTable('#leaderboard-time')) {
$('#leaderboard-time').DataTable().destroy();
// Remove all of the old events.
$('#leaderboard-time').off();
}
// Create table.
$('#leaderboard-time').DataTable({
'searching': true,
'autoWidth': false,
'lengthChange': false,
'data': tableData,
'pageLength': 15,
'columnDefs': [
{ 'width': '15%', 'targets': 0 },
{ 'width': '25%', 'targets': 1 }
],
'columns': [
{ 'title': 'Position' },
{ 'title': 'Username' },
{ 'title': 'Time (Seconds)' },
{ 'title': 'Time (Hours)' }
]
});
// Set the title again in case this is a reload.
$('#loyalty-top-title').html('Top 100 Loyalty');
});
});
// Function that handlers the loading of events.
$(function() {
var currencyOffset = 100,
loyaltyOffset = 100;
// On load more points button.
$('#currency-load-more').on('click', function() {
let table = $('#leaderboard-points').DataTable(),
dataCount = table.rows().count(),
tableData = [];
// Only allow more data to be loaded once the last click was fully loaded.
if (currencyOffset === dataCount) {
toastr.success('Loading more users into the currency table.');
// Get the next 100 users.
socket.getDBTableValuesByOrder('points_top_get_order_btn', 'points', 100, (currencyOffset + 100), 'DESC', true, function(results) {
for (let i = 0; i < results.length; i++) {
tableData.push([
(++currencyOffset),
results[i].key,
helpers.parseNumber(results[i].value)
]);
}
// Add the rows.
table.rows.add(tableData).draw(false);
// Edit the title.
$('#currency-top-title').html('Top ' + helpers.parseNumber(currencyOffset) + ' Currency');
});
} else {
toastr.error('Cannot load more points since there are currently some being loaded.');
}
});
// On load more time button.
$('#loyalty-load-more').on('click', function() {
let table = $('#leaderboard-time').DataTable(),
dataCount = table.rows().count(),
tableData = [];
// Only allow more data to be loaded once the last click was fully loaded.
if (loyaltyOffset === dataCount) {
toastr.success('Loading more users into the loyalty table.');
// Get the next 100 users.
socket.getDBTableValuesByOrder('time_top_get_order_btn', 'time', 100, (loyaltyOffset + 100), 'DESC', true, function(results) {
for (let i = 0; i < results.length; i++) {
tableData.push([
(++loyaltyOffset),
results[i].key,
helpers.parseNumber(results[i].value),
helpers.parseNumber(Math.floor(parseInt(results[i].value) / 3600))
]);
}
// Add the rows.
table.rows.add(tableData).draw(false);
// Edit the title.
$('#loyalty-top-title').html('Top ' + helpers.parseNumber(loyaltyOffset) + ' Loyalty');
});
} else {
toastr.error('Cannot load more time since there are currently some being loaded.');
}
});
});

View File

@@ -0,0 +1,112 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Function that querys all of the data we need.
$(run = function() {
// Get time settings.
socket.getDBValues('time_get_settings', {
tables: ['timeSettings', 'timeSettings', 'timeSettings', 'timeSettings', 'settings', 'settings'],
keys: ['timeLevel', 'timeLevelWarning', 'keepTimeWhenOffline', 'timePromoteHours', 'topListAmountTime', 'timezone']
}, true, function(e) {
// Set the bot timezone.
$('#loyalty-timezone').val((e.timezone === null ? 'GMT' : e.timezone));
// Auto add time when offline.
$('#time-offline').val((e.keepTimeWhenOffline === 'true' ? 'Yes' : 'No'));
// Auto promote users.
$('#time-promote').val((e.timeLevel === 'true' ? 'Yes' : 'No'));
// Auto promote chat notice
$('#time-promote-notice').val((e.timeLevelWarning === 'true' ? 'Yes' : 'No'));
// Time to be promoted.
$('#loyalty-promotion').val(e.timePromoteHours);
// Top list amount.
$('#loyalty-top').val(e.topListAmountTime);
});
});
// Function that handlers the loading of events.
$(function() {
// Button that reloads the time top 100.
$('#loyalty-reload').on('click', function() {
// Reload all.
run();
// Alert the user.
toastr.success('Successfully updated the top 100 table.');
});
// Get user time button.
$('#time-get-user').on('click', function() {
let username = $('#time-username').val().toLowerCase();
if (username.length > 0) {
socket.getDBValue('time_get_user_total', 'time', username, function(e) {
$('#time-username-time').val((e.time === null ? '0' : e.time));
});
}
});
// Save user points.
$('#time-save-user').on('click', function() {
let username = $('#time-username'),
time = $('#time-username-time');
// Make sure both input have something.
switch (false) {
case helpers.handleInputString(username):
case helpers.handleInputNumber(time):
break;
default:
// Save user time.
socket.updateDBValue('time_update_user', 'time', username.val().toLowerCase(), time.val(), function() {
// Alert the user.
toastr.success('Successfully updated user time!');
// Reset box values.
username.val('');
time.val('');
});
}
});
// Save time settings.
$('#loyalty-save-all').on('click', function() {
let timeZone = $('#loyalty-timezone'),
countOfflineTime = $('#time-offline').find(':selected').text() === 'Yes',
timePromote = $('#time-promote').find(':selected').text() === 'Yes',
timePromoteNotice = $('#time-promote-notice').find(':selected').text() === 'Yes',
regHours = $('#loyalty-promotion'),
timeTop = $('#loyalty-top');
// Make sure everything has a value.
switch (false) {
case helpers.handleInputString(timeZone):
case helpers.handleInputNumber(regHours):
case helpers.handleInputNumber(timeTop):
break;
default:
// Update database.
socket.updateDBValues('time_update_settings', {
tables: ['timeSettings', 'timeSettings', 'timeSettings', 'timeSettings', 'settings', 'settings'],
keys: ['timeLevel', 'timeLevelWarning', 'keepTimeWhenOffline', 'timePromoteHours', 'topListAmountTime', 'timezone'],
values: [timePromote, timePromoteNotice, countOfflineTime, regHours.val(), (parseInt(timeTop.val()) > 15 ? 15 : timeTop.val()), timeZone.val()]
}, function() {
socket.sendCommand('update_time_settings_cmd', 'reloadtop', function() {
toastr.success('Successfully updated time settings!');
});
});
}
});
});

View File

@@ -0,0 +1,283 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Function that querys all of the data we need.
$(run = function() {
// Query blacklist.
socket.getDBTableValues('moderation_blacklist_get', 'blackList', function(results) {
let tableData = [];
for (let i = 0; i < results.length; i++) {
let json = JSON.parse(results[i].value);
tableData.push([
json.phrase,
json.isRegex,
json.timeout,
json.message,
json.banReason,
$('<div/>', {
'class': 'btn-group'
}).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-danger',
'style': 'float: right',
'data-blacklist': results[i].key,
'html': $('<i/>', {
'class': 'fa fa-trash'
})
})).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-warning',
'style': 'float: right',
'data-blacklist': results[i].key,
'html': $('<i/>', {
'class': 'fa fa-edit'
})
})).html()
]);
}
// if the table exists, destroy it.
if ($.fn.DataTable.isDataTable('#blacklistTable')) {
$('#blacklistTable').DataTable().destroy();
// Remove all of the old events.
$('#blacklistTable').off();
}
// Create table.
let table = $('#blacklistTable').DataTable({
'searching': true,
'autoWidth': false,
'lengthChange': false,
'data': tableData,
'columnDefs': [
{ 'className': 'default-table', 'orderable': false, 'targets': 5 },
{ 'width': '35%', 'targets': 0 },
{ 'width': '25%', 'targets': 3 },
{ 'width': '25%', 'targets': 4 }
],
'columns': [
{ 'title': 'Blacklist' },
{ 'title': 'Regex' },
{ 'title': 'Timeout' },
{ 'title': 'Message' },
{ 'title': 'Reason' },
{ 'title': 'Actions' }
]
});
// On delete button.
table.on('click', '.btn-danger', function() {
let blacklist = $(this).data('blacklist'),
row = $(this).parents('tr');
// Ask the user if he wants to delete the blacklist.
helpers.getConfirmDeleteModal('blacklist_modal_remove', 'Are you sure you want to remove this blacklist?', true,
'The blacklist has been successfully removed!', function() { // Callback if the user clicks delete.
socket.removeDBValue('moderation_blacklist_rm', 'blackList', blacklist, function() {
socket.sendCommand('moderation_blacklist_rm_cmd', 'reloadmod', function() {
// Remove the table row.
table.row(row).remove().draw(false);
});
});
});
});
// On edit button.
table.on('click', '.btn-warning', function() {
let blacklist = $(this).data('blacklist');
socket.getDBValue('moderation_blacklist_edit_get', 'blackList', blacklist, function(e) {
e = JSON.parse(e.blackList);
// Get advance modal from our util functions in /utils/helpers.js
helpers.getAdvanceModal('blacklist-edit-modal', 'Edit Blacklist', 'Save', $('<form/>', {
'role': 'form'
})
// Append a text area box for the phrase.
.append(helpers.getTextAreaGroup('ban-phrase', 'text', 'Blacklist Phrase', '', e.phrase, 'Phrase, word, or regex that should be blacklisted.', true)
// Append checkbox for if this should be regex or not.
.append(helpers.getCheckBox('is-regex', e.isRegex, 'Regex', 'If the blacklist phrase should be using regex.')))
// Append ban reason. This is the message Twitch shows with the timeout.
.append(helpers.getInputGroup('timeout-banmsg', 'text', 'Timeout Message', '', e.message, 'Message said in chat when a user gets timed-out.')
// Append checkbox for if this should be regex or not.
.append(helpers.getCheckBox('timeout-message-toggle', e.isSilent, 'Silent', 'If the warning message should be said or not.')))
// Append input box for the timeout time.
.append(helpers.getInputGroup('timeout-timeout-time', 'number', 'Timeout Duration (Seconds)', '0', e.timeout,
'How long in seconds the user gets timed-out for when using the phrase in chat. -1 will ban the user and 0 will just delete the message.'))
// Add an advance section that can be opened with a button toggle.
.append($('<div/>', {
'class': 'collapse',
'id': 'advance-collapse',
'style': 'margin-top: 10px;',
'html': $('<form/>', {
'role': 'form'
})
// Append ban reason. This is the message Twitch shows with the timeout.
.append(helpers.getInputGroup('timeout-reason', 'text', 'Timeout Reason', '', e.banReason, 'Message shown to all moderators when the user gets timed-out.'))
// Add group for toggles.
.append($('<div/>', {
'class': 'form-group'
})
// Tooltip to toggle for regulars to bypass this filter.
.append(helpers.getCheckBox('exclude-regulars', e.excludeRegulars, 'Exclude Regulars', 'If regulars should be allowed to bypass this filter.'))
// Tooltip to toggle for subs to bypass this filter.
.append(helpers.getCheckBox('exclude-subscribers', e.excludeSubscribers, 'Exclude Subscribers',
'If subscribers should be allowed to bypass this filter.')))
// Callback function to be called once we hit the save button on the modal.
})), function() {
let phrase = $('#ban-phrase'),
isRegex = $('#is-regex').is(':checked'),
banMsg = $('#timeout-banmsg'),
isSilent = $('#timeout-message-toggle').is(':checked'),
timeoutTime = $('#timeout-timeout-time'),
timeoutMsg = $('#timeout-reason'),
isReg = $('#exclude-regulars').is(':checked'),
isSub = $('#exclude-subscribers').is(':checked');
// Add regex prefix is regex.
if (isRegex && !phrase.val().startsWith('regex:')) {
phrase.val('regex:' + phrase.val());
}
// Handle each input to make sure they have a value.
switch (false) {
case helpers.handleInputString(phrase):
case helpers.handleInputString(banMsg):
case helpers.handleInputString(timeoutTime): // Handle as string even if it's a number.
case helpers.handleInputString(timeoutMsg):
break;
default:
// Delete the old blacklist
socket.removeDBValue('rm_moderation_blacklist', 'blackList', blacklist, function() {
// Update the blacklist
socket.updateDBValue('update_moderation_blacklist', 'blackList', phrase.val(), JSON.stringify({
id: 'panel_' + phrase.val(),
timeout: timeoutTime.val(),
isRegex: isRegex,
phrase: phrase.val(),
isSilent: isSilent,
excludeRegulars: isReg,
excludeSubscribers: isSub,
message: banMsg.val(),
banReason: timeoutMsg.val()
}), function() {
socket.sendCommand('moderation_blacklist_reload_cmd', 'reloadmod', function() {
// Update the table.
run();
// Close the modal.
$('#blacklist-edit-modal').modal('hide');
// Alert the user.
toastr.success('Successfully edited blacklist!');
});
});
});
}
}).modal('toggle');
});
});
});
});
// Function that handlers the loading of events.
$(function() {
// Add blacklist button
$('#add-blacklist-button').on('click', function() {
// Get advance modal from our util functions in /utils/helpers.js
helpers.getAdvanceModal('blacklist-add-modal', 'Add Blacklist', 'Save', $('<form/>', {
'role': 'form'
})
// Append a text area box for the phrase.
.append(helpers.getTextAreaGroup('ban-phrase', 'text', 'Blacklist Phrase', 'Kappa 123', '', 'Phrase, word, or regex that should be blacklisted.', true)
// Append checkbox for if this should be regex or not.
.append(helpers.getCheckBox('is-regex', false, 'Regex', 'If the blacklist phrase should be using regex.')))
// Append ban reason. This is the message Twitch shows with the timeout.
.append(helpers.getInputGroup('timeout-banmsg', 'text', 'Timeout Message', '',
'You were timed-out for using a blacklisted phrase.', 'Message said in chat when a user gets timed-out.')
// Append checkbox for if this should be regex or not.
.append(helpers.getCheckBox('timeout-message-toggle', false, 'Silent', 'If the warning message should be said or not.')))
// Append input box for the timeout time.
.append(helpers.getInputGroup('timeout-timeout-time', 'number', 'Timeout Duration', '0', '600',
'How long in seconds the user gets timed-out for when using the phrase in chat. -1 will ban the user.'))
// Add an advance section that can be opened with a button toggle.
.append($('<div/>', {
'class': 'collapse',
'id': 'advance-collapse',
'style': 'margin-top: 10px;',
'html': $('<form/>', {
'role': 'form'
})
// Append ban reason. This is the message Twitch shows with the timeout.
.append(helpers.getInputGroup('timeout-reason', 'text', 'Timeout Reason', '', 'Using a blacklisted phrase',
'Message shown to all moderators when the user gets timed-out.'))
// Add group for toggles.
.append($('<div/>', {
'class': 'form-group'
})
// Tooltip to toggle for regulars to bypass this filter.
.append(helpers.getCheckBox('exclude-regulars', false, 'Exclude Regulars', 'If regulars should be allowed to bypass this filter.'))
// Tooltip to toggle for subs to bypass this filter.
.append(helpers.getCheckBox('exclude-subscribers', false, 'Exclude Subscribers',
'If subscribers should be allowed to bypass this filter.')))
})), function() {
let phrase = $('#ban-phrase'),
isRegex = $('#is-regex').is(':checked'),
banMsg = $('#timeout-banmsg'),
isSilent = $('#timeout-message-toggle').is(':checked'),
timeoutTime = $('#timeout-timeout-time'),
timeoutMsg = $('#timeout-reason'),
isReg = $('#exclude-regulars').is(':checked'),
isSub = $('#exclude-subscribers').is(':checked');
// Add regex prefix is regex.
if (isRegex && !phrase.val().startsWith('regex:')) {
phrase.val('regex:' + phrase.val());
}
// Handle each input to make sure they have a value.
switch (false) {
case helpers.handleInputString(phrase):
case helpers.handleInputString(banMsg):
case helpers.handleInputString(timeoutTime): // Handle as string even if it's a number.
case helpers.handleInputString(timeoutMsg):
break;
default:
// Add the blacklist.
socket.updateDBValue('add_moderation_blacklist', 'blackList', phrase.val(), JSON.stringify({
id: 'panel_' + phrase.val(),
timeout: timeoutTime.val(),
isRegex: isRegex,
phrase: phrase.val(),
isSilent: isSilent,
excludeRegulars: isReg,
excludeSubscribers: isSub,
message: banMsg.val(),
banReason: timeoutMsg.val()
}), function() {
socket.sendCommand('moderation_blacklist_reload_cmd', 'reloadmod', function() {
// Update the table.
run();
// Close the modal.
$('#blacklist-add-modal').modal('hide');
// Alert the user.
toastr.success('Successfully added blacklist!');
});
});
}
}).modal('toggle');
});
});

View File

@@ -0,0 +1,865 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Function that querys all of the data we need.
$(function() {
// Get filter toggles.
socket.getDBValues('moderation_get_toggles', {
tables: ['chatModerator', 'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator'],
keys: ['linksToggle', 'capsToggle', 'spamToggle', 'symbolsToggle', 'emotesToggle', 'longMessageToggle', 'colorsToggle', 'spamTrackerToggle', 'fakePurgeToggle']
}, true, function(e) {
// Set the links filter toggle.
$('#filter-links').prop('checked', e.linksToggle === 'true');
// Set the caps filter toggle.
$('#filter-caps').prop('checked', e.capsToggle === 'true');
// Set the spam filter toggle.
$('#filter-spam').prop('checked', e.spamToggle === 'true');
// Set the symbols filter toggle.
$('#filter-symbols').prop('checked', e.symbolsToggle === 'true');
// Set the emotes filter toggle.
$('#filter-emotes').prop('checked', e.emotesToggle === 'true');
// Set the long messages filter toggle.
$('#filter-messages').prop('checked', e.longMessageToggle === 'true');
// Set the colors filter toggle.
$('#filter-me').prop('checked', e.colorsToggle === 'true');
// Set the spam tracker filter toggle.
$('#filter-tracker').prop('checked', e.spamTrackerToggle === 'true');
// Set the fake purges filter toggle.
$('#filter-purges').prop('checked', e.fakePurgeToggle === 'true');
});
});
// Function that handles setting events.
$(function() {
// Filter toggle click.
$('[data-filter]').on('change', function() {
// Update the db with the new toggle.
socket.updateDBValue('moderation_update_filter', 'chatModerator', $(this).data('filter'), $(this).is(':checked'), function() {
socket.sendCommand('moderation_update_filter_cmd', 'reloadmod', function() {
toastr.success('Filter toggle successfully updated!');
});
});
});
// Cluster begins here.
// Handle link filter settings.
$('#filter-links-btn').on('click', function() {
// Get link filter settings.
socket.getDBValues('moderation_get_link_settings', {
tables: ['chatModerator', 'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator'],
keys: ['linksMessage', 'linkPermitTime', 'subscribersModerateLinks', 'regularsModerateLinks', 'silentTimeoutLinks', 'silentLinkMessage', 'warningTimeLinks', 'timeoutTimeLinks']
}, true, function(e) {
// Get advance modal from our util functions in /utils/helpers.js
helpers.getAdvanceModal('link-settings', 'Link Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Append input box for the command name. This one is disabled.
.append(helpers.getInputGroup('timeout-message', 'text', 'Warning Message', '', e.linksMessage, 'Message said in chat when a user gets timed-out.')
// Append checkbox for if this message should be enabled.
.append(helpers.getCheckBox('timeout-message-toggle', e.silentTimeoutLinks === 'true', 'Silent', 'If the warning message should be said or not.')))
// Append input box for the warning time.
.append(helpers.getInputGroup('timeout-warning-time', 'number', 'Warning Duration (Seconds)', '0', e.warningTimeLinks,
'How long in seconds the user gets timed-out for on his first offence. 0 seconds will just delete the last message.'))
// Append input box for the timeout time.
.append(helpers.getInputGroup('timeout-timeout-time', 'number', 'Timeout Duration (Seconds)', '0', e.timeoutTimeLinks,
'How long in seconds the user gets timed-out for on his last offence. 0 seconds will just delete the last message.'))
// Add an advance section that can be opened with a button toggle.
.append($('<div/>', {
'class': 'collapse',
'id': 'advance-collapse',
'style': 'margin-top: 10px;',
'html': $('<form/>', {
'role': 'form'
})
// Append ban reason. This is the message Twitch shows with the timeout.
.append(helpers.getInputGroup('timeout-banmsg', 'text', 'Timeout Reason', '', e.silentLinkMessage,
'Message shown to all moderators when the user gets timed-out.'))
// Append input box for the permit time.
.append(helpers.getInputGroup('permit-time', 'number', 'Permit Duration', '0', e.linkPermitTime,
'How long in seconds a user has to post a link when permitted.'))
// Add group for toggles.
.append($('<div/>', {
'class': 'form-group'
})
// Tooltip to toggle for regulars to bypass this filter.
.append(helpers.getCheckBox('exclude-regulars', e.regularsModerateLinks !== 'true', 'Exclude Regulars',
'If regulars should be allowed to bypass this filter.'))
// Tooltip to toggle for subs to bypass this filter.
.append(helpers.getCheckBox('exclude-subscribers', e.subscribersModerateLinks !== 'true', 'Exclude Subscribers',
'If subscribers should be allowed to bypass this filter.')))
// Callback function to be called once we hit the save button on the modal.
})), function() {
let timeoutMessage = $('#timeout-message'),
timeoutMessageToggle = $('#timeout-message-toggle').is(':checked') === true,
warningTime = $('#timeout-warning-time'),
timeoutTime = $('#timeout-timeout-time'),
timeoutReason = $('#timeout-banmsg'),
permitTime = $('#permit-time'),
isReg = $('#exclude-regulars').is(':checked') !== true,
isSub = $('#exclude-subscribers').is(':checked') !== true;
// Handle each input to make sure they have a value.
switch (false) {
case helpers.handleInputString(timeoutMessage):
case helpers.handleInputNumber(warningTime):
case helpers.handleInputNumber(timeoutTime):
case helpers.handleInputString(timeoutReason):
case helpers.handleInputNumber(permitTime):
break;
default:
// Update moderation settings.
socket.updateDBValues('moderation_update_links', {
tables: ['chatModerator', 'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator',
'chatModerator', 'chatModerator', 'chatModerator'],
keys: ['linksMessage', 'linkPermitTime', 'subscribersModerateLinks', 'regularsModerateLinks', 'silentTimeoutLinks',
'silentLinkMessage', 'warningTimeLinks', 'timeoutTimeLinks'],
values: [timeoutMessage.val(), permitTime.val(), isSub, isReg, timeoutMessageToggle, timeoutReason.val(), warningTime.val(), timeoutTime.val()]
}, function() {
socket.sendCommand('moderation_update_filter_cmd', 'reloadmod', function() {
// Hide modal
$('#link-settings').modal('hide');
// Let the user know.
toastr.success('Successfully updated the link filter settings!');
});
});
}
}).modal('toggle');
});
});
// Handle caps filter settings.
$('#filter-caps-btn').on('click', function() {
// Get caps filter settings.
socket.getDBValues('moderation_get_caps_settings', {
tables: ['chatModerator', 'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator',
'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator'],
keys: ['capsMessage', 'capsLimitPercent', 'capsTriggerLength', 'subscribersModerateCaps',
'regularsModerateCaps', 'silentTimeoutCaps', 'silentCapMessage', 'warningTimeCaps', 'timeoutTimeCaps']
}, true, function(e) {
// Get advance modal from our util functions in /utils/helpers.js
helpers.getAdvanceModal('caps-settings', 'Caps Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Append input box for the command name. This one is disabled.
.append(helpers.getInputGroup('timeout-message', 'text', 'Warning Message', '', e.capsMessage, 'Message said in chat when a user gets timed-out.')
// Append checkbox for if this message should be enabled.
.append(helpers.getCheckBox('timeout-message-toggle', e.silentTimeoutCaps === 'true', 'Silent', 'If the warning message should be said or not.')))
// Append input box for the warning time.
.append(helpers.getInputGroup('timeout-warning-time', 'number', 'Warning Duration (Seconds)', '0', e.warningTimeCaps,
'How long in seconds the user gets timed-out for on his first offence. 0 seconds will just delete the last message.'))
// Append input box for the timeout time.
.append(helpers.getInputGroup('timeout-timeout-time', 'number', 'Timeout Duration (Seconds)', '0', e.timeoutTimeCaps,
'How long in seconds the user gets timed-out for on his last offence. 0 seconds will just delete the last message.'))
// Add an advance section that can be opened with a button toggle.
.append($('<div/>', {
'class': 'collapse',
'id': 'advance-collapse',
'style': 'margin-top: 10px;',
'html': $('<form/>', {
'role': 'form'
})
// Append ban reason. This is the message Twitch shows with the timeout.
.append(helpers.getInputGroup('timeout-banmsg', 'text', 'Timeout Reason', '', e.silentCapMessage,
'Message shown to all moderators when the user gets timed-out.'))
// Append input box for amount of caps required before checking.
.append(helpers.getInputGroup('caps-trigger-amount', 'number', 'Caps Trigger Amount', '0', e.capsTriggerLength,
'Amount of caps required in the message before checking for caps.'))
// Append input box for the max caps percent
.append(helpers.getInputGroup('caps-amount', 'number', 'Caps Limit Percent', '0', e.capsLimitPercent,
'Maximum amount in percent of caps allowed in a message.'))
// Add group for toggles.
.append($('<div/>', {
'class': 'form-group'
})
// Tooltip to toggle for regulars to bypass this filter.
.append(helpers.getCheckBox('exclude-regulars', e.regularsModerateCaps !== 'true', 'Exclude Regulars',
'If regulars should be allowed to bypass this filter.'))
// Tooltip to toggle for subs to bypass this filter.
.append(helpers.getCheckBox('exclude-subscribers', e.subscribersModerateCaps !== 'true', 'Exclude Subscribers',
'If subscribers should be allowed to bypass this filter.')))
// Callback function to be called once we hit the save button on the modal.
})), function() {
let timeoutMessage = $('#timeout-message'),
timeoutMessageToggle = $('#timeout-message-toggle').is(':checked') === true,
warningTime = $('#timeout-warning-time'),
timeoutTime = $('#timeout-timeout-time'),
timeoutReason = $('#timeout-banmsg'),
capsTrigger = $('#caps-trigger-amount'),
capsLimit = $('#caps-amount'),
isReg = $('#exclude-regulars').is(':checked') !== true,
isSub = $('#exclude-subscribers').is(':checked') !== true;
// Handle each input to make sure they have a value.
switch (false) {
case helpers.handleInputString(timeoutMessage):
case helpers.handleInputNumber(warningTime):
case helpers.handleInputNumber(timeoutTime):
case helpers.handleInputString(timeoutReason):
case helpers.handleInputNumber(capsTrigger):
case helpers.handleInputNumber(capsLimit):
break;
default:
// Update moderation settings.
socket.updateDBValues('moderation_update_caps', {
tables: ['chatModerator', 'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator',
'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator'],
keys: ['capsMessage', 'capsLimitPercent', 'capsTriggerLength', 'subscribersModerateCaps',
'regularsModerateCaps', 'silentTimeoutCaps', 'silentCapMessage', 'warningTimeCaps', 'timeoutTimeCaps'],
values: [timeoutMessage.val(), capsLimit.val(), capsTrigger.val(), isSub, isReg, timeoutMessageToggle,
timeoutReason.val(), warningTime.val(), timeoutTime.val()]
}, function() {
socket.sendCommand('moderation_update_filter_cmd', 'reloadmod', function() {
// Hide modal
$('#caps-settings').modal('hide');
// Let the user know.
toastr.success('Successfully updated the caps filter settings!');
});
});
}
}).modal('toggle');
});
});
// Handle symbols filter settings.
$('#filter-symbols-btn').on('click', function() {
// Get symbols filter settings.
socket.getDBValues('moderation_get_symbols_settings', {
tables: ['chatModerator', 'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator',
'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator'],
keys: ['symbolsMessage', 'symbolsLimitPercent', 'symbolsGroupLimit', 'symbolsTriggerLength',
'subscribersModerateSymbols', 'regularsModerateSymbols', 'silentTimeoutSymbols', 'silentSymbolsMessage', 'warningTimeSymbols', 'timeoutTimeSymbols']
}, true, function(e) {
// Get advance modal from our util functions in /utils/helpers.js
helpers.getAdvanceModal('symbols-settings', 'Symbols Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Append input box for the command name. This one is disabled.
.append(helpers.getInputGroup('timeout-message', 'text', 'Warning Message', '', e.symbolsMessage, 'Message said in chat when a user gets timed-out.')
// Append checkbox for if this message should be enabled.
.append(helpers.getCheckBox('timeout-message-toggle', e.silentTimeoutSymbols === 'true', 'Silent', 'If the warning message should be said or not.')))
// Append input box for the warning time.
.append(helpers.getInputGroup('timeout-warning-time', 'number', 'Warning Duration (Seconds)', '0', e.warningTimeSymbols,
'How long in seconds the user gets timed-out for on his first offence. 0 seconds will just delete the last message.'))
// Append input box for the timeout time.
.append(helpers.getInputGroup('timeout-timeout-time', 'number', 'Timeout Duration (Seconds)', '0', e.timeoutTimeSymbols,
'How long in seconds the user gets timed-out for on his last offence. 0 seconds will just delete the last message.'))
// Add an advance section that can be opened with a button toggle.
.append($('<div/>', {
'class': 'collapse',
'id': 'advance-collapse',
'style': 'margin-top: 10px;',
'html': $('<form/>', {
'role': 'form'
})
// Append ban reason. This is the message Twitch shows with the timeout.
.append(helpers.getInputGroup('timeout-banmsg', 'text', 'Timeout Reason', '', e.silentSymbolsMessage,
'Message shown to all moderators when the user gets timed-out.'))
// Append input box for amount of symbols required before checking.
.append(helpers.getInputGroup('symbols-trigger-amount', 'number', 'Symbols Trigger Amount', '0', e.symbolsTriggerLength,
'Amount of symbols required in the message before checking for symbols.'))
// Append input box for the max symbols percent.
.append(helpers.getInputGroup('symbols-amount', 'number', 'Symbols Limit Percent', '0', e.symbolsLimitPercent,
'Maximum amount in percent of symbols allowed in a message.'))
// Append input box for the max groupped symbols.
.append(helpers.getInputGroup('symbols-amount-group', 'number', 'Symbols Group Limit', '0', e.symbolsGroupLimit,
'Maximum amount of groupped symbols allowed.'))
// Add group for toggles.
.append($('<div/>', {
'class': 'form-group'
})
// Tooltip to toggle for subs to bypass this filter.
.append(helpers.getCheckBox('exclude-regulars', e.regularsModerateSymbols !== 'true', 'Exclude Regulars',
'If regulars should be allowed to bypass this filter.'))
// Tooltip to toggle for subs to bypass this filter.
.append(helpers.getCheckBox('exclude-subscribers', e.subscribersModerateSymbols !== 'true', 'Exclude Subscribers',
'If subscribers should be allowed to bypass this filter.')))
// Callback function to be called once we hit the save button on the modal.
})), function() {
let timeoutMessage = $('#timeout-message'),
timeoutMessageToggle = $('#timeout-message-toggle').is(':checked') === true,
warningTime = $('#timeout-warning-time'),
timeoutTime = $('#timeout-timeout-time'),
timeoutReason = $('#timeout-banmsg'),
symbolsTrigger = $('#symbols-trigger-amount'),
symbolsLimit = $('#symbols-amount'),
symbolsLimitGroup = $('#symbols-amount-group'),
isReg = $('#exclude-regulars').is(':checked') !== true,
isSub = $('#exclude-subscribers').is(':checked') !== true;
// Handle each input to make sure they have a value.
switch (false) {
case helpers.handleInputString(timeoutMessage):
case helpers.handleInputNumber(warningTime):
case helpers.handleInputNumber(timeoutTime):
case helpers.handleInputString(timeoutReason):
case helpers.handleInputNumber(symbolsTrigger):
case helpers.handleInputNumber(symbolsLimit):
case helpers.handleInputNumber(symbolsLimitGroup):
break;
default:
// Update moderation settings.
socket.updateDBValues('moderation_update_symbols', {
tables: ['chatModerator', 'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator',
'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator'],
keys: ['symbolsMessage', 'symbolsLimitPercent', 'symbolsGroupLimit', 'symbolsTriggerLength',
'subscribersModerateSymbols', 'regularsModerateSymbols', 'silentTimeoutSymbols', 'silentSymbolsMessage', 'warningTimeSymbols', 'timeoutTimeSymbols'],
values: [timeoutMessage.val(), symbolsLimit.val(), symbolsLimitGroup.val(), symbolsTrigger.val(),
isSub, isReg, timeoutMessageToggle, timeoutReason.val(), warningTime.val(), timeoutTime.val()]
}, function() {
socket.sendCommand('moderation_update_filter_cmd', 'reloadmod', function() {
// Hide modal
$('#symbols-settings').modal('hide');
// Let the user know.
toastr.success('Successfully updated the symbols filter settings!');
});
});
}
}).modal('toggle');
});
});
// Handle spam filter settings.
$('#filter-spam-btn').on('click', function() {
// Get spam filter settings.
socket.getDBValues('moderation_get_spam_settings', {
tables: ['chatModerator', 'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator',
'chatModerator', 'chatModerator', 'chatModerator'],
keys: ['spamMessage', 'spamLimit', 'subscribersModerateSpam', 'regularsModerateSpam',
'silentTimeoutSpam', 'silentSpamMessage', 'warningTimeSpam', 'timeoutTimeSpam']
}, true, function(e) {
// Get advance modal from our util functions in /utils/helpers.js
helpers.getAdvanceModal('spam-settings', 'Spam Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Append input box for the command name. This one is disabled.
.append(helpers.getInputGroup('timeout-message', 'text', 'Warning Message', '', e.spamMessage,
'Message said in chat when a user gets timed-out.')
// Append checkbox for if this message should be enabled.
.append(helpers.getCheckBox('timeout-message-toggle', e.silentTimeoutSpam === 'true', 'Silent',
'If the warning message should be said or not.')))
// Append input box for the warning time.
.append(helpers.getInputGroup('timeout-warning-time', 'number', 'Warning Duration (Seconds)', '0', e.warningTimeSpam,
'How long in seconds the user gets timed-out for on his first offence. 0 seconds will just delete the last message.'))
// Append input box for the timeout time.
.append(helpers.getInputGroup('timeout-timeout-time', 'number', 'Timeout Duration (Seconds)', '0', e.timeoutTimeSpam,
'How long in seconds the user gets timed-out for on his last offence. 0 seconds will just delete the last message.'))
// Add an advance section that can be opened with a button toggle.
.append($('<div/>', {
'class': 'collapse',
'id': 'advance-collapse',
'style': 'margin-top: 10px;',
'html': $('<form/>', {
'role': 'form'
})
// Append ban reason. This is the message Twitch shows with the timeout.
.append(helpers.getInputGroup('timeout-banmsg', 'text', 'Timeout Reason', '', e.silentSpamMessage,
'Message shown to all moderators when the user gets timed-out.'))
// Append input box for amount of caps required before checking.
.append(helpers.getInputGroup('spam-amount', 'number', 'Spam Limit', '0', e.spamLimit,
'Amount of repeating characters allowed in a message.'))
// Add group for toggles.
.append($('<div/>', {
'class': 'form-group'
})
// Tooltip to toggle for regulars to bypass this filter.
.append(helpers.getCheckBox('exclude-regulars', e.regularsModerateSpam !== 'true', 'Exclude Regulars',
'If regulars should be allowed to bypass this filter.'))
// Tooltip to toggle for subs to bypass this filter.
.append(helpers.getCheckBox('exclude-subscribers', e.subscribersModerateSpam !== 'true', 'Exclude Subscribers',
'If subscribers should be allowed to bypass this filter.')))
// Callback function to be called once we hit the save button on the modal.
})), function() {
let timeoutMessage = $('#timeout-message'),
timeoutMessageToggle = $('#timeout-message-toggle').is(':checked') === true,
warningTime = $('#timeout-warning-time'),
timeoutTime = $('#timeout-timeout-time'),
timeoutReason = $('#timeout-banmsg'),
spamLimit = $('#spam-amount'),
isReg = $('#exclude-regulars').is(':checked') !== true,
isSub = $('#exclude-subscribers').is(':checked') !== true;
// Handle each input to make sure they have a value.
switch (false) {
case helpers.handleInputString(timeoutMessage):
case helpers.handleInputNumber(warningTime):
case helpers.handleInputNumber(timeoutTime):
case helpers.handleInputString(timeoutReason):
case helpers.handleInputNumber(spamLimit):
break;
default:
// Update moderation settings.
socket.updateDBValues('moderation_update_spam', {
tables: ['chatModerator', 'chatModerator', 'chatModerator', 'chatModerator',
'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator'],
keys: ['spamMessage', 'spamLimit', 'subscribersModerateSpam', 'regularsModerateSpam',
'silentTimeoutSpam', 'silentSpamMessage', 'warningTimeSpam', 'timeoutTimeSpam'],
values: [timeoutMessage.val(), spamLimit.val(), isSub, isReg, timeoutMessageToggle,
timeoutReason.val(), warningTime.val(), timeoutTime.val()]
}, function() {
socket.sendCommand('moderation_update_filter_cmd', 'reloadmod', function() {
// Hide modal
$('#spam-settings').modal('hide');
// Let the user know.
toastr.success('Successfully updated the spam filter settings!');
});
});
}
}).modal('toggle');
});
});
// Handle emotes filter settings.
$('#filter-emotes-btn').on('click', function() {
// Get emotes filter settings.
socket.getDBValues('moderation_get_emotes_settings', {
tables: ['chatModerator', 'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator',
'chatModerator', 'chatModerator', 'chatModerator'],
keys: ['emotesMessage', 'emotesLimit', 'subscribersModerateEmotes',
'regularsModerateEmotes', 'silentTimeoutEmotes', 'silentEmoteMessage', 'warningTimeEmotes', 'timeoutTimeEmotes']
}, true, function(e) {
// Get advance modal from our util functions in /utils/helpers.js
helpers.getAdvanceModal('emotes-settings', 'Emotes Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Append input box for the command name. This one is disabled.
.append(helpers.getInputGroup('timeout-message', 'text', 'Warning Message', '', e.emotesMessage,
'Message said in chat when a user gets timed-out.')
// Append checkbox for if this message should be enabled.
.append(helpers.getCheckBox('timeout-message-toggle', e.silentTimeoutEmotes === 'true', 'Silent',
'If the warning message should be said or not.')))
// Append input box for the warning time.
.append(helpers.getInputGroup('timeout-warning-time', 'number', 'Warning Duration (Seconds)', '0', e.warningTimeEmotes,
'How long in seconds the user gets timed-out for on his first offence. 0 seconds will just delete the last message.'))
// Append input box for the timeout time.
.append(helpers.getInputGroup('timeout-timeout-time', 'number', 'Timeout Duration (Seconds)', '0', e.timeoutTimeEmotes,
'How long in seconds the user gets timed-out for on his last offence. 0 seconds will just delete the last message.'))
// Add an advance section that can be opened with a button toggle.
.append($('<div/>', {
'class': 'collapse',
'id': 'advance-collapse',
'style': 'margin-top: 10px;',
'html': $('<form/>', {
'role': 'form'
})
// Append ban reason. This is the message Twitch shows with the timeout.
.append(helpers.getInputGroup('timeout-banmsg', 'text', 'Timeout Reason', '', e.silentEmoteMessage,
'Message shown to all moderators when the user gets timed-out.'))
// Append input box for amount of caps required before checking.
.append(helpers.getInputGroup('emote-amount', 'number', 'Emote Limit', '0', e.emotesLimit,
'Amount of emotes allowed in a message.'))
// Add group for toggles.
.append($('<div/>', {
'class': 'form-group'
})
// Tooltip to toggle for regulars to bypass this filter.
.append(helpers.getCheckBox('exclude-regulars', e.regularsModerateEmotes !== 'true', 'Exclude Regulars',
'If regulars should be allowed to bypass this filter.'))
// Tooltip to toggle for subs to bypass this filter.
.append(helpers.getCheckBox('exclude-subscribers', e.subscribersModerateEmotes !== 'true', 'Exclude Subscribers',
'If subscribers should be allowed to bypass this filter.')))
// Callback function to be called once we hit the save button on the modal.
})), function() {
let timeoutMessage = $('#timeout-message'),
timeoutMessageToggle = $('#timeout-message-toggle').is(':checked') === true,
warningTime = $('#timeout-warning-time'),
timeoutTime = $('#timeout-timeout-time'),
timeoutReason = $('#timeout-banmsg'),
emoteLimit = $('#emote-amount'),
isReg = $('#exclude-regulars').is(':checked') !== true,
isSub = $('#exclude-subscribers').is(':checked') !== true;
// Handle each input to make sure they have a value.
switch (false) {
case helpers.handleInputString(timeoutMessage):
case helpers.handleInputNumber(warningTime):
case helpers.handleInputNumber(timeoutTime):
case helpers.handleInputString(timeoutReason):
case helpers.handleInputNumber(emoteLimit):
break;
default:
// Update moderation settings.
socket.updateDBValues('moderation_update_emotes', {
tables: ['chatModerator', 'chatModerator', 'chatModerator', 'chatModerator',
'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator'],
keys: ['emotesMessage', 'emotesLimit', 'subscribersModerateEmotes',
'regularsModerateEmotes', 'silentTimeoutEmotes', 'silentEmoteMessage', 'warningTimeEmotes', 'timeoutTimeEmotes'],
values: [timeoutMessage.val(), emoteLimit.val(), isSub, isReg, timeoutMessageToggle,
timeoutReason.val(), warningTime.val(), timeoutTime.val()]
}, function() {
socket.sendCommand('moderation_update_filter_cmd', 'reloadmod', function() {
// Hide modal
$('#emotes-settings').modal('hide');
// Let the user know.
toastr.success('Successfully updated the emotes filter settings!');
});
});
}
}).modal('toggle');
});
});
// Handle me filter settings.
$('#filter-me-btn').on('click', function() {
// Get me filter settings.
socket.getDBValues('moderation_get_me_settings', {
tables: ['chatModerator', 'chatModerator', 'chatModerator', 'chatModerator',
'chatModerator', 'chatModerator', 'chatModerator'],
keys: ['colorsMessage', 'subscribersModerateColors', 'regularsModerateColors',
'silentTimeoutColors', 'silentColorMessage', 'warningTimeColors', 'timeoutTimeColors']
}, true, function(e) {
// Get advance modal from our util functions in /utils/helpers.js
helpers.getAdvanceModal('me-settings', 'Me Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Append input box for the command name. This one is disabled.
.append(helpers.getInputGroup('timeout-message', 'text', 'Warning Message', '', e.colorsMessage,
'Message said in chat when a user gets timed-out.')
// Append checkbox for if this message should be enabled.
.append(helpers.getCheckBox('timeout-message-toggle', e.silentTimeoutColors === 'true', 'Silent',
'If the warning message should be said or not.')))
// Append input box for the warning time.
.append(helpers.getInputGroup('timeout-warning-time', 'number', 'Warning Duration (Seconds)', '0', e.warningTimeColors,
'How long in seconds the user gets timed-out for on his first offence. 0 seconds will just delete the last message.'))
// Append input box for the timeout time.
.append(helpers.getInputGroup('timeout-timeout-time', 'number', 'Timeout Duration (Seconds)', '0', e.timeoutTimeColors,
'How long in seconds the user gets timed-out for on his last offence. 0 seconds will just delete the last message.'))
// Add an advance section that can be opened with a button toggle.
.append($('<div/>', {
'class': 'collapse',
'id': 'advance-collapse',
'style': 'margin-top: 10px;',
'html': $('<form/>', {
'role': 'form'
})
// Append ban reason. This is the message Twitch shows with the timeout.
.append(helpers.getInputGroup('timeout-banmsg', 'text', 'Timeout Reason', '', e.silentColorMessage,
'Message shown to all moderators when the user gets timed-out.'))
// Add group for toggles.
.append($('<div/>', {
'class': 'form-group'
})
// Tooltip to toggle for regulars to bypass this filter.
.append(helpers.getCheckBox('exclude-regulars', e.regularsModerateColors !== 'true', 'Exclude Regulars',
'If regulars should be allowed to bypass this filter.'))
// Tooltip to toggle for subs to bypass this filter.
.append(helpers.getCheckBox('exclude-subscribers', e.subscribersModerateColors !== 'true', 'Exclude Subscribers',
'If subscribers should be allowed to bypass this filter.')))
// Callback function to be called once we hit the save button on the modal.
})), function() {
let timeoutMessage = $('#timeout-message'),
timeoutMessageToggle = $('#timeout-message-toggle').is(':checked') === true,
warningTime = $('#timeout-warning-time'),
timeoutTime = $('#timeout-timeout-time'),
timeoutReason = $('#timeout-banmsg'),
isReg = $('#exclude-regulars').is(':checked') !== true,
isSub = $('#exclude-subscribers').is(':checked') !== true;
// Handle each input to make sure they have a value.
switch (false) {
case helpers.handleInputString(timeoutMessage):
case helpers.handleInputNumber(warningTime):
case helpers.handleInputNumber(timeoutTime):
case helpers.handleInputString(timeoutReason):
break;
default:
// Update moderation settings.
socket.updateDBValues('moderation_update_me', {
tables: ['chatModerator', 'chatModerator', 'chatModerator', 'chatModerator',
'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator'],
keys: ['colorsMessage', 'subscribersModerateColors', 'regularsModerateColors',
'silentTimeoutColors', 'silentColorMessage', 'warningTimeColors', 'timeoutTimeColors'],
values: [timeoutMessage.val(), isSub, isReg, timeoutMessageToggle, timeoutReason.val(), warningTime.val(), timeoutTime.val()]
}, function() {
socket.sendCommand('moderation_update_filter_cmd', 'reloadmod', function() {
// Hide modal
$('#me-settings').modal('hide');
// Let the user know.
toastr.success('Successfully updated the me filter settings!');
});
});
}
}).modal('toggle');
});
});
// Handle message length filter settings.
$('#filter-msglen-btn').on('click', function() {
// Get message length filter settings.
socket.getDBValues('moderation_get_msglen_settings', {
tables: ['chatModerator', 'chatModerator', 'chatModerator', 'chatModerator',
'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator'],
keys: ['longMessageMessage', 'longMessageLimit', 'subscribersModerateLongMsg',
'regularsModerateLongMsg', 'silentTimeoutLongMsg', 'silentLongMessage', 'warningTimeLongMsg', 'timeoutTimeLongMsg']
}, true, function(e) {
// Get advance modal from our util functions in /utils/helpers.js
helpers.getAdvanceModal('msglen-settings', 'Paragraph Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Append input box for the command name. This one is disabled.
.append(helpers.getInputGroup('timeout-message', 'text', 'Warning Message', '', e.longMessageMessage,
'Message said in chat when a user gets timed-out.')
// Append checkbox for if this message should be enabled.
.append(helpers.getCheckBox('timeout-message-toggle', e.silentTimeoutLongMsg === 'true', 'Silent',
'If the warning message should be said or not.')))
// Append input box for the warning time.
.append(helpers.getInputGroup('timeout-warning-time', 'number', 'Warning Duration (Seconds)', '0', e.warningTimeLongMsg,
'How long in seconds the user gets timed-out for on his first offence. 0 seconds will just delete the last message.'))
// Append input box for the timeout time.
.append(helpers.getInputGroup('timeout-timeout-time', 'number', 'Timeout Duration (Seconds)', '0', e.timeoutTimeLongMsg,
'How long in seconds the user gets timed-out for on his last offence. 0 seconds will just delete the last message.'))
// Add an advance section that can be opened with a button toggle.
.append($('<div/>', {
'class': 'collapse',
'id': 'advance-collapse',
'style': 'margin-top: 10px;',
'html': $('<form/>', {
'role': 'form'
})
// Append ban reason. This is the message Twitch shows with the timeout.
.append(helpers.getInputGroup('timeout-banmsg', 'text', 'Timeout Reason', '', e.silentLongMessage,
'Message shown to all moderators when the user gets timed-out.'))
// Append input box for max amount of chars allowed in a message
.append(helpers.getInputGroup('msg-limit', 'number', 'Message Charcater Limit', '0', e.longMessageLimit,
'Amount of characters allowed in a message.'))
// Add group for toggles.
.append($('<div/>', {
'class': 'form-group'
})
// Tooltip to toggle for regulars to bypass this filter.
.append(helpers.getCheckBox('exclude-regulars', e.regularsModerateLongMsg !== 'true', 'Exclude Regulars',
'If regulars should be allowed to bypass this filter.'))
// Tooltip to toggle for subs to bypass this filter.
.append(helpers.getCheckBox('exclude-subscribers', e.subscribersModerateLongMsg !== 'true', 'Exclude Subscribers',
'If subscribers should be allowed to bypass this filter.')))
// Callback function to be called once we hit the save button on the modal.
})), function() {
let timeoutMessage = $('#timeout-message'),
timeoutMessageToggle = $('#timeout-message-toggle').is(':checked') === true,
warningTime = $('#timeout-warning-time'),
timeoutTime = $('#timeout-timeout-time'),
timeoutReason = $('#timeout-banmsg'),
msgLimit = $('#msg-limit'),
isReg = $('#exclude-regulars').is(':checked') !== true,
isSub = $('#exclude-subscribers').is(':checked') !== true;
// Handle each input to make sure they have a value.
switch (false) {
case helpers.handleInputString(timeoutMessage):
case helpers.handleInputNumber(warningTime):
case helpers.handleInputNumber(timeoutTime):
case helpers.handleInputString(timeoutReason):
case helpers.handleInputString(msgLimit):
break;
default:
// Update moderation settings.
socket.updateDBValues('moderation_update_longmsg', {
tables: ['chatModerator', 'chatModerator', 'chatModerator', 'chatModerator',
'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator'],
keys: ['longMessageMessage', 'longMessageLimit', 'subscribersModerateLongMsg',
'regularsModerateLongMsg', 'silentTimeoutLongMsg', 'silentLongMessage', 'warningTimeLongMsg', 'timeoutTimeLongMsg'],
values: [timeoutMessage.val(), msgLimit.val(), isSub, isReg, timeoutMessageToggle,
timeoutReason.val(), warningTime.val(), timeoutTime.val()]
}, function() {
socket.sendCommand('moderation_update_filter_cmd', 'reloadmod', function() {
// Hide modal
$('#msglen-settings').modal('hide');
// Let the user know.
toastr.success('Successfully updated the message length filter settings!');
});
});
}
}).modal('toggle');
});
});
// Handle fake purge filter settings.
$('#filter-purges-btn').on('click', function() {
// Get purges filter settings.
socket.getDBValues('moderation_get_purges_settings', {
tables: ['chatModerator', 'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator'],
keys: ['fakePurgeMessage', 'subscribersModerateFakePurge', 'regularsModerateFakePurge',
'silentTimeoutFakePurge', 'silentFakePurgeMessage', 'warningTimeFakePurge', 'timeoutTimeFakePurge']
}, true, function(e) {
// Get advance modal from our util functions in /utils/helpers.js
helpers.getAdvanceModal('purges-settings', 'Fake Purge Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Append input box for the command name. This one is disabled.
.append(helpers.getInputGroup('timeout-message', 'text', 'Warning Message', '', e.fakePurgeMessage, 'Message said in chat when a user gets timed-out.')
// Append checkbox for if this message should be enabled.
.append(helpers.getCheckBox('timeout-message-toggle', e.silentTimeoutFakePurge === 'true', 'Silent', 'If the warning message should be said or not.')))
// Append input box for the warning time.
.append(helpers.getInputGroup('timeout-warning-time', 'number', 'Warning Duration (Seconds)', '0', e.warningTimeFakePurge,
'How long in seconds the user gets timed-out for on his first offence. 0 seconds will just delete the last message.'))
// Append input box for the timeout time.
.append(helpers.getInputGroup('timeout-timeout-time', 'number', 'Timeout Duration (Seconds)', '0', e.timeoutTimeFakePurge,
'How long in seconds the user gets timed-out for on his last offence. 0 seconds will just delete the last message.'))
// Add an advance section that can be opened with a button toggle.
.append($('<div/>', {
'class': 'collapse',
'id': 'advance-collapse',
'style': 'margin-top: 10px;',
'html': $('<form/>', {
'role': 'form'
})
// Append ban reason. This is the message Twitch shows with the timeout.
.append(helpers.getInputGroup('timeout-banmsg', 'text', 'Timeout Reason', '', e.silentFakePurgeMessage,
'Message shown to all moderators when the user gets timed-out.'))
// Add group for toggles.
.append($('<div/>', {
'class': 'form-group'
})
// Tooltip to toggle for regulars to bypass this filter.
.append(helpers.getCheckBox('exclude-regulars', e.regularsModerateFakePurge !== 'true', 'Exclude Regulars',
'If regulars should be allowed to bypass this filter.'))
// Tooltip to toggle for subs to bypass this filter.
.append(helpers.getCheckBox('exclude-subscribers', e.subscribersModerateFakePurge !== 'true', 'Exclude Subscribers',
'If subscribers should be allowed to bypass this filter.')))
// Callback function to be called once we hit the save button on the modal.
})), function() {
let timeoutMessage = $('#timeout-message'),
timeoutMessageToggle = $('#timeout-message-toggle').is(':checked') === true,
warningTime = $('#timeout-warning-time'),
timeoutTime = $('#timeout-timeout-time'),
timeoutReason = $('#timeout-banmsg'),
isReg = $('#exclude-regulars').is(':checked') !== true,
isSub = $('#exclude-subscribers').is(':checked') !== true;
// Handle each input to make sure they have a value.
switch (false) {
case helpers.handleInputString(timeoutMessage):
case helpers.handleInputNumber(warningTime):
case helpers.handleInputNumber(timeoutTime):
case helpers.handleInputString(timeoutReason):
break;
default:
// Update moderation settings.
socket.updateDBValues('moderation_update_purges', {
tables: ['chatModerator', 'chatModerator', 'chatModerator', 'chatModerator',
'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator'],
keys: ['fakePurgeMessage', 'subscribersModerateFakePurge', 'regularsModerateFakePurge',
'silentTimeoutFakePurge', 'silentFakePurgeMessage', 'warningTimeFakePurge', 'timeoutTimeFakePurge'],
values: [timeoutMessage.val(), isSub, isReg, timeoutMessageToggle, timeoutReason.val(), warningTime.val(), timeoutTime.val()]
}, function() {
socket.sendCommand('moderation_update_filter_cmd', 'reloadmod', function() {
// Hide modal
$('#purges-settings').modal('hide');
// Let the user know.
toastr.success('Successfully updated the fake purge filter settings!');
});
});
}
}).modal('toggle');
});
});
// Handle tracker filter settings.
$('#filter-tracker-btn').on('click', function() {
// Get tracker length filter settings.
socket.getDBValues('moderation_get_msglen_settings', {
tables: ['chatModerator', 'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator',
'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator'],
keys: ['spamTrackerMessage', 'spamTrackerTime', 'spamTrackerLimit', 'subscribersModerateSpamTracker',
'regularsModerateSpamTracker', 'silentTimeoutSpamTracker', 'silentSpamTrackerMessage', 'warningTimeSpamTracker', 'timeoutTimeSpamTracker']
}, true, function(e) {
// Get advance modal from our util functions in /utils/helpers.js
helpers.getAdvanceModal('tracker-settings', 'User Moderation Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Append input box for the command name. This one is disabled.
.append(helpers.getInputGroup('timeout-message', 'text', 'Warning Message', '', e.spamTrackerMessage,
'Message said in chat when a user gets timed-out.')
// Append checkbox for if this message should be enabled.
.append(helpers.getCheckBox('timeout-message-toggle', e.silentTimeoutSpamTracker === 'true', 'Silent',
'If the warning message should be said or not.')))
// Append input box for the warning time.
.append(helpers.getInputGroup('timeout-warning-time', 'number', 'Warning Duration (Seconds)', '0', e.warningTimeSpamTracker,
'How long in seconds the user gets timed-out for on his first offence. 0 seconds will just delete the last message.'))
// Append input box for the timeout time.
.append(helpers.getInputGroup('timeout-timeout-time', 'number', 'Timeout Duration (Seconds)', '0', e.timeoutTimeSpamTracker,
'How long in seconds the user gets timed-out for on his last offence. 0 seconds will just delete the last message.'))
// Add an advance section that can be opened with a button toggle.
.append($('<div/>', {
'class': 'collapse',
'id': 'advance-collapse',
'style': 'margin-top: 10px;',
'html': $('<form/>', {
'role': 'form'
})
// Append ban reason. This is the message Twitch shows with the timeout.
.append(helpers.getInputGroup('timeout-banmsg', 'text', 'Timeout Reason', '', e.silentSpamTrackerMessage,
'Message shown to all moderators when the user gets timed-out.'))
// Append input box for the seconds reset time of the message caching of user.
.append(helpers.getInputGroup('track-time', 'number', 'Message Reset Time', '0', e.spamTrackerTime,
'How long until the message count the user has sent resets.'))
// Append input box for the amount of messages the user can send in the reset time.
.append(helpers.getInputGroup('track-limit', 'number', 'Message Limit', '0', e.spamTrackerLimit,
'How many messages users can send in the reset time period.'))
// Add group for toggles.
.append($('<div/>', {
'class': 'form-group'
})
// Tooltip to toggle for regulars to bypass this filter.
.append(helpers.getCheckBox('exclude-regulars', e.regularsModerateSpamTracker !== 'true', 'Exclude Regulars',
'If regulars should be allowed to bypass this filter.'))
// Tooltip to toggle for subs to bypass this filter.
.append(helpers.getCheckBox('exclude-subscribers', e.subscribersModerateSpamTracker !== 'true', 'Exclude Subscribers',
'If subscribers should be allowed to bypass this filter.')))
// Callback function to be called once we hit the save button on the modal.
})), function() {
let timeoutMessage = $('#timeout-message'),
timeoutMessageToggle = $('#timeout-message-toggle').is(':checked') === true,
warningTime = $('#timeout-warning-time'),
timeoutTime = $('#timeout-timeout-time'),
timeoutReason = $('#timeout-banmsg'),
trackTime = $('#track-time'),
trackLimit = $('#track-limit'),
isReg = $('#exclude-regulars').is(':checked') !== true,
isSub = $('#exclude-subscribers').is(':checked') !== true;
// Handle each input to make sure they have a value.
switch (false) {
case helpers.handleInputString(timeoutMessage):
case helpers.handleInputNumber(warningTime):
case helpers.handleInputNumber(timeoutTime):
case helpers.handleInputString(timeoutReason):
case helpers.handleInputString(trackTime):
case helpers.handleInputString(trackLimit):
break;
default:
// Update moderation settings.
socket.updateDBValues('moderation_update_tracker', {
tables: ['chatModerator', 'chatModerator', 'chatModerator',
'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator', 'chatModerator'],
keys: ['spamTrackerMessage', 'spamTrackerTime', 'spamTrackerLimit',
'subscribersModerateSpamTracker', 'regularsModerateSpamTracker', 'silentTimeoutSpamTracker', 'silentSpamTrackerMessage', 'warningTimeSpamTracker', 'timeoutTimeSpamTracker'],
values: [timeoutMessage.val(), trackTime.val(), trackLimit.val(), isSub, isReg,
timeoutMessageToggle, timeoutReason.val(), warningTime.val(), timeoutTime.val()]
}, function() {
socket.sendCommand('moderation_update_filter_cmd', 'reloadmod', function() {
// Hide modal
$('#tracker-settings').modal('hide');
// Let the user know.
toastr.success('Successfully updated the user moderation filter settings!');
});
});
}
}).modal('toggle');
});
});
});

View File

@@ -0,0 +1,158 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Function that querys all of the data we need.
$(run = function() {
// Query whitelist.
socket.getDBTableValues('moderation_whitelist_get', 'whiteList', function(results) {
let tableData = [];
for (let i = 0; i < results.length; i++) {
tableData.push([
results[i].key,
$('<div/>', {
'class': 'btn-group'
}).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-danger',
'style': 'float: right',
'data-whitelist': results[i].key,
'html': $('<i/>', {
'class': 'fa fa-trash'
})
})).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-warning',
'style': 'float: right',
'data-whitelist': results[i].key,
'html': $('<i/>', {
'class': 'fa fa-edit'
})
})).html()
]);
}
// if the table exists, destroy it.
if ($.fn.DataTable.isDataTable('#whitelistTable')) {
$('#whitelistTable').DataTable().destroy();
// Remove all of the old events.
$('#whitelistTable').off();
}
// Create table.
let table = $('#whitelistTable').DataTable({
'searching': true,
'autoWidth': false,
'lengthChange': false,
'data': tableData,
'columnDefs': [
{ 'className': 'default-table', 'orderable': false, 'targets': 1 }
],
'columns': [
{ 'title': 'Whitelist' },
{ 'title': 'Actions' }
]
});
// On delete button.
table.on('click', '.btn-danger', function() {
let whitelist = $(this).data('whitelist'),
row = $(this).parents('tr');
// Ask the user if he wants to delete the blacklist.
helpers.getConfirmDeleteModal('blacklist_modal_remove', 'Are you sure you want to remove this whitelist?', true,
'The whitelist has been successfully removed!', function() { // Callback if the user clicks delete.
// Delete all information about the alias.
socket.removeDBValue('whitelist_remove', 'whiteList', whitelist, function() {
socket.sendCommand('whitelist_remove_cmd', 'reloadmod', function() {
// Remove the table row.
table.row(row).remove().draw(false);
});
});
});
});
// On edit button.
table.on('click', '.btn-warning', function() {
let whitelist = $(this).data('whitelist'),
t = $(this);
helpers.getModal('edit-whitelist', 'Edit Whitelist', 'Save', $('<form/>', {
'role': 'form'
})
// Append box for the whitelist.
.append(helpers.getInputGroup('whitelist-name', 'text', 'Url', '', whitelist, 'Url that is whitelisted.')), function() {
let w = $('#whitelist-name');
// Handle each input to make sure they have a value.
switch (false) {
case helpers.handleInputString(w):
break;
default:
// Delete old whitelist.
socket.removeDBValue('whitelist_remove', 'whiteList', whitelist, function() {
// Add the whitelist
socket.updateDBValue('whitelist_edit', 'whiteList', w.val().toLowerCase(), 'true', function() {
// Reload the script cache.
socket.sendCommand('whitelist_remove_cmd', 'reloadmod', function() {
// Edit the table row.
t.parents('tr').find('td:eq(0)').text(w.val());
// Close the modal.
$('#edit-whitelist').modal('hide');
// Alert the user.
toastr.success('Successfully edited whitelist!');
});
});
});
}
}).modal('toggle');
});
});
});
// Function that handlers the loading of events.
$(function() {
// Add whitelist button.
$('#add-whitelist-button').on('click', function() {
helpers.getModal('add-whitelist', 'Add Whitelist', 'Save', $('<form/>', {
'role': 'form'
})
// Append box for the whitelist.
.append(helpers.getInputGroup('whitelist-name', 'text', 'Url', 'https://phantombot.github.io/PhantomBot', '', 'Url that will be whitelisted.')), function() {
let whitelist = $('#whitelist-name');
// Handle each input to make sure they have a value.
switch (false) {
case helpers.handleInputString(whitelist):
break;
default:
// Add the whitelist
socket.updateDBValue('whitelist_add', 'whiteList', whitelist.val().toLowerCase(), 'true', function() {
// Reload the script cache.
socket.sendCommand('whitelist_add_cmd', 'reloadmod', function() {
// Reload the table.
run();
// Close the modal.
$('#add-whitelist').modal('hide');
// Alert the user.
toastr.success('Successfully added whitelist!');
});
});
}
}).modal('toggle');
});
});

View File

@@ -0,0 +1,170 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Function that querys all of the data we need.
$(run = function() {
// Query permissions.
socket.getDBTableValues('permissions_get_group', 'group', function(results) {
let tableData = [];
for (let i = 0; i < results.length; i++) {
// Ignore viewers.
if (results[i].value === '7') {
continue;
}
tableData.push([
results[i].key,
helpers.getGroupNameById(results[i].value),
$('<div/>', {
'class': 'btn-group'
}).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-danger',
'style': 'float: right',
'data-toggle': 'tooltip',
'title': 'This will reset the user\'s permission back to viewer. Viewers aren\'t shown in this list',
'data-username': results[i].key,
'html': $('<i/>', {
'class': 'fa fa-trash'
})
})).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-warning',
'style': 'float: right',
'data-username': results[i].key,
'html': $('<i/>', {
'class': 'fa fa-edit'
})
})).html()
]);
}
// if the table exists, destroy it.
if ($.fn.DataTable.isDataTable('#permissionsTable')) {
$('#permissionsTable').DataTable().destroy();
// Remove all of the old events.
$('#permissionsTable').off();
}
// Create table.
let table = $('#permissionsTable').DataTable({
'searching': true,
'autoWidth': false,
'lengthChange': false,
'data': tableData,
'columnDefs': [
{ 'className': 'default-table', 'orderable': false, 'targets': 2 },
{ 'width': '45%', 'targets': 0 }
],
'columns': [
{ 'title': 'User' },
{ 'title': 'Permission' },
{ 'title': 'Actions' }
]
});
// On delete button.
table.on('click', '.btn-danger', function() {
let username = $(this).data('username'),
row = $(this).parents('tr'),
t = $(this);
// Ask the user if he wants to reset the user's permission.
helpers.getConfirmDeleteModal('user_permission_modal_remove', 'Are you sure you want to reset ' + username + '\'s permissions to Viewer?', false,
username + '\'s permissions have been reset to Viewer!', function() {
// Delete all information about the alias.
socket.removeDBValue('permission_remove', 'group', username, function() {
socket.sendCommand('permission_remove_cmd', 'permissionsetuser ' + username + ' 7', function() {
// Hide tooltip.
t.tooltip('hide');
// Remove the table row.
table.row(row).remove().draw(false);
});
});
});
});
// On edit button.
table.on('click', '.btn-warning', function() {
let username = $(this).data('username'),
t = $(this);
socket.getDBValue('permission_user_get', 'group', username, function(e) {
helpers.getModal('edit-user-perm', 'Edit User Permission', 'Save', $('<form/>', {
'role': 'form'
})
// Append user name.
.append(helpers.getInputGroup('user-name', 'text', 'Username', '', username, 'Name of the user. This cannot be edited.', true))
// Append the group.
.append(helpers.getDropdownGroup('user-permission', 'Permission', helpers.getGroupNameById(e.group),
['Caster', 'Administrators', 'Moderators', 'Subscribers', 'Donators', 'VIPs', 'Regulars'])),
// callback once the user hits save.
function() {
let group = helpers.getGroupIdByName($('#user-permission').find(':selected').text());
socket.updateDBValue('permission_user_update', 'group', username, group, function() {
socket.sendCommand('permission_edit_cmd', 'permissionsetuser ' + username + ' ' + group, function() {
// Update the table.
t.parents('tr').find('td:eq(1)').text($('#user-permission').find(':selected').text());
// Close the modal.
$('#edit-user-perm').modal('hide');
// Alert the user.
toastr.success('Successfully updated permissions for user ' + username);
});
});
}).modal('toggle');
});
});
});
});
// Function that handlers the loading of events.
$(function() {
// Add user permission button.
$('#add-permissions-button').on('click', function() {
helpers.getModal('add-user-perm', 'Set User Permission', 'Save', $('<form/>', {
'role': 'form'
})
// Append user name.
.append(helpers.getInputGroup('user-name', 'text', 'Username', 'PhantomBot', '', 'Name of the user to set the permissions on.'))
// Append the group.
.append(helpers.getDropdownGroup('user-permission', 'Permission', 'Regulars', ['Caster', 'Administrators', 'Moderators', 'Subscribers', 'Donators', 'VIPs', 'Regulars'])),
// callback once the user hits save.
function() {
let group = helpers.getGroupIdByName($('#user-permission').find(':selected').text()),
username = $('#user-name');
// make sure the user added a username.
switch (false) {
case helpers.handleInputString(username):
break;
default:
socket.updateDBValue('permission_user_add', 'group', username.val().toLowerCase(), group, function() {
socket.sendCommand('permission_add_cmd', 'permissionsetuser ' + username.val().toLowerCase() + ' ' + group, function() {
// Update the table.
run();
// Close the modal.
$('#add-user-perm').modal('hide');
// Alert the user.
toastr.success('Successfully added permissions for user ' + username.val());
});
});
}
}).modal('toggle');
});
});

View File

@@ -0,0 +1,242 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Function that querys all of the data we need.
$(run = function() {
// Check if the module is enabled.
socket.getDBValue('quotes_module_toggle', 'modules', './systems/quoteSystem.js', function(e) {
// If the module is off, don't load any data.
if (!helpers.handleModuleLoadUp('quotesModule', e.modules)) {
return;
}
// Get all quotes.
socket.getDBTableValues('get_all_quotes', 'quotes', function(results) {
let tableData = [];
for (let i = 0; i < results.length; i++) {
// Quotes are stored in an array for some reason.
// So we need to parse it to access the data.
let data = JSON.parse(results[i].value);
tableData.push([
i,
new Date(parseInt(data[2])).toLocaleDateString(), // Date.
data[0], // Username.
data[3], // Game.
data[1], // Quote.
$('<div/>', {
'class': 'btn-group'
}).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-danger',
'style': 'float: right',
'data-quote': results[i].key,
'html': $('<i/>', {
'class': 'fa fa-trash'
})
})).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-warning',
'style': 'float: right',
'data-quote': results[i].key,
'html': $('<i/>', {
'class': 'fa fa-edit'
})
})).html()
]);
}
// if the table exists, destroy it.
if ($.fn.DataTable.isDataTable('#quotesTable')) {
$('#quotesTable').DataTable().destroy();
// Remove of the old events.
$('#quotesTable').off();
}
// Create table.
let table = $('#quotesTable').DataTable({
'searching': true,
'autoWidth': false,
'lengthChange': false,
'data': tableData,
'columnDefs': [
{ 'className': 'default-table', 'orderable': false, 'targets': 5 },
{ 'width': '5%', 'targets': 0 },
{ 'width': '10%', 'targets': 1 },
{ 'width': '45%', 'targets': 4 }
],
'columns': [
{ 'title': 'Id' },
{ 'title': 'Created On', 'orderData': [1] },
{ 'title': 'Username' },
{ 'title': 'Game' },
{ 'title': 'Quote' },
{ 'title': 'Action' }
]
});
// On delete button.
table.on('click', '.btn-danger', function() {
let quoteId = $(this).data('quote');
// Ask the user if the wants to remove the quote.
helpers.getConfirmDeleteModal('quote_modal_remove', 'Are you sure you want to remove quote with ID ' + quoteId + '?', true,
'You\'ve successfully removed quote with ID ' + quoteId + '!', function() {
// Delete the quote.
socket.sendCommandSync('rm_quote_cmd', 'delquotesilent ' + quoteId, function() {
// Reload the table.
run();
});
});
});
// On edit button.
table.on('click', '.btn-warning', function() {
let quote = $(this).data('quote'),
t = $(this);
// Get the quote.
socket.getDBValue('edit_quote_get', 'quotes', quote, function(e) {
let data = JSON.parse(e.quotes);
helpers.getModal('edit-quote', 'Edit Quote', 'Save', $('<form/>', {
'role': 'form'
})
// Append quote date.
.append(helpers.getInputGroup('quote-date', 'text', 'Created On', '', helpers.getPaddedDateString(new Date(parseInt(data[2])).toLocaleDateString()), 'Date the quote was created on.'))
// Append quote creator
.append(helpers.getInputGroup('quote-user', 'text', 'Created By', '', data[0], 'The user who created the quote.'))
// Append quote game
.append(helpers.getInputGroup('quote-game', 'text', 'Game', '', data[3], 'Game being played when the quote was created.'))
// Append quote
.append(helpers.getTextAreaGroup('quote-quote', 'text', 'Quote', '', data[1], 'Quote text.', false)), function() {// Callback once we click the save button.
let quoteDate = $('#quote-date'),
quoteUser = $('#quote-user'),
quoteGame = $('#quote-game'),
quoteQuote = $('#quote-quote');
// Make sure all boxes have an input.
switch (false) {
case helpers.handleInputDate(quoteDate):
case helpers.handleInputString(quoteUser):
case helpers.handleInputString(quoteGame):
case helpers.handleInputString(quoteQuote):
break;
default:
// Edit the quote.
socket.updateDBValue('edit_quote_update', 'quotes', quote, JSON.stringify([
quoteUser.val(),
quoteQuote.val(),
helpers.getEpochFromDate(quoteDate.val()),
quoteGame.val()
]), function() {
// Update the date.
t.parents('tr').find('td:eq(1)').text(quoteDate.val());
// Update the game.
t.parents('tr').find('td:eq(2)').text(quoteUser.val());
// Update the user.
t.parents('tr').find('td:eq(3)').text(quoteGame.val());
// Update the quote.
t.parents('tr').find('td:eq(4)').text(quoteQuote.val());
// Close the modal.
$('#edit-quote').modal('hide');
// Alert the user.
toastr.success('Successfully edited the quote!');
});
}
}).modal('toggle');
});
});
});
});
});
// Function that handlers the loading of events.
$(function() {
// Module toggle.
$('#quotesModuleToggle').on('change', function() {
// Enable the module then query the data.
socket.sendCommand('quotes_module_toggle_cmd', 'module ' + ($(this).is(':checked') ? 'enablesilent' : 'disablesilent') + ' ./systems/quoteSystem.js', run);
});
// Add quote button.
$('#add-quote-button').on('click', function() {
helpers.getModal('add-quote', 'Add Quote', 'Save', $('<form/>', {
'role': 'form'
})
// Quote input.
.append(helpers.getTextAreaGroup('quote-quote', 'text', 'Quote', 'PhantomBot is great!', '', 'Quote text.', false)), function() {// Callback once we click the save button.
let quoteQuote = $('#quote-quote');
// Handle each input to make sure they have a value.
switch (false) {
case helpers.handleInputString(quoteQuote):
break;
default:
// Add quote.
socket.sendCommandSync('add_quote_cmd', 'addquotesilent ' + quoteQuote.val().replace(/"/g, '\'\''), function() {
// Reload the table.
run();
// Close the modal.
$('#add-quote').modal('hide');
// Alert the user.
toastr.success('Successfully added quote!');
});
}
}).modal('toggle');
});
// Quotes settings button.
$('#quote-settings-button').on('click', function() {
socket.getDBValues('get_quote_settings', {
tables: ['settings', 'settings'],
keys: ['quoteMessage', 'quoteTwitchNamesToggle']
}, true, function(e) {
helpers.getModal('quote-settings', 'Quote Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Quote input.
.append(helpers.getInputGroup('quote-msg', 'text', 'Quote Response', '', helpers.getDefaultIfNullOrUndefined(e.settings, '[(id)] "(quote)", by (user) ((date))'),
'Message said in chat when someone uses the quote command. Tags: (id), (quote), (user), (game) and (date)'))
.append(helpers.getDropdownGroup('quote-twitch-names-toggle', 'Force Twitch Names', (e['quoteTwitchNamesToggle'] !== 'false' ? 'Yes' : 'No'), ['Yes', 'No'],
'If names for quotes should be validated against Twitch usernames. If not, names can be anything.')),
function() {// Callback once we click the save button.
let quoteMsg = $('#quote-msg'),
quoteTwitchNamesToggle = $('#quote-twitch-names-toggle').find(':selected').text() === 'Yes';
// Handle each input to make sure they have a value.
switch (false) {
case helpers.handleInputString(quoteMsg):
break;
default:
// Add quote.
socket.updateDBValues('get_quote_settings_update', {
tables: ['settings', 'settings'],
keys: ['quoteMessage', "quoteTwitchNamesToggle"],
values: [quoteMsg.val(), quoteTwitchNamesToggle]
}, function() {
// Close the modal.
$('#quote-settings').modal('hide');
// Alert the user.
toastr.success('Successfully saved quote settings!');
});
}
}).modal('toggle');
});
});
});

View File

@@ -0,0 +1,216 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Function that querys all of the data we need.
$(run = function() {
// Check if the module is enabled.
socket.getDBValue('ranks_module_toggle', 'modules', './systems/ranksSystem.js', function(e) {
// If the module is off, don't load any data.
if (!helpers.handleModuleLoadUp('ranksCustomModule', e.modules)) {
return;
}
// Get all ranks.
socket.getDBTableValues('custom_get_ranks', 'viewerRanks', function(results) {
let tableData = [];
for (let i = 0; i < results.length; i++) {
tableData.push([
results[i].key,
results[i].value,
$('<div/>', {
'class': 'btn-group'
}).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-danger',
'style': 'float: right',
'data-user': results[i].key,
'html': $('<i/>', {
'class': 'fa fa-trash'
})
})).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-warning',
'style': 'float: right',
'data-user': results[i].key,
'html': $('<i/>', {
'class': 'fa fa-edit'
})
})).html()
]);
}
// if the table exists, destroy it.
if ($.fn.DataTable.isDataTable('#ranksCustomTable')) {
$('#ranksCustomTable').DataTable().destroy();
// Remove all of the old events.
$('#ranksCustomTable').off();
}
// Create table.
let table = $('#ranksCustomTable').DataTable({
'searching': true,
'autoWidth': false,
'lengthChange': false,
'data': tableData,
'columnDefs': [
{ 'className': 'default-table', 'orderable': false, 'targets': 2 },
{ 'width': '45%', 'targets': 0 }
],
'columns': [
{ 'title': 'Username' },
{ 'title': 'Rank' },
{ 'title': 'Actions' }
]
});
// On delete button.
table.on('click', '.btn-danger', function() {
let username = $(this).data('user'),
row = $(this).parents('tr');
helpers.getConfirmDeleteModal('custom_rank_modal_remove', 'Are you sure you want to remove ' + username + '\'s custom rank?', true,
'You\'ve successfully removed ' + username + '\'s custom rank!', function() {
// Delete the rank
socket.removeDBValue('rm_custom_rank', 'viewerRanks', username, function() {
// Remove the table row.
table.row(row).remove().draw(false);
});
});
});
// On edit button.
table.on('click', '.btn-warning', function() {
let user = $(this).data('user'),
t = $(this);
// Get the rank info.
socket.getDBValue('rank_get_name', 'viewerRanks', user, function(e) {
helpers.getModal('edit-set-rank', 'Edit User Rank', 'Save', $('<form/>', {
'role': 'form'
})
// Append alias name.
.append(helpers.getInputGroup('rank-user', 'text', 'Username', '', user, 'Name of the user for the rank to be set on.'))
// Append alias.
.append(helpers.getInputGroup('rank-name', 'text', 'Rank', '', e.viewerRanks, 'Rank name to give to the user')), function() {// Callback once we click the save button.
let rankUser = $('#rank-user'),
rankName = $('#rank-name');
// Make sure all boxes have an input.
switch (false) {
case helpers.handleInputString(rankUser):
case helpers.handleInputString(rankName):
break;
default:
socket.removeDBValue('del_rank_custom', 'viewerRanks', user, function() {
// Add the rank.
socket.updateDBValue('edit_rank_custom', 'viewerRanks', rankUser.val().toLowerCase(), rankName.val(), function() {
// Update the table name.
t.parents('tr').find('td:eq(0)').text(rankUser.val().toLowerCase());
// Update the table hours.
t.parents('tr').find('td:eq(1)').text(rankName.val());
// Close the modal.
$('#edit-set-rank').modal('hide');
// Alert the user.
toastr.success('Successfully edited the user rank!');
});
});
}
}).modal('toggle');
});
});
});
});
});
// Function that handlers the loading of events.
$(function() {
$('#ranksCustomModuleToggle').on('change', function() {
// Enable the module then query the data.
socket.sendCommandSync('ranks_module_toggle_cmd', 'module ' + ($(this).is(':checked') ? 'enablesilent' : 'disablesilent') + ' ./systems/ranksSystem.js', run);
});
// Add user rank button.
$('#rank-user-button').on('click', function() {
helpers.getModal('set-rank', 'Set User Rank', 'Save', $('<form/>', {
'role': 'form'
})
// Append alias name.
.append(helpers.getInputGroup('rank-user', 'text', 'Username', 'PhantomBot', '', 'Name of the user for the rank to be set on.'))
// Append alias.
.append(helpers.getInputGroup('rank-name', 'text', 'Rank', 'Bot', '', 'Rank name to give to the user.')), function() {// Callback once we click the save button.
let rankUser = $('#rank-user'),
rankName = $('#rank-name');
// Make sure all boxes have an input.
switch (false) {
case helpers.handleInputString(rankUser):
case helpers.handleInputString(rankName):
break;
default:
// Add the rank.
socket.updateDBValue('set_rank_custom', 'viewerRanks', rankUser.val().toLowerCase(), rankName.val(), function() {
// Update the table name.
run();
// Close the modal.
$('#set-rank').modal('hide');
// Alert the user.
toastr.success('Successfully added the rank to the user!');
});
}
}).modal('toggle');
});
// Rank settings button.
$('#rank-settings-button').on('click', function() {
socket.getDBValues('get_custom_rank_settings', {
tables: ['settings', 'settings'],
keys: ['rankEligableTime', 'rankEligableCost']
}, true, function(e) {
helpers.getModal('settings-rank', 'Rank Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Append alias name.
.append(helpers.getInputGroup('rank-cost', 'number', 'Rank Cost', '', e.rankEligableCost, 'How much a custom rank will cost for a user.'))
// Append alias.
.append(helpers.getInputGroup('rank-time', 'number', 'Rank Hours', '', e.rankEligableTime, 'How many hours a user needs before they can buy a custom rank.')), function() {// Callback once we click the save button.
let rankCost = $('#rank-cost'),
rankTime = $('#rank-time');
// Make sure all boxes have an input.
switch (false) {
case helpers.handleInputNumber(rankCost):
case helpers.handleInputNumber(rankTime):
break;
default:
// Add the rank.
socket.updateDBValues('update_custom_rank_Settings', {
tables: ['settings', 'settings'],
keys: ['rankEligableTime', 'rankEligableCost'],
values: [rankTime.val(), rankCost.val()]
}, function() {
// Close the modal.
$('#settings-rank').modal('hide');
// Alert the user.
toastr.success('Successfully updated rank settings');
});
}
}).modal('toggle');
});
});
});

View File

@@ -0,0 +1,191 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Function that querys all of the data we need.
$(run = function() {
// Check if the module is enabled.
socket.getDBValue('ranks_module_toggle', 'modules', './systems/ranksSystem.js', function(e) {
// If the module is off, don't load any data.
if (!helpers.handleModuleLoadUp('ranksModule', e.modules)) {
return;
}
// Get all ranks.
socket.getDBTableValues('global_get_ranks', 'ranksMapping', function(results) {
let tableData = [];
for (let i = 0; i < results.length; i++) {
tableData.push([
results[i].key,
results[i].value,
$('<div/>', {
'class': 'btn-group'
}).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-danger',
'style': 'float: right',
'data-rank': results[i].key,
'html': $('<i/>', {
'class': 'fa fa-trash'
})
})).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-warning',
'style': 'float: right',
'data-rank': results[i].key,
'html': $('<i/>', {
'class': 'fa fa-edit'
})
})).html()
]);
}
// if the table exists, destroy it.
if ($.fn.DataTable.isDataTable('#ranksTable')) {
$('#ranksTable').DataTable().destroy();
// Remove all of the old events.
$('#ranksTable').off();
}
// Create table.
let table = $('#ranksTable').DataTable({
'searching': true,
'autoWidth': false,
'lengthChange': false,
'data': tableData,
'columnDefs': [
{ 'className': 'default-table', 'orderable': false, 'targets': 2 },
{ 'width': '45%', 'targets': 0 }
],
'columns': [
{ 'title': 'Hours' },
{ 'title': 'Rank' },
{ 'title': 'Actions' }
]
});
// On delete button.
table.on('click', '.btn-danger', function() {
let rankHours = $(this).data('rank'),
row = $(this).parents('tr'),
rankName = row.find('td:eq(1)').text();
// Ask if the user wants to remove the rank.
helpers.getConfirmDeleteModal('global_rank_modal_remove', 'Are you sure you want to remove the "' + rankName + '" rank?', true,
'You\'ve successfully removed the "' + rankName + '" rank!', function() {
// Delete the rank
socket.removeDBValue('rm_global_rank', 'ranksMapping', rankHours, function() {
// Reload the rank table in the bot.
socket.sendCommand('rm_global_rank_cmd', 'rankreloadtable', function() {
// Remove the table row.
table.row(row).remove().draw(false);
});
});
});
});
// On edit button.
table.on('click', '.btn-warning', function() {
let rank = $(this).data('rank'),
t = $(this);
// Get the rank info.
socket.getDBValue('rank_get_name', 'ranksMapping', rank, function(e) {
helpers.getModal('edit-rank', 'Edit Rank', 'Save', $('<form/>', {
'role': 'form'
})
// Rank name
.append(helpers.getInputGroup('rank-name', 'text', 'Rank', '', e.ranksMapping, 'Name of the rank.'))
// Rank hours
.append(helpers.getInputGroup('rank-hours', 'number', 'Hours', '', rank, 'Number of hours before a user gets this rank.')), function() {// Callback once we click the save button.
let rankName = $('#rank-name'),
rankHours = $('#rank-hours');
// Make sure all boxes have an input.
switch (false) {
case helpers.handleInputString(rankName):
case helpers.handleInputNumber(rankHours):
break;
default:
// Remove the old rank.
socket.removeDBValue('rm_rank_edit_global', 'ranksMapping', rank, function() {
// Add the rank.
socket.updateDBValue('edit_rank_global', 'ranksMapping', rankHours.val(), rankName.val(), function() {
// Reload the rank table in the bot.
socket.sendCommand('edit_global_rank_cmd', 'rankreloadtable', function() {
// Update the table name.
t.parents('tr').find('td:eq(0)').text(rankHours.val());
// Update the table hours.
t.parents('tr').find('td:eq(1)').text(rankName.val());
// Update the rank hours.
t.data('rank', rankHours.val());
// Close the modal.
$('#edit-rank').modal('hide');
// Alert the user.
toastr.success('Successfully edited the rank!');
});
});
});
}
}).modal('toggle');
});
});
});
});
});
// Function that handlers the loading of events.
$(function() {
$('#ranksModuleToggle').on('change', function() {
// Enable the module then query the data.
socket.sendCommandSync('ranks_module_toggle_cmd', 'module ' + ($(this).is(':checked') ? 'enablesilent' : 'disablesilent') + ' ./systems/ranksSystem.js', run);
});
// Add rank button.
$('#add-rank-button').on('click', function() {
helpers.getModal('add-rank', 'Add Rank', 'Save', $('<form/>', {
'role': 'form'
})
// Append alias name.
.append(helpers.getInputGroup('rank-name', 'text', 'Rank', 'VIP', '', 'Name of the rank.'))
// Append alias.
.append(helpers.getInputGroup('rank-hours', 'number', 'Hours', '5', '', 'Number of hours before a user gets this rank.')), function() {// Callback once we click the save button.
let rankName = $('#rank-name'),
rankHours = $('#rank-hours');
// Make sure all boxes have an input.
switch (false) {
case helpers.handleInputString(rankName):
case helpers.handleInputNumber(rankHours):
break;
default:
// Add the rank.
socket.updateDBValue('add_rank_global', 'ranksMapping', rankHours.val(), rankName.val(), function() {
// Reload the rank table in the bot.
socket.sendCommand('add_global_rank_cmd', 'rankreloadtable', function() {
// Update the table name.
run();
// Close the modal.
$('#add-rank').modal('hide');
// Alert the user.
toastr.success('Successfully added the rank!');
});
});
}
}).modal('toggle');
});
});

View File

@@ -0,0 +1,76 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Function that querys all of the data we need.
$(function() {
// Get logging settings.
socket.getDBValues('get_logging_settings', {
tables: ['settings', 'settings', 'settings', 'settings', 'settings',
'settings', 'settings'],
keys: ['log.file', 'log.event', 'log.error', 'log_rotate_days',
'response_@chat', 'response_action', 'whisperMode']
}, true, function(e) {
// Update log event toggle.
$('#logging-events').val((e['log.event'] === 'true' ? 'Yes' : 'No'));
// Update log error toggle.
$('#logging-errors').val((e['log.error'] === 'true' ? 'Yes' : 'No'));
// Update log chat toggle.
$('#logging-chat').val((e['log.file'] === 'true' ? 'Yes' : 'No'));
// Update log keep days.
$('#log-days').val(e.log_rotate_days);
// Set mute mode.
$('#bot-mute-mode').val((e['response_@chat'] === 'true' ? 'No' : 'Yes'));
// Set action mode.
$('#bot-action-mode').val((e['response_action'] === 'true' ? 'Yes' : 'No'));
// Set whisper mode.
$('#bot-whisper-mode').val((e['whisperMode'] === 'true' ? 'Yes' : 'No'));
});
});
// Function that handles events.
$(function() {
// Save button
$('#bot-logging-save').on('click', function() {
let logEvents = $('#logging-events').find(':selected').text() === 'Yes',
logErrors = $('#logging-errors').find(':selected').text() === 'Yes',
logChat = $('#logging-chat').find(':selected').text() === 'Yes',
muteMode = $('#bot-mute-mode').find(':selected').text() !== 'Yes',
actionMode = $('#bot-action-mode').find(':selected').text() === 'Yes',
whisperMode = $('#bot-whisper-mode').find(':selected').text() === 'Yes',
logDays = $('#log-days');
switch (false) {
case helpers.handleInputNumber(logDays):
break;
default:
socket.updateDBValues('update_logging_settings', {
tables: ['settings', 'settings', 'settings', 'settings', 'settings',
'settings', 'settings'],
keys: ['log.file', 'log.event', 'log.error', 'log_rotate_days',
'response_@chat', 'response_action', 'whisperMode'],
values: [logChat, logEvents, logErrors, logDays.val(),
muteMode, actionMode, whisperMode]
}, function() {
socket.sendCommand('update_logging_settings_cmd', 'reloadlogs', function() {
socket.sendCommand('update_misc_settings_cmd', 'reloadmisc', function() {
toastr.success('Successfully updated log settings!');
});
});
});
}
});
});

View File

@@ -0,0 +1,71 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Function that querys all of the data we need.
$(run = function() {
// Get command settings.
socket.getDBValues('get_command_settings', {
tables: ['settings', 'settings', 'settings', 'settings', 'cooldownSettings',
'cooldownSettings'],
keys: ['permComMsgEnabled', 'priceComMsgEnabled', 'coolDownMsgEnabled',
'pricecomMods', 'modCooldown', 'defaultCooldownTime']
}, true, function(e) {
// Set cost message.
$('#cmd-cost-messages').val((e.priceComMsgEnabled === 'true' ? 'Yes' : 'No'));
// Set permission message.
$('#cmd-perm-messages').val((e.permComMsgEnabled === 'true' ? 'Yes' : 'No'));
// Set cooldown message.
$('#cmd-cooldown-messages').val((e.coolDownMsgEnabled === 'true' ? 'Yes' : 'No'));
// Set cost for mods.
$('#pricecom-mods').val((e.pricecomMods === 'true' ? 'No' : 'Yes'));
// Set cooldown for mods.
$('#cooldown-mods').val((e.modCooldown === 'true' ? 'No' : 'Yes'));
// Set global cooldown.
$('#global-cooldown').val(e.defaultCooldownTime);
});
});
// Function that handles events.
$(function() {
// Save button.
$('#cmd-save-btn').on('click', function() {
let cmdCostMessage = $('#cmd-cost-messages').find(':selected').text() === 'Yes',
cmdPermMessage = $('#cmd-perm-messages').find(':selected').text() === 'Yes',
cmdCooldownMessage = $('#cmd-cooldown-messages').find(':selected').text() === 'Yes',
priceComMods = $('#pricecom-mods').find(':selected').text() !== 'Yes',
cooldownMods = $('#cooldown-mods').find(':selected').text() !== 'Yes',
globalTime = $('#global-cooldown');
switch (false) {
case helpers.handleInputNumber(globalTime, 5):
break;
default:
socket.updateDBValues('update_cmd_settings', {
tables: ['settings', 'settings', 'settings', 'settings', 'cooldownSettings',
'cooldownSettings'],
keys: ['permComMsgEnabled', 'priceComMsgEnabled', 'coolDownMsgEnabled',
'pricecomMods', 'modCooldown', 'defaultCooldownTime'],
values: [cmdPermMessage, cmdCostMessage, cmdCooldownMessage,
priceComMods, cooldownMods, globalTime.val()]
}, function() {
socket.wsEvent('update_cmd_settings_ws', './core/commandCoolDown.js', null, ['update'], function() {
toastr.success('Successfully update command settings!');
});
});
}
});
});

View File

@@ -0,0 +1,284 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
$(function() {
var currentLang = '';
// Load file button
$('#load-file-button').on('click', function() {
$.ajax({
'url': '/get-lang?webauth=' + getAuth(),
'type': 'GET',
'success': function(data) {
helpers.getModal('edit-lang', 'Load Lang File', 'Edit', $('<form/>', {
'role': 'form'
})
// Add select box.
.append(helpers.getDropdownGroup('file-to-load', 'Lang file: ', 'Choose a File', data.split('\n'))), function() {
currentLang = $('#file-to-load').find(':selected').text();
$.ajax({
'url': '/lang?webauth=' + getAuth(),
'type': 'GET',
'headers': {
'lang-path': $('#file-to-load').find(':selected').text()
},
'success': function(data) {
// Load the file
loadLang(JSON.parse(data));
// Alert the user.
toastr.success('Successfully loaded the file!');
// Close the modal.
$('#edit-lang').modal('toggle');
// Enable the insert and save buttons.
$('#save-button').prop('disabled', false);
$('#add-line-button').prop('disabled', false);
}
})
}).modal('toggle');
}
});
});
// Add line button.
$('#add-line-button').on('click', function() {
helpers.getModal('add-lang', 'Add Lang Entry', 'Add', $('<form/>', {
'role': 'form'
})
// ID for the lang.
.append(helpers.getInputGroup('lang-id', 'text', 'Lang ID', 'module.name.id'))
// Resonse for the lang.
.append(helpers.getTextAreaGroup('lang-response', 'text', 'Response', 'Response example!')), function() {
const table = $('#langTable').DataTable(),
langId = $('#lang-id'),
langRes = $('#lang-response');
switch (false) {
case helpers.handleInputString(langId):
case helpers.handleInputString(langRes):
break;
default:
langId.val(langId.val().replace(/[^a-zA-Z0-9-\.]+/g, '-'));
table.row.add([
langId.val(),
langRes.val(),
$('<div/>', {
'class': 'btn-group'
}).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-danger',
'style': 'float: right',
'data-id': langId.val(),
'data-response': langRes.val(),
'html': $('<i/>', {
'class': 'fa fa-trash'
})
})).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-warning',
'style': 'float: right',
'data-id': langId.val(),
'data-response': langRes.val(),
'html': $('<i/>', {
'class': 'fa fa-edit'
})
})).html()
]).draw();
// Close the modal.
$('#add-lang').modal('toggle');
// Alert the user.
toastr.success('Successfully added the lang entry.');
}
}).modal('toggle');
});
// Save button
$('#save-button').on('click', function() {
const datas = $('#langTable').DataTable().rows().data(),
dataObj = [];
for (let i = 0; i < datas.length; i++) {
if (typeof datas[i] === 'object') {
dataObj.push({
'id': datas[i][0],
'response': datas[i][1]
});
} else {
// No longer data, break the loop.
break;
}
}
// Post the lang.
$.ajax({
'type': 'PUT',
'url': '/lang?webauth=' + getAuth(),
'contentType': 'application/json',
'headers': {
'lang-path': currentLang
},
'data': JSON.stringify(dataObj),
'success': function(data, text, xhr) {
if (xhr.status === 200) {
toastr.success('Successfully saved the lang!');
} else {
toastr.success('Faled to save the lang.');
}
}
});
});
// Load lang function
function loadLang(langArray) {
const tableData = [];
for (let i = 0; i < langArray.length; i++) {
langArray[i]['response'] = langArray[i]['response'].replace(/\\'/g, '\'');
tableData.push([
langArray[i]['id'],
langArray[i]['response'],
$('<div/>', {
'class': 'btn-group'
}).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-danger',
'style': 'float: right',
'data-id': langArray[i]['id'],
'data-response': langArray[i]['response'],
'html': $('<i/>', {
'class': 'fa fa-trash'
})
})).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-warning',
'style': 'float: right',
'data-id': langArray[i]['id'],
'data-response': langArray[i]['response'],
'html': $('<i/>', {
'class': 'fa fa-edit'
})
})).html()
])
}
// if the table exists, destroy it.
if ($.fn.DataTable.isDataTable('#langTable')) {
$('#langTable').DataTable().destroy();
// Remove all of the old events.
$('#langTable').off();
}
// Create table.
let table = $('#langTable').DataTable({
'searching': true,
'autoWidth': false,
'lengthChange': false,
'paging': false,
'data': tableData,
'columnDefs': [
{ 'className': 'default-table', 'orderable': false, 'targets': 2 },
{ 'width': '25%', 'targets': 0 }
],
'columns': [
{ 'title': 'Lang ID' },
{ 'title': 'Response' },
{ 'title': 'Actions' }
]
});
// On delete button.
table.on('click', '.btn-danger', function() {
const row = $(this).parents('tr'),
id = $(this).data('id');
// Ask the user if he wants to delete the lang.
helpers.getConfirmDeleteModal('lang_modal_remove', 'Are you sure you want to remove this lang entry?', true,
'The land entry has been successfully removed!', function() { // Callback if the user clicks delete.
// Remove the table row.
table.row(row).remove().draw(false);
});
});
// On edit button.
table.on('click', '.btn-warning', function() {
const t = $(this);
helpers.getModal('edit-lang', 'Edit Lang Entry', 'Edit', $('<form/>', {
'role': 'form'
})
// ID for the lang.
.append(helpers.getInputGroup('lang-id', 'text', 'Lang ID', '', t.data('id'), 'The ID of this lang.'))
// Resonse for the lang.
.append(helpers.getTextAreaGroup('lang-response', 'text', 'Response', '', t.data('response').replace(/\\'/g, '\''), 'The response of this lang.')), function() {
let id = $('#lang-id'),
response = $('#lang-response');
switch (false) {
case helpers.handleInputString(id):
case helpers.handleInputString(response):
break;
default:
// Update the special chars.
id = id.val().replace(/[^a-zA-Z0-9-\.]+/g, '-');
// Update the table.
$('#langTable').DataTable().row(t.parents('tr')).data([
id,
response.val(),
$('<div/>', {
'class': 'btn-group'
}).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-danger',
'style': 'float: right',
'data-id': id,
'data-response': response.val(),
'html': $('<i/>', {
'class': 'fa fa-trash'
})
})).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-warning',
'style': 'float: right',
'data-id': id,
'data-response': response.val(),
'html': $('<i/>', {
'class': 'fa fa-edit'
})
})).html()
]).draw(false);
// Alert the user.
toastr.success('Successfully updated the lang response!');
// Close the modal.
$('#edit-lang').modal('toggle');
}
}).modal('toggle');
});
}
function cleanLangID(obj) {
return obj.val(obj.val().replace(/[^a-zA-Z0-9-\.]+/g, '-'));
}
// Load the table for now.
loadLang([]);
});

View File

@@ -0,0 +1,231 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Function that querys all of the data we need.
$(run = function() {
// Get all modules.
socket.getDBTableValues('get_all_modules', 'modules', function(results) {
let twitchModules = [],
discordModules = [];
for (let i = 0; i < results.length; i++) {
if (results[i].key.indexOf('/lang/') === -1 && results[i].key.indexOf('/core/') === -1) {
if (results[i].key.indexOf('./discord') !== -1) {
discordModules.push({
module: results[i].key,
status: results[i].value === 'true'
});
} else {
twitchModules.push({
module: results[i].key,
status: results[i].value === 'true'
});
}
}
}
// Load Twitch table.
let twitchTable = [];
for (let i = 0; i < twitchModules.length; i++) {
twitchTable.push([
twitchModules[i].module,
$('<div/>', {
'class': 'btn-group'
}).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-danger',
'data-toggle': 'tooltip',
'title': 'Delete the module if it no longer exists.',
'style': 'float: right',
'data-module': twitchModules[i].module,
'html': $('<i/>', {
'class': 'fa fa-trash'
})
})).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-' + (twitchModules[i].status ? 'success' : 'warning'),
'data-toggle': 'tooltip',
'title': (twitchModules[i].status ? 'Click to disable the module.' : 'Click to enable the module.') ,
'style': 'float: right',
'data-module': twitchModules[i].module,
'data-mtoggle': twitchModules[i].status,
'html': $('<i/>', {
'class': 'fa fa-' + (twitchModules[i].status ? 'close' : 'check')
})
})).html()
]);
}
// if the table exists, destroy it.
if ($.fn.DataTable.isDataTable('#twitchModuleTable')) {
$('#twitchModuleTable').DataTable().destroy();
// Remove all of the old events.
$('#twitchModuleTable').off();
}
// Create table.
let table = $('#twitchModuleTable').DataTable({
'searching': true,
'autoWidth': false,
'lengthChange': true,
'data': twitchTable,
'columnDefs': [
{ 'className': 'default-table', 'orderable': false, 'targets': 1 },
],
'columns': [
{ 'title': 'Module' },
{ 'title': 'Actions' }
]
});
// On delete button.
table.on('click', '.btn-danger', function() {
let module = $(this).data('module'),
row = $(this).parents('tr');
// Ask the user if he want to remove the module.
helpers.getConfirmDeleteModal('rm_module_cmd_modal', 'Are you sure that you want to remove module "' + module + '"?', true,
'The module "' + module + '"" has been successfully removed!', function() {
socket.removeDBValue('rm_twitch_module', 'modules', module, function() {
// Remove the table row.
table.row(row).remove().draw(false);
});
});
});
// On toggle button.
table.on('click', '.btn-warning, .btn-success', function() {
let module = $(this).data('module'),
toggle = $(this).data('mtoggle'),
btn = $(this);
socket.sendCommand('module_toggle_cmd', 'module ' + (!toggle ? 'enablesilent ' : 'disablesilent ') + module, function() {
toastr.success('successfully ' + (!toggle ? 'enabled' : 'disabled') + ' the module.');
// Update the button.
if (toggle) {
btn.removeClass('btn-success').addClass('btn-warning').find('i').removeClass('fa-close').addClass('fa-check');
btn.prop('title', 'Click to enable the module.').tooltip('fixTitle').tooltip('show');
} else {
btn.removeClass('btn-warning').addClass('btn-success').find('i').removeClass('fa-check').addClass('fa-close');
btn.prop('title', 'Click to disable the module.').tooltip('fixTitle').tooltip('show');
}
btn.data('mtoggle', !toggle);
});
});
// Get the status of Discord.
// Only load the list if we are using it.
socket.getDBValue('get_discord_status', 'panelData', 'hasDiscord', function(e) {
// Disable the tab if we are not using Discord.
if (e.panelData !== 'true') {
$('#discord_modules_t').addClass('disabled').parent().addClass('disabled');
return;
}
// Load Discord table.
let discordTable = [];
for (let i = 0; i < discordModules.length; i++) {
discordTable.push([
discordModules[i].module,
$('<div/>', {
'class': 'btn-group'
}).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-danger',
'data-toggle': 'tooltip',
'title': 'Delete the module if it no longer exists.',
'style': 'float: right',
'data-module': discordModules[i].module,
'html': $('<i/>', {
'class': 'fa fa-trash'
})
})).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-' + (discordModules[i].status ? 'success' : 'warning'),
'data-toggle': 'tooltip',
'title': (discordModules[i].status ? 'Click to disable the module.' : 'Click to enable the module.') ,
'style': 'float: right',
'data-module': discordModules[i].module,
'data-mtoggle': discordModules[i].status,
'html': $('<i/>', {
'class': 'fa fa-' + (discordModules[i].status ? 'close' : 'check')
})
})).html()
]);
}
// if the table exists, destroy it.
if ($.fn.DataTable.isDataTable('#discordModuleTable')) {
$('#discordModuleTable').DataTable().destroy();
// Remove all of the old events.
$('#discordModuleTable').off();
}
// Create table.
let table = $('#discordModuleTable').DataTable({
'searching': true,
'autoWidth': false,
'lengthChange': true,
'data': discordTable,
'columnDefs': [
{ 'className': 'default-table', 'orderable': false, 'targets': 1 },
],
'columns': [
{ 'title': 'Module' },
{ 'title': 'Actions' }
]
});
// On delete button.
table.on('click', '.btn-danger', function() {
let module = $(this).data('module'),
row = $(this).parents('tr');
// Ask the user if he want to remove the module.
helpers.getConfirmDeleteModal('rm_module_cmd_modal', 'Are you sure that you want to remove module "' + module + '"?', true,
'The module "' + module + '"" has been successfully removed!', function() {
socket.removeDBValue('rm_discord_module', 'modules', module, function() {
// Remove the table row.
table.row(row).remove().draw(false);
});
});
});
// On toggle button.
table.on('click', '.btn-warning, .btn-success', function() {
let module = $(this).data('module'),
toggle = $(this).data('mtoggle'),
btn = $(this);
socket.sendCommand('module_toggle_cmd', 'module ' + (!toggle ? 'enablesilent ' : 'disablesilent ') + module, function() {
toastr.success('successfully ' + (!toggle ? 'enabled' : 'disabled') + ' the module.');
// Update the button.
if (toggle) {
btn.removeClass('btn-success').addClass('btn-warning').find('i').removeClass('fa-close').addClass('fa-check');
btn.prop('title', 'Click to enable the module.').tooltip('fixTitle').tooltip('show');
} else {
btn.removeClass('btn-warning').addClass('btn-success').find('i').removeClass('fa-check').addClass('fa-close');
btn.prop('title', 'Click to disable the module.').tooltip('fixTitle').tooltip('show');
}
btn.data('mtoggle', !toggle);
});
});
});
});
});

View File

@@ -0,0 +1,219 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Function that querys all of the data we need.
$(run = function() {
// Check if the module is enabled.
socket.getDBValue('notice_module_toggle', 'modules', './systems/noticeSystem.js', function(e) {
// If the module is off, don't load any data.
if (!helpers.handleModuleLoadUp('noticesModule', e.modules)) {
return;
}
// Query aliases.
socket.getDBTableValues('timers_get_all', 'notices', function(results) {
let tableData = [];
for (let i = 0; i < results.length; i++) {
// Strip the "message_" part to get the ID.
results[i].key = results[i].key.substring(8);
tableData.push([
results[i].key,
results[i].value,
$('<div/>', {
'class': 'btn-group'
}).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-danger',
'style': 'float: right',
'data-notice': results[i].key,
'html': $('<i/>', {
'class': 'fa fa-trash'
})
})).append($('<button/>', {
'type': 'button',
'class': 'btn btn-xs btn-warning',
'style': 'float: right',
'data-notice': results[i].key,
'html': $('<i/>', {
'class': 'fa fa-edit'
})
})).html()
]);
}
// if the table exists, destroy it.
if ($.fn.DataTable.isDataTable('#timersTable')) {
$('#timersTable').DataTable().destroy();
// Remove all of the old events.
$('#timersTable').off();
}
// Create table.
let table = $('#timersTable').DataTable({
'searching': true,
'autoWidth': false,
'lengthChange': false,
'data': tableData,
'columnDefs': [
{ 'className': 'default-table', 'orderable': false, 'targets': 2 },
{ 'width': '3%', 'targets': 0 }
],
'columns': [
{ 'title': 'Id' },
{ 'title': 'Message' },
{ 'title': 'Actions' }
]
});
// On delete button.
table.on('click', '.btn-danger', function() {
let timerId = $(this).data('notice');
// Ask the user if he want to remove the timer.
helpers.getConfirmDeleteModal('timer_modal_remove', 'Are you sure you want to remove timer with ID ' + timerId + '?', true,
'You\'ve successfully removed timer with ID ' + timerId + '!', function() {
// Remove the timer
socket.sendCommand('notice_remove_cmd', 'notice removesilent ' + timerId, function() {
// Reload the table.
run();
});
});
});
// On edit button.
table.on('click', '.btn-warning', function() {
let notice = $(this).data('notice'),
t = $(this);
socket.getDBValue('notice_get_edit', 'notices', 'message_' + notice, function(e) {
helpers.getModal('edit-timer', 'Edit Timer', 'Save', $('<form/>', {
'role': 'form'
})
// Append timer text.
.append(helpers.getTextAreaGroup('notice-text', 'text', 'Timer Message', '', e.notices, 'Message of this timer. Use the "command:" prefix then the name of the command to run a command.')),
// Callback once the user clicks save.
function() {// Callback once we click the save button.
let noticeText = $('#notice-text');
// Handle each input to make sure they have a value.
switch (false) {
case helpers.handleInputString(noticeText):
break;
default:
// Edit the timer
socket.sendCommand('notice_edit_cmd', 'notice editsilent ' + notice + ' ' + noticeText.val(), function() {
// Update the table.
t.parents('tr').find('td:eq(1)').text(noticeText.val());
// Close the modal.
$('#edit-timer').modal('hide');
// Alert the user.
toastr.success('Successfully edited the timer!');
});
}
}).modal('toggle');
});
});
});
});
});
// Function that handlers the loading of events.
$(function() {
// Toggle for the module.
$('#noticesModuleToggle').on('change', function() {
// Enable the module then query the data.
socket.sendCommandSync('notices_module_toggle_cmd', 'module ' + ($(this).is(':checked') ? 'enablesilent' : 'disablesilent') + ' ./systems/noticeSystem.js', run);
});
// Add timer button.
$('#add-timer-button').on('click', function() {
helpers.getModal('add-timer', 'Add Timer', 'Save', $('<form/>', {
'role': 'form'
})
// Append timer text.
.append(helpers.getTextAreaGroup('notice-text', 'text', 'Timer Message', 'Follow me on Twitter! https://twitter.com/PhantomBotApp', '', 'Message of this timer. Use the "command:" prefix then the name of the command to run a command.')),
// Callback once the user clicks save.
function() {// Callback once we click the save button.
let noticeText = $('#notice-text');
// Handle each input to make sure they have a value.
switch (false) {
case helpers.handleInputString(noticeText):
break;
default:
// Edit the timer
socket.sendCommand('notice_add_cmd', 'notice addsilent ' + noticeText.val(), function() {
// Update the table.
run();
// Close the modal.
$('#add-timer').modal('hide');
// Alert the user.
toastr.success('Successfully added the timer!');
});
}
}).modal('toggle');
});
// Notice settings button.
$('#timer-settings-button').on('click', function() {
socket.getDBValues('notice_get_settings', {
tables: ['noticeSettings', 'noticeSettings', 'noticeSettings', 'noticeSettings'],
keys: ['reqmessages', 'interval', 'noticetoggle', 'noticeOfflineToggle']
}, true, function(e) {
helpers.getModal('settings-timer', 'Timer Settings', 'Save', $('<form/>', {
'role': 'form'
})
// Append alias name.
.append(helpers.getInputGroup('notice-interval', 'number', 'Timer Interval (Minutes)', '', e.interval, 'Interval at which a random timer is said in chat.'))
// Append alias name.
.append(helpers.getInputGroup('notice-reqmsg', 'number', 'Timer Required Messages', '', e.reqmessages, 'Amount of message required to trigger a random timer along with the interval.'))
// Append toggle.
.append(helpers.getDropdownGroup('notice-toggle', 'Active Timers', (e.noticetoggle === 'true' ? 'Yes' : 'No'), ['Yes', 'No'], 'If the timers should be enabled.'))
// Append offline toggle.
.append(helpers.getDropdownGroup('notice-offline-toggle', 'Active Offline Timers', (e.noticeOfflineToggle === 'true' ? 'Yes' : 'No'), ['Yes', 'No'], 'If the timers should be said in offline chat.')),
// Callback once the user clicks save.
function() {// Callback once we click the save button.
let noticeInterval = $('#notice-interval'),
noticeReqMsg = $('#notice-reqmsg'),
noticeToggle = $('#notice-toggle').find(':selected').text() === 'Yes',
noticeOfflineToggle = $('#notice-offline-toggle').find(':selected').text() === 'Yes';
// Handle each input to make sure they have a value.
switch (false) {
case helpers.handleInputNumber(noticeInterval):
case helpers.handleInputNumber(noticeReqMsg):
break;
default:
socket.updateDBValues('notices_update_settings', {
tables: ['noticeSettings', 'noticeSettings', 'noticeSettings', 'noticeSettings'],
keys: ['reqmessages', 'interval', 'noticetoggle', 'noticeOfflineToggle'],
values: [noticeReqMsg.val(), noticeInterval.val(), noticeToggle, noticeOfflineToggle]
}, function() {
socket.sendCommand('notices_update_settings_cmd', 'reloadnotice', function() {
// Close the modal.
$('#settings-timer').modal('hide');
// Alert the user.
toastr.success('Successfully updated timer settings');
});
});
}
}).modal('toggle');
});
});
});

View File

@@ -0,0 +1,102 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
$(function() {
/*
* @function removes the page loader.
*/
function showPage() {
helpers.log('Showing dashboard page', helpers.LOG_TYPE.DEBUG);
if ($('.loader').length > 0) {
// Stop pace since we already have one loader.
Pace.stop();
$('.loader').fadeOut(3e2, function() {
$('.loader').remove();
});
$('.main').fadeIn(2e2, function() {
// Fix the window height.
$.fn.layout.Constuctor.prototype.fix();
});
// Add the load for the master script.
$('body').append($('<script>', {
'async': true,
'src': '/panel/js/pages/global.js'
}));
helpers.log('Page shown', helpers.LOG_TYPE.DEBUG);
}
}
/*
* @function handles the loading of pages.
*
* @param {String} folder
* @param {String} page
*/
function loadPage(folder, page, href) {
// Make sure the href isn't blank, then load the page.
if (page !== '') {
helpers.log('Starting ajax request for page: ' + folder + '/' + page, helpers.LOG_TYPE.DEBUG);
// Start pace loading.
if (href === undefined) {
Pace.stop();
} else {
Pace.restart();
}
// Clear all timers. This doesn't clear any global timers (intervals).
helpers.clearTimers();
// Remove all temp global functions.
helpers.temp = {};
// Load the page.
$.ajax({
cache: false,
dataType: 'html',
url: '/panel/pages/' + folder + '/' + page,
success: function(data) {
// Set the new page.
$('#page-content').html(data);
// Scroll to top.
$(window).scrollTop(0);
if (href !== undefined) {
// Set the current tab as active.
$.fn.dinamicMenu(href);
// Update URL.
window.history.pushState(null, '', '/panel');
}
helpers.log('Completed ajax request for page: ' + folder + '/' + page, helpers.LOG_TYPE.DEBUG);
},
error: function(err) {
helpers.logError('Failed to load page (' + page + ') => ' + err.statusText, helpers.LOG_TYPE.FORCE);
}
});
}
}
// Handles loading of tabs.
$('[data-folder]').on('click', function(e) {
e.preventDefault();
// Load the page.
loadPage($(this).data('folder'), $(this).attr('href').substring(1), this.href);
});
// Export to API.
$.showPage = showPage;
$.loadPage = loadPage;
});

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,16 @@
// Configuration for Control Panel
// Automatically Generated by PhantomBot at Startup
// Do NOT Modify! Overwritten when PhantomBot is restarted!
var panelSettings = {
panelPort : 25000,
channelName : "zino1337",
auth : "f5pJo1r6lQXorg50CeNLA8PL28taJv",
http : "https://"
, displayName : "zino1337"
, };
function getPanelPort() { return panelSettings.panelPort; }
function getChannelName() { return panelSettings.channelName; }
function getAuth() { return panelSettings.auth; }
function getProtocol() { return panelSettings.http; }
function getDisplayName() { return panelSettings.displayName; }

View File

@@ -0,0 +1,93 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>PhantomBot | Log in</title>
<!-- Tell the browser to be responsive to screen width -->
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
<!-- Bootstrap 3.3.7 -->
<link rel="stylesheet" href="/panel/vendors/bootstrap/css/bootstrap.min.css">
<!-- Theme style -->
<link rel="stylesheet" href="/panel/vendors/adminlte/css/AdminLTE.min.css">
<link rel="stylesheet" href="/panel/vendors/adminlte/css/skins/skin-purple.min.css">
<!-- Google fonts -->
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,300italic,400italic,600italic">
<!-- Custom style for the body height -->
<style>
body {
height: auto;
}
</style>
</head>
<!-- Main body -->
<body class="hold-transition login-page">
<div class="login-box">
<div class="login-logo">
<a href="https://phantombot.github.io/PhantomBot"><b>Phantom</b>Bot</a>
</div>
<div class="login-box-body">
<p class="login-box-msg">Log in to start your session</p>
<form action="/panel/login" method="POST">
<div class="form-group">
<input type="text" id="username" name="user" class="form-control" placeholder="Username">
</div>
<div class="form-group">
<input type="password" id="password" name="pass" class="form-control" placeholder="Password">
</div>
<div class="row">
<div class="col-xs-4 pull-right">
<input type="hidden" id="kickback" name="kickback" value="">
<button type="submit" id="login-button" class="btn btn-primary btn-block btn-flat">Login</button>
</div>
</div>
</form>
<!-- this could link to a how-to reset the password guide -->
<!-- <a href="#">Unable to login?</a><br> -->
</div>
</div>
<!-- jQuery 3 -->
<script src="/panel/vendors/jquery/jquery.min.js"></script>
<!-- Bootstrap 3.3.7 -->
<script src="/panel/vendors/bootstrap/js/bootstrap.min.js"></script>
<script>
$(function () {
var search = window.location.search.substr(1);
var kvs = search.split('&');
var searchmap = [];
var spl;
for (var i = 0; i < kvs.length; i++) {
spl = kvs[i].split('=', 2);
searchmap[spl[0]] = spl[1];
}
if (searchmap['kickback']) {
$('#kickback').val(searchmap['kickback']);
}
});
</script>
</body>
</html>

View File

@@ -0,0 +1,26 @@
/*
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
.transp50 {
transform: translate(50%);
}
.transm50 {
transform: translate(-50%);
}

View File

@@ -0,0 +1,326 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<main>
<!-- Header -->
<section class="content-header">
<h1>Chat Alerts</h1>
<ol class="breadcrumb">
<li><a href="javascript:void(0);"><i class="fa fa-dashboard"></i> Home</a></li>
<li>Alerts</li>
<li class="active">Chat</li>
</ol>
</section>
<!-- Main content -->
<section class="content">
<div class="row">
<!-- Follower Alerts -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Module toggle.">
<input type="checkbox" id="followHandlerToggle" data-alert-toggle="./handlers/followHandler.js" checked>
<span class="slider round"></span>
</label>
<button type="button" id="followHandlerSettings" class="btn btn-md btn-box-tool" style="margin-bottom: 7px;">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">Follower Alerts</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Welcome and also reward users who follow your channel.</p>
</div>
</form>
</div>
</div>
<!-- Subscriber Alerts -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Module toggle.">
<input type="checkbox" id="subscribeHandlerToggle" data-alert-toggle="./handlers/subscribeHandler.js" checked>
<span class="slider round"></span>
</label>
<button type="button" id="subscribeHandlerSettings" class="btn btn-md btn-box-tool" style="margin-bottom: 7px;">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">Subscriber Alerts</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Welcome and also reward users who subscribe to your channel.</p>
</div>
</form>
</div>
</div>
<!-- Host Alerts -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Module toggle.">
<input type="checkbox" id="hostHandlerToggle" data-alert-toggle="./handlers/hostHandler.js" checked>
<span class="slider round"></span>
</label>
<button type="button" id="hostHandlerSettings" class="btn btn-md btn-box-tool" style="margin-bottom: 7px;">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">Host Alerts</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Welcome and also reward users who host your channel.</p>
</div>
</form>
</div>
</div>
</div>
<div class="row">
<!-- Bits Alerts -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Module toggle.">
<input type="checkbox" id="bitsHandlerToggle" data-alert-toggle="./handlers/bitsHandler.js" checked>
<span class="slider round"></span>
</label>
<button type="button" id="bitsHandlerSettings" class="btn btn-md btn-box-tool" style="margin-bottom: 7px;">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">Bits Alerts</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Welcome and also reward users who cheer in your channel.</p>
</div>
</form>
</div>
</div>
<!-- Clips Alerts -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Module toggle.">
<input type="checkbox" id="clipHandlerToggle" data-alert-toggle="./handlers/clipHandler.js" checked>
<span class="slider round"></span>
</label>
<button type="button" id="clipHandlerSettings" class="btn btn-md btn-box-tool" style="margin-bottom: 7px;">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">Clip Alerts</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Let the bot post clips that viewers make into your chat.</p>
</div>
</form>
</div>
</div>
<!-- Raid Alerts -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Module toggle.">
<input type="checkbox" id="raidHandlerToggle" data-alert-toggle="./handlers/raidHandler.js" checked>
<span class="slider round"></span>
</label>
<button type="button" id="raidHandlerSettings" class="btn btn-md btn-box-tool" style="margin-bottom: 7px;">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">Raid Alerts</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Welcome users who raid your channel or raid them yourself.</p>
</div>
</form>
</div>
</div>
</div>
<div class="row">
<!-- Greeting Alerts -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Module toggle.">
<input type="checkbox" id="greetingSystemToggle" data-alert-toggle="./systems/greetingSystem.js" checked>
<span class="slider round"></span>
</label>
<button type="button" id="greetingSystemSettings" class="btn btn-md btn-box-tool" style="margin-bottom: 7px;">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">Greeting Alerts</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Let users set a custom message to be said in the chat when they join.</p>
</div>
</form>
</div>
</div>
<!-- StreamLabs Alerts -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Module toggle.">
<input type="checkbox" id="donationHandlerToggle" data-alert-toggle="./handlers/donationHandler.js" checked>
<span class="slider round"></span>
</label>
<button type="button" id="donationHandlerSettings" class="btn btn-md btn-box-tool" style="margin-bottom: 7px;">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">StreamLabs Alerts</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Thank and also reward users who send you a tip with StreamLabs.</p>
</div>
</form>
</div>
</div>
<!-- TipeeeStream Alerts -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Module toggle.">
<input type="checkbox" id="tipeeeStreamHandlerToggle" data-alert-toggle="./handlers/tipeeeStreamHandler.js" checked>
<span class="slider round"></span>
</label>
<button type="button" id="tipeeeStreamHandlerSettings" class="btn btn-md btn-box-tool" style="margin-bottom: 7px;">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">TipeeeStream Alerts</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Thank and also reward users who send you a tip with TipeeeStream.</p>
</div>
</form>
</div>
</div>
</div>
<div class="row">
<!-- StreamElements Alerts -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Module toggle.">
<input type="checkbox" id="streamElementsHandlerToggle" data-alert-toggle="./handlers/streamElementsHandler.js" checked>
<span class="slider round"></span>
</label>
<button type="button" id="streamElementsHandlerSettings" class="btn btn-md btn-box-tool" style="margin-bottom: 7px;">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">StreamElements Alerts</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Thank and also reward users who send you a tip with StreamElements.</p>
</div>
</form>
</div>
</div>
<!-- Twitter Alerts -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Module toggle.">
<input type="checkbox" id="twitterHandlerToggle" data-alert-toggle="./handlers/twitterHandler.js" checked>
<span class="slider round"></span>
</label>
<button type="button" id="twitterHandlerSettings" class="btn btn-md btn-box-tool" style="margin-bottom: 7px;">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">Twitter Alerts</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Keep your chat updated with your Tweets and let the bot Tweet when you go live.</p>
</div>
</form>
</div>
</div>
</div>
</section>
<!-- alerts -->
<script src="/panel/js/pages/alerts/alerts.js"></script>
</main>

View File

@@ -0,0 +1,87 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<main>
<!-- Header -->
<section class="content-header">
<h1>Stream Alerts</h1>
<ol class="breadcrumb">
<li><a href="javascript:void(0);"><i class="fa fa-dashboard"></i> Home</a></li>
<li>Alerts</li>
<li class="active">Stream</li>
</ol>
</section>
<!-- Main content -->
<section class="content">
<div class="nav-tabs-custom">
<ul class="nav nav-tabs">
<li class="active"><a href="#stream_alerts_general" data-toggle="tab">Main Settings</a></li>
<li><a href="#stream_alerts_follow" data-toggle="tab">Follows</a></li>
<li><a href="#stream_alerts_subs" data-toggle="tab">Subscriptions</a></li>
<li><a href="#stream_alerts_hosts" data-toggle="tab">Hosts</a></li>
<li><a href="#stream_alerts_raids" data-toggle="tab">Raids</a></li>
<li><a href="#stream_alerts_bits" data-toggle="tab">Bits</a></li>
<li><a href="#stream_alerts_clips" data-toggle="tab">Cips</a></li>
<li><a href="#stream_alerts_twitter" data-toggle="tab">Twitter</a></li>
</ul>
<div class="tab-content">
<!-- Main settings tab. -->
<div class="tab-pane active" id="stream_alerts_general">
</div>
<!-- Followers settings tab. -->
<div class="tab-pane" id="stream_alerts_follow">
</div>
<!-- Subscribers settings tab. -->
<div class="tab-pane" id="stream_alerts_subs">
</div>
<!-- Hosts settings tab. -->
<div class="tab-pane" id="stream_alerts_hosts">
</div>
<!-- Raids settings tab. -->
<div class="tab-pane" id="stream_alerts_raids">
</div>
<!-- Bits settings tab. -->
<div class="tab-pane" id="stream_alerts_bits">
</div>
<!-- Clips settings tab. -->
<div class="tab-pane" id="stream_alerts_clips">
</div>
<!-- Twitter settings tab. -->
<div class="tab-pane" id="stream_alerts_twitter">
</div>
</div>
</div>
</section>
<!-- alerts -->
<script src="/panel/js/pages/alerts/stream.js"></script>
</main>

View File

@@ -0,0 +1,72 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<main>
<!-- Header -->
<section class="content-header">
<!-- Page title and switch toggle. -->
<h1>Audio Hooks
<label class="switch" data-toggle="tooltip" title="Module toggle">
<input type="checkbox" id="audioHookModuleToggle" checked>
<span class="slider round"></span>
</label>
</h1>
<ol class="breadcrumb">
<li><a href="javascript:void(0);"><i class="fa fa-dashboard"></i> Home</a></li>
<li>Audio</li>
<li class="active">Audio Hooks</li>
</ol>
</section>
<!-- Main content -->
<section class="content">
<div class="nav-tabs-custom">
<ul class="nav nav-tabs">
<li class="active"><a href="#audiohooks" id="audiohooks_t" data-toggle="tab">Audio Hooks</a></li>
<li><a href="#audiocommands" id="audiocommands_t" data-toggle="tab">Audio Commands</a></li>
</ul>
<div class="tab-content" id="audioHookModule">
<!-- Audio hook list -->
<div class="tab-pane active" id="audiohooks">
<div class="btn-toolbar pull-right">
<button class="btn btn-primary btn-sm" type="button" id="reload-audio-hooks" data-toggle="tooltip"
title="In case that you added an audio hook and didn't restart the bot, this will reload all audio hooks and add the new one(s).">
<i class="fa fa-refresh"></i>&nbsp; Refresh List
</button>
<button class="btn btn-success btn-sm" type="button" id="audio-hooks-settings"><i class="fa fa-external-link"></i>&nbsp; Browser Source</button>
</div>
<table id="audioHooksTable" class="table table-bordered table-hover"></table>
</div>
<!-- Audio commands -->
<div class="tab-pane" id="audiocommands">
<div class="btn-toolbar pull-right">
<button class="btn btn-primary btn-sm" type="button" id="audio-hooks-cmd-add"><i class="fa fa-plus"></i>&nbsp; Add Command</button>
<!-- Comming soon tm. -->
<!-- <button class="btn btn-default btn-sm" type="button" id="audio-hooks-cmd-settings"><i class="fa fa-cog"></i>&nbsp; Settings</button> -->
</div>
<table id="audioHookCommandsTable" class="table table-bordered table-hover"></table>
</div>
</div>
</div>
</section>
<!-- audioHooks -->
<script src="/panel/js/pages/audio/audioHooks.js"></script>
</main>

View File

@@ -0,0 +1,56 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<main>
<!-- Header -->
<section class="content-header">
<h1>Commands</h1>
<ol class="breadcrumb">
<li><a href="javascript:void(0);"><i class="fa fa-dashboard"></i> Home</a></li>
<li>Commands</li>
<li class="active">Aliases</li>
</ol>
</section>
<!-- Main content -->
<section class="content">
<div class="box box-solid">
<div class="box-header with-border">
<label class="switch" data-toggle="tooltip" title="Module toggle">
<input type="checkbox" id="aliasesModuleToggle" checked>
<span class="slider round"></span>
</label>
<h3 class="box-title">Command Aliases</h3>
</div>
<form role="form" id="aliasesModule">
<!-- Box content -->
<div class="box-body">
<button class="btn btn-primary btn-sm pull-right" type="button" id="aliascom-button"><i class="fa fa-plus"></i>&nbsp; Add Alias</button>
<div class="load-ajax">
<div class="spinner"></div>
<p class="load-ajax-text">Loading...</p>
</div>
<table id="aliasesTable" class="table table-bordered table-hover"></table>
</div>
</form>
</div>
</section>
<!-- aliases -->
<script src="/panel/js/pages/commands/aliases.js"></script>
</main>

View File

@@ -0,0 +1,61 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<main>
<!-- Header -->
<section class="content-header">
<h1>Commands</h1>
<ol class="breadcrumb">
<li><a href="javascript:void(0);"><i class="fa fa-dashboard"></i> Home</a></li>
<li>Commands</li>
<li class="active">Custom</li>
</ol>
</section>
<!-- Main content -->
<section class="content">
<div class="box box-solid">
<div class="box-header with-border">
<label class="switch" data-toggle="tooltip" title="Module toggle">
<input type="checkbox" id="customCommandsModuleToggle" checked>
<span class="slider round"></span>
</label>
<h3 class="box-title">Custom Commands</h3>
</div>
<form role="form" id="customCommandsModule">
<!-- Box content -->
<div class="box-body">
<div class="btn-toolbar pull-right">
<button class="btn btn-primary btn-sm" type="button" id="addcom-button"><i class="fa fa-plus"></i>&nbsp; Add Command</button>
<button class="btn btn-default btn-sm" type="button" onclick="window.open('https://phantombot.github.io/PhantomBot/guides/#guide=content/commands/command-variables');">
<i class="fa fa-info"></i>&nbsp; Variables
</button>
</div>
<div class="load-ajax">
<div class="spinner"></div>
<p class="load-ajax-text">Loading...</p>
</div>
<table id="customCommandsTable" class="table table-bordered table-hover"></table>
</div>
</form>
</div>
</section>
<!-- custom commands -->
<script src="/panel/js/pages/commands/custom.js"></script>
</main>

View File

@@ -0,0 +1,57 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<main>
<!-- Overwrite styles -->
<style>
.dataTables_filter {
float: right;
text-align: right;
}
</style>
<!-- Header -->
<section class="content-header">
<h1>Commands</h1>
<ol class="breadcrumb">
<li><a href="javascript:void(0);"><i class="fa fa-dashboard"></i> Home</a></li>
<li>Commands</li>
<li class="active">Default</li>
</ol>
</section>
<!-- Main content -->
<section class="content">
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title">Default Commands</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<div class="load-ajax">
<div class="spinner"></div>
<p class="load-ajax-text">Loading...</p>
</div>
<table id="defaultCommandsTable" class="table table-bordered table-hover"></table>
</div>
</form>
</div>
</section>
<!-- default commands -->
<script src="/panel/js/pages/commands/default.js"></script>
</main>

View File

@@ -0,0 +1,226 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<main>
<!-- Header -->
<section class="content-header">
<h1>Dashboard</h1>
<ol class="breadcrumb">
<li><a href="javascript:void(0);"><i class="fa fa-dashboard"></i> Home</a></li>
<li class="active">Dashboard</li>
</ol>
</section>
<!-- Main content -->
<section class="content">
<!-- Information Boxes Top -->
<div class="row">
<!-- Uptime Box -->
<div class="col-lg-3 col-xs-6">
<div class="small-box bg-red" id="bg-uptime" data-toggle="tooltip" title="How long the current broadcast has been live for.">
<div class="inner">
<h3 id="dashboard-uptime">Offline</h3>
<p>Uptime</p>
</div>
<div class="icon">
<i class="fa fa-clock-o"></i>
</div>
</div>
</div>
<!-- Views Box -->
<div class="col-lg-3 col-xs-6">
<div class="small-box bg-teal" data-toggle="tooltip" title="The number of people who have viewed your channel. Click the number to hide.">
<div class="inner">
<h3 id="dashboard-views" style="cursor: pointer;">0</h3>
<p>Views</p>
</div>
<div class="icon">
<i class="fa fa-eye"></i>
</div>
</div>
</div>
<!-- Followers Box -->
<div class="col-lg-3 col-xs-6">
<div class="small-box bg-purple" data-toggle="tooltip" title="The number of followers the channel currently has. Click the number to hide.">
<div class="inner">
<h3 id="dashboard-followers" style="cursor: pointer;">0</h3>
<p>Followers</p>
</div>
<div class="icon">
<i class="fa fa-heart"></i>
</div>
</div>
</div>
<!-- Viewers Box -->
<div class="col-lg-3 col-xs-6">
<div class="small-box bg-yellow" data-toggle="tooltip" title="The number of people currently watching the broadcast. Click the number to hide.">
<div class="inner">
<h3 id="dashboard-viewers" style="cursor: pointer;">0</h3>
<p>Viewers</p>
</div>
<div class="icon icon-override">
<i class="fa fa-users"></i>
</div>
</div>
</div>
</div>
<div class="row">
<!-- Left section -->
<section class="col-lg-7">
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title">Recent Events</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<div class="event-log">
</div>
</div>
</form>
</div>
<!-- Split the section in half. -->
<div class="row">
<!-- Left section -->
<div class="col-md-6" id="twitch-chat-box">
<div class="box box-solid">
<div id="twitch-chat-iframe"></div>
</div>
</div>
<!-- Right section -->
<div class="col-md-6" id="twitch-player-box">
<div class="box box-solid">
<div id="twitch-player-iframe"></div>
</div>
</div>
</div>
</section>
<!-- Right section -->
<section class="col-lg-5">
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title">Stream Information</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<!-- Stream Title Input -->
<div class="form-group">
<label>Title</label>
<input type="text" class="form-control" id="stream-title" placeholder="Title This Broadcast" data-str="text" data-toggle="tooltip" title="The current stream title">
</div>
<!-- Stream Game Input -->
<div class="form-group">
<label>Game</label>
<input type="text" class="form-control" id="stream-game" placeholder="Search for a Game or Category" data-str="text" data-toggle="tooltip" title="The current stream game">
</div>
</div>
<!-- Footer of the box -->
<div class="box-footer">
<button type="button" class="btn btn-primary pull-right" id="dashboard-btn-update" data-candisable="true">Update</button>
</div>
</form>
</div>
<!-- Quick action box -->
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title">Quick Actions</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<!-- Permit user -->
<div class="form-group">
<label>User Action</label>
<div class="input-group input-group-md">
<input type="text" class="form-control" id="user-action-user" placeholder="Username" data-toggle="tooltip" title="Enter a username.">
<div class="input-group-btn">
<button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false" aria-haspopup="true">Actions
<span class="fa fa-caret-down"></span>
</button>
<ul class="dropdown-menu pull-right">
<li class="user-action"><a href="#">Permit</a></li>
<li class="user-action"><a href="#">Shoutout</a></li>
<li class="user-action"><a href="#">Raid</a></li>
<li class="user-action"><a href="#">Host</a></li>
</ul>
</div>
</div>
</div>
<!-- Run command -->
<div class="form-group">
<label for="custom-command-run">Run Command</label>
<select class="form-control select2 select2-hidden-accessible" id="custom-command-run" style="width: 100%;" aria-hidden="true">
<option></option>
</select>
</div>
<!-- Run commercial -->
<div class="form-group" id="grp-instant-commercial">
<label>Run Commercial</label>
<div class="input-group input-group-md">
<select class="form-control select2 select2-hidden-accessible" id="instant-commercial-length" data-toggle="tooltip" title="Commercial length, in seconds." aria-hidden="true">
<option></option>
<option>30</option>
<option>60</option>
<option>90</option>
<option>120</option>
<option>150</option>
<option>180</option>
</select>
<span class="input-group-addon" style="border: 0;">
<span class="pretty p-icon">
<input id="instant-commercial-silent" type="checkbox" data-toggle="tooltip" title="If checked, the bot won't announce the commercial in chat.">
<span class="state p-default">
<i class="icon fa fa-check"></i>
<label>Silent</label>
</span>
</span>
</span>
<span class="input-group-btn">
<button type="button" class="btn btn-primary pull-right" id="dashboard-btn-instant-commercial" data-candisable="true">Run</button>
</span>
</div>
</div>
<!-- Send as bot -->
<div class="form-group">
<label>Send Message as Bot</label>
<div class="input-group input-group-md">
<input type="text" class="form-control" id="msg-bot" placeholder="Message" data-toggle="tooltip" title="Enter a message.">
<span class="input-group-btn">
<button type="button" class="btn btn-primary pull-right" id="dashboard-btn-msg-bot" data-candisable="true">Send</button>
</span>
</div>
</div>
</div>
</form>
</div>
</section>
</div>
</section>
<!-- dashboard -->
<script src="/panel/js/pages/dashboard/dashboard.js"></script>
</main>

View File

@@ -0,0 +1,326 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<main>
<!-- Header -->
<section class="content-header">
<h1>Discord Alerts</h1>
<ol class="breadcrumb">
<li><a href="javascript:void(0);"><i class="fa fa-dashboard"></i> Home</a></li>
<li>Discord</li>
<li class="active">Alerts</li>
</ol>
</section>
<!-- Main content -->
<section class="content">
<div class="row">
<!-- Follower Alerts -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Module toggle.">
<input type="checkbox" id="followHandlerToggle" data-alert-toggle="./discord/handlers/followHandler.js" checked >
<span class="slider round"></span>
</label>
<button type="button" id="discordFollowHandlerSettings" class="btn btn-md btn-box-tool" style="margin-bottom: 7px;">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">Follower Alerts</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Display new followers from Twitch into a Discord channel.</p>
</div>
</form>
</div>
</div>
<!-- Subscriber Alerts -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Module toggle.">
<input type="checkbox" id="subscribeHandlerToggle" data-alert-toggle="./discord/handlers/subscribeHandler.js" checked>
<span class="slider round"></span>
</label>
<button type="button" id="discordSubscribeHandlerSettings" class="btn btn-md btn-box-tool" style="margin-bottom: 7px;">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">Subscriber Alerts</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Display new subscribers from Twitch into a Discord channel.</p>
</div>
</form>
</div>
</div>
<!-- Host Alerts -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Module toggle.">
<input type="checkbox" id="hostHandlerToggle" data-alert-toggle="./discord/handlers/hostHandler.js" checked>
<span class="slider round"></span>
</label>
<button type="button" id="discordHostHandlerSettings" class="btn btn-md btn-box-tool" style="margin-bottom: 7px;">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">Host Alerts</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Display hosts from Twitch into a Discord channel.</p>
</div>
</form>
</div>
</div>
</div>
<div class="row">
<!-- Bits Alerts -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Module toggle.">
<input type="checkbox" id="bitsHandlerToggle" data-alert-toggle="./discord/handlers/bitsHandler.js" checked>
<span class="slider round"></span>
</label>
<button type="button" id="discordBitsHandlerSettings" class="btn btn-md btn-box-tool" style="margin-bottom: 7px;">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">Bits Alerts</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Display cheers from Twitch into a Discord channel.</p>
</div>
</form>
</div>
</div>
<!-- Clips Alerts -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Module toggle.">
<input type="checkbox" id="clipHandlerToggle" data-alert-toggle="./discord/handlers/clipHandler.js" checked>
<span class="slider round"></span>
</label>
<button type="button" id="discordClipHandlerSettings" class="btn btn-md btn-box-tool" style="margin-bottom: 7px;">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">Clip Alerts</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Display new clips from Twitch into a Discord channel.</p>
</div>
</form>
</div>
</div>
<!-- Twitch Stream Alerts -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Module toggle.">
<input type="checkbox" id="streamHandlerToggle" data-alert-toggle="./discord/handlers/streamHandler.js" checked>
<span class="slider round"></span>
</label>
<button type="button" id="discordStreamHandlerSettings" class="btn btn-md btn-box-tool" style="margin-bottom: 7px;">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">Stream Alerts</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Post in a Discord channel when you go live on Twitch.</p>
</div>
</form>
</div>
</div>
</div>
<div class="row">
<!-- Greeting Alerts -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Module toggle.">
<input type="checkbox" id="greetingsSystemToggle" data-alert-toggle="./discord/systems/greetingsSystem.js" checked>
<span class="slider round"></span>
</label>
<button type="button" id="discordGreetingsSystemSettings" class="btn btn-md btn-box-tool" style="margin-bottom: 7px;">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">Greeting Alerts</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Welcome new users who join your Discord server and give them a role.</p>
</div>
</form>
</div>
</div>
<!-- StreamLabs Alerts -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Module toggle.">
<input type="checkbox" id="streamlabsHandlerToggle" data-alert-toggle="./discord/handlers/streamlabsHandler.js" checked>
<span class="slider round"></span>
</label>
<button type="button" id="discordStreamlabsHandlerSettings" class="btn btn-md btn-box-tool" style="margin-bottom: 7px;">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">StreamLabs Alerts</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Display StreamLabs tips into a Discord channel.</p>
</div>
</form>
</div>
</div>
<!-- TipeeeStream Alerts -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Module toggle.">
<input type="checkbox" id="tipeeeStreamHandlerToggle" data-alert-toggle="./discord/handlers/tipeeeStreamHandler.js" checked>
<span class="slider round"></span>
</label>
<button type="button" id="discordTipeeeStreamHandlerSettings" class="btn btn-md btn-box-tool" style="margin-bottom: 7px;">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">TipeeeStream Alerts</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Display TipeeeStream tips into a Discord channel.</p>
</div>
</form>
</div>
</div>
</div>
<div class="row">
<!-- StreamElements Alerts -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Module toggle.">
<input type="checkbox" id="streamElementsHandlerToggle" data-alert-toggle="./discord/handlers/streamElementsHandler.js" checked>
<span class="slider round"></span>
</label>
<button type="button" id="discordStreamElementsHandlerSettings" class="btn btn-md btn-box-tool" style="margin-bottom: 7px;">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">StreamElements Alerts</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Display StreamElements tips into a Discord channel.</p>
</div>
</form>
</div>
</div>
<!-- Twitter Alerts -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Module toggle.">
<input type="checkbox" id="twitterHandlerToggle" data-alert-toggle="./discord/handlers/twitterHandler.js" checked>
<span class="slider round"></span>
</label>
<button type="button" id="discordTwitterHandlerSettings" class="btn btn-md btn-box-tool" style="margin-bottom: 7px;">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">Twitter Alerts</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Display your Tweets into a Discord channel.</p>
</div>
</form>
</div>
</div>
</div>
</section>
<!-- discordAlerts -->
<script src="/panel/js/pages/discord/discordAlerts.js"></script>
</main>

View File

@@ -0,0 +1,56 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<main>
<!-- Header -->
<section class="content-header">
<h1>Discord Commands</h1>
<ol class="breadcrumb">
<li><a href="javascript:void(0);"><i class="fa fa-dashboard"></i> Home</a></li>
<li>Discord</li>
<li>Commands</li>
<li class="active">Custom</li>
</ol>
</section>
<!-- Main content -->
<section class="content">
<div class="box box-solid">
<div class="box-header with-border">
<label class="switch" data-toggle="tooltip" title="Module toggle">
<input type="checkbox" id="discordCustomCommandsModuleToggle" checked>
<span class="slider round"></span>
</label>
<h3 class="box-title">Custom Discord Commands</h3>
</div>
<form role="form" id="discordCustomCommandsModule">
<!-- Box content -->
<div class="box-body">
<div class="btn-toolbar pull-right">
<button class="btn btn-primary btn-sm" type="button" id="discord-addcom-button"><i class="fa fa-plus"></i>&nbsp; Add Command</button>
<button class="btn btn-default btn-sm" type="button" onclick="window.open('https://phantombot.github.io/PhantomBot/guides/#guide=content/commands/discord-command-variables');">
<i class="fa fa-info"></i>&nbsp; Variables</button>
</div>
<table id="discordCustomCommandsTable" class="table table-bordered table-hover"></table>
</div>
</form>
</div>
</section>
<!-- custom commands -->
<script src="/panel/js/pages/discord/discordCustomCommands.js"></script>
</main>

View File

@@ -0,0 +1,53 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<main>
<!-- Overwrite styles -->
<style>
.dataTables_filter {
float: right;
text-align: right;
}
</style>
<!-- Header -->
<section class="content-header">
<h1>Discord Commands</h1>
<ol class="breadcrumb">
<li><a href="javascript:void(0);"><i class="fa fa-dashboard"></i> Home</a></li>
<li>Discord</li>
<li>Commands</li>
<li class="active">Default</li>
</ol>
</section>
<!-- Main content -->
<section class="content">
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title">Default Discord Commands</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<table id="discordDefaultCommandsTable" class="table table-bordered table-hover"></table>
</div>
</form>
</div>
</section>
<!-- default commands -->
<script src="/panel/js/pages/discord/discordDefaultCommands.js"></script>
</main>

View File

@@ -0,0 +1,225 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<main>
<!-- Header -->
<section class="content-header">
<h1>Discord Games</h1>
<ol class="breadcrumb">
<li><a href="javascript:void(0);"><i class="fa fa-dashboard"></i> Home</a></li>
<li>Discord</li>
<li class="active">Games</li>
</ol>
</section>
<!-- Main content -->
<section class="content">
<div class="row">
<!-- Dice Roll game -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Module toggle.">
<input type="checkbox" id="discord_rollToggle" data-game-toggle="./discord/games/roll.js" checked>
<span class="slider round"></span>
</label>
<button type="button" id="discord_rollSettings" class="btn btn-md btn-box-tool" style="margin-bottom: 7px;">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">Dice Roll</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Let your viewers role the dices and see if they get lucky.</p>
</div>
</form>
</div>
</div>
<!-- Gambling game -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Module toggle.">
<input type="checkbox" id="discord_gamblingToggle" data-game-toggle="./discord/games/gambling.js" checked>
<span class="slider round"></span>
</label>
<button type="button" id="discord_gamblingSettings" class="btn btn-md btn-box-tool" style="margin-bottom: 7px;">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">Gambling</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Let your viewers gamble all of their points or get lucky and win big.</p>
</div>
</form>
</div>
</div>
<!-- Slot Machine game -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Module toggle.">
<input type="checkbox" id="discord_slotMachineToggle" data-game-toggle="./discord/games/slotMachine.js" checked>
<span class="slider round"></span>
</label>
<button type="button" id="discord_slotMachineSettings" class="btn btn-md btn-box-tool" style="margin-bottom: 7px;">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">Slot Machine</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Let your viewers pull the lever and see if they get matching emotes.</p>
</div>
</form>
</div>
</div>
</div>
<div class="row">
<!-- Kill game -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Module toggle.">
<input type="checkbox" id="discord_killCommandToggle" data-game-toggle="./discord/games/kill.js" checked>
<span class="slider round"></span>
</label>
<button type="button" class="btn btn-md btn-box-tool disabled" data-toggle="tooltip" title="This module doesn't have any settings."
style="margin-bottom: 7px;">
<i class="fa fa-cog fa-lg disabled"></i>
</button>
</div>
<h3 class="box-title">Kill Game</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Let your viewers try to "kill" each other in chat without getting caught by the cops.</p>
</div>
</form>
</div>
</div>
<!-- 8ball game -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Module toggle.">
<input type="checkbox" id="discord_8ballToggle" data-game-toggle="./discord/games/8ball.js" checked>
<span class="slider round"></span>
</label>
<button type="button" class="btn btn-md btn-box-tool disabled" data-toggle="tooltip" title="This module doesn't have any settings."
style="margin-bottom: 7px;">
<i class="fa fa-cog fa-lg disabled"></i>
</button>
</div>
<h3 class="box-title">Magic 8-ball</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Have any questions? Ask the Magic 8-ball anything and it will guide you.</p>
</div>
</form>
</div>
</div>
<!-- Roulette game -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Module toggle.">
<input type="checkbox" id="discord_rouletteToggle" data-game-toggle="./discord/games/roulette.js" checked>
<span class="slider round"></span>
</label>
<button type="button" class="btn btn-md btn-box-tool disabled" data-toggle="tooltip" title="This module doesn't have any settings."
style="margin-bottom: 7px;">
<i class="fa fa-cog fa-lg disabled"></i>
</button>
</div>
<h3 class="box-title">Russian Roulette</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Let your viewers play Russian roulette to test their luck.</p>
</div>
</form>
</div>
</div>
</div>
<div class="row">
<!-- Random game -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Module toggle.">
<input type="checkbox" id="discord_randomToggle" data-game-toggle="./discord/games/random.js" checked>
<span class="slider round"></span>
</label>
<button type="button" class="btn btn-md btn-box-tool disabled" data-toggle="tooltip" title="This module doesn't have any settings."
style="margin-bottom: 7px;">
<i class="fa fa-cog fa-lg disabled"></i>
</button>
</div>
<h3 class="box-title">Random Command</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Let Discord get weird real fast with random responses from the bot.</p>
</div>
</form>
</div>
</div>
</div>
</section>
<!-- games -->
<script src="/panel/js/pages/discord/discordGames.js"></script>
</main>

View File

@@ -0,0 +1,51 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<main>
<!-- Header -->
<section class="content-header">
<h1>Discord Keywords</h1>
<ol class="breadcrumb">
<li><a href="javascript:void(0);"><i class="fa fa-dashboard"></i> Home</a></li>
<li>Discord</li>
<li class="active">Keywords</li>
</ol>
</section>
<!-- Main content -->
<section class="content">
<div class="box box-solid">
<div class="box-header with-border">
<label class="switch" data-toggle="tooltip" title="Module toggle">
<input type="checkbox" id="discordKeywordsModuleToggle" checked>
<span class="slider round"></span>
</label>
<h3 class="box-title">Discord Keywords</h3>
</div>
<form role="form" id="discordKeywordsModule">
<!-- Box content -->
<div class="box-body">
<button class="btn btn-primary btn-sm pull-right" type="button" id="discord-addkey-button"><i class="fa fa-plus"></i>&nbsp; Add Keyword</button>
<table id="discordKeywordTable" class="table table-bordered table-hover"></table>
</div>
</form>
</div>
</section>
<!-- default keywords -->
<script src="/panel/js/pages/discord/discordKeywords.js"></script>
</main>

View File

@@ -0,0 +1,88 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<main>
<!-- Header -->
<section class="content-header">
<!-- Page title.-->
<h1>Discord Logging</h1>
<ol class="breadcrumb">
<li><a href="javascript:void(0);"><i class="fa fa-dashboard"></i> Home</a></li>
<li>Discord</li>
<li class="active">Logging</li>
</ol>
</section>
<!-- Main content -->
<section class="content">
<div class="nav-tabs-custom">
<ul class="nav nav-tabs">
<li class="active"><a href="#discord_logs_pubsub" data-toggle="tab">Twitch Moderation</a></li>
<li><a href="#discord_logs_cmds" data-toggle="tab">Twitch Commands</a></li>
</ul>
<div class="tab-content">
<!-- Twitch Moderation -->
<div class="tab-pane active" id="discord_logs_pubsub">
<div class="form-group">
<label>Enable Twitch Moderation Logs</label>
<div class="dropdown">
<select class="form-control" id="twitch-mod-log" data-toggle="tooltip"
title="Enables the moderation logs for the bot. A restart is required after enabling." style="cursor: pointer;">
<option>Yes</option>
<option>No</option>
</select>
</div>
</div>
<div class="form-group">
<label>Logging Channel</label>
<input type="text" class="form-control" id="twitch-mod-channel" placeholder="#logs" data-toggle="tooltip"
title="Which channel to post the moderation logs to."/>
</div>
</div>
<!-- Twitch Commands -->
<div class="tab-pane" id="discord_logs_cmds">
<div class="form-group">
<label>Enable Twitch Command Logs</label>
<div class="dropdown">
<select class="form-control" id="twitch-command-log" data-toggle="tooltip"
title="Enables the logging for command edit, removing, and adding for Twitch." style="cursor: pointer;">
<option>Yes</option>
<option>No</option>
</select>
</div>
</div>
<div class="form-group">
<label>Logging Channel</label>
<input type="text" class="form-control" id="twitch-command-channel" placeholder="#logs" data-toggle="tooltip"
title="Which channel to post the command logs to. Currently the same as the moderation log one." disabled />
</div>
</div>
<!-- Box footer -->
<div class="box-footer" style="padding-right: 0; padding-bottom: 0;">
<button type="button" class="btn btn-primary pull-right" id="discord-logging-save"> Save</button>
</div>
</div>
</div>
</section>
<!-- discordLogs -->
<script src="/panel/js/pages/discord/discordLogs.js"></script>
</main>

View File

@@ -0,0 +1,85 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<main>
<!-- Chart location and size -->
<style>
canvas {
padding: 0;
margin: auto;
display: block;
width: 450px;
}
</style>
<!-- Header -->
<section class="content-header">
<h1>Betting
<label class="switch" data-toggle="tooltip" title="Module toggle">
<input type="checkbox" id="bettingSystemModuleToggle" checked>
<span class="slider round"></span>
</label>
</h1>
<ol class="breadcrumb">
<li><a href="javascript:void(0);"><i class="fa fa-dashboard"></i> Home</a></li>
<li>Extra</li>
<li class="active">Betting</li>
</ol>
</section>
<!-- Main content -->
<section class="content">
<div class="row">
<!-- Poll menu -->
<div class="col-md-8">
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title">Bet</h3>
<span class="pull-right">
<a href="javascript:void(0)" class="text-muted" data-toggle="tooltip" title="Betting settings" id="settings-betting">
<i class="fa fa-gears"></i>
</a>
</span>
</div>
<form role="form" id="bettingSystemModule">
<!-- Box content -->
<div class="box-body">
<div class="btn-toolbar pull-right">
<button class="btn btn-success" type="button" id="open-betting"><i class="fa fa-unlock-alt"></i>&nbsp; Open</button>
<button class="btn btn-warning" type="button" id="close-betting"><i class="fa fa-lock"></i>&nbsp; Close</button>
<button class="btn btn-danger" type="button" id="reset-betting"><i class="fa fa-trash"></i>&nbsp; Reset</button>
</div>
<canvas width="450" height="450" id="betting-chart" style="margin-top: 50px !important;"></canvas>
</div>
</form>
</div>
</div>
<!-- Twitch chat. -->
<div class="col-md-4">
<div id="twitch-chat-betting"></div>
</div>
</div>
</section>
<!-- betting -->
<script src="/panel/js/pages/extra/betting.js"></script>
<!-- chartjs -->
<script src="/panel/vendors/chart.js/Chart.bundle.min.js"></script>
</main>

View File

@@ -0,0 +1,80 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<main>
<!-- Header -->
<section class="content-header">
<h1>Automatic Commercials</h1>
<ol class="breadcrumb">
<li><a href="javascript:void(0);"><i class="fa fa-dashboard"></i> Home</a></li>
<li>Extra</li>
<li class="active">Automatic Commercials</li>
</ol>
</section>
<!-- Main content -->
<section class="content">
<div class="box box-solid">
<div class="box-header with-border">
<label class="switch" data-toggle="tooltip" title="Module toggle">
<input type="checkbox" id="commercialsModuleToggle" checked>
<span class="slider round"></span>
</label>
<h3 class="box-title">Automatic Commercials</h3>
</div>
<form role="form" id="commercialsModule">
<!-- Box content -->
<div class="box-body">
<!-- Commercial Interval -->
<div class="form-group">
<label>Interval Between Automatic Commercials, in Minutes</label>
<input type="number" class="form-control" id="commercial-interval" value="8" min="8" data-toggle="tooltip" title="Interval between commercials, minimum 8."/>
</div>
<!-- Commercial Length -->
<div class="form-group">
<label for="commercial-length">Commercial Length, in Seconds</label>
<select class="form-control" id="commercial-length">
<option selected="selected">30</option>
<option>60</option>
<option>90</option>
<option>120</option>
<option>150</option>
<option>180</option>
</select>
</div>
<!-- Optional Commercial Message -->
<div class="form-group">
<label>Optional Message Posted to Chat</label>
<input type="text" class="form-control" id="commercial-message" placeholder="Optional message posted to chat"
data-toggle="tooltip" title="Optional message posted to chat."/>
</div>
</div>
<!-- Footer with buttons -->
<div class="box-footer">
<div class="btn-toolbar pull-right">
<button class="btn btn-success" type="button" id="commercials-autotimer-on"><i class="fa fa-check"></i>&nbsp; Set Autotimer</button>
<button class="btn btn-danger hidden" type="button" id="commercials-autotimer-off"><i class="fa fa-trash"></i>&nbsp; Disable Autotimer</button>
</div>
</div>
</form>
</div>
</section>
<!-- commercials -->
<script src="/panel/js/pages/extra/commercials.js"></script>
</main>

View File

@@ -0,0 +1,84 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<main>
<!-- Custom styles for this page -->
<style>
.center {
display: flex;
align-items: center;
justify-content: center;
}
.bottom {
top: 100%;
}
.death-total {
margin-bottom: 20px;
margin-top: 50px;
font-size: 45px;
/*background-color: #000;*/
}
</style>
<!-- Header -->
<section class="content-header">
<h1>Death Counter</h1>
<ol class="breadcrumb">
<li><a href="javascript:void(0);"><i class="fa fa-dashboard"></i> Home</a></li>
<li>Extra</li>
<li class="active">Death Counter</li>
</ol>
</section>
<!-- Main content -->
<section class="content">
<div class="box box-solid">
<div class="box-header with-border">
<label class="switch" data-toggle="tooltip" title="Module toggle">
<input type="checkbox" id="deathCounterModuleToggle" checked>
<span class="slider round"></span>
</label>
<h3 class="box-title">Death Counter</h3>
</div>
<form role="form" id="deathCounterModule">
<!-- Box content -->
<div class="box-body">
<button class="btn btn-primary pull-right" type="button" id="settings-deaths-button"><i class="fa fa-cog"></i>&nbsp; Settings</button>
<div class="death-total center">
<span>Deaths:&nbsp;</span>
<span id="death-number">0</span>
</div>
<div class="btn-toolbar center">
<button class="btn btn-success" type="button" id="incr-deaths-button"
data-toggle="tooltip" title="Increases the death for this game by one."><i class="fa fa-plus"></i>&nbsp; Increase</button>
<button class="btn btn-warning" type="button" id="decr-deaths-button"
data-toggle="tooltip" title="Decreases the death for this game by one."><i class="fa fa-minus"></i>&nbsp; Decrease</button>
<button class="btn btn-danger" type="button" id="reset-deaths-button"
data-toggle="tooltip" title="Resets the deaths for this game back to 0."><i class="fa fa-eraser"></i>&nbsp; Reset</button>
</div>
</div>
</form>
</div>
</section>
<!-- deathcounter -->
<script src="/panel/js/pages/extra/deathcounter.js"></script>
</main>

View File

@@ -0,0 +1,62 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<main>
<!-- Header -->
<section class="content-header">
<h1>Dual Stream</h1>
<ol class="breadcrumb">
<li><a href="javascript:void(0);"><i class="fa fa-dashboard"></i> Home</a></li>
<li>Extra</li>
<li class="active">Dual Stream</li>
</ol>
</section>
<!-- Main content -->
<section class="content">
<div class="box box-solid">
<div class="box-header with-border">
<label class="switch" data-toggle="tooltip" title="Module toggle">
<input type="checkbox" id="dualStreamModuleToggle" checked>
<span class="slider round"></span>
</label>
<h3 class="box-title">Dual Stream</h3>
</div>
<form role="form" id="dualStreamModule">
<!-- Box content -->
<div class="box-body">
<button class="btn btn-primary btn-sm pull-right" type="button" id="dualstream-settings-button"><i class="fa fa-cog"></i>&nbsp; Settings</button>
<div class="form-group" style="margin-top: 30px;">
<label>Dual Stream URL</label>
<div class="input-group">
<span class="input-group-addon" id="multi-main">https://multistre.am/</span>
<input type="text" class="form-control" id="multi-channels" placeholder="PhantomBot"
data-toggle="tooltip" title="Channels to be in the multi Twitch URL. Separate each channel with a /" onkeypress="return event.which !== 13;">
<span class="input-group-btn">
<button type="button" class="btn btn-primary btn-flat" id="dualstream-copy-btn"
data-toggle="tooltip" title="Copy the current multi stream link.">Copy</button>
</span>
</div>
</div>
</div>
</form>
</div>
</section>
<!-- dualstream -->
<script src="/panel/js/pages/extra/dualstream.js"></script>
</main>

View File

@@ -0,0 +1,54 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<main>
<!-- Header -->
<section class="content-header">
<h1>Highlights</h1>
<ol class="breadcrumb">
<li><a href="javascript:void(0);"><i class="fa fa-dashboard"></i> Home</a></li>
<li>Extra</li>
<li class="active">Highlights</li>
</ol>
</section>
<!-- Main content -->
<section class="content">
<div class="box box-solid">
<div class="box-header with-border">
<label class="switch" data-toggle="tooltip" title="Module toggle">
<input type="checkbox" id="highlightsModuleToggle" checked>
<span class="slider round"></span>
</label>
<h3 class="box-title">Stream Highlights</h3>
</div>
<form role="form" id="highlightsModule">
<!-- Box content -->
<div class="box-body">
<div class="btn-toolbar pull-right">
<button class="btn btn-primary btn-sm" type="button" id="add-highlight-button"><i class="fa fa-plus"></i>&nbsp; Create Highlight</button>
<button class="btn btn-danger btn-sm" type="button" id="delete-highlights-button"><i class="fa fa-trash"></i>&nbsp; Delete All</button>
</div>
<table id="highlightsTable" class="table table-bordered table-hover"></table>
</div>
</form>
</div>
</section>
<!-- highlights -->
<script src="/panel/js/pages/extra/highlights.js"></script>
</main>

View File

@@ -0,0 +1,81 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<main>
<!-- Chart location and size -->
<style>
canvas {
padding: 0;
margin: auto;
display: block;
width: 450px;
}
</style>
<!-- Header -->
<section class="content-header">
<h1>Polls
<label class="switch" data-toggle="tooltip" title="Module toggle">
<input type="checkbox" id="pollSystemModuleToggle" checked>
<span class="slider round"></span>
</label>
</h1>
<ol class="breadcrumb">
<li><a href="javascript:void(0);"><i class="fa fa-dashboard"></i> Home</a></li>
<li>Extra</li>
<li class="active">Polls</li>
</ol>
</section>
<!-- Main content -->
<section class="content">
<div class="row">
<!-- Poll menu -->
<div class="col-md-8">
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title">Poll</h3>
</div>
<form role="form" id="pollSystemModule">
<!-- Box content -->
<div class="box-body">
<div class="btn-toolbar pull-right">
<button class="btn btn-success" type="button" id="open-poll"><i class="fa fa-unlock-alt"></i>&nbsp; Open</button>
<button class="btn btn-warning" type="button" id="close-poll"><i class="fa fa-lock"></i>&nbsp; Close</button>
<button class="btn btn-danger" type="button" id="reset-poll"><i class="fa fa-trash"></i>&nbsp; Reset</button>
</div>
<canvas width="450" height="450" id="poll-chart" style="margin-top: 50px !important;"></canvas>
</div>
</form>
</div>
</div>
<!-- Twitch chat. -->
<div class="col-md-4">
<div id="twitch-chat-poll"></div>
</div>
</div>
</section>
<!-- polls -->
<script src="/panel/js/pages/extra/polls.js"></script>
<!-- chartjs -->
<script src="/panel/vendors/chart.js/Chart.bundle.min.js"></script>
</main>

View File

@@ -0,0 +1,133 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<main>
<style>
.table>tbody>tr>th {
border: none !important;
}
</style>
<!-- Header -->
<section class="content-header">
<!-- Page title and switch toggle. -->
<h1>Queue
<label class="switch" data-toggle="tooltip" title="Module toggle">
<input type="checkbox" id="queueModuleToggle" checked>
<span class="slider round"></span>
</label>
</h1>
<ol class="breadcrumb">
<li><a href="javascript:void(0);"><i class="fa fa-dashboard"></i> Home</a></li>
<li>Extra</li>
<li class="active">Queue</li>
</ol>
</section>
<!-- Main content -->
<section class="content">
<div class="row">
<!-- Left section -->
<div class="col-md-3" id="queueTable">
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title">Queue List</h3>
</div>
<form role="form" id="queueListModule">
<!-- Box content -->
<div class="box-body no-padding" style="height: 491px; overflow-x: auto; overflow-y: auto;">
<div id="queue-list">
<table class="table table-hover table-custom" id="queue-table" style="width: 100%;">
<tr>
<th style="width: 5%;">#</th>
<th style="width: 42.5%;">Username</th>
<th style="width: 42.5%;">Gamertag</th>
<th style="width: 10%; text-align: right; padding-right: 16px;">Action</th>
</tr>
</table>
</div>
</div>
</form>
</div>
</div>
<!-- Middle section -->
<div class="col-md-6">
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title">Queue Options</h3>
</div>
<form role="form" id="queueModule">
<!-- Box content -->
<div class="box-body" style="padding-bottom: 150px;">
<!-- Queue title -->
<div class="form-group">
<label for="queue-title">Title</label>
<input type="text" class="form-control" id="queue-title" placeholder="Title of the queue"
data-toggle="tooltip" title="Title of the queue."/>
</div>
<!-- Queue cost -->
<div class="form-group">
<label for="queue-cost">Cost</label>
<input type="number" class="form-control" id="queue-cost" value="0" data-toggle="tooltip" title="Cost to join the queue."/>
</div>
<!-- Queue max size -->
<div class="form-group">
<label for="queue-size">Max Size</label>
<input type="number" class="form-control" id="queue-size" value="0" data-toggle="tooltip" title="Max size of the queue. 0 is unlimited."/>
</div>
<!-- Queue permission -->
<div class="form-group">
<label for="queue-permission">User Level</label>
<select class="form-control" id="queue-permission">
<option selected="selected" hidden="hidden">Viewers</option>
<option>Caster</option>
<option>Administrators</option>
<option>Moderators</option>
<option>Subscribers</option>
<option>Donators</option>
<option>Regulars</option>
<option>Viewers</option>
</select>
</div>
</div>
<!-- Footer with buttons -->
<div class="box-footer">
<div class="btn-toolbar pull-right">
<button class="btn btn-success" type="button" id="open-or-close-queue"><i class="fa fa-unlock-alt"></i>&nbsp; Open</button>
<button class="btn btn-primary" type="button" id="draw-queue"><i class="fa fa-trophy"></i>&nbsp; Draw</button>
<button class="btn btn-danger" type="button" id="reset-queue"><i class="fa fa-trash"></i>&nbsp; Reset</button>
</div>
</div>
</form>
</div>
</div>
<!-- Right section -->
<div class="col-md-3" style="height: 532px;">
<div id="queue-chat"></div>
</div>
</div>
</section>
<!-- queue -->
<script src="/panel/js/pages/extra/queue.js"></script>
</main>

View File

@@ -0,0 +1,245 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<main>
<!-- Header -->
<section class="content-header">
<h1>Games</h1>
<ol class="breadcrumb">
<li><a href="javascript:void(0);"><i class="fa fa-dashboard"></i> Home</a></li>
<li class="active">Games</li>
</ol>
</section>
<!-- Main content -->
<section class="content">
<div class="row">
<!-- Adventure game -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Module toggle.">
<input type="checkbox" id="adventureSystemToggle" data-game-toggle="./games/adventureSystem.js" checked>
<span class="slider round"></span>
</label>
<button type="button" id="adventureSystemSettings" class="btn btn-md btn-box-tool" style="margin-bottom: 7px;">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">Adventures</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Let your viewers go on adventures and have the survivors win points.</p>
</div>
</form>
</div>
</div>
<!-- Roulette game -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Module toggle.">
<input type="checkbox" id="rouletteToggle" data-game-toggle="./games/roulette.js" checked>
<span class="slider round"></span>
</label>
<button type="button" id="rouletteSettings" class="btn btn-md btn-box-tool" style="margin-bottom: 7px;">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">Russian Roulette</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Let your viewers play Russian roulette to test their luck.</p>
</div>
</form>
</div>
</div>
<!-- Slot Machine game -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Module toggle.">
<input type="checkbox" id="slotMachineToggle" data-game-toggle="./games/slotMachine.js" checked>
<span class="slider round"></span>
</label>
<button type="button" id="slotMachineSettings" class="btn btn-md btn-box-tool" style="margin-bottom: 7px;">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">Slot Machine</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Let your viewers pull the lever and see if they get matching emotes.</p>
</div>
</form>
</div>
</div>
</div>
<div class="row">
<!-- Dice Roll game -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Module toggle.">
<input type="checkbox" id="rollToggle" data-game-toggle="./games/roll.js" checked>
<span class="slider round"></span>
</label>
<button type="button" id="rollSettings" class="btn btn-md btn-box-tool" style="margin-bottom: 7px;">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">Dice Roll</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Let your viewers role the dices and see if they get lucky.</p>
</div>
</form>
</div>
</div>
<!-- Gambling game -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Module toggle.">
<input type="checkbox" id="gamblingToggle" data-game-toggle="./games/gambling.js" checked>
<span class="slider round"></span>
</label>
<button type="button" id="gamblingSettings" class="btn btn-md btn-box-tool" style="margin-bottom: 7px;">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">Gambling</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Let your viewers gamble all of their points or get lucky and win big.</p>
</div>
</form>
</div>
</div>
<!-- Kill game -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Module toggle.">
<input type="checkbox" id="killCommandToggle" data-game-toggle="./games/killCommand.js" checked>
<span class="slider round"></span>
</label>
<button type="button" id="killCommandSettings" class="btn btn-md btn-box-tool" style="margin-bottom: 7px;">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">Kill Game</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Let your viewers try to "kill" each other in chat without getting caught by the cops.</p>
</div>
</form>
</div>
</div>
</div>
<div class="row">
<!-- 8ball game -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Module toggle.">
<input type="checkbox" id="8ballToggle" data-game-toggle="./games/8ball.js" checked>
<span class="slider round"></span>
</label>
<button type="button" class="btn btn-md btn-box-tool disabled" data-toggle="tooltip" title="This module doesn't have any settings." style="margin-bottom: 7px;">
<i class="fa fa-cog fa-lg disabled"></i>
</button>
</div>
<h3 class="box-title">Magic 8-ball</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Have any questions? Ask the Magic 8-ball anything and it will guide you.</p>
</div>
</form>
</div>
</div>
<!-- Random game -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Module toggle.">
<input type="checkbox" id="randomToggle" data-game-toggle="./games/random.js" checked>
<span class="slider round"></span>
</label>
<button type="button" class="btn btn-md btn-box-tool" id="randomSettings" data-toggle="tooltip" style="margin-bottom: 7px;">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">Random Command</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Let chat get weird real fast with random responses from the bot.</p>
</div>
</form>
</div>
</div>
</div>
</section>
<!-- games -->
<script src="/panel/js/pages/games/games.js"></script>
</main>

View File

@@ -0,0 +1,104 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<main>
<!-- Header -->
<section class="content-header">
<h1>Auctions
<label class="switch" data-toggle="tooltip" title="Module toggle">
<input type="checkbox" id="auctionSystemModuleToggle" checked>
<span class="slider round"></span>
</label>
</h1>
<ol class="breadcrumb">
<li><a href="javascript:void(0);"><i class="fa fa-dashboard"></i> Home</a></li>
<li>Giveaways</li>
<li class="active">Auction</li>
</ol>
</section>
<!-- Main content -->
<section class="content">
<div class="row">
<!-- Poll menu -->
<div class="col-md-8">
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title">Auction</h3>
</div>
<form role="form" id="auctionOptions">
<!-- Box content -->
<div class="box-body">
<!-- Minimum bet -->
<div class="form-group">
<label for="auction-bet">Minimum Bets</label>
<input type="number" min="1" class="form-control" id="auction-bet" value="1"
data-toggle="tooltip" title="Minimum bets people can place."/>
</div>
<!-- Increments -->
<div class="form-group">
<label for="auction-inc">Increments</label>
<input type="number" min="1" class="form-control" id="auction-inc" value="1"
data-toggle="tooltip" title="The increments people would use. 5 would allow bets like; 5, 10, 15, 20, 25."/>
</div>
<!-- Eligibility -->
<div class="form-group">
<label for="auction-perm">Eligibility</label>
<select class="form-control" id="auction-perm">
<option value="subscribers">Subscribers</option>
<option value="regulars">Regulars</option>
<option selected="selected" value="viewers">Everyone</option>
</select>
</div>
<!-- Timer -->
<div class="form-group">
<label for="auction-timer">Timer (Seconds)</label>
<input type="number" min="0" class="form-control" id="auction-timer" value="0"
data-toggle="tooltip" title="How long the auction should be opened for. 0 is until manually closed."/>
</div>
<!-- Show results -->
<div class="form-group" style="padding-top: 50px; text-align: center;">
<p style="font-size: 25px;"><b>Top Bidder:</b> <span style="font-size: 20px;" id="auction-top-bidder">PhantomBot</span>
<b><span style="margin-left: 10%;">Points:</span></b> <span style="font-size: 20px;" id="auction-points">0</span></p>
</div>
</div>
<!-- Footer with buttons -->
<div class="box-footer">
<div class="btn-toolbar pull-right">
<button class="btn btn-success" type="button" id="open-or-close-auction"><i class="fa fa-unlock-alt"></i>&nbsp; Open</button>
<button class="btn btn-danger" type="button" id="reset-auction"><i class="fa fa-trash"></i>&nbsp; Reset</button>
</div>
</div>
</form>
</div>
</div>
<!-- Twitch chat. -->
<div class="col-md-4">
<div id="twitch-chat-auction"></div>
</div>
</div>
</section>
<!-- auctions -->
<script src="/panel/js/pages/giveaways/auction.js"></script>
</main>

View File

@@ -0,0 +1,159 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<main>
<style>
.table>tbody>tr>th {
border: none !important;
}
</style>
<!-- Header -->
<section class="content-header">
<!-- Page title and switch toggle. -->
<h1>Raffle
<label class="switch" data-toggle="tooltip" title="Module toggle">
<input type="checkbox" id="raffleModuleToggle" checked>
<span class="slider round"></span>
</label>
</h1>
<ol class="breadcrumb">
<li><a href="javascript:void(0);"><i class="fa fa-dashboard"></i> Home</a></li>
<li>Giveaways</li>
<li class="active">Raffle</li>
</ol>
</section>
<!-- Main content -->
<section class="content">
<div class="row">
<!-- Left section -->
<div class="col-md-3" id="raffleTable">
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title">Raffle List</h3>
</div>
<form role="form" id="raffleListModule">
<!-- Box content -->
<div class="box-body no-padding" style="height: 569px; overflow-x: auto; overflow-y: auto;">
<div id="raffle-list">
<table class="table table-hover table-custom" id="raffle-table" style="width: 100%;">
<tr>
<th style="width: 100%;">Username</th>
</tr>
</table>
</div>
</div>
</form>
</div>
</div>
<!-- Left section -->
<div class="col-md-6">
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title">Raffle Options</h3>
<span class="pull-right">
<a href="javascript:void(0)" class="text-muted" data-toggle="tooltip" title="Raffle settings" id="raffle-settings">
<i class="fa fa-gears"></i>
</a>
</span>
</div>
<form role="form" id="raffleModal">
<!-- Box content -->
<div class="box-body" style="padding-bottom: 90px;">
<!-- Keyword -->
<div class="form-group">
<label for="raffle-keyword">Keyword</label>
<input type="text" class="form-control" id="raffle-keyword" placeholder="!enter"
data-toggle="tooltip" title="Keyword used to enter the raffle. This is not case sensitive."/>
</div>
<!-- Cost -->
<div class="row">
<div class="col-md-8">
<div class="form-group">
<label for="raffle-cost" id="raffle-cost-title">Cost</label>
<input type="text" class="form-control" id="raffle-cost" value="0"
data-toggle="tooltip" title="Cost required to enter the raffle. When using time, it will not be deducted from the user."/>
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label for="raffle-req">Requirement</label>
<select class="form-control" id="raffle-req" data-toggle="tooltip" title="If the raffle system should use points or time.">
<option selected="selected" value="-usepoints">Points</option>
<option value="-usetime">Time</option>
</select>
</div>
</div>
</div>
<!-- Eligibility -->
<div class="form-group">
<label for="raffle-perm">Eligibility</label>
<select class="form-control" id="raffle-perm">
<option value="-subscribers">Subscribers</option>
<option value="-followers">Followers</option>
<option selected="selected" value="">Everyone</option>
</select>
</div>
<!-- Timer -->
<div class="form-group">
<label for="raffle-timer">Timer (Minutes)</label>
<input type="number" min="0" class="form-control" id="raffle-timer" value="0"
data-toggle="tooltip" title="How long the raffle should be opened for. 0 is until manually closed."/>
</div>
<!-- Regular luck -->
<div class="form-group">
<label for="raffle-reg">Regular Luck</label>
<input type="number" min="1" max="10" class="form-control" id="raffle-reg" value="1"
data-toggle="tooltip" title="How many more times a regular is likely to win."/>
</div>
<!-- Subscriber luck -->
<div class="form-group">
<label for="raffle-sub">Subscriber Luck</label>
<input type="number" min="1" max="10" class="form-control" id="raffle-sub" value="1"
data-toggle="tooltip" title="How many more times a subscriber is likely to win."/>
</div>
</div>
<!-- Footer with buttons -->
<div class="box-footer">
<div class="btn-toolbar pull-right">
<button class="btn btn-success" type="button" id="open-or-close-raffle"><i class="fa fa-unlock-alt"></i>&nbsp; Open</button>
<button class="btn btn-primary" type="button" id="draw-raffle"><i class="fa fa-trophy"></i>&nbsp; Draw</button>
<button class="btn btn-danger" type="button" id="reset-raffle"><i class="fa fa-trash"></i>&nbsp; Reset</button>
</div>
</div>
</form>
</div>
</div>
<!-- Right section -->
<div class="col-md-3" style="height: 610px;">
<div id="raffle-chat"></div>
</div>
</div>
</section>
<!-- raffle -->
<script src="/panel/js/pages/giveaways/raffle.js"></script>
</main>

View File

@@ -0,0 +1,146 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<main>
<style>
.table>tbody>tr>th {
border: none !important;
}
</style>
<!-- Header -->
<section class="content-header">
<!-- Page title and switch toggle. -->
<h1>Ticket Raffle
<label class="switch" data-toggle="tooltip" title="Module toggle">
<input type="checkbox" id="ticketRaffleModuleToggle" checked>
<span class="slider round"></span>
</label>
</h1>
<ol class="breadcrumb">
<li><a href="javascript:void(0);"><i class="fa fa-dashboard"></i> Home</a></li>
<li>Giveaways</li>
<li class="active">Ticket Raffle</li>
</ol>
</section>
<!-- Main content -->
<section class="content">
<div class="row">
<!-- Left section -->
<div class="col-md-3" id="ticketRaffleTable">
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title">Ticket Raffle List</h3>
</div>
<form role="form" id="ticketRaffleListModule">
<!-- Box content -->
<div class="box-body no-padding" style="height: 569px; overflow-x: auto; overflow-y: auto;">
<div id="raffle-list">
<table class="table table-hover table-custom" id="ticket-raffle-table" style="width: 100%;">
<tr>
<th style="width: 80%;">Username</th>
<th style="width: 20%;">Tickets</th>
</tr>
</table>
</div>
</div>
</form>
</div>
</div>
<!-- Left section -->
<div class="col-md-6">
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title">Ticket Raffle Options</h3>
<span class="pull-right">
<a href="javascript:void(0)" class="text-muted" data-toggle="tooltip" title="Ticket Raffle settings" id="ticket-raffle-settings">
<i class="fa fa-gears"></i>
</a>
</span>
</div>
<form role="form" id="ticketRaffleModal">
<!-- Box content -->
<div class="box-body" style="padding-bottom: 90px;">
<!-- Command -->
<div class="form-group">
<label for="ticket-raffle-cmd">Command</label>
<input id="ticket-raffle-cmd" type="text" class="form-control" value="!tickets"
data-toggle="tooltip" title="Command used to buy tickets. This cannot be changed." disabled/>
</div>
<!-- Eligibility -->
<div class="form-group">
<label for="ticket-raffle-perm">Eligibility</label>
<select class="form-control" id="ticket-raffle-perm">
<option value="-followers">Followers</option>
<option selected="selected" value="">Everyone</option>
</select>
</div>
<!-- Ticket cost -->
<div class="form-group">
<label for="ticket-raffle-cost">Ticket Cost</label>
<input type="text" class="form-control" id="ticket-raffle-cost" value="1"
data-toggle="tooltip" title="How much each ticket cost."/>
</div>
<!-- Maximum tickets -->
<div class="form-group">
<label for="ticket-raffle-max">Maximum Allowed Tickets</label>
<input type="text" class="form-control" id="ticket-raffle-max" value="100"
data-toggle="tooltip" title="How many tickets users are allowed to buy."/>
</div>
<!-- Regular luck -->
<div class="form-group">
<label for="ticket-raffle-reg">Regulars Ticket Multiplier</label>
<input type="number" min="1" max="10" class="form-control" id="ticket-raffle-reg" value="1"
data-toggle="tooltip" title="Ticket multiplier for regulars. Multiplies the number of tickets the users buys with this number."/>
</div>
<!-- Subscriber luck -->
<div class="form-group">
<label for="ticket-raffle-sub">Subscribers Ticket Multiplier</label>
<input type="number" min="1" max="10" class="form-control" id="ticket-raffle-sub" value="1"
data-toggle="tooltip" title="Ticket multiplier for susbcribers. Multiplies the number of tickets the users buys with this number."/>
</div>
</div>
<!-- Footer with buttons -->
<div class="box-footer">
<div class="btn-toolbar pull-right">
<button class="btn btn-success" type="button" id="ticket-open-or-close-raffle"><i class="fa fa-unlock-alt"></i>&nbsp; Open</button>
<button class="btn btn-primary" type="button" id="ticket-draw-raffle"><i class="fa fa-trophy"></i>&nbsp; Draw</button>
<button class="btn btn-danger" type="button" id="ticket-reset-raffle"><i class="fa fa-trash"></i>&nbsp; Reset</button>
</div>
</div>
</form>
</div>
</div>
<!-- Right section -->
<div class="col-md-3" style="height: 610px;">
<div id="ticket-raffle-chat"></div>
</div>
</div>
</section>
<!-- raffle -->
<script src="/panel/js/pages/giveaways/ticketRaffle.js"></script>
</main>

View File

@@ -0,0 +1,73 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<main>
<!-- Header -->
<section class="content-header">
<h1>Help</h1>
<ol class="breadcrumb">
<li><a href="javascript:void(0);"><i class="fa fa-dashboard"></i> Home</a></li>
<li class="active">Help</li>
</ol>
</section>
<!-- Main content -->
<section class="content">
<div class="row">
<div class="col-md-6">
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title">PhantomBot Information</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p><b>PhantomBot Version: </b><span id="panel-bot-version">Error</span></p>
<p><b>Operating System: </b><span id="panel-os-version">Error</span></p>
<p><b>Java Version: </b><span id="panel-java-version">Error</span></p>
<p><b>PhantomBot License: </b><a href="https://github.com/PhantomBot/PhantomBot/blob/master/LICENSE" target="_blank">GNU General Public License v3.0</a></p>
</div>
</form>
</div>
</div>
<div class="col-md-6">
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title">Control Panel Information</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<!-- This is the version we give the panel -->
<p><b>Panel Version:</b> <span id="panel-version-number">Error</span></p>
<!-- This is the template name, this is static -->
<p><b>Panel Template: </b><a href="https://adminlte.io" target="_blank">AdminLTE</a></p>
<!-- We never update the template, so this is a static version -->
<p><b>Template Version: </b>2.4.0</p>
<!-- AdminLTE's license. -->
<p><b>AdminLTE License: </b><a href="https://github.com/almasaeed2010/AdminLTE/blob/master/LICENSE" target="_blank">MIT License</a></p>
</div>
</form>
</div>
</div>
</div>
</section>
<!-- help.js -->
<script src="/panel/js/pages/help/help.js"></script>
</main>

View File

@@ -0,0 +1,57 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<main>
<!-- Overwrite styles -->
<style>
.dataTables_filter {
float: right;
text-align: right;
}
</style>
<!-- Header -->
<section class="content-header">
<h1>History</h1>
<ol class="breadcrumb">
<li><a href="javascript:void(0);"><i class="fa fa-dashboard"></i> Home</a></li>
<li>History</li>
<li class="active">Hosts</li>
</ol>
</section>
<!-- Main content -->
<section class="content">
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title">Host History</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<div class="load-ajax">
<div class="spinner"></div>
<p class="load-ajax-text">Loading...</p>
</div>
<table id="hostHistoryTable" class="table table-bordered table-hover"></table>
</div>
</form>
</div>
</section>
<!-- hostHistory -->
<script src="/panel/js/pages/history/hostHistory.js"></script>
</main>

View File

@@ -0,0 +1,71 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<main>
<!-- Overwrite styles -->
<style>
.dataTables_filter {
float: right;
text-align: right;
}
</style>
<!-- Header -->
<section class="content-header">
<h1>History</h1>
<ol class="breadcrumb">
<li><a href="javascript:void(0);"><i class="fa fa-dashboard"></i> Home</a></li>
<li>History</li>
<li class="active">Raids</li>
</ol>
</section>
<!-- Main content -->
<section class="content">
<div class="nav-tabs-custom">
<ul class="nav nav-tabs">
<li class="active"><a href="#incommingRaids" id="incommingRaids_t" data-toggle="tab">Incoming Raids</a></li>
<li><a href="#outgoingRaids" id="outgoingRaids_t" data-toggle="tab">Outgoing Raids</a></li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="incommingRaids">
<form role="form">
<div class="load-ajax">
<div class="spinner"></div>
<p class="load-ajax-text">Loading...</p>
</div>
<table id="raidHistoryTable" class="table table-bordered table-hover"></table>
</form>
</div>
<div class="tab-pane" id="outgoingRaids">
<form role="form">
<div class="load-ajax">
<div class="spinner"></div>
<p class="load-ajax-text">Loading...</p>
</div>
<table id="outRaidHistoryTable" class="table table-bordered table-hover"></table>
</form>
</div>
</div>
</div>
</section>
<!-- raidHistory -->
<script src="/panel/js/pages/history/raidHistory.js"></script>
</main>

View File

@@ -0,0 +1,57 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<main>
<!-- Overwrite styles -->
<style>
.dataTables_filter {
float: right;
text-align: right;
}
</style>
<!-- Header -->
<section class="content-header">
<h1>History</h1>
<ol class="breadcrumb">
<li><a href="javascript:void(0);"><i class="fa fa-dashboard"></i> Home</a></li>
<li>History</li>
<li class="active">Tips</li>
</ol>
</section>
<!-- Main content -->
<section class="content">
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title">Tips History</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<div class="load-ajax">
<div class="spinner"></div>
<p class="load-ajax-text">Loading...</p>
</div>
<table id="tipsHistoryTable" class="table table-bordered table-hover"></table>
</div>
</form>
</div>
</section>
<!-- tipsHistory -->
<script src="/panel/js/pages/history/tipsHistory.js"></script>
</main>

View File

@@ -0,0 +1,55 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<main>
<!-- Header -->
<section class="content-header">
<h1>Keywords</h1>
<ol class="breadcrumb">
<li><a href="javascript:void(0);"><i class="fa fa-dashboard"></i> Home</a></li>
<li class="active">Keywords</li>
</ol>
</section>
<!-- Main content -->
<section class="content">
<div class="box box-solid">
<div class="box-header with-border">
<label class="switch" data-toggle="tooltip" title="Module toggle">
<input type="checkbox" id="keywordModuleToggle" checked>
<span class="slider round"></span>
</label>
<h3 class="box-title">Keywords</h3>
</div>
<form role="form" id="keywordModule">
<!-- Box content -->
<div class="box-body">
<button class="btn btn-primary btn-sm pull-right" type="button" id="keywordadd-button"><i class="fa fa-plus"></i>&nbsp; Add Keyword</button>
<div class="load-ajax">
<div class="spinner"></div>
<p class="load-ajax-text">Loading...</p>
</div>
<table id="keywordsTable" class="table table-bordered table-hover"></table>
</div>
</form>
</div>
</section>
<!-- keywords -->
<script src="/panel/js/pages/keywords/keywords.js"></script>
</main>

View File

@@ -0,0 +1,409 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<main>
<!-- Header -->
<section class="content-header">
<h1>Currency
<label class="switch" data-toggle="tooltip" title="Module toggle">
<input type="checkbox" id="pointsModuleToggle" checked>
<span class="slider round"></span>
</label>
</h1>
<ol class="breadcrumb">
<li><a href="javascript:void(0);"><i class="fa fa-dashboard"></i> Home</a></li>
<li>Loyalty</li>
<li class="active">Currency</li>
</ol>
</section>
<!-- Main content -->
<section class="content" id="pointsModule">
<div class="row">
<!-- Left section -->
<section class="col-lg-6">
<div class="row">
<!-- Currency settings -->
<div class="col-md-12">
<div class="nav-tabs-custom">
<ul class="nav nav-tabs">
<li class="active" id="main-settings"><a href="#loyalty_settings" data-toggle="tab" aria-expanded="true">Settings</a></li>
<li><a href="#loyalty_settings_adv" data-toggle="tab" aria-expanded="false">Advanced Settings</a></li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="loyalty_settings">
<div class="row">
<!-- Points message -->
<div class="col-md-12">
<div class="form-group">
<label for="points-message">Currency Message</label>
<input type="text" class="form-control" id="points-message" data-toggle="tooltip"
title="Message said in chat when someone uses the !points command. Tags: (userprefix), (user), (points),
(pointsname), (pointsstring), (time), and (rank)"/>
</div>
</div>
</div>
<div class="row">
<!-- Points name single -->
<div class="col-md-6">
<div class="form-group">
<label for="points-name-single">Currency Name (Single)</label>
<input type="text" class="form-control" id="points-name-single" placeholder="Point" data-toggle="tooltip"
title="Name of your currency for single."/>
</div>
</div>
<!-- Points name multiple -->
<div class="col-md-6">
<div class="form-group">
<label for="points-name-multiple">Currency Name (Multiple)</label>
<input type="text" class="form-control" id="points-name-multiple" placeholder="Points" data-toggle="tooltip"
title="Name of your currency for multiple."/>
</div>
</div>
</div>
<div class="row">
<!-- online interval -->
<div class="col-md-6">
<div class="form-group">
<label for="points-interval-online">Payout Interval (Online)</label>
<input type="number" class="form-control" id="points-interval-online" placeholder="15" data-toggle="tooltip"
title="Online payout interval in minutes."/>
</div>
</div>
<!-- offline interval -->
<div class="col-md-6">
<div class="form-group">
<label for="points-interval-offline">Payout Interval (Offline)</label>
<input type="number" class="form-control" id="points-interval-offline" placeholder="10" data-toggle="tooltip"
title="Offline payout interval in minutes."/>
</div>
</div>
</div>
<div class="row">
<!-- online payout -->
<div class="col-md-6">
<div class="form-group">
<label for="points-payout-online">Payout Amount (Online)</label>
<input type="number" class="form-control" id="points-payout-online" placeholder="10" data-toggle="tooltip" title="Online payout amount."/>
</div>
</div>
<!-- offline payout -->
<div class="col-md-6">
<div class="form-group">
<label for="points-payout-offline">Payout Amount (Offline)</label>
<input type="number" class="form-control" id="points-payout-offline" placeholder="15" data-toggle="tooltip" title="Offline payout amount."/>
</div>
</div>
</div>
<div class="row">
<!-- Active bonus -->
<div class="col-md-6">
<div class="form-group">
<label for="points-active">Active Bonus</label>
<input type="number" class="form-control" id="points-active" placeholder="1" data-toggle="tooltip"
title="Amount of extra points active users get at each payout."/>
</div>
</div>
<!-- Top list amount -->
<div class="col-md-6">
<div class="form-group">
<label for="points-top">Top List Amount</label>
<input type="number" class="form-control" id="points-top" max="15" placeholder="5" data-toggle="tooltip"
title="Amount of users who show up in the top list. Max is 15."/>
</div>
</div>
</div>
</div>
<div class="tab-pane" id="loyalty_settings_adv">
<div class="row">
<!-- Caster payout online -->
<div class="col-md-6">
<div class="form-group">
<label for="points-payout-caster-on">Caster Payout (Online)</label>
<input type="number" class="form-control" id="points-payout-caster-on" placeholder="1" data-toggle="tooltip"
title="Payout of for the caster group while online. -1 is default payout."/>
</div>
</div>
<!-- Caster payout offline -->
<div class="col-md-6">
<div class="form-group">
<label for="points-payout-caster-off">Caster Payout (Offline)</label>
<input type="number" class="form-control" id="points-payout-caster-off" placeholder="5" data-toggle="tooltip"
title="Payout of for the caster group while offline. -1 is default payout."/>
</div>
</div>
</div>
<div class="row">
<!-- Caster payout online -->
<div class="col-md-6">
<div class="form-group">
<label for="points-payout-administrator-on">Administrator Payout (Online)</label>
<input type="number" class="form-control" id="points-payout-administrator-on" placeholder="1" data-toggle="tooltip"
title="Payout of for the administrator group while online. -1 is default payout."/>
</div>
</div>
<!-- Caster payout offline -->
<div class="col-md-6">
<div class="form-group">
<label for="points-payout-administrator-off">Administrator Payout (Offline)</label>
<input type="number" class="form-control" id="points-payout-administrator-off" placeholder="5" data-toggle="tooltip"
title="Payout of for the administrator group while offline. -1 is default payout."/>
</div>
</div>
</div>
<div class="row">
<!-- Caster payout online -->
<div class="col-md-6">
<div class="form-group">
<label for="points-payout-moderator-on">Moderator Payout (Online)</label>
<input type="number" class="form-control" id="points-payout-moderator-on" placeholder="1" data-toggle="tooltip"
title="Payout of for the moderator group while online. -1 is default payout."/>
</div>
</div>
<!-- Caster payout offline -->
<div class="col-md-6">
<div class="form-group">
<label for="points-payout-moderator-off">Moderator Payout (Offline)</label>
<input type="number" class="form-control" id="points-payout-moderator-off" placeholder="5" data-toggle="tooltip"
title="Payout of for the moderator group while offline. -1 is default payout."/>
</div>
</div>
</div>
<div class="row">
<!-- Caster payout online -->
<div class="col-md-6">
<div class="form-group">
<label for="points-payout-subscriber-on">Subscriber Payout (Online)</label>
<input type="number" class="form-control" id="points-payout-subscriber-on" placeholder="1" data-toggle="tooltip"
title="Payout of for the subscriber group while online. -1 is default payout."/>
</div>
</div>
<!-- Caster payout offline -->
<div class="col-md-6">
<div class="form-group">
<label for="points-payout-subscriber-off">Subscriber Payout (Offline)</label>
<input type="number" class="form-control" id="points-payout-subscriber-off" placeholder="5" data-toggle="tooltip"
title="Payout of for the subscriber group while offline. -1 is default payout."/>
</div>
</div>
</div>
<div class="row">
<!-- Caster payout online -->
<div class="col-md-6">
<div class="form-group">
<label for="points-payout-donator-on">Donator Payout (Online)</label>
<input type="number" class="form-control" id="points-payout-donator-on" placeholder="1" data-toggle="tooltip"
title="Payout of for the donator group while online. -1 is default payout."/>
</div>
</div>
<!-- Caster payout offline -->
<div class="col-md-6">
<div class="form-group">
<label for="points-payout-donator-off">Donator Payout (Offline)</label>
<input type="number" class="form-control" id="points-payout-donator-off" placeholder="5" data-toggle="tooltip"
title="Payout of for the donator group while offline. -1 is default payout."/>
</div>
</div>
</div>
<div class="row">
<!-- Caster payout online -->
<div class="col-md-6">
<div class="form-group">
<label for="points-payout-regular-on">Regular Payout (Online)</label>
<input type="number" class="form-control" id="points-payout-regular-on" placeholder="1" data-toggle="tooltip"
title="Payout of for the regular group while online. -1 is default payout."/>
</div>
</div>
<!-- Caster payout offline -->
<div class="col-md-6">
<div class="form-group">
<label for="points-payout-regular-off">Regular Payout (Offline)</label>
<input type="number" class="form-control" id="points-payout-regular-off" placeholder="5" data-toggle="tooltip"
title="Payout of for the regular group while offline. -1 is default payout."/>
</div>
</div>
</div>
<div class="row">
<!-- Caster payout online -->
<div class="col-md-6">
<div class="form-group">
<label for="points-payout-viewer-on">Viewer Payout (Online)</label>
<input type="number" class="form-control" id="points-payout-viewer-on" placeholder="1" data-toggle="tooltip"
title="Payout of for the viewer group while online. -1 is default payout."/>
</div>
</div>
<!-- Caster payout offline -->
<div class="col-md-6">
<div class="form-group">
<label for="points-payout-viewer-off">Viewer Payout (Offline)</label>
<input type="number" class="form-control" id="points-payout-viewer-off" placeholder="5" data-toggle="tooltip"
title="Payout of for the viewer group while offline. -1 is default payout."/>
</div>
</div>
</div>
</div>
<!-- Box footer -->
<div class="box-footer" style="padding-right: 0; padding-bottom: 0;">
<button type="button" class="btn btn-primary pull-right" id="points-save-all"> Save</button>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title">Currency Penalty</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<!-- Username -->
<div class="form-group">
<label for="points-panalty-user">Username</label>
<input type="text" class="form-control" id="points-panalty-user" placeholder="PhantomBot" data-toggle="tooltip"
title="Username that won't gain points for the time given.">
</div>
<!-- Bonus Time -->
<div class="form-group">
<label for="points-panalty-time">Penalty Time (Minutes)</label>
<input type="number" class="form-control" id="points-panalty-time" placeholder="1" data-toggle="tooltip"
title="Minutes that the given user won't gain points for.">
</div>
</div>
<!-- Box footer -->
<div class="box-footer">
<button type="button" class="btn btn-primary pull-right" id="points-panalty-btn"> Submit</button>
</div>
</form>
</div>
</div>
</div>
</section>
<!-- Right section -->
<section class="col-lg-6">
<div class="row">
<div class="col-md-12">
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title">Currency Manager</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<!-- Username -->
<div class="form-group">
<label for="points-username">Username</label>
<input type="text" class="form-control" id="points-username" placeholder="PhantomBot" data-toggle="tooltip" title="Username to edit the points for.">
</div>
<!-- Number of points -->
<div class="form-group">
<label for="points-username-points">Currency</label>
<div class="input-group input-group-md">
<input type="number" class="form-control" id="points-username-points" placeholder="0" data-toggle="tooltip" title="Amount of points the user will have.">
<span class="input-group-btn">
<button type="button" class="btn btn-success btn-flat" id="points-get-user" data-toggle="tooltip"
title="Get the user's points if they have any.">Get</button>
</span>
</div>
</div>
</div>
<!-- Box footer -->
<div class="box-footer">
<button type="button" class="btn btn-primary pull-right" id="points-save-user" data-toggle="tooltip" title="Save the user's points."> Save</button>
</div>
</form>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title">Currency Bonus</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<!-- Amount -->
<div class="form-group">
<label for="points-bonus-amount">Amount</label>
<input type="number" class="form-control" id="points-bonus-amount" placeholder="10">
</div>
<!-- Bonus Time -->
<div class="form-group">
<label for="points-bonus-time">Bonus Time (Minutes)</label>
<input type="number" class="form-control" id="points-bonus-time" placeholder="1" data-toggle="tooltip" title="Time that the bonus will last.">
</div>
</div>
<!-- Box footer -->
<div class="box-footer">
<div class="btn-toolbar pull-right">
<button type="button" class="btn btn-default" id="points-bonus-btn" data-toggle="tooltip"
title="Bonus amount of points to give at each payout. The bonus time box must have a value."> Bonus</button>
<button type="button" class="btn btn-default" id="points-makeitrain-btn" data-toggle="tooltip"
title="Make it rain a certain amount of points and gets devided with everyone in the channel."> Make it Rain</button>
<button type="button" class="btn btn-default" id="points-giveall-btn" data-toggle="tooltip"
title="Give points to everyone in the channel."> Give to All</button>
<button type="button" class="btn btn-default" id="points-takeall-btn" data-toggle="tooltip"
title="Take points from everyone in the channel."> Take from All</button>
</div>
</div>
</form>
</div>
</div>
</div>
</section>
</div>
</section>
<!-- currency -->
<script src="/panel/js/pages/loyalty/currency.js"></script>
</main>

View File

@@ -0,0 +1,70 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<main>
<!-- Header -->
<section class="content-header">
<h1>Leaderboard</h1>
<ol class="breadcrumb">
<li><a href="javascript:void(0);"><i class="fa fa-dashboard"></i> Home</a></li>
<li>Loyalty</li>
<li class="active">Leaderboard</li>
</ol>
</section>
<!-- Main content -->
<section class="content">
<div class="row">
<!-- Points leader board -->
<div class="col-md-6">
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title" id="currency-top-title">Top Currency</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<button class="btn btn-primary btn-sm pull-right" type="button" id="currency-load-more"><i class="fa fa-undo"></i>&nbsp; Load More</button>
<table id="leaderboard-points" class="table table-bordered table-hover"></table>
</div>
</form>
</div>
</div>
<!-- Time leader board -->
<div class="col-md-6">
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title" id="loyalty-top-title">Top Loyalty</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<button class="btn btn-primary btn-sm pull-right" type="button" id="loyalty-load-more"><i class="fa fa-undo"></i>&nbsp; Load More</button>
<table id="leaderboard-time" class="table table-bordered table-hover"></table>
</div>
</form>
</div>
</div>
</div>
</section>
<!-- highlights -->
<script src="/panel/js/pages/loyalty/leaderboard.js"></script>
</main>

View File

@@ -0,0 +1,163 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<main>
<!-- Header -->
<section class="content-header">
<h1>Loyalty</h1>
<ol class="breadcrumb">
<li><a href="javascript:void(0);"><i class="fa fa-dashboard"></i> Home</a></li>
<li>Loyalty</li>
<li class="active">Loyalty</li>
</ol>
</section>
<!-- Main content -->
<section class="content">
<div class="row">
<!-- Left section -->
<section class="col-lg-6">
<div class="row">
<!-- Loyalty Settings -->
<div class="col-md-12">
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title">Loyalty Settings</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<div class="form-group">
<label>Configure Time Zone (<a href="https://en.wikipedia.org/wiki/List_of_tz_database_time_zones" target="_blank">list</a>)</label>
<input type="text" class="form-control" id="loyalty-timezone" data-toggle="tooltip"
title="Timezone the bot should use when calculating time."/>
</div>
<!-- Add offline time to user -->
<div class="form-group">
<label for="time-offline">Accumulate User Time Offline</label>
<div class="dropdown">
<select class="form-control" id="time-offline" style="cursor: pointer;">
<option>Yes</option>
<option>No</option>
</select>
</div>
</div>
<div class="row">
<!-- Auto add users to regulars -->
<div class="col-md-6">
<div class="form-group">
<label for="time-promote">Auto Promote Users to Regulars</label>
<div class="dropdown">
<select class="form-control" id="time-promote" style="cursor: pointer;">
<option>Yes</option>
<option>No</option>
</select>
</div>
</div>
</div>
<!-- Say something in chat when auto promoted. -->
<div class="col-md-6">
<div class="form-group">
<label for="time-promote-notice">Announce in Chat When Auto Promotion</label>
<div class="dropdown">
<select class="form-control" id="time-promote-notice" style="cursor: pointer;">
<option>Yes</option>
<option>No</option>
</select>
</div>
</div>
</div>
</div>
<div class="row">
<!-- Regular promotion hours -->
<div class="col-md-6">
<div class="form-group">
<label>Regular Promotion (Hours)</label>
<input type="number" class="form-control" id="loyalty-promotion" placeholder="15" data-toggle="tooltip"
title="How many hours it takes before a user gets promoted to a regular."/>
</div>
</div>
<!-- Top list.-->
<div class="col-md-6">
<div class="form-group">
<label>Top Time List Amount</label>
<input type="number" class="form-control" id="loyalty-top" max="15" data-toggle="tooltip"
title="How many users will show up in the !toptime command. Max is 15 users."/>
</div>
</div>
</div>
</div>
<!-- Box footer -->
<div class="box-footer">
<button type="button" class="btn btn-primary pull-right" id="loyalty-save-all"> Save</button>
</div>
</form>
</div>
</div>
</div>
</section>
<!-- Right section -->
<section class="col-lg-6">
<div class="row">
<div class="col-md-12">
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title">Loyalty Manager</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<!-- Username -->
<div class="form-group">
<label>Username</label>
<input type="text" class="form-control" id="time-username" placeholder="PhantomBot" data-toggle="tooltip" title="Username to edit the time for.">
</div>
<!-- Number of points -->
<div class="form-group">
<label>Time (Seconds)</label>
<div class="input-group input-group-md">
<input type="number" class="form-control" id="time-username-time" placeholder="0" data-toggle="tooltip" title="Amount of time the user will have.">
<span class="input-group-btn">
<button type="button" class="btn btn-success btn-flat" id="time-get-user" data-toggle="tooltip"
title="Get the user's time if they have any.">Get</button>
</span>
</div>
</div>
</div>
<!-- Box footer -->
<div class="box-footer">
<button type="button" class="btn btn-primary pull-right" id="time-save-user" data-toggle="tooltip" title="Save the user's time."> Save</button>
</div>
</form>
</div>
</div>
</div>
</section>
</div>
</section>
<!-- loyalty -->
<script src="/panel/js/pages/loyalty/loyalty.js"></script>
</main>

View File

@@ -0,0 +1,51 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<main>
<!-- Header -->
<section class="content-header">
<h1>Blacklist</h1>
<ol class="breadcrumb">
<li><a href="javascript:void(0);"><i class="fa fa-dashboard"></i> Home</a></li>
<li>Moderation</li>
<li class="active">Blacklist</li>
</ol>
</section>
<!-- Main content -->
<section class="content">
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title">Blacklist</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<button class="btn btn-primary btn-sm pull-right" type="button" id="add-blacklist-button"><i class="fa fa-plus"></i>&nbsp; Add Blacklist</button>
<div class="load-ajax">
<div class="spinner"></div>
<p class="load-ajax-text">Loading...</p>
</div>
<table id="blacklistTable" class="table table-bordered table-hover"></table>
</div>
</form>
</div>
</section>
<!-- blacklist -->
<script src="/panel/js/pages/moderation/blacklist.js"></script>
</main>

View File

@@ -0,0 +1,272 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<main>
<!-- Header -->
<section class="content-header">
<h1>Moderation</h1>
<ol class="breadcrumb">
<li><a href="javascript:void(0);"><i class="fa fa-dashboard"></i> Home</a></li>
<li>Moderation</li>
<li class="active">Filters</li>
</ol>
</section>
<!-- Main content -->
<section class="content">
<div class="row">
<!-- Links filder -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Filter toggle.">
<input type="checkbox" id="filter-links" data-filter="linksToggle">
<span class="slider round"></span>
</label>
<button type="button" id="filter-links-btn" class="btn btn-md btn-box-tool" style="margin-bottom: 7px;" data-toggle="tooltip" title="Filter settings.">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">Links Filter</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Removes messages that contains links that aren't whitelisted.</p>
</div>
</form>
</div>
</div>
<!-- Caps filter -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Filter toggle.">
<input type="checkbox" id="filter-caps" data-filter="capsToggle">
<span class="slider round"></span>
</label>
<button type="button" id="filter-caps-btn" class="btn btn-md btn-box-tool" style="margin-bottom: 7px;" data-toggle="tooltip" title="Filter settings.">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">Caps Filter</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Removes messages that are mostly all capital letters.</p>
</div>
</form>
</div>
</div>
<!-- Symbols filter -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Filter toggle.">
<input type="checkbox" id="filter-symbols" data-filter="symbolsToggle">
<span class="slider round"></span>
</label>
<button type="button" id="filter-symbols-btn" class="btn btn-md btn-box-tool" style="margin-bottom: 7px;" data-toggle="tooltip" title="Filter settings.">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">Symbols Filter</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Removes messages that have too many symbols.</p>
</div>
</form>
</div>
</div>
</div>
<div class="row">
<!-- Spam filter -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Filter toggle.">
<input type="checkbox" id="filter-spam" data-filter="spamToggle">
<span class="slider round"></span>
</label>
<button type="button" id="filter-spam-btn" class="btn btn-md btn-box-tool" style="margin-bottom: 7px;" data-toggle="tooltip" title="Filter settings.">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">Spam Filter</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Removes messages that have a lot of repeating charaters.</p>
</div>
</form>
</div>
</div>
<!-- Emotes filter -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Filter toggle.">
<input type="checkbox" id="filter-emotes" data-filter="emotesToggle">
<span class="slider round"></span>
</label>
<button type="button" id="filter-emotes-btn" class="btn btn-md btn-box-tool" style="margin-bottom: 7px;" data-toggle="tooltip" title="Filter settings.">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">Emotes Filter</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Removes messages that are mostly all emotes.</p>
</div>
</form>
</div>
</div>
<!-- Me filter -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Filter toggle.">
<input type="checkbox" id="filter-me" data-filter="colorsToggle">
<span class="slider round"></span>
</label>
<button type="button" id="filter-me-btn" class="btn btn-md btn-box-tool" style="margin-bottom: 7px;" data-toggle="tooltip" title="Filter settings.">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">Me Filter</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Removes messages that are colored with the <code>/me</code> command.</p>
</div>
</form>
</div>
</div>
</div>
<div class="row">
<!-- Message Length filter -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Filter toggle.">
<input type="checkbox" id="filter-messages" data-filter="longMessageToggle">
<span class="slider round"></span>
</label>
<button type="button" id="filter-msglen-btn" class="btn btn-md btn-box-tool" style="margin-bottom: 7px;" data-toggle="tooltip" title="Filter settings.">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">Paragraph Filter</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Removes messages that are too long.</p>
</div>
</form>
</div>
</div>
<!-- Fake Purge filter -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Filter toggle.">
<input type="checkbox" id="filter-purges" data-filter="fakePurgeToggle">
<span class="slider round"></span>
</label>
<button type="button" id="filter-purges-btn" class="btn btn-md btn-box-tool" style="margin-bottom: 7px;" data-toggle="tooltip" title="Filter settings.">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">Fake Purge Filter</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Removes messages that are a fake purge (<code>&lt;message deleted&gt;</code> variations).</p>
</div>
</form>
</div>
</div>
<!-- Spam Tracker filter -->
<div class="col-md-4">
<div class="box box-solid">
<div class="box-header with-border">
<div class="box-tools pull-right">
<label class="switch" data-toggle="tooltip" title="Filter toggle.">
<input type="checkbox" id="filter-tracker" data-filter="spamTrackerToggle">
<span class="slider round"></span>
</label>
<button type="button" id="filter-tracker-btn" class="btn btn-md btn-box-tool" style="margin-bottom: 7px;" data-toggle="tooltip" title="Filter settings.">
<i class="fa fa-cog fa-lg"></i>
</button>
</div>
<h3 class="box-title">User Moderation</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<p class="auto-cut">Manage how many messages a user can send in a time frame.</p>
</div>
</form>
</div>
</div>
</div>
</section>
<!-- filters -->
<script src="/panel/js/pages/moderation/filters.js"></script>
</main>

View File

@@ -0,0 +1,51 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<main>
<!-- Header -->
<section class="content-header">
<h1>Moderation</h1>
<ol class="breadcrumb">
<li><a href="javascript:void(0);"><i class="fa fa-dashboard"></i> Home</a></li>
<li>Moderation</li>
<li class="active">Whitelist</li>
</ol>
</section>
<!-- Main content -->
<section class="content">
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title">Whitelist</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<button class="btn btn-primary btn-sm pull-right" type="button" id="add-whitelist-button"><i class="fa fa-plus"></i>&nbsp; Add Whitelist</button>
<div class="load-ajax">
<div class="spinner"></div>
<p class="load-ajax-text">Loading...</p>
</div>
<table id="whitelistTable" class="table table-bordered table-hover"></table>
</div>
</form>
</div>
</section>
<!-- whitelist -->
<script src="/panel/js/pages/moderation/whitelist.js"></script>
</main>

View File

@@ -0,0 +1,50 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<main>
<!-- Header -->
<section class="content-header">
<h1>Permissions</h1>
<ol class="breadcrumb">
<li><a href="javascript:void(0);"><i class="fa fa-dashboard"></i> Home</a></li>
<li class="active">Permissions</li>
</ol>
</section>
<!-- Main content -->
<section class="content">
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title">User Permissions</h3>
</div>
<form role="form">
<!-- Box content -->
<div class="box-body">
<button class="btn btn-primary btn-sm pull-right" type="button" id="add-permissions-button"><i class="fa fa-user"></i>&nbsp; Set User Permission</button>
<div class="load-ajax">
<div class="spinner"></div>
<p class="load-ajax-text">Loading, this could take time...</p>
</div>
<table id="permissionsTable" class="table table-bordered table-hover"></table>
</div>
</form>
</div>
</section>
<!-- permissions -->
<script src="/panel/js/pages/permissions/permissions.js"></script>
</main>

View File

@@ -0,0 +1,63 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<main>
<!-- Header -->
<section class="content-header">
<h1>Quotes</h1>
<ol class="breadcrumb">
<li><a href="javascript:void(0);"><i class="fa fa-dashboard"></i> Home</a></li>
<li class="active">Quotes</li>
</ol>
</section>
<!-- Main content -->
<section class="content">
<div class="row">
<div class="col-md-12">
<div class="box box-solid">
<div class="box-header with-border">
<label class="switch" data-toggle="tooltip" title="Module toggle">
<input type="checkbox" id="quotesModuleToggle" checked>
<span class="slider round"></span>
</label>
<h3 class="box-title">Quotes</h3>
</div>
<form role="form" id="quotesModule">
<!-- Box content -->
<div class="box-body">
<div class="btn-toolbar pull-right">
<button class="btn btn-primary btn-sm" type="button" id="add-quote-button"><i class="fa fa-plus"></i>&nbsp; Add Quote</button>
<button class="btn btn-primary btn-sm" type="button" id="quote-settings-button"><i class="fa fa-cog"></i>&nbsp; Settings</button>
</div>
<div class="load-ajax">
<div class="spinner"></div>
<p class="load-ajax-text">Loading...</p>
</div>
<table id="quotesTable" class="table table-bordered table-hover"></table>
</div>
</form>
</div>
</div>
</div>
</section>
<!-- quotes -->
<script src="/panel/js/pages/quotes/quotes.js"></script>
</main>

View File

@@ -0,0 +1,63 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<main>
<!-- Header -->
<section class="content-header">
<h1>Custom Ranks</h1>
<ol class="breadcrumb">
<li><a href="javascript:void(0);"><i class="fa fa-dashboard"></i> Home</a></li>
<li>Ranking</li>
<li class="active">Custom Ranks</li>
</ol>
</section>
<!-- Main content -->
<section class="content">
<div class="row">
<div class="col-md-12">
<div class="box box-solid">
<div class="box-header with-border">
<label class="switch" data-toggle="tooltip" title="Module toggle">
<input type="checkbox" id="ranksCustomModuleToggle" checked>
<span class="slider round"></span>
</label>
<h3 class="box-title">Custom User Ranks</h3>
</div>
<form role="form" id="ranksCustomModule">
<!-- Box content -->
<div class="box-body">
<div class="btn-toolbar pull-right">
<button class="btn btn-primary btn-sm" type="button" id="rank-user-button"><i class="fa fa-user"></i>&nbsp; Set User Rank</button>
<button class="btn btn-primary btn-sm" type="button" id="rank-settings-button"><i class="fa fa-cog"></i>&nbsp; Settings</button>
</div>
<div class="load-ajax">
<div class="spinner"></div>
<p class="load-ajax-text">Loading...</p>
</div>
<table id="ranksCustomTable" class="table table-bordered table-hover"></table>
</div>
</form>
</div>
</div>
</div>
</section>
<!-- ranking -->
<script src="/panel/js/pages/ranking/customRanks.js"></script>
</main>

View File

@@ -0,0 +1,60 @@
<!--
Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<main>
<!-- Header -->
<section class="content-header">
<h1>Global Ranks</h1>
<ol class="breadcrumb">
<li><a href="javascript:void(0);"><i class="fa fa-dashboard"></i> Home</a></li>
<li>Ranking</li>
<li class="active">Global Ranks</li>
</ol>
</section>
<!-- Main content -->
<section class="content">
<div class="row">
<div class="col-md-12">
<div class="box box-solid">
<div class="box-header with-border">
<label class="switch" data-toggle="tooltip" title="Module toggle">
<input type="checkbox" id="ranksModuleToggle" checked>
<span class="slider round"></span>
</label>
<h3 class="box-title">Global Ranks</h3>
</div>
<form role="form" id="ranksModule">
<!-- Box content -->
<div class="box-body">
<button class="btn btn-primary btn-sm pull-right" type="button" id="add-rank-button"><i class="fa fa-plus"></i>&nbsp; Add Rank</button>
<div class="load-ajax">
<div class="spinner"></div>
<p class="load-ajax-text">Loading...</p>
</div>
<table id="ranksTable" class="table table-bordered table-hover"></table>
</div>
</form>
</div>
</div>
</div>
</section>
<!-- ranking -->
<script src="/panel/js/pages/ranking/globalRanks.js"></script>
</main>

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