chore: backup infrastructure configurations [skip ci]

This commit is contained in:
github-actions[bot]
2026-02-14 02:02:16 +00:00
parent ef3b61e195
commit bc78eb2981
29 changed files with 289 additions and 81 deletions

View File

@@ -0,0 +1 @@
{"sync_type": "weight_sync", "status": "partial", "message": "Synced 0 records, 1 failed", "records_processed": 0, "timestamp": "2026-02-13T02:21:20.217843+00:00"}

View File

@@ -0,0 +1 @@
{"sync_type": "weight_sync", "status": "partial", "message": "Synced 0 records, 1 failed", "records_processed": 0, "timestamp": "2026-02-13T03:21:22.787777+00:00"}

View File

@@ -0,0 +1 @@
{"sync_type": "weight_sync", "status": "partial", "message": "Synced 0 records, 1 failed", "records_processed": 0, "timestamp": "2026-02-13T04:21:25.329528+00:00"}

View File

@@ -0,0 +1 @@
{"sync_type": "weight_sync", "status": "partial", "message": "Synced 0 records, 1 failed", "records_processed": 0, "timestamp": "2026-02-13T05:21:27.864525+00:00"}

View File

@@ -0,0 +1 @@
{"sync_type": "weight_sync", "status": "partial", "message": "Synced 0 records, 1 failed", "records_processed": 0, "timestamp": "2026-02-13T06:21:30.477980+00:00"}

View File

@@ -0,0 +1 @@
{"sync_type": "weight_sync", "status": "partial", "message": "Synced 0 records, 1 failed", "records_processed": 0, "timestamp": "2026-02-13T07:21:33.048288+00:00"}

View File

@@ -0,0 +1 @@
{"sync_type": "weight_sync", "status": "partial", "message": "Synced 0 records, 1 failed", "records_processed": 0, "timestamp": "2026-02-13T08:21:35.617814+00:00"}

View File

@@ -0,0 +1 @@
{"sync_type": "weight_sync", "status": "partial", "message": "Synced 0 records, 1 failed", "records_processed": 0, "timestamp": "2026-02-13T09:21:38.171658+00:00"}

View File

@@ -0,0 +1 @@
{"sync_type": "weight_sync", "status": "partial", "message": "Synced 0 records, 1 failed", "records_processed": 0, "timestamp": "2026-02-13T10:21:40.731618+00:00"}

View File

@@ -0,0 +1 @@
{"sync_type": "weight_sync", "status": "partial", "message": "Synced 0 records, 1 failed", "records_processed": 0, "timestamp": "2026-02-13T11:21:43.316770+00:00"}

View File

@@ -0,0 +1 @@
{"sync_type": "weight_sync", "status": "partial", "message": "Synced 0 records, 1 failed", "records_processed": 0, "timestamp": "2026-02-13T12:21:45.918183+00:00"}

View File

@@ -0,0 +1 @@
{"sync_type": "weight_sync", "status": "partial", "message": "Synced 0 records, 1 failed", "records_processed": 0, "timestamp": "2026-02-13T13:21:48.471675+00:00"}

View File

@@ -0,0 +1 @@
{"sync_type": "weight_sync", "status": "partial", "message": "Synced 0 records, 1 failed", "records_processed": 0, "timestamp": "2026-02-13T14:21:51.020607+00:00"}

View File

@@ -0,0 +1 @@
{"sync_type": "weight_sync", "status": "partial", "message": "Synced 0 records, 1 failed", "records_processed": 0, "timestamp": "2026-02-13T15:21:53.597269+00:00"}

View File

@@ -0,0 +1 @@
{"sync_type": "weight_sync", "status": "partial", "message": "Synced 0 records, 1 failed", "records_processed": 0, "timestamp": "2026-02-13T16:21:56.221397+00:00"}

View File

@@ -0,0 +1 @@
{"sync_type": "weight_sync", "status": "partial", "message": "Synced 0 records, 1 failed", "records_processed": 0, "timestamp": "2026-02-13T17:21:58.857035+00:00"}

View File

@@ -0,0 +1 @@
{"sync_type": "weight_sync", "status": "partial", "message": "Synced 0 records, 1 failed", "records_processed": 0, "timestamp": "2026-02-13T18:22:01.499600+00:00"}

View File

@@ -0,0 +1 @@
{"sync_type": "weight_sync", "status": "partial", "message": "Synced 0 records, 1 failed", "records_processed": 0, "timestamp": "2026-02-13T19:22:04.414123+00:00"}

View File

@@ -0,0 +1 @@
{"sync_type": "weight_sync", "status": "partial", "message": "Synced 0 records, 1 failed", "records_processed": 0, "timestamp": "2026-02-13T20:22:07.339822+00:00"}

View File

@@ -0,0 +1 @@
{"sync_type": "weight_sync", "status": "partial", "message": "Synced 0 records, 1 failed", "records_processed": 0, "timestamp": "2026-02-13T21:22:10.339989+00:00"}

View File

@@ -0,0 +1 @@
{"sync_type": "weight_sync", "status": "partial", "message": "Synced 0 records, 1 failed", "records_processed": 0, "timestamp": "2026-02-13T22:22:13.087837+00:00"}

View File

@@ -0,0 +1 @@
{"sync_type": "weight_sync", "status": "partial", "message": "Synced 0 records, 1 failed", "records_processed": 0, "timestamp": "2026-02-13T23:22:16.070996+00:00"}

View File

@@ -0,0 +1 @@
{"sync_type": "weight_sync", "status": "partial", "message": "Synced 0 records, 1 failed", "records_processed": 0, "timestamp": "2026-02-14T00:22:19.302405+00:00"}

View File

@@ -0,0 +1 @@
{"sync_type": "weight_sync", "status": "partial", "message": "Synced 0 records, 1 failed", "records_processed": 0, "timestamp": "2026-02-14T01:22:22.321217+00:00"}

View File

@@ -22,18 +22,27 @@ try:
qbt_client.auth_log_in() qbt_client.auth_log_in()
except qbittorrentapi.LoginFailed as e: except qbittorrentapi.LoginFailed as e:
print(e) print(e)
logger.info(f'qBittorrent Err: {e}')
sys.exit(1) sys.exit(1)
# display qBittorrent info # display qBittorrent info
logger.info(f'qBittorrent: {qbt_client.app.version}') logger.info(f'qBittorrent: {qbt_client.app.version}')
logger.info(f'qBittorrent Web API: {qbt_client.app.web_api_version}') logger.info(f'qBittorrent Web API: {qbt_client.app.web_api_version}')
logger.info('TAGGER Running')
# logger.info(f'Web API Supported: {qbittorrentapi.supported_app_versions}') # logger.info(f'Web API Supported: {qbittorrentapi.supported_app_versions}')
for k,v in qbt_client.app.build_info.items(): print(f'{k}: {v}') for k,v in qbt_client.app.build_info.items(): print(f'{k}: {v}')
for torrent in qbt_client.torrents_info(): for torrent in qbt_client.torrents_info():
tags = [word.strip() for word in torrent.tags.split(',')] tags = [word.strip() for word in torrent.tags.split(',')]
# Log full tracker information
logger.info(f'Torrent Name: {torrent.name}')
logger.info(f'Torrent Hash: {torrent.hash}')
logger.info(f'Tracker Count: {len(torrent.trackers)}')
logger.info('Trackers:')
logger.info(json.dumps(torrent.trackers, indent=2))
if "812415449bd161ba71e1a30fb5450e3d346a0594" == torrent.hash: if "812415449bd161ba71e1a30fb5450e3d346a0594" == torrent.hash:
logger.info(f'Deleting: {torrent.name}') logger.info(f'Deleting: {torrent.name}')
qbt_client.torrents_delete(delete_files=True, torrent_hashes=torrent.hash) qbt_client.torrents_delete(delete_files=True, torrent_hashes=torrent.hash)
@@ -50,10 +59,16 @@ for torrent in qbt_client.torrents_info():
qbt_client.torrents_remove_tags(tags="PR2100",torrent_hashes=torrent.hash) qbt_client.torrents_remove_tags(tags="PR2100",torrent_hashes=torrent.hash)
qbt_client.torrents_add_tags(tags="WDMYCLOUD",torrent_hashes=torrent.hash) qbt_client.torrents_add_tags(tags="WDMYCLOUD",torrent_hashes=torrent.hash)
if torrent.trackers[0]["msg"] != "This torrent is private" and len(torrent.trackers) == 4: if torrent.trackers[0]["msg"] != "This torrent is private":
if "rawkbawx" not in torrent.trackers[3]["url"]: if all("rawkbawx" not in tracker["url"] for tracker in torrent.trackers):
logger.info(f'Tagging as Private: {torrent.name} {torrent.hash}') logger.info(f'Tagging as PublicTracker: {torrent.name} {torrent.hash} {torrent.tags}')
qbt_client.torrents_set_share_limits(ratio_limit=1,seeding_time_limit=1440,inactive_seeding_time_limit=-1,torrent_hashes=torrent.hash)
qbt_client.torrents_add_tags(tags="PublicTracker",torrent_hashes=torrent.hash) qbt_client.torrents_add_tags(tags="PublicTracker",torrent_hashes=torrent.hash)
# Verify tags were added
updated_torrent = qbt_client.torrents_info(torrent_hashes=torrent.hash)[0]
logger.info(f'Updated Tags for {torrent.name}: {updated_torrent.tags}')
else:
logger.info(f'Tagging as Private: {torrent.name} {torrent.hash} {torrent.tags}')
qbt_client.torrents_set_share_limits(ratio_limit=1,seeding_time_limit=1440,inactive_seeding_time_limit=-1,torrent_hashes=torrent.hash)
sys.exit(0) sys.exit(0)

View File

@@ -1,5 +1,104 @@
import qbittorrentapi import qbittorrentapi
from pprint import pprint from pprint import pprint
from datetime import datetime
import time
import qbittorrentapi
import logging
import sys
import time
from datetime import datetime, timedelta
# Creating and Configuring Logger
Log_Format = "%(levelname)s %(asctime)s - %(message)s"
logging.basicConfig(
stream=sys.stdout,
format=Log_Format,
level=logging.INFO,
datefmt='%Y-%m-%d %H:%M:%S'
)
logger = logging.getLogger()
def delete_torrents_by_tag(qbt_client, tag, days_threshold=60):
"""
Delete torrents with a specific tag that are older than the specified days
:param qbt_client: qBittorrent client instance
:param tag: Tag to filter torrents
:param days_threshold: Number of days after which to delete torrents
"""
current_time = int(time.time())
threshold_time = current_time - (days_threshold * 24 * 60 * 60)
deleted_count = 0
total_size_deleted = 0
for torrent in qbt_client.torrents_info():
# Check if the torrent has the specified tag
if tag in torrent.tags.split(','):
# Check if torrent's added time is older than threshold
if torrent.added_on < threshold_time:
# Use time.localtime() to convert timestamp
added_date = time.localtime(torrent.added_on)
formatted_date = time.strftime("%Y-%m-%d %H:%M:%S", added_date)
logger.info(f'Deleting old tagged torrent: {torrent.name}')
logger.info(f' - Added on: {formatted_date}')
logger.info(f' - Size: {torrent.size / (1024*1024*1024):.2f} GB')
logger.info(f' - Hash: {torrent.hash}')
try:
# Delete torrent and its files
qbt_client.torrents_delete(
delete_files=True, # Important: this will remove the actual files
torrent_hashes=torrent.hash
)
deleted_count += 1
total_size_deleted += torrent.size
except Exception as e:
logger.error(f'Error deleting torrent {torrent.name}: {e}')
# Summary logging
logger.info(f'Deletion Summary for tag "{tag}":')
logger.info(f' - Total torrents deleted: {deleted_count}')
logger.info(f' - Total size deleted: {total_size_deleted / (1024*1024*1024):.2f} GB')
def delete_old_torrents(qbt_client, category="", days_threshold=60):
"""
Delete torrents older than specified days in a given category
If no category is specified, works on uncategorized torrents
:param qbt_client: qBittorrent client instance
:param category: Category name to filter torrents (default is uncategorized)
:param days_threshold: Number of days after which to delete torrents
"""
current_time = int(time.time())
threshold_time = current_time - (days_threshold * 24 * 60 * 60)
for torrent in qbt_client.torrents_info(category=category):
# Check if torrent's added time is older than threshold
if torrent.added_on < threshold_time:
# Use time.localtime() to convert timestamp
added_date = time.localtime(torrent.added_on)
formatted_date = time.strftime("%Y-%m-%d %H:%M:%S", added_date)
logger.info(f'Deleting old torrent: {torrent.name} (Added on: {formatted_date})')
try:
# Delete torrent and its files
qbt_client.torrents_delete(
delete_files=True, # Important: this will remove the actual files
torrent_hashes=torrent.hash
)
except Exception as e:
logger.error(f'Error deleting torrent {torrent.name}: {e}')
def main():
# instantiate a Client using the appropriate WebUI configuration # instantiate a Client using the appropriate WebUI configuration
qbt_client = qbittorrentapi.Client( qbt_client = qbittorrentapi.Client(
@@ -18,46 +117,52 @@ except qbittorrentapi.LoginFailed as e:
print(e) print(e)
# display qBittorrent info # display qBittorrent info
print(f'qBittorrent: {qbt_client.app.version}') logger.info(f'qBittorrent: {qbt_client.app.version}')
print(f'qBittorrent Web API: {qbt_client.app.web_api_version}') logger.info(f'qBittorrent Web API: {qbt_client.app.web_api_version}')
for k,v in qbt_client.app.build_info.items(): print(f'{k}: {v}') for k,v in qbt_client.app.build_info.items(): print(f'{k}: {v}')
# Creating an empty dictionary # Creating an empty dictionary
trackermap = {} trackermap = {
"Docspedia": ["http://science.docspedia.world:2710/f200baf50d45595c269b7b2d8c475a56/announce"],
# Adding list as value "MMA": ["http://a.mma-tracker.org:2710/ed6d78535267e979de36ec2401999d3a/announce"],
trackermap["Docspedia"] = ["http://science.docspedia.world:2710/f200baf50d45595c269b7b2d8c475a56/announce"] "IPT": [
trackermap["MMA"] = ["http://a.mma-tracker.org:2710/ed6d78535267e979de36ec2401999d3a/announce"] "http://127.0.0.1.stackoverflow.tech/cc7288bf91565af486c8e4bad2b63a37/announce",
trackermap["IPT"] = ["http://127.0.0.1.stackoverflow.tech/cc7288bf91565af486c8e4bad2b63a37/announce"
"http://routing.bgp.technology/cc7288bf91565af486c8e4bad2b63a37/announce", "http://routing.bgp.technology/cc7288bf91565af486c8e4bad2b63a37/announce",
"http://async.empirehost.me/cc7288bf91565af486c8e4bad2b63a37/announce", "http://async.empirehost.me/cc7288bf91565af486c8e4bad2b63a37/announce"
],
"Anthelion": ["https://tracker.anthelion.me:34001/LmD45Qf7p0MVgYkPm1Uogc8wNqDtvsjF/announce"],
"Cathode": ["https://signal.cathode-ray.tube/yebawgmvnvojwjnfw2a1qr5wg3pqwe4o/announce"],
"RedSeeding": ["https://flacsfor.me/f08a15129e4276f609c8b99abb746195/announce"],
"cinemaz": ["https://tracker.cinemaz.to/50500ba3815e18c837cd753ceb0080e3/announce"],
"iMetal": ["http://metal.iplay.ro/announce.php?passkey=2b4d98fe0f4b7325a15e5654961498ea"],
"rawk": [
"http://rawkbawx.rocks:2710/announce",
"http://rawkbawx.rocks:2710/f7903677d2c030b89b69799f4bd9edbd/announce"
],
"torrentleech": [
"https://tracker.tleechreload.org/a/3d6cde5fd3bf1a375f3466d40f9ee9bb/announce",
"https://tracker.torrentleech.org/a/3d6cde5fd3bf1a375f3466d40f9ee9bb/announce"
],
"MyAnonamouse": ["https://t.myanonamouse.net/tracker.php/VPRYYAL-WpTwnr9G9aIN6044YVZ7x8Ao/announce"],
"Nebulance": ["https://tracker.nebulance.io/edcd6847fb3c31fd9958dd7144f0ea15/announce"],
"Orpheus_seeding": ["https://home.opsfet.ch/EAvBpDtmBtbziuydzwzhasgqAxrCqFwo/announce"],
"tvchaos": ["https://tvchaosuk.com/announce/cbaade5ac5612edf854b295153a60e6b"],
"filelist": [
"http://reactor.filelist.io/98ece6e971fe7e89a0c86a00c20c1037/announce",
"http://reactor.flro.org/98ece6e971fe7e89a0c86a00c20c1037/announce"
] ]
trackermap["Anthelion"] = ["https://tracker.anthelion.me:34001/LmD45Qf7p0MVgYkPm1Uogc8wNqDtvsjF/announce"] }
trackermap["Cathode"] = ["https://signal.cathode-ray.tube/yebawgmvnvojwjnfw2a1qr5wg3pqwe4o/announce"]
trackermap["RedSeeding"] = ["https://flacsfor.me/f08a15129e4276f609c8b99abb746195/announce"]
trackermap["cinemaz"] = ["https://tracker.cinemaz.to/50500ba3815e18c837cd753ceb0080e3/announce"]
trackermap["iMetal"] = ["http://metal.iplay.ro/announce.php?passkey=2b4d98fe0f4b7325a15e5654961498ea"]
trackermap["rawk"] = ["http://rawkbawx.rocks:2710/announce","http://rawkbawx.rocks:2710/f7903677d2c030b89b69799f4bd9edbd/announce"]
trackermap["torrentleech"] = ["https://tracker.tleechreload.org/a/3d6cde5fd3bf1a375f3466d40f9ee9bb/announce"
,"https://tracker.torrentleech.org/a/3d6cde5fd3bf1a375f3466d40f9ee9bb/announce"]
trackermap["MyAnonamouse"] = ["https://t.myanonamouse.net/tracker.php/VPRYYAL-WpTwnr9G9aIN6044YVZ7x8Ao/announce"]
trackermap["Nebulance"] = ["https://tracker.nebulance.io/edcd6847fb3c31fd9958dd7144f0ea15/announce"]
trackermap["Orpheus_seeding"] = ["https://home.opsfet.ch/EAvBpDtmBtbziuydzwzhasgqAxrCqFwo/announce"]
trackermap["tvchaos"] = ["https://tvchaosuk.com/announce/cbaade5ac5612edf854b295153a60e6b"]
trackermap["filelist"] = ["http://reactor.filelist.io/98ece6e971fe7e89a0c86a00c20c1037/announce",
"http://reactor.flro.org/98ece6e971fe7e89a0c86a00c20c1037/announce"]
categories_to_tidy = ["radarr","tv-sonarr","lidar","readarr","readarrAudio","Uncategorized"] categories_to_tidy = ["radarr","tv-sonarr","lidar","readarr","readarrAudio","","tv-sonarrsmall"]
#ensutre cats exist #ensutre cats exist
torrents_cats = qbt_client.torrents_categories() torrents_cats = qbt_client.torrents_categories()
for tracker in trackermap: for tracker in trackermap:
if tracker not in torrents_cats: if tracker not in torrents_cats:
savepath = "/downloads/seeding/" + tracker savepath = "/downloads/seeding/" + tracker
qbt_client.torrents_create_category(name=tracker, save_path=savepath) qbt_client.torrents_create_category(name=tracker, save_path=savepath)
if tracker in torrents_cats: if tracker in torrents_cats:
@@ -85,3 +190,14 @@ for torrent in qbt_client.torrents_info():
qbt_client.torrents_set_category(category=knowntracker,torrent_hashes=torrent.hash) qbt_client.torrents_set_category(category=knowntracker,torrent_hashes=torrent.hash)
else: else:
pprint(f"seedtime {name} to {knowntracker}") pprint(f"seedtime {name} to {knowntracker}")
delete_old_torrents(qbt_client, category="IPT")
delete_old_torrents(qbt_client, category="Nebulance")
delete_torrents_by_tag(qbt_client, tag='PublicTracker')
if __name__ == "__main__":
main()

View File

@@ -42,7 +42,7 @@ job "foodplanner" {
} }
resources { resources {
cpu = 500 cpu = 500
memory = 500 memory = 1024
} }
# Restart policy # Restart policy

View File

@@ -0,0 +1,53 @@
job "postgres-backup" {
datacenters = ["dc1"]
type = "service"
constraint {
attribute = "${attr.kernel.name}"
value = "linux"
}
update {
stagger = "10s"
max_parallel = 1
healthy_deadline = "5m"
}
group "postgres-backup" {
count = 1
restart {
attempts = 6
interval = "1m"
delay = "10s"
mode = "delay"
}
task "postgres-backup" {
driver = "docker"
config {
image = "ghcr.io/sstent/docker-pg-backup:latest"
dns_servers = ["${attr.unique.network.ip-address}","192.168.4.250","8.8.8.8"]
memory_hard_limit = "2048"
volumes = [
"/mnt/Public/configs/postgres_backups:/backups",
]
}
env {
POSTGRES_HOST= "replica.postgres.service.dc1.consul"
POSTGRES_USER= "postgres"
POSTGRES_PASS= "postgres"
}
resources {
cpu = 256 # 500 MHz
memory = 64 # 128MB
} #end resources
} #end task
} # end group
} # end job

View File

@@ -29,7 +29,7 @@ job "sonarr" {
driver = "docker" driver = "docker"
config { config {
image = "lscr.io/linuxserver/sonarr:develop" image = "lscr.io/linuxserver/sonarr:latest"
ports = ["http"] ports = ["http"]
dns_servers = ["${attr.unique.network.ip-address}","192.168.4.250","8.8.8.8"] dns_servers = ["${attr.unique.network.ip-address}","192.168.4.250","8.8.8.8"]