mirror of
https://github.com/shadoll/playing_now_2_mm.git
synced 2025-12-20 08:30:51 +00:00
initial commit
This commit is contained in:
3
.env.example
Normal file
3
.env.example
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
MATTERMOST_ACCESS_TOKEN=
|
||||||
|
MATTERMOST_SERVER_URL=https://my-mattermost.host
|
||||||
|
MUSIC_APP=apple_music # or spotify
|
||||||
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
.env
|
||||||
|
__pycache__
|
||||||
|
.mypy_cache
|
||||||
|
.venv
|
||||||
17
connectors/apple_music.py
Normal file
17
connectors/apple_music.py
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
from appscript import app # type: ignore
|
||||||
|
|
||||||
|
class AppleMusic:
|
||||||
|
def __init__(self):
|
||||||
|
self.music_app = app("Music")
|
||||||
|
|
||||||
|
def get_current_track_info(self) -> tuple:
|
||||||
|
try:
|
||||||
|
current_track = self.music_app.current_track.get()
|
||||||
|
return (
|
||||||
|
current_track.name.get(),
|
||||||
|
current_track.artist.get(),
|
||||||
|
current_track.duration.get(),
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Failed to get current track info: {e}")
|
||||||
|
return None, None, None
|
||||||
17
connectors/spotify.py
Normal file
17
connectors/spotify.py
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import osascript # type: ignore
|
||||||
|
|
||||||
|
class Spotify:
|
||||||
|
def get_current_track_info(self) -> tuple:
|
||||||
|
try:
|
||||||
|
name_code = 'tell application "Spotify" to name of current track as string'
|
||||||
|
artist_code = 'tell application "Spotify" to artist of current track as string'
|
||||||
|
duration_code = 'tell application "Spotify" to duration of current track as string'
|
||||||
|
|
||||||
|
name = osascript.osascript(name_code)[1]
|
||||||
|
artist = osascript.osascript(artist_code)[1]
|
||||||
|
duration = int(osascript.osascript(duration_code)[1]) / 1000 # Convert duration from ms to s
|
||||||
|
|
||||||
|
return name, artist, duration
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Failed to get current track info: {e}")
|
||||||
|
return None, None, None
|
||||||
43
mattermost.py
Normal file
43
mattermost.py
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
from datetime import datetime, timedelta, timezone
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
import os
|
||||||
|
import requests
|
||||||
|
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
|
|
||||||
|
class Mattermost:
|
||||||
|
def __init__(self, user_id="me"):
|
||||||
|
host = os.getenv("MATTERMOST_SERVER_URL", "http://localhost")
|
||||||
|
access_token = os.getenv("MATTERMOST_ACCESS_TOKEN", "")
|
||||||
|
self.user_id = user_id
|
||||||
|
self.url = f"{host}/api/v4/users/{self.user_id}/status/custom"
|
||||||
|
self.headers = {
|
||||||
|
"Authorization": f"Bearer {access_token}",
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
}
|
||||||
|
|
||||||
|
def set_status(self, status, emoji, expires_at=None):
|
||||||
|
data = {
|
||||||
|
"emoji": emoji,
|
||||||
|
"text": status,
|
||||||
|
"expires_at": expires_at,
|
||||||
|
}
|
||||||
|
response = requests.put(self.url, headers=self.headers, json=data)
|
||||||
|
if response.status_code != 200:
|
||||||
|
print(f"Failed to set Mattermost status: {response.content}")
|
||||||
|
raise Exception(f"Failed to set Mattermost status: {response.content}")
|
||||||
|
|
||||||
|
def set_now_playing(self, track, artist, duration):
|
||||||
|
expires_at = (datetime.now(timezone.utc) + timedelta(seconds=duration)).astimezone()
|
||||||
|
status = f"{track} - {artist}"
|
||||||
|
print(f"Setting Mattermost status to {status} until {expires_at}")
|
||||||
|
self.set_status(status, "headphones", expires_at.isoformat())
|
||||||
|
|
||||||
|
|
||||||
|
def get_status(self):
|
||||||
|
response = requests.get(self.url, headers=self.headers)
|
||||||
|
if response.status_code != 200:
|
||||||
|
print(f"Failed to get Mattermost status: {response.content}")
|
||||||
|
raise Exception(f"Failed to get Mattermost status: {response.content}")
|
||||||
|
return response.json()
|
||||||
9
music.py
Normal file
9
music.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
from mattermost import Mattermost
|
||||||
|
|
||||||
|
class Music:
|
||||||
|
def __init__(self, connector):
|
||||||
|
self.mattermost = Mattermost()
|
||||||
|
self.connector = connector()
|
||||||
|
|
||||||
|
def get_current_track_info(self) -> tuple:
|
||||||
|
return self.connector.get_current_track_info()
|
||||||
43
music_app.py
Normal file
43
music_app.py
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
from datetime import datetime
|
||||||
|
import time
|
||||||
|
from music import Music
|
||||||
|
from mattermost import Mattermost
|
||||||
|
from connectors.apple_music import AppleMusic
|
||||||
|
from connectors.spotify import Spotify
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
import os
|
||||||
|
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
|
SLEEP_TIME = 3
|
||||||
|
MUSIC_APP = (
|
||||||
|
os.getenv("MUSIC_APP", "apple_music").replace("_", " ").title().replace(" ", "")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def playing_now() -> tuple:
|
||||||
|
music = Music(connector=globals()[MUSIC_APP])
|
||||||
|
return music.get_current_track_info()
|
||||||
|
|
||||||
|
|
||||||
|
def set_now_playing(name, artist, duration):
|
||||||
|
now = datetime.now().strftime("%H:%M:%S")
|
||||||
|
print(f"{now} 🎧 {name} - {artist} ⏲️ {duration}")
|
||||||
|
if name and artist and duration:
|
||||||
|
Mattermost().set_now_playing(name, artist, duration)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
name_curr, artist_curr, duration_curr = playing_now()
|
||||||
|
set_now_playing(name_curr, artist_curr, duration_curr)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
name, artist, duration = playing_now()
|
||||||
|
if name != name_curr:
|
||||||
|
set_now_playing(name, artist, duration)
|
||||||
|
name_curr = name
|
||||||
|
time.sleep(SLEEP_TIME)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
27
readme.txt
Normal file
27
readme.txt
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# Music Status Updater
|
||||||
|
|
||||||
|
This is a Python application that fetches the currently playing track from either Apple Music or Spotify and sets it as your status on Mattermost.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
- Fetches current playing track from `Apple Music` or `Spotify`
|
||||||
|
- Sets the track as your status on Mattermost
|
||||||
|
- Using Appscript and Osascript for Music Track Information on MacOS
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
- MacOS
|
||||||
|
- Python 3
|
||||||
|
- Apple Music or Spotify
|
||||||
|
- Mattermost
|
||||||
|
|
||||||
|
## Environment Variables
|
||||||
|
`MUSIC_APP`: This variable determines which music service the application will fetch the currently playing track from. It can be either `apple_music` or `spotify`.
|
||||||
|
|
||||||
|
## How to Run
|
||||||
|
1. Clone the repository
|
||||||
|
2. Install the dependencies with `pip install -r requirements.txt`
|
||||||
|
3. Set Mattermost token and host in `.env`
|
||||||
|
4. Set the `MUSIC_APP` environment variable to your preferred music service
|
||||||
|
5. Run the application with `python music_app.py`
|
||||||
|
|
||||||
|
## Note
|
||||||
|
The application runs in an infinite loop, constantly checking for changes in the currently playing track and updating your Mattermost status accordingly.
|
||||||
4
requirements.txt
Normal file
4
requirements.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
python-dotenv
|
||||||
|
requests
|
||||||
|
appscript
|
||||||
|
osascript
|
||||||
Reference in New Issue
Block a user