A Flask web application and Wikipedia bot that manages and processes PetScan lists for Wikipedia articles. It reads {{petscan list}} templates from wiki pages, queries the PetScan API for results, and writes formatted lists or wikitables back to the page.
- Web Interface — Users submit a Wikipedia page title; the app reads the page, finds
{{petscan list}}templates, queries PetScan, and writes the formatted results back. - Bot Mode — Automatically scans all pages containing
{{petscan list}}across configured wikis and processes them in batch. - Template Generator — Converts a PetScan URL into a
{{petscan list}}wikitext template that can be pasted into any wiki page.
| Component | File(s) | Purpose |
|---|---|---|
| Flask Web App | app.py |
HTTP routes for web interface |
| Bot Entry Point | bot.py |
Batch processing for all configured wikis |
| Core Package | PetScanList/ |
API client, wikitext parser, wiki editor, i18n |
| Frontend | static/, templates/ |
CSS, JS, and Jinja2 HTML templates |
| Deployment | shs/ |
Shell scripts for Toolforge deployment |
| Translations | I18n/ |
Localized strings (Arabic) |
| CI/CD | .github/workflows/update.yml |
Auto-deploy on push to main |
- Python 3.11 — Runtime
- Flask — Web framework
- mwclient — MediaWiki API client
- pywikibot — Diff display utility
- wikitextparser — Wikitext parsing and manipulation
- requests — HTTP client for PetScan API
- python-dotenv — Environment variable loading
- Wikimedia Toolforge — Production hosting platform
- Python 3.x
- pip (Python package installer)
- Wikipedia account with bot password
-
Clone this repository:
git clone https://github.com/MrIbrahem/petscan_list.git cd petscan_list -
Create a virtual environment (recommended):
python -m venv venv source venv/bin/activate # On Linux/Mac # or .\venv\Scripts\activate # On Windows
-
Install the required dependencies:
pip install -r requirements.txt
-
Create a bot password for your Wikipedia account:
- Go to Special:BotPasswords on Wikipedia (https://ar.wikipedia.org/wiki/Special:BotPasswords)
- Create a new bot password with necessary permissions
-
Set up your credentials:
- Create a
.envfile in the project root with the following content:WIKIPEDIA_BOT_USERNAME=YOUR_USERNAME WIKIPEDIA_BOT_PASSWORD=YOUR_BOT_PASSWORD
Replace
YOUR_USERNAMEwith your Wikipedia username andYOUR_BOT_PASSWORDwith your bot password.Alternatively, you can set environment variables directly:
set WIKIPEDIA_BOT_USERNAME=YOUR_USERNAME set WIKIPEDIA_BOT_PASSWORD=YOUR_BOT_PASSWORD
- Create a
Start the Flask development server:
python app.pyThen open your web browser and navigate to:
http://localhost:5000
The web interface allows you to:
- Process individual Wikipedia articles
- View results directly in your browser
- Interactive usage with immediate feedback
Run the bot script to automatically process multiple pages:
python bot.pyThe bot mode:
- Automatically searches for pages with "petscan list" template
- Processes all found pages in batch
- Works specifically with Arabic Wikipedia
- Runs continuously without manual intervention
petscan_list/
├── app.py # Flask web application
├── bot.py # Batch bot entry point
├── requirements.txt # Python dependencies
├── jobs.yaml # Toolforge job scheduler config
├── run.bat # Windows dev launcher
├── PetScanList/ # Core Python package
│ ├── __init__.py # Public API exports
│ ├── petscan_bot.py # PetScan HTTP client
│ ├── text_bot.py # Wikitext template processor
│ ├── one_page_bot.py # WikiBot class (auth + page editing)
│ ├── make_template.py # URL → wikitext template converter
│ ├── wikitable.py # Wikitable generator
│ ├── I18n.py # Translation loader
│ ├── sites.py # Supported wiki whitelist
│ ├── pages.py # Page listing helper
│ ├── params.py # Parameter constants
│ ├── account.py # Credential loading
│ └── petscan.lua # Lua Scribunto module for MediaWiki
├── shs/ # Deployment shell scripts
│ ├── install.sh # Initial Toolforge setup
│ ├── pip.sh # Dependency refresh
│ ├── runall.sh # Daily batch job
│ └── update.sh # Live deployment update
├── I18n/ # Translation files
│ └── ar.json # Arabic translations
├── static/ # Frontend assets (CSS, JS)
│ ├── style.css # Main styles
│ ├── theme.css / theme.js # Light/dark theme
│ ├── autocomplete.js # Wiki selector autocomplete
│ ├── tt.js # Tooltip functionality
│ └── images/ # Image assets
├── templates/ # Jinja2 HTML templates
│ ├── index.html # Homepage
│ ├── main.html # Base layout
│ ├── result.html # Operation result page
│ ├── pages.html # Page listing
│ ├── template_form.html # Template generator form
│ ├── tutorials.html # Usage tutorials
│ └── error.html # Error page
└── .github/workflows/
└── update.yml # CI/CD: auto-deploy on push to main
shs/install.sh— Initial Toolforge setup (create venv, clone repo, start webservice)shs/update.sh— Live deployment update with backup and rollbackshs/pip.sh— Dependency refreshshs/runall.sh— Daily batch bot execution
- Navigate to the homepage at
http://localhost:5000 - Enter the Wikipedia article title
- The application will process the PetScan list and display the results
- Make sure your credentials are properly configured
- Run
python bot.py - The bot will automatically:
- Find pages with "petscan list" template
- Process each page
- Show progress in the terminal
- Navigate to
/template - Paste a PetScan URL with query parameters
- Optionally set
_line_format_,at_start,at_end - The tool generates
{{petscan list}}wikitext ready to paste
These parameters are optional:
|_result_=table: Display the result as a wikitable instead of a bulleted list.|_line_format_=: Customize the line format.$1is replaced with the page title. Example:|_line_format_ = # {{user:Mr. Ibrahem/link|$1}}|_at_start_=: Custom content before the list (default:{{Div col|colwidth=20em}})|_at_end_=: Custom content after the list (default:{{Div col end}})
|output_limit = 3000: Maximum number of results to display.
The project follows a clean two-tier architecture:
- Entry points (
app.py,bot.py) at the root — thin wrappers that delegate to the core package. - Core package (
PetScanList/) — contains all business logic, API clients, and utilities. - Presentation (
templates/,static/) — separated from logic.
- Facade:
PetScanList/__init__.pyexports a simplified API. - Separation of Concerns: API client, wikitext processing, and wiki editing are distinct modules.
- Configuration as Code:
sites.pyandparams.pydefine constants at module level. - CI/CD: GitHub Actions auto-deploys on push to
mainvia SSH to Toolforge.
- Modules are short and focused (most under 130 lines).
- Type hints are present on key functions.
- Each module has a clear single responsibility.
- Variable naming is generally descriptive.
- Some Arabic strings are hardcoded outside the I18n system.
- Commented-out dead code exists in several files.
- Synchronous processing — no concurrency for batch operations.
- PetScan API results are capped at 3000 via
OUTPUT_LIMIT. - Site objects are cached per wiki in
WikiBot.sites.
- Clean module separation — Each file in
PetScanList/has a single, well-defined responsibility. - Explicit public API —
__all__in__init__.pymakes the import surface clear and intentional. - Defensive error handling — Specific exception handling for HTTP errors, login failures, and page-not-found.
- User-Agent compliance — All HTTP requests include a proper
User-Agentwith contact info. - Backup-on-deploy —
update.shcreates timestamped backups before every deployment with automatic rollback on failure. - Dual output modes — Supports both bulleted lists and wikitables via the
_result_parameter. - Lua companion module —
petscan.luaprovides server-side PetScan URL generation within MediaWiki. - Automated CI/CD — GitHub Actions deploys to Toolforge on every push to
main. - Toolforge-native — Uses
toolforge-jobsfor scheduled batch runs andwebservicefor the web app.
Zero unit tests, integration tests, or end-to-end tests. Any refactoring is risky without a test safety net.
Some modules use logging, others use print(). one_page_bot.py calls logging.basicConfig() at import time, overriding the caller's configuration.
fix_value()logic appears in bothtext_bot.pyandmake_template.py.{{!}}/{{|}}replacement is done in at least 3 places.- Session creation (
requests.session()) is duplicated inpetscan_bot.pyandI18n.py.
Column headers in wikitable.py are hardcoded Arabic strings instead of using the I18n system.
No setup.py, pyproject.toml, or __main__.py. The package can't be installed via pip or run with python -m PetScanList.
templates/main copy.html— duplicate template file.- Commented-out blocks in
one_page_bot.pyandtext_bot.py. confs/directory referenced in README doesn't exist.
bot.py processes all pages sequentially. For large result sets (up to 3000 pages per wiki), this is very slow.
The /template POST endpoint has no CSRF token. An attacker could craft a form on another site that submits to this endpoint.
account.py defaults to empty strings if env vars are missing. The bot will attempt API calls with empty credentials, producing confusing errors instead of failing fast.
text_bot.py line 134:
pet_section = text.split(template_string)[1].split(template_end_string)[0]If template_string appears multiple times, [1] picks the wrong occurrence, potentially corrupting the page.
No X-Frame-Options, X-Content-Type-Options, or Content-Security-Policy headers. The app is vulnerable to clickjacking and MIME-type sniffing.
one_page_bot.py line 11:
logging.basicConfig(level=LOGGING_LEVEL)This runs at import time and overrides any logging configuration set by Flask or the calling application.
tt.js (tooltip library) needs manual audit to verify it properly escapes user-supplied content.
| Category | Issue | Priority |
|---|---|---|
| Testing | Zero tests exist | High |
| Security | No CSRF on POST forms | High |
| Security | No security headers | Medium |
| Code Quality | Mixed logging (print vs logging) | Medium |
| Code Quality | Code duplication across modules | Medium |
| Documentation | confs/ referenced in README but doesn't exist |
Medium |
| Dead Code | templates/main copy.html should be deleted |
Low |
| Dead Code | Commented-out blocks in multiple files | Low |
| I18n | No en.json for English fallback |
Low |
| I18n | Hardcoded Arabic in wikitable.py |
Low |
| Packaging | No pyproject.toml or setup.py |
Low |
| Deployment | No health check after webservice restart | Low |
| Performance | No concurrency for batch page processing | Low |
- Add fail-fast validation in
account.py— raiseValueErrorif credentials are empty. - Remove
logging.basicConfig()fromone_page_bot.py— let entry points configure logging. - Replace all
print()calls withloggingacross the codebase. - Delete
templates/main copy.html. - Clean up commented-out dead code.
- Fix the README — remove reference to nonexistent
confs/directory. - Extract shared
fix_value()and session-creation utilities.
- Add unit tests for
petscan_bot.py,text_bot.py,make_template.py, andwikitable.py. - Add CSRF protection via Flask-WTF.
- Add security headers via Flask
after_requesthook. - Move hardcoded Arabic labels in
wikitable.pyto the I18n system. - Create
en.jsonfor English translation fallback. - Add
pyproject.tomlfor proper Python packaging. - Add input validation/sanitization for PetScan parameters.
- Add async/concurrent processing for batch page operations (
asyncio+aiohttp). - Split
WikiBotinto smaller classes:WikiAuthenticator,PageEditor. - Add integration tests with mocked PetScan/MediaWiki APIs.
- Create a proper CLI using
argparseorclick. - Add a build pipeline for frontend assets (minification, cache-busting).
- Add Content Security Policy headers.
- Expand wiki support beyond Arabic Wikipedia/Wikisource.
| Metric | Rating | Notes |
|---|---|---|
| Overall Project Rating | 6 / 10 | Functional and deployed, but lacks testing and security hardening |
| Production Readiness | Moderate | Running on Toolforge, but no tests validate changes before deploy |
| Technical Debt | Medium | Code duplication, mixed logging, dead code, no tests |
| Risk Assessment | Low-Medium | CSRF vulnerability, credential handling edge cases, unsafe string splitting |
| Maintainability | 6 / 10 | Good separation of concerns, but no tests make refactoring risky |
| Code Quality | 6.5 / 10 | Clean modules with type hints, but inconsistent logging and duplication |
| Security | 5 / 10 | No CSRF, no security headers, potential XSS in JS |
| Testability | 3 / 10 | Zero tests; modules are structured for testability but untested |
Each subfolder has its own detailed README:
PetScanList/README.md— Core package deep-diveshs/README.md— Deployment scripts analysisI18n/README.md— Internationalization reviewstatic/README.md— Frontend assets reviewtemplates/README.md— HTML templates review