Skip to content

Commit

Permalink
Update reset commit
Browse files Browse the repository at this point in the history
  • Loading branch information
pydevcasts committed Nov 10, 2024
1 parent 870dadb commit 16aa183
Show file tree
Hide file tree
Showing 11 changed files with 425 additions and 0 deletions.
47 changes: 47 additions & 0 deletions src/AI.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import requests

class AIResponse:
def __init__(self, api_key):
self.api_key = api_key

def get_ai_answer(self, question):
url = 'https://api.aimlapi.com/v1/chat/completions'
headers = {
'Authorization': f'Bearer {self.api_key}',
'Content-Type': 'application/json'
}
payload = {
'text': question
}

try:
response = requests.post(url, headers=headers, json=payload)
response.raise_for_status() # will raise an error for 4xx/5xx responses
result = response.json()
return result.get('answer', 'AI could not provide an answer.')
except requests.exceptions.HTTPError as http_err:
print(f"HTTP error occurred: {http_err}")
return 'AI API error: Unable to get a response.'
except Exception as err:
print(f"Other error occurred: {err}")
return 'AI API error: Unable to get a response.'

















# [email protected]
# Poing1981@
# https://meet.google.com/ikb-byyj-bui
27 changes: 27 additions & 0 deletions src/auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# auth.py
import time
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

class Authenticator:
def __init__(self, driver, email, password):
self.driver = driver
self.email = email
self.password = password

def login(self):
try:
self.driver.get('https://accounts.google.com/ServiceLogin')
self.driver.find_element(By.ID, "identifierId").send_keys(self.email)
self.driver.find_element(By.ID, "identifierNext").click()

password_field = WebDriverWait(self.driver, 10).until(
EC.element_to_be_clickable((By.XPATH, '//*[@id="password"]/div[1]/div/div[1]/input')))
password_field.send_keys(self.password)

WebDriverWait(self.driver, 10).until(EC.url_contains("google.com"))
print("Login successful!")
except Exception as e:
print(f"Error during login: {e}")
self.driver.quit()
22 changes: 22 additions & 0 deletions src/controls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# controls.py
import time
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException

class MeetControls:
def __init__(self, driver):
self.driver = driver

def turn_off_mic_cam(self):
try:
time.sleep(5)
mic_button = WebDriverWait(self.driver, 10).until(
EC.element_to_be_clickable((By.XPATH, '//*[contains(concat(" ", @class, " "), concat(" ", "crqnQb", " "))]')))
mic_button.click()
print("Microphone turned off.")
except TimeoutException:
print("TimeoutException: Element not found or not clickable within specified time.")
except Exception as e:
print(f"An error occurred while turning off mic/cam: {e}")
21 changes: 21 additions & 0 deletions src/driver_setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# driver_setup.py
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options

def setup_driver():
options = Options()
options.add_argument('--disable-blink-features=AutomationControlled')
options.add_argument('--start-maximized')
options.add_experimental_option("prefs", {
"profile.default_content_setting_values.media_stream_mic": 1,
"profile.default_content_setting_values.media_stream_camera": 1,
"profile.default_content_setting_values.geolocation": 0,
"profile.default_content_setting_values.notifications": 1
})

# You can also specify the path to your ChromeDriver if needed
# service = Service('/path/to/chromedriver')
# return webdriver.Chrome(service=service, options=options)

return webdriver.Chrome(options=options)
Binary file added src/google-meet-icon.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
49 changes: 49 additions & 0 deletions src/google_meet_bot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# google_meet_bot.py
import time
import threading
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
from driver_setup import setup_driver
from translator import TextTranslator
from question_checker import QuestionChecker
from AI import AIResponse
from auth import Authenticator # Import the Authenticator class
from controls import MeetControls # Import the MeetControls class
from subtitle_saver import SubtitleSaver # Import the SubtitleSaver class

class GoogleMeetBot:
def __init__(self, email, password, api_key, ai_api_key, update_signal):
self.email = email
self.password = password
self.api_key = api_key
self.ai_response = AIResponse(ai_api_key)
self.driver = setup_driver()
self.translator = TextTranslator()
self.question_checker = QuestionChecker(api_key)
self.authenticator = Authenticator(self.driver, self.email, self.password)
self.controls = MeetControls(self.driver) # Initialize MeetControls
self.subtitle_saver = SubtitleSaver(self.driver, self.translator, self.question_checker, update_signal)

def login(self):
self.authenticator.login() # Use the Authenticator class for login

def turn_off_mic_cam(self):
self.controls.turn_off_mic_cam() # Use the MeetControls class for turning off mic/cam

def start(self, meeting_link):
self.login()
self.driver.get(meeting_link)
self.turn_off_mic_cam()

subtitle_thread = threading.Thread(target=self.subtitle_saver.save_subtitles, daemon=True) # Use SubtitleSaver
subtitle_thread.start()

try:
while True:
time.sleep(1)
except KeyboardInterrupt:
print("Program terminated by user.")
finally:
self.driver.quit()
106 changes: 106 additions & 0 deletions src/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import sys
import time
from PyQt6.QtWidgets import (QApplication, QWidget, QVBoxLayout,
QLineEdit, QPushButton, QTextEdit, QFileDialog)
from PyQt6.QtCore import QThread, pyqtSignal
import driver_setup
from google_meet_bot import GoogleMeetBot
from subtitle_saver import SubtitleSaver

class MeetingThread(QThread):
update_output = pyqtSignal(str)

def __init__(self, email, password, meeting_link, api_key, ai_api_key, translator, question_checker):
super().__init__()
self.email = email
self.password = password
self.meeting_link = meeting_link
self.api_key = api_key
self.ai_api_key = ai_api_key
self.driver = driver_setup
self.translator = translator
self.question_checker = question_checker

def run(self):
self.update_output.emit("Starting the meeting...")
self.bot = GoogleMeetBot(self.email, self.password, self.api_key, self.ai_api_key, self.update_output)
self.bot.start(self.meeting_link)

# Sending update_output as update_signal
subtitle_saver = SubtitleSaver(self.driver, self.translator, self.question_checker, self.update_output)
subtitle_saver.save_subtitles() # This method runs concurrently

class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Google Meet Bot")
self.setGeometry(400, 400, 800, 800)

# Assume you initialize translator and question_checker here
self.translator = None # Replace with actual translator
self.question_checker = None # Replace with actual question_checker

layout = QVBoxLayout()

self.email_input = QLineEdit(self)
self.email_input.setPlaceholderText("Enter your email")
self.email_input.setFixedHeight(40) # Increased height
layout.addWidget(self.email_input)

self.password_input = QLineEdit(self)
self.password_input.setPlaceholderText("Enter your password")
self.password_input.setEchoMode(QLineEdit.EchoMode.Password)
self.password_input.setFixedHeight(40) # Increased height
layout.addWidget(self.password_input)

self.meeting_link_input = QLineEdit(self)
self.meeting_link_input.setPlaceholderText("Enter meeting link")
self.meeting_link_input.setFixedHeight(40) # Increased height
layout.addWidget(self.meeting_link_input)

self.start_button = QPushButton("Start Meeting", self)
self.start_button.setStyleSheet("background-color: blue; font-size: 16px;") # Change button color
self.start_button.setFixedHeight(40) # In
self.start_button.clicked.connect(self.start_meeting)
layout.addWidget(self.start_button)

self.output_area = QTextEdit(self)
self.output_area.setReadOnly(True)
self.output_area.setFixedHeight(400) # Set a fixed height for output area
layout.addWidget(self.output_area)

self.download_button = QPushButton("Download Text File", self)
self.download_button.setStyleSheet("background-color: green; font-size: 16px;") # Change button color
self.download_button.setFixedHeight(40) # In
self.download_button.clicked.connect(self.download_file)
layout.addWidget(self.download_button)

self.setLayout(layout)

def start_meeting(self):
email = self.email_input.text()
password = self.password_input.text()
meeting_link = self.meeting_link_input.text()

if email and password and meeting_link:
self.meeting_thread = MeetingThread(email, password, meeting_link, 'YOUR_API_KEY', 'YOUR_AI_API_KEY', self.translator, self.question_checker)
self.meeting_thread.update_output.connect(self.append_output)
self.meeting_thread.start()
else:
self.output_area.append("Please fill in all fields.")

def append_output(self, message):
self.output_area.append(message)

def download_file(self):
file_name, _ = QFileDialog.getSaveFileName(self, "Save File", "", "Text Files (*.txt);;All Files (*)")
if file_name:
with open(file_name, 'w', encoding='utf-8') as file:
file.write(self.output_area.toPlainText())
self.output_area.append(f"File saved at {file_name}.")

if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())
32 changes: 32 additions & 0 deletions src/question_checker.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# question_checker.py
import requests

class QuestionChecker:
def __init__(self, api_key):
self.api_key = api_key

def is_question(self, text):
wh_question_detected = self.contains_wh_question(text)
if wh_question_detected:
return True

url = 'https://api.aimlapi.com/v1/chat/completions' # Replace with your API endpoint
headers = {
'Authorization': f'Bearer {self.api_key}',
'Content-Type': 'application/json'
}
payload = {
'text': text
}
response = requests.post(url, headers=headers, json=payload)
if response.status_code == 200:
result = response.json()
return result.get('is_question', False)
else:
print(f"API error: {response.status_code}, Message: {response.text}")
return False

def contains_wh_question(self, text):
wh_words = ['who', 'what', 'where', 'when', 'why', 'which']
text_lower = text.lower()
return any(wh in text_lower for wh in wh_words)
44 changes: 44 additions & 0 deletions src/subtitle_saver.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# subtitle_saver.py
import time
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException

class SubtitleSaver:
def __init__(self, driver, translator, question_checker, update_signal):
self.driver = driver
self.translator = translator
self.question_checker = question_checker
self.previous_subtitles = set()
self.update_signal = update_signal

def save_subtitles(self):
with open('subtitles.txt', 'a', encoding='utf-8') as f:
while True:
try:
subtitles = WebDriverWait(self.driver, 10).until(
EC.presence_of_element_located((By.XPATH, '//*[contains(concat(" ", @class, " "), concat(" ", "iOzk7", " "))]')))
subtitle_text = subtitles.text.strip()

if subtitle_text and subtitle_text not in self.previous_subtitles:
f.write("English: " + subtitle_text + '\n' + "*" * 20 + '\n')

if self.question_checker.is_question(subtitle_text):
f.write("Type: Question" + '\n' + "*" * 20 + '\n')
else:
f.write("Type: Statement" + '\n' + "*" * 20 + '\n')

translated_text = self.translator.translate(subtitle_text, dest='fa')
f.write("Persian: " + translated_text + '\n' + "*" * 20 + '\n')

f.flush()
self.update_signal.emit(f"English: {subtitle_text}\nType: {'Question' if self.question_checker.is_question(subtitle_text) else 'Statement'}\nPersian: {translated_text}")

self.previous_subtitles.add(subtitle_text)
time.sleep(1)
except TimeoutException:
print("TimeoutException: Element not found.")
except Exception as e:
print(f"Error: {e}")
break
Loading

0 comments on commit 16aa183

Please sign in to comment.