Système de support de présentation avec Python3

introduction

C'est @ seigo2016 de la classe de programmation N lycée 1ère année. Ce sera N High Adcare Day 8. Je me demandais quoi écrire car c'était un bon article, mais comme j'ai beaucoup parlé du projet principal actuel "Itokake Mandala Color Simulator" chez U22 etc., cette fois j'ai beaucoup parlé du récent projet à court terme "PSS ~ Presentation Support". Je parlerai de "System ~".

Objectif du PSS ~ Système de support de présentation ~

Je pense que vous faites souvent des présentations en utilisant PowerPoint, Google Slide, etc. lorsque vous dites quelque chose aux gens. LT a également lieu chaque mois dans la classe de programmation N High (ci-après dénommée Prokura). J'ai donc décidé de créer un système pour soutenir la présentation.

une fonction

  1. Les commentaires circulent en temps réel
  2. Vous pouvez utiliser la diapositive à partir d'un smartphone, etc.
  3. Le pointeur peut être utilisé (non implémenté)

environnement

PSS.png

serveur Web

C'est la partie qui accepte et enregistre les commentaires. Tout fonctionne sur Docker. La mémoire est de 1 Go, mais cela fonctionne de manière inattendue.

Informations sur le serveur

partie Performance
VPN Vultr
CPU 1C/1T
Memory 1024MB
OS OS Debian 10 Buster

Informations sur le conteneur Docker

Je l'utilise également pour pratiquer Docker et Docker-Compose.

Nom du conteneur Aperçu
proxy Nginx Reverse Proxy
web Python3.6(Exécuter Python)
mysql DB(Enregistrer les informations de connexion)

Environnement serveur

J'ai utilisé bcrypt pour hacher le mot de passe et la bibliothèque mysql-connector pour me connecter à mysql. En plus des éléments suivants, SSL et Socket ont été utilisés.

Python3


bcrypt==3.1.7
mysql-connector==2.2.9
pycrypto==2.6.1
PyYAML==5.2
tornado==6.0.3

Environnement client

J'ai utilisé Tkinter comme bibliothèque pour créer l'interface graphique.

Python3


pdf2image==1.10.0
Pillow==6.2.1
progressbar2==3.47.0
PyYAML==5.2

Envoyez des commentaires en temps réel

C'est la partie principale de ce projet. Le système lui-même, dans lequel les commentaires circulent en temps réel, a déjà été créé par d'autres étudiants de clubs professionnels. Cependant, il y avait de nombreuses restrictions telles que ne pas pouvoir l'utiliser si les connexions entre les clients étaient séparées, nous avons donc décidé de créer un nouveau système qui améliorait ces parties. ** Ce système n'enfreint pas le brevet du système de commentaire de Dongo car la méthode de montage et les spécifications sont complètement différentes ** Voilà comment cela fonctionne.

En passant, il y a plusieurs personnes autour de moi qui veulent trouver et signaler des vulnérabilités, donc certaines mesures de sécurité sont nécessaires pour éviter qu'elles ne soient incluses dans la présentation réelle.

serveur

Façade Web

C'est la partie qui accepte les commentaires. Le flux est le suivant.

  1. Vérifiez les commentaires reçus pour les problèmes de sécurité
  2. Enregistrez dans la base de données s'il y a un problème
  3. Affectez à une variable partagée entre les threads.

server.py


def send_comment(comment):
    #Heure actuelle(JST)
    dt_now = dt.now(JST)
    #Enregistrer dans la base de données
    c = database.cursor()
    sql = "INSERT INTO comment (text, entertime) values(%s,%s)"
    c.execute(sql,
              (comment, dt_now,))
    database.commit()
    #Assigner à une variable partagée entre les threads
    with commentbody.get_lock():
        commentbody.value = comment.encode()


class Comment(web.RequestHandler):
    def post(self):
        comment = self.get_argument("comment")
        comment = escape(comment)
        title = "commentaire"
        if re.search(r'\S', comment) and len(comment) < 30:
            send_comment(comment)
            self.render('index.html', title=title)
        else:
            message = "Entrer correctement"
            self.render('index.html', title=title, message=message)

Envoyer au client

Ensuite, ce sera la partie qui envoie le commentaire reçu au client (PC présentateur) par communication socket. Le flux est le suivant.

  1. Attendez la connexion Socket sur le port 10023
  2. Vérifiez les informations de l'utilisateur s'il est connecté
  3. Si les informations reçues correspondent aux informations utilisateur sur la base de données, poursuivez la connexion.
  4. Ensuite, envoyez le commentaire reçu au client, le cas échéant. Nous vérifions si l'identifiant et le mot de passe des données envoyées correspondent au hachage de l'identifiant et du mot de passe enregistrés dans la base de données à l'avance. ~~ ** Le nid n'est-il pas profond? ** ~~

server.py


def connect_socket():  #Communication par socket
    print("SocketStart")
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind(('0.0.0.0', 10023))  #Ouvert sur le port 10023
        while True:
            s.listen(1)
            print("Waitng ....")
            conn, addr = s.accept()
            flg = False
            while True:
                try:
                    conn = context.wrap_socket(conn, server_side=3)
                    with conn:
                        while True:
                            try:
                                print("Connecting")
                                data = conn.recv(1024).decode()
                                if not data:
                                    break
                                elif ":" in data:
                                    loginuser = data.split(":")[0]
                                    loginpass = data.split(":")[1]
                                    sql = "SELECT id, name, pass FROM users WHERE name = %s"
                                    c.execute(sql, (loginuser,))
                                    userdata = c.fetchall()
                                    if len(userdata) and bcrypt.checkpw(loginpass.encode(), userdata[0][2].encode()):
                                        print("Connected")
                                        conn.sendall("Connexion terminée".encode("utf-8"))
                                        flg = True
                                    else:
                                        conn.sendall("Erreur d'authentification".encode("utf-8"))
                                        conn.close()
                                        flg = False
                                elif flg:
                                    comment = commentbody.value
                                    with commentbody.get_lock():
                                        commentbody.value = "".encode()
                                    if len(comment):
                                        conn.sendall(comment)
                                        comment = ""
                            except socket.error:
                                flg = False
                                break
                except Exception as e:
                    flg = False
                    print("Disconnected\n{}".format(e))
        s.close()

Client (PC présentateur)

Recevoir des commentaires

Après la connexion au serveur, l'envoi des informations d'authentification et la connexion, le client (PC présentateur) reçoit le commentaire.

client.py


def rcv_comment():
    #Paramètres de communication du socket
    context = ssl.create_default_context()
    context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
    context.verify_mode = ssl.CERT_NONE
    context.check_hostname = False
    conn = context.wrap_socket(socket.socket(socket.AF_INET),
                               server_hostname=host)
    conn.connect((host, port))
    #Préparer les informations d'authentification(Le format est l'utilisateur:pass)
    idpass = "{}:{}".format(user_name, user_pass).encode()
    conn.sendall(idpass)
    manager = CommentManager(canvas)
    while True:
        try:
            data = conn.recv(1024)
            if len(data):
                comment = data.decode('utf-8')
                print("recv:" + comment)
                #Si une erreur d'authentification est renvoyée, terminez le programme
                if comment == "Erreur d'authentification":
                    break
                #Sinon, transmettez le commentaire à la partie du dessin
                manager.add_text(comment)
        except KeyboardInterrupt:
            break

Dessin de commentaire

Dessinez le commentaire reçu sur la toile de Tkinter.

client.py


class CommentManager: #Gérer les commentaires de dessin
    def __init__(self, canvas):
        self.canvas_text_list = []
        self.canvas = canvas
        root.after(1, self.update)

    def add_text(self, comment): #Ajouter un commentaire au flux
    #La coordonnée X est au bord de l'écran, la coordonnée y est générée aléatoirement
        text = self.canvas.create_text(
            w, random.uniform(2.0, 18.0) * 100, text=comment, font=comment_font) 
        self.canvas_text_list.append(text)

    def update(self): #Déplacer vers la gauche
        new_list = []
        #Déplacez les commentaires dans la liste vers la gauche.(Il semble préférable de tout faire en même temps en utilisant des balises)
        for canvas_text in self.canvas_text_list: 
            self.canvas.move(canvas_text, -15, 0)
            x, y = self.canvas.coords(canvas_text)
            if x > -10:
                new_list.append(canvas_text)
            else: #Après s'être déplacé vers l'extrémité gauche
                self.canvas.delete(canvas_text)
        self.canvas_text_list = new_list
        root.after(20, self.update)

Opération de glissière

Puisque la diapositive elle-même est chargée dans le canevas de Tkinter, mettez simplement à jour l'image

client.py


def next(event): #Envoyer la diapositive
    global page
    if pagemax - 1 > page:
        canvas.itemconfig(labelimg, image=img[page])
        page += 1


def prev(event): #Reculer la diapositive
    global page
    if 0 <= page:
        canvas.itemconfig(labelimg, image=img[page])
        page -= 1

# ~Omission~ # 
if __name__ == '__main__':
    th = Thread(target=rcv_comment)
    th.setDaemon(True)
    th.start()
    root.bind("<Key-n>", next) #Attribuez la clé ici
    root.bind("<Key-p>", prev)
    root.mainloop()

Implémentation de la fonction de pointeur

Il n'est pas implémenté car je suis inquiet de sélectionner celui à utiliser comme dispositif de pointeur. Je l'ajouterai dès sa mise en œuvre. Un smartphone est-il bon après tout?

Tâche

À la fin

J'écris du code en colère qui n'est pas du tout emballé ... Les performances ne sont pas bonnes lorsqu'un grand nombre de commentaires affluent. Je pense qu'il serait sage de l'afficher en superposition.

Recommended Posts

Système de support de présentation avec Python3
Créer un système de recommandation avec python
Commerce système à partir de Python3: investissement à long terme
FizzBuzz en Python3
Grattage avec Python
Statistiques avec python
Grattage avec Python
Python avec Go
"Commerce du système à partir de Python3" lecture du mémo
Twilio avec Python
Intégrer avec Python
Jouez avec 2016-Python
AES256 avec python
Testé avec Python
python commence par ()
avec syntaxe (Python)
Bingo avec python
Zundokokiyoshi avec python
Excel avec Python
Micro-ordinateur avec Python
Cast avec python
Extraire le zip avec Python (prend en charge les noms de fichiers japonais)
Trading système commençant par Python 3: investissement et risque
Communication série avec Python
Zip, décompressez avec python
Django 1.11 a démarré avec Python3.6
Jugement des nombres premiers avec Python
Python avec eclipse + PyDev.
Communication de socket avec Python
Analyse de données avec python 2
Grattage en Python (préparation)
Essayez de gratter avec Python.
Apprendre Python avec ChemTHEATER 03
Recherche séquentielle avec Python
"Orienté objet" appris avec python
Exécutez Python avec VBA
Manipuler yaml avec python
Résolvez AtCoder 167 avec python
[Python] Utiliser JSON avec Python
Apprendre Python avec ChemTHEATER 05-1
Apprenez Python avec ChemTHEATER
Exécutez prepDE.py avec python3
1.1 Premiers pas avec Python
Collecter des tweets avec Python
Binarisation avec OpenCV / Python
3. 3. Programmation IA avec Python
Non bloquant avec Python + uWSGI
Grattage avec Python + PhantomJS
Publier des tweets avec python
Conduisez WebDriver avec python
Utiliser mecab avec Python 3
[Python] Redirection avec CGIHTTPServer
Analyse vocale par python
Pensez à yaml avec python
Utiliser Kinesis avec Python
Premiers pas avec Python
Utiliser DynamoDB avec Python
Gérez Excel avec python
Loi d'Ohm avec Python
Jugement des nombres premiers avec python
Exécutez Blender avec python