Mercurial > libervia-backend
comparison src/plugins/plugin_misc_radiocol.py @ 765:787ee59dba9c
plugins radiocol, xep-0054: better handling of upload errors:
- radiocolSongAdded is now asynchronous
- _buildAvatar return a Failure if the image is not readable
author | souliane <souliane@mailoo.org> |
---|---|
date | Tue, 17 Dec 2013 18:44:53 +0100 |
parents | d0e809014ea2 |
children | bfabeedbf32e |
comparison
equal
deleted
inserted
replaced
764:d0e809014ea2 | 765:787ee59dba9c |
---|---|
19 | 19 |
20 from logging import debug, info, warning, error | 20 from logging import debug, info, warning, error |
21 from twisted.words.xish import domish | 21 from twisted.words.xish import domish |
22 from twisted.internet import reactor | 22 from twisted.internet import reactor |
23 from twisted.words.protocols.jabber import jid | 23 from twisted.words.protocols.jabber import jid |
24 | 24 from twisted.internet import threads, defer |
25 from sat.core import exceptions | |
25 import os.path | 26 import os.path |
26 import copy | 27 import copy |
27 import time | 28 import time |
28 from os import unlink | 29 from os import unlink |
29 from mutagen.oggvorbis import OggVorbis, OggVorbisHeaderError | 30 from mutagen.oggvorbis import OggVorbis, OggVorbisHeaderError |
63 RoomGame._init_(self, host, PLUGIN_INFO, (NC_RADIOCOL, RADIOC_TAG), | 64 RoomGame._init_(self, host, PLUGIN_INFO, (NC_RADIOCOL, RADIOC_TAG), |
64 game_init={'queue': [], 'upload': True, 'playing': False, 'to_delete': {}}) | 65 game_init={'queue': [], 'upload': True, 'playing': False, 'to_delete': {}}) |
65 self.host = host | 66 self.host = host |
66 host.bridge.addMethod("radiocolLaunch", ".plugin", in_sign='asss', out_sign='', method=self.prepareRoom) | 67 host.bridge.addMethod("radiocolLaunch", ".plugin", in_sign='asss', out_sign='', method=self.prepareRoom) |
67 host.bridge.addMethod("radiocolCreate", ".plugin", in_sign='sass', out_sign='', method=self.createGame) | 68 host.bridge.addMethod("radiocolCreate", ".plugin", in_sign='sass', out_sign='', method=self.createGame) |
68 host.bridge.addMethod("radiocolSongAdded", ".plugin", in_sign='sss', out_sign='', method=self.radiocolSongAdded) | 69 host.bridge.addMethod("radiocolSongAdded", ".plugin", in_sign='sss', out_sign='', method=self.radiocolSongAdded, async=True) |
69 host.bridge.addSignal("radiocolPlayers", ".plugin", signature='ssass') # room_jid, referee, players, profile | 70 host.bridge.addSignal("radiocolPlayers", ".plugin", signature='ssass') # room_jid, referee, players, profile |
70 host.bridge.addSignal("radiocolStarted", ".plugin", signature='ssasais') # room_jid, referee, players, [QUEUE_TO_START, QUEUE_LIMIT], profile | 71 host.bridge.addSignal("radiocolStarted", ".plugin", signature='ssasais') # room_jid, referee, players, [QUEUE_TO_START, QUEUE_LIMIT], profile |
71 host.bridge.addSignal("radiocolSongRejected", ".plugin", signature='sss') # room_jid, reason, profile | 72 host.bridge.addSignal("radiocolSongRejected", ".plugin", signature='sss') # room_jid, reason, profile |
72 host.bridge.addSignal("radiocolPreload", ".plugin", signature='sssssss') # room_jid, timestamp, filename, title, artist, album, profile | 73 host.bridge.addSignal("radiocolPreload", ".plugin", signature='sssssss') # room_jid, timestamp, filename, title, artist, album, profile |
73 host.bridge.addSignal("radiocolPlay", ".plugin", signature='sss') # room_jid, filename, profile | 74 host.bridge.addSignal("radiocolPlay", ".plugin", signature='sss') # room_jid, filename, profile |
92 # be streamed to the backend using XMPP file copy | 93 # be streamed to the backend using XMPP file copy |
93 # Here we cheat because we know we are on the same host, and we don't | 94 # Here we cheat because we know we are on the same host, and we don't |
94 # check data. Referee will have to parse the song himself to check it | 95 # check data. Referee will have to parse the song himself to check it |
95 client = self.host.getClient(profile) | 96 client = self.host.getClient(profile) |
96 if not client: | 97 if not client: |
97 error(_("Can't access profile's data")) | 98 raise exceptions.NotConnectedProfileError(_("Can't access profile's data")) |
98 return | |
99 try: | 99 try: |
100 song = OggVorbis(song_path) | 100 song = OggVorbis(song_path) |
101 except OggVorbisHeaderError: | 101 except OggVorbisHeaderError: |
102 #this file is not ogg vorbis, we reject it | 102 #this file is not ogg vorbis, we reject it |
103 self.deleteFile(song_path) # FIXME: same host trick (see note above) | 103 self.deleteFile(song_path) # FIXME: same host trick (see note above) |
104 self.host.bridge.radiocolSongRejected(jid.JID(referee).userhost(), | 104 return defer.fail(exceptions.DataError("Uploaded file is not Ogg Vorbis song, only Ogg Vorbis songs are acceptable")) |
105 "Uploaded file is not Ogg Vorbis song, only Ogg Vorbis songs are acceptable", profile) | |
106 """mess = self.createGameElt(jid.JID(referee)) | |
107 reject_elt = mess.firstChildElement().addElement(('','song_rejected')) | |
108 reject_elt['sender'] = client.jid | |
109 reject_elt['reason'] = "Uploaded file is not Ogg Vorbis song, only Ogg Vorbis songs are acceptable" | |
110 #FIXME: add an error code | |
111 self.host.profiles[profile].xmlstream.send(mess)""" | |
112 return | |
113 attrs = {'filename': os.path.basename(song_path), | 105 attrs = {'filename': os.path.basename(song_path), |
114 'title': song.get("title", ["Unknown"])[0], | 106 'title': song.get("title", ["Unknown"])[0], |
115 'artist': song.get("artist", ["Unknown"])[0], | 107 'artist': song.get("artist", ["Unknown"])[0], |
116 'album': song.get("album", ["Unknown"])[0], | 108 'album': song.get("album", ["Unknown"])[0], |
117 'length': str(song.info.length) | 109 'length': str(song.info.length) |
118 } | 110 } |
119 self.send(jid.JID(referee), ('', 'song_added'), attrs, profile=profile) | |
120 | |
121 radio_data = self.games[jid.JID(referee).userhost()] # FIXME: referee comes from Libervia's client side, it's unsecure | 111 radio_data = self.games[jid.JID(referee).userhost()] # FIXME: referee comes from Libervia's client side, it's unsecure |
122 radio_data['to_delete'][attrs['filename']] = song_path # FIXME: works only because of the same host trick, see the note under the docstring | 112 radio_data['to_delete'][attrs['filename']] = song_path # FIXME: works only because of the same host trick, see the note under the docstring |
113 return threads.deferToThread(self.send, jid.JID(referee), ('', 'song_added'), attrs, profile=profile) | |
123 | 114 |
124 def playNext(self, room_jid, profile): | 115 def playNext(self, room_jid, profile): |
125 """"Play next song in queue if exists, and put a timer | 116 """"Play next song in queue if exists, and put a timer |
126 which trigger after the song has been played to play next one""" | 117 which trigger after the song has been played to play next one""" |
127 #TODO: songs need to be erased once played or found invalids | 118 #TODO: songs need to be erased once played or found invalids |