Mercurial > libervia-backend
comparison sat/plugins/plugin_misc_radiocol.py @ 4037:524856bd7b19
massive refactoring to switch from camelCase to snake_case:
historically, Libervia (SàT before) was using camelCase as allowed by PEP8 when using a
pre-PEP8 code, to use the same coding style as in Twisted.
However, snake_case is more readable and it's better to follow PEP8 best practices, so it
has been decided to move on full snake_case. Because Libervia has a huge codebase, this
ended with a ugly mix of camelCase and snake_case.
To fix that, this patch does a big refactoring by renaming every function and method
(including bridge) that are not coming from Twisted or Wokkel, to use fully snake_case.
This is a massive change, and may result in some bugs.
author | Goffi <goffi@goffi.org> |
---|---|
date | Sat, 08 Apr 2023 13:54:42 +0200 |
parents | be6d91572633 |
children |
comparison
equal
deleted
inserted
replaced
4036:c4464d7ae97b | 4037:524856bd7b19 |
---|---|
63 # Maximum number of songs in the queue (the song being currently played doesn't count) | 63 # Maximum number of songs in the queue (the song being currently played doesn't count) |
64 QUEUE_LIMIT = 2 | 64 QUEUE_LIMIT = 2 |
65 | 65 |
66 | 66 |
67 class Radiocol(object): | 67 class Radiocol(object): |
68 def inheritFromRoomGame(self, host): | 68 def inherit_from_room_game(self, host): |
69 global RoomGame | 69 global RoomGame |
70 RoomGame = host.plugins["ROOM-GAME"].__class__ | 70 RoomGame = host.plugins["ROOM-GAME"].__class__ |
71 self.__class__ = type( | 71 self.__class__ = type( |
72 self.__class__.__name__, (self.__class__, RoomGame, object), {} | 72 self.__class__.__name__, (self.__class__, RoomGame, object), {} |
73 ) | 73 ) |
74 | 74 |
75 def __init__(self, host): | 75 def __init__(self, host): |
76 log.info(_("Radio collective initialization")) | 76 log.info(_("Radio collective initialization")) |
77 self.inheritFromRoomGame(host) | 77 self.inherit_from_room_game(host) |
78 RoomGame._init_( | 78 RoomGame._init_( |
79 self, | 79 self, |
80 host, | 80 host, |
81 PLUGIN_INFO, | 81 PLUGIN_INFO, |
82 (NC_RADIOCOL, RADIOC_TAG), | 82 (NC_RADIOCOL, RADIOC_TAG), |
87 "playing_time": 0, | 87 "playing_time": 0, |
88 "to_delete": {}, | 88 "to_delete": {}, |
89 }, | 89 }, |
90 ) | 90 ) |
91 self.host = host | 91 self.host = host |
92 host.bridge.addMethod( | 92 host.bridge.add_method( |
93 "radiocolLaunch", | 93 "radiocol_launch", |
94 ".plugin", | 94 ".plugin", |
95 in_sign="asss", | 95 in_sign="asss", |
96 out_sign="", | 96 out_sign="", |
97 method=self._prepareRoom, | 97 method=self._prepare_room, |
98 async_=True, | 98 async_=True, |
99 ) | 99 ) |
100 host.bridge.addMethod( | 100 host.bridge.add_method( |
101 "radiocolCreate", | 101 "radiocol_create", |
102 ".plugin", | 102 ".plugin", |
103 in_sign="sass", | 103 in_sign="sass", |
104 out_sign="", | 104 out_sign="", |
105 method=self._createGame, | 105 method=self._create_game, |
106 ) | 106 ) |
107 host.bridge.addMethod( | 107 host.bridge.add_method( |
108 "radiocolSongAdded", | 108 "radiocol_song_added", |
109 ".plugin", | 109 ".plugin", |
110 in_sign="sss", | 110 in_sign="sss", |
111 out_sign="", | 111 out_sign="", |
112 method=self._radiocolSongAdded, | 112 method=self._radiocol_song_added, |
113 async_=True, | 113 async_=True, |
114 ) | 114 ) |
115 host.bridge.addSignal( | 115 host.bridge.add_signal( |
116 "radiocolPlayers", ".plugin", signature="ssass" | 116 "radiocol_players", ".plugin", signature="ssass" |
117 ) # room_jid, referee, players, profile | 117 ) # room_jid, referee, players, profile |
118 host.bridge.addSignal( | 118 host.bridge.add_signal( |
119 "radiocolStarted", ".plugin", signature="ssasais" | 119 "radiocol_started", ".plugin", signature="ssasais" |
120 ) # room_jid, referee, players, [QUEUE_TO_START, QUEUE_LIMIT], profile | 120 ) # room_jid, referee, players, [QUEUE_TO_START, QUEUE_LIMIT], profile |
121 host.bridge.addSignal( | 121 host.bridge.add_signal( |
122 "radiocolSongRejected", ".plugin", signature="sss" | 122 "radiocol_song_rejected", ".plugin", signature="sss" |
123 ) # room_jid, reason, profile | 123 ) # room_jid, reason, profile |
124 host.bridge.addSignal( | 124 host.bridge.add_signal( |
125 "radiocolPreload", ".plugin", signature="ssssssss" | 125 "radiocol_preload", ".plugin", signature="ssssssss" |
126 ) # room_jid, timestamp, filename, title, artist, album, profile | 126 ) # room_jid, timestamp, filename, title, artist, album, profile |
127 host.bridge.addSignal( | 127 host.bridge.add_signal( |
128 "radiocolPlay", ".plugin", signature="sss" | 128 "radiocol_play", ".plugin", signature="sss" |
129 ) # room_jid, filename, profile | 129 ) # room_jid, filename, profile |
130 host.bridge.addSignal( | 130 host.bridge.add_signal( |
131 "radiocolNoUpload", ".plugin", signature="ss" | 131 "radiocol_no_upload", ".plugin", signature="ss" |
132 ) # room_jid, profile | 132 ) # room_jid, profile |
133 host.bridge.addSignal( | 133 host.bridge.add_signal( |
134 "radiocolUploadOk", ".plugin", signature="ss" | 134 "radiocol_upload_ok", ".plugin", signature="ss" |
135 ) # room_jid, profile | 135 ) # room_jid, profile |
136 | 136 |
137 def __create_preload_elt(self, sender, song_added_elt): | 137 def __create_preload_elt(self, sender, song_added_elt): |
138 preload_elt = copy.deepcopy(song_added_elt) | 138 preload_elt = copy.deepcopy(song_added_elt) |
139 preload_elt.name = "preload" | 139 preload_elt.name = "preload" |
141 preload_elt["timestamp"] = str(time.time()) | 141 preload_elt["timestamp"] = str(time.time()) |
142 # attributes filename, title, artist, album, length have been copied | 142 # attributes filename, title, artist, album, length have been copied |
143 # XXX: the frontend should know the temporary directory where file is put | 143 # XXX: the frontend should know the temporary directory where file is put |
144 return preload_elt | 144 return preload_elt |
145 | 145 |
146 def _radiocolSongAdded(self, referee_s, song_path, profile): | 146 def _radiocol_song_added(self, referee_s, song_path, profile): |
147 return self.radiocolSongAdded(jid.JID(referee_s), song_path, profile) | 147 return self.radiocol_song_added(jid.JID(referee_s), song_path, profile) |
148 | 148 |
149 def radiocolSongAdded(self, referee, song_path, profile): | 149 def radiocol_song_added(self, referee, song_path, profile): |
150 """This method is called by libervia when a song has been uploaded | 150 """This method is called by libervia when a song has been uploaded |
151 @param referee (jid.JID): JID of the referee in the room (room userhost + '/' + nick) | 151 @param referee (jid.JID): JID of the referee in the room (room userhost + '/' + nick) |
152 @param song_path (unicode): absolute path of the song added | 152 @param song_path (unicode): absolute path of the song added |
153 @param profile_key (unicode): %(doc_profile_key)s | 153 @param profile_key (unicode): %(doc_profile_key)s |
154 @return: a Deferred instance | 154 @return: a Deferred instance |
172 song = actual_song | 172 song = actual_song |
173 else: | 173 else: |
174 song = OggVorbis(song_path) | 174 song = OggVorbis(song_path) |
175 except (OggVorbisHeaderError, HeaderNotFoundError): | 175 except (OggVorbisHeaderError, HeaderNotFoundError): |
176 # this file is not ogg vorbis nor mp3, we reject it | 176 # this file is not ogg vorbis nor mp3, we reject it |
177 self.deleteFile(song_path) # FIXME: same host trick (see note above) | 177 self.delete_file(song_path) # FIXME: same host trick (see note above) |
178 return defer.fail( | 178 return defer.fail( |
179 exceptions.DataError( | 179 exceptions.DataError( |
180 D_( | 180 D_( |
181 "The uploaded file has been rejected, only Ogg Vorbis and MP3 songs are accepted." | 181 "The uploaded file has been rejected, only Ogg Vorbis and MP3 songs are accepted." |
182 ) | 182 ) |
198 ] = ( | 198 ] = ( |
199 song_path | 199 song_path |
200 ) # FIXME: works only because of the same host trick, see the note under the docstring | 200 ) # FIXME: works only because of the same host trick, see the note under the docstring |
201 return self.send(referee, ("", "song_added"), attrs, profile=profile) | 201 return self.send(referee, ("", "song_added"), attrs, profile=profile) |
202 | 202 |
203 def playNext(self, room_jid, profile): | 203 def play_next(self, room_jid, profile): |
204 """"Play next song in queue if exists, and put a timer | 204 """"Play next song in queue if exists, and put a timer |
205 which trigger after the song has been played to play next one""" | 205 which trigger after the song has been played to play next one""" |
206 # TODO: songs need to be erased once played or found invalids | 206 # TODO: songs need to be erased once played or found invalids |
207 # ==> unlink done the Q&D way with the same host trick (see above) | 207 # ==> unlink done the Q&D way with the same host trick (see above) |
208 radio_data = self.games[room_jid] | 208 radio_data = self.games[room_jid] |
209 if len(radio_data["players"]) == 0: | 209 if len(radio_data["players"]) == 0: |
210 log.debug(_("No more participants in the radiocol: cleaning data")) | 210 log.debug(_("No more participants in the radiocol: cleaning data")) |
211 radio_data["queue"] = [] | 211 radio_data["queue"] = [] |
212 for filename in radio_data["to_delete"]: | 212 for filename in radio_data["to_delete"]: |
213 self.deleteFile(filename, radio_data) | 213 self.delete_file(filename, radio_data) |
214 radio_data["to_delete"] = {} | 214 radio_data["to_delete"] = {} |
215 queue = radio_data["queue"] | 215 queue = radio_data["queue"] |
216 if not queue: | 216 if not queue: |
217 # nothing left to play, we need to wait for uploads | 217 # nothing left to play, we need to wait for uploads |
218 radio_data["playing"] = None | 218 radio_data["playing"] = None |
226 if not radio_data["upload"] and len(queue) < QUEUE_LIMIT: | 226 if not radio_data["upload"] and len(queue) < QUEUE_LIMIT: |
227 # upload is blocked and we now have resources to get more, we reactivate it | 227 # upload is blocked and we now have resources to get more, we reactivate it |
228 self.send(room_jid, ("", "upload_ok"), profile=profile) | 228 self.send(room_jid, ("", "upload_ok"), profile=profile) |
229 radio_data["upload"] = True | 229 radio_data["upload"] = True |
230 | 230 |
231 reactor.callLater(length, self.playNext, room_jid, profile) | 231 reactor.callLater(length, self.play_next, room_jid, profile) |
232 # we wait more than the song length to delete the file, to manage poorly reactive networks/clients | 232 # we wait more than the song length to delete the file, to manage poorly reactive networks/clients |
233 reactor.callLater( | 233 reactor.callLater( |
234 length + 90, self.deleteFile, filename, radio_data | 234 length + 90, self.delete_file, filename, radio_data |
235 ) # FIXME: same host trick (see above) | 235 ) # FIXME: same host trick (see above) |
236 | 236 |
237 def deleteFile(self, filename, radio_data=None): | 237 def delete_file(self, filename, radio_data=None): |
238 """ | 238 """ |
239 Delete a previously uploaded file. | 239 Delete a previously uploaded file. |
240 @param filename: filename to delete, or full filepath if radio_data is None | 240 @param filename: filename to delete, or full filepath if radio_data is None |
241 @param radio_data: current game data | 241 @param radio_data: current game data |
242 @return: True if the file has been deleted | 242 @return: True if the file has been deleted |
261 return True | 261 return True |
262 | 262 |
263 def room_game_cmd(self, mess_elt, profile): | 263 def room_game_cmd(self, mess_elt, profile): |
264 from_jid = jid.JID(mess_elt["from"]) | 264 from_jid = jid.JID(mess_elt["from"]) |
265 room_jid = from_jid.userhostJID() | 265 room_jid = from_jid.userhostJID() |
266 nick = self.host.plugins["XEP-0045"].getRoomNick(room_jid, profile) | 266 nick = self.host.plugins["XEP-0045"].get_room_nick(room_jid, profile) |
267 | 267 |
268 radio_elt = mess_elt.firstChildElement() | 268 radio_elt = mess_elt.firstChildElement() |
269 radio_data = self.games[room_jid] | 269 radio_data = self.games[room_jid] |
270 if "queue" in radio_data: | 270 if "queue" in radio_data: |
271 queue = radio_data["queue"] | 271 queue = radio_data["queue"] |
272 | 272 |
273 from_referee = self.isReferee(room_jid, from_jid.resource) | 273 from_referee = self.is_referee(room_jid, from_jid.resource) |
274 to_referee = self.isReferee(room_jid, jid.JID(mess_elt["to"]).user) | 274 to_referee = self.is_referee(room_jid, jid.JID(mess_elt["to"]).user) |
275 is_player = self.isPlayer(room_jid, nick) | 275 is_player = self.is_player(room_jid, nick) |
276 for elt in radio_elt.elements(): | 276 for elt in radio_elt.elements(): |
277 if not from_referee and not (to_referee and elt.name == "song_added"): | 277 if not from_referee and not (to_referee and elt.name == "song_added"): |
278 continue # sender must be referee, expect when a song is submitted | 278 continue # sender must be referee, expect when a song is submitted |
279 if not is_player and (elt.name not in ("started", "players")): | 279 if not is_player and (elt.name not in ("started", "players")): |
280 continue # user is in the room but not playing | 280 continue # user is in the room but not playing |
285 ): # new game created and/or players list updated | 285 ): # new game created and/or players list updated |
286 players = [] | 286 players = [] |
287 for player in elt.elements(): | 287 for player in elt.elements(): |
288 players.append(str(player)) | 288 players.append(str(player)) |
289 signal = ( | 289 signal = ( |
290 self.host.bridge.radiocolStarted | 290 self.host.bridge.radiocol_started |
291 if elt.name == "started" | 291 if elt.name == "started" |
292 else self.host.bridge.radiocolPlayers | 292 else self.host.bridge.radiocol_players |
293 ) | 293 ) |
294 signal( | 294 signal( |
295 room_jid.userhost(), | 295 room_jid.userhost(), |
296 from_jid.full(), | 296 from_jid.full(), |
297 players, | 297 players, |
298 [QUEUE_TO_START, QUEUE_LIMIT], | 298 [QUEUE_TO_START, QUEUE_LIMIT], |
299 profile, | 299 profile, |
300 ) | 300 ) |
301 elif elt.name == "preload": # a song is in queue and must be preloaded | 301 elif elt.name == "preload": # a song is in queue and must be preloaded |
302 self.host.bridge.radiocolPreload( | 302 self.host.bridge.radiocol_preload( |
303 room_jid.userhost(), | 303 room_jid.userhost(), |
304 elt["timestamp"], | 304 elt["timestamp"], |
305 elt["filename"], | 305 elt["filename"], |
306 elt["title"], | 306 elt["title"], |
307 elt["artist"], | 307 elt["artist"], |
308 elt["album"], | 308 elt["album"], |
309 elt["sender"], | 309 elt["sender"], |
310 profile, | 310 profile, |
311 ) | 311 ) |
312 elif elt.name == "play": | 312 elif elt.name == "play": |
313 self.host.bridge.radiocolPlay( | 313 self.host.bridge.radiocol_play( |
314 room_jid.userhost(), elt["filename"], profile | 314 room_jid.userhost(), elt["filename"], profile |
315 ) | 315 ) |
316 elif elt.name == "song_rejected": # a song has been refused | 316 elif elt.name == "song_rejected": # a song has been refused |
317 self.host.bridge.radiocolSongRejected( | 317 self.host.bridge.radiocol_song_rejected( |
318 room_jid.userhost(), elt["reason"], profile | 318 room_jid.userhost(), elt["reason"], profile |
319 ) | 319 ) |
320 elif elt.name == "no_upload": | 320 elif elt.name == "no_upload": |
321 self.host.bridge.radiocolNoUpload(room_jid.userhost(), profile) | 321 self.host.bridge.radiocol_no_upload(room_jid.userhost(), profile) |
322 elif elt.name == "upload_ok": | 322 elif elt.name == "upload_ok": |
323 self.host.bridge.radiocolUploadOk(room_jid.userhost(), profile) | 323 self.host.bridge.radiocol_upload_ok(room_jid.userhost(), profile) |
324 elif elt.name == "song_added": # a song has been added | 324 elif elt.name == "song_added": # a song has been added |
325 # FIXME: we are KISS for the proof of concept: every song is added, to a limit of 3 in queue. | 325 # FIXME: we are KISS for the proof of concept: every song is added, to a limit of 3 in queue. |
326 # Need to manage some sort of rules to allow peoples to send songs | 326 # Need to manage some sort of rules to allow peoples to send songs |
327 if len(queue) >= QUEUE_LIMIT: | 327 if len(queue) >= QUEUE_LIMIT: |
328 # there are already too many songs in queue, we reject this one | 328 # there are already too many songs in queue, we reject this one |
346 | 346 |
347 self.send(room_jid, preload_elt, profile=profile) | 347 self.send(room_jid, preload_elt, profile=profile) |
348 if not radio_data["playing"] and len(queue) == QUEUE_TO_START: | 348 if not radio_data["playing"] and len(queue) == QUEUE_TO_START: |
349 # We have not started playing yet, and we have QUEUE_TO_START | 349 # We have not started playing yet, and we have QUEUE_TO_START |
350 # songs in queue. We can now start the party :) | 350 # songs in queue. We can now start the party :) |
351 self.playNext(room_jid, profile) | 351 self.play_next(room_jid, profile) |
352 else: | 352 else: |
353 log.error(_("Unmanaged game element: %s") % elt.name) | 353 log.error(_("Unmanaged game element: %s") % elt.name) |
354 | 354 |
355 def getSyncDataForPlayer(self, room_jid, nick): | 355 def get_sync_data_for_player(self, room_jid, nick): |
356 game_data = self.games[room_jid] | 356 game_data = self.games[room_jid] |
357 elements = [] | 357 elements = [] |
358 if game_data["playing"]: | 358 if game_data["playing"]: |
359 preload = copy.deepcopy(game_data["playing"]) | 359 preload = copy.deepcopy(game_data["playing"]) |
360 current_time = game_data["playing_time"] + 1 if self.testing else time.time() | 360 current_time = game_data["playing_time"] + 1 if self.testing else time.time() |