-
Notifications
You must be signed in to change notification settings - Fork 81
/
channels.py
157 lines (118 loc) · 5.2 KB
/
channels.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
# -*- coding: utf-8 -*-
from constants import *
from threading import Lock
from errors import UnknownChannelError
import messages
class Channels(dict):
"""
Object that Stores all channels and their properties.
"""
def __init__(self, mumble_object, callbacks):
self.mumble_object = mumble_object
self.callbacks = callbacks
self.lock = Lock()
def update(self, message):
"""Update the channel informations based on an incoming message"""
self.lock.acquire()
if message.channel_id not in self: # create the channel
self[message.channel_id] = Channel(self.mumble_object, message)
self.callbacks(PYMUMBLE_CLBK_CHANNELCREATED, self[message.channel_id])
else: # update the channel
actions = self[message.channel_id].update(message)
self.callbacks(PYMUMBLE_CLBK_CHANNELUPDATED, self[message.channel_id], actions)
self.lock.release()
def remove(self, id):
"""Delete a channel when server signal the channel is removed"""
self.lock.acquire()
if id in self:
channel = self[id]
del self[id]
self.callbacks(PYMUMBLE_CLBK_CHANNELREMOVED, channel)
self.lock.release()
def find_by_tree(self, tree):
"""Find a channel by its full path (a list with an element for each leaf)"""
if not getattr(tree, '__iter__', False):
tree = (tree) # function use argument as a list
current=self[0]
for name in tree: # going up the tree
for subchannel in self.get_childs(current).itervalues():
found = False
if subchannel["name"] == name:
current=subchannel
found = True
break
if not found: # channel not found
err = "Cannot find channel %s" % str(tree)
raise UnknownChannelError(err)
return current
def get_childs(self, channel):
"""Get the childs of a channel in a list"""
childs = list()
for item in self.itervalues():
if item["parent"] == channel["channel_id"]:
childs.append(item)
return childs
def get_descendants(self, channel):
"""Get all the descendant of a channel, in nested lists"""
descendants = list()
for subchannel in channel.get_childs():
descendants.append(subchannel.get_childs())
return descendants
def get_tree(self, channel):
"""Get the whole list of channels, in a multidimensionnal list"""
tree= list()
current = channel
while current["channel_id"] != 0:
tree.insert(0, current)
current = self[current["channel_id"]]
tree.insert(0, self[0])
return tree
def find_by_name(self, name):
"""Find a channel by name. Stop on the first that match"""
if name == "":
return self[0]
for obj in self.values():
if obj["name"] == name:
return obj
err = "Channel %s does not exists" % name
raise UnknownChannelError(err)
class Channel(dict):
"""
Stores informations about one specific channel
"""
def __init__(self, mumble_object, message):
self.mumble_object = mumble_object
self["channel_id"] = message.channel_id
self.update(message)
def update(self, message):
"""Update a channel based on an incoming message"""
actions = dict()
for (field, value) in message.ListFields():
if field.name in ("session", "actor", "description_hash"):
continue
actions.update(self.update_field(field.name, value))
if message.HasField("description_hash"):
actions.update(self.update_field("description_hash", message.description_hash))
if message.HasField("description"):
self.mumble_object.blobs[message.description_hash] = message.description
else:
self.mumble_object.blobs.get_channel_description(message.description_hash)
return(actions) # return a dict with updates performed, useful for the callback functions
def update_field(self, name, field):
"""Update one value"""
actions = dict()
if name not in self or self[name] != field:
self[name] = field
actions[name] = field
return(actions) # return a dict with updates performed, useful for the callback functions
def get_property(self, property):
if property in self:
return(self[property])
else:
return None
def move_in(self, session=None):
"""Ask to move a session in a specific channel. By default move pymumble own session"""
if session == None:
session = self.mumble_object.users.myself_session
cmd = messages.MoveCmd(session, self["channel_id"])
self.mumble_object.execute_command(cmd)