dopetalk does not endorse any advertised product nor does it accept any liability for it's use or misuse


Our Discord Notification Server invitation link is https://discord.gg/jB2qmRrxyD

Author Topic: ISE - Intelligent Search Engine for Posts and PDFs  (Read 12 times)

Offline smfadmin (OP)

  • SMF (internal) Site
  • Administrator
  • Sr. Member
  • *****
  • Join Date: Dec 2014
  • Location: Management
  • Posts: 586
  • Reputation Power: 0
  • smfadmin has hidden their reputation power
  • Last Login:Today at 06:24:20 PM
  • Supplied Install Member
ISE - Intelligent Search Engine for Posts and PDFs
« on: Yesterday at 11:01:38 PM »
ISE - Intelligent Search Engine for Posts and PDFs!

Current version: ISE_v5.5 for SMF 2.0.19-- Download using the table below:

πŸ“Ž Click on me to view the list of attachments
#FileSizeDL
1ISE_Checkpoint.md7.9 KB⬇️
2ISE_v5.5.zip4.3 MB⬇️
3Claude on PDF search not finding _listatt_ occurrences  and ISE 5.5 and PDF Infexing.pdf4.2 MB⬇️
4Modifications.english.php-post-ISE65.7 KB⬇️
5ManageSettings.php-post-ISE95.2 KB⬇️
6Admin.php-pre-ISE37.2 KB⬇️
7Admin.php-post-ISE48.4 KB⬇️
8Admin - Copy.php-pre-ISE37.2 KB⬇️
9Admin - Copy.php-post-ISE48.4 KB⬇️
10Modifications.english-pre-ISE - Copy.php65.5 KB⬇️
11ManageSettings - Copy.php-pre-ISE95 KB⬇️

πŸ“ ISE_Checkpoint.md

ISE Project β€” Checkpoint

Paste this whole file into a fresh chat to resume. It reflects state as of the end of the PDF-indexing/search work session (PDFIndexer.py two-engine union + resume/locking, PDFsearch.py filename/topic search, orphan_check.py, cron cleanup). Older ISE post-search work (search.py/IndexBuilder.py/ RankingEngine.py) is included for completeness but was not touched this session β€” treat those as stable/working unless told otherwise.

Environment: live box is CentOS 6.10, Python 3.6.3, 2GB RAM. This OS's age is the root cause of most dependency fights below β€” expect the same pattern (no wheel, needs Rust, needs Python 3.8+) with any new tool.


File / component table

FileLocationStatusUse it?
PDFIndexer.py/var/www/html/The_ISE_Project/Rebuilt this session: two-engine (PyMuPDF+pypdf) union extraction, --fast mode, checkpointing, resume-by-default, --start-at, single-instance file lockYes β€” current, deployed, working
PDFsearch.py/var/www/html/The_ISE_Project/Rebuilt this session: adds filename/topic search merged with content search, live progressYes β€” current, deployed, working
orphan_check.py/var/www/html/The_ISE_Project/New this session. Weekly cron job, avatar-excluded, diffs against orphan_state.jsonYes β€” deployed, in crontab
word_index_pdf.json / pdf_store.jsonISE_Data/Rebuilt from scratch with the new two-engine extractor; 497/676 PDFs indexed, 179 skipped (genuinely image-only, confirmed)Yes β€” current on disk
orphan_state.jsonISE_Data/State file for orphan_check.py, auto-managedDon't touch by hand
all_orphans.py/var/www/html/The_ISE_Project/Old one-off diagnostic (no avatar filter, no diffing)No β€” superseded by orphan_check.py, removed from crontab, left on disk unused
search.py, IndexBuilder.py, IndexLookup.py, Tokeniser.py, RankingEngine.py, ResultFormatter.py, ise_trace.py/var/www/html/The_ISE_Project/Older ISE post-search engine (ISE 5.1). Not touched this session.Yes β€” assumed stable; re-verify only if something seems broken
qf_search_bridge.php, qf_PDFsearch_bridge.phpSMF theme/SourcesPHP bridges wiring the dropdown search-engine options to the Python scriptsYes β€” working as of ISE 5.1
Search.php, index_template.php (SMF core, patched)SMFDropdown values 'ISE' / 'ISEpdf' wired inYes β€” working
pdfplumbertried, rejectedNeeds Rust to build cryptography from source on this box; no working path foundNo
pypdfium2tried, rejectedNo compatible wheel at any version for this platformNo
tesseract 3.04 (EPEL) / ocrmypdf 12.7.2tried, parkedocrmypdf requires tesseract β‰₯4.0 (dead end); tesseract 3.04 direct-CLI use never actually testedParked β€” user said "I don't need OCR", not pursuing

Verified facts β€” don't re-check

  • Live box: CentOS 6.10, Python 3.6.3, 2GB RAM, swap present. dmesg confirmed an actual OOM kill of a PDFIndexer.py run (913MB resident) β€” this is a real, hit-once constraint, not theoretical.
  • Package pins that are load-bearing, don't let anything upgrade them without re-testing:
    • pymupdf==1.19.2 (no newer wheel for this Python/platform)
    • pypdf==3.1.0 (5.x requires typing.Protocol, Python 3.8+, crashes on import here)
  • poppler-utils on this box is 0.12.4 (2010) and silently mis-decodes PDFs with malformed ToUnicode CMaps into garbage tokens instead of erroring β€” this was the original root cause of the very first bug in this session (search for "listatt" finding nothing despite the word being visibly present).
  • The two-engine union (PyMuPDF + pypdf) is genuinely more thorough than either alone β€” confirmed via per-engine unique-term tracking built into PDFIndexer.py --monitor output, not just assumed.
  • --fast (PyMuPDF only) is real and works β€” confirmed correct index output, ~3-20x faster depending on file, meaningfully lighter on memory.
  • The two schedules (--fast every 6h, full union every 2 days) write to the same word_index_pdf.json/pdf_store.json β€” the single-instance lock (/tmp/pdfindexer.lock, fcntl) was added and tested (confirmed: a second instance exits immediately with a clear message rather than racing) specifically to stop one overwriting the other's progress if they ever overlap.
  • 179 of 676 PDFs are skipped as having no extractable text β€” confirmed via direct testing (both engines return empty) these are genuinely image-only/scanned, not an extraction bug.
  • Orphaned-attachment root cause confirmed via direct DB query: e.g. attach-4868's id_msg (58213) doesn't resolve to any row in smf209_messages β€” the post was deleted. SMF's dlattach action requires both topic= and attach= to serve a file; confirmed (user tested directly) there is no working fallback without a valid topic. This is a genuine, currently-unfixable-in-code data gap, not a PDFsearch.py bug.
  • ~360 attachments have id_msg=0 β€” confirmed this is SMF's normal avatar convention (profile pictures), not orphaning. Only ~6 of the original 360-ish flagged rows were real orphaned content PDFs.
  • all_orphans.py (old diagnostic) has no avatar filter and no diff logic β€” confirmed strictly redundant with orphan_check.py. User agreed to remove it from cron after initially wanting to keep it.
  • Current live crontab (as of this session, MAILTO=apache, all jobs now redirect output to per-job log files instead of flooding mail):
    0 */2 * * * python3 IndexBuilder.py                                    (post index, every 2h)5 */6 * * * python3 PDFIndexer.py --fast --monitor                     (PDF index, fast, every 6h)10 0 */2 * * python3 PDFIndexer.py --monitor                           (PDF index, full union, every 2 days)15 */12 * * * attach_filetypes.sh /var/www/html/attachments            (every 12h)0 6 * * 1 python3 orphan_check.py --html ... --quiet-if-empty           (weekly Monday 06:00)

    all_orphans.py's 07:00 Monday line was removed.


Open items (decisions, not blockers)

  • OCR for the 179 image-only PDFs β€” parked, not rejected. Tesseract 3.04 (EPEL) is installed and confirmed present; direct-CLI use (bypassing ocrmypdf, which needs tesseract β‰₯4.0) was never actually tested end-to-end. Revisit only if/when wanted.
  • OS migration β€” user twice expressed mild wishful thinking about a newer OS given the repeated dependency-version fights, but has not decided to act on it. Not a live plan, don't push it.
  • Tokeniser is still a plain .split() in PDFIndexer.py β€” not punctuation-aware ([listatt] and listatt index as separate tokens). Known limitation, never prioritized for a fix.
  • pdf_store.json's filename field is always None β€” resolve_filename() exists but isn't wired into PDFIndexer.py's main(). Doesn't block search (PDFsearch.py resolves real filenames itself via direct DB query) but is a known gap in the index file's own completeness.
  • Markdown manual requested and delivered this session (ISE_Python_Scripts_Manual.md, covering PDFIndexer.py/PDFsearch.py/orphan_check.py CLI options) β€” exists as an output file; not saved into project memory/repo, worth confirming it's actually been kept somewhere durable if it's meant to be a lasting reference.
  • Dev-box replication β€” user's stated plan is to follow this session's saved transcript (after text extraction) to redo this same PDFIndexer/PDFsearch work on the separate dev box (/var/www/html/smf20/The_ISE_Project). Not started.

Next actual action

None queued β€” user explicitly paused ISE work this session ("no more ISE!"). When resumed, the next actual action is: replicate the PDFIndexer.py/PDFsearch.py two-engine-union + locking/resume work on the dev box, using this session's saved transcript as the reference.


⚠️ No .md attachment at index 1 for message #49422 (currentMsgId() returned this value).

ISE - Intelligent Search Engine for Posts and PDFs

WHAT THIS IS

Adds a custom search engine option called "ISE" (Intelligent Search
Engine) to your forum's search-engine drop-down box, alongside the
existing Default/Google/Yandex/Nigma options.

ISE is a private, self-hosted search tool: a pure Python search engine (QueryParser -> Tokeniser -> ANDMatcher -> SortEngine -> ResultFormatter) that reads directly from your forum's own posts and returns matching results as clickable links, sorted newest first.

This mod also adds search-query logging (via syslog) for both the
native SMF search box and the ISE dropdown option, so every real search your users type gets recorded for later review.

]REQUISITE MODS

1. Board-color-and-icons (Version 1.1)
2. Automatic Package Version Emulation (Version 1.6)
3. CustomSearch (Version 1.0) -- Install via Emulating 2.0

Install the above, in order, before installing this package.

FEATURES

- WORD matching:   any_search_term
- PHRASE matching: "an exact quoted phrase" (whitespace-exact, no
                    normalization -- a double space inside quotes is
                    matched literally)
- Mixed queries:   word1 word2 "an exact phrase" -- all terms must
                    match (AND logic) for a post to qualify
- Results sorted newest-first
- Every search (native SMF box, ISE dropdown, and the site's Google
  search widget) is logged via syslog: username/Guest, IP address,
  timestamp, and the raw query string

WHAT GETS INSTALLED

- Sources/QueryFrontend.php         -- syslog logging function

- Sources/Search.php (patched)      -- adds the "ISE" case to the search-engine dropdown handler

- Sources/ManageSettings.php (patched) -- adds an admin toggle, "Use ISE search"

- Themes/default/index.template.php (patched) -- loads
  widget_write_log.js and adds the "ISE" option to the dropdown

- Themes/default/scripts/widget_write_log.js -- logs searches made
  through the site's separate Google-search widget

- Themes/default/languages/Modifications.english.php (patched)
-- adds the "ISE" and "Use ISE search" language strings
  (both languages/ and language/ directory spellings are patched,
  since this varies by SMF install)

- $boarddir/The_ISE_Project/  -- the Python search engine itself

  (QueryParser.py, Tokeniser.py, IndexBuilder.py, IndexLookup.py,
  ANDMatcher.py, SortEngine.py, ResultFormatter.py, search.py,
  qf_search_bridge.php, daily_queries.py, query_log_reader.py)
 -- protected from direct web access via its own .htaccess

- $boarddir/ISE_Data/  -- holds the generated search index
  (word_index.json, post_store.json) -- created with 0700
  permissions and its own .htaccess, since this data is a full,
  searchable copy of every post on your forum

- The full Mozilla PDF Javascript libraries at $boarddier/pdfjs

REQUIREMENTS -- READ BEFORE INSTALLING

This mod's PHP/dropdown/logging pieces install automatically through
the Package Manager. The Python search engine itself does NOT run
automatically -- it needs a few things set up on the server first,
by hand, once:

 - Python 3.6+ available on the server, with the PyMySQL package
   installed for whichever interpreter you'll use to run these
   scripts: python3 -m pip install pymysql

AFTER INSTALLING

The Python search engine itself does NOT run by default so folow this carefully:

1. cd ..whatever-your-webroot-is../The_ISE_Project

   python3 IndexBuilder.py

2. cd ..whatever-your-webroot-is../The_ISE_Project
 
   python3 PDFIndexer.py --monitor

3. Go to Admin > Configuration > Modificication Settings > CustomSearch > ISE and ISEpdf uncheck both and Save then recheck both and Save again.

4. Go to the top right of the page and now the dropdown will have ISE and ISEpdf so now you can use it but wait until the indexing has finished.

5. Test a search using the ISE option from the dropdown to confirm everything is wired up correctly before relying on it.

6. crontab -u apache -e

MAILTO=apache
0 */2 * * * python3 /var/www/html/The_ISE_Project/IndexBuilder.py
0 3 * * 0 python3 /var/www/html/The_ISE_Project/PDFIndexer.py --monitor

NOTES

- Search queries are logged via syslog (facility LOCAL0, tag smf-queries) -- typically landing in /var/log/messages depending on your syslog configuration. Two small scripts are included to help review this log:

- The_ISE_Project/daily_queries.py     -- lists today's searches
- The_ISE_Project/query_log_reader.py  -- lists the full history

PRIVACY NOTE

Once enabled, every real user's search terms are logged, including guests (identified by IP address rather than username). Given the sensitive nature of a harm-reduction forum's likely search content, review who has access to your server's syslog output and how long you want to retain this history before enabling this for your full userbase.


Post Merged: Yesterday at 11:52:17 PM
═══════════════════════════════════════════════ISE / SMF MOD WORK β€” RELOADABLE CHECKPOINT(paste this into a fresh chat to resume)═══════════════════════════════════════════════## FILE/COMPONENT STATUS TABLE| File | Location | Status | Use? ||---|---|---|---|| PDFsearch.py | The_ISE_Project/ | Fixed: no result cap, WORD_INDEX_PATH/PDF_STORE_PATH auto-resolve via ISE_ROOT (Path(__file__).resolve().parent.parent) | YES β€” confirmed working on smf20 + live || PDFIndexer.py | The_ISE_Project/ | Fixed: ATTACH_DIR auto-resolves via ISE_ROOT; UTF-8 decode fix for pdftotext; em-dash print fix | YES β€” confirmed working, 670 PDFs/live, 2 PDFs/smf20 || IndexBuilder.py | The_ISE_Project/ | Fixed: Settings.php path auto-resolves via os.path.dirname(__file__) | YES β€” confirmed working, 45,069 posts/live, 7 posts/smf20 || qf_PDFsearch_bridge.php | The_ISE_Project/ | Fixed: $script uses __DIR__ (was hardcoded to live); unique filename per request (no race condition); debug log β†’ ISE_Data/qf_debug.txt (was /tmp/, permission denied) | YES || qf_search_bridge.php | The_ISE_Project/ | Fixed: debug log path same as above | YES || install_ise.php | package root | REVERTED to original simple version β€” just creates The_ISE_Project + ISE_Data dirs (0777). Automatic background indexer launch was built then explicitly abandoned (Andrew's call β€” too many failure modes: buffering, process detachment, stale root-owned log files blocking apache writes) | YES (simple version only) || uninstall_ise.php | package root | NEW β€” recursively deletes The_ISE_Project/ISE_Data/pdfjs even with leftover generated files inside (plain require-dir reverse fails silently on non-empty dirs) | YES, not yet tested live || install.xml | package root | Contains 5 operations: ManageSettings.php (ISE+ISEpdf checkboxes), Search.php (case 'ISE'/'ISEpdf' dispatcher), index.template.php (dropdown options), Modifications.english.php (lang strings), Admin.php (CustomSearch menu registration) | YES β€” confirmed installing correctly on smf20 || package-info.xml | package root | <code>install_ise.php</code> now runs AFTER extract steps (was before β€” scripts didn't exist yet); <code>uninstall_ise.php</code> added to uninstall block; <readme type="bbc">readme.txt</readme> added | YES || readme.txt | package root | Lists 3 prerequisite mods (Board-color-and-icons v1.1, Automatic Package Version Emulation v1.6, CustomSearch v1.0) + manual post-install indexer commands (Andrew added these himself) | YES β€” readme display on install screen never confirmed working (may be an unsupported tag on this fork) || Admin.php | Sources/ | No changes needed beyond install.xml's operation | n/a, not a standalone artifact |## VERIFIED FACTS β€” DON'T RE-CHECK- This SMF fork has **inverted position semantics**: `position="before"` in install.xml actually inserts content AFTER the matched text; `position="after"` inserts BEFORE. Confirmed via direct testing on index.template.php and ManageSettings.php. Order only matters for index.template.php (PHP ternary chain) β€” doesn't matter for ManageSettings.php/Modifications.english.php (independent array/assignment lines).- Bare `<search>`/`<replace>` (no position attribute) silently no-ops on this fork despite showing "Test successful" β€” must use `position="before|after"` + `<add>` instead.- Live SMF root = `/var/www/html/`, DB = `smf209`. Test install = `/var/www/html/smf20/`, DB = `smf20` (own separate DB, own separate Settings.php, own attachments folder).- Three parallel SMF installs exist: `/var/www/html/` (live), `/var/www/html/smf20/`, `/var/www/html/smf21/` β€” each fully independent, no shared files by design (Andrew's explicit requirement).- Python 3.6 on this server: `subprocess.run(..., universal_newlines=True)` defaults to strict ASCII decoding β€” must use `encoding="utf-8", errors="replace"` explicitly for any subprocess call touching real-world text (PDFs, etc.).- `shell_exec` and subprocess execution are NOT blocked by disable_functions or open_basedir on either PHP CLI or the real web-facing PHP (both confirmed empty via direct test).- readme.txt uses BBCode `[b]...[/b]` β€” added `type="bbc"` to the `<readme>` tag but never confirmed it actually renders on the install screen.- PDF search bug (results always capped at 20) β€” root cause was `--limit` argparse default=20 in PDFsearch.py; fixed to default=None.- "Same 20 results regardless of query" bug β€” root cause was qf_PDFsearch_bridge.php reading a stale shared HTML output file when shell_exec silently failed; fixed via unique-filename-per-request + readfile + unlink.- Main forum search "only 2 results for 'drugs'" bug β€” root cause was IndexBuilder.py connecting to smf20's test Settings.php via a hardcoded path instead of live's; unrelated to any of tonight's later bugs.## OPEN ITEMS (decisions, not blockers)- Whether to re-attempt automatic background indexing later, or keep it permanently manual (currently: manual, by Andrew's choice).- Whether readme.txt's BBCode actually renders on this fork's install screen β€” never visually confirmed.- `[lmv=inline]` BBCode tag β€” designed (unparsed_content tag feeding straight into MDParser.php) but not yet built.- `[lmv]` mod currently interferes with the PDF viewer (PDF disappears when [lmv] present) β€” reported, not yet diagnosed. Need PDFBBC.php + LMVBBC.php uploaded to find the collision (likely shared class/function/CSS name, since LMV mirrors PDF's architecture closely).- `[listatt]` "Open with" request β€” real fix is likely server-side `Content-Disposition: inline` header instead of `attachment`, not an OS-level right-click hook (browsers don't let a page control that menu). Not yet built.- Andrew has an already-written "redact tool" β€” mentioned in passing, zero details on what it does or where it lives.## NEXT ACTUAL ACTIONRebuild the package zip using package-info.xml + install.xml + readme.txt + install_ise.php (simple version) + uninstall_ise.php + the fixed PDFsearch.py/PDFIndexer.py/IndexBuilder.py/qf_PDFsearch_bridge.php/qf_search_bridge.php β€” all currently only verified on the *running* smf20 and live filesystems, NOT yet copied into Andrew's actual package source folder. Do that copy first, rebuild the zip, do one full fresh install (vanilla+CustomSearch) end to end, then manually run IndexBuilder.py and PDFIndexer.py per the readme instructions and confirm both complete cleanly.

Post Merged: Today at 03:00:08 PM
Checkpoint as at ISE v5.6 and sit on it as it is stable, packaged and system independent. 

« Last Edit: Today at 03:37:39 PM by smfadmin »
friendly
0
funny
0
informative
0
agree
0
disagree
0
like
0
dislike
0
No reactions
No reactions
No reactions
No reactions
No reactions
No reactions
No reactions
measure twice, cut once

Tags:
 


dopetalk does not endorse any advertised product nor does it accept any liability for it's use or misuse





TERMS AND CONDITIONS

In no event will d&u or any person involved in creating, producing, or distributing site information be liable for any direct, indirect, incidental, punitive, special or consequential damages arising out of the use of or inability to use d&u. You agree to indemnify and hold harmless d&u, its domain founders, sponsors, maintainers, server administrators, volunteers and contributors from and against all liability, claims, damages, costs and expenses, including legal fees, that arise directly or indirectly from the use of any part of the d&u site.


TO USE THIS WEBSITE YOU MUST AGREE TO THE TERMS AND CONDITIONS ABOVE


Founded December 2014
SimplePortal 2.3.6 © 2008-2014, SimplePortal