사용자:하늘/양식

< 사용자:하늘
하늘 (토론 | 기여)님의 2021년 11월 27일 (토) 17:41 판

ceruleanbot

/bot/__init__.py

봇으로도 가벼운 편집기로도 사용할 수 있음. 미디어위키 편집기, 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

bot/__init__.py

from requests import Session
import time
S = Session()
wikis = {}
class wiki:
	def __init__(self, URL: str = 'https://ko.wikipedia.org', apiprefix: str = '/w'):
		''' URL is mediawiki site '''
		self.apiurl = URL + apiprefix + '/api.php'
		self.url = URL
		self.csrftoken = False
		''' edit token '''
		self.logouted = True
		''' logouted? True , False'''
		self.pages = {}
		self.username = '익명 사용자'
		'''page list'''
		wikis[URL] = self
		self.page = page(URL, '')
		''' object '''

	def __repr__(self) -> str:
		return 'Url = ' + self.url + '\n사용자 = ' + self.username

	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.title = pagename
		self.page.get()
		return self.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']
		return

	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.logouted = 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 = '',
	type: str = '',
	sortkey: str = 'timestamp',
	startsortkey: str = None,
	endsortkey: str = None
	):
		params = {
			"action": "query",
			"format": "json",
			"list": "categorymembers",
			"utf8": 1,
			"cmnamespace": namespace,
			"cmtitle": 'category:'+category,
			"cmprop": "title",
			"cmtype": type,
			"cmlimit": "max",
			"cmsort": sortkey,
			"cmstartsortkeyprefix": startsortkey,
			"cmendsortkeyprefix": endsortkey
		}
		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):
		''

	def __del__(self):
		self.logout()

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):
		PARAMS = {
			"action": "query",
			"format": "json",
			"prop": "revisions",
			"formatversion": "2",
			"rvprop": "content",
			"rvslots": "*",
			"titles": self.title
		}
		json = S.get(url=self.apiurl, params=PARAMS).json()['query']['pages'][0]
		if 'missing' in json:
			self.cont = 'Missing page'
		else:
			self.cont = json['revisions'][0]['slots']['main']['content']

	def print(self):
		print(self.cont)

	def __repr__(self) -> str:
		return '제목 = '+self.title+'\n'+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 = ''):
		if wikis[self.url].csrftoken == False:
			wikis[self.url].get_csrftoken()
		print(self.title+' 편집')
		params = {
			"action": "edit",
			"format": "json",
			"title": self.title,
			"text": self.cont,
			"summary": summary,
			"token": wikis[self.url].csrftoken,
			"utf8": 1,
			"formatversion": "latest",
			"bot": "true"
		}
		DATA = S.post(url=self.apiurl, data=params).json()
		print(DATA)

GUI 부분 CLI 부분 독립 시키기

로그인 GUI 구현 안함

#!/usr/bin/python3
import tkinter as tk
import tkinter.ttk as ttk
from bot import *

wikisite = wiki('https://librewiki.net', apiprefix='')
print(wikisite)
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', 'zcxv')

	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):
	#	wikisite.__del__()

window = mainframe()