1
|
|
|
<?php defined('BASEPATH') or exit('No direct script access allowed'); |
2
|
|
|
|
3
|
|
|
class Userscript extends AJAX_Controller { |
4
|
|
|
private $userID; |
5
|
|
|
|
6
|
|
|
public function __construct() { |
7
|
|
|
parent::__construct(); |
8
|
|
|
|
9
|
|
|
$this->load->library('Limiter'); |
10
|
|
|
$this->load->library('form_validation'); |
11
|
|
|
|
12
|
|
|
//500 requests per hour to either AJAX request. |
13
|
|
|
if($this->limiter->limit('tracker_userscript', 1000)) { |
14
|
|
|
$this->output->set_status_header('429', 'Rate limit reached'); //rate limited reached |
15
|
|
|
} |
16
|
|
|
|
17
|
|
|
//API Key is required for all AJAX requests |
18
|
|
|
//We're not using set_rules here since we can't run form_validation twice. |
19
|
|
|
if($this->form_validation->required($this->input->post('api-key')) && ctype_alnum($this->input->post('api-key'))) { |
20
|
|
|
$this->userID = $this->User->get_id_from_api_key($this->input->post('api-key')); |
21
|
|
|
if(!$this->userID) { |
22
|
|
|
$this->output->set_status_header('400', 'Invalid API Key'); |
23
|
|
|
} |
24
|
|
|
} else { |
25
|
|
|
$this->output->set_status_header('400', 'Missing/invalid parameters.'); |
26
|
|
|
} |
27
|
|
|
|
28
|
|
|
$updateAvailable = TRUE; |
29
|
|
|
// TODO: We should record this for analytics purposes. |
30
|
|
|
if($userUserscriptVersion = $this->input->get_request_header('X-Userscript-Version')) { |
31
|
|
|
if(version_compare($userUserscriptVersion, '1.11.3', '<=')) { |
32
|
|
|
// 1.11.3 and below uses an old namespace and having the user update through our notification will install a duplicate version of the script |
33
|
|
|
// so instead we return this is FALSE |
34
|
|
|
$updateAvailable = FALSE; |
35
|
|
|
} else { |
36
|
|
|
$updateAvailable = version_compare($userUserscriptVersion, USERSCRIPT_VERSION, '<'); |
37
|
|
|
} |
38
|
|
|
} else { |
39
|
|
|
|
40
|
|
|
} |
41
|
|
|
$this->output->set_header('X-Userscript-Update-Available: '.((int) $updateAvailable)); |
42
|
|
|
} |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* This is the main update URL for the userscript. |
46
|
|
|
* |
47
|
|
|
* REQ_PARAMS: api-key, manga[site], manga[title], manga[chapter] |
48
|
|
|
* METHOD: POST |
49
|
|
|
* URL: /ajax/userscript/update |
50
|
|
|
*/ |
51
|
|
|
public function update() : void { |
52
|
|
|
if($this->output->is_custom_header_set()) { $this->output->reset_status_header(); return; } |
53
|
|
|
|
54
|
|
|
$this->form_validation->set_rules('manga[site]', 'Manga [Site]', 'required'); |
55
|
|
|
$this->form_validation->set_rules('manga[title]', 'Manga [Title]', 'required'); |
56
|
|
|
$this->form_validation->set_rules('manga[chapter]', 'Manga [Chapter]', 'required'); |
57
|
|
|
|
58
|
|
|
if($this->form_validation->run() === TRUE) { |
59
|
|
|
$manga = $this->input->post('manga'); |
60
|
|
|
|
61
|
|
|
$titleData = $this->Tracker->list->update($this->userID, $manga['site'], $manga['title'], $manga['chapter'], TRUE, TRUE); |
62
|
|
|
if($titleData) { |
63
|
|
|
$malID = $this->Tracker->list->getMalID($this->userID, $titleData['id']); |
64
|
|
|
$json = [ |
65
|
|
|
'mal_sync' => $this->User_Options->get('mal_sync', $this->userID), |
66
|
|
|
'mal_id' => $malID['id'] ?? NULL, |
67
|
|
|
'chapter' => $titleData['chapter'] |
68
|
|
|
]; |
69
|
|
|
|
70
|
|
|
$this->output |
71
|
|
|
->set_status_header('200') |
72
|
|
|
->set_content_type('application/json', 'utf-8') |
73
|
|
|
->set_output(json_encode($json)); |
74
|
|
|
} else { |
75
|
|
|
//TODO: We should probably try and have more verbose errors here. Return via JSON or something. |
76
|
|
|
$this->output->set_status_header('400', 'Unable to update?'); |
77
|
|
|
} |
78
|
|
|
} else { |
79
|
|
|
$this->output->set_status_header('400', 'Missing/invalid parameters.'); |
80
|
|
|
} |
81
|
|
|
} |
82
|
|
|
|
83
|
|
|
/** |
84
|
|
|
* Favourite a chapter via the userscript. |
85
|
|
|
* |
86
|
|
|
* REQ_PARAMS: api-key, manga[site], manga[title], manga[chapter] |
87
|
|
|
* METHOD: POST |
88
|
|
|
* URL: /ajax/userscript/favourite |
89
|
|
|
*/ |
90
|
|
|
public function favourite() : void { |
91
|
|
|
if($this->output->is_custom_header_set()) { $this->output->reset_status_header(); return; } |
92
|
|
|
|
93
|
|
|
if($this->limiter->limit('tracker_userscript_favourite', 250)) { |
94
|
|
|
$this->output->set_status_header('429', 'Rate limit reached'); //rate limited reached |
95
|
|
|
} else { |
96
|
|
|
$this->form_validation->set_rules('manga[site]', 'Manga [Site]', 'required'); |
97
|
|
|
$this->form_validation->set_rules('manga[title]', 'Manga [Title]', 'required'); |
98
|
|
|
$this->form_validation->set_rules('manga[chapter]', 'Manga [Chapter]', 'required'); |
99
|
|
|
$this->form_validation->set_rules('manga[page]', 'Manga [Page]', ''); |
100
|
|
|
|
101
|
|
|
if($this->form_validation->run() === TRUE) { |
102
|
|
|
$manga = $this->input->post('manga'); |
103
|
|
|
|
104
|
|
|
$success = $this->Tracker->favourites->set($this->userID, $manga['site'], $manga['title'], $manga['chapter'], $manga['page'] ?? NULL); |
105
|
|
|
if($success['bool']) { |
106
|
|
|
$this->output->set_status_header('200', $success['status']); //Success! |
107
|
|
|
} else { |
108
|
|
|
$this->output->set_status_header('400', $success['status']); |
109
|
|
|
} |
110
|
|
|
} else { |
111
|
|
|
$this->output->set_status_header('400', 'Missing/invalid parameters.'); |
112
|
|
|
} |
113
|
|
|
} |
114
|
|
|
} |
115
|
|
|
|
116
|
|
|
public function site_fallback() : void { |
117
|
|
|
$this->output |
118
|
|
|
->set_content_type('js') // You could also use ".jpeg" which will have the full stop removed before looking in config/mimes.php |
119
|
|
|
->set_output('console.log('.json_encode('@require site missing? - '.current_url()).');'); |
120
|
|
|
} |
121
|
|
|
} |
122
|
|
|
|