22# vim:sw=4:ts=4:et
33# Many thanks to @troopermax <https://github.com/troopermax>
44
5+ import json
56import getpass
67import argparse
7- from ring_doorbell import Ring
8+ from pathlib import Path
9+ from ring_doorbell import Ring , Auth
10+ from oauthlib .oauth2 import MissingTokenError
811
912
1013def _header ():
@@ -13,95 +16,106 @@ def _header():
1316
1417
1518def _bar ():
16- print (' ---------------------------------' )
19+ print (" ---------------------------------" )
1720
1821
19- def get_username ():
20- try :
21- username = raw_input ("Username: " )
22- except NameError :
23- username = input ("Username: " )
24- return username
22+ cache_file = Path ("test_token.cache" )
23+
24+
25+ def token_updated (token ):
26+ cache_file .write_text (json .dumps (token ))
2527
2628
2729def _format_filename (event ):
2830 if not isinstance (event , dict ):
2931 return
3032
31- if event [' answered' ]:
32- answered_status = ' answered'
33+ if event [" answered" ]:
34+ answered_status = " answered"
3335 else :
34- answered_status = ' not_answered'
36+ answered_status = " not_answered"
3537
36- filename = "{}_{}_{}_{}" .format (event ['created_at' ],
37- event ['kind' ],
38- answered_status ,
39- event ['id' ])
38+ filename = "{}_{}_{}_{}" .format (
39+ event ["created_at" ], event ["kind" ], answered_status , event ["id" ]
40+ )
4041
41- filename = filename .replace (' ' , '_' ).replace (':' , '.' ) + ' .mp4'
42+ filename = filename .replace (" " , "_" ).replace (":" , "." ) + " .mp4"
4243 return filename
4344
4445
4546def main ():
4647
4748 parser = argparse .ArgumentParser (
48- description = 'Ring Doorbell' ,
49- epilog = 'https://github.com/tchellomello/python-ring-doorbell' ,
50- formatter_class = argparse .RawDescriptionHelpFormatter )
51-
52- parser .add_argument ('-u' ,
53- '--username' ,
54- dest = 'username' ,
55- type = str ,
56- help = 'username for Ring account' )
57-
58- parser .add_argument ('-p' ,
59- '--password' ,
60- type = str ,
61- dest = 'password' ,
62- help = 'username for Ring account' )
63-
64- parser .add_argument ('--count' ,
65- action = 'store_true' ,
66- default = False ,
67- help = 'count the number of videos on your Ring account' )
68-
69- parser .add_argument ('--download-all' ,
70- action = 'store_true' ,
71- default = False ,
72- help = 'download all videos on your Ring account' )
49+ description = "Ring Doorbell" ,
50+ epilog = "https://github.com/tchellomello/python-ring-doorbell" ,
51+ formatter_class = argparse .RawDescriptionHelpFormatter ,
52+ )
53+
54+ parser .add_argument (
55+ "-u" , "--username" , dest = "username" , type = str , help = "username for Ring account"
56+ )
57+
58+ parser .add_argument (
59+ "-p" , "--password" , type = str , dest = "password" , help = "username for Ring account"
60+ )
61+
62+ parser .add_argument (
63+ "--count" ,
64+ action = "store_true" ,
65+ default = False ,
66+ help = "count the number of videos on your Ring account" ,
67+ )
68+
69+ parser .add_argument (
70+ "--download-all" ,
71+ action = "store_true" ,
72+ default = False ,
73+ help = "download all videos on your Ring account" ,
74+ )
7375
7476 args = parser .parse_args ()
7577 _header ()
7678
77- if not args .username :
78- args .username = get_username ()
79+ # connect to Ring account
80+ if cache_file .is_file ():
81+ auth = Auth ("RingCLI/0.6" , json .loads (cache_file .read_text ()), token_updated )
82+ else :
83+ if not args .username :
84+ args .username = input ("Username: " )
85+
86+ if not args .password :
87+ args .password = getpass .getpass ("Password: " )
7988
80- if not args .password :
81- args .password = getpass .getpass ("Password: " )
89+ auth = Auth ("RingCLI/0.6" , None , token_updated )
90+ try :
91+ auth .fetch_token (args .username , args .password )
92+ except MissingTokenError :
93+ auth .fetch_token (args .username , args .password , input ("2FA Code: " ))
8294
83- # connect to Ring account
84- myring = Ring (args .username , args .password )
85- doorbell = myring .doorbells [0 ]
95+ ring = Ring (auth )
96+ ring .update_data ()
97+ devices = ring .devices ()
98+ doorbell = devices ["doorbots" ][0 ]
8699
87100 _bar ()
88101
89102 if args .count :
90- print ("\t Counting videos linked on your Ring account.\n " +
91- "\t This may take some time....\n " )
103+ print (
104+ "\t Counting videos linked on your Ring account.\n "
105+ + "\t This may take some time....\n "
106+ )
92107
93108 events = []
94109 counter = 0
95110 history = doorbell .history (limit = 100 )
96- while ( len (history ) > 0 ) :
111+ while len (history ) > 0 :
97112 events += history
98113 counter += len (history )
99- history = doorbell .history (older_than = history [- 1 ]['id' ])
114+ history = doorbell .history (older_than = history [- 1 ]["id" ])
100115
101- motion = len ([m ['kind' ] for m in events if m ['kind' ] == 'motion' ])
102- ding = len ([m ['kind' ] for m in events if m ['kind' ] == 'ding' ])
103- on_demand = \
104- len ([m ['kind' ] for m in events if m ['kind' ] == 'on_demand' ])
116+ motion = len ([m ["kind" ] for m in events if m ["kind" ] == "motion" ])
117+ ding = len ([m ["kind" ] for m in events if m ["kind" ] == "ding" ])
118+ on_demand = len ([m ["kind" ] for m in events if m ["kind" ] == "on_demand" ])
105119
106120 print ("\t Total videos: {}" .format (counter ))
107121 print ("\t Ding triggered: {}" .format (ding ))
@@ -111,43 +125,44 @@ def main():
111125 # already have all events in memory
112126 if args .download_all :
113127 counter = 0
114- print ("\t Downloading all videos linked on your Ring account.\n " +
115- "\t This may take some time....\n " )
128+ print (
129+ "\t Downloading all videos linked on your Ring account.\n "
130+ + "\t This may take some time....\n "
131+ )
116132
117133 for event in events :
118134 counter += 1
119135 filename = _format_filename (event )
120- print ("\t {}/{} Downloading {}" .format (counter ,
121- len (events ),
122- filename ))
136+ print ("\t {}/{} Downloading {}" .format (counter , len (events ), filename ))
123137
124- doorbell .recording_download (event [ 'id' ],
125- filename = filename ,
126- override = False )
138+ doorbell .recording_download (
139+ event [ "id" ], filename = filename , override = False
140+ )
127141
128142 if args .download_all and not args .count :
129- print ("\t Downloading all videos linked on your Ring account.\n " +
130- "\t This may take some time....\n " )
143+ print (
144+ "\t Downloading all videos linked on your Ring account.\n "
145+ + "\t This may take some time....\n "
146+ )
131147 history = doorbell .history (limit = 100 )
132148
133- while (len (history ) > 0 ):
134- print ("\t Processing and downloading the next" +
135- " videos" .format (len (history )))
149+ while len (history ) > 0 :
150+ print (
151+ "\t Processing and downloading the next" + " videos" .format (len (history ))
152+ )
136153
137154 counter = 0
138155 for event in history :
139156 counter += 1
140157 filename = _format_filename (event )
141- print ("\t {}/{} Downloading {}" .format (counter ,
142- len (history ),
143- filename ))
158+ print ("\t {}/{} Downloading {}" .format (counter , len (history ), filename ))
144159
145- doorbell .recording_download (event [ 'id' ],
146- filename = filename ,
147- override = False )
160+ doorbell .recording_download (
161+ event [ "id" ], filename = filename , override = False
162+ )
148163
149- history = doorbell .history (limit = 100 , older_than = history [- 1 ]['id' ])
164+ history = doorbell .history (limit = 100 , older_than = history [- 1 ]["id" ])
150165
151166
152- if __name__ == ' __main__' :
167+ if __name__ == " __main__" :
153168 main ()
0 commit comments