def send_access_token_error(): while not PyTistory._is_listening(): time.sleep(0.1) resp = requests.get( 'http://0.0.0.0:5000/callback#access_token=some-access-token&state=some-state') resp = requests.get( 'http://0.0.0.0:5000/callback_modified?access_token=&state=some-state') return resp
def test_access_token을_찾을_수_없을_때_2(self, mock): mock.post('https://www.tistory.com/auth/login', status_code=302) mock.get('https://www.tistory.com/oauth/authorize', status_code=302, headers={ 'Location': 'some_callback_url/#state=some-state'}) pytistory = PyTistory() self.assertRaises(ConfigurationError, pytistory.configure, client_id='example client id', tistory_id='example tistory id', tistory_password='******')
def test_파일을_통한_인증_오류(self, _1, _2): pytistory = PyTistory() pytistory.__TESTING__ = True self.assertRaises(ConfigurationError, pytistory.configure, file_name='') self.assertRaises(ConfigurationError, pytistory.configure, file_name='asdf') _1.return_value = True with unittest.mock.patch( 'builtins.open', unittest.mock.mock_open(read_data="")): self.assertRaises(InvalidSectionError, pytistory.configure, file_name='asdf') with unittest.mock.patch( 'builtins.open', unittest.mock.mock_open(read_data="[pytistory]")): self.assertRaises(InvalidNameError, pytistory.configure, file_name='asdf')
def test_callback_server를_이용한_인증(self): while PyTistory._is_listening(): time.sleep(0.1) process = multiprocessing.Process(target=send_access_token) process.start() pytistory = PyTistory() pytistory.__TESTING__ = True pytistory.configure(client_id='some-client-id') self.assertEqual(pytistory.access_token, 'some-access-token', 'Access Token 설정 실패') process.join()
def test_파일을_통한_인증_CLIENT_ID만(self, _1, _2): while PyTistory._is_listening(): time.sleep(0.1) process = multiprocessing.Process(target=send_access_token) process.start() pytistory = PyTistory() pytistory.__TESTING__ = True pytistory.configure() self.assertEqual(pytistory.access_token, 'some-access-token', 'Access Token 설정 실패') process.join()
class TestPost(unittest.TestCase): @requests_mock.mock() def setUp(self, mock): mock.post('https://www.tistory.com/auth/login', status_code=302) mock.get( 'https://www.tistory.com/oauth/authorize', status_code=302, headers={ 'Location': 'some_callback_url/#access_token=some-access-token&state=some-state' }) self.pytistory = PyTistory() self.pytistory.configure(client_id='example client id', tistory_id='example tistory id', tistory_password='******') @requests_mock.mock() def test_최근_게시글_목록(self, mock): mock.get('https://www.tistory.com/apis/post/list', json={ "tistory": { "status": "200", "item": { "url": "http://oauth.tistory.com", "secondaryUrl": "", "page": "1", "count": "10", "totalCount": "4", "posts": { "post": [{ "id": "4", "title": "티스토리 OAuth Open API 일단 써보세요!", "postUrl": "http://oauth.tistory.com /4", "visibility": "0", "categoryId": "0", "comments": "6", "trackbacks": "0", "date": "1303796661" }, { "id": "3", "title": "View에 보냅니다~", "postUrl": "http://oauth.tistory.com /3", "visibility": "3", "categoryId": "0", "comments": "0", "trackbacks": "0", "date": "1303372106" }, { "id": "2", "title": "View에 보내봅니다.", "postUrl": "http://oauth.tistory.com /2", "visibility": "3", "categoryId": "0", "comments": "0", "trackbacks": "0", "date": "1303372007" }, { "id": "1", "title": "티스토리 OAuth2.0 API 오픈!", "postUrl": "http://oauth.tistory.com /1", "visibility": "0", "categoryId": "0", "comments": "0", "trackbacks": "0", "date": "1303352668" }] } } } }) data = self.pytistory.post.list(blog_name='oauth') self.assertEqual('1', data['item']['page']) def test_최근_게시글_목록_블로그_비_명시(self): self.assertRaises(NoSpecifiedBlogError, self.pytistory.post.list) @requests_mock.mock() def test_블로그_없을_때(self, mock): mock.get('https://www.tistory.com/apis/post/list', json={"tistory": { "status": "400", "item": {} }}) self.assertRaises(ParsingError, self.pytistory.post.list, blog_name='oauth-not-found') @requests_mock.mock() def test_블로그_글_작성(self, mock): mock.post('https://www.tistory.com/apis/post/write', json={ "tistory": { "status": "200", "postId": "1", "url": "http://sampleUrl.tistory.com/1" } }) response = self.pytistory.post.write('테스트 포스팅', blog_name='oauth', visibility=2, content='글 내용', tag=['가나다', '라마바']) self.assertEqual(response['postId'], "1", "포스팅 작성 불가") response = self.pytistory.post.write('테스트 포스팅', blog_name='oauth', visibility=2, content='글 내용', published=datetime.datetime.now()) self.assertEqual(response['postId'], "1", "포스팅 작성 불가") def test_블로그_글_작성_에러(self): self.assertRaises(TypeError, self.pytistory.post.write, '테스트 포스팅', blog_name='oauth', visibility='a', content='글 내용', tag=['가나다', '라마바']) self.assertRaises(TypeError, self.pytistory.post.write, '테스트 포스팅', blog_name='oauth', visibility=2, published='b', content='글 내용', tag=['가나다', '라마바']) self.assertRaises(TypeError, self.pytistory.post.write, '테스트 포스팅', blog_name='oauth', visibility=2, content='글 내용', published=datetime.datetime.now(), tag='가나다') @requests_mock.mock() def test_블로그_글_읽기(self, mock): mock.get( 'https://www.tistory.com/apis/post/read', json={ "tistory": { "status": "200", "item": { "url": "http://oauth.tistory.com", "secondaryUrl": "", "id": "1", "title": "티스토리 OAuth2.0 API 오픈!", "content": "안녕하세요 Tistory API 입니다.<br><br>이번에 Third-party Developer 용 <b>Tistory OAuth 2.0 API</b> 가 오픈됩니다.<br>Tistory 회원이라면, 여러분의 모든 app에 자유롭게 활용하실 수 있습니다. 많은 기대와 사랑 부탁드립니다. < br > ", "categoryId": "0", "postUrl": "http://oauth.tistory.com/1", "visibility": "0", "acceptComment": "1", "acceptTrackback": "1", "tags": { "tag": ["open", "api"] }, "comments": "0", "trackbacks": "0", "date": "1303352668" } } }) post_response = self.pytistory.post.read(12, blog_name='oauth') self.assertIn('안녕하세요 Tistory API 입니다.', post_response['item']['content']) self.assertIn('티스토리 OAuth2.0 API 오픈!', post_response['item']['title']) self.assertIn('open', post_response['item']['tags']['tag']) @requests_mock.mock() def test_블로그_글_수정(self, mock): mock.post('https://www.tistory.com/apis/post/modify', json={ "tistory": { "status": "200", "postId": "1", "url": "http://sampleUrl.tistory.com/1" } }) response = self.pytistory.post.modify('테스트 포스팅 - 수정', 1, blog_name='oauth', visibility=2, content='글 내용 - 수정', tag=['가나다', '라마바', '수정']) self.assertEqual(response['postId'], "1", "수정 불가") response = self.pytistory.post.modify('테스트 포스팅 - 수정', 1, blog_name='oauth', visibility=2, content='글 내용 - 수정') self.assertEqual(response['postId'], "1", "수정 불가") def test_블로그_글_수정_에러(self): self.assertRaises(TypeError, self.pytistory.post.modify, '테스트 포스팅', 1, blog_name='oauth', visibility='a', content='글 내용', tag=['가나다', '라마바']) self.assertRaises(TypeError, self.pytistory.post.modify, '테스트 포스팅', 1, blog_name='oauth', visibility=2, content='글 내용', tag='가나다') @requests_mock.mock() def test_파일_첨부_후_게시(self, mock): mock.post( 'https://www.tistory.com/apis/post/attach', json={ "tistory": { "status": "200", "url": "http://cfile6.uf.tistory.com/image/1328CE504DB79F5932B13F", "replacer": "%5b%23%23_1N%7ccfile6.uf%401328CE504DB79F5932B13F%7cwidth%3d\"500\"+height%3d\"300\"%7c_%23%23%5d" } }) self.pytistory.post.attach('tests/test_image.png', blog_name='oauth') def test_파일_첨부_후_게시_파일_읽기_오류(self): self.assertRaises(FileNotFoundError, self.pytistory.post.attach, 'tests/test_image_not-found.png', blog_name='oauth') @requests_mock.mock() def test_블로그_글_삭제(self, mock): mock.post('https://www.tistory.com/apis/post/delete', json={"tistory": { "status": "200" }}) self.pytistory.post.delete(1, blog_name='oauth')
class TestComment(unittest.TestCase): @requests_mock.mock() def setUp(self, mock): mock.post('https://www.tistory.com/auth/login', status_code=302) mock.get( 'https://www.tistory.com/oauth/authorize', status_code=302, headers={ 'Location': 'some_callback_url/#access_token=some-access-token&state=some-state' }) self.pytistory = PyTistory() self.pytistory.configure(client_id='example client id', tistory_id='example tistory id', tistory_password='******') @requests_mock.mock() def test_댓글_리스트_받아오기(self, mock): mock.get('https://www.tistory.com/apis/comment/list', json={ "tistory": { "status": "200", "item": { "url": "http://oauth.tistory.com/4", "secondaryUrl": "", "postId": "4", "totalCount": "3", "comments": { "comment": [{ "id": "8176918", "date": "1303796711", "name": "지나다가", "parentId": "", "homepage": "http://someurl.com", "visibility": "2", "comment": "좋은 글 감사합니다.", "open": "Y" }] } } } }) self.pytistory.comment.list(1, blog_name='test') @requests_mock.mock() def test_최근_댓글_목록_가져오기(self, mock): mock.get( 'https://www.tistory.com/apis/comment/newest', json={ "tistory": { "status": "200", "item": { "url": "http://oauth.tistory.com", "secondaryUrl": "", "comments": { "comment": [{ "id": "8176926", "date": "1303796900", "postId": "4", "name": "Tistory API", "homepage": "http://oauth.tistory.com", "comment": "비루한 글에 칭찬을 하시니 몸둘바를 모르.. 지 않아!", "open": "Y", "link": "http://oauth.tistory.com/4#comment8176926" }] } } } }) self.pytistory.comment.newest(blog_name='test') @requests_mock.mock() def test_댓글_작성하기(self, mock): mock.post('https://www.tistory.com/apis/comment/write', json={ "tistory": { "status": "200", "commentUrl": "http://oauth.tistory.com/4#comment8176976", "result": "OK" } }) resp = self.pytistory.comment.write(1, '댓글-예시', blog_name='test') self.assertEqual(resp['result'], 'OK', '댓글을 작성할 수 없습니다.') resp = self.pytistory.comment.write(2, '댓글-예시', blog_name='test', parent_id=1) self.assertEqual(resp['result'], 'OK', '댓글을 작성할 수 없습니다.') resp = self.pytistory.comment.write(1, '댓글-예시', blog_name='test', secret=1) self.assertEqual(resp['result'], 'OK', '댓글을 작성할 수 없습니다.') @requests_mock.mock() def test_댓글_수정하기(self, mock): mock.post('https://www.tistory.com/apis/comment/modify', json={ "tistory": { "status": "200", "commentUrl": "http://oauth.tistory.com/4#comment8176976", "result": "OK" } }) resp = self.pytistory.comment.modify(1, 1, '수정된 댓글', blog_name='test') self.assertEqual(resp['result'], 'OK', '댓글을 작성할 수 없습니다.') resp = self.pytistory.comment.modify(1, 1, '수정된 댓글', blog_name='test', parent_id=1) self.assertEqual(resp['result'], 'OK', '댓글을 작성할 수 없습니다.') resp = self.pytistory.comment.modify(1, 1, '수정된 댓글', blog_name='test', secret=1) self.assertEqual(resp['result'], 'OK', '댓글을 작성할 수 없습니다.') @requests_mock.mock() def test_댓글_삭제하기(self, mock): mock.post('https://www.tistory.com/apis/comment/delete', json={"tistory": { "status": "200" }}) self.pytistory.comment.delete(1, 1, blog_name='test')
def test_아무런_설정_옵션이_없을_때(self): pytistory = PyTistory() self.assertRaises(OptionNotFoundError, pytistory.configure)
def test_토큰이_설정되지_않았을_때(self): pytistory = PyTistory() self.assertRaises(TokenNotFoundError, pytistory.blog.info)
def __init__(self, accessToken): self.accessToken = accessToken self.pyTistory = PyTistory() self.pyTistory.configure(access_token=accessToken)
class TistoryTools: accessToken = "" pyTistory = {} categoryInfo = {} default_folder_path = '' foler_meta_dic_arr = [] def __init__(self, accessToken): self.accessToken = accessToken self.pyTistory = PyTistory() self.pyTistory.configure(access_token=accessToken) def get_category_folder_info(self, blog_name, base_folder): self.foler_meta_dic_arr = metatools.get_folder_meta_total_file( base_folder) if self.foler_meta_dic_arr == None: tistory_api_res = self.pyTistory.category.list(blog_name=blog_name) self.foler_meta_dic_arr = self.make_category_folder_info( tistory_api_res, base_folder, blog_name) self.default_folder_path = base_folder return True def get_category_folder_path(self, blog_name, category_id, base_folder): if self.foler_meta_dic_arr == None: return None for folder_meta_dic in self.foler_meta_dic_arr: if folder_meta_dic['folder_code'] == category_id: return str( PurePath(base_folder).joinpath( folder_meta_dic['target_folder_path'])) return base_folder def make_category_folder_info(self, tistory_api_res, target_folder_path, blog_name): tistory_api_category_info_arr = tistory_api_res['item']['categories'] logging.log_debug(tistory_api_category_info_arr) tmp_folder_meta_dic_arr = [] listCount = len(tistory_api_category_info_arr) while (listCount > 0): for tistory_api_category_info in tistory_api_category_info_arr: # 1. parents item filter ''' {'parent': '157165', 'id': '183301', 'name': 'GCC', 'entries': '3', 'entriesInLogin': '******', 'label': 'Compiler/GCC'} ''' tistory_api_category_info['label'] = html.unescape( tistory_api_category_info['label']) tistory_api_category_info['label'] = mdtools.clean_text_2( tistory_api_category_info['label']) if tistory_api_category_info['parent'] == '': folder_meta_dic = metatools.save_folder_meta_one_file( target_folder_path, tistory_api_category_info['label'].replace(' ', '_'), tistory_api_category_info['id'], blog_name) tistory_api_category_info_arr.remove( tistory_api_category_info) tmp_folder_meta_dic_arr.append(folder_meta_dic) else: for categoryMakeInfo in tmp_folder_meta_dic_arr: if tistory_api_category_info[ 'parent'] == categoryMakeInfo['folder_code']: folder_meta_dic = metatools.save_folder_meta_one_file( target_folder_path, tistory_api_category_info['label'].replace( ' ', '_'), tistory_api_category_info['id'], blog_name) tistory_api_category_info_arr.remove( tistory_api_category_info) tmp_folder_meta_dic_arr.append(folder_meta_dic) listCount = len(tistory_api_category_info_arr) # non category make.. folder_meta_dic = metatools.save_folder_meta_one_file( target_folder_path, 'non_category/type-non', '', blog_name) tmp_folder_meta_dic_arr.append(folder_meta_dic) for i in range(-10, 1): folder_meta_dic = metatools.save_folder_meta_one_file( target_folder_path, 'non_category/type' + str(i), str(i), blog_name) tmp_folder_meta_dic_arr.append(folder_meta_dic) metatools.save_folder_meta_total_file(target_folder_path, tmp_folder_meta_dic_arr) return tmp_folder_meta_dic_arr def writePost(self, blog_name, post_title='title', category_name='', category_id=0, content_html='', tags=[]): tistory_api_res = self.pyTistory.post.write(post_title, blog_name=blog_name, visibility=1, category=category_id, content=content_html, tag=tags) def read_post(self, id, blog_name, base_folder): logging.log_info("read post : target id => " + str(id)) try: tistory_api_res = self.pyTistory.post.read(id, blog_name=blog_name) except Exception as ex: logging.log_info(" - Oops! valid read target skip read post") return None # 1. markdown yml generate markdown_header_yml_dic = metatools.get_markdown_header_yml_skel() markdown_header_yml_dic['title'] = tistory_api_res['item']['title'] markdown_header_yml_dic['publish'] = FUNC_RET_DEF_TRUE if tistory_api_res['item']['tags'] != '': markdown_header_yml_dic['tags'] = ','.join( tistory_api_res['item']['tags']['tag']) # 2. file name generate tistory_post_date = tistory_api_res['item']['date'].replace("-", "") tistory_post_date = tistory_post_date[0:8] + "_" # 2-1. post title markdown_post_title = tistory_api_res['item']['title'] markdown_post_title = markdown_post_title.replace(" ", "_") markdown_post_title = markdown_post_title.replace("/", "|") markdown_post_title = markdown_post_title.replace("\\", "|") markdown_post_title = html.unescape(markdown_post_title) markdown_post_title = mdtools.clean_text_1(markdown_post_title) # 2-2. make file name markdown_file_name = tistory_post_date + markdown_post_title + ".md" # 3. post meta generate post_meta_dic = metatools.get_post_meta_skel() post_meta_dic['meta_ver'] = '1' post_meta_dic['file_md5'] = '' post_meta_dic['file_name'] = markdown_file_name post_meta_dic['is_publish'] = FUNC_RET_DEF_TRUE post_meta_dic['publish_date'] = tistory_api_res['item']['date'] post_meta_dic['publish_id'] = tistory_api_res['item']['id'] post_meta_dic['publish_url'] = tistory_api_res['item']['postUrl'] post_meta_dic['publish_category_id'] = tistory_api_res['item'][ 'categoryId'] # 4. get save target (category <-> folder) target_path = self.get_category_folder_path( blog_name, post_meta_dic['publish_category_id'], base_folder) logging.log_info(' + target_path : ' + target_path) logging.log_info(' + targetfilename : ' + markdown_file_name) # set file info fileinfo_dic = filemgr.get_fileinfo_dic(target_path, markdown_file_name) asset_folder_path = metatools.get_asset_folder_path(fileinfo_dic) # convert html to markdown tistory_api_res['item']['content'] = html.unescape( tistory_api_res['item']['content']) markdown_str = mdtools.convert_html_to_markdown_str( tistory_api_res['item']['content'], asset_folder_path) # convert tistory attach url str to local attach (save to local) markdown_str = mdtools.convert_markdown_tistory_attach_str( markdown_str, asset_folder_path) mdtools.save_markdown_file(markdown_str, fileinfo_dic['abpath_full'], markdown_header_yml_dic) post_meta_dic['file_md5'] = filemgr.get_file_md5_hash( target_path, markdown_file_name) metatools.save_post_meta_file(fileinfo_dic, post_meta_dic) def getPostList(self, blog_name): tistory_api_res = self.pyTistory.post.list(blog_name=blog_name) def editPost(self, blog_name, post_title='title', category_name='', category_id=0, content_html='', tags=[]): tistory_api_res = self.pyTistory.post.write(post_title, blog_name=blog_name, visibility=1, category=category_id, content=content_html, tag=tags) # tistory api def check_post_files(self, blog_name, base_folder): post_info_arr = {} new_post_fileinfo_dic_arr = [] del_post_fileinfo_dic_arr = [] update_post_fileinfo_dic_arr = [] fileinfo_dic_arr = filemgr.get_fileinfo_from_folder( base_folder, '*.md') for fileinfo_dic in fileinfo_dic_arr: post_meta_dic = metatools.get_post_meta_file(fileinfo_dic) # new post : 기존 md post meta 파일이 없다. if post_meta_dic == None: new_post_fileinfo_dic_arr.append(fileinfo_dic) continue if post_meta_dic['file_md5'] != filemgr.get_file_md5_hash( fileinfo_dic['abpath_full']): update_post_fileinfo_dic_arr.append(fileinfo_dic) continue post_info_arr['new_post_fileinfo'] = new_post_fileinfo_dic_arr post_info_arr['update_post_fileinfo'] = update_post_fileinfo_dic_arr return post_info_arr def new_post_markdown_file(self, blog_name, fileinfo_dic): attach_meta_dic_arr = self.attach_meta_chk( blog_name, metatools.get_asset_folder_path(fileinfo_dic)) post_tags = [] post_title = '' post_cateory = 0 """ 0: 비공개 1: 보호 2: 공개 3: 발행 """ post_publish = 0 folder_meta_dic = metatools.get_folder_meta_one_file(fileinfo_dic) md_conv_html = mdtools.convert_markdown_to_html_file( fileinfo_dic['abpath_full'], attach_meta_dic_arr) if md_conv_html['meta'] != None and len( md_conv_html['meta']) > 0 and md_conv_html['meta'][ 'title'] != None and md_conv_html['meta']['title'] != '': post_title = md_conv_html['meta']['title'] else: post_title = fileinfo_dic['file_name'] if md_conv_html['meta'] != None and len( md_conv_html['meta']) > 0 and md_conv_html['meta'][ 'tags'] != None and md_conv_html['meta']['tags'] != '': spilt_target = str(md_conv_html['meta']['tags']) spilt_target = spilt_target.replace('[', '') spilt_target = spilt_target.replace(']', '') spilt_target = spilt_target.replace('\'', '') spilt_target = spilt_target.replace('\"', '') spilt_str = re.split(', "\[\]', spilt_target) for keyword in spilt_str: if len(str(keyword)) > 0: post_tags.append(str(keyword)) if md_conv_html['meta'] != None and len( md_conv_html['meta'] ) > 0 and md_conv_html['meta']['publish'] != None and md_conv_html[ 'meta']['publish'] != '': if str(md_conv_html['meta']['publish']).find('True') != -1: post_publish = 3 if folder_meta_dic['folder_code'] != None and len( folder_meta_dic['folder_code']): post_cateory = int(folder_meta_dic['folder_code']) logging.log_debug('--- post info ----------') logging.log_debug(' > post_title : ' + str(post_title)) logging.log_debug(' > post_tags : ' + str(post_tags)) logging.log_debug(' > post_cateory : ' + str(post_cateory)) logging.log_debug(' > post_publish : ' + str(post_publish)) tistory_api_res = self.pyTistory.post.write( post_title, blog_name=blog_name, visibility=post_publish, category=post_cateory, content=md_conv_html['html'], tag=post_tags) logging.log_debug('server res : ' + str(tistory_api_res)) if tistory_api_res['status'] == '200': metatools.save_new_post_meta_file(fileinfo_dic, tistory_api_res['postId'], tistory_api_res['url'], str(post_cateory)) def edit_post_markdown_file(self, blog_name, fileinfo_dic): attach_meta_dic_arr = self.attach_meta_chk( blog_name, metatools.get_asset_folder_path(fileinfo_dic)) post_tags = [] post_title = '' post_cateory = 0 """ 0: 비공개 1: 보호 2: 공개 3: 발행 """ post_publish = 0 post_delete = False folder_meta_dic = metatools.get_folder_meta_one_file(fileinfo_dic) md_conv_html = mdtools.convert_markdown_to_html_file( fileinfo_dic['abpath_full'], attach_meta_dic_arr) if md_conv_html['meta'] != None and len( md_conv_html['meta']) > 0 and md_conv_html['meta'].get( 'title' ) != None and md_conv_html['meta'][ 'title'] != None and md_conv_html['meta']['title'] != '': post_title = md_conv_html['meta']['title'] else: post_title = fileinfo_dic['file_name'] if md_conv_html['meta'] != None and len( md_conv_html['meta']) > 0 and md_conv_html['meta'].get( 'tags') != None and md_conv_html['meta'][ 'tags'] != None and md_conv_html['meta']['tags'] != '': spilt_target = str(md_conv_html['meta']['tags']) spilt_target = spilt_target.replace('[', '') spilt_target = spilt_target.replace(']', '') spilt_target = spilt_target.replace('\'', '') spilt_target = spilt_target.replace('\"', '') spilt_str = re.split(', "\[\]', spilt_target) for keyword in spilt_str: if len(str(keyword)) > 0: post_tags.append(str(keyword)) if md_conv_html['meta'] != None and len( md_conv_html['meta']) > 0 and md_conv_html['meta'].get( 'publish') != None and md_conv_html['meta'][ 'publish'] != None and md_conv_html['meta'][ 'publish'] != '': if str(md_conv_html['meta']['publish']).find('True') != -1: post_publish = 3 # 강제로 삭제는 못하고, 그냥 비공개로 처리한다. if md_conv_html['meta'] != None and len( md_conv_html['meta']) > 0 and md_conv_html['meta'].get( 'delete' ) != None and md_conv_html['meta'][ 'delete'] != None and md_conv_html['meta']['delete'] != '': logging.log_debug(md_conv_html['meta']['delete']) if str(md_conv_html['meta']['delete']).find('True') != -1: post_publish = 0 post_delete = True if folder_meta_dic['folder_code'] != None and len( folder_meta_dic['folder_code']): post_cateory = int(folder_meta_dic['folder_code']) logging.log_debug('--- post info ----------') logging.log_debug(' > post_title : ' + str(post_title)) logging.log_debug(' > post_tags : ' + str(post_tags)) logging.log_debug(' > post_cateory : ' + str(post_cateory)) logging.log_debug(' > post_publish : ' + str(post_publish)) post_meta_dic = metatools.get_post_meta_file(fileinfo_dic) tistory_api_res = self.pyTistory.post.modify( post_title, int(post_meta_dic['publish_id']), blog_name=blog_name, visibility=post_publish, category=post_cateory, content=md_conv_html['html'], tag=post_tags) logging.log_debug( logging.log_debug('server res : ' + str(tistory_api_res))) if tistory_api_res['status'] == '200': metatools.save_new_post_meta_file(fileinfo_dic, tistory_api_res['postId'], tistory_api_res['url'], str(post_cateory)) # 이후에 삭제옵션이 켜져있으면 그냥 해당 게시물은 로컬에서만 삭제하자 if post_delete == True: logging.log_info(' !!!! delete Target : ' + post_meta_dic['file_name']) metatools.delete_post_meta_file(fileinfo_dic, tistory_api_res['postId'], tistory_api_res['url'], str(post_cateory)) def attach_meta_chk(self, blog_name, asset_path): attach_meta_update_need = False upload_target_fileinfo_dic_arr = metatools.check_attach_meta_file( asset_path) logging.log_info('target upload files') logging.log_info(upload_target_fileinfo_dic_arr) attach_meta_dic_arr = [] for upload_target_fileinfo_dic in upload_target_fileinfo_dic_arr: # upload to tistory tistory_api_res = self.pyTistory.post.attach( upload_target_fileinfo_dic['abpath_full'], blog_name=blog_name) logging.log_debug( logging.log_debug('server res : ' + str(tistory_api_res))) """ {'url': 'http://cfile24.uf.tistory.com/image/999BEE435D80AFA42A5A39', 'status': '200', 'replacer': '[##_1N|[email protected]|width="430" height="121" filename="2019-09-17-17-14-30.png" filemime="image/png"|_##]'} """ attach_meta_dic = {} # if tistory_api_res check if tistory_api_res['status'] == '200': attach_meta_dic['file_name'] = upload_target_fileinfo_dic[ 'file_full_name'] attach_meta_dic['file_url'] = tistory_api_res['url'] attach_meta_dic['attach_folder'] = str( PurePath(asset_path).name) logging.log_debug(attach_meta_dic) attach_meta_dic_arr.append(attach_meta_dic) attach_meta_update_need = True if attach_meta_update_need == True: metatools.save_attach_meta_file(asset_path, attach_meta_dic_arr) return metatools.get_attach_meta_file(asset_path)
class TestBlog(unittest.TestCase): @requests_mock.mock() def setUp(self, mock): mock.post('https://www.tistory.com/auth/login', status_code=302) mock.get( 'https://www.tistory.com/oauth/authorize', status_code=302, headers={ 'Location': 'some_callback_url/#access_token=some-access-token&state=some-state' }) self.pytistory = PyTistory() self.pytistory.configure(client_id='example client id', tistory_id='example tistory id', tistory_password='******') @requests_mock.mock() def test_블로그_정보_받아오기(self, mock): mock.get( 'https://www.tistory.com/apis/blog/info', json={ "tistory": { "status": "200", "id": "*****@*****.**", "item": [{ "url": "http://oauth.tistory.com", "secondaryUrl": "http://", "nickname": "Tistory API", "title": "나만의 앱, Tistory OAuth API 로 만들어보세요!", "description": "", "default": "Y", "blogIconUrl": "http://i1.daumcdn.net/cfs.tistory/blog/79/795307/index.gif", "faviconUrl": "http://i1.daumcdn.net/cfs.tistory/blog/79/795307/index.ico", "profileThumbnailImageUrl": "http://cfile1.uf.tistory.com/R106x0/1851DB584DAF942950AF29", "profileImageUrl": "http://cfile1.uf.tistory.com/R106x0/1851DB584DAF942950AF29", "statistics": { "post": "3", "comment": "0", "trackback": "0", "guestbook": "0", "invitation": "0" } }, { "url": "http://oauth2.tistory.com", "secondaryUrl": "http://", "nickname": "Tistory API", "title": "나만의 비밀 홈", "description": "", "default": "N", "blogIconUrl": "http://i1.daumcdn.net/cfs.tistory/blog/79/795308/index.gif", "faviconUrl": "http://i1.daumcdn.net/cfs.tistory/blog/79/795308/index.ico", "profileThumbnailImageUrl": "", "profileImageUrl": "", "blogId": "795308", "statistics": { "post": "0", "comment": "0", "trackback": "0", "guestbook": "0", "invitation": "0" } }] } }) data = self.pytistory.blog.info() self.assertIn('item', data)
class TestGuestbook(unittest.TestCase): @requests_mock.mock() def setUp(self, mock): mock.post('https://www.tistory.com/auth/login', status_code=302) mock.get( 'https://www.tistory.com/oauth/authorize', status_code=302, headers={ 'Location': 'some_callback_url/#access_token=some-access-token&state=some-state' }) self.pytistory = PyTistory() self.pytistory.configure(client_id='example client id', tistory_id='example tistory id', tistory_password='******') @requests_mock.mock() def test_방명록_리스트_받아오기(self, mock): mock.get('https://www.tistory.com/apis/guestbook/list', json={ "tistory": { "status": "200", "item": { "url": "http://oauth.tistory.com", "secondaryUrl": "", "page": "1", "totalCount": "2", "guestbooks": { "guestbook": [{ "id": "8177011", "date": "1303798898", "name": "잘못들어온 사람", "homepage": "http://wrongway.com", "comment": "아.. 저 여기 잘못들어왔나봐요..", "open": "Y", "replies": { "reply": { "id": "8177015", "date": "1303799030", "name": "Tistory API", "parentId": "8177011", "homepage": "http://oauth.tistory.com", "comment": "들어올때는 마음대로 들어왔겠지만 나갈때는 아니란다", "open": "Y" } } }, { "id": "8177008", "date": "1303798795", "name": "개발자", "homepage": "http://somedeveloper.com", "comment": "좋은 API 많이 만들어주세요!", "open": "Y", "replies": "" }] } } } }) self.pytistory.guestbook.list(blog_name='test') @requests_mock.mock() def test_방명록_작성(self, mock): mock.post('https://www.tistory.com/apis/guestbook/write', json={ "tistory": { "status": "200", "guestbookUrl": "http://oauth.tistory.com/guestbook", "result": "OK" } }) self.pytistory.guestbook.write('방명록 내용', blog_name='test') self.pytistory.guestbook.write('방명록 내용', blog_name='test', parent_id=1) self.pytistory.guestbook.write('방명록 내용', blog_name='test', secret=1) @requests_mock.mock() def test_방명록_수정(self, mock): mock.post('https://www.tistory.com/apis/guestbook/modify', json={ "tistory": { "status": "200", "guestbookUrl": "http://oauth.tistory.com/guestbook", "result": "OK" } }) self.pytistory.guestbook.modify(1, '수정된 방명록 내용', blog_name='test') self.pytistory.guestbook.modify(1, '수정된 방명록 내용', blog_name='test', parent_id=1) self.pytistory.guestbook.modify(1, '수정된 방명록 내용', blog_name='test', secret=1) @requests_mock.mock() def test_방명록_삭제(self, mock): mock.post('https://www.tistory.com/apis/guestbook/delete', json={"tistory": { "status": "200", }}) self.pytistory.guestbook.delete(1, blog_name='test')
class TestCategory(unittest.TestCase): @requests_mock.mock() def setUp(self, mock): mock.post('https://www.tistory.com/auth/login', status_code=302) mock.get( 'https://www.tistory.com/oauth/authorize', status_code=302, headers={ 'Location': 'some_callback_url/#access_token=some-access-token&state=some-state' }) self.pytistory = PyTistory() self.pytistory.configure(client_id='example client id', tistory_id='example tistory id', tistory_password='******') @requests_mock.mock() def test_카테고리_목록(self, mock): mock.get('https://www.tistory.com/apis/category/list', json={ "tistory": { "status": "200", "item": { "url": "oauth", "secondaryUrl": "", "categories": { "category": [{ "id": "403929", "name": "OAuth2.0 Athentication", "parent": "", "label": "OAuth2.0 Athentication", "entries": "0" }] } } } }) self.pytistory.category.list(blog_name='test-blog-5532') @requests_mock.mock() def test_카테고리_목록_target_url_deprecated(self, mock): mock.get('https://www.tistory.com/apis/category/list', json={ "tistory": { "status": "200", "item": { "url": "oauth", "secondaryUrl": "", "categories": { "category": [{ "id": "403929", "name": "OAuth2.0 Athentication", "parent": "", "label": "OAuth2.0 Athentication", "entries": "0" }] } } } }) with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") self.pytistory.category.list(target_url='http://oauth.tistory.com') assert len(w) == 1 assert "A parameter `targetUrl` is deprecated." in str( w[-1].message)