Twitch joue Pokemon fait irruption sur la scène naissante de la diffusion en direct en 2014, permettant aux téléspectateurs de Twitch de prendre le contrôle d’un émulateur Game Boy exécutant Pokemon Red via de simples commandes de chat. Depuis, le même concept a été appliqué à tout sous le soleil. D’autres jeux vidéo, l’installation de Linux et même le trading à la Bourse de New York ont ​​tous été gameifiés via le chat Twitch.

TwitchPlaysPokémon a commencé un engouement pour le contrôle participatif des jeux vidéo, des robots et à peu près tout le reste.

Vous, lecteur assoiffé, vous vous demandez comment obtenir une part de cette délicieuse action. N’ayez crainte, car avec un peu de code délabré, vous pouvez laisser le chat Twitch prendre en charge à peu près tout ce qui se trouve dans, sur ou autour de votre ordinateur.

C’est juste IRC

L’avantage du chat Twitch est qu’il fonctionne sur IRC vanilla (Internet Relay Chat). Le protocole existe depuis toujours et des bibliothèques existent pour faciliter l’interfaçage. Tout comme le streamer original derrière Twitch Plays Pokemon, nous allons utiliser Python car il est idéal pour de petites expériences amusantes comme celles-ci. Cela dit, n’importe quel langage fera l’affaire – appliquez simplement les mêmes techniques dans la syntaxe appropriée.

SimpleTwitchCommander, comme je l’ai nommé sur Github, suppose une certaine familiarité avec la programmation Python de base. Le code vous permettra de prendre des commandes du chat de deux manières. Les commandes du chat peuvent être tabulées, et seule celle avec le plus de votes exécutée, ou chaque commande peut être exécutée directement. En fait, obtenir ce code pour contrôler votre robot, votre jeu vidéo ou votre vipère de compagnie dépend de vous. Ce que nous faisons ici, c’est l’interfaçage avec le chat Twitch et l’extraction de commandes afin que vous puissiez lui faire faire ce que vous voulez. Cela dit, pour cet exemple, nous avons configuré le code pour analyser les commandes d’un simple robot à roues. Plongeons-nous.

Code à pied

import socket
from emoji import demojize
from apscheduler.schedulers.background import BackgroundScheduler
Avec ce code, vous pouvez également regarder des personnes aléatoires sur Internet conduire votre robot directement dans un buisson.

La première chose à faire dans notre code est d’importer les bibliothèques dont nous avons besoin. Les bibliothèques sont géniales, ce sont des cadeaux de programmeurs talentueux qui nous facilitent la vie – ou du moins nous l’espérons. Nous utilisons quatre bibliothèques dans ce cas, mais vous pouvez vous en tirer uniquement avec les trois premières en fonction de votre application. Le premier, et peut-être le plus important, est le socket bibliothèque, qui gère toutes nos communications réseau. le emoji La bibliothèque nous fournit un outil soigné pour supprimer les emojis des messages de chat, car ils peuvent devenir désordonnés. APScheduler est utilisé pour notre système de vote par commande, qui permet aux utilisateurs de Twitch de voter sur l’action souhaitée plutôt que de simplement laisser passer chaque commande Twitch.

class TwitchControl:

Cette instruction configure la classe pour notre programme.

def __init__(self):
    self.server="irc.chat.twitch.tv"
    self.port = 6667
    self.nickname="yourtwitchusername"
    self.token = 'oauth:youroauthkeyhere'
    self.channel="#yourtwitchchannel"

    self.sched = BackgroundScheduler()

    self.sock = socket.socket()
    self.sock.connect((self.server,self.port))
    self.sock.send(f"PASS {self.token}n".encode('utf-8'))
    self.sock.send(f"NICK {self.nickname}n".encode('utf-8'))
    self.sock.send(f"JOIN {self.channel}n".encode('utf-8'))

__init__() est une routine Python spéciale appelée lorsqu’un objet est créé à partir d’une classe. En termes clairs, quand nous appelons TwitchControl, le code dans __init__() s’exécute en premier. Ici, nous créons des variables qui stockent l’adresse du serveur de chat de Twitch, le port, ainsi que nos informations de connexion et de chaîne Twitch. Le jeton oauth est la façon dont le serveur Twitch sait qui se connecte au canal de discussion, et vous pouvez générer le vôtre ici.

    self.voteDict = {"null": 0, "fwd" : 0, "rev" : 0, "left" : 0, "right" : 0}    

Ensuite, nous créons une variable spéciale appelée dictionnaire, et lui donnons le nom voteDict. Les dictionnaires sont excellents, car ils nous permettent de stocker des données par petites paires. Dans notre cas, nous avons nos commandes souhaitées, et chacune a un numéro à côté. Cela correspondra au nombre de votes pour chaque commande dans le chat. Nous les initialisons à 0 pour commencer.

    self.sched.add_job(self.voteCount, 'interval', seconds=2)
    self.sched.start()

Les lignes ci-dessus mis en place APscheduler pour exécuter une fonction à intervalles réguliers de 2 secondes. Cette fonction porte le nom voteCount, et à chaque intervalle de deux secondes, il vérifie voteDict pour voir quelle commande a obtenu le plus de votes dans le chat, puis exécute le gagnant. Nous reviendrons et examinerons voteCount dans un instant. Pour l’instant, regardons la boucle principale qui s’exécute une fois que tout est initialisé.

def loop(self):
    while True:
        resp = self.sock.recv(2048).decode('utf-8')
        if resp.startswith('PING'):
            self.sock.send("PONGn".encode('utf-8'))
        elif len(resp) > 0:
            respClean = demojize(resp)
            print(respClean)
            msgComponents=respClean.split(" ",3)

            msgUser=msgComponents[0] #get username from message
            msgUser = msgUser[msgUser.find(':')+1: msgUser.find('!')]
            msgContent=msgComponents[3] #print message content

Une fois que nous entrons dans la boucle while, nous devons recevoir des données du serveur IRC. Si les données sont « PING », nous répondons par « PONG » selon la pratique IRC typique pour maintenir la connexion active. Sinon, nous nettoyons les données avec la fonction demojize, qui remplace tous les émoticônes du message par du texte brut. Ensuite, nous utilisons des fonctions de chaîne pour diviser le message brut du serveur en ses composants: le nom d’utilisateur qui a envoyé le message et le contenu réel du message. À ce stade, nous pouvons rechercher directement une commande, et si nous voulons que cela déclenche directement les messages, nous pouvons le faire ici.

            if msgContent.find("LIGHTS") >=0:
                print("Turning Lights On!") 
                #code to turn lights on here

Alternativement, si nous voulons collecter des commandes dans le chat et voir laquelle est votée la plus populaire, nous pouvons le faire aussi. Chaque fois qu’une des commandes suivantes est détectée, son champ correspondant dans le voteDict le dictionnaire est incrémenté de 1.

            if msgContent.find("FWD") >=0:
                self.voteDict["fwd"] = self.voteDict["fwd"] +1
            if msgContent.find("REV") >=0:
                self.voteDict["rev"] = self.voteDict["rev"] +1
            if msgContent.find("LEFT") >=0:
                self.voteDict["left"] = self.voteDict["left"] +1
            if msgContent.find("RIGHT") >=0:
                self.voteDict["right"] = self.voteDict["right"] +1

C’est tout ce que fait notre boucle principale. Il reçoit les données du serveur IRC au fur et à mesure de leur entrée, les traite et incrémente le nombre de votes des commandes entrantes. Pour agir réellement sur ces votes, nous devons aller à notre voteCount une fonction. Grace à APscheduler routine que nous avons configurée auparavant, elle s’exécute automatiquement toutes les deux secondes.

def voteCount(self): #function responsible for checking votes and executing commands
    print('Counting votes and executing command')
    voteWinner = max(self.voteDict, key=self.voteDict.get)
    print("biggest vote:" + voteWinner)
    nullCheck=all(x==0 for x in self.voteDict.values())

    if nullCheck:
        print('doing a nullo')

    elif voteWinner=="fwd":
        print('going Forward')
        #code to go forward here
    elif voteWinner=="rev":
        print('going Reverse')
        #code to go reverse here
    elif voteWinner=="left":
        print('going Left')
        #code to go left here
    elif voteWinner=="right":
        print('going Right')
        #code to go right here
    self.voteDict = {"null" : 0, "fwd" : 0, "rev" : 0, "left" : 0, "right" : 0}

voteCount est une fonction simple, qui utilise les fonctions de dictionnaire intégrées de Python pour déterminer la commande qui a eu le plus de votes. Notez que nous vérifions également si tous les votes sont égaux à zéro – dans ce cas, nous ne devons rien faire, d’où le code nullCheck. Une fois que le gagnant est déterminé, le code de la commande correspondante peut être exécuté.

Que vas-tu libérer sur Twitch?

Il y a un peu plus de passe-partout pour enchaîner les choses, mais fondamentalement, ce sont les blocs qui font que tout fonctionne. Prenez la vraie chose de Github si vous souhaitez bricoler à la maison. De toute évidence, à partir de là, c’est simplement une question de personnalisation pour façonner le code en fonction de votre objectif particulier. Si vous cherchez à contrôler un robot, placez vos commandes pour les servos ou les moteurs aux endroits nécessaires, ou envoyez des instructions en série à votre microcontrôleur qui gère ces tâches. Sinon, si vous travaillez avec un jeu dans un émulateur, demandez au code Python d’émuler simplement les pressions sur les boutons appropriés.

Le code n’est en aucun cas optimisé; l’écriture de cet article a pris environ deux fois plus de temps que l’écriture du code lui-même. Il y a probablement d’énormes gains à faire en utilisant un code de gestion de chaînes plus idéalisé et d’autres ajustements de ce type. Un travail supplémentaire pour emballer tout cela dans une bibliothèque soignée est laissé comme un exercice pour le lecteur. J’espère que cela vous permettra de vous amuser en crowdsourcing sur Twitch! Comme toujours, bon piratage.