mirror of
https://github.com/skylanix/MamieHenriette.git
synced 2026-02-06 14:50:34 +01:00
Supprime les fichiers CSS obsolètes et met à jour les templates HTML pour une interface utilisateur améliorée. Les modifications incluent la refonte des pages de configuration, d'alerte live, de modération, et d'aide Twitch, avec une mise en page responsive et des styles modernisés. Les anciennes feuilles de style MVP.css et style.css ont été supprimées au profit d'une intégration de Tailwind CSS.
This commit is contained in:
@@ -1,603 +0,0 @@
|
|||||||
/* MVP.css v1.17.2 - https://github.com/andybrewer/mvp */
|
|
||||||
|
|
||||||
:root {
|
|
||||||
--active-brightness: 0.85;
|
|
||||||
--border-radius: 5px;
|
|
||||||
--box-shadow: 2px 2px 10px;
|
|
||||||
--color-accent: #118bee15;
|
|
||||||
--color-bg: #fff;
|
|
||||||
--color-bg-secondary: #e9e9e9;
|
|
||||||
--color-link: #118bee;
|
|
||||||
--color-secondary: #920de9;
|
|
||||||
--color-secondary-accent: #920de90b;
|
|
||||||
--color-shadow: #f4f4f4;
|
|
||||||
--color-table: #118bee;
|
|
||||||
--color-text: #000;
|
|
||||||
--color-text-secondary: #999;
|
|
||||||
--color-scrollbar: #cacae8;
|
|
||||||
--font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
|
|
||||||
--hover-brightness: 1.2;
|
|
||||||
--justify-important: center;
|
|
||||||
--justify-normal: left;
|
|
||||||
--line-height: 1.5;
|
|
||||||
--width-card: 285px;
|
|
||||||
--width-card-medium: 460px;
|
|
||||||
--width-card-wide: 800px;
|
|
||||||
--width-content: 1080px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
|
||||||
:root[color-mode="user"] {
|
|
||||||
--color-accent: #0097fc4f;
|
|
||||||
--color-bg: #333;
|
|
||||||
--color-bg-secondary: #555;
|
|
||||||
--color-link: #0097fc;
|
|
||||||
--color-secondary: #e20de9;
|
|
||||||
--color-secondary-accent: #e20de94f;
|
|
||||||
--color-shadow: #bbbbbb20;
|
|
||||||
--color-table: #0097fc;
|
|
||||||
--color-text: #f7f7f7;
|
|
||||||
--color-text-secondary: #aaa;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
html {
|
|
||||||
scroll-behavior: smooth;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-reduced-motion: reduce) {
|
|
||||||
html {
|
|
||||||
scroll-behavior: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Layout */
|
|
||||||
article aside {
|
|
||||||
background: var(--color-secondary-accent);
|
|
||||||
border-left: 4px solid var(--color-secondary);
|
|
||||||
padding: 0.01rem 0.8rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
background: var(--color-bg);
|
|
||||||
color: var(--color-text);
|
|
||||||
font-family: var(--font-family);
|
|
||||||
line-height: var(--line-height);
|
|
||||||
margin: 0;
|
|
||||||
overflow-x: hidden;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
footer,
|
|
||||||
header,
|
|
||||||
main {
|
|
||||||
margin: 0 auto;
|
|
||||||
max-width: var(--width-content);
|
|
||||||
/* padding: 3rem 1rem; */
|
|
||||||
padding: 1rem 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr {
|
|
||||||
background-color: var(--color-bg-secondary);
|
|
||||||
border: none;
|
|
||||||
height: 1px;
|
|
||||||
margin: 4rem 0;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
section {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
justify-content: var(--justify-important);
|
|
||||||
}
|
|
||||||
|
|
||||||
section img,
|
|
||||||
article img {
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
section pre {
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
section aside {
|
|
||||||
border: 1px solid var(--color-bg-secondary);
|
|
||||||
border-radius: var(--border-radius);
|
|
||||||
box-shadow: var(--box-shadow) var(--color-shadow);
|
|
||||||
margin: 1rem;
|
|
||||||
padding: 1.25rem;
|
|
||||||
width: var(--width-card);
|
|
||||||
}
|
|
||||||
|
|
||||||
section aside:hover {
|
|
||||||
box-shadow: var(--box-shadow) var(--color-bg-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
[hidden] {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Headers */
|
|
||||||
article header,
|
|
||||||
div header,
|
|
||||||
main header {
|
|
||||||
padding-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
header {
|
|
||||||
text-align: var(--justify-important);
|
|
||||||
}
|
|
||||||
|
|
||||||
header a b,
|
|
||||||
header a em,
|
|
||||||
header a i,
|
|
||||||
header a strong {
|
|
||||||
margin-left: 0.5rem;
|
|
||||||
margin-right: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* header nav img {
|
|
||||||
margin: 1rem 0;
|
|
||||||
} */
|
|
||||||
|
|
||||||
section header {
|
|
||||||
padding-top: 0;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Nav */
|
|
||||||
nav {
|
|
||||||
align-items: center;
|
|
||||||
display: flex;
|
|
||||||
font-weight: bold;
|
|
||||||
justify-content: space-between;
|
|
||||||
/* margin-bottom: 7rem; */
|
|
||||||
}
|
|
||||||
|
|
||||||
nav ul {
|
|
||||||
list-style: none;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
nav ul li {
|
|
||||||
display: inline-block;
|
|
||||||
margin: 0 0.5rem;
|
|
||||||
position: relative;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Nav Dropdown */
|
|
||||||
nav ul li:hover ul {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
nav ul li ul {
|
|
||||||
background: var(--color-bg);
|
|
||||||
border: 1px solid var(--color-bg-secondary);
|
|
||||||
border-radius: var(--border-radius);
|
|
||||||
box-shadow: var(--box-shadow) var(--color-shadow);
|
|
||||||
display: none;
|
|
||||||
height: auto;
|
|
||||||
left: -2px;
|
|
||||||
padding: 0.5rem 1rem;
|
|
||||||
position: absolute;
|
|
||||||
top: 1.7rem;
|
|
||||||
white-space: nowrap;
|
|
||||||
width: auto;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
nav ul li ul::before {
|
|
||||||
/* fill gap above to make mousing over them easier */
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
top: -0.5rem;
|
|
||||||
height: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
nav ul li ul li,
|
|
||||||
nav ul li ul li a {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Nav for Mobile */
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
nav {
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
nav ul li {
|
|
||||||
width: calc(100% - 1em);
|
|
||||||
}
|
|
||||||
|
|
||||||
nav ul li ul {
|
|
||||||
border: none;
|
|
||||||
box-shadow: none;
|
|
||||||
display: block;
|
|
||||||
position: static;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Typography */
|
|
||||||
code,
|
|
||||||
samp {
|
|
||||||
background-color: var(--color-accent);
|
|
||||||
border-radius: var(--border-radius);
|
|
||||||
color: var(--color-text);
|
|
||||||
display: inline-block;
|
|
||||||
margin: 0 0.1rem;
|
|
||||||
padding: 0 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
details {
|
|
||||||
margin: 1.3rem 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
details summary {
|
|
||||||
font-weight: bold;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1,
|
|
||||||
h2,
|
|
||||||
h3,
|
|
||||||
h4,
|
|
||||||
h5,
|
|
||||||
h6 {
|
|
||||||
line-height: var(--line-height);
|
|
||||||
text-wrap: balance;
|
|
||||||
}
|
|
||||||
|
|
||||||
mark {
|
|
||||||
padding: 0.1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
ol li,
|
|
||||||
ul li {
|
|
||||||
padding: 0.2rem 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
margin: 0.75rem 0;
|
|
||||||
padding: 0;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre {
|
|
||||||
margin: 1rem 0;
|
|
||||||
max-width: var(--width-card-wide);
|
|
||||||
padding: 1rem 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre code,
|
|
||||||
pre samp {
|
|
||||||
display: block;
|
|
||||||
max-width: var(--width-card-wide);
|
|
||||||
padding: 0.5rem 2rem;
|
|
||||||
white-space: pre-wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
small {
|
|
||||||
color: var(--color-text-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
sup {
|
|
||||||
background-color: var(--color-secondary);
|
|
||||||
border-radius: var(--border-radius);
|
|
||||||
color: var(--color-bg);
|
|
||||||
font-size: xx-small;
|
|
||||||
font-weight: bold;
|
|
||||||
margin: 0.2rem;
|
|
||||||
padding: 0.2rem 0.3rem;
|
|
||||||
position: relative;
|
|
||||||
top: -2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Links */
|
|
||||||
a {
|
|
||||||
color: var(--color-link);
|
|
||||||
display: inline-block;
|
|
||||||
font-weight: bold;
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
a:hover {
|
|
||||||
filter: brightness(var(--hover-brightness));
|
|
||||||
}
|
|
||||||
|
|
||||||
a:active {
|
|
||||||
filter: brightness(var(--active-brightness));
|
|
||||||
}
|
|
||||||
|
|
||||||
a b,
|
|
||||||
a em,
|
|
||||||
a i,
|
|
||||||
a strong,
|
|
||||||
button,
|
|
||||||
input[type="submit"] {
|
|
||||||
border-radius: var(--border-radius);
|
|
||||||
display: inline-block;
|
|
||||||
font-size: medium;
|
|
||||||
font-weight: bold;
|
|
||||||
line-height: var(--line-height);
|
|
||||||
margin: 0.5rem 0;
|
|
||||||
padding: 1rem 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
button,
|
|
||||||
input[type="submit"] {
|
|
||||||
font-family: var(--font-family);
|
|
||||||
}
|
|
||||||
|
|
||||||
button:hover,
|
|
||||||
input[type="submit"]:hover {
|
|
||||||
cursor: pointer;
|
|
||||||
filter: brightness(var(--hover-brightness));
|
|
||||||
}
|
|
||||||
|
|
||||||
button:active,
|
|
||||||
input[type="submit"]:active {
|
|
||||||
filter: brightness(var(--active-brightness));
|
|
||||||
}
|
|
||||||
|
|
||||||
a b,
|
|
||||||
a strong,
|
|
||||||
button,
|
|
||||||
input[type="submit"] {
|
|
||||||
background-color: var(--color-link);
|
|
||||||
border: 2px solid var(--color-link);
|
|
||||||
color: var(--color-bg);
|
|
||||||
}
|
|
||||||
|
|
||||||
a em,
|
|
||||||
a i {
|
|
||||||
border: 2px solid var(--color-link);
|
|
||||||
border-radius: var(--border-radius);
|
|
||||||
color: var(--color-link);
|
|
||||||
display: inline-block;
|
|
||||||
padding: 1rem 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
article aside a {
|
|
||||||
color: var(--color-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Images */
|
|
||||||
figure {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
figure img {
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
figure figcaption {
|
|
||||||
color: var(--color-text-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Forms */
|
|
||||||
button:disabled,
|
|
||||||
input:disabled {
|
|
||||||
background: var(--color-bg-secondary);
|
|
||||||
border-color: var(--color-bg-secondary);
|
|
||||||
color: var(--color-text-secondary);
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
|
||||||
|
|
||||||
button[disabled]:hover,
|
|
||||||
input[type="submit"][disabled]:hover {
|
|
||||||
filter: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
form {
|
|
||||||
border: 1px solid var(--color-bg-secondary);
|
|
||||||
border-radius: var(--border-radius);
|
|
||||||
box-shadow: var(--box-shadow) var(--color-shadow);
|
|
||||||
display: block;
|
|
||||||
max-width: var(--width-card-wide);
|
|
||||||
min-width: var(--width-card);
|
|
||||||
padding: 1.5rem;
|
|
||||||
text-align: var(--justify-normal);
|
|
||||||
}
|
|
||||||
|
|
||||||
form header {
|
|
||||||
margin: 1.5rem 0;
|
|
||||||
padding: 1.5rem 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
input,
|
|
||||||
label,
|
|
||||||
select,
|
|
||||||
textarea {
|
|
||||||
display: block;
|
|
||||||
font-size: inherit;
|
|
||||||
max-width: var(--width-card-wide);
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="checkbox"],
|
|
||||||
input[type="radio"] {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="checkbox"]+label,
|
|
||||||
input[type="radio"]+label {
|
|
||||||
display: inline-block;
|
|
||||||
font-weight: normal;
|
|
||||||
position: relative;
|
|
||||||
top: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="range"] {
|
|
||||||
padding: 0.4rem 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
input,
|
|
||||||
select,
|
|
||||||
textarea {
|
|
||||||
border: 1px solid var(--color-bg-secondary);
|
|
||||||
border-radius: var(--border-radius);
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
padding: 0.4rem 0.8rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="text"],
|
|
||||||
input[type="password"],
|
|
||||||
input[type="email"],
|
|
||||||
textarea {
|
|
||||||
width: calc(100% - 1.6rem);
|
|
||||||
}
|
|
||||||
|
|
||||||
input[readonly],
|
|
||||||
textarea[readonly] {
|
|
||||||
background-color: var(--color-bg-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
label {
|
|
||||||
font-weight: bold;
|
|
||||||
margin-bottom: 0.2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Popups */
|
|
||||||
dialog {
|
|
||||||
max-width: 90%;
|
|
||||||
max-height: 85dvh;
|
|
||||||
margin: auto;
|
|
||||||
padding-block: 0;
|
|
||||||
padding-inline: 20px;
|
|
||||||
border: 1px solid var(--color-bg-secondary);
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
overscroll-behavior: contain;
|
|
||||||
scroll-behavior: smooth;
|
|
||||||
scrollbar-width: none;
|
|
||||||
/* Hide scrollbar for Firefox */
|
|
||||||
-ms-overflow-style: none;
|
|
||||||
/* Hide scrollbar for IE and Edge */
|
|
||||||
scrollbar-color: transparent transparent;
|
|
||||||
animation: bottom-to-top 0.25s ease-in-out forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
dialog::-webkit-scrollbar {
|
|
||||||
width: 0;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
dialog::-webkit-scrollbar-track {
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
dialog::-webkit-scrollbar-thumb {
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 650px) {
|
|
||||||
dialog {
|
|
||||||
max-width: 39rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dialog::backdrop {
|
|
||||||
background-color: rgba(0, 0, 0, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes bottom-to-top {
|
|
||||||
0% {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateY(10%);
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
opacity: 1;
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dialog hr {
|
|
||||||
margin-block: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tables */
|
|
||||||
table {
|
|
||||||
border: 1px solid var(--color-bg-secondary);
|
|
||||||
border-radius: var(--border-radius);
|
|
||||||
border-spacing: 0;
|
|
||||||
display: inline-block;
|
|
||||||
max-width: 100%;
|
|
||||||
overflow-x: auto;
|
|
||||||
padding: 0;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
table td,
|
|
||||||
table th,
|
|
||||||
table tr {
|
|
||||||
padding: 0.4rem 0.8rem;
|
|
||||||
text-align: var(--justify-important);
|
|
||||||
}
|
|
||||||
|
|
||||||
table thead {
|
|
||||||
background-color: var(--color-table);
|
|
||||||
border-collapse: collapse;
|
|
||||||
border-radius: var(--border-radius);
|
|
||||||
color: var(--color-bg);
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
table thead tr:first-child th:first-child {
|
|
||||||
border-top-left-radius: var(--border-radius);
|
|
||||||
}
|
|
||||||
|
|
||||||
table thead tr:first-child th:last-child {
|
|
||||||
border-top-right-radius: var(--border-radius);
|
|
||||||
}
|
|
||||||
|
|
||||||
table thead th:first-child,
|
|
||||||
table tr td:first-child {
|
|
||||||
text-align: var(--justify-normal);
|
|
||||||
}
|
|
||||||
|
|
||||||
table tr:nth-child(even) {
|
|
||||||
background-color: var(--color-accent);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Quotes */
|
|
||||||
blockquote {
|
|
||||||
display: block;
|
|
||||||
font-size: x-large;
|
|
||||||
line-height: var(--line-height);
|
|
||||||
margin: 1rem auto;
|
|
||||||
max-width: var(--width-card-medium);
|
|
||||||
padding: 1.5rem 1rem;
|
|
||||||
text-align: var(--justify-important);
|
|
||||||
}
|
|
||||||
|
|
||||||
blockquote footer {
|
|
||||||
color: var(--color-text-secondary);
|
|
||||||
display: block;
|
|
||||||
font-size: small;
|
|
||||||
line-height: var(--line-height);
|
|
||||||
padding: 1.5rem 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Scrollbars */
|
|
||||||
* {
|
|
||||||
scrollbar-width: thin;
|
|
||||||
scrollbar-color: var(--color-scrollbar) transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
*::-webkit-scrollbar {
|
|
||||||
width: 5px;
|
|
||||||
height: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
*::-webkit-scrollbar-track {
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
*::-webkit-scrollbar-thumb {
|
|
||||||
background-color: var(--color-scrollbar);
|
|
||||||
border-radius: 10px;
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
header nav img {
|
|
||||||
border-radius: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
table th,
|
|
||||||
table td {
|
|
||||||
text-align: left;
|
|
||||||
vertical-align: top;
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.live-alert tr td:last-child {
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
a.icon {
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
@@ -1,55 +1,101 @@
|
|||||||
{% extends "template.html" %}
|
{% extends "template.html" %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>Commandes de Mamie</h1>
|
<div class="mb-6">
|
||||||
<p>Gérez les commandes personnalisées du bot. Ces commandes peuvent être activées sur Discord et/ou Twitch selon vos besoins.</p>
|
<h1 class="text-2xl font-semibold text-slate-800 dark:text-white mb-1">Commandes</h1>
|
||||||
<table>
|
<p class="text-sm text-slate-600 dark:text-slate-400">
|
||||||
|
Gérez les commandes personnalisées du bot. Ces commandes peuvent être activées sur Discord et/ou Twitch.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="bg-white dark:bg-slate-800 rounded-lg border border-slate-200 dark:border-slate-700 overflow-hidden mb-6">
|
||||||
|
<div class="overflow-x-auto">
|
||||||
|
<table class="w-full">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr class="bg-slate-50 dark:bg-slate-700/50 border-b border-slate-200 dark:border-slate-700">
|
||||||
<th>Commande</th>
|
<th class="px-4 py-3 text-left text-xs font-medium text-slate-500 dark:text-slate-400 uppercase">Commande</th>
|
||||||
<th>Réponse</th>
|
<th class="px-4 py-3 text-left text-xs font-medium text-slate-500 dark:text-slate-400 uppercase">Réponse</th>
|
||||||
<th>Discord</th>
|
<th class="px-4 py-3 text-center text-xs font-medium text-slate-500 dark:text-slate-400 uppercase">Discord</th>
|
||||||
<th>Twitch</th>
|
<th class="px-4 py-3 text-center text-xs font-medium text-slate-500 dark:text-slate-400 uppercase">Twitch</th>
|
||||||
<th>Actions</th>
|
<th class="px-4 py-3 text-right text-xs font-medium text-slate-500 dark:text-slate-400 uppercase">Actions</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody class="divide-y divide-slate-200 dark:divide-slate-700">
|
||||||
{% for commande in commandes %}
|
{% for commande in commandes %}
|
||||||
|
<tr class="hover:bg-slate-50 dark:hover:bg-slate-700/30 transition-colors">
|
||||||
|
<td class="px-4 py-3">
|
||||||
|
<code class="px-1.5 py-0.5 bg-slate-100 dark:bg-slate-700 text-slate-700 dark:text-slate-300 rounded text-xs font-mono">{{ commande.trigger }}</code>
|
||||||
|
</td>
|
||||||
|
<td class="px-4 py-3 text-slate-600 dark:text-slate-400 text-sm max-w-xs">
|
||||||
|
<div class="line-clamp-2">{{ commande.response }}</div>
|
||||||
|
</td>
|
||||||
|
<td class="px-4 py-3 text-center">
|
||||||
|
<a href="{{ url_for('toggle_discord_commande', commande_id = commande.id) }}" class="inline-flex" title="{{ 'Désactiver' if commande.discord_enable else 'Activer' }}">
|
||||||
|
{% if commande.discord_enable %}
|
||||||
|
<span class="w-5 h-5 text-green-600 dark:text-green-500">✓</span>
|
||||||
|
{% else %}
|
||||||
|
<span class="w-5 h-5 text-slate-400">–</span>
|
||||||
|
{% endif %}
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td class="px-4 py-3 text-center">
|
||||||
|
<a href="{{ url_for('toggle_twitch_commande', commande_id = commande.id) }}" class="inline-flex" title="{{ 'Désactiver' if commande.twitch_enable else 'Activer' }}">
|
||||||
|
{% if commande.twitch_enable %}
|
||||||
|
<span class="w-5 h-5 text-green-600 dark:text-green-500">✓</span>
|
||||||
|
{% else %}
|
||||||
|
<span class="w-5 h-5 text-slate-400">–</span>
|
||||||
|
{% endif %}
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td class="px-4 py-3 text-right">
|
||||||
|
<a href="{{ url_for('delete_commande', commande_id = commande.id) }}" onclick="return confirm('Êtes-vous sûr de vouloir supprimer cette commande ?')" class="text-sm text-slate-500 hover:text-red-600 dark:hover:text-red-400 transition-colors">
|
||||||
|
Supprimer
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% else %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ commande.trigger }}</td>
|
<td colspan="5" class="px-4 py-8 text-center text-sm text-slate-500 dark:text-slate-400">
|
||||||
<td>{{ commande.response }}</td>
|
Aucune commande configurée
|
||||||
<td>
|
|
||||||
<a href="{{ url_for('toggle_discord_commande', commande_id = commande.id) }}" class="icon">
|
|
||||||
{{ '✅' if commande.discord_enable else '❌' }}
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<a href="{{ url_for('toggle_twitch_commande', commande_id = commande.id) }}" class="icon">
|
|
||||||
{{ '✅' if commande.twitch_enable else '❌' }}
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<a href="{{ url_for('delete_commande', commande_id = commande.id) }}" onclick="return confirm('Êtes-vous sûr de vouloir supprimer cette commande ?')">Supprimer</a>
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<h2>Ajouter une commande</h2>
|
<div class="bg-white dark:bg-slate-800 rounded-lg border border-slate-200 dark:border-slate-700 p-5">
|
||||||
<form action="{{ url_for('add_commande') }}" method="POST">
|
<h2 class="text-lg font-medium text-slate-800 dark:text-white mb-5">Ajouter une commande</h2>
|
||||||
<label for="trigger">Commande</label>
|
|
||||||
<input name="trigger" type="text" />
|
<form action="{{ url_for('add_commande') }}" method="POST" class="space-y-6">
|
||||||
<label for="response">Réponse</label>
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||||
<textarea name="response" rows="5" cols="50"></textarea>
|
|
||||||
<div>
|
<div>
|
||||||
<label for="discord_enable">Discord</label>
|
<label for="trigger" class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Commande</label>
|
||||||
<input name="discord_enable" type="checkbox" checked />
|
<input type="text" name="trigger" id="trigger" placeholder="!macommande" class="w-full px-3 py-2 bg-slate-50 dark:bg-slate-700 border border-slate-300 dark:border-slate-600 rounded-lg text-sm text-slate-900 dark:text-white placeholder-slate-500 dark:placeholder-slate-400 focus:ring-2 focus:ring-slate-500 focus:border-transparent transition-all">
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex items-end gap-6">
|
||||||
|
<label class="flex items-center gap-3 cursor-pointer">
|
||||||
|
<input type="checkbox" name="discord_enable" checked class="w-4 h-4 text-slate-600 bg-slate-100 dark:bg-slate-700 border-slate-300 dark:border-slate-600 rounded focus:ring-slate-500 focus:ring-2">
|
||||||
|
<span class="text-sm text-slate-700 dark:text-slate-300">Discord</span>
|
||||||
|
</label>
|
||||||
|
<label class="flex items-center gap-3 cursor-pointer">
|
||||||
|
<input type="checkbox" name="twitch_enable" class="w-4 h-4 text-slate-600 bg-slate-100 dark:bg-slate-700 border-slate-300 dark:border-slate-600 rounded focus:ring-slate-500 focus:ring-2">
|
||||||
|
<span class="text-sm text-slate-700 dark:text-slate-300">Twitch</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label for="twitch_enable">Twitch</label>
|
<label for="response" class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Réponse</label>
|
||||||
<input name="twitch_enable" type="checkbox" unchecked />
|
<textarea name="response" id="response" rows="4" placeholder="Le message que le bot enverra..." class="w-full px-3 py-2 bg-slate-50 dark:bg-slate-700 border border-slate-300 dark:border-slate-600 rounded-lg text-sm text-slate-900 dark:text-white placeholder-slate-500 dark:placeholder-slate-400 focus:ring-2 focus:ring-slate-500 focus:border-transparent transition-all resize-none"></textarea>
|
||||||
</div>
|
</div>
|
||||||
<input type="Submit" value="Ajouter">
|
|
||||||
</form>
|
<div class="flex justify-end">
|
||||||
|
<button type="submit" class="px-4 py-2 bg-slate-800 hover:bg-slate-700 dark:bg-slate-700 dark:hover:bg-slate-600 text-white text-sm font-medium rounded-lg transition-colors">
|
||||||
|
Ajouter
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -1,112 +1,126 @@
|
|||||||
{% extends "template.html" %}
|
{% extends "template.html" %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>Configuration de Mamie</h1>
|
<div class="mb-6">
|
||||||
<p>Configurez les tokens Discord, les notifications Humble Bundle et l'API Twitch.</p>
|
<h1 class="text-2xl font-semibold text-slate-800 dark:text-white mb-1">Configurations</h1>
|
||||||
|
<p class="text-sm text-slate-600 dark:text-slate-400">
|
||||||
|
Paramètres Discord, Twitch et Humble Bundle.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<h2>Discord</h2>
|
<div class="bg-white dark:bg-slate-800 rounded-lg border border-slate-200 dark:border-slate-700 mb-6 overflow-hidden">
|
||||||
<form action="{{ url_for('updateConfiguration') }}" method="POST">
|
<div class="px-5 py-4 border-b border-slate-200 dark:border-slate-700">
|
||||||
<fieldset>
|
<h2 class="text-lg font-medium text-slate-800 dark:text-white">Discord</h2>
|
||||||
<legend>API Discord</legend>
|
</div>
|
||||||
<label for="discord_token">Token Discord (caché)</label>
|
|
||||||
<input name="discord_token" type="password" placeholder="Votre token Discord" />
|
|
||||||
<small>Nécessite un redémarrage après modification</small>
|
|
||||||
</fieldset>
|
|
||||||
|
|
||||||
<fieldset>
|
<form action="{{ url_for('updateConfiguration') }}" method="POST" class="p-5 space-y-6">
|
||||||
<legend>Messages de bienvenue</legend>
|
<div>
|
||||||
<label for="welcome_enable">
|
<label for="discord_token" class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Token Discord</label>
|
||||||
<input type="checkbox" name="welcome_enable" {% if configuration.getValue('welcome_enable') %}checked="checked"{% endif %}>
|
<input type="password" name="discord_token" id="discord_token" placeholder="Votre token Discord (caché)" class="w-full px-3 py-2 bg-slate-50 dark:bg-slate-700 border border-slate-300 dark:border-slate-600 rounded-lg text-sm text-slate-900 dark:text-white placeholder-slate-500 dark:placeholder-slate-400 focus:ring-2 focus:ring-slate-500 focus:border-transparent transition-all">
|
||||||
Activer le message de bienvenue pour les nouveaux membres
|
<p class="mt-1 text-xs text-amber-600 dark:text-amber-400">Nécessite un redémarrage après modification</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="pt-4 border-t border-slate-200 dark:border-slate-700">
|
||||||
|
<h3 class="text-sm font-medium text-slate-800 dark:text-white mb-4">Messages de bienvenue</h3>
|
||||||
|
|
||||||
|
<label class="flex items-center gap-3 cursor-pointer mb-4">
|
||||||
|
<input type="checkbox" name="welcome_enable" {% if configuration.getValue('welcome_enable') %}checked{% endif %} class="w-4 h-4 text-slate-600 bg-slate-100 dark:bg-slate-700 border-slate-300 dark:border-slate-600 rounded focus:ring-slate-500">
|
||||||
|
<span class="text-sm text-slate-700 dark:text-slate-300">Activer le message de bienvenue</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label for="welcome_channel_id">Canal de bienvenue</label>
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
|
||||||
<select name="welcome_channel_id">
|
<div>
|
||||||
|
<label for="welcome_channel_id" class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Canal de bienvenue</label>
|
||||||
|
<select name="welcome_channel_id" id="welcome_channel_id" class="w-full px-3 py-2 bg-slate-50 dark:bg-slate-700 border border-slate-300 dark:border-slate-600 rounded-lg text-sm text-slate-900 dark:text-white focus:ring-2 focus:ring-slate-500 focus:border-transparent transition-all">
|
||||||
{% for channel in channels %}
|
{% for channel in channels %}
|
||||||
<option value="{{channel.id}}" {% if configuration.getIntValue('welcome_channel_id')==channel.id %}selected="selected"{% endif %}>
|
<option value="{{ channel.id }}" {% if configuration.getIntValue('welcome_channel_id') == channel.id %}selected{% endif %}>{{ channel.name }}</option>
|
||||||
{{channel.name}}
|
|
||||||
</option>
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<label for="welcome_message">Message personnalisé de bienvenue</label>
|
<div>
|
||||||
<textarea name="welcome_message" rows="3" placeholder="Bienvenue {member.mention} sur le serveur !">{{ configuration.getValue('welcome_message') }}</textarea>
|
<label for="welcome_message" class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Message personnalisé</label>
|
||||||
<small>
|
<textarea name="welcome_message" id="welcome_message" rows="2" placeholder="Bienvenue {member.mention} sur le serveur !" class="w-full px-3 py-2 bg-slate-50 dark:bg-slate-700 border border-slate-300 dark:border-slate-600 rounded-lg text-sm text-slate-900 dark:text-white placeholder-slate-500 dark:placeholder-slate-400 focus:ring-2 focus:ring-slate-500 focus:border-transparent transition-all resize-none">{{ configuration.getValue('welcome_message') }}</textarea>
|
||||||
<strong>Syntaxes disponibles :</strong><br>
|
</div>
|
||||||
• <code>{member.mention}</code> - Mentionne l'utilisateur (@NomUtilisateur)<br>
|
|
||||||
• <code>{member.name}</code> - Nom d'utilisateur (sans mention)<br>
|
|
||||||
• <code>{member.display_name}</code> - Surnom sur le serveur<br>
|
|
||||||
• <code>{member.id}</code> - ID de l'utilisateur<br>
|
|
||||||
• <code>{server.name}</code> - Nom du serveur<br>
|
|
||||||
• <code>{server.member_count}</code> - Nombre total de membres<br>
|
|
||||||
• <code><#ID_DU_CHANNEL></code> - Mentionne un salon (ex: <#123456789012345678>)
|
|
||||||
</small>
|
|
||||||
</fieldset>
|
|
||||||
|
|
||||||
<fieldset>
|
<div class="mt-3 bg-slate-50 dark:bg-slate-700/50 rounded-lg p-3">
|
||||||
<legend>Messages de départ</legend>
|
<p class="text-xs font-medium text-slate-600 dark:text-slate-400 mb-2">Variables :</p>
|
||||||
<label for="leave_enable">
|
<div class="flex flex-wrap gap-2 text-xs">
|
||||||
<input type="checkbox" name="leave_enable" {% if configuration.getValue('leave_enable') %}checked="checked"{% endif %}>
|
<code class="px-1.5 py-0.5 bg-slate-200 dark:bg-slate-600 rounded">{member.mention}</code>
|
||||||
Activer le message de départ quand un membre quitte le serveur
|
<code class="px-1.5 py-0.5 bg-slate-200 dark:bg-slate-600 rounded">{member.name}</code>
|
||||||
|
<code class="px-1.5 py-0.5 bg-slate-200 dark:bg-slate-600 rounded">{server.name}</code>
|
||||||
|
<code class="px-1.5 py-0.5 bg-slate-200 dark:bg-slate-600 rounded">{server.member_count}</code>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="pt-4 border-t border-slate-200 dark:border-slate-700">
|
||||||
|
<h3 class="text-sm font-medium text-slate-800 dark:text-white mb-4">Messages de départ</h3>
|
||||||
|
|
||||||
|
<label class="flex items-center gap-3 cursor-pointer mb-4">
|
||||||
|
<input type="checkbox" name="leave_enable" {% if configuration.getValue('leave_enable') %}checked{% endif %} class="w-4 h-4 text-slate-600 bg-slate-100 dark:bg-slate-700 border-slate-300 dark:border-slate-600 rounded focus:ring-slate-500">
|
||||||
|
<span class="text-sm text-slate-700 dark:text-slate-300">Activer le message de départ</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label for="leave_channel_id">Canal de départ</label>
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
|
||||||
<select name="leave_channel_id">
|
<div>
|
||||||
|
<label for="leave_channel_id" class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Canal de départ</label>
|
||||||
|
<select name="leave_channel_id" id="leave_channel_id" class="w-full px-3 py-2 bg-slate-50 dark:bg-slate-700 border border-slate-300 dark:border-slate-600 rounded-lg text-sm text-slate-900 dark:text-white focus:ring-2 focus:ring-slate-500 focus:border-transparent transition-all">
|
||||||
{% for channel in channels %}
|
{% for channel in channels %}
|
||||||
<option value="{{channel.id}}" {% if configuration.getIntValue('leave_channel_id')==channel.id %}selected="selected"{% endif %}>
|
<option value="{{ channel.id }}" {% if configuration.getIntValue('leave_channel_id') == channel.id %}selected{% endif %}>{{ channel.name }}</option>
|
||||||
{{channel.name}}
|
|
||||||
</option>
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<label for="leave_message">Message personnalisé de départ</label>
|
<div>
|
||||||
<textarea name="leave_message" rows="3" placeholder="{member.mention} a quitté le serveur.">{{ configuration.getValue('leave_message') }}</textarea>
|
<label for="leave_message" class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Message personnalisé</label>
|
||||||
<small>
|
<textarea name="leave_message" id="leave_message" rows="2" placeholder="{member.mention} a quitté le serveur." class="w-full px-3 py-2 bg-slate-50 dark:bg-slate-700 border border-slate-300 dark:border-slate-600 rounded-lg text-sm text-slate-900 dark:text-white placeholder-slate-500 dark:placeholder-slate-400 focus:ring-2 focus:ring-slate-500 focus:border-transparent transition-all resize-none">{{ configuration.getValue('leave_message') }}</textarea>
|
||||||
<strong>Syntaxes disponibles :</strong><br>
|
</div>
|
||||||
• <code>{member.mention}</code> - Mentionne l'utilisateur (@NomUtilisateur)<br>
|
</div>
|
||||||
• <code>{member.name}</code> - Nom d'utilisateur (sans mention)<br>
|
|
||||||
• <code>{member.display_name}</code> - Surnom sur le serveur<br>
|
|
||||||
• <code>{member.id}</code> - ID de l'utilisateur<br>
|
|
||||||
• <code>{server.name}</code> - Nom du serveur<br>
|
|
||||||
• <code>{server.member_count}</code> - Nombre total de membres<br>
|
|
||||||
• <code><#ID_DU_CHANNEL></code> - Mentionne un salon (ex: <#123456789012345678>)
|
|
||||||
</small>
|
|
||||||
</fieldset>
|
|
||||||
|
|
||||||
<fieldset>
|
<div class="pt-4 border-t border-slate-200 dark:border-slate-700">
|
||||||
<legend>Modération</legend>
|
<h3 class="text-sm font-medium text-slate-800 dark:text-white mb-4">Modération</h3>
|
||||||
<label for="moderation_enable">
|
|
||||||
<input type="checkbox" name="moderation_enable" {% if configuration.getValue('moderation_enable') %}checked="checked"{% endif %}>
|
<div class="space-y-3 mb-4">
|
||||||
Activer les commandes d'avertissement (!warn, !unwarn, !inspect)
|
<label class="flex items-center gap-3 cursor-pointer">
|
||||||
|
<input type="checkbox" name="moderation_enable" {% if configuration.getValue('moderation_enable') %}checked{% endif %} class="w-4 h-4 text-slate-600 bg-slate-100 dark:bg-slate-700 border-slate-300 dark:border-slate-600 rounded focus:ring-slate-500">
|
||||||
|
<span class="text-sm text-slate-700 dark:text-slate-300">Activer les commandes d'avertissement</span>
|
||||||
</label>
|
</label>
|
||||||
|
<label class="flex items-center gap-3 cursor-pointer">
|
||||||
<label for="moderation_ban_enable">
|
<input type="checkbox" name="moderation_ban_enable" {% if configuration.getValue('moderation_ban_enable') %}checked{% endif %} class="w-4 h-4 text-slate-600 bg-slate-100 dark:bg-slate-700 border-slate-300 dark:border-slate-600 rounded focus:ring-slate-500">
|
||||||
<input type="checkbox" name="moderation_ban_enable" {% if configuration.getValue('moderation_ban_enable') %}checked="checked"{% endif %}>
|
<span class="text-sm text-slate-700 dark:text-slate-300">Activer les commandes de bannissement</span>
|
||||||
Activer les commandes de bannissement (!ban, !unban)
|
|
||||||
</label>
|
</label>
|
||||||
|
<label class="flex items-center gap-3 cursor-pointer">
|
||||||
<label for="moderation_kick_enable">
|
<input type="checkbox" name="moderation_kick_enable" {% if configuration.getValue('moderation_kick_enable') %}checked{% endif %} class="w-4 h-4 text-slate-600 bg-slate-100 dark:bg-slate-700 border-slate-300 dark:border-slate-600 rounded focus:ring-slate-500">
|
||||||
<input type="checkbox" name="moderation_kick_enable" {% if configuration.getValue('moderation_kick_enable') %}checked="checked"{% endif %}>
|
<span class="text-sm text-slate-700 dark:text-slate-300">Activer la commande d'expulsion</span>
|
||||||
Activer la commande d'expulsion (!kick)
|
|
||||||
</label>
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
<label for="moderation_log_channel_id">Canal de logs de modération</label>
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
|
||||||
<select name="moderation_log_channel_id">
|
<div>
|
||||||
|
<label for="moderation_log_channel_id" class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Canal de logs</label>
|
||||||
|
<select name="moderation_log_channel_id" id="moderation_log_channel_id" class="w-full px-3 py-2 bg-slate-50 dark:bg-slate-700 border border-slate-300 dark:border-slate-600 rounded-lg text-sm text-slate-900 dark:text-white focus:ring-2 focus:ring-slate-500 focus:border-transparent transition-all">
|
||||||
{% for channel in channels %}
|
{% for channel in channels %}
|
||||||
<option value="{{channel.id}}" {% if configuration.getIntValue('moderation_log_channel_id')==channel.id %}selected="selected"{% endif %}>
|
<option value="{{ channel.id }}" {% if configuration.getIntValue('moderation_log_channel_id') == channel.id %}selected{% endif %}>{{ channel.name }}</option>
|
||||||
{{channel.name}}
|
|
||||||
</option>
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
<small>Toutes les actions de modération seront notifiées dans ce canal</small>
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="moderation_embed_delete_delay" class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Délai suppression (sec)</label>
|
||||||
|
<input type="number" name="moderation_embed_delete_delay" id="moderation_embed_delete_delay" value="{{ configuration.getValue('moderation_embed_delete_delay') or '0' }}" min="0" class="w-full px-3 py-2 bg-slate-50 dark:bg-slate-700 border border-slate-300 dark:border-slate-600 rounded-lg text-sm text-slate-900 dark:text-white focus:ring-2 focus:ring-slate-500 focus:border-transparent transition-all">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<label>Rôles Staff autorisés</label>
|
<div>
|
||||||
|
<label class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-3">Rôles Staff autorisés</label>
|
||||||
{% set selected_roles = (configuration.getValue('moderation_staff_role_ids') or '').split(',') %}
|
{% set selected_roles = (configuration.getValue('moderation_staff_role_ids') or '').split(',') %}
|
||||||
|
|
||||||
{% if roles|length > 1 %}
|
{% if roles|length > 1 %}
|
||||||
<div class="tabs">
|
<div class="flex flex-wrap gap-2 mb-3">
|
||||||
{% for guild_data in roles %}
|
{% for guild_data in roles %}
|
||||||
<button type="button" class="tab-button" onclick="openTab(event, 'guild-{{guild_data.guild_id}}')" {% if loop.first %}id="defaultOpen"{% endif %}>
|
<button type="button" onclick="openTab(event, 'guild-{{ guild_data.guild_id }}')" class="tab-button px-3 py-1.5 text-sm rounded-lg bg-slate-100 dark:bg-slate-700 text-slate-700 dark:text-slate-300 hover:bg-slate-200 dark:hover:bg-slate-600 transition-colors {% if loop.first %}active bg-slate-200 dark:bg-slate-600{% endif %}">
|
||||||
{{ guild_data.guild_name }}
|
{{ guild_data.guild_name }}
|
||||||
</button>
|
</button>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@@ -114,127 +128,124 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% for guild_data in roles %}
|
{% for guild_data in roles %}
|
||||||
<div id="guild-{{guild_data.guild_id}}" class="tab-content" {% if not loop.first %}style="display: none;"{% endif %}>
|
<div id="guild-{{ guild_data.guild_id }}" class="tab-content {% if not loop.first %}hidden{% endif %}">
|
||||||
<div style="max-height: 300px; overflow-y: auto; border: 1px solid #ccc; padding: 10px; border-radius: 5px;">
|
<div class="max-h-48 overflow-y-auto bg-slate-50 dark:bg-slate-700/50 rounded-lg p-3 space-y-1">
|
||||||
{% for role in guild_data.roles %}
|
{% for role in guild_data.roles %}
|
||||||
<label style="display: block; margin: 5px 0;">
|
<label class="flex items-center gap-3 cursor-pointer p-2 rounded hover:bg-slate-100 dark:hover:bg-slate-600/50 transition-colors">
|
||||||
<input type="checkbox" name="moderation_staff_role_ids" value="{{role.id}}" {% if role.id|string in selected_roles %}checked="checked"{% endif %}>
|
<input type="checkbox" name="moderation_staff_role_ids" value="{{ role.id }}" {% if role.id|string in selected_roles %}checked{% endif %} class="w-4 h-4 text-slate-600 bg-slate-100 dark:bg-slate-700 border-slate-300 dark:border-slate-600 rounded focus:ring-slate-500">
|
||||||
{% if role.color.value != 0 %}
|
{% if role.color.value != 0 %}
|
||||||
<span style="color:#{{ '%06x' % role.color.value }}">●</span>
|
<span style="color:#{{ '%06x' % role.color.value }}">●</span>
|
||||||
{% else %}
|
{% else %}
|
||||||
<span>○</span>
|
<span class="text-slate-400">○</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{{role.name}}
|
<span class="text-sm text-slate-700 dark:text-slate-300">{{ role.name }}</span>
|
||||||
</label>
|
</label>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<small>Sélectionnez un ou plusieurs rôles qui peuvent utiliser les commandes de modération</small>
|
<div class="pt-4 border-t border-slate-200 dark:border-slate-700">
|
||||||
|
<button type="submit" class="px-4 py-2 bg-slate-800 hover:bg-slate-700 dark:bg-slate-700 dark:hover:bg-slate-600 text-white text-sm font-medium rounded-lg transition-colors">
|
||||||
|
Enregistrer
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
<script>
|
<div class="bg-white dark:bg-slate-800 rounded-lg border border-slate-200 dark:border-slate-700 mb-6 overflow-hidden">
|
||||||
function openTab(evt, tabName) {
|
<div class="px-5 py-4 border-b border-slate-200 dark:border-slate-700">
|
||||||
var i, tabcontent, tabbuttons;
|
<h2 class="text-lg font-medium text-slate-800 dark:text-white">API Twitch</h2>
|
||||||
tabcontent = document.getElementsByClassName("tab-content");
|
</div>
|
||||||
for (i = 0; i < tabcontent.length; i++) {
|
|
||||||
tabcontent[i].style.display = "none";
|
|
||||||
}
|
|
||||||
tabbuttons = document.getElementsByClassName("tab-button");
|
|
||||||
for (i = 0; i < tabbuttons.length; i++) {
|
|
||||||
tabbuttons[i].className = tabbuttons[i].className.replace(" active", "");
|
|
||||||
}
|
|
||||||
document.getElementById(tabName).style.display = "block";
|
|
||||||
evt.currentTarget.className += " active";
|
|
||||||
}
|
|
||||||
document.getElementById("defaultOpen")?.click();
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
<form action="{{ url_for('updateConfiguration') }}" method="POST" class="p-5 space-y-6">
|
||||||
.tabs {
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
overflow: hidden;
|
<div>
|
||||||
border-bottom: 2px solid #ccc;
|
<label for="twitch_client_id" class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Client ID</label>
|
||||||
margin-bottom: 10px;
|
<input type="text" name="twitch_client_id" id="twitch_client_id" value="{{ configuration.getValue('twitch_client_id') }}" class="w-full px-3 py-2 bg-slate-50 dark:bg-slate-700 border border-slate-300 dark:border-slate-600 rounded-lg text-sm text-slate-900 dark:text-white focus:ring-2 focus:ring-slate-500 focus:border-transparent transition-all">
|
||||||
}
|
</div>
|
||||||
.tab-button {
|
<div>
|
||||||
background-color: #f1f1f1;
|
<label for="twitch_client_secret" class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Client Secret</label>
|
||||||
border: none;
|
<input type="text" name="twitch_client_secret" id="twitch_client_secret" value="{{ configuration.getValue('twitch_client_secret') }}" class="w-full px-3 py-2 bg-slate-50 dark:bg-slate-700 border border-slate-300 dark:border-slate-600 rounded-lg text-sm text-slate-900 dark:text-white focus:ring-2 focus:ring-slate-500 focus:border-transparent transition-all">
|
||||||
outline: none;
|
</div>
|
||||||
cursor: pointer;
|
</div>
|
||||||
padding: 10px 20px;
|
|
||||||
transition: 0.3s;
|
|
||||||
font-size: 14px;
|
|
||||||
margin-right: 2px;
|
|
||||||
}
|
|
||||||
.tab-button:hover {
|
|
||||||
background-color: #ddd;
|
|
||||||
}
|
|
||||||
.tab-button.active {
|
|
||||||
background-color: #ccc;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
.tab-content {
|
|
||||||
animation: fadeEffect 0.3s;
|
|
||||||
}
|
|
||||||
@keyframes fadeEffect {
|
|
||||||
from {opacity: 0;}
|
|
||||||
to {opacity: 1;}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<label for="moderation_embed_delete_delay">Délai de suppression des embeds (en secondes)</label>
|
<div>
|
||||||
<input name="moderation_embed_delete_delay" type="number" value="{{ configuration.getValue('moderation_embed_delete_delay') or '0' }}" placeholder="0" min="0" />
|
<label for="twitch_channel" class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Chaîne à rejoindre</label>
|
||||||
<small>Mettre 0 pour ne pas supprimer automatiquement</small>
|
<input type="text" name="twitch_channel" id="twitch_channel" value="{{ configuration.getValue('twitch_channel') }}" placeholder="#machinTruc" class="w-full px-3 py-2 bg-slate-50 dark:bg-slate-700 border border-slate-300 dark:border-slate-600 rounded-lg text-sm text-slate-900 dark:text-white placeholder-slate-500 dark:placeholder-slate-400 focus:ring-2 focus:ring-slate-500 focus:border-transparent transition-all">
|
||||||
</fieldset>
|
</div>
|
||||||
|
|
||||||
<input type="Submit" value="Enregistrer la configuration Discord">
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<h2>API Twitch</h2>
|
|
||||||
<form action="{{ url_for('updateConfiguration') }}" method="POST">
|
|
||||||
<label for="twitch_client_id">Client ID</label>
|
|
||||||
<input name="twitch_client_id" type="text" value="{{ configuration.getValue('twitch_client_id') }}" />
|
|
||||||
<label for="twitch_client_secret">Client Secret</label>
|
|
||||||
<input name="twitch_client_secret" type="text" value="{{ configuration.getValue('twitch_client_secret') }}" />
|
|
||||||
<label for="twitch_channel">Chaîne à rejoindre</label>
|
|
||||||
<input name="twitch_channel" type="text" value="{{ configuration.getValue('twitch_channel') }}"
|
|
||||||
placeholder="#machinTruc" />
|
|
||||||
<input type="Submit" value="Enregistrer la configuration Twitch">
|
|
||||||
<p>
|
|
||||||
<a href="{{ url_for('twitchConfigurationHelp') }}">Aide</a>
|
|
||||||
</p>
|
|
||||||
{% if configuration.getValue('twitch_client_secret') and configuration.getValue('twitch_client_id') %}
|
{% if configuration.getValue('twitch_client_secret') and configuration.getValue('twitch_client_id') %}
|
||||||
<p>
|
<div>
|
||||||
<a href="{{ url_for('twitchRequestToken') }}">Obtenir token et refresh token</a>
|
<a href="{{ url_for('twitchRequestToken') }}" class="text-sm text-slate-600 dark:text-slate-400 hover:underline">
|
||||||
</p>
|
Obtenir token et refresh token
|
||||||
<label for="twitch_access_token">Access Token</label>
|
</a>
|
||||||
<input name="twitch_access_token" type="text" value="{{ configuration.getValue('twitch_access_token') }}"
|
</div>
|
||||||
readonly="readonly" />
|
|
||||||
<label for="twitch_refresh_token">Refresh Token</label>
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
<input name="twitch_refresh_token" type="text" value="{{ configuration.getValue('twitch_refresh_token') }}"
|
<div>
|
||||||
readonly="readonly" />
|
<label for="twitch_access_token" class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Access Token</label>
|
||||||
<p>Nécessite un redémarrage après l'obtention des Tokens.</p>
|
<input type="text" name="twitch_access_token" id="twitch_access_token" value="{{ configuration.getValue('twitch_access_token') }}" readonly class="w-full px-3 py-2 bg-slate-100 dark:bg-slate-700 border border-slate-300 dark:border-slate-600 rounded-lg text-sm text-slate-500 dark:text-slate-400 font-mono">
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="twitch_refresh_token" class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Refresh Token</label>
|
||||||
|
<input type="text" name="twitch_refresh_token" id="twitch_refresh_token" value="{{ configuration.getValue('twitch_refresh_token') }}" readonly class="w-full px-3 py-2 bg-slate-100 dark:bg-slate-700 border border-slate-300 dark:border-slate-600 rounded-lg text-sm text-slate-500 dark:text-slate-400 font-mono">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p class="text-xs text-amber-600 dark:text-amber-400">Nécessite un redémarrage après l'obtention des tokens</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</form>
|
|
||||||
|
|
||||||
<h2>Humble Bundle</h2>
|
<div class="flex items-center gap-4">
|
||||||
<form action="{{ url_for('updateConfiguration') }}" method="POST">
|
<button type="submit" class="px-4 py-2 bg-slate-800 hover:bg-slate-700 dark:bg-slate-700 dark:hover:bg-slate-600 text-white text-sm font-medium rounded-lg transition-colors">
|
||||||
<p>Humble Bundle propose régulièrement des bundles de jeux vidéo à des prix réduits. Activez les notifications pour recevoir automatiquement les nouveaux packs disponibles sur votre serveur Discord.</p>
|
Enregistrer
|
||||||
|
</button>
|
||||||
|
<a href="{{ url_for('twitchConfigurationHelp') }}" class="text-sm text-slate-600 dark:text-slate-400 hover:underline">Besoin d'aide ?</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
<label for="humble_bundle_enable">
|
<div class="bg-white dark:bg-slate-800 rounded-lg border border-slate-200 dark:border-slate-700 overflow-hidden">
|
||||||
<input type="checkbox" name="humble_bundle_enable" {% if configuration.getValue('humble_bundle_enable') %}checked="checked"{% endif %}>
|
<div class="px-5 py-4 border-b border-slate-200 dark:border-slate-700">
|
||||||
Activer les notifications Humble Bundle
|
<h2 class="text-lg font-medium text-slate-800 dark:text-white">Humble Bundle</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form action="{{ url_for('updateConfiguration') }}" method="POST" class="p-5 space-y-6">
|
||||||
|
<p class="text-sm text-slate-600 dark:text-slate-400">
|
||||||
|
Activez les notifications pour recevoir automatiquement les nouveaux packs sur Discord.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<label class="flex items-center gap-3 cursor-pointer">
|
||||||
|
<input type="checkbox" name="humble_bundle_enable" {% if configuration.getValue('humble_bundle_enable') %}checked{% endif %} class="w-4 h-4 text-slate-600 bg-slate-100 dark:bg-slate-700 border-slate-300 dark:border-slate-600 rounded focus:ring-slate-500">
|
||||||
|
<span class="text-sm text-slate-700 dark:text-slate-300">Activer les notifications Humble Bundle</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label for="humble_bundle_channel">Canal de notification</label>
|
<div>
|
||||||
<select name="humble_bundle_channel">
|
<label for="humble_bundle_channel" class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Canal de notification</label>
|
||||||
|
<select name="humble_bundle_channel" id="humble_bundle_channel" class="w-full px-3 py-2 bg-slate-50 dark:bg-slate-700 border border-slate-300 dark:border-slate-600 rounded-lg text-sm text-slate-900 dark:text-white focus:ring-2 focus:ring-slate-500 focus:border-transparent transition-all">
|
||||||
{% for channel in channels %}
|
{% for channel in channels %}
|
||||||
<option value="{{channel.id}}" {% if configuration.getIntValue('humble_bundle_channel')==channel.id %}selected="selected"{% endif %}>
|
<option value="{{ channel.id }}" {% if configuration.getIntValue('humble_bundle_channel') == channel.id %}selected{% endif %}>{{ channel.name }}</option>
|
||||||
{{channel.name}}
|
|
||||||
</option>
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
<input type="Submit" value="Enregistrer la configuration Humble Bundle">
|
<button type="submit" class="px-4 py-2 bg-slate-800 hover:bg-slate-700 dark:bg-slate-700 dark:hover:bg-slate-600 text-white text-sm font-medium rounded-lg transition-colors">
|
||||||
</form>
|
Enregistrer
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function openTab(evt, tabName) {
|
||||||
|
document.querySelectorAll('.tab-content').forEach(el => el.classList.add('hidden'));
|
||||||
|
document.querySelectorAll('.tab-button').forEach(el => {
|
||||||
|
el.classList.remove('active', 'bg-slate-200', 'dark:bg-slate-600');
|
||||||
|
el.classList.add('bg-slate-100', 'dark:bg-slate-700');
|
||||||
|
});
|
||||||
|
document.getElementById(tabName).classList.remove('hidden');
|
||||||
|
evt.currentTarget.classList.add('active', 'bg-slate-200', 'dark:bg-slate-600');
|
||||||
|
evt.currentTarget.classList.remove('bg-slate-100', 'dark:bg-slate-700');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -1,29 +1,44 @@
|
|||||||
{% extends "template.html" %}
|
{% extends "template.html" %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>Humeurs de Mamie</h1>
|
<div class="mb-6">
|
||||||
<p>Définissez les statuts Discord qui changeront automatiquement toutes les 10 minutes pour donner de la personnalité à votre bot.</p>
|
<h1 class="text-2xl font-semibold text-slate-800 dark:text-white mb-1">Humeurs</h1>
|
||||||
<table>
|
<p class="text-sm text-slate-600 dark:text-slate-400">
|
||||||
<thead>
|
Statuts Discord qui changeront automatiquement toutes les 10 minutes.
|
||||||
<tr>
|
</p>
|
||||||
<th>Texte</th>
|
</div>
|
||||||
<th>Action</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for humeur in humeurs %}
|
|
||||||
<tr>
|
|
||||||
<td>{{humeur.text}}</td>
|
|
||||||
<td><a href="{{ url_for('delHumeur', id = humeur.id) }}" onclick="return confirm('Êtes-vous sûr de vouloir supprimer cette humeur ?')">Supprimer</a></td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h2>Ajouter une humeur</h2>
|
<div class="bg-white dark:bg-slate-800 rounded-lg border border-slate-200 dark:border-slate-700 overflow-hidden mb-6">
|
||||||
<form action="{{ url_for('addHumeur') }}" method="POST">
|
{% if humeurs %}
|
||||||
<label for="text">Texte</label>
|
<ul class="divide-y divide-slate-200 dark:divide-slate-700">
|
||||||
<input name="text" type="text" />
|
{% for humeur in humeurs %}
|
||||||
<input type="Submit" value="Ajouter">
|
<li class="flex items-center justify-between px-4 py-3 hover:bg-slate-50 dark:hover:bg-slate-700/50 transition-colors group">
|
||||||
</form>
|
<span class="text-sm text-slate-700 dark:text-slate-300">{{ humeur.text }}</span>
|
||||||
|
<a href="{{ url_for('delHumeur', id = humeur.id) }}" onclick="return confirm('Êtes-vous sûr de vouloir supprimer cette humeur ?')" class="p-1.5 text-slate-400 hover:text-red-500 dark:hover:text-red-400 rounded opacity-0 group-hover:opacity-100 transition-all" title="Supprimer">
|
||||||
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"></path></svg>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% else %}
|
||||||
|
<div class="px-4 py-8 text-center">
|
||||||
|
<p class="text-sm text-slate-500 dark:text-slate-400">Aucune humeur configurée</p>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="bg-white dark:bg-slate-800 rounded-lg border border-slate-200 dark:border-slate-700 p-5">
|
||||||
|
<h2 class="text-lg font-medium text-slate-800 dark:text-white mb-4">Ajouter une humeur</h2>
|
||||||
|
|
||||||
|
<form action="{{ url_for('addHumeur') }}" method="POST">
|
||||||
|
<div class="flex flex-col sm:flex-row gap-3">
|
||||||
|
<div class="flex-1">
|
||||||
|
<input type="text" name="text" id="text" placeholder="Joue à un super jeu..." class="w-full px-3 py-2 bg-slate-50 dark:bg-slate-700 border border-slate-300 dark:border-slate-600 rounded-lg text-sm text-slate-900 dark:text-white placeholder-slate-500 dark:placeholder-slate-400 focus:ring-2 focus:ring-slate-500 focus:border-transparent transition-all">
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="px-4 py-2 bg-slate-800 hover:bg-slate-700 dark:bg-slate-700 dark:hover:bg-slate-600 text-white text-sm font-medium rounded-lg transition-colors whitespace-nowrap">
|
||||||
|
Ajouter
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -1,7 +1,117 @@
|
|||||||
{% extends "template.html" %}
|
{% extends "template.html" %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>Bienvenue sur l'interface d'administration de Mamie.</h1>
|
<div class="text-center py-10">
|
||||||
<p>Nous devons définir ce que nous souhaitons afficher sur la page d'accueil. Peut-être l'historique des dernières
|
<h1 class="text-3xl sm:text-4xl font-bold text-slate-800 dark:text-white mb-3">
|
||||||
modifications ? de la modération ?</p>
|
Panneau d'administration
|
||||||
|
</h1>
|
||||||
|
<p class="text-base text-slate-600 dark:text-slate-400 max-w-xl mx-auto">
|
||||||
|
Gérez les fonctionnalités de votre bot Discord et Twitch depuis cette interface.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 mb-10">
|
||||||
|
<a href="/live-alert" class="group bg-white dark:bg-slate-800 rounded-lg p-5 border border-slate-200 dark:border-slate-700 hover:border-slate-300 dark:hover:border-slate-600 hover:shadow-md transition-all">
|
||||||
|
<div class="flex items-center gap-4">
|
||||||
|
<div class="flex-shrink-0 w-10 h-10 rounded-lg bg-slate-100 dark:bg-slate-700 flex items-center justify-center">
|
||||||
|
<svg class="w-5 h-5 text-slate-600 dark:text-slate-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 10l4.553-2.276A1 1 0 0121 8.618v6.764a1 1 0 01-1.447.894L15 14M5 18h8a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z"></path></svg>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 class="font-medium text-slate-800 dark:text-white">Alertes Live</h3>
|
||||||
|
<p class="text-sm text-slate-500 dark:text-slate-400">Notifications Twitch</p>
|
||||||
|
</div>
|
||||||
|
<svg class="w-5 h-5 text-slate-400 ml-auto opacity-0 group-hover:opacity-100 transition-opacity" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path></svg>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="/commandes" class="group bg-white dark:bg-slate-800 rounded-lg p-5 border border-slate-200 dark:border-slate-700 hover:border-slate-300 dark:hover:border-slate-600 hover:shadow-md transition-all">
|
||||||
|
<div class="flex items-center gap-4">
|
||||||
|
<div class="flex-shrink-0 w-10 h-10 rounded-lg bg-slate-100 dark:bg-slate-700 flex items-center justify-center">
|
||||||
|
<svg class="w-5 h-5 text-slate-600 dark:text-slate-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"></path></svg>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 class="font-medium text-slate-800 dark:text-white">Commandes</h3>
|
||||||
|
<p class="text-sm text-slate-500 dark:text-slate-400">Commandes personnalisées</p>
|
||||||
|
</div>
|
||||||
|
<svg class="w-5 h-5 text-slate-400 ml-auto opacity-0 group-hover:opacity-100 transition-opacity" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path></svg>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="/humeurs" class="group bg-white dark:bg-slate-800 rounded-lg p-5 border border-slate-200 dark:border-slate-700 hover:border-slate-300 dark:hover:border-slate-600 hover:shadow-md transition-all">
|
||||||
|
<div class="flex items-center gap-4">
|
||||||
|
<div class="flex-shrink-0 w-10 h-10 rounded-lg bg-slate-100 dark:bg-slate-700 flex items-center justify-center">
|
||||||
|
<svg class="w-5 h-5 text-slate-600 dark:text-slate-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14.828 14.828a4 4 0 01-5.656 0M9 10h.01M15 10h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 class="font-medium text-slate-800 dark:text-white">Humeurs</h3>
|
||||||
|
<p class="text-sm text-slate-500 dark:text-slate-400">Statuts Discord rotatifs</p>
|
||||||
|
</div>
|
||||||
|
<svg class="w-5 h-5 text-slate-400 ml-auto opacity-0 group-hover:opacity-100 transition-opacity" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path></svg>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="/moderation" class="group bg-white dark:bg-slate-800 rounded-lg p-5 border border-slate-200 dark:border-slate-700 hover:border-slate-300 dark:hover:border-slate-600 hover:shadow-md transition-all">
|
||||||
|
<div class="flex items-center gap-4">
|
||||||
|
<div class="flex-shrink-0 w-10 h-10 rounded-lg bg-slate-100 dark:bg-slate-700 flex items-center justify-center">
|
||||||
|
<svg class="w-5 h-5 text-slate-600 dark:text-slate-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"></path></svg>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 class="font-medium text-slate-800 dark:text-white">Modération</h3>
|
||||||
|
<p class="text-sm text-slate-500 dark:text-slate-400">Historique et actions</p>
|
||||||
|
</div>
|
||||||
|
<svg class="w-5 h-5 text-slate-400 ml-auto opacity-0 group-hover:opacity-100 transition-opacity" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path></svg>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="/protondb" class="group bg-white dark:bg-slate-800 rounded-lg p-5 border border-slate-200 dark:border-slate-700 hover:border-slate-300 dark:hover:border-slate-600 hover:shadow-md transition-all">
|
||||||
|
<div class="flex items-center gap-4">
|
||||||
|
<div class="flex-shrink-0 w-10 h-10 rounded-lg bg-slate-100 dark:bg-slate-700 flex items-center justify-center">
|
||||||
|
<svg class="w-5 h-5 text-slate-600 dark:text-slate-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 4a2 2 0 114 0v1a1 1 0 001 1h3a1 1 0 011 1v3a1 1 0 01-1 1h-1a2 2 0 100 4h1a1 1 0 011 1v3a1 1 0 01-1 1h-3a1 1 0 01-1-1v-1a2 2 0 10-4 0v1a1 1 0 01-1 1H7a1 1 0 01-1-1v-3a1 1 0 00-1-1H4a2 2 0 110-4h1a1 1 0 001-1V7a1 1 0 011-1h3a1 1 0 001-1V4z"></path></svg>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 class="font-medium text-slate-800 dark:text-white">ProtonDB</h3>
|
||||||
|
<p class="text-sm text-slate-500 dark:text-slate-400">Compatibilité Linux</p>
|
||||||
|
</div>
|
||||||
|
<svg class="w-5 h-5 text-slate-400 ml-auto opacity-0 group-hover:opacity-100 transition-opacity" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path></svg>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="/configurations" class="group bg-white dark:bg-slate-800 rounded-lg p-5 border border-slate-200 dark:border-slate-700 hover:border-slate-300 dark:hover:border-slate-600 hover:shadow-md transition-all">
|
||||||
|
<div class="flex items-center gap-4">
|
||||||
|
<div class="flex-shrink-0 w-10 h-10 rounded-lg bg-slate-100 dark:bg-slate-700 flex items-center justify-center">
|
||||||
|
<svg class="w-5 h-5 text-slate-600 dark:text-slate-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"></path><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path></svg>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 class="font-medium text-slate-800 dark:text-white">Configurations</h3>
|
||||||
|
<p class="text-sm text-slate-500 dark:text-slate-400">Paramètres du bot</p>
|
||||||
|
</div>
|
||||||
|
<svg class="w-5 h-5 text-slate-400 ml-auto opacity-0 group-hover:opacity-100 transition-opacity" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path></svg>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="bg-white dark:bg-slate-800 rounded-lg p-6 border border-slate-200 dark:border-slate-700">
|
||||||
|
<div class="flex items-start gap-4">
|
||||||
|
<div class="flex-shrink-0 w-10 h-10 rounded-lg bg-slate-100 dark:bg-slate-700 flex items-center justify-center">
|
||||||
|
<svg class="w-5 h-5 text-slate-600 dark:text-slate-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 class="font-medium text-slate-800 dark:text-white mb-2">À propos</h3>
|
||||||
|
<p class="text-sm text-slate-600 dark:text-slate-400 mb-4">
|
||||||
|
Mamie Henriette est un bot open source pour Discord et Twitch, développé par la communauté.
|
||||||
|
Cette interface vous permet de configurer et gérer toutes les fonctionnalités.
|
||||||
|
</p>
|
||||||
|
<div class="flex flex-wrap gap-3">
|
||||||
|
<a href="https://github.com/skylanix/MamieHenriette" target="_blank" class="inline-flex items-center gap-2 px-3 py-1.5 bg-slate-800 dark:bg-slate-700 text-white rounded text-sm hover:bg-slate-700 dark:hover:bg-slate-600 transition-colors">
|
||||||
|
<svg class="w-4 h-4" fill="currentColor" viewBox="0 0 24 24"><path fill-rule="evenodd" d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z" clip-rule="evenodd"></path></svg>
|
||||||
|
GitHub
|
||||||
|
</a>
|
||||||
|
<a href="https://discord.com/invite/UwAPqMJnx3" target="_blank" class="inline-flex items-center gap-2 px-3 py-1.5 bg-slate-100 dark:bg-slate-700 text-slate-700 dark:text-slate-300 border border-slate-200 dark:border-slate-600 rounded text-sm hover:bg-slate-200 dark:hover:bg-slate-600 transition-colors">
|
||||||
|
<svg class="w-4 h-4" fill="currentColor" viewBox="0 0 24 24"><path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028 14.09 14.09 0 0 0 1.226-1.994.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.946 2.418-2.157 2.418z"></path></svg>
|
||||||
|
Discord
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -1,76 +1,135 @@
|
|||||||
{% extends "template.html" %}
|
{% extends "template.html" %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>Alerte Live</h1>
|
<div class="mb-6">
|
||||||
|
<h1 class="text-2xl font-semibold text-slate-800 dark:text-white mb-1">Alertes Live</h1>
|
||||||
<p>
|
<p class="text-sm text-slate-600 dark:text-slate-400">
|
||||||
Liste des chaines surveillées pour les alertes de live twitch.
|
Chaînes Twitch surveillées. Vérification toutes les 5 minutes, maximum 100 chaînes.
|
||||||
|
</p>
|
||||||
Le bot vérifie toutes les 5 minutes qui est en live dans la liste en dessous.
|
</div>
|
||||||
Le bot enregistre le status de stream toutes les 5 minutes, quand le status pass de "hors-ligne" à "en ligne" alors
|
|
||||||
le bot le notifiera sur discord.
|
|
||||||
Ne peu surveiller qu'au maximum 100 chaines.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
{% if not alert %}
|
{% if not alert %}
|
||||||
<h2>Alertes</h2>
|
<div class="bg-white dark:bg-slate-800 rounded-lg border border-slate-200 dark:border-slate-700 overflow-hidden mb-6">
|
||||||
<table class="live-alert">
|
<div class="px-5 py-4 border-b border-slate-200 dark:border-slate-700">
|
||||||
|
<h2 class="text-lg font-medium text-slate-800 dark:text-white">Alertes configurées</h2>
|
||||||
|
</div>
|
||||||
|
<div class="overflow-x-auto">
|
||||||
|
<table class="w-full">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr class="bg-slate-50 dark:bg-slate-700/50 border-b border-slate-200 dark:border-slate-700">
|
||||||
<th>Chaine</th>
|
<th class="px-4 py-3 text-left text-xs font-medium text-slate-500 dark:text-slate-400 uppercase">Chaîne</th>
|
||||||
<th>Canal</th>
|
<th class="px-4 py-3 text-left text-xs font-medium text-slate-500 dark:text-slate-400 uppercase">Canal Discord</th>
|
||||||
<th>Message</th>
|
<th class="px-4 py-3 text-left text-xs font-medium text-slate-500 dark:text-slate-400 uppercase">Message</th>
|
||||||
<th>#</th>
|
<th class="px-4 py-3 text-right text-xs font-medium text-slate-500 dark:text-slate-400 uppercase">Actions</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody class="divide-y divide-slate-200 dark:divide-slate-700">
|
||||||
{% for alert in alerts %}
|
{% for alert in alerts %}
|
||||||
|
<tr class="hover:bg-slate-50 dark:hover:bg-slate-700/30 transition-colors">
|
||||||
|
<td class="px-4 py-3">
|
||||||
|
<a href="https://www.twitch.tv/{{ alert.login }}" target="_blank" class="text-sm font-medium text-slate-700 dark:text-slate-300 hover:underline">{{ alert.login }}</a>
|
||||||
|
</td>
|
||||||
|
<td class="px-4 py-3">
|
||||||
|
<span class="text-sm text-slate-600 dark:text-slate-400">#{{ alert.notify_channel_name }}</span>
|
||||||
|
</td>
|
||||||
|
<td class="px-4 py-3 text-sm text-slate-600 dark:text-slate-400 max-w-xs">
|
||||||
|
<div class="line-clamp-2">{{ alert.message }}</div>
|
||||||
|
</td>
|
||||||
|
<td class="px-4 py-3">
|
||||||
|
<div class="flex items-center justify-end gap-2">
|
||||||
|
<a href="{{ url_for('toggleLiveAlert', id = alert.id) }}" class="text-sm text-slate-500 hover:text-slate-700 dark:hover:text-slate-300 transition-colors" title="{{ 'Désactiver' if alert.enable else 'Activer' }}">
|
||||||
|
{% if alert.enable %}
|
||||||
|
<span class="text-green-600 dark:text-green-500">Actif</span>
|
||||||
|
{% else %}
|
||||||
|
<span class="text-slate-400">Inactif</span>
|
||||||
|
{% endif %}
|
||||||
|
</a>
|
||||||
|
<a href="{{ url_for('openEditLiveAlert', id = alert.id) }}" class="text-sm text-slate-500 hover:text-slate-700 dark:hover:text-slate-300 transition-colors">
|
||||||
|
Modifier
|
||||||
|
</a>
|
||||||
|
<a href="{{ url_for('delLiveAlert', id = alert.id) }}" onclick="return confirm('Êtes-vous sûr de vouloir supprimer cette alerte ?')" class="text-sm text-slate-500 hover:text-red-600 dark:hover:text-red-400 transition-colors">
|
||||||
|
Supprimer
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% else %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{alert.login}}</td>
|
<td colspan="4" class="px-4 py-8 text-center text-sm text-slate-500 dark:text-slate-400">
|
||||||
<td>{{alert.notify_channel_name}}</td>
|
Aucune alerte configurée
|
||||||
<td>{{alert.message}}</td>
|
|
||||||
<td>
|
|
||||||
<a href="{{ url_for('toggleLiveAlert', id = alert.id) }}" class="icon">{{ '✅' if alert.enable else '❌' }}</a>
|
|
||||||
<a href="{{ url_for('openEditLiveAlert', id = alert.id) }}" class="icon">✐</a>
|
|
||||||
<a href="{{ url_for('delLiveAlert', id = alert.id) }}"
|
|
||||||
onclick="return confirm('Êtes-vous sûr de vouloir supprimer cette alerte ?')" class="icon">🗑</a>
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<h2>{{ 'Editer une alerte' if alert else 'Ajouter une alerte de Live' }}</h2>
|
<div class="bg-white dark:bg-slate-800 rounded-lg border border-slate-200 dark:border-slate-700 p-5">
|
||||||
<form action="{{ url_for('submitEditLiveAlert', id = alert.id) if alert else url_for('addLiveAlert') }}" method="POST">
|
<h2 class="text-lg font-medium text-slate-800 dark:text-white mb-5">
|
||||||
<label for="login">Chaine</label>
|
{% if alert %}Modifier l'alerte{% else %}Ajouter une alerte{% endif %}
|
||||||
<input name="login" type="text" maxlength="32" required="required" value="{{alert.login if alert}}"/>
|
</h2>
|
||||||
<label for="notify_channel">Canal de Notification</label>
|
|
||||||
<select name="notify_channel">
|
<form action="{{ url_for('submitEditLiveAlert', id = alert.id) if alert else url_for('addLiveAlert') }}" method="POST" class="space-y-6">
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||||
|
<div>
|
||||||
|
<label for="login" class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Chaîne Twitch</label>
|
||||||
|
<input type="text" name="login" id="login" maxlength="32" required value="{{ alert.login if alert else '' }}" placeholder="chainesteve" class="w-full px-3 py-2 bg-slate-50 dark:bg-slate-700 border border-slate-300 dark:border-slate-600 rounded-lg text-sm text-slate-900 dark:text-white placeholder-slate-500 dark:placeholder-slate-400 focus:ring-2 focus:ring-slate-500 focus:border-transparent transition-all">
|
||||||
|
<p class="mt-1 text-xs text-slate-500 dark:text-slate-400">Le login de la chaîne, ex: chainesteve</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label for="notify_channel" class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Canal de Notification</label>
|
||||||
|
<select name="notify_channel" id="notify_channel" class="w-full px-3 py-2 bg-slate-50 dark:bg-slate-700 border border-slate-300 dark:border-slate-600 rounded-lg text-sm text-slate-900 dark:text-white focus:ring-2 focus:ring-slate-500 focus:border-transparent transition-all">
|
||||||
{% for channel in channels %}
|
{% for channel in channels %}
|
||||||
<option value="{{channel.id}}"{% if alert and alert.notify_channel == channel.id %}
|
<option value="{{ channel.id }}" {% if alert and alert.notify_channel == channel.id %}selected{% endif %}>{{ channel.name }}</option>
|
||||||
selected="selected" {% endif %}>{{channel.name}}</option>
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
<label for="message">Message</label>
|
</div>
|
||||||
<textarea name="message" rows="5" cols="50" required="required">{{alert.message if alert}}</textarea>
|
</div>
|
||||||
<input type="Submit" value="Ajouter">
|
|
||||||
<p>
|
|
||||||
La chaine est le login de la chaine, par exemple <strong>chainesteve</strong> pour <strong>https://www.twitch.tv/chainesteve</strong>.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Pour le message vous avez acces à ces variables :
|
|
||||||
<ul>
|
|
||||||
<li>{0.user_login} : pour le lien vers la chaine</li>
|
|
||||||
<li>{0.user_name} : à priviligier pour le text</li>
|
|
||||||
<li>{0.game_name}</li>
|
|
||||||
<li>{0.title}</li>
|
|
||||||
<li>{0.language}</li>
|
|
||||||
</ul>
|
|
||||||
Le message est au format <a href="https://commonmark.org/" target="_blank">common-mark</a> dans la limite de ce que
|
|
||||||
support discord.
|
|
||||||
Pour mettre un lien vers la chaine : [description](https://www.twitch.tv/{0.user_login})
|
|
||||||
</p>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label for="message" class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Message de notification</label>
|
||||||
|
<textarea name="message" id="message" rows="4" required placeholder="🔴 **{0.user_name}** est en live !" class="w-full px-3 py-2 bg-slate-50 dark:bg-slate-700 border border-slate-300 dark:border-slate-600 rounded-lg text-sm text-slate-900 dark:text-white placeholder-slate-500 dark:placeholder-slate-400 focus:ring-2 focus:ring-slate-500 focus:border-transparent transition-all resize-none">{{ alert.message if alert else '' }}</textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="bg-slate-50 dark:bg-slate-700/50 rounded-lg p-4">
|
||||||
|
<p class="text-sm font-medium text-slate-700 dark:text-slate-300 mb-3">Variables disponibles :</p>
|
||||||
|
<div class="grid grid-cols-1 sm:grid-cols-2 gap-2 text-sm">
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<code class="px-2 py-0.5 bg-slate-200 dark:bg-slate-600 rounded text-xs font-mono">{0.user_login}</code>
|
||||||
|
<span class="text-slate-600 dark:text-slate-400">Lien vers la chaîne</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<code class="px-2 py-0.5 bg-slate-200 dark:bg-slate-600 rounded text-xs font-mono">{0.user_name}</code>
|
||||||
|
<span class="text-slate-600 dark:text-slate-400">Nom du streamer</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<code class="px-2 py-0.5 bg-slate-200 dark:bg-slate-600 rounded text-xs font-mono">{0.game_name}</code>
|
||||||
|
<span class="text-slate-600 dark:text-slate-400">Jeu en cours</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<code class="px-2 py-0.5 bg-slate-200 dark:bg-slate-600 rounded text-xs font-mono">{0.title}</code>
|
||||||
|
<span class="text-slate-600 dark:text-slate-400">Titre du stream</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<code class="px-2 py-0.5 bg-slate-200 dark:bg-slate-600 rounded text-xs font-mono">{0.language}</code>
|
||||||
|
<span class="text-slate-600 dark:text-slate-400">Langue du stream</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex items-center justify-end gap-3">
|
||||||
|
{% if alert %}
|
||||||
|
<a href="{{ url_for('openLiveAlert') }}" class="px-4 py-2 text-slate-700 dark:text-slate-300 text-sm font-medium rounded-lg hover:bg-slate-100 dark:hover:bg-slate-700 transition-colors">
|
||||||
|
Annuler
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
<button type="submit" class="px-4 py-2 bg-slate-800 hover:bg-slate-700 dark:bg-slate-700 dark:hover:bg-slate-600 text-white text-sm font-medium rounded-lg transition-colors">
|
||||||
|
{% if alert %}Enregistrer{% else %}Ajouter{% endif %}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -1,110 +1,168 @@
|
|||||||
{% extends "template.html" %}
|
{% extends "template.html" %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>Modération Discord</h1>
|
<div class="mb-6">
|
||||||
|
<h1 class="text-2xl font-semibold text-slate-800 dark:text-white mb-1">Modération</h1>
|
||||||
|
<p class="text-sm text-slate-600 dark:text-slate-400">
|
||||||
|
Historique des actions de modération sur le serveur Discord.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<p>
|
<div class="bg-white dark:bg-slate-800 rounded-lg border border-slate-200 dark:border-slate-700 overflow-hidden mb-6">
|
||||||
Historique des actions de modération effectuées sur le serveur Discord.
|
<details class="group">
|
||||||
|
<summary class="flex items-center justify-between px-5 py-4 cursor-pointer hover:bg-slate-50 dark:hover:bg-slate-700/30 transition-colors">
|
||||||
Le bot enregistre automatiquement les avertissements, exclusions et bannissements.
|
<span class="font-medium text-slate-800 dark:text-white">Commandes de modération disponibles</span>
|
||||||
|
<svg class="w-5 h-5 text-slate-400 group-open:rotate-180 transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path></svg>
|
||||||
<table>
|
</summary>
|
||||||
<thead>
|
<div class="border-t border-slate-200 dark:border-slate-700">
|
||||||
<tr>
|
<div class="divide-y divide-slate-200 dark:divide-slate-700 text-sm">
|
||||||
<th>Commande</th>
|
<div class="px-5 py-3 flex flex-col sm:flex-row sm:items-start gap-1 sm:gap-4">
|
||||||
<th>Description</th>
|
<code class="text-slate-700 dark:text-slate-300 font-mono">!averto @user raison</code>
|
||||||
</tr>
|
<span class="text-slate-500 dark:text-slate-400">Avertit un utilisateur</span>
|
||||||
</thead>
|
</div>
|
||||||
<tbody>
|
<div class="px-5 py-3 flex flex-col sm:flex-row sm:items-start gap-1 sm:gap-4">
|
||||||
<tr>
|
<code class="text-slate-700 dark:text-slate-300 font-mono">!delaverto id</code>
|
||||||
<td><strong>!averto @utilisateur raison</strong><br><small>Alias : !warn, !av, !avertissement</small></td>
|
<span class="text-slate-500 dark:text-slate-400">Retire un avertissement</span>
|
||||||
<td>Avertit un utilisateur et enregistre l'avertissement dans la base de données</td>
|
</div>
|
||||||
</tr>
|
<div class="px-5 py-3 flex flex-col sm:flex-row sm:items-start gap-1 sm:gap-4">
|
||||||
<tr>
|
<code class="text-slate-700 dark:text-slate-300 font-mono">!warnings [@user]</code>
|
||||||
<td><strong>!delaverto id</strong><br><small>Alias : !removewarn, !delwarn</small></td>
|
<span class="text-slate-500 dark:text-slate-400">Liste les événements de modération</span>
|
||||||
<td>Retire un avertissement en utilisant son numéro d'ID</td>
|
</div>
|
||||||
</tr>
|
<div class="px-5 py-3 flex flex-col sm:flex-row sm:items-start gap-1 sm:gap-4">
|
||||||
<tr>
|
<code class="text-slate-700 dark:text-slate-300 font-mono">!inspect @user</code>
|
||||||
<td><strong>!warnings</strong> ou <strong>!warnings @utilisateur</strong><br><small>Alias : !listevent, !listwarn</small></td>
|
<span class="text-slate-500 dark:text-slate-400">Informations sur un utilisateur</span>
|
||||||
<td>Affiche la liste des événements de modération (tous ou pour un utilisateur spécifique)</td>
|
</div>
|
||||||
</tr>
|
<div class="px-5 py-3 flex flex-col sm:flex-row sm:items-start gap-1 sm:gap-4">
|
||||||
<tr>
|
<code class="text-slate-700 dark:text-slate-300 font-mono">!kick @user raison</code>
|
||||||
<td><strong>!inspect @utilisateur</strong> ou <strong>!inspect id</strong></td>
|
<span class="text-slate-500 dark:text-slate-400">Expulse un utilisateur</span>
|
||||||
<td>Affiche des informations détaillées sur un utilisateur : création du compte, date d'arrivée, historique de modération</td>
|
</div>
|
||||||
</tr>
|
<div class="px-5 py-3 flex flex-col sm:flex-row sm:items-start gap-1 sm:gap-4">
|
||||||
<tr>
|
<code class="text-slate-700 dark:text-slate-300 font-mono">!ban @user raison</code>
|
||||||
<td><strong>!kick @utilisateur raison</strong></td>
|
<span class="text-slate-500 dark:text-slate-400">Bannit un utilisateur</span>
|
||||||
<td>Expulse un utilisateur du serveur</td>
|
</div>
|
||||||
</tr>
|
<div class="px-5 py-3 flex flex-col sm:flex-row sm:items-start gap-1 sm:gap-4">
|
||||||
<tr>
|
<code class="text-slate-700 dark:text-slate-300 font-mono">!unban id</code>
|
||||||
<td><strong>!ban @utilisateur raison</strong></td>
|
<span class="text-slate-500 dark:text-slate-400">Révoque un bannissement</span>
|
||||||
<td>Bannit définitivement un utilisateur du serveur</td>
|
</div>
|
||||||
</tr>
|
<div class="px-5 py-3 flex flex-col sm:flex-row sm:items-start gap-1 sm:gap-4">
|
||||||
<tr>
|
<code class="text-slate-700 dark:text-slate-300 font-mono">!banlist</code>
|
||||||
<td><strong>!unban discord_id</strong> ou <strong>!unban #sanction_id raison</strong></td>
|
<span class="text-slate-500 dark:text-slate-400">Liste des utilisateurs bannis</span>
|
||||||
<td>Révoque le bannissement d'un utilisateur et lui envoie une invitation</td>
|
</div>
|
||||||
</tr>
|
</div>
|
||||||
<tr>
|
</div>
|
||||||
<td><strong>!banlist</strong></td>
|
</details>
|
||||||
<td>Affiche la liste des utilisateurs actuellement bannis du serveur</td>
|
</div>
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><strong>!aide</strong><br><small>Alias : !help</small></td>
|
|
||||||
<td>Affiche l'aide avec toutes les commandes disponibles</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
{% if not event %}
|
{% if not event %}
|
||||||
<h2>Événements de modération</h2>
|
<div class="bg-white dark:bg-slate-800 rounded-lg border border-slate-200 dark:border-slate-700 overflow-hidden mb-6">
|
||||||
<table class="moderation">
|
<div class="px-5 py-4 border-b border-slate-200 dark:border-slate-700">
|
||||||
|
<h2 class="text-lg font-medium text-slate-800 dark:text-white">Événements de modération</h2>
|
||||||
|
</div>
|
||||||
|
<div class="overflow-x-auto">
|
||||||
|
<table class="w-full">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr class="bg-slate-50 dark:bg-slate-700/50 border-b border-slate-200 dark:border-slate-700">
|
||||||
<th>Type</th>
|
<th class="px-4 py-3 text-left text-xs font-medium text-slate-500 dark:text-slate-400 uppercase">Type</th>
|
||||||
<th>Utilisateur</th>
|
<th class="px-4 py-3 text-left text-xs font-medium text-slate-500 dark:text-slate-400 uppercase">Utilisateur</th>
|
||||||
<th>Discord ID</th>
|
<th class="px-4 py-3 text-left text-xs font-medium text-slate-500 dark:text-slate-400 uppercase">Date</th>
|
||||||
<th>Date & Heure</th>
|
<th class="px-4 py-3 text-left text-xs font-medium text-slate-500 dark:text-slate-400 uppercase">Raison</th>
|
||||||
<th>Raison</th>
|
<th class="px-4 py-3 text-left text-xs font-medium text-slate-500 dark:text-slate-400 uppercase">Staff</th>
|
||||||
<th>Staff</th>
|
<th class="px-4 py-3 text-right text-xs font-medium text-slate-500 dark:text-slate-400 uppercase">Actions</th>
|
||||||
<th>#</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody class="divide-y divide-slate-200 dark:divide-slate-700">
|
||||||
{% for mod_event in events %}
|
{% for mod_event in events %}
|
||||||
|
<tr class="hover:bg-slate-50 dark:hover:bg-slate-700/30 transition-colors">
|
||||||
|
<td class="px-4 py-3">
|
||||||
|
{% if mod_event.type == 'ban' %}
|
||||||
|
<span class="text-xs font-medium text-red-600 dark:text-red-400">Ban</span>
|
||||||
|
{% elif mod_event.type == 'kick' %}
|
||||||
|
<span class="text-xs font-medium text-orange-600 dark:text-orange-400">Kick</span>
|
||||||
|
{% elif mod_event.type == 'warn' or mod_event.type == 'warning' %}
|
||||||
|
<span class="text-xs font-medium text-yellow-600 dark:text-yellow-400">Warn</span>
|
||||||
|
{% elif mod_event.type == 'unban' %}
|
||||||
|
<span class="text-xs font-medium text-green-600 dark:text-green-400">Unban</span>
|
||||||
|
{% else %}
|
||||||
|
<span class="text-xs font-medium text-slate-600 dark:text-slate-400">{{ mod_event.type }}</span>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td class="px-4 py-3">
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<span class="text-sm font-medium text-slate-800 dark:text-white">{{ mod_event.username }}</span>
|
||||||
|
<span class="text-xs text-slate-500 dark:text-slate-400 font-mono">{{ mod_event.discord_id }}</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td class="px-4 py-3 text-sm text-slate-600 dark:text-slate-400 whitespace-nowrap">
|
||||||
|
{{ mod_event.created_at.strftime('%d/%m/%Y %H:%M') if mod_event.created_at else 'N/A' }}
|
||||||
|
</td>
|
||||||
|
<td class="px-4 py-3 text-sm text-slate-600 dark:text-slate-400 max-w-xs">
|
||||||
|
<div class="line-clamp-2">{{ mod_event.reason }}</div>
|
||||||
|
</td>
|
||||||
|
<td class="px-4 py-3 text-sm text-slate-600 dark:text-slate-400">
|
||||||
|
{{ mod_event.staff_name }}
|
||||||
|
</td>
|
||||||
|
<td class="px-4 py-3">
|
||||||
|
<div class="flex items-center justify-end gap-2">
|
||||||
|
<a href="{{ url_for('open_edit_moderation_event', event_id = mod_event.id) }}" class="text-sm text-slate-500 hover:text-slate-700 dark:hover:text-slate-300 transition-colors">
|
||||||
|
Modifier
|
||||||
|
</a>
|
||||||
|
<a href="{{ url_for('delete_moderation_event', event_id = mod_event.id) }}" onclick="return confirm('Êtes-vous sûr de vouloir supprimer cet événement ?')" class="text-sm text-slate-500 hover:text-red-600 dark:hover:text-red-400 transition-colors">
|
||||||
|
Supprimer
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% else %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ mod_event.type }}</td>
|
<td colspan="6" class="px-4 py-8 text-center text-sm text-slate-500 dark:text-slate-400">
|
||||||
<td>{{ mod_event.username }}</td>
|
Aucun événement de modération
|
||||||
<td>{{ mod_event.discord_id }}</td>
|
|
||||||
<td>{{ mod_event.created_at.strftime('%d/%m/%Y %H:%M') if mod_event.created_at else 'N/A' }}</td>
|
|
||||||
<td>{{ mod_event.reason }}</td>
|
|
||||||
<td>{{ mod_event.staff_name }}</td>
|
|
||||||
<td>
|
|
||||||
<a href="{{ url_for('open_edit_moderation_event', event_id = mod_event.id) }}" class="icon">✐</a>
|
|
||||||
<a href="{{ url_for('delete_moderation_event', event_id = mod_event.id) }}" onclick="return confirm('Êtes-vous sûr de vouloir supprimer cet événement ?')" class="icon">🗑</a>
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if event %}
|
{% if event %}
|
||||||
<h2>Editer un événement</h2>
|
<div class="bg-white dark:bg-slate-800 rounded-lg border border-slate-200 dark:border-slate-700 p-5">
|
||||||
<form action="{{ url_for('update_moderation_event', event_id = event.id) }}" method="POST">
|
<h2 class="text-lg font-medium text-slate-800 dark:text-white mb-5">Modifier l'événement</h2>
|
||||||
<label for="type">Type</label>
|
|
||||||
<input name="type" type="text" value="{{ event.type }}" disabled />
|
|
||||||
<label for="username">Utilisateur</label>
|
|
||||||
<input name="username" type="text" value="{{ event.username }}" disabled />
|
|
||||||
<label for="discord_id">Discord ID</label>
|
|
||||||
<input name="discord_id" type="text" value="{{ event.discord_id }}" disabled />
|
|
||||||
<label for="reason">Raison</label>
|
|
||||||
<input name="reason" type="text" value="{{ event.reason }}" required="required" />
|
|
||||||
<label for="staff_name">Staff</label>
|
|
||||||
<input name="staff_name" type="text" value="{{ event.staff_name }}" disabled />
|
|
||||||
<input type="Submit" value="Modifier">
|
|
||||||
<a href="{{ url_for('moderation') }}">Annuler</a>
|
|
||||||
</form>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
|
<form action="{{ url_for('update_moderation_event', event_id = event.id) }}" method="POST" class="space-y-6">
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||||
|
<div>
|
||||||
|
<label class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Type</label>
|
||||||
|
<input type="text" value="{{ event.type }}" disabled class="w-full px-3 py-2 bg-slate-100 dark:bg-slate-700 border border-slate-300 dark:border-slate-600 rounded-lg text-sm text-slate-500 dark:text-slate-400 cursor-not-allowed">
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Staff</label>
|
||||||
|
<input type="text" value="{{ event.staff_name }}" disabled class="w-full px-3 py-2 bg-slate-100 dark:bg-slate-700 border border-slate-300 dark:border-slate-600 rounded-lg text-sm text-slate-500 dark:text-slate-400 cursor-not-allowed">
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Utilisateur</label>
|
||||||
|
<input type="text" value="{{ event.username }}" disabled class="w-full px-3 py-2 bg-slate-100 dark:bg-slate-700 border border-slate-300 dark:border-slate-600 rounded-lg text-sm text-slate-500 dark:text-slate-400 cursor-not-allowed">
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Discord ID</label>
|
||||||
|
<input type="text" value="{{ event.discord_id }}" disabled class="w-full px-3 py-2 bg-slate-100 dark:bg-slate-700 border border-slate-300 dark:border-slate-600 rounded-lg text-sm text-slate-500 dark:text-slate-400 cursor-not-allowed font-mono">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label for="reason" class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Raison</label>
|
||||||
|
<input type="text" name="reason" id="reason" value="{{ event.reason }}" required class="w-full px-3 py-2 bg-slate-50 dark:bg-slate-700 border border-slate-300 dark:border-slate-600 rounded-lg text-sm text-slate-900 dark:text-white focus:ring-2 focus:ring-slate-500 focus:border-transparent transition-all">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex items-center justify-end gap-3">
|
||||||
|
<a href="{{ url_for('moderation') }}" class="px-4 py-2 text-slate-700 dark:text-slate-300 text-sm font-medium rounded-lg hover:bg-slate-100 dark:hover:bg-slate-700 transition-colors">
|
||||||
|
Annuler
|
||||||
|
</a>
|
||||||
|
<button type="submit" class="px-4 py-2 bg-slate-800 hover:bg-slate-700 dark:bg-slate-700 dark:hover:bg-slate-600 text-white text-sm font-medium rounded-lg transition-colors">
|
||||||
|
Enregistrer
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -1,61 +1,124 @@
|
|||||||
{% extends "template.html" %}
|
{% extends "template.html" %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>Proton DB</h1>
|
<div class="mb-6">
|
||||||
<p>ProtonDB évalue la compatibilité des jeux Windows sur Linux via Steam Play.</p>
|
<h1 class="text-2xl font-semibold text-slate-800 dark:text-white mb-1">ProtonDB</h1>
|
||||||
|
<p class="text-sm text-slate-600 dark:text-slate-400">
|
||||||
|
Compatibilité des jeux Windows sur Linux via Steam Play.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
{% if configuration.getValue('proton_db_enable_enable') %}
|
{% if configuration.getValue('proton_db_enable_enable') %}
|
||||||
<h2>Game alias</h2>
|
<div class="bg-white dark:bg-slate-800 rounded-lg border border-slate-200 dark:border-slate-700 overflow-hidden mb-6">
|
||||||
<table>
|
<div class="px-5 py-4 border-b border-slate-200 dark:border-slate-700">
|
||||||
|
<h2 class="text-lg font-medium text-slate-800 dark:text-white">Alias de jeux</h2>
|
||||||
|
</div>
|
||||||
|
<div class="overflow-x-auto">
|
||||||
|
<table class="w-full">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr class="bg-slate-50 dark:bg-slate-700/50 border-b border-slate-200 dark:border-slate-700">
|
||||||
<th>Alias</th>
|
<th class="px-4 py-3 text-left text-xs font-medium text-slate-500 dark:text-slate-400 uppercase">Alias</th>
|
||||||
<th>Game</th>
|
<th class="px-4 py-3 text-left text-xs font-medium text-slate-500 dark:text-slate-400 uppercase">Nom du jeu</th>
|
||||||
<th>#</th>
|
<th class="px-4 py-3 text-right text-xs font-medium text-slate-500 dark:text-slate-400 uppercase">Actions</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody class="divide-y divide-slate-200 dark:divide-slate-700">
|
||||||
{% for a in aliases %}
|
{% for a in aliases %}
|
||||||
|
<tr class="hover:bg-slate-50 dark:hover:bg-slate-700/30 transition-colors">
|
||||||
|
<td class="px-4 py-3">
|
||||||
|
<code class="px-1.5 py-0.5 bg-slate-100 dark:bg-slate-700 text-slate-700 dark:text-slate-300 rounded text-xs font-mono">{{ a.alias }}</code>
|
||||||
|
</td>
|
||||||
|
<td class="px-4 py-3 text-sm text-slate-600 dark:text-slate-400">
|
||||||
|
{{ a.name }}
|
||||||
|
</td>
|
||||||
|
<td class="px-4 py-3 text-right">
|
||||||
|
<a href="{{ url_for('delGameAlias', id = a.id) }}" onclick="return confirm('Êtes-vous sûr de vouloir supprimer cet alias ?')" class="text-sm text-slate-500 hover:text-red-600 dark:hover:text-red-400 transition-colors">
|
||||||
|
Supprimer
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% else %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{a.alias}}</td>
|
<td colspan="3" class="px-4 py-8 text-center text-sm text-slate-500 dark:text-slate-400">
|
||||||
<td>{{a.name}}</td>
|
Aucun alias configuré
|
||||||
<td><a href="{{ url_for('delGameAlias', id = a.id) }}"
|
</td>
|
||||||
onclick="return confirm('Êtes-vous sûr de vouloir supprimer cet alias ?')">Supprimer</a></td>
|
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<h2>Ajouter un Alias</h2>
|
<div class="bg-white dark:bg-slate-800 rounded-lg border border-slate-200 dark:border-slate-700 p-5 mb-6">
|
||||||
<form action="{{ url_for('addGameAlias') }}" method="POST">
|
<h2 class="text-lg font-medium text-slate-800 dark:text-white mb-5">Ajouter un alias</h2>
|
||||||
<label for="alias">Alias</label>
|
|
||||||
<input name="alias" type="text" maxlength="32" required="required" />
|
<form action="{{ url_for('addGameAlias') }}" method="POST" class="space-y-6">
|
||||||
<label for="name">Nom</label>
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
<input name="name" type="text" maxlength="256" required="required" />
|
<div>
|
||||||
<input type="Submit" value="Ajouter">
|
<label for="alias" class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Alias</label>
|
||||||
<p>Si vous créez un alias <strong>GTA : Grand Theft Auto</strong> alors si un utilisateur rentre la commande
|
<input type="text" name="alias" id="alias" maxlength="32" required placeholder="GTA" class="w-full px-3 py-2 bg-slate-50 dark:bg-slate-700 border border-slate-300 dark:border-slate-600 rounded-lg text-sm text-slate-900 dark:text-white placeholder-slate-500 dark:placeholder-slate-400 focus:ring-2 focus:ring-slate-500 focus:border-transparent transition-all">
|
||||||
<strong>!protondb GTA 5</strong> cela fera une recherche sur <strong>Grand Theft Auto 5</strong>.
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="name" class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Nom complet</label>
|
||||||
|
<input type="text" name="name" id="name" maxlength="256" required placeholder="Grand Theft Auto" class="w-full px-3 py-2 bg-slate-50 dark:bg-slate-700 border border-slate-300 dark:border-slate-600 rounded-lg text-sm text-slate-900 dark:text-white placeholder-slate-500 dark:placeholder-slate-400 focus:ring-2 focus:ring-slate-500 focus:border-transparent transition-all">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex justify-end">
|
||||||
|
<button type="submit" class="px-4 py-2 bg-slate-800 hover:bg-slate-700 dark:bg-slate-700 dark:hover:bg-slate-600 text-white text-sm font-medium rounded-lg transition-colors">
|
||||||
|
Ajouter
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div class="mt-5 bg-slate-50 dark:bg-slate-700/50 rounded-lg p-4">
|
||||||
|
<p class="text-sm text-slate-600 dark:text-slate-400">
|
||||||
|
<strong class="text-slate-800 dark:text-white">Exemple :</strong> Si vous créez un alias GTA → Grand Theft Auto, alors !protondb GTA 5 fera une recherche sur Grand Theft Auto 5.
|
||||||
</p>
|
</p>
|
||||||
</form>
|
</div>
|
||||||
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<h2>Configuration</h2>
|
<div class="bg-white dark:bg-slate-800 rounded-lg border border-slate-200 dark:border-slate-700 overflow-hidden">
|
||||||
<form action="{{ url_for('updateConfiguration') }}" method="POST">
|
<div class="px-5 py-4 border-b border-slate-200 dark:border-slate-700">
|
||||||
<label for="proton_db_enable_enable">Activer</label>
|
<h2 class="text-lg font-medium text-slate-800 dark:text-white">Configuration</h2>
|
||||||
<input type="checkbox" name="proton_db_enable_enable" {% if configuration.getValue('proton_db_enable_enable') %}
|
</div>
|
||||||
checked="checked" {% endif %}>
|
|
||||||
<label>Activer la commande Proton DB</label>
|
|
||||||
<label for="proton_db_api_id">API ID</label>
|
|
||||||
<input name="proton_db_api_id" type="text" value="{{ configuration.getValue('proton_db_api_id') }}" />
|
|
||||||
<label for="proton_db_api_key">Clé API</label>
|
|
||||||
<input name="proton_db_api_key" type="text" value="{{ configuration.getValue('proton_db_api_key') }}" />
|
|
||||||
<input type="Submit" value="Définir">
|
|
||||||
<p>Pour trouver les clés, dans votre navigateur avec l'outil d'inspection ouvert (F12 ou clic droit > Inspecter
|
|
||||||
l'élément dans Firefox/Chrome) faites une recherche de jeux sur protondb,
|
|
||||||
puis cherchez les clés dans les requêtes (onglet Réseau/Network),
|
|
||||||
<a href="/static/img/algolia-key.jpg" target="_blank">comme le montre cet exemple</a>
|
|
||||||
</p>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
|
<form action="{{ url_for('updateConfiguration') }}" method="POST" class="p-5 space-y-6">
|
||||||
|
<label class="flex items-center gap-3 cursor-pointer">
|
||||||
|
<input type="checkbox" name="proton_db_enable_enable" {% if configuration.getValue('proton_db_enable_enable') %}checked{% endif %} class="w-4 h-4 text-slate-600 bg-slate-100 dark:bg-slate-700 border-slate-300 dark:border-slate-600 rounded focus:ring-slate-500">
|
||||||
|
<span class="text-sm text-slate-700 dark:text-slate-300">Activer la commande ProtonDB</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
|
<div>
|
||||||
|
<label for="proton_db_api_id" class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">API ID</label>
|
||||||
|
<input type="text" name="proton_db_api_id" id="proton_db_api_id" value="{{ configuration.getValue('proton_db_api_id') }}" class="w-full px-3 py-2 bg-slate-50 dark:bg-slate-700 border border-slate-300 dark:border-slate-600 rounded-lg text-sm text-slate-900 dark:text-white focus:ring-2 focus:ring-slate-500 focus:border-transparent transition-all">
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="proton_db_api_key" class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Clé API</label>
|
||||||
|
<input type="text" name="proton_db_api_key" id="proton_db_api_key" value="{{ configuration.getValue('proton_db_api_key') }}" class="w-full px-3 py-2 bg-slate-50 dark:bg-slate-700 border border-slate-300 dark:border-slate-600 rounded-lg text-sm text-slate-900 dark:text-white focus:ring-2 focus:ring-slate-500 focus:border-transparent transition-all">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit" class="px-4 py-2 bg-slate-800 hover:bg-slate-700 dark:bg-slate-700 dark:hover:bg-slate-600 text-white text-sm font-medium rounded-lg transition-colors">
|
||||||
|
Enregistrer
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div class="px-5 pb-5">
|
||||||
|
<div class="bg-slate-50 dark:bg-slate-700/50 rounded-lg p-4">
|
||||||
|
<p class="text-sm font-medium text-slate-800 dark:text-white mb-2">Comment trouver les clés API ?</p>
|
||||||
|
<ol class="list-decimal list-inside space-y-1 text-sm text-slate-600 dark:text-slate-400">
|
||||||
|
<li>Ouvrez l'outil d'inspection de votre navigateur (F12)</li>
|
||||||
|
<li>Allez dans l'onglet Réseau/Network</li>
|
||||||
|
<li>Faites une recherche de jeu sur ProtonDB</li>
|
||||||
|
<li>Cherchez les clés dans les requêtes réseau</li>
|
||||||
|
</ol>
|
||||||
|
<a href="/static/img/algolia-key.jpg" target="_blank" class="inline-block mt-3 text-sm text-slate-600 dark:text-slate-400 hover:underline">
|
||||||
|
Voir l'exemple en image
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -1,39 +1,218 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html color-mode="user">
|
<html lang="fr" class="h-full">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta name="mobile-web-app-capable" content="yes" />
|
<meta name="mobile-web-app-capable" content="yes">
|
||||||
<title>Mamie Henriette</title>
|
<title>Mamie Henriette</title>
|
||||||
<link rel="stylesheet" href="/static/css/mvp.css" />
|
<script src="https://cdn.tailwindcss.com"></script>
|
||||||
<link rel="stylesheet" href="/static/css/style.css" />
|
<script>
|
||||||
|
tailwind.config = {
|
||||||
|
darkMode: 'class',
|
||||||
|
theme: {
|
||||||
|
extend: {
|
||||||
|
colors: {
|
||||||
|
primary: {
|
||||||
|
50: '#f8fafc',
|
||||||
|
100: '#f1f5f9',
|
||||||
|
200: '#e2e8f0',
|
||||||
|
300: '#cbd5e1',
|
||||||
|
400: '#94a3b8',
|
||||||
|
500: '#64748b',
|
||||||
|
600: '#475569',
|
||||||
|
700: '#334155',
|
||||||
|
800: '#1e293b',
|
||||||
|
900: '#0f172a',
|
||||||
|
},
|
||||||
|
accent: {
|
||||||
|
50: '#f0fdf4',
|
||||||
|
100: '#dcfce7',
|
||||||
|
200: '#bbf7d0',
|
||||||
|
300: '#86efac',
|
||||||
|
400: '#4ade80',
|
||||||
|
500: '#22c55e',
|
||||||
|
600: '#16a34a',
|
||||||
|
700: '#15803d',
|
||||||
|
800: '#166534',
|
||||||
|
900: '#14532d',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
<link rel="icon" href="/static/ico/favicon.ico" type="image/x-icon">
|
<link rel="icon" href="/static/ico/favicon.ico" type="image/x-icon">
|
||||||
<link rel="shortcut icon" href="/static/ico/favicon.ico" type="image/x-icon">
|
<link rel="shortcut icon" href="/static/ico/favicon.ico" type="image/x-icon">
|
||||||
|
<style>
|
||||||
|
/* Animations personnalisées */
|
||||||
|
.fade-in {
|
||||||
|
animation: fadeIn 0.3s ease-in-out;
|
||||||
|
}
|
||||||
|
@keyframes fadeIn {
|
||||||
|
from { opacity: 0; transform: translateY(-10px); }
|
||||||
|
to { opacity: 1; transform: translateY(0); }
|
||||||
|
}
|
||||||
|
/* Scrollbar personnalisée */
|
||||||
|
::-webkit-scrollbar { width: 8px; height: 8px; }
|
||||||
|
::-webkit-scrollbar-track { background: transparent; }
|
||||||
|
::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 4px; }
|
||||||
|
::-webkit-scrollbar-thumb:hover { background: #94a3b8; }
|
||||||
|
.dark ::-webkit-scrollbar-thumb { background: #475569; }
|
||||||
|
.dark ::-webkit-scrollbar-thumb:hover { background: #64748b; }
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body class="h-full bg-gray-50 dark:bg-gray-900 text-gray-900 dark:text-gray-100 transition-colors duration-200">
|
||||||
<header>
|
<!-- Navbar -->
|
||||||
<nav>
|
<nav class="fixed top-0 left-0 right-0 z-50 bg-white dark:bg-gray-800 shadow-md border-b border-gray-200 dark:border-gray-700">
|
||||||
<a href="/"><img src="/static/ico/favicon.ico"></a>
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<ul>
|
<div class="flex items-center justify-between h-16">
|
||||||
<li><a href="/live-alert">Alerte live</a></li>
|
<!-- Logo -->
|
||||||
<li><a href="/commandes">Commandes</a></li>
|
<a href="/" class="flex items-center gap-3 group">
|
||||||
<li><a href="/humeurs">Humeurs</a></li>
|
<img src="/static/ico/favicon.ico" alt="Mamie Henriette" class="w-10 h-10 rounded-full ring-2 ring-slate-200 dark:ring-slate-600 group-hover:ring-slate-300 dark:group-hover:ring-slate-500 transition-all">
|
||||||
<li><a href="/moderation">Modération</a></li>
|
<span class="font-bold text-xl text-slate-800 dark:text-white hidden sm:block">Mamie Henriette</span>
|
||||||
<li><a href="/protondb">ProtonDB</a></li>
|
</a>
|
||||||
<li><a href="/configurations">Configurations</a></li>
|
|
||||||
</ul>
|
<!-- Navigation Desktop -->
|
||||||
|
<div class="hidden md:flex items-center gap-1">
|
||||||
|
<a href="/live-alert" class="px-4 py-2 rounded-lg text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 hover:text-primary-600 dark:hover:text-primary-400 transition-all">
|
||||||
|
<span class="flex items-center gap-2">
|
||||||
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 10l4.553-2.276A1 1 0 0121 8.618v6.764a1 1 0 01-1.447.894L15 14M5 18h8a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z"></path></svg>
|
||||||
|
Alerte live
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
<a href="/commandes" class="px-4 py-2 rounded-lg text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 hover:text-primary-600 dark:hover:text-primary-400 transition-all">
|
||||||
|
<span class="flex items-center gap-2">
|
||||||
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"></path></svg>
|
||||||
|
Commandes
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
<a href="/humeurs" class="px-4 py-2 rounded-lg text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 hover:text-primary-600 dark:hover:text-primary-400 transition-all">
|
||||||
|
<span class="flex items-center gap-2">
|
||||||
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14.828 14.828a4 4 0 01-5.656 0M9 10h.01M15 10h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>
|
||||||
|
Humeurs
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
<a href="/moderation" class="px-4 py-2 rounded-lg text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 hover:text-primary-600 dark:hover:text-primary-400 transition-all">
|
||||||
|
<span class="flex items-center gap-2">
|
||||||
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"></path></svg>
|
||||||
|
Modération
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
<a href="/protondb" class="px-4 py-2 rounded-lg text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 hover:text-primary-600 dark:hover:text-primary-400 transition-all">
|
||||||
|
<span class="flex items-center gap-2">
|
||||||
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 4a2 2 0 114 0v1a1 1 0 001 1h3a1 1 0 011 1v3a1 1 0 01-1 1h-1a2 2 0 100 4h1a1 1 0 011 1v3a1 1 0 01-1 1h-3a1 1 0 01-1-1v-1a2 2 0 10-4 0v1a1 1 0 01-1 1H7a1 1 0 01-1-1v-3a1 1 0 00-1-1H4a2 2 0 110-4h1a1 1 0 001-1V7a1 1 0 011-1h3a1 1 0 001-1V4z"></path></svg>
|
||||||
|
ProtonDB
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
<a href="/configurations" class="px-4 py-2 rounded-lg text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 hover:text-primary-600 dark:hover:text-primary-400 transition-all">
|
||||||
|
<span class="flex items-center gap-2">
|
||||||
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"></path><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path></svg>
|
||||||
|
Configurations
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Actions -->
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<!-- Dark Mode Toggle -->
|
||||||
|
<button onclick="toggleDarkMode()" class="p-2 rounded-lg text-gray-500 hover:bg-gray-100 dark:hover:bg-gray-700 hover:text-primary-600 dark:hover:text-primary-400 transition-all" title="Mode sombre">
|
||||||
|
<svg class="w-5 h-5 hidden dark:block" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"></path></svg>
|
||||||
|
<svg class="w-5 h-5 block dark:hidden" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"></path></svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<!-- Mobile Menu Button -->
|
||||||
|
<button onclick="toggleMobileMenu()" class="md:hidden p-2 rounded-lg text-gray-500 hover:bg-gray-100 dark:hover:bg-gray-700 transition-all">
|
||||||
|
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path></svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Mobile Menu -->
|
||||||
|
<div id="mobile-menu" class="hidden md:hidden border-t border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800">
|
||||||
|
<div class="px-4 py-3 space-y-1">
|
||||||
|
<a href="/live-alert" class="flex items-center gap-3 px-4 py-3 rounded-lg text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 transition-all">
|
||||||
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 10l4.553-2.276A1 1 0 0121 8.618v6.764a1 1 0 01-1.447.894L15 14M5 18h8a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z"></path></svg>
|
||||||
|
Alerte live
|
||||||
|
</a>
|
||||||
|
<a href="/commandes" class="flex items-center gap-3 px-4 py-3 rounded-lg text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 transition-all">
|
||||||
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"></path></svg>
|
||||||
|
Commandes
|
||||||
|
</a>
|
||||||
|
<a href="/humeurs" class="flex items-center gap-3 px-4 py-3 rounded-lg text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 transition-all">
|
||||||
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14.828 14.828a4 4 0 01-5.656 0M9 10h.01M15 10h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>
|
||||||
|
Humeurs
|
||||||
|
</a>
|
||||||
|
<a href="/moderation" class="flex items-center gap-3 px-4 py-3 rounded-lg text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 transition-all">
|
||||||
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"></path></svg>
|
||||||
|
Modération
|
||||||
|
</a>
|
||||||
|
<a href="/protondb" class="flex items-center gap-3 px-4 py-3 rounded-lg text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 transition-all">
|
||||||
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 4a2 2 0 114 0v1a1 1 0 001 1h3a1 1 0 011 1v3a1 1 0 01-1 1h-1a2 2 0 100 4h1a1 1 0 011 1v3a1 1 0 01-1 1h-3a1 1 0 01-1-1v-1a2 2 0 10-4 0v1a1 1 0 01-1 1H7a1 1 0 01-1-1v-3a1 1 0 00-1-1H4a2 2 0 110-4h1a1 1 0 001-1V7a1 1 0 011-1h3a1 1 0 001-1V4z"></path></svg>
|
||||||
|
ProtonDB
|
||||||
|
</a>
|
||||||
|
<a href="/configurations" class="flex items-center gap-3 px-4 py-3 rounded-lg text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 transition-all">
|
||||||
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"></path><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path></svg>
|
||||||
|
Configurations
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
</header>
|
|
||||||
<main>
|
<!-- Main Content -->
|
||||||
|
<main class="pt-20 pb-12 min-h-screen">
|
||||||
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
<div class="fade-in">
|
||||||
{% block content %}{% endblock %}
|
{% block content %}{% endblock %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</main>
|
</main>
|
||||||
<footer>
|
|
||||||
<hr>
|
<!-- Footer -->
|
||||||
<p><a href="https://github.com/skylanix/MamieHenriette" target="_blank">MamieHenriette</a> créé par la communauté <a href="https://discord.com/invite/UwAPqMJnx3" target="_blank">Discord</a> de <a href="https://www.youtube.com/@513v3" target="_blank">573v3</a> - Projet open source sous licence <a href="https://www.gnu.org/licenses/agpl-3.0.html" target="_blank">AGPLv3</a></p>
|
<footer class="bg-white dark:bg-gray-800 border-t border-gray-200 dark:border-gray-700">
|
||||||
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
|
||||||
|
<div class="flex flex-col sm:flex-row items-center justify-between gap-4">
|
||||||
|
<div class="flex items-center gap-2 text-sm text-gray-600 dark:text-gray-400">
|
||||||
|
<img src="/static/ico/favicon.ico" alt="" class="w-6 h-6 rounded-full">
|
||||||
|
<span>Mamie Henriette</span>
|
||||||
|
</div>
|
||||||
|
<p class="text-sm text-gray-500 dark:text-gray-400 text-center">
|
||||||
|
Créé par la communauté
|
||||||
|
<a href="https://discord.com/invite/UwAPqMJnx3" target="_blank" class="text-primary-600 dark:text-primary-400 hover:underline">Discord</a>
|
||||||
|
de
|
||||||
|
<a href="https://www.youtube.com/@513v3" target="_blank" class="text-primary-600 dark:text-primary-400 hover:underline">573v3</a>
|
||||||
|
</p>
|
||||||
|
<div class="flex items-center gap-4">
|
||||||
|
<a href="https://github.com/skylanix/MamieHenriette" target="_blank" class="text-gray-500 hover:text-gray-700 dark:hover:text-gray-300 transition-colors">
|
||||||
|
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24"><path fill-rule="evenodd" d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z" clip-rule="evenodd"></path></svg>
|
||||||
|
</a>
|
||||||
|
<span class="text-xs text-gray-400 dark:text-gray-500">AGPLv3</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Dark mode
|
||||||
|
function toggleDarkMode() {
|
||||||
|
document.documentElement.classList.toggle('dark');
|
||||||
|
localStorage.setItem('darkMode', document.documentElement.classList.contains('dark'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize dark mode from preference
|
||||||
|
if (localStorage.getItem('darkMode') === 'true' ||
|
||||||
|
(!localStorage.getItem('darkMode') && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
||||||
|
document.documentElement.classList.add('dark');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mobile menu
|
||||||
|
function toggleMobileMenu() {
|
||||||
|
document.getElementById('mobile-menu').classList.toggle('hidden');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
@@ -1,35 +1,92 @@
|
|||||||
{% extends "template.html" %}
|
{% extends "template.html" %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>Procédure de configuration de Twitch</h1>
|
<div class="mb-6">
|
||||||
<p>
|
<h1 class="text-2xl font-semibold text-slate-800 dark:text-white mb-1">Configuration Twitch</h1>
|
||||||
<strong>Avant toute chose, activez l'authentification à deux facteurs (2FA) :</strong>
|
<p class="text-sm text-slate-600 dark:text-slate-400">
|
||||||
<a href="https://help.twitch.tv/s/article/two-factor-authentication?language=en_US" target="_blank">Guide officiel
|
Guide étape par étape pour configurer l'API Twitch.
|
||||||
Twitch pour la 2FA</a>
|
</p>
|
||||||
</p>
|
</div>
|
||||||
<p>
|
|
||||||
Rendez-vous sur <a href="https://dev.twitch.tv/console" target="_blank">la console d'applications Twitch</a> et
|
|
||||||
ajoutez une application. Renseignez :
|
|
||||||
<ul>
|
|
||||||
<li>URL de redirection : {{token_redirect_url}}</li>
|
|
||||||
<li>Catégorie : Chat Bot</li>
|
|
||||||
</ul>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<img src="/static/img/twitch-api-01.jpg">
|
<div class="space-y-4">
|
||||||
|
<div class="bg-white dark:bg-slate-800 rounded-lg border border-slate-200 dark:border-slate-700 overflow-hidden">
|
||||||
|
<div class="px-5 py-4 border-b border-slate-200 dark:border-slate-700">
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<span class="w-6 h-6 rounded-full bg-slate-200 dark:bg-slate-700 flex items-center justify-center text-slate-600 dark:text-slate-400 text-xs font-medium">1</span>
|
||||||
|
<h2 class="font-medium text-slate-800 dark:text-white">Activer l'authentification à deux facteurs (2FA)</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="p-5">
|
||||||
|
<p class="text-sm text-slate-600 dark:text-slate-400 mb-4">
|
||||||
|
Avant de créer une application Twitch, vous devez activer la 2FA sur votre compte.
|
||||||
|
</p>
|
||||||
|
<a href="https://help.twitch.tv/s/article/two-factor-authentication?language=en_US" target="_blank" class="inline-flex items-center gap-2 text-sm text-slate-600 dark:text-slate-400 hover:text-slate-800 dark:hover:text-white">
|
||||||
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"></path></svg>
|
||||||
|
Guide officiel Twitch
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<p>
|
<div class="bg-white dark:bg-slate-800 rounded-lg border border-slate-200 dark:border-slate-700 overflow-hidden">
|
||||||
Créez le bot. Puis, de retour à la liste, éditez-le en cliquant sur Gérer. Puis cliquez sur <strong>Nouveau
|
<div class="px-5 py-4 border-b border-slate-200 dark:border-slate-700">
|
||||||
Secret</strong>. Vous trouverez ici le <strong>Client ID</strong> et le <strong>Client Secret</strong>.
|
<div class="flex items-center gap-3">
|
||||||
</p>
|
<span class="w-6 h-6 rounded-full bg-slate-200 dark:bg-slate-700 flex items-center justify-center text-slate-600 dark:text-slate-400 text-xs font-medium">2</span>
|
||||||
|
<h2 class="font-medium text-slate-800 dark:text-white">Créer une application Twitch</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="p-5 space-y-4">
|
||||||
|
<p class="text-sm text-slate-600 dark:text-slate-400">
|
||||||
|
Rendez-vous sur la console Twitch et créez une nouvelle application :
|
||||||
|
</p>
|
||||||
|
<a href="https://dev.twitch.tv/console" target="_blank" class="inline-flex items-center gap-2 px-3 py-1.5 bg-slate-800 dark:bg-slate-700 text-white text-sm rounded-lg hover:bg-slate-700 dark:hover:bg-slate-600 transition-colors">
|
||||||
|
Console Twitch
|
||||||
|
</a>
|
||||||
|
|
||||||
<img src="/static/img/twitch-api-02.jpg">
|
<div class="bg-slate-50 dark:bg-slate-700/50 rounded-lg p-4 space-y-2 text-sm">
|
||||||
|
<div><span class="text-slate-500 dark:text-slate-400">URL de redirection :</span> <code class="ml-1 px-1.5 py-0.5 bg-slate-200 dark:bg-slate-600 rounded text-xs">{{ token_redirect_url }}</code></div>
|
||||||
|
<div><span class="text-slate-500 dark:text-slate-400">Catégorie :</span> <span class="ml-1 text-slate-800 dark:text-white">Chat Bot</span></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<p>
|
<div class="rounded-lg overflow-hidden border border-slate-200 dark:border-slate-700">
|
||||||
Ensuite, retournez sur la page de <a href="{{url_for('openConfigurations')}}">Configuration</a>, après avoir
|
<img src="/static/img/twitch-api-01.jpg" alt="Création d'application Twitch" class="w-full">
|
||||||
enregistré le <strong>Client ID</strong> et le <strong>Client Secret</strong>, cliquez sur le lien <strong>Obtenir
|
</div>
|
||||||
token et refresh token</strong>. Si tout se passe bien les champs <strong>Access Token</strong> et
|
</div>
|
||||||
<strong>Refresh Token</strong> sont remplis.
|
</div>
|
||||||
</p>
|
|
||||||
|
|
||||||
|
<div class="bg-white dark:bg-slate-800 rounded-lg border border-slate-200 dark:border-slate-700 overflow-hidden">
|
||||||
|
<div class="px-5 py-4 border-b border-slate-200 dark:border-slate-700">
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<span class="w-6 h-6 rounded-full bg-slate-200 dark:bg-slate-700 flex items-center justify-center text-slate-600 dark:text-slate-400 text-xs font-medium">3</span>
|
||||||
|
<h2 class="font-medium text-slate-800 dark:text-white">Récupérer les identifiants</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="p-5 space-y-4">
|
||||||
|
<p class="text-sm text-slate-600 dark:text-slate-400">
|
||||||
|
Cliquez sur <strong class="text-slate-800 dark:text-white">Gérer</strong> puis <strong class="text-slate-800 dark:text-white">Nouveau Secret</strong> pour obtenir le Client ID et Client Secret.
|
||||||
|
</p>
|
||||||
|
<div class="rounded-lg overflow-hidden border border-slate-200 dark:border-slate-700">
|
||||||
|
<img src="/static/img/twitch-api-02.jpg" alt="Récupération des identifiants" class="w-full">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="bg-white dark:bg-slate-800 rounded-lg border border-slate-200 dark:border-slate-700 overflow-hidden">
|
||||||
|
<div class="px-5 py-4 border-b border-slate-200 dark:border-slate-700">
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<span class="w-6 h-6 rounded-full bg-slate-200 dark:bg-slate-700 flex items-center justify-center text-slate-600 dark:text-slate-400 text-xs font-medium">4</span>
|
||||||
|
<h2 class="font-medium text-slate-800 dark:text-white">Configurer Mamie Henriette</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="p-5 space-y-4">
|
||||||
|
<ol class="list-decimal list-inside space-y-1 text-sm text-slate-600 dark:text-slate-400">
|
||||||
|
<li>Entrez le Client ID et Client Secret</li>
|
||||||
|
<li>Cliquez sur Enregistrer</li>
|
||||||
|
<li>Cliquez sur "Obtenir token et refresh token"</li>
|
||||||
|
</ol>
|
||||||
|
<a href="{{ url_for('openConfigurations') }}" class="inline-flex items-center gap-2 px-3 py-1.5 bg-slate-800 dark:bg-slate-700 text-white text-sm rounded-lg hover:bg-slate-700 dark:hover:bg-slate-600 transition-colors">
|
||||||
|
Aller à la Configuration
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
Reference in New Issue
Block a user