
    g&w                     &   d dl mZ d dlmZ d dlZd dlZd dlZd dlZd dlZd dl	Z	d dl
Z
d dlZd dlZd dlZd dlZd dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d d	lmZ d d
lmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ  G d de      Zy)    )
check_hash)openN)common)config)database)helpers)	libraries)logger)
mobile_app)notification_handler)	notifiers)newsletter_handler)newsletters)plextv)usersc                       e Zd Zd ZddZd Zd Zd ZddZddZ	ddZ
d	 Zd
 Zd Zd Zd Zd Z	 	 ddZddZddZd ZddZddZd Zd Zy) API2c                     | j                         j                         | _        d| _        d| _        d | _        d | _        d | _        d | _        d | _	        d| _
        d | _        d | _        d | _        d| _        y )NFjsonerror)	_api_docskeys_api_valid_methods_api_authenticated_api_out_type_api_msg
_api_debug_api_cmd_api_apikey_api_callback_api_result_type_api_response_code_api_profileme_api_kwargs_api_appselfkwargss     /opt/Tautulli/plexpy/api2.py__init__zAPI2.__init__2   sv    "&.."2"7"7"9"'#! '"&"    c           	         i }t        j                  | t         j                        D ]  \  }}|j                  d      r|j                  d      r*|du rDt        j                  t        | |            rt        j                  t        | |            nd||<   rt        j                  t        | |            r<dj                  t        j                  t        | |            j                               nd||<    |S )z Makes the api docs. )	predicate__apiTN )inspect
getmembersismethod
startswithgetdocgetattrjoinsplit)r'   mddocsfr.   s        r)   r   zAPI2._api_docsA   s     &&tw7G7GH 	DAq<<$Q\\&-A:BI..QXY]_`QaBbgnnWT1-=>hlDGT[TbTbcjkoqrcsTtchhw~~gdA6F'G'M'M'OPz~DG	 r+   c                 "    | j                         S )z- Return the api docs formatted with markdown.)_api_make_mdr'   s    r)   docs_mdzAPI2.docs_mdM   s       ""r+   c                 "    | j                         S )zL Return the api docs as a dict where commands are keys, docstring are value.)r   r>   s    r)   r:   z	API2.docsR   s     ~~r+   c                 v   t         j                  j                  sd| _        d| _        nt         j                  j
                  sd| _        d| _        nt        t         j                  j
                        dk7  rd| _        d| _        nd|vrd| _        d| _        nd	|vr+d
dj                  | j                        z  | _        d| _        ngd	|v rc|j                  d	      | j                  vrFd|j                  d	d      ddj                  t        | j                              | _        d| _        |j                  dd      | _        |j                  dd      | _        |j                  d	d      | _        |j                  dd      | _        |j                  dd      | _        |j                  dd      | _        d|v r+t%        j&                  |j                  d            rd| _        t         j                  j                  r| j                  r| j                  dv r?| j(                  s/| j                  t         j                  j
                  k(  rd| _        n| j(                  r6t-        j.                  | j                        r| j                  dk(  rd| _        n`| j(                  rFt-        j0                  | j                        r't-        j2                  | j                         d| _        nd| _        d| _        | j*                  r'| j                  | j                  v rd| _        || _        n/| j*                  s#| j                  dv rd| _        d| _        || _        | j                  r"t7        j8                  d| j                  z         t7        j8                  d| j4                  z         | j4                  S )z1 Sets class vars and remove unneeded parameters. zAPI not enabledi  zAPI key not generatedi      zAPI key not generated correctlyapikeyzParameter apikey is requiredcmdz4Parameter cmd is required. Possible commands are: %sz,   zUnknown command:  z. Possible commands are: callbackNdebugF	profilemeout_typer   appT)
get_apikeyr:   r?   register_devicezInvalid apikeyzTautulli APIv2 :: %s.z$Tautulli APIv2 :: Cleaned kwargs: %s)plexpyCONFIGAPI_ENABLEDr   r"   API_KEYlenr7   r   getsortedpopr    r   r   r   r#   r   r   	bool_truer%   r   r   get_temp_device_tokenget_mobile_device_by_tokenset_last_seenr$   r
   	api_debug)r'   argsr(   s      r)   _api_validatezAPI2._api_validateW   s    }}((-DM&)D#&&3DM&)D#&&'2-=DM&)D#V#:DM&)D#& RUYU^U^_c_v_vUwwDM&)D#f_E!2$:Q:Q!QPVPZPZ[`bdPegkgpgpqwx|  yP  yP  rQ  hR  SDM&)D##ZZ
D9!::h5

5$/ **We4$jjd;#ZZ
F;F?w00E1BC DM==$$T]]dmmOp>p==T%5%59N9N%N*.':#C#CDDTDT#UMM%66*.':#H#HIYIY#Z(()9)9:*.' !1*-'&&4==D<S<S+S $#) ,,Bc1c*.' $#) ==4t}}DE?$BRBRRSr+   c                    t         j                  j                  t        j                  j
                  t        j                        }g }	t        |      }t        |      }|r=t        j                  d|z         t        j                  |t        j                        }
t        |dd      5 }|j                         D ]  }d}	 |j                  d      }|d   j                  d	      d
   j!                         }|j                  d      }||j#                  dd      }n$|j                  d      d   j#                  dd      }|d   j                  d      d
   }t'        |      dkD  s|||v s|d
   |t)        j*                  |j#                  dd            |d}|	j-                  |        	 ddd       |dk(  r|	ddd   }	|d
kD  s|d
kD  r t        j                  d|d|       |	|| }	r(t        j                  dz         t/        |	fd      }	|rqt        j                  d|z         |	D cg c]=  }|j1                         D ](  \  }}|j3                         |j3                         v s'|* ? }}}}t'        |      r|}	|r_g }|	D ]K  }dj                  d |j1                         D              }
j5                  |      s;|j-                  |       M t'        |      r|}	|	S # t$        $ rE t'        |	      dz
  }|	|   dxx   t)        j*                  |j#                  dd            z  cc<   Y w xY w# 1 sw Y   xY wc c}}}w )a  
            Get the Tautulli logs.

            ```
            Required parameters:
                None

            Optional parameters:
                sort (str):         "time", "thread", "msg", "loglevel"
                search (str):       A string to search for
                order (str):        "desc" or "asc"
                regex (str):        A regex string to search for
                start (int):        Row number to start from
                end (int):          Row number to end at

            Returns:
                json:
                    [{"loglevel": "DEBUG",
                      "msg": "Latest version is 2d10b0748c7fa2ee4cf59960c3d3fffc6aa9512b",
                      "thread": "MainThread",
                      "time": "2016-05-08 09:36:51 "
                      },
                     {...},
                     {...}
                     ]
            ```
        z0Tautulli APIv2 :: Filtering log using regex '%s')flagsrutf-8)encodingNz-    z :r   z :: 
rF   z : msg)timeloglevelrd   threaddescz'Tautulli APIv2 :: Slicing the log from z to z+Tautulli APIv2 :: Sorting log based on '%s'c                     |    S )N )ksorts    r)   <lambda>zAPI2.get_logs.<locals>.<lambda>   s    AdG r+   )keyz/Tautulli APIv2 :: Searching log values for '%s'r0   c              3   F   K   | ]  \  }}d j                  ||        yw)z{}{}N)format).0rl   vs      r)   	<genexpr>z API2.get_logs.<locals>.<genexpr>   s     %PdafmmAq&9%Ps   !)ospathr7   rN   rO   LOG_DIRr
   FILENAMEintrZ   recompileIr   	readlinesr8   stripreplace
IndexErrorrR   r   sanitizeappendrT   itemslowersearch)r'   rm   r   orderregexstartendr(   logfiletemplogregr;   linetemp_loglevel_and_timeloglvltl_treadrd   rg   tldrl   rs   ttl
stringdicts    `                       r)   get_logszAPI2.get_logs   s   8 '',,v}}44fooFE
#hORWWX**U"$$/C'31 	&Q &)-&-1ZZ-=*3A6<<TB1EKKMF#zz&1H~"ll44"jj/2::4D%a[..u5a8F t9q=%;%GFVZN !7q 9$*&//D"0EF"(	A NN1%5&	&: F?ddmG7eaiRWY\]^eC(GJTQRW*;<GNQWWX$ZZZAfllnPQPWPWPY>Y!Z!ZBZ2wB ! XX%Paggi%PP
::j)IIaL!
 2wY " g,*BBK&'*:*:4<<b;Q*RR&		& 	&T [sQ   -MBK2M*M-M2A M<;M8M2A
M <M?M  MMc           	         t         j                  j                  t        j                  d      }t        j
                  |      D cg c]A  }t         j                  j                  t         j                  j                  ||            r|C }}t        j                  j                  }i }|j                         D ]  \  }}t        |t              r_i }	|j                         D ]E  \  }
}|
j                         t        j                  v rd}|dk(  s|dk(  rt        |      |	|
<   A||	|
<   G |	||<   |dk(  s{|||   d<   |||   d<    |r|j!                  |      S |S c c}w )a   Gets all settings from the config file.

            ```
            Required parameters:
                None

            Optional parameters:
                key (str):      Name of a config section to return

            Returns:
                json:
                    {"General": {"api_enabled": true, ...}
                     "Advanced": {"cache_sizemb": "32", ...},
                     ...
                     }
            ```
        zdata/interfaces/N01General	interfaceinterface_list)ru   rv   r7   rN   PROG_DIRlistdirisdirrO   _configr   
isinstancedictupperr   _DO_NOT_DOWNLOAD_KEYSboolrS   )r'   ro   interface_dirnamer   confsettingsrl   rs   r   kkvvs               r)   get_settingszAPI2.get_settings   sG   $ V__6HI+-::m+D L4''--]D(IJ  L L }}$$ JJL 	?DAq!T"ggi #FBxxzV%A%AA!SyB#I $R" ""#  I~+8K(0>,-	? <<$$3Ls   AEc                    t         j                  j                  sd| _        y|sd| _        yt	        t        j                  t         j                  j                              s| j                          nMt        d t        j                  t         j                  j                        D              s| j                          t        j                         }|j                  |      }|S )a   Query the Tautulli database with raw SQL. Automatically makes a backup of
            the database if the latest backup is older then 24h. `api_sql` must be
            manually enabled in the config file while Tautulli is shut down.

            ```
            Required parameters:
                query (str):        The SQL query

            Optional parameters:
                None

            Returns:
                None
            ```
        zSQL not enabled for the API.NzNo SQL query provided.c              3     K   | ]  }t         j                  j                  t         j                  j                  t        j
                  j                  |            t        j                         d z
  kD  xr |j                  d        yw)iQ z.dbN)	ru   rv   getctimer7   rN   rO   
BACKUP_DIRre   endswith)rr   file_s     r)   rt   zAPI2.sql.<locals>.<genexpr>J  sm      a27 ww''V]]5M5Mu(UVZ^ZcZcZehmZmn .u-. as   B
B)rN   rO   API_SQLr   rR   ru   r   r   	backup_dbanyr   MonitorDatabaseselect)r'   querydbrowss       r)   sqlzAPI2.sql,  s      }}$$:DM4DM 2::fmm6678NN  a;=::fmmF^F^;_a a %%'yyr+   c                 R    t        j                         }|r	d| _        |S d| _        |S )z1 Create a manual backup of the `config.ini` file.successr   )r   make_backupr!   r'   datas     r)   backup_configzAPI2.backup_configR  s0     !!#-1	 8?r+   c                 R    t        j                         }|r	d| _        |S d| _        |S )z0 Create a manual backup of the `plexpy.db` file.r   r   )r   r   r!   r   s     r)   r   zAPI2.backup_dbZ  s0     ##%-1	 8?r+   c                 6    dt         _        d| _        d| _        y)z Restart Tautulli.restartzRestarting Tautullir   NrN   SIGNALr   r!   r&   s     r)   r   zAPI2.restartb  s     "- )r+   c                 6    dt         _        d| _        d| _        y)z Update Tautulli.updatezUpdating Tautullir   Nr   r&   s     r)   r   zAPI2.updatei  s     !+ )r+   c                 R    t        j                         }|r	d| _        |S d| _        |S )z% Refresh the Tautulli libraries list.r   r   )r	   refresh_librariesr!   r'   r(   r   s      r)   refresh_libraries_listzAPI2.refresh_libraries_listp  s.    **,-1	 8?r+   c                 R    t        j                         }|r	d| _        |S d| _        |S )z! Refresh the Tautulli users list.r   r   )r   refresh_usersr!   r   s      r)   refresh_users_listzAPI2.refresh_users_listw  s.    ""$-1	 8?r+   Nc           	         |sd| _         d| _        y|sd| _         d| _        y|rft        j                  |      t        j                  t        j
                        kD  r-dj                  t        j
                  |      | _         d| _        y|r||}t        j                  ||| j                  ||||      }	|	rd| _         d| _        t        j                  | j                  d	
       t        j                  d	      }
t        j                         }dt        j                  j                   i}|j#                  |
       |j#                  |       |S d| _         d| _        y)a   Registers the Tautulli Remote App.

            ```
            Required parameters:
                device_id (str):          The unique device identifier for the mobile device
                device_name (str):        The device name of the mobile device

            Optional parameters:
                platform (str):           The platform of the mobile devices
                version (str):            The version of the app
                friendly_name (str):      A friendly name to identify the mobile device
                onesignal_id (str):       The OneSignal id for the mobile device
                min_version (str):        The minimum Tautulli version supported by the mobile device, e.g. v2.5.6

            Returns:
                json:
                    {"pms_identifier": "08u2phnlkdshf890bhdlksghnljsahgleikjfg9t",
                     "pms_ip": "10.10.10.1",
                     "pms_is_remote": 0,
                     "pms_name": "Winterfell-Server",
                     "pms_platform": "Windows",
                     "pms_plexpass": 1,
                     "pms_port": 32400,
                     "pms_ssl": 0,
                     "pms_url": "http://10.10.10.1:32400",
                     "pms_url_manual": 0,
                     "pms_version": "1.20.0.3133-fede5bdc7"
                     "server_id": "2ce060c87958445d8399a7a0c5663755",
                     "tautulli_install_type": "git",
                     "tautulli_branch": "master",
                     "tautulli_commit": "14b98a32e085d969f010f0249c3d2f660db50880",
                     "tautulli_platform": "Windows",
                     "tautulli_platform_device_name": "Winterfell-PC",
                     "tautulli_platform_linux_distro": "",
                     "tautulli_platform_release": "10",
                     "tautulli_platform_version": "10.0.18362",
                     "tautulli_python_version": "3.8.3"
                     "tautulli_version": "v2.5.6",
                     }
            ```
        z2Device registration failed: no device id provided.r   Nz4Device registration failed: no device name provided.z\Device registration failed: Tautulli version {} does not meet the minimum requirement of {}.)	device_iddevice_namedevice_tokenplatformversionfriendly_nameonesignal_idzDevice registration successful.r   T)r   )return_info	server_idz+Device registration failed: database error.)r   r!   r   version_to_tupler   RELEASErq   r   add_mobile_devicer   set_temp_device_tokenr   get_server_resourcesrN   get_tautulli_inforO   PMS_UUIDr   )r'   r   r   r   r   r   r   min_versionr(   resultplex_servertautullir   s                r)   rM   zAPI2.register_device~  sJ   V PDM$+D!RDM$+D!W55kBWE]E]^d^l^lEmmKKQ6RXR`R`bmKn M$+D! -$L--	:E;?;K;K7?6=<I;GI =DM$-D!,,T-=-=tL 55$GK//1H!7!78DKK$KK!K JDM$+D!r+   c                 8   |sd| _         d| _        yt        j                  |      }|sd|z  | _         d| _        yt	        j
                  d       t        j                  d|d||d|}t        |t              rd	| _         d
| _        d|iS d| _         d| _        y)a]   Send a notification using Tautulli.

            ```
            Required parameters:
                notifier_id (int):      The ID number of the notification agent
                subject (str):          The subject of the message
                body (str):             The body of the message

            Optional parameters:
                headers (str):          The JSON headers for webhook notifications
                script_args (str):      The arguments for script notifications

            Returns:
                json:
                    {"notification_id": 1}
            ```
        z-Notification failed: no notifier id provided.r   N)notifier_idz5Notification failed: invalid notifier_id provided %s.z'Tautulli APIv2 :: Sending notification.api)r   notify_actionsubjectbodyzNotification sent.r   notification_idzNotification failed.rk   )
r   r!   r   get_notifier_configr
   rZ   r   notifyr   ry   )r'   r   r   r   r(   notifierr   s          r)   r   zAPI2.notify  s    $ KDM$+D!00[ISVaaDM$+D!BC&-- 8+<A6=378 17	8 gs#0DM$-D!%w//2DM$+D!r+   c           	      :   |sd| _         d| _        yt        j                  |      }|sd|z  | _         d| _        yt	        j
                  d       t        j                  d|d|||d|}t        |t              rd	| _         d
| _        d|iS d| _         d| _        y)a   Send a newsletter using Tautulli.

            ```
            Required parameters:
                newsletter_id (int):    The ID number of the newsletter agent

            Optional parameters:
                subject (str):          The subject of the newsletter
                body (str):             The body of the newsletter
                message (str):          The message of the newsletter

            Returns:
                json:
                    {"newsletter_notification_id": 1}
            ```
        z-Newsletter failed: no newsletter id provided.r   N)newsletter_idz5Newsletter failed: invalid newsletter_id provided %s.z%Tautulli APIv2 :: Sending newsletter.r   )r   r   r   r   messagezNewsletter sent.r   newsletter_notification_idzNewsletter failed.rk   )
r   r!   r   get_newsletter_configr
   rZ   r   r   r   ry   )r'   r   r   r   r   r(   
newsletterr   s           r)   notify_newsletterzAPI2.notify_newsletter  s    " KDM$+D! 66]S
SVccDM$+D!@A$++ 6-:?4;154;	6
 /56 gs#.DM$-D!0'::0DM$+D!r+   c                     d}d}| j                  d      }t        |      D ],  }|j                  |      }|d|z  z  }||sdn|dz   z  }|dz  }. |dz   |z   }d|z   d	z   S )
z2 Tries to make a API.md to simplify the api docs. a  ## General structure
The API endpoint is
```
http://IP_ADDRESS:PORT + [/HTTP_ROOT] + /api/v2?apikey=$apikey&cmd=$command
```

Example:
```
http://localhost:8181/api/v2?apikey=66198313a092496b8a725867d2223b5f&cmd=get_metadata&rating_key=153037
```

Response example (default `json`)
```
{
    "response": {
        "data": [
            {
                "loglevel": "INFO",
                "msg": "Signal 2 caught, saving and exiting...",
                "thread": "MainThread",
                "time": "22-sep-2015 01:42:56 "
            }
        ],
        "message": null,
        "result": "success"
    }
}
```
```
General optional parameters:

    out_type:   "json" or "xml"
    callback:   "pong"
    debug:      1
```

## API methodsrF   T)r9   z### %s
rc   z

z<pre>z</pre>)r   rT   rS   )r'   headr   docrl   rs   r   s          r)   r=   zAPI2._api_make_md6  s    $L nnn% 	A
AJN"DaBQX-DFND		 %(**r+   c                 `   d}t        j                  t        t        j                  d            j                  d            j                         dd }t        j                  j                  rt        j                  j                  r|t        j                  j                  k(  xr$ t        |t        j                  j                        }|rmt        j                  j                  rt        j                  j                  }|S |}|t        j                  _        t        j                  j                          |S d| _        |S t        j                  j                  rt        j                  j                  }|S |}|t        j                  _        t        j                  j                          |S )a   Get the apikey. Username and password are required
            if auth is enabled. Makes and saves the apikey if it does not exist.

            ```
            Required parameters:
                None

            Optional parameters:
                username (str):     Your Tautulli username
                password (str):     Your Tautulli password

            Returns:
                string:             "apikey"
            ```
         N   r`   r   rB   zYAuthentication is enabled, please add the correct username and password to the parameters)hashlibsha224strrandomgetrandbitsencode	hexdigestrN   rO   HTTP_USERNAMEHTTP_PASSWORDr   rQ   writer   )r'   usernamepasswordr   rC   authenticateds         r)   rL   zAPI2.get_apikeyj  s9     F$6$6s$; < C CG LMWWYZ[\^_==&&6==+F+F$(C(CCy
S[]c]j]j]x]xHyM==((!==00D   "D,2FMM)MM'')  !|  }}$$}},, 	 (.%##%r+   c                     |i }d|||diS )zr Formats the result to a predefined dict so we can change it the to
            the desired output by _api_out_as response)r   r   r   rk   )r'   result_typer   rd   s       r)   _api_respondszAPI2._api_responds  s      <D{sDQRRr+   c                 l   | j                   dk(  r|d   d   S | j                   r#| j                   j                  d      r|d   d   S | j                   dk(  r3d| j                  vridt        j                  j
                  d<   |d   d   S | j                   d	k(  r5|d   d   j                  d      |d   d<   |d   d   sd
|d   d   i|d   d<   | j                  dk(  rdt        j                  j
                  d<   	 | j                  rt        j                  |ddd      }nt        j                  |d      }| j                  2dt        j                  j
                  d<   | j                  dz   |z   dz   }nD| j                  dk(  r5dt        j                  j
                  d<   	 t%        j&                  |d      }|j+                  d       S # t        $ rW}t        j                  dt        j                          z          d| _        t        j                          |d<   d
|d<   Y d}~ld}~ww xY w# t        $ r|}t        j(                  d       d| _        	 ||d<   d
|d<   t%        j&                  |d      }n3# t        $ r'}t        j(                  d|z         d|z  }Y d}~nd}~ww xY wY d}~d}~ww xY w)!z, Formats the response to the desired output r?   r	  r   	download_pms_image_proxyreturn_hashz
image/jpegzContent-Typeget_geoip_lookupr   r   r   zapplication/json;charset=UTF-8   TF)indent	sort_keysensure_ascii)r  Nzapplication/javascript(z);zTautulli APIv2 ::   r   xmlzapplication/xml;charset=UTF-8)prettyz,Tautulli APIv2 :: Failed to parse xml resultz=Tautulli APIv2 :: Failed to parse xml result error message %sa?  <?xml version="1.0" encoding="utf-8"?>
                                <response>
                                    <message>%s</message>
                                    <data></data>
                                    <result>error</result>
                                </response>
                          r`   )r   r4   r$   cherrypyr	  headersrS   r   r   r   dumpsr    	Exceptionr
   api_exception	traceback
format_excr"   	xmltodictunparse	api_errorr   )r'   outes      r)   _api_out_aszAPI2._api_out_as  s    ==I%z?6**]]t}}77Dz?6**]]//D$4$44<H!!)).9:v..]]00&)*of&=&A&A&&IC
OF#z?6*+2C
OI4N*OJ''8XH%%n5(??**SdQVWC**Su=C%%1@XH%%--n=,,s2S84?C 5(8WH%%n5"''D9& zz'""9  ($$%9I<P<P<R%RS*-'!*!5!5!7I 'H	(  "  !OP*-'"%&C	N$+CM#++C=C  "$$%dgh%hi !""C""s\   :A;G #H. 	H+AH&&H+.	J37J.!I65J.6	J&?J!J.!J&&J..J3c           	      
   |j                  d      dk(  rg|j                  d      r"t        j                  j                  |d          |j                  d      rjt        j                  j                  |d          nG|j                  d      dk(  r3|j                  d      r"t        j                  j                  |d          d}t        j                  d|z          | j
                  di | | j                  rQ| j                  rEt        | | j                        }| j                  rd	d
l
m}  ||d      }	  |di | j                  }d}	 t+        |t,        t.        f      r|}n|t        ||}|| j<                  dk(  r| j                  rd| _        d| _        t+        |t,              rP|j                  d      r|j?                  dd      | _        |j                  d      r|j?                  dd      | _        | j<                  dk(  r| j                  sd| _        n%| j<                  dk(  r| j                  dk7  rd| _        | j                  sd| _        | j                  t"        j@                  _!        | jE                  | jG                  | j<                  | j(                  |            S # t        $ rm}t        j                  d| j                  d| j                  d|       d| _        | j                   rdt"        j$                  _         d| _        Y d}~d}~ww xY w# t        $ rP 	 t1        j2                  |      }n5# t4        t6        f$ r# 	 t9        j:                  |d      }n#  Y nxY wY nw xY wY w xY w)z$ handles the stuff from the handler rD   rM   r   r   rL   r  Nz,Tautulli APIv2 :: API called with kwargs: %sr   )profileT)	immediatez Tautulli APIv2 :: Failed to run z with z: r  zCheck the logs for errorsrF   )attr_prefixr      r   r   r   rE   )r
  rd   r   rk   )$rS   r
   _BLACKLIST_WORDSaddrZ   r\   r   r   r6   r#   profilehooksr'  r$   r  r"  r"   r   r  requestshow_tracebacksr   r   r   listr   loads
ValueError	TypeErrorr   parser!   rU   r	  statusr%  r  )r'   r[   r(   r   callr'  r$  rets           r)   _api_runzAPI2._api_run  s    ::e 11zz+&''++F;,?@zz.)''++F>,BCZZ,.zz*%''++F:,>?G&PQ$V$==T444/D ""0tt4
<1 0 01 	&4,/# ;COt44	AtG^G^ %.D!&)D# c4 wwy! #	4 8wwx (+$(?%  I-d6M6M&)D#""g-$2I2IS2P&)D#&&&)D##'#:#:  2 2t?T?TZ^ZgZgnq 2 rsso  <  UYUbUbdhdtdtvw!xy*-'??7;H$$4 ;<$  	jj(	* #//&bAC		sg   :J0 !L) 0	L&9A"L!!L&)	N3M	N	M;M10M;1M53M;8N:M;;NN)F)rF   rF   rh   rF   r   r   )rF   )rF   rF   NNrF   NrF   )rF   rF   rF   )rF   rF   rF   rF   )rF   rF   )r   NrF   )__name__
__module____qualname__r*   r   r?   r:   r\   r   r   r   r   r   r   r   r   r   rM   r   r   r=   rL   r  r%  r8  rk   r+   r)   r   r   1   s    
#
 
E N^@,\$L** TXIKZx,\,\2+h'RS<#|Wtr+   r   )hashing_passwordsr   ior   r   r1   r   ru   r   rz   re   r  r  r   rN   r   r   r   r   r	   r
   r   r   r   r   r   r   r   objectr   rk   r+   r)   <module>r?     se   $ )     	  	             '  %   t6 tr+   