-
Notifications
You must be signed in to change notification settings - Fork 0
/
pyshare.py
570 lines (485 loc) · 18.7 KB
/
pyshare.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
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
#!/usr/bin/env python3.7
# Leonardo Zanotti
# https://github.com/LeonardoZanotti/pyshare
import csv
import os
import platform
import re
import sys
from datetime import datetime, timedelta
from optparse import OptionParser
import pymongo
from dateutil import parser
from decouple import config
from shareplum import Office365, Site
from shareplum.site import Version
# Colors to outputs
BGreen = "\033[1;32m" # Bold Green
BYellow = "\033[1;33m" # Bold Yellow
BPurple = "\033[1;35m" # Bold Purple
Yellow = "\033[0;33m" # Yellow
Blue = "\033[0;34m" # Blue
Green = "\033[0;32m" # Green
Red = "\033[0;31m" # Red
# Background
On_Black = "\033[40m" # Black Background
class SharePoint:
def __init__(self):
# Set class variables and get environment ones
self.spLogin = config("SP_LOGIN")
self.spPassword = config("SP_PASSWORD")
self.spLink = config("SP_LINK")
self.spSite = config("SP_SITE")
self.spList = config("SP_LIST")
self.mongoClient = config("MONGO_CLIENT")
self.mongoDatabase = config("MONGO_DATABASE")
self.mongoCollection = config("MONGO_COLLECTION")
self.getData = None
self.authSpCookie = None
self.authSpSite = None
self.authSpList = None
def __repr__(self):
return "<" + self.authSpList + ">"
def auth(self):
# Authentication
try:
print(f"{Blue}Authenticating...")
self.authSpCookie = Office365(
self.spLink, username=self.spLogin, password=self.spPassword
).GetCookies()
# Login in the SharePoint
self.authSpSite = Site(
f"{self.spLink}/sites/{self.spSite}",
version=Version.v365,
authcookie=self.authSpCookie,
)
# Enter the site and get the List
self.authSpList = self.authSpSite.List(self.spList)
print(f"{Green}Successfully authenticated!")
except Exception as e:
print(f"{Red}SharePoint authentication failed:", e)
sys.exit(0)
def test(self, option, connect):
try:
if option not in ["sc", "su", "sr", "mc", "mu", "mr"]:
print(
f"{Red}Option should be one of the following: sc, su, sr, mc, mu, mr"
)
return
if connect:
self.mongoConnect()
if option == "sc":
data = [
{
"Title": "comp1",
"Organization": "org1",
"type": "CPG",
"website": "https://google.com",
},
{
"Title": "comp2",
"Organization": "org2",
"type": "Startup",
"website": "https://youtube.com",
},
{
"Title": "comp3",
"Organization": "org3",
"type": "Noice",
"website": "https://uol.com.br",
},
]
created = self.authSpList.UpdateListItems(data=data, kind="New")
if created:
print(f"{Green}Successfully created SP items!")
if option == "su":
data = [
{
"ID": "67",
"Title": "comp2",
"Organization": "org2",
"type": "Startup",
"website": "https://youtube.com",
}
]
updated = self.authSpList.UpdateListItems(data=data, kind="Update")
if updated:
print(f"{Green}Successfully updated SP items!")
if option == "sr":
data = ["66", "69"]
removed = self.authSpList.UpdateListItems(data=data, kind="Delete")
if removed:
print(f"{Green}Successfully removed SP items!")
if option == "mc":
data = [
{
"Title": "comp1",
"Organization": "org1",
"type": "Fixes",
"website": "https://mercadolivre.com",
"UpdatedAt": datetime.now(),
},
{
"Title": "comp2",
"Organization": "org2",
"type": "Tranquilo",
"website": "https://dale.com",
"UpdatedAt": datetime.now() - timedelta(days=1),
},
{
"Title": "comp4",
"Organization": "org4",
"type": "Company",
"website": "https://growinco.com",
"UpdatedAt": datetime.now(),
},
]
created = self.mongoCollection.insert_many(data)
if created:
print(f"{Green}Successfully created Mongo items!")
if option == "mu":
# self.mongoCollection.update_one(
# {"Title": "company four"}, {"$set": {"Title": "company five"}}
# )
updated = self.mongoCollection.update_many(
{"Title": {"$not": re.compile("comp2")}},
{"$set": {"UpdatedAt": datetime.now()}},
)
if updated:
print(f"{Green}Successfully updated Mongo items!")
if option == "mr":
# self.mongoCollection.delete_one({"Organization": "Hero"})
removed = self.mongoCollection.delete_many({})
if removed:
print(f"{Green}Successfully removed Mongo items!")
except Exception as e:
print(f"{Red}Test process failed:", e)
def get(self):
# Get items from the Lists
try:
print(f"{Blue}Getting items from SharePoint...")
# Get the list of the site
self.getData = self.authSpList.GetListItems("All Items")
print(f"{Green}SharePoint data successfully obtained:")
for item in self.getData:
item["website"] = item["website"].split(",")[0]
print(f"{Yellow}", item)
except Exception as e:
print(f"{Red}Failed getting SharePoint Lists:", e)
def download(self):
# Download data as csv from the Lists
try:
print(f"{Blue}Downloading csv...")
path = f"./reports/{self.spList}.csv"
# Get existing data from SharePoint
self.get()
if len(self.getData) == 0:
print(f"{Yellow}No data in the SharePoint!")
return
# Download
with open(f"{path}", "w", encoding="UTF8", newline="") as f:
writer = csv.DictWriter(f, fieldnames=self.getData[0].keys())
writer.writeheader()
writer.writerows(self.getData)
print(f"{Green}Successfully downloaded data from SharePoint!")
print(f"{Green}Report saved to {path}")
except Exception as e:
print(f"{Red}Failed downloading SharePoint Lists:", e)
def insert(self, path):
# Insert data from a worksheet file to Microsoft List
try:
print(f"{Blue}Reading and inserting data...")
# Get existing data from SharePoint
self.get()
# Insert
newData = list()
updateData = list()
with open(path) as csv_file:
csv_reader = csv.reader(csv_file, delimiter=",")
fields = next(csv_reader)
for values in csv_reader:
dictionary = dict(zip(fields, values))
for data in self.getData:
if data["Title"] == dictionary["Title"]:
dictionary["ID"] = data["ID"]
updateData.append(
dictionary
) if "ID" in dictionary else newData.append(dictionary)
inserted = (
self.authSpList.UpdateListItems(data=newData, kind="New")
if len(newData) > 0
else True
)
updated = (
self.authSpList.UpdateListItems(data=updateData, kind="Update")
if len(updateData) > 0
else True
)
if inserted and updated:
print(
f"{Green}Successfully inserted {len(newData)} items and updated {len(updateData)} items in the SharePoint!"
)
except Exception as e:
print(f"{Red}Failed inserting data in the SharePoint:", e)
def create(self, data):
# Create new items
try:
print(f"{Blue}Creating SP items...")
if len(data) == 0:
print(f"{Yellow}No data to create!")
return
created = self.authSpList.UpdateListItems(data=data, kind="New")
if created:
print(f"{Green}Successfully created items!")
except Exception as e:
print(f"{Red}SharePoint Lists creation failed:", e)
def update(self, data):
# Update the list
try:
print(f"{Blue}Updating SP items...")
if len(data) == 0:
print(f"{Yellow}No data to update!")
return
updated = self.authSpList.UpdateListItems(data=data, kind="Update")
if updated:
print(f"{Green}Successfully updated items!")
except Exception as e:
print(f"{Red}SharePoint Lists update failed:", e)
def remove(self, data):
# Remove items
try:
print(f"{Blue}Removing SP items...")
if len(data) == 0:
print(f"{Yellow}No data to remove!")
return
removed = self.authSpList.UpdateListItems(data=data, kind="Delete")
if removed:
print(f"{Green}Successfully removed items!")
except Exception as e:
print(f"{Red}SharePoint Lists remove failed:", e)
def mongoConnect(self):
# MongoDB connection
try:
print(f"{Blue}Connecting to MongoDB...")
self.mongoClient = pymongo.MongoClient(self.mongoClient)
self.mongoDatabase = self.mongoClient[self.mongoDatabase]
self.mongoCollection = self.mongoDatabase[self.mongoCollection]
print(f"{Yellow}Connected:", self.mongoClient.server_info())
print(f"{Green}Successfully connected to MongoDB!")
except Exception as e:
print(f"{Red}Unable to connect to the MongoDB server:", e)
sys.exit(0)
def mongoProcess(self, createData, updateData):
# MongoDB test process
try:
print(f"{Blue}Running MongoDB test process...")
if len(createData) > 0:
print("Creating Mongo data...")
self.mongoCollection.insert_many(createData)
else:
print(f"{Yellow}No data to create!")
if len(updateData) > 0:
print("Updating Mongo data...")
for item in updateData:
self.mongoCollection.update_one(
{"_id": item["_id"]}, {"$set": item}, upsert=False
)
else:
print(f"{Yellow}No data to update!")
items = self.mongoCollection.find({})
for item in items:
print(f"{Yellow}", item)
print(f"{Green}MongoDB test process successfully finished!")
except Exception as e:
print(f"{Red}MongoDB test process failed:", e)
def sync(self):
# Sync MongoDB with SharePoint Lists
try:
print(f"{Blue}Syncing databases...")
# Connect to MongoDB
self.mongoConnect()
# Get existing data from SharePoint
self.get()
spData = self.getData
# Get data from both databases
mongoData = list(self.mongoCollection.find({}))
print(f"{Blue}MongoDB data:")
for item in mongoData:
print(f"{Yellow}", item)
addToMongo = list()
updateToMongo = list()
addToSp = mongoData.copy()
updateToSp = list()
for spItem in spData:
foundInMongo = False
for mongoItem in mongoData:
# Item in the SP and in the MongoDB
if (
mongoItem["Title"] == spItem["Title"]
and mongoItem["Organization"] == spItem["Organization"]
):
foundInMongo = True
if mongoItem in addToSp:
addToSp.remove(mongoItem)
if mongoItem["UpdatedAt"] > spItem["Modificado"]:
# Mongo has the newer version
item = mongoItem.copy()
item["Modificado"] = item["UpdatedAt"]
item.pop("UpdatedAt", None)
item["ID"] = spItem["ID"]
item.pop("_id", None)
updateToSp.append(item)
elif mongoItem["UpdatedAt"] < spItem["Modificado"]:
# SP has the newer version
item = spItem.copy()
item["_id"] = mongoItem["_id"]
item["UpdatedAt"] = item["Modificado"]
item.pop("Modificado", None)
item.pop("ID", None)
updateToMongo.append(item)
else:
# Same item
pass
# Item only in the SP
if not foundInMongo:
item = spItem.copy()
item["UpdatedAt"] = item["Modificado"]
item.pop("Modificado", None)
item.pop("ID", None)
addToMongo.append(item)
for item in addToSp:
item["Modificado"] = item["UpdatedAt"]
item.pop("UpdatedAt", None)
item.pop("_id", None)
print(f"{Green}Adding to Mongo: ", addToMongo)
print(f"{Yellow}Updating to Mongo: ", updateToMongo)
print(f"{Blue}Adding to SP: ", addToSp)
print(f"{Red}Updating to SP: ", updateToSp)
self.mongoProcess(addToMongo, updateToMongo)
self.create(addToSp)
self.update(updateToSp)
print(f"{Green}Successfully synced the databases!")
except Exception as e:
print(f"{Red}Failed syncing databases:", e)
def main():
try:
# Options list
parser = OptionParser(
usage="Usage: python3.7 %prog [options]", add_help_option=True
)
parser.add_option(
"-t",
"--test",
dest="spTest",
metavar="option",
help="perform test operations or some individual function",
)
parser.add_option(
"-g",
"--get",
action="store_true",
dest="spGet",
default=False,
help="list all the items in Microsoft List",
)
parser.add_option(
"-d",
"--download",
action="store_true",
dest="spDownload",
default=False,
help="download all the items in Microsoft List as csv worksheet",
)
parser.add_option(
"-i",
"--insert",
dest="spInsert",
metavar="path",
help="insert data in the SharePoint from a worksheet file",
)
parser.add_option(
"-s",
"--sync",
action="store_true",
dest="spSync",
default=False,
help="synchronize the Microsoft List with the MongoDB database",
)
opts, args = parser.parse_args()
checkColors()
# No options passed
if not any(vars(opts).values()):
showHelp()
return
# Creates new SharePoint instance
sharepoint = SharePoint()
# Authentication
sharepoint.auth()
# Test/Run function
if opts.spTest:
# Should connect to MongoDB
mongoConnect = True if "m" in opts.spTest else False
sharepoint.test(opts.spTest, mongoConnect)
# List items
if opts.spGet:
sharepoint.get()
# Download items data as csv
if opts.spDownload:
sharepoint.download()
# Insert worksheet file data to SharePoint
if opts.spInsert:
sharepoint.insert(opts.spInsert)
# Sync MongoDB and SharePoint
if opts.spSync:
sharepoint.sync()
except Exception as e:
print(f"{Red}Error:", e)
def showHelp():
print(
"""{BPurple}
\t _
\t _ __ _ _ ___| |__ __ _ _ __ ___
\t | '_ \| | | / __| '_ \ / _` | '__/ _ \\
\t | |_) | |_| \__ \ | | | (_| | | | __/
\t | .__/ \__, |___/_| |_|\__,_|_| \___|
\t |_| |___/
\t
{BYellow} # Zanotti's SharePoint automation{Blue}
https://github.com/LeonardoZanotti/pyshare
To see all the program options use:
\t
{BGreen}$ python3.7 pyshare.py -h
""".format(
BPurple=BPurple,
BGreen=BGreen,
Blue=Blue,
BYellow=BYellow,
On_Black=On_Black,
)
)
def checkColors():
global BGreen
global BYellow
global BPurple
global BCyan
global Yellow
global Green
global Red
global Blue
global On_Black
# colors
colors = True # output colored c:
machine = sys.platform # detecting the os
checkPlatform = platform.platform() # get current version of os
if machine.lower().startswith(("os", "win", "darwin", "ios")):
colors = False # Mac and Windows shouldn't display colors :c
if (
checkPlatform.startswith("Windows-10")
and int(platform.version().split(".")[2]) >= 10586
):
color = True # coooolorssss \o/
os.system("") # Enables the ANSI -> standard encoding that reads that colors
if not colors:
BGreen = BYellow = BPurple = BCyan = Yellow = Green = Red = Blue = On_Black = ""
if __name__ == "__main__":
main()