αž€αžΆαžšαž”αž„αŸ’αž€αžΎαžαž’αŸ’αž“αž€αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹ Google αž–αžΈ PowerShell αžαžΆαž˜αžšαž™αŸˆ API

αž‡αŸ†αžšαžΆαž”αžŸαž½αžš!

αž’αžαŸ’αžαž”αž‘αž“αŸαŸ‡αž“αžΉαž„αž–αž·αž–αžŽαŸŒαž“αžΆαž’αŸ†αž–αžΈαž€αžΆαžšαž’αž“αž»αžœαžαŸ’αžαž’αž“αŸ’αžαžšαž€αž˜αŸ’αž˜ PowerShell αž‡αžΆαž˜αž½αž™ Google API αžŠαžΎαž˜αŸ’αž”αžΈαžšαŸ€αž”αž…αŸ†αž’αŸ’αž“αž€αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹ G Suite αŸ”

αž™αžΎαž„αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αžŸαŸαžœαžΆαž€αž˜αŸ’αž˜αžαžΆαž„αž€αŸ’αž“αž»αž„ αž“αž·αž„αž–αž–αž€αž‡αžΆαž…αŸ’αžšαžΎαž“αž“αŸ…αž‘αžΌαž‘αžΆαŸ†αž„αžŸαŸ’αžαžΆαž”αŸαž“αŸ” αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž•αŸ’αž“αŸ‚αž€αž—αžΆαž‚αž…αŸ’αžšαžΎαž“ αž€αžΆαžšαž’αž“αž»αž‰αŸ’αž‰αžΆαžαž“αŸ…αž€αŸ’αž“αž»αž„αž–αž½αž€αžœαžΆαž˜αž€αž›αžΎ Google ឬ Active Directory αžŠαŸ‚αž›αžšαžœαžΆαž„αž™αžΎαž„αž˜αž·αž“αž’αžΆαž…αžšαž€αŸ’αžŸαžΆαž€αžΆαžšαž…αž˜αŸ’αž›αž„αž”αžΆαž“αž‘αŸ αž’αžΆαžŸαŸ’αžšαŸαž™αž αŸαžαž»αž“αŸαŸ‡ αž“αŸ…αž–αŸαž›αžŠαŸ‚αž›αž”αž»αž‚αŸ’αž‚αž›αž·αž€αžαŸ’αž˜αžΈαž…αžΆαž€αž…αŸαž‰ αž’αŸ’αž“αž€αžαŸ’αžšαžΌαžœαž”αž„αŸ’αž€αžΎαž/αž”αžΎαž€αž‚αžŽαž“αžΈαž“αŸ…αž€αŸ’αž“αž»αž„αž”αŸ’αžšαž–αŸαž“αŸ’αž’αž‘αžΆαŸ†αž„αž–αžΈαžšαž“αŸαŸ‡αŸ” αžŠαžΎαž˜αŸ’αž”αžΈαž’αŸ’αžœαžΎαž±αŸ’αž™αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžŠαŸ„αž™αžŸαŸ’αžœαŸαž™αž”αŸ’αžšαžœαžαŸ’αžαž· αž™αžΎαž„αž”αžΆαž“αžŸαž˜αŸ’αžšαŸαž…αž…αž·αžαŸ’αžαžŸαžšαžŸαŸαžšαžŸαŸ’αž‚αŸ’αžšαžΈαž”αžŠαŸ‚αž›αž”αŸ’αžšαž˜αžΌαž›αž–αŸαžαŸŒαž˜αžΆαž“ αž αžΎαž™αž•αŸ’αž‰αžΎαžœαžΆαž‘αŸ…αžŸαŸαžœαžΆαž€αž˜αŸ’αž˜αž‘αžΆαŸ†αž„αž–αžΈαžšαŸ”

αž€αžΆαžšαž’αž“αž»αž‰αŸ’αž‰αžΆαž

αž“αŸ…αž–αŸαž›αž”αž„αŸ’αž€αžΎαžαž›αž€αŸ’αžαžαžŽαŸ’αžŒαžαž˜αŸ’αžšαžΌαžœ αž™αžΎαž„αž”αžΆαž“αžŸαž˜αŸ’αžšαŸαž…αž…αž·αžαŸ’αžαž”αŸ’αžšαžΎαž’αŸ’αž“αž€αž‚αŸ’αžšαž”αŸ‹αž‚αŸ’αžšαž„αž˜αž“αž»αžŸαŸ’αžŸαž–αž·αžαž”αŸ’αžšαžΆαž€αžŠαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαž’αž“αž»αž‰αŸ’αž‰αžΆαž αž“αŸαŸ‡αž’αŸ’αžœαžΎαž±αŸ’αž™αž€αžΆαžšαžœαž·αž—αžΆαž‚αžŸαž€αž˜αŸ’αž˜αž—αžΆαž–αž˜αžΆαž“αž—αžΆαž–αž„αžΆαž™αžŸαŸ’αžšαž½αž›αž€αŸ’αž“αž»αž„αž€αžšαžŽαžΈαž˜αžΆαž“αž€αžΆαžšαž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžšαžŠαŸαž’αŸ†αžŠαŸ„αž™αž…αŸƒαžŠαž“αŸ’αž™ αž¬αžŠαŸ„αž™αž…αŸαžαž“αžΆαŸ”

Google APIs αž”αŸ’αžšαžΎαž–αž·αž’αžΈαž€αžΆαžš OAuth 2.0 αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαž•αŸ’αž‘αŸ€αž„αž•αŸ’αž‘αžΆαžαŸ‹ αž“αž·αž„αž€αžΆαžšαž’αž“αž»αž‰αŸ’αž‰αžΆαžαŸ” αž€αžšαžŽαžΈαž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹ αž“αž·αž„αž€αžΆαžšαž–αž·αž–αžŽαŸŒαž“αžΆαž›αž˜αŸ’αž’αž·αžαž”αž“αŸ’αžαŸ‚αž˜αž‘αŸ€αžαž’αžΆαž…αžšαž€αž”αžΆαž“αž“αŸ…αž‘αžΈαž“αŸαŸ‡αŸ– αž€αžΆαžšαž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹ OAuth 2.0 αžŠαžΎαž˜αŸ’αž”αžΈαž…αžΌαž›αž”αŸ’αžšαžΎ Google APIs.

αžαŸ’αž‰αž»αŸ†αž”αžΆαž“αž‡αŸ’αžšαžΎαžŸαžšαžΎαžŸαžŸαŸ’αž‚αŸ’αžšαžΈαž”αžŠαŸ‚αž›αž”αŸ’αžšαžΎαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαž’αž“αž»αž‰αŸ’αž‰αžΆαžαž€αŸ’αž“αž»αž„αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž€αž»αŸ†αž–αŸ’αž™αžΌαž‘αŸαžšαŸ” αžœαžΆαž€αŸαž˜αžΆαž“αž‡αž˜αŸ’αžšαžΎαžŸαž€αŸ’αž“αž»αž„αž€αžΆαžšαž”αŸ’αžšαžΎαž‚αžŽαž“αžΈαžŸαŸαžœαžΆαž€αž˜αŸ’αž˜αž•αž„αžŠαŸ‚αžš αžŠαŸ‚αž›αž˜αž·αž“αžαž˜αŸ’αžšαžΌαžœαž±αŸ’αž™αž˜αžΆαž“αž…αž›αž“αžΆαžŠαŸ‚αž›αž˜αž·αž“αž…αžΆαŸ†αž”αžΆαž…αŸ‹αž–αžΈαž’αŸ’αž“αž€αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αŸ”

αžšαžΌαž”αž—αžΆαž–αžαžΆαž„αž€αŸ’αžšαŸ„αž˜αž‚αžΊαž‡αžΆαž€αžΆαžšαž–αž·αž–αžŽαŸŒαž“αžΆαž‚αŸ’αžšαŸ„αž„αž€αžΆαžšαžŽαŸαž“αŸƒαžŸαŸαžŽαžΆαžšαžΈαž™αŸ‰αžΌαžŠαŸ‚αž›αž”αžΆαž“αž‡αŸ’αžšαžΎαžŸαžšαžΎαžŸαž–αžΈαž‘αŸ†αž–αŸαžš Google αŸ”

αž€αžΆαžšαž”αž„αŸ’αž€αžΎαžαž’αŸ’αž“αž€αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹ Google αž–αžΈ PowerShell αžαžΆαž˜αžšαž™αŸˆ API

  1. αžŠαŸ†αž”αžΌαž„ αž™αžΎαž„αž”αž‰αŸ’αž‡αžΌαž“αž’αŸ’αž“αž€αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αž‘αŸ…αž€αžΆαž“αŸ‹αž‘αŸ†αž–αŸαžšαž•αŸ’αž‘αŸ€αž„αž•αŸ’αž‘αžΆαžαŸ‹αž‚αžŽαž“αžΈ Google αžŠαŸ„αž™αž”αž‰αŸ’αž‡αžΆαž€αŸ‹αž”αŸ‰αžΆαžšαŸ‰αžΆαž˜αŸ‰αŸ‚αžαŸ’αžš GETαŸ–
    • αž›αŸαžαžŸαž˜αŸ’αž‚αžΆαž›αŸ‹αž€αž˜αŸ’αž˜αžœαž·αž’αžΈ
    • αžαŸ†αž”αž“αŸ‹αžŠαŸ‚αž›αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžαŸ’αžšαžΌαžœαž€αžΆαžšαž…αžΌαž›αž”αŸ’αžšαžΎ
    • αž’αžΆαžŸαž™αžŠαŸ’αž‹αžΆαž“αžŠαŸ‚αž›αž’αŸ’αž“αž€αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αž“αžΉαž„αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž‰αŸ’αž‡αžΌαž“αž”αž“αŸ’αžαž”αž“αŸ’αž‘αžΆαž”αŸ‹αž–αžΈαž”αž‰αŸ’αž…αž”αŸ‹αž“αžΈαžαž·αžœαž·αž’αžΈ
    • αžœαž·αž’αžΈαžŠαŸ‚αž›αž™αžΎαž„αž“αžΉαž„αž’αŸ’αžœαžΎαž”αž…αŸ’αž…αž»αž”αŸ’αž”αž“αŸ’αž“αž—αžΆαž–αž“αž·αž˜αž·αžαŸ’αžαžŸαž‰αŸ’αž‰αžΆ
    • αž›αŸαžαžŸαŸ†αž„αžΆαžαŸ‹
    • αž‘αž˜αŸ’αžšαž„αŸ‹αž”αž‰αŸ’αž‡αžΌαž“αž€αžΌαžŠαž•αŸ’αž‘αŸ€αž„αž•αŸ’αž‘αžΆαžαŸ‹

  2. αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž–αžΈαž€αžΆαžšαž’αž“αž»αž‰αŸ’αž‰αžΆαžαžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž‰αŸ’αž…αž”αŸ‹ αž’αŸ’αž“αž€αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αž“αžΉαž„αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž‰αŸ’αž‡αžΌαž“αž”αž“αŸ’αžαž‘αŸ…αž€αžΆαž“αŸ‹αž‘αŸ†αž–αŸαžšαžŠαŸ‚αž›αž”αžΆαž“αž”αž‰αŸ’αž‡αžΆαž€αŸ‹αž“αŸ…αž€αŸ’αž“αž»αž„αžŸαŸ†αžŽαžΎαžŠαŸ†αž”αžΌαž„αžŠαŸ„αž™αž˜αžΆαž“αž€αŸ†αž αž»αžŸ αž¬αž›αŸαžαž€αžΌαžŠαž’αž“αž»αž‰αŸ’αž‰αžΆαžαžŠαŸ‚αž›αž”αžΆαž“αž†αŸ’αž›αž„αž€αžΆαžαŸ‹αžŠαŸ„αž™αž”αŸ‰αžΆαžšαŸ‰αžΆαž˜αŸ‰αŸ‚αžαŸ’αžš GET
  3. αž€αž˜αŸ’αž˜αžœαž·αž’αžΈ (αžŸαŸ’αž‚αŸ’αžšαžΈαž”) αž“αžΉαž„αžαŸ’αžšαžΌαžœαž€αžΆαžšαž‘αž‘αž½αž›αž”αŸ‰αžΆαžšαŸ‰αžΆαž˜αŸ‰αŸ‚αžαŸ’αžšαž‘αžΆαŸ†αž„αž“αŸαŸ‡ αž αžΎαž™αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž”αžΆαž“αž‘αž‘αž½αž›αž›αŸαžαž€αžΌαžŠ αžŸαžΌαž˜αž’αŸ’αžœαžΎαž€αžΆαžšαžŸαŸ’αž“αžΎαžŸαž»αŸ†αžαžΆαž„αž€αŸ’αžšαŸ„αž˜αžŠαžΎαž˜αŸ’αž”αžΈαž‘αž‘αž½αž›αž”αžΆαž“αžαžΌαžαžΉαž“
  4. αž”αŸ’αžšαžŸαž·αž“αž”αžΎαžŸαŸ†αžŽαžΎαž“αŸ„αŸ‡αžαŸ’αžšαžΉαž˜αžαŸ’αžšαžΌαžœ Google API αžαŸ’αžšαž‘αž”αŸ‹αž˜αž€αžœαž·αž‰αŸ–
    • αžŸαž‰αŸ’αž‰αžΆαžŸαž˜αŸ’αž„αžΆαžαŸ‹αž…αžΌαž›αž”αŸ’αžšαžΎ αžŠαŸ‚αž›αž™αžΎαž„αž’αžΆαž…αž’αŸ’αžœαžΎαž€αžΆαžšαžŸαŸ’αž“αžΎαžŸαž»αŸ†αž”αžΆαž“αŸ”
    • αžšαž™αŸˆαž–αŸαž›αžŸαž»αž–αž›αž—αžΆαž–αž“αŸƒαžŸαž‰αŸ’αž‰αžΆαžŸαž˜αŸ’αž„αžΆαžαŸ‹αž“αŸαŸ‡αŸ”
    • αžαž˜αŸ’αžšαžΌαžœβ€‹αž±αŸ’αž™β€‹αž•αŸ’αž‘αž»αž€β€‹αžŸαž‰αŸ’αž‰αžΆβ€‹αžŸαž˜αŸ’αž„αžΆαžαŸ‹β€‹αž‘αžΎαž„αžœαž·αž‰ αžŠαžΎαž˜αŸ’αž”αžΈβ€‹αž•αŸ’αž‘αž»αž€β€‹αžŸαž‰αŸ’αž‰αžΆβ€‹αž…αžΌαž›β€‹αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšβ€‹αž‘αžΎαž„αžœαž·αž‰αŸ”

αžŠαŸ†αž”αžΌαž„αž’αŸ’αž“αž€αžαŸ’αžšαžΌαžœαž…αžΌαž›αž‘αŸ…αž€αžΆαž“αŸ‹αž€αž»αž„αžŸαžΌαž› Google APIαŸ– αž›αž·αžαž·αžαžŸαž˜αŸ’αž‚αžΆαž›αŸ‹ - Google API Consoleαž‡αŸ’αžšαžΎαžŸαžšαžΎαžŸαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžŠαŸ‚αž›αž…αž„αŸ‹αž”αžΆαž“ αž αžΎαž™αž“αŸ…αž€αŸ’αž“αž»αž„αž•αŸ’αž“αŸ‚αž€ Credentials αž”αž„αŸ’αž€αžΎαžαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž€αŸ†αžŽαžαŸ‹αž’αžαŸ’αžαžŸαž‰αŸ’αž‰αžΆαžŽ OAuth αžšαž”αžŸαŸ‹αž’αžαž·αžαž·αž‡αž“αŸ” αž“αŸ…αž‘αžΈαž“αŸ„αŸ‡ (αž¬αž“αŸ…αž–αŸαž›αž€αŸ’αžšαŸ„αž™αž“αŸ…αž€αŸ’αž“αž»αž„αž›αž€αŸ’αžαžŽαŸˆαžŸαž˜αŸ’αž”αžαŸ’αžαž·αž“αŸƒαž€αžΆαžšαž€αŸ†αžŽαžαŸ‹αž’αžαŸ’αžαžŸαž‰αŸ’αž‰αžΆαžŽαžŠαŸ‚αž›αž”αžΆαž“αž”αž„αŸ’αž€αžΎαž) β€‹β€‹αž’αŸ’αž“αž€αžαŸ’αžšαžΌαžœαž”αž‰αŸ’αž‡αžΆαž€αŸ‹αž’αžΆαžŸαž™αžŠαŸ’αž‹αžΆαž“αžŠαŸ‚αž›αž€αžΆαžšαž”αž‰αŸ’αž‡αžΌαž“αž”αž“αŸ’αžαžαŸ’αžšαžΌαžœαž”αžΆαž“αž’αž“αž»αž‰αŸ’αž‰αžΆαžαŸ” αž€αŸ’αž“αž»αž„αž€αžšαžŽαžΈαžšαž”αžŸαŸ‹αž™αžΎαž„ αž‘αžΆαŸ†αž„αž“αŸαŸ‡αž“αžΉαž„αž‡αžΆαž’αžΆαžαž»αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž€αŸ’αž“αž»αž„αžŸαŸ’αžšαž»αž€αž‡αžΆαž…αŸ’αžšαžΎαž“αžŠαŸ‚αž›αž˜αžΆαž“αž…αŸ’αžšαž€αž•αŸ’αžŸαŸαž„αŸ—αž‚αŸ’αž“αžΆ (αžŸαžΌαž˜αž˜αžΎαž›αžαžΆαž„αž€αŸ’αžšαŸ„αž˜)αŸ”

αžŠαžΎαž˜αŸ’αž”αžΈαž’αŸ’αžœαžΎαž±αŸ’αž™αžœαžΆαž€αžΆαž“αŸ‹αžαŸ‚αž„αžΆαž™αžŸαŸ’αžšαž½αž›αž€αŸ’αž“αž»αž„αž€αžΆαžšαž’αžΆαž“αž€αŸ’αž”αž½αž“αžŠαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αžŸαŸ’αž‚αŸ’αžšαžΈαž” αž’αŸ’αž“αž€αž’αžΆαž…αž”αž„αŸ’αž αžΆαž‰αž‡αŸ†αž αžΆαž“αžŠαŸ†αž”αžΌαž„αž“αŸ…αž€αŸ’αž“αž»αž„αž˜αž»αžαž„αžΆαžšαžŠαžΆαž…αŸ‹αžŠαŸ„αž™αž‘αŸ‚αž€αžŠαŸ‚αž›αž“αžΉαž„αžαŸ’αžšαž‘αž”αŸ‹αž€αžΆαžšαž…αžΌαž›αž”αŸ’αžšαžΎ αž“αž·αž„αž’αŸ’αžœαžΎαž±αŸ’αž™αžαžΌαžαžΉαž“αžŸαŸ’αžšαžŸαŸ‹αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαŸ–

$client_secret = 'Our Client Secret'
$client_id = 'Our Client ID'
function Get-GoogleAuthToken {
  if (-not [System.Net.HttpListener]::IsSupported) {
    "HttpListener is not supported."
    exit 1
  }
  $codeverifier = -join ((65..90) + (97..122) + (48..57) + 45 + 46 + 95 + 126 |Get-Random -Count 60| % {[char]$_})
  $hasher = new-object System.Security.Cryptography.SHA256Managed
  $hashByteArray = $hasher.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($codeverifier))
  $base64 = ((([System.Convert]::ToBase64String($hashByteArray)).replace('=','')).replace('+','-')).replace('/','_')
  $ports = @(10600,15084,39700,42847,65387,32079)
  $port = $ports[(get-random -Minimum 0 -maximum 5)]
  Write-Host "Start browser..."
  Start-Process "https://accounts.google.com/o/oauth2/v2/auth?code_challenge_method=S256&code_challenge=$base64&access_type=offline&client_id=$client_id&redirect_uri=http://localhost:$port&response_type=code&scope=https://www.googleapis.com/auth/admin.directory.user https://www.googleapis.com/auth/admin.directory.group"
  $listener = New-Object System.Net.HttpListener
  $listener.Prefixes.Add("http://localhost:"+$port+'/')
  try {$listener.Start()} catch {
    "Unable to start listener."
    exit 1
  }
  while (($code -eq $null)) {
    $context = $listener.GetContext()
    Write-Host "Connection accepted" -f 'mag'
    $url = $context.Request.RawUrl
    $code = $url.split('?')[1].split('=')[1].split('&')[0]
    if ($url.split('?')[1].split('=')[0] -eq 'error') {
      Write-Host "Error!"$code -f 'red'
      $buffer = [System.Text.Encoding]::UTF8.GetBytes("Error!"+$code)
      $context.Response.ContentLength64 = $buffer.Length
      $context.Response.OutputStream.Write($buffer, 0, $buffer.Length)
      $context.Response.OutputStream.Close()
      $listener.Stop()
      exit 1
    }
    $buffer = [System.Text.Encoding]::UTF8.GetBytes("Now you can close this browser tab.")
    $context.Response.ContentLength64 = $buffer.Length
    $context.Response.OutputStream.Write($buffer, 0, $buffer.Length)
    $context.Response.OutputStream.Close()
    $listener.Stop()
  }
  Return Invoke-RestMethod -Method Post -Uri "https://www.googleapis.com/oauth2/v4/token" -Body @{
    code = $code
    client_id = $client_id
    client_secret = $client_secret
    redirect_uri = 'http://localhost:'+$port
    grant_type = 'authorization_code'
    code_verifier   = $codeverifier
  }
  $code = $null

αž™αžΎαž„αž€αŸ†αžŽαžαŸ‹αž›αŸαžαžŸαž˜αŸ’αž‚αžΆαž›αŸ‹αž’αžαž·αžαž·αž‡αž“ αž“αž·αž„αžŸαž˜αŸ’αž„αžΆαžαŸ‹αž’αžαž·αžαž·αž‡αž“αžŠαŸ‚αž›αž‘αž‘αž½αž›αž”αžΆαž“αž€αŸ’αž“αž»αž„αž›αž€αŸ’αžαžŽαŸˆαžŸαž˜αŸ’αž”αžαŸ’αžαž·αž€αŸ†αžŽαžαŸ‹αž’αžαŸ’αžαžŸαž‰αŸ’αž‰αžΆαžŽαž’αžαž·αžαž·αž‡αž“ OAuth αž αžΎαž™αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž•αŸ’αž‘αŸ€αž„αž•αŸ’αž‘αžΆαžαŸ‹αž€αžΌαžŠαž‚αžΊαž‡αžΆαžαŸ’αžŸαŸ‚αž’αž€αŸ’αžŸαžšαž–αžΈ 43 αž‘αŸ… 128 αžαž½αž’αž€αŸ’αžŸαžšαžŠαŸ‚αž›αžαŸ’αžšαžΌαžœαžαŸ‚αž”αž„αŸ’αž€αžΎαžαžŠαŸ„αž™αž…αŸƒαžŠαž“αŸ’αž™αž–αžΈαžαž½αž’αž€αŸ’αžŸαžšαžŠαŸ‚αž›αž˜αž·αž“αž”αžΆαž“αžšαž€αŸ’αžŸαžΆαž‘αž»αž€αŸ– [AZ] / [az] / [0-9] / "-" / "αŸ” / "_" / "~" αŸ”

αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€αž›αŸαžαž€αžΌαžŠαž“αŸαŸ‡αž“αžΉαž„αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž‰αŸ’αž‡αžΌαž“αž˜αŸ’αžαž„αž‘αŸ€αžαŸ” αžœαžΆαž›αž»αž”αž”αŸ†αž”αžΆαžαŸ‹αž—αžΆαž–αž„αžΆαž™αžšαž„αž‚αŸ’αžšαŸ„αŸ‡αžŠαŸ‚αž›αž’αŸ’αž“αž€αžœαžΆαž™αž”αŸ’αžšαž αžΆαžšαž’αžΆαž…αžŸαŸ’αž‘αžΆαž€αŸ‹αž…αžΆαž”αŸ‹αž€αžΆαžšαž†αŸ’αž›αžΎαž™αžαž”αžŠαŸ‚αž›αž”αžΆαž“αžαŸ’αžšαž‘αž”αŸ‹αž˜αž€αžœαž·αž‰αž‡αžΆαž€αžΆαžšαž”αž‰αŸ’αž‡αžΌαž“αž”αž“αŸ’αžαž”αž“αŸ’αž‘αžΆαž”αŸ‹αž–αžΈαž€αžΆαžšαž’αž“αž»αž‰αŸ’αž‰αžΆαžαž–αžΈαž’αŸ’αž“αž€αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αŸ”
αž’αŸ’αž“αž€αž’αžΆαž…αž•αŸ’αž‰αžΎαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž•αŸ’αž‘αŸ€αž„αž•αŸ’αž‘αžΆαžαŸ‹αž€αžΌαžŠαž€αŸ’αž“αž»αž„αžŸαŸ†αžŽαžΎαž”αž…αŸ’αž…αž»αž”αŸ’αž”αž“αŸ’αž“αž‡αžΆαž’αžαŸ’αžαž”αž‘αž…αŸ’αž”αžΆαžŸαŸ‹αž›αžΆαžŸαŸ‹ (αžŠαŸ‚αž›αž’αŸ’αžœαžΎαž±αŸ’αž™αžœαžΆαž‚αŸ’αž˜αžΆαž“αž“αŸαž™ - αž“αŸαŸ‡αž‚αžΊαžŸαž˜αžšαž˜αŸ’αž™αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αžαŸ‚αž”αŸ’αžšαž–αŸαž“αŸ’αž’αžŠαŸ‚αž›αž˜αž·αž“αž‚αžΆαŸ†αž‘αŸ’αžš SHA256) αž¬αžŠαŸ„αž™αž”αž„αŸ’αž€αžΎαž hash αžŠαŸ„αž™αž”αŸ’αžšαžΎαž€αŸ’αž”αž½αž“αžŠαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™ SHA256 αžŠαŸ‚αž›αžαŸ’αžšαžΌαžœαžαŸ‚αž”αž‰αŸ’αž…αžΌαž›αž€αžΌαžŠαž€αŸ’αž“αž»αž„ BASE64Url (αžαž»αžŸαž‚αŸ’αž“αžΆ αž–αžΈ Base64 αžŠαŸ„αž™αžαž½αž’αž€αŸ’αžŸαžšαžαžΆαžšαžΆαž„αž–αžΈαžš) αž“αž·αž„αžŠαž€αž…αŸαž‰αž€αžΆαžšαž”αž‰αŸ’αž…αž”αŸ‹αž”αž“αŸ’αž‘αžΆαžαŸ‹αžαž½αž’αž€αŸ’αžŸαžš: = αŸ”

αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€ αž™αžΎαž„αžαŸ’αžšαžΌαžœαž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αžŸαŸ’αžαžΆαž”αŸ‹ http αž“αŸ…αž›αžΎαž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“ αžŠαžΎαž˜αŸ’αž”αžΈαž‘αž‘αž½αž›αž”αžΆαž“αž€αžΆαžšαž†αŸ’αž›αžΎαž™αžαž”αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž–αžΈαž€αžΆαžšαž’αž“αž»αž‰αŸ’αž‰αžΆαž αžŠαŸ‚αž›αž“αžΉαž„αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž‰αŸ’αž‡αžΌαž“αž˜αž€αžœαž·αž‰αž‡αžΆαž€αžΆαžšαž”αž‰αŸ’αž‡αžΌαž“αž”αž“αŸ’αžαŸ”

αž€αž·αž…αŸ’αž…αž€αžΆαžšαžšαžŠαŸ’αž‹αž”αžΆαž›αžαŸ’αžšαžΌαžœαž”αžΆαž“αž’αž“αž»αžœαžαŸ’αžαž“αŸ…αž›αžΎαž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸαž–αž·αžŸαŸαžŸ αž™αžΎαž„αž˜αž·αž“αž’αžΆαž…αž”αžŠαž·αžŸαŸαž’αž›αž‘αŸ’αž’αž—αžΆαž–αžŠαŸ‚αž›αž’αŸ’αž“αž€αž‚αŸ’αžšαž”αŸ‹αž‚αŸ’αžšαž„αž‡αžΆαž…αŸ’αžšαžΎαž“αž“αžΉαž„αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžŸαŸ’αž‚αŸ’αžšαžΈαž”αž€αŸ’αž“αž»αž„αž–αŸαž›αžαŸ‚αž˜αž½αž™αž‘αŸ αžŠαžΌαž…αŸ’αž“αŸαŸ‡αžœαžΆαž“αžΉαž„αž‡αŸ’αžšαžΎαžŸαžšαžΎαžŸαž…αŸ’αžšαž€αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž’αŸ’αž“αž€αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αž”αž…αŸ’αž…αž»αž”αŸ’αž”αž“αŸ’αž“αžŠαŸ„αž™αž…αŸƒαžŠαž“αŸ’αž™ αž”αŸ‰αž»αž“αŸ’αžαŸ‚αžαŸ’αž‰αž»αŸ†αž”αžΆαž“αž”αž‰αŸ’αž‡αžΆαž€αŸ‹αž…αŸ’αžšαž€αžŠαŸ‚αž›αž”αžΆαž“αž€αŸ†αžŽαžαŸ‹αž‡αžΆαž˜αž»αž“αž–αŸ’αžšαŸ„αŸ‡ αž–αž½αž€αž‚αŸαž€αŸαžαŸ’αžšαžΌαžœαžαŸ‚αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž“αŸ’αžαŸ‚αž˜αžαžΆαž‡αžΏαž‘αž»αž€αž…αž·αžαŸ’αžαž“αŸ…αž€αŸ’αž“αž»αž„αž€αž»αž„αžŸαžΌαž› API αž•αž„αžŠαŸ‚αžšαŸ”

access_type=αž‚αŸ’αž˜αžΆαž“αž’αŸŠαžΈαž“αž’αžΊαžŽαž·αž αž˜αžΆαž“β€‹αž“αŸαž™β€‹αžαžΆβ€‹αž€αž˜αŸ’αž˜αžœαž·αž’αžΈβ€‹αž’αžΆαž…β€‹αž’αŸ’αžœαžΎβ€‹αž”αž…αŸ’αž…αž»αž”αŸ’αž”αž“αŸ’αž“αž—αžΆαž–β€‹αžαžΌαžαžΉαž“β€‹αžŠαŸ‚αž›β€‹αž•αž»αžβ€‹αž€αŸ†αžŽαžαŸ‹β€‹αžŠαŸ„αž™β€‹αžαŸ’αž›αž½αž“β€‹αž―αž„β€‹αžŠαŸ„αž™β€‹αž˜αž·αž“β€‹αž…αžΆαŸ†αž”αžΆαž…αŸ‹β€‹αž˜αžΆαž“β€‹αž’αž“αŸ’αžαžšαž€αž˜αŸ’αž˜β€‹αž‡αžΆαž˜αž½αž™β€‹αž’αŸ’αž“αž€β€‹αž”αŸ’αžšαžΎβ€‹αž‡αžΆαž˜αž½αž™β€‹αž€αž˜αŸ’αž˜αžœαž·αž’αžΈβ€‹αžšαž»αž€αžšαž€
response_type=αž€αžΌαžŠ αž€αŸ†αžŽαžαŸ‹β€‹αž‘αž˜αŸ’αžšαž„αŸ‹β€‹αž“αŸƒβ€‹αžšαž”αŸ€αž”β€‹αžŠαŸ‚αž›β€‹αž€αžΌαžŠβ€‹αž“αžΉαž„β€‹αžαŸ’αžšαžΌαžœβ€‹αž”αžΆαž“β€‹αž”αž‰αŸ’αž‡αžΌαž“β€‹αž˜αž€β€‹αžœαž·αž‰ (αž™αŸ„αž„β€‹αž‘αŸ…β€‹αž›αžΎβ€‹αžœαž·αž’αžΈαžŸαžΆαžŸαŸ’αžαŸ’αžšβ€‹αž•αŸ’αžαž›αŸ‹β€‹αžŸαž·αž‘αŸ’αž’αž·β€‹αž…αžΆαžŸαŸ‹ αž–αŸαž›β€‹αž’αŸ’αž“αž€β€‹αž”αŸ’αžšαžΎβ€‹αž…αž˜αŸ’αž›αž„β€‹αž€αžΌαžŠβ€‹αž–αžΈβ€‹αž€αž˜αŸ’αž˜αžœαž·αž’αžΈβ€‹αžšαž»αž€αžšαž€β€‹αž‘αŸ…β€‹αž€αŸ’αž“αž»αž„β€‹αžŸαŸ’αž‚αŸ’αžšαžΈαž”)
αžœαž·αžŸαžΆαž›αž—αžΆαž– αž”αž„αŸ’αž αžΆαž‰αž–αžΈαžœαž·αžŸαžΆαž›αž—αžΆαž– αž“αž·αž„αž”αŸ’αžšαž—αŸαž‘αž“αŸƒαž€αžΆαžšαž…αžΌαž›αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αŸ” αž–αž½αž€αž‚αŸαžαŸ’αžšαžΌαžœαžαŸ‚αž”αŸ†αž”αŸ‚αž€αžŠαŸ„αž™αžŠαž€αžƒαŸ’αž›αžΆ ឬ %20 (αž™αŸ„αž„αžαžΆαž˜αž€αžΆαžšαž’αŸŠαž·αž“αž€αžΌαžŠ URL)αŸ” αž”αž‰αŸ’αž‡αžΈαž“αŸƒαžαŸ†αž”αž“αŸ‹αž…αžΌαž›αž”αŸ’αžšαžΎαž‡αžΆαž˜αž½αž™αž”αŸ’αžšαž—αŸαž‘αž’αžΆαž…αžαŸ’αžšαžΌαžœαž”αžΆαž“αž‚αŸαž˜αžΎαž›αžƒαžΎαž‰αž“αŸ…αž‘αžΈαž“αŸαŸ‡αŸ– αžœαž·αžŸαžΆαž›αž—αžΆαž– OAuth 2.0 αžŸαž˜αŸ’αžšαžΆαž”αŸ‹ Google APIs.

αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž–αžΈαž‘αž‘αž½αž›αž”αžΆαž“αž›αŸαžαž€αžΌαžŠαž’αž“αž»αž‰αŸ’αž‰αžΆαž αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž“αžΉαž„αžαŸ’αžšαž‘αž”αŸ‹αžŸαžΆαžšαž”αž·αž‘αž‘αŸ…αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžšαž»αž€αžšαž€ αžˆαž”αŸ‹αžŸαŸ’αžαžΆαž”αŸ‹αž“αŸ…αž›αžΎαž…αŸ’αžšαž€ αž“αž·αž„αž•αŸ’αž‰αžΎαžŸαŸ†αžŽαžΎ POST αžŠαžΎαž˜αŸ’αž”αžΈαž‘αž‘αž½αž›αž”αžΆαž“αžŸαž‰αŸ’αž‰αžΆαžŸαž˜αŸ’αž„αžΆαžαŸ‹αŸ” αž™αžΎαž„αž…αž„αŸ’αž’αž»αž›αž”αž„αŸ’αž αžΆαž‰αž“αŸ…αž€αŸ’αž“αž»αž„αžœαžΆαž“αžΌαžœαž›αŸαžαžŸαž˜αŸ’αž‚αžΆαž›αŸ‹ αž“αž·αž„αžŸαž˜αŸ’αž„αžΆαžαŸ‹αžŠαŸ‚αž›αž”αžΆαž“αž”αž‰αŸ’αž‡αžΆαž€αŸ‹αž–αžΈαž˜αž»αž“αž–αžΈαž€αž»αž„αžŸαžΌαž› API αž’αžΆαžŸαž™αžŠαŸ’αž‹αžΆαž“αžŠαŸ‚αž›αž’αŸ’αž“αž€αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αž“αžΉαž„αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž‰αŸ’αž‡αžΌαž“αž”αž“αŸ’αž αž“αž·αž„ grant_type αžŸαŸ’αžšαž”αžαžΆαž˜αž€αžΆαžšαž”αž‰αŸ’αž‡αžΆαž€αŸ‹αž’αŸ†αž–αžΈαž–αž·αž’αžΈαž€αžΆαžšαŸ”

αž‡αžΆαž€αžΆαžšαž†αŸ’αž›αžΎαž™αžαž” αž™αžΎαž„αž“αžΉαž„αž‘αž‘αž½αž›αž”αžΆαž“αžŸαž‰αŸ’αž‰αžΆαžŸαž˜αŸ’αž„αžΆαžαŸ‹αž…αžΌαž›αž”αŸ’αžšαžΎ αžšαž™αŸˆαž–αŸαž›αžŸαž»αž–αž›αž—αžΆαž–αžšαž”αžŸαŸ‹αžœαžΆαž‚αž·αžαž‡αžΆαžœαž·αž“αžΆαž‘αžΈ αž“αž·αž„αž“αž·αž˜αž·αžαŸ’αžαžŸαž‰αŸ’αž‰αžΆαž’αŸ’αžœαžΎαž±αŸ’αž™αžŸαŸ’αžšαžŸαŸ‹ αžŠαŸ‚αž›αž™αžΎαž„αž’αžΆαž…αž’αŸ’αžœαžΎαž”αž…αŸ’αž…αž»αž”αŸ’αž”αž“αŸ’αž“αž—αžΆαž–αžŸαž‰αŸ’αž‰αžΆαžŸαž˜αŸ’αž„αžΆαžαŸ‹αž…αžΌαž›αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž”αžΆαž“αŸ”

αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžαŸ’αžšαžΌαžœαžαŸ‚αžšαž€αŸ’αžŸαžΆαž‘αž»αž€αžαžΌαžαžΉαž“αž“αŸ…αž€αž“αŸ’αž›αŸ‚αž„αžŠαŸ‚αž›αž˜αžΆαž“αžŸαž»αžœαžαŸ’αžαž·αž—αžΆαž–αž‡αžΆαž˜αž½αž™αž“αžΉαž„αž’αžΆαž™αž»αž€αžΆαž›αž’αŸ’αž“αžΎαž™αžΌαžš αžŠαžΌαž…αŸ’αž“αŸαŸ‡αžšαž αžΌαžαžŠαž›αŸ‹αž™αžΎαž„αžŠαž€αžŸαž·αž‘αŸ’αž’αž·αž…αžΌαž›αž”αŸ’αžšαžΎαžŠαŸ‚αž›αž”αžΆαž“αž‘αž‘αž½αž›αž“αŸ„αŸ‡ αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž“αžΉαž„αž˜αž·αž“αž”αŸ’αžšαž‚αž›αŸ‹αžŸαž‰αŸ’αž‰αžΆαžŸαž˜αŸ’αž„αžΆαžαŸ‹αž‘αžΎαž„αžœαž·αž‰αž‘αŸαŸ” αž“αŸ…αž…αž»αž„αž”αž‰αŸ’αž…αž”αŸ‹ αžαŸ’αž‰αž»αŸ†αž”αžΆαž“αž”αž“αŸ’αžαŸ‚αž˜αžŸαŸ†αžŽαžΎαžšαžŠαžΎαž˜αŸ’αž”αžΈαžŠαž€αž αžΌαžαžŸαž‰αŸ’αž‰αžΆαžŸαž˜αŸ’αž„αžΆαžαŸ‹ αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž˜αž·αž“αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž‰αŸ’αž…αž”αŸ‹αžŠαŸ„αž™αž‡αŸ„αž‚αž‡αŸαž™ αž αžΎαž™αž“αž·αž˜αž·αžαŸ’αžαžŸαž‰αŸ’αž‰αžΆαž•αŸ’αž‘αž»αž€αž‘αžΎαž„αžœαž·αž‰αž˜αž·αž“αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž‰αŸ’αž‡αžΌαž“αž˜αž€αžœαž·αž‰αž‘αŸ αžœαžΆαž“αžΉαž„αž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αž“αžΈαžαž·αžœαž·αž’αžΈαž˜αŸ’αžαž„αž‘αŸ€αž (αž™αžΎαž„αž”αžΆαž“αž…αžΆαžαŸ‹αž‘αž»αž€αžαžΆαžœαžΆαž˜αž·αž“αž˜αžΆαž“αžŸαž»αžœαžαŸ’αžαž·αž—αžΆαž–αž€αŸ’αž“αž»αž„αž€αžΆαžšαžšαž€αŸ’αžŸαžΆαž‘αž»αž€αžαžΌαžαžΉαž“αž“αŸ…αž€αŸ’αž“αž»αž„αž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž“αŸ…αž›αžΎαžŸαŸ’αžαžΆαž“αžΈαž™ αž αžΎαž™αž™αžΎαž„αž˜αž·αž“ αž˜αž·αž“αž…αž„αŸ‹αž’αŸ’αžœαžΎαž±αŸ’αž™αžšαžΏαž„αžŸαŸ’αž˜αž»αž‚αžŸαŸ’αž˜αžΆαž‰αž‡αžΆαž˜αž½αž™αž€αžΆαžšαž‚αŸ’αžšαžΈαž” αž¬αž”αžΎαž€αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžšαž»αž€αžšαž€αž‰αžΉαž€αž‰αžΆαž”αŸ‹)

do {
  $token_result = Get-GoogleAuthToken
  $token = $token_result.access_token
  if ($token_result.refresh_token -eq $null) {
    Write-Host ("Session is not destroyed. Revoking token...")
    Invoke-WebRequest -Uri ("https://accounts.google.com/o/oauth2/revoke?token="+$token)
  }
} while ($token_result.refresh_token -eq $null)
$refresh_token = $token_result.refresh_token
$minute = ([int]("{0:mm}" -f ([timespan]::fromseconds($token_result.expires_in))))+((Get-date).Minute)-2
if ($minute -lt 0) {$minute += 60}
elseif ($minute -gt 59) {$minute -=60}
$token_expire = @{
  hour = ([int]("{0:hh}" -f ([timespan]::fromseconds($token_result.expires_in))))+((Get-date).Hour)
  minute = $minute
}

αžŠαžΌαž…αžŠαŸ‚αž›αž’αŸ’αž“αž€αž”αžΆαž“αž€αžαŸ‹αžŸαž˜αŸ’αž‚αžΆαž›αŸ‹αžšαž½αž…αž αžΎαž™ αž“αŸ…αž–αŸαž›αžŠαž€αž αžΌαžαž“αž·αž˜αž·αžαŸ’αžαžŸαž‰αŸ’αž‰αžΆ Invoke-WebRequest αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αŸ’αžšαžΎαŸ” αž˜αž·αž“αžŠαžΌαž… Invoke-RestMethod αž‘αŸ αžœαžΆαž˜αž·αž“αžαŸ’αžšαž‘αž”αŸ‹αž‘αž·αž“αŸ’αž“αž“αŸαž™αžŠαŸ‚αž›αž‘αž‘αž½αž›αž”αžΆαž“αž€αŸ’αž“αž»αž„αž‘αž˜αŸ’αžšαž„αŸ‹αžŠαŸ‚αž›αž’αžΆαž…αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αž”αžΆαž“ αž“αž·αž„αž”αž„αŸ’αž αžΆαž‰αžŸαŸ’αžαžΆαž“αž—αžΆαž–αž“αŸƒαžŸαŸ†αžŽαžΎαŸ”

αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€ αžŸαŸ’αž‚αŸ’αžšαžΈαž”αžŸαž½αžšαž’αŸ’αž“αž€αž±αŸ’αž™αž”αž‰αŸ’αž…αžΌαž›αžˆαŸ’αž˜αŸ„αŸ‡ αž“αž·αž„αž“αžΆαž˜αžαŸ’αžšαž€αžΌαž›αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹ αžŠαŸ„αž™αž”αž„αŸ’αž€αžΎαžαž€αžΆαžšαž…αžΌαž› + αž’αŸŠαžΈαž˜αŸ‚αž›αŸ”

αžŸαŸ†αžŽαžΎ

αžŸαŸ†αžŽαžΎαž”αž“αŸ’αž‘αžΆαž”αŸ‹αž“αžΉαž„αž˜αžΆαž“αž‡αžΆαžŠαŸ†αž”αžΌαž„ αž’αŸ’αž“αž€αžαŸ’αžšαžΌαžœαž–αž·αž“αž·αžαŸ’αž™αž˜αžΎαž›αžαžΆαžαžΎαž’αŸ’αž“αž€αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αžŠαŸ‚αž›αž˜αžΆαž“αž€αžΆαžšαž…αžΌαž›αžŠαžΌαž…αž‚αŸ’αž“αžΆαž˜αžΆαž“αžšαž½αž…αž αžΎαž™ αžŠαžΎαž˜αŸ’αž”αžΈαž‘αž‘αž½αž›αž”αžΆαž“αž€αžΆαžšαžŸαž˜αŸ’αžšαŸαž…αž…αž·αžαŸ’αžαž›αžΎαž€αžΆαžšαž”αž„αŸ’αž€αžΎαžαžαŸ’αž˜αžΈ αž¬αž”αžΎαž€αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž”αž…αŸ’αž…αž»αž”αŸ’αž”αž“αŸ’αž“αŸ”

αžαŸ’αž‰αž»αŸ†αž”αžΆαž“αžŸαž˜αŸ’αžšαŸαž…αž…αž·αžαŸ’αžαž’αž“αž»αžœαžαŸ’αžαžŸαŸ†αžŽαžΎαž‘αžΆαŸ†αž„αž’αžŸαŸ‹αž€αŸ’αž“αž»αž„αž‘αž˜αŸ’αžšαž„αŸ‹αž“αŸƒαž˜αž»αžαž„αžΆαžšαž˜αž½αž™αž‡αžΆαž˜αž½αž™αž“αžΉαž„αž€αžΆαžšαž‡αŸ’αžšαžΎαžŸαžšαžΎαžŸ αžŠαŸ„αž™αž”αŸ’αžšαžΎαž€αž»αž„αžαžΆαž€αŸ‹αŸ–

function GoogleQuery {
  param (
    $type,
    $query
  )
  switch ($type) {
    "SearchAccount" {
      Return Invoke-RestMethod -Method Get -Uri "https://www.googleapis.com/admin/directory/v1/users" -Headers @{Authorization = "Bearer "+(Get-GoogleToken)} -Body @{
        domain = 'rocketguys.com'
        query  = "email:$query"
      }
    }
    "UpdateAccount" {
      $body = @{
        name  = @{
          givenName = $query['givenName']
          familyName = $query['familyName']
        }
        suspended = 'false'
        password = $query['password']
        changePasswordAtNextLogin = 'true'
        phones = @(@{
          primary = 'true'
          value = $query['phone']
          type = "mobile"
        })
        orgUnitPath = $query['orgunit']
      }
      Return Invoke-RestMethod -Method Put -Uri ("https://www.googleapis.com/admin/directory/v1/users/"+$query['email']) -Headers @{Authorization = "Bearer "+(Get-GoogleToken)} -Body (ConvertTo-Json $body) -ContentType 'application/json; charset=utf-8'
    }
    
    "CreateAccount" {
      $body = @{
        primaryEmail = $query['email']
        name  = @{
          givenName = $query['givenName']
          familyName = $query['familyName']
        }
        suspended = 'false'
        password = $query['password']
        changePasswordAtNextLogin = 'true'
        phones = @(@{
          primary = 'true'
          value = $query['phone']
          type = "mobile"
        })
        orgUnitPath = $query['orgunit']
      }
      Return Invoke-RestMethod -Method Post -Uri "https://www.googleapis.com/admin/directory/v1/users" -Headers @{Authorization = "Bearer "+(Get-GoogleToken)} -Body (ConvertTo-Json $body) -ContentType 'application/json; charset=utf-8'
    }
    "AddMember" {
      $body = @{
        userKey = $query['email']
      }
      $ifrequest = Invoke-RestMethod -Method Get -Uri "https://www.googleapis.com/admin/directory/v1/groups" -Headers @{Authorization = "Bearer "+(Get-GoogleToken)} -Body $body
      $array = @()
      foreach ($group in $ifrequest.groups) {$array += $group.email}
      if ($array -notcontains $query['groupkey']) {
        $body = @{
          email = $query['email']
          role = "MEMBER"
        }
        Return Invoke-RestMethod -Method Post -Uri ("https://www.googleapis.com/admin/directory/v1/groups/"+$query['groupkey']+"/members") -Headers @{Authorization = "Bearer "+(Get-GoogleToken)} -Body (ConvertTo-Json $body) -ContentType 'application/json; charset=utf-8'
      } else {
        Return ($query['email']+" now is a member of "+$query['groupkey'])
      }
    }
  }
}

αž€αŸ’αž“αž»αž„αžŸαŸ†αžŽαžΎαž“αžΈαž˜αž½αž™αŸ— αž’αŸ’αž“αž€αžαŸ’αžšαžΌαžœαž•αŸ’αž‰αžΎαž”αž‹αž˜αž€αžαžΆαž€αžΆαžšαž’αž“αž»αž‰αŸ’αž‰αžΆαžαžŠαŸ‚αž›αž˜αžΆαž“αž”αŸ’αžšαž—αŸαž‘αžŸαž‰αŸ’αž‰αžΆαžŸαž˜αŸ’αž„αžΆαžαŸ‹ αž“αž·αž„αžŸαž‰αŸ’αž‰αžΆαžŸαž˜αŸ’αž„αžΆαžαŸ‹αž…αžΌαž›αž”αŸ’αžšαžΎαžŠαŸ„αž™αžαŸ’αž›αž½αž“αž―αž„αŸ” αž”αž…αŸ’αž…αž»αž”αŸ’αž”αž“αŸ’αž“ αž”αŸ’αžšαž—αŸαž‘αž“αž·αž˜αž·αžαŸ’αžαžŸαž‰αŸ’αž‰αžΆαž‚αžΊαžαŸ‚αž„αžαŸ‚αž‡αžΆαž’αŸ’αž“αž€αž€αžΆαž“αŸ‹αŸ” αžŠαŸ„αž™αžŸαžΆαžšαžαŸ‚ αž™αžΎαž„αžαŸ’αžšαžΌαžœαž–αž·αž“αž·αžαŸ’αž™αž˜αžΎαž›αžαžΆαžŸαž‰αŸ’αž‰αžΆαžŸαž˜αŸ’αž„αžΆαžαŸ‹αž˜αž·αž“αž‘αžΆαž“αŸ‹αž•αž»αžαž€αŸ†αžŽαžαŸ‹ αž αžΎαž™αž’αŸ’αžœαžΎαž”αž…αŸ’αž…αž»αž”αŸ’αž”αž“αŸ’αž“αž—αžΆαž–αžœαžΆαž”αž“αŸ’αž‘αžΆαž”αŸ‹αž–αžΈαž˜αž½αž™αž˜αŸ‰αŸ„αž„αž…αžΆαž”αŸ‹αž–αžΈαž–αŸαž›αžŠαŸ‚αž›αžœαžΆαžαŸ’αžšαžΌαžœαž”αžΆαž“αž…αŸαž‰ αžαŸ’αž‰αž»αŸ†αž”αžΆαž“αž”αž‰αŸ’αž‡αžΆαž€αŸ‹αž–αžΈαžŸαŸ†αžŽαžΎαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž˜αž»αžαž„αžΆαžšαž˜αž½αž™αž•αŸ’αžŸαŸαž„αž‘αŸ€αžαžŠαŸ‚αž›αžαŸ’αžšαž‘αž”αŸ‹αžŸαž‰αŸ’αž‰αžΆαžŸαž˜αŸ’αž„αžΆαžαŸ‹αž…αžΌαž›αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαŸ” αž”αŸ†αžŽαŸ‚αž€αž“αŸƒαž€αžΌαžŠαžŠαžΌαž…αž‚αŸ’αž“αžΆαž‚αžΊαž“αŸ…αžŠαžΎαž˜αžŸαŸ’αž‚αŸ’αžšαžΈαž” αž“αŸ…αž–αŸαž›αž‘αž‘αž½αž›αž”αžΆαž“αžŸαž‰αŸ’αž‰αžΆαžŸαž˜αŸ’αž„αžΆαžαŸ‹αž…αžΌαž›αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžŠαŸ†αž”αžΌαž„αŸ–

function Get-GoogleToken {
  if (((Get-date).Hour -gt $token_expire.hour) -or (((Get-date).Hour -ge $token_expire.hour) -and ((Get-date).Minute -gt $token_expire.minute))) {
  Write-Host "Token Expired. Refreshing..."
    $request = (Invoke-RestMethod -Method Post -Uri "https://www.googleapis.com/oauth2/v4/token" -ContentType 'application/x-www-form-urlencoded' -Body @{
      client_id = $client_id
      client_secret = $client_secret
      refresh_token = $refresh_token
      grant_type = 'refresh_token'
    })
    $token = $request.access_token
    $minute = ([int]("{0:mm}" -f ([timespan]::fromseconds($request.expires_in))))+((Get-date).Minute)-2
    if ($minute -lt 0) {$minute += 60}
    elseif ($minute -gt 59) {$minute -=60}
    $script:token_expire = @{
      hour = ([int]("{0:hh}" -f ([timespan]::fromseconds($request.expires_in))))+((Get-date).Hour)
      minute = $minute
    }
  }
  return $token
}

αž–αž·αž“αž·αžαŸ’αž™αž˜αžΎαž›αž€αžΆαžšαž…αžΌαž›αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž’αžαŸ’αžαž·αž—αžΆαž–αŸ–

function Check_Google {
  $query = (GoogleQuery 'SearchAccount' $username)
  if ($query.users -ne $null) {
    $user = $query.users[0]
    Write-Host $user.name.fullName' - '$user.PrimaryEmail' - suspended: '$user.Suspended
    $GAresult = $user
  }
  if ($GAresult) {
      $return = $GAresult
  } else {$return = 'gg'}
  return $return
}

αž’αŸŠαžΈαž˜αŸ‚αž›αŸ–$query request αž“αžΉαž„αžŸαž½αžš API αž±αŸ’αž™αžŸαŸ’αžœαŸ‚αž„αžšαž€αž’αŸ’αž“αž€αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αžŠαŸ‚αž›αž˜αžΆαž“αž’αŸŠαžΈαž˜αŸ‚αž›αž“αŸ„αŸ‡ αžšαž½αž˜αž‘αžΆαŸ†αž„αžˆαŸ’αž˜αŸ„αŸ‡αž€αŸ’αž›αŸ‚αž„αž€αŸ’αž›αžΆαž™αž•αž„αžŠαŸ‚αžšαŸ” αž’αŸ’αž“αž€αž€αŸαž’αžΆαž…αž”αŸ’αžšαžΎαž’αž€αŸ’αžŸαžšαž‡αŸ†αž“αž½αžŸαŸ– =, :, :{PREFIX}*.

αžŠαžΎαž˜αŸ’αž”αžΈαž‘αž‘αž½αž›αž”αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™ αžŸαžΌαž˜αž”αŸ’αžšαžΎαžœαž·αž’αžΈαžŸαŸ’αž“αžΎαžŸαž»αŸ† GET αžŠαžΎαž˜αŸ’αž”αžΈαž”αž‰αŸ’αž…αžΌαž›αž‘αž·αž“αŸ’αž“αž“αŸαž™ (αž”αž„αŸ’αž€αžΎαžαž‚αžŽαž“αžΈ αž¬αž”αž“αŸ’αžαŸ‚αž˜αžŸαž˜αžΆαž‡αž·αž€αž‘αŸ…αž€αŸ’αž“αž»αž„αž€αŸ’αžšαž»αž˜) - POST αžŠαžΎαž˜αŸ’αž”αžΈαž’αŸ’αžœαžΎαž”αž…αŸ’αž…αž»αž”αŸ’αž”αž“αŸ’αž“αž—αžΆαž–αž‘αž·αž“αŸ’αž“αž“αŸαž™αžŠαŸ‚αž›αž˜αžΆαž“αžŸαŸ’αžšαžΆαž”αŸ‹ - PUT αžŠαžΎαž˜αŸ’αž”αžΈαž›αž»αž”αž€αŸ†αžŽαžαŸ‹αžαŸ’αžšαžΆ (αž§αž‘αžΆαž αžšαžŽαŸ αžŸαž˜αžΆαž‡αž·αž€αž˜αž€αž–αžΈαž€αŸ’αžšαž»αž˜) - αž›αž»αž”αŸ”

αžŸαŸ’αž‚αŸ’αžšαžΈαž”αž€αŸαž“αžΉαž„αžŸαž½αžšαžšαž€αž›αŸαžαž‘αžΌαžšαžŸαŸαž–αŸ’αž‘ (αžαŸ’αžŸαŸ‚αžŠαŸ‚αž›αž˜αž·αž“αž˜αžΆαž“αžŸαž»αž–αž›αž—αžΆαž–) αž“αž·αž„αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαžŠαžΆαž€αŸ‹αž”αž‰αŸ’αž…αžΌαž›αž€αŸ’αž“αž»αž„αž€αŸ’αžšαž»αž˜αž…αŸ‚αž€αž…αžΆαž™αž€αŸ’αž“αž»αž„αžαŸ†αž”αž“αŸ‹αŸ” αžœαžΆαžŸαž˜αŸ’αžšαŸαž…αžαžΆαž’αž„αŸ’αž‚αž—αžΆαž–αž’αž„αŸ’αž‚αž—αžΆαž–αžŽαžΆαž˜αž½αž™αžŠαŸ‚αž›αž’αŸ’αž“αž€αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αž‚αž½αžšαžαŸ‚αž˜αžΆαž“αžŠαŸ„αž™αž•αŸ’αž’αŸ‚αž€αž›αžΎ Active Directory OU αžŠαŸ‚αž›αž”αžΆαž“αž‡αŸ’αžšαžΎαžŸαžšαžΎαžŸ αž αžΎαž™αž—αŸ’αž‡αžΆαž”αŸ‹αž˜αž€αž‡αžΆαž˜αž½αž™αž–αžΆαž€αŸ’αž™αžŸαž˜αŸ’αž„αžΆαžαŸ‹αŸ–

do {
  $phone = Read-Host "Π’Π΅Π»Π΅Ρ„ΠΎΠ½ Π² Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π΅ +7Ρ…Ρ…Ρ…Ρ…Ρ…Ρ…Ρ…Ρ…"
} while (-not $phone)
do {
    $moscow = Read-Host "Π’ Московский офис? (y/n) "
} while (-not (($moscow -eq 'y') -or ($moscow -eq 'n')))
$orgunit = '/'
if ($OU -like "*OU=Delivery,OU=Users,OU=ROOT,DC=rocket,DC=local") {
    Write-host "Π‘ΡƒΠ΄Π΅Ρ‚ создана Π² /Team delivery"
    $orgunit = "/Team delivery"
}
$Password =  -join ( 48..57 + 65..90 + 97..122 | Get-Random -Count 12 | % {[char]$_})+"*Ba"

αž αžΎαž™αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€αž‚αžΆαžαŸ‹αž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αžšαŸ€αž”αž…αŸ†αž‚αžŽαž“αžΈ:

$query = @{
  email = $email
  givenName = $firstname
  familyName = $lastname
  password = $password
  phone = $phone
  orgunit = $orgunit
}
if ($GMailExist) {
  Write-Host "ЗапускаСм ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ Π°ΠΊΠΊΠ°ΡƒΠ½Ρ‚Π°" -f mag
  (GoogleQuery 'UpdateAccount' $query) | fl
  write-host "НС Π·Π°Π±ΡƒΠ΄ΡŒ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΡ‚ΡŒ Π³Ρ€ΡƒΠΏΠΏΡ‹ Ρƒ Π²ΠΊΠ»ΡŽΡ‡Π΅Π½Π½ΠΎΠ³ΠΎ $Username Π² Google."
} else {
  Write-Host "ЗапускаСм созданиС Π°ΠΊΠΊΠ°ΡƒΠ½Ρ‚Π°" -f mag
  (GoogleQuery 'CreateAccount' $query) | fl
}
if ($moscow -eq "y"){
  write-host "ДобавляСм Π² Π³Ρ€ΡƒΠΏΠΏΡƒ moscowoffice"
  $query = @{
    groupkey = '[email protected]'
    email = $email
  }
  (GoogleQuery 'AddMember' $query) | fl
}

αž˜αž»αžαž„αžΆαžšαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž’αžΆαž”αŸ‹αžŠαŸαž αž“αž·αž„αž”αž„αŸ’αž€αžΎαžαž‚αžŽαž“αžΈαž˜αžΆαž“αžœαžΆαž€αŸ’αž™αžŸαž˜αŸ’αž–αŸαž“αŸ’αž’αžŸαŸ’αžšαžŠαŸ€αž„αž‚αŸ’αž“αžΆ αž˜αž·αž“αž˜αŸ‚αž“αž‚αŸ’αžšαž”αŸ‹αžœαžΆαž›αž”αž“αŸ’αžαŸ‚αž˜αž‘αžΆαŸ†αž„αž’αžŸαŸ‹αžαŸ’αžšαžΌαžœαž”αžΆαž“αž‘αžΆαž˜αž‘αžΆαžšαž‘αŸ αž“αŸ…αž€αŸ’αž“αž»αž„αž•αŸ’αž“αŸ‚αž€αžŠαŸ‚αž›αž˜αžΆαž“αž›αŸαžαž‘αžΌαžšαžŸαŸαž–αŸ’αž‘ αž’αŸ’αž“αž€αžαŸ’αžšαžΌαžœαž”αž‰αŸ’αž‡αžΆαž€αŸ‹αž’αžΆαžšαŸαžŠαŸ‚αž›αž’αžΆαž…αž˜αžΆαž“αž€αŸ†αžŽαžαŸ‹αžαŸ’αžšαžΆαžšαž αžΌαžαžŠαž›αŸ‹αž˜αž½αž™αž‡αžΆαž˜αž½αž™αž“αžΉαž„αž›αŸαž αž“αž·αž„αž”αŸ’αžšαž—αŸαž‘αžšαž”αžŸαŸ‹αžœαžΆαŸ”

αžŠαžΎαž˜αŸ’αž”αžΈβ€‹αž˜αž·αž“β€‹αž‘αž‘αž½αž›β€‹αž”αžΆαž“β€‹αž€αŸ†αž αž»αžŸβ€‹αž–αŸαž›β€‹αž”αž“αŸ’αžαŸ‚αž˜β€‹αž’αŸ’αž“αž€β€‹αž”αŸ’αžšαžΎβ€‹αž‘αŸ…β€‹αž€αŸ’αž“αž»αž„β€‹αž€αŸ’αžšαž»αž˜β€‹αžŠαŸ†αž”αžΌαž„β€‹αž™αžΎαž„β€‹αž’αžΆαž…β€‹αž–αž·αž“αž·αžαŸ’αž™β€‹αž˜αžΎαž›β€‹αžαžΆβ€‹αžαžΎβ€‹αž‚αžΆαžαŸ‹β€‹αž‚αžΊβ€‹αž‡αžΆβ€‹αžŸαž˜αžΆαž‡αž·αž€β€‹αž€αŸ’αžšαž»αž˜β€‹αž“αŸαŸ‡β€‹αžšαž½αž…β€‹αž αžΎαž™β€‹αžŠαŸ„αž™β€‹αž‘αž‘αž½αž›β€‹αž”αžΆαž“β€‹αž”αž‰αŸ’αž‡αžΈβ€‹αžŸαž˜αžΆαž‡αž·αž€β€‹αž€αŸ’αžšαž»αž˜β€‹αž¬β€‹αžŸαž˜αžΆαžŸαž—αžΆαž–β€‹αž–αžΈβ€‹αž’αŸ’αž“αž€β€‹αž”αŸ’αžšαžΎβ€‹αžαŸ’αž›αž½αž“β€‹αž‚αžΆαžαŸ‹β€‹αž•αŸ’αž‘αžΆαž›αŸ‹αŸ”

αž€αžΆαžšαžŸαžΆαž€αžŸαž½αžšαžŸαž˜αžΆαž‡αž·αž€αž—αžΆαž–αž€αŸ’αžšαž»αž˜αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αž‡αžΆαž€αŸ‹αž›αžΆαž€αŸ‹αž“αžΉαž„αž˜αž·αž“αž€αžΎαžαž‘αžΎαž„αžœαž·αž‰αž‘αŸ αž αžΎαž™αž“αžΉαž„αž”αž„αŸ’αž αžΆαž‰αžαŸ‚αžŸαž˜αžΆαž‡αž·αž€αž—αžΆαž–αž•αŸ’αž‘αžΆαž›αŸ‹αž”αŸ‰αž»αžŽαŸ’αžŽαŸ„αŸ‡αŸ” αžšαž½αž˜αž‘αžΆαŸ†αž„αž’αŸ’αž“αž€αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αž“αŸ…αž€αŸ’αž“αž»αž„αž€αŸ’αžšαž»αž˜αž˜αŸαžŠαŸ‚αž›αž˜αžΆαž“αž€αŸ’αžšαž»αž˜αž€αžΌαž“αžšαž½αž…αž αžΎαž™ αžŠαŸ‚αž›αž’αŸ’αž“αž€αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αž‡αžΆαžŸαž˜αžΆαž‡αž·αž€αž“αžΉαž„αž‘αž‘αž½αž›αž”αžΆαž“αž‡αŸ„αž‚αž‡αŸαž™αŸ”

αžŸαŸαž…αž€αŸ’αžαžΈαžŸαž“αŸ’αž“αž·αžŠαŸ’αž‹αžΆαž“

αž’αŸ’αžœαžΈβ€‹αžŠαŸ‚αž›β€‹αž“αŸ…β€‹αžŸαž›αŸ‹β€‹αž‚αžΊβ€‹αžαŸ’αžšαžΌαžœβ€‹αž•αŸ’αž‰αžΎβ€‹αž›αŸαžβ€‹αžŸαž˜αŸ’αž„αžΆαžαŸ‹β€‹αž±αŸ’αž™β€‹αž’αŸ’αž“αž€β€‹αž”αŸ’αžšαžΎβ€‹αžŸαž˜αŸ’αžšαžΆαž”αŸ‹β€‹αž‚αžŽαž“αžΈβ€‹αžαŸ’αž˜αžΈαŸ” αž™αžΎαž„αž’αŸ’αžœαžΎαžŠαžΌαž…αž“αŸαŸ‡αžαžΆαž˜αžšαž™αŸˆαžŸαžΆαžš SMS αž αžΎαž™αž•αŸ’αž‰αžΎαž–αŸαžαŸŒαž˜αžΆαž“αž‘αžΌαž‘αŸ…αž‡αžΆαž˜αž½αž™αž“αžΉαž„αž€αžΆαžšαžŽαŸ‚αž“αžΆαŸ† αž“αž·αž„αž…αžΌαž›αž‘αŸ…αž€αžΆαž“αŸ‹αž’αŸŠαžΈαž˜αŸ‚αž›αž•αŸ’αž‘αžΆαž›αŸ‹αžαŸ’αž›αž½αž“ αžŠαŸ‚αž›αžšαž½αž˜αž‡αžΆαž˜αž½αž™αž›αŸαžαž‘αžΌαžšαžŸαŸαž–αŸ’αž‘αžαŸ’αžšαžΌαžœαž”αžΆαž“αž•αŸ’αžαž›αŸ‹αžŠαŸ„αž™αž“αžΆαž™αž€αžŠαŸ’αž‹αžΆαž“αž‡αŸ’αžšαžΎαžŸαžšαžΎαžŸαž”αž»αž‚αŸ’αž‚αž›αž·αž€αŸ” αž‡αžΆαž‡αž˜αŸ’αžšαžΎαžŸαž˜αž½αž™ αž’αŸ’αž“αž€αž’αžΆαž…αžŸαž“αŸ’αžŸαŸ†αž”αŸ’αžšαžΆαž€αŸ‹ αž“αž·αž„αž•αŸ’αž‰αžΎαž–αžΆαž€αŸ’αž™αžŸαž˜αŸ’αž„αžΆαžαŸ‹αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αž‘αŸ…αž€αžΆαžšαž‡αž‡αŸ‚αž€αžαžΆαž˜αž‘αžΌαžšαž›αŸαžαžŸαž˜αŸ’αž„αžΆαžαŸ‹ αžŠαŸ‚αž›αž’αžΆαž…αž…αžΆαžαŸ‹αž‘αž»αž€αžαžΆαž‡αžΆαž€αžαŸ’αžαžΆαž‘αžΈαž–αžΈαžšαž•αž„αžŠαŸ‚αžš (MacBooks αž“αžΉαž„αž‡αžΆαž€αžšαžŽαžΈαž›αžΎαž€αž›αŸ‚αž„)αŸ”

αž’αžšαž‚αž»αžŽαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαž’αžΆαž“αžŠαž›αŸ‹αž…αž”αŸ‹αŸ” αžαŸ’αž‰αž»αŸ†αž“αžΉαž„αžšαžΈαž€αžšαžΆαž™αž€αŸ’αž“αž»αž„αž€αžΆαžšαžƒαžΎαž‰αž€αžΆαžšαž•αŸ’αžŠαž›αŸ‹αž™αŸ„αž”αž›αŸ‹αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαž€αŸ‚αž›αž˜αŸ’αž’αžšαž…αž“αžΆαž”αŸαž‘αŸ’αž˜αž“αŸƒαž€αžΆαžšαžŸαžšαžŸαŸαžšαž’αžαŸ’αžαž”αž‘ αž αžΎαž™αžŸαžΌαž˜αž‡αžΌαž“αž–αžšαž±αŸ’αž™αž’αŸ’αž“αž€αž…αžΆαž”αŸ‹αž€αŸ†αž αž»αžŸαžαž·αž…αž‡αžΆαž„αž˜αž»αž“αž“αŸ…αž–αŸαž›αžŸαžšαžŸαŸαžšαžŸαŸ’αž‚αŸ’αžšαžΈαž” =)

αž”αž‰αŸ’αž‡αžΈαž“αŸƒαžαŸ†αžŽαž—αŸ’αž‡αžΆαž”αŸ‹αžŠαŸ‚αž›αž’αžΆαž…αž˜αžΆαž“αž”αŸ’αžšαž™αŸ„αž‡αž“αŸαžαžΆαž˜αž”αŸ’αžšαž’αžΆαž“αž”αž‘ αž¬αž‚αŸ’αžšαžΆαž“αŸ‹αžαŸ‚αž†αŸ’αž›αžΎαž™αžŸαŸ†αžŽαž½αžšαŸ–

αž”αŸ’αžšαž—αž–: www.habr.com

αž”αž“αŸ’αžαŸ‚αž˜αž˜αžαž·αž™αŸ„αž”αž›αŸ‹