serve_client.py 10 KB

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