r39 vs r37
1
api_url, wiki_url, discuss_doc, discuss_doc = selctwiki()
21
3
headers = {'Content-Type': 'application/json', 'Authorization': 'Bearer {}'.format(APItoken)}
4
discuss_headers = {'User-Agent': 'Mozilla/5.0'}
5
####
6
sys_stop=False
72
8
logger = logging.getLogger("wiki edit")
9
discusslogger = logging.getLogger("discuss HTML")
10
streamlogger = logging.getLogger("log stream")
11
12
logging.addLevelName(11, "edit History")
13
logging.editHistory = 11
14
15
logging.addLevelName(31, "edit Fail")
16
logging.editFail= 31
17
18
logging.addLevelName(41, "edit Error")
19
logging.editError = 41
20
21
logging.addLevelName(35, "working Emergency Stop")
22
logging.workingEmergencyStop = 35
23
24
logging.addLevelName(25, "discuss Error")
25
logging.discussError = 25
26
27
logging.addLevelName(12, "discuss Load")
28
logging.discussLoad = 12
29
30
logger.setLevel(logging.DEBUG)
31
discusslogger.setLevel(logging.INFO)
32
33
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
34
stream_hander = logging.StreamHandler()
35
stream_hander.setFormatter(formatter)
36
streamlogger.addHandler(stream_hander)
37
progStart_day=str(time.strftime('%Y %m %d', time.localtime()))
38
progStart_time=str(time.strftime('%H %M %S', time.localtime()))
39
40
if not os.path.exists('/content/drive/My Drive/Colab Notebooks/logs/{}'.format(progStart_day)):
41
os.makedirs('/content/drive/My Drive/Colab Notebooks/logs/{}'.format(progStart_day))
42
os.makedirs('/content/drive/My Drive/Colab Notebooks/logs/{}/{}'.format(progStart_day,progStart_time))
43
44
file_handler = logging.FileHandler('/content/drive/My Drive/Colab Notebooks/logs/{}/{}/wiki edit.log'.format(progStart_day,progStart_time))
45
file_handler.setFormatter(formatter)
46
logger.addHandler(file_handler)
47
48
discuss_file_handler = logging.FileHandler('/content/drive/My Drive/Colab Notebooks/logs/{}/{}/discuss HTML.log'.format(progStart_day,progStart_time))
49
discuss_file_handler.setFormatter(formatter)
50
discusslogger.addHandler(discuss_file_handler)
51
52
error_file_handler = logging.FileHandler('/content/drive/My Drive/Colab Notebooks/logs/{}/{}/error.log'.format(progStart_day,progStart_time))
53
error_file_handler.setFormatter(formatter)
54
streamlogger.addHandler(error_file_handler)
55
56
class checkWikiThread():
57
async def alterResponseTry(self,response,wait_time=0.2):
58
try:
59
await response.html.arender(wait=wait_time)
60
html = await response.html.html
61
loadComple = re.search("토론",str(html))
62
if loadComple==None:
63
logger.log(logging.discussLoad, ('not Loding, wait_time: {}'.format(wait_time)))
64
print('not Loding, wait_time:',wait_time)
65
if wait_time>40:
66
discusslogger.log(logging.discussError,(html))
67
logger.log(logging.discussError, ("timeout, html log saved: {} discuss HTML.log".format(str(progStart_time))))
68
streamlogger.log(logging.discussError, ("timeout, html log saved: {} discuss HTML.log".format(str(progStart_time))))
69
html= await self.alterResponseTry(response,wait_time=float(wait_time+10))
70
else :
71
logger.log(logging.discussLoad, 'load comple')
72
return html
73
except Exception as ex:
74
logger.log(logging.discussError, ex)
75
streamlogger.log(logging.discussError, ex)
76
html= await self.alterResponseTry(response,wait_time)
77
return html
78
def __init__(self):
79
self.state=False
80
self.discuss_state = None
81
async def run(self):
82
self.state=True
83
response = await requests.get("https://{}/discuss/{}".format(wiki_url,discuss_doc),headers=discuss_headers, timeout=100)
84
html = response.text
85
loadComple = re.search("토론",str(html))
86
if loadComple==None:
87
logger.log(logging.discussLoad, 'not Loding, alter way start')
88
#print(html)
89
asession = await AsyncHTMLSession()
90
response = await asession.get("https://{}/discuss/{}".format(wiki_url,discuss_doc),headers=discuss_headers)
91
html= await self.alterResponseTry(response)
92
self.discuss_state = re.search("\/discuss\/[\w,%,:]*#s-1",str(html))
93
time.sleep(30)
94
self.state = False
95
96
def linkcheckchange(match_obj):
97
#구버전 기본값
98
#print(match_obj)
99
#print(match_obj[0])
100
#link = match_obj.group('link')
101
#anchor = match_obj.group('anchor')
102
#content = match_obj.group('content')
103
#namebar = match_obj.group('namebar')
104
#for target,replace in targets:
105
#if link==target:
106
#if content==None:
107
#내용이 없을경우 원래 링크가 내용이 됨
108
#content=link
109
#link=replace
110
#if anchor==None:
111
#anchor=''
112
#if namebar==None:
113
#namebar=''
114
#return '[[{}{}{}|{}]]'.format(namebar,link,anchor,content)
115
#
116
#[[]] 전용
117
first = match_obj.group('first')
118
link = match_obj.group('link')
119
middle = match_obj.group('middle')
120
detachBar = match_obj.group('detachBar')
121
content = match_obj.group('content')
122
last = match_obj.group('last')
123
anchor = match_obj.group('anchor')
124
if middle==None:
125
middle=''
126
for target in targets:
127
target_doc=target['document']
128
replace=target['replace']
129
if link==target_doc:
130
#내용이 없을경우 원래 링크가 내용이 됨
131
#content_replace bool 추가
132
if content==None and content_replace:
133
#혹시 모를 사고 예방
134
if detachBar==None:
135
content='|{}'.format(link)
136
else:
137
content='{}'.format(link)
138
elif content==None:
139
content=''
140
link=replace
141
return '{}{}{}{}{}'.format(first,link,middle,content,last)
142
return match_obj.group(0)
143
def checkchange(match_obj):
144
#[[]] 제외 기본 변경
145
first = match_obj.group('first')
146
link = match_obj.group('link')
147
last = match_obj.group('last')
148
for target in targets:
149
target_doc=target['document']
150
replace=target['replace']
151
if link==target_doc:
152
link=replace
153
#print('hidden')
154
return '{}{}{}'.format(first,link,last)
155
return match_obj.group(0)
156
def checkdelete(match_obj):
157
#분류 정리 전용
158
link = match_obj.group('link')
159
anchor = match_obj.group('anchor')
160
content = match_obj.group('content')
161
for target in targets:
162
target_doc=target['document']
163
replace=target['replace']
164
if link==target_doc:
165
if content==None:
166
#내용이 없을경우 원래 링크가 내용이 됨
167
content=link
168
link=replace
169
if anchor==None:
170
anchor=''
171
return ''
172
return match_obj.group(0)
173
174
def edit_link(title, text):
175
link_patten=re.compile(r"(?P<first>\[\[(?P<namebar>(:)?))(?P<link>((\\\\)|(\\\#)|(\\\|)|(\\\[)|(\\\])|[^\[\]#|])*)(?P<middle>(?P<anchor>#((\\\\)|(\\\#)|(\\\|)|(\\\[)|(\\\])|[^\[\]#|])*)?(?P<detachBar>\|)?)(?(detachBar)(?P<content>((\\\\)|(\\\#)|(\\\|)|(\\\[)|(\\\])|[^\[\]|])*))(?P<last>\]\])")
176
otherMean_patten=re.compile(r"(?P<first>rd\d=)(?P<link>((\\\,)|(\\\\)|(\\\))|[^\,)])*)(?P<last>[,)])")
177
detailContent_patten=re.compile(r"(?P<first>문서명=)(?P<link>((\\\,)|(\\\\)|(\\\))|[^\,)])*)(?P<last>[,)])")
178
categoryMean_patten=re.compile(r"(?P<first>n\d=)(?P<link>((\\\,)|(\\\\)|(\\\))|[^\,)])*)(?P<last>[,)])")
179
top_patten=re.compile(r"(?P<first>top\d=)(?P<link>((\\\,)|(\\\\)|(\\\))|[^\,)])*)(?P<last>[,)])")
180
include_patten=re.compile(r"(?P<first>\[include\()(?P<link>((\\\,)|(\\\\)|(\\\))|[^\,)])*)(?P<last>((?P<comma>,)?)?(?(comma)((\\\,)|(\\\\)|(\\\))|[^)])*)\)\])")
181
redirect_patten=re.compile(r"(?P<first>#redirect )(?P<link>((\\\\)|(\\\#)|(\\\|)|(\\\[)|(\\\])|[^\[\]#|])*)(?P<last>(?P<anchor>#)?.*\n)")
182
183
normal_new_text=link_patten.sub(linkcheckchange,text)
184
new_text=otherMean_patten.sub(checkchange,normal_new_text)
185
new_text=detailContent_patten.sub(checkchange,new_text)
186
new_text=categoryMean_patten.sub(checkchange,new_text)
187
new_text=top_patten.sub(checkchange,new_text)
188
new_text=include_patten.sub(checkchange,new_text)
189
new_text=redirect_patten.sub(checkchange,new_text)
190
if normal_new_text!=new_text:
191
logger.log(logging.editHistory,('특수 변경 문서명: {}'.format(title)))
192
return new_text
193
194
def backlinkchange():
195
data={}
196
data['edit']=[]
197
for target in targets:
198
target_doc=target['document']
199
replace=target['replace']
200
target_backlinks = []
201
backlink_value = ''
202
namespaces=[]
203
res = requests.get('https://{}/api/backlink/{}'.format(api_url,target_doc), headers = headers).json()
204
for namespace in res['namespaces']:
205
namespaces.append(namespace['namespace'])
206
if len(black_namespaces)>0: #블랙 네임이 있다면
207
for black_namespace in black_namespaces:
208
if black_namespace in namespaces:
209
namespaces.remove(black_namespace)
210
if len(namespaces)>0:
211
target_namespace = namespaces.pop(0)
212
else:
213
target_namespace = None
214
while target_namespace != None:
215
res = requests.get('https://{}/api/backlink/{}?namespace={}&from={}'.format(api_url,target_doc,target_namespace, backlink_value), headers = headers).json()
216
backlinks=res['backlinks']
217
backlink_value=res['from']
218
for doc in backlinks:
219
white=False
220
for white_doc in nontargets:
221
if doc['document'] == white_doc:
222
logger.info("화이트 리스트 문서 '{}' Pass".format(doc['document']))
223
white=True
224
break
225
if white:
226
continue
227
target_backlinks.append(doc['document'])
228
if backlink_value==None:
229
if len(namespaces)>0:
230
target_namespace = namespaces.pop(0)
231
backlink_value=''
232
else:
233
break
234
for doc in target_backlinks:
235
try:
236
res = requests.get('https://{}/api/edit/{}'.format(api_url,doc), headers = headers).json()
237
except:
238
res = requests.get('https://{}/api/edit/{}'.format(api_url,doc), headers = headers)
239
logger.log(logging.workingEmergencyStop, str(res.text))
240
streamlogger.log(logging.workingEmergencyStop, str(res.text))
241
exit()
242
try:
243
if not res['exists']:
244
continue
245
except:
246
logger.log(logging.editFail, ('문서명: {}'.format(doc),'res: {}'.format(res)))
247
streamlogger.log(logging.editFail, ('문서명: {}'.format(doc),'res: {}'.format(res)))
248
continue
249
250
token = res['token']
251
text = str(res['text'])
252
new_text = edit_link(doc, text)
253
res = requests.post('https://{}/api/edit/{}'.format(api_url,doc), json = {'text': new_text, 'log': log, 'token': token}, headers = headers)
254
try:
255
if res.json()['status'] != 'success':
256
logger.log(logging.editError, ('문서명: {}'.format(doc),'res: {}'.format(res.text)))
257
streamlogger.log(logging.editError, ('문서명: {}'.format(doc),'res: {}'.format(res.text)))
258
else:
259
data['edit'].append({
260
"doc": str(doc),
261
"rev": res.json()['rev'],
262
"text":text
263
})
264
logger.log(logging.editHistory,('문서명: {}'.format(doc),'rev: {}'.format(res.json()['rev'])))
265
except Exception as ex:
266
logger.critical(('문서명:',doc,'Error:',ex))
267
logger.log(logging.editError,(('문서명:',doc,'Error:',ex)))
268
streamlogger.critical(('문서명:',doc,'Error:',ex))
269
time.sleep(1)
270
with open('/content/drive/My Drive/Colab Notebooks/logs/{}/{}/edit_history.txt'.format(progStart_day,progStart_time), 'w') as outfile:
271
json.dump(data, outfile, indent=4, ensure_ascii=False)
272
273
def revert():
274
data={}
275
data['edit']=[]
276
json_data = {}
277
with open('/content/drive/My Drive/Colab Notebooks/logs/{}/{}/edit_history.txt'.format(revert_day,revert_time), "r") as json_file:
278
json_data = json.load(json_file)
279
for target in json_data['edit']:
280
doc = target['doc']
281
try:
282
res = requests.get('https://{}/api/edit/{}'.format(api_url,doc), headers = headers).json()
283
except:
284
res = requests.get('https://{}/api/edit/{}'.format(api_url,doc), headers = headers)
285
logger.log(logging.workingEmergencyStop, str(res.text))
286
streamlogger.log(logging.workingEmergencyStop, str(res.text))
287
exit()
288
try:
289
if not res['exists']:
290
continue
291
except:
292
logger.log(logging.editFail, ('문서명: {}'.format(doc),'res: {}'.format(res)))
293
streamlogger.log(logging.editFail, ('문서명: {}'.format(doc),'res: {}'.format(res)))
294
continue
295
296
token = res['token']
297
text = str(res['text'])
298
new_text = target['text']
299
log=log+'(r{}으로 되돌림)'.format(str(int(target['rev'])-1))
300
301
res = requests.post('https://{}/api/edit/{}'.format(api_url,doc), json = {'text': new_text, 'log': log, 'token': token}, headers = headers)
302
if res.json()['status'] != 'success':
303
logger.log(logging.editError, ('문서명: {}'.format(doc),'res: {}'.format(res.text)))
304
streamlogger.log(logging.editError, ('문서명: {}'.format(doc),'res: {}'.format(res.text)))
305
else:
306
data['edit'].append({
307
"doc": str(doc),
308
"rev": res.json()['rev'],
309
"text":text
310
})
311
logger.log(logging.editHistory,('문서명: {}'.format(doc),'rev: {}'.format(res.json()['rev'])))
312
313
time.sleep(1)
314
with open('/content/drive/My Drive/Colab Notebooks/logs/{}/{}/edit_history.txt'.format(progStart_day,progStart_time), 'w') as outfile:
315
json.dump(data, outfile, indent=4, ensure_ascii=False)
316
317
def customlinkchange():
318
data={}
319
data['edit']=[]
320
json_data = {}
321
for target, replace in targets:
322
for doc in custom_list:
323
try:
324
res = requests.get('https://{}/api/edit/{}'.format(api_url,doc), headers = headers).json()
325
except:
326
res = requests.get('https://{}/api/edit/{}'.format(api_url,doc), headers = headers)
327
logger.log(logging.workingEmergencyStop, str(res.text))
328
streamlogger.log(logging.workingEmergencyStop, str(res.text))
329
exit()
330
try:
331
if not res['exists']:
332
continue
333
except:
334
logger.log(logging.editFail, ('문서명: {}'.format(doc),'res: {}'.format(res)))
335
streamlogger.log(logging.editFail, ('문서명: {}'.format(doc),'res: {}'.format(res)))
336
continue
337
338
339
token = res['token']
340
text = str(res['text'])
341
new_text = edit_link(doc, text)
342
343
res = requests.post('https://{}/api/edit/{}'.format(api_url,doc), json = {'text': new_text, 'log': log, 'token': token}, headers = headers)
344
if res.json()['status'] != 'success':
345
logger.log(logging.editError, ('문서명: {}'.format(doc),'res: {}'.format(res.text)))
346
streamlogger.log(logging.editError, ('문서명: {}'.format(doc),'res: {}'.format(res.text)))
347
else:
348
data['edit'].append({
349
"doc": str(doc),
350
"rev": res.json()['rev'],
351
"text":text
352
})
353
logger.log(logging.editHistory,('문서명: {}'.format(doc),'rev: {}'.format(res.json()['rev'])))
354
355
time.sleep(1)
356
357
class runningThread(threading.Thread):
358
def __init__(self):
359
super().__init__()
360
self.state=False
361
def run(self):
362
self.state=True
363
logger.info('working start')
364
print('working start')
365
if mod=='normal':
366
backlinkchange()
367
elif mod=='revert':
368
if revert_day != '' or revert_day != '':
369
revert()
370
else:
371
print('revert 시간이 지정되지 않았습니다.')
372
log = '자동 편집 중 '
373
print('로그 변경됨:'+log+'(r{}으로 되돌림)'.format('int'))
374
elif mod=='custom':
375
customlinkchange()
376
else:
377
print('mod not select')
378
logger.info('working end')
379
print('working end')
380
self.state=False
381
382
####
383
checkDiscuss=checkWikiThread()
384
custom_thread=runningThread()
385
custom_thread.start()
386
while True:
387
try:
388
if not checkDiscuss.state:
389
checkDiscuss.run()
390
if not custom_thread.state or sys_stop:
391
logger.info('System Stop')
392
print('system stop')
393
break
394
if checkDiscuss.discuss_state != None:
395
logger.log(logging.workingEmergencyStop, 'discuss normal, System Emergency Stop')
396
streamlogger.log(logging.workingEmergencyStop, 'discuss normal, System Emergency Stop')
397
break
398
except Exception as ex:
399
logger.critical(ex)
400
streamlogger.critical(ex)
401
break
402
logging.shutdown()
403
reload(logging)