ceruleanbot
봇으로도 가벼운 편집기로도 사용할 수 있음. 미디어위키 편집기, GUI 봇. 나무위키는 난이도가 급상승이라 나무위키 편집기는 안 만들 예정.
MIT License
https://www.geeksforgeeks.org/how-to-use-html-in-tkinter-python/
https://bio-info.tistory.com/46
https://github.com/martin-majlis/Wikipedia-API/blob/master/wikipediaapi/__init__.py
#!/usr/bin/python3
import requests
S = requests.Session()
wikis = {}
class wiki:
def __init__(self, URL: str = 'https://ko.wikipedia.org', apiprefix: str = '/w'):
''' '''
self.page : object = None
''' object '''
self.apiurl = URL + apiprefix + '/api.php'
self.url = URL
self.csrftoken = False
''' edit token '''
self.logouted = True
''' logouted? True , False'''
self.pages = {}
'''page list'''
self.username = '익명 사용자'
wikis[URL] = self
def addpage(self, __page__ = None):
'''
add page to edit or read
__page__ is object or str
'''
if type(__page__) == str:
''' if __page__ is str '''
self.pages[__page__] = page(self.url, __page__)
elif type(__page__) == object:
''' if __page__ is object '''
self.pages[__page__['title']] = __page__
elif __page__ == None:
if self.page != None:
self.pages[self.page.title] = self.page
#for item in :
print(self.pages)
def setpage(self, pagename: str) -> object:
'''사이트 객체에 페이지 정보 저장, 개별 페이지 객체 리턴'''
self.page = page(self.url, pagename)
return page
def get_csrftoken(self):
DATA = S.get(url=self.apiurl, params={
"action": "query",
"meta": "tokens",
"format": "json"}).json()
self.csrftoken = DATA['query']['tokens']['csrftoken']
def login(self, username: str, password: str):
# Step 1: Retrieve login token first
DATA = S.get(url=self.apiurl, params = {
'action': "query",
'meta': "tokens",
'type': "login",
'format': "json"
}).json()
# Step 2: Send a POST request to login. Using the main account for login is not
# supported. Obtain credentials via Special:BotPasswords
# 봇 비밀번호 설정 권장, 형식 : Caeruleum@asdfqwerzxcvpoiulkjhmnbv
params = {
"action": "login",
"format": "json",
"lgname": username,
"lgpassword": password,
"lgtoken": DATA['query']['tokens']['logintoken'],
"utf8": 1
}
DATA = S.post(self.apiurl, data=params).json()
if DATA["login"]["result"] == "Success":
print("로그인 성공")
self.get_csrftoken()
self.islogout = False
self.username = username
else:
print("로그인 실패")
exit()
def logout(self):
if self.logouted == True:
print('로그아웃')
else:
DATA = S.post(self.apiurl, data={"action": "logout", "token": self.csrftoken, "format": "json"}).json()
if 'error' in DATA:
print('로그아웃 에러')
print(DATA['error']['code'] + ' ' + DATA['error']['info'])
else:
self.logouted = True
print(DATA)
print('로그아웃')
def pagesInCategory(self, category: str, namespace: str = ''):
params = {
"action": "query",
"format": "json",
"list": "categorymembers",
"utf8": 1,
"cmnamespace": namespace,
"cmtitle": 'category:'+category,
"cmprop": "title|timestamp",
"cmlimit": "max",
"cmsort": "timestamp",
}
data = S.get(url=self.apiurl, params=params).json()
return data['query']['categorymembers']
def savePages(self, summary: str = ''): # 작업 목록의 문서들 모두 저장. wiki.pages
for __page__ in self.pages:
__page__.save(summary)
def savePage(self, summary: str = ''): # 사이트 객체 내의 유일 페이지 객체를 위키에 업로드. wiki.page
self.page.save(summary)
def removecategory(self):
''
class page:
''' page class '''
def __init__(self, url: str, title: str):
self.url = wikis[url].url
self.apiurl = wikis[url].apiurl
self.resturl = wikis[url].url + "/rest.php/v1/page/"
self.title = title
def get(self):
restJson = S.get(url=self.resturl + self.title).json()
if 'httpCode' in restJson:
self.cont = str(restJson['httpCode']) + ' ' + restJson['httpReason']
else:
self.cont = restJson['source']
def print(self):
print(self.cont)
def remove(self, toremove: str):
self.cont = self.cont.replace(toremove, '')
def replace(self, toreplace: str, replace: str) -> None:
self.cont = self.cont.replace(toreplace, replace)
def save(self, summary: str = ''):
csrftoken = wikis[self.url].csrftoken
if csrftoken == False:
print('csrftoken is ungetted')
return
print(self.title+' 편집')
params = {
"action": "edit",
"format": "json",
"title": self.title,
"text": self.cont,
"summary": summary,
"token": csrftoken,
"utf8": 1,
"formatversion": "latest",
"bot": "true"
}
DATA = S.post(url=self.apiurl, data=params).json()
print(DATA)
GUI 부분 CLI 부분 독립 시키기
#!/usr/bin/python3
import ceruleanbot
import time
import requests
import tkinter as tk
import tkinter.ttk as ttk
wikisite = ceruleanbot.wiki('https://librewiki.net', apiprefix='')
def setText(self, text): # for tk obj
self.delete(1.0, tk.END)
self.insert(1.0, text)
class mainframe:
def __init__(self) -> None:
self.window = tk.Tk()
self.style = ttk.Style(self.window)
#for item in self.style.theme_names():
# print(item)
self.style.theme_use('clam')
self.window.title("cerulWikiBot")
self.label = tk.Label(self.window, text='문서 제목 입력하고 소스보기', height=2); self.label.pack()
self.text = tk.Text(self.window)
self.text.focus(); self.text.pack()
self.entry = tk.Entry(self.window, width=50)
self.entry.pack()
self.viewsource = ttk.Button(
self.window, text='소스 보기', command=self.searchdoc)
self.viewsource.pack(pady=0, side='left')
self.savebutton = ttk.Button(
self.window, text='편집 저장', command=self.save) # 미구현
self.savebutton.pack(pady=0, side='left')
self.addtolistb = ttk.Button(
self.window, text='작업 목록에 추가', command=self.addtolist) # 미구현
self.addtolistb.pack(pady=0, side='left')
self.loginb = ttk.Button(self.window, text='로그인', command=self.login)
self.loginb.pack(pady=0, side='left')
self.logoutb = ttk.Button(self.window, text='로그아웃', command=self.logout)
self.logoutb.pack(pady=0, side='left')
self.window.mainloop()
def login(self):
wikisite.login('cerulean', '**********') #일반 사용자가 해도 됨.
def logout(self):
wikisite.logout()
def searchdoc(self):
self.title = self.entry.get()
if self.title == '':
self.label.configure(text='?')
setText(self.text, '?')
else:
self.label.configure(text=self.title)
wikisite.setpage(self.title)
wikisite.page.get()
setText(self.text, wikisite.page.cont)
def save(self):
wikisite.page.cont = self.text.get(1.0, tk.END)
wikisite.page.save()
def addtolist(self):
wikisite.addpage()
def __del__(self):
self.logout()
window = mainframe()