From 172524933fc5e035fa6a53cf132314579ce57a9c Mon Sep 17 00:00:00 2001 From: augenfrosch <45207902+augenfrosch@users.noreply.github.com> Date: Sat, 13 Dec 2025 01:44:41 +0100 Subject: [PATCH 1/2] v2: add poller for TW version --- v2/thaliak-poller/src/main.rs | 24 +++++++++++- v2/thaliak-poller/src/poller/ffxivtc.rs | 52 +++++++++++++++++++++++++ v2/thaliak-poller/src/poller/mod.rs | 1 + 3 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 v2/thaliak-poller/src/poller/ffxivtc.rs diff --git a/v2/thaliak-poller/src/main.rs b/v2/thaliak-poller/src/main.rs index 0f5961a..3f922b7 100644 --- a/v2/thaliak-poller/src/main.rs +++ b/v2/thaliak-poller/src/main.rs @@ -1,5 +1,7 @@ use crate::patch::PatchReconciliationService; -use crate::poller::{Poller, actoz::ActozPoller, shanda::ShandaPoller, sqex::SqexPoller}; +use crate::poller::{ + Poller, actoz::ActozPoller, ffxivtc::FfxivtcPoller, shanda::ShandaPoller, sqex::SqexPoller, +}; use chrono::{Timelike, Utc}; use eyre::Result; use log::{info, warn}; @@ -100,6 +102,25 @@ async fn poll_shanda_loop(reconciliation: PatchReconciliationService, db: Sqlite } } +async fn poll_ffxivtc_loop(reconciliation: PatchReconciliationService, db: SqlitePool) { + let mut rng = rand::rng(); + let poller = FfxivtcPoller::new(); + + info!("FfxivtcPoller: starting initial poll"); + execute_poll(&poller, &reconciliation, &db, "FfxivtcPoller").await; + + loop { + let wait_minutes = rng.random_range(40..=59); + let total_wait = Duration::from_secs((wait_minutes * 60) as u64); + + info!("FfxivtcPoller: sleeping for {} minutes", wait_minutes); + sleep_until(Instant::now() + total_wait).await; + + info!("FfxivtcPoller: starting poll"); + execute_poll(&poller, &reconciliation, &db, "FfxivtcPoller").await; + } +} + #[tokio::main] async fn main() -> Result<()> { let _ = dotenvy::dotenv(); @@ -119,6 +140,7 @@ async fn main() -> Result<()> { _ = poll_sqex_loop(reconciliation.clone(), pools.public.clone()) => {}, _ = poll_actoz_loop(reconciliation.clone(), pools.public.clone()) => {}, _ = poll_shanda_loop(reconciliation.clone(), pools.public.clone()) => {}, + _ = poll_ffxivtc_loop(reconciliation.clone(), pools.public.clone()) => {}, } Ok(()) diff --git a/v2/thaliak-poller/src/poller/ffxivtc.rs b/v2/thaliak-poller/src/poller/ffxivtc.rs new file mode 100644 index 0000000..cd444c7 --- /dev/null +++ b/v2/thaliak-poller/src/poller/ffxivtc.rs @@ -0,0 +1,52 @@ +use super::{GenericPollError, PatchDiscoveryType, Poller, VersionCheckService}; +use crate::patch::PatchReconciliationService; +use log::info; + +const GAME_REPO_ID: i64 = 20; + +pub struct FfxivtcPoller; +impl Poller for FfxivtcPoller { + type Error = GenericPollError; + + async fn poll( + &self, + reconciliation: &PatchReconciliationService, + ) -> Result<(), GenericPollError> { + info!("Polling for TW patches..."); + + let vcs = self.version_check_service(); + let patch_list = vcs + .fetch_patch_list(None) + .await + .map_err(|e| GenericPollError::VersionCheckError(e))?; + info!("TW patch list: {:#?}", patch_list); + + reconciliation + .reconcile(GAME_REPO_ID, &patch_list, PatchDiscoveryType::Offered) + .await + .map_err(|e| GenericPollError::ReconciliationError(e))?; + + Ok(()) + } +} + +impl FfxivtcPoller { + const PATCHER_USER_AGENT: &'static str = "FFXIV_Patch"; + + pub fn new() -> Self { + Self {} + } + + fn version_check_service(&self) -> VersionCheckService { + VersionCheckService::new( + Self::PATCHER_USER_AGENT, + move |base_version| { + format!( + "http://patch-gamever.ffxiv.com.tw/http/win32/ffxivtc_release_tc_game/{}/", + base_version + ) + }, + false, + ) + } +} diff --git a/v2/thaliak-poller/src/poller/mod.rs b/v2/thaliak-poller/src/poller/mod.rs index 7870f27..5d835b4 100644 --- a/v2/thaliak-poller/src/poller/mod.rs +++ b/v2/thaliak-poller/src/poller/mod.rs @@ -6,6 +6,7 @@ use std::time::Duration; use thiserror::Error; pub mod actoz; +pub mod ffxivtc; pub mod shanda; pub mod sqex; From 24e8f21828c223dc4040860aecd55e42d01686e0 Mon Sep 17 00:00:00 2001 From: augenfrosch <45207902+augenfrosch@users.noreply.github.com> Date: Sat, 13 Dec 2025 01:45:28 +0100 Subject: [PATCH 2/2] v2: update db initialization for TW version --- v2/migrations/public/01_init_data.sql | 31 +++++++++++++++++++-------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/v2/migrations/public/01_init_data.sql b/v2/migrations/public/01_init_data.sql index 7342233..3358b0c 100644 --- a/v2/migrations/public/01_init_data.sql +++ b/v2/migrations/public/01_init_data.sql @@ -2,7 +2,8 @@ INSERT INTO service (id, name, icon) VALUES ('jp', 'FFXIV Global', '๐Ÿ‡บ๐Ÿ‡ณ'), ('kr', 'FFXIV Korea', '๐Ÿ‡ฐ๐Ÿ‡ท'), - ('cn', 'FFXIV China', '๐Ÿ‡จ๐Ÿ‡ณ'); + ('cn', 'FFXIV China', '๐Ÿ‡จ๐Ÿ‡ณ'), + ('tw', 'FFXIV Taiwan', '๐Ÿ‡น๐Ÿ‡ผ'); -- repository INSERT INTO repository (id, name, description, slug, service_id) @@ -24,7 +25,13 @@ VALUES (1, 'ffxivneo/win32/release/boot', 'FFXIV Global/JP - Retail - Boot - Win (16, 'shanda/win32/release_chs/ex4', 'FFXIV China - Retail - ex4 (Endwalker) - Win32', '0728f998', 'cn'), (17, 'ffxivneo/win32/release/ex5', 'FFXIV Global/JP - Retail - ex5 (Dawntrail) - Win32', '6cfeab11', 'jp'), (18, 'actoz/win32/release_ko/ex5', 'FFXIV Korea - Retail - ex5 (Dawntrail) - Win32', '5050481e', 'kr'), - (19, 'shanda/win32/release_chs/ex5', 'FFXIV China - Retail - ex5 (Dawntrail) - Win32', '702fc90e', 'cn'); + (19, 'shanda/win32/release_chs/ex5', 'FFXIV China - Retail - ex5 (Dawntrail) - Win32', '702fc90e', 'cn'), + (20, 'ffxivtc/win32/release_tc/game', 'FFXIV Taiwan - Retail - Base Game - Win32', '0b90d03e', 'tw'), + (21, 'ffxivtc/win32/release_tc/ex1', 'FFXIV Taiwan - Retail - ex1 (Heavensward) - Win32', 'be3c0f25', 'tw'), + (22, 'ffxivtc/win32/release_tc/ex2', 'FFXIV Taiwan - Retail - ex2 (Stormblood) - Win32', '27355e9f', 'tw'), + (23, 'ffxivtc/win32/release_tc/ex3', 'FFXIV Taiwan - Retail - ex3 (Shadowbringers) - Win32', '50326e09', 'tw'), + (24, 'ffxivtc/win32/release_tc/ex4', 'FFXIV Taiwan - Retail - ex4 (Endwalker) - Win32', 'ce56fbaa', 'tw'), + (25, 'ffxivtc/win32/release_tc/ex5', 'FFXIV Taiwan - Retail - ex5 (Dawntrail) - Win32', 'b951cb3c', 'tw'); -- expansion INSERT INTO expansion (id, @@ -35,12 +42,12 @@ INSERT INTO expansion (id, name_ko, name_cn, name_tw) -VALUES (0, 'A Realm Reborn', 'ๆ–ฐ็”Ÿใ‚จใ‚ชใƒซใ‚ผใ‚ข', 'A Realm Reborn', 'A Realm Reborn', '์‹ ์ƒ ์—์˜ค๋ฅด์ œ์•„', '้‡็”Ÿไน‹ๅขƒ', ''), - (1, 'Heavensward', '่’ผๅคฉใฎใ‚คใ‚ทใƒฅใ‚ฌใƒซใƒ‰', 'Heavensward', 'Heavensward', '์ฐฝ์ฒœ์˜ ์ด์Šˆ๊ฐ€๋ฅด๋“œ', '่‹็ฉนไน‹็ฆๅŸŽ', ''), - (2, 'Stormblood', '็ด…่“ฎใฎใƒชใƒ™ใƒฌใƒผใ‚ฟใƒผ', 'Stormblood', 'Stormblood', 'ํ™๋ จ์˜ ํ•ด๋ฐฉ์ž', '็บข่Žฒไน‹็‹‚ๆฝฎ', ''), - (3, 'Shadowbringers', 'ๆผ†้ป’ใฎใƒดใ‚ฃใƒฉใƒณใ‚บ', 'Shadowbringers', 'Shadowbringers', '์น ํ‘์˜ ๋ฐ˜์—ญ์ž', 'ๆš—ๅฝฑไน‹้€†็„ฐ', ''), - (4, 'Endwalker', 'ๆšๆœˆใฎใƒ•ใ‚ฃใƒŠใƒผใƒฌ', 'Endwalker', 'Endwalker', 'ํšจ์›”์˜ ์ข…์–ธ', 'ๆ™“ๆœˆไน‹็ปˆ้€”', ''), - (5, 'Dawntrail', '้ป„้‡‘ใฎใƒฌใ‚ฌใ‚ทใƒผ', 'Dawntrail', 'Dawntrail', 'ํ™ฉ๊ธˆ์˜ ์œ ์‚ฐ', '้‡‘ๆ›ฆไน‹้—่พ‰', ''); +VALUES (0, 'A Realm Reborn', 'ๆ–ฐ็”Ÿใ‚จใ‚ชใƒซใ‚ผใ‚ข', 'A Realm Reborn', 'A Realm Reborn', '์‹ ์ƒ ์—์˜ค๋ฅด์ œ์•„', '้‡็”Ÿไน‹ๅขƒ', 'ๆ–ฐ็”Ÿ่‰พๅฅงๅ‚‘ไบž'), + (1, 'Heavensward', '่’ผๅคฉใฎใ‚คใ‚ทใƒฅใ‚ฌใƒซใƒ‰', 'Heavensward', 'Heavensward', '์ฐฝ์ฒœ์˜ ์ด์Šˆ๊ฐ€๋ฅด๋“œ', '่‹็ฉนไน‹็ฆๅŸŽ', '่’ผๅคฉไผŠไฟฎๅŠ ็ˆพๅพท'), + (2, 'Stormblood', '็ด…่“ฎใฎใƒชใƒ™ใƒฌใƒผใ‚ฟใƒผ', 'Stormblood', 'Stormblood', 'ํ™๋ จ์˜ ํ•ด๋ฐฉ์ž', '็บข่Žฒไน‹็‹‚ๆฝฎ', '็ด…่“ฎ่งฃๆ”พ่€…'), + (3, 'Shadowbringers', 'ๆผ†้ป’ใฎใƒดใ‚ฃใƒฉใƒณใ‚บ', 'Shadowbringers', 'Shadowbringers', '์น ํ‘์˜ ๋ฐ˜์—ญ์ž', 'ๆš—ๅฝฑไน‹้€†็„ฐ', 'ๆผ†้ป‘ๅๅ›่€…'), + (4, 'Endwalker', 'ๆšๆœˆใฎใƒ•ใ‚ฃใƒŠใƒผใƒฌ', 'Endwalker', 'Endwalker', 'ํšจ์›”์˜ ์ข…์–ธ', 'ๆ™“ๆœˆไน‹็ปˆ้€”', 'ๆ›‰ๆœˆไน‹็ต‚้€”'), + (5, 'Dawntrail', '้ป„้‡‘ใฎใƒฌใ‚ฌใ‚ทใƒผ', 'Dawntrail', 'Dawntrail', 'ํ™ฉ๊ธˆ์˜ ์œ ์‚ฐ', '้‡‘ๆ›ฆไน‹้—่พ‰', '้ปƒ้‡‘้บ็”ข'); -- expansion_repository_mapping INSERT INTO expansion_repository_mapping (game_repository_id, expansion_id, expansion_repository_id) @@ -61,4 +68,10 @@ VALUES (2, 0, 2), (12, 4, 16), (2, 5, 17), (7, 5, 18), - (12, 5, 19); \ No newline at end of file + (12, 5, 19), + (20, 0, 20), + (20, 1, 21), + (20, 2, 22), + (20, 3, 23), + (20, 4, 24), + (20, 5, 25); \ No newline at end of file