├── .flake8 ├── .gitattributes ├── .github ├── FUNDING.yml ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── lint.yml │ └── year.yml ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── dl-file └── dl.py ├── excel ├── expenses.py ├── graphs.py └── income.py ├── git-commands └── commands.py ├── hue-light └── control.py ├── monitor-website ├── volume_warning.wav └── web.py ├── move-cursor ├── cursor.py └── piano_tiles_bot.py ├── organize-files └── organizer.py ├── reddit ├── README.md ├── extract.py ├── join.py └── samplesubs.txt ├── repo ├── priv.py └── publ.py ├── requirements.txt ├── scheduler ├── scheduler.py └── sound.wav ├── selenium-testing ├── cross-browser.py ├── login-form.py ├── search.py └── sign-up-so.py ├── send-email └── email.py ├── tweeter ├── README.md └── tweet.py ├── whatsapp └── msg.py └── youtube └── dl.py /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | ignore: 3 | E501, 4 | F821 5 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | *.py text diff=python 5 | *.pyc binary 6 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: endormi 2 | patreon: endormi 3 | ko_fi: endormi 4 | custom: www.buymeacoffee.com/endormi 5 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | ## Description 6 | 7 | 8 | 9 | ## Related Issues 10 | 11 | 15 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: flake8 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | flake8: 7 | runs-on: ubuntu-latest 8 | name: flake8 9 | steps: 10 | - name: Check out source repository 11 | uses: actions/checkout@v3 12 | - name: Set up Python environment 13 | uses: actions/setup-python@v4 14 | with: 15 | python-version: "3.11" 16 | - name: flake8 Lint 17 | uses: py-actions/flake8@v2 18 | 19 | -------------------------------------------------------------------------------- /.github/workflows/year.yml: -------------------------------------------------------------------------------- 1 | name: Update Year 2 | 3 | on: 4 | schedule: 5 | - cron: "0 1 1 1 *" # 01:00 on January 1 6 | 7 | jobs: 8 | update_year: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout Repository 12 | uses: actions/checkout@v3 13 | 14 | - name: Update year in LICENSE 15 | uses: endormi/yearplusplus@v2 16 | with: 17 | files: 'LICENSE' 18 | username: 'Year++' 19 | email: '<>' 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/ 2 | *.pyc 3 | *.py[cod] 4 | *$py.class 5 | *.log 6 | .env 7 | .venv 8 | env/ 9 | venv/ 10 | ENV/ 11 | env.bak/ 12 | venv.bak/ 13 | .cache 14 | 15 | # To ignore selenium-testing testresults: 16 | *.html 17 | 18 | # To ignore excel files: 19 | *.xlsx 20 | *.xlsb 21 | *.xltx 22 | *.xls 23 | 24 | # To ignore txt file: 25 | file.txt 26 | 27 | # To ignore downloaded YouTube audio: 28 | *.mp3 29 | 30 | # To ignore subreddits file 31 | subs.txt 32 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribution Guidelines 2 | 3 | Please ensure your pull request adheres to the following guidelines: 4 | 5 | - Search previous suggestions before making a new one, as yours may be a duplicate. 6 | - Make an individual pull request for each suggestion. 7 | - New categories, or improvements to the existing categorization are welcome. 8 | - Keep descriptions short and simple, but descriptive. 9 | - End all descriptions with a full stop/period. 10 | - Check your spelling and grammar. 11 | 12 | ## Contribution to GitHub steps 13 | 14 | - Fork it! 15 | - Create your branch: `git checkout -b my-new-branch` 16 | - Commit your changes: `git commit -am 'Fixed typo'` 17 | - Push to the branch: `git push origin my-new-branch` 18 | - Submit a pull request 19 | 20 | ## Updating your Pull Request 21 | 22 | Sometimes, a maintainer of an this list will ask you to edit your Pull Request before it is included. 23 | This is normally due to spelling errors or because your PR didn't match the guidelines. 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Endormi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Automation [![Python Version](https://img.shields.io/badge/python-3.6.1-brightgreen.svg?)](https://www.python.org/downloads/) 2 | 3 | Collection of automated tasks. 4 | 5 | > **Disclaimer**: Some of the scripts are small and may not be very useful for example [Send-email](https://github.com/endormi/automation/blob/master/send-email/email.py), but are still pretty cool :). 6 | 7 | > I created some of the scripts with the intention that they're a foundation for more complex automated scripts such as. expenses, income, selenium-testing and a few more. The files that are these types of scripts will have (X). 8 | 9 | Clone repository: 10 | 11 | ``` 12 | git clone https://github.com/endormi/automation.git && cd automation 13 | ``` 14 | 15 | Install requirements: 16 | 17 | ```sh 18 | pip install -r requirements.txt 19 | ``` 20 | 21 | Now you can run every script. 22 | 23 | - [DL-file](https://github.com/endormi/automation/blob/master/dl-file/dl.py) - X - File downloader. 24 | - [Excel](https://github.com/endormi/automation/blob/master/excel): 25 | - [Expenses](https://github.com/endormi/automation/blob/master/excel/expenses.py) - X - Adds business and personal expenses to Excel (Current code needs you to add the expenses manually, but will automatically add them to Excel. Not ideal I know, I'll be adding a better code when I have time). This is only a foundation for your excel files, which you can then update to your own liking. 26 | - [Graph](https://github.com/endormi/automation/blob/master/excel/graphs.py) - X - Excel graph. 27 | - [Income](https://github.com/endormi/automation/blob/master/excel/income.py) - X - Adds income to Excel (Current code needs you to add the income manually, but will automatically add them to Excel. Not ideal I know, I'll be adding a better code when I have time). This is only a foundation for your excel files, which you can then update to your own liking. 28 | - [Hue-light](https://github.com/endormi/automation/blob/master/hue-light/control.py) - X - Control hue lights. 29 | - [Git-commands](https://github.com/endormi/automation/blob/master/git-commands/commands.py) - Automates the process of using commands such as clone, commit, branch, pull, merge and blame. 30 | - [Monitor-website](https://github.com/endormi/automation/blob/master/monitor-website/web.py) - If website isn't up-and-running, sends an email and plays a sound. 31 | - [Move-cursor](https://github.com/endormi/automation/blob/master/move-cursor): 32 | - [Move-cursor](https://github.com/endormi/automation/blob/master/move-cursor/cursor.py) - Move cursor every 10 seconds. 33 | - [Piano tiles](https://github.com/endormi/automation/blob/master/move-cursor/piano_tiles_bot.py) - Magic piano tiles game script by [adhirajpandey](https://github.com/adhirajpandey). 34 | - [Organize-files](https://github.com/endormi/automation/blob/master/organize-files/organizer.py) - Organizes files (images, audio, texts, videos and compressed files) and moves them inside specified folders. 35 | - [Reddit](https://github.com/endormi/automation/blob/master/reddit) - Allows you to efficiently transfer joined subreddits from one account to another reddit account: 36 | - [Extract](https://github.com/endormi/automation/blob/master/reddit/extract.py) by [adhirajpandey](https://github.com/adhirajpandey). 37 | - [Join](https://github.com/endormi/automation/blob/master/reddit/join.py) by [adhirajpandey](https://github.com/adhirajpandey). 38 | - [Repo](https://github.com/endormi/automation/tree/master/repo) - Creates a private or public GitHub repository (uses selenium, but you can easily also use the GitHub package). 39 | - [Scheduler](https://github.com/endormi/automation/tree/master/scheduler/scheduler.py) - X - Scheduled jobs (open email, shutdown computer etc.). 40 | - [Selenium testing](https://github.com/endormi/automation/tree/master/selenium-testing): 41 | - [Cross browser](https://github.com/endormi/automation/blob/master/selenium-testing/cross-browser.py) - X - Cross browser testing. 42 | - [Login form](https://github.com/endormi/automation/blob/master/selenium-testing/login-form.py) - X - Login form testing (tests GitHub, Stack Overflow and Twitter) and generates report. 43 | - [Search](https://github.com/endormi/automation/blob/master/selenium-testing/search.py) - X - Search function testing (searches `Python` in GitHub, Stack Overflow and Amazon) and generates report. 44 | - [Sign up SO](https://github.com/endormi/automation/blob/master/selenium-testing/sign-up-so.py) - X - Sign up testing (tests Stack Overflow, Gmail and GitHub) and generates report. 45 | - [Send-email](https://github.com/endormi/automation/blob/master/send-email/email.py) - Send emails (subject, content and image attachments). 46 | - [Tweeter](https://github.com/endormi/automation/blob/master/tweeter) - Write and post tweets. 47 | - [Whatsapp](https://github.com/endormi/automation/blob/master/whatsapp/msg.py) - Send Whatsapp message (I'm thinking of switching from Whatsapp, but thought this still should be added). 48 | - [Youtube](https://github.com/endormi/automation/blob/master/youtube/dl.py) - Download an audio from YouTube. 49 | 50 | ## License 51 | 52 | The source code is released under the [MIT License](https://github.com/endormi/automation/blob/master/LICENSE). 53 | -------------------------------------------------------------------------------- /dl-file/dl.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | author: @endormi 4 | 5 | Automated file downloader using Selenium 6 | 7 | """ 8 | 9 | from selenium import webdriver 10 | from selenium.webdriver.chrome.options import Options 11 | import time 12 | 13 | 14 | """ 15 | Install browser driver: 16 | https://selenium.dev/downloads/ 17 | """ 18 | 19 | options = Options() 20 | options.add_experimental_option('prefs', { 21 | "download.default_directory": r'directory/you/choose', 22 | "download.prompt_for_download": False, 23 | "download.directory_upgrade": True, 24 | "safebrowsing.enabled": True 25 | }) 26 | 27 | browser = webdriver.Chrome(options=options, executable_path=r'file/to/driver/if/needed/otherwise/remove/r') 28 | browser.get('https://chromedriver.chromium.org/') 29 | time.sleep(1) 30 | link = browser.find_element_by_xpath('/html/body/div[2]/div/div[1]/div/div[2]/div/table/tbody/tr/td[2]/div/div[3]/div/table/tbody/tr/td/div/div[4]/ul/li[1]/a') 31 | link.click() 32 | dl_file = browser.find_element_by_xpath('/html/body/table/tbody/tr[6]/td[2]/a') 33 | dl_file.click() 34 | -------------------------------------------------------------------------------- /excel/expenses.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | author: @endormi 4 | 5 | Business and personal expenses tracker 6 | Automatically adds to excel 7 | 8 | """ 9 | 10 | import xlsxwriter 11 | 12 | 13 | wb = xlsxwriter.Workbook('filename.xlsx', {'strings_to_numbers': True}) 14 | wsb = wb.add_worksheet(name='Business Expenses 2022') 15 | wsp = wb.add_worksheet(name='Personal Expenses 2022') 16 | bold = wb.add_format({'bold': True}) 17 | 18 | row = 2 19 | col = 0 20 | 21 | wsb.write('A1', 'Business Expenses', bold) 22 | wsb.write('A2', 'Date:', bold) 23 | wsb.write('B2', 'Type of expense:', bold) 24 | wsb.write('C2', 'Amount of expense:', bold) 25 | wsb.write('D2', 'Total:', bold) 26 | wsp.write('A1', 'Personal Expenses', bold) 27 | wsp.write('A2', 'Date:', bold) 28 | wsp.write('B2', 'Type of expense:', bold) 29 | wsp.write('C2', 'Amount of expense:', bold) 30 | wsp.write('D2', 'Total:', bold) 31 | 32 | currency_format = wb.add_format({'num_format': '# ##0.00 €'}) 33 | 34 | business = ( 35 | ['01.01.2022', 'type1', '1000'], 36 | ['01.01.2022', 'type2', '1000'], 37 | ['01.01.2022', 'type3', '1000'], 38 | ['01.01.2022', 'type4', '1000'], 39 | ['01.01.2022', 'type4', '1000'], 40 | ['01.01.2022', 'type5', '1000'], 41 | ) 42 | 43 | personal = ( 44 | ['01.01.2022', 'type1', '1000'], 45 | ['01.01.2022', 'type2', '1000'], 46 | ['01.01.2022', 'type3', '1000'], 47 | ['01.01.2022', 'type4', '1000'], 48 | ['01.01.2022', 'type4', '1000'], 49 | ['01.01.2022', 'type5', '1000'], 50 | ) 51 | 52 | for i, r, c in (business): 53 | wsb.write(row, col, i) 54 | wsb.write(row, col + 1, r) 55 | wsb.write(row, col + 2, c) 56 | row += 1 57 | 58 | wsb.write_formula("D3", "=SUM(C3:C7)", currency_format) 59 | 60 | for i, r, c in (personal): 61 | wsp.write(row, col, i) 62 | wsp.write(row, col + 1, r) 63 | wsp.write(row, col + 2, c) 64 | row += 1 65 | 66 | wsp.write_formula("D3", "=SUM(C3:C7)", currency_format) 67 | 68 | wb.close() 69 | -------------------------------------------------------------------------------- /excel/graphs.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | author: @endormi 4 | 5 | Automated excel graphs 6 | 7 | """ 8 | 9 | import pandas 10 | import matplotlib.pyplot as plt 11 | 12 | 13 | df = pandas.read_excel('filename.xslx') 14 | val = df[['Month', 'Income']] 15 | 16 | graph = val.plot.bar(x='Month', y='Income') 17 | plt.show() 18 | -------------------------------------------------------------------------------- /excel/income.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | author: @endormi 4 | 5 | Income tracker 6 | Automatically adds to excel 7 | 8 | """ 9 | 10 | import xlsxwriter 11 | 12 | 13 | wb = xlsxwriter.Workbook('filename.xlsx', {'strings_to_numbers': True}) 14 | wsb = wb.add_worksheet(name='Income') 15 | bold = wb.add_format({'bold': True}) 16 | 17 | row = 2 18 | col = 0 19 | 20 | wsb.write('A1', 'Income', bold) 21 | wsb.write('A2', 'Date:', bold) 22 | wsb.write('B2', 'Type of income:', bold) 23 | wsb.write('C2', 'Amount of income:', bold) 24 | wsb.write('D2', 'Total:', bold) 25 | 26 | currency_format = wb.add_format({'num_format': '# ##0.00 €'}) 27 | 28 | income = ( 29 | ['01.01.2022', 'type1', '1000'], 30 | ['01.01.2022', 'type2', '1000'], 31 | ['01.01.2022', 'type3', '1000'], 32 | ['01.01.2022', 'type4', '1000'], 33 | ['01.01.2022', 'type4', '1000'], 34 | ['01.01.2022', 'type5', '1000'], 35 | ) 36 | 37 | for i, r, c in (income): 38 | wsb.write(row, col, i) 39 | wsb.write(row, col + 1, r) 40 | wsb.write(row, col + 2, c) 41 | row += 1 42 | 43 | wsb.write_formula("D3", "=SUM(C3:C7)", currency_format) 44 | 45 | wb.close() 46 | -------------------------------------------------------------------------------- /git-commands/commands.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | author: @endormi 4 | 5 | Automated Git commands 6 | Automate the process of using commands such as clone, commit, branch, pull, merge and blame 7 | 8 | """ 9 | 10 | import subprocess 11 | from pyfiglet import figlet_format 12 | from termcolor import cprint 13 | 14 | 15 | logo = 'Git-Commands' 16 | 17 | 18 | class color: 19 | NOTICE = '\033[91m' 20 | END = '\033[0m' 21 | 22 | 23 | info = color.NOTICE + ''' 24 | Automate the process of using commands such as clone, commit, branch, pull, merge and blame.\n''' + color.END 25 | 26 | 27 | dict = {} 28 | 29 | 30 | def run(*args): 31 | return subprocess.check_call(['git'] + list(args)) 32 | 33 | 34 | def clone(): 35 | print('\nYou will be asked for the user first and then the repository name.\n') 36 | 37 | user = input('User: ') 38 | repo = input('Repository: ') 39 | 40 | subprocess.Popen(['git', 'clone', 'https://github.com/' + user + '/' + repo + '.git']) 41 | 42 | 43 | def commit(): 44 | commit_message = input('\nType in your commit message: ') 45 | run('commit', '-am', commit_message) 46 | run('push', '-u', 'origin', 'master') 47 | 48 | 49 | def branch(): 50 | branch = input('\nType in the name of the branch you want to make: ') 51 | run('checkout', '-b', branch) 52 | 53 | choice = input('\nDo you want to push the branch right now to GitHub? (y/n): ').lower() 54 | 55 | if choice == 'y': 56 | run('push', '-u', 'origin', branch) 57 | else: 58 | print('\nOkay, goodbye!\n') 59 | 60 | 61 | def pull(): 62 | print('\nPulls changes from the current folder if *.git is initialized.') 63 | choice = input('\nDo you want to pull the changes from GitHub? (y/n): ').lower() 64 | 65 | if choice == 'y': 66 | run('pull') 67 | else: 68 | print('\nOkay, goodbye!\n') 69 | 70 | 71 | def fetch(): 72 | print('\nFetches changes from the current folder.') 73 | run('fetch') 74 | 75 | 76 | def merge(): 77 | branch = input('\nType in the name of your branch: ') 78 | run('merge', branch) 79 | 80 | 81 | def reset(): 82 | filename = input('\nType in the name of your file: ') 83 | run('reset', filename) 84 | 85 | 86 | def blame(): 87 | file = input('\nType in the name of the file: ') 88 | run('blame', file) 89 | 90 | 91 | def main(): 92 | cprint(figlet_format(logo, font='slant'), 'green') 93 | print(f'{info} \n') 94 | 95 | print('Commands to use: clone, commit, branch, pull, fetch, merge, reset and blame') 96 | 97 | choose_command = input('Type in the command you want to use: ').lower() 98 | 99 | dict = { 100 | 'clone': clone, 101 | 'commit': commit, 102 | 'branch': branch, 103 | 'pull': pull, 104 | 'fetch': fetch, 105 | 'merge': merge, 106 | 'reset': reset, 107 | 'blame': blame 108 | } 109 | 110 | dict.get(choose_command, lambda: "Invalid")() 111 | 112 | 113 | if __name__ == '__main__': 114 | main() 115 | -------------------------------------------------------------------------------- /hue-light/control.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | author: @endormi 4 | 5 | Automated philips hue light controller using Phue 6 | 7 | """ 8 | 9 | from phue import Bridge 10 | 11 | 12 | ip = '' 13 | b = Bridge(ip) 14 | # If the app is not registered and the button is not pressed, press the button and call connect() (this only needs to be run a single time) 15 | b.connect() 16 | lights = b.get_light_objects('name') 17 | dict = {} 18 | 19 | # for light in ['Kitchen'] 20 | # lights[light].on = True 21 | # lights[light].hue = 15000 22 | # lights[light].saturation = 120 23 | 24 | 25 | # Change the hue and saturation to change color 26 | 27 | def movie(): 28 | for light in lights: 29 | lights[light].on = True 30 | lights[light].hue = 5000 31 | lights[light].saturation = 100 32 | 33 | 34 | def turn_off(): 35 | for light in lights: 36 | lights[light].on = False 37 | 38 | 39 | def main(): 40 | print('Commands to use: movie & turn_off') 41 | 42 | choose_command = input("Type in the command you want to use: ").lower() 43 | 44 | dict = { 45 | 'movie': movie, 46 | 'turn_off': turn_off, 47 | } 48 | 49 | dict.get(choose_command, lambda: 'Invalid')() 50 | 51 | 52 | if __name__ == '__main__': 53 | main() 54 | -------------------------------------------------------------------------------- /monitor-website/volume_warning.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/endormi/automation/52fd89b24e709555c154ec3025c9995a5401f6bb/monitor-website/volume_warning.wav -------------------------------------------------------------------------------- /monitor-website/web.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | author: @endormi 4 | 5 | Automated website monitoring for exceptions 6 | if there is an exception it sends an email and plays a sound (remember to turn down your volume) 7 | 8 | """ 9 | 10 | import requests 11 | from playsound import playsound 12 | import smtplib 13 | 14 | 15 | url = '' 16 | PORT = 587 17 | Your_Email = 'example@company.com' 18 | 19 | """ 20 | Get your password from: 21 | https://myaccount.google.com/apppasswords 22 | """ 23 | Your_Password = 'password' 24 | 25 | 26 | req = requests.get(url, timeout=1) 27 | req.raise_for_status() 28 | 29 | while True: 30 | if req.status_code != 200: 31 | with smtplib.SMTP('smtp.gmail.com', PORT) as send__mail: 32 | send__mail.starttls() 33 | 34 | send__mail.login(Your_Email, Your_Password) 35 | 36 | sub = 'Your site is down!' 37 | body = 'Restart the server and make sure it is running.' 38 | message = f'Subject: {sub} \n\n {body}' 39 | 40 | send__mail.sendmail(Your_Email, Your_Email, message) 41 | print("Email sent!") 42 | 43 | playsound('volume_warning.wav') 44 | break 45 | else: 46 | continue 47 | -------------------------------------------------------------------------------- /move-cursor/cursor.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | author: @endormi 4 | 5 | Move cursor every 10 seconds 6 | 7 | """ 8 | 9 | import pyautogui 10 | import random 11 | import time 12 | 13 | 14 | def countdown_timer(start, end): 15 | for i in range(start, end, 1): 16 | time.sleep(1) 17 | print(i, end="\r") 18 | 19 | 20 | def main(): 21 | while True: 22 | pyautogui.moveTo(random.randint(100, 500), random.randint(10, 50), duration=1) 23 | countdown_timer(1, 10) 24 | 25 | 26 | if __name__ == '__main__': 27 | main() 28 | -------------------------------------------------------------------------------- /move-cursor/piano_tiles_bot.py: -------------------------------------------------------------------------------- 1 | import win32api 2 | import win32con 3 | import pyautogui 4 | import time 5 | import keyboard 6 | 7 | 8 | # using win32api for faster clicks 9 | def click(x, y): 10 | win32api.SetCursorPos((x, y)) 11 | win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 0, 0) 12 | # pause to hold the mouse button for valid clicks 13 | time.sleep(0.02) 14 | win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, 0, 0) 15 | 16 | 17 | # default - chrome window on left half screen, modify if required 18 | tile2_x, tile2_y = 450, 350 19 | tile3_x, tile3_y = 550, 350 20 | tile4_x, tile4_y = 650, 350 21 | tile1_x, tile1_y = 350, 350 22 | 23 | # delay to switch to game window 24 | time.sleep(5) 25 | 26 | print("Script Running ....") 27 | 28 | # press "e" to end the script 29 | while not keyboard.is_pressed("e"): 30 | 31 | # checking r value from r,g,b as it's black - 0,0,0 32 | if pyautogui.pixel(tile1_x, tile1_y)[0] == 0: 33 | click(tile1_x, tile1_y + 15) 34 | 35 | if pyautogui.pixel(tile2_x, tile2_y)[0] == 0: 36 | click(tile2_x, tile2_y + 15) 37 | 38 | if pyautogui.pixel(tile3_x, tile3_y)[0] == 0: 39 | click(tile3_x, tile3_y + 15) 40 | 41 | if pyautogui.pixel(tile4_x, tile4_y)[0] == 0: 42 | click(tile4_x, tile4_y + 15) 43 | -------------------------------------------------------------------------------- /organize-files/organizer.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | author: @endormi 4 | 5 | Automated organizer for images, audio, texts, videos and compressed files 6 | and moves them inside specified folders 7 | 8 | """ 9 | 10 | import os 11 | import shutil 12 | import time 13 | from pyfiglet import figlet_format 14 | from termcolor import cprint 15 | 16 | 17 | logo = 'Organizer' 18 | 19 | 20 | class color: 21 | NOTICE = '\033[91m' 22 | END = '\033[0m' 23 | 24 | 25 | info = color.NOTICE + ''' 26 | Automated organizer for images, audio, texts, videos, compressed files 27 | and moves them inside specified folders.\n''' + color.END 28 | 29 | 30 | PATH = r'folder/to/organize' 31 | 32 | images = r'destination/for/images' 33 | audio = r'destination/for/audio' 34 | docs = r'destination/for/docs' 35 | texts = r'destination/for/texts' 36 | videos = r'destination/for/videos' 37 | compressed_files = r'destination/for/compressed' 38 | 39 | os.chdir(PATH) 40 | move_file = os.listdir(PATH) 41 | 42 | 43 | def organize(): 44 | print("Organizing files!") 45 | 46 | for mv in move_file: 47 | # filetypes 48 | if mv.endswith(('png', 'jpg', 'jpeg', 'gif', 'ico', 'svg')): 49 | if not os.path.exists(f"{images}"): 50 | os.mkdir(f"{images}") 51 | shutil.move(mv, images) 52 | if mv.endswith(('mp3', 'wav', 'mid', 'midi', 'ogg')): 53 | if not os.path.exists(f"{audio}"): 54 | os.mkdir(f"{audio}") 55 | shutil.move(mv, audio) 56 | if mv.endswith(('pdf', 'doc', 'docx', 'docxml')): 57 | if not os.path.exists(f"{docs}"): 58 | os.mkdir(f"{docs}") 59 | shutil.move(mv, docs) 60 | if mv.endswith(('txt', 'text', 'note', 'rtf')): 61 | if not os.path.exists(f"{texts}"): 62 | os.mkdir(f"{texts}") 63 | shutil.move(mv, texts) 64 | if mv.endswith(('mp4', 'avi', 'mov', 'vmw', 'flv', 'mpeg', 'mpg')): 65 | if not os.path.exists(f"{videos}"): 66 | os.mkdir(f"{videos}") 67 | shutil.move(mv, videos) 68 | if mv.endswith(('zip', 'rar', 'tar', '7z', 'pkg')): 69 | if not os.path.exists(f"{compressed_files}"): 70 | os.mkdir(f"{compressed_files}") 71 | shutil.move(mv, compressed_files) 72 | 73 | time.sleep(1) 74 | print("Finished organizing files!") 75 | 76 | 77 | def main(): 78 | cprint(figlet_format(logo, font='slant'), 'green') 79 | print(info + "\n") 80 | 81 | if len(move_file) > 0: 82 | print(f"Found {len(move_file)} file(s). \n") 83 | organize() 84 | 85 | else: 86 | print("No files found!") 87 | print("Check your path: " + PATH) 88 | 89 | 90 | if __name__ == '__main__': 91 | main() 92 | -------------------------------------------------------------------------------- /reddit/README.md: -------------------------------------------------------------------------------- 1 | # Reddit Tool 2 | 3 | ## Description 4 | 5 | This Python tool allows you to efficiently transfer joined subreddits from one account to another reddit account. 6 | It can also help if you want to get a list of subscribed subreddits or if you want to mass subscribe to list of subreddits. 7 | 8 | ## Installation and Usage 9 | 10 | 1. Install the required dependency: `pip install praw` 11 | 2. Get API keys for both the accounts from `https://www.reddit.com/prefs/apps`, Tutorial: `https://www.jcchouinard.com/reddit-api/` 12 | 3. Add your obtained credentials at starting of `extract.py` and `join.py` files. 13 | 4. Now run the `extract.py` file to fetch all the subscribed subreddits into `subs.txt` file. Sample file: `samplesubs.txt` 14 | 5. Use `join.py` to subscribe to all the subreddits in `subs.txt` file. 15 | 6. You can check `joinedlogs.txt` to check status logs. 16 | 17 | ## Disclaimer 18 | This project is not affiliated with Reddit or its services. It's an independent tool created for educational and personal use. 19 | -------------------------------------------------------------------------------- /reddit/extract.py: -------------------------------------------------------------------------------- 1 | import praw 2 | 3 | # Primary Account Details 4 | client_id = "" 5 | client_secret = "" 6 | user_agent = "" 7 | username = "" 8 | password = "" 9 | 10 | reddit = praw.Reddit( 11 | client_id=client_id, 12 | client_secret=client_secret, 13 | user_agent=user_agent, 14 | username=username, 15 | password=password 16 | ) 17 | 18 | subslist = [] 19 | 20 | for subreddit in reddit.user.subreddits(limit=None): 21 | subslist.append(str(subreddit)) 22 | 23 | with open("subs.txt", "w") as f: 24 | for item in subslist: 25 | f.write(item + "\n") 26 | -------------------------------------------------------------------------------- /reddit/join.py: -------------------------------------------------------------------------------- 1 | import praw 2 | 3 | # Secondary Account Details 4 | client_id = "" 5 | client_secret = "" 6 | user_agent = "" 7 | username = "" 8 | password = "" 9 | 10 | reddit = praw.Reddit( 11 | client_id=client_id, 12 | client_secret=client_secret, 13 | user_agent=user_agent, 14 | username=username, 15 | password=password 16 | ) 17 | 18 | # Read from subs.txt 19 | subslist = [] 20 | with open("subs.txt", "r") as f: 21 | for line in f: 22 | subslist.append(line.strip()) 23 | 24 | # Join one by one and write a log to joined.txt 25 | with open("joinedlogs.txt", "w") as f: 26 | for sub in subslist: 27 | try: 28 | reddit.subreddit(sub).subscribe() 29 | f.write("Joined " + sub + "\n") 30 | print("Joined " + sub) 31 | except Exception as e: 32 | f.write("Failed to join " + sub + "\n") 33 | print("Failed to join " + sub + "due to the error :" + e) 34 | 35 | print("Done") 36 | -------------------------------------------------------------------------------- /reddit/samplesubs.txt: -------------------------------------------------------------------------------- 1 | BetterEveryLoop 2 | GooglePixel 3 | OpenAI -------------------------------------------------------------------------------- /repo/priv.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | author: @endormi 4 | 5 | Automated private repository creation 6 | 7 | """ 8 | 9 | from selenium import webdriver 10 | import time 11 | 12 | 13 | """ 14 | Install browser driver: 15 | https://selenium.dev/downloads/ 16 | """ 17 | 18 | browser = webdriver.Chrome(r'file/to/driver/if/needed/otherwise/remove/r') 19 | browser.get('https://github.com/login') 20 | browser.maximize_window() 21 | 22 | user = '' 23 | pw = '' 24 | repo = '' 25 | desc = '' 26 | 27 | username = browser.find_element_by_id('login_field') 28 | username.send_keys(user) 29 | password = browser.find_element_by_id('password') 30 | password.send_keys(pw) 31 | log_in = browser.find_element_by_class_name('btn-block') 32 | log_in.click() 33 | new_repo = browser.find_element_by_link_text('New') 34 | new_repo.click() 35 | repo_name = browser.find_element_by_id('repository_name') 36 | repo_name.send_keys(repo) 37 | repo_desc = browser.find_element_by_id('repository_description') 38 | repo_desc.send_keys(desc) 39 | priv_repo = browser.find_element_by_id('repository_visibility_private') 40 | priv_repo.click() 41 | init = browser.find_element_by_id('repository_auto_init') 42 | init.click() 43 | time.sleep(1) 44 | 45 | """ 46 | Additional for marketplace apps: 47 | app = browser.find_element_by_name('quick_install[your_name][number]') 48 | app.click() 49 | """ 50 | 51 | create_repo = browser.find_element_by_class_name('first-in-line') 52 | create_repo.click() 53 | -------------------------------------------------------------------------------- /repo/publ.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | author: @endormi 4 | 5 | Automated public repository creation 6 | 7 | """ 8 | 9 | from selenium import webdriver 10 | import time 11 | 12 | 13 | """ 14 | Install browser driver: 15 | https://selenium.dev/downloads/ 16 | """ 17 | 18 | browser = webdriver.Chrome(r'file/to/driver/if/needed/otherwise/remove/r') 19 | browser.get('https://github.com/login') 20 | browser.maximize_window() 21 | 22 | user = '' 23 | pw = '' 24 | repo = '' 25 | desc = '' 26 | 27 | username = browser.find_element_by_id('login_field') 28 | username.send_keys(user) 29 | password = browser.find_element_by_id('password') 30 | password.send_keys(pw) 31 | log_in = browser.find_element_by_class_name('btn-block') 32 | log_in.click() 33 | new_repo = browser.find_element_by_link_text('New') 34 | new_repo.click() 35 | repo_name = browser.find_element_by_id('repository_name') 36 | repo_name.send_keys(repo) 37 | repo_desc = browser.find_element_by_id('repository_description') 38 | repo_desc.send_keys(desc) 39 | init = browser.find_element_by_id('repository_auto_init') 40 | init.click() 41 | time.sleep(1) 42 | 43 | """ 44 | Additional for marketplace apps: 45 | app = browser.find_element_by_name('quick_install[your_name][number]') 46 | app.click() 47 | """ 48 | 49 | create_repo = browser.find_element_by_class_name('first-in-line') 50 | create_repo.click() 51 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | html-testRunner>=1.2.1 2 | keyboard>=0.13.5 3 | matplotlib>=3.1.1 4 | numpy>=1.16.4 5 | opencv-python>=4.2.0.34 6 | pandas>=0.25.1 7 | phue>=1.1 8 | playsound>=1.2.2 9 | PyAutoGUI>=0.9.47 10 | pyfiglet>=0.8.post1 11 | pywin32>=305 12 | requests>=2.22.0 13 | schedule>=0.6.0 14 | selenium>=3.141.0 15 | termcolor>=1.1.0 16 | tweepy>=4.6.0 17 | XlsxWriter>=1.2.7 18 | youtube-dl>=2020.6.16.1 19 | praw>=7.7.1 -------------------------------------------------------------------------------- /scheduler/scheduler.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | author: @endormi 4 | 5 | Automated job schedules 6 | 7 | """ 8 | 9 | import schedule 10 | import webbrowser 11 | import os 12 | import sys 13 | import ctypes 14 | import time 15 | from playsound import playsound 16 | 17 | 18 | def run(): 19 | print('Running scheduler...') 20 | 21 | 22 | def certain_show(): 23 | playsound('sound.wav') 24 | print('Show ... is on!') 25 | 26 | 27 | def open_email(): 28 | # If you need to login everytime, you can use my selenium-testing templates to figure it out 29 | print('Opening email..') 30 | webbrowser.open(your_email) 31 | 32 | 33 | def shutdown(): 34 | if sys.platform == 'win32': 35 | user32 = ctypes.WinDLL('user32') 36 | user32.ExitWindowsEx(0x00000008, 0x00000000) 37 | else: 38 | os.system('sudo shutdown now') 39 | 40 | 41 | # This is just a random time I added 42 | schedule.every().monday.at("20:00").do(certain_show) 43 | schedule.every().tuesday.at("20:00").do(certain_show) 44 | 45 | schedule.every(30).minutes.do(run) 46 | 47 | schedule.every().day.at("08:00").do(open_email) 48 | schedule.every().day.at("23:00").do(shutdown) 49 | 50 | """ 51 | schedule.every().minute.at(":30").do(job) 52 | schedule.every(5).to(10).minutes.do(job) 53 | schedule.every().hour.do(job) 54 | """ 55 | 56 | while True: 57 | schedule.run_pending() 58 | time.sleep(1) 59 | -------------------------------------------------------------------------------- /scheduler/sound.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/endormi/automation/52fd89b24e709555c154ec3025c9995a5401f6bb/scheduler/sound.wav -------------------------------------------------------------------------------- /selenium-testing/cross-browser.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | author: @endormi 4 | 5 | Automated cross browser testing 6 | Even if some of the browsers do not work, running this code works 7 | 8 | """ 9 | 10 | from selenium import webdriver 11 | import pyautogui 12 | import time 13 | 14 | 15 | web_browser = {} 16 | 17 | 18 | def test_browsers(wd): 19 | try: 20 | """ 21 | Include all of the browsers that have a official webdriver according to the selenium website 22 | 23 | Look at the https://selenium.dev/downloads/ docs on how to set all of them up 24 | """ 25 | web_browser = { 26 | 'Firefox': webdriver.Firefox, 27 | 'Edge': webdriver.Edge, 28 | 'Ie': webdriver.Ie, 29 | 'Safari': webdriver.Safari, 30 | 'Opera': webdriver.Opera, 31 | } 32 | 33 | if wd == 'Chrome': 34 | browser = webdriver.Chrome(r'file/to/driver/if/needed/otherwise/remove/r') 35 | else: 36 | browser = web_browser.get(wd)() 37 | 38 | browser.maximize_window() 39 | return browser 40 | 41 | except Exception as msg: 42 | print(msg) 43 | 44 | 45 | def test_python_search(wd): 46 | browser = test_browsers(wd) 47 | browser.get('https://www.python.org/') 48 | time.sleep(1) 49 | browser.find_element_by_id('id-search-field').send_keys('style guide') 50 | time.sleep(1) 51 | pyautogui.typewrite(['enter']) 52 | time.sleep(2) 53 | browser.find_element_by_xpath('/html/body/div/div[3]/div/section/form/ul/li[1]/h3/a').click() 54 | time.sleep(1) 55 | browser.find_element_by_xpath('/html/body/div/div[3]/div/section/article/p[2]/i/a[1]').click() 56 | time.sleep(1) 57 | print(browser.current_url) 58 | 59 | 60 | if __name__ == "__main__": 61 | browsers = ['Chrome', 'Firefox', 'Edge', 'Ie', 'Safari', 'Opera'] 62 | for list in browsers: 63 | test_python_search(list) 64 | -------------------------------------------------------------------------------- /selenium-testing/login-form.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | author: @endormi 4 | 5 | Automated login form testing and generate report 6 | 7 | """ 8 | 9 | from selenium import webdriver 10 | import unittest 11 | import HtmlTestRunner 12 | import time 13 | 14 | 15 | """ 16 | Install browser driver: 17 | https://selenium.dev/downloads/ 18 | """ 19 | 20 | 21 | class login_form_test(unittest.TestCase): 22 | 23 | @classmethod 24 | def setUpClass(cls): 25 | cls.browser = webdriver.Chrome(r'file/to/driver/if/needed/otherwise/remove/r') 26 | cls.browser.maximize_window() 27 | 28 | def test_login_github(self): 29 | time.sleep(1) 30 | self.browser.get('https://github.com/login') 31 | self.browser.find_element_by_id('login_field').send_keys('username') 32 | self.browser.find_element_by_id('password').send_keys('password') 33 | self.browser.find_element_by_class_name('btn-block').click() 34 | 35 | def test_login_so(self): 36 | time.sleep(1) 37 | self.browser.get('https://stackoverflow.com/') 38 | self.browser.find_element_by_link_text('Log in').click() 39 | self.browser.find_element_by_id('email').send_keys('username') 40 | self.browser.find_element_by_id('password').send_keys('password') 41 | self.browser.find_element_by_id('submit-button').click() 42 | 43 | def test_login_twitter(self): 44 | time.sleep(1) 45 | self.browser.get('https://twitter.com/login') 46 | self.browser.find_element_by_class_name('js-username-field').send_keys('username') 47 | self.browser.find_element_by_class_name('js-password-field').send_keys('password') 48 | self.browser.find_element_by_class_name('EdgeButtom--medium').click() 49 | 50 | @classmethod 51 | def tearDownClass(cls): 52 | time.sleep(5) 53 | cls.browser.close() 54 | 55 | 56 | if __name__ == '__main__': 57 | unittest.main(testRunner=HtmlTestRunner.HTMLTestRunner(output='output/path')) 58 | -------------------------------------------------------------------------------- /selenium-testing/search.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | author: @endormi 4 | 5 | Automated search testing 6 | Generates report and displays current url 7 | 8 | """ 9 | 10 | import unittest 11 | from selenium import webdriver 12 | import time 13 | import pyautogui 14 | import HtmlTestRunner 15 | 16 | 17 | """ 18 | Install browser driver: 19 | https://selenium.dev/downloads/ 20 | """ 21 | 22 | 23 | class ChromeSearch(unittest.TestCase): 24 | 25 | @classmethod 26 | def setUpClass(cls): 27 | cls.browser = webdriver.Chrome(r'file/to/driver/if/needed/otherwise/remove/r') 28 | cls.browser.maximize_window() 29 | 30 | def test_search_github(self): 31 | self.browser.get("https://www.github.com") 32 | time.sleep(1) 33 | self.browser.find_element_by_class_name('form-control').send_keys('Python') 34 | time.sleep(1) 35 | pyautogui.typewrite(["enter"]) 36 | print(self.browser.current_url) 37 | 38 | def test_search_so(self): 39 | self.browser.get("https://stackoverflow.com/") 40 | time.sleep(1) 41 | self.browser.find_element_by_class_name('js-search-field').send_keys('Python') 42 | pyautogui.typewrite(["enter"]) 43 | time.sleep(1) 44 | print(self.browser.current_url) 45 | 46 | def test_search_amazon(self): 47 | self.browser.get("https://amazon.com/") 48 | time.sleep(1) 49 | self.browser.find_element_by_id('twotabsearchtextbox').send_keys('Python') 50 | pyautogui.typewrite(["enter"]) 51 | time.sleep(1) 52 | print(self.browser.current_url) 53 | 54 | @classmethod 55 | def tearDownClass(cls): 56 | time.sleep(5) 57 | cls.browser.close() 58 | 59 | 60 | if __name__ == "__main__": 61 | unittest.main(testRunner=HtmlTestRunner.HTMLTestRunner(output='output/path')) 62 | -------------------------------------------------------------------------------- /selenium-testing/sign-up-so.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | author: @endormi 4 | 5 | Automated stack overflow sign up form testing and generate report 6 | 7 | """ 8 | 9 | from selenium import webdriver 10 | import unittest 11 | import HtmlTestRunner 12 | import time 13 | 14 | 15 | """ 16 | Install browser driver: 17 | https://selenium.dev/downloads/ 18 | """ 19 | 20 | 21 | class login_form_test(unittest.TestCase): 22 | 23 | @classmethod 24 | def setUpClass(cls): 25 | cls.browser = webdriver.Chrome(r'file/to/driver/if/needed/otherwise/remove/r') 26 | cls.browser.maximize_window() 27 | 28 | def test_signup_so(self): 29 | time.sleep(1) 30 | self.browser.get('https://stackoverflow.com/') 31 | self.browser.find_element_by_link_text('Sign up').click() 32 | self.browser.find_element_by_id('display-name').send_keys('username') 33 | self.browser.find_element_by_id('email').send_keys('example@gmail.com') 34 | self.browser.find_element_by_id('password').send_keys('password') 35 | self.browser.find_element_by_id('opt-in').click() 36 | time.sleep(1) 37 | self.browser.find_element_by_id('submit-button').click() 38 | 39 | def test_signup_with_gmail_auth(self): 40 | time.sleep(1) 41 | self.browser.get('https://stackoverflow.com/') 42 | self.browser.find_element_by_link_text('Sign up').click() 43 | self.browser.find_element_by_xpath('/html/body/div[4]/div[2]/div/div[2]/div[2]/button[1]').click() 44 | time.sleep(2) 45 | self.browser.find_element_by_xpath('//*[@id="identifierId"]').send_keys('username') 46 | time.sleep(1) 47 | self.browser.find_element_by_xpath('//*[@id="identifierNext"]/span/span').click() 48 | time.sleep(1) 49 | self.browser.find_element_by_xpath('//*[@id="password"]/div[1]/div/div[1]/input').send_keys('password') 50 | time.sleep(1) 51 | self.browser.find_element_by_xpath('//*[@id="passwordNext"]/span/span').click() 52 | 53 | def test_signup_with_github_auth(self): 54 | time.sleep(1) 55 | self.browser.get('https://stackoverflow.com/') 56 | self.browser.find_element_by_link_text('Sign up').click() 57 | self.browser.find_element_by_xpath('/html/body/div[4]/div[2]/div/div[2]/div[2]/button[2]').click() 58 | self.browser.find_element_by_id('login_field').send_keys('username') 59 | self.browser.find_element_by_id('password').send_keys('password') 60 | self.browser.find_element_by_class_name('btn-block').click() 61 | 62 | @classmethod 63 | def tearDownClass(cls): 64 | time.sleep(5) 65 | cls.browser.close() 66 | 67 | 68 | if __name__ == '__main__': 69 | unittest.main(testRunner=HtmlTestRunner.HTMLTestRunner(output='output/path')) 70 | -------------------------------------------------------------------------------- /send-email/email.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | author: @endormi 4 | 5 | Automated email sender (uses gmail's port) 6 | subject, content and image attachments 7 | 8 | """ 9 | 10 | import smtplib 11 | from email.message import EmailMessage 12 | # import imghdr 13 | 14 | 15 | PORT = 587 16 | 17 | Your_Email = 'example@company.com' 18 | 19 | """ 20 | Get your password from: 21 | https://myaccount.google.com/apppasswords 22 | """ 23 | Your_Password = 'password' 24 | 25 | receiver = input("Person receiving the email: ") 26 | subject = input("Message subject: ") 27 | content = input("Message content: ") 28 | 29 | with smtplib.SMTP('smtp.gmail.com', PORT) as send__mail: 30 | send__mail.starttls() 31 | send__mail.login(Your_Email, Your_Password) 32 | 33 | message = EmailMessage() 34 | message['From'] = Your_Email 35 | message['To'] = receiver 36 | message['subject'] = subject 37 | message.set_content(content) 38 | 39 | """ Uncomment if you wish to send image attachments 40 | 41 | with open('image/file', 'rb') as image_attachment: 42 | img = image_attachment.read() 43 | img_type = imghdr.what(image_attachment.name) 44 | message.add_attachment(img, maintype='image', subtype=img_type) 45 | """ 46 | 47 | send__mail.send_message(message) 48 | 49 | print("Email sent!") 50 | -------------------------------------------------------------------------------- /tweeter/README.md: -------------------------------------------------------------------------------- 1 | # Guide 2 | 3 | 1. Go to this site: [Twitter API](https://developer.twitter.com/en/docs/twitter-api). 4 | 2. Create a bot following the tutorial. 5 | 3. Copy the Consumer Keys (API Key and Secret) and Authentication Tokens (Access Token and Secret). 6 | 4. Consumer Keys and Authentication Tokens will now be turn into environment variables. 7 | 5. Name the environment variables like so with the values: 8 | 9 | ``` 10 | TWITTER_API_KEY 11 | TWITTER_API_SECRET_KEY 12 | TWITTER_ACCESS_TOKEN 13 | TWITTER_ACCESS_TOKEN_SECRET 14 | ``` 15 | -------------------------------------------------------------------------------- /tweeter/tweet.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | author: @endormi 4 | 5 | Automated tweeter 6 | 7 | """ 8 | 9 | import tweepy 10 | import os 11 | 12 | 13 | auth = tweepy.OAuthHandler(os.getenv("TWITTER_API_KEY"), os.getenv("TWITTER_API_SECRET_KEY")) 14 | auth.set_access_token(os.getenv("TWITTER_ACCESS_TOKEN"), os.getenv("TWITTER_ACCESS_TOKEN_SECRET")) 15 | 16 | api = tweepy.API(auth) 17 | tweet = str(input("Tweet: \n")) 18 | 19 | try: 20 | api.update_status(tweet) 21 | print("Tweeted!") 22 | except tweepy.TweepError as error: 23 | if error.api_code == 187: 24 | print('Tweet already exists.') 25 | else: 26 | raise error 27 | -------------------------------------------------------------------------------- /whatsapp/msg.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | author: @endormi 4 | 5 | Automated text sender for Whatsapp 6 | 7 | """ 8 | 9 | from selenium import webdriver 10 | import time 11 | 12 | 13 | """ 14 | Install browser driver: 15 | https://www.seleniumhq.org/download/ 16 | """ 17 | 18 | name = input("Name: ") 19 | msg = input("Message: ") 20 | amount_of_times = int(input("How many times do you want to send the message? (use numbers) ")) 21 | 22 | browser = webdriver.Chrome(r'file/to/chromedriver/if/needed/otherwise/remove/r') 23 | browser.get('https://web.whatsapp.com') 24 | 25 | time.sleep(1) 26 | 27 | user = browser.find_element_by_xpath('//span[@title = "{}"]'.format(name)) 28 | user.click() 29 | send_msg = browser.find_element_by_class_name('_13mgZ') 30 | 31 | for x in range(amount_of_times): 32 | send_msg.send_keys(msg) 33 | btn = browser.find_element_by_class_name('_3M-N-') 34 | btn.click() 35 | -------------------------------------------------------------------------------- /youtube/dl.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | author: @endormi 4 | 5 | Automated YouTube audio downloader 6 | 7 | """ 8 | 9 | import youtube_dl 10 | 11 | 12 | url = input("Please enter the URL for the video you wish to download: ") 13 | ytdl = youtube_dl.YoutubeDL().extract_info(url=url, download=False) 14 | 15 | file = f"{ytdl['title']}.mp3" 16 | 17 | options = { 18 | 'format': 'bestaudio/best', 19 | 'outtmpl': file, 20 | 'postprocessors': [{ 21 | 'key': 'FFmpegExtractAudio', 22 | 'preferredcodec': 'mp3', 23 | 'preferredquality': '192', 24 | }], 25 | } 26 | 27 | with youtube_dl.YoutubeDL(options) as ydl: 28 | ydl.download([ytdl['webpage_url']]) 29 | --------------------------------------------------------------------------------