Browse Source

From Python to shell script

- Allowing to run mpd + icecast2 + fip relay with metadatas on a VM
  with 128Mo of memory.
- Calculating when to update (given the end field in the JSON)
Yann Weber 5 years ago
parent
commit
bcafd50a3d
5 changed files with 52 additions and 213 deletions
  1. 10
    14
      README.txt
  2. 0
    7
      conf-sample.ini
  3. 0
    185
      fip_current.py
  4. 38
    0
      fip_current.sh
  5. 4
    7
      init_script

+ 10
- 14
README.txt View File

@@ -1,13 +1,14 @@
1 1
 Usage :
2 2
 -------
3 3
 
4
-./fip_current.py [-c CONFIG.ini] [-u]
4
+Edit the script to change the value of :
5
+	host -> icecast2 host & port
6
+	mount -> mountpoint name
7
+	login -> icecast2 login
8
+	passwd -> icecast2 password
5 9
 
6
-#Show current song metadata
7
-./fip_current.py 
8
-
9
-#Update icecast2 metadata
10
-./fip_current.py -c CONFIG.ini -u
10
+Then run :
11
+	./fip_current.sh
11 12
 
12 13
 Instances :
13 14
 -----------
@@ -19,8 +20,9 @@ Requierments :
19 20
 --------------
20 21
 
21 22
 icecast2
22
-python3
23
-python3-requests
23
+jq
24
+curl
25
+sed
24 26
 
25 27
 Icecast2 configuration sample :
26 28
 -------------------------------
@@ -32,9 +34,3 @@ Icecast2 configuration sample :
32 34
 	<local-mount>/fip-metadata.mp3</local-mount>
33 35
 	<relay-shoutcast-metadata>0</relay-shoutcast-metadata>
34 36
 </relay>
35
-
36
-Crontab :
37
----------
38
-
39
-#Update every minute
40
-* * * * * /path/fip_current.py -uc /path/conf.ini

+ 0
- 7
conf-sample.ini View File

@@ -1,7 +0,0 @@
1
-[conf]
2
-debug=false
3
-loop-delay=15
4
-host=127.0.0.1:8000
5
-mount=/fip.mp3
6
-login=admin
7
-password=hackme

+ 0
- 185
fip_current.py View File

@@ -1,185 +0,0 @@
1
-#!/usr/bin/python3
2
-#
3
-# Copyright 2016 Yann Weber
4
-#
5
-# This program is free software: you can redistribute it and/or modify
6
-# it under the terms of the GNU General Public License as published by
7
-# the Free Software Foundation, either version 3 of the License, or
8
-# any later version.
9
-#
10
-# This program is distributed in the hope that it will be useful,
11
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
-# GNU General Public License for more details.
14
-#
15
-# You should have received a copy of the GNU General Public License
16
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
-
18
-import sys
19
-import time
20
-import requests
21
-import configparser
22
-from argparse import ArgumentParser
23
-
24
-API_URL = 'http://www.fipradio.fr/livemeta/7'
25
-DEBUG = False
26
-
27
-
28
-def main():
29
-    """ Parse arguments and run wanted function """
30
-    parser = ArgumentParser(description="Fetch FIP radio stream metadata")
31
-    parser.add_argument(
32
-        '-u', '--icecast-update',
33
-        dest='update',
34
-        action='store_const',
35
-        const=True,
36
-        default=False,
37
-        help="Run Icecast2 metadata update")
38
-    parser.add_argument(
39
-        '-c', '--config',
40
-        dest='conf',
41
-        type=str,
42
-        default='conf.ini',
43
-        help="Configuration file")
44
-    parser.add_argument(
45
-        '-l', '--loop',
46
-        dest='loop',
47
-        action='store_const',
48
-        const=True,
49
-        default=False,
50
-        help="Combined with -u enables loop update")
51
-    """
52
-    parser.add_argument(
53
-        '-d', '--loop-delay',
54
-        dest='delay',
55
-        type=int,
56
-        default=15,
57
-        help="Loop delay in seconds")
58
-    """
59
-    args = parser.parse_args()
60
-    conf = configparser.ConfigParser()
61
-    conf.read(args.conf)
62
-    debug = conf.get('conf', 'debug', fallback="False").lower() == 'true'
63
-    globals()['DEBUG'] = debug
64
-    if args.update:
65
-        host = conf.get('conf', 'host', fallback='127.0.0.1:8000')
66
-        mount = conf.get('conf', 'mount', fallback='/example.ogg')
67
-        login = conf.get('conf', 'login', fallback='admin')
68
-        password = conf.get('conf', 'password', fallback='hackme')
69
-        if args.loop:
70
-            delay = conf.get('conf', 'loop-delay', fallback='15')
71
-            try:
72
-                delay = int(delay)
73
-            except ValueError:
74
-                msg = "loop-delay expected to be an integer '%s' found"
75
-                raise ValueError( msg % delay)
76
-            prev = None
77
-            while True:
78
-                try:
79
-                    if globals()['DEBUG']:
80
-                        print("Update start");
81
-                    prev = icecast_update(host, mount, login, password, prev)
82
-                    if globals()['DEBUG']:
83
-                        print("Updated");
84
-                    time.sleep(delay)
85
-                except Exception as e:
86
-                    prev = None
87
-                    print(str(e), file=sys.stderr)
88
-                
89
-        else:
90
-            icecast_update(host, mount, login, password)
91
-    else:
92
-        print(format_current())
93
-
94
-
95
-def get_all():
96
-    """ Return a dict containing all FIP API metadatas """
97
-    res = requests.get(API_URL)
98
-    if res.status_code != 200:
99
-        msg = "Got status code %d for %s"
100
-        msg %= (res.status_code, API_URL)
101
-        raise RuntimeError(msg)
102
-    return res.json()
103
-
104
-
105
-def get_current():
106
-    """ Return a dict containing currently playing song metadatas """
107
-    datas = get_all()
108
-    if len(datas['levels'])==2:
109
-        level = 1
110
-    else:
111
-        level = 0
112
-    position = datas['levels'][level]['position']
113
-    item_id = datas['levels'][level]['items'][position]
114
-    item = datas['steps'][item_id]
115
-    expt = ['authors', 'title', 'titreAlbum', 'visual', 'lienYoutube']
116
-    for k in expt:
117
-        if k not in item:
118
-            item[k] = ''
119
-
120
-    return item
121
-
122
-
123
-def format_current():
124
-    """ Return a string representing formated current playing song
125
-        metadatas """
126
-    item = get_current()
127
-    infos = """Title :\t\t{title}
128
-Authors :\t{author}
129
-Album :\t\t{album}
130
-Visual :\t{image}
131
-Youtube :\t{youtube}
132
-"""
133
-    res = infos.format(
134
-        title=item['title'].title(),
135
-        author=item['authors'].title(),
136
-        album=item['titreAlbum'].title(),
137
-        image=item['visual'],
138
-        youtube=item['lienYoutube'])
139
-    if globals()['DEBUG']:
140
-        res = "[debug mode]\n"+res
141
-    return res
142
-
143
-
144
-def icecast_infos():
145
-    """ Return formated Icecast2 metadatas from FIP current song
146
-        metadatas """
147
-    item = get_current()
148
-    infos = item['title'].title()
149
-    if len(item['authors']) > 0:
150
-        infos += ' - '+item['authors'].title()
151
-    if len(item['titreAlbum']):
152
-        infos += ' ('+item['titreAlbum'].title()+')'
153
-    if globals()['DEBUG']:
154
-        infos = infos + str(time.time())
155
-    return infos
156
-
157
-
158
-def icecast_update(host, mount, login=None, password=None, prev = None):
159
-    """ Update metadatas to an Icecast2 mount """
160
-    infos = icecast_infos()
161
-    url = "http://{host}/admin/metadata"
162
-    url = url.format(host=host)
163
-    params = {
164
-        'mount': mount,
165
-        'mode': 'updinfo',
166
-        'song': infos}
167
-    auth = None
168
-    if login is not None and password is not None:
169
-        auth = (login, password)
170
-    
171
-    if infos != prev:
172
-        try:
173
-            res = requests.get(url, auth=auth, params=params)
174
-        except requests.exceptions.ConnectionError:
175
-            raise RuntimeError("Connection refuse for "+res.url)
176
-
177
-        if res.status_code != 200:
178
-            msg = "Got status code %d for %s"
179
-            msg %= (res.status_code, res.url)
180
-            raise RuntimeError(msg)
181
-
182
-    return infos
183
-
184
-if __name__ == '__main__':
185
-    main()

+ 38
- 0
fip_current.sh View File

@@ -0,0 +1,38 @@
1
+#!/bin/sh
2
+host="ICECAST2_HOST:PORT"
3
+mount="/MOUNTPOINT"
4
+login="admin"
5
+passwd="hackme"
6
+
7
+
8
+
9
+fip_url="https://www.fip.fr/livemeta/7"
10
+fipmeta="/tmp/fip-meta"
11
+start=$(date "+%s")
12
+touch $fipmeta
13
+while [ 1 ]
14
+do
15
+	q='.["steps"][.["levels"][0]["items"][.["levels"][0]["position"]]] |.["end"], .["title"]+" - "+.["authors"]+" ("+.["titreAlbum"]+")"'
16
+	infos=$(curl -s $fip_url | jq -r "$q" )
17
+	title=$(echo $infos |cut -d" " -f"2-"| sed 's/[^ ]\+/\L\u&/g')
18
+	end=$(echo $infos |cut -d" " -f1)
19
+
20
+	if [ "$(cat $fipmeta)" != "$title" ]
21
+	then
22
+		echo -n $title > $fipmeta
23
+		echo $title
24
+		curl -s -G "http://${login}:${passwd}@${host}/admin/metadata" \
25
+			-d "mount=${mount}"
26
+			-d "mode=updinfo"
27
+			--data-urlencode "song=${title}" > /dev/null
28
+	fi
29
+
30
+	now=$(date "+%s")
31
+	if [ "$now" -gt "$end" ]
32
+	then
33
+		sleep 1
34
+	else
35
+		delay=$(expr $end - $now)
36
+		sleep $delay
37
+	fi
38
+done

+ 4
- 7
init_script View File

@@ -9,14 +9,11 @@
9 9
 # Description:       Start updating Icecast2 metadatas using FIP radio wep API
10 10
 ### END INIT INFO
11 11
 
12
-DPATH=/PUT/SCRIPT/PATH/HERE
12
+DPATH="PATH TO SCRIPT"
13 13
 
14
-SCRIPT="fip_current.py"
15
-DAEMON="${DPATH}/${SCRIPT}"
16
-CONFIG="${DPATH}/conf.ini"
14
+DAEMON="${DPATH}/fip_current.sh"
17 15
 NAME="fip-current"
18 16
 DESC="fip-current update script"
19
-DAEMON_OPTS="-ul -c $CONFIG"
20 17
 PIDFILE="/run/fip-current.pid"
21 18
 
22 19
 set_path()
@@ -38,14 +35,14 @@ case $1 in
38 35
 			echo -n " allready running"
39 36
 			log_end_msg 1
40 37
 		else
41
-			start-stop-daemon --quiet --start --background -m -p $PIDFILE --exec $DAEMON -- $DAEMON_OPTS
38
+			start-stop-daemon --quiet --start --background -m -p $PIDFILE --exec $DAEMON
42 39
 			log_end_msg $?
43 40
 		fi
44 41
 		
45 42
 		;;
46 43
 	stop)
47 44
 		log_daemon_msg "Stopping $DESC"
48
-		start-stop-daemon --stop -p $PIDFILE --remove-pidfile -x $DAEMON
45
+		start-stop-daemon --stop -p $PIDFILE --remove-pidfile
49 46
 		log_end_msg $?
50 47
 		;;
51 48
 	restart)

Loading…
Cancel
Save