-
Notifications
You must be signed in to change notification settings - Fork 69
/
xTrivia.py
315 lines (275 loc) · 9.2 KB
/
xTrivia.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
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
from phBot import *
import phBotChat
import QtBind
import json
import os
import re
pName = 'xTrivia'
pVersion = '0.1.3'
pUrl = 'https://raw.githubusercontent.com/JellyBitz/phBot-xPlugins/master/xTrivia.py'
# ______________________________ Initializing ______________________________ #
# Globals
character_data = None
trivia_data = []
trivia_last_question = ''
# Graphic user interface
gui = QtBind.init(__name__,pName)
lblDescription = QtBind.createLabel(gui,"xTrivia can automatically save all the questions with the answers if you supply the correct pattern (regex).\nIt is working with Notice chat only and sending the question to General chat by default.",6,10)
lblQuestionPattern = QtBind.createLabel(gui,"Question Pattern :",6,45)
tbxQuestionPattern = QtBind.createLineEdit(gui,"",98,43,350,19)
lblAnswerPattern = QtBind.createLabel(gui,"Answer Pattern :",6,65)
tbxAnswerPattern = QtBind.createLineEdit(gui,"",90,63,358,19)
lblReplyTo = QtBind.createLabel(gui,"Reply To :",480,55)
tbxReplyTo = QtBind.createLineEdit(gui,"",530,53,80,19)
btnSaveConfig = QtBind.createButton(gui,'saveConfigs'," Save ",645,4)
lblQuestion = QtBind.createLabel(gui,"Question :",6,105)
tbxQuestion = QtBind.createLineEdit(gui,"",59,103,180,19)
lblAnswer = QtBind.createLabel(gui,"Answer :",59+180+6,105)
tbxAnswer = QtBind.createLineEdit(gui,"",59+180+6+48,103,90,19)
btnAddTrivia = QtBind.createButton(gui,'btnAddTrivia_clicked'," Add ",59+180+6+48+90+6,105-4)
btnRemTrivia = QtBind.createButton(gui,'btnRemTrivia_clicked'," Remove ",720-75-6,105-4)
lstTriviaData = QtBind.createList(gui,6,125,720-12,18*8-3)
# ______________________________ Methods ______________________________ #
# Return folder path
def getPath():
return get_config_dir()+pName+"\\"
# Return character configs path (JSON)
def getConfigPath():
return getPath()+character_data['server'] + "_" + character_data['name'] + ".json"
# Return trivia config path for the server
def getTriviaPath():
return getPath()+"_"+character_data['server'] + "_Trivia.json"
# Check if character is ingame
def isJoined():
global character_data
character_data = get_character_data()
if not (character_data and "name" in character_data and character_data["name"]):
character_data = None
return character_data
# Save all config
def saveConfigs():
# Save if data has been loaded
if isJoined():
# Save all data
data = {}
data['QuestionPattern'] = QtBind.text(gui,tbxQuestionPattern)
data['AnswerPattern'] = QtBind.text(gui,tbxAnswerPattern)
data['ReplyTo'] = QtBind.text(gui,tbxReplyTo)
# Overrides
with open(getConfigPath(),"w") as f:
f.write(json.dumps(data, indent=4, sort_keys=True))
log("Plugin: "+pName+" configs has been saved")
# Load default configs
def loadDefaultConfig():
# Clear data
QtBind.setText(gui,tbxQuestionPattern,"")
QtBind.setText(gui,tbxAnswerPattern,"")
QtBind.setText(gui,tbxReplyTo,"")
QtBind.clear(gui,lstTriviaData)
# Loads all config previously saved
def loadConfigs():
loadDefaultConfig()
if isJoined():
# Check config exists to load
if os.path.exists(getConfigPath()):
data = {}
with open(getConfigPath(),"r") as f:
data = json.load(f)
# Load data
if "QuestionPattern" in data and data["QuestionPattern"]:
QtBind.setText(gui,tbxQuestionPattern,data["QuestionPattern"])
if "AnswerPattern" in data and data["AnswerPattern"]:
QtBind.setText(gui,tbxAnswerPattern,data["AnswerPattern"])
if "ReplyTo" in data and data["ReplyTo"]:
QtBind.setText(gui,tbxReplyTo,data["ReplyTo"])
# Try to load trivia data for first time
UpdateTriviaData()
# Load the trivia data
def UpdateTriviaData():
# Clean it
global trivia_data
trivia_data = []
QtBind.clear(gui,lstTriviaData)
# Check the trivia data
if os.path.exists(getTriviaPath()):
# Try to Load trivia file
with open(getTriviaPath(),"r") as f:
trivia_data = json.load(f)
# Load the listview
for trivia in trivia_data:
QtBind.append(gui,lstTriviaData,'Q: "'+trivia['q']+'" A: "'+trivia['a']+'"')
# Return True if the question exist into the array
def QuestionExists(_array,_question):
for _value in _array:
if _value['q'] == _question:
return True
return False
# Add question answer to database
def AddQuestionAnswer(question,answer):
# Check question existence
if not QuestionExists(trivia_data,question):
# Create trivia object
trivia = {'q':question,'a':answer}
# Insert ordered into the list
index = 0
for data in trivia_data:
if data['q'] > question:
break
index+=1
trivia_data[index:index] = [trivia]
trivia_text = 'Q: "'+question+'" A: "'+answer+'"'
# Overwrite file
with open(getTriviaPath(),"w") as f:
f.write(json.dumps(trivia_data, indent=4, sort_keys=True))
# Update all
UpdateTriviaData()
# Success message
log('Plugin: Trivia ['+trivia_text+'] has been added')
# Add trivia manually
def btnAddTrivia_clicked():
# avoid empty data
question = QtBind.text(gui,tbxQuestion)
if not question:
return
answer = QtBind.text(gui,tbxAnswer)
if not answer:
return
# update it at first
UpdateTriviaData()
# try to add it
AddQuestionAnswer(question,answer)
# reset data
QtBind.setText(gui,tbxQuestion,'')
QtBind.setText(gui,tbxAnswer,'')
# Remove trivia manually
def btnRemTrivia_clicked():
# get index selected
index = QtBind.currentIndex(gui,lstTriviaData)
if index >= 0:
global trivia_data
# save the data to be deleted
trivia = trivia_data[index]
# update it at first
UpdateTriviaData()
# search the trivia index to be deleted
index = -1
for i in range(len(trivia_data)):
if trivia_data[i]['q'] == trivia['q']:
index = i
break
if index != -1:
del trivia_data[index]
QtBind.removeAt(gui,lstTriviaData,index)
# Overwrite the file
with open(getTriviaPath(),"w") as f:
f.write(json.dumps(trivia_data, indent=4, sort_keys=True))
# Success message
log('Plugin: Trivia ['+trivia['q']+'] has been removed')
# Binary search algorithm. Returns the index or -1 if is the element is not found
def binarySearch(_array, _left, _right, _element):
# Check base case
if _right >= _left:
mid = _left + (_right - _left) // 2
if _array[mid]['q'] == _element:
return mid
elif _array[mid]['q'] > _element:
return binarySearch(_array, _left, mid-1, _element)
else:
return binarySearch(_array, mid+1, _right, _element)
else:
return -1
# Returns the answer to the question, otherwise empty is returned
def FindAnswer(Question):
UpdateTriviaData()
# Check if is not empty
if trivia_data:
# Try to find it asap
index = binarySearch(trivia_data,0,len(trivia_data)-1,Question)
# Check existence of the question
if index != -1:
# Return the answer
return trivia_data[index]['a']
# Nothing found
return None
# Send the message to the player or to all chat
def SendAnswer(Answer):
playerToReply = QtBind.text(gui,tbxReplyTo)
if playerToReply:
phBotChat.Private(playerToReply,Answer)
else:
phBotChat.All(Answer)
# Search and reply the trivia question
def ReplyQuestion(Question):
global trivia_last_question
# Try to find the answer
answer = FindAnswer(Question)
# Check answer
if answer == None:
log('Plugin: Trivia answer not found! ['+Question+']')
# Keep in memory the last question made and not answered
trivia_last_question = Question
else:
# Answering as quickly as possible (:
SendAnswer(answer)
log('Plugin: Trivia answer sent ['+answer+']')
# clean it just in case
trivia_last_question = ""
# Save the trivia question/answer into the books ;)
def SaveAnswer(Answer):
# Cannot save it if there is no question previously saved
if trivia_last_question:
global trivia_data
# Update it the gui and data at first
UpdateTriviaData()
# Try to add it
AddQuestionAnswer(trivia_last_question,Answer)
# Check if the message pattern is correct to reply to the question
def CheckQuestionPattern(msg):
# Check the question pattern
questionPattern = QtBind.text(gui,tbxQuestionPattern)
if questionPattern:
try:
if re.search(questionPattern,msg):
ReplyQuestion(msg)
return True
except Exception as ex:
log("Plugin: Error at regex ["+str(ex)+"]")
return False
# Check if the answer pattern is correct to save the answer
def CheckAnswerPattern(msg):
# Check the answer pattern
answerPattern = QtBind.text(gui,tbxAnswerPattern)
if answerPattern:
try:
# The match needs to be grouped, otherwise is not going to work
match = re.findall(answerPattern,msg)
if match:
if type(match[0]) is tuple:
# Remove empty matches
match[0] = list(filter(None, match[0]))[1]
# Save first match
SaveAnswer(match[0])
return True
except Exception as ex:
log("Plugin: Error at regex ["+str(ex)+"]")
return False
# ______________________________ Events ______________________________ #
# Called when the character enters the game world
def joined_game():
loadConfigs()
# All chat messages received are sent to this function
def handle_chat(t,player,msg):
# Check a notice message
if t == 7:
# Just try to check stuffs on this message
CheckQuestionPattern(msg)
CheckAnswerPattern(msg)
# Plugin loaded
log('Plugin: '+pName+' v'+pVersion+' successfully loaded')
if os.path.exists(getPath()):
# Adding RELOAD plugin support
loadConfigs()
else:
# Creating configs folder
os.makedirs(getPath())
log('Plugin: '+pName+' folder has been created')