redstonehero commited on
Commit
a43a2a4
·
verified ·
1 Parent(s): 206865d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +77 -17
app.py CHANGED
@@ -6,22 +6,43 @@ import html
6
  import os
7
 
8
  # --- CONFIGURATION ---
9
- # Pulls credentials secretly from Hugging Face Space Settings
10
  API_KEY = os.environ.get("GELBOORU_API_KEY")
11
  USER_ID = os.environ.get("GELBOORU_USER_ID")
12
 
13
- HEADERS = {"User-Agent": "GelbooruTagFetcher/8.0 (Python/HuggingFace)"}
14
  ENDPOINT = "https://gelbooru.com/index.php"
15
 
16
  # --- DATA LISTS (RAW VALUES) ---
17
  FRANCHISES_RAW =[
 
18
  "kancolle", "fire_emblem", "azur_lane", "honkai", "umamusume",
19
- "arknights", "girls_und_panzer", "girls'_frontline", "zenless_zone_zero",
20
  "granblue_fantasy", "kemono_friends", "nikke", "project_moon",
21
  "wuthering_waves", "league_of_legends", "princess_connect!",
22
  "chainsaw_man", "guilty_gear", "reverse:1999", "mega_man", "dq", "tales"
23
  ]
24
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  HAIR_COLORS_RAW =[
26
  "Any",
27
  "white_hair", "red_hair", "purple_hair", "pink_hair",
@@ -30,12 +51,18 @@ HAIR_COLORS_RAW =[
30
  ]
31
 
32
  # --- UI FORMATTERS ---
33
- FRANCHISE_CHOICES =[(f.replace("_", " ").title(), f) for f in FRANCHISES_RAW]
34
- HAIR_CHOICES =[(h.replace("_", " ").title(), h) for h in HAIR_COLORS_RAW]
 
 
35
 
36
- # --- BACKEND FUNCTIONS ---
 
 
37
 
 
38
  def get_tag_count(tag_name):
 
39
  params = {
40
  "page": "dapi", "s": "tag", "q": "index",
41
  "json": 1, "name": tag_name
@@ -60,7 +87,7 @@ def find_character_tag(selected_franchises, selected_hair):
60
  chosen_franchise = random.choice(selected_franchises)
61
  tag_modifier = f"({chosen_franchise}"
62
 
63
- search_tags = f"score:>10 1girl solo -animated -*cosplay* *{tag_modifier}* sort:random"
64
  if selected_hair != "Any":
65
  search_tags += f" {selected_hair}"
66
 
@@ -86,15 +113,23 @@ def find_character_tag(selected_franchises, selected_hair):
86
  log_buffer += "❌ No results found. Try selecting 'Any' hair color."
87
  return "No Match Found", log_buffer
88
 
 
 
89
  for post in posts:
90
  raw_tags = html.unescape(post.get("tags", ""))
91
  tag_list = raw_tags.split()
92
 
93
- franchise_tags = [t for t in tag_list if tag_modifier in t]
 
 
 
 
 
94
 
95
  if len(franchise_tags) == 1:
96
  candidate = franchise_tags[0]
97
 
 
98
  count = get_tag_count(candidate)
99
  time.sleep(0.2)
100
 
@@ -112,9 +147,14 @@ def find_character_tag(selected_franchises, selected_hair):
112
  return "API Error", f"An error occurred: {str(e)}"
113
 
114
  # --- UI HELPER FUNCTIONS ---
115
- def select_all(): return FRANCHISES_RAW
116
- def select_none(): return[]
117
- def invert_selection(current_selection): return[item for item in FRANCHISES_RAW if item not in current_selection]
 
 
 
 
 
118
 
119
  def copy_notification(x):
120
  if x and "Error" not in x and "No Match" not in x:
@@ -136,9 +176,13 @@ with gr.Blocks(theme=gr.themes.Soft()) as app:
136
  gr.Markdown("Pick your franchises and a hair color. The script will return **one specific character tag**.")
137
 
138
  with gr.Row():
 
139
  with gr.Column(scale=1):
 
140
  franchise_input = gr.CheckboxGroup(
141
- choices=FRANCHISE_CHOICES, value=FRANCHISES_RAW, label="1. Select Franchises"
 
 
142
  )
143
 
144
  with gr.Row():
@@ -147,31 +191,47 @@ with gr.Blocks(theme=gr.themes.Soft()) as app:
147
  btn_invert = gr.Button("Invert Selection", size="sm")
148
 
149
  hair_input = gr.Radio(
150
- choices=HAIR_CHOICES, value="Any", label="2. Select Hair Color"
 
 
151
  )
 
152
  submit_btn = gr.Button("Find Character Tag", variant="primary")
153
 
 
154
  with gr.Column(scale=1):
155
  gr.Markdown("### 👇 Click the button below to copy the tag")
156
 
157
  result_btn = gr.Button(
158
- value="Result will appear here...", variant="secondary", size="lg", interactive=True
 
 
 
159
  )
160
 
161
  log_output = gr.TextArea(
162
- label="Process Logs", lines=10, max_lines=15, interactive=False
 
 
 
163
  )
164
 
 
165
  btn_all.click(fn=select_all, outputs=franchise_input)
166
  btn_none.click(fn=select_none, outputs=franchise_input)
167
  btn_invert.click(fn=invert_selection, inputs=franchise_input, outputs=franchise_input)
168
 
169
  submit_btn.click(
170
- fn=find_character_tag, inputs=[franchise_input, hair_input], outputs=[result_btn, log_output]
 
 
171
  )
172
 
173
  result_btn.click(
174
- fn=copy_notification, inputs=result_btn, outputs=result_btn, js=JS_COPY_LOGIC
 
 
 
175
  )
176
 
177
  if __name__ == "__main__":
 
6
  import os
7
 
8
  # --- CONFIGURATION ---
 
9
  API_KEY = os.environ.get("GELBOORU_API_KEY")
10
  USER_ID = os.environ.get("GELBOORU_USER_ID")
11
 
12
+ HEADERS = {"User-Agent": "GelbooruTagFetcher/10.0 (Python)"}
13
  ENDPOINT = "https://gelbooru.com/index.php"
14
 
15
  # --- DATA LISTS (RAW VALUES) ---
16
  FRANCHISES_RAW =[
17
+ "genshin_impact", "pokemon", "blue_archive", "arknights",
18
  "kancolle", "fire_emblem", "azur_lane", "honkai", "umamusume",
19
+ "girls_und_panzer", "girls'_frontline", "zenless_zone_zero",
20
  "granblue_fantasy", "kemono_friends", "nikke", "project_moon",
21
  "wuthering_waves", "league_of_legends", "princess_connect!",
22
  "chainsaw_man", "guilty_gear", "reverse:1999", "mega_man", "dq", "tales"
23
  ]
24
 
25
+ FRANCHISE_SUBSTITUTIONS = {
26
+ "dq": "dragon quest",
27
+ "tales": "tales of (series)"
28
+ }
29
+
30
+ FRANCHISE_EXCEPTIONS = {
31
+ "fire_emblem": ["falchion_(fire_emblem)"],
32
+ "arknights":["infection_monitor_(arknights)", "oripathy_lesion_(arknights)"],
33
+ "project_moon":["e.g.o_(project_moon)", "(identity)"],
34
+ "zenless_zone_zero":["bangboo_(zenless_zone_zero)"],
35
+ "wuthering_waves":["pangu_terminal_(wuthering_waves)", "tacet_discord_(wuthering_waves)", "blake_bloom_(wuthering_waves)", "tacet_mark_(wuthering_waves)"],
36
+ "league_of_legends":["spirit_blossom_(league_of_legends)", "k/da_(league_of_legends)", "star_guardian_(league_of_legends)"],
37
+ "princess_connect!": ["gourmet_guild_(princess_connect!)"],
38
+ "chainsaw_man":["i'll_teach_you_everything_(chainsaw_man)"],
39
+ "dq":["dqn_(dqnww)", "dancer's_costume_(dq)"],
40
+ "tales":["momdy_(talesshinja)", "normin_(tales)"],
41
+ "genshin_impact":["vision_(genshin_impact)"]
42
+ }
43
+
44
+ UNWANTED = ["costume"]
45
+
46
  HAIR_COLORS_RAW =[
47
  "Any",
48
  "white_hair", "red_hair", "purple_hair", "pink_hair",
 
51
  ]
52
 
53
  # --- UI FORMATTERS ---
54
+ FRANCHISE_CHOICES =[
55
+ (FRANCHISE_SUBSTITUTIONS.get(f, f).replace("_", " ").title(), f)
56
+ for f in FRANCHISES_RAW
57
+ ]
58
 
59
+ HAIR_CHOICES =[
60
+ (h.replace("_", " ").title(), h) for h in HAIR_COLORS_RAW
61
+ ]
62
 
63
+ # --- BACKEND FUNCTIONS ---
64
  def get_tag_count(tag_name):
65
+ """Checks how many posts a specific tag has globally."""
66
  params = {
67
  "page": "dapi", "s": "tag", "q": "index",
68
  "json": 1, "name": tag_name
 
87
  chosen_franchise = random.choice(selected_franchises)
88
  tag_modifier = f"({chosen_franchise}"
89
 
90
+ search_tags = f"1girl solo -alternate_hair_color -animated -*cosplay* *{tag_modifier}* score:>10 sort:random"
91
  if selected_hair != "Any":
92
  search_tags += f" {selected_hair}"
93
 
 
113
  log_buffer += "❌ No results found. Try selecting 'Any' hair color."
114
  return "No Match Found", log_buffer
115
 
116
+ franchise_exceptions = FRANCHISE_EXCEPTIONS.get(chosen_franchise,[])
117
+
118
  for post in posts:
119
  raw_tags = html.unescape(post.get("tags", ""))
120
  tag_list = raw_tags.split()
121
 
122
+ franchise_tags =[
123
+ t for t in tag_list
124
+ if tag_modifier in t
125
+ and not any(u in t for u in UNWANTED)
126
+ and not any(exc in t for exc in franchise_exceptions)
127
+ ]
128
 
129
  if len(franchise_tags) == 1:
130
  candidate = franchise_tags[0]
131
 
132
+ # Check popularity
133
  count = get_tag_count(candidate)
134
  time.sleep(0.2)
135
 
 
147
  return "API Error", f"An error occurred: {str(e)}"
148
 
149
  # --- UI HELPER FUNCTIONS ---
150
+ def select_all():
151
+ return FRANCHISES_RAW
152
+
153
+ def select_none():
154
+ return[]
155
+
156
+ def invert_selection(current_selection):
157
+ return[item for item in FRANCHISES_RAW if item not in current_selection]
158
 
159
  def copy_notification(x):
160
  if x and "Error" not in x and "No Match" not in x:
 
176
  gr.Markdown("Pick your franchises and a hair color. The script will return **one specific character tag**.")
177
 
178
  with gr.Row():
179
+ # --- Left Column: Inputs ---
180
  with gr.Column(scale=1):
181
+
182
  franchise_input = gr.CheckboxGroup(
183
+ choices=FRANCHISE_CHOICES,
184
+ value=FRANCHISES_RAW,
185
+ label="1. Select Franchises"
186
  )
187
 
188
  with gr.Row():
 
191
  btn_invert = gr.Button("Invert Selection", size="sm")
192
 
193
  hair_input = gr.Radio(
194
+ choices=HAIR_CHOICES,
195
+ value="Any",
196
+ label="2. Select Hair Color"
197
  )
198
+
199
  submit_btn = gr.Button("Find Character Tag", variant="primary")
200
 
201
+ # --- Right Column: Outputs ---
202
  with gr.Column(scale=1):
203
  gr.Markdown("### 👇 Click the button below to copy the tag")
204
 
205
  result_btn = gr.Button(
206
+ value="Result will appear here...",
207
+ variant="secondary",
208
+ size="lg",
209
+ interactive=True
210
  )
211
 
212
  log_output = gr.TextArea(
213
+ label="Process Logs",
214
+ lines=10,
215
+ max_lines=15,
216
+ interactive=False
217
  )
218
 
219
+ # --- EVENT LISTENERS ---
220
  btn_all.click(fn=select_all, outputs=franchise_input)
221
  btn_none.click(fn=select_none, outputs=franchise_input)
222
  btn_invert.click(fn=invert_selection, inputs=franchise_input, outputs=franchise_input)
223
 
224
  submit_btn.click(
225
+ fn=find_character_tag,
226
+ inputs=[franchise_input, hair_input],
227
+ outputs=[result_btn, log_output]
228
  )
229
 
230
  result_btn.click(
231
+ fn=copy_notification,
232
+ inputs=result_btn,
233
+ outputs=result_btn,
234
+ js=JS_COPY_LOGIC
235
  )
236
 
237
  if __name__ == "__main__":