사용자:하늘/양식

< 사용자:하늘
하늘 (토론 | 기여)님의 2021년 11월 24일 (수) 14:07 판

ceruleanbot

봇으로도 가벼운 편집기로도 사용할 수 있음. 미디어위키 편집기, GUI 봇. 나무위키는 난이도가 급상승이라 나무위키 편집기는 안 만들 예정.

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

import requests
S = requests.Session()

# 사이트 객체
class wiki:
    def __init__(self, URL: str):
        self.url = URL
        self.csrftoken = False
        self.pages = {}
        self.page = None

    def get_csrftoken(self): # csrftoken(토큰 get)
        params = {"action": "query", "meta": "tokens", "format": "json"}
        DATA = S.get(url=self.url, params=params).json()
        self.csrftoken = DATA['query']['tokens']['csrftoken']

    def login(self, name: str, password: str): #로그인 하기
        # Step 1: Retrieve login token first
        params = {
            'action': "query",
            'meta': "tokens",
            'type': "login",
            'format': "json"
        }
        DATA = S.get(url=self.url, params=params).json()
        LOGIN_TOKEN = DATA['query']['tokens']['logintoken']
        # 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": name,
            "lgpassword": password,
            "lgtoken": LOGIN_TOKEN,
            "utf8": 1
        }
        DATA = S.post(self.url, data=params).json()
        if DATA["login"]["result"] == "Success":
            print("로그인 성공")
            self.get_csrftoken()
        else:
            print("로그인 실패")
            exit()

    def logout(self):
        DATA = S.post(self.url, data={"action": "logout",
                                      "token": self.csrftoken, "format": "json"}).json()
        print("로그아웃")
        print(DATA)

    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.url, 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 addpage(self, __page__=None):  # 작업 목록에 페이지 하나 저장 1번 변수는 문자열(str), 객체(object), 공란 모두 가능. 공란이면 사이트 객체 내의 유일한 문서 객체를 객체 목록에 올림.
        if type(__page__) == str:
            self.pages[__page__] = page(self.url, __page__, self.csrftoken)
        elif type(__page__) == object:
            self.pages[__page__.title] = __page__  # elif type(page) == dict:
        elif __page__ == None:					# setpage() 호출 후에 addpage() 호출
            if self.page != None:
                self.pages[self.page.title] = self.page

    def setpage(self, pagename: str):  # 사이트 객체 내에 페이지 객체 저장, 리턴
        self.page = page(self.url, pagename, self.csrftoken)  # 내부 사이트 객체에 저장
        return self.page  # 페이지 객체 리턴, 사용법 : a = wiki.page('asdf') a.get()

class page:
    def __init__(self, url, title, tokens):
        self.url = url
        self.title = title
        self.csrftoken = tokens

    def get(self):
        params = {
            "action": "query",
            "format": "json",
            "prop": "revisions",
            "formatversion": "2",
            "rvprop": "content",
            "rvslots": "*",
            "titles": self.title
        }
        pageData = S.get(url=self.url, params=params).json()[
            'query']['pages'][0]
        if not 'missing' in pageData:
            self.cont = pageData['revisions'][0]['slots']['main']['content']
        else:
            self.cont = 'missing page'

    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 = ''):
        if self.csrftoken == False:
            print('csrftoken is ungotten')
            return
        print(self.title+' 편집')
        params = {
            "action": "edit",
            "format": "json",
            "title": self.title,
            "text": self.cont,
            "summary": summary,
            "token": self.csrftoken,
            "utf8": 1,
            "formatversion": "latest",
            "bot": "true"
        }
        DATA = S.post(url=self.url, data=params).json()
        print(DATA)

GUI 부분 CLI 부분 독립 시키기

import tkinter
import ceruleanbot
import time
import requests
import tkinter as tk
import tkinter.ttk as ttk
libre = ceruleanbot.wiki('https://librewiki.net/api.php')

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.searchdoc)  # 미구현
		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.addtolist)  # 미구현
		self.loginb.pack(pady=0, side='left')

		self.window.mainloop()

	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)
			libre.setpage(self.title)
			libre.page.get()
			setText(self.text, libre.page.cont)

	def save(self):
		libre.page.save()

	def addtolist(self):
		libre.addpage()

window = mainframe()