1use std::net::SocketAddr;
2use std::sync::Arc;
3
4use tokio::task::JoinHandle;
5
6use crate::bootstrap::logging;
7use crate::cache::image::manager::ImageCacheService;
8use crate::common::AppData;
9use crate::config::Configuration;
10use crate::databases::database;
11use crate::services::authentication::{DbUserAuthenticationRepository, JsonWebToken, Service};
12use crate::services::category::{self, DbCategoryRepository};
13use crate::services::tag::{self, DbTagRepository};
14use crate::services::torrent::{
15 DbTorrentAnnounceUrlRepository, DbTorrentFileRepository, DbTorrentInfoRepository, DbTorrentListingGenerator,
16 DbTorrentRepository, DbTorrentTagRepository,
17};
18use crate::services::user::{self, DbBannedUserList, DbUserProfileRepository, DbUserRepository};
19use crate::services::{proxy, settings, torrent};
20use crate::tracker::statistics_importer::StatisticsImporter;
21use crate::web::api::v1::auth::Authentication;
22use crate::web::api::{start, Version};
23use crate::{mailer, tracker};
24
25pub struct Running {
26 pub api_socket_addr: SocketAddr,
27 pub api_server: Option<JoinHandle<std::result::Result<(), std::io::Error>>>,
28 pub tracker_data_importer_handle: tokio::task::JoinHandle<()>,
29}
30
31#[allow(clippy::too_many_lines)]
37pub async fn run(configuration: Configuration, api_version: &Version) -> Running {
38 let log_level = configuration.settings.read().await.log_level.clone();
39
40 logging::setup(&log_level);
41
42 let configuration = Arc::new(configuration);
43
44 let settings = configuration.settings.read().await;
48
49 let database_connect_url = settings.database.connect_url.clone();
50 let torrent_info_update_interval = settings.tracker_statistics_importer.torrent_info_update_interval;
51 let net_ip = "0.0.0.0".to_string();
52 let net_port = settings.net.port;
53
54 drop(settings);
57
58 let database = Arc::new(database::connect(&database_connect_url).await.expect("Database error."));
61 let json_web_token = Arc::new(JsonWebToken::new(configuration.clone()));
62 let auth = Arc::new(Authentication::new(json_web_token.clone()));
63
64 let category_repository = Arc::new(DbCategoryRepository::new(database.clone()));
66 let tag_repository = Arc::new(DbTagRepository::new(database.clone()));
67 let user_repository = Arc::new(DbUserRepository::new(database.clone()));
68 let user_authentication_repository = Arc::new(DbUserAuthenticationRepository::new(database.clone()));
69 let user_profile_repository = Arc::new(DbUserProfileRepository::new(database.clone()));
70 let torrent_repository = Arc::new(DbTorrentRepository::new(database.clone()));
71 let torrent_info_repository = Arc::new(DbTorrentInfoRepository::new(database.clone()));
72 let torrent_file_repository = Arc::new(DbTorrentFileRepository::new(database.clone()));
73 let torrent_announce_url_repository = Arc::new(DbTorrentAnnounceUrlRepository::new(database.clone()));
74 let torrent_tag_repository = Arc::new(DbTorrentTagRepository::new(database.clone()));
75 let torrent_listing_generator = Arc::new(DbTorrentListingGenerator::new(database.clone()));
76 let banned_user_list = Arc::new(DbBannedUserList::new(database.clone()));
77
78 let tracker_service = Arc::new(tracker::service::Service::new(configuration.clone(), database.clone()).await);
80 let tracker_statistics_importer =
81 Arc::new(StatisticsImporter::new(configuration.clone(), tracker_service.clone(), database.clone()).await);
82 let mailer_service = Arc::new(mailer::Service::new(configuration.clone()).await);
83 let image_cache_service: Arc<ImageCacheService> = Arc::new(ImageCacheService::new(configuration.clone()).await);
84 let category_service = Arc::new(category::Service::new(category_repository.clone(), user_repository.clone()));
85 let tag_service = Arc::new(tag::Service::new(tag_repository.clone(), user_repository.clone()));
86 let proxy_service = Arc::new(proxy::Service::new(image_cache_service.clone(), user_repository.clone()));
87 let settings_service = Arc::new(settings::Service::new(configuration.clone(), user_repository.clone()));
88 let torrent_index = Arc::new(torrent::Index::new(
89 configuration.clone(),
90 tracker_statistics_importer.clone(),
91 tracker_service.clone(),
92 user_repository.clone(),
93 category_repository.clone(),
94 torrent_repository.clone(),
95 torrent_info_repository.clone(),
96 torrent_file_repository.clone(),
97 torrent_announce_url_repository.clone(),
98 torrent_tag_repository.clone(),
99 torrent_listing_generator.clone(),
100 ));
101 let registration_service = Arc::new(user::RegistrationService::new(
102 configuration.clone(),
103 mailer_service.clone(),
104 user_repository.clone(),
105 user_profile_repository.clone(),
106 ));
107 let ban_service = Arc::new(user::BanService::new(
108 user_repository.clone(),
109 user_profile_repository.clone(),
110 banned_user_list.clone(),
111 ));
112 let authentication_service = Arc::new(Service::new(
113 configuration.clone(),
114 json_web_token.clone(),
115 user_repository.clone(),
116 user_profile_repository.clone(),
117 user_authentication_repository.clone(),
118 ));
119
120 let app_data = Arc::new(AppData::new(
123 configuration.clone(),
124 database.clone(),
125 json_web_token.clone(),
126 auth.clone(),
127 authentication_service,
128 tracker_service.clone(),
129 tracker_statistics_importer.clone(),
130 mailer_service,
131 image_cache_service,
132 category_repository,
133 tag_repository,
134 user_repository,
135 user_authentication_repository,
136 user_profile_repository,
137 torrent_repository,
138 torrent_info_repository,
139 torrent_file_repository,
140 torrent_announce_url_repository,
141 torrent_tag_repository,
142 torrent_listing_generator,
143 banned_user_list,
144 category_service,
145 tag_service,
146 proxy_service,
147 settings_service,
148 torrent_index,
149 registration_service,
150 ban_service,
151 ));
152
153 let weak_tracker_statistics_importer = Arc::downgrade(&tracker_statistics_importer);
157
158 let tracker_statistics_importer_handle = tokio::spawn(async move {
159 let interval = std::time::Duration::from_secs(torrent_info_update_interval);
160 let mut interval = tokio::time::interval(interval);
161 interval.tick().await; loop {
163 interval.tick().await;
164 if let Some(tracker) = weak_tracker_statistics_importer.upgrade() {
165 let _ = tracker.import_all_torrents_statistics().await;
166 } else {
167 break;
168 }
169 }
170 });
171
172 let running_api = start(app_data, &net_ip, net_port, api_version).await;
175
176 Running {
177 api_socket_addr: running_api.socket_addr,
178 api_server: running_api.api_server,
179 tracker_data_importer_handle: tracker_statistics_importer_handle,
180 }
181}