-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathldstools.py
executable file
·194 lines (145 loc) · 6.02 KB
/
ldstools.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
#!/usr/bin/python
import requests
import getpass
import json
import sys
import os
from htdb import HomeTeachingDB
class LDSTools(object):
HTVT = {
"currentUser": "https://www.lds.org/htvt/services/v1/user/currentUser",
"members": "https://www.lds.org/htvt/services/v1/{unit}/members",
"memberTags": "https://www.lds.org/htvt/services/v1/{unit}/members/tags",
"districts": "https://www.lds.org/htvt/services/v1/{unit}/districts/{org}",
"summaryStats": "https://www.lds.org/htvt/services/v1/{unit}/unit/summaryStats",
"positions": "https://www.lds.org/htvt/services/v1/{unit}/auxiliaries/positions",
"userStrings": "https://www.lds.org/htvt/services/v1/user/strings/",
}
def __init__(self, username=None, password=None, working_dir="data"):
super(LDSTools, self).__init__()
self.__authenticated = False
self._session = requests.session()
self._username = username
self._api = None
self._user_detail = None
self._current_user = None
self._members_and_callings = None
self._members_htvt = None
self._organization = None
self._districts = None
self._assignment = None
self._positions = None
if not os.path.exists(working_dir):
os.mkdir(working_dir)
self._cwd = working_dir
if username and password:
self.authenticate(username, password)
def sign_in(self):
self._username = self._username or raw_input("username: ")
password = getpass.getpass("password: ")
self.authenticate(self._username, password)
print 'Successfully signed in as "%s"' % (self.currentUser['formattedName'],)
def authenticate(self, username, password):
credentials = {'username' : username, 'password' : password}
self._session.post(self.api['auth-url'], data=credentials)
# TODO: Add a check to validate that authentication was successful
self.__authenticated = True
return self
def getjson(self, url, *args, **kwargs):
import os, json # workaround for a weird bug...
if url.find("{unit}") > -1 or url.find("{org}") > -1:
url = url.format(unit=self.unitNumber, org=self.organization)
print('Attempting to fetch "%s"' % url)
data = json.loads(self._session.get(url, *args, **kwargs).text)
# Store the retrieved data in a file
filename = os.path.splitext(os.path.basename(url))[0]
with open("%s/%s.json" % (self._cwd, filename), 'w') as fp:
json.dump(data, fp, indent=2)
return data
@property
def api(self):
if self._api is None:
self._api = self.getjson('https://tech.lds.org/mobile/ldstools/config.json')
return self._api
@property
def userDetail(self):
if not self.__authenticated:
raise RuntimeError('Must sign in before accessing online data!')
if self._user_detail is None:
self._user_detail = self.getjson(self.api['current-user-detail'])
return self._user_detail
@property
def organization(self):
if self._organization is None:
currentUser = self.getjson(self.HTVT['currentUser'])
for org in currentUser['userOrgRights']:
if org['editable']:
self._organization = org['id']
return self._organization
@property
def districts(self):
if self._districts is None:
self._districts = self.getjson(self.HTVT['districts'])
return self._districts
@property
def positions(self):
if self._positions is None:
self._positions = self.getjson(self.HTVT['positions'])
return self._positions
@property
def unitNumber(self):
return self.userDetail['homeUnitNbr']
@property
def unitMembersAndCallings(self):
if self._members_and_callings is None:
unit = str(self.unitNumber)
url = self.api['unit-members-and-callings-v2'].replace('%@', unit)
self._members_and_callings = self.getjson(url)
return self._members_and_callings
@property
def households(self):
if self._members_htvt is None:
self._members_htvt = self.getjson(self.HTVT['members'])['families']
return self._members_htvt
@property
def directory(self):
return self.unitMembersAndCallings['households']
@property
def callings(self):
return self.unitMembersAndCallings['callings']
@property
def name(self):
return self.unitMembersAndCallings['orgName']
@property
def currentUser(self):
if self._current_user == None:
individualId = self.userDetail['individualId']
self._current_user = self.findIndividual(individualId)
return self._current_user
def findIndividualAndHouse(self, individualId):
blank = {'individualId': -1}
for house in self.households:
headOfHouse = house.get('headOfHouse', blank)
spouse = house.get('spouse', blank) or blank
if individualId == headOfHouse['individualId']:
return headOfHouse, house
elif individualId == spouse['individualId']:
return spouse, house
else:
for child in house.get('children', []):
if individualId == child['individualId']:
return child, house
else:
return blank, blank
def findIndividual(self, individualId):
return self.findIndividualAndHouse(individualId)[0]
def findHousehold(self, individualId):
return self.findIndividualAndHouse(individualId)[1]
if __name__=='__main__':
ward = LDSTools()
ward.sign_in()
print 'Downloaded info for unit: %s - %d' % (ward.name, ward.unitNumber)
htdb = HomeTeachingDB()
htdb.updateHouseholds(ward.households)
htdb.updateDistricts(ward.districts)
htdb.updatePositions(ward.positions)