<filename>Random Python Projects/kahoot_bot.py
import ctypes
import random
from threading import Thread
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import time
from tkinter import ttk
from threading import Thread
import tkinter


class KahootPlayer:

    def __init__(self, gamepin, name, gameplan):
        self.score = '0'
        self.connected = tkinter.StringVar()
        self.connected.set('Not Connected')
        self._GAMEPIN = gamepin  # https://www.python.org/dev/peps/pep-0008/#constants
        self._GAMEPLAN = gameplan
        self.name = name
        self.thread = Thread(target=self._join)
        self.thread.start()

    def _join(self):
        """
        Method that makes the user join the game with a given name.
        :return: None
        """
        chrome_options = Options()
        chrome_options.add_argument("--disable-extensions")
        chrome_options.add_argument("--disable-gpu")
        chrome_options.add_argument("--enable-javascript")
        chrome_options.add_argument("--headless")

        # Remember to add the path we install chromium to the ()

        self._DRIVER = webdriver.Chrome(r'C:\Users\norel\Desktop\chrome-win\chromedriver.exe', options=chrome_options)
        # Connect to the website
        self._DRIVER.get('https://kahoot.it/')
        pin_input = self._DRIVER.find_element_by_xpath('/html/body/div/div/div/div/main/div/form/input')
        pin_input.send_keys(self._GAMEPIN)

        pin_button = self._DRIVER.find_element_by_xpath('/html/body/div/div/div/div/main/div/form/button')
        pin_button.click()

        time.sleep(4)

        name_input = self._DRIVER.find_element_by_xpath('/html/body/div/div/div/div/main/div/form/input')
        name_input.send_keys(self.name)

        name_button = self._DRIVER.find_element_by_xpath('/html/body/div/div/div/div/main/div/form/button')
        name_button.click()

        gui.bot_list_box.item(self.name, values=[self._GAMEPLAN, 'Connected to ' + self._GAMEPIN, self.score])

        # Remember to allow autopilot
        if self._GAMEPLAN == 'autopilot':
            # doing auto pilot
            time.sleep(2)
            while True:
                buttons = self._DRIVER.find_elements_by_xpath('//button')
                if len(buttons) > 0:
                    buttons[random.randint(0, len(buttons) - 1)].click()
                time.sleep(1)
                if self._DRIVER.current_url == 'https://kahoot.it/v2/answer/result':
                    score = self._DRIVER.find_element_by_xpath("""//div[2][@data-functional-selector='player-total-score']""")
                    self.score = score.get_attribute('textContent')
                    print(self.score)
                    gui.bot_list_box.item(self.name, values=[self._GAMEPLAN, 'Connected to ' + self._GAMEPIN, self.score])

        else:
            gameplan = self._GAMEPLAN.lower()
            if gameplan == 'red - 1':
                n = 0  # red...

            elif gameplan == 'blue - 2':
                n = 1  # red...

            elif gameplan == 'yellow - 3':
                n = 2  # red...

            elif gameplan == 'green - 4':
                n = 3  # red...

            else:
                n = 0
            time.sleep(2)
            while True:
                buttons = self._DRIVER.find_elements_by_xpath('//button')
                if len(buttons) > 0:
                    try:
                        buttons[n].click()
                    except IndexError:
                        buttons[0].click()
                time.sleep(1)
                if self._DRIVER.current_url == 'https://kahoot.it/v2/answer/result':
                    self.score = self._DRIVER.find_element_by_xpath("""//div[2][@data-functional-selector='player-total-score']/text()""")
                    gui.bot_list_box.item(self.name, values=[self._GAMEPLAN, 'Connected to ' + self._GAMEPIN, self.score])

    def leave(self):
        self._DRIVER.close()
        print(self._DRIVER.name + " has been closed!")

    def saveplayer(self):
        """
        :return: None
        """
        return NotImplemented


class GUI:
    def __init__(self, window):
        self.bots = []
        self.window = window
        self.window.title('Kahoot Smasher')
        self.window.protocol('WM_DELETE_WINDOW', self.on_close)

        self.top_frame = tkinter.Frame(self.window)
        self.top_frame.pack(pady=(30, 10), padx=(20, 20))

        self.top_frame_toolbar = tkinter.Frame(self.top_frame)
        self.top_frame_toolbar.pack(side=tkinter.BOTTOM, fill='both', padx=(0, 5), pady=(5, 5))

        self.add_bot_button = tkinter.Button(self.top_frame_toolbar, text='Add Bot', command=self.add_bot_w)
        self.add_bot_button.grid(row=0, column=2, sticky='W')

        self.set_pin_entry = tkinter.Entry(self.top_frame_toolbar)
        self.set_pin_entry.grid(row=0, column=1, sticky='W', padx=(0,5))

        self.connected_label = tkinter.Label(self.top_frame_toolbar, text='Connected PIN: ')
        self.connected_label.grid(row=0, column=0, sticky='W')

        self.bot_list_scrollbar = tkinter.Scrollbar(self.top_frame)
        self.bot_list_scrollbar.pack(side=tkinter.RIGHT, fill='both')

        self.bot_list_box = ttk.Treeview(self.top_frame, yscrollcommand=self.bot_list_scrollbar.set,
                                         columns=['COLUMN1', 'COLUMN2', 'COLUMN3'])
        self.bot_list_box.heading('#0', text='Name')
        self.bot_list_box.heading('COLUMN1', text='Mode')
        self.bot_list_box.heading('COLUMN2', text='Status')
        self.bot_list_box.heading('COLUMN3', text='Score')
        self.bot_list_box.pack(side=tkinter.LEFT, fill='both')
        self.bot_list_scrollbar.config(command=self.bot_list_box.yview)

    def on_close(self):
        for bot in self.bots:
            bot.leave()
        self.window.destroy()


    def add_bot_w(self):
        add_bot_window = tkinter.Toplevel(self.window)

        namelbl = tkinter.Label(add_bot_window, text='Name: ')
        namelbl.grid(row=0, column=0, padx=(5, 5), pady=(5, 5))

        nameinput = tkinter.Entry(add_bot_window)
        nameinput.grid(row=0, column=1, padx=(5, 5), pady=(5, 5))

        modelbl = tkinter.Label(add_bot_window, text='Mode: ')
        modelbl.grid(row=1, column=0, padx=(5, 5), pady=(10, 5))

        modeinput = ttk.Combobox(add_bot_window, values=['Random', 'Red - 1', 'Blue - 2', 'Green - 3', 'Yellow - 4'], state='readonly')
        modeinput.grid(row=1, column=1, padx=(5, 5), pady=(10, 5))
        modeinput.current(0)  # Set the default mode

        amount_of_bots_label = tkinter.Label(add_bot_window, text='How many bots would you like:')
        amount_of_bots_label.grid(row=2, column=0, padx=(5, 5), pady=(10, 5))

        amount_of_bots = ttk.Combobox(add_bot_window, values=[x for x in range(1, 16)], state='readonly')
        amount_of_bots.grid(row=2, column=1, padx=(5, 5), pady=(10, 5))
        amount_of_bots.current(0)

        add_button = tkinter.Button(add_bot_window, text='Add',
                                    command=lambda: self.add_bot_to_tree(nameinput.get(), modeinput.get(), amount_of_bots.get(),
                                                                         add_bot_window))
        add_button.grid(row=3, column=0, padx=(5, 5), pady=(20, 5))

    def add_bot_to_tree(self, name, mode, amount, window):

        for bot in self.bots:
            if bot.name == name:
                ctypes.windll.user32.MessageBoxW(0, 'Please enter a different name', 'Name already exists', 1)
                return

        if mode == 'Random':
            mode = 'autopilot'

        if int(amount) > 1:
            window.destroy()
            name = name + ' 0'
            for x in range(int(amount)):
                name = ' '.join(name.split(' ')[:-1]) + ' ' + str(int(name.split(' ')[-1])+1)
                b = KahootPlayer(self.set_pin_entry.get(), name, mode)
                self.bot_list_box.insert('', 'end', iid=name, text=name, values=[mode, b.connected.get()])
                self.bots.append(b)
        else:
            b = KahootPlayer(self.set_pin_entry.get(), name, mode)
            self.bot_list_box.insert('', 'end', iid=name, text=name, values=[mode, b.connected.get()])
            self.bots.append(b)
            window.destroy()

window = tkinter.Tk()
gui = GUI(window)
window.mainloop()

