mirror of
https://github.com/maglore9900/max_headroom.git
synced 2025-06-06 19:45:31 +00:00
working on journal function
moved speech import to agent, changed main import from direct to agent to speech
This commit is contained in:
parent
f9c1503ad2
commit
264f2a811f
10
main.py
10
main.py
@ -1,20 +1,16 @@
|
|||||||
from modules import agent, speak
|
from modules import agent
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
loop = asyncio.new_event_loop()
|
loop = asyncio.new_event_loop()
|
||||||
asyncio.set_event_loop(loop)
|
asyncio.set_event_loop(loop)
|
||||||
|
|
||||||
|
|
||||||
sp = speak.Speak()
|
|
||||||
graph = agent.Agent()
|
graph = agent.Agent()
|
||||||
|
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
text = sp.listen2()
|
text = graph.spk.listen2()
|
||||||
if text and "hey" in text.lower() and "max " in text.lower() or text and "hey" in text.lower() and "mac " in text.lower():
|
if text and "hey" in text.lower() and "max " in text.lower() or text and "hey" in text.lower() and "mac " in text.lower():
|
||||||
if "exit" in text.lower():
|
if "exit" in text.lower():
|
||||||
break
|
break
|
||||||
response = loop.run_until_complete(graph.invoke_agent(text))
|
response = loop.run_until_complete(graph.invoke_agent(text))
|
||||||
if response:
|
if response:
|
||||||
sp.glitch_stream_output(response)
|
graph.spk.glitch_stream_output(response)
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
from typing import TypedDict, Annotated, List, Union
|
from typing import TypedDict, Annotated, List, Union
|
||||||
import operator
|
import operator
|
||||||
from modules import adapter, spotify, app_launcher, windows_focus
|
from modules import adapter, spotify, app_launcher, windows_focus, speak
|
||||||
from langchain_core.agents import AgentAction, AgentFinish
|
from langchain_core.agents import AgentAction, AgentFinish
|
||||||
from langchain.agents import create_openai_tools_agent
|
from langchain.agents import create_openai_tools_agent
|
||||||
from langchain.prompts import PromptTemplate, SystemMessagePromptTemplate
|
from langchain.prompts import PromptTemplate, SystemMessagePromptTemplate
|
||||||
@ -8,7 +8,7 @@ from langchain import hub
|
|||||||
from langchain_core.tools import tool
|
from langchain_core.tools import tool
|
||||||
from langgraph.graph import StateGraph, END
|
from langgraph.graph import StateGraph, END
|
||||||
import asyncio
|
import asyncio
|
||||||
import json
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -19,6 +19,7 @@ class Agent:
|
|||||||
self.ap = app_launcher.AppLauncher()
|
self.ap = app_launcher.AppLauncher()
|
||||||
self.wf = windows_focus.WindowFocusManager()
|
self.wf = windows_focus.WindowFocusManager()
|
||||||
self.llm = self.ad.llm_chat
|
self.llm = self.ad.llm_chat
|
||||||
|
self.spk = speak.Speak()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -29,9 +30,9 @@ class Agent:
|
|||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
Greeting: "Wwell, hello there! It’s Max Headroom, your guide to the digital mmadness! Buckle up, because it’s going to be a bumpy ride through the info-sphere, folks!"
|
Greeting: "Well, hello there! It’s Max Headroom, your guide to the digital madness! Buckle up, because it’s going to be a bumpy ride through the info-sphere, folks!"
|
||||||
|
|
||||||
On Technology: "Tech? Pffft! It’s just the latest toy for the big boys to play with. You think it’s here to help you? Ha! It’s just another way to kkeep you glued to the screen!"
|
On Technology: "Tech? Pffft! It’s just the latest toy for the big boys to play with. You think it’s here to help you? Ha! It’s just another way to keep you glued to the screen!"
|
||||||
|
|
||||||
On Society: "Ah, society! A glorious, glitchy mess, where everyone’s running around like headless chickens, drowning in data and starved for common sense!"
|
On Society: "Ah, society! A glorious, glitchy mess, where everyone’s running around like headless chickens, drowning in data and starved for common sense!"
|
||||||
|
|
||||||
@ -46,16 +47,13 @@ class Agent:
|
|||||||
template=custom_prompt
|
template=custom_prompt
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# Now you can use the modified template
|
|
||||||
# self.prompt = prompt_template.format(input=[], chat_history=[], agent_scratchpad=[])
|
|
||||||
self.query_agent_runnable = create_openai_tools_agent(
|
self.query_agent_runnable = create_openai_tools_agent(
|
||||||
llm=self.llm,
|
llm=self.llm,
|
||||||
tools=[
|
tools=[
|
||||||
# self.rag_final_answer_tool,
|
|
||||||
self.spotify,
|
self.spotify,
|
||||||
self.app_launcher,
|
self.app_launcher,
|
||||||
self.windows_focus
|
self.windows_focus,
|
||||||
|
self.journal_mode
|
||||||
],
|
],
|
||||||
prompt=self.prompt,
|
prompt=self.prompt,
|
||||||
)
|
)
|
||||||
@ -70,34 +68,43 @@ class Agent:
|
|||||||
agent_out: Union[AgentAction, AgentFinish, None]
|
agent_out: Union[AgentAction, AgentFinish, None]
|
||||||
intermediate_steps: Annotated[List[tuple[AgentAction, str]], operator.add]
|
intermediate_steps: Annotated[List[tuple[AgentAction, str]], operator.add]
|
||||||
|
|
||||||
#! Tools
|
#! Tools
|
||||||
@tool("respond")
|
|
||||||
async def respond(self, answer: str):
|
|
||||||
"""Returns a natural language response to the user in `answer`"""
|
|
||||||
return ""
|
|
||||||
|
|
||||||
@tool("spotify")
|
@tool("spotify")
|
||||||
async def spotify(self, command: str):
|
async def spotify(self, command: str):
|
||||||
"""Use this tool to control spotify, commands include: play, pause, stop, next, previous, favorite, search
|
"""Use this tool to control spotify, commands include: play, pause, stop, next, previous, favorite, search.
|
||||||
Only use this tool if the user says Spotify in their query"""
|
Only use this tool if the user says Spotify in their query"""
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
@tool("app_launcher")
|
@tool("app_launcher")
|
||||||
async def app_launcher(self, app_name: str):
|
async def app_launcher(self, app_name: str):
|
||||||
"""Use this tool to launch an app or application on your computer.
|
"""Use this tool to launch an app or application on your computer.
|
||||||
The user query will contain the app name, as well as open, launch, start, or similar type words
|
The user query will contain the app name, as well as open, launch, start, or similar type words.
|
||||||
pass the name of the app to this tool as app_name
|
pass the name of the app to this tool as app_name
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@tool("windows_focus")
|
@tool("windows_focus")
|
||||||
async def windows_focus(self, app_name: str):
|
async def windows_focus(self, app_name: str):
|
||||||
"""Use this tool to focus on a window on your computer.
|
"""Use this tool to focus on a window on your computer.
|
||||||
The user query will contain the app name, as well as focus, switch, show, or similar type words
|
The user query will contain the app name, as well as focus, switch, show, or similar type words.
|
||||||
pass the name of the app to this tool as app_name
|
pass the name of the app to this tool as app_name.
|
||||||
"""
|
"""
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
@tool("journal_mode")
|
||||||
|
async def journal_mode(self, text: str):
|
||||||
|
"""Use this tool to write down journal entries for the user.
|
||||||
|
The user query will contain the word journal, record, write, or similar type words.
|
||||||
|
Examples:
|
||||||
|
- "write down a journal entry for me"
|
||||||
|
- "I want to journal"
|
||||||
|
- "record my thoughts"
|
||||||
|
"""
|
||||||
|
return ""
|
||||||
|
|
||||||
|
@tool("respond")
|
||||||
|
async def respond(self, answer: str):
|
||||||
|
"""Returns a natural language response to the user in `answer`"""
|
||||||
|
return ""
|
||||||
|
|
||||||
def setup_graph(self):
|
def setup_graph(self):
|
||||||
self.graph.add_node("query_agent", self.run_query_agent)
|
self.graph.add_node("query_agent", self.run_query_agent)
|
||||||
@ -105,6 +112,7 @@ class Agent:
|
|||||||
self.graph.add_node("app_launcher", self.app_launcher_tool)
|
self.graph.add_node("app_launcher", self.app_launcher_tool)
|
||||||
self.graph.add_node("windows_focus", self.windows_focus_tool)
|
self.graph.add_node("windows_focus", self.windows_focus_tool)
|
||||||
self.graph.add_node("respond", self.respond)
|
self.graph.add_node("respond", self.respond)
|
||||||
|
self.graph.add_node("journal_mode", self.journal_mode_tool)
|
||||||
|
|
||||||
self.graph.set_entry_point("query_agent")
|
self.graph.set_entry_point("query_agent")
|
||||||
self.graph.add_conditional_edges(
|
self.graph.add_conditional_edges(
|
||||||
@ -114,13 +122,15 @@ class Agent:
|
|||||||
"spotify": "spotify",
|
"spotify": "spotify",
|
||||||
"respond": "respond",
|
"respond": "respond",
|
||||||
"app_launcher": "app_launcher",
|
"app_launcher": "app_launcher",
|
||||||
"windows_focus": "windows_focus"
|
"windows_focus": "windows_focus",
|
||||||
|
"journal_mode": "journal_mode"
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
self.graph.add_edge("spotify", END)
|
self.graph.add_edge("spotify", END)
|
||||||
self.graph.add_edge("app_launcher", END)
|
self.graph.add_edge("app_launcher", END)
|
||||||
self.graph.add_edge("windows_focus", END)
|
self.graph.add_edge("windows_focus", END)
|
||||||
self.graph.add_edge("respond", END)
|
self.graph.add_edge("respond", END)
|
||||||
|
self.graph.add_edge("journal_mode", END)
|
||||||
|
|
||||||
|
|
||||||
self.runnable = self.graph.compile()
|
self.runnable = self.graph.compile()
|
||||||
@ -132,6 +142,18 @@ class Agent:
|
|||||||
print(agent_out)
|
print(agent_out)
|
||||||
return {"agent_out": agent_out}
|
return {"agent_out": agent_out}
|
||||||
|
|
||||||
|
async def journal_mode_tool(self, state: str):
|
||||||
|
print("> journal_mode_tool")
|
||||||
|
while True:
|
||||||
|
text = self.spk.listen2(30)
|
||||||
|
if text:
|
||||||
|
if "exit" in text.lower():
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
with open("journal.txt", "a") as file:
|
||||||
|
file.write(text + "\n")
|
||||||
|
break
|
||||||
|
|
||||||
async def spotify_tool(self, state: str):
|
async def spotify_tool(self, state: str):
|
||||||
try:
|
try:
|
||||||
print("> spotify_tool")
|
print("> spotify_tool")
|
||||||
@ -167,7 +189,8 @@ class Agent:
|
|||||||
print("> app_launcher_tool")
|
print("> app_launcher_tool")
|
||||||
print(f"state: {state}")
|
print(f"state: {state}")
|
||||||
tool_action = state['agent_out'][0]
|
tool_action = state['agent_out'][0]
|
||||||
app_name = tool_action.tool_input['app_name']
|
# app_name = tool_action.tool_input['app_name']
|
||||||
|
app_name = (lambda x: x.get('app_name') or x.get('self'))(tool_action.tool_input)
|
||||||
print(f"app_name: {app_name}")
|
print(f"app_name: {app_name}")
|
||||||
self.ap.find_and_open_app(app_name)
|
self.ap.find_and_open_app(app_name)
|
||||||
|
|
||||||
@ -175,7 +198,8 @@ class Agent:
|
|||||||
print("> windows_focus_tool")
|
print("> windows_focus_tool")
|
||||||
print(f"state: {state}")
|
print(f"state: {state}")
|
||||||
tool_action = state['agent_out'][0]
|
tool_action = state['agent_out'][0]
|
||||||
app_name = tool_action.tool_input['app_name']
|
# app_name = tool_action.tool_input['app_name']
|
||||||
|
app_name = (lambda x: x.get('app_name') or x.get('self'))(tool_action.tool_input)
|
||||||
print(f"app_name: {app_name}")
|
print(f"app_name: {app_name}")
|
||||||
self.wf.bring_specific_instance_to_front(app_name)
|
self.wf.bring_specific_instance_to_front(app_name)
|
||||||
|
|
||||||
|
67
modules/journal.py
Normal file
67
modules/journal.py
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
from langchain_core.prompts import ChatPromptTemplate, HumanMessagePromptTemplate
|
||||||
|
from langchain_core.messages import SystemMessage
|
||||||
|
from langchain_core.output_parsers import StrOutputParser
|
||||||
|
import adapter
|
||||||
|
|
||||||
|
ad = adapter.Adapter()
|
||||||
|
|
||||||
|
class Journal:
|
||||||
|
def __init__(self):
|
||||||
|
self.sys_prompt = """
|
||||||
|
You are tasked with creating a detailed and neutral journal entry. The entry should capture key points, observations, any relevant metrics, and recommended actions or next steps. The language should remain neutral, avoiding any self-referential language.
|
||||||
|
|
||||||
|
Example 1:
|
||||||
|
Date: [DD-MM-YYYY]
|
||||||
|
|
||||||
|
**Key Points:**
|
||||||
|
- [Summary of the main points or events, capturing essential details]
|
||||||
|
|
||||||
|
**Observations:**
|
||||||
|
- [Notes on observations, trends, or insights drawn from the data]
|
||||||
|
|
||||||
|
**Metrics:**
|
||||||
|
- [List of any relevant metrics, figures, or statistics related to the data]
|
||||||
|
|
||||||
|
**Recommended Actions:**
|
||||||
|
- [Suggested actions, strategies, or next steps based on the data analysis]
|
||||||
|
|
||||||
|
|
||||||
|
Example 2:
|
||||||
|
Date: [DD-MM-YYYY]
|
||||||
|
|
||||||
|
**Summary:**
|
||||||
|
- [Overview of the data or event, focusing on significant highlights]
|
||||||
|
|
||||||
|
**Analysis:**
|
||||||
|
- [Detailed analysis, including patterns, anomalies, or key insights]
|
||||||
|
|
||||||
|
**Figures:**
|
||||||
|
- [Relevant numerical data, metrics, or charts]
|
||||||
|
|
||||||
|
**Next Steps:**
|
||||||
|
- [Proposed actions, decisions, or follow-up activities derived from the analysis]
|
||||||
|
|
||||||
|
Ensure that the tone remains neutral, and avoid using 'I' or 'my' in the notes.
|
||||||
|
|
||||||
|
The format MUST be in markdown
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.chat_template = ChatPromptTemplate.from_messages(
|
||||||
|
[
|
||||||
|
SystemMessage(
|
||||||
|
content=(
|
||||||
|
self.sys_prompt
|
||||||
|
)
|
||||||
|
),
|
||||||
|
HumanMessagePromptTemplate.from_template("{text}"),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
self.journal_llm = self.chat_template | ad.llm_chat | StrOutputParser()
|
||||||
|
|
||||||
|
def journal(self, text):
|
||||||
|
message = self.chat_template.format_messages(text=text)
|
||||||
|
response = self.journal_llm.invoke(message)
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
@ -55,14 +55,15 @@ class Speak:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
#! listen with vosk
|
#! listen with vosk
|
||||||
def listen2(self, noise_threshold=500):
|
def listen2(self, time_listen=15):
|
||||||
|
noise_threshold=500
|
||||||
p = pyaudio.PyAudio()
|
p = pyaudio.PyAudio()
|
||||||
stream = p.open(format=pyaudio.paInt16, channels=1, rate=16000, input=True, frames_per_buffer=8000)
|
stream = p.open(format=pyaudio.paInt16, channels=1, rate=16000, input=True, frames_per_buffer=8000)
|
||||||
stream.start_stream()
|
stream.start_stream()
|
||||||
print("Listening...")
|
print("Listening...")
|
||||||
count = 0
|
count = 0
|
||||||
try:
|
try:
|
||||||
while count < 10:
|
while count < time_listen:
|
||||||
data = stream.read(8000, exception_on_overflow=False)
|
data = stream.read(8000, exception_on_overflow=False)
|
||||||
filtered_data = nr.reduce_noise(y=frombuffer(data, dtype=int16), sr=16000).astype(int16).tobytes()
|
filtered_data = nr.reduce_noise(y=frombuffer(data, dtype=int16), sr=16000).astype(int16).tobytes()
|
||||||
|
|
||||||
@ -154,7 +155,7 @@ class Speak:
|
|||||||
stream = None
|
stream = None
|
||||||
|
|
||||||
# Process the audio stream in chunks
|
# Process the audio stream in chunks
|
||||||
chunk_size = 1024 * 8 # Adjust chunk size if needed
|
chunk_size = 1024 * 6 # Adjust chunk size if needed
|
||||||
audio_buffer = b''
|
audio_buffer = b''
|
||||||
|
|
||||||
for chunk in response.iter_content(chunk_size=chunk_size):
|
for chunk in response.iter_content(chunk_size=chunk_size):
|
||||||
@ -171,7 +172,7 @@ class Speak:
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Randomly adjust pitch
|
# Randomly adjust pitch
|
||||||
octaves = random.uniform(-0.5, 1.5)
|
octaves = random.uniform(-0.1, 1.5)
|
||||||
modified_chunk = change_pitch(audio_segment, octaves)
|
modified_chunk = change_pitch(audio_segment, octaves)
|
||||||
|
|
||||||
if random.random() < 0.001: # 1% chance to trigger stutter
|
if random.random() < 0.001: # 1% chance to trigger stutter
|
||||||
|
@ -1,55 +1,101 @@
|
|||||||
import spotipy
|
import spotipy
|
||||||
import environ
|
import environ
|
||||||
from spotipy.oauth2 import SpotifyOAuth
|
from spotipy.oauth2 import SpotifyOAuth
|
||||||
|
from requests.exceptions import ConnectionError, HTTPError
|
||||||
|
import time
|
||||||
|
import functools
|
||||||
|
|
||||||
env = environ.Env()
|
env = environ.Env()
|
||||||
environ.Env.read_env()
|
environ.Env.read_env()
|
||||||
|
|
||||||
|
def handle_spotify_errors_and_device(func):
|
||||||
|
@functools.wraps(func)
|
||||||
|
def wrapper(self, *args, **kwargs):
|
||||||
|
attempts = 3
|
||||||
|
for attempt in range(attempts):
|
||||||
|
try:
|
||||||
|
# Fetch the active device before calling the function
|
||||||
|
device_id = self.get_active_device()
|
||||||
|
if device_id is None:
|
||||||
|
print("No active device found.")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Inject the device_id into the kwargs
|
||||||
|
kwargs['device_id'] = device_id
|
||||||
|
|
||||||
|
return func(self, *args, **kwargs)
|
||||||
|
except (spotipy.exceptions.SpotifyException, ConnectionError, HTTPError) as e:
|
||||||
|
print(f"Attempt {attempt + 1} failed: {e}")
|
||||||
|
if "token" in str(e).lower():
|
||||||
|
self.refresh_token()
|
||||||
|
time.sleep(2) # Wait before retrying
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Unexpected error: {e}")
|
||||||
|
break
|
||||||
|
return wrapper
|
||||||
|
|
||||||
class Spotify:
|
class Spotify:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.sp = spotipy.Spotify(auth_manager=SpotifyOAuth(client_id=env("spotify_client_id"),
|
self.auth_manager = SpotifyOAuth(
|
||||||
client_secret=env("spotify_client_secret"),
|
client_id=env("spotify_client_id"),
|
||||||
redirect_uri=env("spotify_redirect_uri"),
|
client_secret=env("spotify_client_secret"),
|
||||||
scope="user-modify-playback-state user-read-playback-state user-library-modify"))
|
redirect_uri=env("spotify_redirect_uri"),
|
||||||
|
scope="user-modify-playback-state user-read-playback-state user-library-modify"
|
||||||
|
)
|
||||||
|
self.sp = spotipy.Spotify(auth_manager=self.auth_manager)
|
||||||
|
|
||||||
def get_active_device(self):
|
def get_active_device(self):
|
||||||
devices = self.sp.devices()
|
try:
|
||||||
if devices['devices']:
|
devices = self.sp.devices()
|
||||||
# Select the first active device
|
if devices['devices']:
|
||||||
active_device_id = devices['devices'][0]['id']
|
active_device_id = devices['devices'][0]['id']
|
||||||
return active_device_id
|
return active_device_id
|
||||||
else:
|
else:
|
||||||
|
return None
|
||||||
|
except spotipy.exceptions.SpotifyException as e:
|
||||||
|
print(f"Error fetching devices: {e}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def play(self):
|
def refresh_token(self):
|
||||||
try:
|
try:
|
||||||
device_id = self.get_active_device()
|
self.sp = spotipy.Spotify(auth_manager=self.auth_manager)
|
||||||
|
print("Token refreshed successfully.")
|
||||||
|
except spotipy.exceptions.SpotifyException as e:
|
||||||
|
print(f"Failed to refresh token: {e}")
|
||||||
|
|
||||||
|
@handle_spotify_errors_and_device
|
||||||
|
def play(self, device_id=None):
|
||||||
|
if device_id:
|
||||||
self.sp.start_playback(device_id=device_id)
|
self.sp.start_playback(device_id=device_id)
|
||||||
except Exception as e:
|
print("Playback started successfully.")
|
||||||
print(f"Failed to play: {e}")
|
else:
|
||||||
|
print("No active device found.")
|
||||||
def pause(self):
|
|
||||||
try:
|
@handle_spotify_errors_and_device
|
||||||
device_id = self.get_active_device()
|
def pause(self, device_id=None):
|
||||||
|
if device_id:
|
||||||
self.sp.pause_playback(device_id=device_id)
|
self.sp.pause_playback(device_id=device_id)
|
||||||
except Exception as e:
|
print("Playback paused successfully.")
|
||||||
print(f"Failed to pause playback: {e}")
|
else:
|
||||||
|
print("No active device found.")
|
||||||
def next_track(self):
|
|
||||||
try:
|
@handle_spotify_errors_and_device
|
||||||
device_id = self.get_active_device()
|
def next_track(self, device_id=None):
|
||||||
|
if device_id:
|
||||||
self.sp.next_track(device_id=device_id)
|
self.sp.next_track(device_id=device_id)
|
||||||
except Exception as e:
|
else:
|
||||||
print(f"Failed to skip to the next track: {e}")
|
print("Failed to skip to the next track")
|
||||||
|
|
||||||
def previous_track(self):
|
@handle_spotify_errors_and_device
|
||||||
try:
|
def previous_track(self, device_id=None):
|
||||||
device_id = self.get_active_device()
|
if device_id:
|
||||||
self.sp.previous_track(device_id=device_id)
|
self.sp.previous_track(device_id=device_id)
|
||||||
except Exception as e:
|
else:
|
||||||
print(f"Failed to go to the previous track: {e}")
|
print("Failed to go to the previous track")
|
||||||
|
|
||||||
def favorite_current_song(self):
|
@handle_spotify_errors_and_device
|
||||||
try:
|
def favorite_current_song(self, device_id=None):
|
||||||
|
if device_id:
|
||||||
current_track = self.sp.current_playback()
|
current_track = self.sp.current_playback()
|
||||||
if current_track and current_track['item']:
|
if current_track and current_track['item']:
|
||||||
track_id = current_track['item']['id']
|
track_id = current_track['item']['id']
|
||||||
@ -57,15 +103,15 @@ class Spotify:
|
|||||||
print(f"Added '{current_track['item']['name']}' to favorites")
|
print(f"Added '{current_track['item']['name']}' to favorites")
|
||||||
else:
|
else:
|
||||||
print("No song is currently playing")
|
print("No song is currently playing")
|
||||||
except Exception as e:
|
else:
|
||||||
print(f"Failed to add current song to favorites: {e}")
|
print("Failed to add current song to favorites")
|
||||||
|
|
||||||
def search_song_and_play(self, song_name):
|
@handle_spotify_errors_and_device
|
||||||
|
def search_song_and_play(self, song_name, device_id=None):
|
||||||
try:
|
try:
|
||||||
results = self.sp.search(q='track:' + song_name, type='track')
|
results = self.sp.search(q='track:' + song_name, type='track')
|
||||||
if results['tracks']['items']:
|
if results['tracks']['items']:
|
||||||
track_uri = results['tracks']['items'][0]['uri']
|
track_uri = results['tracks']['items'][0]['uri']
|
||||||
device_id = self.get_active_device()
|
|
||||||
if device_id:
|
if device_id:
|
||||||
self.sp.start_playback(device_id=device_id, uris=[track_uri])
|
self.sp.start_playback(device_id=device_id, uris=[track_uri])
|
||||||
else:
|
else:
|
||||||
@ -74,13 +120,13 @@ class Spotify:
|
|||||||
print(f"No results found for song: {song_name}")
|
print(f"No results found for song: {song_name}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Failed to search and play song '{song_name}': {e}")
|
print(f"Failed to search and play song '{song_name}': {e}")
|
||||||
|
|
||||||
def search_artist_and_play(self, artist_name):
|
@handle_spotify_errors_and_device
|
||||||
|
def search_artist_and_play(self, artist_name, device_id=None):
|
||||||
try:
|
try:
|
||||||
results = self.sp.search(q='artist:' + artist_name, type='artist')
|
results = self.sp.search(q='artist:' + artist_name, type='artist')
|
||||||
if results['artists']['items']:
|
if results['artists']['items']:
|
||||||
artist_uri = results['artists']['items'][0]['uri']
|
artist_uri = results['artists']['items'][0]['uri']
|
||||||
device_id = self.get_active_device()
|
|
||||||
if device_id:
|
if device_id:
|
||||||
self.sp.start_playback(device_id=device_id, context_uri=artist_uri)
|
self.sp.start_playback(device_id=device_id, context_uri=artist_uri)
|
||||||
else:
|
else:
|
||||||
@ -89,13 +135,13 @@ class Spotify:
|
|||||||
print(f"No results found for artist: {artist_name}")
|
print(f"No results found for artist: {artist_name}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Failed to search and play artist '{artist_name}': {e}")
|
print(f"Failed to search and play artist '{artist_name}': {e}")
|
||||||
|
|
||||||
def search_album_and_play(self, album_name):
|
@handle_spotify_errors_and_device
|
||||||
|
def search_album_and_play(self, album_name, device_id=None):
|
||||||
try:
|
try:
|
||||||
results = self.sp.search(q='album:' + album_name, type='album')
|
results = self.sp.search(q='album:' + album_name, type='album')
|
||||||
if results['albums']['items']:
|
if results['albums']['items']:
|
||||||
album_uri = results['albums']['items'][0]['uri']
|
album_uri = results['albums']['items'][0]['uri']
|
||||||
device_id = self.get_active_device()
|
|
||||||
if device_id:
|
if device_id:
|
||||||
self.sp.start_playback(device_id=device_id, context_uri=album_uri)
|
self.sp.start_playback(device_id=device_id, context_uri=album_uri)
|
||||||
else:
|
else:
|
||||||
|
5
test.py
Normal file
5
test.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
from modules import spotify2
|
||||||
|
|
||||||
|
sp = spotify2.Spotify()
|
||||||
|
|
||||||
|
sp.search_song_and_play("Shape of You")
|
3844
tmp/app_index.json
3844
tmp/app_index.json
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user