-
Notifications
You must be signed in to change notification settings - Fork 5
/
applemusicrp.py
181 lines (141 loc) · 5.46 KB
/
applemusicrp.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
import sys
import os
import platform
import time
import subprocess
import threading
from sys import exit
import logging
from pypresence import Presence
import pypresence.exceptions
import dialite
import coverpy
# Lazy fix for py2exe
try:
__file__
except NameError:
__file__ = sys.argv[0]
# Client ID (DO NOT USE FOR ANYTHING OTHER THAN THIS APP PLS!)
client_id = "952320054870020146"
RPC = Presence(client_id) # Initialize the Presence client
cover_py = coverpy.CoverPy()
ostype = platform.system()
# Do initial OS-specific stuff
if ostype == 'Darwin':
import rumps
macos_ver = platform.mac_ver()[0]
if int(platform.mac_ver()[0].split('.')[0]) < 10 and int(platform.mac_ver()[0].split('.')[1]) < 15:
macos_legacy = True
else:
macos_legacy = False
elif ostype == 'Windows':
# Windows needs a lot of dependencies :p
from pystray import Icon as icon, Menu as menu, MenuItem as item
from PIL import Image
import win32com.client
import pythoncom
import psutil
def quit():
systray.stop()
exit(0)
image = Image.open(os.path.join(os.path.dirname(os.path.realpath(
__file__)), 'assets/icon.ico'))
menu = menu(item('Quit', quit))
systray = icon('AppleMusicRP', image, 'AppleMusicRP', menu=menu)
else:
# There isn't iTunes for Linux :(
dialite.fail("AppleMusicRP", "You need to be using Windows or macOS!")
exit(1)
# Try to connect to RPC
try:
RPC.connect()
except (ConnectionRefusedError, pypresence.exceptions.DiscordNotFound, pypresence.exceptions.DiscordError) as e:
msg = 'Could not connect to Discord!'
logging.exception(msg)
dialite.fail("AppleMusicRP", msg)
exit(1)
def get_music_info():
if ostype == 'Darwin':
# Get info using AppleScript and then parse
if macos_legacy == True:
# Legacy script for pre Catalina macOS
script_loc = os.path.join(os.path.dirname(os.path.realpath(
__file__)), 'scripts/getmusicinfo-legacy.applescript')
else:
# Normal script for macOS
script_loc = os.path.join(os.path.dirname(os.path.realpath(
__file__)), 'scripts/getmusicinfo.applescript')
p = subprocess.Popen(['osascript', script_loc],
stdout=subprocess.PIPE)
return p.stdout.read().decode("utf-8").strip().split('\\')
else:
# Check if iTunes is running
if "iTunes.exe" in (p.name() for p in psutil.process_iter()):
itunes = win32com.client.Dispatch(
"iTunes.Application", pythoncom.CoInitialize())
else:
return ['STOPPED']
# Get info using Windows API
current_track = itunes.CurrentTrack
playerstate = itunes.PlayerState
if current_track is None:
return ['STOPPED']
return [('PAUSED' if playerstate == 0 else 'PLAYING'), current_track.Name, current_track.Artist,
current_track.Album, str(itunes.PlayerPosition)]
def get_cover_art_url(title, artist):
try:
result = cover_py.get_cover(f'{title} {artist}', 1)
return result.artwork(512)
except coverpy.exceptions.NoResultsException:
return
def rp_updater():
err_count = 0
last_played = time.time()
artwork = 'logo'
current_song = None
while True:
try:
# info[0] is status (PLAYING, PAUSED, or STOPPED), info[1] is title, info[2] is artist, info[3] is album, info[4] is player position
info = get_music_info()
# Set status if music is playing or paused and hasn't been paused for >10 mins
if info[0] == "PLAYING" or info[0] == "PAUSED" and (time.time()) < (last_played+(10*60)):
if info[0] == 'PLAYING':
last_played = time.time()
# .split(',')[0] is an attempt to fix issue #5
elapsed = int(float(info[4].split(',')[0]))
if current_song != (info[0], info[1],):
current_song = (info[0], info[1],)
artwork = get_cover_art_url(info[1], info[2])
RPC.update(large_image=artwork or 'logo',
large_text='Using AppleMusicRP (https://github.com/wxllow/applemusicrp) :)',
details=f'{"Playing" if info[0] == "PLAYING" else "Paused"} {info[1]}',
small_image='play' if info[0] == "PLAYING" else 'pause',
small_text='Playing' if info[0] == "PLAYING" else 'Paused',
state=f'By {info[2]} on {info[3]}',
start=(
(time.time()-elapsed) if info[0] == "PLAYING" else None))
else:
RPC.clear()
except:
err_count += 1
msg = 'An unexpected error has occured while trying to update your Discord status!'
logging.exception(msg)
dialite.fail("AppleMusicRP", msg)
# Prevent endless loops of errors!
if err_count > 1:
exit(1)
time.sleep(0.8)
if ostype == 'Darwin':
# Just needs a quit button, no need to define anything here for now
class App(rumps.App):
pass
if __name__ == '__main__':
# Launch Rich Presence (RP) updating thread
x = threading.Thread(target=rp_updater, daemon=True)
x.start()
# Tray/menu bar app
if ostype == 'Darwin':
app = App('🎵')
exit(app.run())
else:
systray.run()