Repository navigation
Expand file tree
/
Copy pathapp.py
More file actions
152 lines (137 loc) · 5.74 KB
/
Copy pathapp.py
File metadata and controls
152 lines (137 loc) · 5.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
from flask import Flask, request, render_template_string, session, redirect, url_for
import os
import re
import requests
app = Flask(__name__)
app.secret_key = 'your_secret_key_here' # Replace with a secure random key for production
WORDLIST_PATH = "wordlewords"
WORDLE_URL = "https://raw.githubusercontent.com/tabatkins/wordle-list/main/words"
# Caching word list in memory
word_list_cache = None
# HTML Templates
FORM_HTML = """
<!doctype html>
<html>
<head>
<title>Wordle Solver</title>
<style>
body { font-family: Arial, sans-serif; background-color: #f4f4f4; text-align: center; padding: 20px; }
h1 { color: #333; }
form { background: #fff; padding: 20px; border-radius: 8px; box-shadow: 0px 0px 10px 0px #aaa; display: inline-block; }
input, label { display: block; margin: 10px auto; }
input[type="submit"] { background: #28a745; color: white; padding: 10px 20px; border: none; cursor: pointer; }
input[type="submit"]:hover { background: #218838; }
a { display: block; margin-top: 10px; color: #007bff; text-decoration: none; }
a:hover { text-decoration: underline; }
</style>
</head>
<body>
<h1>Wordle Solver</h1>
<form action="{{ url_for('solve') }}" method="post">
<label for="username">Username:</label>
<input type="text" id="username" name="username" required>
<h3>Enter letter ranges for each of the 5 letters:</h3>
{% for i in range(1,6) %}
<label for="letter{{i}}">Letter {{i}} range (e.g., a-z or a-df-z):</label>
<input type="text" id="letter{{i}}" name="letter{{i}}" required>
{% endfor %}
<label for="elim_letters">Letters to eliminate (optional):</label>
<input type="text" id="elim_letters" name="elim_letters" value="{{ session.get('elim_letters', '') }}">
<label for="exists_letters">Letters known to exist (optional):</label>
<input type="text" id="exists_letters" name="exists_letters">
<input type="submit" value="Solve">
</form>
{% if session.get('elim_letters') %}
<p>Eliminated Letters: {{ session.get('elim_letters') }}</p>
<a href="{{ url_for('reset') }}">Clear Eliminated Letters</a>
{% endif %}
</body>
</html>
"""
RESULT_HTML = """
<!doctype html>
<html>
<head>
<title>Wordle Solver - Results</title>
<style>
body { font-family: Arial, sans-serif; background-color: #f4f4f4; text-align: center; padding: 20px; }
h1 { color: #333; }
div { background: #fff; padding: 20px; border-radius: 8px; box-shadow: 0px 0px 10px 0px #aaa; display: inline-block; }
ul { text-align: left; }
a { display: block; margin-top: 10px; color: #007bff; text-decoration: none; }
a:hover { text-decoration: underline; }
</style>
</head>
<body>
<h1>Wordle Solver - Results</h1>
<div>
<p><strong>Username:</strong> {{ username }}</p>
{% if session.get('elim_letters') %}
<p><strong>Eliminated Letters:</strong> {{ session.get('elim_letters') }}</p>
{% endif %}
<h3>Suggestions:</h3>
{% if suggestions %}
<ul>
{% for word in suggestions %}
<li>{{ word }}</li>
{% endfor %}
</ul>
{% else %}
<p>No words found matching your criteria.</p>
{% endif %}
<a href="{{ url_for('index') }}">Try again</a>
</div>
</body>
</html>
"""
def download_dictionary():
"""Downloads the word list if not present."""
try:
response = requests.get(WORDLE_URL, timeout=10)
response.raise_for_status()
with open(WORDLIST_PATH, "w") as f:
f.write(response.text)
return True
except requests.RequestException as e:
print("Failed to download dictionary:", e)
return False
def load_dictionary():
"""Loads the word list from file and caches it."""
global word_list_cache
if word_list_cache is not None:
return word_list_cache
if not os.path.exists(WORDLIST_PATH):
print("Dictionary not found. Downloading...")
if not download_dictionary():
return []
with open(WORDLIST_PATH, "r") as f:
word_list_cache = [line.strip() for line in f if line.strip()]
return word_list_cache
def build_regex(letter_ranges):
"""Creates a regex pattern based on letter constraints."""
return re.compile("^" + "".join(f"[{rng}]" for rng in letter_ranges) + "$", re.IGNORECASE)
def filter_words(words, pattern, eliminated, exists):
"""Filters words based on regex pattern, eliminated, and existing letters in a single pass."""
return [word for word in words if pattern.match(word) and not any(char in word for char in eliminated) and all(letter in word for letter in exists)]
@app.route("/", methods=["GET"])
def index():
return render_template_string(FORM_HTML)
@app.route("/solve", methods=["POST"])
def solve():
username = request.form.get("username", "").strip()
letter_ranges = [request.form.get(f"letter{i}", "").strip() for i in range(1, 6)]
eliminated = session.get("elim_letters", "") + request.form.get("elim_letters", "").strip().lower()
eliminated = "".join(set(eliminated)) # Remove duplicates
session["elim_letters"] = eliminated
exists_letters = request.form.get("exists_letters", "").strip()
words = load_dictionary()
pattern = build_regex(letter_ranges)
suggestions = filter_words(words, pattern, eliminated, exists_letters)
return render_template_string(RESULT_HTML, username=username, suggestions=suggestions)
@app.route("/reset", methods=["GET"])
def reset():
session.pop("elim_letters", None)
return redirect(url_for("index"))
if __name__ == "__main__":
load_dictionary() # Pre-load dictionary
app.run(host="0.0.0.0", port=5000)