· 5 years ago · Mar 01, 2021, 08:16 PM
1# built-in modules
2import tkinter as tk
3from tkinter import ttk
4import os
5import platform
6import time
7import json
8import html
9import sys
10import subprocess
11from configparser import ConfigParser
12
13settings_file = 'settings.ini'
14settings = ConfigParser()
15settings.read(settings_file)
16
17#system functions
18
19def clear_terminal():
20 return os.system('cls' if os.name == 'nt' else 'clear')
21
22def wait(seconds):
23 return time.sleep(seconds)
24
25def countdown(t):
26 while t > 0:
27 print(t)
28 t -= 1
29 wait(1)
30
31def install(package):
32 clear_terminal()
33 print('A missing package has been detected.. starting download.')
34 countdown(5)
35 subprocess.check_call([sys.executable, "-m", "pip", "install", package, '--user'])
36 clear_terminal()
37
38# acquire external modules
39try:
40 import requests
41except:
42 install('requests')
43 import requests
44
45try:
46 import selenium
47except:
48 install('selenium')
49 import selenium
50
51try:
52 from PIL import Image, ImageTk
53except:
54 install('Pillow')
55 from PIL import Image, ImageTk
56
57from selenium import webdriver
58from selenium.common.exceptions import WebDriverException
59from selenium.webdriver.common.by import By
60from selenium.webdriver.common.action_chains import ActionChains
61from selenium.webdriver.support import expected_conditions as EC
62from selenium.webdriver.support.wait import WebDriverWait
63from selenium.webdriver.common.keys import Keys
64from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
65from selenium.webdriver.chrome.options import Options
66
67#tkinter functions
68
69def select_all(e):
70 e.widget.tag_add("sel","1.0","end")
71def hold_delete(e):
72 e.widget.tag_add("del","end-2c")
73
74def toggle_buttons():
75
76 if str(start_btn["state"]) == "normal":
77 start_text.set("Loading...")
78 start_btn["state"] = "disabled"
79 gl_radio["state"] = "disabled"
80 rs_radio["state"] = "disabled"
81 entry_box["state"] = "disabled"
82 else:
83 start_text.set("Start")
84 start_btn["state"] = "normal"
85 gl_radio["state"] = "normal"
86 rs_radio["state"] = "normal"
87 entry_box["state"] = "normal"
88
89def print_results():
90 entry_box.delete("1.0", "end-1c")
91 for l in affiliated_links:
92 entry_box.insert("end-1c",l + '\n')
93 for line in list_of_failed_links:
94 entry_box.insert("end-1c",line + '\n')
95
96
97
98def create_link_array():
99 global link_array
100 link_array = []
101 box_to_string = entry_box.get("1.0", "end-1c")
102 remove_new_lines_txt= box_to_string.replace("\r", "")
103 remove_blank_txt= remove_new_lines_txt.replace("\n ", "")
104 link_array = remove_blank_txt.split("\n")
105 try:
106 while link_array[-1] == '':
107 link_array.pop()
108 except:
109 print('no links')
110 return link_array
111
112def initdriver():
113
114 global driver
115 global driverwait
116
117 user_agent = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.50 Safari/537.36'
118 options = Options()
119 options.add_argument('user-agent={0}'.format(user_agent))
120 options.add_argument('--headless')
121 options.add_argument("--disable-notifications")
122 options.add_argument('window-size=1920x1080')
123 options.add_argument('log-level=3')
124 options.add_experimental_option('excludeSwitches', ['enable-logging'])
125 options.add_experimental_option("prefs", {
126 "download.default_directory": str(os.getcwd()),
127 "download.prompt_for_download": False,
128 "download._upgrade": True,
129 "safebrowsing.enabled": True
130 })
131
132 # myos = platform.system()
133
134 # if myos == 'Windows':
135 # osdependant = "win"
136
137 # if myos == 'Linux':
138 # osdependant = "linux"
139
140 # if myos == 'Darwin':
141 # osdependant = "mx86"
142
143 # executable_path=osdependant
144 driver = webdriver.Chrome(options=options, executable_path= './mx86')
145 driverwait = WebDriverWait(driver, 3)
146
147def generate_gl(store_link, rewardstyle_link, retailer):
148 # This function creates a GeniusLink via an api post request. Adds a note with the retailer and original store link.
149
150 headers = {
151 'Content-Type': 'application/json',
152 'Accept': 'application/json',
153 'X-Api-Key': settings['GeniusLink']['api_key'],
154 'X-Api-Secret': settings['GeniusLink']['api_secret'],
155 }
156
157 params = (
158 ('url', rewardstyle_link),
159 ('groupId', settings['GeniusLink']['groupID']),
160 ('note', f'{retailer},{store_link}'),
161 )
162
163 data = '{}'
164
165 requests.post('https://api.geni.us/v3/shorturls', headers=headers, params=params, data=data)
166
167
168def generate_affiliate_links(link_array):
169
170 global rs_links
171 global list_of_failed_links
172 list_of_failed_links = []
173 rs_links = {}
174 logged_in = False
175
176 for link in link_array:
177 driver.delete_all_cookies()
178 ninja = "javascript:void((function(){var b=document.createElement('script');b.setAttribute('type','text/javascript');b.setAttribute('charset','UTF-8');b.setAttribute('src','https://ln-rules.rewardstyle.com/bookmarklet.js?r='+Math.random()*99999999);document.body.appendChild(b);})());"
179
180 #navigate to link and launch ninja
181 driver.get(link)
182 wait(1)
183 driver.execute_script(ninja)
184 wait(1)
185 driverwait.until(EC.frame_to_be_available_and_switch_to_it((By.ID,"linkninja-frame-bookmarklet")))
186
187 #check if the applet is logged in
188 if not logged_in:
189 driverwait.until(EC.visibility_of_element_located((By.ID, "login")))
190 driver.find_element(By.NAME, "email").send_keys(settings['RewardStyle']['username'])
191 driver.find_element(By.NAME, "password").send_keys(settings['RewardStyle']['password'])
192 driver.find_element(By.CSS_SELECTOR, ".v-btn--block > .v-btn__content").click()
193 logged_in = True
194
195 #retailer not supported check
196 try:
197 driverwait.until(EC.visibility_of_element_located((By.ID, "advertiser_unsupported")))
198 driver.find_element(By.ID, "cta_report_unsupported_error").click()
199 list_of_failed_links.append(link)
200
201 except:
202 # get retailer name
203 driverwait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".text-truncate")))
204 retailer = driver.find_element(By.CSS_SELECTOR, ".text-truncate").text
205 product = driver.find_element(By.ID, "product_name").text
206 driverwait.until(EC.visibility_of_element_located((By.ID, "cta_get_link")))
207 rewardstyle_link = driver.find_element(By.CSS_SELECTOR, 'div#cta_get_link input').get_attribute('value')
208 driver.switch_to.default_content()
209
210 if geniuslink_enabled.get():
211 generate_gl(link, rewardstyle_link, retailer)
212 else:
213 rs_links[product]=rewardstyle_link
214
215
216def generate_list():
217
218 global list_of_failed_links
219 global affiliated_links
220
221 affiliated_links = []
222
223 if geniuslink_enabled.get():
224
225 headers = {
226 'Content-Type': 'application/json',
227 'X-Api-Key': settings['GeniusLink']['api_key'],
228 'X-Api-Secret': settings['GeniusLink']['api_secret']
229 }
230
231 params = (
232 ('sortBy', 'descending'),
233 ('take', str(len(link_array)-len(list_of_failed_links))),
234 )
235
236 api_request = requests.get('https://api.geni.us/v1/links/list', headers=headers, params=params).json()
237
238 affiliated_links = []
239
240 for each_genius_link in api_request['Results']:
241
242 product_name = ' '.join(str(each_genius_link['ProductDisplayName1']).split()[:8])
243
244 affiliated_links.append((str(product_name)) + ' - https://geni.us/' + str(each_genius_link['ShortUrlCode']))
245
246 else:
247 for key in rs_links:
248 x = str(key)
249 y = ' - '
250 z = str(rs_links[key])
251 affiliated_links.append(x + y + z)
252
253
254 affiliated_links.insert(0,'Affiliated Links: \n\n')
255 list_of_failed_links.insert(0,'\n\nList of Failed Links:\n')
256
257 return affiliated_links,list_of_failed_links
258
259def main():
260 create_link_array()
261 toggle_buttons()
262 root.update()
263 initdriver()
264 generate_affiliate_links(link_array)
265 generate_list()
266 driver.close()
267 toggle_buttons()
268 print_results()
269 root.update()
270
271
272#gui
273root = tk.Tk()
274root.geometry("595x600")
275root.title('Linkr - Affiliate link Generator')
276root.iconphoto(False, tk.PhotoImage(file='icon.png'))
277root.resizable(width=True, height=True)
278root.minsize('595', '600')
279macos='#ececec'
280root.configure(bg=macos)
281root.columnconfigure(0,weight=1)
282root.columnconfigure(1,weight=1)
283root.columnconfigure(2,weight=1)
284root.columnconfigure(3,weight=1)
285root.rowconfigure(0,weight=0)
286root.rowconfigure(1,weight=0)
287root.rowconfigure(2,weight=1)
288root.rowconfigure(3,weight=0)
289root.rowconfigure(4,weight=0)
290root.rowconfigure(5,weight=0)
291root.rowconfigure(6,weight=0)
292root.rowconfigure(7,weight=0)
293root.rowconfigure(8,weight=0)
294
295#enabled keyboard functionality
296root.bind_class("Text","<Command-a>", select_all)
297root.bind_class("Text","<Command-A>", select_all)
298root.bind_class("Text","<Control-a>", select_all)
299root.bind_class("Text","<Control-A>", select_all)
300root.bind("<BackSpace>", hold_delete)
301
302#create the canvas
303canvas = tk.Canvas(root, width=600, height=600, bg= macos,borderwidth=0, highlightthickness=0)
304canvas.grid(columnspan=8, rowspan=8)
305
306
307#create the logo
308logo = Image.open('logo.png')
309logo = ImageTk.PhotoImage(logo)
310logo_label = tk.Label(image=logo,bd=0, highlightthickness=0, bg=macos)
311logo_label.image = logo
312logo_label.grid(column=0, row=0, columnspan=8,padx=(20,30),pady=20)
313
314#create the blurb
315instructions = tk.Label(root, text="Enter your links (one per line) then select your link shortening service:", font="Raleway",pady=2,bg=macos)
316instructions.grid(columnspan=8, column=0, row=1,pady=(0,10),sticky='n')
317
318#create entry box with scrollbars
319entry_box=tk.Text(root, height=20, width=70, wrap='none',highlightthickness=0,bd=1,relief='sunken',padx=3)
320
321yScrollBar= ttk.Scrollbar(root, command=entry_box.yview, orient="vertical",elementborderwidth=-1,highlightcolor='blue')
322yScrollBar.grid(row=2, column=8, sticky="nsw",padx=(0,14),pady=(1,1))
323entry_box.configure(yscrollcommand=yScrollBar.set)
324
325xScrollBar= tk.Scrollbar(root, command=entry_box.xview, orient="horizontal")
326xScrollBar.grid(row=3, column=0, sticky="new",columnspan=8,padx=(15,1))
327entry_box.configure(xscrollcommand=xScrollBar.set)
328
329entry_box.grid(row=2,column=0,columnspan=8,padx=(14,0),sticky='nsew')
330
331#create toggle for geniuslink
332geniuslink_enabled = tk.IntVar(value=1)
333gl_radio = ttk.Radiobutton(root, text ="GeniusLink", variable=geniuslink_enabled, value = 1)
334rs_radio = ttk.Radiobutton(root, text ="RewardStyle", variable=geniuslink_enabled, value = 0)
335
336gl_radio.grid(column=1,row=4,sticky='ne',padx=15,pady=15)
337rs_radio.grid(column=2,row=4,sticky='nw',padx=15,pady=15)
338
339#create start button
340
341start_text = tk.StringVar()
342start_btn = ttk.Button(root, textvariable=start_text, command=lambda:main(),state='normal')
343start_text.set("Start")
344start_btn.grid(column=0, row=5, columnspan=8,pady=(0,15))
345
346root.update()
347root.lift()
348root.mainloop()
349