serve_client.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. import base64
  2. import hashlib
  3. import json
  4. import os.path
  5. import re
  6. import requests
  7. from Crypto.Cipher import AES
  8. from config import TARGET_URL
  9. from tools.logger_handle import logger
  10. class ServerClient:
  11. def __init__(self, server_host, user_name, password):
  12. self.user_name = user_name
  13. self.password = password
  14. self.serve_host = server_host
  15. self.access_token = None
  16. self.login_reply = None
  17. self.headers = {
  18. 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36',
  19. }
  20. self.login()
  21. def login(self):
  22. url = self.serve_host + '/auth/oauth2/token'
  23. reply = requests.post(url, params={
  24. 'username': self.user_name,
  25. 'password': self.encryption(self.password),
  26. 'grant_type': 'password',
  27. 'scope': 'server',
  28. 'client_id': 'knowledge',
  29. 'client_secret': 'knowledge'
  30. }, headers={'Content-Type': 'multipart/form-data',
  31. 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36'})
  32. self.access_token = reply.json()['access_token']
  33. self.login_reply = reply.json()
  34. self.headers['Authorization'] = f'Bearer {self.access_token}'
  35. def decryption(self, hex_str, secret='anZz000000000000'):
  36. key_bytes = secret.encode('utf-8')
  37. iv = key_bytes
  38. base64_str = base64.b64encode(bytes.fromhex(hex_str)).decode('utf-8')
  39. cipher = AES.new(key_bytes, AES.MODE_CBC, iv)
  40. decrypted = cipher.decrypt(base64.b64decode(base64_str))
  41. try:
  42. decoded = decrypted.decode('utf-8')
  43. except UnicodeDecodeError:
  44. decoded = decrypted.decode('utf-8', errors='ignore')
  45. # 清除控制字符(类似 JS 中的 [\u0000-\u001F\u007F-\u009F])
  46. cleaned = re.sub(r'[\x00-\x1F\x7F-\x9F]', ' ', decoded)
  47. try:
  48. return json.loads(cleaned)
  49. except json.JSONDecodeError:
  50. return cleaned.strip()
  51. def zero_pad(self, data, block_size=16):
  52. pad_len = block_size - (len(data) % block_size)
  53. if pad_len == 0:
  54. return data
  55. return data + b'\x00' * pad_len
  56. def encryption(self, payload, secret='a25vd2xlZGdl0000'.encode('utf-8')):
  57. data_bytes = payload.encode('utf-8')
  58. padded_data = self.zero_pad(data_bytes)
  59. cipher = AES.new(secret, AES.MODE_CBC, secret)
  60. encrypted = cipher.encrypt(padded_data)
  61. return encrypted.hex()
  62. def get_base_path(self):
  63. url = self.serve_host + '/mgr/document/dcLibrary/knowledges/owner?size=1000&current=1'
  64. reply = requests.get(url, headers=self.headers)
  65. reply_data = reply.json()
  66. if reply_data.get('code') != 0:
  67. return []
  68. data = self.decryption(reply_data['data'])
  69. return data.get('records', [])
  70. def get_folder_by_id(self, _id):
  71. url = f'{self.serve_host}/mgr/document/dcLibrary/tree?id={_id}'
  72. self.headers['documentid'] = _id
  73. reply = requests.get(url, headers=self.headers)
  74. reply_data = reply.json()
  75. if reply_data.get('code') != 0:
  76. return []
  77. data = self.decryption(reply_data['data'])
  78. return data.get('data', [])
  79. def check_resp(self, resp):
  80. if resp.json()['code'] == -2:
  81. self.login()
  82. return True
  83. return False
  84. def download_file(self, file_info, storage_path):
  85. try:
  86. resp = requests.get(f'{self.serve_host}/mgr/document/dcLibrary/file/get/file/{file_info["id"]}',
  87. headers=self.headers)
  88. local_file_name = file_info['filePath'].replace('/', '_')
  89. with open(os.path.join(storage_path, local_file_name), 'wb') as f:
  90. f.write(resp.content)
  91. with open(os.path.join(storage_path, local_file_name + '.metadata'), 'w', encoding='utf-8') as f:
  92. f.write(json.dumps({
  93. 'file_id': file_info["id"],
  94. 'bucket_name': file_info['bucketName'],
  95. 'md5': self.get_file_md5(os.path.join(storage_path, local_file_name)),
  96. 'file_name': file_info['name'],
  97. 'oss_path': file_info['filePath'],
  98. 'update_time': file_info['updateTime']
  99. }))
  100. except Exception as e:
  101. logger.exception(e)
  102. return False
  103. return True
  104. def upload_file(self, file_path):
  105. try:
  106. with open(f'{file_path}.metadata', 'r', encoding='utf-8') as f:
  107. file_metadata = json.loads(f.read())
  108. file_id = file_metadata['file_id']
  109. files = [('file', (file_metadata['file_name'], open(file_path, 'rb'),
  110. 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'))]
  111. resp = requests.post(
  112. f'{self.serve_host}/mgr/document/dcLibrary/saveByPython/{file_id}',
  113. headers=self.headers,
  114. files=files,
  115. data={}
  116. )
  117. if self.check_resp(resp):
  118. resp = requests.post(
  119. f'{self.serve_host}/mgr/document/dcLibrary/saveByPython/{file_id}',
  120. headers=self.headers,
  121. files=files,
  122. data={})
  123. if resp.json()['code'] == 0:
  124. return True
  125. else:
  126. logger.error(resp.json())
  127. return False
  128. except Exception as e:
  129. logger.exception(e)
  130. return False
  131. @staticmethod
  132. def get_file_md5(file_path):
  133. md5 = hashlib.md5()
  134. with open(file_path, 'rb') as f:
  135. # 分块读取以支持大文件
  136. while chunk := f.read(8192):
  137. md5.update(chunk)
  138. return md5.hexdigest()
  139. @staticmethod
  140. def load_metadata(local_path):
  141. with open(f'{local_path}.metadata', 'r', encoding='utf-8') as f:
  142. file_metadata = json.loads(f.read())
  143. return file_metadata
  144. def create_cloud_file(self, local_file='D:/bussion/法律法规/道路交通安全法.docx',
  145. folder_id='5b091f1007c880528bd913530987d5e5'):
  146. payload = {'module': '/jvs-knowledge-ui/jvs-knowledge-import/'}
  147. files = [
  148. ('file', (os.path.basename(local_file), open(local_file, 'rb'),
  149. 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'))]
  150. resp = requests.post(f'{TARGET_URL}/mgr/document/dcLibrary/upload/{folder_id}',
  151. headers=self.headers, data=payload, files=files)
  152. if resp.json().get('code') == 0:
  153. return True
  154. else:
  155. return False
  156. def get_folder_tree(self):
  157. resp = requests.get(f'{TARGET_URL}/mgr/document/dcLibrary/tree/myFolder', headers=self.headers)
  158. if resp.json().get('code') == 0:
  159. return self.decryption(resp.json()['data'])
  160. else:
  161. return []
  162. def get_template_file_info(self, file_id):
  163. try:
  164. resp = requests.get(f'{TARGET_URL}/mgr/document/dcLibrary/template/get/{file_id}',
  165. headers=self.headers)
  166. if resp.json().get('code') == 0:
  167. return self.decryption(resp.json()['data'])
  168. return False
  169. except Exception as e:
  170. logger.error('获取模板信息出错')
  171. logger.exception(e)
  172. return False
  173. def download_template(self, url, file_path):
  174. try:
  175. resp = requests.get(url)
  176. with open(file_path, 'wb') as f:
  177. f.write(resp.content)
  178. return True
  179. except Exception as e:
  180. logger.error('下载模板文件出错')
  181. logger.exception(e)
  182. return False
  183. def get_file_info(self, file_id):
  184. '''
  185. :param file_id:
  186. :return:
  187. '''
  188. logger.info(self.headers)
  189. try:
  190. resp = requests.get(f'{self.serve_host}/mgr/document/no/auth/dcLibrary/info/{file_id}',
  191. headers=self.headers)
  192. if not self.check_resp(resp):
  193. resp = requests.get(f'{self.serve_host}/mgr/document/no/auth/dcLibrary/info/{file_id}',
  194. headers=self.headers)
  195. if not resp.json()['data']:
  196. return False
  197. return self.decryption(resp.json()['data'])
  198. except Exception as e:
  199. logger.exception(e)
  200. return False
  201. if __name__ == '__main__':
  202. client = ServerClient(f'{TARGET_URL}', 'admin', 'jxkj123456')
  203. res = client.decryption(
  204. "9f79aa09fbeba3e4767bab05c6081c3d95d5dfd297ea65c58484ed5bc37b91cc86f731abb9e7c50555f6029f6d210b433a8821dbeaf4a7768688d4054076f7342f2a8a6db59163d0c6c14523f84a850f1f9c06334a92ee5a56e1a1752930773178fbea2b1219c076aced0bd2e4114f3564acf9ee5f3fa91cff8582010be8aa5a11e66acaeb24b890af691cfba58f86d86680f64753137637cd4f98432f8bb48ec653dc3474d30d20443a9f42a677d2cc6b777530df6d41302a60e4a033aa55731df7149774860fdb5c7855e3f94e657672be15c5e03cdd5e1288bc43d3b10f87d358a8d82807bc26955ad9173a30f81d8d11615906ceb4b007bf8009ff4c50c026b450ac28a3a3030a918197fc3f7e6b350a94a634f5954d945f25d419adf3d67caf9ac144f86a0984e608fa84a65e127845edeece7d9b3e381bc3a01db06d075514da65c721c0eca4d88a344850d5f7f53bdf5f83c29a9dfb189e300e387bfab1dedceea2ad1c7c17e4a5628f385059978e2870eb0c379f08956755043c62bc9e648383fc5e341d8a6f1c75be38b17e593ec264397dbca67855868f61957b8253c189ae04e470982e583bce7083db3357f1206490ea69ac023fce58a497ef37739d9e018345f481495d21c9dd91ae247ad72eb15efab7cab9177806a1c77c2e66f7c69e1617b6272dfcabc756078f5ee8237e112b8da2de64bce0d09f7eea540e5006e0634211998161bf8d1da451dfaa8e3b41d7b001d28821f906106c81eed3c50da52ee6169bd0df26182944fbc7e549badd25171b08202bf02f5dae7f2673ef156e61f5167efe2f10646feaccc295d0d5699e40b5c5543dd1ff8cca52d362e2793f293f5e1a52dd23152cbdda8b48faa3d46d0fa223b8a4c86c7459d82b5f2800753dc4a7ab6c321f7c3fb6cebc8a3cf4f001b82bf33b69d767dda1aa494adf171673bd222b4a8250f529392db306f803f56fcb24d618e7e006bc923097c6fbd8fcfb6e00c6e8ee585bb1ce6611f76e501673adb3a8d9cf00feb96e4c325d2184b44ae19d6741fa3fcbf1fe774d33d72d5cd0c6f4729b45c2cfe74738cf9a08cba1a5266f9c708aa3bfb697837fee870759a3b80d4a42bcbdf2f42e5d5156e5531b7cdc1d22bb5537f3e93c968ffee75a9eff4fc875cc784b468f5b6eb07d886274f2ca50c0617aeeab869919af4a3052d9bdd9d5d7aa9d3a55dcfb9dcbd3a815cc6bf7af5891b9238f7fd429eab4e2b04e69bc0143a0824523eab022effc7e9ce4b24e27df54ee8a2a4775e2af39f4f529cadaa6477b011c7b0af17bfff776f0bf46281b3bac742b0b8e8c41a8f9f486e1989558dbf6f96b80dbca24f62aa11dceb2d72b0d69d569ca0f708059223a3e62181991d5591c8379bc315f8d1683d350971bf84d4aea67a7dd39d2c2630076ae6f4bd2b8ae128290791c7f0e443c63f28b0522f3d30edce8474694c88973c0038c12b68369d3c7ce592ee55a27ee665a2c4f71093061fa8cfd911b7043233f052f435b892c97f957768a879590b1e8e732643fce86c6435d944d9036363dc3866101381c389d576bb66e192f6001101ff9b0a13a9e768bc8c8ec7a7d4af8b72152a5dffdefc0a30c24a0aba527bddb1ca69e4e478de97e2049102b2cbbaf00e29ce4e6ebeb4d26470ccfaf9655681d412ea2e41f4bd7fefb3effa82c05c0a65bb97076ca62165adeca283a5f3d4ae444da04b014e3aeb4ee9c717b8620f044d2e2c09141fc4d8d19f0cedb7fe12340cc55ccc7c91abf8e7398927273c9e91fc735ac7f360e2dca2f80171b1dd71b1bebed63f2768d53954528e16ffefcf582ff1be8a89d09bd102e4474c55e49411e7a0c67a1e69104a8a6fd7f2b17b9eed0da84896a178b23459ab08774d7a513b4890d1147fb8d011df3c480ae111512857a3ec6229b0a18905b3e0f26c4b14ca39d7e8bd8fdde035a91b2bcd920d9b3b007d2016563d75aa6ded7390a5e34ba1889959fe6de734e45810c8990de4b474b9a40aa82ec7dfc21ecc7f739e61ea746d7cdeb10a0cf54536757ebe5af4486ed6218e33ceadd5d5b423f7f12d13fb4b5187209e501896acd5b0b041aa597448457c042eabae95632455896be9ce468b63721914caf67744d395f07458ca3ef60a4e3550cd809eb3a1e70f3b9d1a7c851467a65cf9263e816c9eea2254b12fca25e122a9e34f5f33469f05acd73cff2f9560eff02e18cfcb312e0fe8adabeec07d1490e16040d0641c3cdd31c9473234627f52d8c526b27f6ba87cc8319848a91952f18c466a2605db8eb73448564c2ae6433ca5606b8aff46e307e221e7ffecba418eefdf714bcdac4559622cd900298a373bb68cfa6c8bc18735932bef13374374744b096f1ba31356f1c09a41c639a747129001980fb26eb961b80d609034ce2697a8b4c7581057bf84569d8ca49e37dda0c080c556219bbd2927513a7a12fd290db7b3930e7863a10137f7d651a8b0fade773996c163778e1a0610f346af66f329292ef78c66bc206d2b383edd5889cd3ffdc31e13b37f81ef87330e9c8f6bac867e4302a8745808fc134319b31599e9376ce0e2a782d64e285c6691486ceb0a56025b1a4162ee7df3d88e7601ff17fd171a0173d2eaac74965b84ffe7d89a5c9e709841da6b27e4aedf47eda9e470694aab69f3f4a7322625a9042e026cb2ae2c4061d69779cda51eeff713310a9c14b927dc74c6cf6f3a2de485bdcb69be3e587691a6bf1f2933d5c02c50d466b9321e4c7da49f0bd998c5a3a8befaaa02929ca041480154b8ebb25a4246d1ae3cd7c7e8c382af1455246f4c666b605cba7db76e547b897d202c3b98738d2995f7fd0ce2ff8e83302d32a6b3b463ed68ccd48624ee01e3c0d6c1640c3efe7ef0ae524241fb2a7df296f90d63a2f9d52948bea2d6bbd17d29e285a0018afb5aa98a83fdf1c8204a8f70b818daaa416d0db0e0ac357c631414586b7abd46f04298ef95e6d25bb97929231d801061fa9d11d3334e9c664120d6cce76dc5e059818da4b343565e9e4071ed4df9453a7d95cb8183c7c6b7d28a5f14328670b3c2c9a115263ebc7dffe035594be5e42fb184d05fd3709e8efe403e98c8e089fd105149b7262bc47f13e9bb6b4556db2587b7cb359106e9c2dfcb139bc16504998a64f9d0c463960222f3faada7110e8a1e057590aa1e8e4b018a6e646088b961bd947360368fa2f76d88017c0ca87a4926f2a88c2f98f26c09c2cccc451e3b1fdb09c10e91f6e1b4f49a7284ddd353a03a85492cf6d164f425f4024381f57983d10233cae0823b79d8d808388eeaa3f1d9eefd2dad9a7fef690b18419a505b494e65e949ff356a298e7211ce89df306a73116a99f28c7d046c083ef56ed3748ca781bbda4675a360d50a8c762a6fa5579635642a6e6b95dc868918d0a57980fe021084b7df37f4a6eaf78d8c8f69e6aafa58e0e0472a8f1ccf271c54f9d33e36bc2e315fc32f62c4804146bdf8119b006ff3f7a35b29091e6c60ef8ee8df243279277a33dfd5db91fcb4f582a347f471f0e7b4a623189515949d8166f87a0594e384b2feea11fbd55ae81409e67515333a431a098b1bf707316d91bf24585e2ba2391082d2bfe330fc97638b89803b2848f6598a8547749d23e6345d1d873b052d5fc02bef639df1ae8b062dbecf6ec2169b782f67ff8d0bc4072e3232f947e4a04b3937a7208649334b9ee6d7754d88db31d4a957b8c9982c50bc55fe4ed999b91bfe2354d2a7ad7ba0cc8d84903df903020eb1018b60715b6be7902828691fd4819205f052e47bd58478d81057aee7fd37b19a4efa1bd75f03a8dd59d9c81d9a9def013b5ee1392ceb51d07fb0d27adef823268101e29acbd23dedb804ecd9733aac8383eb149dca5b1e0c61ff13a50a7638a8e419ab4d77717009554174764922ccd50cefc5a2f01da8be96d4020e67bea4ed11bae9fbd7144556f957572ba245398b25d7e7383997b9e4a0f9f5a3815b4e211e50e961367e275f33d283c499719d364d814295b4520a64bacba85b4cedcddbf7f248119431076339beeaa03002e97751f3822df94cbc39819d568575c7ac14a783a3c8803c46cb8dc2269808b6b6c21139db93e37cca7de92d16cdea2bb06a6c2c12672e002162c926dceeb71b18f596e01a7781091cf256823dd2fe9c4f556c46114d74b4f89cc416f381d00e0a65a9d486478edc3b6d396a4166edf4c40ac0876a8525392f7f58d84731fa9f6f3182450720a9ea658350ec2b19687c86f9596b223bfd2b1d2c80f6104ce47731be624cced247c7452f9c25b8c8f90c6aed6f8e2d98a91587fad5c97cefa3c1b139bcbba4f60e22ec945f21545b37dd2fc3c0cf737f1eb10d8469ba9845daf49f07751b0978d6bd9543cc98dff52ed5a87535e04233d378a95edda2fc826a3080ba75da1b70167538ab747077a5e69b5564a56383f22288c847151b79c208a74e5a4d25ebc91615816fc60a5c8a65856be771dfa38ead3a6fb03a6bbaad68df77622ab30c59383bf1d12f00b7b6bac4d666b91695c66a146a43e40d15ebcb1a60e1e7b6e29c8b02e395fea18db801beec53b80e1298dda5f5f503cf753920d848797ee19be836819142a9b93a05400120cb31b833917dd05f7b2ff6acd7e79dbbdf79a7ee9fb02e0f7ad7d06d4796f82c1f697519d1a6c375267ff3d27e0ee7711ef0b2829ceb3c14380975ac7a59b02eb283f2ac09c695ca443077ab0d90c958074f6df6d211a779e50d8e186b8654ffb3d2e30f974c591f91476e56dbbb146766219c0991b08956f7287653e7158514f51132649228a1f30575f4e487d5f01aa1ec6c3986ca30fc831996b8c31f02ea16e5cc3be0814915f18d6643600dc0bf4794f866c0ca0a9ea02606866d8f5f913949bde564adfb15ad62abf3c1b118b117fee5f87d57e2f225b0ad83e2147e78678f72792ed28f251769fe71f608ff1168073b7d04c6856bd3f5eeebbe6bf7d2ad18ae924a94a2408b4b14d231d8e08dd0ba0730977105becc0b04673e4784fea0ff3f5006fce5596ce8c67a0910bb869064677bc2232ef3484e68ae9a224dfa98de8c1e70617b324e8c34cc6c6b4c5cee36f75aef550a27b710b5bfb2b772329805dfd63844ae0ade6474b37a75ed60fd8e9344ee38795290d3b971f1acfe339e4c79c6d8bc81b0b7428fdcd0c26cb4437c7a2ddb892fdf3afe4ae3f70ccf8a30cd5c2f3eff9a1c10a9e3e58cc0035b2abeb07149fe9e596a0920dfb98901c677046e9dbb1cc638ddc5fac8b52454d33f18bd3bd39bd45e0d51a2355a64a43507b9a9480c5b4944601eb1c90cfdc329eb93c5d7746c9de477d15592e5a76edd6a83294e2c112238f3a568435a01362b041b345c4de3d231f530585dfedb9bb0d0682185aeb0358325be15f24f8355326822d044966281b190f7f08ebdbe15a99b03b388dc42b4ba783912151432dfa34e3d76fc3658b66c4996cf60988040a551cc38b6f55ab1b43c1ea6f96290da4e1c20364bbbcd476f63e1bb5b06a25819b81a037b151ea624d477890b1075411f084f69a81602b03f322ae7bf6b1bbc043103cd9ab1d4a827245014fe1dac923382fbe185fb0a27c8463001dc33cd5eb653f6f97b3c5d69b959d92eb0a92ce09c7ae58b7812f01edf3102fd38ee65f3c8271253fee0b665cb7f2f86c7f20")
  205. print(res)