Skip to content
This repository was archived by the owner on Apr 27, 2019. It is now read-only.

Commit 201b399

Browse files
committed
Merge pull request #160 from 8r2y5/feature/142
[142] Fixed problem with mapping overridden packet
2 parents 839834e + fa422f3 commit 201b399

18 files changed

+352
-54
lines changed

.gitignore

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
.cache
12
*.py[cod]
23

34
# C extensions
@@ -51,4 +52,5 @@ nosetests.xml
5152
# Mac cleanup
5253
.DS_Store
5354

54-
cover
55+
cover
56+
.noseids

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
StarryPy is Twisted-based plugin-driven Starbound server wrapper. It is currently in beta.
44

5+
# The build is currently broken while we are applying a PEP8 pull request.
6+
57
## Features
68

79
With the built-in plugins (which are removable):

base_plugin.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class MapOverridePacketsMethods(type):
1212

1313
def __new__(cls, name, bases, cls_dict):
1414
if name != 'BasePlugin':
15-
cls_dict['overridden_packets'] = {}
15+
cls_dict['overridden_methods'] = {}
1616
methods = (
1717
key for key, value in cls_dict.iteritems()
1818
if key not in cls.ignored_methods and callable(value)
@@ -23,7 +23,7 @@ def __new__(cls, name, bases, cls_dict):
2323
packet_name = packet.group('packet_name').upper()
2424
enum = getattr(Packets, packet_name, None)
2525
if enum:
26-
cls_dict['overridden_packets'].setdefault(
26+
cls_dict['overridden_methods'].setdefault(
2727
enum.value, {}
2828
)[packet.group('when')] = packet_method_name
2929

@@ -59,11 +59,13 @@ class BasePlugin(object):
5959
active = False
6060

6161
def __init__(self, *args, **kwargs):
62+
self.overridden_methods = {}
6263
super(BasePlugin, self).__init__(*args, **kwargs)
6364
if self.__class__.__name__ != 'BasePlugin':
64-
for packet, when_dict in self.overridden_packets.iteritems():
65+
for packet, when_dict in self.overridden_methods.iteritems():
66+
self.overridden_methods.setdefault(packet, {})
6567
for when, packet_name in when_dict.iteritems():
66-
self.overridden_packets[packet][when] = getattr(
68+
self.overridden_methods[packet][when] = getattr(
6769
self, packet_name
6870
)
6971

plugin_manager.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,8 @@ def load_plugins(self, plugins_to_load):
208208
def activate_plugins(self, plugins, dependencies):
209209
for plugin in (self.plugins_waiting_to_load[x] for x in plugins):
210210
try:
211-
self.plugins[plugin.name] = plugin()
211+
instance = plugin()
212+
self.plugins[plugin.name] = instance
212213
self.logger.debug('Instantiated plugin "%s"', plugin.name)
213214
if len(plugin.depends) > 0:
214215
plugin_deps = (
@@ -217,7 +218,7 @@ def activate_plugins(self, plugins, dependencies):
217218
for p in plugin_deps:
218219
self.plugin_classes[plugin.name].plugins[p.name] = p
219220
self.plugins[plugin.name].activate()
220-
self.map_plugin_packets(plugin)
221+
self.map_plugin_packets(instance)
221222
except FatalPluginError as e:
222223
self.logger.critical(
223224
'A plugin reported a fatal error. Error: %s', str(e)
@@ -275,7 +276,7 @@ def map_plugin_packets(self, plugin):
275276
"""
276277
Maps plugin overridden packets ready to use in do method.
277278
"""
278-
for packet_id, when_dict in plugin.overridden_packets.iteritems():
279+
for packet_id, when_dict in plugin.overridden_methods.iteritems():
279280
for when, packet_method in when_dict.iteritems():
280281
self.packets.setdefault(
281282
packet_id, {}

plugins/admin_messenger/admin_messenger.py

+33-25
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class AdminMessenger(BasePlugin):
99
"""
1010
Adds support to message moderators/admins/owner with a @@ prefixed message.
1111
"""
12-
name = "admin_messenger"
12+
name = 'admin_messenger'
1313
depends = ['player_manager_plugin']
1414

1515
def activate(self):
@@ -26,48 +26,56 @@ def on_chat_sent(self, data):
2626
return False
2727
return True
2828

29-
def message_admins(self, message):
30-
now = datetime.now()
29+
def add_timestamp(self, add_normalizer=False):
3130
if self.config.chattimestamps:
32-
timestamp = "^red;<{}> ^yellow;".format(now.strftime("%H:%M"))
31+
now = datetime.now()
32+
timestamp = '^red;<{}> '.format(now.strftime('%H:%M'))
33+
if add_normalizer:
34+
return '{}^yellow;'.format(timestamp)
35+
return timestamp
3336
else:
34-
timestamp = ""
37+
return ''
38+
39+
def message_admins(self, message):
40+
timestamp = self.add_timestamp(add_normalizer=True)
41+
message = message.message[2:].decode('utf-8')
42+
3543
for protocol in self.factory.protocols.itervalues():
3644
if protocol.player.access_level >= UserLevels.MODERATOR:
3745
protocol.send_chat_message(
38-
"{}{}ADMIN: ^yellow;<{}^yellow;> {}{}".format(
39-
timestamp,
40-
self.config.colors["moderator"],
41-
self.protocol.player.colored_name(self.config.colors),
42-
self.config.colors["moderator"],
43-
message.message[2:].decode("utf-8")
46+
'{timestamp}{moderator_colors}'
47+
'ADMIN: ^yellow;<{player_colors}^yellow;> '
48+
'{moderator_colors}{message}'.format(
49+
timestamp=timestamp,
50+
moderator_colors=self.config.colors['moderator'],
51+
player_colors=(
52+
self.protocol.player.colored_name(
53+
self.config.colors
54+
)
55+
),
56+
message=message
4457
)
4558
)
4659
self.logger.info(
47-
"Received an admin message from %s. Message: %s",
48-
self.protocol.player.name,
49-
message.message[2:].decode("utf-8")
60+
'Received an admin message from %s. Message: %s',
61+
self.protocol.player.name, message
5062
)
5163

5264
@permissions(UserLevels.ADMIN)
5365
def broadcast_message(self, message):
54-
now = datetime.now()
55-
if self.config.chattimestamps:
56-
timestamp = "^red;<{}> ".format(now.strftime("%H:%M"))
57-
else:
58-
timestamp = ""
66+
timestamp = self.add_timestamp()
5967

6068
for protocol in self.factory.protocols.itervalues():
6169
protocol.send_chat_message(
62-
"{}{}BROADCAST: ^red;{}{}".format(
70+
'{}{}BROADCAST: ^red;{}{}'.format(
6371
timestamp,
64-
self.config.colors["admin"],
65-
message.message[3:].decode("utf-8").upper(),
66-
self.config.colors["default"]
72+
self.config.colors['admin'],
73+
message.message[3:].decode('utf-8').upper(),
74+
self.config.colors['default']
6775
)
6876
)
6977
self.logger.info(
70-
"Broadcast from %s. Message: %s",
78+
'Broadcast from %s. Message: %s',
7179
self.protocol.player.name,
72-
message.message[3:].decode("utf-8").upper()
80+
message.message[3:].decode('utf-8').upper()
7381
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
from unittest import TestCase
2+
from datetime import datetime
3+
4+
from mock import Mock, patch
5+
6+
from plugins.admin_messenger.admin_messenger import AdminMessenger
7+
from plugins.core.player_manager_plugin import UserLevels
8+
9+
10+
class AdminMessengerTestCase(TestCase):
11+
def test_activate(self):
12+
plugin = AdminMessenger()
13+
plugin.config = Mock(chat_prefix='test prefix')
14+
15+
with self.assertRaises(AttributeError):
16+
self.plugin.prefix
17+
18+
plugin.activate()
19+
self.assertEqual(plugin.prefix, 'test prefix')
20+
21+
@patch.object(AdminMessenger, 'message_admins')
22+
@patch.object(AdminMessenger, 'broadcast_message')
23+
@patch('plugins.admin_messenger.admin_messenger.packets')
24+
def test_on_chat_sent_broadcast(
25+
self, mock_packets, mock_broadcast, mock_admins
26+
):
27+
mock_parse = Mock()
28+
message = Mock(message='###broadcast message')
29+
mock_parse.parse.return_value = message
30+
mock_packets.chat_sent.return_value = mock_parse
31+
mock_data = Mock(data='test data')
32+
plugin = AdminMessenger()
33+
plugin.config = Mock()
34+
plugin.activate()
35+
plugin.prefix = '#'
36+
37+
self.assertFalse(plugin.on_chat_sent(mock_data))
38+
mock_parse.parse.assert_called_with('test data')
39+
mock_broadcast.assert_called_with(message)
40+
41+
@patch.object(AdminMessenger, 'message_admins')
42+
@patch.object(AdminMessenger, 'broadcast_message')
43+
@patch('plugins.admin_messenger.admin_messenger.packets')
44+
def test_on_chat_sent_message_admins(
45+
self, mock_packets, mock_broadcast, mock_admins
46+
):
47+
plugin = AdminMessenger()
48+
plugin.config = Mock()
49+
plugin.activate()
50+
plugin.prefix = '#'
51+
mock_parse = Mock()
52+
mock_data = Mock(data='test data')
53+
message = Mock(message='##admin message')
54+
mock_parse.parse.return_value = message
55+
mock_packets.chat_sent.return_value = mock_parse
56+
57+
self.assertFalse(plugin.on_chat_sent(mock_data))
58+
mock_admins.assert_called_with(message)
59+
60+
@patch.object(AdminMessenger, 'message_admins')
61+
@patch.object(AdminMessenger, 'broadcast_message')
62+
@patch('plugins.admin_messenger.admin_messenger.packets')
63+
def test_on_chat_sent_normal_message(
64+
self, mock_packets, mock_broadcast, mock_admins
65+
):
66+
mock_parse = Mock()
67+
mock_data = Mock(data='test data')
68+
plugin = AdminMessenger()
69+
plugin.config = Mock()
70+
plugin.activate()
71+
plugin.prefix = '#'
72+
message = Mock(message='test message')
73+
mock_parse.parse.return_value = message
74+
75+
self.assertTrue(plugin.on_chat_sent(mock_data))
76+
self.assertFalse(mock_admins.called)
77+
self.assertFalse(mock_broadcast.called)
78+
79+
@patch('plugins.admin_messenger.admin_messenger.datetime')
80+
def test_add_timestamp(self, mock_datetime):
81+
current_datetime = datetime.now()
82+
mock_datetime.now.return_value = current_datetime
83+
plugin = AdminMessenger()
84+
plugin.config = Mock()
85+
86+
result = plugin.add_timestamp()
87+
self.assertEqual(
88+
result,
89+
'^red;<{}> '.format(current_datetime.strftime('%H:%M'))
90+
)
91+
92+
result = plugin.add_timestamp(True)
93+
self.assertEqual(
94+
result,
95+
'^red;<{}> ^yellow;'.format(current_datetime.strftime('%H:%M'))
96+
)
97+
98+
plugin.config.chattimestamps = False
99+
result = plugin.add_timestamp()
100+
self.assertEqual(result, '')
101+
102+
@patch.object(AdminMessenger, 'add_timestamp')
103+
def test_message_admins(self, mock_add_timestamp):
104+
mock_logger = Mock()
105+
mock_config = Mock()
106+
mock_config.colors = {'moderator': 'moderator colors'}
107+
mock_message = Mock()
108+
mock_message.message = '##test'
109+
mock_add_timestamp.return_value = 'with add_normalizer'
110+
mock_just_player = Mock()
111+
mock_just_player.player.access_level = UserLevels.GUEST
112+
mock_player_moderator = Mock()
113+
mock_player_moderator.player.access_level = UserLevels.MODERATOR
114+
mock_factory = Mock()
115+
mock_factory.protocols = {
116+
'normal player': mock_just_player,
117+
'moderator': mock_player_moderator
118+
}
119+
mock_protocol = Mock()
120+
mock_protocol.player.colored_name.return_value = 'player colors'
121+
plugin = AdminMessenger()
122+
plugin.factory = mock_factory
123+
plugin.config = mock_config
124+
plugin.logger = mock_logger
125+
plugin.protocol = mock_protocol
126+
127+
plugin.message_admins(mock_message)
128+
mock_player_moderator.send_chat_message.assert_called_with(
129+
'{}{}ADMIN: ^yellow;<{}^yellow;> {}{}'.format(
130+
'with add_normalizer',
131+
'moderator colors',
132+
'player colors',
133+
'moderator colors',
134+
'test'
135+
)
136+
)
137+
mock_logger.info.assert_called_with(
138+
'Received an admin message from %s. Message: %s',
139+
mock_protocol.player.name, 'test'
140+
)
141+
self.assertFalse(mock_just_player.send_chat_message.called)
142+
mock_add_timestamp.assert_called_with(add_normalizer=True)
143+
144+
@patch.object(AdminMessenger, 'add_timestamp')
145+
def test_broadcast_message(self, mock_add_timestamp):
146+
mock_logger = Mock()
147+
mock_config = Mock()
148+
mock_config.colors = {
149+
'admin': 'admin colors',
150+
'default': 'default colors'
151+
}
152+
mock_message = Mock()
153+
mock_message.message = '###test'
154+
mock_add_timestamp.return_value = 'without add_normalizer'
155+
mock_just_player = Mock()
156+
mock_player_moderator = Mock()
157+
mock_factory = Mock()
158+
mock_factory.protocols = {
159+
'normal player': mock_just_player,
160+
'moderator': mock_player_moderator
161+
}
162+
mock_protocol = Mock()
163+
mock_protocol.player.access_level = UserLevels.ADMIN
164+
plugin = AdminMessenger()
165+
plugin.factory = mock_factory
166+
plugin.config = mock_config
167+
plugin.logger = mock_logger
168+
plugin.protocol = mock_protocol
169+
expected_message = '{}{}BROADCAST: ^red;{}{}'.format(
170+
'without add_normalizer', 'admin colors', 'TEST',
171+
'default colors'
172+
)
173+
174+
plugin.broadcast_message(mock_message)
175+
mock_player_moderator.send_chat_message.assert_called_with(
176+
expected_message
177+
)
178+
mock_just_player.send_chat_message.assert_called_with(expected_message)
179+
mock_logger.info.assert_called_with(
180+
'Broadcast from %s. Message: %s',
181+
mock_protocol.player.name, 'TEST'
182+
)
183+
self.assertFalse(mock_protocol.send_chat_message.called)
184+
185+
def test_broadcast_message_not_admin(self):
186+
mock_protocol = Mock()
187+
mock_protocol.player.access_level = UserLevels.GUEST
188+
plugin = AdminMessenger()
189+
plugin.protocol = mock_protocol
190+
191+
result = plugin.broadcast_message('test')
192+
self.assertFalse(result)
193+
mock_protocol.send_chat_message.assert_called_with(
194+
'You are not authorized to do this.'
195+
)

plugins/announcer_plugin/announcer_plugin.py

+2-5
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,11 @@
22

33

44
class Announcer(BasePlugin):
5-
'''
5+
"""
66
Broadcasts a message whenever a player joins or leaves the server.
7-
'''
7+
"""
88
name = 'announcer_plugin'
99

10-
def activate(self):
11-
super(Announcer, self).activate()
12-
1310
def after_connect_success(self, data):
1411
self.factory.broadcast(
1512
'{} logged in.'.format(

0 commit comments

Comments
 (0)