Skip to content

Commit

Permalink
Fix: log path invalid; update README
Browse files Browse the repository at this point in the history
  • Loading branch information
akiakise committed Feb 5, 2023
1 parent 0bdad24 commit ea90cad
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 83 deletions.
63 changes: 12 additions & 51 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,65 +2,26 @@

File Association Enhancement.

I have three video players, `MPC-BE` for anime, `PotPlayer` and `mpv` for the others.
However, in Windows, for specify video type such as `.mkv`, you can only associate it with **one** application.
A python application supports rule-check before opening videos. You can associate different players for different rule.

FAE is working for this situation.
For example:

FAE will check the rules configured before opening a file.
The rule is something like `using this application to open videos under that folder`.
1. rule A -> folder `testA` -> opened by player `MPV`;
2. rule B -> folder `testB` -> opened by player `MPC-BE`;
3. rule C -> folder `testC` -> opened by player `PotPlayer`.

## Usage

FAE is under developing, so there isn't a release version, you need to build from source.
1. Download the latest application
on [https://github.com/akiakise/fae/releases](https://github.com/akiakise/fae/releases)

### 1. Create your own configuration file.
2. Doubleclick `fae.exe` and add your own rules:
![config](resources/1-config.png)

Make a copy of [fae.sample.json](fae.sample.json), rename to `fae.json`, change the config items:
3. Always open video files with fae.exe:
![association](resources/2-association.png)

```json
{
"rules": [
{
"index": 1,
"app": "app 1",
"folder": "folder 1"
},
{
"index": 2,
"app": "app 2",
"folder": "folder 2"
}
],
"fallback": "fallback",
"aliases": {
"potplayer": "path to potplayer.exe",
"mpc-be": "patch to mpc-be.exe"
}
}
```

### 2. Build an executable file

```shell
pip3 install -r requirements.txt
pyinstaller.exe --onedir --noconsole --noconfirm fae.py
pyinstaller.exe --onedir --noconsole --noconfirm judge.py
```

### 3. Configure

Execute configure.exe:

![configure](resources/configure.png)

### 4. Configuration file

Move the new configuration file in step 1 into `%APPDATA%/fae`.

### 4. Open video files with judge.exe

![default app](resources/default_app.png)
4. Doubleclick the file you want to open, then the rule will determine whether player to use.

## LICENSE

Expand Down
27 changes: 17 additions & 10 deletions config/__init__.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,30 @@
import json
import os
from typing import List, AnyStr, Dict
from typing import List, AnyStr

from PyQt5.QtWidgets import QMessageBox

DEFAULT_ENCODING = 'utf-8'
PROJECT_NAME = 'fae'
APPDATA = 'APPDATA'

PATH_PROJECT = os.path.abspath(os.getcwd())
PATH_LOG_DIR = os.path.join(PATH_PROJECT, 'log')
PATH_CONFIG = os.path.join(PATH_PROJECT, f'{PROJECT_NAME}.json')

MB = 1024 * 1024
MINUTE = 60 * 1000
DATE_FORMAT = '%Y-%m-%d'
DATE_TIME_FORMAT = '%Y-%m-%d %H:%M:%S'


def get_project_path():
os.chdir(os.path.join(os.path.dirname(__file__), '../'))
return os.path.abspath(os.getcwd())


def get_config_file():
return os.path.join(get_project_path(), f'{PROJECT_NAME}.json')


def get_log_file():
return os.path.join(get_project_path(), f'{PROJECT_NAME}.log')


class Rule:
def __init__(self, index, folder, app):
self.index = index
Expand Down Expand Up @@ -66,8 +73,8 @@ def parse(d: dict):


def load_config():
if os.path.exists(PATH_CONFIG):
with open(PATH_CONFIG, mode='r', encoding=DEFAULT_ENCODING) as f:
if os.path.exists(get_config_file()):
with open(get_config_file(), mode='r', encoding=DEFAULT_ENCODING) as f:
try:
config = Config.parse(json.load(f))
config.rules.sort(key=lambda c: c.index, reverse=False)
Expand All @@ -83,5 +90,5 @@ def load_config():

def write_config(config: Config):
config.apps = list(set(config.apps))
with open(PATH_CONFIG, mode='w', encoding=DEFAULT_ENCODING) as f:
with open(get_config_file(), mode='w', encoding=DEFAULT_ENCODING) as f:
f.write(json.dumps(config.to_dict(), default=lambda o: o.__dict__, indent=2))
18 changes: 14 additions & 4 deletions fae.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@
from PyQt5.QtGui import QFont, QIcon
from PyQt5.QtWidgets import QApplication, QMessageBox

from config import load_config
from log import logger
from config import load_config, get_config_file
from log import get_logger
from ui.wrapper.main_wrapper import MainWrapper
from util import get_extension
import win32api, win32con

if __name__ == '__main__':
logger = get_logger()
argv_length = len(sys.argv)
if argv_length == 1:
# If there is only one argument, start for configure
Expand Down Expand Up @@ -53,20 +54,29 @@ def excepthook(_type, _value, _traceback):
''')
file_path = os.path.abspath(sys.argv[1])
extension = get_extension(file_path)
logger.info(f'config file {get_config_file()}')
logger.info(f'current file: {__file__}')
logger.info(f'executable: {sys.executable}')
config = load_config()
# Check if any rule matches
for rule in config.rules:
if rule.folder in file_path:
try:
subprocess.run(f'{rule.app} "{file_path}"')
logger.info(f'rule matched, rule: {rule}')
command = f'{rule.app} "{file_path}"'
logger.info(f'run command: {command}')
subprocess.run(command)
sys.exit(0)
except Exception as e:
win32api.MessageBoxEx(0, 'Failed to open file, navigate to logs for more details', 'Critical',
win32con.MB_OK)
logger.error('Failed to open file', e)
sys.exit(1)
# Run if no-one rule matches
subprocess.run(f'{config.fallback} "{file_path}"')
logger.info(f'no rule matched, use fallback player: {config.fallback}')
command = f'{config.fallback} "{file_path}"'
logger.info(f'run command: {command}')
subprocess.run(command)
sys.exit(0)
else:
# If there is more than two arguments, warn and exit
Expand Down
2 changes: 1 addition & 1 deletion log/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
from log.log_impl import logger
from log.log_impl import get_logger
30 changes: 14 additions & 16 deletions log/log_impl.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,22 @@
import os
from logging import Formatter, StreamHandler, getLogger, DEBUG
from logging.handlers import RotatingFileHandler
from sys import stdout

from config import MB, PROJECT_NAME, PATH_LOG_DIR, DEFAULT_ENCODING
from config import MB, PROJECT_NAME, DEFAULT_ENCODING, get_log_file

__log_file = os.path.join(PATH_LOG_DIR, f'{PROJECT_NAME.lower()}.log')
if not os.path.exists(PATH_LOG_DIR):
os.makedirs(PATH_LOG_DIR)

# File logger
__file_handler = RotatingFileHandler(__log_file, maxBytes=10 * MB, backupCount=5, encoding=DEFAULT_ENCODING)
__fmt = '%(asctime)s - %(threadName)s(%(thread)d) - %(filename)s:%(lineno)s - %(levelname)s - %(message)s'
__formatter = Formatter(__fmt)
__file_handler.setFormatter(__formatter)
# Console logger
__console_handler = StreamHandler(stdout)
def get_logger():
__file_handler = RotatingFileHandler(get_log_file(), maxBytes=10 * MB, backupCount=5, encoding=DEFAULT_ENCODING)
__fmt = '%(asctime)s - %(threadName)s(%(thread)d) - %(filename)s:%(lineno)s - %(levelname)s - %(message)s'
__formatter = Formatter(__fmt)
__file_handler.setFormatter(__formatter)
# Console logger
__console_handler = StreamHandler(stdout)

# Final logger
logger = getLogger(f'{PROJECT_NAME}Logger')
logger.addHandler(__file_handler)
logger.addHandler(__console_handler)
logger.setLevel(DEBUG)
# Final logger
logger = getLogger(f'{PROJECT_NAME}Logger')
logger.addHandler(__file_handler)
logger.addHandler(__console_handler)
logger.setLevel(DEBUG)
return logger
Binary file added resources/1-config.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 resources/2-association.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion ui/wrapper/dialog_rule_add_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def draw_ui(self):
for app in config.apps:
if app != self.app:
self.combo_box.addItem(app)
if self.app:
if self.app and self.app != self.combo_box_item_other:
self.combo_box.addItem(self.app)
self.combo_box.setCurrentText(self.app)
self.combo_box.addItem(self.combo_box_item_other)
Expand Down

0 comments on commit ea90cad

Please sign in to comment.