socksfinder logo # socksfinder [![Toolforge](https://img.shields.io/endpoint?url=https%3A%2F%2Fsocksfinder.toolforge.org%2Fbadge&label=toolforge&color=990000)](https://socksfinder.toolforge.org/) [![](https://img.shields.io/crates/v/socksfinder.svg)](https://crates.io/crates/socksfinder) [![License](https://img.shields.io/badge/license-ISC-blue.svg)](/LICENSE) [![Build status](https://travis-ci.org/Arkanosis/socksfinder.svg?branch=master)](https://travis-ci.org/Arkanosis/socksfinder) **socksfinder** is a search engine for sock puppets on Wikimedia projects. ## Usage ``` Usage: socksfinder build socksfinder query [--cooccurrences | --threshold=] [--order=] ... socksfinder serve [--hostname=] [--port=] socksfinder stats socksfinder -h | --help socksfinder --version Commands: build Build an index from a MediaWiki XML dump (read on the standard input). query Search pages modified by several users in the index. serve Start a small HTTP server to serve the index. stats Display statistics about the index. Arguments: index Index built from a MediaWiki dump. user User which has modified pages to look for. Options: --cooccurrences Show the co-occurrences matrix instead of the page names. -h, --help Show this screen. --hostname= Hostname to resolve to find the network interface to serve the index [default: localhost]. --order= Order of results, none can be faster and consume less memory [default: none]. Valid orders: none, count_decreasing, count_increasing, alphabetical. --port= Port on which to serve the index [default: 8080]. --threshold= Number of different editors, 0 for all of them [default: 0]. --version Show version. ``` ## Compiling Run `cargo build --release` in your working copy. ## Examples ### Building an index from the last dump of the French Wikipedia Building an index can take quite a while and eat a significant amount of memory (depending on the size of the dump). For the French Wikipedia, it takes about 45 minutes with a fast internet access, and consumes close to 1.5 GiB of RAM. ```console $ curl -s "https://dumps.wikimedia.org/frwiki/latest/frwiki-latest-stub-meta-history.xml.gz" | gunzip | socksfinder build frwiki-latest.idx ``` This only needs to be done once, though, and the resulting index can be redistributed to other users who don't have a fast enough internet access or a powerful enough computer. For the French Wikipedia, the index is around 700 MiB big and can be compressed quite efficiently for distribution (less than 400 MiB when compressed using `gzip --best`). ### Searching for pages modified by editors from a list Searching for pages modified by one or several editors usually requires only a very limited amount of memory (by today standards, at least), around 20 or 30 MiB of RAM. It's usually quite fast as well, around 10 to 50 milliseconds per user depending on your CPU and the number of unique modified pages, though it can take as much as a few seconds when searching for pages modified by editors who have modified several hundred thousands of distinct pages (for even faster performance, see the [server mode](#server-mode) below). ```console $ socksfinder query frwiki-latest.idx Arkanosis Arktest Arkbot Projet:Articles sans portail/1: 3 (Arkanosis, Arktest, Arkbot) Utilisateur:Arktest/test: 3 (Arkanosis, Arktest, Arkbot) ``` By default, only pages modified by all the users in the list are returned. If you want pages modified by at least some threshold, use the `--threshold` option. ```console $ socksfinder query --threshold=2 frwiki-latest.idx Arkanosis Arktest Arkbot Utilisateur:Arkbot/Ébauches dans le top 1000: 2 (Arkanosis, Arkbot) Modèle:Infobox Equipe MotoGP/Bac à sable: 2 (Arkanosis, Arktest) Projet:Articles sans portail/1: 3 (Arkanosis, Arktest, Arkbot) Aholfing: 2 (Arktest, Arkbot) [141 more lines] ``` Instead of the list of modified pages, you can get the co-occurrences matrix, that is, the matrix of the number of pages modified by each pair of editors from the list. ```console $ socksfinder query --cooccurrences frwiki-latest.idx Arkanosis Arktest Arkbot +-----------+-----------+---------+--------+ | | Arkanosis | Arktest | Arkbot | +-----------+-----------+---------+--------+ | Arkanosis | | 106 | 40 | +-----------+-----------+---------+--------+ | Arktest | 106 | | 3 | +-----------+-----------+---------+--------+ | Arkbot | 40 | 3 | | +-----------+-----------+---------+--------+ ``` ### Server mode #### Basics socksfinder can be run in server mode, which means it runs a small HTTP server to provide an HTML / plain text interface to the same features as when using the command line. ```console $ socksfinder serve --hostname=localhost --port=8697 frwiki-latest.idx ``` It can then be used either by opening the HTML interface in a web browser (eg. http://localhost:8697 in the example above), or by querying it using an HTTP client. ```console $ curl 'http://localhost:8697/query?users=Arkanosis,Arktest,Arkbot&coocurrences=true' ``` #### Advantages and downsides Server mode has the following advantages over command line usage: - users don't need to download the program; - users don't need to build or download an index; - users that don't have the time, tools or technical skills can use it; - it's even faster: finding millions of edits can take less than one second depending on your CPU. It has however the following downsides: - it requires much more memory, about the same as the size of the index (for the French Wikipedia, it requires around 800 MiB of RAM). #### Index update with zero downtime When running in server mode, it's possible to reload the index without any downtime. This is especially useful when you have built a new version of the index (for example after a new dump has been made available) and you want to switch to it without stopping the service. To reload the index, send an HTTP GET request to `/reload`. ```console $ curl 'http://localhost:8697/reload' Index reloaded ``` Reload only happens if the index has changed. ```console $ curl 'http://localhost:8697/reload' Index already up-to-date, no need to reload ``` Note that to ensure there's no downtime, socksfinder needs to keep the old index in memory until the new index has been completely loaded and all running queries have been answered. Therefore, while reloading the index, socksfinder can use as much memory as about twice the size of the index. The recommended way to perform index updates is to have a symlink to the latest index and to start socksfinder in server mode with that symlink. When there is a new version of the index available, update the symlink and request an index reload. Older indexes can then be deleted when disk space is running out. ```console $ curl 'http://localhost:8697/version' Running socksfinder v0.7.0 (frwiki-20220220) $ ls -al […] -rw-r--r-- 1 arkanosis arkanosis 763M 22 févr. 02:42 frwiki-20220220.idx -rw-r--r-- 1 arkanosis arkanosis 771M 2 mars 01:41 frwiki-20220301.idx lrwxrwxrwx 1 arkanosis arkanosis 19 22 févr. 02:45 frwiki-latest.idx -> frwiki-20220220.idx $ ln -sf frwiki-20220301.idx frwiki-latest.idx $ ls -al […] -rw-r--r-- 1 arkanosis arkanosis 763M 22 févr. 02:42 frwiki-20220220.idx -rw-r--r-- 1 arkanosis arkanosis 771M 2 mars 01:41 frwiki-20220301.idx lrwxrwxrwx 1 arkanosis arkanosis 19 2 mars 01:47 frwiki-latest.idx -> frwiki-20220301.idx $ curl 'http://localhost:8697/reload' Index reloaded $ curl 'http://localhost:8697/version' Running socksfinder v0.7.0 (frwiki-20220301) ``` #### Instance on Toolforge An instance of socksfinder is available [on Toolforge](https://socksfinder.toolforge.org/). ## Contributing and reporting bugs Contributions are welcome through [GitHub pull requests](https://github.com/Arkanosis/socksfinder/pulls). Please report bugs and feature requests on [GitHub issues](https://github.com/Arkanosis/socksfinder/issues). ## License socksfinder is copyright (C) 2020-2022 Jérémie Roquet and licensed under the ISC license.