• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

sdb9696 / python-ring-doorbell / 6315746352

26 Sep 2023 04:40PM UTC coverage: 61.019% (-5.1%) from 66.139%
6315746352

Pull #3

github

web-flow
Merge 3cc4f4b85 into ee656d852
Pull Request #3: Update to pyproject.toml and poetry and fix docs

7 of 7 new or added lines in 1 file covered. (100.0%)

479 of 785 relevant lines covered (61.02%)

0.61 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/ring_doorbell/cli.py
1
# vim:sw=4:ts=4:et
2
# Many thanks to @troopermax <https://github.com/troopermax>
3
"""Python Ring CLI."""
×
4
import json
×
5
import getpass
×
6
import argparse
×
7
from pathlib import Path
×
8
from oauthlib.oauth2 import MissingTokenError
×
9
from ring_doorbell import Ring, Auth
×
10

11

12
def _header():
×
13
    _bar()
×
14
    print("Ring CLI")
×
15

16

17
def _bar():
×
18
    print("---------------------------------")
×
19

20

21
cache_file = Path("test_token.cache")
×
22

23

24
def token_updated(token):
×
25
    """Writes token to file"""
26
    cache_file.write_text(json.dumps(token), encoding="utf-8")
×
27

28

29
def _format_filename(event):
×
30
    if not isinstance(event, dict):
×
31
        return None
×
32

33
    if event["answered"]:
×
34
        answered_status = "answered"
×
35
    else:
36
        answered_status = "not_answered"
×
37

38
    filename = "{}_{}_{}_{}".format(
×
39
        event["created_at"], event["kind"], answered_status, event["id"]
40
    )
41

42
    filename = filename.replace(" ", "_").replace(":", ".") + ".mp4"
×
43
    return filename
×
44

45

46
def cli():
×
47
    """Command line function."""
48
    parser = argparse.ArgumentParser(
×
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
    )
75

76
    args = parser.parse_args()
×
77
    _header()
×
78

79
    # connect to Ring account
80
    if cache_file.is_file():
×
81
        auth = Auth(
×
82
            "RingCLI/0.6",
83
            json.loads(cache_file.read_text(encoding="utf-8")),
84
            token_updated,
85
        )
86
    else:
87
        if not args.username:
×
88
            args.username = input("Username: ")
×
89

90
        if not args.password:
×
91
            args.password = getpass.getpass("Password: ")
×
92

93
        auth = Auth("RingCLI/0.6", None, token_updated)
×
94
        try:
×
95
            auth.fetch_token(args.username, args.password)
×
96
        except MissingTokenError:
×
97
            auth.fetch_token(args.username, args.password, input("2FA Code: "))
×
98

99
    ring = Ring(auth)
×
100
    ring.update_data()
×
101
    devices = ring.devices()
×
102
    doorbell = devices["doorbots"][0]
×
103

104
    _bar()
×
105

106
    if args.count:
×
107
        print(
×
108
            "\tCounting videos linked on your Ring account.\n"
109
            + "\tThis may take some time....\n"
110
        )
111

112
        events = []
×
113
        counter = 0
×
114
        history = doorbell.history(limit=100)
×
115
        while len(history) > 0:
×
116
            events += history
×
117
            counter += len(history)
×
118
            history = doorbell.history(older_than=history[-1]["id"])
×
119

120
        motion = len([m["kind"] for m in events if m["kind"] == "motion"])
×
121
        ding = len([m["kind"] for m in events if m["kind"] == "ding"])
×
122
        on_demand = len([m["kind"] for m in events if m["kind"] == "on_demand"])
×
123

124
        print("\tTotal videos: {}".format(counter))
×
125
        print("\tDing triggered: {}".format(ding))
×
126
        print("\tMotion triggered: {}".format(motion))
×
127
        print("\tOn-Demand triggered: {}".format(on_demand))
×
128

129
        # already have all events in memory
130
        if args.download_all:
×
131
            counter = 0
×
132
            print(
×
133
                "\tDownloading all videos linked on your Ring account.\n"
134
                + "\tThis may take some time....\n"
135
            )
136

137
            for event in events:
×
138
                counter += 1
×
139
                filename = _format_filename(event)
×
140
                print("\t{}/{} Downloading {}".format(counter, len(events), filename))
×
141

142
                doorbell.recording_download(
×
143
                    event["id"], filename=filename, override=False
144
                )
145

146
    if args.download_all and not args.count:
×
147
        print(
×
148
            "\tDownloading all videos linked on your Ring account.\n"
149
            + "\tThis may take some time....\n"
150
        )
151
        history = doorbell.history(limit=100)
×
152

153
        while len(history) > 0:
×
154
            print(
×
155
                "\tProcessing and downloading the next "
156
                + format(len(history))
157
                + " videos"
158
            )
159

160
            counter = 0
×
161
            for event in history:
×
162
                counter += 1
×
163
                filename = _format_filename(event)
×
164
                print("\t{}/{} Downloading {}".format(counter, len(history), filename))
×
165

166
                doorbell.recording_download(
×
167
                    event["id"], filename=filename, override=False
168
                )
169

170
            history = doorbell.history(limit=100, older_than=history[-1]["id"])
×
171

172

173
if __name__ == "__main__":
×
174
    cli()
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc