forked from hughwilliams94/radio-browser-skill
-
Notifications
You must be signed in to change notification settings - Fork 0
/
__init__.py
123 lines (100 loc) · 4.12 KB
/
__init__.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
#!/usr/bin/env python3
import re
import json
import inflect
from mycroft import intent_file_handler
from pyradios import RadioBrowser
from word2number import w2n
from mycroft.skills.common_play_skill import CommonPlaySkill, CPSMatchLevel
from mycroft.util.log import LOG
def match_station_name(phrase):
"""Takes the user utterance and attempts to match a specific station
:param phrase: User utterance
:type phrase: str
:return: A tuple containing the original phrase, the CPS.MatchLevel,
and a dictionary containing the resolved stream URL.
:rtype: tuple
"""
numbers_regex = r"\b(one|two|three|four|five|six|seven|eight|nine)\b"
try:
rb = RadioBrowser()
except Exception as e:
LOG.exception("Failed to load pyradios" + repr(e))
LOG.info(f"Searching for {phrase}")
results = rb.search(name=phrase)
parsed = json.loads(json.dumps(results))
if len(parsed) > 0:
# If an exatch match has been found return.
LOG.info(f"Found {parsed[0]['name']} ({parsed[0]['url_resolved']})")
return phrase, CPSMatchLevel.EXACT, {"url": parsed[0]["url_resolved"]}
elif re.search(" [0-9]+ ", phrase):
# If no match has been found, replace any digits (1,2,3) with text
# (one, two, three) and repeat search.
num = re.findall("[0-9]+", phrase)
inf_eng = inflect.engine()
for number in num:
phrase = phrase.replace(num, inf_eng.number_to_words(number))
match_station_name(phrase)
elif re.search(numbers_regex, phrase):
# As above but reversed: change strings to ints and repeat search.
num = re.findall(numbers_regex, phrase)
for number in num:
phrase = phrase.replace(number, str(w2n.word_to_num(number)))
match_station_name(phrase)
else:
return None
def match_genre(phrase):
"""Takes the user utterance and attempts to match a genre of station,
returning the most popular of that genre.
:param phrase: User utterance
:type phrase: str
:return: A tuple containing the original phrase, the CPS.MatchLevel,
and a dictionary containing the resolved stream URL.
:rtype: tuple
"""
# Strip 'a' and 'station' from phrases like 'Play a jazz station.'.
stripped_phrase = phrase.lower().replace("a ", "").replace(" station", "")
try:
rb = RadioBrowser()
except Exception as e:
LOG.exception("Failed to load pyradios" + repr(e))
LOG.info(f"Searching for a {stripped_phrase} station")
results = rb.search(tag=stripped_phrase, order="votes")
parsed = json.loads(json.dumps(results))
if len(parsed) > 0:
LOG.info(f"Found {parsed[0]['name']} ({parsed[0]['url_resolved']})")
return phrase, CPSMatchLevel.EXACT, {"url": parsed[0]["url_resolved"]}
else:
match_station_name(phrase)
class RadioBrowserSkill(CommonPlaySkill):
def __init__(self):
super().__init__(name="RadioBrowser")
def CPS_match_query_phrase(self, phrase):
search_phrase = phrase.lower()
if "a " and " station" in search_phrase:
return match_genre(search_phrase)
else:
return match_station_name(phrase)
def CPS_start(self, phrase, data):
if self.audioservice.is_playing:
self.audioservice.stop()
url = data["url"]
LOG.info(f"Playing from {url}")
self.audioservice.play(url)
def handle_intent(self, message, type):
# Generic method for handling intents
matched_station = match_station_name(message.data[type])
LOG.info(f"Playing from {matched_station[2]['url']}")
self.CPS_play(matched_station[2]["url"])
@intent_file_handler("radio.station.intent")
def handle_radio_station(self, message):
# Handles requests for specific stations
self.handle_intent(message, "station")
@intent_file_handler("radio.genre.intent")
def handle_radio_genre(self, message):
# Handles requests for genres
self.handle_intent(message, "genre")
def initialize(self):
self.add_event("mycroft.stop", self.stop)
def create_skill():
return RadioBrowserSkill()