Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Packaging and Some Bug Fixes #1

Merged
merged 2 commits into from
Dec 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions .github/workflows/build_release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
name: Buid Windows and Linux Executables

on:
push:
branches:
- main

jobs:
Windows Build:
runs-on: windows-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.10.6
- name: Install dependencies
run: pip install -r requirements.txt

- name: Build Windows Executable
run: pyinstaller windows.spec

- name: Generate Pre Release
uses: marvinpinto/action-automatic-releases@latest
with:
repo_token: ${{ secrets.TOKEN }}
prerelease: true
files: |
dist/MR.DM.exe

Linux Build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.10.6
- name: Install dependencies
run: pip install -r requirements.txt

- name: Build Linux Executable
run: pyinstaller linux.spec

- name: Generate Pre Release
uses: marvinpinto/action-automatic-releases@latest
with:
repo_token: ${{ secrets.TOKEN }}
prerelease: true
files: |
dist/MR.DM

11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ MR.DM will take care of the rest. It will send the message to all the accounts y
MR.DM is a desktop application. It is available for Windows, Linux, and Mac. You can download the latest executable version from [github releases](https://github.com/oxlac/mr.dm/releases). Or you can build it from the source
with the following instructions.

> [!WARNING]
> You must disable your antivirus before running the executable on windows. For more information, please read [this](https://github.com/pyinstaller/pyinstaller/issues?q=label%3Aantivirus-false-positives+is%3Aclosed)


### Installation

Expand Down Expand Up @@ -150,12 +153,12 @@ You can view the status of the messages being sent on the progress screen. MR.DM

## Roadmap

- [ ] Add Accounts that have posted with a specific hashtag. (In Progress)
- [ ] Add Accounts that have interacted with certain hashtags. (In Progress)
- [ ] Add Accounts that have posted with a specific hashtag.
- [ ] Add Accounts that have interacted with certain hashtags.
- [ ] Add an account from their Instagram profile link.
- [ ] Add accounts that have interacted with a specific post.
- [ ] Ability to send pictures and videos. (Need Contributors)
- [ ] Cleaning up Documentation and Adding Sphinx Autodoc. ( Under Progress)
- [ ] Ability to send pictures and videos.
- [ ] Cleaning up Documentation and Adding Sphinx Autodoc. ( Under Progress by admins)

See the [open issues](https://github.com/oxlac/mr.dm/issues) for a full list of proposed features (and known issues). If you have any other ideas, please open an issue and let us know.

Expand Down
4 changes: 1 addition & 3 deletions backend/session.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from typing import Self

from instaloader import Instaloader, Profile
from selenium import webdriver

Expand All @@ -16,7 +14,7 @@ class Session:
driver: webdriver.Chrome = None
username: str = None

def __new__(cls) -> Self:
def __new__(cls):
if cls._instance is None:
cls._instance = super(Session, cls).__new__(cls)
cls._instance.loader = Instaloader()
Expand Down
27 changes: 24 additions & 3 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,31 @@
from kivy.uix.screenmanager import ScreenManager
from kivymd.app import MDApp


from backend import DatabaseManager, Session
from ui.welcomescreen import WelcomeScreen
import sys
import os


# Define the path for the icon
if getattr(sys, "frozen", False) and hasattr(sys, "_MEIPASS"):
# Running as a bundled executable (PyInstaller)
ICON = os.path.abspath(
os.path.join(os.path.dirname(__file__), "ui/assets/icon.png")
)

else:
# Inside a normal Python environment"
ICON = "ui/assets/icon.png"


class MyApp(MDApp):
"""The main App Class

:param MDApp: KivyMD App Class
:type MDApp: class `MDApp` from `kivymd.app` module
"""
"""

backend_sess = Session()
"""
Backend Session
Expand All @@ -24,7 +38,7 @@ class MyApp(MDApp):
Title of the application
"""

icon = "ui/assets/icon.png"
icon = ICON
"""
Icon of the application
"""
Expand All @@ -44,6 +58,13 @@ def build(self):
# Create Database
inspector.create_inspector(Window, sm)
DatabaseManager().create_tables()
# dismiss the splash screen
try:
import pyi_splash

pyi_splash.close()
except Exception:
pass
return sm


Expand Down
6 changes: 6 additions & 0 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
instaloader==4.10.2
Kivy==2.2.1
selenium==4.16.0
plyer==2.1.0
kivymd @ git+https://github.com/kivymd/KivyMD.git@master#egg=kivymd
pyinstaller==5.6.2
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ instaloader==4.10.2
Kivy==2.2.1
selenium==4.16.0
plyer==2.1.0
-e git+https://github.com/kivymd/KivyMD.git@master#egg=kivymd
kivymd @ git+https://github.com/kivymd/KivyMD.git@master#egg=kivymd
21 changes: 18 additions & 3 deletions ui/accountselectscreen/accountselectscreen.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
ManualDialog,
)
from ui.messagescreen import MessageScreen
from kivy.clock import Clock


class AccountSelectScreen(Screen):
Expand Down Expand Up @@ -66,7 +67,17 @@ class AccountSelectScreen(Screen):
"""

def __init__(self, **kw):
Builder.load_file("ui/accountselectscreen/accountselectscreen.kv")
if getattr(sys, "frozen", False) and hasattr(sys, "_MEIPASS"):
# Running as a bundled executable (PyInstaller)
Builder.load_file(
os.path.abspath(
os.path.join(os.path.dirname(__file__), "accountselectscreen.kv")
)
)
else:
# Inside a normal Python environment
Builder.load_file("ui/accountselectscreen/accountselectscreen.kv")

super().__init__(**kw)
# add the MDDataTable to the layout
self.ids.tablecontainer.add_widget(self.create_datatable(), 1)
Expand Down Expand Up @@ -104,10 +115,8 @@ def edit_selection(self, *args):
"""
self.selection = self.table.get_row_checks()
if len(self.selection) > 0:
self.ids.next.disabled = False
self.ids.Delete.disabled = False
else:
self.ids.next.disabled = True
self.ids.Delete.disabled = True

def verify_delete(self):
Expand All @@ -129,11 +138,17 @@ def delete_selected(self, widget):
"""
Removes the selected accounts from the list
"""

def deselect_rows(*args):
self.table.table_data.select_all("normal")

widget.parent.parent.parent.parent.dismiss()
for selected in self.selection:
for stuff in self.data:
if stuff[1] == selected[1]:
self.data.remove(stuff)
# remove the check from the table
Clock.schedule_once(deselect_rows)
self._update_table()

def open_filepicker(self):
Expand Down
Binary file added ui/assets/Splash Screen.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added ui/assets/icon.ico
Binary file not shown.
1 change: 1 addition & 0 deletions ui/components/confirmmessagedialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ class MessageConfirmDialog(MDDialog):

def __init__(self, callback, **kwargs):
self.callback = callback
self.auto_dismiss = False
self.content_cls = MessageConfirmDialogContent()
self.ok_button = MDRaisedButton(text="Send Messages")
self.cancel_button = MDFlatButton(text="Cancel")
Expand Down
83 changes: 16 additions & 67 deletions ui/messagescreen/messagescreen.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from time import sleep
import os
import sys
from typing import Any

from kivy.clock import mainthread
Expand All @@ -8,7 +9,6 @@
from kivymd.uix.button import MDFlatButton
from kivymd.uix.dialog import MDDialog
from selenium import webdriver
from selenium.webdriver.common.keys import Keys

from ui.components import MessageMenu
from ui.components.message_components import LinkMessage, PostMessage, TextMessage
Expand Down Expand Up @@ -39,7 +39,16 @@ class MessageScreen(Screen):
"""

def __init__(self, data, *args: Any, **kwds: Any) -> Any:
Builder.load_file("ui/messagescreen/messagescreen.kv")
if getattr(sys, "frozen", False) and hasattr(sys, "_MEIPASS"):
# Running as a bundled executable (PyInstaller)
Builder.load_file(
os.path.abspath(
os.path.join(os.path.dirname(__file__), "messagescreen.kv")
)
)
else:
# Inside a normal Python environment
Builder.load_file("ui/messagescreen/messagescreen.kv")
self.data = data
return super().__init__(*args, **kwds)

Expand Down Expand Up @@ -109,6 +118,7 @@ def confirm_send(self):
)
self.confirm_send_dialogue.open()

@mainthread
def navigate_to_progress(self, *args):
"""
Navigates to the progress screen
Expand All @@ -125,68 +135,7 @@ def navigate_to_progress(self, *args):
}
)
self.manager.add_widget(
ProgressScreen(
name="progress_screen", messages=self.messages, accounts=self.data
)
ProgressScreen(name="progress", messages=self.messages, accounts=self.data)
)
self.manager.current = "progress_screen"

def message_loop(self):
"""
This is the main function that deals with sending messages
to each user in the list
"""
for user in self.data:
# compose a new message for the user
self.find_element(
"/html/body/div[2]/div/div/div[2]/div/div/div[1]/div[1]/div[2]/section/div/div/div/div[1]/div/div[1]/div/div[1]/div[2]/div/div"
).click()
sleep(3)
actions = webdriver.ActionChains(self.session.driver)
actions.send_keys(user[1])
actions.perform()
sleep(2)
actions = webdriver.ActionChains(self.session.driver)
actions.send_keys(Keys.TAB)
actions.send_keys(Keys.ENTER)
actions.perform()
sleep(2)
actions = webdriver.ActionChains(self.session.driver)
actions.send_keys(Keys.TAB)
actions.send_keys(Keys.ENTER)
actions.perform()
sleep(3)
# start typing the message
actions = webdriver.ActionChains(self.session.driver)
actions.send_keys(self.reel_link)
actions.send_keys(Keys.ENTER)
actions.perform()
sleep(2)
# send the message
actions = webdriver.ActionChains(self.session.driver)
actions.send_keys(self.message)
actions.send_keys(Keys.ENTER)
actions.perform()
sleep(10)
# add the user to the processed list
self.processed_accounts.append(user[0])
# update the progress bar
self.update_progress()

# finish the process
self.finish()

@mainthread
def update_progress(self):
self.ids.progress.value = len(self.processed_accounts)
self.ids.progress_label.text = (
str(len(self.processed_accounts)) + "/" + str(len(self.data))
)

def finish(self):
self.ids.progress_label.text = "Finished"
self.ids.progress.label.bg_color = (0, 1, 0, 1)
# save the processed accounts to a file
with open("processed_accounts.txt", "w") as f:
for account in self.processed_accounts:
f.write(account + "\n")
self.manager.current = "progress"
self.manager.remove_widget(self)
Loading