{"id":2826,"date":"2021-06-09T09:42:29","date_gmt":"2021-06-09T00:42:29","guid":{"rendered":"http:\/\/www.bravesoft.co.jp\/seblog\/?p=2826"},"modified":"2025-05-14T19:31:00","modified_gmt":"2025-05-14T10:31:00","slug":"%e5%8f%97%e4%bb%98%e3%82%a2%e3%83%97%e3%83%aaipad%e3%82%92swiftuigoogle-calendar-api-slack-api%e3%81%a7%e8%87%aa%e4%bd%9c%e3%81%99%e3%82%8b%e6%96%b9%e6%b3%95%e3%82%bd%e3%83%bc%e3%82%b9%e4%bb%98","status":"publish","type":"post","link":"https:\/\/bravesoft.co.jp\/seblog\/archives\/2826","title":{"rendered":"\u53d7\u4ed8\u30a2\u30d7\u30ea(iPad)\u3092SwiftUI+Google Calendar API+ Slack API\u3067\u81ea\u4f5c\u3059\u308b\u65b9\u6cd5(\u30bd\u30fc\u30b9\u4ed8) #30"},"content":{"rendered":"<p>\u793e\u9577\u306e\u3084\u308b\u3079\u304d\u4ed5\u4e8b\u306f\u5e45\u5e83\u3044\u3002<\/p>\n<p>\u6700\u8fd1\u3001\u3064\u3044\u306b\u6211\u304c\u793e\u3082NTT\u96fb\u8a71\u304c\u65ad\u820e\u96e2\u3055\u308c\u308b\u3053\u3068\u306b\u306a\u3063\u305f\u3002<\/p>\n<p>\u30b3\u30b9\u30c8\u524a\u6e1b\u306f\u826f\u3044\u3053\u3068\u306a\u304c\u3089\u3001\u793e\u5185\u304b\u3089\u3053\u3093\u306a\u58f0\u304c\u30fb\u30fb<\/p>\n<p>\u300c\u793e\u9577\uff01\u53d7\u4ed8\u96fb\u8a71\u304c\u7121\u304f\u306a\u308b\u304b\u3089\u6d41\u884c\u308a\u306e\u53d7\u4ed8\u30a2\u30d7\u30ea\uff08100\u4e07\u5186\u3050\u3089\u3044\uff09\u5c0e\u5165\u3057\u307e\u3059\u2606\u300d<\/p>\n<p><strong>\u3061\u3087\u3063\u3068\u5f85\u3063\u305f<\/strong><\/p>\n<p>\u6700\u5f37\u306e\u3082\u306e\u3065\u304f\u308a\u96c6\u56e3\u3092\u76ee\u6307\u3059<a href=\"https:\/\/www.bravesoft.co.jp\/\" rel=\"noopener noreferrer\" target=\"_blank\">bravesoft<\/a>\u304c\u305d\u306e\u7a0b\u5ea6\u306e\u30a2\u30d7\u30ea\u3092\u81ea\u4f5c\u3057\u306a\u3044\u3067\u3069\u3046\u3059\u308b\u306e\u3060\uff01<\/p>\n<p>\u30fb\u30fb\u30fb\u304b\u304f\u3057\u3066\u3001\u793e\u9577\u81ea\u3089GW\u306b\u300c\u7387\u5148\u81ea\u4f5c\u300d\u3059\u308b\u3053\u3068\u306b\u306a\u3063\u305f\u306e\u3060\u3002<\/p>\n<p>GW\u306b\uff15\u65e5\u3050\u3089\u3044\u304b\u3051\u3066SwiftUI\u306e\u5b66\u7fd2\u304c\u3066\u3089\u958b\u767a\u3057\u305f\u306e\u304c\u3053\u308c\uff08\u53f3\u5074\u306fslack\u5168\u793ech)\u3002<\/p>\n<p><!--\n[video width=\"2404\" height=\"1602\" mp4=\"https:\/\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/\u53d7\u4ed8\u30c6\u3099\u30e2\u52d5\u753b.mp4\" loop=\"on\" autoplay=\"on\" muted=\"on\"\u3000playsinline=\"on\"][\/video]\n--><\/p>\n<div style=\"width: 700px;\" class=\"wp-video\"><!--[if lt IE 9]><script>document.createElement('video');<\/script><![endif]--><br \/>\n<video class=\"wp-video-shortcode\" id=\"video-2826-1\" width=\"700\" height=\"466\" loop=\"1\" muted=\"1\" autoplay=\"1\" \u3000playsinline=\"1\" preload=\"metadata\" controls=\"controls\"><source type=\"video\/mp4\" src=\"https:\/\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/\u53d7\u4ed8\u30c6\u3099\u30e2\u52d5\u753b.mp4?_=1\" \/><a href=\"https:\/\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/\u53d7\u4ed8\u30c6\u3099\u30e2\u52d5\u753b.mp4\">https:\/\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/\u53d7\u4ed8\u30c6\u3099\u30e2\u52d5\u753b.mp4<\/a><\/video><\/div>\n<p>\u4ed5\u69d8\u306f\u30b7\u30f3\u30d7\u30eb\u3067\u3001<\/p>\n<p><strong>\u2460Google\u30ab\u30ec\u30f3\u30c0\u30fc\u304b\u3089\u76f4\u8fd1\u306eMTG\u4e88\u5b9a\u8005\u3092\u53d6\u5f97\u3057\u3066\u8868\u793a<br \/>\n\u2461\u6700\u77ed\uff12\u30bf\u30c3\u30d7\u3067\u53d7\u4ed8\u767b\u9332\u304c\u5b8c\u4e86<br \/>\n\u2462\u5168\u793eslack\u306b\u304a\u5ba2\u69d8\u540d\u3084\u4f1a\u8b70\u540d\u3092\u6295\u7a3f<\/strong><\/p>\n<p>\u76f4\u8fd1\u306e\u6253\u3061\u5408\u308f\u305b\u4e88\u5b9a\u8005\u306e\u307f\u4e0a\u306b\u8868\u793a\u3059\u308b\u306e\u3067\u5927\u4f53\u306f\u304a\u76ee\u5f53\u3066\u306e\u62c5\u5f53\u304c\u4e00\u767a\u3067\u898b\u3064\u304b\u308b\u3002<\/p>\n<p>\u5b9f\u969b\u793e\u5185\u30ea\u30ea\u30fc\u30b9\u3057\u3066\u304b\u308c\u3053\u308c\uff11\u30f6\u6708\u3050\u3089\u3044\u666e\u901a\u306b\u4f7f\u308f\u308c\u3066\u3044\u308b\u3002\u305f\u306e\u3057\u304d\u3002<\/p>\n<p>\u305d\u3053\u3067\u3001\u672c\u30d6\u30ed\u30b0\u3067\u306f\u3082\u306e\u3065\u304f\u308a\u540c\u5fd7\u306e\u305f\u3081\u306b\u3053\u306e\u30a2\u30d7\u30ea\u306e\u958b\u767a\u624b\u9806\u3092\u89e3\u8aac\u3057\u3088\u3046\u3002<\/p>\n<p>\u4eca\u56de\u3001Swift\u3067Google Calendar API\u306b\u63a5\u7d9a\u3057\u305f\u8a33\u3060\u304c\u3001\u307e\u3060\u307e\u3060\u30ec\u30a2\u30b1\u30fc\u30b9\u3089\u3057\u304f\u53c2\u8003\u306b\u3067\u304d\u308b\u8a18\u4e8b\u306f\uff08\u82f1\u8a9e\u570f\u3082\u542b\u3081\u3066\uff09\u304b\u306a\u308a\u5c11\u306a\u304b\u3063\u305f\u3002\u305d\u3053\u3067\u3056\u3063\u3068\u8a2d\u5b9a\u624b\u9806\u3092\u307e\u3068\u3081\u3001\u6700\u5f8c\u306b\u306f\u30bd\u30fc\u30b9\u30b3\u30fc\u30c9\u3082\u305d\u306e\u307e\u307e\u8a18\u8f09\u3059\u308b\u3002\u8ab0\u304b\u306e\u53c2\u8003\u306b\u306a\u308c\u3070\u5e78\u3044\u3002<\/p>\n<p>\u3061\u306a\u307f\u306b\u5f53\u65b9\u306e\u52d5\u4f5c\u74b0\u5883\u306f\u3053\u3093\u306a\u611f\u3058\u3060<br \/>\n<a href=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.002-1.jpeg?ssl=1\" target=\"_blank\" rel=\"noopener noreferrer\"><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"2939\" data-permalink=\"https:\/\/bravesoft.co.jp\/seblog\/archives\/2826\/receptbot%e9%96%8b%e7%99%ba%e8%a8%98-002-2\" data-orig-file=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.002-1.jpeg?fit=1920%2C1080&amp;ssl=1\" data-orig-size=\"1920,1080\" data-comments-opened=\"0\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"ReceptBot\u958b\u767a\u8a18.002\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.002-1.jpeg?fit=300%2C169&amp;ssl=1\" data-large-file=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.002-1.jpeg?fit=700%2C394&amp;ssl=1\" tabindex=\"0\" role=\"button\" src=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.002-1.jpeg?resize=700%2C394&#038;ssl=1\" alt=\"\" width=\"700\" height=\"394\" class=\"aligncenter size-full wp-image-2939\" srcset=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.002-1.jpeg?w=1920&amp;ssl=1 1920w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.002-1.jpeg?resize=300%2C169&amp;ssl=1 300w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.002-1.jpeg?resize=700%2C394&amp;ssl=1 700w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.002-1.jpeg?resize=768%2C432&amp;ssl=1 768w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.002-1.jpeg?resize=1536%2C864&amp;ssl=1 1536w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.002-1.jpeg?resize=800%2C450&amp;ssl=1 800w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.002-1.jpeg?w=1400&amp;ssl=1 1400w\" sizes=\"(max-width: 700px) 100vw, 700px\" data-recalc-dims=\"1\" \/><\/a><br \/>\n\uff08\u753b\u50cf\u306f\u30af\u30ea\u30c3\u30af\u3067\u62e1\u5927\u3067\u304d\u308b\uff09<\/p>\n<h1>\u2460\u307e\u305a\u306fXCode\u3067SwiftUI\u5b9f\u884c\u74b0\u5883\u3092\u6e96\u5099<\/h1>\n<p>\u307e\u305a\u306fXCode\u3092\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3002SwiftUI\u306fXCode11\u4ee5\u964d\u306a\u3089\u6a19\u6e96\u3067\u3064\u3044\u3066\u308b\u3002\uff08\u5b9f\u306f\u5f53\u521d\u306fFlutter\u3067\u958b\u767a\u3057\u3088\u3046\u3068\u601d\u3063\u3066\u3044\u305f\u304c\u3001\u6700\u65b0\u306eMac(M1\u30c1\u30c3\u30d7\uff09\u3067Android Studio\u304c\u3061\u3083\u3093\u3068\u52d5\u304b\u305a\u3001\u82e6\u52b4\u3057\u305d\u3046\u3060\u3063\u305f\u306e\u3067\u6025\u907dApple\u7d14\u6b63\u306eSwiftUI\u306b\u5909\u66f4\u3002\u30de\u30eb\u30c1\u30d7\u30e9\u30c3\u30c8\u30d5\u30a9\u30fc\u30e0\u306e\u958b\u767a\u8a00\u8a9e\u306f\u3061\u3087\u304f\u3061\u3087\u304f\u3053\u3046\u3044\u3046\u554f\u984c\u8d77\u304d\u308b\u306e\u3067\u6ce8\u610f\u3002<\/p>\n<p><a href=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.004.jpeg?ssl=1\" target=\"_blank\" rel=\"noopener noreferrer\"><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"2836\" data-permalink=\"https:\/\/bravesoft.co.jp\/seblog\/archives\/2826\/receptbot%e9%96%8b%e7%99%ba%e8%a8%98-004\" data-orig-file=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.004.jpeg?fit=1920%2C1080&amp;ssl=1\" data-orig-size=\"1920,1080\" data-comments-opened=\"0\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"ReceptBot\u958b\u767a\u8a18.004\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.004.jpeg?fit=300%2C169&amp;ssl=1\" data-large-file=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.004.jpeg?fit=700%2C394&amp;ssl=1\" tabindex=\"0\" role=\"button\" src=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.004.jpeg?resize=700%2C394&#038;ssl=1\" alt=\"\" width=\"700\" height=\"394\" class=\"aligncenter size-full wp-image-2836\" srcset=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.004.jpeg?w=1920&amp;ssl=1 1920w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.004.jpeg?resize=300%2C169&amp;ssl=1 300w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.004.jpeg?resize=700%2C394&amp;ssl=1 700w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.004.jpeg?resize=768%2C432&amp;ssl=1 768w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.004.jpeg?resize=1536%2C864&amp;ssl=1 1536w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.004.jpeg?resize=800%2C450&amp;ssl=1 800w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.004.jpeg?w=1400&amp;ssl=1 1400w\" sizes=\"(max-width: 700px) 100vw, 700px\" data-recalc-dims=\"1\" \/><\/a><\/p>\n<p>SwiftUI\u306f\u3053\u308c\u307e\u3067\u306eStoryBoard\u3068\u3046\u3063\u3066\u304b\u308f\u3063\u3066\u5206\u304b\u308a\u3084\u3059\u3044\u3002UI\u3092\u5168\u3066\u30b3\u30fc\u30c9\u3067\u8a18\u8ff0\u2192HTML\u611f\u899a\u3067\u753b\u9762\u3092\u898b\u306a\u304c\u3089\u3044\u3058\u308c\u308b\u306e\u3067\u7c21\u5358\u3002<\/p>\n<p><a href=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.006.jpeg?ssl=1\" target=\"_blank\" rel=\"noopener noreferrer\"><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"2837\" data-permalink=\"https:\/\/bravesoft.co.jp\/seblog\/archives\/2826\/receptbot%e9%96%8b%e7%99%ba%e8%a8%98-006\" data-orig-file=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.006.jpeg?fit=1920%2C1080&amp;ssl=1\" data-orig-size=\"1920,1080\" data-comments-opened=\"0\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"ReceptBot\u958b\u767a\u8a18.006\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.006.jpeg?fit=300%2C169&amp;ssl=1\" data-large-file=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.006.jpeg?fit=700%2C394&amp;ssl=1\" tabindex=\"0\" role=\"button\" src=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.006.jpeg?resize=700%2C394&#038;ssl=1\" alt=\"\" width=\"700\" height=\"394\" class=\"aligncenter size-full wp-image-2837\" srcset=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.006.jpeg?w=1920&amp;ssl=1 1920w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.006.jpeg?resize=300%2C169&amp;ssl=1 300w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.006.jpeg?resize=700%2C394&amp;ssl=1 700w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.006.jpeg?resize=768%2C432&amp;ssl=1 768w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.006.jpeg?resize=1536%2C864&amp;ssl=1 1536w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.006.jpeg?resize=800%2C450&amp;ssl=1 800w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.006.jpeg?w=1400&amp;ssl=1 1400w\" sizes=\"(max-width: 700px) 100vw, 700px\" data-recalc-dims=\"1\" \/><\/a><\/p>\n<p>\u3055\u3089\u306b\u30e9\u30a4\u30d6\u30e9\u30ea\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u74b0\u5883\u306eCocoaPods\u3092\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3002\u3053\u308c\u3082M1\u30c1\u30c3\u30d7\u306e\u90fd\u5408\u3067\u3001Rosetta\u30e2\u30fc\u30c9\u306a\u308b\u3082\u306e\u3067\u30bf\u30fc\u30df\u30ca\u30eb\u3092\u8d77\u52d5\u3059\u308b\u5fc5\u8981\u3042\u308a\u3002<\/p>\n<p><a href=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.007.jpeg?ssl=1\" target=\"_blank\" rel=\"noopener noreferrer\"><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"2838\" data-permalink=\"https:\/\/bravesoft.co.jp\/seblog\/archives\/2826\/receptbot%e9%96%8b%e7%99%ba%e8%a8%98-007\" data-orig-file=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.007.jpeg?fit=1920%2C1080&amp;ssl=1\" data-orig-size=\"1920,1080\" data-comments-opened=\"0\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"ReceptBot\u958b\u767a\u8a18.007\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.007.jpeg?fit=300%2C169&amp;ssl=1\" data-large-file=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.007.jpeg?fit=700%2C394&amp;ssl=1\" tabindex=\"0\" role=\"button\" src=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.007.jpeg?resize=700%2C394&#038;ssl=1\" alt=\"\" width=\"700\" height=\"394\" class=\"aligncenter size-full wp-image-2838\" srcset=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.007.jpeg?w=1920&amp;ssl=1 1920w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.007.jpeg?resize=300%2C169&amp;ssl=1 300w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.007.jpeg?resize=700%2C394&amp;ssl=1 700w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.007.jpeg?resize=768%2C432&amp;ssl=1 768w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.007.jpeg?resize=1536%2C864&amp;ssl=1 1536w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.007.jpeg?resize=800%2C450&amp;ssl=1 800w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.007.jpeg?w=1400&amp;ssl=1 1400w\" sizes=\"(max-width: 700px) 100vw, 700px\" data-recalc-dims=\"1\" \/><\/a><\/p>\n<p>CocoaPods\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u5b8c\u4e86\u3002\u5fc5\u8981\u306a\u30e9\u30a4\u30d6\u30e9\u30ea\u3082\u30b3\u30fc\u30c9\u3067\u8a18\u8ff0\u3002Google API\u3084HTTP\u30ea\u30af\u30a8\u30b9\u30c8\u95a2\u9023\u30e9\u30a4\u30d6\u30e9\u30ea\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u306b\u91cd\u7528\u3057\u305f\u3002\uff08\u30b3\u30fc\u30c9\u5168\u6587\u306f\u6587\u672b\u306b\u8a18\u8f09\uff09<\/p>\n<h1>\u2461Google\u8a8d\u8a3c(OAuth)\u3068\u9023\u643a\u3059\u308b<\/h1>\n<p>\u5168\u793e\u54e1\u306e\u4e88\u5b9a\u72b6\u6cc1\u3092\u77e5\u308b\u305f\u3081\u306b\u306f\u3001\u4f1a\u793e\u306eGoogle\u30a2\u30ab\u30a6\u30f3\u30c8\u3067Goole\u30ed\u30b0\u30a4\u30f3\u72b6\u614b\u306b\u306a\u308b\u3053\u3068\u304c\u5fc5\u8981\u306b\u306a\u308b\u3002\u3053\u308c\u306f\u30a2\u30d7\u30ea\u304b\u3089Google\u306b\u9077\u79fb\u3057\u3066Google\u30ed\u30b0\u30a4\u30f3\u3057\u3001\u307e\u305f\u30a2\u30d7\u30ea\u306b\u623b\u3063\u3066\u304f\u308bOAuth\u306e\u6d41\u308c\u3092\u5b9f\u88c5\u3059\u308b\u3053\u3068\u3067\u53ef\u80fd\u306b\u306a\u308b\u3002\uff08\u5b9f\u306f\u3082\u3068\u3082\u3068\u306f\u7279\u5b9a\u500b\u4eba\u30a2\u30ab\u30a6\u30f3\u30c8\u304c\u4e0d\u8981\u306a\u300c\u30b5\u30fc\u30d3\u30b9\u30a2\u30ab\u30a6\u30f3\u30c8\u65b9\u5f0f\u300d\u3067\u63a5\u7d9a\u3057\u3088\u3046\u3057\u305f\u304c\u3001\u624b\u7d9a\u304d\u304c\u5206\u304b\u308a\u306b\u304f\u304f\u60c5\u5831\u3082\u5c11\u306a\u3044\u305f\u3081OAuth\u3092\u9078\u629e\u3057\u305f\u3002\u77ed\u671f\u9593\u306e\u76ee\u7684\u9054\u6210\u306e\u305f\u3081\u3053\u3046\u3044\u3046\u5224\u65ad\u304c\u91cd\u8981\uff09<\/p>\n<p><a href=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.010.jpeg?ssl=1\" target=\"_blank\" rel=\"noopener noreferrer\"><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"2839\" data-permalink=\"https:\/\/bravesoft.co.jp\/seblog\/archives\/2826\/receptbot%e9%96%8b%e7%99%ba%e8%a8%98-010\" data-orig-file=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.010.jpeg?fit=1920%2C1080&amp;ssl=1\" data-orig-size=\"1920,1080\" data-comments-opened=\"0\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"ReceptBot\u958b\u767a\u8a18.010\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.010.jpeg?fit=300%2C169&amp;ssl=1\" data-large-file=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.010.jpeg?fit=700%2C394&amp;ssl=1\" tabindex=\"0\" role=\"button\" src=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.010.jpeg?resize=700%2C394&#038;ssl=1\" alt=\"\" width=\"700\" height=\"394\" class=\"aligncenter size-full wp-image-2839\" srcset=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.010.jpeg?w=1920&amp;ssl=1 1920w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.010.jpeg?resize=300%2C169&amp;ssl=1 300w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.010.jpeg?resize=700%2C394&amp;ssl=1 700w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.010.jpeg?resize=768%2C432&amp;ssl=1 768w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.010.jpeg?resize=1536%2C864&amp;ssl=1 1536w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.010.jpeg?resize=800%2C450&amp;ssl=1 800w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.010.jpeg?w=1400&amp;ssl=1 1400w\" sizes=\"(max-width: 700px) 100vw, 700px\" data-recalc-dims=\"1\" \/><\/a><\/p>\n<p>\u307e\u305a\u306fOAuth\u753b\u9762\u306e\u8a2d\u5b9a\u3060\u3002\u3042\u3089\u304b\u3058\u3081\u4f7f\u7528\u3059\u308b\u60c5\u5831\uff08\u30b9\u30b3\u30fc\u30d7\uff09\u3092\u660e\u793a\u3057\u3066\u304a\u304f\u3068\u3001iPad\u30a2\u30d7\u30ea\u304b\u3089Google\u30ed\u30b0\u30a4\u30f3\u3059\u308b\u969b\u306b\u3069\u306e\u60c5\u5831\u306b\u30a2\u30af\u30bb\u30b9\u3055\u308c\u308b\u304b\u660e\u793a\u3055\u308c\u308b\u3002\u305d\u306e\u4e0a\u3067\u3001Google\u30ed\u30b0\u30a4\u30f3\u3057\u305f\u72b6\u614b\u3067iPad\u30a2\u30d7\u30ea\u306b\u623b\u3063\u3066\u304f\u308b\u3068\u3044\u3046\u6d41\u308c\u3002<\/p>\n<p><a href=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.011-1.jpeg?ssl=1\" target=\"_blank\" rel=\"noopener noreferrer\"><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"2877\" data-permalink=\"https:\/\/bravesoft.co.jp\/seblog\/archives\/2826\/receptbot%e9%96%8b%e7%99%ba%e8%a8%98-011-2\" data-orig-file=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.011-1.jpeg?fit=1920%2C1080&amp;ssl=1\" data-orig-size=\"1920,1080\" data-comments-opened=\"0\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"ReceptBot\u958b\u767a\u8a18.011\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.011-1.jpeg?fit=300%2C169&amp;ssl=1\" data-large-file=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.011-1.jpeg?fit=700%2C394&amp;ssl=1\" tabindex=\"0\" role=\"button\" src=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.011-1.jpeg?resize=700%2C394&#038;ssl=1\" alt=\"\" width=\"700\" height=\"394\" class=\"aligncenter size-full wp-image-2877\" srcset=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.011-1.jpeg?w=1920&amp;ssl=1 1920w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.011-1.jpeg?resize=300%2C169&amp;ssl=1 300w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.011-1.jpeg?resize=700%2C394&amp;ssl=1 700w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.011-1.jpeg?resize=768%2C432&amp;ssl=1 768w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.011-1.jpeg?resize=1536%2C864&amp;ssl=1 1536w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.011-1.jpeg?resize=800%2C450&amp;ssl=1 800w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.011-1.jpeg?w=1400&amp;ssl=1 1400w\" sizes=\"(max-width: 700px) 100vw, 700px\" data-recalc-dims=\"1\" \/><\/a><\/p>\n<p>\u6b21\u306b\u30af\u30e9\u30a4\u30a2\u30f3\u30c8ID\u3084URL Schemes\u3092Google\u304b\u3089\u53d6\u5f97\u3002\u3053\u308c\u3089\u306e\u8b58\u5225\u5b50\u3092\u30bd\u30fc\u30b9\u30b3\u30fc\u30c9\u3084plist\u30d5\u30a1\u30a4\u30eb\u306b\u6307\u5b9a\u3059\u308c\u3070\u3001OAuth\u306e\u8a2d\u5b9a\u306f\u5b8c\u4e86\u3060\u3002<\/p>\n<p>\u4e00\u3064\u30cf\u30de\u3063\u305f\u30d0\u30b0\u3042\u308a\u3002AppAuth\u3092\u4f7f\u7528\u3057\u3066\u30ed\u30b0\u30a4\u30f3\u3059\u308b\u3068\u3053\u308d\u3067\u8b0e\u306e\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3002<\/p>\n<pre class=\"prettyprint lang-js linenums\">\r\n\u63a5\u7d9a\u30a8\u30e9\u30fc\u3067\u3059\uff1aError Domain=org.openid.appauth.general Code=-3 \"(null)\" \r\nUserInfo={NSUnderlyingError=0x600000a95230 \r\n{Error Domain=com.apple.AuthenticationServices.WebAuthenticationSession Code=2 \r\n\"Cannot start ASWebAuthenticationSession without providing presentation context. \r\nSet presentationContextProvider before calling -start.\" \r\nUserInfo={NSDebugDescription=Cannot start ASWebAuthenticationSession \r\nwithout providing presentation context. Set presentationContextProvider before calling -start.}}}\r\n<\/pre>\n<p><a href=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.013.jpeg?ssl=1\" target=\"_blank\" rel=\"noopener noreferrer\"><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"2842\" data-permalink=\"https:\/\/bravesoft.co.jp\/seblog\/archives\/2826\/receptbot%e9%96%8b%e7%99%ba%e8%a8%98-013\" data-orig-file=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.013.jpeg?fit=1920%2C1080&amp;ssl=1\" data-orig-size=\"1920,1080\" data-comments-opened=\"0\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"ReceptBot\u958b\u767a\u8a18.013\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.013.jpeg?fit=300%2C169&amp;ssl=1\" data-large-file=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.013.jpeg?fit=700%2C394&amp;ssl=1\" tabindex=\"0\" role=\"button\" src=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.013.jpeg?resize=700%2C394&#038;ssl=1\" alt=\"\" width=\"700\" height=\"394\" class=\"aligncenter size-full wp-image-2842\" srcset=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.013.jpeg?w=1920&amp;ssl=1 1920w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.013.jpeg?resize=300%2C169&amp;ssl=1 300w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.013.jpeg?resize=700%2C394&amp;ssl=1 700w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.013.jpeg?resize=768%2C432&amp;ssl=1 768w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.013.jpeg?resize=1536%2C864&amp;ssl=1 1536w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.013.jpeg?resize=800%2C450&amp;ssl=1 800w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.013.jpeg?w=1400&amp;ssl=1 1400w\" sizes=\"(max-width: 700px) 100vw, 700px\" data-recalc-dims=\"1\" \/><\/a><\/p>\n<p>\u8abf\u3079\u305f\u3068\u3053\u308d\u3001\u6700\u65b0\u306eiOS14\u3068\u3001AppAuth1.1.0\u306f\u76f8\u6027\u304c\u60aa\u3044\u3089\u3057\u3044\u3002\u305d\u3053\u3067\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u30d0\u30fc\u30b8\u30e7\u30f3\u3092AppAuth0.9.5\u306b\u30c0\u30a6\u30f3\u30b0\u30ec\u30fc\u30c9\u3057\u305f\u3068\u3053\u308d\u89e3\u6d88\u3002<\/p>\n<h1>\u2462Google Calendar API\u3068\u9023\u643a\u3059\u308b<\/h1>\n<p>OAuth\u9023\u643a\u304c\u3067\u304d\u308b\u3068\u3001Google API\u304c\u53e9\u3051\u308b\u3088\u3046\u306b\u306a\u308b\u3002\u4eca\u56de\u5229\u7528\u3057\u305f\u306e\u306f\u3001<\/p>\n<p><strong><br \/>\nGoogle Directory API..\u4f1a\u8b70\u5ba4\u3001\u793e\u54e1\u3001\u793e\u54e1\u30b5\u30e0\u30cd\u5199\u771f\u306e\u53d6\u5f97<br \/>\nGoogle Calendar API&#8230;\u30ab\u30ec\u30f3\u30c0\u30fc\u30a4\u30d9\u30f3\u30c8\u60c5\u5831\u306e\u53d6\u5f97<br \/>\n<\/strong><\/p>\n<p><a href=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.017-1.jpeg?ssl=1\" target=\"_blank\" rel=\"noopener noreferrer\"><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"2845\" data-permalink=\"https:\/\/bravesoft.co.jp\/seblog\/archives\/2826\/receptbot%e9%96%8b%e7%99%ba%e8%a8%98-017-2\" data-orig-file=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.017-1.jpeg?fit=1920%2C1080&amp;ssl=1\" data-orig-size=\"1920,1080\" data-comments-opened=\"0\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"ReceptBot\u958b\u767a\u8a18.017\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.017-1.jpeg?fit=300%2C169&amp;ssl=1\" data-large-file=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.017-1.jpeg?fit=700%2C394&amp;ssl=1\" tabindex=\"0\" role=\"button\" src=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.017-1.jpeg?resize=700%2C394&#038;ssl=1\" alt=\"\" width=\"700\" height=\"394\" class=\"aligncenter size-full wp-image-2845\" srcset=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.017-1.jpeg?w=1920&amp;ssl=1 1920w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.017-1.jpeg?resize=300%2C169&amp;ssl=1 300w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.017-1.jpeg?resize=700%2C394&amp;ssl=1 700w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.017-1.jpeg?resize=768%2C432&amp;ssl=1 768w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.017-1.jpeg?resize=1536%2C864&amp;ssl=1 1536w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.017-1.jpeg?resize=800%2C450&amp;ssl=1 800w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.017-1.jpeg?w=1400&amp;ssl=1 1400w\" sizes=\"(max-width: 700px) 100vw, 700px\" data-recalc-dims=\"1\" \/><\/a><\/p>\n<p>Calendar API\u306e\u8a2d\u5b9a\u306f\u6bd4\u8f03\u7684\u7c21\u5358\u306b\u5b8c\u4e86\u3059\u308b\u3002<strong>\u305d\u306e\u6b21\u306eDirectory API\u3067\u4f1a\u8b70\u5ba4\u3084\u793e\u54e1\u3001\u793e\u54e1\u306e\u30b5\u30e0\u30cd\u30a4\u30eb\u753b\u50cf\u306a\u3069\u3092\u53d6\u5f97\u3059\u308b\u30b3\u30fc\u30c7\u30a3\u30f3\u30b0\u306f\u5927\u5909\u3060\u3063\u305f\u3002<\/strong>\u82f1\u8a9e\u570f\u3082\u542b\u3081\u3066\u30cd\u30c3\u30c8\u306b\u60c5\u5831\u304c\u5c11\u306a\u3044\u306e\u3067\u3001Google\u30e9\u30a4\u30d6\u30e9\u30ea\u306e\u539f\u5178\u3092\u8aad\u307f\u8fbc\u3093\u3060\u308a\u3057\u3066\u3088\u3046\u3084\u304f\u5b9f\u88c5\u3002\u8a73\u3057\u304f\u306f\u5f8c\u8ff0\u306e\u30bd\u30fc\u30b9\u30b3\u30fc\u30c9\u3092\u53c2\u8003\u306b\u3002<\/p>\n<h1>\u2463Slack API\u3068\u9023\u643a\u3059\u308b<\/h1>\n<p>\u3055\u3042\u3001\u4f1a\u8b70\u4e88\u5b9a\u304c\u3042\u308b\u4eba\u3092\u753b\u9762\u306b\u4e26\u3079\u3066\u3001\u6765\u5ba2\u60c5\u5831\u3092\u5165\u529b\u3055\u305b\u308bUI\u304c\u51fa\u6765\u305f\u3089\u3001\u6700\u5f8c\u306fSlack\u3067\u6295\u7a3f\u3059\u308b\u305f\u3081\u306e\u8a2d\u5b9a\u3002<\/p>\n<p><a href=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.019.jpeg?ssl=1\" target=\"_blank\" rel=\"noopener noreferrer\"><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"2846\" data-permalink=\"https:\/\/bravesoft.co.jp\/seblog\/archives\/2826\/receptbot%e9%96%8b%e7%99%ba%e8%a8%98-019\" data-orig-file=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.019.jpeg?fit=1920%2C1080&amp;ssl=1\" data-orig-size=\"1920,1080\" data-comments-opened=\"0\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"ReceptBot\u958b\u767a\u8a18.019\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.019.jpeg?fit=300%2C169&amp;ssl=1\" data-large-file=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.019.jpeg?fit=700%2C394&amp;ssl=1\" tabindex=\"0\" role=\"button\" src=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.019.jpeg?resize=700%2C394&#038;ssl=1\" alt=\"\" width=\"700\" height=\"394\" class=\"aligncenter size-full wp-image-2846\" srcset=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.019.jpeg?w=1920&amp;ssl=1 1920w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.019.jpeg?resize=300%2C169&amp;ssl=1 300w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.019.jpeg?resize=700%2C394&amp;ssl=1 700w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.019.jpeg?resize=768%2C432&amp;ssl=1 768w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.019.jpeg?resize=1536%2C864&amp;ssl=1 1536w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.019.jpeg?resize=800%2C450&amp;ssl=1 800w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.019.jpeg?w=1400&amp;ssl=1 1400w\" sizes=\"(max-width: 700px) 100vw, 700px\" data-recalc-dims=\"1\" \/><\/a><\/p>\n<p>\u307e\u305a\u306fApp(bot\u7684\u306a\u3082\u306e)\u3092slack\u306b\u8ffd\u52a0\u3001\u305d\u3057\u3066Webhook(=API)\u3092\u8ffd\u52a0\u3059\u308b\u3002Webhook\u306fslack\u30c1\u30e3\u30f3\u30cd\u30eb\u3054\u3068\u306b\u8a2d\u5b9a\u3059\u308b\u3001\u6295\u7a3f\u7528\u306e\u5c02\u7528URL\u3002<\/p>\n<p><a href=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.020.jpeg?ssl=1\" target=\"_blank\" rel=\"noopener noreferrer\"><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"2847\" data-permalink=\"https:\/\/bravesoft.co.jp\/seblog\/archives\/2826\/receptbot%e9%96%8b%e7%99%ba%e8%a8%98-020\" data-orig-file=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.020.jpeg?fit=1920%2C1080&amp;ssl=1\" data-orig-size=\"1920,1080\" data-comments-opened=\"0\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"ReceptBot\u958b\u767a\u8a18.020\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.020.jpeg?fit=300%2C169&amp;ssl=1\" data-large-file=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.020.jpeg?fit=700%2C394&amp;ssl=1\" tabindex=\"0\" role=\"button\" src=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.020.jpeg?resize=700%2C394&#038;ssl=1\" alt=\"\" width=\"700\" height=\"394\" class=\"aligncenter size-full wp-image-2847\" srcset=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.020.jpeg?w=1920&amp;ssl=1 1920w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.020.jpeg?resize=300%2C169&amp;ssl=1 300w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.020.jpeg?resize=700%2C394&amp;ssl=1 700w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.020.jpeg?resize=768%2C432&amp;ssl=1 768w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.020.jpeg?resize=1536%2C864&amp;ssl=1 1536w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.020.jpeg?resize=800%2C450&amp;ssl=1 800w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/ReceptBot\u958b\u767a\u8a18.020.jpeg?w=1400&amp;ssl=1 1400w\" sizes=\"(max-width: 700px) 100vw, 700px\" data-recalc-dims=\"1\" \/><\/a><\/p>\n<p>Webhook\u3092\u30c6\u30b9\u30c8\u3001\u672c\u756a\u305d\u308c\u305e\u308c\u4f5c\u6210\u3057\u3066\u3001App\u306e\u8a8d\u8a3c\u60c5\u5831\u3092\u53d6\u5f97\u3002\u5272\u3068\u7c21\u5358\u3002<\/p>\n<h1>\u5b8c\u4e86\uff01\u30bd\u30fc\u30b9\u30b3\u30fc\u30c9\u3092\u5168\u516c\u958b\u2606<\/h1>\n<p>\u4ee5\u4e0a\u3067\u8a2d\u5b9a\u306f\u5b8c\u4e86\uff01 SwiftUI\u30d9\u30fc\u30b9\u3067UI\u3092\u52d5\u304b\u3057\u3066\u3044\u3051\u3070\u53d7\u4ed8\u30a2\u30d7\u30ea\u304c\u5b8c\u6210\u3059\u308b\u3002\u4eca\u56de\u3001HTML\u304b\u306e\u3088\u3046\u306bUI\u3092\u5ba3\u8a00\u30d9\u30fc\u30b9\u3067\u4f5c\u308c\u308bSwiftUI\u306e\u826f\u3055\u3092\u7406\u89e3\u3002\u307e\u305fGoogle\u3084Slack\u7b49\u306e\u696d\u52d9\u7cfb\u306eAPI\u9023\u643a\u304c\u5145\u5b9f\u3057\u3066\u304d\u3066\u3044\u308b\u3053\u3068\u3067\u3001\u696d\u52d9DX\u306f\u683c\u6bb5\u306b\u63a8\u9032\u3057\u3084\u3059\u3044\u74b0\u5883\u304c\u6574\u3044\u3064\u3064\u3042\u308b\u3068\u611f\u3058\u305f\u3002\u696d\u52d9\u3092\u30cf\u30c3\u30af\u3059\u308b\u611f\u899a\u3067\u3001\u601d\u3044\u3064\u3044\u305f\u4eba\u304c\u3069\u3093\u3069\u3093DX\u3057\u3066\u3044\u3051\u3070\u826f\u3044\u306e\u3060\u3002<\/p>\n<p>\u4e0b\u8a18\u306b\u30bd\u30fc\u30b9\u30b3\u30fc\u30c9\u3092\u516c\u958b\u3059\u308b\u3002\u30bd\u30fc\u30b9\u306e\u4e2d\u3067\u3082\u8a70\u307e\u3063\u305f\u30dd\u30a4\u30f3\u30c8\u3084\u5de5\u592b\u3057\u305f\u70b9\u304c\u3044\u308d\u3044\u308d\u3042\u308b\u304c\u3001\u6642\u9593\u306e\u90fd\u5408\u3067\u89e3\u8aac\u3057\u304d\u308c\u306a\u3044\u306e\u3067\u3001\u3068\u306b\u304b\u304f\u30bd\u30fc\u30b9\u3092\u5f37\u5f15\u306b\u8cbc\u308a\u4ed8\u3051\u3066\u304a\u304f\u3002\u8a73\u3057\u304f\u77e5\u308a\u305f\u3044\u30a8\u30f3\u30b8\u30cb\u30a2\u8af8\u6c0f\u306f<a href=\"https:\/\/www.bravesoft.co.jp\/recruit\/\" rel=\"noopener noreferrer\" target=\"_blank\">\u305c\u3072\u5f53\u793e\u306b\u5165\u793e\u3057\u3061\u3083\u3063\u3066\u304f\u3060\u3055\u3044 \ud83d\ude42<\/a><\/p>\n<h1>Podfile(Swift\u30e9\u30a4\u30d6\u30e9\u30ea\u7528\uff09<\/h1>\n<p>\u307e\u305a\u306fSwift\u30e9\u30a4\u30d6\u30e9\u30ea\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u306b\u5fc5\u8981\u306a\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb\u306e\u5185\u5bb9<\/p>\n<pre class=\"prettyprint lang-js linenums\">\r\n# Uncomment the next line to define a global platform for your project\r\n# platform :ios, '9.0'\r\n\r\ntarget 'ReceptBot' do\r\n  # Comment the next line if you don't want to use dynamic frameworks\r\n  use_frameworks!\r\n\r\n  # Pods for ReceptBot\r\n  pod 'AppAuth','0.95.1'\r\n  pod 'GTMAppAuth'\r\n  pod 'GoogleAPIClientForREST\/Calendar'\r\n  pod 'GoogleAPIClientForREST\/Directory'\r\n  pod 'Alamofire'\r\n\r\n  target 'ReceptBotTests' do\r\n    inherit! :search_paths\r\n    # Pods for testing\r\n  end\r\n\r\n  target 'ReceptBotUITests' do\r\n    # Pods for testing\r\n  end\r\n\r\nend\r\n<\/pre>\n<h1>ReceptBotApp.swift\uff08\u8d77\u52d5\u51e6\u7406)<\/h1>\n<p>\u6b21\u306bSwiftUI\u306e\u8d77\u52d5\u51e6\u7406\u3002\u3053\u308c\u306f\u3082\u3046\u30c6\u30f3\u30d7\u30ec\u901a\u308a\u3002<\/p>\n<pre class=\"prettyprint lang-js linenums\">\r\n\/\/\r\n\/\/  ReceptBotApp.swift\r\n\/\/  ReceptBot\r\n\/\/  braver\u53d7\u4ed8\u30a2\u30d7\u30ea\u306e\u8d77\u52d5\u51e6\u7406\u3002view\u3092\u547c\u3073\u51fa\u3059\u3060\u3051\r\n\/\/  Created by esga on 2021\/04\/29.\r\n\/\/\r\nimport SwiftUI\r\n\r\n@main\r\nstruct ReceptBotApp: App {\r\n    var body: some Scene {\r\n        WindowGroup {\r\n            ContentView()\r\n        }\r\n    }\r\n}\r\n<\/pre>\n<h1>ContentView.swift\uff08\u753b\u9762\u51e6\u7406)<\/h1>\n<p>\u753b\u9762\u307e\u308f\u308a\u306e\u30e1\u30a4\u30f3\u51e6\u7406\u3002SwiftUI\u306b\u3088\u3063\u3066\u300c\u793e\u54e1\u60c5\u5831\u304c\u53d6\u5f97\u3067\u304d\u305f\u3089\u3001\u753b\u9762\u3092\u81ea\u52d5\u518d\u63cf\u753b\u300d\u3057\u3066\u304f\u308c\u308b\u306e\u3067\u30b3\u30fc\u30c9\u8a18\u8ff0\u304c\u30b7\u30f3\u30d7\u30eb\u3002<\/p>\n<pre class=\"prettyprint lang-js linenums\">\r\n\/\/\r\n\/\/  ContentView.swift\r\n\/\/  ReceptBot\r\n\/\/\u3000\u53d7\u4ed8\u30a2\u30d7\u30ea\u306e\u30e1\u30a4\u30f3\u30d3\u30e5\u30fc\u3002\u8d77\u52d5\u5f8c\u307e\u305a\u4f1a\u8b70\u5ba4\u3067MTG\u4e88\u5b9a\u8005\u306e\u30ea\u30b9\u30c8\u3092\u8868\u793a\r\n\/\/  Created by esga on 2021\/04\/29.\r\n\/\/\r\nimport SwiftUI\r\nimport Alamofire\r\n\r\n\/*-------------\u5168\u4f53\u3067\u4f7f\u3046\u30b0\u30ed\u30fc\u30d0\u30eb\u5909\u6570-------------*\/\r\n\r\n\/\/\u30c6\u30b9\u30c8channel\r\nvar SLACK_WEBHOOK = \"https:\/\/hooks.slack.com\/services\/TQRK*****1sss\"\r\n\/\/\u672c\u756achannel\r\n\/\/var SLACK_WEBHOOK = \"https:\/\/hooks.slack.com\/services\/TQRK*****tYz\"\r\n\r\n\/*--------\u4ee5\u4e0b\u306fBraverByGoogle\u5185\u3088\u308a\u53c2\u7167\u3055\u308c\u308b------*\/\r\n\r\n\/\/var DEBUG_TODAY = \"2021-5-10T10:00\"    \/\/\u4eca\u65e5\u306e\u65e5\u4ed8 \u672c\u756a\u3067\u306f\u672a\u5165\u529b\u3002\u65e5\u4ed8\u304c\u5165\u529b\u3055\u308c\u305f\u3089\u30c6\u30b9\u30c8\u30e2\u30fc\u30c9\r\nvar DEBUG_TODAY:String!   \/\/\u672c\u756a\u306f\u3053\u3061\u3089\u3092\u9069\u7528\r\n\r\n\/\/Google API\u306e\u8a8d\u8a3c\u95a2\u9023\u60c5\u5831\r\nlet CLIENT_ID = \"8949**********h31r5.apps.googleusercontent.com\"\r\nlet URL_SCHEME = \"com.googleusercontent.apps.8949**********31r5\"\r\nlet SCOPES         = [\"https:\/\/www.googleapis.com\/auth\/calendar.readonly\",\r\n                      \"https:\/\/www.googleapis.com\/auth\/calendar.events.readonly\",\r\n                      \"https:\/\/www.googleapis.com\/auth\/admin.directory.user.readonly\",\r\n                      \"https:\/\/www.googleapis.com\/auth\/admin.directory.resource.calendar.readonly\"]\r\n\/*----------------------------------------------*\/\r\n\r\nstruct ContentView: View {\r\n    \r\n    @State private var showInputForm: Bool = false        \/\/\u30e2\u30fc\u30c0\u30eb\u5165\u529b\u30d5\u30a9\u30fc\u30e0\u306e\u8868\u793a\u6307\u793a\r\n    @ObservedObject var braveByGoogle = BraverByGoogle()  \/\/MTG\u4e88\u5b9a\u304c\u3042\u308bbravers\u306e\u30ea\u30b9\u30c8\u3092\u4fdd\u6301\r\n    @ObservedObject var selectedBraver = SelectedBraver() \/\/\u9078\u629e\u3055\u308c\u305fBraver\u306e\u60c5\u5831\u3092\u5165\u529b\u30d5\u30a9\u30fc\u30e0\u306b\u5f15\u304d\u6e21\u3059\r\n    \r\n    let timer = Timer.publish(every: 300, on: .main, in: .common).autoconnect()  \/\/\u81ea\u52d5\u30ea\u30ed\u30fc\u30c9\u30bf\u30a4\u30de\u30fc\u306e\u8a2d\u5b9a.5\u5206\u304a\u304d\r\n    \r\n    var body: some View {\r\n        \r\n        ZStack(){\r\n            AnimatedBackground().blur(radius:20)  \/\/\u30b7\u30b9\u30c6\u30e0\u7a3c\u50cd\u4e2d\u3067\u3042\u308b\u3053\u3068\u3092\u793a\u3059\u305f\u3081\u80cc\u666f\u8272\u30b0\u30e9\u30c7\u3092\u63fa\u3089\u3059\r\n            \r\n            HStack(alignment: .top){\r\n                VStack(){\r\n                    HStack(alignment: .center) { \/\/\u753b\u9762\u4e0a\u90e8\u306e\u6848\u5185\u30e1\u30c3\u30bb\u30fc\u30b8\r\n                        VStack(alignment: .leading){\r\n                            \r\n                            Text(\"\u3054\u6765\u793e\u3042\u308a\u304c\u3068\u3046\u3054\u3056\u3044\u307e\u3059\uff01\")\r\n                                .font(.title)\r\n                                .fontWeight(.semibold)\r\n                                .foregroundColor(Color.white)\r\n                            \r\n                            Text(\"\u76ee\u7684\u306e\u62c5\u5f53\u8005\u3092\u9078\u629e\u3059\u308b\u304b\u3001\u300c\u305d\u306e\u4ed6\u306e\u62c5\u5f53\u8005\u300d\u3092\u62bc\u3057\u3066\u304f\u3060\u3055\u3044\")\r\n                                .font(.footnote)\r\n                                .fontWeight(.medium)\r\n                                .foregroundColor(Color.white)\r\n                                .lineLimit(0)\r\n                                .padding(.top, 1.0)\r\n                        }\r\n                        Spacer()\r\n                        Button(action: {\/\/\u305d\u306e\u4ed6\u306e\u62c5\u5f53\u304c\u62bc\u3055\u308c\u305f\u3089\r\n                            \r\n                            selectedBraver.name = \"\"\r\n                            selectedBraver.mail = \"\"\r\n                            selectedBraver.location = \"\"\r\n                            showInputForm = true;  \/\/\u30e2\u30fc\u30c0\u30eb\u3092\u8868\u793a\u3059\u308b\r\n                            \r\n                        }){\r\n                            \/\/\u76ee\u7684\u306ebraver\u304c\u8868\u793a\u3055\u308c\u3066\u306a\u304b\u3063\u305f\u308a\u305d\u306e\u4ed6\u306e\u8981\u4ef6\u306e\u305f\u3081\r\n                            Text(\"\u305d\u306e\u4ed6\u306e\u62c5\u5f53\u8005\uff1e\")\r\n                                .font(.system(.title3, design: .rounded))\r\n                                .fontWeight(.semibold)\r\n                                .foregroundColor(Color.white)\r\n                                .padding(.vertical,20)\r\n                                .padding(.horizontal,30)\r\n                        }\r\n                        .overlay(\r\n                            RoundedRectangle(cornerRadius: 10)\r\n                                .stroke(Color.white, lineWidth: 1) \/\/\u30dc\u30bf\u30f3\u306e\u67a0\u7dda\r\n                        )\r\n                        .sheet(isPresented: self.$showInputForm) { \/\/\u30dc\u30bf\u30f3\u304c\u62bc\u3055\u308c\u305f\u3089\u30e2\u30fc\u30c0\u30eb\u3067\u5165\u529b\u30d5\u30a9\u30fc\u30e0\u8868\u793a\r\n                            \/\/\u30e2\u30fc\u30c0\u30eb\u9077\u79fb\u3067\u8868\u793a\u3059\u308b\u30d3\u30e5\u30fc\u3002\u305d\u306e\u4ed6\u306e\u62c5\u5f53\r\n                            HStack {\r\n                                InputFormView(selectedBraver:self.selectedBraver, clientName:\"\", clientCompany:\"\" ,note:\"\")\r\n                            }\r\n                        }\r\n                    }\r\n                    .padding(.vertical, 20.0)\r\n                    .padding(.horizontal, 10.0)\r\n                    .background(Color.blue)\r\n                    \r\n                    ScrollView{\r\n                        generateButtons() \/\/\u30dc\u30bf\u30f3(braver)\u306e\u914d\u7f6e\u306f\u5ea7\u6a19\u304c\u52d5\u7684\u306a\u305f\u3081\u5225\u9014\u5b9a\u7fa9\r\n                    }\r\n                }\r\n            }.alert(isPresented: $braveByGoogle.networkError) {  \/\/ Slack\u9001\u4fe1\u3057\u305f\u3089\u30a2\u30e9\u30fc\u30c8\u3092\u8868\u793a\u3059\u308b\r\n                Alert(title: Text(\"\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u30a8\u30e9\u30fc\u3067\u3059\"),\r\n                      message: Text(\"\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u306b\u63a5\u7d9a\u3055\u308c\u3066\u3044\u306a\u3044\u304b\u3001\u30b5\u30fc\u30d0\u5074\u3067\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u3066\u3044\u307e\u3059\u3002\u78ba\u8a8d\u306e\u3046\u3048\u518d\u5ea6\u304a\u8a66\u3057\u304f\u3060\u3055\u3044\"),\r\n                      dismissButton: .default(Text(\"\u4e86\u89e3\"),\r\n                                              action: {\r\n                                              }))\r\n            }\r\n            \r\n        }\r\n        .onAppear(){ \/\/\u753b\u9762\u51fa\u73fe\u6642\u306b\u5b9f\u884c\u3059\u308b\u30e1\u30a4\u30f3\u51e6\u7406\u3002Google API\u3078\u30a2\u30af\u30bb\u30b9\u3057\u3001bravers\u30ea\u30b9\u30c8\u3092\u53d6\u5f97\r\n            \/\/OAuth\u3067Google\u306b\u63a5\u7d9a\u3057\u3066\u4e88\u5b9a\u53c2\u52a0\u8005\u3092\u53d6\u5f97\r\n            braveByGoogle.setBraversByGoogle(viewController:UIHostingController(rootView: ContentView()))\r\n        }\r\n        .onReceive(timer, perform: { time in  \/\/\u5b9a\u671f\u30bf\u30a4\u30de\u30fc\u3067\u30e1\u30a4\u30f3\u51e6\u7406\u3092\u518d\u5b9f\u884c\u3057\u81ea\u52d5\u30ea\u30ed\u30fc\u30c9\u3059\u308b\r\n            braveByGoogle.setBraversByGoogle(viewController:UIHostingController(rootView: ContentView()))\r\n        })\r\n    }\r\n    \r\n    \/\/bravers\u304c\u8868\u793a\u3055\u308c\u308b\u30dc\u30bf\u30f3\u30923\u5217\u305a\u3064\u52d5\u7684\u306b\u8868\u793a\u3002\r\n    private func generateButtons() -> some View {\r\n        \r\n        var width = CGFloat.zero\r\n        var height = CGFloat.zero\r\n        var i = 0\r\n        \r\n        return ZStack(alignment: .topLeading) {\r\n            ForEach(braveByGoogle.braverList, id: \\.id) { braver in \/\/\u53d6\u5f97\u6e08\u307f\u306ebraver\u3092\u9806\u306b\u8868\u793a\r\n\r\n                buttonItem(braver:braver)\r\n                    .padding(.vertical, 10)\r\n                    .padding(.horizontal, 15)\r\n                    .alignmentGuide(.leading, computeValue: { d in\r\n                        \/\/print(\"name:\\(braver.name) i:\\(i) dw.:\\(d.width) dh.:\\(d.height)\")\r\n                        if i%3 == 0  { \/\/4\u4eba\u3081\u3067\u5de6\u4e0b\u3078\u5ea7\u6a19\u3092\u79fb\u52d5\u3055\u305b\u308b\r\n                            width = 0\r\n                            height -= d.height\r\n                        }\r\n                        let result = width\r\n                        if i >= braveByGoogle.braverList.count { \/\/\u5168\u54e1\u5206\u7d42\u4e86\u3067\u5ea7\u6a19\u3092\u3082\u3068\u306b\u623b\u3057\u3066\u304a\u304f\r\n                            width = 0\r\n                        } else {\r\n                            width -= d.width \/\/\u30dc\u30bf\u30f3\u306e\u30b5\u30a4\u30ba\u5206\u53f3\u306b\u305a\u3089\u3059\r\n                        }\r\n                        i += 1\r\n                        return result\r\n                    })\r\n                    .alignmentGuide(.top, computeValue: { d in\r\n                        let result = height\r\n                        if i >= braveByGoogle.braverList.count {\r\n                            height = 0\r\n                            i = 0\r\n                        }\r\n                        return result\r\n                    })\r\n                }\r\n        }.frame(maxWidth: .infinity) \/\/\u6a2a\u5e45\u3044\u3063\u3071\u3044\u307e\u3067\u753b\u9762\u3092\u4f7f\u7528\u3059\u308b\r\n    }\r\n    \/\/\u30dc\u30bf\u30f3\uff11\u3064\uff11\u3064\u306e\u8a2d\u5b9a\r\n    func buttonItem(braver:Braver) -> some View {\r\n        Button(action: {\r\n            print(\"\u30dc\u30bf\u30f3\u304c\u62bc\u3055\u308c\u307e\u3057\u305f\\(braver.name)\")\r\n            selectedBraver.name = braver.name\r\n            selectedBraver.mail = braver.mail\r\n            selectedBraver.location = braver.location\r\n            showInputForm = true \/\/\u30e2\u30fc\u30c0\u30eb\u3067\u5165\u529b\u30d5\u30a9\u30fc\u30e0\u3092\u8868\u793a\r\n        }){\r\n            HStack(){\r\n                Text(\"\")  \/\/\u30d0\u30e9\u30f3\u30b9\u8abf\u6574\u306e\u305f\u3081\u30c0\u30df\u30fc\u306eText\u3092\u633f\u5165\r\n                Image(uiImage:braver.image!) \/\/braver\u306e\u30b5\u30e0\u30cd\u3092\u8868\u793a\r\n                    .resizable()\r\n                    .frame(width: 50, height: 50)\r\n                    .clipShape(Circle())\r\n                Text(braver.name) \/\/braver\u306e\u540d\u524d\u3092\u8868\u793a\r\n                    .foregroundColor(Color.blue)\r\n                    .font(.system(.title3, design: .rounded))\r\n                    .fontWeight(.semibold)\r\n                    .frame(width:130, height:70, alignment: .leading)\r\n            }\r\n        }\r\n        .background(Color.white)\r\n        .cornerRadius(10)\r\n        .overlay(\r\n            RoundedRectangle(cornerRadius: 10)\r\n                .stroke(Color.blue, lineWidth: 1) \/\/\u30dc\u30bf\u30f3\u306e\u67a0\u7dda\r\n        )\r\n        .compositingGroup()        \/\/ shodow\u7528\u306b\u30b0\u30eb\u30fc\u30d7\u5316\r\n        .shadow(color: .gray.opacity(0.6), radius: 5, x: 7, y: 7)\r\n        .sheet(isPresented: self.$showInputForm) { \/\/\u30dc\u30bf\u30f3\u304c\u62bc\u3055\u308c\u305f\u3089\u30e2\u30fc\u30c0\u30eb\u3067\u5165\u529b\u30d5\u30a9\u30fc\u30e0\u8868\u793a\r\n            \/\/\u30e2\u30fc\u30c0\u30eb\u9077\u79fb\u3057\u305f\u5f8c\u306b\u8868\u793a\u3059\u308b\u30d3\u30e5\u30fc\r\n            HStack {\r\n                InputFormView(selectedBraver:self.selectedBraver)\r\n            }\r\n        }\r\n    }\r\n}\r\n\r\n\/\/\u53d7\u4ed8\u7528\u306e\u5165\u529b\u30d5\u30a9\u30fc\u30e0\u3002\u5165\u529b\u5185\u5bb9\u3092slack\u3078\u901a\u77e5\r\nstruct InputFormView : View {\r\n    \r\n    @Environment(\\.presentationMode) var presentationMode \/\/\u9589\u3058\u308b\u30dc\u30bf\u30f3\u7528\r\n    @ObservedObject var selectedBraver: SelectedBraver \/\/\u9078\u629e\u3055\u308c\u305fBraver\u306e\u60c5\u5831\u53d7\u4ed8\u7528\r\n    @State var clientName = \"\"           \/\/\u304a\u5ba2\u69d8\u306e\u6c0f\u540d\u4fdd\u5b58\u7528\r\n    @State var clientCompany = \"\"        \/\/\u304a\u5ba2\u69d8\u306e\u793e\u540d\u4fdd\u5b58\u7528\r\n    @State var note = \"\"                  \/\/\u5099\u8003\u4fdd\u5b58\u7528\r\n    @State private var showAlert = false  \/\/ \u547c\u3073\u51fa\u3057\u7d50\u679c\u30a2\u30e9\u30fc\u30c8\u8868\u793a\u7528\r\n    @State private var sendError = false  \/\/ \u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u63a5\u7d9a\u7d50\u679c\u8868\u793a\r\n    @State private var SUBJECT = \"\"    \/\/ \u30c0\u30a4\u30a2\u30ed\u30b0\u8868\u793a\u30bf\u30a4\u30c8\u30eb\u3002\u6210\u529f\u304b\u5931\u6557\u304b\u3067\u5909\u308f\u308b\r\n    @State private var BODY = \"\"       \/\/ \u30c0\u30a4\u30a2\u30ed\u30b0\u8868\u793a\u6587\r\n\r\n    var body: some View {\r\n        VStack(alignment: .leading){\r\n            Spacer()\r\n            HStack{\r\n                Text(\"\u304a\u5ba2\u69d8\u60c5\u5831\u3092\u5165\u529b\u3057\u3066\u62c5\u5f53\u8005\u3092\u547c\u3073\u51fa\u3057\u3066\u304f\u3060\u3055\u3044\")\r\n                    .font(.title3)\r\n                    .fontWeight(.semibold)\r\n                    .foregroundColor(Color.white)\r\n                    .padding(.vertical,10)\r\n                    .padding(.horizontal,15)\r\n                Spacer()\r\n                Button(action: {  \/\/\u9589\u3058\u308b\u30dc\u30bf\u30f3\r\n                    self.presentationMode.wrappedValue.dismiss() \/\/\u3053\u306e\u30d5\u30a9\u30fc\u30e0\u3092\u9589\u3058\u308b\r\n                }){\r\n                    Text(\"\u9589\u3058\u308b\")\r\n                        .font(.subheadline)\r\n                        .foregroundColor(Color.white)\r\n                        .padding(.vertical,10)\r\n                        .padding(.horizontal,15)\r\n                }\r\n            }\r\n            Form {\r\n                Section(header: Text(\"\u3000\")){}\r\n                Section(header: Text(\"\u304a\u5ba2\u69d8\u306e\u6c0f\u540d(\u5fc5\u9808)\").font(.headline)){\r\n                    TextField(\"\u30ab\u30f3\u30bf\u30f3\u3067OK\", text:$clientName)\r\n                }\r\n                Section(header: Text(\"\u304a\u5ba2\u69d8\u306e\u4f1a\u793e\u540d(\u4efb\u610f)\").font(.headline)){\r\n                    TextField(\"\u30ab\u30f3\u30bf\u30f3\u3067OK\", text:$clientCompany)\r\n                }\r\n                Section(header: Text(\"bravesoft\u306e\u62c5\u5f53\u8005(\u4efb\u610f)\").font(.headline)){\r\n                    TextField(\"\u30ab\u30f3\u30bf\u30f3\u3067OK\", text: $selectedBraver.name)\r\n                }\r\n                Section(header: Text(\"\u5099\u8003\u3084\u76ee\u7684\u306a\u3069\u3001\u5fc5\u8981\u306b\u5fdc\u3058\u3066\u5165\u529b\u304f\u3060\u3055\u3044(\u4efb\u610f)\").font(.headline)){\r\n                    TextEditor(text:$note)\r\n                }\r\n            }\r\n            \/\/\u62c5\u5f53\u8005\u3092\u547c\u3076\u30dc\u30bf\u30f3\r\n            Button(action: {\r\n                sendError = false  \/\/\u30a8\u30e9\u30fc\u3060\u3063\u305f\u5834\u5408\u3042\u3089\u305f\u3081\u3066\u30ea\u30bb\u30c3\u30c8\r\n                \/\/\u767b\u9332\u3055\u308c\u305f\u5185\u5bb9\u3092\u5143\u306bSlack\u3078\u9001\u4fe1\r\n                postToSlack(braverName:selectedBraver.name, location:selectedBraver.location,clientName:clientName, clientCompany:clientCompany, note:note )\r\n            }) {\r\n                Text(\"\u62c5\u5f53\u8005\u3092\u547c\u3076(Slack\u3067\u901a\u77e5\u3057\u307e\u3059)\")\r\n                    .font(.largeTitle)\r\n                    .fontWeight(.semibold)\r\n                    .foregroundColor(Color.white)\r\n                    .frame(maxWidth: .infinity, maxHeight: 100, alignment: .center)\r\n            }\r\n            .background(Color.blue)\r\n            .alert(isPresented: $showAlert) {  \/\/ Slack\u9001\u4fe1\u5f8c\u306e\u30c0\u30a4\u30a2\u30ed\u30b0\u8868\u793a\r\n                Alert(title: Text(SUBJECT),\r\n                      message: Text(BODY),\r\n                      dismissButton: .default(Text(\"\u4e86\u89e3\"),\r\n                                              action: {\r\n                                                self.presentationMode.wrappedValue.dismiss() \/\/\u4e86\u89e3\u304c\u62bc\u3055\u308c\u305f\u3089\u30d5\u30a9\u30fc\u30e0\u3092\u9589\u3058\u308b\r\n                                              }))\r\n            }\r\n            Spacer()\r\n        }\r\n        .background(Color.blue)\r\n    }\r\n    \r\n    \/\/ Slack\u3078\u53d7\u4ed8\u60c5\u5831\u3092\u6295\u7a3f\u3059\u308b\r\n    func postToSlack(braverName:String, location:String, clientName: String, clientCompany: String, note: String) {\r\n        \r\n        let headers: HTTPHeaders = [\r\n            \"Content-Type\": \"application\/json\"\r\n        ]\r\n        let parameters: Parameters = [\r\n            \"attachments\": [\r\n                [\r\n                    \"color\": \"#0066FF\",\r\n                    \"text\": \"<!here>\\n\u304a\u5ba2\u69d8\u304c\u300c\\(braverName)\u300d\u3055\u3093\u3092\u547c\u51fa\u3057\u3066\u307e\u3059!\u300c\\(braverName)\u300d\u3055\u3093\u304c\u6c17\u4ed8\u3044\u3066\u306a\u3044\u5834\u5408\u3001\u540c\u90e8\u7f72\u3084\u8fd1\u6240\u306ebraver\u304c\u6559\u3048\u3066\u3042\u3052\u308b or \u5909\u308f\u308a\u306b\u4f1a\u8b70\u5ba4\u306b\u6848\u5185\u304f\u3060\u3055\u3044! \u7d76\u5bfe\u306b1\u5206\u4ee5\u4e0a\u5f85\u305f\u305b\u306a\u3044\u3067!!\",\r\n                    \"fields\": [\r\n                        [\r\n                            \"title\": \"bravesoft\u306e\u62c5\u5f53\u8005\",\r\n                            \"value\": braverName,\r\n                        ],\r\n                        [\r\n                            \"title\": \"\u304a\u5ba2\u69d8\u793e\u540d\",\r\n                            \"value\": clientCompany,\r\n                            \"short\": true\r\n                        ],                   [\r\n                            \"title\": \"\u304a\u5ba2\u69d8\u6c0f\u540d\",\r\n                            \"value\": clientName,\r\n                            \"short\": true\r\n                        ],\r\n                        [\r\n                            \"title\": \"\u4f1a\u8b70\u540d\u3068\u5834\u6240(\u3042\u304f\u307e\u3067\u4e88\u60f3)\",\r\n                            \"value\": location,\r\n                        ],\r\n                        [\r\n                            \"title\": \"\u5099\u8003\u30fb\u76ee\u7684\",\r\n                            \"value\": note,\r\n                        ]\r\n                    ]\r\n                ]\r\n            ]\r\n        ]\r\n        \r\n        AF.request(SLACK_WEBHOOK,\r\n                   method: .post,\r\n                   parameters: parameters,\r\n                   encoding: JSONEncoding.default,\r\n                   headers: headers).responseString { response in\r\n\r\n                    switch(response.result) {\r\n                    case .success(let value):\r\n                        sendError = false\r\n                        SUBJECT = \"\u62c5\u5f53\u8005\u3092\u547c\u3073\u51fa\u3057\u307e\u3057\u305f\uff01\"\r\n                        BODY = \"1\u5206\u7d4c\u904e\u3057\u3066\u3082\u62c5\u5f53\u8005\u304c\u73fe\u308c\u306a\u3044\u5834\u5408\u306f\u3001\u7533\u3057\u8a33\u3054\u3056\u3044\u307e\u305b\u3093\u304c\u518d\u5ea6\u304a\u547c\u3073\u51fa\u3057\u9802\u304f\u304b\u3001\u304a\u8fd1\u304f\u306e\u30b9\u30bf\u30c3\u30d5\u307e\u3067\u304a\u58f0\u304c\u3051\u304f\u3060\u3055\u3044\u3002\"\r\n                        print(\"Slack\u63a5\u7d9a\u6210\u529f:\\(value)\")\r\n                    case .failure(let error):\r\n                        sendError = true   \/\/\u9001\u4fe1\u5931\u6557\u30a2\u30e9\u30fc\u30c8\u8868\u793a\r\n                        SUBJECT = \"\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u30a8\u30e9\u30fc\u3067\u3059\"\r\n                        BODY = \"\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u63a5\u7d9a\u304b\u3001\u30b5\u30fc\u30d0\u306b\u554f\u984c\u304c\u3042\u308a\u307e\u3059\u3002\u8a2d\u5b9a\u3092\u78ba\u8a8d\u306e\u3046\u3048\u3001\u518d\u5ea6\u304a\u8a66\u3057\u304f\u3060\u3055\u3044\"\r\n                        print(\"Slack\u63a5\u7d9a\u30a8\u30e9\u30fc:\\(error)\")\r\n                    }\r\n                    showAlert = true   \/\/\u30a2\u30e9\u30fc\u30c8\u306f\u3069\u3061\u3089\u306b\u305b\u3088\u8868\u793a\u8868\u793a\r\n                   }\r\n    }\r\n}\r\n\r\n\/\/\u9078\u629e\u3055\u308c\u305fbraver\u306e\u60c5\u5831\u3092\u4fdd\u6301\u3057\u5171\u6709\u3059\u308b\r\nfinal class SelectedBraver: ObservableObject {\r\n    @Published var name = \"\"\r\n    @Published var mail = \"\"\r\n    @Published var location = \"\"\r\n}\r\n\r\n\r\n\r\n\/\/\u80cc\u666f\u753b\u50cf\u3092\u30b0\u30e9\u30c7\u30fc\u30b7\u30e7\u30f3\u3067\u52d5\u304b\u3059\u305f\u3081\u306eView\r\nstruct AnimatedBackground: View{\r\n    @State var start = UnitPoint(x:0, y:-2)\r\n    @State var end = UnitPoint(x:4, y:0)\r\n    \r\n    let timer = Timer.publish(every:1, on: .main, in: .default).autoconnect()\r\n    let colors = [Color.white,\r\n                  Color(red: 190\/255, green: 220\/255, blue: 255\/255), \/\/\u6c34\u8272\u7cfb\u306e\u8272\u3067\u30b0\u30e9\u30c7\u3092\u304b\u3051\u308b\r\n                  Color(red:  90\/255, green: 180\/255, blue: 255\/255),\r\n                  Color(red: 150\/255, green: 200\/255, blue: 255\/255)\r\n    ]\r\n    var body: some View{\r\n        LinearGradient(gradient: Gradient(colors: colors), startPoint: start, endPoint: end)\r\n            .animation(Animation.easeInOut(duration:3)\r\n                        .repeatForever()\r\n            )\r\n            .edgesIgnoringSafeArea(.bottom)  \/\/\u3053\u308c\u3057\u306a\u3044\u3068\u30ad\u30fc\u30dc\u30fc\u30c9\u51fa\u73fe\u6642\u306b\u4e0b\u90e8\u304c\u7121\u52b9\u5316\u3055\u308c\u3066\u3057\u307e\u3046\r\n            .onReceive(timer, perform: { _ in\r\n                start = UnitPoint(x:4, y:0)\r\n                end   = UnitPoint(x:0, y:2)\r\n                start = UnitPoint(x:-4, y:20)\r\n                start = UnitPoint(x:4, y:0)\r\n            })\r\n    }\r\n}\r\nstruct ContentView_Previews: PreviewProvider {\r\n    static var previews: some View {\r\n        Group {\r\n            ContentView()\r\n                .padding(9.0)\r\n        }\r\n    }\r\n}\r\n<\/pre>\n<h1>BraverByGoogle.swift\uff08Google\u901a\u4fe1\u51e6\u7406)<\/h1>\n<p>Google API\u306b\u63a5\u7d9a\u3057\u3066\u5fc5\u8981\u30c7\u30fc\u30bf\u3092\u53d6\u5f97\u3057\u3066\u304f\u308b\u51e6\u7406\u3002<\/p>\n<pre class=\"prettyprint lang-js linenums\">\r\n\/\/\r\n\/\/  BraverByGoogle.swift\r\n\/\/  ReceptBot\r\n\/\/  Google API\u306b\u63a5\u7d9a\u3057\u3066OAuth\u8a8d\u8a3c\u30fbDirectory\u3088\u308abraver\u53d6\u5f97\u30fbCalendar API\u3088\u308a\u4e88\u5b9a\u3092\u53d6\u5f97\r\n\/\/\u3000\u672c\u65e5\u4f1a\u8b70\u5ba4\u3067\u4e88\u5b9a\u304c\u5165\u3063\u3066\u3044\u308bbraver\u306e\u30ea\u30b9\u30c8\u3092\u7dad\u6301\u3059\u308b\r\n\/\/  Created by esga on 2021\/05\/01.\r\n\/\/\r\n\r\nimport Foundation\r\nimport SwiftUI\r\nimport GTMAppAuth\r\nimport AppAuth\r\nimport GoogleAPIClientForREST\r\n\r\n\/\/\u4f1a\u8b70\u5ba4\uff08\u30ea\u30bd\u30fc\u30b9)\u306e\u30c7\u30fc\u30bf\u69cb\u9020\r\nstruct Resource: Identifiable{\r\n    let id =  UUID()\r\n    let rid:  String \/\/\u30ea\u30bd\u30fc\u30b9ID\r\n    let name: String \/\/\u4f1a\u8b70\u5ba4\u540d\r\n    let mail: String  \/\/\u30ea\u30bd\u30fc\u30b9\u306e\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9(=\u30ab\u30ec\u30f3\u30c0\u30fc\u53d6\u5f97\u306e\u30ad\u30fc)\r\n}\r\n\/\/User(Directory\u304b\u3089\u53d6\u5f97\u3057\u305f\u793e\u54e1)\u306e\u30c7\u30fc\u30bf\u69cb\u9020\r\nstruct User: Identifiable{\r\n    let id =  UUID()\r\n    let mail: String \/\/\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\r\n    let name: String \/\/\u6c0f\u540d\r\n}\r\n\r\n\/\/braver\u4e00\u4eba\u3072\u3068\u308a\u306e\u30c7\u30fc\u30bf\u69cb\u9020\r\nstruct Braver: Identifiable{\r\n    let id = UUID()\r\n    let mail: String\r\n    var name: String\r\n    var startDate: Date  \/\/\u4f1a\u8b70\u304c\u59cb\u307e\u308b\u6642\u9593\r\n    var score: Int       \/\/\u73fe\u5728\u6642\u523b\u304b\u3089\u306e\u6642\u9593\u7684\u8ddd\u96e2\uff08\u5358\u4f4d\uff1a\u79d2\uff09\r\n    var location:String  \/\/\u4f1a\u8b70\u304c\u884c\u308f\u308c\u308b\u5834\u6240\r\n    var image:UIImage?   \/\/\u30b5\u30e0\u30cd\u753b\u50cf\r\n}\r\n\r\n\/\/Google API\u3088\u308a\u30ab\u30ec\u30f3\u30c0\u30fc\u30c7\u30fc\u30bf\u3092\u53d6\u5f97\u3057\u3066\u4fdd\u6301\u3059\u308b\u3002\r\nclass BraverByGoogle: ObservableObject{\r\n    \r\n    var nowDate:Date!\r\n    var resourceList: [Resource] = []      \/\/\u4f1a\u8b70\u5ba4\u30ea\u30b9\u30c8\u914d\u5217\r\n    var userList: [String: User] = [:]     \/\/\u5168\u793e\u54e1(Braver)\u30ea\u30b9\u30c8Dictionary \u30e1\u30a2\u30c9\u3068\u540d\u524d\u306e\u30ea\u30b9\u30c8\u3092\u4fdd\u7ba1\r\n    \r\n    @Published var braverList: [Braver] = []    \/\/\u30e1\u30a4\u30f3\u3068\u306a\u308bbraver\u30ea\u30b9\u30c8\u914d\u5217\u3002\u4e00\u610f\u3067MTG\u304c\u8fd1\u3044\u9806\u306b\u4e26\u3079\u308b\r\n    @Published var networkError: Bool = false   \/\/\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u30a8\u30e9\u30fc\u306a\u3089true\u3068\u3057view\u3067\u30a2\u30e9\u30fc\u30c8\u8868\u793a\u3059\u308b\r\n    \r\n    private var authorization: GTMAppAuthFetcherAuthorization? \/\/OAuth\u8a8d\u8a3c\u6e08\u307f\u60c5\u5831\u3002\u4e00\u5ea6\u53d6\u5f97\u3057\u305f\u3089\u30ed\u30fc\u30ab\u30eb\u4fdd\u5b58\r\n    private var currentAuthorizationFlow: OIDExternalUserAgentSession? \/\/\u8a8d\u8a3c\u30bb\u30c3\u30b7\u30e7\u30f3\u306e\u60c5\u5831\r\n    typealias callBackAlias = ((Error?) -> Void) \/\/\u30af\u30ed\u30fc\u30b8\u30e3\u5171\u901a\u5ba3\u8a00\r\n    \r\n    \/\/Google Calender\u304b\u3089\u53d6\u5f97\u3059\u308b\u4e88\u5b9a\u30c7\u30fc\u30bf\u306e\u69cb\u9020\u4f53\r\n    struct GoogleCalendarEvent {\r\n        var id: String\r\n        var name: String\r\n        var startDate: Date?\r\n        var endDate: Date?\r\n    }\r\n    private var backViewController: UIViewController?  \/\/\u547c\u3073\u51fa\u3057\u5143\u30af\u30e9\u30b9\u306eView\u3092\u4fdd\u6301\u3002OAuth\u3067\u30ed\u30b0\u30a4\u30f3\u753b\u9762\u8868\u793a\u5236\u5fa1\u306b\u6d3b\u7528\r\n    private var googleCalendarEventList: [GoogleCalendarEvent] = []    \/\/\u53d6\u5f97\u3057\u3066\u304d\u305f\u4e88\u5b9a\u30c7\u30fc\u30bf\u306e\u914d\u5217\r\n    \r\n    \/\/\u521d\u671f\u30c7\u30fc\u30bf\u51e6\u7406\u3002View\u3092\u9810\u304b\u308a\u3001OAuth\u3092\u78ba\u7acb\u3059\u308b\u3002\u63a5\u7d9a\u6e08\u307f\u306a\u3089\u30ed\u30fc\u30ab\u30eb\u304b\u3089\u53d6\u5f97\u3002\u306a\u3044\u5834\u5408\u306fOAuth\u30ed\u30b0\u30a4\u30f3\r\n    func setBraversByGoogle(viewController: UIViewController){\r\n        \r\n        print(\"init\u51e6\u7406\u3092\u884c\u3044\u307e\u3059\")\r\n        self.braverList.removeAll() \/\/\u53d6\u5f97\u306e\u305f\u3073\u306b\u30ea\u30b9\u30c8\u3092\u521d\u671f\u5316\u3057\u3066\u304a\u304f\r\n        networkError = false        \/\/\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u30a8\u30e9\u30fc\u72b6\u614b\u306e\u5834\u5408\u3082\u521d\u671f\u5316\r\n        nowDate = Date()   \/\/\u65e5\u4ed8\u3092\u30bb\u30c3\u30c8\uff08\u30c7\u30d0\u30c3\u30b0\u306e\u5834\u5408\u306f\u30c7\u30d0\u30c3\u30b0\u5b9a\u7fa9\u3057\u305f\u65e5\u4ed8\u3092\u30bb\u30c3\u30c8)\r\n        \r\n        \/\/\u4eca\u65e5\u306e\u65e5\u6642\uff08\u30c7\u30d0\u30c3\u30b0\u7528\uff09\u3092\u30bb\u30c3\u30c8\r\n        if DEBUG_TODAY != nil {\r\n            let formatter = DateFormatter()\r\n            formatter.dateFormat = \"yyyy-MM-dd'T'HH:mm\"\r\n            formatter.timeZone = TimeZone(identifier: \"Asia\/Tokyo\")\r\n            nowDate = formatter.date(from: DEBUG_TODAY)! \/\/\u30c7\u30d0\u30c3\u30b0\u7528\r\n        }\r\n        self.backViewController = viewController \/\/\u547c\u3073\u51fa\u3057\u5143\u306eView\u3092\u30af\u30e9\u30b9\u5909\u6570\u3067\u9810\u304b\u308b\r\n        \r\n        \/\/\u30ed\u30fc\u30ab\u30eb\u304b\u3089\u904e\u53bb\u306eOAuth\u8a8d\u8a3c\u60c5\u5831\u3092\u53d6\u5f97\u3057\u3066Google\u3078\u63a5\u7d9a\r\n        if GTMAppAuthFetcherAuthorization(fromKeychainForName: \"authorization\") != nil {\r\n            self.authorization = GTMAppAuthFetcherAuthorization(fromKeychainForName: \"authorization\")!\r\n            self.setBraversList()\r\n        }\r\n        \r\n        if self.authorization == nil { \/\/\u3082\u3057\u30ed\u30fc\u30ab\u30eb\u306b\u306a\u3051\u308c\u3070OAuth\u63a5\u7d9a\u3057\u305f\u4e0a\u3067Google\u3078\u63a5\u7d9a\r\n            showAuthorizationDialog(callBack: {(error) -> Void in\r\n                self.setBraversList()\r\n            })\r\n        }\r\n    }\r\n    \r\n    \/\/OAuth\u3078\u306e\u63a5\u7d9a\u51e6\u7406\u3002\u30ed\u30b0\u30a4\u30f3\u6210\u529f\u3057\u305f\u3089OAuth\u60c5\u5831\u3092\u30ed\u30fc\u30ab\u30eb\u4fdd\u5b58\r\n    private func showAuthorizationDialog(callBack: @escaping callBackAlias) {\r\n        \r\n        let configuration = GTMAppAuthFetcherAuthorization.configurationForGoogle()\r\n        let redirectURL = URL.init(string: URL_SCHEME + \":\/oauthredirect\") \/\/\u30ed\u30b0\u30a4\u30f3\u6210\u529f\u5f8c\u623b\u308aURL\r\n        let request = OIDAuthorizationRequest.init(configuration: configuration,\r\n                                                   clientId: CLIENT_ID,\r\n                                                   scopes: SCOPES,\r\n                                                   redirectURL: redirectURL!,\r\n                                                   responseType: OIDResponseTypeCode,\r\n                                                   additionalParameters: nil)\r\n        print(\"request\u3092\u30bb\u30c3\u30c8\u3057\u307e\u3057\u305f..\\(request)\")\r\n        \r\n        \/\/OAuth\u30ed\u30b0\u30a4\u30f3\u3002\u30ed\u30b0\u30a4\u30f3\u753b\u9762\u3092\u547c\u3073\u51fa\u3057\u5143View\u306b\u8868\u793a\u3055\u305b\u305f\u5f8c\u3001Scheme\u3067\u623b\u3059\r\n        currentAuthorizationFlow = OIDAuthState.authState(\r\n            byPresenting: request,\r\n            presenting: self.backViewController!,\r\n            callback: { (authState, error) in\r\n                if let error = error {\r\n                    print(\"\u63a5\u7d9a\u30a8\u30e9\u30fc\u3067\u3059\uff1a\\(error)\")\r\n                    self.networkError = true\r\n                } else {\r\n                    if let authState = authState {\r\n                        print(\"\u8a8d\u8a3c\u6210\u529f\u3057\u307e\u3057\u305f\uff1a\\(authState)\")\r\n                        \/\/ \u8a8d\u8a3c\u60c5\u5831\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3092\u751f\u6210\u3057\u3001\u30ed\u30fc\u30ab\u30eb\u4fdd\u5b58\r\n                        self.authorization = GTMAppAuthFetcherAuthorization.init(authState: authState)\r\n                        GTMAppAuthFetcherAuthorization.save(self.authorization!, toKeychainForName: \"authorization\")\r\n                    }\r\n                }\r\n                callBack(error)\r\n            })\r\n    }\r\n    \r\n    \/\/Google API\u3088\u308a\u4f1a\u8b70\u5ba4\u30c7\u30fc\u30bf\u3092\u53d6\u5f97\u3057\u3001\u53c2\u52a0\u8005braver\u3092\u30af\u30e9\u30b9\u5909\u6570\u306b\u4fdd\u5b58\u3059\u308b\r\n    func setBraversList() {\r\n        \r\n        \/\/\u307e\u305a\u306f\u4f1a\u8b70\u5ba4\u60c5\u5831\u3001\u5168\u793e\u54e1\u60c5\u5831\u3092Google API\u304b\u3089\u53d6\u5f97\u3057\u3066\u304b\u3089resourceList,userList\u8f9e\u66f8\u306b\u30bb\u30c3\u30c8\r\n        self.setResources(callBack: {(error) -> Void in\r\n            self.setUsers(callBack: {(error) -> Void in\r\n                \r\n                \/\/\u73fe\u5728\u304b\u308930\u5206\u524d\u304b\u3089\u306e\u5168\u30c7\u30fc\u30bf\u3092\u53d6\u5f97(\u3061\u3087\u3063\u3068\u524d\u306eMTG\u307e\u3067\u5ff5\u306e\u70ba\u53d6\u5f97\u3059\u308b\uff09\r\n                let startDateTime = Calendar.init(identifier: .gregorian).date(byAdding: .minute, value: -30, to: self.nowDate)\r\n                \/\/\u73fe\u5728\u304b\u30895\u6642\u9593\u5f8c\u307e\u3067\u306e\u5168\u30c7\u30fc\u30bf\u3092\u53d6\u5f97\r\n                let endDateTime = Calendar.init(identifier: .gregorian).date(byAdding: .hour, value: +3, to: self.nowDate)\r\n                \r\n                print(\"\u4f1a\u8b70\u5ba4\u306eCalendar\u3092\u53d6\u5f97\u3057\u307e\u3059\")\r\n                \/\/\u4f1a\u8b70\u5ba4\u306e\u30e1\u30a2\u30c9\u3092\u30ad\u30fc\u306b\u30ab\u30ec\u30f3\u30c0\u30fc\u4e88\u5b9a\u3092\u53d6\u5f97\u3001\u53c2\u52a0braver\u3092\u914d\u5217\u3078\u30bb\u30c3\u30c8\u3059\u308b\r\n                for resource in self.resourceList{\r\n                    print(\"\u4f1a\u8b70\u5ba4:\\(resource.name),mail=\\(resource.mail)\u306e\u4e88\u5b9a\u3092\u53d6\u5f97\u3057\u307e\u3059\")\r\n                    self.setBraverByCalendar(calendarId:resource.mail, startDateTime: startDateTime!, endDateTime: endDateTime!)\r\n                }\r\n            })\r\n        })\r\n    }\r\n    \r\n    \/\/Directory API\u3088\u308a\u4f1a\u8b70\u5ba4\u306e\u4e00\u89a7\u3092\u53d6\u5f97\r\n    private func setResources(callBack: @escaping callBackAlias) {\r\n        print(\"\u4f1a\u8b70\u5ba4\u53d6\u5f97\u306e\u305f\u3081\u3001Directory\u306b\u63a5\u7d9a\u3057\u307e\u3059\")\r\n        let directoryService = GTLRDirectoryService()\r\n        directoryService.authorizer = self.authorization\r\n        directoryService.shouldFetchNextPages = true\r\n        let query = GTLRDirectoryQuery_ResourcesCalendarsList.query(withCustomer: \"my_customer\")\r\n        \r\n        directoryService.executeQuery(query, completionHandler: { (ticket, directory, error) -> Void in\r\n            if let error = error {\r\n                print(\"\u63a5\u7d9a\u30a8\u30e9\u30fc\u304c\u767a\u751f..\\(error)\")\r\n                self.networkError = true\r\n                \r\n            } else {\r\n                print(\"\u4f1a\u8b70\u5ba4\u3092\u53d6\u5f97\u3057\u307e\u3059\")\r\n                if let directory = directory as? GTLRDirectory_CalendarResources, let items = directory.items {\r\n                    self.resourceList.removeAll() \/\/\u73fe\u72b6\u306e\u30ea\u30b9\u30c8\u3092\u521d\u671f\u5316\r\n                    \r\n                    for item in items {\r\n                        let rid:  String = item.resourceId ?? \"\"\r\n                        let name: String = item.resourceName ?? \"\"\r\n                        let mail: String = item.resourceEmail ?? \"\"\r\n                        self.resourceList.append(Resource(rid:rid,name:name,mail:mail)) \/\/\u4f1a\u8b70\u5ba4\u914d\u5217\u306b\u4fdd\u7ba1\r\n                        print(\"\u4f1a\u8b70\u5ba4:\\(name),\\(mail)\")\r\n                    }\r\n                }\r\n            }\r\n            callBack(error)\r\n        })\r\n    }\r\n    \/\/Directory API\u3088\u308abraver\u5168\u54e1\u306e\u4e00\u89a7\u3092\u53d6\u5f97(\u4e88\u5b9a\u30c7\u30fc\u30bf\u306b\u3066\u6c0f\u540d\u304cnil\u306e\u30b1\u30fc\u30b9\u304c\u3042\u308b\u306e\u3067\u88dc\u5b8c\u306e\u305f\u3081)\r\n    private func setUsers(callBack: @escaping callBackAlias) {\r\n        print(\"\u5168User\u53d6\u5f97\u306e\u305f\u3081\u3001Directory\u306b\u63a5\u7d9a\u3057\u307e\u3059\")\r\n        let directoryService = GTLRDirectoryService()\r\n        directoryService.authorizer = self.authorization\r\n        directoryService.shouldFetchNextPages = true\r\n        let query = GTLRDirectoryQuery_UsersList.query()\r\n        query.customer = \"my_customer\"\r\n        \r\n        directoryService.executeQuery(query, completionHandler: { (ticket, user, error) -> Void in\r\n            if let error = error {\r\n                print(\"\u63a5\u7d9a\u30a8\u30e9\u30fc\u304c\u767a\u751f..\\(error)\")\r\n                self.networkError = true\r\n            } else {\r\n                print(\"\u5168User\u3092\u53d6\u5f97\u3057\u307e\u3059\")\r\n                if let user = user as? GTLRDirectory_Users, let items = user.users {\r\n                    self.userList.removeAll() \/\/\u73fe\u72b6\u306e\u30ea\u30b9\u30c8\u3092\u521d\u671f\u5316\r\n                    \r\n                    for item in items {\r\n                        let mail: String = item.primaryEmail ?? \"\"\r\n                        let name: String = item.name?.fullName ?? \"\"\r\n                        self.userList[mail] = User(mail:mail,name:name) \/\/\u793e\u54e1\u30ea\u30b9\u30c8\u306b\u4fdd\u7ba1\r\n                        print(\"\u793e\u54e1:\\(name),\\(mail)\")\r\n                    }\r\n                }\r\n            }\r\n            callBack(error)\r\n        })\r\n    }\r\n    \r\n    \/\/\u6307\u5b9a\u3055\u308c\u305f\u30ab\u30ec\u30f3\u30c0\u30fc\uff08\u4f1a\u8b70\u5ba4\u30ab\u30ec\u30f3\u30c0\u30fc\uff09\u306b\u767b\u9332\u3055\u308c\u3066\u3044\u308bEvent\u3088\u308abraver\u3092\u62bd\u51fa\u3057\u30ea\u30b9\u30c8\u3078\u30bb\u30c3\u30c8\u3059\u308b\r\n    private func setBraverByCalendar(calendarId:String, startDateTime: Date, endDateTime: Date) {\r\n        \r\n        \/\/Google CalenderAPI\u3078\u63a5\u7d9a\r\n        print(\"\u30ab\u30ec\u30f3\u30c0\u30fc\u306b\u63a5\u7d9a\u3057\u307e\u3059\uff01\")\r\n        let calendarService = GTLRCalendarService()\r\n        calendarService.authorizer = self.authorization\r\n        calendarService.shouldFetchNextPages = true\r\n        let query = GTLRCalendarQuery_EventsList.query(withCalendarId: calendarId)\r\n        query.timeMin = GTLRDateTime(date: startDateTime)\r\n        query.timeMax = GTLRDateTime(date: endDateTime)\r\n        \r\n        calendarService.executeQuery(query, completionHandler: { (ticket, event, error) -> Void in\r\n            if let error = error {\r\n                print(\"\\(error)\")\r\n            } else {\r\n                if let event = event as? GTLRCalendar_Events, let items = event.items {\r\n                    \/\/\u4f1a\u8b70\u5ba4\u306e\u4e88\u5b9a\u306b\u542b\u307e\u308c\u308b\u3059\u3079\u3066\u306e\u53c2\u52a0\u8005\u3092\u30c1\u30a7\u30c3\u30af\u3057\u3066\u3044\u304f\r\n                    for item in items {\r\n                        \r\n                        \/\/dump(\"dump item attendee...\\(item.attendees)\")\r\n                        let name: String = item.summary ?? \"\"\r\n                        let startDate: Date? = item.start?.dateTime?.date\r\n                        let location: String = item.location ?? \"\"\r\n                        \r\n                        if startDate == nil {continue} \/\/\u65e5\u4ed8\u672a\u5165\u529b\u306f\u30b9\u30ad\u30c3\u30d7\r\n                        \r\n                        print(\"loc:\\(location),name:\\(name),\\(startDate!)\")\r\n                        \r\n                        if item.attendees != nil {\r\n                            item.attendees!.forEach({(attendee) in \/\/\u4e88\u5b9a\u304b\u3089\u5168\u53c2\u52a0\u8005\u306e\u62bd\u51fa\r\n                                if attendee.email != nil && self.userList.keys.contains(attendee.email!) {  \/\/\u793e\u54e1\u30ea\u30b9\u30c8\u306b\u5f53\u30e1\u30a2\u30c9\u304c\u306a\u3051\u308c\u3070\u975e\u793e\u54e1\u3068\u3057\u3066\u7121\u8996\r\n                                    \r\n                                    \/\/\u53c2\u52a0\u8005braver\u3092braverList\u914d\u5217\u3078\u767b\u9332\u3059\u308b (API\u30d0\u30b0\u3067\u6c0f\u540d\u304cnil\u306e\u30b1\u30fc\u30b9\u304c\u3042\u308b\u306e\u3067\u793e\u54e1\u30ea\u30b9\u30c8\u304b\u3089\u6307\u540d\u3092\u53d6\u5f97\r\n                                    self.setBraver(mail:attendee.email!, name:self.userList[attendee.email!]!.name, startDate:startDate!, location:name+\":\"+location)\r\n                                    print(\"attendee:\\(self.userList[attendee.email!]!.name),\\(attendee.email!),\\(location)\")\r\n                                }\r\n                            })\r\n                        }\r\n                        print(\"loc:\\(location),name:\\(name),\\(startDate!)\")\r\n                    }\r\n                }\r\n            }\r\n            \/\/\u76f4\u8fd1\u306e\u4e88\u5b9a\u8005\u307b\u3069\u4e0a\u306b\u8868\u793a\u3055\u305b\u308b\u305f\u3081\u3001Score\u3067\u6607\u9806\u30bd\u30fc\u30c8\r\n            self.braverList.sort(by: {$0.score < $1.score})\r\n        })\r\n    }\r\n    \r\n    \/\/\u540d\u524d\u3068\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\u3092braverList\u306b\u767b\u9332\u3057\u3066\u3044\u304f\u3002\u91cd\u8907\u306f\u6392\u9664\u3002\r\n    private func setBraver(mail:String, name:String, startDate:Date, location:String){\r\n        \r\n        let replacedName:String = name.replacingOccurrences(of:\"(bravesoft)\", with:\"\") \/\/(bravesoft)\u3092\u6d88\u3059\r\n        let score:Int = abs(Int(nowDate.timeIntervalSince(startDate))) \/\/\u73fe\u5728\u6642\u523b\u3068\u4e88\u5b9a\u65e5\u6642\u306e\u5dee\u5206\u3002\u30b9\u30b3\u30a2\u304c\u5c0f\u3055\u3044\u307b\u3069\u76f4\u8fd1\u306a\u306e\u3067\u512a\u5148\u8868\u793a\r\n        var braverIndex:Int? = searchBraverIndex(mail:mail, braverArray:self.braverList) \/\/\u914d\u5217\u5185\u306b\u65e2\u306b\u5b58\u5728\u3059\u308bbraver\u304b\u5224\u5b9a\r\n        print(\"set\u3057\u307e\u3059..name:\\(name),startDate:\\(startDate),location:\\(location),score:\\(score)\")\r\n        \r\n        \/\/\u65e2\u306b\u5b58\u5728\u3059\u308b\u5834\u5408\u3067\u3001score\u5224\u5b9a\u306b\u3088\u308a\u3088\u308a\u76f4\u8fd1\u306e\u4e88\u5b9a\u306a\u3089\u4e88\u5b9a\u65e5\u6642\u3092\u4e0a\u66f8\u304d\u3002\u5b58\u5728\u3057\u306a\u3044\u306a\u3089\u914d\u5217\u306b\u8ffd\u52a0\u3059\u308b\r\n        if braverIndex != nil {\r\n            if(self.braverList[braverIndex!].score > score){\r\n                print(\"braver\u3092\u3088\u308a\u76f4\u8fd1\u3068\u3057\u3066\u4e0a\u66f8\u304d\u3057\u307e\u3059..name:\\(name),startDate:\\(startDate),location:\\(location),score:\\(score)\")\r\n                self.braverList[braverIndex!].startDate = startDate\r\n                self.braverList[braverIndex!].score     = score\r\n                self.braverList[braverIndex!].location  = location \/\/\u4f1a\u8b70\u5ba4\u306e\u5834\u6240\u3082\u76f4\u8fd1\u306e\u4e88\u6e2c\u3068\u3057\u3066\u4fdd\u5b58\r\n            }\r\n        }\r\n        else{\r\n            print(\"braver\u3092\u767b\u9332\u3057\u307e\u3059..name:\\(name),startDate:\\(startDate),location:\\(location),score:\\(score)\")\r\n            \/\/\u53d6\u5f97\u3057\u305fbraver\u60c5\u5831\u3092\u683c\u7d0d\u3002(\u30b5\u30e0\u30cd\u30a4\u30eb\u306f\u4e00\u65e6\u30c7\u30d5\u30a9\u30eb\u30c8\u753b\u50cf.\u5f8c\u3067\u5dee\u3057\u66ff\u3048\u308b)\r\n            let braver = Braver(mail:mail, name:replacedName, startDate:startDate, score:score, location:location, image:UIImage(named:\"defaultuser\"))\r\n            braverIndex = self.braverList.count  \/\/setBraverImage\u306b\u3053\u306ebraver\u306e\u914d\u5217\u4e0a\u306e\u4f4d\u7f6e\u3092\u4f1d\u3048\u308b\r\n            self.braverList.append(braver)\r\n        }\r\n        setBraverImage(mail:mail)  \/\/braver\u306e\u30b5\u30e0\u30cd\u30a4\u30eb\u753b\u50cf\u3092\u53d6\u5f97\u3057\u3066braverList\u914d\u5217\u3078\u30bb\u30c3\u30c8\u3059\u308b\r\n    }\r\n    \r\n    \/\/\u914d\u5217\u5185\u306e\u69cb\u9020\u4f53\u306b\u3001\u7279\u5b9a\u306email\u306e\u5024\u304c\u3059\u3067\u306b\u5b58\u5728\u3059\u308b\u304b\u30c1\u30a7\u30c3\u30af\r\n    func searchBraverIndex(mail: String, braverArray: [Braver]) -> Int? {\r\n        return braverArray.firstIndex { $0.mail == mail }\r\n    }\r\n    \r\n    \/\/braver\u306e\u30b5\u30e0\u30cd\u753b\u50cf\u3092\u53d6\u5f97\u3057\u3066\u30bb\u30c3\u30c8.API\u7684\u306bbraver\u305d\u308c\u305e\u308c1\u4ef6\u305a\u3064\u53d6\u5f97\u3057\u3066\u30bb\u30c3\u30c8\u3057\u3066\u3044\u304f\r\n    func setBraverImage(mail:String){\r\n        print(\"\u30e6\u30fc\u30b6\u753b\u50cf\u3092\u53d6\u5f97\u3057\u307e\u3059:\\(mail)\")\r\n        let directoryService = GTLRDirectoryService()\r\n        directoryService.authorizer = self.authorization\r\n        directoryService.shouldFetchNextPages = true\r\n        let query = GTLRDirectoryQuery_UsersPhotosGet.query(withUserKey: mail)\r\n        \r\n        directoryService.executeQuery(query, completionHandler: { (ticket, directory, error) -> Void in\r\n            if let error = error {\r\n                if error.localizedDescription.starts(with:\"Resource Not Found\") {\r\n                    print(\"\u753b\u50cf\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093(404)\")  \/\/\u753b\u50cf\u304c\u7121\u3044\u3068404\u304c\u8fd4\u3055\u308c\u308b\u304c\u3001\u30a8\u30e9\u30fc\u51e6\u7406\u306b\u306f\u3057\u306a\u3044\r\n                }\r\n                else{\r\n                    print(\"\u63a5\u7d9a\u30a8\u30e9\u30fc\u304c\u767a\u751f..\\(error)\")\r\n                    self.networkError = true\r\n                }\r\n            } else {\r\n                print(\"\u30e6\u30fc\u30b6\u753b\u50cf\u3092\u53d6\u5f97\u3057\u307e\u3059\")\r\n                if let directory = directory as? GTLRDirectory_UserPhoto, let photo = directory.photoData {\r\n                    var urlSafePhoto = photo.replacingOccurrences(of: \"-\", with: \"+\")  \/\/URL Safe\u3092\u89e3\u9664\u3057\u305fBase64\u6587\u5b57\u5217\u306b\u5909\u63db\r\n                    urlSafePhoto     = urlSafePhoto.replacingOccurrences(of: \"_\", with: \"\/\")\r\n                    let imageData = Data(base64Encoded: urlSafePhoto)\r\n                    let braverIndex:Int! = self.searchBraverIndex(mail:mail, braverArray:self.braverList) \/\/\u3053\u306ebraver\u306e\u5834\u6240\u3092\u63a2\u3059\r\n                    self.braverList[braverIndex!].image = UIImage(data:imageData!)!  \/\/\u914d\u5217\u5185\u306b\u65e2\u306b\u5b58\u5728\u3059\u308bbraver\u304b\u5224\u5b9a\r\n                }\r\n            }\r\n        })\r\n    }\r\n}\r\n<\/pre>\n<p>\u4ee5\u4e0a2\u3064\u306e\u4e3b\u306aSwift\u30d5\u30a1\u30a4\u30eb\u3060\u3051\u3067\u53d7\u4ed8\u30a2\u30d7\u30ea\u304c\u51fa\u6765\u3066\u3001100\u4e07\u5186\u306e\u4fa1\u5024\u3092\u767a\u63ee\u3059\u308b\u3002<\/p>\n<p>Enjoy!<\/p>\n<p><a href=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/new\u53d7\u4ed83.jpg?ssl=1\" target=\"_blank\" rel=\"noopener noreferrer\"><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"2942\" data-permalink=\"https:\/\/bravesoft.co.jp\/seblog\/archives\/2826\/new%e5%8f%97%e4%bb%983\" data-orig-file=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/new\u53d7\u4ed83.jpg?fit=2028%2C1352&amp;ssl=1\" data-orig-size=\"2028,1352\" data-comments-opened=\"0\" data-image-meta=\"{&quot;aperture&quot;:&quot;9&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;ILCE-7M3&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;1623046540&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;45&quot;,&quot;iso&quot;:&quot;1600&quot;,&quot;shutter_speed&quot;:&quot;0.016666666666667&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;1&quot;}\" data-image-title=\"new\u53d7\u4ed83\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/new\u53d7\u4ed83.jpg?fit=300%2C200&amp;ssl=1\" data-large-file=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/new\u53d7\u4ed83.jpg?fit=700%2C467&amp;ssl=1\" tabindex=\"0\" role=\"button\" src=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/new\u53d7\u4ed83.jpg?resize=700%2C467&#038;ssl=1\" alt=\"\" width=\"700\" height=\"467\" class=\"aligncenter size-full wp-image-2942\" srcset=\"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/new\u53d7\u4ed83.jpg?w=2028&amp;ssl=1 2028w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/new\u53d7\u4ed83.jpg?resize=300%2C200&amp;ssl=1 300w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/new\u53d7\u4ed83.jpg?resize=700%2C467&amp;ssl=1 700w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/new\u53d7\u4ed83.jpg?resize=768%2C512&amp;ssl=1 768w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/new\u53d7\u4ed83.jpg?resize=1536%2C1024&amp;ssl=1 1536w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/new\u53d7\u4ed83.jpg?resize=800%2C533&amp;ssl=1 800w, https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/new\u53d7\u4ed83.jpg?w=1400&amp;ssl=1 1400w\" sizes=\"(max-width: 700px) 100vw, 700px\" data-recalc-dims=\"1\" \/><\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u793e\u9577\u306e\u3084\u308b\u3079\u304d\u4ed5\u4e8b\u306f\u5e45\u5e83\u3044\u3002 \u6700\u8fd1\u3001\u3064\u3044\u306b\u6211\u304c\u793e\u3082NTT\u96fb\u8a71\u304c\u65ad\u820e\u96e2\u3055\u308c\u308b\u3053\u3068\u306b\u306a\u3063\u305f\u3002 \u30b3\u30b9\u30c8\u524a\u6e1b\u306f\u826f\u3044\u3053\u3068\u306a\u304c\u3089\u3001\u793e\u5185\u304b\u3089\u3053\u3093\u306a\u58f0\u304c\u30fb\u30fb \u300c\u793e\u9577\uff01\u53d7\u4ed8\u96fb\u8a71\u304c\u7121\u304f\u306a\u308b\u304b\u3089\u6d41\u884c\u308a\u306e\u53d7\u4ed8\u30a2\u30d7\u30ea\uff08100\u4e07\u5186\u3050\u3089\u3044\uff09\u5c0e\u5165\u3057\u307e\u3059&#8230;<\/p>\n","protected":false},"author":1,"featured_media":2941,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false},"version":2}},"categories":[8,4],"tags":[],"class_list":["post-2826","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-gijyutu","category-keiei"],"jetpack_publicize_connections":[],"aioseo_notices":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/bravesoft.co.jp\/seblog\/wp-content\/uploads\/2021\/06\/new\u53d7\u4ed811.jpg?fit=540%2C360&ssl=1","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p7fAdy-JA","jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/bravesoft.co.jp\/seblog\/wp-json\/wp\/v2\/posts\/2826"}],"collection":[{"href":"https:\/\/bravesoft.co.jp\/seblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bravesoft.co.jp\/seblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bravesoft.co.jp\/seblog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/bravesoft.co.jp\/seblog\/wp-json\/wp\/v2\/comments?post=2826"}],"version-history":[{"count":108,"href":"https:\/\/bravesoft.co.jp\/seblog\/wp-json\/wp\/v2\/posts\/2826\/revisions"}],"predecessor-version":[{"id":3514,"href":"https:\/\/bravesoft.co.jp\/seblog\/wp-json\/wp\/v2\/posts\/2826\/revisions\/3514"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/bravesoft.co.jp\/seblog\/wp-json\/wp\/v2\/media\/2941"}],"wp:attachment":[{"href":"https:\/\/bravesoft.co.jp\/seblog\/wp-json\/wp\/v2\/media?parent=2826"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bravesoft.co.jp\/seblog\/wp-json\/wp\/v2\/categories?post=2826"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bravesoft.co.jp\/seblog\/wp-json\/wp\/v2\/tags?post=2826"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}