Téléverser les fichiers vers "methode1"
This commit is contained in:
parent
f1d71ff9ef
commit
3ce51283ce
@ -43,13 +43,11 @@ class NouvelleFenetre:
|
|||||||
self.root.grid_columnconfigure(2, weight=0)
|
self.root.grid_columnconfigure(2, weight=0)
|
||||||
self.root.grid_columnconfigure(3, weight=0)
|
self.root.grid_columnconfigure(3, weight=0)
|
||||||
|
|
||||||
# Initialisez la connexion OBS WebSocket
|
|
||||||
self.obs_host = "localhost" # Adresse IP de votre ordinateur où OBS est en cours d'exécution
|
self.obs_host = "localhost" # Adresse IP de votre ordinateur où OBS est en cours d'exécution
|
||||||
self.obs_port = 4455 # Port par défaut utilisé par OBSWebsocket
|
self.obs_port = 4455 # Port par défaut utilisé par OBSWebsocket
|
||||||
self.obs_password = "MPcZLZfViZihHqmg" # Mot de passe OBSWebsocket
|
self.obs_password = "MPcZLZfViZihHqmg" # Mot de passe OBSWebsocket
|
||||||
|
|
||||||
|
|
||||||
# On récupère la clé Twitch depuis la base de données
|
|
||||||
self.twitch_key_from_database = self.get_twitch_key_from_database(username)
|
self.twitch_key_from_database = self.get_twitch_key_from_database(username)
|
||||||
|
|
||||||
|
|
||||||
@ -63,13 +61,10 @@ class NouvelleFenetre:
|
|||||||
|
|
||||||
self.lancer_auth_twitch()
|
self.lancer_auth_twitch()
|
||||||
|
|
||||||
# Récupérer le token OAuth Twitch depuis la base de données
|
|
||||||
self.oauth_token = self.get_oauth_token_from_database(username)
|
self.oauth_token = self.get_oauth_token_from_database(username)
|
||||||
|
|
||||||
# Initialiser Twitch
|
|
||||||
await self.initialize_twitch()
|
await self.initialize_twitch()
|
||||||
|
|
||||||
# On affiche bienvenue à la personne s'étant identifiée, en récupérant la variable lastname
|
|
||||||
label = Label(self.root, text=f"Bienvenue, {username}!")
|
label = Label(self.root, text=f"Bienvenue, {username}!")
|
||||||
label.grid(row=0, column=0)
|
label.grid(row=0, column=0)
|
||||||
|
|
||||||
@ -79,11 +74,9 @@ class NouvelleFenetre:
|
|||||||
self.entry_twitch = Entry(self.root)
|
self.entry_twitch = Entry(self.root)
|
||||||
self.entry_twitch.grid(row=3, column=0)
|
self.entry_twitch.grid(row=3, column=0)
|
||||||
|
|
||||||
# On met un bouton de validation pour garder les valeurs qu'on a rentré précédement
|
|
||||||
boutonvalidation = Button(self.root, text="Envoyé", command=lambda: self.set_key_twitch(username))
|
boutonvalidation = Button(self.root, text="Envoyé", command=lambda: self.set_key_twitch(username))
|
||||||
boutonvalidation.grid(row=4, column=0)
|
boutonvalidation.grid(row=4, column=0)
|
||||||
|
|
||||||
# On met un bouton de diffusion pour twitch
|
|
||||||
boutondediffusiontwitch = Button(self.root, text="Diffusion de Twitch On/Off", command=lambda: asyncio.run(self.configure_obs_for_twitch(self.twitch_key_from_database)))
|
boutondediffusiontwitch = Button(self.root, text="Diffusion de Twitch On/Off", command=lambda: asyncio.run(self.configure_obs_for_twitch(self.twitch_key_from_database)))
|
||||||
boutondediffusiontwitch.grid(row=4, column=3)
|
boutondediffusiontwitch.grid(row=4, column=3)
|
||||||
|
|
||||||
@ -93,53 +86,43 @@ class NouvelleFenetre:
|
|||||||
self.entry_youtube = Entry(self.root)
|
self.entry_youtube = Entry(self.root)
|
||||||
self.entry_youtube.grid(row=6, column=0)
|
self.entry_youtube.grid(row=6, column=0)
|
||||||
|
|
||||||
# On met un bouton pour envoyer les valeurs remplies du dessus
|
|
||||||
boutonvalidation2 = Button(self.root, text="Envoyé", command=lambda: self.set_key_youtube(username))
|
boutonvalidation2 = Button(self.root, text="Envoyé", command=lambda: self.set_key_youtube(username))
|
||||||
boutonvalidation2.grid(row=7, column=0)
|
boutonvalidation2.grid(row=7, column=0)
|
||||||
|
|
||||||
# On met un bouton de diffusion pour twitch
|
|
||||||
boutondediffusionyoutube = Button(self.root, text="Diffusion de YouTube On/Off")
|
boutondediffusionyoutube = Button(self.root, text="Diffusion de YouTube On/Off")
|
||||||
boutondediffusionyoutube.grid(row=7, column=3)
|
boutondediffusionyoutube.grid(row=7, column=3)
|
||||||
|
|
||||||
# On met un boutton fermer, pour pouvoir fermer la page main, et repasser sur la fenetre de connexion
|
|
||||||
bouton_fermer = Button(self.root, text="Fermer", command=self.fermer_et_reafficher)
|
bouton_fermer = Button(self.root, text="Fermer", command=self.fermer_et_reafficher)
|
||||||
bouton_fermer.grid(row=13, column=0)
|
bouton_fermer.grid(row=13, column=0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Fonction permettant de fermer la deuxième fenetre créee et la première fenetre de connexion de se réafficher tout en se déconnecctant d'OBS
|
|
||||||
def fermer_et_reafficher(self):
|
def fermer_et_reafficher(self):
|
||||||
self.root.destroy()
|
self.root.destroy()
|
||||||
self.ws.disconnect()
|
self.ws.disconnect()
|
||||||
self.root.master.deiconify()
|
self.root.master.deiconify()
|
||||||
|
|
||||||
# Fonction permettant de récupérer la valeur de la clé twitch qui a été renseignée
|
|
||||||
def get_key_twitch(self):
|
def get_key_twitch(self):
|
||||||
self.twitch = self.entry_twitch.get()
|
self.twitch = self.entry_twitch.get()
|
||||||
print(self.twitch)
|
print(self.twitch)
|
||||||
|
|
||||||
# Fonction permettant de récupérer la valeur de la clé youtube qui a été renseignée
|
|
||||||
def get_key_youtube(self):
|
def get_key_youtube(self):
|
||||||
self.youtube = self.entry_youtube.get()
|
self.youtube = self.entry_youtube.get()
|
||||||
print(self.youtube)
|
print(self.youtube)
|
||||||
|
|
||||||
def set_key_twitch(self, username):
|
def set_key_twitch(self, username):
|
||||||
try:
|
try:
|
||||||
# Paramètres du serveur
|
|
||||||
cnx = mysql.connector.connect(user='root', password='',
|
cnx = mysql.connector.connect(user='root', password='',
|
||||||
host='127.0.0.1',
|
host='127.0.0.1',
|
||||||
database='obs_project')
|
database='obs_project')
|
||||||
cur = cnx.cursor()
|
cur = cnx.cursor()
|
||||||
|
|
||||||
# On lance une requête pour vérifier si l'utilisateur correspond à la base de données
|
|
||||||
query = "SELECT * FROM utilisateurs WHERE username = %s"
|
query = "SELECT * FROM utilisateurs WHERE username = %s"
|
||||||
cur.execute(query, (username,))
|
cur.execute(query, (username,))
|
||||||
|
|
||||||
# Renvoie la première ligne de la base de données qui correspond
|
|
||||||
user = cur.fetchone()
|
user = cur.fetchone()
|
||||||
|
|
||||||
if user:
|
if user:
|
||||||
# Utilisateur trouvé, on met à jour la clé Twitch
|
|
||||||
new_twitch_key = self.entry_twitch.get()
|
new_twitch_key = self.entry_twitch.get()
|
||||||
update_query = "UPDATE twitch SET twitch_key = %s WHERE username = %s"
|
update_query = "UPDATE twitch SET twitch_key = %s WHERE username = %s"
|
||||||
cur.execute(update_query, (new_twitch_key, username))
|
cur.execute(update_query, (new_twitch_key, username))
|
||||||
@ -153,27 +136,22 @@ class NouvelleFenetre:
|
|||||||
messagebox.showerror("Erreur", "Une erreur a eu lieu pour mettre à jour votre clé")
|
messagebox.showerror("Erreur", "Une erreur a eu lieu pour mettre à jour votre clé")
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
# On ferme le tout, la connexion etc...
|
|
||||||
cur.close()
|
cur.close()
|
||||||
cnx.close()
|
cnx.close()
|
||||||
|
|
||||||
def set_key_youtube(self, username):
|
def set_key_youtube(self, username):
|
||||||
try:
|
try:
|
||||||
# Paramètres du serveur
|
|
||||||
cnx = mysql.connector.connect(user='root', password='',
|
cnx = mysql.connector.connect(user='root', password='',
|
||||||
host='127.0.0.1',
|
host='127.0.0.1',
|
||||||
database='obs_project')
|
database='obs_project')
|
||||||
cur = cnx.cursor()
|
cur = cnx.cursor()
|
||||||
|
|
||||||
# On lance une requête pour vérifier si l'utilisateur correspond à la base de données
|
|
||||||
query = "SELECT * FROM utilisateurs WHERE username = %s"
|
query = "SELECT * FROM utilisateurs WHERE username = %s"
|
||||||
cur.execute(query, (username,))
|
cur.execute(query, (username,))
|
||||||
|
|
||||||
# Renvoie la première ligne de la base de données qui correspond
|
|
||||||
user = cur.fetchone()
|
user = cur.fetchone()
|
||||||
|
|
||||||
if user:
|
if user:
|
||||||
# Utilisateur trouvé, on met à jour la clé Youtube
|
|
||||||
new_youtube_key = self.entry_youtube.get()
|
new_youtube_key = self.entry_youtube.get()
|
||||||
update_query = "UPDATE youtube SET youtube_key = %s WHERE username = %s"
|
update_query = "UPDATE youtube SET youtube_key = %s WHERE username = %s"
|
||||||
cur.execute(update_query, (new_youtube_key, username))
|
cur.execute(update_query, (new_youtube_key, username))
|
||||||
@ -187,19 +165,16 @@ class NouvelleFenetre:
|
|||||||
messagebox.showerror("Erreur", "Une erreur a eu lieu pour mettre à jour votre clé")
|
messagebox.showerror("Erreur", "Une erreur a eu lieu pour mettre à jour votre clé")
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
# On ferme le tout, la connexion etc...
|
|
||||||
cur.close()
|
cur.close()
|
||||||
cnx.close()
|
cnx.close()
|
||||||
|
|
||||||
def get_twitch_key_from_database(self, username):
|
def get_twitch_key_from_database(self, username):
|
||||||
try:
|
try:
|
||||||
# Paramètres du serveur
|
|
||||||
cnx = mysql.connector.connect(user='root', password='',
|
cnx = mysql.connector.connect(user='root', password='',
|
||||||
host='127.0.0.1',
|
host='127.0.0.1',
|
||||||
database='obs_project')
|
database='obs_project')
|
||||||
cur = cnx.cursor()
|
cur = cnx.cursor()
|
||||||
|
|
||||||
# On lance une requête pour récupérer la clé Twitch de l'utilisateur
|
|
||||||
query = "SELECT twitch_key FROM twitch WHERE username = %s"
|
query = "SELECT twitch_key FROM twitch WHERE username = %s"
|
||||||
cur.execute(query, (username,))
|
cur.execute(query, (username,))
|
||||||
twitch_key = cur.fetchone()
|
twitch_key = cur.fetchone()
|
||||||
@ -215,7 +190,6 @@ class NouvelleFenetre:
|
|||||||
messagebox.showerror("Erreur", "Une erreur a eu lieu pour récupérer la clé Twitch")
|
messagebox.showerror("Erreur", "Une erreur a eu lieu pour récupérer la clé Twitch")
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
# On ferme le tout, la connexion etc...
|
|
||||||
cur.close()
|
cur.close()
|
||||||
cnx.close()
|
cnx.close()
|
||||||
|
|
||||||
@ -232,13 +206,11 @@ class NouvelleFenetre:
|
|||||||
self.obs_ws = obsws(self.obs_host, self.obs_port, self.obs_password)
|
self.obs_ws = obsws(self.obs_host, self.obs_port, self.obs_password)
|
||||||
self.obs_ws.connect()
|
self.obs_ws.connect()
|
||||||
|
|
||||||
# Démarre le streaming sur Twitch
|
|
||||||
start_stream_request = obsrequests.StartStreaming(stream_key=twitch_key_from_database)
|
start_stream_request = obsrequests.StartStreaming(stream_key=twitch_key_from_database)
|
||||||
self.obs_ws.call(start_stream_request)
|
self.obs_ws.call(start_stream_request)
|
||||||
|
|
||||||
self.is_live = True
|
self.is_live = True
|
||||||
else:
|
else:
|
||||||
# Si déjà en live, arrêter le streaming
|
|
||||||
print("Arrêt du streaming Twitch.")
|
print("Arrêt du streaming Twitch.")
|
||||||
self.obs_ws.call(obsrequests.StopStreaming())
|
self.obs_ws.call(obsrequests.StopStreaming())
|
||||||
self.obs_ws.disconnect()
|
self.obs_ws.disconnect()
|
||||||
@ -251,7 +223,6 @@ class NouvelleFenetre:
|
|||||||
|
|
||||||
async def initialize_twitch(self):
|
async def initialize_twitch(self):
|
||||||
try:
|
try:
|
||||||
# Assurez-vous que self.oauth_token est défini
|
|
||||||
if self.oauth_token:
|
if self.oauth_token:
|
||||||
twitch = TwitchHelix(self.client_id, self.oauth_token)
|
twitch = TwitchHelix(self.client_id, self.oauth_token)
|
||||||
users = twitch.get_users()
|
users = twitch.get_users()
|
||||||
@ -268,16 +239,13 @@ class NouvelleFenetre:
|
|||||||
|
|
||||||
|
|
||||||
def lancer_auth_twitch(self):
|
def lancer_auth_twitch(self):
|
||||||
# Vérifier si la colonne OAuth est vide dans la base de données
|
|
||||||
oauth_token = self.get_oauth_token_from_database(self.username)
|
oauth_token = self.get_oauth_token_from_database(self.username)
|
||||||
print(f"Token OAuth récupéré pour {self.username}: {oauth_token}")
|
print(f"Token OAuth récupéré pour {self.username}: {oauth_token}")
|
||||||
|
|
||||||
if oauth_token is None or oauth_token.strip() == '':
|
if oauth_token is None or oauth_token.strip() == '':
|
||||||
# Si la colonne OAuth est vide, ouvrir la page d'authentification Twitch
|
|
||||||
webbrowser.open(self.oauth_authorization_url)
|
webbrowser.open(self.oauth_authorization_url)
|
||||||
messagebox.showinfo("Authentification Twitch", "Veuillez autoriser l'accès à Twitch dans le navigateur Web qui s'est ouvert.")
|
messagebox.showinfo("Authentification Twitch", "Veuillez autoriser l'accès à Twitch dans le navigateur Web qui s'est ouvert.")
|
||||||
else:
|
else:
|
||||||
# Si la colonne OAuth n'est pas vide, afficher un message indiquant que l'authentification n'est pas nécessaire
|
|
||||||
messagebox.showinfo("Authentification Twitch", "L'authentification Twitch n'est pas nécessaire car le token OAuth est déjà présent dans la base de données.")
|
messagebox.showinfo("Authentification Twitch", "L'authentification Twitch n'est pas nécessaire car le token OAuth est déjà présent dans la base de données.")
|
||||||
|
|
||||||
|
|
||||||
@ -292,10 +260,9 @@ class NouvelleFenetre:
|
|||||||
cur.execute(query, (username,))
|
cur.execute(query, (username,))
|
||||||
oauth_token = cur.fetchone()
|
oauth_token = cur.fetchone()
|
||||||
|
|
||||||
# Debugging output
|
|
||||||
print(f"Résultat de la requête pour l'utilisateur {username}: {oauth_token}")
|
print(f"Résultat de la requête pour l'utilisateur {username}: {oauth_token}")
|
||||||
|
|
||||||
if oauth_token and oauth_token[0].strip(): # Vérifie que le token n'est pas None et n'est pas une chaîne vide
|
if oauth_token and oauth_token[0].strip():
|
||||||
print(f"OAuth token trouvé pour l'utilisateur {username}: {oauth_token[0]}")
|
print(f"OAuth token trouvé pour l'utilisateur {username}: {oauth_token[0]}")
|
||||||
return oauth_token[0]
|
return oauth_token[0]
|
||||||
else:
|
else:
|
||||||
|
@ -4,7 +4,7 @@ from tkinter import messagebox
|
|||||||
import mysql.connector
|
import mysql.connector
|
||||||
|
|
||||||
class Mysql:
|
class Mysql:
|
||||||
# On initialise une première fenêtre d'identification et de mot de passe
|
|
||||||
def __init__(self, root):
|
def __init__(self, root):
|
||||||
self.root = root
|
self.root = root
|
||||||
self.root.title("Launcher OBS Extension Multistreaming")
|
self.root.title("Launcher OBS Extension Multistreaming")
|
||||||
@ -18,74 +18,63 @@ class Mysql:
|
|||||||
self.root.grid_columnconfigure(2, weight=0)
|
self.root.grid_columnconfigure(2, weight=0)
|
||||||
self.root.grid_columnconfigure(3, weight=0)
|
self.root.grid_columnconfigure(3, weight=0)
|
||||||
|
|
||||||
# On vérifie sur le serveur si l'identification correspond à des utilisateurs sur le serveur
|
|
||||||
def authenticate_user(self, username, password):
|
def authenticate_user(self, username, password):
|
||||||
try:
|
try:
|
||||||
# Paramètres du serveur
|
|
||||||
cnx = mysql.connector.connect(user='root', password='',
|
cnx = mysql.connector.connect(user='root', password='',
|
||||||
host='127.0.0.1',
|
host='127.0.0.1',
|
||||||
database='obs_project')
|
database='obs_project')
|
||||||
cur = cnx.cursor()
|
cur = cnx.cursor()
|
||||||
|
|
||||||
# On lance une requête pour vérifier si le lastname et le service correspond à la base de donnée
|
|
||||||
query = "SELECT * FROM utilisateurs WHERE username = %s AND password = %s"
|
query = "SELECT * FROM utilisateurs WHERE username = %s AND password = %s"
|
||||||
cur.execute(query, (username, password))
|
cur.execute(query, (username, password))
|
||||||
|
|
||||||
# Renvoie la première ligne de la base de donnée qui correspond
|
|
||||||
user = cur.fetchone()
|
user = cur.fetchone()
|
||||||
|
|
||||||
# Si c'est le cas, on affiche le message suivant et on ouvre une nouvelle fenêtre
|
|
||||||
if user:
|
if user:
|
||||||
messagebox.showinfo("Validé", "Authentification réussi")
|
messagebox.showinfo("Validé", "Authentification réussi")
|
||||||
self.ouvrir_nouvelle_fenetre(username, password)
|
self.ouvrir_nouvelle_fenetre(username, password)
|
||||||
|
|
||||||
# Sinon on affiche un message d'erreur
|
|
||||||
else:
|
else:
|
||||||
messagebox.showerror("Erreur", "Authentification erroné")
|
messagebox.showerror("Erreur", "Authentification erroné")
|
||||||
|
|
||||||
# Message si une erreur innatendue
|
|
||||||
except mysql.connector.Error as err:
|
except mysql.connector.Error as err:
|
||||||
messagebox.showerror("Erreur", f"Erreur: {err}")
|
messagebox.showerror("Erreur", f"Erreur: {err}")
|
||||||
|
|
||||||
# On ferme le tout, la connexion etc...
|
|
||||||
finally:
|
finally:
|
||||||
cur.close()
|
cur.close()
|
||||||
cnx.close()
|
cnx.close()
|
||||||
|
|
||||||
# On va initialiser une nouvelle fenêtre après la connexion tout en fermant la première
|
|
||||||
def ouvrir_nouvelle_fenetre(self, username, password):
|
def ouvrir_nouvelle_fenetre(self, username, password):
|
||||||
if self.root.winfo_exists(): # Vérifie si la fenêtre principale existe toujours
|
if self.root.winfo_exists():
|
||||||
self.root.withdraw() # Fermer la fenêtre actuelle
|
self.root.withdraw()
|
||||||
NouvelleFenetre(self.root, username, password) # Création de la nouvelle fenêtre avec toutes les infos, utilitées etc...
|
NouvelleFenetre(self.root, username, password)
|
||||||
|
|
||||||
|
|
||||||
# Lorsqu'on clique sur la case identifiant, le texte se supprime pour pouvoir taper le sien
|
|
||||||
def click_identifiant(self, event):
|
def click_identifiant(self, event):
|
||||||
entry_identifiant.configure(state=NORMAL)
|
entry_identifiant.configure(state=NORMAL)
|
||||||
entry_identifiant.delete(0, END)
|
entry_identifiant.delete(0, END)
|
||||||
entry_identifiant.unbind('<Button-1>', self.click_identifiant)
|
entry_identifiant.unbind('<Button-1>', self.click_identifiant)
|
||||||
|
|
||||||
# Lorsqu'on clique sur la case password, le texte se supprime pour pouvoir taper le sien
|
|
||||||
def click_pass(self, event):
|
def click_pass(self, event):
|
||||||
entry_pass.configure(state=NORMAL)
|
entry_pass.configure(state=NORMAL)
|
||||||
entry_pass.delete(0, END)
|
entry_pass.delete(0, END)
|
||||||
entry_pass.unbind('<Button-1>', self.click_pass)
|
entry_pass.unbind('<Button-1>', self.click_pass)
|
||||||
|
|
||||||
# On test voir si le username et le password que l'on récupére, correspond pour s'identifier
|
|
||||||
def msg_call_back(self):
|
def msg_call_back(self):
|
||||||
username = entry_identifiant.get()
|
username = entry_identifiant.get()
|
||||||
password = entry_pass.get()
|
password = entry_pass.get()
|
||||||
self.authenticate_user(username, password)
|
self.authenticate_user(username, password)
|
||||||
|
|
||||||
# Creation de la fenetre principale
|
|
||||||
fenetre = Tk()
|
fenetre = Tk()
|
||||||
obj = Mysql(fenetre)
|
obj = Mysql(fenetre)
|
||||||
|
|
||||||
# Ajout des boutons sur la fenêtre
|
|
||||||
label = Label(fenetre, text="Connexion")
|
label = Label(fenetre, text="Connexion")
|
||||||
label.grid(row = 0, column= 0)
|
label.grid(row = 0, column= 0)
|
||||||
|
|
||||||
# Entrée du champs identifiant
|
|
||||||
entry_identifiant = Entry(fenetre)
|
entry_identifiant = Entry(fenetre)
|
||||||
entry_identifiant.grid(row = 1, column=0)
|
entry_identifiant.grid(row = 1, column=0)
|
||||||
entry_identifiant.focus()
|
entry_identifiant.focus()
|
||||||
@ -93,16 +82,13 @@ entry_identifiant.insert(0, "Admin")
|
|||||||
|
|
||||||
entry_identifiant.bind('<Button-1>', obj.click_identifiant)
|
entry_identifiant.bind('<Button-1>', obj.click_identifiant)
|
||||||
|
|
||||||
# Entrée du champs password
|
|
||||||
entry_pass = Entry(fenetre, show='*')
|
entry_pass = Entry(fenetre, show='*')
|
||||||
entry_pass.grid(row = 2, column=0)
|
entry_pass.grid(row = 2, column=0)
|
||||||
entry_pass.insert(0, "Admin")
|
entry_pass.insert(0, "Admin")
|
||||||
|
|
||||||
entry_pass.bind('<Button-1>', obj.click_pass)
|
entry_pass.bind('<Button-1>', obj.click_pass)
|
||||||
|
|
||||||
# Bouton de connexion avec la fonction msg_call_back
|
|
||||||
boutonconnexion = Button(fenetre, text="Connexion", command=obj.msg_call_back, activebackground = "green")
|
boutonconnexion = Button(fenetre, text="Connexion", command=obj.msg_call_back, activebackground = "green")
|
||||||
boutonconnexion.grid(row = 3, column = 0)
|
boutonconnexion.grid(row = 3, column = 0)
|
||||||
|
|
||||||
# Lancer l'application
|
|
||||||
fenetre.mainloop()
|
fenetre.mainloop()
|
||||||
|
Loading…
Reference in New Issue
Block a user