admin commited on
Commit
863d5cf
·
1 Parent(s): a82064e

merge report

Browse files
Files changed (6) hide show
  1. activate.py +157 -0
  2. app.py +13 -215
  3. config.py +19 -0
  4. report.py +54 -0
  5. smtp.py +42 -0
  6. times.py +21 -0
activate.py ADDED
@@ -0,0 +1,157 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import time
3
+ import requests
4
+ import threading
5
+ from tqdm import tqdm
6
+ from huggingface_hub import HfApi
7
+ from smtp import send_email
8
+ from config import *
9
+
10
+
11
+ def get_space_status(repo_id: str):
12
+ response: list = requests.get(
13
+ url=f"{HF_DOMAIN}/api/spaces/semantic-search",
14
+ params={"q": repo_id},
15
+ headers=HEADER,
16
+ timeout=TIMEOUT,
17
+ ).json()
18
+
19
+ if not (response and response[0]["id"] == repo_id):
20
+ return "ERROR"
21
+
22
+ return response[0]["runtime"]["stage"]
23
+
24
+
25
+ def get_spaces(username: str):
26
+ sleepings, errors = [], []
27
+ try:
28
+ spaces = HfApi().list_spaces(author=username)
29
+ for space in spaces:
30
+ status = get_space_status(space.id)
31
+ if status == "SLEEPING":
32
+ space_id = space.id.replace("/", "-").replace("_", "-").lower()
33
+ if space.sdk == "gradio":
34
+ sleepings.append(f"https://{space_id}.hf.space")
35
+ else:
36
+ sleepings.append(f"https://{space_id}.static.hf.space")
37
+
38
+ elif status == "ERROR":
39
+ errors.append(f"{HF_DOMAIN}/spaces/{space.id}")
40
+
41
+ return sleepings, errors
42
+
43
+ except Exception as e:
44
+ print(f"An error occurred in the request: {e}")
45
+
46
+ return [], []
47
+
48
+
49
+ def activate_space(url: str):
50
+ try:
51
+ response = requests.get(url, headers=HEADER, timeout=TIMEOUT)
52
+ response.raise_for_status()
53
+
54
+ except Exception as e:
55
+ print(e)
56
+
57
+
58
+ def get_studios(username: str):
59
+ try:
60
+ response = requests.put(
61
+ f"{MS_DOMAIN}/api/v1/studios/{username}/list",
62
+ data=json.dumps(
63
+ {
64
+ "PageNumber": 1,
65
+ "PageSize": 1000,
66
+ "Name": "",
67
+ "SortBy": "gmt_modified",
68
+ "Order": "desc",
69
+ }
70
+ ),
71
+ headers=HEADER,
72
+ timeout=TIMEOUT,
73
+ )
74
+ response.raise_for_status()
75
+ spaces: list = response.json()["Data"]["Studios"]
76
+ if spaces:
77
+ studios, errors = [], []
78
+ for space in spaces:
79
+ status = space["Status"]
80
+ if status == "Expired":
81
+ studios.append(f"{username}/{space['Name']}")
82
+ elif status == "Failed":
83
+ errors.append(f"{MS_DOMAIN}/studios/{username}/{space['Name']}")
84
+
85
+ return studios, errors
86
+
87
+ except requests.exceptions.Timeout as e:
88
+ print(f"Timeout: {e}, retrying...")
89
+ time.sleep(DELAY)
90
+ return get_studios(username)
91
+
92
+ except Exception as e:
93
+ print(f"Requesting error: {e}")
94
+
95
+ return [], []
96
+
97
+
98
+ def activate_studio(repo: str, holding_delay=5):
99
+ repo_page = f"{MS_DOMAIN}/studios/{repo}"
100
+ status_api = f"{MS_DOMAIN}/api/v1/studio/{repo}/status"
101
+ start_expired_api = f"{MS_DOMAIN}/api/v1/studio/{repo}/start_expired"
102
+ try:
103
+ response = requests.put(start_expired_api, headers=HEADER, timeout=TIMEOUT)
104
+ response.raise_for_status()
105
+ while (
106
+ requests.get(status_api, headers=HEADER, timeout=TIMEOUT).json()["Data"][
107
+ "Status"
108
+ ]
109
+ != "Running"
110
+ ):
111
+ requests.get(repo_page, headers=HEADER, timeout=TIMEOUT)
112
+ time.sleep(holding_delay)
113
+
114
+ except requests.exceptions.Timeout as e:
115
+ print(f"Failed to activate {repo}: {e}, retrying...")
116
+ activate_studio(repo)
117
+
118
+ except Exception as e:
119
+ print(e)
120
+
121
+
122
+ def activates(users=USERS):
123
+ spaces, studios, failures = [], [], []
124
+ usernames = users.split(";")
125
+ for user in tqdm(usernames, desc="Collecting spaces"):
126
+ username = user.strip()
127
+ if username:
128
+ sleeps, errors = get_spaces(username)
129
+ spaces += sleeps
130
+ failures += errors
131
+ time.sleep(DELAY)
132
+
133
+ for space in tqdm(spaces, desc="Activating spaces"):
134
+ activate_space(space)
135
+ time.sleep(DELAY)
136
+
137
+ for user in tqdm(usernames, desc="Collecting studios"):
138
+ username = user.strip()
139
+ if username:
140
+ sleeps, errors = get_studios(username)
141
+ studios += sleeps
142
+ failures += errors
143
+ time.sleep(DELAY)
144
+
145
+ for studio in tqdm(studios, desc="Activating studios"):
146
+ threading.Thread(target=activate_studio, args=(studio,), daemon=True).start()
147
+ time.sleep(DELAY)
148
+
149
+ print("\n".join(spaces + studios) + "\nActivation complete!")
150
+ content = ""
151
+ for failure in failures:
152
+ errepo: str = failure
153
+ errepo = errepo.replace(HF_DOMAIN, "").replace(MS_DOMAIN, "")
154
+ content += f"<br><a href='{failure}'>{errepo[1:]}</a><br>"
155
+
156
+ if content:
157
+ send_email(content)
app.py CHANGED
@@ -1,237 +1,35 @@
1
- import os
2
- import json
3
  import time
4
- import requests
5
  import schedule
6
  import threading
7
  import gradio as gr
8
- from tqdm import tqdm
9
- from datetime import datetime
10
- from zoneinfo import ZoneInfo
11
- from huggingface_hub import HfApi
12
- from tzlocal import get_localzone
13
 
14
- DELAY = 1
15
- TIMEOUT = 15
16
- HF_DOMAIN = "https://huggingface.co"
17
- MS_DOMAIN = "https://www.modelscope.cn"
18
- HEADER = {
19
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537"
20
- }
21
 
22
-
23
- def fix_datetime(naive_time: datetime, target_tz=ZoneInfo("Asia/Shanghai")):
24
- if not naive_time:
25
- return None
26
-
27
- local_tz = get_localzone()
28
- aware_local = naive_time.replace(tzinfo=local_tz)
29
- return aware_local.astimezone(target_tz).strftime("%Y-%m-%d %H:%M:%S")
30
-
31
-
32
- def get_space_status(repo_id: str):
33
- response: list = requests.get(
34
- url=f"{HF_DOMAIN}/api/spaces/semantic-search",
35
- params={"q": repo_id},
36
- headers=HEADER,
37
- timeout=TIMEOUT,
38
- ).json()
39
-
40
- if not (response and response[0]["id"] == repo_id):
41
- return "ERROR"
42
-
43
- return response[0]["runtime"]["stage"]
44
-
45
-
46
- def get_spaces(username: str):
47
- sleepings, errors = [], []
48
- try:
49
- spaces = HfApi().list_spaces(author=username)
50
- for space in spaces:
51
- status = get_space_status(space.id)
52
- if status == "SLEEPING":
53
- space_id = space.id.replace("/", "-").replace("_", "-").lower()
54
- if space.sdk == "gradio":
55
- sleepings.append(f"https://{space_id}.hf.space")
56
- else:
57
- sleepings.append(f"https://{space_id}.static.hf.space")
58
-
59
- elif status == "ERROR":
60
- errors.append(f"{HF_DOMAIN}/spaces/{space.id}")
61
-
62
- return sleepings, errors
63
-
64
- except Exception as e:
65
- print(f"An error occurred in the request: {e}")
66
-
67
- return [], []
68
-
69
-
70
- def activate_space(url: str):
71
- try:
72
- response = requests.get(url, headers=HEADER, timeout=TIMEOUT)
73
- response.raise_for_status()
74
-
75
- except Exception as e:
76
- print(e)
77
-
78
-
79
- def get_studios(username: str):
80
- try:
81
- response = requests.put(
82
- f"{MS_DOMAIN}/api/v1/studios/{username}/list",
83
- data=json.dumps(
84
- {
85
- "PageNumber": 1,
86
- "PageSize": 1000,
87
- "Name": "",
88
- "SortBy": "gmt_modified",
89
- "Order": "desc",
90
- }
91
- ),
92
- headers=HEADER,
93
- timeout=TIMEOUT,
94
- )
95
- response.raise_for_status()
96
- spaces: list = response.json()["Data"]["Studios"]
97
- if spaces:
98
- studios, errors = [], []
99
- for space in spaces:
100
- status = space["Status"]
101
- if status == "Expired":
102
- studios.append(f"{username}/{space['Name']}")
103
- elif status == "Failed":
104
- errors.append(f"{MS_DOMAIN}/studios/{username}/{space['Name']}")
105
-
106
- return studios, errors
107
-
108
- except requests.exceptions.Timeout as e:
109
- print(f"Timeout: {e}, retrying...")
110
- time.sleep(DELAY)
111
- return get_studios(username)
112
-
113
- except Exception as e:
114
- print(f"Requesting error: {e}")
115
-
116
- return [], []
117
-
118
-
119
- def activate_studio(repo: str, holding_delay=5):
120
- repo_page = f"{MS_DOMAIN}/studios/{repo}"
121
- status_api = f"{MS_DOMAIN}/api/v1/studio/{repo}/status"
122
- start_expired_api = f"{MS_DOMAIN}/api/v1/studio/{repo}/start_expired"
123
- try:
124
- response = requests.put(start_expired_api, headers=HEADER, timeout=TIMEOUT)
125
- response.raise_for_status()
126
- while (
127
- requests.get(status_api, headers=HEADER, timeout=TIMEOUT).json()["Data"][
128
- "Status"
129
- ]
130
- != "Running"
131
- ):
132
- requests.get(repo_page, headers=HEADER, timeout=TIMEOUT)
133
- time.sleep(holding_delay)
134
-
135
- except requests.exceptions.Timeout as e:
136
- print(f"Failed to activate {repo}: {e}, retrying...")
137
- activate_studio(repo)
138
-
139
- except Exception as e:
140
- print(e)
141
-
142
-
143
- def send_email(
144
- content,
145
- title="Runtime error detected",
146
- header="Please fix following repo(s):",
147
- email=os.getenv("email"),
148
- password=os.getenv("smtp"),
149
- target=os.getenv("target"),
150
- ):
151
- body = f"""
152
- <html>
153
- <body>
154
- <h2>{header}</h2>
155
- {content}
156
- </body>
157
- </html>
158
- """
159
- response = requests.get(
160
- "http://api.mmp.cc/api/mail",
161
- params={
162
- "host": "smtp.163.com",
163
- "Port": 25,
164
- "key": password, # apikey
165
- "email": email, # from
166
- "mail": target, # to
167
- "title": title, # subject
168
- "name": "ksa", # nickname
169
- "text": body, # content
170
- },
171
- )
172
- if response.status_code == 200:
173
- result: dict = response.json()
174
- if result.get("status") == "success":
175
- print("Email sent successfully!")
176
- else:
177
- print(f"Failed to send email: {result.get('message')}")
178
-
179
- else:
180
- print(f"Request failed with status code: {response.status_code}")
181
-
182
-
183
- def activate(users=os.getenv("users")):
184
- spaces, studios, failures = [], [], []
185
- usernames = users.split(";")
186
- for user in tqdm(usernames, desc="Collecting spaces"):
187
- username = user.strip()
188
- if username:
189
- sleeps, errors = get_spaces(username)
190
- spaces += sleeps
191
- failures += errors
192
- time.sleep(DELAY)
193
-
194
- for space in tqdm(spaces, desc="Activating spaces"):
195
- activate_space(space)
196
- time.sleep(DELAY)
197
-
198
- for user in tqdm(usernames, desc="Collecting studios"):
199
- username = user.strip()
200
- if username:
201
- sleeps, errors = get_studios(username)
202
- studios += sleeps
203
- failures += errors
204
- time.sleep(DELAY)
205
-
206
- for studio in tqdm(studios, desc="Activating studios"):
207
- threading.Thread(target=activate_studio, args=(studio,), daemon=True).start()
208
- time.sleep(DELAY)
209
-
210
- print("\n".join(spaces + studios) + "\nActivation complete!")
211
- content = ""
212
- for failure in failures:
213
- errepo: str = failure
214
- errepo = errepo.replace(HF_DOMAIN, "").replace(MS_DOMAIN, "")
215
- content += f"<br><a href='{failure}'>{errepo[1:]}</a><br>"
216
-
217
- if content:
218
- send_email(content)
219
 
220
 
221
  def run_schedule():
 
 
 
222
  while True:
223
  schedule.run_pending()
224
  time.sleep(DELAY)
225
 
226
 
227
- def monitor(period=os.getenv("period")):
228
- activate()
229
  print(f"Monitor is on and triggered every {period}h...")
230
- schedule.every(int(period)).hours.do(activate)
231
  threading.Thread(target=run_schedule, daemon=True).start()
232
 
233
 
234
  def tasklist():
 
235
  jobs = schedule.get_jobs()
236
  for job in jobs:
237
  last_run = fix_datetime(job.last_run)
 
 
 
1
  import time
 
2
  import schedule
3
  import threading
4
  import gradio as gr
5
+ from activate import activates
6
+ from report import batch_report
7
+ from config import *
8
+ from times import *
 
9
 
 
 
 
 
 
 
 
10
 
11
+ def trigger():
12
+ activates()
13
+ batch_report()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
 
15
 
16
  def run_schedule():
17
+ global START_TIME
18
+ START_TIME = datetime.now()
19
+ trigger()
20
  while True:
21
  schedule.run_pending()
22
  time.sleep(DELAY)
23
 
24
 
25
+ def monitor(period=PERIOD):
 
26
  print(f"Monitor is on and triggered every {period}h...")
27
+ schedule.every(int(period)).hours.do(trigger)
28
  threading.Thread(target=run_schedule, daemon=True).start()
29
 
30
 
31
  def tasklist():
32
+ print(f"Has been running for {calc_time_diff(START_TIME, datetime.now())}")
33
  jobs = schedule.get_jobs()
34
  for job in jobs:
35
  last_run = fix_datetime(job.last_run)
config.py ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ DELAY = 1
4
+ TIMEOUT = 15
5
+ START_TIME = None
6
+ HF_DOMAIN = "https://huggingface.co"
7
+ MS_DOMAIN = "https://www.modelscope.cn"
8
+ HEADER = {
9
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537"
10
+ }
11
+
12
+ REPORT_DELAY = int(os.getenv("delay")) # < 3600 * period / len(traitors)
13
+ TRAITORS = os.getenv("traitors")
14
+ COOKIE = os.getenv("cookie")
15
+ PERIOD = os.getenv("period")
16
+ EMAIL = os.getenv("email")
17
+ SMTP = os.getenv("smtp")
18
+ TAG = os.getenv("target")
19
+ USERS = os.getenv("users")
report.py ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import time
2
+ import json
3
+ import random
4
+ import requests
5
+ from tqdm import tqdm
6
+ from smtp import send_email
7
+ from config import *
8
+
9
+
10
+ def txt2list(url=TRAITORS):
11
+ try: # 发送 GET 请求获取文件内容
12
+ response = requests.get(url)
13
+ response.raise_for_status() # 检查请求是否成功
14
+ return response.text.splitlines()
15
+
16
+ except Exception as e:
17
+ send_email(f"Failed to request traitors: {e}")
18
+ return []
19
+
20
+
21
+ def send_report_request(mid, ck=COOKIE, reason="1,2,3", reason_v2="4", retry=False):
22
+ try:
23
+ bili_jct = ck.split("bili_jct=")[1].split(";")[0]
24
+ response = requests.post(
25
+ "https://space.bilibili.com/ajax/report/add",
26
+ data={
27
+ "mid": mid,
28
+ "reason": reason,
29
+ "reason_v2": reason_v2,
30
+ "csrf": bili_jct,
31
+ },
32
+ headers={
33
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0",
34
+ "Cookie": ck,
35
+ },
36
+ )
37
+ msg = json.loads(response.text)["data"]
38
+ if msg == "举报成功":
39
+ print(f"{msg}: {mid}")
40
+ else:
41
+ send_email(f"Failed to report {mid}: {msg}")
42
+
43
+ except Exception as e:
44
+ print(f"举报 {mid} 失败:{e}")
45
+ if not retry:
46
+ time.sleep(random.uniform(REPORT_DELAY - 2, REPORT_DELAY + 2))
47
+ send_report_request(mid, retry=True)
48
+
49
+
50
+ def batch_report():
51
+ targets = txt2list()
52
+ for mid in tqdm(targets, desc="Reporting UIDs..."):
53
+ send_report_request(mid.strip())
54
+ time.sleep(random.uniform(REPORT_DELAY - 2, REPORT_DELAY + 2))
smtp.py ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import requests
2
+ from config import *
3
+
4
+
5
+ def send_email(
6
+ content,
7
+ title="Runtime error detected",
8
+ header="Please fix following repo(s):",
9
+ email=EMAIL,
10
+ password=SMTP,
11
+ target=TAG,
12
+ ):
13
+ body = f"""
14
+ <html>
15
+ <body>
16
+ <h2>{header}</h2>
17
+ {content}
18
+ </body>
19
+ </html>
20
+ """
21
+ response = requests.get(
22
+ "http://api.mmp.cc/api/mail",
23
+ params={
24
+ "host": "smtp.163.com",
25
+ "Port": 25,
26
+ "key": password, # apikey
27
+ "email": email, # from
28
+ "mail": target, # to
29
+ "title": title, # subject
30
+ "name": "ksa", # nickname
31
+ "text": body, # content
32
+ },
33
+ )
34
+ if response.status_code == 200:
35
+ result: dict = response.json()
36
+ if result.get("status") == "success":
37
+ print("Email sent successfully!")
38
+ else:
39
+ print(f"Failed to send email: {result.get('message')}")
40
+
41
+ else:
42
+ print(f"Request failed with status code: {response.status_code}")
times.py ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from datetime import datetime
2
+ from zoneinfo import ZoneInfo
3
+ from tzlocal import get_localzone
4
+
5
+
6
+ def fix_datetime(naive_time: datetime, target_tz=ZoneInfo("Asia/Shanghai")):
7
+ if not naive_time:
8
+ return None
9
+
10
+ local_tz = get_localzone()
11
+ aware_local = naive_time.replace(tzinfo=local_tz)
12
+ return aware_local.astimezone(target_tz).strftime("%Y-%m-%d %H:%M:%S")
13
+
14
+
15
+ def calc_time_diff(time1: datetime, time2: datetime):
16
+ time_diff = time2 - time1
17
+ days = time_diff.days
18
+ hours = time_diff.seconds // 3600
19
+ minutes = (time_diff.seconds % 3600) // 60
20
+ seconds = time_diff.seconds % 60
21
+ return f"{days} d {hours} h {minutes} m {seconds} s"