osu-finder 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1896 @@
1
+ Metadata-Version: 2.4
2
+ Name: osu-finder
3
+ Version: 0.2.0
4
+ Summary: Automated osu! beatmap finder — local PP/SR calculation via rosu-pp-py, mod-aware filtering, and profile-based preset generation.
5
+ Author: Your Name
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/yourname/osu-finder
8
+ Project-URL: Issues, https://github.com/yourname/osu-finder/issues
9
+ Keywords: osu,beatmap,rosu-pp,rhythm-game
10
+ Classifier: Environment :: Console
11
+ Classifier: Intended Audience :: End Users/Desktop
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Topic :: Games/Entertainment
15
+ Requires-Python: >=3.10
16
+ Description-Content-Type: text/markdown
17
+ Requires-Dist: aiohttp>=3.9
18
+ Requires-Dist: PyYAML>=6.0
19
+ Requires-Dist: rosu-pp-py>=4.0
20
+ Requires-Dist: rich>=13.0
21
+
22
+ # osu-finder
23
+
24
+ <p align="center">
25
+ <strong>Asynchronous beatmap discovery powered by local performance analysis.</strong>
26
+ </p>
27
+
28
+ <p align="center">
29
+ Search • Analyze • Filter • Download
30
+ </p>
31
+
32
+ <p align="center">
33
+
34
+ [![Python](https://img.shields.io/pypi/pyversions/osu-finder.svg)](https://pypi.org/project/osu-finder/)
35
+ [![PyPI](https://img.shields.io/pypi/v/osu-finder.svg)](https://pypi.org/project/osu-finder/)
36
+ [![License](https://img.shields.io/github/license/YOUR_USERNAME/osu-finder)](LICENSE)
37
+
38
+ </p>
39
+
40
+ ---
41
+
42
+ ## Overview
43
+
44
+ **osu-finder** is an asynchronous command-line utility for discovering osu! beatmaps using **local difficulty and performance analysis** instead of relying solely on metadata provided by the official osu! API.
45
+
46
+ Unlike conventional beatmap search tools, **osu-finder** downloads only lightweight `.osu` difficulty files, analyzes them locally using **rosu-pp-py**, evaluates every configured mod combination, and keeps only beatmaps that satisfy your own performance criteria.
47
+
48
+ The project combines:
49
+
50
+ - official osu! API v2
51
+ - local star rating calculation
52
+ - local PP calculation
53
+ - automatic player profile analysis
54
+ - configurable search presets
55
+ - advanced difficulty filtering
56
+ - automatic beatmap downloading
57
+
58
+ into a single automated workflow.
59
+
60
+ ---
61
+
62
+ ## Why osu-finder?
63
+
64
+ The official osu! API provides excellent search capabilities, but it cannot answer questions such as:
65
+
66
+ - *Which ranked maps give around 240 PP with HDHR?*
67
+ - *Find DT stream maps around 300 BPM.*
68
+ - *Search only jump maps between 6.2★ and 6.8★.*
69
+ - *Download maps matching my own top plays.*
70
+ - *Ignore maps I already have installed.*
71
+ - *Evaluate multiple mod combinations before downloading.*
72
+
73
+ osu-finder fills this gap.
74
+
75
+ Instead of trusting API metadata alone, every candidate beatmap is validated locally before being accepted.
76
+
77
+ This makes searches significantly more accurate while avoiding unnecessary downloads.
78
+
79
+ ---
80
+
81
+ # Features
82
+
83
+ ## Local difficulty analysis
84
+
85
+ Instead of using the API's server-side difficulty attributes, osu-finder calculates everything locally with **rosu-pp-py**.
86
+
87
+ For every difficulty it can calculate:
88
+
89
+ - Star Rating
90
+ - Performance Points (PP)
91
+ - Aim strain
92
+ - Speed strain
93
+ - AR
94
+ - CS
95
+ - OD
96
+ - HP
97
+ - BPM (after mods)
98
+ - Length (after mods)
99
+ - Clock rate
100
+
101
+ All calculations are performed locally.
102
+
103
+ ---
104
+
105
+ ## Multi-mod analysis
106
+
107
+ Each difficulty can be evaluated using multiple mod combinations.
108
+
109
+ Example:
110
+
111
+ ```yaml
112
+ mods:
113
+ - ["NM"]
114
+ - ["DT"]
115
+ - ["HD", "HR"]
116
+ ```
117
+
118
+ A beatmap is accepted if **any configured mod combination** satisfies all advanced filters.
119
+
120
+ This allows searching for maps that are only suitable with specific mods without running multiple searches.
121
+
122
+ ---
123
+
124
+ ## Automatic profile analysis
125
+
126
+ Generate search presets directly from a player's top plays.
127
+
128
+ ```bash
129
+ osu-finder -u WhiteCat --focus jump
130
+ ```
131
+
132
+ The generated preset automatically estimates:
133
+
134
+ - preferred PP range
135
+ - star rating range
136
+ - AR range
137
+ - preferred mods
138
+ - dominant playstyle
139
+ - recommended map length
140
+
141
+ making it easy to discover maps matching a player's skill level.
142
+
143
+ ---
144
+
145
+ ## Advanced filtering
146
+
147
+ Filter beatmaps using any combination of:
148
+
149
+ - PP
150
+ - Star Rating
151
+ - BPM
152
+ - Length
153
+ - AR
154
+ - CS
155
+ - OD
156
+ - Playcount
157
+ - Playstyle
158
+
159
+ Unlike API search filters, these values are calculated after applying the selected mods whenever possible.
160
+
161
+ ---
162
+
163
+ ## Playstyle detection
164
+
165
+ osu-finder classifies beatmaps into three categories:
166
+
167
+ - Jump
168
+ - Stream
169
+ - Hybrid
170
+
171
+ The classification is based on the ratio between aim strain and speed strain calculated by **rosu-pp-py**, allowing presets to target specific mechanical skills rather than relying on star rating alone.
172
+
173
+ ---
174
+
175
+ ## Smart local cache
176
+
177
+ Before searching, osu-finder scans the local `Songs` directory and remembers every installed BeatmapSet ID.
178
+
179
+ Already installed maps are skipped automatically.
180
+
181
+ A configurable blacklist provides an additional permanent exclusion list for unwanted beatmaps.
182
+
183
+ ---
184
+
185
+ ## Automatic downloads
186
+
187
+ Accepted beatmaps can be downloaded immediately as `.osz` archives.
188
+
189
+ Optionally, downloaded files may be opened automatically, allowing the osu! client to import them without additional user interaction.
190
+
191
+ ---
192
+
193
+ ## Fully asynchronous
194
+
195
+ Network operations are implemented with **aiohttp** and **asyncio**.
196
+
197
+ The application asynchronously:
198
+
199
+ - communicates with the official osu! API
200
+ - downloads `.osu` files
201
+ - downloads `.osz` archives
202
+ - performs profile analysis
203
+
204
+ while respecting configurable request delays and API rate limits.
205
+
206
+ ---
207
+
208
+ # Design Goals
209
+
210
+ osu-finder was designed around several principles.
211
+
212
+ ## Accuracy over metadata
213
+
214
+ Every beatmap is verified locally before being accepted.
215
+
216
+ Search results depend on actual calculated difficulty attributes rather than incomplete API metadata.
217
+
218
+ ---
219
+
220
+ ## Automation
221
+
222
+ Common workflows should require as little manual work as possible.
223
+
224
+ Searching, analyzing, filtering and downloading beatmaps should happen in a single command whenever possible.
225
+
226
+ ---
227
+
228
+ ## Reproducibility
229
+
230
+ Searches are stored as YAML presets.
231
+
232
+ Once a preset is created, the same search can be reproduced at any time.
233
+
234
+ ---
235
+
236
+ ## Extensibility
237
+
238
+ The project separates:
239
+
240
+ - global configuration
241
+ - search presets
242
+ - profile analysis
243
+ - API communication
244
+ - local PP analysis
245
+ - downloading
246
+
247
+ making it straightforward to extend individual components independently.
248
+
249
+ ---
250
+
251
+ # Installation
252
+
253
+ ## Requirements
254
+
255
+ Before installing **osu-finder**, make sure you have:
256
+
257
+ - Python **3.10** or newer
258
+ - An **osu! API v2 OAuth application**
259
+ - An installed osu! client (optional, for automatic beatmap importing)
260
+ - Internet access to the osu! API and the configured beatmap mirror
261
+
262
+ Supported operating systems:
263
+
264
+ - Windows
265
+ - Linux
266
+ - macOS
267
+
268
+ ---
269
+
270
+ ## Install from PyPI
271
+
272
+ ```bash
273
+ pipx install osu-finder
274
+ ```
275
+
276
+ Verify the installation:
277
+
278
+ ```bash
279
+ osu-finder --help
280
+ ```
281
+
282
+ ---
283
+
284
+ ## Install from source
285
+
286
+ Clone the repository:
287
+
288
+ ```bash
289
+ git clone https://github.com/YOUR_USERNAME/osu-finder.git
290
+ cd osu-finder
291
+ ```
292
+
293
+ Install the package:
294
+
295
+ ```bash
296
+ pipx install .
297
+ ```
298
+
299
+ For development:
300
+
301
+ ```bash
302
+ pipx install -e .
303
+ ```
304
+
305
+ ---
306
+
307
+ # Getting Started
308
+
309
+ The recommended first-time setup consists of four simple steps:
310
+
311
+ 1. Create an osu! OAuth application.
312
+ 2. Initialize the global configuration.
313
+ 3. Create a search preset.
314
+ 4. Run your first search.
315
+
316
+ The following sections explain each step.
317
+
318
+ ---
319
+
320
+ # Step 1 — Create an OAuth Application
321
+
322
+ osu-finder communicates with the official **osu! API v2** using the **Client Credentials Grant** flow.
323
+
324
+ Only public API access is required.
325
+
326
+ Open:
327
+
328
+ https://osu.ppy.sh/home/account/edit#oauth
329
+
330
+ Create a new OAuth application.
331
+
332
+ Example:
333
+
334
+ ```
335
+ Application Name:
336
+ osu-finder
337
+
338
+ Callback URL:
339
+ (empty)
340
+ ```
341
+
342
+ After creating the application you will receive:
343
+
344
+ - Client ID
345
+ - Client Secret
346
+
347
+ These credentials will later be stored inside your global configuration file.
348
+
349
+ > **Note**
350
+ >
351
+ > osu-finder never performs user authentication.
352
+ >
353
+ > No browser login flow is required.
354
+ >
355
+ > Only public API endpoints are accessed.
356
+
357
+ ---
358
+
359
+ # Step 2 — Initialize Configuration
360
+
361
+ Run:
362
+
363
+ ```bash
364
+ osu-finder --init
365
+ ```
366
+
367
+ The interactive wizard creates a new configuration file and guides you through all required settings.
368
+
369
+ Typical questions include:
370
+
371
+ - osu! Client ID
372
+ - osu! Client Secret
373
+ - Songs directory
374
+ - Download directory
375
+ - Beatmap mirror
376
+ - Network configuration
377
+
378
+ After completion your project directory will contain:
379
+
380
+ ```
381
+ config.yaml
382
+ presets/
383
+ ```
384
+
385
+ ---
386
+
387
+ # Global Configuration
388
+
389
+ The global configuration stores settings shared by every preset.
390
+
391
+ Typical structure:
392
+
393
+ ```
394
+ config.yaml
395
+ ```
396
+
397
+ Responsibilities include:
398
+
399
+ - OAuth credentials
400
+ - filesystem paths
401
+ - download directory
402
+ - beatmap mirror
403
+ - proxy configuration
404
+ - blacklist
405
+ - default preset
406
+
407
+ Unlike search presets, these values rarely change.
408
+
409
+ ---
410
+
411
+ # Directory Layout
412
+
413
+ A typical working directory looks like:
414
+
415
+ ```text
416
+ osu-finder/
417
+
418
+ ├── config.yaml
419
+ ├── presets/
420
+ │ ├── default.yaml
421
+ │ ├── stream.yaml
422
+ │ ├── farm.yaml
423
+ │ └── tournament.yaml
424
+ | └── user_mrekk_push.yaml
425
+ │
426
+ ├── downloads/
427
+ │ ├── ...
428
+ │
429
+ └── logs/
430
+ ```
431
+
432
+ Only **config.yaml** is global.
433
+
434
+ Every search configuration lives inside the **presets/** directory.
435
+
436
+ ---
437
+
438
+ # Step 3 — Create a Preset
439
+
440
+ A preset describes **what kinds of beatmaps should be searched for**.
441
+
442
+ There are two ways to create one.
443
+
444
+ ## Interactive
445
+
446
+ ```bash
447
+ osu-finder --create-preset
448
+ ```
449
+
450
+ The CLI asks for all required parameters and writes a ready-to-use YAML preset.
451
+
452
+ ---
453
+
454
+ ## Automatic
455
+
456
+ A preset can also be generated directly from a player's top plays.
457
+
458
+ Example:
459
+
460
+ ```bash
461
+ osu-finder -u WhiteCat
462
+ ```
463
+
464
+ Or specify a particular training focus:
465
+
466
+ ```bash
467
+ osu-finder -u WhiteCat --focus stream
468
+ ```
469
+
470
+ Available focus modes include:
471
+
472
+ - balanced
473
+ - jump
474
+ - stream
475
+ - push
476
+ - farm
477
+
478
+ The generated preset estimates:
479
+
480
+ - preferred PP range
481
+ - star range
482
+ - AR range
483
+ - preferred mods
484
+ - dominant playstyle
485
+ - recommended map length
486
+
487
+ based on the analyzed profile.
488
+
489
+ ---
490
+
491
+ # Step 4 — Run Your First Search
492
+
493
+ If you have a default preset configured:
494
+
495
+ ```bash
496
+ osu-finder
497
+ ```
498
+
499
+ or
500
+
501
+ ```bash
502
+ osu-finder --run-search
503
+ ```
504
+
505
+ To use a specific preset:
506
+
507
+ ```bash
508
+ osu-finder --preset stream
509
+ ```
510
+
511
+ The application will:
512
+
513
+ 1. Load the global configuration.
514
+ 2. Load the selected preset.
515
+ 3. Authenticate with the osu! API.
516
+ 4. Scan the local Songs directory.
517
+ 5. Search beatmapsets.
518
+ 6. Download candidate `.osu` files.
519
+ 7. Perform local difficulty analysis.
520
+ 8. Apply advanced filters.
521
+ 9. Download matching beatmaps.
522
+ 10. Optionally open every downloaded `.osz` file.
523
+
524
+ No manual interaction is required after the search starts.
525
+
526
+ ---
527
+
528
+ # Search Pipeline
529
+
530
+ A simplified overview of the complete workflow:
531
+
532
+ ```text
533
+ Load Configuration
534
+ │
535
+ ▼
536
+ Authenticate
537
+ │
538
+ ▼
539
+ Scan Local Songs Folder
540
+ │
541
+ ▼
542
+ Search Beatmapsets
543
+ │
544
+ ▼
545
+ Download .osu Files
546
+ │
547
+ ▼
548
+ Calculate Difficulty
549
+ │
550
+ ▼
551
+ Apply Advanced Filters
552
+ │
553
+ ▼
554
+ Accepted?
555
+ │ │
556
+ │ No │ Yes
557
+ ▼ ▼
558
+ Skip Download.osz
559
+ │
560
+ ▼
561
+ Optionally Open in osu!
562
+ ```
563
+
564
+ Every difficulty is analyzed locally before any beatmap archive is downloaded.
565
+
566
+ This minimizes unnecessary downloads while ensuring that search results satisfy the configured filters.
567
+
568
+ ---
569
+
570
+ # Typical Workflows
571
+
572
+ ## Find comfortable maps
573
+
574
+ ```bash
575
+ osu-finder --preset comfort
576
+ ```
577
+
578
+ Searches for beatmaps matching an existing preset.
579
+
580
+ ---
581
+
582
+ ## Practice streams
583
+
584
+ ```bash
585
+ osu-finder --preset stream
586
+ ```
587
+
588
+ Returns beatmaps matching stream-oriented filters.
589
+
590
+ ---
591
+
592
+ ## Improve aim
593
+
594
+ ```bash
595
+ osu-finder --preset jump
596
+ ```
597
+
598
+ Searches primarily for jump-heavy maps.
599
+
600
+ ---
601
+
602
+ ## Build a preset from your profile
603
+
604
+ ```bash
605
+ osu-finder -u YourUsername
606
+ ```
607
+
608
+ Automatically creates a preset based on your top plays.
609
+
610
+ ---
611
+
612
+ ## Generate a push preset
613
+
614
+ ```bash
615
+ osu-finder -u YourUsername --focus push
616
+ ```
617
+
618
+ Creates a preset targeting more difficult maps than your current comfort range.
619
+
620
+ ---
621
+
622
+ ## Download maps only once
623
+
624
+ Already installed BeatmapSet IDs are detected automatically.
625
+
626
+ Duplicate downloads are skipped without requiring any user action.
627
+
628
+ # Configuration
629
+
630
+ osu-finder separates configuration into two independent layers:
631
+
632
+ | File | Purpose |
633
+ |------|----------|
634
+ | `config.yaml` | Global application settings |
635
+ | `presets/<name>.yaml` | Individual search configuration |
636
+
637
+ This separation allows multiple search presets to reuse the same credentials, filesystem paths, mirror configuration and network settings.
638
+
639
+ ---
640
+
641
+ # Global Configuration (`config.yaml`)
642
+
643
+ The global configuration contains settings that are shared by every search preset.
644
+
645
+ A minimal configuration looks like this:
646
+
647
+ ```yaml
648
+ credentials:
649
+ client_id: "12345"
650
+ client_secret: YOUR_CLIENT_SECRET
651
+
652
+ paths:
653
+ songs_folder: C:\osu!\Songs
654
+ download_folder: downloads
655
+
656
+ mirror:
657
+ base_url: https://osu.direct
658
+ osu_file_path: /api/osu/{id}
659
+ osz_download_path: /api/d/{id}
660
+
661
+ blacklist: []
662
+
663
+ network:
664
+ proxy_url: null
665
+ fallback_to_direct: true
666
+
667
+ active_preset: default
668
+ ```
669
+
670
+ ---
671
+
672
+ # credentials
673
+
674
+ ```yaml
675
+ credentials:
676
+ client_id: "12345"
677
+ client_secret: YOUR_CLIENT_SECRET
678
+ ```
679
+
680
+ OAuth credentials used to authenticate with the official osu! API.
681
+
682
+ Both values are obtained by creating an OAuth application in your osu! account.
683
+
684
+ These credentials are required before any search can be performed.
685
+
686
+ ---
687
+
688
+ # paths
689
+
690
+ ```yaml
691
+ paths:
692
+ songs_folder: C:\osu!\Songs
693
+ download_folder: downloads
694
+ ```
695
+
696
+ ## songs_folder
697
+
698
+ Path to your local osu! Songs directory.
699
+
700
+ Before every search, osu-finder scans this directory and extracts BeatmapSet IDs from folder names.
701
+
702
+ Already installed beatmaps are skipped automatically.
703
+
704
+ If the directory does not exist, searching still works, but duplicate detection is disabled.
705
+
706
+ ---
707
+
708
+ ## download_folder
709
+
710
+ Destination directory for downloaded `.osz` archives.
711
+
712
+ The directory is created automatically if it does not already exist.
713
+
714
+ ---
715
+
716
+ # mirror
717
+
718
+ ```yaml
719
+ mirror:
720
+ base_url: https://osu.direct
721
+ osu_file_path: /api/osu/{id}
722
+ osz_download_path: /api/d/{id}
723
+ ```
724
+
725
+ The official osu! API does not provide anonymous beatmap file downloads.
726
+
727
+ Instead, osu-finder downloads beatmap files from a configurable mirror.
728
+
729
+ The mirror configuration consists of three parts.
730
+
731
+ ---
732
+
733
+ ## base_url
734
+
735
+ Example:
736
+
737
+ ```yaml
738
+ base_url: https://osu.direct
739
+ ```
740
+
741
+ Root URL of the mirror.
742
+
743
+ ---
744
+
745
+ ## osu_file_path
746
+
747
+ Example:
748
+
749
+ ```yaml
750
+ osu_file_path: /api/osu/{id}
751
+ ```
752
+
753
+ Path used when downloading individual `.osu` difficulty files.
754
+
755
+ `{id}` is automatically replaced with the beatmap difficulty ID.
756
+
757
+ These files are used only for local difficulty analysis.
758
+
759
+ ---
760
+
761
+ ## osz_download_path
762
+
763
+ Example:
764
+
765
+ ```yaml
766
+ osz_download_path: /api/d/{id}
767
+ ```
768
+
769
+ Path used when downloading complete `.osz` beatmap archives.
770
+
771
+ `{id}` is replaced with the BeatmapSet ID.
772
+
773
+ ---
774
+
775
+ # blacklist
776
+
777
+ ```yaml
778
+ blacklist:
779
+ - 123456
780
+ - 654321
781
+ ```
782
+
783
+ A list of BeatmapSet IDs that should never be downloaded.
784
+
785
+ Blacklisted maps are skipped before any analysis is performed.
786
+
787
+ The blacklist works together with the local Songs cache.
788
+
789
+ A beatmap is skipped if it is:
790
+
791
+ - already installed locally;
792
+ - explicitly blacklisted.
793
+
794
+ ---
795
+
796
+ # network
797
+
798
+ ```yaml
799
+ network:
800
+ proxy_url: null
801
+ fallback_to_direct: true
802
+ ```
803
+
804
+ Network-related options.
805
+
806
+ ---
807
+
808
+ ## proxy_url
809
+
810
+ Example:
811
+
812
+ ```yaml
813
+ proxy_url: http://user:password@host:port
814
+ ```
815
+
816
+ Optional HTTP/HTTPS proxy used for:
817
+
818
+ - API requests
819
+ - `.osu` downloads
820
+ - `.osz` downloads
821
+
822
+ SOCKS proxies are currently not supported.
823
+
824
+ ---
825
+
826
+ ## fallback_to_direct
827
+
828
+ ```yaml
829
+ fallback_to_direct: true
830
+ ```
831
+
832
+ When enabled, failed proxy requests are retried without using the proxy.
833
+
834
+ This provides improved reliability when using unstable proxy servers.
835
+
836
+ ---
837
+
838
+ # active_preset
839
+
840
+ ```yaml
841
+ active_preset: default
842
+ ```
843
+
844
+ Specifies which preset should be used when `--preset` is not supplied.
845
+
846
+ Example:
847
+
848
+ ```bash
849
+ osu-finder
850
+ ```
851
+
852
+ is equivalent to
853
+
854
+ ```bash
855
+ osu-finder --preset default
856
+ ```
857
+
858
+ ---
859
+
860
+ # Search Presets
861
+
862
+ Unlike `config.yaml`, presets define **how beatmaps are searched**.
863
+
864
+ Each preset is completely independent.
865
+
866
+ Example directory:
867
+
868
+ ```text
869
+ presets/
870
+
871
+ default.yaml
872
+ stream.yaml
873
+ farm.yaml
874
+ jump.yaml
875
+ tournament.yaml
876
+ ```
877
+
878
+ Switching between presets does not require modifying the global configuration.
879
+
880
+ ---
881
+
882
+ # Preset Structure
883
+
884
+ A preset consists of four independent sections.
885
+
886
+ ```yaml
887
+ mods:
888
+
889
+ base_filters:
890
+
891
+ advanced_filters:
892
+
893
+ execution:
894
+ ```
895
+
896
+ Each section controls a different stage of the search pipeline.
897
+
898
+ ---
899
+
900
+ # mods
901
+
902
+ Example:
903
+
904
+ ```yaml
905
+ mods:
906
+ - ["NM"]
907
+ - ["DT"]
908
+ - ["HD", "HR"]
909
+ ```
910
+
911
+ This is one of the most important parts of the configuration.
912
+
913
+ Every beatmap difficulty is analyzed once **for each configured mod combination**.
914
+
915
+ Example:
916
+
917
+ ```
918
+ NM
919
+ DT
920
+ HDHR
921
+ ```
922
+
923
+ produces three independent analyses.
924
+
925
+ A beatmap is accepted if **at least one** mod combination satisfies all advanced filters.
926
+
927
+ This allows a single search to simultaneously evaluate multiple play styles.
928
+
929
+ ---
930
+
931
+ # base_filters
932
+
933
+ Base filters are sent directly to the official osu! API.
934
+
935
+ They reduce the number of beatmaps that must be analyzed locally.
936
+
937
+ Unlike advanced filters, these values are evaluated before downloading any `.osu` files.
938
+
939
+ ---
940
+
941
+ ## mode
942
+
943
+ ```yaml
944
+ mode: osu
945
+ ```
946
+
947
+ Supported values:
948
+
949
+ - osu
950
+ - taiko
951
+ - fruits
952
+ - mania
953
+
954
+ ---
955
+
956
+ ## status
957
+
958
+ ```yaml
959
+ status: ranked
960
+ ```
961
+
962
+ Available values:
963
+
964
+ - ranked
965
+ - qualified
966
+ - loved
967
+ - pending
968
+ - graveyard
969
+ - any
970
+
971
+ ---
972
+
973
+ ## keywords
974
+
975
+ ```yaml
976
+ keywords: camellia
977
+ ```
978
+
979
+ Performs a text search against beatmap metadata.
980
+
981
+ Typical use cases include:
982
+
983
+ - artist
984
+ - title
985
+ - mapper
986
+ - tags
987
+
988
+ Leave empty to disable keyword filtering.
989
+
990
+ ---
991
+
992
+ ## genre
993
+
994
+ ```yaml
995
+ genre: 3
996
+ ```
997
+
998
+ Optional numeric genre identifier used by the osu! website.
999
+
1000
+ Set to `null` to disable.
1001
+
1002
+ ---
1003
+
1004
+ ## language
1005
+
1006
+ ```yaml
1007
+ language: 2
1008
+ ```
1009
+
1010
+ Optional language identifier.
1011
+
1012
+ Set to `null` to search all languages.
1013
+
1014
+ ---
1015
+
1016
+ ## sort
1017
+
1018
+ Example:
1019
+
1020
+ ```yaml
1021
+ sort: ranked_desc
1022
+ ```
1023
+
1024
+ Determines the order in which beatmaps are returned by the API.
1025
+
1026
+ Common choices include:
1027
+
1028
+ - ranked_desc
1029
+ - ranked_asc
1030
+ - difficulty_desc
1031
+ - difficulty_asc
1032
+
1033
+ The selected order can significantly affect how quickly suitable maps are found.
1034
+
1035
+ # Advanced Filters
1036
+
1037
+ Unlike **base filters**, advanced filters are evaluated **after** downloading and analyzing each individual beatmap difficulty.
1038
+
1039
+ This is where osu-finder differs from conventional beatmap search tools.
1040
+
1041
+ Instead of filtering using API metadata, osu-finder performs a complete local difficulty analysis using **rosu-pp-py**, calculates all requested attributes for every configured mod combination, and only then decides whether a beatmap should be accepted.
1042
+
1043
+ Because of this, filters such as PP, AR, BPM and map length always reflect the selected mods.
1044
+
1045
+ ---
1046
+
1047
+ # Evaluation Pipeline
1048
+
1049
+ For every beatmap difficulty the following steps are performed:
1050
+
1051
+ ```
1052
+ Download .osu
1053
+ │
1054
+ ▼
1055
+ Parse beatmap
1056
+ │
1057
+ ▼
1058
+ Apply mod combination
1059
+ │
1060
+ ▼
1061
+ Calculate difficulty
1062
+ │
1063
+ ▼
1064
+ Calculate PP
1065
+ │
1066
+ ▼
1067
+ Calculate beatmap attributes
1068
+ │
1069
+ ▼
1070
+ Apply Advanced Filters
1071
+ │
1072
+ ▼
1073
+ Accept or Reject
1074
+ ```
1075
+
1076
+ If several mod combinations are configured, the entire pipeline is repeated for each one.
1077
+
1078
+ A difficulty is accepted if **any** configuration satisfies every enabled filter.
1079
+
1080
+ ---
1081
+
1082
+ # PP Filter
1083
+
1084
+ ```yaml
1085
+ pp:
1086
+ min: 220
1087
+ max: 320
1088
+ accuracy: 99.0
1089
+ ```
1090
+
1091
+ The PP filter limits beatmaps by the calculated performance value.
1092
+
1093
+ Unlike the osu! website, PP is not taken from the API.
1094
+
1095
+ Instead, it is calculated locally for every difficulty using **rosu-pp-py**.
1096
+
1097
+ This guarantees that the result always matches the configured mod combination.
1098
+
1099
+ ---
1100
+
1101
+ ## accuracy
1102
+
1103
+ ```yaml
1104
+ accuracy: 99.0
1105
+ ```
1106
+
1107
+ PP depends on player accuracy.
1108
+
1109
+ osu-finder therefore requires a reference accuracy when calculating performance.
1110
+
1111
+ Examples:
1112
+
1113
+ | Accuracy | Interpretation |
1114
+ |-----------|---------------|
1115
+ | 95% | Low consistency |
1116
+ | 98% | Typical score |
1117
+ | 99% | Stable full combo |
1118
+ | 100% | Perfect play |
1119
+
1120
+ Changing this value affects only PP calculations.
1121
+
1122
+ It does **not** influence any other filters.
1123
+
1124
+ ---
1125
+
1126
+ # Star Rating
1127
+
1128
+ ```yaml
1129
+ star_rating:
1130
+ min: 5.8
1131
+ max: 6.5
1132
+ ```
1133
+
1134
+ Limits beatmaps by calculated star rating.
1135
+
1136
+ Stars are computed locally after applying the selected mods.
1137
+
1138
+ For example:
1139
+
1140
+ - DT usually increases star rating.
1141
+ - HR often increases star rating.
1142
+ - EZ generally decreases star rating.
1143
+
1144
+ The calculated value is therefore more accurate than relying on metadata alone.
1145
+
1146
+ ---
1147
+
1148
+ # BPM
1149
+
1150
+ ```yaml
1151
+ bpm:
1152
+ min: 180
1153
+ max: 260
1154
+ ```
1155
+
1156
+ Filters beatmaps by effective BPM.
1157
+
1158
+ Clock-changing mods are fully supported.
1159
+
1160
+ Examples:
1161
+
1162
+ | Mods | Result |
1163
+ |------|--------|
1164
+ | NM | Original BPM |
1165
+ | DT | Increased BPM |
1166
+ | HT | Reduced BPM |
1167
+
1168
+ Example:
1169
+
1170
+ ```
1171
+ Original BPM: 180
1172
+
1173
+ DT
1174
+
1175
+ Effective BPM: 270
1176
+ ```
1177
+
1178
+ The BPM filter always evaluates the effective gameplay speed.
1179
+
1180
+ ---
1181
+
1182
+ # Length
1183
+
1184
+ ```yaml
1185
+ length:
1186
+ min: 90
1187
+ max: 180
1188
+ ```
1189
+
1190
+ Filters beatmaps by playable drain time.
1191
+
1192
+ Clock-changing mods affect map duration.
1193
+
1194
+ For example:
1195
+
1196
+ | Mods | Effective Length |
1197
+ |------|------------------|
1198
+ | NM | Original length |
1199
+ | DT | Shorter |
1200
+ | HT | Longer |
1201
+
1202
+ Example:
1203
+
1204
+ ```
1205
+ Original length
1206
+
1207
+ 180 seconds
1208
+
1209
+ DT
1210
+
1211
+ 120 seconds
1212
+ ```
1213
+
1214
+ This makes it possible to search specifically for short practice maps or longer endurance maps.
1215
+
1216
+ ---
1217
+
1218
+ # AR
1219
+
1220
+ ```yaml
1221
+ ar:
1222
+ min: 9.4
1223
+ max: 10.3
1224
+ ```
1225
+
1226
+ Approach Rate is calculated locally after applying mods.
1227
+
1228
+ Examples:
1229
+
1230
+ | Mods | Effect |
1231
+ |------|---------|
1232
+ | HR | Higher AR |
1233
+ | EZ | Lower AR |
1234
+ | DT | Faster approach timing |
1235
+ | HT | Slower approach timing |
1236
+
1237
+ Because osu-finder evaluates AR after applying mods, searches remain accurate even for mixed mod configurations.
1238
+
1239
+ ---
1240
+
1241
+ # CS
1242
+
1243
+ ```yaml
1244
+ cs:
1245
+ min: 4
1246
+ max: 5
1247
+ ```
1248
+
1249
+ Circle Size filtering is also performed after mod adjustments.
1250
+
1251
+ Examples:
1252
+
1253
+ - HR increases CS.
1254
+ - EZ decreases CS.
1255
+
1256
+ No manual calculations are required.
1257
+
1258
+ ---
1259
+
1260
+ # OD
1261
+
1262
+ ```yaml
1263
+ od:
1264
+ min: 8
1265
+ max: 10
1266
+ ```
1267
+
1268
+ Overall Difficulty is calculated after applying mods.
1269
+
1270
+ This allows searches such as:
1271
+
1272
+ > Find DT maps with OD between 9.5 and 10.3.
1273
+
1274
+ without relying on approximate API values.
1275
+
1276
+ ---
1277
+
1278
+ # Playcount
1279
+
1280
+ ```yaml
1281
+ playcount:
1282
+ min: 5000
1283
+ ```
1284
+
1285
+ Unlike most advanced filters, playcount comes directly from the beatmap metadata.
1286
+
1287
+ It represents overall popularity rather than difficulty.
1288
+
1289
+ Common uses include:
1290
+
1291
+ - avoiding obscure maps
1292
+ - finding hidden gems
1293
+ - searching only widely played beatmaps
1294
+
1295
+ Playcount is evaluated per BeatmapSet.
1296
+
1297
+ ---
1298
+
1299
+ # Playstyle Detection
1300
+
1301
+ ```yaml
1302
+ playstyle:
1303
+ type: jump
1304
+ threshold: 1.15
1305
+ ```
1306
+
1307
+ osu-finder automatically classifies every analyzed difficulty into one of three playstyles.
1308
+
1309
+ - Jump
1310
+ - Stream
1311
+ - Hybrid
1312
+
1313
+ The classification is based on the relationship between **aim strain** and **speed strain** calculated by **rosu-pp-py**.
1314
+
1315
+ ---
1316
+
1317
+ ## Classification Formula
1318
+
1319
+ ```
1320
+ ratio = speed_strain / aim_strain
1321
+ ```
1322
+
1323
+ Using the configured threshold:
1324
+
1325
+ ```
1326
+ ratio >= threshold
1327
+ ```
1328
+
1329
+ ↓
1330
+
1331
+ ```
1332
+ Stream
1333
+ ```
1334
+
1335
+ ```
1336
+ ratio <= 1 / threshold
1337
+ ```
1338
+
1339
+ ↓
1340
+
1341
+ ```
1342
+ Jump
1343
+ ```
1344
+
1345
+ Otherwise:
1346
+
1347
+ ```
1348
+ Hybrid
1349
+ ```
1350
+
1351
+ ---
1352
+
1353
+ ## Why This Matters
1354
+
1355
+ Traditional beatmap searches usually rely on star rating alone.
1356
+
1357
+ However, two beatmaps with identical star ratings may require completely different mechanical skills.
1358
+
1359
+ For example:
1360
+
1361
+ ```
1362
+ 6.3★
1363
+
1364
+ Fast streams
1365
+ ```
1366
+
1367
+ and
1368
+
1369
+ ```
1370
+ 6.3★
1371
+
1372
+ Wide jumps
1373
+ ```
1374
+
1375
+ are fundamentally different despite sharing the same star rating.
1376
+
1377
+ Playstyle filtering enables searches based on mechanical characteristics instead of overall difficulty.
1378
+
1379
+ ---
1380
+
1381
+ # execution
1382
+
1383
+ The final section of every preset controls search execution itself.
1384
+
1385
+ Unlike previous sections, these values do **not** influence beatmap selection.
1386
+
1387
+ Instead, they define how the search process behaves.
1388
+
1389
+ Example:
1390
+
1391
+ ```yaml
1392
+ execution:
1393
+ target_count: 20
1394
+ auto_open: true
1395
+ max_pages: 50
1396
+ request_delay: 1.0
1397
+ ```
1398
+
1399
+ ---
1400
+
1401
+ ## target_count
1402
+
1403
+ ```yaml
1404
+ target_count: 20
1405
+ ```
1406
+
1407
+ Stops searching after the requested number of matching beatmaps has been found.
1408
+
1409
+ Larger values increase search time.
1410
+
1411
+ ---
1412
+
1413
+ ## auto_open
1414
+
1415
+ ```yaml
1416
+ auto_open: true
1417
+ ```
1418
+
1419
+ When enabled, downloaded `.osz` files are opened automatically using the operating system.
1420
+
1421
+ This triggers normal beatmap importing in an installed osu! client.
1422
+
1423
+ ---
1424
+
1425
+ ## max_pages
1426
+
1427
+ ```yaml
1428
+ max_pages: 50
1429
+ ```
1430
+
1431
+ Limits how many pages are requested from the official osu! API.
1432
+
1433
+ This prevents extremely broad searches from running indefinitely.
1434
+
1435
+ Increasing the value improves search coverage at the cost of additional API requests.
1436
+
1437
+ ---
1438
+
1439
+ ## request_delay
1440
+
1441
+ ```yaml
1442
+ request_delay: 1.0
1443
+ ```
1444
+
1445
+ Delay between consecutive requests to the official API.
1446
+
1447
+ This value helps avoid unnecessary rate limiting while remaining respectful to the osu! API infrastructure.
1448
+
1449
+ Most users should leave the default unchanged.
1450
+
1451
+ ---
1452
+
1453
+ # Recommended Preset Examples
1454
+
1455
+ ## Comfortable Practice
1456
+
1457
+ ```yaml
1458
+ pp:
1459
+ min: 180
1460
+ max: 240
1461
+
1462
+ star_rating:
1463
+ min: 5.5
1464
+ max: 6.2
1465
+ ```
1466
+
1467
+ Suitable for consistent practice sessions.
1468
+
1469
+ ---
1470
+
1471
+ ## Rank Push
1472
+
1473
+ ```yaml
1474
+ pp:
1475
+ min: 260
1476
+ max: 340
1477
+
1478
+ star_rating:
1479
+ min: 6.4
1480
+ max: 7.2
1481
+ ```
1482
+
1483
+ Targets maps slightly above the current comfort zone.
1484
+
1485
+ ---
1486
+
1487
+ ## Stream Practice
1488
+
1489
+ ```yaml
1490
+ playstyle:
1491
+ type: stream
1492
+
1493
+ length:
1494
+ min: 120
1495
+
1496
+ bpm:
1497
+ min: 190
1498
+ ```
1499
+
1500
+ Focuses on longer stream-oriented beatmaps.
1501
+
1502
+ ---
1503
+
1504
+ ## Farm Maps
1505
+
1506
+ ```yaml
1507
+ playstyle:
1508
+ type: jump
1509
+
1510
+ length:
1511
+ max: 140
1512
+ ```
1513
+
1514
+ Optimized for shorter jump-heavy maps that are commonly used for PP farming.
1515
+
1516
+ # Command Line Interface
1517
+
1518
+ osu-finder is designed around a small number of commands that cover the entire workflow.
1519
+
1520
+ Most users will only need a few of them during regular usage.
1521
+
1522
+ The typical lifecycle is:
1523
+
1524
+ ```
1525
+
1526
+ Initialize → Create Preset → Search → Download
1527
+
1528
+ ```
1529
+
1530
+ Advanced users can additionally generate presets from player profiles, manage blacklists, or switch between multiple search configurations.
1531
+
1532
+ ---
1533
+
1534
+ # Command Overview
1535
+
1536
+ | Command | Description |
1537
+ |----------|-------------|
1538
+ | `osu-finder` | Run a search using the active preset |
1539
+ | `osu-finder --run-search` | Explicitly start a search |
1540
+ | `osu-finder --preset <name>` | Use a specific preset |
1541
+ | `osu-finder --init` | Create the global configuration |
1542
+ | `osu-finder --create-preset` | Create a preset interactively |
1543
+ | `osu-finder -u <user>` | Generate a preset from a player's profile |
1544
+ | `osu-finder --ban <beatmapset_id>` | Add a BeatmapSet to the blacklist |
1545
+ | `osu-finder --help` | Display command help |
1546
+
1547
+ ---
1548
+
1549
+ # Running Searches
1550
+
1551
+ ## Default preset
1552
+
1553
+ If an active preset is configured:
1554
+
1555
+ ```bash
1556
+ osu-finder
1557
+ ```
1558
+
1559
+ or
1560
+
1561
+ ```bash
1562
+ osu-finder --run-search
1563
+ ```
1564
+
1565
+ Both commands perform exactly the same search.
1566
+
1567
+ The active preset is loaded from:
1568
+
1569
+ ```yaml
1570
+ active_preset: default
1571
+ ```
1572
+
1573
+ inside `config.yaml`.
1574
+
1575
+ ---
1576
+
1577
+ ## Using another preset
1578
+
1579
+ ```bash
1580
+ osu-finder --preset stream
1581
+ ```
1582
+
1583
+ Loads:
1584
+
1585
+ ```
1586
+ presets/stream.yaml
1587
+ ```
1588
+
1589
+ instead of the active preset.
1590
+
1591
+ This allows multiple search profiles without modifying the global configuration.
1592
+
1593
+ Example:
1594
+
1595
+ ```bash
1596
+ osu-finder --preset tournament
1597
+ ```
1598
+
1599
+ ```bash
1600
+ osu-finder --preset dt
1601
+ ```
1602
+
1603
+ ```bash
1604
+ osu-finder --preset farm
1605
+ ```
1606
+
1607
+ ---
1608
+
1609
+ # Initial Setup
1610
+
1611
+ ## Interactive initialization
1612
+
1613
+ ```bash
1614
+ osu-finder --init
1615
+ ```
1616
+
1617
+ Creates the initial configuration and guides the user through:
1618
+
1619
+ - OAuth credentials
1620
+ - osu! Songs directory
1621
+ - download directory
1622
+ - mirror configuration
1623
+ - network options
1624
+
1625
+ This command usually only needs to be executed once.
1626
+
1627
+ ---
1628
+
1629
+ # Preset Management
1630
+
1631
+ ## Create a new preset
1632
+
1633
+ ```bash
1634
+ osu-finder --create-preset
1635
+ ```
1636
+
1637
+ The interactive wizard asks for:
1638
+
1639
+ - base filters
1640
+ - advanced filters
1641
+ - execution settings
1642
+ - mod combinations
1643
+
1644
+ A new YAML file is then created inside:
1645
+
1646
+ ```
1647
+ presets/
1648
+ ```
1649
+
1650
+ ---
1651
+
1652
+ ## Edit an existing preset
1653
+
1654
+ Presets are ordinary YAML files.
1655
+
1656
+ They can be edited using any text editor.
1657
+
1658
+ For example:
1659
+
1660
+ ```
1661
+ presets/default.yaml
1662
+ ```
1663
+
1664
+ ```
1665
+ presets/stream.yaml
1666
+ ```
1667
+
1668
+ ```
1669
+ presets/farm.yaml
1670
+ ```
1671
+
1672
+ No special command is required.
1673
+
1674
+ ---
1675
+
1676
+ # Profile Analysis
1677
+
1678
+ One of osu-finder's most powerful features is automatic preset generation from player profiles.
1679
+
1680
+ Example:
1681
+
1682
+ ```bash
1683
+ osu-finder -u WhiteCat
1684
+ ```
1685
+
1686
+ The application will:
1687
+
1688
+ 1. Resolve the player's user ID.
1689
+ 2. Download their top plays.
1690
+ 3. Analyze every beatmap locally.
1691
+ 4. Calculate statistical ranges.
1692
+ 5. Generate a new search preset.
1693
+
1694
+ The resulting preset can immediately be used for future searches.
1695
+
1696
+ ---
1697
+
1698
+ ## Using Numeric User IDs
1699
+
1700
+ Instead of a username, a numeric user ID may also be provided.
1701
+
1702
+ Example:
1703
+
1704
+ ```bash
1705
+ osu-finder -u 7562902
1706
+ ```
1707
+
1708
+ Both forms are supported.
1709
+
1710
+ ---
1711
+
1712
+ # Focus Modes
1713
+
1714
+ The generated preset depends on the selected focus mode.
1715
+
1716
+ ## balanced
1717
+
1718
+ ```bash
1719
+ osu-finder -u WhiteCat --focus balanced
1720
+ ```
1721
+
1722
+ Creates a general-purpose preset centered around the player's typical performance.
1723
+
1724
+ Recommended for most users.
1725
+
1726
+ ---
1727
+
1728
+ ## jump
1729
+
1730
+ ```bash
1731
+ osu-finder -u WhiteCat --focus jump
1732
+ ```
1733
+
1734
+ Prioritizes jump-oriented maps.
1735
+
1736
+ Typical characteristics include:
1737
+
1738
+ - wider spacing
1739
+ - lower stream density
1740
+ - balanced map length
1741
+
1742
+ ---
1743
+
1744
+ ## stream
1745
+
1746
+ ```bash
1747
+ osu-finder -u WhiteCat --focus stream
1748
+ ```
1749
+
1750
+ Generates filters favoring stream-heavy beatmaps.
1751
+
1752
+ The resulting preset generally prefers:
1753
+
1754
+ - higher BPM
1755
+ - longer drain time
1756
+ - stream-dominant maps
1757
+
1758
+ ---
1759
+
1760
+ ## push
1761
+
1762
+ ```bash
1763
+ osu-finder -u WhiteCat --focus push
1764
+ ```
1765
+
1766
+ Builds a preset slightly above the player's current comfort zone.
1767
+
1768
+ Useful for improving rank or mechanical skill.
1769
+
1770
+ ---
1771
+
1772
+ ## farm
1773
+
1774
+ ```bash
1775
+ osu-finder -u WhiteCat --focus farm
1776
+ ```
1777
+
1778
+ Attempts to generate a preset similar to commonly farmed beatmaps.
1779
+
1780
+ Typically favors:
1781
+
1782
+ - jump maps
1783
+ - moderate length
1784
+ - efficient PP gain
1785
+
1786
+ ---
1787
+
1788
+ # Blacklist Management
1789
+
1790
+ Sometimes certain beatmaps should never appear in search results.
1791
+
1792
+ Example:
1793
+
1794
+ ```bash
1795
+ osu-finder --ban 1234567
1796
+ ```
1797
+
1798
+ The BeatmapSet ID is added to the global blacklist.
1799
+
1800
+ Future searches automatically skip it.
1801
+
1802
+ ---
1803
+
1804
+ # Typical Examples
1805
+
1806
+ ## Search using the default preset
1807
+
1808
+ ```bash
1809
+ osu-finder
1810
+ ```
1811
+
1812
+ ---
1813
+
1814
+ ## Search using a custom preset
1815
+
1816
+ ```bash
1817
+ osu-finder --preset stream
1818
+ ```
1819
+
1820
+ ---
1821
+
1822
+ ## Create a new preset
1823
+
1824
+ ```bash
1825
+ osu-finder --create-preset
1826
+ ```
1827
+
1828
+ ---
1829
+
1830
+ ## Analyze a player's profile
1831
+
1832
+ ```bash
1833
+ osu-finder -u mrekk
1834
+ ```
1835
+
1836
+ ---
1837
+
1838
+ ## Generate a stream practice preset
1839
+
1840
+ ```bash
1841
+ osu-finder -u mrekk --focus stream
1842
+ ```
1843
+
1844
+ ---
1845
+
1846
+ ## Generate a rank push preset
1847
+
1848
+ ```bash
1849
+ osu-finder -u mrekk --focus push
1850
+ ```
1851
+
1852
+ ---
1853
+
1854
+ ## Blacklist a BeatmapSet
1855
+
1856
+ ```bash
1857
+ osu-finder --ban 987654
1858
+ ```
1859
+
1860
+ ---
1861
+
1862
+ # Exit Status
1863
+
1864
+ A successful search returns exit code:
1865
+
1866
+ ```
1867
+ 0
1868
+ ```
1869
+
1870
+ Unexpected failures return a non-zero exit code.
1871
+
1872
+ Typical reasons include:
1873
+
1874
+ - invalid OAuth credentials
1875
+ - network failures
1876
+ - inaccessible beatmap mirror
1877
+ - malformed configuration
1878
+ - API authentication errors
1879
+
1880
+ ---
1881
+
1882
+ # Logging
1883
+
1884
+ osu-finder provides informative console output throughout the search process.
1885
+
1886
+ Typical messages include:
1887
+
1888
+ - authentication
1889
+ - page progress
1890
+ - beatmaps analyzed
1891
+ - local cache statistics
1892
+ - downloads
1893
+ - skipped beatmaps
1894
+ - profile analysis progress
1895
+
1896
+ This output is intended to provide visibility into every stage of the search pipeline without overwhelming the user with unnecessary information.