about summary refs log tree commit diff stats
path: root/src/notification.cpp
diff options
context:
space:
mode:
authorKelly Rauchenberger <fefferburbia@gmail.com>2016-05-20 15:34:44 -0400
committerKelly Rauchenberger <fefferburbia@gmail.com>2016-05-20 15:34:44 -0400
commit0ccac89815ee92c69fefc148cfb272faf7309136 (patch)
tree228775a433018c8a5fd20f0ebb0f8446057b2112 /src/notification.cpp
parentf465dce27cf0f07039e29d8975ad98939f0df3a9 (diff)
downloadlibtwittercpp-0ccac89815ee92c69fefc148cfb272faf7309136.tar.gz
libtwittercpp-0ccac89815ee92c69fefc148cfb272faf7309136.tar.bz2
libtwittercpp-0ccac89815ee92c69fefc148cfb272faf7309136.zip
Started implementing user streams
You can now start a user stream and end it yourself. If it disconnects abnormally, it will reconnect with a backoff as described by Twitter. Some data structures have some fields parsed now; tweets have IDs, text, and authors. Users have IDs, screen names, and names. Notifications from the stream are parsed completely. The ability to follow and unfollow users has also been added, as well as the ability to get a list of friends and followers, and to reply to a tweet.
Diffstat (limited to 'src/notification.cpp')
-rw-r--r--src/notification.cpp848
1 files changed, 848 insertions, 0 deletions
diff --git a/src/notification.cpp b/src/notification.cpp new file mode 100644 index 0000000..3dcdd90 --- /dev/null +++ b/src/notification.cpp
@@ -0,0 +1,848 @@
1#include "notification.h"
2#include <cassert>
3#include <new>
4#include <json.hpp>
5
6using nlohmann::json;
7
8namespace twitter {
9
10 notification::type notification::getType() const
11 {
12 return _type;
13 }
14
15 notification::notification() : _type(type::invalid)
16 {
17
18 }
19
20 notification::notification(std::string data, const user& current_user)
21 {
22 auto _data = json::parse(data);
23
24 if (_data.find("in_reply_to_status_id") != _data.end())
25 {
26 _type = type::tweet;
27
28 new(&_tweet) tweet(data);
29 } else if (_data.find("event") != _data.end())
30 {
31 std::string event = _data.at("event");
32 user source(_data.at("source").dump());
33 user target(_data.at("target").dump());
34
35 if (event == "user_update")
36 {
37 _type = type::update_user;
38
39 new(&_user) user(source);
40 } else if (event == "block")
41 {
42 _type = type::block;
43
44 new(&_user) user(target);
45 } else if (event == "unblock")
46 {
47 _type = type::unblock;
48
49 new(&_user) user(target);
50 } else if (event == "favorite")
51 {
52 new(&_user_and_tweet._tweet) tweet(_data.at("target_object").dump());
53
54 if (current_user == source)
55 {
56 _type = type::favorite;
57
58 new(&_user_and_tweet._user) user(target);
59 } else {
60 _type = type::favorited;
61
62 new(&_user_and_tweet._user) user(source);
63 }
64 } else if (event == "unfavorite")
65 {
66 new(&_user_and_tweet._tweet) tweet(_data.at("target_object").dump());
67
68 if (current_user == source)
69 {
70 _type = type::unfavorite;
71
72 new(&_user_and_tweet._user) user(target);
73 } else {
74 _type = type::unfavorited;
75
76 new(&_user_and_tweet._user) user(source);
77 }
78 } else if (event == "follow")
79 {
80 if (current_user == source)
81 {
82 _type = type::follow;
83
84 new(&_user) user(target);
85 } else {
86 _type = type::followed;
87
88 new(&_user) user(source);
89 }
90 } else if (event == "unfollow")
91 {
92 _type = type::unfollow;
93
94 new(&_user) user(target);
95 } else if (event == "list_created")
96 {
97 _type = type::list_created;
98
99 new(&_list) list(_data.at("target_object").dump());
100 } else if (event == "list_destroyed")
101 {
102 _type = type::list_destroyed;
103
104 new(&_list) list(_data.at("target_object").dump());
105 } else if (event == "list_updated")
106 {
107 _type = type::list_updated;
108
109 new(&_list) list(_data.at("target_object").dump());
110 } else if (event == "list_member_added")
111 {
112 new(&_user_and_list._list) list(_data.at("target_object").dump());
113
114 if (current_user == source)
115 {
116 _type = type::list_add;
117
118 new(&_user_and_list._user) user(target);
119 } else {
120 _type = type::list_added;
121
122 new(&_user_and_list._user) user(source);
123 }
124 } else if (event == "list_member_removed")
125 {
126 new(&_user_and_list._list) list(_data.at("target_object").dump());
127
128 if (current_user == source)
129 {
130 _type = type::list_remove;
131
132 new(&_user_and_list._user) user(target);
133 } else {
134 _type = type::list_removed;
135
136 new(&_user_and_list._user) user(source);
137 }
138 } else if (event == "list_member_subscribe")
139 {
140 new(&_user_and_list._list) list(_data.at("target_object").dump());
141
142 if (current_user == source)
143 {
144 _type = type::list_subscribe;
145
146 new(&_user_and_list._user) user(target);
147 } else {
148 _type = type::list_subscribed;
149
150 new(&_user_and_list._user) user(source);
151 }
152 } else if (event == "list_member_unsubscribe")
153 {
154 new(&_user_and_list._list) list(_data.at("target_object").dump());
155
156 if (current_user == source)
157 {
158 _type = type::list_unsubscribe;
159
160 new(&_user_and_list._user) user(target);
161 } else {
162 _type = type::list_unsubscribed;
163
164 new(&_user_and_list._user) user(source);
165 }
166 } else if (event == "quoted_tweet")
167 {
168 _type = type::quoted;
169
170 new(&_user_and_tweet._user) user(source);
171 new(&_user_and_tweet._tweet) tweet(_data.at("target_object").dump());
172 }
173 } else if (_data.find("warning") != _data.end())
174 {
175 new(&_warning) std::string(_data.at("warning").at("message").get<std::string>());
176
177 if (_data.at("warning").at("code") == "FALLING_BEHIND")
178 {
179 _type = type::stall;
180 } else if (_data.at("warning").at("code") == "FOLLOWS_OVER_LIMIT")
181 {
182 _type = type::follow_limit;
183 } else {
184 _type = type::unknown_warning;
185 }
186 } else if (_data.find("delete") != _data.end())
187 {
188 _type = type::deletion;
189
190 _user_id_and_tweet_id._tweet_id = _data.at("delete").at("status").at("id");
191 _user_id_and_tweet_id._user_id = _data.at("delete").at("status").at("user_id");
192 } else if (_data.find("scrub_geo") != _data.end())
193 {
194 _type = type::scrub_location;
195
196 _user_id_and_tweet_id._tweet_id = _data.at("scrub_geo").at("up_to_status_id");
197 _user_id_and_tweet_id._user_id = _data.at("scrub_geo").at("user_id");
198 } else if (_data.find("limit") != _data.end())
199 {
200 _type = type::limit;
201
202 _limit = _data.at("limit").at("track");
203 } else if (_data.find("status_withheld") != _data.end())
204 {
205 _type = type::withhold_status;
206
207 _withhold_status._user_id = _data.at("status_withheld").at("user_id");
208 _withhold_status._tweet_id = _data.at("status_withheld").at("id");
209
210 new(&_withhold_status._countries) std::vector<std::string>();
211 for (auto s : _data.at("status_withheld").at("withheld_in_countries"))
212 {
213 _withhold_status._countries.push_back(s);
214 }
215 } else if (_data.find("user_withheld") != _data.end())
216 {
217 _type = type::withhold_user;
218
219 _withhold_user._user_id = _data.at("user_withheld").at("id");
220
221 new(&_withhold_user._countries) std::vector<std::string>();
222 for (auto s : _data.at("user_withheld").at("withheld_in_countries"))
223 {
224 _withhold_user._countries.push_back(s);
225 }
226 } else if (_data.find("disconnect") != _data.end())
227 {
228 _type = type::disconnect;
229
230 switch (_data.at("disconnect").at("code").get<int>())
231 {
232 case 1: _disconnect = disconnect_code::shutdown; break;
233 case 2: _disconnect = disconnect_code::duplicate; break;
234 case 4: _disconnect = disconnect_code::stall; break;
235 case 5: _disconnect = disconnect_code::normal; break;
236 case 6: _disconnect = disconnect_code::token_revoked; break;
237 case 7: _disconnect = disconnect_code::admin_logout; break;
238 case 9: _disconnect = disconnect_code::limit; break;
239 case 10: _disconnect = disconnect_code::exception; break;
240 case 11: _disconnect = disconnect_code::broker; break;
241 case 12: _disconnect = disconnect_code::load; break;
242 default: _disconnect = disconnect_code::unknown;
243 }
244 } else if (_data.find("friends") != _data.end())
245 {
246 _type = type::friends;
247
248 new(&_friends) std::set<user_id>(_data.at("friends").begin(), _data.at("friends").end());
249 } else if (_data.find("direct_message") != _data.end())
250 {
251 _type = type::direct;
252
253 new(&_direct_message) direct_message(_data.at("direct_message").dump());
254 } else {
255 _type = type::unknown;
256 }
257 }
258
259 notification::notification(const notification& other)
260 {
261 _type = other._type;
262
263 switch (_type)
264 {
265 case type::tweet:
266 {
267 new(&_tweet) tweet(other._tweet);
268
269 break;
270 }
271
272 case type::update_user:
273 case type::block:
274 case type::unblock:
275 case type::follow:
276 case type::followed:
277 case type::unfollow:
278 {
279 new(&_user) user(other._user);
280
281 break;
282 }
283
284 case type::favorite:
285 case type::favorited:
286 case type::unfavorite:
287 case type::unfavorited:
288 case type::quoted:
289 {
290 new(&_user_and_tweet._user) user(other._user_and_tweet._user);
291 new(&_user_and_tweet._tweet) tweet(other._user_and_tweet._tweet);
292
293 break;
294 }
295
296 case type::list_created:
297 case type::list_destroyed:
298 case type::list_updated:
299 {
300 new(&_list) list(other._list);
301
302 break;
303 }
304
305 case type::list_add:
306 case type::list_added:
307 case type::list_remove:
308 case type::list_removed:
309 case type::list_subscribe:
310 case type::list_subscribed:
311 case type::list_unsubscribe:
312 case type::list_unsubscribed:
313 {
314 new(&_user_and_list._user) user(other._user_and_list._user);
315 new(&_user_and_list._list) list(other._user_and_list._list);
316
317 break;
318 }
319
320 case type::stall:
321 case type::follow_limit:
322 case type::unknown_warning:
323 {
324 new(&_warning) std::string(other._warning);
325
326 break;
327 }
328
329 case type::deletion:
330 case type::scrub_location:
331 {
332 _user_id_and_tweet_id._user_id = other._user_id_and_tweet_id._user_id;
333 _user_id_and_tweet_id._tweet_id = other._user_id_and_tweet_id._tweet_id;
334
335 break;
336 }
337
338 case type::limit:
339 {
340 _limit = other._limit;
341
342 break;
343 }
344
345 case type::withhold_status:
346 {
347 _withhold_status._user_id = other._withhold_status._user_id;
348 _withhold_status._tweet_id = other._withhold_status._tweet_id;
349 new(&_withhold_status._countries) std::vector<std::string>(other._withhold_status._countries);
350
351 break;
352 }
353
354 case type::withhold_user:
355 {
356 _withhold_user._user_id = other._withhold_user._user_id;
357 new(&_withhold_user._countries) std::vector<std::string>(other._withhold_user._countries);
358
359 break;
360 }
361
362 case type::disconnect:
363 {
364 _disconnect = other._disconnect;
365
366 break;
367 }
368
369 case type::friends:
370 {
371 new(&_friends) std::set<user_id>(other._friends);
372
373 break;
374 }
375
376 case type::direct:
377 {
378 new(&_direct_message) direct_message(other._direct_message);
379
380 break;
381 }
382 }
383 }
384
385 notification& notification::operator=(const notification& other)
386 {
387 this->~notification();
388
389 _type = other._type;
390
391 switch (_type)
392 {
393 case type::tweet:
394 {
395 new(&_tweet) tweet(other._tweet);
396
397 break;
398 }
399
400 case type::update_user:
401 case type::block:
402 case type::unblock:
403 case type::follow:
404 case type::followed:
405 case type::unfollow:
406 {
407 new(&_user) user(other._user);
408
409 break;
410 }
411
412 case type::favorite:
413 case type::favorited:
414 case type::unfavorite:
415 case type::unfavorited:
416 case type::quoted:
417 {
418 new(&_user_and_tweet._user) user(other._user_and_tweet._user);
419 new(&_user_and_tweet._tweet) tweet(other._user_and_tweet._tweet);
420
421 break;
422 }
423
424 case type::list_created:
425 case type::list_destroyed:
426 case type::list_updated:
427 {
428 new(&_list) list(other._list);
429
430 break;
431 }
432
433 case type::list_add:
434 case type::list_added:
435 case type::list_remove:
436 case type::list_removed:
437 case type::list_subscribe:
438 case type::list_subscribed:
439 case type::list_unsubscribe:
440 case type::list_unsubscribed:
441 {
442 new(&_user_and_list._user) user(other._user_and_list._user);
443 new(&_user_and_list._list) list(other._user_and_list._list);
444
445 break;
446 }
447
448 case type::stall:
449 case type::follow_limit:
450 case type::unknown_warning:
451 {
452 new(&_warning) std::string(other._warning);
453
454 break;
455 }
456
457 case type::deletion:
458 case type::scrub_location:
459 {
460 _user_id_and_tweet_id._user_id = other._user_id_and_tweet_id._user_id;
461 _user_id_and_tweet_id._tweet_id = other._user_id_and_tweet_id._tweet_id;
462
463 break;
464 }
465
466 case type::limit:
467 {
468 _limit = other._limit;
469
470 break;
471 }
472
473 case type::withhold_status:
474 {
475 _withhold_status._user_id = other._withhold_status._user_id;
476 _withhold_status._tweet_id = other._withhold_status._tweet_id;
477 new(&_withhold_status._countries) std::vector<std::string>(other._withhold_status._countries);
478
479 break;
480 }
481
482 case type::withhold_user:
483 {
484 _withhold_user._user_id = other._withhold_user._user_id;
485 new(&_withhold_user._countries) std::vector<std::string>(other._withhold_user._countries);
486
487 break;
488 }
489
490 case type::disconnect:
491 {
492 _disconnect = other._disconnect;
493
494 break;
495 }
496
497 case type::friends:
498 {
499 new(&_friends) std::set<user_id>(other._friends);
500
501 break;
502 }
503
504 case type::direct:
505 {
506 new(&_direct_message) direct_message(other._direct_message);
507
508 break;
509 }
510 }
511
512 return *this;
513 }
514
515 notification::~notification()
516 {
517 switch (_type)
518 {
519 case type::tweet:
520 {
521 _tweet.~tweet();
522
523 break;
524 }
525
526 case type::update_user:
527 case type::block:
528 case type::unblock:
529 case type::follow:
530 case type::followed:
531 case type::unfollow:
532 {
533 _user.~user();
534
535 break;
536 }
537
538 case type::favorite:
539 case type::favorited:
540 case type::unfavorite:
541 case type::unfavorited:
542 case type::quoted:
543 {
544 _user_and_tweet._user.~user();
545 _user_and_tweet._tweet.~tweet();
546
547 break;
548 }
549
550 case type::list_created:
551 case type::list_destroyed:
552 case type::list_updated:
553 {
554 _list.~list();
555
556 break;
557 }
558
559 case type::list_add:
560 case type::list_added:
561 case type::list_remove:
562 case type::list_removed:
563 case type::list_subscribe:
564 case type::list_subscribed:
565 case type::list_unsubscribe:
566 case type::list_unsubscribed:
567 {
568 _user_and_list._user.~user();
569 _user_and_list._list.~list();
570
571 break;
572 }
573
574 case type::stall:
575 case type::follow_limit:
576 {
577 using string_type = std::string;
578 _warning.~string_type();
579
580 break;
581 }
582
583 case type::withhold_status:
584 {
585 using list_type = std::vector<std::string>;
586 _withhold_status._countries.~list_type();
587
588 break;
589 }
590
591 case type::withhold_user:
592 {
593 using list_type = std::vector<std::string>;
594 _withhold_user._countries.~list_type();
595
596 break;
597 }
598
599 case type::friends:
600 {
601 using list_type = std::set<user_id>;
602 _friends.~list_type();
603
604 break;
605 }
606
607 case type::direct:
608 {
609 _direct_message.~direct_message();
610
611 break;
612 }
613 }
614 }
615
616 tweet notification::getTweet() const
617 {
618 switch (_type)
619 {
620 case type::tweet:
621 {
622 return _tweet;
623 }
624
625 case type::favorite:
626 case type::favorited:
627 case type::unfavorite:
628 case type::unfavorited:
629 case type::quoted:
630 {
631 return _user_and_tweet._tweet;
632 }
633
634 default:
635 {
636 assert(false);
637
638 return tweet();
639 }
640 }
641 }
642
643 user notification::getUser() const
644 {
645 switch (_type)
646 {
647 case type::update_user:
648 case type::block:
649 case type::unblock:
650 case type::follow:
651 case type::followed:
652 case type::unfollow:
653 {
654 return _user;
655 }
656
657 case type::favorite:
658 case type::favorited:
659 case type::unfavorite:
660 case type::unfavorited:
661 case type::quoted:
662 {
663 return _user_and_tweet._user;
664 }
665
666 case type::list_add:
667 case type::list_added:
668 case type::list_remove:
669 case type::list_removed:
670 case type::list_subscribe:
671 case type::list_subscribed:
672 case type::list_unsubscribe:
673 case type::list_unsubscribed:
674 {
675 return _user_and_list._user;
676 }
677
678 default:
679 {
680 assert(false);
681
682 return user();
683 }
684 }
685 }
686
687 list notification::getList() const
688 {
689 switch (_type)
690 {
691 case type::list_created:
692 case type::list_destroyed:
693 case type::list_updated:
694 {
695 return _list;
696 }
697
698 case type::list_add:
699 case type::list_added:
700 case type::list_remove:
701 case type::list_removed:
702 case type::list_subscribe:
703 case type::list_subscribed:
704 case type::list_unsubscribe:
705 case type::list_unsubscribed:
706 {
707 return _user_and_list._list;
708 }
709
710 default:
711 {
712 assert(false);
713
714 return list();
715 }
716 }
717 }
718
719 tweet_id notification::getTweetID() const
720 {
721 switch (_type)
722 {
723 case type::deletion:
724 case type::scrub_location:
725 {
726 return _user_id_and_tweet_id._tweet_id;
727 }
728
729 case type::withhold_status:
730 {
731 return _withhold_status._tweet_id;
732 }
733
734 default:
735 {
736 assert(false);
737
738 return 0;
739 }
740 }
741 }
742
743 user_id notification::getUserID() const
744 {
745 switch (_type)
746 {
747 case type::deletion:
748 case type::scrub_location:
749 {
750 return _user_id_and_tweet_id._user_id;
751 }
752
753 case type::withhold_status:
754 {
755 return _withhold_status._user_id;
756 }
757
758 case type::withhold_user:
759 {
760 return _withhold_user._user_id;
761 }
762
763 default:
764 {
765 assert(false);
766
767 return 0;
768 }
769 }
770 }
771
772 std::vector<std::string> notification::getCountries() const
773 {
774 switch (_type)
775 {
776 case type::withhold_status:
777 {
778 return _withhold_status._countries;
779 }
780
781 case type::withhold_user:
782 {
783 return _withhold_user._countries;
784 }
785
786 default:
787 {
788 assert(false);
789
790 return std::vector<std::string>();
791 }
792 }
793 }
794
795 disconnect_code notification::getDisconnectCode() const
796 {
797 assert(_type == type::disconnect);
798
799 return _disconnect;
800 }
801
802 std::set<user_id> notification::getFriends() const
803 {
804 assert(_type == type::friends);
805
806 return _friends;
807 }
808
809 direct_message notification::getDirectMessage() const
810 {
811 assert(_type == type::direct);
812
813 return _direct_message;
814 }
815
816 int notification::getLimit() const
817 {
818 assert(_type == type::limit);
819
820 return _limit;
821 }
822
823 std::string notification::getWarning() const
824 {
825 switch (_type)
826 {
827 case type::stall:
828 case type::follow_limit:
829 case type::unknown_warning:
830 {
831 return _warning;
832 }
833
834 default:
835 {
836 assert(false);
837
838 return "";
839 }
840 }
841 }
842
843 notification::operator bool() const
844 {
845 return _type != type::invalid;
846 }
847
848};