mirror of
https://github.com/skylanix/MamieHenriette.git
synced 2026-02-06 14:50:34 +01:00
Merge pull request #42 from skylanix/front-tailwind
Supprime les fichiers CSS obsolètes et met à jour les templates HTML …
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