Completed
Push — master ( c2cfef...1a5a57 )
by Angus
02:24
created

Tracker_Admin_Model::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 3
ccs 3
cts 3
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types=1); defined('BASEPATH') OR exit('No direct script access allowed');
2
3
class Tracker_Admin_Model extends Tracker_Base_Model {
4 119
	public function __construct() {
5 119
		parent::__construct();
6 119
	}
7
8
	/**
9
	 * Checks for any series that haven't updated in 16 hours and updates them.
10
	 * This is ran every 4 hours via a cron job.
11
	 */
12
	public function updateLatestChapters() {
13
		// @formatter:off
14
		$query = $this->db
15
			->select('
16
				tracker_titles.id,
17
				tracker_titles.title,
18
				tracker_titles.title_url,
19
				tracker_titles.status,
20
				tracker_sites.site,
21
				tracker_sites.site_class,
22
				tracker_sites.status,
23
				tracker_titles.latest_chapter,
24
				tracker_titles.last_updated,
25
				from_unixtime(MAX(auth_users.last_login)) AS timestamp
26
			')
27
			->from('tracker_titles')
28
			->join('tracker_sites', 'tracker_sites.id = tracker_titles.site_id', 'left')
29
			->join('tracker_chapters', 'tracker_titles.id = tracker_chapters.title_id', 'left')
30
			->join('auth_users', 'tracker_chapters.user_id = auth_users.id', 'left')
31
			->where('tracker_sites.status', 'enabled')
32
			->group_start()
33
				//Check if title is marked as on-going...
34
				->where('tracker_titles.status', 0)
35
				//AND matches one of where queries below
36
				->group_start()
37
					//Then check if it's NULL (only occurs for new series)
38
					->where('latest_chapter', NULL)
39
					//OR if it hasn't updated within the past 12 hours AND isn't a custom update site
40
					->or_group_start()
41
						->where('tracker_sites.use_custom', 'N')
42
						->where('last_checked < DATE_SUB(NOW(), INTERVAL 12 HOUR)')
43
					->group_end()
44
					//OR it is a custom update site and hasn't updated within the past 72 hours (3 days)
45
					->or_where('last_checked < DATE_SUB(NOW(), INTERVAL 72 HOUR)')
46
				->group_end()
47
			->group_end()
48
			->or_group_start()
49
				//Check if title is marked as complete...
50
				->where('tracker_titles.status', 1)
51
				//Then check if it hasn't updated within the past week
52
				->where('last_checked < DATE_SUB(NOW(), INTERVAL 1 WEEK)')
53
			->group_end()
54
			//Status 2 (One-shot) & 255 (Ignore) are both not updated intentionally.
55
			->group_by('tracker_titles.id, tracker_chapters.active')
56
			//Check if the series is actually being tracked by someone
57
			->having('timestamp IS NOT NULL')
58
			//AND if it's currently marked as active by the user
59
			->having('tracker_chapters.active', 'Y')
60
			//AND if they have been active in the last 120 hours (5 days)
61
			->having('timestamp > DATE_SUB(NOW(), INTERVAL 120 HOUR)')
62
			->order_by('tracker_titles.title', 'ASC')
63
			->get();
64
		// @formatter:on
65
66
		if($query->num_rows() > 0) {
67
			foreach ($query->result() as $row) {
68
				print "> {$row->title} <{$row->site_class}> | <{$row->id}>"; //Print this prior to doing anything so we can more easily find out if something went wrong
69
				$titleData = $this->sites->{$row->site_class}->getTitleData($row->title_url);
70
				if(is_array($titleData) && !is_null($titleData['latest_chapter'])) {
71
					//FIXME: "At the moment" we don't seem to be doing anything with TitleData['last_updated'].
72
					//       Should we even use this? Y/N
73
					if($this->Tracker->title->updateByID((int) $row->id, $titleData['latest_chapter'])) {
74
						//Make sure last_checked is always updated on successful run.
75
						//CHECK: Is there a reason we aren't just doing this in updateByID?
76
						$this->db->set('last_checked', 'CURRENT_TIMESTAMP', FALSE)
77
						         ->where('id', $row->id)
78
						         ->update('tracker_titles');
79
80
						print " - ({$titleData['latest_chapter']})\n";
81
					} else {
82
						print " - Something went wrong?\n";
83
					}
84
				} else {
85
					log_message('error', "{$row->title} failed to update successfully");
86
					$this->Tracker->title->updateFailedChecksByID((int) $row->id);
87
88
					print " - FAILED TO PARSE\n";
89
				}
90
			}
91
		}
92
	}
93
94
	/**
95
	 * Checks for any sites which support custom updating (usually via following lists) and updates them.
96
	 * This is run hourly.
97
	 */
98
	public function updateCustom() {
99
		$query = $this->db->select('*')
100
		                  ->from('tracker_sites')
101
		                  ->where('status', 'enabled')
102
		                  ->get();
103
104
		$sites = $query->result_array();
105
		foreach ($sites as $site) {
106
			if($titleDataList = $this->sites->{$site['site_class']}->doCustomUpdate()) {
107
				foreach ($titleDataList as $titleURL => $titleData) {
108
					print "> {$titleData['title']} <{$site['site_class']}>"; //Print this prior to doing anything so we can more easily find out if something went wrong
109
					if(is_array($titleData) && !is_null($titleData['latest_chapter'])) {
110
						if($dbTitleData = $this->Tracker->title->getID($titleURL, (int) $site['id'], FALSE, TRUE)) {
111
							if($this->sites->{$site['site_class']}->doCustomCheck($dbTitleData['latest_chapter'], $titleData['latest_chapter'])) {
112
								$titleID = $dbTitleData['id'];
113 View Code Duplication
								if($this->Tracker->title->updateByID((int) $titleID, $titleData['latest_chapter'])) {
114
									//Make sure last_checked is always updated on successful run.
115
									//CHECK: Is there a reason we aren't just doing this in updateByID?
116
									$this->db->set('last_checked', 'CURRENT_TIMESTAMP', FALSE)
117
									         ->where('id', $titleID)
118
									         ->update('tracker_titles');
119
120
									print " - ({$titleData['latest_chapter']})\n";
121
								} else {
122
									print " - Title doesn't exist? ($titleID)\n";
123
								}
124
							} else {
125
								print " - Failed Check.\n";
126
							}
127
						} else {
128
							log_message('error', "CUSTOM: {$titleData['title']} - {$site['site_class']} || Title does not exist in DB??");
129
							print " - Possibly diff language than in DB? ($titleURL)\n";
130
						}
131
					} else {
132
						log_message('error', "CUSTOM: {$titleData['title']} - {$site['site_class']} failed to custom update successfully");
133
						print " - FAILED TO PARSE\n";
134
					}
135
				}
136
			}
137
		}
138
	}
139
140
	public function refollowCustom() {
141
		$query = $this->db->select('tracker_titles.id, tracker_titles.title_url, tracker_sites.site_class')
142
		                  ->from('tracker_titles')
143
		                  ->join('tracker_sites', 'tracker_sites.id = tracker_titles.site_id', 'left')
144
		                  ->where('tracker_titles.followed','N')
145
		                  ->where('tracker_titles !=', '255')
146
		                  ->where('tracker_sites.status', 'enabled')
147
		                  ->where('tracker_sites.use_custom', 'Y')
148
		                  ->get();
149
150
		if($query->num_rows() > 0) {
151
			foreach($query->result() as $row) {
152
				$titleData = $this->Tracker->sites->{$row->site_class}->getTitleData($row->title_url, TRUE);
153
154
				if($titleData) {
155
					$titleData = array_intersect_key($titleData, array_flip(['followed']));
156
157
					if(!empty($titleData)) {
158
						$this->db->set($titleData)
159
						         ->where('id', $row->id)
160
						         ->update('tracker_titles');
161
162
						print "> {$row->site_class}:{$row->id}:{$row->title_url} FOLLOWED\n";
163
					} else {
164
						print "> {$row->site_class}:{$row->id}:{$row->title_url} FAILED (NO FOLLOWED)\n";
165
					}
166
				} else {
167
					log_message('error', "getTitleData failed for: {$row->site_class} | {$row->title_url}");
168
					print "> {$row->site_class}:{$row->id}:{$row->title_url} FAILED (NO TITLEDATA)\n";
169
				}
170
			}
171
		}
172
	}
173
174
	/**
175
	 * Checks every series to see if title has changed, and update if so.
176
	 * This is ran once a month via a cron job
177
	 */
178
	public function updateTitles() {
179
		// @formatter:off
180
		$query = $this->db
181
			->select('
182
				tracker_titles.id,
183
				tracker_titles.title,
184
				tracker_titles.title_url,
185
				tracker_titles.status,
186
				tracker_sites.site,
187
				tracker_sites.site_class,
188
				tracker_sites.status,
189
				tracker_titles.latest_chapter,
190
				tracker_titles.last_updated
191
			')
192
			->from('tracker_titles')
193
			->join('tracker_sites', 'tracker_sites.id = tracker_titles.site_id', 'left')
194
			->where('tracker_sites.status', 'enabled')
195
196
			->group_by('tracker_titles.id')
197
			->order_by('tracker_titles.title', 'ASC')
198
			->get();
199
		// @formatter:on
200
201
		if($query->num_rows() > 0) {
202
			foreach ($query->result() as $row) {
203
				print "> {$row->title} <{$row->site_class}>"; //Print this prior to doing anything so we can more easily find out if something went wrong
204
				$titleData = $this->sites->{$row->site_class}->getTitleData($row->title_url);
205
				if($titleData['title'] && is_array($titleData) && !is_null($titleData['latest_chapter'])) {
206
					if($titleData['title'] !== $row->title) {
207
						$this->db->set('title', $titleData['title'])
208
						         ->where('id', $row->id)
209
						         ->update('tracker_titles');
210
						//TODO: Add to history somehow?
211
						print " - NEW TITLE ({$titleData['title']})\n";
212
					} else {
213
						print " - TITLE NOT CHANGED\n";
214
					}
215
216
					//We might as well try to update as well.
217 View Code Duplication
					if($this->Tracker->title->updateByID((int) $row->id, $titleData['latest_chapter'])) {
218
						$this->db->set('last_checked', 'CURRENT_TIMESTAMP', FALSE)
219
						         ->where('id', $row->id)
220
						         ->update('tracker_titles');
221
					}
222
				} else {
223
					log_message('error', "{$row->title} failed to update title successfully");
224
					print " - FAILED TO PARSE\n";
225
				}
226
			}
227
		}
228
	}
229
230
	public function getNextUpdateTime(string $format = "%H:%I:%S") : string {
231
		$temp_now = new DateTime();
232
		$temp_now->setTimezone(new DateTimeZone('America/New_York'));
233
		$temp_now_formatted = $temp_now->format('Y-m-d H:i:s');
234
235
		//NOTE: PHP Bug: DateTime:diff doesn't play nice with setTimezone, so we need to create another DT object
236
		$now         = new DateTime($temp_now_formatted);
237
		$future_date = new DateTime($temp_now_formatted);
238
		$now_hour    = (int) $now->format('H');
239
		if($now_hour < 4) {
240
			//Time until 4am
241
			$future_date->setTime(4, 00);
242
		} elseif($now_hour < 8) {
243
			//Time until 8am
244
			$future_date->setTime(8, 00);
245
		} elseif($now_hour < 12) {
246
			//Time until 12pm
247
			$future_date->setTime(12, 00);
248
		} elseif($now_hour < 16) {
249
			//Time until 4pm
250
			$future_date->setTime(16, 00);
251
		} elseif($now_hour < 20) {
252
			//Time until 8pm
253
			$future_date->setTime(20, 00);
254
		} else {
255
			//Time until 12am
256
			$future_date->setTime(00, 00);
257
			$future_date->add(new DateInterval('P1D'));
258
		}
259
260
		$interval = $future_date->diff($now);
261
		return $interval->format($format);
262
	}
263
}
264