-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfacebookposter_unotaku.py
More file actions
377 lines (327 loc) · 19.7 KB
/
facebookposter_unotaku.py
File metadata and controls
377 lines (327 loc) · 19.7 KB
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
# -*- coding: utf-8 -*-
"""FacebookPoster_UNOTaku.ipynb
Automatically generated by Colaboratory.
Original file is located at
https://colab.research.google.com/drive/1YlNMb8agFXmeOKrBWBa1xpr2FCQ5vRKG
"""
# !pip install selenium
# !pip install datetime
# !pip install chromedriver_binary
# !pip install time
# !pip install datetime
import selenium
import re
import chromedriver_binary
import time
import pandas as pd
import numpy as np
import datetime as dt
from urllib.request import urlopen as uopen
from urllib.error import HTTPError
from urllib.error import URLError
from bs4 import BeautifulSoup as bs
from BeautifulSoup import BeautifulSoup
from selenium import webdriver as webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.support.ui import WebDriverWait as WDWait
from selenium.webdriver.support import expected_conditions as EC
from requests_html import HTMLSession
from time import sleep
from datetime import datetime
# The following programs for web-scraping/ Selenium-web-based injections by
# Tony Avellino Ianacone(picano), Kevin 'Kev' Elder, and Kevin Alan Spohn
try:
yrSheets = ["2020","2021", "2022", "2023", "2024", "2025", "2026",
"2027", "2028", "2029", "2030"] # Append/ Modify Array as time transpires,
# and compile relevant data based on previous msgs and correspond the files
# to the same format for Discord purposes... It's okay to rehash the same
# msgs from previous yrs.
maxYrStr = "2021"
# *INSTRUCTIONS ON HOW TO USE: !!! DO NOT SKIP !!! BEING SUPER CEREAL RN!!!*
# Modify 6 elements when using for subsequent times: (1.) yrSheets Values,
# (2.) *.xlsx file extension / PATHName # for Excel file feed-in,
# (3.) maxYrStr (max Yr FB Allows for posting rn... this current year and
# the next; typically maxYrIdx > i aka currYrIdx) # (4.) currYear (this
# year you're using it... Duh), # (5,6). # parity of (UserName,Password);
# preferably of an FB account w/ writer/admin credentials for UNOTaku FB
# Web Page...
maxYrIdx = 0 # The rest should be taken care of internally, as it iterates
# and interacts # with webpages thru python automated script...
maxYrIdx = yrSheets.index(maxYrStr) if(maxYrIdx != -1) else (0)
# print(f"maxYrIdx: {maxYrIdx}\n")
# Run on Thursdays,typically 5:30PM CST...
# And AT LEAST 20 Minutes Prior to current club meeting.
# Post Indiscriminantly for all Thursdays that
# adhere to these parameters, in a for or while loop fashion.
# Post time no. idx, return to UNOTaku default FB home page, click post
# button again, and do the process until no remaining dt objects left...
currYr = "2021" #Assign currIdx given currYr
i = 0 # Use currIdx,i, as the array's sheetNames, and currNames
i = yrSheets.index(currYr) if(i != -1) else (0)
# of the files' sheets as yrs...& a counter to keep track of
# parsing the loop
# print(f"i: {i}\n")
colIdx = [] # Columns A-P for all; Assume row=0
for index in range(0,16,1):
colIdx.append(index)
# print(f"colIdx: {colIdx}\n")
pdPATHNAME = f"UNOTaku Auto_Posting Query.xlsx"
df_sheets = []
for k in range(i,maxYrIdx + i, 1):
df_sheet = df_sheets.append(pd.read_excel(pdPATHNAME,
sheet_name=yrSheets[k], usecols=colIdx))
#reads df_sheets as an array of the sheets, and the df elements,
# denote the elements...
# print("df_sheets: {df_sheets}\n")
msgs = [] # Append msgs, monthName, monthNum, dayNum by wholesale
monthNames = [] # column vectors,containing the related elements in
monthNums = [] # column form... Next portion iterates in time traversal order
dayNum = [] # of O(n^2)
yrs = [] # message string vector, month name array, num month array,
msgsYrSuper = [] # dayNum array, and corresponding yrs for the whole
# traversal...
timePostStr = "5:30PM" # Retrieve all data from the current year, and the
# next, due to FB
wkdayToPost = "Thursday" # time-dependencies. Store residual data in files
# exterior thereof and modify the read excel function PathName when doing
# so... Desktop traversal for users is preferred...
c = i
# print(f"c0:{c}\n")
for j in range(len(df_sheets)):
df = df_sheets[j]
#print(f"df: {df}\n")
while (c < (maxYrIdx + i) and c != -1 and maxYrIdx != -1):
# populating arrays with the df column vector elements for each
# category... # Take your pick of the arrays... Same length
# Assuming, that for all covector matrices containing data, they
# are # all of the same length... nx20 matrix for df...
for idx in range(0, len(df["Reminder Message Text"]), 1):
msgs.append(el for el in df["Reminder Message Text"])
# print(f"msgs: {msgs}\n")
yrs.append(int(el) for el in df["Year"])
# print(f"yrs: {yrs}\n")
monthNames.append(el for el in df["Month Name"])
# print("monthNames: {monthNames}\n")
monthNums.append(int(el) for el in df["Month"])
# print("monthNums: {monthNums}\n")
dayNum.append(int(el) for el in df["Day"])
# print("dayNum: {dayNum}\n")
# print(f"c:{c}\n")
c+= 1
dateTimeStrings = []
currStr = "" # read in a string of the array vectors, of same
i = yrSheets.index(currYr) if(i != -1) else (0) # length, seen above. Derive
# this in order to obtain values for date time string as it iterates thru
# the double for-loop
# print(f"i: {i}\n")
# iterate a double for loop for specific date/time object strings to parse
# using # time.strftime(dateTimeString, "Format for Output here...")...
#Normal circumstances, # i ALWAYS <= maxYearAllowedBY_FB_RN
for idx in range(i, maxYrIdx+i,1):
#iterate the covectors indices...
for j in range(len(msgs)):
currStr = "{0}, {1} {2}, {3}, {4}".format(wkdayToPost,
monthNames[j], dayNum[j], yrs[j], timePostStr)
# Assuming CST as TimeZone for all dt objects created...
# print(f"currStr:{currStr}\n")
#Insert name of all elements in dateTime order/ fashion here
dateTimeStrings.append(currStr)
# print(f"dateTimeStrings: {dateTimeStrings}\n")
msgsYrSuper.append(msgs[j]) #Append All Messages to be posted by yr.
# print(f"msgsYrSuper: {msgsYrSuper}\n")
# print(f"dateTimeStrings: {dateTimeStrings}\n")
# print(f"msgsYrSuper: {msgsYrSuper}\n")
# flattens the array into a set of datetime_strings -> datetime objects
date_times = []
# Iterate for the wholesale column co-vectors containing data, and
# append all elements [i] for arrays and vectors to dateTimeStrings el_i
# Convert all dateTimeString elements into datetime objects using strftime
for idx in range(len(dateTimeStrings)):
# print(f" dateTimeStrings el at {idx}: {dateTimeStrings[idx]}\n")
date_times.append(dt.datetime.strptime(dateTimeStrings[idx],
"%A, %B %-d, %Y, %-I:%M%p"))
# print(f"date_times array:" +
# f"{el.strftime("%A, %B %-d, %Y, %-I:%M%p") for el in date_times}\n")
# Debug Statement checking contents of DT Array
# USER LOGIN FB:
# Example UserName: mlpfanatic903@gmail.com
# Password: [... pwd Redacted]
userName = "userNameHere"
pwd = "passwordHere"
# w/o chromedriver_binary,
# PATH = "C:\\Users\\User\\Desktop\\chromedriver.exe"
# for driver = webdriver.Chrome(PATH)
# , and FB path name for typical login sequence.
driverBrowser = raw_input(f"What browser are you currently using" +
f"(Chrome, Mozilla Firefox, Internet Explorer)?\nMicrosoft Edge," +
f"Safari browsers are not allowed yet...\n")
while driverBrowser.upper() != "CHROME"
or (driverBrowser.upper() != "FIREFOX"
or driverBrowser.upper() != "MOZILLA FIREFOX")
or (driverBrowser.upper() != "INTERNET EXPLORER" or
driverBrowser.upper() != "IE"):
print(f"driverBrowser is not of proper type."
+ f"The proper Browsers are Chrome, Firefox, and IE."
+ f"Please try again.\n")
driverBrowser = raw_input(f"What browser are you currently using"
+ f"(Chrome, Mozilla Firefox, Internet Explorer)?"
+ f"\nMicrosoft Edge, Safari browsers are not allowed yet...\n")
# print(f"driverBrowser: {driverBrowser}\n")
usedByMobileDevice = raw_input(f"Are you using a browser" +
f"injection on a mobile device(y/n)?\n")
while usedByMobileDevice != "Y" or usedByMobileDevice != "N":
print(f"{usedByMobileDevice} is not of proper form" +
".\n"+ "Please use (Y/N, y/n) for input.\n")
usedByMobileDevice = raw_input(f"Are you using a browser" +
f" injection on a mobile device(y/n)?\n")
usedByMobileDevice = usedByMobileDevice.upper()
# print(f"usedByMobileDevice: {usedByMobileDevice}\n")
mobileDevice = raw_input(f"If so, which device type are you using" +
f" (iPhone, Android)?\n")
# print(f"mobileDevice: {mobileDevice}\n")
while mobileDevice.upper() != "NONE"
or mobileDevice.upper() != "IPHONE"
or mobileDevice.upper() != "ANDROID":
print(f"{mobileDevice} is not an acceptable"+
"input for Mobile Device.\nIf no device is" +
" currently being used, then please type" +
" NONE. Else, please select (iPhone, Android)." +
"\nNo other mobile device is allowed by Python" +
"input.\nSo sorry about that...\n")
mobileDevice = raw_input("If so, which device" +
"type are you using (iPhone, Android)?\n")
# Assignment of driver based on responses of input above...
driver = webdriver.Chrome() if (driverBrowser.upper() == "CHROME"
and usedByMobileDevice== "N") else webdriver.Firefox()
if (driverBrowser.upper() == "FIREFOX" or driverBrowser.upper()
== "MOZILLA FIREFOX" and usedByMobileDevice== "N") else
webdriver.IE() if (driverBrowser.upper()== "INTERNET EXPLORER"
or driverBrowser.upper() == "IE" and usedByMobileDevice== "N") else
webdriver.Remote(browser_name="iphone", command_executor=
"http://172.24.101.36:3001/hub") if (usedByMobileDevice == "Y"
and mobileDevice.upper() =="IPHONE") else webdriver.Remote(
browser_name="android", command_executor="http://127.0.0.1:8080/hub")
if (usedByMobileDevice.UPPER() == "Y" and mobileDevice.upper()==
"ANDROID") else null
# print browser type here...
if driver != null:
# Select Browser type then, login screen for FB...
driver.get("https://www.facebook.com/login.php?login_attempt=1&lwv=110")
driver.implicitly_wait(30)
print("Opened facebook...\n")
# Attempt to feed in keys {"User Name": userName, "password": pwd}
email = driver.find_element_by_xpath(
"//input[@id='email' or @name='email']")
email.send_keys(userName)
print("User Name entered...\n")
password = driver.find_element_by_xpath("//input[@id='pass']")
password.send_keys(pwd)
print("Password entered...\n")
#Login Attempt, and it spits user out @ their Home Page
button = driver.find_element_by_xpath("//button[@id='loginbutton']")
button.click()
driver.implicitly_wait(30)
print("Login Button Clicked; FB opened & Logged in...\n")
idx = 0
# UNOTaku Website
driver.get("https://www.facebook.com/UNOtaku.club/publishing_tools/?refSource=pages_manager_bar")
driver.implicitly_wait(30)
minLen = Math.min(len(date_times), len(msgsYrSuper))
while idx < minLen:
if date_times[idx].total_seconds()<= 6480000
and date_times[idx] is not None:
createPostButton = driver.find_element_by_xpath(
"//div[@class='g1fckbup dfy4e4am gcxdxe9k sdgvddc7 b8b10xji okyvhjd0 rpcniqb6 jytk9n0j ojz0a1ch avm085bc mtc4pi7f jza0iyw7 njc9t6cs qhe9tvzt spzutpn9 puibpoiz svsqgeze if5qj5rh har4n1i8 diwav8v6 nlmdo9b9 h706y6tg qbdq5e12 j90q0chr rbzcxh88 h8e39ki1 rgsc13q7 a53abz89 llt6l64p pt6x234n bmtosu2b ndrgvajj s7wjoji2 jztyeye0 d5rc5kzv jdcxz0ji frrweqq6 qnavoh4n b1hd98k5 c332bl9r f1dwqt7s rqkdmjxc tb4cuiq2 nmystfjm kojzg8i3 m33fj6rl wy1fu5n8 chuaj5k6 hkz453cq dkjikr3h ay1kswi3 lcvupfea siqinikb ppbiusal']")
createPostButton.click()
#print("Clicking createPostButton.\n")
driver.implicitly_wait(30)
#send messages to webpage...
post = driver.find_element_by_xpath(
"//div[@aria-label='Write into the dialogue box to include text with your post.' and @class='notranslate _5rpu']")
post.send_keys(msgsYrSuper[idx])
#print("Sending message to FB Post Element.\n")
publishOptions = driver.find_element_by_xpath("//div[class='@rxo4gu2c'] ")
#print("Getting publishOptions Element in div tag.\n")
scheduleDate = publishOptions.find_element_by_xpath("//div[@role='button' and @class='g1fckbup dfy4e4am gcxdxe9k sdgvddc7 b8b10xji okyvhjd0 rpcniqb6 jytk9n0j ojz0a1ch avm085bc mtc4pi7f jza0iyw7 njc9t6cs qhe9tvzt spzutpn9 puibpoiz svsqgeze if5qj5rh har4n1i8 diwav8v6 nlmdo9b9 h706y6tg qbdq5e12 j90q0chr rbzcxh88 h8e39ki1 rgsc13q7 a53abz89 llt6l64p tn64ylxs bmtosu2b ndrgvajj s7wjoji2 jztyeye0 d5rc5kzv jdcxz0ji frrweqq6 qnavoh4n b1hd98k5 c332bl9r f1dwqt7s rqkdmjxc tb4cuiq2 nmystfjm kojzg8i3 m33fj6rl wy1fu5n8 chuaj5k6 hkz453cq dkjikr3h ay1kswi3 lcvupfea siqinikb ppbiusal']")
scheduleDate.click()
#print("Clicking scheduleDateButton.\n")
#schedule
dateTimePostButton = driver.find_element_by_xpath("//div[@class='s7wjoji2 tds9wb2m']")
dateTimePostButton = dateTimePostButton.click()
driver.implicitly_wait(30)
#print("Clicking dTPostButton.\n")
postTypeButton = driver.find_element_by_xpath(
"//button[@title='Select post type (draft post, schedule post)' and @class='_50o7 touchable _6-t _3ni8 postTypeButton']")
postTypeButton.click()
#print("Clicking postTypeButton.\n")
#dropdown menu of date_times'_objects here...
driver.implicitly_wait(30)
#...make sure that the same updated webpage
scheduleButton = postTypeButton.find_element_by_xpath(
"//label[@data-sigil='content_type_scheduled touchable' and @class='_5aqb touchable _skt']")
scheduleButton.click()
#print("Clicking scheduleButton.\n")
driver.implicitly_wait(30)
scheduleButton.find_element_by_xpath("//body[@class='_6nw _4lh hasPagesManagerNavbar _8m53 _-kb _605a t_apw_zaizg chrome webkit x1 Locale_en_US _19_u']")
scheduleButton.click()
driver.implicitly_wait(30)
sendDate = scheduleButton.find_element_by_xpath("//input[@placeholder='mm/dd/yyyy' and @aria-labelledby='js_20 js_26']")
sendDate.send_keys(date_times[idx].strftime("%-m/%-d/%Y"))
#print(f"Feeding specific dates to FB.\n")
driver.implicitly_wait(30)
sendHr = scheduleButton.find_element_by_xpath("//input[@aria-disabled='false' and @aria-label='hours' and @aria-valuemax='12' and @aria-valuemin='1']")
sendHr = sendHr.send_keys(date_times[idx].strftime("%I"))# :%M%p
#print(f"Feeding hours to FB.\n")
driver.implicitly_wait(30)
sendMin = scheduleButton.find_element_by_xpath("//input[@aria-disabled='false' and @aria-label='minutes' and @aria-valuemax='59' and @aria-valuemin='0']"
sendMin = sendMin.send_keys(date_times[idx].strftime("%M"))
#print(f"Feeding minutes to FB.\n")
driver.implicitly_wait(30)
sendAMPM = scheduleButton.find_element_by_xpath("//input[aria-disabled='false' and @aria-label='meridiem' and aria-valuemax='1' and @aria-valuemin='0']")
sendAMPM = sendAMPM.send_keys(date_times[idx].strftime("%p"))
#print(f"Feeding AM/PM modifier to FB.\n")
driver.implicitly_wait(30)
scheduleSecondButton = scheduleButton.find_element_by_xpath("//div[@class='g1fckbup dfy4e4am gcxdxe9k sdgvddc7 b8b10xji okyvhjd0 rpcniqb6 jytk9n0j ojz0a1ch avm085bc mtc4pi7f jza0iyw7 njc9t6cs qhe9tvzt spzutpn9 puibpoiz svsqgeze if5qj5rh har4n1i8 diwav8v6 nlmdo9b9 h706y6tg qbdq5e12 j90q0chr rbzcxh88 h8e39ki1 rgsc13q7 a53abz89 llt6l64p pt6x234n bmtosu2b hk3wrqk2 s7wjoji2 jztyeye0 d5rc5kzv jdcxz0ji frrweqq6 qnavoh4n b1hd98k5 c332bl9r f1dwqt7s rqkdmjxc tb4cuiq2 nmystfjm kojzg8i3 m33fj6rl wy1fu5n8 chuaj5k6 hkz453cq dkjikr3h ay1kswi3 lcvupfea siqinikb ppbiusal']")
scheduleSecondButton.click()
#print("Clicking scheduleSecondButton.\n")
driver.implicitly_wait(30)
schedulePostButton = scheduleSecondButton.find_element_by_xpath("//div[@class='g1fckbup dfy4e4am gcxdxe9k sdgvddc7 b8b10xji okyvhjd0 rpcniqb6 jytk9n0j ojz0a1ch avm085bc mtc4pi7f jza0iyw7 njc9t6cs qhe9tvzt spzutpn9 puibpoiz svsqgeze if5qj5rh har4n1i8 diwav8v6 nlmdo9b9 h706y6tg qbdq5e12 j90q0chr rbzcxh88 h8e39ki1 rgsc13q7 a53abz89 llt6l64p pt6x234n bmtosu2b ndrgvajj s7wjoji2 jztyeye0 d5rc5kzv jdcxz0ji frrweqq6 qnavoh4n b1hd98k5 c332bl9r f1dwqt7s rqkdmjxc tb4cuiq2 nmystfjm kojzg8i3 m33fj6rl wy1fu5n8 chuaj5k6 hkz453cq dkjikr3h ay1kswi3 lcvupfea siqinikb ppbiusal']")
schedulePostButton.click()
#print("Clicking schedulePostButton.\n")
driver.implicitly_wait(30)
#Iterate process for all possible scheduled msgs, but without
# clicking the # "Posts" button this time...
# (i.e. repeat from there)...
#print(f"Post Successful.\n")
idx += 1
except HTTPError, he:
print("Web Browser/ Web Page Not Found or Cannot Be Opened.\n")
except URLError, ue:
print("Web Page cannot locate specific URL tag specified.\n")
except NoSuchElementException, nsee:
print("Element is not found, is null/ empty or does not exist.\n")
except IOError, ioe:
print("The *.csv file requested to be opened and written upon" +
" cannot be accomplished, for some reason.\n" +
"Please check your settings, and try again...\n")
except TimeoutException, te:
print("Session has timed out. Please try again.\n")
except Error, e:
print("Miscellaneous Error type... Something went horribly "+
"wrong, sir/madam.\nCheck the compiler for more...\n")
except Exception, e:
print("Miscellaneous Exception type... Something went " +
"terribly wrong, sir/madam.\nCheck the compiler for more...\n")
else:
print("Facebook Posts for the next 75 days have been "+
"successfully posted to FB UNOTaku Webpage...\n" +
+"Unfortunately, SteveBot is not allowed to do more," +
" so please check back in ~2.5 months or so...\n " +
"Thank you for your patience and understanding...\n" +
"See you then...\n")
driver.close()
driver.quit()