A small recipe that can be useful for the curious people.
A .dlm file is a gzip-compressed tar archive containing two files that Synology’s Download Station uses to search torrent sites.
Archive Structure
my_plugin.dlm (tar.gz)
├── INFO # Plugin metadata (JSON)
└── search.php # Search logic (PHP class)
INFO File
A JSON file describing the plugin. Example:
{
"name": "my_plugin",
"displayname": "My Torrent Site",
"description": "Search torrents on example.com",
"version": "1.0",
"site": "https://example.com/",
"module": "search.php",
"type": "search",
"class": "SynoDLMSearchMyPlugin"
}
Fields
| Field | Required | Description |
|---|---|---|
name |
Yes | Internal identifier (no spaces) |
displayname |
Yes | Name shown in Download Station UI |
description |
Yes | Short description |
version |
Yes | Plugin version string |
site |
Yes | URL of the torrent site |
module |
Yes | PHP filename (always search.php) |
type |
Yes | Always search |
class |
Yes | PHP class name — must match exactly in both files |
accountsupport |
No | true if the site requires login (changes prepare() signature) |
search.php
A PHP class implementing two required methods: prepare() and parse().
Method Signatures
The prepare() signature depends on accountsupport in INFO:
accountsupportisfalseor absent:public function prepare($curl, $query)accountsupportistrue:public function prepare($curl, $query, $username, $password)
This is critical — using the wrong signature causes a silent PHP fatal error and the plugin will not work.
prepare($curl, $query)
Configure the cURL handle that Synology will execute. You set the URL, headers, and options here. You do not execute the request yourself.
public function prepare($curl, $query) {
$url = 'https://example.com/api/search?q=' . urlencode($query);
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_HTTPHEADER, ['Authorization: Bearer MY_KEY']);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($curl, CURLOPT_TIMEOUT, 20);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
}
parse($plugin, $response)
Receives the raw HTTP response body (string). Parse it and call $plugin->addResult() for each torrent found. Return the number of results.
public function parse($plugin, $response) {
$json = json_decode($response, true);
$res = 0;
foreach ($json['results'] as $item) {
$plugin->addResult(
$title, // string: torrent name
$download, // string: .torrent URL or magnet: link
$size, // int: size in bytes
$datetime, // string: date in "Y-m-d" format
$page, // string: URL to the torrent page
$hash, // string: unique identifier (infohash or md5 of title)
$seeds, // int: number of seeders
$leechs, // int: number of leechers
$category // string: category label
);
$res++;
}
return $res;
}
addResult() Parameters
| # | Name | Type | Description |
|---|---|---|---|
| 1 | title |
string | Torrent display name |
| 2 | download |
string | .torrent URL or magnet: URI |
| 3 | size |
int | File size in bytes |
| 4 | datetime |
string | Upload date (Y-m-d format) |
| 5 | page |
string | URL to the torrent detail page |
| 6 | hash |
string | Unique ID (typically the infohash) |
| 7 | seeds |
int | Seeder count |
| 8 | leechs |
int | Leecher count |
| 9 | category |
string | Category label (e.g. "Films: HD") |
Debugging
Add a debug logger to your class:
private $debug = true;
private function DebugLog($str) {
if ($this->debug) {
file_put_contents('/tmp/my_plugin.log', $str . "\n", FILE_APPEND);
}
}
Then SSH into the Synology and tail -f /tmp/my_plugin.log while running a search.
Set $debug = false for production.
Building the .dlm
From the directory containing INFO and search.php:
tar czf my_plugin.dlm INFO search.php
Installing
- Open Download Station on your Synology
- Go to Settings > BT Search
- Click Add and upload the
.dlmfile - Enable the plugin with the checkbox