ka1kuk commited on
Commit
a1ba342
1 Parent(s): 6774313

Rename BingImageCreator.py to ImageCreator.py

Browse files
Files changed (2) hide show
  1. BingImageCreator.py +0 -403
  2. ImageCreator.py +43 -0
BingImageCreator.py DELETED
@@ -1,403 +0,0 @@
1
- import argparse
2
- import asyncio
3
- from functools import partial
4
- import contextlib
5
- import json
6
- import os
7
- import random
8
- import sys
9
- import time
10
- import aiohttp
11
- import pkg_resources
12
- import regex
13
- import requests
14
- from typing import Union
15
-
16
- if os.environ.get("BING_URL") == None:
17
- BING_URL = "https://www.bing.com"
18
- else:
19
- BING_URL = os.environ.get("BING_URL")
20
- # Generate random IP between range 13.104.0.0/14
21
- FORWARDED_IP = (
22
- f"13.{random.randint(104, 107)}.{random.randint(0, 255)}.{random.randint(0, 255)}"
23
- )
24
- HEADERS = {
25
- "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
26
- "accept-language": "en-US,en;q=0.9",
27
- "cache-control": "max-age=0",
28
- "content-type": "application/x-www-form-urlencoded",
29
- "referrer": "https://www.bing.com/images/create/",
30
- "origin": "https://www.bing.com",
31
- "user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36 Edg/110.0.1587.63",
32
- "x-forwarded-for": FORWARDED_IP,
33
- }
34
-
35
- # Error messages
36
- error_timeout = "Your request has timed out."
37
- error_redirect = "Redirect failed"
38
- error_blocked_prompt = (
39
- "Your prompt has been blocked by Bing. Try to change any bad words and try again."
40
- )
41
- error_noresults = "Could not get results"
42
- error_unsupported_lang = "\nthis language is currently not supported by bing"
43
- error_bad_images = "Bad images"
44
- error_no_images = "No images"
45
- #
46
- sending_message = "Sending request..."
47
- wait_message = "Waiting for results..."
48
- download_message = "\nDownloading images..."
49
-
50
-
51
- def debug(debug_file, text_var):
52
- """helper function for debug"""
53
- with open(f"{debug_file}", "a", encoding="utf-8") as f:
54
- f.write(str(text_var))
55
-
56
-
57
- class ImageGen:
58
- """
59
- Image generation by Microsoft Bing
60
- Parameters:3
61
- auth_cookie: str
62
- """
63
-
64
- def __init__(
65
- self,
66
- auth_cookie: '15iNP0L_xa8fjGOOmF9For9sfHo3dWNKCMe_7LCA8XRNqtkFx0CtlH8mSTLDTaCL7GXTYF2z_TIIJKb9C2EZa6isVYJjEK39LbaRLpMCKzb5E6zO5cNilSmlqKco6e6Hn8WIUP22j_GLYVgM1awGOejEL8lcgkN0InQjpX-STlGED3PVabcfeDgDxknaiae2L29sGJ6Mt7gZnfNfgWYuO7XFXep9HAwAzSx5cprtFbwA',
67
- debug_file: Union[str, None] = None,
68
- quiet: bool = False,
69
- all_cookies: list[dict] = None,
70
- ) -> None:
71
- self.session: requests.Session = requests.Session()
72
- self.session.headers = HEADERS
73
- self.session.cookies.set("_U", auth_cookie)
74
- if all_cookies:
75
- for cookie in all_cookies:
76
- self.session.cookies.set(cookie["name"], cookie["value"])
77
- self.quiet = quiet
78
- self.debug_file = debug_file
79
- if self.debug_file:
80
- self.debug = partial(debug, self.debug_file)
81
-
82
- def get_images(self, prompt: str) -> list:
83
- """
84
- Fetches image links from Bing
85
- Parameters:
86
- prompt: str
87
- """
88
- if not self.quiet:
89
- print(sending_message)
90
- if self.debug_file:
91
- self.debug(sending_message)
92
- url_encoded_prompt = requests.utils.quote(prompt)
93
- payload = f"q={url_encoded_prompt}&qs=ds"
94
- # https://www.bing.com/images/create?q=<PROMPT>&rt=3&FORM=GENCRE
95
- url = f"{BING_URL}/images/create?q={url_encoded_prompt}&rt=4&FORM=GENCRE"
96
- response = self.session.post(
97
- url, allow_redirects=False, data=payload, timeout=200
98
- )
99
- # check for content waring message
100
- if "this prompt has been blocked" in response.text.lower():
101
- if self.debug_file:
102
- self.debug(f"ERROR: {error_blocked_prompt}")
103
- raise Exception(
104
- error_blocked_prompt,
105
- )
106
- if (
107
- "we're working hard to offer image creator in more languages"
108
- in response.text.lower()
109
- ):
110
- if self.debug_file:
111
- self.debug(f"ERROR: {error_unsupported_lang}")
112
- raise Exception(error_unsupported_lang)
113
- if response.status_code != 302:
114
- # if rt4 fails, try rt3
115
- url = f"{BING_URL}/images/create?q={url_encoded_prompt}&rt=3&FORM=GENCRE"
116
- response3 = self.session.post(url, allow_redirects=False, timeout=200)
117
- if response3.status_code != 302:
118
- if self.debug_file:
119
- self.debug(f"ERROR: {error_redirect}")
120
- print(f"ERROR: {response3.text}")
121
- raise Exception(error_redirect)
122
- response = response3
123
- # Get redirect URL
124
- redirect_url = response.headers["Location"].replace("&nfy=1", "")
125
- request_id = redirect_url.split("id=")[-1]
126
- self.session.get(f"{BING_URL}{redirect_url}")
127
- # https://www.bing.com/images/create/async/results/{ID}?q={PROMPT}
128
- polling_url = f"{BING_URL}/images/create/async/results/{request_id}?q={url_encoded_prompt}"
129
- # Poll for results
130
- if self.debug_file:
131
- self.debug("Polling and waiting for result")
132
- if not self.quiet:
133
- print("Waiting for results...")
134
- start_wait = time.time()
135
- while True:
136
- if int(time.time() - start_wait) > 200:
137
- if self.debug_file:
138
- self.debug(f"ERROR: {error_timeout}")
139
- raise Exception(error_timeout)
140
- if not self.quiet:
141
- print(".", end="", flush=True)
142
- response = self.session.get(polling_url)
143
- if response.status_code != 200:
144
- if self.debug_file:
145
- self.debug(f"ERROR: {error_noresults}")
146
- raise Exception(error_noresults)
147
- if not response.text or response.text.find("errorMessage") != -1:
148
- time.sleep(1)
149
- continue
150
- else:
151
- break
152
- # Use regex to search for src=""
153
- image_links = regex.findall(r'src="([^"]+)"', response.text)
154
- # Remove size limit
155
- normal_image_links = [link.split("?w=")[0] for link in image_links]
156
- # Remove duplicates
157
- normal_image_links = list(set(normal_image_links))
158
-
159
- # Bad images
160
- bad_images = [
161
- "https://r.bing.com/rp/in-2zU3AJUdkgFe7ZKv19yPBHVs.png",
162
- "https://r.bing.com/rp/TX9QuO3WzcCJz1uaaSwQAz39Kb0.jpg",
163
- ]
164
- for img in normal_image_links:
165
- if img in bad_images:
166
- raise Exception("Bad images")
167
- # No images
168
- if not normal_image_links:
169
- raise Exception(error_no_images)
170
- return normal_image_links
171
-
172
- def save_images(self, links: list, output_dir: str, file_name: str = None) -> None:
173
- """
174
- Saves images to output directory
175
- """
176
- if self.debug_file:
177
- self.debug(download_message)
178
- if not self.quiet:
179
- print(download_message)
180
- with contextlib.suppress(FileExistsError):
181
- os.mkdir(output_dir)
182
- try:
183
- fn = f"{file_name}_" if file_name else ""
184
- jpeg_index = 0
185
- for link in links:
186
- while os.path.exists(
187
- os.path.join(output_dir, f"{fn}{jpeg_index}.jpeg")
188
- ):
189
- jpeg_index += 1
190
- with self.session.get(link, stream=True) as response:
191
- # save response to file
192
- response.raise_for_status()
193
- with open(
194
- os.path.join(output_dir, f"{fn}{jpeg_index}.jpeg"), "wb"
195
- ) as output_file:
196
- for chunk in response.iter_content(chunk_size=8192):
197
- output_file.write(chunk)
198
- except requests.exceptions.MissingSchema as url_exception:
199
- raise Exception(
200
- "Inappropriate contents found in the generated images. Please try again or try another prompt.",
201
- ) from url_exception
202
-
203
-
204
- class ImageGenAsync:
205
- """
206
- Image generation by Microsoft Bing
207
- Parameters:
208
- auth_cookie: str
209
- """
210
-
211
- def __init__(self, auth_cookie: str, quiet: bool = False) -> None:
212
- self.session = aiohttp.ClientSession(
213
- headers=HEADERS,
214
- cookies={"_U": auth_cookie},
215
- trust_env=True,
216
- )
217
- self.quiet = quiet
218
-
219
- async def __aenter__(self):
220
- return self
221
-
222
- async def __aexit__(self, *excinfo) -> None:
223
- await self.session.close()
224
-
225
- async def get_images(self, prompt: str) -> list:
226
- """
227
- Fetches image links from Bing
228
- Parameters:
229
- prompt: str
230
- """
231
- if not self.quiet:
232
- print("Sending request...")
233
- url_encoded_prompt = requests.utils.quote(prompt)
234
- # https://www.bing.com/images/create?q=<PROMPT>&rt=3&FORM=GENCRE
235
- url = f"{BING_URL}/images/create?q={url_encoded_prompt}&rt=4&FORM=GENCRE"
236
- payload = f"q={url_encoded_prompt}&qs=ds"
237
- async with self.session.post(
238
- url, allow_redirects=False, data=payload
239
- ) as response:
240
- content = await response.text()
241
- if "this prompt has been blocked" in content.lower():
242
- raise Exception(
243
- "Your prompt has been blocked by Bing. Try to change any bad words and try again.",
244
- )
245
- if response.status != 302:
246
- # if rt4 fails, try rt3
247
- url = (
248
- f"{BING_URL}/images/create?q={url_encoded_prompt}&rt=3&FORM=GENCRE"
249
- )
250
- async with self.session.post(
251
- url,
252
- allow_redirects=False,
253
- timeout=200,
254
- ) as response3:
255
- if response3.status != 302:
256
- print(f"ERROR: {await response3.text()}")
257
- raise Exception("Redirect failed")
258
- response = response3
259
- # Get redirect URL
260
- redirect_url = response.headers["Location"].replace("&nfy=1", "")
261
- request_id = redirect_url.split("id=")[-1]
262
- await self.session.get(f"{BING_URL}{redirect_url}")
263
- # https://www.bing.com/images/create/async/results/{ID}?q={PROMPT}
264
- polling_url = f"{BING_URL}/images/create/async/results/{request_id}?q={url_encoded_prompt}"
265
- # Poll for results
266
- if not self.quiet:
267
- print("Waiting for results...")
268
- while True:
269
- if not self.quiet:
270
- print(".", end="", flush=True)
271
- # By default, timeout is 300s, change as needed
272
- response = await self.session.get(polling_url)
273
- if response.status != 200:
274
- raise Exception("Could not get results")
275
- content = await response.text()
276
- if content and content.find("errorMessage") == -1:
277
- break
278
-
279
- await asyncio.sleep(1)
280
- continue
281
- # Use regex to search for src=""
282
- image_links = regex.findall(r'src="([^"]+)"', content)
283
- # Remove size limit
284
- normal_image_links = [link.split("?w=")[0] for link in image_links]
285
- # Remove duplicates
286
- normal_image_links = list(set(normal_image_links))
287
-
288
- # Bad images
289
- bad_images = [
290
- "https://r.bing.com/rp/in-2zU3AJUdkgFe7ZKv19yPBHVs.png",
291
- "https://r.bing.com/rp/TX9QuO3WzcCJz1uaaSwQAz39Kb0.jpg",
292
- ]
293
- for im in normal_image_links:
294
- if im in bad_images:
295
- raise Exception("Bad images")
296
- # No images
297
- if not normal_image_links:
298
- raise Exception("No images")
299
- return normal_image_links
300
-
301
- async def save_images(self, links: list, output_dir: str) -> None:
302
- """
303
- Saves images to output directory
304
- """
305
- if not self.quiet:
306
- print("\nDownloading images...")
307
- with contextlib.suppress(FileExistsError):
308
- os.mkdir(output_dir)
309
- try:
310
- jpeg_index = 0
311
- for link in links:
312
- while os.path.exists(os.path.join(output_dir, f"{jpeg_index}.jpeg")):
313
- jpeg_index += 1
314
- async with self.session.get(link, raise_for_status=True) as response:
315
- # save response to file
316
- with open(
317
- os.path.join(output_dir, f"{jpeg_index}.jpeg"), "wb"
318
- ) as output_file:
319
- async for chunk in response.content.iter_chunked(8192):
320
- output_file.write(chunk)
321
- except aiohttp.client_exceptions.InvalidURL as url_exception:
322
- raise Exception(
323
- "Inappropriate contents found in the generated images. Please try again or try another prompt.",
324
- ) from url_exception
325
-
326
-
327
- async def async_image_gen(args) -> None:
328
- async with ImageGenAsync(args.U, args.quiet) as image_generator:
329
- images = await image_generator.get_images(args.prompt)
330
- await image_generator.save_images(images, output_dir=args.output_dir)
331
-
332
-
333
- def main():
334
- parser = argparse.ArgumentParser()
335
- parser.add_argument("-U", help="Auth cookie from browser", type=str)
336
- parser.add_argument("--cookie-file", help="File containing auth cookie", type=str)
337
- parser.add_argument(
338
- "--prompt",
339
- help="Prompt to generate images for",
340
- type=str,
341
- required=True,
342
- )
343
-
344
- parser.add_argument(
345
- "--output-dir",
346
- help="Output directory",
347
- type=str,
348
- default="./output",
349
- )
350
-
351
- parser.add_argument(
352
- "--debug-file",
353
- help="Path to the file where debug information will be written.",
354
- type=str,
355
- )
356
-
357
- parser.add_argument(
358
- "--quiet",
359
- help="Disable pipeline messages",
360
- action="store_true",
361
- )
362
- parser.add_argument(
363
- "--asyncio",
364
- help="Run ImageGen using asyncio",
365
- action="store_true",
366
- )
367
- parser.add_argument(
368
- "--version",
369
- action="store_true",
370
- help="Print the version number",
371
- )
372
-
373
- args = parser.parse_args()
374
-
375
- if args.version:
376
- print(pkg_resources.get_distribution("BingImageCreator").version)
377
- sys.exit()
378
-
379
- # Load auth cookie
380
- cookie_json = None
381
- if args.cookie_file is not None:
382
- with contextlib.suppress(Exception):
383
- with open(args.cookie_file, encoding="utf-8") as file:
384
- cookie_json = json.load(file)
385
-
386
- if args.U is None and args.cookie_file is None:
387
- raise Exception("Could not find auth cookie")
388
-
389
- if not args.asyncio:
390
- # Create image generator
391
- image_generator = ImageGen(
392
- args.U, args.debug_file, args.quiet, all_cookies=cookie_json
393
- )
394
- image_generator.save_images(
395
- image_generator.get_images(args.prompt),
396
- output_dir=args.output_dir,
397
- )
398
- else:
399
- asyncio.run(async_image_gen(args))
400
-
401
-
402
- if __name__ == "__main__":
403
- main()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ImageCreator.py ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import requests
2
+ import time
3
+ from urllib.parse import quote
4
+
5
+ def generate_image_prodia(prompt, model, sampler, seed, neg):
6
+ print("\033[1;32m(Prodia) Creating image for :\033[0m", prompt)
7
+ start_time = time.time()
8
+ def create_job(prompt, model, sampler, seed, neg):
9
+ if neg is None:
10
+ negative = "(nsfw:1.5),verybadimagenegative_v1.3, ng_deepnegative_v1_75t, (ugly face:0.8),cross-eyed,sketches, (worst quality:2), (low quality:2), (normal quality:2), lowres, normal quality, ((monochrome)), ((grayscale)), skin spots, acnes, skin blemishes, bad anatomy, DeepNegative, facing away, tilted head, {Multiple people}, lowres, bad anatomy, bad hands, text, error, missing fingers, extra digit, fewer digits, cropped, worstquality, low quality, normal quality, jpegartifacts, signature, watermark, username, blurry, bad feet, cropped, poorly drawn hands, poorly drawn face, mutation, deformed, worst quality, low quality, normal quality, jpeg artifacts, signature, watermark, extra fingers,fewer digits ,extra limbs ,extra arms ,extra legs ,malformed limbs ,fused fingers ,too many fingers ,long neck ,cross-eyed ,mutated hands ,polar lowres ,bad body ,bad proportions ,gross proportions ,text ,error ,missing fingers ,missing arms ,missing legs ,extra digit ,extra arms ,extra leg ,extra foot ,repeating hair ,nsfw ,[bad-artist-anime],[sketch by bad-artist] ,[mutation],[lowres],[bad hands],[text],[signature],[watermark],[username],[blurry],[monochrome],[grayscale],[realistic],[simple background],[limited palette],close-up,(swimsuit),(cleavage),(armpits),(ass),(navel),(cleavage cutout),(forehead jewel:1.2),(forehead mark:1.5),(bad and mutated hands:1.3),(worst quality:2.0),(low quality:2.0),(blurry:2.0),multiple limbs,bad anatomy,(interlocked fingers:1.2),(interlocked leg:1.2),Ugly Fingers,(extra digit and hands and fingers and legs and arms:1.4),crown braid,(deformed fingers:1.2),(long fingers:1.2)"
11
+ else:
12
+ negative = neg
13
+ url = 'https://api.prodia.com/generate'
14
+ params = {
15
+ 'new': 'true',
16
+ 'prompt': f'{quote(prompt)}',
17
+ 'model': model,
18
+ 'negative_prompt': f"{negative}",
19
+ 'steps': '100',
20
+ 'cfg': '9.5',
21
+ 'seed': f'{seed}',
22
+ 'sampler': sampler,
23
+ 'upscale': 'True',
24
+ 'aspect_ratio': 'square'
25
+ }
26
+ response = requests.get(url,params=params)
27
+ data = response.json()
28
+ return data['job']
29
+
30
+ job_id = create_job(prompt,model,sampler,sampler,neg)
31
+ url = f'https://api.prodia.com/job/{job_id}'
32
+ headers = {
33
+ 'authority': 'api.prodia.com',
34
+ 'accept': '*/*',
35
+ }
36
+
37
+ while True:
38
+ response = requests.get(url=url, headers=headers)
39
+ json = response.json()
40
+ if json['status'] == 'succeeded':
41
+ duration = time.time() - start_time
42
+ response = f'https://images.prodia.xyz/{job_id}.png?download=1'
43
+ return response