jwf-common-python 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. jwf_common_python/__init__.py +14 -0
  2. jwf_common_python/db_utils/__init__.py +6 -0
  3. jwf_common_python/db_utils/clickhouse.py +124 -0
  4. jwf_common_python/db_utils/elasticsearch.py +196 -0
  5. jwf_common_python/db_utils/mysql.py +64 -0
  6. jwf_common_python/eudic/__init__.py +5 -0
  7. jwf_common_python/eudic/wordbook.py +211 -0
  8. jwf_common_python/file_storage/__init__.py +2 -0
  9. jwf_common_python/file_storage/file_interface.py +29 -0
  10. jwf_common_python/file_storage/local.py +50 -0
  11. jwf_common_python/file_storage/tencent_cos.py +65 -0
  12. jwf_common_python/geography/__init__.py +8 -0
  13. jwf_common_python/geography/district_amap.py +181 -0
  14. jwf_common_python/geography/search_amap.py +84 -0
  15. jwf_common_python/github/__init__.py +5 -0
  16. jwf_common_python/github/webhooks.py +87 -0
  17. jwf_common_python/language_utils/__init__.py +34 -0
  18. jwf_common_python/language_utils/core.py +203 -0
  19. jwf_common_python/language_utils/files.py +52 -0
  20. jwf_common_python/language_utils/web.py +117 -0
  21. jwf_common_python/llm/__init__.py +1 -0
  22. jwf_common_python/llm/aliyun_qwen.py +10 -0
  23. jwf_common_python/llm/azure_gpt.py +66 -0
  24. jwf_common_python/llm/baidu_ernie.py +112 -0
  25. jwf_common_python/message_queue/__init__.py +7 -0
  26. jwf_common_python/message_queue/interface.py +49 -0
  27. jwf_common_python/message_queue/kafka.py +145 -0
  28. jwf_common_python/message_queue/rabbitmq.py +113 -0
  29. jwf_common_python/oauth2/__init__.py +0 -0
  30. jwf_common_python/oauth2/google.py +158 -0
  31. jwf_common_python/parse_subtitle/__init__.py +6 -0
  32. jwf_common_python/parse_subtitle/aa.vtt +2364 -0
  33. jwf_common_python/parse_subtitle/parse_srt_file.py +60 -0
  34. jwf_common_python/pdf/__init__.py +0 -0
  35. jwf_common_python/pdf/aaa.py +38 -0
  36. jwf_common_python/pdf/local_parse.py +259 -0
  37. jwf_common_python/sms/__init__.py +1 -0
  38. jwf_common_python/sms/interface.py +7 -0
  39. jwf_common_python/sms/tencent_sms.py +117 -0
  40. jwf_common_python/translate/__init__.py +152 -0
  41. jwf_common_python/translate/_youdao.py +234 -0
  42. jwf_common_python/translate/microsoft.py +696 -0
  43. jwf_common_python/translate/tencent.py +194 -0
  44. jwf_common_python/tts/__init__.py +0 -0
  45. jwf_common_python/tts/microsoft.py +87 -0
  46. jwf_common_python/utils/__init__.py +0 -0
  47. jwf_common_python/utils/image_utils.py +18 -0
  48. jwf_common_python/utils/tencent_utils.py +51 -0
  49. jwf_common_python/utils/utils.py +46 -0
  50. jwf_common_python/video/__init__.py +5 -0
  51. jwf_common_python/video/merge.py +276 -0
  52. jwf_common_python/weather/__init__.py +0 -0
  53. jwf_common_python/weather/amap.py +127 -0
  54. jwf_common_python/weather/wanwei.py +58 -0
  55. jwf_common_python/youdao/__init__.py +13 -0
  56. jwf_common_python/youdao/wordbook.py +88 -0
  57. jwf_common_python-1.0.0.dist-info/METADATA +669 -0
  58. jwf_common_python-1.0.0.dist-info/RECORD +60 -0
  59. jwf_common_python-1.0.0.dist-info/WHEEL +4 -0
  60. jwf_common_python-1.0.0.dist-info/licenses/LICENSE +201 -0
@@ -0,0 +1,234 @@
1
+ import hashlib
2
+ import logging
3
+ import random
4
+ import time
5
+ import uuid
6
+ from typing import Literal, get_args
7
+
8
+ try:
9
+ import requests
10
+ except ImportError:
11
+ raise ImportError("Couldn't import requests. pip install --upgrade requests")
12
+ from requests.models import Response
13
+
14
+ from jwf_common_python.translate import SentenceInfo, Translate, WordInfo
15
+
16
+ LanguageCodeOfYoudao = Literal["zh-CHS", "zh-CHT", "en", "fr", "ja", "de", "es", "ko"]
17
+ LanguageCodeOfBackend = Literal["zh-CN", "zh-TW", "en", "fr", "ja", "de", "es", "ko"]
18
+
19
+
20
+ class YoudaoTranslate(Translate):
21
+ def __init__(self, **kwargs) -> None:
22
+ if not {"YOUDAO_URL", "APP_KEY", "APP_SECRET"}.issubset(kwargs.keys()):
23
+ raise Exception("you need to set YOUDAO_URL,APP_KEY,APP_SECRET")
24
+ self.YOUDAO_URL = kwargs["YOUDAO_URL"]
25
+ self.APP_KEY = kwargs["APP_KEY"]
26
+ self.APP_SECRET = kwargs["APP_SECRET"]
27
+ self._language_code_of_youdao = list(get_args(LanguageCodeOfYoudao))
28
+
29
+ def _encrypt(self, salt, current_time, word):
30
+ signStr = (
31
+ self.APP_KEY + self._truncate(word) + salt + current_time + self.APP_SECRET
32
+ )
33
+ hash_algorithm = hashlib.sha256()
34
+ hash_algorithm.update(signStr.encode("utf-8"))
35
+ return hash_algorithm.hexdigest()
36
+
37
+ def _truncate(self, q):
38
+ if q is None:
39
+ return None
40
+ size = len(q)
41
+ return q if size <= 20 else q[0:10] + str(size) + q[size - 10 : size]
42
+
43
+ def change_language_code(
44
+ self, language_code_of_backend: LanguageCodeOfBackend
45
+ ) -> str:
46
+ """转换语言代码,将language_backend后端的语言代码转换为youdao的语言代码"""
47
+
48
+ match language_code_of_backend:
49
+ case "zh-CN":
50
+ return "zh-CHS"
51
+ case "zh-TW":
52
+ return "zh-CHT"
53
+ case _:
54
+ return language_code_of_backend
55
+
56
+ def _send_request(
57
+ self,
58
+ word: str,
59
+ source_language_code: LanguageCodeOfBackend,
60
+ target_language_code: LanguageCodeOfBackend,
61
+ ) -> dict:
62
+ """_summary_
63
+
64
+ Args:
65
+ word (str): _description_
66
+ source_language_code (str): 待翻译文本的语言代码
67
+ target_language_code (str): 目标语言代码
68
+
69
+ Raises:
70
+ ValueError: _description_
71
+ ValueError: _description_
72
+
73
+ Returns:
74
+ dict: _description_
75
+ """
76
+ current_time = str(int(time.time()))
77
+ salt = str(uuid.uuid1())
78
+ sign = self._encrypt(salt=salt, current_time=current_time, word=word)
79
+
80
+ # 解决不同提供商对简体中文的表示问题
81
+ source_language_code = self.change_language_code(source_language_code)
82
+ target_language_code = self.change_language_code(target_language_code)
83
+ assert (
84
+ source_language_code in self._language_code_of_youdao
85
+ ), f"youdao不支持 {source_language_code} 语言code"
86
+ assert (
87
+ target_language_code in self._language_code_of_youdao
88
+ ), f"youdao不支持 {target_language_code} 语言code"
89
+
90
+ data = {
91
+ "from": source_language_code,
92
+ "to": target_language_code,
93
+ "signType": "v3",
94
+ "curtime": current_time,
95
+ "sign": sign,
96
+ "appKey": self.APP_KEY,
97
+ "salt": salt,
98
+ "q": word,
99
+ # 'vocabId':"您的用户词表ID"
100
+ }
101
+
102
+ try:
103
+ response: Response = requests.post(
104
+ self.YOUDAO_URL,
105
+ data=data,
106
+ headers={"Content-Type": "application/x-www-form-urlencoded"},
107
+ )
108
+ except Exception as e:
109
+ raise ValueError(f"youdao translate connect error: {e}")
110
+ if response.status_code != 200:
111
+ raise ValueError(f"youdao translate status error: {response.status_code}")
112
+ return response.json()
113
+
114
+ def translate(
115
+ self,
116
+ word: str,
117
+ source_language_code: LanguageCodeOfBackend,
118
+ target_language_code: LanguageCodeOfBackend,
119
+ ) -> dict:
120
+ response: dict = self._send_request(
121
+ word=word,
122
+ source_language_code=source_language_code,
123
+ target_language_code=target_language_code,
124
+ )
125
+ # 频率过快时,自动重试
126
+ num = 1
127
+ while response["errorCode"] in ["411", "412", "2411", "3411", "4411", "11411"]:
128
+ sleep_time: float = round(random.uniform(1, 5), 2)
129
+ logging.warning(f"youdao请求速度过快,{sleep_time}秒后自动重试,进行第{num}次重试")
130
+ time.sleep(sleep_time)
131
+ response = self._send_request(
132
+ word=word,
133
+ source_language_code=source_language_code,
134
+ target_language_code=target_language_code,
135
+ )
136
+ num += 1
137
+
138
+ error_code: str = response["errorCode"]
139
+ if error_code != "0":
140
+ raise ValueError(f"youdao translate error: {word} {error_code=}")
141
+ return response
142
+
143
+ @classmethod
144
+ def format_word_response(cls, response: dict) -> WordInfo:
145
+ # only word
146
+ basic_direction: dict | None = response.get("basic")
147
+
148
+ word: str = response["query"]
149
+
150
+ translation_no_class: list[str] = response["translation"]
151
+
152
+ translation_have_class: list[str] | None = (
153
+ basic_direction.get("explains", []) if basic_direction else []
154
+ )
155
+ translation = {
156
+ "no_class": translation_no_class,
157
+ "have_class": translation_have_class,
158
+ }
159
+
160
+ translation_speak_url: str = response["tSpeakUrl"]
161
+ source_speak_url: str = response["speakUrl"]
162
+ source_speech_uk: str | None = (
163
+ basic_direction.get("uk-speech") if basic_direction else None
164
+ )
165
+ source_speech_us: str | None = (
166
+ basic_direction.get("us-speech") if basic_direction else None
167
+ )
168
+ speakUrl = {
169
+ "translation_speak_url": translation_speak_url,
170
+ "source_speak_url": source_speak_url,
171
+ "source_speech_uk": source_speech_uk,
172
+ "source_speech_us": source_speech_us,
173
+ }
174
+
175
+ phonetic_us: str | None = (
176
+ basic_direction.get("us-phonetic") if basic_direction else None
177
+ )
178
+ phonetic: str | None = (
179
+ basic_direction.get("phonetic") if basic_direction else None
180
+ )
181
+ phonetic_uk: str | None = (
182
+ basic_direction.get("uk-phonetic") if basic_direction else None
183
+ )
184
+ phonetic = {"us": phonetic_us, "uk": phonetic_uk, "default": phonetic}
185
+
186
+ word_type: list[str] | None = (
187
+ basic_direction.get("exam_type") if basic_direction else None
188
+ )
189
+
190
+ grammar_info: list[dict] | None = (
191
+ basic_direction.get("wfs") if basic_direction else None
192
+ )
193
+
194
+ extended_info: list[dict[str, list[str]]] | None = response.get("web")
195
+
196
+ format_response: WordInfo = {
197
+ "word": word,
198
+ "translation": translation,
199
+ "speak_url": speakUrl,
200
+ "phonetic": phonetic,
201
+ "word_type": word_type,
202
+ "grammar_info": grammar_info,
203
+ "extended_info": extended_info,
204
+ }
205
+ # import json
206
+ # print(json.dumps(res,indent=2,ensure_ascii=False))
207
+ return format_response
208
+
209
+ @classmethod
210
+ def format_sentence_response(cls, response: dict) -> SentenceInfo:
211
+ sentence: str = response["query"]
212
+ translation: list[str] = response["translation"]
213
+
214
+ source_speak_url: str = response["speakUrl"]
215
+ translation_speak_url: str = response["tSpeakUrl"]
216
+
217
+ response = {
218
+ "sentence": sentence,
219
+ "translation": translation,
220
+ "source_speak_url": source_speak_url,
221
+ "translation_speak_url": translation_speak_url,
222
+ }
223
+
224
+ return response
225
+
226
+ @classmethod
227
+ def download_audio_file(self, url: str) -> bytes:
228
+ try:
229
+ response = requests.get(url=url)
230
+ except Exception as e:
231
+ raise ValueError(f"youdao translate download audio file error: {e}")
232
+ if response.status_code != 200:
233
+ raise ValueError("download audio file,status code error")
234
+ return response.content