bot: first complete commit with task scheduling
parent
274aa63778
commit
0f606ccf5d
16
README.md
16
README.md
|
@ -1,2 +1,18 @@
|
|||
# GoogleMeetBot
|
||||
A bot to automatically join Google Meet meetings at the correct time
|
||||
|
||||
|
||||
## How it works
|
||||
The bot automates a FireFox session using Python and Selenium.<br>
|
||||
It joins the programmed google meetings automatically, with microphone and webcam disabled.<br>
|
||||
It uses the **schedule** python module to automatically access and close meetings at the given time, it can only join one meeting at the time<br>
|
||||
Normally Google Accounts are not allowed to be logged in when using an automated browser, but logging in via stackoverflow.com worksaround this problem<br>
|
||||
In case this is not working, you can disable such security feature in your google account settings. Some business and enterprise account may not have this problem by default
|
||||
|
||||
## Dependencies
|
||||
All python deps are listed in **requirements.txt**, just run<br>
|
||||
pip install -r requirements.txt
|
||||
|
||||
## Add your own meetings
|
||||
To add your own meetings into **meetings.py**, adding another <em>scheduleMeeting</em> line like the one already present. You can add as many as you want, but remember that this bot does not support joining multiple meetings at the same time
|
||||
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
import sys
|
||||
import selenium
|
||||
import requests
|
||||
from selenium import webdriver
|
||||
from selenium.webdriver.support.ui import WebDriverWait
|
||||
from selenium.webdriver.support import expected_conditions as EC
|
||||
from selenium.common.exceptions import TimeoutException
|
||||
from selenium.webdriver.common.by import By
|
||||
import os
|
||||
from enum import Enum
|
||||
import threading
|
||||
from selenium.webdriver.common.keys import Keys
|
||||
from selenium.common.exceptions import NoSuchElementException
|
||||
|
||||
import time as t
|
||||
|
||||
|
||||
G_ACCOUNT_MAIL = None
|
||||
G_ACCOUNT_PASS = None
|
||||
|
||||
FIREFOX_DVD_DIR = "/usr/bin/geckodriver"
|
||||
|
||||
'''Locating by xpath here is the best thing to do here, since google Meet changes selectors, classes name and all that sort of stuff for every meeting
|
||||
XPaths remaing the same, but a slight change by them would make this program fail.
|
||||
The xpath is found clicking by inspecting the element of the searched button, and finding the parent div tthat has role="button" tag
|
||||
'''
|
||||
|
||||
MIC_XPATH = '/html/body/div[1]/c-wiz/div/div/div[8]/div[3]/div/div/div[2]/div/div[1]/div[1]/div[1]/div/div[3]/div[1]/div/div/div'
|
||||
WEBCAM_XPATH = '/html/body/div[1]/c-wiz/div/div/div[8]/div[3]/div/div/div[2]/div/div[1]/div[1]/div[1]/div/div[3]/div[2]/div/div'
|
||||
JOIN_XPATH = '/html/body/div[1]/c-wiz/div/div/div[8]/div[3]/div/div/div[2]/div/div[1]/div[2]/div/div[2]/div/div/div[1]'
|
||||
OPTION_XPATH = '/html/body/div[1]/c-wiz/div/div/div[6]/div[3]/div/div/div[2]/div/div[1]/div[1]/div[1]/div/div[4]/div'
|
||||
|
||||
CHAT_BTN_XPATH = '/html/body/div[1]/c-wiz/div[1]/div/div[6]/div[3]/div[6]/div[3]/div/div[2]/div[3]'
|
||||
CHAT_SELECTCHAT_BTN_XPATH = '/html/body/div[1]/c-wiz/div[1]/div/div[6]/div[3]/div[3]/div/div[2]/div[2]/div[1]/div[2]'
|
||||
|
||||
#Using tagname for text area because xpath doesn't really work, and we're sure it's the only textarea on the webpage
|
||||
CHAT_TEXT_XPATH = "textarea"
|
||||
|
||||
HANG_UP_BTN_XPATH = '/html/body/div[1]/c-wiz/div[1]/div/div[8]/div[3]/div[9]/div[2]/div[2]/div'
|
||||
|
||||
CHAT_CLOSE_BTN_XPATH = '/html/body/div[1]/c-wiz/div[1]/div/div[6]/div[3]/div[3]/div/div[2]/div[1]/div[2]/div/button'
|
||||
|
||||
browser = None
|
||||
|
||||
def initFirefox():
|
||||
global browser, G_ACCOUNT_MAIL, G_ACCOUNT_PASS
|
||||
|
||||
print("Input your google account credentials. The information will not be stored anywhere and you will have to relogin everytime you restart this bot\n")
|
||||
G_ACCOUNT_MAIL = input("Type your email: ")
|
||||
G_ACCOUNT_PASS = input("Type your password: ")
|
||||
|
||||
#webdriver.FirefoxProfile('/home/emamaker/Documents/Projects/GoogleMeetBot/firefox_profile')
|
||||
browser = webdriver.Firefox()
|
||||
|
||||
def joinMeeting(link):
|
||||
global browser
|
||||
|
||||
if link == '':
|
||||
return
|
||||
|
||||
try:
|
||||
browser.get(link)
|
||||
t.sleep(15)
|
||||
print("Trying to join meeting")
|
||||
clickButton(By.XPATH, MIC_XPATH)
|
||||
clickButton(By.XPATH, WEBCAM_XPATH)
|
||||
clickButton(By.XPATH, JOIN_XPATH)
|
||||
except:
|
||||
# In this way, in case of any error we can try again
|
||||
print("Failed to join meeting, trying again in 60 secs")
|
||||
t.sleep(60)
|
||||
joinMeeting(link)
|
||||
|
||||
|
||||
def clickButton(by, selector):
|
||||
global browser
|
||||
WebDriverWait(browser, 5).until(EC.element_to_be_clickable((by, selector))).click()
|
||||
t.sleep(1)
|
||||
|
||||
def writeText(by, selector, text):
|
||||
WebDriverWait(browser, 5).until(EC.element_to_be_clickable((by, selector))).clear()
|
||||
WebDriverWait(browser, 5).until(EC.element_to_be_clickable((by, selector))).send_keys(text + "\n")
|
||||
|
||||
def sendChatMsg(text):
|
||||
global browser
|
||||
|
||||
#open chat menu
|
||||
clickButton(By.XPATH, CHAT_BTN_XPATH)
|
||||
#select chat option
|
||||
clickButton(By.XPATH, CHAT_SELECTCHAT_BTN_XPATH)
|
||||
#write msg
|
||||
writeText(By.TAG_NAME, CHAT_BTN_XPATH, text)
|
||||
t.sleep(1)
|
||||
#close chat
|
||||
clickButton(By.XPATH, CHAT_CLOSE_BTN_XPATH)
|
||||
|
||||
|
||||
def checkStarted():
|
||||
try:
|
||||
clickButton(By.XPATH, OPTION_XPATH)
|
||||
except:
|
||||
return False
|
||||
return True
|
||||
|
||||
def loginIntoGoogle():
|
||||
global browser
|
||||
browser.get("https://myaccount.google.com/?utm_source=sign_in_no_continue")
|
||||
t.sleep(3)
|
||||
#we can use selectors in this webside, since they're static
|
||||
#login button
|
||||
clickButton(By.CSS_SELECTOR, "li.h-c-header__cta-li:nth-child(2) > a:nth-child(1)")
|
||||
#login with google
|
||||
#clickButton(By.CSS_SELECTOR, "button.s-btn__icon:nth-child(1)")
|
||||
#write email
|
||||
writeText(By.CSS_SELECTOR, "#identifierId", G_ACCOUNT_MAIL)
|
||||
t.sleep(3)
|
||||
#write pwd
|
||||
writeText(By.XPATH, "/html/body/div[1]/div[1]/div[2]/div/div[2]/div/div/div[2]/div/div[1]/div/form/span/section/div/div/div[1]/div[1]/div/div/div/div/div[1]/div/div[1]/input", G_ACCOUNT_PASS)
|
||||
t.sleep(3)
|
||||
|
||||
def loginIntoGoogleWithStackOverflow():
|
||||
global browser
|
||||
browser.get("https://stackoverflow.com/users/login?ssrc=head&returnurl=https%3a%2f%2fstackoverflow.com%2f")
|
||||
t.sleep(3)
|
||||
#we can use selectors in this webside, since they're static
|
||||
#login with google
|
||||
clickButton(By.CSS_SELECTOR, "#openid-buttons > button.grid--cell.s-btn.s-btn__icon.s-btn__google.bar-md.ba.bc-black-100")
|
||||
#login button
|
||||
#write email
|
||||
writeText(By.CSS_SELECTOR, "#identifierId", G_ACCOUNT_MAIL)
|
||||
t.sleep(3)
|
||||
#write pwd
|
||||
writeText(By.XPATH, "/html/body/div[1]/div[1]/div[2]/div/div[2]/div/div/div[2]/div/div[1]/div/form/span/section/div/div/div[1]/div[1]/div/div/div/div/div[1]/div/div[1]/input", G_ACCOUNT_PASS)
|
||||
t.sleep(3)
|
||||
|
||||
def hangUpMeeting():
|
||||
clickButton(By.XPATH, HANG_UP_BTN_XPATH)
|
|
@ -0,0 +1,19 @@
|
|||
'''Automatically join Google Meet meetings, with muted camera and mic
|
||||
Just give link and it joins. Features chat too
|
||||
Planning on adding a schedule system'''
|
||||
|
||||
import meetings
|
||||
import browser_manager
|
||||
import schedule
|
||||
import time
|
||||
|
||||
browser_manager.initFirefox()
|
||||
browser_manager.loginIntoGoogleWithStackOverflow()
|
||||
#while checkStarted() is False:
|
||||
#browser.sendChatMsg("hello world")
|
||||
|
||||
meetings.setup_schedule()
|
||||
|
||||
while True:
|
||||
schedule.run_pending()
|
||||
time.sleep(1)
|
|
@ -0,0 +1,30 @@
|
|||
import time as t
|
||||
import schedule
|
||||
import browser_manager
|
||||
|
||||
def setup_schedule():
|
||||
scheduleMeeting("friday", "21:20", "21:22", "https://meet.google.com/jqn-fgav-aad")
|
||||
|
||||
|
||||
def scheduleMeeting(day, startHour, endHour, link):
|
||||
if str(day).lower() == "monday":
|
||||
schedule.every().monday.at(startHour).do(browser_manager.joinMeeting, link)
|
||||
schedule.every().monday.at(endHour).do(browser_manager.hangUpMeeting)
|
||||
elif str(day).lower() == "tuesday":
|
||||
schedule.every().tuesday.at(startHour).do(browser_manager.joinMeeting, link)
|
||||
schedule.every().tuesday.at(endHour).do(browser_manager.hangUpMeeting)
|
||||
elif str(day).lower() == "wednesday":
|
||||
schedule.every().wednesday.at(startHour).do(browser_manager.joinMeeting, link)
|
||||
schedule.every().wednesday.at(endHour).do(browser_manager.hangUpMeeting)
|
||||
elif str(day).lower() == "thursday":
|
||||
schedule.every().thursday.at(startHour).do(browser_manager.joinMeeting, link)
|
||||
schedule.every().thursday.at(endHour).do(browser_manager.hangUpMeeting)
|
||||
elif str(day).lower() == "friday":
|
||||
schedule.every().friday.at(startHour).do(browser_manager.joinMeeting, link)
|
||||
schedule.every().friday.at(endHour).do(browser_manager.hangUpMeeting)
|
||||
elif str(day).lower() == "saturday":
|
||||
schedule.every().saturday.at(startHour).do(browser_manager.joinMeeting, link)
|
||||
schedule.every().saturday.at(endHour).do(browser_manager.hangUpMeeting)
|
||||
elif str(day).lower() == "sunday":
|
||||
schedule.every().sunday.at(startHour).do(browser_manager.joinMeeting, link)
|
||||
schedule.every().sunday.at(endHour).do(browser_manager.hangUpMeeting)
|
|
@ -0,0 +1,83 @@
|
|||
import time as t
|
||||
import schedule
|
||||
import browser_manager
|
||||
|
||||
''' STORE MEET LINKS HERE'''
|
||||
MATHS = 'https://meet.google.com/lookup/fn2tkngzid?authuser=0&hs=179'
|
||||
LITERATURE = 'https://meet.google.com/lookup/bhoqky4qee?authuser=0&hs=179'
|
||||
ENGLISH = 'https://meet.google.com/lookup/hlj4rhyj4p?authuser=0&hs=179'
|
||||
ELECTRONICS = 'https://meet.google.com/lookup/ehuwfglxvr?authuser=0&hs=179'
|
||||
SYSTEMS = ''
|
||||
TPSEE = 'https://meet.google.com/lookup/bc4r2d32ua?authuser=0&hs=179'
|
||||
TPSEE_ELT = 'https://meet.google.com/lookup/gdaq3kmguh?authuser=0&hs=179'
|
||||
TPSEE_SYS = 'https://meet.google.com/lookup/gdaq3kmguh?authuser=0&hs=179'
|
||||
ELT_SYSTEMS = ''
|
||||
|
||||
|
||||
'''TIME SCHEDULE - START AND FINISH'''
|
||||
FIRST_HOUR = "8:00"
|
||||
SECOND_HOUR = "8:50"
|
||||
THIRD_HOUR = "9:50"
|
||||
FOURTH_HOUR = "10:50"
|
||||
FIFTH_HOUR = "11:50"
|
||||
SIXTH_HOUR = "12:40"
|
||||
SEVENTH_HOUR = "13:40"
|
||||
|
||||
def setup_schedule():
|
||||
#scheduleMeeting("friday", "20:56", "20:57", "https://meet.google.com/jqn-fgav-aad")
|
||||
|
||||
# Monday schedule
|
||||
scheduleMeeting("monday", FIRST_HOUR, SECOND_HOUR, TPSEE)
|
||||
scheduleMeeting("monday", SECOND_HOUR, THIRD_HOUR, ENGLISH)
|
||||
scheduleMeeting("monday", THIRD_HOUR, FOURTH_HOUR, SYSTEMS)
|
||||
scheduleMeeting("monday", FOURTH_HOUR, FIFTH_HOUR, MATHS)
|
||||
scheduleMeeting("monday", FIFTH_HOUR, SEVENTH_HOUR, LITERATURE)
|
||||
|
||||
# Tuesday schedule
|
||||
scheduleMeeting("tuesday", FIRST_HOUR, THIRD_HOUR, SYSTEMS)
|
||||
scheduleMeeting("tuesday", THIRD_HOUR, FIFTH_HOUR, ELECTRONICS)
|
||||
scheduleMeeting("tuesday", FIFTH_HOUR, SIXTH_HOUR, TPSEE_ELT)
|
||||
scheduleMeeting("tuesday", SIXTH_HOUR, SEVENTH_HOUR, TPSEE)
|
||||
|
||||
# Wednesday schedule
|
||||
scheduleMeeting("wednesday", FIRST_HOUR, SECOND_HOUR, ELT_SYSTEMS)
|
||||
scheduleMeeting("wednesday", SECOND_HOUR, THIRD_HOUR, MATHS)
|
||||
scheduleMeeting("wednesday", THIRD_HOUR, FOURTH_HOUR, LITERATURE)
|
||||
scheduleMeeting("wednesday", SIXTH_HOUR, SEVENTH_HOUR, LITERATURE)
|
||||
|
||||
# Thursday schedule
|
||||
scheduleMeeting("thursday", FIRST_HOUR, SECOND_HOUR, ELECTRONICS)
|
||||
scheduleMeeting("thursday", SECOND_HOUR, THIRD_HOUR, ENGLISH)
|
||||
scheduleMeeting("thursday", FOURTH_HOUR, FIFTH_HOUR, TPSEE)
|
||||
scheduleMeeting("thursday", FIFTH_HOUR, SIXTH_HOUR, TPSEE_SYS)
|
||||
scheduleMeeting("thursday", SIXTH_HOUR, SEVENTH_HOUR, SYSTEMS)
|
||||
|
||||
# Friday schedule
|
||||
scheduleMeeting("friday", FIRST_HOUR, SECOND_HOUR, MATHS)
|
||||
scheduleMeeting("friday", SECOND_HOUR, THIRD_HOUR, ENGLISH)
|
||||
scheduleMeeting("friday", FOURTH_HOUR, FIFTH_HOUR, LITERATURE)
|
||||
scheduleMeeting("friday", FIFTH_HOUR, SIXTH_HOUR, LITERATURE)
|
||||
scheduleMeeting("friday", SIXTH_HOUR, SEVENTH_HOUR, TPSEE)
|
||||
|
||||
def scheduleMeeting(day, startHour, endHour, link):
|
||||
if str(day).lower() == "monday":
|
||||
schedule.every().monday.at(startHour).do(browser_manager.joinMeeting, link)
|
||||
schedule.every().monday.at(endHour).do(browser_manager.hangUpMeeting)
|
||||
elif str(day).lower() == "tuesday":
|
||||
schedule.every().tuesday.at(startHour).do(browser_manager.joinMeeting, link)
|
||||
schedule.every().tuesday.at(endHour).do(browser_manager.hangUpMeeting)
|
||||
elif str(day).lower() == "wednesday":
|
||||
schedule.every().wednesday.at(startHour).do(browser_manager.joinMeeting, link)
|
||||
schedule.every().wednesday.at(endHour).do(browser_manager.hangUpMeeting)
|
||||
elif str(day).lower() == "thursday":
|
||||
schedule.every().thursday.at(startHour).do(browser_manager.joinMeeting, link)
|
||||
schedule.every().thursday.at(endHour).do(browser_manager.hangUpMeeting)
|
||||
elif str(day).lower() == "friday":
|
||||
schedule.every().friday.at(startHour).do(browser_manager.joinMeeting, link)
|
||||
schedule.every().friday.at(endHour).do(browser_manager.hangUpMeeting)
|
||||
elif str(day).lower() == "saturday":
|
||||
schedule.every().saturday.at(startHour).do(browser_manager.joinMeeting, link)
|
||||
schedule.every().saturday.at(endHour).do(browser_manager.hangUpMeeting)
|
||||
elif str(day).lower() == "sunday":
|
||||
schedule.every().sunday.at(startHour).do(browser_manager.joinMeeting, link)
|
||||
schedule.every().sunday.at(endHour).do(browser_manager.hangUpMeeting)
|
|
@ -0,0 +1,2 @@
|
|||
selenium
|
||||
schedule
|
Loading…
Reference in New Issue