#include <iostream>
#include <Windows.h>
#include <Commctrl.h>
#include <shellapi.h>
#include "windows_gui.hpp"
///////////////////////////
//
// NOTES:
//
// - The following .hpp files are included in this file:
// - windows_gui.hpp
// - windows_gui.hpp in turn calls the following .hpp file:
// - search_strategy_factory.hpp
//
///////////////////////////
using namespace std;
HWND get_hwnd_by_title_part(const char*);
HHOOK _hook;
HMENU menu;
HWND hwnd_main_window;
LRESULT __stdcall MouseCallback(int nCode, WPARAM wParam, LPARAM lParam)
{
switch(wParam)
{
case WM_LBUTTONUP:
{
// get the text of the tree item
DWORD pid = 0;
DWORD bytes_read = 0;
DWORD bytes_written = 0;
BOOL debug = false;
int text_buffer_size = 256;
char text[256];
//get the point & get the hwnd from that point
POINT pt;
GetCursorPos(&pt);
HWND hwnd_clicked = WindowFromPoint(pt);
char class_name[256];
GetClassName(hwnd_clicked, class_name, 256);
//do not go any further if it's not a TreeViewList item
if (strcmp(class_name, "SysTreeView32") != 0) break;
//get HTREEITEM from hwnd
TreeView_GetSelection(hwnd_clicked);
HTREEITEM htreeitem_selected = (HTREEITEM)SendMessage(hwnd_clicked, TVM_GETNEXTITEM, TVGN_DROPHILITE, 0);
//new TVITEM to place in the remote prcess
TVITEM item;
item.hItem = htreeitem_selected;
item.mask = TVIF_TEXT | TVIF_HANDLE;
item.pszText = new TCHAR[256];
item.cchTextMax = 256;
//open process
GetWindowThreadProcessId(hwnd_main_window, &pid);
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
//VirtualAllocEx (treeview)
//VirtualAllocEx (text)
//
// Both functions return a pointer to the allocated memory. Since it has EX at the end, it goes to another process.
LPVOID remote_item_address = VirtualAllocEx(hProcess, 0, sizeof(TVITEM), MEM_COMMIT, PAGE_READWRITE);
LPVOID remote_text_address = VirtualAllocEx(hProcess, 0, text_buffer_size, MEM_COMMIT, PAGE_READWRITE);
//
//
//This following line is very important. The whole TVITEM structure will be sent to the process. The TVITEM.psText will have the results of the the second call we made to VirtualAllocEx, which is for text. It's like a double pointer.
//
// According to https://docs.microsoft.com/en-us/windows/win32/controls/tvm-getitem
// "If the TVIF_TEXT flag is set in the mask member of the TVITEM or TVITEMEX structure, the pszText member must point to a valid buffer and the cchTextMax member must be set to the number of characters in that buffer"
item.pszText = (LPTSTR)remote_text_address;
//WriteProcessMemory (Puts OUR local TVITEM object into the remote process)
//SendMessageA (message is TVM_GETITEM, and fills out the TVItem structure we put in)
//GetLastError (error checking)
//ReadProcessMemory (gets the remote TVITEM object at remote_item_address, and puts it in local &item)
//ReadProcessMemory (gets the remote text object at remote_text_address, and puts it in local &buffer)
BOOL write_process = WriteProcessMemory(hProcess, remote_item_address, &item, sizeof(TVITEM), &bytes_written);
BOOL sent_message = SendMessageA(hwnd_clicked, TVM_GETITEM, TVGN_CARET, (LPARAM)remote_item_address);
// get last error
DWORD last_error = GetLastError();
ReadProcessMemory(hProcess, remote_item_address, &item, sizeof(TVITEM), &bytes_read);
CHAR buffer[256];
ReadProcessMemory(hProcess, remote_text_address, &buffer, text_buffer_size - 1, &bytes_read);
//print out
if(debug)
{
cout << "write process: " << write_process << endl;
cout << "sent message: " << sent_message << endl;
cout << "last error: " << last_error << endl;
cout << "bytes_written: " << bytes_written << endl;
cout << "bytes_read: " << bytes_read << endl;
cout << "Text: " << text << endl;
cout << "Buffer: " << buffer << endl;
cout << endl;
}
//free memory
VirtualFreeEx(hProcess, remote_item_address, sizeof(TVITEM), MEM_RELEASE);
VirtualFreeEx(hProcess, remote_text_address, text_buffer_size, MEM_RELEASE);
CloseHandle(hProcess);
//search
if(strlen(buffer) < 1) break;
//search instance is defined in
search_instance.search(buffer);
break;
}
case WM_COMMAND:
{
cout << "Command" << endl;
break;
}
case WM_INITMENUPOPUP:
{
cout << "Goon" << endl;
break;
}
}
return CallNextHookEx(_hook, nCode, wParam, lParam);
}
HWND get_hwnd_by_title_part(const char* title_part)
{
HWND hwnd = NULL;
while (hwnd = FindWindowEx(NULL, hwnd, NULL, NULL))
{
char title[256];
GetWindowText(hwnd, title, 256);
if (strstr(title, title_part))
{
return hwnd;
}
}
return NULL;
}
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
// get the hwnd of the main_window window
hwnd_main_window = get_hwnd_by_title_part("Explorer");
cout << "hwnd_main_window: " << hwnd_main_window << endl;
// set the hook for left mouse clicks
if (!(_hook = SetWindowsHookEx(WH_MOUSE_LL, MouseCallback, hInstance, 0)))
{
MessageBox(NULL, "Failed to install hook!", "Error", MB_ICONERROR);
}
// create the window to search in different pages (windows_gui.hpp)
HWND hwnd_search_window = create_basic_window();
// getdlgitem at 5 (the text box that is not the buttons). The reason it is 5 is because it corresponds to the index of the text box in the windows_gui.hpp file when it is created by the CreateWindow function.
HWND hwnd_search_text = GetDlgItem(hwnd_search_window, 5);
char hwnd_main_window_hex[256];
sprintf(hwnd_main_window_hex, "Window found in: 0x%x", hwnd_main_window);
SetWindowText(hwnd_search_text, hwnd_main_window_hex);
ShowWindow(hwnd_search_window, SW_SHOW);
UpdateWindow(hwnd_search_window);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
return 0;
}
#include <iostream>
#include <Windows.h>
#include <Commctrl.h>
using namespace std;
#include "search_strategy_factory.hpp"
//search instance to be used for the radio push buttons in the window
Search search_instance = Search();
LRESULT APIENTRY WindowProcedure(HWND , UINT , WPARAM , LPARAM );
HWND create_basic_window()
{
int window_width = 400;
int window_height = 250;
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WindowProcedure;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = GetModuleHandle(NULL);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)CreateSolidBrush(RGB(191,184,191));
wc.lpszMenuName = NULL;
wc.lpszClassName = "WindowClass";
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if (!RegisterClassEx(&wc))
{
MessageBox(NULL, "Window Registration Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return NULL;
}
HWND hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, "WindowClass", "Search Tree View",
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, window_width, window_height, NULL, NULL, GetModuleHandle(NULL), NULL);
if (hwnd == NULL)
{
MessageBox(NULL, "Window Creation Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return NULL;
}
return hwnd;
}
LRESULT APIENTRY WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
{
if (LOWORD(wParam) == 1)
{
search_instance.setStrategy("youtube");
}
else if (LOWORD(wParam) == 2)
{
search_instance.setStrategy("spotify");
}
else if (LOWORD(wParam) == 3)
{
search_instance.setStrategy("discogs");
}
else if (LOWORD(wParam) == 4)
{
search_instance.setStrategy("google");
}
return 0;
}
case WM_CREATE:
{
int window_width = 400;
int window_height = 250;
//create two buttons in this window with padding of 10 pixels on every side
short int top_padding = 10;
short int left_padding = 50;
short int right_padding = 50;
short int bottom_padding = 10;
short int button_bottom_margin = 10;
// I don't know why I needed to put -20 for the width, because it should have worked without it.
short int button_width = (window_width - (left_padding + right_padding)) - 20;
short int button_height = 30;
//Create three buttons and attach them to the window. They will show up as RADIO BUTTONS in the menu. The BS_PUSHLIKE style is used to make the radio buttons look like push buttons.
HWND button1 = CreateWindowEx(0, "BUTTON", "YouTube", WS_VISIBLE | WS_CHILD | BS_AUTORADIOBUTTON | BS_PUSHLIKE, left_padding, top_padding, button_width, button_height, hwnd, (HMENU)1, NULL, NULL);
HWND button2 = CreateWindowEx(0, "BUTTON", "Spotify", WS_VISIBLE | WS_CHILD | BS_AUTORADIOBUTTON | BS_PUSHLIKE, left_padding, top_padding + button_height + button_bottom_margin, button_width, button_height, hwnd, (HMENU)2, NULL, NULL);
HWND button3 = CreateWindowEx(0, "BUTTON", "Discogs", WS_VISIBLE | WS_CHILD | BS_AUTORADIOBUTTON | BS_PUSHLIKE, left_padding, top_padding + (button_height * 2) + (button_bottom_margin * 2), button_width, button_height, hwnd, (HMENU)3, NULL, NULL);
HWND button4 = CreateWindowEx(0, "BUTTON", "Google", WS_VISIBLE | WS_CHILD | BS_AUTORADIOBUTTON | BS_PUSHLIKE, left_padding, top_padding + (button_height * 3) + (button_bottom_margin * 3), button_width, button_height, hwnd, (HMENU)4, NULL, NULL);
//Run the code that would usually happen when clicking the button. The 1 corresponds to the first button when the radio buttons are created.
SendMessage(hwnd, WM_COMMAND, 1, 0);
//Make button 1 the default selection (pushed down)
SendMessage(button1, BM_SETCHECK, BST_CHECKED, 0);
//put some text 25 pixels below button4 with background color of RGB(191,184,191)
//background color is determined by the case in the switch statement in the WindowProcedure function below for the case called WM_CTLCOLORSTATIC
//the (+5) is to make the text appear below the button
HWND text_box = CreateWindowEx(0, "STATIC", "Goon", WS_VISIBLE | WS_CHILD | SS_LEFT | SS_CENTER, left_padding, top_padding + (button_height * 4) + (button_bottom_margin * 4) + 5, button_width, button_height, hwnd, (HMENU)5, NULL, NULL);
break;
}
//Sole reason is to make the background color of Text Label with the same background as the rest of the window
case WM_CTLCOLORSTATIC:
{
HDC hdcStatic = (HDC)wParam;
SetTextColor(hdcStatic, RGB(0, 0, 0));
SetBkColor(hdcStatic, RGB(191, 184, 191));
//create brush
HBRUSH hBrush = CreateSolidBrush(RGB(191, 184, 191));
return (LRESULT)hBrush;
}
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}
#include <iostream>
#include <Windows.h>
#include <Commctrl.h>
using namespace std;
HHOOK _hook;
HMENU menu;
LRESULT APIENTRY WindowProcedure(HWND , UINT , WPARAM , LPARAM );
HWND create_basic_window()
{
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WindowProcedure;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = GetModuleHandle(NULL);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)CreateSolidBrush(RGB(191,184,191));
wc.lpszMenuName = NULL;
wc.lpszClassName = "WindowClass";
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if (!RegisterClassEx(&wc))
{
MessageBox(NULL, "Window Registration Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return NULL;
}
HWND hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, "WindowClass", "Search Tree View",
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 100, 180, NULL, NULL, GetModuleHandle(NULL), NULL);
if (hwnd == NULL)
{
MessageBox(NULL, "Window Creation Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return NULL;
}
return hwnd;
}
LRESULT APIENTRY WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
//add clickable buttons to this hwnd
case WM_CREATE:
{
break;
}
case WM_COMMAND:
{
if (LOWORD(wParam) == 1)
{
// MessageBox(hwnd, "Open", "Menu", MB_OK);
}
return 0;
}
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
HWND hwnd = create_basic_window();
//create two buttons in this window with padding of 10 pixels on every side
RECT rect;
GetClientRect(hwnd, &rect);
int window_length = rect.right;
int window_height = rect.bottom;
short int top_padding = 10;
short int left_padding = 10;
short int right_padding = 10;
short int bottom_padding = 10;
short int button_bottom_margin = 10;
short int button_width = (window_length - (left_padding + right_padding));
short int button_height = 30;
//Create three buttons and attach them to the window. They will show up as RADIO BUTTONS in the menu. The BS_PUSHLIKE style is used to make the radio buttons look like push buttons.
HWND button1 = CreateWindowEx(0, "BUTTON", "Button 1", WS_VISIBLE | WS_CHILD | BS_AUTORADIOBUTTON | BS_PUSHLIKE , left_padding, top_padding, button_width, button_height, hwnd, (HMENU)1, NULL, NULL);
HWND button2 = CreateWindowEx(0, "BUTTON", "Button 2", WS_VISIBLE | WS_CHILD | BS_AUTORADIOBUTTON | BS_PUSHLIKE , left_padding, top_padding + button_height + button_bottom_margin, button_width, button_height, hwnd, (HMENU)2, NULL, NULL);
HWND button3 = CreateWindowEx(0, "BUTTON", "Button 3", WS_VISIBLE | WS_CHILD | BS_AUTORADIOBUTTON | BS_PUSHLIKE, left_padding, top_padding + (button_height * 2) + (button_bottom_margin * 2), button_width, button_height, hwnd, (HMENU)3, NULL, NULL);
//Make button 2 the default selection
HWND button4 = CreateWindowEx(0, "BUTTON", "Button 4", WS_VISIBLE | WS_CHILD | BS_AUTORADIOBUTTON | BS_PUSHLIKE, left_padding, top_padding + (button_height * 3) + (button_bottom_margin * 3), button_width, button_height, hwnd, (HMENU)4, NULL, NULL);
SendMessage(button2, BM_SETCHECK, BST_CHECKED, 0);
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
###########################
##
## Imports
##
###########################
from Xlib import X, display
import time, evdev
from evdev import UInput, ecodes
import os
import ctypes
import ctypes.util
###########################
##
## Get Kernel Device Representation and Simulate Clicks
##
###########################
mouse_name = "HID 1bcf:08a0 Mouse"
device = None
for input_device in [evdev.InputDevice(path) for path in evdev.list_devices()]:
# print(input_device.name, mouse_name)
if input_device.name == mouse_name:
device = input_device
break
if device is None:
print(f"Device with name {mouse_name} not found.")
exit()
# Create a virtual input device
ui = UInput.from_device(device)
def click(button):
ui.write(ecodes.EV_KEY, button, 1)
ui.write(ecodes.EV_SYN, ecodes.SYN_REPORT, 0)
ui.write(ecodes.EV_KEY, button, 0)
ui.write(ecodes.EV_SYN, ecodes.SYN_REPORT, 0)
def press(button):
ui.write(ecodes.EV_KEY, button, 1)
ui.write(ecodes.EV_SYN, ecodes.SYN_REPORT, 0)
def left_click():
# print("Simulated Left Click")
click(ecodes.BTN_LEFT)
def middle_click():
# print("Simulated Middle Click")
click(ecodes.BTN_MIDDLE)
def right_click():
# print("Simulated Right Click")
click(ecodes.BTN_RIGHT)
def left_press():
# print("Simulated Left Press")
press(ecodes.BTN_LEFT)
def middle_press():
# print("Simulated Left Press")
press(ecodes.BTN_MIDDLE)
###########################
##
## disable wheel of mouse
##
##########################
#########
# get the device path of the mouse
#########
mouse_name = "HID 1bcf:08a0 Mouse"
device = None
for input_device in [evdev.InputDevice(path) for path in evdev.list_devices()]:
if input_device.name == mouse_name:
device = input_device
break
if device is None:
print(f"Device with name {mouse_name} not found.")
exit()
# Create a virtual input device
ui = UInput.from_device(device)
speed_factor = .96
debug = None
for event in device.read_loop():
if event.type == evdev.ecodes.EV_REL:
event_code = evdev.ecodes.REL[event.code]
event_value = event.value
# if event_code in ['REL_X', 'REL_Y']:
# event.value = int(event_value * speed_factor)
# el
if event_code == 'REL_WHEEL_HI_RES':
if event_value == 120: # WHEEL UP
left_click()
continue
elif event_value == -120: # WHEEL DOWN
left_press()
continue
# Write all other events to the virtual device
#time.sleep(.01)
ui.write_event(event)
ui.syn()
#!/usr/bin/env python3
import sys
import webbrowser
from PyQt5.QtWidgets import QApplication, QWidget, QLineEdit, QPushButton, QVBoxLayout
from PyQt5.QtGui import QFont
from PyQt5.QtCore import Qt
from pynput import keyboard
import ctypes
import ctypes.util
from Xlib import X, display
from Xlib.ext import xtest
from pynput.keyboard import Controller, Key
import time
from keywords import *
import threading
import subprocess
import re
keyboard_controller = Controller()
class HotkeyGUI(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setWindowTitle('Universal')
self.setFixedSize(260, 40)
self.setStyleSheet("background-color: white;")
layout = QVBoxLayout()
self.input = QLineEdit(self)
self.input.setFont(QFont('ChicagoFLF', 9))
self.input.returnPressed.connect(self.on_enter)
layout.addWidget(self.input)
self.setLayout(layout)
def on_enter(self):
turn_off_caps_lock()
user_input = self.input.text()
self.input.clear()
self.process_input(user_input)
self.hide()
def process_input(self, user_input):
ip_regex = r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$'
def type_input():
time.sleep(0.2)
keyboard_controller = Controller()
keyboard_controller.type(snippets[user_input])
if user_input in snippets:
# Run the typing in a separate thread to avoid blocking the GUI
typing_thread = threading.Thread(target=type_input)
typing_thread.start()
elif '-' in user_input:
before_dash, after_dash = user_input.split('-', 1)
if before_dash in snipsub:
print(snipsub[before_dash].replace("%query%",after_dash))
elif before_dash in subs:
webbrowser.open(subs[before_dash].replace("%query%",after_dash))
elif before_dash == 'job':
job_site = "http://www.google.com/search?q=%query%"
job_hr = "http://www.google.com/search?q=%query%+site:linkedin.com/in+""hiring manager""+OR+recruiter+OR+manager+OR+talent"
job_ceo = "https://www.google.com/search?q=%query%+site:linkedin.com/in+cto+OR+""team lead""+OR+ceo+OR+founder"
webbrowser.open(job_site.replace("%query%",after_dash))
webbrowser.open(job_hr.replace("%query%",after_dash))
webbrowser.open(job_ceo.replace("%query%",after_dash))
elif user_input in sites:
webbrowser.open(sites[user_input])
elif user_input in programs:
try:
# Run the program directly using subprocess
subprocess.run(programs[user_input].split(), check=True)
except Exception as e:
print(f"Error running program: {e}")
elif re.match(ip_regex, user_input) or user_input.startswith("localhost"):
# If it's an IP address or localhost, use HTTP
webbrowser.open(f"http://{user_input}")
elif "." in user_input:
webbrowser.open("https://" + user_input)
else:
webbrowser.open(f"https://www.google.com/search?q={user_input.replace(' ', '+')}")
def toggle_caps_lock():
global keyboard_controller
# Press and release the Caps Lock key
keyboard_controller.press(Key.caps_lock)
keyboard_controller.release(Key.caps_lock)
def get_caps_lock_state():
d = display.Display()
root = d.screen().root
# Fetch the LED status
caps_lock_mask = 0x02
leds = root.query_pointer()._data['mask']
d.close()
return (leds & caps_lock_mask) != 0
def turn_off_caps_lock():
if get_caps_lock_state() == True:
# allow the LED light in capslock keyboard to sync with the reality!
time.sleep(0.15)
toggle_caps_lock()
def on_activate():
turn_off_caps_lock()
if window.isVisible():
window.activateWindow()
else:
window.show()
def for_canonical(f):
return lambda k: f(listener.canonical(k))
app = QApplication(sys.argv)
window = HotkeyGUI()
hotkey = keyboard.HotKey(
keyboard.HotKey.parse('<caps_lock>'),
on_activate)
with keyboard.Listener(on_press=for_canonical(hotkey.press), on_release=for_canonical(hotkey.release)) as listener:
app.exec_()
#####################################
#
# MOUSE
#
######################################
from pynput.mouse import Listener
from pynput.mouse import Controller, Button
mouse_controller = Controller()
def click_left():
mouse_controller.click(Button.left)
def mouse_down_left():
mouse_controller.press(Button.left)
def mouse_up_left():
mouse_controller.release(Button.left)
def click_middle():
mouse_controller.click(Button.middle)
# Helper function to get the cursor type (this is a simplified version)
def get_cursor_type():
d = display.Display()
root = d.screen().root
window = root.query_pointer()._data['child']
print(window.get_window_attributes())
return
# Example cursor types (these should be mapped to actual types based on your environment)
if cursor_type == 0:
return "IBeam"
elif cursor_type == 1:
return "SizeWE"
elif cursor_type == 2:
return "SizeNS"
else:
return "Arrow" # Default cursor type
# Function to handle scroll events
def on_scroll(x, y, dx, dy):
print(dx,dy)
if dy > 0: # Wheel Up
click_left() # Simulate left mouse button click
elif dy < 0: # Wheel Down
cursor_type = get_cursor_type()
if cursor_type in ["IBeam", "SizeWE", "SizeNS"]:
mouse_down_left() # Hold down left mouse button
else:
click_middle() # Perform middle mouse click
from Xlib import X, display
from Xlib.protocol import event
import threading
def event_loop():
d = display.Display()
root = d.screen().root
root.grab_pointer(
False, # owner_events
X.PointerMotionMask | X.ButtonPressMask | X.ButtonReleaseMask, # event_mask
X.GrabModeAsync, # pointer_mode
X.GrabModeAsync, # keyboard_mode
root, # confine_to (use root window)
X.NONE, # cursor (use default)
X.CurrentTime
)
try:
while True:
event = d.next_event()
if event.type == X.ButtonPress:
print(f"Button {event.detail} pressed")
elif event.type == X.ButtonRelease:
print(f"Button {event.detail} released")
except KeyboardInterrupt:
print("Exiting event loop")
finally:
d.ungrab_pointer(X.CurrentTime)
d.close()
def start_mouse_listener():
event_loop()
mouse_thread = threading.Thread(target=start_mouse_listener)
mouse_thread.daemon = True
mouse_thread.start()
# Start listening to mouse events
#include <iostream>
#include <Windows.h>
#include <Commctrl.h>
#include <math.h>
#include <vector>
#include <fstream>
using namespace std;
HHOOK _hook;
HMENU menu;
class AgendaList; // let the compiler know such a class will be defined, namely inside of AgendaItem which contains a pointer to an AgendaList
using namespace std;
//AgendaList prototypeg
int window_width = 400;
int window_height = 400;
int global_index = 0;
string agenda_items_filename = "agenda_items.txt";
const HFONT levi_windows_font = CreateFont(13, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_OUTLINE_PRECIS, CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY, VARIABLE_PITCH, TEXT("Levi Windows"));
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK DestroyChildCallback( HWND , LPARAM);
//resets every single control, for the add & delete operations
BOOL CALLBACK DestroyChildCallback( HWND hwnd, LPARAM lParam)
{
if (hwnd != NULL) {
DestroyWindow(hwnd);
}
return TRUE;
}
class AgendaItem
{
//get a static class variable to keep track of the number of agenda items
private:
int id;
static int last_id;
string text;
AgendaList *parent_list;
int agenda_item_margin = 10;
int agenda_item_padding = 20;
int agenda_item_height = 60;
int agenda_item_x = 0;
double agenda_item_y = id * agenda_item_height;
//I don't know why i had to do the (2 * agenda_item_padding) twice
int agenda_item_width = window_width - (2 * agenda_item_margin) - (2 * agenda_item_margin);
int groupbox_x;
int groupbox_y;
int groupbox_height;
int groupbox_width;
int text_box_x;
int text_box_y;
int text_box_height;
int text_box_width;
int add_button_x;
int add_button_y;
int add_button_height;
int add_button_width;
int close_button_x;
int close_button_y;
int close_button_height;
int close_button_width;
HWND groupbox;
HWND textbox;
HWND button_add;
HWND button_delete;
vector<HWND> agenda_item_controls;
public:
AgendaItem(HWND& parent_hwnd, string text_in)
{
this->text = text_in;
this->id = last_id;
last_id++;
calculate_positions();
draw(parent_hwnd);
///get the userdata from a previous call of SetWindowLongPtr(parent_hwnd, GWLP_USERDATA, (LONG_PTR)this);
///that will represent the Parent Agenda List
this->parent_list = (AgendaList*)GetWindowLongPtr(parent_hwnd, GWLP_USERDATA);
}
void calculate_positions()
{
agenda_item_y = id * agenda_item_height;
groupbox_x = round(agenda_item_x + agenda_item_margin);
groupbox_y = agenda_item_y + agenda_item_margin;
groupbox_height = round(agenda_item_height);
groupbox_width = round(agenda_item_width);
text_box_x = round(agenda_item_x + agenda_item_padding);
text_box_y = round(agenda_item_y + agenda_item_margin + agenda_item_padding);
text_box_height = round(agenda_item_height * 0.33);
text_box_width = round(agenda_item_width * 0.6);
add_button_x = round(agenda_item_width * 0.75);
add_button_y = round(agenda_item_y + agenda_item_margin + agenda_item_padding);
add_button_height = round(agenda_item_height * 0.33);
add_button_width = round(agenda_item_width * 0.07);
close_button_x = round(agenda_item_width * 0.85);
close_button_y = round(agenda_item_y + agenda_item_margin + agenda_item_padding);
close_button_height = round(agenda_item_height * 0.33);
close_button_width = round(agenda_item_width * 0.07);
}
void print_all_values_in_calculate_positions()
{
cout << "agenda_item_x: " << agenda_item_x << endl;
cout << "agenda_item_y: " << agenda_item_y << endl;
cout << "agenda_item_height: " << agenda_item_height << endl;
cout << "agenda_item_width: " << agenda_item_width << endl;
cout << "groupbox_x: " << groupbox_x << endl;
cout << "groupbox_y: " << groupbox_y << endl;
cout << "groupbox_height: " << groupbox_height << endl;
cout << "groupbox_width: " << groupbox_width << endl;
cout << "text_box_x: " << text_box_x << endl;
cout << "text_box_y: " << text_box_y << endl;
cout << "text_box_height: " << text_box_height << endl;
cout << "text_box_width: " << text_box_width << endl;
cout << "add_button_x: " << add_button_x << endl;
cout << "add_button_y: " << add_button_y << endl;
cout << "add_button_height: " << add_button_height << endl;
cout << "add_button_width: " << add_button_width << endl;
cout << "close_button_x: " << close_button_x << endl;
cout << "close_button_y: " << close_button_y << endl;
cout << "close_button_height: " << close_button_height << endl;
cout << "close_button_width: " << close_button_width << endl;
cout << "------------------------------------" << endl;
}
void draw(HWND& parent_hwnd)
{
calculate_positions();
//** NOTE. For some reason, I had to have the buttons in the groupbox have a parent that is not the groupbox, but the parent of the groupbox. The buttons weren't showing up. **//
//define the text string to display for the groupbox
string groupbox_text = "Agenda Item #" + to_string(id);
//define group box with different id's so that we can identify them later
groupbox = CreateWindowEx(0,
TEXT("BUTTON"),
TEXT(groupbox_text.c_str()),
WS_CHILD | WS_VISIBLE | BS_GROUPBOX,
groupbox_x,
groupbox_y,
groupbox_width,
groupbox_height,
parent_hwnd,
(HMENU)id,
GetModuleHandle(NULL),
NULL);
textbox = CreateWindow("EDIT", //
text.c_str(), // text
WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT | ES_AUTOHSCROLL | WS_GROUP, // styles
text_box_x, // x
text_box_y, // y
text_box_width, // width
text_box_height, // height
parent_hwnd, // parent
(HMENU)1, // menu
NULL, // hInstance
NULL); // no extra parameters
button_add = CreateWindow("Button", //
"+", // text
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, // styles
add_button_x, // x
add_button_y, // y
add_button_width, // width
add_button_height, // height
parent_hwnd, // parent
(HMENU)2, // menu
NULL, // hInstance
NULL); // no extra parameters
button_delete = CreateWindow("Button", //
"x", // text
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, // styles
close_button_x, // x
close_button_y, // y
close_button_width, // width
close_button_height, // height
parent_hwnd, // parent
(HMENU)3, // menu
NULL, // hInstance
NULL); // no extra parameters
//Set the UserData for the buttons with the AgendaItem of the AgendaList, via the "this" variable. If I had to do multiple variables, it was possible to put them in a struct. If you know other ways to do this, please let me know.
//I researched CreateDialogParam, but I hit an impasse
//
//in Short, this links the buttons to the AgendaItem
SetWindowLongPtr(textbox, GWLP_USERDATA, (LONG_PTR)this);
SetWindowLongPtr(button_add, GWLP_USERDATA, (LONG_PTR)this);
SetWindowLongPtr(button_delete, GWLP_USERDATA, (LONG_PTR)this);
//every button uses the font in the variable "font"
SendMessage(groupbox, WM_SETFONT, (WPARAM)levi_windows_font, TRUE);
SendMessage(textbox, WM_SETFONT, (WPARAM)levi_windows_font, TRUE);
SendMessage(button_add, WM_SETFONT, (WPARAM)levi_windows_font, TRUE);
SendMessage(button_delete, WM_SETFONT, (WPARAM)
levi_windows_font, TRUE);
//fill the vector with the buttons
agenda_item_controls.push_back(groupbox);
agenda_item_controls.push_back(textbox);
agenda_item_controls.push_back(button_add);
agenda_item_controls.push_back(button_delete);
}
int get_id()
{
return id;
}
string get_text()
{
return text;
}
void set_id(int new_id)
{
id = new_id;
}
HWND get_textbox()
{
return textbox;
}
void set_text(string text_in)
{
text = text_in;
}
vector<HWND> get_agenda_item_controls()
{
return agenda_item_controls;
}
};
//get a static class variable to keep track of the number of agenda items
int AgendaItem::last_id = 0;
class AgendaList
{
private:
HWND parent_hwnd;
vector<AgendaItem*> agenda_items;
public:
AgendaList(HWND& parent_hwnd)
{
cout << "AgendaList this: " << this << endl;
//set userdata to this window
cout << "this: " << this << endl;
this->parent_hwnd = parent_hwnd;
}
//mainly done in initial creation
AgendaItem* create_agenda_item(HWND &parent_hwnd, string text_in)
{
AgendaItem* item = new AgendaItem(parent_hwnd, text_in);
agenda_items.push_back(item);
return item;
}
void delete_agenda_item(AgendaItem* agenda_item)
{
//error if trying to go out of bounds
if(agenda_items.size() <= 1)
{
MessageBox(parent_hwnd, "You must have at least one agenda list item.", "Error", MB_OK | MB_ICONEXCLAMATION);
return;
}
//find the item in the vector and delete it
for (int i = 0; i < agenda_items.size(); i++)
{
if (agenda_items[i] == agenda_item)
{
agenda_items.erase(agenda_items.begin() + i);
}
}
}
AgendaItem* add_new_agenda_item_below(AgendaItem* agenda_item)
{
int id = agenda_item->get_id();
//new AgendaItem
AgendaItem *new_agenda_item = new AgendaItem(parent_hwnd, "");
//set the id of the new AgendaItem to the id of the old one + 1
new_agenda_item->set_id(id + 1);
//insert the new AgendaItem into the vector
agenda_items.insert(agenda_items.begin() + id + 1, new_agenda_item);
//raise the ID's of all the other AgendaItems after the new one
for (int i = id + 1; i < agenda_items.size(); i++)
{
agenda_items[i]->set_id(agenda_items[i]->get_id() + 1);
}
return new_agenda_item;
}
int get_num_agenda_items()
{
return agenda_items.size();
}
void redraw(HWND& parent_hwnd)
{
//clears the window
RECT rect;
GetClientRect(parent_hwnd, &rect);
FillRect(GetDC(parent_hwnd), &rect, (HBRUSH)CreateSolidBrush(RGB(240, 240, 240)));
//Destroy all the child windows in the parent window (Parent HWND Handle)
EnumChildWindows(parent_hwnd, DestroyChildCallback, (LPARAM)&parent_hwnd);
//Set the new ids, AND draw the new buttons
int index = 0;
for (auto &item : agenda_items)
{
item->set_id(index++);
item->draw(parent_hwnd);
}
}
vector<AgendaItem*> get_agenda_items()
{
return agenda_items;
}
BOOL save_into_text_file()
{
//open the file
ofstream file;
file.open(agenda_items_filename);
//if the file is not open, return false
if (!file.is_open())
{
return FALSE;
}
//write the text from each AgendaItem into the file
for (auto &item : agenda_items)
{
file << item->get_text() << endl;
}
//close the file
file.close();
return TRUE;
}
};
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CREATE:
{
AgendaList* agenda_list = new AgendaList(hwnd);
//Initialize via filename
ifstream file;
file.open(agenda_items_filename);
//FILE DOES NOT EXIST
if (!file.is_open())
{
AgendaItem *a1 = agenda_list->create_agenda_item(hwnd, "test");
AgendaItem *a2 = agenda_list->create_agenda_item(hwnd, "grell");
AgendaItem *a3 = agenda_list->create_agenda_item(hwnd, "grain");
}
//FILE DOES EXIST
else
{
string line;
while (getline(file, line))
{
agenda_list->create_agenda_item(hwnd, line);
}
}
//attack agenda_list to the parent main window
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)agenda_list);
break;
}
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
//clicking on the text edit box
case 1:
{
//HIWORD(wParam) is the control-defined notification code according to the docs at https://docs.microsoft.com/en-us/windows/win32/menurc/wm-command
//The notification codes for this edit box is located in https://docs.microsoft.com/en-us/windows/win32/controls/en-killfocus
//I was unable to use WM_NOTIFY, it only worked with WM_COMMAND
if(HIWORD(wParam) == EN_KILLFOCUS)
{
HWND textbox = (HWND)lParam;
//get text
char buffer[256];
GetWindowText(textbox, buffer, 256);
//get the agenda list
AgendaList* agenda_list = (AgendaList*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
//get the current agenda item
AgendaItem* agenda_item = (AgendaItem*)GetWindowLongPtr(textbox, GWLP_USERDATA);
//set the text of the current agenda item
agenda_item->set_text(buffer);
agenda_list->save_into_text_file();
}
break;
}
//add agenda item
case 2:
{
//get the button
HWND button = (HWND)lParam;
//get the userdata from the button (agenda item)
AgendaItem* agenda_item = (AgendaItem*)GetWindowLongPtr(button, GWLP_USERDATA);
//get agenda list (attached to this HWND durig WM_CREATE)
AgendaList *agenda_list = (AgendaList *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
cout << "size: " << agenda_list->get_num_agenda_items() << endl;
AgendaItem* new_agenda_item = agenda_list->add_new_agenda_item_below(agenda_item);
agenda_list->redraw(hwnd);
SetFocus(new_agenda_item->get_textbox());
cout << "size: " << agenda_list->get_num_agenda_items() << endl;
break;
}
//deleting in an agenda item
case 3:
{
//get the button
HWND button = (HWND)lParam;
//get the userdata from the button (attached to the agenda item)
AgendaItem* agenda_item = (AgendaItem*)GetWindowLongPtr(button, GWLP_USERDATA);
//get agenda list (attached to this HWND durig WM_CREATE)
AgendaList* agenda_list = (AgendaList*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
cout << "size: " << agenda_list->get_num_agenda_items() << endl;
agenda_list->delete_agenda_item(agenda_item);
agenda_list->redraw(hwnd);
cout << "size: " << agenda_list->get_num_agenda_items() << endl;
break;
}
}
break;
}
//change the colors of buttons
case WM_CTLCOLORBTN:
{
//get the button
HWND button = (HWND)lParam;
//get the userdata from the button (attached to the agenda item)
AgendaItem* agenda_item = (AgendaItem*)GetWindowLongPtr(button, GWLP_USERDATA);
//get the color of the button
COLORREF color = RGB(128,255,128);
//set the color of the button
SetBkColor((HDC)wParam, color);
return (LRESULT)CreateSolidBrush(color);
}
case WM_LBUTTONDOWN:
cout << "Left button down" << endl;
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
HWND create_window(int width, int height)
{
HWND hwnd;
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = GetModuleHandle(NULL);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
//the typical gray background color
HBRUSH gray;
gray = CreateSolidBrush(RGB(240, 240, 240));
wc.hbrBackground = gray;
wc.lpszMenuName = NULL;
wc.lpszClassName = "Class";
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if (!RegisterClassEx(&wc))
{
MessageBox(NULL, "Window Registration Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return NULL;
}
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
"Class", //
"Agenda",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
width, height,
NULL,
NULL, //
GetModuleHandle(NULL), NULL);
if (hwnd == NULL)
{
MessageBox(NULL, "Window Creation Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return NULL;
}
return hwnd;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
HWND hwnd;
hwnd = create_window(window_width, window_height);
//divide three sections of that window
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
if (IsDialogMessage(hwnd, &msg) == 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return 0;
}
#include <iostream>
#include <Windows.h>
#include <Commctrl.h>
#include <tlhelp32.h>
#include <psapi.h>
#include <algorithm>
#include <vector>
#include <map>
#include <math.h>
#include <ctime>
int pop_up_width, pop_up_height;
using namespace std;
int pop_up_padding = 5;
int size_of_font = 18;
HFONT windows_95_font = CreateFont(size_of_font, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_OUTLINE_PRECIS, CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY, VARIABLE_PITCH, TEXT("System"));
struct ProcessTimes
{
FILETIME fileTimeCreation;
FILETIME fileTimeExit;
FILETIME fileTimeKernel;
FILETIME fileTimeUser;
FILETIME lastFileTimeCreation;
FILETIME lastFileTimeExit;
FILETIME lastFileTimeKernel;
FILETIME lastFileTimeUser;
};
map<DWORD, ProcessTimes *> processTimesMap;
double get_cpu_percentage(HANDLE hProcess)
{
DWORD process_id = GetProcessId(hProcess);
//if the structure is NOT IN MAP, ADD IT
ProcessTimes *processTimes;
if (processTimesMap.find(process_id) == processTimesMap.end())
{
processTimes = new ProcessTimes();
FILETIME creationTime;
FILETIME exitTime;
FILETIME kernelTime;
FILETIME userTime;
int unit_of_process_usage;
GetProcessTimes(hProcess, &creationTime, &exitTime, &kernelTime, &userTime);
processTimes->fileTimeCreation = creationTime;
processTimes->fileTimeExit = exitTime;
processTimes->fileTimeKernel = kernelTime;
processTimes->fileTimeUser = userTime;
processTimesMap[process_id] = processTimes;
}
//if the structure IS IN MAP, UPDATE IT
else
{
processTimes = processTimesMap[process_id];
FILETIME creationTime;
FILETIME exitTime;
FILETIME kernelTime;
FILETIME userTime;
GetProcessTimes(hProcess, &creationTime, &exitTime, &kernelTime, &userTime);
processTimes->fileTimeCreation = creationTime;
processTimes->fileTimeExit = exitTime;
processTimes->fileTimeKernel = kernelTime;
processTimes->fileTimeUser = userTime;
}
//get the difference between the last time and the current time
ULARGE_INTEGER kernelTimeDifference;
kernelTimeDifference.HighPart = processTimes->fileTimeKernel.dwHighDateTime - processTimes->lastFileTimeKernel.dwHighDateTime;
kernelTimeDifference.LowPart = processTimes->fileTimeKernel.dwLowDateTime - processTimes->lastFileTimeKernel.dwLowDateTime;
ULARGE_INTEGER userTimeDifference;
userTimeDifference.HighPart = processTimes->fileTimeUser.dwHighDateTime - processTimes->lastFileTimeUser.dwHighDateTime;
userTimeDifference.LowPart = processTimes->fileTimeUser.dwLowDateTime - processTimes->lastFileTimeUser.dwLowDateTime;
double unit_of_process_usage = (double)((kernelTimeDifference.QuadPart + userTimeDifference.QuadPart));
double cpu_percentage = ((double)unit_of_process_usage / (double)GetTickCount()) * 100;
////THE RATIOS OF THE PROCESSES ARE ACCURATE, BUT NOT THE EXACT NUMBER FROM TASK MANAGER, unless I divide by 18. The numbers in the task manager were 18 times less the number calculated above. Sorry if this is not perfect. I don't know the exact way to calculate the cpu usage with the factor below. My interest lies in many other projects.
cpu_percentage /= 18;
processTimes->lastFileTimeCreation = processTimes->fileTimeCreation;
processTimes->lastFileTimeExit = processTimes->fileTimeExit;
processTimes->lastFileTimeKernel = processTimes->fileTimeKernel;
processTimes->lastFileTimeUser = processTimes->fileTimeUser;
return cpu_percentage;
}
vector<vector<string>> get_processes_information()
{
// get list of processes
HANDLE hProcessSnap;
PROCESSENTRY32 pe32;
vector<vector<string>> processes_information;
int total_processes_to_show = 30;
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE)
{
return {};
}
pe32.dwSize = sizeof(PROCESSENTRY32);
if (!Process32First(hProcessSnap, &pe32))
{
CloseHandle(hProcessSnap);
return {};
}
do
{
HANDLE hProcess;
PROCESS_MEMORY_COUNTERS pmc;
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pe32.th32ProcessID);
if (hProcess == NULL)
{
//do nothing if process is not opened
continue;
}
if (GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc)))
{
int memory_kbs = (int)(pmc.WorkingSetSize / 1024);
string process_name = pe32.szExeFile;
DWORD process_id = pe32.th32ProcessID;
vector<string> process_info;
double cpu_percentage = get_cpu_percentage(hProcess);
PDWORD handle_count_struct_instance = new DWORD;
GetProcessHandleCount(hProcess, handle_count_struct_instance);
int handle_count = *handle_count_struct_instance;
process_info.push_back(process_name);
process_info.push_back(to_string(memory_kbs));
process_info.push_back(to_string(process_id));
process_info.push_back(to_string(handle_count));
process_info.push_back(to_string(cpu_percentage));
processes_information.push_back(process_info);
process_info.clear();
delete handle_count_struct_instance;
}
CloseHandle(hProcess);
} while (Process32Next(hProcessSnap, &pe32));
CloseHandle(hProcessSnap);
// sort processes by memory
sort(processes_information.begin(), processes_information.end(), [](vector<string> a, vector<string> b)
{ return stoi(a[1]) > stoi(b[1]); });
//slice this vector to show only top 20 processes
processes_information.erase(processes_information.begin() + total_processes_to_show, processes_information.end());
return processes_information;
}
LRESULT WINAPI WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
switch (Msg)
{
case WM_CREATE:
{
break;
}
//paint the popup to salmon
case WM_TIMER:
{
int cell_width = 125;
int column_2_distance = 125;
int column_3_distance = 225;
int column_4_distance = 325;
int column_5_distance = 450;
//adds a box
HDC hdcWindow = GetDC(hWnd);
RECT rect;
GetClientRect(hWnd, &rect);
HBRUSH salmon = CreateSolidBrush(RGB(255, 127, 90));
COLORREF dark_blue = RGB(20, 0, 80);
FillRect(hdcWindow, &rect, salmon);
//font for the text
SelectObject(hdcWindow, windows_95_font);
SetTextColor(hdcWindow, dark_blue);
SetBkMode(hdcWindow, TRANSPARENT);
//add text
auto processes_information = get_processes_information();
// SelectObject(hdcWindow, windows_95_font);
// SetTextColor(hdcWindow, dark_blue);
// SetBkMode(hdcWindow, TRANSPARENT);
// DrawText(hdcWindow, TEXT("Processes"), -1, &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE );
for (int i = 0; i < processes_information.size(); i++)
{
int line_height = size_of_font - 2;
RECT text_rect = {pop_up_padding, //left
(i * (line_height)), //top
pop_up_padding + cell_width, //right
(i * (line_height)) + line_height}; //bottom
DrawText(hdcWindow, TEXT(processes_information[i][0].c_str()), -1, &text_rect, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
// draw the text of memory usage right after the process name
text_rect.left = pop_up_padding + column_2_distance;
text_rect.right = pop_up_padding + column_2_distance + cell_width;
DrawText(hdcWindow, TEXT((processes_information[i][1] + " KB").c_str()), -1, &text_rect, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
// draw the text of process id right after the memory usage
text_rect.left = pop_up_padding + column_3_distance;
text_rect.right = pop_up_padding + column_3_distance + cell_width;
DrawText(hdcWindow, TEXT(("ID: " + processes_information[i][2]).c_str()), -1, &text_rect, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
// draw the text of process id right after the memory usage
text_rect.left = pop_up_padding + column_4_distance;
text_rect.right = pop_up_padding + column_4_distance + cell_width;
DrawText(hdcWindow, TEXT(("Handles: " + processes_information[i][3]).c_str()), -1, &text_rect, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
// draw the text of process id right after the memory usage
text_rect.left = pop_up_padding + column_5_distance;
text_rect.right = pop_up_padding + column_5_distance + cell_width;
DrawText(hdcWindow, TEXT(("CPU: " + processes_information[i][4] + "%").c_str()), -1, &text_rect, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
}
DeleteObject(salmon);
DeleteObject(hdcWindow);
return 0;
}
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdcWindow = BeginPaint(hWnd, &ps);
RECT rect;
GetClientRect(hWnd, &rect);
HBRUSH salmon = CreateSolidBrush(RGB(255, 127, 90));
COLORREF dark_blue = RGB(20, 0, 80);
FillRect(hdcWindow, &rect, salmon);
DeleteObject(salmon);
DeleteObject(hdcWindow);
EndPaint(hWnd, &ps);
return 0;
}
case WM_ERASEBKGND:
return 1;
case WM_CLOSE:
case WM_DESTROY:
{
PostQuitMessage(0);
}
return 0;
}
return DefWindowProc(hWnd, Msg, wParam, lParam);
}
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrev, LPSTR lpCmdLine, int nShowCmd)
{
int screen_width = GetSystemMetrics(SM_CXSCREEN),
screen_height = GetSystemMetrics(SM_CYSCREEN);
int padding = 30;
int left_padding = padding;
int top_padding = padding;
int right_padding = padding;
int bottom_padding = padding;
pop_up_width = round(GetSystemMetrics(SM_CXSCREEN) * 0.45);
pop_up_height = round(GetSystemMetrics(SM_CYSCREEN) * 0.66);
//salmon brush HBRUSH
HBRUSH salmon = CreateSolidBrush(RGB(255, 127, 90));
//salmon pen HPEN
HPEN salmon_pen = CreatePen(PS_SOLID, 1, RGB(255, 127, 90));
WNDCLASS wndClass = {0, WndProc, 0, 0, hInstance, NULL, LoadCursor(NULL, IDC_ARROW), 0, NULL, "popup_process"};
if (!RegisterClass(&wndClass))
return MessageBox(HWND_DESKTOP, "Cannot register class!", NULL, MB_ICONERROR | MB_OK);
HWND hWnd = CreateWindowEx(WS_EX_TOPMOST, "popup_process", "popup_process", WS_POPUP,
screen_width - pop_up_width - right_padding, screen_height / 2 - pop_up_height / 2, pop_up_width, pop_up_height, NULL, NULL, hInstance, NULL);
//start timer
SetTimer(hWnd, 1, 1000, NULL);
if (!hWnd)
return MessageBox(HWND_DESKTOP, "Cannot create window!", NULL, MB_ICONERROR | MB_OK);
MSG Msg = {0};
//show & update window
ShowWindow(hWnd, nShowCmd);
UpdateWindow(hWnd);
while (Msg.message != WM_QUIT)
{
if (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
if (GetAsyncKeyState(VK_ESCAPE) & 0x8000)
DestroyWindow(hWnd);
}
return 0;
}
#include <iostream>
#include <Windows.h>
#include <Commctrl.h>
#include <tlhelp32.h>
#include <psapi.h>
#include <algorithm>
#include <vector>
#include <ctime>
using namespace std;
HHOOK _hook;
HMENU menu;
void terminate_process(int pid);
LRESULT __stdcall HookCallback(int nCode, WPARAM wParam, LPARAM lParam)
{
return CallNextHookEx(_hook, nCode, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
// get list of processes
HANDLE hProcessSnap;
PROCESSENTRY32 pe32;
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE)
{
return 0;
}
pe32.dwSize = sizeof(PROCESSENTRY32);
if (!Process32First(hProcessSnap, &pe32))
{
CloseHandle(hProcessSnap);
return 0;
}
do
{
HANDLE hProcess;
PROCESS_MEMORY_COUNTERS pmc;
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pe32.th32ProcessID);
if (hProcess == NULL)
{
cout << pe32.szExeFile << " could not be opened" << endl;
continue;
}
if (GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc)))
{
cout << pe32.szExeFile << " has " << pmc.WorkingSetSize / 1024 << " KB of memory" << endl;
}
int memory_kbs = (int)(pmc.WorkingSetSize / 1024);
// if memory is greater than 250000 MB, kill the process
if (memory_kbs > 250000)
{
cout << endl << "Killing " << pe32.szExeFile << endl;
//DWORD to INT
int pid = pe32.th32ProcessID;
terminate_process(pid);
}
CloseHandle(hProcess);
} while (Process32Next(hProcessSnap, &pe32));
CloseHandle(hProcessSnap);
return 1;
}
void terminate_process(int pid)
{
HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
if (hProcess == NULL)
{
cout << "Could not open process" << endl;
return;
}
if (!TerminateProcess(hProcess, 0))
{
cout << "Could not terminate process" << endl;
return;
}
CloseHandle(hProcess);
}
#include <iostream>
#include <Windows.h>
#include <Commctrl.h>
#include <tlhelp32.h>
#include <math.h>
#include <psapi.h>
#include <algorithm>
#include <vector>
#include <ctime>
using namespace std;
int pop_up_height, pop_up_width;
int moving_speed = 5;
int total_words = 15;
int milliseconds_between_frames = 15;
int j = 0;
void add_transparent_text_to_desktop(HWND &, HDC &, HDC &);
BOOL did_rects_collide(RECT, RECT);
void bounce_rectangles(RECT, RECT);
struct Word;
vector<pair<Word *, Word *>> all_collisions;
COLORREF rainbow_generator(int);
struct Word
{
string content;
int x, y;
POINT path_coordinates[2]{{0, 0}, {0, 0}};
double x_speed, y_speed;
int width, height;
RECT rect;
int id;
bool currently_dragging;
static int last_id;
COLORREF color;
int color_index;
//constructor taking in word
Word(string word_in)
{
content = word_in;
x = rand() % pop_up_width;
y = rand() % pop_up_height;
//x_speed is random number between -20 and 20
x_speed = (rand() % moving_speed * 2) - moving_speed;
y_speed = (rand() % moving_speed * 2) - moving_speed;
width = 0;
height = 0;
RECT rect;
rect.left = x;
rect.top = y;
rect.right = x + width;
rect.bottom = y + height;
color_index = 170;
color = rainbow_generator(color_index);
}
//new method
BOOL is_clicked(int x, int y)
{
if (x > rect.left && x < rect.right && y > rect.top && y < rect.bottom)
{
return true;
}
return false;
}
};
class Context
{
private:
HDC hDC;
HDC hCDC;
HWND hWnd;
static Context *instance;
vector<Word *> words;
public:
static Context &get_instance()
{
static Context instance;
return instance;
}
void set_all_handles(HDC hDC_in, HDC hCDC_in, HWND hWnd_in)
{
hDC = hDC_in;
hCDC = hCDC_in;
hWnd = hWnd_in;
}
void add_word(string word)
{
Word *new_word = new Word(word);
words.push_back(new_word);
}
void add_words(string content, int number_of_words)
{
for (int i = 0; i < number_of_words; i++)
{
add_word(content);
}
}
vector<Word *> get_words()
{
return words;
}
HDC get_hDC()
{
return hDC;
}
HDC get_hCDC()
{
return hCDC;
}
HWND get_hWnd()
{
return hWnd;
}
void delete_words_from_memory()
{
for (auto &word : words)
{
delete word;
}
}
};
Context context = Context::get_instance();
double old_x_speed = 0;
double old_y_speed = 0;
enum direction
{
nw,
ne,
sw,
se
};
direction direction_path_coordinates_went(Word word_param)
{
if ((word_param.path_coordinates[0].x - word_param.path_coordinates[1].x > 0) && (word_param.path_coordinates[0].y - word_param.path_coordinates[1].y > 0))
{
return nw;
}
else if ((word_param.path_coordinates[0].x - word_param.path_coordinates[1].x > 0) && (word_param.path_coordinates[0].y - word_param.path_coordinates[1].y < 0))
{
return sw;
}
else if ((word_param.path_coordinates[0].x - word_param.path_coordinates[1].x < 0) && (word_param.path_coordinates[0].y - word_param.path_coordinates[1].y > 0))
{
return ne;
}
else if ((word_param.path_coordinates[0].x - word_param.path_coordinates[1].x < 0) && (word_param.path_coordinates[0].y - word_param.path_coordinates[1].y < 0))
{
return se;
}
else
{
return nw;
}
}
//define mouseproc
LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode == HC_ACTION)
{
//drag behavior
// if (wParam == WM_MOUSEMOVE && GetAsyncKeyState(VK_LBUTTON) == -32768)
if (wParam == WM_LBUTTONDOWN || (wParam == WM_MOUSEMOVE && GetAsyncKeyState(VK_LBUTTON) == -32768))
{
//get mouse coordinates
POINT p;
GetCursorPos(&p);
int arrow_x = p.x;
int arrow_y = p.y;
//check if any of the words are clicked
for (auto &word : context.get_words())
{
if (word->is_clicked(arrow_x, arrow_y))
{
word->x = arrow_x - word->width / 2;
word->y = arrow_y - word->height / 2;
word->rect.left = word->x;
word->rect.top = word->y;
word->rect.right = word->x + word->width;
word->rect.bottom = word->y + word->height;
//do not update the old speed during dragging, only restart it from the speed when mouse was first clicked
if (wParam != WM_MOUSEMOVE && GetAsyncKeyState(VK_LBUTTON) != -32768)
{
old_x_speed = word->x_speed;
old_y_speed = word->y_speed;
}
//if the path_coordinates[1] is not equal to arrow_x and arrow_y, then update the path_coordinates
if (word->path_coordinates[1].x != arrow_x && word->path_coordinates[1].y != arrow_y)
{
word->path_coordinates[0] = word->path_coordinates[1];
word->path_coordinates[1].x = arrow_x;
word->path_coordinates[1].y = arrow_y;
}
word->x_speed = 0;
word->y_speed = 0;
word->currently_dragging = true;
break;
}
}
}
//if mouse is released
if (wParam == WM_LBUTTONUP)
{
//get mouse coordinates
POINT p;
GetCursorPos(&p);
int arrow_x = p.x;
int arrow_y = p.y;
//check if any of the words are clicked
for (auto &word : context.get_words())
{
if (word->is_clicked(arrow_x, arrow_y))
{
word->currently_dragging = false;
direction path_coordinates_went = direction_path_coordinates_went(*word);
if (path_coordinates_went == nw)
{
word->x_speed = -abs(old_x_speed);
word->y_speed = -abs(old_y_speed);
}
else if (path_coordinates_went == ne)
{
word->x_speed = abs(old_x_speed);
word->y_speed = -abs(old_y_speed);
}
else if (path_coordinates_went == sw)
{
word->x_speed = -abs(old_x_speed);
word->y_speed = abs(old_y_speed);
}
else if (path_coordinates_went == se)
{
word->x_speed = abs(old_x_speed);
word->y_speed = abs(old_y_speed);
}
}
}
}
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
LRESULT WINAPI WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
switch (Msg)
{
//draw text with a transparent background (no black background
case WM_PAINT:
{
return 1;
}
case WM_CREATE:
{
//get the context object
context = Context::get_instance();
//rect
RECT rect;
GetClientRect(hWnd, &rect);
int width = rect.right - rect.left;
int height = rect.bottom - rect.top;
//Create DC
//Create Compatible DC
//Create Bitmap
HDC hDC = GetDC(hWnd);
HDC hCDC = CreateCompatibleDC(hDC);
HBITMAP hBmp = CreateCompatibleBitmap(hDC, width, height);
HBITMAP hBmpOld = (HBITMAP)SelectObject(hCDC, hBmp);
add_transparent_text_to_desktop(hWnd, hDC, hCDC);
//fill the context object
context.set_all_handles(hDC, hCDC, hWnd);
// context.add_word("One");
// context.add_word("Two");
// context.add_word("Three");
// context.add_word("Four");
// context.add_word("Five");
// context.add_word("Six");
// context.add_word("Seven");
// context.add_word("Eight");
// context.add_word("Nine");
// context.add_word("Ten");
// context.add_words("Win32 API", 5);
// context.add_words("Rust", 3);
// context.add_words("C++", 2);
context.add_word("Python");
context.add_word("C#");
context.add_word("Juniper");
context.add_word("Cisco");
context.add_word("AWS");
context.add_word("JavaScript");
//Release DC
ReleaseDC(hWnd, hDC);
//Release Compatible DC
DeleteDC(hCDC);
//Release Bitmap
DeleteObject(hBmp);
break;
}
case WM_TIMER:
{
//remember that this context was created once at WM_CREATE
// add_transparent_text_to_desktop(context.get_hWnd(), context.get_hDC(), context.get_hCDC());
RECT rect;
GetClientRect(hWnd, &rect);
int width = rect.right - rect.left;
int height = rect.bottom - rect.top;
//Create DC
HDC hDC = GetDC(hWnd);
HDC hCDC = CreateCompatibleDC(hDC);
HBITMAP hBmp = CreateCompatibleBitmap(hDC, width, height);
HBITMAP hBmpOld = (HBITMAP)SelectObject(hCDC, hBmp);
add_transparent_text_to_desktop(hWnd, hDC, hCDC);
//clean
DeleteDC(hCDC);
DeleteObject(hBmp);
ReleaseDC(hWnd, hDC);
break;
}
case WM_ERASEBKGND:
return 1;
case WM_CLOSE:
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
}
return DefWindowProc(hWnd, Msg, wParam, lParam);
}
BOOL did_rects_collide(RECT word1, RECT word2)
{
if (word1.left < word2.right && word1.right > word2.left && word1.top < word2.bottom && word1.bottom > word2.top)
{
return true;
}
return false;
}
COLORREF rainbow_generator(int index)
{
//index must be 0 to 255
int red;
int grn;
int blu;
int region = (int)floor((index / 255.0) * 6);
int chunk = (int)((floor(index % 43) / 43) * 255);
switch (region)
{
case 0:
red = 255;
grn = chunk;
blu = 0;
break; //red
case 1:
red = 255 - chunk;
grn = 255;
blu = 0;
break; //yellow
case 2:
red = 0;
grn = 255;
blu = chunk;
break; //green
case 3:
red = 0;
grn = 255 - chunk;
blu = 255;
break; //cyan
case 4:
red = chunk;
grn = 0;
blu = 255;
break; //blue
case 5:
red = 255;
grn = 0;
blu = 255 - chunk;
break; //magenta
}
return RGB(red, grn, blu);
}
void add_transparent_text_to_desktop(HWND &hWnd, HDC &hDC, HDC &hCDC)
{
RECT rect;
GetClientRect(hWnd, &rect);
int width = rect.right - rect.left;
int height = rect.bottom - rect.top;
//make font size as 50px
LOGFONT lf;
GetObject(GetStockObject(DEFAULT_GUI_FONT), sizeof(LOGFONT), &lf);
lf.lfHeight = 50;
HFONT hFont = CreateFontIndirect(&lf);
//hfont with transparent background & white
HFONT hFontOld = (HFONT)SelectObject(hCDC, hFont);
//text must be transparent background. This will only work if there's a blending & UpdateLayeredWindow function below
SetBkMode(hCDC, TRANSPARENT);
//text color
SetTextColor(hCDC, RGB(0, 255, 0));
vector<pair<Word *, Word *>> collided_pairs_vector;
vector<Word *> words = context.get_words();
// cout << "words size: " << words.size() << endl;
//Get a random rectangle & use DrawText function (not TextOut). Use the important DT_CALCRECT flag to get the size of the text to be drawn so I can later use the coordinates to detect collisions
for (auto &word : words)
{
//honestly seems the only purpose of this RECT is to later calculate the height & width of the Text Box
RECT word_rect;
word_rect.left = word->x;
word_rect.top = word->y;
//After this call, word_rect will likely have the right & bottom fields filled
//Also, this is actually not drawing the text
DrawText(hCDC, word->content.c_str(), word->content.length(), &word_rect, DT_CALCRECT | DT_CENTER | DT_VCENTER);
word->width = word_rect.right - word_rect.left;
word->height = word_rect.bottom - word_rect.top;
//Actually draw the text
SetTextColor(hCDC, word->color);
DrawText(hCDC, word->content.c_str(), word->content.length(), &word_rect, DT_CENTER | DT_VCENTER);
word->x += word->x_speed;
word->y += word->y_speed;
//save the word's rect for collision detection
word->rect = word_rect;
//if word is off screen, move it back to the top
if (word->x < 0)
word->x = width;
if (word->x > width)
word->x = 0;
if (word->y < 0)
word->y = height;
if (word->y > height)
word->y = 0;
// collision detection
for (auto &word2 : words)
{
if (word != word2)
{
if (did_rects_collide(word_rect, word2->rect))
{
//only add the pair IF the reverse pair flipped is NOT already in the collided_pairs_vector
pair<Word *, Word *> reversed_pair(word2, word);
//if the reversed pair does NOT exist in the collided_pairs_vector
if (find(collided_pairs_vector.begin(), collided_pairs_vector.end(), reversed_pair) == collided_pairs_vector.end())
{
collided_pairs_vector.push_back(make_pair(word, word2));
}
}
}
}
}
//DEBUG
// int cps = collided_pairs_vector.size();
// if(cps > 0)
// {
// for (auto &collided_pair : collided_pairs_vector)
// {
// cout << "collided pairs: ";
// for (auto &inner_collided_pair : collided_pairs_vector)
// {
// cout << inner_collided_pair.first->content << " " << inner_collided_pair.second->content << " ";
// }
// cout << endl;
// }
// }
int distance = 5;
//remove the pairs
for (auto &collided_pair : collided_pairs_vector)
{
Word *word1 = collided_pair.first;
Word *word2 = collided_pair.second;
int word1_left = word1->rect.left;
int word1_top = word1->rect.top;
int word1_right = word1->rect.right;
int word1_bottom = word1->rect.bottom;
int word2_left = word2->rect.left;
int word2_top = word2->rect.top;
int word2_right = word2->rect.right;
int word2_bottom = word2->rect.bottom;
int x_diff = word1_left - word2_right;
int y_diff = word1_top - word2_bottom;
int word1_xspeed = word1->x_speed;
int word1_yspeed = word1->y_speed;
int word2_xspeed = word2->x_speed;
int word2_yspeed = word2->y_speed;
int margin = 1;
//higher the dampening, the more the distance
float dampen_difference = 0.2;
int distance_between_words_to_turn = 2;
int move_distance_x = round(x_diff * dampen_difference) + margin;
int move_distance_y = round(y_diff * dampen_difference) + margin;
//get the dragged word between word1 & word2
Word *dragged_word;
if (word1->currently_dragging == true)
{
dragged_word = word1;
}
else if (word2->currently_dragging == true)
{
dragged_word = word2;
}
else
dragged_word = nullptr;
word1->x = word1->x + move_distance_x;
word2->x = word2->x - move_distance_x;
word1->y = word1->y + move_distance_y;
word2->y = word2->y - move_distance_y;
double angle_of_collided_words = atan2(y_diff, x_diff);
double angle_of_word1 = atan2(word1_yspeed, word1_xspeed);
double angle_of_word2 = atan2(word2_yspeed, word2_xspeed);
double angle_difference = atan2(y_diff, x_diff) - atan2(word1_yspeed, word1_xspeed);
double angle_difference2 = atan2(y_diff, x_diff) - atan2(word2_yspeed, word2_xspeed);
double angle_difference_to_turn = angle_difference / distance_between_words_to_turn;
double angle_difference_to_turn2 = angle_difference2 / distance_between_words_to_turn;
double new_angle_of_word1 = angle_of_word1 + angle_difference_to_turn;
double new_angle_of_word2 = angle_of_word2 - angle_difference_to_turn2;
// cout << "angle of word 1: " << angle_of_word1 << " angle of word 2: " << angle_of_word2 << " angle difference: " << angle_difference << " angle difference2: " << angle_difference2 << " angle difference to turn: " << angle_difference_to_turn << " angle difference to turn2: " << angle_difference_to_turn2 << " new angle of word 1: " << new_angle_of_word1 << " new angle of word 2: " << new_angle_of_word2 << endl;
// cout << '-----------' << endl;
word1->x_speed = (cos(new_angle_of_word1) > 0) ? cos(new_angle_of_word1) * moving_speed : cos(new_angle_of_word1) * moving_speed;
word1->y_speed = (sin(new_angle_of_word1) > 0) ? sin(new_angle_of_word1) * moving_speed : sin(new_angle_of_word1) * moving_speed;
word2->x_speed = (cos(new_angle_of_word2) > 0) ? cos(new_angle_of_word2) * moving_speed : cos(new_angle_of_word2) * moving_speed;
word2->y_speed = (sin(new_angle_of_word2) > 0) ? sin(new_angle_of_word2) * moving_speed : sin(new_angle_of_word2) * moving_speed;
// If the word is currently being dragged, then we need to NOT move it
//change the direction
if (abs(max(move_distance_x, move_distance_y)) > distance_between_words_to_turn)
{
//if approaching in opposite directions in X
if ((word1_xspeed > 0 && word2_xspeed < 0) || (word1_xspeed < 0 && word2_xspeed > 0))
{
word1->x_speed = word1->x_speed;
word2->x_speed = word2->x_speed;
}
//if approaching in opposite directions in Y
if ((word1_yspeed > 0 && word2_yspeed < 0) || (word1_yspeed < 0 && word2_yspeed > 0))
{
word1->y_speed = word1->y_speed;
word2->y_speed = word2->y_speed;
}
int placeholder;
//if approaching in same direction in X
if ((word1_xspeed > 0 && word2_xspeed > 0) || (word1_xspeed < 0 && word2_xspeed < 0))
{
placeholder = word1_xspeed;
word1->x_speed = word2_xspeed;
word2->x_speed = placeholder;
// word1->x_speed = -word1_xspeed;
// word2->x_speed = -word2_xspeed;
}
//if approaching in same direction in Y
if ((word1_yspeed > 0 && word2_yspeed > 0) || (word1_yspeed < 0 && word2_yspeed < 0))
{
placeholder = abs(word1_yspeed);
word1->y_speed = abs(word2_yspeed);
word2->y_speed = placeholder;
// word1->y_speed = -word1->y_speed;
// word2->y_speed = -word2->y_speed;
}
}
//the word that's dragging doesn't move
if (dragged_word == word1)
{
cout << dragged_word->content << endl;
word1->x = word1_left;
word1->y = word1_top;
word1->x_speed = 0;
word1->y_speed = 0;
}
else if (dragged_word == word2)
{
cout << dragged_word->content << endl;
word2->x = word2_left;
word2->y = word2_top;
word2->x_speed = 0;
word2->y_speed = 0;
}
}
// Call UpdateLayeredWindow
BLENDFUNCTION blend = {0};
blend.BlendOp = AC_SRC_OVER;
blend.SourceConstantAlpha = 255;
blend.AlphaFormat = AC_SRC_ALPHA;
SIZE sizeWnd = {width, height};
//ptpox & ptsrc in the center
POINT ptPos = {(GetSystemMetrics(SM_CXSCREEN) - width) / 2, (GetSystemMetrics(SM_CYSCREEN) - height) / 2};
POINT ptSrc = {0, 0};
UpdateLayeredWindow(hWnd, hDC, &ptPos, &sizeWnd, hCDC, &ptSrc, 0, &blend, ULW_ALPHA);
}
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrev, LPSTR lpCmdLine, int nShowCmd)
{
int screen_width = GetSystemMetrics(SM_CXSCREEN),
screen_height = GetSystemMetrics(SM_CYSCREEN);
int padding = 30;
int left_padding = padding;
int top_padding = padding;
int right_padding = padding;
int bottom_padding = padding;
pop_up_width = screen_width;
pop_up_height = screen_height;
// pop_up_width = 400;
// pop_up_height = 400;
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
//blue brush background
wc.hbrBackground = (HBRUSH)CreateSolidBrush(RGB(20, 222, 80));
wc.lpszMenuName = NULL;
wc.lpszClassName = "popup_process";
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if (!RegisterClassEx(&wc))
{
MessageBox(NULL, "Window Registration Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
// make a transparent window
HWND hwnd = CreateWindowEx(WS_EX_LAYERED | WS_EX_TOPMOST,
"popup_process",
"popup_process",
WS_POPUP,
left_padding,
top_padding,
pop_up_width,
pop_up_height,
NULL,
NULL,
hInstance,
NULL);
//make a transparent window
hwnd = CreateWindowEx(WS_EX_TOPMOST | WS_EX_LAYERED, "popup_process", "popup_process", WS_POPUP, screen_width - pop_up_width - right_padding, screen_height / 2 - pop_up_height / 2, pop_up_width, pop_up_height, NULL, NULL, hInstance, NULL);
HHOOK mouseHookHdl = SetWindowsHookEx(WH_MOUSE_LL, MouseProc, hInstance, 0);
if (mouseHookHdl == NULL)
{
MessageBox(NULL, "SetWindowsHookEx for MouseProc failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nShowCmd);
UpdateWindow(hwnd);
//work with transparency
if (!hwnd)
return MessageBox(HWND_DESKTOP, "Cannot create window!", NULL, MB_ICONERROR | MB_OK);
MSG Msg = {0};
//show & update window
ShowWindow(hwnd, nShowCmd);
UpdateWindow(hwnd);
//run timer every second infiniteyl
SetTimer(hwnd, 0, milliseconds_between_frames, NULL);
while (Msg.message != WM_QUIT)
{
if (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
if (GetAsyncKeyState(VK_ESCAPE) & 0x8000)
DestroyWindow(hwnd);
}
return 0;
}
import os, sys
from random import randrange
import boto3
def lambda_handler(event, context):
try:
#FORCED TO HAVE PROGRAM FLOW witih Try & Catch BECAUSE OF A GLITCH IN AMAZON ECHO DEVICE vs Alexa Service Simulator
try:
response_session_attributes = event["session"]["attributes"]
except:
response_session_attributes = {'debug':'problem'}
is_playing = get_session_value(event,'playing')
is_game_over = get_session_value(event,'game_over')
is_playing = int(is_playing) if is_playing is not None else 0
is_game_over = int(is_game_over) if is_game_over is not None else 0
one_second_break = '<break time="1000ms"/>'
half_second_break = '<break time="500ms"/>'
# s3 = boto3.client("s3")
#AUDIO FILES#
audio_1 = ('bd_countdown','1_game_bd_countdown_48k.mp3','https://a.clyp.it/hzvpcfai.mp3')
audio_2 = ('bd_intro','2_game_bd_intro_48k.mp3','https://a.clyp.it/berksyah.mp3')
audio_3 = ('bd_win_1','3_game_bd_win1_48k.mp3','https://a.clyp.it/dmno3wxu.mp3')
audio_4 = ('bd_hard','4_game_bd_hard_48k.mp3','https://a.clyp.it/itskfkr3.mp3')
audio_5 = ('bd_medium','5_game_bd_medium_48k.mp3','https://a.clyp.it/hmmoie01.mp3')
audio_6 = ('bd_win_2','6_game_bd_win_48k.mp3','https://a.clyp.it/1eozk1qj.mp3')
audio_7 = ('bd_instructions','7_game_bd_instructions_48k.mp3','https://a.clyp.it/sstiscoz.mp3')
audio_8 = ('bd_easy','8_game_bd_easy_48k.mp3','https://a.clyp.it/2dw3nt21.mp3')
audio_9 = ('bd_lose','9_game_bd_lose_48k.mp3','https://a.clyp.it/odikfqdd.mp3')
#END AUDIO FILES#
#PLAY AGAIN#
#
# Note: Reason for a state design pattern is for things just like this!
#
#END PLAY AGAIN#
if event["request"]["type"] == "LaunchRequest":
response_session_attributes['playing'] = 0
return build_ssml_response(generate_audio_tag(audio_2[2]), 0, response_session_attributes)
elif event["request"]["type"] == "IntentRequest":
intent_name = event["request"]["intent"]["name"]
#SATISFIES #2 of Amazon requirements (2017-03-23)
if intent_name == "AMAZON.CancelIntent" or intent_name == "AMAZON.StopIntent":
return build_ssml_response('Thank you for using Bomb Defuse. See you next time!', 1)
#menu
if is_playing == 0:
#choose level section
if intent_name == "ChooseLevelIntent":
if is_playing == 1:
return build_ssml_response("You are already playing", 0, response_session_attributes)
chosen_level = get_slot_value(event,'level')
tries_left = 0
if chosen_level is not False:
if chosen_level == 'easy':
tries_left = 10
response = generate_audio_tag(audio_8[2])+ one_second_break
elif chosen_level == 'medium':
tries_left = 9
response = generate_audio_tag(audio_5[2])+ one_second_break
elif chosen_level == 'hard':
tries_left = 8
response = generate_audio_tag(audio_4[2])+ one_second_break
elif chosen_level == 'testing':
tries_left = 1
response = "testing" + one_second_break
else:
return build_ssml_response("Please Choose Level between Easy, Medium or Hard", 0, response_session_attributes)
#this is where the game really starts. It starts when level is chosen (so far)
response_session_attributes['tries_left'] = tries_left
response_session_attributes['playing'] = 1
maximum_number = 1000
response_session_attributes['maximum_number'] = maximum_number
response_session_attributes['correct_number'] = randrange(1,maximum_number + 1)
response += "Guess a number between 1 and 1000. You have %s chances" % tries_left
return build_ssml_response(response, 0,response_session_attributes)
else:
return build_ssml_response("Please choose level among Easy, Medium or Hard!", 0,response_session_attributes)
#we are currently playing now
elif is_playing == 1:
#power up section
if intent_name == "PowerUpIntent":
maximum_number = get_session_value(event,'maximum_number')
chosen_powerup = get_slot_value(event,'powerup_type')
if chosen_powerup is not False:
if chosen_powerup == 'yellow':
maximum_number -= 10
if chosen_powerup == 'blue':
maximum_number -= 50
if chosen_powerup == 'red':
maximum_number -= 100
if chosen_powerup == 'ultimate':
maximum_number -= 500
response_session_attributes['maximum_number'] = maximum_number
#the "correct number" changes when there is a powerup
response_session_attributes['correct_number'] = randrange(1,maximum_number + 1)
response = "%s %s" % (maximum_number, chosen_powerup)
return build_ssml_response(response, 0, response_session_attributes)
elif intent_name == "TryIntent":
correct_number = get_session_value(event,'correct_number')
correct_number = int(correct_number) if correct_number is not None else -1
tries_left = get_session_value(event,'tries_left')
chosen_number = int(get_slot_value(event,'chosen_number'))
#between 1 and 1000?
if int(chosen_number) >= 0 and int(chosen_number) <= 1000:
tries_left -= 1
word = "tries" if tries_left != 1 else "try"
response_session_attributes['tries_left'] = tries_left
else:
return build_ssml_response("You said %s. Please pick a number between 1 and 1000" % chosen_number,0,response_session_attributes)
if int(correct_number) == int(chosen_number):
response = generate_audio_tag(audio_6[2])+ half_second_break + "Do you want to play again?"
card_text = "Congratulations! You won! The correct number was %s" % correct_number
response_session_attributes['game_over'] = 1
return build_ssml_response(response,0,response_session_attributes, card_text=card_text)
elif int(tries_left) <= 0:
response = generate_audio_tag(audio_9[2])+ "The correct number is %s" % correct_number + half_second_break + "Do you want to play again?"
card_text = "Game over. The correct number was %s" % correct_number
response_session_attributes['game_over'] = 1
return build_ssml_response(response,0,response_session_attributes, card_text=card_text)
elif int(correct_number) > int(chosen_number):
response = "Higher. You have %s %s left." % (tries_left,word)
#response = "%s is incorrect. Guess a higher number. You have %s %s left" % (chosen_number,tries_left,word)
#debug
# response = "Guess a higher number. You have %s %s left. Hint: %s" % (tries_left,word,correct_number)
return build_ssml_response(response,0,response_session_attributes)
elif int(correct_number) < int(chosen_number):
response = "Lower. You have %s %s left." % (tries_left,word)
#response = "%s is incorrect. Guess a lower number. You have %s %s left" % (chosen_number,tries_left,word)
return build_ssml_response(response,0,response_session_attributes)
else:
return build_ssml_response("Unknown Error",0,response_session_attributes)
elif intent_name == "PlayAgainIntent" and is_game_over == 1:
chosen_play_again_yn = get_slot_value(event,'play_again')
if chosen_play_again_yn == 'yes':
response_session_attributes['playing'] = 0
response_session_attributes['game_over'] = 0
return build_ssml_response("Choose A Level Between Easy, Medium, or Hard",0,response_session_attributes)
elif chosen_play_again_yn == 'no':
return build_ssml_response("Thank You For playing Bomb Defuse",1,response_session_attributes)
else:
return build_ssml_response("Unknown Error",0,response_session_attributes, card_text="PlayAgainIntent called")
else:
return build_ssml_response(intent + ' I did not understand. Can you say it again?', 0,response_session_attributes)
except:
exc_type, exc_obj, exc_tb = sys.exc_info()
fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
card_text = str(exc_type) + ' ' + str(fname) + ' ' + str(exc_tb.tb_lineno)
response_session_attributes['card_text'] = card_text
return build_ssml_response("I did not understand you. Can you please say it again?",0,response_session_attributes)
def generate_audio_tag(url):
#
#url = 'https://s3.amazonaws.com/alexagamefilesbucket/' + filename
#
#IF PRIVATE
#
# url = s3.generate_presigned_url('get_object', Params = {'Bucket': 'alexagamefilesbucket', 'Key': filename}, ExpiresIn = 3600)
# url = url.replace("&","%26")
return '<audio src="%s"/>' % url
def put_in_audio_tag(url):
return '<audio src="%s"/>' % url
def get_session_value(event,key):
try:
value = event.get('session').get('attributes').get(key)
return value
except TypeError:
return False
except:
return False
def get_slot_value(event,key):
try:
attribute = event.get('request').get('intent').get('slots').get(key).get('value')
return attribute
except TypeError:
return False
except:
return False
def build_ssml_response(speech_output, should_end_session, session_attributes = {}, **kwargs):
response = {
"version": "1.0",
"sessionAttributes": session_attributes,
"response": {
"outputSpeech": {
"type": "SSML",
"ssml":"<speak>" + str(speech_output)[:7999] + "</speak>"
},
"reprompt": {
"outputSpeech": {
"type": "SSML",
"ssml": "<speak>" + str(speech_output)[:7999] + "</speak>"
}
},
"shouldEndSession": should_end_session
}
}
#if problem playing on amazon echo device
try:
if kwargs['card_text'] is not False:
response['response']['card'] = {"type": "Simple", "title": 'Defuse', "content": kwargs['card_text']}
#except is GOOD in this case & normal
except:
pass
return response
import os, sys
import urllib2
import random
def lambda_handler(event, context):
try:
#FORCED TO HAVE PROGRAM FLOW with Try & Catch BECAUSE OF A GLITCH IN AMAZON ECHO DEVICE vs Alexa Service Simulator
try:
response_session_attributes = event["session"]["attributes"]
except:
response_session_attributes = {'debug':'problem with session variables'}
state = get_session_value(event,'state','menu')
intent = get_intent(event)
#return build_ssml_response(intent, 1, response_session_attributes)
print intent
bodyparts = ["Gallows","Body","Right Arm","Left Arm","Right Leg","Left Leg"]
dict_of_bodyparts = {i+1:c for i,c in enumerate(bodyparts[::-1])}
number_descriptors = {1:'first',2:'second',3:'third',4:'fourth',5:'fifth',6:'sixth',7:'seventh',8:'eighth',9:'ninth',10:'tenth',11:'eleventh',12:'twelveth'}
if state == 'game_over':
if intent == "PlayAgainIntent":
choose_play_again_yn = str(get_slot_value(event,'play_again'))
if choose_play_again_yn == 'yes':
#fall-through
state = 'menu'
response_session_attributes['state'] = 'menu'
elif choose_play_again_yn == 'no':
return build_ssml_response('Thank you for playing Hang Guy', 1,response_session_attributes)
else:
return build_ssml_response('Do you want to play again?', 0,response_session_attributes)
else:
return build_ssml_response('Do you want to play again?', 0,response_session_attributes)
if state == 'menu':
if intent == 'ChooseLevelIntent':
#change this eventually
chosen_level = str(get_slot_value(event,'level')).lower()
if chosen_level not in ['easy','medium','hard']:
return build_ssml_response("Please choose a level between easy, medium or hard", 0, response_session_attributes)
word = get_word(chosen_level)
response_session_attributes['word'] = word
response_session_attributes['state'] = 'guessing'
response_session_attributes['puzzle'] = ""
response_session_attributes['instruction_flag'] = 1
response_session_attributes['correct'] = ""
response_session_attributes['tries_left'] = len(bodyparts)
instructions = 'Your word is %s letters. Start Guessing Letters' % len(word)
return build_ssml_response(instructions, 0, response_session_attributes)
else:
return build_ssml_response("Please choose a level between easy, medium or hard", 0, response_session_attributes)
elif state == 'guessing':
if intent == "ChooseLetterIntent":
chosen_letter = str(get_slot_value(event,'chosen_letter'))[0].lower()
word = str(get_session_value(event,'word'))
debug_text = "%s %s" % (chosen_letter, word)
word_length = len(word)
tries_left = int(get_session_value(event,'tries_left'))
tries_left -= 1
if tries_left <= 0:
response_session_attributes['state'] = 'game_over'
return build_ssml_response("You lost. The correct word was %s . Would you like to play again?" % word, 0,response_session_attributes)
elif chosen_letter in word:
correct = str(get_session_value(event,'correct'))
correct += chosen_letter
correct_position = 0
correct_count = 0
puzzle = ''
response_letter_placement = ''
for i in word:
correct_position += 1
if i in correct:
puzzle += i
else:
puzzle += "_"
if i == chosen_letter:
response_letter_placement += " %s is the %s letter, " % (i,number_descriptors[correct_position])
if correct_position == len(word):
response_letter_placement += '<break time="200ms"/> %s is the last letter. ' % (i)
correct_count += 1
times = "once" if correct_count == 1 else "%s times" % correct_count
response = "%s shows up %s. " % (chosen_letter,times) + response_letter_placement
#ONLY GIVE INSTRUCTIONS ON FIRST TRY
instruction_flag = int(get_session_value(event,'instruction_flag'))
if instruction_flag == 1:
response += ' Say, What Do I Have, to hear your progress. Put <break time="40ms"/>Is<break time="10ms"/>It<break time="50ms"/>before your answer'
response_session_attributes['instruction_flag'] = 0
#CORRECT IF ALL LETTERS ARE SOLVED
if puzzle == word:
response_session_attributes['state'] = 'game_over'
return build_ssml_response('Congratulations. You win! The word was %s. Do you want to play again' % word, 0,response_session_attributes)
response_session_attributes['correct'] = correct
response_session_attributes['puzzle'] = puzzle
return build_ssml_response(response, 0,response_session_attributes, exception=debug_text)
elif chosen_letter not in word:
response = "Sorry, no <say-as interpret-as='spell-out'>%s</say-as>. drawing the %s." % (chosen_letter, dict_of_bodyparts[tries_left])
response_session_attributes['tries_left'] = tries_left
return build_ssml_response(response, 0,response_session_attributes, exception=debug_text)
else:
return build_ssml_response("You said <say-as interpret-as='spell-out'>%s</say-as>. If you want to solve, say I'd like to solve" % chosen_letter, 0,response_session_attributes,exception=word)
if intent == "RemindIntent":
puzzle = str(get_session_value(event,'puzzle')).lower()
word = str(get_session_value(event,'word'))
response = 'You have a %s letter word<break time="500ms"/>' % len(word) + '<break time="300ms"/>'.join(['blank' if i=='_' else i for i in list(puzzle)])
return build_ssml_response(response, 0,response_session_attributes)
if intent == "SolveIntent":
solve = str(get_slot_value(event,'solve'))
word = str(get_session_value(event,'word'))
if solve == word:
response_session_attributes['state'] = 'game_over'
return build_ssml_response('Congratulations. You win! Do you want to play again', 0,response_session_attributes)
else:
response_session_attributes['state'] = 'guessing'
return build_ssml_response('%s is not the answer. Please choose more letters or solve again.' % solve, 0,response_session_attributes)
if intent == "AMAZON.CancelIntent" or intent == "AMAZON.StopIntent":
return build_ssml_response('Thank you for using Hang Guy. See you next time!', 1)
else:
return build_ssml_response('Please guess more letters or solve the puzzle. Say, is it, before the answer', 0,response_session_attributes)
except:
exc_type, exc_obj, exc_tb = sys.exc_info()
fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
exception_text = str(exc_type) + ' ' + str(fname) + ' ' + str(exc_tb.tb_lineno)
response_session_attributes['exception'] = exception_text
return build_ssml_response("I did not understand you. Can you please say it again?",0,response_session_attributes,exception=exception_text)
#####
# PLEASE REPLACE URL IF YOU ARE CHANGING IT!!! WORDS MUST BE SEPARATED IN NEW LINES
#####
def get_word(level):
results = urllib2.urlopen('http://pastebin.com/raw/baKjRnDu').read()
list_of_results = results.split("\n")
length_of_results = len(list_of_results)
dict_of_lengths = {'easy':[3,4],'medium':[5,6],'hard':[7,8,9,10,11,12]}
while True:
list_index = random.randrange(0,length_of_results-1)
word = list_of_results[list_index].strip()
list_index += 1
if list_index == length_of_results - 1:
list_index = 0
if len(word) in dict_of_lengths[level]:
break
return word
def get_intent(event):
if event["request"]["type"] == "LaunchRequest":
return "LaunchRequest"
elif event["request"]["type"] == "IntentRequest":
return event["request"]["intent"]["name"]
else:
return False
def get_session_value(event,key,default=False):
try:
value = event.get('session').get('attributes').get(key,default)
return value
except TypeError:
return default
except:
return default
def get_slot_value(event,key,default=False):
try:
attribute = event.get('request').get('intent').get('slots').get(key).get('value')
return attribute
except TypeError:
return default
except:
return default
def build_ssml_response(speech_output, should_end_session, session_attributes = {}, **kwargs):
response = {
"version": "1.0",
"sessionAttributes": session_attributes,
"response": {
"outputSpeech": {
"type": "SSML",
"ssml":"<speak>" + str(speech_output)[:7999] + "</speak>"
},
"reprompt": {
"outputSpeech": {
"type": "SSML",
"ssml": "<speak>" + str(speech_output)[:7999] + "</speak>"
}
},
"shouldEndSession": should_end_session
}
}
#if problem playing on amazon echo device
try:
if kwargs['exception'] is not False:
response['response']['card'] = {"type": "Simple", "title": 'title', "content": kwargs['exception']}
#except is GOOD in this case & normal
except:
pass
return response
import asyncio
import regex
import traceback
import sys
import time
from helper import *
class CiscoAsyncObject(object):
command_timeout = 40
def byte_to_string(self,obj):
'''byte_to_string
clean up a raw byte stream by recv. Chiefly used in read function.
Arguments:
obj {bytes (recv(1024))} -- messy bytes
Returns:
string -- so beautifully neat
'''
text = obj.decode('utf-8','ignore')
text = ''.join([x for x in str(text) if ord(x) < 128])
return text
async def async_cisco_socket(self,loop,ip,port =23):
'''async_cisco_socket
This should be like the __init__ function of a socket class, but I don't know how to do init in an asynchronous context. So the end result will be that this will just populate self.reader & self.writer of this object
'''
connect_retries = 8
tries = 0
#try this the amount of connect_retries times
while tries < connect_retries:
try :
reader, writer = await asyncio.open_connection(ip, port, loop=loop)
if(reader is not None):
hostname_line(ip,'Socket Created')
#when the connection begins and you have to write "en" & password for Socket
self.ip = ip
self.hostname = get_hostname(ip)
self.reader = reader
self.writer = writer
await self.initialize_socket()
break
else:
print(reader,writer)
except ConnectionRefusedError:
tries = tries + 1
hostname_line(ip,"Couldn't connect because of ConnectionRefusedError")
except TimeoutError:
tries = tries + 1
hostname_line(ip,"Couldn't connect because of TimeoutError")
await asyncio.sleep(1)
except Exception as exc:
tries = tries + 1
hostname_line(ip,"Generic Exception -> %s" % (exc))
if tries >= connect_retries:
hostname_line(ip,"No socket connection because it exhausted it's maximum limit of retries.")
async def sendline(self,command,**kwargs):
'''sendline
sendlines a command into the socket (Cisco here), and you could make it return the text to show up in the loop results, OR you could have it print as it goes. I prefer to have it print as it goes, and I did that option.
Kwargs is:
expect = regex, which will break the recv read calls
print = True/False, which prints the message as it goes
newline = True/False (default True)
'''
chunks = []
text = ''
start_time_timeout_check = time.time()
reader = self.reader
writer = self.writer
ip = self.ip
hostname = self.hostname
print_it = kwargs.get('print',False)
#expect regex that will break the recv loop
expect_regex = kwargs.get('expect',None)
default_regex = hostname + '.*' + '[#|\^|>]'
#the default is in the right
expect_regex = expect_regex if expect_regex != None else default_regex
#IF NEWLINE KWARGS IS FALSE
if kwargs.get("newline") is False:
command = command
else:
command = command + "\n"
#clear line
for i in range(3):
writer.write(b"\x15")
await asyncio.sleep(.05)
#do actual sending
writer.write(command.encode())
while 1:
#Break up out of here no matte what, by the command timeout
total_time = time.time() - start_time_timeout_check
# print("%s %s" % (command,total_time))
if total_time > self.command_timeout:
print('"%s" has timed out' % (command))
return 'Time Out'
try:
chunk = await self.reader.read(8024)
if not chunk:
break
chunk = self.byte_to_string(chunk)
chunk_length = len(chunk)
text = text + chunk
# print("REGEX> ", expect_regex, len(chunk), chunk.replace('\n', ' ').replace('\r', ' '),regex.search(expect_regex,chunk))
#stop doing the recv at if the expect regex is not in the ENTIRE TEXT or the exception. It will stop at expect
if regex.search(expect_regex,text) is not None:
# print(command, "Expect happened")
break
except Exception as exc:
print(hostname_line(ip, "Exception as %s" % (exc)))
traceback.print_exc()
await asyncio.sleep(.5)
continue
except:
print("Error")
#END READ
#THIS IS DONE TO KEEP TRACK OF ? COMMANDS
#This is for later text cleanup
if len(command) > 0:
self.current_command = command.strip()
#just get the result without fluff
#remove command in beginning & prompt at end
text = text.replace(self.current_command,'')
text = text.replace(self.current_command.replace(' ?',''),'')
text = regex.sub(self.current_command,'',text)
text = text.strip()
#clean will remove the prompt, and other custom cleaning
#remove the prompt in the end!
text = regex.sub('\n%s.*[#|\^|>]' % (self.hostname),'',text)
text = regex.sub('%s' % (self.current_command.replace(' ?','')),'',text)
# text = text.strip()
#clean up it for the console
text = sanitize(text.replace('\n', ' ').replace("",'').strip())
text = regex.sub('\r\s*','\r',text)
#does the printing in each send line IF kwargs print is true (like print=True as parameter)
if kwargs.get("newline") == True:
header = wrap(wrap_hostname_line(ip,'Results of "%s"' % (command)))
print(header + "\n" + text)
return text
async def initialize_socket(self):
'''initialize_socket
this is called by the async_connect to get to the config mode
'''
await self.sendline('en',expect="Password")
await self.sendline('goon')
await self.sendline('terminal length 0')
await self.config_mode()
async def config_mode(self):
'''config mode
Goes Into Config Mode of course
'''
await self.sendline("configure terminal")
async def privileged_mode(self):
'''privilged_mode
the mode before global config mode, which is privileged mode
'''
await self.config_mode()
await self.sendline("end")
async def write(self,command):
'''write
Write raw BYTES
command is in BYTES, not string
'''
# print("Writing: %s" % (command))
self.writer.write(command)
async def clear_line(self,command=b"\x15"):
'''clear_line
Simply writes b'\x15' into Telnet which clears the line! This is required for those ? help commands.
This also represents Ctrl+U in the ASCII map, and is verified in Wireshark.
'''
await self.write(b"\x15")
import asyncio
import regex
import traceback
import sys
from async_socket_connection import *
from helper import *
class CiscoSyncObject():
cisco_async_object = None
loop = None
def __init__(self,ip):
'''__init__
The Constructor will simply set an instance variable of an instance of the CiscoAsyncObject inside of async_socket_connection.py. The constructor runs the Asyncio Loop that will never end.
Arguments:
ip {string} -- ip address of device to access
Returns:
nothing -- nothing
'''
async def instantiate_inner_func(loop,ip):
cisco_async_object = CiscoAsyncObject()
await cisco_async_object.async_cisco_socket(loop,ip)
return cisco_async_object
self.loop = asyncio.new_event_loop()
asyncio.set_event_loop(self.loop)
tasks = [asyncio.ensure_future(instantiate_inner_func(self.loop,ip))]
nodes = self.loop.run_until_complete(asyncio.gather(*tasks))
object = l(nodes,0)
self.cisco_async_object = object
def __getattr__(self,name,*args,**kwargs):
'''__get_attr
__getattr__ and __call__ are the two methods that are called when an unknown function is ran in a Python Class, similar to the behavior to the PHP __get magic function. Here the method call is saved for later use in the __call__ function. GetAttr dunder method gets the function name.
Arguments:
name {string} -- method name
*args {[type]} -- [description]
**kwargs {[type]} -- [description]
Returns:
CiscoSyncSocket -- Self
'''
self.method_call = name
return self
def __call__(self,name=None,*args,**kwargs):
'''__call__
See the getattr method. __getattr__ and __call__ both deal with unknown functions. But there's a lot more. getattr(self.cisco_async_object,self.method_call)(name,*args,**kwargs) calls the function dynamically. It calls the self.method call (by call) on the self.cisco_async_object.
Arguments:
name {string} -- argument inside of function
*args {[type]} -- [description]
**kwargs {[type]} -- [description]
Returns:
string -- result
'''
return l(self.loop.run_until_complete(asyncio.gather(getattr(self.cisco_async_object,self.method_call)(name,*args,**kwargs))),0)
import regex, sys, csv, functools,operator,time
from helper import *
#########################
# NONE DECORATOR EXCEPTION
#########################
def catch_exception(func):
def func_wrapper(self,*args,**kwargs):
try:
#actually run function
data = func(self,*args,**kwargs)
except:
data = None
return data
return func_wrapper
#########################
# RULES
#########################
rules_d = {'0244230000':'Shandi Grenville (or another person who attended the phones at the Beechwood offices)',
'0242245500':'Shandi Grenville (or another person who attended the phones at the Beechwood offices)',
'0404821015':'Trevor Moffatt (Beechwood)',
'0242960139':'"Matt Slee (Building & Design Team - South Coast:\' Beechwood)"',
'0412605594':'Anthony Higgins (Southern Trenching)',
'0404821914':'Wayne Braid (Beechwood)',
'0296160999':'someone at the Beechwood Sydney Business Centre (Head Office)',
'0244221233':'someone at Leslie & Thompson Pty Ltd',
'0402350828':'"Thomas Smith (Building & Design Team:\' Beechwood)"',
'0244240012':'someone at the Twin Waters estate (Beechwood)',
'0414975583':'"Geoff Slee (Building & Design Team - South Coast, Beechwood)"'}
rules_d_k = list(rules_d.keys())
#########################
# REGEX VARIABLES
# //ANCHOR: Variables
#########################
format_regex = ''
time_regex = '\d{1,2}:\d{1,2}:\d{1,2}'
date_regex = '\d{4}\-\d{1,2}\-\d{1,2}'
space_new_regex = '[\s|\n]*'
any_regex = '.*?'
date_time_regex = date_regex + space_new_regex + time_regex
time_date_regex = time_regex + space_new_regex + date_regex
overall_date_regex = '(' + time_date_regex + '|' + date_time_regex + ')'
look_start_regex = '(?<=^|\s)'
look_end_regex = '(?=\s|$)'
series_of_words_regex = look_start_regex + '\d*\s*[A-Za-z]*[A-Za-z|\-|\s]*' + look_end_regex
disk_space_regex = look_start_regex + '\d{1,2}\.\d{1,2}MB|GB' + look_end_regex
currency_regex = look_start_regex + '\$\d*\.\d*' + look_end_regex
duration_regex = look_start_regex + '\d{1,2}:\d{1,2}' #00:22 + look_end_regex
phone_number_regex = look_start_regex + '[0-9]+' + look_end_regex
integer_regex = look_start_regex + '[0-9]+' + look_end_regex
input_base_path = '/home/mark/makeshift/files/australia_mobile/data/'
csv_base_path = '/home/mark/makeshift/files/australia_mobile/csv/'
csv_all_file_name = 'phone_all.csv'
csv_filtered_file_name = 'phone_filtered.csv'
csv_rules_file_name = 'rules_total.csv'
csv_all_file_path = csv_base_path + csv_all_file_name
csv_filtered_file_path = csv_base_path + csv_filtered_file_name
csv_rules_file_path = csv_base_path + csv_filtered_file_name
input_files = ['logs_mobile.txt','logs_2016.txt','logs_2017.txt']
input_files = ['logs_mobile_2.txt','logs_2016.txt','logs_2017.txt']
nodes = []
row = []
schema = ''
usage_type = ''
called_number = None
schema_allowed = ['mobile','phone','sms_national','data']
# input_files = ['logs_2017.txt']
#DO SHIT FOR RULES_COUNT_CSV!!!
rules_count_d = {}
for phone_number, name in rules_d.items():
rules_count_d[str(phone_number)] = {}
rules_count_d[phone_number]['name'] = name
for input_file in input_files:
rules_count_d[phone_number][input_file] = 0
#note
#
#TWO TYPES OF ROWS
#
#1) data = ['Data', '0.02MB', '0.02MB', '$0.00000', '$0.00000', '$0.00000']
#
#
#2) calls = ['Mobile', 'Call', '09:46', '0418695084', '0.00MB', '$9.35000', '$0.00000', '$0.00000']
#
#//ANCHOR: REGEX ROWS
data_regex_row = '(%s)%s(%s)%s(%s)%s(%s)%s(%s)%s(%s)' % (series_of_words_regex , space_new_regex , disk_space_regex , space_new_regex , disk_space_regex , space_new_regex , currency_regex , space_new_regex , currency_regex , space_new_regex , currency_regex)
calls_mobile_regex_row = '(%s)%s(%s)%s(%s)%s(%s)%s(%s)%s(%s)%s(%s)' % (series_of_words_regex , space_new_regex, duration_regex , space_new_regex , phone_number_regex , space_new_regex , disk_space_regex , space_new_regex , currency_regex , space_new_regex , currency_regex , space_new_regex , currency_regex)
sms_national_regex_row = '(%s)%s(%s)%s(%s)%s(%s)%s(%s)%s(%s)%s(%s)' % (series_of_words_regex , space_new_regex, integer_regex , space_new_regex , phone_number_regex , space_new_regex , disk_space_regex , space_new_regex , currency_regex , space_new_regex , currency_regex , space_new_regex , currency_regex)
calls_phone_regex_row = '(%s)%s(%s)%s(%s)%s(%s)%s(%s)' % (series_of_words_regex , space_new_regex, duration_regex , space_new_regex , phone_number_regex , space_new_regex , currency_regex , space_new_regex , duration_regex)
#########################
# GET NODES!!! the nodes is a list of dictionaries, and the dictionaries have values of date_time & data
#########################
for input_file in input_files:
input_file_path = input_base_path + input_file
with open(input_file_path,'r') as f:
lines = f.readlines()
for index,line in enumerate(lines):
#IF IT STARTS WITH DATE & TIME
if regex.match("^" + any_regex + date_time_regex,line):
date_time = regex.findall(date_regex,line)[0] + " " + regex.findall(time_regex,line)[0]
data = regex.findall(date_time_regex + "(.*)" + look_end_regex,line)[0]
nodes.append({'date_time':date_time,'data':data,'file':input_file})
# pass
#handles the very weird situation of DATE + DATA + TIME
if regex.match("^" + time_regex + "$",line.strip()):
#get date
date = lines[index-2].strip()
if(regex.match(date_regex,date) is None):
for i in range(-1,-10,-1):
try:
date = regex.findall(date_regex,nodes[i]['date_time'])[0]
except:
continue
date_time = str(date) + " " + line.strip()
data = lines[index-1]
nodes.append({'date_time':date_time,'data':data,'file':input_file})
#########################
# CLIENT
#########################
#Inside File
csv_all_handle = open(csv_all_file_path,'w')
csv_filtered_handle = open(csv_filtered_file_path,'w')
csv_rules_handle = open(csv_rules_file_path,'w')
for node in nodes:
#if the row is not neat, it will reflect in the default if statement below
ignore_row = False
date_time = node['date_time']
messy_line = node['data']
try:
#VARIABLES THAT WILL BE IN THE ROW
try:
time_tuple = time.strptime(date_time,"%Y-%m-%d %H:%M:%S")
date_row_value = time.strftime('%d/%m/%Y %H:%M:%S', time_tuple)
description_date_value = time.strftime('%H:%M', time_tuple)
except:
#if reaching here, the row will likely not even show up
overall_date = None
date_row_value = None
description_date_value = None
#Note: string is already stripped in regex_groups function as it calls the strip_iterate function
#CALL SCHEMA (MOBILE)!!! (follows call structure define above)!!!
#['Call', 'to', 'non-Optus', 'GSM', '01:35', '0412977644', '0.00MB', '$2.15000', '$0.00000', '$0.00000']
if regex_groups(calls_mobile_regex_row,messy_line) is not None:
schema = 'mobile'
rgo = regex_groups(calls_mobile_regex_row,messy_line)
usage_type = l(rgo,0)
duration = l(rgo,1)
called_number = l(rgo,2).strip()
# debug
# print("CALL",row)
# pass
#DATA SCHEMA (follows data structure define above)!!!
#['Data', '5.85MB', '5.85MB', '$0.00000', '$0.00000', '$0.00000']
elif regex_groups(data_regex_row,messy_line) is not None:
#according to Sarah, ignore all data
ignore_row = True
# debug
# print("DATA",row)
# pass
#SMS NATIONAL TYPE OF DATA SCHEMA
#['SMS', 'National', '1', '0406665748', '0.00MB', '$0.00000', '$0.00000', '$0.00000']
elif regex_groups(sms_national_regex_row,messy_line) is not None:
schema = 'sms_national'
rgo = regex_groups(sms_national_regex_row,messy_line)
usage_type = l(rgo,0)
duration = l(rgo,1)
called_number = l(rgo,2).strip()
# print("SMS",row)
# pass
#CALL PHONE!!
elif regex_groups(calls_phone_regex_row,messy_line) is not None:
schema = 'phone'
rgo = regex_groups(calls_phone_regex_row,messy_line)
usage_type = l(rgo,0)
duration = l(rgo,1)
called_number = l(rgo,2).strip()
# print("PHONE", row)
pass
#Fits No Criteria
else:
ignore_row = True
pass
#is_sms?
is_sms = 1 if 'sms' in usage_type.lower() else 0
#what is person's name in the rule sheet
person_name = dvkp(rules_d,called_number[1:])
describe_event = 'At %s I called %s and spoke with %s on the telephone.' % (description_date_value, called_number, person_name)
input_file = node['file']
except KeyError:
print("KeyError in " + str(index))
pass
except IndexError:
print("IndexError in " + str(index))
pass
except ValueError:
print("ValueError in " + str(index))
pass
except TypeError:
print("TypeError in " + str(index))
pass
#########################
# WRITE CSV ROW HERE
#########################
if(ignore_row == False and date_row_value is not None):
row = [date_row_value,duration,is_sms,called_number,input_file]
# print(row)
csv_all_handle.write(str(','.join(list(map(str,row)))))
csv_all_handle.write('\n')
csv_all_handle.flush()
#FILTERED SHEET
#ignore row here means don't print data
#person_name filter means only show values inside the rules section
#date_row_value means don't show funny looking rows
if(ignore_row == False and date_row_value is not None and person_name is not None):
row = [date_row_value,duration,is_sms,describe_event,input_file]
print(row)
#record tallies for the next rules csv sheet
rules_count_d[called_number][input_file] += 1
# print(rules_count_d)
csv_filtered_handle.write(str(','.join(list(map(str,row)))))
csv_filtered_handle.write('\n')
csv_filtered_handle.flush()
#########################
# WORK ON RULES CSV FILE
#########################
# for phone_number,node in rules_count_d.items():
# row = [node[input_file] for input_file in input_files]
# total_sum = sum(row)
# row.insert(0,node['name'])
# row.insert(1,phone_number)
# row.append(total_sum)
# csv_rules_handle.write(str(','.join(list(map(str,row)))))
# csv_rules_handle.write('\n')
# csv_rules_handle.flush()
Netconf
Network Automation via NETCONF + Configure both CLI/NETCONF via Python, to analyze all the key/value pairs & configurable values in a Cisco CSR V1000 router. Subclassing was separate for Netconf & regular CLI.
Python
Click for Portfolio
import paramiko
import xmltodict
import xml
import pprint
import sys
from helpers import *
from time import sleep
from functools import partial
from bs4 import BeautifulSoup
from itertools import cycle
class SSH():
client = None
session = None
read_interval = .5
connect_params = {"hostname": "192.168.0.201", "username": "goon",
"password": "goon", "port": 22, "look_for_keys": False, "allow_agent": False}
def read(self):
blocks = []
chunk_size = 2524
while True:
sleep(self.read_interval)
block = self.session.recv(chunk_size)
# DEBUG
# print(block.decode(),end="")
# file_add_contents("add.xml",block.decode())
# end debug
blocks.append(block.decode())
if len(block) < chunk_size:
break
text = ''.join(blocks).strip()
return text
def start(self, *args, **kwargs):
self.client = paramiko.SSHClient()
# overrides the default above
self.connect_params.update(kwargs)
hostname = self.connect_params.get("hostname")
del self.connect_params['hostname']
# debug
print("LOGGING INTO:")
print(hostname, self.connect_params)
self.client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
self.client.connect(hostname, **self.connect_params)
self.session = self.client.get_transport().open_session()
# Only uncomment if sending command line arguments. Separate into separate class or function if expands.
def s(self, *args, **kwargs):
'''console shorthand'''
self.start(*args, **kwargs)
def close(self):
self.client.close()
print("SSH Session Closed")
class CommandLine(SSH):
'''Command Line Specific'''
# port 22
connect_params = {'hostname': '10.10.20.48', 'username': 'cisco',
'password': 'cisco_1234!', 'port': 22, 'look_for_keys': False, 'allow_agent': False}
def __init__(self, *args, **kwargs):
self.start(*args, **kwargs)
# invoke shell is specific to Command Lines (not netconf)
self.session.invoke_shell()
def send(self, command):
command = command + "\n"
self.session.send(command.encode())
response = self.read()
return response
class Netconf(SSH):
'''Class & Functions & Values specific to NETCONF'''
#
# Cisco DevNet Params
# port 830
#
cisco_namespace_prefix = 'http://cisco.com/ns/yang/'
ietf_namespace_prefix = 'urn:ietf:params:xml:ns:yang:'
connect_params = {'hostname': '10.10.20.48', 'username': 'cisco',
'password': 'cisco_1234!', 'port': 830, 'look_for_keys': False, 'allow_agent': False}
terminator = ']]>]]>'
def __init__(self, *args, **kwargs):
# Cisco Devnet Params
self.start(*args, **kwargs)
self.netconf_hello()
def n(self):
'''console restart socket & netflow shorthand'''
self.start()
self.netconf_hello()
def send(self, command):
command = command + self.terminator + "/n"
self.session.send(command.encode())
response = self.read()
return response
def netconf_hello(self):
self.session.invoke_subsystem('netconf')
hello_rpc = '<?xml version="1.0" encoding="UTF-8"?><hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><capabilities><capability>urn:ietf:params:netconf:base:1.0</capability></capabilities></hello>'
return self.send(hello_rpc)
def change_hostname(self, hostname):
self.send(
f'<?xml version="1.0" encoding="UTF-8"?> <rpc message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"> <edit-config> <target> <running/> </target> <config> <cli-config-data> <cmd>hostname {hostname}</cmd> </cli-config-data> </config> </edit-config> </rpc>')
def print_netconf_graph(self, xml_response):
xml_response = xml_response.replace(self.terminator, '')
try:
print_structure(xmltodict.parse(xml_response))
except xml.parsers.expat.ExpatError:
print("Your XML is structured wrong")
def console_send(self, xml_filepath="payload.txt"):
'''meant for consoles. filename with XML to send must be in payload.txt'''
self.print_netconf_graph(n.send(file_get_contents(xml_filepath)))
def get(self, filter):
rpc_get = '<?xml version="1.0" encoding="UTF-8"?><rpc message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><get><filter>' + \
filter + '</filter></get></rpc>'
return self.send(rpc_get)
def edit_config(self, filter):
rpc_edit_config = '<?xml version="1.0" encoding="UTF-8"?><rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="111"><edit-config><target><running/></target><config>' + \
filter + '</config></edit-config></rpc>'
return self.send(rpc_edit_config)
def pretty_print_xml(self, ugly_xml):
bs = BeautifulSoup(ugly_xml, 'xml')
print(bs.prettify())
if __name__ == '__main__':
try:
#cisco_namespace_prefix = "http://cisco.com/ns/yang/"
#ietf_namespace_prefix = "urn:ietf:params:xml:ns:yang:"
# CISCO DEVNET! CISCO ANYCONNECT MUST BE ACTIVATED
cs = Netconf()
client = cs.client
rpc_fragment = '''<interfaces xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-interfaces-oper">
<interface>
<name>GigabitEthernet2</name>
</interface>
</interfaces>'''
for octet_4 in cycle(range(4, 255)):
rpc_fragment = f'<interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces"> <interface operation="replace"> <name> GigabitEthernet2 </name> <description> GOON </description> <type xmlns:ianaift="urn:ietf:params:xml:ns:yang:iana-if-type"> ianaift:ethernetCsmacd </type> <enabled> true </enabled> <ipv4 xmlns="urn:ietf:params:xml:ns:yang:ietf-ip"> <address> <ip> 10.10.50.{octet_4} </ip> <netmask> 255.255.255.0 </netmask> </address> </ipv4> </interface> </interfaces> '
xml_response = cs.edit_config(rpc_fragment)
xml_response = cs.get(rpc_fragment)
print(xml_response)
finally:
sleep(1)
client.close()
import paramiko
import xmltodict
import xml
import pprint
import sys
from helpers import *
from time import sleep
from functools import partial
from bs4 import BeautifulSoup
from itertools import cycle
class SSH():
client = None
session = None
read_interval = .5
connect_params = {"hostname": "192.168.0.201", "username": "goon",
"password": "goon", "port": 22, "look_for_keys": False, "allow_agent": False}
def read(self):
blocks = []
chunk_size = 2524
while True:
sleep(self.read_interval)
block = self.session.recv(chunk_size)
# DEBUG
# print(block.decode(),end="")
# file_add_contents("add.xml",block.decode())
# end debug
blocks.append(block.decode())
if len(block) < chunk_size:
break
text = ''.join(blocks).strip()
return text
def start(self, *args, **kwargs):
self.client = paramiko.SSHClient()
# overrides the default above
self.connect_params.update(kwargs)
hostname = self.connect_params.get("hostname")
del self.connect_params['hostname']
# debug
print("LOGGING INTO:")
print(hostname, self.connect_params)
self.client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
self.client.connect(hostname, **self.connect_params)
self.session = self.client.get_transport().open_session()
# Only uncomment if sending command line arguments. Separate into separate class or function if expands.
def s(self, *args, **kwargs):
'''console shorthand'''
self.start(*args, **kwargs)
def close(self):
self.client.close()
print("SSH Session Closed")
class CommandLine(SSH):
'''Command Line Specific'''
# port 22
connect_params = {'hostname': '10.10.20.48', 'username': 'cisco',
'password': 'cisco_1234!', 'port': 22, 'look_for_keys': False, 'allow_agent': False}
def __init__(self, *args, **kwargs):
self.start(*args, **kwargs)
# invoke shell is specific to Command Lines (not netconf)
self.session.invoke_shell()
def send(self, command):
command = command + "\n"
self.session.send(command.encode())
response = self.read()
return response
class Netconf(SSH):
'''Class & Functions & Values specific to NETCONF'''
#
# Cisco DevNet Params
# port 830
#
cisco_namespace_prefix = 'http://cisco.com/ns/yang/'
ietf_namespace_prefix = 'urn:ietf:params:xml:ns:yang:'
connect_params = {'hostname': '10.10.20.48', 'username': 'cisco',
'password': 'cisco_1234!', 'port': 830, 'look_for_keys': False, 'allow_agent': False}
terminator = ']]>]]>'
def __init__(self, *args, **kwargs):
# Cisco Devnet Params
self.start(*args, **kwargs)
self.netconf_hello()
def n(self):
'''console restart socket & netflow shorthand'''
self.start()
self.netconf_hello()
def send(self, command):
command = command + self.terminator + "/n"
self.session.send(command.encode())
response = self.read()
return response
def netconf_hello(self):
self.session.invoke_subsystem('netconf')
hello_rpc = '<?xml version="1.0" encoding="UTF-8"?><hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><capabilities><capability>urn:ietf:params:netconf:base:1.0</capability></capabilities></hello>'
return self.send(hello_rpc)
def change_hostname(self, hostname):
self.send(
f'<?xml version="1.0" encoding="UTF-8"?> <rpc message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"> <edit-config> <target> <running/> </target> <config> <cli-config-data> <cmd>hostname {hostname}</cmd> </cli-config-data> </config> </edit-config> </rpc>')
def print_netconf_graph(self, xml_response):
xml_response = xml_response.replace(self.terminator, '')
try:
print_structure(xmltodict.parse(xml_response))
except xml.parsers.expat.ExpatError:
print("Your XML is structured wrong")
def console_send(self, xml_filepath="payload.txt"):
'''meant for consoles. filename with XML to send must be in payload.txt'''
self.print_netconf_graph(n.send(file_get_contents(xml_filepath)))
def get(self, filter):
rpc_get = '<?xml version="1.0" encoding="UTF-8"?><rpc message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><get><filter>' + \
filter + '</filter></get></rpc>'
return self.send(rpc_get)
def edit_config(self, filter):
rpc_edit_config = '<?xml version="1.0" encoding="UTF-8"?><rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="111"><edit-config><target><running/></target><config>' + \
filter + '</config></edit-config></rpc>'
return self.send(rpc_edit_config)
def pretty_print_xml(self, ugly_xml):
bs = BeautifulSoup(ugly_xml, 'xml')
print(bs.prettify())
if __name__ == '__main__':
try:
#cisco_namespace_prefix = "http://cisco.com/ns/yang/"
#ietf_namespace_prefix = "urn:ietf:params:xml:ns:yang:"
# CISCO DEVNET! CISCO ANYCONNECT MUST BE ACTIVATED
cs = Netconf()
client = cs.client
rpc_fragment = '''<interfaces xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-interfaces-oper">
<interface>
<name>GigabitEthernet2</name>
</interface>
</interfaces>'''
for octet_4 in cycle(range(4, 255)):
rpc_fragment = f'<interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces"> <interface operation="replace"> <name> GigabitEthernet2 </name> <description> GOON </description> <type xmlns:ianaift="urn:ietf:params:xml:ns:yang:iana-if-type"> ianaift:ethernetCsmacd </type> <enabled> true </enabled> <ipv4 xmlns="urn:ietf:params:xml:ns:yang:ietf-ip"> <address> <ip> 10.10.50.{octet_4} </ip> <netmask> 255.255.255.0 </netmask> </address> </ipv4> </interface> </interfaces> '
xml_response = cs.edit_config(rpc_fragment)
xml_response = cs.get(rpc_fragment)
print(xml_response)
finally:
sleep(1)
client.close()
import ctypes
import sys
import pprint
import time
import string
import webbrowser
from winapi_constants import *
from ctypes import *
from ctypes.wintypes import *
k = ctypes.WinDLL('kernel32', use_last_error=True)
u = ctypes.WinDLL('user32', use_last_error=True)
c = ctypes.WinDLL('comctl32', use_last_error=True)
def dvkp(dict, key_part, default=''):
try:
return [value for key, value in dict.items() if key_part in key][0]
except:
return default
hwnds = {}
def get_hwnd(window_part_name):
def foreach_window(hwnd, lParam):
if u.IsWindowVisible(hwnd):
length = u.GetWindowTextLengthW(hwnd)
buff = ctypes.create_unicode_buffer(length + 1)
u.GetWindowTextW(hwnd, buff, length + 1)
hwnds[buff.value] = hwnd
return True
EnumWindowsProc = WINFUNCTYPE(c_bool, POINTER(c_int), POINTER(c_int))
u.EnumWindows(EnumWindowsProc(foreach_window), 0)
return dvkp(hwnds, window_part_name)
def get_class_name(hwnd):
class_name = create_unicode_buffer(50)
u.GetClassNameW(hwnd, class_name, 50)
return class_name.value.strip()
def get_window_text(hwnd):
window_text = create_unicode_buffer(50)
u.GetWindowTextW(hwnd, window_text, 50)
return window_text.value.strip()
child_window = -1
window_index = 0
def get_window_children(hwnd):
child_hwnds = []
def child_callback(hwnd, param):
nonlocal child_hwnds
child_hwnds.append(hwnd)
return True
EnumChildProc = WINFUNCTYPE(c_bool, POINTER(c_int), POINTER(c_long))
u.EnumChildWindows(hwnd, EnumChildProc(child_callback), pointer(c_long(0)))
return child_hwnds
def debug_hwnds(child_hwnds):
if(len(child_hwnds) > 0):
for child_hwnd in child_hwnds:
length = u.GetWindowTextLengthW(child_hwnd)
window_text = create_unicode_buffer(length + 1)
u.GetWindowTextW(child_hwnd, window_text, length + 1)
print("EXAMINING: " + str(repr(child_hwnd)) + "\n\tCLASS NAME -> " +
get_class_name(child_hwnd) + "\n\tWINDOW TEXT -> " + window_text.value.strip() + "\n")
get_window_children(child_hwnd)
def get_systreeview32_hwnds(child_hwnds):
systreeview_hwnds = []
if(len(child_hwnds) > 0):
for child_hwnd in child_hwnds:
class_name = get_class_name(child_hwnd)
if(class_name == "SysTreeView32"):
systreeview_hwnds.append(child_hwnd)
get_window_children(child_hwnd)
return systreeview_hwnds
# https://docs.microsoft.com/en-us/windows/win32/controls/tvm-getitem
# https://docs.microsoft.com/en-us/windows/win32/controls/tvm-selectitem
class TVITEMA(Structure):
_fields_ = (('mask', UINT), ('hItem', UINT),
('state', UINT), ('stateMask', UINT), ('pszTextx', LPSTR),
('cchTextMax', c_int), ('iImage', c_int), ('iSelectedImage', c_int), ('children', c_int), ('lparam', LPARAM))
# class TVITEMEX(Structure):
# _fields_ = (('mask', UINT), ('hItem', UINT),
# ('state', UINT), ('stateMask', UINT), ('pszTextx', LPSTR),
# ('cchTextMax',c_int),('iImage',c_int),('iSelectedImage',c_int),('children',c_int),('lparam',LPARAM),('iIntegral',c_int),('uStateEx',c_int),("hwnd",HWND),("iExpandedImage",int),("int",iReserved))
def get_selected_item_text():
systreeview_hwnds = get_systreeview32_hwnds(
get_window_children(get_hwnd("Redacted")))
for hwnd in systreeview_hwnds:
root_item_handle_int = u.SendMessageA(
hwnd, TVM_GETNEXTITEM, TVGN_ROOT, 0)
# print("Root Item", hex(root_item_handle_int))
# SELECTING CODE
selected_item_handle_int = u.SendMessageA(
hwnd, TVM_GETNEXTITEM, TVGN_CARET, 0)
# print("Selected Item", hex(selected_item_handle_int))
text_buffer_size = 127
# make item object
selected_item = TVITEMA()
selected_item.hItem = selected_item_handle_int
selected_item.mask = TVIF_TEXT | TVIF_HANDLE
selected_item.cchTextMax = 127
item_memory_size = sizeof(selected_item) + 1024
process_id_dword = DWORD()
# note: DO NOT FORGET THE BYREF FOR PUTTING VARIABLES IN THAT WILL COME OUT WITH A NEW VALUE (IN SOME CASES LIKE THIS DWORD)
thread_id = u.GetWindowThreadProcessId(hwnd, byref(process_id_dword))
# note, if it was a long pointer, extracting it would be .contents (similar to dereferencing with &. Since it's not a pointer, you use .value
process_id = process_id_dword.value
# now that you have process ID, open Process
k.OpenProcess.argtypes = [DWORD, BOOL, DWORD]
k.OpenProcess.restype = HANDLE
process = k.OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ |
PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION, False, process_id_dword)
# print("PROCESS_ID", process_id)
# print("PROCESS", process)
# https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualallocex
# allocate space for the item object & text object in this process
address_item_remote = k.VirtualAllocEx(
process, 0, item_memory_size, MEM_COMMIT, PAGE_READWRITE)
address_text_remote = k.VirtualAllocEx(
process, 0, text_buffer_size, MEM_COMMIT, PAGE_READWRITE)
# when you copy the selected item in the remote process, put the new memory address pointer in that item
selected_item.pszTextx = address_text_remote
# print("address_item_remote", hex(address_item_remote))
# print("address_text_remote", hex(address_text_remote))
item_memory_size = sizeof(selected_item)
bytes_written = DWORD()
k.WriteProcessMemory(process, address_item_remote, byref(
selected_item), item_memory_size, byref(bytes_written))
u.SendMessageA(hwnd, TVM_GETITEM, TVGN_CARET, address_item_remote)
text_buffer = create_string_buffer(text_buffer_size)
bytes_size = text_buffer_size
bytes_read = DWORD()
k.ReadProcessMemory(process, address_text_remote, byref(
text_buffer), text_buffer_size, byref(bytes_read))
# print("BYTES READ", bytes_read)
selected_item_text = text_buffer.value.decode()
k.VirtualFreeEx(process, address_item_remote, 0, MEM_RELEASE)
k.VirtualFreeEx(process, address_text_remote, 0, MEM_RELEASE)
k.CloseHandle(process)
return selected_item_text
def go_to_url(url):
chrome_path = "C:/Program Files (x86)/Google/Chrome/Application/chrome.exe"
webbrowser.open(url, new=2)
LRESULT = LPARAM
ULONG_PTR = WPARAM
chrome_path = "C:/Program Files (x86)/Google/Chrome/Application/chrome.exe"
LowLevelKeyboardProc = WINFUNCTYPE(LRESULT, c_int, WPARAM, LPARAM)
alphanumeric = [c for c in string.digits + string.ascii_uppercase]
class KBDLLHOOKSTRUCT(Structure):
_fields_ = (('vkCode', DWORD), ('scanCode', DWORD),
('flags', DWORD), ('time', DWORD), ('dwExtraInfo', ULONG_PTR))
@LowLevelKeyboardProc
def keyboard_low_level(nCode, wParam, lParam):
msg = cast(lParam, POINTER(KBDLLHOOKSTRUCT))[0]
vk_code = msg.vkCode
# character = chr(vk_code)
# if alphanumeric, and only proceed if pressing down, not both up & down for duplicates
if wParam == WM_KEYDOWN:
# character = character.lower()
print(f"You wrote {vk_code}")
# leave if "e"
query = get_selected_item_text()
if vk_code == 186: # ;
go_to_url(f"https://open.spotify.com/search/{query}")
elif vk_code == 222: # '
go_to_url(
f"http://www.amazon.com/s/ref=nb_sb_noss_2?url=search-alias`%3Ddigital-music&field-keywords={query}")
elif vk_code == 188:
go_to_url(f"http://www.youtube.com/results?search_query={query}")
elif vk_code == 219:
sys.exit(0)
return u.CallNextHookEx(None, nCode, wParam, lParam)
u.SetWindowsHookExW(WH_KEYBOARD_LL, keyboard_low_level, None, 0)
msg = MSG()
lpmsg = pointer(msg)
while u.GetMessageW(lpmsg, 0, 0, 0) != 0:
u.TranslateMessage(lpmsg)
u.DispatchMessageW(lpmsg)
#![allow(warnings, unused)]
mod players;
mod clear_console;
use std::ops::Deref;
use std::io;
use rand::Rng;
use rand::thread_rng;
use rand::seq::SliceRandom;
const amount_of_cards_in_pack:i8 = 7;
const amount_of_packs_in_box:i8 = 24;
#[derive(Debug, PartialEq,Clone)]
enum SportsCardEnum
{
Plain,
Insert(i32),
Refractor,
AtomicRefractor,
Autograph,
Jersey,
Patch,
PatchAutograph,
}
impl SportsCardEnum {
pub fn odds(&self) -> i32 {
match self {
SportsCardEnum::PatchAutograph => 60000,
SportsCardEnum::Patch => 7500,
SportsCardEnum::Jersey => 2500,
SportsCardEnum::Insert(7) => 360,
SportsCardEnum::Insert(6) => 288,
SportsCardEnum::Insert(5) => 144,
SportsCardEnum::AtomicRefractor => 244,
SportsCardEnum::Autograph => 128,
SportsCardEnum::Insert(4) => 96,
SportsCardEnum::Refractor => 72,
SportsCardEnum::Insert(3) => 36,
SportsCardEnum::Insert(2) => 16,
SportsCardEnum::Insert(1) => 4,
SportsCardEnum::Plain => 4,
_ => 1
}
}
pub fn name_of_insert(&self) -> &str {
match self {
SportsCardEnum::Autograph => "Autograph",
SportsCardEnum::AtomicRefractor => "Atomic Refractor",
SportsCardEnum::PatchAutograph => "Patch Autograph",
SportsCardEnum::Plain => "Plain",
SportsCardEnum::Patch => "Patch",
SportsCardEnum::Refractor => "Refactor",
SportsCardEnum::Jersey => "Jersey",
SportsCardEnum::Insert(1) => "Jam City",
SportsCardEnum::Insert(2) => "Season's Best",
SportsCardEnum::Insert(3) => "Rock Stars",
SportsCardEnum::Insert(4) => "Quick Strike",
SportsCardEnum::Insert(5) => "Thunder & Lightning",
SportsCardEnum::Insert(6) => "NetRageous",
SportsCardEnum::Insert(7) => "Hardware",
_ => "Plain"
}
}
pub fn multiplier(&self) -> f32
{
match self
{
SportsCardEnum::PatchAutograph => 5000.0,
SportsCardEnum::Patch => 2000.0,
SportsCardEnum::Jersey => 1000.0,
SportsCardEnum::Insert(6) => 150.0,
SportsCardEnum::AtomicRefractor => 130.0,
SportsCardEnum::Insert(5) => 100.0,
SportsCardEnum::Autograph => 75.0,
SportsCardEnum::Insert(4) => 75.0,
SportsCardEnum::Refractor => 75.0,
SportsCardEnum::Insert(3) => 25.0,
SportsCardEnum::Insert(2) => 20.0,
SportsCardEnum::Insert(1) => 8.0,
SportsCardEnum::Plain => 1.0,
_ => 1.0,
}
}
}
#[derive(Debug,Clone)]
struct SportsCard
{
sports_card_type: SportsCardEnum,
player_name: String,
player_tier: i8,
price: f32
}
impl SportsCard {
fn get_price(&self) -> f32 {
let base_price: f32 = match self.player_tier
{
_ if self.player_tier == 1 => 2.0,
_ if self.player_tier == 2 => 0.5,
_ if self.player_tier == 3 => 0.4,
_ if self.player_tier == 4 => 0.3,
_ if self.player_tier == 5 => 0.25,
_ if self.player_tier == 6 => 0.20,
_ if self.player_tier == 7 => 0.15,
_ if self.player_tier == 8 => 0.05,
_ => 1.0,
};
let multiplier: f32 = self.sports_card_type.multiplier();
let mut price = (base_price * multiplier);
price = match price
{
_ if price >= 50.0 => price - (price % 10.0),
_ if price >= 20.0 => price - (price % 5.0),
_ => price
};
price
}
}
impl Default for SportsCard
{
fn default() -> Self {
SportsCard {
sports_card_type: SportsCardEnum::Plain,
player_name: "None".to_string(),
price: 1.50,
player_tier: 8
}
}
}
#[derive(Debug)]
struct Pack
{
cards: Vec<SportsCard>,
status_of_pack: SportsCardEnum,
begin_border: usize,
begin_insert_border: usize,
}
impl Pack {
fn get_regular_card(&mut self) -> SportsCard
{
let mut player_tuples = players::player_tuples;
let mut rng = thread_rng();
player_tuples.shuffle(&mut thread_rng());
let player_tuple_length = player_tuples.len();
let shuffle_interval = 7;
let mut end_border = self.begin_border + shuffle_interval;
let index = rng.gen_range(self.begin_border..end_border);
let player = player_tuples[index];
//iterate to next level in tuple for the next function call
self.begin_border = self.begin_border + shuffle_interval;
let mut regular_card = SportsCard
{
sports_card_type: SportsCardEnum::Plain,
player_name: player.0.to_string(),
player_tier: player.1,
..Default::default()
};
regular_card.price = regular_card.get_price();
regular_card
}
fn get_insert(&mut self, sports_card_type: SportsCardEnum) -> SportsCard {
let mut player_tuples = players::player_tuples;
player_tuples.shuffle(&mut thread_rng());
// Only those ranked 1 to 4 ( Vec<&(&str, i8) )
let mut player_inserts_tuple = player_tuples.iter().filter(|player| player.1 <= 4).collect::< Vec<_> > ();
let mut rng = thread_rng();
player_inserts_tuple.shuffle(&mut thread_rng());
let player_inserts_tuple_length = player_inserts_tuple.len();
let shuffle_interval = 7;
let mut end_border = self.begin_insert_border + shuffle_interval;
let index = rng.gen_range(self.begin_insert_border..end_border);
let player_insert = player_inserts_tuple[index];
//iterate to next level in tuple for the next function call
self.begin_insert_border = self.begin_insert_border + shuffle_interval;
let mut insert = SportsCard
{
sports_card_type: sports_card_type,
player_name: player_insert.0.to_string(),
player_tier: player_insert.1,
..Default::default()
};
insert.price = insert.get_price();
insert
}
fn fill_pack(&mut self) -> ()
{
let mut cards: Vec<SportsCard> = vec![];
let mut rng = thread_rng();
let random_number = rng.gen_range(0..60000);
let pack_insert_type: SportsCardEnum = match random_number
{
_ if random_number % SportsCardEnum::PatchAutograph.odds() == 0 => SportsCardEnum::PatchAutograph,
_ if random_number % SportsCardEnum::Patch.odds() == 1 => SportsCardEnum::Patch,
_ if random_number % SportsCardEnum::Jersey.odds() == 2 => SportsCardEnum::Jersey,
_ if random_number % SportsCardEnum::Insert(6).odds() == 3 => SportsCardEnum::Insert(6),
_ if random_number % SportsCardEnum::AtomicRefractor.odds() == 4 => SportsCardEnum::AtomicRefractor,
_ if random_number % SportsCardEnum::Insert(5).odds() == 5 => SportsCardEnum::Insert(5),
_ if random_number % SportsCardEnum::Autograph.odds() == 6 => SportsCardEnum::Autograph,
_ if random_number % SportsCardEnum::Insert(4).odds() == 7 => SportsCardEnum::Insert(4),
_ if random_number % SportsCardEnum::Refractor.odds() == 8 => SportsCardEnum::Refractor,
_ if random_number % SportsCardEnum::Insert(3).odds() == 9 => SportsCardEnum::Insert(3),
_ if random_number % SportsCardEnum::Insert(2).odds() == 10 => SportsCardEnum::Insert(2),
_ if random_number % SportsCardEnum::Insert(1).odds() == 0 => SportsCardEnum::Insert(1),
_ => SportsCardEnum::Plain,
};
self.status_of_pack = pack_insert_type.clone();
for i in (0..amount_of_cards_in_pack)
{
let mut card = self.get_regular_card();
card.price = card.get_price();
cards.push(card);
}
//If there is an insert, put ONE insert in
cards[3] = match pack_insert_type
{
_ if pack_insert_type != SportsCardEnum::Plain => {
let mut insert = self.get_insert(pack_insert_type);
insert.price = insert.get_price();
insert
},
_ => self.get_regular_card()
};
self.cards = cards.clone();
//regular cards gone
}
fn display(&self) -> ()
{
let mut price = 0.0;
println!("");
for card in &self.cards
{
println!("You got a {:?} card of {} worth ${:.2}!", card.sports_card_type.name_of_insert(), card.player_name, card.price);
price += card.price;
}
println!("");
println!("The total price of your pack is ${:.2}!", price.round());
println!("");
}
fn get_price(&self) -> f32
{
let mut pack_price = 0.0;
for card in &self.cards
{
pack_price += card.price;
}
pack_price
}
}
impl Default for Pack
{
fn default() -> Self {
Pack {
cards: vec![],
status_of_pack: SportsCardEnum::Plain,
begin_border: 0,
begin_insert_border: 0
}
}
}
#[derive(Debug)]
struct Box
{
packs: Vec<Pack>,
best_pack: Pack
}
impl Box {
fn fill_box(&mut self) {
}
fn new() -> Box
{
let mut packs = vec![];
for i in (0..amount_of_packs_in_box)
{
let mut pack = Pack::default();
pack.fill_pack();
packs.push(pack);
}
Box { packs , ..Default::default()}
}
fn retrieve_pack(&self,numeric_choice: i8) -> &Pack
{
let index = numeric_choice as usize;
let packs = &self.packs;
//zero-indexed
let pack = packs.get(index-1).unwrap();
pack
}
fn greatest_cards(&self) -> Pack
{
let mut largest_pack_price = 0.0;
let mut largest_pack_index: usize = 0;
let mut best_cards: Vec<(SportsCard,usize)> = vec![];
let packs = &self.packs;
for (pack_index, pack) in packs.iter().enumerate()
{
let mut current_pack_price = 0.0;
for card in &pack.cards
{
current_pack_price += card.price;
best_cards.push((card.clone(),pack_index));
}
//traverse the best cards vector
if current_pack_price > largest_pack_price
{
largest_pack_price = current_pack_price;
largest_pack_index = pack_index;
}
}
let mut best_cards = best_cards.iter().filter(|a| a.0.sports_card_type != SportsCardEnum::Plain).collect::< Vec<_> >();
best_cards.sort_by(|a,b| (b.0.price).partial_cmp(&a.0.price).unwrap_or(core::cmp::Ordering::Equal));
println!("The best pack was pack #{}\n", largest_pack_index + 1);
for best_card_tuple in best_cards
{
println!("In pack #{}, there was a {:?} card with 1:{:#} odds that was a {} insert worth ${:.2}", best_card_tuple.1 + 1, best_card_tuple.0.player_name, best_card_tuple.0.sports_card_type.odds(), best_card_tuple.0.sports_card_type.name_of_insert(), best_card_tuple.0.price);
}
(Pack{..Default::default()})
}
fn ranking_pack(&self, user_pack: &Pack) -> ()
{
let mut pack_prices_vector = vec![];
//fill vector of pack prices
for pack in &self.packs
{
let mut pack_price = 0.0;
pack_prices_vector.push(pack.get_price());
}
pack_prices_vector.sort_by(|a, b| a.partial_cmp(b).unwrap());
let mut tracking_index = 0;
let user_pack_price = user_pack.get_price();
for (i,pack_price) in pack_prices_vector.iter().enumerate()
{
if user_pack_price <= *pack_price
{
tracking_index = i;
break;
}
}
let rank = amount_of_packs_in_box - tracking_index as i8;
let rank_suffix = match rank % 10
{
1 => "st",
2 => "nd",
_ => "th"
};
let percentile = ((tracking_index as f32/24.0)*100.0).round();
//zero-index to human index
println!("Your pack was the {:#}{} best of {:#} packs. You're in {}% percentile.\n", rank,rank_suffix,pack_prices_vector.len(),percentile);
}
}
impl Default for Box {
fn default() -> Self {
Box {
packs: vec![],
best_pack: Pack::default()
}
}
}
fn main() {
clear_console::clear();
let mut choice = String::new();
while choice.trim().to_lowercase() != "q" && choice.trim().to_lowercase() != "quit" && choice.trim().to_lowercase() != "no"
{
let mut box_instance = Box::new();
println!("{}","---------------------------------");
println!("{}","| 1 | 2 | 3 | 4 |");
println!("{}","---------------------------------");
println!("{}","| 5 | 6 | 7 | 8 |");
println!("{}","---------------------------------");
println!("{}","| 9 | 10 | 11 | 12 |");
println!("{}","---------------------------------");
println!("{}","| 13 | 14 | 15 | 16 |");
println!("{}","---------------------------------");
println!("{}","| 17 | 18 | 19 | 20 |");
println!("{}","---------------------------------");
println!("{}","| 21 | 22 | 23 | 24 |");
println!("{}","---------------------------------\n");
println!("{}","You're in Jondar's Comic Books & Sports Cards!!!!! Welcome to my Store, we're happy to have you! A pack of basketcall cards will run you $4.00.\n");
println!("{}","Hope you pull a rare gem!!\n");
let mut message_to_user = format!("Pick a number between 1 & {}\n", amount_of_packs_in_box);
let mut numeric_choice = 0;
loop
{
choice.clear();
println!("{}",message_to_user);
io::stdin().read_line(&mut choice).expect("error: unable to read user choice");
numeric_choice = choice.trim().parse::<i8>().unwrap_or(-1);
//bad
if numeric_choice < 1 || numeric_choice > amount_of_packs_in_box
{
message_to_user = format!("Don't be silly. Choose a correct pack number between 1 & {}... ",amount_of_packs_in_box);
continue;
}
else
{
break;
}
}
// Box.greatest_cards();
clear_console::clear();
let pack = box_instance.retrieve_pack(numeric_choice);
println!("\nYou picked pack #{}!",choice.trim());
pack.display();
box_instance.ranking_pack(&pack);
box_instance.greatest_cards();
println!("\nDo you want to open a pack from another box of cards?");
println!("\n(Write \"No\" or \"Q\" or \"Quit\" if you want to leave)\n");
choice.clear();
io::stdin().read_line(&mut choice).expect("error: unable to read user choice");
clear_console::clear();
}
}
//allow dead code
#![allow(dead_code, warnings)]
use image;
use std::path::Path;
fn main() {
// ask user for the File Path
let mut directory = String::new();
println!("Enter the file path> ");
std::io::stdin().read_line(&mut directory).expect("Failed to read line");
// trim directory
directory = directory.trim().to_string();
// make a new directory if it doesn't exist
let new_directory = directory.to_string() + "_r";
if !Path::new(&new_directory).exists() {
std::fs::create_dir(&new_directory).unwrap();
}
// get all files in directory
let files_in_directory = get_files_in_directory(directory);
let first_file = &files_in_directory[0];
let mut index = 0;
for file_name in files_in_directory {
let file_metadata = std::fs::metadata(&file_name).unwrap();
let file_size = file_metadata.len();
let quality = get_quality(file_size);
compress_image(file_name.as_str(), quality);
// index += 1;
// if index == 10 {
// break;
// }
}
}
fn get_quality(file_size: u64) -> u8 {
return match file_size {
0..=100_000 => 80,
100_001..=200_000 => 72,
200_001..=300_000 => 71,
300_001..=400_000 => 70,
400_001..=500_000 => 60,
500_001..=600_000 => 25,
600_001..=700_000 => 22,
700_001..=800_000 => 18,
800_001.. => 13
};
}
fn get_files_in_directory(directory: String) -> Vec<String> {
let mut files = Vec::new();
for entry in std::fs::read_dir(directory).unwrap() {
let entry = entry.unwrap();
let path = entry.path();
let extension = path.extension().unwrap_or_default().to_str().unwrap();
let image_extensions = vec!["jpg", "jpeg", "png", "bmp", "gif", "jfif"];
if path.is_file() && image_extensions.contains(&extension) {
files.push(path.to_str().unwrap().to_string());
}
}
files
}
//compress image using image crate and have quality parameter
fn compress_image(image_path: &str, image_quality: u8) {
let image = image::open(image_path).unwrap();
let mut buffer = Vec::new();
let path = Path::new(&image_path);
let path_directory_parent = path.parent().unwrap().to_str().unwrap();
let file_prefix = path.file_stem().unwrap().to_str().unwrap();
let extension = "jpg";
let new_full_file_path = format!("{}_r/{}_{}.{}", path_directory_parent, file_prefix, image_quality, extension);
image.write_to(&mut buffer, image::ImageOutputFormat::Jpeg(image_quality)).unwrap();
std::fs::write(&new_full_file_path, &buffer).unwrap();
let size_in_bytes = buffer.len();
// println!("{} bytes written in {}", size_in_bytes, &new_full_file_path);
}
import OpenGL
from ctypes import *
import glm
import random
import sys
from OpenGL.GL import *
from OpenGL.GLUT import *
from OpenGL.GLU import *
from OpenGL.GL.shaders import *
import random
from helpers import *
from PIL import Image
width = 800
height = 600
factor = 0.55
texcoord_0 = [1,0]
texcoord_1 = [0,0]
texcoord_2 = [0,0]
texcoord_3 = [0,0]
texcoord_4 = [0.5,2]
vertices = [
# COORDINATES /COLORS / TexCoord
0.5, 0.0, 0.5, 0.0, 1.0, 0.0, texcoord_0[0], texcoord_0[1], # Vertex 0 Top Right Green
0.5, 0.0, -0.5, 0.0, 0.0, 1.0, texcoord_1[0], texcoord_1[1], # Vertex 1 Bottom Right Blue
-0.5, 0.0, -0.5, 0.0, 1.0, 0.0, texcoord_2[0], texcoord_2[1], # Vertex 2 Bottom Left Green
-0.5, 0.0, 0.5, 1.0, 1.0, 0.0, texcoord_3[0], texcoord_3[1], # Vertex 3 Top Left Yellow
0.0, 1.5, 0.0, 1.0, 0.0, 0.0, texcoord_4[0], texcoord_4[1], # Vertex 4 Pyramid Top Red
]
attributes_in_vertex = 8
total_vertices = int(len(vertices) / attributes_in_vertex)
# PYRAMID
indices = [
0, 1, 2, # Triangle 1
0, 3, 2, # Triangle 2
0, 1, 4, # Triangle 3
1, 2, 4, # Triangle 4
2, 3, 4, # Triangle 5
3, 0, 4, # Triangle 6
]
vertex_shader = """
#version 330 core
// Positions/Coordinates
layout (location = 0) in vec3 aPos;
// Colors
layout (location = 1) in vec3 aColor;
// Texture Coordinates
layout (location = 2) in vec2 aTex;
// Outputs the color for the Fragment Shader
out vec3 color;
// Outputs the texture coordinates to the fragment shader
out vec2 texCoord;
out vec4 position;
flat out int instanceID;
// Controls the scale of the vertices
uniform float scale;
// Inputs the matrices needed for 3D viewing with perspective
uniform mat4 model;
uniform mat4 view;
uniform mat4 proj;
float cube_root(float x)
{
return pow(x, 1.0 / 3.0);
}
float dec(float x)
{
return x - floor(x);
}
float strip_dec(float x)
{
return int(x) % 1;
}
void main()
{
// line the shapes next to each other on the x-axis based on gl_InstanceID
// move the location of the pyramid based on the gl_InstanceID
float distance = 4.0;
float cube_radius = ceil(cube_root(2500));
float squared = pow(cube_radius, 2);
// left-right horizontal
// floor(((77 % 16) / 16) * 5)
float move_z = floor(((gl_InstanceID % int(squared)) / squared) * cube_radius) * distance;
//
// height
//
// 64 / 16 = 4th level
//
float move_y = floor(gl_InstanceID / squared) * distance;
// towards me
float move_x = floor(gl_InstanceID % int(cube_radius)) * distance;
gl_Position = proj * view * vec4(aPos.x + move_x, aPos.y + move_y, aPos.z + move_z, 1.0);
position = proj * view * vec4(aPos.x + move_x, aPos.y + move_y, aPos.z + move_z, 1.0);
// Assigns the colors from the Vertex Data to "color"
color = aColor;
// Assigns the texture coordinates from the Vertex Data to "texCoord"
texCoord = aTex;
instanceID = gl_InstanceID;
}
"""
fragment_shader = """
#version 330 core
// Outputs colors in RGBA
out vec4 FragColor;
// Inputs the color from the Vertex Shader
in vec3 color;
in vec4 position;
// Inputs the texture coordinates from the Vertex Shader
in vec2 texCoord;
flat in int instanceID;
// Inputs the texture sampler
uniform float count;
uniform sampler2D imageTextureFoxNews;
uniform sampler2D imageTextureCnn;
uniform sampler2D imageTextureMsnbc;
uniform sampler2D imageTextureAbc;
void main()
{
vec4 texture_colors;
if(instanceID % 4 == 0)
{
texture_colors = texture2D(imageTextureFoxNews, texCoord);
}
else if (instanceID % 4 == 1)
{
texture_colors = texture2D(imageTextureCnn, texCoord);
}
else if (instanceID % 4 == 2)
{
texture_colors = texture2D(imageTextureMsnbc, texCoord);
}
else if (instanceID % 4 == 3)
{
texture_colors = texture2D(imageTextureAbc, texCoord);
}
//shine light from position that was passed in
vec3 diffuse_color = vec3(1.0, 1.0, 1.0);
vec3 specular_color = vec3(1.0, 1.0, 1.0);
vec3 ambient_color = vec3(1.0, 1.0, 1.0);
float shininess = .60;
float light_intensity = 0.05;
float ambient_intensity = 0.0;
float diffuse_intensity = 2.0;
float specular_intensity = 10.0;
vec3 normal = normalize(position.xyz);
float locations[2] = {200.0,2.0};
float location = 0.0;
vec3 view_position, light_position, view_direction, light_direction, reflect_direction;
float diffuse_factor, specular_factor;
vec4 diffuse_color_final, specular_color_final;
int j = 0;
//to iterate through the location array
for(j = 0; j < 3; j++)
{
location = locations[j];
light_position = vec3(-5.0, location, 0.0);
view_position = vec3(location, location, 300.0);
light_direction = normalize(light_position - position.xyz);
view_direction = normalize(view_position - position.xyz);
diffuse_factor = max(dot(light_direction, normal), 0.0);
reflect_direction = reflect(light_direction, normal);
diffuse_color_final += vec4(diffuse_color * diffuse_factor, 1.0) * light_intensity;
specular_factor = pow(max(dot(view_direction, reflect_direction), 0.0), shininess);
specular_color_final += vec4(specular_color * light_intensity * specular_intensity * specular_factor, 256.0);
}
vec4 ambient_color_final = vec4(ambient_color * light_intensity * ambient_intensity, 1.0);
vec4 final_color = diffuse_color_final + specular_color_final + ambient_color_final;
// get x & y from the texture
float texCoordX = texCoord.x;
float texCoordY = texCoord.y;
// get resolution variables from the texture
float resolutionX = texture_colors.x;
float resolutionY = texture_colors.y;
FragColor = final_color * texture_colors;
}
"""
def bind_vao_to_vbo(vbo, location_in_shader, elements_in_attribute, element_type, values_as_is_bool, stride, offset):
#
# location in shader - a number that represents the attribute that's listed ON the top of shader
# elements in attribute - how many elements are in the attribute
# element type - the type of each element
# values as-is bool - are the values as-is?
# stride - stride is the size of a single vertex!! So if you have 3 for position, 3 for color, and 2 for texture, the stride is 8
# offset - offset is the distance away from the zero element in the vertex/vertice array
#
# binds the vao to the vbo
glBindBuffer(GL_ARRAY_BUFFER, vbo)
# defines the attribute in the shader
glVertexAttribPointer(location_in_shader, elements_in_attribute, element_type, values_as_is_bool, stride, offset)
# enables the attribute in the shader
glEnableVertexAttribArray(location_in_shader)
# unbinds the vao from the vbo
glBindBuffer(GL_ARRAY_BUFFER, 0)
def set_uniform_shader_variable(name, value):
global program
location = glGetUniformLocation(program, name)
if type(value) == glm.vec3:
glUniform3fv(location, 1, glm.value_ptr(value))
elif type(value) == glm.mat4:
glUniformMatrix4fv(location, 1, GL_FALSE, glm.value_ptr(value))
elif type(value) == int:
# typically used for scale & translation & textures
glUniform1i(location, value)
elif type(value) == float:
glUniform1f(location, value)
else:
print("Unsupported type")
def file_get_contents(filename):
with open(filename) as f:
return f.read()
class Texture:
def __init__(self, filepath):
self.texture = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, self.texture)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
image = Image.open(filepath)
image_width, image_height = image.size
image_bytes = image.tobytes('raw', 'RGBA', 0, -1)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image_width, image_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_bytes)
glGenerateMipmap(GL_TEXTURE_2D)
def use(self, fragment_shader_location):
glActiveTexture(GL_TEXTURE0 + fragment_shader_location)
glBindTexture(GL_TEXTURE_2D,self.texture)
def destroy(self):
glDeleteTextures(1, (self.texture,))
# make context
glutInit()
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH)
glutInitWindowSize(width, height)
glutCreateWindow("Pyramid")
# WITHOUT THIS YOU WILL HAVE TRANSPARENT COLORS & TRANSPARENT FACES OF THE SHAPE
glEnable(GL_DEPTH_TEST);
# compile shaders
vertex_shader = compileShader(vertex_shader, GL_VERTEX_SHADER)
fragment_shader = compileShader(fragment_shader, GL_FRAGMENT_SHADER)
# create program & link shaders
program = glCreateProgram()
glAttachShader(program, vertex_shader)
glAttachShader(program, fragment_shader)
glLinkProgram(program)
# use program that consists of shaders
glUseProgram(program)
# create a vertex array object (VAO)
vao = glGenVertexArrays(1)
glBindVertexArray(vao)
# create a vertex buffer object (VBO)
id = 0
vbo = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, vbo)
# create a element buffer object (EBO)
ebo = glGenBuffers(1)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo)
# copy index data to GPU (from the EBO)
glBufferData(
GL_ELEMENT_ARRAY_BUFFER, # target
len(indices) * sizeof(c_int), # size in bytes
(c_int * len(indices))(*indices), # data to be sent to the buffer
GL_STATIC_DRAW # usage
)
# copy vertices data to the GPU (from the VBO)
glBufferData(GL_ARRAY_BUFFER, len(vertices) * sizeof(c_float), (c_float * len(vertices))(*vertices), GL_STATIC_DRAW)
# define each attribute of each Vertex Array Object (VAO) & bind it to the Vertex Buffer Object (VBO)
# these three functions pertain to ONE vertex each, which has attributes like position, color, and texture
bind_vao_to_vbo(vbo, 0, 3, GL_FLOAT, GL_FALSE, sizeof(c_float) * 8, c_void_p(0))
bind_vao_to_vbo(vbo, 1, 3, GL_FLOAT, GL_FALSE, sizeof(c_float) * 8, c_void_p(3 * sizeof(c_float)))
bind_vao_to_vbo(vbo, 2, 2, GL_FLOAT, GL_FALSE, sizeof(c_float) * 8, c_void_p(6 * sizeof(c_float)))
#unbind VAO & EBO (the VBO is already unbound)
glBindVertexArray(0)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
#
#
# TEXTURES
#
#
fox_news_texture = Texture("fox_news_square_rbga.png")
cnn_texture = Texture("cnn_rbga.png")
msnbc_texture = Texture("msnbc_rbga.png")
abc_texture = Texture("abc_rbga.png")
# define variables for render function
rotation = 0.0
rotation_speed = 0.2
model_1 = 0.0
model_2 = 1.0
model_3 = 0.0
translate_1 = -10
translate_2 = -10
translate_3 = -20
proj_radians = 45.0
proj_1 = 0.1
proj_2 = 100.0
count = 0.0
# def debug():
# model = glm.mat4(1.0);
# view = glm.mat4(1.0);
# proj = glm.mat4(1.0);
# global rotation
# rotation += 0.2
# model = glm.rotate(model, glm.radians(rotation), glm.vec3(model_1, model_2, model_3))
# view = glm.translate(view, glm.vec3(0.0, -0.5, -10.0))
# proj = glm.perspective(glm.radians(45.0), width / height, 0.1, 100.0)
# print("model: \n", model)
# print("view: \n", view)
# print("proj: \n", proj)
# debug()
def render():
model = glm.mat4(1.0);
view = glm.mat4(1.0);
proj = glm.mat4(1.0);
global rotation
global rotation_speed
global count
rotation += rotation_speed
model = glm.rotate(model, glm.radians(rotation), glm.vec3(model_1, model_2, model_3))
view = glm.translate(view, glm.vec3(translate_1, translate_2, translate_3))
proj = glm.perspective(glm.radians(proj_radians), width / height, proj_1, proj_2)
set_uniform_shader_variable("model", model)
set_uniform_shader_variable("view", view)
set_uniform_shader_variable("proj", proj)
set_uniform_shader_variable("imageTextureFoxNews",0)
set_uniform_shader_variable("imageTextureCnn",1)
set_uniform_shader_variable("imageTextureMsnbc",2)
set_uniform_shader_variable("imageTextureAbc",3)
set_uniform_shader_variable("count",count)
count += .02
# use texture
fox_news_texture.use(0)
cnn_texture.use(1)
msnbc_texture.use(2)
abc_texture.use(3)
# bind vao
glBindVertexArray(vao)
# start drawing
# glClearColor(0.5, 0.5, 0.5, 1.0)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
# glDrawArrays(GL_TRIANGLES, 0, len(vertices))
# glDrawElements(GL_TRIANGLES, len(indices), GL_UNSIGNED_INT, c_void_p(0))
glDrawElementsInstanced(GL_TRIANGLES, len(indices), GL_UNSIGNED_INT, c_void_p(0), 2500)
glutSwapBuffers()
# poll events
glutPostRedisplay()
def key_pressed(*args):
global model_1
global model_2
global model_3
global rotation_speed
global translate_1
global translate_2
global translate_3
global proj_radians
global proj_1
global proj_2
amount = 0.1
if args[0] == b'q':
model_1 += amount
elif args[0] == b'a':
model_1 -= amount
elif args[0] == b'w':
model_2 += amount
elif args[0] == b's':
model_2 -= amount
elif args[0] == b'e':
model_3 += amount
elif args[0] == b'd':
model_3 -= amount
elif args[0] == b'r':
rotation_speed += amount
elif args[0] == b'f':
rotation_speed -= amount
elif args[0] == b't':
translate_1 -= amount
elif args[0] == b'g':
translate_1 += amount
elif args[0] == b'y':
translate_2 -= amount
elif args[0] == b'h':
translate_2 += amount
elif args[0] == b'u':
translate_3 += amount
elif args[0] == b'j':
translate_3 -= amount
elif args[0] == b'i':
proj_radians += amount
elif args[0] == b'k':
proj_radians -= amount
elif args[0] == b'o':
proj_1 += amount
elif args[0] == b'l':
proj_1 -= amount
elif args[0] == b'p':
proj_2 += amount
elif args[0] == b';':
proj_2 -= amount
# define callbacks
glutDisplayFunc(render)
glutKeyboardFunc(key_pressed)
glutMainLoop()
# cleanup
glDisableVertexAttribArray(0)
fox_news_texture.cleanup()
glBindBuffer(GL_ARRAY_BUFFER, 0)
glBindVertexArray(0)
glUseProgram(0)
glDeleteProgram(program)
glDeleteBuffers(1, vbo)
glDeleteVertexArrays(1, vao)
# VPCS
resource "aws_vpc" "vpc_1" {
cidr_block = "10.1.0.0/16"
tags = {
name = "VPC 1"
}
}
resource "aws_vpc" "vpc_2" {
cidr_block = "10.2.0.0/16"
tags = {
name = "VPC 2"
}
}
# SUBNETS
resource "aws_subnet" "subnet_1" {
cidr_block = "10.1.0.0/24"
vpc_id = aws_vpc.vpc_1.id
}
resource "aws_subnet" "subnet_2" {
cidr_block = "10.2.0.0/24"
vpc_id = aws_vpc.vpc_2.id
}
# INTERNET GATEWAYS
#
# You must have an internet gateway inside of a VPC if you want to SSH into it's instance. Also make sure a network security group is in both the subnet & instance in AWS.
#
resource "aws_internet_gateway" "igw_1" {
vpc_id = aws_vpc.vpc_1.id
}
resource "aws_internet_gateway" "igw_2" {
vpc_id = aws_vpc.vpc_2.id
}
# ROUTE TABLES
#
# Appears that a Route Table in AWS goes into a VPC. Inside of it, it can be sent to certain subnets
# in it's VPC via the aws route_table_association resource
#
resource "aws_route_table" "route_table_1" {
vpc_id = aws_vpc.vpc_1.id
tags = {
name = "route_table_1"
}
}
resource "aws_route" "route_to_igw_1" {
route_table_id = aws_route_table.route_table_1.id
destination_cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.igw_1.id
}
resource "aws_route" "route_to_tgw_in_vpc_1" {
route_table_id = aws_route_table.route_table_1.id
destination_cidr_block = "10.0.0.0/8"
gateway_id = aws_ec2_transit_gateway.tgw_mark.id
depends_on = [aws_ec2_transit_gateway.tgw_mark]
}
resource "aws_route_table_association" "subnet_association_1" {
subnet_id = aws_subnet.subnet_1.id
route_table_id = aws_route_table.route_table_1.id
}
resource "aws_route_table" "route_table_2" {
vpc_id = aws_vpc.vpc_2.id
tags = {
name = "route_table_2"
}
}
resource "aws_route" "route_to_igw_2" {
route_table_id = aws_route_table.route_table_2.id
destination_cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.igw_2.id
}
resource "aws_route" "route_to_tgw_in_vpc_2" {
route_table_id = aws_route_table.route_table_2.id
destination_cidr_block = "10.0.0.0/8"
gateway_id = aws_ec2_transit_gateway.tgw_mark.id
depends_on = [aws_ec2_transit_gateway.tgw_mark]
}
resource "aws_route_table_association" "subnet_association_2" {
subnet_id = aws_subnet.subnet_2.id
route_table_id = aws_route_table.route_table_2.id
}
# NETWORK SECURITY GROUPS
#
# in AWS, a security group is connected to the VPC
#
# Define the first security group for VPC 1
resource "aws_security_group" "allow_ssh_group_vpc_1" {
name = "allow_ssh_group_vpc_1"
description = "Allow SSH Group VPC 1"
vpc_id = aws_vpc.vpc_1.id
# Define ingress rules directly within the security group
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 8
to_port = 0
protocol = "icmp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
# Define the second security group for VPC 2
resource "aws_security_group" "allow_ssh_group_vpc_2" {
name = "allow_ssh_group_vpc_2"
description = "Allow SSH Group VPC 2"
vpc_id = aws_vpc.vpc_2.id
# Define ingress rules directly within the security group
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 8
to_port = 0
protocol = "icmp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
#########################
#
# EC2 VIRTUAL MACHINES
#
#########################
#
#
# ssh -i key_pair_2023.pem ec2-user@ec2-34-236-144-211.compute-1.amazonaws.com
#
# 1) Make sure there's internet gateway
# 2) Make sure there's security groups in VPC & EC2
# 3) Make sure there's a default route to the internet gateway
#
#
resource "aws_instance" "ec2_vpc_1_subnet_1" {
ami = "ami-051f7e7f6c2f40dc1"
subnet_id = aws_subnet.subnet_1.id
instance_type = "t2.micro"
key_name = "key_pair_2023"
vpc_security_group_ids = [aws_security_group.allow_ssh_group_vpc_1.id]
associate_public_ip_address = true
}
resource "aws_instance" "ec2_vpc_2_subnet_2" {
ami = "ami-051f7e7f6c2f40dc1"
subnet_id = aws_subnet.subnet_2.id
instance_type = "t2.micro"
key_name = "key_pair_2023"
vpc_security_group_ids = [aws_security_group.allow_ssh_group_vpc_2.id]
associate_public_ip_address = true
}
output "instance_public_ip" {
value = aws_instance.ec2_vpc_1_subnet_1.public_ip
}
output "instance_public_dns" {
value = aws_instance.ec2_vpc_1_subnet_1.public_dns
}
#
# TRANSIT GATEWAY
#
#
#
resource "aws_ec2_transit_gateway" "tgw_mark" {
description = "Mark's Transit Gateway"
default_route_table_association = "enable"
default_route_table_propagation = "enable"
amazon_side_asn = 64512
tags = {
name = "tgw_mark"
}
}
#
# TRANSIT GATEWAY ATTACHMENTS
#
# Attachments to other VPCs
#
#
resource "aws_ec2_transit_gateway_vpc_attachment" "vpc_1_attachment" {
transit_gateway_id = aws_ec2_transit_gateway.tgw_mark.id
vpc_id = aws_vpc.vpc_1.id
subnet_ids = [aws_subnet.subnet_1.id]
tags = {
name = "vpc_1_attachment"
}
}
resource "aws_ec2_transit_gateway_vpc_attachment" "vpc_2_attachment" {
transit_gateway_id = aws_ec2_transit_gateway.tgw_mark.id
vpc_id = aws_vpc.vpc_2.id
subnet_ids = [aws_subnet.subnet_2.id]
tags = {
name = "vpc_2_attachment"
}
}
# RESOURCE GROUP
resource "azurerm_resource_group" "resource_group_mark_mulcahy" {
name = var.resource_group_name
location = var.location
}
# NETWORK SECURITY GROUPS
resource "azurerm_network_security_group" "security_group_mark" {
name = "security_group_mark"
location = var.location
resource_group_name = var.resource_group_name
}
resource "azurerm_network_security_rule" "allow_ssh_rule" {
name = "allow_ssh_rule"
priority = 100
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "22"
source_address_prefix = "0.0.0.0/0" # You can change this to a more specific address or range
destination_address_prefix = "*"
resource_group_name = var.resource_group_name
network_security_group_name = azurerm_network_security_group.security_group_mark.name
}
resource "azurerm_network_security_rule" "allow_ping_rule" {
name = "allow_ping_rule"
priority = 101
direction = "Inbound"
access = "Allow"
protocol = "Icmp"
source_port_range = "*"
destination_port_range = "*"
source_address_prefix = "0.0.0.0/0" # You can change this to a more specific address or range
destination_address_prefix = "*"
resource_group_name = var.resource_group_name
network_security_group_name = azurerm_network_security_group.security_group_mark.name
}
# VIRTUAL NETWORKS
resource "azurerm_virtual_network" "gateway_hub" {
name = "gateway_hub"
location = var.location
resource_group_name = var.resource_group_name
address_space = ["10.0.0.0/16"]
}
resource "azurerm_virtual_network" "vpc_1" {
name = "vpc_1"
location = var.location
resource_group_name = var.resource_group_name
address_space = ["10.1.0.0/16"]
}
resource "azurerm_virtual_network" "vpc_2" {
name = "vpc_2"
location = var.location
resource_group_name = var.resource_group_name
address_space = ["10.2.0.0/16"]
}
# SUBNETS
resource "azurerm_subnet" "subnet_hub" {
name = "subnet_hub"
resource_group_name = var.resource_group_name
virtual_network_name = azurerm_virtual_network.gateway_hub.name
address_prefixes = ["10.0.0.0/24"]
}
resource "azurerm_subnet" "subnet_1" {
name = "subnet_1"
resource_group_name = var.resource_group_name
virtual_network_name = azurerm_virtual_network.vpc_1.name
address_prefixes = ["10.1.0.0/24"]
}
resource "azurerm_subnet" "subnet_2" {
name = "subnet_2"
resource_group_name = var.resource_group_name
virtual_network_name = azurerm_virtual_network.vpc_2.name
address_prefixes = ["10.2.0.0/24"]
}
resource "azurerm_subnet" "subnet_hub_virtual_gateway" {
name = "GatewaySubnet"
resource_group_name = var.resource_group_name
virtual_network_name = azurerm_virtual_network.gateway_hub.name
address_prefixes = ["10.0.1.0/24"]
}
# ROUTE TABLES
# VPC 1 / SUBNET 1 Route Table
resource "azurerm_route_table" "route_table_1" {
name = "route_table_1"
location = var.location
resource_group_name = var.resource_group_name
}
resource "azurerm_route" "route_1" {
name = "route_1"
resource_group_name = var.resource_group_name
route_table_name = azurerm_route_table.route_table_1.name
address_prefix = "10.2.0.0/16"
next_hop_type = "VirtualNetworkGateway"
}
resource "azurerm_subnet_route_table_association" "route_subnet_association_1" {
subnet_id = azurerm_subnet.subnet_1.id
route_table_id = azurerm_route_table.route_table_1.id
}
# VPC 2 / SUBNET 2 Route Table
resource "azurerm_route_table" "route_table_2" {
name = "route_table_2"
location = var.location
resource_group_name = var.resource_group_name
}
resource "azurerm_route" "route_2" {
name = "route_2"
resource_group_name = var.resource_group_name
route_table_name = azurerm_route_table.route_table_2.name
address_prefix = "10.1.0.0/16"
next_hop_type = "VirtualNetworkGateway"
}
resource "azurerm_subnet_route_table_association" "route_subnet_association_2" {
subnet_id = azurerm_subnet.subnet_2.id
route_table_id = azurerm_route_table.route_table_2.id
}
#########################
#
# VIRTUAL MACHINES
#
#
#
# Virtual Machine has a Network Interface
# Network Interface ID has a Public IP
# Public IP chooses location of this virtual machine
#
#
#########################
#
# VIRTUAL MACHINE IN HUB
#
#########################
##### PUBLIC IP #####
resource "azurerm_public_ip" "public_ip_hub" {
name = "public_ip_hub"
location = var.location
resource_group_name = var.resource_group_name
allocation_method = "Dynamic"
}
##### NETWORK INTERFACE #####
resource "azurerm_network_interface" "network_interface_hub" {
name = "network_interface_hub"
location = var.location
resource_group_name = var.resource_group_name
ip_configuration {
name = "ip_configuration"
subnet_id = azurerm_subnet.subnet_hub.id
private_ip_address_allocation = "Dynamic"
public_ip_address_id = azurerm_public_ip.public_ip_hub.id
}
}
##### NETWORK INTERFACE TO SECURITY GROUP ASSOCIATION #####
resource "azurerm_network_interface_security_group_association" "nsg_association_hub" {
network_interface_id = azurerm_network_interface.network_interface_hub.id
network_security_group_id = azurerm_network_security_group.security_group_mark.id
}
##### SUBNET INTERFACE TO SECURITY GROUP ASSOCIATION #####
resource "azurerm_subnet_network_security_group_association" "ssh_nsg_to_vpc_hub" {
subnet_id = azurerm_subnet.subnet_hub.id
network_security_group_id = azurerm_network_security_group.security_group_mark.id
}
##### VIRTUAL MACHINE #####
#
# Virtual Machine has a Network Interface
# Network Interface ID has a Public IP
#
resource "azurerm_linux_virtual_machine" "virtual_machine_hub" {
name = "VMHub"
location = var.location
resource_group_name = var.resource_group_name
network_interface_ids = [
azurerm_network_interface.network_interface_hub.id,
]
size = "Standard_B1ls"
admin_username = var.vm_username
admin_password = var.vm_password # Password
disable_password_authentication = false # Disable SSH so Text Password can be used
source_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = "18.04-LTS"
version = "latest"
}
os_disk {
caching = "ReadWrite"
storage_account_type = "Standard_LRS"
name = "myosdisk"
}
}
#########################
#
# VIRTUAL MACHINE IN SUBNET 1
#
#
#
#########################
##### PUBLIC IP #####
resource "azurerm_public_ip" "public_ip_1" {
name = "public_ip_1"
location = var.location
resource_group_name = var.resource_group_name
allocation_method = "Dynamic"
}
##### NETWORK INTERFACE #####
resource "azurerm_network_interface" "network_interface_1" {
name = "network_interface_1"
location = var.location
resource_group_name = var.resource_group_name
ip_configuration {
name = "ip_configuration"
subnet_id = azurerm_subnet.subnet_1.id
private_ip_address_allocation = "Dynamic"
public_ip_address_id = azurerm_public_ip.public_ip_1.id
}
}
##### NETWORK INTERFACE TO SECURITY GROUP ASSOCIATION #####
resource "azurerm_network_interface_security_group_association" "nsg_association_1" {
network_interface_id = azurerm_network_interface.network_interface_1.id
network_security_group_id = azurerm_network_security_group.security_group_mark.id
}
##### SUBNET INTERFACE TO SECURITY GROUP ASSOCIATION #####
resource "azurerm_subnet_network_security_group_association" "ssh_nsg_to_vpc_1" {
subnet_id = azurerm_subnet.subnet_1.id
network_security_group_id = azurerm_network_security_group.security_group_mark.id
}
##### VIRTUAL MACHINE #####
#
# Virtual Machine has a Network Interface
# Network Interface ID has a Public IP
#
resource "azurerm_linux_virtual_machine" "virtual_machine_1" {
name = "VMSubnet1"
location = var.location
resource_group_name = var.resource_group_name
network_interface_ids = [
azurerm_network_interface.network_interface_1.id,
]
size = "Standard_B1ls"
admin_username = var.vm_username
admin_password = var.vm_password # Password
disable_password_authentication = false # Disable SSH so Text Password can be used
source_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = "18.04-LTS"
version = "latest"
}
os_disk {
caching = "ReadWrite"
storage_account_type = "Standard_LRS"
name = "myosdisk_subnet_1"
}
}
#########################
#
# VIRTUAL MACHINE IN SUBNET 2
#
#
#
#########################
##### PUBLIC IP #####
resource "azurerm_public_ip" "public_ip_2" {
name = "public_ip_2"
location = var.location
resource_group_name = var.resource_group_name
allocation_method = "Dynamic"
}
##### NETWORK INTERFACE #####
resource "azurerm_network_interface" "network_interface_2" {
name = "network_interface_2"
location = var.location
resource_group_name = var.resource_group_name
ip_configuration {
name = "ip_configuration"
subnet_id = azurerm_subnet.subnet_2.id
private_ip_address_allocation = "Dynamic"
public_ip_address_id = azurerm_public_ip.public_ip_2.id
}
}
#
# Security group assignment to network Interface
#
resource "azurerm_network_interface_security_group_association" "nsg_association_2" {
network_interface_id = azurerm_network_interface.network_interface_2.id
network_security_group_id = azurerm_network_security_group.security_group_mark.id
}
#
# Security group assignment to subnet
#
resource "azurerm_subnet_network_security_group_association" "ssh_nsg_to_vpc_2" {
subnet_id = azurerm_subnet.subnet_2.id
network_security_group_id = azurerm_network_security_group.security_group_mark.id
}
##### VIRTUAL MACHINE #####
#
# Virtual Machine has a Network Interface
# Network Interface ID has a Public IP
#
resource "azurerm_linux_virtual_machine" "virtual_machine_2" {
name = "VMSubnet2"
location = var.location
resource_group_name = var.resource_group_name
network_interface_ids = [
azurerm_network_interface.network_interface_2.id,
]
size = "Standard_B1ls"
admin_username = var.vm_username
admin_password = var.vm_password # Password
disable_password_authentication = false # Disable SSH so Text Password can be used
source_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = "18.04-LTS"
version = "latest"
}
os_disk {
caching = "ReadWrite"
storage_account_type = "Standard_LRS"
name = "myosdisk_subnet_2"
}
}
#########################
#
# VIRTUAL NETWORK GATEWAY
#
#########################
resource "azurerm_public_ip" "public_ip_hub_vnet_gateway" {
name = "public_ip_hub_vnet_gateway"
location = var.location
resource_group_name = var.resource_group_name
allocation_method = "Dynamic"
}
resource "azurerm_virtual_network_gateway" "virtual_network_gateway" {
name = "virtual_network_gateway"
location = var.location
resource_group_name = var.resource_group_name
type = "Vpn"
vpn_type = "RouteBased"
active_active = false
enable_bgp = false
sku = "VpnGw1"
generation = "Generation1"
ip_configuration {
name = "vnetGatewayConfig"
public_ip_address_id = azurerm_public_ip.public_ip_hub_vnet_gateway.id
private_ip_address_allocation = "Dynamic"
subnet_id = azurerm_subnet.subnet_hub_virtual_gateway.id
}
}
#########################
#
# VIRTUAL NETWORK PEERINGS
#
# Requires two way peering, and two way peering is a requirement for the Virtual Network Gateway to work
#
#########################
resource "azurerm_virtual_network_peering" "vpc_1_to_hub" {
name = "vpc1_to_hub"
resource_group_name = var.resource_group_name
virtual_network_name = azurerm_virtual_network.vpc_1.name
remote_virtual_network_id = azurerm_virtual_network.gateway_hub.id
allow_virtual_network_access = true
allow_forwarded_traffic = true
allow_gateway_transit = true
use_remote_gateways = true
depends_on = [azurerm_virtual_network.gateway_hub, azurerm_virtual_network.vpc_1, azurerm_virtual_network.vpc_2, azurerm_virtual_network_gateway.virtual_network_gateway]
}
resource "azurerm_virtual_network_peering" "vpc_2_to_hub" {
name = "vpc2_to_hub"
resource_group_name = var.resource_group_name
virtual_network_name = azurerm_virtual_network.vpc_2.name
remote_virtual_network_id = azurerm_virtual_network.gateway_hub.id
allow_virtual_network_access = true
allow_forwarded_traffic = true
allow_gateway_transit = true
use_remote_gateways = true
depends_on = [azurerm_virtual_network.gateway_hub, azurerm_virtual_network.vpc_1, azurerm_virtual_network.vpc_2, azurerm_virtual_network_gateway.virtual_network_gateway]
}
resource "azurerm_virtual_network_peering" "hub_to_vpc_1" {
name = "hub_to_vpc_1"
resource_group_name = var.resource_group_name
virtual_network_name = azurerm_virtual_network.gateway_hub.name
remote_virtual_network_id = azurerm_virtual_network.vpc_1.id
allow_virtual_network_access = true
allow_forwarded_traffic = true
allow_gateway_transit = true
depends_on = [azurerm_virtual_network.gateway_hub, azurerm_virtual_network.vpc_1, azurerm_virtual_network.vpc_2,azurerm_virtual_network_gateway.virtual_network_gateway]
}
resource "azurerm_virtual_network_peering" "hub_to_vpc_2" {
name = "hub_to_vpc_2"
resource_group_name = var.resource_group_name
virtual_network_name = azurerm_virtual_network.gateway_hub.name
remote_virtual_network_id = azurerm_virtual_network.vpc_2.id
allow_virtual_network_access = true
allow_forwarded_traffic = true
allow_gateway_transit = true
depends_on = [azurerm_virtual_network.gateway_hub, azurerm_virtual_network.vpc_1, azurerm_virtual_network.vpc_2, azurerm_virtual_network_gateway.virtual_network_gateway]
}
#######################
#
# LAMBDA
#
#######################
# Create an IAM role for Lambda
resource "aws_iam_role" "lambda_role" {
name = "lambda_role"
assume_role_policy = data.aws_iam_policy_document.lambda.json
}
# Create a data source for the IAM policy document for Lambda
data "aws_iam_policy_document" "lambda" {
statement {
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["lambda.amazonaws.com"]
}
}
}
data "archive_file" "lambda_hello_world_file" {
type = "zip"
output_path = "/tmp/lambda_hello_world.zip"
source {
content = <<EOF
def lambda_handler(event, context):
return {
'statusCode': 200,
'body': 'Hello, I\'m Lambda!!!'
}
EOF
filename = "main.py"
}
}
resource "aws_lambda_function" "lambda_hello_world_function" {
function_name = "lambda_hello_world_function"
handler = "main.lambda_handler"
runtime = "python3.8"
role = aws_iam_role.lambda_role.arn
filename = data.archive_file.lambda_hello_world_file.output_path
source_code_hash = data.archive_file.lambda_hello_world_file.output_base64sha256
}
#######################
#
# EC2
#
#######################
# Create an EC2 instance with a user script that returns HTML using Alpine
resource "aws_instance" "ec2_hello_world" {
ami = "ami-051f7e7f6c2f40dc1"
instance_type = "t2.micro"
subnet_id = aws_subnet.subnet_ec2.id
associate_public_ip_address = true
# Specify the user script in heredoc format
user_data = <<EOF
#!/bin/bash
sudo dnf update -y
sudo dnf list | grep httpd
sudo dnf install -y httpd.x86_64
sudo systemctl start httpd.service
sudo systemctl status httpd.service
sudo systemctl enable httpd.service
echo “Hello World from $(hostname -f)” > /var/www/html/index.html
EOF
# Associate the security group with the instance
vpc_security_group_ids = [aws_security_group.security_group_ec2_lambda.id]
tags = {
name = "ec2_hello_world"
}
}
######################
#
# VPCs
#
#
# Default VPC in AWS is the client VPC that will be associated with the service network, via vpc_lattice_service_vpc_association_ec2 resource.
# Two services of Lambda & EC2 will be associated with the service network.
# The service network is not a VPC itself!
#
#
resource "aws_default_vpc" "default_vpc" {
tags = {
Name = "Default VPC"
}
}
resource "aws_vpc" "vpc_ec2" {
cidr_block = "10.2.0.0/16"
tags = {
name = "VPC EC2"
}
}
######################
#
# SUBNETS
#
#
# The Lambda Service does not require it's own subnet like EC2 and Load Balancers for the target gruops
#
#
resource "aws_subnet" "subnet_ec2" {
cidr_block = "10.2.0.0/24"
vpc_id = aws_vpc.vpc_ec2.id
}
#########################
#
# SECURITY GROUPS
#
#########################
# Create a security group that allows HTTP and HTTPS traffic from anywhere
resource "aws_security_group" "security_group_ec2_lambda" {
name = "security_group_ec2_lambda"
ingress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
vpc_id = aws_vpc.vpc_ec2.id
}
resource "aws_security_group" "security_group_default_vpc" {
name = "security_group_service_network"
ingress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
vpc_id = aws_default_vpc.default_vpc.id
}
#########################
#
# VPC LATTICE
#
# Service Network -> Service -> Listener -> Target Group
#
# Target Group is a VPC with Containers, EC2, Kubernetes, Load Balancers
# Target Group has no VPC with Lambda
#
# A Key Purpose of AWS Lattice is to have a consistent DNS name for services of different computing styles
# And to have control security & monitoring consistently
# Listeners & Rules can have weighted bias among different rules & paths
#
# Problems I came across was Terraform not setting up the Lambda Function in the Lambda Target Group
# and the initialization script in the USER DATA not working as expected, resulting in endless troubleshooting
# with the Health Check in the EC2 Target Group, until I directly accessed the instance in the private subnet
# with a temporary internet gateway/route table entry.
#
# VPC Lattice adds in the route tables in a route table like 167.*.*.*
#
#########################
##### VPC SERVICE NETWORK #####
#
#
resource "aws_vpclattice_service_network" "vpc_lattice_service_network_mark" {
name = "vpc-lattice-service-network-mark"
auth_type = "NONE"
}
##### VPC LATTICE SERVICES #####
#
#
resource "aws_vpclattice_service" "vpc_lattice_service_lambda" {
name = "vpc-lattice-service-lambda"
auth_type = "NONE"
}
resource "aws_vpclattice_service" "vpc_lattice_service_ec2" {
name = "vpc-lattice-service-ec2"
auth_type = "NONE"
}
##### VPC LATTICE SERVICE TO SERVICE NETWORK ASSOCIATION #####
#
# Back End
#
# Connects services to service network
#
#
resource "aws_vpclattice_service_network_service_association" "vpc_lattice_service_network_association_lambda" {
service_network_identifier = aws_vpclattice_service_network.vpc_lattice_service_network_mark.id
service_identifier = aws_vpclattice_service.vpc_lattice_service_lambda.id
}
resource "aws_vpclattice_service_network_service_association" "vpc_lattice_service_network_association_ec2" {
service_network_identifier = aws_vpclattice_service_network.vpc_lattice_service_network_mark.id
service_identifier = aws_vpclattice_service.vpc_lattice_service_ec2.id
}
##### VPC LATTICE VPC TO SERVICE NETWORK ASSOCIATION (DEFAULT VPC) #####
#
# Client Side
#
# Default VPC was used for my simplicity & sanity
#
# Connects Client VPC to Service Network
# Service Network is not a VPC itself, it's an abstraction
#
resource "aws_vpclattice_service_network_vpc_association" "vpc_lattice_service_vpc_association_ec2" {
vpc_identifier = aws_default_vpc.default_vpc.id
service_network_identifier = aws_vpclattice_service_network.vpc_lattice_service_network_mark.id
security_group_ids = [aws_default_vpc.default_vpc.default_security_group_id]
}
##### VPC LATTICE LISTENER #####
#
# Attaches Listener To Service
#
#
resource "aws_vpclattice_listener" "vpc_lattice_listener_lambda" {
name = "vpc-lattice-listener-lambda"
protocol = "HTTP"
service_identifier = aws_vpclattice_service.vpc_lattice_service_lambda.id
default_action {
forward {
target_groups {
target_group_identifier = aws_vpclattice_target_group.vpc_lattice_target_group_lambda.id
weight = 100
}
}
}
}
resource "aws_vpclattice_listener" "vpc_lattice_listener_ec2" {
name = "vpc-lattice-listener-ec2"
protocol = "HTTP"
service_identifier = aws_vpclattice_service.vpc_lattice_service_ec2.id
default_action {
forward {
target_groups {
target_group_identifier = aws_vpclattice_target_group.vpc_lattice_target_group_ec2.id
weight = 100
}
}
}
}
##### VPC LATTICE TARGET GROUP & ATTACHMENT (LAMBDA) #####
#
# The attachment links the Lambda/EC2/EKS to the target group
#
resource "aws_vpclattice_target_group" "vpc_lattice_target_group_lambda" {
name = "vpc-lattice-target-group-lambda"
type = "LAMBDA"
}
resource "aws_vpclattice_target_group" "vpc_lattice_target_group_ec2" {
name = "vpc-lattice-target-group-ec2"
type = "INSTANCE"
config {
port = 80
protocol = "HTTP"
vpc_identifier = aws_vpc.vpc_ec2.id
}
}
##### VPC TARGET GROUPS
#
# VPC LATTICE TARGET GROUP ATTACHMENT (Lambda) #####
#
# The attachment links the Lambda/EC2/EKS to the target group
#
resource "aws_vpclattice_target_group_attachment" "vpc_lattice_target_group_attachment_lambda" {
target_group_identifier = aws_vpclattice_target_group.vpc_lattice_target_group_lambda.id
target {
id = aws_lambda_function.lambda_hello_world_function.arn
}
}
##### VPC LATTICE TARGET GROUP ATTACHMENT (EC2) #####
#
# The attachment links the Lambda/EC2/EKS to the target group
#
resource "aws_vpclattice_target_group_attachment" "vpc_lattice_target_group_attachment_ec2" {
target_group_identifier = aws_vpclattice_target_group.vpc_lattice_target_group_ec2.id
target {
id = aws_instance.ec2_hello_world.id
port = 80
}
}
resource "aws_default_vpc" "default_vpc" {
tags = {
Name = "Default VPC"
}
}
variable "subnet_default_1" {
description = "Subnet 1 in the default VPC"
default = "subnet-0d803ec41d0ce19a5"
}
variable "default_security_group" {
description = "Security Group Open Default"
default = "sg-06cb6cc7195fb5076"
}
////////////////////
//
// S3
//
////////////////////
# Create an S3 bucket for the website
resource "aws_s3_bucket" "mark_bucket" {
bucket = "mmulcahy222-aws-website-cicd"
}
////////////////////
//
// IAM
//
////////////////////
resource "aws_iam_role" "mark_cicd_role" {
name = "mark-cicd-role"
assume_role_policy = jsonencode({
Version = "2012-10-17",
Statement = [{
Action = "sts:AssumeRole",
Effect = "Allow",
Principal = {
Service = [
"codebuild.amazonaws.com",
"codecommit.amazonaws.com",
"codepipeline.amazonaws.com",
"codedeploy.amazonaws.com",
"ecs.amazonaws.com",
"ecs-tasks.amazonaws.com",
"ecr.amazonaws.com",
]
}
}]
})
}
resource "aws_iam_policy" "mark_cicd_policy" {
name = "mark-cicd-policy"
description = "Temporary policy for CI/CD services"
policy = jsonencode({
Version = "2012-10-17",
Statement = [
{
Action = [
"codebuild:*",
"codedeploy:*",
"codepipeline:*",
"codestar-connections:*",
"codecommit:*",
"ecs:*",
"ecr:*",
//EC2 permissions are needed so CodeBuild can work with EC2
"ec2:*",
"s3:*",
"iam:PassRole",
"cloudwatch:*",
"logs:*"
],
Effect = "Allow",
Resource = "*",
},
],
})
}
resource "aws_iam_role_policy_attachment" "attach_cicd_policy" {
policy_arn = aws_iam_policy.mark_cicd_policy.id
role = aws_iam_role.mark_cicd_role.id
}
////////////////////
//
// ECS
//
////////////////////
resource "aws_ecs_cluster" "mark_ecs_cluster" {
name = "mark-ecs-cluster"
tags = {
Name = "mark-ecs-cluster"
Terraform = "true"
Environment = "dev"
}
}
resource "aws_ecs_cluster_capacity_providers" "mark_ecs_cluster_capacity_providers" {
cluster_name = aws_ecs_cluster.mark_ecs_cluster.name
capacity_providers = ["FARGATE"]
default_capacity_provider_strategy {
capacity_provider = "FARGATE"
weight = 100
}
}
resource "aws_ecs_service" "mark_ecs_service" {
name = "mark_ecs_service"
cluster = aws_ecs_cluster.mark_ecs_cluster.name
task_definition = aws_ecs_task_definition.mark_ecs_task_definition.arn
launch_type = "FARGATE"
desired_count = 1
network_configuration {
subnets = [var.subnet_default_1]
security_groups = [var.default_security_group]
assign_public_ip = true
}
}
resource "aws_ecs_task_definition" "mark_ecs_task_definition" {
family = "mark_ecs_task_definition"
network_mode = "awsvpc"
requires_compatibilities = ["FARGATE"]
execution_role_arn = aws_iam_role.mark_cicd_role.arn
cpu = "256"
memory = "512"
container_definitions = jsonencode([
{
//
//
// NOTE: The container name here must match what's inside of buildspec.yml in the image definition
//
//
name = "mark_container_nginx"
image = "${aws_ecr_repository.mark_ecr.repository_url}:mark_nginx"
portMappings = [
{
containerPort = 80
hostPort = 80
}
]
}
])
}
////////////////////
//
// CODE BUILD (CODEBUILD -> ECR -> CODEDEPLOY -> ECS)
//
// You will need to put DOCKERFILE & BUILDSPEC.YML in the github repository
//
// Build has phrases, and build itself is a part of CodePipeline
//
////////////////////
# Create a CodeBuild source credential resource with the GitHub personal access token
resource "aws_codebuild_source_credential" "github_token" {
auth_type = "PERSONAL_ACCESS_TOKEN"
server_type = "GITHUB"
token = ""
}
# Create a CodeBuild project that uses GitHub as the source and personal access token as the authentication method
resource "aws_codebuild_project" "mark_codebuild" {
name = "mark_codebuild"
description = "mark_codebuild"
service_role = aws_iam_role.mark_cicd_role.arn
artifacts {
type = "NO_ARTIFACTS"
}
environment {
compute_type = "BUILD_GENERAL1_SMALL"
image = "aws/codebuild/amazonlinux2-x86_64-standard:5.0"
type = "LINUX_CONTAINER"
image_pull_credentials_type = "CODEBUILD"
privileged_mode = true
}
source {
type = "GITHUB"
location = "https://github.com/mmulcahy222/mark_aws_cicd"
git_clone_depth = 1
buildspec = "buildspec.yml"
}
}
////////////////////
//
// ECR
//
////////////////////
resource "aws_ecr_repository" "mark_ecr" {
name = "mark_ecr_repository"
image_tag_mutability = "MUTABLE"
image_scanning_configuration {
scan_on_push = true
}
}
output "ecr_repository_name" {
description = "Name of the ECR repository"
value = aws_ecr_repository.mark_ecr.name
}
output "ecr_repository_url" {
description = "URL of the ECR repository"
value = aws_ecr_repository.mark_ecr.repository_url
}
/*
data "aws_ecs_task" "mark_ecs_task" {
task_definition = aws_ecs_task_definition.mark_ecs_task_definition.arn
cluster = aws_ecs_cluster.mark_ecs_cluster.id
}
output "public_ip" {
value = data.aws_ecs_task.mark_ecs_task.eni_network_interface_ids[0].public_ipv4_address
}
*/
////////////////////
//
// CODEPIPELINE
//
////////////////////
resource "aws_codestarconnections_connection" "github_connection" {
name = "github-connection"
provider_type = "GitHub"
}
resource "aws_codepipeline" "mark_codepipeline" {
name = "mark_codepipeline_terraform"
role_arn = aws_iam_role.mark_cicd_role.arn
artifact_store {
location = aws_s3_bucket.mark_bucket.id
type = "S3"
}
stage {
name = "Source"
action {
name = "SourceAction"
category = "Source"
owner = "AWS"
provider = "CodeStarSourceConnection"
version = "1"
output_artifacts = ["source_output"]
configuration = {
ConnectionArn = aws_codestarconnections_connection.github_connection.arn
FullRepositoryId = "mmulcahy222/mark_aws_cicd"
BranchName = "master"
OutputArtifactFormat = "CODE_ZIP"
}
}
}
stage {
name = "Build"
action {
name = "BuildAction"
category = "Build"
owner = "AWS"
provider = "CodeBuild"
version = "1"
input_artifacts = ["source_output"]
output_artifacts = ["build_output"]
configuration = {
ProjectName = aws_codebuild_project.mark_codebuild.name
}
}
}
stage {
name = "Deploy"
action {
name = "DeployAction"
category = "Deploy"
owner = "AWS"
provider = "ECS"
version = "1"
input_artifacts = ["build_output"]
configuration = {
ClusterName = aws_ecs_cluster.mark_ecs_cluster.name
ServiceName = aws_ecs_service.mark_ecs_service.name
FileName = "imagedefinitions.json"
}
}
}
}
version: 0.2
phases:
pre_build:
commands:
- echo Logging in to Amazon ECR...
- export AWS_REGION="us-east-1"
- export AWS_ACCOUNT_ID=""
- export IMAGE_REPO_NAME="mark_ecr_repository"
- export REPOSITORY_URI="${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/${IMAGE_REPO_NAME}"
- export COMMIT_HASH="$(echo ${CODEBUILD_RESOLVED_SOURCE_VERSION} | cut -c 1-7)"
- export IMAGE_TAG="${COMMIT_HASH:-latest}"
build:
commands:
- echo Build started on `date`
- echo Building the Docker image...
- docker build -t ${REPOSITORY_URI}:${IMAGE_TAG} .
- echo Running NGINX in the Docker container...
- docker run -d -p 8080:80 ${REPOSITORY_URI}:${IMAGE_TAG}
post_build:
commands:
- echo Build completed on `date`
- echo Pushing the Docker image...
- aws ecr get-login-password | docker login --username AWS --password-stdin "${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com"
- docker push ${REPOSITORY_URI}:${IMAGE_TAG}
- echo Writing image definitions file...
- printf '[{"name":"mark_container_nginx","imageUri":"%s"}]' ${REPOSITORY_URI}:${IMAGE_TAG} > imagedefinitions.json
artifacts:
files:
- imagedefinitions.json
import json
import os
import pprint
import sys
import operator
import functools
import time
import datetime
import urllib
import urllib.parse
import urllib.request
from collections import defaultdict
from urllib.parse import unquote
from urllib.request import Request, urlopen
import re
import copy
import boto3
import random
import string
from botocore.exceptions import ClientError
origin_type = ''
def handle_exception(default_value=None):
def wrap(f):
def wrapped_f(*args,**kwargs):
try:
return f(*args,**kwargs)
except:
return default_value
return wrapped_f
return wrap
def get_current_location():
#only purpose is for portability between windows system & google functions
#if in local windows system
if os.name == 'nt':
return 'windows'
#if in amazon
elif os.environ.get("AWS_EXECUTION_ENV") is not None:
return 'amazon'
#if google cloud or other cloud like azure
else:
return 'google'
class AmazonAWS:
@handle_exception()
def get_request_json(self,request):
return request
@handle_exception()
def get_intent(self,response_json):
return response_json['request']['intent']['name']
@handle_exception({})
def get_parameter(self,request_json,key):
#called slot values here
return request_json['request']['intent']['slots'][key]['value']
@handle_exception({})
def get_parameters(self,request_json):
#format it for the inner function in a decorator
#looks like {'any': 'thriller', 'time': '00:00'}
slots = request_json['request']['intent']['slots']
parameters = {k:v.get("value") for k,v in slots.items()}
return parameters
def device_text_response(self, **kwargs):
speech_output = kwargs.get("speech_output","OK")
session_attributes = kwargs.get("session_attributes",{})
should_end_session = kwargs.get("should_end_session",0)
response = {
"sessionAttributes": session_attributes,
"response": {
"outputSpeech": {
"type": "SSML",
"ssml":"<speak>" + str(speech_output)[:7999] + "</speak>"
},
"reprompt": {
"outputSpeech": {
"type": "SSML",
"ssml": "<speak>" + str(speech_output)[:7999] + "</speak>"
}
},
},
"shouldEndSession": should_end_session
}
return response
def device_audio_response(self,**kwargs):
alphanumeric = list(string.octdigits + string.ascii_letters)
random.shuffle(alphanumeric)
token = ''.join(alphanumeric[:15])
response = {
"response": {
"outputSpeech": {
"type": "SSML",
"ssml":"<speak>" + kwargs.get("text_speech","Ok") + "</speak>"
},
"directives": [
{
"type": "AudioPlayer.Play",
"playBehavior": "REPLACE_ALL",
"audioItem": {
"stream": {
"token": token,
"url": kwargs.get("audio_url",''),
"offsetInMilliseconds": 0
}
}
}
],
"shouldEndSession": 1
}
}
return response
def return_trip_json(self,contents):
# AMAZON AWS JUST REQUIRES PAYLOAD (you're calling Lambda directly)
#
# if isinstance(contents,dict):
# contents = json.dumps(contents)
# return_dict = {
# "statusCode": 200,
# "headers": {"Content-Type": "application/json"},
# "body": contents
# }
return contents
def response_text_facade(self,contents):
return self.return_trip_json(self.device_text_response(speech_output=contents))
class GoogleCloud:
@handle_exception()
def get_request_json(self,request):
return json.loads(request['body'])
@handle_exception()
def get_intent(self,request_json):
return request_json['queryResult']['intent']['displayName']
@handle_exception({})
def get_parameter(self,request_json,key):
return request_json['queryResult']['parameters'][key]
@handle_exception({})
def get_parameters(self,request_json):
#format it for the inner function in a decorator
#looks like {'any': 'thriller', 'time': '00:00'}
return request_json['queryResult']['parameters']
def device_text_response(self,**kwargs):
response_json = {
"fulfillmentText": str(kwargs.get('speech_output','Ok')),
}
return json.dumps(response_json)
def device_audio_response(self, **kwargs):
response_json = {
#"fulfillmentText": str(speech_output),
"payload": {
"google": {
"richResponse": {
"items": [
{
"simpleResponse": {
"textToSpeech": kwargs.get("text_speech","Ok")
}
}
,
{
"mediaResponse": {
"mediaType": "AUDIO",
"mediaObjects": [
{
"contentUrl": kwargs.get("audio_url",''),
"description": "Audio Book",
"name": "Audio Book"
}
]
}
}
]
,
"suggestions": [
{
"title": "Suggestion"
}
]
}
}
}
}
return json.dumps(response_json)
def return_trip_json(self,contents):
# Amazon API Gateway JSON is here (on way back to Dialogflow) because we're using Amazon API Gateway
# Change Accordingly
#if isinstance(contents,dict):
# contents = json.dumps(contents)
return_dict = {
"statusCode": 200,
"headers": {"Content-Type": "application/json"},
"body": contents
}
return return_dict
def response_text_facade(self,contents):
return self.return_trip_json(self.device_text_response(speech_output=contents))
class HTTPBrowser():
@handle_exception()
def __getattr__(self, name):
def wrapper(*args, **kwargs):
return None
return wrapper
@handle_exception()
def get_http_header_host(self,event):
return event['headers']['Host']
def return_trip_json(self,contents):
if isinstance(contents,dict):
contents = json.dumps(contents)
return_dict = {
"statusCode": 200,
"headers": {"Content-Type": "application/json"},
"body": contents
}
return return_dict
def smart_speaker_decorator(type_of_output="text"):
'''
This is a Decorator to turn any regular code into an Alexa Skill or Google Home Skill using Amazon AWS for now
'''
def first_function(f):
def second_function(*args,**kwargs):
try:
#get_item
def get_item(iterable, index, default=None):
try:
return operator.getitem(iterable, index)
except:
return default
#initial variables (lambda or google event,context)
amazon_aws = AmazonAWS()
google_cloud = GoogleCloud()
http_browser = HTTPBrowser()
event = get_item(args,0)
context = get_item(args,1)
global origin_type
#########################
# DETERMINES THE ORIGIN
#########################
# CHECKS TO SEE IF THERE'S A SESSION->APPLICATION->APPLICATIONID, characteristic of Amazon Event Objects.
#It looks at the decorated get_request_json objects and sees if it put in an exception
amazon_aws_alexa_request_json = amazon_aws.get_request_json(event)
google_cloud_alexa_request_json = google_cloud.get_request_json(event)
if google_cloud_alexa_request_json != None:
origin_type = 'google_cloud'
origin = google_cloud
elif 'amazonaws' in str(http_browser.get_http_header_host(event)):
origin_type = 'http_browser'
origin = http_browser
elif amazon_aws_alexa_request_json != None:
origin_type = 'amazon_aws'
origin = amazon_aws
else:
origin_type = 'http_browser'
origin = http_browser
# Key Error is wrong attribute, Type Error is for doing getattr [] on a string
# Origin is for Google Cloud because most of the time we want Google Devices
#########################
# END DETERMINE ORIGIN
#########################
# Lambda Functions will read this. Not Google Cloud Functions yet. Google Cloud Functions deploy too slowly
destination = amazon_aws
# Handle the event object that passes by differently
request_json = origin.get_request_json(event)
# Get Intent
intent = origin.get_intent(request_json)
# Amazon Slot values & parameters from Google Home
parameters = origin.get_parameters(request_json)
# send intent to the function that called the decorator
if isinstance(parameters,dict):
parameters.update({"intent":intent})
else:
parameters = {}
# RUN ACTUAL CODE
result = f(event,context,*args, **parameters)
# END DEBUG
# END RUN ACTUAL CODE
#
#
# IF THIS IS A WEB REQUEST IN THE AMAZON API GATEWAY!!! (LAMBDA URL)
#
if 'http_browser' == origin_type:
return {"statusCode": 200, "headers": {"Content-Type": "application/json"}, "body": pprint.pformat(locals()) }
#
# Make Destination account for Google Cloud Functions if for some reason the processign is done there
#
# If it's audio, send it in either Google or Amazon format
# IF DOING AUDIO, SEND IT A DICT WITH AUDIO_URL & TEXT_SPEECH!!
# Destination means in this case, format JSON in Amazon AWS format
#
if 'audio' == type_of_output:
#usually for debugging, it will normally not be send that way
if isinstance(result,dict) == False:
result = {}
return origin.return_trip_json(origin.device_audio_response(**result))
#
# TEXT is the fallback for either Amazon or Google
#
elif 'text' == type_of_output:
return origin.return_trip_json(origin.device_text_response(speech_output=result))
#
# YOU should NEVER reach here. Fallback
#
return {"statusCode": 200, "headers": {"Content-Type": "application/json"}, "body": pprint.pformat(locals()) }
except:
exc_type, exc_obj, exc_tb = sys.exc_info()
exception_text = str(exc_type) + ' ' + str(exc_obj) + ' ' + str(exc_tb.tb_lineno)
#
# DEBUG
#
import traceback
traceback.print_exc()
#
# AMAZON AWS ONLY
#
#return {'statusCode': 200, 'headers': {'Content-Type': 'application/json'}, 'body': exception_text + repr(locals())}
#
# IF EXTENDING THIS FOR GOOGLE CLOUD FUNCTIONS TO SEE THIS, ACTIVATE THE FOLLOWING
#
return origin.return_trip_json(origin.device_text_response(speech_output="Nothing was found. Say something else or be more specific. " + exception_text))
#return origin.return_trip_json(origin.device_text_response(speech_output=exception_text + pprint.pformat(locals())))
return second_function
return first_function
def get_audio_url_from_web_url(url):
global origin_type
response = urllib.request.urlopen(url)
if not response:
raise Exception("Unable to open url: {0}".format(self.url))
html = response.read()
if isinstance(html, str):
json_start_pattern = "ytplayer.config = "
else:
json_start_pattern = bytes("ytplayer.config = ", "utf-8")
pattern_idx = html.find(json_start_pattern)
# In case video is unable to play
if(pattern_idx == -1):
raise Exception("Unable to find start pattern.")
start = pattern_idx + 18
html = html[start:]
def get_json_offset(html):
'''called from get_audio_from_web_url. Gets YT Config inside of page, and returns the number offset to slice'''
unmatched_brackets_num = 0
index = 1
for i, ch in enumerate(html):
if isinstance(ch, int):
ch = chr(ch)
if ch == "{":
unmatched_brackets_num += 1
elif ch == "}":
unmatched_brackets_num -= 1
if unmatched_brackets_num == 0:
break
else:
raise Exception("Unable to determine json offset.")
return index + i
#get json offset is to get the starting and last curly braces of beginnign and closing end of config
#json offset is a number value for later slicing, where it will turn into JSON by json.loads
offset = get_json_offset(html)
if not offset:
raise Exception("Unable to extract json.")
if isinstance(html, str):
json_content = json.loads(html[:offset])
else:
json_content = json.loads(html[:offset].decode("utf-8"))
player_response_string = json_content.get("args", {}).get("player_response")
player_response_json = json.loads(player_response_string)
video_audio_nodes = player_response_json.get('streamingData',{}).get('adaptiveFormats',{})
#Run through the nodes containing bitrates & video urls & formats
audio_nodes = []
for video_audio_node in video_audio_nodes:
#only get those with audio
if 'audio' in video_audio_node.get("mimeType"):
audio_url = video_audio_node.get('url',{})
quality = video_audio_node.get('quality',{})
content_length = video_audio_node.get('contentLength',{})
mime_type = video_audio_node.get("mimeType")
#append tuple
audio_nodes.append((content_length,audio_url,mime_type,quality))
#in a list of tuples, the first value in the tuple would be sorted in the list
#size of file (lowest) will be first up to the largest files
audio_nodes.sort()
#the first [-1] means largest sized
#the second [1] is the audio_url as specified in the append function above by virtue of it's placement
audio_quality = 2
if origin_type == 'google_cloud':
audio_quality = -1
#else if amazon or anything else, make it 2
return audio_nodes[audio_quality][1]
# def get_audio_url_from_web_url_april_2019(url):
# global origin_type
# req = Request(url)
# req.add_header('Connection', 'keep-alive')
# req.add_header('User-Agent', 'Mozilla/5.0 (X11; Linux i686; G518Rco3Yp0uLV40Lcc9hAzC1BOROTJADjicLjOmlr4=) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36')
# req.add_header('Accept', 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8')
# req.add_header('Accept-Charset', 'ISO-8859-1,utf-8;q=0.7,*;q=0.3')
# req.add_header('Accept-Language', 'en-US,en;q=0.8')
# html = urlopen(req).read()
# if not html:
# raise Exception("Unable to open url: {0}".format(self.url))
# if isinstance(html, str):
# json_start_pattern = "ytplayer.config = "
# else:
# json_start_pattern = bytes("ytplayer.config = ", "utf-8")
# pattern_idx = html.find(json_start_pattern)
# # In case video is unable to play
# if(pattern_idx == -1):
# raise Exception("Unable to find start pattern.")
# start = pattern_idx + 18
# html = html[start:]
# def get_json_offset(html):
# '''called from get_audio_from_web_url. Gets YT Config inside of page, and returns the number offset to slice'''
# unmatched_brackets_num = 0
# index = 1
# for i, ch in enumerate(html):
# if isinstance(ch, int):
# ch = chr(ch)
# if ch == "{":
# unmatched_brackets_num += 1
# elif ch == "}":
# unmatched_brackets_num -= 1
# if unmatched_brackets_num == 0:
# break
# else:
# raise Exception("Unable to determine json offset.")
# return index + i
# #get json offset is to get the starting and last curly braces of beginnign and closing end of config
# #json offset is a number value for later slicing, where it will turn into JSON by json.loads
# offset = get_json_offset(html)
# if not offset:
# raise Exception("Unable to extract json.")
# if isinstance(html, str):
# json_content = json.loads(html[:offset])
# else:
# json_content = json.loads(html[:offset].decode("utf-8"))
# player_response_string = json_content.get("args", {}).get("player_response")
# player_response_json = json.loads(player_response_string)
# video_audio_nodes = player_response_json.get('streamingData',{}).get('adaptiveFormats',{})
# #Run through the nodes containing bitrates & video urls & formats
# def parse_stream_map(blob):
# dct = defaultdict(list)
# # Split the comma separated videos.
# videos = blob.split(",")
# # Unquote the characters and split to parameters.
# videos = [video.split("&") for video in videos]
# # Split at the equals sign so we can break this key value pairs and
# # toss it into a dictionary.
# for video in videos:
# for kv in video:
# key, value = kv.split("=")
# dct[key].append(unquote(value))
# return dct
# encoded_stream_map = json_content.get("args", {}).get("adaptive_fmts")
# adaptive_urls = parse_stream_map(encoded_stream_map)['url']
# audio_url = adaptive_urls[-1]
# return audio_url
def get_audio_url_from_web_url_may_2021(url):
global origin_type
req = Request(url)
req.add_header('Connection', 'keep-alive')
req.add_header('User-Agent', 'Mozilla/5.0 (X11; Linux i686; G518Rco3Yp0uLV40Lcc9hAzC1BOROTJADjicLjOmlr4=) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36')
req.add_header('Accept', 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8')
req.add_header('Accept-Charset', 'ISO-8859-1,utf-8;q=0.7,*;q=0.3')
req.add_header('Accept-Language', 'en-US,en;q=0.8')
html = urlopen(req).read()
if not html:
raise Exception("Unable to open url: {0}".format(self.url))
if isinstance(html, str):
json_start_pattern = "ytplayer.config = "
else:
json_start_pattern = bytes("ytplayer.config = ", "utf-8")
pattern_idx = html.find(json_start_pattern)
# In case video is unable to play
if(pattern_idx == -1):
raise Exception("Unable to find start pattern.")
start = pattern_idx + 18
html = html[start:]
def get_json_offset(html):
'''called from get_audio_from_web_url. Gets YT Config inside of page, and returns the number offset to slice'''
unmatched_brackets_num = 0
index = 1
for i, ch in enumerate(html):
if isinstance(ch, int):
ch = chr(ch)
if ch == "{":
unmatched_brackets_num += 1
elif ch == "}":
unmatched_brackets_num -= 1
if unmatched_brackets_num == 0:
break
else:
raise Exception("Unable to determine json offset.")
return index + i
#get json offset is to get the starting and last curly braces of beginnign and closing end of config
#json offset is a number value for later slicing, where it will turn into JSON by json.loads
offset = get_json_offset(html)
if not offset:
raise Exception("Unable to extract json.")
if isinstance(html, str):
json_content = json.loads(html[:offset])
else:
json_content = json.loads(html[:offset].decode("utf-8"))
player_response_string = json_content.get("args", {}).get("player_response")
player_response_json = json.loads(player_response_string)
video_audio_nodes = player_response_json.get('streamingData',{}).get('adaptiveFormats',{})
#Run through the nodes containing bitrates & video urls & formats
def parse_stream_map(blob):
dct = defaultdict(list)
# Split the comma separated videos.
videos = blob.split(",")
# Unquote the characters and split to parameters.
videos = [video.split("&") for video in videos]
# Split at the equals sign so we can break this key value pairs and
# toss it into a dictionary.
for video in videos:
for kv in video:
key, value = kv.split("=")
dct[key].append(unquote(value))
return dct
encoded_stream_map = json_content.get("args", {}).get("adaptive_fmts")
adaptive_urls = parse_stream_map(encoded_stream_map)['url']
audio_url = adaptive_urls[-1]
return audio_url
@smart_speaker_decorator('audio')
def lambda_handler(event,context,*args,**kwargs):
#return "GOON"
# return {"audio_url":"DEBUG","text_speech":"DEBUG"}
intent = kwargs.get("intent","Unknown")
choice = kwargs.get("choice","Unknown")
original_choice = choice
developer_key = 'AIzaSyBzh1miCVEe0jOOWrmLEjc-An8NWIb7IDc';
#choice (for YouTube music)
choice = choice.lower()
choice = choice.replace('music','topic')
list_video_url = 'https://www.googleapis.com/youtube/v3/search?q='+urllib.parse.quote(str(choice))+'&part=id,snippet&maxResults=20&type=video&key=' + developer_key
#parameters intent because I dont' want to write new intents beyond the simple fallback
if intent == 'youtube.parameters':
time_choice = get_parameter(request_json,'time_range')
time_days = {"today":1,"day":1,"week":7,"month":30,"year":365}.get(time_choice,365)
date_begin_string = time.strftime('%Y-%m-%dT%H:%M:%SZ',time.gmtime(time.time() - (60 * 60 * int(time_days))))
#duration is only in youtube.parameters for now
if get_parameter(request_json,'duration') == 'long':
list_video_url = list_video_url + '&videoDuration=long'
list_video_url = list_video_url + "&publishedAfter=" + date_begin_string
#read url
results = json.loads(urllib.request.urlopen(list_video_url).read())
title_id_nodes = []
for list_node in results['items']:
video_id = list_node['id']['videoId']
title = list_node['snippet']['title']
title_id_nodes.append((video_id,title))
#FIRST [0] IS THE FIRST RESULT THAT CAME UP (change if expanding for future results)
#SECOND [0] IS THE VIDEO ID IN ACCORDANCE TO THE TUPLE ABOVE
video_id = title_id_nodes[0][0]
#FINISHED DOING ALL THE WORK TO GET VIDEO ID
#
#ALL OF THE FOLLOWING JUST TO GET THE DURATION
get_first_duration_match = lambda list,index: list[index] if index < len(list) else 0
try:
video_info_url = 'https://www.googleapis.com/youtube/v3/videos?id=' + video_id + '&part=contentDetails&type=video&key=' + developer_key
results = json.loads(urllib.request.urlopen(video_info_url).read())
duration_result = results['items'][0]['contentDetails']['duration']
hours = get_first_duration_match(re.findall('(\d*)H',duration_result),0)
minutes = get_first_duration_match(re.findall('(\d*)M',duration_result),0)
seconds = get_first_duration_match(re.findall('(\d*)S',duration_result),0)
except:
duration = "Unknown"
duration = ''
if int(hours) == 1:
duration += "{} hour ".format(hours)
elif int(hours) > 1:
duration += "{} hours ".format(hours)
if int(minutes) == 1:
duration += "{} minute ".format(minutes)
elif int(minutes) > 1:
duration += "{} minutes ".format(minutes)
if duration == '':
duration = "Unknown Time"
duration = duration.strip()
#END DURATION
video_url = 'https://www.youtube.com/watch?v=' + video_id
audio_url = get_audio_url_from_web_url_may_2021(video_url)
#START DYNAMODB
current_location = get_current_location()
if current_location == 'windows' and True:
try:
dynamodb = boto3.resource('dynamodb','us-east-1')
table = dynamodb.Table('audio_api_queries')
results = table.put_item(
Item={
'time':int(datetime.datetime.now().timestamp()),
'ip_address': '44.55.66.77',
'query': choice
}
)
except ClientError:
pass
#END DYNAMODB
return {"audio_url":audio_url,"text_speech":original_choice + ' ' + duration}
if __name__ == '__main__':
google_request = {"body":json.dumps({"responseId": "984cfbb7-35b2-4e64-bfe1-981dd6c01fce", "queryResult": {"queryText": "hybrid 2 aew theme", "parameters": {"number": 44, "choice": "awesome kong 8 million aew theme"}, "allRequiredParamsPresent": None, "fulfillmentMessages": [{"text": {"text": [""] } } ], "intent": {"name": "projects/read-agent/agent/intents/1f250750-1ebd-4f91-ad8d-c31461289c82", "displayName": "add_two"}, "intentDetectionConfidence": 1, "languageCode": "en"}, "originalDetectIntentRequest": {"payload": {} }, "session": "projects/read-agent/agent/sessions/a5e1dd4a-39aa-57fe-78c6-46dc1e7a8799"})}
amazon_request = {'version': '1.0', 'session': {'new': None, 'sessionId': 'amzn1.echo-api.session.0b502c38-74cb-4d86-aed0-668297fa7851', 'application': {'applicationId': 'amzn1.ask.skill.6bcca7d1-6fc6-406d-af8a-042948edde49'}, 'user': {'userId': 'amzn1.ask.account.AGONDUNEBOGQACH2DYQOEAHKHAIYYQZKKMBQNLEGHN6ERTMYBOQLZZXVAV54GCGDTM6GU4AEVT6SH6JIBLBLQXHYWMKSZJCA4TZMHVZ2FV36NZBHOWB5EMO3R5UETE5PVDOCYPE7AF4KQ54IGKNJDOJ7ONPHXGK2facebookMTELZMUDYE4YOJQVIWMHJULABS6CIVVJTBCTUE2ZKPTLKJY'}}, 'context': {'AudioPlayer': {'playerActivity': 'IDLE'}, 'System': {'application': {'applicationId': 'amzn1.ask.skill.6bcca7d1-6fc6-406d-af8a-042948edde49'}, 'user': {'userId': 'amzn1.ask.account.AGONDUNEBOGQACH2DYQOEAHKHAIYYQZKKMBQNLEGHN6ERTMYBOQLZZXVAV54GCGDTM6GU4AEVT6SH6JIBLBLQXHYWMKSZJCA4TZMHVZ2FV36NZBHOWB5EMO3R5UETE5PVDOCYPE7AF4KQ54IGKNJDOJ7ONPHXGK2MTELZMUDYE4YOJQVIWMHJULABS6CIVVJTBCTUE2ZKPTLKJY'}, 'device': {'deviceId': 'amzn1.ask.device.AH3UWTZBQPA4AUHMYSTKPZWUWUHU6GS7HPCK42P64W6ENUBBWJRRFY4E4WP2IN2DPJE4WPBQMNBFO2K2W6GTQPVI4QOOIWMG2I7P62YJVOIEJL5FX6KOSJ2R7L2P25XGBGMWZ2FPX54WUL3GDXE3IUUDYG72AK4LLVZH2O5LDCX2EGKFB3RAS', 'supportedInterfaces': {'AudioPlayer': {}}}, 'apiEndpoint': 'https://api.amazonalexa.com', 'apiAccessToken': 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IjEifQ.eyJhdWQiOiJodHRwczovL2FwaS5hbWF6b25hbGV4YS5jb20iLCJpc3MiOiJBbGV4YVNraWxsS2l0Iiwic3ViIjoiYW16bjEuYXNrLnNraWxsLjZiY2NhN2QxLTZmYzYtNDA2ZC1hZjhhLTA0Mjk0OGVkZGU0OSIsImV4cCI6MTU0NTg5MzM4OCwiaWF0IjoxNTQ1ODg5Nzg4LCJuYmYiOjE1NDU4ODk3ODgsInByaXZhdGVDbGFpbXMiOnsiY29uc2VudFRva2VuIjpudWxsLCJkZXZpY2VJZCI6ImFtem4xLmFzay5kZXZpY2UuQUgzVVdUWkJRUEE0QVVITVlTVEtQWldVV1VIVTZHUzdIUENLNDJQNjRXNkVOVUJCV0pSUkZZNEU0V1AySU4yRFBKRTRXUEJRTU5CRk8ySzJXNkdUUVBWSTRRT09JV01HMkk3UDYyWUpWT0lFSkw1Rlg2S09TSjJSN0wyUDI1WEdCR01XWjJGUFg1NFdVTDNHRFhFM0lVVURZRzcyQUs0TExWWkgyTzVMRENYMkVHS0ZCM1JBUyIsInVzZXJJZCI6ImFtem4xLmFzay5hY2NvdW50LkFHT05EVU5FQk9HUUFDSDJEWVFPRUFIS0hBSVlZUVpLS01CUU5MRUdITjZFUlRNWUJPUUxaWlhWQVY1NEdDR0RUTTZHVTRBRVZUNlNINkpJQkxCTFFYSFlXTUtTWkpDQTRUWk1IVloyRlYzNk5aQkhPV0I1RU1PM1I1VUVURTVQVkRPQ1lQRTdBRjRLUTU0SUdLTkpET0o3T05QSFhHSzJNVEVMWk1VRFlFNFlPSlFWSVdNSEpVTEFCUzZDSVZWSlRCQ1RVRTJaS1BUTEtKWSJ9fQ.PY4fLtwlu7c21PaMgxo8yWlsgsNLtMEnEGpNbKMUKxxTCRAwxUvJi83dtXXek6tN85njP0IYA_MiUTpsxcKuatO_pzW1fUHCNt51Uomn5UIlVUDQ1swCZppEq5c2zL05faBDJcOVr2OZFd3-QHG-m-7q2N8gIByTjgaRomy7duFhyWF0EApDT010Hj1xipePPNwZyfErQFVvyHzw508NtNDHttfOGI0taH-FTFfRPeIytzoRD0ZV_JRiYI61yyX00LTLdMzUc9EAGjXEIxDumcdpkEoLBSQVtuY5kvXPcubuu9X5I58m7tNFmJvNhTUKaP7DZFAlh_9WVzwvFwp-lg'}, 'Viewport': {'experiences': [{'arcMinuteWidth': 246, 'arcMinuteHeight': 144, 'canRotate': False, 'canResize': False}], 'shape': 'RECTANGLE', 'pixelWidth': 1024, 'pixelHeight': 600, 'dpi': 160, 'currentPixelWidth': 1024, 'currentPixelHeight': 600, 'touch': ['SINGLE']}}, 'request': {'type': 'IntentRequest', 'requestId': 'amzn1.echo-api.request.3b6a1e41-adf0-437e-8416-5779dc4b7131', 'timestamp': '2018-12-27T05:49:48Z', 'locale': 'en-US', 'intent': {'name': 'hear_audio', 'confirmationStatus': 'NONE', 'slots': {'choice': {'name': 'any', 'value': 'michael jackson thriller topic', 'confirmationStatus': 'NONE', 'source': 'USER'}}}}}
http_request = {'headers':{'Host':'jo2yo0xn52.execute-api.us-east-1.amazonaws.com'}}
print(lambda_handler(google_request,{}))
import json
import urllib.request
import re
from pprint import pprint
from collections import defaultdict
from urllib.parse import unquote
import urllib
def lambda_handler(request):
# if (event["session"]["application"]["applicationId"] != "amzn1.ask.skill.17266258-eecf-42a5-a328-b235199a76ef"):
# raise ValueError("Invalid Application ID")
yt_url = 'https://www.youtube.com/watch?v=g4NhYg_oOk0'
url = get_audio_url_from_web_url(yt_url)
def get_json_offset(html):
unmatched_brackets_num = 0
index = 1
for i, ch in enumerate(html):
if isinstance(ch, int):
ch = chr(ch)
if ch == "{":
unmatched_brackets_num += 1
elif ch == "}":
unmatched_brackets_num -= 1
if unmatched_brackets_num == 0:
break
else:
raise Exception("Unable to determine json offset.")
return index + i
def get_audio_url_from_web_url(url):
response = urllib.request.urlopen(url)
if not response:
raise Exception("Unable to open url: {0}".format(self.url))
html = response.read()
if isinstance(html, str):
restriction_pattern = "og:restrictions:age"
else:
restriction_pattern = bytes("og:restrictions:age", "utf-8")
if restriction_pattern in html:
raise AgeRestricted("Age restricted video. Unable to download "
"without being signed in.")
if isinstance(html, str):
json_start_pattern = "ytplayer.config = "
else:
json_start_pattern = bytes("ytplayer.config = ", "utf-8")
pattern_idx = html.find(json_start_pattern)
# In case video is unable to play
if(pattern_idx == -1):
raise Exception("Unable to find start pattern.")
start = pattern_idx + 18
html = html[start:]
#get json offset is to get the starting and last curly braces of beginnign and closing end of config
#json offset is a number value for later slicing, where it will turn into JSON by json.loads
offset = get_json_offset(html)
if not offset:
raise Exception("Unable to extract json.")
if isinstance(html, str):
json_content = json.loads(html[:offset])
else:
json_content = json.loads(html[:offset].decode("utf-8"))
player_response_string = json_content.get("args", {}).get("player_response")
player_response_json = json.loads(player_response_string)
video_audio_nodes = player_response_json.get('streamingData',{}).get('adaptiveFormats',{})
#Run through the nodes containing bitrates & video urls & formats
audio_nodes = []
for video_audio_node in video_audio_nodes:
#only get those with audio
if 'audio' in video_audio_node.get("mimeType"):
audio_url = video_audio_node.get('url',{})
quality = video_audio_node.get('quality',{})
content_length = video_audio_node.get('contentLength',{})
mime_type = video_audio_node.get("mimeType")
#append tuple
audio_nodes.append((content_length,audio_url,mime_type,quality))
#in a list of tuples, the first value in the tuple would be sorted in the list
#size of file (lowest) will be first up to the largest files
audio_nodes.sort()
#the first [1] means second most smallest
#the second [1] is the audio_url as specified in the append function above by virtue of it's placement
return audio_nodes[1][1]
def build_response(audio_file, should_end_session):
return {
"response": {
"directives": [
{
"type": "AudioPlayer.Play",
"playBehavior": "REPLACE_ALL",
"audioItem": {
"stream": {
"token": "12345",
"url": audio_file,
"offsetInMilliseconds": 0
}
}
}
],
"shouldEndSession": True
}
}
def get_url_by_choice(choice):
#search query list
url = 'https://www.googleapis.com/youtube/v3/search?q='+choice+'&part=id,snippet&type=video&key=AIzaSyAdRNXjk5yVbUzalf-vh0qrF5VJHvwyFP4';
results = json.loads(urllib.request.urlopen(url).read())
for list_node in results['items']:
video_id = list_node['id']['videoId']
title = list_node['snippet']['title']
print(title,video_id)
if __name__ == '__main__':
choice = "history"
# yt_url = 'https://www.youtube.com/watch?v=aRAQ-bNs32s'
# audio_url = get_audio_url_from_web_url(yt_url)
#
get_url_by_choice(choice);
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . '/home/mark/makeshift/files/saffron');
require_once ("/app/Mage.php"); //to do Magento Library functions
Mage::app('admin');
$prodauct = Mage::getModel('catalog/product')->load(9);
//$helper_data = Mage::helper('custom/data');
$collection = Mage::getModel('catalog/product')->getCollection()->
addAttributeToSelect('*')->addAttributeToFilter('brand', 'Trimark');
$category_model = Mage::getModel('catalog/category');
//foreach($collection as $h){echo $h->getName();}
////////////////////////////////////////
///FUNCTION FOR SETTING OPTIONS FOR A PRODUCT (LIKE ECO ATTRIBUTE OR COLOR)
////////////////////////////////////////
$options_array = array();
function get_magento_option_ids($attribute_name, $option_names)
{
$options_array = &$GLOBALS["options_array"]; //this array grows over time
$attribute_name = strtolower($attribute_name);
if (!isset($options_array[$attribute_name]))
//fill up array with new attribute & options (done to not redeclare model class every single row, which is memory intensive)
{
if ($attribute_name == '')
{
$attribute_name = 'attribute';
} //only done for that one category with no attribute name but had values
$attribute = Mage::getModel('catalog/resource_eav_attribute')->loadByCode('catalog_product',
strtolower($attribute_name));
$options = $attribute->getSource()->getAllOptions(true);
foreach ($options as $array)
{
$options_array[$attribute_name][strtolower(trim($array[label]))] = $array[value];
}
}
///GET VALUES FROM ARRAY ABOVE
foreach ($option_names as $option_name)
{
$values[] = $options_array[$attribute_name][strtolower(fix_name($attribute_name, $option_name))];
}
$string = implode(',', array_values($values));
return $string;
}
function fix_name($attribute_name, $option_name)
{
if ($attribute_name == 'eco_attribute')
{
if (substr_count($option_name, 'nottested') > 0)
{
return 'Not Tested On Animals';
}
if (substr_count($option_name, 'usa') > 0)
{
return 'Made In Usa';
}
if (substr_count($option_name, 'organic') > 0)
{
return 'Organic';
}
if (substr_count($option_name, 'sustainable') > 0)
{
return 'Sustainable';
}
if (substr_count($option_name, 'fairly') > 0)
{
return 'Fairly Traded';
}
if (substr_count($option_name, 'natural') > 0)
{
return 'Natural';
}
if (substr_count($option_name, 'handmade') > 0)
{
return 'Handmade';
}
}
if (substr_count($option_name, 'Caf�') > 0)
{
return "Caf";
}
$option_name = str_replace("�", "e", $option_name);
return $option_name;
}
//////////////////////////////////
/////////////////////
///CONNECT TO DATABASE AND MAKE QUERY
//////////////////////
$c = mysql_connect('localhost', 'root', '*');
mysql_select_db('puck', $c);
$sql = "SELECT * FROM item";
$result = mysql_query($sql);
//////////////////////////
//GET PRICES
//////////////////////////
echo "Making Array For Prices....\n";
$price_result = mysql_query("SELECT itemcode, price FROM keycodeitemprice k");
$price_array = array();
while ($price_row = mysql_fetch_row($price_result))
{
$price_array[$price_row[0]] = $price_row[1];
}
////////////////////////////
//GET CATEGORIES
////////////////////////////
echo "Making Array For Categories....\n";
$category_collection = Mage::getModel('catalog/category')->getCollection()->
addAttributeToSelect('omx_category_id');
$category_omx_id_array = array();
foreach ($category_collection as $category)
{
$category_omx_id_array[strval($category->getomx_category_id())] = $category->
getId();
}
$category_result = mysql_query("SELECT itemcode, catid FROM itemcategory");
$category_array = array();
while ($category_row = mysql_fetch_row($category_result))
{
$magento_category_id = $category_omx_id_array[$category_row[1]];
if ($magento_category_id != null)
{
$category_array[$category_row[0]] .= $category_omx_id_array[$category_row[1]] .
',';
}
}
////////////////////////////////////
//GET CONFIGURABLE ATTRIBUTES
////////////////////////////////////
echo "Making Array For Attributes.....\n";
$product_entity_id = Mage::getModel('eav/config')->getEntityType('catalog_product')->
getEntityTypeId();
$attributes_with_options = Mage::getResourceModel('eav/entity_attribute_collection')->
setEntityTypeFilter($product_entity_id);
$attribute_array = array();
foreach ($attributes_with_options as $attribute_with_options)
{
$attribute_array[$attribute_with_options->getName()] = $attribute_with_options->
getId();
}
/////////////////////////////////////////////
//ATTRIBUTE SET ID's
////////////////////////////////////////
$attribute_set_collection = Mage::getResourceModel('eav/entity_attribute_set_collection');
foreach ($attribute_set_collection as $attribute_set)
{
$attribute_set_array[$attribute_set->getAttributeSetName()] = $attribute_set->
getId();
}
var_export($attribute_set_array);
////////////////////////////////////
//GET ATTRIBUTES FROM ITEM ATTRIBUTES BACKUP TABLE (brand, search, materialandfabric, etc)
////////////////////////////////////
echo "Making Array from Item Attribute backup table...\n";
$item_attribute_sql =
"SELECT ItemCode, AttributeValue8 as Brand, AttributeValue7 as SearchTerm, AttributeValue16 as FulfillmentLatency,
AttributeValue18 as SmallImageUrl, AttributeValue19 as MainImageUrl, AttributeValue20 as Alternate1ImageUrl,
AttributeValue21 as Alternate2ImageUrl, AttributeValue22 as Alternate3ImageUrl, AttributeValue23 as Alternate4ImageUrl,
AttributeValue24 as Alternate5ImageUrl, AttributeValue25 as Alternate6ImageUrl,
AttributeValue42 as MaterialAndFabric, AttributeValue48 as SwatchImageUrl
FROM itemattribute";
$item_attribute_result = mysql_query($item_attribute_sql);
$item_attribute_array = array();
while ($item_attribute_row = mysql_fetch_assoc($item_attribute_result))
{
$item_attribute_array[$item_attribute_row['ItemCode']] = $item_attribute_row;
}
////////////
///SKIPPING OVER ITEMS THAT ARE ALREADY IN THE SCARVES STORE
////////////
$existing_item_codes = Mage::getModel('catalog/product')->getCollection()->
getColumnValues('sku');
$app = Mage::app();
while ($row = mysql_fetch_assoc($result))
{
//if product already exists in magento store, skip and move on to next product
if(in_array($row['ItemCode'], $existing_item_codes))
{
continue;
}
//timer
$start = time();
//variables
$item_code = $row['ItemCode'];
$type_id = ($row['HasChildren'] == 0) ? 'simple' : 'configurable';
$surcharge = $row['SizeSurcharge'] + $row['ColorSurcharge'] + $row['StyleSurcharge'];
$status = ($row['ProductStatus'] == 1) ? 1 : 2;
$visibility = ($row['HasChildren'] == 0) ? 1 : 4;
$visibility = (($row['HasChildren'] == 0)&&(empty($row['ParentItemCode']))) ? 4 : $visibility;
//fill values of product
$product = Mage::getModel('catalog/product');
$product->setWebsiteIds(array(1));
$product->setSku($item_code);
$product->setPrice($price_array[$item_code] + $surcharge);
$product->setAttributeSetId(4);
$product->setTypeId($type_id);
$product->setName($row['ProductName']);
$product->setDescription(strip_tags($row['InfoTextHTML']));
$product->setShortDescription('Nimli');
$product->setStatus($status);
$product->setMetaKeyword(str_replace("|", ",", $item_attribute_array[$item_code]['SearchTerm']));
$product->setVisibility($visibility);
$product->setWeight($row['Weight']);
$product->setCreatedAt($row['LaunchDate']);
$product->setTaxClassId('2'); //2 is taxable goods
$product->setOptionsContainer('container1');
$product->setfulfillmentlatency($item_attribute_array[$item_code]['FulfillmentLatency']);
$product->setmaterialandfabric(str_replace("|", ",", $item_attribute_array[$item_code]['MaterialAndFabric']));
$product->setStockData(array('is_in_stock' => 1, 'qty' => 99999));
$product->setbrand($item_attribute_array[$item_code]['Brand']);
///eco attributes
if(!empty($row['InfoText']))
{
$string = trim(str_replace(array('.gif', '|More Colors', '|More Colors,','|More Options','|More Scents','|More Sizes'), '', $row['InfoText']));
$explode_string = explode(',', $string);
$product->seteco_attribute(trim(get_magento_option_ids('eco_attribute', $explode_string), ','));
}
//set categories
$category_ids = $category_array[$item_code];
if(empty($category_ids) == false)
{
$product->setCategoryIds($category_ids);
}
//set configurable attributes for configurable products
if ($type_id == 'configurable')
{
$position_count = 0;
$configurable_attribute_array = array($row['SizeLabel'], $row['ColorLabel'], $row['StyleLabel']);
$configurable_attribute_array = array_filter($configurable_attribute_array, 'strlen');
foreach($configurable_attribute_array as $key => $value)
{
$configurable_attribute_array[$key] = ($value == 'Color') ? 'color_item' : strtolower(str_replace(array('|', '2'), '', $value));
}
$configurable_attribute_data = array();
$position = 0;
foreach($configurable_attribute_array as $value)
{
$configurable_attribute_data[] = array('label' => $value, 'use_default' => '0',
'position' => $position++, 'attribute_id' => $attribute_array[$value], 'attribute_code' =>
$value, 'frontend_label' => $value, 'store_label' => $value);
}
$product->setCanSaveConfigurableAttributes(true);
$product->setConfigurableAttributesData($configurable_attribute_data);
}
//give configurable attributes values, for item variations
if(!empty($row['SizeLabel']))
{
$attribute_one = strtolower($row['SizeLabel']);
$attribute_one = ($attribute_one == 'color') ? 'color_item' : $attribute_one;
$attribute_one = str_replace(array('|', '2'), '', $attribute_one);
$value_one = $row['SizeDescription'];
$magento_product_data[$attribute_one] = get_magento_option_ids($attribute_one, array($value_one));
}
if(!empty($row['ColorLabel']))
{
$attribute_two = strtolower($row['ColorLabel']);
$attribute_two = ($attribute_two == 'color') ? 'color_item' : $attribute_two;
$attribute_two = str_replace(array('|', '2'), '', $attribute_two);
$value_two = $row['ColorDescription'];
$magento_product_data[$attribute_two] = get_magento_option_ids($attribute_two, array($value_two));
}
if(!empty($row['StyleLabel']))
{
$attribute_three = strtolower($row['StyleLabel']);
$attribute_three = ($attribute_three == 'color') ? 'color_item' : $attribute_three;
$attribute_three = str_replace(array('|', '2'), '', $attribute_three);
$value_three = $row['StyleDescription'];
$magento_product_data[$attribute_three] = get_magento_option_ids($attribute_three, array($value_three));
}
$product->addData($magento_product_data);
//import images
/*
$images_array = array();
$images_array[] = (($item_attribute_array[$item_code]['SwatchImageUrl']) != '') ? array('level' => 'thumbnail', 'url' => $item_attribute_array[$item_code]['SwatchImageUrl'], 'exclude' => true) : '';
$images_array[] = (($item_attribute_array[$item_code]['MainImageUrl']) != '') ? array('level' => 'image', 'url' => $item_attribute_array[$item_code]['MainImageUrl'], 'exclude' => true) : '';
$images_array = array_filter($images_array, 'is_array');
foreach($images_array as $image_data)
{
//$product->addImageToMediaGallery($image_data['url'], array($image_data['level']), false, $image_data['exclude']); //last parameter is exclude, which should be true
}
*/
//save product
$count++;
try
{
$product->save();
$time = time() - $start;
echo ($count) . ': ' . $item_code . " (" . $row['ProductName'] . ") is imported. (" . $time . " seconds)\n";
}
catch(Exception $e)
{
echo $e->faultstring . "\n";
fwrite($log, "Excel Row: $item_code This row was not inserted in Magento because of an error\n");
}
//testing
//if ($count == 1)
//{
// break;
//}
//reset for next iteration
unset($configurable_attributes);
unset($magento_product_data);
unset($images_array);
//clear product cache, so importing can go faster
if ($a % 20 == 0)
{
$app->getCache()->clean();
gc_collect_cycles();
}
}
?>
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . '/home/mark/makeshift/files/saffron');
require_once ("/app/Mage.php"); //to do Magento Library functions
Mage::app('admin');
//connect and choose database
$c = mysql_connect('localhost', 'root', '');
mysql_select_db('puck', $c);
function get_all_attributes()
{
$attributes = array();
$sql_array[] = "SELECT sizelabel FROM item GROUP BY sizelabel";
$sql_array[] = "SELECT colorlabel FROM item GROUP BY colorlabel";
$sql_array[] = "SELECT stylelabel FROM item GROUP BY stylelabel";
foreach ($sql_array as $sql)
{
$result = mysql_query($sql);
while ($row = mysql_fetch_row($result))
{
$row[0] = ucwords($row[0]);
if (!in_array($row[0], $attributes))
{
array_push($attributes, $row[0]);
}
}
}
sort($attributes);
unset($attributes[array_search('', $options)]);
return $attributes;
}
function get_all_options($configurable_attribute)
{
$options = array();
$sql_array[] = "SELECT sizedescription FROM item WHERE sizelabel = '$configurable_attribute' GROUP BY sizedescription";
$sql_array[] = "SELECT colordescription FROM item WHERE colorlabel = '$configurable_attribute' GROUP BY colordescription";
$sql_array[] = "SELECT styledescription FROM item WHERE stylelabel = '$configurable_attribute' GROUP BY styledescription";
foreach ($sql_array as $sql)
{
$result = mysql_query($sql);
while ($row = mysql_fetch_row($result))
{
$row[0] = ucwords($row[0]);
$row[0] = str_replace(array('|2', '|'), "", $row[0]);
if (!in_array($row[0], $options))
{
array_push($options, $row[0]);
}
}
}
sort($options);
unset($options[array_search('', $options)]);
return $options;
}
function get_attributes_with_options()
{
$attributes_with_options = array();
$all_attributes = get_all_attributes();
foreach ($all_attributes as $attribute)
{
$clean_attribute = str_replace(array('|2', '|'), "", $attribute);
if($clean_attribute == ''){$clean_attribute = 'attribute';}
if(ucwords($clean_attribute) == 'Color'){$clean_attribute = 'color_item'; }
$attributes_with_options[$clean_attribute] = (substr_count($attribute, "|") >= 1) ? array_merge($attributes_with_options[$clean_attribute], get_all_options($attribute)) : get_all_options($attribute);
echo "$attribute\n";
$attributes_with_options[$clean_attribute] = array_unique($attributes_with_options[$clean_attribute]);
sort($attributes_with_options[$clean_attribute]);
}
return $attributes_with_options;
}
function add_configurable_attribute($name)
{
$attribute = Mage::getModel('catalog/resource_eav_attribute');
$attribute->addData(array('entity_type_id' => Mage::getModel('eav/entity')->
setType('catalog_product')->getTypeId(), 'attribute_code' => strtolower($name),
'attribute_model' => null, 'backend_model' => null, 'backend_type' => 'int',
'backend_table' => null, 'frontend_model' => null, 'frontend_input' => 'select',
'frontend_label' => ucwords($name), 'frontend_class' => null, 'source_model' =>
'eav/entity_attribute_source_table', 'is_required' => '0', 'is_user_defined' =>
'1', 'default_value' => '', 'is_unique' => '0', 'note' => '',
'frontend_input_renderer' => null, 'is_global' => '1', 'is_visible' => '1',
'is_searchable' => '0', 'is_filterable' => '0', 'is_comparable' => '0',
'is_visible_on_front' => '0', 'is_html_allowed_on_front' => '1',
'is_used_for_price_rules' => '0', 'is_filterable_in_search' => '0',
'used_in_product_listing' => '0', 'used_for_sort_by' => '0', 'is_configurable' =>
'1', 'apply_to' => '', 'is_visible_in_advanced_search' => '0',
'is_wysiwyg_enabled' => '0', 'is_used_for_promo_rules' => '0'));
$attribute->setIsUserDefined(1);
try
{
$attribute->save();
echo "$name is now a Magento Attribute";
}
catch (exception $e)
{
echo '<p>Sorry, error occured while trying to save the attribute. Error: ' . $e->
getMessage() . '</p>' . "\n";
}
}
function add_options_to_attribute($name, $options) //options is an array of values
{
$count = 1;
$attribute = Mage::getResourceModel('eav/entity_attribute_collection')->
setCodeFilter($name)->getFirstItem();
$optionArr = array('value' => array(), 'order' => array(), 'delete' => array());
foreach ($options as $key => $value)
{
$optionArr['value']['option_' . $key] = array($value, $value);
$optionArr['order']['option_' . $key] = $count++;
}
var_export($optionArr);
$attribute->setOption($optionArr);
$attribute->save();
}
function add_attributes_with_options_to_magento()
{
$attributes_with_options = get_attributes_with_options();
foreach($attributes_with_options as $key => $value)
{
add_configurable_attribute($key);
add_options_to_attribute($key, $value);
}
}
add_attributes_with_options_to_magento();
?>
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . 'C:/MagentoProject' .
PATH_SEPARATOR . 'C:/xampp/htdocs/adminfiles' . PATH_SEPARATOR .
'C:/xampp/htdocs/chunk/');
require_once ("/app/Mage.php"); //to do Magento Library functions
Mage::app('admin');
$c = mysql_connect('localhost', 'root', '');
mysql_select_db('puck', $c);
//////////////////////////////////
//DELETE PRODUCT IMAGES
//////////////////////////////////
$media_api = Mage::getModel("catalog/product_attribute_media_api");
function delete_product_images($product)
{
$attributes = $product->getTypeInstance ()->getSetAttributes ();
if (isset ( $attributes ['media_gallery'] )) {
$gallery = $attributes ['media_gallery'];
//Get the images
$galleryData = $product->getMediaGallery ();
foreach ( $galleryData ['images'] as $image ) {
//if image exists
if (
$gallery->getBackend ()->getImage ( $product, $image ['file'] ))
{
$gallery->getBackend ()->removeImage ( $product, $image ['file'] );
}
}
$product->save ();
}
echo $product->getSku() . " has it's images deleted\n";
}
foreach (Mage::getModel('catalog/product')->getCollection()->
addAttributeToSelect('*')->addAttributeToFilter('brand', 'azuri') as $product)
{
$sku = $product->getSku();
delete_product_images($product);
$suffix_array = array('main', 'swatch', 'alt2', 'alt3', 'alt4', 'alt5', 'alt6');
foreach ($suffix_array as $suffix)
{
$filename = dirname(__file__) . '/azuri/' . $sku . "_{$suffix}.jpg";
if (filesize($filename) != 0)
{
switch ($suffix) {
case 'main':
$product->addImageToMediaGallery($filename, 'image', false, true);
break;
case 'swatch':
$product->addImageToMediaGallery($filename, 'thumbnail', false, true);
break;
case 'alt2':
$product->addImageToMediaGallery($filename, 'image', false, false);
break;
case 'alt3':
$product->addImageToMediaGallery($filename, 'image', false, false);
break;
case 'alt4':
$product->addImageToMediaGallery($filename, 'image', false, false);
break;
case 'alt5':
$product->addImageToMediaGallery($filename, 'image', false, false);
break;
case 'alt6':
$product->addImageToMediaGallery($filename, 'image', false, false);
break;
}
}
}
$product->save();
echo "$sku now has images\n";
}
?>
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . 'C:/MagentoProject' .
PATH_SEPARATOR . 'C:/xampp/htdocs/adminfiles' . PATH_SEPARATOR .
'C:/xampp/htdocs/chunk/');
require_once ("/app/Mage.php"); //to do Magento Library functions
Mage::app('admin');
$c = mysql_connect('localhost', 'root', '');
mysql_select_db('puck', $c);
////////////////////////////////////
//GET ALL IMAGE LINKS
////////////////////////////////////
$product_sheet_sql = "SELECT id1, brand FROM brands_csv";
$product_sheet_result = mysql_query($product_sheet_sql);
while ($row = mysql_fetch_assoc($product_sheet_result))
{
$product_sheet_array[$row['id1']] = $row['brand'];
}
////////////////////////////////////
//GET ALL ITEMS IN SKU
////////////////////////////////////
$sql = "SELECT ItemCode, ParentItemCode FROM item";
$result = mysql_query($sql);
while ($row = mysql_fetch_assoc($result))
{
$sku_array[] = $row['ItemCode'];
$parent_array[$row['ItemCode']] = $product_sheet_array[$row['ItemCode']];
if(empty($parent_array[$row['ItemCode']])){$parent_array[$row['ItemCode']] = $product_sheet_array[$row['ItemCode']];}
}
$parent_array = array_filter($parent_array, 'strlen');
//////////////////////////////////
//DELETE PRODUCT IMAGES
//////////////////////////////////
$media_api = Mage::getModel("catalog/product_attribute_media_api");
function delete_product_images($product)
{
$attributes = $product->getTypeInstance ()->getSetAttributes ();
if (isset ( $attributes ['media_gallery'] )) {
$gallery = $attributes ['media_gallery'];
//Get the images
$galleryData = $product->getMediaGallery ();
foreach ( $galleryData ['images'] as $image ) {
//if image exists
if (
$gallery->getBackend ()->getImage ( $product, $image ['file'] ))
{
$gallery->getBackend ()->removeImage ( $product, $image ['file'] );
}
}
$product->save ();
}
echo $product->getSku() . " has it's images deleted\n";
}
////////////////////////////////
//LOOP THROUGH PRODUCTS (DELETE AND ADD ACCORDINGLY)
/////////////////////////////////
////////////////////////////////
//LOOP THROUGH PRODUCTS (DELETE AND ADD ACCORDINGLY)
/////////////////////////////////
/*
foreach(Mage::getModel('catalog/product')->getCollection() as $product)
{
$time = time();
$sku = $product->getSku();
$brand = $parent_array[$sku];
$product->setBrand($brand);
//$product->save();
$seconds = time() - $time;
echo "$sku has been given a brand $brand ($seconds seconds)\n\n";
Mage::app()->getCache()->clean();
unset($product);
}
*/
fpve($parent_array);
?>
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . 'C:/MagentoProject' .
PATH_SEPARATOR . '/home/mark/makeshift/files/saffron/adminfiles' . PATH_SEPARATOR .
'/home/mark/makeshift/files/saffron/' . PATH_SEPARATOR . '/chroot/home/pashmina/pashminamall.com/html');
require_once ("/app/Mage.php"); //to do Magento Library functions
Mage::app('admin');
//instantiate category model
$category_model = Mage::getModel('catalog/category');
//connect and choose database
$c = mysql_connect('localhost', 'root', '');
mysql_select_db('puck', $c);
//get result
$sql = "SELECT cac1.*, cac2.category as parentcategoryname
FROM companyitemcategory as cac1
LEFT JOIN companyitemcategory as cac2 ON cac1.parentcatid = cac2.catid
WHERE cac1.parentcatid NOT IN (700, 739, 886, 889, 890, 892, 893, 891, 895, 894, 896, 897, 898, 899, 1254, 1712, 1781, 2258, 2268, 2259, 2280)
AND cac1.category NOT LIKE '%>>'
ORDER BY cac1.catid";
$result = mysql_query($sql);
//iterate through table
$count = 0;
$path = 4;
while($row = mysql_fetch_assoc($result))
{
$count++;
//SET VARIABLES FROM MYSQL ROW
$category_name = $row['Category'];
$parent_category_name = $row['parentcategoryname'];
$omx_category_id = $row['CatID'];
$omx_parent_category_id = $row['ParentCatID'];
//GET CATEGORY PATH
if ($parent_category_name != null)
{
$parent_category = $category_model->loadByAttribute('omx_category_id', $omx_parent_category_id);
if($parent_category)
{
try
{
$path = $category_model->loadByAttribute('omx_category_id', $omx_parent_category_id)->getPath();
}
catch(Exception $e){}
}
}
else
{
$path = "1/2";
}
///ADD CATEGORY
$category = Mage::getModel('catalog/category');
$category->setStoreId(0);
$general['name'] = $category_name;
$general['path'] = $path;
$general['description'] = $category_name;
$general['meta_title'] = $category_name; //Page title
$general['meta_keywords'] = $category_name;
$general['meta_description'] = $category_name;
$general['landing_page'] = ""; //has to be created in advance, here comes id
$general['display_mode'] = "PRODUCTS_AND_PAGE"; //static block and the products are shown on the page
$general['is_active'] = 1;
$general['is_anchor'] = 0;
$general['omx_category_id'] = $omx_category_id; //new attribute that Mark created, to resolve issues with
//categories of the same name
$general['url_key'] = $category_name;//url to be used for this category's page by magento.
$category->addData($general);
try {
$category->save();
echo "Success! $category_name is now a category. Id: ".$category->getId()."\n";
}
catch (Exception $e){
echo $e->getMessage();
}
//END ADD CATEGORY
//var_export($row);
}
?>
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . 'C:/MagentoProject' .
PATH_SEPARATOR . 'C:/xampp/htdocs/adminfiles' . PATH_SEPARATOR .
'C:/xampp/htdocs/chunk/');
require_once ("/app/Mage.php"); //to do Magento Library functions
Mage::app('admin');
$c = mysql_connect('localhost', 'root', '');
mysql_select_db('puck', $c);
////////////////////////////////////
//GET ALL IMAGE LINKS
////////////////////////////////////
$product_sheet_sql = "SELECT id1, image_link FROM products LIMIT 100, 1700";
$product_sheet_result = mysql_query($product_sheet_sql);
while ($row = mysql_fetch_assoc($product_sheet_result))
{
$product_sheet_array[$row['id1']] = $row['id1'];
}
////////////////////////////////////
//GET ALL ITEMS IN SKU
////////////////////////////////////
$sql = "SELECT ItemCode, ParentItemCode FROM item";
$result = mysql_query($sql);
while ($row = mysql_fetch_assoc($result))
{
$sku_array[] = $row['ItemCode'];
$parent_image_array[$row['ItemCode']] = $product_sheet_array[$row['ItemCode']];
if(empty($parent_image_array[$row['ItemCode']])){$parent_image_array[$row['ItemCode']] = $product_sheet_array[$row['ParentItemCode']];}
}
$parent_image_array = array_keys(array_filter($parent_image_array, "strlen"));
//////////////////////////////////
//DELETE PRODUCT IMAGES
//////////////////////////////////
$media_api = Mage::getModel("catalog/product_attribute_media_api");
function delete_product_images($product)
{
$attributes = $product->getTypeInstance ()->getSetAttributes ();
if (isset ( $attributes ['media_gallery'] )) {
$gallery = $attributes ['media_gallery'];
//Get the images
$galleryData = $product->getMediaGallery ();
foreach ( $galleryData ['images'] as $image ) {
//if image exists
if (
$gallery->getBackend ()->getImage ( $product, $image ['file'] ))
{
$gallery->getBackend ()->removeImage ( $product, $image ['file'] );
}
}
$product->save ();
}
echo $product->getSku() . " has it's images deleted\n";
}
////////////////////////////////
//LOOP THROUGH PRODUCTS (DELETE AND ADD ACCORDINGLY)
/////////////////////////////////
foreach($parent_image_array as $sku)
{
$product = Mage::getModel('catalog/product');
$filename = dirname(__FILE__) . '/images/' . $sku . '.jpg';
if((filesize($filename) != 0)&&(empty($sku) == false))
{
$time = time();
$product->load($product->getIdBySku(trim($sku)));
if($product->getId())
{
delete_product_images($product);
$product->addImageToMediaGallery($filename, array('image', 'small_image'), false, true);
$product->save();
$seconds = time() - $time;
echo "$sku has been given an image ($seconds seconds)\n\n";
Mage::app()->getCache()->clean();
}
else
{
echo "$sku did not get an image\n";
}
unset($product);
}
}
?>
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . 'C:/MagentoProject' .
PATH_SEPARATOR . 'C:/xampp/htdocs/adminfiles' . PATH_SEPARATOR .
'C:/xampp/htdocs/chunk/');
function cm($obj)
{
var_export(get_class_methods($obj));
}
function ve($obj)
{
var_export($obj);
}
function e($obj)
{
echo ($obj);
}
function gc($obj)
{
echo get_class($obj);
}
function fpve($obj)
{
file_put_contents("C:/test/fp.txt", var_export($obj, 1));
}
function fpe($obj)
{
file_put_contents("C:/test/fp.txt", $obj);
}
require_once ("/app/Mage.php"); //to do Magento Library functions
Mage::app('admin');
$product = Mage::getModel('catalog/product')->load(13);
$collection = Mage::getModel('catalog/product')->getCollection();
$category = Mage::getModel('catalog/category')->load(5);
//foreach($collection as $h){echo $h->getName() . "\n";}
$c = mysql_connect('localhost', 'root', '');
mysql_select_db('puck', $c);
$result = mysql_query('');
////////////////////////////////////////
///FUNCTION FOR SETTING OPTIONS FOR A PRODUCT (LIKE ECO ATTRIBUTE OR COLOR)
////////////////////////////////////////
$options_array = array();
function get_magento_option_ids($attribute_name, $option_names)
{
$options_array = &$GLOBALS["options_array"]; //this array grows over time
$attribute_name = strtolower($attribute_name);
if (!isset($options_array[$attribute_name]))
//fill up array with new attribute & options (done to not redeclare model class every single row, which is memory intensive)
{
if ($attribute_name == '')
{
$attribute_name = 'attribute';
} //only done for that one category with no attribute name but had values
$attribute = Mage::getModel('catalog/resource_eav_attribute')->loadByCode('catalog_product',
strtolower($attribute_name));
$options = $attribute->getSource()->getAllOptions(true);
foreach ($options as $array)
{
$options_array[$attribute_name][strtolower(trim($array[label]))] = $array[value];
}
}
///GET VALUES FROM ARRAY ABOVE
foreach ($option_names as $option_name)
{
$values[] = $options_array[$attribute_name][strtolower($option_name)];
}
$string = implode(',', array_values($values));
return $string;
}
////////////////////////////////////
//GET ATTRIBUTES FROM ITEM ATTRIBUTES BACKUP TABLE (brand, search, materialandfabric, etc)
////////////////////////////////////
echo "Making Array from Item Attribute backup table...\n";
$item_attribute_sql =
"SELECT ItemCode, AttributeValue8 as Brand, AttributeValue7 as SearchTerm, AttributeValue16 as FulfillmentLatency,
AttributeValue18 as SmallImageUrl, AttributeValue19 as MainImageUrl, AttributeValue20 as Alternate1ImageUrl,
AttributeValue21 as Alternate2ImageUrl, AttributeValue22 as Alternate3ImageUrl, AttributeValue23 as Alternate4ImageUrl,
AttributeValue24 as Alternate5ImageUrl, AttributeValue25 as Alternate6ImageUrl,
AttributeValue42 as MaterialAndFabric, AttributeValue48 as SwatchImageUrl
FROM itemattribute";
$item_attribute_result = mysql_query($item_attribute_sql);
$item_attribute_array = array();
while ($item_attribute_row = mysql_fetch_assoc($item_attribute_result))
{
$item_attribute_array[$item_attribute_row['ItemCode']] = $item_attribute_row;
}
////////IMPORT
foreach(Mage::getModel('catalog/product')->getCollection() as $product)
{
$sku = $product->getSku();
$material_option_names = explode('|', $item_attribute_array[$sku]['MaterialAndFabric']);
$material_id_string = get_magento_option_ids('materialandfabric', $material_option_names);
//$product->setmaterialandfabric($material_id_string)->save();
echo "$sku has materialandfabric updated with multiple select attributes ($material_id_string)\n";
}
?>
<?
////////////////////
//
// MARKS CHANGES
//
////////////////////
//This wordpress hook was called in C:\makeshift\files\wordpress\goon_city\wp-content\plugins\watupro\controllers\questions.php (function: watupro_questions, line 248)
//This is at the point where a question has been changed in the Administration Panel
add_action( 'watupro_saved_question', 'watupro_saved_question_custom');
function watupro_saved_question_custom($question_id)
{
global $wpdb;
$_watu = new WatuPRO();
//From the question id, get tkhe exam it's affiliated with (exam is a parent entity of the question)
//Left joining into the Exam table to get advanced settings
$exam = $wpdb->get_row($wpdb->prepare("SELECT questions.* , master.advanced_settings FROM " . WATUPRO_QUESTIONS." as questions LEFT JOIN ".WATUPRO_EXAMS." as master ON master.ID = questions.exam_id WHERE questions.ID=%d", $question_id));
$exam_id = $exam->exam_id;
//code from show_exam.php (before submit_exam.php)
$advanced_settings = unserialize(stripslashes($exam->advanced_settings));
//From the Student Taken Occurences Table (the answers that were chosen will be put here for comparison, to compare to the current answers located in the wp_watupro_answers table).
$takings = $wpdb->get_results($wpdb->prepare("SELECT * FROM ".WATUPRO_TAKEN_EXAMS." WHERE exam_id=%d ORDER BY ID DESC", $exam_id));
//Get all the questions from the Exam Id
$questions = $wpdb->get_results($wpdb->prepare("SELECT * FROM ".WATUPRO_QUESTIONS." WHERE exam_id=%d", $exam_id));
//Iterate through all student taking IDS, then iterate through the questions to calculate totals
foreach ($takings as $taking)
{
$taking_id = $taking->ID;
$total = $score = $max_points = $achieved = $num_empty = $num_wrong = 0;
//Iterate through the questions to calculate totals
foreach ($questions as $question) {
$question_id = $question->ID;
//According to the store_result function in the watopro.php lib file, a $question object is a database row.
$answers = $wpdb->get_results($wpdb->prepare("SELECT * FROM ".WATUPRO_ANSWERS." WHERE question_id=%d AND question_id>0 ORDER BY sort_order", $question_id));
//this part is necessary for the WTPQuestion::max_scores function. It's looking at this q_answers variable I just put below
$question->q_answers = $answers;
$chosen_answers = $wpdb->get_results($wpdb->prepare("SELECT * FROM ".WATUPRO_STUDENT_ANSWERS." WHERE taking_id=%d AND question_id=%d", $taking_id,$question_id));
//The entire purpose of getting $chosen_answer_ids is to put as a parameter to WTPQUESTION::calc_answer
//THE FOLLOWING IS TO PROTECT the VALUES WHEN THERE ARE COMMAS
$chosen_answer_ids = array();
$answers_values = array_map(function($answer){return $answer->answer;},$answers);
$answers_quotes = array_map(function($answer_value){return '"'. $answer_value . '"';},$answers_values);
//unfortunately, you have to cross reference the answers the student chose with the correct answer known in the answers table (no join used here)
foreach($chosen_answers as $chosen_answer)
{
//THIS IS THE ANNOYING LONG STRING WITH COMMAS!!!
$chosen_answer_full_names = $chosen_answer->answer;
$chosen_answer_full_names = str_replace($answers_values,$answers_quotes,$chosen_answer_full_names);
foreach(str_getcsv($chosen_answer_full_names) as $chosen_answer_full_name)
{
$chosen_answer_full_name = trim($chosen_answer_full_name);
foreach ($answers as $answer) {
if(strtolower($chosen_answer_full_name) == strtolower($answer->answer))
{
$chosen_answer_ids[] = $answer->ID;
}
}
}
}
if($debug)
{
// echo "STUDENT ID: $taking_id\n";
// debug_help("QUESTION",$question);
// debug_help("ALL ANSWERS",$answers);
// debug_help("CHOSEN ANSWER",$chosen_answers);
// debug_help("CHOSEN ANSWER IDS",$chosen_answer_ids);
}
//THE POINT OF THOSE SQL CALLS WAS TO CALCULATE THE POINTS & A BOOLEAN IF THE QUESTION WAS CORRECT
list($points, $correct, $is_empty) = WTPQuestion::calc_answer($question, $chosen_answer_ids,$answers);
$question_max_points = WTPQuestion::max_points($question);
//calculate total & score
if(empty($question->is_survey)) $total++;
if($correct) $score++;
//calculate percent
if($total==0) $percent=0;
else $percent = number_format($score / $total * 100, 2);
$percent = round($percent);
//get total points that were acquired
//the following is a separate grading system based on the amount of points, and not grading based on # right or # wrong. It is weighted.
$achieved += $points;
$max_points += WTPQuestion::max_points($question);
if($is_empty and empty($question->is_survey))
{
$num_empty++;
}
if(!$is_empty and !$correct and empty($question->is_survey))
{
$num_wrong++;
}
if($achieved <= 0 or $max_points <= 0)
{
$pointspercent = 0;
}
else
{
$pointspercent = number_format($achieved / $max_points * 100, 2);
}
//generic rating, doesn't matter as much as above
$rating = $_watu->calculate_rating($total, $score, $percent);
}//end question iteration
//Grade tabulating should not be in the question for-loop above, just as it is in submit-exam.php
list($grade, $certificate_id, $do_redirect, $grade_obj) = WTPGrade::calculate($exam_id, $achieved, $percent, 0, $user_grade_ids, $pointspercent);
$grade_value = $grade_obj->gtitle;
if($debug)
{
echo "STUDENT TEST OCCURENCE: $taking_id\n";
echo "POINTS: $points\n";
echo "PERCENT: $percent\n";
echo "SCORE: $score\n";
echo "TOTAL: $total\n";
echo "MAX POINTS: $max_points\n";
echo "RATING: $rating\n";
echo "ACHIEVED: $achieved\n";
echo "POINTS PERCENT: $pointspercent\n";
echo "GRADE: $grade\n";
echo "GRADE: {$grade_obj->ID}\n";
echo "NUM EMPTY: $num_empty\n";
echo "NUM WRONG: $num_wrong\n";
echo "\n\n\n\n\n\n";
}
//points = all points combined ($achieved)
//result = String HTML of Grade
//grade_id = ID of Grade
//percent_correct = 75 (based on right vs wrong)
//percent_points = 82 (based on points) $pointpercent
//num_correct = Number of Raw correct in entire exam (known as $score)
//num_wrong = num_wrong
//num_empty = num_empty
//max_points = max_points
$result = $wpdb->update(WATUPRO_TAKEN_EXAMS, array(
"points" => $achieved,
"result" => $grade,
"grade_id" => $grade_obj->ID,
"percent_correct" => $percent,
"percent_points" => $pointspercent,
"num_correct" => $score,
"num_wrong" => $num_wrong,
"num_empty" => $num_empty,
"max_points" => $max_points
),
array(
"id"=>$taking_id
)
);
echo "$result\n";
}//end taking exam occurence iteration
////////////////////
//
// SECOND TWEAK (UPDATE THE OTHER TABLE AS WELL, WHICH IS THE WP_WATUPRO_STUDENT_PLUGIN APP. THE REASON FOR THIS IS TO UPDATE THE SINGLE PAGE VIEW OF THE EXAM TAKEN OCCURENCES, AS IT READS FROM THAT TABLE!!!
//
////////////////////
$student_answers = $wpdb->get_results($wpdb->prepare("SELECT * FROM ".WATUPRO_STUDENT_ANSWERS." WHERE exam_id=%d ORDER BY ID DESC ",$exam_id));
foreach ($student_answers as $key => $student_answer) {
$student_answer_question_id = $student_answer->question_id;
$answers = $wpdb->get_results($wpdb->prepare("SELECT * FROM ".WATUPRO_ANSWERS. " WHERE question_id=%d AND question_id>0 ORDER BY sort_order",$student_answer_question_id));
$question = $wpdb->get_row($wpdb->prepare("SELECT * FROM ".WATUPRO_QUESTIONS. " WHERE ID=%d",$student_answer_question_id));
$question->q_answers = $answers;
$answers_values = array_map(function($answer){return $answer->answer;},$answers);
$answers_quotes = array_map(function($answer_value){return '"'. $answer_value . '"';},$answers_values);
$chosen_answer_ids = array();
$chosen_answer_full_names = $student_answer->answer;
$chosen_answer_full_names = str_replace($answers_values,$answers_quotes,$chosen_answer_full_names);
foreach(str_getcsv($chosen_answer_full_names) as $chosen_answer_full_name)
{
$chosen_answer_full_name = trim($chosen_answer_full_name);
foreach ($answers as $answer) {
if(strtolower($chosen_answer_full_name) == strtolower($answer->answer))
{
$chosen_answer_ids[] = $answer->ID;
}
}
}
list($points, $correct, $is_empty) = WTPQuestion::calc_answer($question, $chosen_answer_ids,$answers);
if($debug)
{
echo "-------\n";
echo "POINTS: $points\n";
echo "CORRECT: $correct\n";
echo "IS EMPTY: $is_empty\n";
}
$result = $wpdb->update(WATUPRO_STUDENT_ANSWERS, array(
"points" => $points,
"is_correct" => $correct,
),
array(
"ID"=>$student_answer->ID
)
);
echo $result;
}
////////////////////
//
// END CHANGING THE SINGLE VIEW SECTION IN THE WP_WATUPRO_STUDENT_PLUGIN
//
////////////////////
}
import { Provider } from 'react-redux';
import '../styles/App.css';
import CounterClass from "./CounterClass.js";
import CounterFunctional from "./CounterFunctional.js";
import ReduxResult from './ReduxResult.js';
import Log from './Log.js';
import store from "./ReduxStore.js";
function App() {
return (
<Provider store={store}>
<div className="App flex bg-red-500 min-h-screen">
<div className="flex flex-1 justify-center items-center flex-col min-h-screen bg-slate-900">
<CounterClass id="1" />
<CounterFunctional id="2" />
<ReduxResult />
</div>
<div className="flex flex-1 flex-col w-full justify-end p-8 min-h-screen bg-slate-950">
<Log/>
</div>
</div>
</Provider>
);
}
export default App;
import React, { useState } from 'react';
import styles from '../styles/styles.module.css';
import { Toaster, toast } from 'sonner'
function Counter() {
const [count, setCount] = useState(0);
const [text, setText] = useState('');
const handlePlusClick = () => {
setCount(count + 1);
toast('Plus');
};
const handleMinusClick = () => {
setCount(count - 1);
toast('Minus');
};
const handleTextChange = (event) => {
setText(event.target.value);
};
return (
<div className="flex items-center justify-center">
<div className="flex">
<input value={count} onChange={handleTextChange} />
</div>
<button className="flex" onClick={handlePlusClick}>+</button>
<button className="flex" onClick={handleMinusClick}>-</button>
</div>
);
}
export default Counter;
import React, { Component } from 'react';
import styles from '../styles/styles.module.css';
import { connect } from 'react-redux';
import { increment, decrement, push_to_log } from './ReduxStore.js';
class ClassCounter extends Component {
constructor(props) {
super(props);
this.state = { count: 0 };
// Order: 0 - Constructor: Initializes state, binds methods.
}
componentDidMount() {
this.props.push_to_log('(Class Component) Component Did Mount');
// Order: 3 - After component insertion. Good for API calls.
}
shouldComponentUpdate(nextProps, nextState) {
this.props.push_to_log('(Class Component) Should Component Update');
// Order: 4 (before each update) - Decides if re-rendering is needed.
return true;
}
getSnapshotBeforeUpdate(prevProps, prevState) {
this.props.push_to_log('(Class Component) Get Snapshot Before Update');
// Order: 6 (before each DOM update) - Right before DOM updates.
return null;
}
componentDidUpdate(prevProps, prevState, snapshot) {
this.props.push_to_log('(Class Component) Component Did Update');
// Order: 7 (after each update) - After updates are flushed to the DOM.
}
componentWillUnmount() {
this.props.push_to_log('(Class Component) Component Will Unmount');
// Order: 8 (before unmounting) - Before removal from the DOM. Good for cleanup.
}
handlePlusClick = () => {
this.setState({ count: this.state.count + 1 });
this.props.increment(this.props.id);
this.props.push_to_log('(Class Component) ');
this.props.push_to_log('(Class Component) Increment');
// Order: 5 (during update) - Increment count.
};
handleMinusClick = () => {
this.setState({ count: this.state.count - 1 });
this.props.decrement(this.props.id);
this.props.push_to_log('(Class Component) ');
this.props.push_to_log('(Class Component) Decrement');
// Order: 5 (during update) - Decrement count.
};
render() {
this.props.push_to_log('(Class Component) Render');
// Order: 1 (initial), 2 (on each update) - Outputs JSX to the DOM.
return (
<div class="flex flex-col mb-2">
<div className="flex justify-center mb-1">
Class Component
</div>
<div className="flex flex-row mb-1">
<div className="">
<input className="h-8 p-1" value={this.state.count} />
</div>
<button className="h-8 w-8 ml-1 bg-slate-700" onClick={this.handlePlusClick}>+</button>
<button className="h-8 w-8 ml-1 bg-slate-700" onClick={this.handleMinusClick}>-</button>
</div>
</div>
);
}
}
const mapStateToProps = (state, ownProps) => ({
count: state.counter.counters[ownProps.id] || 0, // Access count for specific id,
});
const mapDispatchToProps = {
increment,
decrement,
push_to_log
};
export default connect(mapStateToProps, mapDispatchToProps)(ClassCounter);
import React, { useState, useEffect, useLayoutEffect } from 'react';
import { increment, decrement, push_to_log } from "./ReduxStore.js";
import { useDispatch } from "react-redux";
function CounterFunctional({ id }) {
const [count, setCount] = useState(0);
const dispatch = useDispatch();
dispatch(push_to_log('(Functional Component) useState'));
// Order: 0 (on each render) - useState: Adds state to functional components.
useEffect(() => {
dispatch(push_to_log('(Functional Component) useEffect - Mount'));
// Order: 2 (after first render) - Similar to componentDidMount and componentDidUpdate.
return () => {
dispatch(push_to_log('(Functional Component) useEffect - Cleanup'));
// Order: 7 (before unmounting) - Cleanup: Similar to componentWillUnmount.
};
}, []);
useEffect(() => {
dispatch(push_to_log('(Functional Component) useEffect - {count} Update'));
// Order: 3 (after each update) - Runs on state/props update with dependency array.
}, [count]);
useLayoutEffect(() => {
dispatch(push_to_log('(Functional Component) useLayoutEffect'));
// Order: 1 (after each render before DOM updates) - Fires synchronously after all DOM mutations.
});
const handlePlusClick = () => {
setCount(count + 1);
dispatch(push_to_log('(Functional Component) '));
dispatch(push_to_log('(Functional Component) Increment'));
dispatch(increment(id));
// Order: 4 (during update) - Increment count.
};
const handleMinusClick = () => {
setCount(count - 1);
dispatch(decrement(id));
dispatch(push_to_log('(Functional Component) '));
dispatch(push_to_log('(Functional Component) Decrement'));
// Order: 4 (during update) - Decrement count.
};
return (
<div class="flex flex-col mb-5">
<div className="flex justify-center mb-1">
Functional Component
</div>
<div className="flex flex-row mb-1">
<div className="">
<input className="h-8 p-1" value={count} />
</div>
<button className="h-8 w-8 ml-1 bg-slate-700" onClick={handlePlusClick}>+</button>
<button className="h-8 w-8 ml-1 bg-slate-700" onClick={handleMinusClick}>-</button>
</div>
</div>
);
}
export default CounterFunctional;
import React from 'react';
import { useSelector } from "react-redux";
export const Log = () => {
const log_list = useSelector(state => state.log.log);
return (
<div class="flex">
<ul className="w-3/4">
{log_list.map((entry, index) => (
<li className="bg-gradient-to-r from-[#FF3300] to-purple-400 text-[#330033] font-verdana text-[13px] font-bold mb-2 rounded shadow px-2 py-[1px] border-white border-[0px]" key={index}>{entry}</li>
))}
</ul>
</div>
);
}
export default Log;
import React from 'react';
import { useSelector } from 'react-redux';
function ReduxResult() {
const counters = useSelector(state => state.counter.counters);
const total = Object.values(counters).reduce((sum, current) => sum + current, 0);
return (
<div>
<h2>(Redux) Total Count: {total}</h2>
</div>
);
}
export default ReduxResult;
import { configureStore, createSlice } from '@reduxjs/toolkit';
const counterSlice = createSlice({
name: 'counter',
initialState: {
counters: {} // Object to hold individual counters
},
reducers: {
increment: (state, action) => {
const id = action.payload; // id of the counter to increment
if (state.counters[id] === undefined) state.counters[id] = 0;
state.counters[id] += 1;
},
decrement: (state, action) => {
const id = action.payload; // id of the counter to decrement
if (state.counters[id] === undefined) state.counters[id] = 0;
state.counters[id] -= 1;
}
}
});
const logSlice = createSlice({
name: 'log',
initialState: {
log: []
},
reducers: {
push_to_log(state, action) {
state.log.push(action.payload);
if(state.log.length > 18) state.log.shift();
}
}
});
export const { increment, decrement } = counterSlice.actions;
export const { push_to_log } = logSlice.actions;
const store = configureStore({
reducer: {
counter: counterSlice.reducer,
log: logSlice.reducer
}
});
export default store;
def permutation_in_string(small_string,long_string):
'''
is a permutation of small string in long string (true or false)
NOTE: NEETCODE DID A FREQUENCY ARRAY OF A TO Z, OF 26 KEY ENTRIES
'''
length_small_string = len(small_string)
length_long_string = len(long_string)
# fill dict of small string
char_map_small_string = {}
for l in small_string:
char_map_small_string[l] = char_map_small_string.get(l,0) + 1;
# fill dict of sliding window that's fixed
char_map_sliding_window = {}
for l in long_string[0:length_small_string]:
char_map_sliding_window[l] = char_map_sliding_window.get(l,0) + 1;
# sliding window from left to right, fixed size
for right in range(length_small_string,length_long_string):
left = right - length_small_string
letter_right = long_string[right]
letter_left = long_string[left]
print(char_map_small_string,char_map_sliding_window)
if char_map_sliding_window == char_map_small_string:
return True
# the character map will reflect when the sliding window moves right
char_map_sliding_window[letter_left] = char_map_sliding_window[letter_left] - 1
# do this for equality. Remove from charmap if it's zero
if char_map_sliding_window[letter_left] == 0:
del char_map_sliding_window[letter_left]
char_map_sliding_window[letter_right] = char_map_sliding_window.get(letter_right,0) + 1
return False
# permutation_in_string("abee","fibembaeewellon")
def minimum_window_substring(string_small, string_long):
# Create a set of unique characters in the small string
set_string_small = set(string_small)
# Map each character in the small string to its count
char_map_string_small = {}
for c in string_small:
char_map_string_small[c] = char_map_string_small.get(c, 0) + 1
# Initialize a deque
stack = deque()
# Initialize a map to keep track of characters in the long string
char_map_string_long = {}
# Initialize variables for the final result
max_length = 0
result = ''
# Iterate over each character in the long string
for index, character_long in enumerate(string_long):
# If the character is in the small string
if character_long in set_string_small:
# Add the character to the window stack
stack.append([character_long, index])
# Update the character count in the long string map
char_map_string_long[character_long] = char_map_string_long.get(character_long, 0) + 1
# Update the right pointer to the current index
right = index
# If the window size exceeds the small string size, remove the leftmost character
if len(stack) > len(string_small):
# Remove the leftmost character from the window
pop_node = stack.popleft()
removed_character = pop_node[0]
removed_position = pop_node[1]
# Update the left pointer to the removed character's position
left = removed_position
# Decrease the character count in the long string map
char_map_string_long[removed_character] = char_map_string_long.get(removed_character, 0) - 1
# If the character counts in the small and long string maps match
if char_map_string_small == char_map_string_long:
# Calculate the length of the current window
string_length = stack[-1][1] - stack[0][1]
# Update the maximum length found so far
max_length = max(max_length, string_length)
# If the current window is smaller than the maximum length, update the result
if string_length <= max_length:
result = string_long[stack[0][1]: stack[-1][1] + 1]
# Return the minimum window substring
return result
# minimum_window_substring("abc","adobecodebanc")