Repository: jerrymakesjelly/autoremove-torrents (language: python)

Issue:
RemoteFailure: portTested: http error 400: Bad Request
Sat, 30 Jan 2021 03:01:07 autoremovetorrents.main INFO: Auto Remove Torrents 1.5.3
Sat, 30 Jan 2021 03:01:07 autoremovetorrents.main INFO: Loading configurations...
Sat, 30 Jan 2021 03:01:07 autoremovetorrents.main INFO: Found 1 task(s) in the file.
Sat, 30 Jan 2021 03:01:07 autoremovetorrents.task INFO: Running task 'MTeam'...
Sat, 30 Jan 2021 03:01:07 autoremovetorrents.task INFO: Logging in...
Sat, 30 Jan 2021 03:01:07 autoremovetorrents.task INFO: Login successfully. The client is Transmission 2.94 (d8e60ee44f).
Sat, 30 Jan 2021 03:01:07 autoremovetorrents.task INFO: WebUI API version: 15
Sat, 30 Jan 2021 03:01:07 autoremovetorrents.main ERROR: RemoteFailure: portTested: http error 400: Bad Request
Sat, 30 Jan 2021 03:01:07 autoremovetorrents.main ERROR: Task MTeam fails. 

为什么显示错误？？？

Add 'remove-slow-upload-seeds' and 'remove-fast-upload-seeds' to remove torrents with slower or faster upload speed
Add 'remove-slow-upload-seeds' to 'action' keyword in order to remove torrents with slower upload speed.
添加'remove-slow-upload-seeds'到'action'关键字, 从而能够删除慢速上传的种子.

Example:

```
mytask:
  ...
  ...
  ...
  ...
  strategies:
    limit_max_torrents:
      status:
        - downloading
      maximum_number:
        limit: 30
        action: remove-slow-upload-seeds
  delete_data: true
```
fix: TypeError: unsupported operand type(s) for <<: 'float' and 'int'
see: #132 

Build from source code and tested success.

<img width="979" alt="image" src="https://user-images.githubusercontent.com/13919034/166493423-33936882-b293-43cf-9bee-7a46a838cde5.png">



Discussion / hints:

Fix patch:
diff --git a/README-cn.rst b/README-cn.rst
index aac902e..10e7dc8 100644
--- a/README-cn.rst
+++ b/README-cn.rst
@@ -107,146 +107,41 @@
 -----------
 |Screenshot|
 
-.. |Screenshot| image:: https://user-images.githubusercontent.com/6760674/40576720-a78097fe-612d-11e8-9dda-8aac0c5011a2.png
+.. |Screenshot| image:: https://user-images.githubusercontent.com/6760674/174464634-15743d59-f1dc-41c9-bff6-6d90becaeb67.gif
 
 更新日志
 ----------
-**2020-08-27 周四**：1.5.3 版本。
+**2022-06-19 星期日**：版本 1.5.4。
 
-* 修复 psutil 在群晖的兼容问题（用于检查磁盘剩余空间）。（#61）
-* 可以通过 ``--debug`` 或 ``-d`` 命令行启用调试模式。（#76）
-* 修复由主机 URL 末尾的 ``/`` 导致的 API 不兼容的问题。（#81）
-* 添加上传量与下载量两个条件。（#79）
+变动
++++++
 
-**2020-03-27 周五**：1.5.2 版本。
+* 移除端口开放状态（Outgoing Port Status）的信息。(#101) (#135)
+    - 我们确认了一个 bug，即，当我们使用 Transmission 并在 IPv6 网络下检查端口开放状态时，Transmission 的端口检查器会报错并提示“portTested: http error 400: Bad Request”。
+    - 由于没有删种条件需要依赖这个端口开放状态，所以我们删了它。
 
-* 支持 Deluge （#8）；
-* 使用批量删除提升删除效率；
-* 修复配置文件中的多语言支持问题（#69）；
-* 客户端名称不再对大小写敏感。
+* 修改了 ``last_activity`` 的行为。(#93) (#98) (#109)
+    - 默认情况下，``last_activity`` 不再删除那些从未活跃过的种子。
+    - 在需要的情况下，这些从未活跃过的种子可以用以下的方式去删除：
+        + 对于 ``last_activity`` 条件，使用 ``last_activity: never`` 或者 ``last_activity: none``。
+        + 对于 ``remove`` 表达式，使用 ``last_activity = never`` 或者 ``last_activity = none``。
 
-**2020-02-29 周六**：1.5.1 版本。
+新功能
+++++++
 
-* 修复了 1.5.0 版本中丢失的状态 ``StalledUpload`` 和 ``StalledDownload``。（#66）
+* 在 ``action`` 关键字中添加了 ``remove-slow-upload-seeds`` 和 ``remove-fast-upload-seeds`` 两个动作。 (#127) 感谢 @vincent906！
+* remove 表达式中支持等号（``=``）。
+* 添加 ``downloading_time`` 条件。 (#88) 感谢 @dantebarba！
 
-**2020-02-28 周五**：1.5.0 版本。
+修复
++++++
 
-* 修复了无法登录使用纯数字用户名或密码的客户端的问题（#64）；
-* 修复了在没有标签属性的 Transmission 中任务无法执行的问题；
-* 修复了删种条件可能对未打标签以及没有Tracker的种子无效的问题；
-* 修复了 status 中遗漏的 μTorrent 状态“排队中”（``Queued``）；
-* ``status`` 中添加 ``Error`` 状态；
-* 添加对 Transmission 标签的支持（#24）；
-* 添加删除条件“最大下载速度” ``max_downloadspeed``、“最小上传速度” ``min_uploadspeed``；
-* 添加删除条件“最小平均上传速度” ``min_average_uploadspeed``、“最大平均下载速度” ``max_average_downloadspeed`` （#49）；
-* 添加删除条件“最大种子大小” ``max_size`` （#21）；
-* 添加删除条件“最大做种数” ``max_seeder``、“最小下载数” ``min_leecher`` （#62）；
-* 添加删除条件“最大已连接做种者” ``max_connected_seeder``、“最小已连接下载者” ``min_connected_leecher``；
-* 添加删除条件“最后活动时间” ``last_activity``，以删除一段时间内没有上传或下载速度的种子（#1）（#9)；
-* 添加删除条件“最大下载百分比” ``max_progress``；
-* ``free_space``、``maximum_number``、``seed_size`` 的 ``action`` 中添加 ``remove-active-seeds``、``remove-inactive-seeds`` 动作，用于根据最后活动时间去尽量删除活跃的种子或者不活跃的种子（#9）；
-* 添加了新的删除条件“上传比率” ``upload_ratio``，可以根据上传量占种子大小的比例删种（#55）；
+* 修复了上传/下载量以及 ``free_space``、``remote_free_space`` 不能正确处理小数的问题。 (#133) 感谢 @sfwn！
+* 修复了 ``last_activity`` 条件在 Deluge 2.0.3 及以上版本无效的问题。(#119)
 
-**2020-02-03 周一**：迁移文档到 Read the Docs。
+`更多更新日志`_
 
-**2020-01-26 周日**: 1.4.9 版本。
-
-* 添加了 `free_space` 条件（最小剩余空间）。
-
-**2020-01-07 周二**: 1.4.8 版本。
-
-* 修复了在 qBittorrent v4.2.1 中不能删除种子的问题。对造成的不便深感抱歉。 (#53)
-
-**2020-01-06 周一**: 1.4.7 版本。
-
-* 添加了 qBittorrent v4.2.1 中新 API 的支持。 (#46) **注意：这个版本有bug，请升级到1.4.8或者更高的版本。**
-
-**2019-09-17 周二**: 1.4.6 版本。
-
-* 修复了当 Tracker 的 URL 包含端口时，`tracker` 过滤器需要指定端口的问题。
-
-**2019-06-06 周四**: 1.4.5 版本。
-
-* 添加了 `StalledUpload` 与 `StalledDownload` 状态。
-
-**2019-05-22 周三**: 1.4.4 版本。
-
-* 修复了当 `seed_size` / `maximum_number` 条件与 `ratio` / `create_time` / `seeding_time` 条件同时使用时任务会失败的问题。(#33)
-* 新特性：如果过滤器的内容只有一行，现在可以直接写出而不需要使用列表。
-
-**2019-05-19 周日**: 1.4.3 版本。
-
-* 添加对 Python 2.7 的支持。(#29)
-* 停止支持 Python 3.4。(kennethreitz/requests#5092)
-
-**2019-05-13 周一**: 1.4.2 版本。
-
-* 修复了丢失的语法分析器文件。(#32)
-* 修复了运算符的结合性。现在，运算符 `and` 和 `or` 保证是左结合的。（#32）
-
-**2019-05-06 周一**: 1.4.1 版本。
-
-* 修复了丢失的依赖项 `ply`。
-* 修复了在`remove`条件中重复定义的警告。
-
-**2019-05-06 周一**: 更新了文档。
-
-* 增加了关于`remove`条件的描述。
-
-**2019-05-01 周三**: 1.4.0 版本。
-
-* 删除了 ``seeding_time`` 和 ``ratio`` 条件中的限制 (#19)。
-    - 在之前的版本，``seeding_time`` 和 ``ratio`` 条件只会删除那些正在做种的种子。设置这个限制是为了给用户提供一个通过修改种子的状态（例如暂停做种）来避免种子被删除的方法。
-    - 不过现在我们有状态过滤器（``status``），所以这个限制就显得多余了，而且可能会使它的行为跟用户预想的不一样。
-* 支持自定义删除表达式 (#15)。
-    - 现在我们可以直接而明确地写出我们想要的表达式了，例如 ``remove: ratio > 1``。
-    - 复合的条件表达式也支持，例如 ``remove: (seeding_time < 86400 and ratio > 1) or (seeding_time > 86400 and ratio > 3)``。
-    - 旧的写法仍然可用。
-
-**2019-04-17 周三**: 1.3.0 版本。
-
-* 修复了在 qBittorrent 拥有大量的种子时程序会卡住的问题 (`Issue #22 <https://github.com/jerrymakesjelly/autoremove-torrents/issues/22>`_)。
-* 修复了状态过滤器在工作时会写入重复的日志的问题。
-* 日志系统已更新： 
-    - 日志路径可以被指定（使用 ``--log`` 参数，例如 ``--log=/home/jerrymakesjelly/logs``） (`Issue #23 <https://github.com/jerrymakesjelly/autoremove-torrents/issues/23>`_)。
-    - 日志文件将按天存储在不同的文件中（格式：``autoremove.%Y-%m-%d.log``）。
-* 全部单词 ``seed`` 修改为 ``torrent`` (`Issue #25 <https://github.com/jerrymakesjelly/autoremove-torrents/issues/25>`_)。
-* 删去了所有不必要的调试日志。
-
-**2019-01-10 周一**: 1.2.5 版本。
-
-* 修复了在设置多个策略时种子数量不正确的问题 (`Issue #10 <https://github.com/jerrymakesjelly/autoremove-torrents/issues/10>`_, 感谢 @momokoo 报告此问题并提出 PR).
-* 修复了在 qBittorrent 中种子数不正确的问题 (`Issue #13 <https://github.com/jerrymakesjelly/autoremove-torrents/issues/13>`_)。
-
-**2018-05-31 周四**: 1.2.4 版本。
-
-* 修复了启动失败的问题。
-
-**2018-05-30 周三**: 1.2.3 版本。增加了一些功能。
-
-* 允许使用环境变量去指定 ``host``、``username`` 和 ``password``。
-* 允许 ``username`` 和 ``password`` 留空（或者其中之一留空），使得不用用户名或密码也可以登录 WebUI。
-* 现在程序在一个任务失败时不会直接退出。
-
-**2018-05-27 周日**: 1.2.2 版本。 增加了一些功能 :smile:
-
-* 增加了新过滤器：种子状态。
-* 增加了新条件：最大种子数量。
-
-**2018-05-26 周六**: 1.2.1 版本。 修复了 ``setup.py`` 的问题。
-
-**2018-05-26 周六**: 1.2.0 版本. 重构已完成，程序已发布至 PyPI。
-
-* 新特性很快会被加入。
-* 现在你可以通过 ``pip`` 安装程序。
-
-**2018-05-14 周一**: 1.1.0 版本。 创建了 ``setup.py``。
-
-现在你可以直接使用 ``autoremove-torrents`` 命令而不是 ``python3 main.py``。
-
-**2018-03-28 周三**: （更正文档） ``delete_data`` 字段不应该被缩进。
-
-**2018-03-22 周四**: 第一个版本 :bowtie:
+.. _更多更新日志: https://autoremove-torrents.readthedocs.io/zh_CN/latest/changelog.html
 
 计划列表
 -----------
diff --git a/README.rst b/README.rst
index 1eda73d..8d437fc 100644
--- a/README.rst
+++ b/README.rst
@@ -109,146 +109,41 @@ Screenshot
 -----------
 |Screenshot|
 
-.. |Screenshot| image:: https://user-images.githubusercontent.com/6760674/40576720-a78097fe-612d-11e8-9dda-8aac0c5011a2.png
+.. |Screenshot| image:: https://user-images.githubusercontent.com/6760674/174464634-15743d59-f1dc-41c9-bff6-6d90becaeb67.gif
 
 Changelog
 ----------
-**Thu, 27 Aug 2020**: Version 1.5.3.
+**Sun, 19 June 2022**: Version 1.5.4.
 
-* Fix psutil's compatibility in Synology (use to check the free spaces). (#61)
-* Enable to output debug logs by specifying ``--debug`` or ``-d`` argument. (#76)
-* Fix API imcompatibility issue caused by the trailing ``/`` in host URL. (#81)
-* Add uploaded size and downloaded size conditions. (#79)
+Changes
+++++++++
 
-**Fri, 27 Mar 2020**: Version 1.5.2.
+* Remove outgoing port status info. (#101) (#135)
+    - We have confirmed a bug, which is, the outgoing port status checker will fail and report 'portTested: http error 400: Bad Request' when we are using Transmission and check the outgoing port status in IPv6 network.
+    - Since there are no configurations relying on this status, we remove it.
 
-* Support Deluge. (#8)
-* Use batch delete to improve efficiency.
-* Fix multi-language support in config file. (#69)
-* Set the client names to be case-insensitive.
+* Change ``last_activity``'s behaviour. (#93) (#98) (#109)
+    - It won't remove those torrents that have never been active anymore.
+    - These torrents that have never been active can be removed by the following configuration:
+        + ``last_activity: never`` or ``last_activity: none`` for ``last_activity`` condition.
+        + ``last_activity = never`` or ``last_activity = none`` for ``remove`` expression.
 
-**Sat, 29 Feb 2020**: Version 1.5.1.
+Features
++++++++++
 
-* Fix missing status ``StalledUpload`` and ``StalledDownload`` in version 1.5.0. (#66)
+* Add ``remove-slow-upload-seeds`` and ``remove-fast-upload-seeds`` in actions. (#127) Thanks to @vincent906!
+* Support equality (``=``) comparison in remove expression.
+* Add downloading time condition. (#88) Thanks to @dantebarba!
 
-**Fri, 28 Feb 2020**: Version 1.5.0.
-
-* Fix a problem: cannot login to client with numeric username or password. (#64)
-* Fix a problem: tasks could not be executed in a Transmission without label properties.
-* Fix a problem: removing conditions may not work for unlabeled and trackerless torrents.
-* Fix a problem: missing status ``Queued`` in μTorrent.
-* Add new status ``Error`` to filter ``status``.
-* Add support for Transmission labels. (#24)
-* Add removing conditions: Maximum Download Speed ``max_downloadspeed`` and Minimum Upload Speed ``min_uploadspeed``.
-* Add removing conditions: Maximum Average Download Speed ``max_average_downloadspeed`` and Minimum Average Upload Speed ``min_average_uploadspeed``. (#49)
-* Add removing conditions: Maximum Torrent Size ``max_size``. (#21)
-* Add removing conditions: Maximum Number of Seeders ``max_seeder`` and Minimum Number of Leechers ``min_leecher``. (#62)
-* Add removing conditions: Maximum Number of Connected Seeders ``max_connected_seeder`` and Minimum Number of Connected Leechers ``min_connected_leecher``.
-* Add a removing condition: Last Activity ``last_activity``, which removes torrents without upload or download speed for a period of time. (#1) (#9)
-* Add a removing condition: Maximum Download Progress ``max_progress``.
-* Add actions: add ``remove-active-seeds`` and ``remove-inactive-seeds`` to ``free_space``, ``maximum_number`` and ``seed_size`` in order to try to remove active or inactive torrents based on the last active time. (#9)
-* Add a removing condition: Upload Ratio ``upload_ratio``, which can remove torrents based on the ratio of uploaded size to torrent size. (#55)
-
-**Mon, 3 Feb 2020**: Migrate documents to Read the Docs.
-
-**Sun, 26 Jan 2020**: Version 1.4.9.
-
-* Add `free_space` condition.
-
-**Tue, 7 Jan 2020**: Version 1.4.8.
-
-* Fix bug that cannot delete torrents in qBittorrent v4.2.1+. Sorry for any inconvenience. (#53)
-
-**Mon, 6 Jan 2020**: Version 1.4.7.
-
-* Add support for new API in qBittorrent 4.2.1. (#46) **Note: This version has a bug. Please upgrade to v1.4.8 or higher.**
-
-**Tue, 17 Sep 2019**: Version 1.4.6.
-
-* Fix problem that the tracker filter needs to specific ports when the tracker URL includes port number. (#38)
-
-**Thu, 6 Jun 2019**: Version 1.4.5.
-
-* Added status `StalledUpload` and `StalledDownload`. (#34)
-
-**Wed, 22 May 2019**: Version 1.4.4.
-
-* Fixed a bug that when condition `seed_size` / `maximum_number` is used together with condtion `ratio` / `create_time` / `seeding_time`, the task will fail. (#33)
-* New feature: if the content of `filter` has only one line, now it is allowed to write down directly without using list.
-
-**Sun, 19 May 2019**: Version 1.4.3.
-
-* Supported Python 2.7. (#29)
-* Stopped supporting Python 3.4. (kennethreitz/requests#5092)
-
-**Mon, 13 May 2019**: Version 1.4.2.
-
-* Fixed missing parser files. (#32)
-* Fixed association of operators. (#32) Now the operator `and` and `or` are guaranteed to be left-associative.
-
-**Mon, 6 May 2019**: Version 1.4.1.
-
-* Fixed missing dependency: `ply`.
-* Fixed the warning of duplicate definition in condition `remove`.
-
-**Mon, 6 May 2019**: Updated Wiki.
-
-* Added the description of `remove` condition into Simplified-Chinese Wiki.
-
-**Wed, 1 May 2019**: Version 1.4.0.
-
-* Removed torrent status restriction in ``seeding_time`` and ``ratio`` condition (#19).
-    - Before this version, ``seeding_time`` and ``ratio`` condition will only remove those torrents whose status are seeding. We set this restriction to provide a method for users to avoid a torrent being removed by changing its status (e.g. pause seeding).
-    - But now we have a ``status`` filter, this restriction becomes unnecessary, and its behavior may be different from users expectation.
-* Supported custom remove expressions (#15).
-    - Now we can write the condition that we want directly and clearly, e.g. ``remove: ratio > 1``.
-    - Composite condition expressions are also supported, e.g. ``remove: (seeding_time < 86400 and ratio > 1) or (seeding_time > 86400 and ratio > 3)``. Visit Wiki to learn more.
-    - The old remove conditions are still available.
-
-**Wed, 17 Apr 2019**: Version 1.3.0.
-
-* Fixed bug: Program gets stuck when there are a lot of torrents in qBittorrent client (`Issue #22 <https://github.com/jerrymakesjelly/autoremove-torrents/issues/22>`_).
-* Fixed bug: Duplicated logging in status filter.
-* Log system was updated:
-    - Log path can be specified (Use ``--log`` argument, e.g. ``--log=/home/jerrymakesjelly/logs``) (`Issue #23 <https://github.com/jerrymakesjelly/autoremove-torrents/issues/23>`_).
-    - Logs are stored in different files by day (Format: ``autoremove.%Y-%m-%d.log``).
-* Changed the word ``seed`` to ``torrent`` (`Issue #25 <https://github.com/jerrymakesjelly/autoremove-torrents/issues/25>`_).
-* Removed uncessary debug messages.
-
-**Mon, 10 Jan 2019**: Version 1.2.5.
-
-* Fixed bug: Incorrect number of torrents in multiple strategies (`Issue #10 <https://github.com/jerrymakesjelly/autoremove-torrents/issues/10>`_, thanks to @momokoo for the report and PR).
-* Fixed bug: Incorrect number of torrents in qBittorrent (`Issue #13 <https://github.com/jerrymakesjelly/autoremove-torrents/issues/13>`_).
-
-**Thu, 31 May 2018**: Version 1.2.4.
-
-* Fixed startup failure.
-
-**Wed, 30 May 2018**: Version 1.2.3. Added new features.
-
-* Allowed to use environment variables to specify *host*, *username* and *password*.
-* Allowed *username* and *password* to be empty (or one of them is empty) to log in a WebUI without username and/or password.
-* Now the program won't quit directly when a task goes failed.
-
-**Sun, 27 May 2018**: Version 1.2.2. Added new features :smile:
-
-* Added new filter: Torrent Status
-* Added new condition: Maximum number of torrents
-
-**Sat, 26 May 2018**: Version 1.2.1. Fixed issue in *setup.py*.
-
-**Sat, 26 May 2018**: Version 1.2.0. Refactoring was completed, and was published to PyPI.
-
-* New features will be added soon.
-* Now we can install it via *pip*.
-
-**Mon, 14 May 2018**: Version 1.1.0. Created *setup.py*.
+Fix
+++++
 
-You can now use the *autoremove-torrents* command directly instead of *python3 main.py*.
+* Fix a bug that Downloaded/Uploaded Size conditions and ``free_space``/``remote_free_space`` cannot handle decimals correctly. (#133) Thanks to @sfwn!
+* Fix a bug that ``last_activity`` condition doesn't work in Deluge 2.0.3 and above. (#119)
 
-**Wed, 28 Mar 2018**: (Correct document) The *delete_data* field shouldn't be indented.
+`More changelogs`_
 
-**Thu, 22 Mar 2018**: First version :bowtie:
+.. _More changelogs: https://autoremove-torrents.readthedocs.io/en/latest/changelog.html
 
 TODO List
 -----------
diff --git a/autoremovetorrents/client/deluge.py b/autoremovetorrents/client/deluge.py
index 663d4e7..624e38d 100644
--- a/autoremovetorrents/client/deluge.py
+++ b/autoremovetorrents/client/deluge.py
@@ -3,7 +3,6 @@
 from deluge_client.client import DelugeClientException
 from ..torrent import Torrent
 from ..clientstatus import ClientStatus
-from ..portstatus import PortStatus
 from ..torrentstatus import TorrentStatus
 from ..exception.loginfailure import LoginFailure
 from ..exception.remotefailure import RemoteFailure
@@ -66,10 +65,6 @@ def client_status(self):
         cs.upload_speed = session_stats['payload_upload_rate']
         cs.total_uploaded = session_stats['total_upload']
 
-        # Get port status
-        port_is_open = self._call('core.test_listen_port')
-        cs.port_status = PortStatus.Open if port_is_open else PortStatus.Closed
-
         return cs
 
     # Get Deluge version
@@ -154,8 +149,8 @@ def torrent_properties(self, torrent_hash):
             download_time = torrent['active_time'] - torrent['finished_time']
             torrent_obj.average_download_speed = torrent['all_time_download'] / download_time if download_time > 0 else 0
         if 'time_since_transfer' in torrent:
-            # Set the last active time of those never active torrents to timestamp 0
-            torrent_obj.last_activity = torrent['time_since_transfer'] if torrent['time_since_transfer'] > 0 else 0
+            torrent_obj.last_activity = torrent['time_since_transfer'] \
+                if torrent['time_since_transfer'] > 0 else None
         torrent_obj.progress = torrent['progress'] / 100 # Accept Range: 0-1
 
         return torrent_obj
diff --git a/autoremovetorrents/client/qbittorrent.py b/autoremovetorrents/client/qbittorrent.py
index 37470a3..c09ca59 100644
--- a/autoremovetorrents/client/qbittorrent.py
+++ b/autoremovetorrents/client/qbittorrent.py
@@ -5,7 +5,6 @@
 from ..torrent import Torrent
 from ..clientstatus import ClientStatus
 from ..torrentstatus import TorrentStatus
-from ..portstatus import PortStatus
 from ..exception.loginfailure import LoginFailure
 from ..exception.connectionfailure import ConnectionFailure
 from ..exception.incompatibleapi import IncompatibleAPIVersion
@@ -162,13 +161,6 @@ def client_status(self):
         # Uploading speed and uploaded size
         cs.upload_speed = status['up_info_speed']
         cs.total_uploaded = status['up_info_data']
-        # Outgoing port status
-        if status['connection_status'] == 'connected':
-            cs.port_status = PortStatus.Open
-        elif status['connection_status'] == 'firewalled':
-            cs.port_status = PortStatus.Firewalled
-        else:
-            cs.port_status = PortStatus.Closed
         
         return cs
 
@@ -233,7 +225,9 @@ def torrent_properties(self, torrent_hash):
                 # For qBittorrent 3.x, the last activity field doesn't exist.
                 # We need to check the existence
                 if 'last_activity' in torrent:
-                    torrent_obj.last_activity = torrent['last_activity']
+                    # Convert to time interval since last activity
+                    torrent_obj.last_activity = self._refresh_time - torrent['last_activity'] \
+                        if torrent['last_activity'] > 0 else None
                 torrent_obj.progress = torrent['progress']
 
                 return torrent_obj
diff --git a/autoremovetorrents/client/transmission.py b/autoremovetorrents/client/transmission.py
index bfa90a3..178c601 100644
--- a/autoremovetorrents/client/transmission.py
+++ b/autoremovetorrents/client/transmission.py
@@ -1,9 +1,9 @@
 #-*- coding:utf-8 -*-
 import requests
+import time
 from ..torrent import Torrent
 from ..clientstatus import ClientStatus
 from ..torrentstatus import TorrentStatus
-from ..portstatus import PortStatus
 from ..exception.connectionfailure import ConnectionFailure
 from ..exception.loginfailure import LoginFailure
 from ..exception.nosuchclient import NoSuchClient
@@ -68,13 +68,6 @@ def client_status(self):
         # Uploading speed and uploaded size
         cs.upload_speed = status['uploadSpeed']
         cs.total_uploaded = status['current-stats']['uploadedBytes']
-
-        # Outgoing port status
-        port_is_open = self._make_transmission_request('port-test')
-        if port_is_open:
-            cs.port_status = PortStatus.Open
-        else:
-            cs.port_status = PortStatus.Closed
         
         return cs
     
@@ -144,13 +137,16 @@ def torrent_properties(self, torrent_hash):
         torrent_obj.downloaded = torrent['downloadedEver']
         torrent_obj.create_time = torrent['addedDate']
         torrent_obj.seeding_time = torrent['secondsSeeding']
+        torrent_obj.downloading_time = torrent['secondsDownloading']
         torrent_obj.upload_speed = torrent['rateUpload']
         torrent_obj.download_speed = torrent['rateDownload']
         torrent_obj.seeder = sum([tracker['seederCount'] for tracker in torrent['trackerStats']])
         torrent_obj.connected_seeder = torrent['peersSendingToUs']
         torrent_obj.leecher = sum([tracker['leecherCount'] for tracker in torrent['trackerStats']])
         torrent_obj.connected_leecher = torrent['peersGettingFromUs']
-        torrent_obj.last_activity = torrent['activityDate']
+        # Convert to time interval since last activity
+        torrent_obj.last_activity = time.time() - torrent['activityDate'] \
+            if torrent['activityDate'] > 0 else None
         torrent_obj.average_upload_speed = torrent['uploadedEver'] / torrent['secondsSeeding'] if torrent['secondsSeeding'] != 0 else 0
         torrent_obj.average_download_speed = torrent['downloadedEver'] / torrent['secondsDownloading'] if torrent['secondsDownloading'] != 0 else 0
         torrent_obj.progress = torrent['percentDone']
diff --git a/autoremovetorrents/clientstatus.py b/autoremovetorrents/clientstatus.py
index 5166cbc..cb72560 100644
--- a/autoremovetorrents/clientstatus.py
+++ b/autoremovetorrents/clientstatus.py
@@ -24,12 +24,10 @@ def disp(prop, converter = None):
 
         return ('Status reported by the client: \n' +
             '\tDownload Speed: %s\tTotal: %s\n' +
-            '\tUpload Speed: %s\tTotal: %s\n' +
-            '\tOutgoing Port Status: %s') % \
+            '\tUpload Speed: %s\tTotal: %s') % \
             (
                 disp('download_speed', convert_speed),
                 disp('total_downloaded', convert_bytes),
                 disp('upload_speed', convert_speed),
                 disp('total_uploaded', convert_bytes),
-                disp('port_status', lambda s: s.name),
             )
diff --git a/autoremovetorrents/compatibility/inf_.py b/autoremovetorrents/compatibility/inf_.py
new file mode 100644
index 0000000..b6fe94e
--- /dev/null
+++ b/autoremovetorrents/compatibility/inf_.py
@@ -0,0 +1,10 @@
+import sys
+
+# This variable 'inf_' represents infinity
+inf_ = None
+
+if sys.version_info >= (3, 5, 0):
+    import math
+    inf_ = math.inf
+else:
+    inf_ = float('inf')
diff --git a/autoremovetorrents/condition/base.py b/autoremovetorrents/condition/base.py
index 5e961cd..d551d61 100644
--- a/autoremovetorrents/condition/base.py
+++ b/autoremovetorrents/condition/base.py
@@ -1,7 +1,7 @@
 #-*- coding:utf-8 -*-
 from enum import Enum
 
-Comparer = Enum('Comparer', ('LT', 'GT'))
+Comparer = Enum('Comparer', ('LT', 'GT', 'EQ'))
 
 class Condition(object):
     def __init__(self):
@@ -10,4 +10,6 @@ def __init__(self):
         self.remove = set()
     
     def compare(self, a, b, comp):
-        return (comp == Comparer.LT and a < b) or (comp == Comparer.GT and a > b)
\ No newline at end of file
+        return (comp == Comparer.LT and a < b) \
+            or (comp == Comparer.GT and a > b) \
+            or (comp == Comparer.EQ and a == b)
\ No newline at end of file
diff --git a/autoremovetorrents/condition/downloaded.py b/autoremovetorrents/condition/downloaded.py
index af62497..bfc2d59 100644
--- a/autoremovetorrents/condition/downloaded.py
+++ b/autoremovetorrents/condition/downloaded.py
@@ -4,7 +4,7 @@
 class DownloadsCondition(Condition):
     def __init__(self, downloads, comp = Comparer.GT):
         Condition.__init__(self) # Initialize remain and remove list
-        self._downloads = downloads << 30 # Convert bytes to GiB
+        self._downloads = downloads * (1 << 30) # Convert bytes to GiB
         self._comparer = comp
 
     def apply(self, client_status, torrents):
diff --git a/autoremovetorrents/condition/downloadingtime.py b/autoremovetorrents/condition/downloadingtime.py
new file mode 100644
index 0000000..ec27c7c
--- /dev/null
+++ b/autoremovetorrents/condition/downloadingtime.py
@@ -0,0 +1,17 @@
+#-*- coding:utf-8 -*-
+
+from .base import Comparer
+from .base import Condition
+
+class DownloadingTimeCondition(Condition):
+    def __init__(self, dt, comp = Comparer.GT):
+        Condition.__init__(self) # Initialize remain and remove list
+        self._downloading_time = dt
+        self._comparer = comp
+
+    def apply(self, client_status, torrents):
+        for torrent in torrents:
+            if self.compare(torrent.downloading_time, self._downloading_time, self._comparer):
+                self.remove.add(torrent)
+            else:
+                self.remain.add(torrent)
\ No newline at end of file
diff --git a/autoremovetorrents/condition/freespacebase.py b/autoremovetorrents/condition/freespacebase.py
index ef3c147..61f9e70 100644
--- a/autoremovetorrents/condition/freespacebase.py
+++ b/autoremovetorrents/condition/freespacebase.py
@@ -5,7 +5,7 @@
 class FreeSpaceConditionBase(ConditionWithSort):
     def __init__(self, settings):
         ConditionWithSort.__init__(self, settings['action'])
-        self._min = settings['min'] << 30 # Convert B to GiB
+        self._min = settings['min'] * (1 << 30) # Convert B to GiB
 
     def apply(self, free_space, torrents):
         torrents = list(torrents)
diff --git a/autoremovetorrents/condition/lastactivity.py b/autoremovetorrents/condition/lastactivity.py
index 897ff74..f691a47 100644
--- a/autoremovetorrents/condition/lastactivity.py
+++ b/autoremovetorrents/condition/lastactivity.py
@@ -1,4 +1,3 @@
-import time
 from .base import Comparer
 from .base import Condition
 
@@ -8,9 +7,32 @@ def __init__(self, la, comp = Comparer.GT):
         self._last_activity = la
         self._comparer = comp
 
+        # If users set
+        #   last_activity: Never
+        # or
+        #   last_activity: None,
+        # we use a different function to check the torrents' activity
+
+        self._executor = self._apply_to_never_active_torrents \
+            if isinstance(la, str) and la.lower() in ['never', 'none'] else \
+            self._apply_to_ever_active_torrents
+
     def apply(self, client_status, torrents):
+        self._executor(client_status, torrents)
+
+    # Process the torrents that are ever active
+    def _apply_to_ever_active_torrents(self, client_status, torrents):
+        for torrent in torrents:
+            if torrent.last_activity is not None \
+                and self.compare(torrent.last_activity, self._last_activity, self._comparer):
+                self.remove.add(torrent)
+            else:
+                self.remain.add(torrent)
+
+    # Process the torrents that are never active
+    def _apply_to_never_active_torrents(self, client_status, torrents):
         for torrent in torrents:
-            if self.compare(time.time() - torrent.last_activity, self._last_activity, self._comparer):
+            if torrent.last_activity is None:
                 self.remove.add(torrent)
             else:
                 self.remain.add(torrent)
\ No newline at end of file
diff --git a/autoremovetorrents/condition/sortbase.py b/autoremovetorrents/condition/sortbase.py
index 2b46450..874226f 100644
--- a/autoremovetorrents/condition/sortbase.py
+++ b/autoremovetorrents/condition/sortbase.py
@@ -1,6 +1,7 @@
 #-*- coding:utf-8 -*-
 
 from .base import Condition
+from autoremovetorrents.compatibility.inf_ import inf_
 
 class ConditionWithSort(Condition):
     def __init__(self, action):
@@ -13,8 +14,17 @@ def sort_torrents(self, torrents):
             'remove-new-seeds': {'key':lambda torrent: torrent.create_time, 'reverse':True},
             'remove-big-seeds': {'key':lambda torrent: torrent.size, 'reverse':True},
             'remove-small-seeds': {'key':lambda torrent: torrent.size, 'reverse':False},
-            'remove-active-seeds': {'key':lambda torrent: torrent.last_activity, 'reverse':True},
-            'remove-inactive-seeds': {'key':lambda torrent: torrent.last_activity, 'reverse':False}
+            # For remove-active-seeds and remove-inactive-seeds,
+            # we move the torrents that are never active to the bottom of the list,
+            # to remove as many active torrents as possible.
+            'remove-active-seeds': {'key':
+                lambda torrent: torrent.last_activity if torrent.last_activity is not None else inf_,
+            'reverse':False},
+            'remove-inactive-seeds': {'key':
+                lambda torrent: torrent.last_activity if torrent.last_activity is not None else -inf_,
+            'reverse':True},
+            'remove-slow-upload-seeds': {'key':lambda torrent: torrent.upload_speed, 'reverse':False},
+            'remove-fast-upload-seeds': {'key':lambda torrent: torrent.upload_speed, 'reverse':True}
         }
         if self._action in handlers.keys():
-            torrents.sort(key=handlers[self._action]['key'], reverse=handlers[self._action]['reverse'])
\ No newline at end of file
+            torrents.sort(key=handlers[self._action]['key'], reverse=handlers[self._action]['reverse'])
diff --git a/autoremovetorrents/condition/uploaded.py b/autoremovetorrents/condition/uploaded.py
index 0e03b8a..d949bf5 100644
--- a/autoremovetorrents/condition/uploaded.py
+++ b/autoremovetorrents/condition/uploaded.py
@@ -4,7 +4,7 @@
 class UploadsCondition(Condition):
     def __init__(self, uploads, comp = Comparer.GT):
         Condition.__init__(self) # Initialize remain and remove list
-        self._uploads = uploads << 30 # Convert bytes to GiB
+        self._uploads = uploads * (1 << 30) # Convert bytes to GiB
         self._comparer = comp
 
     def apply(self, client_status, torrents):
diff --git a/autoremovetorrents/conditionlexer.py b/autoremovetorrents/conditionlexer.py
index 8fe1191..cbead47 100644
--- a/autoremovetorrents/conditionlexer.py
+++ b/autoremovetorrents/conditionlexer.py
@@ -5,15 +5,16 @@
 class ConditionLexer(object):
     reserved = {
         'and': 'AND',
-        'or': 'OR'
+        'or': 'OR',
     }
     tokens = [
-        'CONDITION', 'NUMBER',
-        'LT', 'GT',
+        'STRING', 'NUMBER',
+        'LT', 'GT', 'EQ',
         'LPAREN', 'RPAREN',
     ] + list(reserved.values())
 
     # Regular expression of tokens
+    t_EQ = r'='
     t_LT = r'<'
     t_GT = r'>'
     t_LPAREN = r'\('
@@ -27,10 +28,10 @@ def t_NUMBER(self, t):
         t.value = float(t.value)
         return t
 
-    def t_CONDITION(self, t):
-        r'[a-zA-Z_]+'
+    def t_STRING(self, t):
+        r'[a-zA-Z][a-zA-Z0-9_\-]*'
         t.value = t.value.lower()
-        t.type = self.reserved.get(t.value, 'CONDITION')
+        t.type = self.reserved.get(t.value, 'STRING')
         return t
     
     def t_error(self, t):
@@ -38,6 +39,6 @@ def t_error(self, t):
 
     def __init__(self):
         # Build the lexer
-        self.lexer = lex.lex(module=self)
+        self.lexer = lex.lex(module=self, optimize=1)
         # Set logger
         self._logger = logger.Logger.register(__name__)
\ No newline at end of file
diff --git a/autoremovetorrents/conditionparser.py b/autoremovetorrents/conditionparser.py
index c68c12c..cad662d 100644
--- a/autoremovetorrents/conditionparser.py
+++ b/autoremovetorrents/conditionparser.py
@@ -14,6 +14,7 @@
 from .condition.ratio import RatioCondition
 from .condition.seeder import SeederCondition
 from .condition.seedingtime import SeedingTimeCondition
+from .condition.downloadingtime import DownloadingTimeCondition
 from .condition.size import SizeCondition
 from .condition.uploaded import UploadsCondition
 from .condition.uploadratio import UploadRatioCondition
@@ -38,6 +39,7 @@ class ConditionParser(object):
         'ratio': RatioCondition,
         'seeder': SeederCondition,
         'seeding_time': SeedingTimeCondition,
+        'downloading_time': DownloadingTimeCondition,
         'size': SizeCondition,
         'upload': UploadsCondition,
         'upload_ratio': UploadRatioCondition,
@@ -60,6 +62,12 @@ class ConditionParser(object):
         ('left', 'AND', 'OR'),
     )
 
+    op = {
+        ConditionLexer.t_LT: Comparer.LT,
+        ConditionLexer.t_GT: Comparer.GT,
+        ConditionLexer.t_EQ: Comparer.EQ,
+    }
+
     def p_statement(self, t):
         'statement : expression'
         self.remove = t[1]
@@ -78,22 +86,25 @@ def p_and_or_expression(self, t):
             t[0] = t[1].intersection(t[3])
         elif t[2] == 'or': # Union
             t[0] = t[1].union(t[3])
+
+    def p_relation_op(self, t):
+        '''
+        relation_op : LT
+                     | GT
+                     | EQ
+        '''
+        t[0] = t[1]
     
     def p_relation_expression(self, t):
         '''
-        expression : CONDITION LT NUMBER
-                    | CONDITION GT NUMBER
+        expression : STRING relation_op NUMBER
+                    | STRING relation_op STRING
         '''
         result = set()
         if t[1] in self._condition_map:
-            if t[2] == '<': # Less than
-                obj = self._condition_map[t[1]](t[3], Comparer.LT)
-                obj.apply(self._client_status, self._torrent_list)
-                result = obj.remove
-            elif t[2] == '>': # Greater than
-                obj = self._condition_map[t[1]](t[3], Comparer.GT)
-                obj.apply(self._client_status, self._torrent_list)
-                result = obj.remove
+            obj = self._condition_map[t[1]](t[3], self.op[t[2]])
+            obj.apply(self._client_status, self._torrent_list)
+            result = obj.remove
         else:
             raise NoSuchCondition('The condition \'%s\' is not supported.' % t[1])
         t[0] = result
@@ -108,7 +119,7 @@ def p_error(self, p):
     def __init__(self, expression):
         # Initialize lexer and parser
         self.lexer = ConditionLexer()
-        self.parser = yacc.yacc(module=self)
+        self.parser = yacc.yacc(module=self, optimize=1)
         # Save expression
         self._expression = expression
         # Logger
diff --git a/autoremovetorrents/lextab.py b/autoremovetorrents/lextab.py
new file mode 100644
index 0000000..228b826
--- /dev/null
+++ b/autoremovetorrents/lextab.py
@@ -0,0 +1,10 @@
+# lextab.py. This file automatically created by PLY (version 3.11). Don't edit!
+_tabversion   = '3.10'
+_lextokens    = set(('AND', 'EQ', 'GT', 'LPAREN', 'LT', 'NUMBER', 'OR', 'RPAREN', 'STRING'))
+_lexreflags   = 64
+_lexliterals  = ''
+_lexstateinfo = {'INITIAL': 'inclusive'}
+_lexstatere   = {'INITIAL': [('(?P<t_NUMBER>\\d+(\\.\\d+)?)|(?P<t_STRING>[a-zA-Z][a-zA-Z0-9_\\-]*)|(?P<t_LPAREN>\\()|(?P<t_RPAREN>\\))|(?P<t_EQ>=)|(?P<t_GT>>)|(?P<t_LT><)', [None, ('t_NUMBER', 'NUMBER'), None, ('t_STRING', 'STRING'), (None, 'LPAREN'), (None, 'RPAREN'), (None, 'EQ'), (None, 'GT'), (None, 'LT')])]}
+_lexstateignore = {'INITIAL': ' \t'}
+_lexstateerrorf = {'INITIAL': 't_error'}
+_lexstateeoff = {}
diff --git a/autoremovetorrents/parser.out b/autoremovetorrents/parser.out
index 972d999..e7ca379 100644
--- a/autoremovetorrents/parser.out
+++ b/autoremovetorrents/parser.out
@@ -1,199 +1,1 @@
 Created by PLY version 3.11 (http://www.dabeaz.com/ply)
-
-Grammar
-
-Rule 0     S' -> statement
-Rule 1     statement -> expression
-Rule 2     expression -> LPAREN expression RPAREN
-Rule 3     expression -> expression AND expression
-Rule 4     expression -> expression OR expression
-Rule 5     expression -> CONDITION LT NUMBER
-Rule 6     expression -> CONDITION GT NUMBER
-
-Terminals, with rules where they appear
-
-AND                  : 3
-CONDITION            : 5 6
-GT                   : 6
-LPAREN               : 2
-LT                   : 5
-NUMBER               : 5 6
-OR                   : 4
-RPAREN               : 2
-error                : 
-
-Nonterminals, with rules where they appear
-
-expression           : 1 2 3 3 4 4
-statement            : 0
-
-Parsing method: LALR
-
-state 0
-
-    (0) S' -> . statement
-    (1) statement -> . expression
-    (2) expression -> . LPAREN expression RPAREN
-    (3) expression -> . expression AND expression
-    (4) expression -> . expression OR expression
-    (5) expression -> . CONDITION LT NUMBER
-    (6) expression -> . CONDITION GT NUMBER
-
-    LPAREN          shift and go to state 3
-    CONDITION       shift and go to state 4
-
-    statement                      shift and go to state 1
-    expression                     shift and go to state 2
-
-state 1
-
-    (0) S' -> statement .
-
-
-
-state 2
-
-    (1) statement -> expression .
-    (3) expression -> expression . AND expression
-    (4) expression -> expression . OR expression
-
-    $end            reduce using rule 1 (statement -> expression .)
-    AND             shift and go to state 5
-    OR              shift and go to state 6
-
-
-state 3
-
-    (2) expression -> LPAREN . expression RPAREN
-    (2) expression -> . LPAREN expression RPAREN
-    (3) expression -> . expression AND expression
-    (4) expression -> . expression OR expression
-    (5) expression -> . CONDITION LT NUMBER
-    (6) expression -> . CONDITION GT NUMBER
-
-    LPAREN          shift and go to state 3
-    CONDITION       shift and go to state 4
-
-    expression                     shift and go to state 7
-
-state 4
-
-    (5) expression -> CONDITION . LT NUMBER
-    (6) expression -> CONDITION . GT NUMBER
-
-    LT              shift and go to state 8
-    GT              shift and go to state 9
-
-
-state 5
-
-    (3) expression -> expression AND . expression
-    (2) expression -> . LPAREN expression RPAREN
-    (3) expression -> . expression AND expression
-    (4) expression -> . expression OR expression
-    (5) expression -> . CONDITION LT NUMBER
-    (6) expression -> . CONDITION GT NUMBER
-
-    LPAREN          shift and go to state 3
-    CONDITION       shift and go to state 4
-
-    expression                     shift and go to state 10
-
-state 6
-
-    (4) expression -> expression OR . expression
-    (2) expression -> . LPAREN expression RPAREN
-    (3) expression -> . expression AND expression
-    (4) expression -> . expression OR expression
-    (5) expression -> . CONDITION LT NUMBER
-    (6) expression -> . CONDITION GT NUMBER
-
-    LPAREN          shift and go to state 3
-    CONDITION       shift and go to state 4
-
-    expression                     shift and go to state 11
-
-state 7
-
-    (2) expression -> LPAREN expression . RPAREN
-    (3) expression -> expression . AND expression
-    (4) expression -> expression . OR expression
-
-    RPAREN          shift and go to state 12
-    AND             shift and go to state 5
-    OR              shift and go to state 6
-
-
-state 8
-
-    (5) expression -> CONDITION LT . NUMBER
-
-    NUMBER          shift and go to state 13
-
-
-state 9
-
-    (6) expression -> CONDITION GT . NUMBER
-
-    NUMBER          shift and go to state 14
-
-
-state 10
-
-    (3) expression -> expression AND expression .
-    (3) expression -> expression . AND expression
-    (4) expression -> expression . OR expression
-
-    AND             reduce using rule 3 (expression -> expression AND expression .)
-    OR              reduce using rule 3 (expression -> expression AND expression .)
-    $end            reduce using rule 3 (expression -> expression AND expression .)
-    RPAREN          reduce using rule 3 (expression -> expression AND expression .)
-
-  ! AND             [ shift and go to state 5 ]
-  ! OR              [ shift and go to state 6 ]
-
-
-state 11
-
-    (4) expression -> expression OR expression .
-    (3) expression -> expression . AND expression
-    (4) expression -> expression . OR expression
-
-    AND             reduce using rule 4 (expression -> expression OR expression .)
-    OR              reduce using rule 4 (expression -> expression OR expression .)
-    $end            reduce using rule 4 (expression -> expression OR expression .)
-    RPAREN          reduce using rule 4 (expression -> expression OR expression .)
-
-  ! AND             [ shift and go to state 5 ]
-  ! OR              [ shift and go to state 6 ]
-
-
-state 12
-
-    (2) expression -> LPAREN expression RPAREN .
-
-    AND             reduce using rule 2 (expression -> LPAREN expression RPAREN .)
-    OR              reduce using rule 2 (expression -> LPAREN expression RPAREN .)
-    $end            reduce using rule 2 (expression -> LPAREN expression RPAREN .)
-    RPAREN          reduce using rule 2 (expression -> LPAREN expression RPAREN .)
-
-
-state 13
-
-    (5) expression -> CONDITION LT NUMBER .
-
-    AND             reduce using rule 5 (expression -> CONDITION LT NUMBER .)
-    OR              reduce using rule 5 (expression -> CONDITION LT NUMBER .)
-    $end            reduce using rule 5 (expression -> CONDITION LT NUMBER .)
-    RPAREN          reduce using rule 5 (expression -> CONDITION LT NUMBER .)
-
-
-state 14
-
-    (6) expression -> CONDITION GT NUMBER .
-
-    AND             reduce using rule 6 (expression -> CONDITION GT NUMBER .)
-    OR              reduce using rule 6 (expression -> CONDITION GT NUMBER .)
-    $end            reduce using rule 6 (expression -> CONDITION GT NUMBER .)
-    RPAREN          reduce using rule 6 (expression -> CONDITION GT NUMBER .)
-
diff --git a/autoremovetorrents/parsetab.py b/autoremovetorrents/parsetab.py
index be3cedf..1b32baf 100644
--- a/autoremovetorrents/parsetab.py
+++ b/autoremovetorrents/parsetab.py
@@ -6,9 +6,9 @@
 
 _lr_method = 'LALR'
 
-_lr_signature = 'leftANDORAND CONDITION GT LPAREN LT NUMBER OR RPARENstatement : expressionexpression : LPAREN expression RPAREN\n        expression : expression AND expression\n                    | expression OR expression\n        \n        expression : CONDITION LT NUMBER\n                    | CONDITION GT NUMBER\n        '
+_lr_signature = 'leftANDORAND EQ GT LPAREN LT NUMBER OR RPAREN STRINGstatement : expressionexpression : LPAREN expression RPAREN\n        expression : expression AND expression\n                    | expression OR expression\n        \n        relation_op : LT\n                     | GT\n                     | EQ\n        \n        expression : STRING relation_op NUMBER\n                    | STRING relation_op STRING\n        '
     
-_lr_action_items = {'LPAREN':([0,3,5,6,],[3,3,3,3,]),'CONDITION':([0,3,5,6,],[4,4,4,4,]),'$end':([1,2,10,11,12,13,14,],[0,-1,-3,-4,-2,-5,-6,]),'AND':([2,7,10,11,12,13,14,],[5,5,-3,-4,-2,-5,-6,]),'OR':([2,7,10,11,12,13,14,],[6,6,-3,-4,-2,-5,-6,]),'LT':([4,],[8,]),'GT':([4,],[9,]),'RPAREN':([7,10,11,12,13,14,],[12,-3,-4,-2,-5,-6,]),'NUMBER':([8,9,],[13,14,]),}
+_lr_action_items = {'LPAREN':([0,3,5,6,],[3,3,3,3,]),'STRING':([0,3,5,6,8,9,10,11,],[4,4,4,4,15,-5,-6,-7,]),'$end':([1,2,12,13,14,15,16,],[0,-1,-3,-4,-2,-9,-8,]),'AND':([2,7,12,13,14,15,16,],[5,5,-3,-4,-2,-9,-8,]),'OR':([2,7,12,13,14,15,16,],[6,6,-3,-4,-2,-9,-8,]),'LT':([4,],[9,]),'GT':([4,],[10,]),'EQ':([4,],[11,]),'RPAREN':([7,12,13,14,15,16,],[14,-3,-4,-2,-9,-8,]),'NUMBER':([8,9,10,11,],[16,-5,-6,-7,]),}
 
 _lr_action = {}
 for _k, _v in _lr_action_items.items():
@@ -17,7 +17,7 @@
       _lr_action[_x][_k] = _y
 del _lr_action_items
 
-_lr_goto_items = {'statement':([0,],[1,]),'expression':([0,3,5,6,],[2,7,10,11,]),}
+_lr_goto_items = {'statement':([0,],[1,]),'expression':([0,3,5,6,],[2,7,12,13,]),'relation_op':([4,],[8,]),}
 
 _lr_goto = {}
 for _k, _v in _lr_goto_items.items():
@@ -27,10 +27,13 @@
 del _lr_goto_items
 _lr_productions = [
   ("S' -> statement","S'",1,None,None,None),
-  ('statement -> expression','statement',1,'p_statement','conditionparser.py',44),
-  ('expression -> LPAREN expression RPAREN','expression',3,'p_sub_expression','conditionparser.py',49),
-  ('expression -> expression AND expression','expression',3,'p_and_or_expression','conditionparser.py',54),
-  ('expression -> expression OR expression','expression',3,'p_and_or_expression','conditionparser.py',55),
-  ('expression -> CONDITION LT NUMBER','expression',3,'p_relation_expression','conditionparser.py',64),
-  ('expression -> CONDITION GT NUMBER','expression',3,'p_relation_expression','conditionparser.py',65),
+  ('statement -> expression','statement',1,'p_statement','conditionparser.py',71),
+  ('expression -> LPAREN expression RPAREN','expression',3,'p_sub_expression','conditionparser.py',76),
+  ('expression -> expression AND expression','expression',3,'p_and_or_expression','conditionparser.py',81),
+  ('expression -> expression OR expression','expression',3,'p_and_or_expression','conditionparser.py',82),
+  ('relation_op -> LT','relation_op',1,'p_relation_op','conditionparser.py',91),
+  ('relation_op -> GT','relation_op',1,'p_relation_op','conditionparser.py',92),
+  ('relation_op -> EQ','relation_op',1,'p_relation_op','conditionparser.py',93),
+  ('expression -> STRING relation_op NUMBER','expression',3,'p_relation_expression','conditionparser.py',99),
+  ('expression -> STRING relation_op STRING','expression',3,'p_relation_expression','conditionparser.py',100),
 ]
diff --git a/autoremovetorrents/portstatus.py b/autoremovetorrents/portstatus.py
deleted file mode 100644
index 5099121..0000000
--- a/autoremovetorrents/portstatus.py
+++ /dev/null
@@ -1,3 +0,0 @@
-# Outgoing port status
-from enum import Enum
-PortStatus = Enum('PortStatus', ('Open', 'Firewalled', 'Closed'))
\ No newline at end of file
diff --git a/autoremovetorrents/strategy.py b/autoremovetorrents/strategy.py
index 829b80e..7dd30fc 100644
--- a/autoremovetorrents/strategy.py
+++ b/autoremovetorrents/strategy.py
@@ -16,6 +16,7 @@
 from .condition.remotefreespace import RemoteFreeSpaceCondition
 from .condition.seeder import SeederCondition
 from .condition.seedingtime import SeedingTimeCondition
+from .condition.downloadingtime import DownloadingTimeCondition
 from .condition.size import SizeCondition
 from .condition.torrentnumber import TorrentNumberCondition
 from .condition.torrentsize import TorrentSizeCondition
@@ -127,6 +128,7 @@ def _apply_conditions(self, client_status):
             'remove': ConditionParser,
             'seed_size': TorrentSizeCondition,
             'seeding_time': SeedingTimeCondition,
+            'downloading_time': DownloadingTimeCondition,
             'max_size': SizeCondition,
             'upload_ratio': UploadRatioCondition,
         }
diff --git a/autoremovetorrents/torrent.py b/autoremovetorrents/torrent.py
index cd4250a..c088352 100644
--- a/autoremovetorrents/torrent.py
+++ b/autoremovetorrents/torrent.py
@@ -10,6 +10,8 @@ class Torrent(object):
     def __init__(self):
         # Proper attributes:
         # hash, name, category, tracker, status, size, ratio, uploaded, create_time, seeding_time
+        # NOTE: The attribute 'last_activity' stores the time interval since last activity,
+        #       not the unix timestamp of last activity.
         pass
 
     # Format torrent info
@@ -27,7 +29,7 @@ def disp(prop, converter = None):
             "\tProgress:%.2f%%\tSize:%s\tRatio:%.3f\tTotal Uploaded:%s\n" +
             "\tSeeder(connected/total):%d/%d\tLeecher(connected/total):%d/%d\tStatus:%s\n" +
             "\tDownload Speed:%s(Avg.:%s)\tUpload Speed:%s(Avg.:%s)\n" +
-            "\tCreate Time:%s\tSeeding Time:%s\tLast Activity:%s\n" +
+            "\tCreate Time:%s\tSeeding Time:%s\tDownloading Time:%s\tLast Activity:%s\n" +
             "\tCategory:%s\tTracker:%s") % \
             (
                 disp('name'),
@@ -46,7 +48,8 @@ def disp(prop, converter = None):
                 disp('average_upload_speed', convert_speed),
                 disp('create_time', convert_timestamp),
                 disp('seeding_time', convert_seconds),
-                disp('last_activity', convert_timestamp),
+                disp('downloading_time', convert_seconds),
+                disp('last_activity', convert_seconds),
                 disp('category', ','.join),
                 disp('tracker', lambda t: \
                     ','.join(
diff --git a/autoremovetorrents/util/convertseconds.py b/autoremovetorrents/util/convertseconds.py
index 40bf259..016c9fe 100644
--- a/autoremovetorrents/util/convertseconds.py
+++ b/autoremovetorrents/util/convertseconds.py
@@ -1,4 +1,7 @@
 def convert_seconds(sec):
+    if sec is None:
+        return 'None'
+
     m, s = divmod(sec, 60)
     h, m = divmod(m, 60)
     d, h = divmod(h, 24)
diff --git a/autoremovetorrents/version.py b/autoremovetorrents/version.py
index 6459149..aebade6 100644
--- a/autoremovetorrents/version.py
+++ b/autoremovetorrents/version.py
@@ -1,4 +1,4 @@
 #-*- coding:utf-8 -*-
 
 # Current autoremove-torrents version
-__version__ = '1.5.3'
\ No newline at end of file
+__version__ = '1.5.4'
\ No newline at end of file
diff --git a/docs/README.rst b/docs/README.rst
new file mode 100644
index 0000000..b305288
--- /dev/null
+++ b/docs/README.rst
@@ -0,0 +1,50 @@
+About Docs
+===========
+
+Prerequisite
+-------------
+
+::
+
+    pip install sphinx sphinx-intl sphinx_rtd_theme
+
+
+How to compile these documents?
+--------------------------------
+
+For Linux:
+
+::
+
+    make html
+
+For Windows, use the batch file `make.bat`:
+
+::
+
+    ./make html
+
+
+Beside, the documentation on `autoremove-torrents.readthedocs.io`_ will be updated by Read the Docs service automatically when commits are merged to the `master` branch. We needn't to update them manually.
+
+.. _autoremove-torrents.readthedocs.io: https://autoremove-torrents.readthedocs.io/
+
+How to generate Simplified-Chinese translation?
+------------------------------------------------
+
+First, the documents should be written in English and saved to the folder `docs`.
+
+When the original texts are completed, use these commands to generate translation files:
+
+::
+
+    sphinx-build -b gettext . _build/gettext
+    sphinx-intl update -p _build/gettext -l zh_CN
+
+And then, update the translation texts by editing the `*.po` files in `locales/zh_CN/LC_MESSAGES`.
+
+The translation is done when all of the `msgstr` fields are filled. You can compile the simplified-chinese documents by the following command, to check the results:
+
+::
+
+    sphinx-build -b html -D language=zh_CN . _build/html/zh_CN
diff --git a/docs/changelog.rst b/docs/changelog.rst
new file mode 100644
index 0000000..13855f2
--- /dev/null
+++ b/docs/changelog.rst
@@ -0,0 +1,357 @@
+.. _changelog:
+
+ChangeLog
+==========
+
+Version 1.5.4
+--------------
+
+*Release Date: Sunday, 19 June 2022*
+
+Changes
+++++++++
+
+* Remove outgoing port status info. (#101) (#135)
+    - We have confirmed a bug, which is, the outgoing port status checker will fail and report 'portTested: http error 400: Bad Request' when we are using Transmission and check the outgoing port status in IPv6 network.
+    - Since there are no configurations relying on this status, we remove it.
+
+* Change ``last_activity``'s behaviour. (#93) (#98) (#109)
+    - By default, it won't remove those torrents that have never been active anymore.
+    - These torrents that have never been active can be removed by the following configuration:
+        + ``last_activity: never`` or ``last_activity: none`` for ``last_activity`` condition.
+        + ``last_activity = never`` or ``last_activity = none`` for ``remove`` expression.
+
+Features
++++++++++
+
+* Add ``remove-slow-upload-seeds`` and ``remove-fast-upload-seeds`` actions to keyword ``action``. (#127) Thanks to @vincent906!
+* Support equality (``=``) comparison in ``remove`` expression.
+* Add ``downloading_time`` condition. (#88) Thanks to @dantebarba!
+
+Fix
+++++
+
+* Fix a bug that Downloaded/Uploaded Size conditions and ``free_space``/``remote_free_space`` cannot handle decimals correctly. (#133) Thanks to @sfwn!
+* Fix a bug that ``last_activity`` condition doesn't work in Deluge 2.0.3 and above. (#119)
+
+Version 1.5.3
+--------------
+
+*Release Date: Thursday, 27 August 2020*
+
+Features
++++++++++
+
+* Enable to output debug logs by specifying ``--debug`` or ``-d`` argument. (#76)
+* Add uploaded size and downloaded size conditions. (#79)
+
+Fix
+++++
+
+* Fix psutil's compatibility in Synology (use to check the free spaces). (#61)
+* Fix API imcompatibility issue caused by the trailing ``/`` in host URL. (#81)
+
+Version 1.5.2
+--------------
+
+*Release Date: Friday, 27 March 2020*
+
+Change
++++++++
+
+* Set the client names to be case-insensitive.
+
+Features
++++++++++
+
+* Support Deluge. (#8)
+* Use batch delete to improve efficiency.
+
+Fix
+++++
+
+* Fix multi-language support in config file. (#69)
+
+Version 1.5.1
+--------------
+
+*Release Date: Saturday, 29 February 2020*
+
+Fix
+++++
+
+* Fix missing status ``StalledUpload`` and ``StalledDownload`` in version 1.5.0. (#66)
+
+Version 1.5.0
+--------------
+
+*Release Date: Friday, 28 February 2020*
+
+Features
++++++++++
+
+* Add new status ``Error`` to filter ``status``.
+* Add support for Transmission labels. (#24)
+* Add removing conditions: Maximum Download Speed ``max_downloadspeed`` and Minimum Upload Speed ``min_uploadspeed``.
+* Add removing conditions: Maximum Average Download Speed ``max_average_downloadspeed`` and Minimum Average Upload Speed ``min_average_uploadspeed``. (#49)
+* Add removing conditions: Maximum Torrent Size ``max_size``. (#21)
+* Add removing conditions: Maximum Number of Seeders ``max_seeder`` and Minimum Number of Leechers ``min_leecher``. (#62)
+* Add removing conditions: Maximum Number of Connected Seeders ``max_connected_seeder`` and Minimum Number of Connected Leechers ``min_connected_leecher``.
+* Add a removing condition: Last Activity ``last_activity``, which removes torrents without upload or download speed for a period of time. (#1) (#9)
+* Add a removing condition: Maximum Download Progress ``max_progress``.
+* Add actions: add ``remove-active-seeds`` and ``remove-inactive-seeds`` to ``free_space``, ``maximum_number`` and ``seed_size`` in order to try to remove active or inactive torrents based on the last active time. (#9)
+* Add a removing condition: Upload Ratio ``upload_ratio``, which can remove torrents based on the ratio of uploaded size to torrent size. (#55)
+
+Fix
+++++
+
+* Fix a problem: cannot login to client with numeric username or password. (#64)
+* Fix a problem: tasks could not be executed in a Transmission without label properties.
+* Fix a problem: removing conditions may not work for unlabeled and trackerless torrents.
+* Fix a problem: missing status ``Queued`` in μTorrent.
+
+Documents Migration
+--------------------
+
+*Date: Monday, 3 February 2020*
+
+* Migrate documents to Read the Docs.
+
+Version 1.4.9
+--------------
+
+*Release Date: Sunday, 26 January 2020*
+
+Feature
+++++++++
+
+* Add `free_space` condition. Thanks to @drawwon!
+
+Version 1.4.8
+--------------
+
+*Release Date: Tuesday, 7 January 2020*
+
+Fix
+++++
+
+* Fix bug that cannot delete torrents in qBittorrent v4.2.1+. Sorry for any inconvenience. (#53)
+
+Version 1.4.7
+--------------
+
+*Release Date: Monday, 6 January 2020*
+
+Feature
+++++++++
+
+* Add support for new API in qBittorrent 4.2.1. (#46)
+
+.. note::
+
+   Note: This version has a bug. Please upgrade to v1.4.8 or higher.
+
+Version 1.4.6
+--------------
+
+*Release Date: Tuesday, 17 September 2019*
+
+Fix
+++++
+
+* Fix problem that the tracker filter needs to specific ports when the tracker URL includes port number. (#38)
+
+Version 1.4.5
+--------------
+
+*Release Date: Thursday, 6 June 2019*
+
+Feature
+++++++++
+
+* Added status `StalledUpload` and `StalledDownload`. (#34)
+
+Version 1.4.4
+--------------
+
+*Release Date: Wednesday, 22 May 2019*
+
+Feature
+++++++++
+
+* New feature: if the content of `filter` has only one line, now it is allowed to write down directly without using list.
+
+Fix
+++++
+
+* Fixed a bug that when condition `seed_size` / `maximum_number` is used together with condtion `ratio` / `create_time` / `seeding_time`, the task will fail. (#33)
+
+Version 1.4.3
+--------------
+
+*Release Date: Sunday, 19 May 2019*
+
+Changes
+++++++++
+
+* Supported Python 2.7. (#29)
+* Stopped supporting Python 3.4. (kennethreitz/requests#5092)
+
+Version 1.4.2
+--------------
+
+*Release Date: Monday, 13 May 2019*
+
+Fix
+++++
+
+* Fixed missing parser files. (#32)
+* Fixed association of operators. (#32) Now the operator `and` and `or` are guaranteed to be left-associative.
+
+Version 1.4.1
+--------------
+
+*Release Date: Monday, 6 May 2019*
+
+Fix
+++++
+
+* Fixed missing dependency: `ply`.
+* Fixed the warning of duplicate definition in condition `remove`.
+
+Wiki Update
+------------
+
+*Date: Monday, 6 May 2019*
+
+* Added the description of `remove` condition into Simplified-Chinese Wiki.
+
+Version 1.4.0
+--------------
+
+*Release Date: Wednesday, 1 May 2019*
+
+Changes
+++++++++
+
+* Removed torrent status restriction in ``seeding_time`` and ``ratio`` condition (#19).
+    - Before this version, ``seeding_time`` and ``ratio`` condition will only remove those torrents whose status are seeding. We set this restriction to provide a method for users to avoid a torrent being removed by changing its status (e.g. pause seeding).
+    - But now we have a ``status`` filter, this restriction becomes unnecessary, and its behavior may be different from users expectation.
+
+Features
++++++++++
+
+* Supported custom remove expressions (#15).
+    - Now we can write the condition that we want directly and clearly, e.g. ``remove: ratio > 1``.
+    - Composite condition expressions are also supported, e.g. ``remove: (seeding_time < 86400 and ratio > 1) or (seeding_time > 86400 and ratio > 3)``. Visit Wiki to learn more.
+    - The old remove conditions are still available.
+
+Version 1.3.0
+--------------
+
+*Release Date: Wednesday, 17 April 2019*
+
+Changes
+++++++++
+
+* Log system was updated:
+    - Log path can be specified (Use ``--log`` argument, e.g. ``--log=/home/jerrymakesjelly/logs``) (#23).
+    - Logs are stored in different files by day (Format: ``autoremove.%Y-%m-%d.log``).
+* Changed the word ``seed`` to ``torrent`` (#25).
+* Removed uncessary debug messages.
+
+Fix
+++++
+
+* Fixed bug: Program gets stuck when there are a lot of torrents in qBittorrent client (#22).
+* Fixed bug: Duplicated logging in status filter.
+
+Version 1.2.5
+--------------
+
+*Release Date: Monday, 10 January 2019*
+
+Fix
+++++
+
+* Fixed bug: Incorrect number of torrents in multiple strategies (#10). Thanks to @momokoo!
+* Fixed bug: Incorrect number of torrents in qBittorrent (#13).
+
+Version 1.2.4
+--------------
+
+*Release Date: Thursday, 31 May 2018*
+
+Fix
+++++
+
+* Fixed startup failure.
+
+Version 1.2.3
+--------------
+
+*Release Date: Wednesday, 30 May 2018*
+
+Change
++++++++
+
+* Now the program won't quit directly when a task goes failed.
+
+Features
++++++++++
+
+* Allowed to use environment variables to specify *host*, *username* and *password*.
+* Allowed *username* and *password* to be empty (or one of them is empty) to log in a WebUI without username and/or password.
+
+Version 1.2.2
+--------------
+
+*Release Date: Sunday, 27 May 2018*
+
+Features
++++++++++
+
+* Added new filter: Torrent Status
+* Added new condition: Maximum number of torrents
+
+Version 1.2.1
+--------------
+
+*Release Date: Saturday, 26 May 2018*
+
+Fix
+++++
+
+* Fixed issue in *setup.py*.
+
+Version 1.2.0
+--------------
+
+*Release Date: Saturday, 26 May 2018*
+
+* Published to PyPI!
+* Refactoring was completed.
+    - New features will be added soon.
+    - Now we can install it via *pip*.
+
+Version 1.1.0
+--------------
+
+*Release Date: Monday, 14 May 2018*
+
+* Created *setup.py*.
+    - You can now use the *autoremove-torrents* command directly instead of *python3 main.py*.
+
+Correct Document
+-----------------
+
+*Date: Wednesday, 28 March 2018*
+
+* The *delete_data* field shouldn't be indented.
+
+FIRST VERSION
+--------------
+
+*Release Date: Thursday, 22 March 2018*
+
+* First version :bowtie:
diff --git a/docs/conf.py b/docs/conf.py
index fc1834d..0276fe0 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -41,7 +41,7 @@
 # List of patterns, relative to source directory, that match files and
 # directories to ignore when looking for source files.
 # This pattern also affects html_static_path and html_extra_path.
-exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
+exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', 'README.rst']
 
 # The master toctree document.
 master_doc = 'index'
diff --git a/docs/config.rst b/docs/config.rst
index 1af9adf..e7d47fd 100644
--- a/docs/config.rst
+++ b/docs/config.rst
@@ -260,7 +260,7 @@ Use the removing condition keywords directly. There are 18 remove conditions.
 
    As long as a chosen torrent satisfies one of these conditions, it will be removed.
 
-The first 15 conditions are here. In order to avoid torrents being mistakenly deleted, some conditions are only available for certain torrent status.
+The first 18 conditions are here. In order to avoid torrents being mistakenly deleted, some conditions are only available for certain torrent status.
 
 .. list-table::
    :header-rows: 1
@@ -277,6 +277,10 @@ The first 15 conditions are here. In order to avoid torrents being mistakenly de
      - Second
      - All
      - The maximum time elapsed since the torrent was added to the client. When a torrent reaches the limit, it will be removed (no matter what state it is).
+   * - ``downloading_time``
+     - Second
+     - All
+     - Maximum downloading time of a torrent.
    * - ``seeding_time``
      - Second
      - All
@@ -338,6 +342,12 @@ The first 15 conditions are here. In order to avoid torrents being mistakenly de
      - All
      - The maximum upload ratio. Note that the upload ratio here is different from the ratio. For each torrent, the upload ratio is ``uploaded size`` divided by its ``size``.
 
+.. note::
+
+   In version 1.5.4 and above, the behavior of ``last_activity`` has been changed. By default, it only considers those torrents that have ever been active, and the other torrents, which have no activity yet, won't be deleted.
+
+   Moreover, to remove those torrents that have never been active, please use ``last_activity: Never`` or ``last_activity: None``.
+
 Beside these condition, the other 3 remove conditions are here. The rest of the torrents will be removed if they trigger these conditions.
 
 * ``seed_size``: Calculate the total size of the torrents you chosen. If the total size exceeds the limit, some of the torrents will be removed. The following two properties must be specificed.
@@ -351,18 +361,25 @@ Beside these condition, the other 3 remove conditions are here. The rest of the
      * - Value
        - Description
      * - remove-old-seeds
-       - Try to remove old seeds.
+       - Try to remove old torrents.
      * - remove-new-seeds
-       - Try to remove new seeds.
+       - Try to remove new torrents.
      * - remove-big-seeds
-       - Try to remove large seeds.
+       - Try to remove large torrents.
      * - remove-small-seeds
-       - Try to remove small seeds.
+       - Try to remove small torrents.
      * - remove-active-seeds
-       - Try to remove active seeds.
+       - Try to remove active torrents.
      * - remove-inactive-seeds
-       - Try to remove inactive seeds.
+       - Try to remove inactive torrents.
+     * - remove-fast-upload-seeds
+       - Try to remove torrents with fast upload speeds.
+     * - remove-slow-upload-seeds
+       - Try to remove torrents with slow upload speeds.
+
+  .. note::
 
+     Similar to ``last_activity``, the action ``remove-active-seeds`` and ``remove-inactive-seeds`` first consider those torrents that were once active. Only if these torrents are all removed but the constraints are still not met, the torrents that have never been active can be removed (but the order is not guaranteed).
 
 * ``maximum_number``: Set the maximum number of torrents. When the number of chosen torrents is exceed the maximum number, some of the torrents will be deleted, just like the condition `seed_size`. The following two properties must be specified:
   
@@ -499,6 +516,10 @@ Use the ``remove`` keyword. The ``remove`` keyword is a new keyword in version 1
         - KiB/s
         - Downloading
         - Download speed.
+      * - ``downloading_time``
+        - Second
+        - All
+        - Downloading time.
       * - ``last_activity``
         - Second
         - All
@@ -540,7 +561,7 @@ Use the ``remove`` keyword. The ``remove`` keyword is a new keyword in version 1
         - Downloading or Uploading
         - Upload Speed
 
-   ``Comparison Operator``: Available parameters are as follows. This program doesn't provide the ``equal`` sign, because the status data of the torrents change quickly, and usually it's meaningless to set a specific value.
+   ``Comparison Operator``: Available operators are as follows.
 
    .. list-table::
       :header-rows: 1
@@ -551,6 +572,8 @@ Use the ``remove`` keyword. The ``remove`` keyword is a new keyword in version 1
         - Less Than
       * - ``>``
         - Greater Than
+      * - ``=``
+        - Equals
 
    ``Value``: Specify a numeric value. Supports integers and floats.
 
diff --git a/docs/index.rst b/docs/index.rst
index 31422f2..5d616e7 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -13,6 +13,7 @@ Welcome to autoremove-torrents's documentation!
    intro
    inst
    config
+   changelog
 
 Indices and tables
 ==================
diff --git a/docs/locales/zh_CN/LC_MESSAGES/changelog.po b/docs/locales/zh_CN/LC_MESSAGES/changelog.po
new file mode 100644
index 0000000..3c6e903
--- /dev/null
+++ b/docs/locales/zh_CN/LC_MESSAGES/changelog.po
@@ -0,0 +1,715 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) 2020, jerrymakesjelly
+# This file is distributed under the same license as the autoremove-torrents
+# package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: autoremove-torrents \n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2022-06-19 18:32+0800\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 2.8.1\n"
+
+#: ../../changelog.rst:4
+msgid "ChangeLog"
+msgstr "更新日志"
+
+#: ../../changelog.rst:7
+msgid "Version 1.5.4"
+msgstr "版本 1.5.4"
+
+#: ../../changelog.rst:9
+msgid "*Release Date: Sunday, 19 June 2022*"
+msgstr "*发布日期：2022 年 6 月 19 日 星期日*"
+
+#: ../../changelog.rst:12 ../../changelog.rst:195 ../../changelog.rst:235
+#: ../../changelog.rst:255
+msgid "Changes"
+msgstr "变动"
+
+#: ../../changelog.rst:16
+msgid "Remove outgoing port status info. (#101) (#135)"
+msgstr "移除端口开放状态（Outgoing Port Status）的信息。(#101) (#135)"
+
+#: ../../changelog.rst:15
+msgid ""
+"We have confirmed a bug, which is, the outgoing port status checker will "
+"fail and report 'portTested: http error 400: Bad Request' when we are "
+"using Transmission and check the outgoing port status in IPv6 network."
+msgstr ""
+"我们确认了一个 bug，即，当我们使用 Transmission 并在 IPv6 网络下检查端口开放状态时，Transmission "
+"的端口检查器会报错并提示“portTested: http error 400: Bad Request”。"
+
+#: ../../changelog.rst:16
+msgid "Since there are no configurations relying on this status, we remove it."
+msgstr "由于没有删种条件需要依赖这个端口开放状态，所以我们删了它。"
+
+#: ../../changelog.rst:22
+msgid "Change ``last_activity``'s behaviour. (#93) (#98) (#109)"
+msgstr "修改了 ``last_activity`` 的行为。(#93) (#98) (#109)"
+
+#: ../../changelog.rst:19
+msgid ""
+"By default, it won't remove those torrents that have never been active "
+"anymore."
+msgstr "默认情况下，``last_activity`` 不再删除那些从未活跃过的种子。"
+
+#: ../../changelog.rst:22
+msgid ""
+"These torrents that have never been active can be removed by the "
+"following configuration:"
+msgstr "在需要的情况下，这些从未活跃过的种子可以用以下的方式去删除："
+
+#: ../../changelog.rst:21
+msgid ""
+"``last_activity: never`` or ``last_activity: none`` for ``last_activity``"
+" condition."
+msgstr ""
+"对于 ``last_activity`` 条件，使用 ``last_activity:never`` 或者 ``last_activity: "
+"none``。"
+
+#: ../../changelog.rst:22
+msgid ""
+"``last_activity = never`` or ``last_activity = none`` for ``remove`` "
+"expression."
+msgstr ""
+"对于 ``remove`` 表达式，使用 ``last_activity = never`` 或者 ``last_activity = "
+"none``。"
+
+#: ../../changelog.rst:25 ../../changelog.rst:43 ../../changelog.rst:65
+#: ../../changelog.rst:91 ../../changelog.rst:242 ../../changelog.rst:301
+#: ../../changelog.rst:312
+msgid "Features"
+msgstr "新功能"
+
+#: ../../changelog.rst:27
+msgid ""
+"Add ``remove-slow-upload-seeds`` and ``remove-fast-upload-seeds`` actions"
+" to keyword ``action``. (#127) Thanks to @vincent906!"
+msgstr "在 ``action`` 关键字中添加了 ``remove-slow-upload-seeds`` 和 ``remove-fast-upload-seeds`` 两个动作。 (#127) 感谢 @vincent906！"
+
+#: ../../changelog.rst:28
+msgid "Support equality (``=``) comparison in ``remove`` expression."
+msgstr "``remove`` 表达式中支持等号（``=``）。"
+
+#: ../../changelog.rst:29
+msgid "Add ``downloading_time`` condition. (#88) Thanks to @dantebarba!"
+msgstr "添加 ``downloading_time`` 条件。 (#88) 感谢 @dantebarba！"
+
+#: ../../changelog.rst:32 ../../changelog.rst:49 ../../changelog.rst:71
+#: ../../changelog.rst:81 ../../changelog.rst:106 ../../changelog.rst:136
+#: ../../changelog.rst:160 ../../changelog.rst:185 ../../changelog.rst:206
+#: ../../changelog.rst:217 ../../changelog.rst:264 ../../changelog.rst:275
+#: ../../changelog.rst:286 ../../changelog.rst:323
+msgid "Fix"
+msgstr "修复"
+
+#: ../../changelog.rst:34
+msgid ""
+"Fix a bug that Downloaded/Uploaded Size conditions and "
+"``free_space``/``remote_free_space`` cannot handle decimals correctly. "
+"(#133) Thanks to @sfwn!"
+msgstr "修复了上传/下载量以及 ``free_space``、``remote_free_space`` 不能正确处理小数的问题。 (#133) 感谢 @sfwn！"
+
+#: ../../changelog.rst:35
+msgid ""
+"Fix a bug that ``last_activity`` condition doesn't work in Deluge 2.0.3 "
+"and above. (#119)"
+msgstr "修复了 ``last_activity`` 条件在 Deluge 2.0.3 及以上版本无效的问题。(#119)"
+
+#: ../../changelog.rst:38
+msgid "Version 1.5.3"
+msgstr "版本 1.5.3"
+
+#: ../../changelog.rst:40
+msgid "*Release Date: Thursday, 27 August 2020*"
+msgstr "*发布日期：2020 年 8 月 27 日 星期四*"
+
+#: ../../changelog.rst:45
+msgid ""
+"Enable to output debug logs by specifying ``--debug`` or ``-d`` argument."
+" (#76)"
+msgstr "可以通过 ``--debug`` 或 ``-d`` 命令行启用调试模式。（#76）"
+
+#: ../../changelog.rst:46
+msgid "Add uploaded size and downloaded size conditions. (#79)"
+msgstr "添加上传量与下载量两个条件。（#79）"
+
+#: ../../changelog.rst:51
+msgid ""
+"Fix psutil's compatibility in Synology (use to check the free spaces). "
+"(#61)"
+msgstr "修复 psutil 在群晖的兼容问题（用于检查磁盘剩余空间）。（#61）"
+
+#: ../../changelog.rst:52
+msgid ""
+"Fix API imcompatibility issue caused by the trailing ``/`` in host URL. "
+"(#81)"
+msgstr "修复由主机 URL 末尾的 ``/`` 导致的 API 不兼容的问题。（#81）"
+
+#: ../../changelog.rst:55
+msgid "Version 1.5.2"
+msgstr "版本 1.5.2"
+
+#: ../../changelog.rst:57
+msgid "*Release Date: Friday, 27 March 2020*"
+msgstr "*发布日期：2020 年 3 月 27 日 星期五*"
+
+#: ../../changelog.rst:60 ../../changelog.rst:296
+msgid "Change"
+msgstr "变动"
+
+#: ../../changelog.rst:62
+msgid "Set the client names to be case-insensitive."
+msgstr "客户端名称不再对大小写敏感。"
+
+#: ../../changelog.rst:67
+msgid "Support Deluge. (#8)"
+msgstr "支持 Deluge。（#8）"
+
+#: ../../changelog.rst:68
+msgid "Use batch delete to improve efficiency."
+msgstr "使用批量删除提升删除效率。"
+
+#: ../../changelog.rst:73
+msgid "Fix multi-language support in config file. (#69)"
+msgstr "修复配置文件中的多语言支持问题。（#69）"
+
+#: ../../changelog.rst:76
+msgid "Version 1.5.1"
+msgstr "版本 1.5.1"
+
+#: ../../changelog.rst:78
+msgid "*Release Date: Saturday, 29 February 2020*"
+msgstr "*发布日期：2020 年 2 月 29 日 星期六*"
+
+#: ../../changelog.rst:83
+msgid ""
+"Fix missing status ``StalledUpload`` and ``StalledDownload`` in version "
+"1.5.0. (#66)"
+msgstr "修复了 1.5.0 版本中丢失的状态 ``StalledUpload`` 和 ``StalledDownload``。（#66）"
+
+#: ../../changelog.rst:86
+msgid "Version 1.5.0"
+msgstr "版本 1.5.0"
+
+#: ../../changelog.rst:88
+msgid "*Release Date: Friday, 28 February 2020*"
+msgstr "*发布日期：2020 年 2 月 28 日 星期五*"
+
+#: ../../changelog.rst:93
+msgid "Add new status ``Error`` to filter ``status``."
+msgstr "``status`` 中添加 ``Error`` 状态。"
+
+#: ../../changelog.rst:94
+msgid "Add support for Transmission labels. (#24)"
+msgstr "添加对 Transmission 标签的支持（#24）。"
+
+#: ../../changelog.rst:95
+msgid ""
+"Add removing conditions: Maximum Download Speed ``max_downloadspeed`` and"
+" Minimum Upload Speed ``min_uploadspeed``."
+msgstr "添加删除条件“最大下载速度” ``max_downloadspeed``、“最小上传速度” ``min_uploadspeed``。"
+
+#: ../../changelog.rst:96
+msgid ""
+"Add removing conditions: Maximum Average Download Speed "
+"``max_average_downloadspeed`` and Minimum Average Upload Speed "
+"``min_average_uploadspeed``. (#49)"
+msgstr ""
+"添加删除条件“最小平均上传速度” ``min_average_uploadspeed``、“最大平均下载速度” "
+"``max_average_downloadspeed`` （#49）。"
+
+#: ../../changelog.rst:97
+msgid "Add removing conditions: Maximum Torrent Size ``max_size``. (#21)"
+msgstr "添加删除条件“最大种子大小” ``max_size`` （#21）。"
+
+#: ../../changelog.rst:98
+msgid ""
+"Add removing conditions: Maximum Number of Seeders ``max_seeder`` and "
+"Minimum Number of Leechers ``min_leecher``. (#62)"
+msgstr "添加删除条件“最大做种数” ``max_seeder``、“最小下载数” ``min_leecher`` （#62）。"
+
+#: ../../changelog.rst:99
+msgid ""
+"Add removing conditions: Maximum Number of Connected Seeders "
+"``max_connected_seeder`` and Minimum Number of Connected Leechers "
+"``min_connected_leecher``."
+msgstr ""
+"添加删除条件“最大已连接做种者” ``max_connected_seeder``、“最小已连接下载者” "
+"``min_connected_leecher``。"
+
+#: ../../changelog.rst:100
+msgid ""
+"Add a removing condition: Last Activity ``last_activity``, which removes "
+"torrents without upload or download speed for a period of time. (#1) (#9)"
+msgstr "添加删除条件“最后活动时间” ``last_activity``，以删除一段时间内没有上传或下载速度的种子（#1）（#9)。"
+
+#: ../../changelog.rst:101
+msgid "Add a removing condition: Maximum Download Progress ``max_progress``."
+msgstr "添加删除条件“最大下载百分比” ``max_progress``。"
+
+#: ../../changelog.rst:102
+msgid ""
+"Add actions: add ``remove-active-seeds`` and ``remove-inactive-seeds`` to"
+" ``free_space``, ``maximum_number`` and ``seed_size`` in order to try to "
+"remove active or inactive torrents based on the last active time. (#9)"
+msgstr ""
+"``free_space``、``maximum_number``、``seed_size`` 的 ``action`` 中添加 "
+"``remove-active-seeds``、``remove-inactive-seeds`` "
+"动作，用于根据最后活动时间去尽量删除活跃的种子或者不活跃的种子（#9）。"
+
+#: ../../changelog.rst:103
+msgid ""
+"Add a removing condition: Upload Ratio ``upload_ratio``, which can remove"
+" torrents based on the ratio of uploaded size to torrent size. (#55)"
+msgstr "添加了新的删除条件“上传比率” ``upload_ratio``，可以根据上传量占种子大小的比例删种（#55）。"
+
+#: ../../changelog.rst:108
+msgid ""
+"Fix a problem: cannot login to client with numeric username or password. "
+"(#64)"
+msgstr "修复了无法登录使用纯数字用户名或密码的客户端的问题。（#64）"
+
+#: ../../changelog.rst:109
+msgid ""
+"Fix a problem: tasks could not be executed in a Transmission without "
+"label properties."
+msgstr "修复了在没有标签属性的 Transmission 中任务无法执行的问题。"
+
+#: ../../changelog.rst:110
+msgid ""
+"Fix a problem: removing conditions may not work for unlabeled and "
+"trackerless torrents."
+msgstr "修复了删种条件可能对未打标签以及没有Tracker的种子无效的问题。"
+
+#: ../../changelog.rst:111
+msgid "Fix a problem: missing status ``Queued`` in μTorrent."
+msgstr "修复了 status 中遗漏的 μTorrent 状态“排队中”（``Queued``）。"
+
+#: ../../changelog.rst:114
+msgid "Documents Migration"
+msgstr "文档迁移"
+
+#: ../../changelog.rst:116
+msgid "*Date: Monday, 3 February 2020*"
+msgstr "*日期：2020 年 2 月 3 日 星期一*"
+
+#: ../../changelog.rst:118
+msgid "Migrate documents to Read the Docs."
+msgstr "迁移文档到 Read the Docs。"
+
+#: ../../changelog.rst:121
+msgid "Version 1.4.9"
+msgstr "版本 1.4.9"
+
+#: ../../changelog.rst:123
+msgid "*Release Date: Sunday, 26 January 2020*"
+msgstr "*发布日期：2020 年 1 月 26 日 星期日*"
+
+#: ../../changelog.rst:126 ../../changelog.rst:146 ../../changelog.rst:170
+#: ../../changelog.rst:180
+msgid "Feature"
+msgstr "新功能"
+
+#: ../../changelog.rst:128
+msgid "Add `free_space` condition. Thanks to @drawwon!"
+msgstr "添加了 `free_space` 条件（最小剩余空间）。感谢 @drawwon！"
+
+#: ../../changelog.rst:131
+msgid "Version 1.4.8"
+msgstr "版本 1.4.8"
+
+#: ../../changelog.rst:133
+msgid "*Release Date: Tuesday, 7 January 2020*"
+msgstr "*发布日期：2020 年 1 月 7 日 星期二*"
+
+#: ../../changelog.rst:138
+msgid ""
+"Fix bug that cannot delete torrents in qBittorrent v4.2.1+. Sorry for any"
+" inconvenience. (#53)"
+msgstr "修复了在 qBittorrent v4.2.1 中不能删除种子的问题。对造成的不便深感抱歉。 (#53)"
+
+#: ../../changelog.rst:141
+msgid "Version 1.4.7"
+msgstr "版本 1.4.7"
+
+#: ../../changelog.rst:143
+msgid "*Release Date: Monday, 6 January 2020*"
+msgstr "*发布日期：2020 年 1 月 6 日 星期一*"
+
+#: ../../changelog.rst:148
+msgid "Add support for new API in qBittorrent 4.2.1. (#46)"
+msgstr "添加了 qBittorrent v4.2.1 中新 API 的支持。 (#46)"
+
+#: ../../changelog.rst:152
+msgid "Note: This version has a bug. Please upgrade to v1.4.8 or higher."
+msgstr "注意：这个版本有 bug，请升级到 1.4.8 或者更高的版本。"
+
+#: ../../changelog.rst:155
+msgid "Version 1.4.6"
+msgstr "版本 1.4.6"
+
+#: ../../changelog.rst:157
+msgid "*Release Date: Tuesday, 17 September 2019*"
+msgstr "*发布日期：2019 年 9 月 17 日 星期二*"
+
+#: ../../changelog.rst:162
+msgid ""
+"Fix problem that the tracker filter needs to specific ports when the "
+"tracker URL includes port number. (#38)"
+msgstr "修复了当 Tracker 的 URL 包含端口时，`tracker` 过滤器需要指定端口的问题。"
+
+#: ../../changelog.rst:165
+msgid "Version 1.4.5"
+msgstr "版本 1.4.5"
+
+#: ../../changelog.rst:167
+msgid "*Release Date: Thursday, 6 June 2019*"
+msgstr "*发布日期：2019 年 6 月 6 日 星期四*"
+
+#: ../../changelog.rst:172
+msgid "Added status `StalledUpload` and `StalledDownload`. (#34)"
+msgstr "添加了 `StalledUpload` 与 `StalledDownload` 状态。"
+
+#: ../../changelog.rst:175
+msgid "Version 1.4.4"
+msgstr "版本 1.4.4"
+
+#: ../../changelog.rst:177
+msgid "*Release Date: Wednesday, 22 May 2019*"
+msgstr "*发布日期：2019 年 5 月 22 日 星期三*"
+
+#: ../../changelog.rst:182
+msgid ""
+"New feature: if the content of `filter` has only one line, now it is "
+"allowed to write down directly without using list."
+msgstr "新特性：如果过滤器的内容只有一行，现在可以直接写出而不需要使用列表。"
+
+#: ../../changelog.rst:187
+msgid ""
+"Fixed a bug that when condition `seed_size` / `maximum_number` is used "
+"together with condtion `ratio` / `create_time` / `seeding_time`, the task"
+" will fail. (#33)"
+msgstr ""
+"修复了当 `seed_size` / `maximum_number` 条件与 `ratio` / `create_time` / "
+"`seeding_time` 条件同时使用时任务会失败的问题。(#33)"
+
+#: ../../changelog.rst:190
+msgid "Version 1.4.3"
+msgstr "版本 1.4.3"
+
+#: ../../changelog.rst:192
+msgid "*Release Date: Sunday, 19 May 2019*"
+msgstr "*发布日期：2019 年 5 月 19 日 星期日*"
+
+#: ../../changelog.rst:197
+msgid "Supported Python 2.7. (#29)"
+msgstr "添加对 Python 2.7 的支持。(#29)"
+
+#: ../../changelog.rst:198
+msgid "Stopped supporting Python 3.4. (kennethreitz/requests#5092)"
+msgstr "停止支持 Python 3.4。(kennethreitz/requests#5092)"
+
+#: ../../changelog.rst:201
+msgid "Version 1.4.2"
+msgstr "版本 1.4.2"
+
+#: ../../changelog.rst:203
+msgid "*Release Date: Monday, 13 May 2019*"
+msgstr "*发布日期：2019 年 5 月 13 日 星期一*"
+
+#: ../../changelog.rst:208
+msgid "Fixed missing parser files. (#32)"
+msgstr "修复了丢失的语法分析器文件。(#32)"
+
+#: ../../changelog.rst:209
+msgid ""
+"Fixed association of operators. (#32) Now the operator `and` and `or` are"
+" guaranteed to be left-associative."
+msgstr "修复了运算符的结合性。现在，运算符 `and` 和 `or` 保证是左结合的。（#32）"
+
+#: ../../changelog.rst:212
+msgid "Version 1.4.1"
+msgstr "版本 1.4.1"
+
+#: ../../changelog.rst:214
+msgid "*Release Date: Monday, 6 May 2019*"
+msgstr "*发布日期：2019 年 5 月 6 日 星期一*"
+
+#: ../../changelog.rst:219
+msgid "Fixed missing dependency: `ply`."
+msgstr "修复了丢失的依赖项 `ply`。"
+
+#: ../../changelog.rst:220
+msgid "Fixed the warning of duplicate definition in condition `remove`."
+msgstr "修复了在 `remove` 条件中重复定义的警告。"
+
+#: ../../changelog.rst:223
+msgid "Wiki Update"
+msgstr "Wiki 更新"
+
+#: ../../changelog.rst:225
+msgid "*Date: Monday, 6 May 2019*"
+msgstr "*日期：2019 年 5 月 6 日 星期一*"
+
+#: ../../changelog.rst:227
+msgid "Added the description of `remove` condition into Simplified-Chinese Wiki."
+msgstr "增加了关于 `remove` 条件的描述。"
+
+#: ../../changelog.rst:230
+msgid "Version 1.4.0"
+msgstr "版本 1.4.0"
+
+#: ../../changelog.rst:232
+msgid "*Release Date: Wednesday, 1 May 2019*"
+msgstr "*发布日期：2019 年 5 月 1 日 星期三*"
+
+#: ../../changelog.rst:239
+msgid ""
+"Removed torrent status restriction in ``seeding_time`` and ``ratio`` "
+"condition (#19)."
+msgstr "删除了 ``seeding_time`` 和 ``ratio`` 条件中的限制 (#19)。"
+
+#: ../../changelog.rst:238
+msgid ""
+"Before this version, ``seeding_time`` and ``ratio`` condition will only "
+"remove those torrents whose status are seeding. We set this restriction "
+"to provide a method for users to avoid a torrent being removed by "
+"changing its status (e.g. pause seeding)."
+msgstr ""
+"在之前的版本，``seeding_time`` 和 ``ratio`` "
+"条件只会删除那些正在做种的种子。设置这个限制是为了给用户提供一个通过修改种子的状态（例如暂停做种）来避免种子被删除的方法。"
+
+#: ../../changelog.rst:239
+msgid ""
+"But now we have a ``status`` filter, this restriction becomes "
+"unnecessary, and its behavior may be different from users expectation."
+msgstr "不过现在我们有状态过滤器（``status``），所以这个限制就显得多余了，而且可能会使它的行为跟用户预想的不一样。"
+
+#: ../../changelog.rst:247
+msgid "Supported custom remove expressions (#15)."
+msgstr "支持自定义删除表达式 (#15)。"
+
+#: ../../changelog.rst:245
+msgid ""
+"Now we can write the condition that we want directly and clearly, e.g. "
+"``remove: ratio > 1``."
+msgstr "现在我们可以直接而明确地写出我们想要的表达式了，例如 ``remove: ratio > 1``。"
+
+#: ../../changelog.rst:246
+msgid ""
+"Composite condition expressions are also supported, e.g. ``remove: "
+"(seeding_time < 86400 and ratio > 1) or (seeding_time > 86400 and ratio >"
+" 3)``. Visit Wiki to learn more."
+msgstr ""
+"复合的条件表达式也支持，例如 ``remove: (seeding_time < 86400 and ratio > 1) or "
+"(seeding_time > 86400 and ratio > 3)``。"
+
+#: ../../changelog.rst:247
+msgid "The old remove conditions are still available."
+msgstr "旧的写法仍然可用。"
+
+#: ../../changelog.rst:250
+msgid "Version 1.3.0"
+msgstr "版本 1.3.0"
+
+#: ../../changelog.rst:252
+msgid "*Release Date: Wednesday, 17 April 2019*"
+msgstr "*发布日期：2019 年 4 月 17 日 星期三*"
+
+#: ../../changelog.rst:258
+msgid "Log system was updated:"
+msgstr "日志系统已更新： "
+
+#: ../../changelog.rst:258
+msgid ""
+"Log path can be specified (Use ``--log`` argument, e.g. "
+"``--log=/home/jerrymakesjelly/logs``) (#23)."
+msgstr "日志路径可以被指定（使用 ``--log`` 参数，例如 ``--log=/home/jerrymakesjelly/logs``） (#23)。"
+
+#: ../../changelog.rst:259
+#, python-format
+msgid ""
+"Logs are stored in different files by day (Format: "
+"``autoremove.%Y-%m-%d.log``)."
+msgstr "日志文件将按天存储在不同的文件中（格式：``autoremove.%Y-%m-%d.log``）。"
+
+#: ../../changelog.rst:260
+msgid "Changed the word ``seed`` to ``torrent`` (#25)."
+msgstr "全部单词 ``seed`` 修改为 ``torrent`` （#25）。"
+
+#: ../../changelog.rst:261
+msgid "Removed uncessary debug messages."
+msgstr "删去了所有不必要的调试日志。"
+
+#: ../../changelog.rst:266
+msgid ""
+"Fixed bug: Program gets stuck when there are a lot of torrents in "
+"qBittorrent client (#22)."
+msgstr "修复了在 qBittorrent 拥有大量的种子时程序会卡住的问题 (#22)。"
+
+#: ../../changelog.rst:267
+msgid "Fixed bug: Duplicated logging in status filter."
+msgstr "修复了状态过滤器在工作时会写入重复的日志的问题。"
+
+#: ../../changelog.rst:270
+msgid "Version 1.2.5"
+msgstr "版本 1.2.5"
+
+#: ../../changelog.rst:272
+msgid "*Release Date: Monday, 10 January 2019*"
+msgstr "*发布日期：2019 年 1 月 10 日 星期一*"
+
+#: ../../changelog.rst:277
+msgid ""
+"Fixed bug: Incorrect number of torrents in multiple strategies (#10). "
+"Thanks to @momokoo!"
+msgstr "修复了在设置多个策略时种子数量不正确的问题 (#10)。感谢 @momokoo！"
+
+#: ../../changelog.rst:278
+msgid "Fixed bug: Incorrect number of torrents in qBittorrent (#13)."
+msgstr "修复了在 qBittorrent 中种子数不正确的问题 (#13)。"
+
+#: ../../changelog.rst:281
+msgid "Version 1.2.4"
+msgstr "版本 1.2.4"
+
+#: ../../changelog.rst:283
+msgid "*Release Date: Thursday, 31 May 2018*"
+msgstr "*发布日期：2018 年 5 月 31 日 星期四*"
+
+#: ../../changelog.rst:288
+msgid "Fixed startup failure."
+msgstr "修复了启动失败的问题。"
+
+#: ../../changelog.rst:291
+msgid "Version 1.2.3"
+msgstr "版本 1.2.3"
+
+#: ../../changelog.rst:293
+msgid "*Release Date: Wednesday, 30 May 2018*"
+msgstr "*发布日期：2018 年 5 月 30 日 星期三*"
+
+#: ../../changelog.rst:298
+msgid "Now the program won't quit directly when a task goes failed."
+msgstr "现在程序在一个任务失败时不会直接退出。"
+
+#: ../../changelog.rst:303
+msgid ""
+"Allowed to use environment variables to specify *host*, *username* and "
+"*password*."
+msgstr "允许使用环境变量去指定 ``host``、``username`` 和 ``password``。"
+
+#: ../../changelog.rst:304
+msgid ""
+"Allowed *username* and *password* to be empty (or one of them is empty) "
+"to log in a WebUI without username and/or password."
+msgstr "允许 ``username`` 和 ``password`` 留空（或者其中之一留空），使得不用用户名或密码也可以登录 WebUI。"
+
+#: ../../changelog.rst:307
+msgid "Version 1.2.2"
+msgstr "版本 1.2.2"
+
+#: ../../changelog.rst:309
+msgid "*Release Date: Sunday, 27 May 2018*"
+msgstr "*发布日期：2018 年 5 月 27 日 星期日*"
+
+#: ../../changelog.rst:314
+msgid "Added new filter: Torrent Status"
+msgstr "增加了新过滤器：种子状态。"
+
+#: ../../changelog.rst:315
+msgid "Added new condition: Maximum number of torrents"
+msgstr "增加了新条件：最大种子数量。"
+
+#: ../../changelog.rst:318
+msgid "Version 1.2.1"
+msgstr "版本 1.2.1"
+
+#: ../../changelog.rst:320 ../../changelog.rst:330
+msgid "*Release Date: Saturday, 26 May 2018*"
+msgstr "*发布日期：2018 年 5 月 26 日 星期六*"
+
+#: ../../changelog.rst:325
+msgid "Fixed issue in *setup.py*."
+msgstr "修复了 ``setup.py`` 的问题。"
+
+#: ../../changelog.rst:328
+msgid "Version 1.2.0"
+msgstr "版本 1.2.0"
+
+#: ../../changelog.rst:332
+msgid "Published to PyPI!"
+msgstr "程序已发布至 PyPI！"
+
+#: ../../changelog.rst:335
+msgid "Refactoring was completed."
+msgstr "重构已完成。"
+
+#: ../../changelog.rst:334
+msgid "New features will be added soon."
+msgstr "新特性很快会被加入。"
+
+#: ../../changelog.rst:335
+msgid "Now we can install it via *pip*."
+msgstr "现在你可以通过 ``pip`` 安装程序。"
+
+#: ../../changelog.rst:338
+msgid "Version 1.1.0"
+msgstr "版本 1.1.0"
+
+#: ../../changelog.rst:340
+msgid "*Release Date: Monday, 14 May 2018*"
+msgstr "*发布日期：2018 年 5 月 14 日 星期一*"
+
+#: ../../changelog.rst:343
+msgid "Created *setup.py*."
+msgstr "创建了 ``setup.py``。"
+
+#: ../../changelog.rst:343
+msgid ""
+"You can now use the *autoremove-torrents* command directly instead of "
+"*python3 main.py*."
+msgstr "现在你可以直接使用 ``autoremove-torrents`` 命令而不是 ``python3 main.py``。"
+
+#: ../../changelog.rst:346
+msgid "Correct Document"
+msgstr "文档勘误"
+
+#: ../../changelog.rst:348
+msgid "*Date: Wednesday, 28 March 2018*"
+msgstr "*日期：2018 年 3 月 28 日 星期三*"
+
+#: ../../changelog.rst:350
+msgid "The *delete_data* field shouldn't be indented."
+msgstr "``delete_data`` 字段不应该被缩进。"
+
+#: ../../changelog.rst:353
+msgid "FIRST VERSION"
+msgstr "第一个版本"
+
+#: ../../changelog.rst:355
+msgid "*Release Date: Thursday, 22 March 2018*"
+msgstr "*发布日期：2018 年 3 月 22 日 星期四*"
+
+#: ../../changelog.rst:357
+msgid "First version :bowtie:"
+msgstr "第一个版本 :bowtie:"
+
+#~ msgid "It won't remove those torrents that have never been active anymore."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Add ``remove-slow-upload-seeds`` and "
+#~ "``remove-fast-upload-seeds`` in actions."
+#~ " (#127) Thanks to @vincent906!"
+#~ msgstr ""
+
diff --git a/docs/locales/zh_CN/LC_MESSAGES/config.po b/docs/locales/zh_CN/LC_MESSAGES/config.po
index fb4c3c2..f89fb16 100644
--- a/docs/locales/zh_CN/LC_MESSAGES/config.po
+++ b/docs/locales/zh_CN/LC_MESSAGES/config.po
@@ -4,19 +4,18 @@
 # package.
 # jerrymakesjelly <ganzhaoyu037@gmail.com>, 2020.
 #
-#, fuzzy
 msgid ""
 msgstr ""
 "Project-Id-Version: autoremove-torrents \n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2020-08-27 15:46+0800\n"
+"POT-Creation-Date: 2022-06-19 17:25+0800\n"
 "PO-Revision-Date: 2020-02-02 16:32+0800\n"
 "Last-Translator: jerrymakesjelly <ganzhaoyu037@gmail.com>\n"
 "Language-Team: Chinese (Simplified)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=utf-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.8.0\n"
+"Generated-By: Babel 2.8.1\n"
 
 #: ../../config.rst:4
 msgid "Configuration"
@@ -236,14 +235,14 @@ msgstr "状态"
 msgid "Remarks"
 msgstr "备注"
 
-#: ../../config.rst:131 ../../config.rst:290 ../../config.rst:500
+#: ../../config.rst:131 ../../config.rst:294 ../../config.rst:517
 msgid "Downloading"
 msgstr "Downloading"
 
 #: ../../config.rst:132 ../../config.rst:134 ../../config.rst:136
-#: ../../config.rst:138 ../../config.rst:144 ../../config.rst:483
-#: ../../config.rst:487 ../../config.rst:507 ../../config.rst:515
-#: ../../config.rst:519 ../../config.rst:535
+#: ../../config.rst:138 ../../config.rst:144 ../../config.rst:500
+#: ../../config.rst:504 ../../config.rst:528 ../../config.rst:536
+#: ../../config.rst:540 ../../config.rst:556
 msgid "/"
 msgstr "/"
 
@@ -388,41 +387,42 @@ msgstr "只要选择的种子满足这些条件之一，它就会被删除。"
 
 #: ../../config.rst:263
 msgid ""
-"The first 15 conditions are here. In order to avoid torrents being "
+"The first 18 conditions are here. In order to avoid torrents being "
 "mistakenly deleted, some conditions are only available for certain "
 "torrent status."
-msgstr "前 15 个条件如下。为了防止误删种子，某些条件只对特定的状态有效。"
+msgstr "前 18 个条件如下。为了防止误删种子，某些条件只对特定的状态有效。"
 
 #: ../../config.rst:268
 msgid "Condition"
 msgstr "条件"
 
-#: ../../config.rst:269 ../../config.rst:471
+#: ../../config.rst:269 ../../config.rst:488
 msgid "Unit"
 msgstr "单位"
 
-#: ../../config.rst:270 ../../config.rst:472
+#: ../../config.rst:270 ../../config.rst:489
 msgid "Available Status"
 msgstr "可用状态"
 
-#: ../../config.rst:271 ../../config.rst:352 ../../config.rst:473
-#: ../../config.rst:549
+#: ../../config.rst:271 ../../config.rst:362 ../../config.rst:490
+#: ../../config.rst:570
 msgid "Description"
 msgstr "说明"
 
-#: ../../config.rst:272 ../../config.rst:514
+#: ../../config.rst:272 ../../config.rst:535
 msgid "``ratio``"
 msgstr "``ratio``"
 
 #: ../../config.rst:274 ../../config.rst:278 ../../config.rst:282
-#: ../../config.rst:286 ../../config.rst:298 ../../config.rst:302
+#: ../../config.rst:286 ../../config.rst:290 ../../config.rst:302
 #: ../../config.rst:306 ../../config.rst:310 ../../config.rst:314
-#: ../../config.rst:318 ../../config.rst:330 ../../config.rst:334
-#: ../../config.rst:338 ../../config.rst:476 ../../config.rst:480
-#: ../../config.rst:492 ../../config.rst:496 ../../config.rst:504
-#: ../../config.rst:508 ../../config.rst:512 ../../config.rst:516
-#: ../../config.rst:520 ../../config.rst:524 ../../config.rst:528
-#: ../../config.rst:532 ../../config.rst:536
+#: ../../config.rst:318 ../../config.rst:322 ../../config.rst:334
+#: ../../config.rst:338 ../../config.rst:342 ../../config.rst:493
+#: ../../config.rst:497 ../../config.rst:509 ../../config.rst:513
+#: ../../config.rst:521 ../../config.rst:525 ../../config.rst:529
+#: ../../config.rst:533 ../../config.rst:537 ../../config.rst:541
+#: ../../config.rst:545 ../../config.rst:549 ../../config.rst:553
+#: ../../config.rst:557
 msgid "All"
 msgstr "全部"
 
@@ -430,12 +430,13 @@ msgstr "全部"
 msgid "Maximum ratio"
 msgstr "分享率上限"
 
-#: ../../config.rst:276 ../../config.rst:490
+#: ../../config.rst:276 ../../config.rst:507
 msgid "``create_time``"
 msgstr "``create_time``"
 
-#: ../../config.rst:277 ../../config.rst:281 ../../config.rst:329
-#: ../../config.rst:491 ../../config.rst:503 ../../config.rst:523
+#: ../../config.rst:277 ../../config.rst:281 ../../config.rst:285
+#: ../../config.rst:333 ../../config.rst:508 ../../config.rst:520
+#: ../../config.rst:524 ../../config.rst:544
 msgid "Second"
 msgstr "秒"
 
@@ -446,242 +447,294 @@ msgid ""
 "is)."
 msgstr "种子从添加到客户端到现在所经过的时间，以秒为单位。在这里设置一个添加时间的上限，当种子在客户端中存活时间超过此上限后，种子会被直接删除（不管种子现在正处于哪种状态）。"
 
-#: ../../config.rst:280 ../../config.rst:522
+#: ../../config.rst:280 ../../config.rst:519
+msgid "``downloading_time``"
+msgstr "``downloading_time``"
+
+#: ../../config.rst:283
+msgid "Maximum downloading time of a torrent."
+msgstr "最长下载时间。"
+
+#: ../../config.rst:284 ../../config.rst:543
 msgid "``seeding_time``"
 msgstr "``seeding_time``"
 
-#: ../../config.rst:283
+#: ../../config.rst:287
 msgid "Maximum seeding time of a torrent."
 msgstr "最长做种时间。"
 
-#: ../../config.rst:284
+#: ../../config.rst:288
 msgid "``max_download``"
 msgstr "``max_download``"
 
-#: ../../config.rst:285 ../../config.rst:305 ../../config.rst:313
-#: ../../config.rst:495 ../../config.rst:527 ../../config.rst:531
+#: ../../config.rst:289 ../../config.rst:309 ../../config.rst:317
+#: ../../config.rst:512 ../../config.rst:548 ../../config.rst:552
 msgid "GiB"
 msgstr "GiB"
 
-#: ../../config.rst:287
+#: ../../config.rst:291
 msgid ""
 "Maximum downloaded size of a torrent. Torrents whose downloaded size "
 "exceed this limitation will be removed."
 msgstr "种子最大下载量，超过此限制的种子会被删除。"
 
-#: ../../config.rst:288
+#: ../../config.rst:292
 msgid "``max_downloadspeed``"
 msgstr "``max_downloadspeed``"
 
-#: ../../config.rst:289 ../../config.rst:293 ../../config.rst:297
-#: ../../config.rst:301 ../../config.rst:475 ../../config.rst:479
-#: ../../config.rst:499 ../../config.rst:539
+#: ../../config.rst:293 ../../config.rst:297 ../../config.rst:301
+#: ../../config.rst:305 ../../config.rst:492 ../../config.rst:496
+#: ../../config.rst:516 ../../config.rst:560
 msgid "KiB/s"
 msgstr "KiB/s"
 
-#: ../../config.rst:291
+#: ../../config.rst:295
 msgid ""
 "Maximum download speed of a torrent. Torrents that exceed the limitation "
 "will be removed."
 msgstr "种子的最大下载速度，超过此限制的种子会被删除。"
 
-#: ../../config.rst:292
+#: ../../config.rst:296
 msgid "``min_uploadspeed``"
 msgstr "``min_uploadspeed``"
 
-#: ../../config.rst:294 ../../config.rst:322 ../../config.rst:326
-#: ../../config.rst:484 ../../config.rst:488 ../../config.rst:540
+#: ../../config.rst:298 ../../config.rst:326 ../../config.rst:330
+#: ../../config.rst:501 ../../config.rst:505 ../../config.rst:561
 msgid "Downloading or Uploading"
 msgstr "Downloading 或 Uploading"
 
-#: ../../config.rst:295
+#: ../../config.rst:299
 msgid ""
 "Minimum upload speed of a torrent. Torrents below this speed will be "
 "removed."
 msgstr "种子的最小上传速度，低于此速度的种子会被删除。"
 
-#: ../../config.rst:296
+#: ../../config.rst:300
 msgid "``max_average_downloadspeed``"
 msgstr "``max_average_downloadspeed``"
 
-#: ../../config.rst:299
+#: ../../config.rst:303
 msgid "Maximum average download speed. Just like ``max_downloadspeed``."
 msgstr "最大平均下载速度，如同 ``max_downloadspeed`` 。"
 
-#: ../../config.rst:300
+#: ../../config.rst:304
 msgid "``min_average_uploadspeed``"
 msgstr "``min_average_uploadspeed``"
 
-#: ../../config.rst:303
+#: ../../config.rst:307
 msgid "Minimum average upload speed. Just like ``min_uploadspeed``."
 msgstr "最小平均上传速度，如同 ``min_uploadspeed`` 。"
 
-#: ../../config.rst:304
+#: ../../config.rst:308
 msgid "``max_size``"
 msgstr "``max_size``"
 
-#: ../../config.rst:307
+#: ../../config.rst:311
 msgid ""
 "Torrent size limitation. Remove those torrents whose size exceeds the "
 "limit."
 msgstr "种子大小限制，超过此限制的种子会被删除。"
 
-#: ../../config.rst:308
+#: ../../config.rst:312
 msgid "``max_seeder``"
 msgstr "``max_seeder``"
 
-#: ../../config.rst:311
+#: ../../config.rst:315
 msgid ""
 "Maximum number of seeders. When the seeders exceeds the limitation, the "
 "torrent will be removed."
 msgstr "最大做种者数，超过此限制的种子会被删除。"
 
-#: ../../config.rst:312
+#: ../../config.rst:316
 msgid "``max_upload``"
 msgstr "``max_upload``"
 
-#: ../../config.rst:315
+#: ../../config.rst:319
 msgid ""
 "Maximum uploaded size of a torrent. Torrents whose uploaded size exceed "
 "this limitation will be removed."
 msgstr "种子的最大上传体积，超过此限制的种子会被删除。"
 
-#: ../../config.rst:316
+#: ../../config.rst:320
 msgid "``min_leecher``"
 msgstr "``min_leecher``"
 
-#: ../../config.rst:319
+#: ../../config.rst:323
 msgid ""
 "Minimum number of leechers. When the number of leechers is less than the "
 "settings, the torrent will be removed."
 msgstr "最小下载者数，低于此设置的种子会被删除。"
 
-#: ../../config.rst:320
+#: ../../config.rst:324
 msgid "``max_connected_seeder``"
 msgstr "``max_connected_seeder``"
 
-#: ../../config.rst:323
+#: ../../config.rst:327
 msgid "Maximum number of connected seeders. Just like ``max_seeder``."
 msgstr "已连接做种者的最大值，如同 ``max_seeder`` 。"
 
-#: ../../config.rst:324
+#: ../../config.rst:328
 msgid "``min_connected_leecher``"
 msgstr "``min_connected_leecher``"
 
-#: ../../config.rst:327
+#: ../../config.rst:331
 msgid "Minimum number of connected leechers. Just like ``min_leecher``."
 msgstr "已连接下载者数的最小值，如同 ``min_leecher``。"
 
-#: ../../config.rst:328 ../../config.rst:502
+#: ../../config.rst:332 ../../config.rst:523
 msgid "``last_activity``"
 msgstr "``last_activity``"
 
-#: ../../config.rst:331
+#: ../../config.rst:335
 msgid ""
 "The maximum time allowed since a torrent has stopped being active, that "
 "is, the maximum time without uploading or downloading. When the torrent "
 "reaches the limit, it will be removed."
 msgstr "种子从停止活动到现在所允许经过的最长时间，即允许的没有上传或下载活动的最长时间。当种子到达此限制时，它就会被删除。"
 
-#: ../../config.rst:332
+#: ../../config.rst:336
 msgid "``max_progress``"
 msgstr "``max_progress``"
 
-#: ../../config.rst:333
+#: ../../config.rst:337
 msgid "Percent (%)"
 msgstr "百分比 (%)"
 
-#: ../../config.rst:335
+#: ../../config.rst:339
 msgid "The maximum download progress. The maximum value is 100."
 msgstr "允许的最大下载进度，最大值是100。"
 
-#: ../../config.rst:336 ../../config.rst:534
+#: ../../config.rst:340 ../../config.rst:555
 msgid "``upload_ratio``"
 msgstr "``upload_ratio``"
 
-#: ../../config.rst:339
+#: ../../config.rst:343
 msgid ""
 "The maximum upload ratio. Note that the upload ratio here is different "
 "from the ratio. For each torrent, the upload ratio is ``uploaded size`` "
 "divided by its ``size``."
 msgstr "最大上传比率。注意，此处的上传比率与分享率不同，对于每个种子来说，上传比率是指上传量除以种子大小的比值。"
 
-#: ../../config.rst:341
+#: ../../config.rst:347
+msgid ""
+"In version 1.5.4 and above, the behavior of ``last_activity`` has been "
+"changed. By default, it only considers those torrents that have ever been"
+" active, and the other torrents, which have no activity yet, won't be "
+"deleted."
+msgstr ""
+"对于 1.5.4 或以上版本，``last_activity`` 的默认行为已经改变。在默认情况下，``last_activity`` "
+"只考虑曾经活动过的种子；而对于从未活动过的种子，``last_activity`` 不会删除它们。"
+
+#: ../../config.rst:349
+msgid ""
+"Moreover, to remove those torrents that have never been active, please "
+"use ``last_activity: Never`` or ``last_activity: None``."
+msgstr "此外，若需要删除从未活动过的种子，请使用 ``last_activity: Never`` 或者 ``last_activity: None``。"
+
+#: ../../config.rst:351
 msgid ""
 "Beside these condition, the other 3 remove conditions are here. The rest "
 "of the torrents will be removed if they trigger these conditions."
 msgstr "除了上面的删种条件，这里还有 3 个删种条件。当剩下的种子触发这些删种条件时，它们就会被删除。"
 
-#: ../../config.rst:343
+#: ../../config.rst:353
 msgid ""
 "``seed_size``: Calculate the total size of the torrents you chosen. If "
 "the total size exceeds the limit, some of the torrents will be removed. "
 "The following two properties must be specificed."
 msgstr "``seed_size``：计算上述选择的种子的总大小。如果总大小超过限制，一部分种子会被删除。需要设置以下两个属性："
 
-#: ../../config.rst:345
+#: ../../config.rst:355
 msgid "``limit``: Limit of the total size, in GiB."
 msgstr "``limit``：总大小限制，以GiB为单位。"
 
-#: ../../config.rst:346
+#: ../../config.rst:356
 msgid ""
 "``action``: Determine which torrents will be removed. Can be the "
 "following values:"
 msgstr "``action``：确定哪部分种子将被删除。可以是以下值："
 
-#: ../../config.rst:351
+#: ../../config.rst:361
 msgid "Value"
 msgstr "值"
 
-#: ../../config.rst:353
+#: ../../config.rst:363
 msgid "remove-old-seeds"
 msgstr "remove-old-seeds"
 
-#: ../../config.rst:354
-msgid "Try to remove old seeds."
+#: ../../config.rst:364
+msgid "Try to remove old torrents."
 msgstr "尽量删除旧的种子。"
 
-#: ../../config.rst:355
+#: ../../config.rst:365
 msgid "remove-new-seeds"
 msgstr "remove-new-seeds"
 
-#: ../../config.rst:356
-msgid "Try to remove new seeds."
+#: ../../config.rst:366
+msgid "Try to remove new torrents."
 msgstr "尽量删除新的种子。"
 
-#: ../../config.rst:357
+#: ../../config.rst:367
 msgid "remove-big-seeds"
 msgstr "remove-big-seeds"
 
-#: ../../config.rst:358
-msgid "Try to remove large seeds."
+#: ../../config.rst:368
+msgid "Try to remove large torrents."
 msgstr "尽量删除体积大的种子。"
 
-#: ../../config.rst:359
+#: ../../config.rst:369
 msgid "remove-small-seeds"
 msgstr "remove-small-seeds"
 
-#: ../../config.rst:360
-msgid "Try to remove small seeds."
+#: ../../config.rst:370
+msgid "Try to remove small torrents."
 msgstr "尽量删除体积小的种子。"
 
-#: ../../config.rst:361
+#: ../../config.rst:371
 msgid "remove-active-seeds"
 msgstr "remove-active-seeds"
 
-#: ../../config.rst:362
-msgid "Try to remove active seeds."
+#: ../../config.rst:372
+msgid "Try to remove active torrents."
 msgstr "尽量删除活跃的种子。"
 
-#: ../../config.rst:363
+#: ../../config.rst:373
 msgid "remove-inactive-seeds"
 msgstr "remove-inactive-seeds"
 
-#: ../../config.rst:364
-msgid "Try to remove inactive seeds."
+#: ../../config.rst:374
+msgid "Try to remove inactive torrents."
 msgstr "尽量删除不活跃的种子。"
 
-#: ../../config.rst:367
+#: ../../config.rst:375
+msgid "remove-fast-upload-seeds"
+msgstr "remove-fast-upload-seeds"
+
+#: ../../config.rst:376
+msgid "Try to remove torrents with fast upload speeds."
+msgstr "尽量删除上传速度快的种子。"
+
+#: ../../config.rst:377
+msgid "remove-slow-upload-seeds"
+msgstr "remove-slow-upload-seeds"
+
+#: ../../config.rst:378
+msgid "Try to remove torrents with slow upload speeds."
+msgstr "尽量删除上传速度慢的种子。"
+
+#: ../../config.rst:382
+msgid ""
+"Similar to ``last_activity``, the action ``remove-active-seeds`` and "
+"``remove-inactive-seeds`` first consider those torrents that were once "
+"active. Only if these torrents are all removed but the constraints are "
+"still not met, the torrents that have never been active can be removed "
+"(but the order is not guaranteed)."
+msgstr ""
+"与 ``last_activity`` 类似，``remove-active-seeds`` 与 ``remove-inactive-"
+"seeds`` "
+"动作将优先考虑曾经活动过的种子。只有在这些种子都被删除但限制条件仍然没有被满足的情况下，从未活动过的种子才会被删除（但不保证删除顺序）。"
+
+#: ../../config.rst:384
 msgid ""
 "``maximum_number``: Set the maximum number of torrents. When the number "
 "of chosen torrents is exceed the maximum number, some of the torrents "
@@ -691,17 +744,17 @@ msgstr ""
 "``maximum_number``：判断上述选择的选择的种子的总个数。如果个数超出设置的最大值，一部分种子会被删除，就像 `seed_size`"
 " 条件一样。需要设置以下两个属性："
 
-#: ../../config.rst:369
+#: ../../config.rst:386
 msgid "``limit``: Maximum number limitation"
 msgstr "``limit``：总个数限制"
 
-#: ../../config.rst:370
+#: ../../config.rst:387
 msgid ""
 "``action``: Determine which torrents will be removed. The values and its "
 "meanings are in the table above."
 msgstr "``action``：确定哪些种子会被删除，取值与含义同上表。"
 
-#: ../../config.rst:372
+#: ../../config.rst:389
 msgid ""
 "``free_space``: Check the free space on disk is enough or not. When the "
 "free space is not enough, some of the chosen torrents will be deleted, "
@@ -711,24 +764,24 @@ msgstr ""
 "``free_space``：检查磁盘的剩余空间是否符合设定。如果空间不足，一部分种子会被删除，就像 seed_size "
 "条件一样。需要设置以下三个属性："
 
-#: ../../config.rst:374
+#: ../../config.rst:391
 msgid ""
 "``min``: Minimum free space, in `GiB`. When the free space of the "
 "specified directory is less than this value, the removing strategy will "
 "be trigger."
 msgstr "``min``：剩余空间最小值，以`GiB`为单位；当目录的剩余空间小于这个值时，删除策略会被触发。"
 
-#: ../../config.rst:375
+#: ../../config.rst:392
 msgid "``path``: Directory that needs to be monitored"
 msgstr "``path``：需要监控剩余空间的目录"
 
-#: ../../config.rst:376
+#: ../../config.rst:393
 msgid ""
 "``action``: Removing strategy, which determines which torrents will be "
 "removed. The values and its meanings are in the table above."
 msgstr "``action``：删除策略，用于确定哪些种子会被删除。取值与含义同上表"
 
-#: ../../config.rst:378
+#: ../../config.rst:395
 msgid ""
 "``remote_free_space``: Decide which torrents to be removed based on the "
 "free space too, but use the free space data reported by the bittorrent "
@@ -737,19 +790,19 @@ msgstr ""
 "``remote_free_space``：同样也是根据磁盘剩余空间来决定哪些种子会被删除，但这里使用BT客户端汇报的磁盘剩余空间大小。它的行为与"
 " ``free_space`` 一致。"
 
-#: ../../config.rst:380
+#: ../../config.rst:397
 msgid "``min``: Minimum free space, in `GiB`."
 msgstr "``min``：允许的剩余空间最小值，以 `GiB` 为单位。"
 
-#: ../../config.rst:381
+#: ../../config.rst:398
 msgid "``path``: Directory that needs to be checked by the bittorrent client."
 msgstr "``path``：BT客户端需要检查剩余空间大小的目录路径"
 
-#: ../../config.rst:382
+#: ../../config.rst:399
 msgid "``action``: Removing strategy."
 msgstr "``action``：删除策略"
 
-#: ../../config.rst:386
+#: ../../config.rst:403
 msgid ""
 "If your autoremove-torrents and your bittorrent client are running on "
 "different machines, you need to use ``remote_free_space`` to check the "
@@ -759,7 +812,7 @@ msgstr ""
 "如果你的 autoremove-torrents 和你的 BT 客户端运行在不同的机器上，你就需要使用 ``remote_free_space``"
 " 去查询剩余空间了。除此之外，``free_space`` 和 ``remote_free_space`` 是一样的。"
 
-#: ../../config.rst:388
+#: ../../config.rst:405
 msgid ""
 "Please note that not all of the clients support checking the specified "
 "path. Currently, only Deluge and Transmission support, and the parameter "
@@ -768,27 +821,27 @@ msgstr ""
 "请注意，并不是所有的客户端都支持检测特定目录的剩余空间。截至目前，只有 Deluge 和 Transmission 支持查询特定目录；若在 "
 "qBittorrent 中使用 ``remote_free_space`` 的 ``path`` 参数，它将会被忽略。"
 
-#: ../../config.rst:390
+#: ../../config.rst:407
 msgid ""
 "Here is an example. For torrents whose categories are xxx or yyy, it "
 "removes the torrents which ratio is greater than 1 or seeding time is "
 "more than 1209600 seconds:"
 msgstr "这是一个例子。对于分类是 xxx 或 yyy 的种子，分享率大于1或者做种时间大于1209600秒的种子会被删除："
 
-#: ../../config.rst:408
+#: ../../config.rst:425
 msgid ""
 "Here is another example. For all torrents, it removes the torrents which "
 "seeding time is greater than 259200 seconds:"
 msgstr "这也是一个例子。对于全体种子，做种时间大于259200秒的种子会被删除："
 
-#: ../../config.rst:422
+#: ../../config.rst:439
 msgid ""
 "Here is another another example. For all torrents, when the free space in"
 " directory `/home/myserver/downloads` is less than 10GiB, the program "
 "will try to remove the big torrents:"
 msgstr "这还有一个例子。对于全体种子，当 `/home/myserver/downloads` 的剩余空间小于10GiB时，程序会尝试删除体积大的种子："
 
-#: ../../config.rst:438
+#: ../../config.rst:455
 msgid ""
 "Here is the last example. For all torrents, remove those torrents whose "
 "ratio is greater than 3 first, and then if the total size of the rest of "
@@ -798,11 +851,11 @@ msgstr ""
 "这是最后一个例子。对于全体种子，首先删掉那些分享率大于 3 的种子，然后如果剩下的种子的总大小还大于 500GiB "
 "就尽量删除一些活跃的种子，直到总大小小于 500GiB 为止："
 
-#: ../../config.rst:455
+#: ../../config.rst:472
 msgid "2. Use ``remove`` Keyword (Advanced)"
 msgstr "2. 使用 ``remove`` 关键词 （高级)"
 
-#: ../../config.rst:457
+#: ../../config.rst:474
 msgid ""
 "Use the ``remove`` keyword. The ``remove`` keyword is a new keyword in "
 "version 1.4.0, which supports the complex removing condition. The "
@@ -812,181 +865,189 @@ msgstr ""
 "使用 ``remove`` 关键词。``remove`` "
 "关键词是在1.4.0版本中新增的关键词，用于支持复杂的删除条件的设置。``remove`` 关键词后接一个表达式，表达式由以下语法构成："
 
-#: ../../config.rst:459
+#: ../../config.rst:476
 msgid "``<Parameter> <Comparison Operator> <Value>``"
 msgstr "``<参数> <比较运算符> <数值>``"
 
-#: ../../config.rst:461
+#: ../../config.rst:478
 msgid ""
 "``Parameter``: Available parameters are as follows, and they are case-"
 "insensitive."
 msgstr "``参数``：可选列表如下，不区分大小写。"
 
-#: ../../config.rst:465
+#: ../../config.rst:482
 msgid ""
 "Some properties can only be used in specific status. The torrents not in "
 "available status will not be removed."
 msgstr "某些属性只能在特定的状态中使用，不在可用状态的种子不会被删除。"
 
-#: ../../config.rst:470
+#: ../../config.rst:487
 msgid "Parameter"
 msgstr "参数"
 
-#: ../../config.rst:474
+#: ../../config.rst:491
 msgid "``average_downloadspeed``"
 msgstr "``average_downloadspeed``"
 
-#: ../../config.rst:477
+#: ../../config.rst:494
 msgid "Average download speed."
 msgstr "平均下载速度。"
 
-#: ../../config.rst:478
+#: ../../config.rst:495
 msgid "``average_uploadspeed``"
 msgstr "``average_uploadspeed``"
 
-#: ../../config.rst:481
+#: ../../config.rst:498
 msgid "Average upload speed."
 msgstr "平均上传速度。"
 
-#: ../../config.rst:482
+#: ../../config.rst:499
 msgid "``connected_leecher``"
 msgstr "``connected_leecher``"
 
-#: ../../config.rst:485
+#: ../../config.rst:502
 msgid "The number of connected leecher."
 msgstr "已连接的下载者数。"
 
-#: ../../config.rst:486
+#: ../../config.rst:503
 msgid "``connected_seeder``"
 msgstr "``connected_seeder``"
 
-#: ../../config.rst:489
+#: ../../config.rst:506
 msgid "The number of connected seeder."
 msgstr "已连接的做种者数。"
 
-#: ../../config.rst:493
+#: ../../config.rst:510
 msgid "The elapsed time since the torrent was added to the client."
 msgstr "种子从添加到客户端到现在所经过的时间。"
 
-#: ../../config.rst:494
+#: ../../config.rst:511
 msgid "``download``"
 msgstr "``download``"
 
-#: ../../config.rst:497
+#: ../../config.rst:514
 msgid "Downloaded Size"
 msgstr "下载量"
 
-#: ../../config.rst:498
+#: ../../config.rst:515
 msgid "``download_speed``"
 msgstr "``download_speed``"
 
-#: ../../config.rst:501
+#: ../../config.rst:518
 msgid "Download speed."
 msgstr "下载速度"
 
-#: ../../config.rst:505
+#: ../../config.rst:522
+msgid "Downloading time."
+msgstr "下载时间。"
+
+#: ../../config.rst:526
 msgid ""
 "The elapsed time since the torrent has stopped being active (without "
 "uploading or downloading)."
 msgstr "种子从停止活动（无上传或下载）到现在所经过的时间。"
 
-#: ../../config.rst:506
+#: ../../config.rst:527
 msgid "``leecher``"
 msgstr "``leecher``"
 
-#: ../../config.rst:509
+#: ../../config.rst:530
 msgid "The number of leechers."
 msgstr "下载者数。"
 
-#: ../../config.rst:510
+#: ../../config.rst:531
 msgid "``progress``"
 msgstr "``progress``"
 
-#: ../../config.rst:511
+#: ../../config.rst:532
 msgid "%"
 msgstr "%"
 
-#: ../../config.rst:513
+#: ../../config.rst:534
 msgid "The download progress."
 msgstr "下载进度。"
 
-#: ../../config.rst:517
+#: ../../config.rst:538
 msgid "Ratio"
 msgstr "分享率"
 
-#: ../../config.rst:518
+#: ../../config.rst:539
 msgid "``seeder``"
 msgstr "``seeder``"
 
-#: ../../config.rst:521
+#: ../../config.rst:542
 msgid "The number of seeders."
 msgstr "做种者数。"
 
-#: ../../config.rst:525
+#: ../../config.rst:546
 msgid "Seeding time."
 msgstr "做种时间"
 
-#: ../../config.rst:526
+#: ../../config.rst:547
 msgid "``size``"
 msgstr "``size``"
 
-#: ../../config.rst:529
+#: ../../config.rst:550
 msgid "The torrent size."
 msgstr "种子大小。"
 
-#: ../../config.rst:530
+#: ../../config.rst:551
 msgid "``upload``"
 msgstr "``upload``"
 
-#: ../../config.rst:533=
+#: ../../config.rst:554
 msgid "Uploaded Size"
 msgstr "上传量"
 
-#: ../../config.rst:537
+#: ../../config.rst:558
 msgid "uploaded size / size"
 msgstr "上传量 / 种子大小"
 
-#: ../../config.rst:538
+#: ../../config.rst:559
 msgid "``upload_speed``"
 msgstr "``upload_speed``"
 
-#: ../../config.rst:541
+#: ../../config.rst:562
 msgid "Upload Speed"
 msgstr "上传速度"
 
-#: ../../config.rst:543
-msgid ""
-"``Comparison Operator``: Available parameters are as follows. This "
-"program doesn't provide the ``equal`` sign, because the status data of "
-"the torrents change quickly, and usually it's meaningless to set a "
-"specific value."
-msgstr "``比较运算符``：可选列表如下。由于种子的状态数据变化快，通常情况下设置一个特定的数据没有意义，因此本程序不提供等号。"
+#: ../../config.rst:564
+msgid "``Comparison Operator``: Available operators are as follows."
+msgstr "``比较运算符``：可用的运算符如下。"
 
-#: ../../config.rst:548
+#: ../../config.rst:569
 msgid "Comparison Operator"
 msgstr "比较运算符"
 
-#: ../../config.rst:550
+#: ../../config.rst:571
 msgid "``<``"
 msgstr "``<``"
 
-#: ../../config.rst:551
+#: ../../config.rst:572
 msgid "Less Than"
 msgstr "小于"
 
-#: ../../config.rst:552
+#: ../../config.rst:573
 msgid "``>``"
 msgstr "``>``"
 
-#: ../../config.rst:553
+#: ../../config.rst:574
 msgid "Greater Than"
 msgstr "大于"
 
-#: ../../config.rst:555
+#: ../../config.rst:575
+msgid "``=``"
+msgstr "``=``"
+
+#: ../../config.rst:576
+msgid "Equals"
+msgstr "等于"
+
+#: ../../config.rst:578
 msgid "``Value``: Specify a numeric value. Supports integers and floats."
 msgstr "``数值``：指定一个数值，支持整数和小数。"
 
-#: ../../config.rst:557
+#: ../../config.rst:580
 msgid ""
 "This syntax selects the eligible torrents directly, and removes them "
 "directly or works with the following compound expressions. Here is an "
@@ -994,52 +1055,52 @@ msgid ""
 "259200 seconds:"
 msgstr "该语法直接选出符合条件的种子，并直接删除它们或者与后面的复合表达式配合使用。这是一个例子，它直接删除做种时间大于259200秒的种子："
 
-#: ../../config.rst:571
+#: ../../config.rst:594
 msgid ""
 "``<Expression 1> and <Expression 2>`` and ``<Expression 1> or <Expression"
 " 2>``"
 msgstr "``<表达式1> and <表达式2>`` 以及 ``<表达式1> or <表达式2>``"
 
-#: ../../config.rst:573
+#: ../../config.rst:596
 msgid "This syntax is a compound expression."
 msgstr "该语法是复合表达式。"
 
-#: ../../config.rst:575
+#: ../../config.rst:598
 msgid ""
 "``and``: Select torrents that meet both the ``Expression 1`` and "
 "``Expression 2`` (intersection)."
 msgstr "``and``：选择同时满足 ``表达式1`` 和 ``表达式2`` 的种子（交集）。"
 
-#: ../../config.rst:576
+#: ../../config.rst:599
 msgid ""
 "``or``: Select torrents that meet one or both of the ``Expression 1`` and"
 " ``Expression 2`` (Union)."
 msgstr "``or``：选择满足 ``表达式1`` 或者 ``表达式2`` 或者同时满足两个表达式的种子（并集）。"
 
-#: ../../config.rst:578
+#: ../../config.rst:601
 msgid ""
 "Here is an example. For all torrents, it removes those torrents which "
 "ratio is greater than 2 **and** seeding time is more than 60000 seconds:"
 msgstr "这是一个例子。对于全体种子，分享率超过 2 **而且** 做种时间超过 60000 秒的种子会被删除："
 
-#: ../../config.rst:592
+#: ../../config.rst:615
 msgid ""
 "Here is another example. For all torrents, it removes those torrents "
 "which ratio is less than 1 **or** seeding time is more than 60000:"
 msgstr "这是另外一个例子。对于全体种子，分享率小于 1 **或者** 做种时间超过 60000 秒的种子会被删除："
 
-#: ../../config.rst:606
+#: ../../config.rst:629
 msgid "``(<Expression>)``"
 msgstr "``(<表达式>)``"
 
-#: ../../config.rst:608
+#: ../../config.rst:631
 msgid ""
 "When an expression is enclosed in parentheses, it is still an expression."
 " Using parentheses can change the priority. And you can use multiple "
 "parentheses for nesting."
 msgstr "一个表达式加上括号以后，它仍然是表达式。使用括号可以改变优先级。可以使用多重括号嵌套。"
 
-#: ../../config.rst:610
+#: ../../config.rst:633
 msgid ""
 "Here is an example. For all torrents, it removes those torrents which "
 "seeding time is more than 60000 seconds, **or** those torrents which "
@@ -1048,21 +1109,21 @@ msgstr ""
 "这是一个例子。对于全体种子，做种时间超过 60000 秒的种子， **或者** 分享率大于 3 **而且** 添加时间超过 1400000 "
 "秒的种子会被删除："
 
-#: ../../config.rst:625
+#: ../../config.rst:648
 msgid "Part 4: Delete data"
 msgstr "第四部分：删除数据"
 
-#: ../../config.rst:627
+#: ../../config.rst:650
 msgid ""
 "Determine whether to delete data at the same time. If this field isn't "
 "specificed, the default value is ``false``."
 msgstr "决定是否在删除种子的同时也删除数据。如果此字段未指定，则默认值为 ``false`` 。"
 
-#: ../../config.rst:630
+#: ../../config.rst:653
 msgid "The Last Step..."
 msgstr "最后一步……"
 
-#: ../../config.rst:632
+#: ../../config.rst:655
 msgid ""
 "Remember to check your configuration file and make sure it works as you "
 "think. Use the following command line to see the torrents that will be "
@@ -1078,3 +1139,12 @@ msgstr "记得检查你的配置文件，确保它按照你的想法工作（不
 #~ " same as the ``free_space``."
 #~ msgstr ""
 
+#~ msgid ""
+#~ "``Comparison Operator``: Available parameters "
+#~ "are as follows. This program doesn't "
+#~ "provide the ``equal`` sign, because the"
+#~ " status data of the torrents change"
+#~ " quickly, and usually it's meaningless "
+#~ "to set a specific value."
+#~ msgstr "``比较运算符``：可选列表如下。由于种子的状态数据变化快，通常情况下设置一个特定的数据没有意义，因此本程序不提供等号。"
+
diff --git a/docs/locales/zh_CN/LC_MESSAGES/intro.po b/docs/locales/zh_CN/LC_MESSAGES/intro.po
index 9c96d8e..e9217a3 100644
--- a/docs/locales/zh_CN/LC_MESSAGES/intro.po
+++ b/docs/locales/zh_CN/LC_MESSAGES/intro.po
@@ -9,14 +9,14 @@ msgid ""
 msgstr ""
 "Project-Id-Version: autoremove-torrents \n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2020-08-25 15:01+0800\n"
+"POT-Creation-Date: 2022-04-29 16:12+0800\n"
 "PO-Revision-Date: 2020-02-02 17:29+0800\n"
 "Last-Translator: jerrymakesjelly <ganzhaoyu037@gmail.com>\n"
 "Language-Team: Chinese (Simplified)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=utf-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.8.0\n"
+"Generated-By: Babel 2.10.1\n"
 
 #: ../../intro.rst:4
 msgid "Introduction"
@@ -42,9 +42,10 @@ msgstr "支持的客户端"
 
 #: ../../intro.rst:13
 msgid ""
-"Until now, this program supports qBittorrent/Transmission/μTorrent. "
-"Deluge and rTorrent are both on my planning list."
-msgstr "截至目前，程序支持 qBittorrent/Transmission/μTorrent。Deluge 和 rTorrent 正在计划之中。"
+"Until now, this program supports "
+"qBittorrent/Transmission/μTorrent/Deluge. rTorrent is on my planning "
+"list."
+msgstr "截至目前，程序支持 qBittorrent/Transmission/μTorrent/Deluge。rTorrent 正在计划之中。"
 
 #: ../../intro.rst:18
 msgid "Client"
@@ -58,7 +59,7 @@ msgstr "支持情况"
 msgid "qBittorrent"
 msgstr "qBittorrent"
 
-#: ../../intro.rst:21 ../../intro.rst:23 ../../intro.rst:25
+#: ../../intro.rst:21 ../../intro.rst:23 ../../intro.rst:25 ../../intro.rst:27
 msgid "Yes"
 msgstr "是"
 
@@ -74,14 +75,14 @@ msgstr "μTorrent"
 msgid "Deluge"
 msgstr "Deluge"
 
-#: ../../intro.rst:27 ../../intro.rst:29
-msgid "On Planning"
-msgstr "计划中"
-
 #: ../../intro.rst:28
 msgid "rTorrent"
 msgstr "rTorrent"
 
+#: ../../intro.rst:29
+msgid "On Planning"
+msgstr "计划中"
+
 #: ../../intro.rst:32
 msgid "Supported Properties"
 msgstr "支持的属性"
@@ -117,18 +118,19 @@ msgstr "✓ :superscript:`2.0 或更高版本`"
 #: ../../intro.rst:113 ../../intro.rst:114 ../../intro.rst:116
 #: ../../intro.rst:117 ../../intro.rst:118 ../../intro.rst:119
 #: ../../intro.rst:121 ../../intro.rst:122 ../../intro.rst:123
-#: ../../intro.rst:124 ../../intro.rst:126 ../../intro.rst:127
-#: ../../intro.rst:128 ../../intro.rst:129 ../../intro.rst:131
-#: ../../intro.rst:132 ../../intro.rst:133 ../../intro.rst:134
-#: ../../intro.rst:136 ../../intro.rst:137 ../../intro.rst:138
-#: ../../intro.rst:139 ../../intro.rst:141 ../../intro.rst:142
-#: ../../intro.rst:143 ../../intro.rst:144 ../../intro.rst:146
-#: ../../intro.rst:147 ../../intro.rst:148 ../../intro.rst:149
+#: ../../intro.rst:124 ../../intro.rst:127 ../../intro.rst:128
+#: ../../intro.rst:131 ../../intro.rst:132 ../../intro.rst:133
+#: ../../intro.rst:134 ../../intro.rst:136 ../../intro.rst:137
+#: ../../intro.rst:138 ../../intro.rst:139 ../../intro.rst:141
+#: ../../intro.rst:142 ../../intro.rst:143 ../../intro.rst:144
+#: ../../intro.rst:146 ../../intro.rst:147 ../../intro.rst:148
+#: ../../intro.rst:149 ../../intro.rst:151 ../../intro.rst:152
+#: ../../intro.rst:153 ../../intro.rst:154
 msgid "✓"
 msgstr "✓"
 
 #: ../../intro.rst:49 ../../intro.rst:54 ../../intro.rst:74 ../../intro.rst:89
-#: ../../intro.rst:94
+#: ../../intro.rst:94 ../../intro.rst:126 ../../intro.rst:129
 msgid "✗"
 msgstr "✗"
 
@@ -165,13 +167,12 @@ msgid "Download Speed"
 msgstr "下载速度"
 
 #: ../../intro.rst:80
-#, fuzzy
 msgid "Downloaded Size"
-msgstr "下载速度"
+msgstr "下载量"
 
 #: ../../intro.rst:85
 msgid "Free Space"
-msgstr ""
+msgstr "空闲空间"
 
 #: ../../intro.rst:90
 msgid "Last Activity"
@@ -206,22 +207,26 @@ msgid "Size"
 msgstr "种子大小"
 
 #: ../../intro.rst:125
+msgid "Stall Status"
+msgstr "空闲状态（Stall）"
+
+#: ../../intro.rst:130
 msgid "Status"
 msgstr "状态"
 
-#: ../../intro.rst:130
+#: ../../intro.rst:135
 msgid "Tracker"
 msgstr "Tracker"
 
-#: ../../intro.rst:135
+#: ../../intro.rst:140
 msgid "Upload Ratio"
 msgstr "上传比率"
 
-#: ../../intro.rst:140
+#: ../../intro.rst:145
 msgid "Upload Speed"
 msgstr "上传速度"
 
-#: ../../intro.rst:145
+#: ../../intro.rst:150
 msgid "Uploaded Size"
-msgstr ""
+msgstr "上传量"
 


Test patch:
diff --git a/pytest/test_strategies/README.rst b/pytest/test_strategies/README.rst
index 46c892c..a80f063 100644
--- a/pytest/test_strategies/README.rst
+++ b/pytest/test_strategies/README.rst
@@ -144,6 +144,98 @@ Sort by Create Time, Ascending
      - 
      - Paused
 
+Sort by Downloading Time, Ascending
+++++++++++++++++++++++++++++++++++++
+
+.. list-table::
+   :header-rows: 1
+
+   * - Name
+     - downloading_time
+     - Category
+     - Tracker
+     - State
+   * - Torrent - 13
+     - 1
+     -
+     - 
+     - Checking
+   * - Torrent - 14
+     - 2
+     -
+     - https://www.site2.org/tracker/announce
+     - Queued
+   * - Torrent - 15
+     - 3
+     -
+     - 
+     - Paused
+   * - Torrent - 16
+     - 4
+     -
+     - 
+     - Stopped
+   * - Torrent - 10
+     - 120
+     - Category - 2
+     - https://www.site2.org/tracker/announce
+     - Uploading
+   * - Torrent - 9
+     - 4932
+     - Category - 3
+     - http://tracker.site3.com/?action=announce
+     - Uploading
+   * - Torrent - 2
+     - 5022
+     - Category - 2
+     - https://www.site2.org/tracker/announce
+     - Downloading
+   * - Torrent - 8
+     - 23033
+     - Category - 2
+     - https://www.site2.org/tracker/announce
+     - Uploading
+   * - Torrent - 3
+     - 25933
+     - Category - 2
+     - https://www.site2.org/tracker/announce
+     - Uploading
+   * - Torrent - 4
+     - 39203
+     - Category - 3
+     - http://tracker.site3.com/?action=announce
+     - Uploading
+   * - Torrent - 1
+     - 41322
+     - Category - 1
+     - https://tracker.site1.com/announce
+     - Downloading
+   * - Torrent - 5
+     - 42003
+     - Category - 2
+     - https://www.site2.org/tracker/announce
+     - Uploading
+   * - Torrent - 12
+     - 43222
+     - Category - 2
+     - https://www.site2.org/tracker/announce
+     - Downloading
+   * - Torrent - 6
+     - 43233
+     - Category - 2
+     - https://www.site2.org/tracker/announce
+     - Uploading
+   * - Torrent - 11
+     - 43322
+     - Category - 1
+     - https://tracker.site1.com/announce
+     - Downloading
+   * - Torrent - 7
+     - 66992
+     - Category - 1
+     - https://tracker.site1.com/announce
+     - Uploading
+
 Sort by Finishing Time, Ascending
 ++++++++++++++++++++++++++++++++++
 
@@ -799,11 +891,6 @@ Sort by Last Active Time, Ascending
      - Category
      - Tracker
      - State
-   * - Torrent - 4
-     - 1526614323
-     - Category - 3
-     - http://tracker.site3.com/?action=announce
-     - Uploading
    * - Torrent - 9
      - 1526730151
      - Category - 3
@@ -879,6 +966,11 @@ Sort by Last Active Time, Ascending
      - 
      - 
      - Stopped
+   * - Torrent - 4
+     - Never Active
+     - Category - 3
+     - http://tracker.site3.com/?action=announce
+     - Uploading
 
 .. list-table::
    :header-rows: 1
@@ -1809,82 +1901,82 @@ Sort by Size, Ascending
      - Tracker
      - State
    * - Torrent - 14
-     - 312186667
+     - 312186667 (0.29 GiB)
      - 
      - https://www.site2.org/tracker/announce
      - Queued
    * - Torrent - 3
-     - 347000034
+     - 347000034 (0.32 GiB)
      - Category - 2
      - https://www.site2.org/tracker/announce
      - Uploading
    * - Torrent - 16
-     - 1132013553
+     - 1132013553 (1.05 GiB)
      - 
      - 
      - Stopped
    * - Torrent - 13
-     - 1746686185
+     - 1746686185 (1.63 GiB)
      - 
      - 
      - Checking
    * - Torrent - 15
-     - 2126568405
+     - 2126568405 (1.98 GiB)
      - 
      - 
      - Paused
    * - Torrent - 9
-     - 3022394751
+     - 3022394751 (2.81 GiB)
      - Category - 3
      - http://tracker.site3.com/?action=announce
      - Uploading
    * - Torrent - 12
-     - 4030908717
+     - 4030908717 (3.75 GiB)
      - Category - 2
      - https://www.site2.org/tracker/announce
      - Downloading
    * - Torrent - 7
-     - 7239185152
+     - 7239185152 (6.74 GiB)
      - Category - 1
      - https://tracker.site1.com/announce
      - Uploading
    * - Torrent - 8
-     - 7619309310
+     - 7619309310 (7.10 GiB)
      - Category - 2
      - https://www.site2.org/tracker/announce
      - Uploading
    * - Torrent - 5
-     - 9627866528
+     - 9627866528 (8.96 GiB)
      - Category - 2
      - https://www.site2.org/tracker/announce
      - Uploading
    * - Torrent - 4
-     - 10152029087
+     - 10152029087 (9.45 GiB)
      - Category - 3
      - http://tracker.site3.com/?action=announce
      - Uploading
    * - Torrent - 6
-     - 13200820552
+     - 13200820552 (12.29 GiB)
      - Category - 2
      - https://www.site2.org/tracker/announce
      - Uploading
    * - Torrent - 1
-     - 13762548460
+     - 13762548460 (12.817 GiB)
      - Category - 1
      - https://tracker.site1.com/announce
      - Downloading
    * - Torrent - 11
-     - 13767802684
+     - 13767802684 (12.822 GiB)
      - Category - 1
      - https://tracker.site1.com/announce
      - Downloading
    * - Torrent - 10
-     - 14844911534
+     - 14844911534 (13.83 GiB)
      - Category - 2
      - https://www.site2.org/tracker/announce
      - Uploading
    * - Torrent - 2
-     - 27918469580
+     - 27918469580 (26.00 GiB)
      - Category - 2
      - https://www.site2.org/tracker/announce
      - Downloading
@@ -2351,7 +2443,7 @@ Sort by Amount of Uploaded Data in Current Session, Ascending
      - https://www.site2.org/tracker/announce
      - Downloading
 
-Sort by Current Download Speed, Ascending
+Sort by Current Upload Speed, Ascending
 ++++++++++++++++++++++++++++++++++++++++++
 
 .. list-table::
diff --git a/pytest/test_strategies/cases/downloading_time/test_downloading_time.yml b/pytest/test_strategies/cases/downloading_time/test_downloading_time.yml
new file mode 100644
index 0000000..85b3de2
--- /dev/null
+++ b/pytest/test_strategies/cases/downloading_time/test_downloading_time.yml
@@ -0,0 +1,4 @@
+test:
+  downloading_time: 50000
+remove:
+  - Torrent - 7
diff --git a/pytest/test_strategies/cases/free_space/test_free_space_with_remove_fast_upload_seeds.yml b/pytest/test_strategies/cases/free_space/test_free_space_with_remove_fast_upload_seeds.yml
new file mode 100644
index 0000000..e387f34
--- /dev/null
+++ b/pytest/test_strategies/cases/free_space/test_free_space_with_remove_fast_upload_seeds.yml
@@ -0,0 +1,7 @@
+test:
+  free_space:
+    min: 110
+    path: .
+    action: remove-fast-upload-seeds
+remove:
+  - Torrent - 2
diff --git a/pytest/test_strategies/cases/free_space/test_free_space_with_remove_slow_upload_seeds.yml b/pytest/test_strategies/cases/free_space/test_free_space_with_remove_slow_upload_seeds.yml
new file mode 100644
index 0000000..42e80cc
--- /dev/null
+++ b/pytest/test_strategies/cases/free_space/test_free_space_with_remove_slow_upload_seeds.yml
@@ -0,0 +1,16 @@
+test:
+  free_space:
+    min: 140
+    path: .
+    action: remove-slow-upload-seeds
+remove:
+  - Torrent - 3
+  - Torrent - 4
+  - Torrent - 5
+  - Torrent - 7
+  - Torrent - 8
+  - Torrent - 9
+  - Torrent - 13
+  - Torrent - 14
+  - Torrent - 15
+  - Torrent - 16
diff --git a/pytest/test_strategies/cases/last_activity/test_last_activity.yml b/pytest/test_strategies/cases/last_activity/test_last_activity.yml
index 9a35176..950ecd4 100644
--- a/pytest/test_strategies/cases/last_activity/test_last_activity.yml
+++ b/pytest/test_strategies/cases/last_activity/test_last_activity.yml
@@ -1,5 +1,4 @@
 test:
   last_activity: 700000
 remove:
-  - Torrent - 4
   - Torrent - 9
\ No newline at end of file
diff --git a/pytest/test_strategies/cases/last_activity/test_last_activity_never.yml b/pytest/test_strategies/cases/last_activity/test_last_activity_never.yml
new file mode 100644
index 0000000..fc5e82a
--- /dev/null
+++ b/pytest/test_strategies/cases/last_activity/test_last_activity_never.yml
@@ -0,0 +1,4 @@
+test:
+  last_activity: Never
+remove:
+  - Torrent - 4
\ No newline at end of file
diff --git a/pytest/test_strategies/cases/last_activity/test_last_activity_none.yml b/pytest/test_strategies/cases/last_activity/test_last_activity_none.yml
new file mode 100644
index 0000000..156f20c
--- /dev/null
+++ b/pytest/test_strategies/cases/last_activity/test_last_activity_none.yml
@@ -0,0 +1,4 @@
+test:
+  last_activity: None
+remove:
+  - Torrent - 4
\ No newline at end of file
diff --git a/pytest/test_strategies/cases/maximum_number/test_maximum_number_with_remove_fast_upload_seeds.yml b/pytest/test_strategies/cases/maximum_number/test_maximum_number_with_remove_fast_upload_seeds.yml
new file mode 100644
index 0000000..d90013e
--- /dev/null
+++ b/pytest/test_strategies/cases/maximum_number/test_maximum_number_with_remove_fast_upload_seeds.yml
@@ -0,0 +1,8 @@
+test:
+  maximum_number:
+    limit: 13
+    action: remove-fast-upload-seeds
+remove:
+  - Torrent - 1
+  - Torrent - 2
+  - Torrent - 12
diff --git a/pytest/test_strategies/cases/maximum_number/test_maximum_number_with_remove_inactive_seeds.yml b/pytest/test_strategies/cases/maximum_number/test_maximum_number_with_remove_inactive_seeds.yml
index 2c695be..f139d4f 100644
--- a/pytest/test_strategies/cases/maximum_number/test_maximum_number_with_remove_inactive_seeds.yml
+++ b/pytest/test_strategies/cases/maximum_number/test_maximum_number_with_remove_inactive_seeds.yml
@@ -3,4 +3,4 @@ test:
     limit: 15
     action: remove-inactive-seeds
 remove:
-  - Torrent - 4
\ No newline at end of file
+  - Torrent - 9
\ No newline at end of file
diff --git a/pytest/test_strategies/cases/maximum_number/test_maximum_number_with_remove_slow_upload_seeds.yml b/pytest/test_strategies/cases/maximum_number/test_maximum_number_with_remove_slow_upload_seeds.yml
new file mode 100644
index 0000000..ef912b1
--- /dev/null
+++ b/pytest/test_strategies/cases/maximum_number/test_maximum_number_with_remove_slow_upload_seeds.yml
@@ -0,0 +1,16 @@
+test:
+  maximum_number:
+    limit: 5
+    action: remove-slow-upload-seeds
+remove:
+  - Torrent - 3
+  - Torrent - 4
+  - Torrent - 5
+  - Torrent - 6
+  - Torrent - 7
+  - Torrent - 8
+  - Torrent - 9
+  - Torrent - 13
+  - Torrent - 14
+  - Torrent - 15
+  - Torrent - 16
diff --git a/pytest/test_strategies/cases/remote_free_space/test_remote_free_space_with_remove_big_seeds.yml b/pytest/test_strategies/cases/remote_free_space/test_remote_free_space_with_remove_big_seeds.yml
index 80a1e9f..1bb6b19 100644
--- a/pytest/test_strategies/cases/remote_free_space/test_remote_free_space_with_remove_big_seeds.yml
+++ b/pytest/test_strategies/cases/remote_free_space/test_remote_free_space_with_remove_big_seeds.yml
@@ -1,5 +1,5 @@
 test:
-  free_space:
+  remote_free_space:
     min: 110
     path: /
     action: remove-big-seeds
diff --git a/pytest/test_strategies/cases/remote_free_space/test_remote_free_space_with_remove_fast_upload_seeds.yml b/pytest/test_strategies/cases/remote_free_space/test_remote_free_space_with_remove_fast_upload_seeds.yml
new file mode 100644
index 0000000..71af405
--- /dev/null
+++ b/pytest/test_strategies/cases/remote_free_space/test_remote_free_space_with_remove_fast_upload_seeds.yml
@@ -0,0 +1,7 @@
+test:
+  remote_free_space:
+    min: 110
+    path: /
+    action: remove-fast-upload-seeds
+remove:
+  - Torrent - 2
diff --git a/pytest/test_strategies/cases/remote_free_space/test_remote_free_space_with_remove_new_seeds.yml b/pytest/test_strategies/cases/remote_free_space/test_remote_free_space_with_remove_new_seeds.yml
index 3e7b11e..64d4cc5 100644
--- a/pytest/test_strategies/cases/remote_free_space/test_remote_free_space_with_remove_new_seeds.yml
+++ b/pytest/test_strategies/cases/remote_free_space/test_remote_free_space_with_remove_new_seeds.yml
@@ -1,5 +1,5 @@
 test:
-  free_space:
+  remote_free_space:
     min: 110
     path: /
     action: remove-new-seeds
diff --git a/pytest/test_strategies/cases/remote_free_space/test_remote_free_space_with_remove_old_seeds.yml b/pytest/test_strategies/cases/remote_free_space/test_remote_free_space_with_remove_old_seeds.yml
index 00665c1..ee4d1ff 100644
--- a/pytest/test_strategies/cases/remote_free_space/test_remote_free_space_with_remove_old_seeds.yml
+++ b/pytest/test_strategies/cases/remote_free_space/test_remote_free_space_with_remove_old_seeds.yml
@@ -1,5 +1,5 @@
 test:
-  free_space:
+  remote_free_space:
     min: 110
     path: /
     action: remove-old-seeds
diff --git a/pytest/test_strategies/cases/remote_free_space/test_remote_free_space_with_remove_slow_upload_seeds.yml b/pytest/test_strategies/cases/remote_free_space/test_remote_free_space_with_remove_slow_upload_seeds.yml
new file mode 100644
index 0000000..c16be21
--- /dev/null
+++ b/pytest/test_strategies/cases/remote_free_space/test_remote_free_space_with_remove_slow_upload_seeds.yml
@@ -0,0 +1,16 @@
+test:
+  remote_free_space:
+    min: 140
+    path: /
+    action: remove-slow-upload-seeds
+remove:
+  - Torrent - 3
+  - Torrent - 4
+  - Torrent - 5
+  - Torrent - 7
+  - Torrent - 8
+  - Torrent - 9
+  - Torrent - 13
+  - Torrent - 14
+  - Torrent - 15
+  - Torrent - 16
diff --git a/pytest/test_strategies/cases/remote_free_space/test_remote_free_space_with_remove_small_seeds.yml b/pytest/test_strategies/cases/remote_free_space/test_remote_free_space_with_remove_small_seeds.yml
index d3bd225..1a6e73f 100644
--- a/pytest/test_strategies/cases/remote_free_space/test_remote_free_space_with_remove_small_seeds.yml
+++ b/pytest/test_strategies/cases/remote_free_space/test_remote_free_space_with_remove_small_seeds.yml
@@ -1,5 +1,5 @@
 test:
-  free_space:
+  remote_free_space:
     min: 105
     path: /
     action: remove-small-seeds
diff --git a/pytest/test_strategies/cases/remote_free_space/test_remote_free_space_with_zero_limit.yml b/pytest/test_strategies/cases/remote_free_space/test_remote_free_space_with_zero_limit.yml
index 4ac771c..1a44dcb 100644
--- a/pytest/test_strategies/cases/remote_free_space/test_remote_free_space_with_zero_limit.yml
+++ b/pytest/test_strategies/cases/remote_free_space/test_remote_free_space_with_zero_limit.yml
@@ -1,5 +1,5 @@
 test:
-  free_space:
+  remote_free_space:
     min: 0
     path: /
     action: remove-big-seeds
diff --git a/pytest/test_strategies/cases/remove_conditions/test_connected_leecher_eq.yml b/pytest/test_strategies/cases/remove_conditions/test_connected_leecher_eq.yml
new file mode 100644
index 0000000..a43519f
--- /dev/null
+++ b/pytest/test_strategies/cases/remove_conditions/test_connected_leecher_eq.yml
@@ -0,0 +1,4 @@
+test:
+  remove: connected_leecher = 1
+remove:
+  - Torrent - 5
diff --git a/pytest/test_strategies/cases/remove_conditions/test_connected_seeder_eq.yml b/pytest/test_strategies/cases/remove_conditions/test_connected_seeder_eq.yml
new file mode 100644
index 0000000..6b0a9ba
--- /dev/null
+++ b/pytest/test_strategies/cases/remove_conditions/test_connected_seeder_eq.yml
@@ -0,0 +1,5 @@
+test:
+  remove: connected_seeder = 1
+remove:
+  - Torrent - 1
+  - Torrent - 12
diff --git a/pytest/test_strategies/cases/remove_conditions/test_create_time_eq.yml b/pytest/test_strategies/cases/remove_conditions/test_create_time_eq.yml
new file mode 100644
index 0000000..674850c
--- /dev/null
+++ b/pytest/test_strategies/cases/remove_conditions/test_create_time_eq.yml
@@ -0,0 +1,4 @@
+test:
+  remove: create_time = 95201
+remove:
+  - Torrent - 15
\ No newline at end of file
diff --git a/pytest/test_strategies/cases/remove_conditions/test_downloading_time_gt.yml b/pytest/test_strategies/cases/remove_conditions/test_downloading_time_gt.yml
new file mode 100644
index 0000000..9985da7
--- /dev/null
+++ b/pytest/test_strategies/cases/remove_conditions/test_downloading_time_gt.yml
@@ -0,0 +1,4 @@
+test:
+  remove: downloading_time > 50000
+remove:
+  - Torrent - 7
\ No newline at end of file
diff --git a/pytest/test_strategies/cases/remove_conditions/test_downloading_time_lt.yml b/pytest/test_strategies/cases/remove_conditions/test_downloading_time_lt.yml
new file mode 100644
index 0000000..88fbf9f
--- /dev/null
+++ b/pytest/test_strategies/cases/remove_conditions/test_downloading_time_lt.yml
@@ -0,0 +1,7 @@
+test:
+  remove: downloading_time < 100
+remove:
+  - Torrent - 13
+  - Torrent - 14
+  - Torrent - 15
+  - Torrent - 16
diff --git a/pytest/test_strategies/cases/remove_conditions/test_last_activity_eq.yml b/pytest/test_strategies/cases/remove_conditions/test_last_activity_eq.yml
new file mode 100644
index 0000000..8fea58c
--- /dev/null
+++ b/pytest/test_strategies/cases/remove_conditions/test_last_activity_eq.yml
@@ -0,0 +1,4 @@
+test:
+  remove: last_activity = 86250
+remove:
+  - Torrent - 16
\ No newline at end of file
diff --git a/pytest/test_strategies/cases/remove_conditions/test_last_activity_gt.yml b/pytest/test_strategies/cases/remove_conditions/test_last_activity_gt.yml
index f945077..816b94d 100644
--- a/pytest/test_strategies/cases/remove_conditions/test_last_activity_gt.yml
+++ b/pytest/test_strategies/cases/remove_conditions/test_last_activity_gt.yml
@@ -1,4 +1,4 @@
 test:
-  remove: last_activity > 800000
+  remove: last_activity > 700000
 remove:
-  - Torrent - 4
\ No newline at end of file
+  - Torrent - 9
\ No newline at end of file
diff --git a/pytest/test_strategies/cases/remove_conditions/test_last_activity_never.yml b/pytest/test_strategies/cases/remove_conditions/test_last_activity_never.yml
new file mode 100644
index 0000000..da3b406
--- /dev/null
+++ b/pytest/test_strategies/cases/remove_conditions/test_last_activity_never.yml
@@ -0,0 +1,4 @@
+test:
+  remove: last_activity = Never
+remove:
+  - Torrent - 4
\ No newline at end of file
diff --git a/pytest/test_strategies/cases/remove_conditions/test_leecher_eq.yml b/pytest/test_strategies/cases/remove_conditions/test_leecher_eq.yml
new file mode 100644
index 0000000..db0c42b
--- /dev/null
+++ b/pytest/test_strategies/cases/remove_conditions/test_leecher_eq.yml
@@ -0,0 +1,6 @@
+test:
+  remove: leecher = 2
+remove:
+  - Torrent - 4
+  - Torrent - 5
+  - Torrent - 13
diff --git a/pytest/test_strategies/cases/remove_conditions/test_progress_eq.yml b/pytest/test_strategies/cases/remove_conditions/test_progress_eq.yml
new file mode 100644
index 0000000..8a8baf6
--- /dev/null
+++ b/pytest/test_strategies/cases/remove_conditions/test_progress_eq.yml
@@ -0,0 +1,4 @@
+test:
+  remove: progress = 16.86464548110962
+remove:
+  - Torrent - 11
\ No newline at end of file
diff --git a/pytest/test_strategies/cases/remove_conditions/test_seeder_eq.yml b/pytest/test_strategies/cases/remove_conditions/test_seeder_eq.yml
new file mode 100644
index 0000000..7c3f187
--- /dev/null
+++ b/pytest/test_strategies/cases/remove_conditions/test_seeder_eq.yml
@@ -0,0 +1,8 @@
+test:
+  remove: seeder = 1
+remove:
+  - Torrent - 1
+  - Torrent - 2
+  - Torrent - 11
+  - Torrent - 12
+  - Torrent - 15
diff --git a/pytest/test_strategies/cases/remove_conditions/test_seeding_time_eq.yml b/pytest/test_strategies/cases/remove_conditions/test_seeding_time_eq.yml
new file mode 100644
index 0000000..d6a5cac
--- /dev/null
+++ b/pytest/test_strategies/cases/remove_conditions/test_seeding_time_eq.yml
@@ -0,0 +1,4 @@
+test:
+  remove: seeding_time = 1
+remove:
+  - Torrent - 13
\ No newline at end of file
diff --git a/pytest/test_strategies/cases/seed_size/test_seed_size_with_remove_fast_upload_seeds.yml b/pytest/test_strategies/cases/seed_size/test_seed_size_with_remove_fast_upload_seeds.yml
new file mode 100644
index 0000000..0066ecd
--- /dev/null
+++ b/pytest/test_strategies/cases/seed_size/test_seed_size_with_remove_fast_upload_seeds.yml
@@ -0,0 +1,10 @@
+test:
+  seed_size:
+    limit: 45
+    action: remove-fast-upload-seeds
+remove:
+  - Torrent - 1
+  - Torrent - 2
+  - Torrent - 6
+  - Torrent - 10
+  - Torrent - 11
diff --git a/pytest/test_strategies/cases/seed_size/test_seed_size_with_remove_inactive_seeds.yml b/pytest/test_strategies/cases/seed_size/test_seed_size_with_remove_inactive_seeds.yml
index 6c2c556..6d621bf 100644
--- a/pytest/test_strategies/cases/seed_size/test_seed_size_with_remove_inactive_seeds.yml
+++ b/pytest/test_strategies/cases/seed_size/test_seed_size_with_remove_inactive_seeds.yml
@@ -5,7 +5,7 @@ test:
 remove:
   - Torrent - 1
   - Torrent - 2
-  - Torrent - 4
   - Torrent - 5
   - Torrent - 6
-  - Torrent - 9
\ No newline at end of file
+  - Torrent - 7
+  - Torrent - 8
\ No newline at end of file
diff --git a/pytest/test_strategies/cases/seed_size/test_seed_size_with_remove_slow_upload_seeds.yml b/pytest/test_strategies/cases/seed_size/test_seed_size_with_remove_slow_upload_seeds.yml
new file mode 100644
index 0000000..9b1d2cc
--- /dev/null
+++ b/pytest/test_strategies/cases/seed_size/test_seed_size_with_remove_slow_upload_seeds.yml
@@ -0,0 +1,19 @@
+test:
+  seed_size:
+    limit: 30
+    action: remove-slow-upload-seeds
+remove:
+  - Torrent - 1
+  - Torrent - 3
+  - Torrent - 4
+  - Torrent - 5
+  - Torrent - 6
+  - Torrent - 7
+  - Torrent - 8
+  - Torrent - 9
+  - Torrent - 10
+  - Torrent - 11
+  - Torrent - 13
+  - Torrent - 14
+  - Torrent - 15
+  - Torrent - 16
diff --git a/pytest/test_strategies/clientstatus.json b/pytest/test_strategies/clientstatus.json
index dd87264..f432b3c 100644
--- a/pytest/test_strategies/clientstatus.json
+++ b/pytest/test_strategies/clientstatus.json
@@ -3,6 +3,5 @@
     "total_downloaded": 136217978800,
     "upload_speed": 45239782,
     "total_uploaded": 38697636454675,
-    "port_status": "Open",
     "free_space": 107374182400
 }
\ No newline at end of file
diff --git a/pytest/test_strategies/conftest.py b/pytest/test_strategies/conftest.py
index f9f4dc8..bbccce7 100644
--- a/pytest/test_strategies/conftest.py
+++ b/pytest/test_strategies/conftest.py
@@ -6,13 +6,15 @@
 import pytest
 import json
 from autoremovetorrents.clientstatus import ClientStatus
-from autoremovetorrents.portstatus import PortStatus
 from autoremovetorrents.torrent import Torrent
 from autoremovetorrents.torrentstatus import TorrentStatus
 from autoremovetorrents.compatibility.open_ import open_
 
 @pytest.fixture(scope="module")
 def test_data():
+    # Get mocked time
+    env = _test_env_interval()
+
     # Load input data
     input_torrents = []
     with open_(os.path.join(os.path.realpath(os.path.dirname(__file__)),'data.json'), encoding='utf-8') as f:
@@ -30,12 +32,14 @@ def test_data():
         torrent_obj.uploaded = torrent['uploaded']
         torrent_obj.create_time = torrent['added_on']
         torrent_obj.seeding_time = torrent['seeding_time']
+        torrent_obj.downloading_time = torrent['downloading_time']
         torrent_obj.upload_speed = torrent['upspeed']
         torrent_obj.average_upload_speed = torrent['up_speed_avg']
         torrent_obj.downloaded = torrent['downloaded']
         torrent_obj.download_speed = torrent['dlspeed']
         torrent_obj.average_download_speed = torrent['dl_speed_avg']
-        torrent_obj.last_activity = torrent['last_activity']
+        torrent_obj.last_activity = env['time.time'] - torrent['last_activity'] \
+            if torrent['last_activity'] > 0 else None
         torrent_obj.seeder = torrent['num_complete']
         torrent_obj.connected_seeder = torrent['num_seeds']
         torrent_obj.leecher = torrent['num_incomplete']
@@ -45,12 +49,15 @@ def test_data():
 
     return input_torrents
 
-@pytest.fixture(scope="module")
-def test_env():
+def _test_env_interval():
     with open_(os.path.join(os.path.realpath(os.path.dirname(__file__)), 'environment.json'), encoding='utf-8') as f:
         env = json.load(f)
     return env
 
+@pytest.fixture(scope="module")
+def test_env():
+    return _test_env_interval()
+
 @pytest.fixture(scope="module")
 def test_status():
     cs = ClientStatus()
@@ -61,7 +68,6 @@ def test_status():
         cs.total_downloaded = data['total_downloaded']
         cs.upload_speed = data['upload_speed']
         cs.total_uploaded = data['total_uploaded']
-        cs.port_status = PortStatus[data['port_status']]
         cs.free_space = lambda _: data['free_space']
 
     return cs
diff --git a/pytest/test_strategies/data.json b/pytest/test_strategies/data.json
index 8ace8c5..23efeee 100644
--- a/pytest/test_strategies/data.json
+++ b/pytest/test_strategies/data.json
@@ -27,6 +27,7 @@
         "remaining": 8055324533,
         "save_path": "./Downloads/",
         "seeding_time": 61382,
+        "downloading_time": 41322,
         "seen_complete": 1526742547,
         "seq_dl": false,
         "size": 13762548460,
@@ -70,6 +71,7 @@
         "remaining": 8863615408,
         "save_path": "./Downloads/",
         "seeding_time": 7025,
+        "downloading_time": 5022,
         "seen_complete": 1526739352,
         "seq_dl": false,
         "size": 27918469580,
@@ -113,6 +115,7 @@
         "remaining": 0,
         "save_path": "./Downloads/",
         "seeding_time": 41683,
+        "downloading_time": 25933,
         "seen_complete": 1526741130,
         "seq_dl": false,
         "size": 347000034,
@@ -143,7 +146,7 @@
         "force_start": true,
         "hash": "589d65494cc1772dc3e7ae8ed67526200a385b87",
         "is_stalled": false,
-        "last_activity": 1526614323,
+        "last_activity": -1,
         "name": "Torrent - 4",
         "num_complete": 9,
         "num_incomplete": 2,
@@ -156,6 +159,7 @@
         "remaining": 0,
         "save_path": "./Downloads/",
         "seeding_time": 58388,
+        "downloading_time": 39203,
         "seen_complete": 1526614351,
         "seq_dl": false,
         "size": 10152029087,
@@ -199,6 +203,7 @@
         "remaining": 0,
         "save_path": "./Downloads/",
         "seeding_time": 34818,
+        "downloading_time": 42003,
         "seen_complete": 1526742181,
         "seq_dl": false,
         "size": 9627866528,
@@ -242,6 +247,7 @@
         "remaining": 0,
         "save_path": "./Downloads/",
         "seeding_time": 11328,
+        "downloading_time": 43233,
         "seen_complete": 1526742572,
         "seq_dl": false,
         "size": 13200820552,
@@ -285,6 +291,7 @@
         "remaining": 0,
         "save_path": "./Downloads/",
         "seeding_time": 73801,
+        "downloading_time": 66992,
         "seen_complete": 1526739648,
         "seq_dl": false,
         "size": 7239185152,
@@ -328,6 +335,7 @@
         "remaining": 0,
         "save_path": "./Downloads/",
         "seeding_time": 8041,
+        "downloading_time": 23033,
         "seen_complete": 1526742225,
         "seq_dl": false,
         "size": 7619309310,
@@ -371,6 +379,7 @@
         "remaining": 0,
         "save_path": "./Downloads/",
         "seeding_time": 6085,
+        "downloading_time": 4932,
         "seen_complete": 1526730169,
         "seq_dl": false,
         "size": 3022394751,
@@ -414,6 +423,7 @@
         "remaining": 0,
         "save_path": "./Downloads/",
         "seeding_time": 856,
+        "downloading_time": 120,
         "seen_complete": 1526742579,
         "seq_dl": false,
         "size": 14844911534,
@@ -457,6 +467,7 @@
         "remaining": 11445911552,
         "save_path": "./Downloads/",
         "seeding_time": 30667,
+        "downloading_time": 43322,
         "seen_complete": 1526742464,
         "seq_dl": false,
         "size": 13767802684,
@@ -500,6 +511,7 @@
         "remaining": 2315255556,
         "save_path": "./Downloads/",
         "seeding_time": 39155,
+        "downloading_time": 43222,
         "seen_complete": 1526742614,
         "seq_dl": false,
         "size": 4030908717,
@@ -543,6 +555,7 @@
         "remaining": 0,
         "save_path": "./Downloads/",
         "seeding_time": 1,
+        "downloading_time": 1,
         "seen_complete": 1527349645,
         "seq_dl": false,
         "size": 1746686185,
@@ -584,6 +597,7 @@
         "remaining": 0,
         "save_path": "./Downloads/",
         "seeding_time": 2,
+        "downloading_time": 2,
         "seen_complete": 1527349962,
         "seq_dl": false,
         "size": 312186667,
@@ -627,6 +641,7 @@
         "remaining": 0,
         "save_path": "./Downloads/",
         "seeding_time": 3,
+        "downloading_time": 3,
         "seen_complete": 1527351233,
         "seq_dl": false,
         "size": 2126568405,
@@ -668,6 +683,7 @@
         "remaining": 0,
         "save_path": "./Downloads/",
         "seeding_time": 4,
+        "downloading_time": 4,
         "seen_complete": 1527345392,
         "seq_dl": false,
         "size": 1132013553,