about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKelly Rauchenberger <fefferburbia@gmail.com>2016-11-29 16:18:25 -0500
committerKelly Rauchenberger <fefferburbia@gmail.com>2016-11-29 16:18:25 -0500
commit7c44fd17bb6be54a2ea4b60761e91053ca988977 (patch)
tree42f08e0db610617fd0629b117610bfa1a365acaf
parentd90a1e74c77ba67f25a812609fd49d479bc464dd (diff)
downloadlibtwittercpp-7c44fd17bb6be54a2ea4b60761e91053ca988977.tar.gz
libtwittercpp-7c44fd17bb6be54a2ea4b60761e91053ca988977.tar.bz2
libtwittercpp-7c44fd17bb6be54a2ea4b60761e91053ca988977.zip
Made tweets, users, and notifications into copyable objects
Notifications are now also mutable. Users and tweets no longer have helper methods for interacting with the client. Fixed a bug (possibly introduced by a change to the Twitter API) that caused non-reply tweets to be marked as unknown notifications.
-rw-r--r--src/client.cpp36
-rw-r--r--src/client.h10
-rw-r--r--src/direct_message.h1
-rw-r--r--src/list.h2
-rw-r--r--src/notification.cpp518
-rw-r--r--src/notification.h52
-rw-r--r--src/stream.cpp2
-rw-r--r--src/stream.h2
-rw-r--r--src/tweet.cpp65
-rw-r--r--src/tweet.h32
-rw-r--r--src/user.cpp24
-rw-r--r--src/user.h17
12 files changed, 610 insertions, 151 deletions
diff --git a/src/client.cpp b/src/client.cpp index f8908fd..e16e30b 100644 --- a/src/client.cpp +++ b/src/client.cpp
@@ -330,7 +330,7 @@ namespace twitter {
330 _oauth_token.get()); 330 _oauth_token.get());
331 331
332 _current_user = 332 _current_user =
333 make_unique<user>(*this, 333 make_unique<user>(
334 get(*_oauth_client, 334 get(*_oauth_client,
335 "https://api.twitter.com/1.1/account/verify_credentials.json") 335 "https://api.twitter.com/1.1/account/verify_credentials.json")
336 .perform()); 336 .perform());
@@ -349,7 +349,7 @@ namespace twitter {
349 datastrstream << twitter::implode(std::begin(media_ids), std::end(media_ids), ","); 349 datastrstream << twitter::implode(std::begin(media_ids), std::end(media_ids), ",");
350 } 350 }
351 351
352 return tweet(*this, 352 return tweet(
353 post(*_oauth_client, 353 post(*_oauth_client,
354 "https://api.twitter.com/1.1/statuses/update.json", 354 "https://api.twitter.com/1.1/statuses/update.json",
355 datastrstream.str()) 355 datastrstream.str())
@@ -369,7 +369,7 @@ namespace twitter {
369 datastrstream << twitter::implode(std::begin(media_ids), std::end(media_ids), ","); 369 datastrstream << twitter::implode(std::begin(media_ids), std::end(media_ids), ",");
370 } 370 }
371 371
372 return tweet(*this, 372 return tweet(
373 post(*_oauth_client, 373 post(*_oauth_client,
374 "https://api.twitter.com/1.1/statuses/update.json", 374 "https://api.twitter.com/1.1/statuses/update.json",
375 datastrstream.str()) 375 datastrstream.str())
@@ -533,6 +533,16 @@ namespace twitter {
533 return result; 533 return result;
534 } 534 }
535 535
536 std::set<user_id> client::getFriends(const user& id) const
537 {
538 return getFriends(id.getID());
539 }
540
541 std::set<user_id> client::getFriends() const
542 {
543 return getFriends(getUser().getID());
544 }
545
536 std::set<user_id> client::getFollowers(user_id id) const 546 std::set<user_id> client::getFollowers(user_id id) const
537 { 547 {
538 long long cursor = -1; 548 long long cursor = -1;
@@ -567,6 +577,16 @@ namespace twitter {
567 return result; 577 return result;
568 } 578 }
569 579
580 std::set<user_id> client::getFollowers(const user& id) const
581 {
582 return getFollowers(id.getID());
583 }
584
585 std::set<user_id> client::getFollowers() const
586 {
587 return getFollowers(getUser().getID());
588 }
589
570 void client::follow(user_id toFollow) const 590 void client::follow(user_id toFollow) const
571 { 591 {
572 std::stringstream datastrstream; 592 std::stringstream datastrstream;
@@ -576,6 +596,11 @@ namespace twitter {
576 post(*_oauth_client, "https://api.twitter.com/1.1/friendships/create.json", datastrstream.str()).perform(); 596 post(*_oauth_client, "https://api.twitter.com/1.1/friendships/create.json", datastrstream.str()).perform();
577 } 597 }
578 598
599 void client::follow(const user& toFollow) const
600 {
601 return follow(toFollow.getID());
602 }
603
579 void client::unfollow(user_id toUnfollow) const 604 void client::unfollow(user_id toUnfollow) const
580 { 605 {
581 std::stringstream datastrstream; 606 std::stringstream datastrstream;
@@ -584,6 +609,11 @@ namespace twitter {
584 609
585 post(*_oauth_client, "https://api.twitter.com/1.1/friendships/destroy.json", datastrstream.str()).perform(); 610 post(*_oauth_client, "https://api.twitter.com/1.1/friendships/destroy.json", datastrstream.str()).perform();
586 } 611 }
612
613 void client::unfollow(const user& toUnfollow) const
614 {
615 return unfollow(toUnfollow.getID());
616 }
587 617
588 const user& client::getUser() const 618 const user& client::getUser() const
589 { 619 {
diff --git a/src/client.h b/src/client.h index 37081ff..2230dbb 100644 --- a/src/client.h +++ b/src/client.h
@@ -29,10 +29,20 @@ namespace twitter {
29 long uploadMedia(std::string media_type, const char* data, long data_length) const; 29 long uploadMedia(std::string media_type, const char* data, long data_length) const;
30 30
31 tweet replyToTweet(std::string msg, tweet_id in_response_to, std::list<long> media_ids = {}) const; 31 tweet replyToTweet(std::string msg, tweet_id in_response_to, std::list<long> media_ids = {}) const;
32
32 std::set<user_id> getFriends(user_id id) const; 33 std::set<user_id> getFriends(user_id id) const;
34 std::set<user_id> getFriends(const user& u) const;
35 std::set<user_id> getFriends() const;
36
33 std::set<user_id> getFollowers(user_id id) const; 37 std::set<user_id> getFollowers(user_id id) const;
38 std::set<user_id> getFollowers(const user& u) const;
39 std::set<user_id> getFollowers() const;
40
34 void follow(user_id toFollow) const; 41 void follow(user_id toFollow) const;
42 void follow(const user& toFollow) const;
43
35 void unfollow(user_id toUnfollow) const; 44 void unfollow(user_id toUnfollow) const;
45 void unfollow(const user& toUnfollow) const;
36 46
37 const user& getUser() const; 47 const user& getUser() const;
38 48
diff --git a/src/direct_message.h b/src/direct_message.h index 12e254c..46a66dc 100644 --- a/src/direct_message.h +++ b/src/direct_message.h
@@ -8,6 +8,7 @@ namespace twitter {
8 class direct_message { 8 class direct_message {
9 public: 9 public:
10 10
11 direct_message() {}
11 explicit direct_message(std::string data); 12 explicit direct_message(std::string data);
12 }; 13 };
13 14
diff --git a/src/list.h b/src/list.h index 69085b4..1bf034f 100644 --- a/src/list.h +++ b/src/list.h
@@ -8,7 +8,9 @@ namespace twitter {
8 class list { 8 class list {
9 public: 9 public:
10 10
11 list() {}
11 explicit list(std::string data); 12 explicit list(std::string data);
13
12 }; 14 };
13 15
14}; 16};
diff --git a/src/notification.cpp b/src/notification.cpp index 3269a90..0e46112 100644 --- a/src/notification.cpp +++ b/src/notification.cpp
@@ -28,16 +28,11 @@ namespace twitter {
28 28
29 try 29 try
30 { 30 {
31 if (!json["in_reply_to_status_id"].is_null()) 31 if (!json["event"].is_null())
32 {
33 _type = type::tweet;
34
35 new(&_tweet) tweet(tclient, data);
36 } else if (!json["event"].is_null())
37 { 32 {
38 std::string event = json["event"]; 33 std::string event = json["event"];
39 user source(tclient, json["source"].dump()); 34 user source(json["source"].dump());
40 user target(tclient, json["target"].dump()); 35 user target(json["target"].dump());
41 36
42 if (event == "user_update") 37 if (event == "user_update")
43 { 38 {
@@ -56,7 +51,7 @@ namespace twitter {
56 new(&_user) user(target); 51 new(&_user) user(target);
57 } else if (event == "favorite") 52 } else if (event == "favorite")
58 { 53 {
59 new(&_user_and_tweet._tweet) tweet(tclient, json["target_object"].dump()); 54 new(&_user_and_tweet._tweet) tweet(json["target_object"].dump());
60 55
61 if (current_user == source) 56 if (current_user == source)
62 { 57 {
@@ -70,7 +65,7 @@ namespace twitter {
70 } 65 }
71 } else if (event == "unfavorite") 66 } else if (event == "unfavorite")
72 { 67 {
73 new(&_user_and_tweet._tweet) tweet(tclient, json["target_object"].dump()); 68 new(&_user_and_tweet._tweet) tweet(json["target_object"].dump());
74 69
75 if (current_user == source) 70 if (current_user == source)
76 { 71 {
@@ -175,7 +170,9 @@ namespace twitter {
175 _type = type::quoted; 170 _type = type::quoted;
176 171
177 new(&_user_and_tweet._user) user(source); 172 new(&_user_and_tweet._user) user(source);
178 new(&_user_and_tweet._tweet) tweet(tclient, json["target_object"].dump()); 173 new(&_user_and_tweet._tweet) tweet(json["target_object"].dump());
174 } else {
175 _type = type::unknown;
179 } 176 }
180 } else if (!json["warning"].is_null()) 177 } else if (!json["warning"].is_null())
181 { 178 {
@@ -260,7 +257,9 @@ namespace twitter {
260 257
261 new(&_direct_message) direct_message(json["direct_message"].dump()); 258 new(&_direct_message) direct_message(json["direct_message"].dump());
262 } else { 259 } else {
263 _type = type::unknown; 260 _type = type::tweet;
261
262 new(&_tweet) tweet(data);
264 } 263 }
265 } catch (const std::domain_error& error) 264 } catch (const std::domain_error& error)
266 { 265 {
@@ -268,7 +267,7 @@ namespace twitter {
268 } 267 }
269 } 268 }
270 269
271 notification::notification(notification&& other) 270 notification::notification(const notification& other)
272 { 271 {
273 _type = other._type; 272 _type = other._type;
274 273
@@ -276,7 +275,7 @@ namespace twitter {
276 { 275 {
277 case type::tweet: 276 case type::tweet:
278 { 277 {
279 new(&_tweet) tweet(std::move(other._tweet)); 278 new(&_tweet) tweet(other._tweet);
280 279
281 break; 280 break;
282 } 281 }
@@ -288,7 +287,7 @@ namespace twitter {
288 case type::followed: 287 case type::followed:
289 case type::unfollow: 288 case type::unfollow:
290 { 289 {
291 new(&_user) user(std::move(other._user)); 290 new(&_user) user(other._user);
292 291
293 break; 292 break;
294 } 293 }
@@ -299,8 +298,8 @@ namespace twitter {
299 case type::unfavorited: 298 case type::unfavorited:
300 case type::quoted: 299 case type::quoted:
301 { 300 {
302 new(&_user_and_tweet._user) user(std::move(other._user_and_tweet._user)); 301 new(&_user_and_tweet._user) user(other._user_and_tweet._user);
303 new(&_user_and_tweet._tweet) tweet(std::move(other._user_and_tweet._tweet)); 302 new(&_user_and_tweet._tweet) tweet(other._user_and_tweet._tweet);
304 303
305 break; 304 break;
306 } 305 }
@@ -309,7 +308,7 @@ namespace twitter {
309 case type::list_destroyed: 308 case type::list_destroyed:
310 case type::list_updated: 309 case type::list_updated:
311 { 310 {
312 new(&_list) list(std::move(other._list)); 311 new(&_list) list(other._list);
313 312
314 break; 313 break;
315 } 314 }
@@ -323,8 +322,8 @@ namespace twitter {
323 case type::list_unsubscribe: 322 case type::list_unsubscribe:
324 case type::list_unsubscribed: 323 case type::list_unsubscribed:
325 { 324 {
326 new(&_user_and_list._user) user(std::move(other._user_and_list._user)); 325 new(&_user_and_list._user) user(other._user_and_list._user);
327 new(&_user_and_list._list) list(std::move(other._user_and_list._list)); 326 new(&_user_and_list._list) list(other._user_and_list._list);
328 327
329 break; 328 break;
330 } 329 }
@@ -333,7 +332,7 @@ namespace twitter {
333 case type::follow_limit: 332 case type::follow_limit:
334 case type::unknown_warning: 333 case type::unknown_warning:
335 { 334 {
336 new(&_warning) std::string(std::move(other._warning)); 335 new(&_warning) std::string(other._warning);
337 336
338 break; 337 break;
339 } 338 }
@@ -358,7 +357,7 @@ namespace twitter {
358 { 357 {
359 _withhold_status._user_id = other._withhold_status._user_id; 358 _withhold_status._user_id = other._withhold_status._user_id;
360 _withhold_status._tweet_id = other._withhold_status._tweet_id; 359 _withhold_status._tweet_id = other._withhold_status._tweet_id;
361 new(&_withhold_status._countries) std::vector<std::string>(std::move(other._withhold_status._countries)); 360 new(&_withhold_status._countries) std::vector<std::string>(other._withhold_status._countries);
362 361
363 break; 362 break;
364 } 363 }
@@ -366,7 +365,7 @@ namespace twitter {
366 case type::withhold_user: 365 case type::withhold_user:
367 { 366 {
368 _withhold_user._user_id = other._withhold_user._user_id; 367 _withhold_user._user_id = other._withhold_user._user_id;
369 new(&_withhold_user._countries) std::vector<std::string>(std::move(other._withhold_user._countries)); 368 new(&_withhold_user._countries) std::vector<std::string>(other._withhold_user._countries);
370 369
371 break; 370 break;
372 } 371 }
@@ -380,14 +379,14 @@ namespace twitter {
380 379
381 case type::friends: 380 case type::friends:
382 { 381 {
383 new(&_friends) std::set<user_id>(std::move(other._friends)); 382 new(&_friends) std::set<user_id>(other._friends);
384 383
385 break; 384 break;
386 } 385 }
387 386
388 case type::direct: 387 case type::direct:
389 { 388 {
390 new(&_direct_message) direct_message(std::move(other._direct_message)); 389 new(&_direct_message) direct_message(other._direct_message);
391 390
392 break; 391 break;
393 } 392 }
@@ -400,17 +399,25 @@ namespace twitter {
400 } 399 }
401 } 400 }
402 401
403 notification& notification::operator=(notification&& other) 402 notification::notification(notification&& other) : notification()
404 { 403 {
405 this->~notification(); 404 swap(*this, other);
406 405 }
407 _type = other._type; 406
407 notification& notification::operator=(notification other)
408 {
409 swap(*this, other);
408 410
411 return *this;
412 }
413
414 notification::~notification()
415 {
409 switch (_type) 416 switch (_type)
410 { 417 {
411 case type::tweet: 418 case type::tweet:
412 { 419 {
413 new(&_tweet) tweet(std::move(other._tweet)); 420 _tweet.~tweet();
414 421
415 break; 422 break;
416 } 423 }
@@ -422,7 +429,7 @@ namespace twitter {
422 case type::followed: 429 case type::followed:
423 case type::unfollow: 430 case type::unfollow:
424 { 431 {
425 new(&_user) user(std::move(other._user)); 432 _user.~user();
426 433
427 break; 434 break;
428 } 435 }
@@ -433,8 +440,8 @@ namespace twitter {
433 case type::unfavorited: 440 case type::unfavorited:
434 case type::quoted: 441 case type::quoted:
435 { 442 {
436 new(&_user_and_tweet._user) user(std::move(other._user_and_tweet._user)); 443 _user_and_tweet._user.~user();
437 new(&_user_and_tweet._tweet) tweet(std::move(other._user_and_tweet._tweet)); 444 _user_and_tweet._tweet.~tweet();
438 445
439 break; 446 break;
440 } 447 }
@@ -443,7 +450,7 @@ namespace twitter {
443 case type::list_destroyed: 450 case type::list_destroyed:
444 case type::list_updated: 451 case type::list_updated:
445 { 452 {
446 new(&_list) list(std::move(other._list)); 453 _list.~list();
447 454
448 break; 455 break;
449 } 456 }
@@ -457,8 +464,8 @@ namespace twitter {
457 case type::list_unsubscribe: 464 case type::list_unsubscribe:
458 case type::list_unsubscribed: 465 case type::list_unsubscribed:
459 { 466 {
460 new(&_user_and_list._user) user(std::move(other._user_and_list._user)); 467 _user_and_list._user.~user();
461 new(&_user_and_list._list) list(std::move(other._user_and_list._list)); 468 _user_and_list._list.~list();
462 469
463 break; 470 break;
464 } 471 }
@@ -467,65 +474,192 @@ namespace twitter {
467 case type::follow_limit: 474 case type::follow_limit:
468 case type::unknown_warning: 475 case type::unknown_warning:
469 { 476 {
470 new(&_warning) std::string(std::move(other._warning)); 477 using string_type = std::string;
478 _warning.~string_type();
471 479
472 break; 480 break;
473 } 481 }
474 482
475 case type::deletion: 483 case type::withhold_status:
476 case type::scrub_location:
477 { 484 {
478 _user_id_and_tweet_id._user_id = other._user_id_and_tweet_id._user_id; 485 using list_type = std::vector<std::string>;
479 _user_id_and_tweet_id._tweet_id = other._user_id_and_tweet_id._tweet_id; 486 _withhold_status._countries.~list_type();
480 487
481 break; 488 break;
482 } 489 }
483 490
484 case type::limit: 491 case type::withhold_user:
485 { 492 {
486 _limit = other._limit; 493 using list_type = std::vector<std::string>;
494 _withhold_user._countries.~list_type();
487 495
488 break; 496 break;
489 } 497 }
490 498
491 case type::withhold_status: 499 case type::friends:
492 { 500 {
493 _withhold_status._user_id = other._withhold_status._user_id; 501 using list_type = std::set<user_id>;
494 _withhold_status._tweet_id = other._withhold_status._tweet_id; 502 _friends.~list_type();
495 new(&_withhold_status._countries) std::vector<std::string>(std::move(other._withhold_status._countries));
496 503
497 break; 504 break;
498 } 505 }
499 506
500 case type::withhold_user: 507 case type::direct:
501 { 508 {
502 _withhold_user._user_id = other._withhold_user._user_id; 509 _direct_message.~direct_message();
503 new(&_withhold_user._countries) std::vector<std::string>(std::move(other._withhold_user._countries));
504 510
505 break; 511 break;
506 } 512 }
507 513
514 case type::deletion:
515 case type::scrub_location:
516 case type::limit:
508 case type::disconnect: 517 case type::disconnect:
518 case type::unknown:
519 case type::invalid:
509 { 520 {
510 _disconnect = other._disconnect; 521 break;
522 }
523 }
524 }
525
526 void swap(notification& first, notification& second)
527 {
528 using type = notification::type;
529
530 type tempType = first._type;
531 tweet tempTweet;
532 user tempUser;
533 list tempList;
534 std::string tempWarning;
535 user_id tempUserId;
536 tweet_id tempTweetId;
537 int tempLimit;
538 std::vector<std::string> tempCountries;
539 disconnect_code tempDisconnectCode;
540 std::set<user_id> tempFriends;
541 direct_message tempDirectMessage;
542
543 switch (first._type)
544 {
545 case type::tweet:
546 {
547 tempTweet = std::move(first._tweet);
511 548
512 break; 549 break;
513 } 550 }
514 551
515 case type::friends: 552 case type::update_user:
553 case type::block:
554 case type::unblock:
555 case type::follow:
556 case type::followed:
557 case type::unfollow:
516 { 558 {
517 new(&_friends) std::set<user_id>(std::move(other._friends)); 559 tempUser = std::move(first._user);
518 560
519 break; 561 break;
520 } 562 }
563
564 case type::favorite:
565 case type::favorited:
566 case type::unfavorite:
567 case type::unfavorited:
568 case type::quoted:
569 {
570 tempTweet = std::move(first._user_and_tweet._tweet);
571 tempUser = std::move(first._user_and_tweet._user);
521 572
522 case type::direct: 573 break;
574 }
575
576 case type::list_created:
577 case type::list_destroyed:
578 case type::list_updated:
523 { 579 {
524 new(&_direct_message) direct_message(std::move(other._direct_message)); 580 tempList = std::move(first._list);
525 581
582 break;
583 }
584
585 case type::list_add:
586 case type::list_added:
587 case type::list_remove:
588 case type::list_removed:
589 case type::list_subscribe:
590 case type::list_subscribed:
591 case type::list_unsubscribe:
592 case type::list_unsubscribed:
593 {
594 tempList = std::move(first._user_and_list._list);
595 tempUser = std::move(first._user_and_list._user);
596
597 break;
598 }
599
600 case type::stall:
601 case type::follow_limit:
602 case type::unknown_warning:
603 {
604 tempWarning = std::move(first._warning);
605
526 break; 606 break;
527 } 607 }
608
609 case type::deletion:
610 case type::scrub_location:
611 {
612 tempUserId = first._user_id_and_tweet_id._user_id;
613 tempTweetId = first._user_id_and_tweet_id._tweet_id;
614
615 break;
616 }
617
618 case type::limit:
619 {
620 tempLimit = first._limit;
528 621
622 break;
623 }
624
625 case type::withhold_status:
626 {
627 tempUserId = first._withhold_status._user_id;
628 tempTweetId = first._withhold_status._tweet_id;
629 tempCountries = std::move(first._withhold_status._countries);
630
631 break;
632 }
633
634 case type::withhold_user:
635 {
636 tempUserId = first._withhold_user._user_id;
637 tempCountries = std::move(first._withhold_user._countries);
638
639 break;
640 }
641
642 case type::disconnect:
643 {
644 tempDisconnectCode = first._disconnect;
645
646 break;
647 }
648
649 case type::friends:
650 {
651 tempFriends = std::move(first._friends);
652
653 break;
654 }
655
656 case type::direct:
657 {
658 tempDirectMessage = std::move(first._direct_message);
659
660 break;
661 }
662
529 case type::invalid: 663 case type::invalid:
530 case type::unknown: 664 case type::unknown:
531 { 665 {
@@ -533,16 +667,19 @@ namespace twitter {
533 } 667 }
534 } 668 }
535 669
536 return *this; 670 first.~notification();
537 } 671
538 672 first._type = second._type;
539 notification::~notification() 673
540 { 674 // Okay now you need to initialize the first with the data from the second
541 switch (_type) 675 // And then destruct the second and initialize it with the data stored in temp
676 // This is hell
677
678 switch (second._type)
542 { 679 {
543 case type::tweet: 680 case type::tweet:
544 { 681 {
545 _tweet.~tweet(); 682 new(&first._tweet) tweet(std::move(second._tweet));
546 683
547 break; 684 break;
548 } 685 }
@@ -554,7 +691,7 @@ namespace twitter {
554 case type::followed: 691 case type::followed:
555 case type::unfollow: 692 case type::unfollow:
556 { 693 {
557 _user.~user(); 694 new(&first._user) user(std::move(second._user));
558 695
559 break; 696 break;
560 } 697 }
@@ -565,8 +702,8 @@ namespace twitter {
565 case type::unfavorited: 702 case type::unfavorited:
566 case type::quoted: 703 case type::quoted:
567 { 704 {
568 _user_and_tweet._user.~user(); 705 new(&first._user_and_tweet._user) user(std::move(second._user_and_tweet._user));
569 _user_and_tweet._tweet.~tweet(); 706 new(&first._user_and_tweet._tweet) tweet(std::move(second._user_and_tweet._tweet));
570 707
571 break; 708 break;
572 } 709 }
@@ -575,7 +712,7 @@ namespace twitter {
575 case type::list_destroyed: 712 case type::list_destroyed:
576 case type::list_updated: 713 case type::list_updated:
577 { 714 {
578 _list.~list(); 715 new(&first._list) list(std::move(second._list));
579 716
580 break; 717 break;
581 } 718 }
@@ -589,8 +726,8 @@ namespace twitter {
589 case type::list_unsubscribe: 726 case type::list_unsubscribe:
590 case type::list_unsubscribed: 727 case type::list_unsubscribed:
591 { 728 {
592 _user_and_list._user.~user(); 729 new(&first._user_and_list._user) user(std::move(second._user_and_list._user));
593 _user_and_list._list.~list(); 730 new(&first._user_and_list._list) list(std::move(second._user_and_list._list));
594 731
595 break; 732 break;
596 } 733 }
@@ -599,49 +736,199 @@ namespace twitter {
599 case type::follow_limit: 736 case type::follow_limit:
600 case type::unknown_warning: 737 case type::unknown_warning:
601 { 738 {
602 using string_type = std::string; 739 new(&first._warning) std::string(std::move(second._warning));
603 _warning.~string_type(); 740
741 break;
742 }
743
744 case type::deletion:
745 case type::scrub_location:
746 {
747 first._user_id_and_tweet_id._user_id = second._user_id_and_tweet_id._user_id;
748 first._user_id_and_tweet_id._tweet_id = second._user_id_and_tweet_id._tweet_id;
749
750 break;
751 }
752
753 case type::limit:
754 {
755 first._limit = second._limit;
604 756
605 break; 757 break;
606 } 758 }
607 759
608 case type::withhold_status: 760 case type::withhold_status:
609 { 761 {
610 using list_type = std::vector<std::string>; 762 first._withhold_status._user_id = second._withhold_status._user_id;
611 _withhold_status._countries.~list_type(); 763 first._withhold_status._tweet_id = second._withhold_status._tweet_id;
612 764 new(&first._withhold_status._countries) std::vector<std::string>(std::move(second._withhold_status._countries));
765
613 break; 766 break;
614 } 767 }
615 768
616 case type::withhold_user: 769 case type::withhold_user:
617 { 770 {
618 using list_type = std::vector<std::string>; 771 first._withhold_user._user_id = second._withhold_user._user_id;
619 _withhold_user._countries.~list_type(); 772 new(&first._withhold_user._countries) std::vector<std::string>(std::move(second._withhold_user._countries));
620 773
621 break; 774 break;
622 } 775 }
623 776
777 case type::disconnect:
778 {
779 first._disconnect = second._disconnect;
780
781 break;
782 }
783
624 case type::friends: 784 case type::friends:
625 { 785 {
626 using list_type = std::set<user_id>; 786 new(&first._friends) std::set<user_id>(std::move(second._friends));
627 _friends.~list_type();
628 787
629 break; 788 break;
630 } 789 }
631 790
632 case type::direct: 791 case type::direct:
633 { 792 {
634 _direct_message.~direct_message(); 793 new(&first._direct_message) direct_message(std::move(second._direct_message));
635 794
636 break; 795 break;
637 } 796 }
638 797
798 case type::invalid:
799 case type::unknown:
800 {
801 break;
802 }
803 }
804
805 // Now destruct the second and initialize it with data from the first
806 second.~notification();
807
808 second._type = tempType;
809
810 switch (tempType)
811 {
812 case type::tweet:
813 {
814 new(&second._tweet) tweet(std::move(tempTweet));
815
816 break;
817 }
818
819 case type::update_user:
820 case type::block:
821 case type::unblock:
822 case type::follow:
823 case type::followed:
824 case type::unfollow:
825 {
826 new(&second._user) user(std::move(tempUser));
827
828 break;
829 }
830
831 case type::favorite:
832 case type::favorited:
833 case type::unfavorite:
834 case type::unfavorited:
835 case type::quoted:
836 {
837 new(&second._user_and_tweet._user) user(std::move(tempUser));
838 new(&second._user_and_tweet._tweet) tweet(std::move(tempTweet));
839
840 break;
841 }
842
843 case type::list_created:
844 case type::list_destroyed:
845 case type::list_updated:
846 {
847 new(&second._list) list(std::move(tempList));
848
849 break;
850 }
851
852 case type::list_add:
853 case type::list_added:
854 case type::list_remove:
855 case type::list_removed:
856 case type::list_subscribe:
857 case type::list_subscribed:
858 case type::list_unsubscribe:
859 case type::list_unsubscribed:
860 {
861 new(&second._user_and_list._user) user(std::move(tempUser));
862 new(&second._user_and_list._list) list(std::move(tempList));
863
864 break;
865 }
866
867 case type::stall:
868 case type::follow_limit:
869 case type::unknown_warning:
870 {
871 new(&second._warning) std::string(std::move(tempWarning));
872
873 break;
874 }
875
639 case type::deletion: 876 case type::deletion:
640 case type::scrub_location: 877 case type::scrub_location:
878 {
879 second._user_id_and_tweet_id._user_id = tempUserId;
880 second._user_id_and_tweet_id._tweet_id = tempTweetId;
881
882 break;
883 }
884
641 case type::limit: 885 case type::limit:
886 {
887 second._limit = tempLimit;
888
889 break;
890 }
891
892 case type::withhold_status:
893 {
894 second._withhold_status._user_id = tempUserId;
895 second._withhold_status._tweet_id = tempTweetId;
896 new(&second._withhold_status._countries) std::vector<std::string>(std::move(tempCountries));
897
898 break;
899 }
900
901 case type::withhold_user:
902 {
903 second._withhold_user._user_id = tempUserId;
904 new(&second._withhold_user._countries) std::vector<std::string>(std::move(tempCountries));
905
906 break;
907 }
908
642 case type::disconnect: 909 case type::disconnect:
643 case type::unknown: 910 {
911 second._disconnect = tempDisconnectCode;
912
913 break;
914 }
915
916 case type::friends:
917 {
918 new(&second._friends) std::set<user_id>(std::move(tempFriends));
919
920 break;
921 }
922
923 case type::direct:
924 {
925 new(&second._direct_message) direct_message(std::move(tempDirectMessage));
926
927 break;
928 }
929
644 case type::invalid: 930 case type::invalid:
931 case type::unknown:
645 { 932 {
646 break; 933 break;
647 } 934 }
@@ -767,6 +1054,28 @@ namespace twitter {
767 } 1054 }
768 } 1055 }
769 1056
1057 void notification::setTweetID(tweet_id _arg)
1058 {
1059 switch (_type)
1060 {
1061 case type::deletion:
1062 case type::scrub_location:
1063 {
1064 _user_id_and_tweet_id._tweet_id = _arg;;
1065 }
1066
1067 case type::withhold_status:
1068 {
1069 _withhold_status._tweet_id = _arg;
1070 }
1071
1072 default:
1073 {
1074 assert(false);
1075 }
1076 }
1077 }
1078
770 user_id notification::getUserID() const 1079 user_id notification::getUserID() const
771 { 1080 {
772 switch (_type) 1081 switch (_type)
@@ -794,6 +1103,33 @@ namespace twitter {
794 } 1103 }
795 } 1104 }
796 1105
1106 void notification::setUserID(user_id _arg)
1107 {
1108 switch (_type)
1109 {
1110 case type::deletion:
1111 case type::scrub_location:
1112 {
1113 _user_id_and_tweet_id._user_id = _arg;
1114 }
1115
1116 case type::withhold_status:
1117 {
1118 _withhold_status._user_id = _arg;
1119 }
1120
1121 case type::withhold_user:
1122 {
1123 _withhold_user._user_id = _arg;
1124 }
1125
1126 default:
1127 {
1128 assert(false);
1129 }
1130 }
1131 }
1132
797 const std::vector<std::string>& notification::getCountries() const 1133 const std::vector<std::string>& notification::getCountries() const
798 { 1134 {
799 switch (_type) 1135 switch (_type)
@@ -822,6 +1158,13 @@ namespace twitter {
822 return _disconnect; 1158 return _disconnect;
823 } 1159 }
824 1160
1161 void notification::setDisconnectCode(disconnect_code _arg)
1162 {
1163 assert(_type == type::disconnect);
1164
1165 _disconnect = _arg;
1166 }
1167
825 const std::set<user_id>& notification::getFriends() const 1168 const std::set<user_id>& notification::getFriends() const
826 { 1169 {
827 assert(_type == type::friends); 1170 assert(_type == type::friends);
@@ -843,6 +1186,13 @@ namespace twitter {
843 return _limit; 1186 return _limit;
844 } 1187 }
845 1188
1189 void notification::setLimit(int _arg)
1190 {
1191 assert(_type == type::limit);
1192
1193 _limit = _arg;
1194 }
1195
846 const std::string& notification::getWarning() const 1196 const std::string& notification::getWarning() const
847 { 1197 {
848 switch (_type) 1198 switch (_type)
diff --git a/src/notification.h b/src/notification.h index b5ecd49..a6dd6f4 100644 --- a/src/notification.h +++ b/src/notification.h
@@ -88,25 +88,69 @@ namespace twitter {
88 88
89 type getType() const; 89 type getType() const;
90 90
91 notification() {}
91 notification(const client& tclient, std::string data); 92 notification(const client& tclient, std::string data);
93
94 notification(const notification& other);
92 notification(notification&& other); 95 notification(notification&& other);
93 notification& operator=(notification&& other); 96 notification& operator=(notification other);
94 ~notification(); 97 ~notification();
95 98
96 notification(const notification& other) = delete; 99 friend void swap(notification& first, notification& second);
97 notification& operator=(const notification& other) = delete;
98 100
99 const tweet& getTweet() const; 101 const tweet& getTweet() const;
102 tweet& getTweet()
103 {
104 return const_cast<tweet&>(static_cast<const notification&>(*this).getTweet());
105 }
106
100 const user& getUser() const; 107 const user& getUser() const;
108 user& getUser()
109 {
110 return const_cast<user&>(static_cast<const notification&>(*this).getUser());
111 }
112
101 const list& getList() const; 113 const list& getList() const;
114 list& getList()
115 {
116 return const_cast<list&>(static_cast<const notification&>(*this).getList());
117 }
118
102 tweet_id getTweetID() const; 119 tweet_id getTweetID() const;
120 void setTweetID(tweet_id _arg);
121
103 user_id getUserID() const; 122 user_id getUserID() const;
123 void setUserID(user_id _arg);
124
104 const std::vector<std::string>& getCountries() const; 125 const std::vector<std::string>& getCountries() const;
126 std::vector<std::string>& getCountries()
127 {
128 return const_cast<std::vector<std::string>&>(static_cast<const notification&>(*this).getCountries());
129 }
130
105 disconnect_code getDisconnectCode() const; 131 disconnect_code getDisconnectCode() const;
132 void setDisconnectCode(disconnect_code _arg);
133
106 const std::set<user_id>& getFriends() const; 134 const std::set<user_id>& getFriends() const;
135 std::set<user_id>& getFriends()
136 {
137 return const_cast<std::set<user_id>&>(static_cast<const notification&>(*this).getFriends());
138 }
139
107 const direct_message& getDirectMessage() const; 140 const direct_message& getDirectMessage() const;
141 direct_message& getDirectMessage()
142 {
143 return const_cast<direct_message&>(static_cast<const notification&>(*this).getDirectMessage());
144 }
145
108 int getLimit() const; 146 int getLimit() const;
147 void setLimit(int _arg);
148
109 const std::string& getWarning() const; 149 const std::string& getWarning() const;
150 std::string& getWarning()
151 {
152 return const_cast<std::string&>(static_cast<const notification&>(*this).getWarning());
153 }
110 154
111 private: 155 private:
112 union { 156 union {
@@ -140,7 +184,7 @@ namespace twitter {
140 std::set<user_id> _friends; 184 std::set<user_id> _friends;
141 direct_message _direct_message; 185 direct_message _direct_message;
142 }; 186 };
143 type _type; 187 type _type = type::invalid;
144 }; 188 };
145 189
146}; 190};
diff --git a/src/stream.cpp b/src/stream.cpp index d2b3afe..cb55ee8 100644 --- a/src/stream.cpp +++ b/src/stream.cpp
@@ -256,7 +256,7 @@ namespace twitter {
256 _backoff_amount = std::chrono::milliseconds(0); 256 _backoff_amount = std::chrono::milliseconds(0);
257 } 257 }
258 258
259 _notify(n); 259 _notify(std::move(n));
260 260
261 _buffer = ""; 261 _buffer = "";
262 } 262 }
diff --git a/src/stream.h b/src/stream.h index 3391912..b682ce2 100644 --- a/src/stream.h +++ b/src/stream.h
@@ -16,7 +16,7 @@ namespace twitter {
16 class stream { 16 class stream {
17 public: 17 public:
18 18
19 typedef std::function<void(const notification& _notification)> notify_callback; 19 typedef std::function<void(notification _notification)> notify_callback;
20 20
21 stream( 21 stream(
22 const client& tclient, 22 const client& tclient,
diff --git a/src/tweet.cpp b/src/tweet.cpp index 4abe2f8..864bcd8 100644 --- a/src/tweet.cpp +++ b/src/tweet.cpp
@@ -6,19 +6,19 @@
6 6
7namespace twitter { 7namespace twitter {
8 8
9 tweet::tweet(const client& tclient, std::string data) try 9 tweet::tweet(std::string data) try
10 : _client(tclient) 10 : _valid(true)
11 { 11 {
12 auto json = nlohmann::json::parse(data); 12 auto json = nlohmann::json::parse(data);
13 _id = json["id"].get<tweet_id>(); 13 _id = json["id"].get<tweet_id>();
14 _text = json["text"].get<std::string>(); 14 _text = json["text"].get<std::string>();
15 _author = make_unique<user>(_client, json["user"].dump()); 15 _author = make_unique<user>(json["user"].dump());
16 16
17 if (!json["retweeted_status"].is_null()) 17 if (!json["retweeted_status"].is_null())
18 { 18 {
19 _is_retweet = true; 19 _is_retweet = true;
20 20
21 _retweeted_status = make_unique<tweet>(_client, json["retweeted_status"].dump()); 21 _retweeted_status = make_unique<tweet>(json["retweeted_status"].dump());
22 } 22 }
23 23
24 if (!json["entities"].is_null()) 24 if (!json["entities"].is_null())
@@ -40,14 +40,53 @@ namespace twitter {
40 std::throw_with_nested(malformed_object("tweet", data)); 40 std::throw_with_nested(malformed_object("tweet", data));
41 } 41 }
42 42
43 std::string tweet::generateReplyPrefill() const 43 tweet::tweet(const tweet& other)
44 {
45 _valid = other._valid;
46 _id = other._id;
47 _text = other._text;
48 _author = make_unique<user>(*other._author);
49 _is_retweet = other._is_retweet;
50
51 if (_is_retweet)
52 {
53 _retweeted_status = make_unique<tweet>(*other._retweeted_status);
54 }
55
56 _mentions = other._mentions;
57 }
58
59 tweet::tweet(tweet&& other) : tweet()
60 {
61 swap(*this, other);
62 }
63
64 tweet& tweet::operator=(tweet other)
65 {
66 swap(*this, other);
67
68 return *this;
69 }
70
71 void swap(tweet& first, tweet& second)
72 {
73 std::swap(first._valid, second._valid);
74 std::swap(first._id, second._id);
75 std::swap(first._text, second._text);
76 std::swap(first._author, second._author);
77 std::swap(first._is_retweet, second._is_retweet);
78 std::swap(first._retweeted_status, second._retweeted_status);
79 std::swap(first._mentions, second._mentions);
80 }
81
82 std::string tweet::generateReplyPrefill(const user& me) const
44 { 83 {
45 std::ostringstream output; 84 std::ostringstream output;
46 output << "@" << _author->getScreenName() << " "; 85 output << "@" << _author->getScreenName() << " ";
47 86
48 for (auto mention : _mentions) 87 for (auto mention : _mentions)
49 { 88 {
50 if ((mention.first != _author->getID()) && (mention.first != _client.getUser().getID())) 89 if ((mention.first != _author->getID()) && (mention.first != me.getID()))
51 { 90 {
52 output << "@" << mention.second << " "; 91 output << "@" << mention.second << " ";
53 } 92 }
@@ -56,20 +95,12 @@ namespace twitter {
56 return output.str(); 95 return output.str();
57 } 96 }
58 97
59 tweet tweet::reply(std::string message, std::list<long> media_ids) const
60 {
61 return _client.replyToTweet(message, _id, media_ids);
62 }
63
64 bool tweet::isMyTweet() const
65 {
66 return *_author == _client.getUser();
67 }
68
69 std::string tweet::getURL() const 98 std::string tweet::getURL() const
70 { 99 {
100 assert(_valid);
101
71 std::ostringstream urlstr; 102 std::ostringstream urlstr;
72 urlstr << "https://twitter.com"; 103 urlstr << "https://twitter.com/";
73 urlstr << _author->getScreenName(); 104 urlstr << _author->getScreenName();
74 urlstr << "/statuses/"; 105 urlstr << "/statuses/";
75 urlstr << _id; 106 urlstr << _id;
diff --git a/src/tweet.h b/src/tweet.h index e21d689..ae1c916 100644 --- a/src/tweet.h +++ b/src/tweet.h
@@ -18,57 +18,65 @@ namespace twitter {
18 class tweet { 18 class tweet {
19 public: 19 public:
20 20
21 tweet(const client& tclient, std::string data); 21 tweet() {}
22 tweet(std::string data);
22 23
23 tweet(const tweet& other) = delete; 24 tweet(const tweet& other);
24 tweet& operator=(const tweet& other) = delete; 25 tweet(tweet&& other);
25 26
26 tweet(tweet&& other) = default; 27 tweet& operator=(tweet other);
27 tweet& operator=(tweet&& other) = default; 28
29 friend void swap(tweet& first, tweet& second);
28 30
29 tweet_id getID() const 31 tweet_id getID() const
30 { 32 {
33 assert(_valid);
34
31 return _id; 35 return _id;
32 } 36 }
33 37
34 std::string getText() const 38 std::string getText() const
35 { 39 {
40 assert(_valid);
41
36 return _text; 42 return _text;
37 } 43 }
38 44
39 const user& getAuthor() const 45 const user& getAuthor() const
40 { 46 {
47 assert(_valid);
48
41 return *_author; 49 return *_author;
42 } 50 }
43 51
44 bool isRetweet() const 52 bool isRetweet() const
45 { 53 {
54 assert(_valid);
55
46 return _is_retweet; 56 return _is_retweet;
47 } 57 }
48 58
49 const tweet& getRetweet() const 59 const tweet& getRetweet() const
50 { 60 {
51 assert(_is_retweet); 61 assert(_valid && _is_retweet);
52 62
53 return *_retweeted_status; 63 return *_retweeted_status;
54 } 64 }
55 65
56 const std::vector<std::pair<user_id, std::string>>& getMentions() const 66 const std::vector<std::pair<user_id, std::string>>& getMentions() const
57 { 67 {
68 assert(_valid);
69
58 return _mentions; 70 return _mentions;
59 } 71 }
60 72
61 std::string generateReplyPrefill() const; 73 std::string generateReplyPrefill(const user& me) const;
62
63 tweet reply(std::string message, std::list<long> media_ids = {}) const;
64
65 bool isMyTweet() const;
66 74
67 std::string getURL() const; 75 std::string getURL() const;
68 76
69 private: 77 private:
70 78
71 const client& _client; 79 bool _valid = false;
72 tweet_id _id; 80 tweet_id _id;
73 std::string _text; 81 std::string _text;
74 std::unique_ptr<user> _author; 82 std::unique_ptr<user> _author;
diff --git a/src/user.cpp b/src/user.cpp index 0b6e93a..f9b02a1 100644 --- a/src/user.cpp +++ b/src/user.cpp
@@ -5,8 +5,8 @@
5 5
6namespace twitter { 6namespace twitter {
7 7
8 user::user(const client& tclient, std::string data) try 8 user::user(std::string data) try
9 : _client(tclient) 9 : _valid(true)
10 { 10 {
11 auto json = nlohmann::json::parse(data); 11 auto json = nlohmann::json::parse(data);
12 _id = json["id"].get<user_id>(); 12 _id = json["id"].get<user_id>();
@@ -19,25 +19,5 @@ namespace twitter {
19 { 19 {
20 std::throw_with_nested(malformed_object("user", data)); 20 std::throw_with_nested(malformed_object("user", data));
21 } 21 }
22
23 std::set<user_id> user::getFriends() const
24 {
25 return _client.getFriends(_id);
26 }
27
28 std::set<user_id> user::getFollowers() const
29 {
30 return _client.getFollowers(_id);
31 }
32
33 void user::follow() const
34 {
35 _client.follow(_id);
36 }
37
38 void user::unfollow() const
39 {
40 _client.unfollow(_id);
41 }
42 22
43}; 23};
diff --git a/src/user.h b/src/user.h index f08840b..ef7d72e 100644 --- a/src/user.h +++ b/src/user.h
@@ -3,6 +3,7 @@
3 3
4#include <string> 4#include <string>
5#include <set> 5#include <set>
6#include <cassert>
6 7
7namespace twitter { 8namespace twitter {
8 9
@@ -13,20 +14,27 @@ namespace twitter {
13 class user { 14 class user {
14 public: 15 public:
15 16
16 user(const client& tclient, std::string data); 17 user() {}
18 user(std::string data);
17 19
18 user_id getID() const 20 user_id getID() const
19 { 21 {
22 assert(_valid);
23
20 return _id; 24 return _id;
21 } 25 }
22 26
23 std::string getScreenName() const 27 std::string getScreenName() const
24 { 28 {
29 assert(_valid);
30
25 return _screen_name; 31 return _screen_name;
26 } 32 }
27 33
28 std::string getName() const 34 std::string getName() const
29 { 35 {
36 assert(_valid);
37
30 return _name; 38 return _name;
31 } 39 }
32 40
@@ -40,14 +48,9 @@ namespace twitter {
40 return _id != other._id; 48 return _id != other._id;
41 } 49 }
42 50
43 std::set<user_id> getFriends() const;
44 std::set<user_id> getFollowers() const;
45 void follow() const;
46 void unfollow() const;
47
48 private: 51 private:
49 52
50 const client& _client; 53 bool _valid = false;
51 user_id _id; 54 user_id _id;
52 std::string _screen_name; 55 std::string _screen_name;
53 std::string _name; 56 std::string _name;