;ELC ;;; Compiled ;;; in Emacs version 28.0.50 ;;; with all optimizations. (byte-code "\300\301!\210\300\302!\210\300\303!\210\300\304!\210\300\305!\210\300\306!\210\307\310\311\312\313\314\315\316\317\320& \210\321\322\323\324\325DD\326\327\330\315\310&\210\321\331\323\324\332DD\333\327\330\315\310&\207" [require cl-lib s subr-x json request websocket custom-declare-group grammarly nil "Grammarly API interface." :prefix "grammarly-" :group text :link (url-link :tag "Github" "https://github.com/jcs-elpa/grammarly") custom-declare-variable grammarly-username funcall function #[0 "\300\207" [#1=""] 1 #1#] "Grammarly login username." :type string grammarly-password #[0 "\300\207" [#1#] 1 #1#] "Grammarly login password."] 10) #@13 User agent. (defconst grammarly--user-agent "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:68.0) Gecko/20100101 Firefox/68.0" (#$ . 746)) #@38 Header for simulate using a browser. (defconst grammarly--browser-headers '(("User-Agent") ("Accept" . "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3") ("Accept-Language" . "en-GB,en-US;q=0.9,en;q=0.8") ("Cache-Control" . "no-cache") ("Pragma" . "no-cache")) (#$ . 893)) #@38 Authorize message for Grammarly API. (defconst grammarly--authorize-msg (byte-code "\301\302\303BE\207" [grammarly--user-agent ("origin" . "chrome-extension://kbfnbcaeplbcioakkpcpgfkobkghlhen") ("Cookie" . "$COOKIES$") "User-Agent"] 4) (#$ . 1243)) #@46 Grammarly initialize message for verify use. (defconst grammarly--init-msg '(("type" . "initial") ("token") ("docid" . "dfad0927-7b35-e155-6de9-4a107053da35-43543554345") ("client" . "extension_chrome") ("protocolVersion" . "1.0") ("clientSupports" "free_clarity_alerts" "readability_check" "filler_words_check" "sentence_variety_check" "free_occasional_premium_alerts") ("dialect" . "american") ("clientVersion" . "14.924.2437") ("extDomain" . "editpad.org") ("action" . "start") ("id" . 0)) (#$ . 1499)) #@39 Grammarly request package definition. (defconst grammarly--request-check '(("ch" "+0:0:$STR$:0") ("rev" . 0) ("action" . "submit_ot") ("id" . 0)) (#$ . 2011)) #@52 List of callback function when execute on message. (defvar grammarly-on-message-function-list nil (#$ . 2176)) #@49 List of callback function when execute on open. (defvar grammarly-on-open-function-list nil (#$ . 2293)) #@50 List of callback function when execute on close. (defvar grammarly-on-close-function-list nil (#$ . 2404)) #@43 Current text that are going to check for. (defvar grammarly--text "" (#$ . 2517)) #@28 Websocket for this client. (defvar grammarly--client nil (#$ . 2605)) #@55 Run every this seconds until we received API request. (defvar grammarly--update-time 0.1 (#$ . 2681)) #@25 Record the cookie down. (defvar grammarly--cookies "" (#$ . 2789)) #@37 Universal timer for each await use. (defvar grammarly--timer nil (#$ . 2862)) #@78 Flag to after we are done preparing; basically after authentication process. (defvar grammarly--start-checking-p nil (#$ . 2946)) #@40 Flag to see if we show debug messages. (defvar grammarly--show-debug-message nil (#$ . 3082)) #@93 Debug message like function `message' with same argument FMT and ARGS. (fn FMT &rest ARGS) (defalias 'grammarly--debug-message #[385 "\205 \301\302#\207" [grammarly--show-debug-message apply message] 6 (#$ . 3182)]) #@21 Kill the websocket. (defalias 'grammarly--kill-websocket #[0 "\205 \301!\210\302\211\207" [grammarly--client websocket-close nil] 2 (#$ . 3409)]) #@17 Kill the timer. (defalias 'grammarly--kill-timer #[0 "\301!\205 \302!\210\303\211\207" [grammarly--timer timerp cancel-timer nil] 2 (#$ . 3565)]) #@58 Execute all function LST with ARGS. (fn LST &rest ARGS) (defalias 'grammarly--execute-function-list #[385 "\300!\203 \301\"\207<\203$\211\205#\211@\301\"\210A\266\202\202\207\302\303\"\207" [functionp apply user-error "[ERROR] Function does not exists: %s"] 7 (#$ . 3721)]) #@33 Authorization cookie container. (defvar grammarly--auth-cookie nil (#$ . 4016)) #@76 Check if current COOKIE the last cookie from COOKIES. (fn COOKIE COOKIES) (defalias 'grammarly--last-cookie #[514 "\211GS8\232\207" [] 4 (#$ . 4102)]) #@48 Return cookie value by cookie NAME. (fn NAME) (defalias 'grammarly--get-cookie-by-name #[257 "G\301\302\211\204+W\203+8\211@\211\230\203\"A\262\303\262\266T\262\202\207" [grammarly--auth-cookie 0 nil t] 9 (#$ . 4262)]) #@35 Form all cookies into one string. (defalias 'grammarly--form-cookie #[0 "\301\302\303\304\305#\306\301\211\211\203?\211@\211@\262\211A\262\307\310\311\f\"\203.\306\202/\312%\262BBA\266\202\202 \210\313!\314!\207" [grammarly--auth-cookie nil request-cookie-alist ".grammarly.com" "/" t "" format "%s %s=%s%s" grammarly--last-cookie ";" reverse string-trim] 14 (#$ . 4507)]) #@26 Refresh the cookie once. (defalias 'grammarly--update-cookie #[0 "\301 \211\207" [grammarly--cookies grammarly--form-cookie] 2 (#$ . 4912)]) #@13 Get cookie. (defalias 'grammarly--get-cookie #[0 "\303\304\305\306\307\310\311\312\n\313\"\314\315\316\317& \207" [grammarly--start-checking-p grammarly--cookies grammarly--browser-headers nil "" request "https://grammarly.com/signin" :type "GET" :headers append (("Sec-Fetch-Mode" . "navigate") ("Sec-Fetch-Sit" . "same-origin") ("Sec-Fetch-User" . "?1") ("Upgrade-Insecure-Requests" . "1") ("Referer" . "https://www.grammarly.com/")) :success #[128 "\301\302\303\"\210\304 \210\305 \203\306 \207\307\211\207" [grammarly--start-checking-p nil plist-member :response grammarly--update-cookie grammarly-premium-p grammarly--authenticate t] 5 "\n\n(fn &key RESPONSE &allow-other-keys)"] :error #[128 "\300\301\302\"\210\303\304\"\207" [nil plist-member :error-thrown grammarly--debug-message "[ERROR] Error while getting cookie: %s"] 5 "\n\n(fn &rest ARGS &key ERROR-THROWN &allow-other-keys)"]] 10 (#$ . 5060)]) #@52 Return non-nil means we are using premium version. (defalias 'grammarly-premium-p #[0 "\211\302\230\262?\205 \211\302\230\262?\207" [grammarly-username grammarly-password ""] 3 (#$ . 5985)]) #@41 Login to Grammarly for premium version. (defalias 'grammarly--authenticate #[0 "\303\304\"\210\305\306\307\310\311\312\313\314\315 B\316\317\320\321\322!B\323\321\324!B\325\326\327\330\331\321\322!\321\332!\321\324!$B\257 \333\334\335\336B\337\nB\340BBBC!\341\342\343\344& \207" [grammarly-username grammarly--user-agent grammarly-password message "connecting as %s" request "https://auth.grammarly.com/v3/api/login" :type "POST" :headers ("accept" . "application/json") ("accept-language" . "en-GB,en-US;q=0.9,en;q=0.8") ("content-type" . "application/json") "user-agent" ("x-client-type" . "funnel") ("x-client-version" . "1.2.2026") "x-container-id" grammarly--get-cookie-by-name "gnar_containerId" "x-csrf-token" "csrf-token" ("sec-fetch-site" . "same-site") ("sec-fetch-mode" . "cors") "cookie" format "gnar_containrId=%s; grauth=%s; csrf-token=%s" "grauth" :data json-encode "email_login" "email" "password" (("secureLogin" . "false")) :success #[128 "\301\302\303\"\210\304\211\207" [grammarly--start-checking-p nil plist-member :response t] 5 "\n\n(fn &key RESPONSE &allow-other-keys)"] :error #[128 "\301\302\303\"\210\304\305\306\"\207" [grammarly--start-checking-p nil plist-member :error-thrown t grammarly--debug-message "[ERROR] Error while authenticating login: %s"] 5 "\n\n(fn &rest ARGS &key ERROR-THROWN &allow-other-keys)"]] 22 (#$ . 6187)]) #@26 Form the authorize list. (defalias 'grammarly--form-authorize-list #[0 "\302!\211A@ \241\210\207" [grammarly--authorize-msg grammarly--cookies copy-sequence] 3 (#$ . 7561)]) #@42 Form a check request by TEXT. (fn TEXT) (defalias 'grammarly--form-check-request #[257 "\301!\211@A\211\302\303\304#\240\266\207" [grammarly--request-check copy-sequence s-replace "$STR$" "+0:0:$STR$:0"] 8 (#$ . 7742)]) #@46 Execution after received all needed cookies. (defalias 'grammarly--after-got-cookie #[0 "\301 \210\302\303\304\305 \306\307\310\311\312\313\314\315& \211\207" [grammarly--client grammarly--kill-websocket websocket-open "wss://capi.grammarly.com/freews" :custom-header-alist grammarly--form-authorize-list :on-open #[257 "\304!\210\305 \306\n!\"\210\305 \306\307 !!\"\207" [grammarly-on-open-function-list grammarly--client grammarly--init-msg grammarly--text grammarly--execute-function-list websocket-send-text json-encode grammarly--form-check-request] 6 "\n\n(fn WS)"] :on-message #[514 "\301\302H\"\210\303\302H!\207" [grammarly-on-message-function-list grammarly--execute-function-list 2 grammarly--default-callback] 6 "\n\n(fn WS FRAME)"] :on-error #[771 "\300\301\"\207" [grammarly--debug-message "[ERROR] Connection error while opening websocket: %s"] 6 "\n\n(fn WS TYPE ERR)"] :on-close #[257 "\301!\207" [grammarly-on-close-function-list grammarly--execute-function-list] 3 "\n\n(fn WS)"]] 12 (#$ . 7972)]) #@68 Reset the timer for the next run with FNC and PRED. (fn FNC PRED) (defalias 'grammarly--reset-timer #[514 "\302 \210\211 \203\303\304\305%\211\207 \207" [grammarly--update-time grammarly--timer grammarly--kill-timer run-with-timer nil grammarly--reset-timer] 8 (#$ . 9002)]) #@46 Default callback, print out DATA. (fn DATA) (defalias 'grammarly--default-callback #[257 "\301\302\303\304#)\266\203\205\305 \207" [inhibit-changing-match-data "\"action\":\"finished\"" nil t string-match grammarly--kill-websocket] 8 (#$ . 9291)]) #@36 Send the TEXT to check. (fn TEXT) (defalias 'grammarly-check-text #[257 "\211;\203\211\211\301\230\262\203\302\303!\207\211\304 \210\305\306\307\"\207" [grammarly--text "" user-error "[ERROR] Text can't be 'nil' or 'empty'" grammarly--get-cookie grammarly--reset-timer grammarly--after-got-cookie (lambda nil (null grammarly--start-checking-p))] 4 (#$ . 9553)]) (provide 'grammarly)