Completed
Push — master ( 4a1c4b...dec28d )
by Angus
03:08
created

Userscript   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 112
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 11

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
dl 0
loc 112
ccs 0
cts 74
cp 0
rs 10
c 0
b 0
f 0
wmc 16
lcom 1
cbo 11

4 Methods

Rating   Name   Duplication   Size   Complexity  
A site_fallback() 0 5 1
B __construct() 0 31 6
A update() 0 31 4
A favourite() 0 24 5
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
			$updateAvailable = version_compare($userUserscriptVersion, USERSCRIPT_VERSION, '<');
32
		} else {
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

This check looks for the else branches of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These else branches can be removed.

if (rand(1, 6) > 3) {
print "Check failed";
} else {
    //print "Check succeeded";
}

could be turned into

if (rand(1, 6) > 3) {
    print "Check failed";
}

This is much more concise to read.

Loading history...
33
34
		}
35
		$this->output->set_header('X-Userscript-Update-Available: '.((int) $updateAvailable));
36
	}
37
38
	/**
39
	 * This is the main update URL for the userscript.
40
	 *
41
	 * REQ_PARAMS: api-key, manga[site], manga[title], manga[chapter]
42
	 * METHOD:     POST
43
	 * URL:        /ajax/userscript/update
44
	 */
45
	public function update() : void {
46
		if($this->output->is_custom_header_set()) { $this->output->reset_status_header(); return; }
47
48
		$this->form_validation->set_rules('manga[site]', 'Manga [Site]', 'required');
49
		$this->form_validation->set_rules('manga[title]', 'Manga [Title]', 'required');
50
		$this->form_validation->set_rules('manga[chapter]', 'Manga [Chapter]', 'required');
51
52
		if($this->form_validation->run() === TRUE) {
53
			$manga = $this->input->post('manga');
54
55
			$titleData = $this->Tracker->list->update($this->userID, $manga['site'], $manga['title'], $manga['chapter'], TRUE, TRUE);
56
			if($titleData) {
57
				$malID = $this->Tracker->list->getMalID($this->userID, $titleData['id']);
58
				$json = [
59
					'mal_sync' => $this->User_Options->get('mal_sync', $this->userID),
60
					'mal_id'   => $malID['id'] ?? NULL,
61
					'chapter'  => $titleData['chapter']
62
				];
63
64
				$this->output
65
				     ->set_status_header('200')
66
				     ->set_content_type('application/json', 'utf-8')
67
				     ->set_output(json_encode($json));
68
			} else {
69
				//TODO: We should probably try and have more verbose errors here. Return via JSON or something.
70
				$this->output->set_status_header('400', 'Unable to update?');
71
			}
72
		} else {
73
			$this->output->set_status_header('400', 'Missing/invalid parameters.');
74
		}
75
	}
76
77
	/**
78
	 * Favourite a chapter via the userscript.
79
	 *
80
	 * REQ_PARAMS: api-key, manga[site], manga[title], manga[chapter]
81
	 * METHOD:     POST
82
	 * URL:        /ajax/userscript/favourite
83
	 */
84
	public function favourite() : void {
85
		if($this->output->is_custom_header_set()) { $this->output->reset_status_header(); return; }
86
87
		if($this->limiter->limit('tracker_userscript_favourite', 250)) {
88
			$this->output->set_status_header('429', 'Rate limit reached'); //rate limited reached
89
		} else {
90
			$this->form_validation->set_rules('manga[site]', 'Manga [Site]', 'required');
91
			$this->form_validation->set_rules('manga[title]', 'Manga [Title]', 'required');
92
			$this->form_validation->set_rules('manga[chapter]', 'Manga [Chapter]', 'required');
93
94
			if($this->form_validation->run() === TRUE) {
95
				$manga = $this->input->post('manga');
96
97
				$success = $this->Tracker->favourites->set($manga['site'], $manga['title'], $manga['chapter'], $this->userID);
98
				if($success['bool']) {
99
					$this->output->set_status_header('200', $success['status']); //Success!
100
				} else {
101
					$this->output->set_status_header('400', $success['status']);
102
				}
103
			} else {
104
				$this->output->set_status_header('400', 'Missing/invalid parameters.');
105
			}
106
		}
107
	}
108
109
	public function site_fallback() : void {
110
		$this->output
111
			->set_content_type('js') // You could also use ".jpeg" which will have the full stop removed before looking in config/mimes.php
112
			->set_output('console.log('.json_encode('@require site missing? - '.current_url()).');');
113
	}
114
}
115