top of page

TwitchPlays_TEMPLATE.py
for Python 3.9.x
[ published on 2022-08-16 ]

  1. import concurrent.futures

  2. import random

  3. import keyboard

  4. import pydirectinput

  5. import pyautogui

  6. import TwitchPlays_Connection

  7. from TwitchPlays_KeyCodes import *

  8. ​

  9. ##################### GAME VARIABLES #####################

  10. ​

  11. # Replace this with your Twitch username. Must be all lowercase.

  12. TWITCH_CHANNEL = 'dougdoug' 

  13. ​

  14. # If streaming on Youtube, set this to False

  15. STREAMING_ON_TWITCH = True

  16.  

  17. # Replace this with your Youtube's Channel ID

  18. # Find this by clicking your Youtube profile pic -> Settings -> Advanced Settings

  19. YOUTUBE_CHANNEL_ID = "YOUTUBE_CHANNEL_ID_HERE" 

  20. ​

  21. # If you're using an Unlisted stream to test on Youtube, replace "None" below with your stream's URL in quotes.

  22. # Otherwise you can leave this as "None"

  23. YOUTUBE_STREAM_URL = None

  24. ​

  25. ##################### MESSAGE QUEUE VARIABLES #####################

  26. ​

  27. # MESSAGE_RATE controls how fast we process incoming Twitch Chat messages. It's the number of seconds it will take to handle all messages in the queue.

  28. # This is used because Twitch delivers messages in "batches", rather than one at a time. So we process the messages over MESSAGE_RATE duration, rather than processing the entire batch at once.

  29. # A smaller number means we go through the message queue faster, but we will run out of messages faster and activity might "stagnate" while waiting for a new batch. 

  30. # A higher number means we go through the queue slower, and messages are more evenly spread out, but delay from the viewers' perspective is higher.

  31. # You can set this to 0 to disable the queue and handle all messages immediately. However, then the wait before another "batch" of messages is more noticeable.

  32. MESSAGE_RATE = 0.5

  33. # MAX_QUEUE_LENGTH limits the number of commands that will be processed in a given "batch" of messages. 

  34. # e.g. if you get a batch of 50 messages, you can choose to only process the first 10 of them and ignore the others.

  35. # This is helpful for games where too many inputs at once can actually hinder the gameplay.

  36. # Setting to ~50 is good for total chaos, ~5-10 is good for 2D platformers

  37. MAX_QUEUE_LENGTH = 20

  38. MAX_WORKERS = 100 # Maximum number of threads you can process at a time 

  39.  

  40. last_time = time.time()

  41. message_queue = []

  42. thread_pool = concurrent.futures.ThreadPoolExecutor(max_workers=MAX_WORKERS)

  43. active_tasks = []

  44. pyautogui.FAILSAFE = False

  45. ​

  46. ##########################################################

  47. ​

  48. # Count down before starting, so you have time to load up the game

  49. countdown = 0

  50. while countdown > 0:

  51.     print(countdown)

  52.     countdown -= 1

  53.     time.sleep(1)

  54. ​

  55. if STREAMING_ON_TWITCH:

  56.     t = TwitchPlays_Connection.Twitch()

  57.     t.twitch_connect(TWITCH_CHANNEL)

  58. else:

  59.     t = TwitchPlays_Connection.YouTube()

  60.     t.youtube_connect(YOUTUBE_CHANNEL_ID, YOUTUBE_STREAM_URL)

  61. ​

  62. def handle_message(message):

  63.     try:

  64.         msg = message['message'].lower()

  65.         username = message['username'].lower()

  66. ​

  67.         print("Got this message from " + username + ": " + msg)

  68. ​

  69.         # Now that you have a chat message, this is where you add your game logic.

  70.         # Use the "HoldKey(KEYCODE)" function to permanently press and hold down a key.

  71.         # Use the "ReleaseKey(KEYCODE)" function to release a specific keyboard key.

  72.         # Use the "HoldAndReleaseKey(KEYCODE, SECONDS)" function press down a key for X seconds, then release it.

  73.         # Use the pydirectinput library to press or move the mouse

  74. ​

  75.         # I've added some example videogame logic code below:

  76. ​

  77.         ###################################

  78.         # Example GTA V Code 

  79.         ###################################

  80.  

  81.         # If the chat message is "left", then hold down the A key for 2 seconds

  82.         if msg == "left": 

  83.             HoldAndReleaseKey(A, 2)

  84. ​

  85.         # If the chat message is "right", then hold down the D key for 2 seconds

  86.         if msg == "right": 

  87.             HoldAndReleaseKey(D, 2)

  88.  

  89.         # If message is "drive", then permanently hold down the W key

  90.         if msg == "drive": 

  91.             ReleaseKey(S) #release brake key first

  92.             HoldKey(W) #start permanently driving

  93. ​

  94.         # If message is "reverse", then permanently hold down the S key

  95.         if msg == "reverse": 

  96.             ReleaseKey(W) #release drive key first

  97.             HoldKey(S) #start permanently reversing

  98. ​

  99.         # Release both the "drive" and "reverse" keys

  100.         if msg == "stop": 

  101.             ReleaseKey(W)

  102.             ReleaseKey(S)

  103. ​

  104.         # Press the spacebar for 0.7 seconds

  105.         if msg == "brake": 

  106.             HoldAndReleaseKey(SPACE, 0.7)

  107. ​

  108.         # Press the left mouse button down for 1 second, then release it

  109.         if msg == "shoot": 

  110.             pydirectinput.mouseDown(button="left")

  111.             time.sleep(1)

  112.             pydirectinput.mouseUp(button="left")

  113. ​

  114.         # Move the mouse up by 30 pixels

  115.         if msg == "aim up":

  116.             pydirectinput.moveRel(0, -30, relative=True)

  117. ​

  118.         # Move the mouse right by 200 pixels

  119.         if msg == "aim right":

  120.             pydirectinput.moveRel(200, 0, relative=True)

  121. ​

  122.         ####################################

  123.         ####################################

  124. ​

  125.     except Exception as e:

  126.         print("Encountered exception: " + str(e))

  127. ​

  128. ​

  129. while True:

  130. ​

  131.     active_tasks = [t for t in active_tasks if not t.done()]

  132. ​

  133.     #Check for new messages

  134.     new_messages = t.twitch_receive_messages();

  135.     if new_messages:

  136.         message_queue += new_messages; # New messages are added to the back of the queue

  137.         message_queue = message_queue[-MAX_QUEUE_LENGTH:] # Shorten the queue to only the most recent X messages

  138.  

  139.     messages_to_handle = []

  140.     if not message_queue:

  141.         # No messages in the queue

  142.         last_time = time.time()

  143.     else:

  144.         # Determine how many messages we should handle now

  145.         r = 1 if MESSAGE_RATE == 0 else (time.time() - last_time) / MESSAGE_RATE

  146.         n = int(r * len(message_queue))

  147.         if n > 0:

  148.             # Pop the messages we want off the front of the queue

  149.             messages_to_handle = message_queue[0:n]

  150.             del message_queue[0:n]

  151.             last_time = time.time();

  152.     # If user presses Shift+Backspace, automatically end the program

  153.     if keyboard.is_pressed('shift+backspace'):

  154.         exit()

  155. ​

  156.     if not messages_to_handle:

  157.         continue

  158.     else:

  159.         for message in messages_to_handle:

  160.             if len(active_tasks) <= MAX_WORKERS:

  161.                 active_tasks.append(thread_pool.submit(handle_message, message))

  162.             else:

  163.                 print(f'WARNING: active tasks ({len(active_tasks)}) exceeds number of workers

  164. ({MAX_WORKERS}). ({len(message_queue)} messages in the queue)')

End of Document

bottom of page