aboutsummaryrefslogtreecommitdiff
path: root/modules/utils.py
blob: c8406ce1024a9e1d37bafe954cc8e3990b895c21 (plain)
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
# This is python file with usable utilities for modules
# This can't be used as mcwrapper module. Although it's not a problem if loaded.
import os
import datetime
import re
import struct
import traceback
from enum import Enum

# Dummy variable to be used before it is set by mcwrapper
conf = type('defconf', (object,), {})

class Service(Enum):
	# Request service of conf function
	# This function is called right after argument parsing.
	# Configuration is loaded before almost anything is done.
	# Prototype: config(conf)
	#   Where conf is class containing configuration variables.
	config = 1
	# Request service of init function
	# This function is called right before Minecraft server is started.
	# Prototype: init()
	init = 2
	# Request service of clean function
	# This function is called before mcwrapper exits.
	# Prototype: clean()
	clean = 3
	# Request service of parse function
	# Prototype: parse(line)
	#   Where line is line from Minecraft server standard and error output.
	parse = 4
	# Signalize that exceptions shouldn't be ignored.
	# Otherwise exception is printed and module is removed.
	exceptionThrow = 101
	# Requests service of action and action_help function.
	# This flag can't be denied by serviceServer or by configuration.
	# Prototype: action(act, args)
	#   Where act is string specifying action and args are rest of command line
	#   arguments.
	# Prototype: action_help()
	action = 201
	# Requests service of argument function.
	# This flag can't be denied by serviceServer or by configuration.
	# Prototype: argument(arg, args)
	#   Where arg is parser argument and args are rest of command line arguments.
	argument = 202
	def toStr(service):
		if service == Service.config:
			return 'S-Config'
		elif service == Service.init:
			return 'S-Init'
		elif service == Service.clean:
			return 'S-Clean'
		elif service == Service.parse:
			return 'S-Parse'
		elif service == Service.exceptionThrow:
			return 'F-ExceptionThrow'
		elif service == Service.action:
			return 'P-Action'
		elif service == Service.argument:
			return 'P-Argument'

def __module_disable__(module):
	"""Disable specified module"""
	if verbose_level >= 0:
		print('Disabling module: ' + str(module))
	if Service.clean in module.services:
		try:
			module.clean()
		except Exception:
			traceback.print_exc()
	for name, value in vars(conf).items():
		if re.search('^__modules', name):
			try:
				value.remove(module)
			except KeyError:
				pass
	del module

def printArgumentsHelp():
	"""Prints help for all arguments from loaded modules"""
	print('   -h, --help')
	print('       Prints this help text.')
	print('   -v, --verbose')
	print('       Increase verbose level of output.')
	print('   -q, --quiet')
	print('       Decrease verbose level of output.')
	for mod in conf.__modules_argument__:
		mod.argument_help()

def serviceCall(servicename, func, argv=[], mode=0):
	"""Calls func in all/n-th modules with specified service.
	
	  servicename - String name of service
	  func - String name of functions to be called
	  argv - List of arguments passed to functions
	  mode - Mode of execution
			 0 - called for every module without result returning
	         1 - called for every module and return result
			 2 - called until True is returned from function called
	"""	
	def execmod(servicename, func, argv, mod):
		cmd = 'mod.' + func + '( '
		for i in range(0, len(argv)):
			cmd += 'argv[' + str(i) + '],'
		cmd = cmd[0:len(cmd)-1] + ')'
		try:
			return eval(cmd)
		except Exception as e:
			if Service.exceptionThrow in mod.services:
				raise e
			else:
				traceback.print_exc()
				__module_disable__(mod)
				return None
	if mode == 0:
		for mod in vars(conf)['__modules_' + servicename + '__'].copy():
			execmod(servicename, func, argv, mod)
		return 
	elif mode == 1:
		ret = dict()
		for mod in vars(conf)['__modules_' + servicename + '__'].copy():
			ret[mod] = execmod(servicename, func, argv, mod)
		return ret
	elif mode == 2:
		for mod in vars(conf)['__modules_' + servicename + '__'].copy():
			rtn = execmod(servicename, func, argv, mod)
			if rtn:
				return rtn, mod
		return None, None

def isServerRunning():
	"""Check if server is running. It checks if input_pipe exists.
	Returns:
	  True  - Running in any state or residue pipe exists.
	  False - Not running
	"""
	return os.path.exists(conf.inputPipe)

__default_config__ = {
		"modules": {'say', 'argmodules', 'list-modules', 'printconf'},
		"identifier": None,
		}
__default_server_config__ = {
		"modules": {'status', 'players'},
		"folder": '/dev/shm/mcwrapper-exampleserver',
		"logOutput": False,
		"logFile": datetime.datetime.now().strftime('%y-%m-%d-%H-%M-%S') + '.log',
		"command": [],
		}

def setServerConf(identifier):
	"""Sets server configuration."""
	conf.identifier = identifier
	try:
		conf.server[identifier]
		vars(conf).update(conf.server[identifier])
	except AttributeError:
		if conf.verbose_level >= 0:
			print('W: No configuration associated with identifier: "' + conf.identifier)
	configSet(__default_server_config__)
	# Set additional runtime configuration variables
	conf.inputPipe = conf.folder + '/input_pipe'

def configSet(confs):
	"""This is for setting default configurations. If configuration for module is
	not set in conf file, then it must be set while module initialization.

	confs - dictionary of configuration options and default values.
	"""
	for name, val in confs.items():
		try:
			dir(conf).index(name)
		except ValueError:
			exec('conf.' + name + '=val')

def varint_unpack(data):
	"Returns varint value from beginning of data and number of bytes used."
	i = 0
	nextbt = True
	newdata = 0
	while nextbt:
		bt = data[i]
		if not bt & (1 << 7):
			nextbt = False
		bt = bt & ~(1 << 7)
		newdata = newdata | (bt << (i * 7))
		print(newdata)
	return newdata, i

def varint_pack(integer):
	pass

#################################################################################
## dummy module
services = ()