-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathts3base.py
224 lines (202 loc) · 7.47 KB
/
ts3base.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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
import os
import threading
import time
from functools import partial
from collections import defaultdict
from pluginbase import PluginBase
from ts3socket import ts3socket
from ts3tools import ts3tools
from myexception import MyException
from threading import Thread
from threading import Lock
# For easier usage calculate the path relative to here.
here = os.path.abspath(os.path.dirname(__file__))
get_path = partial(os.path.join, here)
class ts3base(threading.Thread):
def __init__(self, config):
"""
Creates a new instance of ts3base and initializes all neccessary parameters
"""
# init threading
threading.Thread.__init__(self)
# set config for whole class
self.config = config
# debug message
self.debprint('instance initialized')
# init callbacks
self.callbacks = defaultdict(dict)
# list of all classes (instances, objects, however)
self.classes = {}
# identifier + package name for pluginbase
self.identifier = config['id']
self.package = 'ts3eventscripts' + self.identifier
# init pluginbase
self.pluginbase = PluginBase(package=self.package)
# lock for command socket send & receive method
self.sendlock = Lock()
# init ts3 connection
self.ts3_init()
# load user plugins
self.plugin_load()
for plugin in self.pluginsource.list_plugins():
self.debprint(plugin)
# init all plugins
self.plugin_init()
def ts3_init(self):
"""
Initialization of the ts3eventscript sockets for teamspeak3
"""
# init ts3 query socket (command socket)
self.command_socket = ts3socket(
self.config['ip'],
int(self.config['port']),
int(self.config['sid']),
self.config['user'],
self.config['pass'])
# debug message
self.debprint('command socket initialized')
# init event socket for event thread
self.event_socket = ts3socket(
self.config['ip'],
int(self.config['port']),
int(self.config['sid']),
self.config['user'],
self.config['pass'])
# send register commands
self.event_socket.send('servernotifyregister event=server')
self.event_socket.send('servernotifyregister event=textprivate')
self.event_socket.send('servernotifyregister event=textserver')
# init event thread
self.event_thread = Thread(target=self.event_process)
self.event_thread.daemon = True
self.event_thread.start()
self.debprint('initialized event socket in thread')
def plugin_load(self):
"""
Load plugins specified from a user
"""
paths = []
for path in os.listdir(get_path('./plugins/')):
paths.append('./plugins/' + path)
self.pluginsource = self.pluginbase.make_plugin_source(
# core plugins are loaded for any instance. Other plugins are handled later on
searchpath=paths, identifier=self.identifier)
def plugin_init(self):
"""
Init plugins for this instance
"""
self.debprint('loading plugins')
plugins = self.config['plugins'].split(',')
# load core plugins first
for plugin_name in self.pluginsource.list_plugins():
author = plugin_name.split('_', 1)[0]
if author == 'core':
plugin = self.pluginsource.load_plugin(plugin_name)
plugin.setup(self) # pass ts3base instance to plugin
# load user plugins next
for plugin_name in self.pluginsource.list_plugins():
if plugin_name in plugins:
plugin = self.pluginsource.load_plugin(plugin_name)
plugin.setup(self) # pass ts3base instance to plugin
def event_process(self):
"""
The event process is called in the event thread. It's the socket receiver.
When received an event, execute a callback named "ts3.receivedevent" with raw event data
"""
while 1:
event = self.event_socket.receive()
self.execute_callback('ts3.receivedevent', event)
def get_event_socket(self):
"""
Get the event socket
"""
return self.event_socket
def get_command_socket(self):
"""
Get the command socket
"""
return self.command_socket
def send_receive(self, cmd):
"""
Locks (so that other plugins must wait before doing something), sends the specified command and waits for answer message.
Uses the command socket only!
"""
with self.sendlock:
self.command_socket.send(cmd)
return self.command_socket.recv_all()
def register_callback(self, plugin, key, function):
"""
Register a new callback
"""
self.callbacks[key][plugin + '_' + function.__name__] = function
# debug message
self.debprint(
'plugin ' +
plugin +
' -> (func)' +
function.__name__ +
' -> (callback)' +
key)
def execute_callback(self, key, values):
"""
Execute all plugin callbacks from a specific type in a separate thread
"""
if key in self.callbacks:
for index, func in self.callbacks[key].items():
t = Thread(target=func, args=(values,))
t.daemon = True
t.start()
def get_class(self, pluginname):
"""
If avaiable, returns a dictionary with name of the plugin (index is "plugin")
and the function used to call the given method (index is "function").
"""
if pluginname in self.classes.keys():
return self.classes[pluginname]
else:
return None
def get_class_list(self):
"""
Returns a list (names only) with all classes registered here.
The names can be used to get the class with get_class()
"""
return self.classes.keys()
def register_class(self, key, plugin):
"""
Registers a class which can be used from plugins.
-> classes can be used from plugins to communicate with each other
"""
self.classes[key] = plugin(self)
self.debprint(
'plugin ' +
key +
' registered class ' +
plugin.__name__)
def debprint(self, msg):
"""
Prints a debug message to the console
"""
print(self.config['id'] + ' - ' + msg)
def run(self):
"""
Main class to keep ts3base.py running forever
"""
try:
# set nickname to instance id to identify itself (set some id's)
ts3tools.set_nickname(self, self.config['id'])
answer = ts3tools.parse_raw_answer(self.send_receive('clientfind pattern=' + self.config['id']))
self.clid = answer['clid']
# debug message
self.debprint('The bot has the following client id: ' + self.clid)
# set nickname
ts3tools.set_nickname(self, self.config['name'])
# execute start event
self.execute_callback('ts3.start', {})
while 1:
# loop callback
self.execute_callback('ts3.loop', {})
# sleep a half second
time.sleep(0.5)
except MyException as e:
print(str(e))
exit()