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