OSDN Git Service

7f6844069d4af058fefad7bec1d87e812d92e75c
[newslash/newslash.git] / src / newslash_web / lib / Newslash / Web / Controller / API / Story.pm
1 package Newslash::Web::Controller::API::Story;
2 use Mojo::Base 'Mojolicious::Controller';
3 use Mojo::Util qw(dumper);
4 use Mojo::JSON qw(decode_json encode_json);
5
6 use DateTime::Format::ISO8601;
7 use DateTime::Format::MySQL;
8 use Data::Dumper;
9
10 sub _submission_to_story {
11     my ($c, $submission) = @_;
12     my $story = {};
13     for my $k (qw{title tags}) {
14         $story->{$k} = $submission->{$k};
15     }
16     # convert intro_text
17     $story->{intro_text} = $c->tt2renderer->render("system/submission/submission_formatter", $submission);
18     $story->{submitter} = $submission->{uid};
19     return $story;
20 }
21
22 sub _journal_to_story {
23     my ($c, $journal) = @_;
24     my $story = {};
25     for my $k (qw{title tags}) {
26         $story->{$k} = $journal->{$k};
27     }
28     $story->{intro_text} = $c->tt2renderer->render('system/subsmission/journal2submission',
29                                                    { text => $journal->{full_text},
30                                                      author => $journal->{author},
31                                                    });
32     if (!$story->{intro_text}) {
33         $story->{intro_text} = $journal->{full_text};
34     }
35     $story->{submitter} = $journal->{uid};
36     return $story;
37 }
38
39 sub get {
40     my $c = shift;
41     my $sid = $c->param('sid');
42     my $stoid = $c->param('stoid');
43     my $subid = $c->param('subid') || $c->param('submission_id');
44     my $journal_id = $c->param('journal_id');
45     my $stories = $c->model('stories');
46     my $story;
47     my $user = $c->stash('user');
48
49     if ($stoid) {
50         $story = $stories->select(story_id => $stoid,
51                                   hide_future => !$user->{is_admin},
52                                   public_only => !$user->{is_admin},
53                                  );
54     }
55     elsif ($sid) {
56         $story = $stories->select(sid => $sid,
57                                   hide_future => !$user->{is_admin},
58                                   public_only => !$user->{is_admin},
59                                  );
60     }
61     elsif ($subid) {
62         my $item = $c->model('submissions')->select(subid => $subid);
63         if ($item) {
64             $story = $c->_submission_to_story($item);
65         }
66     }
67     elsif ($journal_id) {
68         my $item = $c->model('journals')->select(id => $journal_id);
69         if ($item) {
70             $story = $c->_journal_to_story($item);
71         }
72     }
73     else {
74         $c->render(json => { error => 1, message => "invalid_request" });
75         $c->rendered(400);
76         return;
77     }
78
79     if (!$story) {
80         $c->render(json => { error => 1, message => "not_found" });
81         $c->rendered(404);
82         return;
83     }
84     my $related = $stories->get_related_items(stoid => $story->{stoid});
85     $story->{related} = $related;
86     $c->render(json => { item => $story });
87 }
88
89 sub post {
90     my $c = shift;
91     my $params = {};
92
93     my $user = $c->stash('user');
94     my $stories = $c->model('stories');
95     my $users = $c->model('users');
96     my $topics = $c->model('topics');
97     my $submissions = $c->model('submissions');
98
99     my $data = $c->req->json;
100     my $item = $data->{item};
101     my $message = "";
102
103     if (!$user->{is_admin} && !$user->{editor}) {
104         $c->render(json => { err => 1, message => "no_permission" });
105         $c->rendered(403);
106         return;
107     }
108
109     # client send data like this:
110     # {"item":{"title":"ほげ","introtext":"ほんぶん","bodytext":"","createtime":"2017-06-30T21:50:04","author":"hylom","dept":"テスト","commentstatus":"enabled","submissioncopy":0,"url":"","email":"","tags_string":"news","related_urls":"http://sdtest.osdn.co.jp:3000/story/16/01/28/0610215/"},"action":"preview"}
111
112     $params->{title} = $c->format_htmltext($item->{title}, "title");
113     $message = "no_title" if !$params->{title};
114
115     # convert time
116     my $dt = DateTime::Format::ISO8601->parse_datetime($item->{createtime} || $item->{create_time});
117     if (!$dt) {
118         $message = "invalid_createtime";
119     }
120     else {
121         # convert localtime to GMT
122         if ($user && $user->{config}->{ui}->{offset_sec}) {
123             my $offset_sec = $user->{config}->{ui}->{offset_sec} || 0;
124             if ($offset_sec) {
125                 $dt->subtract(seconds => $offset_sec);
126             }
127         }
128         $params->{time} = DateTime::Format::MySQL->format_datetime($dt);
129     }
130
131     # check: is author valid ?
132     my $author = $users->select(nickname => $item->{author});
133     if (!defined $author || !$author->{is_admin}) {
134         $message = "invalid_author";
135     }
136     $params->{uid} = $author->{uid};
137
138     # check: dept exists ?
139     $params->{dept} = $item->{dept};
140     if (!$params->{dept}) {
141         $message = "department_not_given";
142     }
143
144     # check: introtext exists ?
145     my $intro_text = $item->{intro_text} || $item->{introtext} || "";
146     $params->{introtext} = $c->format_htmltext($intro_text, "story");
147     $params->{intro_text} = $params->{introtext};
148     if (!$params->{introtext}) {
149         $message = "introtext_not_given";
150     }
151
152     # bodytext (omittable)
153     my $body_text = $item->{body_text} || $item->{bodytext} || "";
154     $params->{bodytext} = $c->format_htmltext($body_text, "story");
155
156     # related urls
157     my $related_string = $item->{add_related} || $item->{related_urls} || "";
158     my @relateds = split(/\s+/, $related_string);
159     my $related_sids = [];
160     for my $related (@relateds) {
161         if ($related =~ m|^.*(\d\d/\d\d/\d\d/\d+)/?|) {
162             push @$related_sids, $1;
163         }
164     }
165     $params->{add_related} = $related_sids;
166
167     # tags
168     # tags_strings is like: "mainpage japan business transport"
169     my @tags = split(/\s+/, $item->{tags_string} || "");
170     $params->{add_tags} = \@tags;
171
172     # add topics
173     my $primary_topic = $topics->get_primary_topic_from_tags(\@tags);
174     if ($primary_topic) {
175         $params->{topics_chosen} = { $primary_topic->{tid} => 10 };
176     }
177     else {
178         $params->{topics_chosen} = { 49 => 10, }; # tid => weight
179     }
180
181     # TODO: media related
182     #$item->{mediaurl};
183     #$item->{mediatype};
184
185     # source
186     if ($item->{source_id}) {
187         if ($item->{source_type} eq "submission") {
188             $params->{submission_id} = $item->{source_id};
189         }
190         elsif ($item->{source_type} eq "journal") {
191             $params->{journal_id} = $item->{source_id};
192         }
193     }
194
195     $params->{commentstatus} = $item->{commentstatus} || $item->{comment_status} || "enabled";
196     if (!$item->{display}) {
197         $params->{neverdisplay} = 1;
198     }
199
200     $params->{action} = $data->{action} || 'preview';
201
202     if (length($message) > 0) {
203         $c->render(json => { err => 1, message => $message });
204         $c->rendered(400);
205         return;
206     }
207
208     if ($data->{action} eq 'preview') {
209         $c->render(json => {item => $params});
210         return;
211     }
212
213     # invalid action
214     if ($params->{action} ne 'post') {
215         $c->render(json => { err => 1, message => "invalid_action" });
216         $c->rendered(400);
217         return;
218     }
219
220     # post action
221     my ($sid, $stoid);
222     if ($item->{stoid} || $item->{id}) {
223         # update story
224         $params->{stoid} = $item->{stoid} || $item->{id};
225         ($sid, $stoid) = $stories->update(user => $user, %$params);
226     }
227     else {
228         # create story
229         ($sid, $stoid) = $stories->create(user => $user, %$params);
230         #$stoid = $stories->create2(user => $user,
231         #                           config => $c->config->{Story},
232         #                           params => $params);
233     }
234
235     # error check
236     if (!$stoid) {
237         if ($stories->last_errorno && $stories->last_errorno == 1062) { #ER_DUP_ENTRY
238             $c->render(json => { error => 1, message => "duplicated_entry" });
239             $c->rendered(409);
240             return;
241         }
242         $c->render(json => { error => 1, message => $stories->last_error });
243         $c->rendered(500);
244         return;
245     }
246
247     # post succeeded, return result
248     $c->render(json => {type => "story", id => $stoid, sid => $sid, url_id => $sid});
249     $c->event_que->emit("story", "post", $user->{uid}, $stoid);
250     $c->stats->add_event_counter("story_create");
251     return;
252 }
253
254 1;